From 9b13d1f8bbde73c3a8af325e6a5c40fa5df7915b Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 1 Sep 2021 08:43:58 +0000 Subject: [PATCH 001/491] [stdlib] Fix cc mismatch violation on swift_isClassType _isClassType is mainly called by compiler-generated code, but it's also called by stdlib. The call-site of stdlib used @_silgen_name to link the function, so it's called through swiftcc. However its cc is defined as C-cc, so caller and callee used different cc. This patch adds C-compatible decl of swift_isClassType in shims so that it can be called by stdlib with C-cc. This change doesn't break ABI because `_isClassType` in stdlib was defined as internal API. --- stdlib/public/SwiftShims/RuntimeShims.h | 7 +++++++ stdlib/public/core/ReflectionMirror.swift | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/stdlib/public/SwiftShims/RuntimeShims.h b/stdlib/public/SwiftShims/RuntimeShims.h index b5ffb04c81958..c133adae411a2 100644 --- a/stdlib/public/SwiftShims/RuntimeShims.h +++ b/stdlib/public/SwiftShims/RuntimeShims.h @@ -20,6 +20,7 @@ #include "SwiftStddef.h" #include "SwiftStdint.h" +#include "SwiftStdbool.h" #include "Visibility.h" #ifdef __cplusplus @@ -61,6 +62,12 @@ int _swift_stdlib_putc_stderr(int C); SWIFT_RUNTIME_STDLIB_API __swift_size_t _swift_stdlib_getHardwareConcurrency(void); +#ifdef __swift__ +/// Called by ReflectionMirror in stdlib through C-calling-convention +SWIFT_RUNTIME_STDLIB_API +__swift_bool swift_isClassType(const void *type); +#endif + /// Manually allocated memory is at least 16-byte aligned in Swift. /// /// When swift_slowAlloc is called with "default" alignment (alignMask == diff --git a/stdlib/public/core/ReflectionMirror.swift b/stdlib/public/core/ReflectionMirror.swift index 2f68b9078aa21..8631695d99e79 100644 --- a/stdlib/public/core/ReflectionMirror.swift +++ b/stdlib/public/core/ReflectionMirror.swift @@ -12,8 +12,11 @@ import SwiftShims -@_silgen_name("swift_isClassType") -internal func _isClassType(_: Any.Type) -> Bool +internal func _isClassType(_ type: Any.Type) -> Bool { + // a thick metatype is represented with a pointer metadata structure, + // so this unsafeBitCast is a safe operation here. + return swift_isClassType(unsafeBitCast(type, to: UnsafeRawPointer.self)) +} @_silgen_name("swift_getMetadataKind") internal func _metadataKind(_: Any.Type) -> UInt From d3f99373c9a3b623e686a378f72887e26f0bc68f Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 12 Nov 2021 15:24:08 +1000 Subject: [PATCH 002/491] [rebranch] Update uses of ErrorHandling.h functions llvm-project `ErrorHandling.h` was updated to remove std::string. This added a new `report_fatal_error` overload taking a `const Twine &`, removed the overload that took `const std::string &`, and updated `fatal_error_handler_t` to use `const char *` rather than `const std::string &`. Fix uses of these functions to take into account these updates. Note that without the `const std::string &` overload, passing a `std::string` into `report_fatal_error` now results in an ambiguous match between the `StringRef` and `Twine` overloads so we need to be explicit about one or the other. --- lib/AST/Availability.cpp | 5 ++- lib/DependencyScan/ScanDependencies.cpp | 4 +- lib/Driver/UnixToolChains.cpp | 8 ++-- lib/FrontendTool/FrontendTool.cpp | 21 +++++----- lib/FrontendTool/LoadedModuleTrace.cpp | 42 ++++++++----------- lib/Sema/TypeChecker.cpp | 4 +- .../sourcekitd/bin/XPC/Service/XPCService.cpp | 4 +- .../lib/API/sourcekitdAPI-Common.cpp | 4 +- 8 files changed, 42 insertions(+), 50 deletions(-) diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index d0f473432b3b3..6825b66bf6c77 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -506,6 +506,7 @@ ASTContext::getSwift5PlusAvailability(llvm::VersionTuple swiftVersion) { default: break; } } - llvm::report_fatal_error("Missing call to getSwiftXYAvailability for Swift " + - swiftVersion.getAsString()); + llvm::report_fatal_error( + Twine("Missing call to getSwiftXYAvailability for Swift ") + + swiftVersion.getAsString()); } diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index daffda1142a32..8b8076084d926 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -775,8 +775,8 @@ generateFullDependencyGraph(CompilerInstance &instance, module.first, {module.second, currentImportPathSet}); if (!moduleDepsQuery) { - std::string err = "Module Dependency Cache missing module" + module.first; - llvm::report_fatal_error(err); + llvm::report_fatal_error(Twine("Module Dependency Cache missing module") + + module.first); } auto moduleDeps = *moduleDepsQuery; diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index 9ef3943ccebe9..dc14e7782c79a 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -310,11 +310,11 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, } if (!linkFilePath.empty()) { - auto linkFile = linkFilePath.str(); - if (llvm::sys::fs::is_regular_file(linkFile)) { - Arguments.push_back(context.Args.MakeArgString(Twine("@") + linkFile)); + if (llvm::sys::fs::is_regular_file(linkFilePath)) { + Arguments.push_back( + context.Args.MakeArgString(Twine("@") + linkFilePath)); } else { - llvm::report_fatal_error(linkFile + " not found"); + llvm::report_fatal_error(Twine(linkFilePath) + " not found"); } } diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 560afb32d4c42..3287bb8669178 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -1844,15 +1844,15 @@ int swift::performFrontend(ArrayRef Args, // // Unfortunately it's not really safe to do anything else, since very // low-level operations in LLVM can trigger fatal errors. - auto diagnoseFatalError = [&PDC](const std::string &reason, bool shouldCrash){ - static const std::string *recursiveFatalError = nullptr; + auto diagnoseFatalError = [&PDC](const char *reason, bool shouldCrash) { + static const char *recursiveFatalError = nullptr; if (recursiveFatalError) { // Report the /original/ error through LLVM's default handler, not // whatever we encountered. llvm::remove_fatal_error_handler(); - llvm::report_fatal_error(*recursiveFatalError, shouldCrash); + llvm::report_fatal_error(recursiveFatalError, shouldCrash); } - recursiveFatalError = &reason; + recursiveFatalError = reason; SourceManager dummyMgr; @@ -1868,12 +1868,13 @@ int swift::performFrontend(ArrayRef Args, if (shouldCrash) abort(); }; - llvm::ScopedFatalErrorHandler handler([](void *rawCallback, - const std::string &reason, - bool shouldCrash) { - auto *callback = static_cast(rawCallback); - (*callback)(reason, shouldCrash); - }, &diagnoseFatalError); + llvm::ScopedFatalErrorHandler handler( + [](void *rawCallback, const char *reason, bool shouldCrash) { + auto *callback = + static_cast(rawCallback); + (*callback)(reason, shouldCrash); + }, + &diagnoseFatalError); std::unique_ptr Instance = std::make_unique(); diff --git a/lib/FrontendTool/LoadedModuleTrace.cpp b/lib/FrontendTool/LoadedModuleTrace.cpp index 0aee945082852..f82b4a77c2887 100644 --- a/lib/FrontendTool/LoadedModuleTrace.cpp +++ b/lib/FrontendTool/LoadedModuleTrace.cpp @@ -154,8 +154,8 @@ class ABIDependencyEvaluator { llvm::DenseSet visited; /// Helper function to handle invariant violations as crashes in debug mode. - void crashOnInvariantViolation( - llvm::function_ref f) const; + void + crashOnInvariantViolation(llvm::function_ref f) const; /// Computes the ABI exports for \p importedModule and adds them to /// \p module's ABI exports. @@ -223,13 +223,13 @@ class ABIDependencyEvaluator { // See [NOTE: Bailing-vs-crashing-in-trace-emission]. // TODO: Use PrettyStackTrace instead? void ABIDependencyEvaluator::crashOnInvariantViolation( - llvm::function_ref f) const { + llvm::function_ref f) const { #ifndef NDEBUG - std::string msg; - llvm::raw_string_ostream os(msg); + SmallVector msg; + llvm::raw_svector_ostream os(msg); os << "error: invariant violation: "; f(os); - llvm::report_fatal_error(os.str()); + llvm::report_fatal_error(msg); #endif } @@ -256,7 +256,7 @@ void ABIDependencyEvaluator::reexposeImportedABI(ModuleDecl *module, ModuleDecl *importedModule, bool includeImportedModule) { if (module == importedModule) { - crashOnInvariantViolation([&](llvm::raw_string_ostream &os) { + crashOnInvariantViolation([&](raw_ostream &os) { os << "module "; printModule(module, os); os << " imports itself!\n"; @@ -266,7 +266,7 @@ void ABIDependencyEvaluator::reexposeImportedABI(ModuleDecl *module, auto addToABIExportMap = [this](ModuleDecl *module, ModuleDecl *reexport) { if (module == reexport) { - crashOnInvariantViolation([&](llvm::raw_string_ostream &os) { + crashOnInvariantViolation([&](raw_ostream &os) { os << "expected module "; printModule(reexport, os); os << " to not re-export itself\n"; @@ -409,7 +409,7 @@ void ABIDependencyEvaluator::computeABIDependenciesForModule( if (moduleIter != searchStack.end()) { if (isFakeCycleThroughOverlay(moduleIter)) return; - crashOnInvariantViolation([&](llvm::raw_string_ostream &os) { + crashOnInvariantViolation([&](raw_ostream &os) { os << "unexpected cycle in import graph!\n"; for (auto m : searchStack) { printModule(m, os); @@ -557,21 +557,6 @@ static void computeSwiftModuleTraceInfo( const llvm::DenseMap &pathToModuleDecl, const DependencyTracker &depTracker, StringRef prebuiltCachePath, std::vector &traceInfo) { - - SmallString<256> buffer; - - std::string errMsg; - llvm::raw_string_ostream err(errMsg); - - // FIXME: Use PrettyStackTrace instead. - auto errorUnexpectedPath = - [&pathToModuleDecl](llvm::raw_string_ostream &errStream) { - errStream << "The module <-> path mapping we have is:\n"; - for (auto &m : pathToModuleDecl) - errStream << m.second->getName() << " <-> " << m.first << '\n'; - llvm::report_fatal_error(errStream.str()); - }; - using namespace llvm::sys; auto computeAdjacentInterfacePath = [](SmallVectorImpl &modPath) { @@ -580,6 +565,7 @@ static void computeSwiftModuleTraceInfo( path::replace_extension(modPath, swiftInterfaceExt); }; + SmallString<256> buffer; auto deps = depTracker.getDependencies(); SmallVector dependencies{deps.begin(), deps.end()}; auto incrDeps = depTracker.getIncrementalDependencyPaths(); @@ -643,8 +629,14 @@ static void computeSwiftModuleTraceInfo( // built a swiftmodule from that interface, so we should have that // filename available. if (isSwiftinterface) { + // FIXME: Use PrettyStackTrace instead. + SmallVector errMsg; + llvm::raw_svector_ostream err(errMsg); err << "Unexpected path for swiftinterface file:\n" << depPath << "\n"; - errorUnexpectedPath(err); + err << "The module <-> path mapping we have is:\n"; + for (auto &m : pathToModuleDecl) + err << m.second->getName() << " <-> " << m.first << '\n'; + llvm::report_fatal_error(errMsg); } // Skip cached modules in the prebuilt cache. We will add the corresponding diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index d8486d5c15801..ad8814e60cc14 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -480,9 +480,7 @@ void TypeChecker::checkForForbiddenPrefix(ASTContext &C, DeclBaseName Name) { StringRef Str = Name.getIdentifier().str(); if (Str.startswith(C.TypeCheckerOpts.DebugForbidTypecheckPrefix)) { - std::string Msg = "forbidden typecheck occurred: "; - Msg += Str; - llvm::report_fatal_error(Msg); + llvm::report_fatal_error(Twine("forbidden typecheck occurred: ") + Str); } } diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp index 335199362bd87..0e7bc87ce5ee1 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp @@ -343,11 +343,11 @@ static void sourcekitdServer_event_handler(xpc_connection_t peer) { }); } -static void fatal_error_handler(void *user_data, const std::string& reason, +static void fatal_error_handler(void *user_data, const char *reason, bool gen_crash_diag) { // Write the result out to stderr avoiding errs() because raw_ostreams can // call report_fatal_error. - fprintf(stderr, "SOURCEKITD SERVER FATAL ERROR: %s\n", reason.c_str()); + fprintf(stderr, "SOURCEKITD SERVER FATAL ERROR: %s\n", reason); if (gen_crash_diag) ::abort(); } diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp index f91529214e775..4ea0728fbcab0 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp @@ -189,12 +189,12 @@ void sourcekitd::printResponse(sourcekitd_response_t Resp, raw_ostream &OS) { printVariant(sourcekitd_response_get_value(Resp), OS); } -static void fatal_error_handler(void *user_data, const std::string& reason, +static void fatal_error_handler(void *user_data, const char *reason, bool gen_crash_diag) { // Write the result out to stderr avoiding errs() because raw_ostreams can // call report_fatal_error. // FIXME: Put the error message in the crash report. - fprintf(stderr, "SOURCEKITD FATAL ERROR: %s\n", reason.c_str()); + fprintf(stderr, "SOURCEKITD FATAL ERROR: %s\n", reason); ::abort(); } From 5b305b9f9ddca600d1927d460265000d1e776b98 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 12 Nov 2021 19:35:35 +1000 Subject: [PATCH 003/491] [rebranch] Rename various functions to match new names in LLVM llvm-project 601102d282d5e9a1429fea52ee17303aec8a7c10 renamed various functions in `CharInfo.h` and `Lexer.h`. Rename uses in Swift. --- lib/IDE/SyntaxModel.cpp | 4 ++-- lib/IRGen/IRGenModule.cpp | 2 +- lib/Parse/Lexer.cpp | 16 ++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp index f531ac8d6f93f..39d777fb8c73f 100644 --- a/lib/IDE/SyntaxModel.cpp +++ b/lib/IDE/SyntaxModel.cpp @@ -1599,10 +1599,10 @@ class DocFieldParser { if (!advanceIf('-') || !advanceIf(' ')) return None; - if (ptr == end || !clang::isIdentifierBody(*ptr)) + if (ptr == end || !clang::isAsciiIdentifierContinue(*ptr)) return None; const char *identStart = ptr++; - while (advanceIf([](char c) { return clang::isIdentifierBody(c); })) + while (advanceIf([](char c) { return clang::isAsciiIdentifierContinue(c); })) ; StringRef ident(identStart, ptr - identStart); diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index d965eb5563e05..bdfaabe0da35a 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -1247,7 +1247,7 @@ llvm::Constant *IRGenModule::getOpaquePtr(llvm::Constant *ptr) { } static void appendEncodedName(raw_ostream &os, StringRef name) { - if (clang::isValidIdentifier(name)) { + if (clang::isValidAsciiIdentifier(name)) { os << "_" << name; } else { for (auto c : name) diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index ed44215c4e597..20dd80e2a4ec9 100644 --- a/lib/Parse/Lexer.cpp +++ b/lib/Parse/Lexer.cpp @@ -42,9 +42,9 @@ void Parser_registerParseRegexStrawperson(ParseRegexStrawperson fn) { using namespace swift; using namespace swift::syntax; -// clang::isIdentifierHead and clang::isIdentifierBody are deliberately not in -// this list as a reminder that they are using C rules for identifiers. -// (Admittedly these are the same as Swift's right now.) +// clang::isAsciiIdentifierStart and clang::isAsciiIdentifierContinue are +// deliberately not in this list as a reminder that they are using C rules for +// identifiers. (Admittedly these are the same as Swift's right now.) using clang::isAlphanumeric; using clang::isDigit; using clang::isHexDigit; @@ -521,7 +521,7 @@ void Lexer::skipSlashStarComment() { static bool isValidIdentifierContinuationCodePoint(uint32_t c) { if (c < 0x80) - return clang::isIdentifierBody(c, /*dollar*/true); + return clang::isAsciiIdentifierContinue(c, /*dollar*/true); // N1518: Recommendations for extended identifier characters for C and C++ // Proposed Annex X.1: Ranges of characters allowed @@ -679,10 +679,10 @@ void Lexer::lexHash() { // Scan for [a-zA-Z]+ to see what we match. const char *tmpPtr = CurPtr; - if (clang::isIdentifierHead(*tmpPtr)) { + if (clang::isAsciiIdentifierStart(*tmpPtr)) { do { ++tmpPtr; - } while (clang::isIdentifierBody(*tmpPtr)); + } while (clang::isAsciiIdentifierContinue(*tmpPtr)); } // Map the character sequence onto @@ -2462,10 +2462,10 @@ void Lexer::lexImpl() { return lexOperatorIdentifier(); case '%': // Lex %[0-9a-zA-Z_]+ as a local SIL value - if (InSILBody && clang::isIdentifierBody(CurPtr[0])) { + if (InSILBody && clang::isAsciiIdentifierContinue(CurPtr[0])) { do { ++CurPtr; - } while (clang::isIdentifierBody(CurPtr[0])); + } while (clang::isAsciiIdentifierContinue(CurPtr[0])); return formToken(tok::sil_local_name, TokStart); } From f3bad25d22a7c1ea054e72a873d3050ed7e584ff Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 12 Nov 2021 20:06:09 +1000 Subject: [PATCH 004/491] [rebranch][ClangImporter] Update hashExtension to use HashBuilder llvm-project updated `hashExtension` in 655bea4226b401a11164f99c6344e38d8742b8e4 to use a `HashBuilder` rather than `hash_code`. Update use in ClangImporter. --- lib/ClangImporter/ImporterImpl.h | 2 +- lib/ClangImporter/SwiftLookupTable.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 8042c857087ce..e4599ec810994 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -1618,7 +1618,7 @@ class SwiftNameLookupExtension : public clang::ModuleFileExtension { buffersForDiagnostics(buffersForDiagnostics), availability(avail) {} clang::ModuleFileExtensionMetadata getExtensionMetadata() const override; - llvm::hash_code hashExtension(llvm::hash_code code) const override; + void hashExtension(ExtensionHashBuilder &HBuilder) const override; std::unique_ptr createExtensionWriter(clang::ASTWriter &writer) override; diff --git a/lib/ClangImporter/SwiftLookupTable.cpp b/lib/ClangImporter/SwiftLookupTable.cpp index b76d05d781bc7..c79086ba12eaf 100644 --- a/lib/ClangImporter/SwiftLookupTable.cpp +++ b/lib/ClangImporter/SwiftLookupTable.cpp @@ -1849,12 +1849,12 @@ SwiftNameLookupExtension::getExtensionMetadata() const { return metadata; } -llvm::hash_code -SwiftNameLookupExtension::hashExtension(llvm::hash_code code) const { - return llvm::hash_combine(code, StringRef("swift.lookup"), - SWIFT_LOOKUP_TABLE_VERSION_MAJOR, - SWIFT_LOOKUP_TABLE_VERSION_MINOR, - version::getSwiftFullVersion()); +void +SwiftNameLookupExtension::hashExtension(ExtensionHashBuilder &HBuilder) const { + HBuilder.add(StringRef("swift.lookup")); + HBuilder.add(SWIFT_LOOKUP_TABLE_VERSION_MAJOR); + HBuilder.add(SWIFT_LOOKUP_TABLE_VERSION_MINOR); + HBuilder.add(version::getSwiftFullVersion()); } void importer::addEntryToLookupTable(SwiftLookupTable &table, From d81f22670505ec590fddf6586096c185c04acab0 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Sat, 13 Nov 2021 11:29:19 +1000 Subject: [PATCH 005/491] [rebranch][IRGen] Update uses of AttributeList functions The functions in llvm-project `AttributeList` have been renamed/refactored to help remove uses of `AttributeList::*Index`. Update to use these new functions where possible. There's one use of `AttrIndex` remaining as `replaceAttributeTypeAtIndex` still takes the index and there is no `param` equivalent. We could add one locally, but presumably that will be added eventually. --- lib/IRGen/CallEmission.h | 4 +- lib/IRGen/GenArchetype.cpp | 6 +-- lib/IRGen/GenBuiltin.cpp | 6 +-- lib/IRGen/GenCall.cpp | 60 ++++++++++------------- lib/IRGen/GenCall.h | 5 -- lib/IRGen/GenDecl.cpp | 20 +++----- lib/IRGen/GenEnum.cpp | 3 +- lib/IRGen/GenFunc.cpp | 2 +- lib/IRGen/GenHeap.cpp | 6 +-- lib/IRGen/GenKeyPath.cpp | 20 ++++---- lib/IRGen/GenMeta.cpp | 6 +-- lib/IRGen/GenObjC.cpp | 4 +- lib/IRGen/GenOpaque.cpp | 16 +++--- lib/IRGen/GenProto.cpp | 6 +-- lib/IRGen/IRGenFunction.cpp | 32 +++--------- lib/IRGen/IRGenModule.cpp | 19 +++---- lib/IRGen/IRGenSIL.cpp | 3 +- lib/IRGen/MetadataRequest.cpp | 16 +++--- lib/SIL/IR/SILInstruction.cpp | 8 +-- lib/SIL/IR/SILModule.cpp | 5 +- lib/SILOptimizer/Analysis/ARCAnalysis.cpp | 2 +- 21 files changed, 96 insertions(+), 153 deletions(-) diff --git a/lib/IRGen/CallEmission.h b/lib/IRGen/CallEmission.h index 25072be085369..a0467ae40fc20 100644 --- a/lib/IRGen/CallEmission.h +++ b/lib/IRGen/CallEmission.h @@ -97,7 +97,9 @@ class CallEmission { WitnessMetadata *witnessMetadata); virtual Address getCalleeErrorSlot(SILType errorType, bool isCalleeAsync) = 0; - void addAttribute(unsigned Index, llvm::Attribute::AttrKind Attr); + void addFnAttribute(llvm::Attribute::AttrKind Attr); + + void addParamAttribute(unsigned ParamIndex, llvm::Attribute::AttrKind Attr); void emitToMemory(Address addr, const LoadableTypeInfo &substResultTI, bool isOutlined); diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp index 30871955b094b..68736d1f8e9ae 100644 --- a/lib/IRGen/GenArchetype.cpp +++ b/lib/IRGen/GenArchetype.cpp @@ -518,8 +518,7 @@ MetadataResponse irgen::emitOpaqueTypeMetadataRef(IRGenFunction &IGF, {request.get(IGF), genericArgs, descriptor, indexValue}); result->setDoesNotThrow(); result->setCallingConv(IGF.IGM.SwiftCC); - result->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly); + result->addFnAttr(llvm::Attribute::ReadOnly); }); assert(result); @@ -552,8 +551,7 @@ llvm::Value *irgen::emitOpaqueTypeWitnessTableRef(IRGenFunction &IGF, {genericArgs, descriptor, indexValue}); result->setDoesNotThrow(); result->setCallingConv(IGF.IGM.SwiftCC); - result->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly); + result->addFnAttr(llvm::Attribute::ReadOnly); }); assert(result); diff --git a/lib/IRGen/GenBuiltin.cpp b/lib/IRGen/GenBuiltin.cpp index 9083f57665596..25eefb4bd39b8 100644 --- a/lib/IRGen/GenBuiltin.cpp +++ b/lib/IRGen/GenBuiltin.cpp @@ -603,10 +603,8 @@ if (Builtin.ID == BuiltinValueKind::id) { \ llvm::CallInst *call = IGF.Builder.CreateCall(fn, {context, errorBuffer.getAddress()}); call->setCallingConv(IGF.IGM.SwiftCC); - call->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - call->addAttribute(llvm::AttributeList::FirstArgIndex + 1, - llvm::Attribute::ReadOnly); + call->addFnAttr(llvm::Attribute::NoUnwind); + call->addParamAttr(1, llvm::Attribute::ReadOnly); auto attrs = call->getAttributes(); IGF.IGM.addSwiftSelfAttributes(attrs, 0); diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 4dbcdeb177aee..b3745329468d5 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -260,8 +260,7 @@ static void addIndirectValueParameterAttributes(IRGenModule &IGM, // The parameter must reference dereferenceable memory of the type. addDereferenceableAttributeToBuilder(IGM, b, ti); - attrs = attrs.addAttributes(IGM.getLLVMContext(), - argIndex + llvm::AttributeList::FirstArgIndex, b); + attrs = attrs.addParamAttributes(IGM.getLLVMContext(), argIndex, b); } static void addInoutParameterAttributes(IRGenModule &IGM, @@ -276,8 +275,7 @@ static void addInoutParameterAttributes(IRGenModule &IGM, // The inout must reference dereferenceable memory of the type. addDereferenceableAttributeToBuilder(IGM, b, ti); - attrs = attrs.addAttributes(IGM.getLLVMContext(), - argIndex + llvm::AttributeList::FirstArgIndex, b); + attrs = attrs.addParamAttributes(IGM.getLLVMContext(), argIndex, b); } static llvm::CallingConv::ID getFreestandingConvention(IRGenModule &IGM) { @@ -319,25 +317,21 @@ static void addIndirectResultAttributes(IRGenModule &IGM, assert(storageType); b.addStructRetAttr(storageType); } - attrs = attrs.addAttributes(IGM.getLLVMContext(), - paramIndex + llvm::AttributeList::FirstArgIndex, - b); + attrs = attrs.addParamAttributes(IGM.getLLVMContext(), paramIndex, b); } void IRGenModule::addSwiftAsyncContextAttributes(llvm::AttributeList &attrs, unsigned argIndex) { llvm::AttrBuilder b; b.addAttribute(llvm::Attribute::SwiftAsync); - attrs = attrs.addAttributes(this->getLLVMContext(), - argIndex + llvm::AttributeList::FirstArgIndex, b); + attrs = attrs.addParamAttributes(this->getLLVMContext(), argIndex, b); } void IRGenModule::addSwiftSelfAttributes(llvm::AttributeList &attrs, unsigned argIndex) { llvm::AttrBuilder b; b.addAttribute(llvm::Attribute::SwiftSelf); - attrs = attrs.addAttributes(this->getLLVMContext(), - argIndex + llvm::AttributeList::FirstArgIndex, b); + attrs = attrs.addParamAttributes(this->getLLVMContext(), argIndex, b); } void IRGenModule::addSwiftErrorAttributes(llvm::AttributeList &attrs, @@ -355,9 +349,8 @@ void IRGenModule::addSwiftErrorAttributes(llvm::AttributeList &attrs, b.addAttribute(llvm::Attribute::NoAlias); b.addAttribute(llvm::Attribute::NoCapture); b.addDereferenceableAttr(getPointerSize().getValue()); - - auto attrIndex = argIndex + llvm::AttributeList::FirstArgIndex; - attrs = attrs.addAttributes(this->getLLVMContext(), attrIndex, b); + + attrs = attrs.addParamAttributes(this->getLLVMContext(), argIndex, b); } void irgen::addByvalArgumentAttributes(IRGenModule &IGM, @@ -368,18 +361,13 @@ void irgen::addByvalArgumentAttributes(IRGenModule &IGM, b.addByValAttr(storageType); b.addAttribute(llvm::Attribute::getWithAlignment( IGM.getLLVMContext(), llvm::Align(align.getValue()))); - attrs = attrs.addAttributes(IGM.getLLVMContext(), - argIndex + llvm::AttributeList::FirstArgIndex, b); + attrs = attrs.addParamAttributes(IGM.getLLVMContext(), argIndex, b); } -void irgen::addExtendAttribute(IRGenModule &IGM, llvm::AttributeList &attrs, - unsigned index, bool signExtend) { - llvm::AttrBuilder b; +static llvm::Attribute::AttrKind attrKindForExtending(bool signExtend) { if (signExtend) - b.addAttribute(llvm::Attribute::SExt); - else - b.addAttribute(llvm::Attribute::ZExt); - attrs = attrs.addAttributes(IGM.getLLVMContext(), index, b); + return llvm::Attribute::SExt; + return llvm::Attribute::ZExt; } namespace swift { @@ -1366,7 +1354,8 @@ void SignatureExpansion::expandExternalSignatureTypes() { bool signExt = clangResultTy->hasSignedIntegerRepresentation(); assert((signExt || clangResultTy->hasUnsignedIntegerRepresentation()) && "Invalid attempt to add extension attribute to argument!"); - addExtendAttribute(IGM, Attrs, llvm::AttributeList::ReturnIndex, signExt); + Attrs = Attrs.addRetAttribute(IGM.getLLVMContext(), + attrKindForExtending(signExt)); } // If we return indirectly, that is the first parameter type. @@ -1396,8 +1385,8 @@ void SignatureExpansion::expandExternalSignatureTypes() { bool signExt = paramTys[i]->hasSignedIntegerRepresentation(); assert((signExt || paramTys[i]->hasUnsignedIntegerRepresentation()) && "Invalid attempt to add extension attribute to argument!"); - addExtendAttribute(IGM, Attrs, getCurParamIndex() + - llvm::AttributeList::FirstArgIndex, signExt); + Attrs = Attrs.addParamAttribute(IGM.getLLVMContext(), getCurParamIndex(), + attrKindForExtending(signExt)); LLVM_FALLTHROUGH; } case clang::CodeGen::ABIArgInfo::Direct: { @@ -2147,8 +2136,7 @@ class SyncCallEmission final : public CallEmission { assert(LastArgWritten > 0); Args[--LastArgWritten] = errorResultSlot.getAddress(); - addAttribute(LastArgWritten + llvm::AttributeList::FirstArgIndex, - llvm::Attribute::NoCapture); + addParamAttribute(LastArgWritten, llvm::Attribute::NoCapture); IGF.IGM.addSwiftErrorAttributes(CurCallee.getMutableAttributes(), LastArgWritten); @@ -2847,12 +2835,12 @@ fixUpTypesInByValAndStructRetAttributes(llvm::FunctionType *fnType, auto attrListIndex = llvm::AttributeList::FirstArgIndex + i; if (attrList.hasParamAttr(i, llvm::Attribute::StructRet) && paramTy->getPointerElementType() != attrList.getParamStructRetType(i)) - attrList = attrList.replaceAttributeType( + attrList = attrList.replaceAttributeTypeAtIndex( context, attrListIndex, llvm::Attribute::StructRet, paramTy->getPointerElementType()); if (attrList.hasParamAttr(i, llvm::Attribute::ByVal) && paramTy->getPointerElementType() != attrList.getParamByValType(i)) - attrList = attrList.replaceAttributeType( + attrList = attrList.replaceAttributeTypeAtIndex( context, attrListIndex, llvm::Attribute::ByVal, paramTy->getPointerElementType()); } @@ -4090,11 +4078,17 @@ void CallEmission::setArgs(Explosion &adjusted, bool isOutlined, } } -void CallEmission::addAttribute(unsigned index, - llvm::Attribute::AttrKind attr) { +void CallEmission::addFnAttribute(llvm::Attribute::AttrKind attr) { + assert(state == State::Emitting); + auto &attrs = CurCallee.getMutableAttributes(); + attrs = attrs.addFnAttribute(IGF.IGM.getLLVMContext(), attr); +} + +void CallEmission::addParamAttribute(unsigned paramIndex, + llvm::Attribute::AttrKind attr) { assert(state == State::Emitting); auto &attrs = CurCallee.getMutableAttributes(); - attrs = attrs.addAttribute(IGF.IGM.getLLVMContext(), index, attr); + attrs = attrs.addParamAttribute(IGF.IGM.getLLVMContext(), paramIndex, attr); } /// Initialize an Explosion with the parameters of the current diff --git a/lib/IRGen/GenCall.h b/lib/IRGen/GenCall.h index 0172fdf0ff630..e9fb9a7ceb167 100644 --- a/lib/IRGen/GenCall.h +++ b/lib/IRGen/GenCall.h @@ -156,11 +156,6 @@ namespace irgen { Alignment align, llvm::Type *storageType); - /// Add signext or zeroext attribute set for an argument that needs - /// extending. - void addExtendAttribute(IRGenModule &IGM, llvm::AttributeList &attrs, - unsigned index, bool signExtend); - /// Can a series of values be simply pairwise coerced to (or from) an /// explosion schema, or do they need to traffic through memory? bool canCoerceToSchema(IRGenModule &IGM, diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 8dc2cfd6ead6f..d3355d402c7ba 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -2248,10 +2248,8 @@ llvm::Function *irgen::createFunction(IRGenModule &IGM, llvm::AttrBuilder initialAttrs; IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode); // Merge initialAttrs with attrs. - auto updatedAttrs = - signature.getAttributes().addAttributes(IGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - initialAttrs); + auto updatedAttrs = signature.getAttributes().addFnAttributes( + IGM.getLLVMContext(), initialAttrs); if (!updatedAttrs.isEmpty()) fn->setAttributes(updatedAttrs); @@ -2619,9 +2617,8 @@ static void addLLVMFunctionAttributes(SILFunction *f, Signature &signature) { auto &attrs = signature.getMutableAttributes(); switch (f->getInlineStrategy()) { case NoInline: - attrs = attrs.addAttribute(signature.getType()->getContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoInline); + attrs = attrs.addFnAttribute(signature.getType()->getContext(), + llvm::Attribute::NoInline); break; case AlwaysInline: // FIXME: We do not currently transfer AlwaysInline since doing so results @@ -2631,9 +2628,8 @@ static void addLLVMFunctionAttributes(SILFunction *f, Signature &signature) { } if (isReadOnlyFunction(f)) { - attrs = attrs.addAttribute(signature.getType()->getContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly); + attrs = attrs.addFnAttribute(signature.getType()->getContext(), + llvm::Attribute::ReadOnly); } } @@ -3097,8 +3093,8 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded( llvm::AttrBuilder attrBuilder; IGM.constructInitialFnAttributes(attrBuilder); attrBuilder.addAttribute(llvm::Attribute::AlwaysInline); - llvm::AttributeList attr = signature.getAttributes().addAttributes( - IGM.getLLVMContext(), llvm::AttributeList::FunctionIndex, attrBuilder); + llvm::AttributeList attr = signature.getAttributes().addFnAttributes( + IGM.getLLVMContext(), attrBuilder); thunk->setAttributes(attr); IRGenFunction subIGF(IGM, thunk); diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index 93d7b4dc7f512..a94d45e69b49f 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -3865,8 +3865,7 @@ namespace { auto call = IGF.Builder.CreateCall(IGM.getGetEnumCaseMultiPayloadFn(), {addr.getAddress(), metadata}); call->setDoesNotThrow(); - call->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly); + call->addFnAttr(llvm::Attribute::ReadOnly); return call; } diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 1b57f9368611f..7e36af9d3561a 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -1263,7 +1263,7 @@ static llvm::Value *emitPartialApplicationForwarder(IRGenModule &IGM, // Merge initial attributes with outAttrs. llvm::AttrBuilder b; IGM.constructInitialFnAttributes(b); - fwd->addAttributes(llvm::AttributeList::FunctionIndex, b); + fwd->addFnAttrs(b); IRGenFunction subIGF(IGM, fwd); if (origType->isAsync()) { diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index 4f6a27b1fe32e..643ea2d640362 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -1237,8 +1237,7 @@ llvm::Constant *IRGenModule::getFixLifetimeFn() { // Don't inline the function, so it stays as a signal to the ARC passes. // The ARC passes will remove references to the function when they're // no longer needed. - fixLifetime->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoInline); + fixLifetime->addFnAttr(llvm::Attribute::NoInline); // Give the function an empty body. auto entry = llvm::BasicBlock::Create(getLLVMContext(), "", fixLifetime); @@ -1958,8 +1957,7 @@ emitHeapMetadataRefForUnknownHeapObject(IRGenFunction &IGF, object->getName() + ".Type"); metadata->setCallingConv(llvm::CallingConv::C); metadata->setDoesNotThrow(); - metadata->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly); + metadata->addFnAttr(llvm::Attribute::ReadOnly); return metadata; } diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index 79ae451f86da7..acee202ed887c 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -188,22 +188,22 @@ getAccessorForComputedComponent(IRGenModule &IGM, case Getter: // Original accessor's args should be @in or @out, meaning they won't be // captured or aliased. - accessorThunk->addAttribute(1, llvm::Attribute::NoCapture); - accessorThunk->addAttribute(1, llvm::Attribute::NoAlias); - accessorThunk->addAttribute(2, llvm::Attribute::NoCapture); - accessorThunk->addAttribute(2, llvm::Attribute::NoAlias); + accessorThunk->addParamAttr(0, llvm::Attribute::NoCapture); + accessorThunk->addParamAttr(0, llvm::Attribute::NoAlias); + accessorThunk->addParamAttr(1, llvm::Attribute::NoCapture); + accessorThunk->addParamAttr(1, llvm::Attribute::NoAlias); // Output is sret. - accessorThunk->addAttribute( - 1, llvm::Attribute::getWithStructRetType( + accessorThunk->addParamAttr( + 0, llvm::Attribute::getWithStructRetType( IGM.getLLVMContext(), thunkParams[0]->getPointerElementType())); break; case Setter: // Original accessor's args should be @in or @out, meaning they won't be // captured or aliased. - accessorThunk->addAttribute(1, llvm::Attribute::NoCapture); - accessorThunk->addAttribute(1, llvm::Attribute::NoAlias); - accessorThunk->addAttribute(2, llvm::Attribute::NoCapture); - accessorThunk->addAttribute(2, llvm::Attribute::NoAlias); + accessorThunk->addParamAttr(0, llvm::Attribute::NoCapture); + accessorThunk->addParamAttr(0, llvm::Attribute::NoAlias); + accessorThunk->addParamAttr(1, llvm::Attribute::NoCapture); + accessorThunk->addParamAttr(1, llvm::Attribute::NoAlias); break; case Equals: case Hash: diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 2733b43d63fff..ba8a8ce6a341e 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -4980,10 +4980,8 @@ namespace { auto candidate = IGF.IGM.getAddrOfTypeMetadata(type); auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(), {request.get(IGF), candidate}); - call->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - call->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadNone); + call->addFnAttr(llvm::Attribute::NoUnwind); + call->addFnAttr(llvm::Attribute::ReadNone); return MetadataResponse::handle(IGF, request, call); }); diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp index 3f860074818fd..d99ef7b718d7c 100644 --- a/lib/IRGen/GenObjC.cpp +++ b/lib/IRGen/GenObjC.cpp @@ -721,8 +721,8 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM, // Merge initial attributes with attrs. llvm::AttrBuilder b; IGM.constructInitialFnAttributes(b); - fwd->addAttributes(llvm::AttributeList::FunctionIndex, b); - + fwd->addFnAttrs(b); + IRGenFunction subIGF(IGM, fwd); if (IGM.DebugInfo) IGM.DebugInfo->emitArtificialFunction(subIGF, fwd); diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp index fb62ca43beda5..f6b3a405b0e00 100644 --- a/lib/IRGen/GenOpaque.cpp +++ b/lib/IRGen/GenOpaque.cpp @@ -164,8 +164,8 @@ static llvm::AttributeList getValueWitnessAttrs(IRGenModule &IGM, auto &ctx = IGM.getLLVMContext(); // All value witnesses are nounwind. - auto attrs = llvm::AttributeList::get(ctx, llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); + auto attrs = + llvm::AttributeList().addFnAttribute(ctx, llvm::Attribute::NoUnwind); switch (index) { // These have two arguments, but they can alias. @@ -178,21 +178,19 @@ static llvm::AttributeList getValueWitnessAttrs(IRGenModule &IGM, case ValueWitness::DestructiveProjectEnumData: case ValueWitness::GetEnumTag: case ValueWitness::StoreEnumTagSinglePayload: - return attrs.addAttribute(ctx, 1, llvm::Attribute::NoAlias); + return attrs.addParamAttribute(ctx, 0, llvm::Attribute::NoAlias); case ValueWitness::GetEnumTagSinglePayload: - return attrs - .addAttribute(ctx, llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly) - .addAttribute(ctx, 1, llvm::Attribute::NoAlias); + return attrs.addFnAttribute(ctx, llvm::Attribute::ReadOnly) + .addParamAttribute(ctx, 0, llvm::Attribute::NoAlias); // These have two arguments and they don't alias each other. case ValueWitness::AssignWithTake: case ValueWitness::InitializeBufferWithCopyOfBuffer: case ValueWitness::InitializeWithCopy: case ValueWitness::InitializeWithTake: - return attrs.addAttribute(ctx, 1, llvm::Attribute::NoAlias) - .addAttribute(ctx, 2, llvm::Attribute::NoAlias); + return attrs.addParamAttribute(ctx, 0, llvm::Attribute::NoAlias) + .addParamAttribute(ctx, 1, llvm::Attribute::NoAlias); case ValueWitness::Size: case ValueWitness::Flags: diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index a8aa859610bed..7eed9cdcd4ca1 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -3638,10 +3638,8 @@ IRGenModule::getAssociatedTypeWitnessTableAccessFunctionSignature() { /*varargs*/ false); } - auto attrs = llvm::AttributeList::get(getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - + auto attrs = llvm::AttributeList().addFnAttribute(getLLVMContext(), + llvm::Attribute::NoUnwind); return Signature(fnType, attrs, SwiftCC); } diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp index f975f1fd03db5..be925b0a1a171 100644 --- a/lib/IRGen/IRGenFunction.cpp +++ b/lib/IRGen/IRGenFunction.cpp @@ -180,13 +180,9 @@ llvm::Value *IRGenFunction::emitVerifyEndOfLifetimeCall(llvm::Value *object, void IRGenFunction::emitAllocBoxCall(llvm::Value *typeMetadata, llvm::Value *&box, llvm::Value *&valueAddress) { - auto attrs = llvm::AttributeList::get(IGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - llvm::CallInst *call = Builder.CreateCall(IGM.getAllocBoxFn(), typeMetadata); - call->setAttributes(attrs); + call->addFnAttr(llvm::Attribute::NoUnwind); box = Builder.CreateExtractValue(call, 0); valueAddress = Builder.CreateExtractValue(call, 1); @@ -197,13 +193,9 @@ void IRGenFunction::emitMakeBoxUniqueCall(llvm::Value *box, llvm::Value *alignMask, llvm::Value *&outBox, llvm::Value *&outValueAddress) { - auto attrs = llvm::AttributeList::get(IGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - llvm::CallInst *call = Builder.CreateCall(IGM.getMakeBoxUniqueFn(), {box, typeMetadata, alignMask}); - call->setAttributes(attrs); + call->addFnAttr(llvm::Attribute::NoUnwind); outBox = Builder.CreateExtractValue(call, 0); outValueAddress = Builder.CreateExtractValue(call, 1); @@ -212,39 +204,27 @@ void IRGenFunction::emitMakeBoxUniqueCall(llvm::Value *box, void IRGenFunction::emitDeallocBoxCall(llvm::Value *box, llvm::Value *typeMetadata) { - auto attrs = llvm::AttributeList::get(IGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - llvm::CallInst *call = Builder.CreateCall(IGM.getDeallocBoxFn(), box); call->setCallingConv(IGM.DefaultCC); - call->setAttributes(attrs); + call->addFnAttr(llvm::Attribute::NoUnwind); } llvm::Value *IRGenFunction::emitProjectBoxCall(llvm::Value *box, llvm::Value *typeMetadata) { - llvm::Attribute::AttrKind attrKinds[] = { - llvm::Attribute::NoUnwind, - llvm::Attribute::ReadNone, - }; - auto attrs = llvm::AttributeList::get( - IGM.getLLVMContext(), llvm::AttributeList::FunctionIndex, attrKinds); llvm::CallInst *call = Builder.CreateCall(IGM.getProjectBoxFn(), box); call->setCallingConv(IGM.DefaultCC); - call->setAttributes(attrs); + call->addFnAttr(llvm::Attribute::NoUnwind); + call->addFnAttr(llvm::Attribute::ReadNone); return call; } llvm::Value *IRGenFunction::emitAllocEmptyBoxCall() { - auto attrs = llvm::AttributeList::get(IGM.getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); llvm::CallInst *call = Builder.CreateCall(IGM.getAllocEmptyBoxFn(), {}); call->setCallingConv(IGM.DefaultCC); - call->setAttributes(attrs); + call->addFnAttr(llvm::Attribute::NoUnwind); return call; } diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index bdfaabe0da35a..255299feff477 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -943,8 +943,8 @@ llvm::Constant *swift::getRuntimeFn(llvm::Module &Module, else buildFnAttr.addAttribute(Attr); } - fn->addAttributes(llvm::AttributeList::FunctionIndex, buildFnAttr); - fn->addAttributes(llvm::AttributeList::ReturnIndex, buildRetAttr); + fn->addFnAttrs(buildFnAttr); + fn->addRetAttrs(buildRetAttr); fn->addParamAttrs(0, buildFirstParamAttr); } @@ -1182,14 +1182,10 @@ void IRGenerator::addBackDeployedObjCActorInitialization(ClassDecl *ClassDecl) { llvm::AttributeList IRGenModule::getAllocAttrs() { if (AllocAttrs.isEmpty()) { + AllocAttrs = llvm::AttributeList().addRetAttribute( + getLLVMContext(), llvm::Attribute::NoAlias); AllocAttrs = - llvm::AttributeList::get(getLLVMContext(), - llvm::AttributeList::ReturnIndex, - llvm::Attribute::NoAlias); - AllocAttrs = - AllocAttrs.addAttribute(getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); + AllocAttrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoUnwind); } return AllocAttrs; } @@ -1206,7 +1202,7 @@ void IRGenModule::setHasNoFramePointer(llvm::AttrBuilder &Attrs) { void IRGenModule::setHasNoFramePointer(llvm::Function *F) { llvm::AttrBuilder b; setHasNoFramePointer(b); - F->addAttributes(llvm::AttributeList::FunctionIndex, b); + F->addFnAttrs(b); } /// Construct initial function attributes from options. @@ -1230,8 +1226,7 @@ void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs, llvm::AttributeList IRGenModule::constructInitialAttributes() { llvm::AttrBuilder b; constructInitialFnAttributes(b); - return llvm::AttributeList::get(getLLVMContext(), - llvm::AttributeList::FunctionIndex, b); + return llvm::AttributeList().addFnAttributes(getLLVMContext(), b); } llvm::ConstantInt *IRGenModule::getInt32(uint32_t value) { diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 245e2aae82efc..d3d5fdac21266 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -2989,8 +2989,7 @@ static std::unique_ptr getCallEmissionForLoweredValue( auto callEmission = getCallEmission(IGF, selfValue, std::move(callee)); if (IGF.CurSILFn->isThunk()) - callEmission->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoInline); + callEmission->addFnAttribute(llvm::Attribute::NoInline); return callEmission; } diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 21ff16f54e6c4..b3b25b49cb14d 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -612,8 +612,7 @@ static MetadataResponse emitNominalPrespecializedGenericMetadataRef( cacheVariable}); call->setDoesNotThrow(); call->setCallingConv(IGF.IGM.SwiftCC); - call->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadNone); + call->addFnAttr(llvm::Attribute::ReadNone); return MetadataResponse::handle(IGF, request, call); } } @@ -1831,8 +1830,7 @@ void irgen::emitCacheAccessFunction(IRGenModule &IGM, accessor->setDoesNotThrow(); // Don't inline cache functions, since doing so has little impact on // overall performance. - accessor->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoInline); + accessor->addFnAttr(llvm::Attribute::NoInline); // Accessor functions don't need frame pointers. IGM.setHasNoFramePointer(accessor); @@ -2051,10 +2049,9 @@ IRGenFunction::emitGenericTypeMetadataAccessFunctionCall( auto call = Builder.CreateCall(accessFunction, callArgs); call->setDoesNotThrow(); call->setCallingConv(IGM.SwiftCC); - call->addAttribute(llvm::AttributeList::FunctionIndex, - allocatedArgsBuffer - ? llvm::Attribute::InaccessibleMemOrArgMemOnly - : llvm::Attribute::ReadNone); + call->addFnAttr(allocatedArgsBuffer + ? llvm::Attribute::InaccessibleMemOrArgMemOnly + : llvm::Attribute::ReadNone); // If we allocated a buffer for the arguments, end its lifetime. if (allocatedArgsBuffer) @@ -2110,8 +2107,7 @@ MetadataResponse irgen::emitGenericTypeMetadataAccessFunction( } call->setDoesNotThrow(); call->setCallingConv(IGM.SwiftCC); - call->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly); + call->addFnAttr(llvm::Attribute::ReadOnly); result = call; } else { static_assert(NumDirectGenericTypeMetadataAccessFunctionArgs == 3, diff --git a/lib/SIL/IR/SILInstruction.cpp b/lib/SIL/IR/SILInstruction.cpp index 15968190b1902..f1bd60e4a4ec2 100644 --- a/lib/SIL/IR/SILInstruction.cpp +++ b/lib/SIL/IR/SILInstruction.cpp @@ -1010,12 +1010,12 @@ SILInstruction::MemoryBehavior SILInstruction::getMemoryBehavior() const { if (IInfo.ID != llvm::Intrinsic::not_intrinsic) { auto IAttrs = IInfo.getOrCreateAttributes(getModule().getASTContext()); // Read-only. - if (IAttrs.hasFnAttribute(llvm::Attribute::ReadOnly) && - IAttrs.hasFnAttribute(llvm::Attribute::NoUnwind)) + if (IAttrs.hasFnAttr(llvm::Attribute::ReadOnly) && + IAttrs.hasFnAttr(llvm::Attribute::NoUnwind)) return MemoryBehavior::MayRead; // Read-none? - return IAttrs.hasFnAttribute(llvm::Attribute::ReadNone) && - IAttrs.hasFnAttribute(llvm::Attribute::NoUnwind) + return IAttrs.hasFnAttr(llvm::Attribute::ReadNone) && + IAttrs.hasFnAttr(llvm::Attribute::NoUnwind) ? MemoryBehavior::None : MemoryBehavior::MayHaveSideEffects; } diff --git a/lib/SIL/IR/SILModule.cpp b/lib/SIL/IR/SILModule.cpp index 3c6f5369a4d5b..e92d96d2eb168 100644 --- a/lib/SIL/IR/SILModule.cpp +++ b/lib/SIL/IR/SILModule.cpp @@ -821,9 +821,8 @@ void SILModule::notifyMovedInstruction(SILInstruction *inst, bool SILModule::isNoReturnBuiltinOrIntrinsic(Identifier Name) { const auto &IntrinsicInfo = getIntrinsicInfo(Name); if (IntrinsicInfo.ID != llvm::Intrinsic::not_intrinsic) { - return IntrinsicInfo - .getOrCreateAttributes(getASTContext()) - .hasFnAttribute(llvm::Attribute::NoReturn); + return IntrinsicInfo.getOrCreateAttributes(getASTContext()) + .hasFnAttr(llvm::Attribute::NoReturn); } const auto &BuiltinInfo = getBuiltinInfo(Name); switch (BuiltinInfo.ID) { diff --git a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp index 40a8ccbee2b48..83d9c3fabde95 100644 --- a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp @@ -104,7 +104,7 @@ static bool canApplyOfBuiltinUseNonTrivialValues(BuiltinInst *BInst) { auto &II = BInst->getIntrinsicInfo(); if (II.ID != llvm::Intrinsic::not_intrinsic) { auto attrs = II.getOrCreateAttributes(F->getASTContext()); - if (attrs.hasFnAttribute(llvm::Attribute::ReadNone)) { + if (attrs.hasFnAttr(llvm::Attribute::ReadNone)) { for (auto &Op : BInst->getAllOperands()) { if (!Op.get()->getType().isTrivial(*F)) { return true; From 1349c46a94a68b92f08e72bbe28ec2c093e43a5e Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Sat, 13 Nov 2021 12:26:39 +1000 Subject: [PATCH 006/491] [rebranch] Fix missing includes --- lib/IRGen/IRGen.cpp | 2 +- lib/Immediate/Immediate.cpp | 2 +- tools/swift-llvm-opt/LLVMOpt.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index 4a52cda0ab55e..241e9c0c5939d 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -62,6 +62,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/Linker/Linker.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -71,7 +72,6 @@ #include "llvm/Support/MD5.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/Path.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Coroutines.h" #include "llvm/Transforms/IPO.h" diff --git a/lib/Immediate/Immediate.cpp b/lib/Immediate/Immediate.cpp index d1cca84e85699..7456e67925842 100644 --- a/lib/Immediate/Immediate.cpp +++ b/lib/Immediate/Immediate.cpp @@ -34,7 +34,7 @@ #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" -#include "llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h" +#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" diff --git a/tools/swift-llvm-opt/LLVMOpt.cpp b/tools/swift-llvm-opt/LLVMOpt.cpp index 8f1f112e67c32..9e72647dbc90a 100644 --- a/tools/swift-llvm-opt/LLVMOpt.cpp +++ b/tools/swift-llvm-opt/LLVMOpt.cpp @@ -51,6 +51,7 @@ #include "llvm/LinkAllIR.h" #include "llvm/LinkAllPasses.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -60,7 +61,6 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Target/TargetMachine.h" From 2fdaeb62f02d278e08a2e7363e638ae5e7b4ddb9 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Sat, 13 Nov 2021 13:46:23 +1000 Subject: [PATCH 007/491] [rebranch] Handle new BuiltinType::Ibm128 --- lib/ClangImporter/ClangAdapter.cpp | 1 + lib/ClangImporter/ImportType.cpp | 1 + lib/IRGen/GenCall.cpp | 2 ++ 3 files changed, 4 insertions(+) diff --git a/lib/ClangImporter/ClangAdapter.cpp b/lib/ClangImporter/ClangAdapter.cpp index 1d576226156de..e1ab2094f0b52 100644 --- a/lib/ClangImporter/ClangAdapter.cpp +++ b/lib/ClangImporter/ClangAdapter.cpp @@ -396,6 +396,7 @@ OmissionTypeName importer::getClangTypeNameForOmission(clang::ASTContext &ctx, case clang::BuiltinType::Float16: case clang::BuiltinType::Float128: case clang::BuiltinType::NullPtr: + case clang::BuiltinType::Ibm128: return OmissionTypeName(); // Objective-C types that aren't mapped directly; rather, pointers to diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index d6b81c592637f..26d6f34b24604 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -289,6 +289,7 @@ namespace { case clang::BuiltinType::Float128: case clang::BuiltinType::NullPtr: case clang::BuiltinType::Char8: + case clang::BuiltinType::Ibm128: return Type(); // Objective-C types that aren't mapped directly; rather, pointers to diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index b3745329468d5..8d5694477dec7 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -1119,6 +1119,8 @@ namespace { return convertFloatingType(Ctx.getTargetInfo().getBFloat16Format()); case clang::BuiltinType::Float128: return convertFloatingType(Ctx.getTargetInfo().getFloat128Format()); + case clang::BuiltinType::Ibm128: + return convertFloatingType(Ctx.getTargetInfo().getIbm128Format()); // nullptr_t -> void* case clang::BuiltinType::NullPtr: From 618e94b5087796f9ad3129596430ded32964f054 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Sat, 13 Nov 2021 15:19:47 +1000 Subject: [PATCH 008/491] [rebranch] OptTable::ParseOneArg now returns a std::unique_ptr --- lib/Driver/Driver.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 43224b6f1d357..bd8617971913d 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1157,7 +1157,8 @@ parseArgsUntil(const llvm::opt::OptTable& Opts, } unsigned Prev = Index; - Arg *A = Opts.ParseOneArg(*Args, Index, FlagsToInclude, FlagsToExclude); + std::unique_ptr A = Opts.ParseOneArg(*Args, Index, FlagsToInclude, + FlagsToExclude); assert(Index > Prev && "Parser failed to consume argument."); // Check for missing argument error. @@ -1169,7 +1170,7 @@ parseArgsUntil(const llvm::opt::OptTable& Opts, break; } - Args->append(A); + Args->append(A.release()); if (CheckUntil && A->getOption().matches(UntilOption)) { if (Index < End) From 0316c913c14e3249940f88c7e94fbafb3a3587cd Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Sat, 13 Nov 2021 15:42:19 +1000 Subject: [PATCH 009/491] [rebranch] Delegate to DenseMapInfo where possible `WidthPreservingAPIntDenseMapInfo` uses the same `getHashValue` and `isEqual` as the normal `DenseMapInfo` but with different empty and tombstone keys. `hash_value` is no longer a complete type, so just delegate to `DenseMapInfo` rather than add another `#include`. --- include/swift/Basic/APIntMap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/swift/Basic/APIntMap.h b/include/swift/Basic/APIntMap.h index 3938dfc143ec9..dac8cd895f2fa 100644 --- a/include/swift/Basic/APIntMap.h +++ b/include/swift/Basic/APIntMap.h @@ -38,11 +38,11 @@ struct WidthPreservingAPIntDenseMapInfo { } static unsigned getHashValue(const APInt &Key) { - return static_cast(hash_value(Key)); + return llvm::DenseMapInfo::getHashValue(Key); } static bool isEqual(const APInt &LHS, const APInt &RHS) { - return LHS.getBitWidth() == RHS.getBitWidth() && LHS == RHS; + return llvm::DenseMapInfo::isEqual(LHS, RHS); } }; From b6a11de971b544520b777cb8d84165729d27a4b7 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Sat, 13 Nov 2021 15:59:00 +1000 Subject: [PATCH 010/491] [rebranch] Fix up a incorrect main -> next merge `CoverageFilenamesSectionWriter` now takes an `ArrayRef` rather than `ArrayRef`. stable/20210726 reverted that change so that the coverage formats were the same. stable/20211026 doesn't have that revert though. --- lib/IRGen/GenCoverage.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/IRGen/GenCoverage.cpp b/lib/IRGen/GenCoverage.cpp index bdedf23c75619..635c52ba6f18e 100644 --- a/lib/IRGen/GenCoverage.cpp +++ b/lib/IRGen/GenCoverage.cpp @@ -66,14 +66,12 @@ void IRGenModule::emitCoverageMapping() { Files.push_back(M->getFile()); auto remapper = getOptions().CoveragePrefixMap; - // Awkwardly munge absolute filenames into a vector of StringRefs. + llvm::SmallVector FilenameStrs; - llvm::SmallVector FilenameRefs; for (StringRef Name : Files) { llvm::SmallString<256> Path(Name); llvm::sys::fs::make_absolute(Path); FilenameStrs.push_back(remapper.remapPath(Path)); - FilenameRefs.push_back(FilenameStrs.back()); } // Encode the filenames. @@ -81,7 +79,7 @@ void IRGenModule::emitCoverageMapping() { llvm::LLVMContext &Ctx = getLLVMContext(); { llvm::raw_string_ostream OS(Filenames); - llvm::coverage::CoverageFilenamesSectionWriter(FilenameRefs).write(OS); + llvm::coverage::CoverageFilenamesSectionWriter(FilenameStrs).write(OS); } auto *FilenamesVal = llvm::ConstantDataArray::getString(Ctx, Filenames, false); From 6c39a9a683e24b5592af6f33c3b2ece0f7fa3979 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 16 Nov 2021 23:46:47 +1000 Subject: [PATCH 011/491] [rebranch] Add missing string include --- include/swift/Demangling/TypeLookupError.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/Demangling/TypeLookupError.h b/include/swift/Demangling/TypeLookupError.h index a0be10a5dba09..3c253c9026850 100644 --- a/include/swift/Demangling/TypeLookupError.h +++ b/include/swift/Demangling/TypeLookupError.h @@ -20,7 +20,7 @@ #include "swift/Basic/TaggedUnion.h" #include "swift/Runtime/Portability.h" -#include +#include namespace swift { From ee6706f3d996d8e0d196703a3c89bc49c715e3d0 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 17 Nov 2021 11:25:24 +1000 Subject: [PATCH 012/491] [rebranch] Update test broken in merge `async-args.swift` was updated in 29fd8d33446ee1135fb6017b96866c79ed6ed152 but the update looks to have been lost in a merge. Re-apply the missing portion. --- test/DebugInfo/async-args.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/DebugInfo/async-args.swift b/test/DebugInfo/async-args.swift index c287307b4eae2..b7201d6e1d831 100644 --- a/test/DebugInfo/async-args.swift +++ b/test/DebugInfo/async-args.swift @@ -10,10 +10,10 @@ func withGenericArg(_ msg: T) async { // This odd debug info is part of a contract with CoroSplit/CoroFrame to fix // this up after coroutine splitting. // CHECK-LABEL: {{^define .*}} @"$s1M14withGenericArgyyxYalF"(%swift.context* swiftasync %0 - // CHECK: call void @llvm.dbg.declare(metadata %swift.context* %0 - // CHECK-SAME: metadata ![[MSG:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, {{.*}}DW_OP_deref)) - // CHECK: call void @llvm.dbg.declare(metadata %swift.context* %0 - // CHECK-SAME: metadata ![[TAU:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, + // CHECK: call void @llvm.dbg.declare(metadata %swift.type** % + // CHECK-SAME: metadata ![[TAU:[0-9]+]], metadata !DIExpression() + // CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** % + // CHECK-SAME: metadata ![[MSG:[0-9]+]], metadata !DIExpression(DW_OP_deref)) await forceSplit() // CHECK-LABEL: {{^define .*}} @"$s1M14withGenericArgyyxYalFTQ0_"(i8* swiftasync %0) From 015b4d46f87d275be3359301c8df41b82e85d64f Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 17 Nov 2021 12:02:50 +1000 Subject: [PATCH 013/491] [rebranch] Immediately release OptTable parsed argument I had missed that `A` was used after `Args->append`. Just release the `unique_ptr` straight away and use it in the rest of the function. --- lib/Driver/Driver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index bd8617971913d..10169187064de 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1157,8 +1157,8 @@ parseArgsUntil(const llvm::opt::OptTable& Opts, } unsigned Prev = Index; - std::unique_ptr A = Opts.ParseOneArg(*Args, Index, FlagsToInclude, - FlagsToExclude); + Arg *A = Opts.ParseOneArg(*Args, Index, FlagsToInclude, FlagsToExclude) + .release(); assert(Index > Prev && "Parser failed to consume argument."); // Check for missing argument error. @@ -1170,7 +1170,7 @@ parseArgsUntil(const llvm::opt::OptTable& Opts, break; } - Args->append(A.release()); + Args->append(A); if (CheckUntil && A->getOption().matches(UntilOption)) { if (Index < End) From 7fd8d4fb1a82ac13a08020d2bf2f0de722a518cb Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 18 Nov 2021 16:47:28 +1000 Subject: [PATCH 014/491] [rebranch] Replace `LLVM_ATTRIBUTE_NORETURN` with `[[noreturn]]` llvm-project 09529892b518c8df8c24395e68e0a7a5e8bda5fb removed `LLVM_ATTRIBUTE_NORETURN` in favour of the C++11 `[[noreturn]]`. --- lib/Demangling/Demangler.cpp | 6 ++---- lib/Demangling/DemanglerAssert.h | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index 90953faf46d36..d3d8e39a334f5 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -91,10 +91,8 @@ static bool isRequirement(Node::Kind kind) { // Public utility functions // ////////////////////////////////// -LLVM_ATTRIBUTE_NORETURN void swift::Demangle::failAssert(const char *file, - unsigned line, - NodePointer node, - const char *expr) { +void swift::Demangle::failAssert(const char *file, unsigned line, + NodePointer node, const char *expr) { fprintf(stderr, "%s:%u: assertion failed for Node %p: %s", file, line, node, expr); abort(); diff --git a/lib/Demangling/DemanglerAssert.h b/lib/Demangling/DemanglerAssert.h index 52bd7aed46c5f..9fb58aad9cd6b 100644 --- a/lib/Demangling/DemanglerAssert.h +++ b/lib/Demangling/DemanglerAssert.h @@ -51,8 +51,8 @@ namespace swift { namespace Demangle { SWIFT_BEGIN_INLINE_NAMESPACE -LLVM_ATTRIBUTE_NORETURN void failAssert(const char *file, unsigned line, - NodePointer node, const char *expr); +[[noreturn]] void failAssert(const char *file, unsigned line, NodePointer node, + const char *expr); SWIFT_END_INLINE_NAMESPACE } // end namespace Demangle From 87d26e9567e8f558587d5a50fbec5abc76f82066 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 12 Nov 2021 18:16:31 +1000 Subject: [PATCH 015/491] [next] Ignore the new PPCQuad intrinsic Added in llvm-project 741aeda97d6327edd9905b21a5308fcee21bbefd. --- lib/AST/Builtins.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index ec82618cca616..983a87e182b7a 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -2086,6 +2086,7 @@ Type IntrinsicTypeDecoder::decodeImmediate() { case IITDescriptor::VecOfBitcastsToInt: case IITDescriptor::Subdivide2Argument: case IITDescriptor::Subdivide4Argument: + case IITDescriptor::PPCQuad: // These types cannot be expressed in swift yet. return Type(); From bd4b73755be1fcc64b2beb86805d6eb3f8c98006 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 18 Nov 2021 21:45:39 +1000 Subject: [PATCH 016/491] [next] Update `DenseMapInfo` declarations llvm-project 4c484f11d355e4293f7b245a9330f0a1e89630ac updated the `DenseMapInfo` template to take a SFINAE template parameter. --- include/swift/AST/AutoDiff.h | 2 +- include/swift/Basic/Located.h | 2 +- include/swift/Basic/SourceLoc.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/swift/AST/AutoDiff.h b/include/swift/AST/AutoDiff.h index 3bcdc5dc0852e..d78b720db0b62 100644 --- a/include/swift/AST/AutoDiff.h +++ b/include/swift/AST/AutoDiff.h @@ -705,7 +705,7 @@ using swift::SILFunctionType; using swift::DifferentiabilityKind; using swift::SILDifferentiabilityWitnessKey; -template struct DenseMapInfo; +template struct DenseMapInfo; template <> struct DenseMapInfo { static AutoDiffConfig getEmptyKey() { diff --git a/include/swift/Basic/Located.h b/include/swift/Basic/Located.h index 6b3430b365124..f9f5b2296456f 100644 --- a/include/swift/Basic/Located.h +++ b/include/swift/Basic/Located.h @@ -55,7 +55,7 @@ bool operator ==(const Located &lhs, const Located &rhs) { namespace llvm { -template struct DenseMapInfo; +template struct DenseMapInfo; template struct DenseMapInfo> { diff --git a/include/swift/Basic/SourceLoc.h b/include/swift/Basic/SourceLoc.h index c638e50ee72e2..1ed9ae2b12c36 100644 --- a/include/swift/Basic/SourceLoc.h +++ b/include/swift/Basic/SourceLoc.h @@ -246,7 +246,7 @@ class CharSourceRange { } // end namespace swift namespace llvm { -template struct DenseMapInfo; +template struct DenseMapInfo; template <> struct DenseMapInfo { static swift::SourceLoc getEmptyKey() { From 52d13bdfa9b643516ecb6e6c720207ba841cd959 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 18 Nov 2021 21:55:45 +1000 Subject: [PATCH 017/491] [next] Update `UnivariateLinearPolyBase::getValue()` uses llvm-project 1ea4296208e61b1bd4e8a91bee9b5f56a0cfd526 removed `UnivariateLinearPolyBase::getValue()`. Use `getKnownMinValue()` instead. --- lib/IRGen/GenMeta.cpp | 2 +- lib/IRGen/GenProto.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index ba8a8ce6a341e..56f77a32f21a3 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -381,7 +381,7 @@ void IRGenModule::addVTableTypeMetadata( vis = VCallVisibility::VCallVisibilityLinkageUnit; } - auto relptrSize = DataLayout.getTypeAllocSize(Int32Ty).getValue(); + auto relptrSize = DataLayout.getTypeAllocSize(Int32Ty).getKnownMinValue(); setVCallVisibility(var, vis, std::make_pair(minOffset, maxOffset + relptrSize)); } diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index 7eed9cdcd4ca1..51c7d340042b0 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -2214,7 +2214,7 @@ static void addWTableTypeMetadata(IRGenModule &IGM, break; } - auto relptrSize = IGM.DataLayout.getTypeAllocSize(IGM.Int32Ty).getValue(); + auto relptrSize = IGM.DataLayout.getTypeAllocSize(IGM.Int32Ty).getKnownMinValue(); IGM.setVCallVisibility(global, vis, std::make_pair(minOffset, maxOffset + relptrSize)); } From 2df553cc02ff641b9b99a0b2d3fd4acb3de7e796 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 29 Nov 2021 09:05:22 -0800 Subject: [PATCH 018/491] arm64e: Update for LLVM ptr_auth intrinsics differences ptr_auth intrinsics are not polymorphic rather expect an int64 type. rdar://85583820 --- lib/IRGen/GenPointerAuth.cpp | 58 ++++++++++++++------------------ stdlib/public/core/PtrAuth.swift | 6 ++-- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/lib/IRGen/GenPointerAuth.cpp b/lib/IRGen/GenPointerAuth.cpp index df719af21a86d..386f24dc94646 100644 --- a/lib/IRGen/GenPointerAuth.cpp +++ b/lib/IRGen/GenPointerAuth.cpp @@ -39,7 +39,7 @@ getPointerAuthPair(IRGenFunction &IGF, const PointerAuthInfo &authInfo) { auto key = llvm::ConstantInt::get(IGF.IGM.Int32Ty, authInfo.getKey()); llvm::Value *discriminator = authInfo.getDiscriminator(); if (discriminator->getType()->isPointerTy()) { - discriminator = IGF.Builder.CreatePtrToInt(discriminator, IGF.IGM.IntPtrTy); + discriminator = IGF.Builder.CreatePtrToInt(discriminator, IGF.IGM.Int64Ty); } return { key, discriminator }; } @@ -47,23 +47,19 @@ getPointerAuthPair(IRGenFunction &IGF, const PointerAuthInfo &authInfo) { llvm::Value *irgen::emitPointerAuthBlend(IRGenFunction &IGF, llvm::Value *address, llvm::Value *other) { - address = IGF.Builder.CreatePtrToInt(address, IGF.IGM.IntPtrTy); - auto intrinsic = - llvm::Intrinsic::getDeclaration(&IGF.IGM.Module, - llvm::Intrinsic::ptrauth_blend, - { IGF.IGM.IntPtrTy }); + address = IGF.Builder.CreatePtrToInt(address, IGF.IGM.Int64Ty); + auto intrinsic = llvm::Intrinsic::getDeclaration( + &IGF.IGM.Module, llvm::Intrinsic::ptrauth_blend); return IGF.Builder.CreateCall(intrinsic, {address, other}); } llvm::Value *irgen::emitPointerAuthStrip(IRGenFunction &IGF, llvm::Value *fnPtr, unsigned Key) { - auto fnVal = IGF.Builder.CreatePtrToInt(fnPtr, IGF.IGM.IntPtrTy); + auto fnVal = IGF.Builder.CreatePtrToInt(fnPtr, IGF.IGM.Int64Ty); auto keyArg = llvm::ConstantInt::get(IGF.IGM.Int32Ty, Key); - auto intrinsic = - llvm::Intrinsic::getDeclaration(&IGF.IGM.Module, - llvm::Intrinsic::ptrauth_strip, - { IGF.IGM.IntPtrTy }); + auto intrinsic = llvm::Intrinsic::getDeclaration( + &IGF.IGM.Module, llvm::Intrinsic::ptrauth_strip); auto strippedPtr = IGF.Builder.CreateCall(intrinsic, {fnVal, keyArg}); return IGF.Builder.CreateIntToPtr(strippedPtr, fnPtr->getType()); } @@ -96,15 +92,13 @@ llvm::Value *irgen::emitPointerAuthResign(IRGenFunction &IGF, // Otherwise, auth and resign it. auto origTy = fnPtr->getType(); - fnPtr = IGF.Builder.CreatePtrToInt(fnPtr, IGF.IGM.IntPtrTy); + fnPtr = IGF.Builder.CreatePtrToInt(fnPtr, IGF.IGM.Int64Ty); auto oldPair = getPointerAuthPair(IGF, oldAuthInfo); auto newPair = getPointerAuthPair(IGF, newAuthInfo); - auto intrinsic = - llvm::Intrinsic::getDeclaration(&IGF.IGM.Module, - llvm::Intrinsic::ptrauth_resign, - { IGF.IGM.IntPtrTy }); + auto intrinsic = llvm::Intrinsic::getDeclaration( + &IGF.IGM.Module, llvm::Intrinsic::ptrauth_resign); llvm::Value *args[] = { fnPtr, oldPair.first, oldPair.second, newPair.first, newPair.second }; @@ -115,14 +109,12 @@ llvm::Value *irgen::emitPointerAuthResign(IRGenFunction &IGF, llvm::Value *irgen::emitPointerAuthAuth(IRGenFunction &IGF, llvm::Value *fnPtr, const PointerAuthInfo &oldAuthInfo) { auto origTy = fnPtr->getType(); - fnPtr = IGF.Builder.CreatePtrToInt(fnPtr, IGF.IGM.IntPtrTy); + fnPtr = IGF.Builder.CreatePtrToInt(fnPtr, IGF.IGM.Int64Ty); auto oldPair = getPointerAuthPair(IGF, oldAuthInfo); - auto intrinsic = - llvm::Intrinsic::getDeclaration(&IGF.IGM.Module, - llvm::Intrinsic::ptrauth_auth, - { IGF.IGM.IntPtrTy }); + auto intrinsic = llvm::Intrinsic::getDeclaration( + &IGF.IGM.Module, llvm::Intrinsic::ptrauth_auth); llvm::Value *args[] = { fnPtr, oldPair.first, oldPair.second }; @@ -151,14 +143,12 @@ llvm::Value *irgen::emitPointerAuthSign(IRGenFunction &IGF, llvm::Value *fnPtr, } auto origTy = fnPtr->getType(); - fnPtr = IGF.Builder.CreatePtrToInt(fnPtr, IGF.IGM.IntPtrTy); + fnPtr = IGF.Builder.CreatePtrToInt(fnPtr, IGF.IGM.Int64Ty); auto newPair = getPointerAuthPair(IGF, newAuthInfo); - auto intrinsic = - llvm::Intrinsic::getDeclaration(&IGF.IGM.Module, - llvm::Intrinsic::ptrauth_sign, - { IGF.IGM.IntPtrTy }); + auto intrinsic = llvm::Intrinsic::getDeclaration( + &IGF.IGM.Module, llvm::Intrinsic::ptrauth_sign); llvm::Value *args[] = { fnPtr, newPair.first, newPair.second }; @@ -246,7 +236,7 @@ PointerAuthInfo PointerAuthInfo::emit(IRGenFunction &IGF, discriminator = emitPointerAuthBlend(IGF, storageAddress, discriminator); } else { discriminator = - IGF.Builder.CreatePtrToInt(storageAddress, IGF.IGM.IntPtrTy); + IGF.Builder.CreatePtrToInt(storageAddress, IGF.IGM.Int64Ty); } } @@ -260,7 +250,7 @@ PointerAuthInfo::getOtherDiscriminator(IRGenModule &IGM, assert(schema); switch (schema.getOtherDiscrimination()) { case PointerAuthSchema::Discrimination::None: - return llvm::ConstantInt::get(IGM.IntPtrTy, 0); + return llvm::ConstantInt::get(IGM.Int64Ty, 0); case PointerAuthSchema::Discrimination::Decl: return entity.getDeclDiscriminator(IGM); @@ -269,7 +259,7 @@ PointerAuthInfo::getOtherDiscriminator(IRGenModule &IGM, return entity.getTypeDiscriminator(IGM); case PointerAuthSchema::Discrimination::Constant: - return llvm::ConstantInt::get(IGM.IntPtrTy, + return llvm::ConstantInt::get(IGM.Int64Ty, schema.getConstantDiscrimination()); } llvm_unreachable("bad kind"); @@ -278,7 +268,7 @@ PointerAuthInfo::getOtherDiscriminator(IRGenModule &IGM, static llvm::ConstantInt *getDiscriminatorForHash(IRGenModule &IGM, uint64_t rawHash) { uint16_t reducedHash = (rawHash % 0xFFFF) + 1; - return IGM.getSize(Size(reducedHash)); + return llvm::ConstantInt::get(IGM.Int64Ty, reducedHash); } static llvm::ConstantInt *getDiscriminatorForString(IRGenModule &IGM, @@ -347,7 +337,8 @@ PointerAuthEntity::getDeclDiscriminator(IRGenModule &IGM) const { llvm_unreachable("bad kind"); }; auto specialKind = Storage.get(StoredKind); - return IGM.getSize(Size(getSpecialDiscriminator(specialKind))); + return llvm::ConstantInt::get(IGM.Int64Ty, + getSpecialDiscriminator(specialKind)); } case Kind::ValueWitness: { @@ -367,7 +358,8 @@ PointerAuthEntity::getDeclDiscriminator(IRGenModule &IGM) const { llvm_unreachable("bad kind"); }; auto witness = Storage.get(StoredKind); - return IGM.getSize(Size(getValueWitnessDiscriminator(witness))); + return llvm::ConstantInt::get(IGM.Int64Ty, + getValueWitnessDiscriminator(witness)); } case Kind::AssociatedType: { @@ -694,5 +686,5 @@ void ConstantAggregateBuilderBase::addSignedPointer(llvm::Constant *pointer, return add(pointer); addSignedPointer(pointer, schema.getKey(), schema.isAddressDiscriminated(), - llvm::ConstantInt::get(IGM().IntPtrTy, otherDiscriminator)); + llvm::ConstantInt::get(IGM().Int64Ty, otherDiscriminator)); } diff --git a/stdlib/public/core/PtrAuth.swift b/stdlib/public/core/PtrAuth.swift index f2beaebc3a736..64a7446a35e0f 100644 --- a/stdlib/public/core/PtrAuth.swift +++ b/stdlib/public/core/PtrAuth.swift @@ -89,7 +89,7 @@ internal enum _PtrAuth { @_transparent static func blend(pointer: UnsafeRawPointer, discriminator: UInt64) -> UInt64 { - return UInt64(Builtin.int_ptrauth_blend_Int64( + return UInt64(Builtin.int_ptrauth_blend( UInt64(UInt(bitPattern: pointer))._value, discriminator._value)) } @@ -99,7 +99,7 @@ internal enum _PtrAuth { static func sign(pointer: UnsafeRawPointer, key: Key, discriminator: UInt64) -> UnsafeRawPointer { - let bitPattern = UInt64(Builtin.int_ptrauth_sign_Int64( + let bitPattern = UInt64(Builtin.int_ptrauth_sign( UInt64(UInt(bitPattern: pointer))._value, key._value._value, discriminator._value)) @@ -115,7 +115,7 @@ internal enum _PtrAuth { oldDiscriminator: UInt64, newKey: Key, newDiscriminator: UInt64) -> UnsafeRawPointer { - let bitPattern = UInt64(Builtin.int_ptrauth_resign_Int64( + let bitPattern = UInt64(Builtin.int_ptrauth_resign( UInt64(UInt(bitPattern: pointer))._value, oldKey._value._value, oldDiscriminator._value, From 66ce0ee9012dd3ac808b14916327180c0257918f Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 29 Nov 2021 14:00:44 -0800 Subject: [PATCH 019/491] Fix tests --- test/IRGen/async/get_async_continuation.sil | 8 ++++---- test/IRGen/async/hop_to_executor.sil | 2 +- test/IRGen/class_resilience.swift | 4 ++-- test/IRGen/enum_resilience.swift | 14 +++++++------- test/IRGen/lifetime.sil | 10 +++++----- test/IRGen/opaque_values_irgen.sil | 2 +- test/IRGen/protocol_resilience_thunks.swift | 16 ++++++++-------- test/IRGen/ptrauth-blocks.sil | 4 ++-- test/IRGen/ptrauth-builtins.sil | 16 ++++++++-------- test/IRGen/ptrauth-class-methods.sil | 6 +++--- test/IRGen/ptrauth-classes.sil | 2 +- test/IRGen/ptrauth-dynamic_replaceable.sil | 4 ++-- ...rauth-dynamic_replaceable_opaque_return.swift | 2 +- test/IRGen/ptrauth-partial-apply.sil | 12 ++++++------ test/IRGen/ptrauth-protocols.sil | 2 +- test/IRGen/ptrauth-value-witnesses.sil | 12 ++++++------ test/IRGen/simple_partial_apply.sil | 4 ++-- 17 files changed, 60 insertions(+), 60 deletions(-) diff --git a/test/IRGen/async/get_async_continuation.sil b/test/IRGen/async/get_async_continuation.sil index 11794c0dfe125..0d4f71d10b049 100644 --- a/test/IRGen/async/get_async_continuation.sil +++ b/test/IRGen/async/get_async_continuation.sil @@ -27,9 +27,9 @@ bb0: // CHECK: [[context_addr:%.*]] = getelementptr inbounds %swift.context, %swift.context* [[base_context]], i32 0, i32 0 // CHECK: [[ctxt:%.*]] = load %swift.context*, %swift.context** [[ctxt_addr]] // CHECK-arm64e: [[ctxt_addr_int:%[0-9]+]] = ptrtoint %swift.context** [[context_addr]] to i64 -// CHECK-arm64e: [[ptrauth_blend:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ctxt_addr_int]], i64 48546) +// CHECK-arm64e: [[ptrauth_blend:%[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 [[ctxt_addr_int]], i64 48546) // CHECK-arm64e: [[ctxt_int:%[0-9]+]] = ptrtoint %swift.context* [[ctxt]] to i64 -// CHECK-arm64e: [[signed_int:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[ctxt_int]], i32 2, i64 [[ptrauth_blend]]) +// CHECK-arm64e: [[signed_int:%[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 [[ctxt_int]], i32 2, i64 [[ptrauth_blend]]) // CHECK-arm64e: [[signed_ctxt:%[0-9]+]] = inttoptr i64 [[signed_int]] to %swift.context* // CHECK-arm64e: store %swift.context* [[signed_ctxt]], %swift.context** [[context_addr]] // CHECK-x86_64: store %swift.context* [[ctxt]], %swift.context** [[context_addr]] @@ -44,9 +44,9 @@ bb0: // CHECK: [[continuation_fn_addr:%.*]] = getelementptr inbounds %swift.context, %swift.context* [[base_context]], i32 0, i32 1 // CHECK: [[continuation_fn:%.*]] = bitcast i8* [[resume_intrinsic]] to void (%swift.context*)* // CHECK-arm64e: [[continuation_fn_addr_int:%[0-9]+]] = ptrtoint void (%swift.context*)** [[continuation_fn_addr]] to i64 -// CHECK-arm64e: [[ptrauth_blend:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[continuation_fn_addr_int]], i64 55047) +// CHECK-arm64e: [[ptrauth_blend:%[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 [[continuation_fn_addr_int]], i64 55047) // CHECK-arm64e: [[continuation_fn_int:%[0-9]+]] = ptrtoint void (%swift.context*)* [[continuation_fn]] to i64 -// CHECK-arm64e: [[signed_int:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[continuation_fn_int]], i32 0, i64 [[ptrauth_blend]]) +// CHECK-arm64e: [[signed_int:%[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 [[continuation_fn_int]], i32 0, i64 [[ptrauth_blend]]) // CHECK-arm64e: [[signed_continuation_fn:%[0-9]+]] = inttoptr i64 [[signed_int]] to void (%swift.context*)* // CHECK-arm64e: store void (%swift.context*)* [[signed_continuation_fn]], void (%swift.context*)** [[continuation_fn_addr]] // CHECK-x86_64: store void (%swift.context*)* [[continuation_fn]], void (%swift.context*)** [[continuation_fn_addr]] diff --git a/test/IRGen/async/hop_to_executor.sil b/test/IRGen/async/hop_to_executor.sil index f0d2adf4f8170..f3868d7342558 100644 --- a/test/IRGen/async/hop_to_executor.sil +++ b/test/IRGen/async/hop_to_executor.sil @@ -28,7 +28,7 @@ bb0(%0 : $Optional): // CHECK-LABEL: define internal swift{{(tail)?}}cc void @__swift_suspend_point // CHECK-SAME: (i8* [[RESUME_FN:%0]], [[INT]] %1, [[INT]] %2, %swift.context* [[CTXT:%[^,]+]]) // CHECK-arm64e: [[RESUME_FN_INT:%[^,]+]] = ptrtoint i8* [[RESUME_FN]] to i64 -// CHECK-arm64e: [[PTRAUTH_SIGN:%[^,]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[RESUME_FN_INT]], i32 0, i64 0) +// CHECK-arm64e: [[PTRAUTH_SIGN:%[^,]+]] = call i64 @llvm.ptrauth.sign(i64 [[RESUME_FN_INT]], i32 0, i64 0) // CHECK-arm64e: [[RESUME_FN:%[^,]+]] = inttoptr i64 [[PTRAUTH_SIGN]] to i8* // CHECK: {{(must)?}}tail call swift{{(tail)?}}cc void @swift_task_switch(%swift.context* swiftasync [[CTXT]], i8* [[RESUME_FN]], [[INT]] %1, [[INT]] %2) // CHECK: ret void diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift index 76886c0e6e83f..10fe5332edcce 100644 --- a/test/IRGen/class_resilience.swift +++ b/test/IRGen/class_resilience.swift @@ -563,7 +563,7 @@ public class ClassWithResilientThenEmpty { // CHECK-NEXT: [[VTABLE_OFFSET_ADDR:%.*]] = bitcast i8* [[VTABLE_OFFSET_TMP]] to i32 (%T16class_resilience14ResilientChildC*)** // CHECK-NEXT: [[METHOD:%.*]] = load i32 (%T16class_resilience14ResilientChildC*)*, i32 (%T16class_resilience14ResilientChildC*)** [[VTABLE_OFFSET_ADDR]] // CHECK-arm64e-NEXT: ptrtoint i32 (%T16class_resilience14ResilientChildC*)** [[VTABLE_OFFSET_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: [[RESULT:%.*]] = call swiftcc i32 [[METHOD]](%T16class_resilience14ResilientChildC* swiftself %0) // CHECK-NEXT: ret i32 [[RESULT]] @@ -579,7 +579,7 @@ public class ClassWithResilientThenEmpty { // CHECK-NEXT: [[VTABLE_OFFSET_ADDR:%.*]] = bitcast i8* [[VTABLE_OFFSET_TMP]] to void (i32, %T16class_resilience14ResilientChildC*)** // CHECK-NEXT: [[METHOD:%.*]] = load void (i32, %T16class_resilience14ResilientChildC*)*, void (i32, %T16class_resilience14ResilientChildC*)** [[VTABLE_OFFSET_ADDR]] // CHECK-arm64e-NEXT: ptrtoint void (i32, %T16class_resilience14ResilientChildC*)** [[VTABLE_OFFSET_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call swiftcc void [[METHOD]](i32 %0, %T16class_resilience14ResilientChildC* swiftself %1) // CHECK-NEXT: ret void diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift index 7c27e4021c2ef..bb729a8a1902f 100644 --- a/test/IRGen/enum_resilience.swift +++ b/test/IRGen/enum_resilience.swift @@ -101,7 +101,7 @@ public func functionWithResilientEnum(_ m: Medium) -> Medium { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]] // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* [[METADATA]]) // CHECK-NEXT: ret void @@ -121,7 +121,7 @@ public func functionWithIndirectResilientEnum(_ ia: IndirectApproach) -> Indirec // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]] // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* [[METADATA]]) // CHECK-NEXT: ret void @@ -143,7 +143,7 @@ public func constructResilientEnumNoPayload() -> Medium { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[WITNESS_FN:%.*]] = bitcast i8* [[WITNESS]] // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call void [[WITNESS_FN]](%swift.opaque* noalias %0, i32 [[TAG]], %swift.type* [[METADATA]]) // CHECK-NEXT: ret void @@ -169,14 +169,14 @@ public func constructResilientEnumPayload(_ s: Size) -> Medium { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]] to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias [[ENUM_STORAGE]], %swift.opaque* noalias %1, %swift.type* [[METADATA]]) // CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 4 // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[WITNESS_FN:%initializeWithTake]] = bitcast i8* [[WITNESS]] to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias %0, %swift.opaque* noalias [[ENUM_STORAGE]], %swift.type* [[METADATA]]) // CHECK-NEXT: [[TAG:%.*]] = load i32, i32* @"$s14resilient_enum6MediumO8PostcardyAC0A7_struct4SizeVcACmFWC" @@ -192,7 +192,7 @@ public func constructResilientEnumPayload(_ s: Size) -> Medium { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[WITNESS_FN:%destructiveInjectEnumTag]] = bitcast i8* [[WITNESS]] // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call void [[WITNESS_FN]](%swift.opaque* noalias %0, i32 [[TAG]], %swift.type* [[METADATA2]]) // CHECK-NEXT: [[STORAGE_ALLOCA:%.*]] = bitcast %swift.opaque* [[ENUM_STORAGE]] to i8* // CHECK-NEXT: call void @llvm.lifetime.end.p0i8({{(i32|i64)}} -1, i8* [[STORAGE_ALLOCA]]) @@ -348,7 +348,7 @@ extension ResilientMultiPayloadGenericEnum { // CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK: [[STORE_TAG:%.*]] = bitcast i8* {{%.+}} to void (%swift.opaque*, i32, i32, %swift.type*)* // CHECK-arm64e-NEXT: ptrtoint i8** {{.*}} to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call void [[STORE_TAG]](%swift.opaque* noalias [[BUFFER]], i32 1, i32 1, %swift.type* [[METADATA]]) // CHECK-NEXT: ret void // CHECK-NEXT: {{^}$}} diff --git a/test/IRGen/lifetime.sil b/test/IRGen/lifetime.sil index c1548218960bf..5349165113e23 100644 --- a/test/IRGen/lifetime.sil +++ b/test/IRGen/lifetime.sil @@ -33,14 +33,14 @@ bb0(%x : $*T): // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]], align // CHECK-NEXT: [[INIT_WITH_COPY_FN:%.*]] = bitcast i8* [[T4]] to [[OPAQUE]]* ([[OPAQUE]]*, [[OPAQUE]]*, [[TYPE]]*)* // CHECK-arm64e-NEXT: ptrtoint i8** [[T3]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: [[Y:%.*]] = call [[OPAQUE]]* [[INIT_WITH_COPY_FN]]([[OPAQUE]]* noalias [[Y_TMP]], [[OPAQUE]]* noalias [[X:%.*]], [[TYPE]]* %T) // Destroy 'y'. // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 1 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]], align // CHECK-NEXT: [[DESTROY_FN:%.*]] = bitcast i8* [[T4]] to void ([[OPAQUE]]*, [[TYPE]]*)* // CHECK-arm64e-NEXT: ptrtoint i8** [[T3]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call void [[DESTROY_FN]]([[OPAQUE]]* noalias [[Y_TMP]], [[TYPE]]* %T) // Destroy 'x'. // CHECK-NEXT: call void [[DESTROY_FN]]([[OPAQUE]]* noalias [[X]], [[TYPE]]* %T) @@ -76,21 +76,21 @@ bb0(%x : $*T): // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]], align // CHECK-NEXT: [[INIT_WITH_COPY_FN:%.*]] = bitcast i8* [[T4]] to [[OPAQUE]]* ([[OPAQUE]]*, [[OPAQUE]]*, [[TYPE]]*)* // CHECK-arm64e-NEXT: ptrtoint i8** [[T3]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: [[Y:%.*]] = call [[OPAQUE]]* [[INIT_WITH_COPY_FN]]([[OPAQUE]]* noalias [[Y_TMP]], [[OPAQUE]]* noalias [[X:%.*]], [[TYPE]]* %T) // Destroy 'y'. // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 1 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]], align // CHECK-NEXT: [[DESTROY_FN:%.*]] = bitcast i8* [[T4]] to void ([[OPAQUE]]*, [[TYPE]]*)* // CHECK-arm64e-NEXT: ptrtoint i8** [[T3]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call void [[DESTROY_FN]]([[OPAQUE]]* noalias [[Y_TMP]], [[TYPE]]* %T) // Copy 'x' into 'y' again, this time as a take. // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 4 // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]], align // CHECK-NEXT: [[TAKE_FN:%.*]] = bitcast i8* [[T4]] to [[OPAQUE]]* ([[OPAQUE]]*, [[OPAQUE]]*, [[TYPE]]*)* // CHECK-arm64e-NEXT: ptrtoint i8** [[T3]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call [[OPAQUE]]* [[TAKE_FN]]([[OPAQUE]]* noalias [[Y_TMP]], [[OPAQUE]]* noalias [[X]], [[TYPE]]* %T) // Destroy 'y'. // CHECK-NEXT: call void [[DESTROY_FN]]([[OPAQUE]]* noalias [[Y_TMP]], [[TYPE]]* %T) diff --git a/test/IRGen/opaque_values_irgen.sil b/test/IRGen/opaque_values_irgen.sil index 5ed4a8fd374d9..ba04dab44a17d 100644 --- a/test/IRGen/opaque_values_irgen.sil +++ b/test/IRGen/opaque_values_irgen.sil @@ -7,7 +7,7 @@ sil_stage canonical // CHECK: define hidden swiftcc void @f010_irgen_identity(%swift.opaque* noalias nocapture sret({{.*}}) %0, %swift.opaque* noalias nocapture %1, %swift.type* %T) // CHECK: entry: // CHECK-NOT: call -// CHECK-arm64e: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e: call i64 @llvm.ptrauth.blend // CHECK-NOT: call // CHECK: %{{.*}} = call %swift.opaque* %initializeWithTake(%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* %T) // CHECK-NOT: call diff --git a/test/IRGen/protocol_resilience_thunks.swift b/test/IRGen/protocol_resilience_thunks.swift index 39a85cfb4a210..c7eec8338bea1 100644 --- a/test/IRGen/protocol_resilience_thunks.swift +++ b/test/IRGen/protocol_resilience_thunks.swift @@ -43,7 +43,7 @@ public protocol MyResilientProtocol { // CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_GEP]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[WITNESS]] to void (i1, %swift.opaque*, %swift.type*, i8**)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_GEP]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call swiftcc void [[FN]](i1 %0, %swift.opaque* noalias nocapture swiftself %1, %swift.type* %2, i8** %3) // CHECK-NEXT: ret void @@ -52,7 +52,7 @@ public protocol MyResilientProtocol { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[WITNESS]] to i1 (%swift.opaque*, %swift.type*, i8**)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: [[RESULT:%.*]] = call swiftcc i1 [[FN]](%swift.opaque* noalias nocapture swiftself %0, %swift.type* %1, i8** %2) // CHECK-NEXT: ret i1 [[RESULT]] @@ -61,7 +61,7 @@ public protocol MyResilientProtocol { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[WITNESS]] to void (%Any*, %swift.opaque*, %swift.type*, i8**)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call swiftcc void [[FN]](%Any* noalias nocapture sret({{.*}}) %0, %swift.opaque* noalias nocapture swiftself %1, %swift.type* %2, i8** %3) // CHECK-NEXT: ret void @@ -70,7 +70,7 @@ public protocol MyResilientProtocol { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[WITNESS]] to void (%swift.opaque*, %swift.error**, %swift.type*, i8**)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call swiftcc void [[FN]](%swift.opaque* noalias nocapture swiftself %0, %swift.error**{{( noalias nocapture( swifterror)? dereferenceable\(.\))?}} %1, %swift.type* %2, i8** %3) // CHECK-NEXT: ret void @@ -79,7 +79,7 @@ public protocol MyResilientProtocol { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[WITNESS]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, %swift.opaque*, %swift.type*, i8**)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call swiftcc void [[FN]](%swift.opaque* noalias nocapture sret({{.*}}) %0, %swift.opaque* noalias nocapture %1, %swift.type* %2, %swift.opaque* noalias nocapture swiftself %3, %swift.type* %4, i8** %5) // CHECK-NEXT: ret void @@ -88,7 +88,7 @@ public protocol MyResilientProtocol { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[WITNESS]] to i1 (%swift.opaque*, %swift.type*, i8**)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: [[RESULT:%.*]] = call swiftcc i1 %5(%swift.opaque* noalias nocapture swiftself %0, %swift.type* %1, i8** %2) // CHECK-NEXT: ret i1 [[RESULT]] @@ -97,7 +97,7 @@ public protocol MyResilientProtocol { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[WITNESS]] to void (i1, %swift.opaque*, %swift.type*, i8**)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: call swiftcc void [[FN]](i1 %0, %swift.opaque* nocapture swiftself %1, %swift.type* %2, i8** %3) // CHECK-NEXT: ret void @@ -106,6 +106,6 @@ public protocol MyResilientProtocol { // CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]] // CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[WITNESS]] to { i8*, %TSb* } (i8*, %swift.opaque*, %swift.type*, i8**)* // CHECK-arm64e-NEXT: ptrtoint i8** [[WITNESS_ADDR]] to i64 -// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend.i64 +// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend // CHECK-NEXT: [[RESULT:%.*]] = call swiftcc { i8*, %TSb* } [[FN]](i8* noalias dereferenceable({{16|32}}) %0, %swift.opaque* nocapture swiftself %1, %swift.type* %2, i8** %3) // CHECK-NEXT: ret { i8*, %TSb* } [[RESULT]] diff --git a/test/IRGen/ptrauth-blocks.sil b/test/IRGen/ptrauth-blocks.sil index fa2ce0b38aeef..a95d3f372db15 100644 --- a/test/IRGen/ptrauth-blocks.sil +++ b/test/IRGen/ptrauth-blocks.sil @@ -23,7 +23,7 @@ entry(%0 : $*@block_storage Builtin.RawPointer): // CHECK: [[HEADER:%.*]] = getelementptr inbounds { %objc_block, i8* }, { %objc_block, i8* }* %0, i32 0, i32 0 // CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* [[HEADER]], i32 0, i32 3 // CHECK: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign.i64(i64 ptrtoint (void (void (...)*)* @invoke_trivial to i64), i32 0, i64 [[T0]]) +// CHECK: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (void (void (...)*)* @invoke_trivial to i64), i32 0, i64 [[T0]]) // CHECK: [[T0:%.*]] = inttoptr i64 [[SIGNED]] to i8* // CHECK: store i8* [[T0]], i8** [[SLOT]], // CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* [[HEADER]], i32 0, i32 4 @@ -45,7 +45,7 @@ entry(%0 : $*@block_storage Builtin.NativeObject): // CHECK: [[HEADER:%.*]] = getelementptr inbounds { %objc_block, %swift.refcounted* }, { %objc_block, %swift.refcounted* }* %0, i32 0, i32 0 // CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* [[HEADER]], i32 0, i32 3 // CHECK: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign.i64(i64 ptrtoint (void (void (...)*)* @invoke_nontrivial to i64), i32 0, i64 [[T0]]) +// CHECK: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (void (void (...)*)* @invoke_nontrivial to i64), i32 0, i64 [[T0]]) // CHECK: [[T0:%.*]] = inttoptr i64 [[SIGNED]] to i8* // CHECK: store i8* [[T0]], i8** [[SLOT]], // CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* [[HEADER]], i32 0, i32 4 diff --git a/test/IRGen/ptrauth-builtins.sil b/test/IRGen/ptrauth-builtins.sil index a54cafe149755..dfa2c90e5cb4a 100644 --- a/test/IRGen/ptrauth-builtins.sil +++ b/test/IRGen/ptrauth-builtins.sil @@ -5,12 +5,12 @@ import Builtin sil @test_strip : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 { bb0(%ptr : $Builtin.Int64): %key = integer_literal $Builtin.Int32, 0 - %result = builtin "int_ptrauth_strip_Int64"(%ptr : $Builtin.Int64, %key : $Builtin.Int32) : $Builtin.Int64 + %result = builtin "int_ptrauth_strip"(%ptr : $Builtin.Int64, %key : $Builtin.Int32) : $Builtin.Int64 return %result : $Builtin.Int64 } // CHECK-LABEL: define{{ protected | dllexport | }}swiftcc i64 @test_strip(i64 %0) // CHECK: entry: -// CHECK-ptrauth-NEXT: %1 = call i64 @llvm.ptrauth.strip.i64(i64 %0, i32 0) +// CHECK-ptrauth-NEXT: %1 = call i64 @llvm.ptrauth.strip(i64 %0, i32 0) // CHECK-ptrauth-NEXT: ret i64 %1 // CHECK-noptrauth-NEXT: ret i64 %0 // CHECK-NEXT: } @@ -18,12 +18,12 @@ bb0(%ptr : $Builtin.Int64): sil @test_sign : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64 { bb0(%ptr : $Builtin.Int64, %disc : $Builtin.Int64): %key = integer_literal $Builtin.Int32, 0 - %result = builtin "int_ptrauth_sign_Int64"(%ptr : $Builtin.Int64, %key : $Builtin.Int32, %disc : $Builtin.Int64) : $Builtin.Int64 + %result = builtin "int_ptrauth_sign"(%ptr : $Builtin.Int64, %key : $Builtin.Int32, %disc : $Builtin.Int64) : $Builtin.Int64 return %result : $Builtin.Int64 } // CHECK-LABEL: define{{ protected | dllexport | }}swiftcc i64 @test_sign(i64 %0, i64 %1) // CHECK: entry: -// CHECK-ptrauth-NEXT: %2 = call i64 @llvm.ptrauth.sign.i64(i64 %0, i32 0, i64 %1) +// CHECK-ptrauth-NEXT: %2 = call i64 @llvm.ptrauth.sign(i64 %0, i32 0, i64 %1) // CHECK-ptrauth-NEXT: ret i64 %2 // CHECK-noptrauth-NEXT: ret i64 %0 // CHECK-NEXT: } @@ -31,12 +31,12 @@ bb0(%ptr : $Builtin.Int64, %disc : $Builtin.Int64): sil @test_auth : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64 { bb0(%ptr : $Builtin.Int64, %disc : $Builtin.Int64): %key = integer_literal $Builtin.Int32, 0 - %result = builtin "int_ptrauth_auth_Int64"(%ptr : $Builtin.Int64, %key : $Builtin.Int32, %disc : $Builtin.Int64) : $Builtin.Int64 + %result = builtin "int_ptrauth_auth"(%ptr : $Builtin.Int64, %key : $Builtin.Int32, %disc : $Builtin.Int64) : $Builtin.Int64 return %result : $Builtin.Int64 } // CHECK-LABEL: define{{ protected | dllexport | }}swiftcc i64 @test_auth(i64 %0, i64 %1) // CHECK: entry: -// CHECK-ptrauth-NEXT: %2 = call i64 @llvm.ptrauth.auth.i64(i64 %0, i32 0, i64 %1) +// CHECK-ptrauth-NEXT: %2 = call i64 @llvm.ptrauth.auth(i64 %0, i32 0, i64 %1) // CHECK-ptrauth-NEXT: ret i64 %2 // CHECK-noptrauth-NEXT: ret i64 %0 // CHECK-NEXT: } @@ -44,12 +44,12 @@ bb0(%ptr : $Builtin.Int64, %disc : $Builtin.Int64): sil @test_resign : $@convention(thin) (Builtin.Int64, Builtin.Int64, Builtin.Int64) -> Builtin.Int64 { bb0(%ptr : $Builtin.Int64, %oldDisc : $Builtin.Int64, %newDisc : $Builtin.Int64): %key = integer_literal $Builtin.Int32, 0 - %result = builtin "int_ptrauth_resign_Int64"(%ptr : $Builtin.Int64, %key : $Builtin.Int32, %oldDisc : $Builtin.Int64, %key : $Builtin.Int32, %newDisc : $Builtin.Int64) : $Builtin.Int64 + %result = builtin "int_ptrauth_resign"(%ptr : $Builtin.Int64, %key : $Builtin.Int32, %oldDisc : $Builtin.Int64, %key : $Builtin.Int32, %newDisc : $Builtin.Int64) : $Builtin.Int64 return %result : $Builtin.Int64 } // CHECK-LABEL: define{{ protected | dllexport | }}swiftcc i64 @test_resign(i64 %0, i64 %1, i64 %2) // CHECK: entry: -// CHECK-ptrauth-NEXT: %3 = call i64 @llvm.ptrauth.resign.i64(i64 %0, i32 0, i64 %1, i32 0, i64 %2) +// CHECK-ptrauth-NEXT: %3 = call i64 @llvm.ptrauth.resign(i64 %0, i32 0, i64 %1, i32 0, i64 %2) // CHECK-ptrauth-NEXT: ret i64 %3 // CHECK-noptrauth-NEXT: ret i64 %0 // CHECK-NEXT: } diff --git a/test/IRGen/ptrauth-class-methods.sil b/test/IRGen/ptrauth-class-methods.sil index a239202155beb..5a871c68e2b5d 100644 --- a/test/IRGen/ptrauth-class-methods.sil +++ b/test/IRGen/ptrauth-class-methods.sil @@ -61,7 +61,7 @@ bb0(%0 : $A): // CHECK-NEXT: [[FN:%.*]] = load void (%T4test1AC*)*, void (%T4test1AC*)** [[SLOT]] // CHECK-NEXT: [[T0:%.*]] = ptrtoint void (%T4test1AC*)** [[SLOT]] to i64 // Discriminator value is arbitrary, but must be the same as the next test. -// CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 23008) +// CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 23008) // CHECK-NEXT: call swiftcc void [[FN]](%T4test1AC* swiftself %0) [ "ptrauth"(i32 0, i64 [[DISCRIMINATOR]]) ] // CHECK-NEXT: ret void @@ -79,7 +79,7 @@ bb0(%0 : $B): // CHECK-NEXT: [[FN:%.*]] = load void (%T4test1BC*)*, void (%T4test1BC*)** [[SLOT]] // CHECK-NEXT: [[T0:%.*]] = ptrtoint void (%T4test1BC*)** [[SLOT]] to i64 // Discriminator value is arbitrary, but must be the same as the previous test. -// CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 23008) +// CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 23008) // CHECK-NEXT: call swiftcc void [[FN]](%T4test1BC* swiftself %0) [ "ptrauth"(i32 0, i64 [[DISCRIMINATOR]]) ] // CHECK-NEXT: ret void @@ -98,6 +98,6 @@ bb0(%0 : $G): // CHECK-NEXT: [[FN:%.*]] = load void (%T4test1GC*)*, void (%T4test1GC*)** [[SLOT]] // CHECK-NEXT: [[T0:%.*]] = ptrtoint void (%T4test1GC*)** [[SLOT]] to i64 // Discriminator value is arbitrary, but must be the same as the previous test. -// CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 47035) +// CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 47035) // CHECK-NEXT: call swiftcc void [[FN]](%T4test1GC* swiftself %0) [ "ptrauth"(i32 0, i64 [[DISCRIMINATOR]]) ] // CHECK-NEXT: ret void diff --git a/test/IRGen/ptrauth-classes.sil b/test/IRGen/ptrauth-classes.sil index e97f71f290e71..d4ce0bbeb2876 100644 --- a/test/IRGen/ptrauth-classes.sil +++ b/test/IRGen/ptrauth-classes.sil @@ -15,7 +15,7 @@ sil_vtable B {} // CHECK-LABEL: define internal %swift.type* @"$s4test1ACMi"(%swift.type_descriptor* %0, i8** %1, i8* %2) // CHECK: [[INT:%.*]] = ptrtoint %swift.type_descriptor* %0 to i64 -// CHECK: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign.i64(i64 [[INT]], i32 2, i64 44678) +// CHECK: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[INT]], i32 2, i64 44678) // CHECK: [[PTR:%.*]] = inttoptr i64 [[SIGNED]] to %swift.type_descriptor* // CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* [[PTR]], i8** %1, i8* %2) // CHECK: ret %swift.type* [[METADATA]] diff --git a/test/IRGen/ptrauth-dynamic_replaceable.sil b/test/IRGen/ptrauth-dynamic_replaceable.sil index c588977888bb8..7e21c444eb6ff 100644 --- a/test/IRGen/ptrauth-dynamic_replaceable.sil +++ b/test/IRGen/ptrauth-dynamic_replaceable.sil @@ -39,7 +39,7 @@ // CHECK-NEXT: br i1 [[CMP]], label %original_entry, label %forward_to_replaced // CHECK: forward_to_replaced: // CHECK-NEXT: [[TYPED_PTR:%.*]] = bitcast i8* [[FUN_PTR]] to void ()* -// CHECK-NEXT: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 ptrtoint (%swift.dyn_repl_link_entry* @test_dynamically_replaceableTX to i64), i64 679) +// CHECK-NEXT: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (%swift.dyn_repl_link_entry* @test_dynamically_replaceableTX to i64), i64 679) // CHECK-NEXT: tail call swiftcc void [[TYPED_PTR]]() [ "ptrauth"(i32 0, i64 [[BLEND]]) ] // CHECK-NEXT: ret void // CHECK: original_entry: @@ -63,7 +63,7 @@ bb0: // CHECK: entry: // CHECK: [[FUN_PTR:%.*]] = call i8* @swift_getOrigOfReplaceable{{.*}}({{.*}} getelementptr {{.*}} @test_replacementTX, i32 0, i32 0 // CHECK: [[TYPED_PTR:%.*]] = bitcast i8* [[FUN_PTR]] to void ()* -// CHECK-NEXT: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 ptrtoint (%swift.dyn_repl_link_entry* @test_replacementTX to i64), i64 679) +// CHECK-NEXT: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (%swift.dyn_repl_link_entry* @test_replacementTX to i64), i64 679) // CHECK-NEXT: call swiftcc void [[TYPED_PTR]]() [ "ptrauth"(i32 0, i64 [[BLEND]]) ] // CHECK: ret void // CHECK: } diff --git a/test/IRGen/ptrauth-dynamic_replaceable_opaque_return.swift b/test/IRGen/ptrauth-dynamic_replaceable_opaque_return.swift index 7001e34dd9d3b..5ad3b90eaa811 100644 --- a/test/IRGen/ptrauth-dynamic_replaceable_opaque_return.swift +++ b/test/IRGen/ptrauth-dynamic_replaceable_opaque_return.swift @@ -26,7 +26,7 @@ extension Int: P { // CHECK: entry: // CHECK: %0 = load i8*, i8** getelementptr inbounds (%swift.dyn_repl_link_entry, %swift.dyn_repl_link_entry* @"$s1A3baryQrSiFQOMk", i32 0, i32 0) // CHECK: %1 = bitcast i8* %0 to %swift.type_descriptor* ()* -// CHECK: %2 = call i64 @llvm.ptrauth.blend.i64(i64 ptrtoint (%swift.dyn_repl_link_entry* @"$s1A3baryQrSiFQOMk" to i64), i64 44678) +// CHECK: %2 = call i64 @llvm.ptrauth.blend(i64 ptrtoint (%swift.dyn_repl_link_entry* @"$s1A3baryQrSiFQOMk" to i64), i64 44678) // CHECK: %3 = tail call swiftcc %swift.type_descriptor* %1() [ "ptrauth"(i32 0, i64 %2) ] // CHECK: ret %swift.type_descriptor* %3 // CHECK: } diff --git a/test/IRGen/ptrauth-partial-apply.sil b/test/IRGen/ptrauth-partial-apply.sil index ed2c59eecf25f..3f1db37f783e6 100644 --- a/test/IRGen/ptrauth-partial-apply.sil +++ b/test/IRGen/ptrauth-partial-apply.sil @@ -18,9 +18,9 @@ bb0(%0 : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> (), %1 : $Builtin. // CHECK: [[CTXT:%.*]] = bitcast %swift.refcounted* [[ALLOC]] to [[CTXT_TY:<{ %swift.refcounted, i32, i32, i8\* }>]]* // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[CTXT_TY]], [[CTXT_TY]]* [[CTXT]], i32 0, i32 3 // CHECK: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 7185) +// CHECK: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 7185) // CHECK: [[T0:%.*]] = ptrtoint void (i32, i32)* [[FN]] to i64 -// CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.resign.i64(i64 [[T0]], i32 0, i64 {{.*}}, i32 1, i64 [[DISC]]) +// CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 0, i64 {{.*}}, i32 1, i64 [[DISC]]) // CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to void (i32, i32)* // CHECK: [[T3:%.*]] = bitcast void (i32, i32)* [[T2]] to i8* // CHECK: store i8* [[T3]], i8** [[SLOT]], align 8 @@ -31,7 +31,7 @@ bb0(%0 : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> (), %1 : $Builtin. // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[CTXT_TY]], [[CTXT_TY]]* [[T0]], i32 0, i32 3 // CHECK: [[T0:%.*]] = load i8*, i8** [[SLOT]], align 8 // CHECK: [[T1:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T1]], i64 7185) +// CHECK: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T1]], i64 7185) // CHECK: [[FN:%.*]] = bitcast i8* [[T0]] to void (i32, i32)* // CHECK: call swiftcc void [[FN]](i32 {{.*}}, i32 {{.*}}) [ "ptrauth"(i32 1, i64 [[DISC]]) ] @@ -46,9 +46,9 @@ bb0(%0 : $@callee_owned (Builtin.Int32, Builtin.Int32) -> (), %1 : $Builtin.Int3 // CHECK: [[CTXT:%.*]] = bitcast %swift.refcounted* [[ALLOC]] to [[CTXT_TY:<{ %swift.refcounted, i32, i32, %swift.refcounted\*, i8\* }>]]* // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[CTXT_TY]], [[CTXT_TY]]* {{%.*}}, i32 0, i32 4 // CHECK: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 7185) +// CHECK: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 7185) // CHECK: [[T0:%.*]] = ptrtoint void (i32, i32, %swift.refcounted*)* [[FN]] to i64 -// CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.resign.i64(i64 [[T0]], i32 0, i64 {{.*}}, i32 1, i64 [[DISC]]) +// CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 0, i64 {{.*}}, i32 1, i64 [[DISC]]) // CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to void (i32, i32, %swift.refcounted*)* // CHECK: [[T3:%.*]] = bitcast void (i32, i32, %swift.refcounted*)* [[T2]] to i8* // CHECK: store i8* [[T3]], i8** [[SLOT]], align 8 @@ -59,6 +59,6 @@ bb0(%0 : $@callee_owned (Builtin.Int32, Builtin.Int32) -> (), %1 : $Builtin.Int3 // CHECK: [[SLOT:%.*]] = getelementptr inbounds <{ %swift.refcounted, i32, i32, %swift.refcounted*, i8* }>, <{ %swift.refcounted, i32, i32, %swift.refcounted*, i8* }>* [[T0]], i32 0, i32 4 // CHECK: [[T0:%.*]] = load i8*, i8** [[SLOT]], align 8 // CHECK: [[T1:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T1]], i64 7185) +// CHECK: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T1]], i64 7185) // CHECK: [[FN:%.*]] = bitcast i8* [[T0]] to void (i32, i32, %swift.refcounted*)* // CHECK: call swiftcc void [[FN]](i32 {{.*}}, i32 {{.*}}, %swift.refcounted* {{.*}}) [ "ptrauth"(i32 1, i64 [[DISC]]) ] diff --git a/test/IRGen/ptrauth-protocols.sil b/test/IRGen/ptrauth-protocols.sil index 91e3affc3d1ad..c697dc99f5827 100644 --- a/test/IRGen/ptrauth-protocols.sil +++ b/test/IRGen/ptrauth-protocols.sil @@ -79,7 +79,7 @@ bb0: // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]], align 8 // CHECK-NEXT: [[FOO:%.*]] = bitcast i8* [[T1]] to void (%swift.type*, %swift.type*, i8**)* // CHECK-NEXT: [[T1:%.*]] = ptrtoint i8** [[T0]] to i64 -// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T1]], i64 53700) +// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T1]], i64 53700) // TODO: be smart about this and do a complete-metadata fetch in the first place // CHECK-NEXT: [[ASSOC_RESPONSE:%.*]] = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 0, %swift.type* [[T_ASSOC]]) // CHECK-NEXT: [[ASSOC:%.*]] = extractvalue %swift.metadata_response [[ASSOC_RESPONSE]], 0 diff --git a/test/IRGen/ptrauth-value-witnesses.sil b/test/IRGen/ptrauth-value-witnesses.sil index e297ec4d0fc35..58c3cbeea6b42 100644 --- a/test/IRGen/ptrauth-value-witnesses.sil +++ b/test/IRGen/ptrauth-value-witnesses.sil @@ -27,7 +27,7 @@ bb0(%0 : $*T): // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align // CHECK-NEXT: [[WITNESS:%.*]] = bitcast i8* [[T0]] to // CHECK-NEXT: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 1272) +// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 1272) // CHECK-NEXT: call void [[WITNESS]](%swift.opaque* noalias %0, %swift.type* %T) {{#[0-9]+}} [ "ptrauth"(i32 0, i64 [[DISC]]) ] // CHECK-NEXT: ret void @@ -43,7 +43,7 @@ bb0(%0 : $*T, %1 : $*T): // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align // CHECK-NEXT: [[WITNESS:%.*]] = bitcast i8* [[T0]] to // CHECK-NEXT: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 58298) +// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 58298) // CHECK-NEXT: call %swift.opaque* [[WITNESS]](%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* %T) {{#[0-9]+}} [ "ptrauth"(i32 0, i64 [[DISC]]) ] // CHECK-NEXT: ret void @@ -59,7 +59,7 @@ bb0(%0 : $*T, %1 : $*T): // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align // CHECK-NEXT: [[WITNESS:%.*]] = bitcast i8* [[T0]] to // CHECK-NEXT: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 18648) +// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 18648) // CHECK-NEXT: call %swift.opaque* [[WITNESS]](%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* %T) {{#[0-9]+}} [ "ptrauth"(i32 0, i64 [[DISC]]) ] // CHECK-NEXT: ret void @@ -75,7 +75,7 @@ bb0(%0 : $*T, %1 : $*T): // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align // CHECK-NEXT: [[WITNESS:%.*]] = bitcast i8* [[T0]] to // CHECK-NEXT: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 34641) +// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 34641) // CHECK-NEXT: call %swift.opaque* [[WITNESS]](%swift.opaque* %0, %swift.opaque* %1, %swift.type* %T) {{#[0-9]+}} [ "ptrauth"(i32 0, i64 [[DISC]]) ] // CHECK-NEXT: ret void @@ -91,7 +91,7 @@ bb0(%0 : $*T, %1 : $*T): // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align // CHECK-NEXT: [[WITNESS:%.*]] = bitcast i8* [[T0]] to // CHECK-NEXT: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 61402) +// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 61402) // CHECK-NEXT: call %swift.opaque* [[WITNESS]](%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* %T) {{#[0-9]+}} [ "ptrauth"(i32 0, i64 [[DISC]]) ] // CHECK-NEXT: ret void @@ -109,7 +109,7 @@ bb0(%0 : $*T, %1 : $*T): // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align // CHECK-NEXT: [[WITNESS:%.*]] = bitcast i8* [[T0]] to // CHECK-NEXT: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64 -// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend.i64(i64 [[T0]], i64 1272) +// CHECK-NEXT: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 1272) // CHECK-NEXT: call void [[WITNESS]](%swift.opaque* noalias %0, %swift.type* %T) {{#[0-9]+}} [ "ptrauth"(i32 0, i64 [[DISC]]) ] // CHECK-NEXT: call void [[WITNESS]](%swift.opaque* noalias %1, %swift.type* %T) {{#[0-9]+}} [ "ptrauth"(i32 0, i64 [[DISC]]) ] // CHECK-NEXT: ret void diff --git a/test/IRGen/simple_partial_apply.sil b/test/IRGen/simple_partial_apply.sil index 11df3cfe79bf9..cc6d1cb384d12 100644 --- a/test/IRGen/simple_partial_apply.sil +++ b/test/IRGen/simple_partial_apply.sil @@ -13,7 +13,7 @@ struct SingleRefcounted { } // CHECK-LABEL: define {{.*}} @escape_partial_apply_swift_class -// CHECK-arm64e: call i64 @llvm.ptrauth.resign.i64 +// CHECK-arm64e: call i64 @llvm.ptrauth.resign // CHECK: [[FPTR:%.*]] = insertvalue { i8*, %swift.refcounted* } undef, i8* {{.*}}, 0 // CHECK-NEXT: [[FCTX:%.*]] = insertvalue { i8*, %swift.refcounted* } [[FPTR]], %swift.refcounted* {{.*}}, 1 // CHECK-NEXT: ret { i8*, %swift.refcounted* } [[FCTX]] @@ -36,7 +36,7 @@ entry(%body : $@convention(method) (Int, @guaranteed SingleRefcounted) -> Int, % } // CHECK-LABEL: define {{.*}} @noescape_partial_apply_swift_indirect -// CHECK-arm64e: call i64 @llvm.ptrauth.resign.i64 +// CHECK-arm64e: call i64 @llvm.ptrauth.resign // CHECK: [[CTX:%.*]] = bitcast {{.*}}** %1 to %swift.opaque* // CHECK-NEXT: [[CONT:%.*]] = bitcast i8* %2 // CHECK-NEXT: call {{.*}}void [[CONT]](i8* {{.*}}, %swift.opaque* [[CTX]], %swift.refcounted* {{.*}}%3) From 50c2864488c0c45b9653c825a221143662e50f3a Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 20 Dec 2021 16:40:27 -0800 Subject: [PATCH 020/491] Consistently initialize clang CodeGenOptions.DebugTypeExtRefs on all code paths. This flag is part of the Clang module hash. Setting it on all paths makes it easier to reason about the permutations of Clang modules that are being built on behalf of Swift. (cherry picked from commit f0b7065169627895019939fe0ace13b8bc6e27bd) --- lib/IRGen/IRGenModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 52f73b01546e2..25e6cddb91538 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -103,6 +103,7 @@ static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context, auto &CGO = Importer->getClangCodeGenOpts(); CGO.OptimizationLevel = Opts.shouldOptimize() ? 3 : 0; + CGO.DebugTypeExtRefs = !Opts.DisableClangModuleSkeletonCUs; CGO.DiscardValueNames = !Opts.shouldProvideValueNames(); switch (Opts.DebugInfoLevel) { case IRGenDebugInfoLevel::None: @@ -113,7 +114,6 @@ static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context, break; case IRGenDebugInfoLevel::ASTTypes: case IRGenDebugInfoLevel::DwarfTypes: - CGO.DebugTypeExtRefs = !Opts.DisableClangModuleSkeletonCUs; CGO.setDebugInfo(clang::codegenoptions::DebugInfoKind::FullDebugInfo); break; } From 9aa68d74fd5efad94495ad72d839b083273a5512 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 20 Dec 2021 16:40:38 -0800 Subject: [PATCH 021/491] Initialize clang::CodeGenOptions.DebugExtRefs in ClangImporter. This fixes a race condition in parallel builds. DebugExtRefs is part of the Clang module hash. ObjectFilePCHContainerOperations has its own CodenOpts object which always sets DebugExtRefs=true, so the module has could differ depending on whether a module was built as a top-level module or as a dependency of another module. This fixes the SwiftREPL tests. rdar://86279876 (cherry picked from commit c30f256bbebfb7bfbac84a576bd29381e794153b) --- lib/ClangImporter/ClangImporter.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index a45966eec590f..ac9ad96a67916 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1130,6 +1130,10 @@ ClangImporter::create(ASTContext &ctx, // Create a compiler instance. { + // The Clang modules produced by ClangImporter are always embedded in an + // ObjectFilePCHContainer and contain -gmodules debug info. + importer->Impl.Invocation->getCodeGenOpts().DebugTypeExtRefs = true; + auto PCHContainerOperations = std::make_shared(); PCHContainerOperations->registerWriter( From 029f0bc5c0163275ae72dd62e08869907846eaaf Mon Sep 17 00:00:00 2001 From: YR Chen Date: Sun, 24 Apr 2022 15:07:23 +0800 Subject: [PATCH 022/491] [Driver] Fix searching for SwiftDriver on Windows --- lib/DriverTool/driver.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/DriverTool/driver.cpp b/lib/DriverTool/driver.cpp index f71e2de9eaef3..9497ad87b7ef9 100644 --- a/lib/DriverTool/driver.cpp +++ b/lib/DriverTool/driver.cpp @@ -32,6 +32,7 @@ #include "swift/FrontendTool/FrontendTool.h" #include "swift/DriverTool/DriverTool.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Errno.h" @@ -168,12 +169,13 @@ static bool appendSwiftDriverName(SmallString<256> &buffer) { return true; } - llvm::sys::path::append(buffer, "swift-driver"); + StringRef execSuffix(llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows() ? ".exe" : ""); + llvm::sys::path::append(buffer, "swift-driver" + execSuffix); if (llvm::sys::fs::exists(buffer)) { return true; } llvm::sys::path::remove_filename(buffer); - llvm::sys::path::append(buffer, "swift-driver-new"); + llvm::sys::path::append(buffer, "swift-driver-new" + execSuffix); if (llvm::sys::fs::exists(buffer)) { return true; } From a1df4bad6def3bd37c17053f9cd29c0eb0a8fb00 Mon Sep 17 00:00:00 2001 From: YR Chen Date: Sun, 24 Apr 2022 15:08:28 +0800 Subject: [PATCH 023/491] [Driver] More robust way of finding subcommand path --- lib/DriverTool/driver.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/DriverTool/driver.cpp b/lib/DriverTool/driver.cpp index 9497ad87b7ef9..ddfe0cc1964d5 100644 --- a/lib/DriverTool/driver.cpp +++ b/lib/DriverTool/driver.cpp @@ -381,15 +381,16 @@ int swift::mainEntry(int argc_, const char **argv_) { subCommandArgs.erase(&subCommandArgs[1]); // We are running as a subcommand, try to find the subcommand adjacent to // the executable we are running as. - SmallString<256> SubcommandPath( - llvm::sys::path::parent_path(getExecutablePath(argv[0]))); - llvm::sys::path::append(SubcommandPath, SubcommandName); - - // If we didn't find the tool there, let the OS search for it. - if (!llvm::sys::fs::exists(SubcommandPath)) { + SmallString<256> SubcommandPath(SubcommandName); + auto result = llvm::sys::findProgramByName(SubcommandName, + { llvm::sys::path::parent_path(getExecutablePath(argv[0])) }); + if (!result.getError()) { + SubcommandPath = *result; + } else { + // If we didn't find the tool there, let the OS search for it. + result = llvm::sys::findProgramByName(SubcommandName); // Search for the program and use the path if found. If there was an // error, ignore it and just let the exec fail. - auto result = llvm::sys::findProgramByName(SubcommandName); if (!result.getError()) SubcommandPath = *result; } From 185047550bd43c3cb357b8c35a0760e3ed702a10 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 4 May 2022 19:39:19 -0700 Subject: [PATCH 024/491] Update Demangle.h Add missing include for rebranch. --- include/swift/Demangling/Demangle.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h index a6cb8713485d3..fd80f81480d49 100644 --- a/include/swift/Demangling/Demangle.h +++ b/include/swift/Demangling/Demangle.h @@ -23,8 +23,10 @@ #include "swift/Demangling/NamespaceMacros.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" + #include #include +#include #include #include From 68296c90372d98f6aba063cebefa1cad37c2052b Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 25 Apr 2022 15:24:26 -0700 Subject: [PATCH 025/491] [next] Remove LLVM_ATTRIBUTE_DEPRECATED `LLVM_ATTRIBUTE_DEPRECATED` was removed in llvm/llvm-project 903c30f4d1f3bc0d1aae9ca83af17c0062d02b40. Use `[[deprecated]]` directly. --- include/swift/ABI/Metadata.h | 12 ++++-------- include/swift/ABI/MetadataValues.h | 4 ++-- include/swift/AST/Identifier.h | 3 +-- include/swift/Basic/Debug.h | 3 +-- include/swift/Runtime/ExistentialContainer.h | 3 +-- include/swift/SIL/SILType.h | 3 +-- include/swift/SIL/SILValue.h | 8 +++----- lib/SILGen/Cleanup.h | 4 ++-- 8 files changed, 15 insertions(+), 25 deletions(-) diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h index 17173cdc57c1e..1a5423fa4716d 100644 --- a/include/swift/ABI/Metadata.h +++ b/include/swift/ABI/Metadata.h @@ -424,8 +424,7 @@ struct TargetMetadata { #endif #ifndef NDEBUG - LLVM_ATTRIBUTE_DEPRECATED(void dump() const, - "Only meant for use in the debugger"); + [[deprecated("Only meant for use in the debugger")]] void dump() const; #endif protected: @@ -2667,8 +2666,7 @@ struct TargetContextDescriptor { } #ifndef NDEBUG - LLVM_ATTRIBUTE_DEPRECATED(void dump() const, - "only for use in the debugger"); + [[deprecated("Only meant for use in the debugger")]] void dump() const; #endif private: @@ -2930,8 +2928,7 @@ struct TargetProtocolDescriptor final } #ifndef NDEBUG - LLVM_ATTRIBUTE_DEPRECATED(void dump() const, - "only for use in the debugger"); + [[deprecated("Only meant for use in the debugger")]] void dump() const; #endif static bool classof(const TargetContextDescriptor *cd) { @@ -4399,8 +4396,7 @@ class TargetEnumDescriptor final } #ifndef NDEBUG - LLVM_ATTRIBUTE_DEPRECATED(void dump() const, - "Only meant for use in the debugger"); + [[deprecated("Only meant for use in the debugger")]] void dump() const; #endif }; diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h index 99944212655f7..363f920a3a321 100644 --- a/include/swift/ABI/MetadataValues.h +++ b/include/swift/ABI/MetadataValues.h @@ -22,6 +22,7 @@ #include "swift/ABI/KeyPath.h" #include "swift/ABI/ProtocolDispatchStrategy.h" #include "swift/AST/Ownership.h" +#include "swift/Basic/Debug.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/FlagSet.h" #include "llvm/ADT/ArrayRef.h" @@ -531,8 +532,7 @@ class ProtocolDescriptorFlags { } #ifndef NDEBUG - LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED, - "Only for use in the debugger"); + SWIFT_DEBUG_DUMP; #endif }; diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h index 316a91dd980f6..6a5e1655d7cb7 100644 --- a/include/swift/AST/Identifier.h +++ b/include/swift/AST/Identifier.h @@ -778,8 +778,7 @@ class DeclNameRef { llvm::raw_ostream &printPretty(llvm::raw_ostream &os) const; /// Dump this name to standard error. - LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED, - "only for use within the debugger"); + SWIFT_DEBUG_DUMP; }; inline DeclNameRef DeclNameRef::getFromOpaqueValue(void *p) { diff --git a/include/swift/Basic/Debug.h b/include/swift/Basic/Debug.h index ad47b7f6f398c..edbdeb66cdd81 100644 --- a/include/swift/Basic/Debug.h +++ b/include/swift/Basic/Debug.h @@ -20,8 +20,7 @@ /// This deprecates the method so it won't be called directly and marks it as /// used so it won't be eliminated as dead code. #define SWIFT_DEBUG_HELPER(method) \ - LLVM_ATTRIBUTE_DEPRECATED(method LLVM_ATTRIBUTE_USED, \ - "only for use in the debugger") + [[deprecated("only for use in the debugger")]] method LLVM_ATTRIBUTE_USED /// Declares a const void instance method with the name and parameters provided. /// Methods declared with this macro should never be called except in the diff --git a/include/swift/Runtime/ExistentialContainer.h b/include/swift/Runtime/ExistentialContainer.h index bf7e63c7cb825..ccd520f808940 100644 --- a/include/swift/Runtime/ExistentialContainer.h +++ b/include/swift/Runtime/ExistentialContainer.h @@ -68,8 +68,7 @@ struct TargetOpaqueExistentialContainer { /// Dump information about this specific box and its contents. Only intended /// for use in the debugger. - LLVM_ATTRIBUTE_DEPRECATED(void dump() const, - "Only meant for use in the debugger"); + [[deprecated("Only meant for use in the debugger")]] void dump() const; #endif }; using OpaqueExistentialContainer = TargetOpaqueExistentialContainer; diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index c2d7da1593e81..43bca2de93ddf 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -184,8 +184,7 @@ class SILType { } // FIXME -- Temporary until LLDB adopts getASTType() - LLVM_ATTRIBUTE_DEPRECATED(CanType getSwiftRValueType() const, - "Please use getASTType()") { + [[deprecated("Please use getASTType()")]] CanType getSwiftRValueType() const { return getASTType(); } diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h index 33b5fdbc60b80..d2fd0f0a77bc9 100644 --- a/include/swift/SIL/SILValue.h +++ b/include/swift/SIL/SILValue.h @@ -17,6 +17,7 @@ #ifndef SWIFT_SIL_SILVALUE_H #define SWIFT_SIL_SILVALUE_H +#include "swift/Basic/Debug.h" #include "swift/Basic/Range.h" #include "swift/Basic/ArrayRefView.h" #include "swift/Basic/STLExtras.h" @@ -659,8 +660,7 @@ class SILValue { /// Verify that this SILValue and its uses respects ownership invariants. void verifyOwnership(DeadEndBlocks *DEBlocks) const; - LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED, - "Only for use in the debugger"); + SWIFT_DEBUG_DUMP; }; inline SILNodePointer::SILNodePointer(SILValue value) : node(value) { } @@ -1090,10 +1090,8 @@ class Operand { SILBasicBlock *getParentBlock() const; SILFunction *getParentFunction() const; - LLVM_ATTRIBUTE_DEPRECATED( - void dump() const LLVM_ATTRIBUTE_USED, - "Dump the operand's state. Only for use in the debugger!"); void print(llvm::raw_ostream &os) const; + SWIFT_DEBUG_DUMP; private: void removeFromCurrent() { diff --git a/lib/SILGen/Cleanup.h b/lib/SILGen/Cleanup.h index ed89eb83e33b1..e51979f1d9912 100644 --- a/lib/SILGen/Cleanup.h +++ b/lib/SILGen/Cleanup.h @@ -17,6 +17,7 @@ #ifndef SWIFT_SILGEN_CLEANUP_H #define SWIFT_SILGEN_CLEANUP_H +#include "swift/Basic/Debug.h" #include "swift/Basic/DiverseStack.h" #include "swift/SIL/SILLocation.h" #include "swift/SIL/SILValue.h" @@ -280,8 +281,7 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager { bool hasAnyActiveCleanups(CleanupsDepth from); /// Dump the output of each cleanup on this stack. - LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED, - "Only for use in the debugger"); + SWIFT_DEBUG_DUMP; /// Dump the given cleanup handle if it is on the current stack. void dump(CleanupHandle handle) const; From 114b4d96e437e0456729a838c7162da118c9ae63 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 25 Apr 2022 17:00:51 -0700 Subject: [PATCH 026/491] [next] Use new VersionTuple API The `VersionTuple` API was changed llvm/llvm-project 219672b8dd06c4765185fa3161c98437d49b4a1b to return `VersionTuple` from `get*Version` rather than pass in major, minor, and subminor output parameters. Update uses to the new API. Note that `getMacOSXVersion` is slightly different in that it returns a boolean while taking a `VersionTuple` output parameter to match its previous behaviour. There doesn't seem to be any use that actually checks this value though, so we should either update the API to return an `Optional` and actually check it *or* remove the "failure" case and return a `VersionTuple` like all the others. --- include/swift/Basic/LangOptions.h | 11 ++-- lib/Basic/LangOptions.cpp | 11 ++-- lib/Basic/Platform.cpp | 17 +++-- lib/Driver/DarwinToolChains.cpp | 69 ++++++++------------ lib/Frontend/CompilerInvocation.cpp | 17 +++-- lib/Serialization/ModuleFile.cpp | 14 ++-- lib/Serialization/SerializedModuleLoader.cpp | 13 ++-- lib/SymbolGraphGen/JSON.cpp | 6 +- 8 files changed, 72 insertions(+), 86 deletions(-) diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index fb150994366f8..f254b3e67eb9f 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -591,15 +591,16 @@ namespace swift { /// This is only implemented on certain OSs. If no target has been /// configured, returns v0.0.0. llvm::VersionTuple getMinPlatformVersion() const { - unsigned major = 0, minor = 0, revision = 0; if (Target.isMacOSX()) { - Target.getMacOSXVersion(major, minor, revision); + llvm::VersionTuple OSVersion; + Target.getMacOSXVersion(OSVersion); + return OSVersion; } else if (Target.isiOS()) { - Target.getiOSVersion(major, minor, revision); + return Target.getiOSVersion(); } else if (Target.isWatchOS()) { - Target.getOSVersion(major, minor, revision); + return Target.getOSVersion(); } - return llvm::VersionTuple(major, minor, revision); + return llvm::VersionTuple(/*Major=*/0, /*Minor=*/0, /*Subminor=*/0); } /// Sets an implicit platform condition. diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index 0b30ccfac9bc2..90e0248e75282 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -235,11 +235,12 @@ std::pair LangOptions::setTarget(llvm::Triple triple) { llvm::raw_svector_ostream osx(osxBuf); osx << llvm::Triple::getOSTypeName(llvm::Triple::MacOSX); - unsigned major, minor, micro; - triple.getMacOSXVersion(major, minor, micro); - osx << major << "." << minor; - if (micro != 0) - osx << "." << micro; + llvm::VersionTuple OSVersion; + triple.getMacOSXVersion(OSVersion); + + osx << OSVersion.getMajor() << "." << OSVersion.getMinor().getValueOr(0); + if (auto Subminor = OSVersion.getSubminor()) + osx << "." << *Subminor; triple.setOSName(osx.str()); } diff --git a/lib/Basic/Platform.cpp b/lib/Basic/Platform.cpp index a10d52099212e..74a93c08790c4 100644 --- a/lib/Basic/Platform.cpp +++ b/lib/Basic/Platform.cpp @@ -395,11 +395,13 @@ llvm::Triple swift::getUnversionedTriple(const llvm::Triple &triple) { Optional swift::getSwiftRuntimeCompatibilityVersionForTarget( const llvm::Triple &Triple) { - unsigned Major, Minor, Micro; #define MAX(a, b) ((a) > (b) ? (a) : (b)) if (Triple.isMacOSX()) { - Triple.getMacOSXVersion(Major, Minor, Micro); + llvm::VersionTuple OSVersion; + Triple.getMacOSXVersion(OSVersion); + unsigned Major = OSVersion.getMajor(); + unsigned Minor = OSVersion.getMinor().getValueOr(0); auto floorFor64 = [&Triple](llvm::VersionTuple v) { if (!Triple.isAArch64()) return v; @@ -414,7 +416,7 @@ swift::getSwiftRuntimeCompatibilityVersionForTarget( if (Minor <= 14) { return floorFor64(llvm::VersionTuple(5, 0)); } else if (Minor <= 15) { - if (Micro <= 3) { + if (OSVersion.getSubminor().getValueOr(0) <= 3) { return floorFor64(llvm::VersionTuple(5, 1)); } else { return floorFor64(llvm::VersionTuple(5, 2)); @@ -429,7 +431,9 @@ swift::getSwiftRuntimeCompatibilityVersionForTarget( return floorFor64(llvm::VersionTuple(5, 5)); } } else if (Triple.isiOS()) { // includes tvOS - Triple.getiOSVersion(Major, Minor, Micro); + llvm::VersionTuple OSVersion = Triple.getiOSVersion(); + unsigned Major = OSVersion.getMajor(); + unsigned Minor = OSVersion.getMinor().getValueOr(0); auto floorForArchitecture = [&Triple, Major](llvm::VersionTuple v) { // arm64 simulators and macCatalyst are introduced in iOS 14.0/tvOS 14.0 @@ -463,13 +467,16 @@ swift::getSwiftRuntimeCompatibilityVersionForTarget( return floorForArchitecture(llvm::VersionTuple(5, 5)); } } else if (Triple.isWatchOS()) { + llvm::VersionTuple OSVersion = Triple.getWatchOSVersion(); + unsigned Major = OSVersion.getMajor(); + unsigned Minor = OSVersion.getMinor().getValueOr(0); + auto floorFor64bits = [&Triple](llvm::VersionTuple v) { if (!Triple.isArch64Bit()) return v; // 64-bit watchOS was introduced with Swift 5.3 return MAX(v, llvm::VersionTuple(5, 3)); }; - Triple.getWatchOSVersion(Major, Minor, Micro); if (Major <= 5) { return floorFor64bits(llvm::VersionTuple(5, 0)); } else if (Major <= 6) { diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 8b5933d8f9650..0f2f32acd3ece 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -213,10 +213,11 @@ static bool findXcodeClangLibPath(const Twine &libName, } static void addVersionString(const ArgList &inputArgs, ArgStringList &arguments, - unsigned major, unsigned minor, unsigned micro) { + llvm::VersionTuple version) { llvm::SmallString<8> buf; llvm::raw_svector_ostream os{buf}; - os << major << '.' << minor << '.' << micro; + os << version.getMajor() << '.' << version.getMinor().getValueOr(0) << '.' + << version.getSubminor().getValueOr(0); arguments.push_back(inputArgs.MakeArgString(os.str())); } @@ -588,38 +589,30 @@ toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments, } // Compute the platform version. - unsigned major, minor, micro; + llvm::VersionTuple osVersion; if (tripleIsMacCatalystEnvironment(triple)) { - triple.getiOSVersion(major, minor, micro); - - // Mac Catalyst on arm was introduced with an iOS deployment target of - // 14.0; the linker doesn't want to see a deployment target before that. - if (major < 14 && triple.isAArch64()) { - major = 14; - minor = 0; - micro = 0; - } - - // Mac Catalyst was introduced with an iOS deployment target of 13.1; - // the linker doesn't want to see a deployment target before that. - if (major < 13) { - major = 13; - minor = 1; - micro = 0; + osVersion = triple.getiOSVersion(); + + if (osVersion.getMajor() < 14 && triple.isAArch64()) { + // Mac Catalyst on arm was introduced with an iOS deployment target of + // 14.0; the linker doesn't want to see a deployment target before that. + osVersion = llvm::VersionTuple(/*Major=*/14, /*Minor=*/0); + } else if (osVersion.getMajor() < 13) { + // Mac Catalyst was introduced with an iOS deployment target of 13.1; + // the linker doesn't want to see a deployment target before that. + osVersion = llvm::VersionTuple(/*Major=*/13, /*Minor=*/1); } } else { switch (getDarwinPlatformKind((triple))) { case DarwinPlatformKind::MacOS: - triple.getMacOSXVersion(major, minor, micro); + triple.getMacOSXVersion(osVersion); // The first deployment of arm64 for macOS is version 10.16; - if (triple.isAArch64() && major <= 10 && minor < 16) { - llvm::VersionTuple firstMacARM64e(10, 16, 0); - firstMacARM64e = canonicalizePlatformVersion(PlatformKind::macOS, - firstMacARM64e); - major = firstMacARM64e.getMajor(); - minor = firstMacARM64e.getMinor().getValueOr(0); - micro = firstMacARM64e.getSubminor().getValueOr(0); + if (triple.isAArch64() && osVersion.getMajor() <= 10 && + osVersion.getMinor().getValueOr(0) < 16) { + osVersion = llvm::VersionTuple(/*Major=*/10, /*Minor=*/16); + osVersion = canonicalizePlatformVersion(PlatformKind::macOS, + osVersion); } break; @@ -627,37 +620,31 @@ toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments, case DarwinPlatformKind::IPhoneOSSimulator: case DarwinPlatformKind::TvOS: case DarwinPlatformKind::TvOSSimulator: - triple.getiOSVersion(major, minor, micro); + osVersion = triple.getiOSVersion(); // The first deployment of arm64 simulators is iOS/tvOS 14.0; // the linker doesn't want to see a deployment target before that. if (triple.isSimulatorEnvironment() && triple.isAArch64() && - major < 14) { - major = 14; - minor = 0; - micro = 0; + osVersion.getMajor() < 14) { + osVersion = llvm::VersionTuple(/*Major=*/14, /*Minor=*/0); } break; case DarwinPlatformKind::WatchOS: case DarwinPlatformKind::WatchOSSimulator: - triple.getOSVersion(major, minor, micro); + osVersion = triple.getOSVersion(); break; } } // Compute the SDK version. - unsigned sdkMajor = 0, sdkMinor = 0, sdkMicro = 0; - if (auto sdkVersion = getTargetSDKVersion(triple)) { - sdkMajor = sdkVersion->getMajor(); - sdkMinor = sdkVersion->getMinor().getValueOr(0); - sdkMicro = sdkVersion->getSubminor().getValueOr(0); - } + auto sdkVersion = getTargetSDKVersion(triple) + .getValueOr(llvm::VersionTuple()); Arguments.push_back("-platform_version"); Arguments.push_back(platformName); - addVersionString(context.Args, Arguments, major, minor, micro); - addVersionString(context.Args, Arguments, sdkMajor, sdkMinor, sdkMicro); + addVersionString(context.Args, Arguments, osVersion); + addVersionString(context.Args, Arguments, sdkVersion); }; addPlatformVersionArg(getTriple()); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index e2f1ca5878a23..c13c23403ee74 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -852,12 +852,12 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, // and that library clients will generally raise deployment targets as the // library evolves so the min inlining version should be the deployment // target by default. - unsigned major, minor, patch; - if (triple.isMacOSX()) - triple.getMacOSXVersion(major, minor, patch); - else - triple.getOSVersion(major, minor, patch); - return llvm::VersionTuple(major, minor, patch); + if (triple.isMacOSX()) { + llvm::VersionTuple OSVersion; + triple.getMacOSXVersion(OSVersion); + return OSVersion; + } + return triple.getOSVersion(); }; Opts.MinimumInliningTargetVersion = @@ -2365,9 +2365,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, // silently override "auto" to "never" when back-deploying. This approach // sacrifices async backtraces when back-deploying but prevents crashes in // older tools that cannot handle the async frame bit in the frame pointer. - unsigned major, minor, micro; - Triple.getWatchOSVersion(major, minor, micro); - if (major < 8) + llvm::VersionTuple OSVersion = Triple.getWatchOSVersion(); + if (OSVersion.getMajor() < 8) Opts.SwiftAsyncFramePointer = SwiftAsyncFramePointerKind::Never; } diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 1e54de8b221ff..dbf6c4f49d1d9 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -79,15 +79,15 @@ static bool areCompatibleOSs(const llvm::Triple &moduleTarget, static bool isTargetTooNew(const llvm::Triple &moduleTarget, const llvm::Triple &ctxTarget) { - unsigned major, minor, micro; - if (moduleTarget.isMacOSX()) { - moduleTarget.getMacOSXVersion(major, minor, micro); - return ctxTarget.isMacOSXVersionLT(major, minor, micro); + llvm::VersionTuple osVersion; + moduleTarget.getMacOSXVersion(osVersion); + // TODO: Add isMacOSXVersionLT(Triple) API (or taking a VersionTuple) + return ctxTarget.isMacOSXVersionLT(osVersion.getMajor(), + osVersion.getMinor().getValueOr(0), + osVersion.getSubminor().getValueOr(0)); } - - moduleTarget.getOSVersion(major, minor, micro); - return ctxTarget.isOSVersionLT(major, minor, micro); + return ctxTarget.isOSVersionLT(moduleTarget); } ModuleFile::ModuleFile(std::shared_ptr core) diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 0cf5517fbecc7..296b83b36aa75 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -689,14 +689,14 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID, static std::pair getOSAndVersionForDiagnostics(const llvm::Triple &triple) { StringRef osName; - unsigned major, minor, micro; + llvm::VersionTuple osVersion; if (triple.isMacOSX()) { // macOS triples represent their versions differently, so we have to use the // special accessor. - triple.getMacOSXVersion(major, minor, micro); + triple.getMacOSXVersion(osVersion); osName = swift::prettyPlatformString(PlatformKind::macOS); } else { - triple.getOSVersion(major, minor, micro); + osVersion = triple.getOSVersion(); if (triple.isWatchOS()) { osName = swift::prettyPlatformString(PlatformKind::watchOS); } else if (triple.isTvOS()) { @@ -714,12 +714,7 @@ getOSAndVersionForDiagnostics(const llvm::Triple &triple) { } assert(!osName.empty()); - clang::VersionTuple version; - if (micro != 0) - version = clang::VersionTuple(major, minor, micro); - else - version = clang::VersionTuple(major, minor); - return {osName, version}; + return {osName, osVersion}; } LoadedFile *SerializedModuleLoaderBase::loadAST( diff --git a/lib/SymbolGraphGen/JSON.cpp b/lib/SymbolGraphGen/JSON.cpp index ed7bdf7217b77..9a7354d27b63b 100644 --- a/lib/SymbolGraphGen/JSON.cpp +++ b/lib/SymbolGraphGen/JSON.cpp @@ -52,11 +52,7 @@ void swift::symbolgraphgen::serialize(const llvm::Triple &T, OS.attributeObject("operatingSystem", [&](){ OS.attribute("name", T.getOSTypeName(T.getOS())); - unsigned Major; - unsigned Minor; - unsigned Patch; - T.getOSVersion(Major, Minor, Patch); - llvm::VersionTuple OSVersion(Major, Minor, Patch); + llvm::VersionTuple OSVersion = T.getOSVersion(); OS.attributeBegin("minimumVersion"); serialize(OSVersion, OS); From cbcd6c75f55c442c3e25253ab580a166e9a90872 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 25 Apr 2022 17:11:46 -0700 Subject: [PATCH 027/491] [next] Handle new LLVM triples --- lib/Basic/Platform.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Basic/Platform.cpp b/lib/Basic/Platform.cpp index 74a93c08790c4..85e26057da15f 100644 --- a/lib/Basic/Platform.cpp +++ b/lib/Basic/Platform.cpp @@ -181,11 +181,14 @@ StringRef swift::getPlatformNameForTriple(const llvm::Triple &triple) { case llvm::Triple::Ananas: case llvm::Triple::CloudABI: case llvm::Triple::DragonFly: + case llvm::Triple::DriverKit: case llvm::Triple::Emscripten: case llvm::Triple::Fuchsia: case llvm::Triple::KFreeBSD: case llvm::Triple::Lv2: case llvm::Triple::NetBSD: + case llvm::Triple::PS5: + case llvm::Triple::ShaderModel: case llvm::Triple::Solaris: case llvm::Triple::Minix: case llvm::Triple::RTEMS: From c678e2f8a9b72d9db86a07ea90fdf70d6b36287f Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 25 Apr 2022 17:17:59 -0700 Subject: [PATCH 028/491] [next] Add missing include llvm/llvm-project 25991aadcc57fdada57147a9c83ca6301f6430bb removed `llvm/Remarks/Remark.h` from `llvm/Remarks/RemarkParser.h`. Include it directly. --- include/swift/SIL/SILRemarkStreamer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/swift/SIL/SILRemarkStreamer.h b/include/swift/SIL/SILRemarkStreamer.h index c7cf33009f3c3..4fde3c6c89e9c 100644 --- a/include/swift/SIL/SILRemarkStreamer.h +++ b/include/swift/SIL/SILRemarkStreamer.h @@ -21,6 +21,7 @@ #include "swift/Basic/SourceManager.h" #include "swift/SIL/OptimizationRemark.h" +#include "llvm/Remarks/Remark.h" #include "llvm/Remarks/RemarkStreamer.h" namespace swift { From 42848f801912c5e40a1ada8d50bf07c237734157 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 25 Apr 2022 17:45:55 -0700 Subject: [PATCH 029/491] [next] Add default handling for new IITDescriptor::AnyPtrToElt Added in llvm/llvm-project 49c2206b3bdce4a37a4602527b2d3da673514333. Unhandled for now. --- lib/AST/Builtins.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index a8e1c59e88922..fbe8f8a07b822 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -2096,6 +2096,7 @@ Type IntrinsicTypeDecoder::decodeImmediate() { case IITDescriptor::Subdivide2Argument: case IITDescriptor::Subdivide4Argument: case IITDescriptor::PPCQuad: + case IITDescriptor::AnyPtrToElt: // These types cannot be expressed in swift yet. return Type(); From 074f1dd7e338655ce6bd401d6213f14c8b90378b Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 25 Apr 2022 19:22:08 -0700 Subject: [PATCH 030/491] [next] Add missing WithColor include Best guess is that this was removed in a transitive include in llvm/llvm-project 75e164f61d391979b4829bf2746a5d74b94e95f2. --- lib/SILOptimizer/Mandatory/FlowIsolation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/SILOptimizer/Mandatory/FlowIsolation.cpp b/lib/SILOptimizer/Mandatory/FlowIsolation.cpp index 21b7d318be6c7..0d47dca21f6a6 100644 --- a/lib/SILOptimizer/Mandatory/FlowIsolation.cpp +++ b/lib/SILOptimizer/Mandatory/FlowIsolation.cpp @@ -12,6 +12,7 @@ #define DEBUG_TYPE "flow-isolation" +#include "llvm/Support/WithColor.h" #include "swift/AST/Expr.h" #include "swift/AST/ActorIsolation.h" #include "swift/AST/DiagnosticsSIL.h" From 092b2ddf7ab355753aaadd46932169ab0761dae9 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 26 Apr 2022 13:51:40 -0700 Subject: [PATCH 031/491] [next] Update dependency scanner to use new Clang API apple/llvm-project 000a90ab63ce0595d442b3e7e8adc9c0506d2525 removed `getAdditionalArgsWithoutModulePaths`. Based on the v2 libclang API, we should be using `getCommandLineWithoutModulePaths` now. --- lib/ClangImporter/ClangModuleDependencyScanner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index c09f91b71f2e5..3cb3c2c3dc439 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -249,7 +249,7 @@ void ClangImporter::recordModuleDependencies( // Add all args the non-path arguments required to be passed in, according // to the Clang scanner for (const auto &clangArg : - clangModuleDep.getAdditionalArgsWithoutModulePaths()) { + clangModuleDep.getCanonicalCommandLineWithoutModulePaths()) { swiftArgs.push_back("-Xcc"); swiftArgs.push_back("-Xclang"); swiftArgs.push_back("-Xcc"); From 04035b43b77b3a0a856c1ff87e3723f7c587e37b Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 26 Apr 2022 16:26:30 -0700 Subject: [PATCH 032/491] [next] Temporarily use getPointerElementType `PointerType::getElementType` has been removed entirely as part of the opaque pointers migration. Update to `getPointerElementType` for now until we've also migrated. --- lib/IRGen/GenArchetype.cpp | 2 +- lib/IRGen/GenBuiltin.cpp | 2 +- lib/IRGen/GenCall.cpp | 2 +- lib/IRGen/GenClass.cpp | 2 +- lib/IRGen/GenDecl.cpp | 6 +++--- lib/IRGen/GenEnum.cpp | 2 +- lib/IRGen/GenExistential.cpp | 4 ++-- lib/IRGen/GenHeap.cpp | 6 +++--- lib/IRGen/GenMeta.cpp | 2 +- lib/IRGen/GenOpaque.cpp | 4 ++-- lib/IRGen/GenStruct.cpp | 2 +- lib/IRGen/IRBuilder.h | 8 ++++---- lib/IRGen/IRGenModule.cpp | 2 +- lib/IRGen/IRGenSIL.cpp | 4 ++-- lib/IRGen/StructLayout.cpp | 2 +- 15 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp index 71e0833453915..1ea7e8ab4ffdd 100644 --- a/lib/IRGen/GenArchetype.cpp +++ b/lib/IRGen/GenArchetype.cpp @@ -344,7 +344,7 @@ const TypeInfo *TypeConverter::convertArchetypeType(ArchetypeType *archetype) { } // Otherwise, for now, always use an opaque indirect type. - llvm::Type *storageType = IGM.OpaquePtrTy->getElementType(); + llvm::Type *storageType = IGM.OpaquePtrTy->getPointerElementType(); // Opaque result types can be private and from a different module. In this // case we can't access their type metadata from another module. diff --git a/lib/IRGen/GenBuiltin.cpp b/lib/IRGen/GenBuiltin.cpp index d9b4b094d466b..864c9191f6bc1 100644 --- a/lib/IRGen/GenBuiltin.cpp +++ b/lib/IRGen/GenBuiltin.cpp @@ -447,7 +447,7 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin, llvm::SmallVector Indices(2, NameGEP->getOperand(1)); NameGEP = llvm::ConstantExpr::getGetElementPtr( - ((llvm::PointerType *)FuncNamePtr->getType())->getElementType(), + ((llvm::PointerType *)FuncNamePtr->getType())->getPointerElementType(), FuncNamePtr, makeArrayRef(Indices)); // Replace the placeholder value with the new GEP. diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 7349fcb7b984c..d82b092182fdb 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -4904,7 +4904,7 @@ Callee irgen::getBlockPointerCallee(IRGenFunction &IGF, auto castBlockPtr = IGF.Builder.CreateBitCast(blockPtr, blockPtrTy); // Extract the invocation pointer for blocks. - auto blockStructTy = blockPtrTy->getElementType(); + auto blockStructTy = blockPtrTy->getPointerElementType(); llvm::Value *invokeFnPtrPtr = IGF.Builder.CreateStructGEP(blockStructTy, castBlockPtr, 3); Address invokeFnPtrAddr(invokeFnPtrPtr, IGF.IGM.getPointerAlignment()); diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp index 37fa570556230..c3673d343bee3 100644 --- a/lib/IRGen/GenClass.cpp +++ b/lib/IRGen/GenClass.cpp @@ -595,7 +595,7 @@ OwnedAddress irgen::projectPhysicalClassMemberAddress(IRGenFunction &IGF, auto element = fieldInfo.second; Address memberAddr = element.project(IGF, baseAddr, None); // We may need to bitcast the address if the field is of a generic type. - if (memberAddr.getType()->getElementType() != fieldTI.getStorageType()) + if (memberAddr.getType()->getPointerElementType() != fieldTI.getStorageType()) memberAddr = IGF.Builder.CreateBitCast(memberAddr, fieldTI.getStorageType()->getPointerTo()); return OwnedAddress(memberAddr, base); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index c913e40859fdc..1ad1898e6fdc1 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -2221,7 +2221,7 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo, StringRef name, } static bool isPointerTo(llvm::Type *ptrTy, llvm::Type *objTy) { - return cast(ptrTy)->getElementType() == objTy; + return cast(ptrTy)->getPointerElementType() == objTy; } /// Get or create an LLVM function with these linkage rules. @@ -3349,7 +3349,7 @@ llvm::Constant *IRGenModule::getOrCreateGOTEquivalent(llvm::Constant *global, static llvm::Constant *getElementBitCast(llvm::Constant *ptr, llvm::Type *newEltType) { auto ptrType = cast(ptr->getType()); - if (ptrType->getElementType() == newEltType) { + if (ptrType->getPointerElementType() == newEltType) { return ptr; } else { auto newPtrType = newEltType->getPointerTo(ptrType->getAddressSpace()); @@ -4566,7 +4566,7 @@ llvm::GlobalValue *IRGenModule::defineAlias(LinkEntity entity, LinkInfo link = LinkInfo::get(*this, entity, ForDefinition); auto *ptrTy = cast(definition->getType()); auto *alias = llvm::GlobalAlias::create( - ptrTy->getElementType(), ptrTy->getAddressSpace(), link.getLinkage(), + ptrTy->getPointerElementType(), ptrTy->getAddressSpace(), link.getLinkage(), link.getName(), definition, &Module); ApplyIRLinkage({link.getLinkage(), link.getVisibility(), link.getDLLStorage()}) .to(alias); diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index a94d45e69b49f..16e911e31406b 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -6863,7 +6863,7 @@ const TypeInfo *TypeConverter::convertEnumType(TypeBase *key, CanType type, // Resilient enum types lower down to the same opaque type. if (IGM.isResilient(theEnum, ResilienceExpansion::Maximal)) - storageType = cast(IGM.OpaquePtrTy->getElementType()); + storageType = cast(IGM.OpaquePtrTy->getPointerElementType()); else storageType = IGM.createNominalType(type); diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp index 58ac7286658f1..b9501346db828 100644 --- a/lib/IRGen/GenExistential.cpp +++ b/lib/IRGen/GenExistential.cpp @@ -1184,7 +1184,7 @@ class ClassExistentialTypeInfo final spareBits.append(TC.IGM.getWitnessTablePtrSpareBits()); \ } \ auto storageTy = buildReferenceStorageType(TC.IGM, \ - TC.IGM.Name##ReferencePtrTy->getElementType()); \ + TC.IGM.Name##ReferencePtrTy->getPointerElementType()); \ return AddressOnly##Name##ClassExistentialTypeInfo::create( \ getStoredProtocols(), \ storageTy, \ @@ -1209,7 +1209,7 @@ class ClassExistentialTypeInfo final spareBits.append(TC.IGM.getWitnessTablePtrSpareBits()); \ } \ auto storageTy = buildReferenceStorageType(TC.IGM, \ - TC.IGM.Name##ReferencePtrTy->getElementType()); \ + TC.IGM.Name##ReferencePtrTy->getPointerElementType()); \ if (TC.IGM.isLoadableReferenceAddressOnly(Refcounting)) { \ return AddressOnly##Name##ClassExistentialTypeInfo::create( \ getStoredProtocols(), \ diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index 2c30459b507a7..313515599e4e3 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -752,7 +752,7 @@ void IRGenFunction::storeReferenceStorageExtraInhabitant(llvm::Value *index, switch (style) { \ case ReferenceCounting::Native: \ return new Native##Name##ReferenceTypeInfo( \ - valueType, IGM.Name##ReferencePtrTy->getElementType(), \ + valueType, IGM.Name##ReferencePtrTy->getPointerElementType(), \ IGM.getPointerSize(), IGM.getPointerAlignment(), \ std::move(spareBits), isOptional); \ case ReferenceCounting::ObjC: \ @@ -760,7 +760,7 @@ void IRGenFunction::storeReferenceStorageExtraInhabitant(llvm::Value *index, case ReferenceCounting::Block: \ case ReferenceCounting::Unknown: \ return new Unknown##Name##ReferenceTypeInfo( \ - valueType, IGM.Name##ReferencePtrTy->getElementType(), \ + valueType, IGM.Name##ReferencePtrTy->getPointerElementType(), \ IGM.getPointerSize(), IGM.getPointerAlignment(), \ std::move(spareBits), isOptional); \ case ReferenceCounting::Bridge: \ @@ -1837,7 +1837,7 @@ static llvm::Value *emitLoadOfHeapMetadataRef(IRGenFunction &IGF, // mistyped. llvm::StructType *structTy = cast( - cast(object->getType())->getElementType()); + cast(object->getType())->getPointerElementType()); llvm::Value *slot; diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index c3fa32c509a4d..5cbe8277db8b1 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -4321,7 +4321,7 @@ static void emitObjCClassSymbol(IRGenModule &IGM, // Create the alias. auto *ptrTy = cast(metadata->getType()); auto *alias = llvm::GlobalAlias::create( - ptrTy->getElementType(), ptrTy->getAddressSpace(), link.getLinkage(), + ptrTy->getPointerElementType(), ptrTy->getAddressSpace(), link.getLinkage(), link.getName(), metadata, &IGM.Module); ApplyIRLinkage({link.getLinkage(), link.getVisibility(), link.getDLLStorage()}) .to(alias, link.isForDefinition()); diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp index 5e0edc371d23e..34b5cd4bf2337 100644 --- a/lib/IRGen/GenOpaque.cpp +++ b/lib/IRGen/GenOpaque.cpp @@ -291,7 +291,7 @@ getOrCreateValueWitnessTablePtrTy(IRGenModule &IGM, llvm::PointerType *&cache, } llvm::StructType *IRGenModule::getValueWitnessTableTy() { - return cast(getValueWitnessTablePtrTy()->getElementType()); + return cast(getValueWitnessTablePtrTy()->getPointerElementType()); } llvm::PointerType *IRGenModule::getValueWitnessTablePtrTy() { return getOrCreateValueWitnessTablePtrTy(*this, ValueWitnessTablePtrTy, @@ -300,7 +300,7 @@ llvm::PointerType *IRGenModule::getValueWitnessTablePtrTy() { llvm::StructType *IRGenModule::getEnumValueWitnessTableTy() { return cast(getEnumValueWitnessTablePtrTy() - ->getElementType()); + ->getPointerElementType()); } llvm::PointerType *IRGenModule::getEnumValueWitnessTablePtrTy() { return getOrCreateValueWitnessTablePtrTy(*this, EnumValueWitnessTablePtrTy, diff --git a/lib/IRGen/GenStruct.cpp b/lib/IRGen/GenStruct.cpp index 213a2a63c27a0..64607dcf457c8 100644 --- a/lib/IRGen/GenStruct.cpp +++ b/lib/IRGen/GenStruct.cpp @@ -1472,7 +1472,7 @@ namespace { const TypeInfo * TypeConverter::convertResilientStruct(IsABIAccessible_t abiAccessible) { - llvm::Type *storageType = IGM.OpaquePtrTy->getElementType(); + llvm::Type *storageType = IGM.OpaquePtrTy->getPointerElementType(); return new ResilientStructTypeInfo(storageType, abiAccessible); } diff --git a/lib/IRGen/IRBuilder.h b/lib/IRGen/IRBuilder.h index 46dc02120bf4b..5c941a492bef0 100644 --- a/lib/IRGen/IRBuilder.h +++ b/lib/IRGen/IRBuilder.h @@ -156,7 +156,7 @@ class IRBuilder : public IRBuilderBase { Address CreateStructGEP(Address address, unsigned index, Size offset, const llvm::Twine &name = "") { llvm::Value *addr = CreateStructGEP( - address.getType()->getElementType(), address.getAddress(), + address.getType()->getPointerElementType(), address.getAddress(), index, name); return Address(addr, address.getAlignment().alignmentAtOffset(offset)); } @@ -172,7 +172,7 @@ class IRBuilder : public IRBuilderBase { Address CreateConstArrayGEP(Address base, unsigned index, Size eltSize, const llvm::Twine &name = "") { auto addr = CreateConstInBoundsGEP1_32( - base.getType()->getElementType(), base.getAddress(), index, name); + base.getType()->getPointerElementType(), base.getAddress(), index, name); return Address(addr, base.getAlignment().alignmentAtOffset(eltSize * index)); } @@ -181,7 +181,7 @@ class IRBuilder : public IRBuilderBase { Address CreateConstByteArrayGEP(Address base, Size offset, const llvm::Twine &name = "") { auto addr = CreateConstInBoundsGEP1_32( - base.getType()->getElementType(), base.getAddress(), offset.getValue(), + base.getType()->getPointerElementType(), base.getAddress(), offset.getValue(), name); return Address(addr, base.getAlignment().alignmentAtOffset(offset)); } @@ -199,7 +199,7 @@ class IRBuilder : public IRBuilderBase { const llvm::Twine &name = "") { // Do nothing if the type doesn't change. auto origPtrType = address.getType(); - if (origPtrType->getElementType() == type) return address; + if (origPtrType->getPointerElementType() == type) return address; // Otherwise, cast to a pointer to the correct type. auto ptrType = type->getPointerTo(origPtrType->getAddressSpace()); diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 61dd0d713d65e..e361a16a9bfbe 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -1057,7 +1057,7 @@ llvm::Constant *IRGenModule::getObjCEmptyCachePtr() { if (ObjCInterop) { // struct objc_cache _objc_empty_cache; ObjCEmptyCachePtr = Module.getOrInsertGlobal("_objc_empty_cache", - OpaquePtrTy->getElementType()); + OpaquePtrTy->getPointerElementType()); ApplyIRLinkage(IRLinkage::ExternalImport) .to(cast(ObjCEmptyCachePtr)); } else { diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index d37476ec4c13e..27acbc8c017b7 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -809,7 +809,7 @@ class IRGenSILFunction : SILDebugVariable VarInfo, const SILDebugScope *Scope) { bool canStore = - cast(Alloca->getType())->getElementType() == + cast(Alloca->getType())->getPointerElementType() == Val->getType(); if (canStore) return true; @@ -909,7 +909,7 @@ class IRGenSILFunction : auto *Address = Alloca.getAddress(); if (WasMoved) { auto nonPtrAllocaType = - cast(Address->getType())->getElementType(); + cast(Address->getType())->getPointerElementType(); if (nonPtrAllocaType != Storage->getType()) Address = Builder.CreateBitOrPointerCast( Address, llvm::PointerType::get(Storage->getType(), 0)); diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp index 2f6bc939ad335..7c10b948d3caa 100644 --- a/lib/IRGen/StructLayout.cpp +++ b/lib/IRGen/StructLayout.cpp @@ -78,7 +78,7 @@ StructLayout::StructLayout(IRGenModule &IGM, IsKnownPOD = IsPOD; IsKnownBitwiseTakable = IsBitwiseTakable; IsKnownAlwaysFixedSize = IsFixedSize; - Ty = (typeToFill ? typeToFill : IGM.OpaquePtrTy->getElementType()); + Ty = (typeToFill ? typeToFill : IGM.OpaquePtrTy->getPointerElementType()); } else { MinimumAlign = builder.getAlignment(); MinimumSize = builder.getSize(); From 1531ed7a25a4d70b9aca1c628e5dc448b5b4f477 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 26 Apr 2022 16:41:47 -0700 Subject: [PATCH 033/491] [next] Update ParseTopLevelDecl callers `ParseTopLevelDecl` was changed in llvm/llvm-project ab28488efe6de6f8fa856a1dfd8c0320d41d7608 and now takes a Sema::ModuleImportState output parameter rather than the previous (defaulted) boolean. --- lib/ClangImporter/ClangImporter.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 9a7e16b637d30..50741115becec 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1276,7 +1276,9 @@ ClangImporter::create(ASTContext &ctx, // callbacks are still being added, and (b) the logic to parse them has // changed. clang::Parser::DeclGroupPtrTy parsed; - while (!importer->Impl.Parser->ParseTopLevelDecl(parsed)) { + clang::Sema::ModuleImportState importState = + clang::Sema::ModuleImportState::NotACXX20Module; + while (!importer->Impl.Parser->ParseTopLevelDecl(parsed, importState)) { for (auto *D : parsed.get()) { importer->Impl.addBridgeHeaderTopLevelDecls(D); @@ -1434,7 +1436,9 @@ bool ClangImporter::Implementation::importHeader( }; clang::Parser::DeclGroupPtrTy parsed; - while (!Parser->ParseTopLevelDecl(parsed)) { + clang::Sema::ModuleImportState importState = + clang::Sema::ModuleImportState::NotACXX20Module; + while (!Parser->ParseTopLevelDecl(parsed, importState)) { if (parsed) handleParsed(parsed.get()); for (auto additionalParsedGroup : consumer.getAdditionalParsedDecls()) From d8d8bdc0071e641706a5ddf0d6e91f9fec29cd5a Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 27 Apr 2022 14:43:15 -0700 Subject: [PATCH 034/491] [next] Update how supplementary outputs are removed `ArgList::eraseArgIf` was removed in apple/llvm-project 000a90ab63ce0595d442b3e7e8adc9c0506d2525. Re-implement by retrieving the option specifier ID for all options that have the `SupplementaryOutput` flag in the given arguments and then erasing those. --- lib/Driver/FrontendUtil.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/Driver/FrontendUtil.cpp b/lib/Driver/FrontendUtil.cpp index b9d690ad0d0bb..3f0e340b7e861 100644 --- a/lib/Driver/FrontendUtil.cpp +++ b/lib/Driver/FrontendUtil.cpp @@ -18,6 +18,7 @@ #include "swift/Driver/Driver.h" #include "swift/Driver/Job.h" #include "swift/Driver/ToolChain.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Host.h" @@ -40,6 +41,22 @@ void swift::driver::ExpandResponseFilesWithRetry(llvm::StringSaver &Saver, } } +static void removeSupplementaryOutputs(llvm::opt::ArgList &ArgList) { + llvm::DenseSet OptSpecifiersToRemove; + + for (llvm::opt::Arg *Arg : ArgList.getArgs()) { + if (!Arg) + return; + + const llvm::opt::Option &Opt = Arg->getOption(); + if (Opt.hasFlag(options::SupplementaryOutput)) + OptSpecifiersToRemove.insert(Opt.getID()); + } + + for (unsigned Specifier : OptSpecifiersToRemove) { + ArgList.eraseArg(Specifier); + } +} bool swift::driver::getSingleFrontendInvocationFromDriverArguments( ArrayRef Argv, DiagnosticEngine &Diags, llvm::function_ref FrontendArgs)> Action, @@ -85,9 +102,7 @@ bool swift::driver::getSingleFrontendInvocationFromDriverArguments( if (ForceNoOutputs) { // Clear existing output modes and supplementary outputs. ArgList->eraseArg(options::OPT_modes_Group); - ArgList->eraseArgIf([](const llvm::opt::Arg *A) { - return A && A->getOption().hasFlag(options::SupplementaryOutput); - }); + removeSupplementaryOutputs(*ArgList); unsigned index = ArgList->MakeIndex("-typecheck"); // Takes ownership of the Arg. From 06a864cb31ca74a66a8b02fc21f95bda7cea2ad6 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 27 Apr 2022 14:49:13 -0700 Subject: [PATCH 035/491] [next] Rename BitInt to ExtInt This was renamed in llvm/llvm-project 6c75ab5f66b403f7ca67e86aeed3a58abe10570b. --- lib/ClangImporter/ImportType.cpp | 4 ++-- lib/IRGen/GenCall.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index d4cfdeba74bef..a8769be584048 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -390,10 +390,10 @@ namespace { llvm_unreachable("Invalid BuiltinType."); } - ImportResult VisitExtIntType(const clang::ExtIntType *type) { + ImportResult VisitBitIntType(const clang::BitIntType *type) { Impl.addImportDiagnostic(type, Diagnostic(diag::unsupported_builtin_type, type->getTypeClassName())); - // ExtInt is not supported in Swift. + // BitInt is not supported in Swift. return Type(); } diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index d82b092182fdb..811d4ab87a05c 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -933,8 +933,8 @@ namespace { case clang::Type::Pipe: llvm_unreachable("OpenCL type in ABI lowering?"); - case clang::Type::ExtInt: - llvm_unreachable("ExtInt type in ABI lowering?"); + case clang::Type::BitInt: + llvm_unreachable("BitInt type in ABI lowering?"); case clang::Type::ConstantMatrix: { llvm_unreachable("ConstantMatrix type in ABI lowering?"); From 0dff9ac15022eeea2ae02e1af7a4adbb2efb8a25 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 27 Apr 2022 17:05:21 -0700 Subject: [PATCH 036/491] [next] Update `PPCallbacks::InclusionDirective` overrides `InclusionDirective` was changed in llvm/llvm-project d79ad2f1dbc2db63121620f55d6cfa915f2733ac to pass an `Optional` rather than a `FileEntry *`. Update overrides in Swift to use the new API. --- lib/ClangImporter/ClangImporter.cpp | 20 ++++++++++++-------- lib/ClangImporter/ImporterImpl.h | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 50741115becec..a0c6a9eabba28 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -104,7 +104,7 @@ namespace { StringRef FileName, bool IsAngled, clang::CharSourceRange FilenameRange, - const clang::FileEntry *File, + Optional File, StringRef SearchPath, StringRef RelativePath, const clang::Module *Imported, @@ -282,14 +282,14 @@ class BridgingPPTracker : public clang::PPCallbacks { StringRef FileName, bool IsAngled, clang::CharSourceRange FilenameRange, - const clang::FileEntry *File, + Optional File, StringRef SearchPath, StringRef RelativePath, const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) override{ if (!Imported) { if (File) - Impl.BridgeHeaderFiles.insert(File); + Impl.BridgeHeaderFiles.insert(*File); return; } // Synthesize identifier locations. @@ -2930,16 +2930,18 @@ void ClangImporter::lookupBridgingHeaderDecls( bool ClangImporter::lookupDeclsFromHeader(StringRef Filename, llvm::function_ref filter, llvm::function_ref receiver) const { - auto File = getClangPreprocessor().getFileManager().getFile(Filename); - if (!File) + llvm::Expected ExpectedFile = + getClangPreprocessor().getFileManager().getFileRef(Filename); + if (!ExpectedFile) return true; + clang::FileEntryRef File = *ExpectedFile; auto &ClangCtx = getClangASTContext(); auto &ClangSM = ClangCtx.getSourceManager(); auto &ClangPP = getClangPreprocessor(); // Look up the header in the includes of the bridging header. - if (Impl.BridgeHeaderFiles.count(*File)) { + if (Impl.BridgeHeaderFiles.count(File)) { auto headerFilter = [&](ClangNode ClangN) -> bool { if (ClangN.isNull()) return false; @@ -2948,7 +2950,9 @@ bool ClangImporter::lookupDeclsFromHeader(StringRef Filename, if (ClangLoc.isInvalid()) return false; - if (ClangSM.getFileEntryForID(ClangSM.getFileID(ClangLoc)) != *File) + Optional LocRef = + ClangSM.getFileEntryRefForID(ClangSM.getFileID(ClangLoc)); + if (!LocRef || *LocRef != File) return false; return filter(ClangN); @@ -2958,7 +2962,7 @@ bool ClangImporter::lookupDeclsFromHeader(StringRef Filename, return false; } - clang::FileID FID = ClangSM.translateFile(*File); + clang::FileID FID = ClangSM.translateFile(File); if (FID.isInvalid()) return false; diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 5a4a4b168e3d8..713460da5d63f 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -761,7 +761,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// Tracks macro definitions from the bridging header. std::vector BridgeHeaderMacros; /// Tracks included headers from the bridging header. - llvm::DenseSet BridgeHeaderFiles; + llvm::DenseSet BridgeHeaderFiles; void addBridgeHeaderTopLevelDecls(clang::Decl *D); bool shouldIgnoreBridgeHeaderTopLevelDecl(clang::Decl *D); From f2e14e48679187cfff6daf141599f3e0db88da6a Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 27 Apr 2022 17:39:12 -0700 Subject: [PATCH 037/491] [next] Define DEBUG_TYPE after includes Not sure which LLVM commit added an `#undef` for `DEBUG_TYPE` in a header transitively included by these files, but it doesn't seem uncommon for headers to define and undefine their own `DEBUG_TYPE`. Move `#define DEBUG_TYPE` after the includes to prevent it being undefined. --- lib/IRGen/IRGenDebugInfo.cpp | 4 ++-- lib/IRGen/IRGenSIL.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index b845928deaa51..6f255b5268889 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -14,8 +14,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "debug-info" - #include "IRGenDebugInfo.h" #include "GenOpaque.h" #include "GenStruct.h" @@ -68,6 +66,8 @@ #include "swift/AST/ASTDemangler.h" #endif +#define DEBUG_TYPE "debug-info" + using namespace swift; using namespace irgen; diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 27acbc8c017b7..7ecc263745f4e 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -15,8 +15,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "irgensil" - #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticsIRGen.h" #include "swift/AST/IRGenOptions.h" @@ -93,6 +91,8 @@ #include "NativeConventionSchema.h" #include "ReferenceTypeInfo.h" +#define DEBUG_TYPE "irgensil" + using namespace swift; using namespace irgen; From a743a4ec224613679fcf63d1c690f3e709435395 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 27 Apr 2022 17:53:12 -0700 Subject: [PATCH 038/491] [next] Replace include for findDbgValues `findDbgValues` was moved from `llvm/Transforms/Utils/Local.h` into `llvm/IR/DebugInfo.h` in llvm/llvm-project 0ebf9a8e34b6aeee520aa5dc6916a155c5789533. Include that header instead. --- lib/IRGen/IRGenSIL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 7ecc263745f4e..d9ac22acd5d6f 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -48,6 +48,7 @@ #include "llvm/ADT/TinyPtrVector.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" @@ -58,7 +59,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/SaveAndRestore.h" -#include "llvm/Transforms/Utils/Local.h" #include "CallEmission.h" #include "EntryPointArgumentEmission.h" From b521dc7c4263c324235cc55999c453e2e8370915 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 28 Apr 2022 11:45:45 -0700 Subject: [PATCH 039/491] [next] Handle new ObjectFormatTypes LLVM has added two new object format types, add them as unhandled for now. --- lib/IRGen/GenClass.cpp | 2 ++ lib/IRGen/GenDecl.cpp | 18 ++++++++++++++++++ lib/IRGen/GenMeta.cpp | 2 ++ lib/IRGen/GenReflection.cpp | 2 ++ lib/IRGen/IRGen.cpp | 2 ++ 5 files changed, 26 insertions(+) diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp index c3673d343bee3..ee623b54db9ff 100644 --- a/lib/IRGen/GenClass.cpp +++ b/lib/IRGen/GenClass.cpp @@ -2246,7 +2246,9 @@ namespace { case llvm::Triple::Wasm: var->setSection(".data"); break; + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("Don't know how to emit private global constants for " "the selected object format."); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 1ad1898e6fdc1..a455cfa89d577 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -1015,7 +1015,9 @@ std::string IRGenModule::GetObjCSectionName(StringRef Section, assert(Section.substr(0, 2) == "__" && "expected the name to begin with __"); switch (TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("must know the object file format"); case llvm::Triple::MachO: @@ -1036,7 +1038,9 @@ std::string IRGenModule::GetObjCSectionName(StringRef Section, void IRGenModule::SetCStringLiteralSection(llvm::GlobalVariable *GV, ObjCLabelType Type) { switch (TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("must know the object file format"); case llvm::Triple::MachO: @@ -1643,7 +1647,9 @@ void IRGenerator::noteUseOfOpaqueTypeDescriptor(OpaqueTypeDecl *opaque) { static std::string getDynamicReplacementSection(IRGenModule &IGM) { std::string sectionName; switch (IGM.TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("Don't know how to emit field records table for " "the selected object format."); @@ -1665,7 +1671,9 @@ static std::string getDynamicReplacementSection(IRGenModule &IGM) { static std::string getDynamicReplacementSomeSection(IRGenModule &IGM) { std::string sectionName; switch (IGM.TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("Don't know how to emit field records table for " "the selected object format."); @@ -2035,7 +2043,9 @@ void IRGenModule::emitVTableStubs() { static std::string getEntryPointSection(IRGenModule &IGM) { std::string sectionName; switch (IGM.TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("Don't know how to emit field records table for " "the selected object format."); @@ -3870,7 +3880,9 @@ llvm::Constant *IRGenModule::emitSwiftProtocols(bool asContiguousArray) { StringRef sectionName; switch (TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("Don't know how to emit protocols for " "the selected object format."); @@ -3968,7 +3980,9 @@ llvm::Constant *IRGenModule::emitProtocolConformances(bool asContiguousArray) { StringRef sectionName; switch (TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("Don't know how to emit protocol conformances for " "the selected object format."); @@ -4067,7 +4081,9 @@ llvm::Constant *IRGenModule::emitTypeMetadataRecords(bool asContiguousArray) { case llvm::Triple::COFF: sectionName = ".sw5tymd$B"; break; + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("Don't know how to emit type metadata table for " "the selected object format."); @@ -4166,7 +4182,9 @@ void IRGenModule::emitAccessibleFunctions() { StringRef sectionName; switch (TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("Don't know how to emit accessible functions for " "the selected object format."); diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 5cbe8277db8b1..35372ec98638a 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -117,7 +117,9 @@ void IRGenModule::setTrueConstGlobal(llvm::GlobalVariable *var) { disableAddressSanitizer(*this, var); switch (TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("unknown object format"); case llvm::Triple::MachO: diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index fbe33707583c4..5ee2c446979e2 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -1360,7 +1360,9 @@ static std::string getReflectionSectionName(IRGenModule &IGM, SmallString<50> SectionName; llvm::raw_svector_ostream OS(SectionName); switch (IGM.TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("unknown object format"); case llvm::Triple::XCOFF: diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index e7fcb18d97c69..7d194c029f216 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -1541,7 +1541,9 @@ swift::createSwiftModuleObjectFile(SILModule &SILMod, StringRef Buffer, Data, "__Swift_AST"); std::string Section; switch (IGM.TargetInfo.OutputObjectFormat) { + case llvm::Triple::DXContainer: case llvm::Triple::GOFF: + case llvm::Triple::SPIRV: case llvm::Triple::UnknownObjectFormat: llvm_unreachable("unknown object format"); case llvm::Triple::XCOFF: From cedf5b6c922cdb9db835fec1ac2e73000325853f Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 28 Apr 2022 11:55:29 -0700 Subject: [PATCH 040/491] [next] Add missing include Not sure which header it was removed from. Could be worth trying IWYU at some point. --- lib/IRGen/GenDecl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index a455cfa89d577..cb9580a3e16d0 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -40,6 +40,7 @@ #include "clang/AST/GlobalDecl.h" #include "clang/CodeGen/CodeGenABITypes.h" #include "clang/CodeGen/ModuleBuilder.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalAlias.h" From caa5003c7c08a613bbd2cb0a8f1bb39b9d8ef3ad Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 28 Apr 2022 12:08:39 -0700 Subject: [PATCH 041/491] [next] Pass LLVM context to AttrBuilder constructor The `AttrBuilder` API was changed in llvm/llvm-project d2cc6c2d0c2f8a6e272110416a3fd579ed5a3ac1 to now take a `LLVMContext &` as part of its constructor. Update uses to pass one in. --- lib/IRGen/GenCall.cpp | 14 +++++++------- lib/IRGen/GenDecl.cpp | 4 ++-- lib/IRGen/GenFunc.cpp | 2 +- lib/IRGen/GenObjC.cpp | 2 +- lib/IRGen/IRGenModule.cpp | 10 +++++----- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 811d4ab87a05c..7d2ad78bae043 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -255,7 +255,7 @@ static void addIndirectValueParameterAttributes(IRGenModule &IGM, llvm::AttributeList &attrs, const TypeInfo &ti, unsigned argIndex) { - llvm::AttrBuilder b; + llvm::AttrBuilder b(IGM.getLLVMContext()); // Value parameter pointers can't alias or be captured. b.addAttribute(llvm::Attribute::NoAlias); b.addAttribute(llvm::Attribute::NoCapture); @@ -269,7 +269,7 @@ static void addInoutParameterAttributes(IRGenModule &IGM, SILType paramSILType, llvm::AttributeList &attrs, const TypeInfo &ti, unsigned argIndex, bool aliasable) { - llvm::AttrBuilder b; + llvm::AttrBuilder b(IGM.getLLVMContext()); // Thanks to exclusivity checking, it is not possible to alias inouts except // those that are inout_aliasable. if (!aliasable && paramSILType.getASTType()->getAnyPointerElementType()) { @@ -318,7 +318,7 @@ static void addIndirectResultAttributes(IRGenModule &IGM, llvm::AttributeList &attrs, unsigned paramIndex, bool allowSRet, llvm::Type *storageType) { - llvm::AttrBuilder b; + llvm::AttrBuilder b(IGM.getLLVMContext()); b.addAttribute(llvm::Attribute::NoAlias); b.addAttribute(llvm::Attribute::NoCapture); if (allowSRet) { @@ -330,21 +330,21 @@ static void addIndirectResultAttributes(IRGenModule &IGM, void IRGenModule::addSwiftAsyncContextAttributes(llvm::AttributeList &attrs, unsigned argIndex) { - llvm::AttrBuilder b; + llvm::AttrBuilder b(getLLVMContext()); b.addAttribute(llvm::Attribute::SwiftAsync); attrs = attrs.addParamAttributes(this->getLLVMContext(), argIndex, b); } void IRGenModule::addSwiftSelfAttributes(llvm::AttributeList &attrs, unsigned argIndex) { - llvm::AttrBuilder b; + llvm::AttrBuilder b(getLLVMContext()); b.addAttribute(llvm::Attribute::SwiftSelf); attrs = attrs.addParamAttributes(this->getLLVMContext(), argIndex, b); } void IRGenModule::addSwiftErrorAttributes(llvm::AttributeList &attrs, unsigned argIndex) { - llvm::AttrBuilder b; + llvm::AttrBuilder b(getLLVMContext()); // Don't add the swifterror attribute on ABIs that don't pass it in a register. // We create a shadow stack location of the swifterror parameter for the // debugger on such platforms and so we can't mark the parameter with a @@ -365,7 +365,7 @@ void irgen::addByvalArgumentAttributes(IRGenModule &IGM, llvm::AttributeList &attrs, unsigned argIndex, Alignment align, llvm::Type *storageType) { - llvm::AttrBuilder b; + llvm::AttrBuilder b(IGM.getLLVMContext()); b.addByValAttr(storageType); b.addAttribute(llvm::Attribute::getWithAlignment( IGM.getLLVMContext(), llvm::Align(align.getValue()))); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index cb9580a3e16d0..d47fe56390bad 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -2271,7 +2271,7 @@ llvm::Function *irgen::createFunction(IRGenModule &IGM, linkInfo.getDLLStorage()}) .to(fn, linkInfo.isForDefinition()); - llvm::AttrBuilder initialAttrs; + llvm::AttrBuilder initialAttrs(IGM.getLLVMContext()); IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode); // Merge initialAttrs with attrs. auto updatedAttrs = signature.getAttributes().addFnAttributes( @@ -3116,7 +3116,7 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded( thunk->setCallingConv(llvm::CallingConv::C); - llvm::AttrBuilder attrBuilder; + llvm::AttrBuilder attrBuilder(IGM.getLLVMContext()); IGM.constructInitialFnAttributes(attrBuilder); attrBuilder.addAttribute(llvm::Attribute::AlwaysInline); llvm::AttributeList attr = signature.getAttributes().addFnAttributes( diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 859913e9a93e5..b7bc23fdbf7ba 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -1263,7 +1263,7 @@ static llvm::Value *emitPartialApplicationForwarder(IRGenModule &IGM, fwd->setAttributes(outAttrs); // Merge initial attributes with outAttrs. - llvm::AttrBuilder b; + llvm::AttrBuilder b(IGM.getLLVMContext()); IGM.constructInitialFnAttributes(b); fwd->addFnAttrs(b); diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp index 72800ae067301..f415ce043ea56 100644 --- a/lib/IRGen/GenObjC.cpp +++ b/lib/IRGen/GenObjC.cpp @@ -719,7 +719,7 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM, fwd->setAttributes(attrs); // Merge initial attributes with attrs. - llvm::AttrBuilder b; + llvm::AttrBuilder b(IGM.getLLVMContext()); IGM.constructInitialFnAttributes(b); fwd->addFnAttrs(b); diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index e361a16a9bfbe..ef49741163afd 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -939,9 +939,9 @@ llvm::Constant *swift::getRuntimeFn(llvm::Module &Module, && !::useDllStorage(llvm::Triple(Module.getTargetTriple()))) fn->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); - llvm::AttrBuilder buildFnAttr; - llvm::AttrBuilder buildRetAttr; - llvm::AttrBuilder buildFirstParamAttr; + llvm::AttrBuilder buildFnAttr(Module.getContext()); + llvm::AttrBuilder buildRetAttr(Module.getContext()); + llvm::AttrBuilder buildFirstParamAttr(Module.getContext()); for (auto Attr : attrs) { if (isReturnAttribute(Attr)) @@ -1208,7 +1208,7 @@ void IRGenModule::setHasNoFramePointer(llvm::AttrBuilder &Attrs) { } void IRGenModule::setHasNoFramePointer(llvm::Function *F) { - llvm::AttrBuilder b; + llvm::AttrBuilder b(getLLVMContext()); setHasNoFramePointer(b); F->addFnAttrs(b); } @@ -1232,7 +1232,7 @@ void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs, } llvm::AttributeList IRGenModule::constructInitialAttributes() { - llvm::AttrBuilder b; + llvm::AttrBuilder b(getLLVMContext()); constructInitialFnAttributes(b); return llvm::AttributeList().addFnAttributes(getLLVMContext(), b); } From 59bc1c9b4a50acb5ef9e37d3334c91b1af394fb9 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 2 May 2022 14:41:21 -0700 Subject: [PATCH 042/491] [next] Desugar new UsingType llvm/llvm-project added a new `UsingType` for types found via `UsingDecl` in e1600db19d6303f84b995acb9340459694e06ea9. Desugar in clang importer to previous `RecordDecl`. --- lib/ClangImporter/ImportType.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index a8769be584048..9280ca2b6f0be 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -929,6 +929,7 @@ namespace { SUGAR_TYPE(Adjusted) SUGAR_TYPE(SubstTemplateTypeParm) SUGAR_TYPE(Elaborated) + SUGAR_TYPE(Using) ImportResult VisitDecayedType(const clang::DecayedType *type) { clang::ASTContext &clangCtx = Impl.getClangASTContext(); From ff42c48db4107b56e2ca37e464d00215aae88629 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 28 Apr 2022 14:12:02 -0700 Subject: [PATCH 043/491] [next] Handle new BTFTagAttributedType Introduced in llvm/llvm-project 3251ba2d0fcf5223fce3e270b91c54f548664b4e. --- .../ClangImporter/SwiftAbstractBasicReader.h | 5 +++++ .../ClangImporter/SwiftAbstractBasicWriter.h | 16 +++++++++++++++- lib/ClangImporter/ImportType.cpp | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/swift/ClangImporter/SwiftAbstractBasicReader.h b/include/swift/ClangImporter/SwiftAbstractBasicReader.h index 300f64d8df0bf..0889de8d9cc39 100644 --- a/include/swift/ClangImporter/SwiftAbstractBasicReader.h +++ b/include/swift/ClangImporter/SwiftAbstractBasicReader.h @@ -89,6 +89,11 @@ class DataStreamBasicReader clang::QualType type = asImpl().readTypeRef(); return getASTContext().getQualifiedType(type, quals); } + + const clang::BTFTypeTagAttr *readBTFTypeTagAttr() { + llvm::report_fatal_error("Read BTFTypeTagAttr that should never have been" + " serialized"); + } }; } diff --git a/include/swift/ClangImporter/SwiftAbstractBasicWriter.h b/include/swift/ClangImporter/SwiftAbstractBasicWriter.h index acc7593c9c5c0..be8e2bf3c0e57 100644 --- a/include/swift/ClangImporter/SwiftAbstractBasicWriter.h +++ b/include/swift/ClangImporter/SwiftAbstractBasicWriter.h @@ -21,6 +21,7 @@ #define SWIFT_CLANGIMPORTER_SWIFTABSTRACTBASICWRITER_H #include "clang/AST/AbstractTypeWriter.h" +#include "clang/AST/Type.h" namespace swift { @@ -80,11 +81,24 @@ class DataStreamBasicWriter assert(!type.isNull()); auto split = type.split(); - asImpl().writeQualifiers(split.Quals); + auto qualifiers = split.Quals; + // Unwrap BTFTagAttributeType and merge any of its qualifiers. + while (auto btfType = dyn_cast(split.Ty)) { + split = btfType->getWrappedType().split(); + qualifiers.addQualifiers(split.Quals); + } + + asImpl().writeQualifiers(qualifiers); // Just recursively visit the given type. asImpl().writeTypeRef(split.Ty); } + + void writeBTFTypeTagAttr(const clang::BTFTypeTagAttr *attr) { + // BTFTagAttributeType is explicitly unwrapped above, so we should never + // hit any of its attributes. + llvm::report_fatal_error("Should never hit BTFTypeTagAttr serialization"); + } }; } diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 9280ca2b6f0be..705c567740bde 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -930,6 +930,7 @@ namespace { SUGAR_TYPE(SubstTemplateTypeParm) SUGAR_TYPE(Elaborated) SUGAR_TYPE(Using) + SUGAR_TYPE(BTFTagAttributed) ImportResult VisitDecayedType(const clang::DecayedType *type) { clang::ASTContext &clangCtx = Impl.getClangASTContext(); From ba3f582155b165796193a9887a95226ad98ed3c3 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 4 May 2022 12:59:46 -0700 Subject: [PATCH 044/491] [next] Do not use libcxx standalone build This was removed in llvm/llvm-project 6f17768e11480063f4c2bcbeea559505fee3ea19. Use new build instead. --- utils/build-script-impl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/build-script-impl b/utils/build-script-impl index 723b40ad242f5..f005af1255572 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -1263,7 +1263,7 @@ FOUNDATION_STATIC_SOURCE_DIR="${WORKSPACE}/swift-corelibs-foundation" LIBDISPATCH_SOURCE_DIR="${WORKSPACE}/swift-corelibs-libdispatch" LIBDISPATCH_STATIC_SOURCE_DIR="${WORKSPACE}/swift-corelibs-libdispatch" LIBICU_SOURCE_DIR="${WORKSPACE}/icu" -LIBCXX_SOURCE_DIR="${WORKSPACE}/llvm-project/libcxx" +LIBCXX_SOURCE_DIR="${WORKSPACE}/llvm-project/runtimes" EXPERIMENTAL_STRING_PROCESSING_SOURCE_DIR="${WORKSPACE}/swift-experimental-string-processing" LIBXML2_SOURCE_DIR="${WORKSPACE}/libxml2" @@ -1900,8 +1900,9 @@ for host in "${ALL_HOSTS[@]}"; do ;; libcxx) - build_targets=() + build_targets=(cxx) cmake_options=( + -DLLVM_ENABLE_RUNTIMES="libcxx" -DLIBCXX_INSTALL_LIBRARY=OFF "${cmake_options[@]}" "${llvm_cmake_options[@]}" ) From edcd53b09fc89a75bec69d2790193e209be87453 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 9 May 2022 16:17:55 -0700 Subject: [PATCH 045/491] [next] Disable opaque pointers by default LLVM has enabled opaque pointers by default. Disable while we migrate. Note that individual tests can have opaque pointers enabled by using `-Xcc -Xclang -Xcc -opaque-pointers`. --- lib/ClangImporter/ClangImporter.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 8a0e31f24e8e0..8dee5f076d300 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -865,6 +865,9 @@ importer::addCommonInvocationArguments( invocationArgStrs.push_back("-fansi-escape-codes"); + invocationArgStrs.push_back("-Xclang"); + invocationArgStrs.push_back("-no-opaque-pointers"); + for (auto extraArg : importerOpts.ExtraArgs) { invocationArgStrs.push_back(extraArg); } From f2bd6ce9cbe93287cd0119441ebb05060c3f067f Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 10 May 2022 11:42:48 -0700 Subject: [PATCH 046/491] [next] Remove subminor version from various tests The "0" subminor is no longer included after 114b4d96e437e0456729a838c7162da118c9ae63 (which generally doesn't add a subminor). Remove it from checks depending on it. --- test/Sema/availability_and_delayed_parsing.swift | 2 +- test/Sema/availability_refinement_contexts.swift | 2 +- ...lability_refinement_contexts_target_min_inlining.swift | 8 ++++---- test/Sema/availability_versions.swift | 6 +++--- test/SymbolGraph/Module/Module.swift | 3 +-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/test/Sema/availability_and_delayed_parsing.swift b/test/Sema/availability_and_delayed_parsing.swift index 2e28e0b9e555e..9461e2df770f0 100644 --- a/test/Sema/availability_and_delayed_parsing.swift +++ b/test/Sema/availability_and_delayed_parsing.swift @@ -21,7 +21,7 @@ @available(macOS 10.12, *) public func foo() { } -// TRC-API: (root versions=[10.10.0,+Inf) +// TRC-API: (root versions=[10.10,+Inf) // TRC-API: (decl versions=[10.12,+Inf) decl=foo() #if canImport(Swift) diff --git a/test/Sema/availability_refinement_contexts.swift b/test/Sema/availability_refinement_contexts.swift index 088a644384ff6..53005ac16a18b 100644 --- a/test/Sema/availability_refinement_contexts.swift +++ b/test/Sema/availability_refinement_contexts.swift @@ -3,7 +3,7 @@ // REQUIRES: OS=macosx -// CHECK: {{^}}(root versions=[10.{{[0-9]+}}.0,+Inf) +// CHECK: {{^}}(root versions=[10.{{[0-9]+}},+Inf) // CHECK-NEXT: {{^}} (decl versions=[10.51,+Inf) decl=SomeClass // CHECK-NEXT: {{^}} (decl versions=[10.52,+Inf) decl=someMethod() diff --git a/test/Sema/availability_refinement_contexts_target_min_inlining.swift b/test/Sema/availability_refinement_contexts_target_min_inlining.swift index 321386501ed1b..79663543d92f5 100644 --- a/test/Sema/availability_refinement_contexts_target_min_inlining.swift +++ b/test/Sema/availability_refinement_contexts_target_min_inlining.swift @@ -11,8 +11,8 @@ // CHECK-tvos: {{^}}(root versions=[9.0,+Inf) // CHECK-watchos: {{^}}(root versions=[2.0,+Inf) -// CHECK-macosx-NEXT: {{^}} (api_boundary versions=[10.15.0,+Inf) decl=foo() -// CHECK-ios-NEXT: {{^}} (api_boundary versions=[13.0.0,+Inf) decl=foo() -// CHECK-tvos-NEXT: {{^}} (api_boundary versions=[13.0.0,+Inf) decl=foo() -// CHECK-watchos-NEXT: {{^}} (api_boundary versions=[6.0.0,+Inf) decl=foo() +// CHECK-macosx-NEXT: {{^}} (api_boundary versions=[10.15,+Inf) decl=foo() +// CHECK-ios-NEXT: {{^}} (api_boundary versions=[13.0,+Inf) decl=foo() +// CHECK-tvos-NEXT: {{^}} (api_boundary versions=[13.0,+Inf) decl=foo() +// CHECK-watchos-NEXT: {{^}} (api_boundary versions=[6.0,+Inf) decl=foo() func foo() {} diff --git a/test/Sema/availability_versions.swift b/test/Sema/availability_versions.swift index df04122a1eabd..fca1c4f3dba3f 100644 --- a/test/Sema/availability_versions.swift +++ b/test/Sema/availability_versions.swift @@ -1434,7 +1434,7 @@ protocol HasMethodF { class TriesToConformWithFunctionIntroducedOn10_51 : HasMethodF { @available(OSX, introduced: 10.51) - func f(_ p: Int) { } // expected-error {{protocol 'HasMethodF' requires 'f' to be available in macOS 10.50.0 and newer}} + func f(_ p: Int) { } // expected-error {{protocol 'HasMethodF' requires 'f' to be available in macOS 10.50 and newer}} } @@ -1450,7 +1450,7 @@ class SuperHasMethodF { func f(_ p: Int) { } // expected-note {{'f' declared here}} } -class TriesToConformWithPotentiallyUnavailableFunctionInSuperClass : SuperHasMethodF, HasMethodF { // expected-error {{protocol 'HasMethodF' requires 'f' to be available in macOS 10.50.0 and newer}} +class TriesToConformWithPotentiallyUnavailableFunctionInSuperClass : SuperHasMethodF, HasMethodF { // expected-error {{protocol 'HasMethodF' requires 'f' to be available in macOS 10.50 and newer}} // The conformance here is generating an error on f in the super class. } @@ -1474,7 +1474,7 @@ class ConformsByOverridingFunctionInSuperClass : SuperHasMethodF, HasMethodF { class HasNoMethodF1 { } extension HasNoMethodF1 : HasMethodF { @available(OSX, introduced: 10.51) - func f(_ p: Int) { } // expected-error {{protocol 'HasMethodF' requires 'f' to be available in macOS 10.50.0 and newer}} + func f(_ p: Int) { } // expected-error {{protocol 'HasMethodF' requires 'f' to be available in macOS 10.50 and newer}} } class HasNoMethodF2 { } diff --git a/test/SymbolGraph/Module/Module.swift b/test/SymbolGraph/Module/Module.swift index 913dbafa38ec7..e5117634a55b6 100644 --- a/test/SymbolGraph/Module/Module.swift +++ b/test/SymbolGraph/Module/Module.swift @@ -14,7 +14,6 @@ public struct S { // CHECK: vendor // CHECK-NEXT: operatingSystem // CHECK-NEXT: name -// CHECK-NEXT: minimumVersion +// CHECK-NEXT: minimumVersion // CHECK-NEXT: major // CHECK-NEXT: minor -// CHECK-NEXT: patch From a6a6ae456ae549edcc9ee2da387802b9e46e0198 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 10 May 2022 15:41:19 -0700 Subject: [PATCH 047/491] [next] Use SmallString over reserved std::string A `llvm::raw_string_ostream` is unbuffered, but calling `SetBufferSize` adds a buffer. Since its destructor doesn't flush (as it assumes it is unbuffered), this then asserts in the `llvm::raw_ostream` destructor. Remove the `SetBufferSize` call (the string is the underlying buffer) and also switch to using `llvm::SmallString` instead. This fixes a crash in `SourceKit/SyntaxTree/basic.swift` and `SourceKit/SyntaxTree/pound_if.swift`, which are presumably the only two tests that actually use this. --- tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp index 42138c3651ea0..bb51581c0c6df 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp @@ -3111,12 +3111,9 @@ void serializeSyntaxTreeAsJson( auto StartClock = clock(); // 4096 is a heuristic buffer size that appears to usually be able to fit an // incremental syntax tree - size_t ReserveBufferSize = 4096; - std::string SyntaxTreeString; - SyntaxTreeString.reserve(ReserveBufferSize); + llvm::SmallString<4096> SyntaxTreeString; { - llvm::raw_string_ostream SyntaxTreeStream(SyntaxTreeString); - SyntaxTreeStream.SetBufferSize(ReserveBufferSize); + llvm::raw_svector_ostream SyntaxTreeStream(SyntaxTreeString); swift::json::Output::UserInfoMap JsonUserInfo; swift::json::Output SyntaxTreeOutput(SyntaxTreeStream, JsonUserInfo, /*PrettyPrint=*/false); From f05fab3f3c03cae715859bf41dbb69b70d8ac392 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 10 May 2022 16:17:48 -0700 Subject: [PATCH 048/491] [next] Update module_deps_cache_reuse.swift to be more stable Change a few `CHECK-NEXT` lines to just `CHECK` where it's not actually important that they are the next arguments. --- test/ScanDependencies/module_deps_cache_reuse.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/ScanDependencies/module_deps_cache_reuse.swift b/test/ScanDependencies/module_deps_cache_reuse.swift index 55c0573ab299f..c95e20ce1503d 100644 --- a/test/ScanDependencies/module_deps_cache_reuse.swift +++ b/test/ScanDependencies/module_deps_cache_reuse.swift @@ -111,11 +111,11 @@ import SubE // CHECK-NEXT: "-frontend" // CHECK-NEXT: "-only-use-extra-clang-opts // CHECK-NOT: "BUILD_DIR/bin/clang" -// CHECK-NEXT: "-Xcc" +// CHECK: "-Xcc" // CHECK-NEXT: "-fsyntax-only", -// CHECK: "-fsystem-module", -// CHECK-NEXT: "-emit-pcm", -// CHECK-NEXT: "-module-name", +// CHECK: "-fsystem-module", +// CHECK: "-emit-pcm", +// CHECK: "-module-name", // CHECK-NEXT: "C" /// --------Swift module E @@ -129,7 +129,7 @@ import SubE // CHECK-SAME: E.swiftinterface /// --------Swift module F -// CHECK: "modulePath": "F.swiftmodule", +// CHECK-LABEL: "modulePath": "F.swiftmodule", // CHECK-NEXT: "sourceFiles": [ // CHECK-NEXT: ], // CHECK-NEXT: "directDependencies": [ From 6094e9f22fdd551c4cc24fdc5317e5d950b409a7 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 11 May 2022 15:01:12 -0700 Subject: [PATCH 049/491] [next] Add missing void for function taking no arguments --- test/PrintAsObjC/Inputs/arc-conventions.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/PrintAsObjC/Inputs/arc-conventions.m b/test/PrintAsObjC/Inputs/arc-conventions.m index 690e58ae02722..d19f1aaf5dcb9 100644 --- a/test/PrintAsObjC/Inputs/arc-conventions.m +++ b/test/PrintAsObjC/Inputs/arc-conventions.m @@ -1,7 +1,7 @@ @import Foundation; #import "swift.h" -int main() { +int main(void) { @autoreleasepool { Test *test = [[Test alloc] init]; id result = [test initAllTheThings]; // CHECK: method called From 798134f605a21bf73e89c45c23558e94f2fd1b77 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 11 May 2022 15:19:26 -0700 Subject: [PATCH 050/491] [next] Fix removing supplementary outputs d8d8bdc0071e641706a5ddf0d6e91f9fec29cd5a changed how supplementary outputs were removed, but since tests weren't able to be run there was inevitably a bug. The `return` should have been a `continue`. --- lib/Driver/FrontendUtil.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Driver/FrontendUtil.cpp b/lib/Driver/FrontendUtil.cpp index 3f0e340b7e861..10da67f95adbd 100644 --- a/lib/Driver/FrontendUtil.cpp +++ b/lib/Driver/FrontendUtil.cpp @@ -46,7 +46,7 @@ static void removeSupplementaryOutputs(llvm::opt::ArgList &ArgList) { for (llvm::opt::Arg *Arg : ArgList.getArgs()) { if (!Arg) - return; + continue; const llvm::opt::Option &Opt = Arg->getOption(); if (Opt.hasFlag(options::SupplementaryOutput)) @@ -57,6 +57,7 @@ static void removeSupplementaryOutputs(llvm::opt::ArgList &ArgList) { ArgList.eraseArg(Specifier); } } + bool swift::driver::getSingleFrontendInvocationFromDriverArguments( ArrayRef Argv, DiagnosticEngine &Diags, llvm::function_ref FrontendArgs)> Action, From 50ecb47a4605edceb9a884791c910394535ec907 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 11 May 2022 15:42:21 -0700 Subject: [PATCH 051/491] [next] Revert "[rebranch] Update test broken in merge" This reverts commit ee6706f3d996d8e0d196703a3c89bc49c715e3d0. With the latest LLVM rebranch this test now matches how it was written originally. --- test/DebugInfo/async-args.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/DebugInfo/async-args.swift b/test/DebugInfo/async-args.swift index b7201d6e1d831..c287307b4eae2 100644 --- a/test/DebugInfo/async-args.swift +++ b/test/DebugInfo/async-args.swift @@ -10,10 +10,10 @@ func withGenericArg(_ msg: T) async { // This odd debug info is part of a contract with CoroSplit/CoroFrame to fix // this up after coroutine splitting. // CHECK-LABEL: {{^define .*}} @"$s1M14withGenericArgyyxYalF"(%swift.context* swiftasync %0 - // CHECK: call void @llvm.dbg.declare(metadata %swift.type** % - // CHECK-SAME: metadata ![[TAU:[0-9]+]], metadata !DIExpression() - // CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** % - // CHECK-SAME: metadata ![[MSG:[0-9]+]], metadata !DIExpression(DW_OP_deref)) + // CHECK: call void @llvm.dbg.declare(metadata %swift.context* %0 + // CHECK-SAME: metadata ![[MSG:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, {{.*}}DW_OP_deref)) + // CHECK: call void @llvm.dbg.declare(metadata %swift.context* %0 + // CHECK-SAME: metadata ![[TAU:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, await forceSplit() // CHECK-LABEL: {{^define .*}} @"$s1M14withGenericArgyyxYalFTQ0_"(i8* swiftasync %0) From 427a689a966343a99b67ae81c7d1f31decfbe16b Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 11 May 2022 16:34:12 -0700 Subject: [PATCH 052/491] [next] Convert `const char *` fields to `StringRef` llvm/llvm-project d0262c2394f46bb7da2a75529413d625c70908e5 added a new default bool param to the two constructors in `SmallVectorMemoryBuffer`. Since `options.OutputPath` is a `const char *` and that can be promoted to a `bool`, the constructor being called was changed to the first constructor (with a default buffer name) - promotion is preferred over conversion. Convert the various output paths to a `StringRef` - all their uses converted to `StringRef` anyway. Also specify the default parameter in order to maintain the old behaviour, which didn't require a null terminator. --- .../Serialization/SerializationOptions.h | 6 ++--- lib/Frontend/Frontend.cpp | 6 ++--- lib/Frontend/ModuleInterfaceBuilder.cpp | 2 +- lib/FrontendTool/FrontendTool.cpp | 2 +- lib/Serialization/Serialization.cpp | 25 +++++++++++-------- .../SILFunctionExtractor.cpp | 2 +- tools/sil-opt/SILOpt.cpp | 2 +- 7 files changed, 24 insertions(+), 21 deletions(-) diff --git a/include/swift/Serialization/SerializationOptions.h b/include/swift/Serialization/SerializationOptions.h index a07d726913c08..207a98062b512 100644 --- a/include/swift/Serialization/SerializationOptions.h +++ b/include/swift/Serialization/SerializationOptions.h @@ -29,9 +29,9 @@ namespace swift { SerializationOptions &operator=(SerializationOptions &&) = default; ~SerializationOptions() = default; - const char *OutputPath = nullptr; - const char *DocOutputPath = nullptr; - const char *SourceInfoOutputPath = nullptr; + StringRef OutputPath; + StringRef DocOutputPath; + StringRef SourceInfoOutputPath; std::string ABIDescriptorPath; bool emptyABIDescriptor = false; llvm::VersionTuple UserModuleVersion; diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index e11946d535b71..c417a60074c97 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -140,9 +140,9 @@ SerializationOptions CompilerInvocation::computeSerializationOptions( const FrontendOptions &opts = getFrontendOptions(); SerializationOptions serializationOpts; - serializationOpts.OutputPath = outs.ModuleOutputPath.c_str(); - serializationOpts.DocOutputPath = outs.ModuleDocOutputPath.c_str(); - serializationOpts.SourceInfoOutputPath = outs.ModuleSourceInfoOutputPath.c_str(); + serializationOpts.OutputPath = outs.ModuleOutputPath; + serializationOpts.DocOutputPath = outs.ModuleDocOutputPath; + serializationOpts.SourceInfoOutputPath = outs.ModuleSourceInfoOutputPath; serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str(); if (opts.SerializeBridgingHeader && !outs.ModuleOutputPath.empty()) serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath; diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index 0146dd829c184..ad7aeeb804b74 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -273,7 +273,7 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( // optimization pipeline. SerializationOptions SerializationOpts; std::string OutPathStr = OutPath.str(); - SerializationOpts.OutputPath = OutPathStr.c_str(); + SerializationOpts.OutputPath = OutPathStr; SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName; SerializationOpts.AutolinkForceLoad = !subInvocation.getIRGenOptions().ForceLoadSymbolName.empty(); diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 277110ae78823..dd6a5928ffc47 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -1333,7 +1333,7 @@ static bool serializeSIB(SILModule *SM, const PrimarySpecificPaths &PSPs, assert(!moduleOutputPath.empty() && "must have an output path"); SerializationOptions serializationOpts; - serializationOpts.OutputPath = moduleOutputPath.c_str(); + serializationOpts.OutputPath = moduleOutputPath; serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index c4ab6747b39e3..eecf650b883ed 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -5892,7 +5892,7 @@ void swift::serializeToBuffers( std::unique_ptr *moduleSourceInfoBuffer, const SILModule *M) { - assert(!withNullAsEmptyStringRef(options.OutputPath).empty()); + assert(!options.OutputPath.empty()); { FrontendStatsTracer tracer(getContext(DC).Stats, "Serialization, swiftmodule, to buffer"); @@ -5911,10 +5911,11 @@ void swift::serializeToBuffers( emitABIDescriptor(DC, options); if (moduleBuffer) *moduleBuffer = std::make_unique( - std::move(buf), options.OutputPath); + std::move(buf), options.OutputPath, + /*RequiresNullTerminator=*/false); } - if (!withNullAsEmptyStringRef(options.DocOutputPath).empty()) { + if (!options.DocOutputPath.empty()) { FrontendStatsTracer tracer(getContext(DC).Stats, "Serialization, swiftdoc, to buffer"); llvm::SmallString<1024> buf; @@ -5928,10 +5929,11 @@ void swift::serializeToBuffers( }); if (moduleDocBuffer) *moduleDocBuffer = std::make_unique( - std::move(buf), options.DocOutputPath); + std::move(buf), options.DocOutputPath, + /*RequiresNullTerminator=*/false); } - if (!withNullAsEmptyStringRef(options.SourceInfoOutputPath).empty()) { + if (!options.SourceInfoOutputPath.empty()) { FrontendStatsTracer tracer(getContext(DC).Stats, "Serialization, swiftsourceinfo, to buffer"); llvm::SmallString<1024> buf; @@ -5945,7 +5947,8 @@ void swift::serializeToBuffers( }); if (moduleSourceInfoBuffer) *moduleSourceInfoBuffer = std::make_unique( - std::move(buf), options.SourceInfoOutputPath); + std::move(buf), options.SourceInfoOutputPath, + /*RequiresNullTerminator=*/false); } } @@ -5954,12 +5957,12 @@ void swift::serialize(ModuleOrSourceFile DC, const symbolgraphgen::SymbolGraphOptions &symbolGraphOptions, const SILModule *M, const fine_grained_dependencies::SourceFileDepGraph *DG) { - assert(!withNullAsEmptyStringRef(options.OutputPath).empty()); + assert(!options.OutputPath.empty()); - if (StringRef(options.OutputPath) == "-") { + if (options.OutputPath == "-") { // Special-case writing to stdout. Serializer::writeToStream(llvm::outs(), DC, M, options, DG); - assert(withNullAsEmptyStringRef(options.DocOutputPath).empty()); + assert(options.DocOutputPath.empty()); return; } @@ -5974,7 +5977,7 @@ void swift::serialize(ModuleOrSourceFile DC, if (hadError) return; - if (!withNullAsEmptyStringRef(options.DocOutputPath).empty()) { + if (!options.DocOutputPath.empty()) { (void)withOutputFile(getContext(DC).Diags, options.DocOutputPath, [&](raw_ostream &out) { @@ -5985,7 +5988,7 @@ void swift::serialize(ModuleOrSourceFile DC, }); } - if (!withNullAsEmptyStringRef(options.SourceInfoOutputPath).empty()) { + if (!options.SourceInfoOutputPath.empty()) { (void)withOutputFile(getContext(DC).Diags, options.SourceInfoOutputPath, [&](raw_ostream &out) { diff --git a/tools/sil-func-extractor/SILFunctionExtractor.cpp b/tools/sil-func-extractor/SILFunctionExtractor.cpp index 729fa6a4af7cf..9a0414194e1bf 100644 --- a/tools/sil-func-extractor/SILFunctionExtractor.cpp +++ b/tools/sil-func-extractor/SILFunctionExtractor.cpp @@ -356,7 +356,7 @@ int main(int argc, char **argv) { } SerializationOptions serializationOpts; - serializationOpts.OutputPath = OutputFile.c_str(); + serializationOpts.OutputPath = OutputFile; serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp index 3f5f7fcf68995..f0c05100a5e18 100644 --- a/tools/sil-opt/SILOpt.cpp +++ b/tools/sil-opt/SILOpt.cpp @@ -817,7 +817,7 @@ int main(int argc, char **argv) { } SerializationOptions serializationOpts; - serializationOpts.OutputPath = OutputFile.c_str(); + serializationOpts.OutputPath = OutputFile; serializationOpts.SerializeAllSIL = EmitSIB; serializationOpts.IsSIB = EmitSIB; From 950b7160c27386211dde7fbca71701e4273bb08e Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 12 May 2022 10:35:55 -0700 Subject: [PATCH 053/491] Correct the expected output in an example. --- stdlib/public/core/Integers.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/core/Integers.swift b/stdlib/public/core/Integers.swift index fa60dadf7ce98..f9d42102cadb5 100644 --- a/stdlib/public/core/Integers.swift +++ b/stdlib/public/core/Integers.swift @@ -1878,7 +1878,7 @@ extension BinaryInteger { /// print(Int16.max.binaryString) /// // Prints "0b01111111_11111111" /// print((101 as UInt8).binaryString) -/// // Prints "0b11001001" +/// // Prints "0b01100101" /// /// The `binaryString` implementation uses the static `bitWidth` property and /// the right shift operator (`>>`), both of which are available to any type From b939a59a8b417d14909753712eddde4ae05e3169 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 12 May 2022 12:07:36 -0700 Subject: [PATCH 054/491] Re-introduce an IRBuilder optimization that LLVM removed --- lib/IRGen/IRBuilder.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/lib/IRGen/IRBuilder.h b/lib/IRGen/IRBuilder.h index 5c941a492bef0..b0593d71bc4ee 100644 --- a/lib/IRGen/IRBuilder.h +++ b/lib/IRGen/IRBuilder.h @@ -120,6 +120,40 @@ class IRBuilder : public IRBuilderBase { return ClearedIP->getModule(); } + using IRBuilderBase::CreateAnd; + llvm::Value *CreateAnd(llvm::Value *LHS, llvm::Value *RHS, + const Twine &Name = "") { + if (auto *RC = dyn_cast(RHS)) + if (isa(RC) && + cast(RC)->isMinusOne()) + return LHS; // LHS & -1 -> LHS + return IRBuilderBase::CreateAnd(LHS, RHS, Name); + } + llvm::Value *CreateAnd(llvm::Value *LHS, const APInt &RHS, + const Twine &Name = "") { + return CreateAnd(LHS, llvm::ConstantInt::get(LHS->getType(), RHS), Name); + } + llvm::Value *CreateAnd(llvm::Value *LHS, uint64_t RHS, const Twine &Name = "") { + return CreateAnd(LHS, llvm::ConstantInt::get(LHS->getType(), RHS), Name); + } + + using IRBuilderBase::CreateOr; + llvm::Value *CreateOr(llvm::Value *LHS, llvm::Value *RHS, + const Twine &Name = "") { + if (auto *RC = dyn_cast(RHS)) + if (RC->isNullValue()) + return LHS; // LHS | 0 -> LHS + return IRBuilderBase::CreateOr(LHS, RHS, Name); + } + llvm::Value *CreateOr(llvm::Value *LHS, const APInt &RHS, + const Twine &Name = "") { + return CreateOr(LHS, llvm::ConstantInt::get(LHS->getType(), RHS), Name); + } + llvm::Value *CreateOr(llvm::Value *LHS, uint64_t RHS, + const Twine &Name = "") { + return CreateOr(LHS, llvm::ConstantInt::get(LHS->getType(), RHS), Name); + } + /// Don't create allocas this way; you'll get a dynamic alloca. /// Use IGF::createAlloca or IGF::emitDynamicAlloca. llvm::Value *CreateAlloca(llvm::Type *type, llvm::Value *arraySize, From 05c7e1836864373c0688e3f80f6bd913fa2db6a5 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 12 May 2022 10:47:56 -0700 Subject: [PATCH 055/491] Fix IRGen test failures on rebranch rdar://93054141 --- test/IRGen/newtype.swift | 12 ++++++------ test/IRGen/objc_globals.swift | 8 ++++---- test/IRGen/pre_specialize.swift | 24 ++++++++++++------------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/test/IRGen/newtype.swift b/test/IRGen/newtype.swift index 35e092fa970fd..95f36eefe2cdc 100644 --- a/test/IRGen/newtype.swift +++ b/test/IRGen/newtype.swift @@ -222,15 +222,15 @@ public func mutateRef() { // CHECK-CC: declare %struct.__CFString* @getMyABINewType() // CHECK-CC: declare %struct.__CFString* @getMyABIOldType() // -// CHECK-CC: declare void @takeMyABINewType(%struct.__CFString*) -// CHECK-CC: declare void @takeMyABIOldType(%struct.__CFString*) +// CHECK-CC: declare void @takeMyABINewType(%struct.__CFString* noundef) +// CHECK-CC: declare void @takeMyABIOldType(%struct.__CFString* noundef) // -// CHECK-CC: declare void @takeMyABINewTypeNonNull(%struct.__CFString*) -// CHECK-CC: declare void @takeMyABIOldTypeNonNull(%struct.__CFString*) +// CHECK-CC: declare void @takeMyABINewTypeNonNull(%struct.__CFString* noundef) +// CHECK-CC: declare void @takeMyABIOldTypeNonNull(%struct.__CFString* noundef) // // CHECK-CC: declare %0* @getMyABINewTypeNS() // CHECK-CC: declare %0* @getMyABIOldTypeNS() // -// CHECK-CC: declare void @takeMyABINewTypeNonNullNS(%0*) -// CHECK-CC: declare void @takeMyABIOldTypeNonNullNS(%0*) +// CHECK-CC: declare void @takeMyABINewTypeNonNullNS(%0* noundef) +// CHECK-CC: declare void @takeMyABIOldTypeNonNullNS(%0* noundef) diff --git a/test/IRGen/objc_globals.swift b/test/IRGen/objc_globals.swift index 27a22bf0f18f0..c4c988f4f8cee 100644 --- a/test/IRGen/objc_globals.swift +++ b/test/IRGen/objc_globals.swift @@ -34,14 +34,14 @@ public func fooLazy() { // CHECK-LABEL: define internal {{.*}}* @giveMeANumber() // CHECK: [[CLASS:%.*]] = load %struct._class_t*, %struct._class_t** -// CHECK: [[SELECTOR:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.{{.*}} -// CHECK: bitcast %struct._class_t* [[CLASS]] to i8* +// CHECK-DAG: [[SELECTOR:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.{{.*}} +// CHECK-DAG: bitcast %struct._class_t* [[CLASS]] to i8* // CHECK: call {{.*}} @objc_msgSend // CHECK: ret // CHECK-LABEL: define internal i8* @giveMeAMetaclass() // CHECK: [[CLASS:%.*]] = load %struct._class_t*, %struct._class_t** -// CHECK: [[SELECTOR:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ -// CHECK: bitcast %struct._class_t* [[CLASS]] to i8* +// CHECK-DAG: [[SELECTOR:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ +// CHECK-DAG: bitcast %struct._class_t* [[CLASS]] to i8* // CHECK: call {{.*}} @objc_msgSend // CHECK: ret diff --git a/test/IRGen/pre_specialize.swift b/test/IRGen/pre_specialize.swift index 78e22a0cce2cb..160fccde07faa 100644 --- a/test/IRGen/pre_specialize.swift +++ b/test/IRGen/pre_specialize.swift @@ -34,26 +34,26 @@ // -------------- // specialized InternalThing.compute() -// CHECK-A-FRAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT:(i64|i32)]] @"$s1A13InternalThingV7computexyFAA09Resilienta5BoxedB0VySiG_Ts5"({{(i64|i32)}}{{( returned)?}} %0) -// CHECK-A-RES: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s1A13InternalThingV7computexyFAA09Resilienta5BoxedB0VySiG_Ts5"(%T1A27ResilientInternalBoxedThingVySiG* noalias nocapture sret({{.*}}) %0, [[INT:(i64|i32)]] %1) -// CHECK-A: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @"$s1A13InternalThingV7computexyFSb_Ts5"(i1{{( returned)?}} %0) -// CHECK-A: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A13InternalThingV7computexyFSi_Ts5"([[INT]]{{( returned)?}} %0) +// CHECK-A-FRAG-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT:(i64|i32)]] @"$s1A13InternalThingV7computexyFAA09Resilienta5BoxedB0VySiG_Ts5"({{(i64|i32)}}{{( returned)?}} %0) +// CHECK-A-RES-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s1A13InternalThingV7computexyFAA09Resilienta5BoxedB0VySiG_Ts5"(%T1A27ResilientInternalBoxedThingVySiG* {{.*}}sret({{.*}}){{.*}} %0, [[INT:(i64|i32)]] %1) +// CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @"$s1A13InternalThingV7computexyFSb_Ts5"(i1{{( returned)?}} %0) +// CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A13InternalThingV7computexyFSi_Ts5"([[INT]]{{( returned)?}} %0) // specialized InternalThing.computedX.getter -// CHECK-A: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A13InternalThingV9computedXxvgSi_Ts5"([[INT]]{{( returned)?}} %0) +// CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A13InternalThingV9computedXxvgSi_Ts5"([[INT]]{{( returned)?}} %0) // specialized InternalThing.computedX.setter -// CHECK-A: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s1A13InternalThingV9computedXxvsSi_Ts5"([[INT]] %0, %T1A13InternalThingVySiG* nocapture swiftself dereferenceable({{(4|8)}}) %1) +// CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s1A13InternalThingV9computedXxvsSi_Ts5"([[INT]] %0, %T1A13InternalThingVySiG* nocapture swiftself {{(writeonly )?}}dereferenceable({{(4|8)}}) %1) // specialized InternalThing.subscript.getter -// CHECK-A: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A13InternalThingVyxSicigSi_Ts5"([[INT]] %0, [[INT]]{{( returned)?}} %1) +// CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A13InternalThingVyxSicigSi_Ts5"([[INT]] %0, [[INT]]{{( returned)?}} %1) // specialized InternalThing.subscript.setter -// CHECK-A: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s1A13InternalThingVyxSicisSi_Ts5"([[INT]] %0, [[INT]] %1, %T1A13InternalThingVySiG* nocapture swiftself dereferenceable({{(4|8)}}) %2) +// CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s1A13InternalThingVyxSicisSi_Ts5"([[INT]] %0, [[INT]] %1, %T1A13InternalThingVySiG* nocapture swiftself {{(writeonly )?}}dereferenceable({{(4|8)}}) %2) // specialized InternalRef.compute() -// CHECK-A-FRAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT:(i64|i32)]] @"$s1A11InternalRefC7computexyFAA09ResilientA10BoxedThingVySiG_Ts5" -// CHECK-A-RES: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s1A11InternalRefC7computexyFAA09ResilientA10BoxedThingVySiG_Ts5" -// CHECK-A: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @"$s1A11InternalRefC7computexyFSb_Ts5" -// CHECK-A: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A11InternalRefC7computexyFSi_Ts5" +// CHECK-A-FRAG-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT:(i64|i32)]] @"$s1A11InternalRefC7computexyFAA09ResilientA10BoxedThingVySiG_Ts5" +// CHECK-A-RES-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s1A11InternalRefC7computexyFAA09ResilientA10BoxedThingVySiG_Ts5" +// CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @"$s1A11InternalRefC7computexyFSb_Ts5" +// CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A11InternalRefC7computexyFSi_Ts5" // specialized InternalRef.computedX.getter // CHECK-A-DAG: define{{( dllexport)?}}{{( protected)?}} swiftcc [[INT]] @"$s1A11InternalRefC9computedXxvgSi_Ts5" From e382e15f6a328673cdc17fc1a6b157a13daa2a18 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 13 May 2022 13:30:10 -0700 Subject: [PATCH 056/491] [next] Generalise interop tests that only care about name and types Due to a now default-enabled `undef` pass (llvm/llvm-project 1b1c8d83d3567a60280291c0adb95d1d60335509), a whole bunch of interop IRGen tests are failing due to missing `undefs`, even though they don't matter in these tests at all. Add regex matches so that these tests just check for the name and types of the functions they care about. --- .../emit-called-inline-function-irgen.swift | 8 ++--- .../Cxx/class/constructors-irgen.swift | 6 ++-- ...lls-function-from-nested-calls-irgen.swift | 8 ++--- ...ls-function-from-nested-struct-irgen.swift | 4 +-- .../constructor-calls-function-irgen.swift | 6 ++-- .../constructor-calls-method-irgen.swift | 2 +- .../field-init-calls-function-irgen.swift | 2 +- .../method-calls-function-irgen.swift | 2 +- ...alls-method-from-nested-struct-irgen.swift | 2 +- .../method-calls-method-irgen.swift | 2 +- ...static-var-init-calls-function-irgen.swift | 2 +- .../Cxx/static/static-member-func-irgen.swift | 8 ++--- .../Interop/Cxx/static/static-var-irgen.swift | 30 +++++++++---------- ...plate-uninstantiatable-members-irgen.swift | 4 +-- .../templates/function-template-irgen.swift | 8 ++--- 15 files changed, 47 insertions(+), 47 deletions(-) diff --git a/test/Interop/C/function/emit-called-inline-function-irgen.swift b/test/Interop/C/function/emit-called-inline-function-irgen.swift index fa8d395f53925..8d53db8a28bf7 100644 --- a/test/Interop/C/function/emit-called-inline-function-irgen.swift +++ b/test/Interop/C/function/emit-called-inline-function-irgen.swift @@ -13,10 +13,10 @@ import EmitCalledInlineFunction // C99-DAG: define internal i32 @calledFromSwift() // C99-DAG: define internal i32 @calledTransitively() -// CXX-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z15calledFromSwiftv|"\?calledFromSwift@@YAHXZ"}}() -// CXX-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z18calledTransitivelyv|"\?calledTransitively@@YAHXZ"}}() -// CXX-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_ZN1C32memberFunctionCalledTransitivelyEv|"\?memberFunctionCalledTransitively@C@@QEAAHXZ"}}(%class.C* nonnull align 1 dereferenceable(1) %this) -// CXX-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z29calledTransitivelyFromVarInitv|"\?calledTransitivelyFromVarInit@@YAHXZ"}}() +// CXX-DAG: define {{.*}}i32 @{{_Z15calledFromSwiftv|"\?calledFromSwift@@YAHXZ"}}() +// CXX-DAG: define {{.*}}i32 @{{_Z18calledTransitivelyv|"\?calledTransitively@@YAHXZ"}}() +// CXX-DAG: define {{.*}}i32 @{{_ZN1C32memberFunctionCalledTransitivelyEv|"\?memberFunctionCalledTransitively@C@@QEAAHXZ"}}(%class.C* {{.*}}) +// CXX-DAG: define {{.*}}i32 @{{_Z29calledTransitivelyFromVarInitv|"\?calledTransitivelyFromVarInit@@YAHXZ"}}() calledFromSwift() diff --git a/test/Interop/Cxx/class/constructors-irgen.swift b/test/Interop/Cxx/class/constructors-irgen.swift index 2e666d8c50345..7fb34a6bacd0d 100644 --- a/test/Interop/Cxx/class/constructors-irgen.swift +++ b/test/Interop/Cxx/class/constructors-irgen.swift @@ -96,7 +96,7 @@ public func createTemplatedConstructor() { // ITANIUM_X64: call void @_ZN20TemplatedConstructorC1I7ArgTypeEET_(%struct.TemplatedConstructor* [[OBJ_AS_STRUCT]], i32 [[IVAL]]) // ITANIUM_X64: ret void - // ITANIUM_X64-LABEL: define linkonce_odr void @_ZN20TemplatedConstructorC1I7ArgTypeEET_(%struct.TemplatedConstructor* nonnull align 4 dereferenceable(4) {{.*}}, i32 {{.*}}) + // ITANIUM_X64-LABEL: define {{.*}}void @_ZN20TemplatedConstructorC1I7ArgTypeEET_(%struct.TemplatedConstructor* {{.*}}, i32 {{.*}}) // ITANIUM_ARM-LABEL: define protected swiftcc void @"$ss26createTemplatedConstructoryyF"() // ITANIUM_ARM: [[OBJ:%.*]] = alloca %TSo20TemplatedConstructorV @@ -105,7 +105,7 @@ public func createTemplatedConstructor() { // ITANIUM_ARM: call %struct.TemplatedConstructor* @_ZN20TemplatedConstructorC2I7ArgTypeEET_(%struct.TemplatedConstructor* [[OBJ_AS_STRUCT]], [1 x i32] [[IVAL]]) // ITANIUM_ARM: ret void - // ITANIUM_ARM-LABEL: define linkonce_odr %struct.TemplatedConstructor* @_ZN20TemplatedConstructorC2I7ArgTypeEET_(%struct.TemplatedConstructor* nonnull returned align 4 dereferenceable(4) {{.*}}, [1 x i32] {{.*}}) + // ITANIUM_ARM-LABEL: define {{.*}}%struct.TemplatedConstructor* @_ZN20TemplatedConstructorC2I7ArgTypeEET_(%struct.TemplatedConstructor* {{.*}}, [1 x i32] {{.*}}) // MICROSOFT_X64-LABEL: define dllexport swiftcc void @"$ss26createTemplatedConstructoryyF"() // MICROSOFT_X64: [[OBJ:%.*]] = alloca %TSo20TemplatedConstructorV @@ -114,6 +114,6 @@ public func createTemplatedConstructor() { // MICROSOFT_X64: call %struct.TemplatedConstructor* @"??$?0UArgType@@@TemplatedConstructor@@QEAA@UArgType@@@Z"(%struct.TemplatedConstructor* [[OBJ_AS_STRUCT]], i32 [[IVAL]]) // MICROSOFT_X64: ret void - // MICROSOFT_X64-LABEL: define linkonce_odr dso_local %struct.TemplatedConstructor* @"??$?0UArgType@@@TemplatedConstructor@@QEAA@UArgType@@@Z"(%struct.TemplatedConstructor* nonnull returned align 4 dereferenceable(4) {{.*}}, i32 {{.*}}) + // MICROSOFT_X64-LABEL: define {{.*}}%struct.TemplatedConstructor* @"??$?0UArgType@@@TemplatedConstructor@@QEAA@UArgType@@@Z"(%struct.TemplatedConstructor* {{.*}}, i32 {{.*}}) let templated = TemplatedConstructor(ArgType()) } diff --git a/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-from-nested-calls-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-from-nested-calls-irgen.swift index dfee1a7ffc338..8b6bda8e92326 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-from-nested-calls-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-from-nested-calls-irgen.swift @@ -4,7 +4,7 @@ import ConstructorCallsFunctionFromNestedCalls let a = Hold42WithLongInitCallGraph() -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z11get42Level1v|"\?get42Level1@@YAHXZ"}} -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z11get42Level2v|"\?get42Level2@@YAHXZ"}} -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z11get42Level3v|"\?get42Level3@@YAHXZ"}} -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z11get42Level4v|"\?get42Level4@@YAHXZ"}} +// CHECK-DAG: define {{.*}}i32 @{{_Z11get42Level1v|"\?get42Level1@@YAHXZ"}} +// CHECK-DAG: define {{.*}}i32 @{{_Z11get42Level2v|"\?get42Level2@@YAHXZ"}} +// CHECK-DAG: define {{.*}}i32 @{{_Z11get42Level3v|"\?get42Level3@@YAHXZ"}} +// CHECK-DAG: define {{.*}}i32 @{{_Z11get42Level4v|"\?get42Level4@@YAHXZ"}} diff --git a/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-from-nested-struct-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-from-nested-struct-irgen.swift index db0b577c7d3c2..30480be5b74ee 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-from-nested-struct-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-from-nested-struct-irgen.swift @@ -11,5 +11,5 @@ let b = HoldMemberThatHoldsMemberThatHolds42() let sum = a.holder.m + b.holder.holder.m -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 %t) -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z5get42v|"\?get42@@YAHXZ"}} +// CHECK-DAG: define {{.*}}i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 {{.*}}) +// CHECK-DAG: define {{.*}}i32 @{{_Z5get42v|"\?get42@@YAHXZ"}} diff --git a/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-irgen.swift index 35eed32d2bd70..eb92ee30d59c2 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-function-irgen.swift @@ -11,6 +11,6 @@ let b = Hold23() let sum = a.m + b.m -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 %t) -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z5get42v|"\?get42@@YAHXZ"}} -// CHECK-DAG: define linkonce_odr{{( dso_local)?}} i32 @{{_Z15passThroughArgTIiET_S0_|"\?\?\$passThroughArgT@H@@YAHH@Z"}} +// CHECK-DAG: define {{.*}}i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 {{.*}}) +// CHECK-DAG: define {{.*}}i32 @{{_Z5get42v|"\?get42@@YAHXZ"}} +// CHECK-DAG: define {{.*}}i32 @{{_Z15passThroughArgTIiET_S0_|"\?\?\$passThroughArgT@H@@YAHH@Z"}} diff --git a/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-method-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-method-irgen.swift index 6943b7be955fa..0dec7b0234bc0 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-method-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/constructor-calls-method-irgen.swift @@ -6,4 +6,4 @@ public func getIncrementorValue() -> CInt { return callConstructor(41) } -// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_ZN11Incrementor9incrementEi|"\?increment@Incrementor@@QEAAHH@Z"}}(%struct.Incrementor* nonnull align 1 dereferenceable(1) %this, i32 %t) +// CHECK: define {{.*}}i32 @{{_ZN11Incrementor9incrementEi|"\?increment@Incrementor@@QEAAHH@Z"}}(%struct.Incrementor* {{.*}}, i32 {{.*}}) diff --git a/test/Interop/Cxx/class/inline-function-codegen/field-init-calls-function-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/field-init-calls-function-irgen.swift index f87dd4f2a7cc0..6caf49f9f03ed 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/field-init-calls-function-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/field-init-calls-function-irgen.swift @@ -6,4 +6,4 @@ public func getInitializedField() -> CInt { return initializeField() } -// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 %t) +// CHECK: define {{.*}}i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 {{.*}}) diff --git a/test/Interop/Cxx/class/inline-function-codegen/method-calls-function-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/method-calls-function-irgen.swift index 8f8236f8b927b..224b5121cab3e 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/method-calls-function-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/method-calls-function-irgen.swift @@ -6,4 +6,4 @@ public func getValueFromMethod() -> CInt { return callMethod(41) } -// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 %t) +// CHECK: define {{.*}}i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 {{.*}}) diff --git a/test/Interop/Cxx/class/inline-function-codegen/method-calls-method-from-nested-struct-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/method-calls-method-from-nested-struct-irgen.swift index e48646023424c..a733935576bd3 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/method-calls-method-from-nested-struct-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/method-calls-method-from-nested-struct-irgen.swift @@ -6,4 +6,4 @@ public func getValueFromMethod() -> CInt { return callMethod(41) } -// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_ZN13IncrementUser11Incrementor9incrementEi|"\?increment@Incrementor@IncrementUser@@QEAAHH@Z"}}(%"struct.IncrementUser::Incrementor"* nonnull align 1 dereferenceable(1) %this, i32 %t) +// CHECK: define {{.*}}i32 @{{_ZN13IncrementUser11Incrementor9incrementEi|"\?increment@Incrementor@IncrementUser@@QEAAHH@Z"}}(%"struct.IncrementUser::Incrementor"* {{.*}}, i32 {{.*}}) diff --git a/test/Interop/Cxx/class/inline-function-codegen/method-calls-method-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/method-calls-method-irgen.swift index e3ce488dc5615..8c644dc7a616c 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/method-calls-method-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/method-calls-method-irgen.swift @@ -6,4 +6,4 @@ public func getValueFromMethod() -> CInt { return callMethod(41) } -// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_ZN11Incrementor9incrementEi|"\?increment@Incrementor@@QEAAHH@Z"}}(%struct.Incrementor* nonnull align 1 dereferenceable(1) %this, i32 %t) +// CHECK: define {{.*}}i32 @{{_ZN11Incrementor9incrementEi|"\?increment@Incrementor@@QEAAHH@Z"}}(%struct.Incrementor*{{.*}}, i32{{.*}}) diff --git a/test/Interop/Cxx/class/inline-function-codegen/static-var-init-calls-function-irgen.swift b/test/Interop/Cxx/class/inline-function-codegen/static-var-init-calls-function-irgen.swift index 5d71b4a74717c..9a804f81120ce 100644 --- a/test/Interop/Cxx/class/inline-function-codegen/static-var-init-calls-function-irgen.swift +++ b/test/Interop/Cxx/class/inline-function-codegen/static-var-init-calls-function-irgen.swift @@ -8,4 +8,4 @@ public func getInitializedStaticVar() -> CInt { return initializeStaticVar() } -// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32 %t) +// CHECK: define {{.*}}i32 @{{_Z9incrementi|"\?increment@@YAHH@Z"}}(i32{{.*}}) diff --git a/test/Interop/Cxx/static/static-member-func-irgen.swift b/test/Interop/Cxx/static/static-member-func-irgen.swift index e14ff02a8931e..8830ef28aea45 100644 --- a/test/Interop/Cxx/static/static-member-func-irgen.swift +++ b/test/Interop/Cxx/static/static-member-func-irgen.swift @@ -6,18 +6,18 @@ public func callStaticMemberFunc() -> CInt { return WithStaticMemberFunc.staticMemberFunc() } -// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main20callStaticMemberFuncs5Int32VyF"() +// CHECK: define {{.*}}i32 @"$s4main20callStaticMemberFuncs5Int32VyF"() // CHECK: [[VALUE:%.*]] = call i32 @{{_ZN20WithStaticMemberFunc16staticMemberFuncEv|"\?staticMemberFunc@WithStaticMemberFunc@@SAHXZ"}}() // CHECK: ret i32 [[VALUE]] -// CHECK: declare {{(dso_local )?}}i32 @{{_ZN20WithStaticMemberFunc16staticMemberFuncEv|"\?staticMemberFunc@WithStaticMemberFunc@@SAHXZ"}}() +// CHECK: declare {{.*}}i32 @{{_ZN20WithStaticMemberFunc16staticMemberFuncEv|"\?staticMemberFunc@WithStaticMemberFunc@@SAHXZ"}}() public func callStaticMemberFuncAddr() -> CInt { return WithStaticMemberFunc.getStaticMemberFuncAddress()!() } -// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main24callStaticMemberFuncAddrs5Int32VyF"() +// CHECK: define {{.*}}i32 @"$s4main24callStaticMemberFuncAddrs5Int32VyF"() // CHECK: call i32 ()* @{{_ZN20WithStaticMemberFunc26getStaticMemberFuncAddressEv|"\?getStaticMemberFuncAddress@WithStaticMemberFunc@@SAP6AHXZXZ"}}() -// CHECK: declare {{(dso_local )?}}i32 ()* @{{_ZN20WithStaticMemberFunc26getStaticMemberFuncAddressEv|"\?getStaticMemberFuncAddress@WithStaticMemberFunc@@SAP6AHXZXZ"}}() +// CHECK: declare {{.*}}i32 ()* @{{_ZN20WithStaticMemberFunc26getStaticMemberFuncAddressEv|"\?getStaticMemberFuncAddress@WithStaticMemberFunc@@SAP6AHXZXZ"}}() diff --git a/test/Interop/Cxx/static/static-var-irgen.swift b/test/Interop/Cxx/static/static-var-irgen.swift index 0b52f0bf6380a..01a0adfd6fa1b 100644 --- a/test/Interop/Cxx/static/static-var-irgen.swift +++ b/test/Interop/Cxx/static/static-var-irgen.swift @@ -23,42 +23,42 @@ public func initStaticVars() -> CInt { // CHECK: @{{_ZL25staticConstexprNonTrivial|staticConstexprNonTrivial}} = internal constant %class.NonTrivial { i32 8192 }, align 4 // CHECK: define internal void @{{__cxx_global_var_init|"\?\?__EstaticVarInit@@YAXXZ"}}() -// CHECK: %call = call i32 @{{_Z13makeStaticVarv|"\?makeStaticVar@@YAHXZ"}}() +// CHECK: %call = call {{.*}}i32 @{{_Z13makeStaticVarv|"\?makeStaticVar@@YAHXZ"}}() // CHECK: store i32 %call, i32* @{{_ZL13staticVarInit|staticVarInit}}, align 4 -// CHECK: declare{{( dso_local)?}} i32 @{{_Z13makeStaticVarv|"\?makeStaticVar@@YAHXZ"}}() +// CHECK: declare {{.*}}i32 @{{_Z13makeStaticVarv|"\?makeStaticVar@@YAHXZ"}}() // CHECK: define internal void @{{__cxx_global_var_init.1|"\?\?__EstaticVarInlineInit@@YAXXZ"}}() -// CHECK: %call = call i32 @{{_Z19inlineMakeStaticVarv|"\?inlineMakeStaticVar@@YAHXZ"}}() +// CHECK: %call = call {{.*}}i32 @{{_Z19inlineMakeStaticVarv|"\?inlineMakeStaticVar@@YAHXZ"}}() // CHECK: store i32 %call, i32* @{{_ZL19staticVarInlineInit|staticVarInlineInit}}, align 4 -// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_Z19inlineMakeStaticVarv|"\?inlineMakeStaticVar@@YAHXZ"}}() +// CHECK: define {{.*}}i32 @{{_Z19inlineMakeStaticVarv|"\?inlineMakeStaticVar@@YAHXZ"}}() // CHECK: ret i32 8 // CHECK: define internal void @{{__cxx_global_var_init.2|"\?\?__EstaticConstInit@@YAXXZ"}}() -// CHECK: %call = call i32 @{{_Z15makeStaticConstv|"\?makeStaticConst@@YAHXZ"}}() +// CHECK: %call = call {{.*}}i32 @{{_Z15makeStaticConstv|"\?makeStaticConst@@YAHXZ"}}() // CHECK: store i32 %call, i32* @{{_ZL15staticConstInit|staticConstInit}}, align 4 -// CHECK: declare{{( dso_local)?}} i32 @{{_Z15makeStaticConstv|"\?makeStaticConst@@YAHXZ"}}() +// CHECK: declare {{.*}}i32 @{{_Z15makeStaticConstv|"\?makeStaticConst@@YAHXZ"}}() // CHECK: define internal void @{{__cxx_global_var_init.3|"\?\?__EstaticConstInlineInit@@YAXXZ"}}() -// CHECK: %call = call i32 @{{_Z21inlineMakeStaticConstv|"\?inlineMakeStaticConst@@YAHXZ"}}() +// CHECK: %call = call {{.*}}i32 @{{_Z21inlineMakeStaticConstv|"\?inlineMakeStaticConst@@YAHXZ"}}() // CHECK: store i32 %call, i32* @{{_ZL21staticConstInlineInit|staticConstInlineInit}}, align 4 -// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_Z21inlineMakeStaticConstv|"\?inlineMakeStaticConst@@YAHXZ"}}() +// CHECK: define {{.*}}i32 @{{_Z21inlineMakeStaticConstv|"\?inlineMakeStaticConst@@YAHXZ"}}() // CHECK: ret i32 16 // CHECK: define internal void @{{__cxx_global_var_init.4|"\?\?__EstaticNonTrivial@@YAXXZ"}}() -// CHECK: call {{void|%class.NonTrivial\*}} {{@_ZN10NonTrivialC[12]Ei\(%class.NonTrivial\* nonnull align 4 dereferenceable\(4\) @_ZL16staticNonTrivial, i32 1024\)|@"\?\?0NonTrivial@@QEAA@H@Z"\(%class.NonTrivial\* nonnull align 4 dereferenceable\(4\) @staticNonTrivial, i32 1024\)}} +// CHECK: call{{.*}} {{void|%class.NonTrivial\*}} {{@_ZN10NonTrivialC[12]Ei\(%class.NonTrivial\* .*@_ZL16staticNonTrivial, i32 .*1024\)|@"\?\?0NonTrivial@@QEAA@H@Z"\(%class.NonTrivial\* .*@staticNonTrivial, i32 .*1024\)}} // CHECK: define internal void @{{__cxx_global_var_init.5|"\?\?__EstaticConstNonTrivial@@YAXXZ"}}() -// CHECK: call {{void|%class.NonTrivial\*}} {{@_ZN10NonTrivialC[12]Ei\(%class.NonTrivial\* nonnull align 4 dereferenceable\(4\) @_ZL21staticConstNonTrivial, i32 2048\)|@"\?\?0NonTrivial@@QEAA@H@Z"\(%class.NonTrivial\* nonnull align 4 dereferenceable\(4\) @staticConstNonTrivial, i32 2048\)}} +// CHECK: call{{.*}} {{void|%class.NonTrivial\*}} {{@_ZN10NonTrivialC[12]Ei\(%class.NonTrivial\* .*@_ZL21staticConstNonTrivial, i32 .*2048\)|@"\?\?0NonTrivial@@QEAA@H@Z"\(%class.NonTrivial\* .*@staticConstNonTrivial, i32 .*2048\)}} public func readStaticVar() -> CInt { return staticVar } -// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main13readStaticVars5Int32VyF"() +// CHECK: define {{.*}}i32 @"$s4main13readStaticVars5Int32VyF"() // CHECK: [[VALUE:%.*]] = load i32, i32* getelementptr inbounds (%Ts5Int32V, %Ts5Int32V* bitcast (i32* @{{_ZL9staticVar|staticVar}} to %Ts5Int32V*), i32 0, i32 0), align 4 // CHECK: ret i32 [[VALUE]] @@ -66,14 +66,14 @@ public func writeStaticVar(_ v: CInt) { staticVar = v } -// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main14writeStaticVaryys5Int32VF"(i32 %0) +// CHECK: define {{.*}}void @"$s4main14writeStaticVaryys5Int32VF"(i32 {{.*}}%0) // CHECK: store i32 %0, i32* getelementptr inbounds (%Ts5Int32V, %Ts5Int32V* bitcast (i32* @{{_ZL9staticVar|staticVar}} to %Ts5Int32V*), i32 0, i32 0), align 4 public func readStaticNonTrivial() -> NonTrivial { return staticNonTrivial } -// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main20readStaticNonTrivialSo0dE0VyF"() +// CHECK: define {{.*}}i32 @"$s4main20readStaticNonTrivialSo0dE0VyF"() // CHECK: [[VALUE:%.*]] = load i32, i32* getelementptr inbounds (%TSo10NonTrivialV, %TSo10NonTrivialV* bitcast (%class.NonTrivial* @{{_ZL16staticNonTrivial|staticNonTrivial}} to %TSo10NonTrivialV*), i32 0, i32 0, i32 0), align 4 // CHECK: ret i32 [[VALUE]] @@ -81,7 +81,7 @@ public func writeStaticNonTrivial(_ i: NonTrivial) { staticNonTrivial = i } -// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main21writeStaticNonTrivialyySo0dE0VF"(i32 %0) +// CHECK: define {{.*}}void @"$s4main21writeStaticNonTrivialyySo0dE0VF"(i32 {{.*}}%0) // CHECK: store i32 %0, i32* getelementptr inbounds (%TSo10NonTrivialV, %TSo10NonTrivialV* bitcast (%class.NonTrivial* @{{_ZL16staticNonTrivial|staticNonTrivial}} to %TSo10NonTrivialV*), i32 0, i32 0, i32 0), align 4 func modifyInout(_ c: inout CInt) { @@ -91,7 +91,7 @@ func modifyInout(_ c: inout CInt) { public func passingVarAsInout() { modifyInout(&staticVar) } -// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main17passingVarAsInoutyyF"() +// CHECK: define {{.*}}void @"$s4main17passingVarAsInoutyyF"() // CHECK: call swiftcc void @"$s4main11modifyInoutyys5Int32VzF"(%Ts5Int32V* nocapture dereferenceable(4) bitcast (i32* @{{_ZL9staticVar|staticVar}} to %Ts5Int32V*)) // CHECK: define internal void @_GLOBAL__sub_I__swift_imported_modules_() diff --git a/test/Interop/Cxx/templates/class-template-uninstantiatable-members-irgen.swift b/test/Interop/Cxx/templates/class-template-uninstantiatable-members-irgen.swift index 15a5360263eb7..ea3bdc3cad02a 100644 --- a/test/Interop/Cxx/templates/class-template-uninstantiatable-members-irgen.swift +++ b/test/Interop/Cxx/templates/class-template-uninstantiatable-members-irgen.swift @@ -8,11 +8,11 @@ import ClassTemplateInstantiationErrors // CHECK: ret void // CHECK-LABEL: define {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE8incValueEv|"\?incValue@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHXZ"}}(%struct.CannotBeInstantianted* -// CHECK: call i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE6getOneEv|"\?getOne@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHXZ"}}(%struct.CannotBeInstantianted* +// CHECK: call {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE6getOneEv|"\?getOne@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHXZ"}}(%struct.CannotBeInstantianted* // CHECK: ret i32 // CHECK-LABEL: define {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE8incValueES0_|"\?incValue@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHUIntWrapper@@@Z"}}(%struct.CannotBeInstantianted* {{.*}}, {{i32|i64|\[1 x i32\]|\%struct\.IntWrapper\* byval\(\%struct\.IntWrapper\)}} -// CHECK: call i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE6getOneEv|"\?getOne@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHXZ"}}(%struct.CannotBeInstantianted* +// CHECK: call {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE6getOneEv|"\?getOne@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHXZ"}}(%struct.CannotBeInstantianted* // CHECK: ret i32 // CHECK-LABEL: define {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE6getOneEv|"\?getOne@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHXZ"}}(%struct.CannotBeInstantianted* diff --git a/test/Interop/Cxx/templates/function-template-irgen.swift b/test/Interop/Cxx/templates/function-template-irgen.swift index e5ea48e4d8547..4bc1ba1de42cd 100644 --- a/test/Interop/Cxx/templates/function-template-irgen.swift +++ b/test/Interop/Cxx/templates/function-template-irgen.swift @@ -6,7 +6,7 @@ import FunctionTemplates // CHECK: [[RET_VAL:%.*]] = call i32 @{{_Z16passThroughConstIiEKT_S0_|"\?\?\$passThroughConst@H@@YA\?BHH@Z"}}(i32 %0) // CHECK: ret i32 [[RET_VAL]] -// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z16passThroughConstIiEKT_S0_|"\?\?\$passThroughConst@H@@YA\?BHH@Z"}}(i32 %value) +// CHECK-LABEL: define {{.*}}i32 @{{_Z16passThroughConstIiEKT_S0_|"\?\?\$passThroughConst@H@@YA\?BHH@Z"}}(i32 {{.*}}%value) public func testPassThroughConst(x: Int32) -> Int32 { return passThroughConst(x) } @@ -15,7 +15,7 @@ public func testPassThroughConst(x: Int32) -> Int32 { // CHECK: [[RET_VAL:%.*]] = call i32 @{{_Z11passThroughIiET_S0_|"\?\?\$passThrough@H@@YAHH@Z"}}(i32 %0) // CHECK: ret i32 [[RET_VAL]] -// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z11passThroughIiET_S0_|"\?\?\$passThrough@H@@YAHH@Z"}}(i32 %value) +// CHECK-LABEL: define {{.*}}i32 @{{_Z11passThroughIiET_S0_|"\?\?\$passThrough@H@@YAHH@Z"}}(i32 {{.*}}%value) public func testPassThrough(x: Int32) -> Int32 { return passThrough(x) } @@ -24,7 +24,7 @@ public func testPassThrough(x: Int32) -> Int32 { // CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 %0, i32 %0) // CHECK: ret i32 [[OUT_VAL]] -// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 %a, i32 %b) +// CHECK-LABEL: define {{.*}}i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 {{.*}}%a, i32 {{.*}}%b) public func testAddMixedTypeParams(x: Int32) -> Int32 { return addMixedTypeParams(x, x) } @@ -33,7 +33,7 @@ public func testAddMixedTypeParams(x: Int32) -> Int32 { // CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 %0, i32 %0) // CHECK: ret i32 [[OUT_VAL]] -// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 %a, i32 %b) +// CHECK-LABEL: define {{.*}}i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 {{.*}}%a, i32 {{.*}}%b) public func testAddSameTypeParams(x: Int32) -> Int32 { return addSameTypeParams(x, x) } From 36632cde49a0fd88d536726ab5110b4148ee2e38 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 18 May 2022 16:29:17 -0700 Subject: [PATCH 057/491] [rebranch] Temporarily fix lit target_triple Any substring of `target_triple` is allowed as a feature (when used in REQUIRES/UNSUPPORTED/XFAIL) in `lit.py`. This is what allows eg. `XFAIL: linux` even though `linux` isn't listed as an available feature. `TARGET_TRIPLE` was renamed to `LLVM_TARGET_TRIPLE` upstream, so rename it here as well. Going forward we should remove `target_triple` entirely and use our `OS=...` features instead. --- test/Unit/lit.site.cfg.in | 2 +- test/lit.site.cfg.in | 2 +- validation-test/lit.site.cfg.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Unit/lit.site.cfg.in b/test/Unit/lit.site.cfg.in index ca000f6066171..aaf0abb915a64 100644 --- a/test/Unit/lit.site.cfg.in +++ b/test/Unit/lit.site.cfg.in @@ -6,7 +6,7 @@ config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" config.llvm_libs_dir = "@LLVM_LIBS_DIR@" config.build_mode = lit_config.params.get('build_mode', "@SWIFT_BUILD_MODE@") config.swift_obj_root = "@SWIFT_BINARY_DIR@" -config.target_triple = "@TARGET_TRIPLE@" +config.target_triple = "@LLVM_TARGET_TRIPLE@" config.swiftlib_dir = "@LIT_SWIFTLIB_DIR@" config.swift_test_results_dir = \ lit_config.params.get("swift_test_results_dir", "@SWIFT_TEST_RESULTS_DIR@") diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 31402817a8913..f8391195d6730 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -23,7 +23,7 @@ config.llvm_code_generators = "@LLVM_TARGETS_TO_BUILD@".split(";") config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" config.swift_src_root = lit_config.params.get("swift_src_root", "@SWIFT_SOURCE_DIR@") config.swift_obj_root = "@SWIFT_BINARY_DIR@" -config.target_triple = "@TARGET_TRIPLE@" +config.target_triple = "@LLVM_TARGET_TRIPLE@" config.variant_triple = "@VARIANT_TRIPLE@" config.variant_sdk = "@VARIANT_SDK@" config.variant_suffix = "@VARIANT_SUFFIX@" diff --git a/validation-test/lit.site.cfg.in b/validation-test/lit.site.cfg.in index 6e4718d9bff30..c8eacace72e35 100644 --- a/validation-test/lit.site.cfg.in +++ b/validation-test/lit.site.cfg.in @@ -22,7 +22,7 @@ config.llvm_code_generators = "@LLVM_TARGETS_TO_BUILD@".split(";") config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" config.swift_src_root = "@SWIFT_SOURCE_DIR@" config.swift_obj_root = "@SWIFT_BINARY_DIR@" -config.target_triple = "@TARGET_TRIPLE@" +config.target_triple = "@LLVM_TARGET_TRIPLE@" config.variant_triple = "@VARIANT_TRIPLE@" config.variant_suffix = "@VARIANT_SUFFIX@" config.variant_sdk = "@VARIANT_SDK@" From ac4715bb333f52b6dd1bf794a3242f199f921986 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 19 May 2022 15:20:24 -0700 Subject: [PATCH 058/491] [rebranch] Remove check for minor version Minor isn't provided in the `Triple` for Linux, so it's no longer added to the output. --- lib/SymbolGraphGen/JSON.cpp | 9 +++++---- test/SymbolGraph/Module/Module.swift | 18 +++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/SymbolGraphGen/JSON.cpp b/lib/SymbolGraphGen/JSON.cpp index 9a7354d27b63b..575e13d2a3dc1 100644 --- a/lib/SymbolGraphGen/JSON.cpp +++ b/lib/SymbolGraphGen/JSON.cpp @@ -53,10 +53,11 @@ void swift::symbolgraphgen::serialize(const llvm::Triple &T, OS.attribute("name", T.getOSTypeName(T.getOS())); llvm::VersionTuple OSVersion = T.getOSVersion(); - - OS.attributeBegin("minimumVersion"); - serialize(OSVersion, OS); - OS.attributeEnd(); + if (!OSVersion.empty()) { + OS.attributeBegin("minimumVersion"); + serialize(OSVersion, OS); + OS.attributeEnd(); + } }); }); } diff --git a/test/SymbolGraph/Module/Module.swift b/test/SymbolGraph/Module/Module.swift index e5117634a55b6..4ebc350b03485 100644 --- a/test/SymbolGraph/Module/Module.swift +++ b/test/SymbolGraph/Module/Module.swift @@ -1,8 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift %s -module-name SymbolGraphModule -emit-module -emit-module-path %t/ // RUN: %target-swift-symbolgraph-extract -module-name SymbolGraphModule -I %t -pretty-print -output-dir %t -// RUN: %FileCheck %s --input-file %t/SymbolGraphModule.symbols.json - +// RUN: %FileCheck %s --input-file %t/SymbolGraphModule.symbols.json --check-prefix=CHECK --check-prefix=CHECK-%target-os public struct S { public var x: Int } @@ -14,6 +13,15 @@ public struct S { // CHECK: vendor // CHECK-NEXT: operatingSystem // CHECK-NEXT: name -// CHECK-NEXT: minimumVersion -// CHECK-NEXT: major -// CHECK-NEXT: minor +// CHECK-macosx-NEXT: minimumVersion +// CHECK-ios-NEXT: minimumVersion +// CHECK-tvos-NEXT: minimumVersion +// CHECK-watchos-NEXT: minimumVersion +// CHECK-macosx-NEXT: major +// CHECK-ios-NEXT: major +// CHECK-tvos-NEXT: major +// CHECK-watchos-NEXT: major +// CHECK-macosx-NEXT: minor +// CHECK-ios-NEXT: minor +// CHECK-tvos-NEXT: minor +// CHECK-watchos-NEXT: minor From 589b155ed1bd042330f7002bd35bc74d723b2226 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 25 May 2022 16:25:17 -0700 Subject: [PATCH 059/491] [Test] Temporarily disable failing test --- test/ClangImporter/overlay.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/ClangImporter/overlay.swift b/test/ClangImporter/overlay.swift index 6f949d87ae74a..9c80c8a1b6c2c 100644 --- a/test/ClangImporter/overlay.swift +++ b/test/ClangImporter/overlay.swift @@ -3,6 +3,8 @@ // REQUIRES: objc_interop +// REQUIRES: rdar93135127 + // Do not import Foundation! This tests indirect visibility. #if REVERSED import Redeclaration From 2cfd7cba0339956fba81d4635d014ffb1409eacc Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 26 May 2022 09:58:59 -0700 Subject: [PATCH 060/491] tests: unmark test as XFAIL on Windows This passes on the rebranch. Unmark it as XFAIL on Windows to get the test suite passing. --- test/DebugInfo/local-vars.swift.gyb | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/DebugInfo/local-vars.swift.gyb b/test/DebugInfo/local-vars.swift.gyb index c13f46fa0a451..ca95a75a7a050 100644 --- a/test/DebugInfo/local-vars.swift.gyb +++ b/test/DebugInfo/local-vars.swift.gyb @@ -2,9 +2,6 @@ // test only verifies that the variables show up in the debug info at // all. There are other tests testing liveness and representation. -// rdar://problem/57611302 -// XFAIL: OS=windows-msvc - // RUN: %gyb %s -o %t.swift // RUN: %target-swift-frontend %t.swift -g -emit-ir -o - | %FileCheck %t.swift // RUN: %target-swift-frontend %t.swift -g -c -o %t.o From 5e44a45b351cf92ba7e7bd5444e1da772c6fcbe8 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 26 May 2022 12:19:46 -0700 Subject: [PATCH 061/491] [Test] More test updates to take into account VersionTuple change --- .../availability_refinement_contexts_target_min_inlining.swift | 2 +- test/Serialization/target-too-new-ios.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Sema/availability_refinement_contexts_target_min_inlining.swift b/test/Sema/availability_refinement_contexts_target_min_inlining.swift index 8ebaa31721368..c65bfe1074333 100644 --- a/test/Sema/availability_refinement_contexts_target_min_inlining.swift +++ b/test/Sema/availability_refinement_contexts_target_min_inlining.swift @@ -12,7 +12,7 @@ // CHECK-watchos: {{^}}(root versions=[2.0,+Inf) // CHECK-macosx-NEXT: {{^}} (decl_implicit versions=[10.15,+Inf) decl=foo() -// CHECK-ios-NEXT: {{^}} (decl_implicit versions=[13.0,+Inf) decl=foo() +// CHECK-ios-NEXT: {{^}} (decl_implicit versions=[13,+Inf) decl=foo() // CHECK-tvos-NEXT: {{^}} (decl_implicit versions=[13.0,+Inf) decl=foo() // CHECK-watchos-NEXT: {{^}} (decl_implicit versions=[6.0,+Inf) decl=foo() func foo() {} diff --git a/test/Serialization/target-too-new-ios.swift b/test/Serialization/target-too-new-ios.swift index 9e76046ce5237..d913b9c1754b4 100644 --- a/test/Serialization/target-too-new-ios.swift +++ b/test/Serialization/target-too-new-ios.swift @@ -12,5 +12,5 @@ // REQUIRES: OS=ios -// CHECK: :[[@LINE+1]]:8: error: compiling for iOS 12.0, but module 'empty' has a minimum deployment target of iOS 50.50.1: {{.*}}empty.swiftmodule{{$}} +// CHECK: :[[@LINE+1]]:8: error: compiling for iOS 12, but module 'empty' has a minimum deployment target of iOS 50.50.1: {{.*}}empty.swiftmodule{{$}} import empty From 6775624ea3f05a68a88f492ac5dfd41afb1bc3c5 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 1 Jun 2022 15:12:03 -0700 Subject: [PATCH 062/491] [Test] Fix up rest of availability test This was partially fixed in 5e44a45b351cf92ba7e7bd5444e1da772c6fcbe8, but tvos and watchos also need to be updated. --- ...availability_refinement_contexts_target_min_inlining.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Sema/availability_refinement_contexts_target_min_inlining.swift b/test/Sema/availability_refinement_contexts_target_min_inlining.swift index c65bfe1074333..4674f0bb65144 100644 --- a/test/Sema/availability_refinement_contexts_target_min_inlining.swift +++ b/test/Sema/availability_refinement_contexts_target_min_inlining.swift @@ -13,6 +13,6 @@ // CHECK-macosx-NEXT: {{^}} (decl_implicit versions=[10.15,+Inf) decl=foo() // CHECK-ios-NEXT: {{^}} (decl_implicit versions=[13,+Inf) decl=foo() -// CHECK-tvos-NEXT: {{^}} (decl_implicit versions=[13.0,+Inf) decl=foo() -// CHECK-watchos-NEXT: {{^}} (decl_implicit versions=[6.0,+Inf) decl=foo() +// CHECK-tvos-NEXT: {{^}} (decl_implicit versions=[13,+Inf) decl=foo() +// CHECK-watchos-NEXT: {{^}} (decl_implicit versions=[6,+Inf) decl=foo() func foo() {} From d3693e7482cf8c88601f4103a80713b4ba53519b Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 1 Jun 2022 15:13:27 -0700 Subject: [PATCH 063/491] [Test] Remove availability check from SILGen test This test is just checking that we don't crash, make it more stable by allowing no availability. --- test/SILGen/cf_curried_init.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SILGen/cf_curried_init.swift b/test/SILGen/cf_curried_init.swift index 006bd8be9a3ff..15ed624be98f6 100644 --- a/test/SILGen/cf_curried_init.swift +++ b/test/SILGen/cf_curried_init.swift @@ -8,4 +8,4 @@ import CoreGraphics let _: (CFURL) -> CGDataProvider? = CGDataProvider.init // CHECK-LABEL: sil private [ossa] @$s15cf_curried_initSo17CGDataProviderRefaSgSo8CFURLRefacfu_ : $@convention(thin) (@guaranteed CFURL) -> @owned Optional -// CHECK-LABEL: sil [available {{.*}}] [clang CGDataProvider.init] @CGDataProviderCreateWithURL : $@convention(c) (CFURL) -> @owned Optional +// CHECK-LABEL: sil {{.*}}[clang CGDataProvider.init] @CGDataProviderCreateWithURL : $@convention(c) (CFURL) -> @owned Optional From f6d432feed4bb1a5d6dcf3220ca290c99968fc8b Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 2 Jun 2022 15:57:40 -0700 Subject: [PATCH 064/491] [next] Generalise further interop tests See e382e15f6a328673cdc17fc1a6b157a13daa2a18 for previous test fixes - these were xfailed at the time, so weren't updated then. --- .../Cxx/operators/member-inline-irgen.swift | 22 +++++++++---------- .../operators/member-out-of-line-irgen.swift | 4 ++-- ...plate-uninstantiatable-members-irgen.swift | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/Interop/Cxx/operators/member-inline-irgen.swift b/test/Interop/Cxx/operators/member-inline-irgen.swift index a9fd8ab8c0c14..07c2b346787ea 100644 --- a/test/Interop/Cxx/operators/member-inline-irgen.swift +++ b/test/Interop/Cxx/operators/member-inline-irgen.swift @@ -11,18 +11,18 @@ public func sub(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> L public func call(_ wrapper: inout LoadableIntWrapper, _ arg: Int32) -> Int32 { wrapper(arg) } -// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZN18LoadableIntWrapperclEi|"\?\?GLoadableIntWrapper@@QEAAHH@Z")]](%struct.LoadableIntWrapper* {{%[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(.*\) align 4}} {{%[0-9]+}}) -// CHECK: define linkonce_odr [[RES]] [[NAME]](%struct.LoadableIntWrapper* nonnull align 4 dereferenceable(4) {{.*}}, {{i32 %.*|\[1 x i32\] %.*|i64 %.*|%struct.LoadableIntWrapper\* byval\(%struct.LoadableIntWrapper\) align 4 %.*}}) +// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZN18LoadableIntWrapperclEi|"\?\?GLoadableIntWrapper@@QEAAHH@Z")]](%struct.LoadableIntWrapper* {{%[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(.*\)}}{{.*}}) +// CHECK: define {{.*}}[[RES]] [[NAME]](%struct.LoadableIntWrapper* {{.*}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(%struct.LoadableIntWrapper\)}}{{.*}}) public func call(_ wrapper: inout AddressOnlyIntWrapper) -> Int32 { wrapper() } -// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZN21AddressOnlyIntWrapperclEv|"\?\?GAddressOnlyIntWrapper@@QEAAHXZ")]](%struct.AddressOnlyIntWrapper* {{%[0-9]+}}) -// CHECK: define linkonce_odr [[RES]] [[NAME]](%struct.AddressOnlyIntWrapper* nonnull align 4 dereferenceable(4) {{.*}}) +// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZN21AddressOnlyIntWrapperclEv|"\?\?GAddressOnlyIntWrapper@@QEAAHXZ")]](%struct.AddressOnlyIntWrapper* {{.*}}) +// CHECK: define {{.*}}[[RES]] [[NAME]](%struct.AddressOnlyIntWrapper* {{.*}}) public func index(_ arr: inout ReadOnlyIntArray, _ arg: Int32) -> Int32 { arr[arg] } -// CHECK: call [[RES:i32|i64]]* [[NAME:@(_ZNK16ReadOnlyIntArrayixEi|"\?\?AReadOnlyIntArray@@QEBAAEBHH@Z")]](%struct.ReadOnlyIntArray* {{%[0-9]+}}, {{i32|i64}} {{%[0-9]+}}) -// CHECK: define linkonce_odr nonnull align 4 dereferenceable(4) [[RES]]* [[NAME]](%struct.ReadOnlyIntArray* nonnull align 4 dereferenceable(20) {{.*}}, {{i32 %.*|\[1 x i32\] %.*|i64 %.*|%struct.ReadOnlyIntArray\* byval\(%struct.ReadOnlyIntArray\) align 2 %.*}}) +// CHECK: call [[RES:i32|i64]]* [[NAME:@(_ZNK16ReadOnlyIntArrayixEi|"\?\?AReadOnlyIntArray@@QEBAAEBHH@Z")]](%struct.ReadOnlyIntArray* {{.*}}, {{i32|i64}}{{.*}}) +// CHECK: define {{.*}}[[RES]]* [[NAME]](%struct.ReadOnlyIntArray* {{.*}}, {{i32|\[1 x i32\]|i64|%struct.ReadOnlyIntArray\* byval\(%struct.ReadOnlyIntArray\)}}{{.*}}) // CHECK: [[THIS:%.*]] = load %struct.ReadOnlyIntArray*, %struct.ReadOnlyIntArray** // CHECK: [[VALUES:%.*]] = getelementptr inbounds %struct.ReadOnlyIntArray, %struct.ReadOnlyIntArray* [[THIS]] // CHECK: [[VALUE:%.*]] = getelementptr inbounds [5 x {{i32|i64}}], [5 x {{i32|i64}}]* [[VALUES]] @@ -30,8 +30,8 @@ public func index(_ arr: inout ReadOnlyIntArray, _ arg: Int32) -> Int32 { arr[ar public func index(_ arr: inout ReadWriteIntArray, _ arg: Int32, _ val: Int32) { arr[arg] = val } -// CHECK: call [[RES:i32|i64]]* [[NAME:@(_ZN17ReadWriteIntArrayixEi|"\?\?AReadWriteIntArray@@QEAAAEAHH@Z")]](%struct.ReadWriteIntArray* {{%[0-9]+}}, {{i32|i64}} {{%[0-9]+}}) -// CHECK: define linkonce_odr nonnull align 4 dereferenceable(4) [[RES]]* [[NAME]](%struct.ReadWriteIntArray* nonnull align 4 dereferenceable(20) {{.*}}, {{i32 %.*|\[1 x i32\] %.*|i64 %.*|%struct.ReadWriteIntArray\* byval\(%struct.ReadWriteIntArray\) align 2 %.*}}) +// CHECK: call [[RES:i32|i64]]* [[NAME:@(_ZN17ReadWriteIntArrayixEi|"\?\?AReadWriteIntArray@@QEAAAEAHH@Z")]](%struct.ReadWriteIntArray* {{.*}}, {{i32|i64}}{{.*}}) +// CHECK: define {{.*}}[[RES]]* [[NAME]](%struct.ReadWriteIntArray* {{.*}}, {{i32|\[1 x i32\]|i64|%struct.ReadWriteIntArray\* byval\(%struct.ReadWriteIntArray\)}}{{.*}}) // CHECK: [[THIS:%.*]] = load %struct.ReadWriteIntArray*, %struct.ReadWriteIntArray** // CHECK: [[VALUES:%.*]] = getelementptr inbounds %struct.ReadWriteIntArray, %struct.ReadWriteIntArray* [[THIS]] // CHECK: [[VALUE:%.*]] = getelementptr inbounds [5 x {{i32|i64}}], [5 x {{i32|i64}}]* [[VALUES]] @@ -39,13 +39,13 @@ public func index(_ arr: inout ReadWriteIntArray, _ arg: Int32, _ val: Int32) { public func index(_ arr: inout NonTrivialIntArrayByVal, _ arg: Int32) -> Int32 { arr[arg] } -// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZNK23NonTrivialIntArrayByValixEi|"\?\?ANonTrivialIntArrayByVal@@QEBAAEBHH@Z")]](%struct.NonTrivialIntArrayByVal* {{%[0-9]+}}, {{i32|i64}} {{%[0-9]+}}) +// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZNK23NonTrivialIntArrayByValixEi|"\?\?ANonTrivialIntArrayByVal@@QEBAAEBHH@Z")]](%struct.NonTrivialIntArrayByVal* {{.*}}, {{i32|i64}}{{.*}}) -// CHECK: define linkonce_odr [[RES]] [[NAME]](%struct.NonTrivialIntArrayByVal* nonnull align 4 dereferenceable(20) {{.*}}, {{i32 %.*|\[1 x i32\] %.*|i64 %.*|%struct.NonTrivialIntArrayByVal\* byval\(%struct.NonTrivialIntArrayByVal\) align 2 %.*}}) +// CHECK: define {{.*}}[[RES]] [[NAME]](%struct.NonTrivialIntArrayByVal* {{.*}}, {{i32|\[1 x i32\]|i64|%struct.NonTrivialIntArrayByVal\* byval\(%struct.NonTrivialIntArrayByVal\)}}{{.*}}) // CHECK: [[THIS:%.*]] = load %struct.NonTrivialIntArrayByVal*, %struct.NonTrivialIntArrayByVal** // CHECK: [[VALUES:%.*]] = getelementptr inbounds %struct.NonTrivialIntArrayByVal, %struct.NonTrivialIntArrayByVal* [[THIS]] // CHECK: [[VALUE:%.*]] = getelementptr inbounds [5 x {{i32|i64}}], [5 x {{i32|i64}}]* [[VALUES]] // CHECK: [[VALUE2:%.*]] = load {{i32|i64}}, {{i32|i64}}* [[VALUE]] // CHECK: ret {{i32|i64}} [[VALUE2]] -// CHECK: define linkonce_odr [[RESA]] [[NAMEA]](%struct.LoadableIntWrapper* nonnull align 4 dereferenceable(4) {{.*}}, {{i32 %.*.coerce|\[1 x i32\] %.*.coerce|i64 %.*.coerce|%struct.LoadableIntWrapper\* byval\(%struct.LoadableIntWrapper\) align 4 %.*}}) \ No newline at end of file +// CHECK: define {{.*}}[[RESA]] [[NAMEA]](%struct.LoadableIntWrapper* {{.*}}, {{i32 .*%.*.coerce|\[1 x i32\] .*%.*.coerce|i64 .*%.*.coerce|%struct.LoadableIntWrapper\* .*byval\(%struct.LoadableIntWrapper\).*}}) diff --git a/test/Interop/Cxx/operators/member-out-of-line-irgen.swift b/test/Interop/Cxx/operators/member-out-of-line-irgen.swift index 80c6a9ab9b312..d2c03ceff088a 100644 --- a/test/Interop/Cxx/operators/member-out-of-line-irgen.swift +++ b/test/Interop/Cxx/operators/member-out-of-line-irgen.swift @@ -7,5 +7,5 @@ import MemberOutOfLine public func add(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs + rhs } -// CHECK: call {{i32|i64}} [[NAME:@_ZNK18LoadableIntWrapperplES_]](%struct.LoadableIntWrapper* %{{[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(.*\) align 4}} %{{[0-9]+}}) -// CHECK: declare {{(dso_local )?}}{{i32|i64}} [[NAME]](%struct.LoadableIntWrapper* nonnull align 4 dereferenceable(4), {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(%struct.LoadableIntWrapper\) align 4}}) +// CHECK: call {{i32|i64}} [[NAME:@_ZNK18LoadableIntWrapperplES_]](%struct.LoadableIntWrapper* %{{[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(.*\)}}{{.*}}) +// CHECK: declare {{.*}}{{i32|i64}} [[NAME]](%struct.LoadableIntWrapper* {{.*}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* .*byval\(%struct.LoadableIntWrapper\)}}{{.*}}) diff --git a/test/Interop/Cxx/templates/class-template-uninstantiatable-members-irgen.swift b/test/Interop/Cxx/templates/class-template-uninstantiatable-members-irgen.swift index ea3bdc3cad02a..0878bc0de45aa 100644 --- a/test/Interop/Cxx/templates/class-template-uninstantiatable-members-irgen.swift +++ b/test/Interop/Cxx/templates/class-template-uninstantiatable-members-irgen.swift @@ -11,7 +11,7 @@ import ClassTemplateInstantiationErrors // CHECK: call {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE6getOneEv|"\?getOne@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHXZ"}}(%struct.CannotBeInstantianted* // CHECK: ret i32 -// CHECK-LABEL: define {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE8incValueES0_|"\?incValue@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHUIntWrapper@@@Z"}}(%struct.CannotBeInstantianted* {{.*}}, {{i32|i64|\[1 x i32\]|\%struct\.IntWrapper\* byval\(\%struct\.IntWrapper\)}} +// CHECK-LABEL: define {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE8incValueES0_|"\?incValue@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHUIntWrapper@@@Z"}}(%struct.CannotBeInstantianted* {{.*}}, {{i32|i64|\[1 x i32\]|\%struct\.IntWrapper\* .*byval\(\%struct\.IntWrapper\)}} // CHECK: call {{.*}}i32 @{{_ZN21CannotBeInstantiantedI10IntWrapperE6getOneEv|"\?getOne@\?\$CannotBeInstantianted@UIntWrapper@@@@QEAAHXZ"}}(%struct.CannotBeInstantianted* // CHECK: ret i32 From f26925bfe13248cd4afd8e2ce181236e05a15fa6 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 3 Jun 2022 17:45:51 -0700 Subject: [PATCH 065/491] [next] Re-enable test that no longer fails This is fixed by e41a9833dc850d5757c000a666cb8876f1e6fd5a (https://github.com/apple/llvm-project/pull/4801), which properly marks the decl as demoted. --- test/ClangImporter/overlay.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/ClangImporter/overlay.swift b/test/ClangImporter/overlay.swift index 9c80c8a1b6c2c..6f949d87ae74a 100644 --- a/test/ClangImporter/overlay.swift +++ b/test/ClangImporter/overlay.swift @@ -3,8 +3,6 @@ // REQUIRES: objc_interop -// REQUIRES: rdar93135127 - // Do not import Foundation! This tests indirect visibility. #if REVERSED import Redeclaration From a3f14cc7337f70939dea72f26611fd2b783bd5b7 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 8 Jun 2022 14:45:13 -0700 Subject: [PATCH 066/491] [next] Update dependency scanner to inline old API apple/llvm-project 000a90ab63ce0595d442b3e7e8adc9c0506d2525 removed `getAdditionalArgsWithoutModulePaths`. 092b2ddf7ab355753aaadd46932169ab0761dae9 swapped to using `getCommandLineWithoutModulePaths` instead, but this is (almost) all cc1 args used to build the module - which is very different to what was being looped over previously. Inline `getAdditionalArgsWithoutModulePaths` instead. Resolves rdar://94545725. --- .../ClangModuleDependencyScanner.cpp | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index 3cb3c2c3dc439..8317955075676 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -209,10 +209,14 @@ void ClangImporter::recordModuleDependencies( // We pass the entire argument list via -Xcc, so the invocation should // use extra clang options alone. swiftArgs.push_back("-only-use-extra-clang-opts"); - auto addClangArg = [&](StringRef arg) { + auto addClangArg = [&](Twine arg) { swiftArgs.push_back("-Xcc"); swiftArgs.push_back(arg.str()); }; + auto addClangFrontendArg = [&](Twine arg) { + addClangArg("-Xclang"); + addClangArg(arg); + }; // Add all args inherited from creating the importer. auto It = allArgs.begin(); @@ -246,24 +250,23 @@ void ClangImporter::recordModuleDependencies( } } - // Add all args the non-path arguments required to be passed in, according - // to the Clang scanner - for (const auto &clangArg : - clangModuleDep.getCanonicalCommandLineWithoutModulePaths()) { - swiftArgs.push_back("-Xcc"); - swiftArgs.push_back("-Xclang"); - swiftArgs.push_back("-Xcc"); - swiftArgs.push_back(clangArg); - } + // Add the equivalent of the old `getAdditionalArgsWithoutModulePaths`. + // TODO: Should we be passing all cc1 args (ie. + // `getCanonicalCommandLineWithoutModulePaths`)? + addClangFrontendArg("-fno-implicit-modules"); + addClangFrontendArg("-emit-module"); + addClangFrontendArg(Twine("-fmodule-name=") + clangModuleDep.ID.ModuleName); + if (clangModuleDep.IsSystem) + addClangFrontendArg("-fsystem-module"); + if (clangModuleDep.BuildInvocation.getLangOpts()->NeededByPCHOrCompilationUsesPCH) + addClangFrontendArg("-fmodule-related-to-pch"); // If the scanner is invoked with '-clang-target', ensure this is the target // used to build this PCM. if (Impl.SwiftContext.LangOpts.ClangTarget.hasValue()) { llvm::Triple triple = Impl.SwiftContext.LangOpts.ClangTarget.getValue(); - swiftArgs.push_back("-Xcc"); - swiftArgs.push_back("-target"); - swiftArgs.push_back("-Xcc"); - swiftArgs.push_back(triple.str()); + addClangArg("-target"); + addClangArg(triple.str()); } // Swift frontend action: -emit-pcm From bcffb8e543880f6bcc4d743abb49818fb089bb71 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 8 Jun 2022 15:19:32 -0700 Subject: [PATCH 067/491] [next] Temporarily disable tgmath.swift.gyb Disable `test/stdlib/tgmath.swift.gyb` while it's being looked into in order to unblock CI. --- test/stdlib/tgmath.swift.gyb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/stdlib/tgmath.swift.gyb b/test/stdlib/tgmath.swift.gyb index 1a982fb1617a9..f282d2dc58eda 100644 --- a/test/stdlib/tgmath.swift.gyb +++ b/test/stdlib/tgmath.swift.gyb @@ -17,6 +17,8 @@ // RUN: %line-directive %t/tgmath.swift -- %target-run %t/a.out // REQUIRES: executable_test +// REQUIRES: rdar94452524 + #if canImport(Darwin) import Darwin.C.tgmath #elseif canImport(Glibc) From 0d96000b94de5851805d4fbb04e4fba810b8120e Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Thu, 9 Jun 2022 12:50:01 -0700 Subject: [PATCH 068/491] [next] Add missing chrono include `std::chrono::high_resolution_clock` is being used in `FrozenMultiMapTest.cpp` but it was relying on `chrono` being included transitively. Include it directly. --- unittests/Basic/FrozenMultiMapTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/Basic/FrozenMultiMapTest.cpp b/unittests/Basic/FrozenMultiMapTest.cpp index 23637f79018d2..0424b029de81e 100644 --- a/unittests/Basic/FrozenMultiMapTest.cpp +++ b/unittests/Basic/FrozenMultiMapTest.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" +#include #include #include #include From f76d6f0127237c5d0419a86bafd0d45ee7565092 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 13 Jun 2022 10:32:35 -0700 Subject: [PATCH 069/491] [Test] Update availability check for VersionTuple change Another fix to the availability checks - optional version parts are no longer output. --- ...ty_refinement_contexts_target_min_inlining_maccatalyst.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sema/availability_refinement_contexts_target_min_inlining_maccatalyst.swift b/test/Sema/availability_refinement_contexts_target_min_inlining_maccatalyst.swift index a3e41616fe962..3453983224a86 100644 --- a/test/Sema/availability_refinement_contexts_target_min_inlining_maccatalyst.swift +++ b/test/Sema/availability_refinement_contexts_target_min_inlining_maccatalyst.swift @@ -11,5 +11,5 @@ // Verify that -target-min-inlining-version min implies 13.1 on macCatalyst. // CHECK: {{^}}(root versions=[13.1,+Inf) -// CHECK-NEXT: {{^}} (decl_implicit versions=[14.4.0,+Inf) decl=foo() +// CHECK-NEXT: {{^}} (decl_implicit versions=[14.4,+Inf) decl=foo() func foo() {} From dee08e0ea99dbf2a7764a655b5e575602f1fa4f5 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 14 Jun 2022 14:29:34 -0700 Subject: [PATCH 070/491] [next] Add Default argument for hasFlag llvm/llvm-project removed the default for the `Default` argument in 522712e2d241ea33575a9c7a60ad582634f04f0d. Specify it directly in the call to `hasFlag`. --- lib/Frontend/CompilerInvocation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index fd24932b085a9..b116872544019 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -607,7 +607,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, // Determine whether string processing is enabled Opts.EnableExperimentalStringProcessing = Args.hasFlag(OPT_enable_experimental_string_processing, - OPT_disable_experimental_string_processing); + OPT_disable_experimental_string_processing, /*Default=*/true); // Add a future feature if it is not already implied by the language version. auto addFutureFeatureIfNotImplied = [&](Feature feature) { From a686e878ef4e3e921824b617aef3a28aae1b621d Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 24 Jun 2022 09:24:29 -0700 Subject: [PATCH 071/491] [next] Add missing include for llvm/IR/Constants.h --- lib/IRGen/TargetConstantFolding.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/IRGen/TargetConstantFolding.cpp b/lib/IRGen/TargetConstantFolding.cpp index 51cf7ddaaf957..6a15690ba3180 100644 --- a/lib/IRGen/TargetConstantFolding.cpp +++ b/lib/IRGen/TargetConstantFolding.cpp @@ -21,6 +21,7 @@ #include "swift/SIL/SILBuilder.h" #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Utils/InstructionDeleter.h" +#include "llvm/IR/Constants.h" #include "llvm/Support/Debug.h" using namespace swift; From 149efac8780f6e534c5ccff76ae0516ae0b53064 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Fri, 17 Jun 2022 13:30:34 -0700 Subject: [PATCH 072/491] Update swift to build against cas-support --- lib/ClangImporter/ClangModuleDependencyScanner.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index 8317955075676..e0d6f902e3951 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -44,8 +44,9 @@ class swift::ClangModuleDependenciesCacheImpl { ClangModuleDependenciesCacheImpl() : importHackFileCache(), - service(ScanningMode::MinimizedSourcePreprocessing, ScanningOutputFormat::Full), - tool(service) { } + service(ScanningMode::DependencyDirectivesScan, + ScanningOutputFormat::Full, clang::CASOptions(), nullptr), + tool(service) {} ~ClangModuleDependenciesCacheImpl(); /// Retrieve the name of the file used for the "import hack" that is From bdf60152f097d2901d134300ae69019a9d0d4ef2 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 29 Jun 2022 08:52:47 -0700 Subject: [PATCH 073/491] [Test] Add a hack to prevent a very odd tail bug `test/Driver/filelists.swift` writes out the swift driver jobs to a file called `%t/forFilelistCapture`. We then `tail -2 | head -1` that file to get the first line, run some seds, and expect that to the output file list (eg. from the swift-frontend command). Unfortunately if that file happens to end up being 4096 in length, `tail` skips the first line and thus the seds run on *second* line. That produces `/usr/bin/ld` instead, which obviously doesn't contain the output files! Add a comment to the end of the file so that it's unlikely to be 4096 in length. Technically we could still hit it if we removed a bunch of arguments, but this is fine until that bug is fixed. --- test/Driver/filelists.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/Driver/filelists.swift b/test/Driver/filelists.swift index 7b52089623f48..2cdfa720dca5b 100644 --- a/test/Driver/filelists.swift +++ b/test/Driver/filelists.swift @@ -76,9 +76,10 @@ // RUN: %empty-directory(%t) // RUN: echo "int dummy;" >%t/a.cpp // RUN: %target-clang -c %t/a.cpp -o %t/a.o -// RUN: %swiftc_driver -save-temps -driver-print-jobs %S/../Inputs/empty.swift %t/a.o -lto=llvm-full -target x86_64-apple-macosx10.9 -driver-filelist-threshold=0 -o filelist 2>&1 | tee %t/forFilelistCapture | %FileCheck -check-prefix FILELIST %s -// RUN: tail -2 %t/forFilelistCapture | head -1 | sed 's/.*-output-filelist //' | sed 's/ .*//' > %t/output-filelist -// RUN: tail -1 %t/forFilelistCapture | sed 's/.*-filelist //' | sed 's/ .*//' > %t/input-filelist +// RUN: %swiftc_driver -save-temps -driver-print-jobs %S/../Inputs/empty.swift %t/a.o -lto=llvm-full -target x86_64-apple-macosx10.9 -driver-filelist-threshold=0 -o filelist 2>&1 | tee -a %t/forFilelistCapture | %FileCheck -check-prefix FILELIST %s +// RUN: echo "# A comment so it's less likely this file will be 4096 in size\n" >> %t/forFilelistCapture +// RUN: tail -3 %t/forFilelistCapture | head -1 | sed 's/.*-output-filelist //' | sed 's/ .*//' > %t/output-filelist +// RUN: tail -2 %t/forFilelistCapture | head -1 | sed 's/.*-filelist //' | sed 's/ .*//' > %t/input-filelist // RUN: cat $(cat %t/output-filelist) | %FileCheck -check-prefix OUTPUT-FILELIST-CONTENTS %s // RUN: cat $(cat %t/input-filelist) | %FileCheck -check-prefix INPUT-FILELIST-CONTENTS %s From 93c350dff7e6080d11503ba17adb4c3a53abb7f9 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 30 Jun 2022 12:27:25 -0700 Subject: [PATCH 074/491] Reference style doesn't allow links in abstracts. Fixes --- stdlib/public/core/FloatingPoint.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/core/FloatingPoint.swift b/stdlib/public/core/FloatingPoint.swift index d4f5e6a48e244..b1d6909e2bf68 100644 --- a/stdlib/public/core/FloatingPoint.swift +++ b/stdlib/public/core/FloatingPoint.swift @@ -328,7 +328,7 @@ public protocol FloatingPoint: SignedNumeric, Strideable, Hashable /// `infinity` is greater than this value. static var greatestFiniteMagnitude: Self { get } - /// The [mathematical constant Ï€][wiki], approximately equal to 3.14159. + /// The mathematical constant pi (Ï€), approximately equal to 3.14159. /// /// When measuring an angle in radians, Ï€ is equivalent to a half-turn. /// From deed208b7b5b6ac801d261f5aa8948fd8fbe8dee Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 30 Jun 2022 12:33:30 -0700 Subject: [PATCH 075/491] Add an example and cross reference to TSPL. Fixes --- stdlib/public/core/KeyPath.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift index 30d99bae7ff25..03e8880b1262d 100644 --- a/stdlib/public/core/KeyPath.swift +++ b/stdlib/public/core/KeyPath.swift @@ -200,6 +200,14 @@ public class PartialKeyPath: AnyKeyPath { } internal enum KeyPathKind { case readOnly, value, reference } /// A key path from a specific root type to a specific resulting value type. +/// +/// The most common way to make an instance of this type +/// is by using a key-path expression like `\SomeClass.someProperty`. +/// For more information, +/// see [Key-Path Expressions[keypath] in *[The Swift Programming Language][tspl]*. +/// +/// [keypath]: https://docs.swift.org/swift-book/ReferenceManual/Expressions.html#ID563 +/// [tspl]: https://docs.swift.org/swift-book/ public class KeyPath: PartialKeyPath { @usableFromInline internal final override class var _rootAndValueType: ( From b8aae6ecf1e7b0c1ebd9aa9acf7c3affa95246ec Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 5 Jul 2022 12:29:08 -0700 Subject: [PATCH 076/491] [rebranch] Fix compile error caused by new AttrBuilder API `AttrBuilder` now requires a `LLVMContext &` to be passed in, fix up the use added in `main`. --- lib/IRGen/GenCall.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index d64536a8ce550..fb439a00db510 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -2923,7 +2923,7 @@ llvm::CallInst *IRBuilder::CreateCall(const FunctionPointer &fn, if (auto func = dyn_cast(fn.getRawPointer())) { for (unsigned argIndex = 0; argIndex < func->arg_size(); ++argIndex) { if (func->hasParamAttribute(argIndex, llvm::Attribute::StructRet)) { - llvm::AttrBuilder builder; + llvm::AttrBuilder builder(func->getContext()); builder.addStructRetAttr(nullptr); attrs = attrs.addParamAttributes(func->getContext(), argIndex, builder); } From e46a285a98a09f2cefa59d6872851c7c2ac909e9 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 6 Jul 2022 17:06:58 -0700 Subject: [PATCH 077/491] Reference doesn't allow code voice in abstract. Fixes --- stdlib/public/core/Optional.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift index 067a05089a155..c77e875a17457 100644 --- a/stdlib/public/core/Optional.swift +++ b/stdlib/public/core/Optional.swift @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -/// A type that represents either a wrapped value or `nil`, the absence of a -/// value. +/// A type that represents either a wrapped value the absence of a value. /// /// You use the `Optional` type whenever you use optional values, even if you /// never type the word `Optional`. Swift's type system usually shows the From 8f6289745ba9e7b81c01308ca30301a6228754f5 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 6 Jul 2022 17:15:53 -0700 Subject: [PATCH 078/491] Add per-architecture availability note. The documentation publication pipeline doesn't have a way to expose per-architecture availability, like how it it shows per-platform availability. So add this in prose instead. Fixes --- stdlib/public/core/FloatingPointTypes.swift.gyb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb index a223c3764a5e2..bb8c2d36b48f1 100644 --- a/stdlib/public/core/FloatingPointTypes.swift.gyb +++ b/stdlib/public/core/FloatingPointTypes.swift.gyb @@ -41,8 +41,9 @@ def Availability(bits): if Self == 'Float16': SelfDocComment = '''\ -/// A half-precision (16b), floating-point value type.''' - +/// A half-precision (16b), floating-point value type. +/// +/// `Float16` is available on Apple silicon, and unavailable on Intel.''' elif Self == 'Float': SelfDocComment = '''\ /// A single-precision, floating-point value type.''' @@ -53,7 +54,9 @@ elif Self == 'Double': elif Self == 'Float80': SelfDocComment = '''\ -/// An extended-precision, floating-point value type.''' +/// An extended-precision, floating-point value type. +/// +/// `Float80` is available on Intel, and unavailable on Apple silicon.''' else: raise ValueError('Unhandled float type.') From 4dfaa820acc1383122f857e7702abeaaf35bdf62 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 29 Jun 2022 08:49:00 -0700 Subject: [PATCH 079/491] [rebranch] Remove now unused function --- lib/Serialization/Serialization.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 589971146a879..a310a063da176 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -80,10 +80,6 @@ using llvm::BCBlockRAII; ASTContext &SerializerBase::getASTContext() const { return M->getASTContext(); } -static StringRef withNullAsEmptyStringRef(const char *data) { - return StringRef(data ? data : ""); -} - /// Used for static_assert. static constexpr bool declIDFitsIn32Bits() { using Int32Info = std::numeric_limits; From a61af545454724ee475302392fb0bfd2d39049b9 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Tue, 12 Jul 2022 08:35:58 -0700 Subject: [PATCH 080/491] [build] Ignore .git in ninja copy As part of the build the entire ninja source dir is copied to the build dir and then built. When using git's fsmonitor feature the .git directory contains a socket which causes the copytree to fail. With this change .git is ignored entirely instead. Error: ``` Traceback (most recent call last): ... File "/Users/ksmiley/dev/oss-swift/swift/utils/swift_build_support/swift_build_support/build_script_invocation.py", line 69, in build_ninja ninja_build.build() File "/Users/ksmiley/dev/oss-swift/swift/utils/swift_build_support/swift_build_support/products/ninja.py", line 80, in build shell.copytree(self.source_dir, self.build_dir) File "/Users/ksmiley/dev/oss-swift/swift/utils/swift_build_support/swift_build_support/shell.py", line 193, in copytree shutil.copytree(src, dest) File "/Users/ksmiley/.pyenv/versions/3.10.2/lib/python3.10/shutil.py", line 556, in copytree return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks, File "/Users/ksmiley/.pyenv/versions/3.10.2/lib/python3.10/shutil.py", line 512, in _copytree raise Error(errors) shutil.Error: [('/Users/ksmiley/dev/oss-swift/ninja/.git/fsmonitor--daemon.ipc', '/Users/ksmiley/dev/oss-swift/build/buildbot_osx/ninja-build/.git/fsmonitor--daemon.ipc', "[Errno 102] Operation not supported on socket: '/Users/ksmiley/dev/oss-swift/ninja/.git/fsmonitor--daemon.ipc'")] ``` --- .../swift_build_support/products/ninja.py | 2 +- utils/swift_build_support/swift_build_support/shell.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/utils/swift_build_support/swift_build_support/products/ninja.py b/utils/swift_build_support/swift_build_support/products/ninja.py index 722fb61b3d63d..0c755c13d8b3b 100644 --- a/utils/swift_build_support/swift_build_support/products/ninja.py +++ b/utils/swift_build_support/swift_build_support/products/ninja.py @@ -77,7 +77,7 @@ def build(self): # Ninja can only be built in-tree. Copy the source tree to the build # directory. shell.rmtree(self.build_dir) - shell.copytree(self.source_dir, self.build_dir) + shell.copytree(self.source_dir, self.build_dir, ignore_pattern=".git") with shell.pushd(self.build_dir): shell.call([sys.executable, 'configure.py', '--bootstrap'], env=env) diff --git a/utils/swift_build_support/swift_build_support/shell.py b/utils/swift_build_support/swift_build_support/shell.py index 222d540dd2c95..a40726537228f 100644 --- a/utils/swift_build_support/swift_build_support/shell.py +++ b/utils/swift_build_support/swift_build_support/shell.py @@ -183,13 +183,14 @@ def rmtree(path, dry_run=None, echo=True): shutil.rmtree(path) -def copytree(src, dest, dry_run=None, echo=True): +def copytree(src, dest, dry_run=None, ignore_pattern=None, echo=True): dry_run = _coerce_dry_run(dry_run) if dry_run or echo: _echo_command(dry_run, ['cp', '-r', src, dest]) if dry_run: return - shutil.copytree(src, dest) + ignore = shutil.ignore_patterns(ignore_pattern) if ignore_pattern else None + shutil.copytree(src, dest, ignore=ignore) def symlink(source, dest, dry_run=None, echo=True): From cd5253cfbd08d869e24c6127a5c74c2e0fbc1f6f Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Tue, 12 Jul 2022 12:00:53 -0700 Subject: [PATCH 081/491] [build] Add swift-autolink-extract to macOS toolchains Including this symlink makes it easier to cross compile for Linux which requires use of this tool. --- utils/build-presets.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build-presets.ini b/utils/build-presets.ini index 5a4bc093c832f..3a46c3cd5d7db 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -18,7 +18,7 @@ swift-install-components=back-deployment;compiler;clang-builtin-headers;stdlib;s [preset: mixin_buildbot_install_components_with_clang] -swift-install-components=back-deployment;compiler;clang-resource-dir-symlink;stdlib;sdk-overlay;parser-lib;static-mirror-lib;toolchain-tools;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers +swift-install-components=autolink-driver;back-deployment;compiler;clang-resource-dir-symlink;stdlib;sdk-overlay;parser-lib;static-mirror-lib;toolchain-tools;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers llvm-install-components=llvm-cov;llvm-profdata;IndexStore;clang;clang-resource-headers;compiler-rt;clangd;dsymutil;LTO;clang-features-file [preset: mixin_buildbot_trunk_base] From 183993c2da1b2d305f69c3cf25c7fa68aef3645a Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Tue, 19 Jul 2022 10:06:25 -0700 Subject: [PATCH 082/491] [rebranch] Use new AddressSanitizerOptions in pass construction llvm/llvm-project `3131714f8daca338492a7d5b189e4d63131bc808` changed `ModuleAddressSanitizerPass` to take an `AddressSanitizerOptions` instead. `b7fd30eac3183993806cc218b6deb39eb625c083` also removed `AddressSanitizerPass` after it was rolled into `ModuleAddressSanitizerPass` in `b7fd30eac3183993806cc218b6deb39eb625c083`. Update IRGen to use the new options and remove the additional pass. --- lib/IRGen/IRGen.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index 409a9f3afb370..ef828acb2a51c 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -484,21 +484,17 @@ performOptimizationsUsingNewPassManger(const IRGenOptions &Opts, if (Opts.Sanitizers & SanitizerKind::Address) { PB.registerOptimizerLastEPCallback([&](ModulePassManager &MPM, OptimizationLevel Level) { - auto Recover = bool(Opts.SanitizersWithRecoveryInstrumentation & - SanitizerKind::Address); - bool UseAfterScope = false; - bool ModuleUseAfterScope = true; - bool UseOdrIndicator = Opts.SanitizeAddressUseODRIndicator; - llvm::AsanDtorKind DestructorKind = llvm::AsanDtorKind::Global; - llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn = - llvm::AsanDetectStackUseAfterReturnMode::Runtime; + AddressSanitizerOptions ASOpts; + ASOpts.CompileKernel = false; + ASOpts.Recover = bool(Opts.SanitizersWithRecoveryInstrumentation & + SanitizerKind::Address); + ASOpts.UseAfterScope = false; + ASOpts.UseAfterReturn = llvm::AsanDetectStackUseAfterReturnMode::Runtime; MPM.addPass( RequireAnalysisPass()); - MPM.addPass(ModuleAddressSanitizerPass(false, Recover, - ModuleUseAfterScope, - UseOdrIndicator, DestructorKind)); - MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( - {false, Recover, UseAfterScope, UseAfterReturn}))); + MPM.addPass(ModuleAddressSanitizerPass( + ASOpts, /*UseGlobalGC=*/true, Opts.SanitizeAddressUseODRIndicator, + /*DestructorKind=*/llvm::AsanDtorKind::Global)); }); } From f8b716947d06c04dc6743cd4332cfcf030dbcc97 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 21 Jul 2022 11:25:39 -0700 Subject: [PATCH 083/491] Add missing 'try' for throwing async code. Fixes --- stdlib/public/Concurrency/TaskGroup.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/public/Concurrency/TaskGroup.swift b/stdlib/public/Concurrency/TaskGroup.swift index 4313b9b9be848..586ed25d87b38 100644 --- a/stdlib/public/Concurrency/TaskGroup.swift +++ b/stdlib/public/Concurrency/TaskGroup.swift @@ -99,14 +99,14 @@ public func withTaskGroup( /// you can use a `for`-`await`-`in` loop: /// /// var sum = 0 -/// for await result in group { +/// for try await result in group { /// sum += result /// } /// /// If you need more control or only a few results, /// you can call `next()` directly: /// -/// guard let first = await group.next() else { +/// guard let first = try await group.next() else { /// group.cancelAll() /// return 0 /// } @@ -578,7 +578,7 @@ public struct ThrowingTaskGroup { /// /// You can also use a `for`-`await`-`in` loop to collect results of a task group: /// - /// for await try value in group { + /// for try await value in group { /// collected += value /// } /// From c0abd3a3e8379c490b6ec1ae0183cd5f9e2567b0 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 21 Jul 2022 11:31:36 -0700 Subject: [PATCH 084/491] Remove unused link destination. See also commit 93c350dff7e6080d11503ba17adb4c3a53abb7f9 --- stdlib/public/core/FloatingPoint.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/public/core/FloatingPoint.swift b/stdlib/public/core/FloatingPoint.swift index b1d6909e2bf68..3207f921e4252 100644 --- a/stdlib/public/core/FloatingPoint.swift +++ b/stdlib/public/core/FloatingPoint.swift @@ -339,8 +339,6 @@ public protocol FloatingPoint: SignedNumeric, Strideable, Hashable /// /// print(Double.pi) /// // Prints "3.14159265358979" - /// - /// [wiki]: https://en.wikipedia.org/wiki/Pi static var pi: Self { get } // NOTE: Rationale for "ulp" instead of "epsilon": From 7a75ddafe18813aa07a7c6b63ab648d881181d4e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 21 Jul 2022 17:03:18 -0700 Subject: [PATCH 085/491] Add "#if hasAttribute(X)" support query attributes. --- include/swift/AST/Attr.h | 4 ++++ lib/AST/Attr.cpp | 20 ++++++++++++++++++++ lib/Parse/ParseIfConfig.cpp | 13 +++++++++++++ test/attr/has_attribute.swift | 25 +++++++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 test/attr/has_attribute.swift diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 221381d5cdfeb..8b76b434e55c3 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -2626,6 +2626,10 @@ inline SourceLoc extractNearestSourceLoc(const DeclAttribute *attr) { return attr->getLocation(); } +/// Determine whether the given attribute is available, looking up the +/// attribute by name. +bool hasAttribute(const LangOptions &langOpts, llvm::StringRef attributeName); + } // end namespace swift #endif diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 4b26fac5c8b61..043789fc86cf1 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -2285,3 +2285,23 @@ void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) { if (attr) attr->print(out); } + +bool swift::hasAttribute( + const LangOptions &langOpts, llvm::StringRef attributeName) { + DeclAttrKind kind = DeclAttribute::getAttrKindFromString(attributeName); + if (kind == DAK_Count) + return false; + + if (DeclAttribute::isUserInaccessible(kind)) + return false; + if (DeclAttribute::isDeclModifier(kind)) + return false; + if (DeclAttribute::shouldBeRejectedByParser(kind)) + return false; + if (DeclAttribute::isSilOnly(kind)) + return false; + if (DeclAttribute::isConcurrencyOnly(kind)) + return false; + + return true; +} diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp index 75d07691d7093..a26014c11f1f0 100644 --- a/lib/Parse/ParseIfConfig.cpp +++ b/lib/Parse/ParseIfConfig.cpp @@ -346,6 +346,16 @@ class ValidateIfConfigCondition : return E; } + if (*KindName == "hasAttribute") { + if (!getDeclRefStr(Arg, DeclRefKind::Ordinary)) { + D.diagnose(E->getLoc(), diag::unsupported_platform_condition_argument, + "attribute name"); + return nullptr; + } + + return E; + } + // ( 'os' | 'arch' | '_endian' | '_runtime' ) '(' identifier ')'' auto Kind = getPlatformConditionKind(*KindName); if (!Kind.hasValue()) { @@ -574,6 +584,9 @@ class EvaluateIfConfigCondition : } else if (KindName == "hasFeature") { auto featureName = getDeclRefStr(Arg); return Ctx.LangOpts.hasFeature(featureName); + } else if (KindName == "hasAttribute") { + auto attributeName = getDeclRefStr(Arg); + return hasAttribute(Ctx.LangOpts, attributeName); } auto Val = getDeclRefStr(Arg); diff --git a/test/attr/has_attribute.swift b/test/attr/has_attribute.swift new file mode 100644 index 0000000000000..0d93e67975d0c --- /dev/null +++ b/test/attr/has_attribute.swift @@ -0,0 +1,25 @@ +// RUN: %target-typecheck-verify-swift + +#if !hasAttribute(dynamicCallable) +BOOM +#endif + +#if hasAttribute(fortran) +BOOM +#endif + +#if hasAttribute(cobol) +this is unparsed junk // expected-error{{consecutive statements on a line must be separated by}} +#endif + +#if hasAttribute(optional) +ModifiersAreNotAttributes +#endif + +#if hasAttribute(__raw_doc_comment) +UserInaccessibleAreNotAttributes +#endif + +#if hasAttribute(17) +// expected-error@-1{{unexpected platform condition argument: expected attribute name}} +#endif From b3c5fde118f2a7782ea2b887e1349109a3215c00 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sat, 23 Jul 2022 14:30:14 -0700 Subject: [PATCH 086/491] Parse declaration attributes within #if...#endif blocks. Introduce support for parsing declaration attributes that occur within example: #if hasAttribute(frozen) @frozen #endif public struct X { ... } will apply to "frozen" attribute to the struct `X`, but only when the compiler supports the "frozen" attribute. Correctly determining whether a particular `#if` block contains attributes to be associated with the following declaration vs. starting a new declaration requires arbitrary lookahead. The parser will ensure that at least one of the branches of the `#if` contains an attribute, and that none of the branches contains something that does not fit the attribute grammar, before committing to parsing the `#if` clause as part of the declaration attributes. This lookahead does occur at the top level (e.g., in the parsing of top-level declarations and code), but should only need to scan past the first `#if` line to the following token in the common case. Unlike other `#if` when used to wrap statements or declarations, we make no attempt to record the `#if` not taken anywhere in the AST. This reflects a change in attitude in the design of the AST, because we have found that trying to represent this information there (e.g., via `IfConfigDecl`) complicates clients while providing little value. This information is best kept in the syntax tree, only. --- include/swift/Parse/Parser.h | 55 +++++++++++- lib/Parse/ParseDecl.cpp | 77 ++++++++++++----- lib/Parse/ParseIfConfig.cpp | 119 ++++++++++++++++++++++---- lib/Parse/ParseStmt.cpp | 3 +- lib/Parse/Parser.cpp | 10 ++- test/attr/conditional_attribute.swift | 94 ++++++++++++++++++++ 6 files changed, 308 insertions(+), 50 deletions(-) create mode 100644 test/attr/conditional_attribute.swift diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 15f863b0458bb..6737f7b22fa35 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -100,6 +100,16 @@ class ConsumeTokenReceiver { virtual ~ConsumeTokenReceiver() = default; }; +/// The role of the elements in a given #if +enum class IfConfigElementsRole { + // Parse normally. + Normal, + // Parse, but only for syntax. Throw away the results. + SyntaxOnly, + // Already skipped; no need to parse anything. + Skipped +}; + /// The main class used for parsing a source file (.swift or .sil). /// /// Rather than instantiating a Parser yourself, use one of the parsing APIs @@ -684,7 +694,8 @@ class Parser { while (Tok.isNot(K..., tok::eof, tok::r_brace, tok::pound_endif, tok::pound_else, tok::pound_elseif, tok::code_complete) && - !isStartOfStmt() && !isStartOfSwiftDecl()) { + !isStartOfStmt() && + !isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false)) { skipSingle(); } } @@ -945,7 +956,7 @@ class Parser { // Decl Parsing /// Returns true if parser is at the start of a Swift decl or decl-import. - bool isStartOfSwiftDecl(); + bool isStartOfSwiftDecl(bool allowPoundIfAttributes = true); /// Returns true if the parser is at the start of a SIL decl. bool isStartOfSILDecl(); @@ -982,6 +993,7 @@ class Parser { ParserResult parseDecl(ParseDeclOptions Flags, bool IsAtStartOfLineOrPreviousHadSemi, + bool IfConfigsAreDeclAttrs, llvm::function_ref Handler); std::pair, Optional> @@ -1004,12 +1016,29 @@ class Parser { ParserResult parseDeclAssociatedType(ParseDeclOptions Flags, DeclAttributes &Attributes); - + + /// Parse a #if ... #endif directive. + /// Delegate callback function to parse elements in the blocks and record + /// them however they wish. The parsing function will be provided with the + /// location of the clause token (`#if`, `#else`, etc.), the condition, + /// whether this is the active clause, and the role of the elements. + template + Result parseIfConfigRaw( + llvm::function_ref + parseElements, + llvm::function_ref finish); + /// Parse a #if ... #endif directive. /// Delegate callback function to parse elements in the blocks. ParserResult parseIfConfig( llvm::function_ref &, bool)> parseElements); + /// Parse an #if ... #endif containing only attributes. + ParserStatus parseIfConfigDeclAttributes( + DeclAttributes &attributes, bool ifConfigsAreDeclAttrs, + PatternBindingInitializer *initContext); + /// Parse a #error or #warning diagnostic. ParserResult parseDeclPoundDiagnostic(); @@ -1020,8 +1049,26 @@ class Parser { void setLocalDiscriminator(ValueDecl *D); void setLocalDiscriminatorToParamList(ParameterList *PL); + /// Skip an `#if` configuration block containing only attributes. + /// + /// \returns true if the skipping was successful, false otherwise. + bool skipIfConfigOfAttributes(bool &sawAnyAttributes); + + /// Determine whether the `#if` at which the parser occurs only contains + /// attributes (in all branches), in which case it is treated as part of + /// an attribute list. + bool ifConfigContainsOnlyAttributes(); + /// Parse the optional attributes before a declaration. - ParserStatus parseDeclAttributeList(DeclAttributes &Attributes); + ParserStatus parseDeclAttributeList(DeclAttributes &Attributes, + bool IfConfigsAreDeclAttrs = false); + + /// Parse the optional attributes before a declaration. + /// + /// This is the inner loop, which can be called recursively. + ParserStatus parseDeclAttributeList(DeclAttributes &Attributes, + bool IfConfigsAreDeclAttrs, + PatternBindingInitializer *initContext); /// Parse the optional modifiers before a declaration. bool parseDeclModifierList(DeclAttributes &Attributes, SourceLoc &StaticLoc, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d5b2c0c9ef7ae..77e45817256a1 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3793,6 +3793,26 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes, return makeParserSuccess(); } +ParserStatus Parser::parseDeclAttributeList( + DeclAttributes &Attributes, bool ifConfigsAreDeclAttrs, + PatternBindingInitializer *initContext) { + ParserStatus Status; + while (Tok.isAny(tok::at_sign, tok::pound_if)) { + if (Tok.is(tok::at_sign)) { + SyntaxParsingContext AttrCtx(SyntaxContext, SyntaxKind::Attribute); + SourceLoc AtLoc = consumeToken(); + Status |= parseDeclAttribute(Attributes, AtLoc, initContext); + } else { + if (!ifConfigsAreDeclAttrs && !ifConfigContainsOnlyAttributes()) + break; + + Status |= parseIfConfigDeclAttributes( + Attributes, ifConfigsAreDeclAttrs, initContext); + } + } + return Status; +} + /// \verbatim /// attribute-list: /// /*empty*/ @@ -3800,19 +3820,14 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes, /// attribute-list-clause: /// '@' attribute /// \endverbatim -ParserStatus Parser::parseDeclAttributeList(DeclAttributes &Attributes) { - if (Tok.isNot(tok::at_sign)) +ParserStatus Parser::parseDeclAttributeList( + DeclAttributes &Attributes, bool IfConfigsAreDeclAttrs) { + if (Tok.isNot(tok::at_sign, tok::pound_if)) return makeParserSuccess(); PatternBindingInitializer *initContext = nullptr; - ParserStatus Status; SyntaxParsingContext AttrListCtx(SyntaxContext, SyntaxKind::AttributeList); - do { - SyntaxParsingContext AttrCtx(SyntaxContext, SyntaxKind::Attribute); - SourceLoc AtLoc = consumeToken(); - Status |= parseDeclAttribute(Attributes, AtLoc, initContext); - } while (Tok.is(tok::at_sign)); - return Status; + return parseDeclAttributeList(Attributes, IfConfigsAreDeclAttrs, initContext); } /// \verbatim @@ -3902,7 +3917,8 @@ bool Parser::parseDeclModifierList(DeclAttributes &Attributes, BacktrackingScope Scope(*this); consumeToken(); // consume actor - isActorModifier = isStartOfSwiftDecl(); + isActorModifier = isStartOfSwiftDecl( + /*allowPoundIfAttributes=*/false); } if (!isActorModifier) @@ -4273,7 +4289,7 @@ static void skipAttribute(Parser &P) { } } -bool Parser::isStartOfSwiftDecl() { +bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes) { if (Tok.is(tok::at_sign) && peekToken().is(tok::kw_rethrows)) { // @rethrows does not follow the general rule of @ so // it is needed to short circuit this else there will be an infinite @@ -4307,7 +4323,7 @@ bool Parser::isStartOfSwiftDecl() { // check 'let' and 'var' right now. if (Tok.is(tok::kw_try)) return peekToken().isAny(tok::kw_let, tok::kw_var); - + // Skip an attribute, since it might be a type attribute. This can't // happen at the top level of a scope, but we do use isStartOfSwiftDecl() // in positions like generic argument lists. @@ -4318,10 +4334,20 @@ bool Parser::isStartOfSwiftDecl() { // If this attribute is the last element in the block, // consider it is a start of incomplete decl. - if (Tok.isAny(tok::r_brace, tok::eof, tok::pound_endif)) + if (Tok.isAny(tok::r_brace, tok::eof) || + (Tok.is(tok::pound_endif) && !allowPoundIfAttributes)) return true; - return isStartOfSwiftDecl(); + return isStartOfSwiftDecl(allowPoundIfAttributes); + } + + // Skip a #if that contains only attributes in all branches. These will be + // parsed as attributes of a declaration, not as separate declarations. + if (Tok.is(tok::pound_if) && allowPoundIfAttributes) { + BacktrackingScope backtrack(*this); + bool sawAnyAttributes = false; + return skipIfConfigOfAttributes(sawAnyAttributes) && sawAnyAttributes && + isStartOfSwiftDecl(); } // If we have a decl modifying keyword, check if the next token is a valid @@ -4343,13 +4369,13 @@ bool Parser::isStartOfSwiftDecl() { // If we found the start of a decl while trying to skip over the // paren, then we have something incomplete like 'private('. Return // true for better recovery. - if (isStartOfSwiftDecl()) + if (isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false)) return true; skipSingle(); } } - return isStartOfSwiftDecl(); + return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false); } } @@ -4376,7 +4402,7 @@ bool Parser::isStartOfSwiftDecl() { consumeToken(tok::l_paren); consumeToken(tok::identifier); consumeToken(tok::r_paren); - return isStartOfSwiftDecl(); + return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false); } if (Tok.isContextualKeyword("actor")) { @@ -4388,7 +4414,7 @@ bool Parser::isStartOfSwiftDecl() { // it's an actor declaration, otherwise, it isn't. do { consumeToken(); - } while (isStartOfSwiftDecl()); + } while (isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false)); return Tok.is(tok::identifier); } @@ -4399,7 +4425,7 @@ bool Parser::isStartOfSwiftDecl() { // Otherwise, do a recursive parse. Parser::BacktrackingScope Backtrack(*this); consumeToken(tok::identifier); - return isStartOfSwiftDecl(); + return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false); } bool Parser::isStartOfSILDecl() { @@ -4510,12 +4536,13 @@ setOriginalDeclarationForDifferentiableAttributes(DeclAttributes attrs, ParserResult Parser::parseDecl(ParseDeclOptions Flags, bool IsAtStartOfLineOrPreviousHadSemi, + bool IfConfigsAreDeclAttrs, llvm::function_ref Handler) { ParserPosition BeginParserPosition; if (isCodeCompletionFirstPass()) BeginParserPosition = getParserPosition(); - if (Tok.is(tok::pound_if)) { + if (Tok.is(tok::pound_if) && !ifConfigContainsOnlyAttributes()) { auto IfConfigResult = parseIfConfig( [&](SmallVectorImpl &Decls, bool IsActive) { ParserStatus Status; @@ -4574,7 +4601,8 @@ Parser::parseDecl(ParseDeclOptions Flags, DeclAttributes Attributes; if (Tok.hasComment()) Attributes.add(new (Context) RawDocCommentAttr(Tok.getCommentRange())); - ParserStatus AttrStatus = parseDeclAttributeList(Attributes); + ParserStatus AttrStatus = parseDeclAttributeList( + Attributes, IfConfigsAreDeclAttrs); // Parse modifiers. // Keep track of where and whether we see a contextual keyword on the decl. @@ -5356,7 +5384,9 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi, if (loadCurrentSyntaxNodeFromCache()) { return ParserStatus(); } - Result = parseDecl(Options, IsAtStartOfLineOrPreviousHadSemi, handler); + Result = parseDecl( + Options, IsAtStartOfLineOrPreviousHadSemi, + /* IfConfigsAreDeclAttrs=*/false, handler); if (Result.isParseErrorOrHasCompletion()) skipUntilDeclRBrace(tok::semi, tok::pound_endif); SourceLoc SemiLoc; @@ -6200,7 +6230,8 @@ void Parser::skipSILUntilSwiftDecl() { // Tell the lexer we're about to start lexing SIL. Lexer::SILBodyRAII sbr(*L); - while (!Tok.is(tok::eof) && !isStartOfSwiftDecl()) { + while (!Tok.is(tok::eof) && + !isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false)) { // SIL pound dotted paths need to be skipped specially as they can contain // decl keywords like 'subscript'. if (consumeIf(tok::pound)) { diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp index a26014c11f1f0..8f94038376c77 100644 --- a/lib/Parse/ParseIfConfig.cpp +++ b/lib/Parse/ParseIfConfig.cpp @@ -744,12 +744,15 @@ static Expr *findAnyLikelySimulatorEnvironmentTest(Expr *Condition) { /// Parse and populate a #if ... #endif directive. /// Delegate callback function to parse elements in the blocks. -ParserResult Parser::parseIfConfig( - llvm::function_ref &, bool)> parseElements) { +template +Result Parser::parseIfConfigRaw( + llvm::function_ref + parseElements, + llvm::function_ref finish) { assert(Tok.is(tok::pound_if)); SyntaxParsingContext IfConfigCtx(SyntaxContext, SyntaxKind::IfConfigDecl); - SmallVector Clauses; Parser::StructureMarkerRAII ParsingDecl( *this, Tok.getLoc(), Parser::StructureMarkerKind::IfConfig); @@ -808,14 +811,14 @@ ParserResult Parser::parseIfConfig( SyntaxContext->addRawSyntax(ParsedRawSyntaxNode()); } else { llvm::SaveAndRestore S(InPoundIfEnvironment, true); - ParserResult Result = parseExprSequence(diag::expected_expr, + ParserResult result = parseExprSequence(diag::expected_expr, /*isBasic*/true, /*isForDirective*/true); - if (Result.hasCodeCompletion()) + if (result.hasCodeCompletion()) return makeParserCodeCompletionStatus(); - if (Result.isNull()) + if (result.isNull()) return makeParserError(); - Condition = Result.get(); + Condition = result.get(); if (validateIfConfigCondition(Condition, Context, Diags)) { // Error in the condition; isActive = false; @@ -847,7 +850,6 @@ ParserResult Parser::parseIfConfig( } // Parse elements - SmallVector Elements; llvm::SaveAndRestore S(InInactiveClauseEnvironment, InInactiveClauseEnvironment || !isActive); // Disable updating the interface hash inside inactive blocks. @@ -856,22 +858,22 @@ ParserResult Parser::parseIfConfig( T.emplace(CurrentTokenHash, None); if (isActive || !isVersionCondition) { - parseElements(Elements, isActive); + parseElements( + ClauseLoc, Condition, isActive, IfConfigElementsRole::Normal); } else if (SyntaxContext->isEnabled()) { // We shouldn't skip code if we are building syntax tree. // The parser will keep running and we just discard the AST part. DiagnosticSuppression suppression(Context.Diags); - SmallVector droppedElements; - parseElements(droppedElements, false); + parseElements( + ClauseLoc, Condition, isActive, IfConfigElementsRole::SyntaxOnly); } else { DiagnosticTransaction DT(Diags); skipUntilConditionalBlockClose(); DT.abort(); + parseElements( + ClauseLoc, Condition, isActive, IfConfigElementsRole::Skipped); } - Clauses.emplace_back(ClauseLoc, Condition, - Context.AllocateCopy(Elements), isActive); - if (Tok.isNot(tok::pound_elseif, tok::pound_else)) break; @@ -883,8 +885,89 @@ ParserResult Parser::parseIfConfig( SourceLoc EndLoc; bool HadMissingEnd = parseEndIfDirective(EndLoc); - auto *ICD = new (Context) IfConfigDecl(CurDeclContext, - Context.AllocateCopy(Clauses), - EndLoc, HadMissingEnd); - return makeParserResult(ICD); + return finish(EndLoc, HadMissingEnd); +} + +/// Parse and populate a #if ... #endif directive. +/// Delegate callback function to parse elements in the blocks. +ParserResult Parser::parseIfConfig( + llvm::function_ref &, bool)> parseElements) { + SmallVector clauses; + return parseIfConfigRaw>( + [&](SourceLoc clauseLoc, Expr *condition, bool isActive, + IfConfigElementsRole role) { + SmallVector elements; + if (role != IfConfigElementsRole::Skipped) + parseElements(elements, isActive); + if (role == IfConfigElementsRole::SyntaxOnly) + elements.clear(); + + clauses.emplace_back( + clauseLoc, condition, Context.AllocateCopy(elements), isActive); + }, [&](SourceLoc endLoc, bool hadMissingEnd) { + auto *ICD = new (Context) IfConfigDecl(CurDeclContext, + Context.AllocateCopy(clauses), + endLoc, hadMissingEnd); + return makeParserResult(ICD); + }); +} + +ParserStatus Parser::parseIfConfigDeclAttributes( + DeclAttributes &attributes, bool ifConfigsAreDeclAttrs, + PatternBindingInitializer *initContext) { + ParserStatus status = makeParserSuccess(); + return parseIfConfigRaw( + [&](SourceLoc clauseLoc, Expr *condition, bool isActive, + IfConfigElementsRole role) { + if (isActive) { + status |= parseDeclAttributeList( + attributes, ifConfigsAreDeclAttrs, initContext); + } else if (role != IfConfigElementsRole::Skipped) { + DeclAttributes skippedAttributes; + PatternBindingInitializer *skippedInitContext = nullptr; + status |= parseDeclAttributeList( + skippedAttributes, ifConfigsAreDeclAttrs, skippedInitContext); + } + }, + [&](SourceLoc endLoc, bool hadMissingEnd) { + return status; + }); +} + +bool Parser::skipIfConfigOfAttributes(bool &sawAnyAttributes) { + assert(Tok.is(tok::pound_if)); + while (true) { + // #if / #else / #elseif + consumeToken(); + + // + skipUntilTokenOrEndOfLine(tok::NUM_TOKENS); + + while (true) { + if (Tok.is(tok::at_sign)) { + sawAnyAttributes = true; + skipAnyAttribute(); + continue; + } + + if (Tok.is(tok::pound_if)) { + skipIfConfigOfAttributes(sawAnyAttributes); + continue; + } + + break; + } + + if (Tok.isNot(tok::pound_elseif, tok::pound_else)) + break; + } + + return Tok.isAtStartOfLine() && consumeIf(tok::pound_endif); +} + +bool Parser::ifConfigContainsOnlyAttributes() { + assert(Tok.is(tok::pound_if)); + bool sawAnyAttributes = false; + BacktrackingScope backtrack(*this); + return skipIfConfigOfAttributes(sawAnyAttributes) && sawAnyAttributes; } diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 2c27227afdc42..d5217c1b40b6c 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -346,7 +346,7 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl &Entries, // Parse the decl, stmt, or expression. PreviousHadSemi = false; - if (Tok.is(tok::pound_if)) { + if (Tok.is(tok::pound_if) && !isStartOfSwiftDecl()) { auto IfConfigResult = parseIfConfig( [&](SmallVectorImpl &Elements, bool IsActive) { parseBraceItems(Elements, Kind, IsActive @@ -389,6 +389,7 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl &Entries, ParserResult DeclResult = parseDecl(IsTopLevel ? PD_AllowTopLevel : PD_Default, IsAtStartOfLineOrPreviousHadSemi, + /*IfConfigsAreDeclAttrs=*/true, [&](Decl *D) { TmpDecls.push_back(D); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index d8403377e8c35..07c3b152891c4 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -186,7 +186,9 @@ void Parser::performCodeCompletionSecondPassImpl( ContextChange CC(*this, DC); parseDecl(ParseDeclOptions(info.Flags), - /*IsAtStartOfLineOrPreviousHadSemi=*/true, [&](Decl *D) { + /*IsAtStartOfLineOrPreviousHadSemi=*/true, + /*IfConfigsAreDeclAttrs=*/false, + [&](Decl *D) { if (auto *NTD = dyn_cast(DC)) { NTD->addMemberPreservingSourceOrder(D); } else if (auto *ED = dyn_cast(DC)) { @@ -766,7 +768,7 @@ void Parser::skipUntilDeclRBrace() { while (Tok.isNot(tok::eof, tok::r_brace, tok::pound_endif, tok::pound_else, tok::pound_elseif, tok::code_complete) && - !isStartOfSwiftDecl()) + !isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false)) skipSingle(); } @@ -776,7 +778,7 @@ void Parser::skipListUntilDeclRBrace(SourceLoc startLoc, tok T1, tok T2) { bool hasDelimiter = Tok.getLoc() == startLoc || consumeIf(tok::comma); bool possibleDeclStartsLine = Tok.isAtStartOfLine(); - if (isStartOfSwiftDecl()) { + if (isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false)) { // Could have encountered something like `_ var:` // or `let foo:` or `var:` @@ -806,7 +808,7 @@ void Parser::skipListUntilDeclRBrace(SourceLoc startLoc, tok T1, tok T2) { void Parser::skipUntilDeclRBrace(tok T1, tok T2) { while (Tok.isNot(T1, T2, tok::eof, tok::r_brace, tok::pound_endif, tok::pound_else, tok::pound_elseif) && - !isStartOfSwiftDecl()) { + !isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false)) { skipSingle(); } } diff --git a/test/attr/conditional_attribute.swift b/test/attr/conditional_attribute.swift new file mode 100644 index 0000000000000..a4cc5eb8dd69c --- /dev/null +++ b/test/attr/conditional_attribute.swift @@ -0,0 +1,94 @@ +// RUN: %target-typecheck-verify-swift + +#if hasAttribute(foo) +@foo(this is gibberish) +#endif +struct S1 { } + +@frozen +#if hasAttribute(foo) +@foo +#endif +public struct S2 { } + +#if hasAttribute(foo) +@foo +#endif +@inlinable +func f1() { } + +#if hasAttribute(foo) +@foo +#else +@available(*, deprecated, message: "nope") +@frozen +#endif +public struct S3 { } + +// Nested #if +#if hasAttribute(foo) + @foo +#elseif hasAttribute(available) + @available(*, deprecated, message: "nope") +#if hasAttribute(frozen) +@frozen +#endif +#endif +public struct S4 { } + +// Nested in a type +struct Inner { +#if hasAttribute(foo) + @foo(this is gibberish) +#endif + struct S1 { } + + @frozen +#if hasAttribute(foo) + #if hasAttribute(bar) + @foo @bar + #endif +#endif + public struct S2 { } + +#if hasAttribute(foo) + @foo +#endif + @inlinable + func f1() { } + +#if hasAttribute(foo) + @foo +#else + @available(*, deprecated, message: "nope") + @frozen +#endif + public struct S3 { } +} + +// Nested in a function +func f2() { +#if hasAttribute(foo) + @foo(this is gibberish) +#endif + struct S1 { } + + @available(*, deprecated) +#if hasAttribute(foo) + @foo +#endif + struct S2 { } + +#if hasAttribute(foo) + @foo +#endif + @available(*, deprecated) + func f1() { } + +#if hasAttribute(foo) + @foo +#else + @available(*, deprecated, message: "nope") +#endif + struct S3 { } +} From 3f8d80aaf60b7e9ce3f0d14eb0b3acbd6597f30b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 26 Jul 2022 10:13:59 -0400 Subject: [PATCH 087/491] Fix infinite recursion at the end of a file --- lib/Parse/ParseDecl.cpp | 4 ++-- lib/Parse/ParseIfConfig.cpp | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 77e45817256a1..a22da33554f28 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4346,8 +4346,8 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes) { if (Tok.is(tok::pound_if) && allowPoundIfAttributes) { BacktrackingScope backtrack(*this); bool sawAnyAttributes = false; - return skipIfConfigOfAttributes(sawAnyAttributes) && sawAnyAttributes && - isStartOfSwiftDecl(); + return skipIfConfigOfAttributes(sawAnyAttributes) && + (Tok.is(tok::eof) || (sawAnyAttributes && isStartOfSwiftDecl())); } // If we have a decl modifying keyword, check if the next token is a valid diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp index 8f94038376c77..0ddc6b439ae0a 100644 --- a/lib/Parse/ParseIfConfig.cpp +++ b/lib/Parse/ParseIfConfig.cpp @@ -962,6 +962,10 @@ bool Parser::skipIfConfigOfAttributes(bool &sawAnyAttributes) { break; } + // If we ran out of tokens, say we consumed the rest. + if (Tok.is(tok::eof)) + return true; + return Tok.isAtStartOfLine() && consumeIf(tok::pound_endif); } From 0475e7368da111214162b1593b786c4d4e1969f7 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 14 Jul 2022 14:15:01 -0700 Subject: [PATCH 088/491] IRGen: Enable the new llvm pass manager rdar://96687157 --- include/swift/AST/IRGenOptions.h | 2 +- include/swift/Option/FrontendOptions.td | 5 ++++- lib/Frontend/CompilerInvocation.cpp | 6 ++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 18fccce5a5f1c..35bbb8cfd084e 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -446,7 +446,7 @@ class IRGenOptions { IRGenOptions() : DWARFVersion(2), OutputKind(IRGenOutputKind::LLVMAssemblyAfterOptimization), - Verify(true), LegacyPassManager(1), OptMode(OptimizationMode::NotSet), + Verify(true), LegacyPassManager(0), OptMode(OptimizationMode::NotSet), Sanitizers(OptionSet()), SanitizersWithRecoveryInstrumentation(OptionSet()), SanitizeAddressUseODRIndicator(false), diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index a360b829185be..daa9774e3dde7 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -1083,5 +1083,8 @@ def concurrency_model_EQ : def enable_new_llvm_pass_manager : Flag<["-"], "enable-new-llvm-pass-manager">, - HelpText<"Enable new llvm pass manager">; + HelpText<"Enable the new llvm pass manager">; +def disable_new_llvm_pass_manager : + Flag<["-"], "disable-new-llvm-pass-manager">, + HelpText<"Disable the new llvm pass manager">; } // end let Flags = [FrontendOption, NoDriverOption, HelpHidden] diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 8cf7d740ee8ba..e78fb5fb59ad4 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2397,8 +2397,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, Opts.SwiftAsyncFramePointer = SwiftAsyncFramePointerKind::Never; } - if (Args.hasArg(OPT_enable_new_llvm_pass_manager)) - Opts.LegacyPassManager = false; + Opts.LegacyPassManager = + Args.hasFlag(OPT_disable_new_llvm_pass_manager, + OPT_enable_new_llvm_pass_manager, + Opts.LegacyPassManager); return false; } From 4ce47b618a87efac053aaace98f0b5625fb921c9 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 26 Jul 2022 11:33:43 -0700 Subject: [PATCH 089/491] IRGen: Add definitions to compiler.used at Onone LLVM's O0 pipeline has decided to run GlobalDCE (if there are coro intrinsics present in the module). Add definitions to compiler.used to counter act that. --- lib/IRGen/GenDecl.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index d629b4064d47d..7e5e6b0175c34 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -928,6 +928,15 @@ static void markGlobalAsUsedBasedOnLinkage(IRGenModule &IGM, LinkInfo &link, // That mostly means we need to be good at not marking things external. if (link.isUsed()) IGM.addUsedGlobal(global); + else if (!IGM.IRGen.Opts.shouldOptimize() && + !IGM.IRGen.Opts.ConditionalRuntimeRecords && + !IGM.IRGen.Opts.VirtualFunctionElimination && + !IGM.IRGen.Opts.WitnessMethodElimination && + !global->isDeclaration()) { + // llvm's pipeline has decide to run GlobalDCE as part of the O0 pipeline. + // Mark non public symbols as compiler used to counter act this. + IGM.addCompilerUsedGlobal(global); + } } bool LinkInfo::isUsed(IRLinkage IRL) { From d7f8e11a79ea56f7707196028a3cc734f50884d8 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 26 Jul 2022 12:09:48 -0700 Subject: [PATCH 090/491] tests: LLVM optimizes away internal globals that are not referenced otherwise --- test/IRGen/async/partial_apply.sil | 12 +++++++++--- test/IRGen/async/partial_apply_forwarder.sil | 2 -- test/IRGen/big_types_corner_cases.swift | 3 ++- test/IRGen/class_resilience.swift | 9 ++++++--- test/IRGen/partial_apply.sil | 19 ------------------- 5 files changed, 17 insertions(+), 28 deletions(-) diff --git a/test/IRGen/async/partial_apply.sil b/test/IRGen/async/partial_apply.sil index c75b1dfa88ba0..09f682faa1a8b 100644 --- a/test/IRGen/async/partial_apply.sil +++ b/test/IRGen/async/partial_apply.sil @@ -255,6 +255,7 @@ bb0(%0 : $Base): } sil public_external @receive_closure : $@async @convention(thin) (@owned @async @callee_guaranteed () -> (@owned C)) -> () +sil public_external @receive_closure2 : $@async @convention(thin) (@owned @async @callee_guaranteed (@owned Base) -> (@owned C)) -> () // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swift{{(tail)?}}cc void @test_partial_apply( // CHECK-LABEL: define internal swift{{(tail)?}}cc void @"$s26parametric_casting_closureTA"( @@ -266,8 +267,10 @@ bb0(%0 : $Base): %2 = partial_apply [callee_guaranteed] %1(%0) : $@async @convention(thin) (@owned Base) -> @owned C %3 = function_ref @receive_closure : $@async @convention(thin) (@owned @async @callee_guaranteed () -> (@owned C)) -> () %4 = apply %3(%2) : $@async @convention(thin) (@owned @async @callee_guaranteed () -> (@owned C)) -> () - %5 = tuple () - return %5 : $() + %5 = function_ref @receive_closure2 : $@async @convention(thin) (@owned @async @callee_guaranteed (@owned Base) -> (@owned C)) -> () + %8 = apply %5(%6) : $@async @convention(thin) (@owned @async @callee_guaranteed (@owned Base) -> (@owned C)) -> () + %7 = tuple () + return %7 : $() } @@ -281,10 +284,14 @@ entry(%i : $Int): unreachable } +sil public_external @receive_closure3 : $@async @convention(thin) (@owned @async @callee_guaranteed () -> ()) -> () + sil @partial_apply_complex_generic_function : $@async @convention(thin) (Int) -> () { bb0(%0 : $Int): %fn = function_ref @complex_generic_function : $@async @convention(thin) (Int) -> () %pa = partial_apply [callee_guaranteed] %fn (%0) : $@async @convention(thin) (Int) -> () + %fn2 = function_ref @receive_closure3 : $@async @convention(thin) (@owned @async @callee_guaranteed () -> ()) -> () + apply %fn2(%pa) : $@async @convention(thin) (@owned @async @callee_guaranteed () -> ()) -> () %result = tuple () return %result : $() } @@ -606,7 +613,6 @@ bb0(%thick : $@callee_guaranteed @async @convention(thick) (Int64, Int32) -> Int return %pa_f : $@async @callee_guaranteed (Int64) -> Int64 } -// CHECK-LABEL: define internal swift{{(tail)?}}cc void @"$sTA.{{[0-9]+}}"( // CHECK-LABEL: define internal swift{{(tail)?}}cc void @"$sTA.{{[0-9]+}}"( sil @external_closure : $@convention(thin) @async (Int, Int) -> (Int, @error Error) diff --git a/test/IRGen/async/partial_apply_forwarder.sil b/test/IRGen/async/partial_apply_forwarder.sil index 79988aee0b9c9..804da5a7e9ffb 100644 --- a/test/IRGen/async/partial_apply_forwarder.sil +++ b/test/IRGen/async/partial_apply_forwarder.sil @@ -49,7 +49,6 @@ entry(%p : $*Ï„_0_0): unreachable } -// CHECK-LABEL: define internal swift{{(tail)?}}cc void @"$s7takingPTA"( sil hidden @reabstract_context : $@async @convention(thin) (@owned C) -> () { bb0(%0 : $C): %6 = alloc_stack $C @@ -119,7 +118,6 @@ bb0(%0 : $*Ï„_0_1, %2: $EmptyType): } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swift{{(tail)?}}cc void @bind_polymorphic_param_from_forwarder_parameter( -// CHECK-LABEL: define internal swift{{(tail)?}}cc void @"$s7takingQTA.{{[0-9]+}}"( sil public @bind_polymorphic_param_from_forwarder_parameter : $@async @convention(thin) <Ï„_0_1>(@in Ï„_0_1) -> () { bb0(%0 : $*Ï„_0_1): %1 = alloc_ref $WeakBox> diff --git a/test/IRGen/big_types_corner_cases.swift b/test/IRGen/big_types_corner_cases.swift index 97fa5a0150522..e3a7935b67211 100644 --- a/test/IRGen/big_types_corner_cases.swift +++ b/test/IRGen/big_types_corner_cases.swift @@ -159,9 +159,10 @@ class SuperSub : SuperBase { return BigStruct() } func f() { - let _ = { + let x = { nil ?? super.boom() } + x() } } diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift index 10fe5332edcce..b5aabafd4e6b8 100644 --- a/test/IRGen/class_resilience.swift +++ b/test/IRGen/class_resilience.swift @@ -3,8 +3,8 @@ // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_class.swiftmodule -module-name=resilient_class -I %t %S/../Inputs/resilient_class.swift -// RUN: %target-swift-frontend -enable-objc-interop -I %t -emit-ir -enable-library-evolution %t/class_resilience.swift | %FileCheck %t/class_resilience.swift --check-prefixes=CHECK,CHECK-objc,CHECK-objc%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-%target-import-type-objc-STABLE-ABI-%target-mandates-stable-abi -DINT=i%target-ptrsize -D#MDWORDS=7 -D#MDSIZE32=52 -D#MDSIZE64=80 -D#WORDSIZE=%target-alignment -// RUN: %target-swift-frontend -disable-objc-interop -I %t -emit-ir -enable-library-evolution %t/class_resilience.swift | %FileCheck %t/class_resilience.swift --check-prefixes=CHECK,CHECK-native,CHECK-native%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-native-STABLE-ABI-%target-mandates-stable-abi -DINT=i%target-ptrsize -D#MDWORDS=4 -D#MDSIZE32=40 -D#MDSIZE64=56 -D#WORDSIZE=%target-alignment +// RUN: %target-swift-frontend -enable-objc-interop -I %t -emit-ir -enable-library-evolution %t/class_resilience.swift | %FileCheck %t/class_resilience.swift --check-prefixes=CHECK,CHECK-objc,CHECK-objc%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-%target-import-type-objc-STABLE-ABI-%target-mandates-stable-abi,CHECK-%target-sdk-name -DINT=i%target-ptrsize -D#MDWORDS=7 -D#MDSIZE32=52 -D#MDSIZE64=80 -D#WORDSIZE=%target-alignment +// RUN: %target-swift-frontend -disable-objc-interop -I %t -emit-ir -enable-library-evolution %t/class_resilience.swift | %FileCheck %t/class_resilience.swift --check-prefixes=CHECK,CHECK-native,CHECK-native%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-native-STABLE-ABI-%target-mandates-stable-abi,CHECK-%target-sdk-name -DINT=i%target-ptrsize -D#MDWORDS=4 -D#MDSIZE32=40 -D#MDSIZE64=56 -D#WORDSIZE=%target-alignment // RUN: %target-swift-frontend -I %t -emit-ir -enable-library-evolution -O %t/class_resilience.swift // CHECK: @"$s16class_resilience26ClassWithResilientPropertyC1s16resilient_struct4SizeVvpWvd" = hidden global [[INT]] 0 @@ -34,7 +34,10 @@ // CHECK: @"$s16class_resilience14ResilientChildCMo" = {{(protected )?}}{{(dllexport )?}}global [[BOUNDS]] zeroinitializer -// CHECK: @"$s15resilient_class22ResilientOutsideParentC8getValueSiyFTq" = external{{( dllimport)?}} global %swift.method_descriptor +// CHECK-macosx: @"$s15resilient_class22ResilientOutsideParentC8getValueSiyFTq" = external{{( dllimport)?}} global %swift.method_descriptor +// CHECK-iphoneos: @"$s15resilient_class22ResilientOutsideParentC8getValueSiyFTq" = external{{( dllimport)?}} global %swift.method_descriptor +// CHECK-watchos: @"$s15resilient_class22ResilientOutsideParentC8getValueSiyFTq" = external{{( dllimport)?}} global %swift.method_descriptor +// CHECK-tvos: @"$s15resilient_class22ResilientOutsideParentC8getValueSiyFTq" = external{{( dllimport)?}} global %swift.method_descriptor // CHECK: @"$s16class_resilience14ResilientChildCMn" = {{(protected )?}}{{(dllexport )?}}constant <{{.*}}> <{ // -- flags: class, unique, has vtable, has override table, in-place initialization, has resilient superclass diff --git a/test/IRGen/partial_apply.sil b/test/IRGen/partial_apply.sil index b64180a4d05fc..98282d7f68979 100644 --- a/test/IRGen/partial_apply.sil +++ b/test/IRGen/partial_apply.sil @@ -392,12 +392,6 @@ sil public_external @receive_closure : $@convention(thin) (@o // CHECK: [[TYPE:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0 // CHECK: call swiftcc void @receive_closure(i8* bitcast (%T13partial_apply3SubC* (%swift.refcounted*)* @"$s26parametric_casting_closureTA.{{[0-9]+}}" to i8*), %swift.refcounted* [[CTX]], %swift.type* [[TYPE]]) -// CHECK-LABEL: define internal swiftcc %T13partial_apply3SubC* @"$s26parametric_casting_closureTA"(%T13partial_apply4BaseC* %0, %swift.refcounted* swiftself %1) -// CHECK: [[RES:%.*]] = tail call swiftcc %T13partial_apply4BaseC* @parametric_casting_closure -// CHECK: [[CASTED:%.*]] = bitcast %T13partial_apply4BaseC* [[RES]] to %T13partial_apply3SubC* -// CHECK: ret %T13partial_apply3SubC* [[CASTED]] - - // CHECK-LABEL: define internal swiftcc %T13partial_apply3SubC* @"$s26parametric_casting_closureTA.{{[0-9]+}}"(%swift.refcounted* swiftself %0) // CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s13partial_apply3SubCMa"(i64 0) // CHECK: [[TYPE:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0 @@ -458,19 +452,6 @@ bb0(%0 : $Int): // CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8*** // CHECK-NEXT: store i8** %T.Y.P2, i8*** [[T1]], align 8 -// CHECK-LABEL: define internal swiftcc void @"$s24complex_generic_functionTA"(%swift.refcounted* swiftself %0) -// CHECK: [[T0:%.*]] = bitcast %swift.refcounted* %0 to <{ %swift.refcounted, [24 x i8], %TSi }>* -// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, <{ %swift.refcounted, [24 x i8], %TSi }>* [[T0]], i32 0, i32 1 -// CHECK-NEXT: [[BUFFER:%.*]] = bitcast [24 x i8]* [[T1]] to %swift.type** -// CHECK-NEXT: %T = load %swift.type*, %swift.type** [[BUFFER]], align 8 -// CHECK-NEXT: store %swift.type* %T, %swift.type** -// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 1 -// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8*** -// CHECK-NEXT: %T.P2 = load i8**, i8*** [[T1]], align 8 -// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[BUFFER]], i32 2 -// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.type** [[T0]] to i8*** -// CHECK-NEXT: %T.Y.P2 = load i8**, i8*** [[T1]], align 8 - struct ComplexBoundedType {} // SR-901: Ensure that a partial_apply which captures bound generic type From 10ec81edf014aa090a4bd8f9e5356774fe79e70d Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 26 Jul 2022 05:43:45 -0700 Subject: [PATCH 091/491] IRGen: Add force import thunk to used globals on windows LLVM's new pass pipeline will otherwise remove the internal symbol. --- lib/IRGen/IRGenModule.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index ad22a072ca921..d191a35c8a7c9 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -1619,6 +1619,7 @@ static llvm::GlobalObject *createForceImportThunk(IRGenModule &IGM) { auto BB = llvm::BasicBlock::Create(IGM.getLLVMContext(), "", ForceImportThunk); llvm::IRBuilder<> IRB(BB); IRB.CreateRetVoid(); + IGM.addUsedGlobal(ForceImportThunk); return ForceImportThunk; } } From 3b4224020985731344e3140da49c6a4b9cf00712 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 27 Jul 2022 08:28:23 -0700 Subject: [PATCH 092/491] Adjust to removal of LLVM_ATTRIBUTE_DEPRECATED --- include/swift/SIL/SILValue.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h index 255a4748e3f6a..33d18862111d8 100644 --- a/include/swift/SIL/SILValue.h +++ b/include/swift/SIL/SILValue.h @@ -668,10 +668,10 @@ class SILValue { /// NOTE: This is implemented in ValueOwnership.cpp not SILValue.cpp. /// /// FIXME: remove this redundant API from SILValue. - LLVM_ATTRIBUTE_DEPRECATED( - ValueOwnershipKind getOwnershipKind() - const { return Value->getOwnershipKind(); }, - "Please use ValueBase::getOwnershipKind()"); + [[deprecated("Please use ValueBase::getOwnershipKind()")]] ValueOwnershipKind + getOwnershipKind() const { + return Value->getOwnershipKind(); + }; /// Verify that this SILValue and its uses respects ownership invariants. void verifyOwnership(DeadEndBlocks *DEBlocks) const; From 2418aeb3759627f06791e8ad882453d70e3dbfb6 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 29 Jul 2022 12:32:49 +0900 Subject: [PATCH 093/491] [Distributed] documentation --- .../public/Distributed/DistributedActor.swift | 159 +++++++++++++++++- .../Distributed/DistributedActorSystem.swift | 6 + 2 files changed, 156 insertions(+), 9 deletions(-) diff --git a/stdlib/public/Distributed/DistributedActor.swift b/stdlib/public/Distributed/DistributedActor.swift index f3f105149c9f3..b9d8ceff3c082 100644 --- a/stdlib/public/Distributed/DistributedActor.swift +++ b/stdlib/public/Distributed/DistributedActor.swift @@ -15,21 +15,151 @@ import _Concurrency // ==== Distributed Actor ----------------------------------------------------- + + /// Common protocol to which all distributed actors conform implicitly. /// -/// It is not possible to conform to this protocol manually explicitly. -/// Only a 'distributed actor' declaration or protocol with 'DistributedActor' -/// requirement may conform to this protocol. +/// The `DistributedActor` protocol generalizes over all distributed actor types. +/// Distributed actor types implicitly conform to this protocol. +/// +/// It is not possible to conform to this protocol manually by any other type +/// than a `distributed actor`. +/// +/// It is possible to require a type conform to the +/// ``DistributedActor`` protocol by refining it with another protocol, +/// or by using a generic constraint. +/// +/// +/// ## The ActorSystem associated type +/// Every distributed actor must declare what type of distributed actor system +/// it is part of by implementing the ``ActorSystem`` associated type requirement. +/// +/// This causes a number of other properties of the actor to be inferred: +/// - the ``SerializationRequirement`` that will be used at compile time to +/// verify `distributed` target declarations are well formed, +/// - if the distributed actor is `Codable`, based on the ``ID`` being Codable or not, +/// - the type of the `ActorSystem` accepted in the synthesized default initializer. +/// +/// A distributed actor must declare what type of actor system it is ready to +/// work with by fulfilling the ``ActorSystem`` type member requirement: +/// +/// ```swift +/// distributed actor Greeter { +/// typealias ActorSystem = GreetingSystem // which conforms to DistributedActorSystem +/// +/// func greet() -> String { "Hello!" } +/// } +/// ``` +/// +/// ### The DefaultDistributedActorSystem type alias +/// Since it is fairly common to only be using one specific type of actor system +/// within a module or entire codebase, it is possible to declare the default type +/// or actor system all distributed actors will be using in a module by declaring +/// a `DefaultDistributedActorSystem` module wide typealias: +/// +/// ```swift +/// import Distributed +/// import AmazingActorSystemLibrary +/// +/// typealias DefaultDistributedActorSystem = AmazingActorSystem +/// +/// distributed actor Greeter {} // ActorSystem == AmazingActorSystem +/// ``` +/// +/// This declaration makes all `distributed actor` declarations, +/// which do not explicitly specify an ``ActorSystem`` typealias, to assume the +/// `AmazingActorSystem` as their `ActorSystem`. +/// +/// It is possible for a specific actor to override the system it is using, +/// by declaring an ``ActorSystem`` type alias as usual: +/// +/// ```swift +/// typealias DefaultDistributedActorSystem = AmazingActorSystem +/// +/// distributed actor Amazing { +/// // ActorSystem == AmazingActorSystem +/// } +/// +/// distributed actor Superb { +/// typealias ActorSystem = SuperbActorSystem +/// } +/// ``` /// -/// The 'DistributedActor' protocol provides the core functionality of any -/// distributed actor. +/// In general the `DefaultDistributedActorSystem` should not be declared public, +/// as picking the default should be left up to each specific module of a project. /// -/// ## Implicit `Codable` conformance +/// ## Default initializer +/// While classes and actors receive a synthesized *argument-free default +/// initializer* (`init()`), distributed actors synthesize a default initializer +/// that accepts a distributed actor system the actor is part of: `init(actorSystem:)`. +/// +/// The accepted actor system must be of the `Self.ActorSystem` type, which +/// must conform to the ``DistributedActorSystem`` protocol. This is required +/// because of how distributed actors are always managed by, a concrete +/// distributed actor system, and cannot exist on their own without one. +/// +/// It is possible to explicitly declare an parameter-free initializer (`init()`), +/// however the `actorSystem` property still must be assigned a concrete actor +/// system instance the actor shall be part of. + +/// In general it is recommended to always have an `actorSystem` parameter as +/// the last non-defaulted non-closure parameter in every distributed actors +/// initializer parameter list. This way it is simple to swap in a "test actor +// system" instance in unit tests, and avoid relying on global state which could +/// make testing more difficult. +/// +/// ## Implicit properties +/// Every concrete `distributed actor` type receives two synthesized properties, +/// which implement the protocol requirements of this protocol: `id` and `actorSystem`. +/// +/// ### Property: Actor System +/// The ``actorSystem`` property is an important part of every distributed actor's lifecycle management. +/// Initialization as well as de-initialization both require interactions with the actor system, +/// and it is the actor system that delivers +/// +/// +/// The ``actorSystem`` property must be assigned in every designated initializer +/// of a distributed actor explicitly. It is highly recommended to make it a +/// parameter of every distributed actor initializer, and simply forward the +/// value to the stored property, like this: +/// +/// ```swift +/// init(name: String, actorSystem: Self.ActorSystem) { +/// self.name = name +/// self.actorSystem = actorSystem +/// } +/// ``` +/// +/// ### Property: Distributed Actor Identity +/// The ``id`` is assigned by the actor system during the distributed actor's +/// initialization, and cannot be set or mutated by the actor itself. +/// +/// The ``id`` is the effective identity of the actor, and is used in equality checks. +/// +/// ## Automatic Conformances +/// +/// ### Hashable and Identifiable conformance +/// Every distributed actor conforms to the Hashable and Identifiable protocols. +/// Its identity is strictly driven by its `id`, and therefore hash and equality +/// implementations directly delegate to the `id` property. +/// +/// Comparing a local distributed actor instance and a remote reference to it +/// (both using the same ``id``) always returns true, as they both conceptually +/// point at the same distributed actor. +/// +/// It is not possible to implement those protocols relying on the actual actor's +/// state, because it may be remote and the state may not be available. In other +/// words, since these protocols must be implemented using `nonisolated` functions, +/// only `nonisolated` `id` and `actorSystem` properties are accessible for their +/// implementations. +/// +/// ### Implicit `Codable` conformance /// If created with an actor system whose `ActorID` is `Codable`, the /// compiler will synthesize code for the concrete distributed actor to conform -/// to `Codable` as well. This is necessary to support distributed calls where -/// the `SerializationRequirement` is `Codable` and thus users may want to pass -/// actors as arguments to remote calls. +/// to `Codable` as well. +/// +/// This is necessary to support distributed calls where the `SerializationRequirement` +/// is `Codable` and thus users may want to pass actors as arguments to remote calls. /// /// The synthesized implementations use a single `SingleValueContainer` to /// encode/decode the `self.id` property of the actor. The `Decoder` required @@ -40,6 +170,10 @@ import _Concurrency /// /// Use the `CodingUserInfoKey.actorSystemKey` to provide the necessary /// actor system for the decoding initializer when decoding a distributed actor. +/// +/// - SeeAlso: ``DistributedActorSystem`` +/// - SeeAlso: ``Actor`` +/// - SeeAlso: ``AnyActor`` @available(SwiftStdlib 5.7, *) public protocol DistributedActor: AnyActor, Identifiable, Hashable where ID == ActorSystem.ActorID, @@ -102,6 +236,13 @@ extension DistributedActor { // ==== Codable conformance ---------------------------------------------------- extension CodingUserInfoKey { + + /// Key which is required to be set on a `Decoder`'s `userInfo` while attempting + /// to `init(from:)` a `DistributedActor`. The stored value under this key must + /// conform to ``DistributedActorSystem``. + /// + /// Missing to set this key will result in that initializer throwing, because + /// an actor system is required @available(SwiftStdlib 5.7, *) public static let actorSystemKey = CodingUserInfoKey(rawValue: "$distributed_actor_system")! } diff --git a/stdlib/public/Distributed/DistributedActorSystem.swift b/stdlib/public/Distributed/DistributedActorSystem.swift index 95f95d73d2e75..68d7e5bec4cd6 100644 --- a/stdlib/public/Distributed/DistributedActorSystem.swift +++ b/stdlib/public/Distributed/DistributedActorSystem.swift @@ -581,6 +581,12 @@ public struct ExecuteDistributedTargetError: DistributedActorSystemError { } } +/// Error thrown by distributed actor systems while encountering encoding/decoding +/// issues. +/// +/// Also thrown when attempt to decode ``DistributedActor`` is made, +/// but no ``DistributedActorSystem`` is available in the `Decoder`'s +/// `userInfo[.actorSystemKey]`, as it is required to perform the resolve call. @available(SwiftStdlib 5.7, *) public struct DistributedActorCodingError: DistributedActorSystemError { public let message: String From d34e086c79702e27f03ff15df49d4683b2762a5f Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Wed, 13 Jul 2022 20:40:45 -0700 Subject: [PATCH 094/491] Change return type of getEnumTag in value witness table make it actually matches the description above --- include/swift/ABI/ValueWitness.def | 2 +- lib/PrintAsClang/PrintClangValueType.cpp | 3 +-- .../SwiftToCxx/core/swift-impl-defs-in-cxx.swift | 2 +- .../SwiftToCxx/enums/swift-enum-case-functions.swift | 12 ++++++------ 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/swift/ABI/ValueWitness.def b/include/swift/ABI/ValueWitness.def index 646deb4bd0d78..151fb31db4eb4 100644 --- a/include/swift/ABI/ValueWitness.def +++ b/include/swift/ABI/ValueWitness.def @@ -262,7 +262,7 @@ END_VALUE_WITNESS_RANGE(TypeLayoutWitness, /// [0..NumElements-1]. FUNCTION_VALUE_WITNESS(getEnumTag, GetEnumTag, - INT_TYPE, + UINT_TYPE, (IMMUTABLE_VALUE_TYPE, TYPE_TYPE)) BEGIN_VALUE_WITNESS_RANGE(EnumValueWitness, diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index 2b81ed970b76a..d22a934d34121 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -228,8 +228,7 @@ void ClangValueTypePrinter::printValueTypeDecl( "metadata._0);\n"; os << " return _getOpaquePointer();\n"; os << " }\n"; - // FIXME: (tongjie) return type should be unsigned - os << " inline int _getEnumTag() const {\n"; + os << " inline unsigned _getEnumTag() const {\n"; printEnumVWTableVariable(); os << " return enumVWTable->getEnumTag(_getOpaquePointer(), " "metadata._0);\n"; diff --git a/test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift b/test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift index d28fc27daa443..0b91dee3a3037 100644 --- a/test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift +++ b/test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift @@ -53,7 +53,7 @@ // CHECK-NEXT: unsigned extraInhabitantCount; // CHECK-NEXT: }; // CHECK-EMPTY: -// CHECK-NEXT: using EnumValueWitnessGetEnumTagTy = int(* __ptrauth_swift_value_witness_function_pointer(41909))(const void * _Nonnull, void * _Nonnull) SWIFT_NOEXCEPT_FUNCTION_PTR; +// CHECK-NEXT: using EnumValueWitnessGetEnumTagTy = unsigned(* __ptrauth_swift_value_witness_function_pointer(41909))(const void * _Nonnull, void * _Nonnull) SWIFT_NOEXCEPT_FUNCTION_PTR; // CHECK-NEXT: using EnumValueWitnessDestructiveProjectEnumDataTy = void(* __ptrauth_swift_value_witness_function_pointer(1053))(void * _Nonnull, void * _Nonnull) SWIFT_NOEXCEPT_FUNCTION_PTR; // CHECK-NEXT: using EnumValueWitnessDestructiveInjectEnumTagTy = void(* __ptrauth_swift_value_witness_function_pointer(45796))(void * _Nonnull, unsigned, void * _Nonnull) SWIFT_NOEXCEPT_FUNCTION_PTR; // CHECK-EMPTY: diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift b/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift index c3a386979a2c9..fae7a13f21337 100644 --- a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift +++ b/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift @@ -170,7 +170,7 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: inline bool isThird() const { // CHECK-NEXT: return *this == cases::third; // CHECK-NEXT: } -// CHECK: inline int _getEnumTag() const { +// CHECK: inline unsigned _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums12BoolWithCaseOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; // CHECK-NEXT: #ifdef __arm64e__ @@ -201,7 +201,7 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: inline bool isThree() const { // CHECK-NEXT: return *this == cases::three; // CHECK-NEXT: } -// CHECK: inline int _getEnumTag() const { +// CHECK: inline unsigned _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums9CLikeEnumOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; // CHECK-NEXT: #ifdef __arm64e__ @@ -224,7 +224,7 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: inline bool isOne() const { // CHECK-NEXT: return *this == cases::one; // CHECK-NEXT: } -// CHECK: inline int _getEnumTag() const { +// CHECK: inline unsigned _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums8DataCaseOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; // CHECK-NEXT: #ifdef __arm64e__ @@ -255,7 +255,7 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: inline bool isBignum() const { // CHECK-NEXT: return *this == cases::Bignum; // CHECK-NEXT: } -// CHECK: inline int _getEnumTag() const { +// CHECK: inline unsigned _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums17IntDoubleOrBignumOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; // CHECK-NEXT: #ifdef __arm64e__ @@ -286,7 +286,7 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: inline bool isPosInfinity() const { // CHECK-NEXT: return *this == cases::PosInfinity; // CHECK-NEXT: } -// CHECK: inline int _getEnumTag() const { +// CHECK: inline unsigned _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums13IntOrInfinityOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; // CHECK-NEXT: #ifdef __arm64e__ @@ -321,7 +321,7 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: inline bool isFourth() const { // CHECK-NEXT: return *this == cases::fourth; // CHECK-NEXT: } -// CHECK: inline int _getEnumTag() const { +// CHECK: inline unsigned _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums20MultipleBoolWithCaseOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; // CHECK-NEXT: #ifdef __arm64e__ From a1907f499ea825e543a968c267b053d7785901d5 Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Mon, 8 Aug 2022 12:13:40 -0700 Subject: [PATCH 095/491] add test case checking return type --- .../core/unsigned-return-type-no-zext.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp diff --git a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp new file mode 100644 index 0000000000000..d53c089659e7d --- /dev/null +++ b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp @@ -0,0 +1,14 @@ +// RUN: %empty-directory(%t) +// RUN: %target-interop-build-clangxx -c %s -I %t -S -emit-llvm -o %t/ir.ll +// RUN: %FileCheck %s < %t/ir.ll + +unsigned char getEnumTagi8(void *p); +unsigned getEnumTagi32(void *p); + +void test(void *p) { + getEnumTagi8(p); + getEnumTagi32(p); +} + +// CHECK: declare zeroext i8 @_Z12getEnumTagi8Pv(i8*) #1 +// CHECK: declare i32 @_Z13getEnumTagi32Pv(i8*) #1 From bfba8d17eac7a421abf91d63fdafb51fe106bad7 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 Aug 2022 15:40:47 -0700 Subject: [PATCH 096/491] Fix link markup. Co-authored-by: Ben Rimmington --- stdlib/public/core/KeyPath.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift index 03e8880b1262d..796380b8b7d1a 100644 --- a/stdlib/public/core/KeyPath.swift +++ b/stdlib/public/core/KeyPath.swift @@ -204,7 +204,7 @@ internal enum KeyPathKind { case readOnly, value, reference } /// The most common way to make an instance of this type /// is by using a key-path expression like `\SomeClass.someProperty`. /// For more information, -/// see [Key-Path Expressions[keypath] in *[The Swift Programming Language][tspl]*. +/// see [Key-Path Expressions][keypath] in *[The Swift Programming Language][tspl]*. /// /// [keypath]: https://docs.swift.org/swift-book/ReferenceManual/Expressions.html#ID563 /// [tspl]: https://docs.swift.org/swift-book/ From 36114194c3b76996e16e7e9ae53870216cfc430c Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 Aug 2022 15:40:58 -0700 Subject: [PATCH 097/491] Fix missing word. Co-authored-by: Ben Rimmington --- stdlib/public/core/Optional.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift index c77e875a17457..e3b9068fb4f13 100644 --- a/stdlib/public/core/Optional.swift +++ b/stdlib/public/core/Optional.swift @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -/// A type that represents either a wrapped value the absence of a value. +/// A type that represents either a wrapped value or the absence of a value. /// /// You use the `Optional` type whenever you use optional values, even if you /// never type the word `Optional`. Swift's type system usually shows the From 4d35aae50e8fddf09bbb7dc840b2dedc848987bf Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 9 Aug 2022 12:45:36 -0700 Subject: [PATCH 098/491] Incorporate tech review from @stephentyrone. --- stdlib/public/core/FloatingPointTypes.swift.gyb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb index bb8c2d36b48f1..cbb1ae5b2787a 100644 --- a/stdlib/public/core/FloatingPointTypes.swift.gyb +++ b/stdlib/public/core/FloatingPointTypes.swift.gyb @@ -43,7 +43,8 @@ if Self == 'Float16': SelfDocComment = '''\ /// A half-precision (16b), floating-point value type. /// -/// `Float16` is available on Apple silicon, and unavailable on Intel.''' +/// `Float16` is available on Apple silicon, +/// and unavailable on Intel when targeting macOS.''' elif Self == 'Float': SelfDocComment = '''\ /// A single-precision, floating-point value type.''' @@ -56,7 +57,9 @@ elif Self == 'Float80': SelfDocComment = '''\ /// An extended-precision, floating-point value type. /// -/// `Float80` is available on Intel, and unavailable on Apple silicon.''' +/// `Float80` is available on Intel +/// when the target system supports an 80-bit long double type, +/// and unavailable on Apple silicon.''' else: raise ValueError('Unhandled float type.') From 5c058d9c48d7ceb84e196a6f9b12d3518d7cf638 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 10 Aug 2022 08:25:32 -0700 Subject: [PATCH 099/491] [IRGen] Update for upstream `clang::CreateLLVMCodeGen()` API change --- lib/IRGen/IRGenModule.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index a4fbcd09d0dbf..66e133cf4039d 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -35,6 +35,7 @@ #include "clang/CodeGen/CodeGenABITypes.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/CodeGen/SwiftCallingConv.h" +#include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/HeaderSearch.h" @@ -137,12 +138,13 @@ static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context, CGO.TrapFuncName = Opts.TrapFuncName; } + auto &VFS = Importer->getClangInstance().getVirtualFileSystem(); auto &HSI = Importer->getClangPreprocessor() .getHeaderSearchInfo() .getHeaderSearchOpts(); auto &PPO = Importer->getClangPreprocessor().getPreprocessorOpts(); auto *ClangCodeGen = clang::CreateLLVMCodeGen(ClangContext.getDiagnostics(), - ModuleName, HSI, PPO, CGO, + ModuleName, &VFS, HSI, PPO, CGO, LLVMContext); ClangCodeGen->Initialize(ClangContext); return ClangCodeGen; From 2f38f8305060e77b3b97f5642370805b80609592 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Thu, 11 Aug 2022 15:09:53 +0100 Subject: [PATCH 100/491] [test] Rename a test --- .../{coverage_deinit.swift => coverage_deinit_objc.swift} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test/Profiler/{coverage_deinit.swift => coverage_deinit_objc.swift} (85%) diff --git a/test/Profiler/coverage_deinit.swift b/test/Profiler/coverage_deinit_objc.swift similarity index 85% rename from test/Profiler/coverage_deinit.swift rename to test/Profiler/coverage_deinit_objc.swift index 39882aefdb7a9..776bbc7a87e1a 100644 --- a/test/Profiler/coverage_deinit.swift +++ b/test/Profiler/coverage_deinit_objc.swift @@ -12,5 +12,5 @@ public class Derived: NSString { } } -// CHECK-LABEL: sil_coverage_map "{{.*}}coverage_deinit.swift" "$s15coverage_deinit7DerivedCfD" +// CHECK-LABEL: sil_coverage_map "{{.*}}coverage_deinit_objc.swift" "$s15coverage_deinit7DerivedCfD" // CHECK-NEXT: [[@LINE-5]]:10 -> [[@LINE-4]]:4 : 0 From 19e1e2f7a2310be305c4848bb9fc07c24bab5f19 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Thu, 11 Aug 2022 15:09:53 +0100 Subject: [PATCH 101/491] [SILGen] Fix `deinit` coverage mapping Stop profiling the deallocating deinitializer function for non-ObjC classes, and instead profile the destructor, which is where we emit the user's code written in a `deinit`. rdar://54443107 --- lib/SILGen/SILGen.cpp | 2 +- lib/SILGen/SILGenDestructor.cpp | 2 -- test/Profiler/coverage_class.swift | 2 +- test/Profiler/coverage_deinit.swift | 30 +++++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 test/Profiler/coverage_deinit.swift diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index b5c3a8ec9c9ce..96d0bdcf4306b 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -1079,6 +1079,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) { auto *dd = cast(constant.getDecl()); preEmitFunction(constant, f, dd); PrettyStackTraceSILFunction X("silgen emitDestroyingDestructor", f); + f->createProfiler(dd, constant, ForDefinition); SILGenFunction(*this, *f, dd).emitDestroyingDestructor(dd); postEmitFunction(constant, f); return; @@ -1100,7 +1101,6 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) { auto loc = RegularLocation::getAutoGeneratedLocation(dd); preEmitFunction(constant, f, loc); PrettyStackTraceSILFunction X("silgen emitDeallocatingDestructor", f); - f->createProfiler(dd, constant, ForDefinition); SILGenFunction(*this, *f, dd).emitDeallocatingDestructor(dd); postEmitFunction(constant, f); return; diff --git a/lib/SILGen/SILGenDestructor.cpp b/lib/SILGen/SILGenDestructor.cpp index dea2dc4c0f867..bf523bbcd7ad8 100644 --- a/lib/SILGen/SILGenDestructor.cpp +++ b/lib/SILGen/SILGenDestructor.cpp @@ -207,8 +207,6 @@ void SILGenFunction::emitDeallocatingDestructor(DestructorDecl *dd) { selfForDealloc = B.createUncheckedRefCast(loc, selfForDealloc, classTy); B.createDeallocRef(loc, selfForDealloc); - emitProfilerIncrement(dd->getTypecheckedBody()); - // Return. B.createReturn(loc, emitEmptyTuple(loc)); } diff --git a/test/Profiler/coverage_class.swift b/test/Profiler/coverage_class.swift index 24fc0888d19fc..11cd0b4290b89 100644 --- a/test/Profiler/coverage_class.swift +++ b/test/Profiler/coverage_class.swift @@ -10,7 +10,7 @@ class C { // CHECK-NEXT: [[@LINE+1]]:10 -> [[@LINE+1]]:12 init() {} - // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.__deallocating_deinit + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.deinit // CHECK-NEXT: [[@LINE+1]]:10 -> [[@LINE+1]]:12 deinit {} } diff --git a/test/Profiler/coverage_deinit.swift b/test/Profiler/coverage_deinit.swift new file mode 100644 index 0000000000000..e0816977198c4 --- /dev/null +++ b/test/Profiler/coverage_deinit.swift @@ -0,0 +1,30 @@ +// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -suppress-warnings -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_deinit %s | %FileCheck %s +// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -emit-ir %s + +func foo() {} + +public class Foo { + // CHECK-LABEL: sil @$s15coverage_deinit3FooCfd + // CHECK: integer_literal $Builtin.Int64, 0 + // CHECK: integer_literal $Builtin.Int32, 2 + // CHECK: integer_literal $Builtin.Int32, 0 + // CHECK-NEXT: builtin "int_instrprof_increment" + // CHECK: function_ref @$sSb6randomSbyFZ + // CHECK: cond_br + // CHECK: integer_literal $Builtin.Int64, 0 + // CHECK: integer_literal $Builtin.Int32, 2 + // CHECK: integer_literal $Builtin.Int32, 1 + // CHECK-NEXT: builtin "int_instrprof_increment" + // CHECK-NEXT: // function_ref coverage_deinit.foo() -> () + deinit { + if .random() { + foo() + } + } +} + +// CHECK-LABEL: sil_coverage_map "{{.*}}coverage_deinit.swift" "$s15coverage_deinit3FooCfd" +// CHECK-NEXT: [[@LINE-8]]:10 -> [[@LINE-4]]:4 : 0 +// CHECK-NEXT: [[@LINE-8]]:8 -> [[@LINE-8]]:17 : 0 +// CHECK-NEXT: [[@LINE-9]]:18 -> [[@LINE-7]]:6 : 1 +// CHECK-NEXT: [[@LINE-8]]:6 -> [[@LINE-7]]:4 : 0 From 59db2038906cb93dd403cf45826f01f6591ab022 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Fri, 12 Aug 2022 08:56:12 -0700 Subject: [PATCH 102/491] Update the llvm-project branch for main to stable/20220421 --- utils/update_checkout/update-checkout-config.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/update_checkout/update-checkout-config.json b/utils/update_checkout/update-checkout-config.json index 10cbf471d3d4e..bca4309b21f63 100644 --- a/utils/update_checkout/update-checkout-config.json +++ b/utils/update_checkout/update-checkout-config.json @@ -87,10 +87,10 @@ "default-branch-scheme": "main", "branch-schemes": { "main": { - "aliases": ["swift/main", "main", "stable/20211026"], + "aliases": ["swift/main", "main", "stable/20220421"], "repos": { - "llvm-project": "stable/20211026", - "swift-llvm-bindings": "stable/20211026", + "llvm-project": "stable/20220421", + "swift-llvm-bindings": "stable/20220421", "swift": "main", "cmark": "gfm", "llbuild": "main", @@ -129,7 +129,7 @@ } }, "rebranch": { - "aliases": ["rebranch", "stable/20220421"], + "aliases": ["rebranch"], "repos": { "llvm-project": "stable/20220421", "swift-llvm-bindings": "stable/20220421", From 059f730e17a99c883fef102f0d1c661ad17acee6 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Fri, 12 Aug 2022 18:54:30 +0100 Subject: [PATCH 103/491] [AST] NFC: Pretty stack trace for `Traversal::visitNominalTypeDecl` This helps a bit in getting more readable stack traces when the compiler crashes. --- lib/AST/ASTWalker.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 2900b6a31af31..4f47d45558848 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -284,6 +284,9 @@ class Traversal : public ASTVisitor Date: Sat, 13 Aug 2022 03:52:07 +0300 Subject: [PATCH 104/491] Gardening: Migrate test suite to GH issues: Compatibility --- test/Compatibility/exhaustive_switch.swift | 48 ++++++----- .../implicit_tupling_untupling_codegen.swift | 85 ++++++++++--------- test/Compatibility/self.swift | 4 +- test/Compatibility/special_case_name.swift | 2 +- test/Compatibility/tuple_arguments_4.swift | 4 +- 5 files changed, 73 insertions(+), 70 deletions(-) diff --git a/test/Compatibility/exhaustive_switch.swift b/test/Compatibility/exhaustive_switch.swift index ca51f109f891c..d0d1d7509a238 100644 --- a/test/Compatibility/exhaustive_switch.swift +++ b/test/Compatibility/exhaustive_switch.swift @@ -803,7 +803,8 @@ func checkLiteralTuples() { } } -func sr6975() { +// https://github.com/apple/swift/issues/49523 +do { enum E { case a, b } @@ -1177,42 +1178,43 @@ extension Result where T == NoError { } } -enum SR10301 { - case value(T) - case error(E) -} -enum SR10301Error: Error { - case bad -} +// https://github.com/apple/swift/issues/52701 +do { + enum Enum { + case value(T) + case error(E) + } + enum MyError: Error { + case bad + } + + let foo: Enum -func sr10301(_ foo: SR10301) { switch foo { - case .value: return - case .error((_, SR10301Error.bad)): return + case .value: break + case .error((_, MyError.bad)): break case .error((_, let err)): _ = err - return + break } -} -func sr10301_is(_ foo: SR10301) { + // 'is' switch foo { - case .value: return - case .error((_, is SR10301Error)): return + case .value: break + case .error((_, is MyError)): break case .error((_, let err)): _ = err - return + break } -} -func sr10301_as(_ foo: SR10301) { + // 'as' switch foo { - case .value: return - case .error((_, let err as SR10301Error)): + case .value: break + case .error((_, let err as MyError)): _ = err - return + break case .error((_, let err)): _ = err - return + break } } diff --git a/test/Compatibility/implicit_tupling_untupling_codegen.swift b/test/Compatibility/implicit_tupling_untupling_codegen.swift index 8d039e46ffab6..2af38a4dcb11e 100644 --- a/test/Compatibility/implicit_tupling_untupling_codegen.swift +++ b/test/Compatibility/implicit_tupling_untupling_codegen.swift @@ -2,6 +2,7 @@ // REQUIRES: executable_test +// https://github.com/apple/swift/issues/53611 // Even though we test that type-checking and exhaustiveness checking work fine // in the presence of implicit tupling/untupling in exhaustive_switch.swift, // make sure that the "patched" patterns do not lead to incorrect codegen. @@ -12,46 +13,46 @@ enum Untupled { let u_ex = Untupled.upair(1, 2) -func sr11212_content_untupled_pattern_tupled1(u: Untupled) -> (Int, Int) { +func content_untupled_pattern_tupled1(u: Untupled) -> (Int, Int) { switch u { case .upair((let x, let y)): return (x, y) } } -print(sr11212_content_untupled_pattern_tupled1(u: u_ex)) +print(content_untupled_pattern_tupled1(u: u_ex)) // CHECK: (1, 2) -func sr11212_content_untupled_pattern_tupled2(u: Untupled) -> (Int, Int) { +func content_untupled_pattern_tupled2(u: Untupled) -> (Int, Int) { switch u { case .upair(let (x, y)): return (x, y) } } -print(sr11212_content_untupled_pattern_tupled2(u: u_ex)) +print(content_untupled_pattern_tupled2(u: u_ex)) // CHECK: (1, 2) -func sr11212_content_untupled_pattern_tupled3(u: Untupled) -> (Int, Int) { +func content_untupled_pattern_tupled3(u: Untupled) -> (Int, Int) { switch u { case let .upair((x, y)): return (x, y) } } -print(sr11212_content_untupled_pattern_tupled3(u: u_ex)) +print(content_untupled_pattern_tupled3(u: u_ex)) // CHECK: (1, 2) -func sr11212_content_untupled_pattern_untupled1(u: Untupled) -> (Int, Int) { +func content_untupled_pattern_untupled1(u: Untupled) -> (Int, Int) { switch u { case .upair(let x, let y): return (x, y) } } -print(sr11212_content_untupled_pattern_untupled1(u: u_ex)) +print(content_untupled_pattern_untupled1(u: u_ex)) // CHECK: (1, 2) -func sr11212_content_untupled_pattern_untupled2(u: Untupled) -> (Int, Int) { +func content_untupled_pattern_untupled2(u: Untupled) -> (Int, Int) { switch u { case let .upair(x, y): return (x, y) } } -print(sr11212_content_untupled_pattern_untupled2(u: u_ex)) +print(content_untupled_pattern_untupled2(u: u_ex)) // CHECK: (1, 2) -func sr11212_content_untupled_pattern_ambiguous1(u: Untupled) -> (Int, Int) { +func content_untupled_pattern_ambiguous1(u: Untupled) -> (Int, Int) { switch u { case .upair(let u_): return u_ } } -print(sr11212_content_untupled_pattern_ambiguous1(u: u_ex)) +print(content_untupled_pattern_ambiguous1(u: u_ex)) // CHECK: (1, 2) -func sr11212_content_untupled_pattern_ambiguous2(u: Untupled) -> (Int, Int) { +func content_untupled_pattern_ambiguous2(u: Untupled) -> (Int, Int) { switch u { case let .upair(u_): return u_ } } -print(sr11212_content_untupled_pattern_ambiguous2(u: u_ex)) +print(content_untupled_pattern_ambiguous2(u: u_ex)) // CHECK: (1, 2) enum Tupled { @@ -60,46 +61,46 @@ enum Tupled { let t_ex = Tupled.tpair((1, 2)) -func sr11212_content_tupled_pattern_tupled1(t: Tupled) -> (Int, Int) { +func content_tupled_pattern_tupled1(t: Tupled) -> (Int, Int) { switch t { case .tpair((let x, let y)): return (x, y) } } -print(sr11212_content_tupled_pattern_tupled1(t: t_ex)) +print(content_tupled_pattern_tupled1(t: t_ex)) // CHECK: (1, 2) -func sr11212_content_tupled_pattern_tupled2(t: Tupled) -> (Int, Int) { +func content_tupled_pattern_tupled2(t: Tupled) -> (Int, Int) { switch t { case .tpair(let (x, y)): return (x, y) } } -print(sr11212_content_tupled_pattern_tupled2(t: t_ex)) +print(content_tupled_pattern_tupled2(t: t_ex)) // CHECK: (1, 2) -func sr11212_content_tupled_pattern_tupled3(t: Tupled) -> (Int, Int) { +func content_tupled_pattern_tupled3(t: Tupled) -> (Int, Int) { switch t { case let .tpair((x, y)): return (x, y) } } -print(sr11212_content_tupled_pattern_tupled3(t: t_ex)) +print(content_tupled_pattern_tupled3(t: t_ex)) // CHECK: (1, 2) -func sr11212_content_tupled_pattern_untupled1(t: Tupled) -> (Int, Int) { +func content_tupled_pattern_untupled1(t: Tupled) -> (Int, Int) { switch t { case .tpair(let x, let y): return (x, y) } } -print(sr11212_content_tupled_pattern_untupled1(t: t_ex)) +print(content_tupled_pattern_untupled1(t: t_ex)) // CHECK: (1, 2) -func sr11212_content_tupled_pattern_untupled2(t: Tupled) -> (Int, Int) { +func content_tupled_pattern_untupled2(t: Tupled) -> (Int, Int) { switch t { case let .tpair(x, y): return (x, y) } } -print(sr11212_content_tupled_pattern_untupled2(t: t_ex)) +print(content_tupled_pattern_untupled2(t: t_ex)) // CHECK: (1, 2) -func sr11212_content_tupled_pattern_ambiguous1(t: Tupled) -> (Int, Int) { +func content_tupled_pattern_ambiguous1(t: Tupled) -> (Int, Int) { switch t { case .tpair(let t_): return t_ } } -print(sr11212_content_tupled_pattern_ambiguous1(t: t_ex)) +print(content_tupled_pattern_ambiguous1(t: t_ex)) // CHECK: (1, 2) -func sr11212_content_tupled_pattern_ambiguous2(t: Tupled) -> (Int, Int) { +func content_tupled_pattern_ambiguous2(t: Tupled) -> (Int, Int) { switch t { case let .tpair(t_): return t_ } } -print(sr11212_content_tupled_pattern_ambiguous2(t: t_ex)) +print(content_tupled_pattern_ambiguous2(t: t_ex)) // CHECK: (1, 2) enum Box { @@ -108,44 +109,44 @@ enum Box { let b_ex : Box<(Int, Int)> = Box.box((1, 2)) -func sr11212_content_generic_pattern_tupled1(b: Box<(Int, Int)>) -> (Int, Int) { +func content_generic_pattern_tupled1(b: Box<(Int, Int)>) -> (Int, Int) { switch b { case .box((let x, let y)): return (x, y) } } -print(sr11212_content_generic_pattern_tupled1(b: b_ex)) +print(content_generic_pattern_tupled1(b: b_ex)) // CHECK: (1, 2) -func sr11212_content_generic_pattern_tupled2(b: Box<(Int, Int)>) -> (Int, Int) { +func content_generic_pattern_tupled2(b: Box<(Int, Int)>) -> (Int, Int) { switch b { case .box(let (x, y)): return (x, y) } } -print(sr11212_content_generic_pattern_tupled2(b: b_ex)) +print(content_generic_pattern_tupled2(b: b_ex)) // CHECK: (1, 2) -func sr11212_content_generic_pattern_tupled3(b: Box<(Int, Int)>) -> (Int, Int) { +func content_generic_pattern_tupled3(b: Box<(Int, Int)>) -> (Int, Int) { switch b { case let .box((x, y)): return (x, y) } } -print(sr11212_content_generic_pattern_tupled3(b: b_ex)) +print(content_generic_pattern_tupled3(b: b_ex)) // CHECK: (1, 2) -func sr11212_content_generic_pattern_untupled1(b: Box<(Int, Int)>) -> (Int, Int) { +func content_generic_pattern_untupled1(b: Box<(Int, Int)>) -> (Int, Int) { switch b { case .box(let x, let y): return (x, y) } } -print(sr11212_content_generic_pattern_untupled1(b: b_ex)) +print(content_generic_pattern_untupled1(b: b_ex)) // CHECK: (1, 2) -func sr11212_content_generic_pattern_untupled2(b: Box<(Int, Int)>) -> (Int, Int) { +func content_generic_pattern_untupled2(b: Box<(Int, Int)>) -> (Int, Int) { switch b { case let .box(x, y): return (x, y) } } -print(sr11212_content_generic_pattern_untupled2(b: b_ex)) +print(content_generic_pattern_untupled2(b: b_ex)) // CHECK: (1, 2) -func sr11212_content_generic_pattern_ambiguous1(b: Box<(Int, Int)>) -> (Int, Int) { +func content_generic_pattern_ambiguous1(b: Box<(Int, Int)>) -> (Int, Int) { switch b { case .box(let b_): return b_ } } -print(sr11212_content_generic_pattern_ambiguous1(b: b_ex)) +print(content_generic_pattern_ambiguous1(b: b_ex)) // CHECK: (1, 2) -func sr11212_content_generic_pattern_ambiguous2(b: Box<(Int, Int)>) -> (Int, Int) { +func content_generic_pattern_ambiguous2(b: Box<(Int, Int)>) -> (Int, Int) { switch b { case let .box(b_): return b_ } } -print(sr11212_content_generic_pattern_ambiguous2(b: b_ex)) +print(content_generic_pattern_ambiguous2(b: b_ex)) // CHECK: (1, 2) diff --git a/test/Compatibility/self.swift b/test/Compatibility/self.swift index e1417e5c9f3ee..dc86a187ed3c1 100644 --- a/test/Compatibility/self.swift +++ b/test/Compatibility/self.swift @@ -1,7 +1,7 @@ // RUN: %target-typecheck-verify-swift -swift-version 4 -// SR-695 -// in version 4 and earlier all of these should build with no diagnostic +// https://github.com/apple/swift/issues/43310 +// In version 4 and earlier all of these should build with no diagnostic. class Mario { func getFriend() -> Self { return self } func getEnemy() -> Mario { return self } diff --git a/test/Compatibility/special_case_name.swift b/test/Compatibility/special_case_name.swift index 5c6b8522532d7..7518b804a9e5f 100644 --- a/test/Compatibility/special_case_name.swift +++ b/test/Compatibility/special_case_name.swift @@ -1,6 +1,6 @@ // RUN: %target-typecheck-verify-swift -swift-version 4 -// https://bugs.swift.org/browse/SR-1660 +// https://github.com/apple/swift/issues/44269 enum DayOfTheWeek : Int { case monday = 0 diff --git a/test/Compatibility/tuple_arguments_4.swift b/test/Compatibility/tuple_arguments_4.swift index 6dddcf4cb5310..25b3176bad45b 100644 --- a/test/Compatibility/tuple_arguments_4.swift +++ b/test/Compatibility/tuple_arguments_4.swift @@ -1,6 +1,6 @@ // RUN: %target-typecheck-verify-swift -swift-version 4 -// https://bugs.swift.org/browse/SR-6837 +// https://github.com/apple/swift/issues/49386 // FIXME: Can't overload local functions so these must be top-level func takePairOverload(_ pair: (Int, Int?)) {} @@ -18,7 +18,7 @@ do { // expected-error@-1 {{contextual closure type '(Int, Int?) -> ()' expects 2 arguments, but 1 was used in closure body}} } -// https://bugs.swift.org/browse/SR-6796 +// https://github.com/apple/swift/issues/49345 do { func f(a: (() -> Void)? = nil) {} func log() -> ((T) -> Void)? { return nil } From 2b6d7ea5f65524f30085720358f4fedf132a98bf Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Sat, 13 Aug 2022 03:55:01 +0300 Subject: [PATCH 105/491] Gardening: Migrate test suite to GH issues: Concurrency --- test/Concurrency/Runtime/executor_deinit1.swift | 2 +- test/Concurrency/objc_async_overload.swift | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/Concurrency/Runtime/executor_deinit1.swift b/test/Concurrency/Runtime/executor_deinit1.swift index 904defa6bbea8..b77bb04799fa4 100644 --- a/test/Concurrency/Runtime/executor_deinit1.swift +++ b/test/Concurrency/Runtime/executor_deinit1.swift @@ -6,7 +6,7 @@ // REQUIRES: concurrency_runtime // UNSUPPORTED: back_deployment_runtime -// https://bugs.swift.org/browse/SR-14461 +// https://github.com/apple/swift/issues/56817 // UNSUPPORTED: OS=linux-gnu // REQUIRES: rdar78325660 diff --git a/test/Concurrency/objc_async_overload.swift b/test/Concurrency/objc_async_overload.swift index c254b02b53578..6f735452c148b 100644 --- a/test/Concurrency/objc_async_overload.swift +++ b/test/Concurrency/objc_async_overload.swift @@ -7,7 +7,11 @@ func syncContext() { let r = Request() let d = Delegate() - d.makeRequest1(r) // NOTE: this use to trigger an overload resolution error, see SR-13760 + + // https://github.com/apple/swift/issues/56157 + // This use to trigger an overload resolution error. + d.makeRequest1(r) + d.makeRequest2(r) d.makeRequest3(r) } From 87eb2cac31997674236550e923cd5ced5629b2ec Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 11 Aug 2022 21:05:37 -0400 Subject: [PATCH 106/491] AST: Don't strip bound dependent member types when forming keys in a generic environment --- lib/AST/GenericEnvironment.cpp | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp index 18330a77321b8..269a76b8629cc 100644 --- a/lib/AST/GenericEnvironment.cpp +++ b/lib/AST/GenericEnvironment.cpp @@ -273,15 +273,6 @@ auto GenericEnvironment::getOrCreateNestedTypeStorage() -> NestedTypeStorage & { return *nestedTypeStorage; } -static Type stripBoundDependentMemberTypes(Type t) { - if (auto *depMemTy = t->getAs()) { - return DependentMemberType::get( - stripBoundDependentMemberTypes(depMemTy->getBase()), - depMemTy->getName()); - } - - return t; -} Type GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) { auto genericSig = getGenericSignature(); @@ -315,12 +306,11 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) { // First, write an ErrorType to the location where this type is cached, // to catch re-entrant lookups that might arise from an invalid generic // signature (eg, >). - CanDependentMemberType nestedDependentMemberType; + CanDependentMemberType nestedType; GenericTypeParamType *genericParam = nullptr; if (auto depMemTy = requirements.anchor->getAs()) { - nestedDependentMemberType = cast( - stripBoundDependentMemberTypes(depMemTy)->getCanonicalType()); - auto &entry = getOrCreateNestedTypeStorage()[nestedDependentMemberType]; + nestedType = cast(depMemTy->getCanonicalType()); + auto &entry = getOrCreateNestedTypeStorage()[nestedType]; if (entry) return entry; @@ -342,7 +332,9 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) { Type result; - if (requirements.anchor->getRootGenericParam()->isTypeSequence()) { + auto rootGP = requirements.anchor->getRootGenericParam(); + if (rootGP->isTypeSequence()) { + assert(getKind() == Kind::Normal); result = SequenceArchetypeType::get(ctx, this, requirements.anchor, requirements.protos, superclass, requirements.layout); @@ -384,7 +376,6 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) { // If the anchor type isn't rooted in a generic parameter that // represents an opaque declaration, then apply the outer substitutions. // It would be incorrect to build an opaque type archetype here. - auto rootGP = requirements.anchor->getRootGenericParam(); unsigned opaqueDepth = getOpaqueTypeDecl()->getOpaqueGenericParams().front()->getDepth(); if (rootGP->getDepth() < opaqueDepth) { @@ -403,7 +394,7 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) { if (genericParam) addMapping(genericParam, result); else - getOrCreateNestedTypeStorage()[nestedDependentMemberType] = result; + getOrCreateNestedTypeStorage()[nestedType] = result; return result; } From 7a970367fddbd27bbb1282f2f0f6a0e248e41b69 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 11 Aug 2022 21:11:42 -0400 Subject: [PATCH 107/491] AST: Rename GenericEnvironment::Kind::Normal to ::Primary, ::getIncomplete() to ::forPrimary() --- include/swift/AST/GenericEnvironment.h | 10 ++++------ lib/AST/ASTContext.cpp | 3 +-- lib/AST/GenericEnvironment.cpp | 16 ++++++++-------- lib/AST/GenericSignature.cpp | 2 +- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h index bf4c33193e578..6afb751b9409f 100644 --- a/include/swift/AST/GenericEnvironment.h +++ b/include/swift/AST/GenericEnvironment.h @@ -73,7 +73,7 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final enum class Kind { /// A normal generic environment, determined only by its generic /// signature. - Normal, + Primary, /// A generic environment describing an opened existential archetype. OpenedExistential, /// A generic environment describing an opaque type archetype. @@ -84,7 +84,7 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final private: mutable llvm::PointerIntPair SignatureAndKind{ - GenericSignature(), Kind::Normal}; + GenericSignature(), Kind::Primary}; NestedTypeStorage *nestedTypeStorage = nullptr; friend TrailingObjects; @@ -151,10 +151,8 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final /// create a generic environment. SubstitutionMap getOpaqueSubstitutions() const; - /// Create a new, "incomplete" generic environment that will be populated - /// by calls to \c addMapping(). - static - GenericEnvironment *getIncomplete(GenericSignature signature); + /// Create a new, primary generic environment. + static GenericEnvironment *forPrimary(GenericSignature signature); /// Create a new generic environment for an opened existential. /// diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 117e0d696779b..5b4df191a6dec 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4637,8 +4637,7 @@ GenericSignature::get(TypeArrayView params, return newSig; } -GenericEnvironment *GenericEnvironment::getIncomplete( - GenericSignature signature) { +GenericEnvironment *GenericEnvironment::forPrimary(GenericSignature signature) { auto &ctx = signature->getASTContext(); // Allocate and construct the new environment. diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp index 269a76b8629cc..560669fb08c0d 100644 --- a/lib/AST/GenericEnvironment.cpp +++ b/lib/AST/GenericEnvironment.cpp @@ -26,7 +26,7 @@ using namespace swift; size_t GenericEnvironment::numTrailingObjects( OverloadToken) const { switch (getKind()) { - case Kind::Normal: + case Kind::Primary: case Kind::OpenedExistential: return 0; @@ -38,7 +38,7 @@ size_t GenericEnvironment::numTrailingObjects( size_t GenericEnvironment::numTrailingObjects( OverloadToken) const { switch (getKind()) { - case Kind::Normal: + case Kind::Primary: case Kind::OpenedExistential: return 0; @@ -50,7 +50,7 @@ size_t GenericEnvironment::numTrailingObjects( size_t GenericEnvironment::numTrailingObjects( OverloadToken) const { switch (getKind()) { - case Kind::Normal: + case Kind::Primary: case Kind::Opaque: return 0; @@ -105,7 +105,7 @@ UUID GenericEnvironment::getOpenedExistentialUUID() const { } GenericEnvironment::GenericEnvironment(GenericSignature signature) - : SignatureAndKind(signature, Kind::Normal) + : SignatureAndKind(signature, Kind::Primary) { // Clear out the memory that holds the context types. std::uninitialized_fill(getContextTypes().begin(), getContextTypes().end(), @@ -209,7 +209,7 @@ struct SubstituteOuterFromSubstitutionMap { Type GenericEnvironment::maybeApplyOpaqueTypeSubstitutions(Type type) const { switch (getKind()) { - case Kind::Normal: + case Kind::Primary: case Kind::OpenedExistential: return type; @@ -283,7 +283,7 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) { /// Substitute a type for the purpose of requirements. auto substForRequirements = [&](Type type) { switch (getKind()) { - case Kind::Normal: + case Kind::Primary: case Kind::OpenedExistential: if (type->hasTypeParameter()) { return mapTypeIntoContext(type, conformanceLookupFn); @@ -334,13 +334,13 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) { auto rootGP = requirements.anchor->getRootGenericParam(); if (rootGP->isTypeSequence()) { - assert(getKind() == Kind::Normal); + assert(getKind() == Kind::Primary); result = SequenceArchetypeType::get(ctx, this, requirements.anchor, requirements.protos, superclass, requirements.layout); } else { switch (getKind()) { - case Kind::Normal: + case Kind::Primary: result = PrimaryArchetypeType::getNew(ctx, this, requirements.anchor, requirements.protos, superclass, requirements.layout); diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 72debb632aeb4..28f247f0539f6 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -267,7 +267,7 @@ GenericEnvironment *GenericSignature::getGenericEnvironment() const { GenericEnvironment *GenericSignatureImpl::getGenericEnvironment() const { if (GenericEnv == nullptr) { const auto impl = const_cast(this); - impl->GenericEnv = GenericEnvironment::getIncomplete(this); + impl->GenericEnv = GenericEnvironment::forPrimary(this); } return GenericEnv; From b36f37cc72fc44f13231d0533f285facdb6f1249 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 11 Aug 2022 23:44:18 -0400 Subject: [PATCH 108/491] Serialization: Preserve identity of opened generic environments We used to create a new environment for each opened archetype, which is incorrect when deserializing a nested type of another opened archetype. --- include/swift/AST/GenericEnvironment.h | 24 ++----- lib/AST/ASTContext.cpp | 7 +- lib/AST/GenericEnvironment.cpp | 11 ++- lib/Serialization/DeclTypeRecordNodes.def | 2 +- lib/Serialization/Deserialization.cpp | 70 +++++++++++++++---- lib/Serialization/ModuleFile.cpp | 1 + lib/Serialization/ModuleFile.h | 7 ++ lib/Serialization/ModuleFileSharedCore.cpp | 4 ++ lib/Serialization/ModuleFileSharedCore.h | 3 + lib/Serialization/ModuleFormat.h | 17 +++-- lib/Serialization/Serialization.cpp | 34 +++++++-- lib/Serialization/Serialization.h | 10 +++ .../nested_opened_archetype_other.swift | 11 +++ .../nested_opened_archetype.swift | 15 ++++ 14 files changed, 165 insertions(+), 51 deletions(-) create mode 100644 test/Serialization/Inputs/nested_opened_archetype_other.swift create mode 100644 test/Serialization/nested_opened_archetype.swift diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h index 6afb751b9409f..d548b04eed9e3 100644 --- a/include/swift/AST/GenericEnvironment.h +++ b/include/swift/AST/GenericEnvironment.h @@ -54,6 +54,7 @@ class QueryInterfaceTypeSubstitutions { /// Extra data in a generic environment for an opened existential. struct OpenedGenericEnvironmentData { Type existential; + GenericSignature parentSig; UUID uuid; }; @@ -110,7 +111,8 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final explicit GenericEnvironment(GenericSignature signature); explicit GenericEnvironment( - GenericSignature signature, Type existential, UUID uuid); + GenericSignature signature, + Type existential, GenericSignature parentSig, UUID uuid); explicit GenericEnvironment( GenericSignature signature, OpaqueTypeDecl *opaque, SubstitutionMap subs); @@ -143,6 +145,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final /// Retrieve the UUID for an opened existential environment. UUID getOpenedExistentialUUID() const; + /// Retrieve the parent signature for an opened existential environment. + GenericSignature getOpenedExistentialParentSignature() const; + /// Retrieve the opaque type declaration for a generic environment describing /// opaque types. OpaqueTypeDecl *getOpaqueTypeDecl() const; @@ -156,29 +161,12 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final /// Create a new generic environment for an opened existential. /// - /// This function uses the provided parent signature to construct a new - /// signature suitable for use with an opened archetype. If you have an - /// existing generic signature from e.g. deserialization use - /// \c GenericEnvironment::forOpenedArchetypeSignature instead. - /// /// \param existential The subject existential type /// \param parentSig The signature of the context where this existential type is being opened /// \param uuid The unique identifier for this opened existential static GenericEnvironment * forOpenedExistential(Type existential, GenericSignature parentSig, UUID uuid); - /// Create a new generic environment for an opened existential. - /// - /// It is unlikely you want to use this function. - /// Call \c GenericEnvironment::forOpenedExistential instead. - /// - /// \param existential The subject existential type - /// \param signature The signature of the opened archetype - /// \param uuid The unique identifier for this opened existential - static GenericEnvironment * - forOpenedArchetypeSignature(Type existential, - GenericSignature signature, UUID uuid); - /// Create a new generic environment for an opaque type with the given set of /// outer substitutions. static GenericEnvironment *forOpaqueType( diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 5b4df191a6dec..ff439ef5633e9 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4655,19 +4655,14 @@ GenericEnvironment::forOpenedExistential( Type existential, GenericSignature parentSig, UUID uuid) { auto &ctx = existential->getASTContext(); auto signature = ctx.getOpenedExistentialSignature(existential, parentSig); - return GenericEnvironment::forOpenedArchetypeSignature(existential, signature, uuid); -} -GenericEnvironment *GenericEnvironment::forOpenedArchetypeSignature( - Type existential, GenericSignature signature, UUID uuid) { // Allocate and construct the new environment. - auto &ctx = existential->getASTContext(); unsigned numGenericParams = signature.getGenericParams().size(); size_t bytes = totalSizeToAlloc( 0, 0, 1, numGenericParams); void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment)); - return new (mem) GenericEnvironment(signature, existential, uuid); + return new (mem) GenericEnvironment(signature, existential, parentSig, uuid); } /// Create a new generic environment for an opaque type with the given set of diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp index 560669fb08c0d..4edb06ba06271 100644 --- a/lib/AST/GenericEnvironment.cpp +++ b/lib/AST/GenericEnvironment.cpp @@ -104,6 +104,12 @@ UUID GenericEnvironment::getOpenedExistentialUUID() const { return getTrailingObjects()->uuid; } +GenericSignature +GenericEnvironment::getOpenedExistentialParentSignature() const { + assert(getKind() == Kind::OpenedExistential); + return getTrailingObjects()->parentSig; +} + GenericEnvironment::GenericEnvironment(GenericSignature signature) : SignatureAndKind(signature, Kind::Primary) { @@ -113,11 +119,12 @@ GenericEnvironment::GenericEnvironment(GenericSignature signature) } GenericEnvironment::GenericEnvironment( - GenericSignature signature, Type existential, UUID uuid) + GenericSignature signature, + Type existential, GenericSignature parentSig, UUID uuid) : SignatureAndKind(signature, Kind::OpenedExistential) { new (getTrailingObjects()) - OpenedGenericEnvironmentData{ existential, uuid }; + OpenedGenericEnvironmentData{ existential, parentSig, uuid }; // Clear out the memory that holds the context types. std::uninitialized_fill(getContextTypes().begin(), getContextTypes().end(), diff --git a/lib/Serialization/DeclTypeRecordNodes.def b/lib/Serialization/DeclTypeRecordNodes.def index 5cb7c43ef53ee..3ee4b07b526af 100644 --- a/lib/Serialization/DeclTypeRecordNodes.def +++ b/lib/Serialization/DeclTypeRecordNodes.def @@ -167,7 +167,7 @@ OTHER(TOP_LEVEL_CODE_DECL_CONTEXT, 112) OTHER(GENERIC_PARAM_LIST, 120) OTHER(GENERIC_SIGNATURE, 121) OTHER(REQUIREMENT_SIGNATURE, 122) -// 123 is unused; was LAYOUT_REQUIREMENT +OTHER(GENERIC_ENVIRONMENT, 123) OTHER(BUILTIN_PROTOCOL_CONFORMANCE, 124) OTHER(SIL_GENERIC_SIGNATURE, 125) OTHER(SUBSTITUTION_MAP, 126) diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index ec5c414a9fbf5..3e3fcb77aa00a 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1188,6 +1188,53 @@ ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) { return signature; } +Expected +ModuleFile::getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID) { + using namespace decls_block; + + assert(ID <= GenericEnvironments.size() && + "invalid GenericEnvironment ID"); + auto &envOffset = GenericEnvironments[ID-1]; + + // If we've already deserialized this generic environment, return it. + if (envOffset.isComplete()) + return envOffset.get(); + + // Read the generic environment. + BCOffsetRAII restoreOffset(DeclTypeCursor); + fatalIfNotSuccess(DeclTypeCursor.JumpToBit(envOffset)); + + llvm::BitstreamEntry entry = + fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd)); + if (entry.Kind != llvm::BitstreamEntry::Record) + fatal(); + + StringRef blobData; + SmallVector scratch; + unsigned recordID = fatalIfUnexpected( + DeclTypeCursor.readRecord(entry.ID, scratch, &blobData)); + if (recordID != GENERIC_ENVIRONMENT) + fatal(); + + GenericSignatureID parentSigID; + TypeID existentialID; + GenericEnvironmentLayout::readRecord(scratch, existentialID, parentSigID); + + auto existentialTypeOrError = getTypeChecked(existentialID); + if (!existentialTypeOrError) + return existentialTypeOrError.takeError(); + + auto parentSigOrError = getGenericSignatureChecked(parentSigID); + if (!parentSigOrError) + return parentSigOrError.takeError(); + + auto *genericEnv = GenericEnvironment::forOpenedExistential( + existentialTypeOrError.get(), parentSigOrError.get(), UUID::fromTime()); + envOffset = genericEnv; + + return genericEnv; +} + SubstitutionMap ModuleFile::getSubstitutionMap( serialization::SubstitutionMapID id) { auto map = getSubstitutionMapChecked(id); @@ -5747,29 +5794,22 @@ Expected DESERIALIZE_TYPE(PRIMARY_ARCHETYPE_TYPE)( Expected DESERIALIZE_TYPE(OPENED_ARCHETYPE_TYPE)( ModuleFile &MF, SmallVectorImpl &scratch, StringRef blobData) { - TypeID existentialID; TypeID interfaceID; - GenericSignatureID sigID; + GenericEnvironmentID genericEnvID; - decls_block::OpenedArchetypeTypeLayout::readRecord(scratch, existentialID, - interfaceID, sigID); - - auto sigOrError = MF.getGenericSignatureChecked(sigID); - if (!sigOrError) - return sigOrError.takeError(); + decls_block::OpenedArchetypeTypeLayout::readRecord(scratch, + interfaceID, + genericEnvID); auto interfaceTypeOrError = MF.getTypeChecked(interfaceID); if (!interfaceTypeOrError) return interfaceTypeOrError.takeError(); - auto existentialTypeOrError = MF.getTypeChecked(existentialID); - if (!existentialTypeOrError) - return existentialTypeOrError.takeError(); + auto envOrError = MF.getGenericEnvironmentChecked(genericEnvID); + if (!envOrError) + return envOrError.takeError(); - auto env = GenericEnvironment::forOpenedArchetypeSignature( - existentialTypeOrError.get(), sigOrError.get(), UUID::fromTime()); - return env->mapTypeIntoContext(interfaceTypeOrError.get()) - ->castTo(); + return envOrError.get()->mapTypeIntoContext(interfaceTypeOrError.get()); } Expected DESERIALIZE_TYPE(OPAQUE_ARCHETYPE_TYPE)( diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 642fe6a2a21d0..7135e3bcfa80c 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -113,6 +113,7 @@ ModuleFile::ModuleFile(std::shared_ptr core) allocateBuffer(Types, core->Types); allocateBuffer(ClangTypes, core->ClangTypes); allocateBuffer(GenericSignatures, core->GenericSignatures); + allocateBuffer(GenericEnvironments, core->GenericEnvironments); allocateBuffer(SubstitutionMaps, core->SubstitutionMaps); allocateBuffer(Identifiers, core->Identifiers); } diff --git a/lib/Serialization/ModuleFile.h b/lib/Serialization/ModuleFile.h index 89911ee38c1f8..4b27ba9a38b6d 100644 --- a/lib/Serialization/ModuleFile.h +++ b/lib/Serialization/ModuleFile.h @@ -259,6 +259,9 @@ class ModuleFile /// Generic signatures referenced by this module. MutableArrayRef> GenericSignatures; + /// Generic environments referenced by this module. + MutableArrayRef> GenericEnvironments; + /// Substitution maps referenced by this module. MutableArrayRef> SubstitutionMaps; @@ -862,6 +865,10 @@ class ModuleFile llvm::Expected getGenericSignatureChecked(serialization::GenericSignatureID ID); + /// Returns the generic environment for the given ID or the first error. + llvm::Expected + getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID); + /// Returns the substitution map for the given ID, deserializing it if /// needed. SubstitutionMap getSubstitutionMap(serialization::SubstitutionMapID id); diff --git a/lib/Serialization/ModuleFileSharedCore.cpp b/lib/Serialization/ModuleFileSharedCore.cpp index 87ab1da6506ac..3020d91d3179e 100644 --- a/lib/Serialization/ModuleFileSharedCore.cpp +++ b/lib/Serialization/ModuleFileSharedCore.cpp @@ -839,6 +839,10 @@ bool ModuleFileSharedCore::readIndexBlock(llvm::BitstreamCursor &cursor) { assert(blobData.empty()); allocateBuffer(GenericSignatures, scratch); break; + case index_block::GENERIC_ENVIRONMENT_OFFSETS: + assert(blobData.empty()); + allocateBuffer(GenericEnvironments, scratch); + break; case index_block::SUBSTITUTION_MAP_OFFSETS: assert(blobData.empty()); allocateBuffer(SubstitutionMaps, scratch); diff --git a/lib/Serialization/ModuleFileSharedCore.h b/lib/Serialization/ModuleFileSharedCore.h index 8aa43c905fe34..e2c8de16c459c 100644 --- a/lib/Serialization/ModuleFileSharedCore.h +++ b/lib/Serialization/ModuleFileSharedCore.h @@ -218,6 +218,9 @@ class ModuleFileSharedCore { /// Generic signatures referenced by this module. ArrayRef GenericSignatures; + /// Generic environments referenced by this module. + ArrayRef GenericEnvironments; + /// Substitution maps referenced by this module. ArrayRef SubstitutionMaps; diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index f9874d58c2ecf..b65ee1c3f15cc 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 700; // explicit_copy_addr +const uint16_t SWIFTMODULE_VERSION_MINOR = 701; // opened archetype serialization /// A standard hash seed used for all string hashes in a serialized module. /// @@ -145,6 +145,9 @@ using ProtocolConformanceIDField = DeclIDField; using GenericSignatureID = DeclID; using GenericSignatureIDField = DeclIDField; +using GenericEnvironmentID = unsigned; +using GenericEnvironmentIDField = BCFixed<32>; + // SubstitutionMapID must be the same as DeclID because it is stored in the // same way. using SubstitutionMapID = DeclID; @@ -1122,9 +1125,8 @@ namespace decls_block { TYPE_LAYOUT(OpenedArchetypeTypeLayout, OPENED_ARCHETYPE_TYPE, - TypeIDField, // the existential type - TypeIDField, // the interface type - GenericSignatureIDField // generic signature + TypeIDField, // the interface type + GenericEnvironmentIDField // generic environment ID ); TYPE_LAYOUT(OpaqueArchetypeTypeLayout, @@ -1691,6 +1693,12 @@ namespace decls_block { BCArray // generic parameter types >; + using GenericEnvironmentLayout = BCRecordLayout< + GENERIC_ENVIRONMENT, + TypeIDField, // existential type + GenericSignatureIDField // parent signature + >; + using SubstitutionMapLayout = BCRecordLayout< SUBSTITUTION_MAP, GenericSignatureIDField, // generic signature @@ -2178,6 +2186,7 @@ namespace index_block { LOCAL_TYPE_DECLS, OPAQUE_RETURN_TYPE_DECLS, GENERIC_SIGNATURE_OFFSETS, + GENERIC_ENVIRONMENT_OFFSETS, PROTOCOL_CONFORMANCE_OFFSETS, SIL_LAYOUT_OFFSETS, diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index d13a536b52348..56e5c8c760c6a 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -594,6 +594,13 @@ Serializer::addGenericSignatureRef(GenericSignature sig) { return GenericSignaturesToSerialize.addRef(sig); } +GenericEnvironmentID +Serializer::addGenericEnvironmentRef(GenericEnvironment *env) { + if (!env) + return 0; + return GenericEnvironmentsToSerialize.addRef(env); +} + SubstitutionMapID Serializer::addSubstitutionMapRef(SubstitutionMap substitutions) { return SubstitutionMapsToSerialize.addRef(substitutions); @@ -878,6 +885,7 @@ void Serializer::writeBlockInfoBlock() { BLOCK_RECORD(index_block, ENTRY_POINT); BLOCK_RECORD(index_block, LOCAL_DECL_CONTEXT_OFFSETS); BLOCK_RECORD(index_block, GENERIC_SIGNATURE_OFFSETS); + BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS); BLOCK_RECORD(index_block, SUBSTITUTION_MAP_OFFSETS); BLOCK_RECORD(index_block, CLANG_TYPE_OFFSETS); BLOCK_RECORD(index_block, LOCAL_TYPE_DECLS); @@ -1490,6 +1498,20 @@ void Serializer::writeASTBlockEntity(GenericSignature sig) { } } +void Serializer::writeASTBlockEntity(const GenericEnvironment *genericEnv) { + using namespace decls_block; + + assert(GenericEnvironmentsToSerialize.hasRef(genericEnv)); + + auto existentialTypeID = addTypeRef(genericEnv->getOpenedExistentialType()); + auto parentSig = genericEnv->getOpenedExistentialParentSignature(); + auto parentSigID = addGenericSignatureRef(parentSig); + + auto genericEnvAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code]; + GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, genericEnvAbbrCode, + existentialTypeID, parentSigID); +} + void Serializer::writeASTBlockEntity(const SubstitutionMap substitutions) { using namespace decls_block; assert(substitutions); @@ -4603,14 +4625,12 @@ class Serializer::TypeSerializer : public TypeVisitor { void visitOpenedArchetypeType(const OpenedArchetypeType *archetypeTy) { using namespace decls_block; - auto sig = archetypeTy->getGenericEnvironment()->getGenericSignature(); - auto existentialTypeID = S.addTypeRef(archetypeTy->getExistentialType()); auto interfaceTypeID = S.addTypeRef(archetypeTy->getInterfaceType()); - auto sigID = S.addGenericSignatureRef(sig); + auto genericEnvID = S.addGenericEnvironmentRef( + archetypeTy->getGenericEnvironment()); unsigned abbrCode = S.DeclTypeAbbrCodes[OpenedArchetypeTypeLayout::Code]; OpenedArchetypeTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - existentialTypeID, interfaceTypeID, - sigID); + interfaceTypeID, genericEnvID); } void @@ -5107,6 +5127,7 @@ void Serializer::writeAllDeclsAndTypes() { registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); + registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); @@ -5161,6 +5182,8 @@ void Serializer::writeAllDeclsAndTypes() { writeASTBlockEntitiesIfNeeded(LocalDeclContextsToSerialize); wroteSomething |= writeASTBlockEntitiesIfNeeded(GenericSignaturesToSerialize); + wroteSomething |= + writeASTBlockEntitiesIfNeeded(GenericEnvironmentsToSerialize); wroteSomething |= writeASTBlockEntitiesIfNeeded(SubstitutionMapsToSerialize); wroteSomething |= @@ -5764,6 +5787,7 @@ void Serializer::writeAST(ModuleOrSourceFile DC) { writeOffsets(Offsets, ClangTypesToSerialize); writeOffsets(Offsets, LocalDeclContextsToSerialize); writeOffsets(Offsets, GenericSignaturesToSerialize); + writeOffsets(Offsets, GenericEnvironmentsToSerialize); writeOffsets(Offsets, SubstitutionMapsToSerialize); writeOffsets(Offsets, ConformancesToSerialize); writeOffsets(Offsets, SILLayoutsToSerialize); diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index 90b9469dada71..6c3632e827e65 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -219,6 +219,10 @@ class Serializer : public SerializerBase { index_block::GENERIC_SIGNATURE_OFFSETS> GenericSignaturesToSerialize; + ASTBlockRecordKeeper + GenericEnvironmentsToSerialize; + ASTBlockRecordKeeper SubstitutionMapsToSerialize; @@ -353,6 +357,9 @@ class Serializer : public SerializerBase { /// Writes a generic signature. void writeASTBlockEntity(GenericSignature sig); + /// Writes a generic environment. + void writeASTBlockEntity(const GenericEnvironment *env); + /// Writes a substitution map. void writeASTBlockEntity(const SubstitutionMap substitutions); @@ -483,6 +490,9 @@ class Serializer : public SerializerBase { /// The GenericSignature will be scheduled for serialization if necessary. GenericSignatureID addGenericSignatureRef(GenericSignature sig); + /// Records the use of the given opened generic environment. + GenericEnvironmentID addGenericEnvironmentRef(GenericEnvironment *env); + /// Records the use of the given substitution map. /// /// The SubstitutionMap will be scheduled for serialization if necessary. diff --git a/test/Serialization/Inputs/nested_opened_archetype_other.swift b/test/Serialization/Inputs/nested_opened_archetype_other.swift new file mode 100644 index 0000000000000..da087a961bf5f --- /dev/null +++ b/test/Serialization/Inputs/nested_opened_archetype_other.swift @@ -0,0 +1,11 @@ +public protocol P { + associatedtype A: Q + + func foo() -> A +} + +public protocol Q {} + +@_transparent public func f(p: any P) -> any Q { + return p.foo() +} diff --git a/test/Serialization/nested_opened_archetype.swift b/test/Serialization/nested_opened_archetype.swift new file mode 100644 index 0000000000000..3f4017eaa052a --- /dev/null +++ b/test/Serialization/nested_opened_archetype.swift @@ -0,0 +1,15 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -emit-module-path %t/nested_opened_archetype_other.swiftmodule %S/Inputs/nested_opened_archetype_other.swift +// RUN: %target-swift-frontend -emit-sil %s -I %t + +import nested_opened_archetype_other + +struct SP : P { + func foo() -> SQ { return SQ() } +} + +struct SQ : Q {} + +func g() { + f(p: SP()) +} From 48b4d3a73d56ae70512838cba45e3dad1ffdb648 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 15 Aug 2022 11:08:53 -0700 Subject: [PATCH 109/491] stdlib: Sprinkle an __always inline onto Range.index(after:) After moving to the new llvm pass pipeline this function no longer gets inlined. Leading to 150% regressions in ObjectiveCBridge benchmarks. rdar://98533158 --- stdlib/public/core/Range.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift index dd368177f61b1..b3e72f45e7499 100644 --- a/stdlib/public/core/Range.swift +++ b/stdlib/public/core/Range.swift @@ -229,6 +229,7 @@ where Bound: Strideable, Bound.Stride: SignedInteger public var endIndex: Index { return upperBound } @inlinable + @inline(__always) public func index(after i: Index) -> Index { _failEarlyRangeCheck(i, bounds: startIndex.. Date: Mon, 15 Aug 2022 11:39:12 -0700 Subject: [PATCH 110/491] ABI checker: adding protocol requirement with default implementation should not be flagged as breakage rdar://98583968 --- lib/DriverTool/swift_api_digester_main.cpp | 15 +++++++++++++++ .../protocol-req-with-default-impl.swift | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 test/api-digester/protocol-req-with-default-impl.swift diff --git a/lib/DriverTool/swift_api_digester_main.cpp b/lib/DriverTool/swift_api_digester_main.cpp index 16c56fed1e3f8..0b9a05cbed8b2 100644 --- a/lib/DriverTool/swift_api_digester_main.cpp +++ b/lib/DriverTool/swift_api_digester_main.cpp @@ -691,6 +691,21 @@ class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass { // to the allowlist. ShouldComplain = false; } + if (ShouldComplain) { + // Providing a default implementation via a protocol extension for + // a protocol requirement is both ABI and API safe. + if (auto *PD = dyn_cast(D->getParent())) { + for (auto *SIB: PD->getChildren()) { + if (auto *SIBD = dyn_cast(SIB)) { + if (SIBD->isFromExtension() && + SIBD->getPrintedName() == D->getPrintedName()) { + ShouldComplain = false; + break; + } + } + } + } + } if (ShouldComplain) D->emitDiag(D->getLoc(), diag::protocol_req_added); } diff --git a/test/api-digester/protocol-req-with-default-impl.swift b/test/api-digester/protocol-req-with-default-impl.swift new file mode 100644 index 0000000000000..b4cbfea706c1e --- /dev/null +++ b/test/api-digester/protocol-req-with-default-impl.swift @@ -0,0 +1,18 @@ +// RUN: %empty-directory(%t) + +// RUN: echo "public protocol P {}" > %t/Foo-1.swift +// RUN: echo "public protocol P { func f() }" > %t/Foo-2.swift +// RUN: echo "public extension P { func f() {} }" >> %t/Foo-2.swift + +// RUN: %target-swift-frontend -emit-module %t/Foo-1.swift -module-name Foo -emit-module-interface-path %t/Foo1.swiftinterface +// RUN: %target-swift-frontend -emit-module %t/Foo-2.swift -module-name Foo -emit-module-interface-path %t/Foo2.swiftinterface + +// RUN: %target-swift-frontend -compile-module-from-interface %t/Foo1.swiftinterface -o %t/Foo1.swiftmodule -module-name Foo -emit-abi-descriptor-path %t/Foo1.json + +// RUN: %target-swift-frontend -compile-module-from-interface %t/Foo2.swiftinterface -o %t/Foo2.swiftmodule -module-name Foo -emit-abi-descriptor-path %t/Foo2.json + +// RUN: %api-digester -diagnose-sdk -print-module --input-paths %t/Foo1.json -input-paths %t/Foo2.json -abi -o %t/result.txt + +// RUN: %FileCheck %s < %t/result.txt + +// CHECK-NOT: added as a protocol requirement From c864087b1f082d6c254e55bda2df04d08f4216f1 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 15 Aug 2022 11:50:58 -0700 Subject: [PATCH 111/491] [interop][SwiftToCxx] add a test that verifies that we can emit C++ header from previously built swiftmodule --- .../SwiftToCxx/core/gen-header-for-module.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/Interop/SwiftToCxx/core/gen-header-for-module.swift diff --git a/test/Interop/SwiftToCxx/core/gen-header-for-module.swift b/test/Interop/SwiftToCxx/core/gen-header-for-module.swift new file mode 100644 index 0000000000000..276435d2d2397 --- /dev/null +++ b/test/Interop/SwiftToCxx/core/gen-header-for-module.swift @@ -0,0 +1,17 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -emit-module -module-name Core -o %t +// RUN: %target-swift-frontend -parse-as-library %t/Core.swiftmodule -typecheck -module-name Core -clang-header-expose-public-decls -emit-clang-header-path %t/core.h +// RUN: %FileCheck %s < %t/core.h + +// RUN: %empty-directory(%t-evo) +// RUN: %target-swift-frontend %s -emit-module -enable-library-evolution -module-name Core -o %t-evo +// RUN: %target-swift-frontend -parse-as-library %t-evo/Core.swiftmodule -enable-library-evolution -typecheck -module-name Core -clang-header-expose-public-decls -emit-clang-header-path %t-evo/core.h +// RUN: %FileCheck %s < %t-evo/core.h + + +public func reprintedInImportedModule() -> Int { + return 42 +} + +// CHECK: namespace Core { +// CHECK: swift::Int reprintedInImportedModule() noexcept SWIFT_WARN_UNUSED_RESULT { From 34b5ead2e08c4c4c16a0eb7f1f24256b54d95940 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 15 Aug 2022 11:56:06 -0700 Subject: [PATCH 112/491] [interop][SwiftToCxx] add a test that verifies that we can emit C++ header from previously built swiftinterface --- test/Interop/SwiftToCxx/core/gen-header-for-module.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/Interop/SwiftToCxx/core/gen-header-for-module.swift b/test/Interop/SwiftToCxx/core/gen-header-for-module.swift index 276435d2d2397..d4fc95f866fbe 100644 --- a/test/Interop/SwiftToCxx/core/gen-header-for-module.swift +++ b/test/Interop/SwiftToCxx/core/gen-header-for-module.swift @@ -8,6 +8,15 @@ // RUN: %target-swift-frontend -parse-as-library %t-evo/Core.swiftmodule -enable-library-evolution -typecheck -module-name Core -clang-header-expose-public-decls -emit-clang-header-path %t-evo/core.h // RUN: %FileCheck %s < %t-evo/core.h +// RUN: %empty-directory(%t-int) +// RUN: %target-swift-frontend %s -typecheck -emit-module-interface-path %t-int/Core.swiftinterface -module-name Core +// RUN: %target-swift-frontend -parse-as-library %t-int/Core.swiftinterface -typecheck -module-name Core -clang-header-expose-public-decls -emit-clang-header-path %t-int/core.h +// RUN: %FileCheck %s < %t-int/core.h + +// RUN: %empty-directory(%t-int-evo) +// RUN: %target-swift-frontend %s -typecheck -enable-library-evolution -emit-module-interface-path %t-int-evo/Core.swiftinterface -module-name Core +// RUN: %target-swift-frontend -parse-as-library %t-int-evo/Core.swiftinterface -typecheck -enable-library-evolution -module-name Core -clang-header-expose-public-decls -emit-clang-header-path %t-int-evo/core.h +// RUN: %FileCheck %s < %t-int-evo/core.h public func reprintedInImportedModule() -> Int { return 42 From 3b522c747dfc2f9ead7e90f24350dd4e606ee139 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Mon, 15 Aug 2022 11:58:18 -0700 Subject: [PATCH 113/491] ABIChecker: removing the importation of SwiftOnoneSupport shouldn't be flagged as breakage SwiftOnoneSupport is automatically imported in the debug mode. When diffing the release build with a baseline genearted in the debug build, we may hit this false positive. --- lib/DriverTool/swift_api_digester_main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/DriverTool/swift_api_digester_main.cpp b/lib/DriverTool/swift_api_digester_main.cpp index 0b9a05cbed8b2..d7269e8e5892a 100644 --- a/lib/DriverTool/swift_api_digester_main.cpp +++ b/lib/DriverTool/swift_api_digester_main.cpp @@ -558,6 +558,11 @@ static void diagnoseRemovedDecl(const SDKNodeDecl *D) { if (Ctx.getOpts().SkipRemoveDeprecatedCheck && D->isDeprecated()) return; + // Don't complain about removing importation of SwiftOnoneSupport. + if (D->getKind() == SDKNodeKind::DeclImport && + D->getName() == "SwiftOnoneSupport") { + return; + } D->emitDiag(SourceLoc(), diag::removed_decl, false); } From a673043737c8a7504a78be3f520ffecd0b59b465 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Mon, 15 Aug 2022 12:15:47 -0700 Subject: [PATCH 114/491] Terminology change: 'garbage' -> 'unexpected' There are no "garbage" characters in Swift code. They are just "unexpected." --- include/swift/Syntax/Trivia.h.gyb | 2 +- lib/Parse/Lexer.cpp | 8 +- lib/Parse/ParseExpr.cpp | 6 +- lib/Parse/ParseIfConfig.cpp | 4 +- lib/Parse/ParseType.cpp | 4 +- lib/Parse/ParsedSyntaxRecorder.cpp.gyb | 16 +- lib/Syntax/SyntaxFactory.cpp.gyb | 56 ++--- test/Parse/invalid-utf8.swift | 4 +- test/Syntax/Inputs/invalid.sed | 4 +- test/Syntax/tokens_nonbreaking_space.swift | 12 +- test/Syntax/tokens_nul.swift | 4 +- test/Syntax/tokens_unknown_and_invalid.swift | 8 +- unittests/Parse/LexerTests.cpp | 4 +- unittests/Parse/LexerTriviaTests.cpp | 4 +- unittests/Syntax/DeclSyntaxTests.cpp | 210 +++++++++--------- unittests/Syntax/ExprSyntaxTests.cpp | 124 +++++------ unittests/Syntax/StmtSyntaxTests.cpp | 40 ++-- unittests/Syntax/SyntaxCollectionTests.cpp | 6 +- unittests/Syntax/TriviaTests.cpp | 4 +- unittests/Syntax/TypeSyntaxTests.cpp | 136 ++++++------ unittests/Syntax/UnknownSyntaxTests.cpp | 34 +-- utils/gyb_syntax_support/Child.py | 4 +- utils/gyb_syntax_support/CommonNodes.py | 2 +- utils/gyb_syntax_support/Node.py | 12 +- .../NodeSerializationCodes.py | 2 +- utils/gyb_syntax_support/Trivia.py | 3 +- 26 files changed, 357 insertions(+), 356 deletions(-) diff --git a/include/swift/Syntax/Trivia.h.gyb b/include/swift/Syntax/Trivia.h.gyb index 9f13ac3d91612..7dfc24faceb16 100644 --- a/include/swift/Syntax/Trivia.h.gyb +++ b/include/swift/Syntax/Trivia.h.gyb @@ -365,7 +365,7 @@ private: return Text.startswith("///"); case TriviaKind::DocBlockComment: return Text.startswith("/**") && Text.endswith("*/"); - case TriviaKind::GarbageText: + case TriviaKind::UnexpectedText: case TriviaKind::Shebang: return !Text.empty(); % for trivia in TRIVIAS: diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index 1ed4b0953b05f..59dc231927bd4 100644 --- a/lib/Parse/Lexer.cpp +++ b/lib/Parse/Lexer.cpp @@ -3222,7 +3222,7 @@ ParsedTrivia TriviaLexer::lexTrivia(StringRef TriviaStr) { if (tryAdvanceToEndOfConflictMarker(CurPtr, BufferEnd)) { // Conflict marker. size_t Length = CurPtr - TriviaStart; - Pieces.push_back(TriviaKind::GarbageText, Length); + Pieces.push_back(TriviaKind::UnexpectedText, Length); continue; } break; @@ -3231,13 +3231,13 @@ ParsedTrivia TriviaLexer::lexTrivia(StringRef TriviaStr) { // BOM marker. CurPtr = CurPtr + 2; size_t Length = CurPtr - TriviaStart; - Pieces.push_back(TriviaKind::GarbageText, Length); + Pieces.push_back(TriviaKind::UnexpectedText, Length); continue; } break; case 0: { size_t Length = CurPtr - TriviaStart; - Pieces.push_back(TriviaKind::GarbageText, Length); + Pieces.push_back(TriviaKind::UnexpectedText, Length); continue; } default: @@ -3267,7 +3267,7 @@ ParsedTrivia TriviaLexer::lexTrivia(StringRef TriviaStr) { } size_t Length = CurPtr - TriviaStart; - Pieces.push_back(TriviaKind::GarbageText, Length); + Pieces.push_back(TriviaKind::UnexpectedText, Length); continue; } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 22daf368ac403..486e0be0e305f 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1247,7 +1247,7 @@ Parser::parseExprPostfixSuffix(ParserResult Result, bool isExprBasic, // } // In this case, we want to consume the trailing closure because // otherwise it will get parsed as a get-set clause on a variable - // declared by `baseExpr.` which is complete garbage. + // declared by `baseExpr.` which is clearly wrong. bool hasBindOptional = false; parseExprPostfixSuffix(makeParserResult(CCExpr), isExprBasic, periodHasKeyPathBehavior, hasBindOptional); @@ -1702,11 +1702,11 @@ ParserResult Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { if (SyntaxContext->isEnabled()) { ParsedPatternSyntax PatternNode = ParsedSyntaxRecorder::makeIdentifierPattern( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Identifier=*/SyntaxContext->popToken(), *SyntaxContext); ParsedExprSyntax ExprNode = ParsedSyntaxRecorder::makeUnresolvedPatternExpr( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Pattern=*/std::move(PatternNode), *SyntaxContext); SyntaxContext->addSyntax(std::move(ExprNode)); } diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp index 558ce0497de9e..4c67e718ef76a 100644 --- a/lib/Parse/ParseIfConfig.cpp +++ b/lib/Parse/ParseIfConfig.cpp @@ -822,10 +822,10 @@ ParserResult Parser::parseIfConfig( // to disambiguate whether a postfix expression is the condition of // #elseif or a postfix expression of the #else body. // To do this, push three empty syntax nodes onto the stack. - // - First one for garbage nodes between the #else keyword and the + // - First one for unexpected nodes between the #else keyword and the // condition // - One for the condition itself (whcih doesn't exist) - // - And finally one for the garbage nodes between the condition and + // - And finally one for the unexpected nodes between the condition and // the elements SyntaxContext->addRawSyntax(ParsedRawSyntaxNode()); SyntaxContext->addRawSyntax(ParsedRawSyntaxNode()); diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index 5ec6a652dbe02..797aa740ea280 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -916,9 +916,9 @@ Parser::parseTypeSimpleOrComposition(Diag<> MessageID, ParseTypeReason reason) { if (SyntaxContext->isEnabled()) { if (auto synType = SyntaxContext->popIf()) { auto LastNode = ParsedSyntaxRecorder::makeCompositionTypeElement( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Type=*/std::move(*synType), - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Ampersand=*/None, *SyntaxContext); SyntaxContext->addSyntax(std::move(LastNode)); } diff --git a/lib/Parse/ParsedSyntaxRecorder.cpp.gyb b/lib/Parse/ParsedSyntaxRecorder.cpp.gyb index 96175d826705f..30b9bdee85e53 100644 --- a/lib/Parse/ParsedSyntaxRecorder.cpp.gyb +++ b/lib/Parse/ParsedSyntaxRecorder.cpp.gyb @@ -173,21 +173,21 @@ ParsedSyntaxRecorder::makeTupleTypeElement(ParsedTypeSyntax Type, llvm::Optional TrailingComma, SyntaxParsingContext &SPCtx) { return makeTupleTypeElement( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*InOut=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Name=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*SecondName=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Colon=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, std::move(Type), - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Ellipsis=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Initializer=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, std::move(TrailingComma), SPCtx ); diff --git a/lib/Syntax/SyntaxFactory.cpp.gyb b/lib/Syntax/SyntaxFactory.cpp.gyb index e2612415b3617..75a379c44ea9d 100644 --- a/lib/Syntax/SyntaxFactory.cpp.gyb +++ b/lib/Syntax/SyntaxFactory.cpp.gyb @@ -65,8 +65,8 @@ SyntaxFactory::countChildren(SyntaxKind Kind){ % for node in SYNTAX_NODES: % if not node.is_syntax_collection(): case SyntaxKind::${node.syntax_kind}: -% child_count = len(node.non_garbage_children) -% non_optional_child_count = sum(0 if child.is_optional else 1 for child in node.non_garbage_children) +% child_count = len(node.non_unexpected_children) +% non_optional_child_count = sum(0 if child.is_optional else 1 for child in node.non_unexpected_children) return {${non_optional_child_count}, ${child_count}}; % end % end @@ -244,11 +244,11 @@ SyntaxFactory::makeBlank${node.syntax_kind}() { TupleTypeSyntax SyntaxFactory::makeVoidTupleType() { return makeTupleType( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*LeftParen=*/makeLeftParenToken({}, {}), - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Elements=*/makeBlankTupleTypeElementList(), - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*RightParen=*/makeRightParenToken({}, {}) ); } @@ -259,21 +259,21 @@ SyntaxFactory::makeTupleTypeElement(llvm::Optional Label, TypeSyntax Type, llvm::Optional TrailingComma) { return makeTupleTypeElement( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*InOut=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Name=*/Label, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*SecondName=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Colon=*/Colon, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Type=*/Type, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Ellipsis=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Intitializer=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*TrailingComma=*/TrailingComma ); } @@ -282,21 +282,21 @@ TupleTypeElementSyntax SyntaxFactory::makeTupleTypeElement(TypeSyntax Type, llvm::Optional TrailingComma) { return makeTupleTypeElement( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*InOut=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Name=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*SecondName=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Colon=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Type=*/Type, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Ellipsis=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Initializer=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*TrailingComma=*/TrailingComma ); } @@ -305,15 +305,15 @@ GenericParameterSyntax SyntaxFactory::makeGenericParameter(TokenSyntax Name, llvm::Optional TrailingComma) { return makeGenericParameter( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Attributes=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Name=*/Name, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Colon=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*InheritedType=*/None, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*TrailingComma=*/TrailingComma ); } @@ -327,9 +327,9 @@ TypeSyntax SyntaxFactory::makeTypeIdentifier(StringRef TypeName, TrailingTrivia ); return makeSimpleTypeIdentifier( - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Name=*/identifier, - /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*GenerigArgumentClause=*/None ); } diff --git a/test/Parse/invalid-utf8.swift b/test/Parse/invalid-utf8.swift index 552328da8133f..4e0931981a665 100644 --- a/test/Parse/invalid-utf8.swift +++ b/test/Parse/invalid-utf8.swift @@ -10,7 +10,7 @@ static func foo() {} // expected-error{{static methods may only be declared on a // Below this line are such octets that should be skipped by the lexer. // They may not be rendered correctly by your text editor, if at all. -// Begin magic UTF-8 garbage +// Begin magic UTF-8 values // 0xC0 À // expected-error {{invalid UTF-8 found in source file}} // 0xC1 @@ -31,7 +31,7 @@ static func foo() {} // expected-error{{static methods may only be declared on a ü // expected-error {{invalid UTF-8 found in source file}} // 0xFD ý // expected-error {{invalid UTF-8 found in source file}} -// End magic UTF-8 garbage +// End magic UTF-8 values // Make sure we don't stop processing the whole file. static func bar() {} // expected-error{{static methods may only be declared on a type}} {{1-8=}} diff --git a/test/Syntax/Inputs/invalid.sed b/test/Syntax/Inputs/invalid.sed index 278f6fd59e7f0..90a753b15153f 100644 --- a/test/Syntax/Inputs/invalid.sed +++ b/test/Syntax/Inputs/invalid.sed @@ -1,7 +1,7 @@ # [0xC2] is utf8 2 byte character start byte. # 0xC2 without second byte is invalid UTF-8 sequence. -# It becomes garbage text trivia. +# It becomes unexpected text trivia. # Marker(1) is replaced to this sequence. s/Z1/Â/g @@ -26,7 +26,7 @@ s/Z4/â€/g # [0xE1, 0x9A, 0x80] in UTF-8 is U+1680. # This character is invalid for swift source. -# It becomes garbage trivia. +# It becomes unexpected trivia. # Marker(5) is replaced to this sequence. s/Z5/ /g diff --git a/test/Syntax/tokens_nonbreaking_space.swift b/test/Syntax/tokens_nonbreaking_space.swift index b0da4cebc0d1b..5fcae5a51e9fc 100644 --- a/test/Syntax/tokens_nonbreaking_space.swift +++ b/test/Syntax/tokens_nonbreaking_space.swift @@ -15,30 +15,30 @@ let cZ=Z3 // CHECK-LABEL: 4:7 // CHECK-NEXT:(Token equal // CHECK-NEXT: (text="=") -// CHECK-NEXT: (trivia garbageText \302\240)) +// CHECK-NEXT: (trivia unexpectedText \302\240)) // CHECK-LABEL: 4:10 // CHECK-NEXT:(Token integer_literal // CHECK-NEXT: (text="3") -// CHECK-NEXT: (trivia garbageText \302\240) +// CHECK-NEXT: (trivia unexpectedText \302\240) // CHECK-NEXT: (trivia space 1)) // CHECK-LABEL: 5:5 // CHECK-NEXT:(Token identifier // CHECK-NEXT: (text="b") -// CHECK-NEXT: (trivia garbageText \302\240)) +// CHECK-NEXT: (trivia unexpectedText \302\240)) // CHECK-LABEL: 5:10 // CHECK-NEXT:(Token integer_literal // CHECK-NEXT: (text="3") -// CHECK-NEXT: (trivia garbageText \302\240) +// CHECK-NEXT: (trivia unexpectedText \302\240) // CHECK-LABEL: 6:5 // CHECK-NEXT:(Token identifier // CHECK-NEXT: (text="c") -// CHECK-NEXT: (trivia garbageText \302\240)) +// CHECK-NEXT: (trivia unexpectedText \302\240)) // CHECK-LABEL: 6:8 // CHECK-NEXT:(Token equal // CHECK-NEXT: (text="=") -// CHECK-NEXT: (trivia garbageText \302\240)) +// CHECK-NEXT: (trivia unexpectedText \302\240)) diff --git a/test/Syntax/tokens_nul.swift b/test/Syntax/tokens_nul.swift index 16d13599faac6..d302e28f0807a 100644 --- a/test/Syntax/tokens_nul.swift +++ b/test/Syntax/tokens_nul.swift @@ -12,12 +12,12 @@ func b() {} // CHECK-NEXT:(Token equal // CHECK-NEXT: (text="=") // CHECK-NEXT: (trivia space 1) -// CHECK-NEXT: (trivia garbageText \000)) +// CHECK-NEXT: (trivia unexpectedText \000)) // CHECK-LABEL: 4:10 // CHECK-NEXT:(Token integer_literal // CHECK-NEXT: (text="3") -// CHECK-NEXT: (trivia garbageText \000) +// CHECK-NEXT: (trivia unexpectedText \000) // CHECK-NEXT: (trivia space 1)) // CHECK-LABEL: 5:1 diff --git a/test/Syntax/tokens_unknown_and_invalid.swift b/test/Syntax/tokens_unknown_and_invalid.swift index 64bfdd6232c6f..9f4b1451df750 100644 --- a/test/Syntax/tokens_unknown_and_invalid.swift +++ b/test/Syntax/tokens_unknown_and_invalid.swift @@ -44,11 +44,11 @@ jjj // CHECK-LABEL: 14:3 // CHECK-NEXT: (Token identifier // CHECK-NEXT: (trivia newline 1) -// CHECK-NEXT: (trivia garbageText \302) +// CHECK-NEXT: (trivia unexpectedText \302) // CHECK-NEXT: (trivia space 1) // CHECK-NEXT: (text="bbb") // CHECK-NEXT: (trivia space 1) -// CHECK-NEXT: (trivia garbageText \302)) +// CHECK-NEXT: (trivia unexpectedText \302)) // Checks around ccc // CHECK-LABEL: 16:5 @@ -82,8 +82,8 @@ jjj // CHECK-LABEL: 27:5 // CHECK-NEXT: (Token identifier // CHECK-NEXT: (trivia newline 1) -// CHECK-NEXT: (trivia garbageText \341\232\200) +// CHECK-NEXT: (trivia unexpectedText \341\232\200) // CHECK-NEXT: (trivia space 1) // CHECK-NEXT: (text="iii") // CHECK-NEXT: (trivia space 1) -// CHECK-NEXT: (trivia garbageText \341\232\200)) +// CHECK-NEXT: (trivia unexpectedText \341\232\200)) diff --git a/unittests/Parse/LexerTests.cpp b/unittests/Parse/LexerTests.cpp index 28ebb111be794..202119e85fcb9 100644 --- a/unittests/Parse/LexerTests.cpp +++ b/unittests/Parse/LexerTests.cpp @@ -422,7 +422,7 @@ TEST_F(LexerTest, BOMNoCommentTrivia) { ParsedTrivia LeadingTriviaPieces = TriviaLexer::lexTrivia(LeadingTrivia); ParsedTrivia TrailingTriviaPieces = TriviaLexer::lexTrivia(TrailingTrivia); ASSERT_EQ((ParsedTrivia{{ - ParsedTriviaPiece(TriviaKind::GarbageText, strlen("\xEF\xBB\xBF")), + ParsedTriviaPiece(TriviaKind::UnexpectedText, strlen("\xEF\xBB\xBF")), ParsedTriviaPiece(TriviaKind::LineComment, strlen("// comment")), ParsedTriviaPiece(TriviaKind::Newline, 1) }}), LeadingTriviaPieces); @@ -472,7 +472,7 @@ TEST_F(LexerTest, BOMAttachCommentTrivia) { ParsedTrivia LeadingTriviaPieces = TriviaLexer::lexTrivia(LeadingTrivia); ParsedTrivia TrailingTriviaPieces = TriviaLexer::lexTrivia(TrailingTrivia); ASSERT_EQ((ParsedTrivia{{ - ParsedTriviaPiece(TriviaKind::GarbageText, strlen("\xEF\xBB\xBF")), + ParsedTriviaPiece(TriviaKind::UnexpectedText, strlen("\xEF\xBB\xBF")), ParsedTriviaPiece(TriviaKind::LineComment, strlen("// comment")), ParsedTriviaPiece(TriviaKind::Newline, 1) }}), LeadingTriviaPieces); diff --git a/unittests/Parse/LexerTriviaTests.cpp b/unittests/Parse/LexerTriviaTests.cpp index 9cb2f78285f45..8a7763fd53755 100644 --- a/unittests/Parse/LexerTriviaTests.cpp +++ b/unittests/Parse/LexerTriviaTests.cpp @@ -139,7 +139,7 @@ TEST_F(LexerTriviaTest, TriviaHashbangAfterBOM) { ASSERT_EQ(LeadingTrivia, "\xEF\xBB\xBF" "#!/bin/swift\n"); ASSERT_EQ(TrailingTrivia, ""); ASSERT_EQ(LeadingTriviaPieces, (ParsedTrivia{{ - ParsedTriviaPiece(TriviaKind::GarbageText, strlen("\xEF\xBB\xBF")), + ParsedTriviaPiece(TriviaKind::UnexpectedText, strlen("\xEF\xBB\xBF")), ParsedTriviaPiece(TriviaKind::Shebang, strlen("#!/bin/swift")), ParsedTriviaPiece(TriviaKind::Newline, 1)}})); ASSERT_EQ(TrailingTriviaPieces, ParsedTrivia()); @@ -190,7 +190,7 @@ TEST_F(LexerTriviaTest, TriviaConflictMarker) { ASSERT_EQ(TrailingTrivia, ""); ASSERT_EQ(LeadingTriviaPieces, (ParsedTrivia{{ ParsedTriviaPiece(TriviaKind::Newline, 1), - ParsedTriviaPiece(TriviaKind::GarbageText, expectedTrivia.size()), + ParsedTriviaPiece(TriviaKind::UnexpectedText, expectedTrivia.size()), ParsedTriviaPiece(TriviaKind::Newline, 1)}})); ASSERT_EQ(TrailingTriviaPieces, ParsedTrivia()); } diff --git a/unittests/Syntax/DeclSyntaxTests.cpp b/unittests/Syntax/DeclSyntaxTests.cpp index 342e250b4e72e..cdde094ada49b 100644 --- a/unittests/Syntax/DeclSyntaxTests.cpp +++ b/unittests/Syntax/DeclSyntaxTests.cpp @@ -19,10 +19,10 @@ DeclModifierSyntax getCannedDeclModifier(const RC &Arena) { auto Set = Factory.makeIdentifier("set", "", ""); auto RParen = Factory.makeRightParenToken("", ""); auto DeclModifierDetail = Factory.makeDeclModifierDetail( - /*GarbageNodes=*/None, LParen, /*GarbageNodes=*/None, Set, - /*GarbageNodes=*/None, RParen); - return Factory.makeDeclModifier(/*GarbageNodes=*/None, Private, - /*GarbageNodes=*/None, DeclModifierDetail); + /*UnexpectedNodes=*/None, LParen, /*UnexpectedNodes=*/None, Set, + /*UnexpectedNodes=*/None, RParen); + return Factory.makeDeclModifier(/*UnexpectedNodes=*/None, Private, + /*UnexpectedNodes=*/None, DeclModifierDetail); } TEST(DeclSyntaxTests, DeclModifierMakeAPIs) { @@ -50,11 +50,11 @@ TEST(DeclSyntaxTests, DeclModifierGetAPIs) { auto Set = Factory.makeIdentifier("set", "", ""); auto RParen = Factory.makeRightParenToken("", ""); auto DeclModifierDetail = Factory.makeDeclModifierDetail( - /*GarbageNodes=*/None, LParen, /*GarbageNodes=*/None, Set, - /*GarbageNodes=*/None, RParen); + /*UnexpectedNodes=*/None, LParen, /*UnexpectedNodes=*/None, Set, + /*UnexpectedNodes=*/None, RParen); auto Mod = - Factory.makeDeclModifier(/*GarbageNodes=*/None, Private, - /*GarbageNodes=*/None, DeclModifierDetail); + Factory.makeDeclModifier(/*UnexpectedNodes=*/None, Private, + /*UnexpectedNodes=*/None, DeclModifierDetail); ASSERT_EQ(Private.getRaw(), Mod.getName().getRaw()); ASSERT_EQ(LParen.getRaw(), Mod.getDetail()->getLeftParen().getRaw()); @@ -74,9 +74,9 @@ TEST(DeclSyntaxTests, DeclModifierWithAPIs) { llvm::raw_svector_ostream OS(Scratch); Factory.makeBlankDeclModifier() .withName(Private) - .withDetail(Factory.makeDeclModifierDetail(/*GarbageNodes=*/None, LParen, - /*GarbageNodes=*/None, Set, - /*GarbageNodes=*/None, RParen)) + .withDetail(Factory.makeDeclModifierDetail(/*UnexpectedNodes=*/None, LParen, + /*UnexpectedNodes=*/None, Set, + /*UnexpectedNodes=*/None, RParen)) .print(OS); ASSERT_EQ(OS.str().str(), "private(set)"); } @@ -99,9 +99,9 @@ TEST(DeclSyntaxTests, TypealiasMakeAPIs) { auto Subsequence = Factory.makeIdentifier("MyCollection", "", ""); auto ElementName = Factory.makeIdentifier("Element", "", ""); auto ElementParam = Factory.makeGenericParameter( - /*GarbageNodes=*/None, /*Attributes=*/None, /*GarbageNodes=*/None, - /*Name=*/ElementName, /*GarbageNodes=*/None, /*Colon=*/None, - /*GarbageNodes=*/None, /*InheritedType=*/None, /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Attributes=*/None, /*UnexpectedNodes=*/None, + /*Name=*/ElementName, /*UnexpectedNodes=*/None, /*Colon=*/None, + /*UnexpectedNodes=*/None, /*InheritedType=*/None, /*UnexpectedNodes=*/None, /*TrailingComma=*/None); auto LeftAngle = Factory.makeLeftAngleToken("", ""); auto RightAngle = Factory.makeRightAngleToken("", " "); @@ -113,8 +113,8 @@ TEST(DeclSyntaxTests, TypealiasMakeAPIs) { auto Assignment = Factory.makeEqualToken("", " "); auto ElementType = Factory.makeTypeIdentifier("Element", "", ""); auto ElementArg = Factory.makeGenericArgument( - /*GarbageNodes=*/None, /*ArgumentType=*/ElementType, - /*GarbageNodes=*/None, /*TrailingComma=*/None); + /*UnexpectedNodes=*/None, /*ArgumentType=*/ElementType, + /*UnexpectedNodes=*/None, /*TrailingComma=*/None); auto GenericArgs = GenericArgumentClauseSyntaxBuilder(Arena) @@ -125,19 +125,19 @@ TEST(DeclSyntaxTests, TypealiasMakeAPIs) { auto Array = Factory.makeIdentifier("Array", "", ""); auto Array_Int = Factory.makeSimpleTypeIdentifier( - /*GarbageNodes=*/None, /*Name=*/Array, /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Name=*/Array, /*UnexpectedNodes=*/None, /*GenericArgumentClause=*/GenericArgs); auto TypeInit = Factory.makeTypeInitializerClause( - /*GarbageNodes=*/None, /*Equal=*/Assignment, /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Equal=*/Assignment, /*UnexpectedNodes=*/None, /*Value=*/Array_Int); Factory .makeTypealiasDecl( - /*GarbageNodes=*/None, /*Attributes=*/None, /*GarbageNodes=*/None, - /*Modifiers=*/None, /*GarbageNodes=*/None, - /*TypealiasKeyword=*/Typealias, /*GarbageNodes=*/None, - /*Identifier=*/Subsequence, /*GarbageNodes=*/None, - /*GenericParameterClause=*/GenericParams, /*GarbageNodes=*/None, - /*Initializer=*/TypeInit, /*GarbageNodes=*/None, + /*UnexpectedNodes=*/None, /*Attributes=*/None, /*UnexpectedNodes=*/None, + /*Modifiers=*/None, /*UnexpectedNodes=*/None, + /*TypealiasKeyword=*/Typealias, /*UnexpectedNodes=*/None, + /*Identifier=*/Subsequence, /*UnexpectedNodes=*/None, + /*GenericParameterClause=*/GenericParams, /*UnexpectedNodes=*/None, + /*Initializer=*/TypeInit, /*UnexpectedNodes=*/None, /*GenericWhereClause=*/None) .print(OS); ASSERT_EQ(OS.str().str(), @@ -152,9 +152,9 @@ TEST(DeclSyntaxTests, TypealiasWithAPIs) { auto MyCollection = Factory.makeIdentifier("MyCollection", "", ""); auto ElementName = Factory.makeIdentifier("Element", "", ""); auto ElementParam = Factory.makeGenericParameter( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, ElementName, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, ElementName, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None); auto LeftAngle = Factory.makeLeftAngleToken("", ""); auto RightAngle = Factory.makeRightAngleToken("", " "); auto GenericParams = GenericParameterClauseSyntaxBuilder(Arena) @@ -166,7 +166,7 @@ TEST(DeclSyntaxTests, TypealiasWithAPIs) { auto ElementType = Factory.makeTypeIdentifier("Element", "", ""); auto ElementArg = Factory.makeGenericArgument( - /*GarbageNodes=*/None, ElementType, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, ElementType, /*UnexpectedNodes=*/None, None); auto GenericArgs = GenericArgumentClauseSyntaxBuilder(Arena) .useLeftAngleBracket(LeftAngle) @@ -176,9 +176,9 @@ TEST(DeclSyntaxTests, TypealiasWithAPIs) { auto Array = Factory.makeIdentifier("Array", "", ""); auto Array_Int = Factory.makeSimpleTypeIdentifier( - /*GarbageNodes=*/None, Array, /*GarbageNodes=*/None, GenericArgs); + /*UnexpectedNodes=*/None, Array, /*UnexpectedNodes=*/None, GenericArgs); auto Type_Init = Factory.makeTypeInitializerClause( - /*GarbageNodes=*/None, Equal, /*GarbageNodes=*/None, Array_Int); + /*UnexpectedNodes=*/None, Equal, /*UnexpectedNodes=*/None, Array_Int); { SmallString<1> Scratch; llvm::raw_svector_ostream OS(Scratch); @@ -214,7 +214,7 @@ TEST(DeclSyntaxTests, TypealiasBuilderAPIs) { auto ElementType = Factory.makeTypeIdentifier("Element", "", ""); auto ElementArg = Factory.makeGenericArgument( - /*GarbageNodes=*/None, ElementType, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, ElementType, /*UnexpectedNodes=*/None, None); auto GenericArgs = GenericArgumentClauseSyntaxBuilder(Arena) @@ -225,9 +225,9 @@ TEST(DeclSyntaxTests, TypealiasBuilderAPIs) { auto Array = Factory.makeIdentifier("Array", "", ""); auto Array_Int = Factory.makeSimpleTypeIdentifier( - /*GarbageNodes=*/None, Array, /*GarbageNodes=*/None, GenericArgs); + /*UnexpectedNodes=*/None, Array, /*UnexpectedNodes=*/None, GenericArgs); auto Type_Init = Factory.makeTypeInitializerClause( - /*GarbageNodes=*/None, Equal, /*GarbageNodes=*/None, Array_Int); + /*UnexpectedNodes=*/None, Equal, /*UnexpectedNodes=*/None, Array_Int); TypealiasDeclSyntaxBuilder(Arena) .useTypealiasKeyword(Typealias) .useIdentifier(MyCollection) @@ -253,18 +253,18 @@ FunctionParameterSyntax getCannedFunctionParameter(const RC &Arena) auto Sign = Factory.makePrefixOperator("-", "", ""); auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); auto OneLiteral = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); - auto One = Factory.makePrefixOperatorExpr(/*GarbageNodes=*/None, Sign, - /*GarbageNodes=*/None, OneLiteral); - auto DefaultArg = Factory.makeInitializerClause(/*GarbageNodes=*/None, Equal, - /*GarbageNodes=*/None, One); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); + auto One = Factory.makePrefixOperatorExpr(/*UnexpectedNodes=*/None, Sign, + /*UnexpectedNodes=*/None, OneLiteral); + auto DefaultArg = Factory.makeInitializerClause(/*UnexpectedNodes=*/None, Equal, + /*UnexpectedNodes=*/None, One); auto Comma = Factory.makeCommaToken("", " "); return Factory.makeFunctionParameter( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, ExternalName, - /*GarbageNodes=*/None, LocalName, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, NoEllipsis, - /*GarbageNodes=*/None, DefaultArg, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, ExternalName, + /*UnexpectedNodes=*/None, LocalName, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, NoEllipsis, + /*UnexpectedNodes=*/None, DefaultArg, /*UnexpectedNodes=*/None, Comma); } TEST(DeclSyntaxTests, FunctionParameterMakeAPIs) { @@ -297,18 +297,18 @@ TEST(DeclSyntaxTests, FunctionParameterGetAPIs) { auto Sign = Factory.makePrefixOperator("-", "", ""); auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); auto OneLiteral = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); - auto One = Factory.makePrefixOperatorExpr(/*GarbageNodes=*/None, Sign, - /*GarbageNodes=*/None, OneLiteral); - auto DefaultArg = Factory.makeInitializerClause(/*GarbageNodes=*/None, Equal, - /*GarbageNodes=*/None, One); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); + auto One = Factory.makePrefixOperatorExpr(/*UnexpectedNodes=*/None, Sign, + /*UnexpectedNodes=*/None, OneLiteral); + auto DefaultArg = Factory.makeInitializerClause(/*UnexpectedNodes=*/None, Equal, + /*UnexpectedNodes=*/None, One); auto Comma = Factory.makeCommaToken("", ""); auto Param = Factory.makeFunctionParameter( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, ExternalName, - /*GarbageNodes=*/None, LocalName, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, NoEllipsis, - /*GarbageNodes=*/None, DefaultArg, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, ExternalName, + /*UnexpectedNodes=*/None, LocalName, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, NoEllipsis, + /*UnexpectedNodes=*/None, DefaultArg, /*UnexpectedNodes=*/None, Comma); ASSERT_EQ(ExternalName.getRaw(), Param.getFirstName()->getRaw()); ASSERT_EQ(LocalName.getRaw(), Param.getSecondName()->getRaw()); @@ -346,9 +346,9 @@ TEST(DeclSyntaxTests, FunctionParameterWithAPIs) { auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "", Arena); auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); - auto One = Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); - auto DefaultArg = Factory.makeInitializerClause(/*GarbageNodes=*/None, Equal, - /*GarbageNodes=*/None, One); + auto One = Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); + auto DefaultArg = Factory.makeInitializerClause(/*UnexpectedNodes=*/None, Equal, + /*UnexpectedNodes=*/None, One); auto Comma = Factory.makeCommaToken("", ""); { @@ -435,18 +435,18 @@ FunctionSignatureSyntax getCannedFunctionSignature(const RC &Arena) .appending(Param) .castTo(); auto RParen = Factory.makeRightParenToken("", " "); - auto Parameter = Factory.makeParameterClause(/*GarbageNodes=*/None, LParen, - /*GarbageNodes=*/None, List, - /*GarbageNodes=*/None, RParen); + auto Parameter = Factory.makeParameterClause(/*UnexpectedNodes=*/None, LParen, + /*UnexpectedNodes=*/None, List, + /*UnexpectedNodes=*/None, RParen); auto Throws = Factory.makeThrowsKeyword("", " "); auto Arrow = Factory.makeArrowToken("", " "); auto Int = Factory.makeTypeIdentifier("Int", "", " "); - auto Return = Factory.makeReturnClause(/*GarbageNodes=*/None, Arrow, - /*GarbageNodes=*/None, Int); + auto Return = Factory.makeReturnClause(/*UnexpectedNodes=*/None, Arrow, + /*UnexpectedNodes=*/None, Int); return Factory.makeFunctionSignature( - /*GarbageNodes=*/None, Parameter, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, Throws, /*GarbageNodes=*/None, Return); + /*UnexpectedNodes=*/None, Parameter, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, Throws, /*UnexpectedNodes=*/None, Return); } TEST(DeclSyntaxTests, FunctionSignatureMakeAPIs) { @@ -485,14 +485,14 @@ TEST(DeclSyntaxTests, FunctionSignatureGetAPIs) { auto Int = Factory.makeTypeIdentifier("Int", "", ""); - auto ParamClause = Factory.makeParameterClause(/*GarbageNodes=*/None, LParen, - /*GarbageNodes=*/None, List, - /*GarbageNodes=*/None, RParen); - auto ReturnClause = Factory.makeReturnClause(/*GarbageNodes=*/None, Arrow, - /*GarbageNodes=*/None, Int); + auto ParamClause = Factory.makeParameterClause(/*UnexpectedNodes=*/None, LParen, + /*UnexpectedNodes=*/None, List, + /*UnexpectedNodes=*/None, RParen); + auto ReturnClause = Factory.makeReturnClause(/*UnexpectedNodes=*/None, Arrow, + /*UnexpectedNodes=*/None, Int); auto Sig = Factory.makeFunctionSignature( - /*GarbageNodes=*/None, ParamClause, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, Throws, /*GarbageNodes=*/None, ReturnClause); + /*UnexpectedNodes=*/None, ParamClause, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, Throws, /*UnexpectedNodes=*/None, ReturnClause); ASSERT_EQ(LParen.getRaw(), Sig.getInput().getLeftParen().getRaw()); @@ -540,11 +540,11 @@ TEST(DeclSyntaxTests, FunctionSignatureWithAPIs) { auto Arrow = Factory.makeArrowToken("", " "); auto Int = Factory.makeTypeIdentifier("Int", "", ""); - auto Parameter = Factory.makeParameterClause(/*GarbageNodes=*/None, LParen, - /*GarbageNodes=*/None, List, - /*GarbageNodes=*/None, RParen); - auto Return = Factory.makeReturnClause(/*GarbageNodes=*/None, Arrow, - /*GarbageNodes=*/None, Int); + auto Parameter = Factory.makeParameterClause(/*UnexpectedNodes=*/None, LParen, + /*UnexpectedNodes=*/None, List, + /*UnexpectedNodes=*/None, RParen); + auto Return = Factory.makeReturnClause(/*UnexpectedNodes=*/None, Arrow, + /*UnexpectedNodes=*/None, Int); SmallString<48> Scratch; llvm::raw_svector_ostream OS(Scratch); Factory.makeBlankFunctionSignature() @@ -567,19 +567,19 @@ ModifierListSyntax getCannedModifiers(const RC &Arena) { auto NoArgument = TokenSyntax::missingToken(tok::identifier, "", Arena); auto NoRParen = TokenSyntax::missingToken(tok::r_paren, ")", Arena); auto PublicDeclModifierDetail = Factory.makeDeclModifierDetail( - /*GarbageNodes=*/None, NoLParen, /*GarbageNodes=*/None, NoArgument, - /*GarbageNodes=*/None, NoRParen); + /*UnexpectedNodes=*/None, NoLParen, /*UnexpectedNodes=*/None, NoArgument, + /*UnexpectedNodes=*/None, NoRParen); auto Public = Factory.makeDeclModifier( - /*GarbageNodes=*/None, PublicID, - /*GarbageNodes=*/None, PublicDeclModifierDetail); + /*UnexpectedNodes=*/None, PublicID, + /*UnexpectedNodes=*/None, PublicDeclModifierDetail); auto StaticKW = Factory.makeStaticKeyword("", " "); auto StaticDeclModifierDetail = Factory.makeDeclModifierDetail( - /*GarbageNodes=*/None, NoLParen, /*GarbageNodes=*/None, NoArgument, - /*GarbageNodes=*/None, NoRParen); + /*UnexpectedNodes=*/None, NoLParen, /*UnexpectedNodes=*/None, NoArgument, + /*UnexpectedNodes=*/None, NoRParen); auto Static = - Factory.makeDeclModifier(/*GarbageNodes=*/None, StaticKW, - /*GarbageNodes=*/None, StaticDeclModifierDetail); + Factory.makeDeclModifier(/*UnexpectedNodes=*/None, StaticKW, + /*UnexpectedNodes=*/None, StaticDeclModifierDetail); return Factory.makeBlankModifierList().appending(Public).appending(Static); } @@ -609,22 +609,22 @@ CodeBlockSyntax getCannedBody(const RC &Arena) { SyntaxFactory Factory(Arena); auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "-", Arena); auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); - auto One = Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); + auto One = Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); auto ReturnKW = Factory.makeReturnKeyword("\n ", ""); - auto Return = Factory.makeReturnStmt(/*GarbageNodes=*/None, ReturnKW, - /*GarbageNodes=*/None, One); - auto ReturnItem = Factory.makeCodeBlockItem(/*GarbageNodes=*/None, Return, - /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None); + auto Return = Factory.makeReturnStmt(/*UnexpectedNodes=*/None, ReturnKW, + /*UnexpectedNodes=*/None, One); + auto ReturnItem = Factory.makeCodeBlockItem(/*UnexpectedNodes=*/None, Return, + /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None); auto Stmts = Factory.makeCodeBlockItemList({ReturnItem}); auto LBrace = Factory.makeLeftBraceToken("", ""); auto RBrace = Factory.makeRightBraceToken("\n", ""); - return Factory.makeCodeBlock(/*GarbageNodes=*/None, LBrace, - /*GarbageNodes=*/None, Stmts, - /*GarbageNodes=*/None, RBrace); + return Factory.makeCodeBlock(/*UnexpectedNodes=*/None, LBrace, + /*UnexpectedNodes=*/None, Stmts, + /*UnexpectedNodes=*/None, RBrace); } GenericWhereClauseSyntax getCannedWhereClause(const RC &Arena) { @@ -634,10 +634,10 @@ GenericWhereClauseSyntax getCannedWhereClause(const RC &Arena) { auto EqualEqual = Factory.makeEqualityOperator("", " "); auto Int = Factory.makeTypeIdentifier("Int", "", " "); auto SameType = Factory.makeSameTypeRequirement( - /*GarbageNodes=*/None, T, /*GarbageNodes=*/None, EqualEqual, - /*GarbageNodes=*/None, Int); - auto Req = Factory.makeGenericRequirement(/*GarbageNodes=*/None, SameType, - /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, T, /*UnexpectedNodes=*/None, EqualEqual, + /*UnexpectedNodes=*/None, Int); + auto Req = Factory.makeGenericRequirement(/*UnexpectedNodes=*/None, SameType, + /*UnexpectedNodes=*/None, None); auto Requirements = Factory.makeBlankGenericRequirementList().appending(Req); @@ -658,10 +658,10 @@ FunctionDeclSyntax getCannedFunctionDecl(const RC &Arena) { auto Body = getCannedBody(Arena); return Factory.makeFunctionDecl( - /*GarbageNodes=*/None, NoAttributes, /*GarbageNodes=*/None, Modifiers, - /*GarbageNodes=*/None, FuncKW, /*GarbageNodes=*/None, Foo, - /*GarbageNodes=*/None, GenericParams, /*GarbageNodes=*/None, Signature, - /*GarbageNodes=*/None, GenericWhere, /*GarbageNodes=*/None, Body); + /*UnexpectedNodes=*/None, NoAttributes, /*UnexpectedNodes=*/None, Modifiers, + /*UnexpectedNodes=*/None, FuncKW, /*UnexpectedNodes=*/None, Foo, + /*UnexpectedNodes=*/None, GenericParams, /*UnexpectedNodes=*/None, Signature, + /*UnexpectedNodes=*/None, GenericWhere, /*UnexpectedNodes=*/None, Body); } TEST(DeclSyntaxTests, FunctionDeclMakeAPIs) { @@ -729,7 +729,7 @@ TEST(DeclSyntaxTests, ProtocolMakeAPIs) { auto MyCollection = Factory.makeIdentifier("MyCollection", "", ""); auto ElementName = Factory.makeIdentifier("Element", "", ""); auto ElementParam = Factory.makePrimaryAssociatedType( - /*GarbageNodes=*/None, ElementName, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, ElementName, /*UnexpectedNodes=*/None, None); auto LeftAngle = Factory.makeLeftAngleToken("", ""); auto RightAngle = Factory.makeRightAngleToken("", " "); auto PrimaryAssocs = PrimaryAssociatedTypeClauseSyntaxBuilder(Arena) @@ -745,12 +745,12 @@ TEST(DeclSyntaxTests, ProtocolMakeAPIs) { .useRightBrace(RightBrace) .build(); Factory - .makeProtocolDecl(/*GarbageNodes=*/None, None, /*GarbageNodes=*/None, - None, /*GarbageNodes=*/None, Protocol, - /*GarbageNodes=*/None, MyCollection, - /*GarbageNodes=*/None, PrimaryAssocs, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, - None, /*GarbageNodes=*/None, Members) + .makeProtocolDecl(/*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, + None, /*UnexpectedNodes=*/None, Protocol, + /*UnexpectedNodes=*/None, MyCollection, + /*UnexpectedNodes=*/None, PrimaryAssocs, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, + None, /*UnexpectedNodes=*/None, Members) .print(OS); ASSERT_EQ(OS.str().str(), "protocol MyCollection {}"); diff --git a/unittests/Syntax/ExprSyntaxTests.cpp b/unittests/Syntax/ExprSyntaxTests.cpp index 1a72590d4065a..e288b8a0075e8 100644 --- a/unittests/Syntax/ExprSyntaxTests.cpp +++ b/unittests/Syntax/ExprSyntaxTests.cpp @@ -15,9 +15,9 @@ TEST(ExprSyntaxTests, IntegerLiteralExprMakeAPIs) { auto LiteralToken = Factory.makeIntegerLiteral("100", "", ""); auto Sign = Factory.makePrefixOperator("-", "", ""); auto IntegerLiteral = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, LiteralToken); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, LiteralToken); auto Literal = Factory.makePrefixOperatorExpr( - /*GarbageNodes=*/None, Sign, /*GarbageNodes=*/None, IntegerLiteral); + /*UnexpectedNodes=*/None, Sign, /*UnexpectedNodes=*/None, IntegerLiteral); llvm::SmallString<10> Scratch; llvm::raw_svector_ostream OS(Scratch); @@ -29,7 +29,7 @@ TEST(ExprSyntaxTests, IntegerLiteralExprMakeAPIs) { auto LiteralToken = Factory.makeIntegerLiteral("1_000", "", ""); auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "", Arena); auto Literal = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, LiteralToken); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, LiteralToken); llvm::SmallString<10> Scratch; llvm::raw_svector_ostream OS(Scratch); @@ -39,7 +39,7 @@ TEST(ExprSyntaxTests, IntegerLiteralExprMakeAPIs) { { auto IntLiteral = Factory.makeIntegerLiteral("0", "", " "); auto IntLiteralExpr = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, IntLiteral); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, IntLiteral); auto Literal = Factory.makeBlankPrefixOperatorExpr() .withOperatorToken(TokenSyntax::missingToken( tok::oper_prefix, "", Arena)) @@ -54,9 +54,9 @@ TEST(ExprSyntaxTests, IntegerLiteralExprMakeAPIs) { auto LiteralToken = Factory.makeIntegerLiteral("1_000_000_000_000", "", ""); auto PlusSign = Factory.makePrefixOperator("+", "", ""); auto IntLiteralExpr = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, LiteralToken); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, LiteralToken); auto OneThousand = Factory.makePrefixOperatorExpr( - /*GarbageNodes=*/None, PlusSign, /*GarbageNodes=*/None, IntLiteralExpr); + /*UnexpectedNodes=*/None, PlusSign, /*UnexpectedNodes=*/None, IntLiteralExpr); llvm::SmallString<10> Scratch; llvm::raw_svector_ostream OS(Scratch); @@ -74,9 +74,9 @@ TEST(ExprSyntaxTests, SymbolicReferenceExprGetAPIs) { auto Array = Factory.makeIdentifier("Array", "", ""); auto Int = Factory.makeIdentifier("Int", "", ""); auto IntType = Factory.makeSimpleTypeIdentifier( - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, None); auto GenericArg = Factory.makeGenericArgument( - /*GarbageNodes=*/None, IntType, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, IntType, /*UnexpectedNodes=*/None, None); GenericArgumentClauseSyntaxBuilder ArgBuilder(Arena); ArgBuilder.useLeftAngleBracket(Factory.makeLeftAngleToken("", "")) .useRightAngleBracket(Factory.makeRightAngleToken("", "")) @@ -85,7 +85,7 @@ TEST(ExprSyntaxTests, SymbolicReferenceExprGetAPIs) { auto GenericArgs = ArgBuilder.build(); auto Ref = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Array, /*GarbageNodes=*/None, GenericArgs); + /*UnexpectedNodes=*/None, Array, /*UnexpectedNodes=*/None, GenericArgs); ASSERT_EQ(Ref.getIdentifier().getRaw(), Array.getRaw()); @@ -107,10 +107,10 @@ TEST(ExprSyntaxTests, SymbolicReferenceExprMakeAPIs) { SyntaxFactory Factory(Arena); auto Array = Factory.makeIdentifier("Array", "", ""); auto Int = Factory.makeIdentifier("Int", "", ""); - auto IntType = Factory.makeSimpleTypeIdentifier(/*GarbageNodes=*/None, Int, - /*GarbageNodes=*/None, None); - auto GenericArg = Factory.makeGenericArgument(/*GarbageNodes=*/None, IntType, - /*GarbageNodes=*/None, None); + auto IntType = Factory.makeSimpleTypeIdentifier(/*UnexpectedNodes=*/None, Int, + /*UnexpectedNodes=*/None, None); + auto GenericArg = Factory.makeGenericArgument(/*UnexpectedNodes=*/None, IntType, + /*UnexpectedNodes=*/None, None); GenericArgumentClauseSyntaxBuilder ArgBuilder(Arena); ArgBuilder.useLeftAngleBracket(Factory.makeLeftAngleToken("", "")) .useRightAngleBracket(Factory.makeRightAngleToken("", "")) @@ -131,8 +131,8 @@ TEST(ExprSyntaxTests, SymbolicReferenceExprMakeAPIs) { auto BlankArgs = Factory.makeBlankGenericArgumentClause(); Factory - .makeSymbolicReferenceExpr(/*GarbageNodes=*/None, Foo, - /*GarbageNodes=*/None, BlankArgs) + .makeSymbolicReferenceExpr(/*UnexpectedNodes=*/None, Foo, + /*UnexpectedNodes=*/None, BlankArgs) .print(OS); EXPECT_EQ(OS.str().str(), "foo"); } @@ -141,8 +141,8 @@ TEST(ExprSyntaxTests, SymbolicReferenceExprMakeAPIs) { llvm::SmallString<48> Scratch; llvm::raw_svector_ostream OS(Scratch); Factory - .makeSymbolicReferenceExpr(/*GarbageNodes=*/None, Array, - /*GarbageNodes=*/None, GenericArgs) + .makeSymbolicReferenceExpr(/*UnexpectedNodes=*/None, Array, + /*UnexpectedNodes=*/None, GenericArgs) .print(OS); ASSERT_EQ(OS.str().str(), "Array"); } @@ -153,10 +153,10 @@ TEST(ExprSyntaxTests, SymbolicReferenceExprWithAPIs) { SyntaxFactory Factory(Arena); auto Array = Factory.makeIdentifier("Array", "", ""); auto Int = Factory.makeIdentifier("Int", "", ""); - auto IntType = Factory.makeSimpleTypeIdentifier(/*GarbageNodes=*/None, Int, - /*GarbageNodes=*/None, None); - auto GenericArg = Factory.makeGenericArgument(/*GarbageNodes=*/None, IntType, - /*GarbageNodes=*/None, None); + auto IntType = Factory.makeSimpleTypeIdentifier(/*UnexpectedNodes=*/None, Int, + /*UnexpectedNodes=*/None, None); + auto GenericArg = Factory.makeGenericArgument(/*UnexpectedNodes=*/None, IntType, + /*UnexpectedNodes=*/None, None); GenericArgumentClauseSyntaxBuilder ArgBuilder(Arena); ArgBuilder.useLeftAngleBracket(Factory.makeLeftAngleToken("", "")) .useRightAngleBracket(Factory.makeRightAngleToken("", "")) @@ -197,13 +197,13 @@ TEST(ExprSyntaxTests, TupleExprElementGetAPIs) { auto Foo = Factory.makeIdentifier("foo", "", ""); auto Colon = Factory.makeColonToken("", " "); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto Comma = Factory.makeCommaToken("", " "); { auto Arg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, X, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, SymbolicRef, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, X, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, SymbolicRef, /*UnexpectedNodes=*/None, Comma); ASSERT_EQ(X.getRaw(), Arg.getLabel()->getRaw()); ASSERT_EQ(Colon.getRaw(), Arg.getColon()->getRaw()); @@ -227,7 +227,7 @@ TEST(ExprSyntaxTests, TupleExprElementMakeAPIs) { auto Foo = Factory.makeIdentifier("foo", "", ""); auto Colon = Factory.makeColonToken("", " "); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto Comma = Factory.makeCommaToken("", " "); { @@ -248,9 +248,9 @@ TEST(ExprSyntaxTests, TupleExprElementMakeAPIs) { llvm::SmallString<48> Scratch; llvm::raw_svector_ostream OS(Scratch); Factory - .makeTupleExprElement(/*GarbageNodes=*/None, X, /*GarbageNodes=*/None, - Colon, /*GarbageNodes=*/None, SymbolicRef, - /*GarbageNodes=*/None, Comma) + .makeTupleExprElement(/*UnexpectedNodes=*/None, X, /*UnexpectedNodes=*/None, + Colon, /*UnexpectedNodes=*/None, SymbolicRef, + /*UnexpectedNodes=*/None, Comma) .print(OS); ASSERT_EQ(OS.str().str(), "x: foo, "); } @@ -263,7 +263,7 @@ TEST(ExprSyntaxTests, TupleExprElementWithAPIs) { auto Foo = Factory.makeIdentifier("foo", "", ""); auto Colon = Factory.makeColonToken("", " "); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto Comma = Factory.makeCommaToken("", " "); { @@ -290,13 +290,13 @@ TupleExprElementListSyntax getFullArgumentList(const RC &Arena) { auto Foo = Factory.makeIdentifier("foo", "", ""); auto Colon = Factory.makeColonToken("", " "); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto Comma = Factory.makeCommaToken("", " "); auto NoComma = TokenSyntax::missingToken(tok::comma, ",", Arena); auto Arg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, X, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, SymbolicRef, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, X, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, SymbolicRef, /*UnexpectedNodes=*/None, Comma); return Factory.makeBlankTupleExprElementList() .appending(Arg) @@ -312,24 +312,24 @@ getLabellessArgumentList(const RC &Arena) { auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); auto TwoDigits = Factory.makeIntegerLiteral("2", "", ""); auto ThreeDigits = Factory.makeIntegerLiteral("3", "", ""); - auto One = Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); + auto One = Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); auto NoLabel = TokenSyntax::missingToken(tok::identifier, "", Arena); auto NoColon = TokenSyntax::missingToken(tok::colon, ":", Arena); auto Comma = Factory.makeCommaToken("", " "); auto NoComma = TokenSyntax::missingToken(tok::comma, ",", Arena); - auto Two = Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, TwoDigits); + auto Two = Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, TwoDigits); auto Three = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, ThreeDigits); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, ThreeDigits); auto OneArg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, NoLabel, /*GarbageNodes=*/None, NoColon, - /*GarbageNodes=*/None, One, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, NoLabel, /*UnexpectedNodes=*/None, NoColon, + /*UnexpectedNodes=*/None, One, /*UnexpectedNodes=*/None, Comma); auto TwoArg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, NoLabel, /*GarbageNodes=*/None, NoColon, - /*GarbageNodes=*/None, Two, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, NoLabel, /*UnexpectedNodes=*/None, NoColon, + /*UnexpectedNodes=*/None, Two, /*UnexpectedNodes=*/None, Comma); auto ThreeArg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, NoLabel, /*GarbageNodes=*/None, NoColon, - /*GarbageNodes=*/None, Three, /*GarbageNodes=*/None, NoComma); + /*UnexpectedNodes=*/None, NoLabel, /*UnexpectedNodes=*/None, NoColon, + /*UnexpectedNodes=*/None, Three, /*UnexpectedNodes=*/None, NoComma); return Factory.makeBlankTupleExprElementList() .appending(OneArg) @@ -348,13 +348,13 @@ TEST(ExprSyntaxTests, TupleExprElementListGetAPIs) { auto Foo = Factory.makeIdentifier("foo", "", ""); auto Colon = Factory.makeColonToken("", " "); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto Comma = Factory.makeCommaToken("", " "); auto NoComma = TokenSyntax::missingToken(tok::comma, ",", Arena); auto Arg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, X, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, SymbolicRef, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, X, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, SymbolicRef, /*UnexpectedNodes=*/None, Comma); auto ArgList = Factory.makeBlankTupleExprElementList() .appending(Arg) @@ -411,13 +411,13 @@ TEST(ExprSyntaxTests, TupleExprElementListMakeAPIs) { auto Foo = Factory.makeIdentifier("foo", "", ""); auto Colon = Factory.makeColonToken("", " "); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto Comma = Factory.makeCommaToken("", " "); auto NoComma = TokenSyntax::missingToken(tok::comma, ",", Arena); auto Arg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, X, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, SymbolicRef, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, X, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, SymbolicRef, /*UnexpectedNodes=*/None, Comma); std::vector Args { Arg, Arg.withLabel(Y), Arg.withLabel(Z).withTrailingComma(NoComma) @@ -451,16 +451,16 @@ TEST(ExprSyntaxTests, FunctionCallExprGetAPIs) { SyntaxFactory Factory(Arena); auto Foo = Factory.makeIdentifier("foo", "", ""); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto LeftParen = Factory.makeLeftParenToken("", ""); auto ArgList = getFullArgumentList(Arena); auto RightParen = Factory.makeRightParenToken("", ""); auto Call = Factory.makeFunctionCallExpr( - /*GarbageNodes=*/None, SymbolicRef, /*GarbageNodes=*/None, LeftParen, - /*GarbageNodes=*/None, ArgList, - /*GarbageNodes=*/None, RightParen, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, SymbolicRef, /*UnexpectedNodes=*/None, LeftParen, + /*UnexpectedNodes=*/None, ArgList, + /*UnexpectedNodes=*/None, RightParen, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None); { auto GottenExpression1 = Call.getCalledExpression(); @@ -491,17 +491,17 @@ TEST(ExprSyntaxTests, FunctionCallExprMakeAPIs) { SyntaxFactory Factory(Arena); auto Foo = Factory.makeIdentifier("foo", "", ""); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto LeftParen = Factory.makeLeftParenToken("", ""); auto ArgList = getFullArgumentList(Arena); auto RightParen = Factory.makeRightParenToken("", ""); { auto Call = Factory.makeFunctionCallExpr( - /*GarbageNodes=*/None, SymbolicRef, /*GarbageNodes=*/None, LeftParen, - /*GarbageNodes=*/None, ArgList, - /*GarbageNodes=*/None, RightParen, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, SymbolicRef, /*UnexpectedNodes=*/None, LeftParen, + /*UnexpectedNodes=*/None, ArgList, + /*UnexpectedNodes=*/None, RightParen, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None); llvm::SmallString<64> Scratch; llvm::raw_svector_ostream OS(Scratch); Call.print(OS); @@ -521,7 +521,7 @@ TEST(ExprSyntaxTests, FunctionCallExprWithAPIs) { SyntaxFactory Factory(Arena); auto Foo = Factory.makeIdentifier("foo", "", ""); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto LeftParen = Factory.makeLeftParenToken("", ""); auto ArgList = getFullArgumentList(Arena); auto RightParen = Factory.makeRightParenToken("", ""); @@ -577,14 +577,14 @@ TEST(ExprSyntaxTests, FunctionCallExprBuilderAPIs) { auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); auto TwoDigits = Factory.makeIntegerLiteral("2", "", ""); auto ThreeDigits = Factory.makeIntegerLiteral("3", "", ""); - auto One = Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); + auto One = Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); auto NoLabel = TokenSyntax::missingToken(tok::identifier, "", Arena); auto NoColon = TokenSyntax::missingToken(tok::colon, ":", Arena); auto Comma = Factory.makeCommaToken("", " "); auto NoComma = TokenSyntax::missingToken(tok::comma, ",", Arena); auto Foo = Factory.makeIdentifier("foo", "", ""); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); { llvm::SmallString<64> Scratch; @@ -595,8 +595,8 @@ TEST(ExprSyntaxTests, FunctionCallExprBuilderAPIs) { } auto OneArg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, NoLabel, /*GarbageNodes=*/None, NoColon, - /*GarbageNodes=*/None, One, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, NoLabel, /*UnexpectedNodes=*/None, NoColon, + /*UnexpectedNodes=*/None, One, /*UnexpectedNodes=*/None, Comma); { llvm::SmallString<64> Scratch; llvm::raw_svector_ostream OS(Scratch); diff --git a/unittests/Syntax/StmtSyntaxTests.cpp b/unittests/Syntax/StmtSyntaxTests.cpp index 6d83d96b05b84..fc8d537b47f63 100644 --- a/unittests/Syntax/StmtSyntaxTests.cpp +++ b/unittests/Syntax/StmtSyntaxTests.cpp @@ -47,7 +47,7 @@ TEST(StmtSyntaxTests, FallthroughStmtMakeAPIs) { llvm::SmallString<48> Scratch; llvm::raw_svector_ostream OS(Scratch); - Factory.makeFallthroughStmt(/*GarbageNodes=*/None, FallthroughKW).print(OS); + Factory.makeFallthroughStmt(/*UnexpectedNodes=*/None, FallthroughKW).print(OS); ASSERT_EQ(OS.str().str(), "fallthrough"); } @@ -57,7 +57,7 @@ TEST(StmtSyntaxTests, FallthroughStmtMakeAPIs) { auto NewFallthroughKW = FallthroughKW.withLeadingTrivia(" "); - Factory.makeFallthroughStmt(/*GarbageNodes=*/None, NewFallthroughKW) + Factory.makeFallthroughStmt(/*UnexpectedNodes=*/None, NewFallthroughKW) .print(OS); ASSERT_EQ(OS.str().str(), " fallthrough"); } @@ -69,7 +69,7 @@ TEST(StmtSyntaxTests, FallthroughStmtMakeAPIs) { auto NewFallthroughKW = FallthroughKW.withLeadingTrivia(" ").withTrailingTrivia(" "); - Factory.makeFallthroughStmt(/*GarbageNodes=*/None, NewFallthroughKW) + Factory.makeFallthroughStmt(/*UnexpectedNodes=*/None, NewFallthroughKW) .print(OS); ASSERT_EQ(OS.str().str(), " fallthrough "); } @@ -90,8 +90,8 @@ TEST(StmtSyntaxTests, BreakStmtGetAPIs) { SyntaxFactory Factory(Arena); auto BreakKW = Factory.makeBreakKeyword("", " "); auto Label = Factory.makeIdentifier("sometimesYouNeedTo", "", ""); - auto Break = Factory.makeBreakStmt(/*GarbageNodes=*/None, BreakKW, - /*GarbageNodes=*/None, Label); + auto Break = Factory.makeBreakStmt(/*UnexpectedNodes=*/None, BreakKW, + /*UnexpectedNodes=*/None, Label); /// These should be directly shared through reference-counting. ASSERT_EQ(BreakKW.getRaw(), Break.getBreakKeyword().getRaw()); @@ -143,8 +143,8 @@ TEST(StmtSyntaxTests, BreakStmtMakeAPIs) { llvm::raw_svector_ostream OS(Scratch); auto BreakKW = Factory.makeBreakKeyword("", " "); auto Label = Factory.makeIdentifier("theBuild", "", ""); - auto Break = Factory.makeBreakStmt(/*GarbageNodes=*/None, BreakKW, - /*GarbageNodes=*/None, Label); + auto Break = Factory.makeBreakStmt(/*UnexpectedNodes=*/None, BreakKW, + /*UnexpectedNodes=*/None, Label); Break.print(OS); ASSERT_EQ(OS.str().str(), "break theBuild"); // don't you dare } @@ -163,8 +163,8 @@ TEST(StmtSyntaxTests, ContinueStmtGetAPIs) { SyntaxFactory Factory(Arena); auto ContinueKW = Factory.makeContinueKeyword("", " "); auto Label = Factory.makeIdentifier("always", "", ""); - auto Continue = Factory.makeContinueStmt(/*GarbageNodes=*/None, ContinueKW, - /*GarbageNodes=*/None, Label); + auto Continue = Factory.makeContinueStmt(/*UnexpectedNodes=*/None, ContinueKW, + /*UnexpectedNodes=*/None, Label); /// These should be directly shared through reference-counting. ASSERT_EQ(ContinueKW.getRaw(), Continue.getContinueKeyword().getRaw()); @@ -215,8 +215,8 @@ TEST(StmtSyntaxTests, ContinueStmtMakeAPIs) { llvm::raw_svector_ostream OS(Scratch); auto ContinueKW = Factory.makeContinueKeyword("", " "); auto Label = Factory.makeIdentifier("toLead", "", ""); - auto Continue = Factory.makeContinueStmt(/*GarbageNodes=*/None, ContinueKW, - /*GarbageNodes=*/None, Label); + auto Continue = Factory.makeContinueStmt(/*UnexpectedNodes=*/None, ContinueKW, + /*UnexpectedNodes=*/None, Label); Continue.print(OS); ASSERT_EQ(OS.str().str(), "continue toLead"); // by example } @@ -237,9 +237,9 @@ TEST(StmtSyntaxTests, ReturnStmtMakeAPIs) { auto Minus = Factory.makePrefixOperator("-", "", ""); auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); auto OneLiteral = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); auto MinusOne = Factory.makePrefixOperatorExpr( - /*GarbageNodes=*/None, Minus, /*GarbageNodes=*/None, OneLiteral); + /*UnexpectedNodes=*/None, Minus, /*UnexpectedNodes=*/None, OneLiteral); { llvm::SmallString<48> Scratch; @@ -252,7 +252,7 @@ TEST(StmtSyntaxTests, ReturnStmtMakeAPIs) { llvm::SmallString<48> Scratch; llvm::raw_svector_ostream OS(Scratch); Factory - .makeReturnStmt(/*GarbageNodes=*/None, ReturnKW, /*GarbageNodes=*/None, + .makeReturnStmt(/*UnexpectedNodes=*/None, ReturnKW, /*UnexpectedNodes=*/None, MinusOne) .print(OS); ASSERT_EQ(OS.str().str(), "return -1"); @@ -266,11 +266,11 @@ TEST(StmtSyntaxTests, ReturnStmtGetAPIs) { auto Minus = Factory.makePrefixOperator("-", "", ""); auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); auto OneLiteral = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); auto MinusOne = Factory.makePrefixOperatorExpr( - /*GarbageNodes=*/None, Minus, /*GarbageNodes=*/None, OneLiteral); - auto Return = Factory.makeReturnStmt(/*GarbageNodes=*/None, ReturnKW, - /*GarbageNodes=*/None, MinusOne); + /*UnexpectedNodes=*/None, Minus, /*UnexpectedNodes=*/None, OneLiteral); + auto Return = Factory.makeReturnStmt(/*UnexpectedNodes=*/None, ReturnKW, + /*UnexpectedNodes=*/None, MinusOne); ASSERT_EQ(ReturnKW.getRaw(), Return.getReturnKeyword().getRaw()); auto GottenExpression = Return.getExpression().getValue(); @@ -285,9 +285,9 @@ TEST(StmtSyntaxTests, ReturnStmtWithAPIs) { auto Minus = Factory.makePrefixOperator("-", "", ""); auto OneDigits = Factory.makeIntegerLiteral("1", "", ""); auto OneLiteral = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); auto MinusOne = Factory.makePrefixOperatorExpr( - /*GarbageNodes=*/None, Minus, /*GarbageNodes=*/None, OneLiteral); + /*UnexpectedNodes=*/None, Minus, /*UnexpectedNodes=*/None, OneLiteral); { llvm::SmallString<48> Scratch; diff --git a/unittests/Syntax/SyntaxCollectionTests.cpp b/unittests/Syntax/SyntaxCollectionTests.cpp index 3105b89d279cf..b863d77fc7b00 100644 --- a/unittests/Syntax/SyntaxCollectionTests.cpp +++ b/unittests/Syntax/SyntaxCollectionTests.cpp @@ -14,12 +14,12 @@ TupleExprElementSyntax getCannedArgument(const RC &Arena) { auto Foo = Factory.makeIdentifier("foo", "", ""); auto Colon = Factory.makeColonToken("", " "); auto SymbolicRef = Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Foo, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, Foo, /*UnexpectedNodes=*/None, None); auto Comma = Factory.makeCommaToken("", " "); return Factory.makeTupleExprElement( - /*GarbageNodes=*/None, X, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, SymbolicRef, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, X, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, SymbolicRef, /*UnexpectedNodes=*/None, Comma); } TEST(SyntaxCollectionTests, empty) { diff --git a/unittests/Syntax/TriviaTests.cpp b/unittests/Syntax/TriviaTests.cpp index 239f33ece30b3..6a3b55322942e 100644 --- a/unittests/Syntax/TriviaTests.cpp +++ b/unittests/Syntax/TriviaTests.cpp @@ -52,7 +52,7 @@ TEST(TriviaTests, Empty) { ASSERT_DEATH({ llvm::SmallString<1> Scratch; llvm::raw_svector_ostream OS(Scratch); - Trivia::garbageText("").print(OS); + Trivia::unexpectedText("").print(OS); ASSERT_EQ(OS.str().str(), ""); }, ""); #endif @@ -163,7 +163,7 @@ TEST(TriviaTests, Contains) { ASSERT_FALSE(Trivia().contains(TriviaKind::DocBlockComment)); ASSERT_FALSE(Trivia().contains(TriviaKind::DocLineComment)); ASSERT_FALSE(Trivia().contains(TriviaKind::Formfeed)); - ASSERT_FALSE(Trivia().contains(TriviaKind::GarbageText)); + ASSERT_FALSE(Trivia().contains(TriviaKind::UnexpectedText)); ASSERT_FALSE(Trivia().contains(TriviaKind::LineComment)); ASSERT_FALSE(Trivia().contains(TriviaKind::Newline)); ASSERT_FALSE(Trivia().contains(TriviaKind::Space)); diff --git a/unittests/Syntax/TypeSyntaxTests.cpp b/unittests/Syntax/TypeSyntaxTests.cpp index 2e2722422a59e..db8c2efc3d443 100644 --- a/unittests/Syntax/TypeSyntaxTests.cpp +++ b/unittests/Syntax/TypeSyntaxTests.cpp @@ -101,11 +101,11 @@ TEST(TypeSyntaxTests, TypeAttributeMakeAPIs) { llvm::raw_svector_ostream OS { Scratch }; auto cID = Factory.makeIdentifier("c", "", ""); Factory - .makeAttribute(/*GarbageNodes=*/None, At, /*GarbageNodes=*/None, - conventionID, /*GarbageNodes=*/None, LeftParen, - /*GarbageNodes=*/None, cID, /*GarbageNodes=*/None, + .makeAttribute(/*UnexpectedNodes=*/None, At, /*UnexpectedNodes=*/None, + conventionID, /*UnexpectedNodes=*/None, LeftParen, + /*UnexpectedNodes=*/None, cID, /*UnexpectedNodes=*/None, RightParen, - /*GarbageNodes=*/None, None) + /*UnexpectedNodes=*/None, None) .print(OS); ASSERT_EQ(OS.str().str(), "@convention(c)"); } @@ -115,11 +115,11 @@ TEST(TypeSyntaxTests, TypeAttributeMakeAPIs) { llvm::raw_svector_ostream OS { Scratch }; auto swiftID = Factory.makeIdentifier("swift", "", ""); Factory - .makeAttribute(/*GarbageNodes=*/None, At, /*GarbageNodes=*/None, - conventionID, /*GarbageNodes=*/None, LeftParen, - /*GarbageNodes=*/None, swiftID, /*GarbageNodes=*/None, + .makeAttribute(/*UnexpectedNodes=*/None, At, /*UnexpectedNodes=*/None, + conventionID, /*UnexpectedNodes=*/None, LeftParen, + /*UnexpectedNodes=*/None, swiftID, /*UnexpectedNodes=*/None, RightParen, - /*GarbageNodes=*/None, None) + /*UnexpectedNodes=*/None, None) .print(OS); ASSERT_EQ(OS.str().str(), "@convention(swift)"); } @@ -129,11 +129,11 @@ TEST(TypeSyntaxTests, TypeAttributeMakeAPIs) { llvm::raw_svector_ostream OS { Scratch }; auto blockID = Factory.makeIdentifier("block", "", ""); Factory - .makeAttribute(/*GarbageNodes=*/None, At, /*GarbageNodes=*/None, - conventionID, /*GarbageNodes=*/None, LeftParen, - /*GarbageNodes=*/None, blockID, /*GarbageNodes=*/None, + .makeAttribute(/*UnexpectedNodes=*/None, At, /*UnexpectedNodes=*/None, + conventionID, /*UnexpectedNodes=*/None, LeftParen, + /*UnexpectedNodes=*/None, blockID, /*UnexpectedNodes=*/None, RightParen, - /*GarbageNodes=*/None, None) + /*UnexpectedNodes=*/None, None) .print(OS); ASSERT_EQ(OS.str().str(), "@convention(block)"); } @@ -214,12 +214,12 @@ TEST(TypeSyntaxTests, TupleBuilderAPIs) { auto NoComma = TokenSyntax::missingToken(tok::comma, ",", Arena); auto IntId = Factory.makeIdentifier("Int", "", ""); auto IntType = Factory.makeSimpleTypeIdentifier( - /*GarbageNodes=*/None, IntId, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, IntId, /*UnexpectedNodes=*/None, None); auto Int = Factory.makeTupleTypeElement(IntType, NoComma); auto IntWithComma = Factory.makeTupleTypeElement(IntType, Comma); auto StringId = Factory.makeIdentifier("String", "", ""); auto StringType = Factory.makeSimpleTypeIdentifier( - /*GarbageNodes=*/None, StringId, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, StringId, /*UnexpectedNodes=*/None, None); auto String = Factory.makeTupleTypeElement(StringType, Comma); Builder.addElement(IntWithComma); Builder.addElement(String); @@ -284,9 +284,9 @@ TEST(TypeSyntaxTests, TupleMakeAPIs) { Factory.makeTupleTypeElement(Int, None)}); auto RightParen = Factory.makeRightParenToken("", ""); auto TupleType = - Factory.makeTupleType(/*GarbageNodes=*/None, LeftParen, - /*GarbageNodes=*/None, TupleElementList, - /*GarbageNodes=*/None, RightParen); + Factory.makeTupleType(/*UnexpectedNodes=*/None, LeftParen, + /*UnexpectedNodes=*/None, TupleElementList, + /*UnexpectedNodes=*/None, RightParen); TupleType.print(OS); ASSERT_EQ(OS.str().str(), "(Int, Bool, Int, Bool, Int)"); @@ -322,7 +322,7 @@ TEST(TypeSyntaxTests, OptionalTypeMakeAPIs) { auto Int = Factory.makeTypeIdentifier("Int", "", ""); auto Question = Factory.makePostfixQuestionMarkToken("", ""); auto OptionalInt = Factory.makeOptionalType( - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, Question); + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, Question); OptionalInt.print(OS); ASSERT_EQ(OS.str(), "Int?"); } @@ -352,7 +352,7 @@ TEST(TypeSyntaxTests, ImplicitlyUnwrappedOptionalTypeMakeAPIs) { auto Int = Factory.makeTypeIdentifier("Int", "", ""); auto Bang = Factory.makeExclamationMarkToken("", ""); auto IntBang = Factory.makeImplicitlyUnwrappedOptionalType( - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, Bang); + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, Bang); IntBang.print(OS); ASSERT_EQ(OS.str(), "Int!"); } @@ -383,8 +383,8 @@ TEST(TypeSyntaxTests, MetatypeTypeMakeAPIs) { auto Dot = Factory.makePeriodToken("", ""); auto Type = Factory.makeTypeToken("", ""); Factory - .makeMetatypeType(/*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, - Dot, /*GarbageNodes=*/None, Type) + .makeMetatypeType(/*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, + Dot, /*UnexpectedNodes=*/None, Type) .print(OS); ASSERT_EQ(OS.str(), "T.Type"); } @@ -459,8 +459,8 @@ TEST(TypeSyntaxTests, ArrayTypeMakeAPIs) { auto RightSquare = Factory.makeRightSquareBracketToken("", ""); auto Void = Factory.makeVoidTupleType(); Factory - .makeArrayType(/*GarbageNodes=*/None, LeftSquare, /*GarbageNodes=*/None, - Void, /*GarbageNodes=*/None, RightSquare) + .makeArrayType(/*UnexpectedNodes=*/None, LeftSquare, /*UnexpectedNodes=*/None, + Void, /*UnexpectedNodes=*/None, RightSquare) .print(OS); ASSERT_EQ(OS.str(), "[()]"); } @@ -502,10 +502,10 @@ TEST(TypeSyntaxTests, DictionaryTypeMakeAPIs) { auto Value = Factory.makeTypeIdentifier("Int", "", ""); auto Colon = Factory.makeColonToken("", " "); Factory - .makeDictionaryType(/*GarbageNodes=*/None, LeftSquare, - /*GarbageNodes=*/None, Key, /*GarbageNodes=*/None, - Colon, /*GarbageNodes=*/None, Value, - /*GarbageNodes=*/None, RightSquare) + .makeDictionaryType(/*UnexpectedNodes=*/None, LeftSquare, + /*UnexpectedNodes=*/None, Key, /*UnexpectedNodes=*/None, + Colon, /*UnexpectedNodes=*/None, Value, + /*UnexpectedNodes=*/None, RightSquare) .print(OS); ASSERT_EQ(OS.str(), "[String : Int]"); } @@ -544,10 +544,10 @@ TEST(TypeSyntaxTests, FunctionTypeMakeAPIs) { auto TypeList = Factory.makeTupleTypeElementList({xArg, yArg}); Factory .makeFunctionType( - /*GarbageNodes=*/None, LeftParen, /*GarbageNodes=*/None, TypeList, - /*GarbageNodes=*/None, RightParen, /*GarbageNodes=*/None, Async, - /*GarbageNodes=*/None, Throws, /*GarbageNodes=*/None, Arrow, - /*GarbageNodes=*/None, Int) + /*UnexpectedNodes=*/None, LeftParen, /*UnexpectedNodes=*/None, TypeList, + /*UnexpectedNodes=*/None, RightParen, /*UnexpectedNodes=*/None, Async, + /*UnexpectedNodes=*/None, Throws, /*UnexpectedNodes=*/None, Arrow, + /*UnexpectedNodes=*/None, Int) .print(OS); ASSERT_EQ(OS.str().str(), "(x: Int, y: Int) async throws -> Int"); } @@ -571,10 +571,10 @@ TEST(TypeSyntaxTests, FunctionTypeMakeAPIs) { auto TypeList = Factory.makeTupleTypeElementList({xArg, yArg}); Factory .makeFunctionType( - /*GarbageNodes=*/None, LeftParen, /*GarbageNodes=*/None, TypeList, - /*GarbageNodes=*/None, RightParen, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, Throws, /*GarbageNodes=*/None, Arrow, - /*GarbageNodes=*/None, Int) + /*UnexpectedNodes=*/None, LeftParen, /*UnexpectedNodes=*/None, TypeList, + /*UnexpectedNodes=*/None, RightParen, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, Throws, /*UnexpectedNodes=*/None, Arrow, + /*UnexpectedNodes=*/None, Int) .print(OS); ASSERT_EQ(OS.str().str(), "(x: Int, y: Int) throws -> Int"); } @@ -585,10 +585,10 @@ TEST(TypeSyntaxTests, FunctionTypeMakeAPIs) { {IntArg.withTrailingComma(Comma), IntArg}); Factory .makeFunctionType( - /*GarbageNodes=*/None, LeftParen, /*GarbageNodes=*/None, TypeList, - /*GarbageNodes=*/None, RightParen, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, Rethrows, - /*GarbageNodes=*/None, Arrow, /*GarbageNodes=*/None, Int) + /*UnexpectedNodes=*/None, LeftParen, /*UnexpectedNodes=*/None, TypeList, + /*UnexpectedNodes=*/None, RightParen, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, Rethrows, + /*UnexpectedNodes=*/None, Arrow, /*UnexpectedNodes=*/None, Int) .print(OS); ASSERT_EQ(OS.str().str(), "(Int, Int) rethrows -> Int"); } @@ -601,10 +601,10 @@ TEST(TypeSyntaxTests, FunctionTypeMakeAPIs) { auto ThrowsTok = TokenSyntax::missingToken(tok::kw_throws, "throws", Arena); Factory .makeFunctionType( - /*GarbageNodes=*/None, LeftParen, /*GarbageNodes=*/None, TypeList, - /*GarbageNodes=*/None, RightParen, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, ThrowsTok, /*GarbageNodes=*/None, Arrow, - /*GarbageNodes=*/None, Void) + /*UnexpectedNodes=*/None, LeftParen, /*UnexpectedNodes=*/None, TypeList, + /*UnexpectedNodes=*/None, RightParen, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, ThrowsTok, /*UnexpectedNodes=*/None, Arrow, + /*UnexpectedNodes=*/None, Void) .print(OS); ASSERT_EQ(OS.str().str(), "() -> ()"); } @@ -618,10 +618,10 @@ TEST(TypeSyntaxTests, FunctionTypeWithAPIs) { auto RightParen = Factory.makeRightParenToken("", " "); auto Int = Factory.makeTypeIdentifier("Int", "", ""); auto IntArg = Factory.makeTupleTypeElement( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None); auto Throws = Factory.makeThrowsKeyword("", " "); auto Rethrows = Factory.makeRethrowsKeyword("", " "); auto Arrow = Factory.makeArrowToken("", " "); @@ -633,15 +633,15 @@ TEST(TypeSyntaxTests, FunctionTypeWithAPIs) { auto y = Factory.makeIdentifier("y", "", ""); auto Colon = Factory.makeColonToken("", " "); auto xArg = Factory.makeTupleTypeElement( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, x, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, x, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, Comma); auto yArg = Factory.makeTupleTypeElement( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, y, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, y, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None); Factory.makeBlankFunctionType() .withLeftParen(LeftParen) @@ -705,15 +705,15 @@ TEST(TypeSyntaxTests, FunctionTypeBuilderAPIs) { auto y = Factory.makeIdentifier("y", "", ""); auto Colon = Factory.makeColonToken("", " "); auto xArg = Factory.makeTupleTypeElement( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, x, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, Comma); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, x, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, Comma); auto yArg = Factory.makeTupleTypeElement( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, y, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, Int, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, y, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, Int, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None); Builder.useLeftParen(LeftParen) .useRightParen(RightParen) @@ -732,11 +732,11 @@ TEST(TypeSyntaxTests, FunctionTypeBuilderAPIs) { llvm::raw_svector_ostream OS(Scratch); FunctionTypeSyntaxBuilder Builder(Arena); auto IntArg = Factory.makeTupleTypeElement( - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, Int, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, Int, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None); Builder.useLeftParen(LeftParen) .useRightParen(RightParen) .addArgument(IntArg.withTrailingComma(Comma)) diff --git a/unittests/Syntax/UnknownSyntaxTests.cpp b/unittests/Syntax/UnknownSyntaxTests.cpp index b3c79d56c30f7..a80548988eef3 100644 --- a/unittests/Syntax/UnknownSyntaxTests.cpp +++ b/unittests/Syntax/UnknownSyntaxTests.cpp @@ -15,17 +15,17 @@ SymbolicReferenceExprSyntax getCannedSymbolicRef(const RC &Arena) { // First, make a symbolic reference to an 'Array' auto Array = Factory.makeIdentifier("Array", {}, {}); auto Int = Factory.makeIdentifier("Int", {}, {}); - auto IntType = Factory.makeSimpleTypeIdentifier(/*GarbageNodes=*/None, Int, - /*GarbageNodes=*/None, None); - auto IntArg = Factory.makeGenericArgument(/*GarbageNodes=*/None, IntType, - /*GarbageNodes=*/None, None); + auto IntType = Factory.makeSimpleTypeIdentifier(/*UnexpectedNodes=*/None, Int, + /*UnexpectedNodes=*/None, None); + auto IntArg = Factory.makeGenericArgument(/*UnexpectedNodes=*/None, IntType, + /*UnexpectedNodes=*/None, None); GenericArgumentClauseSyntaxBuilder ArgBuilder(Arena); ArgBuilder.useLeftAngleBracket(Factory.makeLeftAngleToken({}, {})) .useRightAngleBracket(Factory.makeRightAngleToken({}, {})) .addArgument(IntArg); return Factory.makeSymbolicReferenceExpr( - /*GarbageNodes=*/None, Array, /*GarbageNodes=*/None, ArgBuilder.build()); + /*UnexpectedNodes=*/None, Array, /*UnexpectedNodes=*/None, ArgBuilder.build()); } FunctionCallExprSyntax getCannedFunctionCall(const RC &Arena) { @@ -38,21 +38,21 @@ FunctionCallExprSyntax getCannedFunctionCall(const RC &Arena) { auto OneDigits = Factory.makeIntegerLiteral("1", {}, {}); auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "", Arena); auto OneLiteral = - Factory.makeIntegerLiteralExpr(/*GarbageNodes=*/None, OneDigits); - auto One = Factory.makePrefixOperatorExpr(/*GarbageNodes=*/None, NoSign, - /*GarbageNodes=*/None, OneLiteral); + Factory.makeIntegerLiteralExpr(/*UnexpectedNodes=*/None, OneDigits); + auto One = Factory.makePrefixOperatorExpr(/*UnexpectedNodes=*/None, NoSign, + /*UnexpectedNodes=*/None, OneLiteral); auto NoComma = TokenSyntax::missingToken(tok::comma, ",", Arena); auto Arg = Factory.makeTupleExprElement( - /*GarbageNodes=*/None, Label, /*GarbageNodes=*/None, Colon, - /*GarbageNodes=*/None, One, /*GarbageNodes=*/None, NoComma); + /*UnexpectedNodes=*/None, Label, /*UnexpectedNodes=*/None, Colon, + /*UnexpectedNodes=*/None, One, /*UnexpectedNodes=*/None, NoComma); auto Args = Factory.makeTupleExprElementList({Arg}); return Factory.makeFunctionCallExpr( - /*GarbageNodes=*/None, getCannedSymbolicRef(Arena), /*GarbageNodes=*/None, - LParen, /*GarbageNodes=*/None, Args, - /*GarbageNodes=*/None, RParen, /*GarbageNodes=*/None, None, - /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, getCannedSymbolicRef(Arena), /*UnexpectedNodes=*/None, + LParen, /*UnexpectedNodes=*/None, Args, + /*UnexpectedNodes=*/None, RParen, /*UnexpectedNodes=*/None, None, + /*UnexpectedNodes=*/None, None); } TEST(UnknownSyntaxTests, UnknownSyntaxMakeAPIs) { @@ -157,9 +157,9 @@ TEST(UnknownSyntaxTests, EmbedUnknownExpr) { SmallString<48> KnownScratch; llvm::raw_svector_ostream KnownOS(KnownScratch); auto CallWithKnownExpr = Factory.makeFunctionCallExpr( - /*GarbageNodes=*/None, SymbolicRef, /*GarbageNodes=*/None, LParen, - /*GarbageNodes=*/None, EmptyArgs, /*GarbageNodes=*/None, RParen, - /*GarbageNodes=*/None, None, /*GarbageNodes=*/None, None); + /*UnexpectedNodes=*/None, SymbolicRef, /*UnexpectedNodes=*/None, LParen, + /*UnexpectedNodes=*/None, EmptyArgs, /*UnexpectedNodes=*/None, RParen, + /*UnexpectedNodes=*/None, None, /*UnexpectedNodes=*/None, None); CallWithKnownExpr.print(KnownOS); // Let's make a function call expression where the called expression is diff --git a/utils/gyb_syntax_support/Child.py b/utils/gyb_syntax_support/Child.py index f874300cba299..ac37e76f35bc1 100644 --- a/utils/gyb_syntax_support/Child.py +++ b/utils/gyb_syntax_support/Child.py @@ -84,5 +84,5 @@ def main_token(self): return self.token_choices[0] return None - def is_garbage_nodes(self): - return self.syntax_kind == 'GarbageNodes' + def is_unexpected_nodes(self): + return self.syntax_kind == 'UnexpectedNodes' diff --git a/utils/gyb_syntax_support/CommonNodes.py b/utils/gyb_syntax_support/CommonNodes.py index 9f9a03eee7226..daaa6b8f94544 100644 --- a/utils/gyb_syntax_support/CommonNodes.py +++ b/utils/gyb_syntax_support/CommonNodes.py @@ -63,7 +63,7 @@ requires_leading_newline=True), ]), - Node('GarbageNodes', kind='SyntaxCollection', element='Syntax', + Node('UnexpectedNodes', kind='SyntaxCollection', element='Syntax', description=''' A collection of syntax nodes that occurred in the source code but could not be used to form a valid syntax tree. diff --git a/utils/gyb_syntax_support/Node.py b/utils/gyb_syntax_support/Node.py index 483159f5b543e..3192e422d7f0f 100644 --- a/utils/gyb_syntax_support/Node.py +++ b/utils/gyb_syntax_support/Node.py @@ -24,27 +24,27 @@ def __init__(self, name, description=None, kind=None, traits=None, self.traits = traits or [] self.children = [] - # Add implicitly generated GarbageNodes children in between any two + # Add implicitly generated UnexpectedNodes children in between any two # defined children if kind != 'SyntaxCollection': for i in range(2 * len(children)): if i % 2 == 0: if i == 0: - name = 'GarbageBefore' + children[0].name + name = 'UnexpectedBefore' + children[0].name else: - name = 'GarbageBetween%sAnd%s' % \ + name = 'UnexpectedBetween%sAnd%s' % \ (children[int(i / 2) - 1].name, children[int(i / 2)].name) self.children.append(Child( name, - kind='GarbageNodes', + kind='UnexpectedNodes', collection_element_name=name, is_optional=True )) else: self.children.append(children[int((i - 1) / 2)]) - self.non_garbage_children = \ - [child for child in children if not child.is_garbage_nodes()] + self.non_unexpected_children = \ + [child for child in children if not child.is_unexpected_nodes()] self.base_kind = kind if self.base_kind == 'SyntaxCollection': diff --git a/utils/gyb_syntax_support/NodeSerializationCodes.py b/utils/gyb_syntax_support/NodeSerializationCodes.py index d4c1481bbca3a..63d4b02238e6f 100644 --- a/utils/gyb_syntax_support/NodeSerializationCodes.py +++ b/utils/gyb_syntax_support/NodeSerializationCodes.py @@ -267,7 +267,7 @@ 'MissingStmt': 263, 'MissingType': 264, 'MissingPattern': 265, - 'GarbageNodes' : 266, + 'UnexpectedNodes' : 266, 'LabeledStmt': 267, 'InfixOperatorExpr': 268, 'MoveExpr': 269, diff --git a/utils/gyb_syntax_support/Trivia.py b/utils/gyb_syntax_support/Trivia.py index d859ec67775b3..22d97919c3148 100644 --- a/utils/gyb_syntax_support/Trivia.py +++ b/utils/gyb_syntax_support/Trivia.py @@ -58,7 +58,8 @@ def is_collection(self): 'A documentation block comment, starting with \'/**\' and ending ' 'with \'*/\'.', is_comment=True, serialization_code=11), - Trivia('GarbageText', 'Any skipped garbage text.', serialization_code=12), + Trivia('UnexpectedText', 'Any skipped unexpected text.', + serialization_code=12), Trivia('Shebang', 'A script command, starting with \'#!\'.', serialization_code=13), ] From a091425ea16a4ea6e9a292e8174a1925e132fdc4 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 12 Aug 2022 00:06:53 -0400 Subject: [PATCH 115/491] AST: GenericEnvironment::forOpenedExistential() uniques the environment --- lib/AST/ASTContext.cpp | 65 +++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index ff439ef5633e9..910f7b81363d3 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4436,42 +4436,13 @@ CanOpenedArchetypeType OpenedArchetypeType::get(CanType existential, Type interfaceType, GenericSignature parentSig, Optional knownID) { - assert(existential->isExistentialType()); assert(!interfaceType->hasArchetype() && "must be interface type"); - // FIXME: Opened archetypes can't be transformed because the - // the identity of the archetype has to be preserved. This - // means that simplifying an opened archetype in the constraint - // system to replace type variables with fixed types is not - // yet supported. For now, assert that an opened archetype never - // contains type variables to catch cases where type variables - // would be applied to the type-checked AST. - assert(!existential->hasTypeVariable() && - "opened existentials containing type variables cannot be simplified"); - auto &ctx = existential->getASTContext(); - auto &openedExistentialEnvironments = - ctx.getImpl().OpenedExistentialEnvironments; - // If we know the ID already... - if (knownID) { - // ... and we already have an archetype for that ID, return it. - auto found = openedExistentialEnvironments.find(*knownID); - - if (found != openedExistentialEnvironments.end()) { - assert(found->second->getOpenedExistentialType()->isEqual(existential) && - "Retrieved the wrong generic environment?"); - auto result = found->second->mapTypeIntoContext(interfaceType) - ->castTo(); - return CanOpenedArchetypeType(result); - } - } else { - // Create a new ID. + if (!knownID) knownID = UUID::fromTime(); - } - /// Create a generic environment for this opened archetype. - auto genericEnv = + auto *genericEnv = GenericEnvironment::forOpenedExistential(existential, parentSig, *knownID); - openedExistentialEnvironments[*knownID] = genericEnv; // Map the interface type into that environment. auto result = genericEnv->mapTypeIntoContext(interfaceType) @@ -4653,7 +4624,32 @@ GenericEnvironment *GenericEnvironment::forPrimary(GenericSignature signature) { GenericEnvironment * GenericEnvironment::forOpenedExistential( Type existential, GenericSignature parentSig, UUID uuid) { + assert(existential->isExistentialType()); + // FIXME: Opened archetypes can't be transformed because the + // the identity of the archetype has to be preserved. This + // means that simplifying an opened archetype in the constraint + // system to replace type variables with fixed types is not + // yet supported. For now, assert that an opened archetype never + // contains type variables to catch cases where type variables + // would be applied to the type-checked AST. + assert(!existential->hasTypeVariable() && + "opened existentials containing type variables cannot be simplified"); + auto &ctx = existential->getASTContext(); + + auto &openedExistentialEnvironments = + ctx.getImpl().OpenedExistentialEnvironments; + auto found = openedExistentialEnvironments.find(uuid); + + if (found != openedExistentialEnvironments.end()) { + auto *existingEnv = found->second; + assert(existingEnv->getOpenedExistentialType()->isEqual(existential)); + assert(existingEnv->getOpenedExistentialParentSignature().getPointer() == parentSig.getPointer()); + assert(existingEnv->getOpenedExistentialUUID() == uuid); + + return existingEnv; + } + auto signature = ctx.getOpenedExistentialSignature(existential, parentSig); // Allocate and construct the new environment. @@ -4662,7 +4658,12 @@ GenericEnvironment::forOpenedExistential( OpenedGenericEnvironmentData, Type>( 0, 0, 1, numGenericParams); void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment)); - return new (mem) GenericEnvironment(signature, existential, parentSig, uuid); + auto *genericEnv = + new (mem) GenericEnvironment(signature, existential, parentSig, uuid); + + openedExistentialEnvironments[uuid] = genericEnv; + + return genericEnv; } /// Create a new generic environment for an opaque type with the given set of From 482e1ac80f1d0ef1644733eb266160e4cdedb6f0 Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Mon, 15 Aug 2022 15:31:43 -0700 Subject: [PATCH 116/491] [Interop][SwiftToCxx] Implement the new enum header design --- .../UserGuide-CallingSwiftFromC++.md | 6 +- lib/PrintAsClang/DeclAndTypePrinter.cpp | 182 +++++---- lib/PrintAsClang/PrintClangValueType.cpp | 30 +- .../enums/resilient-enum-in-cxx-execution.cpp | 25 +- .../enums/resilient-enum-in-cxx.swift | 28 +- .../enums/swift-enum-case-functions.swift | 350 +++++++++++++++--- 6 files changed, 463 insertions(+), 158 deletions(-) diff --git a/docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md b/docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md index dc5c9460862de..3d7e76bc790f4 100644 --- a/docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md +++ b/docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md @@ -595,7 +595,7 @@ enum value will abort the program. A resilient Swift enumeration value could represent a case that's unknown to the client. Swift forces the client to check if the value is `@uknown default` when switching over the enumeration to account for that. C++ follows a similar principle, -by exposing an `unknown_default` case that can then be matched in a switch. +by exposing an `unknownDefault` case that can then be matched in a switch. For example, given the following resilient enumeration: @@ -620,14 +620,14 @@ void test(const DateFormatStyle &style) { case DateFormatStyle::full: ... break; - case DateFormatStyle::unknown_default: // just like Swift's @unknown default + case DateFormatStyle::unknownDefault: // just like Swift's @unknown default // Some case value added in a future version of enum. break; } } ``` -The `unknown_default` case value is not a constructible case and you will get a compiler error if you try to construct it in C++. +The `unknownDefault` case value is not a constructible case and you will get a compiler error if you try to construct it in C++. ## Using Swift Class Types diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 669e8c86e42e6..2d811e3088f65 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -414,94 +414,55 @@ class DeclAndTypePrinter::Implementation return p1.second.tag < p2.second.tag; }); - if (elementTagMapping.empty()) { - os << "\n"; - return; - } - - os << " enum class cases {\n"; - for (const auto &pair : elementTagMapping) { - os << " "; + os << '\n'; + os << " enum class cases {"; + llvm::interleave(elementTagMapping, os, [&](const auto &pair){ + os << "\n "; syntaxPrinter.printIdentifier(pair.first->getNameStr()); - os << ",\n"; - } - os << " };\n"; // enum class cases' closing bracket - - // Printing operator cases() - os << " inline operator cases() const {\n"; - if (ED->isResilient()) { - os << " auto tag = _getEnumTag();\n"; - for (const auto &pair : elementTagMapping) { - os << " if (tag == " << cxx_synthesis::getCxxImplNamespaceName(); - os << "::" << pair.second.globalVariableName << ") return cases::"; - syntaxPrinter.printIdentifier(pair.first->getNameStr()); - os << ";\n"; - } - // TODO: change to Swift's fatalError when it's available in C++ - os << " abort();\n"; - } else { // non-resilient enum - os << " switch (_getEnumTag()) {\n"; - for (const auto &pair : elementTagMapping) { - os << " case " << pair.second.tag << ": return cases::"; - syntaxPrinter.printIdentifier(pair.first->getNameStr()); - os << ";\n"; - } - // TODO: change to Swift's fatalError when it's available in C++ - os << " default: abort();\n"; - os << " }\n"; // switch's closing bracket - } - os << " }\n"; // operator cases()'s closing bracket - + }, ","); + // TODO: allow custom name for this special case + auto resilientUnknownDefaultCaseName = "unknownDefault"; if (ED->isResilient()) { - os << " inline bool inResilientUnknownCase() const {\n"; - os << " auto tag = _getEnumTag();\n"; - os << " return"; - llvm::interleave( - elementTagMapping, os, - [&](const auto &pair) { - os << "\n tag != " << cxx_synthesis::getCxxImplNamespaceName() - << "::" << pair.second.globalVariableName; - }, - " &&"); - os << ";\n"; - os << " }\n"; + os << ",\n " << resilientUnknownDefaultCaseName; } - - // Printing case-related functions + os << "\n };\n\n"; // enum class cases' closing bracket + + // Printing struct, is, and get functions for each case DeclAndTypeClangFunctionPrinter clangFuncPrinter( os, owningPrinter.prologueOS, owningPrinter.typeMapping, owningPrinter.interopContext); - - for (const auto &pair : elementTagMapping) { + + auto printIsFunction = [&](StringRef caseName, EnumDecl *ED) { os << " inline bool is"; - auto name = pair.first->getNameStr().str(); + std::string name; + llvm::raw_string_ostream nameStream(name); + ClangSyntaxPrinter(nameStream).printIdentifier(caseName); name[0] = std::toupper(name[0]); os << name << "() const {\n"; - os << " return _getEnumTag() == "; - if (ED->isResilient()) { - os << cxx_synthesis::getCxxImplNamespaceName() - << "::" << pair.second.globalVariableName; - } else { - os << pair.second.tag; - } - os << ";\n }\n"; - - if (!pair.first->hasAssociatedValues()) { - continue; - } - - auto associatedValueList = pair.first->getParameterList(); + os << " return *this == "; + syntaxPrinter.printBaseName(ED); + os << "::"; + syntaxPrinter.printIdentifier(caseName); + os << ";\n"; + os << " }\n"; + }; + + auto printGetFunction = [&](EnumElementDecl *elementDecl) { + auto associatedValueList = elementDecl->getParameterList(); // TODO: add tuple type support if (associatedValueList->size() > 1) { - continue; + return; } auto firstType = associatedValueList->front()->getType(); auto firstTypeDecl = firstType->getNominalOrBoundGenericNominal(); OptionalTypeKind optKind; std::tie(firstType, optKind) = getObjectTypeAndOptionality(firstTypeDecl, firstType); - - // FIXME: (tongjie) may have to forward declare return type + + auto name = elementDecl->getNameStr().str(); + name[0] = std::toupper(name[0]); + + // FIXME: may have to forward declare return type os << " inline "; clangFuncPrinter.printClangFunctionReturnType( firstType, optKind, firstTypeDecl->getModuleContext(), @@ -509,12 +470,12 @@ class DeclAndTypePrinter::Implementation os << " get" << name << "() const {\n"; os << " if (!is" << name << "()) abort();\n"; os << " alignas("; - syntaxPrinter.printBaseName(ED); + syntaxPrinter.printBaseName(elementDecl->getParentEnum()); os << ") unsigned char buffer[sizeof("; - syntaxPrinter.printBaseName(ED); + syntaxPrinter.printBaseName(elementDecl->getParentEnum()); os << ")];\n"; os << " auto *thisCopy = new(buffer) "; - syntaxPrinter.printBaseName(ED); + syntaxPrinter.printBaseName(elementDecl->getParentEnum()); os << "(*this);\n"; os << " char * _Nonnull payloadFromDestruction = " "thisCopy->_destructiveProjectEnumData();\n"; @@ -531,7 +492,7 @@ class DeclAndTypePrinter::Implementation } else { os << " return "; syntaxPrinter.printModuleNamespaceQualifiersIfNeeded( - firstTypeDecl->getModuleContext(), ED->getModuleContext()); + firstTypeDecl->getModuleContext(), elementDecl->getParentEnum()->getModuleContext()); os << cxx_synthesis::getCxxImplNamespaceName(); os << "::"; ClangValueTypePrinter::printCxxImplClassName(os, firstTypeDecl); @@ -542,8 +503,77 @@ class DeclAndTypePrinter::Implementation os << "::initializeWithTake(result, payloadFromDestruction);\n"; os << " });\n"; } - os << " }\n"; + os << " }\n"; // closing bracket of get function + }; + + auto printStruct = [&](StringRef caseName, EnumElementDecl *elementDecl) { + os << " static struct { // impl struct for case " << caseName << '\n'; + os << " inline constexpr operator cases() const {\n"; + os << " return cases::"; + syntaxPrinter.printIdentifier(caseName); + os << ";\n"; + os << " }\n"; + if (elementDecl != nullptr) { + os << " inline "; + syntaxPrinter.printBaseName(elementDecl->getParentEnum()); + os << " operator()("; + // TODO: implement parameter for associated value + os << ") const {\n"; + // TODO: print _make for now; need to implement actual code making an enum + os << " return "; + syntaxPrinter.printBaseName(elementDecl->getParentEnum()); + os << "::_make();\n"; + os << " }\n"; + } + os << " } "; + syntaxPrinter.printIdentifier(caseName); + os << ";\n"; + }; + + for (const auto &pair : elementTagMapping) { + // Printing struct + printStruct(pair.first->getNameStr(), pair.first); + // Printing `is` function + printIsFunction(pair.first->getNameStr(), ED); + if (pair.first->hasAssociatedValues()) { + // Printing `get` function + printGetFunction(pair.first); + } + os << '\n'; + } + + if (ED->isResilient()) { + // Printing struct for unknownDefault + printStruct(resilientUnknownDefaultCaseName, /* elementDecl */ nullptr); + // Printing isUnknownDefault + printIsFunction(resilientUnknownDefaultCaseName, ED); + os << '\n'; + } + os << '\n'; + + // Printing operator cases() + os << " inline operator cases() const {\n"; + if (ED->isResilient()) { + os << " auto tag = _getEnumTag();\n"; + for (const auto &pair : elementTagMapping) { + os << " if (tag == " << cxx_synthesis::getCxxImplNamespaceName(); + os << "::" << pair.second.globalVariableName << ") return cases::"; + syntaxPrinter.printIdentifier(pair.first->getNameStr()); + os << ";\n"; + } + os << " return cases::" << resilientUnknownDefaultCaseName << ";\n"; + } else { // non-resilient enum + os << " switch (_getEnumTag()) {\n"; + for (const auto &pair : elementTagMapping) { + os << " case " << pair.second.tag << ": return cases::"; + syntaxPrinter.printIdentifier(pair.first->getNameStr()); + os << ";\n"; + } + // TODO: change to Swift's fatalError when it's available in C++ + os << " default: abort();\n"; + os << " }\n"; // switch's closing bracket } + os << " }\n"; // operator cases()'s closing bracket os << "\n"; }); os << outOfLineDefinitions; diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index ffdceeb518b87..a58b641abba55 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -254,7 +254,35 @@ void ClangValueTypePrinter::printValueTypeDecl( os << " friend class " << cxx_synthesis::getCxxImplNamespaceName() << "::"; printCxxImplClassName(os, typeDecl); os << ";\n"; - os << "};\n\n"; + os << "};\n"; + // Print the definition of enum static struct data memebers + if (isa(typeDecl)) { + auto tagMapping = interopContext.getIrABIDetails().getEnumTagMapping(cast(typeDecl)); + for (const auto& pair : tagMapping) { + os << "decltype("; + printer.printBaseName(typeDecl); + os << "::"; + printer.printIdentifier(pair.first->getNameStr()); + os << ") "; + printer.printBaseName(typeDecl); + os << "::"; + printer.printIdentifier(pair.first->getNameStr()); + os << ";\n"; + } + if (isOpaqueLayout) { + os << "decltype("; + printer.printBaseName(typeDecl); + // TODO: allow custom name for this special case + os << "::"; + printer.printIdentifier("unknownDefault"); + os << ") "; + printer.printBaseName(typeDecl); + os << "::"; + printer.printIdentifier("unknownDefault"); + os << ";\n"; + } + } + os << '\n'; const auto *moduleContext = typeDecl->getModuleContext(); // Print out the "hidden" _impl class. diff --git a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx-execution.cpp b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx-execution.cpp index 6502d24dd36ac..8f87d76638188 100644 --- a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx-execution.cpp +++ b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx-execution.cpp @@ -18,16 +18,28 @@ #include #include "enums.h" +using namespace Enums; + +void useFooInSwitch(const Foo& f) { + switch (f) { + case Foo::a: + std::cout << "Foo::a\n"; + break;; + case Foo::unknownDefault: + std::cout << "Foo::unknownDefault\n"; + break; + } +} + int main() { - using namespace Enums; auto f1 = makeFoo(10); auto f2 = makeFoo(-10); printFoo(f1); printFoo(f2); - assert(!f2.inResilientUnknownCase()); - if (f1.inResilientUnknownCase()) { + assert(!f2.isUnknownDefault()); + if (f1.isUnknownDefault()) { std::cout << "f1.inResilientUnknownCase()\n"; assert(!f1.isA()); } else { @@ -35,6 +47,9 @@ int main() { assert(f1.getA() == 10.0); } + useFooInSwitch(f1); + useFooInSwitch(f2); + return 0; } @@ -43,3 +58,7 @@ int main() { // CHECK-NEXT: a(-10.0) // NEW_CASE: f1.inResilientUnknownCase() + +// NEW_CASE: Foo::unknownDefault +// OLD_CASE: Foo::a +// CHECK-NEXT: Foo::a diff --git a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift index 6022a2f763999..2795cc2d9ffbd 100644 --- a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift +++ b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift @@ -42,22 +42,22 @@ public func printFoo(_ x: Foo) { // CHECK-EMPTY: // CHECK-NEXT: class Foo final { // CHECK-NEXT: public: +// CHECK: enum class cases { +// CHECK-NEXT: a, +// NEW_CASE-NEXT: b, +// CHECK-NEXT: unknownDefault +// CHECK-NEXT: } +// CHECK: static struct { // impl struct for case unknownDefault +// CHECK-NEXT: constexpr operator cases() const { +// CHECK-NEXT: return cases::unknownDefault; +// CHECK-NEXT: } +// CHECK-NEXT: } unknownDefault; +// CHECK-NEXT: inline bool isUnknownDefault() const { +// CHECK-NEXT: return *this == Foo::unknownDefault; +// CHECK-NEXT: } // CHECK: inline operator cases() const { // CHECK-NEXT: auto tag = _getEnumTag(); // CHECK-NEXT: if (tag == _impl::$s5Enums3FooO1ayACSdcACmFWC) return cases::a; // NEW_CASE-NEXT: if (tag == _impl::$s5Enums3FooO1byACSicACmFWC) return cases::b; -// CHECK-NEXT: abort(); -// CHECK-NEXT: } -// CHECK-NEXT: inline bool inResilientUnknownCase() const { -// CHECK-NEXT: auto tag = _getEnumTag(); -// CHECK-NEXT: return -// OLD_CASE-NEXT: tag != _impl::$s5Enums3FooO1ayACSdcACmFWC; -// NEW_CASE-NEXT: tag != _impl::$s5Enums3FooO1ayACSdcACmFWC && -// NEW_CASE-NEXT: tag != _impl::$s5Enums3FooO1byACSicACmFWC; -// CHECK-NEXT: } -// CHECK-NEXT: inline bool isA() const { -// CHECK-NEXT: return _getEnumTag() == _impl::$s5Enums3FooO1ayACSdcACmFWC; +// CHECK-NEXT: return cases::unknownDefault; // CHECK-NEXT: } -// NEW_CASE: inline bool isB() const { -// NEW_CASE-NEXT: return _getEnumTag() == _impl::$s5Enums3FooO1byACSicACmFWC; -// NEW_CASE-NEXT: } diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift b/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift index 1b7bad1258e2a..0679c2bd61506 100644 --- a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift +++ b/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift @@ -4,7 +4,7 @@ // RUN: %check-interop-cxx-header-in-clang(%t/enums.h -Wno-unused-private-field -Wno-unused-function) -// test case-related member functions: operator cases() and isXYZ predicates +// test case-related member functions and structs public enum DataCase { case one(_ x: Int) } @@ -153,7 +153,53 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: class BoolWithCase final { -// CHECK: inline operator cases() const { +// CHECK: static struct { // impl struct for case second +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::second; +// CHECK-NEXT: } +// CHECK-NEXT: inline BoolWithCase operator()() const { +// CHECK-NEXT: return BoolWithCase::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } second; +// CHECK-NEXT: inline bool isSecond() const { +// CHECK-NEXT: return *this == BoolWithCase::second; +// CHECK-NEXT: } +// CHECK-NEXT: inline bool getSecond() const { +// CHECK-NEXT: if (!isSecond()) abort(); +// CHECK-NEXT: alignas(BoolWithCase) unsigned char buffer[sizeof(BoolWithCase)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) BoolWithCase(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: bool result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case first +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::first; +// CHECK-NEXT: } +// CHECK-NEXT: inline BoolWithCase operator()() const { +// CHECK-NEXT: return BoolWithCase::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } first; +// CHECK-NEXT: inline bool isFirst() const { +// CHECK-NEXT: return *this == BoolWithCase::first; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case third +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::third; +// CHECK-NEXT: } +// CHECK-NEXT: inline BoolWithCase operator()() const { +// CHECK-NEXT: return BoolWithCase::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } third; +// CHECK-NEXT: inline bool isThird() const { +// CHECK-NEXT: return *this == BoolWithCase::third; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline operator cases() const { // CHECK-NEXT: switch (_getEnumTag()) { // CHECK-NEXT: case 0: return cases::second; // CHECK-NEXT: case 1: return cases::first; @@ -161,15 +207,6 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: default: abort(); // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: inline bool isSecond() const { -// CHECK-NEXT: return _getEnumTag() == 0; -// CHECK-NEXT: } -// CHECK: inline bool isFirst() const { -// CHECK-NEXT: return _getEnumTag() == 1; -// CHECK-NEXT: } -// CHECK-NEXT: inline bool isThird() const { -// CHECK-NEXT: return _getEnumTag() == 2; -// CHECK-NEXT: } // CHECK: inline int _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums12BoolWithCaseOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; @@ -184,7 +221,44 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: class CLikeEnum final { -// CHECK: inline operator cases() const { +// CHECK: static struct { // impl struct for case one +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::one; +// CHECK-NEXT: } +// CHECK-NEXT: inline CLikeEnum operator()() const { +// CHECK-NEXT: return CLikeEnum::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } one; +// CHECK-NEXT: inline bool isOne() const { +// CHECK-NEXT: return *this == CLikeEnum::one; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case two +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::two; +// CHECK-NEXT: } +// CHECK-NEXT: inline CLikeEnum operator()() const { +// CHECK-NEXT: return CLikeEnum::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } two; +// CHECK-NEXT: inline bool isTwo() const { +// CHECK-NEXT: return *this == CLikeEnum::two; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case three +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::three; +// CHECK-NEXT: } +// CHECK-NEXT: inline CLikeEnum operator()() const { +// CHECK-NEXT: return CLikeEnum::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } three; +// CHECK-NEXT: inline bool isThree() const { +// CHECK-NEXT: return *this == CLikeEnum::three; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline operator cases() const { // CHECK-NEXT: switch (_getEnumTag()) { // CHECK-NEXT: case 0: return cases::one; // CHECK-NEXT: case 1: return cases::two; @@ -192,15 +266,6 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: default: abort(); // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: inline bool isOne() const { -// CHECK-NEXT: return _getEnumTag() == 0; -// CHECK-NEXT: } -// CHECK: inline bool isTwo() const { -// CHECK-NEXT: return _getEnumTag() == 1; -// CHECK-NEXT: } -// CHECK: inline bool isThree() const { -// CHECK-NEXT: return _getEnumTag() == 2; -// CHECK-NEXT: } // CHECK: inline int _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums9CLikeEnumOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; @@ -215,15 +280,34 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: class DataCase final { -// CHECK: inline operator cases() const { +// CHECK: static struct { // impl struct for case one +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::one; +// CHECK-NEXT: } +// CHECK-NEXT: inline DataCase operator()() const { +// CHECK-NEXT: return DataCase::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } one; +// CHECK-NEXT: inline bool isOne() const { +// CHECK-NEXT: return *this == DataCase::one; +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int getOne() const { +// CHECK-NEXT: if (!isOne()) abort(); +// CHECK-NEXT: alignas(DataCase) unsigned char buffer[sizeof(DataCase)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) DataCase(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: swift::Int result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline operator cases() const { // CHECK-NEXT: switch (_getEnumTag()) { // CHECK-NEXT: case 0: return cases::one; // CHECK-NEXT: default: abort(); // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: inline bool isOne() const { -// CHECK-NEXT: return _getEnumTag() == 0; -// CHECK-NEXT: } // CHECK: inline int _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums8DataCaseOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; @@ -238,7 +322,68 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: class IntDoubleOrBignum final { -// CHECK: inline operator cases() const { +// CHECK: enum class cases { +// CHECK-NEXT: Int, +// CHECK-NEXT: Double, +// CHECK-NEXT: Bignum +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case Int +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::Int; +// CHECK-NEXT: } +// CHECK-NEXT: inline IntDoubleOrBignum operator()() const { +// CHECK-NEXT: return IntDoubleOrBignum::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } Int; +// CHECK-NEXT: inline bool isInt() const { +// CHECK-NEXT: return *this == IntDoubleOrBignum::Int; +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int getInt() const { +// CHECK-NEXT: if (!isInt()) abort(); +// CHECK-NEXT: alignas(IntDoubleOrBignum) unsigned char buffer[sizeof(IntDoubleOrBignum)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) IntDoubleOrBignum(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: swift::Int result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case Double +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::Double; +// CHECK-NEXT: } +// CHECK-NEXT: inline IntDoubleOrBignum operator()() const { +// CHECK-NEXT: return IntDoubleOrBignum::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } Double; +// CHECK-NEXT: inline bool isDouble() const { +// CHECK-NEXT: return *this == IntDoubleOrBignum::Double; +// CHECK-NEXT: } +// CHECK-NEXT: inline double getDouble() const { +// CHECK-NEXT: if (!isDouble()) abort(); +// CHECK-NEXT: alignas(IntDoubleOrBignum) unsigned char buffer[sizeof(IntDoubleOrBignum)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) IntDoubleOrBignum(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: double result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case Bignum +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::Bignum; +// CHECK-NEXT: } +// CHECK-NEXT: inline IntDoubleOrBignum operator()() const { +// CHECK-NEXT: return IntDoubleOrBignum::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } Bignum; +// CHECK-NEXT: inline bool isBignum() const { +// CHECK-NEXT: return *this == IntDoubleOrBignum::Bignum; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline operator cases() const { // CHECK-NEXT: switch (_getEnumTag()) { // CHECK-NEXT: case 0: return cases::Int; // CHECK-NEXT: case 1: return cases::Double; @@ -246,15 +391,6 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: default: abort(); // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: inline bool isInt() const { -// CHECK-NEXT: return _getEnumTag() == 0; -// CHECK-NEXT: } -// CHECK: inline bool isDouble() const { -// CHECK-NEXT: return _getEnumTag() == 1; -// CHECK-NEXT: } -// CHECK: inline bool isBignum() const { -// CHECK-NEXT: return _getEnumTag() == 2; -// CHECK-NEXT: } // CHECK: inline int _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums17IntDoubleOrBignumOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; @@ -269,23 +405,60 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: class IntOrInfinity final { -// CHECK: inline operator cases() const { +// CHECK: static struct { // impl struct for case Int +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::Int; +// CHECK-NEXT: } +// CHECK-NEXT: inline IntOrInfinity operator()() const { +// CHECK-NEXT: return IntOrInfinity::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } Int; +// CHECK-NEXT: inline bool isInt() const { +// CHECK-NEXT: return *this == IntOrInfinity::Int; +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int getInt() const { +// CHECK-NEXT: if (!isInt()) abort(); +// CHECK-NEXT: alignas(IntOrInfinity) unsigned char buffer[sizeof(IntOrInfinity)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) IntOrInfinity(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: swift::Int result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case NegInfinity +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::NegInfinity; +// CHECK-NEXT: } +// CHECK-NEXT: inline IntOrInfinity operator()() const { +// CHECK-NEXT: return IntOrInfinity::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } NegInfinity; +// CHECK-NEXT: inline bool isNegInfinity() const { +// CHECK-NEXT: return *this == IntOrInfinity::NegInfinity; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case PosInfinity +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::PosInfinity; +// CHECK-NEXT: } +// CHECK-NEXT: inline IntOrInfinity operator()() const { +// CHECK-NEXT: return IntOrInfinity::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } PosInfinity; +// CHECK-NEXT: inline bool isPosInfinity() const { +// CHECK-NEXT: return *this == IntOrInfinity::PosInfinity; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline operator cases() const { // CHECK-NEXT: switch (_getEnumTag()) { // CHECK-NEXT: case 0: return cases::Int; // CHECK-NEXT: case 1: return cases::NegInfinity; // CHECK-NEXT: case 2: return cases::PosInfinity; // CHECK-NEXT: default: abort(); // CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: inline bool isInt() const { -// CHECK-NEXT: return _getEnumTag() == 0; -// CHECK-NEXT: } -// CHECK: inline bool isNegInfinity() const { -// CHECK-NEXT: return _getEnumTag() == 1; -// CHECK-NEXT: } -// CHECK: inline bool isPosInfinity() const { -// CHECK-NEXT: return _getEnumTag() == 2; -// CHECK-NEXT: } +// CHECK-NEXT: } // CHECK: inline int _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums13IntOrInfinityOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; @@ -300,26 +473,81 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK: class MultipleBoolWithCase final { -// CHECK: inline operator cases() const { -// CHECK-NEXT: switch (_getEnumTag()) { -// CHECK-NEXT: case 0: return cases::second; -// CHECK-NEXT: case 1: return cases::third; -// CHECK-NEXT: case 2: return cases::first; -// CHECK-NEXT: case 3: return cases::fourth; -// CHECK-NEXT: default: abort(); -// CHECK-NEXT: } -// CHECK-NEXT: } +// CHECK: static struct { // impl struct for case second +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::second; +// CHECK-NEXT: } +// CHECK-NEXT: inline MultipleBoolWithCase operator()() const { +// CHECK-NEXT: return MultipleBoolWithCase::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } second; // CHECK-NEXT: inline bool isSecond() const { -// CHECK-NEXT: return _getEnumTag() == 0; +// CHECK-NEXT: return *this == MultipleBoolWithCase::second; // CHECK-NEXT: } -// CHECK: inline bool isThird() const { -// CHECK-NEXT: return _getEnumTag() == 1; +// CHECK-NEXT: inline bool getSecond() const { +// CHECK-NEXT: if (!isSecond()) abort(); +// CHECK-NEXT: alignas(MultipleBoolWithCase) unsigned char buffer[sizeof(MultipleBoolWithCase)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) MultipleBoolWithCase(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: bool result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; // CHECK-NEXT: } -// CHECK: inline bool isFirst() const { -// CHECK-NEXT: return _getEnumTag() == 2; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case third +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::third; +// CHECK-NEXT: } +// CHECK-NEXT: inline MultipleBoolWithCase operator()() const { +// CHECK-NEXT: return MultipleBoolWithCase::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } third; +// CHECK-NEXT: inline bool isThird() const { +// CHECK-NEXT: return *this == MultipleBoolWithCase::third; // CHECK-NEXT: } +// CHECK-NEXT: inline bool getThird() const { +// CHECK-NEXT: if (!isThird()) abort(); +// CHECK-NEXT: alignas(MultipleBoolWithCase) unsigned char buffer[sizeof(MultipleBoolWithCase)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) MultipleBoolWithCase(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: bool result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case first +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::first; +// CHECK-NEXT: } +// CHECK-NEXT: inline MultipleBoolWithCase operator()() const { +// CHECK-NEXT: return MultipleBoolWithCase::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } first; +// CHECK-NEXT: inline bool isFirst() const { +// CHECK-NEXT: return *this == MultipleBoolWithCase::first; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case fourth +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::fourth; +// CHECK-NEXT: } +// CHECK-NEXT: inline MultipleBoolWithCase operator()() const { +// CHECK-NEXT: return MultipleBoolWithCase::_make(); +// CHECK-NEXT: } +// CHECK-NEXT: } fourth; // CHECK-NEXT: inline bool isFourth() const { -// CHECK-NEXT: return _getEnumTag() == 3; +// CHECK-NEXT: return *this == MultipleBoolWithCase::fourth; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline operator cases() const { +// CHECK-NEXT: switch (_getEnumTag()) { +// CHECK-NEXT: case 0: return cases::second; +// CHECK-NEXT: case 1: return cases::third; +// CHECK-NEXT: case 2: return cases::first; +// CHECK-NEXT: case 3: return cases::fourth; +// CHECK-NEXT: default: abort(); +// CHECK-NEXT: } // CHECK-NEXT: } // CHECK: inline int _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums20MultipleBoolWithCaseOMa(0); From ee20fec3827b97cb209ca3d476f83a885906ad6f Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 15 Aug 2022 22:54:55 -0300 Subject: [PATCH 117/491] [Sema] Warn about dictionary literal of dictionary type about duplicated keys --- include/swift/AST/DiagnosticsSema.def | 6 +- include/swift/AST/Expr.h | 3 + lib/AST/Expr.cpp | 32 +++ lib/Sema/MiscDiagnostics.cpp | 158 +++++++++++++ test/Constraints/bridging.swift | 2 +- .../diag_dictionary_keys_duplicated.swift | 211 ++++++++++++++++++ 6 files changed, 410 insertions(+), 2 deletions(-) create mode 100644 test/Sema/diag_dictionary_keys_duplicated.swift diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index eed4a177a1fa3..02395bb6485c2 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -3768,7 +3768,11 @@ ERROR(should_use_empty_dictionary_literal,none, // Dictionary literals ERROR(type_is_not_dictionary,none, "contextual type %0 cannot be used with dictionary literal", (Type)) - +WARNING(duplicated_literal_keys_in_dictionary_literal, none, + "dictionary literal of type %0 has duplicate entries for %1 literal key%select{ %3|}2", + (Type, StringRef, bool, StringRef)) +NOTE(duplicated_key_declared_here, none, + "duplicate key declared here", ()) // Generic specializations ERROR(cannot_explicitly_specialize_generic_function,none, diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 2f8c33f3d4701..b3cdc73adf82e 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -617,6 +617,9 @@ class LiteralExpr : public Expr { void setInitializer(ConcreteDeclRef initializer) { Initializer = initializer; } + + /// Get description string for the literal expression. + StringRef getLiteralKindDescription() const; }; /// BuiltinLiteralExpr - Common base class between all literals diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 9b885d3e34f72..191de32a726d4 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -972,6 +972,38 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const { // Support methods for Exprs. //===----------------------------------------------------------------------===// +StringRef LiteralExpr::getLiteralKindDescription() const { + switch (getKind()) { + case ExprKind::IntegerLiteral: + return "integer"; + case ExprKind::FloatLiteral: + return "floating-point"; + case ExprKind::BooleanLiteral: + return "boolean"; + case ExprKind::StringLiteral: + return "string"; + case ExprKind::InterpolatedStringLiteral: + return "string"; + case ExprKind::RegexLiteral: + return "regular expression"; + case ExprKind::MagicIdentifierLiteral: + return MagicIdentifierLiteralExpr::getKindString( + cast(this)->getKind()); + case ExprKind::NilLiteral: + return "nil"; + case ExprKind::ObjectLiteral: + return "object"; + // Define an unreachable case for all non-literal expressions. + // This way, if a new literal is added in the future, the compiler + // will warn that a case is missing from this switch. + #define LITERAL_EXPR(Id, Parent) + #define EXPR(Id, Parent) case ExprKind::Id: + #include "swift/AST/ExprNodes.def" + llvm_unreachable("Not a literal expression"); + } + llvm_unreachable("Unhandled literal"); +} + IntegerLiteralExpr * IntegerLiteralExpr::createFromUnsigned(ASTContext &C, unsigned value) { llvm::SmallString<8> Scratch; llvm::APInt(sizeof(unsigned)*8, value).toString(Scratch, 10, /*signed*/ false); diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 12a8e8a6d48e7..317336956341b 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -5011,6 +5011,163 @@ static void diagUnqualifiedAccessToMethodNamedSelf(const Expr *E, const_cast(E)->walk(Walker); } +static void +diagnoseDictionaryLiteralDuplicateKeyEntries(const Expr *E, + const DeclContext *DC) { + class DiagnoseWalker : public ASTWalker { + ASTContext &Ctx; + + private: + std::string getKeyStringValue(const LiteralExpr *keyExpr) { + if (isa(keyExpr)) { + return keyExpr->getLiteralKindDescription().str(); + } + std::string out; + llvm::raw_string_ostream OS(out); + keyExpr->printConstExprValue(&OS, /*additionalCheck=*/nullptr); + return out; + } + + std::string getKeyStringValueForDiagnostic(const LiteralExpr *keyExpr) { + std::string out; + switch (keyExpr->getKind()) { + case ExprKind::NilLiteral: + case ExprKind::MagicIdentifierLiteral: + return out; + case ExprKind::StringLiteral: { + const auto *SL = cast(keyExpr); + out = SL->getValue().str(); + break; + } + default: + llvm::raw_string_ostream OS(out); + keyExpr->printConstExprValue(&OS, /*additionalCheck=*/nullptr); + break; + } + return "'" + out + "'"; + } + + bool shouldDiagnoseLiteral(const LiteralExpr *LE) { + switch (LE->getKind()) { + case ExprKind::IntegerLiteral: + case ExprKind::FloatLiteral: + case ExprKind::BooleanLiteral: + case ExprKind::StringLiteral: + case ExprKind::MagicIdentifierLiteral: + case ExprKind::NilLiteral: + return true; + // Skip interpolated literals because they + // can contain expressions that although equal + // maybe be evaluated to different values. e.g. + // "\(a) \(a)" where 'a' is a computed variable. + case ExprKind::InterpolatedStringLiteral: + // Also skip object literals as most of them takes paramenters that can + // contain expressions that altough equal may evaluate to different + // values e.g. #fileLiteral(resourceName: a) where 'a' is a computed + // property is valid. + case ExprKind::ObjectLiteral: + // Literal expressions produce Regex type result, + // which cannot be keys due to not conforming to hashable. + case ExprKind::RegexLiteral: + return false; + // If a new literal is added in the future, the compiler + // will warn that a case is missing from this switch. + #define LITERAL_EXPR(Id, Parent) + #define EXPR(Id, Parent) case ExprKind::Id: + #include "swift/AST/ExprNodes.def" + llvm_unreachable("Not a literal expression"); + } + llvm_unreachable("Unhandled literal"); + } + public: + DiagnoseWalker(const DeclContext *DC) : Ctx(DC->getASTContext()) {} + + bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override { + return false; + } + + bool shouldWalkIntoTapExpression() override { return false; } + + std::pair walkToExprPre(Expr *E) override { + const auto *DLE = dyn_cast_or_null(E); + if (!DLE) + return {true, E}; + + auto type = DLE->getType(); + // For other types conforming with `ExpressibleByDictionaryLiteral` + // protocol, duplicated keys may be allowed. + if (!(type && type->isDictionary())) { + return {true, E}; + } + + using LiteralKey = std::pair; + using Element = std::pair; + + std::map> groupedLiteralKeys; + + for (size_t i = 0; i < DLE->getElements().size(); ++i) { + const auto *elt = DLE->getElement(i); + const auto *tupleElt = cast(elt); + const auto *keyExpr = + tupleElt->getElement(0)->getSemanticsProvidingExpr(); + auto *LE = dyn_cast(keyExpr); + if (!LE) + continue; + + if (!shouldDiagnoseLiteral(LE)) + continue; + + auto keyStringValue = getKeyStringValue(LE); + auto literalKey = std::make_pair(keyStringValue, keyExpr->getKind()); + groupedLiteralKeys[literalKey].push_back({tupleElt, i}); + } + + // All keys are unique. + if (groupedLiteralKeys.size() == DLE->getNumElements()) { + return {true, E}; + } + + auto &DE = Ctx.Diags; + auto emitNoteWithFixit = [&](const Element &duplicated) { + auto note = DE.diagnose(duplicated.first->getLoc(), + diag::duplicated_key_declared_here); + auto duplicatedEltIdx = duplicated.second; + const auto commanLocs = DLE->getCommaLocs(); + note.fixItRemove(duplicated.first->getSourceRange()); + if (duplicatedEltIdx < commanLocs.size()) { + note.fixItRemove(commanLocs[duplicatedEltIdx]); + } else { + // For the last element remove the previous comma. + note.fixItRemove(commanLocs[duplicatedEltIdx - 1]); + } + }; + + for (auto &entry : groupedLiteralKeys) { + auto &keyValuePairs = entry.second; + if (keyValuePairs.size() == 1) { + continue; + } + + auto elt = keyValuePairs.front(); + const auto keyValue = entry.first.first; + const auto keyExpr = cast( + elt.first->getElement(0)->getSemanticsProvidingExpr()); + const auto value = getKeyStringValueForDiagnostic(keyExpr); + DE.diagnose(elt.first->getLoc(), + diag::duplicated_literal_keys_in_dictionary_literal, type, + keyExpr->getLiteralKindDescription(), value.empty(), value); + for (auto &duplicated : keyValuePairs) { + emitNoteWithFixit(duplicated); + } + } + return {true, E}; + } + }; + + DiagnoseWalker Walker(DC); + const_cast(E)->walk(Walker); +} + namespace { class CompletionHandlerUsageChecker final : public ASTWalker { @@ -5098,6 +5255,7 @@ void swift::performSyntacticExprDiagnostics(const Expr *E, diagDeprecatedObjCSelectors(DC, E); diagnoseConstantArgumentRequirement(E, DC); diagUnqualifiedAccessToMethodNamedSelf(E, DC); + diagnoseDictionaryLiteralDuplicateKeyEntries(E, DC); } void swift::performStmtDiagnostics(const Stmt *S, DeclContext *DC) { diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift index 8e499f665e2c2..7571c40878094 100644 --- a/test/Constraints/bridging.swift +++ b/test/Constraints/bridging.swift @@ -391,7 +391,7 @@ func rdar60501780() { func foo(_: [String: NSObject]) {} func bar(_ v: String) { - foo(["": "", "": v as NSString]) + foo(["a": "", "b": v as NSString]) } } diff --git a/test/Sema/diag_dictionary_keys_duplicated.swift b/test/Sema/diag_dictionary_keys_duplicated.swift new file mode 100644 index 0000000000000..f34a9481afc2d --- /dev/null +++ b/test/Sema/diag_dictionary_keys_duplicated.swift @@ -0,0 +1,211 @@ +// RUN: %target-typecheck-verify-swift + +class CustomDict: ExpressibleByDictionaryLiteral { + typealias Key = String + typealias Value = String + + required init(dictionaryLiteral elements: (String, String)...) {} +} +func fDict(_ d: [String: String]) {} +func fCustomDict(_ d: CustomDict) {} +func fDictGeneric(_ d: D) where D: ExpressibleByDictionaryLiteral {} + +// Duplicated +let _ = [ + // expected-note@+1{{duplicate key declared here}} {{3-11=}} {{11-12=}} + "A": "A", // expected-warning{{dictionary literal of type '[String : String]' has duplicate entries for string literal key 'A'}} + "A": "B" // expected-note{{duplicate key declared here}} {{3-12=}} {{16:11-12=}} +] + +let _: [String: String] = [ + // expected-note@+1{{duplicate key declared here}} {{3-11=}} {{11-12=}} + "A": "A", // expected-warning{{dictionary literal of type '[String : String]' has duplicate entries for string literal key 'A'}} + "A": "B" // expected-note{{duplicate key declared here}} {{3-12=}} {{22:11-12=}} +] + +let _: [String: String] = [ + // expected-note@+1{{duplicate key declared here}} {{3-15=}}{{15-16=}} + (("A")): "A", // expected-warning{{dictionary literal of type '[String : String]' has duplicate entries for string literal key 'A'}} + "A": "B" // expected-note{{duplicate key declared here}} {{3-12=}} {{28:15-16=}} +] + +let _: [String: String] = [ + // expected-note@+1{{duplicate key declared here}} {{3-11=}} {{11-12=}} + "A": "A", // expected-warning{{dictionary literal of type '[String : String]' has duplicate entries for string literal key 'A'}} + "B": "B", + "C": "C", + "A": "D" // expected-note{{duplicate key declared here}} {{3-12=}} {{36:11-12=}} +] + +// Number literal key +let _: [Int: String] = [ + // expected-note@+1{{duplicate key declared here}} {{3-9=}} {{9-10=}} + 1: "1", // expected-warning{{dictionary literal of type '[Int : String]' has duplicate entries for integer literal key '1'}} + 2: "2", + 1: "3" // expected-note{{duplicate key declared here}} {{3-10=}} {{44:9-10=}} +] + +let _: [Double: String] = [ + // expected-note@+1{{duplicate key declared here}} {{3-12=}} {{12-13=}} + 1.01: "1", // expected-warning{{dictionary literal of type '[Double : String]' has duplicate entries for floating-point literal key '1.01'}} + 2: "2", + 1.01: "3" // expected-note{{duplicate key declared here}} {{3-13=}} {{51:9-10=}} +] + +// Boolean literal +let _: [Bool: String] = [ + // expected-note@+1{{duplicate key declared here}} {{3-12=}} {{12-13=}} + true: "1", // expected-warning{{dictionary literal of type '[Bool : String]' has duplicate entries for boolean literal key 'true'}} + false: "2", + true: "3" // expected-note{{duplicate key declared here}} {{3-13=}} {{59:13-14=}} +] + +// nil literal +let _: [Int?: String] = [ + // expected-note@+1{{duplicate key declared here}} {{3-11=}} {{11-12=}} + nil: "1", // expected-warning{{dictionary literal of type '[Int? : String]' has duplicate entries for nil literal key}} + 2: "2", + nil: "3" // expected-note{{duplicate key declared here}} {{3-12=}} {{67:9-10=}} +] + +// Nested +let _: [String: [String: String]] = [ + // expected-note@+1{{duplicate key declared here}} {{3-11=}} {{11-12=}} + "A": [:], // expected-warning{{dictionary literal of type '[String : [String : String]]' has duplicate entries for string literal key 'A'}} + "B": [:], + "C": [:], + "A": [:] // expected-note{{duplicate key declared here}} {{3-12=}} {{76:11-12=}} +] + +let _: [String: [String: String]] = [ + // expected-note@+1{{duplicate key declared here}} {{3-11=}} {{11-12=}} + "A": [:], // expected-warning{{dictionary literal of type '[String : [String : String]]' has duplicate entries for string literal key 'A'}} + "B": [:], + "C": [:], + "A": ["a": "", "a": ""] // expected-note{{duplicate key declared here}} {{3-27=}} {{84:11-12=}} + // expected-warning@-1{{dictionary literal of type '[String : String]' has duplicate entries for string literal key 'a'}} + // expected-note@-2{{duplicate key declared here}} {{9-16=}} {{16-17=}} + // expected-note@-3{{duplicate key declared here}} {{18-25=}} {{16-17=}} +] + +// Parent OK, nested duplicated +let _: [String: [String: String]] = [ + "A": [:], + "B": [:], + "C": [:], + // expected-note@+1{{duplicate key declared here}} {{9-16=}} {{16-17=}} + "D": ["a": "", "a": ""] // expected-warning{{dictionary literal of type '[String : String]' has duplicate entries for string literal key 'a'}} + // expected-note@-1{{duplicate key declared here}}{{18-25=}} {{18-25=}} {{16-17=}} +] + +// Ok, because custom implementations of ExpressibleByDictionaryLiteral can allow duplicated keys. +let _: CustomDict = [ + "A": "A", + "A": "B" +] + +fDict([ + // expected-note@+1{{duplicate key declared here}} {{3-11=}} {{11-12=}} + "A": "A", // expected-warning{{dictionary literal of type '[String : String]' has duplicate entries for string literal key 'A'}} + "A": "B" // expected-note{{duplicate key declared here}} {{3-12=}} {{109:11-12=}} +]) +fCustomDict([ + "A": "A", + "A": "B" +]) +fDictGeneric([ + // expected-note@+1{{duplicate key declared here}} {{3-11=}} {{11-12=}} + "A": "A", // expected-warning{{dictionary literal of type '[String : String]' has duplicate entries for string literal key 'A'}} + "A": "B" // expected-note{{duplicate key declared here}} {{3-12=}} {{118:11-12=}} +]) + +// Magic literals +let _: [String: String] = [ + // expected-note@+1{{duplicate key declared here}} {{3-13=}} {{13-14=}} + #file: "A", // expected-warning{{dictionary literal of type '[String : String]' has duplicate entries for #file literal key}} + #file: "B" // expected-note{{duplicate key declared here}} {{3-14=}} {{125:13-14=}} +] + + +// OK +let _ = [ + "A": "A", + "B": "B" +] +let _: [String: String] = [ + "A": "A", + "B": "B" +] +let _: CustomDict = [ + "A": "A", + "B": "B" +] + +// Number literal key +let _: [Int: String] = [ + 1: "1", + 2: "2", + 3: "3" +] + +let _: [Double: String] = [ + 1.01: "1", + 2: "2", + 1.02: "3" +] + +// Boolean literal +let _: [Bool: String] = [ + true: "1", + false: "2" +] + +// nil literal +let _: [Int?: String] = [ + nil: "1", + 2: "2" +] + +// Key as the same variable is OK, we only diagnose literals +let a = "A" + +let _: [String: String] = [ + a: "A", + "B": "B", + "a": "C", + a: "D" +] + +let _: [String: [String: String]] = [ + "A": [:], + "B": [:], + "C": [:], + "D": ["a": "", "b": ""] +] + +fDict([ + "A": "A", + "B": "B" +]) +fCustomDict([ + "A": "A", + "B": "B" +]) +fDictGeneric([ + "A": "A", + "B": "B" +]) + +func magicFn() { + let _: [String: String] = [ + #file: "A", + #function: "B" + ] +} + +// Interpolated literals +let _: [String: String] = [ + "\(a)": "A", + "\(a)": "B", + "\(1)": "C" +] From 1b7b6a33aacde022624020cdbf916e81c4de122f Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 15 Aug 2022 22:55:09 -0300 Subject: [PATCH 118/491] [NFC] Replace other usage of get literal expr description --- lib/AST/Expr.cpp | 6 +++--- lib/Sema/TypeCheckStmt.cpp | 28 +--------------------------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 191de32a726d4..bf702af68865a 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -993,9 +993,9 @@ StringRef LiteralExpr::getLiteralKindDescription() const { return "nil"; case ExprKind::ObjectLiteral: return "object"; - // Define an unreachable case for all non-literal expressions. - // This way, if a new literal is added in the future, the compiler - // will warn that a case is missing from this switch. + // Define an unreachable case for all non-literal expressions. + // This way, if a new literal is added in the future, the compiler + // will warn that a case is missing from this switch. #define LITERAL_EXPR(Id, Parent) #define EXPR(Id, Parent) case ExprKind::Id: #include "swift/AST/ExprNodes.def" diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index ac08d3e584e0e..4ba74d0cb4833 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1227,34 +1227,8 @@ static bool isDiscardableType(Type type) { } static void diagnoseIgnoredLiteral(ASTContext &Ctx, LiteralExpr *LE) { - const auto getLiteralDescription = [](LiteralExpr *LE) -> StringRef { - switch (LE->getKind()) { - case ExprKind::IntegerLiteral: return "integer"; - case ExprKind::FloatLiteral: return "floating-point"; - case ExprKind::BooleanLiteral: return "boolean"; - case ExprKind::StringLiteral: return "string"; - case ExprKind::InterpolatedStringLiteral: return "string"; - case ExprKind::RegexLiteral: return "regular expression"; - case ExprKind::MagicIdentifierLiteral: - return MagicIdentifierLiteralExpr::getKindString( - cast(LE)->getKind()); - case ExprKind::NilLiteral: return "nil"; - case ExprKind::ObjectLiteral: return "object"; - - // Define an unreachable case for all non-literal expressions. - // This way, if a new literal is added in the future, the compiler - // will warn that a case is missing from this switch. -#define LITERAL_EXPR(Id, Parent) -#define EXPR(Id, Parent) case ExprKind::Id: -#include "swift/AST/ExprNodes.def" - llvm_unreachable("Not a literal expression"); - } - - llvm_unreachable("Unhandled ExprKind in switch."); - }; - Ctx.Diags.diagnose(LE->getLoc(), diag::expression_unused_literal, - getLiteralDescription(LE)) + LE->getLiteralKindDescription()) .highlight(LE->getSourceRange()); } From 4b9d9cc04f64fdb12eb249af798a3108aaf71c2e Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Mon, 15 Aug 2022 20:24:03 -0700 Subject: [PATCH 119/491] update formatting --- lib/PrintAsClang/DeclAndTypePrinter.cpp | 36 +++++++++++++----------- lib/PrintAsClang/PrintClangValueType.cpp | 5 ++-- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 2d811e3088f65..3117831223d8d 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -416,22 +416,25 @@ class DeclAndTypePrinter::Implementation os << '\n'; os << " enum class cases {"; - llvm::interleave(elementTagMapping, os, [&](const auto &pair){ - os << "\n "; - syntaxPrinter.printIdentifier(pair.first->getNameStr()); - }, ","); + llvm::interleave( + elementTagMapping, os, + [&](const auto &pair) { + os << "\n "; + syntaxPrinter.printIdentifier(pair.first->getNameStr()); + }, + ","); // TODO: allow custom name for this special case auto resilientUnknownDefaultCaseName = "unknownDefault"; if (ED->isResilient()) { os << ",\n " << resilientUnknownDefaultCaseName; } os << "\n };\n\n"; // enum class cases' closing bracket - + // Printing struct, is, and get functions for each case DeclAndTypeClangFunctionPrinter clangFuncPrinter( os, owningPrinter.prologueOS, owningPrinter.typeMapping, owningPrinter.interopContext); - + auto printIsFunction = [&](StringRef caseName, EnumDecl *ED) { os << " inline bool is"; std::string name; @@ -446,7 +449,7 @@ class DeclAndTypePrinter::Implementation os << ";\n"; os << " }\n"; }; - + auto printGetFunction = [&](EnumElementDecl *elementDecl) { auto associatedValueList = elementDecl->getParameterList(); // TODO: add tuple type support @@ -458,10 +461,10 @@ class DeclAndTypePrinter::Implementation OptionalTypeKind optKind; std::tie(firstType, optKind) = getObjectTypeAndOptionality(firstTypeDecl, firstType); - + auto name = elementDecl->getNameStr().str(); name[0] = std::toupper(name[0]); - + // FIXME: may have to forward declare return type os << " inline "; clangFuncPrinter.printClangFunctionReturnType( @@ -492,7 +495,8 @@ class DeclAndTypePrinter::Implementation } else { os << " return "; syntaxPrinter.printModuleNamespaceQualifiersIfNeeded( - firstTypeDecl->getModuleContext(), elementDecl->getParentEnum()->getModuleContext()); + firstTypeDecl->getModuleContext(), + elementDecl->getParentEnum()->getModuleContext()); os << cxx_synthesis::getCxxImplNamespaceName(); os << "::"; ClangValueTypePrinter::printCxxImplClassName(os, firstTypeDecl); @@ -503,9 +507,9 @@ class DeclAndTypePrinter::Implementation os << "::initializeWithTake(result, payloadFromDestruction);\n"; os << " });\n"; } - os << " }\n"; // closing bracket of get function + os << " }\n"; // closing bracket of get function }; - + auto printStruct = [&](StringRef caseName, EnumElementDecl *elementDecl) { os << " static struct { // impl struct for case " << caseName << '\n'; os << " inline constexpr operator cases() const {\n"; @@ -519,7 +523,7 @@ class DeclAndTypePrinter::Implementation os << " operator()("; // TODO: implement parameter for associated value os << ") const {\n"; - // TODO: print _make for now; need to implement actual code making an enum + // TODO: print _make for now; need to print actual code making an enum os << " return "; syntaxPrinter.printBaseName(elementDecl->getParentEnum()); os << "::_make();\n"; @@ -541,7 +545,7 @@ class DeclAndTypePrinter::Implementation } os << '\n'; } - + if (ED->isResilient()) { // Printing struct for unknownDefault printStruct(resilientUnknownDefaultCaseName, /* elementDecl */ nullptr); @@ -550,7 +554,7 @@ class DeclAndTypePrinter::Implementation os << '\n'; } os << '\n'; - + // Printing operator cases() os << " inline operator cases() const {\n"; if (ED->isResilient()) { @@ -573,7 +577,7 @@ class DeclAndTypePrinter::Implementation os << " default: abort();\n"; os << " }\n"; // switch's closing bracket } - os << " }\n"; // operator cases()'s closing bracket + os << " }\n"; // operator cases()'s closing bracket os << "\n"; }); os << outOfLineDefinitions; diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index a58b641abba55..17eb92991c37a 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -257,8 +257,9 @@ void ClangValueTypePrinter::printValueTypeDecl( os << "};\n"; // Print the definition of enum static struct data memebers if (isa(typeDecl)) { - auto tagMapping = interopContext.getIrABIDetails().getEnumTagMapping(cast(typeDecl)); - for (const auto& pair : tagMapping) { + auto tagMapping = interopContext.getIrABIDetails().getEnumTagMapping( + cast(typeDecl)); + for (const auto &pair : tagMapping) { os << "decltype("; printer.printBaseName(typeDecl); os << "::"; From 7115e64689fdbfc2de0b44e0c5dbaf1d2bece3c0 Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Mon, 15 Aug 2022 20:24:40 -0700 Subject: [PATCH 120/491] update test case --- .../enums/swift-enum-case-functions.swift | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift b/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift index 0679c2bd61506..1f9ea323f0266 100644 --- a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift +++ b/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift @@ -207,6 +207,7 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: default: abort(); // CHECK-NEXT: } // CHECK-NEXT: } +// CHECK: private: // CHECK: inline int _getEnumTag() const { // CHECK-NEXT: auto metadata = _impl::$s5Enums12BoolWithCaseOMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; @@ -218,6 +219,10 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); // CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); // CHECK-NEXT: } +// CHECK: }; +// CHECK-NEXT: decltype(BoolWithCase::first) BoolWithCase::first; +// CHECK-NEXT: decltype(BoolWithCase::second) BoolWithCase::second; +// CHECK-NEXT: decltype(BoolWithCase::third) BoolWithCase::third; // CHECK: class CLikeEnum final { @@ -277,6 +282,10 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); // CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); // CHECK-NEXT: } +// CHECK: }; +// CHECK-NEXT: decltype(CLikeEnum::one) CLikeEnum::one; +// CHECK-NEXT: decltype(CLikeEnum::two) CLikeEnum::two; +// CHECK-NEXT: decltype(CLikeEnum::three) CLikeEnum::three; // CHECK: class DataCase final { @@ -319,6 +328,8 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); // CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); // CHECK-NEXT: } +// CHECK: }; +// CHECK-NEXT: decltype(DataCase::one) DataCase::one; // CHECK: class IntDoubleOrBignum final { @@ -402,6 +413,10 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); // CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); // CHECK-NEXT: } +// CHECK: }; +// CHECK-NEXT: decltype(IntDoubleOrBignum::Int) IntDoubleOrBignum::Int; +// CHECK-NEXT: decltype(IntDoubleOrBignum::Double) IntDoubleOrBignum::Double; +// CHECK-NEXT: decltype(IntDoubleOrBignum::Bignum) IntDoubleOrBignum::Bignum; // CHECK: class IntOrInfinity final { @@ -470,6 +485,10 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); // CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); // CHECK-NEXT: } +// CHECK: }; +// CHECK-NEXT: decltype(IntOrInfinity::NegInfinity) IntOrInfinity::NegInfinity; +// CHECK-NEXT: decltype(IntOrInfinity::Int) IntOrInfinity::Int; +// CHECK-NEXT: decltype(IntOrInfinity::PosInfinity) IntOrInfinity::PosInfinity; // CHECK: class MultipleBoolWithCase final { @@ -560,3 +579,8 @@ public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { // CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); // CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); // CHECK-NEXT: } +// CHECK: }; +// CHECK-NEXT: decltype(MultipleBoolWithCase::first) MultipleBoolWithCase::first; +// CHECK-NEXT: decltype(MultipleBoolWithCase::second) MultipleBoolWithCase::second; +// CHECK-NEXT: decltype(MultipleBoolWithCase::third) MultipleBoolWithCase::third; +// CHECK-NEXT: decltype(MultipleBoolWithCase::fourth) MultipleBoolWithCase::fourth; From 50c79f9b3cc96a267cfa05675b675cb65242f62d Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 15 Aug 2022 21:16:24 -0700 Subject: [PATCH 121/491] Fix tests on older/32 bit platforms (#60538) (cherry picked from commit 503a17cc7e31ef7c3463c1d6a54c67297a150064) --- test/Inputs/SmallStringTestUtilities.swift | 3 ++- test/stdlib/NSSlowTaggedLocalizedString.swift | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/test/Inputs/SmallStringTestUtilities.swift b/test/Inputs/SmallStringTestUtilities.swift index 9592fb669562d..0d13f2033ec51 100644 --- a/test/Inputs/SmallStringTestUtilities.swift +++ b/test/Inputs/SmallStringTestUtilities.swift @@ -75,7 +75,8 @@ extension _SmallString { return nil #else guard _isObjCTaggedPointer(ns) else { return nil } - self.init(taggedCocoa: ns) + self = (ns as String)._guts.asSmall //regular tagged NSStrings are guaranteed to bridge to SmallStrings + assert(_StringGuts(self).isSmall) #endif } #endif diff --git a/test/stdlib/NSSlowTaggedLocalizedString.swift b/test/stdlib/NSSlowTaggedLocalizedString.swift index 5f385745e702f..31634c7526b8e 100644 --- a/test/stdlib/NSSlowTaggedLocalizedString.swift +++ b/test/stdlib/NSSlowTaggedLocalizedString.swift @@ -16,6 +16,11 @@ let longTaggedTests = TestSuite("NonContiguousTaggedStrings") var constant = "Send Message to different Team" func runEqualLongTagged() { + + if MemoryLayout.size != 8 { + return //no tagged pointers + } + let native = constant.withUTF8 { String(decoding: $0, as: UTF8.self) } let longTagged = NSSlowTaggedLocalizedString.createTest()! constant.withCString { From b4949a0b2cc2e9b72304399bfcd03f93ba8c446b Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 15 Aug 2022 18:51:19 -0700 Subject: [PATCH 122/491] [CSApply] Attempt value-to-opaque-result abstraction only after canonicalization `ExprRewriter::coerceToType` should canonicalize contextual type before attempting to use it for value abstraction, because sugared type could have typealias references that hide their underlying opaque result types. Resolves: rdar://98577451 --- lib/Sema/CSApply.cpp | 4 ++-- .../rdar98577451.swift | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 validation-test/Sema/type_checker_crashers_fixed/rdar98577451.swift diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 85ea9fc99a0fc..149593e721a76 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -6850,11 +6850,11 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, // below is just an approximate check since the above would be expensive to // verify and still relies on the type checker ensuing `fromType` is // compatible with any opaque archetypes. - if (toType->hasOpaqueArchetype() && + if (toType->getCanonicalType()->hasOpaqueArchetype() && cs.getConstraintLocator(locator)->isForContextualType()) { // Find the opaque type declaration. We need its generic signature. OpaqueTypeDecl *opaqueDecl = nullptr; - bool found = toType.findIf([&](Type type) { + bool found = toType->getCanonicalType().findIf([&](Type type) { if (auto opaqueType = type->getAs()) { opaqueDecl = opaqueType->getDecl(); return true; diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar98577451.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar98577451.swift new file mode 100644 index 0000000000000..49a869814891b --- /dev/null +++ b/validation-test/Sema/type_checker_crashers_fixed/rdar98577451.swift @@ -0,0 +1,21 @@ +// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 + +// REQUIRES: objc_interop +// REQUIRES: OS=macosx + +protocol P { + associatedtype T + func f() -> T +} + +struct S: P { + func f() -> some Any { return 3 } +} + +struct G { + typealias Foo = (T?, S.T) +} + +func f(t: T) -> G.Foo { + return (t, S().f()) // Ok +} From f608802cfe498b8684e4ea63603fe99073102ce6 Mon Sep 17 00:00:00 2001 From: Sima Nerush <2002ssn@gmail.com> Date: Sat, 30 Jul 2022 20:08:53 -0600 Subject: [PATCH 123/491] Sema: Emit diagnostics when walking into collection literals with defaulted types Resolves https://github.com/apple/swift/issues/60011 Gardening: clean up `checkTypeDefaultedCollectionExpr` function --- lib/Sema/MiscDiagnostics.cpp | 73 ++++++++++++++--------- test/Constraints/array_literal.swift | 39 +++++++++++- test/Constraints/casts.swift | 1 + test/Constraints/casts_swift6.swift | 1 + test/Constraints/construction.swift | 1 + test/Constraints/dictionary_literal.swift | 3 +- test/Constraints/subscript.swift | 1 + test/IDE/print_usrs_opaque_types.swift | 10 ++++ test/expr/cast/objc_coerce_array.swift | 4 ++ 9 files changed, 104 insertions(+), 29 deletions(-) diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 12a8e8a6d48e7..de43feb009e25 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -109,13 +109,15 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, SmallPtrSet AlreadyDiagnosedBitCasts; bool IsExprStmt; + bool HasReachedSemanticsProvidingExpr; - public: ASTContext &Ctx; const DeclContext *DC; + public: DiagnoseWalker(const DeclContext *DC, bool isExprStmt) - : IsExprStmt(isExprStmt), Ctx(DC->getASTContext()), DC(DC) {} + : IsExprStmt(isExprStmt), HasReachedSemanticsProvidingExpr(false), + Ctx(DC->getASTContext()), DC(DC) {} std::pair walkToPatternPre(Pattern *P) override { return { false, P }; @@ -128,6 +130,17 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, bool shouldWalkIntoTapExpression() override { return false; } std::pair walkToExprPre(Expr *E) override { + + if (auto collection = dyn_cast(E)) { + if (collection->isTypeDefaulted()) { + // Diagnose type defaulted collection literals in subexpressions as + // warnings to preserve source compatibility. + diagnoseTypeDefaultedCollectionExpr( + collection, Ctx, + /*downgradeToWarning=*/HasReachedSemanticsProvidingExpr); + } + } + // See through implicit conversions of the expression. We want to be able // to associate the parent of this expression with the ultimate callee. auto Base = E; @@ -328,6 +341,11 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, checkMoveExpr(moveExpr); } + if (!HasReachedSemanticsProvidingExpr && + E == E->getSemanticsProvidingExpr()) { + HasReachedSemanticsProvidingExpr = true; + } + return { true, E }; } @@ -444,23 +462,34 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, return false; } - /// We have a collection literal with a defaulted type, e.g. of [Any]. Emit - /// an error if it was inferred to this type in an invalid context, which is - /// one in which the parent expression is not itself a collection literal. - void checkTypeDefaultedCollectionExpr(CollectionExpr *c) { - // If the parent is a non-expression, or is not itself a literal, then - // produce an error with a fixit to add the type as an explicit - // annotation. - if (c->getNumElements() == 0) - Ctx.Diags.diagnose(c->getLoc(), diag::collection_literal_empty) - .highlight(c->getSourceRange()); - else { + /// Diagnose a collection literal with a defaulted type such as \c [Any]. + static void diagnoseTypeDefaultedCollectionExpr(CollectionExpr *c, + ASTContext &ctx, + bool downgradeToWarning) { + // Produce a diagnostic with a fixit to add the defaulted type as an + // explicit annotation. + auto &diags = ctx.Diags; + + if (c->getNumElements() == 0) { + InFlightDiagnostic inFlight = + diags.diagnose(c->getLoc(), diag::collection_literal_empty); + inFlight.highlight(c->getSourceRange()); + + if (downgradeToWarning) { + inFlight.limitBehavior(DiagnosticBehavior::Warning); + } + } else { assert(c->getType()->hasTypeRepr() && "a defaulted type should always be printable"); - Ctx.Diags.diagnose(c->getLoc(), diag::collection_literal_heterogeneous, - c->getType()) - .highlight(c->getSourceRange()) - .fixItInsertAfter(c->getEndLoc(), " as " + c->getType()->getString()); + InFlightDiagnostic inFlight = diags.diagnose( + c->getLoc(), diag::collection_literal_heterogeneous, c->getType()); + inFlight.highlight(c->getSourceRange()); + inFlight.fixItInsertAfter(c->getEndLoc(), + " as " + c->getType()->getString()); + + if (downgradeToWarning) { + inFlight.limitBehavior(DiagnosticBehavior::Warning); + } } } @@ -1334,16 +1363,6 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, DiagnoseWalker Walker(DC, isExprStmt); const_cast(E)->walk(Walker); - - // Diagnose uses of collection literals with defaulted types at the top - // level. - if (auto collection - = dyn_cast(E->getSemanticsProvidingExpr())) { - if (collection->isTypeDefaulted()) { - Walker.checkTypeDefaultedCollectionExpr( - const_cast(collection)); - } - } } diff --git a/test/Constraints/array_literal.swift b/test/Constraints/array_literal.swift index 8276bd5632e66..f8e87090f98b1 100644 --- a/test/Constraints/array_literal.swift +++ b/test/Constraints/array_literal.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-availability-checking struct IntList : ExpressibleByArrayLiteral { typealias Element = Int @@ -142,19 +142,56 @@ func defaultToAny(i: Int, s: String) { // expected-error@-1{{empty collection literal requires an explicit type}} let _: Int = a5 // expected-error{{value of type '[Any]'}} + let _: [Any] = [] let _: [Any] = [1, "a", 3.5] let _: [Any] = [1, "a", [3.5, 3.7, 3.9]] let _: [Any] = [1, "a", [3.5, "b", 3]] + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} let _: [Any] = [1, [2, [3]]] + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} + + func f1() -> [Any] { + [] + } let _: [Any?] = [1, "a", nil, 3.5] let _: [Any?] = [1, "a", nil, [3.5, 3.7, 3.9]] let _: [Any?] = [1, "a", nil, [3.5, "b", nil]] + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}} let _: [Any?] = [1, [2, [3]]] + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} let _: [Any?] = [1, nil, [2, nil, [3]]] + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}} let a6 = [B(), C()] let _: Int = a6 // expected-error{{value of type '[A]'}} + + let a7: some Collection = [1, "Swift"] + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} {{41-41= as [Any]}} + let _: (any Sequence)? = [1, "Swift"] + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} + let _: any Sequence = [1, nil, "Swift"] + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}} + let _ = [1, true, ([], 1)] + // expected-error@-1 {{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} + // expected-warning@-2 {{empty collection literal requires an explicit type}} + let _ = true ? [] : [] + // expected-warning@-1{{empty collection literal requires an explicit type}} + let _ = (true, ([1, "Swift"])) + //expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} + let _ = ([1, true]) + //expected-error@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} + + func f2(_: [T]) {} + + func f3() -> [T]? {} + + f2([]) + // expected-warning@-1{{empty collection literal requires an explicit type}} + f2([1, nil, ""]) + // expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}} + _ = f3() ?? [] + // expected-warning@-1{{empty collection literal requires an explicit type}} } func noInferAny(iob: inout B, ioc: inout C) { diff --git a/test/Constraints/casts.swift b/test/Constraints/casts.swift index 4038c2cc92b8a..65c9f9a2f5e4c 100644 --- a/test/Constraints/casts.swift +++ b/test/Constraints/casts.swift @@ -337,6 +337,7 @@ func test_compatibility_coercions(_ arr: [Int], _ optArr: [Int]?, _ dict: [Strin // The array can also be inferred to be [Any]. _ = ([] ?? []) as Array // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[Any]', so the right side is never used}} + // expected-warning@-1{{empty collection literal requires an explicit type}} // rdar://88334481 – Don't apply the compatibility logic for collection literals. typealias Magic = T diff --git a/test/Constraints/casts_swift6.swift b/test/Constraints/casts_swift6.swift index 496eeb90b7059..000484e984943 100644 --- a/test/Constraints/casts_swift6.swift +++ b/test/Constraints/casts_swift6.swift @@ -57,6 +57,7 @@ func test_compatibility_coercions(_ arr: [Int], _ optArr: [Int]?, _ dict: [Strin // The array can also be inferred to be [Any]. _ = ([] ?? []) as Array // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[Any]', so the right side is never used}} + // expected-warning@-1 {{empty collection literal requires an explicit type}} // Cases from rdar://88334481 typealias Magic = T diff --git a/test/Constraints/construction.swift b/test/Constraints/construction.swift index d4857ad08d633..e738589758672 100644 --- a/test/Constraints/construction.swift +++ b/test/Constraints/construction.swift @@ -172,6 +172,7 @@ SR_5245(s: SR_5245.S(f: [.e1, .e2])) // rdar://problem/34670592 - Compiler crash on heterogeneous collection literal _ = Array([1, "hello"]) // Ok +// expected-warning@-1 {{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} func init_via_non_const_metatype(_ s1: S1.Type) { _ = s1(i: 42) // expected-error {{initializing from a metatype value must reference 'init' explicitly}} {{9-9=.init}} diff --git a/test/Constraints/dictionary_literal.swift b/test/Constraints/dictionary_literal.swift index d73270f8cf30b..217cceec6e9d4 100644 --- a/test/Constraints/dictionary_literal.swift +++ b/test/Constraints/dictionary_literal.swift @@ -139,6 +139,7 @@ func testDefaultExistentials() { "b": ["a", 2, 3.14159], "c": ["a": 2, "b": 3.5]] // expected-error@-3{{heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional}} + // expected-warning@-3{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}} let d3 = ["b" : B(), "c" : C()] let _: Int = d3 // expected-error{{value of type '[String : A]'}} @@ -193,4 +194,4 @@ f59215(["", ""]) //expected-error{{dictionary of type '[String : String]' cannot f59215(["", "", "", ""]) //expected-error{{dictionary of type '[String : String]' cannot be used with array literal}} // expected-note@-1{{did you mean to use a dictionary literal instead?}} {{11-12=:}} {{19-20=:}} f59215(["", "", "", ""]) //expected-error{{dictionary of type '[String : String]' cannot be used with array literal}} -// expected-note@-1{{did you mean to use a dictionary literal instead?}} {{11-12=:}} {{19-20=:}} \ No newline at end of file +// expected-note@-1{{did you mean to use a dictionary literal instead?}} {{11-12=:}} {{19-20=:}} diff --git a/test/Constraints/subscript.swift b/test/Constraints/subscript.swift index 00db94819bc27..34bdef40c7f8e 100644 --- a/test/Constraints/subscript.swift +++ b/test/Constraints/subscript.swift @@ -104,6 +104,7 @@ extension Int { let _ = 1["1"] // expected-error {{ambiguous use of 'subscript(_:)'}} let squares = [ 1, 2, 3 ].reduce([:]) { (dict, n) in + // expected-warning@-1 {{empty collection literal requires an explicit type}} var dict = dict dict[n] = n * n return dict diff --git a/test/IDE/print_usrs_opaque_types.swift b/test/IDE/print_usrs_opaque_types.swift index 5723746352632..f6bc21c72759b 100644 --- a/test/IDE/print_usrs_opaque_types.swift +++ b/test/IDE/print_usrs_opaque_types.swift @@ -9,17 +9,20 @@ func testUnifyingGenericParams(x: T) -> some Collection where T == U { // expected-warning@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}} return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test0C22UnifyingGenericParams21xQrx_tSlRz7ElementQzRs_r0_lF func testUnifyingGenericParams2(x: T) -> some Collection where T: Collection, U == T.Element { return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test0C24ConcretizingGenericParam1xQrSi_tSiRszlF func testConcretizingGenericParam(x: T) -> some Collection where T == Int { // expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}} return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } struct GenericContext { @@ -27,11 +30,13 @@ struct GenericContext { func testUnifyingGenericParams(x: T) -> some Collection where T == U { // expected-warning@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}} return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextV0c8UnifyingD7Params21xQrx_tSlRz7ElementQzRsd__lF func testUnifyingGenericParams2(x: T) -> some Collection where T: Collection, U == T.Element { return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextVyQrxcqd__Rszluip @@ -40,6 +45,7 @@ struct GenericContext { // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextVyQrxcqd__Rszluig get { return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } } } @@ -48,6 +54,7 @@ extension GenericContext where T == Int { // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextVAASiRszlE0c12ConcretizingD5Param1xQrSi_tF func testConcretizingGenericParam(x: T) -> some Collection { return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } } @@ -58,6 +65,7 @@ extension TooGenericTooContext where T == U { // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test010TooGenericD7ContextVAAq_RszrlE0c8UnifyingE6Params1xQrx_tF func testUnifyingGenericParams(x: T) -> some Collection { return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } } @@ -65,12 +73,14 @@ extension TooGenericTooContext where T: Collection, U == T.Element { // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test010TooGenericD7ContextVAASlRz7ElementQzRs_rlE0c8UnifyingE7Params21xQrx_tF func testUnifyingGenericParams2(x: T) -> some Collection { return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } } extension TooGenericTooContext where T == Int { // CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test010TooGenericD7ContextVAASiRszrlE0c12ConcretizingE5Param1xQrSi_tF func testConcretizingGenericParam(x: T) -> some Collection { return [] + // expected-warning@-1 {{empty collection literal requires an explicit type}} } } diff --git a/test/expr/cast/objc_coerce_array.swift b/test/expr/cast/objc_coerce_array.swift index 22f3c5eb0aadb..b34d6ca08e742 100644 --- a/test/expr/cast/objc_coerce_array.swift +++ b/test/expr/cast/objc_coerce_array.swift @@ -7,9 +7,13 @@ var x = 1 _ = [x] as [NSNumber] _ = ["x":["y":"z","a":1]] as [String : [String : AnyObject]] +// expected-warning@-1{{heterogeneous collection literal could only be inferred to '[String : AnyObject]'; add explicit type annotation if this is intentiona}} _ = ["x":["z",1]] as [String : [AnyObject]] +// expected-warning@-1{{heterogeneous collection literal could only be inferred to '[AnyObject]'; add explicit type annotation if this is intentional}} _ = [["y":"z","a":1]] as [[String : AnyObject]] +// expected-warning@-1{{heterogeneous collection literal could only be inferred to '[String : AnyObject]'; add explicit type annotation if this is intentional}} _ = [["z",1]] as [[AnyObject]] +// expected-warning@-1{{heterogeneous collection literal could only be inferred to '[AnyObject]'; add explicit type annotation if this is intentional}} var y: Any = 1 From a15d59ee351947830755bd28c565b8a0924df5be Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 16 Aug 2022 13:56:11 +0200 Subject: [PATCH 124/491] tests: Fix SILOptimizer/accessutils.sil for 32-bit test targets rdar://98669547 --- test/SILOptimizer/accessutils.sil | 138 ++++++++++++++++-------------- 1 file changed, 75 insertions(+), 63 deletions(-) diff --git a/test/SILOptimizer/accessutils.sil b/test/SILOptimizer/accessutils.sil index fe72f9cc42a20..b6d0c8c807089 100644 --- a/test/SILOptimizer/accessutils.sil +++ b/test/SILOptimizer/accessutils.sil @@ -12,13 +12,13 @@ import Swift import SwiftShims class List { - var x: Int + var x: Int64 let next: List } struct S { var l: List - var y: Int + var y: Int64 } struct Ptr { @@ -26,39 +26,39 @@ struct Ptr { } // CHECK-LABEL: Accesses for readIdentifiedArg -// CHECK-NEXT: Value: %0 = argument of bb0 : $*Int +// CHECK-NEXT: Value: %0 = argument of bb0 : $*Int64 // CHECK-NEXT: Scope: base -// CHECK-NEXT: Base: argument - %0 = argument of bb0 : $*Int +// CHECK-NEXT: Base: argument - %0 = argument of bb0 : $*Int64 // CHECK-NEXT: Path: "" -// CHECK-NEXT: Storage: %0 = argument of bb0 : $*Int +// CHECK-NEXT: Storage: %0 = argument of bb0 : $*Int64 // CHECK-NEXT: Path: "" // CHECK-NEXT: End accesses for readIdentifiedArg -sil [ossa] @readIdentifiedArg : $@convention(thin) (@in Int) -> Int { -bb0(%0 : $*Int): - %res = load [trivial] %0 : $*Int - return %res : $Int +sil [ossa] @readIdentifiedArg : $@convention(thin) (@in Int64) -> Int64 { +bb0(%0 : $*Int64): + %res = load [trivial] %0 : $*Int64 + return %res : $Int64 } // CHECK-LABEL: Accesses for writeIdentifiedArg -// CHECK-NEXT: Value: %0 = argument of bb0 : $*Int +// CHECK-NEXT: Value: %0 = argument of bb0 : $*Int64 // CHECK-NEXT: Scope: base -// CHECK-NEXT: Base: argument - %0 = argument of bb0 : $*Int +// CHECK-NEXT: Base: argument - %0 = argument of bb0 : $*Int64 // CHECK-NEXT: Path: "" -// CHECK-NEXT: Storage: %0 = argument of bb0 : $*Int +// CHECK-NEXT: Storage: %0 = argument of bb0 : $*Int64 // CHECK-NEXT: Path: "" // CHECK-NEXT: End accesses for writeIdentifiedArg -sil [ossa] @writeIdentifiedArg : $@convention(thin) (@inout Int) -> () { -bb0(%0 : $*Int): +sil [ossa] @writeIdentifiedArg : $@convention(thin) (@inout Int64) -> () { +bb0(%0 : $*Int64): %2 = integer_literal $Builtin.Int64, 42 - %3 = struct $Int (%2 : $Builtin.Int64) - store %3 to [trivial] %0 : $*Int + %3 = struct $Int64 (%2 : $Builtin.Int64) + store %3 to [trivial] %0 : $*Int64 %5 = tuple () return %5 : $() } // CHECK-LABEL: Accesses for $writeToHead -// CHECK-NEXT: Value: %7 = begin_access [modify] [dynamic] %6 : $*Int -// CHECK-NEXT: Scope: %7 = begin_access [modify] [dynamic] %6 : $*Int +// CHECK-NEXT: Value: %7 = begin_access [modify] [dynamic] %6 : $*Int64 +// CHECK-NEXT: Scope: %7 = begin_access [modify] [dynamic] %6 : $*Int64 // CHECK-NEXT: Base: class - %6 = ref_element_addr %5 : $List, #List.x // CHECK-NEXT: Path: "" // CHECK-NEXT: Storage: %0 = argument of bb0 : $S @@ -69,26 +69,26 @@ bb0(%0 : @guaranteed $S): debug_value %0 : $S, let, name "s", argno 1 %2 = struct_extract %0 : $S, #S.l %3 = integer_literal $Builtin.Int64, 10 - %4 = struct $Int (%3 : $Builtin.Int64) + %4 = struct $Int64 (%3 : $Builtin.Int64) %5 = begin_borrow [lexical] %2 : $List %6 = ref_element_addr %5 : $List, #List.x - %7 = begin_access [modify] [dynamic] %6 : $*Int - store %4 to [trivial] %7 : $*Int - end_access %7 : $*Int + %7 = begin_access [modify] [dynamic] %6 : $*Int64 + store %4 to [trivial] %7 : $*Int64 + end_access %7 : $*Int64 end_borrow %5 : $List %11 = tuple () return %11 : $() } // CHECK-LABEL: Accesses for storeToArgs -// CHECK-NEXT: Value: %6 = begin_access [modify] [dynamic] %5 : $*Int -// CHECK-NEXT: Scope: %6 = begin_access [modify] [dynamic] %5 : $*Int +// CHECK-NEXT: Value: %6 = begin_access [modify] [dynamic] %5 : $*Int64 +// CHECK-NEXT: Scope: %6 = begin_access [modify] [dynamic] %5 : $*Int64 // CHECK-NEXT: Base: class - %5 = ref_element_addr %0 : $List, #List.x // CHECK-NEXT: Path: "" // CHECK-NEXT: Storage: %0 = argument of bb0 : $List // CHECK-NEXT: Path: "c0" -// CHECK-NEXT: Value: %14 = begin_access [modify] [dynamic] %13 : $*Int -// CHECK-NEXT: Scope: %14 = begin_access [modify] [dynamic] %13 : $*Int +// CHECK-NEXT: Value: %14 = begin_access [modify] [dynamic] %13 : $*Int64 +// CHECK-NEXT: Scope: %14 = begin_access [modify] [dynamic] %13 : $*Int64 // CHECK-NEXT: Base: class - %13 = ref_element_addr %1 : $List, #List.x // CHECK-NEXT: Path: "" // CHECK-NEXT: Storage: %1 = argument of bb0 : $List @@ -100,21 +100,21 @@ bb0(%1 : @guaranteed $List, %2 : @guaranteed $List): bb1: %8 = integer_literal $Builtin.Int64, 10 - %9 = struct $Int (%8 : $Builtin.Int64) + %9 = struct $Int64 (%8 : $Builtin.Int64) %10 = ref_element_addr %1 : $List, #List.x - %11 = begin_access [modify] [dynamic] %10 : $*Int - store %9 to [trivial] %11 : $*Int - end_access %11 : $*Int + %11 = begin_access [modify] [dynamic] %10 : $*Int64 + store %9 to [trivial] %11 : $*Int64 + end_access %11 : $*Int64 %14 = tuple () br bb3 bb2: %16 = integer_literal $Builtin.Int64, 20 - %17 = struct $Int (%16 : $Builtin.Int64) + %17 = struct $Int64 (%16 : $Builtin.Int64) %18 = ref_element_addr %2 : $List, #List.x - %19 = begin_access [modify] [dynamic] %18 : $*Int - store %17 to [trivial] %19 : $*Int - end_access %19 : $*Int + %19 = begin_access [modify] [dynamic] %18 : $*Int64 + store %17 to [trivial] %19 : $*Int64 + end_access %19 : $*Int64 %22 = tuple () br bb3 @@ -124,8 +124,8 @@ bb3: } // CHECK-LABEL: Accesses for storeMaybeLocalPhi -// CHECK-NEXT: Value: %10 = begin_access [modify] [dynamic] %9 : $*Int -// CHECK-NEXT: Scope: %10 = begin_access [modify] [dynamic] %9 : $*Int +// CHECK-NEXT: Value: %10 = begin_access [modify] [dynamic] %9 : $*Int64 +// CHECK-NEXT: Scope: %10 = begin_access [modify] [dynamic] %9 : $*Int64 // CHECK-NEXT: Base: class - %9 = ref_element_addr %6 : $List, #List.x // CHECK-NEXT: Path: "" // CHECK-NEXT: Storage: %4 = alloc_ref $List @@ -147,11 +147,11 @@ bb2: bb3(%12 : $List): %14 = integer_literal $Builtin.Int64, 20 - %15 = struct $Int (%14 : $Builtin.Int64) + %15 = struct $Int64 (%14 : $Builtin.Int64) %16 = ref_element_addr %12 : $List, #List.x - %17 = begin_access [modify] [dynamic] %16 : $*Int - store %15 to %17 : $*Int - end_access %17 : $*Int + %17 = begin_access [modify] [dynamic] %16 : $*Int64 + store %15 to %17 : $*Int64 + end_access %17 : $*Int64 %20 = tuple () strong_release %12 : $List %22 = tuple () @@ -224,20 +224,20 @@ bb3(%6 : $Builtin.RawPointer) : // CHECK-LABEL: Accesses for readIdentifiedBoxArg -// CHECK-NEXT: Value: %2 = begin_access [read] [dynamic] %1 : $*Int -// CHECK-NEXT: Scope: %2 = begin_access [read] [dynamic] %1 : $*Int -// CHECK-NEXT: Base: box - %1 = project_box %0 : ${ var Int }, 0 +// CHECK-NEXT: Value: %2 = begin_access [read] [dynamic] %1 : $*Int64 +// CHECK-NEXT: Scope: %2 = begin_access [read] [dynamic] %1 : $*Int64 +// CHECK-NEXT: Base: box - %1 = project_box %0 : ${ var Int64 }, 0 // CHECK-NEXT: Path: "" -// CHECK-NEXT: Storage: %0 = argument of bb0 : ${ var Int } +// CHECK-NEXT: Storage: %0 = argument of bb0 : ${ var Int64 } // CHECK-NEXT: Path: "c0" // CHECK-NEXT: End accesses for readIdentifiedBoxArg -sil [ossa] @readIdentifiedBoxArg : $@convention(thin) (@guaranteed { var Int }) -> Int { -bb0(%0 : @guaranteed ${ var Int }): - %1 = project_box %0 : ${ var Int }, 0 - %5 = begin_access [read] [dynamic] %1 : $*Int - %6 = load [trivial] %5 : $*Int - end_access %5 : $*Int - return %6 : $Int +sil [ossa] @readIdentifiedBoxArg : $@convention(thin) (@guaranteed { var Int64 }) -> Int64 { +bb0(%0 : @guaranteed ${ var Int64 }): + %1 = project_box %0 : ${ var Int64 }, 0 + %5 = begin_access [read] [dynamic] %1 : $*Int64 + %6 = load [trivial] %5 : $*Int64 + end_access %5 : $*Int64 + return %6 : $Int64 } @@ -274,6 +274,18 @@ bb0(%0 : $Int64): return %99 : $() } +struct MySwiftArrayBodyStorage { + @_hasStorage var count : Int64 +} + +struct MyArrayBody { + @_hasStorage var _storage : MySwiftArrayBodyStorage +} + +class MyContiguousArrayStorageBase { + @_hasStorage var countAndCapacity : MyArrayBody +} + struct _MyBridgeStorage { @_hasStorage var rawValue : Builtin.BridgeObject } @@ -288,21 +300,21 @@ struct MyArray { } // CHECK-LABEL: Accesses for testRefTailAndStruct0 -// CHECK-NEXT: Value: %8 = struct_element_addr %7 : $*Int, #Int._value // user: %9 +// CHECK-NEXT: Value: %8 = struct_element_addr %7 : $*Int64, #Int64._value // user: %9 // CHECK-NEXT: Scope: base -// CHECK-NEXT: Base: class - %5 = ref_element_addr [immutable] %4 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity +// CHECK-NEXT: Base: class - %5 = ref_element_addr [immutable] %4 : $MyContiguousArrayStorageBase, #MyContiguousArrayStorageBase.countAndCapacity // CHECK-NEXT: Path: "s0.s0.s0" // CHECK-NEXT: Storage: %0 = argument of bb0 : $MyArray // CHECK-NEXT: Path: "s0.s0.s0.c0.s0.s0.s0" // CHECK-NEXT: Value: %11 = struct_element_addr %10 : $*String, #String._guts // CHECK-NEXT: Scope: base -// CHECK-NEXT: Base: tail - %10 = ref_tail_addr [immutable] %4 : $__ContiguousArrayStorageBase, $String +// CHECK-NEXT: Base: tail - %10 = ref_tail_addr [immutable] %4 : $MyContiguousArrayStorageBase, $String // CHECK-NEXT: Path: "s0" // CHECK-NEXT: Storage: %0 = argument of bb0 : $MyArray // CHECK-NEXT: Path: "s0.s0.s0.ct.s0" -// CHECK-NEXT: Value: %10 = ref_tail_addr [immutable] %4 : $__ContiguousArrayStorageBase, $String +// CHECK-NEXT: Value: %10 = ref_tail_addr [immutable] %4 : $MyContiguousArrayStorageBase, $String // CHECK-NEXT: Scope: base -// CHECK-NEXT: Base: tail - %10 = ref_tail_addr [immutable] %4 : $__ContiguousArrayStorageBase, $String +// CHECK-NEXT: Base: tail - %10 = ref_tail_addr [immutable] %4 : $MyContiguousArrayStorageBase, $String // CHECK-NEXT: Path: "" // CHECK-NEXT: Storage: %0 = argument of bb0 : $MyArray // CHECK-NEXT: Path: "s0.s0.s0.ct" @@ -312,16 +324,16 @@ bb0(%0 : $MyArray): %1 = struct_extract %0 : $MyArray, #MyArray._buffer %2 = struct_extract %1 : $_MyArrayBuffer, #_MyArrayBuffer._storage %3 = struct_extract %2 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue - %4 = unchecked_ref_cast %3 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase - %5 = ref_element_addr [immutable] %4 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity - %6 = struct_element_addr %5 : $*_ArrayBody, #_ArrayBody._storage - %7 = struct_element_addr %6 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage.count - %8 = struct_element_addr %7 : $*Int, #Int._value + %4 = unchecked_ref_cast %3 : $Builtin.BridgeObject to $MyContiguousArrayStorageBase + %5 = ref_element_addr [immutable] %4 : $MyContiguousArrayStorageBase, #MyContiguousArrayStorageBase.countAndCapacity + %6 = struct_element_addr %5 : $*MyArrayBody, #MyArrayBody._storage + %7 = struct_element_addr %6 : $*MySwiftArrayBodyStorage, #MySwiftArrayBodyStorage.count + %8 = struct_element_addr %7 : $*Int64, #Int64._value %9 = load %8 : $*Builtin.Int64 - %10 = ref_tail_addr [immutable] %4 : $__ContiguousArrayStorageBase, $String + %10 = ref_tail_addr [immutable] %4 : $MyContiguousArrayStorageBase, $String %11 = struct_element_addr %10 : $*String, #String._guts %12 = load %11 : $*_StringGuts %13 = load %10 : $*String %14 = tuple () return %14 : $() -} \ No newline at end of file +} From 6079452a58d073ef5cb48563cd436985d9ad4edc Mon Sep 17 00:00:00 2001 From: Xiaodi Wu <13952+xwu@users.noreply.github.com> Date: Tue, 16 Aug 2022 09:02:48 -0400 Subject: [PATCH 125/491] Re-alphabetize underscored attributes reference (#60558) --- docs/ReferenceGuides/UnderscoredAttributes.md | 99 +++++++++---------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/docs/ReferenceGuides/UnderscoredAttributes.md b/docs/ReferenceGuides/UnderscoredAttributes.md index d0c36a66d8145..3f4c1aae786e1 100644 --- a/docs/ReferenceGuides/UnderscoredAttributes.md +++ b/docs/ReferenceGuides/UnderscoredAttributes.md @@ -23,6 +23,10 @@ the Swift ABI. This attribute is intended for the SIMD types in the standard library which use it to increase the alignment of their internal storage to at least 16 bytes. +## `@_alwaysEmitConformanceMetadata` + +Forces conformances of the attributed protocol to always have their Type Metadata get emitted into the binary and prevents it from being optimized away or stripped by the linker. + ## `@_alwaysEmitIntoClient` Forces the body of a function to be emitted into client code. @@ -39,6 +43,14 @@ Most notably, default argument expressions are implicitly `@_alwaysEmitIntoClient`, which means that adding a default argument to a function which did not have one previously does not break ABI. +## `@_assemblyVision` + +Forces emission of assembly vision remarks for a function or method, showing +where various runtime calls and performance impacting hazards are in the code +at source level after optimization. + +Adding this attribute to a type leads to remarks being emitted for all methods. + ## `@_backDeploy(before: ...)` Causes the body of a function to be emitted into the module interface to be @@ -53,14 +65,6 @@ client is called instead. For more details, see the [pitch thread](https://forums.swift.org/t/pitch-function-back-deployment/55769/) in the forums. -## `@_assemblyVision` - -Forces emission of assembly vision remarks for a function or method, showing -where various runtime calls and performance impacting hazards are in the code -at source level after optimization. - -Adding this attribute to a type leads to remarks being emitted for all methods. - ## `@_borrowed` Indicates that the [conservative access pattern](/docs/Lexicon.md#access-pattern) @@ -482,6 +486,19 @@ Fun fact: Rust has a very similar concept called including one called `Send`, which inspired the design of `Sendable`. +## `@_noAllocation`, `@_noLocks` + +These attributes are performance annotations. If a function is annotated with +such an attribute, the compiler issues a diagnostic message if the function +calls a runtime function which allocates memory or locks, respectively. +The `@_noLocks` attribute implies `@_noAllocation` because a memory allocation +also locks. + +## `@_noImplicitCopy` + +Marks a var decl as a variable that must be copied explicitly using the builtin +function Builtin.copy. + ## `@_nonEphemeral` Marks a function parameter that cannot accept a temporary pointer produced from @@ -755,6 +772,14 @@ Clients can access SPI by marking the import as `@_spi(spiName) import Module`. This design makes it easy to find out which clients are using certain SPIs by doing a textual search. +## `@_spi_available(platform, version)` + +Like `@available`, this attribute indicates a decl is available only as an SPI. +This implies several behavioral changes comparing to regular `@available`: +1. Type checker diagnoses when a client accidently exposes such a symbol in library APIs. +2. When emitting public interfaces, `@_spi_available` is printed as `@available(platform, unavailable)`. +3. ClangImporter imports ObjC macros `SPI_AVAILABLE` and `__SPI_AVAILABLE` to this attribute. + ## `@_staticInitializeObjCMetadata` Indicates that a static initializer should be emitted to register the @@ -789,19 +814,11 @@ A type eraser has the following restrictions: This feature was designed to be used for compiler-driven type erasure for dynamic replacement of functions with an opaque return type. -## `@_weakLinked` - -Allows a declaration to be weakly-referenced, i.e., any references emitted by -client modules to the declaration's symbol will have weak linkage. This means -that client code will compile without the guarantee that the symbol will be -available at runtime. This requires a dynamic safety check (such as using -`dlsym (3)`); otherwise, accessing the symbol when it is unavailable leads -to a runtime crash. +## `@_unavailableFromAsync` -This is an unsafe alternative to using `@available`, which is statically checked. -If the availability of a library symbol is newer than the deployment target of -the client, the symbol will be weakly linked, but checking for `@available` and -`#(un)available` ensures that a symbol is not accessed when it is unavailable. +Marks a synchronous API as being unavailable from asynchronous contexts. Direct +usage of annotated API from asynchronous contexts will result in a warning from +the compiler. ## `@_unsafeMainActor`, `@_unsafeSendable` @@ -812,38 +829,23 @@ within Swift 5 code that has adopted concurrency, but non-`@MainActor` See the forum post on [Concurrency in Swift 5 and 6](https://forums.swift.org/t/concurrency-in-swift-5-and-6/49337) for more details. -## `@_noImplicitCopy` - -Marks a var decl as a variable that must be copied explicitly using the builtin -function Builtin.copy. - -## `@_noAllocation`, `@_noLocks` - -These attributes are performance annotations. If a function is annotated with -such an attribute, the compiler issues a diagnostic message if the function -calls a runtime function which allocates memory or locks, respectively. -The `@_noLocks` attribute implies `@_noAllocation` because a memory allocation -also locks. - -## `@_unavailableFromAsync` - -Marks a synchronous API as being unavailable from asynchronous contexts. Direct -usage of annotated API from asynchronous contexts will result in a warning from -the compiler. - ## `@_unsafeInheritExecutor` This `async` function uses the pre-SE-0338 semantics of unsafely inheriting the caller's executor. This is an underscored feature because the right way of inheriting an executor is to pass in the required executor and switch to it. Unfortunately, there are functions in the standard library which need to inherit their caller's executor but cannot change their ABI because they were not defined as `@_alwaysEmitIntoClient` in the initial release. +## `@_weakLinked` -## `@_spi_available(platform, version)` - -Like `@available`, this attribute indicates a decl is available only as an SPI. -This implies several behavioral changes comparing to regular `@available`: -1. Type checker diagnoses when a client accidently exposes such a symbol in library APIs. -2. When emitting public interfaces, `@_spi_available` is printed as `@available(platform, unavailable)`. -3. ClangImporter imports ObjC macros `SPI_AVAILABLE` and `__SPI_AVAILABLE` to this attribute. +Allows a declaration to be weakly-referenced, i.e., any references emitted by +client modules to the declaration's symbol will have weak linkage. This means +that client code will compile without the guarantee that the symbol will be +available at runtime. This requires a dynamic safety check (such as using +`dlsym (3)`); otherwise, accessing the symbol when it is unavailable leads +to a runtime crash. +This is an unsafe alternative to using `@available`, which is statically checked. +If the availability of a library symbol is newer than the deployment target of +the client, the symbol will be weakly linked, but checking for `@available` and +`#(un)available` ensures that a symbol is not accessed when it is unavailable. ## `_local` @@ -852,8 +854,3 @@ the distributed actor isolation checks. This is used for things like `whenLocal` where the actor passed to the closure is known-to-be-local, and similarly a `self` of obtained from an _isolated_ function inside a distributed actor is also guaranteed to be local by construction. - - -## `@_alwaysEmitConformanceMetadata` - -Forces conformances of the attributed protocol to always have their Type Metadata get emitted into the binary and prevents it from being optimized away or stripped by the linker. From e22e44359638896cb007a7f6adf9be506e62ebc0 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Tue, 16 Aug 2022 16:02:23 +0200 Subject: [PATCH 126/491] [SourceKit] Re-enable cancellation of non-completion requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables the ability to cancel requests, which aren’t code completion requests, again. Previous crashes in SILGen are prevented by disabling cancellation during the SIL stages. Instead, we add dedicated cancellation checkpoints before and after SIL. rdar://98390926 --- test/SourceKit/Diagnostics/cancel_diags.swift | 7 +++++++ tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp | 11 +++++++++++ tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp | 4 ++++ unittests/SourceKit/SwiftLang/CursorInfoTest.cpp | 6 ++---- 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 test/SourceKit/Diagnostics/cancel_diags.swift diff --git a/test/SourceKit/Diagnostics/cancel_diags.swift b/test/SourceKit/Diagnostics/cancel_diags.swift new file mode 100644 index 0000000000000..7b4281d240693 --- /dev/null +++ b/test/SourceKit/Diagnostics/cancel_diags.swift @@ -0,0 +1,7 @@ +// RUN: not %sourcekitd-test -req=diags %s -print-raw-response -id=diag -async -- %s == -cancel=diag 2>&1 | %FileCheck %s + +func foo(x: Invalid1, y: Invalid2) { + x / y / x / y / x / y / x / y +} + +// CHECK: error response (Request Cancelled) diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index 03f4454413ad1..4b2e4c7e84e02 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -1069,6 +1069,7 @@ ASTUnitRef ASTBuildOperation::buildASTUnit(std::string &Error) { } return nullptr; } + CompIns.getASTContext().CancellationFlag = CancellationFlag; registerIDERequestFunctions(CompIns.getASTContext().evaluator); if (TracedOp.enabled()) { TracedOp.start(TraceInfo); @@ -1112,9 +1113,19 @@ ASTUnitRef ASTBuildOperation::buildASTUnit(std::string &Error) { // don't block any other AST processing for the same SwiftInvocation. if (auto SF = CompIns.getPrimarySourceFile()) { + if (CancellationFlag->load(std::memory_order_relaxed)) { + return nullptr; + } + // Disable cancellation while performing SILGen. If the cancellation flag + // is set, type checking performed during SILGen checks the cancellation + // flag and might thus fail, which SILGen cannot handle. + llvm::SaveAndRestore>> DisableCancellationDuringSILGen(CompIns.getASTContext().CancellationFlag, nullptr); SILOptions SILOpts = Invocation.getSILOptions(); auto &TC = CompIns.getSILTypes(); std::unique_ptr SILMod = performASTLowering(*SF, TC, SILOpts); + if (CancellationFlag->load(std::memory_order_relaxed)) { + return nullptr; + } runSILDiagnosticPasses(*SILMod); } } diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp index c3bbb16d51f3b..6adf5eedd1444 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp @@ -1621,6 +1621,10 @@ static void computeDiagnostics( auto Diagnostics = DiagConsumer.getDiagnosticsForBuffer(BufferID); Receiver(RequestResult::fromResult(Diagnostics)); } + + void cancelled() override { + Receiver(RequestResult::cancelled()); + } }; auto Consumer = std::make_shared(std::move(Receiver)); diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp index 6c113f363d235..bdc872a538add 100644 --- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp +++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp @@ -424,8 +424,7 @@ TEST_F(CursorInfoTest, CursorInfoMustWaitDueTokenRace) { EXPECT_EQ(strlen("fog"), Info.Length); } -// Disabled until we re-enable cancellation (rdar://91251055) -TEST_F(CursorInfoTest, DISABLED_CursorInfoCancelsPreviousRequest) { +TEST_F(CursorInfoTest, CursorInfoCancelsPreviousRequest) { // TODO: This test case relies on the following snippet being slow to type // check so that the first cursor info request takes longer to execute than it // takes time to schedule the second request. If that is fixed, we need to @@ -475,8 +474,7 @@ TEST_F(CursorInfoTest, DISABLED_CursorInfoCancelsPreviousRequest) { llvm::report_fatal_error("Did not receive a resonse for the first request"); } -// Disabled until we re-enable cancellation (rdar://91251055) -TEST_F(CursorInfoTest, DISABLED_CursorInfoCancellation) { +TEST_F(CursorInfoTest, CursorInfoCancellation) { // TODO: This test case relies on the following snippet being slow to type // check so that the first cursor info request takes longer to execute than it // takes time to schedule the second request. If that is fixed, we need to From 7fd2a29fb7a5f67c2b0dc8ae6a446251e45b9b23 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Thu, 4 Aug 2022 14:40:09 -0700 Subject: [PATCH 127/491] Refactor 'ModuleInterfaceBuilder' to separate CompilerInstance setup logic from compilation logic (moved to ExplicitModuleInterfaceBuilder). --- include/swift/AST/ModuleLoader.h | 2 - include/swift/Frontend/FrontendOptions.h | 2 +- .../swift/Frontend/ModuleInterfaceLoader.h | 22 +- include/swift/Option/FrontendOptions.td | 6 +- .../ArgsToFrontendOptionsConverter.cpp | 4 +- lib/Frontend/Frontend.cpp | 5 +- lib/Frontend/ModuleInterfaceBuilder.cpp | 343 +++++++++--------- lib/Frontend/ModuleInterfaceBuilder.h | 166 ++++++--- lib/Frontend/ModuleInterfaceLoader.cpp | 66 ++-- lib/FrontendTool/FrontendTool.cpp | 3 + lib/Serialization/ModuleDependencyScanner.cpp | 1 - 11 files changed, 357 insertions(+), 263 deletions(-) diff --git a/include/swift/AST/ModuleLoader.h b/include/swift/AST/ModuleLoader.h index 7b4a7d0b48d5d..8c7520dcf0c16 100644 --- a/include/swift/AST/ModuleLoader.h +++ b/include/swift/AST/ModuleLoader.h @@ -165,7 +165,6 @@ struct InterfaceSubContextDelegate { StringRef interfacePath, StringRef outputPath, SourceLoc diagLoc, - bool ignoreInterfaceProvidedOptions, llvm::function_ref, ArrayRef, StringRef)> action) = 0; @@ -173,7 +172,6 @@ struct InterfaceSubContextDelegate { StringRef interfacePath, StringRef outputPath, SourceLoc diagLoc, - bool ignoreInterfaceProvidedOptions, llvm::function_ref action) = 0; virtual ~InterfaceSubContextDelegate() = default; diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 52d845a7be017..bbe2123020087 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -110,7 +110,7 @@ class FrontendOptions { /// If building a module from interface, ignore compiler flags /// specified in the swiftinterface. - bool IgnoreInterfaceProvidedOptions = false; + bool ExplicitInterfaceBuild = false; /// The module for which we should verify all of the generic signatures. std::string VerifyGenericSignaturesInModule; diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index 478363a83ce58..fc085b14bbb81 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -300,7 +300,6 @@ struct ModuleInterfaceLoaderOptions { bool disableImplicitSwiftModule = false; bool disableBuildingInterface = false; bool downgradeInterfaceVerificationError = false; - bool ignoreInterfaceProvidedOptions = false; std::string mainExecutablePath; ModuleInterfaceLoaderOptions(const FrontendOptions &Opts): remarkOnRebuildFromInterface(Opts.RemarkOnRebuildFromModuleInterface), @@ -308,7 +307,6 @@ struct ModuleInterfaceLoaderOptions { disableImplicitSwiftModule(Opts.DisableImplicitModules), disableBuildingInterface(Opts.DisableBuildingInterface), downgradeInterfaceVerificationError(Opts.DowngradeInterfaceVerificationError), - ignoreInterfaceProvidedOptions(Opts.IgnoreInterfaceProvidedOptions), mainExecutablePath(Opts.MainExecutablePath) { switch (Opts.RequestedAction) { @@ -442,6 +440,21 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { bool SerializeDependencyHashes, bool TrackSystemDependencies, ModuleInterfaceLoaderOptions Opts, RequireOSSAModules_t RequireOSSAModules); + + /// Unconditionally build \p InPath (a swiftinterface file) to \p OutPath (as + /// a swiftmodule file). + /// + /// Unlike the above `buildSwiftModuleFromSwiftInterface`, this method + /// bypasses the instantiation of a `CompilerInstance` from the compiler + /// configuration flags in the interface and instead directly uses the + /// supplied \p Instance + static bool buildExplicitSwiftModuleFromSwiftInterface( + CompilerInstance &Instance, const StringRef moduleCachePath, + const StringRef backupInterfaceDir, const StringRef prebuiltCachePath, + const StringRef ABIDescriptorPath, StringRef interfacePath, + StringRef outputPath, bool ShouldSerializeDeps, + ArrayRef CompiledCandidates, StringRef CompilerVersion, + DependencyTracker *tracker = nullptr); }; struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { @@ -476,8 +489,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { SmallVectorImpl &SubArgs, std::string &CompilerVersion, StringRef interfacePath, - SourceLoc diagnosticLoc, - bool ignoreInterfaceProvidedOptions); + SourceLoc diagnosticLoc); public: InterfaceSubContextDelegateImpl( SourceManager &SM, DiagnosticEngine *Diags, @@ -492,7 +504,6 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { StringRef interfacePath, StringRef outputPath, SourceLoc diagLoc, - bool ignoreInterfaceProvidedOptions, llvm::function_ref, ArrayRef, StringRef)> action) override; @@ -500,7 +511,6 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { StringRef interfacePath, StringRef outputPath, SourceLoc diagLoc, - bool ignoreInterfaceProvidedOptions, llvm::function_ref action) override; ~InterfaceSubContextDelegateImpl() = default; diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 9260e6a84e94c..c4828fa8f3218 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -877,9 +877,9 @@ def compile_module_from_interface : HelpText<"Treat the (single) input as a swiftinterface and produce a module">, ModeOpt; -def ignore_interface_provided_options : - Flag<["-"], "ignore-interface-provided-options">, - HelpText<"Ignore all module flags specified in the swiftinterface being built">; +def explicit_interface_module_build : + Flag<["-"], "explicit-interface-module-build">, + HelpText<"Use the specified command-line to build the module from interface, instead of flags specified in the interface">; def build_module_from_parseable_interface : Flag<["-"], "build-module-from-parseable-interface">, diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index e53eb16f3abc3..0607b04395cdc 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -83,7 +83,7 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.EnablePrivateImports |= Args.hasArg(OPT_enable_private_imports); Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_library_evolution); Opts.FrontendParseableOutput |= Args.hasArg(OPT_frontend_parseable_output); - Opts.IgnoreInterfaceProvidedOptions |= Args.hasArg(OPT_ignore_interface_provided_options); + Opts.ExplicitInterfaceBuild |= Args.hasArg(OPT_explicit_interface_module_build); // FIXME: Remove this flag Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_resilience); @@ -622,7 +622,7 @@ bool ArgsToFrontendOptionsConverter:: bool ArgsToFrontendOptionsConverter::checkBuildFromInterfaceOnlyOptions() const { if (Opts.RequestedAction != FrontendOptions::ActionType::CompileModuleFromInterface && - Opts.IgnoreInterfaceProvidedOptions) { + Opts.ExplicitInterfaceBuild) { Diags.diagnose(SourceLoc(), diag::error_cannot_ignore_interface_options_in_mode); return true; diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index de34857b5c7bc..2df1ce62c71e5 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -211,10 +211,11 @@ void CompilerInstance::recordPrimaryInputBuffer(unsigned BufID) { } bool CompilerInstance::setUpASTContextIfNeeded() { - if (Invocation.getFrontendOptions().RequestedAction == + if ((Invocation.getFrontendOptions().RequestedAction == FrontendOptions::ActionType::CompileModuleFromInterface || Invocation.getFrontendOptions().RequestedAction == - FrontendOptions::ActionType::TypecheckModuleFromInterface) { + FrontendOptions::ActionType::TypecheckModuleFromInterface) && + !Invocation.getFrontendOptions().ExplicitInterfaceBuild) { // Compiling a module interface from source uses its own CompilerInstance // with options read from the input file. Don't bother setting up an // ASTContext at this level. diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index 6b2874164dd53..62f4875b21857 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -68,20 +68,47 @@ static Optional getRelativeDepPath(StringRef DepPath, return None; } -bool ModuleInterfaceBuilder::collectDepsForSerialization( - CompilerInstance &SubInstance, SmallVectorImpl &Deps, +struct ErrorDowngradeConsumerRAII: DiagnosticConsumer { + DiagnosticEngine &Diag; + std::vector allConsumers; + bool SeenError; + ErrorDowngradeConsumerRAII(DiagnosticEngine &Diag): Diag(Diag), + allConsumers(Diag.takeConsumers()), SeenError(false) { + Diag.addConsumer(*this); + } + ~ErrorDowngradeConsumerRAII() { + for (auto *consumer: allConsumers) { + Diag.addConsumer(*consumer); + } + Diag.removeConsumer(*this); + } + void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override { + DiagnosticInfo localInfo(Info); + if (localInfo.Kind == DiagnosticKind::Error) { + localInfo.Kind = DiagnosticKind::Warning; + SeenError = true; + for (auto *consumer: allConsumers) { + consumer->handleDiagnostic(SM, localInfo); + } + } + } +}; + +bool ExplicitModuleInterfaceBuilder::collectDepsForSerialization( + SmallVectorImpl &Deps, StringRef interfacePath, bool IsHashBased) { - llvm::vfs::FileSystem &fs = *sourceMgr.getFileSystem(); + llvm::vfs::FileSystem &fs = *Instance.getSourceMgr().getFileSystem(); - auto &Opts = SubInstance.getASTContext().SearchPathOpts; + auto &Opts = Instance.getASTContext().SearchPathOpts; SmallString<128> SDKPath(Opts.getSDKPath()); path::native(SDKPath); SmallString<128> ResourcePath(Opts.RuntimeResourcePath); path::native(ResourcePath); - auto DTDeps = SubInstance.getDependencyTracker()->getDependencies(); + auto DTDeps = Instance.getDependencyTracker()->getDependencies(); SmallVector InitialDepNames(DTDeps.begin(), DTDeps.end()); - auto IncDeps = SubInstance.getDependencyTracker()->getIncrementalDependencyPaths(); + auto IncDeps = + Instance.getDependencyTracker()->getIncrementalDependencyPaths(); InitialDepNames.append(IncDeps.begin(), IncDeps.end()); InitialDepNames.push_back(interfacePath.str()); for (const auto &extra : extraDependencies) { @@ -105,12 +132,12 @@ bool ModuleInterfaceBuilder::collectDepsForSerialization( if (!prebuiltCachePath.empty() && DepName.startswith(prebuiltCachePath)) continue; // Don't serialize interface path if it's from the preferred interface dir. - // This ensures the prebuilt module caches generated from these interfaces are - // relocatable. + // This ensures the prebuilt module caches generated from these interfaces + // are relocatable. if (!backupInterfaceDir.empty() && DepName.startswith(backupInterfaceDir)) continue; if (dependencyTracker) { - dependencyTracker->addDependency(DepName, /*isSystem*/IsSDKRelative); + dependencyTracker->addDependency(DepName, /*isSystem*/ IsSDKRelative); } // Don't serialize compiler-relative deps so the cache is relocatable. @@ -126,7 +153,8 @@ bool ModuleInterfaceBuilder::collectDepsForSerialization( /// not a .swiftmodule, we can avoid opening the buffer. std::unique_ptr DepBuf = nullptr; auto getDepBuf = [&]() -> llvm::MemoryBuffer * { - if (DepBuf) return DepBuf.get(); + if (DepBuf) + return DepBuf.get(); if (auto Buf = fs.getBufferForFile(DepName, /*FileSize=*/-1, /*RequiresNullTerminator=*/false)) { DepBuf = std::move(Buf.get()); @@ -137,52 +165,148 @@ bool ModuleInterfaceBuilder::collectDepsForSerialization( if (IsHashBased) { auto buf = getDepBuf(); - if (!buf) return true; + if (!buf) + return true; uint64_t hash = xxHash64(buf->getBuffer()); - Deps.push_back( - FileDependency::hashBased(DepNameToStore, IsSDKRelative, + Deps.push_back(FileDependency::hashBased(DepNameToStore, IsSDKRelative, Status->getSize(), hash)); } else { uint64_t mtime = - Status->getLastModificationTime().time_since_epoch().count(); - Deps.push_back( - FileDependency::modTimeBased(DepNameToStore, IsSDKRelative, + Status->getLastModificationTime().time_since_epoch().count(); + Deps.push_back(FileDependency::modTimeBased(DepNameToStore, IsSDKRelative, Status->getSize(), mtime)); } } return false; } -struct ErrorDowngradeConsumerRAII: DiagnosticConsumer { - DiagnosticEngine &Diag; - std::vector allConsumers; - bool SeenError; - ErrorDowngradeConsumerRAII(DiagnosticEngine &Diag): Diag(Diag), - allConsumers(Diag.takeConsumers()), SeenError(false) { - Diag.addConsumer(*this); +std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface( + StringRef interfacePath, StringRef outputPath, bool ShouldSerializeDeps, + std::unique_ptr *ModuleBuffer, + ArrayRef compiledCandidates, + StringRef CompilerVersion) { + auto Invocation = Instance.getInvocation(); + // Try building forwarding module first. If succeed, return. + if (Instance.getASTContext() + .getModuleInterfaceChecker() + ->tryEmitForwardingModule(Invocation.getModuleName(), interfacePath, + compiledCandidates, outputPath)) { + return std::error_code(); } - ~ErrorDowngradeConsumerRAII() { - for (auto *consumer: allConsumers) { - Diag.addConsumer(*consumer); - } - Diag.removeConsumer(*this); + FrontendOptions &FEOpts = Invocation.getFrontendOptions(); + bool isTypeChecking = + (FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck); + const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput(); + StringRef InPath = InputInfo.getFileName(); + const auto &OutputInfo = + InputInfo.getPrimarySpecificPaths().SupplementaryOutputs; + StringRef OutPath = OutputInfo.ModuleOutputPath; + + // Build the .swiftmodule; this is a _very_ abridged version of the logic + // in performCompile in libFrontendTool, specialized, to just the one + // module-serialization task we're trying to do here. + LLVM_DEBUG(llvm::dbgs() << "Setting up instance to compile " << InPath + << " to " << OutPath << "\n"); + + LLVM_DEBUG(llvm::dbgs() << "Performing sema\n"); + if (isTypeChecking && FEOpts.DowngradeInterfaceVerificationError) { + ErrorDowngradeConsumerRAII R(Instance.getDiags()); + Instance.performSema(); + return std::error_code(); } - void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override { - DiagnosticInfo localInfo(Info); - if (localInfo.Kind == DiagnosticKind::Error) { - localInfo.Kind = DiagnosticKind::Warning; - SeenError = true; - for (auto *consumer: allConsumers) { - consumer->handleDiagnostic(SM, localInfo); + SWIFT_DEFER { + // Make sure to emit a generic top-level error if a module fails to + // load. This is not only good for users; it also makes sure that we've + // emitted an error in the parent diagnostic engine, which is what + // determines whether the process exits with a proper failure status. + if (Instance.getASTContext().hadError()) { + auto builtByCompiler = getSwiftInterfaceCompilerVersionForCurrentCompiler( + Instance.getASTContext()); + + if (!isTypeChecking && CompilerVersion.str() != builtByCompiler) { + diagnose(diag::module_interface_build_failed_mismatching_compiler, + InterfacePath, + Invocation.getModuleName(), + CompilerVersion, + builtByCompiler); + } else { + diagnose(diag::module_interface_build_failed, + InterfacePath, + isTypeChecking, + Invocation.getModuleName(), + CompilerVersion.str() == builtByCompiler, + CompilerVersion.str(), + builtByCompiler); } } + }; + + Instance.performSema(); + if (Instance.getASTContext().hadError()) { + LLVM_DEBUG(llvm::dbgs() << "encountered errors\n"); + return std::make_error_code(std::errc::not_supported); + } + // If we are just type-checking the interface, we are done. + if (isTypeChecking) + return std::error_code(); + + SILOptions &SILOpts = Invocation.getSILOptions(); + auto Mod = Instance.getMainModule(); + auto &TC = Instance.getSILTypes(); + auto SILMod = performASTLowering(Mod, TC, SILOpts); + if (!SILMod) { + LLVM_DEBUG(llvm::dbgs() << "SILGen did not produce a module\n"); + return std::make_error_code(std::errc::not_supported); } -}; -bool ModuleInterfaceBuilder::buildSwiftModuleInternal( + // Setup the callbacks for serialization, which can occur during the + // optimization pipeline. + SerializationOptions SerializationOpts; + std::string OutPathStr = OutPath.str(); + SerializationOpts.OutputPath = OutPathStr.c_str(); + SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName; + SerializationOpts.AutolinkForceLoad = + !Invocation.getIRGenOptions().ForceLoadSymbolName.empty(); + SerializationOpts.UserModuleVersion = FEOpts.UserModuleVersion; + + // Record any non-SDK module interface files for the debug info. + StringRef SDKPath = Instance.getASTContext().SearchPathOpts.getSDKPath(); + if (!getRelativeDepPath(InPath, SDKPath)) + SerializationOpts.ModuleInterface = InPath; + + SerializationOpts.SDKName = Instance.getASTContext().LangOpts.SDKName; + SerializationOpts.ABIDescriptorPath = ABIDescriptorPath.str(); + SmallVector Deps; + bool serializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes; + if (collectDepsForSerialization(Deps, interfacePath, serializeHashes)) { + return std::make_error_code(std::errc::not_supported); + } + if (ShouldSerializeDeps) + SerializationOpts.Dependencies = Deps; + SerializationOpts.IsOSSA = SILOpts.EnableOSSAModules; + + SILMod->setSerializeSILAction([&]() { + // We don't want to serialize module docs in the cache -- they + // will be serialized beside the interface file. + serializeToBuffers(Mod, SerializationOpts, ModuleBuffer, + /*ModuleDocBuffer*/ nullptr, + /*SourceInfoBuffer*/ nullptr, SILMod.get()); + }); + + LLVM_DEBUG(llvm::dbgs() << "Running SIL processing passes\n"); + if (Instance.performSILProcessing(SILMod.get())) { + LLVM_DEBUG(llvm::dbgs() << "encountered errors\n"); + return std::make_error_code(std::errc::not_supported); + } + if (Instance.getDiags().hadAnyError()) { + return std::make_error_code(std::errc::not_supported); + } + return std::error_code(); +} + +bool ImplicitModuleInterfaceBuilder::buildSwiftModuleInternal( StringRef OutPath, bool ShouldSerializeDeps, - bool IgnoreInterfaceProvidedOptions, std::unique_ptr *ModuleBuffer, ArrayRef CompiledCandidates) { @@ -198,140 +322,31 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( llvm::RestorePrettyStackState(savedInnerPrettyStackState); }; - SubError = (bool)subASTDelegate.runInSubCompilerInstance(moduleName, - interfacePath, - OutPath, - diagnosticLoc, - IgnoreInterfaceProvidedOptions, - [&](SubCompilerInstanceInfo &info) { - auto &SubInstance = *info.Instance; - auto subInvocation = SubInstance.getInvocation(); - // Try building forwarding module first. If succeed, return. - if (SubInstance.getASTContext().getModuleInterfaceChecker() - ->tryEmitForwardingModule(moduleName, interfacePath, - CompiledCandidates, OutPath)) { - return std::error_code(); - } - FrontendOptions &FEOpts = subInvocation.getFrontendOptions(); - bool isTypeChecking = - (FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck); - const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput(); - StringRef InPath = InputInfo.getFileName(); - const auto &OutputInfo = - InputInfo.getPrimarySpecificPaths().SupplementaryOutputs; - StringRef OutPath = OutputInfo.ModuleOutputPath; - - // Build the .swiftmodule; this is a _very_ abridged version of the logic - // in performCompile in libFrontendTool, specialized, to just the one - // module-serialization task we're trying to do here. - LLVM_DEBUG(llvm::dbgs() << "Setting up instance to compile " - << InPath << " to " << OutPath << "\n"); - - LLVM_DEBUG(llvm::dbgs() << "Performing sema\n"); - if (isTypeChecking && FEOpts.DowngradeInterfaceVerificationError) { - ErrorDowngradeConsumerRAII R(SubInstance.getDiags()); - SubInstance.performSema(); - return std::error_code(); - } - SWIFT_DEFER { - // Make sure to emit a generic top-level error if a module fails to - // load. This is not only good for users; it also makes sure that we've - // emitted an error in the parent diagnostic engine, which is what - // determines whether the process exits with a proper failure status. - if (SubInstance.getASTContext().hadError()) { - auto builtByCompiler = - getSwiftInterfaceCompilerVersionForCurrentCompiler( - SubInstance.getASTContext()); - StringRef emittedByCompiler = info.CompilerVersion; - if (!isTypeChecking && emittedByCompiler != builtByCompiler) { - diagnose(diag::module_interface_build_failed_mismatching_compiler, - moduleName, emittedByCompiler, builtByCompiler); - } else { - diagnose(diag::module_interface_build_failed, isTypeChecking, - moduleName, emittedByCompiler == builtByCompiler, - emittedByCompiler, builtByCompiler); - } - } - }; - - SubInstance.performSema(); - if (SubInstance.getASTContext().hadError()) { - LLVM_DEBUG(llvm::dbgs() << "encountered errors\n"); - return std::make_error_code(std::errc::not_supported); - } - // If we are just type-checking the interface, we are done. - if (isTypeChecking) - return std::error_code(); - - SILOptions &SILOpts = subInvocation.getSILOptions(); - auto Mod = SubInstance.getMainModule(); - auto &TC = SubInstance.getSILTypes(); - auto SILMod = performASTLowering(Mod, TC, SILOpts); - if (!SILMod) { - LLVM_DEBUG(llvm::dbgs() << "SILGen did not produce a module\n"); - return std::make_error_code(std::errc::not_supported); - } - - // Setup the callbacks for serialization, which can occur during the - // optimization pipeline. - SerializationOptions SerializationOpts; - std::string OutPathStr = OutPath.str(); - SerializationOpts.OutputPath = OutPathStr; - SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName; - SerializationOpts.AutolinkForceLoad = - !subInvocation.getIRGenOptions().ForceLoadSymbolName.empty(); - SerializationOpts.UserModuleVersion = FEOpts.UserModuleVersion; - - // Record any non-SDK module interface files for the debug info. - StringRef SDKPath = SubInstance.getASTContext().SearchPathOpts.getSDKPath(); - if (!getRelativeDepPath(InPath, SDKPath)) - SerializationOpts.ModuleInterface = InPath; - - SerializationOpts.SDKName = SubInstance.getASTContext().LangOpts.SDKName; - SerializationOpts.ABIDescriptorPath = ABIDescriptorPath.str(); - SmallVector Deps; - bool serializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes; - if (collectDepsForSerialization(SubInstance, Deps, serializeHashes)) { - return std::make_error_code(std::errc::not_supported); - } - if (ShouldSerializeDeps) - SerializationOpts.Dependencies = Deps; - SerializationOpts.IsOSSA = SILOpts.EnableOSSAModules; - - SILMod->setSerializeSILAction([&]() { - // We don't want to serialize module docs in the cache -- they - // will be serialized beside the interface file. - serializeToBuffers(Mod, SerializationOpts, ModuleBuffer, - /*ModuleDocBuffer*/nullptr, - /*SourceInfoBuffer*/nullptr, - SILMod.get()); - }); - - LLVM_DEBUG(llvm::dbgs() << "Running SIL processing passes\n"); - if (SubInstance.performSILProcessing(SILMod.get())) { - LLVM_DEBUG(llvm::dbgs() << "encountered errors\n"); - return std::make_error_code(std::errc::not_supported); - } - if (SubInstance.getDiags().hadAnyError()) { - return std::make_error_code(std::errc::not_supported); - } - return std::error_code(); - }); + SubError = (bool)subASTDelegate.runInSubCompilerInstance( + moduleName, interfacePath, OutPath, diagnosticLoc, + [&](SubCompilerInstanceInfo &info) { + auto EBuilder = ExplicitModuleInterfaceBuilder( + *info.Instance, diags, sourceMgr, moduleCachePath, backupInterfaceDir, + prebuiltCachePath, ABIDescriptorPath, extraDependencies, diagnosticLoc, + dependencyTracker); + return EBuilder.buildSwiftModuleFromInterface( + interfacePath, OutPath, ShouldSerializeDeps, ModuleBuffer, + CompiledCandidates, info.CompilerVersion); + }); }, ThreadStackSize); return !RunSuccess || SubError; } -bool ModuleInterfaceBuilder::buildSwiftModule(StringRef OutPath, - bool ShouldSerializeDeps, - bool IgnoreInterfaceProvidedOptions, - std::unique_ptr *ModuleBuffer, - llvm::function_ref RemarkRebuild, - ArrayRef CompiledCandidates) { +bool ImplicitModuleInterfaceBuilder::buildSwiftModule(StringRef OutPath, + bool ShouldSerializeDeps, + std::unique_ptr *ModuleBuffer, + llvm::function_ref RemarkRebuild, + ArrayRef CompiledCandidates) { auto build = [&]() { if (RemarkRebuild) { RemarkRebuild(); } - return buildSwiftModuleInternal(OutPath, ShouldSerializeDeps, IgnoreInterfaceProvidedOptions, + return buildSwiftModuleInternal(OutPath, ShouldSerializeDeps, ModuleBuffer, CompiledCandidates); }; if (disableInterfaceFileLock) { diff --git a/lib/Frontend/ModuleInterfaceBuilder.h b/lib/Frontend/ModuleInterfaceBuilder.h index 4e92247ae31df..3d4e7ee022d5f 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.h +++ b/lib/Frontend/ModuleInterfaceBuilder.h @@ -13,10 +13,10 @@ #ifndef SWIFT_FRONTEND_MODULEINTERFACEBUILDER_H #define SWIFT_FRONTEND_MODULEINTERFACEBUILDER_H +#include "swift/AST/ModuleLoader.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/SourceLoc.h" #include "swift/Frontend/Frontend.h" -#include "swift/AST/ModuleLoader.h" #include "swift/Serialization/SerializationOptions.h" #include "llvm/Support/StringSaver.h" @@ -24,7 +24,7 @@ namespace llvm { namespace vfs { class FileSystem; } -} +} // namespace llvm namespace swift { @@ -33,7 +33,10 @@ class LangOptions; class SearchPathOptions; class DependencyTracker; -class ModuleInterfaceBuilder { +/// A utility class to build a Swift interface file into a module +/// using a `CompilerInstance` constructed from the flags specified in the +/// interface file. +class ImplicitModuleInterfaceBuilder { SourceManager &sourceMgr; DiagnosticEngine *diags; InterfaceSubContextDelegate &subASTDelegate; @@ -50,14 +53,11 @@ class ModuleInterfaceBuilder { public: /// Emit a diagnostic tied to this declaration. - template - static InFlightDiagnostic diagnose( - DiagnosticEngine *Diags, - SourceManager &SM, - StringRef InterfacePath, - SourceLoc Loc, - Diag ID, - typename detail::PassArgument::type... Args) { + template + static InFlightDiagnostic + diagnose(DiagnosticEngine *Diags, SourceManager &SM, StringRef InterfacePath, + SourceLoc Loc, Diag ID, + typename detail::PassArgument::type... Args) { if (Loc.isInvalid()) { // Diagnose this inside the interface file, if possible. Loc = SM.getLocFromExternalSource(InterfacePath, 1, 1); @@ -67,14 +67,76 @@ class ModuleInterfaceBuilder { private: /// Emit a diagnostic tied to this declaration. - template - InFlightDiagnostic diagnose( - Diag ID, - typename detail::PassArgument::type... Args) const { - return diagnose(diags, sourceMgr, interfacePath, diagnosticLoc, - ID, std::move(Args)...); + template + InFlightDiagnostic + diagnose(Diag ID, + typename detail::PassArgument::type... Args) const { + return diagnose(diags, sourceMgr, interfacePath, diagnosticLoc, ID, + std::move(Args)...); } + bool + buildSwiftModuleInternal(StringRef OutPath, bool ShouldSerializeDeps, + std::unique_ptr *ModuleBuffer, + ArrayRef CandidateModules); + +public: + ImplicitModuleInterfaceBuilder( + SourceManager &sourceMgr, DiagnosticEngine *diags, + InterfaceSubContextDelegate &subASTDelegate, StringRef interfacePath, + StringRef moduleName, StringRef moduleCachePath, + StringRef backupInterfaceDir, StringRef prebuiltCachePath, + StringRef ABIDescriptorPath, bool disableInterfaceFileLock = false, + SourceLoc diagnosticLoc = SourceLoc(), + DependencyTracker *tracker = nullptr) + : sourceMgr(sourceMgr), diags(diags), subASTDelegate(subASTDelegate), + interfacePath(interfacePath), moduleName(moduleName), + moduleCachePath(moduleCachePath), prebuiltCachePath(prebuiltCachePath), + backupInterfaceDir(backupInterfaceDir), + ABIDescriptorPath(ABIDescriptorPath), + disableInterfaceFileLock(disableInterfaceFileLock), + diagnosticLoc(diagnosticLoc), dependencyTracker(tracker) {} + + /// Ensures the requested file name is added as a dependency of the resulting + /// module. + void addExtraDependency(StringRef path) { extraDependencies.push_back(path); } + + bool buildSwiftModule(StringRef OutPath, bool ShouldSerializeDeps, + std::unique_ptr *ModuleBuffer, + llvm::function_ref RemarkRebuild = nullptr, + ArrayRef CandidateModules = {}); +}; + +/// Use the provided `CompilerInstance` to build a swift interface into a module +class ExplicitModuleInterfaceBuilder { +public: + ExplicitModuleInterfaceBuilder(CompilerInstance &Instance, + DiagnosticEngine *diags, + SourceManager &sourceMgr, + const StringRef moduleCachePath, + const StringRef backupInterfaceDir, + const StringRef prebuiltCachePath, + const StringRef ABIDescriptorPath, + const SmallVector &extraDependencies, + SourceLoc diagnosticLoc = SourceLoc(), + DependencyTracker *tracker = nullptr) + : Instance(Instance), + diags(diags), + sourceMgr(sourceMgr), + moduleCachePath(moduleCachePath), + prebuiltCachePath(prebuiltCachePath), + backupInterfaceDir(backupInterfaceDir), + ABIDescriptorPath(ABIDescriptorPath), + extraDependencies(extraDependencies), + diagnosticLoc(diagnosticLoc), + dependencyTracker(tracker) {} + + std::error_code buildSwiftModuleFromInterface( + StringRef interfacePath, StringRef outputPath, bool ShouldSerializeDeps, + std::unique_ptr *ModuleBuffer, + ArrayRef CompiledCandidates, + StringRef CompilerVersion); + /// Populate the provided \p Deps with \c FileDependency entries for all /// dependencies \p SubInstance's DependencyTracker recorded while compiling /// the module, excepting .swiftmodules in \p moduleCachePath or @@ -82,48 +144,44 @@ class ModuleInterfaceBuilder { /// to avoid having to do recursive scanning when rechecking this dependency /// in future and to make the module caches relocatable. bool collectDepsForSerialization( - CompilerInstance &SubInstance, SmallVectorImpl &Deps, - bool IsHashBased); + StringRef interfacePath, bool IsHashBased); - bool buildSwiftModuleInternal(StringRef OutPath, - bool ShouldSerializeDeps, - bool IgnoreInterfaceProvidedOptions, - std::unique_ptr *ModuleBuffer, - ArrayRef CandidateModules); -public: - ModuleInterfaceBuilder(SourceManager &sourceMgr, DiagnosticEngine *diags, - InterfaceSubContextDelegate &subASTDelegate, - StringRef interfacePath, - StringRef moduleName, - StringRef moduleCachePath, - StringRef backupInterfaceDir, - StringRef prebuiltCachePath, - StringRef ABIDescriptorPath, - bool disableInterfaceFileLock = false, - SourceLoc diagnosticLoc = SourceLoc(), - DependencyTracker *tracker = nullptr) - : sourceMgr(sourceMgr), diags(diags), - subASTDelegate(subASTDelegate), - interfacePath(interfacePath), moduleName(moduleName), - moduleCachePath(moduleCachePath), prebuiltCachePath(prebuiltCachePath), - backupInterfaceDir(backupInterfaceDir), - ABIDescriptorPath(ABIDescriptorPath), - disableInterfaceFileLock(disableInterfaceFileLock), - diagnosticLoc(diagnosticLoc), dependencyTracker(tracker) {} + /// Emit a diagnostic tied to this declaration. + template + static InFlightDiagnostic + diagnose(DiagnosticEngine *Diags, SourceManager &SM, StringRef InterfacePath, + SourceLoc Loc, Diag ID, + typename detail::PassArgument::type... Args) { + if (Loc.isInvalid()) { + // Diagnose this inside the interface file, if possible. + Loc = SM.getLocFromExternalSource(InterfacePath, 1, 1); + } + return Diags->diagnose(Loc, ID, std::move(Args)...); + } - /// Ensures the requested file name is added as a dependency of the resulting - /// module. - void addExtraDependency(StringRef path) { - extraDependencies.push_back(path); +private: + /// Emit a diagnostic tied to this declaration. + template + InFlightDiagnostic diagnose( + Diag ID, + StringRef InterfacePath, + typename detail::PassArgument::type... Args) const { + return diagnose(diags, sourceMgr, InterfacePath, diagnosticLoc, + ID, std::move(Args)...); } - bool buildSwiftModule(StringRef OutPath, - bool ShouldSerializeDeps, - bool ignoreInterfaceProvidedOptions, - std::unique_ptr *ModuleBuffer, - llvm::function_ref RemarkRebuild = nullptr, - ArrayRef CandidateModules = {}); +private: + CompilerInstance &Instance; + DiagnosticEngine *diags; + SourceManager &sourceMgr; + StringRef moduleCachePath; + StringRef prebuiltCachePath; + StringRef backupInterfaceDir; + StringRef ABIDescriptorPath; + const SmallVector extraDependencies; + const SourceLoc diagnosticLoc; + DependencyTracker *const dependencyTracker; }; } // end namespace swift diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 45a6c30883b39..f0d97e3962c58 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1003,7 +1003,7 @@ class ModuleInterfaceLoaderImpl { } // Set up a builder if we need to build the module. It'll also set up // the genericSubInvocation we'll need to use to compute the cache paths. - ModuleInterfaceBuilder builder( + ImplicitModuleInterfaceBuilder builder( ctx.SourceMgr, diagsToUse, astDelegate, interfacePath, moduleName, cacheDir, prebuiltCacheDir, backupInterfaceDir, StringRef(), @@ -1018,7 +1018,6 @@ class ModuleInterfaceLoaderImpl { builder.addExtraDependency(modulePath); failed = builder.buildSwiftModule(cachedOutputPath, /*shouldSerializeDeps*/true, - Opts.ignoreInterfaceProvidedOptions, &moduleBuffer, remarkRebuild); } if (!failed) { @@ -1037,7 +1036,7 @@ class ModuleInterfaceLoaderImpl { interfacePath, backupPath); // Set up a builder if we need to build the module. It'll also set up // the genericSubInvocation we'll need to use to compute the cache paths. - ModuleInterfaceBuilder fallbackBuilder( + ImplicitModuleInterfaceBuilder fallbackBuilder( ctx.SourceMgr, &ctx.Diags, astDelegate, backupPath, moduleName, cacheDir, prebuiltCacheDir, backupInterfaceDir, StringRef(), Opts.disableInterfaceLock, diagnosticLoc, @@ -1053,7 +1052,6 @@ class ModuleInterfaceLoaderImpl { // can find it from the canonical interface file. auto failedAgain = fallbackBuilder.buildSwiftModule(cachedOutputPath, /*shouldSerializeDeps*/true, - Opts.ignoreInterfaceProvidedOptions, &moduleBuffer, remarkRebuild); if (failedAgain) @@ -1230,14 +1228,13 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( /*CreateCacheDirIfAbsent*/ true, CacheDir, PrebuiltCacheDir, BackupInterfaceDir, SerializeDependencyHashes, TrackSystemDependencies, RequireOSSAModules); - ModuleInterfaceBuilder builder(SourceMgr, &Diags, astDelegate, InPath, - ModuleName, CacheDir, PrebuiltCacheDir, - BackupInterfaceDir, ABIOutputPath, - LoaderOpts.disableInterfaceLock); + ImplicitModuleInterfaceBuilder builder(SourceMgr, &Diags, astDelegate, InPath, + ModuleName, CacheDir, PrebuiltCacheDir, + BackupInterfaceDir, ABIOutputPath, + LoaderOpts.disableInterfaceLock); // FIXME: We really only want to serialize 'important' dependencies here, if // we want to ship the built swiftmodules to another machine. auto failed = builder.buildSwiftModule(OutPath, /*shouldSerializeDeps*/true, - LoaderOpts.ignoreInterfaceProvidedOptions, /*ModuleBuffer*/nullptr, nullptr, SearchPathOpts.CandidateCompiledModules); if (!failed) @@ -1249,20 +1246,39 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( return true; assert(failed); assert(!backInPath.empty()); - ModuleInterfaceBuilder backupBuilder(SourceMgr, &Diags, astDelegate, backInPath, - ModuleName, CacheDir, PrebuiltCacheDir, - BackupInterfaceDir, ABIOutputPath, - LoaderOpts.disableInterfaceLock); + ImplicitModuleInterfaceBuilder backupBuilder(SourceMgr, &Diags, astDelegate, backInPath, + ModuleName, CacheDir, PrebuiltCacheDir, + BackupInterfaceDir, ABIOutputPath, + LoaderOpts.disableInterfaceLock); // Ensure we can rebuild module after user changed the original interface file. backupBuilder.addExtraDependency(InPath); // FIXME: We really only want to serialize 'important' dependencies here, if // we want to ship the built swiftmodules to another machine. return backupBuilder.buildSwiftModule(OutPath, /*shouldSerializeDeps*/true, - LoaderOpts.ignoreInterfaceProvidedOptions, /*ModuleBuffer*/nullptr, nullptr, SearchPathOpts.CandidateCompiledModules); } +bool ModuleInterfaceLoader::buildExplicitSwiftModuleFromSwiftInterface( + CompilerInstance &Instance, const StringRef moduleCachePath, + const StringRef backupInterfaceDir, const StringRef prebuiltCachePath, + const StringRef ABIDescriptorPath, StringRef interfacePath, + StringRef outputPath, bool ShouldSerializeDeps, + ArrayRef CompiledCandidates, StringRef CompilerVersion, + DependencyTracker *tracker) { + auto Builder = ExplicitModuleInterfaceBuilder( + Instance, &Instance.getDiags(), Instance.getSourceMgr(), + moduleCachePath, backupInterfaceDir, prebuiltCachePath, + ABIDescriptorPath, {}); + auto error = Builder.buildSwiftModuleFromInterface( + interfacePath, outputPath, ShouldSerializeDeps, /*ModuleBuffer*/nullptr, + CompiledCandidates, CompilerVersion); + if (!error) + return false; + else + return true; +} + void ModuleInterfaceLoader::collectVisibleTopLevelModuleNames( SmallVectorImpl &names) const { collectVisibleTopLevelModuleNamesImpl( @@ -1365,8 +1381,7 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs( SmallVectorImpl &SubArgs, std::string &CompilerVersion, StringRef interfacePath, - SourceLoc diagnosticLoc, - bool ignoreInterfaceProvidedOptions) { + SourceLoc diagnosticLoc) { llvm::vfs::FileSystem &fs = *SM.getFileSystem(); auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath); if (!FileOrError) { @@ -1386,14 +1401,13 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs( diag::error_extracting_version_from_module_interface); return true; } - - if (!ignoreInterfaceProvidedOptions) { - if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver, SubArgs)) { - diagnose(interfacePath, diagnosticLoc, - diag::error_extracting_version_from_module_interface); - return true; - } + + if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver, SubArgs)) { + diagnose(interfacePath, diagnosticLoc, + diag::error_extracting_version_from_module_interface); + return true; } + assert(VersMatches.size() == 2); // FIXME We should diagnose this at a location that makes sense: auto Vers = swift::version::Version(VersMatches[1], SourceLoc(), Diags); @@ -1613,11 +1627,9 @@ InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName, StringRef interfacePath, StringRef outputPath, SourceLoc diagLoc, - bool ignoreInterfaceProvidedOptions, llvm::function_ref, ArrayRef, StringRef)> action) { return runInSubCompilerInstance(moduleName, interfacePath, outputPath, diagLoc, - ignoreInterfaceProvidedOptions, [&](SubCompilerInstanceInfo &info){ return action(info.Instance->getASTContext(), info.Instance->getMainModule(), @@ -1632,7 +1644,6 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName, StringRef interfacePath, StringRef outputPath, SourceLoc diagLoc, - bool ignoreInterfaceProvidedOptions, llvm::function_ref action) { // We are about to mess up the compiler invocation by using the compiler // arguments in the textual interface file. So copy to use a new compiler @@ -1690,8 +1701,7 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName, SubArgs, CompilerVersion, interfacePath, - diagLoc, - ignoreInterfaceProvidedOptions)) { + diagLoc)) { return std::make_error_code(std::errc::not_supported); } diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 616be1a952d5d..b476fa2c11192 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -423,6 +423,9 @@ static bool buildModuleFromInterface(CompilerInstance &Instance) { ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); StringRef ABIPath = Instance.getPrimarySpecificPathsForAtMostOnePrimary() .SupplementaryOutputs.ABIDescriptorOutputPath; + + + return ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( Instance.getSourceMgr(), Instance.getDiags(), Invocation.getSearchPathOptions(), Invocation.getLangOptions(), diff --git a/lib/Serialization/ModuleDependencyScanner.cpp b/lib/Serialization/ModuleDependencyScanner.cpp index bfc56ebe7ced2..7ef4260b306a4 100644 --- a/lib/Serialization/ModuleDependencyScanner.cpp +++ b/lib/Serialization/ModuleDependencyScanner.cpp @@ -111,7 +111,6 @@ ErrorOr ModuleDependencyScanner::scanInterfaceFile( moduleInterfacePath.str(), StringRef(), SourceLoc(), - false, [&](ASTContext &Ctx, ModuleDecl *mainMod, ArrayRef Args, ArrayRef PCMArgs, StringRef Hash) { From a90d3e2de17489fb909cc5b084d9df496add794c Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Thu, 4 Aug 2022 15:38:37 -0700 Subject: [PATCH 128/491] Factor out reading flags/version from an interface from setting up a Compiler sub-instance --- .../swift/Frontend/ModuleInterfaceLoader.h | 27 ++-- .../ArgsToFrontendOptionsConverter.cpp | 6 +- lib/Frontend/ModuleInterfaceBuilder.cpp | 19 ++- lib/Frontend/ModuleInterfaceLoader.cpp | 121 +++++++++++------- 4 files changed, 106 insertions(+), 67 deletions(-) diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index fc085b14bbb81..0a426bf15c374 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -453,7 +453,7 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { const StringRef backupInterfaceDir, const StringRef prebuiltCachePath, const StringRef ABIDescriptorPath, StringRef interfacePath, StringRef outputPath, bool ShouldSerializeDeps, - ArrayRef CompiledCandidates, StringRef CompilerVersion, + ArrayRef CompiledCandidates, DependencyTracker *tracker = nullptr); }; @@ -473,13 +473,8 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { InFlightDiagnostic diagnose(StringRef interfacePath, SourceLoc diagnosticLoc, Diag ID, - typename detail::PassArgument::type... Args) { - SourceLoc loc = diagnosticLoc; - if (diagnosticLoc.isInvalid()) { - // Diagnose this inside the interface file, if possible. - loc = SM.getLocFromExternalSource(interfacePath, 1, 1); - } - return Diags->diagnose(loc, ID, std::move(Args)...); + typename detail::PassArgument::type... Args) { + return InterfaceSubContextDelegateImpl::diagnose(interfacePath, diagnosticLoc, SM, Diags, ID, std::move(Args)...); } void inheritOptionsForBuildingInterface(const SearchPathOptions &SearchPathOpts, @@ -500,6 +495,22 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { StringRef backupModuleInterfaceDir, bool serializeDependencyHashes, bool trackSystemDependencies, RequireOSSAModules_t requireOSSAModules); + + template + static InFlightDiagnostic diagnose(StringRef interfacePath, + SourceLoc diagnosticLoc, + SourceManager &SM, + DiagnosticEngine *Diags, + Diag ID, + typename detail::PassArgument::type... Args) { + SourceLoc loc = diagnosticLoc; + if (diagnosticLoc.isInvalid()) { + // Diagnose this inside the interface file, if possible. + loc = SM.getLocFromExternalSource(interfacePath, 1, 1); + } + return Diags->diagnose(loc, ID, std::move(Args)...); + } + std::error_code runInSubContext(StringRef moduleName, StringRef interfacePath, StringRef outputPath, diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 0607b04395cdc..5f1fa24c1c693 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -93,6 +93,10 @@ bool ArgsToFrontendOptionsConverter::convert( if (Args.hasArg(OPT_track_system_dependencies)) { Opts.IntermoduleDependencyTracking = IntermoduleDepTrackingMode::IncludeSystem; + } else if (Args.hasArg(OPT_explicit_interface_module_build)) { + // Always track at least the non-system dependencies for interface building. + Opts.IntermoduleDependencyTracking = + IntermoduleDepTrackingMode::ExcludeSystem; } if (const Arg *A = Args.getLastArg(OPT_bad_file_descriptor_retry_count)) { @@ -624,7 +628,7 @@ bool ArgsToFrontendOptionsConverter::checkBuildFromInterfaceOnlyOptions() if (Opts.RequestedAction != FrontendOptions::ActionType::CompileModuleFromInterface && Opts.ExplicitInterfaceBuild) { Diags.diagnose(SourceLoc(), - diag::error_cannot_ignore_interface_options_in_mode); + diag::error_cannot_explicit_interface_build_in_mode); return true; } return false; diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index 62f4875b21857..75051c074921b 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -181,16 +181,16 @@ bool ExplicitModuleInterfaceBuilder::collectDepsForSerialization( } std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface( - StringRef interfacePath, StringRef outputPath, bool ShouldSerializeDeps, + StringRef InterfacePath, StringRef OutputPath, bool ShouldSerializeDeps, std::unique_ptr *ModuleBuffer, - ArrayRef compiledCandidates, + ArrayRef CompiledCandidates, StringRef CompilerVersion) { auto Invocation = Instance.getInvocation(); // Try building forwarding module first. If succeed, return. if (Instance.getASTContext() .getModuleInterfaceChecker() - ->tryEmitForwardingModule(Invocation.getModuleName(), interfacePath, - compiledCandidates, outputPath)) { + ->tryEmitForwardingModule(Invocation.getModuleName(), InterfacePath, + CompiledCandidates, OutputPath)) { return std::error_code(); } FrontendOptions &FEOpts = Invocation.getFrontendOptions(); @@ -198,15 +198,12 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface( (FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck); const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput(); StringRef InPath = InputInfo.getFileName(); - const auto &OutputInfo = - InputInfo.getPrimarySpecificPaths().SupplementaryOutputs; - StringRef OutPath = OutputInfo.ModuleOutputPath; // Build the .swiftmodule; this is a _very_ abridged version of the logic // in performCompile in libFrontendTool, specialized, to just the one // module-serialization task we're trying to do here. LLVM_DEBUG(llvm::dbgs() << "Setting up instance to compile " << InPath - << " to " << OutPath << "\n"); + << " to " << OutputPath << "\n"); LLVM_DEBUG(llvm::dbgs() << "Performing sema\n"); if (isTypeChecking && FEOpts.DowngradeInterfaceVerificationError) { @@ -262,7 +259,7 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface( // Setup the callbacks for serialization, which can occur during the // optimization pipeline. SerializationOptions SerializationOpts; - std::string OutPathStr = OutPath.str(); + std::string OutPathStr = OutputPath.str(); SerializationOpts.OutputPath = OutPathStr.c_str(); SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName; SerializationOpts.AutolinkForceLoad = @@ -277,8 +274,8 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface( SerializationOpts.SDKName = Instance.getASTContext().LangOpts.SDKName; SerializationOpts.ABIDescriptorPath = ABIDescriptorPath.str(); SmallVector Deps; - bool serializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes; - if (collectDepsForSerialization(Deps, interfacePath, serializeHashes)) { + bool SerializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes; + if (collectDepsForSerialization(Deps, InterfacePath, SerializeHashes)) { return std::make_error_code(std::errc::not_supported); } if (ShouldSerializeDeps) diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index f0d97e3962c58..9af79012ede69 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1259,13 +1259,83 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( SearchPathOpts.CandidateCompiledModules); } +static bool readSwiftInterfaceVersionAndArgs( + SourceManager &SM, DiagnosticEngine &Diags, llvm::StringSaver &ArgSaver, + SmallVectorImpl &SubArgs, std::string &CompilerVersion, + StringRef interfacePath, SourceLoc diagnosticLoc) { + llvm::vfs::FileSystem &fs = *SM.getFileSystem(); + auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath); + if (!FileOrError) { + // Don't use this->diagnose() because it'll just try to re-open + // interfacePath. + Diags.diagnose(diagnosticLoc, diag::error_open_input_file, interfacePath, + FileOrError.getError().message()); + return true; + } + auto SB = FileOrError.get()->getBuffer(); + auto VersRe = getSwiftInterfaceFormatVersionRegex(); + auto CompRe = getSwiftInterfaceCompilerVersionRegex(); + SmallVector VersMatches, CompMatches; + + if (!VersRe.match(SB, &VersMatches)) { + InterfaceSubContextDelegateImpl::diagnose( + interfacePath, diagnosticLoc, SM, &Diags, + diag::error_extracting_version_from_module_interface); + return true; + } + + if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver, SubArgs)) { + InterfaceSubContextDelegateImpl::diagnose( + interfacePath, diagnosticLoc, SM, &Diags, + diag::error_extracting_version_from_module_interface); + return true; + } + + assert(VersMatches.size() == 2); + // FIXME We should diagnose this at a location that makes sense: + auto Vers = swift::version::Version(VersMatches[1], SourceLoc(), &Diags); + + if (CompRe.match(SB, &CompMatches)) { + assert(CompMatches.size() == 2); + CompilerVersion = ArgSaver.save(CompMatches[1]).str(); + } else { + // Don't diagnose; handwritten module interfaces don't include this field. + CompilerVersion = "(unspecified, file possibly handwritten)"; + } + + // For now: we support anything with the same "major version" and assume + // minor versions might be interesting for debugging, or special-casing a + // compatible field variant. + if (Vers.asMajorVersion() != InterfaceFormatVersion.asMajorVersion()) { + InterfaceSubContextDelegateImpl::diagnose( + interfacePath, diagnosticLoc, SM, &Diags, + diag::unsupported_version_of_module_interface, interfacePath, Vers); + return true; + } + return false; +} + bool ModuleInterfaceLoader::buildExplicitSwiftModuleFromSwiftInterface( CompilerInstance &Instance, const StringRef moduleCachePath, const StringRef backupInterfaceDir, const StringRef prebuiltCachePath, const StringRef ABIDescriptorPath, StringRef interfacePath, StringRef outputPath, bool ShouldSerializeDeps, - ArrayRef CompiledCandidates, StringRef CompilerVersion, + ArrayRef CompiledCandidates, DependencyTracker *tracker) { + + // Read out the compiler version. + llvm::BumpPtrAllocator alloc; + llvm::StringSaver ArgSaver(alloc); + std::string CompilerVersion; + SmallVector InterfaceArgs; + readSwiftInterfaceVersionAndArgs(Instance.getSourceMgr(), + Instance.getDiags(), + ArgSaver, + InterfaceArgs, + CompilerVersion, + interfacePath, + SourceLoc()); + auto Builder = ExplicitModuleInterfaceBuilder( Instance, &Instance.getDiags(), Instance.getSourceMgr(), moduleCachePath, backupInterfaceDir, prebuiltCachePath, @@ -1382,53 +1452,10 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs( std::string &CompilerVersion, StringRef interfacePath, SourceLoc diagnosticLoc) { - llvm::vfs::FileSystem &fs = *SM.getFileSystem(); - auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath); - if (!FileOrError) { - // Don't use this->diagnose() because it'll just try to re-open - // interfacePath. - Diags->diagnose(diagnosticLoc, diag::error_open_input_file, - interfacePath, FileOrError.getError().message()); - return true; - } - auto SB = FileOrError.get()->getBuffer(); - auto VersRe = getSwiftInterfaceFormatVersionRegex(); - auto CompRe = getSwiftInterfaceCompilerVersionRegex(); - SmallVector VersMatches, CompMatches; - - if (!VersRe.match(SB, &VersMatches)) { - diagnose(interfacePath, diagnosticLoc, - diag::error_extracting_version_from_module_interface); - return true; - } - - if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver, SubArgs)) { - diagnose(interfacePath, diagnosticLoc, - diag::error_extracting_version_from_module_interface); + if (readSwiftInterfaceVersionAndArgs(SM, *Diags, ArgSaver, SubArgs, + CompilerVersion, interfacePath, + diagnosticLoc)) return true; - } - - assert(VersMatches.size() == 2); - // FIXME We should diagnose this at a location that makes sense: - auto Vers = swift::version::Version(VersMatches[1], SourceLoc(), Diags); - - if (CompRe.match(SB, &CompMatches)) { - assert(CompMatches.size() == 2); - CompilerVersion = ArgSaver.save(CompMatches[1]).str(); - } - else { - // Don't diagnose; handwritten module interfaces don't include this field. - CompilerVersion = "(unspecified, file possibly handwritten)"; - } - - // For now: we support anything with the same "major version" and assume - // minor versions might be interesting for debugging, or special-casing a - // compatible field variant. - if (Vers.asMajorVersion() != InterfaceFormatVersion.asMajorVersion()) { - diagnose(interfacePath, diagnosticLoc, - diag::unsupported_version_of_module_interface, interfacePath, Vers); - return true; - } SmallString<32> ExpectedModuleName = subInvocation.getModuleName(); if (subInvocation.parseArgs(SubArgs, *Diags)) { From aee45799b8261ae8780866e940cec354a50bd49d Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Fri, 5 Aug 2022 07:41:34 -0700 Subject: [PATCH 129/491] Invoke Explicit Interface Build when '-explicit-interface-module-build' is specified on a '-compile-module-from-interface' frontend action, using the CompilerInstance instantiated directly from the command-line in order to build the module. --- include/swift/AST/DiagnosticsFrontend.def | 4 ++-- lib/FrontendTool/FrontendTool.cpp | 23 +++++++++++++------ ... => ExplicitInterfaceBuild.swiftinterface} | 6 ++--- 3 files changed, 21 insertions(+), 12 deletions(-) rename test/ModuleInterface/{IgnoreInterfaceFlags.swiftinterface => ExplicitInterfaceBuild.swiftinterface} (61%) diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 76fe1c522faec..753fb792d2623 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -99,8 +99,8 @@ WARNING(warning_cannot_find_locale_file,none, "cannot find translations for '%0' at '%1': no such file", (StringRef, StringRef)) WARNING(warning_cannot_multithread_batch_mode,none, "ignoring -num-threads argument; cannot multithread batch mode", ()) -ERROR(error_cannot_ignore_interface_options_in_mode,none, - "'-ignore-interface-provided-options' only supported when building a module from interface ('-compile-module-from-interface')'", ()) +ERROR(error_cannot_explicit_interface_build_in_mode,none, + "'-explicit-interface-module-build' only supported when building a module from interface ('-compile-module-from-interface')'", ()) ERROR(error_unsupported_option_argument,none, "unsupported argument '%1' to option '%0'", (StringRef, StringRef)) ERROR(error_immediate_mode_missing_stdlib,none, diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index b476fa2c11192..d523501064dd5 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -422,17 +422,26 @@ static bool buildModuleFromInterface(CompilerInstance &Instance) { StringRef PrebuiltCachePath = FEOpts.PrebuiltModuleCachePath; ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); StringRef ABIPath = Instance.getPrimarySpecificPathsForAtMostOnePrimary() - .SupplementaryOutputs.ABIDescriptorOutputPath; - - - - return ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( + .SupplementaryOutputs.ABIDescriptorOutputPath; + + // If an explicit interface build was requested, bypass the creation of a new + // sub-instance from the interface which will build it in a separate thread, + // and isntead directly use the current \c Instance for compilation. + if (FEOpts.ExplicitInterfaceBuild) + return ModuleInterfaceLoader::buildExplicitSwiftModuleFromSwiftInterface( + Instance, Invocation.getClangModuleCachePath(), + FEOpts.BackupModuleInterfaceDir, PrebuiltCachePath, ABIPath, InputPath, + Invocation.getOutputFilename(), + FEOpts.SerializeModuleInterfaceDependencyHashes, + Invocation.getSearchPathOptions().CandidateCompiledModules); + else + return ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( Instance.getSourceMgr(), Instance.getDiags(), Invocation.getSearchPathOptions(), Invocation.getLangOptions(), Invocation.getClangImporterOptions(), Invocation.getClangModuleCachePath(), PrebuiltCachePath, - FEOpts.BackupModuleInterfaceDir, - Invocation.getModuleName(), InputPath, Invocation.getOutputFilename(), ABIPath, + FEOpts.BackupModuleInterfaceDir, Invocation.getModuleName(), InputPath, + Invocation.getOutputFilename(), ABIPath, FEOpts.SerializeModuleInterfaceDependencyHashes, FEOpts.shouldTrackSystemDependencies(), LoaderOpts, RequireOSSAModules_t(Invocation.getSILOptions())); diff --git a/test/ModuleInterface/IgnoreInterfaceFlags.swiftinterface b/test/ModuleInterface/ExplicitInterfaceBuild.swiftinterface similarity index 61% rename from test/ModuleInterface/IgnoreInterfaceFlags.swiftinterface rename to test/ModuleInterface/ExplicitInterfaceBuild.swiftinterface index 8d220742cc1f1..c2da98ec78641 100644 --- a/test/ModuleInterface/IgnoreInterfaceFlags.swiftinterface +++ b/test/ModuleInterface/ExplicitInterfaceBuild.swiftinterface @@ -3,10 +3,10 @@ // REQUIRES: OS=macosx // RUN: %empty-directory(%t) -// Without '-ignore-interface-provided-options' this job fails because of the mismatch in 'module-name' -// RUN: %target-swift-frontend -compile-module-from-interface -module-name IgnoresFlags -ignore-interface-provided-options -o %/t/IgnoresFlags.swiftmodule %s -verify +// Without '-explicit-interface-module-build' this job fails because of the mismatch in 'module-name' +// RUN: %target-swift-frontend -compile-module-from-interface -module-name IgnoresFlags -explicit-interface-module-build -o %/t/IgnoresFlags.swiftmodule %s -verify import Swift extension Int { public static var fortytwo: Int = 42 -} \ No newline at end of file +} From 9c094c59a26913b7efd427f5547c8a24e253fc82 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 12 Aug 2022 00:11:21 -0400 Subject: [PATCH 130/491] SIL: Simplify SILCloner::remapRootOpenedType() --- include/swift/SIL/SILCloner.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 355f76a4d5c6d..26844459fb52d 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -254,13 +254,10 @@ class SILCloner : protected SILInstructionVisitor { assert(archetypeTy->isRoot()); auto sig = Builder.getFunction().getGenericSignature(); - auto existentialTy = archetypeTy->getExistentialType()->getCanonicalType(); - auto env = GenericEnvironment::forOpenedExistential( - getOpASTType(existentialTy), sig, UUID::fromTime()); - auto interfaceTy = OpenedArchetypeType::getSelfInterfaceTypeFromContext(sig, existentialTy->getASTContext()); - auto replacementTy = - env->mapTypeIntoContext(interfaceTy) - ->template castTo(); + auto origExistentialTy = archetypeTy->getExistentialType() + ->getCanonicalType(); + auto substExistentialTy = getOpASTType(origExistentialTy); + auto replacementTy = OpenedArchetypeType::get(substExistentialTy, sig); registerOpenedExistentialRemapping(archetypeTy, replacementTy); } From 0b1dce79e848f1e7a012a60c56769847e3d8fb6a Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 16 Aug 2022 09:06:14 -0700 Subject: [PATCH 131/491] Make test IRGen/objc_object_getClass.swift resilient to order rdar://98722116 --- test/IRGen/objc_object_getClass.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/IRGen/objc_object_getClass.swift b/test/IRGen/objc_object_getClass.swift index 9d498cef84248..b7f7bd6a6498c 100644 --- a/test/IRGen/objc_object_getClass.swift +++ b/test/IRGen/objc_object_getClass.swift @@ -18,5 +18,5 @@ func test(_ o: ObjCSubclass) { o.field = 10 } -// CHECK: declare i8* @object_getClass(i8*) -// CHECK: call %objc_class* bitcast (i8* (i8*)* @object_getClass to %objc_class* (%objc_object*)*)(%objc_object* %{{.*}}) +// CHECK-DAG: declare i8* @object_getClass(i8*) +// CHECK-DAG: call %objc_class* bitcast (i8* (i8*)* @object_getClass to %objc_class* (%objc_object*)*)(%objc_object* %{{.*}}) From 2dc50a6d63629c80bcc223ff717fb171c7beda9e Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 16 Aug 2022 09:09:44 -0700 Subject: [PATCH 132/491] Fix test IRGen/abitypes.swift We now annotate the function arguments with `noundef`. rdar://98722116 --- test/IRGen/abitypes.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IRGen/abitypes.swift b/test/IRGen/abitypes.swift index 760c2e1d42a20..87c7796145724 100644 --- a/test/IRGen/abitypes.swift +++ b/test/IRGen/abitypes.swift @@ -569,7 +569,7 @@ class Foo { // armv7-ios: define internal void @makeOne(%struct.One* noalias sret({{.*}}) align 4 %agg.result, float %f, float %s) // armv7s-ios: define internal void @makeOne(%struct.One* noalias sret({{.*}}) align 4 %agg.result, float %f, float %s) -// armv7k-watchos: define internal %struct.One @makeOne(float %f, float %s) +// armv7k-watchos: define internal %struct.One @makeOne(float {{.*}}%f, float {{.*}}%s) // rdar://17631440 - Expand direct arguments that are coerced to aggregates. // x86_64-macosx: define{{( protected)?}} swiftcc float @"$s8abitypes13testInlineAggySfSo6MyRectVF"(float %0, float %1, float %2, float %3) {{.*}} { From 94f6496431d6aa8b78214e9081f0b18b4609f3af Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 16 Aug 2022 10:43:10 -0700 Subject: [PATCH 133/491] [interop][SwiftToCxx] NFC,do not require definition of protocols for classes in C++ generation mode --- lib/PrintAsClang/ModuleContentsWriter.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/PrintAsClang/ModuleContentsWriter.cpp b/lib/PrintAsClang/ModuleContentsWriter.cpp index cf5aebbd726f8..5be6c7470c02f 100644 --- a/lib/PrintAsClang/ModuleContentsWriter.cpp +++ b/lib/PrintAsClang/ModuleContentsWriter.cpp @@ -388,11 +388,12 @@ class ModuleWriter { if ((superclass = CD->getSuperclassDecl())) { allRequirementsSatisfied &= require(superclass); } - for (auto proto : CD->getLocalProtocols( - ConformanceLookupKind::OnlyExplicit)) - if (printer.shouldInclude(proto)) - allRequirementsSatisfied &= require(proto); - + if (outputLangMode != OutputLanguageMode::Cxx) { + for (auto proto : + CD->getLocalProtocols(ConformanceLookupKind::OnlyExplicit)) + if (printer.shouldInclude(proto)) + allRequirementsSatisfied &= require(proto); + } if (!allRequirementsSatisfied) return false; From dcf87a2f6d71de80d3215c0d5a04612d2473f35b Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 16 Aug 2022 10:58:13 -0700 Subject: [PATCH 134/491] [interop][SwiftToCxx] prohibit printing of generic structs for now --- lib/PrintAsClang/PrintClangValueType.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index 8d3773d823b10..50b1ea3c150b2 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -83,6 +83,9 @@ printCValueTypeStorageStruct(raw_ostream &os, const NominalTypeDecl *typeDecl, void ClangValueTypePrinter::printValueTypeDecl( const NominalTypeDecl *typeDecl, llvm::function_ref bodyPrinter) { + // FIXME: Add support for generic structs. + if (typeDecl->isGeneric()) + return; llvm::Optional typeSizeAlign; if (!typeDecl->isResilient()) { From 8bf745bdf09855d02f9e03709fdb8c73200d6e0f Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 17 Aug 2022 03:25:50 +0900 Subject: [PATCH 135/491] [static-stdlib] Explicit autolink for RegexParser in StringProcessing (#60319) _RegexParser is used only in StringProcessing and it's imported with @_implementationOnly. Modules imported with @_implementationOnly are not autolinked, so build system let the importer module how to link it. When building a shared library, _RegexParser is already linked into StringProcessing. But when building a static library, it's not. So we need to add autolink entry explicitly. --- stdlib/public/StringProcessing/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stdlib/public/StringProcessing/CMakeLists.txt b/stdlib/public/StringProcessing/CMakeLists.txt index 6ac07067d6b7e..42ac94da95dc8 100644 --- a/stdlib/public/StringProcessing/CMakeLists.txt +++ b/stdlib/public/StringProcessing/CMakeLists.txt @@ -14,6 +14,13 @@ set(swift_string_processing_link_libraries swiftCore swift_RegexParser) +set(swift_string_processing_compile_flags) +if(SWIFT_BUILD_STATIC_STDLIB) + # Explicitly autolink swift_RegexParser because it's imported with @_implementationOnly + list(APPEND swift_string_processing_compile_flags + "-Xfrontend" "-public-autolink-library" "-Xfrontend" "swift_RegexParser") +endif() + file(GLOB_RECURSE _STRING_PROCESSING_SOURCES "${EXPERIMENTAL_STRING_PROCESSING_SOURCE_DIR}/Sources/_StringProcessing/*.swift" "${EXPERIMENTAL_STRING_PROCESSING_SOURCE_DIR}/Sources/_CUnicode/*.h" @@ -40,6 +47,7 @@ add_swift_target_library(swift_StringProcessing ${SWIFT_STDLIB_LIBRARY_BUILD_TYP C_COMPILE_FLAGS -Dswift_StringProcessing_EXPORTS SWIFT_COMPILE_FLAGS + ${swift_string_processing_compile_flags} ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}" From c1ae4ed6bf0d49dd11977b8c9d22cb53c04c7dda Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Tue, 16 Aug 2022 20:27:29 +0100 Subject: [PATCH 136/491] [Profiler] Introduce `CounterExpr::isSemanticallyZero` Refactor `CounterExpr::expand` to accept a function lookup for the counter indices, and add `isSemanticallyZero` to allow for checking whether a simplified counter is 0. --- lib/SIL/IR/SILProfiler.cpp | 48 ++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index a5026ffa37796..45a895441ae29 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -341,31 +341,65 @@ class CounterExpr { /// Returns true if this is a Zero node. bool isZero() const { return K == Kind::Zero; } + /// Returns true if the counter is semantically a Zero node. This considers + /// the simplified version of the counter that has eliminated redundant + /// operations. + bool isSemanticallyZero() const { + // Run the counter through the counter builder to simplify it, using a dummy + // mapping of unique counter indices for each node reference. The value of + // the indices doesn't matter, but we need to ensure that e.g subtraction + // of a node from itself cancels out. + llvm::coverage::CounterExpressionBuilder Builder; + llvm::DenseMap DummyIndices; + unsigned LastIdx = 0; + auto Counter = expand(Builder, [&](auto Node) { + if (!DummyIndices.count(Node)) { + DummyIndices[Node] = LastIdx; + LastIdx += 1; + } + return DummyIndices[Node]; + }); + return Counter.isZero(); + } + /// Expand this node into an llvm::coverage::Counter. /// /// Updates \c Builder with any expressions that are needed to represent this /// counter. llvm::coverage::Counter expand(llvm::coverage::CounterExpressionBuilder &Builder, - llvm::DenseMap &Counters) const { + llvm::function_ref GetCounterIdx) const { switch (K) { case Kind::Zero: return llvm::coverage::Counter::getZero(); case Kind::Node: - return llvm::coverage::Counter::getCounter(Counters[Node]); + return llvm::coverage::Counter::getCounter(GetCounterIdx(Node)); case Kind::Add: - return Builder.add(LHS->expand(Builder, Counters), - RHS->expand(Builder, Counters)); + return Builder.add(LHS->expand(Builder, GetCounterIdx), + RHS->expand(Builder, GetCounterIdx)); case Kind::Sub: - return Builder.subtract(LHS->expand(Builder, Counters), - RHS->expand(Builder, Counters)); + return Builder.subtract(LHS->expand(Builder, GetCounterIdx), + RHS->expand(Builder, GetCounterIdx)); case Kind::Ref: - return LHS->expand(Builder, Counters); + return LHS->expand(Builder, GetCounterIdx); } llvm_unreachable("Unhandled Kind in switch."); } + /// Expand this node into an llvm::coverage::Counter. + /// + /// Updates \c Builder with any expressions that are needed to represent this + /// counter. + llvm::coverage::Counter + expand(llvm::coverage::CounterExpressionBuilder &Builder, + const llvm::DenseMap &Counters) const { + return expand(Builder, [&](auto Node) { + // FIXME: We ought to assert that the node is present. + return Counters.lookup(Node); + }); + } + void print(raw_ostream &OS) const { switch (K) { case Kind::Zero: From d1eb6f9465b18155fb17d14f9da78f345f73cbc5 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Tue, 16 Aug 2022 20:27:30 +0100 Subject: [PATCH 137/491] [Profiler] Avoid introducing empty unreachable regions When computing the counter for the region following a labeled statement such as `if`, avoid adding a new empty region if the counter for such a region is known to be zero, i.e unreachable. This avoids adding spurious unreachable regions after an if statements where each branch returns, throws, or otherwise jumps to a parent statement. We will however still add the region if any code follows such a statement, making it non-empty. rdar://29390569 --- lib/SIL/IR/SILProfiler.cpp | 12 +++++- test/Profiler/coverage_if.swift | 71 +++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index 45a895441ae29..b33b8b48be044 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -814,7 +814,17 @@ struct CoverageMapping : public ASTWalker { if (ControlFlowAdjust) Count = &createCounter(CounterExpr::Sub(*Count, *ControlFlowAdjust)); - RegionStack.emplace_back(ASTNode(), *Count, getEndLoc(Scope), None); + if (Count->isSemanticallyZero()) { + // If the counter is semantically zero, form an 'incomplete' region with + // no starting location. This prevents forming unreachable regions unless + // there is a following statement or expression to extend the region. + RegionStack.emplace_back(ASTNode(), *Count, None, None); + } else { + // Otherwise, we have a non-zero counter, so form a new region starting + // at the end of the previous scope. This ensures the user covers both + // branches of a condition. + RegionStack.emplace_back(ASTNode(), *Count, getEndLoc(Scope), None); + } } /// Push a region covering \c Node onto the stack. diff --git a/test/Profiler/coverage_if.swift b/test/Profiler/coverage_if.swift index a19813f431218..9b3a3b0361d4f 100644 --- a/test/Profiler/coverage_if.swift +++ b/test/Profiler/coverage_if.swift @@ -17,3 +17,74 @@ func foo(x : Bool) { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0 foo(x: true); foo(x: false); + +// rdar://29390569 – Make sure we don't add a spurious unreachable empty region. + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo1 +func foo1() -> Int { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0 + if .random() { // CHECK: [[@LINE]]:6 -> [[@LINE]]:15 : 0 + return 0 // CHECK: [[@LINE-1]]:16 -> [[@LINE+2]]:4 : 1 + // CHECK: [[@LINE+1]]:4 -> {{[0-9]+}}:2 : (0 - 1) + } else if .random() { // CHECK: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + return 1 // CHECK: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 + } else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : ((0 - 1) - 2) + return 2 // CHECK: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : ((0 - 1) - 2) + } // CHECK-NOT: zero +} + +// ...but we will add an unreachable region if you write code there. +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo2 +func foo2() -> Int { + if .random() { + return 0 + } else if .random() { + return 1 + } else { + return 2 + } + _ = foo1() // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:2 : zero +} + +// Make sure we don't add unreachable regions for a labeled jump either. +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo3 +func foo3() -> Int { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0 + x: do { // CHECK: [[@LINE]]:9 -> [[@LINE+6]]:4 : 0 + if .random() { // CHECK: [[@LINE]]:8 -> [[@LINE]]:17 : 0 + return 0 // CHECK: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 1 + } else { // CHECK: [[@LINE]]:6 -> [[@LINE+3]]:4 : (0 - 1) + break x // CHECK: [[@LINE-1]]:12 -> [[@LINE+1]]:6 : (0 - 1) + } // CHECK-NOT: zero + } + return 2 +} +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo4 +func foo4() -> Int { + x: do { + if .random() { + return 0 + } else { + break x + } + let y = 0 // CHECK: [[@LINE]]:13 -> [[@LINE+1]]:4 : zero + } + return 2 +} + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo5 +func foo5() throws -> Int { // CHECK: [[@LINE]]:27 -> {{[0-9]+}}:2 : 0 + if .random() { // CHECK: [[@LINE]]:6 -> [[@LINE]]:15 : 0 + return 0 // CHECK: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1 + } else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : (0 - 1) + struct S: Error {} // CHECK: [[@LINE-1]]:10 -> [[@LINE+2]]:4 : (0 - 1) + throw S() + } // CHECK-NOT: zero +} + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo6 +func foo6(_ x: Int?) -> Int? { // CHECK: [[@LINE]]:30 -> {{[0-9]+}}:2 : 0 + if let x = x { + return x // CHECK: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1 + } else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : (0 - 1) + return nil // CHECK: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : (0 - 1) + } // CHECK-NOT: zero +} From 10bd9433ef8e7f11216d216c287d04a56927ca2f Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 16 Aug 2022 13:18:27 -0700 Subject: [PATCH 138/491] [TypeChecker] NFC: Adjust test-case for rdar://98577451 Replace `-target` with `-disable-availability-checking` and drop `REQUIRES:` lines that limit test to macOS. --- .../Sema/type_checker_crashers_fixed/rdar98577451.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar98577451.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar98577451.swift index 49a869814891b..7d1ec3be7c349 100644 --- a/validation-test/Sema/type_checker_crashers_fixed/rdar98577451.swift +++ b/validation-test/Sema/type_checker_crashers_fixed/rdar98577451.swift @@ -1,7 +1,4 @@ -// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 - -// REQUIRES: objc_interop -// REQUIRES: OS=macosx +// RUN: %target-typecheck-verify-swift -disable-availability-checking protocol P { associatedtype T From d4a7f86e3dcf37f8f3556d720b2a0edb93e5850f Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 16 Aug 2022 14:39:22 -0700 Subject: [PATCH 139/491] [interop][SwiftToCxx] do not emit unsupported function signatures yet --- lib/PrintAsClang/DeclAndTypePrinter.cpp | 39 +++-- lib/PrintAsClang/PrintClangFunction.cpp | 140 +++++++++++------- lib/PrintAsClang/PrintClangFunction.h | 38 ++++- .../swift-function-unsupported-cxx-type.swift | 16 ++ 4 files changed, 160 insertions(+), 73 deletions(-) create mode 100644 test/Interop/SwiftToCxx/functions/swift-function-unsupported-cxx-type.swift diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 72a665bd04470..67fb031b15c57 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -685,6 +685,8 @@ class DeclAndTypePrinter::Implementation .printSwiftABIFunctionSignatureAsCxxFunction( AFD, methodTy, /*selfTypeDeclContext=*/typeDeclContext); + if (!funcABI) + return; owningPrinter.prologueOS << cFuncPrologueOS.str(); DeclAndTypeClangFunctionPrinter declPrinter(os, owningPrinter.prologueOS, @@ -692,11 +694,11 @@ class DeclAndTypePrinter::Implementation owningPrinter.interopContext); if (auto *accessor = dyn_cast(AFD)) { declPrinter.printCxxPropertyAccessorMethod( - typeDeclContext, accessor, funcABI.getSymbolName(), resultTy, + typeDeclContext, accessor, funcABI->getSymbolName(), resultTy, /*isDefinition=*/false); } else { declPrinter.printCxxMethod(typeDeclContext, AFD, - funcABI.getSymbolName(), resultTy, + funcABI->getSymbolName(), resultTy, /*isDefinition=*/false); } @@ -708,11 +710,12 @@ class DeclAndTypePrinter::Implementation if (auto *accessor = dyn_cast(AFD)) { defPrinter.printCxxPropertyAccessorMethod( - typeDeclContext, accessor, funcABI.getSymbolName(), resultTy, + typeDeclContext, accessor, funcABI->getSymbolName(), resultTy, /*isDefinition=*/true); } else { - defPrinter.printCxxMethod(typeDeclContext, AFD, funcABI.getSymbolName(), - resultTy, /*isDefinition=*/true); + defPrinter.printCxxMethod(typeDeclContext, AFD, + funcABI->getSymbolName(), resultTy, + /*isDefinition=*/true); } // FIXME: SWIFT_WARN_UNUSED_RESULT @@ -1043,7 +1046,8 @@ class DeclAndTypePrinter::Implementation } // Print out the extern C Swift ABI function signature. - FuncionSwiftABIInformation printSwiftABIFunctionSignatureAsCxxFunction( + Optional + printSwiftABIFunctionSignatureAsCxxFunction( AbstractFunctionDecl *FD, Optional givenFuncType = None, Optional selfTypeDeclContext = None) { assert(outputLang == OutputLanguageMode::Cxx); @@ -1063,13 +1067,16 @@ class DeclAndTypePrinter::Implementation auto resultTy = getForeignResultType(FD, funcTy, asyncConvention, errorConvention); + std::string cRepresentationString; + llvm::raw_string_ostream cRepresentationOS(cRepresentationString); + FuncionSwiftABIInformation funcABI(FD); - os << "SWIFT_EXTERN "; + cRepresentationOS << "SWIFT_EXTERN "; - DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.prologueOS, - owningPrinter.typeMapping, - owningPrinter.interopContext); + DeclAndTypeClangFunctionPrinter funcPrinter( + cRepresentationOS, owningPrinter.prologueOS, owningPrinter.typeMapping, + owningPrinter.interopContext); auto ABIparams = owningPrinter.interopContext.getIrABIDetails() .getFunctionABIAdditionalParams(FD); llvm::SmallVector @@ -1085,10 +1092,16 @@ class DeclAndTypePrinter::Implementation if (!selfTypeDeclContext && !ABIparams.empty()) convertABIAdditionalParams(FD, resultTy, ABIparams, additionalParams); - funcPrinter.printFunctionSignature( + auto representation = funcPrinter.printFunctionSignature( FD, funcABI.getSymbolName(), resultTy, DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto, additionalParams); + if (representation.isUnsupported()) { + // FIXME: Emit remark about unemitted declaration. + return None; + } + + os << cRepresentationOS.str(); // Swift functions can't throw exceptions, we can only // throw them from C++ when emitting C++ inline thunks for the Swift // functions. @@ -1371,8 +1384,10 @@ class DeclAndTypePrinter::Implementation llvm::raw_string_ostream cFuncPrologueOS(cFuncDecl); auto funcABI = Implementation(cFuncPrologueOS, owningPrinter, outputLang) .printSwiftABIFunctionSignatureAsCxxFunction(FD); + if (!funcABI) + return; owningPrinter.prologueOS << cFuncPrologueOS.str(); - printAbstractFunctionAsCxxFunctionThunk(FD, funcABI); + printAbstractFunctionAsCxxFunctionThunk(FD, *funcABI); return; } if (FD->getDeclContext()->isTypeContext()) diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index fe586222e4116..e7e1a00d49597 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -86,7 +86,7 @@ struct CFunctionSignatureTypePrinterModifierDelegate { // Prints types in the C function signature that corresponds to the // native Swift function/method. class CFunctionSignatureTypePrinter - : public TypeVisitor, bool>, private ClangSyntaxPrinter { public: @@ -123,33 +123,40 @@ class CFunctionSignatureTypePrinter return true; } - void visitType(TypeBase *Ty, Optional optionalKind, - bool isInOutParam) { + ClangRepresentation visitType(TypeBase *Ty, + Optional optionalKind, + bool isInOutParam) { assert(Ty->getDesugaredType() == Ty && "unhandled sugared type"); os << "/* "; Ty->print(os); os << " */"; + return ClangRepresentation::unsupported; } - void visitTupleType(TupleType *TT, Optional optionalKind, - bool isInOutParam) { + ClangRepresentation visitTupleType(TupleType *TT, + Optional optionalKind, + bool isInOutParam) { assert(TT->getNumElements() == 0); // FIXME: Handle non-void type. os << "void"; + return ClangRepresentation::representable; } - void visitTypeAliasType(TypeAliasType *aliasTy, - Optional optionalKind, - bool isInOutParam) { + ClangRepresentation + visitTypeAliasType(TypeAliasType *aliasTy, + Optional optionalKind, + bool isInOutParam) { const TypeAliasDecl *alias = aliasTy->getDecl(); if (printIfKnownSimpleType(alias, optionalKind, isInOutParam)) - return; + return ClangRepresentation::representable; - visitPart(aliasTy->getSinglyDesugaredType(), optionalKind, isInOutParam); + return visitPart(aliasTy->getSinglyDesugaredType(), optionalKind, + isInOutParam); } - void visitClassType(ClassType *CT, Optional optionalKind, - bool isInOutParam) { + ClangRepresentation visitClassType(ClassType *CT, + Optional optionalKind, + bool isInOutParam) { // FIXME: handle optionalKind. if (languageMode != OutputLanguageMode::Cxx) { if (modifiersDelegate.prefixIndirectlyPassedParamTypeInC) @@ -157,34 +164,38 @@ class CFunctionSignatureTypePrinter os << "void * _Nonnull"; if (isInOutParam) os << " * _Nonnull"; - return; + return ClangRepresentation::representable; } if (typeUseKind == FunctionSignatureTypeUse::ParamType && !isInOutParam) os << "const "; ClangSyntaxPrinter(os).printBaseName(CT->getDecl()); if (typeUseKind == FunctionSignatureTypeUse::ParamType) os << "&"; + return ClangRepresentation::representable; } - void visitEnumType(EnumType *ET, Optional optionalKind, - bool isInOutParam) { - visitValueType(ET, optionalKind, isInOutParam); + ClangRepresentation visitEnumType(EnumType *ET, + Optional optionalKind, + bool isInOutParam) { + return visitValueType(ET, optionalKind, isInOutParam); } - void visitStructType(StructType *ST, Optional optionalKind, - bool isInOutParam) { - visitValueType(ST, optionalKind, isInOutParam); + ClangRepresentation visitStructType(StructType *ST, + Optional optionalKind, + bool isInOutParam) { + return visitValueType(ST, optionalKind, isInOutParam); } - void visitValueType(NominalType *NT, Optional optionalKind, - bool isInOutParam) { + ClangRepresentation visitValueType(NominalType *NT, + Optional optionalKind, + bool isInOutParam) { assert(isa(NT) || isa(NT)); const auto *decl = NT->getNominalOrBoundGenericNominal(); assert(isa(decl) || isa(decl)); // Handle known type names. if (printIfKnownSimpleType(decl, optionalKind, isInOutParam)) - return; + return ClangRepresentation::representable; // FIXME: Handle optional structures. if (typeUseKind == FunctionSignatureTypeUse::ParamType) { if (languageMode != OutputLanguageMode::Cxx && @@ -207,6 +218,7 @@ class CFunctionSignatureTypePrinter } else ClangValueTypePrinter(os, cPrologueOS, typeMapping, interopContext) .printValueTypeReturnType(decl, languageMode, moduleContext); + return ClangRepresentation::representable; } bool printIfKnownGenericStruct(const BoundGenericStructType *BGT, @@ -233,22 +245,25 @@ class CFunctionSignatureTypePrinter return true; } - void visitBoundGenericStructType(BoundGenericStructType *BGT, - Optional optionalKind, - bool isInOutParam) { + ClangRepresentation + visitBoundGenericStructType(BoundGenericStructType *BGT, + Optional optionalKind, + bool isInOutParam) { if (printIfKnownGenericStruct(BGT, optionalKind, isInOutParam)) - return; + return ClangRepresentation::representable; + return ClangRepresentation::unsupported; } - void visitGenericTypeParamType(GenericTypeParamType *genericTpt, - Optional optionalKind, - bool isInOutParam) { + ClangRepresentation + visitGenericTypeParamType(GenericTypeParamType *genericTpt, + Optional optionalKind, + bool isInOutParam) { // FIXME: handle optionalKind. if (typeUseKind == FunctionSignatureTypeUse::ReturnType) { // generic is always returned indirectly in C signature. assert(languageMode == OutputLanguageMode::Cxx); os << genericTpt->getName(); - return; + return ClangRepresentation::representable; } if (!isInOutParam) os << "const "; @@ -256,15 +271,17 @@ class CFunctionSignatureTypePrinter // Pass a reference to a template type. os << genericTpt->getName(); os << " &"; - return; + return ClangRepresentation::representable; } // Pass an opaque param in C mode. os << "void * _Nonnull"; + return ClangRepresentation::representable; } - void visitPart(Type Ty, Optional optionalKind, - bool isInOutParam) { - TypeVisitor::visit(Ty, optionalKind, isInOutParam); + ClangRepresentation visitPart(Type Ty, + Optional optionalKind, + bool isInOutParam) { + return TypeVisitor::visit(Ty, optionalKind, isInOutParam); } private: @@ -279,7 +296,8 @@ class CFunctionSignatureTypePrinter } // end namespace -void DeclAndTypeClangFunctionPrinter::printClangFunctionReturnType( +ClangRepresentation +DeclAndTypeClangFunctionPrinter::printClangFunctionReturnType( Type ty, OptionalTypeKind optKind, ModuleDecl *moduleContext, OutputLanguageMode outputLang) { CFunctionSignatureTypePrinter typePrinter( @@ -287,10 +305,10 @@ void DeclAndTypeClangFunctionPrinter::printClangFunctionReturnType( CFunctionSignatureTypePrinterModifierDelegate(), moduleContext, FunctionSignatureTypeUse::ReturnType); // Param for indirect return cannot be marked as inout - typePrinter.visit(ty, optKind, /*isInOutParam=*/false); + return typePrinter.visit(ty, optKind, /*isInOutParam=*/false); } -void DeclAndTypeClangFunctionPrinter::printFunctionSignature( +ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature( const AbstractFunctionDecl *FD, StringRef name, Type resultTy, FunctionSignatureKind kind, ArrayRef additionalParams, FunctionSignatureModifiers modifiers) { @@ -321,19 +339,21 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature( auto print = [&, this](Type ty, Optional optionalKind, StringRef name, bool isInOutParam, - CFunctionSignatureTypePrinterModifierDelegate delegate = {}) { - // FIXME: add support for noescape and PrintMultiPartType, - // see DeclAndTypePrinter::print. - CFunctionSignatureTypePrinter typePrinter(os, cPrologueOS, typeMapping, - outputLang, interopContext, - delegate, emittedModule); - typePrinter.visit(ty, optionalKind, isInOutParam); - - if (!name.empty()) { - os << ' '; - ClangSyntaxPrinter(os).printIdentifier(name); - } - }; + CFunctionSignatureTypePrinterModifierDelegate delegate = {}) + -> ClangRepresentation { + // FIXME: add support for noescape and PrintMultiPartType, + // see DeclAndTypePrinter::print. + CFunctionSignatureTypePrinter typePrinter(os, cPrologueOS, typeMapping, + outputLang, interopContext, + delegate, emittedModule); + auto result = typePrinter.visit(ty, optionalKind, isInOutParam); + + if (!name.empty()) { + os << ' '; + ClangSyntaxPrinter(os).printIdentifier(name); + } + return result; + }; // Print any modifiers before the signature. if (modifiers.isStatic) { @@ -343,6 +363,9 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature( if (modifiers.isInline) os << "inline "; + ClangRepresentation resultingRepresentation = + ClangRepresentation::representable; + // Print out the return type. bool isIndirectReturnType = kind == FunctionSignatureKind::CFunctionProto && @@ -355,7 +378,11 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature( Type objTy; std::tie(objTy, retKind) = DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy); - printClangFunctionReturnType(objTy, retKind, emittedModule, outputLang); + if (resultingRepresentation + .merge(printClangFunctionReturnType(objTy, retKind, emittedModule, + outputLang)) + .isUnsupported()) + return resultingRepresentation; } else { os << "void"; } @@ -398,9 +425,12 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature( llvm::raw_string_ostream os(paramName); os << "_" << paramIndex; } - print(objTy, argKind, paramName, param->isInOut()); + resultingRepresentation.merge( + print(objTy, argKind, paramName, param->isInOut())); ++paramIndex; }); + if (resultingRepresentation.isUnsupported()) + return resultingRepresentation; } if (additionalParams.size()) { assert(kind == FunctionSignatureKind::CFunctionProto); @@ -419,8 +449,9 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature( (*delegate.prefixIndirectlyPassedParamTypeInC)(os); os << "void * _Nonnull _self"; } else { - print(param.type, OptionalTypeKind::OTK_None, "_self", - /*isInOut*/ false, delegate); + resultingRepresentation.merge( + print(param.type, OptionalTypeKind::OTK_None, "_self", + /*isInOut*/ false, delegate)); } } else if (param.role == AdditionalParam::Role::Error) { os << "SWIFT_ERROR_RESULT "; @@ -440,6 +471,7 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature( os << ')'; if (modifiers.isConst) os << " const"; + return resultingRepresentation; } void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse( diff --git a/lib/PrintAsClang/PrintClangFunction.h b/lib/PrintAsClang/PrintClangFunction.h index 87cdb449008ca..3ed58e3c854ee 100644 --- a/lib/PrintAsClang/PrintClangFunction.h +++ b/lib/PrintAsClang/PrintClangFunction.h @@ -36,6 +36,25 @@ class ParameterList; class PrimitiveTypeMapping; class SwiftToClangInteropContext; +struct ClangRepresentation { + enum Kind { representable, unsupported }; + + ClangRepresentation(Kind kind) : kind(kind) {} + + /// Returns true if the given Swift node is unsupported in Clang in any + /// language mode. + bool isUnsupported() const { return kind == unsupported; } + + const ClangRepresentation &merge(ClangRepresentation other) { + if (kind != unsupported) + kind = other.kind; + return *this; + } + +private: + Kind kind; +}; + /// Responsible for printing a Swift function decl or type in C or C++ mode, to /// be included in a Swift module's generated clang header. class DeclAndTypeClangFunctionPrinter { @@ -79,10 +98,14 @@ class DeclAndTypeClangFunctionPrinter { /// Print the C function declaration or the C++ function thunk that /// corresponds to the given function declaration. - void printFunctionSignature(const AbstractFunctionDecl *FD, StringRef name, - Type resultTy, FunctionSignatureKind kind, - ArrayRef additionalParams = {}, - FunctionSignatureModifiers modifiers = {}); + /// + /// \return value describing in which Clang language mode the function is + /// supported, if any. + ClangRepresentation + printFunctionSignature(const AbstractFunctionDecl *FD, StringRef name, + Type resultTy, FunctionSignatureKind kind, + ArrayRef additionalParams = {}, + FunctionSignatureModifiers modifiers = {}); /// Print the use of the C++ function thunk parameter as it's passed to the C /// function declaration. @@ -110,9 +133,10 @@ class DeclAndTypeClangFunctionPrinter { bool isDefinition); /// Print Swift type as C/C++ type, as the return type of a C/C++ function. - void printClangFunctionReturnType(Type ty, OptionalTypeKind optKind, - ModuleDecl *moduleContext, - OutputLanguageMode outputLang); + ClangRepresentation + printClangFunctionReturnType(Type ty, OptionalTypeKind optKind, + ModuleDecl *moduleContext, + OutputLanguageMode outputLang); private: void printCxxToCFunctionParameterUse( diff --git a/test/Interop/SwiftToCxx/functions/swift-function-unsupported-cxx-type.swift b/test/Interop/SwiftToCxx/functions/swift-function-unsupported-cxx-type.swift new file mode 100644 index 0000000000000..cfa795f10f073 --- /dev/null +++ b/test/Interop/SwiftToCxx/functions/swift-function-unsupported-cxx-type.swift @@ -0,0 +1,16 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -typecheck -module-name Functions -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h +// RUN: %FileCheck %s < %t/functions.h + +// RUN: %check-interop-cxx-header-in-clang(%t/functions.h) + +public func a() { } +public func b(_ x: @escaping (Int) -> ()) { } +public func c() {} + +// CHECK: SWIFT_EXTERN void $s9Functions1ayyF(void) SWIFT_NOEXCEPT SWIFT_CALL; // a() +// CHECK: SWIFT_EXTERN void $s9Functions1cyyF(void) SWIFT_NOEXCEPT SWIFT_CALL; // c() + +// CHECK: inline void a() noexcept { +// CHECK: inline void c() noexcept { +// CHECK-NOT: b( From 196994fc110a447281454d80da01393d7eaeee5c Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 29 Jun 2022 12:16:51 -0700 Subject: [PATCH 140/491] Fix store_borrow generation in SILGen This change ensures all store_borrows are ended with an end_borrow, and uses of the store_borrow destination are all in the enclosing store_borrow scope and via the store_borrow return address. Fix tests to reflect new store_borrow pattern --- lib/SILGen/ManagedValue.cpp | 33 +++- lib/SILGen/ManagedValue.h | 2 + lib/SILGen/SILGenApply.cpp | 6 +- lib/SILGen/SILGenBridging.cpp | 4 +- lib/SILGen/SILGenBuilder.cpp | 18 +- lib/SILGen/SILGenBuilder.h | 7 +- lib/SILGen/SILGenExpr.cpp | 26 ++- lib/SILGen/SILGenFunction.h | 4 + .../false_positive_leaks.sil | 5 +- .../OwnershipVerifier/interior_pointer.sil | 4 +- test/SIL/OwnershipVerifier/use_verifier.sil | 3 +- test/SIL/Parser/borrow.sil | 8 +- test/SIL/Serialization/borrow.sil | 4 +- test/SIL/memory_lifetime.sil | 3 +- test/SIL/memory_lifetime_failures.sil | 36 ++-- test/SILGen/class_bound_protocols.swift | 5 +- test/SILGen/copy_operator.swift | 10 +- test/SILGen/lexical_lifetime.swift | 4 +- test/SILGen/objc_bridging_any.swift | 11 +- test/SILGen/objc_bridging_peephole.swift | 8 +- ...ply_protocol_class_refinement_method.swift | 5 +- test/SILGen/protocol_extensions.swift | 5 +- test/SILGen/subclass_existentials.swift | 5 +- test/SILGen/switch_var.swift | 8 +- test/SILOptimizer/OSLogMandatoryOptTest.sil | 5 +- test/SILOptimizer/OSLogMandatoryOptTest.swift | 37 ++-- .../dead_code_elimination_ossa.sil | 3 +- .../existential_transform_extras_ossa.sil | 3 +- .../for_each_loop_unroll_test.sil | 15 +- .../mandatory_inlining_ossa_to_non_ossa.sil | 7 +- test/SILOptimizer/mem2reg_borrows.sil | 171 +++++------------- .../move_only_type_eliminator.sil | 14 +- .../ownership_model_eliminator.sil | 6 +- test/SILOptimizer/specialize_ossa.sil | 21 ++- 34 files changed, 256 insertions(+), 250 deletions(-) diff --git a/lib/SILGen/ManagedValue.cpp b/lib/SILGen/ManagedValue.cpp index 7c9ac26b386ca..f09d72ff736ef 100644 --- a/lib/SILGen/ManagedValue.cpp +++ b/lib/SILGen/ManagedValue.cpp @@ -200,7 +200,6 @@ ManagedValue ManagedValue::materialize(SILGenFunction &SGF, auto temporary = SGF.emitTemporaryAllocation(loc, getType()); bool hadCleanup = hasCleanup(); - // The temporary memory is +0 if the value was. if (hadCleanup) { SGF.B.emitStoreValueOperation(loc, forward(SGF), temporary, StoreOwnershipQualifier::Init); @@ -218,9 +217,37 @@ ManagedValue ManagedValue::materialize(SILGenFunction &SGF, return ManagedValue::forOwnedAddressRValue( temporary, SGF.enterDestroyCleanup(temporary)); } + // The temporary memory is +0 if the value was. auto object = SGF.emitManagedBeginBorrow(loc, getValue()); - SGF.emitManagedStoreBorrow(loc, object.getValue(), temporary); - return ManagedValue::forBorrowedAddressRValue(temporary); + auto borrowedAddr = + SGF.emitManagedStoreBorrow(loc, object.getValue(), temporary); + return ManagedValue::forBorrowedAddressRValue(borrowedAddr.getValue()); +} + +ManagedValue ManagedValue::formallyMaterialize(SILGenFunction &SGF, + SILLocation loc) const { + auto temporary = SGF.emitTemporaryAllocation(loc, getType()); + bool hadCleanup = hasCleanup(); + auto &lowering = SGF.getTypeLowering(getType()); + + if (hadCleanup) { + SGF.B.emitStoreValueOperation(loc, forward(SGF), temporary, + StoreOwnershipQualifier::Init); + + return ManagedValue::forOwnedAddressRValue( + temporary, SGF.enterDestroyCleanup(temporary)); + } + if (lowering.isAddressOnly()) { + assert(!SGF.silConv.useLoweredAddresses()); + auto copy = SGF.B.createCopyValue(loc, getValue()); + SGF.B.emitStoreValueOperation(loc, copy, temporary, + StoreOwnershipQualifier::Init); + return ManagedValue::forOwnedAddressRValue( + temporary, SGF.enterDestroyCleanup(temporary)); + } + auto object = SGF.emitFormalEvaluationManagedBeginBorrow(loc, getValue()); + return SGF.emitFormalEvaluationManagedStoreBorrow(loc, object.getValue(), + temporary); } void ManagedValue::print(raw_ostream &os) const { diff --git a/lib/SILGen/ManagedValue.h b/lib/SILGen/ManagedValue.h index 9be116087b1e7..0d124a942d827 100644 --- a/lib/SILGen/ManagedValue.h +++ b/lib/SILGen/ManagedValue.h @@ -320,6 +320,8 @@ class ManagedValue { /// exact same level of cleanup it had before. ManagedValue materialize(SILGenFunction &SGF, SILLocation loc) const; + ManagedValue formallyMaterialize(SILGenFunction &SGF, SILLocation loc) const; + /// Disable the cleanup for this value. void forwardCleanup(SILGenFunction &SGF) const; diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 2a786911c49a8..40a10304b9bbd 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -5722,7 +5722,11 @@ ArgumentSource AccessorBaseArgPreparer::prepareAccessorObjectBaseArg() { assert(!selfParam.isIndirectMutating() && "passing unmaterialized r-value as inout argument"); - base = base.materialize(SGF, loc); + base = base.formallyMaterialize(SGF, loc); + auto shouldTake = IsTake_t(base.hasCleanup()); + base = SGF.emitFormalAccessLoad(loc, base.forward(SGF), + SGF.getTypeLowering(baseLoweredType), + SGFContext(), shouldTake); } return ArgumentSource(loc, RValue(SGF, loc, baseFormalType, base)); diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index 7523df3ef808d..ba1ce02851491 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -154,8 +154,8 @@ emitBridgeNativeToObjectiveC(SILGenFunction &SGF, if (witnessConv.isSILIndirect(witnessConv.getParameters()[0]) && !swiftValue.getType().isAddress()) { auto tmp = SGF.emitTemporaryAllocation(loc, swiftValue.getType()); - SGF.B.createStoreBorrowOrTrivial(loc, swiftValue.borrow(SGF, loc), tmp); - swiftValue = ManagedValue::forUnmanaged(tmp); + swiftValue = SGF.emitManagedStoreBorrow( + loc, swiftValue.borrow(SGF, loc).getValue(), tmp); } // Call the witness. diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp index 4de678a0c3ee5..c7efd8cebe3d5 100644 --- a/lib/SILGen/SILGenBuilder.cpp +++ b/lib/SILGen/SILGenBuilder.cpp @@ -721,21 +721,23 @@ createValueMetatype(SILLocation loc, SILType metatype, return ManagedValue::forUnmanaged(v); } -void SILGenBuilder::createStoreBorrow(SILLocation loc, ManagedValue value, - SILValue address) { +ManagedValue SILGenBuilder::createStoreBorrow(SILLocation loc, + ManagedValue value, + SILValue address) { assert(value.getOwnershipKind() == OwnershipKind::Guaranteed); - createStoreBorrow(loc, value.getValue(), address); + auto *sbi = createStoreBorrow(loc, value.getValue(), address); + return ManagedValue(sbi, CleanupHandle::invalid()); } -void SILGenBuilder::createStoreBorrowOrTrivial(SILLocation loc, - ManagedValue value, - SILValue address) { +ManagedValue SILGenBuilder::createStoreBorrowOrTrivial(SILLocation loc, + ManagedValue value, + SILValue address) { if (value.getOwnershipKind() == OwnershipKind::None) { createStore(loc, value, address, StoreOwnershipQualifier::Trivial); - return; + return ManagedValue(address, CleanupHandle::invalid()); } - createStoreBorrow(loc, value, address); + return createStoreBorrow(loc, value, address); } ManagedValue SILGenBuilder::createBridgeObjectToRef(SILLocation loc, diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h index 5c18dc73b76db..bdde2ada064c0 100644 --- a/lib/SILGen/SILGenBuilder.h +++ b/lib/SILGen/SILGenBuilder.h @@ -190,12 +190,13 @@ class SILGenBuilder : public SILBuilder { ManagedValue createFormalAccessLoadBorrow(SILLocation loc, ManagedValue base); using SILBuilder::createStoreBorrow; - void createStoreBorrow(SILLocation loc, ManagedValue value, SILValue address); + ManagedValue createStoreBorrow(SILLocation loc, ManagedValue value, + SILValue address); /// Create a store_borrow if we have a non-trivial value and a store [trivial] /// otherwise. - void createStoreBorrowOrTrivial(SILLocation loc, ManagedValue value, - SILValue address); + ManagedValue createStoreBorrowOrTrivial(SILLocation loc, ManagedValue value, + SILValue address); /// Prepares a buffer to receive the result of an expression, either using the /// 'emit into' initialization buffer if available, or allocating a temporary diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 6584ff2ad93f1..f204f328a4554 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -129,12 +129,13 @@ ManagedValue SILGenFunction::emitManagedStoreBorrow( assert(lowering.getLoweredType().getObjectType() == v->getType()); if (lowering.isTrivial() || v->getOwnershipKind() == OwnershipKind::None) { lowering.emitStore(B, loc, v, addr, StoreOwnershipQualifier::Trivial); - return ManagedValue::forUnmanaged(v); + return ManagedValue::forTrivialAddressRValue(addr); } assert((!lowering.isAddressOnly() || !silConv.useLoweredAddresses()) && "cannot retain an unloadable type"); auto *sbi = B.createStoreBorrow(loc, v, addr); - return emitManagedBorrowedRValueWithCleanup(sbi->getSrc(), sbi, lowering); + Cleanups.pushCleanup(sbi); + return ManagedValue(sbi, CleanupHandle::invalid()); } ManagedValue SILGenFunction::emitManagedBeginBorrow(SILLocation loc, @@ -243,6 +244,18 @@ ManagedValue SILGenFunction::emitFormalEvaluationManagedBeginBorrow( lowering); } +ManagedValue SILGenFunction::emitFormalEvaluationManagedStoreBorrow( + SILLocation loc, SILValue v, SILValue addr) { + auto &lowering = getTypeLowering(v->getType()); + if (lowering.isTrivial() || v->getOwnershipKind() == OwnershipKind::None) { + lowering.emitStore(B, loc, v, addr, StoreOwnershipQualifier::Trivial); + return ManagedValue::forTrivialAddressRValue(addr); + } + auto *sbi = B.createStoreBorrow(loc, v, addr); + return emitFormalEvaluationManagedBorrowedRValueWithCleanup(loc, v, sbi, + lowering); +} + ManagedValue SILGenFunction::emitFormalEvaluationManagedBorrowedRValueWithCleanup( SILLocation loc, SILValue original, SILValue borrowed) { @@ -260,10 +273,6 @@ SILGenFunction::emitFormalEvaluationManagedBorrowedRValueWithCleanup( if (lowering.isTrivial()) return ManagedValue::forUnmanaged(borrowed); - if (!borrowed->getType().isObject()) { - return ManagedValue(borrowed, CleanupHandle::invalid()); - } - assert(isInFormalEvaluationScope() && "Must be in formal evaluation scope"); auto &cleanup = Cleanups.pushCleanup(); CleanupHandle handle = Cleanups.getTopCleanup(); @@ -329,10 +338,7 @@ ManagedValue SILGenFunction::emitManagedBorrowedRValueWithCleanup( original->getOwnershipKind() == OwnershipKind::None) return ManagedValue::forUnmanaged(borrowed); - if (borrowed->getType().isObject()) { - Cleanups.pushCleanup(borrowed); - } - + Cleanups.pushCleanup(borrowed); return ManagedValue(borrowed, CleanupHandle::invalid()); } diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index c2aff0f73e40d..f192cf553f6f1 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -1544,6 +1544,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction emitFormalEvaluationManagedBeginBorrow(SILLocation loc, SILValue v, const TypeLowering &lowering); + ManagedValue emitFormalEvaluationManagedStoreBorrow(SILLocation loc, + SILValue v, + SILValue addr); + ManagedValue emitManagedRValueWithCleanup(SILValue v); ManagedValue emitManagedRValueWithCleanup(SILValue v, const TypeLowering &lowering); diff --git a/test/SIL/OwnershipVerifier/false_positive_leaks.sil b/test/SIL/OwnershipVerifier/false_positive_leaks.sil index 7f6ec9345388e..3a51ba37f7b3a 100644 --- a/test/SIL/OwnershipVerifier/false_positive_leaks.sil +++ b/test/SIL/OwnershipVerifier/false_positive_leaks.sil @@ -26,9 +26,10 @@ sil [ossa] @leak_loop_test : $@convention(thin) (@owned Builtin.NativeObject) -> bb0(%0 : @owned $Builtin.NativeObject): %1 = alloc_stack $Builtin.NativeObject %2 = begin_borrow %0 : $Builtin.NativeObject - store_borrow %2 to %1 : $*Builtin.NativeObject + %sbi = store_borrow %2 to %1 : $*Builtin.NativeObject %3 = function_ref @in_guaranteed_user : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () - apply %3(%1) : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () + apply %3(%sbi) : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () + end_borrow %sbi : $*Builtin.NativeObject end_borrow %2 : $Builtin.NativeObject dealloc_stack %1 : $*Builtin.NativeObject br bb1 diff --git a/test/SIL/OwnershipVerifier/interior_pointer.sil b/test/SIL/OwnershipVerifier/interior_pointer.sil index 341af147dec10..6121b4a960bd3 100644 --- a/test/SIL/OwnershipVerifier/interior_pointer.sil +++ b/test/SIL/OwnershipVerifier/interior_pointer.sil @@ -119,8 +119,7 @@ bb0(%0 : @owned $Box, %1 : $*Int): // CHECK-NEXT: Found outside of lifetime use?! // CHECK-NEXT: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %4, %3 // CHECK-NEXT: Consuming User: end_borrow %1 : $Builtin.NativeObject // id: %4 -// CHECK-NEXT: Non Consuming User: %7 = apply %6(%3) : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () -// CHECK-NEXT: Block: bb0 +// CHECK-NEXT: Non Consuming User: end_borrow %3 : $*Builtin.NativeObject sil [ossa] @store_borrow_result_used_outside_of_borrow_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () { bb0(%0 : @owned $Builtin.NativeObject): %0a = begin_borrow %0 : $Builtin.NativeObject @@ -130,6 +129,7 @@ bb0(%0 : @owned $Builtin.NativeObject): destroy_value %0 : $Builtin.NativeObject %func = function_ref @use_builtinnativeobject_inguaranteed : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () apply %func(%result) : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () + end_borrow %result : $*Builtin.NativeObject dealloc_stack %1 : $*Builtin.NativeObject %9999 = tuple() return %9999 : $() diff --git a/test/SIL/OwnershipVerifier/use_verifier.sil b/test/SIL/OwnershipVerifier/use_verifier.sil index 705b02dcc928e..a8e0f83aabfa6 100644 --- a/test/SIL/OwnershipVerifier/use_verifier.sil +++ b/test/SIL/OwnershipVerifier/use_verifier.sil @@ -127,7 +127,8 @@ bb0(%0 : @guaranteed $Builtin.NativeObject): sil [ossa] @store_borrow_result : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () { bb0(%0 : @guaranteed $Builtin.NativeObject): %1 = alloc_stack $Builtin.NativeObject - store_borrow %0 to %1 : $*Builtin.NativeObject + %sb = store_borrow %0 to %1 : $*Builtin.NativeObject + end_borrow %sb : $*Builtin.NativeObject dealloc_stack %1 : $*Builtin.NativeObject %9999 = tuple() return %9999 : $() diff --git a/test/SIL/Parser/borrow.sil b/test/SIL/Parser/borrow.sil index 9f5eddac272d6..fbce300ea7435 100644 --- a/test/SIL/Parser/borrow.sil +++ b/test/SIL/Parser/borrow.sil @@ -10,8 +10,8 @@ import Builtin // CHECK: [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]] // CHECK: end_borrow [[BORROWED_ARG2]] // CHECK: [[MEM:%.*]] = alloc_stack $Builtin.NativeObject -// CHECK: store_borrow [[ARG2]] to [[MEM]] : $*Builtin.NativeObject -// CHECK: end_borrow [[MEM]] : $*Builtin.NativeObject +// CHECK: [[SB:%.*]] = store_borrow [[ARG2]] to [[MEM]] : $*Builtin.NativeObject +// CHECK: end_borrow [[SB]] : $*Builtin.NativeObject // CHECK: } // end sil function 'borrow_test' sil [ossa] @borrow_test : $@convention(thin) (@in Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { bb0(%0 : $*Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject): @@ -19,8 +19,8 @@ bb0(%0 : $*Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject): end_borrow %2 : $Builtin.NativeObject %3 = alloc_stack $Builtin.NativeObject - store_borrow %1 to %3 : $*Builtin.NativeObject - end_borrow %3 : $*Builtin.NativeObject + %sb = store_borrow %1 to %3 : $*Builtin.NativeObject + end_borrow %sb : $*Builtin.NativeObject dealloc_stack %3 : $*Builtin.NativeObject destroy_addr %0 : $*Builtin.NativeObject diff --git a/test/SIL/Serialization/borrow.sil b/test/SIL/Serialization/borrow.sil index 0485712b54078..917a6aa9c3e25 100644 --- a/test/SIL/Serialization/borrow.sil +++ b/test/SIL/Serialization/borrow.sil @@ -56,8 +56,8 @@ bb0(%0 : $*Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject): end_borrow %2 : $Builtin.NativeObject %3 = alloc_stack $Builtin.NativeObject - store_borrow %1 to %3 : $*Builtin.NativeObject - end_borrow %3 : $*Builtin.NativeObject + %sb = store_borrow %1 to %3 : $*Builtin.NativeObject + end_borrow %sb : $*Builtin.NativeObject dealloc_stack %3 : $*Builtin.NativeObject destroy_addr %0 : $*Builtin.NativeObject %4 = tuple() diff --git a/test/SIL/memory_lifetime.sil b/test/SIL/memory_lifetime.sil index e59fccc7f7ded..d4c105a194e7a 100644 --- a/test/SIL/memory_lifetime.sil +++ b/test/SIL/memory_lifetime.sil @@ -506,7 +506,8 @@ bb0(%0 : $*T): sil [ossa] @test_store_borrow : $@convention(thin) (@guaranteed T) -> () { bb0(%0 : @guaranteed $T): %s = alloc_stack $T - store_borrow %0 to %s : $*T + %sb = store_borrow %0 to %s : $*T + end_borrow %sb : $*T dealloc_stack %s : $*T %res = tuple () return %res : $() diff --git a/test/SIL/memory_lifetime_failures.sil b/test/SIL/memory_lifetime_failures.sil index f04d4446d60e7..ce868ce49c910 100644 --- a/test/SIL/memory_lifetime_failures.sil +++ b/test/SIL/memory_lifetime_failures.sil @@ -271,11 +271,12 @@ bb0(%0 : $*T): return %res : $() } -// CHECK: SIL memory lifetime failure in @test_store_borrow_destroy: memory is not initialized, but should be +// CHECK: SIL memory lifetime failure in @test_store_borrow_destroy: store-borrow location cannot be written sil [ossa] @test_store_borrow_destroy : $@convention(thin) (@guaranteed T) -> () { bb0(%0 : @guaranteed $T): %s = alloc_stack $T - store_borrow %0 to %s : $*T + %sb = store_borrow %0 to %s : $*T + end_borrow %sb : $*T destroy_addr %s : $*T dealloc_stack %s : $*T %res = tuple () @@ -284,13 +285,14 @@ bb0(%0 : @guaranteed $T): sil [ossa] @func_with_inout_param : $@convention(thin) (@inout T) -> () -// CHECK: SIL memory lifetime failure in @test_store_borrow_inout: store-borrow location cannot be written +// T-CHECK: SIL memory lifetime failure in @test_store_borrow_inout: store-borrow location cannot be written sil [ossa] @test_store_borrow_inout : $@convention(thin) (@guaranteed T) -> () { bb0(%0 : @guaranteed $T): %s = alloc_stack $T - store_borrow %0 to %s : $*T + %sb = store_borrow %0 to %s : $*T %f = function_ref @func_with_inout_param : $@convention(thin) (@inout T) -> () - %a = apply %f(%s) : $@convention(thin) (@inout T) -> () + %a = apply %f(%sb) : $@convention(thin) (@inout T) -> () + end_borrow %sb : $*T dealloc_stack %s : $*T %res = tuple () return %res : $() @@ -300,7 +302,8 @@ bb0(%0 : @guaranteed $T): sil [ossa] @test_store_borrow_store : $@convention(thin) (@guaranteed T, @owned T) -> () { bb0(%0 : @guaranteed $T, %1 : @owned $T): %s = alloc_stack $T - store_borrow %0 to %s : $*T + %sb = store_borrow %0 to %s : $*T + end_borrow %sb : $*T store %1 to [assign] %s : $*T dealloc_stack %s : $*T %res = tuple () @@ -311,7 +314,8 @@ bb0(%0 : @guaranteed $T, %1 : @owned $T): sil [ossa] @test_store_borrow_load : $@convention(thin) (@guaranteed T) -> @owned T { bb0(%0 : @guaranteed $T): %s = alloc_stack $T - store_borrow %0 to %s : $*T + %sb = store_borrow %0 to %s : $*T + end_borrow %sb : $*T %res = load [take] %s : $*T dealloc_stack %s : $*T return %res : $T @@ -321,7 +325,8 @@ bb0(%0 : @guaranteed $T): sil [ossa] @test_store_borrow_copy_src : $@convention(thin) (@guaranteed T) -> @out T { bb0(%0 : $*T, %1 : @guaranteed $T): %s = alloc_stack $T - store_borrow %1 to %s : $*T + %sb = store_borrow %1 to %s : $*T + end_borrow %sb : $*T copy_addr [take] %s to [initialization] %0 : $*T dealloc_stack %s : $*T %res = tuple () @@ -332,7 +337,8 @@ bb0(%0 : $*T, %1 : @guaranteed $T): sil [ossa] @test_store_borrow_copy_dst : $@convention(thin) (@in_guaranteed T, @guaranteed T) -> () { bb0(%0 : $*T, %1 : @guaranteed $T): %s = alloc_stack $T - store_borrow %1 to %s : $*T + %sb = store_borrow %1 to %s : $*T + end_borrow %sb : $*T copy_addr %0 to %s : $*T dealloc_stack %s : $*T %res = tuple () @@ -343,7 +349,8 @@ bb0(%0 : $*T, %1 : @guaranteed $T): sil [ossa] @test_store_borrow_init_enum : $@convention(thin) (@guaranteed Optional) -> () { bb0(%0 : @guaranteed $Optional): %s = alloc_stack $Optional - store_borrow %0 to %s : $*Optional + %sb = store_borrow %0 to %s : $*Optional + end_borrow %sb : $*Optional %ie = init_enum_data_addr %s : $*Optional, #Optional.some!enumelt dealloc_stack %s : $*Optional %res = tuple () @@ -354,8 +361,9 @@ bb0(%0 : @guaranteed $Optional): sil [ossa] @test_store_borrow_take_enum : $@convention(thin) (@guaranteed Optional) -> () { bb0(%0 : @guaranteed $Optional): %s = alloc_stack $Optional - store_borrow %0 to %s : $*Optional + %sb = store_borrow %0 to %s : $*Optional %ue = unchecked_take_enum_data_addr %s : $*Optional, #Optional.some!enumelt + end_borrow %sb : $*Optional dealloc_stack %s : $*Optional %res = tuple () return %res : $() @@ -369,7 +377,8 @@ bb0(%0 : @guaranteed $T): store %copy to [init] %stk : $*T %ld = load [take] %stk : $*T destroy_value %ld : $T - store_borrow %0 to %stk : $*T + %sb = store_borrow %0 to %stk : $*T + end_borrow %sb : $*T dealloc_stack %stk : $*T %8 = tuple () return %8 : $() @@ -385,7 +394,8 @@ bb0(%0 : @guaranteed $T): destroy_value %ld : $T br bb1 bb1: - store_borrow %0 to %stk : $*T + %sb = store_borrow %0 to %stk : $*T + end_borrow %sb : $*T dealloc_stack %stk : $*T %8 = tuple () return %8 : $() diff --git a/test/SILGen/class_bound_protocols.swift b/test/SILGen/class_bound_protocols.swift index 5e13d532fbc21..d342d8bd9d1cd 100644 --- a/test/SILGen/class_bound_protocols.swift +++ b/test/SILGen/class_bound_protocols.swift @@ -189,10 +189,11 @@ func takesInheritsMutatingMethod(x: inout InheritsMutatingMethod, // ** pass to an in_guaranteed method. PredictableMemOpts is able to handle this // ** type of temporary codegen successfully. // CHECK-NEXT: [[TEMPORARY_2:%.*]] = alloc_stack $@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: store_borrow [[X_PAYLOAD_RELOADED:%.*]] to [[TEMPORARY_2]] + // CHECK-NEXT: [[SB:%.*]] = store_borrow [[X_PAYLOAD_RELOADED:%.*]] to [[TEMPORARY_2]] // // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", InheritsMutatingMethod) Self, #HasMutatingMethod.mutatingCounter!getter : (Self) -> () -> Value, [[X_PAYLOAD]] : $@opened("{{.*}}", InheritsMutatingMethod) Self : $@convention(witness_method: HasMutatingMethod) <Ï„_0_0 where Ï„_0_0 : HasMutatingMethod> (@in_guaranteed Ï„_0_0) -> Value - // CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[METHOD]]<@opened("{{.*}}", InheritsMutatingMethod) Self>([[TEMPORARY_2]]) : $@convention(witness_method: HasMutatingMethod) <Ï„_0_0 where Ï„_0_0 : HasMutatingMethod> (@in_guaranteed Ï„_0_0) -> Value + // CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[METHOD]]<@opened("{{.*}}", InheritsMutatingMethod) Self>([[SB]]) : $@convention(witness_method: HasMutatingMethod) <Ï„_0_0 where Ï„_0_0 : HasMutatingMethod> (@in_guaranteed Ï„_0_0) -> Value + // CHECK-NEXT: end_borrow [[SB]] // CHECK-NEXT: dealloc_stack [[TEMPORARY_2]] // CHECK-NEXT: end_borrow // CHECK-NEXT: destroy_addr diff --git a/test/SILGen/copy_operator.swift b/test/SILGen/copy_operator.swift index 77260e1aeeb33..2fff7423f4da2 100644 --- a/test/SILGen/copy_operator.swift +++ b/test/SILGen/copy_operator.swift @@ -24,10 +24,11 @@ class Klass {} // CHECK-NEXT: debug_value // CHECK-NEXT: [[RESULT_ADDR:%.*]] = alloc_stack $Klass // CHECK-NEXT: [[INPUT_ADDR:%.*]] = alloc_stack $Klass -// CHECK-NEXT: store_borrow [[ARG]] to [[INPUT_ADDR]] +// CHECK-NEXT: [[SB:%.*]] = store_borrow [[ARG]] to [[INPUT_ADDR]] // CHECK-NEXT: // function_ref _copy(_:) // CHECK-NEXT: [[COPY:%.*]] = function_ref @$ss5_copyyxxlF : -// CHECK-NEXT: [[APPLY_RESULT:%.*]] = apply [[COPY]]([[RESULT_ADDR]], [[INPUT_ADDR]]) +// CHECK-NEXT: [[APPLY_RESULT:%.*]] = apply [[COPY]]([[RESULT_ADDR]], [[SB]]) +// CHECK-NEXT: end_borrow // CHECK-NEXT: dealloc_stack [[INPUT_ADDR]] // CHECK-NEXT: [[RELOADED_VALUE:%.*]] = load [take] [[RESULT_ADDR]] // CHECK-NEXT: dealloc_stack [[RESULT_ADDR]] @@ -65,10 +66,11 @@ public func useCopy(_ k: Klass) -> Klass { // CHECK-NEXT: debug_value // CHECK-NEXT: [[RESULT_ADDR:%.*]] = alloc_stack $T // CHECK-NEXT: [[INPUT_ADDR:%.*]] = alloc_stack $T -// CHECK-NEXT: store_borrow [[ARG]] to [[INPUT_ADDR]] +// CHECK-NEXT: [[SB:%.*]] = store_borrow [[ARG]] to [[INPUT_ADDR]] // CHECK-NEXT: // function_ref _copy(_:) // CHECK-NEXT: [[COPY:%.*]] = function_ref @$ss5_copyyxxlF : -// CHECK-NEXT: [[APPLY_RESULT:%.*]] = apply [[COPY]]([[RESULT_ADDR]], [[INPUT_ADDR]]) +// CHECK-NEXT: [[APPLY_RESULT:%.*]] = apply [[COPY]]([[RESULT_ADDR]], [[SB]]) +// CHECK-NEXT: end_borrow // CHECK-NEXT: dealloc_stack [[INPUT_ADDR]] // CHECK-NEXT: [[RELOADED_VALUE:%.*]] = load [take] [[RESULT_ADDR]] // CHECK-NEXT: dealloc_stack [[RESULT_ADDR]] diff --git a/test/SILGen/lexical_lifetime.swift b/test/SILGen/lexical_lifetime.swift index 812c42e2e38fc..94543f6abef1a 100644 --- a/test/SILGen/lexical_lifetime.swift +++ b/test/SILGen/lexical_lifetime.swift @@ -91,9 +91,9 @@ func lexical_borrow_let_class_in_enum() { // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INSTANCE]] // CHECK: debug_value [[LIFETIME]] // CHECK: [[ADDR:%[^,]+]] = alloc_stack $C -// CHECK: store_borrow [[LIFETIME]] to [[ADDR]] +// CHECK: [[SB:%.*]] = store_borrow [[LIFETIME]] to [[ADDR]] // CHECK: [[USE_GENERIC:%[^,]+]] = function_ref @use_generic -// CHECK: [[REGISTER_6:%[^,]+]] = apply [[USE_GENERIC]]([[ADDR]]) +// CHECK: [[REGISTER_6:%[^,]+]] = apply [[USE_GENERIC]]([[SB]]) // CHECK: dealloc_stack [[ADDR]] // CHECK: end_borrow [[LIFETIME]] // CHECK: [[RETVAL:%[^,]+]] = tuple () diff --git a/test/SILGen/objc_bridging_any.swift b/test/SILGen/objc_bridging_any.swift index 609db861364e8..e44a5b4373fe9 100644 --- a/test/SILGen/objc_bridging_any.swift +++ b/test/SILGen/objc_bridging_any.swift @@ -151,8 +151,8 @@ func passingToId(receiver: NSIdLover, // CHECK: [[BRIDGE_OPTIONAL:%.*]] = function_ref @$sSq19_bridgeToObjectiveCyXlyF // CHECK: [[TMP:%.*]] = alloc_stack $Optional // CHECK: [[BORROWED_OPT_STRING_COPY:%.*]] = begin_borrow [[OPT_STRING_COPY]] - // CHECK: store_borrow [[BORROWED_OPT_STRING_COPY]] to [[TMP]] - // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]([[TMP]]) + // CHECK: [[SB1:%.*]] = store_borrow [[BORROWED_OPT_STRING_COPY]] to [[TMP]] + // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]([[SB1]]) // CHECK: end_borrow [[BORROWED_OPT_STRING_COPY]] // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover, // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]]) @@ -162,8 +162,8 @@ func passingToId(receiver: NSIdLover, // CHECK: [[BRIDGE_OPTIONAL:%.*]] = function_ref @$sSq19_bridgeToObjectiveCyXlyF // CHECK: [[TMP:%.*]] = alloc_stack $Optional // CHECK: [[BORROWED_OPT_NSSTRING_COPY:%.*]] = begin_borrow [[OPT_NSSTRING_COPY]] - // CHECK: store_borrow [[BORROWED_OPT_NSSTRING_COPY]] to [[TMP]] - // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]([[TMP]]) + // CHECK: [[SB2:%.*]] = store_borrow [[BORROWED_OPT_NSSTRING_COPY]] to [[TMP]] + // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]([[SB2]]) // CHECK: end_borrow [[BORROWED_OPT_NSSTRING_COPY]] // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover, // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]]) @@ -668,7 +668,8 @@ class AnyHashableClass : NSObject { // CHECK: [[FN:%.*]] = function_ref @$sIeg_ytIegr_TR // CHECK: partial_apply [callee_guaranteed] [[FN]] // CHECK: [[SELF:%.*]] = alloc_stack $Optional<@callee_guaranteed @substituted <Ï„_0_0> () -> @out Ï„_0_0 for <()>> -// CHECK: apply [[BRIDGE]]<() -> ()>([[SELF]]) +// CHECK: [[SB:%.*]] = store_borrow {{.*}} to [[SELF]] +// CHECK: apply [[BRIDGE]]<() -> ()>([[SB]]) func bridgeOptionalFunctionToAnyObject(fn: (() -> ())?) -> AnyObject { return fn as AnyObject } diff --git a/test/SILGen/objc_bridging_peephole.swift b/test/SILGen/objc_bridging_peephole.swift index 5da6d358d433c..a5d933373e1a8 100644 --- a/test/SILGen/objc_bridging_peephole.swift +++ b/test/SILGen/objc_bridging_peephole.swift @@ -118,8 +118,8 @@ func testForcedMethodResult(dummy: DummyClass) { // CHECK: [[BRIDGE:%.*]] = function_ref @$sSq19_bridgeToObjectiveCyXlyF // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $Optional // CHECK-NEXT: [[BORROW:%.*]] = begin_borrow [[OPTSTRING]] - // CHECK-NEXT: store_borrow [[BORROW]] to [[TEMP]] : $*Optional - // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE]]([[TEMP]]) + // CHECK-NEXT: [[SB:%.*]] = store_borrow [[BORROW]] to [[TEMP]] : $*Optional + // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE]]([[SB]]) // CHECK: [[USE:%.*]] = function_ref @$s22objc_bridging_peephole12useAnyObjectyyyXlF // CHECK: apply [[USE]]([[ANYOBJECT]]) useAnyObject(dummy.fetchNullproneString() as AnyObject) @@ -227,8 +227,8 @@ func testForcedPropertyValue(dummy: DummyClass) { // CHECK: [[BRIDGE:%.*]] = function_ref @$sSq19_bridgeToObjectiveCyXlyF // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $Optional // CHECK-NEXT: [[BORROW:%.*]] = begin_borrow [[OPTSTRING]] - // CHECK-NEXT: store_borrow [[BORROW]] to [[TEMP]] : $*Optional - // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE]]([[TEMP]]) + // CHECK-NEXT: [[SB:%.*]] = store_borrow [[BORROW]] to [[TEMP]] : $*Optional + // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE]]([[SB]]) // CHECK: dealloc_stack [[TEMP]] // CHECK: [[USE:%.*]] = function_ref @$s22objc_bridging_peephole12useAnyObjectyyyXlF // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]]) diff --git a/test/SILGen/partial_apply_protocol_class_refinement_method.swift b/test/SILGen/partial_apply_protocol_class_refinement_method.swift index 2201676a7e6c8..fea78c1cff3cd 100644 --- a/test/SILGen/partial_apply_protocol_class_refinement_method.swift +++ b/test/SILGen/partial_apply_protocol_class_refinement_method.swift @@ -9,8 +9,9 @@ protocol Q: class, P {} func partialApply(_ q: Q) -> () -> () { // CHECK: [[OPENED:%.*]] = open_existential_ref [[ARG]] // CHECK: [[TMP:%.*]] = alloc_stack - // CHECK: store_borrow [[OPENED]] to [[TMP:%.*]] : - // CHECK: apply {{%.*}}<{{.*}}>([[TMP]]) + // CHECK: [[SB:%.*]] = store_borrow [[OPENED]] to [[TMP:%.*]] : + // CHECK: apply {{%.*}}<{{.*}}>([[SB]]) + // CHECK: end_borrow // CHECK-NEXT: dealloc_stack [[TMP]] return q.foo } diff --git a/test/SILGen/protocol_extensions.swift b/test/SILGen/protocol_extensions.swift index 670b41bc4aa37..eb18b54b392a1 100644 --- a/test/SILGen/protocol_extensions.swift +++ b/test/SILGen/protocol_extensions.swift @@ -103,9 +103,10 @@ func testD(_ m: MetaHolder, dd: D.Type, d: D) { // CHECK: [[D2L:%[0-9]+]] = begin_borrow [lexical] [[D2]] // CHECK: [[RESULT:%.*]] = project_box [[D2L]] // CHECK: [[MATERIALIZED_BORROWED_D:%[0-9]+]] = alloc_stack $D - // CHECK: store_borrow [[D]] to [[MATERIALIZED_BORROWED_D]] + // CHECK: [[SB:%.*]] = store_borrow [[D]] to [[MATERIALIZED_BORROWED_D]] // CHECK: [[FN:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE11returnsSelf{{[_0-9a-zA-Z]*}}F - // CHECK: apply [[FN]]([[RESULT]], [[MATERIALIZED_BORROWED_D]]) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : P1> (@in_guaranteed Ï„_0_0) -> @out Ï„_0_0 + // CHECK: apply [[FN]]([[RESULT]], [[SB]]) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : P1> (@in_guaranteed Ï„_0_0) -> @out Ï„_0_0 + // CHECK: end_borrow // CHECK-NEXT: dealloc_stack [[MATERIALIZED_BORROWED_D]] var d2: D = d.returnsSelf() diff --git a/test/SILGen/subclass_existentials.swift b/test/SILGen/subclass_existentials.swift index 02c66300fa6d7..3d39fdb7f3015 100644 --- a/test/SILGen/subclass_existentials.swift +++ b/test/SILGen/subclass_existentials.swift @@ -129,12 +129,13 @@ func methodCalls( // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base & P to $@opened("{{.*}}", Base & P) Self // CHECK: [[SELF_BOX:%.*]] = alloc_stack $@opened("{{.*}}", Base & P) Self - // CHECK: store_borrow [[PAYLOAD]] to [[SELF_BOX]] : $*@opened("{{.*}}", Base & P) Self + // CHECK: [[SB:%.*]] = store_borrow [[PAYLOAD]] to [[SELF_BOX]] : $*@opened("{{.*}}", Base & P) Self // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", Base & P) Self, #P.protocolSelfReturn : (Self) -> () -> Self, [[PAYLOAD]] : $@opened("{{.*}}", Base & P) Self : $@convention(witness_method: P) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> @out Ï„_0_0 // CHECK: [[RESULT_BOX:%.*]] = alloc_box // CHECK: [[RESULT_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[RESULT_BOX]] // CHECK: [[RESULT_BUF:%.*]] = project_box [[RESULT_LIFETIME]] - // CHECK: apply [[METHOD]]<@opened("{{.*}}", Base & P) Self>([[RESULT_BUF]], [[SELF_BOX]]) : $@convention(witness_method: P) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> @out Ï„_0_0 + // CHECK: apply [[METHOD]]<@opened("{{.*}}", Base & P) Self>([[RESULT_BUF]], [[SB]]) : $@convention(witness_method: P) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> @out Ï„_0_0 + // end_borrow [[SB]] // CHECK: dealloc_stack [[SELF_BOX]] : $*@opened("{{.*}}", Base & P) Self // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT_BUF]] : $*@opened("{{.*}}", Base & P) Self // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", Base & P) Self : $@opened("{{.*}}", Base & P) Self, $Base & P diff --git a/test/SILGen/switch_var.swift b/test/SILGen/switch_var.swift index 2256841ac6efc..7de48efd06161 100644 --- a/test/SILGen/switch_var.swift +++ b/test/SILGen/switch_var.swift @@ -472,8 +472,8 @@ func test_let() { // CHECK: [[VAL_COPY_3:%.*]] = copy_value [[BORROWED_VAL_3]] // CHECK: [[BORROWED_VAL_COPY_3:%.*]] = begin_borrow [lexical] [[VAL_COPY_3]] // CHECK: function_ref @$s10switch_var4barsSSyF - // CHECK: store_borrow [[BORROWED_VAL_COPY_3]] to [[IN_ARG:%.*]] : - // CHECK: apply {{%.*}}({{.*}}, [[IN_ARG]]) + // CHECK: [[SB:%.*]] = store_borrow [[BORROWED_VAL_COPY_3]] to [[IN_ARG:%.*]] : + // CHECK: apply {{%.*}}({{.*}}, [[SB]]) // CHECK: cond_br {{%.*}}, [[YES_CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]] // ExprPatterns implicitly contain a 'let' binding. case bars(): @@ -548,8 +548,8 @@ func test_mixed_let_var() { // CHECK: [[BORROWED_VAL:%.*]] = begin_borrow [[VAL]] // CHECK: [[VAL_COPY:%.*]] = copy_value [[BORROWED_VAL]] // CHECK: [[BORROWED_VAL_COPY:%.*]] = begin_borrow [lexical] [[VAL_COPY]] - // CHECK: store_borrow [[BORROWED_VAL_COPY]] to [[TMP_VAL_COPY_ADDR:%.*]] : - // CHECK: apply {{.*}}({{.*}}, [[TMP_VAL_COPY_ADDR]]) + // CHECK: [[SB:%.*]] = store_borrow [[BORROWED_VAL_COPY]] to [[TMP_VAL_COPY_ADDR:%.*]] : + // CHECK: apply {{.*}}({{.*}}, [[SB]]) // CHECK: cond_br {{.*}}, [[CASE3:bb[0-9]+]], [[NOCASE3:bb[0-9]+]] case bars(): // CHECK: [[CASE3]]: diff --git a/test/SILOptimizer/OSLogMandatoryOptTest.sil b/test/SILOptimizer/OSLogMandatoryOptTest.sil index 1b7215cd0504c..adcd8d1df7bf5 100644 --- a/test/SILOptimizer/OSLogMandatoryOptTest.sil +++ b/test/SILOptimizer/OSLogMandatoryOptTest.sil @@ -89,9 +89,10 @@ bb0: %9 = struct_extract %8 : $OSLogMessageStub, #OSLogMessageStub.interpolation %10 = struct_extract %9 : $OSLogInterpolationStub, #OSLogInterpolationStub.formatString %11 = alloc_stack $String - store_borrow %10 to %11 : $*String + %12 = store_borrow %10 to %11 : $*String %13 = function_ref @useFormatStringIndirect : $@convention(thin) (@in_guaranteed String) -> () - %14 = apply %13(%11) : $@convention(thin) (@in_guaranteed String) -> () + %14 = apply %13(%12) : $@convention(thin) (@in_guaranteed String) -> () + end_borrow %12 : $*String end_borrow %8 : $OSLogMessageStub destroy_value %7 : $OSLogMessageStub dealloc_stack %11 : $*String diff --git a/test/SILOptimizer/OSLogMandatoryOptTest.swift b/test/SILOptimizer/OSLogMandatoryOptTest.swift index 3503f3bf943e0..2642a99a77e41 100644 --- a/test/SILOptimizer/OSLogMandatoryOptTest.swift +++ b/test/SILOptimizer/OSLogMandatoryOptTest.swift @@ -45,8 +45,8 @@ func testSimpleInterpolation() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]] // We need to wade through some borrows and copy values here. // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] @@ -92,8 +92,8 @@ func testInterpolationWithFormatOptions() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] @@ -140,8 +140,8 @@ func testInterpolationWithFormatOptionsAndPrivacy() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] @@ -194,8 +194,9 @@ func testInterpolationWithMultipleArguments() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]] + // CHECK-DAG: [[ARGSARRAYADDR]] = alloc_stack $Array<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()> // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] @@ -244,8 +245,8 @@ func testLogMessageWithoutData() { // Check whether argument array is folded. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to {{.*}} // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[ARGSARRAY:%[0-9]+]] @@ -317,8 +318,8 @@ func testMessageWithTooManyArguments() { // Check whether argument array is folded. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] @@ -402,8 +403,8 @@ func testDynamicStringArguments() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] @@ -455,8 +456,8 @@ func testNSObjectInterpolation() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] @@ -503,8 +504,8 @@ func testDoubleInterpolation() { // not checked here, but is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) - // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[SB:%[0-9]+]]) + // CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] diff --git a/test/SILOptimizer/dead_code_elimination_ossa.sil b/test/SILOptimizer/dead_code_elimination_ossa.sil index 4c3662b53e6dd..dd5b9a5e1ce78 100644 --- a/test/SILOptimizer/dead_code_elimination_ossa.sil +++ b/test/SILOptimizer/dead_code_elimination_ossa.sil @@ -353,9 +353,10 @@ bb0(%0 : @guaranteed $S): debug_value %0 : $S, let, name "self", argno 1 %2 = alloc_stack $S %3 = store_borrow %0 to %2 : $*S - %4 = load_borrow %2 : $*S + %4 = load_borrow %3 : $*S fix_lifetime %4 : $S end_borrow %4 : $S + end_borrow %3 : $*S dealloc_stack %2 : $*S %8 = tuple () return %8 : $() diff --git a/test/SILOptimizer/existential_transform_extras_ossa.sil b/test/SILOptimizer/existential_transform_extras_ossa.sil index 0df506afed6cb..51b1ab9a24f2a 100644 --- a/test/SILOptimizer/existential_transform_extras_ossa.sil +++ b/test/SILOptimizer/existential_transform_extras_ossa.sil @@ -295,7 +295,8 @@ bb0(%0 : @guaranteed $Klass3 & P): %3 = alloc_stack $@opened("77949BFA-77BC-11EB-BC0E-F2189810406F", Klass3 & P) Self %4 = store_borrow %2 to %3 : $*@opened("77949BFA-77BC-11EB-BC0E-F2189810406F", Klass3 & P) Self %5 = witness_method $@opened("77949BFA-77BC-11EB-BC0E-F2189810406F", Klass3 & P) Self, #P.foo : (Self) -> () -> Int32, %2 : $@opened("77949BFA-77BC-11EB-BC0E-F2189810406F", Klass3 & P) Self : $@convention(witness_method: P) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> Int32 - %6 = apply %5<@opened("77949BFA-77BC-11EB-BC0E-F2189810406F", Klass3 & P) Self>(%3) : $@convention(witness_method: P) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> Int32 + %6 = apply %5<@opened("77949BFA-77BC-11EB-BC0E-F2189810406F", Klass3 & P) Self>(%4) : $@convention(witness_method: P) <Ï„_0_0 where Ï„_0_0 : P> (@in_guaranteed Ï„_0_0) -> Int32 + end_borrow %4 : $*@opened("77949BFA-77BC-11EB-BC0E-F2189810406F", Klass3 & P) Self dealloc_stack %3 : $*@opened("77949BFA-77BC-11EB-BC0E-F2189810406F", Klass3 & P) Self return %6 : $Int32 } diff --git a/test/SILOptimizer/for_each_loop_unroll_test.sil b/test/SILOptimizer/for_each_loop_unroll_test.sil index 313789f670281..2580aa9faf04a 100644 --- a/test/SILOptimizer/for_each_loop_unroll_test.sil +++ b/test/SILOptimizer/for_each_loop_unroll_test.sil @@ -33,9 +33,10 @@ bb0: %26 = thin_to_thick_function %25 : $@convention(thin) @noescape (@in_guaranteed Builtin.Int64) -> @error Error to $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error Error // A stub for Sequence.forEach(_:) %30 = function_ref @forEach : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error - try_apply %30<[Builtin.Int64]>(%26, %22) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error, normal bb1, error bb2 + try_apply %30<[Builtin.Int64]>(%26, %23) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error, normal bb1, error bb2 bb1(%32 : $()): + end_borrow %23 : $*Array dealloc_stack %22 : $*Array end_borrow %21 : $Array destroy_value %3 : $Array @@ -95,9 +96,10 @@ bb0(%0: @owned $@callee_guaranteed @substituted () -> @out A for , %1: %26 = thin_to_thick_function %25 : $@convention(thin) @noescape (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error Error to $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error Error // A stub for Sequence.forEach(_:) %30 = function_ref @forEach : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error - try_apply %30<[() -> Int]>(%26, %22) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error, normal bb1, error bb2 + try_apply %30<[() -> Int]>(%26, %23) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error, normal bb1, error bb2 bb1(%32 : $()): + end_borrow %23 : $*Array<() -> Int> dealloc_stack %22 : $*Array<() -> Int> end_borrow %21 : $Array<() -> Int> destroy_value %5 : $Array<() -> Int> @@ -163,14 +165,16 @@ bb0: %26 = thin_to_thick_function %25 : $@convention(thin) @noescape (@in_guaranteed Builtin.Int64) -> @error Error to $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error Error // A stub for Sequence.forEach(_:) %30 = function_ref @forEach : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error - try_apply %30<[Builtin.Int64]>(%26, %22) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error, normal bb1, error bb2 + try_apply %30<[Builtin.Int64]>(%26, %23) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error, normal bb1, error bb2 bb1(%32 : $()): + end_borrow %23 : $*Array // An indirect fixLifetime use dealloc_stack %22 : $*Array %33 = alloc_stack $Array %34 = store_borrow %21 to %33 : $*Array - fix_lifetime %33 : $*Array + fix_lifetime %34 : $*Array + end_borrow %34 : $*Array dealloc_stack %33 : $*Array end_borrow %21 : $Array destroy_value %3 : $Array @@ -207,9 +211,10 @@ bb2(%arg2 : $Builtin.Int64): %26 = thin_to_thick_function %25 : $@convention(thin) @noescape (@in_guaranteed Builtin.Int64) -> @error Error to $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error Error // A stub for Sequence.forEach(_:) %30 = function_ref @forEach : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error - try_apply %30<[Builtin.Int64]>(%26, %22) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error, normal bb3, error bb4 + try_apply %30<[Builtin.Int64]>(%26, %23) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed Ï„_0_0.Element) -> @error Error, @in_guaranteed Ï„_0_0) -> @error Error, normal bb3, error bb4 bb3(%32 : $()): + end_borrow %23 : $*Array dealloc_stack %22 : $*Array end_borrow %21 : $Array destroy_value %13 : $Array diff --git a/test/SILOptimizer/mandatory_inlining_ossa_to_non_ossa.sil b/test/SILOptimizer/mandatory_inlining_ossa_to_non_ossa.sil index 4711909b0b638..0d38e6d96b0b2 100644 --- a/test/SILOptimizer/mandatory_inlining_ossa_to_non_ossa.sil +++ b/test/SILOptimizer/mandatory_inlining_ossa_to_non_ossa.sil @@ -28,10 +28,11 @@ sil [ossa] [transparent] @load_store_borrow_ossa_callee : $@convention(thin) (@o bb0(%0 : @owned $Builtin.NativeObject): %1 = begin_borrow %0 : $Builtin.NativeObject %2 = alloc_stack $Builtin.NativeObject - store_borrow %1 to %2 : $*Builtin.NativeObject - end_borrow %1 : $Builtin.NativeObject + %sb = store_borrow %1 to %2 : $*Builtin.NativeObject %f = function_ref @in_guaranteed_user : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () - apply %f(%2) : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () + apply %f(%sb) : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () + end_borrow %sb : $*Builtin.NativeObject + end_borrow %1 : $Builtin.NativeObject dealloc_stack %2 : $*Builtin.NativeObject %3 = alloc_stack $Builtin.NativeObject diff --git a/test/SILOptimizer/mem2reg_borrows.sil b/test/SILOptimizer/mem2reg_borrows.sil index 39f2648a95211..35310a76abe52 100644 --- a/test/SILOptimizer/mem2reg_borrows.sil +++ b/test/SILOptimizer/mem2reg_borrows.sil @@ -103,12 +103,13 @@ bb0(%0 : @owned $Klass): sil [ossa] @test_with_structs_and_borrows1 : $@convention(thin) (@guaranteed WrapperStruct) -> () { bb0(%0 : @guaranteed $WrapperStruct): %stk = alloc_stack $WrapperStruct - store_borrow %0 to %stk : $*WrapperStruct - %ele = struct_element_addr %stk : $*WrapperStruct, #WrapperStruct.val + %sb = store_borrow %0 to %stk : $*WrapperStruct + %ele = struct_element_addr %sb : $*WrapperStruct, #WrapperStruct.val %ld = load_borrow %ele : $*Klass %f = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () apply %f(%ld) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %ld : $Klass + end_borrow %sb : $*WrapperStruct dealloc_stack %stk : $*WrapperStruct %r = tuple () return %r : $() @@ -119,7 +120,8 @@ bb0(%0 : @guaranteed $WrapperStruct): sil [ossa] @store_only_allocas : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): %1 = alloc_stack $Klass - store_borrow %0 to %1 : $*Klass + %2 = store_borrow %0 to %1 : $*Klass + end_borrow %2 : $*Klass dealloc_stack %1 : $*Klass %6 = tuple () return %6 : $() @@ -131,7 +133,8 @@ bb0(%0 : @guaranteed $Klass): sil [ossa] @store_only_lexicalallocas : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): %1 = alloc_stack [lexical] $Klass - store_borrow %0 to %1 : $*Klass + %2 = store_borrow %0 to %1 : $*Klass + end_borrow %2 : $*Klass dealloc_stack %1 : $*Klass %6 = tuple () return %6 : $() @@ -143,11 +146,12 @@ bb0(%0 : @guaranteed $Klass): sil [ossa] @test1 : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): %1 = alloc_stack $Klass - store_borrow %0 to %1 : $*Klass - %2 = load_borrow %1 : $*Klass + %sb = store_borrow %0 to %1 : $*Klass + %2 = load_borrow %sb : $*Klass %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %2 : $Klass + end_borrow %sb : $*Klass dealloc_stack %1 : $*Klass %6 = tuple () return %6 : $() @@ -159,11 +163,12 @@ bb0(%0 : @guaranteed $Klass): sil [ossa] @test1_lexical : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): %1 = alloc_stack [lexical] $Klass - store_borrow %0 to %1 : $*Klass - %2 = load_borrow %1 : $*Klass + %sb = store_borrow %0 to %1 : $*Klass + %2 = load_borrow %sb : $*Klass %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %2 : $Klass + end_borrow %sb : $*Klass dealloc_stack %1 : $*Klass %6 = tuple () return %6 : $() @@ -175,15 +180,16 @@ bb0(%0 : @guaranteed $Klass): sil [ossa] @test2 : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): %1 = alloc_stack $Klass - store_borrow %0 to %1 : $*Klass - %2 = load_borrow %1 : $*Klass + %sb = store_borrow %0 to %1 : $*Klass + %2 = load_borrow %sb : $*Klass %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %2 : $Klass - %5 = load_borrow %1 : $*Klass + %5 = load_borrow %sb : $*Klass %6 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () %7 = apply %3(%5) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %5 : $Klass + end_borrow %sb : $*Klass dealloc_stack %1 : $*Klass %8 = tuple () return %8 : $() @@ -195,15 +201,17 @@ bb0(%0 : @guaranteed $Klass): sil [ossa] @test3 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): %2 = alloc_stack $Klass - store_borrow %0 to %2 : $*Klass - %3 = load_borrow %2 : $*Klass + %sb1 = store_borrow %0 to %2 : $*Klass + %3 = load_borrow %sb1 : $*Klass %4 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () %5 = apply %4(%3) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %3 : $Klass - store_borrow %1 to %2 : $*Klass - %6 = load_borrow %2 : $*Klass + end_borrow %sb1 : $*Klass + %sb2 = store_borrow %1 to %2 : $*Klass + %6 = load_borrow %sb2 : $*Klass %7 = apply %4(%6) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %6 : $Klass + end_borrow %sb2 : $*Klass dealloc_stack %2 : $*Klass %9 = tuple () return %9 : $() @@ -215,14 +223,15 @@ bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): sil [ossa] @test4 : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): %1 = alloc_stack $Klass - store_borrow %0 to %1 : $*Klass - %2 = load_borrow %1 : $*Klass + %sb = store_borrow %0 to %1 : $*Klass + %2 = load_borrow %sb: $*Klass %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %2 : $Klass - %5 = load [copy] %1 : $*Klass + %5 = load [copy] %sb : $*Klass %6 = function_ref @use_owned : $@convention(thin) (@owned Klass) -> () %7 = apply %6(%5) : $@convention(thin) (@owned Klass) -> () + end_borrow %sb : $*Klass dealloc_stack %1 : $*Klass %8 = tuple () return %8 : $() @@ -235,135 +244,47 @@ sil [ossa] @test6 : $@convention(thin) (@owned Klass) -> () { bb0(%0 : @owned $Klass): %1 = alloc_stack $Klass %b = begin_borrow %0 : $Klass - store_borrow %b to %1 : $*Klass - end_borrow %b : $Klass - %2 = load_borrow %1 : $*Klass + %sb = store_borrow %b to %1 : $*Klass + %2 = load_borrow %sb : $*Klass %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %2 : $Klass + end_borrow %sb : $*Klass + end_borrow %b : $Klass destroy_value %0 : $Klass dealloc_stack %1 : $*Klass %6 = tuple () return %6 : $() } -// Following tests are not optimized because multi block alloc with store_borrows is not handled in mem2reg -sil [ossa] @test_control_flow1 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { -bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): - %stk = alloc_stack $Klass - cond_br undef, bb1, bb2 - -bb1: - store_borrow %0 to %stk : $*Klass - br bb3 - -bb2: - store_borrow %1 to %stk : $*Klass - br bb3 - -bb3: - %2 = load_borrow %stk : $*Klass - %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () - %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () - end_borrow %2 : $Klass - dealloc_stack %stk : $*Klass - %8 = tuple () - return %8 : $() -} - -sil [ossa] @test_control_flow2 : $@convention(thin) (@owned Klass, @owned Klass) -> () { -bb0(%0 : @owned $Klass, %1 : @owned $Klass): - %stk = alloc_stack $Klass - cond_br undef, bb1, bb2 - -bb1: - %b1 = begin_borrow %0 : $Klass - store_borrow %b1 to %stk : $*Klass - end_borrow %b1 : $Klass - br bb3 - -bb2: - %b2 = begin_borrow %1 : $Klass - store_borrow %b2 to %stk : $*Klass - end_borrow %b2 : $Klass - br bb3 - -bb3: - %2 = load_borrow %stk : $*Klass - %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () - %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () - end_borrow %2 : $Klass - destroy_value %0 : $Klass - destroy_value %1 : $Klass - dealloc_stack %stk : $*Klass - %8 = tuple () - return %8 : $() -} - -sil [ossa] @test_control_flow3 : $@convention(thin) (@owned Klass, @owned Klass) -> () { -bb0(%0 : @owned $Klass, %1 : @owned $Klass): - %stk = alloc_stack $Klass - cond_br undef, bb1, bb2 - -bb1: - %b1 = begin_borrow %0 : $Klass - store_borrow %b1 to %stk : $*Klass - end_borrow %b1 : $Klass - br bb3 - -bb2: - %b2 = begin_borrow %1 : $Klass - store_borrow %b2 to %stk : $*Klass - end_borrow %b2 : $Klass - br bb3 - -bb3: - cond_br undef, bb4, bb5 - -bb4: - %2 = load_borrow %stk : $*Klass - %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () - %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () - end_borrow %2 : $Klass - br bb6 - -bb5: - br bb6 - -bb6: - destroy_value %0 : $Klass - destroy_value %1 : $Klass - dealloc_stack %stk : $*Klass - %8 = tuple () - return %8 : $() -} - -sil [ossa] @test_control_flow4 : $@convention(thin) (@guaranteed Klass) -> () { +sil [ossa] @test_control_flow1 : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): %stk = alloc_stack $Klass - store_borrow %0 to %stk : $*Klass + %sb = store_borrow %0 to %stk : $*Klass cond_br undef, bb1, bb2 bb1: - %ld1 = load_borrow %stk : $*Klass + %ld1 = load_borrow %sb : $*Klass fix_lifetime %ld1 : $Klass end_borrow %ld1 : $Klass + end_borrow %sb : $*Klass dealloc_stack %stk : $*Klass %r = tuple () return %r : $() bb2: - %ld2 = load_borrow %stk : $*Klass + %ld2 = load_borrow %sb : $*Klass fix_lifetime %ld2 : $Klass end_borrow %ld2 : $Klass + end_borrow %sb : $*Klass dealloc_stack %stk : $*Klass unreachable } -// CHECK-LABEL: sil [ossa] @test_control_flow5 : +// CHECK-LABEL: sil [ossa] @test_control_flow2 : // CHECK-NOT: alloc_stack -// CHECK-LABEL: } // end sil function 'test_control_flow5' -sil [ossa] @test_control_flow5 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { +// CHECK-LABEL: } // end sil function 'test_control_flow2' +sil [ossa] @test_control_flow2 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): %stk = alloc_stack $Klass cond_br undef, bb1, bb2 @@ -389,10 +310,10 @@ bb3: return %8 : $() } -// CHECK-LABEL: sil [ossa] @test_control_flow6 : +// CHECK-LABEL: sil [ossa] @test_control_flow3 : // CHECK-NOT: alloc_stack -// CHECK-LABEL: } // end sil function 'test_control_flow6' -sil [ossa] @test_control_flow6 : $@convention(thin) () -> () { +// CHECK-LABEL: } // end sil function 'test_control_flow3' +sil [ossa] @test_control_flow3 : $@convention(thin) () -> () { bb0: %4 = alloc_stack [lexical] $Klass %f = function_ref @get_owned : $@convention(thin) () -> @owned Klass @@ -417,10 +338,10 @@ bb3: return %r : $() } -// CHECK-LABEL: sil [ossa] @test_control_flow7 : +// CHECK-LABEL: sil [ossa] @test_control_flow4 : // CHECK-NOT: alloc_stack -// CHECK-LABEL: } // end sil function 'test_control_flow7' -sil [ossa] @test_control_flow7 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { +// CHECK-LABEL: } // end sil function 'test_control_flow4' +sil [ossa] @test_control_flow4 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): %stk = alloc_stack [lexical] $Klass cond_br undef, bb1, bb2 diff --git a/test/SILOptimizer/move_only_type_eliminator.sil b/test/SILOptimizer/move_only_type_eliminator.sil index fb8109384f226..f2f601535a379 100644 --- a/test/SILOptimizer/move_only_type_eliminator.sil +++ b/test/SILOptimizer/move_only_type_eliminator.sil @@ -165,19 +165,20 @@ bb0(%0 : $Trivial): %alloc = alloc_stack $@moveOnly Trivial %1 = copyable_to_moveonlywrapper [owned] %0 : $Trivial %1a = begin_borrow %1 : $@moveOnly Trivial - store_borrow %1a to %alloc : $*@moveOnly Trivial - %2 = load [copy] %alloc : $*@moveOnly Trivial + %sb = store_borrow %1a to %alloc : $*@moveOnly Trivial + %2 = load [copy] %sb : $*@moveOnly Trivial %2a = begin_borrow %2 : $@moveOnly Trivial %3 = moveonlywrapper_to_copyable [guaranteed] %2a : $@moveOnly Trivial apply %f(%3) : $@convention(thin) (Trivial) -> () end_borrow %2a : $@moveOnly Trivial destroy_value %2 : $@moveOnly Trivial - %4 = load_borrow %alloc : $*@moveOnly Trivial + %4 = load_borrow %sb : $*@moveOnly Trivial %5 = moveonlywrapper_to_copyable [guaranteed] %4 : $@moveOnly Trivial apply %f(%5) : $@convention(thin) (Trivial) -> () end_borrow %4 : $@moveOnly Trivial + end_borrow %sb : $*@moveOnly Trivial end_borrow %1a : $@moveOnly Trivial destroy_value %1 : $@moveOnly Trivial dealloc_stack %alloc : $*@moveOnly Trivial @@ -418,18 +419,19 @@ bb0(%0 : @guaranteed $Klass): %1aa = copy_value %0 : $Klass %1 = copyable_to_moveonlywrapper [owned] %1aa : $Klass %1a = begin_borrow %1 : $@moveOnly Klass - store_borrow %1a to %alloc : $*@moveOnly Klass - %2 = load [copy] %alloc : $*@moveOnly Klass + %sb = store_borrow %1a to %alloc : $*@moveOnly Klass + %2 = load [copy] %sb : $*@moveOnly Klass %2a = begin_borrow %2 : $@moveOnly Klass %3 = moveonlywrapper_to_copyable [guaranteed] %2a : $@moveOnly Klass apply %f(%3) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %2a : $@moveOnly Klass destroy_value %2 : $@moveOnly Klass - %4 = load_borrow %alloc : $*@moveOnly Klass + %4 = load_borrow %sb : $*@moveOnly Klass %5 = moveonlywrapper_to_copyable [guaranteed] %4 : $@moveOnly Klass apply %f(%5) : $@convention(thin) (@guaranteed Klass) -> () end_borrow %4 : $@moveOnly Klass + end_borrow %sb : $*@moveOnly Klass end_borrow %1a : $@moveOnly Klass destroy_value %1 : $@moveOnly Klass diff --git a/test/SILOptimizer/ownership_model_eliminator.sil b/test/SILOptimizer/ownership_model_eliminator.sil index ff3a59668cdb9..ed8150350bf1d 100644 --- a/test/SILOptimizer/ownership_model_eliminator.sil +++ b/test/SILOptimizer/ownership_model_eliminator.sil @@ -112,7 +112,8 @@ bb0(%0 : @owned $Builtin.NativeObject): end_borrow %1 : $Builtin.NativeObject %2 = alloc_stack $Builtin.NativeObject %3 = begin_borrow %0 : $Builtin.NativeObject - store_borrow %3 to %2 : $*Builtin.NativeObject + %4 = store_borrow %3 to %2 : $*Builtin.NativeObject + end_borrow %4 : $*Builtin.NativeObject end_borrow %3 : $Builtin.NativeObject dealloc_stack %2 : $*Builtin.NativeObject destroy_value %0 : $Builtin.NativeObject @@ -375,7 +376,8 @@ bb0(%0 : @guaranteed $Builtin.NativeObject): %result = store_borrow %0 to %1 : $*Builtin.NativeObject %f = function_ref @use_native_object_inguaranteed : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () apply %f(%result) : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () + end_borrow %result : $*Builtin.NativeObject dealloc_stack %1 : $*Builtin.NativeObject %9999 = tuple() return %9999 : $() -} \ No newline at end of file +} diff --git a/test/SILOptimizer/specialize_ossa.sil b/test/SILOptimizer/specialize_ossa.sil index 613c7aa859ea4..7a3b9dd004be7 100644 --- a/test/SILOptimizer/specialize_ossa.sil +++ b/test/SILOptimizer/specialize_ossa.sil @@ -977,8 +977,8 @@ bb3: dealloc_stack %0a : $*Builtin.Int32 %0b = alloc_stack $Builtin.NativeObject - store_borrow %1 to %0b : $*Builtin.NativeObject - try_apply %f(%0b) : $@convention(thin) (@in_guaranteed T) -> @error Error, normal bb4, error bb5 + %sb1 = store_borrow %1 to %0b : $*Builtin.NativeObject + try_apply %f(%sb1) : $@convention(thin) (@in_guaranteed T) -> @error Error, normal bb4, error bb5 bb4(%result2 : $()): br bb6 @@ -988,13 +988,14 @@ bb5(%e2 : @owned $Error): br bb6 bb6: + end_borrow %sb1 : $*Builtin.NativeObject dealloc_stack %0b : $*Builtin.NativeObject %0c = alloc_stack $Builtin.NativeObject - store_borrow %1 to %0c : $*Builtin.NativeObject + %sb2 = store_borrow %1 to %0c : $*Builtin.NativeObject %outParam = alloc_stack $Builtin.NativeObject %f2 = function_ref @generic_try_apply_callee_out_param : $@convention(thin) (@in_guaranteed T) -> (@out T, @error Error) - try_apply %f2(%outParam, %0c) : $@convention(thin) (@in_guaranteed T) -> (@out T, @error Error), normal bb7, error bb8 + try_apply %f2(%outParam, %sb2) : $@convention(thin) (@in_guaranteed T) -> (@out T, @error Error), normal bb7, error bb8 bb7(%result3 : $()): destroy_addr %outParam : $*Builtin.NativeObject @@ -1005,6 +1006,7 @@ bb8(%error4 : @owned $Error): br bb9 bb9: + end_borrow %sb2 : $*Builtin.NativeObject dealloc_stack %outParam : $*Builtin.NativeObject dealloc_stack %0c : $*Builtin.NativeObject %9999 = tuple() @@ -1030,13 +1032,15 @@ bb2(%e : @owned $Error): bb3: dealloc_stack %0a : $*Builtin.Int32 %0b = alloc_stack $Builtin.NativeObject - store_borrow %1 to %0b : $*Builtin.NativeObject - try_apply %f(%0b) : $@convention(thin) (@in_guaranteed T) -> @error Error, normal bb4, error bb5 + %sb = store_borrow %1 to %0b : $*Builtin.NativeObject + try_apply %f(%sb) : $@convention(thin) (@in_guaranteed T) -> @error Error, normal bb4, error bb5 bb4(%result2 : $()): + end_borrow %sb : $*Builtin.NativeObject br bb6 bb5(%e2 : @owned $Error): + end_borrow %sb : $*Builtin.NativeObject dealloc_stack %0b : $*Builtin.NativeObject br bbError(%e2 : $Error) @@ -1084,8 +1088,8 @@ sil [ossa] @test_try_apply_loadable : $@convention(thin) (@inout Klass, @guarant bb0(%0 : $*Klass, %1 : @guaranteed $Klass): %f = function_ref @generic_try_apply_callee_loadable_1 : $@convention(thin) (@inout T, @in_guaranteed T) -> @error Error %1b = alloc_stack $Klass - store_borrow %1 to %1b : $*Klass - try_apply %f(%0, %1b) : $@convention(thin) (@inout T, @in_guaranteed T) -> @error Error, normal bb4, error bb5 + %sb = store_borrow %1 to %1b : $*Klass + try_apply %f(%0, %sb) : $@convention(thin) (@inout T, @in_guaranteed T) -> @error Error, normal bb4, error bb5 bb4(%result2 : $()): br bb6 @@ -1095,6 +1099,7 @@ bb5(%e2 : @owned $Error): br bb6 bb6: + end_borrow %sb : $*Klass dealloc_stack %1b : $*Klass %9999 = tuple() return %9999 : $() From 5244e6f3d534b9d5c0db5c7aa32da033bb78296d Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Thu, 11 Aug 2022 02:01:10 -0700 Subject: [PATCH 141/491] Improve verification for store_borrow Add ScopedAddressOperand and ScopedAddressValue abstraction utilities Introduce verification for store_borrow to validate its uses are correctly enclosed in their scope. Include end_borrow/end_access as implicit uses while validating a borrow introducer Add flow sensitive verifier rule for store_borrow/end_borrow pair Make sure store_borrow is always to an alloc_stack Make sure uses to store borrow location are via its return address only --- include/swift/SIL/ScopedAddressUtils.h | 105 +++++++ lib/SIL/Utils/CMakeLists.txt | 1 + lib/SIL/Utils/OwnershipUtils.cpp | 1 + lib/SIL/Utils/ScopedAddressUtils.cpp | 172 ++++++++++++ lib/SIL/Verifier/MemoryLifetimeVerifier.cpp | 8 +- lib/SIL/Verifier/SILOwnershipVerifier.cpp | 9 + lib/SIL/Verifier/SILVerifier.cpp | 58 +++- .../SIL/OwnershipVerifier/borrow_validate.sil | 40 +++ test/SIL/memory_lifetime_failures.sil | 50 +--- test/SIL/store_borrow_verify_errors.sil | 261 ++++++++++++++++++ .../{SILOptimizer => SIL}/verifier_reject.sil | 0 11 files changed, 661 insertions(+), 44 deletions(-) create mode 100644 include/swift/SIL/ScopedAddressUtils.h create mode 100644 lib/SIL/Utils/ScopedAddressUtils.cpp create mode 100644 test/SIL/store_borrow_verify_errors.sil rename test/{SILOptimizer => SIL}/verifier_reject.sil (100%) diff --git a/include/swift/SIL/ScopedAddressUtils.h b/include/swift/SIL/ScopedAddressUtils.h new file mode 100644 index 0000000000000..19af91a3a72ef --- /dev/null +++ b/include/swift/SIL/ScopedAddressUtils.h @@ -0,0 +1,105 @@ +//===--- ScopedAddressUtils.h ---------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 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 +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_SIL_SCOPEDADDRESSUTILS_H +#define SWIFT_SIL_SCOPEDADDRESSUTILS_H + +#include "swift/Basic/Debug.h" +#include "swift/Basic/LLVM.h" +#include "swift/SIL/PrunedLiveness.h" +#include "swift/SIL/SILBasicBlock.h" +#include "swift/SIL/SILInstruction.h" +#include "swift/SIL/SILValue.h" + +namespace swift { + +class ScopedAddressValueKind { +public: + enum Kind : uint8_t { + Invalid = 0, + StoreBorrow, + BeginAccess, + }; + +private: + Kind value; + +public: + static ScopedAddressValueKind get(SILValue value) { + switch (value->getKind()) { + default: + return Kind::Invalid; + case ValueKind::StoreBorrowInst: + return Kind::StoreBorrow; + case ValueKind::BeginAccessInst: + return Kind::BeginAccess; + } + } + + ScopedAddressValueKind(Kind newValue) : value(newValue) {} + + operator Kind() const { return value; } + + void print(llvm::raw_ostream &os) const; + SWIFT_DEBUG_DUMP { print(llvm::dbgs()); } +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &os, + ScopedAddressValueKind kind); + +struct ScopedAddressValue { + SILValue value; + ScopedAddressValueKind kind = ScopedAddressValueKind::Invalid; + + ScopedAddressValue() = default; + + explicit ScopedAddressValue(SILValue value) { + kind = ScopedAddressValueKind::get(value); + if (kind) + this->value = value; + } + + operator bool() const { + return kind != ScopedAddressValueKind::Invalid && value; + } + + void print(llvm::raw_ostream &os) const; + SWIFT_DEBUG_DUMP { print(llvm::dbgs()); } + + // Helpers to allow a ScopedAddressValue to easily be used as a SILValue + // programatically. + SILValue operator->() { return value; } + SILValue operator->() const { return value; } + SILValue operator*() { return value; } + SILValue operator*() const { return value; } + + /// Returns true if \p op is a scope edning use of the scoped address value. + bool isScopeEndingUse(Operand *op) const; + /// Pass all scope ending instructions to the visitor. + bool visitScopeEndingUses(function_ref visitor) const; + /// Returns false, if liveness cannot be computed due to pointer escape or + /// unkown address use. Add this scope's live blocks into the PrunedLiveness + /// result. + bool computeLiveness(PrunedLiveness &liveness) const; +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &os, + const ScopedAddressValue &value); + +/// Returns true if there are other store_borrows enclosed within a store_borrow +/// \p sbi's scope +bool hasOtherStoreBorrowsInLifetime(StoreBorrowInst *sbi, + PrunedLiveness *liveness, + DeadEndBlocks *deadEndBlocks); +} // namespace swift + +#endif diff --git a/lib/SIL/Utils/CMakeLists.txt b/lib/SIL/Utils/CMakeLists.txt index da9d2ae976102..3c837728b38fb 100644 --- a/lib/SIL/Utils/CMakeLists.txt +++ b/lib/SIL/Utils/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(swiftSIL PRIVATE PrettyStackTrace.cpp Projection.cpp PrunedLiveness.cpp + ScopedAddressUtils.cpp SILBridging.cpp SILInstructionWorklist.cpp SILRemarkStreamer.cpp diff --git a/lib/SIL/Utils/OwnershipUtils.cpp b/lib/SIL/Utils/OwnershipUtils.cpp index a617a668bdc64..b29aab8fcfd92 100644 --- a/lib/SIL/Utils/OwnershipUtils.cpp +++ b/lib/SIL/Utils/OwnershipUtils.cpp @@ -20,6 +20,7 @@ #include "swift/SIL/Projection.h" #include "swift/SIL/PrunedLiveness.h" #include "swift/SIL/SILArgument.h" +#include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILInstruction.h" using namespace swift; diff --git a/lib/SIL/Utils/ScopedAddressUtils.cpp b/lib/SIL/Utils/ScopedAddressUtils.cpp new file mode 100644 index 0000000000000..4f749814c2073 --- /dev/null +++ b/lib/SIL/Utils/ScopedAddressUtils.cpp @@ -0,0 +1,172 @@ +//===--- ScopedAddressUtils.cpp -------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 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 +// +//===----------------------------------------------------------------------===// + +#include "swift/SIL/ScopedAddressUtils.h" +#include "swift/SIL/OwnershipUtils.h" +#include "swift/SIL/PrunedLiveness.h" +#include "swift/SIL/SILArgument.h" +#include "swift/SIL/SILBuilder.h" +#include "swift/SIL/SILInstruction.h" + +using namespace swift; + +void ScopedAddressValueKind::print(llvm::raw_ostream &os) const { + switch (value) { + case ScopedAddressValueKind::Invalid: + llvm_unreachable("Using invalid case?!"); + case ScopedAddressValueKind::StoreBorrow: + os << "StoreBorrow"; + return; + case ScopedAddressValueKind::BeginAccess: + os << "BeginAccess"; + return; + } + llvm_unreachable("Covered switch isn't covered?!"); +} + +llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os, + ScopedAddressValueKind kind) { + kind.print(os); + return os; +} + +bool ScopedAddressValue::isScopeEndingUse(Operand *op) const { + switch (kind) { + case ScopedAddressValueKind::Invalid: + llvm_unreachable("Using invalid case?!"); + case ScopedAddressValueKind::StoreBorrow: { + if (auto *endBorrow = dyn_cast(op->getUser())) { + return endBorrow->getOperand() == value; + } + return false; + } + case ScopedAddressValueKind::BeginAccess: { + if (auto *endAccess = dyn_cast(op->getUser())) { + return endAccess->getOperand() == value; + } + return false; + } + } +} + +bool ScopedAddressValue::visitScopeEndingUses( + function_ref visitor) const { + switch (kind) { + case ScopedAddressValueKind::Invalid: + llvm_unreachable("Using invalid case?!"); + case ScopedAddressValueKind::StoreBorrow: { + for (auto *use : value->getUses()) { + if (isa(use->getUser())) { + if (!visitor(use)) + return false; + } + } + return true; + } + case ScopedAddressValueKind::BeginAccess: { + for (auto *use : value->getUses()) { + if (isa(use->getUser())) { + if (!visitor(use)) + return false; + } + } + return true; + } + } +} + +bool ScopedAddressValue::computeLiveness(PrunedLiveness &liveness) const { + auto addressKind = findTransitiveUsesForAddress(value); + if (addressKind != AddressUseKind::NonEscaping) { + return false; + } + + liveness.initializeDefBlock(value->getParentBlock()); + visitScopeEndingUses([&](Operand *endOp) { + liveness.updateForUse(endOp->getUser(), /* isLifetimeEnding */ true); + return true; + }); + return true; +} + +void ScopedAddressValue::createScopeEnd(SILBasicBlock::iterator insertPt, + SILLocation loc) const { + switch (kind) { + case ScopedAddressValueKind::StoreBorrow: { + SILBuilderWithScope(insertPt).createEndBorrow(loc, value); + return; + } + case ScopedAddressValueKind::BeginAccess: { + SILBuilderWithScope(insertPt).createEndAccess(loc, value, false); + return; + } + case ScopedAddressValueKind::Invalid: + llvm_unreachable("Using invalid case?!"); + } +} + +void ScopedAddressValue::endScopeAtLivenessBoundary( + PrunedLiveness *liveness) const { + // If no users exist, create scope ending instruction immediately after the + // scoped address value. + if (liveness->empty()) { + createScopeEnd(value->getNextInstruction()->getIterator(), + RegularLocation::getAutoGeneratedLocation()); + return; + } + + PrunedLivenessBoundary scopedAddressBoundary; + scopedAddressBoundary.compute(*liveness); + // Go over the boundary and create scope ending instructions. + scopedAddressBoundary.visitInsertionPoints( + [&](SILBasicBlock::iterator insertPt) { + createScopeEnd(insertPt, RegularLocation::getAutoGeneratedLocation()); + }); +} + +bool swift::hasOtherStoreBorrowsInLifetime(StoreBorrowInst *storeBorrow, + PrunedLiveness *liveness, + DeadEndBlocks *deadEndBlocks) { + SmallVector otherStoreBorrows; + // Collect all other store_borrows to the destination of \p storeBorrow + for (auto *destUse : storeBorrow->getDest()->getUses()) { + if (auto *user = dyn_cast(destUse->getUser())) { + if (user == storeBorrow) { + continue; + } + otherStoreBorrows.push_back(user); + } + } + + for (auto *otherStoreBorrow : otherStoreBorrows) { + // Return true, if otherStoreBorrow was in \p storeBorrow's scope + if (liveness->isWithinBoundaryOfDef(otherStoreBorrow, storeBorrow)) { + return true; + } + } + return false; +} + +void ScopedAddressValue::print(llvm::raw_ostream &os) const { + os << "ScopedAddressIntroducingValue:\n" + "Kind: " + << kind + << "\n" + "Value: " + << value; +} + +llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os, + const ScopedAddressValue &value) { + value.print(os); + return os; +} diff --git a/lib/SIL/Verifier/MemoryLifetimeVerifier.cpp b/lib/SIL/Verifier/MemoryLifetimeVerifier.cpp index 50c0405061a25..b7e8dc029fce0 100644 --- a/lib/SIL/Verifier/MemoryLifetimeVerifier.cpp +++ b/lib/SIL/Verifier/MemoryLifetimeVerifier.cpp @@ -274,11 +274,11 @@ void MemoryLifetimeVerifier::requireBitsSet(const Bits &bits, SILValue addr, } } -void MemoryLifetimeVerifier::requireNoStoreBorrowLocation(SILValue addr, - SILInstruction *where) { - if (isStoreBorrowLocation(addr)) { +void MemoryLifetimeVerifier::requireNoStoreBorrowLocation( + SILValue addr, SILInstruction *where) { + if (isa(addr)) { reportError("store-borrow location cannot be written", - locations.getLocation(addr)->selfAndParents.find_first(), where); + locations.getLocationIdx(addr), where); } } diff --git a/lib/SIL/Verifier/SILOwnershipVerifier.cpp b/lib/SIL/Verifier/SILOwnershipVerifier.cpp index 33f5fa399ac4a..6f5eb5e9f135d 100644 --- a/lib/SIL/Verifier/SILOwnershipVerifier.cpp +++ b/lib/SIL/Verifier/SILOwnershipVerifier.cpp @@ -38,6 +38,7 @@ #include "swift/SIL/SILModule.h" #include "swift/SIL/SILVTable.h" #include "swift/SIL/SILVisitor.h" +#include "swift/SIL/ScopedAddressUtils.h" #include "swift/SIL/TypeLowering.h" #include "llvm/ADT/DenseSet.h" @@ -363,6 +364,14 @@ bool SILValueOwnershipChecker::gatherUsers( reborrowVerifier.verifyReborrows(scopedOperand, value); } + if (auto *svi = dyn_cast(op->getUser())) { + if (auto scopedAddress = ScopedAddressValue(svi)) { + scopedAddress.visitScopeEndingUses([&](Operand *endOp) { + nonLifetimeEndingUsers.push_back(endOp); + return true; + }); + } + } // Next see if our use is an interior pointer operand. If we have an // interior pointer, we need to add all of its address uses as "implicit // regular users" of our consumed value. diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 70aa7b4281f7d..b566205f7c382 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -35,6 +35,7 @@ #include "swift/SIL/OwnershipUtils.h" #include "swift/SIL/PostOrder.h" #include "swift/SIL/PrettyStackTrace.h" +#include "swift/SIL/PrunedLiveness.h" #include "swift/SIL/SILDebugScope.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" @@ -42,6 +43,7 @@ #include "swift/SIL/SILVTable.h" #include "swift/SIL/SILVTableVisitor.h" #include "swift/SIL/SILVisitor.h" +#include "swift/SIL/ScopedAddressUtils.h" #include "swift/SIL/TypeLowering.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/PostOrderIterator.h" @@ -2291,6 +2293,29 @@ class SILVerifier : public SILVerifierBase { } } + bool checkScopedAddressUses(ScopedAddressValue scopedAddress, + PrunedLiveness *scopedAddressLiveness, + DeadEndBlocks *deadEndBlocks) { + SmallVector uses; + findTransitiveUsesForAddress(scopedAddress.value, &uses); + + // Check if the collected uses are well-scoped. + for (auto *use : uses) { + auto *user = use->getUser(); + if (deadEndBlocks->isDeadEnd(user->getParent())) { + continue; + } + if (scopedAddress.isScopeEndingUse(use)) { + continue; + } + if (!scopedAddressLiveness->isWithinBoundary(user)) { + llvm::errs() << "User found outside scope: " << *user; + return false; + } + } + return true; + } + void checkBeginAccessInst(BeginAccessInst *BAI) { requireSameType(BAI->getType(), BAI->getSource()->getType(), "result must be same type as operand"); @@ -2443,6 +2468,8 @@ class SILVerifier : public SILVerifierBase { "Can't store a non loadable type"); require(SI->getDest()->getType().isAddress(), "Must store to an address dest"); + require(isa(SI->getDest()), + "store_borrow destination should be alloc_stack"); requireSameType(SI->getDest()->getType().getObjectType(), SI->getSrc()->getType(), "Store operand type and dest type mismatch"); @@ -2450,6 +2477,27 @@ class SILVerifier : public SILVerifierBase { // Note: This is the current implementation and the design is not final. require(isa(SI->getDest()), "store_borrow destination can only be an alloc_stack"); + + PrunedLiveness scopedAddressLiveness; + ScopedAddressValue scopedAddress(SI); + bool success = scopedAddress.computeLiveness(scopedAddressLiveness); + + require(!success || checkScopedAddressUses( + scopedAddress, &scopedAddressLiveness, &DEBlocks), + "Ill formed store_borrow scope"); + + require(!success || !hasOtherStoreBorrowsInLifetime( + SI, &scopedAddressLiveness, &DEBlocks), + "A store_borrow cannot be nested within another " + "store_borrow to its destination"); + + for (auto *use : SI->getDest()->getUses()) { + auto *user = use->getUser(); + require( + user == SI || isa(user) || + isa(user), + "A store_borrow destination can be used only via its return address"); + } } void checkAssignInst(AssignInst *AI) { @@ -5563,7 +5611,8 @@ class SILVerifier : public SILVerifierBase { } state.Stack.pop_back(); - } else if (isa(i) || isa(i)) { + } else if (isa(i) || isa(i) || + isa(i)) { bool notAlreadyPresent = state.ActiveOps.insert(&i).second; require(notAlreadyPresent, "operation was not ended before re-beginning it"); @@ -5574,6 +5623,13 @@ class SILVerifier : public SILVerifierBase { bool present = state.ActiveOps.erase(beginOp); require(present, "operation has already been ended"); } + } else if (auto *endBorrow = dyn_cast(&i)) { + if (isa(endBorrow->getOperand())) { + if (auto beginOp = i.getOperand(0)->getDefiningInstruction()) { + bool present = state.ActiveOps.erase(beginOp); + require(present, "operation has already been ended"); + } + } } else if (auto gaci = dyn_cast(&i)) { require(!state.GotAsyncContinuation, "get_async_continuation while unawaited continuation is already active"); diff --git a/test/SIL/OwnershipVerifier/borrow_validate.sil b/test/SIL/OwnershipVerifier/borrow_validate.sil index 0ed753c5bac87..b3ce6f8937cc0 100644 --- a/test/SIL/OwnershipVerifier/borrow_validate.sil +++ b/test/SIL/OwnershipVerifier/borrow_validate.sil @@ -768,3 +768,43 @@ bb3(%borrowphi : @guaranteed $Klass): %99 = tuple () return %99 : $() } + +// CHECK: Error#: 0. Begin Error in Function: 'test_scope_end_order1' +// CHECK: Found outside of lifetime use?! +// CHECK: Value: %3 = begin_borrow %1 : $Klass // users: %5, %4 +// CHECK: Consuming User: end_borrow %3 : $Klass // id: %5 +// CHECK: Non Consuming User: end_borrow %4 : $*Klass // id: %6 +// CHECK: Block: bb0 +// CHECK: Error#: 0. End Error in Function: 'test_scope_end_order1' +sil [ossa] @test_scope_end_order1 : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %copy = copy_value %0 : $Klass + %stk = alloc_stack $Klass + %borrow = begin_borrow %copy : $Klass + %ra = store_borrow %borrow to %stk : $*Klass + end_borrow %borrow : $Klass + end_borrow %ra : $*Klass + destroy_value %copy : $Klass + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + +// CHECK: Error#: 0. Begin Error in Function: 'test_scope_end_order2' +// CHECK: Found outside of lifetime use?! +// CHECK: Value: %2 = load_borrow %0 : $*Klass // users: %4, %3 +// CHECK: Consuming User: end_borrow %2 : $Klass // id: %4 +// CHECK: Non Consuming User: end_borrow %3 : $*Klass // id: %5 +// CHECK: Block: bb0 +// CHECK: Error#: 0. End Error in Function: 'test_scope_end_order2' +sil [ossa] @test_scope_end_order2 : $@convention(thin) (@in_guaranteed Klass) -> () { +bb0(%0 : $*Klass): + %stk = alloc_stack $Klass + %borrow = load_borrow %0 : $*Klass + %ra = store_borrow %borrow to %stk : $*Klass + end_borrow %borrow : $Klass + end_borrow %ra : $*Klass + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} diff --git a/test/SIL/memory_lifetime_failures.sil b/test/SIL/memory_lifetime_failures.sil index ce868ce49c910..0733f6668ff62 100644 --- a/test/SIL/memory_lifetime_failures.sil +++ b/test/SIL/memory_lifetime_failures.sil @@ -28,6 +28,10 @@ struct Mixed { var i: Int } +sil @use_owned : $@convention(thin) (@owned T) -> () +sil @use_guaranteed : $@convention(thin) (@guaranteed T) -> () +sil @get_owned : $@convention(thin) () -> @owned T + // CHECK: SIL memory lifetime failure in @test_simple: indirect argument is not alive at function return sil [ossa] @test_simple : $@convention(thin) (@inout T) -> @owned T { bb0(%0 : $*T): @@ -276,8 +280,8 @@ sil [ossa] @test_store_borrow_destroy : $@convention(thin) (@guaranteed T) -> () bb0(%0 : @guaranteed $T): %s = alloc_stack $T %sb = store_borrow %0 to %s : $*T + destroy_addr %sb : $*T end_borrow %sb : $*T - destroy_addr %s : $*T dealloc_stack %s : $*T %res = tuple () return %res : $() @@ -303,8 +307,8 @@ sil [ossa] @test_store_borrow_store : $@convention(thin) (@guaranteed T, @owned bb0(%0 : @guaranteed $T, %1 : @owned $T): %s = alloc_stack $T %sb = store_borrow %0 to %s : $*T + store %1 to [assign] %sb : $*T end_borrow %sb : $*T - store %1 to [assign] %s : $*T dealloc_stack %s : $*T %res = tuple () return %res : $() @@ -315,8 +319,8 @@ sil [ossa] @test_store_borrow_load : $@convention(thin) (@guaranteed T) -> @owne bb0(%0 : @guaranteed $T): %s = alloc_stack $T %sb = store_borrow %0 to %s : $*T + %res = load [take] %sb : $*T end_borrow %sb : $*T - %res = load [take] %s : $*T dealloc_stack %s : $*T return %res : $T } @@ -326,8 +330,8 @@ sil [ossa] @test_store_borrow_copy_src : $@convention(thin) (@guaranteed T) -> @ bb0(%0 : $*T, %1 : @guaranteed $T): %s = alloc_stack $T %sb = store_borrow %1 to %s : $*T + copy_addr [take] %sb to [initialization] %0 : $*T end_borrow %sb : $*T - copy_addr [take] %s to [initialization] %0 : $*T dealloc_stack %s : $*T %res = tuple () return %res : $() @@ -338,8 +342,8 @@ sil [ossa] @test_store_borrow_copy_dst : $@convention(thin) (@in_guaranteed T, @ bb0(%0 : $*T, %1 : @guaranteed $T): %s = alloc_stack $T %sb = store_borrow %1 to %s : $*T + copy_addr %0 to %sb : $*T end_borrow %sb : $*T - copy_addr %0 to %s : $*T dealloc_stack %s : $*T %res = tuple () return %res : $() @@ -350,8 +354,8 @@ sil [ossa] @test_store_borrow_init_enum : $@convention(thin) (@guaranteed Option bb0(%0 : @guaranteed $Optional): %s = alloc_stack $Optional %sb = store_borrow %0 to %s : $*Optional + %ie = init_enum_data_addr %sb : $*Optional, #Optional.some!enumelt end_borrow %sb : $*Optional - %ie = init_enum_data_addr %s : $*Optional, #Optional.some!enumelt dealloc_stack %s : $*Optional %res = tuple () return %res : $() @@ -362,45 +366,13 @@ sil [ossa] @test_store_borrow_take_enum : $@convention(thin) (@guaranteed Option bb0(%0 : @guaranteed $Optional): %s = alloc_stack $Optional %sb = store_borrow %0 to %s : $*Optional - %ue = unchecked_take_enum_data_addr %s : $*Optional, #Optional.some!enumelt + %ue = unchecked_take_enum_data_addr %sb : $*Optional, #Optional.some!enumelt end_borrow %sb : $*Optional dealloc_stack %s : $*Optional %res = tuple () return %res : $() } -// CHECK: SIL memory lifetime failure in @test_store_borrow_single_block: store-borrow location cannot be written -sil [ossa] @test_store_borrow_single_block : $@convention(thin) (@guaranteed T) -> () { -bb0(%0 : @guaranteed $T): - %stk = alloc_stack $T - %copy = copy_value %0 : $T - store %copy to [init] %stk : $*T - %ld = load [take] %stk : $*T - destroy_value %ld : $T - %sb = store_borrow %0 to %stk : $*T - end_borrow %sb : $*T - dealloc_stack %stk : $*T - %8 = tuple () - return %8 : $() -} - -// CHECK: SIL memory lifetime failure in @test_store_borrow_multi_block: store-borrow location cannot be written -sil [ossa] @test_store_borrow_multi_block : $@convention(thin) (@guaranteed T) -> () { -bb0(%0 : @guaranteed $T): - %stk = alloc_stack $T - %copy = copy_value %0 : $T - store %copy to [init] %stk : $*T - %ld = load [take] %stk : $*T - destroy_value %ld : $T - br bb1 -bb1: - %sb = store_borrow %0 to %stk : $*T - end_borrow %sb : $*T - dealloc_stack %stk : $*T - %8 = tuple () - return %8 : $() -} - // CHECK: SIL memory lifetime failure in @test_cast_br_take_always: memory is not initialized, but should be sil [ossa] @test_cast_br_take_always : $@convention(thin) (@in U) -> () { bb0(%0 : $*U): diff --git a/test/SIL/store_borrow_verify_errors.sil b/test/SIL/store_borrow_verify_errors.sil new file mode 100644 index 0000000000000..bf75ca78d0bd6 --- /dev/null +++ b/test/SIL/store_borrow_verify_errors.sil @@ -0,0 +1,261 @@ +// RUN: %target-sil-opt -verify-continue-on-failure -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s + +import Builtin + +class Klass {} + +struct NonTrivialStruct { + var val: Klass +} + +sil @use_owned : $@convention(thin) (@owned Klass) -> () +sil @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () +sil @get_owned : $@convention(thin) () -> @owned Klass + +// CHECK: Begin Error in function test_missing_end_borrow_single +// CHECK: SIL verification failed: return with operations still active: state.ActiveOps.empty() +// CHECK: Verifying instruction: +// CHECK: %4 = tuple () // user: %5 +// CHECK: -> return %4 : $() // id: %5 +// CHECK: End Error in function test_missing_end_borrow_single +sil [ossa] @test_missing_end_borrow_single : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %ra = store_borrow %0 to %stk : $*Klass + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + +// CHECK: Begin Error in function test_missing_end_borrow +// CHECK: SIL verification failed: return with operations still active: state.ActiveOps.empty() +// CHECK: Verifying instruction: +// CHECK: %8 = tuple () // user: %9 +// CHECK: -> return %8 : $() // id: %9 +// CHECK: End Error in function test_missing_end_borrow +sil [ossa] @test_missing_end_borrow : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %ra = store_borrow %0 to %stk : $*Klass + cond_br undef, bb1, bb2 + +bb1: + end_borrow %ra : $*Klass + br bb3 + +bb2: + br bb3 + +bb3: + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + +// CHECK: Begin Error in function test_missing_end_borrow +// CHECK: SIL verification failed: inconsistent active-operations sets entering basic block: state.ActiveOps == foundState.ActiveOps || isUnreachable() +// CHECK: Verifying instruction: +// CHECK: -> br bb3 // id: %5 +// CHECK: End Error in function test_missing_end_borrow +sil [ossa] @test_missing_end_borrow_dead : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %ra = store_borrow %0 to %stk : $*Klass + cond_br undef, bb1, bb2 + +bb1: + end_borrow %ra : $*Klass + br bb3 + +bb2: + unreachable + +bb3: + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + +// CHECK: Begin Error in function test_load_borrow_from_stk +// CHECK: SIL verification failed: A store_borrow destination can be used only via its return address: user == SI || isa(user) || isa(user) +// CHECK: Verifying instruction: +// CHECK: %2 = alloc_stack $Klass // users: %10, %7, %4 +// CHECK: %3 = begin_borrow %1 : $Klass // users: %6, %4 +// CHECK: -> %4 = store_borrow %3 to %2 : $*Klass // user: %5 +// CHECK: end_borrow %4 : $*Klass // id: %5 +// CHECK: End Error in function test_load_borrow_from_stk +sil [ossa] @test_load_borrow_from_stk : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %copy = copy_value %0 : $Klass + %stk = alloc_stack $Klass + %borrow = begin_borrow %copy : $Klass + %ra = store_borrow %borrow to %stk : $*Klass + end_borrow %ra : $*Klass + end_borrow %borrow : $Klass + %ld = load_borrow %stk : $*Klass + end_borrow %ld : $Klass + destroy_value %copy : $Klass + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + +// CHECK: User found outside scope: end_borrow %3 : $Klass // id: %5 +// CHECK: Begin Error in function test_load_borrow_outside_scope +// CHECK: SIL verification failed: Ill formed store_borrow scope +// CHECK: Verifying instruction: +// CHECK: %0 = argument of bb0 : $Klass // user: %2 +// CHECK: %1 = alloc_stack $Klass // users: %6, %2 +// CHECK: -> %2 = store_borrow %0 to %1 : $*Klass // users: %4, %3 +// CHECK: %3 = load_borrow %2 : $*Klass // user: %5 +// CHECK: end_borrow %2 : $*Klass // id: %4 +// CHECK: End Error in function test_load_borrow_outside_scope +sil [ossa] @test_load_borrow_outside_scope : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %ra = store_borrow %0 to %stk : $*Klass + %ld = load_borrow %ra : $*Klass + end_borrow %ra : $*Klass + end_borrow %ld : $Klass + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + +// CHECK: Begin Error in function test_load_borrow_store_borrow_nested +// CHECK: SIL verification failed: A store_borrow cannot be nested within another store_borrow to its destination +// CHECK: Verifying instruction: +// CHECK: %0 = argument of bb0 : $Klass // user: %2 +// CHECK: %1 = alloc_stack $Klass // users: %8, %4, %2 +// CHECK: -> %2 = store_borrow %0 to %1 : $*Klass // users: %7, %3 +// CHECK: %3 = load_borrow %2 : $*Klass // users: %6, %4 +// CHECK: end_borrow %2 : $*Klass // id: %7 +// CHECK: End Error in function test_load_borrow_store_borrow_nested +sil [ossa] @test_load_borrow_store_borrow_nested : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %ra1 = store_borrow %0 to %stk : $*Klass + %ld = load_borrow %ra1 : $*Klass + %ra2 = store_borrow %ld to %stk : $*Klass + end_borrow %ra2 : $*Klass + end_borrow %ld : $Klass + end_borrow %ra1 : $*Klass + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + +// CHECK: Begin Error in function test_store_borrow_single_block +// CHECK: SIL verification failed: A store_borrow destination can be used only via its return address: user == SI || isa(user) || isa(user) +// CHECK: Verifying instruction: +// CHECK: %0 = argument of bb0 : $Klass // users: %6, %2 +// CHECK: %1 = alloc_stack $Klass // users: %8, %6, %4, %3 +// CHECK: -> %6 = store_borrow %0 to %1 : $*Klass // user: %7 +// CHECK: end_borrow %6 : $*Klass // id: %7 +// CHECK: End Error in function test_store_borrow_single_block +sil [ossa] @test_store_borrow_single_block : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %copy = copy_value %0 : $Klass + store %copy to [init] %stk : $*Klass + %ld = load [take] %stk : $*Klass + destroy_value %ld : $Klass + %sb = store_borrow %0 to %stk : $*Klass + end_borrow %sb : $*Klass + dealloc_stack %stk : $*Klass + %8 = tuple () + return %8 : $() +} + +// CHECK: Begin Error in function test_store_borrow_multi_block +// CHECK: SIL verification failed: A store_borrow destination can be used only via its return address: user == SI || isa(user) || isa(user) +// CHECK: Verifying instruction: +// CHECK: %0 = argument of bb0 : $Klass // users: %7, %2 +// CHECK: %1 = alloc_stack $Klass // users: %9, %7, %4, %3 +// CHECK: -> %7 = store_borrow %0 to %1 : $*Klass // user: %8 +// CHECK: end_borrow %7 : $*Klass // id: %8 +// CHECK: End Error in function test_store_borrow_multi_block +sil [ossa] @test_store_borrow_multi_block : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %copy = copy_value %0 : $Klass + store %copy to [init] %stk : $*Klass + %ld = load [take] %stk : $*Klass + destroy_value %ld : $Klass + br bb1 +bb1: + %sb = store_borrow %0 to %stk : $*Klass + end_borrow %sb : $*Klass + dealloc_stack %stk : $*Klass + %8 = tuple () + return %8 : $() +} + +// CHECK: Begin Error in function test_store_borrow_dest +// CHECK: SIL verification failed: store_borrow destination should be alloc_stack: isa(SI->getDest()) +// CHECK: Verifying instruction: +// CHECK: %0 = argument of bb0 : $Klass // user: %3 +// CHECK: %2 = struct_element_addr %1 : $*NonTrivialStruct, #NonTrivialStruct.val // user: %3 +// CHECK: -> %3 = store_borrow %0 to %2 : $*Klass // user: %4 +// CHECK: end_borrow %3 : $*Klass // id: %4 +// CHECK: End Error in function test_store_borrow_dest +sil [ossa] @test_store_borrow_dest : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $NonTrivialStruct + %addr = struct_element_addr %stk : $*NonTrivialStruct, #NonTrivialStruct.val + %ra = store_borrow %0 to %addr : $*Klass + end_borrow %ra : $*Klass + dealloc_stack %stk : $*NonTrivialStruct + %1 = tuple () + return %1 : $() +} + +// CHECK: Begin Error in function test_store_borrow_within_store_borrow1 +// CHECK: SIL verification failed: A store_borrow cannot be nested within another store_borrow to its destination +// CHECK: Verifying instruction: +// CHECK: %0 = argument of bb0 : $Klass // users: %3, %2 +// CHECK: %1 = alloc_stack $Klass // users: %6, %3, %2 +// CHECK: -> %2 = store_borrow %0 to %1 : $*Klass // user: %5 +// CHECK: end_borrow %2 : $*Klass // id: %5 +// CHECK: End Error in function test_store_borrow_within_store_borrow1 +sil [ossa] @test_store_borrow_within_store_borrow1 : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %ra1 = store_borrow %0 to %stk : $*Klass + %ra2 = store_borrow %0 to %stk : $*Klass + end_borrow %ra2 : $*Klass + end_borrow %ra1 : $*Klass + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + +// CHECK: Begin Error in function test_store_borrow_within_store_borrow2 +// CHECK: SIL verification failed: A store_borrow cannot be nested within another store_borrow to its destination +// CHECK: Verifying instruction: +// CHECK: %0 = argument of bb0 : $Klass // users: %3, %2 +// CHECK: %1 = alloc_stack $Klass // users: %9, %3, %2 +// CHECK: -> %2 = store_borrow %0 to %1 : $*Klass // user: %6 +// CHECK: end_borrow %2 : $*Klass // id: %6 +// CHECK: End Error in function test_store_borrow_within_store_borrow2 +sil [ossa] @test_store_borrow_within_store_borrow2 : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack $Klass + %ra1 = store_borrow %0 to %stk : $*Klass + %ra2 = store_borrow %0 to %stk : $*Klass + cond_br undef, bb1, bb2 + +bb1: + end_borrow %ra2 : $*Klass + end_borrow %ra1 : $*Klass + br bb3 + +bb2: + unreachable + +bb3: + dealloc_stack %stk : $*Klass + %1 = tuple () + return %1 : $() +} + diff --git a/test/SILOptimizer/verifier_reject.sil b/test/SIL/verifier_reject.sil similarity index 100% rename from test/SILOptimizer/verifier_reject.sil rename to test/SIL/verifier_reject.sil From c3ef007979de9294bc0e8c76753c1599c100df99 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 29 Jun 2022 12:52:17 -0700 Subject: [PATCH 142/491] Fix store_borrow cloning when we are cloning into a function w/o ownership Map store_borrow return_address with the destination, so that while cloning a store_borrow into a function w/o ownership, users of store_borrow return address can be mapped with the lowered store's destination. --- include/swift/SIL/SILCloner.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 26844459fb52d..f24c00e264f5f 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -1160,12 +1160,10 @@ template void SILCloner::visitStoreBorrowInst(StoreBorrowInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { - // TODO: Eliminate store_borrow result so we can use - // recordClonedInstruction. It is not "technically" necessary, but it is - // better from an invariant perspective. getBuilder().createStore( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), StoreOwnershipQualifier::Unqualified); + mapValue(Inst, getOpValue(Inst->getDest())); return; } From b6cf3cd7a1ba77bf64d3ca3649a7554f75816ac2 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Thu, 7 Jul 2022 11:11:29 -0700 Subject: [PATCH 143/491] Fix store_borrow generation and pattern matching in foreach loop unroll optimization --- .../LoopTransforms/ForEachLoopUnroll.cpp | 35 +++++++++++-------- .../for_each_loop_unroll_test.sil | 8 ++--- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp b/lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp index 16eb4c7d07ec9..b45d757461d2d 100644 --- a/lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp +++ b/lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp @@ -249,7 +249,7 @@ static FixLifetimeInst *isFixLifetimeUseOfArray(SILInstruction *user, AllocStackInst *alloc = dyn_cast(storeUser->getDest()); if (!alloc) return nullptr; - auto fixLifetimeUsers = alloc->getUsersOfType(); + auto fixLifetimeUsers = storeUser->getUsersOfType(); if (fixLifetimeUsers.empty()) return nullptr; auto firstUser = fixLifetimeUsers.begin(); @@ -278,7 +278,7 @@ static TryApplyInst *isForEachUseOfArray(SILInstruction *user, SILValue array) { AllocStackInst *alloc = dyn_cast(storeUser->getDest()); if (!alloc) return nullptr; - auto applyUsers = alloc->getUsersOfType(); + auto applyUsers = storeUser->getUsersOfType(); if (applyUsers.empty()) return nullptr; auto firstUser = applyUsers.begin(); @@ -385,12 +385,11 @@ void ArrayInfo::getLastDestroys( /// not clean up any resulting dead instructions. static void removeForEachCall(TryApplyInst *forEachCall, InstructionDeleter &deleter) { - AllocStackInst *allocStack = - dyn_cast(forEachCall->getArgument(1)); - assert(allocStack); + auto *sbi = cast(forEachCall->getArgument(1)); + auto *asi = cast(sbi->getDest()); // The allocStack will be used in the forEach call and also in a store // instruction and a dealloc_stack instruction. Force delete all of them. - deleter.recursivelyForceDeleteUsersAndFixLifetimes(allocStack); + deleter.recursivelyForceDeleteUsersAndFixLifetimes(asi); } /// Unroll the \c forEachCall on an array, using the information in @@ -502,12 +501,15 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall, // "error" branch of a try_apply. The error block created here will always // jump to the error target of the original forEach. auto errorTargetGenerator = [&](SILBasicBlock *insertionBlock, - SILValue borrowedElem ) { + SILValue borrowedElem, SILValue storeBorrow) { SILBasicBlock *newErrorBB = fun->createBasicBlockBefore(insertionBlock); SILValue argument = newErrorBB->createPhiArgument( errorArgument->getType(), errorArgument->getOwnershipKind()); // Make the errorBB jump to the error target of the original forEach. SILBuilderWithScope builder(newErrorBB, forEachCall); + if (storeBorrow) { + builder.createEndBorrow(forEachLoc, storeBorrow); + } if (borrowedElem) { builder.createEndBorrow(forEachLoc, borrowedElem); } @@ -537,28 +539,33 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall, : forEachCall->getParentBlock(); SILBuilderWithScope unrollBuilder(currentBB, forEachCall); SILValue borrowedElem; + SILValue addr; + if (arrayElementType.isTrivial(*fun)) { unrollBuilder.createStore(forEachLoc, elementCopy, allocStack, StoreOwnershipQualifier::Trivial); + addr = allocStack; } else { // Borrow the elementCopy and store it in the allocStack. Note that the // element's copy is guaranteed to be alive until the array is alive. // Therefore it is okay to use a borrow here. borrowedElem = unrollBuilder.createBeginBorrow(forEachLoc, elementCopy); - unrollBuilder.createStoreBorrow(forEachLoc, borrowedElem, allocStack); - - SILBuilderWithScope(&nextNormalBB->front(), forEachCall) - .createEndBorrow(forEachLoc, borrowedElem); + addr = + unrollBuilder.createStoreBorrow(forEachLoc, borrowedElem, allocStack); + SILBuilderWithScope builder(&nextNormalBB->front(), forEachCall); + builder.createEndBorrow(forEachLoc, addr); + builder.createEndBorrow(forEachLoc, borrowedElem); } SILBasicBlock *errorTarget = - errorTargetGenerator(nextNormalBB, borrowedElem); + errorTargetGenerator(nextNormalBB, borrowedElem, + isa(addr) ? addr : SILValue()); // Note that the substitution map must be empty as we are not supporting // elements of address-only type. All elements in the array are guaranteed // to be loadable. TODO: generalize this to address-only types. unrollBuilder.createTryApply(forEachLoc, forEachBodyClosure, - SubstitutionMap(), allocStack, - nextNormalBB, errorTarget); + SubstitutionMap(), addr, nextNormalBB, + errorTarget); nextNormalBB = currentBB; } diff --git a/test/SILOptimizer/for_each_loop_unroll_test.sil b/test/SILOptimizer/for_each_loop_unroll_test.sil index 2580aa9faf04a..31030a1860676 100644 --- a/test/SILOptimizer/for_each_loop_unroll_test.sil +++ b/test/SILOptimizer/for_each_loop_unroll_test.sil @@ -118,8 +118,8 @@ bb2(%39 : @owned $Error): // CHECK-NOT: forEach // CHECK: [[STACK:%[0-9]+]] = alloc_stack $@callee_guaranteed @substituted <Ï„_0_0> () -> @out Ï„_0_0 for // CHECK: [[ELEM1BORROW:%[0-9]+]] = begin_borrow [[ELEM1]] -// CHECK: store_borrow [[ELEM1BORROW]] to [[STACK]] -// CHECK: try_apply [[BODYCLOSURE]]([[STACK]]) : $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted <Ï„_0_0> () -> @out Ï„_0_0 for ) -> @error Error, normal [[NORMAL:bb[0-9]+]], error [[ERROR:bb[0-9]+]] +// CHECK: [[SB1:%.*]] = store_borrow [[ELEM1BORROW]] to [[STACK]] +// CHECK: try_apply [[BODYCLOSURE]]([[SB1]]) : $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted <Ï„_0_0> () -> @out Ï„_0_0 for ) -> @error Error, normal [[NORMAL:bb[0-9]+]], error [[ERROR:bb[0-9]+]] // CHECK: [[ERROR]]([[ERRPARAM:%[0-9]+]] : @owned $Error): // CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM]] : $Error) @@ -127,8 +127,8 @@ bb2(%39 : @owned $Error): // CHECK: [[NORMAL]](%{{.*}} : $()): // CHECK: end_borrow [[ELEM1BORROW]] // CHECK: [[ELEM2BORROW:%[0-9]+]] = begin_borrow [[ELEM2]] -// CHECK: store_borrow [[ELEM2BORROW]] to [[STACK]] -// CHECK: try_apply [[BODYCLOSURE]]([[STACK]]) : $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted <Ï„_0_0> () -> @out Ï„_0_0 for ) -> @error Error, normal [[NORMAL2:bb[0-9]+]], error [[ERROR2:bb[0-9]+]] +// CHECK: [[SB2:%.*]] = store_borrow [[ELEM2BORROW]] to [[STACK]] +// CHECK: try_apply [[BODYCLOSURE]]([[SB2]]) : $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted <Ï„_0_0> () -> @out Ï„_0_0 for ) -> @error Error, normal [[NORMAL2:bb[0-9]+]], error [[ERROR2:bb[0-9]+]] // CHECK: [[ERROR2]]([[ERRPARAM2:%[0-9]+]] : @owned $Error): // CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM2]] : $Error) From 9ce2681af2e4f0bef2477ab87ea77a8ab5602b62 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 6 Jul 2022 13:06:23 -0700 Subject: [PATCH 144/491] Update utility which checks if scope ending instructions in OSSA can be trivially deleted --- lib/SILOptimizer/Utils/InstOptUtils.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index 661297ed6930a..6b74b031c8847 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -120,9 +120,13 @@ swift::createDecrementBefore(SILValue ptr, SILInstruction *insertPt) { return builder.createReleaseValue(loc, ptr, builder.getDefaultAtomicity()); } -static bool isOSSAEndScopeWithNoneOperand(SILInstruction *i) { +/// Returns true if OSSA scope ending instructions end_borrow/destroy_value can +/// be deleted trivially +static bool canTriviallyDeleteOSSAEndScopeInst(SILInstruction *i) { if (!isa(i) && !isa(i)) return false; + if (isa(i->getOperand(0))) + return false; return i->getOperand(0)->getOwnershipKind() == OwnershipKind::None; } @@ -172,7 +176,7 @@ bool swift::isInstructionTriviallyDead(SILInstruction *inst) { // // Examples of ossa end_scope instructions: end_borrow, destroy_value. if (inst->getFunction()->hasOwnership() && - isOSSAEndScopeWithNoneOperand(inst)) + canTriviallyDeleteOSSAEndScopeInst(inst)) return true; if (!inst->mayHaveSideEffects()) From 69d67813384d11a6578cdac172f8dea55358c2d9 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Fri, 5 Aug 2022 11:16:59 -0700 Subject: [PATCH 145/491] Update utility to allow end_borrow on addresses which have OwnershipKind::None --- include/swift/SIL/SILBuilder.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index c093d427f438d..19c4d2be55843 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -774,7 +774,8 @@ class SILBuilder { } void emitEndBorrowOperation(SILLocation loc, SILValue v) { - if (!hasOwnership() || v->getOwnershipKind() == OwnershipKind::None) + if (!hasOwnership() || (!v->getType().isAddress() && + v->getOwnershipKind() == OwnershipKind::None)) return; createEndBorrow(loc, v); } From ab47788c3ee3b89d2c8da0238423dfba57cf33ac Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Fri, 22 Jul 2022 11:52:16 -0700 Subject: [PATCH 146/491] Fix store_borrow pattern in DifferentiableActivityAnalysis Update the store_borrow pattern to correctly propagate Varied --- .../Analysis/DifferentiableActivityAnalysis.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/SILOptimizer/Analysis/DifferentiableActivityAnalysis.cpp b/lib/SILOptimizer/Analysis/DifferentiableActivityAnalysis.cpp index 1c377adb1a5ca..e0ccd3421ab41 100644 --- a/lib/SILOptimizer/Analysis/DifferentiableActivityAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/DifferentiableActivityAnalysis.cpp @@ -154,10 +154,15 @@ void DifferentiableActivityInfo::propagateVaried( propagateVariedInwardsThroughProjections(si->getDest(), i); \ } PROPAGATE_VARIED_THROUGH_STORE(Store) - PROPAGATE_VARIED_THROUGH_STORE(StoreBorrow) PROPAGATE_VARIED_THROUGH_STORE(CopyAddr) PROPAGATE_VARIED_THROUGH_STORE(UnconditionalCheckedCastAddr) #undef PROPAGATE_VARIED_THROUGH_STORE + else if (auto *sbi = dyn_cast(inst)) { + if (isVaried(sbi->getSrc(), i)) { + setVariedAndPropagateToUsers(sbi, i); + propagateVariedInwardsThroughProjections(sbi, i); + } + } // Handle `tuple_element_addr`. else if (auto *teai = dyn_cast(inst)) { if (isVaried(teai->getOperand(), i)) { From 05452dad86a2333533c7f469e68578caf4072567 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Fri, 5 Aug 2022 11:14:57 -0700 Subject: [PATCH 147/491] Fix store_borrow generation in AddressLowering --- lib/SILOptimizer/Mandatory/AddressLowering.cpp | 17 ++++++++++++----- test/SILOptimizer/address_lowering.sil | 3 ++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp index 4203e74157d53..08079447dd03f 100644 --- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp +++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp @@ -1774,25 +1774,32 @@ void CallArgRewriter::rewriteIndirectArgument(Operand *operand) { // Allocate temporary storage for a loadable operand. AllocStackInst *allocInst = argBuilder.createAllocStack(callLoc, argValue->getType()); - - operand->set(allocInst); - if (apply.getArgumentConvention(*operand).isOwnedConvention()) { argBuilder.createTrivialStoreOr(apply.getLoc(), argValue, allocInst, StoreOwnershipQualifier::Init); apply.insertAfterFullEvaluation([&](SILBuilder &callBuilder) { callBuilder.createDeallocStack(callLoc, allocInst); }); + operand->set(allocInst); } else { auto borrow = argBuilder.emitBeginBorrowOperation(callLoc, argValue); - argBuilder.emitStoreBorrowOperation(callLoc, borrow, allocInst); - + auto *store = + argBuilder.emitStoreBorrowOperation(callLoc, borrow, allocInst); + auto *storeBorrow = dyn_cast(store); apply.insertAfterFullEvaluation([&](SILBuilder &callBuilder) { + if (storeBorrow) { + callBuilder.emitEndBorrowOperation(callLoc, storeBorrow); + } if (borrow != argValue) { callBuilder.emitEndBorrowOperation(callLoc, borrow); } callBuilder.createDeallocStack(callLoc, allocInst); }); + if (storeBorrow) { + operand->set(storeBorrow); + } else { + operand->set(allocInst); + } } } diff --git a/test/SILOptimizer/address_lowering.sil b/test/SILOptimizer/address_lowering.sil index e8559fb84dc6d..ccf645055c759 100644 --- a/test/SILOptimizer/address_lowering.sil +++ b/test/SILOptimizer/address_lowering.sil @@ -262,7 +262,8 @@ bb0(%0 : @owned $T): // CHECK: [[TMP:%.*]] = alloc_stack $C // CHECK: [[B:%.*]] = begin_borrow [[LD]] : $C // CHECK: [[SB:%.*]] = store_borrow [[B]] to [[TMP]] : $*C -// CHECK: apply %{{.*}}([[TMP]]) : $@convention(thin) (@in_guaranteed C) -> () +// CHECK: apply %{{.*}}([[SB]]) : $@convention(thin) (@in_guaranteed C) -> () +// CHECK: end_borrow [[SB]] : $*C // CHECK: end_borrow [[B]] : $C // CHECK: dealloc_stack [[TMP]] : $*C // CHECK: destroy_value [[LD]] : $C From a3d054ce42449e8fa82e855c975c996dff942fb9 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Fri, 5 Aug 2022 11:17:45 -0700 Subject: [PATCH 148/491] Fix store_borrow visitor in MoveOnlyWrappedTypeEliminator --- .../Mandatory/MoveOnlyWrappedTypeEliminator.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp index 05b1e6595d3a1..ee86485aa0407 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp @@ -88,6 +88,14 @@ struct SILMoveOnlyWrappedTypeEliminatorVisitor SILBuilderWithScope b(si); b.emitStoreValueOperation(si->getLoc(), si->getSrc(), si->getDest(), StoreOwnershipQualifier::Trivial); + SmallVector endBorrows; + for (auto *ebi : si->getUsersOfType()) { + endBorrows.push_back(ebi); + } + for (auto *ebi : endBorrows) { + ebi->eraseFromParent(); + } + si->replaceAllUsesWith(si->getDest()); return eraseFromParent(si); } From 34cc511af50bcca4d1ff75819b277e3e2f17e1db Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Mon, 8 Aug 2022 12:39:18 -0700 Subject: [PATCH 149/491] Fix store_borrow pattern in DefiniteInitialization --- lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 49c4de9b006d5..3644864a1be40 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -1838,9 +1838,11 @@ findMethodForStoreInitializationOfTemporary(const DIMemoryObjectInfo &TheMemory, ApplyInst *TheApply = nullptr; + auto addr = + isa(SI) ? cast(SI) : SI->getDest(); // Check to see if the address of the alloc_stack is only passed to one // apply_inst and gather the apply while we are at it. - for (auto UI : SI->getDest()->getUses()) { + for (auto UI : addr->getUses()) { if (auto *ApplyUser = dyn_cast(UI->getUser())) { if (TheApply || UI->getOperandNumber() != 1) { return nullptr; From bf7cbb55048b1eb366418729396abd060736aefb Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 10 Aug 2022 14:29:12 -0700 Subject: [PATCH 150/491] Add new utilities for store borrow extension and ending store borrow scope --- include/swift/SIL/ScopedAddressUtils.h | 13 +++++ lib/SIL/Utils/ScopedAddressUtils.cpp | 72 +++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/include/swift/SIL/ScopedAddressUtils.h b/include/swift/SIL/ScopedAddressUtils.h index 19af91a3a72ef..7e5155e6ea3fb 100644 --- a/include/swift/SIL/ScopedAddressUtils.h +++ b/include/swift/SIL/ScopedAddressUtils.h @@ -19,6 +19,7 @@ #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILValue.h" +#include "swift/SILOptimizer/Utils/InstModCallbacks.h" namespace swift { @@ -90,6 +91,12 @@ struct ScopedAddressValue { /// unkown address use. Add this scope's live blocks into the PrunedLiveness /// result. bool computeLiveness(PrunedLiveness &liveness) const; + + /// Create appropriate scope ending instruction at \p insertPt. + void createScopeEnd(SILBasicBlock::iterator insertPt, SILLocation loc) const; + + /// Create scope ending instructions at \p liveness boundary. + void endScopeAtLivenessBoundary(PrunedLiveness *liveness) const; }; llvm::raw_ostream &operator<<(llvm::raw_ostream &os, @@ -100,6 +107,12 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, bool hasOtherStoreBorrowsInLifetime(StoreBorrowInst *sbi, PrunedLiveness *liveness, DeadEndBlocks *deadEndBlocks); + +/// Extend the store_borrow \p sbi's scope such that it encloses \p newUsers. +bool extendStoreBorrow(StoreBorrowInst *sbi, + SmallVectorImpl &newUses, + DeadEndBlocks *deadEndBlocks, + InstModCallbacks callbacks = InstModCallbacks()); } // namespace swift #endif diff --git a/lib/SIL/Utils/ScopedAddressUtils.cpp b/lib/SIL/Utils/ScopedAddressUtils.cpp index 4f749814c2073..132668b831b2f 100644 --- a/lib/SIL/Utils/ScopedAddressUtils.cpp +++ b/lib/SIL/Utils/ScopedAddressUtils.cpp @@ -16,6 +16,8 @@ #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILInstruction.h" +#include "swift/SILOptimizer/Utils/InstructionDeleter.h" +#include "swift/SILOptimizer/Utils/OwnershipOptUtils.h" using namespace swift; @@ -85,12 +87,18 @@ bool ScopedAddressValue::visitScopeEndingUses( } bool ScopedAddressValue::computeLiveness(PrunedLiveness &liveness) const { - auto addressKind = findTransitiveUsesForAddress(value); + SmallVector uses; + // Collect all uses that need to be enclosed by the scope. + auto addressKind = findTransitiveUsesForAddress(value, &uses); if (addressKind != AddressUseKind::NonEscaping) { return false; } liveness.initializeDefBlock(value->getParentBlock()); + for (auto *use : uses) { + // Update all collected uses as non-lifetime ending. + liveness.updateForUse(use->getUser(), /* lifetimeEnding */ false); + } visitScopeEndingUses([&](Operand *endOp) { liveness.updateForUse(endOp->getUser(), /* isLifetimeEnding */ true); return true; @@ -156,6 +164,68 @@ bool swift::hasOtherStoreBorrowsInLifetime(StoreBorrowInst *storeBorrow, return false; } +bool swift::extendStoreBorrow(StoreBorrowInst *sbi, + SmallVectorImpl &newUses, + DeadEndBlocks *deadEndBlocks, + InstModCallbacks callbacks) { + ScopedAddressValue scopedAddress(sbi); + + SmallVector discoveredBlocks; + PrunedLiveness storeBorrowLiveness(&discoveredBlocks); + bool success = scopedAddress.computeLiveness(storeBorrowLiveness); + + // If all new uses are within store_borrow boundary, no need for extension. + if (storeBorrowLiveness.areUsesWithinBoundary(newUses, deadEndBlocks)) { + return true; + } + + if (!success) { + return false; + } + + // store_borrow extension is possible only when there are no other + // store_borrows to the same destination within the store_borrow's lifetime + // built from newUsers. + if (hasOtherStoreBorrowsInLifetime(sbi, &storeBorrowLiveness, + deadEndBlocks)) { + return false; + } + + InstModCallbacks tempCallbacks = callbacks; + InstructionDeleter deleter(std::move(tempCallbacks)); + GuaranteedOwnershipExtension borrowExtension(deleter, *deadEndBlocks); + auto status = borrowExtension.checkBorrowExtension( + BorrowedValue(sbi->getSrc()), newUses); + if (status == GuaranteedOwnershipExtension::Invalid) { + return false; + } + + borrowExtension.transform(status); + + SmallVector endBorrowUses; + // Collect old scope-ending instructions. + scopedAddress.visitScopeEndingUses([&](Operand *op) { + endBorrowUses.push_back(op); + return true; + }); + + for (auto *use : newUses) { + // Update newUsers as non-lifetime ending. + storeBorrowLiveness.updateForUse(use->getUser(), + /* lifetimeEnding */ false); + } + + // Add new scope-ending instructions. + scopedAddress.endScopeAtLivenessBoundary(&storeBorrowLiveness); + + // Remove old scope-ending instructions. + for (auto *endBorrowUse : endBorrowUses) { + callbacks.deleteInst(endBorrowUse->getUser()); + } + + return true; +} + void ScopedAddressValue::print(llvm::raw_ostream &os) const { os << "ScopedAddressIntroducingValue:\n" "Kind: " From 46bdf131d7a851e9779d9621483e741c46d41956 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 10 Aug 2022 23:32:44 -0700 Subject: [PATCH 151/491] Fix store_borrow generation in GenericCloner --- .../swift/SILOptimizer/Utils/GenericCloner.h | 7 ++++ lib/SILOptimizer/Utils/GenericCloner.cpp | 37 ++++++++++++++++--- ...ialize_default_witness_resilience_ossa.sil | 4 +- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/include/swift/SILOptimizer/Utils/GenericCloner.h b/include/swift/SILOptimizer/Utils/GenericCloner.h index e3b6cb396816f..e070c06ace2a6 100644 --- a/include/swift/SILOptimizer/Utils/GenericCloner.h +++ b/include/swift/SILOptimizer/Utils/GenericCloner.h @@ -41,6 +41,8 @@ class GenericCloner RemappedScopeCache; llvm::SmallVector AllocStacks; + llvm::SmallVector StoreBorrowsToCleanup; + llvm::SmallVector FunctionExits; AllocStackInst *ReturnValueAddr = nullptr; public: @@ -92,6 +94,11 @@ class GenericCloner if (Callback) Callback(Orig, Cloned); + if (auto *termInst = dyn_cast(Cloned)) { + if (termInst->isFunctionExiting()) { + FunctionExits.push_back(termInst); + } + } SILClonerWithScopes::postProcess(Orig, Cloned); } diff --git a/lib/SILOptimizer/Utils/GenericCloner.cpp b/lib/SILOptimizer/Utils/GenericCloner.cpp index fe0f143e420af..d0eef1806c8cd 100644 --- a/lib/SILOptimizer/Utils/GenericCloner.cpp +++ b/lib/SILOptimizer/Utils/GenericCloner.cpp @@ -13,11 +13,13 @@ #include "swift/SILOptimizer/Utils/GenericCloner.h" #include "swift/AST/Type.h" +#include "swift/SIL/OwnershipUtils.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILValue.h" +#include "swift/SIL/ScopedAddressUtils.h" #include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/ADT/ArrayRef.h" @@ -61,7 +63,6 @@ void GenericCloner::populateCloned() { assert(!ReturnValueAddr && "Stale cloner state."); SILFunction *Cloned = getCloned(); - // Create arguments for the entry block. SILBasicBlock *OrigEntryBB = &*Original.begin(); SILBasicBlock *ClonedEntryBB = Cloned->createBasicBlock(); @@ -142,14 +143,19 @@ void GenericCloner::populateCloned() { // Store the new direct parameter to an alloc_stack. createAllocStack(); - if (!NewArg->getArgumentConvention().isGuaranteedConvention()) { + SILValue addr; + if (NewArg->getArgumentConvention().isGuaranteedConvention() && + NewArg->getFunction()->hasOwnership()) { + auto *sbi = getBuilder().createStoreBorrow(Loc, NewArg, ASI); + StoreBorrowsToCleanup.push_back(sbi); + addr = sbi; + } else { getBuilder().emitStoreValueOperation(Loc, NewArg, ASI, StoreOwnershipQualifier::Init); - } else { - getBuilder().emitStoreBorrowOperation(Loc, NewArg, ASI); + addr = ASI; } - entryArgs.push_back(ASI); + entryArgs.push_back(addr); return true; } } @@ -225,4 +231,25 @@ void GenericCloner::postFixUp(SILFunction *f) { getBuilder().setInsertionPoint(applyBlock); getBuilder().createUnreachable(apply->getLoc()); } + + SmallVector discoveredBlocks; + for (auto *sbi : StoreBorrowsToCleanup) { + ScopedAddressValue scopedAddress(sbi); + if (scopedAddress->getUses().empty()) { + scopedAddress.createScopeEnd(sbi->getNextInstruction()->getIterator(), + RegularLocation::getAutoGeneratedLocation()); + continue; + } + discoveredBlocks.clear(); + PrunedLiveness storeBorrowLiveness(&discoveredBlocks); + bool success = scopedAddress.computeLiveness(storeBorrowLiveness); + if (success) { + scopedAddress.endScopeAtLivenessBoundary(&storeBorrowLiveness); + continue; + } + for (auto *exit : FunctionExits) { + scopedAddress.createScopeEnd(exit->getIterator(), + RegularLocation::getAutoGeneratedLocation()); + } + } } diff --git a/test/SILOptimizer/specialize_default_witness_resilience_ossa.sil b/test/SILOptimizer/specialize_default_witness_resilience_ossa.sil index 81f71d17613a8..79c7d4e9c5d1b 100644 --- a/test/SILOptimizer/specialize_default_witness_resilience_ossa.sil +++ b/test/SILOptimizer/specialize_default_witness_resilience_ossa.sil @@ -38,9 +38,9 @@ public struct ConformingNonTrivialStruct : ResilientProtocol { // CHECK-LABEL: sil shared [ossa] @$s8defaultA4main26ConformingNonTrivialStructV_TB5 // CHECK: bb0(%0 : @guaranteed $ConformingNonTrivialStruct): // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $ConformingNonTrivialStruct -// CHECK-NEXT: store_borrow %0 to [[TMP]] : $*ConformingNonTrivialStruct +// CHECK-NEXT: [[SB:%.*]] = store_borrow %0 to [[TMP]] : $*ConformingNonTrivialStruct // CHECK: [[FN:%.*]] = function_ref @$s8defaultB4main26ConformingNonTrivialStructV_TB5 -// CHECK-NEXT: [[LOAD:%.*]] = load_borrow [[TMP]] : $*ConformingNonTrivialStruct +// CHECK-NEXT: [[LOAD:%.*]] = load_borrow [[SB]] : $*ConformingNonTrivialStruct // CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]([[LOAD]]) // CHECK: dealloc_stack [[TMP]] : $*ConformingNonTrivialStruct // CHECK } // end sil function 's8defaultA4main16ConformingNonTrivialStructV_TB5' From 98fa7f079f2c50e41739846faa431fe52be4c81a Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 10 Aug 2022 21:38:40 -0700 Subject: [PATCH 152/491] Handle ValueMetatypeInst as a leaf user in swift::findTransitiveUsesForAddress --- lib/SIL/Utils/OwnershipUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SIL/Utils/OwnershipUtils.cpp b/lib/SIL/Utils/OwnershipUtils.cpp index b29aab8fcfd92..58dd54a5c65e0 100644 --- a/lib/SIL/Utils/OwnershipUtils.cpp +++ b/lib/SIL/Utils/OwnershipUtils.cpp @@ -918,7 +918,7 @@ swift::findTransitiveUsesForAddress(SILValue projectedAddress, isa(user) || isa(user) || isa(user) || isa(user) || isa(user) || isa(user) || - isa(user)) { + isa(user) || isa(user)) { leafUse(op); continue; } From b7c23edfe6ff6e47664b9c76e352370223a66be4 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 10 Aug 2022 21:41:07 -0700 Subject: [PATCH 153/491] Fix SILCombine of partial_apply to correctly extend store_borrow when needed --- .../swift/SILOptimizer/Utils/InstOptUtils.h | 2 +- .../swift/SILOptimizer/Utils/ValueLifetime.h | 14 +++++ lib/SILOptimizer/Utils/InstOptUtils.cpp | 16 ++--- .../Utils/PartialApplyCombiner.cpp | 58 ++++++++++++++----- 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/include/swift/SILOptimizer/Utils/InstOptUtils.h b/include/swift/SILOptimizer/Utils/InstOptUtils.h index ce5f3b685cebc..a7c92b2dc941c 100644 --- a/include/swift/SILOptimizer/Utils/InstOptUtils.h +++ b/include/swift/SILOptimizer/Utils/InstOptUtils.h @@ -247,7 +247,7 @@ void emitDestroyOperation(SILBuilder &builder, SILLocation loc, /// Returns true, if there are no other users beside those collected in \p /// destroys, i.e. if \p inst can be considered as "dead". bool collectDestroys(SingleValueInstruction *inst, - SmallVectorImpl &destroys); + SmallVectorImpl &destroys); /// If Closure is a partial_apply or thin_to_thick_function with only local /// ref count users and a set of post-dominating releases: diff --git a/include/swift/SILOptimizer/Utils/ValueLifetime.h b/include/swift/SILOptimizer/Utils/ValueLifetime.h index 440d9763e8dd9..86bbad8663f81 100644 --- a/include/swift/SILOptimizer/Utils/ValueLifetime.h +++ b/include/swift/SILOptimizer/Utils/ValueLifetime.h @@ -138,6 +138,20 @@ class ValueLifetimeAnalysis { propagateLiveness(); } + ValueLifetimeAnalysis(SILArgument *def, ArrayRef useRange) + : defValue(def), inLiveBlocks(def->getFunction()), userSet() { + for (auto *use : useRange) + userSet.insert(use->getUser()); + propagateLiveness(); + } + + ValueLifetimeAnalysis(SILInstruction *def, ArrayRef useRange) + : defValue(def), inLiveBlocks(def->getFunction()), userSet() { + for (auto *use : useRange) + userSet.insert(use->getUser()); + propagateLiveness(); + } + /// Compute the LifetimeBoundary--the last users and boundary edges. This /// always succeeds. /// diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index 6b74b031c8847..4e0b1d0102774 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -25,6 +25,7 @@ #include "swift/SIL/SILDebugInfoExpression.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILUndef.h" +#include "swift/SIL/ScopedAddressUtils.h" #include "swift/SIL/TypeLowering.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/Analysis.h" @@ -971,16 +972,16 @@ void swift::getConsumedPartialApplyArgs(PartialApplyInst *pai, } bool swift::collectDestroys(SingleValueInstruction *inst, - SmallVectorImpl &destroys) { + SmallVectorImpl &destroys) { bool isDead = true; for (Operand *use : inst->getUses()) { SILInstruction *user = use->getUser(); if (useHasTransitiveOwnership(user)) { if (!collectDestroys(cast(user), destroys)) isDead = false; - destroys.push_back(user); + destroys.push_back(use); } else if (useDoesNotKeepValueAlive(user)) { - destroys.push_back(user); + destroys.push_back(use); } else { isDead = false; } @@ -996,7 +997,7 @@ bool swift::collectDestroys(SingleValueInstruction *inst, /// weirdness of the old retain/release ARC model. Most likely this will /// not be needed anymore with OSSA. static bool keepArgsOfPartialApplyAlive(PartialApplyInst *pai, - ArrayRef paiUsers, + ArrayRef paiUses, SILBuilderContext &builderCtxt, InstModCallbacks callbacks) { SmallVector argsToHandle; @@ -1008,7 +1009,7 @@ static bool keepArgsOfPartialApplyAlive(PartialApplyInst *pai, // Compute the set of endpoints, which will be used to insert destroys of // temporaries. This may fail if the frontier is located on a critical edge // which we may not split. - ValueLifetimeAnalysis vla(pai, paiUsers); + ValueLifetimeAnalysis vla(pai, paiUses); ValueLifetimeAnalysis::Frontier partialApplyFrontier; if (!vla.computeFrontier(partialApplyFrontier, @@ -1068,7 +1069,7 @@ bool swift::tryDeleteDeadClosure(SingleValueInstruction *closure, // Collect all destroys of the closure (transitively including destorys of // copies) and check if those are the only uses of the closure. - SmallVector closureDestroys; + SmallVector closureDestroys; if (!collectDestroys(closure, closureDestroys)) return false; @@ -1102,7 +1103,8 @@ bool swift::tryDeleteDeadClosure(SingleValueInstruction *closure, // Delete all copy and destroy instructions in order so that leaf uses are // deleted first. - for (SILInstruction *user : closureDestroys) { + for (auto *use : closureDestroys) { + auto *user = use->getUser(); assert( (useDoesNotKeepValueAlive(user) || useHasTransitiveOwnership(user)) && "We expect only ARC operations without " diff --git a/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp b/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp index 3c81442b9e0cf..98501b0397ba3 100644 --- a/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp +++ b/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "swift/SIL/SILValue.h" +#include "swift/SIL/ScopedAddressUtils.h" #include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/ValueLifetime.h" @@ -59,34 +60,44 @@ class PartialApplyCombiner { /// apply instructions. bool PartialApplyCombiner::copyArgsToTemporaries( ArrayRef applies) { + SmallVector argsToHandle; + + // Find args that need extension for a non-stack partial_apply // A partial_apply [stack]'s argument are not owned by the partial_apply and // therefore their lifetime must outlive any uses. - if (pai->isOnStack()) - return true; - - SmallVector argsToHandle; - getConsumedPartialApplyArgs(pai, argsToHandle, - /*includeTrivialAddrArgs*/ true); - if (argsToHandle.empty()) - return true; + if (!pai->isOnStack()) { + getConsumedPartialApplyArgs(pai, argsToHandle, + /*includeTrivialAddrArgs*/ true); + } // Compute the set of endpoints, which will be used to insert destroys of // temporaries. - SmallVector paiUsers; + SmallVector paiUses; // Of course we must inlude all apply instructions which we want to optimize. for (FullApplySite ai : applies) { - paiUsers.push_back(ai.getInstruction()); + paiUses.push_back(ai.getCalleeOperand()); + } + + SmallVector storeBorrowsToHandle; + for (auto arg : pai->getArguments()) { + if (auto *sbi = dyn_cast(arg)) { + storeBorrowsToHandle.push_back(sbi); + } } + if (argsToHandle.empty() && storeBorrowsToHandle.empty()) { + return true; + } // Also include all destroys in the liferange for the arguments. // This is needed for later processing in tryDeleteDeadClosure: in case the - // pai gets dead after this optimization, tryDeleteDeadClosure relies on that - // we already copied the pai arguments to extend their lifetimes until the pai - // is finally destroyed. - collectDestroys(pai, paiUsers); + // pai gets dead after this optimization, tryDeleteDeadClosure relies on + // that we already copied the pai arguments to extend their lifetimes until + // the pai is finally destroyed. + collectDestroys(pai, paiUses); - ValueLifetimeAnalysis vla(pai, paiUsers); + ValueLifetimeAnalysis vla(pai, + llvm::makeArrayRef(paiUses.begin(), paiUses.end())); ValueLifetimeAnalysis::Frontier partialApplyFrontier; // Computing the frontier may fail if the frontier is located on a critical @@ -114,6 +125,23 @@ bool PartialApplyCombiner::copyArgsToTemporaries( // allocated temporary) at the end of the partial_apply's lifetime. endLifetimeAtFrontier(tmp, partialApplyFrontier, builderCtxt, callbacks); } + + DeadEndBlocks deBlocks(pai->getFunction()); + for (auto *storeBorrow : storeBorrowsToHandle) { + if (extendStoreBorrow(storeBorrow, paiUses, &deBlocks, callbacks)) { + continue; + } + SILBuilderWithScope builder(pai, builderCtxt); + // Copy address-arguments into a stack-allocated temporary. + auto *asi = builder.createAllocStack(pai->getLoc(), storeBorrow->getType()); + builder.createCopyAddr(pai->getLoc(), storeBorrow, asi, IsTake_t::IsNotTake, + IsInitialization_t::IsInitialization); + argToTmpCopy.insert(std::make_pair(storeBorrow, asi)); + + // Destroy the argument value (either as SSA value or in the stack- + // allocated temporary) at the end of the partial_apply's lifetime. + endLifetimeAtFrontier(asi, partialApplyFrontier, builderCtxt, callbacks); + } return true; } From e65601f592d27e7e812013bd970cdf6fb96d0752 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Tue, 2 Aug 2022 13:38:20 -0700 Subject: [PATCH 154/491] Rename MoveOnlyChecker -> MoveOnlyObjectChecker.cpp. --- include/swift/SILOptimizer/PassManager/Passes.def | 4 ++-- lib/SILOptimizer/Mandatory/CMakeLists.txt | 2 +- .../{MoveOnlyChecker.cpp => MoveOnlyObjectChecker.cpp} | 2 +- lib/SILOptimizer/PassManager/PassPipeline.cpp | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) rename lib/SILOptimizer/Mandatory/{MoveOnlyChecker.cpp => MoveOnlyObjectChecker.cpp} (99%) diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def index aeba65c7dc696..160ab2adcad38 100644 --- a/include/swift/SILOptimizer/PassManager/Passes.def +++ b/include/swift/SILOptimizer/PassManager/Passes.def @@ -437,8 +437,8 @@ PASS(BugReducerTester, "bug-reducer-tester", "sil-bug-reducer Tool Testing by Asserting on a Sentinel Function") PASS(AssemblyVisionRemarkGenerator, "assembly-vision-remark-generator", "Emit assembly vision remarks that provide source level guidance of where runtime calls ended up") -PASS(MoveOnlyChecker, "sil-move-only-checker", - "Pass that enforces move only invariants on raw SIL") +PASS(MoveOnlyObjectChecker, "sil-move-only-object-checker", + "Pass that enforces move only invariants on raw SIL for objects") PASS(MoveKillsCopyableValuesChecker, "sil-move-kills-copyable-values-checker", "Pass that checks that any copyable (non-move only) value that is passed " "to _move do not have any uses later than the _move") diff --git a/lib/SILOptimizer/Mandatory/CMakeLists.txt b/lib/SILOptimizer/Mandatory/CMakeLists.txt index 927b2e3b62e8a..9b8a77e074040 100644 --- a/lib/SILOptimizer/Mandatory/CMakeLists.txt +++ b/lib/SILOptimizer/Mandatory/CMakeLists.txt @@ -25,7 +25,7 @@ target_sources(swiftSILOptimizer PRIVATE MoveFunctionCanonicalization.cpp MoveKillsCopyableAddressesChecker.cpp MoveKillsCopyableValuesChecker.cpp - MoveOnlyChecker.cpp + MoveOnlyObjectChecker.cpp NestedSemanticFunctionCheck.cpp OptimizeHopToExecutor.cpp PerformanceDiagnostics.cpp diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyObjectChecker.cpp similarity index 99% rename from lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp rename to lib/SILOptimizer/Mandatory/MoveOnlyObjectChecker.cpp index a8571f776a733..6e08f760329ca 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyObjectChecker.cpp @@ -540,6 +540,6 @@ class MoveOnlyCheckerPass : public SILFunctionTransform { } // anonymous namespace -SILTransform *swift::createMoveOnlyChecker() { +SILTransform *swift::createMoveOnlyObjectChecker() { return new MoveOnlyCheckerPass(); } diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index b99aa93aa937c..4fc850df776a8 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -171,7 +171,8 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) { // SSA based move function checking and no implicit copy checking. P.addMoveKillsCopyableValuesChecker(); // No uses after _move of copyable // value. - P.addMoveOnlyChecker(); // Check noImplicitCopy isn't copied. + P.addMoveOnlyObjectChecker(); // Check noImplicitCopy and move only + // types. // Now that we have run move only checking, eliminate SILMoveOnly wrapped // trivial types from the IR. We cannot introduce extra "copies" of trivial From 3fd9037ee9e97be5e80be277303244f8d4eee7d4 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 16 Aug 2022 16:18:50 -0700 Subject: [PATCH 155/491] [ConstraintSystem] Don't produce argument info object for extraneous arguments An extraneous argument doesn't have a corresponding parameter so the information object for such an argument is not safe to produce. Resolves: https://github.com/apple/swift/issues/60436 Resolves: rdar://98304482 --- include/swift/Sema/ConstraintSystem.h | 18 +++++++++++++++++- lib/Sema/ConstraintSystem.cpp | 6 +++--- test/Constraints/argument_matching.swift | 8 ++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 6788b26148a0c..1a7890aa5adbe 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -715,7 +715,6 @@ class FunctionArgApplyInfo { FunctionType *FnType; const ValueDecl *Callee; -public: FunctionArgApplyInfo(ArgumentList *argList, Expr *argExpr, unsigned argIdx, Type argType, unsigned paramIdx, Type fnInterfaceType, FunctionType *fnType, const ValueDecl *callee) @@ -723,6 +722,23 @@ class FunctionArgApplyInfo { ParamIdx(paramIdx), FnInterfaceType(fnInterfaceType), FnType(fnType), Callee(callee) {} +public: + static Optional + get(ArgumentList *argList, Expr *argExpr, unsigned argIdx, Type argType, + unsigned paramIdx, Type fnInterfaceType, FunctionType *fnType, + const ValueDecl *callee) { + assert(fnType); + + if (argIdx >= argList->size()) + return None; + + if (paramIdx >= fnType->getNumParams()) + return None; + + return FunctionArgApplyInfo(argList, argExpr, argIdx, argType, paramIdx, + fnInterfaceType, fnType, callee); + } + /// \returns The list of the arguments used for this application. ArgumentList *getArgList() const { return ArgList; } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 4b2f56d260a50..a675f32f7849d 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -5682,9 +5682,9 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const { auto argIdx = applyArgElt->getArgIdx(); auto paramIdx = applyArgElt->getParamIdx(); - return FunctionArgApplyInfo(argList, argExpr, argIdx, - simplifyType(getType(argExpr)), paramIdx, - fnInterfaceType, fnType, callee); + return FunctionArgApplyInfo::get(argList, argExpr, argIdx, + simplifyType(getType(argExpr)), paramIdx, + fnInterfaceType, fnType, callee); } bool constraints::isKnownKeyPathType(Type type) { diff --git a/test/Constraints/argument_matching.swift b/test/Constraints/argument_matching.swift index a83ca9694e63a..7920e42eb5747 100644 --- a/test/Constraints/argument_matching.swift +++ b/test/Constraints/argument_matching.swift @@ -1802,3 +1802,11 @@ do { // expected-error@-1 {{cannot convert value of type 'Bool' to expected argument type 'String'}} // expected-error@-2 {{missing argument label 'file:' in call}} } + +// https://github.com/apple/swift/issues/60436 +func test_extraneous_argument_with_inout() { + func test(_: Int) {} + + var x: Int = 0 + test(42, &x) // expected-error {{extra argument in call}} +} From 6ca24c923986bb9ae635df20dadea339cfa0b7b1 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 16 Aug 2022 16:42:29 -0700 Subject: [PATCH 156/491] Factor out checking if a binary module is up-to-date from the rest of 'ModuleInterfaceLoaderImpl' logic, to be used by other clients --- lib/Frontend/ModuleInterfaceLoader.cpp | 260 ++++++++++++++----------- 1 file changed, 141 insertions(+), 119 deletions(-) diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 9af79012ede69..b8d38dc231608 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -337,58 +337,100 @@ struct ModuleRebuildInfo { } }; -/// Handles the details of loading module interfaces as modules, and will -/// do the necessary lookup to determine if we should be loading from the -/// normal cache, the prebuilt cache, a module adjacent to the interface, or -/// a module that we'll build from a module interface. -class ModuleInterfaceLoaderImpl { - friend class swift::ModuleInterfaceLoader; - friend class swift::ModuleInterfaceCheckerImpl; +/// Constructs the full path of the dependency \p dep by prepending the SDK +/// path if necessary. +StringRef getFullDependencyPath(const FileDependency &dep, + const ASTContext &ctx, + SmallVectorImpl &scratch) { + if (!dep.isSDKRelative()) + return dep.getPath(); + + path::native(ctx.SearchPathOpts.getSDKPath(), scratch); + llvm::sys::path::append(scratch, dep.getPath()); + return StringRef(scratch.data(), scratch.size()); +} + +class UpToDateModuleCheker { ASTContext &ctx; llvm::vfs::FileSystem &fs; - DiagnosticEngine &diags; - ModuleRebuildInfo rebuildInfo; - const StringRef modulePath; - const std::string interfacePath; - const StringRef moduleName; - const StringRef prebuiltCacheDir; - const StringRef backupInterfaceDir; - const StringRef cacheDir; - const SourceLoc diagnosticLoc; - DependencyTracker *const dependencyTracker; - const ModuleLoadingMode loadMode; - ModuleInterfaceLoaderOptions Opts; RequireOSSAModules_t requiresOSSAModules; - ModuleInterfaceLoaderImpl( - ASTContext &ctx, StringRef modulePath, StringRef interfacePath, - StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir, - StringRef backupInterfaceDir, - SourceLoc diagLoc, ModuleInterfaceLoaderOptions Opts, - RequireOSSAModules_t requiresOSSAModules, - DependencyTracker *dependencyTracker = nullptr, - ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized) - : ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags), - modulePath(modulePath), interfacePath(interfacePath), - moduleName(moduleName), - prebuiltCacheDir(prebuiltCacheDir), - backupInterfaceDir(backupInterfaceDir), - cacheDir(cacheDir), diagnosticLoc(diagLoc), - dependencyTracker(dependencyTracker), loadMode(loadMode), Opts(Opts), - requiresOSSAModules(requiresOSSAModules) {} +public: + UpToDateModuleCheker(ASTContext &ctx, RequireOSSAModules_t requiresOSSAModules) + : ctx(ctx), + fs(*ctx.SourceMgr.getFileSystem()), + requiresOSSAModules(requiresOSSAModules) {} + + // Check if all the provided file dependencies are up-to-date compared to + // what's currently on disk. + bool dependenciesAreUpToDate(StringRef modulePath, + ModuleRebuildInfo &rebuildInfo, + ArrayRef deps, + bool skipSystemDependencies) { + SmallString<128> SDKRelativeBuffer; + for (auto &in : deps) { + if (skipSystemDependencies && in.isSDKRelative() && + in.isModificationTimeBased()) { + continue; + } + StringRef fullPath = getFullDependencyPath(in, ctx, SDKRelativeBuffer); + switch (checkDependency(modulePath, in, fullPath)) { + case DependencyStatus::UpToDate: + LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is up to date\n"); + break; + case DependencyStatus::OutOfDate: + LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is out of date\n"); + rebuildInfo.addOutOfDateDependency(modulePath, fullPath); + return false; + case DependencyStatus::Missing: + LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is missing\n"); + rebuildInfo.addMissingDependency(modulePath, fullPath); + return false; + } + } + return true; + } + + // Check that the output .swiftmodule file is at least as new as all the + // dependencies it read when it was built last time. + bool serializedASTBufferIsUpToDate( + StringRef path, const llvm::MemoryBuffer &buf, + ModuleRebuildInfo &rebuildInfo, + SmallVectorImpl &allDeps) { + + // Clear the existing dependencies, because we're going to re-fill them + // in validateSerializedAST. + allDeps.clear(); - /// Constructs the full path of the dependency \p dep by prepending the SDK - /// path if necessary. - StringRef getFullDependencyPath(const FileDependency &dep, - SmallVectorImpl &scratch) const { - if (!dep.isSDKRelative()) - return dep.getPath(); + LLVM_DEBUG(llvm::dbgs() << "Validating deps of " << path << "\n"); + auto validationInfo = serialization::validateSerializedAST( + buf.getBuffer(), requiresOSSAModules, ctx.LangOpts.SDKName, + /*ExtendedValidationInfo=*/nullptr, &allDeps); - path::native(ctx.SearchPathOpts.getSDKPath(), scratch); - llvm::sys::path::append(scratch, dep.getPath()); - return StringRef(scratch.data(), scratch.size()); + if (validationInfo.status != serialization::Status::Valid) { + rebuildInfo.setSerializationStatus(path, validationInfo.status); + return false; + } + + bool skipCheckingSystemDependencies = + ctx.SearchPathOpts.DisableModulesValidateSystemDependencies; + return dependenciesAreUpToDate(path, rebuildInfo, allDeps, + skipCheckingSystemDependencies); } + // Check that the output .swiftmodule file is at least as new as all the + // dependencies it read when it was built last time. + bool swiftModuleIsUpToDate( + StringRef modulePath, ModuleRebuildInfo &rebuildInfo, + SmallVectorImpl &AllDeps, + std::unique_ptr &moduleBuffer) { + auto OutBuf = fs.getBufferForFile(modulePath); + if (!OutBuf) + return false; + moduleBuffer = std::move(*OutBuf); + return serializedASTBufferIsUpToDate(modulePath, *moduleBuffer, rebuildInfo, AllDeps); + } + enum class DependencyStatus { UpToDate, OutOfDate, @@ -429,6 +471,49 @@ class ModuleInterfaceLoaderImpl { DependencyStatus::UpToDate : DependencyStatus::OutOfDate; } +}; + +/// Handles the details of loading module interfaces as modules, and will +/// do the necessary lookup to determine if we should be loading from the +/// normal cache, the prebuilt cache, a module adjacent to the interface, or +/// a module that we'll build from a module interface. +class ModuleInterfaceLoaderImpl { + friend class swift::ModuleInterfaceLoader; + friend class swift::ModuleInterfaceCheckerImpl; + ASTContext &ctx; + llvm::vfs::FileSystem &fs; + DiagnosticEngine &diags; + ModuleRebuildInfo rebuildInfo; + UpToDateModuleCheker upToDateChecker; + const StringRef modulePath; + const std::string interfacePath; + const StringRef moduleName; + const StringRef prebuiltCacheDir; + const StringRef backupInterfaceDir; + const StringRef cacheDir; + const SourceLoc diagnosticLoc; + DependencyTracker *const dependencyTracker; + const ModuleLoadingMode loadMode; + ModuleInterfaceLoaderOptions Opts; + RequireOSSAModules_t requiresOSSAModules; + + ModuleInterfaceLoaderImpl( + ASTContext &ctx, StringRef modulePath, StringRef interfacePath, + StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir, + StringRef backupInterfaceDir, + SourceLoc diagLoc, ModuleInterfaceLoaderOptions Opts, + RequireOSSAModules_t requiresOSSAModules, + DependencyTracker *dependencyTracker = nullptr, + ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized) + : ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags), + upToDateChecker(ctx, requiresOSSAModules), + modulePath(modulePath), interfacePath(interfacePath), + moduleName(moduleName), + prebuiltCacheDir(prebuiltCacheDir), + backupInterfaceDir(backupInterfaceDir), + cacheDir(cacheDir), diagnosticLoc(diagLoc), + dependencyTracker(dependencyTracker), loadMode(loadMode), Opts(Opts), + requiresOSSAModules(requiresOSSAModules) {} std::string getBackupPublicModuleInterfacePath() { return getBackupPublicModuleInterfacePath(ctx.SourceMgr, backupInterfaceDir, @@ -461,73 +546,6 @@ class ModuleInterfaceLoaderImpl { return std::string(); } - // Check if all the provided file dependencies are up-to-date compared to - // what's currently on disk. - bool dependenciesAreUpToDate(StringRef modulePath, - ArrayRef deps, - bool skipSystemDependencies) { - SmallString<128> SDKRelativeBuffer; - for (auto &in : deps) { - if (skipSystemDependencies && in.isSDKRelative() && - in.isModificationTimeBased()) { - continue; - } - StringRef fullPath = getFullDependencyPath(in, SDKRelativeBuffer); - switch (checkDependency(modulePath, in, fullPath)) { - case DependencyStatus::UpToDate: - LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is up to date\n"); - break; - case DependencyStatus::OutOfDate: - LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is out of date\n"); - rebuildInfo.addOutOfDateDependency(modulePath, fullPath); - return false; - case DependencyStatus::Missing: - LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is missing\n"); - rebuildInfo.addMissingDependency(modulePath, fullPath); - return false; - } - } - return true; - } - - // Check that the output .swiftmodule file is at least as new as all the - // dependencies it read when it was built last time. - bool serializedASTBufferIsUpToDate( - StringRef path, const llvm::MemoryBuffer &buf, - SmallVectorImpl &allDeps) { - - // Clear the existing dependencies, because we're going to re-fill them - // in validateSerializedAST. - allDeps.clear(); - - LLVM_DEBUG(llvm::dbgs() << "Validating deps of " << path << "\n"); - auto validationInfo = serialization::validateSerializedAST( - buf.getBuffer(), requiresOSSAModules, ctx.LangOpts.SDKName, - /*ExtendedValidationInfo=*/nullptr, &allDeps); - - if (validationInfo.status != serialization::Status::Valid) { - rebuildInfo.setSerializationStatus(path, validationInfo.status); - return false; - } - - bool skipCheckingSystemDependencies = - ctx.SearchPathOpts.DisableModulesValidateSystemDependencies; - return dependenciesAreUpToDate(path, allDeps, - skipCheckingSystemDependencies); - } - - // Check that the output .swiftmodule file is at least as new as all the - // dependencies it read when it was built last time. - bool swiftModuleIsUpToDate( - StringRef modulePath, SmallVectorImpl &AllDeps, - std::unique_ptr &moduleBuffer) { - auto OutBuf = fs.getBufferForFile(modulePath); - if (!OutBuf) - return false; - moduleBuffer = std::move(*OutBuf); - return serializedASTBufferIsUpToDate(modulePath, *moduleBuffer, AllDeps); - } - // Check that a "forwarding" .swiftmodule file is at least as new as all the // dependencies it read when it was built last time. Requires that the // forwarding module has been loaded from disk. @@ -557,7 +575,8 @@ class ModuleInterfaceLoaderImpl { bool skipCheckingSystemDependencies = ctx.SearchPathOpts.DisableModulesValidateSystemDependencies; - if (!dependenciesAreUpToDate(path, deps, skipCheckingSystemDependencies)) + if (!upToDateChecker.dependenciesAreUpToDate(path, rebuildInfo, deps, + skipCheckingSystemDependencies)) return false; moduleBuffer = std::move(*modBuf); @@ -729,8 +748,8 @@ class ModuleInterfaceLoaderImpl { if (!adjacentMod.empty()) { auto adjacentModuleBuffer = fs.getBufferForFile(adjacentMod); if (adjacentModuleBuffer) { - if (serializedASTBufferIsUpToDate(adjacentMod, *adjacentModuleBuffer.get(), - deps)) { + if (upToDateChecker.serializedASTBufferIsUpToDate(adjacentMod, *adjacentModuleBuffer.get(), + rebuildInfo, deps)) { LLVM_DEBUG(llvm::dbgs() << "Found up-to-date module at " << adjacentMod << "; deferring to serialized module loader\n"); @@ -767,7 +786,8 @@ class ModuleInterfaceLoaderImpl { if(!prebuiltMod.empty()) { std::unique_ptr moduleBuffer; - if (swiftModuleIsUpToDate(prebuiltMod, deps, moduleBuffer)) { + if (upToDateChecker.swiftModuleIsUpToDate(prebuiltMod, rebuildInfo, + deps, moduleBuffer)) { LLVM_DEBUG(llvm::dbgs() << "Found up-to-date prebuilt module at " << prebuiltMod << "\n"); UsableModulePath = prebuiltMod; @@ -819,7 +839,8 @@ class ModuleInterfaceLoaderImpl { ModuleRebuildInfo::ModuleKind::Forwarding); } // Otherwise, check if the AST buffer itself is up to date. - } else if (serializedASTBufferIsUpToDate(cachedOutputPath, *buf, deps)) { + } else if (upToDateChecker.serializedASTBufferIsUpToDate(cachedOutputPath, *buf, + rebuildInfo, deps)) { LLVM_DEBUG(llvm::dbgs() << "Found up-to-date cached module at " << cachedOutputPath << "\n"); return DiscoveredModule::normal(cachedOutputPath, std::move(buf)); @@ -854,7 +875,7 @@ class ModuleInterfaceLoaderImpl { // we may record out-of-date information. SmallString<128> SDKRelativeBuffer; auto addDependency = [&](FileDependency dep) -> FileDependency { - auto status = fs.status(getFullDependencyPath(dep, SDKRelativeBuffer)); + auto status = fs.status(getFullDependencyPath(dep, ctx, SDKRelativeBuffer)); uint64_t mtime = status->getLastModificationTime().time_since_epoch().count(); fwd.addDependency(dep.getPath(), dep.isSDKRelative(), status->getSize(), @@ -955,7 +976,7 @@ class ModuleInterfaceLoaderImpl { if (dependencyTracker) { SmallString<128> SDKRelativeBuffer; for (auto &dep: allDeps) { - StringRef fullPath = getFullDependencyPath(dep, SDKRelativeBuffer); + StringRef fullPath = getFullDependencyPath(dep, ctx, SDKRelativeBuffer); dependencyTracker->addDependency(fullPath, /*IsSystem=*/dep.isSDKRelative()); } @@ -1197,7 +1218,8 @@ bool ModuleInterfaceCheckerImpl::tryEmitForwardingModule( std::unique_ptr moduleBuffer; for (auto mod: candidates) { // Check if the candidate compiled module is still up-to-date. - if (Impl.swiftModuleIsUpToDate(mod, deps, moduleBuffer)) { + if (Impl.upToDateChecker.swiftModuleIsUpToDate(mod, Impl.rebuildInfo, + deps, moduleBuffer)) { // If so, emit a forwarding module to the candidate. ForwardingModule FM(mod); auto hadError = withOutputFile(Ctx.Diags, outputPath, From 256c0ff04a91680b1c5fb180373bbd772227768f Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 16 Aug 2022 16:42:44 -0700 Subject: [PATCH 157/491] [Explicit Modules] On an explicit interface build, early exit if the expected output is up-to-date. --- include/swift/AST/DiagnosticsSema.def | 4 ++++ include/swift/Basic/LangOptions.h | 3 +++ include/swift/Option/Options.td | 4 ++++ lib/Frontend/CompilerInvocation.cpp | 2 ++ lib/Frontend/ModuleInterfaceLoader.cpp | 15 +++++++++++++++ ...ed-explicit-interface-build-nop.swiftinterface | 14 ++++++++++++++ 6 files changed, 42 insertions(+) create mode 100644 test/ModuleInterface/repeated-explicit-interface-build-nop.swiftinterface diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index b2dfc26399396..d1299120de8f0 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -979,6 +979,10 @@ REMARK(cross_import_added,none, REMARK(module_loaded,none, "loaded module at %0", (StringRef)) + +REMARK(explicit_interface_build_skipped,none, + "Skipped rebuilding module at %0 - up-to-date", + (StringRef)) WARNING(cannot_find_project_version,none, "cannot find user version number for %0 module '%1'; version number ignored", (StringRef, StringRef)) diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index e38bfbcbd3842..1003af65371d8 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -215,6 +215,9 @@ namespace swift { /// Emit a remark after loading a module. bool EnableModuleLoadingRemarks = false; + + /// Emit a remark on early exit in explicit interface build + bool EnableSkipExplicitInterfaceModuleBuildRemarks = false; /// /// Support for alternate usage modes diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 3e6901c488c0b..c4dbcbb451bb7 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -340,6 +340,10 @@ def remark_loading_module : Flag<["-"], "Rmodule-loading">, Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, HelpText<"Emit a remark and file path of each loaded module">; +def remark_skip_explicit_interface_build : Flag<["-"], "Rskip-explicit-interface-build">, + Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, + HelpText<"Emit a remark if an explicit module interface invocation has an early exit because the expected output is up-to-date">; + def emit_tbd : Flag<["-"], "emit-tbd">, HelpText<"Emit a TBD file">, Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index f52fe884217be..2a47ec9e64407 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -797,6 +797,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.EnableModuleLoadingRemarks = Args.hasArg(OPT_remark_loading_module); + Opts.EnableSkipExplicitInterfaceModuleBuildRemarks = Args.hasArg(OPT_remark_skip_explicit_interface_build); + llvm::Triple Target = Opts.Target; StringRef TargetArg; std::string TargetArgScratch; diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index b8d38dc231608..bbf4281469f3f 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1345,6 +1345,21 @@ bool ModuleInterfaceLoader::buildExplicitSwiftModuleFromSwiftInterface( ArrayRef CompiledCandidates, DependencyTracker *tracker) { + // First, check if the expected output already exists and possibly up-to-date w.r.t. + // all of the dependencies it was built with. If so, early exit. + UpToDateModuleCheker checker(Instance.getASTContext(), + RequireOSSAModules_t(Instance.getSILOptions())); + ModuleRebuildInfo rebuildInfo; + SmallVector allDeps; + std::unique_ptr moduleBuffer; + if (checker.swiftModuleIsUpToDate(outputPath, rebuildInfo, allDeps, moduleBuffer)) { + if (Instance.getASTContext().LangOpts.EnableSkipExplicitInterfaceModuleBuildRemarks) { + Instance.getDiags().diagnose(SourceLoc(), + diag::explicit_interface_build_skipped, outputPath); + } + return false; + } + // Read out the compiler version. llvm::BumpPtrAllocator alloc; llvm::StringSaver ArgSaver(alloc); diff --git a/test/ModuleInterface/repeated-explicit-interface-build-nop.swiftinterface b/test/ModuleInterface/repeated-explicit-interface-build-nop.swiftinterface new file mode 100644 index 0000000000000..61ea233981188 --- /dev/null +++ b/test/ModuleInterface/repeated-explicit-interface-build-nop.swiftinterface @@ -0,0 +1,14 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: -parse-stdlib + +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -compile-module-from-interface -module-name ExplicitModule -explicit-interface-module-build -o %/t/ExplicitModule.swiftmodule %s + +// RUN: %target-swift-frontend -compile-module-from-interface -module-name ExplicitModule -explicit-interface-module-build -o %/t/ExplicitModule.swiftmodule %s -Rskip-explicit-interface-build 2>&1 | %FileCheck %s + +import Swift +extension Int { + public static var fortytwo: Int = 42 +} + +// CHECK: :0: remark: Skipped rebuilding module at {{.*}}ExplicitModule.swiftmodule - up-to-date \ No newline at end of file From 5b88b966b90c230239910e60cc31bcbbfaf33501 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 12 Aug 2022 13:26:53 -0700 Subject: [PATCH 158/491] [Concurrency] Apply `@preconcurrency` to typealiases at the point of use. When referencing a `@preconcurrency` typealias from code that does not require strict concurrency, strip off `@Sendable` and global actor types. This is consistent with references to functions/properties/etc. that are `@preconcurrency`. Fixes https://github.com/apple/swift/issues/60487, rdar://98343624. --- lib/Sema/TypeCheckType.cpp | 47 ++++++++++++++++--- .../preconcurrency_typealias.swift | 34 ++++++++++++++ 2 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 test/Concurrency/preconcurrency_typealias.swift diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index d0f63ee3a3c3e..0877bd29b09ba 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -286,6 +286,27 @@ static Type getIdentityOpaqueTypeArchetypeType( return OpaqueTypeArchetypeType::get(opaqueDecl, interfaceType, subs); } +/// Adjust the underlying type of a typealias within the given context to +/// account for @preconcurrency. +static Type adjustTypeAliasTypeInContext( + Type type, TypeAliasDecl *aliasDecl, DeclContext *fromDC) { + if (!aliasDecl->preconcurrency()) + return type; + + if (contextRequiresStrictConcurrencyChecking( + fromDC, + [](const AbstractClosureExpr *closure) { + return closure->getType(); + }, + [](const ClosureExpr *closure) { + return closure->isIsolatedByPreconcurrency(); + })) + return type; + + return type->stripConcurrency( + /*recurse=*/true, /*dropGlobalActor=*/true); +} + Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl, DeclContext *foundDC, bool isSpecialized) const { @@ -307,6 +328,13 @@ Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl, return genericParam->getDeclaredInterfaceType(); } + /// Call this function before returning the underlying type of a typealias, + /// to adjust its type for concurrency. + auto adjustAliasType = [&](Type type) -> Type { + return adjustTypeAliasTypeInContext( + type, cast(typeDecl), fromDC); + }; + if (!isSpecialized) { // If we are referring to a type within its own context, and we have either // a generic type with no generic arguments or a non-generic type, use the @@ -342,9 +370,9 @@ Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl, if (ugAliasDecl == aliasDecl) { if (getStage() == TypeResolutionStage::Structural && aliasDecl->getUnderlyingTypeRepr() != nullptr) { - return aliasDecl->getStructuralType(); + return adjustAliasType(aliasDecl->getStructuralType()); } - return aliasDecl->getDeclaredInterfaceType(); + return adjustAliasType(aliasDecl->getDeclaredInterfaceType()); } extendedType = unboundGeneric->getParent(); @@ -356,9 +384,9 @@ Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl, if (aliasType->getDecl() == aliasDecl) { if (getStage() == TypeResolutionStage::Structural && aliasDecl->getUnderlyingTypeRepr() != nullptr) { - return aliasDecl->getStructuralType(); + return adjustAliasType(aliasDecl->getStructuralType()); } - return aliasDecl->getDeclaredInterfaceType(); + return adjustAliasType(aliasDecl->getDeclaredInterfaceType()); } extendedType = aliasType->getParent(); continue; @@ -381,9 +409,9 @@ Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl, // Otherwise, return the appropriate type. if (getStage() == TypeResolutionStage::Structural && aliasDecl->getUnderlyingTypeRepr() != nullptr) { - return aliasDecl->getStructuralType(); + return adjustAliasType(aliasDecl->getStructuralType()); } - return aliasDecl->getDeclaredInterfaceType(); + return adjustAliasType(aliasDecl->getDeclaredInterfaceType()); } // When a nominal type used outside its context, return the unbound @@ -1591,6 +1619,12 @@ static Type resolveNestedIdentTypeComponent(TypeResolution resolution, AssociatedTypeDecl *inferredAssocType) { bool hasUnboundOpener = !!resolution.getUnboundTypeOpener(); + // Type aliases might require adjustment due to @preconcurrency. + if (auto aliasDecl = dyn_cast(member)) { + memberType = adjustTypeAliasTypeInContext( + memberType, aliasDecl, resolution.getDeclContext()); + } + if (options.contains(TypeResolutionFlags::SilenceErrors)) { if (TypeChecker::isUnsupportedMemberTypeAccess(parentTy, member, hasUnboundOpener) @@ -4493,6 +4527,7 @@ class ExistentialTypeVisitor } } else if (auto *alias = dyn_cast_or_null(comp->getBoundDecl())) { auto type = Type(alias->getDeclaredInterfaceType()->getDesugaredType()); + // If this is a type alias to a constraint type, the type // alias name must be prefixed with 'any' to be used as an // existential type. diff --git a/test/Concurrency/preconcurrency_typealias.swift b/test/Concurrency/preconcurrency_typealias.swift new file mode 100644 index 0000000000000..6233594c07d23 --- /dev/null +++ b/test/Concurrency/preconcurrency_typealias.swift @@ -0,0 +1,34 @@ +// RUN: %target-swift-frontend -typecheck -verify %s +// REQUIRES: concurrency + +@preconcurrency @MainActor func f() { } +// expected-note@-1 2{{calls to global function 'f()' from outside of its actor context are implicitly asynchronous}} + +@preconcurrency typealias FN = @Sendable () -> Void + +struct Outer { + @preconcurrency typealias FN = @Sendable () -> Void +} + +func test() { + var _: Outer.FN = { + f() + } + + var _: FN = { + f() + print("Hello") + } +} + +@available(SwiftStdlib 5.1, *) +func testAsync() async { + var _: Outer.FN = { + f() // expected-error{{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}} + } + + var _: FN = { + f() // expected-error{{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}} + print("Hello") + } +} From 2fbdad72706b732d4f98a18d5789d20b302394be Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 16 Aug 2022 17:04:25 -0700 Subject: [PATCH 159/491] Don't perform `@preconcurrency` typealias adjustments in `@preconcurrency` decls When a `@preconcurrency` typealias is used within the type of a `@preconcurrency` declaration, such as a function, do not strip concurrency-related types, because the stripping will happen in the outer declaration. Fixes https://github.com/apple/swift/issues/60488. --- lib/Sema/TypeCheckDecl.cpp | 14 ++++++++++++- lib/Sema/TypeCheckType.cpp | 17 ++++++++++++--- lib/Sema/TypeCheckType.h | 3 +++ .../preconcurrency_typealias.swift | 21 +++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index b4b0e990393b1..9f910c1ebe39b 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1826,6 +1826,8 @@ UnderlyingTypeRequest::evaluate(Evaluator &evaluator, TypeResolutionOptions options((typeAlias->getGenericParams() ? TypeResolverContext::GenericTypeAliasDecl : TypeResolverContext::TypeAliasDecl)); + if (typeAlias->preconcurrency()) + options |= TypeResolutionFlags::Preconcurrency; // This can happen when code completion is attempted inside // of typealias underlying type e.g. `typealias F = () -> Int#^TOK^#` @@ -2091,8 +2093,11 @@ ResultTypeRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { : ErrorType::get(ctx)); } - const auto options = + auto options = TypeResolutionOptions(TypeResolverContext::FunctionResult); + if (decl->preconcurrency()) + options |= TypeResolutionFlags::Preconcurrency; + auto *const dc = decl->getInnermostDeclContext(); return TypeResolution::forInterface(dc, options, /*unboundTyOpener*/ nullptr, @@ -2193,6 +2198,13 @@ static Type validateParameterType(ParamDecl *decl) { options = TypeResolutionOptions(TypeResolverContext::EnumElementDecl); } + // Set the "preconcurrency" flag if this is a parameter of a preconcurrency + // declaration. + if (auto decl = dc->getAsDecl()) { + if (decl->preconcurrency()) + options |= TypeResolutionFlags::Preconcurrency; + } + // If the element is a variadic parameter, resolve the parameter type as if // it were in non-parameter position, since we want functions to be // @escaping in this case. diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 0877bd29b09ba..d35ab74bd9e85 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -289,10 +289,20 @@ static Type getIdentityOpaqueTypeArchetypeType( /// Adjust the underlying type of a typealias within the given context to /// account for @preconcurrency. static Type adjustTypeAliasTypeInContext( - Type type, TypeAliasDecl *aliasDecl, DeclContext *fromDC) { + Type type, TypeAliasDecl *aliasDecl, DeclContext *fromDC, + TypeResolutionOptions options) { + // If we are in a @preconcurrency declaration, don't adjust the types of + // type aliases. + if (options.contains(TypeResolutionFlags::Preconcurrency)) + return type; + + // If the type alias itself isn't marked with @preconcurrency, don't + // adjust the type. if (!aliasDecl->preconcurrency()) return type; + // Only adjust the type within a strict concurrency context, so we don't + // change the types as seen by code that hasn't adopted concurrency. if (contextRequiresStrictConcurrencyChecking( fromDC, [](const AbstractClosureExpr *closure) { @@ -332,7 +342,7 @@ Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl, /// to adjust its type for concurrency. auto adjustAliasType = [&](Type type) -> Type { return adjustTypeAliasTypeInContext( - type, cast(typeDecl), fromDC); + type, cast(typeDecl), fromDC, options); }; if (!isSpecialized) { @@ -1622,7 +1632,8 @@ static Type resolveNestedIdentTypeComponent(TypeResolution resolution, // Type aliases might require adjustment due to @preconcurrency. if (auto aliasDecl = dyn_cast(member)) { memberType = adjustTypeAliasTypeInContext( - memberType, aliasDecl, resolution.getDeclContext()); + memberType, aliasDecl, resolution.getDeclContext(), + resolution.getOptions()); } if (options.contains(TypeResolutionFlags::SilenceErrors)) { diff --git a/lib/Sema/TypeCheckType.h b/lib/Sema/TypeCheckType.h index 398a609681a8d..ea40a524e23be 100644 --- a/lib/Sema/TypeCheckType.h +++ b/lib/Sema/TypeCheckType.h @@ -67,6 +67,9 @@ enum class TypeResolutionFlags : uint16_t { /// Needed to enforce that \c any P does not resolve to a /// parameterized existential with an opaque type constraint. DisallowOpaqueTypes = 1 << 9, + + /// We are in a `@preconcurrency` declaration. + Preconcurrency = 1 << 10, }; /// Type resolution contexts that require special handling. diff --git a/test/Concurrency/preconcurrency_typealias.swift b/test/Concurrency/preconcurrency_typealias.swift index 6233594c07d23..fc4f302474a1a 100644 --- a/test/Concurrency/preconcurrency_typealias.swift +++ b/test/Concurrency/preconcurrency_typealias.swift @@ -10,6 +10,15 @@ struct Outer { @preconcurrency typealias FN = @Sendable () -> Void } +@preconcurrency func preconcurrencyFunc(callback: FN) {} + +func usage() { +} + +func usageAsync() async { +} + + func test() { var _: Outer.FN = { f() @@ -19,6 +28,12 @@ func test() { f() print("Hello") } + + var mutableVariable = 0 + preconcurrencyFunc { + mutableVariable += 1 // no sendable warning + } + mutableVariable += 1 } @available(SwiftStdlib 5.1, *) @@ -31,4 +46,10 @@ func testAsync() async { f() // expected-error{{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}} print("Hello") } + + var mutableVariable = 0 + preconcurrencyFunc { + mutableVariable += 1 // expected-warning{{mutation of captured var 'mutableVariable' in concurrently-executing code; this is an error in Swift 6}} + } + mutableVariable += 1 } From 5299326be6bf853269ee0e58fc4c005cbc1b06ea Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 16 Aug 2022 21:48:58 -0700 Subject: [PATCH 160/491] Remove debris from test case --- test/Concurrency/preconcurrency_typealias.swift | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/Concurrency/preconcurrency_typealias.swift b/test/Concurrency/preconcurrency_typealias.swift index fc4f302474a1a..1ec75aba3ab5b 100644 --- a/test/Concurrency/preconcurrency_typealias.swift +++ b/test/Concurrency/preconcurrency_typealias.swift @@ -12,13 +12,6 @@ struct Outer { @preconcurrency func preconcurrencyFunc(callback: FN) {} -func usage() { -} - -func usageAsync() async { -} - - func test() { var _: Outer.FN = { f() From 7fc8377e1cfb94ddf5175ebbec1ec25c1739001a Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 17 Aug 2022 15:21:51 +0300 Subject: [PATCH 161/491] Gardening: Migrate test suite to GH issues: Constraints (1/5) --- test/Constraints/ErrorBridging.swift | 4 +++- .../array_literal_local_array.swift | 4 +++- test/Constraints/assignment.swift | 16 +++++++------ test/Constraints/associated_types.swift | 18 +++++++-------- test/Constraints/availability.swift | 6 ++--- test/Constraints/bridging.swift | 20 ++++++++-------- test/Constraints/casts_objc.swift | 5 ++-- test/Constraints/diag_ambiguities.swift | 10 ++++---- test/Constraints/dictionary_literal.swift | 4 +++- test/Constraints/dynamic_lookup.swift | 18 ++++++++++----- test/Constraints/enum_cases.swift | 3 ++- test/Constraints/function_conversion.swift | 18 ++++++++------- test/Constraints/gather_all_adjacencies.swift | 4 +++- .../generic_super_constraint.swift | 2 +- test/Constraints/lvalues.swift | 9 ++++---- test/Constraints/overload.swift | 5 ++-- test/Constraints/protocols.swift | 20 ++++++++-------- test/Constraints/result_builder.swift | 4 +++- test/Constraints/result_builder_diags.swift | 8 ++++--- test/Constraints/sr10324.swift | 2 ++ test/Constraints/sr10595.swift | 2 ++ test/Constraints/sr10728.swift | 2 ++ test/Constraints/sr10757.swift | 2 +- test/Constraints/sr10906.swift | 2 ++ test/Constraints/sr10914.swift | 2 ++ test/Constraints/sr12277.swift | 2 ++ test/Constraints/sr12365.swift | 2 ++ test/Constraints/sr12383.swift | 2 ++ test/Constraints/sr12520.swift | 2 ++ test/Constraints/sr12964.swift | 2 ++ test/Constraints/sr13183.swift | 3 ++- test/Constraints/sr13815.swift | 2 +- test/Constraints/sr13951.swift | 2 ++ test/Constraints/sr13992.swift | 2 +- test/Constraints/sr15742.swift | 2 +- test/Constraints/sr2705.swift | 2 ++ test/Constraints/sr4664.swift | 2 ++ test/Constraints/sr5252.swift | 2 ++ test/Constraints/sr7098.swift | 2 ++ test/Constraints/sr7425.swift | 2 ++ test/Constraints/sr7875.swift | 2 ++ test/Constraints/sr7884.swift | 6 +++-- test/Constraints/sr9102.swift | 2 ++ test/Constraints/sr9626.swift | 2 ++ test/Constraints/subscript.swift | 23 +++++++++++-------- test/Constraints/super_constructor.swift | 10 ++++---- test/Constraints/tuple.swift | 11 +++++---- .../type_inference_from_default_exprs.swift | 2 +- test/Constraints/type_of.swift | 9 +++++--- .../valid_pointer_conversions.swift | 17 +++++++++----- .../without_actually_escaping.swift | 2 +- 51 files changed, 199 insertions(+), 108 deletions(-) diff --git a/test/Constraints/ErrorBridging.swift b/test/Constraints/ErrorBridging.swift index 86bfd5cfe0b4c..108a7e868b746 100644 --- a/test/Constraints/ErrorBridging.swift +++ b/test/Constraints/ErrorBridging.swift @@ -43,7 +43,9 @@ let e1fix = ns1 as FooError // expected-error {{'NSError' is not convertible to let esub = ns1 as Error let esub2 = ns1 as? Error // expected-warning{{conditional cast from 'NSError' to 'any Error' always succeeds}} -// SR-1562 / rdar://problem/26370984 +// rdar://problem/26370984 +// https://github.com/apple/swift/issues/44171 + enum MyError : Error { case failed } diff --git a/test/Constraints/array_literal_local_array.swift b/test/Constraints/array_literal_local_array.swift index 09e4d1169df98..c7a02f0b33128 100644 --- a/test/Constraints/array_literal_local_array.swift +++ b/test/Constraints/array_literal_local_array.swift @@ -1,6 +1,8 @@ // RUN: %target-typecheck-verify-swift -// SR-9611: Array type locally interferes with array literals. +/// https://github.com/apple/swift/issues/52057 +/// `Array` type locally interferes with array literals + struct Array { } func foo() { diff --git a/test/Constraints/assignment.swift b/test/Constraints/assignment.swift index d8e1b19b726e6..c8bbb41617787 100644 --- a/test/Constraints/assignment.swift +++ b/test/Constraints/assignment.swift @@ -71,18 +71,20 @@ func f23798944() { } } -.sr_3506 = 0 // expected-error {{type 'Int' has no member 'sr_3506'}} - -// SR-1553 +// https://github.com/apple/swift/issues/46094 +do { + .x = 0 // expected-error {{type 'Int' has no member 'x'}} +} +// https://github.com/apple/swift/issues/44162 func returnsVoid() {} _ = returnsVoid() // expected-warning {{using '_' to ignore the result of a Void-returning function is redundant}}{{1-5=}} -// SR-14003 -class SR14003 { - var callback: ((SR14003) -> Void)! +// https://github.com/apple/swift/issues/56396 +class С_56396 { + var callback: ((С_56396) -> Void)! func setCallback(_ callback: @escaping (Self) -> Void) { - self.callback = callback // expected-error {{cannot assign value of type '(Self) -> Void' to type '((SR14003) -> Void)?'}} + self.callback = callback // expected-error {{cannot assign value of type '(Self) -> Void' to type '((С_56396) -> Void)?'}} } } diff --git a/test/Constraints/associated_types.swift b/test/Constraints/associated_types.swift index 8b368df98c5c2..6996cc93e1f2f 100644 --- a/test/Constraints/associated_types.swift +++ b/test/Constraints/associated_types.swift @@ -32,13 +32,13 @@ func owl3() { Owl().eat(Mince(), with:Spoon()) } -// "Can't access associated types through class-constrained generic parameters" -// (https://bugs.swift.org/browse/SR-726) +// https://github.com/apple/swift/issues/43341 +// Can't access associated types through class-constrained generic parameters func spoon(_ s: S) { let _: S.Runcee? } -// SR-4143 +// https://github.com/apple/swift/issues/46726 protocol SameTypedDefault { associatedtype X @@ -109,15 +109,15 @@ struct UsesSameTypedDefaultDerivedWithoutSatisfyingReqts: SameTypedDefaultDerive static var y: YType { return YType() } } -// SR-12199 +// https://github.com/apple/swift/issues/54624 -protocol SR_12199_P1 { +protocol P1_54624 { associatedtype Assoc // expected-note {{'Assoc' declared here}} } -enum SR_12199_E {} +enum E_54624 {} -protocol SR_12199_P2: SR_12199_P1 where Assoc == SR_12199_E { - associatedtype Assoc: SR_12199_E // expected-error {{type 'Self.Assoc' constrained to non-protocol, non-class type 'SR_12199_E'}} - // expected-warning@-1 {{redeclaration of associated type 'Assoc' from protocol 'SR_12199_P1' is better expressed as a 'where' clause on the protocol}} +protocol P2_54624: P1_54624 where Assoc == E_54624 { + associatedtype Assoc: E_54624 // expected-error {{type 'Self.Assoc' constrained to non-protocol, non-class type 'E_54624'}} + // expected-warning@-1 {{redeclaration of associated type 'Assoc' from protocol 'P1_54624' is better expressed as a 'where' clause on the protocol}} } diff --git a/test/Constraints/availability.swift b/test/Constraints/availability.swift index 24e07b4b97af8..2b8be52b55bc8 100644 --- a/test/Constraints/availability.swift +++ b/test/Constraints/availability.swift @@ -38,8 +38,8 @@ func test_contextual_member_with_availability() { @available(*, unavailable) func unavailableFunction(_ x: Int) -> Bool { true } // expected-note {{'unavailableFunction' has been explicitly marked unavailable here}} -// SR-13260: Availability checking not working in the where clause of a for -// loop. -func sr13260(_ arr: [Int]) { +/// https://github.com/apple/swift/issues/55700 +/// Availability checking not working in the `where` clause of a `for` loop +func f_55700(_ arr: [Int]) { for x in arr where unavailableFunction(x) {} // expected-error {{'unavailableFunction' is unavailable}} } diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift index 8e499f665e2c2..b7f2dbb2c8be9 100644 --- a/test/Constraints/bridging.swift +++ b/test/Constraints/bridging.swift @@ -395,15 +395,17 @@ func rdar60501780() { } } -// SR-15161 -func SR15161_as(e: Error?) { - let _ = e as? NSError // Ok -} +// https://github.com/apple/swift/issues/57484 +do { + func as1(e: Error?) { + let _ = e as? NSError // Ok + } -func SR15161_is(e: Error?) { - _ = e is NSError // expected-warning{{checking a value with optional type '(any Error)?' against type 'NSError' succeeds whenever the value is non-nil; did you mean to use '!= nil'?}} -} + func as2(e: Error?) { + let _ = e as! NSError // expected-warning{{forced cast from '(any Error)?' to 'NSError' only unwraps and bridges; did you mean to use '!' with 'as'?}} + } -func SR15161_as_1(e: Error?) { - let _ = e as! NSError // expected-warning{{forced cast from '(any Error)?' to 'NSError' only unwraps and bridges; did you mean to use '!' with 'as'?}} + func is1(e: Error?) { + _ = e is NSError // expected-warning{{checking a value with optional type '(any Error)?' against type 'NSError' succeeds whenever the value is non-nil; did you mean to use '!= nil'?}} + } } diff --git a/test/Constraints/casts_objc.swift b/test/Constraints/casts_objc.swift index 5f03476384d35..e9630761472e2 100644 --- a/test/Constraints/casts_objc.swift +++ b/test/Constraints/casts_objc.swift @@ -43,8 +43,9 @@ func test(_ a : CFString!, b : CFString) { let r22507759: NSObject! = "test" as NSString let _: NSString! = unsafeDowncast(r22507759) // expected-error {{missing argument for parameter 'to' in call}} -// rdar://problem/29496775 / SR-3319 -func sr3319(f: CGFloat, n: NSNumber) { +// rdar://problem/29496775 +// https://github.com/apple/swift/issues/45907 +func f_45907(f: CGFloat, n: NSNumber) { let _ = [f].map { $0 as NSNumber } let _ = [n].map { $0 as! CGFloat } } diff --git a/test/Constraints/diag_ambiguities.swift b/test/Constraints/diag_ambiguities.swift index 07436d53644c3..cb328fb0d5ed4 100644 --- a/test/Constraints/diag_ambiguities.swift +++ b/test/Constraints/diag_ambiguities.swift @@ -42,7 +42,8 @@ func rdar29907555(_ value: Any!) -> String { // expected-note@-2 {{provide a default value to avoid this warning}} } -struct SR3715 { +// https://github.com/apple/swift/issues/46300 +struct S_46300 { var overloaded: Int! // expected-note {{implicitly unwrapped property 'overloaded' declared here}} func overloaded(_ x: Int) {} @@ -73,8 +74,9 @@ class MoviesViewController { } } -// SR-15053 -func SR15053(_ a: T, _ b: T) -> T { +// https://github.com/apple/swift/issues/57380 + +func f1_57380(_ a: T, _ b: T) -> T { (a + b) / 2 // expected-note {{overloads for '/' exist with these partially matching parameter lists: (Int, Int)}} // expected-error@-1 {{binary operator '/' cannot be applied to operands of type 'T' and 'Int'}} } @@ -89,7 +91,7 @@ func %% (_ lhs: Float, _ rhs: Float) -> Float { lhs / rhs } -func SR15053(_ a: T, _ b: T) { +func f2_57380(_ a: T, _ b: T) { (a + b) %% 2 // expected-error {{cannot convert value of type 'T' to expected argument type 'Int'}} } diff --git a/test/Constraints/dictionary_literal.swift b/test/Constraints/dictionary_literal.swift index d73270f8cf30b..d9a28218c5764 100644 --- a/test/Constraints/dictionary_literal.swift +++ b/test/Constraints/dictionary_literal.swift @@ -150,7 +150,9 @@ func testDefaultExistentials() { // expected-error@-1{{heterogeneous collection literal could only be inferred to '[AnyHashable : String]'}} } -// SR-4952, rdar://problem/32330004 - Assertion failure during swift::ASTVisitor<::FailureDiagnosis,...>::visit +/// rdar://problem/32330004 +/// https://github.com/apple/swift/issues/47529 +/// Assertion failure during `swift::ASTVisitor<::FailureDiagnosis,...>::visit` func rdar32330004_1() -> [String: Any] { return ["a""one": 1, "two": 2, "three": 3] // expected-note {{did you mean to use a dictionary literal instead?}} // expected-error@-1 {{expected ',' separator}} diff --git a/test/Constraints/dynamic_lookup.swift b/test/Constraints/dynamic_lookup.swift index b5df9d6df7438..e2d01758fdcc7 100644 --- a/test/Constraints/dynamic_lookup.swift +++ b/test/Constraints/dynamic_lookup.swift @@ -408,22 +408,25 @@ func testAnyObjectAmbiguity(_ x: AnyObject) { _ = x.ambiguousMethodParam // expected-error {{ambiguous use of 'ambiguousMethodParam'}} _ = x.unambiguousMethodParam - // SR-12799: Don't emit a "single-element" tuple error. + // https://github.com/apple/swift/issues/55244 + // Don't emit a single-element tuple error. _ = x[singleCandidate: 0] _ = x[ambiguousSubscript: 0] // expected-error {{ambiguous use of 'subscript(ambiguousSubscript:)'}} _ = x[ambiguousSubscript: 0] as Int _ = x[ambiguousSubscript: 0] as String - // SR-8611: Make sure we can coalesce subscripts with the same types and - // selectors through AnyObject lookup. + // https://github.com/apple/swift/issues/51126 + // Make sure we can coalesce subscripts with the same types and selectors + // through AnyObject lookup. _ = x[unambiguousSubscript: ""] // But not if they have different selectors. _ = x[differentSelectors: 0] // expected-error {{ambiguous use of 'subscript(differentSelectors:)}} } -// SR-11648 +// https://github.com/apple/swift/issues/54059 + class HasMethodWithDefault { @objc func hasDefaultParam(_ x: Int = 0) {} } @@ -432,7 +435,9 @@ func testAnyObjectWithDefault(_ x: AnyObject) { x.hasDefaultParam() } -// SR-11829: Don't perform dynamic lookup for callAsFunction. +/// https://github.com/apple/swift/issues/54241 +/// Don't perform dynamic lookup for `callAsFunction`. + class ClassWithObjcCallAsFunction { @objc func callAsFunction() {} } @@ -462,6 +467,7 @@ func test_dynamic_subscript_accepts_type_name_argument() { func testAnyObjectConstruction(_ x: AnyObject) { AnyObject() // expected-error {{type 'AnyObject' cannot be instantiated}} - // FIXME(SR-15210): This should also be rejected. + // https://github.com/apple/swift/issues/57532 + // FIXME: This should also be rejected. _ = type(of: x).init() } diff --git a/test/Constraints/enum_cases.swift b/test/Constraints/enum_cases.swift index 8ff8f5a79d446..6d925378351a4 100644 --- a/test/Constraints/enum_cases.swift +++ b/test/Constraints/enum_cases.swift @@ -172,7 +172,8 @@ struct EnumElementPatternFromContextualType { } } -// SR-14408 +// https://github.com/apple/swift/issues/56765 + enum CompassPoint { case North(Int) case South diff --git a/test/Constraints/function_conversion.swift b/test/Constraints/function_conversion.swift index 44ed0bd62f369..c828835308e76 100644 --- a/test/Constraints/function_conversion.swift +++ b/test/Constraints/function_conversion.swift @@ -82,11 +82,13 @@ func rdar_59703585() { // expected-error@-1 {{cannot assign value of type '(UnsafePointer, UnsafeMutableRawPointer?) -> ()' to type 'Fn?' (aka 'Optional<@convention(c) (Optional>, Optional) -> ()>')}} } -// SR-14869 -var v1: (inout Float) -> () -v1 = { (_: inout Int) in } -// expected-error@-1{{cannot assign value of type '(inout Int) -> ()' to type '(inout Float) -> ()'}} - -var v2: (Int , inout Float) -> () -v2 = { (_: Int, _: inout Int) in } -// expected-error@-1{{cannot assign value of type '(Int, inout Int) -> ()' to type '(Int, inout Float) -> ()'}} +// https://github.com/apple/swift/issues/57216 +do { + var v1: (inout Float) -> () + v1 = { (_: inout Int) in } + // expected-error@-1{{cannot assign value of type '(inout Int) -> ()' to type '(inout Float) -> ()'}} + + var v2: (Int , inout Float) -> () + v2 = { (_: Int, _: inout Int) in } + // expected-error@-1{{cannot assign value of type '(Int, inout Int) -> ()' to type '(Int, inout Float) -> ()'}} +} diff --git a/test/Constraints/gather_all_adjacencies.swift b/test/Constraints/gather_all_adjacencies.swift index b4587dd351d6b..0628b571bf265 100644 --- a/test/Constraints/gather_all_adjacencies.swift +++ b/test/Constraints/gather_all_adjacencies.swift @@ -1,6 +1,8 @@ // RUN: %target-swift-frontend -typecheck %s -// SR-5120 / rdar://problem/32618740 +// rdar://problem/32618740 +// https://github.com/apple/swift/issues/47696 + protocol InitCollection: Collection { init(_ array: [Iterator.Element]) } diff --git a/test/Constraints/generic_super_constraint.swift b/test/Constraints/generic_super_constraint.swift index 9f2c46e021a9f..26d4dcea6a968 100644 --- a/test/Constraints/generic_super_constraint.swift +++ b/test/Constraints/generic_super_constraint.swift @@ -14,7 +14,7 @@ func bar(_ x: U, y: T) -> (Derived, Int) where U: Base, U: Derived { return (x, y) } -// SR-7551 captures a crash on this code. +// https://github.com/apple/swift/issues/50093 captures a crash on this code. class IntegerClass : ExpressibleByIntegerLiteral, Equatable { required init(integerLiteral value: Int) { } static func ==(lhs: IntegerClass, rhs: IntegerClass) -> Bool { return true } diff --git a/test/Constraints/lvalues.swift b/test/Constraints/lvalues.swift index 106220a454dcd..f4f2f38b105cf 100644 --- a/test/Constraints/lvalues.swift +++ b/test/Constraints/lvalues.swift @@ -200,9 +200,9 @@ func testImmutableUnsafePointer(_ p: UnsafePointer) { p[0] = 1 // expected-error {{cannot assign through subscript: subscript is get-only}} } -// Inferring closure param type to -// inout crashes compiler -let g = { x in f0(x) } // expected-error{{passing value of type 'Int' to an inout parameter requires explicit '&'}} {{19-19=&}} +/// https://github.com/apple/swift/issues/42633 +/// Inferring closure param type to `inout` crashes compiler +let _ = { x in f0(x) } // expected-error{{passing value of type 'Int' to an inout parameter requires explicit '&'}} {{19-19=&}} // Crash with optional closure taking inout func rdar17245353() { @@ -242,7 +242,8 @@ func wump(to: T, _ body: (G) -> ()) {} wump(to: 0, { $0[] = 0 }) // expected-error@-1 {{missing argument for parameter #1 in call}} -// SR-13732 +// https://github.com/apple/swift/issues/56129 + extension MutableCollection { public mutating func writePrefix(from source: inout I) -> (writtenCount: Int, afterLastWritten: Index) diff --git a/test/Constraints/overload.swift b/test/Constraints/overload.swift index c2895effbf0c3..593d431b48955 100644 --- a/test/Constraints/overload.swift +++ b/test/Constraints/overload.swift @@ -194,8 +194,9 @@ func overloadedMethod() {} // expected-note {{in call to function 'overloaded overloadedMethod() // expected-error@-1 {{generic parameter 'T' could not be inferred}} -// Ensure we select the overload of '??' returning T? rather than T. -func SR3817(_ d: [String : Any], _ s: String, _ t: String) -> Any { +/// https://github.com/apple/swift/issues/46402 +/// Ensure we select the overload of `??` returning `T?` rather than `T`. +func f_46402(_ d: [String : Any], _ s: String, _ t: String) -> Any { if let r = d[s] ?? d[t] { return r } else { diff --git a/test/Constraints/protocols.swift b/test/Constraints/protocols.swift index 386f7959bd408..e5e1d91448ee6 100644 --- a/test/Constraints/protocols.swift +++ b/test/Constraints/protocols.swift @@ -416,8 +416,9 @@ func rdar_50512161() { } } -// SR-11609: Compiler crash on missing conformance for default param -func test_sr_11609() { +// https://github.com/apple/swift/issues/54017 +// Compiler crash on missing conformance for default param +do { func foo(_ x: T = .init()) -> T { x } // expected-note {{where 'T' = 'String'}} let _: String = foo() // expected-error@-1 {{local function 'foo' requires that 'String' conform to 'Initable'}} @@ -520,14 +521,15 @@ case test(cond: Bool, v: Int64) } } -// SR-15970 -protocol SR15970_P {} -struct SR15970_S {} +// https://github.com/apple/swift/issues/58231 -func SR15970_F(x: Int) -> SR15970_P { - return SR15970_S() // expected-error{{return expression of type 'SR15970_S' does not conform to 'SR15970_P'}} +protocol P_58231 {} +struct S_58231 {} + +func f1_58231(x: Int) -> P_58231 { + return S_58231() // expected-error{{return expression of type 'S_58231' does not conform to 'P_58231'}} } -func SR15970_F1(x: Int) -> SR15970_P? { - return SR15970_S() // expected-error{{return expression of type 'SR15970_S' does not conform to 'SR15970_P'}} +func f2_58231(x: Int) -> P_58231? { + return S_58231() // expected-error{{return expression of type 'S_58231' does not conform to 'P_58231'}} } diff --git a/test/Constraints/result_builder.swift b/test/Constraints/result_builder.swift index 17906dfe2906b..fd8aa89c91032 100644 --- a/test/Constraints/result_builder.swift +++ b/test/Constraints/result_builder.swift @@ -217,7 +217,9 @@ print(mbuilders.methodBuilder(13)) // CHECK: ("propertyBuilder", 12) print(mbuilders.propertyBuilder) -// SR-11439: Operator builders +// https://github.com/apple/swift/issues/53840 +// Operator builders + infix operator ^^^ func ^^^ (lhs: Int, @TupleBuilder rhs: (Int) -> (String, Int)) -> (String, Int) { return rhs(lhs) diff --git a/test/Constraints/result_builder_diags.swift b/test/Constraints/result_builder_diags.swift index 04b1cf55972bb..6d25264fbe342 100644 --- a/test/Constraints/result_builder_diags.swift +++ b/test/Constraints/result_builder_diags.swift @@ -232,7 +232,8 @@ func test_56221372() -> some P { }) } -struct SR11440 { +// https://github.com/apple/swift/issues/53841 +struct S_53841 { typealias ReturnsTuple = () -> (T, T) subscript(@TupleBuilder x: ReturnsTuple) -> (ReturnsTuple) -> Void { //expected-note {{in call to 'subscript(_:)'}} return { _ in } @@ -261,8 +262,9 @@ struct SR11440 { func acceptInt(_: Int, _: () -> Void) { } -// SR-11350 crash due to improper recontextualization. -func erroneousSR11350(x: Int) { +// https://github.com/apple/swift/issues/53751 +// Crash due to improper recontextualization. +func erroneous_53751(x: Int) { tuplify(true) { b in 17 x + 25 diff --git a/test/Constraints/sr10324.swift b/test/Constraints/sr10324.swift index 6cacfb2710420..b1e572be451a7 100644 --- a/test/Constraints/sr10324.swift +++ b/test/Constraints/sr10324.swift @@ -2,6 +2,8 @@ // REQUIRES: rdar65007946 +// https://github.com/apple/swift/issues/52724 + struct A { static func * (lhs: A, rhs: A) -> B { return B() } static func * (lhs: B, rhs: A) -> B { return B() } diff --git a/test/Constraints/sr10595.swift b/test/Constraints/sr10595.swift index 377228685fc6c..a6ee0c8a108dc 100644 --- a/test/Constraints/sr10595.swift +++ b/test/Constraints/sr10595.swift @@ -1,5 +1,7 @@ // RUN: %target-swift-frontend -typecheck -verify %s +// https://github.com/apple/swift/issues/52995 + protocol Nested { associatedtype U // expected-note {{protocol requires nested type 'U'; do you want to add it?}} } diff --git a/test/Constraints/sr10728.swift b/test/Constraints/sr10728.swift index c91d85e2298fc..adc0937b49cc2 100644 --- a/test/Constraints/sr10728.swift +++ b/test/Constraints/sr10728.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/53125 + typealias T1 = Int typealias T2 = Float typealias T3 = Bool diff --git a/test/Constraints/sr10757.swift b/test/Constraints/sr10757.swift index 498ae2686d74a..bcabcf18c3fb1 100644 --- a/test/Constraints/sr10757.swift +++ b/test/Constraints/sr10757.swift @@ -1,6 +1,6 @@ // RUN: %target-typecheck-verify-swift -// SR-10757 +// https://github.com/apple/swift/issues/53147 struct Parser { let run: (inout Substring) -> A? diff --git a/test/Constraints/sr10906.swift b/test/Constraints/sr10906.swift index 1903ca3ca4500..c54b67b99494a 100644 --- a/test/Constraints/sr10906.swift +++ b/test/Constraints/sr10906.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/53296 + protocol ViewDataSource: class { func foo() -> [T] } diff --git a/test/Constraints/sr10914.swift b/test/Constraints/sr10914.swift index 4d84d3077d914..12b755dd7a419 100644 --- a/test/Constraints/sr10914.swift +++ b/test/Constraints/sr10914.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/53305 + struct Data { init(_: S) where S.Element == UInt8 { } diff --git a/test/Constraints/sr12277.swift b/test/Constraints/sr12277.swift index 21585076ceb81..5a9ae91030ee6 100644 --- a/test/Constraints/sr12277.swift +++ b/test/Constraints/sr12277.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/54705 + enum Time { case milliseconds(Int) } diff --git a/test/Constraints/sr12365.swift b/test/Constraints/sr12365.swift index 09a97afb320d8..1750da5ce641e 100644 --- a/test/Constraints/sr12365.swift +++ b/test/Constraints/sr12365.swift @@ -1,5 +1,7 @@ // RUN: %target-swift-frontend -typecheck -verify %s +// https://github.com/apple/swift/issues/54799 + public protocol MyProtocol {} public struct MyProtocolImpl: MyProtocol {} diff --git a/test/Constraints/sr12383.swift b/test/Constraints/sr12383.swift index 4262054641438..1bd4e66dcff89 100644 --- a/test/Constraints/sr12383.swift +++ b/test/Constraints/sr12383.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/54820 + protocol Protocol { associatedtype Index: Comparable subscript(bounds: Range) -> Int { get } diff --git a/test/Constraints/sr12520.swift b/test/Constraints/sr12520.swift index 7c075659c0a89..3fae0954e33b4 100644 --- a/test/Constraints/sr12520.swift +++ b/test/Constraints/sr12520.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/54962 + @propertyWrapper @dynamicMemberLookup struct Binding { diff --git a/test/Constraints/sr12964.swift b/test/Constraints/sr12964.swift index b18de10a36f30..cd22ff5d2dbae 100644 --- a/test/Constraints/sr12964.swift +++ b/test/Constraints/sr12964.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/55410 + protocol P {} typealias T = (P) -> Void let x: T! = [1, 2, 3].reversed().reduce() diff --git a/test/Constraints/sr13183.swift b/test/Constraints/sr13183.swift index 2ab0551b36f94..2bf3b7cd58fe3 100644 --- a/test/Constraints/sr13183.swift +++ b/test/Constraints/sr13183.swift @@ -1,6 +1,7 @@ // RUN: %target-typecheck-verify-swift -// SR-13183: Make sure we don't incorrectly split the constraint system without +// https://github.com/apple/swift/issues/55623 +// Make sure we don't incorrectly split the constraint system without // considering that a result builder type var may connect the inside of a // closure body with the enclosing expression. diff --git a/test/Constraints/sr13815.swift b/test/Constraints/sr13815.swift index 64a929c96b1dd..55744e7d604f9 100644 --- a/test/Constraints/sr13815.swift +++ b/test/Constraints/sr13815.swift @@ -1,6 +1,6 @@ // RUN: %target-typecheck-verify-swift -// SR-13815 +// https://github.com/apple/swift/issues/56212 enum E { case foo(String) diff --git a/test/Constraints/sr13951.swift b/test/Constraints/sr13951.swift index 502fbea37b593..9273c90740b03 100644 --- a/test/Constraints/sr13951.swift +++ b/test/Constraints/sr13951.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/56348 + protocol TheProtocol {} struct TheType1: TheProtocol {} diff --git a/test/Constraints/sr13992.swift b/test/Constraints/sr13992.swift index d381cdd0f4117..3e1dfeb4bba00 100644 --- a/test/Constraints/sr13992.swift +++ b/test/Constraints/sr13992.swift @@ -1,6 +1,6 @@ // RUN: %target-typecheck-verify-swift -// SR-13992 +// https://github.com/apple/swift/issues/56387 protocol V {} diff --git a/test/Constraints/sr15742.swift b/test/Constraints/sr15742.swift index 5c75914068b14..8d04d877da002 100644 --- a/test/Constraints/sr15742.swift +++ b/test/Constraints/sr15742.swift @@ -1,6 +1,6 @@ // RUN: %target-swift-frontend -dump-ast %s | %FileCheck %s -// https://bugs.swift.org/browse/SR-15742 +// https://github.com/apple/swift/issues/58019 func fetch() { // CHECK: open_existential_expr implicit type='Void' diff --git a/test/Constraints/sr2705.swift b/test/Constraints/sr2705.swift index a05e700e2109c..89459982ac426 100644 --- a/test/Constraints/sr2705.swift +++ b/test/Constraints/sr2705.swift @@ -1,5 +1,7 @@ // RUN: %target-swift-emit-silgen %s -verify | %FileCheck %s +// https://github.com/apple/swift/issues/45309 + func f(_: () -> T) {} func f(_: @autoclosure () -> T) {} diff --git a/test/Constraints/sr4664.swift b/test/Constraints/sr4664.swift index d3a10fd8f918a..35eb31fbcef87 100644 --- a/test/Constraints/sr4664.swift +++ b/test/Constraints/sr4664.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/47241 + struct M where T : Collection { // expected-note {{where 'T' = 'X.Y'}} static func f(a: T, b: T) -> [E] { } diff --git a/test/Constraints/sr5252.swift b/test/Constraints/sr5252.swift index f5c25622503fb..a31e186d5faf9 100644 --- a/test/Constraints/sr5252.swift +++ b/test/Constraints/sr5252.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/47827 + protocol P {} class Helper {} diff --git a/test/Constraints/sr7098.swift b/test/Constraints/sr7098.swift index 90005f93b1810..ac1e08b8bd441 100644 --- a/test/Constraints/sr7098.swift +++ b/test/Constraints/sr7098.swift @@ -1,6 +1,8 @@ // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s // REQUIRES: objc_interop +// https://github.com/apple/swift/issues/49646 + import Foundation class C : NSObject, NSWobbling { diff --git a/test/Constraints/sr7425.swift b/test/Constraints/sr7425.swift index 4006e8811d273..5a75834a14178 100644 --- a/test/Constraints/sr7425.swift +++ b/test/Constraints/sr7425.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift -swift-version 4 +// https://github.com/apple/swift/issues/49968 + protocol X { var foo: Int { get } var bar: Int { get } diff --git a/test/Constraints/sr7875.swift b/test/Constraints/sr7875.swift index 79745a7e8183b..b60dd962cafbb 100644 --- a/test/Constraints/sr7875.swift +++ b/test/Constraints/sr7875.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/50410 + protocol Proto {} class Base {} class Test : Base, Proto {} diff --git a/test/Constraints/sr7884.swift b/test/Constraints/sr7884.swift index a3dde699869af..d1b1a7eb1e7b0 100644 --- a/test/Constraints/sr7884.swift +++ b/test/Constraints/sr7884.swift @@ -1,7 +1,8 @@ // RUN: %target-typecheck-verify-swift -// SR-7884 +// https://github.com/apple/swift/issues/50419 + func f(_ x: T) -> T { return x } @@ -13,7 +14,8 @@ func f(_ x: T?) -> T? { let r = f(1) let _ = r! // expected-error {{cannot force unwrap value of non-optional type 'Int'}} -// SR-7899 +// https://github.com/apple/swift/issues/50434 + func testLazySequence(_ lazySequence: LazySequence<[Int]>?) { let value = lazySequence?.compactMap({ $0 as? Int }).first // expected-warning {{conditional cast from 'Int' to 'Int' always succeeds}} let _: Int = value! diff --git a/test/Constraints/sr9102.swift b/test/Constraints/sr9102.swift index e92567a5b5eea..5d9959f70ce01 100644 --- a/test/Constraints/sr9102.swift +++ b/test/Constraints/sr9102.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/51599 + func test(_ a: [Int], _ f: ((Int) -> Bool)?) { _ = a.filter(f!) } diff --git a/test/Constraints/sr9626.swift b/test/Constraints/sr9626.swift index 049951ba18619..2ff7fbd2e94de 100644 --- a/test/Constraints/sr9626.swift +++ b/test/Constraints/sr9626.swift @@ -1,5 +1,7 @@ // RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s +// https://github.com/apple/swift/issues/52072 + class BaseClass {} class SubClass: BaseClass {} struct Box { init(_: T.Type) {} } diff --git a/test/Constraints/subscript.swift b/test/Constraints/subscript.swift index 00db94819bc27..82a330e71feef 100644 --- a/test/Constraints/subscript.swift +++ b/test/Constraints/subscript.swift @@ -117,14 +117,17 @@ func r23670252(_ dictionary: [String : AnyObject], someObject: AnyObject) { } -// SR-718 - Type mismatch reported as extraneous parameter -struct SR718 { - subscript(b : Int) -> Int - { return 0 } - subscript(a a : UInt) -> Int { return 0 } -} +// https://github.com/apple/swift/issues/43333 +// Type mismatch reported as extraneous parameter +do { + struct S { + subscript(b : Int) -> Int + { return 0 } + subscript(a a : UInt) -> Int { return 0 } + } -SR718()[a: Int()] // expected-error {{cannot convert value of type 'Int' to expected argument type 'UInt'}} + S()[a: Int()] // expected-error {{cannot convert value of type 'Int' to expected argument type 'UInt'}} +} // rdar://problem/25601561 - Qol: Bad diagnostic for failed assignment from Any to more specific type @@ -166,8 +169,10 @@ func rdar_45819956() { // expected-error@-1 {{cannot pass an inout argument to a subscript; use 'withUnsafeMutablePointer' to explicitly convert argument to a pointer}} } -// rdar://problem/45825806 - [SR-7190] Array-to-pointer in subscript arg crashes compiler -func rdar_45825806() { +// rdar://problem/45825806 +// https://github.com/apple/swift/issues/49738 +// Array-to-pointer in subscript arg crashes compiler +do { struct S { subscript(takesPtr ptr: UnsafePointer) -> Int { get { return 0 } diff --git a/test/Constraints/super_constructor.swift b/test/Constraints/super_constructor.swift index d6976b7ec010f..9d23d076a13f1 100644 --- a/test/Constraints/super_constructor.swift +++ b/test/Constraints/super_constructor.swift @@ -52,15 +52,17 @@ class B { } } -// SR-2484: Bad diagnostic for incorrectly calling private init -class SR_2484 { +/// https://github.com/apple/swift/issues/45089 +/// Bad diagnostic for incorrectly calling private `init` + +class C_45089 { private init() {} // expected-note {{'init()' declared here}} private init(a: Int) {} } -class Impl_2484 : SR_2484 { +class Impl_45089 : C_45089 { init() { - super.init() // expected-error {{'SR_2484' initializer is inaccessible due to 'private' protection level}} + super.init() // expected-error {{'C_45089' initializer is inaccessible due to 'private' protection level}} } } diff --git a/test/Constraints/tuple.swift b/test/Constraints/tuple.swift index 262c3d24f9b1b..968bdb018e3fa 100644 --- a/test/Constraints/tuple.swift +++ b/test/Constraints/tuple.swift @@ -201,8 +201,9 @@ func foo(_ pair: (Int, Int)) -> Victory<(x: Int, y: Int)> { } -// https://bugs.swift.org/browse/SR-596 -// Compiler crashes when accessing a non-existent property of a closure parameter +// https://github.com/apple/swift/issues/43213 +// Compiler crashes when accessing a non-existent property of a closure +// parameter func call(_ f: (C) -> Void) {} func makeRequest() { call { obj in @@ -242,7 +243,9 @@ let _ = (x, (y, 0)) takesRValue((x, (y, 0))) takesAny((x, (y, 0))) -// SR-2600 - Closure cannot infer tuple parameter names +// https://github.com/apple/swift/issues/45205 +// Closure cannot infer tuple parameter names + typealias Closure = ((a: A, b: B)) -> String func invoke(a: A, b: B, _ closure: Closure) { @@ -321,7 +324,7 @@ struct DupLabelSubscript { let dupLabelSubscriptStruct = DupLabelSubscript() let _ = dupLabelSubscriptStruct[foo: 5, foo: 5] // ok -// SR-12869 +// https://github.com/apple/swift/issues/55316 var dict: [String: (Int, Int)] = [:] let bignum: Int64 = 1337 diff --git a/test/Constraints/type_inference_from_default_exprs.swift b/test/Constraints/type_inference_from_default_exprs.swift index a4d7f81b8fa2c..07a4e595d1795 100644 --- a/test/Constraints/type_inference_from_default_exprs.swift +++ b/test/Constraints/type_inference_from_default_exprs.swift @@ -178,7 +178,7 @@ func test_magic_defaults() { let _: String = generic_with_magic() } -// SR-16069 +// https://github.com/apple/swift/issues/58330 func test_allow_same_type_between_dependent_types() { struct Default : P { typealias X = Int diff --git a/test/Constraints/type_of.swift b/test/Constraints/type_of.swift index 992a16688e7b6..57ea89c951ec7 100644 --- a/test/Constraints/type_of.swift +++ b/test/Constraints/type_of.swift @@ -79,8 +79,11 @@ foo(type(of: G.T.self)) // Ok let _: Any = type(of: G.T.self) // Ok foo(type(of: bar())) // expected-error {{ambiguous use of 'bar()'}} -struct SR10696 { - func bar(_ s: SR10696.Type) { - type(of: s)() // expected-error {{type 'SR10696.Type' has no member 'init'}} +// https://github.com/apple/swift/issues/53093 +do { + struct S { + func bar(_ s: S.Type) { + type(of: s)() // expected-error {{type 'S.Type' has no member 'init'}} + } } } diff --git a/test/Constraints/valid_pointer_conversions.swift b/test/Constraints/valid_pointer_conversions.swift index 265083a6bc211..dd591bc646514 100644 --- a/test/Constraints/valid_pointer_conversions.swift +++ b/test/Constraints/valid_pointer_conversions.swift @@ -20,7 +20,9 @@ func givesPtr(_ str: String) { var d = 0.0 var arr = [1, 2, 3] - // SR-9090: Allow double optional promotion for pointer conversions. + // https://github.com/apple/swift/issues/51587 + // Allow double optional promotion for pointer conversions. + takesDoubleOptionalPtr(&arr) takesDoubleOptionalPtr(arr) takesDoubleOptionalPtr(str) @@ -35,12 +37,15 @@ func givesPtr(_ str: String) { // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'Double') are expected to be equal}} } -// SR12382 -func SR12382(_ x: UnsafeMutablePointer??) {} +// https://github.com/apple/swift/issues/54818 +do { + func f(_ x: UnsafeMutablePointer??) {} -var i = 0 -SR12382(&i) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} -// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'Double') are expected to be equal}} + var i = 0 + f(&i) + // expected-error@-1 {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} + // expected-note@-2 {{arguments to generic parameter 'Pointee' ('Int' and 'Double') are expected to be equal}} +} //problem/68254165 - Bad diagnostic when using String init(decodingCString:) with an incorrect pointer type func rdar68254165(ptr: UnsafeMutablePointer) { diff --git a/test/Constraints/without_actually_escaping.swift b/test/Constraints/without_actually_escaping.swift index d6ce858c24801..f7de8e5518e17 100644 --- a/test/Constraints/without_actually_escaping.swift +++ b/test/Constraints/without_actually_escaping.swift @@ -69,7 +69,7 @@ let _: ((Int) -> Int, (@escaping (Int) -> Int) -> ()) -> () = withoutActuallyEsc // Failing to propagate @noescape into non-single-expression // closure passed to withoutActuallyEscaping -// https://bugs.swift.org/browse/SR-7886 +// https://github.com/apple/swift/issues/50421 class Box { let value: T From 1f840d75cc812b5d41b56c8d04acf465b71f787c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 17 Aug 2022 22:07:37 +0900 Subject: [PATCH 162/491] actor system docs --- .../public/Distributed/DistributedActor.swift | 19 +- .../Distributed/DistributedActorSystem.swift | 263 +++++++++++++++++- 2 files changed, 269 insertions(+), 13 deletions(-) diff --git a/stdlib/public/Distributed/DistributedActor.swift b/stdlib/public/Distributed/DistributedActor.swift index b9d8ceff3c082..f8fd243be0ca9 100644 --- a/stdlib/public/Distributed/DistributedActor.swift +++ b/stdlib/public/Distributed/DistributedActor.swift @@ -101,7 +101,7 @@ import _Concurrency /// It is possible to explicitly declare an parameter-free initializer (`init()`), /// however the `actorSystem` property still must be assigned a concrete actor /// system instance the actor shall be part of. - +/// /// In general it is recommended to always have an `actorSystem` parameter as /// the last non-defaulted non-closure parameter in every distributed actors /// initializer parameter list. This way it is simple to swap in a "test actor @@ -224,10 +224,13 @@ public protocol DistributedActor: AnyActor, Identifiable, Hashable @available(SwiftStdlib 5.7, *) extension DistributedActor { + + /// A distributed actor's hash and equality is implemented by directly delegating to it's ``id``. nonisolated public func hash(into hasher: inout Hasher) { self.id.hash(into: &hasher) } + /// A distributed actor's hash and equality is implemented by directly delegating to it's ``id``. nonisolated public static func ==(lhs: Self, rhs: Self) -> Bool { lhs.id == rhs.id } @@ -249,6 +252,18 @@ extension CodingUserInfoKey { @available(SwiftStdlib 5.7, *) extension DistributedActor /*: implicitly Decodable */ where Self.ID: Decodable { + + /// Initializes an instance of this distributed actor by decoding its ``id``, + /// and passing it to the ``DistributedActorSystem`` obtained from `decoder.userInfo[`actorSystemKey]`. + /// + /// ## Requires: The decoder must have the ``CodingUserInfoKey/actorSystemKey`` set to + /// the ``ActorSystem`` that this actor expects, as it will be used to call ``DistributedActor/resolve(id:using:)`` + /// on, in order to obtain the instance this initializer should return. + /// + /// - Parameter decoder: used to decode the ``ID`` of this distributed actor. + /// - Throws: If the actor system value in `decoder.userInfo` is missing, or mis-typed; + /// the `ID` fails to decode from the passed `decoder`; + // or if the ``DistributedActor/resolve(id:using:)`` method invoked by this initializer throws. nonisolated public init(from decoder: Decoder) throws { guard let system = decoder.userInfo[.actorSystemKey] as? ActorSystem else { throw DistributedActorCodingError(message: @@ -263,6 +278,8 @@ extension DistributedActor /*: implicitly Decodable */ where Self.ID: Decodable @available(SwiftStdlib 5.7, *) extension DistributedActor /*: implicitly Encodable */ where Self.ID: Encodable { + + /// Encodes the ``actor.id`` as a single value into the passed `encoder`. nonisolated public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(self.id) diff --git a/stdlib/public/Distributed/DistributedActorSystem.swift b/stdlib/public/Distributed/DistributedActorSystem.swift index 68d7e5bec4cd6..92742378fa781 100644 --- a/stdlib/public/Distributed/DistributedActorSystem.swift +++ b/stdlib/public/Distributed/DistributedActorSystem.swift @@ -12,28 +12,267 @@ import Swift import _Concurrency -/// A distributed actor system is what enables all functionality of distributed actors. +/// A distributed actor system underpins and implements all functionality of distributed actors. /// -/// Distributed actors must always be associated with a concrete distributed actor system, -/// and do so by declaring a `typealias ActorSystem = ...`, or by having a module wide -/// `typealias DefaultDistributedActorSystem` declared which then applies to all distributed -/// actors that do not declare a specific type alias in their bodies. +/// A ``DistributedActor`` is always initialized in association with some concrete actor system. +/// And that actor system instance is then used to manage the identity of the actor, as well as +/// handle all remote interactions of the distributed actor. +/// +/// ## Using a DistributedActorSystem library +/// +/// From a library user's perspective (e.g. someone using a `ClusterSystem` or `SampleWebSocketActorSystem`), +/// the basic use of a distributed actor system is fairly opaque. +/// +/// Any distributed actor must declare what actor system it is able to operate with. This is done either by a +/// `typealias ActorSystem` in the body of such `distributed actor` declaration, or a module-wide global +/// `typealias DefaultDistributedActorSystem`. Refer to the ``DistributedActor`` documentation to learn more +/// about the tradeoffs of these approaches. +/// +/// Once an actor has declared the system it is able to work with, such system instance must provided +/// at initialization time, in order for the system to be able to take over the actor's identity management. +/// +/// For example, a simple distributed actor may look like this: +/// +/// ```swift +/// distributed actor Greeter { +/// init(name: String, actorSystem: ActorSystem) { +/// self.name = name +/// self.actorSystem = actorSystem // required (!) initialization of implicit actorSystem property +/// } +/// } +/// ``` +/// Notice that every distributed actor initializer must initialize the synthesized ``DistributedActor/actorSystem``. +/// This property is later used for identity management and other remote interactions of the actor. +/// For more details refer to ``DistributedActor`` which explains more about declaring distributed actors. +/// +/// For more details about how the specific actor system implementation deals with remote message transports, +/// and serialization, please refer to the specific system's documentation. +/// +/// > Note: For example, you may refer to the [Swift Distributed Actors cluster library](https://github.com/apple/swift-distributed-actors/) documentation, +/// > which is one example of such feature complete distributed actor system implementation: +/// +/// ## Implementing a DistributedActorSystem +/// +/// The following section is dedicated to distributed actor system library authors, and generally can be skipped over +/// by library users, as it explains the interactions of synthesized code and specific distributed actor system methods +/// and how they must be implemented. +/// +/// Methods discussed in this section are generally not intended to be called directly, but instead will have calls +/// generated to them from distributed actor declarations in appropriate places (such as initializers, `distributed func` calls etc). +/// +/// ### Assigning and Resigning Actor Identifiers +/// +/// During a local distributed actor's initialization (i.e. any `init` of a `distributed actor`), the actor system will +/// be invoked in order to assign an ``ActorID`` for this actor. +/// +/// A call to ``assignID(_:)`` is made during the initialization of the distributed actor. +/// The snippet below showcases this, though no guarantees are made at this point about the exact placement of this call. +/// +/// ```swift +/// distributed actor ShowcaseIDInit { +/// // let actorSystem: ActorSystem // synthesized; +/// +/// // typealias ID = ActorSystem.ActorID +/// // let id: ID // synthesized; implements `Identifiable.id` requirement +/// +/// init(actorSystem: ActorSystem) { +/// self.actorSystem = actorSystem +/// // ... +/// // self.id = actorSystem.assignID(Self.self) // synthesized; +/// // ... +/// } +/// } +/// ``` +/// +/// The result of ``assignID(_:)`` is then directly stored in the synthesized `id` property of the actor. +/// +/// The actor system should assign _globally unique_ identifiers to types, such that they may be properly resolved +/// from any process in the distributed actor system. The exact shape of the ``ActorID`` is left up to the library to decide. +/// It can be as small as an integer based identifier, or as large as a series of key-value pairs identifying the actor. +/// +/// The actor system must retain a mapping from the ``ActorID`` to the specific actor _instance_ which it is given in +/// ``actorReady(_)`` in order to implement the ``resolve(id:using:)`` method, which is how incoming and outgoing remote calls are made possible. +/// +/// Users have no control over this assignment, nor are they allowed to set the `id` property explicitly. +/// The ``DistributedActor/id`` is used to implement the distributed actor's ``Hashable``, ``Equatable``, +/// and even ``Codable`` conformance (which is synthesized if and only if the ``ActorID`` is ``Codable`` itself). +/// +/// > Tip: Take note that throwing or failable initializers complicate this somewhat. Thankfully, the compiler +/// > will always emit the right code such that every ``assignID(_:)`` is balanced with a ``resignID(_:)`` call, +/// > when the actor either failed to initialize, or deinitialized property. +/// > +/// > It is also possible that a throwing initializer throws before assigning the actorSystem, and id properties. +/// > In such case, no `assignID` nor `resignID` calls are made. There is no risk of the compiler ever attempting +/// > to call a `resignID(_:)` without first having assigned given ID. +/// +/// Manually invoking `assignID` and `resignID` is generally not recommended but isn't strictly a programmer error, +/// and it is up to the actor system to decide how to deal with such calls. +/// +/// Once the ``distributed actor`` deinitializes, a call to ``resignID(_:)`` will be made. Generally this is made from +/// the distributed actor's `deinit`, however in the case of throwing initializers it may also happen during such failed +/// init, in order to release the ID that is no longer used. +/// +/// ```swift +/// // Synthesized inside a distributed actor's deinit: +/// deinit { +/// // actorSystem.resignID(self.id) +/// } +/// ``` +/// +/// After an ID is resigned, it technically could be used to identify another instance. +/// For example, an advanced actor system implementation could use such approach to implement actors which +/// are created "ad-hoc" and always contain the appropriate ID, and if one isn't allocated yet for such ID, +/// it could _then_ create one on demand and make sure it is assigned the required ID. +/// +/// ### Readying Distributed Actors +/// +/// Once a `distributed actor` has been _fully initialized_ during its initializer, a call to ``actorReady(_:)`` +/// is synthesized. This call is made after the actor's properties (including all user-declared properties) have been +/// initialized, but before other user-defined code in the initializer gets a chance to run. +/// +/// > Note: Generally due to actor initializer isolation rules, users will need to make their initializers `async` +/// in order to write code that safely performs extra actions after it has fully initialized. +/// +/// The ``actorReady(_)`` call on the actor system is a signal to the actor system that this actor _instance_ is now ready +/// and may be resolved and interacted with via the actor system. Generally, a distributed actor system implementation +/// will _weakly retain_ the actors it has readied, because retaining them strongly would mean that they will never be +/// deallocated (and thus never resign their ID's). +/// +/// > Note: Generally actor systems should retain actors _weakly_ in order to allow them be deinitialized when no longer in use. +/// > +/// > Sometimes though, it can be quite useful to have the system retain certain "well known" actors, for example when it is expected +/// > that other nodes in the distributed system will need to interact with them, even if end-user code does no longer hold +/// > strong references to them. An example of such "retain while actor system is active" distributed actors would be any kind +/// > of actor which implements discovery or health check mechanisms between clustered nodes, sometimes called "system actors", +/// i.e. actors that serve the actor system directly. +/// +/// Next, we will discuss the the just mentioned resolve method, which is closely tied to readying actors. +/// +/// ### Resolving (potentially remote) Distributed Actors +/// +/// An important functionality of any distributed actor system is being able to turn a ``DistributedActor`` type and ``ActorID`` +/// into an reference to such actor, regardless where the actor is located. The ID should have enough information stored +/// to be able to make the decision _where_ the actor is located, without having to contact remote nodes. Specifically, +/// the implementation of ``DistributedActorSystem/resolve(id:as:)`` is _not_ `async` and should _not_ perform long running +/// or blocking operations in order to return. +/// +/// > Note: Currently only concrete distributed actors types can be resolved. +/// +/// The actor system's ``DistributedActorSystem/resolve(id:as:)`` method is called by the compiler whenever end-users +/// call the ``DistributedActor``'s ``resolve(id:using:)`` method. The return types of those methods differ, +/// as the actor system's return type is `Act?` (and it may throw if unable to resolve the `ActorID`). +/// +/// The actor system's `resolve` returning `nil` means that the ``ActorID`` passed to it refers to a _remote_ +/// distributed actor. The Swift runtime reacts to this by creating a remote actor reference (sometimes called a "proxy"). +/// +/// +/// ### Handling remote calls +/// +/// Finally, calls on a _remote_ distributed actor reference's distributed methods are turned into invocations of +/// `remoteCall(on:target:invocation:returning:throwing:)` (or `remoteCallVoid(on:target:invocation:throwing:)` for Void returning methods). +/// +/// Implementing the remote calls correctly and efficiently is one of the most important tasks for a distributed actor system library. +/// Since those methods are not currently expressible as protocol requirements Swift, and therefore will not appear in +/// the protocol's documentation as explicit requirements, due to their advanced use of generics, we present their +/// signatures that a conforming type one has to implement here: +/// +/// > Note: Although the the `remoteCall` methods are not expressed as protocol requirements in source, +/// > the compiler will provide the same errors as-if they were declared explicitly in this protocol. +/// +/// ```swift +/// /// Invoked by the Swift runtime when making a remote call. +/// /// +/// /// The `arguments` are the arguments container that was previously created +/// /// by `makeInvocationEncoder` and has been populated with all arguments. +/// /// +/// /// This method should perform the actual remote function call, and await for its response. +/// /// +/// /// ## Errors +/// /// This method is allowed to throw because of underlying transport or serialization errors, +/// /// as well as by re-throwing the error received from the remote callee (if able to). +/// func remoteCall( +/// on actor: Act, +/// target: RemoteCallTarget, +/// invocation: inout InvocationEncoder, +/// throwing: Err.Type, +/// returning: Res.Type +/// ) async throws -> Res +/// where Act: DistributedActor, +/// Act.ID == ActorID, +/// Err: Error, +/// Res: SerializationRequirement +/// ``` +/// +/// ```swift +/// /// Invoked by the Swift runtime when making a `Void`-returning remote call. +/// /// +/// /// The `arguments` are the arguments container that was previously created +/// /// by `makeInvocationEncoder` and has been populated with all arguments. +/// /// +/// /// This method should perform the actual remote function call, and await for its response. +/// /// +/// /// ## Errors +/// /// This method is allowed to throw because of underlying transport or serialization errors, +/// /// as well as by re-throwing the error received from the remote callee (if able to). +/// func remoteCallVoid( +/// on actor: Act, +/// target: RemoteCallTarget, +/// invocation: inout InvocationEncoder, +/// throwing: Err.Type +/// ) async throws -> Res +/// where Act: DistributedActor, +/// Act.ID == ActorID, +/// Err: Error +/// ``` +/// +/// Implementations of remote calls generally will serialize the `actor.id`, `target` and `invocation` +/// into some form of wire envelope, and send it over the network (or process boundary) using some +/// transport mechanism of their choice. As they do so, they need to suspend the remoteCall function, +/// and resume it once a reply to the call arrives; Unless the transport layer is also async/await aware, +/// this will often require making use of a ``CheckedContinuation``. +/// +/// While implementing remote calls please keep in mind any potential failure scenarios that may occur, +/// such as message loss, connection failures and similar issues. Such situations should all should be +/// surfaced by resuming the remoteCall by throwing an error conforming to ``DistributedActorSystemError``. +/// +/// While it is not _required_ to conform error thrown out of these methods to ``DistributedActorSystemError``, +/// the general guideline about conforming errors to this protocol is that errors which are outside of the user's control, +/// but are thrown because transport or actor system issues happening, should conform to it. This is to simplify +/// separating "business logic errors" from transport errors. +/// +/// +/// ### Further reading +/// +/// For an even more in-depth explanation about the inner workings of a distributed actor system, +/// you can refer to the following Swift Evolution proposals: +/// +/// - [SE-0336: Distributed Actor Isolation](https://github.com/apple/swift-evolution/blob/main/proposals/0336-distributed-actor-isolation.md) +/// - [SE-0344: Distributed Actor Runtime](https://github.com/apple/swift-evolution/blob/main/proposals/0344-distributed-actor-runtime.md) @available(SwiftStdlib 5.7, *) public protocol DistributedActorSystem: Sendable { - /// The identity used by actors that communicate via this transport + /// The type ID that will be assigned to any distributed actor managed by this actor system. + /// + /// ### A note on Codable IDs + /// If this type is Codable, then any `distributed actor` using this `ActorID` as its ``DistributedActor/ID``, + /// will gain a synthesized ``Codable`` conformance which is implemented by encoding the `ID`. + /// The decoding counter part of the Codable conformance is implemented by decoding the `ID` and passing it to + // the ``DistributedActor/resolve(id:using:)`` method. associatedtype ActorID: Sendable & Hashable + /// Type of ``DistributedTargetInvocationEncoder`` that should be used when the Swift runtime needs to encode + /// a distributed target call into an encoder, before passing it off to `remoteCall(...)`. associatedtype InvocationEncoder: DistributedTargetInvocationEncoder + /// Type of ``DistributedTargetInvocationDecoder`` that should be used when decoding invocations during + /// ``executeDistributedTarget(on:target:invocationDecoder:handler:)`` calls. associatedtype InvocationDecoder: DistributedTargetInvocationDecoder /// The type of the result handler which will be offered the results /// returned by a distributed function invocation called via - /// `executeDistributedTarget`. + /// ``executeDistributedTarget(on:target:invocationDecoder:handler:)``. associatedtype ResultHandler: DistributedTargetInvocationResultHandler /// The serialization requirement that will be applied to all distributed targets used with this system. - // TODO: constrain SerializationRequirement in typesystem to only be ok with protocol or class here - associatedtype SerializationRequirement + associatedtype SerializationRequirement // TODO: constrain SerializationRequirement in type-system to only be ok with protocol or class here where SerializationRequirement == InvocationEncoder.SerializationRequirement, SerializationRequirement == InvocationDecoder.SerializationRequirement, SerializationRequirement == ResultHandler.SerializationRequirement @@ -164,9 +403,6 @@ public protocol DistributedActorSystem: Sendable { // Act.ID == ActorID, // Err: Error - /// Implementation synthesized by the compiler. - /// Not intended to be invoked explicitly from user code! - // // Implementation notes: // The `metatype` must be the type of `Value`, and it must conform to // `SerializationRequirement`. If it does not, the method will crash at @@ -175,6 +411,8 @@ public protocol DistributedActorSystem: Sendable { // useful since it allows us to avoid boxing the value into an existential, // before we'd right away unbox it as first thing in the implementation of // this function. + /// Implementation synthesized by the compiler. + /// Not intended to be invoked explicitly from user code! func invokeHandlerOnReturn( handler: ResultHandler, resultBuffer: UnsafeRawPointer, @@ -184,6 +422,7 @@ public protocol DistributedActorSystem: Sendable { // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Execute Distributed Methods + @available(SwiftStdlib 5.7, *) extension DistributedActorSystem { From 78c0540b6fca098983fe6802fa0382e286586106 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 17 Aug 2022 15:09:17 +0100 Subject: [PATCH 163/491] [Glibc] Refer to UUID headers from the modulemap using relative paths This improves portability of the Swift toolchains by removing a usage of absolute path to Glibc. The Glibc modulemap is now injected into the Glibc include path using LLVM VFS, so it can reference Glibc headers using relative paths. This already works for other Glibc headers (e.g. `assert.h`) --- stdlib/public/Platform/glibc.modulemap.gyb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/Platform/glibc.modulemap.gyb b/stdlib/public/Platform/glibc.modulemap.gyb index e745aac1dbc88..82597f579736c 100644 --- a/stdlib/public/Platform/glibc.modulemap.gyb +++ b/stdlib/public/Platform/glibc.modulemap.gyb @@ -51,7 +51,7 @@ module SwiftGlibc [system] { % if CMAKE_SDK != "WASI" and CMAKE_SDK != "ANDROID": module CUUID [system] { - header "${GLIBC_INCLUDE_PATH}/uuid/uuid.h" + header "uuid/uuid.h" link "uuid" export * } From 9ecdf09cbf8b9e441ace8732286f92e76285703f Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 17 Aug 2022 07:30:14 -0700 Subject: [PATCH 164/491] Second attempt to fix IRGen/objc_object_getClass.swift There can be a `noundef` parameter attribute on object_getClass' declaration. rdar://98722116 --- test/IRGen/objc_object_getClass.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IRGen/objc_object_getClass.swift b/test/IRGen/objc_object_getClass.swift index b7f7bd6a6498c..2c62ea309e8cc 100644 --- a/test/IRGen/objc_object_getClass.swift +++ b/test/IRGen/objc_object_getClass.swift @@ -18,5 +18,5 @@ func test(_ o: ObjCSubclass) { o.field = 10 } -// CHECK-DAG: declare i8* @object_getClass(i8*) +// CHECK-DAG: declare i8* @object_getClass(i8*{{.*}}) // CHECK-DAG: call %objc_class* bitcast (i8* (i8*)* @object_getClass to %objc_class* (%objc_object*)*)(%objc_object* %{{.*}}) From e3a321721dde6a5cf4687c3d077df63d9ed81498 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Fri, 29 Jul 2022 16:25:55 +0100 Subject: [PATCH 165/491] [cxx-interop] Synthesize conformances to `CxxSequence` This makes ClangImporter automatically conform C++ sequence types to `Cxx.CxxSequence` protocol. We consider a C++ type to be a sequence type if it defines `begin()` & `end()` methods that return iterators of the same type which conforms to `UnsafeCxxInputIterator`. --- include/swift/AST/KnownProtocols.def | 1 + lib/AST/ASTContext.cpp | 1 + .../ClangDerivedConformances.cpp | 77 +++++++++++++++++++ lib/ClangImporter/ClangDerivedConformances.h | 8 +- lib/ClangImporter/ImportDecl.cpp | 1 + lib/IRGen/GenMeta.cpp | 1 + .../stdlib/overlay/Inputs/custom-sequence.h | 49 ++++++++++++ .../custom-sequence-module-interface.swift | 60 +++++++++++++++ .../overlay/custom-sequence-typechecker.swift | 24 +++--- .../Cxx/stdlib/overlay/custom-sequence.swift | 5 -- 10 files changed, 211 insertions(+), 16 deletions(-) create mode 100644 test/Interop/Cxx/stdlib/overlay/custom-sequence-module-interface.swift diff --git a/include/swift/AST/KnownProtocols.def b/include/swift/AST/KnownProtocols.def index da4f40596e202..ffea06fd02040 100644 --- a/include/swift/AST/KnownProtocols.def +++ b/include/swift/AST/KnownProtocols.def @@ -105,6 +105,7 @@ PROTOCOL(DistributedTargetInvocationDecoder) PROTOCOL(DistributedTargetInvocationResultHandler) // C++ Standard Library Overlay: +PROTOCOL(CxxSequence) PROTOCOL(UnsafeCxxInputIterator) PROTOCOL(AsyncSequence) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 910f7b81363d3..4b443e7a1c671 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1054,6 +1054,7 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const { case KnownProtocolKind::DistributedTargetInvocationResultHandler: M = getLoadedModule(Id_Distributed); break; + case KnownProtocolKind::CxxSequence: case KnownProtocolKind::UnsafeCxxInputIterator: M = getLoadedModule(Id_Cxx); break; diff --git a/lib/ClangImporter/ClangDerivedConformances.cpp b/lib/ClangImporter/ClangDerivedConformances.cpp index 185adebb0ce5a..d1fc7e0998cee 100644 --- a/lib/ClangImporter/ClangDerivedConformances.cpp +++ b/lib/ClangImporter/ClangDerivedConformances.cpp @@ -184,3 +184,80 @@ void swift::conformToCxxIteratorIfNeeded( impl.addSynthesizedProtocolAttrs(decl, {KnownProtocolKind::UnsafeCxxInputIterator}); } + +void swift::conformToCxxSequenceIfNeeded( + ClangImporter::Implementation &impl, NominalTypeDecl *decl, + const clang::CXXRecordDecl *clangDecl) { + PrettyStackTraceDecl trace("conforming to CxxSequence", decl); + + assert(decl); + assert(clangDecl); + ASTContext &ctx = decl->getASTContext(); + + ProtocolDecl *cxxIteratorProto = + ctx.getProtocol(KnownProtocolKind::UnsafeCxxInputIterator); + ProtocolDecl *cxxSequenceProto = + ctx.getProtocol(KnownProtocolKind::CxxSequence); + // If the Cxx module is missing, or does not include one of the necessary + // protocols, bail. + if (!cxxIteratorProto || !cxxSequenceProto) + return; + + // Check if present: `mutating func __beginUnsafe() -> RawIterator` + auto beginId = ctx.getIdentifier("__beginUnsafe"); + auto begins = lookupDirectWithoutExtensions(decl, beginId); + if (begins.size() != 1) + return; + auto begin = dyn_cast(begins.front()); + if (!begin) + return; + auto rawIteratorTy = begin->getResultInterfaceType(); + + // Check if present: `mutating func __endUnsafe() -> RawIterator` + auto endId = ctx.getIdentifier("__endUnsafe"); + auto ends = lookupDirectWithoutExtensions(decl, endId); + if (ends.size() != 1) + return; + auto end = dyn_cast(ends.front()); + if (!end) + return; + + // Check if `__beginUnsafe` and `__endUnsafe` have the same return type. + auto endTy = end->getResultInterfaceType(); + if (!endTy || endTy->getCanonicalType() != rawIteratorTy->getCanonicalType()) + return; + + // Check if RawIterator conforms to UnsafeCxxInputIterator. + auto rawIteratorConformanceRef = decl->getModuleContext()->lookupConformance( + rawIteratorTy, cxxIteratorProto); + if (!rawIteratorConformanceRef.isConcrete()) + return; + auto rawIteratorConformance = rawIteratorConformanceRef.getConcrete(); + auto pointeeDecl = + cxxIteratorProto->getAssociatedType(ctx.getIdentifier("Pointee")); + assert(pointeeDecl && + "UnsafeCxxInputIterator must have a Pointee associated type"); + auto pointeeTy = rawIteratorConformance->getTypeWitness(pointeeDecl); + assert(pointeeTy && "valid conformance must have a Pointee witness"); + + // Take the default definition of `Iterator` from CxxSequence protocol. This + // type is currently `CxxIterator`. + auto iteratorDecl = cxxSequenceProto->getAssociatedType(ctx.Id_Iterator); + auto iteratorTy = iteratorDecl->getDefaultDefinitionType(); + // Substitute generic `Self` parameter. + auto cxxSequenceSelfTy = cxxSequenceProto->getSelfInterfaceType(); + auto declSelfTy = decl->getDeclaredInterfaceType(); + iteratorTy = iteratorTy.subst( + [&](SubstitutableType *dependentType) { + if (dependentType->isEqual(cxxSequenceSelfTy)) + return declSelfTy; + return Type(dependentType); + }, + LookUpConformanceInModule(decl->getModuleContext())); + + impl.addSynthesizedTypealias(decl, ctx.Id_Element, pointeeTy); + impl.addSynthesizedTypealias(decl, ctx.Id_Iterator, iteratorTy); + impl.addSynthesizedTypealias(decl, ctx.getIdentifier("RawIterator"), + rawIteratorTy); + impl.addSynthesizedProtocolAttrs(decl, {KnownProtocolKind::CxxSequence}); +} diff --git a/lib/ClangImporter/ClangDerivedConformances.h b/lib/ClangImporter/ClangDerivedConformances.h index ae74eac07f3f1..f82719468cbd7 100644 --- a/lib/ClangImporter/ClangDerivedConformances.h +++ b/lib/ClangImporter/ClangDerivedConformances.h @@ -21,11 +21,17 @@ namespace swift { bool isIterator(const clang::CXXRecordDecl *clangDecl); /// If the decl is a C++ input iterator, synthesize a conformance to the -/// UnsafeCxxInputIterator protocol, which is defined in the std overlay. +/// UnsafeCxxInputIterator protocol, which is defined in the Cxx module. void conformToCxxIteratorIfNeeded(ClangImporter::Implementation &impl, NominalTypeDecl *decl, const clang::CXXRecordDecl *clangDecl); +/// If the decl is a C++ sequence, synthesize a conformance to the CxxSequence +/// protocol, which is defined in the Cxx module. +void conformToCxxSequenceIfNeeded(ClangImporter::Implementation &impl, + NominalTypeDecl *decl, + const clang::CXXRecordDecl *clangDecl); + } // namespace swift #endif // SWIFT_CLANG_DERIVED_CONFORMANCES_H diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index f8a02d2edc472..a33dfa4258f82 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -2612,6 +2612,7 @@ namespace { if (clangModule && requiresCPlusPlus(clangModule)) { if (auto structDecl = dyn_cast_or_null(result)) { conformToCxxIteratorIfNeeded(Impl, structDecl, decl); + conformToCxxSequenceIfNeeded(Impl, structDecl, decl); } } diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index fe95035610289..0d1e4b5ed5973 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -5808,6 +5808,7 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) { case KnownProtocolKind::DistributedTargetInvocationEncoder: case KnownProtocolKind::DistributedTargetInvocationDecoder: case KnownProtocolKind::DistributedTargetInvocationResultHandler: + case KnownProtocolKind::CxxSequence: case KnownProtocolKind::UnsafeCxxInputIterator: case KnownProtocolKind::SerialExecutor: case KnownProtocolKind::Sendable: diff --git a/test/Interop/Cxx/stdlib/overlay/Inputs/custom-sequence.h b/test/Interop/Cxx/stdlib/overlay/Inputs/custom-sequence.h index a9a31b9366477..3b8b26ab0ef88 100644 --- a/test/Interop/Cxx/stdlib/overlay/Inputs/custom-sequence.h +++ b/test/Interop/Cxx/stdlib/overlay/Inputs/custom-sequence.h @@ -37,4 +37,53 @@ struct SimpleEmptySequence { const int *end() const { return nullptr; } }; +struct HasMutatingBeginEnd { + ConstIterator begin() { return ConstIterator(1); } + ConstIterator end() { return ConstIterator(5); } +}; + +// TODO: this should conform to CxxSequence. +struct __attribute__((swift_attr("import_reference"), + swift_attr("retain:immortal"), + swift_attr("release:immortal"))) ImmortalSequence { + ConstIterator begin() { return ConstIterator(1); } + ConstIterator end() { return ConstIterator(5); } +}; + +// MARK: Types that are not actually sequences + +struct HasNoBeginMethod { + ConstIterator end() const { return ConstIterator(1); } +}; + +struct HasNoEndMethod { + ConstIterator begin() const { return ConstIterator(1); } +}; + +struct HasBeginEndTypeMismatch { + ConstIterator begin() const { return ConstIterator(1); } + ConstIteratorOutOfLineEq end() const { return ConstIteratorOutOfLineEq(3); } +}; + +struct HasBeginEndReturnNonIterators { + struct NotIterator {}; + + NotIterator begin() const { return NotIterator(); } + NotIterator end() const { return NotIterator(); } +}; + +// TODO: this should not be conformed to CxxSequence, because +// `const ConstIterator &` is imported as `UnsafePointer`, and +// calling `successor()` is not actually going to call +// `ConstIterator::operator++()`. It will increment the address instead. +struct HasBeginEndReturnRef { +private: + ConstIterator b = ConstIterator(1); + ConstIterator e = ConstIterator(5); + +public: + const ConstIterator &begin() const { return b; } + const ConstIterator &end() const { return e; } +}; + #endif // TEST_INTEROP_CXX_STDLIB_INPUTS_CUSTOM_SEQUENCE_H \ No newline at end of file diff --git a/test/Interop/Cxx/stdlib/overlay/custom-sequence-module-interface.swift b/test/Interop/Cxx/stdlib/overlay/custom-sequence-module-interface.swift new file mode 100644 index 0000000000000..85f2267bdf07b --- /dev/null +++ b/test/Interop/Cxx/stdlib/overlay/custom-sequence-module-interface.swift @@ -0,0 +1,60 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=CustomSequence -source-filename=x -I %S/Inputs -enable-experimental-cxx-interop -module-cache-path %t | %FileCheck %s + +// CHECK: import Cxx + +// CHECK: struct SimpleSequence : CxxSequence { +// CHECK: typealias Element = ConstIterator.Pointee +// CHECK: typealias Iterator = CxxIterator +// CHECK: typealias RawIterator = ConstIterator +// CHECK: } + +// CHECK: struct SimpleSequenceWithOutOfLineEqualEqual : CxxSequence { +// CHECK: typealias Element = ConstIteratorOutOfLineEq.Pointee +// CHECK: typealias Iterator = CxxIterator +// CHECK: typealias RawIterator = ConstIteratorOutOfLineEq +// CHECK: } + +// CHECK: struct SimpleArrayWrapper : CxxSequence { +// CHECK: typealias Element = UnsafePointer.Pointee +// CHECK: typealias Iterator = CxxIterator +// CHECK: typealias RawIterator = UnsafePointer +// CHECK: } + +// CHECK: struct SimpleArrayWrapperNullableIterators : CxxSequence { +// CHECK: typealias Element = Optional>.Pointee +// CHECK: typealias Iterator = CxxIterator +// CHECK: typealias RawIterator = UnsafePointer? +// CHECK: } + +// CHECK: struct SimpleEmptySequence : CxxSequence { +// CHECK: typealias Element = Optional>.Pointee +// CHECK: typealias Iterator = CxxIterator +// CHECK: typealias RawIterator = UnsafePointer? +// CHECK: } + +// CHECK: struct HasMutatingBeginEnd : CxxSequence { +// CHECK: typealias Element = ConstIterator.Pointee +// CHECK: typealias Iterator = CxxIterator +// CHECK: typealias RawIterator = ConstIterator +// CHECK: } + +// CHECK: struct HasNoBeginMethod { +// CHECK-NOT: typealias Element +// CHECK-NOT: typealias Iterator +// CHECK-NOT: typealias RawIterator +// CHECK: } +// CHECK: struct HasNoEndMethod { +// CHECK-NOT: typealias Element +// CHECK-NOT: typealias Iterator +// CHECK-NOT: typealias RawIterator +// CHECK: } +// CHECK: struct HasBeginEndTypeMismatch { +// CHECK-NOT: typealias Element +// CHECK-NOT: typealias Iterator +// CHECK-NOT: typealias RawIterator +// CHECK: } +// CHECK: struct HasBeginEndReturnNonIterators { +// CHECK-NOT: typealias Element +// CHECK-NOT: typealias Iterator +// CHECK-NOT: typealias RawIterator +// CHECK: } diff --git a/test/Interop/Cxx/stdlib/overlay/custom-sequence-typechecker.swift b/test/Interop/Cxx/stdlib/overlay/custom-sequence-typechecker.swift index d7858274d7f30..cfd6ef48ebc47 100644 --- a/test/Interop/Cxx/stdlib/overlay/custom-sequence-typechecker.swift +++ b/test/Interop/Cxx/stdlib/overlay/custom-sequence-typechecker.swift @@ -3,12 +3,7 @@ import CustomSequence import Cxx -// === SimpleSequence === -// Conformance to UnsafeCxxInputIterator is synthesized. -extension SimpleSequence: CxxSequence {} - -func checkSimpleSequence() { - let seq = SimpleSequence() +func checkIntSequence(_ seq: S) where S: Sequence, S.Element == Int32 { let contains = seq.contains(where: { $0 == 3 }) print(contains) @@ -17,17 +12,26 @@ func checkSimpleSequence() { } } +// === SimpleSequence === +// Conformance to UnsafeCxxInputIterator is synthesized. +// Conformance to CxxSequence is synthesized. +checkIntSequence(SimpleSequence()) + // === SimpleSequenceWithOutOfLineEqualEqual === -extension SimpleSequenceWithOutOfLineEqualEqual : CxxSequence {} +// Conformance to CxxSequence is synthesized. +checkIntSequence(SimpleSequenceWithOutOfLineEqualEqual()) // === SimpleArrayWrapper === // No UnsafeCxxInputIterator conformance required, since the iterators are actually UnsafePointers here. -extension SimpleArrayWrapper: CxxSequence {} +// Conformance to CxxSequence is synthesized. +checkIntSequence(SimpleArrayWrapper()) // === SimpleArrayWrapperNullableIterators === // No UnsafeCxxInputIterator conformance required, since the iterators are actually optional UnsafePointers here. -extension SimpleArrayWrapperNullableIterators: CxxSequence {} +// Conformance to CxxSequence is synthesized. +checkIntSequence(SimpleArrayWrapperNullableIterators()) // === SimpleEmptySequence === // No UnsafeCxxInputIterator conformance required, since the iterators are actually optional UnsafePointers here. -extension SimpleEmptySequence: CxxSequence {} +// Conformance to CxxSequence is synthesized. +checkIntSequence(SimpleEmptySequence()) diff --git a/test/Interop/Cxx/stdlib/overlay/custom-sequence.swift b/test/Interop/Cxx/stdlib/overlay/custom-sequence.swift index 98cf933d2b695..66d5700a23fb4 100644 --- a/test/Interop/Cxx/stdlib/overlay/custom-sequence.swift +++ b/test/Interop/Cxx/stdlib/overlay/custom-sequence.swift @@ -9,11 +9,6 @@ import Cxx var CxxSequenceTestSuite = TestSuite("CxxSequence") -extension SimpleSequence: CxxSequence {} - -extension SimpleEmptySequence: CxxSequence {} - - CxxSequenceTestSuite.test("SimpleSequence as Swift.Sequence") { let seq = SimpleSequence() let contains = seq.contains(where: { $0 == 3 }) From 3a3a98e06fddb2a6d4767493cc4dc718a7777eb4 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Wed, 17 Aug 2022 17:27:24 +0100 Subject: [PATCH 166/491] [Profiler] NFC: Constify `LoadedCounts` --- lib/SIL/IR/SILProfiler.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index a5026ffa37796..d7a3f401cc58c 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -467,17 +467,20 @@ struct PGOMapping : public ASTWalker { /// The next counter value to assign. unsigned NextCounter; + /// The loaded counter data. + const llvm::InstrProfRecord &LoadedCounts; + /// The map of statements to counters. llvm::DenseMap &LoadedCounterMap; - llvm::Expected &LoadedCounts; llvm::DenseMap &CondToParentMap; llvm::DenseMap CounterMap; PGOMapping(llvm::DenseMap &LoadedCounterMap, - llvm::Expected &LoadedCounts, + const llvm::InstrProfRecord &LoadedCounts, llvm::DenseMap &RegionCondToParentMap) - : NextCounter(0), LoadedCounterMap(LoadedCounterMap), - LoadedCounts(LoadedCounts), CondToParentMap(RegionCondToParentMap) {} + : NextCounter(0), LoadedCounts(LoadedCounts), + LoadedCounterMap(LoadedCounterMap), + CondToParentMap(RegionCondToParentMap) {} unsigned getParentCounter() const { if (Parent.isNull()) @@ -516,7 +519,7 @@ struct PGOMapping : public ASTWalker { "region does not have an associated counter"); unsigned CounterIndexForFunc = CounterIt->second; - return LoadedCounts->Counts[CounterIndexForFunc]; + return LoadedCounts.Counts[CounterIndexForFunc]; } bool walkToDeclPre(Decl *D) override { @@ -552,7 +555,7 @@ struct PGOMapping : public ASTWalker { if (!parent) { auto thenVal = thenCount.getValue(); for (auto pCount = NextCounter - 1; pCount > 0; --pCount) { - auto cCount = LoadedCounts->Counts[pCount]; + auto cCount = LoadedCounts.Counts[pCount]; if (cCount > thenVal) { count = cCount; break; @@ -642,7 +645,7 @@ struct PGOMapping : public ASTWalker { if (!parent) { auto thenVal = thenCount.getValue(); for (auto pCount = NextCounter - 1; pCount > 0; --pCount) { - auto cCount = LoadedCounts->Counts[pCount]; + auto cCount = LoadedCounts.Counts[pCount]; if (cCount > thenVal) { count = cCount; break; @@ -1186,7 +1189,7 @@ void SILProfiler::assignRegionCounters() { llvm::dbgs() << PGOFuncName << "\n"; return; } - PGOMapping pgoMapper(RegionLoadedCounterMap, LoadedCounts, + PGOMapping pgoMapper(RegionLoadedCounterMap, LoadedCounts.get(), RegionCondToParentMap); Root.walk(pgoMapper); } From 68c80c57cff992a277f978fe25dcd97fe2d39c90 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Wed, 17 Aug 2022 17:27:36 +0100 Subject: [PATCH 167/491] [Profiler] Simplify PGOMapping a bit Rather than re-computing the counter indices as we walk, use the indices that we've already computed as a part of MapRegionCounters. This should be NFC. Eventually we should also stop duplicating the counter arithmetic, and instead rely on the CounterExprs computed by CoverageMapping. For now I'm leaving that as follow-up work. --- lib/SIL/IR/SILProfiler.cpp | 126 +++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 70 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index d7a3f401cc58c..09d027b11dddb 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -463,25 +463,36 @@ class SourceMappingRegion { }; /// An ASTWalker that maps ASTNodes to profiling counters. +/// +/// TODO: We ought to be able to leverage the CounterExprs from the +/// CoverageMapping walker to recompute the correct counter information +/// for this walker. struct PGOMapping : public ASTWalker { - /// The next counter value to assign. - unsigned NextCounter; + /// The counter indices for AST nodes. + const llvm::DenseMap &CounterMap; /// The loaded counter data. const llvm::InstrProfRecord &LoadedCounts; - /// The map of statements to counters. + /// The output map of statements to counters. llvm::DenseMap &LoadedCounterMap; llvm::DenseMap &CondToParentMap; - llvm::DenseMap CounterMap; - PGOMapping(llvm::DenseMap &LoadedCounterMap, + PGOMapping(const llvm::DenseMap &CounterMap, const llvm::InstrProfRecord &LoadedCounts, + llvm::DenseMap &LoadedCounterMap, llvm::DenseMap &RegionCondToParentMap) - : NextCounter(0), LoadedCounts(LoadedCounts), + : CounterMap(CounterMap), LoadedCounts(LoadedCounts), LoadedCounterMap(LoadedCounterMap), CondToParentMap(RegionCondToParentMap) {} + /// Retrieve the counter index for a leaf node. + unsigned getCounterIndex(ASTNode Node) const { + auto result = CounterMap.find(Node); + assert(result != CounterMap.end() && "Unmapped node?"); + return result->second; + } + unsigned getParentCounter() const { if (Parent.isNull()) return 0; @@ -522,39 +533,42 @@ struct PGOMapping : public ASTWalker { return LoadedCounts.Counts[CounterIndexForFunc]; } + /// Record the execution count for a leaf node. + void setKnownExecutionCount(ASTNode Node) { + LoadedCounterMap[Node] = loadExecutionCount(Node); + } + + /// Record a computed execution count for a node. + void setExecutionCount(ASTNode Node, ProfileCounter count) { + LoadedCounterMap[Node] = count; + } + bool walkToDeclPre(Decl *D) override { if (isUnmapped(D)) return false; if (auto *AFD = dyn_cast(D)) { return visitFunctionDecl(*this, AFD, [&] { - auto node = AFD->getBody(); - CounterMap[node] = NextCounter++; - auto count = loadExecutionCount(node); - LoadedCounterMap[node] = count; + setKnownExecutionCount(AFD->getBody()); }); } - if (auto *TLCD = dyn_cast(D)) { - auto node = TLCD->getBody(); - CounterMap[node] = NextCounter++; - auto count = loadExecutionCount(node); - LoadedCounterMap[node] = count; - } + if (auto *TLCD = dyn_cast(D)) + setKnownExecutionCount(TLCD->getBody()); + return true; } std::pair walkToStmtPre(Stmt *S) override { unsigned parent = getParentCounter(); + auto parentCount = LoadedCounts.Counts[parent]; if (auto *IS = dyn_cast(S)) { auto thenStmt = IS->getThenStmt(); - CounterMap[thenStmt] = NextCounter++; auto thenCount = loadExecutionCount(thenStmt); - LoadedCounterMap[thenStmt] = thenCount; + setExecutionCount(thenStmt, thenCount); if (auto elseStmt = IS->getElseStmt()) { - CounterMap[elseStmt] = parent; - auto count = loadExecutionCount(elseStmt); + auto count = parentCount; if (!parent) { auto thenVal = thenCount.getValue(); - for (auto pCount = NextCounter - 1; pCount > 0; --pCount) { + for (auto pCount = getCounterIndex(thenStmt); pCount > 0; --pCount) { auto cCount = LoadedCounts.Counts[pCount]; if (cCount > thenVal) { count = cCount; @@ -562,7 +576,7 @@ struct PGOMapping : public ASTWalker { } } } - LoadedCounterMap[elseStmt] = subtract(count, thenCount); + setExecutionCount(elseStmt, subtract(count, thenCount)); auto Cond = IS->getCond(); for (const auto &elt : Cond) { if (elt.getKind() == @@ -571,47 +585,24 @@ struct PGOMapping : public ASTWalker { } } } - } else if (auto *US = dyn_cast(S)) { - auto guardBody = US->getBody(); - CounterMap[guardBody] = NextCounter++; + } else if (auto *GS = dyn_cast(S)) { + auto guardBody = GS->getBody(); auto guardCount = loadExecutionCount(guardBody); - LoadedCounterMap[guardBody] = guardCount; - CounterMap[US] = parent; - auto count = loadExecutionCount(US); - LoadedCounterMap[US] = subtract(count, guardCount); + setExecutionCount(guardBody, guardCount); + setExecutionCount(GS, subtract(parentCount, guardCount)); } else if (auto *WS = dyn_cast(S)) { - auto whileBody = WS->getBody(); - CounterMap[whileBody] = NextCounter++; - auto whileCount = loadExecutionCount(whileBody); - LoadedCounterMap[whileBody] = whileCount; - CounterMap[WS] = parent; - auto count = loadExecutionCount(WS); - LoadedCounterMap[WS] = count; + setKnownExecutionCount(WS->getBody()); + setExecutionCount(WS, parentCount); } else if (auto *RWS = dyn_cast(S)) { - auto rwsBody = RWS->getBody(); - CounterMap[rwsBody] = NextCounter++; - auto rwsBodyCount = loadExecutionCount(rwsBody); - LoadedCounterMap[rwsBody] = rwsBodyCount; - CounterMap[RWS] = parent; - auto count = loadExecutionCount(RWS); - LoadedCounterMap[RWS] = count; + setKnownExecutionCount(RWS->getBody()); + setExecutionCount(RWS, parentCount); } else if (auto *FES = dyn_cast(S)) { - auto fesBody = FES->getBody(); - CounterMap[fesBody] = NextCounter++; - auto fesCount = loadExecutionCount(fesBody); - LoadedCounterMap[fesBody] = fesCount; - CounterMap[FES] = parent; - auto count = loadExecutionCount(FES); - LoadedCounterMap[FES] = count; + setKnownExecutionCount(FES->getBody()); + setExecutionCount(FES, parentCount); } else if (auto *SS = dyn_cast(S)) { - CounterMap[SS] = NextCounter++; - auto ssCount = loadExecutionCount(SS); - LoadedCounterMap[SS] = ssCount; + setKnownExecutionCount(SS); } else if (auto *CS = dyn_cast(S)) { - auto stmt = getProfilerStmtForCase(CS); - CounterMap[stmt] = NextCounter++; - auto csCount = loadExecutionCount(stmt); - LoadedCounterMap[stmt] = csCount; + setKnownExecutionCount(getProfilerStmtForCase(CS)); } return {true, S}; } @@ -627,24 +618,19 @@ struct PGOMapping : public ASTWalker { unsigned parent = getParentCounter(); - if (Parent.isNull()) { - CounterMap[E] = NextCounter++; - auto eCount = loadExecutionCount(E); - LoadedCounterMap[E] = eCount; - } + if (Parent.isNull()) + setKnownExecutionCount(E); if (auto *IE = dyn_cast(E)) { auto thenExpr = IE->getThenExpr(); - CounterMap[thenExpr] = NextCounter++; auto thenCount = loadExecutionCount(thenExpr); - LoadedCounterMap[thenExpr] = thenCount; + setExecutionCount(thenExpr, thenCount); auto elseExpr = IE->getElseExpr(); assert(elseExpr && "An if-expr must have an else subexpression"); - CounterMap[elseExpr] = parent; - auto count = loadExecutionCount(elseExpr); + auto count = LoadedCounts.Counts[parent]; if (!parent) { auto thenVal = thenCount.getValue(); - for (auto pCount = NextCounter - 1; pCount > 0; --pCount) { + for (auto pCount = getCounterIndex(thenExpr); pCount > 0; --pCount) { auto cCount = LoadedCounts.Counts[pCount]; if (cCount > thenVal) { count = cCount; @@ -652,7 +638,7 @@ struct PGOMapping : public ASTWalker { } } } - LoadedCounterMap[elseExpr] = subtract(count, thenCount); + setExecutionCount(elseExpr, subtract(count, thenCount)); } return {true, E}; } @@ -1189,8 +1175,8 @@ void SILProfiler::assignRegionCounters() { llvm::dbgs() << PGOFuncName << "\n"; return; } - PGOMapping pgoMapper(RegionLoadedCounterMap, LoadedCounts.get(), - RegionCondToParentMap); + PGOMapping pgoMapper(RegionCounterMap, LoadedCounts.get(), + RegionLoadedCounterMap, RegionCondToParentMap); Root.walk(pgoMapper); } } From 3ebc541fd59a7ba947f84ea72a7223bea1a38acc Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 17 Aug 2022 10:05:56 -0700 Subject: [PATCH 168/491] [CSDiagnostics] Verify that member is in collection context `MissingMemberFailure::diagnoseInLiteralCollectionContext` should verify that a parent (or parent of a parent) expression is indeed a collection expression instead of checking types. Resolves: rdar://91452726 --- lib/Sema/CSDiagnostics.cpp | 13 +++++-------- test/expr/closure/multi_statement.swift | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 5ab1333ff8a28..d6640b68a217a 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -3976,17 +3976,14 @@ bool MissingMemberFailure::diagnoseInLiteralCollectionContext() const { if (!parentExpr) return false; - auto parentType = getType(parentExpr); + // This could happen if collection is a dictionary literal i.e. + // ["a": .test] - the element is a tuple - ("a", .test). + if (isExpr(parentExpr)) + parentExpr = findParentExpr(parentExpr); - if (!parentType->isKnownStdlibCollectionType() && !parentType->is()) + if (!isExpr(parentExpr)) return false; - if (isa(parentExpr)) { - parentExpr = findParentExpr(parentExpr); - if (!parentExpr) - return false; - } - if (auto *defaultableVar = getRawType(parentExpr)->getAs()) { if (solution.DefaultedConstraints.count( diff --git a/test/expr/closure/multi_statement.swift b/test/expr/closure/multi_statement.swift index 77a10631f883c..73d0dec116916 100644 --- a/test/expr/closure/multi_statement.swift +++ b/test/expr/closure/multi_statement.swift @@ -546,3 +546,23 @@ func test_conflicting_pattern_vars() { } } } + +// rdar://91452726 - crash in MissingMemberFailure::diagnoseInLiteralCollectionContext +struct Test { + struct ID { + } + + enum E : Hashable, Equatable { + case id + } + + var arr: [(ID, E)] + + func test() { + _ = arr.map { v in + switch v { + case .id: return true // expected-error {{value of tuple type '(Test.ID, Test.E)' has no member 'id'}} + } + } + } +} From 65b7777e3c6dbbbd29acd009ff5cf05889961828 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Wed, 17 Aug 2022 12:35:39 -0700 Subject: [PATCH 169/491] [pruned-liveness] Fix incorrect header comment that didn't describe the algorithm correctly. --- include/swift/SIL/PrunedLiveness.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/include/swift/SIL/PrunedLiveness.h b/include/swift/SIL/PrunedLiveness.h index 7b51f41666532..6851386b4fb70 100644 --- a/include/swift/SIL/PrunedLiveness.h +++ b/include/swift/SIL/PrunedLiveness.h @@ -57,10 +57,10 @@ /// /// Example 2. Cross-block liveness. /// -/// Initial State: +/// Initial State after initializing a def block: /// /// ----- -/// | Def | [LiveOut] +/// | Def | [LiveWithin] /// ----- /// | /// ----- @@ -68,10 +68,10 @@ /// ----- /// | /// ----- -/// | | [Dead] +/// | Use | [Dead] /// ----- /// -/// State after updateForUse: +/// Later state after updateForUse is applied to the use: /// /// ----- /// | Def | [LiveOut] @@ -85,6 +85,10 @@ /// | Use | [LiveWithin] /// ----- /// +/// +/// An invariant is that for any liveness region, the post-dominating blocks of +/// the region are the LiveWithin regions. +/// //===----------------------------------------------------------------------===// #ifndef SWIFT_SILOPTIMIZER_UTILS_PRUNEDLIVENESS_H From 6a55161187cebb129326a07d458862d1a47ec2dd Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Wed, 27 Jul 2022 20:00:05 -0400 Subject: [PATCH 170/491] Correct VFS libc modulemap injection condition. We should only be skipping VFS libc modulemap injection on Darwin and Windows. Unfortunately, we cannot just use the isOSGlibc Triple method because LLVM's sense of Glibc (does the platform _actually use_ glibc) differs from Swift's sense of Glibc (does the platform use libc). There may be other non-libc platforms that we should skip VFS injection on but let's correct the conditional for now and other prs should add those platforms as necessary. --- lib/ClangImporter/ClangIncludePaths.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index 507c034a513c7..931e6c49c4063 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -171,11 +171,15 @@ createClangArgs(const ASTContext &ctx, clang::driver::Driver &clangDriver) { return clangDriverArgs; } +static bool shouldInjectGlibcModulemap(const llvm::Triple &triple) { + return triple.isOSGlibc() || triple.isOSOpenBSD() || triple.isOSFreeBSD() || + triple.isAndroid(); +} + static SmallVector, 2> getGlibcFileMapping(ASTContext &ctx) { const llvm::Triple &triple = ctx.LangOpts.Target; - // We currently only need this when building for Linux. - if (!triple.isOSLinux()) + if (!shouldInjectGlibcModulemap(triple)) return {}; // Extract the Glibc path from Clang driver. From 2c295abb1be096246c21cb3c760f083912a77556 Mon Sep 17 00:00:00 2001 From: Dario Rexin Date: Wed, 17 Aug 2022 13:29:26 -0700 Subject: [PATCH 171/491] [IRGen] Properly handle empty payloads in getEnumTagMultipayload (#60590) * [IRGen] Properly handle empty payloads in getEnumTagMultipayload rdar://97914498 The generated code assumed that payloads would always be at least 1 byte long, ignoring the possibility of empty payloads, causing runtime crashes when using empty payloads in multi payload enums. * Fix test * Remove unnecessary basic block --- lib/IRGen/TypeLayout.cpp | 9 +++++++- test/Interpreter/rdar97914498.swift | 32 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test/Interpreter/rdar97914498.swift diff --git a/lib/IRGen/TypeLayout.cpp b/lib/IRGen/TypeLayout.cpp index b4e25b913ac4c..3342f8748cab0 100644 --- a/lib/IRGen/TypeLayout.cpp +++ b/lib/IRGen/TypeLayout.cpp @@ -2321,7 +2321,7 @@ EnumTypeLayoutEntry::getEnumTagMultipayload(IRGenFunction &IGF, auto usePayloadBB = IGF.createBasicBlock("use-payload-for-tag"); auto numPayloads = IGM.getInt32(cases.size()); auto usePayloadValue = Builder.CreateICmpUGE(loadedTag, numPayloads); - auto tagValue = llvm::PHINode::Create(IGM.Int32Ty, 3); + auto tagValue = llvm::PHINode::Create(IGM.Int32Ty, 4); tagValue->addIncoming(loadedTag, Builder.GetInsertBlock()); Builder.CreateCondBr(usePayloadValue, usePayloadBB, resultBB); @@ -2330,6 +2330,13 @@ EnumTypeLayoutEntry::getEnumTagMultipayload(IRGenFunction &IGF, auto truncSize = Builder.CreateZExtOrTrunc(maxPayloadSize(IGF), IGM.Int32Ty); auto sizeGTE4 = Builder.CreateICmpUGE(truncSize, four); auto sizeClampedTo4 = Builder.CreateSelect(sizeGTE4, four, truncSize); + auto sizeGreaterZeroBB = IGF.createBasicBlock(""); + auto zero = IGM.getInt32(0); + auto sizeGreaterZero = Builder.CreateICmpUGT(sizeClampedTo4, zero); + tagValue->addIncoming(loadedTag, Builder.GetInsertBlock()); + Builder.CreateCondBr(sizeGreaterZero, sizeGreaterZeroBB, resultBB); + + Builder.emitBlock(sizeGreaterZeroBB); auto payloadValue = emitLoad1to4Bytes(IGF, enumAddr, sizeClampedTo4); auto payloadGTE4BB = IGF.createBasicBlock(""); auto payloadLT4BB = IGF.createBasicBlock(""); diff --git a/test/Interpreter/rdar97914498.swift b/test/Interpreter/rdar97914498.swift new file mode 100644 index 0000000000000..a86b5dfdaaca2 --- /dev/null +++ b/test/Interpreter/rdar97914498.swift @@ -0,0 +1,32 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swiftc_driver -Xfrontend -disable-availability-checking -O -Xllvm -sil-opt-pass-count=0 -Xfrontend -disable-llvm-optzns %s -o %t/out +// RUN: %target-codesign %t/out +// RUN: %target-run %t/out + +// REQUIRES: executable_test +// REQUIRES: foundation + +// This is a regression test that ensures that empty payloads in multi +// payload enums are properly handled. + +import Foundation + +@inline(never) +func crash() { + let testURL = URL(string: "https://www.google.com")! + let r = Resource<()>(url: testURL, method: .get) + print(r.url) +} + +enum HTTPMethod { + case get + case post(Payload) + case patch(Payload) +} + +struct Resource { + let url: URL + let method: HTTPMethod +} + +crash() From 63a2c7640c14d4473207dce32b8eb073c80ec3e9 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Fri, 12 Aug 2022 09:37:02 -0700 Subject: [PATCH 172/491] Introduce ExternalTypeRefCache LLDB would like to cache typeref information to accelerate finding type information. This patch adds an optional interface that allows of typeref to register and provider field descriptor information for faster lookups. --- include/swift/Reflection/ReflectionContext.h | 63 ++++++++------- include/swift/Reflection/TypeRefBuilder.h | 22 +++++- include/swift/Remote/ExternalTypeRefCache.h | 75 ++++++++++++++++++ stdlib/public/Reflection/TypeRefBuilder.cpp | 79 ++++++++++++++++--- .../SwiftRemoteMirror/SwiftRemoteMirror.cpp | 2 +- 5 files changed, 197 insertions(+), 44 deletions(-) create mode 100644 include/swift/Remote/ExternalTypeRefCache.h diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h index 125a42029e705..77a32127d0ddb 100644 --- a/include/swift/Reflection/ReflectionContext.h +++ b/include/swift/Reflection/ReflectionContext.h @@ -211,9 +211,10 @@ class ReflectionContext uint32_t ThreadPort; }; - explicit ReflectionContext(std::shared_ptr reader) - : super(std::move(reader), *this) - {} + explicit ReflectionContext( + std::shared_ptr reader, + remote::ExternalTypeRefCache *externalCache = nullptr) + : super(std::move(reader), *this, externalCache) {} ReflectionContext(const ReflectionContext &other) = delete; ReflectionContext &operator=(const ReflectionContext &other) = delete; @@ -227,8 +228,10 @@ class ReflectionContext return sizeof(StoredPointer) * 2; } + /// On success returns the ID of the newly registered Reflection Info. template - bool readMachOSections( + llvm::Optional + readMachOSections( RemoteAddress ImageStart, llvm::SmallVector PotentialModuleNames = {}) { auto Buf = @@ -350,7 +353,7 @@ class ReflectionContext {MPEnumMdSec.first, MPEnumMdSec.second}, PotentialModuleNames}; - this->addReflectionInfo(info); + auto InfoID = this->addReflectionInfo(info); // Find the __DATA segment. for (unsigned I = 0; I < NumCommands; ++I) { @@ -374,10 +377,11 @@ class ReflectionContext savedBuffers.push_back(std::move(Buf)); savedBuffers.push_back(std::move(Sections)); - return true; + return InfoID; } - bool readPECOFFSections( + /// On success returns the ID of the newly registered Reflection Info. + llvm::Optional readPECOFFSections( RemoteAddress ImageStart, llvm::SmallVector PotentialModuleNames = {}) { auto DOSHdrBuf = this->getReader().readBytes( @@ -477,11 +481,11 @@ class ReflectionContext {ConformMdSec.first, ConformMdSec.second}, {MPEnumMdSec.first, MPEnumMdSec.second}, PotentialModuleNames}; - this->addReflectionInfo(Info); - return true; + return this->addReflectionInfo(Info); } - bool readPECOFF(RemoteAddress ImageStart, + /// On success returns the ID of the newly registered Reflection Info. + llvm::Optional readPECOFF(RemoteAddress ImageStart, llvm::SmallVector PotentialModuleNames = {}) { auto Buf = this->getReader().readBytes(ImageStart, sizeof(llvm::object::dos_header)); @@ -504,8 +508,9 @@ class ReflectionContext return readPECOFFSections(ImageStart, PotentialModuleNames); } + /// On success returns the ID of the newly registered Reflection Info. template - bool readELFSections( + llvm::Optional readELFSections( RemoteAddress ImageStart, llvm::Optional FileBuffer, llvm::SmallVector PotentialModuleNames = {}) { @@ -673,8 +678,7 @@ class ReflectionContext {MPEnumMdSec.first, MPEnumMdSec.second}, PotentialModuleNames}; - this->addReflectionInfo(info); - return true; + return this->addReflectionInfo(info); } /// Parses metadata information from an ELF image. Because the Section @@ -693,22 +697,22 @@ class ReflectionContext /// instance's memory reader. /// /// \return - /// /b True if the metadata information was parsed successfully, - /// /b false otherwise. - bool + /// \b The newly added reflection info ID if successful, + /// \b llvm::None otherwise. + llvm::Optional readELF(RemoteAddress ImageStart, llvm::Optional FileBuffer, llvm::SmallVector PotentialModuleNames = {}) { auto Buf = this->getReader().readBytes(ImageStart, sizeof(llvm::ELF::Elf64_Ehdr)); if (!Buf) - return false; + return llvm::None; // Read the header. auto Hdr = reinterpret_cast(Buf.get()); if (!Hdr->checkMagic()) - return false; + return llvm::None; // Check if we have a ELFCLASS32 or ELFCLASS64 unsigned char FileClass = Hdr->getFileClass(); @@ -719,11 +723,12 @@ class ReflectionContext return readELFSections>( ImageStart, FileBuffer, PotentialModuleNames); } else { - return false; + return llvm::None; } } - bool + /// On success returns the ID of the newly registered Reflection Info. + llvm::Optional addImage(RemoteAddress ImageStart, llvm::SmallVector PotentialModuleNames = {}) { // Read the first few bytes to look for a magic header. @@ -761,7 +766,7 @@ class ReflectionContext } // We don't recognize the format. - return false; + return llvm::None; } /// Adds an image using the FindSection closure to find the swift metadata @@ -770,9 +775,9 @@ class ReflectionContext /// of freeing the memory buffer in the RemoteRef return value. /// process. /// \return - /// \b True if any of the reflection sections were registered, - /// \b false otherwise. - bool + /// \b The newly added reflection info ID if successful, + /// \b llvm::None otherwise. + llvm::Optional addImage(llvm::function_ref< std::pair, uint64_t>(ReflectionSectionKind)> FindSection, @@ -798,7 +803,7 @@ class ReflectionContext // If we didn't find any sections, return. if (llvm::all_of(Pairs, [](const auto &Pair) { return !Pair.first; })) - return false; + return {}; ReflectionInfo Info = {{Pairs[0].first, Pairs[0].second}, {Pairs[1].first, Pairs[1].second}, @@ -809,12 +814,12 @@ class ReflectionContext {Pairs[6].first, Pairs[6].second}, {Pairs[7].first, Pairs[7].second}, PotentialModuleNames}; - this->addReflectionInfo(Info); - return true; + return addReflectionInfo(Info); } - void addReflectionInfo(ReflectionInfo I) { - getBuilder().addReflectionInfo(I); + /// Adds the reflection info and returns it's id. + uint32_t addReflectionInfo(ReflectionInfo I) { + return getBuilder().addReflectionInfo(I); } bool ownsObject(RemoteAddress ObjectAddress) { diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h index 83731f7a802bd..33ddfbb8ed5e8 100644 --- a/include/swift/Reflection/TypeRefBuilder.h +++ b/include/swift/Reflection/TypeRefBuilder.h @@ -18,6 +18,7 @@ #ifndef SWIFT_REFLECTION_TYPEREFBUILDER_H #define SWIFT_REFLECTION_TYPEREFBUILDER_H +#include "swift/Remote/ExternalTypeRefCache.h" #include "swift/Remote/MetadataReader.h" #include "swift/Reflection/MetadataSourceBuilder.h" #include "swift/Reflection/Records.h" @@ -426,6 +427,8 @@ class TypeRefBuilder { TypeConverter TC; MetadataSourceBuilder MSB; + remote::ExternalTypeRefCache *ExternalTypeRefCache = nullptr; + #define TYPEREF(Id, Parent) \ std::unordered_map Id##TypeRefs; @@ -915,10 +918,17 @@ class TypeRefBuilder { /// Parsing reflection metadata /// - void addReflectionInfo(ReflectionInfo I) { + /// Add the ReflectionInfo and return a unique ID for the reflection image + /// added. Since we only add reflection infos, the ID can be its index. + /// We return a uint32_t since it's extremely unlikely we'll run out of + /// indexes. + uint32_t addReflectionInfo(ReflectionInfo I) { ReflectionInfos.push_back(I); + auto InfoID = ReflectionInfos.size() - 1; + assert(InfoID <= UINT32_MAX && "ReflectionInfo ID overflow"); + return InfoID; } - + const std::vector &getReflectionInfos() { return ReflectionInfos; } @@ -943,6 +953,9 @@ class TypeRefBuilder { llvm::Optional> findFieldDescriptorAtIndex(size_t Index, const std::string &MangledName); + llvm::Optional> + getFieldDescriptorFromExternalCache(const std::string &MangledName); + public: RemoteRef readTypeRef(uint64_t remoteAddr); @@ -983,8 +996,9 @@ class TypeRefBuilder { public: template - TypeRefBuilder(remote::MetadataReader &reader) - : TC(*this), + TypeRefBuilder(remote::MetadataReader &reader, + remote::ExternalTypeRefCache *externalCache = nullptr) + : TC(*this), ExternalTypeRefCache(externalCache), PointerSize(sizeof(typename Runtime::StoredPointer)), TypeRefDemangler( [this, &reader](RemoteRef string, bool useOpaqueTypeSymbolicReferences) -> Demangle::Node * { diff --git a/include/swift/Remote/ExternalTypeRefCache.h b/include/swift/Remote/ExternalTypeRefCache.h new file mode 100644 index 0000000000000..8ac79f136a3e6 --- /dev/null +++ b/include/swift/Remote/ExternalTypeRefCache.h @@ -0,0 +1,75 @@ +//===--- ExternalTypeRefCache.h - Abstract access to external caches of +//typeref ------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2022 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 +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file declares an abstract interface for external caches of +/// typeref information. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_REMOTE_EXTERNALTYPEREFCACHE_H +#define SWIFT_REMOTE_EXTERNALTYPEREFCACHE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Optional.h" + +#include + +namespace swift { +namespace reflection { + +template +class ReflectionSection; +class FieldDescriptorIterator; +using FieldSection = ReflectionSection; +} + +namespace remote { +/// A struct with the information required to locate a specific field +/// descriptor. +struct FieldDescriptorLocator { + /// The reflection info ID the field descriptor belongs to. + uint64_t InfoID; + + /// The offset of the field descriptor in the FieldSection buffer. + uint64_t Offset; +}; + +/// An abstract interface for providing external type layout information. +struct ExternalTypeRefCache { + virtual ~ExternalTypeRefCache() = default; + + /// Cache the field descriptors of a reflection info with a given id with + /// their corresponding mangled names. The amount of field descriptors and + /// mangled names must be the same. If a field descriptor does not have a + /// mangled name a corresponding empty string must be in the mangled_names + /// array. + virtual void + cacheFieldDescriptors(uint64_t InfoID, + const swift::reflection::FieldSection &FieldDescriptors, + llvm::ArrayRef MangledNames) = 0; + + /// Retrieve a pair representing the reflection info id and the offset of a + /// field descriptor in the field section buffer, if available. + virtual llvm::Optional + getFieldDescriptorLocator(const std::string &Name) = 0; + + /// Returns whether the reflection info with the corresponding ID has been + /// cached already. + virtual bool isReflectionInfoCached(uint64_t InfoID) = 0; +}; + +} // namespace remote +} // namespace swift +#endif diff --git a/stdlib/public/Reflection/TypeRefBuilder.cpp b/stdlib/public/Reflection/TypeRefBuilder.cpp index 1e18379972426..ad376c92878de 100644 --- a/stdlib/public/Reflection/TypeRefBuilder.cpp +++ b/stdlib/public/Reflection/TypeRefBuilder.cpp @@ -221,22 +221,32 @@ void TypeRefBuilder::populateFieldTypeInfoCacheWithReflectionAtIndex( if (ProcessedReflectionInfoIndexes.contains(Index)) return; + llvm::SmallVector Names; const auto &Info = ReflectionInfos[Index]; for (auto FD : Info.Field) { - if (!FD->hasMangledTypeName()) - continue; - auto CandidateMangledName = readTypeRef(FD, FD->MangledTypeName); - if (auto NormalizedName = normalizeReflectionName(CandidateMangledName)) { - FieldTypeInfoCache[std::move(*NormalizedName)] = FD; + if (FD->hasMangledTypeName()) { + auto CandidateMangledName = readTypeRef(FD, FD->MangledTypeName); + if (auto NormalizedName = normalizeReflectionName(CandidateMangledName)) { + if (ExternalTypeRefCache) + Names.push_back(*NormalizedName); + FieldTypeInfoCache[std::move(*NormalizedName)] = FD; + } + } else if (ExternalTypeRefCache) { + // Mark the lack of a mangled name for this field descriptor with an empty + // string. + Names.push_back(""); } } + if (ExternalTypeRefCache) + ExternalTypeRefCache->cacheFieldDescriptors(Index, Info.Field, Names); + ProcessedReflectionInfoIndexes.insert(Index); } llvm::Optional> -TypeRefBuilder::findFieldDescriptorAtIndex(size_t Index, - const std::string &MangledName) { +TypeRefBuilder::findFieldDescriptorAtIndex( + size_t Index, const std::string &MangledName) { populateFieldTypeInfoCacheWithReflectionAtIndex(Index); auto Found = FieldTypeInfoCache.find(MangledName); if (Found != FieldTypeInfoCache.end()) { @@ -245,6 +255,41 @@ TypeRefBuilder::findFieldDescriptorAtIndex(size_t Index, return llvm::None; } +llvm::Optional> +TypeRefBuilder::getFieldDescriptorFromExternalCache( + const std::string &MangledName) { + if (!ExternalTypeRefCache) + return llvm::None; + + if (auto Locator = ExternalTypeRefCache->getFieldDescriptorLocator(MangledName)) { + if (Locator->InfoID >= ReflectionInfos.size()) + return llvm::None; + + auto &Field = ReflectionInfos[Locator->InfoID].Field; + auto Addr = Field.startAddress().getAddressData() + Locator->Offset; + + // Validate that we've got the correct field descriptor offset by parsing + // the mangled name for that specific offset and making sure it's the one + // we're looking for. + for (auto FD : Field) { + if (FD.getAddressData() == Addr) { + if (!FD->hasMangledTypeName()) + break; + auto CandidateMangledName = readTypeRef(FD, FD->MangledTypeName); + if (auto NormalizedName = + normalizeReflectionName(CandidateMangledName)) { + FieldTypeInfoCache[std::move(*NormalizedName)] = FD; + break; + } + } + } + auto Found = FieldTypeInfoCache.find(MangledName); + if (Found != FieldTypeInfoCache.end()) + return Found->second; + } + return llvm::None; +} + RemoteRef TypeRefBuilder::getFieldTypeInfo(const TypeRef *TR) { const std::string *MangledName; NodePointer Node; @@ -263,23 +308,37 @@ RemoteRef TypeRefBuilder::getFieldTypeInfo(const TypeRef *TR) { if (Found != FieldTypeInfoCache.end()) return Found->second; + if (auto FD = getFieldDescriptorFromExternalCache(*MangledName)) + return *FD; + // Heuristic: find the outermost Module node available, and try to parse the // ReflectionInfos with a matching name first. auto ModuleName = FindOutermostModuleName(Node); // If we couldn't find a module name or the type is imported (__C module) we // don't any useful information on which image to look for the type. - if (ModuleName && ModuleName != llvm::StringRef("__C")) - for (size_t i = 0; i < ReflectionInfos.size(); ++i) + if (ModuleName && !ModuleName->equals("__C")) { + for (size_t i = 0; i < ReflectionInfos.size(); ++i) { + // If the external cache already has the contents of this reflection info, + // and the previous lookup in the cache failed, then the field descriptor + // we're looking for isn't in this reflection info. + if (ExternalTypeRefCache && + ExternalTypeRefCache->isReflectionInfoCached(i)) + continue; if (llvm::is_contained(ReflectionInfos[i].PotentialModuleNames, ModuleName)) if (auto FD = findFieldDescriptorAtIndex(i, *MangledName)) return *FD; + } + } // On failure, fill out the cache, ReflectionInfo by ReflectionInfo, // until we find the field descriptor we're looking for. - for (size_t i = 0; i < ReflectionInfos.size(); ++i) + for (size_t i = 0; i < ReflectionInfos.size(); ++i) { + if (ExternalTypeRefCache && ExternalTypeRefCache->isReflectionInfoCached(i)) + continue; if (auto FD = findFieldDescriptorAtIndex(i, *MangledName)) return *FD; + } return nullptr; } diff --git a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp index 6eb1577f2f602..64d61e2f620e6 100644 --- a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp +++ b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp @@ -278,7 +278,7 @@ int swift_reflection_addImage(SwiftReflectionContextRef ContextRef, swift_addr_t imageStart) { auto Context = ContextRef->nativeContext; - return Context->addImage(RemoteAddress(imageStart)); + return Context->addImage(RemoteAddress(imageStart)).hasValue(); } int From c9d31ec2d24212c7a6b5291e7962bb92debf3ea0 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 17 Aug 2022 14:29:07 -0700 Subject: [PATCH 173/491] Fix test to work on 64-bit and 32-bit targets rdar://98728891 --- .../SILOptimizer/inline_terminator_scopes.sil | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/test/SILOptimizer/inline_terminator_scopes.sil b/test/SILOptimizer/inline_terminator_scopes.sil index 2ede3cbf4d3f2..7c9d008032f62 100644 --- a/test/SILOptimizer/inline_terminator_scopes.sil +++ b/test/SILOptimizer/inline_terminator_scopes.sil @@ -1,26 +1,26 @@ // RUN: %target-sil-opt -enable-sil-verify-all %s -inline -sil-print-debuginfo | %FileCheck %s // Generated from: -// func g(_ x: Int) -> Int { +// func g(_ x: Int64) -> Int64 { // if (x > 0) { // return 1 // } // return 0 // } // -// public func f(_ x: Int) -> Int { return g(x) } +// public func f(_ x: Int64) -> Int64 { return g(x) } -// CHECK: sil @$s1a1fyS2iF : $@convention(thin) (Int) -> Int { -// CHECK: bb0(%0 : $Int): +// CHECK: sil @$s1a1gys5Int64VADF : $@convention(thin) (Int64) -> Int64 { +// CHECK: bb0(%0 : $Int64): // CHECK-NEXT: scope [[SCOPE_10:[0-9]+]] -// CHECK: cond_br {{.*}}, bb1, bb2, loc "t.swift":3:9, scope [[SCOPE_10]] +// CHECK: cond_br {{.*}}, bb1, bb2, loc "t.swift":2:9, scope [[SCOPE_10]] // CHECK: bb1: // CHECK-NEXT: scope [[SCOPE_11:[0-9]+]] -// CHECK: br bb3({{.*}} : $Int), loc "t.swift":4:5, scope [[SCOPE_11]] +// CHECK: br bb3({{.*}} : $Int64), loc "t.swift":3:5, scope [[SCOPE_11]] // CHECK: bb2: // CHECK-NEXT: scope [[SCOPE_9:[0-9]+]] -// CHECK: br bb3({{.*}} : $Int), loc "t.swift":6:3, scope [[SCOPE_9]] -// CHECK: bb3({{.*}} : $Int): +// CHECK: br bb3({{.*}} : $Int64), loc "t.swift":5:3, scope [[SCOPE_9]] +// CHECK: bb3({{.*}} : $Int64): sil_stage canonical @@ -28,48 +28,48 @@ import Builtin import Swift import SwiftShims -func g(_ x: Int) -> Int +func g(_ x: Int64) -> Int64 -public func f(_ x: Int) -> Int +public func f(_ x: Int64) -> Int64 -sil_scope 1 { loc "t.swift":2:6 parent @$s1a1gyS2iF : $@convention(thin) (Int) -> Int } -sil_scope 2 { loc "t.swift":2:25 parent 1 } -sil_scope 3 { loc "t.swift":3:3 parent 2 } -sil_scope 4 { loc "t.swift":3:14 parent 3 } +sil_scope 1 { loc "t.swift":1:6 parent @$s1a1gys5Int64VADF : $@convention(thin) (Int64) -> Int64 } +sil_scope 2 { loc "t.swift":1:29 parent 1 } +sil_scope 3 { loc "t.swift":2:3 parent 2 } +sil_scope 4 { loc "t.swift":2:14 parent 3 } // g(_:) -sil hidden @$s1a1gyS2iF : $@convention(thin) (Int) -> Int { +sil @$s1a1gys5Int64VADF : $@convention(thin) (Int64) -> Int64 { // %0 "x" // users: %3, %1 -bb0(%0 : $Int): - %2 = integer_literal $Builtin.Int64, 0, loc "t.swift":3:11, scope 3 // user: %4 - %3 = struct_extract %0 : $Int, #Int._value, loc "t.swift":3:9, scope 3 // user: %4 - %4 = builtin "cmp_slt_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1, loc "t.swift":3:9, scope 3 // user: %5 - cond_br %4, bb1, bb2, loc "t.swift":3:9, scope 3 // id: %5 +bb0(%0 : $Int64): + %2 = integer_literal $Builtin.Int64, 0, loc "t.swift":2:11, scope 3 // user: %4 + %3 = struct_extract %0 : $Int64, #Int64._value, loc "t.swift":2:9, scope 3 // user: %4 + %4 = builtin "cmp_slt_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1, loc "t.swift":2:9, scope 3 // user: %5 + cond_br %4, bb1, bb2, loc "t.swift":2:9, scope 3 // id: %5 bb1: // Preds: bb0 - %6 = integer_literal $Builtin.Int64, 1, loc "t.swift":4:12, scope 4 // user: %7 - %7 = struct $Int (%6 : $Builtin.Int64), loc "t.swift":4:12, scope 4 // user: %8 - br bb3(%7 : $Int), loc "t.swift":4:5, scope 4 // id: %8 + %6 = integer_literal $Builtin.Int64, 1, loc "t.swift":3:12, scope 4 // user: %7 + %7 = struct $Int64 (%6 : $Builtin.Int64), loc "t.swift":3:12, scope 4 // user: %8 + br bb3(%7 : $Int64), loc "t.swift":3:5, scope 4 // id: %8 bb2: // Preds: bb0 - %9 = integer_literal $Builtin.Int64, 0, loc "t.swift":6:10, scope 2 // user: %10 - %10 = struct $Int (%9 : $Builtin.Int64), loc "t.swift":6:10, scope 2 // user: %11 - br bb3(%10 : $Int), loc "t.swift":6:3, scope 2 // id: %11 + %9 = integer_literal $Builtin.Int64, 0, loc "t.swift":5:10, scope 2 // user: %10 + %10 = struct $Int64 (%9 : $Builtin.Int64), loc "t.swift":5:10, scope 2 // user: %11 + br bb3(%10 : $Int64), loc "t.swift":5:3, scope 2 // id: %11 // %12 // user: %13 -bb3(%12 : $Int): // Preds: bb2 bb1 - return %12 : $Int, loc "t.swift":7:1, scope 2 // id: %13 -} // end sil function '$s1a1gyS2iF' +bb3(%12 : $Int64): // Preds: bb2 bb1 + return %12 : $Int64, loc "t.swift":6:1, scope 2 // id: %13 +} // end sil function '$s1a1gys5Int64VADF' -sil_scope 7 { loc "t.swift":9:13 parent @$s1a1fyS2iF : $@convention(thin) (Int) -> Int } -sil_scope 8 { loc "t.swift":9:32 parent 7 } +sil_scope 7 { loc "t.swift":8:13 parent @$s1a1fys5Int64VADF : $@convention(thin) (Int64) -> Int64 } +sil_scope 8 { loc "t.swift":8:36 parent 7 } // f(_:) -sil @$s1a1fyS2iF : $@convention(thin) (Int) -> Int { +sil @$s1a1fys5Int64VADF : $@convention(thin) (Int64) -> Int64 { // %0 "x" // users: %3, %1 -bb0(%0 : $Int): +bb0(%0 : $Int64): // function_ref g(_:) - %2 = function_ref @$s1a1gyS2iF : $@convention(thin) (Int) -> Int, loc "t.swift":9:41, scope 8 // user: %3 - %3 = apply %2(%0) : $@convention(thin) (Int) -> Int, loc "t.swift":9:41, scope 8 // user: %4 - return %3 : $Int, loc "t.swift":9:34, scope 8 // id: %4 -} // end sil function '$s1a1fyS2iF' + %2 = function_ref @$s1a1gys5Int64VADF : $@convention(thin) (Int64) -> Int64, loc "t.swift":8:45, scope 8 // user: %3 + %3 = apply %2(%0) : $@convention(thin) (Int64) -> Int64, loc "t.swift":8:45, scope 8 // user: %4 + return %3 : $Int64, loc "t.swift":8:38, scope 8 // id: %4 +} // end sil function '$s1a1fys5Int64VADF' From f295cbee199c95bcf3b5771664d48599228a9be0 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 16 Aug 2022 11:20:42 -0700 Subject: [PATCH 174/491] IRGen: Fix shift amount in typelayout lowering of mulipayload enums to bits Transfer the fix in #42131 to the typelayout lowering code. Noticed as part of investigating the fix for #60590. --- lib/IRGen/TypeLayout.cpp | 4 +-- .../Inputs/resilient_multipayload_enum.swift | 9 ++++++ .../resilient_multipayload_enum.swift | 32 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/Interpreter/Inputs/resilient_multipayload_enum.swift create mode 100644 test/Interpreter/resilient_multipayload_enum.swift diff --git a/lib/IRGen/TypeLayout.cpp b/lib/IRGen/TypeLayout.cpp index b4e25b913ac4c..cd7cd2a606326 100644 --- a/lib/IRGen/TypeLayout.cpp +++ b/lib/IRGen/TypeLayout.cpp @@ -2398,7 +2398,7 @@ void EnumTypeLayoutEntry::storeEnumTagMultipayload(IRGenFunction &IGF, // } else { // unsigned numPayloadBits = layout.payloadSize * CHAR_BIT; // whichTag = numPayloads + (whichEmptyCase >> numPayloadBits); - // whichPayloadValue = whichEmptyCase & ((1U << numPayloads) - 1U); + // whichPayloadValue = whichEmptyCase & ((1U << numPayloadBits) - 1U); // } // storeMultiPayloadTag(value, layout, whichTag); // storeMultiPayloadValue(value, layout, whichPayloadValue); @@ -2444,7 +2444,7 @@ void EnumTypeLayoutEntry::storeEnumTagMultipayload(IRGenFunction &IGF, whichTag->addIncoming(tmp2, Builder.GetInsertBlock()); auto tmp3 = Builder.CreateSub( - Builder.CreateShl(IGM.getInt32(1), numPayloads), IGM.getInt32(1)); + Builder.CreateShl(IGM.getInt32(1), numPayloadBits), IGM.getInt32(1)); auto tmp4 = Builder.CreateAnd(whichEmptyCase, tmp3); whichPayloadValue->addIncoming(tmp4, Builder.GetInsertBlock()); Builder.CreateBr(storeBB); diff --git a/test/Interpreter/Inputs/resilient_multipayload_enum.swift b/test/Interpreter/Inputs/resilient_multipayload_enum.swift new file mode 100644 index 0000000000000..bcd233ffe29a1 --- /dev/null +++ b/test/Interpreter/Inputs/resilient_multipayload_enum.swift @@ -0,0 +1,9 @@ +public enum ProblematicEnumeration { + case zero(T) + case one(Bool) + case two + case three + case four + case five + case six +} diff --git a/test/Interpreter/resilient_multipayload_enum.swift b/test/Interpreter/resilient_multipayload_enum.swift new file mode 100644 index 0000000000000..5392a06413d40 --- /dev/null +++ b/test/Interpreter/resilient_multipayload_enum.swift @@ -0,0 +1,32 @@ +// Build unoptimized library +// RUN: %empty-directory(%t) +// RUN: %target-build-swift-dylib(%t/%target-library-name(ResilientEnum)) -enable-library-evolution %S/Inputs/resilient_multipayload_enum.swift -emit-module -emit-module-path %t/ResilientEnum.swiftmodule -module-name ResilientEnum +// RUN: %target-codesign %t/%target-library-name(ResilientEnum) +// RUN: %target-build-swift %s -lResilientEnum -I %t -L %t -o %t/main %target-rpath(%t) +// RUN: %target-codesign %t/main +// RUN: %target-run %t/main %t/%target-library-name(ResilientEnum) | %FileCheck %s + +// Build optimized library (this exercises a different value witness generation path) +// RUN: %empty-directory(%t) +// RUN: %target-build-swift-dylib(%t/%target-library-name(ResilientEnum)) -enable-library-evolution %S/Inputs/resilient_multipayload_enum.swift -emit-module -emit-module-path %t/ResilientEnum.swiftmodule -module-name ResilientEnum -O +// RUN: %target-codesign %t/%target-library-name(ResilientEnum) +// RUN: %target-build-swift %s -lResilientEnum -I %t -L %t -o %t/main %target-rpath(%t) +// RUN: %target-codesign %t/main +// RUN: %target-run %t/main %t/%target-library-name(ResilientEnum) | %FileCheck %s + +import ResilientEnum + +@inline(never) +@_semantics("optimize.sil.specialize.generic.never") +func dump(_ t: T) { + print(t) +} + +@inline(never) +func doit() { + let e = ProblematicEnumeration.six + // CHECK: six + dump(e) +} + +doit() From 1761fc240642cbc0b9d30a73ad2ef65d7008e699 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 17 Aug 2022 16:25:25 -0700 Subject: [PATCH 175/491] Consider store_borrow as a write in LoadBorrowImmutabilityChecker --- lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp b/lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp index ed4cd59a2b154..522ea2ca810e7 100644 --- a/lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp +++ b/lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp @@ -108,6 +108,7 @@ bool GatherWritesVisitor::visitUse(Operand *op, AccessUseType useTy) { case SILInstructionKind::DestroyValueInst: case SILInstructionKind::InjectEnumAddrInst: case SILInstructionKind::StoreInst: + case SILInstructionKind::StoreBorrowInst: case SILInstructionKind::AssignInst: case SILInstructionKind::UncheckedTakeEnumDataAddrInst: case SILInstructionKind::MarkFunctionEscapeInst: @@ -130,10 +131,6 @@ bool GatherWritesVisitor::visitUse(Operand *op, AccessUseType useTy) { #include "swift/AST/ReferenceStorage.def" // Ignored pointer uses... - - // Allow store_borrow within the load_borrow scope. - // FIXME: explain why. - case SILInstructionKind::StoreBorrowInst: // Returns are never in scope. case SILInstructionKind::ReturnInst: return true; From f374f2bad3ccb51bc6576957ef4e681b7b392263 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 17 Aug 2022 16:25:44 -0700 Subject: [PATCH 176/491] Handle store_borrow in MemAccessUtils --- include/swift/SIL/MemAccessUtils.h | 4 ++++ lib/SIL/Utils/MemAccessUtils.cpp | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/include/swift/SIL/MemAccessUtils.h b/include/swift/SIL/MemAccessUtils.h index 3408ccb15b5d9..6616483ba10c3 100644 --- a/include/swift/SIL/MemAccessUtils.h +++ b/include/swift/SIL/MemAccessUtils.h @@ -1691,6 +1691,10 @@ Result AccessUseDefChainVisitor::visit(SILValue sourceAddr) { if (isAccessStorageIdentityCast(svi)) return asImpl().visitStorageCast(svi, &svi->getAllOperands()[0], AccessStorageCast::Identity); + if (auto *sbi = dyn_cast(svi)) + return asImpl().visitStorageCast( + svi, &sbi->getAllOperands()[CopyLikeInstruction::Dest], + AccessStorageCast::Identity); } switch (sourceAddr->getKind()) { default: diff --git a/lib/SIL/Utils/MemAccessUtils.cpp b/lib/SIL/Utils/MemAccessUtils.cpp index 3cdf25560f4f6..017a314ec1904 100644 --- a/lib/SIL/Utils/MemAccessUtils.cpp +++ b/lib/SIL/Utils/MemAccessUtils.cpp @@ -1935,6 +1935,11 @@ bool AccessPathDefUseTraversal::visitUser(DFSEntry dfs) { return true; } } + if (auto *sbi = dyn_cast(use->getUser())) { + if (use->get() == sbi->getDest()) { + pushUsers(sbi, dfs); + } + } if (isa(use->getUser())) { return true; } From 4a9a932dce65499f51b1caa1abec32ad23e99eb5 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Wed, 17 Aug 2022 16:29:56 -0700 Subject: [PATCH 177/491] Ban @objcMembers Without Importing Foundation rdar://98734024 --- include/swift/AST/DiagnosticsSema.def | 2 +- lib/Sema/TypeCheckAttr.cpp | 8 +++++++- lib/Sema/TypeCheckDeclObjC.cpp | 3 +++ lib/Sema/TypeCheckObjC.h | 3 +++ test/Sema/objcmembers_attr_requires_module.swift | 6 ++++++ 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 test/Sema/objcmembers_attr_requires_module.swift diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index b2dfc26399396..3e19342d7982b 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5238,7 +5238,7 @@ ERROR(objc_extension_not_class,none, "'@objc' can only be applied to an extension of a class", ()) // If you change this, also change enum ObjCReason -#define OBJC_ATTR_SELECT "select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)|marked @objc by an access note}" +#define OBJC_ATTR_SELECT "select{marked @_cdecl|marked dynamic|marked @objc|marked @objcMembers|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)|marked @objc by an access note}" WARNING(attribute_meaningless_when_nonobjc,none, "'@%0' attribute is meaningless on a property that cannot be " diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 8061f84362915..08a6afed1c123 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1147,9 +1147,11 @@ static bool checkObjCDeclContext(Decl *D) { return false; } -static void diagnoseObjCAttrWithoutFoundation(ObjCAttr *attr, Decl *decl, +static void diagnoseObjCAttrWithoutFoundation(DeclAttribute *attr, Decl *decl, ObjCReason reason, DiagnosticBehavior behavior) { + assert(attr->getKind() == DeclAttrKind::DAK_ObjC || + attr->getKind() == DeclAttrKind::DAK_ObjCMembers); auto *SF = decl->getDeclContext()->getParentSourceFile(); assert(SF); @@ -1369,6 +1371,10 @@ void AttributeChecker::visitNonObjCAttr(NonObjCAttr *attr) { void AttributeChecker::visitObjCMembersAttr(ObjCMembersAttr *attr) { if (!isa(D)) diagnoseAndRemoveAttr(attr, diag::objcmembers_attribute_nonclass); + + auto reason = ObjCReason(ObjCReason::ExplicitlyObjCMembers, attr); + auto behavior = behaviorLimitForObjCReason(reason, Ctx); + diagnoseObjCAttrWithoutFoundation(attr, D, reason, behavior); } void AttributeChecker::visitOptionalAttr(OptionalAttr *attr) { diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 6a56d0bd89be0..351547f80a0c8 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -37,6 +37,7 @@ swift::behaviorLimitForObjCReason(ObjCReason reason, ASTContext &ctx) { case ObjCReason::ExplicitlyCDecl: case ObjCReason::ExplicitlyDynamic: case ObjCReason::ExplicitlyObjC: + case ObjCReason::ExplicitlyObjCMembers: case ObjCReason::ExplicitlyIBOutlet: case ObjCReason::ExplicitlyIBAction: case ObjCReason::ExplicitlyIBSegueAction: @@ -71,6 +72,7 @@ unsigned swift::getObjCDiagnosticAttrKind(ObjCReason reason) { case ObjCReason::ExplicitlyCDecl: case ObjCReason::ExplicitlyDynamic: case ObjCReason::ExplicitlyObjC: + case ObjCReason::ExplicitlyObjCMembers: case ObjCReason::ExplicitlyIBOutlet: case ObjCReason::ExplicitlyIBAction: case ObjCReason::ExplicitlyIBSegueAction: @@ -128,6 +130,7 @@ void ObjCReason::describe(const Decl *D) const { case ObjCReason::ExplicitlyCDecl: case ObjCReason::ExplicitlyDynamic: case ObjCReason::ExplicitlyObjC: + case ObjCReason::ExplicitlyObjCMembers: case ObjCReason::ExplicitlyIBOutlet: case ObjCReason::ExplicitlyIBAction: case ObjCReason::ExplicitlyIBSegueAction: diff --git a/lib/Sema/TypeCheckObjC.h b/lib/Sema/TypeCheckObjC.h index 7f8bc171dd2d9..defee4ce263b4 100644 --- a/lib/Sema/TypeCheckObjC.h +++ b/lib/Sema/TypeCheckObjC.h @@ -49,6 +49,8 @@ class ObjCReason { ExplicitlyDynamic, /// Has an explicit '@objc' attribute. ExplicitlyObjC, + /// Has an explicit '@objcmembers' attribute. + ExplicitlyObjCMembers, /// Has an explicit '@IBOutlet' attribute. ExplicitlyIBOutlet, /// Has an explicit '@IBAction' attribute. @@ -101,6 +103,7 @@ class ObjCReason { case ExplicitlyCDecl: case ExplicitlyDynamic: case ExplicitlyObjC: + case ExplicitlyObjCMembers: case ExplicitlyIBOutlet: case ExplicitlyIBAction: case ExplicitlyIBSegueAction: diff --git a/test/Sema/objcmembers_attr_requires_module.swift b/test/Sema/objcmembers_attr_requires_module.swift new file mode 100644 index 0000000000000..28cb5fe0a68c8 --- /dev/null +++ b/test/Sema/objcmembers_attr_requires_module.swift @@ -0,0 +1,6 @@ +// RUN: %target-swift-frontend -typecheck -verify -enable-objc-interop %s +// RUN: %target-swift-frontend -typecheck -verify -enable-objc-interop %s -parse-as-library + +@objcMembers class Oof { + // expected-error@-1 {{@objcMembers attribute used without importing module 'Foundation'}} +} From ee8fd046e6acc33c7d2bc7033be62fc961a90447 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Wed, 17 Aug 2022 12:42:15 -0700 Subject: [PATCH 178/491] [move-keyword] Make sure we error correctly on f(_move y, &y) and f(&y, _move y) This was actually crashing on the inout use since I at some point changed the isReinit code to use a more general routine to determine that which was incorrect. Instead, this is actually trying to recognize reinits that we know how to change into a non-reinit form (e.x.: store [assign] -> store [init]). Since the inout use was not handled by the convert reinit to init code, we crashed. Now we get the correct behavior since the access to y always occurs /before/ the formal evaluation of the inout. --- .../MoveKillsCopyableAddressesChecker.cpp | 22 ++++++++++- ...move_function_kills_copyable_addresses.sil | 39 +++++++++++++++++++ ...tion_kills_copyable_addressonly_vars.swift | 16 ++++++++ ...unction_kills_copyable_loadable_vars.swift | 16 ++++++++ 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 test/SILOptimizer/move_function_kills_copyable_addresses.sil diff --git a/lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp b/lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp index d8402d0c22a38..fc601d45baa0f 100644 --- a/lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp +++ b/lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp @@ -264,6 +264,24 @@ struct ClosureOperandState { } // namespace +/// Is this a reinit instruction that we know how to convert into its init form. +static bool isReinitToInitConvertibleInst(Operand *memUse) { + auto *memInst = memUse->getUser(); + switch (memInst->getKind()) { + default: + return false; + + case SILInstructionKind::CopyAddrInst: { + auto *cai = cast(memInst); + return !cai->isInitializationOfDest(); + } + case SILInstructionKind::StoreInst: { + auto *si = cast(memInst); + return si->getOwnershipQualifier() == StoreOwnershipQualifier::Assign; + } + } +} + static void convertMemoryReinitToInitForm(SILInstruction *memInst) { switch (memInst->getKind()) { default: @@ -932,7 +950,7 @@ bool GatherClosureUseVisitor::visitUse(Operand *op, AccessUseType useTy) { return true; } - if (memInstMustReinitialize(op)) { + if (isReinitToInitConvertibleInst(op)) { if (stripAccessMarkers(op->get()) != useState.address) { LLVM_DEBUG(llvm::dbgs() << "!!! Error! Found reinit use not on base address: " @@ -1308,7 +1326,7 @@ bool GatherLexicalLifetimeUseVisitor::visitUse(Operand *op, return true; } - if (memInstMustReinitialize(op)) { + if (isReinitToInitConvertibleInst(op)) { if (stripAccessMarkers(op->get()) != useState.address) { LLVM_DEBUG(llvm::dbgs() << "!!! Error! Found reinit use not on base address: " diff --git a/test/SILOptimizer/move_function_kills_copyable_addresses.sil b/test/SILOptimizer/move_function_kills_copyable_addresses.sil new file mode 100644 index 0000000000000..f0e36b33ee050 --- /dev/null +++ b/test/SILOptimizer/move_function_kills_copyable_addresses.sil @@ -0,0 +1,39 @@ +// RUN: %target-sil-opt -enable-sil-verify-all -o - -sil-move-kills-copyable-addresses-checker -verify %s + +// This file is meant for specific SIL patterns that may be hard to produce with +// the current swift frontend but have reproduced before and we want to make +// sure keep on working. + +sil_stage raw + +class Klass {} + +sil @useTwice : $@convention(thin) (@guaranteed Klass, @inout Klass) -> () + +sil hidden [ossa] @$s4test3fooyyAA5KlassCnF : $@convention(thin) (@owned Klass) -> () { +bb0(%0 : @owned $Klass): + %1 = begin_borrow [lexical] %0 : $Klass + debug_value %1 : $Klass, let, name "k", argno 1 + %3 = alloc_stack [lexical] $Klass, var, name "k2" // expected-error {{'k2' used after being moved}} + %4 = copy_value %1 : $Klass + %5 = move_value [allows_diagnostics] %4 : $Klass + store %5 to [init] %3 : $*Klass + %7 = begin_access [modify] [static] %3 : $*Klass + %8 = alloc_stack $Klass + mark_unresolved_move_addr %7 to %8 : $*Klass // expected-note {{move here}} + %10 = load [copy] %8 : $*Klass + destroy_addr %8 : $*Klass + end_access %7 : $*Klass + %13 = begin_access [modify] [static] %3 : $*Klass + %14 = function_ref @useTwice : $@convention(thin) (@guaranteed Klass, @inout Klass) -> () + %15 = apply %14(%10, %13) : $@convention(thin) (@guaranteed Klass, @inout Klass) -> () // expected-note {{use here}} + end_access %13 : $*Klass + destroy_value %10 : $Klass + dealloc_stack %8 : $*Klass + destroy_addr %3 : $*Klass + dealloc_stack %3 : $*Klass + end_borrow %1 : $Klass + destroy_value %0 : $Klass + %23 = tuple () + return %23 : $() +} \ No newline at end of file diff --git a/test/SILOptimizer/move_function_kills_copyable_addressonly_vars.swift b/test/SILOptimizer/move_function_kills_copyable_addressonly_vars.swift index c257901f81608..1c76a03297f06 100644 --- a/test/SILOptimizer/move_function_kills_copyable_addressonly_vars.swift +++ b/test/SILOptimizer/move_function_kills_copyable_addressonly_vars.swift @@ -688,3 +688,19 @@ func reinitInPieces1(_ k: ProtPair) { k2.lhs = selfType.getP() k2.rhs = selfType.getP() } + +//////////////////////// +// InOut and Use Test // +//////////////////////// + +func useValueAndInOut(_ x: T, _ y: inout T) {} +func useValueAndInOut(_ x: inout T, _ y: T) {} + +func inoutAndUseTest(_ x: T) { + var y = x // expected-error {{'y' used after being moved}} + // expected-error @-1 {{'y' used after being moved}} + useValueAndInOut(_move y, &y) // expected-note {{use here}} + // expected-note @-1 {{move here}} + useValueAndInOut(&y, _move y) // expected-note {{use here}} + // expected-note @-1 {{move here}} +} diff --git a/test/SILOptimizer/move_function_kills_copyable_loadable_vars.swift b/test/SILOptimizer/move_function_kills_copyable_loadable_vars.swift index 81a5e396e832b..0672a61e7b29d 100644 --- a/test/SILOptimizer/move_function_kills_copyable_loadable_vars.swift +++ b/test/SILOptimizer/move_function_kills_copyable_loadable_vars.swift @@ -729,3 +729,19 @@ func reinitInPieces1(_ k: KlassPair) { k2.lhs = Klass() k2.rhs = Klass() } + +//////////////////////// +// InOut and Use Test // +//////////////////////// + +func useValueAndInOut(_ x: Klass, _ y: inout Klass) {} +func useValueAndInOut(_ x: inout Klass, _ y: Klass) {} + +func inoutAndUseTest(_ x: Klass) { + var y = x // expected-error {{'y' used after being moved}} + // expected-error @-1 {{'y' used after being moved}} + useValueAndInOut(_move y, &y) // expected-note {{use here}} + // expected-note @-1 {{move here}} + useValueAndInOut(&y, _move y) // expected-note {{use here}} + // expected-note @-1 {{move here}} +} From ecccce61139bbc4f8ae24a1ef433ce3a998f4ce3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 18 Aug 2022 11:14:30 +0900 Subject: [PATCH 179/491] [Concurrency] Deprecate one of the cancellation handler overloads (#60569) --- .../public/BackDeployConcurrency/SourceCompatibilityShims.swift | 1 + stdlib/public/Concurrency/SourceCompatibilityShims.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/stdlib/public/BackDeployConcurrency/SourceCompatibilityShims.swift b/stdlib/public/BackDeployConcurrency/SourceCompatibilityShims.swift index 15b71fee3f173..93a8d886b9ccf 100644 --- a/stdlib/public/BackDeployConcurrency/SourceCompatibilityShims.swift +++ b/stdlib/public/BackDeployConcurrency/SourceCompatibilityShims.swift @@ -54,6 +54,7 @@ extension TaskPriority { @available(SwiftStdlib 5.1, *) @_alwaysEmitIntoClient +@available(*, deprecated, renamed: "withTaskCancellationHandler(operation:onCancel:)") public func withTaskCancellationHandler( handler: @Sendable () -> Void, operation: () async throws -> T diff --git a/stdlib/public/Concurrency/SourceCompatibilityShims.swift b/stdlib/public/Concurrency/SourceCompatibilityShims.swift index a4f22f7a63d03..d573cd34b9699 100644 --- a/stdlib/public/Concurrency/SourceCompatibilityShims.swift +++ b/stdlib/public/Concurrency/SourceCompatibilityShims.swift @@ -54,6 +54,7 @@ extension TaskPriority { @available(SwiftStdlib 5.1, *) @_alwaysEmitIntoClient +@available(*, deprecated, renamed: "withTaskCancellationHandler(operation:onCancel:)") public func withTaskCancellationHandler( handler: @Sendable () -> Void, operation: () async throws -> T From 06be02636c3649b58b073878873a73404ebbdbce Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Thu, 18 Aug 2022 05:35:09 +0300 Subject: [PATCH 180/491] Gardening: Migrate test suite to GH issues: Constraints (3/5) --- test/Constraints/function.swift | 72 ++++++++++------- test/Constraints/generics.swift | 108 +++++++++++++------------ test/Constraints/members.swift | 62 +++++++------- test/Constraints/patterns.swift | 66 ++++++++------- test/Constraints/tuple_arguments.swift | 63 ++++++++------- 5 files changed, 204 insertions(+), 167 deletions(-) diff --git a/test/Constraints/function.swift b/test/Constraints/function.swift index 568160eee9247..e0565b8a26f0d 100644 --- a/test/Constraints/function.swift +++ b/test/Constraints/function.swift @@ -75,34 +75,40 @@ func r22451001() -> AnyObject {} print(r22451001(5)) // expected-error {{argument passed to call that takes no arguments}} -// SR-590 Passing two parameters to a function that takes one argument of type Any crashes the compiler -// SR-1028: Segmentation Fault: 11 when superclass init takes parameter of type 'Any' -func sr590(_ x: Any) {} // expected-note {{'sr590' declared here}} -sr590(3,4) // expected-error {{extra argument in call}} -sr590() // expected-error {{missing argument for parameter #1 in call}} -// Make sure calling with structural tuples still works. -sr590(()) -sr590((1, 2)) - -// SR-2657: Poor diagnostics when function arguments should be '@escaping'. -private class SR2657BlockClass { // expected-note 4 {{generic parameters are always considered '@escaping'}} - let f: T - init(f: T) { self.f = f } +/// https://github.com/apple/swift/issues/43207 +/// Passing two parameters to a function that takes one argument of type `Any` +/// crashes the compiler +do { + func f(_ x: Any) {} // expected-note {{'f' declared here}} + + f(3,4) // expected-error {{extra argument in call}} + f() // expected-error {{missing argument for parameter #1 in call}} + // Make sure calling with structural tuples still works. + f(()) + f((1, 2)) } -func takesAny(_: Any) {} +/// https://github.com/apple/swift/issues/45262 +/// Poor diagnostics when function arguments should be `@escaping` +func f_45262(block: () -> (), other: () -> Int) { -func foo(block: () -> (), other: () -> Int) { - let _ = SR2657BlockClass(f: block) + class C { // expected-note 4 {{generic parameters are always considered '@escaping'}} + let f: T + init(f: T) { self.f = f } + } + + func takesAny(_: Any) {} + + let _ = C(f: block) // expected-error@-1 {{converting non-escaping parameter 'block' to generic parameter 'T' may allow it to escape}} - let _ = SR2657BlockClass<()->()>(f: block) + let _ = C<()->()>(f: block) // expected-error@-1 {{converting non-escaping parameter 'block' to generic parameter 'T' may allow it to escape}} - let _: SR2657BlockClass<()->()> = SR2657BlockClass(f: block) + let _: C<()->()> = C(f: block) // expected-error@-1 {{converting non-escaping parameter 'block' to generic parameter 'T' may allow it to escape}} - let _: SR2657BlockClass<()->()> = SR2657BlockClass<()->()>(f: block) + let _: C<()->()> = C<()->()>(f: block) // expected-error@-1 {{converting non-escaping parameter 'block' to generic parameter 'T' may allow it to escape}} - _ = SR2657BlockClass(f: block) // expected-error {{converting non-escaping value to 'Any' may allow it to escape}} - _ = SR2657BlockClass(f: other) // expected-error {{converting non-escaping value to 'Any' may allow it to escape}} + _ = C(f: block) // expected-error {{converting non-escaping value to 'Any' may allow it to escape}} + _ = C(f: other) // expected-error {{converting non-escaping value to 'Any' may allow it to escape}} takesAny(block) // expected-error {{converting non-escaping value to 'Any' may allow it to escape}} takesAny(other) // expected-error {{converting non-escaping value to 'Any' may allow it to escape}} } @@ -140,7 +146,8 @@ protocol Q { associatedtype U : P } -func sr10811(_ fn: () -> Int) { +// https://github.com/apple/swift/issues/53201 +func f_53201(_ fn: () -> Int) { struct S1 : P { typealias U = () -> Int } @@ -246,8 +253,8 @@ func test_passing_noescape_function_ref_to_generic_parameter() { } } -// SR-14784 -func SR14784(_ fs: () -> T..., a _ : Int) -> T { +// https://github.com/apple/swift/issues/57133 +func f_57133(_ fs: () -> T..., a _ : Int) -> T { fs.first! // expected-error{{function produces expected type 'T'; did you mean to call it with '()'?}} {{11-11=()}} } @@ -264,11 +271,14 @@ func testInvalidTupleImplosions() { tuplify(takesInout) // expected-error {{cannot convert value of type '(Int, inout String) -> ()' to expected argument type '(Int) -> Void'}} } -// SR-15179 -func SR15179(_ fn: @escaping (Ts) -> Void) {} // expected-note {{in call to function 'SR15179'}} -func fn1(x: Int..., y: Int...) {} -SR15179(fn1) // expected-error {{cannot convert value of type '(Int..., Int...) -> ()' to expected argument type '(Ts) -> Void'}} -// expected-error@-1{{generic parameter 'Ts' could not be inferred}} +// https://github.com/apple/swift/issues/57502 +do { + func f(_ fn: @escaping (Ts) -> Void) {} // expected-note {{in call to function 'f'}} -func fn(_ x: inout Int, _ y: inout Int) {} -SR15179(fn) // expected-error {{cannot convert value of type '(inout Int, inout Int) -> ()' to expected argument type '(Int) -> Void'}} + func g1(x: Int..., y: Int...) {} + f(g1) // expected-error {{cannot convert value of type '(Int..., Int...) -> ()' to expected argument type '(Ts) -> Void'}} + // expected-error@-1{{generic parameter 'Ts' could not be inferred}} + + func g2(_ x: inout Int, _ y: inout Int) {} + f(g2) // expected-error {{cannot convert value of type '(inout Int, inout Int) -> ()' to expected argument type '(Int) -> Void'}} +} diff --git a/test/Constraints/generics.swift b/test/Constraints/generics.swift index f127758a93a82..5169d9b925292 100644 --- a/test/Constraints/generics.swift +++ b/test/Constraints/generics.swift @@ -205,11 +205,9 @@ struct R24267414 { // expected-note {{'T' declared as parameter to type 'R24 var _ : Int = R24267414.foo() // expected-error {{generic parameter 'T' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{24-24=}} -// https://bugs.swift.org/browse/SR-599 -func SR599() -> T.Type { return T.self } // expected-note {{in call to function 'SR599()'}} -_ = SR599() // expected-error {{generic parameter 'T' could not be inferred}} - - +// https://github.com/apple/swift/issues/43216 +func f_43216() -> T.Type { return T.self } // expected-note {{in call to function 'f_43216()'}} +_ = f_43216() // expected-error {{generic parameter 'T' could not be inferred}} // QoI: Poor diagnostic when we are unable to infer type @@ -456,17 +454,20 @@ func genericFunc(t: T) { // expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} } -struct SR_3525 {} -func sr3525_arg_int(_: inout SR_3525) {} -func sr3525_arg_gen(_: inout SR_3525) {} -func sr3525_1(t: SR_3525) { - let _ = sr3525_arg_int(&t) // expected-error {{cannot pass immutable value as inout argument: 't' is a 'let' constant}} -} -func sr3525_2(t: SR_3525) { - let _ = sr3525_arg_gen(&t) // expected-error {{cannot pass immutable value as inout argument: 't' is a 'let' constant}} -} -func sr3525_3(t: SR_3525) { - let _ = sr3525_arg_gen(&t) // expected-error {{cannot pass immutable value as inout argument: 't' is a 'let' constant}} +// https://github.com/apple/swift/issues/46113 +do { + struct S {} + + func arg_int(_: inout S) {} + func arg_gen(_: inout S) {} + + func f1(t: S) { + let _ = arg_int(&t) // expected-error {{cannot pass immutable value as inout argument: 't' is a 'let' constant}} + let _ = arg_gen(&t) // expected-error {{cannot pass immutable value as inout argument: 't' is a 'let' constant}} + } + func f2(t: S) { + let _ = arg_gen(&t) // expected-error {{cannot pass immutable value as inout argument: 't' is a 'let' constant}} + } } class testStdlibType { @@ -566,7 +567,9 @@ func rdar35541153() { bar(y, "ultimate question", 42) // Ok } -// rdar://problem/38159133 - [SR-7125]: Swift 4.1 Xcode 9.3b4 regression +// rdar://problem/38159133 +// https://github.com/apple/swift/issues/49673 +// Swift 4.1 Xcode 9.3b4 regression protocol P_38159133 {} @@ -601,9 +604,8 @@ func rdar39616039() { c += 1 // ok } -// https://bugs.swift.org/browse/SR-8075 - -func sr8075() { +// https://github.com/apple/swift/issues/50608 +do { struct UIFont { init(ofSize: Float) {} } @@ -640,7 +642,7 @@ func rdar40537858() { let _: E = .bar([s]) // expected-error {{generic enum 'E' requires that 'S' conform to 'P'}} } -// https://bugs.swift.org/browse/SR-8934 +// https://github.com/apple/swift/issues/51439 struct BottleLayout { let count : Int } @@ -650,40 +652,38 @@ let ix = arr.firstIndex(of:layout) // expected-error {{referencing instance meth let _: () -> UInt8 = { .init("a" as Unicode.Scalar) } // expected-error {{missing argument label 'ascii:' in call}} -// https://bugs.swift.org/browse/SR-9068 +// https://github.com/apple/swift/issues/51569 func compare(c: C) -> Bool where C.Element == (key: Key, value: Value) { _ = Dictionary(uniqueKeysWithValues: Array(c)) } -// https://bugs.swift.org/browse/SR-7984 -struct SR_7984 { +// https://github.com/apple/swift/issues/50517 + +struct S1_50517 { func doSomething() {} } +extension S1_50517 where Bar: String {} // expected-error {{type 'Bar' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'Bar == String' to require 'Bar' to be 'String'}} {{29-30= ==}} -extension SR_7984 where Bar: String {} // expected-error {{type 'Bar' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'Bar == String' to require 'Bar' to be 'String'}} {{28-29= ==}} - -protocol SR_7984_Proto { +protocol P1_50517 { associatedtype Bar } +extension P1_50517 where Bar: String {} // expected-error {{type 'Self.Bar' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'Bar == String' to require 'Bar' to be 'String'}} {{29-30= ==}} -extension SR_7984_Proto where Bar: String {} // expected-error {{type 'Self.Bar' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'Bar == String' to require 'Bar' to be 'String'}} {{34-35= ==}} - -protocol SR_7984_HasFoo { +protocol P2_50517 { associatedtype Foo } -protocol SR_7984_HasAssoc { - associatedtype Assoc: SR_7984_HasFoo +protocol P3_50517 { + associatedtype Assoc: P2_50517 } +struct S2_50517 {} +extension S2_50517 where T.Assoc.Foo: String {} // expected-error {{type 'T.Assoc.Foo' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'T.Assoc.Foo == String' to require 'T.Assoc.Foo' to be 'String'}} {{37-38= ==}} -struct SR_7984_X {} -extension SR_7984_X where T.Assoc.Foo: String {} // expected-error {{type 'T.Assoc.Foo' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'T.Assoc.Foo == String' to require 'T.Assoc.Foo' to be 'String'}} {{38-39= ==}} - -struct SR_7984_S where T.Element: String {} // expected-error {{type 'T.Element' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'T.Element == String' to require 'T.Element' to be 'String'}} {{46-47= ==}} -func SR_7984_F(foo: T) where T.Element: String {} // expected-error {{type 'T.Element' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'T.Element == String' to require 'T.Element' to be 'String'}} {{52-53= ==}} +struct S3_50517 where T.Element: String {} // expected-error {{type 'T.Element' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'T.Element == String' to require 'T.Element' to be 'String'}} {{45-46= ==}} +func f_50517(foo: T) where T.Element: String {} // expected-error {{type 'T.Element' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'T.Element == String' to require 'T.Element' to be 'String'}} {{50-51= ==}} -protocol SR_7984_P { +protocol P4_50517 { func S(bar: T) where T.Element: String // expected-error {{type 'T.Element' constrained to non-protocol, non-class type 'String'}} expected-note {{use 'T.Element == String' to require 'T.Element' to be 'String'}} {{47-48= ==}} } @@ -710,10 +710,11 @@ protocol Q { init(_ x: T) // expected-note 2{{where 'T' = 'T'}} } -struct SR10694 { +// https://github.com/apple/swift/issues/53091 +struct S_53091 { init(_ x: T) {} // expected-note 3{{where 'T' = 'T'}} - func bar(_ x: T, _ s: SR10694, _ q: Q) { - SR10694.self(x) // expected-error {{initializer 'init(_:)' requires that 'T' conform to 'P'}} + func bar(_ x: T, _ s: S_53091, _ q: Q) { + S_53091.self(x) // expected-error {{initializer 'init(_:)' requires that 'T' conform to 'P'}} type(of: s)(x) // expected-error {{initializer 'init(_:)' requires that 'T' conform to 'P'}} // expected-error@-1 {{initializing from a metatype value must reference 'init' explicitly}} @@ -724,14 +725,17 @@ struct SR10694 { type(of: q)(x) // expected-error {{initializer 'init(_:)' requires that 'T' conform to 'P'}} // expected-error@-1 {{initializing from a metatype value must reference 'init' explicitly}} - var srTy = SR10694.self - srTy(x) // expected-error {{initializer 'init(_:)' requires that 'T' conform to 'P'}} + var ty = S_53091.self + ty(x) // expected-error {{initializer 'init(_:)' requires that 'T' conform to 'P'}} // expected-error@-1 {{initializing from a metatype value must reference 'init' explicitly}} } } -// SR-7003 (rdar://problem/51203824) - Poor diagnostics when attempting to access members on unfulfilled generic type -func sr_7003() { +// rdar://problem/51203824 +// https://github.com/apple/swift/issues/49551 +// Poor diagnostics when attempting to access members on unfulfilled +// generic type +func f_49551() { struct E { // expected-note 4 {{'T' declared as parameter to type 'E'}} static var foo: String { return "" } var bar: String { return "" } @@ -817,20 +821,22 @@ func test_correct_identification_of_requirement_source() { // expected-error@-1 {{initializer 'init(_:_:)' requires that 'Int' conform to 'P'}} } -struct SR11435 { +// https://github.com/apple/swift/issues/53836 + +struct S_53836 { subscript(x x: U) -> U { x } // expected-note {{where 'U' = 'Int'}} } - -extension SR11435 where T : P { // expected-note {{where 'T' = 'Int'}} +extension S_53836 where T : P { // expected-note {{where 'T' = 'Int'}} var foo: Int { 0 } } func test_identification_of_key_path_component_callees() { - _ = \SR11435.foo // expected-error {{property 'foo' requires that 'Int' conform to 'P'}} - _ = \SR11435.[x: 5] // expected-error {{subscript 'subscript(x:)' requires that 'Int' conform to 'P'}} + _ = \S_53836.foo // expected-error {{property 'foo' requires that 'Int' conform to 'P'}} + _ = \S_53836.[x: 5] // expected-error {{subscript 'subscript(x:)' requires that 'Int' conform to 'P'}} } -func sr_11491(_ value: [String]) { +// https://github.com/apple/swift/issues/53891 +func f_53891(_ value: [String]) { var arr: Set = [] arr.insert(value) // expected-error@-1 {{cannot convert value of type '[String]' to expected argument type 'String'}} diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift index 14eee4d19f41f..e6d88c45f27e8 100644 --- a/test/Constraints/members.swift +++ b/test/Constraints/members.swift @@ -329,7 +329,8 @@ let _ = .Tomato(cloud: .none) // expected-error {{reference to member 'Tomato' -// SR-650: REGRESSION: Assertion failed: (baseTy && "Couldn't find appropriate context"), function getMemberSubstitutions +// https://github.com/apple/swift/issues/43267 +// REGRESSION: Assertion failed: (baseTy && "Couldn't find appropriate context"), function getMemberSubstitutions enum SomeErrorType { case StandaloneError case UnderlyingError(String) @@ -341,15 +342,17 @@ enum SomeErrorType { } } -// SR-2193: QoI: better diagnostic when a decl exists, but is not a type - -enum SR_2193_Error: Error { - case Boom -} - +// https://github.com/apple/swift/issues/44801 +// QoI: Better diagnostic when a decl exists, but is not a type do { - throw SR_2193_Error.Boom -} catch let e as SR_2193_Error.Boom { // expected-error {{enum case 'Boom' is not a member type of 'SR_2193_Error'}} + enum E: Error { + case Boom + } + + do { + throw E.Boom + } catch let e as E.Boom { // expected-error {{enum case 'Boom' is not a member type of 'E'}} + } } // rdar://problem/25341015 @@ -450,8 +453,9 @@ func rdar33914444() { // expected-error@-1 {{type 'A.R' has no member 'e1'; did you mean 'e'?}} } -// SR-5324: Better diagnostic when instance member of outer type is referenced from nested type - +// https://github.com/apple/swift/issues/47898 +// Better diagnostic when instance member of outer type is referenced from +// nested type struct Outer { var outer: Int @@ -645,15 +649,18 @@ func rdar_50467583_and_50909555() { } } -// SR-9396 (rdar://problem/46427500) - Nonsensical error message related to constrained extensions -struct SR_9396 {} +// rdar://problem/46427500 +// https://github.com/apple/swift/issues/51862 +// Nonsensical error message related to constrained extensions -extension SR_9396 where A == Bool { // expected-note {{where 'A' = 'Int'}} +struct S_51862 {} + +extension S_51862 where A == Bool { // expected-note {{where 'A' = 'Int'}} func foo() {} } -func test_sr_9396(_ s: SR_9396) { - s.foo() // expected-error {{referencing instance method 'foo()' on 'SR_9396' requires the types 'Int' and 'Bool' be equivalent}} +func test_51862(_ s: S_51862) { + s.foo() // expected-error {{referencing instance method 'foo()' on 'S_51862' requires the types 'Int' and 'Bool' be equivalent}} } // rdar://problem/34770265 - Better diagnostic needed for constrained extension method call @@ -672,7 +679,7 @@ func test_34770265(_ dict: [Int: Int]) { // expected-error@-1 {{referencing instance method 'rdar_34770265_val()' on 'Dictionary' requires the types 'Int' and 'String' be equivalent}} } -// SR-12672 +// https://github.com/apple/swift/issues/55116 _ = [.e] // expected-error {{reference to member 'e' cannot be resolved without a contextual type}} let _ : [Any] = [.e] // expected-error {{type 'Any' has no member 'e'}} _ = [1 :.e] // expected-error {{reference to member 'e' cannot be resolved without a contextual type}} @@ -681,9 +688,9 @@ let _ : [Int: Any] = [1 : .e] // expected-error {{type 'Any' has no member 'e'}} let _ : (Int, Any) = (1, .e) // expected-error {{type 'Any' has no member 'e'}} _ = (1, .e) // expected-error {{cannot infer contextual base in reference to member 'e'}} -// SR-13359 +// https://github.com/apple/swift/issues/55799 typealias Pair = (Int, Int) -func testSR13359(_ pair: (Int, Int), _ alias: Pair, _ void: Void, labeled: (a: Int, b: Int)) { +func test_55799(_ pair: (Int, Int), _ alias: Pair, _ void: Void, labeled: (a: Int, b: Int)) { _ = pair[0] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; did you mean to use '.0'?}} {{11-14=.0}} _ = pair[1] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; did you mean to use '.1'?}} {{11-14=.1}} _ = pair[2] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; use '.' notation instead}} {{none}} @@ -743,14 +750,15 @@ func rdar55369704() { } } -// SR-14533 -struct SR14533 { - var xs: [Int] -} - -func fSR14533(_ s: SR14533) { - for (x1, x2) in zip(s.xs, s.ys) { - // expected-error@-1{{value of type 'SR14533' has no member 'ys'}} +// https://github.com/apple/swift/issues/56885 +do { + struct S { + var xs: [Int] // expected-note {{'xs' declared here}} + } + func f(_ s: S) { + for (x1, x2) in zip(s.xs, s.ys) { + // expected-error@-1 {{value of type 'S' has no member 'ys'; did you mean 'xs'?}} + } } } diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift index b6769f32224a7..755f8a77c4e92 100644 --- a/test/Constraints/patterns.swift +++ b/test/Constraints/patterns.swift @@ -135,7 +135,8 @@ case let x?: break // expected-warning{{immutable value 'x' was never used; cons case nil: break } -func SR2066(x: Int?) { +// https://github.com/apple/swift/issues/44675 +func f_44675(x: Int?) { // nil literals should still work when wrapped in parentheses switch x { case (nil): break @@ -247,16 +248,16 @@ func ugly(_ a: A) { } } -// SR-2057 +// https://github.com/apple/swift/issues/44666 +do { + enum E { + case foo + } -enum SR2057 { - case foo + let x: E? + if case .foo = x { } // Ok } -let sr2057: SR2057? -if case .foo = sr2057 { } // Ok - - // Invalid 'is' pattern class SomeClass {} if case let doesNotExist as SomeClass:AlsoDoesNotExist {} @@ -337,7 +338,8 @@ func rdar32241441() { } -// SR-6100 +// https://github.com/apple/swift/issues/48655 + struct One { // expected-note{{'Two' declared as parameter to type 'One'}} public enum E: Error { // if you remove associated value, everything works @@ -352,9 +354,10 @@ func testOne() { } } -// SR-8347 -// constrain initializer expressions of optional some pattern bindings to be optional -func test8347() -> String { +// https://github.com/apple/swift/issues/50875 +// Constrain initializer expressions of optional some pattern bindings to +// be optional. +func test_50875() -> String { struct C { subscript (s: String) -> String? { return "" @@ -404,29 +407,32 @@ func test8347() -> String { } } -enum SR_7799 { - case baz - case bar -} +// https://github.com/apple/swift/issues/50338 +do { + enum E { + case baz + case bar + } -let sr7799: SR_7799? = .bar + let oe: E? = .bar -switch sr7799 { - case .bar?: break // Ok - case .baz: break // Ok - default: break -} + switch oe { + case .bar?: break // Ok + case .baz: break // Ok + default: break + } -let sr7799_1: SR_7799?? = .baz + let ooe: E?? = .baz -switch sr7799_1 { - case .bar?: break // Ok - case .baz: break // Ok - default: break -} + switch ooe { + case .bar?: break // Ok + case .baz: break // Ok + default: break + } -if case .baz = sr7799_1 {} // Ok -if case .bar? = sr7799_1 {} // Ok + if case .baz = ooe {} // Ok + if case .bar? = ooe {} // Ok +} // rdar://problem/60048356 - `if case` fails when `_` pattern doesn't have a label func rdar_60048356() { diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift index 99d9de4369c50..10fa59a5827ae 100644 --- a/test/Constraints/tuple_arguments.swift +++ b/test/Constraints/tuple_arguments.swift @@ -1452,7 +1452,7 @@ func singleElementTupleArgument(completion: ((didAdjust: Bool)) -> Void) { } -// SR-4378 +// https://github.com/apple/swift/issues/46957 final public class MutableProperty { public init(_ initialValue: Value) {} @@ -1479,18 +1479,21 @@ let pages3: MutableProperty<(data: DataSourcePage, totalCount: Int)> = Muta totalCount: 0 )) -// SR-4745 -let sr4745 = [1, 2] -let _ = sr4745.enumerated().map { (count, element) in "\(count): \(element)" } - -// SR-4738 +// https://github.com/apple/swift/issues/47322 +do { + let x = [1, 2] + let _ = x.enumerated().map { (count, element) in "\(count): \(element)" } +} -let sr4738 = (1, (2, 3)) -[sr4738].map { (x, (y, z)) -> Int in x + y + z } // expected-note 2 {{'x' declared here}} -// expected-error@-1 {{closure tuple parameter does not support destructuring}} {{20-26=arg1}} {{38-38=let (y, z) = arg1; }} -// expected-warning@-2 {{unnamed parameters must be written with the empty name '_'}} {{20-20=_: }} -// expected-error@-3 {{cannot find 'y' in scope; did you mean 'x'?}} -// expected-error@-4 {{cannot find 'z' in scope; did you mean 'x'?}} +// https://github.com/apple/swift/issues/47315 +do { + let tuple = (1, (2, 3)) + [tuple].map { (x, (y, z)) -> Int in x + y + z } // expected-note 2 {{'x' declared here}} + // expected-error@-1 {{closure tuple parameter does not support destructuring}} {{21-27=arg1}} {{39-39=let (y, z) = arg1; }} + // expected-warning@-2 {{unnamed parameters must be written with the empty name '_'}} {{21-21=_: }} + // expected-error@-3 {{cannot find 'y' in scope; did you mean 'x'?}} + // expected-error@-4 {{cannot find 'z' in scope; did you mean 'x'?}} +} // rdar://problem/31892961 let r31892961_1 = [1: 1, 2: 2] @@ -1572,11 +1575,12 @@ func rdar32875953() { _ = zip(array1, array2).map(+) } -struct SR_5199 {} +// https://github.com/apple/swift/issues/47775 +struct S_47775 {} extension Sequence where Iterator.Element == (key: String, value: String?) { - func f() -> [SR_5199] { + func f() -> [S_47775] { return self.map { (key, value) in - SR_5199() // Ok + S_47775() // Ok } } } @@ -1604,7 +1608,8 @@ func rdar33159366(s: AnySequence) { _ = a.compactMap(itsFalse) } -func sr5429(t: T) { +// https://github.com/apple/swift/issues/48003 +func f_48003(t: T) { _ = AnySequence([t]).first(where: { (t: T) in true }) } @@ -1657,7 +1662,7 @@ do { foo(bar()) // expected-error {{cannot convert value of type '((()) -> Void)?' to expected argument type '(() -> Void)?'}} } -// https://bugs.swift.org/browse/SR-6509 +// https://github.com/apple/swift/issues/49059 public extension Optional { func apply(_ transform: ((Wrapped) -> Result)?) -> Result? { return self.flatMap { value in @@ -1671,7 +1676,7 @@ public extension Optional { } } -// https://bugs.swift.org/browse/SR-6837 +// https://github.com/apple/swift/issues/49386 // FIXME: Can't overload local functions so these must be top-level func takePairOverload(_ pair: (Int, Int?)) {} @@ -1688,7 +1693,7 @@ do { // expected-error@-1 {{contextual closure type '(Int, Int?) -> ()' expects 2 arguments, but 1 was used in closure body}} } -// https://bugs.swift.org/browse/SR-6796 +// https://github.com/apple/swift/issues/49345 do { func f(a: (() -> Void)? = nil) {} func log() -> ((T) -> Void)? { return nil } @@ -1705,17 +1710,19 @@ do { h() // expected-error {{missing argument for parameter #1 in call}} } -// https://bugs.swift.org/browse/SR-7191 -class Mappable { - init(_: T) { } - func map(_ body: (T) -> U) -> U { fatalError() } -} +// https://github.com/apple/swift/issues/49739 +do { + class Mappable { + init(_: T) { } + func map(_ body: (T) -> U) -> U { fatalError() } + } -let x = Mappable(()) -x.map { (_: Void) in return () } -x.map { (_: ()) in () } + let x = Mappable(()) + x.map { (_: Void) in return () } + x.map { (_: ()) in () } +} -// https://bugs.swift.org/browse/SR-9470 +// https://github.com/apple/swift/issues/51932 do { func f(_: Int...) {} let _ = [(1, 2, 3)].map(f) // expected-error {{no exact matches in call to instance method 'map'}} From 1cc4054600472197f953eb693c5ca99424d771c0 Mon Sep 17 00:00:00 2001 From: YOCKOW Date: Thu, 18 Aug 2022 12:42:34 +0900 Subject: [PATCH 181/491] [build-script] Omit "Build Script Analyzer" when `SystemExit` is caught. The content of ".build_script_log" file may be debris when `SystemExit` is thrown; e.g. `--help` is passed. Resolves https://github.com/apple/swift/issues/60567 --- utils/build-script | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/build-script b/utils/build-script index 1f9f32b653385..c7497c09665b6 100755 --- a/utils/build-script +++ b/utils/build-script @@ -718,6 +718,8 @@ def main(): if __name__ == "__main__": try: exit_code = main() + except SystemExit as e: + os._exit(e.code) except KeyboardInterrupt: sys.exit(1) finally: From 8713d78704f9e87c1e5e8913915a86dacbabf1c2 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 15 Aug 2022 20:10:41 -0400 Subject: [PATCH 182/491] [PrintOptions] Print explicit 'any' in SIL. --- include/swift/AST/PrintOptions.h | 1 + lib/SIL/IR/SILPrinter.cpp | 1 + lib/Sema/TypeCheckType.cpp | 3 + .../SILOptimizer/activity_analysis.swift | 8 +- test/ClangImporter/serialization-sil.swift | 26 +- test/Concurrency/async_main.swift | 22 +- test/Constraints/ranking.swift | 30 +- ...distributed_actor_default_init_sil_4.swift | 4 +- ...distributed_actor_default_init_sil_6.swift | 8 +- ...distributed_actor_default_init_sil_7.swift | 6 +- test/Frontend/module-alias-emit-sil.swift | 12 +- test/IRGen/async/async_calls_verifier.sil | 4 +- .../OwnershipVerifier/interior_pointer.sil | 6 +- test/SIL/Parser/async.sil | 4 +- test/SIL/Parser/basic.sil | 50 +- test/SIL/Parser/basic_objc.sil | 2 +- test/SIL/Parser/opaque_values_parse.sil | 12 +- test/SIL/Parser/polymorphic_function.sil | 2 +- test/SIL/Parser/protocol_getter.sil | 4 +- test/SIL/Parser/undef.sil | 26 +- test/SIL/Parser/undef_objc.sil | 2 +- test/SIL/Parser/witness_method.sil | 2 +- test/SIL/Serialization/async.sil | 6 +- .../Serialization/opaque_values_serialize.sil | 12 +- test/SILGen/SILDeclRef.swift | 2 +- test/SILGen/address_only_types.swift | 52 +- test/SILGen/assignment.swift | 12 +- test/SILGen/async_builtins.swift | 22 +- test/SILGen/async_let.swift | 2 +- .../back_deploy_attribute_throwing_func.swift | 30 +- test/SILGen/boxed_existentials.swift | 60 +- test/SILGen/builtins.swift | 14 +- test/SILGen/call_as_function.swift | 6 +- test/SILGen/casts.swift | 6 +- test/SILGen/class_bound_protocols.swift | 106 +-- .../struct_codable_member_type_lookup.swift | 6 +- test/SILGen/default_arguments.swift | 34 +- test/SILGen/dependent_member_lowering.swift | 2 +- test/SILGen/distributed_thunk.swift | 6 +- test/SILGen/dynamic.swift | 4 +- test/SILGen/dynamic_callable_attribute.swift | 6 +- test/SILGen/dynamic_lookup.swift | 18 +- test/SILGen/dynamic_lookup_throws.swift | 4 +- test/SILGen/dynamic_self.swift | 110 +-- test/SILGen/effectful_properties.swift | 8 +- test/SILGen/enum.swift | 6 +- test/SILGen/errors.swift | 268 +++---- test/SILGen/existential_erasure.swift | 40 +- ...ntial_member_accesses_self_assoctype.swift | 654 +++++++++--------- test/SILGen/existential_metatypes.swift | 22 +- test/SILGen/foreach.swift | 24 +- test/SILGen/foreign_errors.swift | 50 +- test/SILGen/function_conversion.swift | 58 +- test/SILGen/function_conversion_objc.swift | 10 +- test/SILGen/function_type_lowering.swift | 2 +- test/SILGen/functions.swift | 8 +- test/SILGen/generic_casts.swift | 26 +- test/SILGen/generic_closures.swift | 8 +- .../generic_property_base_lifetime.swift | 26 +- test/SILGen/generic_witness.swift | 8 +- test/SILGen/guaranteed_closure_context.swift | 8 +- test/SILGen/hop_to_executor.swift | 4 +- test/SILGen/if_expr.swift | 6 +- test/SILGen/init_delegation_optional.swift | 30 +- test/SILGen/initializers.swift | 82 +-- test/SILGen/keypaths_objc_optional.swift | 22 +- test/SILGen/let_decls.swift | 24 +- test/SILGen/lifetime.swift | 8 +- test/SILGen/literals.swift | 20 +- test/SILGen/mangling.swift | 10 +- test/SILGen/metatype_casts.swift | 2 +- test/SILGen/metatype_object_conversion.swift | 2 +- test/SILGen/metatypes.swift | 14 +- test/SILGen/noimplicitcopy.swift | 32 +- test/SILGen/objc_async.swift | 26 +- test/SILGen/objc_async_from_swift.swift | 2 +- test/SILGen/objc_bridging_any.swift | 56 +- test/SILGen/objc_bridging_array.swift | 4 +- test/SILGen/objc_effectful_properties.swift | 8 +- test/SILGen/objc_error.swift | 28 +- test/SILGen/objc_factory_init.swift | 8 +- test/SILGen/objc_ownership_conventions.swift | 28 +- test/SILGen/objc_protocols.swift | 50 +- test/SILGen/opaque_values_silgen.swift | 38 +- test/SILGen/opaque_values_silgen_lib.swift | 170 ++--- test/SILGen/opened_existentials.swift | 8 +- test/SILGen/optional_to_bool.swift | 2 +- test/SILGen/ownership.swift | 6 +- test/SILGen/parameterized_existentials.swift | 60 +- test/SILGen/partial_apply_override.swift | 4 +- test/SILGen/partial_apply_protocol.swift | 42 +- ...ply_protocol_class_refinement_method.swift | 2 +- test/SILGen/partial_apply_throws.swift | 8 +- test/SILGen/preconcurrency.swift | 6 +- test/SILGen/properties.swift | 24 +- test/SILGen/protocol_extensions.swift | 72 +- test/SILGen/protocol_optional.swift | 10 +- test/SILGen/protocol_with_superclass.swift | 56 +- ...rotocol_with_superclass_where_clause.swift | 56 +- test/SILGen/protocols.swift | 74 +- test/SILGen/reabstract.swift | 2 +- test/SILGen/reasync.swift | 8 +- test/SILGen/rethrows.swift | 40 +- test/SILGen/sil_locations.swift | 6 +- test/SILGen/subclass_existentials.swift | 272 ++++---- test/SILGen/switch.swift | 18 +- test/SILGen/switch_var.swift | 22 +- .../synthesized_conformance_class.swift | 18 +- .../SILGen/synthesized_conformance_enum.swift | 18 +- .../synthesized_conformance_struct.swift | 12 +- test/SILGen/toplevel_errors.swift | 12 +- test/SILGen/tuples.swift | 48 +- test/SILGen/value_ownership.swift | 6 +- test/SILGen/without_actually_escaping.swift | 8 +- test/SILGen/witnesses.swift | 22 +- test/SILGen/witnesses_class.swift | 4 +- test/SILGen/writeback.swift | 18 +- .../access_enforcement_selection.swift | 4 +- test/SILOptimizer/access_marker_verify.swift | 94 +-- test/SILOptimizer/address_lowering.sil | 236 +++---- test/SILOptimizer/address_lowering_lib.sil | 16 +- test/SILOptimizer/allocbox_to_stack.sil | 28 +- .../allocbox_to_stack_ownership.sil | 20 +- .../allocboxtostack_localapply.sil | 14 +- .../allocboxtostack_localapply_ossa.sil | 14 +- test/SILOptimizer/allocstack_hoisting.sil | 8 +- .../anyhashable_to_protocol.swift | 2 +- test/SILOptimizer/arcsequenceopts.sil | 26 +- test/SILOptimizer/array_property_opt.sil | 8 +- .../array_property_opt_ossa_guaranteed.sil | 8 +- .../array_property_opt_ossa_owned.sil | 8 +- .../assemblyvision_remark/cast_remarks.swift | 20 +- test/SILOptimizer/basic-aa.sil | 12 +- test/SILOptimizer/capture_propagation.sil | 78 +-- test/SILOptimizer/cast_folding.swift | 2 +- ...cast_folding_conditional_conformance.swift | 4 +- .../cast_folding_parameterized_protocol.swift | 58 +- ...cast_optimizer_conditional_conformance.sil | 66 +- .../castoptimizer-wrongscope.swift | 4 +- .../closure_lifetime_fixup_objc.swift | 10 +- test/SILOptimizer/closure_specialize.sil | 12 +- .../closure_specialize_consolidated.sil | 30 +- test/SILOptimizer/constant_propagation.sil | 6 +- .../constant_propagation_ownership.sil | 8 +- test/SILOptimizer/copy_propagation_borrow.sil | 14 +- test/SILOptimizer/copy_propagation_opaque.sil | 22 +- .../cross-module-optimization.swift | 4 +- test/SILOptimizer/cse.sil | 28 +- .../cse_metatype_conformance.swift | 12 +- test/SILOptimizer/cse_objc.sil | 6 +- test/SILOptimizer/cse_objc_ossa.sil | 6 +- test/SILOptimizer/cse_ossa.sil | 20 +- .../dead_code_elimination_nontrivial_ossa.sil | 14 +- .../definite-init-wrongscope.swift | 8 +- test/SILOptimizer/definite_init_actor.swift | 2 +- test/SILOptimizer/definite_init_closures.sil | 16 +- test/SILOptimizer/definite_init_crashes.sil | 10 +- .../definite_init_failable_initializers.swift | 156 ++--- ..._init_markuninitialized_delegatingself.sil | 6 +- .../devirt_protocol_method_invocations.swift | 10 +- test/SILOptimizer/devirt_speculative.sil | 8 +- test/SILOptimizer/devirt_try_apply.sil | 76 +- .../devirt_try_apply_ownership.sil | 76 +- .../di-conditional-destroy-scope.swift | 2 +- test/SILOptimizer/diagnose_unreachable.sil | 28 +- test/SILOptimizer/eager_specialize.sil | 40 +- test/SILOptimizer/eager_specialize_ossa.sil | 50 +- test/SILOptimizer/escape_analysis.sil | 26 +- .../escape_analysis_invalidate.sil | 18 +- .../escape_analysis_release_hoisting.sil | 10 +- ...clusivity_static_diagnostics_inlined.swift | 8 +- ...existential_specializer_indirect_class.sil | 4 +- .../existential_specializer_soletype.sil | 144 ++-- .../existential_spl_witness_method.swift | 4 +- .../existential_transform_extras.sil | 14 +- .../existential_transform_extras_ossa.sil | 14 +- .../existential_transform_respecialize.sil | 2 +- .../existential_transform_soletype.swift | 4 +- .../for_each_loop_unroll_test.sil | 50 +- test/SILOptimizer/functionsigopts.sil | 20 +- test/SILOptimizer/inline_lifetime.sil | 14 +- .../inline_subclass_existential.swift | 8 +- test/SILOptimizer/inline_tryApply.sil | 2 +- .../SILOptimizer/lexical_destroy_hoisting.sil | 2 +- test/SILOptimizer/licm.sil | 2 +- test/SILOptimizer/mandatory_combiner.sil | 8 +- test/SILOptimizer/mandatory_inlining.sil | 28 +- .../mandatory_inlining_devirt.swift | 6 +- .../mandatory_inlining_open_existential.swift | 8 +- .../mandatory_inlining_ownership.sil | 18 +- .../mandatory_inlining_ownership2.sil | 32 +- test/SILOptimizer/mem-behavior.sil | 4 +- test/SILOptimizer/mem2reg_lifetime.sil | 6 +- test/SILOptimizer/partial_specialization.sil | 2 +- .../retain_release_code_motion.sil | 8 +- test/SILOptimizer/shrink_borrow_scope.sil | 4 +- test/SILOptimizer/sil_combine.sil | 22 +- test/SILOptimizer/sil_combine1.swift | 2 +- test/SILOptimizer/sil_combine_apply.sil | 30 +- test/SILOptimizer/sil_combine_apply_ossa.sil | 20 +- .../sil_combine_concrete_existential.sil | 100 +-- .../sil_combine_concrete_existential.swift | 38 +- test/SILOptimizer/sil_combine_enum_addr.sil | 12 +- .../sil_combine_enum_addr_ossa.sil | 4 +- test/SILOptimizer/sil_combine_objc_bridge.sil | 2 +- .../sil_combine_objc_bridge_ossa.sil | 2 +- test/SILOptimizer/sil_combine_ossa.sil | 10 +- ...ombine_peephole_thick_to_objc_metatype.sil | 6 +- ...e_peephole_thick_to_objc_metatype_ossa.sil | 6 +- .../sil_combine_protocol_conf.swift | 50 +- .../sil_combiner_concrete_prop_all_args.sil | 40 +- test/SILOptimizer/sil_simplify_instrs.sil | 4 +- .../SILOptimizer/sil_simplify_instrs_ossa.sil | 4 +- test/SILOptimizer/simplify-cfg-debugonly.sil | 4 +- test/SILOptimizer/simplify_cfg.sil | 6 +- test/SILOptimizer/simplify_cfg_ossa.sil | 4 +- test/SILOptimizer/simplify_cfg_tryapply.sil | 10 +- test/SILOptimizer/specialize.sil | 2 +- ...tatypes_with_nondefault_representation.sil | 4 +- ...es_with_nondefault_representation_ossa.sil | 4 +- .../specialize_opaque_type_archetypes.swift | 2 +- test/SILOptimizer/specialize_ossa.sil | 6 +- .../specialize_partial_apply.swift | 28 +- .../specialize_self_conforming.swift | 4 +- .../specialize_self_conforming_error.swift | 18 +- .../specialized_anyobject_conformance.swift | 2 +- test/SILOptimizer/sr-5068.sil | 16 +- .../stack-nesting-wrong-scope.swift | 4 +- test/SILOptimizer/stack_promotion.sil | 4 +- test/SILOptimizer/temp_rvalue_opt.sil | 4 +- test/SILOptimizer/temp_rvalue_opt_ossa.sil | 4 +- test/SILOptimizer/templvalueopt.sil | 6 +- test/SILOptimizer/templvalueopt_ossa.sil | 6 +- test/SILOptimizer/throw_inline.swift | 2 +- test/SILOptimizer/typed-access-tb-aa.sil | 6 +- test/SILOptimizer/unexpected_error.sil | 4 +- test/Serialization/Inputs/def_basic.sil | 58 +- test/Serialization/Inputs/def_basic_objc.sil | 2 +- test/Serialization/function.swift | 4 +- test/Serialization/objc.swift | 4 +- test/Serialization/transparent.swift | 4 +- test/TypeDecoder/lowered_function_types.swift | 2 +- test/TypeDecoder/lowered_metatypes.swift | 2 +- test/attr/attr_objc.swift | 8 +- .../coding/class_codable_inherited.swift | 4 +- test/stdlib/unmanaged_rc.swift | 6 +- 246 files changed, 3050 insertions(+), 3045 deletions(-) diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index e4a227ce8d200..d31b482a33c39 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -679,6 +679,7 @@ struct PrintOptions { static PrintOptions printQualifiedSILType() { PrintOptions result = PrintOptions::printSIL(); result.FullyQualifiedTypesIfAmbiguous = true; + result.PrintExplicitAny = true; return result; } diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index b034830eca85e..d155afe87b30d 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -4067,6 +4067,7 @@ PrintOptions PrintOptions::printSIL(const SILPrintContext *ctx) { result.PrintInSILBody = true; result.PreferTypeRepr = false; result.PrintIfConfig = false; + result.PrintExplicitAny = true; result.OpaqueReturnTypePrinting = OpaqueReturnTypePrintingMode::StableReference; if (ctx && ctx->printFullConvention()) diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index d35ab74bd9e85..d47288a4b041e 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -2507,6 +2507,9 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr, attrs.has(TAK_objc_metatype)) { if (auto SF = getDeclContext()->getParentSourceFile()) { if (SF->Kind == SourceFileKind::SIL) { + if (auto existential = dyn_cast(repr)) + repr = existential->getConstraint(); + TypeRepr *base; if (auto metatypeRepr = dyn_cast(repr)) { base = metatypeRepr->getBase(); diff --git a/test/AutoDiff/SILOptimizer/activity_analysis.swift b/test/AutoDiff/SILOptimizer/activity_analysis.swift index 3281dbe7f2358..dfecc3f25757c 100644 --- a/test/AutoDiff/SILOptimizer/activity_analysis.swift +++ b/test/AutoDiff/SILOptimizer/activity_analysis.swift @@ -141,7 +141,7 @@ func checked_cast_branch(_ x: Float) -> Float { // CHECK: [NONE] %2 = metatype $@thin Int.Type // CHECK: [NONE] %3 = metatype $@thick Int.Type // CHECK: bb1: -// CHECK: [NONE] %5 = argument of bb1 : $@thick Any.Type +// CHECK: [NONE] %5 = argument of bb1 : $@thick any Any.Type // CHECK: [NONE] %6 = integer_literal $Builtin.Int1, -1 // CHECK: bb2: // CHECK: [NONE] %8 = argument of bb2 : $@thick Int.Type @@ -162,7 +162,7 @@ func checked_cast_branch(_ x: Float) -> Float { // CHECK: [ACTIVE] %23 = apply %22(%0, %0, %21) : $@convention(method) (Float, Float, @thin Float.Type) -> Float // CHECK-LABEL: sil hidden [ossa] @${{.*}}checked_cast_branch{{.*}} : $@convention(thin) (Float) -> Float { -// CHECK: checked_cast_br %3 : $@thick Int.Type to Any.Type, bb1, bb2 +// CHECK: checked_cast_br %3 : $@thick Int.Type to any Any.Type, bb1, bb2 // CHECK: } @differentiable(reverse) @@ -552,12 +552,12 @@ func testTryApply(_ x: Float) -> Float { // CHECK: bb0: // CHECK: [ACTIVE] %0 = argument of bb0 : $Float // CHECK: [NONE] // function_ref closure #1 in testTryApply(_:) -// CHECK: [NONE] %3 = thin_to_thick_function %2 : $@convention(thin) () -> @error Error to $@noescape @callee_guaranteed () -> @error Error +// CHECK: [NONE] %3 = thin_to_thick_function %2 : $@convention(thin) () -> @error any Error to $@noescape @callee_guaranteed () -> @error any Error // CHECK: [NONE] // function_ref rethrowing(_:) // CHECK: bb1: // CHECK: [NONE] %6 = argument of bb1 : $() // CHECK: bb2: -// CHECK: [NONE] %8 = argument of bb2 : $Error +// CHECK: [NONE] %8 = argument of bb2 : $any Error //===----------------------------------------------------------------------===// // Coroutine differentiation (`begin_apply`) diff --git a/test/ClangImporter/serialization-sil.swift b/test/ClangImporter/serialization-sil.swift index 15cbfc3bc368c..fadb8fe401526 100644 --- a/test/ClangImporter/serialization-sil.swift +++ b/test/ClangImporter/serialization-sil.swift @@ -7,40 +7,40 @@ // @_transparent to force serialization. @_transparent public func testPartialApply(_ obj: Test) { - // CHECK-LABEL: @$s4Test16testPartialApplyyySoAA_pF : $@convention(thin) (@guaranteed Test) -> () { + // CHECK-LABEL: @$s4Test16testPartialApplyyySoAA_pF : $@convention(thin) (@guaranteed any Test) -> () { if let curried1 = obj.normalObject { - // CHECK: dynamic_method_br [[CURRIED1_OBJ:%.+]] : $@opened([[CURRIED1_EXISTENTIAL:.+]], Test) Self, #Test.normalObject!foreign, [[CURRIED1_TRUE:[^,]+]], [[CURRIED1_FALSE:[^,]+]] + // CHECK: dynamic_method_br [[CURRIED1_OBJ:%.+]] : $@opened([[CURRIED1_EXISTENTIAL:.+]], any Test) Self, #Test.normalObject!foreign, [[CURRIED1_TRUE:[^,]+]], [[CURRIED1_FALSE:[^,]+]] // CHECK: [[CURRIED1_FALSE]]: - // CHECK: [[CURRIED1_TRUE]]([[CURRIED1_METHOD:%.+]] : $@convention(objc_method) (@opened([[CURRIED1_EXISTENTIAL]], Test) Self) -> @autoreleased AnyObject): + // CHECK: [[CURRIED1_TRUE]]([[CURRIED1_METHOD:%.+]] : $@convention(objc_method) (@opened([[CURRIED1_EXISTENTIAL]], any Test) Self) -> @autoreleased AnyObject): // CHECK: [[CURRIED1_OBJECT_COPY:%.*]] = copy_value [[CURRIED1_OBJ]] - // CHECK: [[CURRIED1_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[CURRIED1_METHOD]]([[CURRIED1_OBJECT_COPY]]) : $@convention(objc_method) (@opened([[CURRIED1_EXISTENTIAL]], Test) Self) -> @autoreleased AnyObject + // CHECK: [[CURRIED1_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[CURRIED1_METHOD]]([[CURRIED1_OBJECT_COPY]]) : $@convention(objc_method) (@opened([[CURRIED1_EXISTENTIAL]], any Test) Self) -> @autoreleased AnyObject // CHECK: [[CURRIED1_THUNK:%.+]] = function_ref @$syXlIego_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @owned AnyObject) -> @out Any // CHECK: = partial_apply [callee_guaranteed] [[CURRIED1_THUNK]]([[CURRIED1_PARTIAL]]) curried1() } if let curried2 = obj.innerPointer { - // CHECK: dynamic_method_br [[CURRIED2_OBJ:%.+]] : $@opened([[CURRIED2_EXISTENTIAL:.+]], Test) Self, #Test.innerPointer!foreign, [[CURRIED2_TRUE:[^,]+]], [[CURRIED2_FALSE:[^,]+]] + // CHECK: dynamic_method_br [[CURRIED2_OBJ:%.+]] : $@opened([[CURRIED2_EXISTENTIAL:.+]], any Test) Self, #Test.innerPointer!foreign, [[CURRIED2_TRUE:[^,]+]], [[CURRIED2_FALSE:[^,]+]] // CHECK: [[CURRIED2_FALSE]]: - // CHECK: [[CURRIED2_TRUE]]([[CURRIED2_METHOD:%.+]] : $@convention(objc_method) (@opened([[CURRIED2_EXISTENTIAL]], Test) Self) -> @unowned_inner_pointer UnsafeMutableRawPointer): + // CHECK: [[CURRIED2_TRUE]]([[CURRIED2_METHOD:%.+]] : $@convention(objc_method) (@opened([[CURRIED2_EXISTENTIAL]], any Test) Self) -> @unowned_inner_pointer UnsafeMutableRawPointer): // CHECK: [[CURRIED2_OBJ_COPY:%.*]] = copy_value [[CURRIED2_OBJ]] - // CHECK: [[CURRIED2_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[CURRIED2_METHOD]]([[CURRIED2_OBJ_COPY]]) : $@convention(objc_method) (@opened([[CURRIED2_EXISTENTIAL]], Test) Self) -> @unowned_inner_pointer UnsafeMutableRawPointer + // CHECK: [[CURRIED2_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[CURRIED2_METHOD]]([[CURRIED2_OBJ_COPY]]) : $@convention(objc_method) (@opened([[CURRIED2_EXISTENTIAL]], any Test) Self) -> @unowned_inner_pointer UnsafeMutableRawPointer curried2() } if let prop1 = obj.normalObjectProp { - // CHECK: dynamic_method_br [[PROP1_OBJ:%.+]] : $@opened([[PROP1_EXISTENTIAL:.+]], Test) Self, #Test.normalObjectProp!getter.foreign, [[PROP1_TRUE:[^,]+]], [[PROP1_FALSE:[^,]+]] + // CHECK: dynamic_method_br [[PROP1_OBJ:%.+]] : $@opened([[PROP1_EXISTENTIAL:.+]], any Test) Self, #Test.normalObjectProp!getter.foreign, [[PROP1_TRUE:[^,]+]], [[PROP1_FALSE:[^,]+]] // CHECK: [[PROP1_FALSE]]: - // CHECK: [[PROP1_TRUE]]([[PROP1_METHOD:%.+]] : $@convention(objc_method) (@opened([[PROP1_EXISTENTIAL]], Test) Self) -> @autoreleased AnyObject): + // CHECK: [[PROP1_TRUE]]([[PROP1_METHOD:%.+]] : $@convention(objc_method) (@opened([[PROP1_EXISTENTIAL]], any Test) Self) -> @autoreleased AnyObject): // CHECK: [[PROP1_OBJ_COPY:%.*]] = copy_value [[PROP1_OBJ]] - // CHECK: [[PROP1_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[PROP1_METHOD]]([[PROP1_OBJ_COPY]]) : $@convention(objc_method) (@opened([[PROP1_EXISTENTIAL]], Test) Self) -> @autoreleased AnyObject + // CHECK: [[PROP1_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[PROP1_METHOD]]([[PROP1_OBJ_COPY]]) : $@convention(objc_method) (@opened([[PROP1_EXISTENTIAL]], any Test) Self) -> @autoreleased AnyObject // CHECK: = apply [[PROP1_PARTIAL]]() : $@callee_guaranteed () -> @owned AnyObject _ = prop1 } if let prop2 = obj.innerPointerProp { - // CHECK: dynamic_method_br [[PROP2_OBJ:%.+]] : $@opened([[PROP2_EXISTENTIAL:.+]], Test) Self, #Test.innerPointerProp!getter.foreign, [[PROP2_TRUE:[^,]+]], [[PROP2_FALSE:[^,]+]] + // CHECK: dynamic_method_br [[PROP2_OBJ:%.+]] : $@opened([[PROP2_EXISTENTIAL:.+]], any Test) Self, #Test.innerPointerProp!getter.foreign, [[PROP2_TRUE:[^,]+]], [[PROP2_FALSE:[^,]+]] // CHECK: [[PROP2_FALSE]]: - // CHECK: [[PROP2_TRUE]]([[PROP2_METHOD:%.+]] : $@convention(objc_method) (@opened([[PROP2_EXISTENTIAL]], Test) Self) -> @unowned_inner_pointer UnsafeMutableRawPointer): + // CHECK: [[PROP2_TRUE]]([[PROP2_METHOD:%.+]] : $@convention(objc_method) (@opened([[PROP2_EXISTENTIAL]], any Test) Self) -> @unowned_inner_pointer UnsafeMutableRawPointer): // CHECK: [[PROP2_OBJ_COPY:%.*]] = copy_value [[PROP2_OBJ]] - // CHECK: [[PROP2_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[PROP2_METHOD]]([[PROP2_OBJ_COPY]]) : $@convention(objc_method) (@opened([[PROP2_EXISTENTIAL]], Test) Self) -> @unowned_inner_pointer UnsafeMutableRawPointer + // CHECK: [[PROP2_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[PROP2_METHOD]]([[PROP2_OBJ_COPY]]) : $@convention(objc_method) (@opened([[PROP2_EXISTENTIAL]], any Test) Self) -> @unowned_inner_pointer UnsafeMutableRawPointer // CHECK: = apply [[PROP2_PARTIAL]]() : $@callee_guaranteed () -> UnsafeMutableRawPointer _ = prop2 } diff --git a/test/Concurrency/async_main.swift b/test/Concurrency/async_main.swift index 1ecfa79f7e114..e51dc3f0578ee 100644 --- a/test/Concurrency/async_main.swift +++ b/test/Concurrency/async_main.swift @@ -32,11 +32,11 @@ func asyncFunc() async { // CHECK-EXEC-NEXT: 43 // static MyProgram.main() -// CHECK-SIL-LABEL: sil hidden @$s10async_main9MyProgramV0B0yyYaKFZ : $@convention(method) @async (@thin MyProgram.Type) -> @error Error +// CHECK-SIL-LABEL: sil hidden @$s10async_main9MyProgramV0B0yyYaKFZ : $@convention(method) @async (@thin MyProgram.Type) -> @error any Error // static MyProgram.$main() -// CHECK-SIL-LABEL: sil hidden @$s10async_main9MyProgramV5$mainyyYaKFZ : $@convention(method) @async (@thin MyProgram.Type) -> @error Error +// CHECK-SIL-LABEL: sil hidden @$s10async_main9MyProgramV5$mainyyYaKFZ : $@convention(method) @async (@thin MyProgram.Type) -> @error any Error // async_Main @@ -44,8 +44,8 @@ func asyncFunc() async { // call main // CHECK-SIL: %0 = metatype $@thin MyProgram.Type // user: %2 // CHECK-SIL-NEXT: // function_ref static MyProgram.$main() -// CHECK-SIL-NEXT: %1 = function_ref @$s10async_main9MyProgramV5$mainyyYaKFZ : $@convention(method) @async (@thin MyProgram.Type) -> @error Error // user: %2 -// CHECK-SIL-NEXT: try_apply %1(%0) : $@convention(method) @async (@thin MyProgram.Type) -> @error Error, normal bb1, error bb2 // id: %2 +// CHECK-SIL-NEXT: %1 = function_ref @$s10async_main9MyProgramV5$mainyyYaKFZ : $@convention(method) @async (@thin MyProgram.Type) -> @error any Error // user: %2 +// CHECK-SIL-NEXT: try_apply %1(%0) : $@convention(method) @async (@thin MyProgram.Type) -> @error any Error, normal bb1, error bb2 // id: %2 // unwrap error and exit or explode // CHECK-SIL: bb1(%3 : $()): @@ -56,8 +56,8 @@ func asyncFunc() async { // CHECK-SIL-NEXT: %7 = apply %6(%5) : $@convention(c) (Int32) -> Never // CHECK-SIL-NEXT: unreachable -// CHECK-SIL: bb2(%9 : $Error): -// CHECK-SIL-NEXT: %10 = builtin "errorInMain"(%9 : $Error) : $() +// CHECK-SIL: bb2(%9 : $any Error): +// CHECK-SIL-NEXT: %10 = builtin "errorInMain"(%9 : $any Error) : $() // CHECK-SIL-NEXT: unreachable // main @@ -68,12 +68,12 @@ func asyncFunc() async { // CHECK-SIL-NEXT: %3 = integer_literal $Builtin.Int64, 2048 // CHECK-SIL-NEXT: %4 = struct $Int (%3 : $Builtin.Int64) // CHECK-SIL-NEXT: %5 = metatype $@thick ().Type -// CHECK-SIL-NEXT: %6 = init_existential_metatype %5 : $@thick ().Type, $@thick Any.Type +// CHECK-SIL-NEXT: %6 = init_existential_metatype %5 : $@thick ().Type, $@thick any Any.Type // CHECK-SIL-NEXT: // function_ref thunk for @escaping @convention(thin) @async () -> () -// CHECK-SIL-NEXT: %7 = function_ref @$sIetH_yts5Error_pIegHrzo_TR : $@convention(thin) @async (@convention(thin) @async () -> ()) -> (@out (), @error Error) -// CHECK-SIL-NEXT: %8 = partial_apply [callee_guaranteed] %7(%2) : $@convention(thin) @async (@convention(thin) @async () -> ()) -> (@out (), @error Error) -// CHECK-SIL-NEXT: %9 = convert_function %8 : $@async @callee_guaranteed () -> (@out (), @error Error) to $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for <()> -// CHECK-SIL-NEXT: %10 = builtin "createAsyncTask"<()>(%4 : $Int, %6 : $@thick Any.Type, %9 : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for <()>) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-SIL-NEXT: %7 = function_ref @$sIetH_yts5Error_pIegHrzo_TR : $@convention(thin) @async (@convention(thin) @async () -> ()) -> (@out (), @error any Error) +// CHECK-SIL-NEXT: %8 = partial_apply [callee_guaranteed] %7(%2) : $@convention(thin) @async (@convention(thin) @async () -> ()) -> (@out (), @error any Error) +// CHECK-SIL-NEXT: %9 = convert_function %8 : $@async @callee_guaranteed () -> (@out (), @error any Error) to $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()> +// CHECK-SIL-NEXT: %10 = builtin "createAsyncTask"<()>(%4 : $Int, %6 : $@thick any Any.Type, %9 : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>) : $(Builtin.NativeObject, Builtin.RawPointer) // CHECK-SIL-NEXT: %11 = tuple_extract %10 : $(Builtin.NativeObject, Builtin.RawPointer), 0 // CHECK-SIL-NEXT: // function_ref swift_job_run // CHECK-SIL-NEXT: %12 = function_ref @swift_job_run : $@convention(thin) (UnownedJob, UnownedSerialExecutor) -> () diff --git a/test/Constraints/ranking.swift b/test/Constraints/ranking.swift index 500b2de76cd4d..2545af88596f8 100644 --- a/test/Constraints/ranking.swift +++ b/test/Constraints/ranking.swift @@ -32,35 +32,35 @@ func genericNoOptional(_: T) {} // CHECK-LABEL: sil hidden [ossa] @$s7ranking22propertyVersusFunctionyyAA1P_p_xtAaCRzlF func propertyVersusFunction(_ p: P, _ t: T) { - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.p!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.p!getter let _ = p.p - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.p!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.p!getter let _: P = p.p - // CHECK: function_ref @$s7ranking22propertyVersusFunctionyyAA1P_p_xtAaCRzlFyAaC_pcAaC_pcfu_ : $@convention(thin) (@in_guaranteed P) -> @owned @callee_guaranteed (@in_guaranteed P) -> () + // CHECK: function_ref @$s7ranking22propertyVersusFunctionyyAA1P_p_xtAaCRzlFyAaC_pcAaC_pcfu_ : $@convention(thin) (@in_guaranteed any P) -> @owned @callee_guaranteed (@in_guaranteed any P) -> () let _: (P) -> () = p.p - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.p!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.p!getter let _: P? = p.p - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.p!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.p!getter let _: Any = p.p - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.p!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.p!getter let _: Any? = p.p - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.p!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.p!getter // CHECK: function_ref @$s7ranking15genericOverloadyyxlF genericOverload(p.p) - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.q!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.q!getter // CHECK: function_ref @$s7ranking15genericOverloadyyxSglF genericOverload(p.q) - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.p!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.p!getter // CHECK: function_ref @$s7ranking15genericOptionalyyxSglF genericOptional(p.p) - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.q!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.q!getter // CHECK: function_ref @$s7ranking15genericOptionalyyxSglF genericOptional(p.q) - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.p!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.p!getter // CHECK: function_ref @$s7ranking17genericNoOptionalyyxlF genericNoOptional(p.p) - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.q!getter + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.q!getter // CHECK: function_ref @$s7ranking17genericNoOptionalyyxlF genericNoOptional(p.q) @@ -68,7 +68,7 @@ func propertyVersusFunction(_ p: P, _ t: T) { let _ = t.p // CHECK: witness_method $T, #P.p!getter let _: P = t.p - // CHECK: function_ref @$s7ranking22propertyVersusFunctionyyAA1P_p_xtAaCRzlFyAaC_pcxcfu1_ : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed (@in_guaranteed P) -> () + // CHECK: function_ref @$s7ranking22propertyVersusFunctionyyAA1P_p_xtAaCRzlFyAaC_pcxcfu1_ : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed (@in_guaranteed any P) -> () let _: (P) -> () = t.p // CHECK: witness_method $T, #P.p!getter let _: P? = t.p @@ -103,7 +103,7 @@ extension P { let _ = self.p // CHECK: witness_method $Self, #P.p!getter let _: P = self.p - // CHECK: function_ref @$s7ranking1PPAAE22propertyVersusFunctionyyFyAaB_pcxcfu_ : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed (@in_guaranteed P) -> () + // CHECK: function_ref @$s7ranking1PPAAE22propertyVersusFunctionyyFyAaB_pcxcfu_ : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed (@in_guaranteed any P) -> () let _: (P) -> () = self.p // CHECK: witness_method $Self, #P.p!getter let _: P? = self.p @@ -311,7 +311,7 @@ struct S2 { // We currently prefer the non-variadic init due to having // "less effective parameters", and we don't compare the types for ranking due // to the difference in variadic-ness. - // CHECK: function_ref @$s7ranking2S2VyAcA1R_pcfC : $@convention(method) (@in R, @thin S2.Type) -> S2 + // CHECK: function_ref @$s7ranking2S2VyAcA1R_pcfC : $@convention(method) (@in any R, @thin S2.Type) -> S2 _ = S2(0) } } diff --git a/test/Distributed/SIL/distributed_actor_default_init_sil_4.swift b/test/Distributed/SIL/distributed_actor_default_init_sil_4.swift index 1e9251d88c545..1bd8d6e874f94 100644 --- a/test/Distributed/SIL/distributed_actor_default_init_sil_4.swift +++ b/test/Distributed/SIL/distributed_actor_default_init_sil_4.swift @@ -29,7 +29,7 @@ distributed actor MyDistActor { } // CHECK-LABEL: // MyDistActor.init(system_async_fail_throws:cond:) - // CHECK: sil hidden @$s14default_deinit11MyDistActorC24system_async_fail_throws4condACSg015FakeDistributedE7Systems0kE6SystemV_SbtYaKcfc : $@convention(method) @async (@owned FakeActorSystem, Bool, @owned MyDistActor) -> (@owned Optional, @error Error) { + // CHECK: sil hidden @$s14default_deinit11MyDistActorC24system_async_fail_throws4condACSg015FakeDistributedE7Systems0kE6SystemV_SbtYaKcfc : $@convention(method) @async (@owned FakeActorSystem, Bool, @owned MyDistActor) -> (@owned Optional, @error any Error) { // CHECK: bb0([[SYSTEM:%[0-9]+]] : $FakeActorSystem, [[COND:%[0-9]+]] : $Bool, [[SELF:%[0-9]+]] : $MyDistActor): // CHECK: cond_br {{%[0-9]+}}, [[SUCCESS_BB:bb[0-9]+]], [[FAIL_BB:bb[0-9]+]] @@ -43,7 +43,7 @@ distributed actor MyDistActor { // CHECK: [[RESIGN_FN:%[0-9]+]] = function_ref @$s27FakeDistributedActorSystems0aC6SystemV8resignIDyyAA0C7AddressVF : $@convention(method) (@guaranteed ActorAddress, @guaranteed FakeActorSystem) -> () // CHECK: = apply [[RESIGN_FN]] // CHECK: builtin "destroyDefaultActor" - // CHECK: throw {{%[0-9]+}} : $Error + // CHECK: throw {{%[0-9]+}} : $any Error // CHECK: [[RET_BB]]: // CHECK: return diff --git a/test/Distributed/SIL/distributed_actor_default_init_sil_6.swift b/test/Distributed/SIL/distributed_actor_default_init_sil_6.swift index c62748c5e3751..f97b6f7a77e2f 100644 --- a/test/Distributed/SIL/distributed_actor_default_init_sil_6.swift +++ b/test/Distributed/SIL/distributed_actor_default_init_sil_6.swift @@ -26,10 +26,10 @@ distributed actor MyDistActor { self.actorSystem = try getSystem() } -// CHECK: sil hidden @$s14default_deinit11MyDistActorCACyKcfc : $@convention(method) (@owned MyDistActor) -> (@owned MyDistActor, @error Error) { +// CHECK: sil hidden @$s14default_deinit11MyDistActorCACyKcfc : $@convention(method) (@owned MyDistActor) -> (@owned MyDistActor, @error any Error) { // CHECK: bb0([[SELF:%[0-9]+]] : $MyDistActor): // CHECK: builtin "initializeDefaultActor"([[SELF]] : $MyDistActor) -// CHECK: try_apply {{%[0-9]+}}() : $@convention(thin) () -> (@owned FakeActorSystem, @error Error), normal [[SUCCESS_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] +// CHECK: try_apply {{%[0-9]+}}() : $@convention(thin) () -> (@owned FakeActorSystem, @error any Error), normal [[SUCCESS_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // CHECK: [[SUCCESS_BB]]([[SYSTEM_VAL:%[0-9]+]] : $FakeActorSystem): // *** save system *** @@ -54,11 +54,11 @@ distributed actor MyDistActor { // CHECK: = apply [[READY_FN]]([[SELF]], [[RELOADED_SYS2]]) // CHECK: return [[SELF]] -// CHECK: [[ERROR_BB]]([[ERRVAL:%[0-9]+]] : $Error): +// CHECK: [[ERROR_BB]]([[ERRVAL:%[0-9]+]] : $any Error): // CHECK-NEXT: = metatype $@thick MyDistActor.Type // CHECK-NEXT: = builtin "destroyDefaultActor"([[SELF]] : $MyDistActor) : $() // CHECK-NEXT: dealloc_partial_ref [[SELF]] -// CHECK: throw [[ERRVAL]] : $Error +// CHECK: throw [[ERRVAL]] : $any Error // CHECK: } // end sil function '$s14default_deinit11MyDistActorCACyKcfc' diff --git a/test/Distributed/SIL/distributed_actor_default_init_sil_7.swift b/test/Distributed/SIL/distributed_actor_default_init_sil_7.swift index 2e0f9a87c41db..fd75bed66acc4 100644 --- a/test/Distributed/SIL/distributed_actor_default_init_sil_7.swift +++ b/test/Distributed/SIL/distributed_actor_default_init_sil_7.swift @@ -34,10 +34,10 @@ distributed actor MyDistActor { someField = try getSomeClass() } -// CHECK: sil hidden @$s14default_deinit11MyDistActorCACyKcfc : $@convention(method) (@owned MyDistActor) -> (@owned MyDistActor, @error Error) { +// CHECK: sil hidden @$s14default_deinit11MyDistActorCACyKcfc : $@convention(method) (@owned MyDistActor) -> (@owned MyDistActor, @error any Error) { // CHECK: bb0([[SELF:%[0-9]+]] : $MyDistActor): // CHECK: builtin "initializeDefaultActor"([[SELF]] : $MyDistActor) -// CHECK: try_apply {{%[0-9]+}}() : $@convention(thin) () -> (@owned FakeActorSystem, @error Error), normal [[SYSTEM_SUCCESS_BB:bb[0-9]+]], error [[SYSTEM_ERROR_BB:bb[0-9]+]] +// CHECK: try_apply {{%[0-9]+}}() : $@convention(thin) () -> (@owned FakeActorSystem, @error any Error), normal [[SYSTEM_SUCCESS_BB:bb[0-9]+]], error [[SYSTEM_ERROR_BB:bb[0-9]+]] // CHECK: [[SYSTEM_SUCCESS_BB]]([[SYSTEM_VAL:%[0-9]+]] : $FakeActorSystem): // *** save system *** @@ -56,7 +56,7 @@ distributed actor MyDistActor { // CHECK: br [[JOIN_PT:bb[0-9]+]] // CHECK: [[JOIN_PT]]: -// CHECK: try_apply {{.*}}() : $@convention(thin) () -> (@owned SomeClass, @error Error), normal [[CLASS_SUCCESS_BB:bb[0-9]+]], error [[CLASS_ERROR_BB:bb[0-9]+]] +// CHECK: try_apply {{.*}}() : $@convention(thin) () -> (@owned SomeClass, @error any Error), normal [[CLASS_SUCCESS_BB:bb[0-9]+]], error [[CLASS_ERROR_BB:bb[0-9]+]] // CHECK: [[CLASS_SUCCESS_BB]]{{.*}}: // CHECK: store {{.*}} to {{.*}} : $*SomeClass diff --git a/test/Frontend/module-alias-emit-sil.swift b/test/Frontend/module-alias-emit-sil.swift index 2c738c57265d1..4b72b2a24b284 100644 --- a/test/Frontend/module-alias-emit-sil.swift +++ b/test/Frontend/module-alias-emit-sil.swift @@ -28,7 +28,7 @@ // CHECK: init() // CHECK: } -// CHECK: public func start() -> Loggable? +// CHECK: public func start() -> (any Loggable)? // CHECK: public func end(_ arg: Logger) @@ -44,18 +44,18 @@ // CHECK: } // end sil function '$s7FileLib02MyB0V12AppleLogging8LoggableAadEP9verbositySivgTW' // CHECK: // start() -// CHECK: sil @$s7FileLib5start12AppleLogging8Loggable_pSgyF : $@convention(thin) () -> @out Optional { +// CHECK: sil @$s7FileLib5start12AppleLogging8Loggable_pSgyF : $@convention(thin) () -> @out Optional { // CHECK: // %0 "$return_value" // user: %2 -// CHECK: bb0(%0 : $*Optional): +// CHECK: bb0(%0 : $*Optional): // CHECK: // function_ref setup() -// CHECK: %1 = function_ref @$s12AppleLogging5setupAA8Loggable_pSgyF : $@convention(thin) () -> @out Optional // user: %2 -// CHECK: %2 = apply %1(%0) : $@convention(thin) () -> @out Optional +// CHECK: %1 = function_ref @$s12AppleLogging5setupAA8Loggable_pSgyF : $@convention(thin) () -> @out Optional // user: %2 +// CHECK: %2 = apply %1(%0) : $@convention(thin) () -> @out Optional // CHECK: %3 = tuple () // user: %4 // CHECK: return %3 : $() // id: %4 // CHECK: } // end sil function '$s7FileLib5start12AppleLogging8Loggable_pSgyF' // CHECK: // setup() -// CHECK: sil @$s12AppleLogging5setupAA8Loggable_pSgyF : $@convention(thin) () -> @out Optional +// CHECK: sil @$s12AppleLogging5setupAA8Loggable_pSgyF : $@convention(thin) () -> @out Optional // CHECK: // end(_:) // CHECK: sil @$s7FileLib3endyy12AppleLogging6LoggerVF : $@convention(thin) (Logger) -> () { diff --git a/test/IRGen/async/async_calls_verifier.sil b/test/IRGen/async/async_calls_verifier.sil index 2dd88a3bfe292..ce23a10f25973 100644 --- a/test/IRGen/async/async_calls_verifier.sil +++ b/test/IRGen/async/async_calls_verifier.sil @@ -65,8 +65,8 @@ bb2(%result_error : $Error): // CHECK: SIL verification failed: cannot call an async function from a non async function: !calleeConv.funcTy->isAsync() || AI->getFunction()->isAsync() // CHECK: Verifying instruction: // CHECK: // function_ref asynccallee2 -// CHECK: %0 = function_ref @asynccallee2 : $@convention(thin) @async () -> ((), @error Error) // user: %1 -// CHECK: -> try_apply %0() : $@convention(thin) @async () -> ((), @error Error), normal bb1, error bb2 // id: %1 +// CHECK: %0 = function_ref @asynccallee2 : $@convention(thin) @async () -> ((), @error any Error) // user: %1 +// CHECK: -> try_apply %0() : $@convention(thin) @async () -> ((), @error any Error), normal bb1, error bb2 // id: %1 // CHECK-LABEL: End Error in function nonasync_try_apply_caller sil [ossa] @nonasync_try_apply_caller : $@convention(thin) () -> () { bb0: diff --git a/test/SIL/OwnershipVerifier/interior_pointer.sil b/test/SIL/OwnershipVerifier/interior_pointer.sil index 6121b4a960bd3..da71052913ab4 100644 --- a/test/SIL/OwnershipVerifier/interior_pointer.sil +++ b/test/SIL/OwnershipVerifier/interior_pointer.sil @@ -137,9 +137,9 @@ bb0(%0 : @owned $Builtin.NativeObject): // CHECK-LABEL: Error#: 0. Begin Error in Function: 'open_existential_box_interior_pointer_error' // CHECK-NEXT: Found outside of lifetime use?! -// CHECK-NEXT: Value: %1 = begin_borrow %0 : $Error // users: %3, %2 -// CHECK-NEXT: Consuming User: end_borrow %1 : $Error // id: %3 -// CHECK-NEXT: Non Consuming User: %6 = apply %5<@opened("01234567-89AB-CDEF-0123-000000000000", Error) Self>(%2) : $@convention(witness_method: Error) <τ_0_0 where τ_0_0 : Error> (@in_guaranteed τ_0_0) -> Int // type-defs: %2; user: %7 +// CHECK-NEXT: Value: %1 = begin_borrow %0 : $any Error // users: %3, %2 +// CHECK-NEXT: Consuming User: end_borrow %1 : $any Error // id: %3 +// CHECK-NEXT: Non Consuming User: %6 = apply %5<@opened("01234567-89AB-CDEF-0123-000000000000", any Error) Self>(%2) : $@convention(witness_method: Error) <τ_0_0 where τ_0_0 : Error> (@in_guaranteed τ_0_0) -> Int // type-defs: %2; user: %7 // CHECK-NEXT: Block: bb0 // CHECK: Error#: 0. End Error in Function: 'open_existential_box_interior_pointer_error' sil [ossa] @open_existential_box_interior_pointer_error : $@convention(thin) (@owned Error) -> Int { diff --git a/test/SIL/Parser/async.sil b/test/SIL/Parser/async.sil index d8f3db691d2fd..71c4285722278 100644 --- a/test/SIL/Parser/async.sil +++ b/test/SIL/Parser/async.sil @@ -71,7 +71,7 @@ bb1(%r : $Builtin.Int32): // CHECK-NEXT: br br bb3 // CHECK-NEXT: {{^ *$}} - // CHECK-NEXT: [[ERROR]]([[EVALUE:%.*]] : $Error): + // CHECK-NEXT: [[ERROR]]([[EVALUE:%.*]] : $any Error): bb2(%e : $Error): // CHECK-NEXT: br br bb3 @@ -125,7 +125,7 @@ bb1: // CHECK-NEXT: br br bb3 // CHECK-NEXT: {{^ *$}} - // CHECK-NEXT: [[ERROR]]([[EVALUE:%.*]] : $Error): + // CHECK-NEXT: [[ERROR]]([[EVALUE:%.*]] : $any Error): bb2(%e : $Error): dealloc_stack %a : $*Builtin.Int32 br bb3 diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil index d3f8dec67f404..9203151bfa7db 100644 --- a/test/SIL/Parser/basic.sil +++ b/test/SIL/Parser/basic.sil @@ -197,7 +197,7 @@ bb0(%0 : $*P): // CHECK: witness_method ${{.*}}, #P.doIt %2 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", P) Self, #P.doIt, %1 : $*@opened("01234567-89ab-cdef-0123-000000000000", P) Self : $@convention(witness_method: P) (@inout T) -> () // Make sure we have the correct scope for generic parameters. - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.doIt + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.doIt %7 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", P) Self, #P.doIt, %1 : $*@opened("01234567-89ab-cdef-0123-000000000000", P) Self : $@convention(witness_method: P) (@inout T) -> () // CHECK: apply %3 = apply %2<@opened("01234567-89ab-cdef-0123-000000000000", P) Self>(%1) : $@convention(witness_method: P) (@inout T) -> () @@ -208,7 +208,7 @@ bb0(%0 : $*P): %6 = witness_method $@opened("01234567-89ab-cdef-0123-000000000001", P) Self, #P.doIt, %5 : $*@opened("01234567-89ab-cdef-0123-000000000001", P) Self : $@convention(witness_method: P) (@in_guaranteed T) -> () %8 = apply %6<@opened("01234567-89ab-cdef-0123-000000000001", P) Self>(%5) : $@convention(witness_method: P) (@in_guaranteed T) -> () - destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*P + destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*any P return %4 : $() // CHECK: return } @@ -287,17 +287,17 @@ bb0(%0 : $*T): protocol Bendable { } -// CHECK: $@convention(thin) (@in Bendable & Runcible) -> @out Runcible +// CHECK: $@convention(thin) (@in any Bendable & Runcible) -> @out any Runcible sil @_T4todo18erasure_from_protoFT1xPS_8RuncibleS_8Bendable__PS0__ : $@convention(thin) (@in Bendable & Runcible) -> @out Runcible { bb0(%0 : $*Runcible, %1 : $*Bendable & Runcible): // CHECK: alloc_box %2 = alloc_box $<τ_0_0> { var τ_0_0 } %2a = project_box %2 : $<τ_0_0> { var τ_0_0 } , 0 - // CHECK: copy_addr [take] {{.*}} to [initialization] {{.*}} : $*Bendable & Runcible + // CHECK: copy_addr [take] {{.*}} to [initialization] {{.*}} : $*any Bendable & Runcible copy_addr [take] %1 to [initialization] %2a : $*Bendable & Runcible // CHECK: alloc_stack %4 = alloc_stack $Bendable & Runcible - // CHECK: copy_addr {{.*}} to [initialization] {{.*}} : $*Bendable & Runcible + // CHECK: copy_addr {{.*}} to [initialization] {{.*}} : $*any Bendable & Runcible copy_addr %2a to [initialization] %4 : $*Bendable & Runcible %7 = tuple () // CHECK: destroy_addr @@ -314,7 +314,7 @@ protocol ClassBound : AnyObject { func classBoundMethod() } -// CHECK: $@convention(thin) (ClassBound) -> () +// CHECK: $@convention(thin) (any ClassBound) -> () sil @_T4todo18class_bound_methodFT1xPS_10ClassBound__T_ : $@convention(thin) (ClassBound) -> () { bb0(%0 : $ClassBound): %1 = alloc_box $<τ_0_0> { var τ_0_0 } // CHECK: alloc_box @@ -322,7 +322,7 @@ bb0(%0 : $ClassBound): store %0 to %1a : $*ClassBound // CHECK: store %3 = load %1a : $*ClassBound // CHECK: load strong_retain %3 : $ClassBound // CHECK: strong_retain - // CHECK: open_existential_ref {{%.*}} : $ClassBound to $@opened({{.*}}, ClassBound) Self + // CHECK: open_existential_ref {{%.*}} : $any ClassBound to $@opened({{.*}}, any ClassBound) Self %5 = open_existential_ref %3 : $ClassBound to $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self // CHECK: witness_method %6 = witness_method $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self, #ClassBound.classBoundMethod, %5 : $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self : $@convention(witness_method: ClassBound) (T) -> () @@ -636,7 +636,7 @@ bb0(%0 : $*SomeProtocol): copy_addr [take] %0 to [initialization] %1a : $*SomeProtocol %4 = alloc_stack $SomeProtocol // CHECK: alloc_stack copy_addr %1a to [initialization] %4 : $*SomeProtocol - // CHECK: existential_metatype $@thick SomeProtocol.Type, {{%.*}} : $*SomeProtocol + // CHECK: existential_metatype $@thick any SomeProtocol.Type, {{%.*}} : $*any SomeProtocol %6 = existential_metatype $@thick SomeProtocol.Type, %4 : $*SomeProtocol destroy_addr %4 : $*SomeProtocol dealloc_stack %4 : $*SomeProtocol @@ -1010,15 +1010,15 @@ class ConcreteClass : ClassP { struct Spoon : Bendable { } -// CHECK-LABEL: sil @test_init_existential : $@convention(thin) (Spoon) -> @out Bendable +// CHECK-LABEL: sil @test_init_existential : $@convention(thin) (Spoon) -> @out any Bendable sil @test_init_existential : $@convention(thin) (Spoon) -> @out Bendable { bb0(%0 : $*Bendable, %1 : $Spoon): %2 = alloc_box $<τ_0_0> { var τ_0_0 } %2a = project_box %2 : $<τ_0_0> { var τ_0_0 } , 0 store %1 to %2a : $*Spoon - // CHECK: init_existential_addr %{{.*}} : $*Bendable, $Spoon + // CHECK: init_existential_addr %{{.*}} : $*any Bendable, $Spoon %4 = init_existential_addr %0 : $*Bendable, $Spoon - // CHECK: deinit_existential_addr %{{.*}} : $*Bendable + // CHECK: deinit_existential_addr %{{.*}} : $*any Bendable deinit_existential_addr %0 : $*Bendable %5 = load %2a : $*Spoon store %5 to %4 : $*Spoon @@ -1027,7 +1027,7 @@ bb0(%0 : $*Bendable, %1 : $Spoon): return %8 : $() } -// CHECK-LABEL: sil @test_existential_ref : $@convention(thin) (ConcreteClass) -> ClassP +// CHECK-LABEL: sil @test_existential_ref : $@convention(thin) (ConcreteClass) -> any ClassP sil @test_existential_ref : $@convention(thin) (ConcreteClass) -> ClassP { bb0(%0 : $ConcreteClass): %1 = alloc_box $<τ_0_0> { var τ_0_0 } @@ -1035,7 +1035,7 @@ bb0(%0 : $ConcreteClass): store %0 to %1a : $*ConcreteClass %3 = load %1a : $*ConcreteClass strong_retain %3 : $ConcreteClass - // CHECK: init_existential_ref %{{.*}} : $ConcreteClass : $ConcreteClass, $ClassP + // CHECK: init_existential_ref %{{.*}} : $ConcreteClass : $ConcreteClass, $any ClassP %5 = init_existential_ref %3 : $ConcreteClass : $ConcreteClass, $ClassP strong_release %1 : $<τ_0_0> { var τ_0_0 } return %5 : $ClassP @@ -1292,7 +1292,7 @@ sil @debug_value : $@convention(thin) (Int, @in P, AnyObject) -> () { bb0(%0 : $Int, %1 : $*P, %2 : $AnyObject): debug_value %0 : $Int // CHECK: debug_value %0 : $Int debug_value [poison] %2 : $AnyObject // CHECK: debug_value [poison] %2 : $AnyObject - debug_value %1 : $*P, expr op_deref // CHECK: debug_value %1 : $*P, expr op_deref + debug_value %1 : $*P, expr op_deref // CHECK: debug_value %1 : $*any P, expr op_deref unreachable } @@ -1380,17 +1380,17 @@ struct SomeError: Error { // CHECK-LABEL: sil @existential_box : $@convention(thin) (SomeError) -> () { sil @existential_box : $@convention(thin) (SomeError) -> () { bb0(%0 : $SomeError): - // CHECK: %1 = alloc_existential_box $Error, $SomeError + // CHECK: %1 = alloc_existential_box $any Error, $SomeError %1 = alloc_existential_box $Error, $SomeError - // CHECK: %2 = project_existential_box $SomeError in %1 : $Error + // CHECK: %2 = project_existential_box $SomeError in %1 : $any Error %2 = project_existential_box $SomeError in %1 : $Error // CHECK: store %0 to %2 : $*SomeError store %0 to %2 : $*SomeError - // CHECK: %4 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self + // CHECK: %4 = open_existential_box %1 : $any Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", any Error) Self %4 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self - // CHECK: destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self + // CHECK: destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", any Error) Self destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self - // CHECK: dealloc_existential_box %1 : $Error, $SomeError + // CHECK: dealloc_existential_box %1 : $any Error, $SomeError dealloc_existential_box %1 : $Error, $SomeError return undef : $() } @@ -1437,25 +1437,25 @@ entry: } -// CHECK-LABEL: sil @error_result : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil @error_result : $@convention(thin) () -> @error any Error sil @error_result : $@convention(thin) () -> @error Error { entry: unreachable } -// CHECK-LABEL: sil @error_result2 : $@convention(thin) () -> (Int, @error Error) +// CHECK-LABEL: sil @error_result2 : $@convention(thin) () -> (Int, @error any Error) sil @error_result2 : $@convention(thin) () -> (Int, @error Error) { entry: unreachable } -// CHECK-LABEL: sil @error_result3 : $@convention(thin) () -> (@owned Class1, @error Error) +// CHECK-LABEL: sil @error_result3 : $@convention(thin) () -> (@owned Class1, @error any Error) sil @error_result3 : $@convention(thin) () -> (@owned Class1, @error Error) { entry: unreachable } -// CHECK-LABEL: sil @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error) +// CHECK-LABEL: sil @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error any Error) sil @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error) { entry(%0 : $Class1): return %0 : $Class1 @@ -1465,7 +1465,7 @@ entry(%0 : $Class1): sil @try_apply : $@convention(thin) (@owned Class1) -> () { entry(%0 : $Class1): %1 = function_ref @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error) - // CHECK: try_apply %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error), normal bb1, error bb2 + // CHECK: try_apply %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error any Error), normal bb1, error bb2 try_apply %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error), normal bb1, error bb2 bb1(%2 : $Class1): @@ -1483,7 +1483,7 @@ bb3: sil @apply_nothrow : $@convention(thin) (@owned Class1) -> () { entry(%0 : $Class1): %1 = function_ref @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error) - // CHECK: apply [nothrow] %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error) + // CHECK: apply [nothrow] %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error any Error) %2 = apply [nothrow] %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error) strong_release %2 : $Class1 %3 = tuple () diff --git a/test/SIL/Parser/basic_objc.sil b/test/SIL/Parser/basic_objc.sil index 427329ef3c8b6..22c27072c6324 100644 --- a/test/SIL/Parser/basic_objc.sil +++ b/test/SIL/Parser/basic_objc.sil @@ -23,7 +23,7 @@ protocol SomeClassProtocol : class {} // CHECK-LABEL: sil [ossa] @metatype_to_object // CHECK: {{%.*}} = objc_metatype_to_object {{%.*}} : $@objc_metatype SomeClass.Type to $AnyObject -// CHECK: {{%.*}} = objc_existential_metatype_to_object {{%.*}} : $@objc_metatype SomeClassProtocol.Type to $AnyObject +// CHECK: {{%.*}} = objc_existential_metatype_to_object {{%.*}} : $@objc_metatype any SomeClassProtocol.Type to $AnyObject sil [ossa] @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject) { entry(%a : $@objc_metatype SomeClass.Type, %b : $@objc_metatype SomeClassProtocol.Type): %x = objc_metatype_to_object %a : $@objc_metatype SomeClass.Type to $AnyObject diff --git a/test/SIL/Parser/opaque_values_parse.sil b/test/SIL/Parser/opaque_values_parse.sil index 15d73df0eac55..153021a0bbb4f 100644 --- a/test/SIL/Parser/opaque_values_parse.sil +++ b/test/SIL/Parser/opaque_values_parse.sil @@ -27,9 +27,9 @@ bb0(%0 : $T): return %t : $() } -// CHECK-LABEL: sil @openExistentialBoxValue : $@convention(thin) (@in Error) -> () { -// CHECK: bb0([[ARG:%.*]] : $Error): -// CHECK: open_existential_box_value [[ARG]] : $Error to $@opened("{{.*}}", Error) Self +// CHECK-LABEL: sil @openExistentialBoxValue : $@convention(thin) (@in any Error) -> () { +// CHECK: bb0([[ARG:%.*]] : $any Error): +// CHECK: open_existential_box_value [[ARG]] : $any Error to $@opened("{{.*}}", any Error) Self // CHECK-LABEL: } // end sil function 'openExistentialBoxValue' sil @openExistentialBoxValue : $@convention(thin) (@in Error) -> () { bb0(%0 : $Error): @@ -38,9 +38,9 @@ bb0(%0 : $Error): return %t : $() } -// CHECK-LABEL: sil @openExistentialValue : $@convention(thin) (@in Foo) -> () { -// CHECK: bb0([[ARG:%.*]] : $Foo): -// CHECK: open_existential_value [[ARG]] : $Foo to $@opened("2E9EACA6-FD59-11E6-B016-685B3593C496", Foo) Self +// CHECK-LABEL: sil @openExistentialValue : $@convention(thin) (@in any Foo) -> () { +// CHECK: bb0([[ARG:%.*]] : $any Foo): +// CHECK: open_existential_value [[ARG]] : $any Foo to $@opened("2E9EACA6-FD59-11E6-B016-685B3593C496", any Foo) Self // CHECK-LABEL: } // end sil function 'openExistentialValue' sil @openExistentialValue : $@convention(thin) (@in Foo) -> () { bb0(%0 : $Foo): diff --git a/test/SIL/Parser/polymorphic_function.sil b/test/SIL/Parser/polymorphic_function.sil index 06752f70e4163..cb09094c83365 100644 --- a/test/SIL/Parser/polymorphic_function.sil +++ b/test/SIL/Parser/polymorphic_function.sil @@ -16,7 +16,7 @@ sil @test : $() -> () { bb0: %281 = alloc_stack $mmStreamable %282 = open_existential_addr mutable_access %281 : $*mmStreamable to $*@opened("01234567-89ab-cdef-0123-000000000000", mmStreamable) Self - // CHECK: witness_method $@opened({{.*}}, mmStreamable) Self, #mmStreamable.writeTo + // CHECK: witness_method $@opened({{.*}}, any mmStreamable) Self, #mmStreamable.writeTo %293 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", mmStreamable) Self, #mmStreamable.writeTo, %282 : $*@opened("01234567-89ab-cdef-0123-000000000000", mmStreamable) Self : $@convention(witness_method: mmStreamable) @callee_owned (@inout T_1_0, @inout T_0_0) -> () dealloc_stack %281 : $*mmStreamable %1 = tuple () diff --git a/test/SIL/Parser/protocol_getter.sil b/test/SIL/Parser/protocol_getter.sil index 4417113949cad..c23f7b7618ed9 100644 --- a/test/SIL/Parser/protocol_getter.sil +++ b/test/SIL/Parser/protocol_getter.sil @@ -12,7 +12,7 @@ protocol TestP : class { sil @test : $@convention(method) (TestP) -> () { bb0(%0 : $TestP): %1 = open_existential_ref %0 : $TestP to $@opened("01234567-89ab-cdef-0123-000000000000", TestP) Self - // CHECK: witness_method $@opened({{.*}}, TestP) Self, #TestP.count!getter : {{.*}}, %{{.*}} : $@opened({{.*}} : $@convention(witness_method: TestP) <τ_0_0 where τ_0_0 : TestP> (τ_0_0) -> Int + // CHECK: witness_method $@opened({{.*}}, any TestP) Self, #TestP.count!getter : {{.*}}, %{{.*}} : $@opened({{.*}} : $@convention(witness_method: TestP) <τ_0_0 where τ_0_0 : TestP> (τ_0_0) -> Int %2 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", TestP) Self, #TestP.count!getter, %1 : $@opened("01234567-89ab-cdef-0123-000000000000", TestP) Self : $@convention(witness_method: TestP) (T) -> Int %3 = tuple () return %3 : $() @@ -24,7 +24,7 @@ sil @top : $@convention(thin) (@owned TestP) -> @owned Optional { bb0(%0 : $TestP): strong_retain %0 : $TestP %3 = open_existential_ref %0 : $TestP to $@opened("01234567-89ab-cdef-0123-111111111111", TestP) Self - // CHECK: witness_method $@opened({{.*}}, TestP) Self, #TestP.test + // CHECK: witness_method $@opened({{.*}}, any TestP) Self, #TestP.test %4 = witness_method $@opened("01234567-89ab-cdef-0123-111111111111", TestP) Self, #TestP.test, %3 : $@opened("01234567-89ab-cdef-0123-111111111111", TestP) Self : $@convention(witness_method: TestP) @callee_owned (@owned T) -> @owned Optional %5 = apply %4<@opened("01234567-89ab-cdef-0123-111111111111", TestP) Self>(%3) : $@convention(witness_method: TestP) @callee_owned (@owned T) -> @owned Optional strong_release %0 : $TestP diff --git a/test/SIL/Parser/undef.sil b/test/SIL/Parser/undef.sil index 981cea862f25a..abda8a3797dc1 100644 --- a/test/SIL/Parser/undef.sil +++ b/test/SIL/Parser/undef.sil @@ -124,7 +124,7 @@ bb0: // CHECK: value_metatype $@thick C.Type, undef : $C value_metatype $@thick C.Type, undef : $C - // CHECK: existential_metatype $@thick P.Type, undef : $P + // CHECK: existential_metatype $@thick any P.Type, undef : $any P existential_metatype $@thick P.Type, undef : $P // Aggregate Types @@ -171,25 +171,25 @@ bb0: // Protocol and Protocol Composition Types - // CHECK: init_existential_addr undef : $*P, $D + // CHECK: init_existential_addr undef : $*any P, $D init_existential_addr undef : $*P, $D - // CHECK: deinit_existential_addr undef : $*P + // CHECK: deinit_existential_addr undef : $*any P deinit_existential_addr undef : $*P - // CHECK: open_existential_addr immutable_access undef : $*P to $*@opened("01234567-89AB-CDEF-0123-000000000000", P) Self + // CHECK: open_existential_addr immutable_access undef : $*any P to $*@opened("01234567-89AB-CDEF-0123-000000000000", any P) Self open_existential_addr immutable_access undef : $*P to $*@opened("01234567-89AB-CDEF-0123-000000000000", P) Self - // CHECK: open_existential_addr mutable_access undef : $*P to $*@opened("01234567-89AB-CDEF-0123-100000000000", P) Self + // CHECK: open_existential_addr mutable_access undef : $*any P to $*@opened("01234567-89AB-CDEF-0123-100000000000", any P) Self open_existential_addr mutable_access undef : $*P to $*@opened("01234567-89AB-CDEF-0123-100000000000", P) Self - // CHECK: init_existential_ref undef : $D : $D, $ClassP + // CHECK: init_existential_ref undef : $D : $D, $any ClassP init_existential_ref undef : $D : $D, $ClassP - // CHECK: open_existential_ref undef : $ClassP to $@opened("01234567-89AB-CDEF-0123-000000000001", ClassP) Self + // CHECK: open_existential_ref undef : $any ClassP to $@opened("01234567-89AB-CDEF-0123-000000000001", any ClassP) Self open_existential_ref undef : $ClassP to $@opened("01234567-89AB-CDEF-0123-000000000001", ClassP) Self - // CHECK: init_existential_metatype undef : $@thick D.Type, $@thick P.Type + // CHECK: init_existential_metatype undef : $@thick D.Type, $@thick any P.Type init_existential_metatype undef : $@thick D.Type, $@thick P.Type - // CHECK: open_existential_metatype undef : $@thick P.Type to $@thick (@opened("01234567-89AB-CDEF-0123-000000000002", P) Self).Type + // CHECK: open_existential_metatype undef : $@thick any P.Type to $@thick (@opened("01234567-89AB-CDEF-0123-000000000002", any P) Self).Type open_existential_metatype undef : $@thick P.Type to $@thick (@opened("01234567-89AB-CDEF-0123-000000000002", P) Self).Type - // CHECK: open_existential_box undef : $Error to $*@opened("01234567-89AB-CDEF-0123-000000000003", Error) Self + // CHECK: open_existential_box undef : $any Error to $*@opened("01234567-89AB-CDEF-0123-000000000003", any Error) Self open_existential_box undef : $Error to $*@opened("01234567-89AB-CDEF-0123-000000000003", Error) Self - // CHECK: dealloc_existential_box undef : $Error, $() + // CHECK: dealloc_existential_box undef : $any Error, $() dealloc_existential_box undef : $Error, $() // Blocks @@ -331,7 +331,7 @@ bb3: sil @dynamic_method_br_test : $() -> () { bb0: - // CHECK: dynamic_method_br undef : $P, #C.fn!foreign, bb1, bb2 + // CHECK: dynamic_method_br undef : $any P, #C.fn!foreign, bb1, bb2 dynamic_method_br undef : $P, #C.fn!foreign, bb1, bb2 bb1(%x : $@convention(objc_method) (P) -> ()): br bb3 @@ -368,7 +368,7 @@ bb3: sil @try_apply_test : $() -> () { bb0: - // CHECK: try_apply undef(undef) : $@convention(thin) (()) -> @error Error, normal bb1, error bb2 + // CHECK: try_apply undef(undef) : $@convention(thin) (()) -> @error any Error, normal bb1, error bb2 try_apply undef(undef) : $@convention(thin) (()) -> @error Error, normal bb1, error bb2 bb1(%1 : $()): br bb3 diff --git a/test/SIL/Parser/undef_objc.sil b/test/SIL/Parser/undef_objc.sil index 967dc842053d6..f02a89edef9f3 100644 --- a/test/SIL/Parser/undef_objc.sil +++ b/test/SIL/Parser/undef_objc.sil @@ -17,7 +17,7 @@ bb0: objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type // CHECK: objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject - // CHECK: objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject + // CHECK: objc_existential_metatype_to_object undef : $@objc_metatype any P.Type to $AnyObject objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject unreachable } diff --git a/test/SIL/Parser/witness_method.sil b/test/SIL/Parser/witness_method.sil index 8705139782fc8..e959ac5961e9e 100644 --- a/test/SIL/Parser/witness_method.sil +++ b/test/SIL/Parser/witness_method.sil @@ -20,7 +20,7 @@ sil hidden @existential : $@convention(thin) (@in AssocReqt) -> () { bb0(%0 : $*AssocReqt): // CHECK: open_existential_addr %2 = open_existential_addr immutable_access %0 : $*AssocReqt to $*@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA", AssocReqt) Self - // CHECK: witness_method $@opened({{.*}}, AssocReqt) Self, #AssocReqt.requiredMethod {{.*}} $@convention(witness_method: AssocReqt) + // CHECK: witness_method $@opened({{.*}}, any AssocReqt) Self, #AssocReqt.requiredMethod {{.*}} $@convention(witness_method: AssocReqt) %3 = witness_method $@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA", AssocReqt) Self, #AssocReqt.requiredMethod : (Self) -> () -> (), %2 : $*@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA", AssocReqt) Self : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> () // CHECK: apply {{.*}} $@convention(witness_method: AssocReqt) %4 = apply %3<@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA", AssocReqt) Self>(%2) : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> () diff --git a/test/SIL/Serialization/async.sil b/test/SIL/Serialization/async.sil index 49d6bc0c11aed..e9070ebc4b69b 100644 --- a/test/SIL/Serialization/async.sil +++ b/test/SIL/Serialization/async.sil @@ -40,7 +40,7 @@ entry: // CHECK-NEXT: await_async_continuation [[CONT]] : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]], error [[ERROR:bb[0-9]+]] await_async_continuation %c : $Builtin.RawUnsafeContinuation, resume bb1, error bb2 // CHECK-NEXT: {{^ *$}} - // CHECK-NEXT: [[ERROR]]([[EVALUE:%.*]] : $Error): + // CHECK-NEXT: [[ERROR]]([[EVALUE:%.*]] : $any Error): bb2(%e : $Error): // CHECK-NEXT: br br bb3 @@ -82,8 +82,8 @@ entry: // CHECK-NEXT: await_async_continuation [[CONT]] : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]], error [[ERROR:bb[0-9]+]] await_async_continuation %c : $Builtin.RawUnsafeContinuation, resume bb1, error bb2 // CHECK-NEXT: {{^ *$}} - // CHECK-NEXT: [[ERROR]]([[EVALUE:%.*]] : $Error): -bb2(%e : $Error): + // CHECK-NEXT: [[ERROR]]([[EVALUE:%.*]] : $any Error): +bb2(%e : $any Error): // CHECK-NEXT: dealloc_stack dealloc_stack %a : $*Builtin.Int32 // CHECK-NEXT: br diff --git a/test/SIL/Serialization/opaque_values_serialize.sil b/test/SIL/Serialization/opaque_values_serialize.sil index fb30339ef30a7..4b7060c97e9ac 100644 --- a/test/SIL/Serialization/opaque_values_serialize.sil +++ b/test/SIL/Serialization/opaque_values_serialize.sil @@ -32,9 +32,9 @@ bb0(%0 : $T): return %t : $() } -// CHECK-LABEL: sil [serialized] @openExistentialBoxValue : $@convention(thin) (@in Error) -> () { -// CHECK: bb0([[ARG:%.*]] : $Error): -// CHECK: open_existential_box_value [[ARG]] : $Error to $@opened({{.*}}, Error) Self +// CHECK-LABEL: sil [serialized] @openExistentialBoxValue : $@convention(thin) (@in any Error) -> () { +// CHECK: bb0([[ARG:%.*]] : $any Error): +// CHECK: open_existential_box_value [[ARG]] : $any Error to $@opened({{.*}}, any Error) Self // CHECK-LABEL: } // end sil function 'openExistentialBoxValue' sil [serialized] @openExistentialBoxValue : $@convention(thin) (@in Error) -> () { bb0(%0 : $Error): @@ -43,9 +43,9 @@ bb0(%0 : $Error): return %t : $() } -// CHECK-LABEL: sil [serialized] @openExistentialValue : $@convention(thin) (@in Foo) -> () { -// CHECK: bb0([[ARG:%.*]] : $Foo): -// CHECK: open_existential_value [[ARG]] : $Foo to $@opened({{.*}}, Foo) Self +// CHECK-LABEL: sil [serialized] @openExistentialValue : $@convention(thin) (@in any Foo) -> () { +// CHECK: bb0([[ARG:%.*]] : $any Foo): +// CHECK: open_existential_value [[ARG]] : $any Foo to $@opened({{.*}}, any Foo) Self // CHECK-LABEL: } // end sil function 'openExistentialValue' sil [serialized] @openExistentialValue : $@convention(thin) (@in Foo) -> () { bb0(%0 : $Foo): diff --git a/test/SILGen/SILDeclRef.swift b/test/SILGen/SILDeclRef.swift index 0b1ed5d7671e4..820a767b67654 100644 --- a/test/SILGen/SILDeclRef.swift +++ b/test/SILGen/SILDeclRef.swift @@ -40,7 +40,7 @@ public class Derived2: Base { // CHECK-LABEL: sil @$s10SILDeclRef5testP1ps5Int32VAA1P_p_tF // Check that witness_method contains SILDeclRefs with a signature. -// CHECK: witness_method $@opened({{.*}}, P) Self, #P.foo : (Self) -> () -> Int32, %{{.*}} : $*@opened({{.*}}, P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32 +// CHECK: witness_method $@opened({{.*}}, any P) Self, #P.foo : (Self) -> () -> Int32, %{{.*}} : $*@opened({{.*}}, any P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32 public func testP(p: P) -> Int32 { return p.foo() } diff --git a/test/SILGen/address_only_types.swift b/test/SILGen/address_only_types.swift index 288f5014859e3..31c973a2fffee 100644 --- a/test/SILGen/address_only_types.swift +++ b/test/SILGen/address_only_types.swift @@ -15,7 +15,7 @@ protocol Unloadable { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B9_argument{{[_0-9a-zA-Z]*}}F func address_only_argument(_ x: Unloadable) { - // CHECK: bb0([[XARG:%[0-9]+]] : $*Unloadable): + // CHECK: bb0([[XARG:%[0-9]+]] : $*any Unloadable): // CHECK: debug_value [[XARG]] {{.*}} expr op_deref // CHECK-NEXT: tuple // CHECK-NEXT: return @@ -23,15 +23,15 @@ func address_only_argument(_ x: Unloadable) { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B17_ignored_argument{{[_0-9a-zA-Z]*}}F func address_only_ignored_argument(_: Unloadable) { - // CHECK: bb0([[XARG:%[0-9]+]] : $*Unloadable): + // CHECK: bb0([[XARG:%[0-9]+]] : $*any Unloadable): // CHECK-NOT: dealloc_stack {{.*}} [[XARG]] // CHECK: return } // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B7_return{{[_0-9a-zA-Z]*}}F func address_only_return(_ x: Unloadable, y: Int) -> Unloadable { - // CHECK: bb0([[RET:%[0-9]+]] : $*Unloadable, [[XARG:%[0-9]+]] : $*Unloadable, [[YARG:%[0-9]+]] : $Builtin.Int64): - // CHECK-NEXT: debug_value [[XARG]] : $*Unloadable, let, name "x", {{.*}} expr op_deref + // CHECK: bb0([[RET:%[0-9]+]] : $*any Unloadable, [[XARG:%[0-9]+]] : $*any Unloadable, [[YARG:%[0-9]+]] : $Builtin.Int64): + // CHECK-NEXT: debug_value [[XARG]] : $*any Unloadable, let, name "x", {{.*}} expr op_deref // CHECK-NEXT: debug_value [[YARG]] : $Builtin.Int64, let, name "y" // CHECK-NEXT: copy_addr [[XARG]] to [initialization] [[RET]] // CHECK-NEXT: [[VOID:%[0-9]+]] = tuple () @@ -46,12 +46,12 @@ func address_only_missing_return() -> Unloadable { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B27_conditional_missing_return{{[_0-9a-zA-Z]*}}F func address_only_conditional_missing_return(_ x: Unloadable) -> Unloadable { - // CHECK: bb0({{%.*}} : $*Unloadable, {{%.*}} : $*Unloadable): + // CHECK: bb0({{%.*}} : $*any Unloadable, {{%.*}} : $*any Unloadable): // CHECK: switch_enum {{%.*}}, case #Bool.true_!enumelt: [[TRUE:bb[0-9]+]], case #Bool.false_!enumelt: [[FALSE:bb[0-9]+]] switch Bool.true_ { case .true_: // CHECK: [[TRUE]]: - // CHECK: copy_addr %1 to [initialization] %0 : $*Unloadable + // CHECK: copy_addr %1 to [initialization] %0 : $*any Unloadable // CHECK: return return x case .false_: @@ -63,7 +63,7 @@ func address_only_conditional_missing_return(_ x: Unloadable) -> Unloadable { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B29_conditional_missing_return_2 func address_only_conditional_missing_return_2(_ x: Unloadable) -> Unloadable { - // CHECK: bb0({{%.*}} : $*Unloadable, {{%.*}} : $*Unloadable): + // CHECK: bb0({{%.*}} : $*any Unloadable, {{%.*}} : $*any Unloadable): // CHECK: switch_enum {{%.*}}, case #Bool.true_!enumelt: [[TRUE1:bb[0-9]+]], case #Bool.false_!enumelt: [[FALSE1:bb[0-9]+]] switch Bool.true_ { case .true_: @@ -92,7 +92,7 @@ func some_address_only_function_2(_ x: Unloadable) -> () {} // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B7_call_1 func address_only_call_1() -> Unloadable { - // CHECK: bb0([[RET:%[0-9]+]] : $*Unloadable): + // CHECK: bb0([[RET:%[0-9]+]] : $*any Unloadable): return some_address_only_function_1() // FIXME emit into // CHECK: [[FUNC:%[0-9]+]] = function_ref @$s18address_only_types05some_a1_B11_function_1AA10Unloadable_pyF @@ -104,7 +104,7 @@ func address_only_call_1() -> Unloadable { func address_only_call_1_ignore_return() { // CHECK: bb0: some_address_only_function_1() - // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable + // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $any Unloadable // CHECK: [[FUNC:%[0-9]+]] = function_ref @$s18address_only_types05some_a1_B11_function_1AA10Unloadable_pyF // CHECK: apply [[FUNC]]([[TEMP]]) // CHECK: destroy_addr [[TEMP]] @@ -114,8 +114,8 @@ func address_only_call_1_ignore_return() { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B7_call_2{{[_0-9a-zA-Z]*}}F func address_only_call_2(_ x: Unloadable) { - // CHECK: bb0([[XARG:%[0-9]+]] : $*Unloadable): - // CHECK: debug_value [[XARG]] : $*Unloadable, {{.*}} expr op_deref + // CHECK: bb0([[XARG:%[0-9]+]] : $*any Unloadable): + // CHECK: debug_value [[XARG]] : $*any Unloadable, {{.*}} expr op_deref some_address_only_function_2(x) // CHECK: [[FUNC:%[0-9]+]] = function_ref @$s18address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F // CHECK: apply [[FUNC]]([[XARG]]) @@ -126,7 +126,7 @@ func address_only_call_2(_ x: Unloadable) { func address_only_call_1_in_2() { // CHECK: bb0: some_address_only_function_2(some_address_only_function_1()) - // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable + // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $any Unloadable // CHECK: [[FUNC1:%[0-9]+]] = function_ref @$s18address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F // CHECK: apply [[FUNC1]]([[TEMP]]) // CHECK: [[FUNC2:%[0-9]+]] = function_ref @$s18address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F @@ -139,10 +139,10 @@ func address_only_call_1_in_2() { func address_only_materialize() -> Int { // CHECK: bb0: return some_address_only_function_1().foo() - // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable + // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $any Unloadable // CHECK: [[FUNC:%[0-9]+]] = function_ref @$s18address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F // CHECK: apply [[FUNC]]([[TEMP]]) - // CHECK: [[TEMP_PROJ:%[0-9]+]] = open_existential_addr immutable_access [[TEMP]] : $*Unloadable to $*[[OPENED:@opened\(.*, Unloadable\) Self]] + // CHECK: [[TEMP_PROJ:%[0-9]+]] = open_existential_addr immutable_access [[TEMP]] : $*any Unloadable to $*[[OPENED:@opened\(.*, any Unloadable\) Self]] // CHECK: [[FOO_METHOD:%[0-9]+]] = witness_method $[[OPENED]], #Unloadable.foo : // CHECK: [[RET:%[0-9]+]] = apply [[FOO_METHOD]]<[[OPENED]]>([[TEMP_PROJ]]) // CHECK: destroy_addr [[TEMP]] @@ -152,9 +152,9 @@ func address_only_materialize() -> Int { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B21_assignment_from_temp{{[_0-9a-zA-Z]*}}F func address_only_assignment_from_temp(_ dest: inout Unloadable) { - // CHECK: bb0([[DEST:%[0-9]+]] : $*Unloadable): + // CHECK: bb0([[DEST:%[0-9]+]] : $*any Unloadable): dest = some_address_only_function_1() - // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable + // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $any Unloadable // CHECK: %[[ACCESS:.*]] = begin_access [modify] [unknown] %0 : // CHECK: copy_addr [take] [[TEMP]] to %[[ACCESS]] : // CHECK-NOT: destroy_addr [[TEMP]] @@ -164,14 +164,14 @@ func address_only_assignment_from_temp(_ dest: inout Unloadable) { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B19_assignment_from_lv{{[_0-9a-zA-Z]*}}F func address_only_assignment_from_lv(_ dest: inout Unloadable, v: Unloadable) { var v = v - // CHECK: bb0([[DEST:%[0-9]+]] : $*Unloadable, [[VARG:%[0-9]+]] : $*Unloadable): - // CHECK: [[VBOX:%.*]] = alloc_box ${ var Unloadable } + // CHECK: bb0([[DEST:%[0-9]+]] : $*any Unloadable, [[VARG:%[0-9]+]] : $*any Unloadable): + // CHECK: [[VBOX:%.*]] = alloc_box ${ var any Unloadable } // CHECK: [[V_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[VBOX]] // CHECK: [[PBOX:%[0-9]+]] = project_box [[V_LIFETIME]] - // CHECK: copy_addr [[VARG]] to [initialization] [[PBOX]] : $*Unloadable + // CHECK: copy_addr [[VARG]] to [initialization] [[PBOX]] : $*any Unloadable dest = v // CHECK: [[READBOX:%.*]] = begin_access [read] [unknown] [[PBOX]] : - // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable + // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $any Unloadable // CHECK: copy_addr [[READBOX]] to [initialization] [[TEMP]] : // CHECK: [[RET:%.*]] = begin_access [modify] [unknown] %0 : // CHECK: copy_addr [take] [[TEMP]] to [[RET]] : @@ -189,7 +189,7 @@ var global_prop : Unloadable { func address_only_assignment_from_temp_to_property() { // CHECK: bb0: global_prop = some_address_only_function_1() - // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable + // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $any Unloadable // CHECK: [[SETTER:%[0-9]+]] = function_ref @$s18address_only_types11global_propAA10Unloadable_pvs // CHECK: apply [[SETTER]]([[TEMP]]) // CHECK: dealloc_stack [[TEMP]] @@ -197,9 +197,9 @@ func address_only_assignment_from_temp_to_property() { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B31_assignment_from_lv_to_property{{[_0-9a-zA-Z]*}}F func address_only_assignment_from_lv_to_property(_ v: Unloadable) { - // CHECK: bb0([[VARG:%[0-9]+]] : $*Unloadable): - // CHECK: debug_value [[VARG]] : $*Unloadable, {{.*}} expr op_deref - // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable + // CHECK: bb0([[VARG:%[0-9]+]] : $*any Unloadable): + // CHECK: debug_value [[VARG]] : $*any Unloadable, {{.*}} expr op_deref + // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $any Unloadable // CHECK: copy_addr [[VARG]] to [initialization] [[TEMP]] // CHECK: [[SETTER:%[0-9]+]] = function_ref @$s18address_only_types11global_propAA10Unloadable_pvs // CHECK: apply [[SETTER]]([[TEMP]]) @@ -209,9 +209,9 @@ func address_only_assignment_from_lv_to_property(_ v: Unloadable) { // CHECK-LABEL: sil hidden [ossa] @$s18address_only_types0a1_B4_varAA10Unloadable_pyF func address_only_var() -> Unloadable { - // CHECK: bb0([[RET:%[0-9]+]] : $*Unloadable): + // CHECK: bb0([[RET:%[0-9]+]] : $*any Unloadable): var x = some_address_only_function_1() - // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Unloadable } + // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var any Unloadable } // CHECK: [[XBOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[XBOX]] // CHECK: [[XPB:%.*]] = project_box [[XBOX_LIFETIME]] // CHECK: apply {{%.*}}([[XPB]]) diff --git a/test/SILGen/assignment.swift b/test/SILGen/assignment.swift index b61e23cbe4708..c2e4288bad863 100644 --- a/test/SILGen/assignment.swift +++ b/test/SILGen/assignment.swift @@ -38,15 +38,15 @@ protocol P { // Verify that the access to the LHS does not begin until after the // RHS is formally evaluated. -// CHECK-LABEL: sil hidden [ossa] @$s10assignment15copyRightToLeft1pyAA1P_pz_tF : $@convention(thin) (@inout P) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s10assignment15copyRightToLeft1pyAA1P_pz_tF : $@convention(thin) (@inout any P) -> () { func copyRightToLeft(p: inout P) { - // CHECK: bb0(%0 : $*P): - // CHECK: [[READ:%.*]] = begin_access [read] [unknown] %0 : $*P + // CHECK: bb0(%0 : $*any P): + // CHECK: [[READ:%.*]] = begin_access [read] [unknown] %0 : $*any P // CHECK: [[READ_OPEN:%.*]] = open_existential_addr immutable_access [[READ]] - // CHECK: end_access [[READ]] : $*P - // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*P + // CHECK: end_access [[READ]] : $*any P + // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*any P // CHECK: [[WRITE_OPEN:%.*]] = open_existential_addr mutable_access [[WRITE]] - // CHECK: end_access [[WRITE]] : $*P + // CHECK: end_access [[WRITE]] : $*any P p.left = p.right } diff --git a/test/SILGen/async_builtins.swift b/test/SILGen/async_builtins.swift index 2d151074e0aab..410e3a600727b 100644 --- a/test/SILGen/async_builtins.swift +++ b/test/SILGen/async_builtins.swift @@ -18,7 +18,7 @@ public struct X { // CHECK-LABEL: sil hidden [ossa] @$s4test1XV12launchFutureyyxlF : $@convention(method) (@in_guaranteed T, X) -> () func launchFuture(_ value: T) { - // CHECK: builtin "createAsyncTask"([[ZERO:%.*]] : $Int, [[FN:%.*]] : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + // CHECK: builtin "createAsyncTask"([[ZERO:%.*]] : $Int, [[FN:%.*]] : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) _ = Builtin.createAsyncTask(0) { () async throws -> T in return value } @@ -26,7 +26,7 @@ public struct X { // CHECK-LABEL: sil hidden [ossa] @$s4test1XV16launchGroupChild_5groupyx_BptlF : $@convention(method) (@in_guaranteed T, Builtin.RawPointer, X) -> () { func launchGroupChild(_ value: T, group: Builtin.RawPointer) { - // CHECK: builtin "createAsyncTaskInGroup"([[ZERO:%.*]] : $Int, [[GROUP:%.*]] : $Builtin.RawPointer, [[FN:%.*]] : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + // CHECK: builtin "createAsyncTaskInGroup"([[ZERO:%.*]] : $Int, [[GROUP:%.*]] : $Builtin.RawPointer, [[FN:%.*]] : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) _ = Builtin.createAsyncTaskInGroup(0, group) { () async throws -> T in return value } @@ -86,7 +86,7 @@ public func usesWithUnsafeContinuation() async { // CHECK: dealloc_stack [[BOX]] } -// CHECK-LABEL: sil [ossa] @$s4test34usesWithUnsafeThrowingContinuationyyYaKF : $@convention(thin) @async () -> @error Error { +// CHECK-LABEL: sil [ossa] @$s4test34usesWithUnsafeThrowingContinuationyyYaKF : $@convention(thin) @async () -> @error any Error { public func usesWithUnsafeThrowingContinuation() async throws { let _: Int = try await Builtin.withUnsafeThrowingContinuation { c in } @@ -101,8 +101,8 @@ public func usesWithUnsafeThrowingContinuation() async throws { // CHECK: [[RESULT:%.*]] = load [trivial] [[BOX]] : $*Int // CHECK: dealloc_stack [[BOX]] - // CHECK: bb2([[ERROR:%.*]] : @owned $Error): - // CHECK: builtin "willThrow"([[ERROR]] : $Error) : $() + // CHECK: bb2([[ERROR:%.*]] : @owned $any Error): + // CHECK: builtin "willThrow"([[ERROR]] : $any Error) : $() // CHECK: dealloc_stack [[BOX]] // CHECK: throw [[ERROR]] } @@ -142,12 +142,12 @@ public func resumeThrowingContinuation(_ cont: Builtin.RawUnsafeContinuation, // CHECK-LABEL: sil [ossa] @$s4test026resumeThrowingContinuationC0yyBc_s5Error_pntF public func resumeThrowingContinuationThrowing(_ cont: Builtin.RawUnsafeContinuation, _ error: __owned Error) { - // CHECK: bb0(%0 : $Builtin.RawUnsafeContinuation, %1 : @owned $Error): - // CHECK: [[BORROW:%.*]] = begin_borrow [lexical] %1 : $Error + // CHECK: bb0(%0 : $Builtin.RawUnsafeContinuation, %1 : @owned $any Error): + // CHECK: [[BORROW:%.*]] = begin_borrow [lexical] %1 : $any Error // CHECK-NEXT: debug_value - // CHECK-NEXT: [[COPY:%.*]] = copy_value [[BORROW]] : $Error - // CHECK-NEXT: builtin "resumeThrowingContinuationThrowing"(%0 : $Builtin.RawUnsafeContinuation, [[COPY]] : $Error) - // CHECK-NEXT: end_borrow [[BORROW]] : $Error - // CHECK-NEXT: destroy_value %1 : $Error + // CHECK-NEXT: [[COPY:%.*]] = copy_value [[BORROW]] : $any Error + // CHECK-NEXT: builtin "resumeThrowingContinuationThrowing"(%0 : $Builtin.RawUnsafeContinuation, [[COPY]] : $any Error) + // CHECK-NEXT: end_borrow [[BORROW]] : $any Error + // CHECK-NEXT: destroy_value %1 : $any Error Builtin.resumeThrowingContinuationThrowing(cont, error) } diff --git a/test/SILGen/async_let.swift b/test/SILGen/async_let.swift index 62bb2fc575248..0f588d331273d 100644 --- a/test/SILGen/async_let.swift +++ b/test/SILGen/async_let.swift @@ -41,7 +41,7 @@ func testAsyncLetWithThrows(cond: Bool) async throws -> String { return await s } -// CHECK-LABEL: sil hidden [ossa] @$s4test0A14AsyncLetThrowsSSyYaKF : $@convention(thin) @async () -> (@owned String, @error Error) { +// CHECK-LABEL: sil hidden [ossa] @$s4test0A14AsyncLetThrowsSSyYaKF : $@convention(thin) @async () -> (@owned String, @error any Error) { func testAsyncLetThrows() async throws -> String { async let s = try await getStringThrowingly() diff --git a/test/SILGen/back_deploy_attribute_throwing_func.swift b/test/SILGen/back_deploy_attribute_throwing_func.swift index be5baded56f7f..de50439572b00 100644 --- a/test/SILGen/back_deploy_attribute_throwing_func.swift +++ b/test/SILGen/back_deploy_attribute_throwing_func.swift @@ -6,13 +6,13 @@ // REQUIRES: OS=macosx // -- Fallback definition of throwingFunc() -// CHECK-LABEL: sil non_abi [serialized] [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKFTwB : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil non_abi [serialized] [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKFTwB : $@convention(thin) () -> @error any Error // CHECK: bb0: // CHECK: [[RESULT:%.*]] = tuple () // CHECK: return [[RESULT]] : $() // -- Back deployment thunk for throwingFunc() -// CHECK-LABEL: sil non_abi [serialized] [thunk] [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKFTwb : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil non_abi [serialized] [thunk] [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKFTwb : $@convention(thin) () -> @error any Error // CHECK: bb0: // CHECK: [[MAJOR:%.*]] = integer_literal $Builtin.Word, 10 // CHECK: [[MINOR:%.*]] = integer_literal $Builtin.Word, 52 @@ -22,21 +22,21 @@ // CHECK: cond_br [[AVAIL]], [[AVAIL_BB:bb[0-9]+]], [[UNAVAIL_BB:bb[0-9]+]] // // CHECK: [[UNAVAIL_BB]]: -// CHECK: [[FALLBACKFN:%.*]] = function_ref @$s11back_deploy12throwingFuncyyKFTwB : $@convention(thin) () -> @error Error -// CHECK: try_apply [[FALLBACKFN]]() : $@convention(thin) () -> @error Error, normal [[UNAVAIL_NORMAL_BB:bb[0-9]+]], error [[UNAVAIL_ERROR_BB:bb[0-9]+]] +// CHECK: [[FALLBACKFN:%.*]] = function_ref @$s11back_deploy12throwingFuncyyKFTwB : $@convention(thin) () -> @error any Error +// CHECK: try_apply [[FALLBACKFN]]() : $@convention(thin) () -> @error any Error, normal [[UNAVAIL_NORMAL_BB:bb[0-9]+]], error [[UNAVAIL_ERROR_BB:bb[0-9]+]] // -// CHECK: [[UNAVAIL_ERROR_BB]]([[ARG:%.*]] : @owned $Error): -// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ARG]] : $Error) +// CHECK: [[UNAVAIL_ERROR_BB]]([[ARG:%.*]] : @owned $any Error): +// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ARG]] : $any Error) // // CHECK: [[UNAVAIL_NORMAL_BB]]([[ARG:%.*]] : $()): // CHECK: br [[RETURN_BB:bb[0-9]+]] // // CHECK: [[AVAIL_BB]]: -// CHECK: [[ORIGFN:%.*]] = function_ref @$s11back_deploy12throwingFuncyyKF : $@convention(thin) () -> @error Error -// CHECK: try_apply [[ORIGFN]]() : $@convention(thin) () -> @error Error, normal [[AVAIL_NORMAL_BB:bb[0-9]+]], error [[AVAIL_ERROR_BB:bb[0-9]+]] +// CHECK: [[ORIGFN:%.*]] = function_ref @$s11back_deploy12throwingFuncyyKF : $@convention(thin) () -> @error any Error +// CHECK: try_apply [[ORIGFN]]() : $@convention(thin) () -> @error any Error, normal [[AVAIL_NORMAL_BB:bb[0-9]+]], error [[AVAIL_ERROR_BB:bb[0-9]+]] // -// CHECK: [[AVAIL_ERROR_BB]]([[ARG:%.*]] : @owned $Error): -// CHECK: br [[RETHROW_BB]]([[ARG]] : $Error) +// CHECK: [[AVAIL_ERROR_BB]]([[ARG:%.*]] : @owned $any Error): +// CHECK: br [[RETHROW_BB]]([[ARG]] : $any Error) // // CHECK: [[AVAIL_NORMAL_BB]]([[ARG:%.*]] : $()): // CHECK: br [[RETURN_BB]] @@ -45,19 +45,19 @@ // CHECK: [[RESULT:%.*]] = tuple () // CHECK: return [[RESULT]] : $() // -// CHECK: [[RETHROW_BB]]([[RETHROW_BB_ARG:%.*]] : @owned $Error) -// CHECK: throw [[RETHROW_BB_ARG]] : $Error +// CHECK: [[RETHROW_BB]]([[RETHROW_BB_ARG:%.*]] : @owned $any Error) +// CHECK: throw [[RETHROW_BB_ARG]] : $any Error // -- Original definition of throwingFunc() -// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKF : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKF : $@convention(thin) () -> @error any Error @available(macOS 10.51, *) @_backDeploy(before: macOS 10.52) public func throwingFunc() throws {} -// CHECK-LABEL: sil hidden [available 10.51] [ossa] @$s11back_deploy6calleryyKF : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil hidden [available 10.51] [ossa] @$s11back_deploy6calleryyKF : $@convention(thin) () -> @error any Error @available(macOS 10.51, *) func caller() throws { // -- Verify the thunk is called - // CHECK: {{%.*}} = function_ref @$s11back_deploy12throwingFuncyyKFTwb : $@convention(thin) () -> @error Error + // CHECK: {{%.*}} = function_ref @$s11back_deploy12throwingFuncyyKFTwb : $@convention(thin) () -> @error any Error try throwingFunc() } diff --git a/test/SILGen/boxed_existentials.swift b/test/SILGen/boxed_existentials.swift index 8de27ed962541..a8f2543cf6c25 100644 --- a/test/SILGen/boxed_existentials.swift +++ b/test/SILGen/boxed_existentials.swift @@ -2,8 +2,8 @@ // RUN: %target-swift-emit-silgen -module-name boxed_existentials -Xllvm -sil-full-demangle %s | %FileCheck %s --check-prefix=GUARANTEED func test_type_lowering(_ x: Error) { } -// CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials18test_type_loweringyys5Error_pF : $@convention(thin) (@guaranteed Error) -> () { -// CHECK-NOT: destroy_value %0 : $Error +// CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials18test_type_loweringyys5Error_pF : $@convention(thin) (@guaranteed any Error) -> () { +// CHECK-NOT: destroy_value %0 : $any Error class Document {} @@ -20,13 +20,13 @@ func test_concrete_erasure(_ x: ClericalError) -> Error { // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials21test_concrete_erasureys5Error_pAA08ClericalF0OF // CHECK: bb0([[ARG:%.*]] : @guaranteed $ClericalError): // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] -// CHECK: [[EXISTENTIAL:%.*]] = alloc_existential_box $Error, $ClericalError -// CHECK: [[ADDR:%.*]] = project_existential_box $ClericalError in [[EXISTENTIAL]] : $Error +// CHECK: [[EXISTENTIAL:%.*]] = alloc_existential_box $any Error, $ClericalError +// CHECK: [[ADDR:%.*]] = project_existential_box $ClericalError in [[EXISTENTIAL]] : $any Error // CHECK: store [[EXISTENTIAL]] to [init] [[EXISTENTIAL_BUF:%.*]] : // CHECK: store [[ARG_COPY]] to [init] [[ADDR]] : $*ClericalError // CHECK-NOT: destroy_value [[ARG]] // CHECK: [[EXISTENTIAL2:%.*]] = load [take] [[EXISTENTIAL_BUF]] -// CHECK: return [[EXISTENTIAL2]] : $Error +// CHECK: return [[EXISTENTIAL2]] : $any Error protocol HairType {} @@ -34,9 +34,9 @@ func test_composition_erasure(_ x: HairType & Error) -> Error { return x } // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials24test_composition_erasureys5Error_psAC_AA8HairTypepF -// CHECK: [[VALUE_ADDR:%.*]] = open_existential_addr immutable_access [[OLD_EXISTENTIAL:%.*]] : $*Error & HairType to $*[[VALUE_TYPE:@opened\(.*, Error & HairType\) Self]] -// CHECK: [[NEW_EXISTENTIAL:%.*]] = alloc_existential_box $Error, $[[VALUE_TYPE]] -// CHECK: [[ADDR:%.*]] = project_existential_box $[[VALUE_TYPE]] in [[NEW_EXISTENTIAL]] : $Error +// CHECK: [[VALUE_ADDR:%.*]] = open_existential_addr immutable_access [[OLD_EXISTENTIAL:%.*]] : $*any Error & HairType to $*[[VALUE_TYPE:@opened\(.*, any Error & HairType\) Self]] +// CHECK: [[NEW_EXISTENTIAL:%.*]] = alloc_existential_box $any Error, $[[VALUE_TYPE]] +// CHECK: [[ADDR:%.*]] = project_existential_box $[[VALUE_TYPE]] in [[NEW_EXISTENTIAL]] : $any Error // CHECK: store [[NEW_EXISTENTIAL]] to [init] [[NEW_EXISTENTIALBUF:%.*]] : // CHECK: copy_addr [[VALUE_ADDR]] to [initialization] [[ADDR]] // CHECK-NOT: destroy_addr [[OLD_EXISTENTIAL]] @@ -49,9 +49,9 @@ func test_class_composition_erasure(_ x: HairClass & Error) -> Error { return x } // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials30test_class_composition_erasureys5Error_psAC_AA9HairClasspF -// CHECK: [[VALUE:%.*]] = open_existential_ref [[OLD_EXISTENTIAL:%.*]] : $Error & HairClass to $[[VALUE_TYPE:@opened\(.*, Error & HairClass\) Self]] -// CHECK: [[NEW_EXISTENTIAL:%.*]] = alloc_existential_box $Error, $[[VALUE_TYPE]] -// CHECK: [[ADDR:%.*]] = project_existential_box $[[VALUE_TYPE]] in [[NEW_EXISTENTIAL]] : $Error +// CHECK: [[VALUE:%.*]] = open_existential_ref [[OLD_EXISTENTIAL:%.*]] : $any Error & HairClass to $[[VALUE_TYPE:@opened\(.*, any Error & HairClass\) Self]] +// CHECK: [[NEW_EXISTENTIAL:%.*]] = alloc_existential_box $any Error, $[[VALUE_TYPE]] +// CHECK: [[ADDR:%.*]] = project_existential_box $[[VALUE_TYPE]] in [[NEW_EXISTENTIAL]] : $any Error // CHECK: store [[NEW_EXISTENTIAL]] to [init] [[NEW_EXISTENTIALBUF:%.*]] : // CHECK: [[COPIED_VALUE:%.*]] = copy_value [[VALUE]] // CHECK: store [[COPIED_VALUE]] to [init] [[ADDR]] @@ -62,8 +62,8 @@ func test_property(_ x: Error) -> String { return x._domain } // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials13test_propertyySSs5Error_pF -// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error): -// CHECK: [[VALUE:%.*]] = open_existential_box [[ARG]] : $Error to $*[[VALUE_TYPE:@opened\(.*, Error\) Self]] +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Error): +// CHECK: [[VALUE:%.*]] = open_existential_box [[ARG]] : $any Error to $*[[VALUE_TYPE:@opened\(.*, any Error\) Self]] // FIXME: Extraneous copy here // CHECK-NEXT: [[COPY:%[0-9]+]] = alloc_stack $[[VALUE_TYPE]] // CHECK-NEXT: copy_addr [[VALUE]] to [initialization] [[COPY]] : $*[[VALUE_TYPE]] @@ -80,16 +80,16 @@ func test_property_of_lvalue(_ x: Error) -> String { } // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials23test_property_of_lvalueySSs5Error_pF : -// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error): -// CHECK: [[VAR:%.*]] = alloc_box ${ var Error } +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Error): +// CHECK: [[VAR:%.*]] = alloc_box ${ var any Error } // CHECK: [[VAR_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[VAR]] // CHECK: [[PVAR:%.*]] = project_box [[VAR_LIFETIME]] -// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] : $Error +// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] : $any Error // CHECK: store [[ARG_COPY]] to [init] [[PVAR]] -// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PVAR]] : $*Error +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PVAR]] : $*any Error // CHECK: [[VALUE_BOX:%.*]] = load [copy] [[ACCESS]] // CHECK: [[BORROWED_VALUE_BOX:%.*]] = begin_borrow [[VALUE_BOX]] -// CHECK: [[VALUE:%.*]] = open_existential_box [[BORROWED_VALUE_BOX]] : $Error to $*[[VALUE_TYPE:@opened\(.*, Error\) Self]] +// CHECK: [[VALUE:%.*]] = open_existential_box [[BORROWED_VALUE_BOX]] : $any Error to $*[[VALUE_TYPE:@opened\(.*, any Error\) Self]] // CHECK: [[COPY:%.*]] = alloc_stack $[[VALUE_TYPE]] // CHECK: copy_addr [[VALUE]] to [initialization] [[COPY]] // CHECK: destroy_value [[VALUE_BOX]] @@ -110,7 +110,7 @@ extension Error { // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials21test_extension_methodyys5Error_pF func test_extension_method(_ error: Error) { - // CHECK: bb0([[ARG:%.*]] : @guaranteed $Error): + // CHECK: bb0([[ARG:%.*]] : @guaranteed $any Error): // CHECK: [[VALUE:%.*]] = open_existential_box [[ARG]] // CHECK: [[METHOD:%.*]] = function_ref // CHECK-NOT: copy_addr @@ -127,15 +127,15 @@ func plusOneError() -> Error { } // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials31test_open_existential_semanticsyys5Error_p_sAC_ptF // GUARANTEED-LABEL: sil hidden [ossa] @$s18boxed_existentials31test_open_existential_semanticsyys5Error_p_sAC_ptF -// CHECK: bb0([[ARG0:%.*]]: @guaranteed $Error, -// GUARANTEED: bb0([[ARG0:%.*]]: @guaranteed $Error, +// CHECK: bb0([[ARG0:%.*]]: @guaranteed $any Error, +// GUARANTEED: bb0([[ARG0:%.*]]: @guaranteed $any Error, func test_open_existential_semantics(_ guaranteed: Error, _ immediate: Error) { var immediate = immediate - // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error } + // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var any Error } // CHECK: [[IMMEDIATE_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[IMMEDIATE_BOX]] // CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_LIFETIME]] - // GUARANTEED: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error } + // GUARANTEED: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var any Error } // GUARANTEED: [[IMMEDIATE_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[IMMEDIATE_BOX]] // GUARANTEED: [[PB:%.*]] = project_box [[IMMEDIATE_LIFETIME]] @@ -154,7 +154,7 @@ func test_open_existential_semantics(_ guaranteed: Error, // GUARANTEED-NOT: destroy_value [[ARG0]] guaranteed.extensionMethod() - // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]] : $*Error + // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]] : $*any Error // CHECK: [[IMMEDIATE:%.*]] = load [copy] [[ACCESS]] // -- need a copy_value to guarantee // CHECK: [[IMMEDIATE_BORROW:%.*]] = begin_borrow [[IMMEDIATE]] @@ -167,7 +167,7 @@ func test_open_existential_semantics(_ guaranteed: Error, // out. // CHECK: destroy_value [[IMMEDIATE]] - // GUARANTEED: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]] : $*Error + // GUARANTEED: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]] : $*any Error // GUARANTEED: [[IMMEDIATE:%.*]] = load [copy] [[ACCESS]] // -- need a copy_value to guarantee // GUARANTEED: [[BORROWED_IMMEDIATE:%.*]] = begin_borrow [[IMMEDIATE]] @@ -200,10 +200,10 @@ func test_open_existential_semantics(_ guaranteed: Error, } // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials14erasure_to_anyyyps5Error_p_sAC_ptF -// CHECK: bb0([[OUT:%.*]] : $*Any, [[GUAR:%.*]] : @guaranteed $Error, +// CHECK: bb0([[OUT:%.*]] : $*Any, [[GUAR:%.*]] : @guaranteed $any Error, func erasure_to_any(_ guaranteed: Error, _ immediate: Error) -> Any { var immediate = immediate - // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error } + // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var any Error } // CHECK: [[IMMEDIATE_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[IMMEDIATE_BOX]] // CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_LIFETIME]] if true { @@ -243,10 +243,10 @@ extension Error { // Make sure we don't assert on this. // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials4testyyF -// CHECK: [[ERROR_ADDR:%.*]] = alloc_stack $Error +// CHECK: [[ERROR_ADDR:%.*]] = alloc_stack $any Error // CHECK: [[ARRAY_GET:%.*]] = function_ref @$sSayxSicig -// CHECK: apply [[ARRAY_GET]]([[ERROR_ADDR]] -// CHECK: [[ERROR:%.*]] = load [take] [[ERROR_ADDR]] : $*Error +// CHECK: apply [[ARRAY_GET]]([[ERROR_ADDR]] +// CHECK: [[ERROR:%.*]] = load [take] [[ERROR_ADDR]] : $*any Error // CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] // CHECK: open_existential_box [[BORROWED_ERROR]] func test() { diff --git a/test/SILGen/builtins.swift b/test/SILGen/builtins.swift index 7aa92acc5b3c9..de751260ea5a7 100644 --- a/test/SILGen/builtins.swift +++ b/test/SILGen/builtins.swift @@ -217,11 +217,11 @@ func class_archetype_to_native_object(_ t: T) -> Builtin.NativeObject { } // CHECK-LABEL: sil hidden [ossa] @$s8builtins34class_existential_to_native_object{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[ARG:%.*]] : @guaranteed $ClassProto): +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any ClassProto): // CHECK-NEXT: debug_value // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]] -// CHECK-NEXT: [[REF:%[0-9]+]] = open_existential_ref [[ARG_COPY]] : $ClassProto -// CHECK-NEXT: [[PTR:%[0-9]+]] = unchecked_ref_cast [[REF]] : $@opened({{.*}}, ClassProto) Self to $Builtin.NativeObject +// CHECK-NEXT: [[REF:%[0-9]+]] = open_existential_ref [[ARG_COPY]] : $any ClassProto +// CHECK-NEXT: [[PTR:%[0-9]+]] = unchecked_ref_cast [[REF]] : $@opened({{.*}}, any ClassProto) Self to $Builtin.NativeObject // CHECK-NEXT: return [[PTR]] func class_existential_to_native_object(_ t:ClassProto) -> Builtin.NativeObject { return Builtin.unsafeCastToNativeObject(t as ClassProto) @@ -716,15 +716,15 @@ func refcast_class_any(_ o: A) -> AnyObject { } // CHECK-LABEL: sil hidden [ossa] @$s8builtins20refcast_punknown_any{{[_0-9a-zA-Z]*}}F -// CHECK: unchecked_ref_cast_addr PUnknown in %{{.*}} : $*PUnknown to AnyObject in %{{.*}} : $*AnyObject +// CHECK: unchecked_ref_cast_addr any PUnknown in %{{.*}} : $*any PUnknown to AnyObject in %{{.*}} : $*AnyObject func refcast_punknown_any(_ o: PUnknown) -> AnyObject { return Builtin.castReference(o as PUnknown) } // CHECK-LABEL: sil hidden [ossa] @$s8builtins18refcast_pclass_anyyyXlAA6PClass_pF : -// CHECK: bb0([[ARG:%.*]] : @guaranteed $PClass): +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any PClass): // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] -// CHECK: [[ARG_CAST:%.*]] = unchecked_ref_cast [[ARG_COPY]] : $PClass to $AnyObject +// CHECK: [[ARG_CAST:%.*]] = unchecked_ref_cast [[ARG_COPY]] : $any PClass to $AnyObject // CHECK: return [[ARG_CAST]] // CHECK: } // end sil function '$s8builtins18refcast_pclass_anyyyXlAA6PClass_pF' func refcast_pclass_any(_ o: PClass) -> AnyObject { @@ -732,7 +732,7 @@ func refcast_pclass_any(_ o: PClass) -> AnyObject { } // CHECK-LABEL: sil hidden [ossa] @$s8builtins20refcast_any_punknown{{[_0-9a-zA-Z]*}}F -// CHECK: unchecked_ref_cast_addr AnyObject in %{{.*}} : $*AnyObject to PUnknown in %{{.*}} : $*PUnknown +// CHECK: unchecked_ref_cast_addr AnyObject in %{{.*}} : $*AnyObject to any PUnknown in %{{.*}} : $*any PUnknown func refcast_any_punknown(_ o: AnyObject) -> PUnknown { return Builtin.castReference(o) } diff --git a/test/SILGen/call_as_function.swift b/test/SILGen/call_as_function.swift index e0282023d4685..81d8aaa7d9baf 100644 --- a/test/SILGen/call_as_function.swift +++ b/test/SILGen/call_as_function.swift @@ -16,17 +16,17 @@ class C { func callAsFunction(_ x: String) -> Self { return self } } -// CHECK-LABEL: sil hidden [ossa] @$s16call_as_function05test_a1_b1_C0yyAA1SV_AA2P1_pAA2P2_pxtAA1CCRbzlF : $@convention(thin) (S, @in_guaranteed P1, @in_guaranteed P2, @guaranteed T) -> () +// CHECK-LABEL: sil hidden [ossa] @$s16call_as_function05test_a1_b1_C0yyAA1SV_AA2P1_pAA2P2_pxtAA1CCRbzlF : $@convention(thin) (S, @in_guaranteed any P1, @in_guaranteed any P2, @guaranteed T) -> () func test_call_as_function(_ s: S, _ p1: P1, _ p2: P2, _ t: T) { // CHECK: function_ref @$s16call_as_function1SV0A10AsFunctionySiSgSiF : $@convention(method) (Int, S) -> Optional // CHECK: switch_enum %{{.+}} : $Optional let _: Int = s(0) // SR-12590: SILGen crash on existential callAsFunction. - // CHECK: witness_method $@opened({{.+}}, P1) Self, #P1.callAsFunction : (Self) -> () -> () + // CHECK: witness_method $@opened({{.+}}, any P1) Self, #P1.callAsFunction : (Self) -> () -> () p1() - // CHECK: witness_method $@opened({{.+}}, P2) Self, #P2.callAsFunction : (Self) -> () -> Self + // CHECK: witness_method $@opened({{.+}}, any P2) Self, #P2.callAsFunction : (Self) -> () -> Self _ = p2() // CHECK: class_method %{{.+}} : $C, #C.callAsFunction : (C) -> (String) -> @dynamic_self C, $@convention(method) (@guaranteed String, @guaranteed C) -> @owned C diff --git a/test/SILGen/casts.swift b/test/SILGen/casts.swift index e38208fa97105..2380c634b16ac 100644 --- a/test/SILGen/casts.swift +++ b/test/SILGen/casts.swift @@ -77,11 +77,11 @@ protocol P {} struct S : P {} // CHECK: sil hidden [ossa] @$s5casts32downcast_existential_conditional{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[IN:%.*]] : $*P): -// CHECK: [[COPY:%.*]] = alloc_stack $P +// CHECK: bb0([[IN:%.*]] : $*any P): +// CHECK: [[COPY:%.*]] = alloc_stack $any P // CHECK: copy_addr [[IN]] to [initialization] [[COPY]] // CHECK: [[TMP:%.*]] = alloc_stack $S -// CHECK: checked_cast_addr_br take_always P in [[COPY]] : $*P to S in [[TMP]] : $*S, bb1, bb2 +// CHECK: checked_cast_addr_br take_always any P in [[COPY]] : $*any P to S in [[TMP]] : $*S, bb1, bb2 // Success block. // CHECK: bb1: // CHECK: [[T0:%.*]] = load [trivial] [[TMP]] : $*S diff --git a/test/SILGen/class_bound_protocols.swift b/test/SILGen/class_bound_protocols.swift index d342d8bd9d1cd..b1ded07117b90 100644 --- a/test/SILGen/class_bound_protocols.swift +++ b/test/SILGen/class_bound_protocols.swift @@ -67,14 +67,14 @@ func class_bound_generic_2(x: T) -> T { // CHECK-LABEL: sil hidden [ossa] @$ss20class_bound_protocol{{[_0-9a-zA-Z]*}}F func class_bound_protocol(x: ClassBound) -> ClassBound { var x = x - // CHECK: bb0([[X:%.*]] : @guaranteed $ClassBound): - // CHECK: [[X_ADDR:%.*]] = alloc_box ${ var ClassBound } + // CHECK: bb0([[X:%.*]] : @guaranteed $any ClassBound): + // CHECK: [[X_ADDR:%.*]] = alloc_box ${ var any ClassBound } // CHECK: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X_ADDR]] // CHECK: [[PB:%.*]] = project_box [[X_LIFETIME]] // CHECK: [[X_COPY:%.*]] = copy_value [[X]] // CHECK: store [[X_COPY]] to [init] [[PB]] return x - // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*ClassBound + // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*any ClassBound // CHECK: [[X1:%.*]] = load [copy] [[READ]] // CHECK: return [[X1]] } @@ -83,14 +83,14 @@ func class_bound_protocol(x: ClassBound) -> ClassBound { func class_bound_protocol_composition(x: ClassBound & NotClassBound) -> ClassBound & NotClassBound { var x = x - // CHECK: bb0([[X:%.*]] : @guaranteed $ClassBound & NotClassBound): - // CHECK: [[X_ADDR:%.*]] = alloc_box ${ var ClassBound & NotClassBound } + // CHECK: bb0([[X:%.*]] : @guaranteed $any ClassBound & NotClassBound): + // CHECK: [[X_ADDR:%.*]] = alloc_box ${ var any ClassBound & NotClassBound } // CHECK: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X_ADDR]] // CHECK: [[PB:%.*]] = project_box [[X_LIFETIME]] // CHECK: [[X_COPY:%.*]] = copy_value [[X]] // CHECK: store [[X_COPY]] to [init] [[PB]] return x - // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*ClassBound & NotClassBound + // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*any ClassBound & NotClassBound // CHECK: [[X1:%.*]] = load [copy] [[READ]] // CHECK: return [[X1]] } @@ -98,7 +98,7 @@ func class_bound_protocol_composition(x: ClassBound & NotClassBound) // CHECK-LABEL: sil hidden [ossa] @$ss19class_bound_erasure{{[_0-9a-zA-Z]*}}F func class_bound_erasure(x: ConcreteClass) -> ClassBound { return x - // CHECK: [[PROTO:%.*]] = init_existential_ref {{%.*}} : $ConcreteClass, $ClassBound + // CHECK: [[PROTO:%.*]] = init_existential_ref {{%.*}} : $ConcreteClass, $any ClassBound // CHECK: return [[PROTO]] } @@ -106,18 +106,18 @@ func class_bound_erasure(x: ConcreteClass) -> ClassBound { func class_bound_existential_upcast(x: ClassBound & ClassBound2) -> ClassBound { return x - // CHECK: bb0([[ARG:%.*]] : @guaranteed $ClassBound & ClassBound2): - // CHECK: [[OPENED:%.*]] = open_existential_ref [[ARG]] : $ClassBound & ClassBound2 to [[OPENED_TYPE:\$@opened\(.*, ClassBound & ClassBound2\) Self]] + // CHECK: bb0([[ARG:%.*]] : @guaranteed $any ClassBound & ClassBound2): + // CHECK: [[OPENED:%.*]] = open_existential_ref [[ARG]] : $any ClassBound & ClassBound2 to [[OPENED_TYPE:\$@opened\(.*, any ClassBound & ClassBound2\) Self]] // CHECK: [[OPENED_COPY:%.*]] = copy_value [[OPENED]] - // CHECK: [[PROTO:%.*]] = init_existential_ref [[OPENED_COPY]] : [[OPENED_TYPE]] : [[OPENED_TYPE]], $ClassBound + // CHECK: [[PROTO:%.*]] = init_existential_ref [[OPENED_COPY]] : [[OPENED_TYPE]] : [[OPENED_TYPE]], $any ClassBound // CHECK: return [[PROTO]] } // CHECK: } // end sil function '$ss30class_bound_existential_upcast1xs10ClassBound_psAC_s0E6Bound2p_tF' // CHECK-LABEL: sil hidden [ossa] @$ss41class_bound_to_unbound_existential_upcast1xs13NotClassBound_ps0hI0_sACp_tF : -// CHECK: bb0([[ARG0:%.*]] : $*NotClassBound, [[ARG1:%.*]] : @guaranteed $ClassBound & NotClassBound): -// CHECK: [[X_OPENED:%.*]] = open_existential_ref [[ARG1]] : $ClassBound & NotClassBound to [[OPENED_TYPE:\$@opened\(.*, ClassBound & NotClassBound\) Self]] -// CHECK: [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[ARG0]] : $*NotClassBound, [[OPENED_TYPE]] +// CHECK: bb0([[ARG0:%.*]] : $*any NotClassBound, [[ARG1:%.*]] : @guaranteed $any ClassBound & NotClassBound): +// CHECK: [[X_OPENED:%.*]] = open_existential_ref [[ARG1]] : $any ClassBound & NotClassBound to [[OPENED_TYPE:\$@opened\(.*, any ClassBound & NotClassBound\) Self]] +// CHECK: [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[ARG0]] : $*any NotClassBound, [[OPENED_TYPE]] // CHECK: [[X_OPENED_COPY:%.*]] = copy_value [[X_OPENED]] // CHECK: store [[X_OPENED_COPY]] to [init] [[PAYLOAD_ADDR]] func class_bound_to_unbound_existential_upcast @@ -126,18 +126,18 @@ func class_bound_to_unbound_existential_upcast } // CHECK-LABEL: sil hidden [ossa] @$ss18class_bound_method1xys10ClassBound_p_tF : -// CHECK: bb0([[ARG:%.*]] : @guaranteed $ClassBound): +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any ClassBound): func class_bound_method(x: ClassBound) { var x = x x.classBoundMethod() - // CHECK: [[XBOX:%.*]] = alloc_box ${ var ClassBound }, var, name "x" + // CHECK: [[XBOX:%.*]] = alloc_box ${ var any ClassBound }, var, name "x" // CHECK: [[XLIFETIME:%[^,]+]] = begin_borrow [lexical] [[XBOX]] // CHECK: [[XBOX_PB:%.*]] = project_box [[XLIFETIME]] // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] // CHECK: store [[ARG_COPY]] to [init] [[XBOX_PB]] - // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[XBOX_PB]] : $*ClassBound - // CHECK: [[X:%.*]] = load [copy] [[READ]] : $*ClassBound - // CHECK: [[PROJ:%.*]] = open_existential_ref [[X]] : $ClassBound to $[[OPENED:@opened\(.*, ClassBound\) Self]] + // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[XBOX_PB]] : $*any ClassBound + // CHECK: [[X:%.*]] = load [copy] [[READ]] : $*any ClassBound + // CHECK: [[PROJ:%.*]] = open_existential_ref [[X]] : $any ClassBound to $[[OPENED:@opened\(.*, any ClassBound\) Self]] // CHECK: [[METHOD:%.*]] = witness_method $[[OPENED]], #ClassBound.classBoundMethod : // CHECK: apply [[METHOD]]<[[OPENED]]>([[PROJ]]) // CHECK: destroy_value [[PROJ]] @@ -159,28 +159,28 @@ protocol InheritsMutatingMethod : class, HasMutatingMethod {} func takesInOut(_: inout T) {} -// CHECK-LABEL: sil hidden [ossa] @$ss27takesInheritsMutatingMethod1x1yys0bcD0_pz_s5ValueVtF : $@convention(thin) (@inout InheritsMutatingMethod, Value) -> () { +// CHECK-LABEL: sil hidden [ossa] @$ss27takesInheritsMutatingMethod1x1yys0bcD0_pz_s5ValueVtF : $@convention(thin) (@inout any InheritsMutatingMethod, Value) -> () { func takesInheritsMutatingMethod(x: inout InheritsMutatingMethod, y: Value) { - // CHECK: [[X_ADDR:%.*]] = begin_access [modify] [unknown] %0 : $*InheritsMutatingMethod - // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*InheritsMutatingMethod - // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $InheritsMutatingMethod to $@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", InheritsMutatingMethod) Self, #HasMutatingMethod.mutateMe : (inout Self) -> () -> (), [[X_PAYLOAD]] : $@opened("{{.*}}", InheritsMutatingMethod) Self : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@inout τ_0_0) -> () - // CHECK-NEXT: apply [[METHOD]]<@opened("{{.*}}", InheritsMutatingMethod) Self>([[TEMPORARY]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@inout τ_0_0) -> () - // CHECK-NEXT: [[X_PAYLOAD:%.*]] = load [take] [[TEMPORARY]] : $*@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: [[X_VALUE:%.*]] = init_existential_ref [[X_PAYLOAD]] : $@opened("{{.*}}", InheritsMutatingMethod) Self : $@opened("{{.*}}", InheritsMutatingMethod) Self, $InheritsMutatingMethod - // CHECK-NEXT: assign [[X_VALUE]] to [[X_ADDR]] : $*InheritsMutatingMethod - // CHECK-NEXT: end_access [[X_ADDR]] : $*InheritsMutatingMethod - // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}", InheritsMutatingMethod) Self + // CHECK: [[X_ADDR:%.*]] = begin_access [modify] [unknown] %0 : $*any InheritsMutatingMethod + // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*any InheritsMutatingMethod + // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $any InheritsMutatingMethod to $@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", any InheritsMutatingMethod) Self, #HasMutatingMethod.mutateMe : (inout Self) -> () -> (), [[X_PAYLOAD]] : $@opened("{{.*}}", any InheritsMutatingMethod) Self : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@inout τ_0_0) -> () + // CHECK-NEXT: apply [[METHOD]]<@opened("{{.*}}", any InheritsMutatingMethod) Self>([[TEMPORARY]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@inout τ_0_0) -> () + // CHECK-NEXT: [[X_PAYLOAD:%.*]] = load [take] [[TEMPORARY]] : $*@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: [[X_VALUE:%.*]] = init_existential_ref [[X_PAYLOAD]] : $@opened("{{.*}}", any InheritsMutatingMethod) Self : $@opened("{{.*}}", any InheritsMutatingMethod) Self, $any InheritsMutatingMethod + // CHECK-NEXT: assign [[X_VALUE]] to [[X_ADDR]] : $*any InheritsMutatingMethod + // CHECK-NEXT: end_access [[X_ADDR]] : $*any InheritsMutatingMethod + // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}", any InheritsMutatingMethod) Self x.mutateMe() - // CHECK-NEXT: [[X_ADDR:%.*]] = begin_access [read] [unknown] %0 : $*InheritsMutatingMethod - // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*InheritsMutatingMethod - // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $InheritsMutatingMethod to $@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}", InheritsMutatingMethod) Self + // CHECK-NEXT: [[X_ADDR:%.*]] = begin_access [read] [unknown] %0 : $*any InheritsMutatingMethod + // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*any InheritsMutatingMethod + // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $any InheritsMutatingMethod to $@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}", any InheritsMutatingMethod) Self // CHECK-NEXT: [[X_PAYLOAD_RELOADED:%.*]] = load_borrow [[TEMPORARY]] // // ** *NOTE* This extra copy is here since RValue invariants enforce that all @@ -188,31 +188,31 @@ func takesInheritsMutatingMethod(x: inout InheritsMutatingMethod, // ** load... only to then need to store the value back in a stack location to // ** pass to an in_guaranteed method. PredictableMemOpts is able to handle this // ** type of temporary codegen successfully. - // CHECK-NEXT: [[TEMPORARY_2:%.*]] = alloc_stack $@opened("{{.*}}", InheritsMutatingMethod) Self + // CHECK-NEXT: [[TEMPORARY_2:%.*]] = alloc_stack $@opened("{{.*}}", any InheritsMutatingMethod) Self // CHECK-NEXT: [[SB:%.*]] = store_borrow [[X_PAYLOAD_RELOADED:%.*]] to [[TEMPORARY_2]] // - // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", InheritsMutatingMethod) Self, #HasMutatingMethod.mutatingCounter!getter : (Self) -> () -> Value, [[X_PAYLOAD]] : $@opened("{{.*}}", InheritsMutatingMethod) Self : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value - // CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[METHOD]]<@opened("{{.*}}", InheritsMutatingMethod) Self>([[SB]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value + // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", any InheritsMutatingMethod) Self, #HasMutatingMethod.mutatingCounter!getter : (Self) -> () -> Value, [[X_PAYLOAD]] : $@opened("{{.*}}", any InheritsMutatingMethod) Self : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value + // CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[METHOD]]<@opened("{{.*}}", any InheritsMutatingMethod) Self>([[SB]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value // CHECK-NEXT: end_borrow [[SB]] // CHECK-NEXT: dealloc_stack [[TEMPORARY_2]] // CHECK-NEXT: end_borrow // CHECK-NEXT: destroy_addr - // CHECK-NEXT: end_access [[X_ADDR]] : $*InheritsMutatingMethod - // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}", InheritsMutatingMethod) Self + // CHECK-NEXT: end_access [[X_ADDR]] : $*any InheritsMutatingMethod + // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}", any InheritsMutatingMethod) Self _ = x.mutatingCounter - // CHECK-NEXT: [[X_ADDR:%.*]] = begin_access [modify] [unknown] %0 : $*InheritsMutatingMethod - // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*InheritsMutatingMethod - // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $InheritsMutatingMethod to $@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", InheritsMutatingMethod) Self, #HasMutatingMethod.mutatingCounter!setter : (inout Self) -> (Value) -> (), [[X_PAYLOAD]] : $@opened("{{.*}}", InheritsMutatingMethod) Self : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (Value, @inout τ_0_0) -> () - // CHECK-NEXT: apply [[METHOD]]<@opened("{{.*}}", InheritsMutatingMethod) Self>(%1, [[TEMPORARY]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (Value, @inout τ_0_0) -> () - // CHECK-NEXT: [[X_PAYLOAD:%.*]] = load [take] [[TEMPORARY]] : $*@opened("{{.*}}", InheritsMutatingMethod) Self - // CHECK-NEXT: [[X_VALUE:%.*]] = init_existential_ref [[X_PAYLOAD]] : $@opened("{{.*}}", InheritsMutatingMethod) Self : $@opened("{{.*}}", InheritsMutatingMethod) Self, $InheritsMutatingMethod - // CHECK-NEXT: assign [[X_VALUE]] to [[X_ADDR]] : $*InheritsMutatingMethod - // CHECK-NEXT: end_access [[X_ADDR]] : $*InheritsMutatingMethod - // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}", InheritsMutatingMethod) Self + // CHECK-NEXT: [[X_ADDR:%.*]] = begin_access [modify] [unknown] %0 : $*any InheritsMutatingMethod + // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*any InheritsMutatingMethod + // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $any InheritsMutatingMethod to $@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", any InheritsMutatingMethod) Self, #HasMutatingMethod.mutatingCounter!setter : (inout Self) -> (Value) -> (), [[X_PAYLOAD]] : $@opened("{{.*}}", any InheritsMutatingMethod) Self : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (Value, @inout τ_0_0) -> () + // CHECK-NEXT: apply [[METHOD]]<@opened("{{.*}}", any InheritsMutatingMethod) Self>(%1, [[TEMPORARY]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (Value, @inout τ_0_0) -> () + // CHECK-NEXT: [[X_PAYLOAD:%.*]] = load [take] [[TEMPORARY]] : $*@opened("{{.*}}", any InheritsMutatingMethod) Self + // CHECK-NEXT: [[X_VALUE:%.*]] = init_existential_ref [[X_PAYLOAD]] : $@opened("{{.*}}", any InheritsMutatingMethod) Self : $@opened("{{.*}}", any InheritsMutatingMethod) Self, $any InheritsMutatingMethod + // CHECK-NEXT: assign [[X_VALUE]] to [[X_ADDR]] : $*any InheritsMutatingMethod + // CHECK-NEXT: end_access [[X_ADDR]] : $*any InheritsMutatingMethod + // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}", any InheritsMutatingMethod) Self x.mutatingCounter = y takesInOut(&x.mutatingCounter) diff --git a/test/SILGen/codable/struct_codable_member_type_lookup.swift b/test/SILGen/codable/struct_codable_member_type_lookup.swift index 45e0f539df097..af1fb5e8408c0 100644 --- a/test/SILGen/codable/struct_codable_member_type_lookup.swift +++ b/test/SILGen/codable/struct_codable_member_type_lookup.swift @@ -2,10 +2,10 @@ // Make sure we have an int, not a float. // -// CHECK-LABEL: sil hidden [ossa] @$s33struct_codable_member_type_lookup32StaticInstanceNameDisambiguationV6encode2to{{.*}}F : $@convention(method) (@in_guaranteed Encoder, StaticInstanceNameDisambiguation) -> @error Error { -// CHECK: bb0([[ENCODER:%.*]] : $*Encoder, [[INPUT:%.*]] : $StaticInstanceNameDisambiguation): +// CHECK-LABEL: sil hidden [ossa] @$s33struct_codable_member_type_lookup32StaticInstanceNameDisambiguationV6encode2to{{.*}}F : $@convention(method) (@in_guaranteed any Encoder, StaticInstanceNameDisambiguation) -> @error any Error { +// CHECK: bb0([[ENCODER:%.*]] : $*any Encoder, [[INPUT:%.*]] : $StaticInstanceNameDisambiguation): // CHECK: [[INT_VALUE:%.*]] = struct_extract [[INPUT]] -// CHECK: [[FUNC:%.*]] = function_ref @$ss22KeyedEncodingContainerV6encode_6forKeyySi_xtKF : $@convention(method) <τ_0_0 where τ_0_0 : CodingKey> (Int, @in_guaranteed τ_0_0, @inout KeyedEncodingContainer<τ_0_0>) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @$ss22KeyedEncodingContainerV6encode_6forKeyySi_xtKF : $@convention(method) <τ_0_0 where τ_0_0 : CodingKey> (Int, @in_guaranteed τ_0_0, @inout KeyedEncodingContainer<τ_0_0>) -> @error any Error // CHECK: try_apply [[FUNC]]([[INT_VALUE]], // CHECK: } // end sil function '$s33struct_codable_member_type_lookup32StaticInstanceNameDisambiguationV6encode2toys7Encoder_p_tKF' struct StaticInstanceNameDisambiguation : Codable { diff --git a/test/SILGen/default_arguments.swift b/test/SILGen/default_arguments.swift index 98efd29f3ffe1..58cccc9fe46b5 100644 --- a/test/SILGen/default_arguments.swift +++ b/test/SILGen/default_arguments.swift @@ -292,12 +292,12 @@ func localFunctionWithDefaultArg() { // CHECK-LABEL: sil private [ossa] @$s17default_arguments27localFunctionWithDefaultArgyyF3barL_yySiSgFfA_ // CHECK-SAME: $@convention(thin) () -> Optional -// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments15throwingDefault7closureySbyKXE_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments15throwingDefault7closureySbyKXE_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) func throwingDefault(closure: () throws -> Bool = { return true }) throws { try _ = closure() } -// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) func throwingAutoclosureDefault(closure: @autoclosure () throws -> Bool = true ) throws { try _ = closure() } @@ -312,12 +312,12 @@ func autoclosureDefaultArg(closure: @autoclosure () -> Bool = true ) { _ = closure() } -// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments23throwingDefaultEscaping7closureySbyKc_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments23throwingDefaultEscaping7closureySbyKc_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) func throwingDefaultEscaping(closure: @escaping () throws -> Bool = { return true }) throws { try _ = closure() } -// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) func throwingAutoclosureDefaultEscaping(closure: @escaping @autoclosure () throws -> Bool = true ) throws { try _ = closure() } @@ -332,18 +332,18 @@ func autoclosureDefaultEscaping(closure: @escaping @autoclosure () -> Bool = tr _ = closure() } -// CHECK-LABEL: sil hidden [ossa] @{{.*}}callThem{{.*}} : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil hidden [ossa] @{{.*}}callThem{{.*}} : $@convention(thin) () -> @error any Error -// CHECK: [[F:%.*]] = function_ref @$s17default_arguments15throwingDefault7closureySbyKXE_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) -// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) +// CHECK: [[F:%.*]] = function_ref @$s17default_arguments15throwingDefault7closureySbyKXE_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) +// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) // CHECK: [[E:%.*]] = convert_escape_to_noescape [not_guaranteed] [[C]] -// CHECK: [[R:%.*]] = function_ref @$s17default_arguments15throwingDefault7closureySbyKXE_tKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Bool, @error Error)) -> @error Error +// CHECK: [[R:%.*]] = function_ref @$s17default_arguments15throwingDefault7closureySbyKXE_tKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Bool, @error any Error)) -> @error any Error // CHECK: try_apply [[R]]([[E]]) -// CHECK: [[F:%.*]] = function_ref @$s17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) -// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) +// CHECK: [[F:%.*]] = function_ref @$s17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) +// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) // CHECK: [[E:%.*]] = convert_escape_to_noescape [not_guaranteed] [[C]] -// CHECK: [[R:%.*]] = function_ref @$s17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Bool, @error Error)) -> @error Error +// CHECK: [[R:%.*]] = function_ref @$s17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Bool, @error any Error)) -> @error any Error // CHECK: try_apply [[R]]([[E]]) // CHECK: [[F:%.*]] = function_ref @$s17default_arguments0A3Arg7closureySbyXE_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool @@ -358,14 +358,14 @@ func autoclosureDefaultEscaping(closure: @escaping @autoclosure () -> Bool = tr // CHECK: [[R:%.*]] = function_ref @$s17default_arguments21autoclosureDefaultArg7closureySbyXK_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> () // CHECK: apply [[R]]([[E]]) -// CHECK: [[F:%.*]] = function_ref @$s17default_arguments23throwingDefaultEscaping7closureySbyKc_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) -// CHECK: [[E:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) -// CHECK: [[R:%.*]] = function_ref @$s17default_arguments23throwingDefaultEscaping7closureySbyKc_tKF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Bool, @error Error)) -> @error Erro +// CHECK: [[F:%.*]] = function_ref @$s17default_arguments23throwingDefaultEscaping7closureySbyKc_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) +// CHECK: [[E:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) +// CHECK: [[R:%.*]] = function_ref @$s17default_arguments23throwingDefaultEscaping7closureySbyKc_tKF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Bool, @error any Error)) -> @error any Error // CHECK: try_apply [[R]]([[E]]) -// CHECK: [[F:%.*]] = function_ref @$s17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) -// CHECK: [[E:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error) -// CHECK: [[R:%.*]] = function_ref @$s17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Bool, @error Error)) -> @error Error +// CHECK: [[F:%.*]] = function_ref @$s17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) +// CHECK: [[E:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error any Error) +// CHECK: [[R:%.*]] = function_ref @$s17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Bool, @error any Error)) -> @error any Error // CHECK: try_apply [[R]]([[E]]) // CHECK: [[F:%.*]] = function_ref @$s17default_arguments0A8Escaping7closureySbyc_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool diff --git a/test/SILGen/dependent_member_lowering.swift b/test/SILGen/dependent_member_lowering.swift index 88f826efabab1..30259091cf6ab 100644 --- a/test/SILGen/dependent_member_lowering.swift +++ b/test/SILGen/dependent_member_lowering.swift @@ -30,7 +30,7 @@ protocol P1: P0 where Foo == String { func foo() -> String } -// CHECK-LABEL: sil hidden [ossa] @$s25dependent_member_lowering26existentialDependentMemberySSAA2P1_pF : $@convention(thin) (@in_guaranteed P1) -> @owned String +// CHECK-LABEL: sil hidden [ossa] @$s25dependent_member_lowering26existentialDependentMemberySSAA2P1_pF : $@convention(thin) (@in_guaranteed any P1) -> @owned String func existentialDependentMember(_ p1: any P1) -> String { // CHECK: $@convention(witness_method: P0) <τ_0_0 where τ_0_0 : P0> (@in_guaranteed τ_0_0) -> @out τ_0_0.Foo return p1.foo() diff --git a/test/SILGen/distributed_thunk.swift b/test/SILGen/distributed_thunk.swift index 84b9bc448b633..238d6f135a4f4 100644 --- a/test/SILGen/distributed_thunk.swift +++ b/test/SILGen/distributed_thunk.swift @@ -9,7 +9,7 @@ distributed actor DA { } extension DA { - // CHECK-LABEL: sil hidden [thunk] [distributed] [ref_adhoc_requirement_witness "$s11Distributed29LocalTestingInvocationDecoderC18decodeNextArgumentxyKSeRzSERzlF"] [ossa] @$s17distributed_thunk2DAC1fyyYaKFTE : $@convention(method) @async (@guaranteed DA) -> @error Error { + // CHECK-LABEL: sil hidden [thunk] [distributed] [ref_adhoc_requirement_witness "$s11Distributed29LocalTestingInvocationDecoderC18decodeNextArgumentxyKSeRzSERzlF"] [ossa] @$s17distributed_thunk2DAC1fyyYaKFTE : $@convention(method) @async (@guaranteed DA) -> @error any Error { // CHECK: function_ref @swift_distributed_actor_is_remote // Call the actor function @@ -23,7 +23,7 @@ protocol ServerProto { } extension DA: ServerProto { - // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk2DACAA11ServerProtoA2aDP11doSomethingyyYaKFTW : $@convention(witness_method: ServerProto) @async (@in_guaranteed DA) -> @error Error + // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk2DACAA11ServerProtoA2aDP11doSomethingyyYaKFTW : $@convention(witness_method: ServerProto) @async (@in_guaranteed DA) -> @error any Error // TODO: we do hop here actually; ...-NOT: hop_to_executor // CHECK: function_ref @$s17distributed_thunk2DAC11doSomethingyyYaKFTE // CHECK: return @@ -33,7 +33,7 @@ extension DA: ServerProto { distributed actor DA2: ServerProto { typealias ActorSystem = LocalTestingDistributedActorSystem - // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk3DA2CAA11ServerProtoA2aDP11doSomethingyyYaKFTW : $@convention(witness_method: ServerProto) @async (@in_guaranteed DA2) -> @error Error + // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk3DA2CAA11ServerProtoA2aDP11doSomethingyyYaKFTW : $@convention(witness_method: ServerProto) @async (@in_guaranteed DA2) -> @error any Error // CHECK-NOT: hop_to_executor // CHECK-NOT: return // CHECK: function_ref @$s17distributed_thunk3DA2C11doSomethingyyYaKFTE diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift index 87fe564926510..ddebaf67597cc 100644 --- a/test/SILGen/dynamic.swift +++ b/test/SILGen/dynamic.swift @@ -466,13 +466,13 @@ public class Base { public class Sub : Base { // CHECK-LABEL: sil hidden [ossa] @$s7dynamic3SubC1xSbvg : $@convention(method) (@guaranteed Sub) -> Bool { // CHECK: bb0([[SELF:%.*]] : @guaranteed $Sub): - // CHECK: [[AUTOCLOSURE:%.*]] = function_ref @$s7dynamic3SubC1xSbvgSbyKXEfu_ : $@convention(thin) (@guaranteed Sub) -> (Bool, @error Error) + // CHECK: [[AUTOCLOSURE:%.*]] = function_ref @$s7dynamic3SubC1xSbvgSbyKXEfu_ : $@convention(thin) (@guaranteed Sub) -> (Bool, @error any Error) // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] // CHECK: = partial_apply [callee_guaranteed] [[AUTOCLOSURE]]([[SELF_COPY]]) // CHECK: return {{%.*}} : $Bool // CHECK: } // end sil function '$s7dynamic3SubC1xSbvg' - // CHECK-LABEL: sil private [transparent] [ossa] @$s7dynamic3SubC1xSbvgSbyKXEfu_ : $@convention(thin) (@guaranteed Sub) -> (Bool, @error Error) { + // CHECK-LABEL: sil private [transparent] [ossa] @$s7dynamic3SubC1xSbvgSbyKXEfu_ : $@convention(thin) (@guaranteed Sub) -> (Bool, @error any Error) { // CHECK: bb0([[VALUE:%.*]] : @guaranteed $Sub): // CHECK: [[VALUE_COPY:%.*]] = copy_value [[VALUE]] // CHECK: [[CAST_VALUE_COPY:%.*]] = upcast [[VALUE_COPY]] diff --git a/test/SILGen/dynamic_callable_attribute.swift b/test/SILGen/dynamic_callable_attribute.swift index a18123f48e38c..34b257b58461e 100644 --- a/test/SILGen/dynamic_callable_attribute.swift +++ b/test/SILGen/dynamic_callable_attribute.swift @@ -59,17 +59,17 @@ class C { func dynamicallyCall(withKeywordArguments x: [String: String]) -> Self { return self } } -// CHECK-LABEL: sil hidden [ossa] @$s26dynamic_callable_attribute05test_A10_callablesyyAA1SV_AA2P1_pAA2P2_pxtAA1CCRbzlF : $@convention(thin) (S, @in_guaranteed P1, @in_guaranteed P2, @guaranteed T) -> () +// CHECK-LABEL: sil hidden [ossa] @$s26dynamic_callable_attribute05test_A10_callablesyyAA1SV_AA2P1_pAA2P2_pxtAA1CCRbzlF : $@convention(thin) (S, @in_guaranteed any P1, @in_guaranteed any P2, @guaranteed T) -> () func test_dynamic_callables(_ s: S, _ p1: P1, _ p2: P2, _ t: T) { // SR-12615: Compiler crash on @dynamicCallable IUO. // CHECK: function_ref @$s26dynamic_callable_attribute1SV15dynamicallyCall13withArgumentsSiSgSaySiG_tF : $@convention(method) (@guaranteed Array, S) -> Optional // CHECK: switch_enum %{{.+}} : $Optional let _: Int = s(0) - // CHECK: witness_method $@opened({{.+}} P1) Self, #P1.dynamicallyCall : (Self) -> ([String : Any]) -> () + // CHECK: witness_method $@opened({{.+}} any P1) Self, #P1.dynamicallyCall : (Self) -> ([String : Any]) -> () p1(x: 5) - // CHECK: witness_method $@opened({{.+}} P2) Self, #P2.dynamicallyCall : (Self) -> ([Int]) -> Self + // CHECK: witness_method $@opened({{.+}} any P2) Self, #P2.dynamicallyCall : (Self) -> ([Int]) -> Self _ = p2() // CHECK: class_method %{{.+}} : $C, #C.dynamicallyCall : (C) -> ([String : String]) -> @dynamic_self C, $@convention(method) (@guaranteed Dictionary, @guaranteed C) -> @owned C diff --git a/test/SILGen/dynamic_lookup.swift b/test/SILGen/dynamic_lookup.swift index 557338ca0b01a..a7b307adc877c 100644 --- a/test/SILGen/dynamic_lookup.swift +++ b/test/SILGen/dynamic_lookup.swift @@ -61,8 +61,8 @@ func direct_to_static_method(_ obj: AnyObject) { // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]] // CHECK-NEXT: [[OBJCOPY:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject // CHECK: end_access [[READ]] - // CHECK-NEXT: [[OBJMETA:%[0-9]+]] = existential_metatype $@thick AnyObject.Type, [[OBJCOPY]] : $AnyObject - // CHECK-NEXT: [[OPENMETA:%[0-9]+]] = open_existential_metatype [[OBJMETA]] : $@thick AnyObject.Type to $@thick (@opened([[UUID:".*"]], AnyObject) Self).Type + // CHECK-NEXT: [[OBJMETA:%[0-9]+]] = existential_metatype $@thick any AnyObject.Type, [[OBJCOPY]] : $AnyObject + // CHECK-NEXT: [[OPENMETA:%[0-9]+]] = open_existential_metatype [[OBJMETA]] : $@thick any AnyObject.Type to $@thick (@opened([[UUID:".*"]], AnyObject) Self).Type // CHECK-NEXT: [[METHOD:%[0-9]+]] = objc_method [[OPENMETA]] : $@thick (@opened([[UUID]], AnyObject) Self).Type, #X.staticF!foreign : (X.Type) -> () -> (), $@convention(objc_method) (@thick (@opened([[UUID]], AnyObject) Self).Type) -> () // CHECK: apply [[METHOD]]([[OPENMETA]]) : $@convention(objc_method) (@thick (@opened([[UUID]], AnyObject) Self).Type) -> () // CHECK: end_borrow [[OBJLIFETIME]] @@ -122,7 +122,7 @@ func opt_to_class(_ obj: AnyObject) { // CHECK-LABEL: sil hidden [ossa] @$s14dynamic_lookup20opt_to_class_unboundyyF : $@convention(thin) () -> () { // CHECK: bb0: -// CHECK: metatype $@thin AnyObject.Protocol +// CHECK: metatype $@thin (any AnyObject).Type // CHECK: function_ref @$[[THUNK_NAME:[_a-zA-Z0-9]+]] // CHECK: } // end sil function '$s14dynamic_lookup20opt_to_class_unboundyyF' // @@ -157,8 +157,8 @@ func opt_to_static_method(_ obj: AnyObject) { // CHECK: [[PBO:%.*]] = project_box [[OPTLIFETIME]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]] // CHECK: [[OBJCOPY:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject - // CHECK: [[OBJMETA:%[0-9]+]] = existential_metatype $@thick AnyObject.Type, [[OBJCOPY]] : $AnyObject - // CHECK: [[OPENMETA:%[0-9]+]] = open_existential_metatype [[OBJMETA]] : $@thick AnyObject.Type to $@thick (@opened + // CHECK: [[OBJMETA:%[0-9]+]] = existential_metatype $@thick any AnyObject.Type, [[OBJCOPY]] : $AnyObject + // CHECK: [[OPENMETA:%[0-9]+]] = open_existential_metatype [[OBJMETA]] : $@thick any AnyObject.Type to $@thick (@opened // CHECK: [[OBJCMETA:%[0-9]+]] = thick_to_objc_metatype [[OPENMETA]] // CHECK: [[OPTTEMP:%.*]] = alloc_stack $Optional<@callee_guaranteed () -> ()> // CHECK: dynamic_method_br [[OBJCMETA]] : $@objc_metatype (@opened({{".*"}}, AnyObject) Self).Type, #X.staticF!foreign, [[HASMETHOD:[A-Za-z0-9_]+]], [[NOMETHOD:[A-Za-z0-9_]+]] @@ -359,13 +359,13 @@ func downcast(_ obj: AnyObject) -> X { } // CHECK-LABEL: sil hidden [ossa] @$s14dynamic_lookup7consumeyyAA5Fruit_pF -// CHECK: bb0(%0 : @guaranteed $Fruit): +// CHECK: bb0(%0 : @guaranteed $any Fruit): // CHECK: [[BOX:%.*]] = alloc_stack $Optional -// CHECK: dynamic_method_br [[SELF:%.*]] : $@opened("{{.*}}", Fruit) Self, #Fruit.juice!getter.foreign, bb1, bb2 +// CHECK: dynamic_method_br [[SELF:%.*]] : $@opened("{{.*}}", any Fruit) Self, #Fruit.juice!getter.foreign, bb1, bb2 -// CHECK: bb1([[FN:%.*]] : $@convention(objc_method) (@opened("{{.*}}", Fruit) Self) -> @autoreleased Juice): +// CHECK: bb1([[FN:%.*]] : $@convention(objc_method) (@opened("{{.*}}", any Fruit) Self) -> @autoreleased Juice): // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] -// CHECK: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]]([[SELF_COPY]]) : $@convention(objc_method) (@opened("{{.*}}", Fruit) Self) -> @autoreleased Juice +// CHECK: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]]([[SELF_COPY]]) : $@convention(objc_method) (@opened("{{.*}}", any Fruit) Self) -> @autoreleased Juice // CHECK: [[B:%.*]] = begin_borrow [[METHOD]] // CHECK: [[RESULT:%.*]] = apply [[B]]() : $@callee_guaranteed () -> @owned Juice // CHECK: end_borrow [[B]] diff --git a/test/SILGen/dynamic_lookup_throws.swift b/test/SILGen/dynamic_lookup_throws.swift index bb853cb2e8c17..03209f9f551ee 100644 --- a/test/SILGen/dynamic_lookup_throws.swift +++ b/test/SILGen/dynamic_lookup_throws.swift @@ -12,7 +12,7 @@ class Blub : NSObject { @objc func blub() throws {} } -// CHECK-LABEL: sil hidden [ossa] @$s21dynamic_lookup_throws8testBlub1ayyXl_tKF : $@convention(thin) (@guaranteed AnyObject) -> @error Error +// CHECK-LABEL: sil hidden [ossa] @$s21dynamic_lookup_throws8testBlub1ayyXl_tKF : $@convention(thin) (@guaranteed AnyObject) -> @error any Error // CHECK: bb0([[ARG:%.*]] : @guaranteed $AnyObject): func testBlub(a: AnyObject) throws { // CHECK: [[ANYOBJECT_REF:%.*]] = open_existential_ref [[ARG]] : $AnyObject to $@opened("[[OPENED:.*]]", AnyObject) Self @@ -25,6 +25,6 @@ func testBlub(a: AnyObject) throws { // CHECK: bb2 // CHECK: function_ref @$s10Foundation22_convertNSErrorToErrorys0E0_pSo0C0CSgF - // CHECK: throw {{%.*}} : $Error + // CHECK: throw {{%.*}} : $any Error try a.blub() } diff --git a/test/SILGen/dynamic_self.swift b/test/SILGen/dynamic_self.swift index 21f64ea58364d..b2cb414efa9b3 100644 --- a/test/SILGen/dynamic_self.swift +++ b/test/SILGen/dynamic_self.swift @@ -84,73 +84,73 @@ func testArchetypeDispatch(t: T) { // CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self23testExistentialDispatch{{[_0-9a-zA-Z]*}}F func testExistentialDispatch(p: P) { -// CHECK: bb0([[P:%[0-9]+]] : $*P): -// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P to $*@opened([[N:".*"]], P) Self -// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $P -// CHECK: [[P_F_METHOD:%[0-9]+]] = witness_method $@opened([[N]], P) Self, #P.f : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 -// CHECK: [[P_RESULT_ADDR:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*P, $@opened([[N]], P) Self -// CHECK: apply [[P_F_METHOD]]<@opened([[N]], P) Self>([[P_RESULT_ADDR]], [[PCOPY_ADDR]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 -// CHECK: destroy_addr [[P_RESULT]] : $*P -// CHECK: dealloc_stack [[P_RESULT]] : $*P +// CHECK: bb0([[P:%[0-9]+]] : $*any P): +// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P to $*@opened([[N:".*"]], any P) Self +// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $any P +// CHECK: [[P_F_METHOD:%[0-9]+]] = witness_method $@opened([[N]], any P) Self, #P.f : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: [[P_RESULT_ADDR:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*any P, $@opened([[N]], any P) Self +// CHECK: apply [[P_F_METHOD]]<@opened([[N]], any P) Self>([[P_RESULT_ADDR]], [[PCOPY_ADDR]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: destroy_addr [[P_RESULT]] : $*any P +// CHECK: dealloc_stack [[P_RESULT]] : $*any P _ = p.f() -// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P to $*@opened([[N:".*"]], P) Self -// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $P -// CHECK: [[PCOPY_ADDR_1:%[0-9]+]] = alloc_stack $@opened([[N]], P) Self -// CHECK: copy_addr [[PCOPY_ADDR]] to [initialization] [[PCOPY_ADDR_1]] : $*@opened([[N]], P) Self -// CHECK: [[P_P_GETTER:%[0-9]+]] = witness_method $@opened([[N]], P) Self, #P.p!getter : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 -// CHECK: [[P_RESULT_ADDR2:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*P, $@opened([[N]], P) Self -// CHECK: apply [[P_P_GETTER]]<@opened([[N]], P) Self>([[P_RESULT_ADDR2]], [[PCOPY_ADDR_1]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 -// CHECK: destroy_addr [[PCOPY_ADDR_1]] : $*@opened([[N]], P) Self -// CHECK: destroy_addr [[P_RESULT]] : $*P -// CHECK: dealloc_stack [[PCOPY_ADDR_1]] : $*@opened([[N]], P) Self -// CHECK: dealloc_stack [[P_RESULT]] : $*P +// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P to $*@opened([[N:".*"]], any P) Self +// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $any P +// CHECK: [[PCOPY_ADDR_1:%[0-9]+]] = alloc_stack $@opened([[N]], any P) Self +// CHECK: copy_addr [[PCOPY_ADDR]] to [initialization] [[PCOPY_ADDR_1]] : $*@opened([[N]], any P) Self +// CHECK: [[P_P_GETTER:%[0-9]+]] = witness_method $@opened([[N]], any P) Self, #P.p!getter : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: [[P_RESULT_ADDR2:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*any P, $@opened([[N]], any P) Self +// CHECK: apply [[P_P_GETTER]]<@opened([[N]], any P) Self>([[P_RESULT_ADDR2]], [[PCOPY_ADDR_1]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: destroy_addr [[PCOPY_ADDR_1]] : $*@opened([[N]], any P) Self +// CHECK: destroy_addr [[P_RESULT]] : $*any P +// CHECK: dealloc_stack [[PCOPY_ADDR_1]] : $*@opened([[N]], any P) Self +// CHECK: dealloc_stack [[P_RESULT]] : $*any P _ = p.p -// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P to $*@opened([[N:".*"]], P) Self -// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $P -// CHECK: [[PCOPY_ADDR_1:%[0-9]+]] = alloc_stack $@opened([[N]], P) Self -// CHECK: copy_addr [[PCOPY_ADDR]] to [initialization] [[PCOPY_ADDR_1]] : $*@opened([[N]], P) Self -// CHECK: [[P_SUBSCRIPT_GETTER:%[0-9]+]] = witness_method $@opened([[N]], P) Self, #P.subscript!getter : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 -// CHECK: [[P_RESULT_ADDR:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*P, $@opened([[N]], P) Self -// CHECK: apply [[P_SUBSCRIPT_GETTER]]<@opened([[N]], P) Self>([[P_RESULT_ADDR]], [[PCOPY_ADDR_1]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 -// CHECK: destroy_addr [[PCOPY_ADDR_1]] : $*@opened([[N]], P) Self -// CHECK: destroy_addr [[P_RESULT]] : $*P -// CHECK: dealloc_stack [[PCOPY_ADDR_1]] : $*@opened([[N]], P) Self -// CHECK: dealloc_stack [[P_RESULT]] : $*P +// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P to $*@opened([[N:".*"]], any P) Self +// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $any P +// CHECK: [[PCOPY_ADDR_1:%[0-9]+]] = alloc_stack $@opened([[N]], any P) Self +// CHECK: copy_addr [[PCOPY_ADDR]] to [initialization] [[PCOPY_ADDR_1]] : $*@opened([[N]], any P) Self +// CHECK: [[P_SUBSCRIPT_GETTER:%[0-9]+]] = witness_method $@opened([[N]], any P) Self, #P.subscript!getter : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: [[P_RESULT_ADDR:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*any P, $@opened([[N]], any P) Self +// CHECK: apply [[P_SUBSCRIPT_GETTER]]<@opened([[N]], any P) Self>([[P_RESULT_ADDR]], [[PCOPY_ADDR_1]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: destroy_addr [[PCOPY_ADDR_1]] : $*@opened([[N]], any P) Self +// CHECK: destroy_addr [[P_RESULT]] : $*any P +// CHECK: dealloc_stack [[PCOPY_ADDR_1]] : $*@opened([[N]], any P) Self +// CHECK: dealloc_stack [[P_RESULT]] : $*any P _ = p[] } -// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self28testExistentialDispatchClass{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed CP) -> () +// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self28testExistentialDispatchClass{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed any CP) -> () func testExistentialDispatchClass(cp: CP) { -// CHECK: bb0([[CP:%[0-9]+]] : @guaranteed $CP): -// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $CP to $@opened([[N:".*"]], CP) Self -// CHECK: [[CP_F:%[0-9]+]] = witness_method $@opened([[N]], CP) Self, #CP.f : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: [[CP_F_RESULT:%[0-9]+]] = apply [[CP_F]]<@opened([[N]], CP) Self>([[CP_ADDR]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[CP_F_RESULT]] : $@opened([[N]], CP) Self : $@opened([[N]], CP) Self, $CP +// CHECK: bb0([[CP:%[0-9]+]] : @guaranteed $any CP): +// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $any CP to $@opened([[N:".*"]], any CP) Self +// CHECK: [[CP_F:%[0-9]+]] = witness_method $@opened([[N]], any CP) Self, #CP.f : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: [[CP_F_RESULT:%[0-9]+]] = apply [[CP_F]]<@opened([[N]], any CP) Self>([[CP_ADDR]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[CP_F_RESULT]] : $@opened([[N]], any CP) Self : $@opened([[N]], any CP) Self, $any CP // CHECK: destroy_value [[RESULT_EXISTENTIAL]] _ = cp.f() -// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $CP to $@opened([[N:".*"]], CP) Self -// CHECK: [[CP_ADDR_1:%[0-9]+]] = copy_value [[CP_ADDR]] : $@opened([[N]], CP) Self -// CHECK: [[CP_BORROWED:%[0-9]+]] = begin_borrow [[CP_ADDR_1]] : $@opened([[N]], CP) Self -// CHECK: [[CP_P_GETTER:%[0-9]+]] = witness_method $@opened([[N]], CP) Self, #CP.p!getter : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: [[APPLY_RESULT:%[0-9]+]] = apply [[CP_P_GETTER]]<@opened([[N]], CP) Self>([[CP_BORROWED]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: end_borrow [[CP_BORROWED]] : $@opened([[N]], CP) Self -// CHECK: destroy_value [[CP_ADDR_1]] : $@opened([[N]], CP) Self -// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[APPLY_RESULT]] : $@opened([[N]], CP) Self : $@opened([[N]], CP) Self, $CP -// CHECK: destroy_value [[RESULT_EXISTENTIAL]] : $CP +// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $any CP to $@opened([[N:".*"]], any CP) Self +// CHECK: [[CP_ADDR_1:%[0-9]+]] = copy_value [[CP_ADDR]] : $@opened([[N]], any CP) Self +// CHECK: [[CP_BORROWED:%[0-9]+]] = begin_borrow [[CP_ADDR_1]] : $@opened([[N]], any CP) Self +// CHECK: [[CP_P_GETTER:%[0-9]+]] = witness_method $@opened([[N]], any CP) Self, #CP.p!getter : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: [[APPLY_RESULT:%[0-9]+]] = apply [[CP_P_GETTER]]<@opened([[N]], any CP) Self>([[CP_BORROWED]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: end_borrow [[CP_BORROWED]] : $@opened([[N]], any CP) Self +// CHECK: destroy_value [[CP_ADDR_1]] : $@opened([[N]], any CP) Self +// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[APPLY_RESULT]] : $@opened([[N]], any CP) Self : $@opened([[N]], any CP) Self, $any CP +// CHECK: destroy_value [[RESULT_EXISTENTIAL]] : $any CP _ = cp.p -// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $CP to $@opened([[N:".*"]], CP) Self -// CHECK: [[CP_ADDR_1:%[0-9]+]] = copy_value [[CP_ADDR]] : $@opened([[N]], CP) Self -// CHECK: [[CP_BORROWED:%[0-9]+]] = begin_borrow [[CP_ADDR_1]] : $@opened([[N]], CP) Self -// CHECK: [[CP_SUBSCRIPT_GETTER:%[0-9]+]] = witness_method $@opened([[N]], CP) Self, #CP.subscript!getter : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: [[APPLY_RESULT:%[0-9]+]] = apply [[CP_SUBSCRIPT_GETTER]]<@opened([[N]], CP) Self>([[CP_BORROWED]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: end_borrow [[CP_BORROWED]] : $@opened([[N]], CP) Self -// CHECK: destroy_value [[CP_ADDR_1]] : $@opened([[N]], CP) Self -// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[APPLY_RESULT]] : $@opened([[N]], CP) Self : $@opened([[N]], CP) Self, $CP -// CHECK: destroy_value [[RESULT_EXISTENTIAL]] : $CP +// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $any CP to $@opened([[N:".*"]], any CP) Self +// CHECK: [[CP_ADDR_1:%[0-9]+]] = copy_value [[CP_ADDR]] : $@opened([[N]], any CP) Self +// CHECK: [[CP_BORROWED:%[0-9]+]] = begin_borrow [[CP_ADDR_1]] : $@opened([[N]], any CP) Self +// CHECK: [[CP_SUBSCRIPT_GETTER:%[0-9]+]] = witness_method $@opened([[N]], any CP) Self, #CP.subscript!getter : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: [[APPLY_RESULT:%[0-9]+]] = apply [[CP_SUBSCRIPT_GETTER]]<@opened([[N]], any CP) Self>([[CP_BORROWED]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: end_borrow [[CP_BORROWED]] : $@opened([[N]], any CP) Self +// CHECK: destroy_value [[CP_ADDR_1]] : $@opened([[N]], any CP) Self +// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[APPLY_RESULT]] : $@opened([[N]], any CP) Self : $@opened([[N]], any CP) Self, $any CP +// CHECK: destroy_value [[RESULT_EXISTENTIAL]] : $any CP _ = cp[] } @@ -348,7 +348,7 @@ class FactoryFactory { // CHECK: [[DYNAMIC_SELF:%.*]] = unchecked_trivial_bit_cast %0 : $@thick FactoryFactory.Type to $@thick @dynamic_self FactoryFactory.Type // CHECK: [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self FactoryFactory.Type.Type, [[DYNAMIC_SELF]] : $@thick @dynamic_self FactoryFactory.Type - // CHECK: [[ANY:%.*]] = init_existential_metatype [[METATYPE]] : $@thick @dynamic_self FactoryFactory.Type.Type, $@thick Any.Type + // CHECK: [[ANY:%.*]] = init_existential_metatype [[METATYPE]] : $@thick @dynamic_self FactoryFactory.Type.Type, $@thick any Any.Type let _: Any.Type = type(of: self) while true {} diff --git a/test/SILGen/effectful_properties.swift b/test/SILGen/effectful_properties.swift index c3848ed98aa09..4eb5e9bd43b5b 100644 --- a/test/SILGen/effectful_properties.swift +++ b/test/SILGen/effectful_properties.swift @@ -1,7 +1,7 @@ // RUN: %target-swift-frontend -emit-silgen -disable-availability-checking %s -module-name accessors -swift-version 5 | %FileCheck --enable-var-scope %s class C { - // CHECK-DAG: sil hidden [ossa] @$s9accessors1CC16prop_asyncThrowsSivg : $@convention(method) @async (@guaranteed C) -> (Int, @error Error) { + // CHECK-DAG: sil hidden [ossa] @$s9accessors1CC16prop_asyncThrowsSivg : $@convention(method) @async (@guaranteed C) -> (Int, @error any Error) { var prop_asyncThrows : Int { get async throws { 0 } } @@ -9,7 +9,7 @@ class C { var prop_async : Int { get async { 1 } } - // CHECK-DAG: sil hidden [ossa] @$s9accessors1CC11prop_throwsSivg : $@convention(method) (@guaranteed C) -> (Int, @error Error) { + // CHECK-DAG: sil hidden [ossa] @$s9accessors1CC11prop_throwsSivg : $@convention(method) (@guaranteed C) -> (Int, @error any Error) { var prop_throws : Int { get throws { 2 } } @@ -20,14 +20,14 @@ struct S { subscript(_ s : Int) -> Int { get async { 0 } } - // CHECK-DAG: sil hidden [ossa] @$s9accessors1SVySiSdcig : $@convention(method) (Double, S) -> (Int, @error Error) { + // CHECK-DAG: sil hidden [ossa] @$s9accessors1SVySiSdcig : $@convention(method) (Double, S) -> (Int, @error any Error) { subscript(_ s : Double) -> Int { get throws { 0 } } } enum E { - // CHECK-DAG: sil hidden [ossa] @$s9accessors1EOyS2icig : $@convention(method) @async (Int, E) -> (Int, @error Error) { + // CHECK-DAG: sil hidden [ossa] @$s9accessors1EOyS2icig : $@convention(method) @async (Int, E) -> (Int, @error any Error) { subscript(_ e : Int) -> Int { get async throws { 0 } } diff --git a/test/SILGen/enum.swift b/test/SILGen/enum.swift index 5a9ca073cdb66..e265d653f1d0c 100644 --- a/test/SILGen/enum.swift +++ b/test/SILGen/enum.swift @@ -63,16 +63,16 @@ func AddressOnly_cases(_ s: S) { _ = AddressOnly.nought // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type - // CHECK-NEXT: [[P_BUF:%.*]] = alloc_stack $P + // CHECK-NEXT: [[P_BUF:%.*]] = alloc_stack $any P // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[P_BUF]] // CHECK-NEXT: store %0 to [trivial] [[PAYLOAD_ADDR]] // CHECK-NEXT: [[MERE:%.*]] = alloc_stack $AddressOnly // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[MERE]] - // CHECK-NEXT: copy_addr [take] [[P_BUF]] to [initialization] [[PAYLOAD]] : $*P + // CHECK-NEXT: copy_addr [take] [[P_BUF]] to [initialization] [[PAYLOAD]] : $*any P // CHECK-NEXT: inject_enum_addr [[MERE]] // CHECK-NEXT: destroy_addr [[MERE]] // CHECK-NEXT: dealloc_stack [[MERE]] - // CHECK-NEXT: dealloc_stack [[P_BUF]] : $*P + // CHECK-NEXT: dealloc_stack [[P_BUF]] : $*any P _ = AddressOnly.mere(s) // Address-only enum vs loadable payload diff --git a/test/SILGen/errors.swift b/test/SILGen/errors.swift index c17797bceec6e..95219eefc4cde 100644 --- a/test/SILGen/errors.swift +++ b/test/SILGen/errors.swift @@ -14,7 +14,7 @@ enum HomeworkError : Error { func someValidPointer() -> UnsafePointer { fatalError() } func someValidPointer() -> UnsafeMutablePointer { fatalError() } -// CHECK: sil hidden [ossa] @$s6errors10make_a_cat{{.*}}F : $@convention(thin) () -> (@owned Cat, @error Error) { +// CHECK: sil hidden [ossa] @$s6errors10make_a_cat{{.*}}F : $@convention(thin) () -> (@owned Cat, @error any Error) { // CHECK: [[T1:%.*]] = metatype $@thick Cat.Type // CHECK: [[T0:%.*]] = function_ref @$s6errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat // CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]]) @@ -23,11 +23,11 @@ func make_a_cat() throws -> Cat { return Cat() } -// CHECK: sil hidden [ossa] @$s6errors15dont_make_a_cat{{.*}}F : $@convention(thin) () -> (@owned Cat, @error Error) { +// CHECK: sil hidden [ossa] @$s6errors15dont_make_a_cat{{.*}}F : $@convention(thin) () -> (@owned Cat, @error any Error) { // CHECK: [[T0:%.*]] = metatype $@thin HomeworkError.Type // CHECK-NEXT: [[T1:%.*]] = enum $HomeworkError, #HomeworkError.TooHard!enumelt -// CHECK-NEXT: [[BOX:%.*]] = alloc_existential_box $Error, $HomeworkError -// CHECK-NEXT: [[ADDR:%.*]] = project_existential_box $HomeworkError in [[BOX]] : $Error +// CHECK-NEXT: [[BOX:%.*]] = alloc_existential_box $any Error, $HomeworkError +// CHECK-NEXT: [[ADDR:%.*]] = project_existential_box $HomeworkError in [[BOX]] : $any Error // CHECK-NEXT: store [[BOX]] to [init] [[BOXBUF:%.*]] : // CHECK-NEXT: store [[T1]] to [init] [[ADDR]] // CHECK-NEXT: [[BOX2:%.*]] = load [take] [[BOXBUF]] @@ -38,11 +38,11 @@ func dont_make_a_cat() throws -> Cat { throw HomeworkError.TooHard } -// CHECK: sil hidden [ossa] @$s6errors11dont_return{{.*}}F : $@convention(thin) (@in_guaranteed T) -> (@out T, @error Error) { +// CHECK: sil hidden [ossa] @$s6errors11dont_return{{.*}}F : $@convention(thin) (@in_guaranteed T) -> (@out T, @error any Error) { // CHECK: [[T0:%.*]] = metatype $@thin HomeworkError.Type // CHECK-NEXT: [[T1:%.*]] = enum $HomeworkError, #HomeworkError.TooMuch!enumelt -// CHECK-NEXT: [[BOX:%.*]] = alloc_existential_box $Error, $HomeworkError -// CHECK-NEXT: [[ADDR:%.*]] = project_existential_box $HomeworkError in [[BOX]] : $Error +// CHECK-NEXT: [[BOX:%.*]] = alloc_existential_box $any Error, $HomeworkError +// CHECK-NEXT: [[ADDR:%.*]] = project_existential_box $HomeworkError in [[BOX]] : $any Error // CHECK-NEXT: store [[BOX]] to [init] [[BOXBUF:%.*]] : // CHECK-NEXT: store [[T1]] to [init] [[ADDR]] // CHECK-NEXT: [[BOX2:%.*]] = load [take] [[BOXBUF]] @@ -62,15 +62,15 @@ func dont_return(_ argument: T) throws -> T { // In the true case, call make_a_cat(). // CHECK: [[FLAG_TRUE]]: -// CHECK: [[MAC_FN:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error Error) -// CHECK-NEXT: try_apply [[MAC_FN]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[MAC_NORMAL:bb[0-9]+]], error [[MAC_ERROR:bb[0-9]+]] +// CHECK: [[MAC_FN:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error any Error) +// CHECK-NEXT: try_apply [[MAC_FN]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[MAC_NORMAL:bb[0-9]+]], error [[MAC_ERROR:bb[0-9]+]] // CHECK: [[MAC_NORMAL]]([[T0:%.*]] : @owned $Cat): // CHECK-NEXT: br [[TERNARY_CONT:bb[0-9]+]]([[T0]] : $Cat) // In the false case, call dont_make_a_cat(). // CHECK: [[FLAG_FALSE]]: -// CHECK: [[DMAC_FN:%.*]] = function_ref @$s6errors15dont_make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error Error) -// CHECK-NEXT: try_apply [[DMAC_FN]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[DMAC_NORMAL:bb[0-9]+]], error [[DMAC_ERROR:bb[0-9]+]] +// CHECK: [[DMAC_FN:%.*]] = function_ref @$s6errors15dont_make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error any Error) +// CHECK-NEXT: try_apply [[DMAC_FN]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[DMAC_NORMAL:bb[0-9]+]], error [[DMAC_ERROR:bb[0-9]+]] // CHECK: [[DMAC_NORMAL]]([[T0:%.*]] : @owned $Cat): // CHECK-NEXT: br [[TERNARY_CONT]]([[T0]] : $Cat) @@ -79,7 +79,7 @@ func dont_return(_ argument: T) throws -> T { // CHECK-NEXT: [[ARG_TEMP:%.*]] = alloc_stack $Cat // CHECK-NEXT: store [[T0]] to [init] [[ARG_TEMP]] // CHECK: [[DR_FN:%.*]] = function_ref @$s6errors11dont_return{{.*}} : -// CHECK-NEXT: try_apply [[DR_FN]]([[RET_TEMP]], [[ARG_TEMP]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error Error), normal [[DR_NORMAL:bb[0-9]+]], error [[DR_ERROR:bb[0-9]+]] +// CHECK-NEXT: try_apply [[DR_FN]]([[RET_TEMP]], [[ARG_TEMP]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error any Error), normal [[DR_NORMAL:bb[0-9]+]], error [[DR_ERROR:bb[0-9]+]] // CHECK: [[DR_NORMAL]]({{%.*}} : $()): // CHECK-NEXT: destroy_addr [[ARG_TEMP]] // CHECK-NEXT: dealloc_stack [[ARG_TEMP]] @@ -92,13 +92,13 @@ func dont_return(_ argument: T) throws -> T { // CHECK-NEXT: return [[T0]] : $Cat // Catch dispatch block. -// CHECK: [[CATCH:bb[0-9]+]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[CATCH:bb[0-9]+]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] -// CHECK-NEXT: [[SRC_TEMP:%.*]] = alloc_stack $Error +// CHECK-NEXT: [[SRC_TEMP:%.*]] = alloc_stack $any Error // CHECK-NEXT: [[COPIED_BORROWED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]] // CHECK-NEXT: store [[COPIED_BORROWED_ERROR]] to [init] [[SRC_TEMP]] // CHECK-NEXT: [[DEST_TEMP:%.*]] = alloc_stack $HomeworkError -// CHECK-NEXT: checked_cast_addr_br copy_on_success Error in [[SRC_TEMP]] : $*Error to HomeworkError in [[DEST_TEMP]] : $*HomeworkError, [[IS_HWE:bb[0-9]+]], [[NOT_HWE:bb[0-9]+]] +// CHECK-NEXT: checked_cast_addr_br copy_on_success any Error in [[SRC_TEMP]] : $*any Error to HomeworkError in [[DEST_TEMP]] : $*HomeworkError, [[IS_HWE:bb[0-9]+]], [[NOT_HWE:bb[0-9]+]] // Catch HomeworkError. // CHECK: [[IS_HWE]]: @@ -140,21 +140,21 @@ func dont_return(_ argument: T) throws -> T { // CHECK: [[T0:%.*]] = function_ref @$s6errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat // CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]]) // CHECK-NEXT: end_borrow [[BORROWED_ERROR]] -// CHECK-NEXT: destroy_value [[ERROR]] : $Error +// CHECK-NEXT: destroy_value [[ERROR]] : $any Error // CHECK-NEXT: br [[RETURN]]([[T2]] : $Cat) // Landing pad. -// CHECK: [[MAC_ERROR]]([[T0:%.*]] : @owned $Error): +// CHECK: [[MAC_ERROR]]([[T0:%.*]] : @owned $any Error): // CHECK-NEXT: dealloc_stack [[RET_TEMP]] -// CHECK-NEXT: br [[CATCH]]([[T0]] : $Error) -// CHECK: [[DMAC_ERROR]]([[T0:%.*]] : @owned $Error): +// CHECK-NEXT: br [[CATCH]]([[T0]] : $any Error) +// CHECK: [[DMAC_ERROR]]([[T0:%.*]] : @owned $any Error): // CHECK-NEXT: dealloc_stack [[RET_TEMP]] -// CHECK-NEXT: br [[CATCH]]([[T0]] : $Error) -// CHECK: [[DR_ERROR]]([[T0:%.*]] : @owned $Error): +// CHECK-NEXT: br [[CATCH]]([[T0]] : $any Error) +// CHECK: [[DR_ERROR]]([[T0:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_addr [[CAT:%.*]] : // CHECK-NEXT: dealloc_stack [[CAT]] // CHECK-NEXT: dealloc_stack -// CHECK-NEXT: br [[CATCH]]([[T0]] : $Error) +// CHECK-NEXT: br [[CATCH]]([[T0]] : $any Error) func all_together_now(_ flag: Bool) -> Cat { do { return try dont_return(flag ? make_a_cat() : dont_make_a_cat()) @@ -168,16 +168,16 @@ func all_together_now(_ flag: Bool) -> Cat { // Make sure that if we catch an error in a throwing function we borrow the // error and only consume the error in the rethrow block. // -// CHECK-LABEL: sil hidden [ossa] @$s6errors20all_together_now_twoyAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional, @error Error) { +// CHECK-LABEL: sil hidden [ossa] @$s6errors20all_together_now_twoyAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional, @error any Error) { // CHECK: bb0( // CHECK-NOT: bb1 // CHECK: try_apply {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // -// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] // CHECK: [[COPIED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]] -// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*Error -// CHECK: checked_cast_addr_br copy_on_success Error in [[CAST_INPUT_MEM]] : $*Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]], +// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*any Error +// CHECK: checked_cast_addr_br copy_on_success any Error in [[CAST_INPUT_MEM]] : $*any Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]], // // CHECK: [[CAST_YES_BB]]: // CHECK: [[SUBERROR:%.*]] = load [take] [[CAST_OUTPUT_MEM]] @@ -186,13 +186,13 @@ func all_together_now(_ flag: Bool) -> Cat { // CHECK: [[SWITCH_MATCH_FAIL_BB]]([[SUBERROR:%.*]] : @owned $HomeworkError): // CHECK: destroy_value [[SUBERROR]] // CHECK: end_borrow [[BORROWED_ERROR]] -// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $Error) +// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $any Error) // // CHECK: [[CAST_NO_BB]]: // CHECK: end_borrow [[BORROWED_ERROR]] -// CHECK: br [[RETHROW_BB]]([[ERROR]] : $Error) +// CHECK: br [[RETHROW_BB]]([[ERROR]] : $any Error) // -// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $Error): +// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $any Error): // CHECK: throw [[ERROR_FOR_RETHROW]] // CHECK: } // end sil function '$s6errors20all_together_now_twoyAA3CatCSgSbKF' func all_together_now_two(_ flag: Bool) throws -> Cat? { @@ -205,16 +205,16 @@ func all_together_now_two(_ flag: Bool) throws -> Cat? { // Same as the previous test, but with multiple cases instead of just one. // -// CHECK-LABEL: sil hidden [ossa] @$s6errors22all_together_now_threeyAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional, @error Error) { +// CHECK-LABEL: sil hidden [ossa] @$s6errors22all_together_now_threeyAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional, @error any Error) { // CHECK: bb0( // CHECK-NOT: bb1 // CHECK: try_apply {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // -// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] // CHECK: [[COPIED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]] -// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*Error -// CHECK: checked_cast_addr_br copy_on_success Error in [[CAST_INPUT_MEM]] : $*Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]], +// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*any Error +// CHECK: checked_cast_addr_br copy_on_success any Error in [[CAST_INPUT_MEM]] : $*any Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]], // // CHECK: [[CAST_YES_BB]]: // CHECK: [[SUBERROR:%.*]] = load [take] [[CAST_OUTPUT_MEM]] @@ -223,13 +223,13 @@ func all_together_now_two(_ flag: Bool) throws -> Cat? { // CHECK: [[SWITCH_MATCH_FAIL_BB]]([[SUBERROR:%.*]] : @owned $HomeworkError): // CHECK: destroy_value [[SUBERROR]] // CHECK: end_borrow [[BORROWED_ERROR]] -// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $Error) +// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $any Error) // // CHECK: [[CAST_NO_BB]]: // CHECK: end_borrow [[BORROWED_ERROR]] -// CHECK: br [[RETHROW_BB]]([[ERROR]] : $Error) +// CHECK: br [[RETHROW_BB]]([[ERROR]] : $any Error) // -// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $Error): +// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $any Error): // CHECK: throw [[ERROR_FOR_RETHROW]] // CHECK: } // end sil function '$s6errors22all_together_now_threeyAA3CatCSgSbKF' func all_together_now_three(_ flag: Bool) throws -> Cat? { @@ -244,16 +244,16 @@ func all_together_now_three(_ flag: Bool) throws -> Cat? { // Same as the previous test, but with a multi-pattern catch instead of two separate ones. // -// CHECK-LABEL: sil hidden [ossa] @$s6errors21all_together_now_fouryAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional, @error Error) { +// CHECK-LABEL: sil hidden [ossa] @$s6errors21all_together_now_fouryAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional, @error any Error) { // CHECK: bb0( // CHECK-NOT: bb1 // CHECK: try_apply {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // -// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] // CHECK: [[COPIED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]] -// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*Error -// CHECK: checked_cast_addr_br copy_on_success Error in [[CAST_INPUT_MEM]] : $*Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]], +// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*any Error +// CHECK: checked_cast_addr_br copy_on_success any Error in [[CAST_INPUT_MEM]] : $*any Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]], // // CHECK: [[CAST_YES_BB]]: // CHECK: [[SUBERROR:%.*]] = load [take] [[CAST_OUTPUT_MEM]] @@ -273,13 +273,13 @@ func all_together_now_three(_ flag: Bool) throws -> Cat? { // CHECK: [[SWITCH_MATCH_FAIL_BB]]([[SUBERROR:%.*]] : @owned $HomeworkError): // CHECK: destroy_value [[SUBERROR]] // CHECK: end_borrow [[BORROWED_ERROR]] -// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $Error) +// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $any Error) // // CHECK: [[CAST_NO_BB]]: // CHECK: end_borrow [[BORROWED_ERROR]] -// CHECK: br [[RETHROW_BB]]([[ERROR]] : $Error) +// CHECK: br [[RETHROW_BB]]([[ERROR]] : $any Error) // -// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $Error): +// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $any Error): // CHECK: throw [[ERROR_FOR_RETHROW]] // CHECK: } // end sil function '$s6errors21all_together_now_fouryAA3CatCSgSbKF' func all_together_now_four(_ flag: Bool) throws -> Cat? { @@ -292,20 +292,20 @@ func all_together_now_four(_ flag: Bool) throws -> Cat? { // A multi-pattern catch with associated value bindings. // -// CHECK-LABEL: sil hidden [ossa] @$s6errors21all_together_now_fiveyAA3CatCSbKF : $@convention(thin) (Bool) -> (@owned Cat, @error Error) { +// CHECK-LABEL: sil hidden [ossa] @$s6errors21all_together_now_fiveyAA3CatCSbKF : $@convention(thin) (Bool) -> (@owned Cat, @error any Error) { // Return block. // CHECK: [[RETURN:bb[0-9]+]]([[RETVAL:%.*]] : @owned $Cat): // CHECK-NEXT: return [[RETVAL]] : $Cat // Catch dispatch block. -// CHECK: [[CATCH:bb[0-9]+]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[CATCH:bb[0-9]+]]([[ERROR:%.*]] : @owned $any Error): // CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] -// CHECK-NEXT: [[SRC_TEMP:%.*]] = alloc_stack $Error +// CHECK-NEXT: [[SRC_TEMP:%.*]] = alloc_stack $any Error // CHECK-NEXT: [[COPIED_BORROWED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]] // CHECK-NEXT: store [[COPIED_BORROWED_ERROR]] to [init] [[SRC_TEMP]] // CHECK-NEXT: [[DEST_TEMP:%.*]] = alloc_stack $HomeworkError -// CHECK-NEXT: checked_cast_addr_br copy_on_success Error in [[SRC_TEMP]] : $*Error to HomeworkError in [[DEST_TEMP]] : $*HomeworkError, [[IS_HWE:bb[0-9]+]], [[NOT_HWE:bb[0-9]+]] +// CHECK-NEXT: checked_cast_addr_br copy_on_success any Error in [[SRC_TEMP]] : $*any Error to HomeworkError in [[DEST_TEMP]] : $*HomeworkError, [[IS_HWE:bb[0-9]+]], [[NOT_HWE:bb[0-9]+]] // Catch HomeworkError. // CHECK: [[IS_HWE]]: @@ -342,7 +342,7 @@ func all_together_now_four(_ flag: Bool) throws -> Cat? { // CHECK-NEXT: [[COPIED_CAT:%.*]] = copy_value [[BORROWED_CAT]] : $Cat // CHECK-NEXT: end_borrow [[BORROWED_CAT]] : $Cat // CHECK-NEXT: destroy_value [[CAT]] : $Cat -// CHECK-NEXT: destroy_value [[ERROR]] : $Error +// CHECK-NEXT: destroy_value [[ERROR]] : $any Error // CHECK-NEXT: br [[RETURN]]([[COPIED_CAT]] : $Cat) // Catch other HomeworkErrors. @@ -363,8 +363,8 @@ func all_together_now_four(_ flag: Bool) throws -> Cat? { // CHECK-NEXT: br [[RETHROW]] // Rethrow -// CHECK: [[RETHROW]]([[ERROR:%.*]] : @owned $Error): -// CHECK-NEXT: throw [[ERROR]] : $Error +// CHECK: [[RETHROW]]([[ERROR:%.*]] : @owned $any Error): +// CHECK-NEXT: throw [[ERROR]] : $any Error func all_together_now_five(_ flag: Bool) throws -> Cat { do { return try dont_return(Cat()) @@ -394,16 +394,16 @@ class HasThrowingInit { } } -// CHECK-LABEL: sil hidden [exact_self_class] [ossa] @$s6errors15HasThrowingInit{{.*}} : $@convention(method) (Int, @thick HasThrowingInit.Type) -> (@owned HasThrowingInit, @error Error) +// CHECK-LABEL: sil hidden [exact_self_class] [ossa] @$s6errors15HasThrowingInit{{.*}} : $@convention(method) (Int, @thick HasThrowingInit.Type) -> (@owned HasThrowingInit, @error any Error) // CHECK: [[SELF:%.*]] = alloc_ref $HasThrowingInit -// CHECK: [[T0:%.*]] = function_ref @$s6errors15HasThrowingInit{{.*}}c : $@convention(method) (Int, @owned HasThrowingInit) -> (@owned HasThrowingInit, @error Error) -// CHECK-NEXT: try_apply [[T0]](%0, [[SELF]]) : $@convention(method) (Int, @owned HasThrowingInit) -> (@owned HasThrowingInit, @error Error), normal bb1, error bb2 +// CHECK: [[T0:%.*]] = function_ref @$s6errors15HasThrowingInit{{.*}}c : $@convention(method) (Int, @owned HasThrowingInit) -> (@owned HasThrowingInit, @error any Error) +// CHECK-NEXT: try_apply [[T0]](%0, [[SELF]]) : $@convention(method) (Int, @owned HasThrowingInit) -> (@owned HasThrowingInit, @error any Error), normal bb1, error bb2 // CHECK: bb1([[SELF:%.*]] : @owned $HasThrowingInit): // CHECK-NEXT: return [[SELF]] -// CHECK: bb2([[ERROR:%.*]] : @owned $Error): +// CHECK: bb2([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: throw [[ERROR]] -// CHECK-LABEL: sil hidden [ossa] @$s6errors15HasThrowingInit{{.*}} : $@convention(method) (Int, @owned HasThrowingInit) -> (@owned HasThrowingInit, @error Error) { +// CHECK-LABEL: sil hidden [ossa] @$s6errors15HasThrowingInit{{.*}} : $@convention(method) (Int, @owned HasThrowingInit) -> (@owned HasThrowingInit, @error any Error) { // CHECK: [[T0:%.*]] = mark_uninitialized [rootself] %1 : $HasThrowingInit // CHECK-NEXT: [[BORROWED_T0:%.*]] = begin_borrow [[T0]] // CHECK-NEXT: [[T1:%.*]] = ref_element_addr [[BORROWED_T0]] : $HasThrowingInit @@ -445,28 +445,28 @@ protocol Doomed { // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s6errors12DoomedStructVAA0B0A2aDP5checkyyKFTW : // CHECK: [[SELF:%.*]] = load [trivial] %0 : $*DoomedStruct -// CHECK: [[T0:%.*]] = function_ref @$s6errors12DoomedStructV5checkyyKF : $@convention(method) (DoomedStruct) -> @error Error +// CHECK: [[T0:%.*]] = function_ref @$s6errors12DoomedStructV5checkyyKF : $@convention(method) (DoomedStruct) -> @error any Error // CHECK-NEXT: try_apply [[T0]]([[SELF]]) // CHECK: bb1([[T0:%.*]] : $()): // CHECK: [[T0:%.*]] = tuple () // CHECK: return [[T0]] : $() -// CHECK: bb2([[T0:%.*]] : @owned $Error): -// CHECK: throw [[T0]] : $Error +// CHECK: bb2([[T0:%.*]] : @owned $any Error): +// CHECK: throw [[T0]] : $any Error struct DoomedStruct : Doomed { func check() throws {} } // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s6errors11DoomedClassCAA0B0A2aDP5checkyyKFTW : // CHECK: [[BORROWED_SELF:%.*]] = load_borrow %0 -// CHECK: [[T0:%.*]] = class_method [[BORROWED_SELF]] : $DoomedClass, #DoomedClass.check : (DoomedClass) -> () throws -> (), $@convention(method) (@guaranteed DoomedClass) -> @error Error +// CHECK: [[T0:%.*]] = class_method [[BORROWED_SELF]] : $DoomedClass, #DoomedClass.check : (DoomedClass) -> () throws -> (), $@convention(method) (@guaranteed DoomedClass) -> @error any Error // CHECK-NEXT: try_apply [[T0]]([[BORROWED_SELF]]) // CHECK: bb1([[T0:%.*]] : $()): // CHECK: [[T0:%.*]] = tuple () // CHECK: end_borrow [[BORROWED_SELF]] // CHECK: return [[T0]] : $() -// CHECK: bb2([[T0:%.*]] : @owned $Error): +// CHECK: bb2([[T0:%.*]] : @owned $any Error): // CHECK: end_borrow [[BORROWED_SELF]] -// CHECK: throw [[T0]] : $Error +// CHECK: throw [[T0]] : $any Error class DoomedClass : Doomed { func check() throws {} } @@ -497,15 +497,15 @@ func create(_ fn: () throws -> T) throws -> T { func testThunk(_ fn: () throws -> Int) throws -> Int { return try create(fn) } -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$sSis5Error_pIgdzo_SisAA_pIegrzo_TR : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (@out Int, @error Error) -// CHECK: bb0(%0 : $*Int, %1 : $@noescape @callee_guaranteed () -> (Int, @error Error)): +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$sSis5Error_pIgdzo_SisAA_pIegrzo_TR : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (@out Int, @error any Error) +// CHECK: bb0(%0 : $*Int, %1 : $@noescape @callee_guaranteed () -> (Int, @error any Error)): // CHECK: try_apply %1() // CHECK: bb1([[T0:%.*]] : $Int): // CHECK: store [[T0]] to [trivial] %0 : $*Int // CHECK: [[T0:%.*]] = tuple () // CHECK: return [[T0]] -// CHECK: bb2([[T0:%.*]] : @owned $Error): -// CHECK: throw [[T0]] : $Error +// CHECK: bb2([[T0:%.*]] : @owned $any Error): +// CHECK: throw [[T0]] : $any Error func createInt(_ fn: () -> Int) throws {} func testForceTry(_ fn: () -> Int) { @@ -513,7 +513,7 @@ func testForceTry(_ fn: () -> Int) { } // CHECK-LABEL: sil hidden [ossa] @$s6errors12testForceTryyySiyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> () // CHECK: bb0([[ARG:%.*]] : $@noescape @callee_guaranteed () -> Int): -// CHECK: [[FUNC:%.*]] = function_ref @$s6errors9createIntyySiyXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @$s6errors9createIntyySiyXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @error any Error // CHECK: try_apply [[FUNC]]([[ARG]]) // CHECK: return // CHECK: function_ref @swift_unexpectedError @@ -526,24 +526,24 @@ func testForceTryMultiple() { // CHECK-LABEL: sil hidden [ossa] @$s6errors20testForceTryMultipleyyF // CHECK-NEXT: bb0: // CHECK: [[FN_1:%.+]] = function_ref @$s6errors10make_a_catAA3CatCyKF -// CHECK-NEXT: try_apply [[FN_1]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[SUCCESS_1:[^ ]+]], error [[CLEANUPS_1:[^ ]+]], +// CHECK-NEXT: try_apply [[FN_1]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[SUCCESS_1:[^ ]+]], error [[CLEANUPS_1:[^ ]+]], // CHECK: [[SUCCESS_1]]([[VALUE_1:%.+]] : @owned $Cat) // CHECK: [[FN_2:%.+]] = function_ref @$s6errors10make_a_catAA3CatCyKF -// CHECK-NEXT: try_apply [[FN_2]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[SUCCESS_2:[^ ]+]], error [[CLEANUPS_2:[^ ]+]], +// CHECK-NEXT: try_apply [[FN_2]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[SUCCESS_2:[^ ]+]], error [[CLEANUPS_2:[^ ]+]], // CHECK: [[SUCCESS_2]]([[VALUE_2:%.+]] : @owned $Cat) // CHECK-NEXT: destroy_value [[VALUE_2]] : $Cat // CHECK-NEXT: destroy_value [[VALUE_1]] : $Cat // CHECK-NEXT: [[VOID:%.+]] = tuple () // CHECK-NEXT: return [[VOID]] : $() -// CHECK: [[FAILURE:.+]]([[ERROR:%.+]] : @owned $Error): +// CHECK: [[FAILURE:.+]]([[ERROR:%.+]] : @owned $any Error): // CHECK: [[UNEXPECTED_ERROR:%.+]] = function_ref @swift_unexpectedError // CHECK-NEXT: apply [[UNEXPECTED_ERROR]]([[ERROR]] // CHECK-NEXT: unreachable -// CHECK: [[CLEANUPS_1]]([[ERROR:%.+]] : @owned $Error): -// CHECK-NEXT: br [[FAILURE]]([[ERROR]] : $Error) -// CHECK: [[CLEANUPS_2]]([[ERROR:%.+]] : @owned $Error): +// CHECK: [[CLEANUPS_1]]([[ERROR:%.+]] : @owned $any Error): +// CHECK-NEXT: br [[FAILURE]]([[ERROR]] : $any Error) +// CHECK: [[CLEANUPS_2]]([[ERROR:%.+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[VALUE_1]] : $Cat -// CHECK-NEXT: br [[FAILURE]]([[ERROR]] : $Error) +// CHECK-NEXT: br [[FAILURE]]([[ERROR]] : $any Error) // CHECK: } // end sil function '$s6errors20testForceTryMultipleyyF' // Make sure we balance scopes correctly inside a switch. @@ -566,14 +566,14 @@ func feedCat() throws -> Int { return 1 } } -// CHECK-LABEL: sil hidden [ossa] @$s6errors7feedCatSiyKF : $@convention(thin) () -> (Int, @error Error) -// CHECK: debug_value undef : $Error, var, name "$error", argno 1 -// CHECK: %1 = function_ref @$s6errors13preferredFoodAA03CatC0OyKF : $@convention(thin) () -> (CatFood, @error Error) -// CHECK: try_apply %1() : $@convention(thin) () -> (CatFood, @error Error), normal bb1, error bb5 +// CHECK-LABEL: sil hidden [ossa] @$s6errors7feedCatSiyKF : $@convention(thin) () -> (Int, @error any Error) +// CHECK: debug_value undef : $any Error, var, name "$error", argno 1 +// CHECK: %1 = function_ref @$s6errors13preferredFoodAA03CatC0OyKF : $@convention(thin) () -> (CatFood, @error any Error) +// CHECK: try_apply %1() : $@convention(thin) () -> (CatFood, @error any Error), normal bb1, error bb5 // CHECK: bb1([[VAL:%.*]] : $CatFood): // CHECK: switch_enum [[VAL]] : $CatFood, case #CatFood.Canned!enumelt: bb2, case #CatFood.Dry!enumelt: bb3 -// CHECK: bb5([[ERROR:%.*]] : @owned $Error) -// CHECK: throw [[ERROR]] : $Error +// CHECK: bb5([[ERROR:%.*]] : @owned $any Error) +// CHECK: throw [[ERROR]] : $any Error // Throwing statements inside cases. func getHungryCat(_ food: CatFood) throws -> Cat { @@ -585,39 +585,39 @@ func getHungryCat(_ food: CatFood) throws -> Cat { } } // errors.getHungryCat throws (errors.CatFood) -> errors.Cat -// CHECK-LABEL: sil hidden [ossa] @$s6errors12getHungryCatyAA0D0CAA0D4FoodOKF : $@convention(thin) (CatFood) -> (@owned Cat, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s6errors12getHungryCatyAA0D0CAA0D4FoodOKF : $@convention(thin) (CatFood) -> (@owned Cat, @error any Error) // CHECK: bb0(%0 : $CatFood): -// CHECK: debug_value undef : $Error, var, name "$error", argno 2 +// CHECK: debug_value undef : $any Error, var, name "$error", argno 2 // CHECK: switch_enum %0 : $CatFood, case #CatFood.Canned!enumelt: bb1, case #CatFood.Dry!enumelt: bb3 // CHECK: bb1: -// CHECK: [[FN:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error Error) -// CHECK: try_apply [[FN]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal bb2, error bb6 +// CHECK: [[FN:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error any Error) +// CHECK: try_apply [[FN]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal bb2, error bb6 // CHECK: bb3: -// CHECK: [[FN:%.*]] = function_ref @$s6errors15dont_make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error Error) -// CHECK: try_apply [[FN]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal bb4, error bb7 -// CHECK: bb6([[ERROR:%.*]] : @owned $Error): -// CHECK: br bb8([[ERROR:%.*]] : $Error) -// CHECK: bb7([[ERROR:%.*]] : @owned $Error): -// CHECK: br bb8([[ERROR]] : $Error) -// CHECK: bb8([[ERROR:%.*]] : @owned $Error): -// CHECK: throw [[ERROR]] : $Error +// CHECK: [[FN:%.*]] = function_ref @$s6errors15dont_make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error any Error) +// CHECK: try_apply [[FN]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal bb4, error bb7 +// CHECK: bb6([[ERROR:%.*]] : @owned $any Error): +// CHECK: br bb8([[ERROR:%.*]] : $any Error) +// CHECK: bb7([[ERROR:%.*]] : @owned $any Error): +// CHECK: br bb8([[ERROR]] : $any Error) +// CHECK: bb8([[ERROR:%.*]] : @owned $any Error): +// CHECK: throw [[ERROR]] : $any Error func take_many_cats(_ cats: Cat...) throws {} func test_variadic(_ cat: Cat) throws { try take_many_cats(make_a_cat(), cat, make_a_cat(), make_a_cat()) } -// CHECK-LABEL: sil hidden [ossa] @$s6errors13test_variadicyyAA3CatCKF : $@convention(thin) (@guaranteed Cat) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s6errors13test_variadicyyAA3CatCKF : $@convention(thin) (@guaranteed Cat) -> @error any Error { // CHECK: bb0([[ARG:%.*]] : @guaranteed $Cat): -// CHECK: debug_value undef : $Error, var, name "$error", argno 2 +// CHECK: debug_value undef : $any Error, var, name "$error", argno 2 // CHECK: [[N:%.*]] = integer_literal $Builtin.Word, 4 // CHECK: [[T0:%.*]] = function_ref @$ss27_allocateUninitializedArray{{.*}}F // CHECK: [[T1:%.*]] = apply [[T0]]([[N]]) // CHECK: ([[ARRAY:%.*]], [[T2:%.*]]) = destructure_tuple [[T1]] // CHECK: [[ELT0:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Cat // Element 0. -// CHECK: [[T0:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error Error) -// CHECK: try_apply [[T0]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[NORM_0:bb[0-9]+]], error [[ERR_0:bb[0-9]+]] +// CHECK: [[T0:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error any Error) +// CHECK: try_apply [[T0]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[NORM_0:bb[0-9]+]], error [[ERR_0:bb[0-9]+]] // CHECK: [[NORM_0]]([[CAT0:%.*]] : @owned $Cat): // CHECK-NEXT: store [[CAT0]] to [init] [[ELT0]] // Element 1. @@ -629,57 +629,57 @@ func test_variadic(_ cat: Cat) throws { // CHECK-NEXT: [[T0:%.*]] = integer_literal $Builtin.Word, 2 // CHECK-NEXT: [[ELT2:%.*]] = index_addr [[ELT0]] : $*Cat, [[T0]] // CHECK-NEXT: // function_ref -// CHECK-NEXT: [[T0:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error Error) -// CHECK-NEXT: try_apply [[T0]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[NORM_2:bb[0-9]+]], error [[ERR_2:bb[0-9]+]] +// CHECK-NEXT: [[T0:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error any Error) +// CHECK-NEXT: try_apply [[T0]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[NORM_2:bb[0-9]+]], error [[ERR_2:bb[0-9]+]] // CHECK: [[NORM_2]]([[CAT2:%.*]] : @owned $Cat): // CHECK-NEXT: store [[CAT2]] to [init] [[ELT2]] // Element 3. // CHECK-NEXT: [[T0:%.*]] = integer_literal $Builtin.Word, 3 // CHECK-NEXT: [[ELT3:%.*]] = index_addr [[ELT0]] : $*Cat, [[T0]] // CHECK-NEXT: // function_ref -// CHECK-NEXT: [[T0:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error Error) -// CHECK-NEXT: try_apply [[T0]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[NORM_3:bb[0-9]+]], error [[ERR_3:bb[0-9]+]] +// CHECK-NEXT: [[T0:%.*]] = function_ref @$s6errors10make_a_catAA3CatCyKF : $@convention(thin) () -> (@owned Cat, @error any Error) +// CHECK-NEXT: try_apply [[T0]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[NORM_3:bb[0-9]+]], error [[ERR_3:bb[0-9]+]] // CHECK: [[NORM_3]]([[CAT3:%.*]] : @owned $Cat): // CHECK-NEXT: store [[CAT3]] to [init] [[ELT3]] // Complete the call and return. // CHECK: [[FIN_FN:%.*]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF // CHECK: [[FIN_ARRAY:%.*]] = apply [[FIN_FN]]([[ARRAY]]) -// CHECK: [[TAKE_FN:%.*]] = function_ref @$s6errors14take_many_catsyyAA3CatCd_tKF : $@convention(thin) (@guaranteed Array) -> @error Error -// CHECK-NEXT: try_apply [[TAKE_FN]]([[FIN_ARRAY]]) : $@convention(thin) (@guaranteed Array) -> @error Error, normal [[NORM_CALL:bb[0-9]+]], error [[ERR_CALL:bb[0-9]+]] +// CHECK: [[TAKE_FN:%.*]] = function_ref @$s6errors14take_many_catsyyAA3CatCd_tKF : $@convention(thin) (@guaranteed Array) -> @error any Error +// CHECK-NEXT: try_apply [[TAKE_FN]]([[FIN_ARRAY]]) : $@convention(thin) (@guaranteed Array) -> @error any Error, normal [[NORM_CALL:bb[0-9]+]], error [[ERR_CALL:bb[0-9]+]] // CHECK: [[NORM_CALL]]([[T0:%.*]] : $()): // CHECK-NEXT: destroy_value [[FIN_ARRAY]] // CHECK-NEXT: [[T0:%.*]] = tuple () // CHECK-NEXT: return // Failure from element 0. -// CHECK: [[ERR_0]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[ERR_0]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NOT: end_borrow // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$ss29_deallocateUninitializedArray{{.*}}F // CHECK-NEXT: apply [[T0]]([[ARRAY]]) -// CHECK-NEXT: br [[RETHROW:.*]]([[ERROR]] : $Error) +// CHECK-NEXT: br [[RETHROW:.*]]([[ERROR]] : $any Error) // Failure from element 2. -// CHECK: [[ERR_2]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[ERR_2]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_addr [[ELT1]] // CHECK-NEXT: destroy_addr [[ELT0]] // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$ss29_deallocateUninitializedArray{{.*}}F // CHECK-NEXT: apply [[T0]]([[ARRAY]]) -// CHECK-NEXT: br [[RETHROW]]([[ERROR]] : $Error) +// CHECK-NEXT: br [[RETHROW]]([[ERROR]] : $any Error) // Failure from element 3. -// CHECK: [[ERR_3]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[ERR_3]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_addr [[ELT2]] // CHECK-NEXT: destroy_addr [[ELT1]] // CHECK-NEXT: destroy_addr [[ELT0]] // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$ss29_deallocateUninitializedArray{{.*}}F // CHECK-NEXT: apply [[T0]]([[ARRAY]]) -// CHECK-NEXT: br [[RETHROW]]([[ERROR]] : $Error) +// CHECK-NEXT: br [[RETHROW]]([[ERROR]] : $any Error) // Failure from call. -// CHECK: [[ERR_CALL]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[ERR_CALL]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_value [[FIN_ARRAY]] -// CHECK-NEXT: br [[RETHROW]]([[ERROR]] : $Error) +// CHECK-NEXT: br [[RETHROW]]([[ERROR]] : $any Error) // Rethrow. -// CHECK: [[RETHROW]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[RETHROW]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: throw [[ERROR]] // CHECK: } // end sil function '$s6errors13test_variadicyyAA3CatCKF' @@ -692,7 +692,7 @@ class BaseThrowingInit : HasThrowingInit { try super.init(value: value) } } -// CHECK: sil hidden [ossa] @$s6errors16BaseThrowingInit{{.*}}c : $@convention(method) (Int, Int, @owned BaseThrowingInit) -> (@owned BaseThrowingInit, @error Error) +// CHECK: sil hidden [ossa] @$s6errors16BaseThrowingInit{{.*}}c : $@convention(method) (Int, Int, @owned BaseThrowingInit) -> (@owned BaseThrowingInit, @error any Error) // CHECK: [[BOX:%.*]] = alloc_box ${ var BaseThrowingInit } // CHECK: [[MARKED_BOX:%.*]] = mark_uninitialized [derivedself] [[BOX]] // CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[MARKED_BOX]] @@ -707,7 +707,7 @@ class BaseThrowingInit : HasThrowingInit { // Super delegation. // CHECK-NEXT: [[T0:%.*]] = load [take] [[PB]] // CHECK-NEXT: [[T2:%.*]] = upcast [[T0]] : $BaseThrowingInit to $HasThrowingInit -// CHECK: [[T3:%[0-9]+]] = function_ref @$s6errors15HasThrowingInitC5valueACSi_tKcfc : $@convention(method) (Int, @owned HasThrowingInit) -> (@owned HasThrowingInit, @error Error) +// CHECK: [[T3:%[0-9]+]] = function_ref @$s6errors15HasThrowingInitC5valueACSi_tKcfc : $@convention(method) (Int, @owned HasThrowingInit) -> (@owned HasThrowingInit, @error any Error) // CHECK-NEXT: apply [[T3]](%0, [[T2]]) // Cleanups for writebacks. @@ -723,7 +723,7 @@ protocol Buildable { func supportFirstStructure(_ b: inout B) throws { try b.firstStructure.support() } -// CHECK-LABEL: sil hidden [ossa] @$s6errors21supportFirstStructure{{.*}}F : $@convention(thin) (@inout B) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s6errors21supportFirstStructure{{.*}}F : $@convention(thin) (@inout B) -> @error any Error { // CHECK: [[MODIFY:%.*]] = witness_method $B, #Buildable.firstStructure!modify : // CHECK: ([[T1:%.*]], [[TOKEN:%.*]]) = begin_apply [[MODIFY]]([[BASE:%[0-9]*]]) // CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support : @@ -733,7 +733,7 @@ func supportFirstStructure(_ b: inout B) throws { // CHECK: end_apply [[TOKEN]] // CHECK: return -// CHECK: [[BB_ERROR]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[BB_ERROR]]([[ERROR:%.*]] : @owned $any Error): // CHECK: abort_apply [[TOKEN]] // CHECK: throw [[ERROR]] @@ -743,14 +743,14 @@ func supportStructure(_ b: inout B, name: String) throws { try b[name].support() } -// CHECK-LABEL: sil hidden [ossa] @$s6errors16supportStructure_4nameyxz_SStKAA9BuildableRzlF : $@convention(thin) (@inout B, @guaranteed String) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s6errors16supportStructure_4nameyxz_SStKAA9BuildableRzlF : $@convention(thin) (@inout B, @guaranteed String) -> @error any Error { // CHECK: bb0({{.*}}, [[INDEX:%.*]] : @guaranteed $String): // CHECK: [[INDEX_COPY:%.*]] = copy_value [[INDEX]] : $String // CHECK: [[BORROWED_INDEX_COPY:%.*]] = begin_borrow [[INDEX_COPY]] // CHECK: [[MODIFY:%.*]] = witness_method $B, #Buildable.subscript!modify : // CHECK: ([[T1:%.*]], [[TOKEN:%.*]]) = begin_apply [[MODIFY]]([[BORROWED_INDEX_COPY]], [[BASE:%[0-9]*]]) // CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support : -// CHECK: try_apply [[SUPPORT]]([[T1]]) : $@convention(witness_method: Supportable) <τ_0_0 where τ_0_0 : Supportable> (@inout τ_0_0) -> @error Error, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]] +// CHECK: try_apply [[SUPPORT]]([[T1]]) : $@convention(witness_method: Supportable) <τ_0_0 where τ_0_0 : Supportable> (@inout τ_0_0) -> @error any Error, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]] // CHECK: [[BB_NORMAL]] // CHECK: end_apply [[TOKEN]] @@ -758,7 +758,7 @@ func supportStructure(_ b: inout B, name: String) throws { // CHECK: destroy_value [[INDEX_COPY]] : $String // CHECK: return -// CHECK: [[BB_ERROR]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[BB_ERROR]]([[ERROR:%.*]] : @owned $any Error): // CHECK: abort_apply [[TOKEN]] // CHECK: end_borrow [[BORROWED_INDEX_COPY]] // CHECK: destroy_value [[INDEX_COPY]] : $String @@ -782,7 +782,7 @@ struct Bridge { func supportStructure(_ b: inout Bridge, name: String) throws { try b[name].support() } -// CHECK: sil hidden [ossa] @$s6errors16supportStructure_4nameyAA6BridgeVz_SStKF : $@convention(thin) (@inout Bridge, @guaranteed String) -> @error Error { +// CHECK: sil hidden [ossa] @$s6errors16supportStructure_4nameyAA6BridgeVz_SStKF : $@convention(thin) (@inout Bridge, @guaranteed String) -> @error any Error { // CHECK: bb0([[ARG1:%.*]] : $*Bridge, [[ARG2:%.*]] : @guaranteed $String): // CHECK: [[INDEX_COPY_1:%.*]] = copy_value [[ARG2]] : $String // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[ARG1]] : $*Bridge @@ -810,7 +810,7 @@ func supportStructure(_ b: inout Bridge, name: String) throws { // We end up with ugly redundancy here because we don't want to // consume things during cleanup emission. It's questionable. -// CHECK: [[BB_ERROR]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[BB_ERROR]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: [[T0:%.*]] = load [copy] [[TEMP]] // CHECK-NEXT: [[INDEX_COPY_2_COPY:%.*]] = copy_value [[INDEX_COPY_2]] // CHECK-NEXT: // function_ref @@ -836,7 +836,7 @@ func testForcePeephole(_ f: () throws -> Int?) -> Int { // CHECK-LABEL: sil hidden [ossa] @$s6errors15testOptionalTryyyF // CHECK-NEXT: bb0: // CHECK: [[FN:%.+]] = function_ref @$s6errors10make_a_catAA3CatCyKF -// CHECK-NEXT: try_apply [[FN]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]], +// CHECK-NEXT: try_apply [[FN]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]], // CHECK: [[SUCCESS]]([[VALUE:%.+]] : @owned $Cat) // CHECK-NEXT: [[WRAPPED:%.+]] = enum $Optional, #Optional.some!enumelt, [[VALUE]] // CHECK-NEXT: br [[DONE:[^ ]+]]([[WRAPPED]] : $Optional) @@ -844,7 +844,7 @@ func testForcePeephole(_ f: () throws -> Int?) -> Int { // CHECK-NEXT: destroy_value [[RESULT]] : $Optional // CHECK-NEXT: [[VOID:%.+]] = tuple () // CHECK-NEXT: return [[VOID]] : $() -// CHECK: [[CLEANUPS:.+]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[CLEANUPS:.+]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: [[NONE:%.+]] = enum $Optional, #Optional.none!enumelt // CHECK-NEXT: br [[DONE]]([[NONE]] : $Optional) @@ -868,7 +868,7 @@ func testOptionalTryThatNeverThrows() { // CHECK-NEXT: [[LIFETIME:%.+]] = begin_borrow [lexical] [[BOX]] // CHECK-NEXT: [[PB:%.*]] = project_box [[LIFETIME]] // CHECK: [[FN:%.+]] = function_ref @$s6errors10make_a_catAA3CatCyKF -// CHECK-NEXT: try_apply [[FN]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]], +// CHECK-NEXT: try_apply [[FN]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]], // CHECK: [[SUCCESS]]([[VALUE:%.+]] : @owned $Cat) // CHECK-NEXT: [[CAT_ENUM:%.+]] = enum $Optional, #Optional.some!enumelt // CHECK-NEXT: store [[CAT_ENUM]] to [init] [[PB]] : $*Optional @@ -878,7 +878,7 @@ func testOptionalTryThatNeverThrows() { // CHECK-NEXT: destroy_value [[BOX]] : ${ var Optional } // CHECK-NEXT: [[VOID:%.+]] = tuple () // CHECK-NEXT: return [[VOID]] : $() -// CHECK: [[CLEANUPS:.+]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[CLEANUPS:.+]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: inject_enum_addr [[PB]] : $*Optional, #Optional.none!enumelt // CHECK-NEXT: br [[DONE]] @@ -892,7 +892,7 @@ func testOptionalTryVar() { // CHECK: [[BOX:%.+]] = alloc_stack $Optional // CHECK-NEXT: [[BOX_DATA:%.+]] = init_enum_data_addr [[BOX]] : $*Optional, #Optional.some!enumelt // CHECK: [[FN:%.+]] = function_ref @$s6errors11dont_return{{.*}}F -// CHECK-NEXT: try_apply [[FN]]([[BOX_DATA]], %0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]], +// CHECK-NEXT: try_apply [[FN]]([[BOX_DATA]], %0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error any Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]], // CHECK: [[SUCCESS]]({{%.+}} : $()): // CHECK-NEXT: inject_enum_addr [[BOX]] : $*Optional, #Optional.some!enumelt // CHECK-NEXT: br [[DONE:[^ ]+]], @@ -902,7 +902,7 @@ func testOptionalTryVar() { // CHECK-NOT: destroy_addr %0 : $*T // CHECK-NEXT: [[VOID:%.+]] = tuple () // CHECK-NEXT: return [[VOID]] : $() -// CHECK: [[CLEANUPS]]([[ERROR:%.+]] : @owned $Error): +// CHECK: [[CLEANUPS]]([[ERROR:%.+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: inject_enum_addr [[BOX]] : $*Optional, #Optional.none!enumelt // CHECK-NEXT: br [[DONE]] @@ -918,7 +918,7 @@ func testOptionalTryAddressOnly(_ obj: T) { // CHECK-NEXT: [[PB:%.*]] = project_box [[LIFETIME]] // CHECK-NEXT: [[BOX_DATA:%.+]] = init_enum_data_addr [[PB]] : $*Optional, #Optional.some!enumelt // CHECK: [[FN:%.+]] = function_ref @$s6errors11dont_return{{.*}}F -// CHECK-NEXT: try_apply [[FN]]([[BOX_DATA]], %0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]], +// CHECK-NEXT: try_apply [[FN]]([[BOX_DATA]], %0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error any Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]], // CHECK: [[SUCCESS]]({{%.+}} : $()): // CHECK-NEXT: inject_enum_addr [[PB]] : $*Optional, #Optional.some!enumelt // CHECK-NEXT: br [[DONE:[^ ]+]], @@ -928,7 +928,7 @@ func testOptionalTryAddressOnly(_ obj: T) { // CHECK-NOT: destroy_addr %0 : $*T // CHECK-NEXT: [[VOID:%.+]] = tuple () // CHECK-NEXT: return [[VOID]] : $() -// CHECK: [[CLEANUPS]]([[ERROR:%.+]] : @owned $Error): +// CHECK: [[CLEANUPS]]([[ERROR:%.+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: inject_enum_addr [[PB]] : $*Optional, #Optional.none!enumelt // CHECK-NEXT: br [[DONE]] @@ -940,10 +940,10 @@ func testOptionalTryAddressOnlyVar(_ obj: T) { // CHECK-LABEL: sil hidden [ossa] @$s6errors23testOptionalTryMultipleyyF // CHECK: bb0: // CHECK: [[FN_1:%.+]] = function_ref @$s6errors10make_a_catAA3CatCyKF -// CHECK-NEXT: try_apply [[FN_1]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[SUCCESS_1:[^ ]+]], error [[CLEANUPS_1:[^ ]+]], +// CHECK-NEXT: try_apply [[FN_1]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[SUCCESS_1:[^ ]+]], error [[CLEANUPS_1:[^ ]+]], // CHECK: [[SUCCESS_1]]([[VALUE_1:%.+]] : @owned $Cat) // CHECK: [[FN_2:%.+]] = function_ref @$s6errors10make_a_catAA3CatCyKF -// CHECK-NEXT: try_apply [[FN_2]]() : $@convention(thin) () -> (@owned Cat, @error Error), normal [[SUCCESS_2:[^ ]+]], error [[CLEANUPS_2:[^ ]+]], +// CHECK-NEXT: try_apply [[FN_2]]() : $@convention(thin) () -> (@owned Cat, @error any Error), normal [[SUCCESS_2:[^ ]+]], error [[CLEANUPS_2:[^ ]+]], // CHECK: [[SUCCESS_2]]([[VALUE_2:%.+]] : @owned $Cat) // CHECK-NEXT: [[TUPLE:%.+]] = tuple ([[VALUE_1]] : $Cat, [[VALUE_2]] : $Cat) // CHECK-NEXT: [[WRAPPED:%.+]] = enum $Optional<(Cat, Cat)>, #Optional.some!enumelt, [[TUPLE]] @@ -952,15 +952,15 @@ func testOptionalTryAddressOnlyVar(_ obj: T) { // CHECK-NEXT: destroy_value [[RESULT]] : $Optional<(Cat, Cat)> // CHECK-NEXT: [[VOID:%.+]] = tuple () // CHECK-NEXT: return [[VOID]] : $() -// CHECK: [[FAILURE:.+]]([[ERROR:%.*]] : @owned $Error): +// CHECK: [[FAILURE:.+]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: [[NONE:%.+]] = enum $Optional<(Cat, Cat)>, #Optional.none!enumelt // CHECK-NEXT: br [[DONE]]([[NONE]] : $Optional<(Cat, Cat)>) -// CHECK: [[CLEANUPS_1]]([[ERROR:%.+]] : @owned $Error): -// CHECK-NEXT: br [[FAILURE]]([[ERROR]] : $Error) -// CHECK: [[CLEANUPS_2]]([[ERROR:%.+]] : @owned $Error): +// CHECK: [[CLEANUPS_1]]([[ERROR:%.+]] : @owned $any Error): +// CHECK-NEXT: br [[FAILURE]]([[ERROR]] : $any Error) +// CHECK: [[CLEANUPS_2]]([[ERROR:%.+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[VALUE_1]] : $Cat -// CHECK-NEXT: br [[FAILURE]]([[ERROR]] : $Error) +// CHECK-NEXT: br [[FAILURE]]([[ERROR]] : $any Error) // CHECK: } // end sil function '$s6errors23testOptionalTryMultipleyyF' func testOptionalTryMultiple() { _ = try? (make_a_cat(), make_a_cat()) diff --git a/test/SILGen/existential_erasure.swift b/test/SILGen/existential_erasure.swift index 9e1dea023f0c2..514d2f04dcb18 100644 --- a/test/SILGen/existential_erasure.swift +++ b/test/SILGen/existential_erasure.swift @@ -25,8 +25,8 @@ func throwingFunc() throws -> Bool { return true } // CHECK-LABEL: sil hidden [ossa] @$s19existential_erasure5PQtoPyyF : $@convention(thin) () -> () { func PQtoP() { - // CHECK: [[PQ_PAYLOAD:%.*]] = open_existential_addr immutable_access [[PQ:%.*]] : $*P & Q to $*[[OPENED_TYPE:@opened\(.*, P & Q\) Self]] - // CHECK: [[P_PAYLOAD:%.*]] = init_existential_addr [[P:%.*]] : $*P, $[[OPENED_TYPE]] + // CHECK: [[PQ_PAYLOAD:%.*]] = open_existential_addr immutable_access [[PQ:%.*]] : $*any P & Q to $*[[OPENED_TYPE:@opened\(.*, any P & Q\) Self]] + // CHECK: [[P_PAYLOAD:%.*]] = init_existential_addr [[P:%.*]] : $*any P, $[[OPENED_TYPE]] // CHECK: copy_addr [[PQ_PAYLOAD]] to [initialization] [[P_PAYLOAD]] // CHECK: destroy_addr [[PQ]] // CHECK-NOT: destroy_addr [[P]] @@ -41,20 +41,20 @@ func PQtoP() { // CHECK-LABEL: sil hidden [ossa] @$s19existential_erasure19openExistentialToP1yyAA1P_pKF func openExistentialToP1(_ p: P) throws { -// CHECK: bb0(%0 : $*P): -// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*P to $*[[OPEN_TYPE:@opened\(.*, P\) Self]] -// CHECK: [[RESULT:%.*]] = alloc_stack $P +// CHECK: bb0(%0 : $*any P): +// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*[[OPEN_TYPE:@opened\(.*, any P\) Self]] +// CHECK: [[RESULT:%.*]] = alloc_stack $any P // CHECK: [[FUNC:%.*]] = function_ref @$s19existential_erasure12throwingFuncSbyKF // CHECK: try_apply [[FUNC]]() // // CHECK: bb1([[SUCCESS:%.*]] : $Bool): // CHECK: [[METHOD:%.*]] = witness_method $[[OPEN_TYPE]], #P.downgrade : {{.*}}, [[OPEN]] -// CHECK: [[RESULT_ADDR:%.*]] = init_existential_addr [[RESULT]] : $*P, $[[OPEN_TYPE]] +// CHECK: [[RESULT_ADDR:%.*]] = init_existential_addr [[RESULT]] : $*any P, $[[OPEN_TYPE]] // CHECK: apply [[METHOD]]<[[OPEN_TYPE]]>([[RESULT_ADDR]], [[SUCCESS]], [[OPEN]]) // CHECK: dealloc_stack [[RESULT]] // CHECK: return // -// CHECK: bb2([[FAILURE:%.*]] : @owned $Error): +// CHECK: bb2([[FAILURE:%.*]] : @owned $any Error): // CHECK: dealloc_stack [[RESULT]] // CHECK: throw [[FAILURE]] // @@ -63,18 +63,18 @@ func openExistentialToP1(_ p: P) throws { // CHECK-LABEL: sil hidden [ossa] @$s19existential_erasure19openExistentialToP2yyAA1P_pKF func openExistentialToP2(_ p: P) throws { -// CHECK: bb0(%0 : $*P): -// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*P to $*[[OPEN_TYPE:@opened\(.*, P\) Self]] -// CHECK: [[RESULT:%.*]] = alloc_stack $P +// CHECK: bb0(%0 : $*any P): +// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*[[OPEN_TYPE:@opened\(.*, any P\) Self]] +// CHECK: [[RESULT:%.*]] = alloc_stack $any P // CHECK: [[METHOD:%.*]] = witness_method $[[OPEN_TYPE]], #P.upgrade : {{.*}}, [[OPEN]] -// CHECK: [[RESULT_ADDR:%.*]] = init_existential_addr [[RESULT]] : $*P, $[[OPEN_TYPE]] +// CHECK: [[RESULT_ADDR:%.*]] = init_existential_addr [[RESULT]] : $*any P, $[[OPEN_TYPE]] // CHECK: try_apply [[METHOD]]<[[OPEN_TYPE]]>([[RESULT_ADDR]], [[OPEN]]) // // CHECK: bb1 // CHECK: dealloc_stack [[RESULT]] // CHECK: return // -// CHECK: bb2([[FAILURE:%.*]]: @owned $Error): +// CHECK: bb2([[FAILURE:%.*]]: @owned $any Error): // CHECK: deinit_existential_addr [[RESULT]] // CHECK: dealloc_stack [[RESULT]] // CHECK: throw [[FAILURE]] @@ -92,23 +92,23 @@ extension Error { // CHECK-LABEL: sil hidden [ossa] @$s19existential_erasure12errorHandlerys5Error_psAC_pKF func errorHandler(_ e: Error) throws -> Error { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error): -// CHECK: debug_value [[ARG]] : $Error -// CHECK: [[OPEN:%.*]] = open_existential_box [[ARG]] : $Error to $*[[OPEN_TYPE:@opened\(.*, Error\) Self]] +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Error): +// CHECK: debug_value [[ARG]] : $any Error +// CHECK: [[OPEN:%.*]] = open_existential_box [[ARG]] : $any Error to $*[[OPEN_TYPE:@opened\(.*, any Error\) Self]] // CHECK: [[FUNC:%.*]] = function_ref @$ss5ErrorP19existential_erasureE17returnOrThrowSelf{{[_0-9a-zA-Z]*}}F -// CHECK: [[RESULT:%.*]] = alloc_existential_box $Error, $[[OPEN_TYPE]] -// CHECK: [[ADDR:%.*]] = project_existential_box $[[OPEN_TYPE]] in [[RESULT]] : $Error +// CHECK: [[RESULT:%.*]] = alloc_existential_box $any Error, $[[OPEN_TYPE]] +// CHECK: [[ADDR:%.*]] = project_existential_box $[[OPEN_TYPE]] in [[RESULT]] : $any Error // CHECK: store [[RESULT]] to [init] [[RESULT_BUF:%.*]] : // CHECK: try_apply [[FUNC]]<[[OPEN_TYPE]]>([[ADDR]], [[OPEN]]) // // CHECK: bb1 // CHECK: [[RESULT2:%.*]] = load [take] [[RESULT_BUF]] -// CHECK: return [[RESULT2]] : $Error +// CHECK: return [[RESULT2]] : $any Error // -// CHECK: bb2([[FAILURE:%.*]] : @owned $Error): +// CHECK: bb2([[FAILURE:%.*]] : @owned $any Error): // CHECK: [[RESULT3:%.*]] = load [take] [[RESULT_BUF]] // CHECK: dealloc_existential_box [[RESULT3]] -// CHECK: throw [[FAILURE]] : $Error +// CHECK: throw [[FAILURE]] : $any Error // return try e.returnOrThrowSelf() } diff --git a/test/SILGen/existential_member_accesses_self_assoctype.swift b/test/SILGen/existential_member_accesses_self_assoctype.swift index 5b0e41581ec0e..56ddf57a8a1f2 100644 --- a/test/SILGen/existential_member_accesses_self_assoctype.swift +++ b/test/SILGen/existential_member_accesses_self_assoctype.swift @@ -63,76 +63,76 @@ protocol P { // ----------------------------------------------------------------------------- // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype24testCovariantSelfMethod11pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $P, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfMethod1 : (Self) -> () -> Self -// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*P, $@opened([[OPENED_ID]], P) Self -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[DEST]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $any P, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfMethod1 : (Self) -> () -> Self +// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*any P, $@opened([[OPENED_ID]], any P) Self +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[DEST]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 func testCovariantSelfMethod1(p: any P) { let x = p.covariantSelfMethod1() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype24testCovariantSelfMethod21pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional

, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfMethod2 : (Self) -> () -> Self? -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> -// CHECK: init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfMethod2 : (Self) -> () -> Self? +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self func testCovariantSelfMethod2(p: any P) { let x = p.covariantSelfMethod2() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype24testCovariantSelfMethod31pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfMethod3 : (Self) -> () -> Self.Type -// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.Type -// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], P) Self).Type, $@thick P.Type -// CHECK: debug_value [[EXIST_META]] : $@thick P.Type, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfMethod3 : (Self) -> () -> Self.Type +// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.Type +// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], any P) Self).Type, $@thick any P.Type +// CHECK: debug_value [[EXIST_META]] : $@thick any P.Type, let, name "x" func testCovariantSelfMethod3(p: any P) { let x = p.covariantSelfMethod3() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype24testCovariantSelfMethod41pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(P, P), let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfMethod4 : (Self) -> () -> (Self, Self) -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[SRC_0:%[0-9]+]], [[SRC_1:%[0-9]+]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @out τ_0_0) -// CHECK: init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self -// CHECK: init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(any P, any P), let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfMethod4 : (Self) -> () -> (Self, Self) +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[SRC_0:%[0-9]+]], [[SRC_1:%[0-9]+]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @out τ_0_0) +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self func testCovariantSelfMethod4(p: any P) { let x = p.covariantSelfMethod4() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype24testCovariantSelfMethod51pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfMethod5 : (Self) -> () -> Array -// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfMethod5 : (Self) -> () -> Array +// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0> // CHECK: [[ARRAY_UPCAST_FN:%[0-9]+]] = function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], P) Self, P>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: debug_value %{{[0-9]+}} : $Array

, let, name "x" +// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], any P) Self, any P>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> +// CHECK: debug_value %{{[0-9]+}} : $Array, let, name "x" func testCovariantSelfMethod5(p: any P) { let x = p.covariantSelfMethod5() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype24testCovariantSelfMethod61pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfMethod6 : (Self) -> () -> [String : Self] -// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfMethod6 : (Self) -> () -> [String : Self] +// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary // CHECK: [[DICT_UPCAST_FN:%[0-9]+]] = function_ref @$ss17_dictionaryUpCastySDyq0_q1_GSDyxq_GSHRzSHR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" +// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> +// CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" func testCovariantSelfMethod6(p: any P) { let x = p.covariantSelfMethod6() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype24testCovariantSelfMethod71pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[THUNK:%[0-9]+]] = function_ref @$s42existential_member_accesses_self_assoctype1P_pIgn_xIegn_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @noescape @callee_guaranteed (@in_guaranteed P) -> ()) -> () -// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], P) Self> -// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], P) Self) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P) Self> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[THUNK:%[0-9]+]] = function_ref @$s42existential_member_accesses_self_assoctype1P_pIgn_xIegn_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @noescape @callee_guaranteed (@in_guaranteed any P) -> ()) -> () +// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], any P) Self> +// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], any P) Self) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P) Self> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfMethod7 : (Self) -> ((Self) -> ()) -> () -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[STEP3]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>, @in_guaranteed τ_0_0) -> () +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfMethod7 : (Self) -> ((Self) -> ()) -> () +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[STEP3]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>, @in_guaranteed τ_0_0) -> () func testCovariantSelfMethod7(p: any P) { p.covariantSelfMethod7 { _ in } } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype24testCovariantSelfMethod81pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", P\) Self]] -// CHECK: [[THUNK:%[0-9]+]] = function_ref @[[SELF_ARRAY_THUNK_NAME:\$[0-9a-zA-Z_]+]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed Array<τ_0_0>, @noescape @callee_guaranteed (@guaranteed Array

) -> ()) -> () +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", any P\) Self]] +// CHECK: [[THUNK:%[0-9]+]] = function_ref @[[SELF_ARRAY_THUNK_NAME:\$[0-9a-zA-Z_]+]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed Array<τ_0_0>, @noescape @callee_guaranteed (@guaranteed Array) -> ()) -> () // CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<[[OPENED_TY]]> // CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@guaranteed Array<[[OPENED_TY]]>) -> () to $@callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]], [[OPENED_TY]]> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] @@ -141,105 +141,105 @@ func testCovariantSelfMethod7(p: any P) { // CHECK: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @[[SELF_ARRAY_THUNK_NAME]] // CHECK: [[ARRAY_UPCAST:%[0-9]+]] = function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF -// CHECK: apply [[ARRAY_UPCAST]]<τ_0_0, P> +// CHECK: apply [[ARRAY_UPCAST]]<τ_0_0, any P> // CHECK: } // end sil function '[[SELF_ARRAY_THUNK_NAME]]' func testCovariantSelfMethod8(p: any P) { p.covariantSelfMethod8 { _ in } } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty11pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $P, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $any P, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self // FIXME: What's this copy for? -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfProperty1!getter : (Self) -> () -> Self -// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*P, $@opened([[OPENED_ID]], P) Self -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[DEST]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfProperty1!getter : (Self) -> () -> Self +// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*any P, $@opened([[OPENED_ID]], any P) Self +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[DEST]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 func testCovariantSelfProperty1(p: any P) { let x = p.covariantSelfProperty1 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty21pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional

, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfProperty2!getter : (Self) -> () -> Self? -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPTIONAL:%[0-9]+]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> -// CHECK: init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfProperty2!getter : (Self) -> () -> Self? +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPTIONAL:%[0-9]+]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self func testCovariantSelfProperty2(p: any P) { let x = p.covariantSelfProperty2 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty31pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfProperty3!getter : (Self) -> () -> Self.Type -// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.Type -// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], P) Self).Type, $@thick P.Type -// CHECK: debug_value [[EXIST_META]] : $@thick P.Type, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfProperty3!getter : (Self) -> () -> Self.Type +// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.Type +// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], any P) Self).Type, $@thick any P.Type +// CHECK: debug_value [[EXIST_META]] : $@thick any P.Type, let, name "x" func testCovariantSelfProperty3(p: any P) { let x = p.covariantSelfProperty3 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty41pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(P, P), let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfProperty4!getter : (Self) -> () -> (Self, Self) -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[SRC_0:%[0-9]+]], [[SRC_1:%[0-9]+]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @out τ_0_0) -// CHECK: [[DEST_0_INITED:%[0-9]+]] = init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self -// CHECK: [[DEST_1_INITED:%[0-9]+]] = init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(any P, any P), let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfProperty4!getter : (Self) -> () -> (Self, Self) +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[SRC_0:%[0-9]+]], [[SRC_1:%[0-9]+]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @out τ_0_0) +// CHECK: [[DEST_0_INITED:%[0-9]+]] = init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self +// CHECK: [[DEST_1_INITED:%[0-9]+]] = init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self func testCovariantSelfProperty4(p: any P) { let x = p.covariantSelfProperty4 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty51pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfProperty5!getter : (Self) -> () -> Array -// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfProperty5!getter : (Self) -> () -> Array +// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0> // CHECK: [[ARRAY_UPCAST_FN:%[0-9]+]] = function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], P) Self, P>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: debug_value %{{[0-9]+}} : $Array

, let, name "x" +// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], any P) Self, any P>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> +// CHECK: debug_value %{{[0-9]+}} : $Array, let, name "x" func testCovariantSelfProperty5(p: any P) { let x = p.covariantSelfProperty5 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty61pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfProperty6!getter : (Self) -> () -> [String : Self] -// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfProperty6!getter : (Self) -> () -> [String : Self] +// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary // CHECK: [[DICT_UPCAST_FN:%[0-9]+]] = function_ref @$ss17_dictionaryUpCastySDyq0_q1_GSDyxq_GSHRzSHR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" +// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> +// CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" func testCovariantSelfProperty6(p: any P) { let x = p.covariantSelfProperty6 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty71pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantSelfProperty7!getter : (Self) -> () -> ((Self) -> ()) -> () -// CHECK: [[RESULT_FN:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed @substituted <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <τ_0_0> -// CHECK: [[STEP1:%[0-9]+]] = convert_function [[RESULT_FN]] : $@callee_guaranteed @substituted <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <@opened([[OPENED_ID]], P) Self> to $@callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P) Self>) -> () -// CHECK: [[THUNK:%[0-9]+]] = function_ref @$sxlyxIsgn_Iegy_42existential_member_accesses_self_assoctype1P_pIgn_Iegy_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@in_guaranteed P) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> ()) -> () -// CHECK: partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], P) Self>([[STEP1]]) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@in_guaranteed P) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> ()) -> () -// CHECK: debug_value %{{[0-9]+}} : $@callee_guaranteed (@noescape @callee_guaranteed (@in_guaranteed P) -> ()) -> (), let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantSelfProperty7!getter : (Self) -> () -> ((Self) -> ()) -> () +// CHECK: [[RESULT_FN:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed @substituted <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <τ_0_0> +// CHECK: [[STEP1:%[0-9]+]] = convert_function [[RESULT_FN]] : $@callee_guaranteed @substituted <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <@opened([[OPENED_ID]], any P) Self> to $@callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P) Self>) -> () +// CHECK: [[THUNK:%[0-9]+]] = function_ref @$sxlyxIsgn_Iegy_42existential_member_accesses_self_assoctype1P_pIgn_Iegy_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@in_guaranteed any P) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> ()) -> () +// CHECK: partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], any P) Self>([[STEP1]]) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@in_guaranteed any P) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> ()) -> () +// CHECK: debug_value %{{[0-9]+}} : $@callee_guaranteed (@noescape @callee_guaranteed (@in_guaranteed any P) -> ()) -> (), let, name "x" func testCovariantSelfProperty7(p: any P) { let x = p.covariantSelfProperty7 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty81pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", P\) Self]] +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", any P\) Self]] // CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $[[OPENED_TY]] // CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*[[OPENED_TY]] // CHECK: [[WITNESS:%[0-9]+]] = witness_method $[[OPENED_TY]], #P.covariantSelfProperty8!getter : (Self) -> () -> ((Self...) -> ()) -> () // CHECK: [[RESULT_FN:%[0-9]+]] = apply [[WITNESS]]<[[OPENED_TY]]>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0, τ_0_0>) -> () for <τ_0_0, τ_0_0> // CHECK: [[STEP1:%[0-9]+]] = convert_function [[RESULT_FN]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0, τ_0_0>) -> () for <[[OPENED_TY]], [[OPENED_TY]]> to $@callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]], [[OPENED_TY]]>) -> () -// CHECK: [[THUNK:%[0-9]+]] = function_ref @[[THUNK_NAME:\$[0-9a-zA-Z_]+]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@guaranteed Array

) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0, τ_0_0>) -> ()) -> () +// CHECK: [[THUNK:%[0-9]+]] = function_ref @[[THUNK_NAME:\$[0-9a-zA-Z_]+]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@guaranteed Array) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0, τ_0_0>) -> ()) -> () // CHECK: partial_apply [callee_guaranteed] [[THUNK]]<[[OPENED_TY]]>([[STEP1]]) -// CHECK: debug_value %{{[0-9]+}} : $@callee_guaranteed (@noescape @callee_guaranteed (@guaranteed Array

) -> ()) -> (), let, name "x" +// CHECK: debug_value %{{[0-9]+}} : $@callee_guaranteed (@noescape @callee_guaranteed (@guaranteed Array) -> ()) -> (), let, name "x" // CHECK: } // end sil function '$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty81pyAA1P_p_tF' // CHECK: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @[[THUNK_NAME]] @@ -250,90 +250,90 @@ func testCovariantSelfProperty8(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript11pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $P, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> Self -// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*P, $@opened([[OPENED_ID]], P) Self -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[DEST]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $any P, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> Self +// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*any P, $@opened([[OPENED_ID]], any P) Self +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[DEST]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 func testCovariantSelfSubscript1(p: any P) { let x = p[covariantSelfSubscript1: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript21pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional

, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> Self? -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPTIONAL:%[0-9]+]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> -// CHECK: init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> Self? +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPTIONAL:%[0-9]+]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self func testCovariantSelfSubscript2(p: any P) { let x = p[covariantSelfSubscript2: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript31pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> Self.Type -// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.Type -// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], P) Self).Type, $@thick P.Type -// CHECK: debug_value [[EXIST_META]] : $@thick P.Type, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> Self.Type +// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.Type +// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], any P) Self).Type, $@thick any P.Type +// CHECK: debug_value [[EXIST_META]] : $@thick any P.Type, let, name "x" func testCovariantSelfSubscript3(p: any P) { let x = p[covariantSelfSubscript3: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript41pyAA1P_p_tF -// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(P, P), let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> (Self, Self) -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[SRC_0:%[0-9]+]], [[SRC_1:%[0-9]+]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @out τ_0_0) -// CHECK: init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self -// CHECK: init_existential_addr %{{[0-9]+}} : $*P, $@opened([[OPENED_ID]], P) Self +// CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(any P, any P), let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> (Self, Self) +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[SRC_0:%[0-9]+]], [[SRC_1:%[0-9]+]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @out τ_0_0) +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P, $@opened([[OPENED_ID]], any P) Self func testCovariantSelfSubscript4(p: any P) { let x = p[covariantSelfSubscript4: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript51pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> Array -// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> Array +// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0> // CHECK: [[ARRAY_UPCAST_FN:%[0-9]+]] = function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], P) Self, P>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: debug_value %{{[0-9]+}} : $Array

, let, name "x" +// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], any P) Self, any P>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> +// CHECK: debug_value %{{[0-9]+}} : $Array, let, name "x" func testCovariantSelfSubscript5(p: any P) { let x = p[covariantSelfSubscript5: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript61pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> [String : Self] -// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> [String : Self] +// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary // CHECK: [[DICT_UPCAST_FN:%[0-9]+]] = function_ref @$ss17_dictionaryUpCastySDyq0_q1_GSDyxq_GSHRzSHR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" +// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> +// CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" func testCovariantSelfSubscript6(p: any P) { let x = p[covariantSelfSubscript6: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript71pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[THUNK:%[0-9]+]] = function_ref @$s42existential_member_accesses_self_assoctype1P_pIgn_xIegn_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @noescape @callee_guaranteed (@in_guaranteed P) -> ()) -> () -// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], P) Self> -// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], P) Self) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P) Self> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[THUNK:%[0-9]+]] = function_ref @$s42existential_member_accesses_self_assoctype1P_pIgn_xIegn_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @noescape @callee_guaranteed (@in_guaranteed any P) -> ()) -> () +// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], any P) Self> +// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], any P) Self) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P) Self> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> ((Self) -> ()) -> () -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[STEP3]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>, @in_guaranteed τ_0_0) -> () +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> ((Self) -> ()) -> () +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[STEP3]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>, @in_guaranteed τ_0_0) -> () func testCovariantSelfSubscript7(p: any P) { _ = p[covariantSelfSubscript7: { _ in }] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript81pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", P\) Self]] -// CHECK: [[THUNK:%[0-9]+]] = function_ref @[[SELF_ARRAY_THUNK_NAME]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed Array<τ_0_0>, @noescape @callee_guaranteed (@guaranteed Array

) -> ()) -> () +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", any P\) Self]] +// CHECK: [[THUNK:%[0-9]+]] = function_ref @[[SELF_ARRAY_THUNK_NAME]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed Array<τ_0_0>, @noescape @callee_guaranteed (@guaranteed Array) -> ()) -> () // CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<[[OPENED_TY]]> // CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@guaranteed Array<[[OPENED_TY]]>) -> () to $@callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]], [[OPENED_TY]]> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] @@ -347,75 +347,75 @@ func testCovariantSelfSubscript8(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype25testCovariantAssocMethod11pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Any, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocMethod1 : (Self) -> () -> Self.A -// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*Any, $@opened([[OPENED_ID]], P) Self.A -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[DEST]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocMethod1 : (Self) -> () -> Self.A +// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*Any, $@opened([[OPENED_ID]], any P) Self.A +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[DEST]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A func testCovariantAssocMethod1(p: any P) { let x = p.covariantAssocMethod1() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype25testCovariantAssocMethod21pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocMethod2 : (Self) -> () -> Self.A? -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.A> -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocMethod2 : (Self) -> () -> Self.A? +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.A> +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A func testCovariantAssocMethod2(p: any P) { let x = p.covariantAssocMethod2() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype25testCovariantAssocMethod31pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocMethod3 : (Self) -> () -> Self.A.Type -// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.A.Type -// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], P) Self.A).Type, $@thick Any.Type -// CHECK: debug_value [[EXIST_META]] : $@thick Any.Type, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocMethod3 : (Self) -> () -> Self.A.Type +// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.A.Type +// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], any P) Self.A).Type, $@thick any Any.Type +// CHECK: debug_value [[EXIST_META]] : $@thick any Any.Type, let, name "x" func testCovariantAssocMethod3(p: any P) { let x = p.covariantAssocMethod3() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype25testCovariantAssocMethod41pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(Any, Any), let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocMethod4 : (Self) -> () -> (Self.A, Self.A) -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>(%{{[0-9]+}}, %{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0.A, @out τ_0_0.A) -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocMethod4 : (Self) -> () -> (Self.A, Self.A) +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>(%{{[0-9]+}}, %{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0.A, @out τ_0_0.A) +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A func testCovariantAssocMethod4(p: any P) { let x = p.covariantAssocMethod4() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype25testCovariantAssocMethod51pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocMethod5 : (Self) -> () -> Array -// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0.A> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocMethod5 : (Self) -> () -> Array +// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0.A> // CHECK: [[ARRAY_UPCAST_FN:%[0-9]+]] = function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], P) Self.A, Any>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> +// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], any P) Self.A, Any>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> // CHECK: debug_value %{{[0-9]+}} : $Array, let, name "x" func testCovariantAssocMethod5(p: any P) { let x = p.covariantAssocMethod5() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype25testCovariantAssocMethod61pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocMethod6 : (Self) -> () -> [String : Self.A] -// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocMethod6 : (Self) -> () -> [String : Self.A] +// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary // CHECK: [[DICT_UPCAST_FN:%[0-9]+]] = function_ref @$ss17_dictionaryUpCastySDyq0_q1_GSDyxq_GSHRzSHR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> +// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> // CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" func testCovariantAssocMethod6(p: any P) { let x = p.covariantAssocMethod6() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype25testCovariantAssocMethod71pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self // CHECK: function_ref thunk for @callee_guaranteed (@in_guaranteed Any) -> () // CHECK-NEXT: function_ref @$sypIgn_1A42existential_member_accesses_self_assoctype1PPQzIegn_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0.A, @noescape @callee_guaranteed (@in_guaranteed Any) -> ()) -> () -// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], P) Self> -// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], P) Self.A) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P) Self.A> +// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], any P) Self> +// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], any P) Self.A) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P) Self.A> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocMethod7 : (Self) -> ((Self.A) -> ()) -> () -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[STEP3]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocMethod7 : (Self) -> ((Self.A) -> ()) -> () +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[STEP3]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () func testCovariantAssocMethod7(p: any P) { p.covariantAssocMethod7 { _ in } } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype25testCovariantAssocMethod81pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", P\) Self]] +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", any P\) Self]] // CHECK: [[THUNK:%[0-9]+]] = function_ref @[[ASSOCTYPE_ARRAY_THUNK_NAME:\$[0-9a-zA-Z_]+]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed Array<τ_0_0.A>, @noescape @callee_guaranteed (@guaranteed Array) -> ()) -> () // CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<[[OPENED_TY]]> // CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@guaranteed Array<[[OPENED_TY]].A>) -> () to $@callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]].A, [[OPENED_TY]].A> @@ -433,88 +433,88 @@ func testCovariantAssocMethod8(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty11pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Any, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocProperty1!getter : (Self) -> () -> Self.A -// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*Any, $@opened([[OPENED_ID]], P) Self.A -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[DEST]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocProperty1!getter : (Self) -> () -> Self.A +// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*Any, $@opened([[OPENED_ID]], any P) Self.A +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[DEST]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A func testCovariantAssocProperty1(p: any P) { let x = p.covariantAssocProperty1 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty21pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocProperty2!getter : (Self) -> () -> Self.A? -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>(%{{[0-9]+}}, [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.A> -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocProperty2!getter : (Self) -> () -> Self.A? +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>(%{{[0-9]+}}, [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.A> +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A func testCovariantAssocProperty2(p: any P) { let x = p.covariantAssocProperty2 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty31pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocProperty3!getter : (Self) -> () -> Self.A.Type -// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.A.Type -// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], P) Self.A).Type, $@thick Any.Type -// CHECK: debug_value [[EXIST_META]] : $@thick Any.Type, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocProperty3!getter : (Self) -> () -> Self.A.Type +// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.A.Type +// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], any P) Self.A).Type, $@thick any Any.Type +// CHECK: debug_value [[EXIST_META]] : $@thick any Any.Type, let, name "x" func testCovariantAssocProperty3(p: any P) { let x = p.covariantAssocProperty3 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty41pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(Any, Any), let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocProperty4!getter : (Self) -> () -> (Self.A, Self.A) -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>(%{{[0-9]+}}, %{{[0-9]+}}, [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0.A, @out τ_0_0.A) -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocProperty4!getter : (Self) -> () -> (Self.A, Self.A) +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>(%{{[0-9]+}}, %{{[0-9]+}}, [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0.A, @out τ_0_0.A) +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A func testCovariantAssocProperty4(p: any P) { let x = p.covariantAssocProperty4 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty51pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocProperty5!getter : (Self) -> () -> Array -// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0.A> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocProperty5!getter : (Self) -> () -> Array +// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0.A> // CHECK: [[ARRAY_UPCAST_FN:%[0-9]+]] = function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], P) Self.A, Any>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> +// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], any P) Self.A, Any>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> // CHECK: debug_value %{{[0-9]+}} : $Array, let, name "x" func testCovariantAssocProperty5(p: any P) { let x = p.covariantAssocProperty5 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty61pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocProperty6!getter : (Self) -> () -> [String : Self.A] -// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocProperty6!getter : (Self) -> () -> [String : Self.A] +// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary // CHECK: [[DICT_UPCAST_FN:%[0-9]+]] = function_ref @$ss17_dictionaryUpCastySDyq0_q1_GSDyxq_GSHRzSHR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> +// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> // CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" func testCovariantAssocProperty6(p: any P) { let x = p.covariantAssocProperty6 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty71pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.covariantAssocProperty7!getter : (Self) -> () -> ((Self.A) -> ()) -> () -// CHECK: [[RESULT_FN:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed @substituted <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <τ_0_0.A> -// CHECK: [[STEP1:%[0-9]+]] = convert_function [[RESULT_FN]] : $@callee_guaranteed @substituted <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <@opened([[OPENED_ID]], P) Self.A> to $@callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P) Self.A>) -> () +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.covariantAssocProperty7!getter : (Self) -> () -> ((Self.A) -> ()) -> () +// CHECK: [[RESULT_FN:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed @substituted <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <τ_0_0.A> +// CHECK: [[STEP1:%[0-9]+]] = convert_function [[RESULT_FN]] : $@callee_guaranteed @substituted <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <@opened([[OPENED_ID]], any P) Self.A> to $@callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P) Self.A>) -> () // CHECK: [[THUNK:%[0-9]+]] = function_ref @$sxly1A42existential_member_accesses_self_assoctype1PPQzIsgn_Iegy_ypIgn_Iegy_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@in_guaranteed Any) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>) -> ()) -> () -// CHECK: partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], P) Self>([[STEP1]]) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@in_guaranteed Any) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>) -> ()) -> () +// CHECK: partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], any P) Self>([[STEP1]]) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed (@in_guaranteed Any) -> (), @guaranteed @callee_guaranteed (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>) -> ()) -> () // CHECK: debug_value %{{[0-9]+}} : $@callee_guaranteed (@noescape @callee_guaranteed (@in_guaranteed Any) -> ()) -> (), let, name "x" func testCovariantAssocProperty7(p: any P) { let x = p.covariantAssocProperty7 } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty81pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", P\) Self]] +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", any P\) Self]] // CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $[[OPENED_TY]] // CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*[[OPENED_TY]] // CHECK: [[WITNESS:%[0-9]+]] = witness_method $[[OPENED_TY]], #P.covariantAssocProperty8!getter : (Self) -> () -> ((Self.A...) -> ()) -> () @@ -534,88 +534,88 @@ func testCovariantAssocProperty8(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript11pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Any, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> Self.A -// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*Any, $@opened([[OPENED_ID]], P) Self.A -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[DEST]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> Self.A +// CHECK: [[DEST:%[0-9]+]] = init_existential_addr [[LET]] : $*Any, $@opened([[OPENED_ID]], any P) Self.A +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[DEST]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A func testCovariantAssocSubscript1(p: any P) { let x = p[covariantAssocSubscript1: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript21pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $Optional, let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> Self.A? -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>(%{{[0-9]+}}, [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.A> -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> Self.A? +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>(%{{[0-9]+}}, [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.A> +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A func testCovariantAssocSubscript2(p: any P) { let x = p[covariantAssocSubscript2: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript31pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> Self.A.Type -// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.A.Type -// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], P) Self.A).Type, $@thick Any.Type -// CHECK: debug_value [[EXIST_META]] : $@thick Any.Type, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> Self.A.Type +// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.A.Type +// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], any P) Self.A).Type, $@thick any Any.Type +// CHECK: debug_value [[EXIST_META]] : $@thick any Any.Type, let, name "x" func testCovariantAssocSubscript3(p: any P) { let x = p[covariantAssocSubscript3: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript41pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] $(Any, Any), let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> (Self.A, Self.A) -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>(%{{[0-9]+}}, %{{[0-9]+}}, [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0.A, @out τ_0_0.A) -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A -// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], P) Self.A +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> (Self.A, Self.A) +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>(%{{[0-9]+}}, %{{[0-9]+}}, [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0.A, @out τ_0_0.A) +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A +// CHECK: init_existential_addr %{{[0-9]+}} : $*Any, $@opened([[OPENED_ID]], any P) Self.A func testCovariantAssocSubscript4(p: any P) { let x = p[covariantAssocSubscript4: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript51pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> Array -// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0.A> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> Array +// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0.A> // CHECK: [[ARRAY_UPCAST_FN:%[0-9]+]] = function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], P) Self.A, Any>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> +// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], any P) Self.A, Any>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> // CHECK: debug_value %{{[0-9]+}} : $Array, let, name "x" func testCovariantAssocSubscript5(p: any P) { let x = p[covariantAssocSubscript5: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript61pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> (()) -> [String : Self.A] -// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> (()) -> [String : Self.A] +// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary // CHECK: [[DICT_UPCAST_FN:%[0-9]+]] = function_ref @$ss17_dictionaryUpCastySDyq0_q1_GSDyxq_GSHRzSHR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> +// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> // CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" func testCovariantAssocSubscript6(p: any P) { let x = p[covariantAssocSubscript6: ()] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript71pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P) Self +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P) Self // CHECK: [[THUNK:%[0-9]+]] = function_ref @$sypIgn_1A42existential_member_accesses_self_assoctype1PPQzIegn_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0.A, @noescape @callee_guaranteed (@in_guaranteed Any) -> ()) -> () -// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], P) Self> -// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], P) Self.A) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P) Self.A> +// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<@opened([[OPENED_ID]], any P) Self> +// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], any P) Self.A) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P) Self.A> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], P) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], P) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P) Self, #P.subscript!getter : (Self) -> ((Self.A) -> ()) -> () -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P) Self>([[STEP3]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () +// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $@opened([[OPENED_ID]], any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENED_COPY]] : $*@opened([[OPENED_ID]], any P) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P) Self, #P.subscript!getter : (Self) -> ((Self.A) -> ()) -> () +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[STEP3]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () func testCovariantAssocSubscript7(p: any P) { _ = p[covariantAssocSubscript7: { _ in }] } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript81pyAA1P_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", P\) Self]] +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P to $*[[OPENED_TY:@opened\("[0-9A-F-]+", any P\) Self]] // CHECK: [[THUNK:%[0-9]+]] = function_ref @[[ASSOCTYPE_ARRAY_THUNK_NAME]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed Array<τ_0_0.A>, @noescape @callee_guaranteed (@guaranteed Array) -> ()) -> () // CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]<[[OPENED_TY]]> // CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@guaranteed Array<[[OPENED_TY]].A>) -> () to $@callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 == τ_0_1> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]].A, [[OPENED_TY]].A> @@ -636,78 +636,78 @@ class Class {} protocol P2: P where A: Class & P {} // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype36testCovariantAssocMethod1Constrained2p2yAA2P2_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P2) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P2) Self, #P.covariantAssocMethod1 : (Self) -> () -> Self.A -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P2) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A -// CHECK: init_existential_ref %{{[0-9]+}} : $@opened([[OPENED_ID]], P2) Self.A : $@opened([[OPENED_ID]], P2) Self.A, $Class & P -// CHECK: debug_value %{{[0-9]+}} : $Class & P, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P2) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P2) Self, #P.covariantAssocMethod1 : (Self) -> () -> Self.A +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P2) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A +// CHECK: init_existential_ref %{{[0-9]+}} : $@opened([[OPENED_ID]], any P2) Self.A : $@opened([[OPENED_ID]], any P2) Self.A, $any Class & P +// CHECK: debug_value %{{[0-9]+}} : $any Class & P, let, name "x" func testCovariantAssocMethod1Constrained(p2: any P2) { let x = p2.covariantAssocMethod1() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype36testCovariantAssocMethod2Constrained2p2yAA2P2_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P2) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P2) Self, #P.covariantAssocMethod2 : (Self) -> () -> Self.A? -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P2) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.A> -// CHECK: init_existential_ref %{{[0-9]+}} : $@opened([[OPENED_ID]], P2) Self.A : $@opened([[OPENED_ID]], P2) Self.A, $Class & P -// CHECK: debug_value %{{[0-9]+}} : $Optional, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P2) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P2) Self, #P.covariantAssocMethod2 : (Self) -> () -> Self.A? +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P2) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0.A> +// CHECK: init_existential_ref %{{[0-9]+}} : $@opened([[OPENED_ID]], any P2) Self.A : $@opened([[OPENED_ID]], any P2) Self.A, $any Class & P +// CHECK: debug_value %{{[0-9]+}} : $Optional, let, name "x" func testCovariantAssocMethod2Constrained(p2: any P2) { let x = p2.covariantAssocMethod2() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype36testCovariantAssocMethod3Constrained2p2yAA2P2_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P2) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P2) Self, #P.covariantAssocMethod3 : (Self) -> () -> Self.A.Type -// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P2) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.A.Type -// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], P2) Self.A).Type, $@thick (Class & P).Type -// CHECK: debug_value [[EXIST_META]] : $@thick (Class & P).Type, let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P2) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P2) Self, #P.covariantAssocMethod3 : (Self) -> () -> Self.A.Type +// CHECK: [[META:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P2) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @thick τ_0_0.A.Type +// CHECK: [[EXIST_META:%[0-9]+]] = init_existential_metatype [[META]] : $@thick (@opened([[OPENED_ID]], any P2) Self.A).Type, $@thick any (Class & P).Type +// CHECK: debug_value [[EXIST_META]] : $@thick any (Class & P).Type, let, name "x" func testCovariantAssocMethod3Constrained(p2: any P2) { let x = p2.covariantAssocMethod3() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype36testCovariantAssocMethod4Constrained2p2yAA2P2_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P2) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P2) Self, #P.covariantAssocMethod4 : (Self) -> () -> (Self.A, Self.A) -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P2) Self>(%{{[0-9]+}}, %{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0.A, @out τ_0_0.A) -// CHECK: init_existential_ref %{{[0-9]+}} : $@opened([[OPENED_ID]], P2) Self.A : $@opened([[OPENED_ID]], P2) Self.A, $Class & P -// CHECK: init_existential_ref %{{[0-9]+}} : $@opened([[OPENED_ID]], P2) Self.A : $@opened([[OPENED_ID]], P2) Self.A, $Class & P -// CHECK: debug_value %{{[0-9]+}} : $(Class & P, Class & P), let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P2) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P2) Self, #P.covariantAssocMethod4 : (Self) -> () -> (Self.A, Self.A) +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P2) Self>(%{{[0-9]+}}, %{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (@out τ_0_0.A, @out τ_0_0.A) +// CHECK: init_existential_ref %{{[0-9]+}} : $@opened([[OPENED_ID]], any P2) Self.A : $@opened([[OPENED_ID]], any P2) Self.A, $any Class & P +// CHECK: init_existential_ref %{{[0-9]+}} : $@opened([[OPENED_ID]], any P2) Self.A : $@opened([[OPENED_ID]], any P2) Self.A, $any Class & P +// CHECK: debug_value %{{[0-9]+}} : $(any Class & P, any Class & P), let, name "x" func testCovariantAssocMethod4Constrained(p2: any P2) { let x = p2.covariantAssocMethod4() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype36testCovariantAssocMethod5Constrained2p2yAA2P2_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P2) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P2) Self, #P.covariantAssocMethod5 : (Self) -> () -> Array -// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P2) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0.A> +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P2) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P2) Self, #P.covariantAssocMethod5 : (Self) -> () -> Array +// CHECK: [[ARRAY:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P2) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Array<τ_0_0.A> // CHECK: [[ARRAY_UPCAST_FN:%[0-9]+]] = function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], P2) Self.A, Class & P>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> -// CHECK: debug_value %{{[0-9]+}} : $Array, let, name "x" +// CHECK: [[RESULT:%[0-9]+]] = apply [[ARRAY_UPCAST_FN]]<@opened([[OPENED_ID]], any P2) Self.A, any Class & P>([[ARRAY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> +// CHECK: debug_value %{{[0-9]+}} : $Array, let, name "x" func testCovariantAssocMethod5Constrained(p2: any P2) { let x = p2.covariantAssocMethod5() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype36testCovariantAssocMethod6Constrained2p2yAA2P2_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P2) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P2) Self, #P.covariantAssocMethod6 : (Self) -> () -> [String : Self.A] -// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P2) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P2) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P2) Self, #P.covariantAssocMethod6 : (Self) -> () -> [String : Self.A] +// CHECK: [[DICT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P2) Self>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Dictionary // CHECK: [[DICT_UPCAST_FN:%[0-9]+]] = function_ref @$ss17_dictionaryUpCastySDyq0_q1_GSDyxq_GSHRzSHR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> -// CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" +// CHECK: [[RESULT:%[0-9]+]] = apply [[DICT_UPCAST_FN]]([[DICT]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> +// CHECK: debug_value %{{[0-9]+}} : $Dictionary, let, name "x" func testCovariantAssocMethod6Constrained(p2: any P2) { let x = p2.covariantAssocMethod6() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype36testCovariantAssocMethod7Constrained2p2yAA2P2_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P2) Self +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P2 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P2) Self // CHECK: function_ref thunk for @callee_guaranteed (@guaranteed Class & P) -> () -// CHECK-NEXT: [[THUNK1:%[0-9]+]] = function_ref @$s42existential_member_accesses_self_assoctype1P_AA5ClassCXcIgg_1AAaBPQzIegg_AA2P2RzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P2> (@guaranteed τ_0_0.A, @noescape @callee_guaranteed (@guaranteed Class & P) -> ()) -> () -// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK1]]<@opened([[OPENED_ID]], P2) Self> -// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@guaranteed @opened([[OPENED_ID]], P2) Self.A) -> () to $@callee_guaranteed @substituted <τ_0_0 where τ_0_0 : _NativeClass> (@guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P2) Self.A> +// CHECK-NEXT: [[THUNK1:%[0-9]+]] = function_ref @$s42existential_member_accesses_self_assoctype1P_AA5ClassCXcIgg_1AAaBPQzIegg_AA2P2RzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P2> (@guaranteed τ_0_0.A, @noescape @callee_guaranteed (@guaranteed any Class & P) -> ()) -> () +// CHECK: [[STEP1:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK1]]<@opened([[OPENED_ID]], any P2) Self> +// CHECK: [[STEP2:%[0-9]+]] = convert_function [[STEP1]] : $@callee_guaranteed (@guaranteed @opened([[OPENED_ID]], any P2) Self.A) -> () to $@callee_guaranteed @substituted <τ_0_0 where τ_0_0 : _NativeClass> (@guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P2) Self.A> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] -// CHECK: [[STEP4:%[0-9]+]] = convert_function [[STEP3]] : $@noescape @callee_guaranteed @substituted <τ_0_0 where τ_0_0 : _NativeClass> (@guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P2) Self.A> to $@noescape @callee_guaranteed (@guaranteed @opened([[OPENED_ID]], P2) Self.A) -> () +// CHECK: [[STEP4:%[0-9]+]] = convert_function [[STEP3]] : $@noescape @callee_guaranteed @substituted <τ_0_0 where τ_0_0 : _NativeClass> (@guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P2) Self.A> to $@noescape @callee_guaranteed (@guaranteed @opened([[OPENED_ID]], any P2) Self.A) -> () // FIXME: 'A.P.A' is a rather weird way to print (@opened P2).A // CHECK: function_ref thunk for @callee_guaranteed (@guaranteed A.P.A) -> () // CHECK: [[THUNK2:%[0-9]+]] = function_ref @$s1A42existential_member_accesses_self_assoctype1PPQzIgg_AEIegn_AB2P2RzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P2> (@in_guaranteed τ_0_0.A, @noescape @callee_guaranteed (@guaranteed τ_0_0.A) -> ()) -> () -// CHECK: [[STEP5:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK2]]<@opened([[OPENED_ID]], P2) Self>([[STEP4]]) -// CHECK: [[STEP6:%[0-9]+]] = convert_function [[STEP5]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], P2) Self.A) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], P2) Self.A> +// CHECK: [[STEP5:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK2]]<@opened([[OPENED_ID]], any P2) Self>([[STEP4]]) +// CHECK: [[STEP6:%[0-9]+]] = convert_function [[STEP5]] : $@callee_guaranteed (@in_guaranteed @opened([[OPENED_ID]], any P2) Self.A) -> () to $@callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P2) Self.A> // CHECK: [[STEP7:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP6]] -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P2) Self, #P.covariantAssocMethod7 : (Self) -> ((Self.A) -> ()) -> () -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P2) Self>([[STEP7]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P2) Self, #P.covariantAssocMethod7 : (Self) -> ((Self.A) -> ()) -> () +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P2) Self>([[STEP7]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () func testCovariantAssocMethod7Constrained(p2: any P2) { p2.covariantAssocMethod7 { _ in } } @@ -723,26 +723,26 @@ protocol P3: P where A == Bool { // ----------------------------------------------------------------------------- // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype33testCovariantAssocMethod1Concrete2p3yAA2P3_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P3 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P3) Self +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P3 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P3) Self // CHECK: [[BOOL_ADDR:%[0-9]+]] = alloc_stack $Bool -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P3) Self, #P.covariantAssocMethod1 : (Self) -> () -> Self.A -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P3) Self>([[BOOL_ADDR]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P3) Self, #P.covariantAssocMethod1 : (Self) -> () -> Self.A +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P3) Self>([[BOOL_ADDR]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A // CHECK: [[BOOL:%[0-9]+]] = load [trivial] [[BOOL_ADDR]] : $*Bool // CHECK: debug_value [[BOOL]] : $Bool, let, name "x" func testCovariantAssocMethod1Concrete(p3: any P3) { let x = p3.covariantAssocMethod1() } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype37testContravariantAssocMethod1Concrete2p3yAA2P3_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P3 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P3) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P3) Self, #P3.contravariantAssocMethod1 : (Self) -> (Self.A) -> () -// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], P3) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P3) <τ_0_0 where τ_0_0 : P3> (Bool, @in_guaranteed τ_0_0) -> () +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P3 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P3) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P3) Self, #P3.contravariantAssocMethod1 : (Self) -> (Self.A) -> () +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P3) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P3) <τ_0_0 where τ_0_0 : P3> (Bool, @in_guaranteed τ_0_0) -> () func testContravariantAssocMethod1Concrete(p3: any P3) { p3.contravariantAssocMethod1(true) } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype33testInvariantAssocMethod1Concrete2p3yAA2P3_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P3 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P3) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P3) Self, #P3.invariantAssocMethod1 : (Self) -> () -> GenericStruct -// CHECK: [[RESULT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], P3) Self>([[OPENED]]) : $@convention(witness_method: P3) <τ_0_0 where τ_0_0 : P3> (@in_guaranteed τ_0_0) -> GenericStruct +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P3 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P3) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P3) Self, #P3.invariantAssocMethod1 : (Self) -> () -> GenericStruct +// CHECK: [[RESULT:%[0-9]+]] = apply [[WITNESS]]<@opened([[OPENED_ID]], any P3) Self>([[OPENED]]) : $@convention(witness_method: P3) <τ_0_0 where τ_0_0 : P3> (@in_guaranteed τ_0_0) -> GenericStruct // CHECK: debug_value [[RESULT]] : $GenericStruct, let, name "x" func testInvariantAssocMethod1Concrete(p3: any P3) { let x = p3.invariantAssocMethod1() @@ -757,12 +757,12 @@ protocol P4: P where A == (B, B) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype42testCovariantAssocMethod1PartiallyConcrete2p4yAA2P4_p_tF -// CHECK: alloc_stack [lexical] $(P4, P4), let, name "x" -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*P4 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], P4) Self -// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], P4) Self, #P.covariantAssocMethod1 : (Self) -> () -> Self.A -// CHECK: apply %4<@opened([[OPENED_ID]], P4) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A -// CHECK: init_existential_addr %{{[0-9]+}} : $*P4, $@opened([[OPENED_ID]], P4) Self.B -// CHECK: init_existential_addr %{{[0-9]+}} : $*P4, $@opened([[OPENED_ID]], P4) Self.B +// CHECK: alloc_stack [lexical] $(any P4, any P4), let, name "x" +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access %0 : $*any P4 to $*@opened([[OPENED_ID:"[0-9A-F-]+"]], any P4) Self +// CHECK: [[WITNESS:%[0-9]+]] = witness_method $@opened([[OPENED_ID]], any P4) Self, #P.covariantAssocMethod1 : (Self) -> () -> Self.A +// CHECK: apply %4<@opened([[OPENED_ID]], any P4) Self>(%{{[0-9]+}}, [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0.A +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P4, $@opened([[OPENED_ID]], any P4) Self.B +// CHECK: init_existential_addr %{{[0-9]+}} : $*any P4, $@opened([[OPENED_ID]], any P4) Self.B func testCovariantAssocMethod1PartiallyConcrete(p4: any P4) { let x = p4.covariantAssocMethod1() } diff --git a/test/SILGen/existential_metatypes.swift b/test/SILGen/existential_metatypes.swift index f80e01aa5988c..cfa7ffdad71a4 100644 --- a/test/SILGen/existential_metatypes.swift +++ b/test/SILGen/existential_metatypes.swift @@ -20,24 +20,24 @@ struct S: P { } // CHECK-LABEL: sil hidden [ossa] @$s21existential_metatypes0A8MetatypeyyAA1P_pF -// CHECK: bb0([[X:%.*]] : $*P): +// CHECK: bb0([[X:%.*]] : $*any P): func existentialMetatype(_ x: P) { - // CHECK: [[TYPE1:%.*]] = existential_metatype $@thick P.Type, [[X]] + // CHECK: [[TYPE1:%.*]] = existential_metatype $@thick any P.Type, [[X]] let type1 = type(of: x) - // CHECK: [[INSTANCE1:%.*]] = alloc_stack [lexical] $P + // CHECK: [[INSTANCE1:%.*]] = alloc_stack [lexical] $any P // CHECK: [[OPEN_TYPE1:%.*]] = open_existential_metatype [[TYPE1]] // CHECK: [[INIT:%.*]] = witness_method {{.*}} #P.init!allocator - // CHECK: [[INSTANCE1_VALUE:%.*]] = init_existential_addr [[INSTANCE1]] : $*P + // CHECK: [[INSTANCE1_VALUE:%.*]] = init_existential_addr [[INSTANCE1]] : $*any P // CHECK: apply [[INIT]]<{{.*}}>([[INSTANCE1_VALUE]], [[OPEN_TYPE1]]) let instance1 = type1.init() // CHECK: [[S:%.*]] = metatype $@thick S.Type - // CHECK: [[TYPE2:%.*]] = init_existential_metatype [[S]] : $@thick S.Type, $@thick P.Type + // CHECK: [[TYPE2:%.*]] = init_existential_metatype [[S]] : $@thick S.Type, $@thick any P.Type let type2: P.Type = S.self - // CHECK: [[INSTANCE2:%.*]] = alloc_stack [lexical] $P + // CHECK: [[INSTANCE2:%.*]] = alloc_stack [lexical] $any P // CHECK: [[OPEN_TYPE2:%.*]] = open_existential_metatype [[TYPE2]] // CHECK: [[STATIC_METHOD:%.*]] = witness_method {{.*}} #P.staticMethod - // CHECK: [[INSTANCE2_VALUE:%.*]] = init_existential_addr [[INSTANCE2]] : $*P + // CHECK: [[INSTANCE2_VALUE:%.*]] = init_existential_addr [[INSTANCE2]] : $*any P // CHECK: apply [[STATIC_METHOD]]<{{.*}}>([[INSTANCE2_VALUE]], [[OPEN_TYPE2]]) let instance2 = type2.staticMethod() } @@ -64,9 +64,9 @@ func existentialMetatypeUpcast2(_ x: (P & Q).Type) -> P.Type { // rdar://32288618 // CHECK-LABEL: sil hidden [ossa] @$s21existential_metatypes0A19MetatypeVarPropertyAA5ValueVyF : $@convention(thin) () -> Value func existentialMetatypeVarProperty() -> Value { - // CHECK: [[BOX:%.*]] = alloc_box ${ var @thick P.Type } + // CHECK: [[BOX:%.*]] = alloc_box ${ var @thick any P.Type } // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK: [[ADDR:%.*]] = project_box [[BOX_LIFETIME]] : ${ var @thick P.Type }, 0 + // CHECK: [[ADDR:%.*]] = project_box [[BOX_LIFETIME]] : ${ var @thick any P.Type }, 0 // CHECK: [[T0:%.*]] = metatype $@thick S.Type // CHECK: [[T1:%.*]] = init_existential_metatype [[T0]] // CHECK: store [[T1]] to [trivial] [[ADDR]] : @@ -82,8 +82,8 @@ func existentialMetatypeVarProperty() -> Value { var _type: P.Type { get {return S.self } set {} } func getterResultStaticStorageAccess() { // CHECK: [[GET_TYPE:%.*]] = function_ref @$s21existential_metatypes5_typeAA1P_pXpvg - // CHECK-NEXT: [[TYPE:%.*]] = apply [[GET_TYPE]]() : $@convention(thin) () -> @thick P.Type - // CHECK-NEXT: [[OPEN:%.*]] = open_existential_metatype [[TYPE]] : $@thick P.Type to $@thick ([[ARCHETYPE:@opened\(.*, P\) Self]]).Type + // CHECK-NEXT: [[TYPE:%.*]] = apply [[GET_TYPE]]() : $@convention(thin) () -> @thick any P.Type + // CHECK-NEXT: [[OPEN:%.*]] = open_existential_metatype [[TYPE]] : $@thick any P.Type to $@thick ([[ARCHETYPE:@opened\(.*, any P\) Self]]).Type // CHECK-NEXT: [[GET_VALUE:%.*]] = witness_method $[[ARCHETYPE]], #P.value!getter // CHECK-NEXT: [[VALUE:%.*]] = apply [[GET_VALUE]]<[[ARCHETYPE]]>([[OPEN]]) // CHECK-NEXT: // function_ref diff --git a/test/SILGen/foreach.swift b/test/SILGen/foreach.swift index 47ca842a76c67..e4115ead83f99 100644 --- a/test/SILGen/foreach.swift +++ b/test/SILGen/foreach.swift @@ -206,27 +206,27 @@ func existentialBreak(_ xx: [P]) { funcEnd() } -// CHECK-LABEL: sil hidden [ossa] @$s7foreach24existentialContinueBreakyySayAA1P_pGF : $@convention(thin) (@guaranteed Array

) -> () { -// CHECK: bb0([[ARRAY:%.*]] : @guaranteed $Array

): -// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator> }, var, name "$x$generator" +// CHECK-LABEL: sil hidden [ossa] @$s7foreach24existentialContinueBreakyySayAA1P_pGF : $@convention(thin) (@guaranteed Array) -> () { +// CHECK: bb0([[ARRAY:%.*]] : @guaranteed $Array): +// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator> }, var, name "$x$generator" // CHECK: [[ITERATOR_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[ITERATOR_BOX]] // CHECK: [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_LIFETIME]] -// CHECK: [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array

+// CHECK: [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array // CHECK: store [[ARRAY_COPY:%.*]] to [init] [[BORROWED_ARRAY_STACK]] // CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @$sSlss16IndexingIteratorVyxG0B0RtzrlE04makeB0ACyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in τ_0_0) -> @out IndexingIterator<τ_0_0> -// CHECK: apply [[MAKE_ITERATOR_FUNC]]<[P]>([[PROJECT_ITERATOR_BOX]], [[BORROWED_ARRAY_STACK]]) -// CHECK: [[ELT_STACK:%.*]] = alloc_stack $Optional

+// CHECK: apply [[MAKE_ITERATOR_FUNC]]<[any P]>([[PROJECT_ITERATOR_BOX]], [[BORROWED_ARRAY_STACK]]) +// CHECK: [[ELT_STACK:%.*]] = alloc_stack $Optional // CHECK: br [[LOOP_DEST:bb[0-9]+]] // // CHECK: [[LOOP_DEST]]: -// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator> +// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator> // CHECK: [[FUNC_REF:%.*]] = function_ref @$ss16IndexingIteratorV4next7ElementQzSgyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection> (@inout IndexingIterator<τ_0_0>) -> @out Optional<τ_0_0.Element> -// CHECK: apply [[FUNC_REF]]<[P]>([[ELT_STACK]], [[WRITE]]) -// CHECK: switch_enum_addr [[ELT_STACK]] : $*Optional

, case #Optional.some!enumelt: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]] +// CHECK: apply [[FUNC_REF]]<[any P]>([[ELT_STACK]], [[WRITE]]) +// CHECK: switch_enum_addr [[ELT_STACK]] : $*Optional, case #Optional.some!enumelt: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]] // // CHECK: [[SOME_BB]]: -// CHECK: [[T0:%.*]] = alloc_stack [lexical] $P, let, name "x" -// CHECK: [[ELT_STACK_TAKE:%.*]] = unchecked_take_enum_data_addr [[ELT_STACK]] : $*Optional

, #Optional.some!enumelt +// CHECK: [[T0:%.*]] = alloc_stack [lexical] $any P, let, name "x" +// CHECK: [[ELT_STACK_TAKE:%.*]] = unchecked_take_enum_data_addr [[ELT_STACK]] : $*Optional, #Optional.some!enumelt // CHECK: copy_addr [take] [[ELT_STACK_TAKE]] to [initialization] [[T0]] // CHECK: cond_br {{%.*}}, [[LOOP_BREAK_END_BLOCK:bb[0-9]+]], [[CONTINUE_CHECK_BLOCK:bb[0-9]+]] // @@ -260,7 +260,7 @@ func existentialBreak(_ xx: [P]) { // CHECK: [[CONT_BLOCK]] // CHECK: dealloc_stack [[ELT_STACK]] // CHECK: end_borrow [[ITERATOR_LIFETIME]] -// CHECK: destroy_value [[ITERATOR_BOX]] : ${ var IndexingIterator> } +// CHECK: destroy_value [[ITERATOR_BOX]] : ${ var IndexingIterator> } // CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> () // CHECK: apply [[FUNC_END_FUNC]]() // CHECK: } // end sil function '$s7foreach24existentialContinueBreakyySayAA1P_pGF' diff --git a/test/SILGen/foreign_errors.swift b/test/SILGen/foreign_errors.swift index 1f8e49cde00be..70b867680a1df 100644 --- a/test/SILGen/foreign_errors.swift +++ b/test/SILGen/foreign_errors.swift @@ -8,7 +8,7 @@ import Foundation import errors -// CHECK-LABEL: sil hidden [ossa] @$s14foreign_errors5test0yyKF : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil hidden [ossa] @$s14foreign_errors5test0yyKF : $@convention(thin) () -> @error any Error func test0() throws { // Create a strong temporary holding nil before we perform any further parts of function emission. // CHECK: [[ERR_TEMP0:%.*]] = alloc_stack [dynamic_lifetime] $Optional @@ -49,10 +49,10 @@ func test0() throws { // Error path: fall out and rethrow. // CHECK: [[ERROR_BB]]: // CHECK: [[T0:%.*]] = load [take] [[ERR_TEMP0]] - // CHECK: [[T1:%.*]] = function_ref @$s10Foundation22_convertNSErrorToErrorys0E0_pSo0C0CSgF : $@convention(thin) (@guaranteed Optional) -> @owned Error + // CHECK: [[T1:%.*]] = function_ref @$s10Foundation22_convertNSErrorToErrorys0E0_pSo0C0CSgF : $@convention(thin) (@guaranteed Optional) -> @owned any Error // CHECK: [[T2:%.*]] = apply [[T1]]([[T0]]) - // CHECK: "willThrow"([[T2]] : $Error) - // CHECK: throw [[T2]] : $Error + // CHECK: "willThrow"([[T2]] : $any Error) + // CHECK: throw [[T2]] : $any Error } extension NSObject { @@ -60,17 +60,17 @@ extension NSObject { throw NSError(domain: "", code: 1, userInfo: [:]) } // CHECK-LABEL: sil private [thunk] [ossa] @$sSo8NSObjectC14foreign_errorsE5abortyyKFTo : $@convention(objc_method) (Optional>>, NSObject) -> ObjCBool -// CHECK: [[T0:%.*]] = function_ref @$sSo8NSObjectC14foreign_errorsE5abortyyKF : $@convention(method) (@guaranteed NSObject) -> @error Error +// CHECK: [[T0:%.*]] = function_ref @$sSo8NSObjectC14foreign_errorsE5abortyyKF : $@convention(method) (@guaranteed NSObject) -> @error any Error // CHECK: try_apply [[T0]]( // CHECK: bb1( // CHECK: [[BITS:%.*]] = integer_literal $Builtin.Int{{[18]}}, {{1|-1}} // CHECK: [[VALUE:%.*]] = struct ${{Bool|UInt8}} ([[BITS]] : $Builtin.Int{{[18]}}) // CHECK: [[BOOL:%.*]] = struct $ObjCBool ([[VALUE]] : ${{Bool|UInt8}}) // CHECK: br bb6([[BOOL]] : $ObjCBool) -// CHECK: bb2([[ERR:%.*]] : @owned $Error): +// CHECK: bb2([[ERR:%.*]] : @owned $any Error): // CHECK: switch_enum %0 : $Optional>>, case #Optional.some!enumelt: bb3, case #Optional.none!enumelt: bb4 // CHECK: bb3([[UNWRAPPED_OUT:%.+]] : $AutoreleasingUnsafeMutablePointer>): -// CHECK: [[T0:%.*]] = function_ref @$s10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF : $@convention(thin) (@guaranteed Error) -> @owned NSError +// CHECK: [[T0:%.*]] = function_ref @$s10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF : $@convention(thin) (@guaranteed any Error) -> @owned NSError // CHECK: [[T1:%.*]] = apply [[T0]]([[ERR]]) // CHECK: [[OBJCERR:%.*]] = enum $Optional, #Optional.some!enumelt, [[T1]] : $NSError // CHECK: [[TEMP:%.*]] = alloc_stack $Optional @@ -80,7 +80,7 @@ extension NSObject { // CHECK: dealloc_stack [[TEMP]] // CHECK: br bb5 // CHECK: bb4: -// CHECK: destroy_value [[ERR]] : $Error +// CHECK: destroy_value [[ERR]] : $any Error // CHECK: br bb5 // CHECK: bb5: // CHECK: [[BITS:%.*]] = integer_literal $Builtin.Int{{[18]}}, 0 @@ -97,8 +97,8 @@ extension NSObject { // CHECK: bb0([[UNOWNED_ARG0:%.*]] : $Optional>>, [[UNOWNED_ARG1:%.*]] : @unowned $NSObject): // CHECK: [[ARG1:%.*]] = copy_value [[UNOWNED_ARG1]] // CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]] -// CHECK: [[T0:%.*]] = function_ref @$sSo8NSObjectC14foreign_errorsE14badDescriptionSSyKF : $@convention(method) (@guaranteed NSObject) -> (@owned String, @error Error) -// CHECK: try_apply [[T0]]([[BORROWED_ARG1]]) : $@convention(method) (@guaranteed NSObject) -> (@owned String, @error Error), normal [[NORMAL_BB:bb[0-9][0-9]*]], error [[ERROR_BB:bb[0-9][0-9]*]] +// CHECK: [[T0:%.*]] = function_ref @$sSo8NSObjectC14foreign_errorsE14badDescriptionSSyKF : $@convention(method) (@guaranteed NSObject) -> (@owned String, @error any Error) +// CHECK: try_apply [[T0]]([[BORROWED_ARG1]]) : $@convention(method) (@guaranteed NSObject) -> (@owned String, @error any Error), normal [[NORMAL_BB:bb[0-9][0-9]*]], error [[ERROR_BB:bb[0-9][0-9]*]] // // CHECK: [[NORMAL_BB]]([[RESULT:%.*]] : @owned $String): // CHECK: [[T0:%.*]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString @@ -109,11 +109,11 @@ extension NSObject { // CHECK: destroy_value [[RESULT]] // CHECK: br bb6([[T2]] : $Optional) // -// CHECK: [[ERROR_BB]]([[ERR:%.*]] : @owned $Error): +// CHECK: [[ERROR_BB]]([[ERR:%.*]] : @owned $any Error): // CHECK: switch_enum [[UNOWNED_ARG0]] : $Optional>>, case #Optional.some!enumelt: [[SOME_BB:bb[0-9][0-9]*]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9][0-9]*]] // // CHECK: [[SOME_BB]]([[UNWRAPPED_OUT:%.+]] : $AutoreleasingUnsafeMutablePointer>): -// CHECK: [[T0:%.*]] = function_ref @$s10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF : $@convention(thin) (@guaranteed Error) -> @owned NSError +// CHECK: [[T0:%.*]] = function_ref @$s10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF : $@convention(thin) (@guaranteed any Error) -> @owned NSError // CHECK: [[T1:%.*]] = apply [[T0]]([[ERR]]) // CHECK: [[OBJCERR:%.*]] = enum $Optional, #Optional.some!enumelt, [[T1]] : $NSError // CHECK: [[TEMP:%.*]] = alloc_stack $Optional @@ -124,7 +124,7 @@ extension NSObject { // CHECK: br bb5 // // CHECK: [[NONE_BB]]: -// CHECK: destroy_value [[ERR]] : $Error +// CHECK: destroy_value [[ERR]] : $any Error // CHECK: br bb5 // // CHECK: bb5: @@ -148,12 +148,12 @@ extension NSObject { } let fn = ErrorProne.fail -// CHECK-LABEL: sil private [ossa] @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_ : $@convention(thin) (@thick ErrorProne.Type) -> @owned @callee_guaranteed () -> @error Error { -// CHECK: [[T0:%.*]] = function_ref @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_yyKcfu0_ : $@convention(thin) (@thick ErrorProne.Type) -> @error Error +// CHECK-LABEL: sil private [ossa] @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_ : $@convention(thin) (@thick ErrorProne.Type) -> @owned @callee_guaranteed () -> @error any Error { +// CHECK: [[T0:%.*]] = function_ref @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_yyKcfu0_ : $@convention(thin) (@thick ErrorProne.Type) -> @error any Error // CHECK-NEXT: [[T1:%.*]] = partial_apply [callee_guaranteed] [[T0]](%0) // CHECK-NEXT: return [[T1]] -// CHECK-LABEL: sil private [ossa] @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_yyKcfu0_ : $@convention(thin) (@thick ErrorProne.Type) -> @error Error { +// CHECK-LABEL: sil private [ossa] @$s14foreign_errors2fnyyKcvpfiyyKcSo10ErrorProneCmcfu_yyKcfu0_ : $@convention(thin) (@thick ErrorProne.Type) -> @error any Error { // CHECK: [[TEMP:%.*]] = alloc_stack [dynamic_lifetime] $Optional // CHECK: [[SELF:%.*]] = thick_to_objc_metatype %0 : $@thick ErrorProne.Type to $@objc_metatype ErrorProne.Type // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $@objc_metatype ErrorProne.Type, #ErrorProne.fail!foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional>>, @objc_metatype ErrorProne.Type) -> ObjCBool @@ -162,21 +162,21 @@ let fn = ErrorProne.fail // CHECK: return // CHECK: [[T0:%.*]] = load [take] [[TEMP]] // CHECK: [[T1:%.*]] = apply {{%.*}}([[T0]]) -// CHECK: "willThrow"([[T1]] : $Error) +// CHECK: "willThrow"([[T1]] : $any Error) // CHECK: throw [[T1]] func testArgs() throws { try ErrorProne.consume(nil) } -// CHECK-LABEL: sil hidden [ossa] @$s14foreign_errors8testArgsyyKF : $@convention(thin) () -> @error Error -// CHECK: debug_value undef : $Error, var, name "$error", argno 1 +// CHECK-LABEL: sil hidden [ossa] @$s14foreign_errors8testArgsyyKF : $@convention(thin) () -> @error any Error +// CHECK: debug_value undef : $any Error, var, name "$error", argno 1 // CHECK: objc_method {{.*}} : $@objc_metatype ErrorProne.Type, #ErrorProne.consume!foreign : (ErrorProne.Type) -> (Any?) throws -> (), $@convention(objc_method) (Optional, Optional>>, @objc_metatype ErrorProne.Type) -> ObjCBool func testBridgedResult() throws { let array = try ErrorProne.collection(withCount: 0) } -// CHECK-LABEL: sil hidden [ossa] @$s14foreign_errors17testBridgedResultyyKF : $@convention(thin) () -> @error Error { -// CHECK: debug_value undef : $Error, var, name "$error", argno 1 +// CHECK-LABEL: sil hidden [ossa] @$s14foreign_errors17testBridgedResultyyKF : $@convention(thin) () -> @error any Error { +// CHECK: debug_value undef : $any Error, var, name "$error", argno 1 // CHECK: objc_method {{.*}} : $@objc_metatype ErrorProne.Type, #ErrorProne.collection!foreign : (ErrorProne.Type) -> (Int) throws -> [Any], $@convention(objc_method) (Int, Optional>>, @objc_metatype ErrorProne.Type) -> @autoreleased Optional // CHECK: } // end sil function '$s14foreign_errors17testBridgedResultyyKF' @@ -213,15 +213,15 @@ class VeryErrorProne : ErrorProne { // CHECK: } // end sil function '$s14foreign_errors14VeryErrorProneC7withTwoACyXlSg_tKcfc' // rdar://21051021 -// CHECK: sil hidden [ossa] @$s14foreign_errors12testProtocolyySo010ErrorProneD0_pKF : $@convention(thin) (@guaranteed ErrorProneProtocol) -> @error Error -// CHECK: bb0([[ARG0:%.*]] : @guaranteed $ErrorProneProtocol): +// CHECK: sil hidden [ossa] @$s14foreign_errors12testProtocolyySo010ErrorProneD0_pKF : $@convention(thin) (@guaranteed any ErrorProneProtocol) -> @error any Error +// CHECK: bb0([[ARG0:%.*]] : @guaranteed $any ErrorProneProtocol): func testProtocol(_ p: ErrorProneProtocol) throws { - // CHECK: [[T0:%.*]] = open_existential_ref [[ARG0]] : $ErrorProneProtocol to $[[OPENED:@opened\(.*, ErrorProneProtocol\) Self]] + // CHECK: [[T0:%.*]] = open_existential_ref [[ARG0]] : $any ErrorProneProtocol to $[[OPENED:@opened\(.*, any ErrorProneProtocol\) Self]] // CHECK: [[T1:%.*]] = objc_method [[T0]] : $[[OPENED]], #ErrorProneProtocol.obliterate!foreign : {{.*}} // CHECK: apply [[T1]]<[[OPENED]]>({{%.*}}, [[T0]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : ErrorProneProtocol> (Optional>>, τ_0_0) -> ObjCBool try p.obliterate() - // CHECK: [[T0:%.*]] = open_existential_ref [[ARG0]] : $ErrorProneProtocol to $[[OPENED:@opened\(.*, ErrorProneProtocol\) Self]] + // CHECK: [[T0:%.*]] = open_existential_ref [[ARG0]] : $any ErrorProneProtocol to $[[OPENED:@opened\(.*, any ErrorProneProtocol\) Self]] // CHECK: [[T1:%.*]] = objc_method [[T0]] : $[[OPENED]], #ErrorProneProtocol.invigorate!foreign : {{.*}} // CHECK: apply [[T1]]<[[OPENED]]>({{%.*}}, {{%.*}}, [[T0]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : ErrorProneProtocol> (Optional>>, Optional<@convention(block) () -> ()>, τ_0_0) -> ObjCBool try p.invigorate(callback: {}) diff --git a/test/SILGen/function_conversion.swift b/test/SILGen/function_conversion.swift index 618d45c7e3c18..5cd4a3734e117 100644 --- a/test/SILGen/function_conversion.swift +++ b/test/SILGen/function_conversion.swift @@ -25,19 +25,19 @@ func cToBlock(_ arg: @escaping @convention(c) (Int) -> Int) -> @convention(block // ==== Throws variance -// CHECK-LABEL: sil hidden [ossa] @$s19function_conversion12funcToThrowsyyyKcyycF : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @owned @callee_guaranteed () -> @error Error +// CHECK-LABEL: sil hidden [ossa] @$s19function_conversion12funcToThrowsyyyKcyycF : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @owned @callee_guaranteed () -> @error any Error // CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed () -> ()): // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] -// CHECK: [[FUNC:%.*]] = convert_function [[ARG_COPY]] : $@callee_guaranteed () -> () to $@callee_guaranteed () -> @error Error +// CHECK: [[FUNC:%.*]] = convert_function [[ARG_COPY]] : $@callee_guaranteed () -> () to $@callee_guaranteed () -> @error any Error // CHECK: return [[FUNC]] // CHECK: } // end sil function '$s19function_conversion12funcToThrowsyyyKcyycF' func funcToThrows(_ x: @escaping () -> ()) -> () throws -> () { return x } -// CHECK-LABEL: sil hidden [ossa] @$s19function_conversion12thinToThrowsyyyKXfyyXfF : $@convention(thin) (@convention(thin) () -> ()) -> @convention(thin) () -> @error Error -// CHECK: [[FUNC:%.*]] = convert_function %0 : $@convention(thin) () -> () to $@convention(thin) () -> @error Error -// CHECK: return [[FUNC]] : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil hidden [ossa] @$s19function_conversion12thinToThrowsyyyKXfyyXfF : $@convention(thin) (@convention(thin) () -> ()) -> @convention(thin) () -> @error any Error +// CHECK: [[FUNC:%.*]] = convert_function %0 : $@convention(thin) () -> () to $@convention(thin) () -> @error any Error +// CHECK: return [[FUNC]] : $@convention(thin) () -> @error any Error func thinToThrows(_ x: @escaping @convention(thin) () -> ()) -> @convention(thin) () throws -> () { return x } @@ -195,8 +195,8 @@ func convExistentialTrivial(_ t2: @escaping (Q) -> Trivial, t3: @escaping (Q?) - let _: (P) -> P = t2 } -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pAA7TrivialVIegnd_AdA1P_pIegyr_TR : $@convention(thin) (Trivial, @guaranteed @callee_guaranteed (@in_guaranteed Q) -> Trivial) -> @out P -// CHECK: alloc_stack $Q +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pAA7TrivialVIegnd_AdA1P_pIegyr_TR : $@convention(thin) (Trivial, @guaranteed @callee_guaranteed (@in_guaranteed any Q) -> Trivial) -> @out any P +// CHECK: alloc_stack $any Q // CHECK-NEXT: init_existential_addr // CHECK-NEXT: store // CHECK-NEXT: apply @@ -219,10 +219,10 @@ func convExistentialTrivial(_ t2: @escaping (Q) -> Trivial, t3: @escaping (Q?) - // CHECK: store // CHECK: return -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pAA7TrivialVIegnd_AA1P_pAaE_pIegnr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in_guaranteed Q) -> Trivial) -> @out P -// CHECK: [[TMP:%.*]] = alloc_stack $Q -// CHECK-NEXT: open_existential_addr immutable_access %1 : $*P -// CHECK-NEXT: init_existential_addr [[TMP]] : $*Q +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pAA7TrivialVIegnd_AA1P_pAaE_pIegnr_TR : $@convention(thin) (@in_guaranteed any P, @guaranteed @callee_guaranteed (@in_guaranteed any Q) -> Trivial) -> @out any P +// CHECK: [[TMP:%.*]] = alloc_stack $any Q +// CHECK-NEXT: open_existential_addr immutable_access %1 : $*any P +// CHECK-NEXT: init_existential_addr [[TMP]] : $*any Q // CHECK-NEXT: copy_addr {{.*}} to [initialization] {{.*}} // CHECK-NEXT: apply // CHECK-NEXT: init_existential_addr @@ -247,36 +247,36 @@ func convExistentialMetatype(_ em: @escaping (Q.Type?) -> Trivial.Type) { let _: (P.Type) -> P.Type = em } -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtAA1P_pXmTIegyd_TR : $@convention(thin) (@thin Trivial.Type, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtAA1P_pXmTIegyd_TR : $@convention(thin) (@thin Trivial.Type, @guaranteed @callee_guaranteed (Optional<@thick any Q.Type>) -> @thin Trivial.Type) -> @thick any P.Type // CHECK: [[META:%.*]] = metatype $@thick Trivial.Type -// CHECK-NEXT: init_existential_metatype [[META]] : $@thick Trivial.Type, $@thick Q.Type -// CHECK-NEXT: enum $Optional<@thick Q.Type> +// CHECK-NEXT: init_existential_metatype [[META]] : $@thick Trivial.Type, $@thick any Q.Type +// CHECK-NEXT: enum $Optional<@thick any Q.Type> // CHECK-NEXT: apply // CHECK-NEXT: metatype $@thick Trivial.Type -// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type +// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick any P.Type // CHECK-NEXT: return -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtSgAA1P_pXmTIegyd_TR : $@convention(thin) (Optional<@thin Trivial.Type>, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtSgAA1P_pXmTIegyd_TR : $@convention(thin) (Optional<@thin Trivial.Type>, @guaranteed @callee_guaranteed (Optional<@thick any Q.Type>) -> @thin Trivial.Type) -> @thick any P.Type // CHECK: switch_enum %0 : $Optional<@thin Trivial.Type> // CHECK: bb1([[META:%.*]] : $@thin Trivial.Type): // CHECK-NEXT: metatype $@thick Trivial.Type -// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick Q.Type -// CHECK-NEXT: enum $Optional<@thick Q.Type> +// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick any Q.Type +// CHECK-NEXT: enum $Optional<@thick any Q.Type> // CHECK: bb2: -// CHECK-NEXT: enum $Optional<@thick Q.Type> +// CHECK-NEXT: enum $Optional<@thick any Q.Type> // CHECK: bb3({{.*}}): // CHECK-NEXT: apply // CHECK-NEXT: metatype $@thick Trivial.Type -// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type +// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick any P.Type // CHECK-NEXT: return -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AA1P_pXmTAaF_pXmTIegyd_TR : $@convention(thin) (@thick P.Type, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type -// CHECK: open_existential_metatype %0 : $@thick P.Type to $@thick (@opened({{.*}}, P) Self).Type -// CHECK-NEXT: init_existential_metatype %2 : $@thick (@opened({{.*}}, P) Self).Type, $@thick Q.Type -// CHECK-NEXT: enum $Optional<@thick Q.Type> +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AA1P_pXmTAaF_pXmTIegyd_TR : $@convention(thin) (@thick any P.Type, @guaranteed @callee_guaranteed (Optional<@thick any Q.Type>) -> @thin Trivial.Type) -> @thick any P.Type +// CHECK: open_existential_metatype %0 : $@thick any P.Type to $@thick (@opened({{.*}}, any P) Self).Type +// CHECK-NEXT: init_existential_metatype %2 : $@thick (@opened({{.*}}, any P) Self).Type, $@thick any Q.Type +// CHECK-NEXT: enum $Optional<@thick any Q.Type> // CHECK-NEXT: apply %1 // CHECK-NEXT: metatype $@thick Trivial.Type -// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type +// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick any P.Type // CHECK-NEXT: return // ==== Class metatype upcasts @@ -403,7 +403,7 @@ func convClassBoundMetatypeArchetypeUpcast(_ f1: @escaping (Parent.T // CHECK: function_ref @$s19function_conversion1Q_pIegn_AA1P_pIegn_TR // CHECK: function_ref @$sSi_SitSgIegy_S2iIegyy_TR -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pIegn_AA1P_pIegn_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in_guaranteed Q) -> ()) -> () +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s19function_conversion1Q_pIegn_AA1P_pIegn_TR : $@convention(thin) (@in_guaranteed any P, @guaranteed @callee_guaranteed (@in_guaranteed any Q) -> ()) -> () // CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$sSi_SitSgIegy_S2iIegyy_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (Optional<(Int, Int)>) -> ()) -> () @@ -598,12 +598,12 @@ func rdar35702810() { let fn_map: ([Int: Z]) -> Void = { _ in } // CHECK: function_ref @$ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> - // CHECK: apply %5(%4) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> + // CHECK: apply %5(%4) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1> foo_arr(type: A.self, fn_arr) // CHECK: function_ref @$ss17_dictionaryUpCastySDyq0_q1_GSDyxq_GSHRzSHR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> - // CHECK: apply %2(%0) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> - // CHECK: apply %1(%4) : $@callee_guaranteed (@guaranteed Dictionary) -> () + // CHECK: apply %2(%0) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3> + // CHECK: apply %1(%4) : $@callee_guaranteed (@guaranteed Dictionary) -> () foo_map(type: A.self, fn_map) } diff --git a/test/SILGen/function_conversion_objc.swift b/test/SILGen/function_conversion_objc.swift index 988024812f0e4..3c009a02e229c 100644 --- a/test/SILGen/function_conversion_objc.swift +++ b/test/SILGen/function_conversion_objc.swift @@ -26,10 +26,10 @@ func convExistentialMetatypeToObject(_ f: @escaping (NSBurrito) -> NSBurrito.Typ let _: (NSBurrito) -> AnyObject = f } -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s24function_conversion_objc9NSBurrito_pAaB_pXmTIeggd_AaB_pyXlIeggo_TR : $@convention(thin) (@guaranteed NSBurrito, @guaranteed @callee_guaranteed (@guaranteed NSBurrito) -> @thick NSBurrito.Type) -> @owned AnyObject +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s24function_conversion_objc9NSBurrito_pAaB_pXmTIeggd_AaB_pyXlIeggo_TR : $@convention(thin) (@guaranteed any NSBurrito, @guaranteed @callee_guaranteed (@guaranteed any NSBurrito) -> @thick any NSBurrito.Type) -> @owned AnyObject // CHECK: apply %1(%0) -// CHECK: thick_to_objc_metatype {{.*}} : $@thick NSBurrito.Type to $@objc_metatype NSBurrito.Type -// CHECK: objc_existential_metatype_to_object {{.*}} : $@objc_metatype NSBurrito.Type to $AnyObject +// CHECK: thick_to_objc_metatype {{.*}} : $@thick any NSBurrito.Type to $@objc_metatype any NSBurrito.Type +// CHECK: objc_existential_metatype_to_object {{.*}} : $@objc_metatype any NSBurrito.Type to $AnyObject // CHECK: return // CHECK-LABEL: sil hidden [ossa] @$s24function_conversion_objc28convProtocolMetatypeToObjectyyAA9NSBurrito_pmycF @@ -39,8 +39,8 @@ func convProtocolMetatypeToObject(_ f: @escaping () -> NSBurrito.Protocol) { let _: () -> Protocol = f } -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s24function_conversion_objc9NSBurrito_pXMtIegd_So8ProtocolCIego_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @thin NSBurrito.Protocol) -> @owned Protocol -// CHECK: apply %0() : $@callee_guaranteed () -> @thin NSBurrito.Protocol +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s24function_conversion_objc9NSBurrito_pXMtIegd_So8ProtocolCIego_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @thin (any NSBurrito).Type) -> @owned Protocol +// CHECK: apply %0() : $@callee_guaranteed () -> @thin (any NSBurrito).Type // CHECK: objc_protocol #NSBurrito : $Protocol // CHECK: copy_value // CHECK: return diff --git a/test/SILGen/function_type_lowering.swift b/test/SILGen/function_type_lowering.swift index 4685b37de8927..70496a9e89944 100644 --- a/test/SILGen/function_type_lowering.swift +++ b/test/SILGen/function_type_lowering.swift @@ -16,7 +16,7 @@ func c(_ x: (V) -> T, _: U) {} // CHECK-LABEL: sil {{.*}}003Hca{{.*}} : $@convention(thin) (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for ) -> () func ç(_ x: (T) -> T) {} -// CHECK-LABEL: sil {{.*}}returnsThrowing{{.*}} : $@convention(thin) (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @error Error) for <τ_0_1, τ_0_2>) for ) -> () { +// CHECK-LABEL: sil {{.*}}returnsThrowing{{.*}} : $@convention(thin) (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @error any Error) for <τ_0_1, τ_0_2>) for ) -> () { func returnsThrowing(_ x: (T) -> (U) throws -> V) {} diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift index 504e2c0731ff1..b5c2dc3c74fd9 100644 --- a/test/SILGen/functions.swift +++ b/test/SILGen/functions.swift @@ -232,15 +232,15 @@ func calls(_ i:Int, j:Int, k:Int) { // -- Curry the projected concrete value in an existential (or its Type) // -- onto protocol type methods dispatched using protocol_method. - // CHECK: [[PBOX:%[0-9]+]] = alloc_box ${ var SomeProtocol } + // CHECK: [[PBOX:%[0-9]+]] = alloc_box ${ var any SomeProtocol } // CHECK: [[PLIFETIME:%[^,]+]] = begin_borrow [lexical] [[PBOX]] // CHECK: [[PADDR:%.*]] = project_box [[PLIFETIME]] var p : SomeProtocol = ConformsToSomeProtocol() // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PADDR]] - // CHECK: [[TEMP:%.*]] = alloc_stack $SomeProtocol + // CHECK: [[TEMP:%.*]] = alloc_stack $any SomeProtocol // CHECK: copy_addr [[READ]] to [initialization] [[TEMP]] - // CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr immutable_access [[TEMP]] : $*SomeProtocol to $*[[OPENED:@opened\(.*, SomeProtocol\) Self]] + // CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr immutable_access [[TEMP]] : $*any SomeProtocol to $*[[OPENED:@opened\(.*, any SomeProtocol\) Self]] // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]] // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]] // CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method : @@ -249,7 +249,7 @@ func calls(_ i:Int, j:Int, k:Int) { // CHECK: dealloc_stack [[TEMP]] p.method(i) - // CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr immutable_access [[PADDR:%.*]] : $*SomeProtocol to $*[[OPENED:@opened\(.*, SomeProtocol\) Self]] + // CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr immutable_access [[PADDR:%.*]] : $*any SomeProtocol to $*[[OPENED:@opened\(.*, any SomeProtocol\) Self]] // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]] // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]] // CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method : diff --git a/test/SILGen/generic_casts.swift b/test/SILGen/generic_casts.swift index 27173e707864a..a715540be0555 100644 --- a/test/SILGen/generic_casts.swift +++ b/test/SILGen/generic_casts.swift @@ -122,10 +122,10 @@ func class_archetype_is_class func opaque_existential_to_opaque_archetype (_ p:NotClassBound) -> T { return p as! T - // CHECK: bb0([[RET:%.*]] : $*T, [[ARG:%.*]] : $*NotClassBound): - // CHECK: [[TEMP:%.*]] = alloc_stack $NotClassBound + // CHECK: bb0([[RET:%.*]] : $*T, [[ARG:%.*]] : $*any NotClassBound): + // CHECK: [[TEMP:%.*]] = alloc_stack $any NotClassBound // CHECK-NEXT: copy_addr [[ARG]] to [initialization] [[TEMP]] - // CHECK-NEXT: unconditional_checked_cast_addr NotClassBound in [[TEMP]] : $*NotClassBound to T in [[RET]] : $*T + // CHECK-NEXT: unconditional_checked_cast_addr any NotClassBound in [[TEMP]] : $*any NotClassBound to T in [[RET]] : $*T // CHECK-NEXT: dealloc_stack [[TEMP]] // CHECK-NEXT: [[T0:%.*]] = tuple () // CHECK-NEXT: return [[T0]] @@ -135,14 +135,14 @@ func opaque_existential_to_opaque_archetype func opaque_existential_is_opaque_archetype (_ p:NotClassBound, _: T) -> Bool { return p is T - // CHECK: checked_cast_addr_br take_always NotClassBound in [[CONTAINER:%.*]] : {{.*}} to T in + // CHECK: checked_cast_addr_br take_always any NotClassBound in [[CONTAINER:%.*]] : {{.*}} to T in } // CHECK-LABEL: sil hidden [ossa] @$s13generic_casts37opaque_existential_to_class_archetype{{[_0-9a-zA-Z]*}}F func opaque_existential_to_class_archetype (_ p:NotClassBound) -> T { return p as! T - // CHECK: unconditional_checked_cast_addr NotClassBound in {{%.*}} : $*NotClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T + // CHECK: unconditional_checked_cast_addr any NotClassBound in {{%.*}} : $*any NotClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T // CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]] : $*T // CHECK: return [[DOWNCAST]] : $T } @@ -151,14 +151,14 @@ func opaque_existential_to_class_archetype func opaque_existential_is_class_archetype (_ p:NotClassBound, _: T) -> Bool { return p is T - // CHECK: checked_cast_addr_br take_always NotClassBound in {{%.*}} : $*NotClassBound to T in + // CHECK: checked_cast_addr_br take_always any NotClassBound in {{%.*}} : $*any NotClassBound to T in } // CHECK-LABEL: sil hidden [ossa] @$s13generic_casts021class_existential_to_C10_archetype{{[_0-9a-zA-Z]*}}F func class_existential_to_class_archetype (_ p:ClassBound) -> T { return p as! T - // CHECK: unconditional_checked_cast_addr ClassBound in {{%.*}} : $*ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T + // CHECK: unconditional_checked_cast_addr any ClassBound in {{%.*}} : $*any ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T // CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]] // CHECK: return [[DOWNCAST]] : $T } @@ -167,26 +167,26 @@ func class_existential_to_class_archetype func class_existential_is_class_archetype (_ p:ClassBound, _: T) -> Bool { return p is T - // CHECK: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T + // CHECK: checked_cast_addr_br {{.*}} any ClassBound in {{%.*}} : $*any ClassBound to T in {{%.*}} : $*T } // CHECK-LABEL: sil hidden [ossa] @$s13generic_casts40opaque_existential_to_addr_only_concrete{{[_0-9a-zA-Z]*}}F func opaque_existential_to_addr_only_concrete(_ p: NotClassBound) -> Unloadable { return p as! Unloadable - // CHECK: bb0([[RET:%.*]] : $*Unloadable, {{%.*}}: $*NotClassBound): - // CHECK: unconditional_checked_cast_addr NotClassBound in {{%.*}} : $*NotClassBound to Unloadable in [[RET]] : $*Unloadable + // CHECK: bb0([[RET:%.*]] : $*Unloadable, {{%.*}}: $*any NotClassBound): + // CHECK: unconditional_checked_cast_addr any NotClassBound in {{%.*}} : $*any NotClassBound to Unloadable in [[RET]] : $*Unloadable } // CHECK-LABEL: sil hidden [ossa] @$s13generic_casts40opaque_existential_is_addr_only_concrete{{[_0-9a-zA-Z]*}}F func opaque_existential_is_addr_only_concrete(_ p: NotClassBound) -> Bool { return p is Unloadable - // CHECK: checked_cast_addr_br take_always NotClassBound in {{%.*}} : $*NotClassBound to Unloadable in + // CHECK: checked_cast_addr_br take_always any NotClassBound in {{%.*}} : $*any NotClassBound to Unloadable in } // CHECK-LABEL: sil hidden [ossa] @$s13generic_casts39opaque_existential_to_loadable_concrete{{[_0-9a-zA-Z]*}}F func opaque_existential_to_loadable_concrete(_ p: NotClassBound) -> S { return p as! S - // CHECK: unconditional_checked_cast_addr NotClassBound in {{%.*}} : $*NotClassBound to S in [[DOWNCAST_ADDR:%.*]] : $*S + // CHECK: unconditional_checked_cast_addr any NotClassBound in {{%.*}} : $*any NotClassBound to S in [[DOWNCAST_ADDR:%.*]] : $*S // CHECK: [[DOWNCAST:%.*]] = load [trivial] [[DOWNCAST_ADDR]] : $*S // CHECK: return [[DOWNCAST]] : $S } @@ -194,7 +194,7 @@ func opaque_existential_to_loadable_concrete(_ p: NotClassBound) -> S { // CHECK-LABEL: sil hidden [ossa] @$s13generic_casts39opaque_existential_is_loadable_concrete{{[_0-9a-zA-Z]*}}F func opaque_existential_is_loadable_concrete(_ p: NotClassBound) -> Bool { return p is S - // CHECK: checked_cast_addr_br take_always NotClassBound in {{%.*}} : $*NotClassBound to S in + // CHECK: checked_cast_addr_br take_always any NotClassBound in {{%.*}} : $*any NotClassBound to S in } // CHECK-LABEL: sil hidden [ossa] @$s13generic_casts021class_existential_to_C0{{[_0-9a-zA-Z]*}}F diff --git a/test/SILGen/generic_closures.swift b/test/SILGen/generic_closures.swift index dc7afc55f263e..c936d47786815 100644 --- a/test/SILGen/generic_closures.swift +++ b/test/SILGen/generic_closures.swift @@ -35,12 +35,12 @@ func generic_nondependent_context(_ x: T, y: Int) -> Int { func generic_capture(_ x: T) -> Any.Type { func foo() -> Any.Type { return T.self } - // CHECK: [[FOO:%.*]] = function_ref @$s16generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick Any.Type + // CHECK: [[FOO:%.*]] = function_ref @$s16generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick any Any.Type // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]]() // CHECK: destroy_value [[FOO_CLOSURE]] let _ = foo - // CHECK: [[FOO:%.*]] = function_ref @$s16generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick Any.Type + // CHECK: [[FOO:%.*]] = function_ref @$s16generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick any Any.Type // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]() // CHECK: return [[FOO_CLOSURE]] @@ -71,11 +71,11 @@ protocol Concept { func generic_nocapture_existential(_ x: T, y: Concept) -> Bool { func foo(_ a: Concept) -> Bool { return a.sensical } - // CHECK: [[FOO:%.*]] = function_ref @$s16generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in_guaranteed Concept) -> Bool + // CHECK: [[FOO:%.*]] = function_ref @$s16generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in_guaranteed any Concept) -> Bool // CHECK: [[FOO_CLOSURE:%.*]] = thin_to_thick_function [[FOO]] let _ = foo - // CHECK: [[FOO:%.*]] = function_ref @$s16generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in_guaranteed Concept) -> Bool + // CHECK: [[FOO:%.*]] = function_ref @$s16generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in_guaranteed any Concept) -> Bool // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]([[ARG:%.*]]) // CHECK: return [[FOO_CLOSURE]] diff --git a/test/SILGen/generic_property_base_lifetime.swift b/test/SILGen/generic_property_base_lifetime.swift index 516af45e01e7f..919bd5998e38c 100644 --- a/test/SILGen/generic_property_base_lifetime.swift +++ b/test/SILGen/generic_property_base_lifetime.swift @@ -14,12 +14,12 @@ protocol ProtocolB { } -// CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolA_pF : $@convention(thin) (@guaranteed ProtocolA) -> Int { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $ProtocolA): +// CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolA_pF : $@convention(thin) (@guaranteed any ProtocolA) -> Int { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any ProtocolA): // CHECK: [[PROJECTION:%.*]] = open_existential_ref [[ARG]] // CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]] // CHECK: [[BORROWED_PROJECTION_COPY:%.*]] = begin_borrow [[PROJECTION_COPY]] -// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}, ProtocolA) Self, #ProtocolA.intProp!getter : {{.*}}, [[PROJECTION]] +// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}, any ProtocolA) Self, #ProtocolA.intProp!getter : {{.*}}, [[PROJECTION]] // CHECK: [[RESULT:%.*]] = apply [[WITNESS_METHOD]]<@opened{{.*}}>([[BORROWED_PROJECTION_COPY]]) // CHECK: end_borrow [[BORROWED_PROJECTION_COPY]] // CHECK: destroy_value [[PROJECTION_COPY]] @@ -29,11 +29,11 @@ func getIntPropExistential(_ a: ProtocolA) -> Int { return a.intProp } -// CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolA_pF : $@convention(thin) (@guaranteed ProtocolA) -> () { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $ProtocolA): +// CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolA_pF : $@convention(thin) (@guaranteed any ProtocolA) -> () { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any ProtocolA): // CHECK: [[PROJECTION:%.*]] = open_existential_ref [[ARG]] // CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]] -// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}, ProtocolA) Self, #ProtocolA.intProp!setter : {{.*}}, [[PROJECTION]] +// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}, any ProtocolA) Self, #ProtocolA.intProp!setter : {{.*}}, [[PROJECTION]] // CHECK: apply [[WITNESS_METHOD]]<@opened{{.*}}>({{%.*}}, [[PROJECTION_COPY]]) // CHECK: destroy_value [[PROJECTION_COPY]] // CHECK: } // end sil function '$s30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolA_pF' @@ -58,7 +58,7 @@ func setIntPropGeneric(_ a: T) { // CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolB_pF // CHECK: [[PROJECTION:%.*]] = open_existential_addr immutable_access %0 -// CHECK: [[STACK:%[0-9]+]] = alloc_stack $@opened({{".*"}}, ProtocolB) Self +// CHECK: [[STACK:%[0-9]+]] = alloc_stack $@opened({{".*"}}, any ProtocolB) Self // CHECK: copy_addr [[PROJECTION]] to [initialization] [[STACK]] // CHECK: apply {{%.*}}([[STACK]]) // CHECK: destroy_addr [[STACK]] @@ -77,12 +77,12 @@ func getIntPropGeneric(_ a: T) -> Int { return a.intProp } -// CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolO_pF : $@convention(thin) (@guaranteed ProtocolO) -> Int { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $ProtocolO): +// CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolO_pF : $@convention(thin) (@guaranteed any ProtocolO) -> Int { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any ProtocolO): // CHECK: [[PROJECTION:%.*]] = open_existential_ref [[ARG]] // CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]] // CHECK: [[PROJECTION_BORROW:%.*]] = begin_borrow [[PROJECTION_COPY]] -// CHECK: [[METHOD:%.*]] = objc_method [[PROJECTION_BORROW]] : $@opened({{.*}}, ProtocolO) Self, #ProtocolO.intProp!getter.foreign : {{.*}} +// CHECK: [[METHOD:%.*]] = objc_method [[PROJECTION_BORROW]] : $@opened({{.*}}, any ProtocolO) Self, #ProtocolO.intProp!getter.foreign : {{.*}} // CHECK: apply [[METHOD]]<@opened{{.*}}>([[PROJECTION_BORROW]]) // CHECK: destroy_value [[PROJECTION_COPY]] // CHECK: } // end sil function '$s30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolO_pF' @@ -90,11 +90,11 @@ func getIntPropExistential(_ a: ProtocolO) -> Int { return a.intProp } -// CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolO_pF : $@convention(thin) (@guaranteed ProtocolO) -> () { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $ProtocolO): +// CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolO_pF : $@convention(thin) (@guaranteed any ProtocolO) -> () { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any ProtocolO): // CHECK: [[PROJECTION:%.*]] = open_existential_ref [[ARG]] // CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]] -// CHECK: [[METHOD:%.*]] = objc_method [[PROJECTION_COPY]] : $@opened({{.*}}, ProtocolO) Self, #ProtocolO.intProp!setter.foreign : {{.*}} +// CHECK: [[METHOD:%.*]] = objc_method [[PROJECTION_COPY]] : $@opened({{.*}}, any ProtocolO) Self, #ProtocolO.intProp!setter.foreign : {{.*}} // CHECK: apply [[METHOD]]<@opened{{.*}}>({{.*}}, [[PROJECTION_COPY]]) // CHECK: destroy_value [[PROJECTION_COPY]] // CHECK: } // end sil function '$s30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolO_pF' diff --git a/test/SILGen/generic_witness.swift b/test/SILGen/generic_witness.swift index 4c966c5e69a6d..19a9cf4c2cbf4 100644 --- a/test/SILGen/generic_witness.swift +++ b/test/SILGen/generic_witness.swift @@ -14,12 +14,12 @@ func foo(_ x: B) { x.runce(5) } -// CHECK-LABEL: sil hidden [ossa] @$s15generic_witness3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@in_guaranteed Runcible) -> () +// CHECK-LABEL: sil hidden [ossa] @$s15generic_witness3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@in_guaranteed any Runcible) -> () func bar(_ x: Runcible) { var x = x - // CHECK: [[BOX:%.*]] = alloc_box ${ var Runcible } - // CHECK: [[TEMP:%.*]] = alloc_stack $Runcible - // CHECK: [[EXIST:%.*]] = open_existential_addr immutable_access [[TEMP]] : $*Runcible to $*[[OPENED:@opened\(.*, Runcible\) Self]] + // CHECK: [[BOX:%.*]] = alloc_box ${ var any Runcible } + // CHECK: [[TEMP:%.*]] = alloc_stack $any Runcible + // CHECK: [[EXIST:%.*]] = open_existential_addr immutable_access [[TEMP]] : $*any Runcible to $*[[OPENED:@opened\(.*, any Runcible\) Self]] // CHECK: [[METHOD:%.*]] = witness_method $[[OPENED]], #Runcible.runce : // CHECK: apply [[METHOD]]<[[OPENED]], Int> x.runce(5) diff --git a/test/SILGen/guaranteed_closure_context.swift b/test/SILGen/guaranteed_closure_context.swift index 3ec75531411e2..54e3aca506db0 100644 --- a/test/SILGen/guaranteed_closure_context.swift +++ b/test/SILGen/guaranteed_closure_context.swift @@ -16,7 +16,7 @@ func guaranteed_captures() { // CHECK: [[MUTABLE_RETAINABLE_BOX:%.*]] = alloc_box ${ var C } // CHECK: [[MUTABLE_RETAINABLE_BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[MUTABLE_RETAINABLE_BOX]] var mutableRetainable = C() - // CHECK: [[MUTABLE_ADDRESS_ONLY_BOX:%.*]] = alloc_box ${ var P } + // CHECK: [[MUTABLE_ADDRESS_ONLY_BOX:%.*]] = alloc_box ${ var any P } // CHECK: [[MUTABLE_ADDRESS_ONLY_BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[MUTABLE_ADDRESS_ONLY_BOX]] var mutableAddressOnly: P = C() @@ -25,7 +25,7 @@ func guaranteed_captures() { // CHECK: [[IMMUTABLE_RETAINABLE:%.*]] = apply {{.*}} -> @owned C // CHECK: [[B_IMMUTABLE_RETAINABLE:%.*]] = begin_borrow [lexical] [[IMMUTABLE_RETAINABLE]] : $C let immutableRetainable = C() - // CHECK: [[IMMUTABLE_ADDRESS_ONLY:%.*]] = alloc_stack [lexical] $P + // CHECK: [[IMMUTABLE_ADDRESS_ONLY:%.*]] = alloc_stack [lexical] $any P let immutableAddressOnly: P = C() func captureEverything() { @@ -53,7 +53,7 @@ func guaranteed_captures() { // CHECK: [[MUTABLE_RETAINABLE_BOX_COPY:%.*]] = copy_value [[MUTABLE_RETAINABLE_BOX_LIFETIME]] // CHECK: [[MUTABLE_ADDRESS_ONLY_BOX_COPY:%.*]] = copy_value [[MUTABLE_ADDRESS_ONLY_BOX_LIFETIME]] // CHECK: [[IMMUTABLE_RETAINABLE_COPY:%.*]] = copy_value [[B_IMMUTABLE_RETAINABLE]] - // CHECK: [[IMMUTABLE_ADDRESS:%.*]] = alloc_stack $P + // CHECK: [[IMMUTABLE_ADDRESS:%.*]] = alloc_stack $any P // CHECK: [[CLOSURE:%.*]] = partial_apply {{.*}}([[MUTABLE_TRIVIAL_BOX_COPY]], [[MUTABLE_RETAINABLE_BOX_COPY]], [[MUTABLE_ADDRESS_ONLY_BOX_COPY]], [[IMMUTABLE_TRIVIAL]], [[IMMUTABLE_RETAINABLE_COPY]], [[IMMUTABLE_ADDRESS]]) // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE]] // CHECK: apply {{.*}}[[CONVERT]] @@ -66,4 +66,4 @@ func guaranteed_captures() { escape(captureEverything) } -// CHECK: sil private [ossa] [[FN_NAME]] : $@convention(thin) (@guaranteed { var S }, @guaranteed { var C }, @guaranteed { var P }, S, @guaranteed C, @in_guaranteed P) +// CHECK: sil private [ossa] [[FN_NAME]] : $@convention(thin) (@guaranteed { var S }, @guaranteed { var C }, @guaranteed { var any P }, S, @guaranteed C, @in_guaranteed any P) diff --git a/test/SILGen/hop_to_executor.swift b/test/SILGen/hop_to_executor.swift index 1d3b9ef9d5c1b..99e908a25cb7a 100644 --- a/test/SILGen/hop_to_executor.swift +++ b/test/SILGen/hop_to_executor.swift @@ -20,7 +20,7 @@ actor MyActor { print(x) } - // CHECK-LABEL: sil hidden [ossa] @$s4test7MyActorC14throwingCalleeyySiYaKF : $@convention(method) @async (Int, @guaranteed MyActor) -> @error Error { + // CHECK-LABEL: sil hidden [ossa] @$s4test7MyActorC14throwingCalleeyySiYaKF : $@convention(method) @async (Int, @guaranteed MyActor) -> @error any Error { // CHECK: [[GENERIC_EXEC:%.*]] = enum $Optional, #Optional.none // CHECK: hop_to_executor [[GENERIC_EXEC]] : // CHECK: } // end sil function '$s4test7MyActorC14throwingCalleeyySiYaKF' @@ -28,7 +28,7 @@ actor MyActor { print(x) } - // CHECK-LABEL: sil hidden [ossa] @$s4test7MyActorC0A13AsyncFunctionyyYaKF : $@convention(method) @async (@guaranteed MyActor) -> @error Error { + // CHECK-LABEL: sil hidden [ossa] @$s4test7MyActorC0A13AsyncFunctionyyYaKF : $@convention(method) @async (@guaranteed MyActor) -> @error any Error { // CHECK: hop_to_executor %0 : $MyActor // CHECK: = apply {{.*}} : $@convention(method) @async (Int, @guaranteed MyActor) -> () // CHECK-NEXT: hop_to_executor %0 : $MyActor diff --git a/test/SILGen/if_expr.swift b/test/SILGen/if_expr.swift index 26bd0d59e226a..fa8a3a4fae3a1 100644 --- a/test/SILGen/if_expr.swift +++ b/test/SILGen/if_expr.swift @@ -31,12 +31,12 @@ func consumeAddressOnly(_: AddressOnly) {} // CHECK: sil hidden [ossa] @$s7if_expr19addr_only_ternary_1{{[_0-9a-zA-Z]*}}F func addr_only_ternary_1(x: Bool) -> AddressOnly { - // CHECK: bb0([[RET:%.*]] : $*AddressOnly, {{.*}}): - // CHECK: [[a:%[0-9]+]] = alloc_box ${ var AddressOnly }, var, name "a" + // CHECK: bb0([[RET:%.*]] : $*any AddressOnly, {{.*}}): + // CHECK: [[a:%[0-9]+]] = alloc_box ${ var any AddressOnly }, var, name "a" // CHECK: [[a_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[a]] // CHECK: [[PBa:%.*]] = project_box [[a_LIFETIME]] var a : AddressOnly = A() - // CHECK: [[b:%[0-9]+]] = alloc_box ${ var AddressOnly }, var, name "b" + // CHECK: [[b:%[0-9]+]] = alloc_box ${ var any AddressOnly }, var, name "b" // CHECK: [[b_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[b]] // CHECK: [[PBb:%.*]] = project_box [[b_LIFETIME]] var b : AddressOnly = B() diff --git a/test/SILGen/init_delegation_optional.swift b/test/SILGen/init_delegation_optional.swift index 42d17d99e8fd9..b499494605e5d 100644 --- a/test/SILGen/init_delegation_optional.swift +++ b/test/SILGen/init_delegation_optional.swift @@ -153,13 +153,13 @@ extension Optional { // CHECK-NEXT: [[RET:%[0-9]+]] = tuple () // CHECK-NEXT: return [[RET]] : $() // - // CHECK: bb7([[ERR:%[0-9]+]] : @owned $Error): + // CHECK: bb7([[ERR:%[0-9]+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERR]] // CHECK-NEXT: inject_enum_addr [[OPT_RESULT_ADDR]] : {{.*}}, #Optional.none!enumelt // CHECK-NEXT: br bb2 // - // CHECK: [[ERROR_BB]]([[ERR:%[0-9]+]] : @owned $Error): - // CHECK-NEXT: br bb7([[ERR]] : $Error) + // CHECK: [[ERROR_BB]]([[ERR:%[0-9]+]] : @owned $any Error): + // CHECK-NEXT: br bb7([[ERR]] : $any Error) // CHECK-NEXT: } } @@ -230,13 +230,13 @@ extension Optional { // CHECK-NEXT: [[RET:%[0-9]+]] = tuple () // CHECK-NEXT: return [[RET]] : $() // - // CHECK: bb10([[ERROR:%[0-9]+]] : @owned $Error): + // CHECK: bb10([[ERROR:%[0-9]+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: inject_enum_addr [[OPT_OPT_RESULT_ADDR]] : {{.*}}, #Optional.none!enumelt // CHECK-NEXT: br bb2 // - // CHECK: [[ERROR_BB]]([[ERROR:%[0-9]+]] : @owned $Error): - // CHECK-NEXT: br bb10([[ERROR]] : $Error) + // CHECK: [[ERROR_BB]]([[ERROR:%[0-9]+]] : @owned $any Error): + // CHECK-NEXT: br bb10([[ERROR]] : $any Error) // CHECK-NEXT: } } @@ -297,14 +297,14 @@ extension Optional { // CHECK-NEXT: [[RET:%[0-9]+]] = tuple () // CHECK-NEXT: return [[RET]] : $() // - // CHECK: bb9([[ERROR:%[0-9]+]] : @owned $Error): + // CHECK: bb9([[ERROR:%[0-9]+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: inject_enum_addr [[OPT_RESULT_ADDR]] : {{.*}}, #Optional.none!enumelt // CHECK-NEXT: br bb4 // - // CHECK: [[ERROR_BB]]([[ERROR:%[0-9]+]] : @owned $Error): + // CHECK: [[ERROR_BB]]([[ERROR:%[0-9]+]] : @owned $any Error): // CHECK-NEXT: dealloc_stack [[TMP_OPT_RESULT_ADDR]] - // CHECK-NEXT: br bb9([[ERROR]] : $Error) + // CHECK-NEXT: br bb9([[ERROR]] : $any Error) // CHECK-NEXT: } } @@ -350,11 +350,11 @@ extension Optional { // CHECK-NEXT: [[RET:%[0-9]+]] = tuple () // CHECK-NEXT: return [[RET]] : $() // - // CHECK: bb6({{%[0-9]+}} : @owned $Error): + // CHECK: bb6({{%[0-9]+}} : @owned $any Error): // CHECK: unreachable // - // CHECK: [[ERROR_BB]]([[ERROR:%[0-9]+]] : @owned $Error): - // CHECK: br bb6([[ERROR]] : $Error) + // CHECK: [[ERROR_BB]]([[ERROR:%[0-9]+]] : @owned $any Error): + // CHECK: br bb6([[ERROR]] : $any Error) // CHECK-NEXT: } } } @@ -477,13 +477,13 @@ extension Optional where Wrapped == Optional { // CHECK: bb9([[RET:%[0-9]+]] : $Optional>>): // CHECK-NEXT: return [[RET]] // - // CHECK: bb10([[ERROR:%[0-9]+]] : @owned $Error): + // CHECK: bb10([[ERROR:%[0-9]+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: [[NIL:%[0-9]+]] = enum $Optional>>>, #Optional.none!enumelt // CHECK-NEXT: br bb2([[NIL]] : $Optional>>>) // - // CHECK: [[ERROR_BB]]([[ERROR:%[0-9]+]] : @owned $Error): - // CHECK-NEXT: br bb10([[ERROR]] : $Error) + // CHECK: [[ERROR_BB]]([[ERROR:%[0-9]+]] : @owned $any Error): + // CHECK-NEXT: br bb10([[ERROR]] : $any Error) // CHECK-NEXT: } try? self.init(SpecFailableAndThrows: ()) } diff --git a/test/SILGen/initializers.swift b/test/SILGen/initializers.swift index da9f9a1d7c165..3e9f55657225e 100644 --- a/test/SILGen/initializers.swift +++ b/test/SILGen/initializers.swift @@ -232,7 +232,7 @@ struct ThrowStruct { // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers11ThrowStructV0A0ACSgyt_tcfC // CHECK: bb0([[SELF_META:%[0-9]+]] : $@thin ThrowStruct.Type): // CHECK: [[DELEG_INIT:%[0-9]+]] = function_ref @$s21failable_initializers11ThrowStructV6throwsACyt_tKcfC - // CHECK-NEXT: try_apply [[DELEG_INIT]]([[SELF_META]]) : $@convention(method) (@thin ThrowStruct.Type) -> (@owned ThrowStruct, @error Error), normal [[SUCC_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] + // CHECK-NEXT: try_apply [[DELEG_INIT]]([[SELF_META]]) : $@convention(method) (@thin ThrowStruct.Type) -> (@owned ThrowStruct, @error any Error), normal [[SUCC_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // // CHECK: [[SUCC_BB]]([[RESULT:%[0-9]+]] : @owned $ThrowStruct): // CHECK-NEXT: [[INJECT_INTO_OPT:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, [[RESULT]] @@ -260,13 +260,13 @@ struct ThrowStruct { // CHECK: bb6([[RET:%[0-9]+]] : @owned $Optional): // CHECK-NEXT: return [[RET]] // - // CHECK: bb7([[ERR:%[0-9]+]] : @owned $Error): + // CHECK: bb7([[ERR:%[0-9]+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERR]] // CHECK-NEXT: [[NIL:%[0-9]+]] = enum $Optional, #Optional.none!enumelt // CHECK-NEXT: br bb2([[NIL]] : $Optional) // - // CHECK: [[ERROR_BB]]([[ERR:%[0-9]+]] : @owned $Error): - // CHECK-NEXT: br bb7([[ERR]] : $Error) + // CHECK: [[ERROR_BB]]([[ERR:%[0-9]+]] : @owned $any Error): + // CHECK-NEXT: br bb7([[ERR]] : $any Error) // CHECK-NEXT: } init?(failable: ()) { try? self.init(throws: ()) @@ -275,7 +275,7 @@ struct ThrowStruct { // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers11ThrowStructV9failable2ACSgyt_tcfC // CHECK: bb0([[SELF_META:%[0-9]+]] : $@thin ThrowStruct.Type): // CHECK: [[DELEG_INIT:%[0-9]+]] = function_ref @$s21failable_initializers11ThrowStructV0A9AndThrowsACSgyt_tKcfC - // CHECK-NEXT: try_apply [[DELEG_INIT]]([[SELF_META]]) : $@convention(method) (@thin ThrowStruct.Type) -> (@owned Optional, @error Error), normal [[SUCC_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] + // CHECK-NEXT: try_apply [[DELEG_INIT]]([[SELF_META]]) : $@convention(method) (@thin ThrowStruct.Type) -> (@owned Optional, @error any Error), normal [[SUCC_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // // CHECK: [[SUCC_BB]]([[OPT_RESULT:%[0-9]+]] : @owned $Optional): // CHECK: [[SELECT:%[0-9]+]] = select_enum [[OPT_RESULT]] @@ -299,11 +299,11 @@ struct ThrowStruct { // CHECK: bb5([[RET:%[0-9]+]] : @owned $Optional): // CHECK-NEXT: return [[RET]] // - // CHECK: bb6([[ERR:%[0-9]+]] : @owned $Error): + // CHECK: bb6([[ERR:%[0-9]+]] : @owned $any Error): // CHECK: unreachable // - // CHECK: [[ERROR_BB]]([[ERR:%[0-9]+]] : @owned $Error): - // CHECK-NEXT: br bb6([[ERR]] : $Error) + // CHECK: [[ERROR_BB]]([[ERR:%[0-9]+]] : @owned $any Error): + // CHECK-NEXT: br bb6([[ERR]] : $any Error) // CHECK-NEXT: } init?(failable2: ()) { try! self.init(failableAndThrows: ()) @@ -316,7 +316,7 @@ struct ThrowStruct { // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers11ThrowStructV9failable4ACSgyt_tcfC // CHECK: bb0([[SELF_META:%[0-9]+]] : $@thin ThrowStruct.Type): // CHECK: [[DELEG_INIT:%[0-9]+]] = function_ref @$s21failable_initializers11ThrowStructV0A9AndThrowsACSgyt_tKcfC - // CHECK-NEXT: try_apply [[DELEG_INIT]]([[SELF_META]]) : $@convention(method) (@thin ThrowStruct.Type) -> (@owned Optional, @error Error), normal [[SUCC_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] + // CHECK-NEXT: try_apply [[DELEG_INIT]]([[SELF_META]]) : $@convention(method) (@thin ThrowStruct.Type) -> (@owned Optional, @error any Error), normal [[SUCC_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // // CHECK: [[SUCC_BB]]([[OPT_RESULT:%[0-9]+]] : @owned $Optional): // CHECK-NEXT: [[INJECT_INTO_OPT:%[0-9]+]] = enum {{.*}}, #Optional.some!enumelt, [[OPT_RESULT]] @@ -354,13 +354,13 @@ struct ThrowStruct { // CHECK: bb9([[RET:%[0-9]+]] : @owned $Optional): // CHECK-NEXT: return [[RET]] // - // CHECK: bb10([[ERR:%[0-9]+]] : @owned $Error): + // CHECK: bb10([[ERR:%[0-9]+]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERR]] // CHECK-NEXT: [[NIL:%[0-9]+]] = enum $Optional>, #Optional.none!enumelt // CHECK-NEXT: br bb2([[NIL]] : $Optional>) // - // CHECK: [[ERROR_BB]]([[ERR:%[0-9]+]] : @owned $Error): - // CHECK-NEXT: br bb10([[ERR]] : $Error) + // CHECK: [[ERROR_BB]]([[ERR:%[0-9]+]] : @owned $any Error): + // CHECK-NEXT: br bb10([[ERR]] : $any Error) // CHECK-NEXT: } init?(failable4: ()) { try? self.init(failableAndThrows: ()) @@ -733,7 +733,7 @@ class ThrowDerivedClass : ThrowBaseClass { // ---- Delegating to super - // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC30delegatingFailBeforeDelegationACSi_tKcfc : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) { + // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC30delegatingFailBeforeDelegationACSi_tKcfc : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) { // CHECK: bb0( // First initialize. // CHECK: [[REF:%.*]] = alloc_box ${ var ThrowDerivedClass }, let, name "self" @@ -752,7 +752,7 @@ class ThrowDerivedClass : ThrowBaseClass { // // Now we perform the unwrap. // CHECK: [[UNWRAP_FN:%.*]] = function_ref @$s21failable_initializers6unwrapyS2iKF : $@convention(thin) - // CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] + // CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error any Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // // CHECK: [[NORMAL_BB]]( // CHECK: [[SELF:%.*]] = load [take] [[PROJ]] @@ -767,7 +767,7 @@ class ThrowDerivedClass : ThrowBaseClass { // // Finally the error BB. We do not touch self since self is still in the // box implying that destroying MARK_UNINIT will destroy it for us. - // CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK: destroy_value [[MARK_UNINIT]] // CHECK: throw [[ERROR]] // CHECK: } // end sil function '$s21failable_initializers17ThrowDerivedClassC30delegatingFailBeforeDelegationACSi_tKcfc' @@ -776,7 +776,7 @@ class ThrowDerivedClass : ThrowBaseClass { super.init(noFail: ()) } - // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC41delegatingFailDuringDelegationArgEmissionACSi_tKcfc : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) { + // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC41delegatingFailDuringDelegationArgEmissionACSi_tKcfc : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) { // CHECK: bb0( // First initialize. // CHECK: [[REF:%.*]] = alloc_box ${ var ThrowDerivedClass }, let, name "self" @@ -797,7 +797,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: [[SELF:%.*]] = load [take] [[PROJ]] // CHECK: [[BASE_SELF:%.*]] = upcast [[SELF]] : $ThrowDerivedClass to $ThrowBaseClass // CHECK: [[UNWRAP_FN:%.*]] = function_ref @$s21failable_initializers6unwrapyS2iKF : $@convention(thin) - // CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] + // CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error any Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // // Now we emit the call to the initializer. Notice how we return self back to // its memory locatio nbefore any other work is done. @@ -816,7 +816,7 @@ class ThrowDerivedClass : ThrowBaseClass { // 1. Store self back into the "conceptually" uninitialized box. // 2. destroy the box. // 3. Perform the rethrow. - // CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK: [[SELF:%.*]] = unchecked_ref_cast [[BASE_SELF]] : $ThrowBaseClass to $ThrowDerivedClass // CHECK: store [[SELF]] to [init] [[PROJ]] // CHECK: destroy_value [[MARK_UNINIT]] @@ -826,7 +826,7 @@ class ThrowDerivedClass : ThrowBaseClass { super.init(noFail: try unwrap(delegatingFailDuringDelegationArgEmission)) } - // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC34delegatingFailDuringDelegationCallACSi_tKcfc : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) { + // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC34delegatingFailDuringDelegationCallACSi_tKcfc : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) { // CHECK: bb0( // First initialize. // CHECK: [[REF:%.*]] = alloc_box ${ var ThrowDerivedClass }, let, name "self" @@ -839,7 +839,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: [[SELF:%.*]] = load [take] [[PROJ]] // CHECK: [[BASE_SELF:%.*]] = upcast [[SELF]] : $ThrowDerivedClass to $ThrowBaseClass // CHECK: [[INIT_FN:%.*]] = function_ref @$s21failable_initializers14ThrowBaseClassCACyKcfc : $@convention(method) - // CHECK: try_apply [[INIT_FN]]([[BASE_SELF]]) : $@convention(method) (@owned ThrowBaseClass) -> (@owned ThrowBaseClass, @error Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] + // CHECK: try_apply [[INIT_FN]]([[BASE_SELF]]) : $@convention(method) (@owned ThrowBaseClass) -> (@owned ThrowBaseClass, @error any Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // // Insert the return statement into the normal block... // CHECK: [[NORMAL_BB]]([[BASE_SELF_INIT:%.*]] : @owned $ThrowBaseClass): @@ -850,7 +850,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: return [[RESULT]] // // ... and destroy the box in the error block. - // CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: end_borrow [[LIFETIME]] // CHECK-NEXT: destroy_value [[MARK_UNINIT]] // CHECK-NEXT: throw [[ERROR]] @@ -859,7 +859,7 @@ class ThrowDerivedClass : ThrowBaseClass { try super.init() } - // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC29delegatingFailAfterDelegationACSi_tKcfc : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) { + // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC29delegatingFailAfterDelegationACSi_tKcfc : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) { // CHECK: bb0( // First initialize. // CHECK: [[REF:%.*]] = alloc_box ${ var ThrowDerivedClass }, let, name "self" @@ -877,8 +877,8 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: store [[NEW_SELF_CAST]] to [init] [[PROJ]] // // Finally perform the unwrap. - // CHECK: [[UNWRAP_FN:%.*]] = function_ref @$s21failable_initializers6unwrapyS2iKF : $@convention(thin) (Int) -> (Int, @error Error) - // CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] + // CHECK: [[UNWRAP_FN:%.*]] = function_ref @$s21failable_initializers6unwrapyS2iKF : $@convention(thin) (Int) -> (Int, @error any Error) + // CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error any Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // // Insert the return statement into the normal block... // CHECK: [[NORMAL_BB]]( @@ -887,7 +887,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: return [[RESULT]] // // ... and destroy the box in the error block. - // CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: end_borrow [[LIFETIME]] // CHECK-NEXT: destroy_value [[MARK_UNINIT]] // CHECK-NEXT: throw [[ERROR]] @@ -897,7 +897,7 @@ class ThrowDerivedClass : ThrowBaseClass { try unwrap(delegatingFailAfterDelegation) } - // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC30delegatingFailBeforeDelegation0fg6DuringI11ArgEmissionACSi_SitKcfc : $@convention(method) (Int, Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) { + // CHECK-LABEL: sil hidden [ossa] @$s21failable_initializers17ThrowDerivedClassC30delegatingFailBeforeDelegation0fg6DuringI11ArgEmissionACSi_SitKcfc : $@convention(method) (Int, Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) { // Create our box. // CHECK: [[REF:%.*]] = alloc_box ${ var ThrowDerivedClass }, let, name "self" // CHECK: [[MARK_UNINIT:%.*]] = mark_uninitialized [derivedself] [[REF]] : ${ var ThrowDerivedClass } @@ -905,15 +905,15 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: [[PROJ:%.*]] = project_box [[MARK_UNINIT_LIFETIME]] // // Perform the unwrap. - // CHECK: [[UNWRAP_FN:%.*]] = function_ref @$s21failable_initializers6unwrapyS2iKF : $@convention(thin) (Int) -> (Int, @error Error) - // CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[UNWRAP_NORMAL_BB:bb[0-9]+]], error [[UNWRAP_ERROR_BB:bb[0-9]+]] + // CHECK: [[UNWRAP_FN:%.*]] = function_ref @$s21failable_initializers6unwrapyS2iKF : $@convention(thin) (Int) -> (Int, @error any Error) + // CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error any Error), normal [[UNWRAP_NORMAL_BB:bb[0-9]+]], error [[UNWRAP_ERROR_BB:bb[0-9]+]] // // Now we begin argument emission where we perform another unwrap. // CHECK: [[UNWRAP_NORMAL_BB]]( // CHECK: [[SELF:%.*]] = load [take] [[PROJ]] // CHECK: [[SELF_CAST:%.*]] = upcast [[SELF]] : $ThrowDerivedClass to $ThrowBaseClass - // CHECK: [[UNWRAP_FN2:%.*]] = function_ref @$s21failable_initializers6unwrapyS2iKF : $@convention(thin) (Int) -> (Int, @error Error) - // CHECK: try_apply [[UNWRAP_FN2]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[UNWRAP_NORMAL_BB2:bb[0-9]+]], error [[UNWRAP_ERROR_BB2:bb[0-9]+]] + // CHECK: [[UNWRAP_FN2:%.*]] = function_ref @$s21failable_initializers6unwrapyS2iKF : $@convention(thin) (Int) -> (Int, @error any Error) + // CHECK: try_apply [[UNWRAP_FN2]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error any Error), normal [[UNWRAP_NORMAL_BB2:bb[0-9]+]], error [[UNWRAP_ERROR_BB2:bb[0-9]+]] // // Then since this example has a // CHECK: [[UNWRAP_NORMAL_BB2]]([[INT:%.*]] : $Int): @@ -927,15 +927,15 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: return [[RESULT]] // // ... and destroy the box in the error block. - // CHECK: [[UNWRAP_ERROR_BB]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[UNWRAP_ERROR_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK: br [[ERROR_JOIN:bb[0-9]+]]([[ERROR]] // - // CHECK: [[UNWRAP_ERROR_BB2]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[UNWRAP_ERROR_BB2]]([[ERROR:%.*]] : @owned $any Error): // CHECK: [[SELF_CASTED_BACK:%.*]] = unchecked_ref_cast [[SELF_CAST]] : $ThrowBaseClass to $ThrowDerivedClass // CHECK: store [[SELF_CASTED_BACK]] to [init] [[PROJ]] // CHECK: br [[ERROR_JOIN]]([[ERROR]] // - // CHECK: [[ERROR_JOIN]]([[ERROR_PHI:%.*]] : @owned $Error): + // CHECK: [[ERROR_JOIN]]([[ERROR_PHI:%.*]] : @owned $any Error): // CHECK: end_borrow [[MARK_UNINIT_LIFETIME]] // CHECK: destroy_value [[MARK_UNINIT]] // CHECK: throw [[ERROR_PHI]] @@ -1040,7 +1040,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: [[MARKED_SELF_BOX:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]] // CHECK: [[SELF_LIFETIME:%.*]] = begin_borrow [lexical] [[MARKED_SELF_BOX]] // CHECK: [[PB_BOX:%.*]] = project_box [[SELF_LIFETIME]] - // CHECK: try_apply {{.*}}({{.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[SUCC_BB1:bb[0-9]+]], error [[ERROR_BB1:bb[0-9]+]] + // CHECK: try_apply {{.*}}({{.*}}) : $@convention(thin) (Int) -> (Int, @error any Error), normal [[SUCC_BB1:bb[0-9]+]], error [[ERROR_BB1:bb[0-9]+]] // // CHECK: [[SUCC_BB1]]( // CHECK: try_apply {{.*}}({{.*}}, [[SELF_META]]) : {{.*}}, normal [[SUCC_BB2:bb[0-9]+]], error [[ERROR_BB2:bb[0-9]+]] @@ -1052,13 +1052,13 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: return [[RESULT]] // - // CHECK: [[ERROR_BB1]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[ERROR_BB1]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: br [[THROWING_BB:bb[0-9]+]]([[ERROR]] // - // CHECK: [[ERROR_BB2]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[ERROR_BB2]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: br [[THROWING_BB]]([[ERROR]] // - // CHECK: [[THROWING_BB]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[THROWING_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: end_borrow [[SELF_LIFETIME]] // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] @@ -1083,7 +1083,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: assign [[NEW_SELF]] to [[PB_BOX]] // CHECK-NEXT: // function_ref // CHECK-NEXT: function_ref @ - // CHECK-NEXT: try_apply {{.*}}({{.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[SUCC_BB2:bb[0-9]+]], error [[ERROR_BB2:bb[0-9]+]] + // CHECK-NEXT: try_apply {{.*}}({{.*}}) : $@convention(thin) (Int) -> (Int, @error any Error), normal [[SUCC_BB2:bb[0-9]+]], error [[ERROR_BB2:bb[0-9]+]] // // CHECK: [[SUCC_BB2]]( // CHECK-NEXT: [[RESULT:%.*]] = load [copy] [[PB_BOX]] @@ -1091,13 +1091,13 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: return [[RESULT]] // - // CHECK: [[ERROR_BB1]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[ERROR_BB1]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: br [[THROWING_BB:bb[0-9]+]]([[ERROR]] // - // CHECK: [[ERROR_BB2]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[ERROR_BB2]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: br [[THROWING_BB]]([[ERROR]] // - // CHECK: [[THROWING_BB]]([[ERROR:%.*]] : @owned $Error): + // CHECK: [[THROWING_BB]]([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: end_borrow [[SELF_LIFETIME]] // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] diff --git a/test/SILGen/keypaths_objc_optional.swift b/test/SILGen/keypaths_objc_optional.swift index fadaaea3fc634..cdbb0a281365f 100644 --- a/test/SILGen/keypaths_objc_optional.swift +++ b/test/SILGen/keypaths_objc_optional.swift @@ -18,21 +18,21 @@ import Foundation } // CHECK-LABEL: sil hidden [ossa] @{{.*}}testKeyPathAccessorsForOptionalStorageComponentsyyF -// CHECK: keypath $KeyPath>, (objc "object"; root $SwiftProtocol; gettable_property $Optional, id #SwiftProtocol.object!getter.foreign : (Self) -> () -> Object, getter @$[[SWIFT_PROP_GETTER:[_a-zA-Z0-9]+]] -// CHECK: keypath $KeyPath>, (root $SwiftProtocol; gettable_property $Optional, id #SwiftProtocol.subscript!getter.foreign : (Self) -> (Bool) -> Object, getter @$[[SWIFT_SUBSCR_GETTER:[_a-zA-Z0-9]+]] -// CHECK: keypath $ReferenceWritableKeyPath, (root $SwiftProtocol; gettable_property $Optional, id #SwiftProtocol.object!getter.foreign : (Self) -> () -> Object, getter @$[[SWIFT_PROP_GETTER]] : {{.*}}; optional_force : $Object; settable_property $String, -// CHECK: keypath $ReferenceWritableKeyPath, (root $SwiftProtocol; gettable_property $Optional, id #SwiftProtocol.subscript!getter.foreign : (Self) -> (Bool) -> Object, getter @$[[SWIFT_SUBSCR_GETTER]] : {{.*}}; optional_force : $Object; settable_property $String, -// CHECK: keypath $KeyPath>, (objc "flag"; root $ObjCProtocol; gettable_property $Optional, id #ObjCProtocol.flag!getter.foreign : (Self) -> () -> Bool, getter @$[[OBJC_PROP_GETTER:[_a-zA-Z0-9]+]] +// CHECK: keypath $KeyPath>, (objc "object"; root $any SwiftProtocol; gettable_property $Optional, id #SwiftProtocol.object!getter.foreign : (Self) -> () -> Object, getter @$[[SWIFT_PROP_GETTER:[_a-zA-Z0-9]+]] +// CHECK: keypath $KeyPath>, (root $any SwiftProtocol; gettable_property $Optional, id #SwiftProtocol.subscript!getter.foreign : (Self) -> (Bool) -> Object, getter @$[[SWIFT_SUBSCR_GETTER:[_a-zA-Z0-9]+]] +// CHECK: keypath $ReferenceWritableKeyPath, (root $any SwiftProtocol; gettable_property $Optional, id #SwiftProtocol.object!getter.foreign : (Self) -> () -> Object, getter @$[[SWIFT_PROP_GETTER]] : {{.*}}; optional_force : $Object; settable_property $String, +// CHECK: keypath $ReferenceWritableKeyPath, (root $any SwiftProtocol; gettable_property $Optional, id #SwiftProtocol.subscript!getter.foreign : (Self) -> (Bool) -> Object, getter @$[[SWIFT_SUBSCR_GETTER]] : {{.*}}; optional_force : $Object; settable_property $String, +// CHECK: keypath $KeyPath>, (objc "flag"; root $any ObjCProtocol; gettable_property $Optional, id #ObjCProtocol.flag!getter.foreign : (Self) -> () -> Bool, getter @$[[OBJC_PROP_GETTER:[_a-zA-Z0-9]+]] // CHECK: } // end sil function '${{.*}}testKeyPathAccessorsForOptionalStorageComponentsyyF' // -// CHECK: sil shared [thunk] [ossa] @$[[SWIFT_PROP_GETTER]] : $@convention(thin) (@in_guaranteed SwiftProtocol) -> @out Optional { -// CHECK: [[BASE:%[0-9]+]] = open_existential_ref {{%[0-9]+}} : $SwiftProtocol to $[[OPENED_TY:@opened\("[-A-F0-9]+", SwiftProtocol\) Self]] +// CHECK: sil shared [thunk] [ossa] @$[[SWIFT_PROP_GETTER]] : $@convention(thin) (@in_guaranteed any SwiftProtocol) -> @out Optional { +// CHECK: [[BASE:%[0-9]+]] = open_existential_ref {{%[0-9]+}} : $any SwiftProtocol to $[[OPENED_TY:@opened\("[-A-F0-9]+", any SwiftProtocol\) Self]] // CHECK: dynamic_method_br [[BASE]] : $[[OPENED_TY]], #SwiftProtocol.object!getter.foreign, bb1 // CHECK: bb1({{%[0-9]+}} : $@convention(objc_method) ([[OPENED_TY]]) -> @autoreleased Object) // CHECK: } // end sil function '$[[SWIFT_PROP_GETTER]]' // -// CHECK: sil shared [thunk] [ossa] @$[[SWIFT_SUBSCR_GETTER]] : $@convention(thin) (@in_guaranteed SwiftProtocol, UnsafeRawPointer) -> @out Optional { -// CHECK: [[BASE:%[0-9]+]] = open_existential_ref {{%[0-9]+}} : $SwiftProtocol to $[[OPENED_TY:@opened\("[-A-F0-9]+", SwiftProtocol\) Self]] +// CHECK: sil shared [thunk] [ossa] @$[[SWIFT_SUBSCR_GETTER]] : $@convention(thin) (@in_guaranteed any SwiftProtocol, UnsafeRawPointer) -> @out Optional { +// CHECK: [[BASE:%[0-9]+]] = open_existential_ref {{%[0-9]+}} : $any SwiftProtocol to $[[OPENED_TY:@opened\("[-A-F0-9]+", any SwiftProtocol\) Self]] // CHECK: [[INDEX:%[0-9]+]] = load [trivial] {{%[0-9]+}} : $*Bool // CHECK: dynamic_method_br [[BASE]] : $[[OPENED_TY]], #SwiftProtocol.subscript!getter.foreign, bb1, bb2 // CHECK: bb1({{%[0-9]+}} : $@convention(objc_method) (ObjCBool, [[OPENED_TY]]) -> @autoreleased Object): @@ -40,9 +40,9 @@ import Foundation // CHECK: bb2: // CHECK: } // end sil function '$[[SWIFT_SUBSCR_GETTER]]' // -// CHECK: sil shared [thunk] [ossa] @$[[OBJC_PROP_GETTER]] : $@convention(thin) (@in_guaranteed ObjCProtocol) -> @out Optional { +// CHECK: sil shared [thunk] [ossa] @$[[OBJC_PROP_GETTER]] : $@convention(thin) (@in_guaranteed any ObjCProtocol) -> @out Optional { // CHECK: bb0([[OUT:%[0-9]+]] : $*Optional, -// CHECK: [[BASE:%[0-9]+]] = open_existential_ref {{%[0-9]+}} : $ObjCProtocol to $[[OPENED_TY:@opened\("[-A-F0-9]+", ObjCProtocol\) Self]] +// CHECK: [[BASE:%[0-9]+]] = open_existential_ref {{%[0-9]+}} : $any ObjCProtocol to $[[OPENED_TY:@opened\("[-A-F0-9]+", any ObjCProtocol\) Self]] // CHECK: [[DEST:%[0-9]+]] = alloc_stack $Optional // CHECK: dynamic_method_br [[BASE]] : $[[OPENED_TY]], #ObjCProtocol.flag!getter.foreign, bb1, bb2 // CHECK: bb1({{%[0-9]+}} : $@convention(objc_method) ([[OPENED_TY]]) -> {{ObjCBool|Bool}}): diff --git a/test/SILGen/let_decls.swift b/test/SILGen/let_decls.swift index 312566c15a1be..3ee79c4f6f923 100644 --- a/test/SILGen/let_decls.swift +++ b/test/SILGen/let_decls.swift @@ -285,7 +285,7 @@ protocol SimpleProtocol { // methods on protocol and archetypes calls. // CHECK-LABEL: sil hidden [ossa] @{{.*}}testLetProtocolBases -// CHECK: bb0(%0 : $*SimpleProtocol): +// CHECK: bb0(%0 : $*any SimpleProtocol): func testLetProtocolBases(_ p : SimpleProtocol) { // CHECK-NEXT: debug_value {{.*}} expr op_deref // CHECK-NEXT: open_existential_addr @@ -320,9 +320,9 @@ func testLetArchetypeBases(_ p : T) { } // CHECK-LABEL: sil hidden [ossa] @{{.*}}testDebugValue -// CHECK: bb0(%0 : $Int, %1 : $*SimpleProtocol): +// CHECK: bb0(%0 : $Int, %1 : $*any SimpleProtocol): // CHECK-NEXT: debug_value %0 : $Int, let, name "a" -// CHECK-NEXT: debug_value %1 : $*SimpleProtocol, let, name "b", {{.*}} expr op_deref +// CHECK-NEXT: debug_value %1 : $*any SimpleProtocol, let, name "b", {{.*}} expr op_deref func testDebugValue(_ a : Int, b : SimpleProtocol) -> Int { // CHECK-NEXT: debug_value %0 : $Int, let, name "x" @@ -340,14 +340,14 @@ func testDebugValue(_ a : Int, b : SimpleProtocol) -> Int { // CHECK-LABEL: sil hidden [ossa] @{{.*}}testAddressOnlyTupleArgument func testAddressOnlyTupleArgument(_ bounds: (start: SimpleProtocol, pastEnd: Int)) { -// CHECK: bb0(%0 : $*SimpleProtocol, %1 : $Int): -// CHECK-NEXT: %2 = alloc_stack [lexical] $(start: SimpleProtocol, pastEnd: Int), let, name "bounds", argno 1 -// CHECK-NEXT: %3 = tuple_element_addr %2 : $*(start: SimpleProtocol, pastEnd: Int), 0 -// CHECK-NEXT: copy_addr %0 to [initialization] %3 : $*SimpleProtocol -// CHECK-NEXT: %5 = tuple_element_addr %2 : $*(start: SimpleProtocol, pastEnd: Int), 1 +// CHECK: bb0(%0 : $*any SimpleProtocol, %1 : $Int): +// CHECK-NEXT: %2 = alloc_stack [lexical] $(start: any SimpleProtocol, pastEnd: Int), let, name "bounds", argno 1 +// CHECK-NEXT: %3 = tuple_element_addr %2 : $*(start: any SimpleProtocol, pastEnd: Int), 0 +// CHECK-NEXT: copy_addr %0 to [initialization] %3 : $*any SimpleProtocol +// CHECK-NEXT: %5 = tuple_element_addr %2 : $*(start: any SimpleProtocol, pastEnd: Int), 1 // CHECK-NEXT: store %1 to [trivial] %5 : $*Int -// CHECK-NEXT: destroy_addr %2 : $*(start: SimpleProtocol, pastEnd: Int) -// CHECK-NEXT: dealloc_stack %2 : $*(start: SimpleProtocol, pastEnd: Int) +// CHECK-NEXT: destroy_addr %2 : $*(start: any SimpleProtocol, pastEnd: Int) +// CHECK-NEXT: dealloc_stack %2 : $*(start: any SimpleProtocol, pastEnd: Int) } @@ -484,10 +484,10 @@ func testLetPropertyAccessOnLValueBase(_ a : LetPropertyStruct) -> Int { var addressOnlyGetOnlyGlobalProperty : SimpleProtocol { get {} } // CHECK-LABEL: sil hidden [ossa] @$s9let_decls018testAddressOnlyGetE14GlobalPropertyAA14SimpleProtocol_pyF -// CHECK: bb0(%0 : $*SimpleProtocol): +// CHECK: bb0(%0 : $*any SimpleProtocol): // CHECK-NEXT: // function_ref // CHECK-NEXT: %1 = function_ref @$s9let_decls014addressOnlyGetD14GlobalPropertyAA14SimpleProtocol_pvg -// CHECK-NEXT: %2 = apply %1(%0) : $@convention(thin) () -> @out SimpleProtocol +// CHECK-NEXT: %2 = apply %1(%0) : $@convention(thin) () -> @out any SimpleProtocol // CHECK-NEXT: %3 = tuple () // CHECK-NEXT: return %3 : $() // CHECK-NEXT: } diff --git a/test/SILGen/lifetime.swift b/test/SILGen/lifetime.swift index 5c97be85307ab..fd2524c8343b0 100644 --- a/test/SILGen/lifetime.swift +++ b/test/SILGen/lifetime.swift @@ -260,8 +260,8 @@ struct Daleth { var c:Unloadable // -- address-only value constructor: - // CHECK-LABEL: sil hidden [ossa] @$s8lifetime6DalethV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@owned Aleph, @owned Beth, @in Unloadable, @thin Daleth.Type) -> @out Daleth { - // CHECK: bb0([[THIS:%.*]] : $*Daleth, [[A:%.*]] : @owned $Aleph, [[B:%.*]] : @owned $Beth, [[C:%.*]] : $*Unloadable, {{%.*}} : $@thin Daleth.Type): + // CHECK-LABEL: sil hidden [ossa] @$s8lifetime6DalethV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@owned Aleph, @owned Beth, @in any Unloadable, @thin Daleth.Type) -> @out Daleth { + // CHECK: bb0([[THIS:%.*]] : $*Daleth, [[A:%.*]] : @owned $Aleph, [[B:%.*]] : @owned $Beth, [[C:%.*]] : $*any Unloadable, {{%.*}} : $@thin Daleth.Type): // CHECK-NEXT: [[A_ADDR:%.*]] = struct_element_addr [[THIS]] : $*Daleth, #Daleth.a // CHECK-NEXT: store [[A]] to [init] [[A_ADDR]] // CHECK-NEXT: [[B_ADDR:%.*]] = struct_element_addr [[THIS]] : $*Daleth, #Daleth.b @@ -314,8 +314,8 @@ struct Zayin { var b:Unloadable // -- address-only value initializer with tuple destructuring: - // CHECK-LABEL: sil hidden [ossa] @$s8lifetime5ZayinV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@in Unloadable, Val, @in Unloadable, @thin Zayin.Type) -> @out Zayin - // CHECK: bb0([[THIS:%.*]] : $*Zayin, [[A0:%.*]] : $*Unloadable, [[A1:%.*]] : $Val, [[B:%.*]] : $*Unloadable, {{%.*}} : $@thin Zayin.Type): + // CHECK-LABEL: sil hidden [ossa] @$s8lifetime5ZayinV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@in any Unloadable, Val, @in any Unloadable, @thin Zayin.Type) -> @out Zayin + // CHECK: bb0([[THIS:%.*]] : $*Zayin, [[A0:%.*]] : $*any Unloadable, [[A1:%.*]] : $Val, [[B:%.*]] : $*any Unloadable, {{%.*}} : $@thin Zayin.Type): // CHECK-NEXT: [[THIS_A_ADDR:%.*]] = struct_element_addr [[THIS]] : $*Zayin, #Zayin.a // CHECK-NEXT: [[THIS_A0_ADDR:%.*]] = tuple_element_addr [[THIS_A_ADDR]] : {{.*}}, 0 // CHECK-NEXT: [[THIS_A1_ADDR:%.*]] = tuple_element_addr [[THIS_A_ADDR]] : {{.*}}, 1 diff --git a/test/SILGen/literals.swift b/test/SILGen/literals.swift index 0b8f2bc833410..fe5113f3200b1 100644 --- a/test/SILGen/literals.swift +++ b/test/SILGen/literals.swift @@ -218,21 +218,21 @@ struct NestedLValuePath { protocol WrapsSelfInArray {} -// CHECK-LABEL: sil hidden [ossa] @$s8literals16WrapsSelfInArrayPAAE04wrapdE0AA05TakesE7LiteralCyAaB_pGyF : $@convention(method) (@inout Self) -> @owned TakesArrayLiteral +// CHECK-LABEL: sil hidden [ossa] @$s8literals16WrapsSelfInArrayPAAE04wrapdE0AA05TakesE7LiteralCyAaB_pGyF : $@convention(method) (@inout Self) -> @owned TakesArrayLiteral // CHECK: [[ARRAY_LENGTH:%.*]] = integer_literal $Builtin.Word, 1 // CHECK: [[ALLOCATE_VARARGS:%.*]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF -// CHECK: [[ARR_TMP:%.*]] = apply [[ALLOCATE_VARARGS]]([[ARRAY_LENGTH]]) +// CHECK: [[ARR_TMP:%.*]] = apply [[ALLOCATE_VARARGS]]([[ARRAY_LENGTH]]) // CHECK: ([[ARR:%.*]], [[ADDRESS:%.*]]) = destructure_tuple [[ARR_TMP]] // CHECK: [[POINTER:%.*]] = pointer_to_address [[ADDRESS]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] %0 : $*Self -// CHECK: [[EXISTENTIAL:%.*]] = init_existential_addr [[POINTER]] : $*WrapsSelfInArray, $Self +// CHECK: [[EXISTENTIAL:%.*]] = init_existential_addr [[POINTER]] : $*any WrapsSelfInArray, $Self // CHECK: copy_addr [[ACCESS]] to [initialization] [[EXISTENTIAL]] : $*Self // CHECK: end_access [[ACCESS]] : $*Self // CHECK: [[FIN_FN:%.*]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF -// CHECK: [[FIN_ARR:%.*]] = apply [[FIN_FN]]([[ARR]]) -// CHECK: [[METATYPE:%.*]] = metatype $@thick TakesArrayLiteral.Type -// CHECK: [[CTOR:%.*]] = class_method [[METATYPE]] : $@thick TakesArrayLiteral.Type, #TakesArrayLiteral.init!allocator : (TakesArrayLiteral.Type) -> (Element...) -> TakesArrayLiteral, $@convention(method) -// CHECK: [[RESULT:%.*]] = apply [[CTOR]]([[FIN_ARR]], [[METATYPE]]) +// CHECK: [[FIN_ARR:%.*]] = apply [[FIN_FN]]([[ARR]]) +// CHECK: [[METATYPE:%.*]] = metatype $@thick TakesArrayLiteral.Type +// CHECK: [[CTOR:%.*]] = class_method [[METATYPE]] : $@thick TakesArrayLiteral.Type, #TakesArrayLiteral.init!allocator : (TakesArrayLiteral.Type) -> (Element...) -> TakesArrayLiteral, $@convention(method) +// CHECK: [[RESULT:%.*]] = apply [[CTOR]]([[FIN_ARR]], [[METATYPE]]) // CHECK: return [[RESULT]] extension WrapsSelfInArray { mutating func wrapInArray() -> TakesArrayLiteral { @@ -247,7 +247,7 @@ protocol FooProtocol { func makeThrowing() throws -> T { return T() } func makeBasic() -> T { return T() } -// CHECK-LABEL: sil hidden [ossa] @$s8literals15throwingElementSayxGyKAA11FooProtocolRzlF : $@convention(thin) () -> (@owned Array, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s8literals15throwingElementSayxGyKAA11FooProtocolRzlF : $@convention(thin) () -> (@owned Array, @error any Error) // CHECK: [[ARRAY_LENGTH:%.*]] = integer_literal $Builtin.Word, 2 // CHECK: [[ALLOCATE_VARARGS:%.*]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK: [[ARR_TMP:%.*]] = apply [[ALLOCATE_VARARGS]]([[ARRAY_LENGTH]]) @@ -265,11 +265,11 @@ func makeBasic() -> T { return T() } // CHECK: [[FIN_ARR:%.*]] = apply [[FIN_FN]]([[ARR]]) // CHECK: return [[FIN_ARR]] -// CHECK: bb2([[ERR:%.*]] : @owned $Error): +// CHECK: bb2([[ERR:%.*]] : @owned $any Error): // CHECK: destroy_addr [[POINTER]] : $*T // CHECK: [[DEALLOC:%.*]] = function_ref @$ss29_deallocateUninitializedArrayyySayxGnlF // CHECK: [[TMP:%.*]] = apply [[DEALLOC]]([[ARR]]) -// CHECK: throw [[ERR]] : $Error +// CHECK: throw [[ERR]] : $any Error func throwingElement() throws -> [T] { return try [makeBasic(), makeThrowing()] } diff --git a/test/SILGen/mangling.swift b/test/SILGen/mangling.swift index 2d401ff78c260..4f93ece3cd05d 100644 --- a/test/SILGen/mangling.swift +++ b/test/SILGen/mangling.swift @@ -144,25 +144,25 @@ func curry1() { } -// CHECK-LABEL: sil hidden [ossa] @$s8mangling3barSiyKF : $@convention(thin) () -> (Int, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s8mangling3barSiyKF : $@convention(thin) () -> (Int, @error any Error) func bar() throws -> Int { return 0 } -// CHECK-LABEL: sil hidden [ossa] @$s8mangling12curry1ThrowsyyKF : $@convention(thin) () -> @error Error +// CHECK-LABEL: sil hidden [ossa] @$s8mangling12curry1ThrowsyyKF : $@convention(thin) () -> @error any Error func curry1Throws() throws { } -// CHECK-LABEL: sil hidden [ossa] @$s8mangling12curry2ThrowsyycyKF : $@convention(thin) () -> (@owned @callee_guaranteed () -> (), @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s8mangling12curry2ThrowsyycyKF : $@convention(thin) () -> (@owned @callee_guaranteed () -> (), @error any Error) func curry2Throws() throws -> () -> () { return curry1 } -// CHECK-LABEL: sil hidden [ossa] @$s8mangling6curry3yyKcyF : $@convention(thin) () -> @owned @callee_guaranteed () -> @error Error +// CHECK-LABEL: sil hidden [ossa] @$s8mangling6curry3yyKcyF : $@convention(thin) () -> @owned @callee_guaranteed () -> @error any Error func curry3() -> () throws -> () { return curry1Throws } -// CHECK-LABEL: sil hidden [ossa] @$s8mangling12curry3ThrowsyyKcyKF : $@convention(thin) () -> (@owned @callee_guaranteed () -> @error Error, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s8mangling12curry3ThrowsyyKcyKF : $@convention(thin) () -> (@owned @callee_guaranteed () -> @error any Error, @error any Error) func curry3Throws() throws -> () throws -> () { return curry1Throws } diff --git a/test/SILGen/metatype_casts.swift b/test/SILGen/metatype_casts.swift index 59b2fadd13810..33847c5afee32 100644 --- a/test/SILGen/metatype_casts.swift +++ b/test/SILGen/metatype_casts.swift @@ -29,7 +29,7 @@ class FashionPolice {} // CHECK-LABEL: sil hidden [ossa] @$s14metatype_casts30anyObjectToExistentialMetatype{{[_0-9a-zA-Z]*}}F func anyObjectToExistentialMetatype(o: AnyObject) -> Emergency.Type? { - // CHECK: checked_cast_addr_br take_always AnyObject in {{%.*}} : $*AnyObject to Emergency.Type in {{%.*}} + // CHECK: checked_cast_addr_br take_always AnyObject in {{%.*}} : $*AnyObject to any Emergency.Type in {{%.*}} return o as? Emergency.Type } diff --git a/test/SILGen/metatype_object_conversion.swift b/test/SILGen/metatype_object_conversion.swift index 88d1d8dced43e..d55342724995c 100644 --- a/test/SILGen/metatype_object_conversion.swift +++ b/test/SILGen/metatype_object_conversion.swift @@ -19,7 +19,7 @@ func metatypeToObject(_ x: C.Type) -> AnyObject { // CHECK-LABEL: sil hidden [ossa] @$s26metatype_object_conversion27existentialMetatypeToObjectyyXlAA2CP_pXpF func existentialMetatypeToObject(_ x: CP.Type) -> AnyObject { - // CHECK: bb0([[THICK:%.*]] : $@thick CP.Type): + // CHECK: bb0([[THICK:%.*]] : $@thick any CP.Type): // CHECK: [[OBJC:%.*]] = thick_to_objc_metatype [[THICK]] // CHECK: [[OBJECT:%.*]] = objc_existential_metatype_to_object [[OBJC]] // CHECK: return [[OBJECT]] diff --git a/test/SILGen/metatypes.swift b/test/SILGen/metatypes.swift index 88f7740a1c4b2..b9e49ae46a7fa 100644 --- a/test/SILGen/metatypes.swift +++ b/test/SILGen/metatypes.swift @@ -63,7 +63,7 @@ func archetype_metatypes(t: T) -> (T.Type, T.Type) { // CHECK-LABEL: sil hidden [ossa] @$s9metatypes012existential_A0{{[_0-9a-zA-Z]*}}F func existential_metatypes(p: SomeProtocol) -> SomeProtocol.Type { - // CHECK: existential_metatype $@thick SomeProtocol.Type + // CHECK: existential_metatype $@thick any SomeProtocol.Type return type(of: p) } @@ -79,24 +79,24 @@ func generic_metatypes(x: T) // rdar://16610078 -// CHECK-LABEL: sil hidden [ossa] @$s9metatypes30existential_metatype_from_thinypXpyF : $@convention(thin) () -> @thick Any.Type +// CHECK-LABEL: sil hidden [ossa] @$s9metatypes30existential_metatype_from_thinypXpyF : $@convention(thin) () -> @thick any Any.Type // CHECK: [[T0:%.*]] = metatype $@thin SomeStruct.Type // CHECK-NEXT: [[T1:%.*]] = metatype $@thick SomeStruct.Type -// CHECK-NEXT: [[T2:%.*]] = init_existential_metatype [[T1]] : $@thick SomeStruct.Type, $@thick Any.Type -// CHECK-NEXT: return [[T2]] : $@thick Any.Type +// CHECK-NEXT: [[T2:%.*]] = init_existential_metatype [[T1]] : $@thick SomeStruct.Type, $@thick any Any.Type +// CHECK-NEXT: return [[T2]] : $@thick any Any.Type func existential_metatype_from_thin() -> Any.Type { return SomeStruct.self } -// CHECK-LABEL: sil hidden [ossa] @$s9metatypes36existential_metatype_from_thin_valueypXpyF : $@convention(thin) () -> @thick Any.Type +// CHECK-LABEL: sil hidden [ossa] @$s9metatypes36existential_metatype_from_thin_valueypXpyF : $@convention(thin) () -> @thick any Any.Type // CHECK: [[T1:%.*]] = metatype $@thin SomeStruct.Type // CHECK: [[T0:%.*]] = function_ref @$s9metatypes10SomeStructV{{[_0-9a-zA-Z]*}}fC // CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]]) // CHECK-NEXT: debug_value [[T2]] : $SomeStruct, let, name "s" // CHECK-NEXT: [[T0:%.*]] = metatype $@thin SomeStruct.Type // CHECK-NEXT: [[T1:%.*]] = metatype $@thick SomeStruct.Type -// CHECK-NEXT: [[T2:%.*]] = init_existential_metatype [[T1]] : $@thick SomeStruct.Type, $@thick Any.Type -// CHECK-NEXT: return [[T2]] : $@thick Any.Type +// CHECK-NEXT: [[T2:%.*]] = init_existential_metatype [[T1]] : $@thick SomeStruct.Type, $@thick any Any.Type +// CHECK-NEXT: return [[T2]] : $@thick any Any.Type func existential_metatype_from_thin_value() -> Any.Type { let s = SomeStruct() return type(of: s) diff --git a/test/SILGen/noimplicitcopy.swift b/test/SILGen/noimplicitcopy.swift index 924586db1c767..b760394d9afcd 100644 --- a/test/SILGen/noimplicitcopy.swift +++ b/test/SILGen/noimplicitcopy.swift @@ -158,7 +158,7 @@ func callPrintIntOwnedArg() { let _ = y } -// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error any Error { // CHECK: bb0([[ARG:%.*]] : @noImplicitCopy $Int): // CHECK: [[ARG_WRAPPED:%.*]] = copyable_to_moveonlywrapper [owned] [[ARG]] // CHECK: [[LEXICAL_ARG:%.*]] = move_value [lexical] [[ARG_WRAPPED]] @@ -171,7 +171,7 @@ func callPrintIntOwnedArg() { // CHECK: apply [[FUNC]]([[GUARANTEED_ESCAPED_X_1]], [[GUARANTEED_ESCAPED_X_2]], {{.*}}) // CHECK: } // end sil function '$s14noimplicitcopy17printIntArgThrowsyySiKF' // -// SIL-LABEL: sil hidden @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error Error { +// SIL-LABEL: sil hidden @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error any Error { // SIL-NOT: @moveOnly // SIL: } // end sil function '$s14noimplicitcopy17printIntArgThrowsyySiKF' func printIntArgThrows(@_noImplicitCopy _ x: Int) throws { @@ -179,15 +179,15 @@ func printIntArgThrows(@_noImplicitCopy _ x: Int) throws { print("printIntArgThrows: \(x)") } -// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy21callPrintIntArgThrowsyyKF : $@convention(thin) () -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy21callPrintIntArgThrowsyyKF : $@convention(thin) () -> @error any Error { // CHECK: [[INT_LITERAL_FUNC:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // CHECK: [[VALUE:%.*]] = apply [[INT_LITERAL_FUNC]]( -// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error any Error // CHECK: try_apply [[FUNC]]([[VALUE]]) // // CHECK: [[INT_LITERAL_FUNC:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // CHECK: [[VALUE:%.*]] = apply [[INT_LITERAL_FUNC]]( -// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error any Error // CHECK: try_apply [[FUNC]]([[VALUE]]) // // CHECK: [[Y_BOX:%.*]] = alloc_box ${ var Int } @@ -195,7 +195,7 @@ func printIntArgThrows(@_noImplicitCopy _ x: Int) throws { // CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX_BORROWED]] // CHECK: [[Y_BOX_PROJECT_ACCESS:%.*]] = begin_access [read] [unknown] [[Y_BOX_PROJECT]] // CHECK: [[Y_VALUE:%.*]] = load [trivial] [[Y_BOX_PROJECT_ACCESS]] -// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error any Error // CHECK: try_apply [[FUNC]]([[Y_VALUE]]) // CHECK: } // end sil function '$s14noimplicitcopy21callPrintIntArgThrowsyyKF' func callPrintIntArgThrows() throws { @@ -208,11 +208,11 @@ func callPrintIntArgThrows() throws { let _ = y } -// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error any Error { // CHECK: bb0(%0 : @noImplicitCopy $Int): // CHECK: } // end sil function '$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF' // -// SIL-LABEL: sil hidden @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error Error { +// SIL-LABEL: sil hidden @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error any Error { // SIL-NOT: @moveOnly // SIL: } // end sil function '$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF' func printIntOwnedArgThrows(@_noImplicitCopy _ x: __owned Int) throws { @@ -220,15 +220,15 @@ func printIntOwnedArgThrows(@_noImplicitCopy _ x: __owned Int) throws { print("printIntOwnedArgThrows: \(x)") } -// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy26callPrintIntOwnedArgThrowsyyKF : $@convention(thin) () -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy26callPrintIntOwnedArgThrowsyyKF : $@convention(thin) () -> @error any Error { // CHECK: [[INT_LITERAL_FUNC:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // CHECK: [[VALUE:%.*]] = apply [[INT_LITERAL_FUNC]]( -// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error any Error // CHECK: try_apply [[FUNC]]([[VALUE]]) // // CHECK: [[INT_LITERAL_FUNC:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // CHECK: [[VALUE:%.*]] = apply [[INT_LITERAL_FUNC]]( -// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error any Error // CHECK: try_apply [[FUNC]]([[VALUE]]) // // CHECK: [[Y_BOX:%.*]] = alloc_box ${ var Int } @@ -236,7 +236,7 @@ func printIntOwnedArgThrows(@_noImplicitCopy _ x: __owned Int) throws { // CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX_BORROWED]] // CHECK: [[Y_BOX_PROJECT_ACCESS:%.*]] = begin_access [read] [unknown] [[Y_BOX_PROJECT]] // CHECK: [[Y_VALUE:%.*]] = load [trivial] [[Y_BOX_PROJECT_ACCESS]] -// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error any Error // CHECK: try_apply [[FUNC]]([[Y_VALUE]]) // CHECK: } // end sil function '$s14noimplicitcopy26callPrintIntOwnedArgThrowsyyKF' func callPrintIntOwnedArgThrows() throws { @@ -410,7 +410,7 @@ func callPrintKlassOwnedArg() { printKlassOwnedArg(y) } -// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy19printKlassArgThrowsyyAA0C0CKF : $@convention(thin) (@guaranteed Klass) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy19printKlassArgThrowsyyAA0C0CKF : $@convention(thin) (@guaranteed Klass) -> @error any Error { // CHECK: bb0([[ARG:%.*]] : @noImplicitCopy @guaranteed $Klass): // CHECK: [[WRAPPED_ARG:%.*]] = copyable_to_moveonlywrapper [guaranteed] [[ARG]] // CHECK: [[COPIED_ARG:%.*]] = copy_value [[WRAPPED_ARG]] @@ -420,7 +420,7 @@ func callPrintKlassOwnedArg() { // CHECK: apply {{%.*}}([[UNWRAPPED_ARG]]) : // CHECK: } // end sil function '$s14noimplicitcopy19printKlassArgThrowsyyAA0C0CKF' // -// SIL-LABEL: sil hidden @$s14noimplicitcopy19printKlassArgThrowsyyAA0C0CKF : $@convention(thin) (@guaranteed Klass) -> @error Error { +// SIL-LABEL: sil hidden @$s14noimplicitcopy19printKlassArgThrowsyyAA0C0CKF : $@convention(thin) (@guaranteed Klass) -> @error any Error { // SIL-NOT: @moveOnly // SIL: } // end sil function '$s14noimplicitcopy19printKlassArgThrowsyyAA0C0CKF' func printKlassArgThrows(@_noImplicitCopy _ x: Klass) throws { @@ -438,7 +438,7 @@ func callPrintKlassArgThrows() throws { try printKlassArgThrows(y) } -// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy24printKlassOwnedArgThrowsyyAA0C0CnKF : $@convention(thin) (@owned Klass) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s14noimplicitcopy24printKlassOwnedArgThrowsyyAA0C0CnKF : $@convention(thin) (@owned Klass) -> @error any Error { // CHECK: bb0([[ARG:%.*]] : @noImplicitCopy @owned $Klass): // CHECK: [[WRAPPED_ARG:%.*]] = copyable_to_moveonlywrapper [owned] [[ARG]] // CHECK: [[MOVED_ARG:%.*]] = move_value [lexical] [[WRAPPED_ARG]] @@ -448,7 +448,7 @@ func callPrintKlassArgThrows() throws { // CHECK: apply {{%.*}}([[UNWRAPPED_ARG]]) : // CHECK: } // end sil function '$s14noimplicitcopy24printKlassOwnedArgThrowsyyAA0C0CnKF' // -// SIL-LABEL: sil hidden @$s14noimplicitcopy24printKlassOwnedArgThrowsyyAA0C0CnKF : $@convention(thin) (@owned Klass) -> @error Error { +// SIL-LABEL: sil hidden @$s14noimplicitcopy24printKlassOwnedArgThrowsyyAA0C0CnKF : $@convention(thin) (@owned Klass) -> @error any Error { // SIL-NOT: @moveOnly // SIL: } // end sil function '$s14noimplicitcopy24printKlassOwnedArgThrowsyyAA0C0CnKF' func printKlassOwnedArgThrows(@_noImplicitCopy _ x: __owned Klass) throws { diff --git a/test/SILGen/objc_async.swift b/test/SILGen/objc_async.swift index 17d923edf68c6..d137483bc55eb 100644 --- a/test/SILGen/objc_async.swift +++ b/test/SILGen/objc_async.swift @@ -34,11 +34,11 @@ func testSlowServer(slowServer: SlowServer) async throws { // CHECK: [[RESUME_BUF:%.*]] = alloc_stack $String // CHECK: [[METHOD:%.*]] = objc_method {{.*}} $@convention(objc_method) (@convention(block) (Optional, Optional) -> (), SlowServer) -> () // CHECK: [[CONT:%.*]] = get_async_continuation_addr [throws] String, [[RESUME_BUF]] - // CHECK: [[WRAPPED:%.*]] = struct $UnsafeContinuation ([[CONT]] : $Builtin.RawUnsafeContinuation) - // CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage UnsafeContinuation + // CHECK: [[WRAPPED:%.*]] = struct $UnsafeContinuation ([[CONT]] : $Builtin.RawUnsafeContinuation) + // CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage UnsafeContinuation // CHECK: [[CONT_SLOT:%.*]] = project_block_storage [[BLOCK_STORAGE]] // CHECK: store [[WRAPPED]] to [trivial] [[CONT_SLOT]] - // CHECK: [[BLOCK_IMPL:%.*]] = function_ref @[[STRING_COMPLETION_THROW_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation, Optional, Optional) -> () + // CHECK: [[BLOCK_IMPL:%.*]] = function_ref @[[STRING_COMPLETION_THROW_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation, Optional, Optional) -> () // CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] {{.*}}, invoke [[BLOCK_IMPL]] // CHECK: apply [[METHOD]]([[BLOCK]], %0) // CHECK: await_async_continuation [[CONT]] {{.*}}, resume [[RESUME:bb[0-9]+]], error [[ERROR:bb[0-9]+]] @@ -52,22 +52,22 @@ func testSlowServer(slowServer: SlowServer) async throws { // CHECK: [[BLOCK_IMPL:%.*]] = function_ref @[[VOID_COMPLETION_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<(), Never>) -> () await slowServer.serverRestart("somewhere") - // CHECK: function_ref @[[STRING_NONZERO_FLAG_THROW_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation, {{.*}}Bool, Optional, Optional) -> () + // CHECK: function_ref @[[STRING_NONZERO_FLAG_THROW_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation, {{.*}}Bool, Optional, Optional) -> () let _: String = try await slowServer.doSomethingFlaggy() - // CHECK: function_ref @[[STRING_ZERO_FLAG_THROW_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation, Optional, {{.*}}Bool, Optional) -> () + // CHECK: function_ref @[[STRING_ZERO_FLAG_THROW_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation, Optional, {{.*}}Bool, Optional) -> () let _: String = try await slowServer.doSomethingZeroFlaggy() - // CHECK: function_ref @[[STRING_STRING_ZERO_FLAG_THROW_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<(String, String), Error>, {{.*}}Bool, Optional, Optional, Optional) -> () + // CHECK: function_ref @[[STRING_STRING_ZERO_FLAG_THROW_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<(String, String), any Error>, {{.*}}Bool, Optional, Optional, Optional) -> () let _: (String, String) = try await slowServer.doSomethingMultiResultFlaggy() - // CHECK: [[BLOCK_IMPL:%.*]] = function_ref @[[NSSTRING_INT_THROW_COMPLETION_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<(String, Int), Error>, Optional, Int, Optional) -> () + // CHECK: [[BLOCK_IMPL:%.*]] = function_ref @[[NSSTRING_INT_THROW_COMPLETION_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<(String, Int), any Error>, Optional, Int, Optional) -> () let (_, _): (String, Int) = try await slowServer.findMultipleAnswers() let (_, _): (Bool, Bool) = try await slowServer.findDifferentlyFlavoredBooleans() - // CHECK: [[ERROR]]([[ERROR_VALUE:%.*]] : @owned $Error): + // CHECK: [[ERROR]]([[ERROR_VALUE:%.*]] : @owned $any Error): // CHECK: dealloc_stack [[RESUME_BUF]] // CHECK: br [[THROWBB:bb[0-9]+]]([[ERROR_VALUE]] - // CHECK: [[THROWBB]]([[ERROR_VALUE:%.*]] : @owned $Error): + // CHECK: [[THROWBB]]([[ERROR_VALUE:%.*]] : @owned $any Error): // CHECK: throw [[ERROR_VALUE]] let _: String = await slowServer.findAnswerNullably("foo") @@ -209,16 +209,16 @@ func testThrowingMethodFromMain(slowServer: SlowServer) async -> String { // CHECK: [[STRING_ARG:%.*]] = apply {{%.*}}({{%.*}}) : $@convention(method) (@guaranteed String) -> @owned NSString // CHECK: [[METH:%.*]] = objc_method {{%.*}} : $SlowServer, #SlowServer.doSomethingDangerous!foreign // CHECK: [[RAW_CONT:%.*]] = get_async_continuation_addr [throws] String, [[RESULT_BUF]] : $*String -// CHECK: [[CONT:%.*]] = struct $UnsafeContinuation ([[RAW_CONT]] : $Builtin.RawUnsafeContinuation) -// CHECK: [[STORE_ALLOC:%.*]] = alloc_stack $@block_storage UnsafeContinuation +// CHECK: [[CONT:%.*]] = struct $UnsafeContinuation ([[RAW_CONT]] : $Builtin.RawUnsafeContinuation) +// CHECK: [[STORE_ALLOC:%.*]] = alloc_stack $@block_storage UnsafeContinuation // CHECK: [[PROJECTED:%.*]] = project_block_storage [[STORE_ALLOC]] : $*@block_storage -// CHECK: store [[CONT]] to [trivial] [[PROJECTED]] : $*UnsafeContinuation +// CHECK: store [[CONT]] to [trivial] [[PROJECTED]] : $*UnsafeContinuation // CHECK: [[INVOKER:%.*]] = function_ref @$sSo8NSStringCSgSo7NSErrorCSgIeyByy_SSTz_ // CHECK: [[BLOCK:%.*]] = init_block_storage_header [[STORE_ALLOC]] {{.*}}, invoke [[INVOKER]] // CHECK: [[OPTIONAL_BLK:%.*]] = enum {{.*}}, #Optional.some!enumelt, [[BLOCK]] // CHECK: %28 = apply [[METH]]([[STRING_ARG]], [[OPTIONAL_BLK]], {{%.*}}) : $@convention(objc_method) (NSString, Optional<@convention(block) (Optional, Optional) -> ()>, SlowServer) -> () // CHECK: [[STRING_ARG_COPY:%.*]] = copy_value [[STRING_ARG]] : $NSString -// CHECK: dealloc_stack [[STORE_ALLOC]] : $*@block_storage UnsafeContinuation +// CHECK: dealloc_stack [[STORE_ALLOC]] : $*@block_storage UnsafeContinuation // CHECK: destroy_value [[STRING_ARG]] : $NSString // CHECK: await_async_continuation [[RAW_CONT]] : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]], error [[ERROR:bb[0-9]+]] diff --git a/test/SILGen/objc_async_from_swift.swift b/test/SILGen/objc_async_from_swift.swift index f85e52162ae93..58888f59b1379 100644 --- a/test/SILGen/objc_async_from_swift.swift +++ b/test/SILGen/objc_async_from_swift.swift @@ -78,7 +78,7 @@ class SlowSwiftServer: NSObject, SlowServing { // CHECK: [[BLOCK_BORROW:%.*]] = begin_borrow [[BLOCK_COPY]] // CHECK: [[NIL_ERROR:%.*]] = enum $Optional, #Optional.none // CHECK: apply [[BLOCK_BORROW]]({{%.*}}, [[NIL_ERROR]]) - // CHECK: [[ERROR]]([[NATIVE_RESULT:%.*]] : @owned $Error): + // CHECK: [[ERROR]]([[NATIVE_RESULT:%.*]] : @owned $any Error): // CHECK: [[BLOCK_BORROW:%.*]] = begin_borrow [[BLOCK_COPY]] // CHECK: [[NIL_NSSTRING:%.*]] = enum $Optional, #Optional.none // CHECK: apply [[BLOCK_BORROW]]([[NIL_NSSTRING]], {{%.*}}) diff --git a/test/SILGen/objc_bridging_any.swift b/test/SILGen/objc_bridging_any.swift index e44a5b4373fe9..5034dd05ac71d 100644 --- a/test/SILGen/objc_bridging_any.swift +++ b/test/SILGen/objc_bridging_any.swift @@ -29,10 +29,10 @@ func passingToId(receiver: NSIdLover, // CHECK: debug_value [[NSSTRING:%.*]] : $NSString // CHECK: debug_value [[OBJECT:%.*]] : $AnyObject // CHECK: debug_value [[CLASS_GENERIC:%.*]] : $T - // CHECK: debug_value [[CLASS_EXISTENTIAL:%.*]] : $CP + // CHECK: debug_value [[CLASS_EXISTENTIAL:%.*]] : $any CP // CHECK: debug_value [[GENERIC:%.*]] : $*U, {{.*}} expr op_deref - // CHECK: debug_value [[EXISTENTIAL:%.*]] : $*P, {{.*}} expr op_deref - // CHECK: debug_value [[ERROR:%.*]] : $Error + // CHECK: debug_value [[EXISTENTIAL:%.*]] : $*any P, {{.*}} expr op_deref + // CHECK: debug_value [[ERROR:%.*]] : $any Error // CHECK: debug_value [[ANY:%.*]] : $*Any, {{.*}} expr op_deref // CHECK: debug_value [[KNOWN_UNBRIDGED:%.*]] : $KnownUnbridged // CHECK: debug_value [[OPT_STRING:%.*]] : $Optional @@ -72,7 +72,7 @@ func passingToId(receiver: NSIdLover, receiver.takesId(object) // CHECK: [[CLASS_EXISTENTIAL_COPY:%.*]] = copy_value [[CLASS_EXISTENTIAL]] - // CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $CP + // CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $any CP // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]] // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover, // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]]) @@ -92,9 +92,9 @@ func passingToId(receiver: NSIdLover, // CHECK: destroy_value [[ANYOBJECT]] receiver.takesId(generic) - // CHECK: [[COPY:%.*]] = alloc_stack $P + // CHECK: [[COPY:%.*]] = alloc_stack $any P // CHECK: copy_addr [[EXISTENTIAL]] to [initialization] [[COPY]] - // CHECK: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*P to $*[[OPENED_TYPE:@opened\(.*, P\) Self]], + // CHECK: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*any P to $*[[OPENED_TYPE:@opened\(.*, any P\) Self]], // CHECK: [[TMP:%.*]] = alloc_stack $[[OPENED_TYPE]] // CHECK: copy_addr [[OPENED_COPY]] to [initialization] [[TMP]] // CHECK: // function_ref _bridgeAnythingToObjectiveC @@ -108,15 +108,15 @@ func passingToId(receiver: NSIdLover, // CHECK: destroy_value [[ANYOBJECT]] receiver.takesId(existential) - // CHECK: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] : $Error + // CHECK: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] : $any Error // CHECK: [[BORROWED_ERROR_COPY:%.*]] = begin_borrow [[ERROR_COPY]] - // CHECK: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[BORROWED_ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]], Error) Self - // CHECK: [[ERROR_STACK:%[0-9]+]] = alloc_stack $@opened([[ERROR_ARCHETYPE]], Error) Self - // CHECK: copy_addr [[ERROR_BOX]] to [initialization] [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]], Error) Self + // CHECK: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[BORROWED_ERROR_COPY]] : $any Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]], any Error) Self + // CHECK: [[ERROR_STACK:%[0-9]+]] = alloc_stack $@opened([[ERROR_ARCHETYPE]], any Error) Self + // CHECK: copy_addr [[ERROR_BOX]] to [initialization] [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]], any Error) Self // CHECK: [[BRIDGE_FUNCTION:%[0-9]+]] = function_ref @$ss27_bridgeAnythingToObjectiveCyyXlxlF - // CHECK: [[BRIDGED_ERROR:%[0-9]+]] = apply [[BRIDGE_FUNCTION]]<@opened([[ERROR_ARCHETYPE]], Error) Self>([[ERROR_STACK]]) - // CHECK: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]], Error) Self - // CHECK: destroy_value [[ERROR_COPY]] : $Error + // CHECK: [[BRIDGED_ERROR:%[0-9]+]] = apply [[BRIDGE_FUNCTION]]<@opened([[ERROR_ARCHETYPE]], any Error) Self>([[ERROR_STACK]]) + // CHECK: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]], any Error) Self + // CHECK: destroy_value [[ERROR_COPY]] : $any Error // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover, // CHECK: apply [[METHOD]]([[BRIDGED_ERROR]], [[SELF]]) // CHECK: destroy_value [[BRIDGED_ERROR]] : $AnyObject @@ -228,19 +228,19 @@ func passingToNullableId(receiver: NSIdLover, // CHECK: [[NSSTRING:%.*]] : $NSString // CHECK: [[OBJECT:%.*]] : $AnyObject // CHECK: [[CLASS_GENERIC:%.*]] : $T - // CHECK: [[CLASS_EXISTENTIAL:%.*]] : $CP + // CHECK: [[CLASS_EXISTENTIAL:%.*]] : $any CP // CHECK: [[GENERIC:%.*]] : $*U - // CHECK: [[EXISTENTIAL:%.*]] : $*P - // CHECK: [[ERROR:%.*]] : $Error + // CHECK: [[EXISTENTIAL:%.*]] : $*any P + // CHECK: [[ERROR:%.*]] : $any Error // CHECK: [[ANY:%.*]] : $*Any, // CHECK: [[KNOWN_UNBRIDGED:%.*]] : $KnownUnbridged, // CHECK: [[OPT_STRING:%.*]] : $Optional, // CHECK: [[OPT_NSSTRING:%.*]] : $Optional // CHECK: [[OPT_OBJECT:%.*]] : $Optional // CHECK: [[OPT_CLASS_GENERIC:%.*]] : $Optional - // CHECK: [[OPT_CLASS_EXISTENTIAL:%.*]] : $Optional + // CHECK: [[OPT_CLASS_EXISTENTIAL:%.*]] : $Optional // CHECK: [[OPT_GENERIC:%.*]] : $*Optional - // CHECK: [[OPT_EXISTENTIAL:%.*]] : $*Optional

+ // CHECK: [[OPT_EXISTENTIAL:%.*]] : $*Optional // CHECK: [[OPT_ANY:%.*]] : $*Optional // CHECK: [[OPT_KNOWN_UNBRIDGED:%.*]] : $Optional // CHECK: [[OPT_OPT_A:%.*]] : $Optional> @@ -281,7 +281,7 @@ func passingToNullableId(receiver: NSIdLover, receiver.takesNullableId(classGeneric) // CHECK: [[CLASS_EXISTENTIAL_COPY:%.*]] = copy_value [[CLASS_EXISTENTIAL]] - // CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $CP + // CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $any CP // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]] // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]] // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover, @@ -302,9 +302,9 @@ func passingToNullableId(receiver: NSIdLover, // CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]] receiver.takesNullableId(generic) - // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $P + // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $any P // CHECK-NEXT: copy_addr [[EXISTENTIAL]] to [initialization] [[COPY]] - // CHECK-NEXT: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*P to $*[[OPENED_TYPE:@opened\(.*, P\) Self]], + // CHECK-NEXT: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*any P to $*[[OPENED_TYPE:@opened\(.*, any P\) Self]], // CHECK: [[TMP:%.*]] = alloc_stack $[[OPENED_TYPE]] // CHECK: copy_addr [[OPENED_COPY]] to [initialization] [[TMP]] // CHECK-NEXT: // function_ref _bridgeAnythingToObjectiveC @@ -320,18 +320,18 @@ func passingToNullableId(receiver: NSIdLover, // CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]] receiver.takesNullableId(existential) - // CHECK-NEXT: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] : $Error + // CHECK-NEXT: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] : $any Error // CHECK-NEXT: [[BORROWED_ERROR_COPY:%.*]] = begin_borrow [[ERROR_COPY]] - // CHECK-NEXT: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[BORROWED_ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]], Error) Self - // CHECK-NEXT: [[ERROR_STACK:%[0-9]+]] = alloc_stack $@opened([[ERROR_ARCHETYPE]], Error) Self - // CHECK-NEXT: copy_addr [[ERROR_BOX]] to [initialization] [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]], Error) Self + // CHECK-NEXT: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[BORROWED_ERROR_COPY]] : $any Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]], any Error) Self + // CHECK-NEXT: [[ERROR_STACK:%[0-9]+]] = alloc_stack $@opened([[ERROR_ARCHETYPE]], any Error) Self + // CHECK-NEXT: copy_addr [[ERROR_BOX]] to [initialization] [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]], any Error) Self // CHECK-NEXT: end_borrow [[BORROWED_ERROR_COPY]] // CHECK: [[BRIDGE_FUNCTION:%[0-9]+]] = function_ref @$ss27_bridgeAnythingToObjectiveCyyXlxlF - // CHECK-NEXT: [[BRIDGED_ERROR:%[0-9]+]] = apply [[BRIDGE_FUNCTION]]<@opened([[ERROR_ARCHETYPE]], Error) Self>([[ERROR_STACK]]) + // CHECK-NEXT: [[BRIDGED_ERROR:%[0-9]+]] = apply [[BRIDGE_FUNCTION]]<@opened([[ERROR_ARCHETYPE]], any Error) Self>([[ERROR_STACK]]) // CHECK-NEXT: [[BRIDGED_ERROR_OPT:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, [[BRIDGED_ERROR]] : $AnyObject // CHECK-NEXT: destroy_addr [[ERROR_STACK]] - // CHECK-NEXT: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]], Error) Self - // CHECK-NEXT: destroy_value [[ERROR_COPY]] : $Error + // CHECK-NEXT: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]], any Error) Self + // CHECK-NEXT: destroy_value [[ERROR_COPY]] : $any Error // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover, // CHECK-NEXT: apply [[METHOD]]([[BRIDGED_ERROR_OPT]], [[SELF]]) // CHECK-NEXT: destroy_value [[BRIDGED_ERROR_OPT]] diff --git a/test/SILGen/objc_bridging_array.swift b/test/SILGen/objc_bridging_array.swift index f550e78752db7..7c0b86a2b9a6d 100644 --- a/test/SILGen/objc_bridging_array.swift +++ b/test/SILGen/objc_bridging_array.swift @@ -15,8 +15,8 @@ func setChildren(p: Parent, c: Child) { p.children = [c] } -// CHECK-LABEL: sil hidden [ossa] @$s19objc_bridging_array11setChildren1p1cyAA6Parent_p_AA5ChildCtF : $@convention(thin) (@guaranteed Parent, @guaranteed Child) -> () { -// CHECK: [[OPENED:%.*]] = open_existential_ref %0 : $Parent to $[[OPENED_TYPE:@opened\(.*, Parent\) Self]] +// CHECK-LABEL: sil hidden [ossa] @$s19objc_bridging_array11setChildren1p1cyAA6Parent_p_AA5ChildCtF : $@convention(thin) (@guaranteed any Parent, @guaranteed Child) -> () { +// CHECK: [[OPENED:%.*]] = open_existential_ref %0 : $any Parent to $[[OPENED_TYPE:@opened\(.*, any Parent\) Self]] // CHECK: [[COPIED:%.*]] = copy_value [[OPENED]] : $[[OPENED_TYPE]] // CHECK: [[LENGTH:%.*]] = integer_literal $Builtin.Word, 1 // CHECK: [[FN:%.*]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) diff --git a/test/SILGen/objc_effectful_properties.swift b/test/SILGen/objc_effectful_properties.swift index 32dc203b39065..bebf2292c6dad 100644 --- a/test/SILGen/objc_effectful_properties.swift +++ b/test/SILGen/objc_effectful_properties.swift @@ -30,11 +30,11 @@ func testAsyncThrows(eff : EffProps) async { // CHECK: [[RESUME_BUF:%.*]] = alloc_stack $Optional // CHECK: [[METHOD:%.*]] = objc_method {{.*}} $@convention(objc_method) (@convention(block) (Optional, Optional) -> (), EffProps) -> () // CHECK: [[CONT:%.*]] = get_async_continuation_addr [throws] Optional, [[RESUME_BUF]] - // CHECK: [[WRAPPED:%.*]] = struct $UnsafeContinuation, Error> ([[CONT]] : $Builtin.RawUnsafeContinuation) - // CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage UnsafeContinuation, Error> + // CHECK: [[WRAPPED:%.*]] = struct $UnsafeContinuation, any Error> ([[CONT]] : $Builtin.RawUnsafeContinuation) + // CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage UnsafeContinuation, any Error> // CHECK: [[CONT_SLOT:%.*]] = project_block_storage [[BLOCK_STORAGE]] // CHECK: store [[WRAPPED]] to [trivial] [[CONT_SLOT]] - // CHECK: [[BLOCK_IMPL:%.*]] = function_ref @[[NSO_COMPLETION_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation, Error>, Optional, Optional) -> () + // CHECK: [[BLOCK_IMPL:%.*]] = function_ref @[[NSO_COMPLETION_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation, any Error>, Optional, Optional) -> () // CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] {{.*}}, invoke [[BLOCK_IMPL]] // CHECK: apply [[METHOD]]([[BLOCK]], %0) // CHECK: await_async_continuation [[CONT]] {{.*}}, resume [[RESUME:bb[0-9]+]], error [[RESUME_ERROR:bb[0-9]+]] @@ -43,7 +43,7 @@ func testAsyncThrows(eff : EffProps) async { // CHECK: [[RESULT:%.*]] = load [take] [[RESUME_BUF]] // CHECK: dealloc_stack [[RESUME_BUF]] - // CHECK: [[RESUME_ERROR]]([[ERROR_VAL:%[0-9]+]] : @owned $Error): + // CHECK: [[RESUME_ERROR]]([[ERROR_VAL:%[0-9]+]] : @owned $any Error): // CHECK: dealloc_stack [[RESUME_BUF]] let _ = try? await eff.catto } diff --git a/test/SILGen/objc_error.swift b/test/SILGen/objc_error.swift index 09fbac59f0cb0..dc364979af1f2 100644 --- a/test/SILGen/objc_error.swift +++ b/test/SILGen/objc_error.swift @@ -8,10 +8,10 @@ import Foundation -// CHECK-LABEL: sil hidden [ossa] @$s10objc_error20NSErrorError_erasureys0D0_pSo0C0CF : $@convention(thin) (@guaranteed NSError) -> @owned Error { +// CHECK-LABEL: sil hidden [ossa] @$s10objc_error20NSErrorError_erasureys0D0_pSo0C0CF : $@convention(thin) (@guaranteed NSError) -> @owned any Error { // CHECK: bb0([[ERROR:%.*]] : @guaranteed $NSError): // CHECK: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] -// CHECK: [[ERROR_TYPE:%.*]] = init_existential_ref [[ERROR_COPY]] : $NSError : $NSError, $Error +// CHECK: [[ERROR_TYPE:%.*]] = init_existential_ref [[ERROR_COPY]] : $NSError : $NSError, $any Error // CHECK-NOT: destroy_value [[ERROR]] // CHECK: return [[ERROR_TYPE]] // CHECK: } // end sil function '$s10objc_error20NSErrorError_erasureys0D0_pSo0C0CF' @@ -19,11 +19,11 @@ func NSErrorError_erasure(_ x: NSError) -> Error { return x } -// CHECK-LABEL: sil hidden [ossa] @$s10objc_error30NSErrorError_archetype_erasureys0D0_pxSo0C0CRbzlF : $@convention(thin) (@guaranteed T) -> @owned Error { +// CHECK-LABEL: sil hidden [ossa] @$s10objc_error30NSErrorError_archetype_erasureys0D0_pxSo0C0CRbzlF : $@convention(thin) (@guaranteed T) -> @owned any Error { // CHECK: bb0([[ERROR:%.*]] : @guaranteed $T): // CHECK: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] // CHECK: [[T0:%.*]] = upcast [[ERROR_COPY]] : $T to $NSError -// CHECK: [[ERROR_TYPE:%.*]] = init_existential_ref [[T0]] : $NSError : $NSError, $Error +// CHECK: [[ERROR_TYPE:%.*]] = init_existential_ref [[T0]] : $NSError : $NSError, $any Error // CHECK-NOT: destroy_value [[ERROR]] // CHECK: return [[ERROR_TYPE]] // CHECK: } // end sil function '$s10objc_error30NSErrorError_archetype_erasureys0D0_pxSo0C0CRbzlF' @@ -64,7 +64,7 @@ func test_cast_to_nserror() { // CHECK: unconditional_checked_cast_addr AnyObject in {{%.*}} : $*AnyObject to NSError in {{%.*}} : $*NSError let nsForcedCast = (e as AnyObject) as! NSError - // CHECK: checked_cast_addr_br {{.*}} Error in {{%.*}} : $*Error to NSError in {{%.*}} : $*NSError, bb1, bb2 + // CHECK: checked_cast_addr_br {{.*}} Error in {{%.*}} : $*any Error to NSError in {{%.*}} : $*NSError, bb1, bb2 do { throw e } catch _ as NSError { @@ -91,14 +91,14 @@ func testAcceptError(error: Error) { // CHECK-LABEL: sil hidden [ossa] @$s10objc_error16testProduceError{{[_0-9a-zA-Z]*}}F func testProduceError() -> Error { // CHECK: function_ref @produceError : $@convention(c) () -> @autoreleased NSError - // CHECK: init_existential_ref {{.*}} : $NSError : $NSError, $Error + // CHECK: init_existential_ref {{.*}} : $NSError : $NSError, $any Error return produceError() } // CHECK-LABEL: sil hidden [ossa] @$s10objc_error24testProduceOptionalError{{[_0-9a-zA-Z]*}}F func testProduceOptionalError() -> Error? { // CHECK: function_ref @produceOptionalError - // CHECK: init_existential_ref {{.*}} : $NSError : $NSError, $Error + // CHECK: init_existential_ref {{.*}} : $NSError : $NSError, $any Error return produceOptionalError(); } @@ -108,7 +108,7 @@ class MyNSError : NSError { } } -// CHECK-LABEL: sil hidden [ossa] @$s10objc_error14eraseMyNSError{{[_0-9a-zA-Z]*}}F : $@convention(thin) () -> @owned Error { +// CHECK-LABEL: sil hidden [ossa] @$s10objc_error14eraseMyNSError{{[_0-9a-zA-Z]*}}F : $@convention(thin) () -> @owned any Error { // CHECK: bb0: // CHECK: [[NSERROR_SUBCLASS:%.*]] = apply {{.*}}({{.*}}) : $@convention(method) (@thick MyNSError.Type) -> @owned MyNSError // CHECK: [[UPCAST:%.*]] = upcast [[NSERROR_SUBCLASS]] : $MyNSError to $NSError @@ -152,19 +152,19 @@ extension Error { // CHECK: [[SUCCESS]]([[EMBEDDED_RESULT:%.*]] : @owned $AnyObject): // CHECK: [[EMBEDDED_NSERROR:%[0-9]+]] = unchecked_ref_cast [[EMBEDDED_RESULT]] : $AnyObject to $NSError - // CHECK: [[ERROR:%[0-9]+]] = init_existential_ref [[EMBEDDED_NSERROR]] : $NSError : $NSError, $Error + // CHECK: [[ERROR:%[0-9]+]] = init_existential_ref [[EMBEDDED_NSERROR]] : $NSError : $NSError, $any Error // CHECK: destroy_addr [[COPY]] : $*Self - // CHECK: br [[CONTINUATION:bb[0-9]+]]([[ERROR]] : $Error) + // CHECK: br [[CONTINUATION:bb[0-9]+]]([[ERROR]] : $any Error) // CHECK: [[FAILURE]]: - // CHECK: [[ERROR_BOX:%[0-9]+]] = alloc_existential_box $Error, $Self - // CHECK: [[ERROR_PROJECTED:%[0-9]+]] = project_existential_box $Self in [[ERROR_BOX]] : $Error + // CHECK: [[ERROR_BOX:%[0-9]+]] = alloc_existential_box $any Error, $Self + // CHECK: [[ERROR_PROJECTED:%[0-9]+]] = project_existential_box $Self in [[ERROR_BOX]] : $any Error // CHECK: store [[ERROR_BOX]] to [init] [[ERROR_BUF:%.*]] : // CHECK: copy_addr [take] [[COPY]] to [initialization] [[ERROR_PROJECTED]] : $*Self // CHECK: [[ERROR_BOX2:%.*]] = load [take] [[ERROR_BUF]] - // CHECK: br [[CONTINUATION]]([[ERROR_BOX2]] : $Error) + // CHECK: br [[CONTINUATION]]([[ERROR_BOX2]] : $any Error) - // CHECK: [[CONTINUATION]]([[ERROR_ARG:%[0-9]+]] : @owned $Error): + // CHECK: [[CONTINUATION]]([[ERROR_ARG:%[0-9]+]] : @owned $any Error): return self as NSError } } diff --git a/test/SILGen/objc_factory_init.swift b/test/SILGen/objc_factory_init.swift index 99d8c3d57424a..2344e845629bd 100644 --- a/test/SILGen/objc_factory_init.swift +++ b/test/SILGen/objc_factory_init.swift @@ -68,11 +68,11 @@ extension Hive { // CHECK: return [[HIVE_COPY]] // CHECK: bb2: // CHECK: [[OPTIONAL_NSERROR:%.*]] = load [take] [[FOREIGN_ERROR_STACK]] : $*Optional - // CHECK: [[CONVERT_NSERROR_TO_ERROR_FUNC:%.*]] = function_ref @$s10Foundation22_convertNSErrorToErrorys0E0_pSo0C0CSgF : $@convention(thin) (@guaranteed Optional) -> @owned Error - // CHECK: [[ERROR:%.*]] = apply [[CONVERT_NSERROR_TO_ERROR_FUNC]]([[OPTIONAL_NSERROR]]) : $@convention(thin) (@guaranteed Optional) -> @owned Error - // CHECK: "willThrow"([[ERROR]] : $Error) + // CHECK: [[CONVERT_NSERROR_TO_ERROR_FUNC:%.*]] = function_ref @$s10Foundation22_convertNSErrorToErrorys0E0_pSo0C0CSgF : $@convention(thin) (@guaranteed Optional) -> @owned any Error + // CHECK: [[ERROR:%.*]] = apply [[CONVERT_NSERROR_TO_ERROR_FUNC]]([[OPTIONAL_NSERROR]]) : $@convention(thin) (@guaranteed Optional) -> @owned any Error + // CHECK: "willThrow"([[ERROR]] : $any Error) // CHECK: dealloc_stack [[FOREIGN_ERROR_STACK]] - // CHECK: throw [[ERROR]] : $Error + // CHECK: throw [[ERROR]] : $any Error // CHECK: } // end sil function '$sSo4HiveC17objc_factory_initE15otherFlakyQueenABSo3BeeC_tKcfC' convenience init(otherFlakyQueen other: Bee) throws { try self.init(flakyQueen: other) diff --git a/test/SILGen/objc_ownership_conventions.swift b/test/SILGen/objc_ownership_conventions.swift index b5db92ec1cb04..fe7195dd148d9 100644 --- a/test/SILGen/objc_ownership_conventions.swift +++ b/test/SILGen/objc_ownership_conventions.swift @@ -134,18 +134,18 @@ func test10(_ g: Gizmo) -> AnyClass { // CHECK: [[G_COPY:%.*]] = copy_value [[G]] // CHECK-NEXT: [[NS_G_COPY:%[0-9]+]] = upcast [[G_COPY]] : $Gizmo to $NSObject // CHECK-NEXT: [[NS_G_BORROW:%.*]] = begin_borrow [[NS_G_COPY]] - // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[NS_G_BORROW]] : $NSObject, #NSObject.classProp!getter.foreign : (NSObject) -> () -> AnyObject.Type?, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype AnyObject.Type> - // CHECK-NEXT: [[OPT_OBJC:%.*]] = apply [[GETTER]]([[NS_G_BORROW]]) : $@convention(objc_method) (NSObject) -> Optional<@objc_metatype AnyObject.Type> + // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[NS_G_BORROW]] : $NSObject, #NSObject.classProp!getter.foreign : (NSObject) -> () -> (any AnyObject.Type)?, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype any AnyObject.Type> + // CHECK-NEXT: [[OPT_OBJC:%.*]] = apply [[GETTER]]([[NS_G_BORROW]]) : $@convention(objc_method) (NSObject) -> Optional<@objc_metatype any AnyObject.Type> // CHECK-NEXT: switch_enum [[OPT_OBJC]] : $Optional<{{.*}}>, case #Optional.some!enumelt: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]] // - // CHECK: [[SOME_BB]]([[OBJC:%.*]] : $@objc_metatype AnyObject.Type): + // CHECK: [[SOME_BB]]([[OBJC:%.*]] : $@objc_metatype any AnyObject.Type): // CHECK-NEXT: [[THICK:%.*]] = objc_to_thick_metatype [[OBJC]] - // CHECK: [[T0:%.*]] = enum $Optional<@thick AnyObject.Type>, #Optional.some!enumelt, [[THICK]] - // CHECK: bb{{.*}}(%{{.*}} : $Optional<@thick AnyObject.Type>): + // CHECK: [[T0:%.*]] = enum $Optional<@thick any AnyObject.Type>, #Optional.some!enumelt, [[THICK]] + // CHECK: bb{{.*}}(%{{.*}} : $Optional<@thick any AnyObject.Type>): // CHECK: destroy_value [[NS_G_COPY]] : $NSObject - // CHECK: bb{{.*}}([[RES:%.*]] : $@thick AnyObject.Type): + // CHECK: bb{{.*}}([[RES:%.*]] : $@thick any AnyObject.Type): // CHECK-NOT: destroy_value [[G]] : $Gizmo - // CHECK-NEXT: return [[RES]] : $@thick AnyObject.Type + // CHECK-NEXT: return [[RES]] : $@thick any AnyObject.Type return g.classProp } @@ -155,20 +155,20 @@ func test11(_ g: Gizmo) -> AnyClass { // CHECK: [[G_COPY:%.*]] = copy_value [[G]] // CHECK: [[NS_G_COPY:%[0-9]+]] = upcast [[G_COPY:%[0-9]+]] : $Gizmo to $NSObject // CHECK-NEXT: [[NS_G_BORROW:%.*]] = begin_borrow [[NS_G_COPY]] - // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[NS_G_BORROW]] : $NSObject, #NSObject.qualifiedClassProp!getter.foreign : (NSObject) -> () -> NSAnsing.Type?, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype NSAnsing.Type> - // CHECK-NEXT: [[OPT_OBJC:%.*]] = apply [[GETTER]]([[NS_G_BORROW]]) : $@convention(objc_method) (NSObject) -> Optional<@objc_metatype NSAnsing.Type> + // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[NS_G_BORROW]] : $NSObject, #NSObject.qualifiedClassProp!getter.foreign : (NSObject) -> () -> (any NSAnsing.Type)?, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype any NSAnsing.Type> + // CHECK-NEXT: [[OPT_OBJC:%.*]] = apply [[GETTER]]([[NS_G_BORROW]]) : $@convention(objc_method) (NSObject) -> Optional<@objc_metatype any NSAnsing.Type> // CHECK-NEXT: switch_enum [[OPT_OBJC]] : $Optional<{{.*}}>, case #Optional.some!enumelt: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]] // - // CHECK: [[SOME_BB]]([[OBJC:%.*]] : $@objc_metatype NSAnsing.Type): + // CHECK: [[SOME_BB]]([[OBJC:%.*]] : $@objc_metatype any NSAnsing.Type): // CHECK-NEXT: [[THICK:%.*]] = objc_to_thick_metatype [[OBJC]] - // CHECK: [[T0:%.*]] = enum $Optional<@thick NSAnsing.Type>, #Optional.some!enumelt, [[THICK]] - // CHECK: bb{{.*}}(%{{.*}} : $Optional<@thick NSAnsing.Type>): + // CHECK: [[T0:%.*]] = enum $Optional<@thick any NSAnsing.Type>, #Optional.some!enumelt, [[THICK]] + // CHECK: bb{{.*}}(%{{.*}} : $Optional<@thick any NSAnsing.Type>): // CHECK: destroy_value [[NS_G_COPY]] : $NSObject - // CHECK: bb{{.*}}([[RES:%.*]] : $@thick NSAnsing.Type): + // CHECK: bb{{.*}}([[RES:%.*]] : $@thick any NSAnsing.Type): // CHECK: [[OPENED:%.*]] = open_existential_metatype [[RES]] // CHECK: [[RES_ANY:%.*]] = init_existential_metatype [[OPENED]] // CHECK-NOT: destroy_value [[G]] : $Gizmo - // CHECK-NEXT: return [[RES_ANY]] : $@thick AnyObject.Type + // CHECK-NEXT: return [[RES_ANY]] : $@thick any AnyObject.Type return g.qualifiedClassProp } diff --git a/test/SILGen/objc_protocols.swift b/test/SILGen/objc_protocols.swift index eea020c8a8562..e8797686fd3cd 100644 --- a/test/SILGen/objc_protocols.swift +++ b/test/SILGen/objc_protocols.swift @@ -85,14 +85,14 @@ func objc_generic_partial_apply(_ x: T) { // CHECK-LABEL: sil hidden [ossa] @$s14objc_protocols0A9_protocol{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[THIS:%.*]] : @guaranteed $NSRuncing): +// CHECK: bb0([[THIS:%.*]] : @guaranteed $any NSRuncing): // -- Result of runce is autoreleased according to default objc conv -// CHECK: [[THIS1:%.*]] = open_existential_ref [[THIS]] : $NSRuncing to $[[OPENED:@opened\(.*, NSRuncing\) Self]] +// CHECK: [[THIS1:%.*]] = open_existential_ref [[THIS]] : $any NSRuncing to $[[OPENED:@opened\(.*, any NSRuncing\) Self]] // CHECK: [[METHOD:%.*]] = objc_method [[THIS1]] : $[[OPENED]], #NSRuncing.runce!foreign // CHECK: [[RESULT1:%.*]] = apply [[METHOD]]<[[OPENED]]>([[THIS1]]) // -- Result of copyRuncing is received copy_valued according to -copy family -// CHECK: [[THIS2:%.*]] = open_existential_ref [[THIS]] : $NSRuncing to $[[OPENED2:@opened\(.*, NSRuncing\) Self]] +// CHECK: [[THIS2:%.*]] = open_existential_ref [[THIS]] : $any NSRuncing to $[[OPENED2:@opened\(.*, any NSRuncing\) Self]] // CHECK: [[METHOD:%.*]] = objc_method [[THIS2]] : $[[OPENED2]], #NSRuncing.copyRuncing!foreign // CHECK: [[RESULT2:%.*]] = apply [[METHOD]]<[[OPENED2]]>([[THIS2:%.*]]) @@ -102,9 +102,9 @@ func objc_protocol(_ x: NSRuncing) -> (NSObject, NSObject) { return (x.runce(), x.copyRuncing()) } -// CHECK-LABEL: sil hidden [ossa] @$s14objc_protocols0A23_protocol_partial_applyyyAA9NSRuncing_pF : $@convention(thin) (@guaranteed NSRuncing) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s14objc_protocols0A23_protocol_partial_applyyyAA9NSRuncing_pF : $@convention(thin) (@guaranteed any NSRuncing) -> () { func objc_protocol_partial_apply(_ x: NSRuncing) { - // CHECK: bb0([[ARG:%.*]] : @guaranteed $NSRuncing): + // CHECK: bb0([[ARG:%.*]] : @guaranteed $any NSRuncing): // CHECK: [[FN:%.*]] = function_ref @$s14objc_protocols0A23_protocol_partial_applyyyAA9NSRuncing_pFSo8NSObjectCycAaC_pcfu_ // CHECK: [[RESULT:%.*]] = apply [[FN]]([[ARG]]) _ = x.runce @@ -116,12 +116,12 @@ func objc_protocol_partial_apply(_ x: NSRuncing) { // CHECK-LABEL: sil hidden [ossa] @$s14objc_protocols0A21_protocol_composition{{[_0-9a-zA-Z]*}}F func objc_protocol_composition(_ x: NSRuncing & NSFunging) { - // CHECK: [[THIS:%.*]] = open_existential_ref [[THIS_ORIG:%.*]] : $NSFunging & NSRuncing to $[[OPENED:@opened\(.*, NSFunging & NSRuncing\) Self]] + // CHECK: [[THIS:%.*]] = open_existential_ref [[THIS_ORIG:%.*]] : $any NSFunging & NSRuncing to $[[OPENED:@opened\(.*, any NSFunging & NSRuncing\) Self]] // CHECK: [[METHOD:%.*]] = objc_method [[THIS]] : $[[OPENED]], #NSRuncing.runce!foreign // CHECK: apply [[METHOD]]<[[OPENED]]>([[THIS]]) x.runce() - // CHECK: [[THIS:%.*]] = open_existential_ref [[THIS_ORIG:%.*]] : $NSFunging & NSRuncing to $[[OPENED:@opened\(.*, NSFunging & NSRuncing\) Self]] + // CHECK: [[THIS:%.*]] = open_existential_ref [[THIS_ORIG:%.*]] : $any NSFunging & NSRuncing to $[[OPENED:@opened\(.*, any NSFunging & NSRuncing\) Self]] // CHECK: [[METHOD:%.*]] = objc_method [[THIS]] : $[[OPENED]], #NSFunging.funge!foreign // CHECK: apply [[METHOD]]<[[OPENED]]>([[THIS]]) x.funge() @@ -235,24 +235,24 @@ extension InformallyFunging: NSFunging { } init(int: Int) } -// CHECK-LABEL: sil hidden [ossa] @$s14objc_protocols28testInitializableExistential_1iAA0D0_pAaD_pXp_SitF : $@convention(thin) (@thick Initializable.Type, Int) -> @owned Initializable { +// CHECK-LABEL: sil hidden [ossa] @$s14objc_protocols28testInitializableExistential_1iAA0D0_pAaD_pXp_SitF : $@convention(thin) (@thick any Initializable.Type, Int) -> @owned any Initializable { func testInitializableExistential(_ im: Initializable.Type, i: Int) -> Initializable { - // CHECK: bb0([[META:%[0-9]+]] : $@thick Initializable.Type, [[I:%[0-9]+]] : $Int): - // CHECK: [[I2_BOX:%[0-9]+]] = alloc_box ${ var Initializable } + // CHECK: bb0([[META:%[0-9]+]] : $@thick any Initializable.Type, [[I:%[0-9]+]] : $Int): + // CHECK: [[I2_BOX:%[0-9]+]] = alloc_box ${ var any Initializable } // CHECK: [[I2_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[I2_BOX]] // CHECK: [[PB:%.*]] = project_box [[I2_LIFETIME]] - // CHECK: [[ARCHETYPE_META:%[0-9]+]] = open_existential_metatype [[META]] : $@thick Initializable.Type to $@thick (@opened([[N:".*"]], Initializable) Self).Type - // CHECK: [[ARCHETYPE_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[ARCHETYPE_META]] : $@thick (@opened([[N]], Initializable) Self).Type to $@objc_metatype (@opened([[N]], Initializable) Self).Type - // CHECK: [[I2_ALLOC:%[0-9]+]] = alloc_ref_dynamic [objc] [[ARCHETYPE_META_OBJC]] : $@objc_metatype (@opened([[N]], Initializable) Self).Type, $@opened([[N]], Initializable) Self - // CHECK: [[INIT_WITNESS:%[0-9]+]] = objc_method [[I2_ALLOC]] : $@opened([[N]], Initializable) Self, #Initializable.init!initializer.foreign : {{.*}} - // CHECK: [[I2:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]], Initializable) Self>([[I]], [[I2_ALLOC]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Initializable> (Int, @owned τ_0_0) -> @owned τ_0_0 - // CHECK: [[I2_EXIST_CONTAINER:%[0-9]+]] = init_existential_ref [[I2]] : $@opened([[N]], Initializable) Self : $@opened([[N]], Initializable) Self, $Initializable - // CHECK: store [[I2_EXIST_CONTAINER]] to [init] [[PB]] : $*Initializable - // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*Initializable - // CHECK: [[I2:%[0-9]+]] = load [copy] [[READ]] : $*Initializable + // CHECK: [[ARCHETYPE_META:%[0-9]+]] = open_existential_metatype [[META]] : $@thick any Initializable.Type to $@thick (@opened([[N:".*"]], any Initializable) Self).Type + // CHECK: [[ARCHETYPE_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[ARCHETYPE_META]] : $@thick (@opened([[N]], any Initializable) Self).Type to $@objc_metatype (@opened([[N]], any Initializable) Self).Type + // CHECK: [[I2_ALLOC:%[0-9]+]] = alloc_ref_dynamic [objc] [[ARCHETYPE_META_OBJC]] : $@objc_metatype (@opened([[N]], any Initializable) Self).Type, $@opened([[N]], any Initializable) Self + // CHECK: [[INIT_WITNESS:%[0-9]+]] = objc_method [[I2_ALLOC]] : $@opened([[N]], any Initializable) Self, #Initializable.init!initializer.foreign : {{.*}} + // CHECK: [[I2:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]], any Initializable) Self>([[I]], [[I2_ALLOC]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Initializable> (Int, @owned τ_0_0) -> @owned τ_0_0 + // CHECK: [[I2_EXIST_CONTAINER:%[0-9]+]] = init_existential_ref [[I2]] : $@opened([[N]], any Initializable) Self : $@opened([[N]], any Initializable) Self, $any Initializable + // CHECK: store [[I2_EXIST_CONTAINER]] to [init] [[PB]] : $*any Initializable + // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*any Initializable + // CHECK: [[I2:%[0-9]+]] = load [copy] [[READ]] : $*any Initializable // CHECK: end_borrow [[I2_LIFETIME]] - // CHECK: destroy_value [[I2_BOX]] : ${ var Initializable } - // CHECK: return [[I2]] : $Initializable + // CHECK: destroy_value [[I2_BOX]] : ${ var any Initializable } + // CHECK: return [[I2]] : $any Initializable var i2 = im.init(int: i) return i2 } @@ -291,8 +291,8 @@ public protocol DangerousEscaper { // Make sure we emit an withoutActuallyEscaping sentinel. -// CHECK-LABEL: sil [ossa] @$s14objc_protocols19couldActuallyEscapeyyyyc_AA16DangerousEscaper_ptF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (), @guaranteed DangerousEscaper) -> () { -// CHECK: bb0([[CLOSURE_ARG:%.*]] : @guaranteed $@callee_guaranteed () -> (), [[SELF:%.*]] : @guaranteed $DangerousEscaper): +// CHECK-LABEL: sil [ossa] @$s14objc_protocols19couldActuallyEscapeyyyyc_AA16DangerousEscaper_ptF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (), @guaranteed any DangerousEscaper) -> () { +// CHECK: bb0([[CLOSURE_ARG:%.*]] : @guaranteed $@callee_guaranteed () -> (), [[SELF:%.*]] : @guaranteed $any DangerousEscaper): // CHECK: [[OE:%.*]] = open_existential_ref [[SELF]] // CHECK: [[CLOSURE_COPY1:%.*]] = copy_value [[CLOSURE_ARG]] // CHECK: [[NOESCAPE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_COPY1]] @@ -309,8 +309,8 @@ public protocol DangerousEscaper { // CHECK: destroy_addr [[BLOCK_ADDR]] : $*@callee_guaranteed () -> () // CHECK: dealloc_stack [[BLOCK]] : $*@block_storage @callee_guaranteed () -> () // CHECK: destroy_value [[CLOSURE_COPY1]] : $@callee_guaranteed () -> () -// CHECK: [[METH:%.*]] = objc_method [[OE]] : $@opened("{{.*}}", DangerousEscaper) Self, #DangerousEscaper.malicious!foreign -// CHECK: apply [[METH]]<@opened("{{.*}}", DangerousEscaper) Self>([[BLOCK_CLOSURE_COPY]], [[OE]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : DangerousEscaper> (@convention(block) @noescape () -> (), τ_0_0) -> () +// CHECK: [[METH:%.*]] = objc_method [[OE]] : $@opened("{{.*}}", any DangerousEscaper) Self, #DangerousEscaper.malicious!foreign +// CHECK: apply [[METH]]<@opened("{{.*}}", any DangerousEscaper) Self>([[BLOCK_CLOSURE_COPY]], [[OE]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : DangerousEscaper> (@convention(block) @noescape () -> (), τ_0_0) -> () // CHECK: destroy_value [[BLOCK_CLOSURE_COPY]] : $@convention(block) @noescape () -> () // CHECK: return {{.*}} : $() diff --git a/test/SILGen/opaque_values_silgen.swift b/test/SILGen/opaque_values_silgen.swift index 3a119df748b42..39e686e068c5e 100644 --- a/test/SILGen/opaque_values_silgen.swift +++ b/test/SILGen/opaque_values_silgen.swift @@ -60,15 +60,15 @@ func forEachStmt() { // Tests that existential boxes can contain opaque types // --- -// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen12openExistBoxySSs5Error_pF : $@convention(thin) (@guaranteed Error) -> @owned String { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error): -// CHECK: [[OPAQUE_ARG:%.*]] = open_existential_box_value [[ARG]] : $Error to $@opened({{.*}}, Error) Self -// CHECK: [[ALLOC_OPEN:%.*]] = alloc_stack $@opened({{.*}}, Error) Self +// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen12openExistBoxySSs5Error_pF : $@convention(thin) (@guaranteed any Error) -> @owned String { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Error): +// CHECK: [[OPAQUE_ARG:%.*]] = open_existential_box_value [[ARG]] : $any Error to $@opened({{.*}}, any Error) Self +// CHECK: [[ALLOC_OPEN:%.*]] = alloc_stack $@opened({{.*}}, any Error) Self // CHECK: [[COPY:%.*]] = copy_value [[OPAQUE_ARG]] // CHECK: store [[COPY]] to [init] [[ALLOC_OPEN]] // CHECK: destroy_addr [[ALLOC_OPEN]] // CHECK: dealloc_stack [[ALLOC_OPEN]] -// CHECK-NOT: destroy_value [[ARG]] : $Error +// CHECK-NOT: destroy_value [[ARG]] : $any Error // CHECK: return {{.*}} : $String // CHECK-LABEL: } // end sil function '$s20opaque_values_silgen12openExistBoxySSs5Error_pF' func openExistBox(_ x: Error) -> String { @@ -99,13 +99,13 @@ protocol EmptyP {} struct AddressOnlyStruct : EmptyP {} -// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen10addrOnlyIf1xAA6EmptyP_pSb_tF : $@convention(thin) (Bool) -> @out EmptyP { +// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen10addrOnlyIf1xAA6EmptyP_pSb_tF : $@convention(thin) (Bool) -> @out any EmptyP { // HECK: bb0([[ARG:%.*]] : $Bool): -// HECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var EmptyP }, var +// HECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var any EmptyP }, var // HECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]] // HECK: [[APPLY_FOR_BOX:%.*]] = apply %{{.*}}(%{{.*}}) : $@convention(method) (@thin AddressOnlyStruct.Type) -> AddressOnlyStruct -// HECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[APPLY_FOR_BOX]] : $AddressOnlyStruct, $AddressOnlyStruct, $EmptyP -// HECK: store [[INIT_OPAQUE]] to [init] [[PROJ_BOX]] : $*EmptyP +// HECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[APPLY_FOR_BOX]] : $AddressOnlyStruct, $AddressOnlyStruct, $any EmptyP +// HECK: store [[INIT_OPAQUE]] to [init] [[PROJ_BOX]] : $*any EmptyP // HECK: [[APPLY_FOR_BRANCH:%.*]] = apply %{{.*}}([[ARG]]) : $@convention(method) (Bool) -> Builtin.Int1 // HECK: cond_br [[APPLY_FOR_BRANCH]], bb2, bb1 // HECK: bb1: @@ -128,19 +128,19 @@ func addrOnlyIf(x: Bool) -> EmptyP { // Tests LValue of error types / existential boxes // --- -// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen12propOfLValueySSs5Error_pF : $@convention(thin) (@guaranteed Error) -> @owned String { -// HECK: bb0([[ARG:%.*]] : $Error): -// HECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var Error } +// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen12propOfLValueySSs5Error_pF : $@convention(thin) (@guaranteed any Error) -> @owned String { +// HECK: bb0([[ARG:%.*]] : $any Error): +// HECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var any Error } // HECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]] // HECK: [[COPY_ARG:%.*]] = copy_value [[ARG]] // HECK: store [[COPY_ARG]] to [init] [[PROJ_BOX]] -// HECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJ_BOX]] : $*Error +// HECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJ_BOX]] : $*any Error // HECK: [[LOAD_BOX:%.*]] = load [copy] [[READ]] -// HECK: [[OPAQUE_ARG:%.*]] = open_existential_box [[LOAD_BOX]] : $Error to $*@opened({{.*}}, Error) Self +// HECK: [[OPAQUE_ARG:%.*]] = open_existential_box [[LOAD_BOX]] : $any Error to $*@opened({{.*}}, any Error) Self // HECK: [[LOAD_OPAQUE:%.*]] = load [copy] [[OPAQUE_ARG]] -// HECK: [[ALLOC_OPEN:%.*]] = alloc_stack $@opened({{.*}}, Error) Self +// HECK: [[ALLOC_OPEN:%.*]] = alloc_stack $@opened({{.*}}, any Error) Self // HECK: store [[LOAD_OPAQUE]] to [init] [[ALLOC_OPEN]] -// HECK: [[RET_VAL:%.*]] = apply {{.*}}<@opened({{.*}}, Error) Self>([[ALLOC_OPEN]]) +// HECK: [[RET_VAL:%.*]] = apply {{.*}}<@opened({{.*}}, any Error) Self>([[ALLOC_OPEN]]) // HECK: return [[RET_VAL]] : $String // CHECK-LABEL: } // end sil function '$s20opaque_values_silgen12propOfLValueySSs5Error_pF' func propOfLValue(_ x: Error) -> String { @@ -297,11 +297,11 @@ public func unsafeDowncastToAnyObject(fromAny any: Any) -> AnyObject { // Test open_existential_box_value in a conversion context. // --- // CHECK-OSX-LABEL: sil [ossa] @$s20opaque_values_silgen22testOpenExistentialBox1eys5Error_pSg_tF : $@convention(thin) (@guaranteed Optional) -> () { -// CHECK-OSX: [[BORROW:%.*]] = begin_borrow [lexical] %{{.*}} : $Error -// CHECK-OSX: [[VAL:%.*]] = open_existential_box_value [[BORROW]] : $Error to $@opened +// CHECK-OSX: [[BORROW:%.*]] = begin_borrow [lexical] %{{.*}} : $any Error +// CHECK-OSX: [[VAL:%.*]] = open_existential_box_value [[BORROW]] : $any Error to $@opened // CHECK-OSX: [[COPY:%.*]] = copy_value [[VAL]] : $@opened // CHECK-OSX: [[ANY:%.*]] = init_existential_value [[COPY]] : $@opened -// CHECK-OSX: end_borrow [[BORROW]] : $Error +// CHECK-OSX: end_borrow [[BORROW]] : $any Error // CHECK-OSX-LABEL: } // end sil function '$s20opaque_values_silgen22testOpenExistentialBox1eys5Error_pSg_tF' public func testOpenExistentialBox(e: Error?) { if let u = e { diff --git a/test/SILGen/opaque_values_silgen_lib.swift b/test/SILGen/opaque_values_silgen_lib.swift index 64a17c1c41414..c3be2e15e2aa4 100644 --- a/test/SILGen/opaque_values_silgen_lib.swift +++ b/test/SILGen/opaque_values_silgen_lib.swift @@ -157,12 +157,12 @@ func f010_PAndS_cases() { // Init of Empty protocol + Builtin.NativeObject enum (including opaque tuples as a return value) // --- // implicit closure #2 (Swift.EmptyP, Swift.String) -> Swift.PAndSEnum in implicit closure #1 (Swift.PAndSEnum.Type) -> (Swift.EmptyP, Swift.String) -> Swift.PAndSEnum in Swift.f010_PAndS_cases() -> () -// CHECK-LABEL: sil private [ossa] @$ss16f010_PAndS_casesyyFs0B5SEnumOs6EmptyP_p_SStcACmcfu_ACsAD_p_SStcfu0_ : $@convention(thin) (@in_guaranteed EmptyP, @guaranteed String, @thin PAndSEnum.Type) -> @out PAndSEnum { -// HECK: bb0([[ARG0:%.*]] : @guaranteed $EmptyP, [[ARG1:%.*]] : @guaranteed $String, [[ARG2:%.*]] : $@thin PAndSEnum.Type): +// CHECK-LABEL: sil private [ossa] @$ss16f010_PAndS_casesyyFs0B5SEnumOs6EmptyP_p_SStcACmcfu_ACsAD_p_SStcfu0_ : $@convention(thin) (@in_guaranteed any EmptyP, @guaranteed String, @thin PAndSEnum.Type) -> @out PAndSEnum { +// HECK: bb0([[ARG0:%.*]] : @guaranteed $any EmptyP, [[ARG1:%.*]] : @guaranteed $String, [[ARG2:%.*]] : $@thin PAndSEnum.Type): // HECK: [[COPY0:%.*]] = copy_value [[ARG0]] // HECK: [[COPY1:%.*]] = copy_value [[ARG1]] -// HECK: [[RTUPLE:%.*]] = tuple ([[COPY0]] : $EmptyP, [[COPY1]] : $String) -// HECK: [[RETVAL:%.*]] = enum $PAndSEnum, #PAndSEnum.A!enumelt, [[RTUPLE]] : $(EmptyP, String) +// HECK: [[RTUPLE:%.*]] = tuple ([[COPY0]] : $any EmptyP, [[COPY1]] : $String) +// HECK: [[RETVAL:%.*]] = enum $PAndSEnum, #PAndSEnum.A!enumelt, [[RTUPLE]] : $(any EmptyP, String) // HECK: return [[RETVAL]] : $PAndSEnum // CHECK-LABEL: } // end sil function '$ss16f010_PAndS_casesyyFs0B5SEnumOs6EmptyP_p_SStcACmcfu_ACsAD_p_SStcfu0_' @@ -299,12 +299,12 @@ func f070_materializeSelf(t: T) where T: AnyObject { // Test open existential with opaque values // --- -// CHECK-LABEL: sil hidden [ossa] @$ss8f080_bar1pBi64_s1P_p_tF : $@convention(thin) (@in_guaranteed P) -> Builtin.Int64 { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $P): -// HECK: [[OPENED_ARG:%.*]] = open_existential_value [[ARG]] : $P to $@opened +// CHECK-LABEL: sil hidden [ossa] @$ss8f080_bar1pBi64_s1P_p_tF : $@convention(thin) (@in_guaranteed any P) -> Builtin.Int64 { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any P): +// HECK: [[OPENED_ARG:%.*]] = open_existential_value [[ARG]] : $any P to $@opened // HECK: [[WITNESS_FUNC:%.*]] = witness_method $@opened // HECK: [[RESULT:%.*]] = apply [[WITNESS_FUNC]]<{{.*}}>([[OPENED_ARG]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Builtin.Int64 -// CHECK-NOT: destroy_value [[ARG]] : $P +// CHECK-NOT: destroy_value [[ARG]] : $any P // HECK: return [[RESULT]] : $Builtin.Int64 // CHECK-LABEL: } // end sil function '$ss8f080_bar1pBi64_s1P_p_tF' func f080_bar(p: P) -> Builtin.Int64 { @@ -415,12 +415,12 @@ func f170_force_convert() -> T { // Tests supporting function for f190_return_foo_var - cast and return of protocol // --- -// CHECK-LABEL: sil hidden [ossa] @$ss15f180_return_foos4FooP_pyF : $@convention(thin) () -> @out FooP { +// CHECK-LABEL: sil hidden [ossa] @$ss15f180_return_foos4FooP_pyF : $@convention(thin) () -> @out any FooP { // CHECK: bb0: // HECK: [[INT_LIT:%.*]] = integer_literal $Builtin.Builtin.Int64Literal, 42 // HECK: [[INT_ARG:%.*]] = apply %{{.*}}([[INT_LIT]], [[INT_TYPE]]) : $@convention(method) (Builtin.Builtin.Int64Literal, @thin Builtin.Int64.Type) -> Builtin.Int64 -// HECK: [[INT_CAST:%.*]] = unconditional_checked_cast_value [[INT_ARG]] : $Builtin.Int64 to $FooP -// HECK: return [[INT_CAST]] : $FooP +// HECK: [[INT_CAST:%.*]] = unconditional_checked_cast_value [[INT_ARG]] : $Builtin.Int64 to $any FooP +// HECK: return [[INT_CAST]] : $any FooP // CHECK-LABEL: } // end sil function '$ss15f180_return_foos4FooP_pyF' func f180_return_foo() -> FooP { return Int64(42) as! FooP @@ -429,12 +429,12 @@ var foo_var : FooP = f180_return_foo() // Tests return of global variables by doing a load of copy // --- -// CHECK-LABEL: sil hidden [ossa] @$ss19f190_return_foo_vars4FooP_pyF : $@convention(thin) () -> @out FooP { +// CHECK-LABEL: sil hidden [ossa] @$ss19f190_return_foo_vars4FooP_pyF : $@convention(thin) () -> @out any FooP { // CHECK: bb0: -// HECK: [[GLOBAL:%.*]] = global_addr {{.*}} : $*FooP -// HECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*FooP -// HECK: [[LOAD_GLOBAL:%.*]] = load [copy] [[READ]] : $*FooP -// HECK: return [[LOAD_GLOBAL]] : $FooP +// HECK: [[GLOBAL:%.*]] = global_addr {{.*}} : $*any FooP +// HECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*any FooP +// HECK: [[LOAD_GLOBAL:%.*]] = load [copy] [[READ]] : $*any FooP +// HECK: return [[LOAD_GLOBAL]] : $any FooP // CHECK-LABEL: } // end sil function '$ss19f190_return_foo_vars4FooP_pyF' func f190_return_foo_var() -> FooP { return foo_var @@ -462,15 +462,15 @@ func f200_use_foo_var() { // Tests composition erasure of opaque existentials + copy into of opaques // --- -// CHECK-LABEL: sil hidden [ossa] @$ss16f210_compErasureys5Error_psAB_s4FooPpF : $@convention(thin) (@in_guaranteed Error & FooP) -> @owned Error { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error & FooP): -// HECK: [[OPAQUE_ARG:%.*]] = open_existential_value [[ARG]] : $Error & FooP to $@opened({{.*}}, Error) Self & FooP -// HECK: [[EXIST_BOX:%.*]] = alloc_existential_box $Error, $@opened({{.*}}, Error) Self & FooP -// HECK: [[PROJ_BOX:%.*]] = project_existential_box $@opened({{.*}}, Error) Self & FooP in [[EXIST_BOX]] -// HECK: [[COPY_OPAQUE:%.*]] = copy_value [[OPAQUE_ARG]] : $@opened({{.*}}, Error) Self & FooP -// HECK: store [[COPY_OPAQUE]] to [init] [[PROJ_BOX]] : $*@opened({{.*}}, Error) Self & FooP -// CHECK-NOT: destroy_value [[ARG]] : $Error & FooP -// HECK: return [[EXIST_BOX]] : $Error +// CHECK-LABEL: sil hidden [ossa] @$ss16f210_compErasureys5Error_psAB_s4FooPpF : $@convention(thin) (@in_guaranteed any Error & FooP) -> @owned any Error { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Error & FooP): +// HECK: [[OPAQUE_ARG:%.*]] = open_existential_value [[ARG]] : $any Error & FooP to $@opened({{.*}}, any Error) Self & FooP +// HECK: [[EXIST_BOX:%.*]] = alloc_existential_box $any Error, $@opened({{.*}}, any Error) Self & FooP +// HECK: [[PROJ_BOX:%.*]] = project_existential_box $@opened({{.*}}, any Error) Self & FooP in [[EXIST_BOX]] +// HECK: [[COPY_OPAQUE:%.*]] = copy_value [[OPAQUE_ARG]] : $@opened({{.*}}, any Error) Self & FooP +// HECK: store [[COPY_OPAQUE]] to [init] [[PROJ_BOX]] : $*@opened({{.*}}, any Error) Self & FooP +// CHECK-NOT: destroy_value [[ARG]] : $any Error & FooP +// HECK: return [[EXIST_BOX]] : $any Error // CHECK-LABEL: } // end sil function '$ss16f210_compErasureys5Error_psAB_s4FooPpF' func f210_compErasure(_ x: FooP & Error) -> Error { return x @@ -561,10 +561,10 @@ func f270_convOptAnyStruct(_ a1: @escaping (AnyStruct?) -> AnyStruct) { // Tests conversion between existential types // --- -// CHECK-LABEL: sil hidden [ossa] @$ss21f280_convExistTrivialyys0D6StructVs1P_pcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed P) -> TrivialStruct) -> () { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed P) -> TrivialStruct): +// CHECK-LABEL: sil hidden [ossa] @$ss21f280_convExistTrivialyys0D6StructVs1P_pcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed any P) -> TrivialStruct) -> () { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed any P) -> TrivialStruct): // HECK: [[COPY_ARG:%.*]] = copy_value [[ARG]] -// HECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (@in_guaranteed P2, @guaranteed @callee_guaranteed (@in_guaranteed P) -> TrivialStruct) -> @out P2 +// HECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (@in_guaranteed P2, @guaranteed @callee_guaranteed (@in_guaranteed any P) -> TrivialStruct) -> @out P2 // HECK: destroy_value [[PAPPLY]] : $@callee_guaranteed (@in_guaranteed P2) -> @out P2 // CHECK-NOT: destroy_value [[ARG]] // HECK: return %{{.*}} : $() @@ -575,26 +575,26 @@ func f280_convExistTrivial(_ s: @escaping (P) -> TrivialStruct) { // part of f280_convExistTrivial: conversion between existential types - reabstraction thunk // --- -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$ss1P_ps13TrivialStructVIegnd_s2P2_psAD_pIegnr_TR : $@convention(thin) (@in_guaranteed P2, @guaranteed @callee_guaranteed (@in_guaranteed P) -> TrivialStruct) -> @out P2 { -// CHECK: bb0([[ARG0:%.*]] : @guaranteed $P2, [[ARG1:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed P) -> TrivialStruct): -// HECK: [[OPENED_ARG:%.*]] = open_existential_value [[ARG]] : $P2 to $@opened({{.*}}, P2) Self +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$ss1P_ps13TrivialStructVIegnd_s2P2_psAD_pIegnr_TR : $@convention(thin) (@in_guaranteed any P2, @guaranteed @callee_guaranteed (@in_guaranteed any P) -> TrivialStruct) -> @out any P2 { +// CHECK: bb0([[ARG0:%.*]] : @guaranteed $any P2, [[ARG1:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed any P) -> TrivialStruct): +// HECK: [[OPENED_ARG:%.*]] = open_existential_value [[ARG]] : $any P2 to $@opened({{.*}}, any P2) Self // HECK: [[COPIED_VAL:%.*]] = copy_value [[OPENED_ARG]] -// HECK: [[INIT_P:%.*]] = init_existential_value [[COPIED_VAL]] : $@opened({{.*}}, P2) Self, $@opened({{.*}}, P2) Self, $P +// HECK: [[INIT_P:%.*]] = init_existential_value [[COPIED_VAL]] : $@opened({{.*}}, any P2) Self, $@opened({{.*}}, any P2) Self, $any P // HECK: [[BORROWED_INIT_P:%.*]] = begin_borrow [[INIT_P]] -// HECK: [[APPLY_P:%.*]] = apply [[ARG1]]([[BORROWED_INIT_P]]) : $@callee_guaranteed (@in_guaranteed P) -> TrivialStruct -// HECK: [[RETVAL:%.*]] = init_existential_value [[APPLY_P]] : $TrivialStruct, $TrivialStruct, $P2 +// HECK: [[APPLY_P:%.*]] = apply [[ARG1]]([[BORROWED_INIT_P]]) : $@callee_guaranteed (@in_guaranteed any P) -> TrivialStruct +// HECK: [[RETVAL:%.*]] = init_existential_value [[APPLY_P]] : $TrivialStruct, $TrivialStruct, $any P2 // HECK: end_borrow [[BORROWED_INIT_P]] // CHECK-NOT: destroy_value [[ARG0]] -// HECK: return [[RETVAL]] : $P2 +// HECK: return [[RETVAL]] : $any P2 // CHECK-LABEL: } // end sil function '$ss1P_ps13TrivialStructVIegnd_s2P2_psAD_pIegnr_TR' // Tests conversion between existential types - optionals case // --- -// CHECK-LABEL: sil hidden [ossa] @$ss21f290_convOptExistTrivyys13TrivialStructVs1P_pSgcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed Optional

) -> TrivialStruct) -> () { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed Optional

) -> TrivialStruct): +// CHECK-LABEL: sil hidden [ossa] @$ss21f290_convOptExistTrivyys13TrivialStructVs1P_pSgcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed Optional) -> TrivialStruct) -> () { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed Optional) -> TrivialStruct): // HECK: [[COPY_ARG:%.*]] = copy_value [[ARG]] -// HECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (Optional, @guaranteed @callee_guaranteed (@in_guaranteed Optional

) -> TrivialStruct) -> @out P2 -// HECK: destroy_value [[PAPPLY]] : $@callee_guaranteed (Optional) -> @out P2 +// HECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (Optional, @guaranteed @callee_guaranteed (@in_guaranteed Optional) -> TrivialStruct) -> @out any P2 +// HECK: destroy_value [[PAPPLY]] : $@callee_guaranteed (Optional) -> @out any P2 // CHECK-NOT: destroy_value [[ARG]] // HECK: return %{{.*}} : $() // CHECK-LABEL: } // end sil function '$ss21f290_convOptExistTrivyys13TrivialStructVs1P_pSgcF' @@ -604,21 +604,21 @@ func f290_convOptExistTriv(_ s: @escaping (P?) -> TrivialStruct) { // part of f290_convOptExistTriv: conversion between existential types - reabstraction thunk - optionals case // --- -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$ss1P_pSgs13TrivialStructVIegnd_ADSgs2P2_pIegyr_TR : $@convention(thin) (Optional, @guaranteed @callee_guaranteed (@in_guaranteed Optional

) -> TrivialStruct) -> @out P2 { -// CHECK: bb0([[ARG0:%.*]] : $Optional, [[ARG1:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed Optional

) -> TrivialStruct): +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$ss1P_pSgs13TrivialStructVIegnd_ADSgs2P2_pIegyr_TR : $@convention(thin) (Optional, @guaranteed @callee_guaranteed (@in_guaranteed Optional) -> TrivialStruct) -> @out any P2 { +// CHECK: bb0([[ARG0:%.*]] : $Optional, [[ARG1:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed Optional) -> TrivialStruct): // HECK: switch_enum [[ARG0]] : $Optional, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1 // HECK: bb1: -// HECK: [[ONONE:%.*]] = enum $Optional

, #Optional.none!enumelt -// HECK: br bb3([[ONONE]] : $Optional

) +// HECK: [[ONONE:%.*]] = enum $Optional, #Optional.none!enumelt +// HECK: br bb3([[ONONE]] : $Optional) // HECK: bb2([[OSOME:%.*]] : $TrivialStruct): -// HECK: [[INIT_S:%.*]] = init_existential_value [[OSOME]] : $TrivialStruct, $TrivialStruct, $P -// HECK: [[ENUM_S:%.*]] = enum $Optional

, #Optional.some!enumelt, [[INIT_S]] : $P -// HECK: br bb3([[ENUM_S]] : $Optional

) -// HECK: bb3([[OPT_S:%.*]] : $Optional

): +// HECK: [[INIT_S:%.*]] = init_existential_value [[OSOME]] : $TrivialStruct, $TrivialStruct, $any P +// HECK: [[ENUM_S:%.*]] = enum $Optional, #Optional.some!enumelt, [[INIT_S]] : $any P +// HECK: br bb3([[ENUM_S]] : $Optional) +// HECK: bb3([[OPT_S:%.*]] : $Optional): // HECK: [[BORROWED_OPT_S:%.*]] = begin_borrow [[OPT_S]] -// HECK: [[APPLY_P:%.*]] = apply [[ARG1]]([[BORROWED_OPT_S]]) : $@callee_guaranteed (@in_guaranteed Optional

) -> TrivialStruct -// HECK: [[RETVAL:%.*]] = init_existential_value [[APPLY_P]] : $TrivialStruct, $TrivialStruct, $P2 -// HECK: return [[RETVAL]] : $P2 +// HECK: [[APPLY_P:%.*]] = apply [[ARG1]]([[BORROWED_OPT_S]]) : $@callee_guaranteed (@in_guaranteed Optional) -> TrivialStruct +// HECK: [[RETVAL:%.*]] = init_existential_value [[APPLY_P]] : $TrivialStruct, $TrivialStruct, $any P2 +// HECK: return [[RETVAL]] : $any P2 // CHECK-LABEL: } // end sil function '$ss1P_pSgs13TrivialStructVIegnd_ADSgs2P2_pIegyr_TR' // Tests corner-case: reabstraction of an empty tuple to any @@ -835,11 +835,11 @@ func f390_addrCallResult(_ f: (() -> T)?) { // Tests reabstraction / partial apply of protocols under opaque value mode // --- -// CHECK-LABEL: sil hidden [ossa] @$ss16f400_maybeCloneP1cys8Clonable_p_tF : $@convention(thin) (@in_guaranteed Clonable) -> () { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $Clonable): -// HECK: [[OPEN_ARG:%.*]] = open_existential_value [[ARG]] : $Clonable -// HECK: [[APPLY_OPAQUE:%.*]] = apply %{{.*}}<@opened({{.*}}, Clonable) Self>([[OPEN_ARG]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out Optional<τ_0_0> -// HECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}<@opened({{.*}}, Clonable) Self>([[APPLY_OPAQUE]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional +// CHECK-LABEL: sil hidden [ossa] @$ss16f400_maybeCloneP1cys8Clonable_p_tF : $@convention(thin) (@in_guaranteed any Clonable) -> () { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Clonable): +// HECK: [[OPEN_ARG:%.*]] = open_existential_value [[ARG]] : $any Clonable +// HECK: [[APPLY_OPAQUE:%.*]] = apply %{{.*}}<@opened({{.*}}, any Clonable) Self>([[OPEN_ARG]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out Optional<τ_0_0> +// HECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}<@opened({{.*}}, any Clonable) Self>([[APPLY_OPAQUE]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional // CHECK-NOT: destroy_value [[ARG]] // HECK: return %{{.*}} : $() // CHECK-LABEL: } // end sil function '$ss16f400_maybeCloneP1cys8Clonable_p_tF' @@ -962,12 +962,12 @@ func f470_nativeToC(fromAny any: Any) -> AnyObject { // Test emitOpenExistential. // --- -// CHECK-LABEL: sil hidden [ossa] @$ss13f480_getError04someC0yps0C0_p_tF : $@convention(thin) (@guaranteed Error) -> @out Any { -// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error): -// HECK: [[VAL:%.*]] = open_existential_box_value [[ARG]] : $Error to $@opened("{{.*}}", Error) Self -// HECK: [[COPY:%.*]] = copy_value [[VAL]] : $@opened("{{.*}}", Error) Self -// HECK: [[ANY:%.*]] = init_existential_value [[COPY]] : $@opened("{{.*}}", Error) Self, $@opened("{{.*}}", Error) Self, $Any -// CHECK-NOT: destroy_value [[ARG]] : $Error +// CHECK-LABEL: sil hidden [ossa] @$ss13f480_getError04someC0yps0C0_p_tF : $@convention(thin) (@guaranteed any Error) -> @out Any { +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Error): +// HECK: [[VAL:%.*]] = open_existential_box_value [[ARG]] : $any Error to $@opened("{{.*}}", any Error) Self +// HECK: [[COPY:%.*]] = copy_value [[VAL]] : $@opened("{{.*}}", any Error) Self +// HECK: [[ANY:%.*]] = init_existential_value [[COPY]] : $@opened("{{.*}}", any Error) Self, $@opened("{{.*}}", any Error) Self, $Any +// CHECK-NOT: destroy_value [[ARG]] : $any Error // HECK: return [[ANY]] : $Any // CHECK-LABEL: } // end sil function '$ss13f480_getError04someC0yps0C0_p_tF' func f480_getError(someError: Error) -> Any { @@ -976,17 +976,17 @@ func f480_getError(someError: Error) -> Any { // Test visitBindOptionalExpr // --- -// CHECK-LABEL: sil hidden [ossa] @$ss15f500_getAnyHashys1P_pSgs14ConvertibleToP_pSgF : $@convention(thin) (@in_guaranteed Optional) -> @out Optional

{ -// CHECK: bb0(%0 : @guaranteed $Optional): -// HECK: [[COPY:%.*]] = copy_value [[ARG]] : $Optional -// HECK: [[DATA:%.*]] = unchecked_enum_data [[COPY]] : $Optional, #Optional.some!enumelt -// HECK: [[BORROW_DATA:%.*]] = begin_borrow [[DATA]] : $ConvertibleToP -// HECK: [[VAL:%.*]] = open_existential_value [[BORROW_DATA]] : $ConvertibleToP to $@opened("{{.*}}", ConvertibleToP) Self -// HECK: [[WT:%.*]] = witness_method $@opened("{{.*}}", ConvertibleToP) Self, #ConvertibleToP.asP : (Self) -> () -> P, [[VAL]] : $@opened("{{.*}}", ConvertibleToP) Self : $@convention(witness_method: ConvertibleToP) <τ_0_0 where τ_0_0 : ConvertibleToP> (@in_guaranteed τ_0_0) -> @out P -// HECK: [[AS_P:%.*]] = apply [[WT]]<@opened("{{.*}}", ConvertibleToP) Self>([[VAL]]) : $@convention(witness_method: ConvertibleToP) <τ_0_0 where τ_0_0 : ConvertibleToP> (@in_guaranteed τ_0_0) -> @out P -// HECK: [[ENUM:%.*]] = enum $Optional

, #Optional.some!enumelt, [[AS_P]] : $P -// HECK: destroy_value [[DATA]] : $ConvertibleToP -// HECK: br bb{{.*}}([[ENUM]] : $Optional

) +// CHECK-LABEL: sil hidden [ossa] @$ss15f500_getAnyHashys1P_pSgs14ConvertibleToP_pSgF : $@convention(thin) (@in_guaranteed Optional) -> @out Optional { +// CHECK: bb0(%0 : @guaranteed $Optional): +// HECK: [[COPY:%.*]] = copy_value [[ARG]] : $Optional +// HECK: [[DATA:%.*]] = unchecked_enum_data [[COPY]] : $Optional, #Optional.some!enumelt +// HECK: [[BORROW_DATA:%.*]] = begin_borrow [[DATA]] : $any ConvertibleToP +// HECK: [[VAL:%.*]] = open_existential_value [[BORROW_DATA]] : $any ConvertibleToP to $@opened("{{.*}}", any ConvertibleToP) Self +// HECK: [[WT:%.*]] = witness_method $@opened("{{.*}}", any ConvertibleToP) Self, #ConvertibleToP.asP : (Self) -> () -> P, [[VAL]] : $@opened("{{.*}}", any ConvertibleToP) Self : $@convention(witness_method: ConvertibleToP) <τ_0_0 where τ_0_0 : ConvertibleToP> (@in_guaranteed τ_0_0) -> @out any P +// HECK: [[AS_P:%.*]] = apply [[WT]]<@opened("{{.*}}", any ConvertibleToP) Self>([[VAL]]) : $@convention(witness_method: ConvertibleToP) <τ_0_0 where τ_0_0 : ConvertibleToP> (@in_guaranteed τ_0_0) -> @out any P +// HECK: [[ENUM:%.*]] = enum $Optional, #Optional.some!enumelt, [[AS_P]] : $any P +// HECK: destroy_value [[DATA]] : $any ConvertibleToP +// HECK: br bb{{.*}}([[ENUM]] : $Optional) // HECK: } // end sil function '$ss15f500_getAnyHashys1P_pSgs14ConvertibleToP_pSgF' func f500_getAnyHash(_ value: ConvertibleToP?) -> P? { return value?.asP() @@ -1058,20 +1058,20 @@ public func f530_assignToVar() { // Test open_existential_value ownership // --- -// CHECK-LABEL: sil [ossa] @$ss16f540_takeDecoder4fromBi1_s0C0_p_tKF : $@convention(thin) (@in_guaranteed Decoder) -> (Builtin.Int1, @error Error) { -// CHECK: bb0(%0 : @guaranteed $Decoder): -// HECK: [[OPENED:%.*]] = open_existential_value %0 : $Decoder to $@opened("{{.*}}", Decoder) Self -// HECK: [[WT:%.*]] = witness_method $@opened("{{.*}}", Decoder) Self, #Decoder.unkeyedContainer : (Self) -> () throws -> UnkeyedDecodingContainer, %3 : $@opened("{{.*}}", Decoder) Self : $@convention(witness_method: Decoder) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error Error) -// HECK: try_apply [[WT]]<@opened("{{.*}}", Decoder) Self>([[OPENED]]) : $@convention(witness_method: Decoder) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error Error), normal bb2, error bb1 +// CHECK-LABEL: sil [ossa] @$ss16f540_takeDecoder4fromBi1_s0C0_p_tKF : $@convention(thin) (@in_guaranteed any Decoder) -> (Builtin.Int1, @error any Error) { +// CHECK: bb0(%0 : @guaranteed $any Decoder): +// HECK: [[OPENED:%.*]] = open_existential_value %0 : $any Decoder to $@opened("{{.*}}", any Decoder) Self +// HECK: [[WT:%.*]] = witness_method $@opened("{{.*}}", any Decoder) Self, #Decoder.unkeyedContainer : (Self) -> () throws -> UnkeyedDecodingContainer, %3 : $@opened("{{.*}}", any Decoder) Self : $@convention(witness_method: Decoder) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error any Error) +// HECK: try_apply [[WT]]<@opened("{{.*}}", any Decoder) Self>([[OPENED]]) : $@convention(witness_method: Decoder) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error any Error), normal bb2, error bb1 // -// CHECK:bb{{.*}}([[RET1:%.*]] : @owned $UnkeyedDecodingContainer): -// HECK: [[BORROW2:%.*]] = begin_borrow [lexical] [[RET1]] : $UnkeyedDecodingContainer -// HECK: [[OPENED2:%.*]] = open_existential_value [[BORROW2]] : $UnkeyedDecodingContainer to $@opened("{{.*}}", UnkeyedDecodingContainer) Self -// HECK: [[WT2:%.*]] = witness_method $@opened("{{.*}}", UnkeyedDecodingContainer) Self, #UnkeyedDecodingContainer.isAtEnd!getter : (Self) -> () -> Builtin.Int1, [[OPENED2]] : $@opened("{{.*}}", UnkeyedDecodingContainer) Self : $@convention(witness_method: UnkeyedDecodingContainer) <τ_0_0 where τ_0_0 : UnkeyedDecodingContainer> (@in_guaranteed τ_0_0) -> Builtin.Int1 -// HECK: [[RET2:%.*]] = apply [[WT2]]<@opened("{{.*}}", UnkeyedDecodingContainer) Self>([[OPENED2]]) : $@convention(witness_method: UnkeyedDecodingContainer) <τ_0_0 where τ_0_0 : UnkeyedDecodingContainer> (@in_guaranteed τ_0_0) -> Builtin.Int1 -// HECK: end_borrow [[BORROW2]] : $UnkeyedDecodingContainer -// HECK: destroy_value [[RET1]] : $UnkeyedDecodingContainer -// CHECK-NOT: destroy_value %0 : $Decoder +// CHECK:bb{{.*}}([[RET1:%.*]] : @owned $any UnkeyedDecodingContainer): +// HECK: [[BORROW2:%.*]] = begin_borrow [lexical] [[RET1]] : $any UnkeyedDecodingContainer +// HECK: [[OPENED2:%.*]] = open_existential_value [[BORROW2]] : $any UnkeyedDecodingContainer to $@opened("{{.*}}", any UnkeyedDecodingContainer) Self +// HECK: [[WT2:%.*]] = witness_method $@opened("{{.*}}", any UnkeyedDecodingContainer) Self, #UnkeyedDecodingContainer.isAtEnd!getter : (Self) -> () -> Builtin.Int1, [[OPENED2]] : $@opened("{{.*}}", UnkeyedDecodingContainer) Self : $@convention(witness_method: UnkeyedDecodingContainer) <τ_0_0 where τ_0_0 : UnkeyedDecodingContainer> (@in_guaranteed τ_0_0) -> Builtin.Int1 +// HECK: [[RET2:%.*]] = apply [[WT2]]<@opened("{{.*}}", any UnkeyedDecodingContainer) Self>([[OPENED2]]) : $@convention(witness_method: UnkeyedDecodingContainer) <τ_0_0 where τ_0_0 : UnkeyedDecodingContainer> (@in_guaranteed τ_0_0) -> Builtin.Int1 +// HECK: end_borrow [[BORROW2]] : $any UnkeyedDecodingContainer +// HECK: destroy_value [[RET1]] : $any UnkeyedDecodingContainer +// CHECK-NOT: destroy_value %0 : $any Decoder // HECK: return [[RET2]] : $Builtin.Int1 // CHECK-LABEL: } // end sil function '$ss16f540_takeDecoder4fromBi1_s0C0_p_tKF' public func f540_takeDecoder(from decoder: Decoder) throws -> Builtin.Int1 { diff --git a/test/SILGen/opened_existentials.swift b/test/SILGen/opened_existentials.swift index 09924dcca59c7..fca2098e63028 100644 --- a/test/SILGen/opened_existentials.swift +++ b/test/SILGen/opened_existentials.swift @@ -24,10 +24,10 @@ public func test() -> String { // order. This test will break when we properly update the existential-opening // logic to wait until the argument is evaluated. - // CHECK: [[PSTACK:%.*]] = alloc_stack $P - // CHECK: [[GETP:%.*]] = function_ref @$s19opened_existentials4getPAA1P_pyF : $@convention(thin) () -> @out P // user: %2 - // CHECK: [[P:%.*]] = apply [[GETP]]([[PSTACK]]) : $@convention(thin) () -> @out P - // CHECK: [[OPENEDP:%.*]] = open_existential_addr immutable_access [[PSTACK]] : $*P to $*@opened + // CHECK: [[PSTACK:%.*]] = alloc_stack $any P + // CHECK: [[GETP:%.*]] = function_ref @$s19opened_existentials4getPAA1P_pyF : $@convention(thin) () -> @out any P // user: %2 + // CHECK: [[P:%.*]] = apply [[GETP]]([[PSTACK]]) : $@convention(thin) () -> @out any P + // CHECK: [[OPENEDP:%.*]] = open_existential_addr immutable_access [[PSTACK]] : $*any P to $*@opened // CHECK: [[F:%.*]] = function_ref @$s19opened_existentials1fSSyF : $@convention(thin) () -> @owned String // CHECK: [[F_RESULT:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned String g(f(), getP()) diff --git a/test/SILGen/optional_to_bool.swift b/test/SILGen/optional_to_bool.swift index da3512dfbcfd9..6e9a96927468e 100644 --- a/test/SILGen/optional_to_bool.swift +++ b/test/SILGen/optional_to_bool.swift @@ -9,7 +9,7 @@ public class B: A { // CHECK: switch_enum {{%.*}} : $Optional public lazy var x: Int = 0 // CHECK-LABEL: sil [lazy_getter] [noinline] [ossa] @$s16optional_to_bool1BC1y{{[_0-9a-zA-Z]*}}vg - // CHECK: switch_enum_addr {{%.*}} : $*Optional

+ // CHECK: switch_enum_addr {{%.*}} : $*Optional public lazy var y: P = 0 } diff --git a/test/SILGen/ownership.swift b/test/SILGen/ownership.swift index 724d7a29b9ed8..a4ffef9f90923 100644 --- a/test/SILGen/ownership.swift +++ b/test/SILGen/ownership.swift @@ -6,13 +6,13 @@ enum MyError : Error { case case1 } -// CHECK: bb{{[0-9]+}}([[ERROR:%.*]] : @owned $Error): +// CHECK: bb{{[0-9]+}}([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] -// CHECK-NEXT: [[ERROR_SLOT:%.*]] = alloc_stack $Error +// CHECK-NEXT: [[ERROR_SLOT:%.*]] = alloc_stack $any Error // CHECK-NEXT: [[COPIED_BORROWED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]] // CHECK-NEXT: store [[COPIED_BORROWED_ERROR]] to [init] [[ERROR_SLOT]] // CHECK-NEXT: [[ERROR_SLOT_CAST_RESULT:%.*]] = alloc_stack $MyError -// CHECK-NEXT: checked_cast_addr_br copy_on_success Error in [[ERROR_SLOT]] : $*Error to MyError in [[ERROR_SLOT_CAST_RESULT]] : $*MyError +// CHECK-NEXT: checked_cast_addr_br copy_on_success any Error in [[ERROR_SLOT]] : $*any Error to MyError in [[ERROR_SLOT_CAST_RESULT]] : $*MyError func test1(f: () throws -> ()) throws { do { let _ = try f() diff --git a/test/SILGen/parameterized_existentials.swift b/test/SILGen/parameterized_existentials.swift index eb024125a8d89..6f141ab4bf3e9 100644 --- a/test/SILGen/parameterized_existentials.swift +++ b/test/SILGen/parameterized_existentials.swift @@ -24,32 +24,32 @@ struct S: Q { struct R { var force: () -> any P - // CHECK-LABEL: sil hidden [ossa] @$s13parameterized1RV5forceACyxq_q0_GAA1P_px1TRts_q_1URtsq0_1VRtsXPyc_tcfC : $@convention(method) (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> () -> @out P<τ_0_0, τ_0_1, τ_0_2> for , @thin R.Type) -> @owned R { + // CHECK-LABEL: sil hidden [ossa] @$s13parameterized1RV5forceACyxq_q0_GAA1P_px1TRts_q_1URtsq0_1VRtsXPyc_tcfC : $@convention(method) (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> () -> @out any P<τ_0_0, τ_0_1, τ_0_2> for , @thin R.Type) -> @owned R { } -// CHECK-LABEL: sil hidden [ossa] @$s13parameterized6upcastyAA1P_pAA1SVF : $@convention(thin) (S) -> @out P { +// CHECK-LABEL: sil hidden [ossa] @$s13parameterized6upcastyAA1P_pAA1SVF : $@convention(thin) (S) -> @out any P { func upcast(_ x: S) -> any P { - // CHECK: bb0([[RESULT_PARAM:%.*]] : $*P, [[CONCRETE_VAL:%.*]] : $S): - // CHECK: [[Q_INT_STRING_FLOAT:%.*]] = alloc_stack $Q - // CHECK: [[INIT_Q_INT_STRING_FLOAT:%.*]] = init_existential_addr [[Q_INT_STRING_FLOAT]] : $*Q, $S + // CHECK: bb0([[RESULT_PARAM:%.*]] : $*any P, [[CONCRETE_VAL:%.*]] : $S): + // CHECK: [[Q_INT_STRING_FLOAT:%.*]] = alloc_stack $any Q + // CHECK: [[INIT_Q_INT_STRING_FLOAT:%.*]] = init_existential_addr [[Q_INT_STRING_FLOAT]] : $*any Q, $S // CHECK: store [[CONCRETE_VAL]] to [trivial] [[INIT_Q_INT_STRING_FLOAT]] : $*S - // CHECK: [[OPEN_Q_INT_STRING_FLOAT:%.*]] = open_existential_addr immutable_access [[Q_INT_STRING_FLOAT]] : $*Q to $*[[OPENED_Q_INT_STRING_FLOAT:@opened\(.*, Q\) Self]] - // CHECK: [[RESULT_INIT:%.*]] = init_existential_addr [[RESULT_PARAM]] : $*P, $[[OPENED_Q_INT_STRING_FLOAT]] + // CHECK: [[OPEN_Q_INT_STRING_FLOAT:%.*]] = open_existential_addr immutable_access [[Q_INT_STRING_FLOAT]] : $*any Q to $*[[OPENED_Q_INT_STRING_FLOAT:@opened\(.*, any Q\) Self]] + // CHECK: [[RESULT_INIT:%.*]] = init_existential_addr [[RESULT_PARAM]] : $*any P, $[[OPENED_Q_INT_STRING_FLOAT]] // CHECK: copy_addr [[OPEN_Q_INT_STRING_FLOAT]] to [initialization] [[RESULT_INIT]] : $*[[OPENED_Q_INT_STRING_FLOAT]] return x as any Q as any P } -// CHECK-LABEL: sil hidden [ossa] @$s13parameterized12upupupupcastyAA1P_pAA1SVF : $@convention(thin) (S) -> @out P { +// CHECK-LABEL: sil hidden [ossa] @$s13parameterized12upupupupcastyAA1P_pAA1SVF : $@convention(thin) (S) -> @out any P { func upupupupcast(_ x: S) -> any P { - // CHECK: bb0([[RESULT_PARAM:%.*]] : $*P, [[CONCRETE_VAL:%.*]] : $S): + // CHECK: bb0([[RESULT_PARAM:%.*]] : $*any P, [[CONCRETE_VAL:%.*]] : $S): - // CHECK: [[P_INT_STRING_FLOAT:%.*]] = alloc_stack $P - // CHECK: [[INIT_INT_STRING_FLOAT:%.*]] = init_existential_addr [[P_INT_STRING_FLOAT]] : $*P, $S + // CHECK: [[P_INT_STRING_FLOAT:%.*]] = alloc_stack $any P + // CHECK: [[INIT_INT_STRING_FLOAT:%.*]] = init_existential_addr [[P_INT_STRING_FLOAT]] : $*any P, $S // CHECK: store [[CONCRETE_VAL]] to [trivial] [[INIT_INT_STRING_FLOAT]] : $*S - // CHECK: [[OPEN_INT_STRING_FLOAT:%.*]] = open_existential_addr immutable_access %3 : $*P to $*[[OPENED_P_INT_STRING_FLOAT:@opened\(.*, P\) Self]] + // CHECK: [[OPEN_INT_STRING_FLOAT:%.*]] = open_existential_addr immutable_access %3 : $*any P to $*[[OPENED_P_INT_STRING_FLOAT:@opened\(.*, any P\) Self]] - // CHECK: [[RESULT_INIT:%.*]] = init_existential_addr [[RESULT_PARAM]] : $*P, $[[OPENED_P_INT_STRING_FLOAT]] + // CHECK: [[RESULT_INIT:%.*]] = init_existential_addr [[RESULT_PARAM]] : $*any P, $[[OPENED_P_INT_STRING_FLOAT]] // CHECK: copy_addr [[OPEN_INT_STRING_FLOAT]] to [initialization] [[RESULT_INIT]] : $*[[OPENED_P_INT_STRING_FLOAT]] return x as any P as any P } @@ -58,10 +58,10 @@ func use(_ k: (S) -> Void) {} // CHECK-LABEL: sil hidden [ossa] @$s13parameterized11upcastInputyyF : $@convention(thin) () -> () { func upcastInput() { - // CHECK: [[P_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pXEfU_ : $@convention(thin) (@in_guaranteed P) -> () - // CHECK: [[THICK_P_FN:%.*]] = thin_to_thick_function [[P_FN]] : $@convention(thin) (@in_guaranteed P) -> () to $@noescape @callee_guaranteed (@in_guaranteed P) -> () - // CHECK: [[S_TO_P_THUNK_FN:%.*]] = function_ref @$s13parameterized1P_pIgn_AA1SVIegy_TR : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P) -> ()) -> () - // CHECK: [[PARTIAL_INT_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_P_THUNK_FN]]([[THICK_P_FN]]) : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P) -> ()) -> () + // CHECK: [[P_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pXEfU_ : $@convention(thin) (@in_guaranteed any P) -> () + // CHECK: [[THICK_P_FN:%.*]] = thin_to_thick_function [[P_FN]] : $@convention(thin) (@in_guaranteed any P) -> () to $@noescape @callee_guaranteed (@in_guaranteed any P) -> () + // CHECK: [[S_TO_P_THUNK_FN:%.*]] = function_ref @$s13parameterized1P_pIgn_AA1SVIegy_TR : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed any P) -> ()) -> () + // CHECK: [[PARTIAL_INT_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_P_THUNK_FN]]([[THICK_P_FN]]) : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed any P) -> ()) -> () // CHECK: [[NOESCAPE_P_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_INT_THUNK_FN]] : $@callee_guaranteed (S) -> () to $@noescape @callee_guaranteed (S) -> () // CHECK: [[USE_FN:%.*]] = function_ref @$s13parameterized3useyyyAA1SVXEF : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> () // CHECK: {{%.*}} = apply [[USE_FN]]([[NOESCAPE_P_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> () @@ -75,26 +75,26 @@ func reuse(_ k: () -> any P) {} func upcastResult() { // CHECK: [[RES_FN:%.*]] = function_ref @$s13parameterized12upcastResultyyFAA1SVyXEfU_ : $@convention(thin) () -> S // CHECK: [[THICK_RES_FN:%.*]] = thin_to_thick_function [[RES_FN]] : $@convention(thin) () -> S to $@noescape @callee_guaranteed () -> S - // CHECK: [[S_TO_P_RES_THUNK_FN:%.*]] = function_ref @$s13parameterized1SVIgd_AA1P_pSi1TAaDPRts_SS1UAFRtsSf1VAFRtsXPIegr_TR : $@convention(thin) (@noescape @callee_guaranteed () -> S) -> @out P - // CHECK: [[PARTIAL_RES_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_P_RES_THUNK_FN]]([[THICK_RES_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> S) -> @out P - // CHECK: [[NOESCAPE_RES_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_RES_THUNK_FN]] : $@callee_guaranteed () -> @out P to $@noescape @callee_guaranteed () -> @out P - // CHECK: [[REUSE_FN:%.*]] = function_ref @$s13parameterized5reuseyyAA1P_pSi1TAaCPRts_SS1UAERtsSf1VAERtsXPyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> @out P) -> () - // CHECK: {{%.*}} = apply [[REUSE_FN]]([[NOESCAPE_RES_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out P) -> () + // CHECK: [[S_TO_P_RES_THUNK_FN:%.*]] = function_ref @$s13parameterized1SVIgd_AA1P_pSi1TAaDPRts_SS1UAFRtsSf1VAFRtsXPIegr_TR : $@convention(thin) (@noescape @callee_guaranteed () -> S) -> @out any P + // CHECK: [[PARTIAL_RES_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_P_RES_THUNK_FN]]([[THICK_RES_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> S) -> @out any P + // CHECK: [[NOESCAPE_RES_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_RES_THUNK_FN]] : $@callee_guaranteed () -> @out any P to $@noescape @callee_guaranteed () -> @out any P + // CHECK: [[REUSE_FN:%.*]] = function_ref @$s13parameterized5reuseyyAA1P_pSi1TAaCPRts_SS1UAERtsSf1VAERtsXPyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> @out any P) -> () + // CHECK: {{%.*}} = apply [[REUSE_FN]]([[NOESCAPE_RES_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out any P) -> () reuse({ () -> S in S() }) - // CHECK: [[RES_Q_FN:%.*]] = function_ref @$s13parameterized12upcastResultyyFAA1Q_pSi1XAaCPRts_SS1YAERtsSf1ZAERtsXPyXEfU0_ : $@convention(thin) () -> @out Q - // CHECK: [[THICK_NOESCAPE_RES_Q_FN:%.*]] = thin_to_thick_function [[RES_Q_FN]] : $@convention(thin) () -> @out Q to $@noescape @callee_guaranteed () -> @out Q - // CHECK: [[P_TO_Q_RES_THUNK_FN:%.*]] = function_ref @$s13parameterized1Q_pSi1XAaBPRts_SS1YADRtsSf1ZADRtsXPIgr_AA1P_pSi1TAaJPRts_SS1UALRtsSf1VALRtsXPIegr_TR : $@convention(thin) (@noescape @callee_guaranteed () -> @out Q) -> @out P - // CHECK: [[PARTIAL_P_TO_Q_RES_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[P_TO_Q_RES_THUNK_FN]]([[THICK_NOESCAPE_RES_Q_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out Q) -> @out P - // CHECK: [[NOESCAPE_PARTIAL_P_TO_Q_RES_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_P_TO_Q_RES_THUNK_FN]] : $@callee_guaranteed () -> @out P to $@noescape @callee_guaranteed () -> @out P - // CHECK: [[REUSE_FN:%.*]] = function_ref @$s13parameterized5reuseyyAA1P_pSi1TAaCPRts_SS1UAERtsSf1VAERtsXPyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> @out P) -> () - // CHECK: {{%.*}} = apply [[REUSE_FN]]([[NOESCAPE_PARTIAL_P_TO_Q_RES_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out P) -> () + // CHECK: [[RES_Q_FN:%.*]] = function_ref @$s13parameterized12upcastResultyyFAA1Q_pSi1XAaCPRts_SS1YAERtsSf1ZAERtsXPyXEfU0_ : $@convention(thin) () -> @out any Q + // CHECK: [[THICK_NOESCAPE_RES_Q_FN:%.*]] = thin_to_thick_function [[RES_Q_FN]] : $@convention(thin) () -> @out any Q to $@noescape @callee_guaranteed () -> @out any Q + // CHECK: [[P_TO_Q_RES_THUNK_FN:%.*]] = function_ref @$s13parameterized1Q_pSi1XAaBPRts_SS1YADRtsSf1ZADRtsXPIgr_AA1P_pSi1TAaJPRts_SS1UALRtsSf1VALRtsXPIegr_TR : $@convention(thin) (@noescape @callee_guaranteed () -> @out any Q) -> @out any P + // CHECK: [[PARTIAL_P_TO_Q_RES_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[P_TO_Q_RES_THUNK_FN]]([[THICK_NOESCAPE_RES_Q_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out any Q) -> @out any P + // CHECK: [[NOESCAPE_PARTIAL_P_TO_Q_RES_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_P_TO_Q_RES_THUNK_FN]] : $@callee_guaranteed () -> @out any P to $@noescape @callee_guaranteed () -> @out any P + // CHECK: [[REUSE_FN:%.*]] = function_ref @$s13parameterized5reuseyyAA1P_pSi1TAaCPRts_SS1UAERtsSf1VAERtsXPyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> @out any P) -> () + // CHECK: {{%.*}} = apply [[REUSE_FN]]([[NOESCAPE_PARTIAL_P_TO_Q_RES_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out any P) -> () reuse({ () -> any Q in S() }) } -// CHECK-LABEL: sil hidden [ossa] @$s13parameterized5forceAA1P_px1TRts_q_1URtsq0_1VRtsXPyr1_lF : $@convention(thin) () -> @out P { +// CHECK-LABEL: sil hidden [ossa] @$s13parameterized5forceAA1P_px1TRts_q_1URtsq0_1VRtsXPyr1_lF : $@convention(thin) () -> @out any P { func force() -> any P { return R(force: { force() }).force() } diff --git a/test/SILGen/partial_apply_override.swift b/test/SILGen/partial_apply_override.swift index 4ffd362ffed59..269e12c8b3bda 100644 --- a/test/SILGen/partial_apply_override.swift +++ b/test/SILGen/partial_apply_override.swift @@ -29,8 +29,8 @@ public func convert(strings: [String]) -> [Int] { // CHECK: [[CONVERTED:%.*]] = convert_function [[CURRY_RESULT]] // CHECK: [[NOESCAPE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CONVERTED]] // CHECK: // function_ref -// CHECK-NEXT: [[THUNK:%.*]] = function_ref @$sSSSis5Error_pIggdzo_SSSisAA_pIegnrzo_TR : $@convention(thin) (@in_guaranteed String, @noescape @callee_guaranteed (@guaranteed String) -> (Int, @error Error)) -> (@out Int, @error Error) +// CHECK-NEXT: [[THUNK:%.*]] = function_ref @$sSSSis5Error_pIggdzo_SSSisAA_pIegnrzo_TR : $@convention(thin) (@in_guaranteed String, @noescape @callee_guaranteed (@guaranteed String) -> (Int, @error any Error)) -> (@out Int, @error any Error) // CHECK-NEXT: [[REABSTRACTED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[NOESCAPE]]) // CHECK-LABEL: sil private [ossa] @$s22partial_apply_override7convert7stringsSaySiGSaySSG_tFSiSScAA18StringIntConverterCcfu_SiSScfu0_ : $@convention(thin) (@guaranteed String, @guaranteed StringIntConverter) -> Int -// CHECK: [[METHOD:%.*]] = class_method %1 : $StringIntConverter, #StringIntConverter.convert : (StringIntConverter) -> (String) -> Int, $@convention(method) (@in_guaranteed String, @guaranteed StringIntConverter) -> @out Int \ No newline at end of file +// CHECK: [[METHOD:%.*]] = class_method %1 : $StringIntConverter, #StringIntConverter.convert : (StringIntConverter) -> (String) -> Int, $@convention(method) (@in_guaranteed String, @guaranteed StringIntConverter) -> @out Int diff --git a/test/SILGen/partial_apply_protocol.swift b/test/SILGen/partial_apply_protocol.swift index 5297346fa6c3f..855cc73eced49 100644 --- a/test/SILGen/partial_apply_protocol.swift +++ b/test/SILGen/partial_apply_protocol.swift @@ -16,25 +16,25 @@ protocol Clonable { // Partial apply of methods returning Self-derived types //===----------------------------------------------------------------------===// -// CHECK-LABEL: sil hidden [ossa] @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tF : $@convention(thin) (@in_guaranteed Clonable) -> () +// CHECK-LABEL: sil hidden [ossa] @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tF : $@convention(thin) (@in_guaranteed any Clonable) -> () func testClonable(c: Clonable) { - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tFAaD_pycAaD_pcfu_ : $@convention(thin) (@in_guaranteed Clonable) -> @owned @callee_guaranteed () -> @out Clonable + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tFAaD_pycAaD_pcfu_ : $@convention(thin) (@in_guaranteed any Clonable) -> @owned @callee_guaranteed () -> @out any Clonable // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: () -> Clonable = c.clone - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tFAaD_pSgycAaD_pcfu1_ : $@convention(thin) (@in_guaranteed Clonable) -> @owned @callee_guaranteed () -> @out Optional + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tFAaD_pSgycAaD_pcfu1_ : $@convention(thin) (@in_guaranteed any Clonable) -> @owned @callee_guaranteed () -> @out Optional // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: () -> Clonable? = c.maybeClone - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tFAaD_pXpycAaD_pcfu3_ : $@convention(thin) (@in_guaranteed Clonable) -> @owned @callee_guaranteed () -> @thick Clonable.Type + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tFAaD_pXpycAaD_pcfu3_ : $@convention(thin) (@in_guaranteed any Clonable) -> @owned @callee_guaranteed () -> @thick any Clonable.Type // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: () -> Clonable.Type = c.cloneMetatype - // CHECK: [[METHOD_FN:%.*]] = witness_method $@opened("{{.*}}", Clonable) Self, #Clonable.getCloneFn : - // CHECK: [[RESULT:%.*]] = apply [[METHOD_FN]]<@opened("{{.*}}", Clonable) Self>({{.*}}) + // CHECK: [[METHOD_FN:%.*]] = witness_method $@opened("{{.*}}", any Clonable) Self, #Clonable.getCloneFn : + // CHECK: [[RESULT:%.*]] = apply [[METHOD_FN]]<@opened("{{.*}}", any Clonable) Self>({{.*}}) // CHECK: [[CONV_RESULT:%.*]] = convert_function [[RESULT]] - // CHECK: [[THUNK_FN:%.*]] = function_ref @$sxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable - // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}", Clonable) Self>([[CONV_RESULT]]) + // CHECK: [[THUNK_FN:%.*]] = function_ref @$sxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out any Clonable + // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}", any Clonable) Self>([[CONV_RESULT]]) let _: () -> Clonable = c.getCloneFn() // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol12testClonable1cyAA0E0_p_tFAaD_pycycAaD_pcfu5_ @@ -42,8 +42,8 @@ func testClonable(c: Clonable) { let _: () -> () -> Clonable = c.getCloneFn } -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$sxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable -// CHECK: bb0(%0 : $*Clonable, %1 : @guaranteed $@callee_guaranteed () -> @out τ_0_0): +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$sxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out any Clonable +// CHECK: bb0(%0 : $*any Clonable, %1 : @guaranteed $@callee_guaranteed () -> @out τ_0_0): // CHECK-NEXT: [[INNER_RESULT:%.*]] = alloc_stack $τ_0_0 // CHECK-NEXT: apply %1([[INNER_RESULT]]) // CHECK-NEXT: [[OUTER_RESULT:%.*]] = init_existential_addr %0 @@ -58,36 +58,36 @@ func testClonable(c: Clonable) { // Make sure the thunk only has the context generic parameters if needed! //===----------------------------------------------------------------------===// -// CHECK-LABEL: sil hidden [ossa] @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlF : $@convention(thin) (@in_guaranteed Clonable, @in_guaranteed T) -> () +// CHECK-LABEL: sil hidden [ossa] @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlF : $@convention(thin) (@in_guaranteed any Clonable, @in_guaranteed T) -> () func testClonableInGenericContext(c: Clonable, t: T) { - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pycAaE_pcfu_ : $@convention(thin) (@in_guaranteed Clonable) -> @owned @callee_guaranteed () -> @out Clonable + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pycAaE_pcfu_ : $@convention(thin) (@in_guaranteed any Clonable) -> @owned @callee_guaranteed () -> @out any Clonable // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: () -> Clonable = c.clone - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pSgycAaE_pcfu1_ : $@convention(thin) (@in_guaranteed Clonable) -> @owned @callee_guaranteed () -> @out Optional // user: %8 + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pSgycAaE_pcfu1_ : $@convention(thin) (@in_guaranteed any Clonable) -> @owned @callee_guaranteed () -> @out Optional // user: %8 // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: () -> Clonable? = c.maybeClone - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pXpycAaE_pcfu3_ : $@convention(thin) (@in_guaranteed Clonable) -> @owned @callee_guaranteed () -> @thick Clonable.Type + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pXpycAaE_pcfu3_ : $@convention(thin) (@in_guaranteed any Clonable) -> @owned @callee_guaranteed () -> @thick any Clonable.Type // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: () -> Clonable.Type = c.cloneMetatype - // CHECK: [[METHOD_FN:%.*]] = witness_method $@opened("{{.*}}", Clonable) Self, #Clonable.getCloneFn : - // CHECK: [[RESULT:%.*]] = apply [[METHOD_FN]]<@opened("{{.*}}", Clonable) Self>({{.*}}) + // CHECK: [[METHOD_FN:%.*]] = witness_method $@opened("{{.*}}", any Clonable) Self, #Clonable.getCloneFn : + // CHECK: [[RESULT:%.*]] = apply [[METHOD_FN]]<@opened("{{.*}}", any Clonable) Self>({{.*}}) // CHECK: [[RESULT_CONV:%.*]] = convert_function [[RESULT]] - // CHECK: [[THUNK_FN:%.*]] = function_ref @$sxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable - // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}", Clonable) Self>([[RESULT_CONV]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable + // CHECK: [[THUNK_FN:%.*]] = function_ref @$sxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out any Clonable + // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}", any Clonable) Self>([[RESULT_CONV]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out any Clonable let _: () -> Clonable = c.getCloneFn() - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pycycAaE_pcfu5_ : $@convention(thin) (@in_guaranteed Clonable) -> @owned @callee_guaranteed () -> @owned @callee_guaranteed () -> @out Clonable + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pycycAaE_pcfu5_ : $@convention(thin) (@in_guaranteed any Clonable) -> @owned @callee_guaranteed () -> @owned @callee_guaranteed () -> @out any Clonable // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: () -> () -> Clonable = c.getCloneFn - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pxcAaE_pcfu7_ : $@convention(thin) <τ_0_0> (@in_guaranteed Clonable) -> @owned @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> @out Clonable for <τ_0_0> + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pxcAaE_pcfu7_ : $@convention(thin) <τ_0_0> (@in_guaranteed any Clonable) -> @owned @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> @out any Clonable for <τ_0_0> // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: (T) -> Clonable = c.genericClone - // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pycxcAaE_pcfu9_ : $@convention(thin) <τ_0_0> (@in_guaranteed Clonable) -> @owned @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> (@owned @callee_guaranteed () -> @out Clonable) for <τ_0_0> + // CHECK: [[THUNK_FN:%.*]] = function_ref @$s22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlFAaE_pycxcAaE_pcfu9_ : $@convention(thin) <τ_0_0> (@in_guaranteed any Clonable) -> @owned @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> (@owned @callee_guaranteed () -> @out any Clonable) for <τ_0_0> // CHECK: [[THUNK:%.*]] = apply [[THUNK_FN]]({{.*}}) let _: (T) -> () -> Clonable = c.genericGetCloneFn } diff --git a/test/SILGen/partial_apply_protocol_class_refinement_method.swift b/test/SILGen/partial_apply_protocol_class_refinement_method.swift index fea78c1cff3cd..8cc15fb550705 100644 --- a/test/SILGen/partial_apply_protocol_class_refinement_method.swift +++ b/test/SILGen/partial_apply_protocol_class_refinement_method.swift @@ -5,7 +5,7 @@ protocol P { func foo() } protocol Q: class, P {} // CHECK-LABEL: sil hidden [ossa] @$s46partial_apply_protocol_class_refinement_method0A5ApplyyyycAA1Q_pF : $@convention -// CHECK: bb0([[ARG:%.*]] : @guaranteed $Q): +// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Q): func partialApply(_ q: Q) -> () -> () { // CHECK: [[OPENED:%.*]] = open_existential_ref [[ARG]] // CHECK: [[TMP:%.*]] = alloc_stack diff --git a/test/SILGen/partial_apply_throws.swift b/test/SILGen/partial_apply_throws.swift index 46e823fa81acb..3b992e3326bf3 100644 --- a/test/SILGen/partial_apply_throws.swift +++ b/test/SILGen/partial_apply_throws.swift @@ -6,10 +6,10 @@ class C { _ = C.foo -// CHECK-LABEL: sil private [ossa] @$s20partial_apply_throwsyyKcAA1CCcfu_ : $@convention(thin) (@guaranteed C) -> @owned @callee_guaranteed () -> @error Error { +// CHECK-LABEL: sil private [ossa] @$s20partial_apply_throwsyyKcAA1CCcfu_ : $@convention(thin) (@guaranteed C) -> @owned @callee_guaranteed () -> @error any Error { -// CHECK-LABEL: sil private [ossa] @$s20partial_apply_throwsyyKcAA1CCcfu_yyKcfu0_ : $@convention(thin) (@guaranteed C) -> @error Error { -// CHECK: [[FN:%.*]] = class_method %0 : $C, #C.foo : (C) -> () throws -> (), $@convention(method) (@guaranteed C) -> @error Error +// CHECK-LABEL: sil private [ossa] @$s20partial_apply_throwsyyKcAA1CCcfu_yyKcfu0_ : $@convention(thin) (@guaranteed C) -> @error any Error { +// CHECK: [[FN:%.*]] = class_method %0 : $C, #C.foo : (C) -> () throws -> (), $@convention(method) (@guaranteed C) -> @error any Error // CHECK: try_apply [[FN]](%0) // CHECK: return -// CHECK: throw \ No newline at end of file +// CHECK: throw diff --git a/test/SILGen/preconcurrency.swift b/test/SILGen/preconcurrency.swift index 45911de8cb4bc..bbf14e28440b1 100644 --- a/test/SILGen/preconcurrency.swift +++ b/test/SILGen/preconcurrency.swift @@ -9,10 +9,10 @@ class C { // CHECK-LABEL: sil hidden [ossa] @$s14preconcurrency28testModuleMethodWithSendable3anyyyp_tF func testModuleMethodWithSendable(any: Any) { - // CHECK: function_ref @$s14preconcurrency1fyyypF : $@convention(thin) (@in_guaranteed Sendable) -> () + // CHECK: function_ref @$s14preconcurrency1fyyypF : $@convention(thin) (@in_guaranteed any Sendable) -> () let _ = f - // CHECK: function_ref @$s14preconcurrency1fyyypF : $@convention(thin) (@in_guaranteed Sendable) -> () + // CHECK: function_ref @$s14preconcurrency1fyyypF : $@convention(thin) (@in_guaranteed any Sendable) -> () let _ = preconcurrency.f f(any) preconcurrency.f(any) @@ -21,7 +21,7 @@ func testModuleMethodWithSendable(any: Any) { // CHECK-LABEL: sil hidden [ossa] @$s14preconcurrency30testInstanceMethodWithSendable1c3anyyAA1CC_yptF : $@convention(thin) (@guaranteed C, @in_guaranteed Any) -> () { func testInstanceMethodWithSendable(c: C, any: Any) { // CHECK-LABEL: sil private [ossa] @$s14preconcurrency30testInstanceMethodWithSendable1c3anyyAA1CC_yptFyypcAFcfu_yypcfu0_ - // CHECK: class_method %1 : $C, #C.f : (C) -> (Sendable) -> () + // CHECK: class_method %1 : $C, #C.f : (C) -> (any Sendable) -> () let _ = c.f let _ = C.f let _ = C.g diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift index a4a1ac902eb65..836105dc7c66b 100644 --- a/test/SILGen/properties.swift +++ b/test/SILGen/properties.swift @@ -824,25 +824,25 @@ protocol NonmutatingProtocol { // CHECK-NEXT: [[C:%.*]] = load [copy] [[C_INOUT:%.*]] : $*ReferenceType // CHECK-NEXT: end_access [[C_INOUT]] : $*ReferenceType // CHECK-NEXT: [[C_BORROW:%.*]] = begin_borrow [[C]] -// CHECK-NEXT: [[C_FIELD_BOX:%.*]] = alloc_stack $NonmutatingProtocol -// CHECK-NEXT: [[GETTER:%.*]] = class_method [[C_BORROW]] : $ReferenceType, #ReferenceType.p!getter : (ReferenceType) -> () -> NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol -// CHECK-NEXT: apply [[GETTER]]([[C_FIELD_BOX]], [[C_BORROW]]) : $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol +// CHECK-NEXT: [[C_FIELD_BOX:%.*]] = alloc_stack $any NonmutatingProtocol +// CHECK-NEXT: [[GETTER:%.*]] = class_method [[C_BORROW]] : $ReferenceType, #ReferenceType.p!getter : (ReferenceType) -> () -> any NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out any NonmutatingProtocol +// CHECK-NEXT: apply [[GETTER]]([[C_FIELD_BOX]], [[C_BORROW]]) : $@convention(method) (@guaranteed ReferenceType) -> @out any NonmutatingProtocol // CHECK-NEXT: end_borrow [[C_BORROW]] -// CHECK-NEXT: [[C_FIELD_PAYLOAD:%.*]] = open_existential_addr immutable_access [[C_FIELD_BOX]] : $*NonmutatingProtocol to $*@opened("{{.*}}", NonmutatingProtocol) Self -// CHECK-NEXT: [[C_FIELD_COPY:%.*]] = alloc_stack $@opened("{{.*}}", NonmutatingProtocol) Self -// CHECK-NEXT: copy_addr [[C_FIELD_PAYLOAD]] to [initialization] [[C_FIELD_COPY]] : $*@opened("{{.*}}", NonmutatingProtocol) Self +// CHECK-NEXT: [[C_FIELD_PAYLOAD:%.*]] = open_existential_addr immutable_access [[C_FIELD_BOX]] : $*any NonmutatingProtocol to $*@opened("{{.*}}", any NonmutatingProtocol) Self +// CHECK-NEXT: [[C_FIELD_COPY:%.*]] = alloc_stack $@opened("{{.*}}", any NonmutatingProtocol) Self +// CHECK-NEXT: copy_addr [[C_FIELD_PAYLOAD]] to [initialization] [[C_FIELD_COPY]] : $*@opened("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: destroy_value [[C]] : $ReferenceType // CHECK-NEXT: [[C_FIELD_BORROW:%.*]] = alloc_stack // CHECK-NEXT: copy_addr [[C_FIELD_COPY]] to [initialization] [[C_FIELD_BORROW]] -// CHECK-NEXT: [[GETTER:%.*]] = witness_method $@opened("{{.*}}", NonmutatingProtocol) Self, #NonmutatingProtocol.x!getter : (Self) -> () -> Int, [[C_FIELD_PAYLOAD]] : $*@opened("{{.*}}", NonmutatingProtocol) Self : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int -// CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[GETTER]]<@opened("{{.*}}", NonmutatingProtocol) Self>([[C_FIELD_BORROW]]) : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK-NEXT: [[GETTER:%.*]] = witness_method $@opened("{{.*}}", any NonmutatingProtocol) Self, #NonmutatingProtocol.x!getter : (Self) -> () -> Int, [[C_FIELD_PAYLOAD]] : $*@opened("{{.*}}", any NonmutatingProtocol) Self : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[GETTER]]<@opened("{{.*}}", any NonmutatingProtocol) Self>([[C_FIELD_BORROW]]) : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK-NEXT: destroy_addr [[C_FIELD_BORROW]] -// CHECK-NEXT: destroy_addr [[C_FIELD_COPY]] : $*@opened("{{.*}}", NonmutatingProtocol) Self +// CHECK-NEXT: destroy_addr [[C_FIELD_COPY]] : $*@opened("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: dealloc_stack [[C_FIELD_BORROW]] -// CHECK-NEXT: dealloc_stack [[C_FIELD_COPY]] : $*@opened("{{.*}}", NonmutatingProtocol) Self -// CHECK-NEXT: destroy_addr [[C_FIELD_BOX]] : $*NonmutatingProtocol -// CHECK-NEXT: dealloc_stack [[C_FIELD_BOX]] : $*NonmutatingProtocol +// CHECK-NEXT: dealloc_stack [[C_FIELD_COPY]] : $*@opened("{{.*}}", any NonmutatingProtocol) Self +// CHECK-NEXT: destroy_addr [[C_FIELD_BOX]] : $*any NonmutatingProtocol +// CHECK-NEXT: dealloc_stack [[C_FIELD_BOX]] : $*any NonmutatingProtocol // CHECK-NEXT: tuple () // CHECK-NEXT: return diff --git a/test/SILGen/protocol_extensions.swift b/test/SILGen/protocol_extensions.swift index eb18b54b392a1..63afbc50d426c 100644 --- a/test/SILGen/protocol_extensions.swift +++ b/test/SILGen/protocol_extensions.swift @@ -499,80 +499,80 @@ extension P1 { } // CHECK-LABEL: sil hidden [ossa] @$s19protocol_extensions17testExistentials1{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[P:%[0-9]+]] : $*P1, [[B:%[0-9]+]] : $Bool, [[I:%[0-9]+]] : $Int64): +// CHECK: bb0([[P:%[0-9]+]] : $*any P1, [[B:%[0-9]+]] : $Bool, [[I:%[0-9]+]] : $Int64): func testExistentials1(_ p1: P1, b: Bool, i: Int64) { - // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: [[F1:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE2f1{{[_0-9a-zA-Z]*}}F - // CHECK: apply [[F1]]<@opened([[UUID]], P1) Self>([[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> () + // CHECK: apply [[F1]]<@opened([[UUID]], any P1) Self>([[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> () p1.f1() - // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] : // CHECK: [[GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAEySbs5Int64Vcig - // CHECK: apply [[GETTER]]<@opened([[UUID]], P1) Self>([[I]], [[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Int64, @in_guaranteed τ_0_0) -> Bool + // CHECK: apply [[GETTER]]<@opened([[UUID]], any P1) Self>([[I]], [[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Int64, @in_guaranteed τ_0_0) -> Bool // CHECK: store{{.*}} : $*Bool // CHECK: destroy_addr [[POPENED_COPY]] // CHECK: dealloc_stack [[POPENED_COPY]] var b2 = p1[i] - // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] : // CHECK: [[GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE4propSbvg - // CHECK: apply [[GETTER]]<@opened([[UUID]], P1) Self>([[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> Bool + // CHECK: apply [[GETTER]]<@opened([[UUID]], any P1) Self>([[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> Bool // CHECK: store{{.*}} : $*Bool // CHECK: dealloc_stack [[POPENED_COPY]] var b3 = p1.prop } // CHECK-LABEL: sil hidden [ossa] @$s19protocol_extensions17testExistentials2{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[P:%[0-9]+]] : $*P1): +// CHECK: bb0([[P:%[0-9]+]] : $*any P1): func testExistentials2(_ p1: P1) { - // CHECK: [[P1A:%[0-9]+]] = alloc_box ${ var P1 } + // CHECK: [[P1A:%[0-9]+]] = alloc_box ${ var any P1 } // CHECK: [[P1AL:%[0-9]+]] = begin_borrow [lexical] [[P1A]] // CHECK: [[PB:%.*]] = project_box [[P1AL]] - // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: [[FN:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE11returnsSelf{{[_0-9a-zA-Z]*}}F - // CHECK: [[P1AINIT:%[0-9]+]] = init_existential_addr [[PB]] : $*P1, $@opened([[UUID2:".*"]], P1) Self - // CHECK: apply [[FN]]<@opened([[UUID]], P1) Self>([[P1AINIT]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> @out τ_0_0 + // CHECK: [[P1AINIT:%[0-9]+]] = init_existential_addr [[PB]] : $*any P1, $@opened([[UUID2:".*"]], any P1) Self + // CHECK: apply [[FN]]<@opened([[UUID]], any P1) Self>([[P1AINIT]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> @out τ_0_0 var p1a: P1 = p1.returnsSelf() } // CHECK-LABEL: sil hidden [ossa] @$s19protocol_extensions23testExistentialsGetters{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[P:%[0-9]+]] : $*P1): +// CHECK: bb0([[P:%[0-9]+]] : $*any P1): func testExistentialsGetters(_ p1: P1) { - // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] : // CHECK: [[FN:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE5prop2Sbvg - // CHECK: [[B:%[0-9]+]] = apply [[FN]]<@opened([[UUID]], P1) Self>([[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> Bool + // CHECK: [[B:%[0-9]+]] = apply [[FN]]<@opened([[UUID]], any P1) Self>([[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> Bool let b: Bool = p1.prop2 - // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] : // CHECK: [[GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAEyS2bcig - // CHECK: apply [[GETTER]]<@opened([[UUID]], P1) Self>([[B]], [[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @in_guaranteed τ_0_0) -> Bool + // CHECK: apply [[GETTER]]<@opened([[UUID]], any P1) Self>([[B]], [[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @in_guaranteed τ_0_0) -> Bool let b2: Bool = p1[b] } // CHECK-LABEL: sil hidden [ossa] @$s19protocol_extensions22testExistentialSetters{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[P:%[0-9]+]] : $*P1, [[B:%[0-9]+]] : $Bool): +// CHECK: bb0([[P:%[0-9]+]] : $*any P1, [[B:%[0-9]+]] : $Bool): func testExistentialSetters(_ p1: P1, b: Bool) { var p1 = p1 - // CHECK: [[PBOX:%[0-9]+]] = alloc_box ${ var P1 } + // CHECK: [[PBOX:%[0-9]+]] = alloc_box ${ var any P1 } // CHECK: [[PLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[PBOX]] // CHECK: [[PBP:%[0-9]+]] = project_box [[PLIFETIME]] - // CHECK-NEXT: copy_addr [[P]] to [initialization] [[PBP]] : $*P1 + // CHECK-NEXT: copy_addr [[P]] to [initialization] [[PBP]] : $*any P1 // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBP]] - // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr mutable_access [[WRITE]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr mutable_access [[WRITE]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: [[GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE5prop2Sbvs - // CHECK: apply [[GETTER]]<@opened([[UUID]], P1) Self>([[B]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> () + // CHECK: apply [[GETTER]]<@opened([[UUID]], any P1) Self>([[B]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> () // CHECK-NOT: deinit_existential_addr p1.prop2 = b // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBP]] - // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr mutable_access [[WRITE]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr mutable_access [[WRITE]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: [[SUBSETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAEyS2bcis - // CHECK: apply [[SUBSETTER]]<@opened([[UUID]], P1) Self>([[B]], [[B]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, Bool, @inout τ_0_0) -> () - // CHECK-NOT: deinit_existential_addr [[PB]] : $*P1 + // CHECK: apply [[SUBSETTER]]<@opened([[UUID]], any P1) Self>([[B]], [[B]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, Bool, @inout τ_0_0) -> () + // CHECK-NOT: deinit_existential_addr [[PB]] : $*any P1 p1[b] = b // CHECK: return @@ -596,16 +596,16 @@ func testLogicalExistentialSetters(_ hasAP1: HasAP1, _ b: Bool) { // CHECK: [[PBHASP1:%[0-9]+]] = project_box [[HASP1_LIFETIME]] // CHECK-NEXT: copy_addr [[HASP1]] to [initialization] [[PBHASP1]] : $*HasAP1 // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBHASP1]] - // CHECK: [[P1_COPY:%[0-9]+]] = alloc_stack $P1 + // CHECK: [[P1_COPY:%[0-9]+]] = alloc_stack $any P1 // CHECK-NEXT: [[HASP1_COPY:%[0-9]+]] = alloc_stack $HasAP1 // CHECK-NEXT: copy_addr [[WRITE]] to [initialization] [[HASP1_COPY]] : $*HasAP1 - // CHECK: [[SOMEP1_GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions6HasAP1V6someP1AA0F0_pvg : $@convention(method) (@in_guaranteed HasAP1) -> @out P1 - // CHECK: [[RESULT:%[0-9]+]] = apply [[SOMEP1_GETTER]]([[P1_COPY]], [[HASP1_COPY]]) : $@convention(method) (@in_guaranteed HasAP1) -> @out P1 - // CHECK: [[P1_OPENED:%[0-9]+]] = open_existential_addr mutable_access [[P1_COPY]] : $*P1 to $*@opened([[UUID:".*"]], P1) Self + // CHECK: [[SOMEP1_GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions6HasAP1V6someP1AA0F0_pvg : $@convention(method) (@in_guaranteed HasAP1) -> @out any P1 + // CHECK: [[RESULT:%[0-9]+]] = apply [[SOMEP1_GETTER]]([[P1_COPY]], [[HASP1_COPY]]) : $@convention(method) (@in_guaranteed HasAP1) -> @out any P1 + // CHECK: [[P1_OPENED:%[0-9]+]] = open_existential_addr mutable_access [[P1_COPY]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self // CHECK: [[PROP2_SETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE5prop2Sbvs : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> () - // CHECK: apply [[PROP2_SETTER]]<@opened([[UUID]], P1) Self>([[B]], [[P1_OPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> () - // CHECK: [[SOMEP1_SETTER:%[0-9]+]] = function_ref @$s19protocol_extensions6HasAP1V6someP1AA0F0_pvs : $@convention(method) (@in P1, @inout HasAP1) -> () - // CHECK: apply [[SOMEP1_SETTER]]([[P1_COPY]], [[WRITE]]) : $@convention(method) (@in P1, @inout HasAP1) -> () + // CHECK: apply [[PROP2_SETTER]]<@opened([[UUID]], any P1) Self>([[B]], [[P1_OPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> () + // CHECK: [[SOMEP1_SETTER:%[0-9]+]] = function_ref @$s19protocol_extensions6HasAP1V6someP1AA0F0_pvs : $@convention(method) (@in any P1, @inout HasAP1) -> () + // CHECK: apply [[SOMEP1_SETTER]]([[P1_COPY]], [[WRITE]]) : $@convention(method) (@in any P1, @inout HasAP1) -> () // CHECK-NOT: deinit_existential_addr hasAP1.someP1.prop2 = b // CHECK: return @@ -617,7 +617,7 @@ func plusOneP1() -> P1 {} func test_open_existential_semantics_opaque(_ guaranteed: P1, immediate: P1) { var immediate = immediate - // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var P1 } + // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var any P1 } // CHECK: [[IMMEDIATE_LIFETIME:%.*]] = begin_borrow [lexical] [[IMMEDIATE_BOX]] // CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_LIFETIME]] // CHECK: [[VALUE:%.*]] = open_existential_addr immutable_access %0 @@ -637,7 +637,7 @@ func test_open_existential_semantics_opaque(_ guaranteed: P1, // CHECK: dealloc_stack [[IMMEDIATE]] immediate.f1() - // CHECK: [[PLUS_ONE:%.*]] = alloc_stack $P1 + // CHECK: [[PLUS_ONE:%.*]] = alloc_stack $any P1 // CHECK: [[VALUE:%.*]] = open_existential_addr immutable_access [[PLUS_ONE]] // CHECK: [[METHOD:%.*]] = function_ref // -- Can consume the value from our own copy @@ -656,11 +656,11 @@ extension CP1 { func plusOneCP1() -> CP1 {} // CHECK-LABEL: sil hidden [ossa] @$s19protocol_extensions37test_open_existential_semantics_class{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[ARG0:%.*]] : @guaranteed $CP1, [[ARG1:%.*]] : @guaranteed $CP1): +// CHECK: bb0([[ARG0:%.*]] : @guaranteed $any CP1, [[ARG1:%.*]] : @guaranteed $any CP1): func test_open_existential_semantics_class(_ guaranteed: CP1, immediate: CP1) { var immediate = immediate - // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var CP1 } + // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var any CP1 } // CHECK: [[IMMEDIATE_LIFETIME:%.*]] = begin_borrow [lexical] [[IMMEDIATE_BOX]] // CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_LIFETIME]] diff --git a/test/SILGen/protocol_optional.swift b/test/SILGen/protocol_optional.swift index 24c4ce956f381..8714cac6d19f9 100644 --- a/test/SILGen/protocol_optional.swift +++ b/test/SILGen/protocol_optional.swift @@ -69,7 +69,7 @@ func optionalMethodUnboundRefGeneric(t: T) { // CHECK-LABEL: sil hidden [ossa] @$s17protocol_optional0B27MethodUnboundRefExistentialyyF : $@convention(thin) () -> () { // CHECK: bb0: -// CHECK: [[BOX:%[0-9]+]] = alloc_box ${ var @callee_guaranteed (@guaranteed P1) -> @owned Optional<@callee_guaranteed () -> @owned P1> } +// CHECK: [[BOX:%[0-9]+]] = alloc_box ${ var @callee_guaranteed (@guaranteed any P1) -> @owned Optional<@callee_guaranteed () -> @owned any P1> } // CHECK: [[BOX_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[BOX]] // CHECK: [[PBOX:%[0-9]+]] = project_box [[BOX_LIFETIME]] // CHECK: [[THUNK:%[0-9]+]] = function_ref @$[[THUNK_NAME:[_0-9a-zA-Z]+]] @@ -78,15 +78,15 @@ func optionalMethodUnboundRefGeneric(t: T) { // CHECK: end_borrow [[BOX_LIFETIME]] // CHECK: } // end sil function '$s17protocol_optional0B27MethodUnboundRefExistentialyyF' -// CHECK: sil private [ossa] @$[[THUNK_NAME]] : $@convention(thin) (@guaranteed P1) -> @owned Optional<@callee_guaranteed () -> @owned P1> { -// CHECK: bb0([[EXIST:%[0-9]+]] : @guaranteed $P1): -// CHECK: [[OPENED:%[0-9]+]] = open_existential_ref [[EXIST]] : $P1 to $[[OPENED_TY:@opened\("[-A-F0-9]+", P1\) Self]] +// CHECK: sil private [ossa] @$[[THUNK_NAME]] : $@convention(thin) (@guaranteed any P1) -> @owned Optional<@callee_guaranteed () -> @owned any P1> { +// CHECK: bb0([[EXIST:%[0-9]+]] : @guaranteed $any P1): +// CHECK: [[OPENED:%[0-9]+]] = open_existential_ref [[EXIST]] : $any P1 to $[[OPENED_TY:@opened\("[-A-F0-9]+", any P1\) Self]] // CHECK: [[OPENED_COPY:%[0-9]+]] = copy_value [[OPENED]] // CHECK: alloc_stack $Optional<@callee_guaranteed @substituted <τ_0_0 where τ_0_0 : AnyObject> () -> @owned τ_0_0 for <[[OPENED_TY]]>> // CHECK: dynamic_method_br [[OPENED_COPY]] : $[[OPENED_TY]], #P1.methodReturnsSelf!foreign, bb1, bb2 // // CHECK: bb{{[0-9]+}}([[ARG:%[0-9]+]] : @owned $@callee_guaranteed @substituted <τ_0_0 where τ_0_0 : AnyObject> () -> @owned τ_0_0 for <[[OPENED_TY]]>): -// CHECK: [[ERASED:%[0-9]+]] = convert_function [[ARG]] : {{.*}} to $@callee_guaranteed () -> @owned P1 +// CHECK: [[ERASED:%[0-9]+]] = convert_function [[ARG]] : {{.*}} to $@callee_guaranteed () -> @owned any P1 // CHECK: } // end sil function '$[[THUNK_NAME]]' func optionalMethodUnboundRefExistential() { // Test that we erase to existential bounds. diff --git a/test/SILGen/protocol_with_superclass.swift b/test/SILGen/protocol_with_superclass.swift index 781469982e70e..5136b862ad081 100644 --- a/test/SILGen/protocol_with_superclass.swift +++ b/test/SILGen/protocol_with_superclass.swift @@ -55,27 +55,27 @@ extension ProtoRefinesClass { // CHECK-NEXT: destroy_value [[UPCAST2]] : $Concrete let _: Concrete = self - // CHECK: [[BOX:%.*]] = alloc_stack $BaseProto + // CHECK: [[BOX:%.*]] = alloc_stack $any BaseProto // CHECK-NEXT: [[SELF:%.*]] = copy_value %3 : $Self - // CHECK-NEXT: [[ADDR:%.*]] = init_existential_addr [[BOX]] : $*BaseProto, $Self + // CHECK-NEXT: [[ADDR:%.*]] = init_existential_addr [[BOX]] : $*any BaseProto, $Self // CHECK-NEXT: store [[SELF]] to [init] [[ADDR]] : $*Self - // CHECK-NEXT: destroy_addr [[BOX]] : $*BaseProto - // CHECK-NEXT: dealloc_stack [[BOX]] : $*BaseProto + // CHECK-NEXT: destroy_addr [[BOX]] : $*any BaseProto + // CHECK-NEXT: dealloc_stack [[BOX]] : $*any BaseProto let _: BaseProto = self // CHECK: [[SELF:%.*]] = copy_value %3 : $Self - // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[SELF]] : $Self : $Self, $Generic & BaseProto + // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[SELF]] : $Self : $Self, $any Generic & BaseProto let _: BaseProto & Generic = self // CHECK: [[SELF:%.*]] = copy_value %3 : $Self - // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[SELF]] : $Self : $Self, $Concrete & BaseProto + // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[SELF]] : $Self : $Self, $any Concrete & BaseProto let _: BaseProto & Concrete = self // CHECK: return } } -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass22usesProtoRefinesClass1yyAA0eF5Class_pF : $@convention(thin) (@guaranteed ProtoRefinesClass) -> () +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass22usesProtoRefinesClass1yyAA0eF5Class_pF : $@convention(thin) (@guaranteed any ProtoRefinesClass) -> () func usesProtoRefinesClass1(_ t: ProtoRefinesClass) { let x: ProtoRefinesClass.ConcreteAlias = "hi" _ = ProtoRefinesClass.ConcreteAlias.self @@ -148,7 +148,7 @@ extension ProtoRefinesProtoWithClass { } } -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass016usesProtoRefinesE10WithClass1yyAA0efeG5Class_pF : $@convention(thin) (@guaranteed ProtoRefinesProtoWithClass) -> () +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass016usesProtoRefinesE10WithClass1yyAA0efeG5Class_pF : $@convention(thin) (@guaranteed any ProtoRefinesProtoWithClass) -> () func usesProtoRefinesProtoWithClass1(_ t: ProtoRefinesProtoWithClass) { let x: ProtoRefinesProtoWithClass.ConcreteAlias = "hi" _ = ProtoRefinesProtoWithClass.ConcreteAlias.self @@ -198,14 +198,14 @@ class ClassWithInits { protocol ProtocolWithClassInits : ClassWithInits {} -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass26useProtocolWithClassInits1yyAA0efG5Inits_pXpF : $@convention(thin) (@thick ProtocolWithClassInits.Type) -> () +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass26useProtocolWithClassInits1yyAA0efG5Inits_pXpF : $@convention(thin) (@thick any ProtocolWithClassInits.Type) -> () func useProtocolWithClassInits1(_ t: ProtocolWithClassInits.Type) { - // CHECK: [[OPENED:%.*]] = open_existential_metatype %0 : $@thick ProtocolWithClassInits.Type - // CHECK-NEXT: [[UPCAST:%.*]] = upcast [[OPENED]] : $@thick (@opened("{{.*}}", ProtocolWithClassInits) Self).Type to $@thick ClassWithInits.Type + // CHECK: [[OPENED:%.*]] = open_existential_metatype %0 : $@thick any ProtocolWithClassInits.Type + // CHECK-NEXT: [[UPCAST:%.*]] = upcast [[OPENED]] : $@thick (@opened("{{.*}}", any ProtocolWithClassInits) Self).Type to $@thick ClassWithInits.Type // CHECK-NEXT: [[METHOD:%.*]] = class_method [[UPCAST]] : $@thick ClassWithInits.Type, #ClassWithInits.init!allocator : (ClassWithInits.Type) -> (()) -> ClassWithInits, $@convention(method) <τ_0_0> (@thick ClassWithInits<τ_0_0>.Type) -> @owned ClassWithInits<τ_0_0> // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[UPCAST]]) - // CHECK-NEXT: [[CAST:%.*]] = unchecked_ref_cast [[RESULT]] : $ClassWithInits to $@opened("{{.*}}", ProtocolWithClassInits) Self - // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[CAST]] : $@opened("{{.*}}", ProtocolWithClassInits) Self : $@opened("{{.*}}", ProtocolWithClassInits) Self, $ProtocolWithClassInits + // CHECK-NEXT: [[CAST:%.*]] = unchecked_ref_cast [[RESULT]] : $ClassWithInits to $@opened("{{.*}}", any ProtocolWithClassInits) Self + // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[CAST]] : $@opened("{{.*}}", any ProtocolWithClassInits) Self : $@opened("{{.*}}", any ProtocolWithClassInits) Self, $any ProtocolWithClassInits // CHECK-NEXT: destroy_value [[EXISTENTIAL]] let _: ProtocolWithClassInits = t.init(requiredInit: ()) } @@ -219,7 +219,7 @@ func useProtocolWithClassInits2(_ t: T.Type) { protocol ProtocolRefinesClassInits : ProtocolWithClassInits {} -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass29useProtocolRefinesClassInits1yyAA0efG5Inits_pXpF : $@convention(thin) (@thick ProtocolRefinesClassInits.Type) -> () +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass29useProtocolRefinesClassInits1yyAA0efG5Inits_pXpF : $@convention(thin) (@thick any ProtocolRefinesClassInits.Type) -> () func useProtocolRefinesClassInits1(_ t: ProtocolRefinesClassInits.Type) { let _: ProtocolRefinesClassInits = t.init(requiredInit: ()) } @@ -255,17 +255,17 @@ func passesRefinedProtocol(_ r: RefinedProto) { takesBaseProtocol(r) } -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass21passesRefinedProtocolyyAA0E5Proto_pF : $@convention(thin) (@guaranteed RefinedProto) -> () -// CHECK: bb0(%0 : @guaranteed $RefinedProto): -// CHECK: [[OPENED:%.*]] = open_existential_ref %0 : $RefinedProto to $@opened("{{.*}}", RefinedProto) Self -// CHECK-NEXT: [[BASE:%.*]] = alloc_stack $BaseProto -// CHECK-NEXT: [[BASE_PAYLOAD:%.*]] = init_existential_addr [[BASE]] : $*BaseProto, $@opened("{{.*}}", RefinedProto) Self -// CHECK-NEXT: [[OPENED_COPY:%.*]] = copy_value [[OPENED]] : $@opened("{{.*}}", RefinedProto) Self -// CHECK-NEXT: store [[OPENED_COPY]] to [init] [[BASE_PAYLOAD]] : $*@opened("{{.*}}", RefinedProto) Self -// CHECK: [[FUNC:%.*]] = function_ref @$s24protocol_with_superclass17takesBaseProtocolyyAA0E5Proto_pF : $@convention(thin) (@in_guaranteed BaseProto) -> () -// CHECK-NEXT: apply [[FUNC]]([[BASE]]) : $@convention(thin) (@in_guaranteed BaseProto) -> () -// CHECK-NEXT: destroy_addr [[BASE]] : $*BaseProto -// CHECK-NEXT: dealloc_stack [[BASE]] : $*BaseProto +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass21passesRefinedProtocolyyAA0E5Proto_pF : $@convention(thin) (@guaranteed any RefinedProto) -> () +// CHECK: bb0(%0 : @guaranteed $any RefinedProto): +// CHECK: [[OPENED:%.*]] = open_existential_ref %0 : $any RefinedProto to $@opened("{{.*}}", any RefinedProto) Self +// CHECK-NEXT: [[BASE:%.*]] = alloc_stack $any BaseProto +// CHECK-NEXT: [[BASE_PAYLOAD:%.*]] = init_existential_addr [[BASE]] : $*any BaseProto, $@opened("{{.*}}", any RefinedProto) Self +// CHECK-NEXT: [[OPENED_COPY:%.*]] = copy_value [[OPENED]] : $@opened("{{.*}}", any RefinedProto) Self +// CHECK-NEXT: store [[OPENED_COPY]] to [init] [[BASE_PAYLOAD]] : $*@opened("{{.*}}", any RefinedProto) Self +// CHECK: [[FUNC:%.*]] = function_ref @$s24protocol_with_superclass17takesBaseProtocolyyAA0E5Proto_pF : $@convention(thin) (@in_guaranteed any BaseProto) -> () +// CHECK-NEXT: apply [[FUNC]]([[BASE]]) : $@convention(thin) (@in_guaranteed any BaseProto) -> () +// CHECK-NEXT: destroy_addr [[BASE]] : $*any BaseProto +// CHECK-NEXT: dealloc_stack [[BASE]] : $*any BaseProto // CHECK-NEXT: [[RESULT:%.*]] = tuple () // CHECK-NEXT: return [[RESULT]] : $() @@ -278,10 +278,10 @@ func passesFuncTakingBaseClass() { // CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass25passesFuncTakingBaseClassyyF : $@convention(thin) () -> () -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s24protocol_with_superclass9BaseClassCIegg_AA12RefinedProto_pIegg_TR : $@convention(thin) (@guaranteed RefinedProto, @guaranteed @callee_guaranteed (@guaranteed BaseClass) -> ()) -> () -// CHECK: [[PAYLOAD:%.*]] = open_existential_ref %0 : $RefinedProto to $@opened("{{.*}}", RefinedProto) Self +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s24protocol_with_superclass9BaseClassCIegg_AA12RefinedProto_pIegg_TR : $@convention(thin) (@guaranteed any RefinedProto, @guaranteed @callee_guaranteed (@guaranteed BaseClass) -> ()) -> () +// CHECK: [[PAYLOAD:%.*]] = open_existential_ref %0 : $any RefinedProto to $@opened("{{.*}}", any RefinedProto) Self // CHECK: [[COPY:%.*]] = copy_value [[PAYLOAD]] -// CHECK: [[UPCAST:%.*]] = upcast [[COPY]] : $@opened("{{.*}}", RefinedProto) Self to $BaseClass +// CHECK: [[UPCAST:%.*]] = upcast [[COPY]] : $@opened("{{.*}}", any RefinedProto) Self to $BaseClass // CHECK: [[BORROW:%.*]] = begin_borrow [[UPCAST]] // CHECK: apply %1([[BORROW]]) // CHECK: end_borrow [[BORROW]] diff --git a/test/SILGen/protocol_with_superclass_where_clause.swift b/test/SILGen/protocol_with_superclass_where_clause.swift index bb667867d57b3..c8af7f2efa113 100644 --- a/test/SILGen/protocol_with_superclass_where_clause.swift +++ b/test/SILGen/protocol_with_superclass_where_clause.swift @@ -55,27 +55,27 @@ extension ProtoRefinesClass { // CHECK-NEXT: destroy_value [[UPCAST2]] : $Concrete let _: Concrete = self - // CHECK: [[BOX:%.*]] = alloc_stack $BaseProto + // CHECK: [[BOX:%.*]] = alloc_stack $any BaseProto // CHECK-NEXT: [[SELF:%.*]] = copy_value %3 : $Self - // CHECK-NEXT: [[ADDR:%.*]] = init_existential_addr [[BOX]] : $*BaseProto, $Self + // CHECK-NEXT: [[ADDR:%.*]] = init_existential_addr [[BOX]] : $*any BaseProto, $Self // CHECK-NEXT: store [[SELF]] to [init] [[ADDR]] : $*Self - // CHECK-NEXT: destroy_addr [[BOX]] : $*BaseProto - // CHECK-NEXT: dealloc_stack [[BOX]] : $*BaseProto + // CHECK-NEXT: destroy_addr [[BOX]] : $*any BaseProto + // CHECK-NEXT: dealloc_stack [[BOX]] : $*any BaseProto let _: BaseProto = self // CHECK: [[SELF:%.*]] = copy_value %3 : $Self - // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[SELF]] : $Self : $Self, $Generic & BaseProto + // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[SELF]] : $Self : $Self, $any Generic & BaseProto let _: BaseProto & Generic = self // CHECK: [[SELF:%.*]] = copy_value %3 : $Self - // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[SELF]] : $Self : $Self, $Concrete & BaseProto + // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[SELF]] : $Self : $Self, $any Concrete & BaseProto let _: BaseProto & Concrete = self // CHECK: return } } -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass22usesProtoRefinesClass1yyAA0eF5Class_pF : $@convention(thin) (@guaranteed ProtoRefinesClass) -> () +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass22usesProtoRefinesClass1yyAA0eF5Class_pF : $@convention(thin) (@guaranteed any ProtoRefinesClass) -> () func usesProtoRefinesClass1(_ t: ProtoRefinesClass) { let x: ProtoRefinesClass.ConcreteAlias = "hi" _ = ProtoRefinesClass.ConcreteAlias.self @@ -148,7 +148,7 @@ extension ProtoRefinesProtoWithClass { } } -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass016usesProtoRefinesE10WithClass1yyAA0efeG5Class_pF : $@convention(thin) (@guaranteed ProtoRefinesProtoWithClass) -> () +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass016usesProtoRefinesE10WithClass1yyAA0efeG5Class_pF : $@convention(thin) (@guaranteed any ProtoRefinesProtoWithClass) -> () func usesProtoRefinesProtoWithClass1(_ t: ProtoRefinesProtoWithClass) { let x: ProtoRefinesProtoWithClass.ConcreteAlias = "hi" _ = ProtoRefinesProtoWithClass.ConcreteAlias.self @@ -198,14 +198,14 @@ class ClassWithInits { protocol ProtocolWithClassInits where Self : ClassWithInits {} -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass26useProtocolWithClassInits1yyAA0efG5Inits_pXpF : $@convention(thin) (@thick ProtocolWithClassInits.Type) -> () +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass26useProtocolWithClassInits1yyAA0efG5Inits_pXpF : $@convention(thin) (@thick any ProtocolWithClassInits.Type) -> () func useProtocolWithClassInits1(_ t: ProtocolWithClassInits.Type) { - // CHECK: [[OPENED:%.*]] = open_existential_metatype %0 : $@thick ProtocolWithClassInits.Type - // CHECK-NEXT: [[UPCAST:%.*]] = upcast [[OPENED]] : $@thick (@opened("{{.*}}", ProtocolWithClassInits) Self).Type to $@thick ClassWithInits.Type + // CHECK: [[OPENED:%.*]] = open_existential_metatype %0 : $@thick any ProtocolWithClassInits.Type + // CHECK-NEXT: [[UPCAST:%.*]] = upcast [[OPENED]] : $@thick (@opened("{{.*}}", any ProtocolWithClassInits) Self).Type to $@thick ClassWithInits.Type // CHECK-NEXT: [[METHOD:%.*]] = class_method [[UPCAST]] : $@thick ClassWithInits.Type, #ClassWithInits.init!allocator : (ClassWithInits.Type) -> (()) -> ClassWithInits, $@convention(method) <τ_0_0> (@thick ClassWithInits<τ_0_0>.Type) -> @owned ClassWithInits<τ_0_0> // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[UPCAST]]) - // CHECK-NEXT: [[CAST:%.*]] = unchecked_ref_cast [[RESULT]] : $ClassWithInits to $@opened("{{.*}}", ProtocolWithClassInits) Self - // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[CAST]] : $@opened("{{.*}}", ProtocolWithClassInits) Self : $@opened("{{.*}}", ProtocolWithClassInits) Self, $ProtocolWithClassInits + // CHECK-NEXT: [[CAST:%.*]] = unchecked_ref_cast [[RESULT]] : $ClassWithInits to $@opened("{{.*}}", any ProtocolWithClassInits) Self + // CHECK-NEXT: [[EXISTENTIAL:%.*]] = init_existential_ref [[CAST]] : $@opened("{{.*}}", any ProtocolWithClassInits) Self : $@opened("{{.*}}", any ProtocolWithClassInits) Self, $any ProtocolWithClassInits // CHECK-NEXT: destroy_value [[EXISTENTIAL]] let _: ProtocolWithClassInits = t.init(requiredInit: ()) } @@ -219,7 +219,7 @@ func useProtocolWithClassInits2(_ t: T.Type) { protocol ProtocolRefinesClassInits where Self : ProtocolWithClassInits {} -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass29useProtocolRefinesClassInits1yyAA0efG5Inits_pXpF : $@convention(thin) (@thick ProtocolRefinesClassInits.Type) -> () +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass29useProtocolRefinesClassInits1yyAA0efG5Inits_pXpF : $@convention(thin) (@thick any ProtocolRefinesClassInits.Type) -> () func useProtocolRefinesClassInits1(_ t: ProtocolRefinesClassInits.Type) { let _: ProtocolRefinesClassInits = t.init(requiredInit: ()) } @@ -255,17 +255,17 @@ func passesRefinedProtocol(_ r: RefinedProto) { takesBaseProtocol(r) } -// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass21passesRefinedProtocolyyAA0E5Proto_pF : $@convention(thin) (@guaranteed RefinedProto) -> () -// CHECK: bb0(%0 : @guaranteed $RefinedProto): -// CHECK: [[OPENED:%.*]] = open_existential_ref %0 : $RefinedProto to $@opened("{{.*}}", RefinedProto) Self -// CHECK-NEXT: [[BASE:%.*]] = alloc_stack $BaseProto -// CHECK-NEXT: [[BASE_PAYLOAD:%.*]] = init_existential_addr [[BASE]] : $*BaseProto, $@opened("{{.*}}", RefinedProto) Self -// CHECK-NEXT: [[OPENED_COPY:%.*]] = copy_value [[OPENED]] : $@opened("{{.*}}", RefinedProto) Self -// CHECK-NEXT: store [[OPENED_COPY]] to [init] [[BASE_PAYLOAD]] : $*@opened("{{.*}}", RefinedProto) Self -// CHECK: [[FUNC:%.*]] = function_ref @$s24protocol_with_superclass17takesBaseProtocolyyAA0E5Proto_pF : $@convention(thin) (@in_guaranteed BaseProto) -> () -// CHECK-NEXT: apply [[FUNC]]([[BASE]]) : $@convention(thin) (@in_guaranteed BaseProto) -> () -// CHECK-NEXT: destroy_addr [[BASE]] : $*BaseProto -// CHECK-NEXT: dealloc_stack [[BASE]] : $*BaseProto +// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass21passesRefinedProtocolyyAA0E5Proto_pF : $@convention(thin) (@guaranteed any RefinedProto) -> () +// CHECK: bb0(%0 : @guaranteed $any RefinedProto): +// CHECK: [[OPENED:%.*]] = open_existential_ref %0 : $any RefinedProto to $@opened("{{.*}}", any RefinedProto) Self +// CHECK-NEXT: [[BASE:%.*]] = alloc_stack $any BaseProto +// CHECK-NEXT: [[BASE_PAYLOAD:%.*]] = init_existential_addr [[BASE]] : $*any BaseProto, $@opened("{{.*}}", any RefinedProto) Self +// CHECK-NEXT: [[OPENED_COPY:%.*]] = copy_value [[OPENED]] : $@opened("{{.*}}", any RefinedProto) Self +// CHECK-NEXT: store [[OPENED_COPY]] to [init] [[BASE_PAYLOAD]] : $*@opened("{{.*}}", any RefinedProto) Self +// CHECK: [[FUNC:%.*]] = function_ref @$s24protocol_with_superclass17takesBaseProtocolyyAA0E5Proto_pF : $@convention(thin) (@in_guaranteed any BaseProto) -> () +// CHECK-NEXT: apply [[FUNC]]([[BASE]]) : $@convention(thin) (@in_guaranteed any BaseProto) -> () +// CHECK-NEXT: destroy_addr [[BASE]] : $*any BaseProto +// CHECK-NEXT: dealloc_stack [[BASE]] : $*any BaseProto // CHECK-NEXT: [[RESULT:%.*]] = tuple () // CHECK-NEXT: return [[RESULT]] : $() @@ -278,10 +278,10 @@ func passesFuncTakingBaseClass() { // CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass25passesFuncTakingBaseClassyyF : $@convention(thin) () -> () -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s24protocol_with_superclass9BaseClassCIegg_AA12RefinedProto_pIegg_TR : $@convention(thin) (@guaranteed RefinedProto, @guaranteed @callee_guaranteed (@guaranteed BaseClass) -> ()) -> () -// CHECK: [[PAYLOAD:%.*]] = open_existential_ref %0 : $RefinedProto to $@opened("{{.*}}", RefinedProto) Self +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s24protocol_with_superclass9BaseClassCIegg_AA12RefinedProto_pIegg_TR : $@convention(thin) (@guaranteed any RefinedProto, @guaranteed @callee_guaranteed (@guaranteed BaseClass) -> ()) -> () +// CHECK: [[PAYLOAD:%.*]] = open_existential_ref %0 : $any RefinedProto to $@opened("{{.*}}", any RefinedProto) Self // CHECK: [[COPY:%.*]] = copy_value [[PAYLOAD]] -// CHECK: [[UPCAST:%.*]] = upcast [[COPY]] : $@opened("{{.*}}", RefinedProto) Self to $BaseClass +// CHECK: [[UPCAST:%.*]] = upcast [[COPY]] : $@opened("{{.*}}", any RefinedProto) Self to $BaseClass // CHECK: [[BORROW:%.*]] = begin_borrow [[UPCAST]] // CHECK: apply %1([[BORROW]]) // CHECK: end_borrow [[BORROW]] diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift index 7b3352687d237..94bef80856fc7 100644 --- a/test/SILGen/protocols.swift +++ b/test/SILGen/protocols.swift @@ -22,12 +22,12 @@ func use_subscript_rvalue_get(_ i : Int) -> Int { // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_subscript_rvalue_get // CHECK: bb0(%0 : $Int): -// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols16subscriptableGetAA013SubscriptableC0_pvp : $*SubscriptableGet -// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*SubscriptableGet -// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*SubscriptableGet to $*[[OPENED:@opened\(.*, SubscriptableGet\) Self]] +// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols16subscriptableGetAA013SubscriptableC0_pvp : $*any SubscriptableGet +// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*any SubscriptableGet +// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*any SubscriptableGet to $*[[OPENED:@opened\(.*, any SubscriptableGet\) Self]] // CHECK: [[ALLOCSTACK:%[0-9]+]] = alloc_stack $[[OPENED]] // CHECK: copy_addr [[PROJ]] to [initialization] [[ALLOCSTACK]] : $*[[OPENED]] -// CHECK-NEXT: end_access [[READ]] : $*SubscriptableGet +// CHECK-NEXT: end_access [[READ]] : $*any SubscriptableGet // CHECK-NEXT: [[TMP:%.*]] = alloc_stack // CHECK-NEXT: copy_addr [[ALLOCSTACK]] to [initialization] [[TMP]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGet.subscript!getter @@ -44,15 +44,15 @@ func use_subscript_lvalue_get(_ i : Int) -> Int { // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_subscript_lvalue_get // CHECK: bb0(%0 : $Int): -// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols19subscriptableGetSetAA013SubscriptablecD0_pvp : $*SubscriptableGetSet -// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*SubscriptableGetSet -// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*SubscriptableGetSet to $*[[OPENED:@opened\(.*, SubscriptableGetSet\) Self]] +// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols19subscriptableGetSetAA013SubscriptablecD0_pvp : $*any SubscriptableGetSet +// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*any SubscriptableGetSet +// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*any SubscriptableGetSet to $*[[OPENED:@opened\(.*, any SubscriptableGetSet\) Self]] // CHECK: [[ALLOCSTACK:%[0-9]+]] = alloc_stack $[[OPENED]] // CHECK: copy_addr [[PROJ]] to [initialization] [[ALLOCSTACK]] : $*[[OPENED]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGetSet.subscript!getter // CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[METH]]<[[OPENED]]>(%0, [[ALLOCSTACK]]) // CHECK-NEXT: destroy_addr [[ALLOCSTACK]] : $*[[OPENED]] -// CHECK-NEXT: end_access [[READ]] : $*SubscriptableGetSet +// CHECK-NEXT: end_access [[READ]] : $*any SubscriptableGetSet // CHECK-NEXT: dealloc_stack [[ALLOCSTACK]] : $*[[OPENED]] // CHECK-NEXT: return [[RESULT]] @@ -62,9 +62,9 @@ func use_subscript_lvalue_set(_ i : Int) { // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_subscript_lvalue_set // CHECK: bb0(%0 : $Int): -// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols19subscriptableGetSetAA013SubscriptablecD0_pvp : $*SubscriptableGetSet -// CHECK: [[READ:%.*]] = begin_access [modify] [dynamic] [[GLOB]] : $*SubscriptableGetSet -// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr mutable_access [[READ]] : $*SubscriptableGetSet to $*[[OPENED:@opened\(.*, SubscriptableGetSet\) Self]] +// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols19subscriptableGetSetAA013SubscriptablecD0_pvp : $*any SubscriptableGetSet +// CHECK: [[READ:%.*]] = begin_access [modify] [dynamic] [[GLOB]] : $*any SubscriptableGetSet +// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr mutable_access [[READ]] : $*any SubscriptableGetSet to $*[[OPENED:@opened\(.*, any SubscriptableGetSet\) Self]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGetSet.subscript!setter // CHECK-NEXT: apply [[METH]]<[[OPENED]]>(%0, %0, [[PROJ]]) @@ -133,12 +133,12 @@ func use_property_rvalue_get() -> Int { return propertyGet.a } // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_property_rvalue_get -// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols11propertyGetAA18PropertyWithGetter_pvp : $*PropertyWithGetter -// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*PropertyWithGetter -// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*PropertyWithGetter to $*[[OPENED:@opened\(.*, PropertyWithGetter\) Self]] +// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols11propertyGetAA18PropertyWithGetter_pvp : $*any PropertyWithGetter +// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*any PropertyWithGetter +// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*any PropertyWithGetter to $*[[OPENED:@opened\(.*, any PropertyWithGetter\) Self]] // CHECK: [[COPY:%.*]] = alloc_stack $[[OPENED]] // CHECK-NEXT: copy_addr [[PROJ]] to [initialization] [[COPY]] : $*[[OPENED]] -// CHECK-NEXT: end_access [[READ]] : $*PropertyWithGetter +// CHECK-NEXT: end_access [[READ]] : $*any PropertyWithGetter // CHECK: [[BORROW:%.*]] = alloc_stack $[[OPENED]] // CHECK-NEXT: copy_addr [[COPY]] to [initialization] [[BORROW]] : $*[[OPENED]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetter.a!getter @@ -148,9 +148,9 @@ func use_property_lvalue_get() -> Int { return propertyGetSet.b } // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_property_lvalue_get -// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols14propertyGetSetAA24PropertyWithGetterSetter_pvp : $*PropertyWithGetterSetter -// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*PropertyWithGetterSetter -// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*PropertyWithGetterSetter to $*[[OPENED:@opened\(.*, PropertyWithGetterSetter\) Self]] +// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols14propertyGetSetAA24PropertyWithGetterSetter_pvp : $*any PropertyWithGetterSetter +// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*any PropertyWithGetterSetter +// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*any PropertyWithGetterSetter to $*[[OPENED:@opened\(.*, any PropertyWithGetterSetter\) Self]] // CHECK: [[STACK:%[0-9]+]] = alloc_stack $[[OPENED]] // CHECK: copy_addr [[PROJ]] to [initialization] [[STACK]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetterSetter.b!getter @@ -162,9 +162,9 @@ func use_property_lvalue_set(_ x : Int) { // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_property_lvalue_set // CHECK: bb0(%0 : $Int): -// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols14propertyGetSetAA24PropertyWithGetterSetter_pvp : $*PropertyWithGetterSetter -// CHECK: [[READ:%.*]] = begin_access [modify] [dynamic] [[GLOB]] : $*PropertyWithGetterSetter -// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr mutable_access [[READ]] : $*PropertyWithGetterSetter to $*[[OPENED:@opened\(.*, PropertyWithGetterSetter\) Self]] +// CHECK: [[GLOB:%[0-9]+]] = global_addr @$s9protocols14propertyGetSetAA24PropertyWithGetterSetter_pvp : $*any PropertyWithGetterSetter +// CHECK: [[READ:%.*]] = begin_access [modify] [dynamic] [[GLOB]] : $*any PropertyWithGetterSetter +// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr mutable_access [[READ]] : $*any PropertyWithGetterSetter to $*[[OPENED:@opened\(.*, any PropertyWithGetterSetter\) Self]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetterSetter.b!setter // CHECK-NEXT: apply [[METH]]<[[OPENED]]>(%0, [[PROJ]]) @@ -233,14 +233,14 @@ func use_initializable_archetype(_ t: T, i: Int) { // CHECK: sil hidden [ossa] @$s9protocols29use_initializable_existential{{[_0-9a-zA-Z]*}}F func use_initializable_existential(_ im: Initializable.Type, i: Int) { -// CHECK: bb0([[IM:%[0-9]+]] : $@thick Initializable.Type, [[I:%[0-9]+]] : $Int): -// CHECK: [[ARCHETYPE_META:%[0-9]+]] = open_existential_metatype [[IM]] : $@thick Initializable.Type to $@thick (@opened([[N:".*"]], Initializable) Self).Type -// CHECK: [[TEMP_VALUE:%[0-9]+]] = alloc_stack $Initializable -// CHECK: [[INIT_WITNESS:%[0-9]+]] = witness_method $@opened([[N]], Initializable) Self, #Initializable.init!allocator : {{.*}}, [[ARCHETYPE_META]]{{.*}} : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0 -// CHECK: [[TEMP_ADDR:%[0-9]+]] = init_existential_addr [[TEMP_VALUE]] : $*Initializable, $@opened([[N]], Initializable) Self -// CHECK: [[INIT_RESULT:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]], Initializable) Self>([[TEMP_ADDR]], [[I]], [[ARCHETYPE_META]]) : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0 -// CHECK: destroy_addr [[TEMP_VALUE]] : $*Initializable -// CHECK: dealloc_stack [[TEMP_VALUE]] : $*Initializable +// CHECK: bb0([[IM:%[0-9]+]] : $@thick any Initializable.Type, [[I:%[0-9]+]] : $Int): +// CHECK: [[ARCHETYPE_META:%[0-9]+]] = open_existential_metatype [[IM]] : $@thick any Initializable.Type to $@thick (@opened([[N:".*"]], any Initializable) Self).Type +// CHECK: [[TEMP_VALUE:%[0-9]+]] = alloc_stack $any Initializable +// CHECK: [[INIT_WITNESS:%[0-9]+]] = witness_method $@opened([[N]], any Initializable) Self, #Initializable.init!allocator : {{.*}}, [[ARCHETYPE_META]]{{.*}} : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0 +// CHECK: [[TEMP_ADDR:%[0-9]+]] = init_existential_addr [[TEMP_VALUE]] : $*any Initializable, $@opened([[N]], any Initializable) Self +// CHECK: [[INIT_RESULT:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]], any Initializable) Self>([[TEMP_ADDR]], [[I]], [[ARCHETYPE_META]]) : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0 +// CHECK: destroy_addr [[TEMP_VALUE]] : $*any Initializable +// CHECK: dealloc_stack [[TEMP_VALUE]] : $*any Initializable im.init(int: i) // CHECK: [[RESULT:%[0-9]+]] = tuple () // CHECK: return [[RESULT]] : $() @@ -381,13 +381,13 @@ func testExistentialPropertyRead(_ t: inout T) { } // CHECK-LABEL: sil hidden [ossa] @$s9protocols27testExistentialPropertyRead{{[_0-9a-zA-Z]*}}F // CHECK: [[READ:%.*]] = begin_access [read] [unknown] %0 : $*T -// CHECK: [[P_TEMP:%.*]] = alloc_stack $PropertyWithGetterSetter +// CHECK: [[P_TEMP:%.*]] = alloc_stack $any PropertyWithGetterSetter // CHECK: [[T_TEMP:%.*]] = alloc_stack $T // CHECK: copy_addr [[READ]] to [initialization] [[T_TEMP]] : $*T // CHECK: [[P_GETTER:%.*]] = witness_method $T, #ExistentialProperty.p!getter : // CHECK-NEXT: apply [[P_GETTER]]([[P_TEMP]], [[T_TEMP]]) // CHECK-NEXT: destroy_addr [[T_TEMP]] -// CHECK-NEXT: [[OPEN:%.*]] = open_existential_addr immutable_access [[P_TEMP]] : $*PropertyWithGetterSetter to $*[[P_OPENED:@opened\(.*, PropertyWithGetterSetter\) Self]] +// CHECK-NEXT: [[OPEN:%.*]] = open_existential_addr immutable_access [[P_TEMP]] : $*any PropertyWithGetterSetter to $*[[P_OPENED:@opened\(.*, any PropertyWithGetterSetter\) Self]] // CHECK-NEXT: [[T0:%.*]] = alloc_stack $[[P_OPENED]] // CHECK-NEXT: copy_addr [[OPEN]] to [initialization] [[T0]] // CHECK-NEXT: [[B_GETTER:%.*]] = witness_method $[[P_OPENED]], #PropertyWithGetterSetter.b!getter @@ -422,9 +422,9 @@ public func test(_ p: Proto) { p.val.x += 1 } -// CHECK-LABEL: sil [ossa] @$s9protocols4testyyAA5Proto_pF : $@convention(thin) (@in_guaranteed Proto) -> () +// CHECK-LABEL: sil [ossa] @$s9protocols4testyyAA5Proto_pF : $@convention(thin) (@in_guaranteed any Proto) -> () // CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access -// CHECK: [[MAT:%.*]] = witness_method $@opened("{{.*}}", Proto) Self, #Proto.val!modify +// CHECK: [[MAT:%.*]] = witness_method $@opened("{{.*}}", any Proto) Self, #Proto.val!modify // CHECK: ([[BUF:%.*]], [[TOKEN:%.*]]) = begin_apply [[MAT]] // CHECK: end_apply [[TOKEN]] // CHECK: return @@ -438,10 +438,10 @@ protocol SelfReturningSubscript { public func testSelfReturningSubscript() { // CHECK-LABEL: sil private [ossa] @$s9protocols26testSelfReturningSubscriptyyFAA0cdE0_pAaC_pXEfU_ // CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access - // CHECK: [[OPEN_ADDR:%.*]] = alloc_stack $@opened("{{.*}}", SelfReturningSubscript) Self - // CHECK: copy_addr [[OPEN]] to [initialization] [[OPEN_ADDR]] : $*@opened("{{.*}}", SelfReturningSubscript) Self - // CHECK: [[WIT_M:%.*]] = witness_method $@opened("{{.*}}", SelfReturningSubscript) Self, #SelfReturningSubscript.subscript!getter - // CHECK: apply [[WIT_M]]<@opened("{{.*}}", SelfReturningSubscript) Self>({{%.*}}, {{%.*}}, [[OPEN_ADDR]]) + // CHECK: [[OPEN_ADDR:%.*]] = alloc_stack $@opened("{{.*}}", any SelfReturningSubscript) Self + // CHECK: copy_addr [[OPEN]] to [initialization] [[OPEN_ADDR]] : $*@opened("{{.*}}", any SelfReturningSubscript) Self + // CHECK: [[WIT_M:%.*]] = witness_method $@opened("{{.*}}", any SelfReturningSubscript) Self, #SelfReturningSubscript.subscript!getter + // CHECK: apply [[WIT_M]]<@opened("{{.*}}", any SelfReturningSubscript) Self>({{%.*}}, {{%.*}}, [[OPEN_ADDR]]) _ = [String: SelfReturningSubscript]().mapValues { $0[2] } } diff --git a/test/SILGen/reabstract.swift b/test/SILGen/reabstract.swift index a68773ff4d3fa..463ab972d618d 100644 --- a/test/SILGen/reabstract.swift +++ b/test/SILGen/reabstract.swift @@ -113,7 +113,7 @@ func testSharedOwnedOpaque(_ s: C, o: C) { // Make sure that when we generate the reabstraction thunk from Klass -> P, we // pass off the value at +1. -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s10reabstract1P_pIegg_xIegg_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0, @guaranteed @callee_guaranteed (@guaranteed P) -> ()) -> () { +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s10reabstract1P_pIegg_xIegg_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0, @guaranteed @callee_guaranteed (@guaranteed any P) -> ()) -> () { // CHECK: bb0([[ARG:%.*]] : @guaranteed $τ_0_0, // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] // CHECK: [[EXISTENTIAL:%.*]] = init_existential_ref [[ARG_COPY]] diff --git a/test/SILGen/reasync.swift b/test/SILGen/reasync.swift index 7b214db41ca49..2fbf045705030 100644 --- a/test/SILGen/reasync.swift +++ b/test/SILGen/reasync.swift @@ -22,14 +22,14 @@ func asyncCaller(_ fn: () async -> ()) async { await reasyncFunction(fn) } -// CHECK-LABEL: sil hidden [ossa] @$s7reasync23throwingReasyncFunctionyyyyYaKXEYaKF : $@convention(thin) @async (@noescape @async @callee_guaranteed () -> @error Error) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @$s7reasync23throwingReasyncFunctionyyyyYaKXEYaKF : $@convention(thin) @async (@noescape @async @callee_guaranteed () -> @error any Error) -> @error any Error { func throwingReasyncFunction(_ a: () async throws -> ()) reasync throws { try await a() } -// CHECK-LABEL: sil hidden [ossa] @$s7reasync18throwingSyncCalleryyyyXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> @error Error { -// CHECK: [[FN:%.*]] = function_ref @$s7reasync23throwingReasyncFunctionyyyyYaKXEYaKF : $@convention(thin) @async (@noescape @async @callee_guaranteed () -> @error Error) -> @error Error -// CHECK: try_apply [noasync] [[FN]]({{.*}}) : $@convention(thin) @async (@noescape @async @callee_guaranteed () -> @error Error) -> @error Error, normal bb1, error bb2 +// CHECK-LABEL: sil hidden [ossa] @$s7reasync18throwingSyncCalleryyyyXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> @error any Error { +// CHECK: [[FN:%.*]] = function_ref @$s7reasync23throwingReasyncFunctionyyyyYaKXEYaKF : $@convention(thin) @async (@noescape @async @callee_guaranteed () -> @error any Error) -> @error any Error +// CHECK: try_apply [noasync] [[FN]]({{.*}}) : $@convention(thin) @async (@noescape @async @callee_guaranteed () -> @error any Error) -> @error any Error, normal bb1, error bb2 func throwingSyncCaller(_ fn: () -> ()) throws { try throwingReasyncFunction(fn) } diff --git a/test/SILGen/rethrows.swift b/test/SILGen/rethrows.swift index c1eaa16efcb24..d2e5ad8fe3ec5 100644 --- a/test/SILGen/rethrows.swift +++ b/test/SILGen/rethrows.swift @@ -8,44 +8,44 @@ func rethrower(_ fn: () throws -> Int) rethrows -> Int { func thrower() throws -> Int { return 0 } func nonthrower() -> Int { return 0 } -// CHECK-LABEL: sil hidden @$s8rethrows5test0yyKF : $@convention(thin) () -> @error Error { -// CHECK: [[THROWER:%.*]] = function_ref @$s8rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error Error) +// CHECK-LABEL: sil hidden @$s8rethrows5test0yyKF : $@convention(thin) () -> @error any Error { +// CHECK: [[THROWER:%.*]] = function_ref @$s8rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error any Error) // CHECK: [[T0:%.*]] = thin_to_thick_function [[THROWER]] // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[T0]] -// CHECK: [[RETHROWER:%.*]] = function_ref @$s8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error) -// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]] +// CHECK: [[RETHROWER:%.*]] = function_ref @$s8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error) +// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]] // CHECK: [[NORMAL]]([[RESULT_T0:%.*]] : $Int): // CHECK-NEXT: strong_release [[T0]] // CHECK-NEXT: [[T1:%.*]] = tuple () // CHECK-NEXT: return [[T1]] -// CHECK: [[ERROR]]([[RESULT_T0:%.*]] : $Error): +// CHECK: [[ERROR]]([[RESULT_T0:%.*]] : $any Error): // CHECK-NEXT: strong_release [[T0]] // CHECK-NEXT: throw [[RESULT_T0]] func test0() throws { try rethrower(thrower) } -// CHECK-LABEL: sil hidden @$s8rethrows5test1yyKF : $@convention(thin) () -> @error Error { -// CHECK: [[CLOSURE:%.*]] = function_ref @$s8rethrows5test1yyKFSiyKXEfU_ : $@convention(thin) () -> (Int, @error Error) +// CHECK-LABEL: sil hidden @$s8rethrows5test1yyKF : $@convention(thin) () -> @error any Error { +// CHECK: [[CLOSURE:%.*]] = function_ref @$s8rethrows5test1yyKFSiyKXEfU_ : $@convention(thin) () -> (Int, @error any Error) // CHECK: [[T0:%.*]] = thin_to_thick_function [[CLOSURE]] -// CHECK: [[RETHROWER:%.*]] = function_ref @$s8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error) -// CHECK: try_apply [[RETHROWER]]([[T0]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]] +// CHECK: [[RETHROWER:%.*]] = function_ref @$s8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error) +// CHECK: try_apply [[RETHROWER]]([[T0]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]] // CHECK: [[NORMAL]]({{%.*}} : $Int): // CHECK-NEXT: [[T1:%.*]] = tuple () // CHECK-NEXT: return [[T1]] -// CHECK: [[ERROR]]([[ERROR:%.*]] : $Error): +// CHECK: [[ERROR]]([[ERROR:%.*]] : $any Error): // CHECK-NEXT: throw [[ERROR]] // Closure. -// CHECK-LABEL: sil private @$s8rethrows5test1yyKFSiyKXEfU_ : $@convention(thin) () -> (Int, @error Error) { -// CHECK: [[THROWER:%.*]] = function_ref @$s8rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error Error) +// CHECK-LABEL: sil private @$s8rethrows5test1yyKFSiyKXEfU_ : $@convention(thin) () -> (Int, @error any Error) { +// CHECK: [[THROWER:%.*]] = function_ref @$s8rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error any Error) // CHECK: [[T0:%.*]] = thin_to_thick_function [[THROWER]] // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[T0]] -// CHECK: [[RETHROWER:%.*]] = function_ref @$s8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error) -// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]] +// CHECK: [[RETHROWER:%.*]] = function_ref @$s8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error) +// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]] // CHECK: [[NORMAL]]([[RESULT:%.*]] : $Int): // CHECK-NEXT: strong_release [[T0]] // CHECK-NEXT: return [[RESULT]] -// CHECK: [[ERROR]]([[ERROR:%.*]] : $Error): +// CHECK: [[ERROR]]([[ERROR:%.*]] : $any Error): // CHECK-NEXT: strong_release [[T0]] // CHECK-NEXT: throw [[ERROR]] func test1() throws { @@ -55,15 +55,15 @@ func test1() throws { // CHECK-LABEL: sil hidden @$s8rethrows5test2yyF : $@convention(thin) () -> () { // CHECK: [[NONTHROWER:%.*]] = function_ref @$s8rethrows10nonthrowerSiyF : $@convention(thin) () -> Int // CHECK: [[T0:%.*]] = thin_to_thick_function [[NONTHROWER]] -// CHECK: [[T1:%.*]] = convert_function [[T0]] : $@callee_guaranteed () -> Int to $@callee_guaranteed () -> (Int, @error Error) +// CHECK: [[T1:%.*]] = convert_function [[T0]] : $@callee_guaranteed () -> Int to $@callee_guaranteed () -> (Int, @error any Error) // CHECK: [[T2:%.*]] = convert_escape_to_noescape [[T1]] -// CHECK: [[RETHROWER:%.*]] = function_ref @$s8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error) -// CHECK: try_apply [[RETHROWER]]([[T2]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]] +// CHECK: [[RETHROWER:%.*]] = function_ref @$s8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error) +// CHECK: try_apply [[RETHROWER]]([[T2]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]] // CHECK: [[NORMAL]]([[T0:%.*]] : $Int): // CHECK-NEXT: strong_release [[T1]] // CHECK-NEXT: [[RESULT:%.*]] = tuple () // CHECK-NEXT: return [[RESULT]] -// CHECK: [[ERROR]]([[T0:%.*]] : $Error): +// CHECK: [[ERROR]]([[T0:%.*]] : $any Error): // CHECK-NEXT: unreachable func test2() { rethrower(nonthrower) @@ -77,7 +77,7 @@ func test2() { // CHECK: [[NORMAL]]({{%.*}} : $Int): // CHECK-NEXT: [[RESULT:%.*]] = tuple () // CHECK-NEXT: return [[RESULT]] -// CHECK: [[ERROR]]([[ERROR:%.*]] : $Error): +// CHECK: [[ERROR]]([[ERROR:%.*]] : $any Error): // CHECK-NEXT: unreachable // CHECK-LABEL: // end sil function '$s8rethrows5test3yyF' func test3() { diff --git a/test/SILGen/sil_locations.swift b/test/SILGen/sil_locations.swift index bf93823aa55e8..26f9e951f4a90 100644 --- a/test/SILGen/sil_locations.swift +++ b/test/SILGen/sil_locations.swift @@ -286,9 +286,9 @@ func test_isa_2(_ p: P) { // CHECK-LABEL: sil hidden [ossa] @$s13sil_locations10test_isa_2{{[_0-9a-zA-Z]*}}F - // CHECK: alloc_stack $(P, Int), loc "{{.*}}":[[@LINE-10]]:10 - // CHECK: tuple_element_addr{{.*}} $*(P, Int), 0, loc "{{.*}}":[[@LINE-11]]:10 - // CHECK: tuple_element_addr{{.*}} $*(P, Int), 1, loc "{{.*}}":[[@LINE-12]]:10 + // CHECK: alloc_stack $(any P, Int), loc "{{.*}}":[[@LINE-10]]:10 + // CHECK: tuple_element_addr{{.*}} $*(any P, Int), 0, loc "{{.*}}":[[@LINE-11]]:10 + // CHECK: tuple_element_addr{{.*}} $*(any P, Int), 1, loc "{{.*}}":[[@LINE-12]]:10 // CHECK: load {{.*}}, loc "{{.*}}":[[@LINE-12]]:8 // // CHECK: checked_cast_addr_br {{.*}}, loc "{{.*}}":[[@LINE-14]]:9 diff --git a/test/SILGen/subclass_existentials.swift b/test/SILGen/subclass_existentials.swift index 3d39fdb7f3015..05674b8b08288 100644 --- a/test/SILGen/subclass_existentials.swift +++ b/test/SILGen/subclass_existentials.swift @@ -42,8 +42,8 @@ class Derived : Base, P { protocol R {} -// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials11conversions8baseAndP7derived0fE1R0dE5PType0F4Type0fE5RTypeyAA1P_AA4BaseCySiGXc_AA7DerivedCAA1R_ANXcAaI_ALXcXpANmAaO_ANXcXptF : $@convention(thin) (@guaranteed Base & P, @guaranteed Derived, @guaranteed Derived & R, @thick (Base & P).Type, @thick Derived.Type, @thick (Derived & R).Type) -> () { -// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Base & P, +// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials11conversions8baseAndP7derived0fE1R0dE5PType0F4Type0fE5RTypeyAA1P_AA4BaseCySiGXc_AA7DerivedCAA1R_ANXcAaI_ALXcXpANmAaO_ANXcXptF : $@convention(thin) (@guaranteed any Base & P, @guaranteed Derived, @guaranteed any Derived & R, @thick any (Base & P).Type, @thick Derived.Type, @thick any (Derived & R).Type) -> () { +// CHECK: bb0([[ARG0:%.*]] : @guaranteed $any Base & P, func conversions( baseAndP: Base & P, @@ -56,111 +56,111 @@ func conversions( // Values - // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base & P + // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $any Base & P // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]] - // CHECK: [[BASE:%.*]] = upcast [[REF]] : $@opened("{{.*}}", Base & P) Self to $Base + // CHECK: [[BASE:%.*]] = upcast [[REF]] : $@opened("{{.*}}", any Base & P) Self to $Base // CHECK: destroy_value [[BASE]] : $Base let _: Base = baseAndP - // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base & P - // CHECK: [[RESULT:%.*]] = alloc_stack $P - // CHECK: [[RESULT_PAYLOAD:%.*]] = init_existential_addr [[RESULT]] : $*P, $@opened("{{.*}}", Base & P) Self + // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $any Base & P + // CHECK: [[RESULT:%.*]] = alloc_stack $any P + // CHECK: [[RESULT_PAYLOAD:%.*]] = init_existential_addr [[RESULT]] : $*any P, $@opened("{{.*}}", any Base & P) Self // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]] // CHECK: store [[REF]] to [init] [[RESULT_PAYLOAD]] - // CHECK: destroy_addr [[RESULT]] : $*P - // CHECK: dealloc_stack [[RESULT]] : $*P + // CHECK: destroy_addr [[RESULT]] : $*any P + // CHECK: dealloc_stack [[RESULT]] : $*any P let _: P = baseAndP - // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base & P - // CHECK: [[RESULT:%.*]] = alloc_stack $Q - // CHECK: [[RESULT_PAYLOAD:%.*]] = init_existential_addr [[RESULT]] : $*Q, $@opened("{{.*}}", Base & P) Self + // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $any Base & P + // CHECK: [[RESULT:%.*]] = alloc_stack $any Q + // CHECK: [[RESULT_PAYLOAD:%.*]] = init_existential_addr [[RESULT]] : $*any Q, $@opened("{{.*}}", any Base & P) Self // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]] // CHECK: store [[REF]] to [init] [[RESULT_PAYLOAD]] - // CHECK: destroy_addr [[RESULT]] : $*Q - // CHECK: dealloc_stack [[RESULT]] : $*Q + // CHECK: destroy_addr [[RESULT]] : $*any Q + // CHECK: dealloc_stack [[RESULT]] : $*any Q let _: Q = baseAndP - // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG2:%.*]] : $Derived & R + // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG2:%.*]] : $any Derived & R // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]] - // CHECK: [[RESULT:%.*]] = init_existential_ref [[REF]] : $@opened("{{.*}}", Derived & R) Self : $@opened("{{.*}}", Derived & R) Self, $Base & P + // CHECK: [[RESULT:%.*]] = init_existential_ref [[REF]] : $@opened("{{.*}}", any Derived & R) Self : $@opened("{{.*}}", any Derived & R) Self, $any Base & P // CHECK: destroy_value [[RESULT]] let _: Base & P = derivedAndR // Metatypes - // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick (Base & P).Type to $@thick (@opened("{{.*}}", Base & P) Self).Type - // CHECK: [[RESULT:%.*]] = upcast [[PAYLOAD]] : $@thick (@opened("{{.*}}", Base & P) Self).Type to $@thick Base.Type + // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick any (Base & P).Type to $@thick (@opened("{{.*}}", any Base & P) Self).Type + // CHECK: [[RESULT:%.*]] = upcast [[PAYLOAD]] : $@thick (@opened("{{.*}}", any Base & P) Self).Type to $@thick Base.Type let _: Base.Type = baseAndPType - // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick (Base & P).Type to $@thick (@opened("{{.*}}", Base & P) Self).Type - // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}", Base & P) Self).Type, $@thick P.Type + // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick any (Base & P).Type to $@thick (@opened("{{.*}}", any Base & P) Self).Type + // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}", any Base & P) Self).Type, $@thick any P.Type let _: P.Type = baseAndPType - // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick (Base & P).Type to $@thick (@opened("{{.*}}", Base & P) Self).Type - // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}", Base & P) Self).Type, $@thick Q.Type + // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick any (Base & P).Type to $@thick (@opened("{{.*}}", any Base & P) Self).Type + // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}", any Base & P) Self).Type, $@thick any Q.Type let _: Q.Type = baseAndPType - // CHECK: [[RESULT:%.*]] = init_existential_metatype %4 : $@thick Derived.Type, $@thick (Base & P).Type + // CHECK: [[RESULT:%.*]] = init_existential_metatype %4 : $@thick Derived.Type, $@thick any (Base & P).Type let _: (Base & P).Type = derivedType - // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %5 : $@thick (Derived & R).Type to $@thick (@opened("{{.*}}", Derived & R) Self).Type - // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}", Derived & R) Self).Type, $@thick (Base & P).Type + // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %5 : $@thick any (Derived & R).Type to $@thick (@opened("{{.*}}", any Derived & R) Self).Type + // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}", any Derived & R) Self).Type, $@thick any (Base & P).Type let _: (Base & P).Type = derivedAndRType // CHECK: return } -// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials11methodCalls8baseAndP0eF5PTypeyAA1P_AA4BaseCySiGXc_AaE_AHXcXptF : $@convention(thin) (@guaranteed Base & P, @thick (Base & P).Type) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials11methodCalls8baseAndP0eF5PTypeyAA1P_AA4BaseCySiGXc_AaE_AHXcXptF : $@convention(thin) (@guaranteed any Base & P, @thick any (Base & P).Type) -> () { func methodCalls( baseAndP: Base & P, baseAndPType: (Base & P).Type) { - // CHECK: bb0([[ARG0:%.*]] : @guaranteed $Base & P, - // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base & P to $@opened("{{.*}}", Base & P) Self - // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]] : $@opened("{{.*}}", Base & P) Self - // CHECK: [[CLASS_REF:%.*]] = upcast [[REF]] : $@opened("{{.*}}", Base & P) Self to $Base + // CHECK: bb0([[ARG0:%.*]] : @guaranteed $any Base & P, + // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $any Base & P to $@opened("{{.*}}", any Base & P) Self + // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]] : $@opened("{{.*}}", any Base & P) Self + // CHECK: [[CLASS_REF:%.*]] = upcast [[REF]] : $@opened("{{.*}}", any Base & P) Self to $Base // CHECK: [[METHOD:%.*]] = class_method [[CLASS_REF]] : $Base, #Base.classSelfReturn : (Base) -> () -> @dynamic_self Base, $@convention(method) <τ_0_0> (@guaranteed Base<τ_0_0>) -> @owned Base<τ_0_0> // CHECK: [[RESULT_CLASS_REF:%.*]] = apply [[METHOD]]([[CLASS_REF]]) : $@convention(method) <τ_0_0> (@guaranteed Base<τ_0_0>) -> @owned Base<τ_0_0> // CHECK: destroy_value [[CLASS_REF]] : $Base - // CHECK: [[RESULT_REF:%.*]] = unchecked_ref_cast [[RESULT_CLASS_REF]] : $Base to $@opened("{{.*}}", Base & P) Self - // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", Base & P) Self, $Base & P - // CHECK: destroy_value [[RESULT]] : $Base & P + // CHECK: [[RESULT_REF:%.*]] = unchecked_ref_cast [[RESULT_CLASS_REF]] : $Base to $@opened("{{.*}}", any Base & P) Self + // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", any Base & P) Self, $any Base & P + // CHECK: destroy_value [[RESULT]] : $any Base & P let _: Base & P = baseAndP.classSelfReturn() - // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base & P to $@opened("{{.*}}", Base & P) Self - // CHECK: [[SELF_BOX:%.*]] = alloc_stack $@opened("{{.*}}", Base & P) Self - // CHECK: [[SB:%.*]] = store_borrow [[PAYLOAD]] to [[SELF_BOX]] : $*@opened("{{.*}}", Base & P) Self - // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", Base & P) Self, #P.protocolSelfReturn : (Self) -> () -> Self, [[PAYLOAD]] : $@opened("{{.*}}", Base & P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 + // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $any Base & P to $@opened("{{.*}}", any Base & P) Self + // CHECK: [[SELF_BOX:%.*]] = alloc_stack $@opened("{{.*}}", any Base & P) Self + // CHECK: [[SB:%.*]] = store_borrow [[PAYLOAD]] to [[SELF_BOX]] : $*@opened("{{.*}}", any Base & P) Self + // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", any Base & P) Self, #P.protocolSelfReturn : (Self) -> () -> Self, [[PAYLOAD]] : $@opened("{{.*}}", any Base & P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 // CHECK: [[RESULT_BOX:%.*]] = alloc_box // CHECK: [[RESULT_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[RESULT_BOX]] // CHECK: [[RESULT_BUF:%.*]] = project_box [[RESULT_LIFETIME]] - // CHECK: apply [[METHOD]]<@opened("{{.*}}", Base & P) Self>([[RESULT_BUF]], [[SB]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 + // CHECK: apply [[METHOD]]<@opened("{{.*}}", any Base & P) Self>([[RESULT_BUF]], [[SB]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0 // end_borrow [[SB]] - // CHECK: dealloc_stack [[SELF_BOX]] : $*@opened("{{.*}}", Base & P) Self - // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT_BUF]] : $*@opened("{{.*}}", Base & P) Self - // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", Base & P) Self : $@opened("{{.*}}", Base & P) Self, $Base & P - // CHECK: destroy_value [[RESULT]] : $Base & P + // CHECK: dealloc_stack [[SELF_BOX]] : $*@opened("{{.*}}", any Base & P) Self + // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT_BUF]] : $*@opened("{{.*}}", any Base & P) Self + // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", any Base & P) Self : $@opened("{{.*}}", any Base & P) Self, $any Base & P + // CHECK: destroy_value [[RESULT]] : $any Base & P // CHECK: end_borrow [[RESULT_LIFETIME]] // CHECK: dealloc_box [[RESULT_BOX]] let _: Base & P = baseAndP.protocolSelfReturn() - // CHECK: [[METATYPE:%.*]] = open_existential_metatype %1 : $@thick (Base & P).Type to $@thick (@opened("{{.*}}", Base & P) Self).Type - // CHECK: [[METATYPE_REF:%.*]] = upcast [[METATYPE]] : $@thick (@opened("{{.*}}", Base & P) Self).Type to $@thick Base.Type + // CHECK: [[METATYPE:%.*]] = open_existential_metatype %1 : $@thick any (Base & P).Type to $@thick (@opened("{{.*}}", any Base & P) Self).Type + // CHECK: [[METATYPE_REF:%.*]] = upcast [[METATYPE]] : $@thick (@opened("{{.*}}", any Base & P) Self).Type to $@thick Base.Type // CHECK: [[METHOD:%.*]] = function_ref @$s21subclass_existentials4BaseC15classSelfReturnACyxGXDyFZ : $@convention(method) <τ_0_0> (@thick Base<τ_0_0>.Type) -> @owned Base<τ_0_0> // CHECK: [[RESULT_REF2:%.*]] = apply [[METHOD]]([[METATYPE_REF]]) - // CHECK: [[RESULT_REF:%.*]] = unchecked_ref_cast [[RESULT_REF2]] : $Base to $@opened("{{.*}}", Base & P) Self - // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", Base & P) Self : $@opened("{{.*}}", Base & P) Self, $Base & P + // CHECK: [[RESULT_REF:%.*]] = unchecked_ref_cast [[RESULT_REF2]] : $Base to $@opened("{{.*}}", any Base & P) Self + // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", any Base & P) Self : $@opened("{{.*}}", any Base & P) Self, $any Base & P // CHECK: destroy_value [[RESULT]] let _: Base & P = baseAndPType.classSelfReturn() - // CHECK: [[METATYPE:%.*]] = open_existential_metatype %1 : $@thick (Base & P).Type to $@thick (@opened("{{.*}}", Base & P) Self).Type - // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", Base & P) Self, #P.protocolSelfReturn : (Self.Type) -> () -> Self, [[METATYPE]] : $@thick (@opened("{{.*}}", Base & P) Self).Type : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0 + // CHECK: [[METATYPE:%.*]] = open_existential_metatype %1 : $@thick any (Base & P).Type to $@thick (@opened("{{.*}}", any Base & P) Self).Type + // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}", any Base & P) Self, #P.protocolSelfReturn : (Self.Type) -> () -> Self, [[METATYPE]] : $@thick (@opened("{{.*}}", any Base & P) Self).Type : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0 // CHECK: [[RESULT_BOX:%.*]] = alloc_box // CHECK: [[RESULT_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[RESULT_BOX]] // CHECK: [[RESULT_BUF:%.*]] = project_box - // CHECK: apply [[METHOD]]<@opened("{{.*}}", Base & P) Self>([[RESULT_BUF]], [[METATYPE]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0 - // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT_BUF]] : $*@opened("{{.*}}", Base & P) Self - // CHECK: [[RESULT_VALUE:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", Base & P) Self : $@opened("{{.*}}", Base & P) Self, $Base & P + // CHECK: apply [[METHOD]]<@opened("{{.*}}", any Base & P) Self>([[RESULT_BUF]], [[METATYPE]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0 + // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT_BUF]] : $*@opened("{{.*}}", any Base & P) Self + // CHECK: [[RESULT_VALUE:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}", any Base & P) Self : $@opened("{{.*}}", any Base & P) Self, $any Base & P // CHECK: destroy_value [[RESULT_VALUE]] // CHECK: end_borrow [[RESULT_LIFETIME]] // CHECK: dealloc_box [[RESULT_BOX]] @@ -182,21 +182,21 @@ func methodCalls( // CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials29methodCallsOnProtocolMetatypeyyF : $@convention(thin) () -> () { -// CHECK: metatype $@thin (Base & P).Protocol +// CHECK: metatype $@thin (any Base & P).Type // CHECK: function_ref @$[[THUNK1_NAME:[_a-zA-Z0-9]+]] // CHECK: } // end sil function '$s21subclass_existentials29methodCallsOnProtocolMetatypeyyF' // -// CHECK: sil private [ossa] @$[[THUNK1_NAME]] : $@convention(thin) (@guaranteed Base & P) -> @owned @callee_guaranteed () -> @owned Base & P { -// CHECK: bb0(%0 : @guaranteed $Base & P): +// CHECK: sil private [ossa] @$[[THUNK1_NAME]] : $@convention(thin) (@guaranteed any Base & P) -> @owned @callee_guaranteed () -> @owned any Base & P { +// CHECK: bb0(%0 : @guaranteed $any Base & P): // CHECK: [[THUNK2:%[0-9]+]] = function_ref @$[[THUNK2_NAME:[_a-zA-Z0-9]+]] // CHECK: [[SELF_COPY:%[0-9]+]] = copy_value %0 // CHECK: [[RESULT:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK2]]([[SELF_COPY]]) // CHECK: return [[RESULT]] // CHECK: } // end sil function '$[[THUNK1_NAME]]' // -// CHECK: sil private [ossa] @$[[THUNK2_NAME]] : $@convention(thin) (@guaranteed Base & P) -> @owned Base & P { -// CHECK: bb0(%0 : @guaranteed $Base & P): -// CHECK: [[OPENED:%[0-9]+]] = open_existential_ref %0 : $Base & P to $[[OPENED_TY:@opened\("[-A-F0-9]+", Base & P\) Self]] +// CHECK: sil private [ossa] @$[[THUNK2_NAME]] : $@convention(thin) (@guaranteed any Base & P) -> @owned any Base & P { +// CHECK: bb0(%0 : @guaranteed $any Base & P): +// CHECK: [[OPENED:%[0-9]+]] = open_existential_ref %0 : $any Base & P to $[[OPENED_TY:@opened\("[-A-F0-9]+", any Base & P\) Self]] // CHECK: [[OPENED_COPY:%[0-9]+]] = copy_value [[OPENED]] // CHECK: [[CLASS:%[0-9]+]] = upcast [[OPENED_COPY]] : $[[OPENED_TY]] to $Base // CHECK: [[METHOD:%[0-9]+]] = class_method [[CLASS]] : $Base, #Base.classSelfReturn @@ -231,7 +231,7 @@ class PropertyC { } } -// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials16propertyAccessesyyAA9PropertyP_AA0E1CCXcF : $@convention(thin) (@guaranteed PropertyC & PropertyP) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials16propertyAccessesyyAA9PropertyP_AA0E1CCXcF : $@convention(thin) (@guaranteed any PropertyC & PropertyP) -> () { func propertyAccesses(_ x: PropertyP & PropertyC) { var xx = x xx.p.p = x @@ -249,7 +249,7 @@ func propertyAccesses(_ x: PropertyP & PropertyC) { xx[(1, 2)] += 1 } -// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials19functionConversions15returnsBaseAndP0efG5PType0E7Derived0eI4Type0eiG1R0eiG5RTypeyAA1P_AA0F0CySiGXcyc_AaI_ALXcXpycAA0I0CycANmycAA1R_ANXcycAaO_ANXcXpyctF : $@convention(thin) (@guaranteed @callee_guaranteed () -> @owned Base & P, @guaranteed @callee_guaranteed () -> @thick (Base & P).Type, @guaranteed @callee_guaranteed () -> @owned Derived, @guaranteed @callee_guaranteed () -> @thick Derived.Type, @guaranteed @callee_guaranteed () -> @owned Derived & R, @guaranteed @callee_guaranteed () -> @thick (Derived & R).Type) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials19functionConversions15returnsBaseAndP0efG5PType0E7Derived0eI4Type0eiG1R0eiG5RTypeyAA1P_AA0F0CySiGXcyc_AaI_ALXcXpycAA0I0CycANmycAA1R_ANXcycAaO_ANXcXpyctF : $@convention(thin) (@guaranteed @callee_guaranteed () -> @owned any Base & P, @guaranteed @callee_guaranteed () -> @thick any (Base & P).Type, @guaranteed @callee_guaranteed () -> @owned Derived, @guaranteed @callee_guaranteed () -> @thick Derived.Type, @guaranteed @callee_guaranteed () -> @owned any Derived & R, @guaranteed @callee_guaranteed () -> @thick any (Derived & R).Type) -> () { func functionConversions( returnsBaseAndP: @escaping () -> (Base & P), returnsBaseAndPType: @escaping () -> (Base & P).Type, @@ -280,45 +280,45 @@ func functionConversions( // CHECK-NEXT: } } -// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials9downcasts8baseAndP7derived0dE5PType0F4TypeyAA1P_AA4BaseCySiGXc_AA7DerivedCAaG_AJXcXpALmtF : $@convention(thin) (@guaranteed Base & P, @guaranteed Derived, @thick (Base & P).Type, @thick Derived.Type) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials9downcasts8baseAndP7derived0dE5PType0F4TypeyAA1P_AA4BaseCySiGXc_AA7DerivedCAaG_AJXcXpALmtF : $@convention(thin) (@guaranteed any Base & P, @guaranteed Derived, @thick any (Base & P).Type, @thick Derived.Type) -> () { func downcasts( baseAndP: Base & P, derived: Derived, baseAndPType: (Base & P).Type, derivedType: Derived.Type) { - // CHECK: bb0([[ARG0:%.*]] : @guaranteed $Base & P, [[ARG1:%.*]] : @guaranteed $Derived, [[ARG2:%.*]] : $@thick (Base & P).Type, [[ARG3:%.*]] : $@thick Derived.Type): - // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to Derived + // CHECK: bb0([[ARG0:%.*]] : @guaranteed $any Base & P, [[ARG1:%.*]] : @guaranteed $Derived, [[ARG2:%.*]] : $@thick any (Base & P).Type, [[ARG3:%.*]] : $@thick Derived.Type): + // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to Derived let _ = baseAndP as? Derived - // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to Derived + // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to Derived let _ = baseAndP as! Derived - // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to Derived & R + // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to any Derived & R let _ = baseAndP as? (Derived & R) - // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to Derived & R + // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to any Derived & R let _ = baseAndP as! (Derived & R) - // CHECK: checked_cast_br %3 : $@thick Derived.Type to (Derived & R).Type + // CHECK: checked_cast_br %3 : $@thick Derived.Type to any (Derived & R).Type let _ = derivedType as? (Derived & R).Type - // CHECK: unconditional_checked_cast %3 : $@thick Derived.Type to (Derived & R).Type + // CHECK: unconditional_checked_cast %3 : $@thick Derived.Type to any (Derived & R).Type let _ = derivedType as! (Derived & R).Type - // CHECK: checked_cast_br %2 : $@thick (Base & P).Type to Derived.Type + // CHECK: checked_cast_br %2 : $@thick any (Base & P).Type to Derived.Type let _ = baseAndPType as? Derived.Type - // CHECK: unconditional_checked_cast %2 : $@thick (Base & P).Type to Derived.Type + // CHECK: unconditional_checked_cast %2 : $@thick any (Base & P).Type to Derived.Type let _ = baseAndPType as! Derived.Type - // CHECK: checked_cast_br %2 : $@thick (Base & P).Type to (Derived & R).Type + // CHECK: checked_cast_br %2 : $@thick any (Base & P).Type to any (Derived & R).Type let _ = baseAndPType as? (Derived & R).Type - // CHECK: unconditional_checked_cast %2 : $@thick (Base & P).Type to (Derived & R).Type + // CHECK: unconditional_checked_cast %2 : $@thick any (Base & P).Type to any (Derived & R).Type let _ = baseAndPType as! (Derived & R).Type // CHECK: return @@ -335,22 +335,22 @@ func archetypeUpcasts & P + // CHECK-NEXT: init_existential_ref [[COPIED]] : $BaseTAndP : $BaseTAndP, $any Base & P let _: Base & P = baseTAndP // CHECK: [[COPIED:%.*]] = copy_value [[ARG1]] : $BaseIntAndP - // CHECK-NEXT: init_existential_ref [[COPIED]] : $BaseIntAndP : $BaseIntAndP, $Base & P + // CHECK-NEXT: init_existential_ref [[COPIED]] : $BaseIntAndP : $BaseIntAndP, $any Base & P let _: Base & P = baseIntAndP // CHECK: [[COPIED:%.*]] = copy_value [[ARG2]] : $DerivedT - // CHECK-NEXT: init_existential_ref [[COPIED]] : $DerivedT : $DerivedT, $Base & P + // CHECK-NEXT: init_existential_ref [[COPIED]] : $DerivedT : $DerivedT, $any Base & P let _: Base & P = derived // CHECK: return // CHECK-NEXT: } } -// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials18archetypeDowncasts1s1t2pt5baseT0F3Int0f6TAndP_C00fg5AndP_C008derived_C00ji2R_C00fH10P_concrete0fgi2P_K0yx_q_q0_q1_q2_q3_q4_q5_AA1R_AA7DerivedCXcAA1P_AA4BaseCyq_GXcAaQ_ASySiGXctAaQR0_ATRb1_AURb2_ATRb3_AaQR3_AURb4_AaQR4_APRb5_r6_lF : $@convention(thin) , BaseInt : Base, BaseTAndP : Base, BaseTAndP : P, BaseIntAndP : Base, BaseIntAndP : P, DerivedT : Derived> (@in_guaranteed S, @in_guaranteed T, @in_guaranteed PT, @guaranteed BaseT, @guaranteed BaseInt, @guaranteed BaseTAndP, @guaranteed BaseIntAndP, @guaranteed DerivedT, @guaranteed Derived & R, @guaranteed Base & P, @guaranteed Base & P) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s21subclass_existentials18archetypeDowncasts1s1t2pt5baseT0F3Int0f6TAndP_C00fg5AndP_C008derived_C00ji2R_C00fH10P_concrete0fgi2P_K0yx_q_q0_q1_q2_q3_q4_q5_AA1R_AA7DerivedCXcAA1P_AA4BaseCyq_GXcAaQ_ASySiGXctAaQR0_ATRb1_AURb2_ATRb3_AaQR3_AURb4_AaQR4_APRb5_r6_lF : $@convention(thin) , BaseInt : Base, BaseTAndP : Base, BaseTAndP : P, BaseIntAndP : Base, BaseIntAndP : P, DerivedT : Derived> (@in_guaranteed S, @in_guaranteed T, @in_guaranteed PT, @guaranteed BaseT, @guaranteed BaseInt, @guaranteed BaseTAndP, @guaranteed BaseIntAndP, @guaranteed DerivedT, @guaranteed any Derived & R, @guaranteed any Base & P, @guaranteed any Base & P) -> () { func archetypeDowncasts & P, baseIntAndP_concrete: Base & P) { - // CHECK: ([[ARG0:%.*]] : $*S, [[ARG1:%.*]] : $*T, [[ARG2:%.*]] : $*PT, [[ARG3:%.*]] : @guaranteed $BaseT, [[ARG4:%.*]] : @guaranteed $BaseInt, [[ARG5:%.*]] : @guaranteed $BaseTAndP, [[ARG6:%.*]] : @guaranteed $BaseIntAndP, [[ARG7:%.*]] : @guaranteed $DerivedT, [[ARG8:%.*]] : @guaranteed $Derived & R, [[ARG9:%.*]] : @guaranteed $Base & P, [[ARG10:%.*]] : @guaranteed $Base & P) + // CHECK: ([[ARG0:%.*]] : $*S, [[ARG1:%.*]] : $*T, [[ARG2:%.*]] : $*PT, [[ARG3:%.*]] : @guaranteed $BaseT, [[ARG4:%.*]] : @guaranteed $BaseInt, [[ARG5:%.*]] : @guaranteed $BaseTAndP, [[ARG6:%.*]] : @guaranteed $BaseIntAndP, [[ARG7:%.*]] : @guaranteed $DerivedT, [[ARG8:%.*]] : @guaranteed $any Derived & R, [[ARG9:%.*]] : @guaranteed $any Base & P, [[ARG10:%.*]] : @guaranteed $any Base & P) // CHECK: [[COPY:%.*]] = alloc_stack $S // CHECK-NEXT: copy_addr %0 to [initialization] [[COPY]] : $*S - // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Base & P - // CHECK-NEXT: checked_cast_addr_br take_always S in [[COPY]] : $*S to Base & P in [[RESULT]] : $*Base & P + // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $any Base & P + // CHECK-NEXT: checked_cast_addr_br take_always S in [[COPY]] : $*S to any Base & P in [[RESULT]] : $*any Base & P let _ = s as? (Base & P) // CHECK: [[COPY:%.*]] = alloc_stack $S // CHECK-NEXT: copy_addr [[ARG0]] to [initialization] [[COPY]] : $*S - // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Base & P - // CHECK-NEXT: unconditional_checked_cast_addr S in [[COPY]] : $*S to Base & P in [[RESULT]] : $*Base & P + // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $any Base & P + // CHECK-NEXT: unconditional_checked_cast_addr S in [[COPY]] : $*S to any Base & P in [[RESULT]] : $*any Base & P let _ = s as! (Base & P) // CHECK: [[COPY:%.*]] = alloc_stack $S // CHECK-NEXT: copy_addr [[ARG0]] to [initialization] [[COPY]] : $*S - // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Base & P - // CHECK-NEXT: checked_cast_addr_br take_always S in [[COPY]] : $*S to Base & P in [[RESULT]] : $*Base & P + // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $any Base & P + // CHECK-NEXT: checked_cast_addr_br take_always S in [[COPY]] : $*S to any Base & P in [[RESULT]] : $*any Base & P let _ = s as? (Base & P) // CHECK: [[COPY:%.*]] = alloc_stack $S // CHECK-NEXT: copy_addr [[ARG0]] to [initialization] [[COPY]] : $*S - // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Base & P - // CHECK-NEXT: unconditional_checked_cast_addr S in [[COPY]] : $*S to Base & P in [[RESULT]] : $*Base & P + // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $any Base & P + // CHECK-NEXT: unconditional_checked_cast_addr S in [[COPY]] : $*S to any Base & P in [[RESULT]] : $*any Base & P let _ = s as! (Base & P) // CHECK: [[COPIED:%.*]] = copy_value [[ARG5]] : $BaseTAndP - // CHECK-NEXT: checked_cast_br [[COPIED]] : $BaseTAndP to Derived & R + // CHECK-NEXT: checked_cast_br [[COPIED]] : $BaseTAndP to any Derived & R let _ = baseTAndP_archetype as? (Derived & R) // CHECK: [[COPIED:%.*]] = copy_value [[ARG5]] : $BaseTAndP - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $BaseTAndP to Derived & R + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $BaseTAndP to any Derived & R let _ = baseTAndP_archetype as! (Derived & R) - // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base & P - // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $Base & P - // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*Base & P + // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base & P + // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $any Base & P + // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*any Base & P // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Optional // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[RESULT]] : $*Optional, #Optional.some - // CHECK-NEXT: checked_cast_addr_br take_always Base & P in [[COPY]] : $*Base & P to S in [[PAYLOAD]] : $*S + // CHECK-NEXT: checked_cast_addr_br take_always any Base & P in [[COPY]] : $*any Base & P to S in [[PAYLOAD]] : $*S let _ = baseTAndP_concrete as? S - // CHECK: [[COPY:%.*]] = alloc_stack $Base & P - // CHECK-NEXT: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base & P - // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*Base & P + // CHECK: [[COPY:%.*]] = alloc_stack $any Base & P + // CHECK-NEXT: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base & P + // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*any Base & P // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $S - // CHECK-NEXT: unconditional_checked_cast_addr Base & P in [[COPY]] : $*Base & P to S in [[RESULT]] : $*S + // CHECK-NEXT: unconditional_checked_cast_addr any Base & P in [[COPY]] : $*any Base & P to S in [[RESULT]] : $*S let _ = baseTAndP_concrete as! S - // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to BaseT + // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to BaseT let _ = baseTAndP_concrete as? BaseT - // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to BaseT + // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to BaseT let _ = baseTAndP_concrete as! BaseT - // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to BaseInt + // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to BaseInt let _ = baseTAndP_concrete as? BaseInt - // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to BaseInt + // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to BaseInt let _ = baseTAndP_concrete as! BaseInt - // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to BaseTAndP + // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to BaseTAndP let _ = baseTAndP_concrete as? BaseTAndP - // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to BaseTAndP + // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to BaseTAndP let _ = baseTAndP_concrete as! BaseTAndP // CHECK: [[COPIED:%.*]] = copy_value [[ARG6]] : $BaseIntAndP - // CHECK-NEXT: checked_cast_br [[COPIED]] : $BaseIntAndP to Derived & R + // CHECK-NEXT: checked_cast_br [[COPIED]] : $BaseIntAndP to any Derived & R let _ = baseIntAndP_archetype as? (Derived & R) // CHECK: [[COPIED:%.*]] = copy_value [[ARG6]] : $BaseIntAndP - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $BaseIntAndP to Derived & R + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $BaseIntAndP to any Derived & R let _ = baseIntAndP_archetype as! (Derived & R) - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $Base & P - // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*Base & P + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $any Base & P + // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*any Base & P // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Optional // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[RESULT]] : $*Optional, #Optional.some - // CHECK-NEXT: checked_cast_addr_br take_always Base & P in [[COPY]] : $*Base & P to S in [[PAYLOAD]] : $*S + // CHECK-NEXT: checked_cast_addr_br take_always any Base & P in [[COPY]] : $*any Base & P to S in [[PAYLOAD]] : $*S let _ = baseIntAndP_concrete as? S - // CHECK: [[COPY:%.*]] = alloc_stack $Base & P - // CHECK-NEXT: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*Base & P + // CHECK: [[COPY:%.*]] = alloc_stack $any Base & P + // CHECK-NEXT: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*any Base & P // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $S - // CHECK-NEXT: unconditional_checked_cast_addr Base & P in [[COPY]] : $*Base & P to S in [[RESULT]] : $*S + // CHECK-NEXT: unconditional_checked_cast_addr any Base & P in [[COPY]] : $*any Base & P to S in [[RESULT]] : $*S let _ = baseIntAndP_concrete as! S - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to DerivedT + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to DerivedT let _ = baseIntAndP_concrete as? DerivedT - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to DerivedT + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to DerivedT let _ = baseIntAndP_concrete as! DerivedT - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to BaseT + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to BaseT let _ = baseIntAndP_concrete as? BaseT - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to BaseT + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to BaseT let _ = baseIntAndP_concrete as! BaseT - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to BaseInt + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to BaseInt let _ = baseIntAndP_concrete as? BaseInt - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to BaseInt + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to BaseInt let _ = baseIntAndP_concrete as! BaseInt - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base & P to BaseTAndP + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: checked_cast_br [[COPIED]] : $any Base & P to BaseTAndP let _ = baseIntAndP_concrete as? BaseTAndP - // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base & P - // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base & P to BaseTAndP + // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $any Base & P + // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $any Base & P to BaseTAndP let _ = baseIntAndP_concrete as! BaseTAndP // CHECK: return diff --git a/test/SILGen/switch.swift b/test/SILGen/switch.swift index 7525a124bc757..119e341f665ca 100644 --- a/test/SILGen/switch.swift +++ b/test/SILGen/switch.swift @@ -336,11 +336,11 @@ struct Z : P { func p() {} } // CHECK-LABEL: sil hidden [ossa] @$s6switch10test_isa_11pyAA1P_p_tF func test_isa_1(p: P) { - // CHECK: [[PTMPBUF:%[0-9]+]] = alloc_stack $P - // CHECK-NEXT: copy_addr %0 to [initialization] [[PTMPBUF]] : $*P + // CHECK: [[PTMPBUF:%[0-9]+]] = alloc_stack $any P + // CHECK-NEXT: copy_addr %0 to [initialization] [[PTMPBUF]] : $*any P switch p { // CHECK: [[TMPBUF:%[0-9]+]] = alloc_stack $X - // CHECK: checked_cast_addr_br copy_on_success P in [[P:%.*]] : $*P to X in [[TMPBUF]] : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[P:%.*]] : $*any P to X in [[TMPBUF]] : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]] case is X: // CHECK: [[IS_X]]: @@ -355,7 +355,7 @@ func test_isa_1(p: P) { // CHECK: br [[CONT:bb[0-9]+]] // CHECK: [[IS_NOT_X]]: - // CHECK: checked_cast_addr_br copy_on_success P in [[P]] : $*P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[P]] : $*any P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]] // CHECK: [[IS_Y]]: case is Y: @@ -364,7 +364,7 @@ func test_isa_1(p: P) { b() // CHECK: [[IS_NOT_Y]]: - // CHECK: checked_cast_addr_br copy_on_success P in [[P]] : $*P to Z in {{%.*}} : $*Z, [[IS_Z:bb[0-9]+]], [[IS_NOT_Z:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[P]] : $*any P to Z in {{%.*}} : $*Z, [[IS_Z:bb[0-9]+]], [[IS_NOT_Z:bb[0-9]+]] // CHECK: [[IS_Z]]: case is Z: @@ -386,7 +386,7 @@ func test_isa_1(p: P) { // CHECK-LABEL: sil hidden [ossa] @$s6switch10test_isa_21pyAA1P_p_tF func test_isa_2(p: P) { switch (p, foo()) { - // CHECK: checked_cast_addr_br copy_on_success P in [[P:%.*]] : $*P to X in {{%.*}} : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[P:%.*]] : $*any P to X in {{%.*}} : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]] // CHECK: [[IS_X]]: // CHECK: function_ref @$s6switch3fooSiyF @@ -398,7 +398,7 @@ func test_isa_2(p: P) { a() // CHECK: [[IS_NOT_X]]: - // CHECK: checked_cast_addr_br copy_on_success P in [[P]] : $*P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[P]] : $*any P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]] // CHECK: [[IS_Y]]: // CHECK: function_ref @$s6switch3fooSiyF @@ -412,7 +412,7 @@ func test_isa_2(p: P) { // CHECK: [[NOT_CASE2]]: // CHECK: [[IS_NOT_Y]]: - // CHECK: checked_cast_addr_br copy_on_success P in [[P:%.*]] : $*P to X in {{%.*}} : $*X, [[CASE3:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[P:%.*]] : $*any P to X in {{%.*}} : $*X, [[CASE3:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]] case (is X, _): // CHECK: [[CASE3]]: @@ -422,7 +422,7 @@ func test_isa_2(p: P) { // -- case (is Y, foo()): // CHECK: [[IS_NOT_X]]: - // CHECK: checked_cast_addr_br copy_on_success P in [[P]] : $*P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[P]] : $*any P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]] // CHECK: [[IS_Y]]: // CHECK: function_ref @$s6switch3barSiyF // CHECK: cond_br {{%.*}}, [[CASE4:bb[0-9]+]], [[NOT_CASE4:bb[0-9]+]] diff --git a/test/SILGen/switch_var.swift b/test/SILGen/switch_var.swift index 7de48efd06161..f5eddc212a65b 100644 --- a/test/SILGen/switch_var.swift +++ b/test/SILGen/switch_var.swift @@ -207,17 +207,17 @@ struct X : P { func p() {} } struct Y : P { func p() {} } struct Z : P { func p() {} } -// CHECK-LABEL: sil hidden [ossa] @$s10switch_var05test_B2_41pyAA1P_p_tF : $@convention(thin) (@in_guaranteed P) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s10switch_var05test_B2_41pyAA1P_p_tF : $@convention(thin) (@in_guaranteed any P) -> () { func test_var_4(p p: P) { // CHECK: function_ref @$s10switch_var3fooSiyF switch (p, foo()) { - // CHECK: [[PAIR:%.*]] = alloc_stack $(P, Int) + // CHECK: [[PAIR:%.*]] = alloc_stack $(any P, Int) // CHECK: store - // CHECK: [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(P, Int), 0 - // CHECK: [[T0:%.*]] = tuple_element_addr [[PAIR]] : $*(P, Int), 1 + // CHECK: [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(any P, Int), 0 + // CHECK: [[T0:%.*]] = tuple_element_addr [[PAIR]] : $*(any P, Int), 1 // CHECK: [[PAIR_1:%.*]] = load [trivial] [[T0]] : $*Int // CHECK: [[TMP:%.*]] = alloc_stack $X - // CHECK: checked_cast_addr_br copy_on_success P in [[PAIR_0]] : $*P to X in [[TMP]] : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[PAIR_0]] : $*any P to X in [[TMP]] : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]] // CHECK: [[IS_X]]: // CHECK: [[T0:%.*]] = load [trivial] [[TMP]] : $*X @@ -235,7 +235,7 @@ func test_var_4(p p: P) { // CHECK: end_borrow [[XLIFETIME]] // CHECK: destroy_value [[XADDR]] // CHECK: dealloc_stack [[TMP]] - // CHECK: destroy_addr [[PAIR_0]] : $*P + // CHECK: destroy_addr [[PAIR_0]] : $*any P // CHECK: dealloc_stack [[PAIR]] // CHECK: br [[CONT:bb[0-9]+]] a(x: x) @@ -250,7 +250,7 @@ func test_var_4(p p: P) { // CHECK: [[NEXT]]: // CHECK: [[TMP:%.*]] = alloc_stack $Y - // CHECK: checked_cast_addr_br copy_on_success P in [[PAIR_0]] : $*P to Y in [[TMP]] : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]] + // CHECK: checked_cast_addr_br copy_on_success any P in [[PAIR_0]] : $*any P to Y in [[TMP]] : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]] // CHECK: [[IS_Y]]: // CHECK: [[T0:%.*]] = load [trivial] [[TMP]] : $*Y @@ -271,7 +271,7 @@ func test_var_4(p p: P) { // CHECK: end_borrow [[YLIFETIME]] // CHECK: destroy_value [[YADDR]] // CHECK: dealloc_stack [[TMP]] - // CHECK: destroy_addr [[PAIR_0]] : $*P + // CHECK: destroy_addr [[PAIR_0]] : $*any P // CHECK: dealloc_stack [[PAIR]] // CHECK: br [[CONT]] b(x: y) @@ -286,7 +286,7 @@ func test_var_4(p p: P) { // CHECK: br [[NEXT]] // CHECK: [[NEXT]]: - // CHECK: [[ZADDR:%.*]] = alloc_box ${ var (P, Int) } + // CHECK: [[ZADDR:%.*]] = alloc_box ${ var (any P, Int) } // CHECK: [[ZLIFETIME:%.+]] = begin_borrow [lexical] [[ZADDR]] // CHECK: [[Z:%.*]] = project_box [[ZLIFETIME]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] @@ -310,7 +310,7 @@ func test_var_4(p p: P) { // CHECK-NEXT: destroy_value [[ZADDR]] // CHECK-NOT: destroy_addr case (_, var w): - // CHECK: [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(P, Int), 0 + // CHECK: [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(any P, Int), 0 // CHECK: [[WADDR:%.*]] = alloc_box ${ var Int } // CHECK: [[WLIFETIME:%.+]] = begin_borrow [lexical] [[WADDR]] // CHECK: [[W:%.*]] = project_box [[WLIFETIME]] @@ -319,7 +319,7 @@ func test_var_4(p p: P) { // CHECK: function_ref @$s10switch_var1d1xySi_tF // CHECK: end_borrow [[WLIFETIME]] // CHECK: destroy_value [[WADDR]] - // CHECK-NEXT: destroy_addr [[PAIR_0]] : $*P + // CHECK-NEXT: destroy_addr [[PAIR_0]] : $*any P // CHECK-NEXT: dealloc_stack [[PAIR]] // CHECK-NEXT: dealloc_stack // CHECK-NEXT: br [[CONT]] diff --git a/test/SILGen/synthesized_conformance_class.swift b/test/SILGen/synthesized_conformance_class.swift index 981404444a736..a19db139c7888 100644 --- a/test/SILGen/synthesized_conformance_class.swift +++ b/test/SILGen/synthesized_conformance_class.swift @@ -42,14 +42,14 @@ class Nonfinal { // CHECK: } // CHECK-LABEL: extension Final : Encodable where T : Encodable { -// CHECK: func encode(to encoder: Encoder) throws +// CHECK: func encode(to encoder: any Encoder) throws // CHECK: } // CHECK-LABEL: extension Final : Decodable where T : Decodable { -// CHECK: init(from decoder: Decoder) throws +// CHECK: init(from decoder: any Decoder) throws // CHECK: } // CHECK-LABEL: extension Nonfinal : Encodable where T : Encodable { -// CHECK: func encode(to encoder: Encoder) throws +// CHECK: func encode(to encoder: any Encoder) throws // CHECK: } // Make sure that CodingKeys members are actually emitted. @@ -64,15 +64,15 @@ class Nonfinal { extension Final: Encodable where T: Encodable {} // CHECK-LABEL: // Final.encode(to:) -// CHECK-NEXT: sil hidden [ossa] @$s29synthesized_conformance_class5FinalCAASERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed Encoder, @guaranteed Final) -> @error Error { +// CHECK-NEXT: sil hidden [ossa] @$s29synthesized_conformance_class5FinalCAASERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, @guaranteed Final) -> @error any Error { extension Final: Decodable where T: Decodable {} // CHECK-LABEL: // Final.init(from:) -// CHECK-NEXT: sil hidden [exact_self_class] [ossa] @$s29synthesized_conformance_class5FinalCAASeRzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in Decoder, @thick Final.Type) -> (@owned Final, @error Error) { +// CHECK-NEXT: sil hidden [exact_self_class] [ossa] @$s29synthesized_conformance_class5FinalCAASeRzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in any Decoder, @thick Final.Type) -> (@owned Final, @error any Error) { extension Nonfinal: Encodable where T: Encodable {} // CHECK-LABEL: // Nonfinal.encode(to:) -// CHECK-NEXT: sil hidden [ossa] @$s29synthesized_conformance_class8NonfinalCAASERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed Encoder, @guaranteed Nonfinal) -> @error Error { +// CHECK-NEXT: sil hidden [ossa] @$s29synthesized_conformance_class8NonfinalCAASERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, @guaranteed Nonfinal) -> @error any Error { final class FinalHashableClass : Hashable { static func ==(lhs: FinalHashableClass, rhs: FinalHashableClass) -> Bool { @@ -105,19 +105,19 @@ func doIt(_ c: FinalHashableClass) -> Int { // Witness tables for Final // CHECK-LABEL: sil_witness_table hidden Final: Encodable module synthesized_conformance_class { -// CHECK-NEXT: method #Encodable.encode: (Self) -> (Encoder) throws -> () : @$s29synthesized_conformance_class5FinalCyxGSEAASERzlSE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance Final +// CHECK-NEXT: method #Encodable.encode: (Self) -> (any Encoder) throws -> () : @$s29synthesized_conformance_class5FinalCyxGSEAASERzlSE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance Final // CHECK-NEXT: conditional_conformance (T: Encodable): dependent // CHECK-NEXT: } // CHECK-LABEL: sil_witness_table hidden Final: Decodable module synthesized_conformance_class { -// CHECK-NEXT: method #Decodable.init!allocator: (Self.Type) -> (Decoder) throws -> Self : @$s29synthesized_conformance_class5FinalCyxGSeAASeRzlSe4fromxs7Decoder_p_tKcfCTW // protocol witness for Decodable.init(from:) in conformance Final +// CHECK-NEXT: method #Decodable.init!allocator: (Self.Type) -> (any Decoder) throws -> Self : @$s29synthesized_conformance_class5FinalCyxGSeAASeRzlSe4fromxs7Decoder_p_tKcfCTW // protocol witness for Decodable.init(from:) in conformance Final // CHECK-NEXT: conditional_conformance (T: Decodable): dependent // CHECK-NEXT: } // Witness tables for Nonfinal // CHECK-LABEL: sil_witness_table hidden Nonfinal: Encodable module synthesized_conformance_class { -// CHECK-NEXT: method #Encodable.encode: (Self) -> (Encoder) throws -> () : @$s29synthesized_conformance_class8NonfinalCyxGSEAASERzlSE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance Nonfinal +// CHECK-NEXT: method #Encodable.encode: (Self) -> (any Encoder) throws -> () : @$s29synthesized_conformance_class8NonfinalCyxGSEAASERzlSE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance Nonfinal // CHECK-NEXT: conditional_conformance (T: Encodable): dependent // CHECK-NEXT: } diff --git a/test/SILGen/synthesized_conformance_enum.swift b/test/SILGen/synthesized_conformance_enum.swift index 1d8d21914c42c..f1bf4d753777f 100644 --- a/test/SILGen/synthesized_conformance_enum.swift +++ b/test/SILGen/synthesized_conformance_enum.swift @@ -49,10 +49,10 @@ extension Enum: Hashable where T: Hashable {} extension Enum: Codable where T: Codable {} // CHECK-LABEL: // Enum.encode(to:) -// CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASeRzSERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed Encoder, @in_guaranteed Enum) -> @error Error { +// CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASeRzSERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, @in_guaranteed Enum) -> @error any Error { // CHECK-LABEL: // Enum.init(from:) -// CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASeRzSERzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in Decoder, @thin Enum.Type) -> (@out Enum, @error Error) +// CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASeRzSERzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in any Decoder, @thin Enum.Type) -> (@out Enum, @error any Error) extension NoValues: CaseIterable {} // CHECK-LABEL: // static NoValues.allCases.getter @@ -60,10 +60,10 @@ extension NoValues: CaseIterable {} extension NoValues: Codable {} // CHECK-LABEL: // NoValues.encode(to:) -// CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum8NoValuesO6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed Encoder, NoValues) -> @error Error { +// CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum8NoValuesO6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, NoValues) -> @error any Error { // CHECK-LABEL: // NoValues.init(from:) -// CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum8NoValuesO4fromACs7Decoder_p_tKcfC : $@convention(method) (@in Decoder, @thin NoValues.Type) -> (NoValues, @error Error) +// CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum8NoValuesO4fromACs7Decoder_p_tKcfC : $@convention(method) (@in any Decoder, @thin NoValues.Type) -> (NoValues, @error any Error) // Witness tables for Enum @@ -81,13 +81,13 @@ extension NoValues: Codable {} // CHECK: } // CHECK-LABEL: sil_witness_table hidden Enum: Decodable module synthesized_conformance_enum { -// CHECK-NEXT: method #Decodable.init!allocator: (Self.Type) -> (Decoder) throws -> Self : @$s28synthesized_conformance_enum4EnumOyxGSeAASeRzSERzlSe4fromxs7Decoder_p_tKcfCTW // protocol witness for Decodable.init(from:) in conformance Enum +// CHECK-NEXT: method #Decodable.init!allocator: (Self.Type) -> (any Decoder) throws -> Self : @$s28synthesized_conformance_enum4EnumOyxGSeAASeRzSERzlSe4fromxs7Decoder_p_tKcfCTW // protocol witness for Decodable.init(from:) in conformance Enum // CHECK-NEXT: conditional_conformance (T: Decodable): dependent // CHECK-NEXT: conditional_conformance (T: Encodable): dependent // CHECK-NEXT: } // CHECK-LABEL: sil_witness_table hidden Enum: Encodable module synthesized_conformance_enum { -// CHECK-NEXT: method #Encodable.encode: (Self) -> (Encoder) throws -> () : @$s28synthesized_conformance_enum4EnumOyxGSEAASeRzSERzlSE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance Enum +// CHECK-NEXT: method #Encodable.encode: (Self) -> (any Encoder) throws -> () : @$s28synthesized_conformance_enum4EnumOyxGSEAASeRzSERzlSE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance Enum // CHECK-NEXT: conditional_conformance (T: Decodable): dependent // CHECK-NEXT: conditional_conformance (T: Encodable): dependent // CHECK-NEXT: } @@ -101,9 +101,9 @@ extension NoValues: Codable {} // CHECK-NEXT: } // CHECK-LABEL: sil_witness_table hidden NoValues: Decodable module synthesized_conformance_enum { -// CHECK-NEXT: method #Decodable.init!allocator: (Self.Type) -> (Decoder) throws -> Self : @$s28synthesized_conformance_enum8NoValuesOSeAASe4fromxs7Decoder_p_tKcfCTW // protocol witness for Decodable.init(from:) in conformance NoValues +// CHECK-NEXT: method #Decodable.init!allocator: (Self.Type) -> (any Decoder) throws -> Self : @$s28synthesized_conformance_enum8NoValuesOSeAASe4fromxs7Decoder_p_tKcfCTW // protocol witness for Decodable.init(from:) in conformance NoValues // CHECK-NEXT: } // CHECK-LABEL: sil_witness_table hidden NoValues: Encodable module synthesized_conformance_enum { -// CHECK-NEXT: method #Encodable.encode: (Self) -> (Encoder) throws -> () : @$s28synthesized_conformance_enum8NoValuesOSEAASE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance NoValues -// CHECK-NEXT: } \ No newline at end of file +// CHECK-NEXT: method #Encodable.encode: (Self) -> (any Encoder) throws -> () : @$s28synthesized_conformance_enum8NoValuesOSEAASE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance NoValues +// CHECK-NEXT: } diff --git a/test/SILGen/synthesized_conformance_struct.swift b/test/SILGen/synthesized_conformance_struct.swift index cd1213b76e02a..e5e58cfe31757 100644 --- a/test/SILGen/synthesized_conformance_struct.swift +++ b/test/SILGen/synthesized_conformance_struct.swift @@ -29,8 +29,8 @@ struct Struct { // CHECK: var hashValue: Int { get } // CHECK: } // CHECK-LABEL: extension Struct : Decodable & Encodable where T : Decodable, T : Encodable { -// CHECK: func encode(to encoder: Encoder) throws -// CHECK: init(from decoder: Decoder) throws +// CHECK: func encode(to encoder: any Encoder) throws +// CHECK: init(from decoder: any Decoder) throws // CHECK: } extension Struct: Equatable where T: Equatable {} @@ -48,10 +48,10 @@ extension Struct: Hashable where T: Hashable {} extension Struct: Codable where T: Codable {} // CHECK-LABEL: // Struct.encode(to:) -// CHECK-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASeRzSERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed Encoder, @in_guaranteed Struct) -> @error Error { +// CHECK-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASeRzSERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, @in_guaranteed Struct) -> @error any Error { // CHECK-LABEL: // Struct.init(from:) -// CHECK-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASeRzSERzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in Decoder, @thin Struct.Type) -> (@out Struct, @error Error) +// CHECK-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASeRzSERzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in any Decoder, @thin Struct.Type) -> (@out Struct, @error any Error) // Witness tables @@ -70,13 +70,13 @@ extension Struct: Codable where T: Codable {} // CHECK: } // CHECK-LABEL: sil_witness_table hidden Struct: Decodable module synthesized_conformance_struct { -// CHECK-NEXT: method #Decodable.init!allocator: (Self.Type) -> (Decoder) throws -> Self : @$s30synthesized_conformance_struct6StructVyxGSeAASeRzSERzlSe4fromxs7Decoder_p_tKcfCTW // protocol witness for Decodable.init(from:) in conformance Struct +// CHECK-NEXT: method #Decodable.init!allocator: (Self.Type) -> (any Decoder) throws -> Self : @$s30synthesized_conformance_struct6StructVyxGSeAASeRzSERzlSe4fromxs7Decoder_p_tKcfCTW // protocol witness for Decodable.init(from:) in conformance Struct // CHECK-NEXT: conditional_conformance (T: Decodable): dependent // CHECK-NEXT: conditional_conformance (T: Encodable): dependent // CHECK-NEXT: } // CHECK-LABEL: sil_witness_table hidden Struct: Encodable module synthesized_conformance_struct { -// CHECK-NEXT: method #Encodable.encode: (Self) -> (Encoder) throws -> () : @$s30synthesized_conformance_struct6StructVyxGSEAASeRzSERzlSE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance Struct +// CHECK-NEXT: method #Encodable.encode: (Self) -> (any Encoder) throws -> () : @$s30synthesized_conformance_struct6StructVyxGSEAASeRzSERzlSE6encode2toys7Encoder_p_tKFTW // protocol witness for Encodable.encode(to:) in conformance Struct // CHECK-NEXT: conditional_conformance (T: Decodable): dependent // CHECK-NEXT: conditional_conformance (T: Encodable): dependent // CHECK-NEXT: } diff --git a/test/SILGen/toplevel_errors.swift b/test/SILGen/toplevel_errors.swift index 624791e45f072..79e6cc85ff07c 100644 --- a/test/SILGen/toplevel_errors.swift +++ b/test/SILGen/toplevel_errors.swift @@ -9,19 +9,19 @@ throw MyError.A // CHECK: sil [ossa] @main // CHECK: [[T0:%.*]] = enum $MyError, #MyError.A!enumelt -// CHECK: [[ERR:%.*]] = alloc_existential_box $Error, $MyError -// CHECK: [[ADDR:%.*]] = project_existential_box $MyError in [[ERR]] : $Error +// CHECK: [[ERR:%.*]] = alloc_existential_box $any Error, $MyError +// CHECK: [[ADDR:%.*]] = project_existential_box $MyError in [[ERR]] : $any Error // CHECK: store [[ERR]] to [init] [[ERRBUF:%.*]] : // CHECK: store [[T0]] to [trivial] [[ADDR]] : $*MyError // CHECK: [[ERR2:%.*]] = load [take] [[ERRBUF]] -// CHECK: builtin "willThrow"([[ERR2]] : $Error) -// CHECK: br bb2([[ERR2]] : $Error) +// CHECK: builtin "willThrow"([[ERR2]] : $any Error) +// CHECK: br bb2([[ERR2]] : $any Error) // CHECK: bb1([[T0:%.*]] : $Int32): // CHECK: return [[T0]] : $Int32 -// CHECK: bb2([[T0:%.*]] : @owned $Error): -// CHECK: builtin "errorInMain"([[T0]] : $Error) +// CHECK: bb2([[T0:%.*]] : @owned $any Error): +// CHECK: builtin "errorInMain"([[T0]] : $any Error) // CHECK: end_lifetime [[T0]] // CHECK: [[T0:%.*]] = integer_literal $Builtin.Int32, 1 // CHECK: [[T1:%.*]] = struct $Int32 ([[T0]] : $Builtin.Int32) diff --git a/test/SILGen/tuples.swift b/test/SILGen/tuples.swift index b76b55293e8d1..5e46052162092 100644 --- a/test/SILGen/tuples.swift +++ b/test/SILGen/tuples.swift @@ -24,52 +24,52 @@ func make_xy() -> (x: Int, y: P) { return (make_int(), make_p()) } // CHECK-LABEL: sil hidden [ossa] @$s6tuples17testShuffleOpaqueyyF func testShuffleOpaque() { - // CHECK: [[X:%.*]] = alloc_box ${ var P } + // CHECK: [[X:%.*]] = alloc_box ${ var any P } // CHECK: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X]] // CHECK-NEXT: [[PBX:%.*]] = project_box [[X_LIFETIME]] // CHECK: [[Y:%.*]] = alloc_box ${ var Int } // CHECK: [[Y_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[Y]] // CHECK-NEXT: [[PBY:%.*]] = project_box [[Y_LIFETIME]] - // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $P + // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $any P // CHECK: [[T0:%.*]] = function_ref @$s6tuples7make_xySi1x_AA1P_p1ytyF // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[TMP]]) - // CHECK-NEXT: copy_addr [take] [[TMP]] to [initialization] [[PBX]] : $*P + // CHECK-NEXT: copy_addr [take] [[TMP]] to [initialization] [[PBX]] : $*any P // CHECK-NEXT: store [[T1]] to [trivial] [[PBY]] // CHECK-NEXT: dealloc_stack [[TMP]] var (x,y) : (y:P, x:Int) = make_xy() - // CHECK-NEXT: [[PAIR:%.*]] = alloc_box ${ var (y: P, x: Int) } + // CHECK-NEXT: [[PAIR:%.*]] = alloc_box ${ var (y: any P, x: Int) } // CHECK-NEXT: [[PAIR_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[PAIR]] // CHECK-NEXT: [[PBPAIR:%.*]] = project_box [[PAIR_LIFETIME]] - // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $P + // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $any P // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples7make_xySi1x_AA1P_p1ytyF // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[TMP]]) - // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: P, x: Int), 0 - // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: P, x: Int), 1 - // CHECK-NEXT: copy_addr [take] [[TMP]] to [initialization] [[PAIR_0]] : $*P + // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: any P, x: Int), 0 + // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: any P, x: Int), 1 + // CHECK-NEXT: copy_addr [take] [[TMP]] to [initialization] [[PAIR_0]] : $*any P // CHECK-NEXT: store [[T1]] to [trivial] [[PAIR_1]] // CHECK-NEXT: dealloc_stack [[TMP]] var pair : (y:P, x:Int) = make_xy() - // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $P + // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $any P // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples7make_xySi1x_AA1P_p1ytyF // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[TMP]]) - // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBPAIR]] : $*(y: P, x: Int) - // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 0 + // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBPAIR]] : $*(y: any P, x: Int) + // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[WRITE]] : $*(y: any P, x: Int), 0 // CHECK-NEXT: copy_addr [take] [[TMP]] to [[PAIR_0]] - // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 1 + // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[WRITE]] : $*(y: any P, x: Int), 1 // CHECK-NEXT: assign [[T1]] to [[PAIR_1]] - // CHECK-NEXT: end_access [[WRITE]] : $*(y: P, x: Int) + // CHECK-NEXT: end_access [[WRITE]] : $*(y: any P, x: Int) // CHECK-NEXT: dealloc_stack [[TMP]] pair = make_xy() } // CHECK-LABEL: testShuffleTuple func testShuffleTuple() { - // CHECK: [[X:%.*]] = alloc_box ${ var P } + // CHECK: [[X:%.*]] = alloc_box ${ var any P } // CHECK: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X]] // CHECK-NEXT: [[PBX:%.*]] = project_box [[X_LIFETIME]] // CHECK: [[Y:%.*]] = alloc_box ${ var Int } @@ -78,7 +78,7 @@ func testShuffleTuple() { // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples8make_intSiyF // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]() - // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $P + // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $any P // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples6make_pAA1P_pyF // CHECK-NEXT: apply [[T0]]([[TMP]]) @@ -87,18 +87,18 @@ func testShuffleTuple() { // CHECK-NEXT: dealloc_stack [[TMP]] var (x,y) : (y:P, x:Int) = (x: make_int(), y: make_p()) - // CHECK-NEXT: [[PAIR:%.*]] = alloc_box ${ var (y: P, x: Int) } + // CHECK-NEXT: [[PAIR:%.*]] = alloc_box ${ var (y: any P, x: Int) } // CHECK-NEXT: [[PAIR_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[PAIR]] // CHECK-NEXT: [[PBPAIR:%.*]] = project_box [[PAIR_LIFETIME]] // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples8make_intSiyF // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]() - // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $P + // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $any P // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples6make_pAA1P_pyF // CHECK-NEXT: apply [[T0]]([[TMP]]) - // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: P, x: Int), 0 - // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: P, x: Int), 1 + // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: any P, x: Int), 0 + // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: any P, x: Int), 1 // CHECK-NEXT: copy_addr [take] [[TMP]] to [initialization] [[PBX]] // CHECK-NEXT: store [[T1]] to [trivial] [[PAIR_1]] // CHECK-NEXT: dealloc_stack [[TMP]] @@ -107,16 +107,16 @@ func testShuffleTuple() { // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples8make_intSiyF // CHECK-NEXT: [[INT:%.*]] = apply [[T0]]() - // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P + // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $any P // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples6make_pAA1P_pyF // CHECK-NEXT: apply [[T0]]([[TEMP]]) - // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBPAIR]] : $*(y: P, x: Int) - // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 0 + // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBPAIR]] : $*(y: any P, x: Int) + // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[WRITE]] : $*(y: any P, x: Int), 0 // CHECK-NEXT: copy_addr [take] [[TEMP]] to [[PAIR_0]] - // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 1 + // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[WRITE]] : $*(y: any P, x: Int), 1 // CHECK-NEXT: assign [[INT]] to [[PAIR_1]] - // CHECK-NEXT: end_access [[WRITE]] : $*(y: P, x: Int) + // CHECK-NEXT: end_access [[WRITE]] : $*(y: any P, x: Int) // CHECK-NEXT: dealloc_stack [[TEMP]] pair = (x: make_int(), y: make_p()) } diff --git a/test/SILGen/value_ownership.swift b/test/SILGen/value_ownership.swift index 57f3faff47ac3..1cd1290a0264f 100644 --- a/test/SILGen/value_ownership.swift +++ b/test/SILGen/value_ownership.swift @@ -70,10 +70,10 @@ func useConsumingGetterGeneric(_ t: T) { blackHole(t.explicitPropertyGet) } -// CHECK-LABEL: sil hidden [ossa] @$s15value_ownership29useConsumingGetterExistentialyyAA14OwnershipProto_pF : $@convention(thin) (@in_guaranteed OwnershipProto) -> () { +// CHECK-LABEL: sil hidden [ossa] @$s15value_ownership29useConsumingGetterExistentialyyAA14OwnershipProto_pF : $@convention(thin) (@in_guaranteed any OwnershipProto) -> () { func useConsumingGetterExistential(_ e: OwnershipProto) { -// CHECK: [[FN:%.*]] = witness_method $@opened("{{.*}}", OwnershipProto) Self, #OwnershipProto.explicitPropertyGet!getter : (__owned Self) -> () -> String, %2 : $*@opened("{{.*}}", OwnershipProto) Self : $@convention(witness_method: OwnershipProto) <τ_0_0 where τ_0_0 : OwnershipProto> (@in τ_0_0) -> @owned String -// CHECK-NEXT: apply [[FN]]<@opened("{{.*}}", OwnershipProto) Self>({{%.*}}) : $@convention(witness_method: OwnershipProto) <τ_0_0 where τ_0_0 : OwnershipProto> (@in τ_0_0) -> @owned String +// CHECK: [[FN:%.*]] = witness_method $@opened("{{.*}}", any OwnershipProto) Self, #OwnershipProto.explicitPropertyGet!getter : (__owned Self) -> () -> String, %2 : $*@opened("{{.*}}", any OwnershipProto) Self : $@convention(witness_method: OwnershipProto) <τ_0_0 where τ_0_0 : OwnershipProto> (@in τ_0_0) -> @owned String +// CHECK-NEXT: apply [[FN]]<@opened("{{.*}}", any OwnershipProto) Self>({{%.*}}) : $@convention(witness_method: OwnershipProto) <τ_0_0 where τ_0_0 : OwnershipProto> (@in τ_0_0) -> @owned String blackHole(e.explicitPropertyGet) } diff --git a/test/SILGen/without_actually_escaping.swift b/test/SILGen/without_actually_escaping.swift index a6e278dfe4055..2d85243f30612 100644 --- a/test/SILGen/without_actually_escaping.swift +++ b/test/SILGen/without_actually_escaping.swift @@ -22,7 +22,7 @@ func letEscape(f: () -> ()) -> () -> () { // CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [without_actually_escaping] [ossa] @$sIg_Ieg_TR : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () { // CHECK-LABEL: sil hidden [ossa] @$s25without_actually_escaping14letEscapeThrow1fyycyycyKXE_tKF -// CHECK: bb0([[ARG:%.*]] : $@noescape @callee_guaranteed () -> (@owned @callee_guaranteed () -> (), @error Error)): +// CHECK: bb0([[ARG:%.*]] : $@noescape @callee_guaranteed () -> (@owned @callee_guaranteed () -> (), @error any Error)): // CHECK: [[CVT:%.*]] = function_ref @$sIeg_s5Error_pIgozo_Ieg_sAA_pIegozo_TR // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CVT]]([[ARG]]) // CHECK: [[MD:%.*]] = mark_dependence [[CLOSURE]] : {{.*}} on [[ARG]] @@ -37,10 +37,10 @@ func letEscape(f: () -> ()) -> () -> () { // CHECK: destroy_value [[MD]] // CHECK: return [[RES]] // -// CHECK: bb2([[ERR:%.*]] : @owned $Error): +// CHECK: bb2([[ERR:%.*]] : @owned $any Error): // CHECK: end_borrow [[BORROW]] // CHECK: destroy_value [[MD]] -// CHECK: throw [[ERR]] : $Error +// CHECK: throw [[ERR]] : $any Error // CHECK: } func letEscapeThrow(f: () throws -> () -> ()) throws -> () -> () { @@ -49,7 +49,7 @@ func letEscapeThrow(f: () throws -> () -> ()) throws -> () -> () { // thunk for @callee_guaranteed () -> (@owned @escaping @callee_guaranteed () -> (), @error @owned Error) // The thunk must be [without_actually_escaping]. -// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [without_actually_escaping] [ossa] @$sIeg_s5Error_pIgozo_Ieg_sAA_pIegozo_TR : $@convention(thin) (@noescape @callee_guaranteed () -> (@owned @callee_guaranteed () -> (), @error Error)) -> (@owned @callee_guaranteed () -> (), @error Error) { +// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [without_actually_escaping] [ossa] @$sIeg_s5Error_pIgozo_Ieg_sAA_pIegozo_TR : $@convention(thin) (@noescape @callee_guaranteed () -> (@owned @callee_guaranteed () -> (), @error any Error)) -> (@owned @callee_guaranteed () -> (), @error any Error) { // We used to crash on this example because we would use the wrong substitution // map. diff --git a/test/SILGen/witnesses.swift b/test/SILGen/witnesses.swift index ffb8808359e1a..950ffd849875d 100644 --- a/test/SILGen/witnesses.swift +++ b/test/SILGen/witnesses.swift @@ -44,16 +44,16 @@ protocol Existentiable { func protocol_method(x: Existentiable) -> Loadable { return x.foo() } -// CHECK-LABEL: sil hidden [ossa] @$s9witnesses15protocol_method1xAA8LoadableVAA13Existentiable_p_tF : $@convention(thin) (@in_guaranteed Existentiable) -> Loadable { -// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened\(.*, Existentiable\) Self]], #Existentiable.foo : +// CHECK-LABEL: sil hidden [ossa] @$s9witnesses15protocol_method1xAA8LoadableVAA13Existentiable_p_tF : $@convention(thin) (@in_guaranteed any Existentiable) -> Loadable { +// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened\(.*, any Existentiable\) Self]], #Existentiable.foo : // CHECK: apply [[METHOD]]<[[OPENED]]>({{%.*}}) // CHECK: } func protocol_generic_method(x: Existentiable) -> Loadable { return x.generic() } -// CHECK-LABEL: sil hidden [ossa] @$s9witnesses23protocol_generic_method1xAA8LoadableVAA13Existentiable_p_tF : $@convention(thin) (@in_guaranteed Existentiable) -> Loadable { -// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened\(.*, Existentiable\) Self]], #Existentiable.generic : +// CHECK-LABEL: sil hidden [ossa] @$s9witnesses23protocol_generic_method1xAA8LoadableVAA13Existentiable_p_tF : $@convention(thin) (@in_guaranteed any Existentiable) -> Loadable { +// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened\(.*, any Existentiable\) Self]], #Existentiable.generic : // CHECK: apply [[METHOD]]<[[OPENED]], Loadable>({{%.*}}, {{%.*}}) // CHECK: } @@ -61,8 +61,8 @@ func protocol_generic_method(x: Existentiable) -> Loadable { func foo() } -// CHECK-LABEL: sil hidden [ossa] @$s9witnesses20protocol_objc_method1xyAA8ObjCAble_p_tF : $@convention(thin) (@guaranteed ObjCAble) -> () -// CHECK: objc_method {{%.*}} : $@opened({{.*}}, ObjCAble) Self, #ObjCAble.foo!foreign +// CHECK-LABEL: sil hidden [ossa] @$s9witnesses20protocol_objc_method1xyAA8ObjCAble_p_tF : $@convention(thin) (@guaranteed any ObjCAble) -> () +// CHECK: objc_method {{%.*}} : $@opened({{.*}}, any ObjCAble) Self, #ObjCAble.foo!foreign func protocol_objc_method(x: ObjCAble) { x.foo() } @@ -122,10 +122,10 @@ struct ConformingStruct : X { mutating func addrOnly(x: AddrOnly) -> AddrOnly { return x } // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s9witnesses16ConformingStructVAA1XA2aDP8addrOnly{{[_0-9a-zA-Z]*}}FTW : - // CHECK: bb0(%0 : $*AddrOnly, %1 : $*AddrOnly, %2 : $*ConformingStruct): + // CHECK: bb0(%0 : $*any AddrOnly, %1 : $*any AddrOnly, %2 : $*ConformingStruct): // CHECK-NEXT: // function_ref - // CHECK-NEXT: %3 = function_ref @$s9witnesses16ConformingStructV8addrOnly{{[_0-9a-zA-Z]*}}F : $@convention(method) (@in_guaranteed AddrOnly, @inout ConformingStruct) -> @out AddrOnly - // CHECK-NEXT: %4 = apply %3(%0, %1, %2) : $@convention(method) (@in_guaranteed AddrOnly, @inout ConformingStruct) -> @out AddrOnly + // CHECK-NEXT: %3 = function_ref @$s9witnesses16ConformingStructV8addrOnly{{[_0-9a-zA-Z]*}}F : $@convention(method) (@in_guaranteed any AddrOnly, @inout ConformingStruct) -> @out any AddrOnly + // CHECK-NEXT: %4 = apply %3(%0, %1, %2) : $@convention(method) (@in_guaranteed any AddrOnly, @inout ConformingStruct) -> @out any AddrOnly // CHECK-NEXT: %5 = tuple () // CHECK-NEXT: return %5 : $() // CHECK-NEXT: } @@ -226,10 +226,10 @@ struct ConformsWithMoreGeneric : X, Y { mutating func addrOnly(x: G) -> G { return x } // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s9witnesses23ConformsWithMoreGenericVAA1XA2aDP8addrOnly{{[_0-9a-zA-Z]*}}FTW : - // CHECK: bb0(%0 : $*AddrOnly, %1 : $*AddrOnly, %2 : $*ConformsWithMoreGeneric): + // CHECK: bb0(%0 : $*any AddrOnly, %1 : $*any AddrOnly, %2 : $*ConformsWithMoreGeneric): // CHECK-NEXT: // function_ref // CHECK-NEXT: %3 = function_ref @$s9witnesses23ConformsWithMoreGenericV8addrOnly{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0 - // CHECK-NEXT: %4 = apply %3(%0, %1, %2) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0 + // CHECK-NEXT: %4 = apply %3(%0, %1, %2) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0 // CHECK-NEXT: [[RESULT:%.*]] = tuple () // CHECK-NEXT: return [[RESULT]] : $() // CHECK-NEXT: } diff --git a/test/SILGen/witnesses_class.swift b/test/SILGen/witnesses_class.swift index 75c141c0e8add..ae5b087244f9c 100644 --- a/test/SILGen/witnesses_class.swift +++ b/test/SILGen/witnesses_class.swift @@ -37,9 +37,9 @@ func gen(_ foo: T) { } // CHECK-LABEL: sil hidden [ossa] @$s15witnesses_class2exyyAA7Fooable_pF -// CHECK: bb0([[SELF:%[0-0]+]] : @guaranteed $Fooable): +// CHECK: bb0([[SELF:%[0-0]+]] : @guaranteed $any Fooable): // CHECK: [[SELF_PROJ:%.*]] = open_existential_ref [[SELF]] -// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened\(.*, Fooable\) Self]], +// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened\(.*, any Fooable\) Self]], // CHECK-NOT: copy_value [[SELF_PROJ]] : $ // CHECK: apply [[METHOD]]<[[OPENED]]>([[SELF_PROJ]]) // CHECK-NOT: destroy_value [[SELF]] diff --git a/test/SILGen/writeback.swift b/test/SILGen/writeback.swift index 6e103338fda9a..c01e2300c18ca 100644 --- a/test/SILGen/writeback.swift +++ b/test/SILGen/writeback.swift @@ -105,14 +105,14 @@ var addressOnly: Fungible { func funge(x x: inout Fungible) {} funge(x: &addressOnly) -// CHECK: [[TEMP:%.*]] = alloc_stack $Fungible -// CHECK: [[GET:%.*]] = function_ref @$s9writeback11addressOnlyAA8Fungible_pvg : $@convention(thin) () -> @out Fungible -// CHECK: apply [[GET]]([[TEMP]]) : $@convention(thin) () -> @out Fungible -// CHECK: [[FUNGE:%.*]] = function_ref @$s9writeback5funge1xyAA8Fungible_pz_tF : $@convention(thin) (@inout Fungible) -> () -// CHECK: apply [[FUNGE]]([[TEMP]]) : $@convention(thin) (@inout Fungible) -> () -// CHECK: [[SET:%.*]] = function_ref @$s9writeback11addressOnlyAA8Fungible_pvs : $@convention(thin) (@in Fungible) -> () -// CHECK: apply [[SET]]([[TEMP]]) : $@convention(thin) (@in Fungible) -> () -// CHECK: dealloc_stack [[TEMP]] : $*Fungible +// CHECK: [[TEMP:%.*]] = alloc_stack $any Fungible +// CHECK: [[GET:%.*]] = function_ref @$s9writeback11addressOnlyAA8Fungible_pvg : $@convention(thin) () -> @out any Fungible +// CHECK: apply [[GET]]([[TEMP]]) : $@convention(thin) () -> @out any Fungible +// CHECK: [[FUNGE:%.*]] = function_ref @$s9writeback5funge1xyAA8Fungible_pz_tF : $@convention(thin) (@inout any Fungible) -> () +// CHECK: apply [[FUNGE]]([[TEMP]]) : $@convention(thin) (@inout any Fungible) -> () +// CHECK: [[SET:%.*]] = function_ref @$s9writeback11addressOnlyAA8Fungible_pvs : $@convention(thin) (@in any Fungible) -> () +// CHECK: apply [[SET]]([[TEMP]]) : $@convention(thin) (@in any Fungible) -> () +// CHECK: dealloc_stack [[TEMP]] : $*any Fungible // Test that writeback occurs with generic properties. // @@ -138,7 +138,7 @@ func test_generic(runce runce: inout Runce, anse: Runce.Frob.An // We should *not* write back when referencing decls or members as rvalues. // -// CHECK-LABEL: sil hidden [ossa] @$s9writeback15loadAddressOnlyAA8Fungible_pyF : $@convention(thin) () -> @out Fungible { +// CHECK-LABEL: sil hidden [ossa] @$s9writeback15loadAddressOnlyAA8Fungible_pyF : $@convention(thin) () -> @out any Fungible { func loadAddressOnly() -> Fungible { // CHECK: function_ref writeback.addressOnly.getter // CHECK-NOT: function_ref writeback.addressOnly.setter diff --git a/test/SILOptimizer/access_enforcement_selection.swift b/test/SILOptimizer/access_enforcement_selection.swift index dbdecc51a83df..f40cd4728181a 100644 --- a/test/SILOptimizer/access_enforcement_selection.swift +++ b/test/SILOptimizer/access_enforcement_selection.swift @@ -109,8 +109,8 @@ public protocol Apply { func apply(_ body: (Apply) -> ()) } -// CHECK-LABEL: sil private @$s28access_enforcement_selection20testRecursiveClosure1a1xyAA5Apply_p_SiztF9localFuncL_1byAaE_p_tF : $@convention(thin) (@in_guaranteed Apply, @inout_aliasable Int) -> () { -// CHECK: bb0(%0 : $*Apply, %1 : $*Int): +// CHECK-LABEL: sil private @$s28access_enforcement_selection20testRecursiveClosure1a1xyAA5Apply_p_SiztF9localFuncL_1byAaE_p_tF : $@convention(thin) (@in_guaranteed any Apply, @inout_aliasable Int) -> () { +// CHECK: bb0(%0 : $*any Apply, %1 : $*Int): // CHECK: begin_access [modify] [dynamic] %1 : $*Int // CHECK-LABEL: } // end sil function '$s28access_enforcement_selection20testRecursiveClosure1a1xyAA5Apply_p_SiztF9localFuncL_1byAaE_p_tF' public func testRecursiveClosure(a: Apply, x: inout Int) { diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift index 89e6f43658a11..1b12d9c8f605c 100644 --- a/test/SILOptimizer/access_marker_verify.swift +++ b/test/SILOptimizer/access_marker_verify.swift @@ -268,8 +268,8 @@ func testInitLValue(p: HasIntGetter) -> Int { var x = p.x return x } -// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify14testInitLValue1pSiAA12HasIntGetter_p_tF : $@convention(thin) (@in_guaranteed HasIntGetter) -> Int { -// CHECK: bb0(%0 : $*HasIntGetter): +// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify14testInitLValue1pSiAA12HasIntGetter_p_tF : $@convention(thin) (@in_guaranteed any HasIntGetter) -> Int { +// CHECK: bb0(%0 : $*any HasIntGetter): // CHECK: alloc_box ${ var Int }, var, name "x" // CHECK: [[PROJ:%.*]] = project_box // CHECK: [[OPENED:%.*]] = open_existential_addr immutable_access %0 @@ -277,7 +277,7 @@ func testInitLValue(p: HasIntGetter) -> Int { // CHECK-NOT: begin_access // CHECK: copy_addr %{{.*}} to [initialization] [[X]] : $*@opened // CHECK: witness_method $@opened -// CHECK: apply %{{.*}}<@opened("{{.*}}", HasIntGetter) Self>([[X]]) : $@convention(witness_method: HasIntGetter) <τ_0_0 where τ_0_0 : HasIntGetter> (@in_guaranteed τ_0_0) -> Int +// CHECK: apply %{{.*}}<@opened("{{.*}}", any HasIntGetter) Self>([[X]]) : $@convention(witness_method: HasIntGetter) <τ_0_0 where τ_0_0 : HasIntGetter> (@in_guaranteed τ_0_0) -> Int // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[PROJ]] : $*Int // CHECK: store %{{.*}} to [trivial] [[ACCESS]] : $*Int // CHECK: end_access @@ -566,7 +566,7 @@ enum OptionalWithMap { } } } -// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify15OptionalWithMapO3mapyqd__Sgqd__xKXEKlF : $@convention(method) (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @error Error) for , @in_guaranteed OptionalWithMap) -> (@out Optional, @error Error) +// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify15OptionalWithMapO3mapyqd__Sgqd__xKXEKlF : $@convention(method) (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @error any Error) for , @in_guaranteed OptionalWithMap) -> (@out Optional, @error any Error) // CHECK: [[STK:%.]] = alloc_stack $OptionalWithMap // CHECK-NOT: begin_access // CHECK: copy_addr %2 to [initialization] [[STK]] : $*OptionalWithMap @@ -826,14 +826,14 @@ func testWriteback() { } // CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify13testWritebackyyF : $@convention(thin) () -> () { // CHECK: bb0: -// CHECK: %0 = alloc_stack $P +// CHECK: %0 = alloc_stack $any P // CHECK: [[GETTER:%.*]] = apply -// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] %0 : $*P +// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] %0 : $*any P // Call takesInoutP -// CHECK: apply %{{.*}}([[ACCESS]]) : $@convention(thin) (@inout P) -> () +// CHECK: apply %{{.*}}([[ACCESS]]) : $@convention(thin) (@inout any P) -> () // Call addressOnly.setter -// CHECK: apply %{{.*}}([[ACCESS]]) : $@convention(thin) (@in P) -> () -// CHECK: end_access [[ACCESS]] : $*P +// CHECK: apply %{{.*}}([[ACCESS]]) : $@convention(thin) (@in any P) -> () +// CHECK: end_access [[ACCESS]] : $*any P // CHECK-LABEL: } // end sil function '$s20access_marker_verify13testWritebackyyF' // --- writeback temp. @@ -869,15 +869,15 @@ protocol HasClassGetter { func testMixedTuple(p: HasClassGetter) -> (BaseClass, Any) { return (p.c, p.c) } -// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify14testMixedTuple1pAA9BaseClassC_yptAA03HasH6Getter_p_tF : $@convention(thin) (@in_guaranteed HasClassGetter) -> (@owned BaseClass, @out Any) { -// CHECK: bb0(%0 : $*Any, %1 : $*HasClassGetter): -// CHECK: [[P1:%.*]] = open_existential_addr immutable_access %1 : $*HasClassGetter to $*@opened +// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify14testMixedTuple1pAA9BaseClassC_yptAA03HasH6Getter_p_tF : $@convention(thin) (@in_guaranteed any HasClassGetter) -> (@owned BaseClass, @out Any) { +// CHECK: bb0(%0 : $*Any, %1 : $*any HasClassGetter): +// CHECK: [[P1:%.*]] = open_existential_addr immutable_access %1 : $*any HasClassGetter to $*@opened // CHECK: [[TEMP1:%.*]] = alloc_stack $@opened // CHECK-NOT: begin_access // CHECK: copy_addr [[P1]] to [initialization] [[TEMP1]] : $*@opened // CHECK-NOT: begin_access // CHECK: [[OUTC:%.*]] = apply {{.*}} $@convention(witness_method: HasClassGetter) <τ_0_0 where τ_0_0 : HasClassGetter> (@in_guaranteed τ_0_0) -> @owned BaseClass -// CHECK: [[P2:%.*]] = open_existential_addr immutable_access %1 : $*HasClassGetter to $*@opened +// CHECK: [[P2:%.*]] = open_existential_addr immutable_access %1 : $*any HasClassGetter to $*@opened // CHECK: [[TEMP2:%.*]] = alloc_stack $@opened // CHECK-NOT: begin_access // CHECK: copy_addr [[P2]] to [initialization] [[TEMP2]] : $*@opened @@ -904,14 +904,14 @@ internal struct CanCastStruct : CanCast { // CHECK: bb0(%0 : $*Optional, %1 : $*CanCastStruct): // CHECK: [[OUT_ENUM:%.*3]] = init_enum_data_addr %0 : $*Optional, #Optional.some!enumelt // CHECK: [[TEMP_SUB:%.*]] = alloc_stack $Optional> -// CHECK: [[TEMP_BASE:%.*]] = alloc_stack $CanCast -// CHECK: [[TEMP_BASE_ADR:%.*]] = init_existential_addr [[TEMP_BASE]] : $*CanCast, $CanCastStruct +// CHECK: [[TEMP_BASE:%.*]] = alloc_stack $any CanCast +// CHECK: [[TEMP_BASE_ADR:%.*]] = init_existential_addr [[TEMP_BASE]] : $*any CanCast, $CanCastStruct // CHECK-NOT: begin_access // CHECK: copy_addr %1 to [initialization] [[TEMP_BASE_ADR]] : $*CanCastStruct // CHECK-NOT: begin_access // CHECK: [[TEMP_SUB_ADR:%.*]] = init_enum_data_addr [[TEMP_SUB]] : $*Optional>, #Optional.some!enumelt // CHECK-NOT: begin_access -// CHECK: checked_cast_addr_br take_always CanCast in [[TEMP_BASE]] : $*CanCast to CanCastStruct in [[TEMP_SUB_ADR]] : $*CanCastStruct +// CHECK: checked_cast_addr_br take_always any CanCast in [[TEMP_BASE]] : $*any CanCast to CanCastStruct in [[TEMP_SUB_ADR]] : $*CanCastStruct // CHECK-NOT: begin_access // CHECK: [[TEMP_DATA:%.*]] = unchecked_take_enum_data_addr [[TEMP_SUB]] : $*Optional>, #Optional.some!enumelt // CHECK-NOT: begin_access @@ -930,34 +930,34 @@ func testOpenExistential(p: PBar) { q.bar() } } -// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify19testOpenExistential1pyAA4PBar_p_tF : $@convention(thin) (@in_guaranteed PBar) -> () { -// CHECK: bb0(%0 : $*PBar): -// CHECK: [[Q0:%.*]] = alloc_stack [lexical] $Optional, let, name "q0" -// CHECK: [[PBAR:%.*]] = alloc_stack $PBar +// CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify19testOpenExistential1pyAA4PBar_p_tF : $@convention(thin) (@in_guaranteed any PBar) -> () { +// CHECK: bb0(%0 : $*any PBar): +// CHECK: [[Q0:%.*]] = alloc_stack [lexical] $Optional, let, name "q0" +// CHECK: [[PBAR:%.*]] = alloc_stack $any PBar // CHECK-NOT: begin_access -// CHECK: copy_addr %0 to [initialization] [[PBAR]] : $*PBar +// CHECK: copy_addr %0 to [initialization] [[PBAR]] : $*any PBar // CHECK-NOT: begin_access -// CHECK: [[Q0_DATA:%.*]] = init_enum_data_addr [[Q0]] : $*Optional, #Optional.some!enumelt +// CHECK: [[Q0_DATA:%.*]] = init_enum_data_addr [[Q0]] : $*Optional, #Optional.some!enumelt // CHECK-NOT: begin_access -// CHECK: checked_cast_addr_br take_always PBar in [[PBAR]] : $*PBar to Q in [[Q0_DATA]] : $*Q, bb1, bb2 +// CHECK: checked_cast_addr_br take_always any PBar in [[PBAR]] : $*any PBar to any Q in [[Q0_DATA]] : $*any Q, bb1, bb2 // CHECK-NOT: begin_access -// CHECK: inject_enum_addr [[Q0]] : $*Optional, #Optional.some!enumelt +// CHECK: inject_enum_addr [[Q0]] : $*Optional, #Optional.some!enumelt // CHECK-NOT: begin_access -// CHECK: apply %{{.*}}([[Q0]], {{.*}}) : $@convention(method) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, _OptionalNilComparisonType, @thin Optional<τ_0_0>.Type) -> Bool -// CHECK: [[Q:%.*]] = alloc_stack [lexical] $Q, let, name "q" -// CHECK: [[OPT_Q:%.*]] = alloc_stack $Optional +// CHECK: apply %{{.*}}([[Q0]], {{.*}}) : $@convention(method) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, _OptionalNilComparisonType, @thin Optional<τ_0_0>.Type) -> Bool +// CHECK: [[Q:%.*]] = alloc_stack [lexical] $any Q, let, name "q" +// CHECK: [[OPT_Q:%.*]] = alloc_stack $Optional // CHECK-NOT: begin_access -// CHECK: copy_addr [[Q0]] to [initialization] [[OPT_Q]] : $*Optional +// CHECK: copy_addr [[Q0]] to [initialization] [[OPT_Q]] : $*Optional // CHECK-NOT: begin_access -// CHECK: switch_enum_addr [[OPT_Q]] : $*Optional, case #Optional.some!enumelt: bb +// CHECK: switch_enum_addr [[OPT_Q]] : $*Optional, case #Optional.some!enumelt: bb // CHECK-NOT: begin_access -// CHECK: [[OPT_Q_ADR:%.*]] = unchecked_take_enum_data_addr [[OPT_Q]] : $*Optional, #Optional.some!enumelt +// CHECK: [[OPT_Q_ADR:%.*]] = unchecked_take_enum_data_addr [[OPT_Q]] : $*Optional, #Optional.some!enumelt // CHECK-NOT: begin_access -// CHECK: copy_addr [take] [[OPT_Q_ADR]] to [initialization] [[Q]] : $*Q +// CHECK: copy_addr [take] [[OPT_Q_ADR]] to [initialization] [[Q]] : $*any Q // CHECK-NOT: begin_access -// CHECK: [[Q_ADR:%.*]] = open_existential_addr immutable_access [[Q]] : $*Q to $*@opened("{{.*}}", Q) Self -// CHECK: witness_method $@opened("{{.*}}", Q) Self, #PBar.bar -// CHECK: apply %{{.*}}<@opened("{{.*}}", Q) Self>([[Q_ADR]]) +// CHECK: [[Q_ADR:%.*]] = open_existential_addr immutable_access [[Q]] : $*any Q to $*@opened("{{.*}}", any Q) Self +// CHECK: witness_method $@opened("{{.*}}", any Q) Self, #PBar.bar +// CHECK: apply %{{.*}}<@opened("{{.*}}", any Q) Self>([[Q_ADR]]) // CHECK-LABEL: } // end sil function '$s20access_marker_verify19testOpenExistential1pyAA4PBar_p_tF' // --- local existential @@ -972,18 +972,18 @@ func testLocalExistential() { _ = p } // CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify20testLocalExistentialyyF : $@convention(thin) () -> () { -// CHECK: alloc_box ${ var P }, var, name "p" -// CHECK: [[PROJ:%.*]] = project_box %{{.*}} : ${ var P }, 0 +// CHECK: alloc_box ${ var any P }, var, name "p" +// CHECK: [[PROJ:%.*]] = project_box %{{.*}} : ${ var any P }, 0 // CHECK-NOT: begin_access -// CHECK: apply %{{.*}}([[PROJ]]) : $@convention(thin) () -> @out P +// CHECK: apply %{{.*}}([[PROJ]]) : $@convention(thin) () -> @out any P // CHECK-NOT: begin_access -// CHECK: partial_apply [callee_guaranteed] %{{.*}}([[PROJ]]) : $@convention(thin) (@inout_aliasable P) -> () +// CHECK: partial_apply [callee_guaranteed] %{{.*}}([[PROJ]]) : $@convention(thin) (@inout_aliasable any P) -> () // CHECK-NOT: begin_access // CHECK: apply -// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJ]] : $*P -// CHECK: [[COPY:%.*]] = alloc_stack $P +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJ]] : $*any P +// CHECK: [[COPY:%.*]] = alloc_stack $any P // CHECK-NOT: begin_access -// CHECK: copy_addr [[ACCESS]] to [initialization] [[COPY]] : $*P +// CHECK: copy_addr [[ACCESS]] to [initialization] [[COPY]] : $*any P // CHECK: end_access // CHECK-NOT: begin_access // CHECK-LABEL: } // end sil function '$s20access_marker_verify20testLocalExistentialyyF' @@ -1047,9 +1047,9 @@ class testInitExistentialGlobal { } // CHECK-LABEL: sil private [global_init_once_fn] [ossa] @{{.*}}WZ : $@convention(c) (Builtin.RawPointer) -> () { // CHECK: alloc_global @$s20access_marker_verify25testInitExistentialGlobalC0D8PropertyAA1P_pvpZ -// CHECK: [[GADR:%.*]] = global_addr @$s20access_marker_verify25testInitExistentialGlobalC0D8PropertyAA1P_pvpZ : $*P +// CHECK: [[GADR:%.*]] = global_addr @$s20access_marker_verify25testInitExistentialGlobalC0D8PropertyAA1P_pvpZ : $*any P // CHECK: %{{.*}} = apply %{{.*}}({{.*}}) : $@convention(method) (@thin StructP.Type) -> StructP -// CHECK: [[EADR:%.*]] = init_existential_addr [[GADR]] : $*P, $StructP +// CHECK: [[EADR:%.*]] = init_existential_addr [[GADR]] : $*any P, $StructP // CHECK: store %{{.*}} to [trivial] [[EADR]] : $*StructP // CHECK-LABEL: } // end sil function '{{.*}}WZ @@ -1061,13 +1061,13 @@ public enum SomeError: Swift.Error { public func testInitBox() throws { throw SomeError.error } -// CHECK-LABEL: sil [ossa] @$s20access_marker_verify11testInitBoxyyKF : $@convention(thin) () -> @error Error { -// CHECK: [[BOXALLOC:%.*]] = alloc_existential_box $Error, $SomeError -// CHECK: [[PROJ:%.*]] = project_existential_box $SomeError in [[BOXALLOC]] : $Error +// CHECK-LABEL: sil [ossa] @$s20access_marker_verify11testInitBoxyyKF : $@convention(thin) () -> @error any Error { +// CHECK: [[BOXALLOC:%.*]] = alloc_existential_box $any Error, $SomeError +// CHECK: [[PROJ:%.*]] = project_existential_box $SomeError in [[BOXALLOC]] : $any Error // CHECK: store [[BOXALLOC]] to [init] [[BOXBUF:%.*]] : // CHECK: store %{{.*}} to [trivial] [[PROJ]] : $*SomeError // CHECK: [[BOXALLOC2:%.*]] = load [take] [[BOXBUF]] -// CHECK: throw [[BOXALLOC2]] : $Error +// CHECK: throw [[BOXALLOC2]] : $any Error // CHECK-LABEL: } // end sil function '$s20access_marker_verify11testInitBoxyyKF' public final class HasStaticProp { diff --git a/test/SILOptimizer/address_lowering.sil b/test/SILOptimizer/address_lowering.sil index ccf645055c759..395922826aa6b 100644 --- a/test/SILOptimizer/address_lowering.sil +++ b/test/SILOptimizer/address_lowering.sil @@ -256,17 +256,17 @@ bb0(%0 : @owned $T): // FIXME: Optimize transfers from indirect function args to indirect call args. // Verify that a subsequent pass remove the temp allocation. // -// CHECK-LABEL: sil [ossa] @f043_indirectGuaranteedArg : $@convention(thin) (@in C) -> () { -// CHECK: bb0(%0 : $*C): -// CHECK: [[LD:%.*]] = load [take] %0 : $*C -// CHECK: [[TMP:%.*]] = alloc_stack $C -// CHECK: [[B:%.*]] = begin_borrow [[LD]] : $C -// CHECK: [[SB:%.*]] = store_borrow [[B]] to [[TMP]] : $*C -// CHECK: apply %{{.*}}([[SB]]) : $@convention(thin) (@in_guaranteed C) -> () -// CHECK: end_borrow [[SB]] : $*C -// CHECK: end_borrow [[B]] : $C -// CHECK: dealloc_stack [[TMP]] : $*C -// CHECK: destroy_value [[LD]] : $C +// CHECK-LABEL: sil [ossa] @f043_indirectGuaranteedArg : $@convention(thin) (@in any C) -> () { +// CHECK: bb0(%0 : $*any C): +// CHECK: [[LD:%.*]] = load [take] %0 : $*any C +// CHECK: [[TMP:%.*]] = alloc_stack $any C +// CHECK: [[B:%.*]] = begin_borrow [[LD]] : $any C +// CHECK: [[SB:%.*]] = store_borrow [[B]] to [[TMP]] : $*any C +// CHECK: apply %{{.*}}([[SB]]) : $@convention(thin) (@in_guaranteed any C) -> () +// CHECK: end_borrow [[SB]] : $*any C +// CHECK: end_borrow [[B]] : $any C +// CHECK: dealloc_stack [[TMP]] : $*any C +// CHECK: destroy_value [[LD]] : $any C // CHECK-LABEL: } // end sil function 'f043_indirectGuaranteedArg' sil [ossa] @f043_indirectGuaranteedArg : $@convention(thin) (@in C) -> () { bb0(%0 : @owned $C): @@ -392,10 +392,10 @@ bb0(%0 : @owned $T): return %10 : $() } -// CHECK-LABEL: sil [ossa] @f070_mixedResult1 : $@convention(thin) (@in T, @owned C) -> (@out T, @owned C) { -// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $C): +// CHECK-LABEL: sil [ossa] @f070_mixedResult1 : $@convention(thin) (@in T, @owned any C) -> (@out T, @owned any C) { +// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $any C): // CHECK: copy_addr [take] %1 to [initialization] %0 : $*T -// CHECK: return %2 : $C +// CHECK: return %2 : $any C // CHECK-LABEL: } // end sil function 'f070_mixedResult1' sil [ossa] @f070_mixedResult1 : $@convention(thin) (@in T, @owned C) -> (@out T, @owned C) { bb0(%0 : @owned $T, %1 : @owned $C): @@ -403,13 +403,13 @@ bb0(%0 : @owned $T, %1 : @owned $C): return %4 : $(T, C) } -// CHECK-LABEL: sil [ossa] @f071_mixedResult2 : $@convention(thin) (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) { -// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : @owned $C): +// CHECK-LABEL: sil [ossa] @f071_mixedResult2 : $@convention(thin) (@in T, @owned any C) -> (@out T, @out T, @owned any C, @owned any C) { +// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : @owned $any C): // CHECK: copy_addr %2 to [initialization] %0 : $*T -// CHECK: [[C:%.*]] = copy_value %3 : $C +// CHECK: [[C:%.*]] = copy_value %3 : $any C // CHECK: copy_addr [take] %2 to [initialization] %1 : $*T -// CHECK: [[T:%.*]] = tuple ([[C]] : $C, %3 : $C) -// CHECK: return [[T]] : $(C, C) +// CHECK: [[T:%.*]] = tuple ([[C]] : $any C, %3 : $any C) +// CHECK: return [[T]] : $(any C, any C) // CHECK-LABEL: } // end sil function 'f071_mixedResult2' sil [ossa] @f071_mixedResult2 : $@convention(thin) (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) { bb0(%0 : @owned $T, %1 : @owned $C): @@ -419,18 +419,18 @@ bb0(%0 : @owned $T, %1 : @owned $C): return %6 : $(T, T, C, C) } -// CHECK-LABEL: sil [ossa] @f072_callMixedResult1 : $@convention(thin) (@in T, @owned C) -> (@out T, @owned C) { -// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $C): +// CHECK-LABEL: sil [ossa] @f072_callMixedResult1 : $@convention(thin) (@in T, @owned any C) -> (@out T, @owned any C) { +// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $any C): // CHECK: [[IN:%.*]] = alloc_stack $T // CHECK: // function_ref f070_mixedResult1 -// CHECK: [[F:%.*]] = function_ref @f070_mixedResult1 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C) +// CHECK: [[F:%.*]] = function_ref @f070_mixedResult1 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned any C) -> (@out τ_0_0, @owned any C) // CHECK: copy_addr %1 to [initialization] [[IN]] : $*T -// CHECK: [[C:%.*]] = copy_value %2 : $C -// CHECK: [[R:%.*]] = apply [[F]](%0, [[IN]], [[C]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C) -// CHECK: destroy_value %2 : $C +// CHECK: [[C:%.*]] = copy_value %2 : $any C +// CHECK: [[R:%.*]] = apply [[F]](%0, [[IN]], [[C]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned any C) -> (@out τ_0_0, @owned any C) +// CHECK: destroy_value %2 : $any C // CHECK: destroy_addr %1 : $*T // CHECK: dealloc_stack [[IN]] : $*T -// CHECK: return [[R]] : $C +// CHECK: return [[R]] : $any C // CHECK-LABEL: } // end sil function 'f072_callMixedResult1' sil [ossa] @f072_callMixedResult1 : $@convention(thin) (@in T, @owned C) -> (@out T, @owned C) { bb0(%0 : @owned $T, %1 : @owned $C): @@ -445,19 +445,19 @@ bb0(%0 : @owned $T, %1 : @owned $C): return %15 : $(T, C) } -// CHECK-LABEL: sil [ossa] @f073_callMixedResult2 : $@convention(thin) (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) { -// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : @owned $C): +// CHECK-LABEL: sil [ossa] @f073_callMixedResult2 : $@convention(thin) (@in T, @owned any C) -> (@out T, @out T, @owned any C, @owned any C) { +// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : @owned $any C): // CHECK: [[IN:%.*]] = alloc_stack $T -// CHECK: [[F:%.*]] = function_ref @f071_mixedResult2 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C) +// CHECK: [[F:%.*]] = function_ref @f071_mixedResult2 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned any C) -> (@out τ_0_0, @out τ_0_0, @owned any C, @owned any C) // CHECK: copy_addr %2 to [initialization] [[IN]] : $*T -// CHECK: [[C:%.*]] = copy_value %3 : $C -// CHECK: [[T:%.*]] = apply [[F]](%0, %1, [[IN]], [[C]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C) -// CHECK: ([[OUT0:%.*]], [[OUT1:%.*]]) = destructure_tuple [[T]] : $(C, C) -// CHECK: destroy_value %3 : $C +// CHECK: [[C:%.*]] = copy_value %3 : $any C +// CHECK: [[T:%.*]] = apply [[F]](%0, %1, [[IN]], [[C]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned any C) -> (@out τ_0_0, @out τ_0_0, @owned any C, @owned any C) +// CHECK: ([[OUT0:%.*]], [[OUT1:%.*]]) = destructure_tuple [[T]] : $(any C, any C) +// CHECK: destroy_value %3 : $any C // CHECK: destroy_addr %2 : $*T -// CHECK: [[R:%.*]] = tuple ([[OUT0]] : $C, [[OUT1]] : $C) +// CHECK: [[R:%.*]] = tuple ([[OUT0]] : $any C, [[OUT1]] : $any C) // CHECK: dealloc_stack [[IN]] : $*T -// CHECK: return [[R]] : $(C, C) +// CHECK: return [[R]] : $(any C, any C) // CHECK-LABEL: } // end sil function 'f073_callMixedResult2' sil [ossa] @f073_callMixedResult2 : $@convention(thin) (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) { bb0(%0 : @owned $T, %1 : @owned $C): @@ -479,14 +479,14 @@ sil [ossa] @returnMixedResult3 : $@convention(thin) () -> (@out T, @out C, @ // // FIXME: verify that a subsequent pass remove the temp allocation. // -// CHECK-LABEL: sil [ossa] @f074_callMixedResult3 : $@convention(thin) () -> (@out T, @out C, @owned C) { -// CHECK: bb0(%0 : $*T, %1 : $*C): -// CHECK: [[OUT1:%.*]] = alloc_stack $C -// CHECK: [[OUT2:%.*]] = apply %{{.*}}(%0, [[OUT1]]) : $@convention(thin) <τ_0_0> () -> (@out τ_0_0, @out C, @owned C) -// CHECK: [[LD:%.*]] = load [take] [[OUT1]] : $*C -// CHECK: dealloc_stack [[OUT1]] : $*C -// CHECK: store [[LD]] to [init] %1 : $*C -// CHECK: return [[OUT2]] : $C +// CHECK-LABEL: sil [ossa] @f074_callMixedResult3 : $@convention(thin) () -> (@out T, @out any C, @owned any C) { +// CHECK: bb0(%0 : $*T, %1 : $*any C): +// CHECK: [[OUT1:%.*]] = alloc_stack $any C +// CHECK: [[OUT2:%.*]] = apply %{{.*}}(%0, [[OUT1]]) : $@convention(thin) <τ_0_0> () -> (@out τ_0_0, @out any C, @owned any C) +// CHECK: [[LD:%.*]] = load [take] [[OUT1]] : $*any C +// CHECK: dealloc_stack [[OUT1]] : $*any C +// CHECK: store [[LD]] to [init] %1 : $*any C +// CHECK: return [[OUT2]] : $any C // CHECK-LABEL: } // end sil function 'f074_callMixedResult3' sil [ossa] @f074_callMixedResult3 : $@convention(thin) () -> (@out T, @out C, @owned C) { bb0: @@ -497,20 +497,20 @@ bb0: return %5 : $(T, C, C) } -// CHECK-LABEL: sil [ossa] @f075_reusedResult : $@convention(thin) (@in T, @owned C) -> (@out T, @owned C) { -// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $C): -// CHECK: [[TUPLE:%.*]] = alloc_stack $(T, C) -// CHECK: [[E1:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, C), 0 +// CHECK-LABEL: sil [ossa] @f075_reusedResult : $@convention(thin) (@in T, @owned any C) -> (@out T, @owned any C) { +// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $any C): +// CHECK: [[TUPLE:%.*]] = alloc_stack $(T, any C) +// CHECK: [[E1:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, any C), 0 // CHECK: copy_addr [take] %1 to [initialization] [[E1]] : $*T -// CHECK: [[E2:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, C), 1 -// CHECK: store %2 to [init] [[E2]] : $*C -// CHECK: apply %{{.*}}([[TUPLE]]) : $@convention(thin) <τ_0_0> (@in_guaranteed (τ_0_0, C)) -> () -// CHECK: [[E1:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, C), 0 -// CHECK: [[E2:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, C), 1 -// CHECK: [[LD:%.*]] = load [take] [[E2]] : $*C +// CHECK: [[E2:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, any C), 1 +// CHECK: store %2 to [init] [[E2]] : $*any C +// CHECK: apply %{{.*}}([[TUPLE]]) : $@convention(thin) <τ_0_0> (@in_guaranteed (τ_0_0, any C)) -> () +// CHECK: [[E1:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, any C), 0 +// CHECK: [[E2:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, any C), 1 +// CHECK: [[LD:%.*]] = load [take] [[E2]] : $*any C // CHECK: copy_addr [take] [[E1]] to [initialization] %0 : $*T -// CHECK: dealloc_stack [[TUPLE]] : $*(T, C) -// CHECK: return [[LD]] : $C +// CHECK: dealloc_stack [[TUPLE]] : $*(T, any C) +// CHECK: return [[LD]] : $any C // CHECK-LABEL: } // end sil function 'f075_reusedResult' sil [ossa] @f075_reusedResult : $@convention(thin) (@in T, @owned C) -> (@out T, @owned C) { bb0(%0 : @owned $T, %1 : @owned $C): @@ -897,21 +897,21 @@ bb0(%0 : @owned $T): return %r : $() } -// CHECK-LABEL: sil [ossa] @f160_testOpenedArchetype : $@convention(thin) (@in P) -> () { -// CHECK: bb0(%0 : $*P): -// CHECK: [[ALLOC:%.*]] = alloc_stack $P, var, name "q" -// CHECK: copy_addr %0 to [initialization] [[ALLOC]] : $*P -// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*P to $*[[ARCHETYPE:@opened\(.*, P\) Self]] +// CHECK-LABEL: sil [ossa] @f160_testOpenedArchetype : $@convention(thin) (@in any P) -> () { +// CHECK: bb0(%0 : $*any P): +// CHECK: [[ALLOC:%.*]] = alloc_stack $any P, var, name "q" +// CHECK: copy_addr %0 to [initialization] [[ALLOC]] : $*any P +// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*[[ARCHETYPE:@opened\(.*, any P\) Self]] // CHECK: [[CP:%.*]] = alloc_stack $[[ARCHETYPE]] // type-defs: [[OPEN]]; // CHECK: [[WT:%.*]] = witness_method $[[ARCHETYPE]], #P.foo : (Self) -> () -> (), [[OPEN]] : $*[[ARCHETYPE]] : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // CHECK: copy_addr [[OPEN]] to [initialization] [[CP]] : $*[[ARCHETYPE]] // CHECK: %{{.*}} = apply [[WT]]<[[ARCHETYPE]]>([[CP]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // CHECK: destroy_addr [[CP]] : $*[[ARCHETYPE]] -// CHECK: destroy_addr [[ALLOC]] : $*P -// CHECK: destroy_addr %0 : $*P +// CHECK: destroy_addr [[ALLOC]] : $*any P +// CHECK: destroy_addr %0 : $*any P // CHECK: %{{.*}} = tuple () // CHECK: dealloc_stack [[CP]] : $*[[ARCHETYPE]] -// CHECK: dealloc_stack [[ALLOC]] : $*P +// CHECK: dealloc_stack [[ALLOC]] : $*any P // CHECK: return %{{.*}} : $() // CHECK-LABEL: } // end sil function 'f160_testOpenedArchetype' sil [ossa] @f160_testOpenedArchetype : $@convention(thin) (@in P) -> () { @@ -934,23 +934,23 @@ bb0(%0 : @owned $P): return %16 : $() } -// CHECK-LABEL: sil [ossa] @f161_testOpenedArchetype : $@convention(thin) (@in P) -> () { -// CHECK: bb0(%0 : $*P): -// CHECK: [[ALLOCP:%.*]] = alloc_stack $P, var, name "q" -// CHECK: copy_addr %0 to [initialization] [[ALLOCP]] : $*P -// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*P to $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self -// CHECK: [[OPTIONAL:%.*]] = alloc_stack $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self> -// CHECK: witness_method $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self, #P.foo : (Self) -> () -> (), [[OPEN]] : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () -// CHECK: [[INIT:%.*]] = init_enum_data_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>, #Optional.some!enumelt -// CHECK: copy_addr [[OPEN]] to [initialization] [[INIT]] : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self -// CHECK: inject_enum_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>, #Optional.some!enumelt -// CHECK: [[DATA:%.*]] = unchecked_take_enum_data_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>, #Optional.some!enumelt -// CHECK: %10 = apply %{{.*}}<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>([[DATA]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () -// CHECK: destroy_addr %9 : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self -// CHECK: destroy_addr [[ALLOCP]] : $*P -// CHECK: destroy_addr %0 : $*P -// CHECK: dealloc_stack [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self> -// CHECK: dealloc_stack [[ALLOCP]] : $*P +// CHECK-LABEL: sil [ossa] @f161_testOpenedArchetype : $@convention(thin) (@in any P) -> () { +// CHECK: bb0(%0 : $*any P): +// CHECK: [[ALLOCP:%.*]] = alloc_stack $any P, var, name "q" +// CHECK: copy_addr %0 to [initialization] [[ALLOCP]] : $*any P +// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self +// CHECK: [[OPTIONAL:%.*]] = alloc_stack $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self> +// CHECK: witness_method $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self, #P.foo : (Self) -> () -> (), [[OPEN]] : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () +// CHECK: [[INIT:%.*]] = init_enum_data_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>, #Optional.some!enumelt +// CHECK: copy_addr [[OPEN]] to [initialization] [[INIT]] : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self +// CHECK: inject_enum_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>, #Optional.some!enumelt +// CHECK: [[DATA:%.*]] = unchecked_take_enum_data_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>, #Optional.some!enumelt +// CHECK: %10 = apply %{{.*}}<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>([[DATA]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () +// CHECK: destroy_addr %9 : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self +// CHECK: destroy_addr [[ALLOCP]] : $*any P +// CHECK: destroy_addr %0 : $*any P +// CHECK: dealloc_stack [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self> +// CHECK: dealloc_stack [[ALLOCP]] : $*any P // CHECK-LABEL: } // end sil function 'f161_testOpenedArchetype' sil [ossa] @f161_testOpenedArchetype : $@convention(thin) (@in P) -> () { bb0(%0 : @owned $P): @@ -975,9 +975,9 @@ bb0(%0 : @owned $P): } // CHECK-LABEL: sil [ossa] @f162_testOpenedArchetype : -// CHECK: [[STK:%.*]] = alloc_stack $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self> +// CHECK: [[STK:%.*]] = alloc_stack $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self> // CHECK: bb6: -// CHECK: dealloc_stack [[STK]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self> +// CHECK: dealloc_stack [[STK]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self> // CHECK: br bb7 // CHECK-LABEL: } // end sil function 'f162_testOpenedArchetype' sil [ossa] @f162_testOpenedArchetype : $@convention(thin) (@in P) -> () { @@ -1126,12 +1126,12 @@ bb4: return %31 : $() } -// CHECK-LABEL: sil [ossa] @f230_testTryApply : $@convention(thin) (@in T) -> (@out T, @error Error) { +// CHECK-LABEL: sil [ossa] @f230_testTryApply : $@convention(thin) (@in T) -> (@out T, @error any Error) { // CHECK: bb0(%0 : $*T, %1 : $*T): -// CHECK: [[F:%.*]] = function_ref @throwsError : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error) -// CHECK: try_apply [[F]](%0, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal bb2, error bb1 -// CHECK: bb1([[E:%.*]] : $Error): -// CHECK: throw [[E]] : $Error +// CHECK: [[F:%.*]] = function_ref @throwsError : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error any Error) +// CHECK: try_apply [[F]](%0, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error any Error), normal bb2, error bb1 +// CHECK: bb1([[E:%.*]] : $any Error): +// CHECK: throw [[E]] : $any Error // CHECK: bb2([[NONE:%.*]] : $()): // CHECK: %{{.*}} = tuple () // CHECK: return %{{.*}} : $() @@ -1148,12 +1148,12 @@ bb2(%7 : $Error): throw %7 : $Error } -// CHECK-LABEL: sil [ossa] @f240_testTryApplyDirect : $@convention(thin) (@in T) -> (Builtin.Int64, @error Error) { +// CHECK-LABEL: sil [ossa] @f240_testTryApplyDirect : $@convention(thin) (@in T) -> (Builtin.Int64, @error any Error) { // CHECK: bb0(%0 : $*T): -// CHECK: [[F:%.*]] = function_ref @returnInt : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (Builtin.Int64, @error Error) -// CHECK: try_apply [[F]](%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (Builtin.Int64, @error Error), normal bb2, error bb1 -// CHECK: bb1([[E:%.*]] : $Error): -// CHECK: throw [[E]] : $Error +// CHECK: [[F:%.*]] = function_ref @returnInt : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (Builtin.Int64, @error any Error) +// CHECK: try_apply [[F]](%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (Builtin.Int64, @error any Error), normal bb2, error bb1 +// CHECK: bb1([[E:%.*]] : $any Error): +// CHECK: throw [[E]] : $any Error // CHECK: bb2([[V:%.*]] : $Builtin.Int64): // CHECK: return [[V]] : $Builtin.Int64 // CHECK-LABEL: } // end sil function 'f240_testTryApplyDirect' @@ -1169,14 +1169,14 @@ bb2(%7 : $Error): throw %7 : $Error } -// CHECK-LABEL: sil [ossa] @f250_testTryApplyIndirect : $@convention(thin) (@in T) -> (Builtin.Int64, @error Error) { +// CHECK-LABEL: sil [ossa] @f250_testTryApplyIndirect : $@convention(thin) (@in T) -> (Builtin.Int64, @error any Error) { // CHECK: bb0(%0 : $*T): -// CHECK: [[F:%.*]] = function_ref @returnIntOut : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out Builtin.Int64, @error Error) +// CHECK: [[F:%.*]] = function_ref @returnIntOut : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out Builtin.Int64, @error any Error) // CHECK: [[OUT_I:%.*]] = alloc_stack $Builtin.Int64 -// CHECK: try_apply %1([[OUT_I]], %0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out Builtin.Int64, @error Error), normal bb2, error bb1 -// CHECK: bb1([[E:%.*]] : $Error): +// CHECK: try_apply %1([[OUT_I]], %0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out Builtin.Int64, @error any Error), normal bb2, error bb1 +// CHECK: bb1([[E:%.*]] : $any Error): // CHECK: dealloc_stack [[OUT_I]] : $*Builtin.Int64 -// CHECK: throw [[E]] : $Error +// CHECK: throw [[E]] : $any Error // CHECK: bb2(%{{.*}} : $()): // CHECK: [[V:%.*]] = load [trivial] [[OUT_I]] : $*Builtin.Int64 // CHECK: dealloc_stack [[OUT_I]] : $*Builtin.Int64 @@ -1194,16 +1194,16 @@ bb2(%7 : $Error): throw %7 : $Error } -// CHECK-LABEL: sil [ossa] @f260_testTryApplyTuple : $@convention(thin) (@in T) -> (@out T, @error Error) { +// CHECK-LABEL: sil [ossa] @f260_testTryApplyTuple : $@convention(thin) (@in T) -> (@out T, @error any Error) { // CHECK: bb0(%0 : $*T, %1 : $*T): // CHECK: [[OUT_T:%.*]] = alloc_stack $T -// CHECK: [[F:%.*]] = function_ref @returnTuple : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, Builtin.Int64, @out Builtin.Int64, @out τ_0_0, @error Error) +// CHECK: [[F:%.*]] = function_ref @returnTuple : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, Builtin.Int64, @out Builtin.Int64, @out τ_0_0, @error any Error) // CHECK: [[OUT_I:%.*]] = alloc_stack $Builtin.Int64 -// CHECK: try_apply [[F]]([[OUT_T]], [[OUT_I]], %0, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, Builtin.Int64, @out Builtin.Int64, @out τ_0_0, @error Error), normal bb2, error bb1 -// CHECK: bb1([[E:%.*]] : $Error): +// CHECK: try_apply [[F]]([[OUT_T]], [[OUT_I]], %0, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, Builtin.Int64, @out Builtin.Int64, @out τ_0_0, @error any Error), normal bb2, error bb1 +// CHECK: bb1([[E:%.*]] : $any Error): // CHECK: dealloc_stack [[OUT_I]] : $*Builtin.Int64 // CHECK: dealloc_stack [[OUT_T]] : $*T -// CHECK: throw [[E]] : $Error +// CHECK: throw [[E]] : $any Error // CHECK: bb2([[RESULT:%.*]] : $Builtin.Int64): // CHECK: dealloc_stack [[OUT_I]] : $*Builtin.Int64 // CHECK: destroy_addr [[OUT_T]] : $*T @@ -1346,17 +1346,17 @@ sil [ossa] @use_C : $@convention(thin) (@owned C) -> () // CHECK-LABEL: sil [ossa] @test_checked_cast_br2 : $@convention(method) (@in Any) -> () { // CHECK: bb0(%0 : $*Any): -// CHECK: [[SUCCESS_DST:%.*]] = alloc_stack $C -// CHECK: checked_cast_addr_br take_on_success Any in %0 : $*Any to C in [[SUCCESS_DST]] : $*C, bb2, bb1 +// CHECK: [[SUCCESS_DST:%.*]] = alloc_stack $any C +// CHECK: checked_cast_addr_br take_on_success Any in %0 : $*Any to any C in [[SUCCESS_DST]] : $*any C, bb2, bb1 // CHECK: bb1: -// CHECK: dealloc_stack [[SUCCESS_DST]] : $*C +// CHECK: dealloc_stack [[SUCCESS_DST]] : $*any C // CHECK: destroy_addr %0 : $*Any // CHECK: br bb3 // CHECK: bb2: -// CHECK: [[LD:%.*]] = load [take] [[SUCCESS_DST]] : $*C -// CHECK: dealloc_stack [[SUCCESS_DST]] : $*C -// CHECK: [[FUNC:%.*]] = function_ref @use_C : $@convention(thin) (@owned C) -> () -// CHECK: apply [[FUNC]]([[LD]]) : $@convention(thin) (@owned C) -> () +// CHECK: [[LD:%.*]] = load [take] [[SUCCESS_DST]] : $*any C +// CHECK: dealloc_stack [[SUCCESS_DST]] : $*any C +// CHECK: [[FUNC:%.*]] = function_ref @use_C : $@convention(thin) (@owned any C) -> () +// CHECK: apply [[FUNC]]([[LD]]) : $@convention(thin) (@owned any C) -> () // CHECK: br bb3 // CHECK: bb3: // CHECK: [[RES:%.*]] = tuple () @@ -1382,19 +1382,19 @@ bb3: sil @use_Any : $@convention(thin) (@in Any) -> () -// CHECK-LABEL: sil [ossa] @test_checked_cast_br3 : $@convention(method) (@owned C) -> () { -// CHECK: bb0(%0 : @owned $C): +// CHECK-LABEL: sil [ossa] @test_checked_cast_br3 : $@convention(method) (@owned any C) -> () { +// CHECK: bb0(%0 : @owned $any C): // CHECK: [[DST:%.*]] = alloc_stack $Any -// CHECK: [[SRC_TMP:%.*]] = alloc_stack $C -// CHECK: store %0 to [init] [[SRC_TMP]] : $*C -// CHECK: checked_cast_addr_br take_on_success C in [[SRC_TMP]] : $*C to Any in [[DST]] : $*Any, bb2, bb1 +// CHECK: [[SRC_TMP:%.*]] = alloc_stack $any C +// CHECK: store %0 to [init] [[SRC_TMP]] : $*any C +// CHECK: checked_cast_addr_br take_on_success any C in [[SRC_TMP]] : $*any C to Any in [[DST]] : $*Any, bb2, bb1 // CHECK: bb1: -// CHECK: [[LD:%.*]] = load [take] [[SRC_TMP]] : $*C -// CHECK: dealloc_stack [[SRC_TMP]] : $*C -// CHECK: destroy_value [[LD]] : $C +// CHECK: [[LD:%.*]] = load [take] [[SRC_TMP]] : $*any C +// CHECK: dealloc_stack [[SRC_TMP]] : $*any C +// CHECK: destroy_value [[LD]] : $any C // CHECK: br bb3 // CHECK: bb2: -// CHECK: dealloc_stack [[SRC_TMP]] : $*C +// CHECK: dealloc_stack [[SRC_TMP]] : $*any C // CHECK: [[FUNC:%.*]] = function_ref @use_Any : $@convention(thin) (@in Any) -> () // CHECK: apply [[FUNC]]([[DST]]) : $@convention(thin) (@in Any) -> () // CHECK: br bb3 diff --git a/test/SILOptimizer/address_lowering_lib.sil b/test/SILOptimizer/address_lowering_lib.sil index b0647db5ba86b..ab9a5c51ead82 100644 --- a/test/SILOptimizer/address_lowering_lib.sil +++ b/test/SILOptimizer/address_lowering_lib.sil @@ -5,16 +5,16 @@ import Swift sil_stage raw -// CHECK-LABEL: sil [ossa] @test_open_existential_box_value : $@convention(thin) (@in Error) -> () { +// CHECK-LABEL: sil [ossa] @test_open_existential_box_value : $@convention(thin) (@in any Error) -> () { // CHECK: [[ALLOC:%.*]] = alloc_stack $Any -// CHECK: [[VAL:%.*]] = load [take] %0 : $*Error -// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [[VAL]] : $Error -// CHECK: [[OPENADDR:%.*]] = open_existential_box [[BORROW]] : $Error to $*@opened("169A6848-B636-11EC-83C4-D0817AD59B9D", Error) Self -// CHECK: [[INIT:%.*]] = init_existential_addr [[ALLOC]] : $*Any, $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D", Error) Self -// CHECK: copy_addr [[OPENADDR]] to [initialization] [[INIT]] : $*@opened("169A6848-B636-11EC-83C4-D0817AD59B9D", Error) Self +// CHECK: [[VAL:%.*]] = load [take] %0 : $*any Error +// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [[VAL]] : $any Error +// CHECK: [[OPENADDR:%.*]] = open_existential_box [[BORROW]] : $any Error to $*@opened("169A6848-B636-11EC-83C4-D0817AD59B9D", any Error) Self +// CHECK: [[INIT:%.*]] = init_existential_addr [[ALLOC]] : $*Any, $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D", any Error) Self +// CHECK: copy_addr [[OPENADDR]] to [initialization] [[INIT]] : $*@opened("169A6848-B636-11EC-83C4-D0817AD59B9D", any Error) Self // CHECK: destroy_addr [[ALLOC]] : $*Any -// CHECK: end_borrow [[BORROW]] : $Error -// CHECK: destroy_value [[VAL]] : $Error +// CHECK: end_borrow [[BORROW]] : $any Error +// CHECK: destroy_value [[VAL]] : $any Error // CHECK: dealloc_stack [[ALLOC]] : $*Any // CHECK-LABEL: } // end sil function 'test_open_existential_box_value' sil [ossa] @test_open_existential_box_value : $@convention(thin) (@in Error) -> () { diff --git a/test/SILOptimizer/allocbox_to_stack.sil b/test/SILOptimizer/allocbox_to_stack.sil index cbaa504beb738..d41fa7bad1ce0 100644 --- a/test/SILOptimizer/allocbox_to_stack.sil +++ b/test/SILOptimizer/allocbox_to_stack.sil @@ -190,14 +190,14 @@ sil @protocols : $@convention(thin) (@in LogicValue, @thin Bool.Type) -> Bool { bb0(%0 : $*LogicValue, %1 : $@thin Bool.Type): %2 = alloc_box ${ var LogicValue } %2a = project_box %2 : ${ var LogicValue }, 0 -// CHECK: %2 = alloc_stack $LogicValue +// CHECK: %2 = alloc_stack $any LogicValue copy_addr [take] %0 to [initialization] %2a : $*LogicValue %6 = open_existential_addr mutable_access %2a : $*LogicValue to $*@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self %7 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self, #LogicValue.getLogicValue, %6 : $*@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self : $@convention(witness_method: LogicValue) (@in_guaranteed T) -> Bool %8 = apply %7<@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self>(%6) : $@convention(witness_method: LogicValue) (@in_guaranteed T) -> Bool strong_release %2 : ${ var LogicValue } -// CHECK: destroy_addr %2 : $*LogicValue -// CHECK-NEXT: dealloc_stack %2 : $*LogicValue +// CHECK: destroy_addr %2 : $*any LogicValue +// CHECK-NEXT: dealloc_stack %2 : $*any LogicValue // CHECK-NEXT: return return %8 : $Bool } @@ -752,10 +752,10 @@ class ThrowDerivedClass : ThrowBaseClass { //final init(failBeforeFullInitialization: Int) throws } -sil @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error Error) -sil @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) +sil @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error any Error) +sil @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) -sil hidden @try_apply_during_chaining_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) { +sil hidden @try_apply_during_chaining_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) { // %0 // users: %11, %5 // %1 // user: %7 bb0(%0 : $Int, %1 : $ThrowDerivedClass): @@ -764,13 +764,13 @@ bb0(%0 : $Int, %1 : $ThrowDerivedClass): %4 = project_box %3 : ${ var ThrowDerivedClass }, 0 store %1 to %4 : $*ThrowDerivedClass %8 = load %4 : $*ThrowDerivedClass - %9 = function_ref @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) - %10 = function_ref @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error Error) - try_apply %10(%0) : $@convention(thin) (Int) -> (Int, @error Error), normal bb1, error bb3 + %9 = function_ref @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) + %10 = function_ref @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error any Error) + try_apply %10(%0) : $@convention(thin) (Int) -> (Int, @error any Error), normal bb1, error bb3 // %12 // user: %13 bb1(%12 : $Int): // Preds: bb0 - try_apply %9(%12, %8) : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error), normal bb2, error bb4 + try_apply %9(%12, %8) : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error), normal bb2, error bb4 // %14 // user: %15 bb2(%14 : $ThrowDerivedClass): // Preds: bb1 @@ -1175,14 +1175,14 @@ bb0(%0: ${ var Int }): return %v : $() } -// CHECK-LABEL: sil private @testPAUsedByTryApply : $@convention(method) (@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error Error) -> () { +// CHECK-LABEL: sil private @testPAUsedByTryApply : $@convention(method) (@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error any Error) -> () { // CHECK-LABEL: } // end sil function 'testPAUsedByTryApply' -sil private @testPAUsedByTryApply : $@convention(method) (@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error Error) -> () { -bb0(%0: $@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error Error): +sil private @testPAUsedByTryApply : $@convention(method) (@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error any Error) -> () { +bb0(%0: $@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error any Error): %box = alloc_box ${ var Int }, var %closure = function_ref @testPAUsedByTryApplyClosure : $@convention(thin) (@guaranteed { var Int }) -> () %pa = partial_apply [callee_guaranteed] %closure(%box) : $@convention(thin) (@guaranteed { var Int }) -> () - try_apply %0(%pa) : $@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error Error, normal bb2, error bb3 + try_apply %0(%pa) : $@callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @error any Error, normal bb2, error bb3 bb2(%result : $()): br bb4 diff --git a/test/SILOptimizer/allocbox_to_stack_ownership.sil b/test/SILOptimizer/allocbox_to_stack_ownership.sil index ebe27edd1cd77..895df33ed3392 100644 --- a/test/SILOptimizer/allocbox_to_stack_ownership.sil +++ b/test/SILOptimizer/allocbox_to_stack_ownership.sil @@ -187,14 +187,14 @@ sil [ossa] @protocols : $@convention(thin) (@in LogicValue, @thin Bool.Type) -> bb0(%0 : $*LogicValue, %1 : $@thin Bool.Type): %2 = alloc_box ${ var LogicValue } %2a = project_box %2 : ${ var LogicValue }, 0 -// CHECK: %2 = alloc_stack $LogicValue +// CHECK: %2 = alloc_stack $any LogicValue copy_addr [take] %0 to [initialization] %2a : $*LogicValue %6 = open_existential_addr mutable_access %2a : $*LogicValue to $*@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self %7 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self, #LogicValue.getLogicValue, %6 : $*@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self : $@convention(witness_method: LogicValue) (@in_guaranteed T) -> Bool %8 = apply %7<@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self>(%6) : $@convention(witness_method: LogicValue) (@in_guaranteed T) -> Bool destroy_value %2 : ${ var LogicValue } -// CHECK: destroy_addr %2 : $*LogicValue -// CHECK-NEXT: dealloc_stack %2 : $*LogicValue +// CHECK: destroy_addr %2 : $*any LogicValue +// CHECK-NEXT: dealloc_stack %2 : $*any LogicValue // CHECK-NEXT: return return %8 : $Bool } @@ -825,10 +825,10 @@ class ThrowDerivedClass : ThrowBaseClass { //final init(failBeforeFullInitialization: Int) throws } -sil [ossa] @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error Error) -sil [ossa] @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) +sil [ossa] @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error any Error) +sil [ossa] @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) -sil hidden [ossa] @try_apply_during_chaining_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) { +sil hidden [ossa] @try_apply_during_chaining_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) { // %0 // users: %11, %5 // %1 // user: %7 bb0(%0 : $Int, %1 : @owned $ThrowDerivedClass): @@ -837,13 +837,13 @@ bb0(%0 : $Int, %1 : @owned $ThrowDerivedClass): %4 = project_box %3 : ${ var ThrowDerivedClass }, 0 store %1 to [init] %4 : $*ThrowDerivedClass %8 = load [take] %4 : $*ThrowDerivedClass - %9 = function_ref @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error) - %10 = function_ref @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error Error) - try_apply %10(%0) : $@convention(thin) (Int) -> (Int, @error Error), normal bb1, error bb3 + %9 = function_ref @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) + %10 = function_ref @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error any Error) + try_apply %10(%0) : $@convention(thin) (Int) -> (Int, @error any Error), normal bb1, error bb3 // %12 // user: %13 bb1(%12 : $Int): // Preds: bb0 - try_apply %9(%12, %8) : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error Error), normal bb2, error bb4 + try_apply %9(%12, %8) : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error), normal bb2, error bb4 // %14 // user: %15 bb2(%14 : @owned $ThrowDerivedClass): // Preds: bb1 diff --git a/test/SILOptimizer/allocboxtostack_localapply.sil b/test/SILOptimizer/allocboxtostack_localapply.sil index 3d6a2c4f1e3e5..48f697e630074 100644 --- a/test/SILOptimizer/allocboxtostack_localapply.sil +++ b/test/SILOptimizer/allocboxtostack_localapply.sil @@ -59,15 +59,15 @@ bb0(%0 : ${ var Int64 }): // CHECK-NOT: alloc_box // CHECK: [[STK:%.*]] = alloc_stack $Int64, var, name "x" // CHECK-LABEL: } // end sil function '$testtryapply' -sil [noinline] @$testtryapply : $@convention(thin) () -> @error Error { +sil [noinline] @$testtryapply : $@convention(thin) () -> @error any Error { bb0: %1 = alloc_box ${ var Int64 }, var, name "x" %2 = project_box %1 : ${ var Int64 }, 0 %3 = integer_literal $Builtin.Int64, 0 %4 = struct $Int64 (%3 : $Builtin.Int64) store %4 to %2 : $*Int64 - %6 = function_ref @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error - try_apply %6(%1) : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error, normal bb1, error bb2 + %6 = function_ref @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error + try_apply %6(%1) : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error, normal bb1, error bb2 bb1(%8 : $()): strong_release %1 : ${ var Int64 } %10 = tuple () @@ -77,7 +77,7 @@ bb2(%12 : $Error): throw %12 : $Error } -sil private [noinline] @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error { +sil private [noinline] @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error { bb0(%0 : ${ var Int64 }): %2 = project_box %0 : ${ var Int64 }, 0 %4 = begin_access [read] [dynamic] %2 : $*Int64 @@ -92,11 +92,11 @@ bb0(%0 : ${ var Int64 }): return %12 : $() } -sil private [noinline] @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error { +sil private [noinline] @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error { bb0(%0 : ${ var Int64 }): %2 = project_box %0 : ${ var Int64 }, 0 - %4 = function_ref @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error - try_apply %4(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error, normal bb1, error bb2 + %4 = function_ref @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error + try_apply %4(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error, normal bb1, error bb2 bb1(%6 : $()): %7 = tuple () return %7 : $() diff --git a/test/SILOptimizer/allocboxtostack_localapply_ossa.sil b/test/SILOptimizer/allocboxtostack_localapply_ossa.sil index 8ce1cac0e5a1b..41c60d3bad6aa 100644 --- a/test/SILOptimizer/allocboxtostack_localapply_ossa.sil +++ b/test/SILOptimizer/allocboxtostack_localapply_ossa.sil @@ -59,15 +59,15 @@ bb0(%0 : @guaranteed ${ var Int64 }): // CHECK-NOT: alloc_box // CHECK: [[STK:%.*]] = alloc_stack $Int64, var, name "x" // CHECK-LABEL: } // end sil function '$testtryapply' -sil [noinline] [ossa] @$testtryapply : $@convention(thin) () -> @error Error { +sil [noinline] [ossa] @$testtryapply : $@convention(thin) () -> @error any Error { bb0: %1 = alloc_box ${ var Int64 }, var, name "x" %2 = project_box %1 : ${ var Int64 }, 0 %3 = integer_literal $Builtin.Int64, 0 %4 = struct $Int64 (%3 : $Builtin.Int64) store %4 to [trivial] %2 : $*Int64 - %6 = function_ref @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error - try_apply %6(%1) : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error, normal bb1, error bb2 + %6 = function_ref @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error + try_apply %6(%1) : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error, normal bb1, error bb2 bb1(%8 : $()): destroy_value %1 : ${ var Int64 } %10 = tuple () @@ -77,7 +77,7 @@ bb2(%12 : $Error): throw %12 : $Error } -sil private [noinline] [ossa] @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error { +sil private [noinline] [ossa] @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error { bb0(%0 : @guaranteed ${ var Int64 }): %2 = project_box %0 : ${ var Int64 }, 0 %4 = begin_access [read] [dynamic] %2 : $*Int64 @@ -92,11 +92,11 @@ bb0(%0 : @guaranteed ${ var Int64 }): return %12 : $() } -sil private [noinline] [ossa] @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error { +sil private [noinline] [ossa] @$testtryapplybas : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error { bb0(%0 : @guaranteed ${ var Int64 }): %2 = project_box %0 : ${ var Int64 }, 0 - %4 = function_ref @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error - try_apply %4(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> @error Error, normal bb1, error bb2 + %4 = function_ref @$testtryapplybar : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error + try_apply %4(%0) : $@convention(thin) (@guaranteed { var Int64 }) -> @error any Error, normal bb1, error bb2 bb1(%6 : $()): %7 = tuple () return %7 : $() diff --git a/test/SILOptimizer/allocstack_hoisting.sil b/test/SILOptimizer/allocstack_hoisting.sil index ee198b918a5a5..fc86613687155 100644 --- a/test/SILOptimizer/allocstack_hoisting.sil +++ b/test/SILOptimizer/allocstack_hoisting.sil @@ -45,7 +45,7 @@ bb3: return %3 : $() } -sil @throwing_fun : $@convention(thin) () -> @error Error +sil @throwing_fun : $@convention(thin) () -> @error any Error // CHECK-LABEL: sil @hoist_generic // CHECK: bb0({{.*}}): @@ -63,7 +63,7 @@ sil @throwing_fun : $@convention(thin) () -> @error Error // CHECK: dealloc_stack [[AS]] // CHECK: throw -sil @hoist_generic_throwing : $@convention(thin) (@in T, Builtin.Int1) -> @error Error { +sil @hoist_generic_throwing : $@convention(thin) (@in T, Builtin.Int1) -> @error any Error { bb0(%0 : $*T, %1: $Builtin.Int1): cond_br %1, bb1, bb2 bb1: @@ -76,8 +76,8 @@ bb2: destroy_addr %0 : $*T br bb3 bb3: - %3 = function_ref @throwing_fun : $@convention(thin) () -> @error Error - try_apply %3() : $@convention(thin) () -> @error Error, normal bb4, error bb5 + %3 = function_ref @throwing_fun : $@convention(thin) () -> @error any Error + try_apply %3() : $@convention(thin) () -> @error any Error, normal bb4, error bb5 bb4(%6: $()): %4 = tuple () diff --git a/test/SILOptimizer/anyhashable_to_protocol.swift b/test/SILOptimizer/anyhashable_to_protocol.swift index e4153f5fa096c..c3038d9ffb54a 100644 --- a/test/SILOptimizer/anyhashable_to_protocol.swift +++ b/test/SILOptimizer/anyhashable_to_protocol.swift @@ -11,7 +11,7 @@ class FooProtocolImplementation : NSObject, FooProtocol { } // CHECK-LABEL: sil @{{.*}}testit -// CHECK: checked_cast_addr_br {{.*}} AnyHashable {{.*}} to FooProtocol +// CHECK: checked_cast_addr_br {{.*}} AnyHashable {{.*}} to any FooProtocol public func testit(_ x: AnyHashable) -> Bool { return (x as? FooProtocol) != nil } diff --git a/test/SILOptimizer/arcsequenceopts.sil b/test/SILOptimizer/arcsequenceopts.sil index 2a6ce093cacba..17b896008058a 100644 --- a/test/SILOptimizer/arcsequenceopts.sil +++ b/test/SILOptimizer/arcsequenceopts.sil @@ -92,7 +92,7 @@ sil [serialized] @guaranteed_use : $@convention(thin) (@guaranteed Builtin.Nativ sil [serialized] @owned_return : $@convention(thin) () -> (@owned <τ_0_0> { var τ_0_0 } ) -sil [serialized] @guaranteed_throwing_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error Error +sil [serialized] @guaranteed_throwing_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error any Error ///////////////// // Basic Tests // @@ -405,7 +405,7 @@ bb0(%0 : $<τ_0_0> { var τ_0_0 } ): return %1 : $() } -sil @guaranteed_box_throwing_use : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error Error { +sil @guaranteed_box_throwing_use : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error any Error { bb0(%0 : $<τ_0_0> { var τ_0_0 } ): %1 = tuple () return %1 : $() @@ -2125,18 +2125,18 @@ bb0: return %9999 : $() } -// CHECK-LABEL: sil [serialized] @try_apply_test_1 : $@convention(thin) (Builtin.NativeObject) -> @error Error { +// CHECK-LABEL: sil [serialized] @try_apply_test_1 : $@convention(thin) (Builtin.NativeObject) -> @error any Error { // CHECK: bb0 // CHECK: strong_retain // CHECK: bb1 // CHECK: strong_release // CHECK: bb2 // CHECK: strong_release -sil [serialized] @try_apply_test_1 : $@convention(thin) (Builtin.NativeObject) -> @error Error { +sil [serialized] @try_apply_test_1 : $@convention(thin) (Builtin.NativeObject) -> @error any Error { bb0(%0 : $Builtin.NativeObject): strong_retain %0 : $Builtin.NativeObject - %1 = function_ref @guaranteed_throwing_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error Error - try_apply %1(%0) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error Error, normal bb1, error bb2 + %1 = function_ref @guaranteed_throwing_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error any Error + try_apply %1(%0) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error any Error, normal bb1, error bb2 bb1(%2 : $()): strong_release %0 : $Builtin.NativeObject @@ -2147,7 +2147,7 @@ bb2(%3 : $Error): throw %3 : $Error } -// CHECK-LABEL: sil [serialized] @try_apply_test_2 : $@convention(thin) (Builtin.NativeObject) -> @error Error { +// CHECK-LABEL: sil [serialized] @try_apply_test_2 : $@convention(thin) (Builtin.NativeObject) -> @error any Error { // CHECK: bb0( // CHECK: strong_retain // CHECK: try_apply @@ -2155,13 +2155,13 @@ bb2(%3 : $Error): // CHECK: strong_release // CHECK: bb2( // CHECK: strong_release -sil [serialized] @try_apply_test_2 : $@convention(thin) (Builtin.NativeObject) -> @error Error { +sil [serialized] @try_apply_test_2 : $@convention(thin) (Builtin.NativeObject) -> @error any Error { bb0(%0 : $Builtin.NativeObject): strong_retain %0 : $Builtin.NativeObject %1 = function_ref @guaranteed_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () apply %1(%0) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () - %2 = function_ref @guaranteed_throwing_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error Error - try_apply %2(%0) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error Error, normal bb1, error bb2 + %2 = function_ref @guaranteed_throwing_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error any Error + try_apply %2(%0) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error any Error, normal bb1, error bb2 bb1(%3 : $()): strong_release %0 : $Builtin.NativeObject @@ -2176,16 +2176,16 @@ bb2(%4 : $Error): // CHECK-NOT: strong_retain // CHECK-NOT: strong_release // CHECK_LABEL: } // end sil function '$try_apply_test_3' -sil hidden [noinline] @$try_apply_test_3 : $@convention(thin) () -> @error Error { +sil hidden [noinline] @$try_apply_test_3 : $@convention(thin) () -> @error any Error { bb0: %box = alloc_box $<τ_0_0> { var τ_0_0 } %proj = project_box %box : $<τ_0_0> { var τ_0_0 } , 0 - %funcref = function_ref @guaranteed_box_throwing_use : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error Error + %funcref = function_ref @guaranteed_box_throwing_use : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error any Error br bb1 bb1: strong_retain %box : $<τ_0_0> { var τ_0_0 } - try_apply %funcref (%box) : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error Error, normal bbs, error bbe + try_apply %funcref (%box) : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error any Error, normal bbs, error bbe bbs(%s : $()): strong_release %box : $<τ_0_0> { var τ_0_0 } diff --git a/test/SILOptimizer/array_property_opt.sil b/test/SILOptimizer/array_property_opt.sil index 10773f39913e6..1d20d4aac2d8e 100644 --- a/test/SILOptimizer/array_property_opt.sil +++ b/test/SILOptimizer/array_property_opt.sil @@ -112,7 +112,7 @@ bb0(%0: $MyArray): // Make sure we can handle try_apply when splitting edges. This test used to crash. -sil @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) +sil @throwing_fun : $@convention(thin) () -> (MyBool, @error any Error) // CHECK-LABEL: sil @clone_try_apply_exit : // CHECK: bb1: @@ -125,7 +125,7 @@ sil @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) // CHECK: [[FUNC2:%.*]] = function_ref @arrayPropertyIsNative // CHECK: apply [[FUNC2]] // CHECK_LABEL: } // end sil function 'clone_try_apply_exit' -sil @clone_try_apply_exit : $@convention(thin) (@inout MyArray, @inout MyBool) -> (MyBool, @error Error) { +sil @clone_try_apply_exit : $@convention(thin) (@inout MyArray, @inout MyBool) -> (MyBool, @error any Error) { bb0(%0 : $*MyArray, %1 : $*MyBool): %3 = load %0 : $*MyArray br bb1 @@ -135,8 +135,8 @@ bb1: %4 = load %1 : $*MyBool retain_value %3 : $MyArray %5 = apply %2(%3) : $@convention(method) (@owned MyArray) -> Bool - %7 = function_ref @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) - try_apply %7() : $@convention(thin) () -> (MyBool, @error Error), normal bb2, error bb6 + %7 = function_ref @throwing_fun : $@convention(thin) () -> (MyBool, @error any Error) + try_apply %7() : $@convention(thin) () -> (MyBool, @error any Error), normal bb2, error bb6 bb2(%8 : $MyBool): %6 = integer_literal $Builtin.Int1, -1 diff --git a/test/SILOptimizer/array_property_opt_ossa_guaranteed.sil b/test/SILOptimizer/array_property_opt_ossa_guaranteed.sil index 4713a888bac30..b9540a467132e 100644 --- a/test/SILOptimizer/array_property_opt_ossa_guaranteed.sil +++ b/test/SILOptimizer/array_property_opt_ossa_guaranteed.sil @@ -133,7 +133,7 @@ protocol AProtocol : class { // Make sure we can handle try_apply when splitting edges. This test used to crash. -sil [ossa] @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) +sil [ossa] @throwing_fun : $@convention(thin) () -> (MyBool, @error any Error) // CHECK-LABEL: sil [ossa] @clone_try_apply_exit : // CHECK: bb1: @@ -146,7 +146,7 @@ sil [ossa] @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) // CHECK: [[FUNC2:%.*]] = function_ref @arrayPropertyIsNative // CHECK: apply [[FUNC2]] // CHECK_LABEL: } // end sil function 'clone_try_apply_exit' -sil [ossa] @clone_try_apply_exit : $@convention(thin) (@inout MyArray, @inout MyBool) -> (MyBool, @error Error) { +sil [ossa] @clone_try_apply_exit : $@convention(thin) (@inout MyArray, @inout MyBool) -> (MyBool, @error any Error) { bb0(%0 : $*MyArray, %1 : $*MyBool): %3 = load [copy] %0 : $*MyArray br bb1 @@ -155,8 +155,8 @@ bb1: %2 = function_ref @arrayPropertyIsNative : $@convention(method) (@guaranteed MyArray) -> Bool %4 = load [trivial] %1 : $*MyBool %5 = apply %2(%3) : $@convention(method) (@guaranteed MyArray) -> Bool - %7 = function_ref @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) - try_apply %7() : $@convention(thin) () -> (MyBool, @error Error), normal bb2, error bb5 + %7 = function_ref @throwing_fun : $@convention(thin) () -> (MyBool, @error any Error) + try_apply %7() : $@convention(thin) () -> (MyBool, @error any Error), normal bb2, error bb5 bb2(%8 : $MyBool): %6 = integer_literal $Builtin.Int1, -1 diff --git a/test/SILOptimizer/array_property_opt_ossa_owned.sil b/test/SILOptimizer/array_property_opt_ossa_owned.sil index e9f53f754b8f3..28dd0bc3b7fa9 100644 --- a/test/SILOptimizer/array_property_opt_ossa_owned.sil +++ b/test/SILOptimizer/array_property_opt_ossa_owned.sil @@ -169,7 +169,7 @@ protocol AProtocol : class { // Make sure we can handle try_apply when splitting edges. This test used to crash. -sil [ossa] @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) +sil [ossa] @throwing_fun : $@convention(thin) () -> (MyBool, @error any Error) // CHECK-LABEL: sil [ossa] @clone_try_apply_exit : // CHECK: bb1: @@ -182,7 +182,7 @@ sil [ossa] @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) // CHECK: [[FUNC2:%.*]] = function_ref @arrayPropertyIsNative // CHECK: apply [[FUNC2]] // CHECK_LABEL: } // end sil function 'clone_try_apply_exit' -sil [ossa] @clone_try_apply_exit : $@convention(thin) (@inout MyArray, @inout MyBool) -> (MyBool, @error Error) { +sil [ossa] @clone_try_apply_exit : $@convention(thin) (@inout MyArray, @inout MyBool) -> (MyBool, @error any Error) { bb0(%0 : $*MyArray, %1 : $*MyBool): %3 = load [copy] %0 : $*MyArray br bb1 @@ -192,8 +192,8 @@ bb1: %4 = load [trivial] %1 : $*MyBool %copy3 = copy_value %3 : $MyArray %5 = apply %2(%copy3) : $@convention(method) (@owned MyArray) -> Bool - %7 = function_ref @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) - try_apply %7() : $@convention(thin) () -> (MyBool, @error Error), normal bb2, error bb5 + %7 = function_ref @throwing_fun : $@convention(thin) () -> (MyBool, @error any Error) + try_apply %7() : $@convention(thin) () -> (MyBool, @error any Error), normal bb2, error bb5 bb2(%8 : $MyBool): %6 = integer_literal $Builtin.Int1, -1 diff --git a/test/SILOptimizer/assemblyvision_remark/cast_remarks.swift b/test/SILOptimizer/assemblyvision_remark/cast_remarks.swift index a4a54fe570193..9c45250d797f6 100644 --- a/test/SILOptimizer/assemblyvision_remark/cast_remarks.swift +++ b/test/SILOptimizer/assemblyvision_remark/cast_remarks.swift @@ -221,7 +221,7 @@ public func forcedCast(_ ns: Existential1) -> Existential2 { // Make sure the colon info is right so that the arrow is under the a. // // TODO: We should also note the retain as being on 'ns'. - return ns as! Existential2 // expected-remark @:13 {{unconditional runtime cast of value with type 'Existential1' to 'Existential2'}} + return ns as! Existential2 // expected-remark @:13 {{unconditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} // expected-note @-5:26 {{of 'ns'}} } @@ -231,7 +231,7 @@ public func forcedCast2(_ ns: Existential1) -> Existential2 { // Today, we seem to completely eliminate 'x' here in the debug info. TODO: // Maybe we can recover this info somehow. We should also note the retain as being on 'ns' let x = ns - return x as! Existential2 // expected-remark @:12 {{unconditional runtime cast of value with type 'Existential1' to 'Existential2'}} + return x as! Existential2 // expected-remark @:12 {{unconditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} // expected-note @-7:27 {{of 'ns'}} } @@ -241,7 +241,7 @@ public func forcedCast3(_ ns: Existential1) -> Existential2 { // Today, we seem to completely eliminate 'x' here in the debug info. TODO: // Maybe we can recover this info somehow. var x = ns // expected-warning {{variable 'x' was never mutated}} - return x as! Existential2 // expected-remark @:12 {{unconditional runtime cast of value with type 'Existential1' to 'Existential2'}} + return x as! Existential2 // expected-remark @:12 {{unconditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} // expected-note @-7:27 {{of 'ns'}} } @@ -250,13 +250,13 @@ public func forcedCast4(_ ns: Existential1, _ ns2: Existential1) -> Existential2 // Make sure the colon info is right so that the arrow is under the a. var x = ns x = ns2 - return x as! Existential2 // expected-remark @:12 {{unconditional runtime cast of value with type 'Existential1' to 'Existential2'}} + return x as! Existential2 // expected-remark @:12 {{unconditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} // expected-note @-5:47 {{of 'ns2'}} } public func condCast(_ ns: Existential1) -> Existential2? { // Make sure the colon info is right so that the arrow is under the a. - return ns as? Existential2 // expected-remark @:13 {{conditional runtime cast of value with type 'Existential1' to 'Existential2'}} + return ns as? Existential2 // expected-remark @:13 {{conditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} // expected-note @-3:24 {{of 'ns'}} } @@ -266,7 +266,7 @@ public func condCast2(_ ns: Existential1) -> Existential2? { // Today, we seem to completely eliminate 'x' here in the debug info. TODO: // Maybe we can recover this info somehow. let x = ns - return x as? Existential2 // expected-remark @:12 {{conditional runtime cast of value with type 'Existential1' to 'Existential2'}} + return x as? Existential2 // expected-remark @:12 {{conditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} // expected-note @-7:25 {{of 'ns'}} } @@ -276,7 +276,7 @@ public func condCast3(_ ns: Existential1) -> Existential2? { // Today, we seem to completely eliminate 'x' here in the debug info. TODO: // Maybe we can recover this info somehow. var x = ns // expected-warning {{variable 'x' was never mutated}} - return x as? Existential2 // expected-remark @:12 {{conditional runtime cast of value with type 'Existential1' to 'Existential2'}} + return x as? Existential2 // expected-remark @:12 {{conditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} // expected-note @-7:25 {{of 'ns'}} } @@ -285,7 +285,7 @@ public func condCast4(_ ns: Existential1, _ ns2: Existential1) -> Existential2? // Make sure the colon info is right so that the arrow is under the a. var x = ns x = ns2 - return x as? Existential2 // expected-remark @:12 {{conditional runtime cast of value with type 'Existential1' to 'Existential2'}} + return x as? Existential2 // expected-remark @:12 {{conditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} // expected-note @-5:45 {{of 'ns2'}} } @@ -293,7 +293,7 @@ public func condCast5(_ ns: Existential1) -> Existential2? { // Make sure the colon info is right so that the arrow is under the a. // // Today, we lose that x was assigned. - if let x = ns as? Existential2 { // expected-remark @:17 {{conditional runtime cast of value with type 'Existential1' to 'Existential2'}} + if let x = ns as? Existential2 { // expected-remark @:17 {{conditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} return x // expected-note @-5:25 {{of 'ns'}} } return nil @@ -303,7 +303,7 @@ public func condCast6(_ ns: Existential1) -> Existential2? { // Make sure the colon info is right so that the arrow is under the a. // // Today, we lose that x was assigned. - guard let x = ns as? Existential2 else { // expected-remark @:20 {{conditional runtime cast of value with type 'Existential1' to 'Existential2'}} + guard let x = ns as? Existential2 else { // expected-remark @:20 {{conditional runtime cast of value with type 'any Existential1' to 'any Existential2'}} return nil // expected-note @-5:25 {{of 'ns'}} } return x diff --git a/test/SILOptimizer/basic-aa.sil b/test/SILOptimizer/basic-aa.sil index b24fe632275d2..352f94249361c 100644 --- a/test/SILOptimizer/basic-aa.sil +++ b/test/SILOptimizer/basic-aa.sil @@ -646,19 +646,19 @@ struct S : P { // CHECK-LABEL: @init_existential_addr // CHECK: PAIR #3. -// CHECK-NEXT: %0 = argument of bb0 : $P -// CHECK-NEXT: %3 = init_existential_addr %2 : $*P, $S +// CHECK-NEXT: %0 = argument of bb0 : $any P +// CHECK-NEXT: %3 = init_existential_addr %2 : $*any P, $S // CHECK-NEXT: NoAlias // CHECK: PAIR #12. -// CHECK-NEXT: %2 = alloc_stack $P -// CHECK-NEXT: %3 = init_existential_addr %2 : $*P, $S +// CHECK-NEXT: %2 = alloc_stack $any P +// CHECK-NEXT: %3 = init_existential_addr %2 : $*any P, $S // CHECK-NEXT: MayAlias // CHECK: PAIR #13. -// CHECK-NEXT: %2 = alloc_stack $P +// CHECK-NEXT: %2 = alloc_stack $any P // CHECK-NEXT: %4 = struct_element_addr %3 : $*S, #S.i // CHECK-NEXT: MayAlias // CHECK: PAIR #16. -// CHECK-NEXT: %3 = init_existential_addr %2 : $*P, $S +// CHECK-NEXT: %3 = init_existential_addr %2 : $*any P, $S // CHECK-NEXT: %4 = struct_element_addr %3 : $*S, #S.i // CHECK-NEXT: PartialAlias sil @init_existential_addr : $@convention(thin) (P) -> () { diff --git a/test/SILOptimizer/capture_propagation.sil b/test/SILOptimizer/capture_propagation.sil index 9b5f926a7e9d8..d81879edfaa5e 100644 --- a/test/SILOptimizer/capture_propagation.sil +++ b/test/SILOptimizer/capture_propagation.sil @@ -137,12 +137,12 @@ bb0: return %2 : $@callee_owned (Int32, Int32) -> Bool } -sil @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error) +sil @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error) -sil @throwing_closure : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) { +sil @throwing_closure : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) { bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type): - %3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error) - try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error Error), normal bb1, error bb2 + %3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error) + try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error), normal bb1, error bb2 bb1(%5 : $Bool): return %5 : $Bool @@ -155,28 +155,28 @@ bb2(%7 : $Error): // CHECK: [[F:%[0-9]+]] = function_ref @specialized_throwing_closure // CHECK: [[R:%[0-9]+]] = thin_to_thick_function [[F]] // CHECK: return [[R]] -sil @return_throwing_closure : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error Error) { +sil @return_throwing_closure : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error any Error) { bb0: %0 = metatype $@thin Int32.Type - %1 = function_ref @throwing_closure : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) - %2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) - return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error) + %1 = function_ref @throwing_closure : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) + %2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) + return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error any Error) } // Check if we can handle a non-throwing closure which is passed to a thunk accepting a throwing closure. sil @simple_nonthrowing_closure : $@convention(thin) (Int32) -> Bool -// CHECK-LABEL: sil shared @{{.*}}throwing_thunk{{.*}} : $@convention(thin) (Int32) -> (Bool, @error Error) { +// CHECK-LABEL: sil shared @{{.*}}throwing_thunk{{.*}} : $@convention(thin) (Int32) -> (Bool, @error any Error) { // CHECK: = function_ref @simple_nonthrowing_closure // CHECK-NEXT: thin_to_thick_function // CHECK-NEXT: convert_function // CHECK-NEXT: try_apply // CHECK: return // CHECK: throw -sil @throwing_thunk : $@convention(thin) (Int32, @owned @callee_owned (Int32) -> (Bool, @error Error)) -> (Bool, @error Error) { -bb0(%0 : $Int32, %1 : $@callee_owned (Int32) -> (Bool, @error Error)): - try_apply %1(%0) : $@callee_owned (Int32) -> (Bool, @error Error), normal bb1, error bb2 +sil @throwing_thunk : $@convention(thin) (Int32, @owned @callee_owned (Int32) -> (Bool, @error any Error)) -> (Bool, @error any Error) { +bb0(%0 : $Int32, %1 : $@callee_owned (Int32) -> (Bool, @error any Error)): + try_apply %1(%0) : $@callee_owned (Int32) -> (Bool, @error any Error), normal bb1, error bb2 bb1(%5 : $Bool): return %5 : $Bool @@ -186,17 +186,17 @@ bb2(%7 : $Error): } // CHECK-LABEL: sil @return_throwing_thunk_closure -// CHECK: [[F:%[0-9]+]] = function_ref @{{.*}}throwing_thunk{{.*}} : $@convention(thin) (Int32) -> (Bool, @error Error) +// CHECK: [[F:%[0-9]+]] = function_ref @{{.*}}throwing_thunk{{.*}} : $@convention(thin) (Int32) -> (Bool, @error any Error) // CHECK: [[T:%[0-9]+]] = thin_to_thick_function [[F]] // CHECK: return [[T]] -sil @return_throwing_thunk_closure : $@convention(thin) () -> @owned @callee_owned (Int32) -> (Bool, @error Error) { +sil @return_throwing_thunk_closure : $@convention(thin) () -> @owned @callee_owned (Int32) -> (Bool, @error any Error) { bb0: %c1 = function_ref @simple_nonthrowing_closure : $@convention(thin) (Int32) -> Bool %c2 = thin_to_thick_function %c1 : $@convention(thin) (Int32) -> Bool to $@callee_owned (Int32) -> Bool - %c3 = convert_function %c2 : $@callee_owned (Int32) -> Bool to $@callee_owned (Int32) -> (Bool, @error Error) - %t1 = function_ref @throwing_thunk : $@convention(thin) (Int32, @owned @callee_owned (Int32) -> (Bool, @error Error)) -> (Bool, @error Error) - %2 = partial_apply %t1(%c3) : $@convention(thin) (Int32, @owned @callee_owned (Int32) -> (Bool, @error Error)) -> (Bool, @error Error) - return %2 : $@callee_owned (Int32) -> (Bool, @error Error) + %c3 = convert_function %c2 : $@callee_owned (Int32) -> Bool to $@callee_owned (Int32) -> (Bool, @error any Error) + %t1 = function_ref @throwing_thunk : $@convention(thin) (Int32, @owned @callee_owned (Int32) -> (Bool, @error any Error)) -> (Bool, @error any Error) + %2 = partial_apply %t1(%c3) : $@convention(thin) (Int32, @owned @callee_owned (Int32) -> (Bool, @error any Error)) -> (Bool, @error any Error) + return %2 : $@callee_owned (Int32) -> (Bool, @error any Error) } // Negative tests @@ -292,10 +292,10 @@ bb0: } -sil @other_inst_in_returnblock : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) { +sil @other_inst_in_returnblock : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) { bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type): - %3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error) - try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error Error), normal bb1, error bb2 + %3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error) + try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error), normal bb1, error bb2 bb1(%5 : $Bool): %r = alloc_ref $X @@ -311,19 +311,19 @@ bb2(%7 : $Error): // CHECK: [[F:%[0-9]+]] = function_ref @other_inst_in_returnblock // CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]]) // CHECK: return [[R]] -sil @return_other_inst_in_returnblock : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error Error) { +sil @return_other_inst_in_returnblock : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error any Error) { bb0: %0 = metatype $@thin Int32.Type - %1 = function_ref @other_inst_in_returnblock : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) - %2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) - return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error) + %1 = function_ref @other_inst_in_returnblock : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) + %2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) + return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error any Error) } -sil @wrong_return2 : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) { +sil @wrong_return2 : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) { bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type): - %3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error) - try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error Error), normal bb1, error bb2 + %3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error) + try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error), normal bb1, error bb2 bb1(%5 : $Bool): %i = integer_literal $Builtin.Int1, 0 @@ -339,19 +339,19 @@ bb2(%7 : $Error): // CHECK: [[F:%[0-9]+]] = function_ref @wrong_return2 // CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]]) // CHECK: return [[R]] -sil @return_wrong_return2 : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error Error) { +sil @return_wrong_return2 : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error any Error) { bb0: %0 = metatype $@thin Int32.Type - %1 = function_ref @wrong_return2 : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) - %2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) - return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error) + %1 = function_ref @wrong_return2 : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) + %2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) + return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error any Error) } -sil @wrong_terminator : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) { +sil @wrong_terminator : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) { bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type): - %3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error Error) - try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error Error), normal bb1, error bb2 + %3 = function_ref @specialized_throwing_closure : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error) + try_apply %3(%0, %1) : $@convention(thin) (Int32, Int32) -> (Bool, @error any Error), normal bb1, error bb2 bb1(%5 : $Bool): return %5 : $Bool @@ -370,12 +370,12 @@ bb3: // CHECK: [[F:%[0-9]+]] = function_ref @wrong_terminator // CHECK: [[R:%[0-9]+]] = partial_apply [[F]]([[M]]) // CHECK: return [[R]] -sil @return_wrong_terminator : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error Error) { +sil @return_wrong_terminator : $@convention(thin) () -> @owned @callee_owned (Int32, Int32) -> (Bool, @error any Error) { bb0: %0 = metatype $@thin Int32.Type - %1 = function_ref @wrong_terminator : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) - %2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error Error) - return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error) + %1 = function_ref @wrong_terminator : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) + %2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> (Bool, @error any Error) + return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error any Error) } // Test generic capture propagation diff --git a/test/SILOptimizer/cast_folding.swift b/test/SILOptimizer/cast_folding.swift index 9a6b8b843369b..7abe971207d6a 100644 --- a/test/SILOptimizer/cast_folding.swift +++ b/test/SILOptimizer/cast_folding.swift @@ -1029,7 +1029,7 @@ public func testCastAnyObjectProtocolToAnyObjectType() -> AnyObject.Type? { } // CHECK-LABEL: // testCastProtocolTypeProtocolToProtocolTypeType -// CHECK: sil [noinline] @{{.*}}testCastProtocol{{.*}}$@convention(thin) () -> Optional<@thick P.Type.Type> +// CHECK: sil [noinline] @{{.*}}testCastProtocol{{.*}}$@convention(thin) () -> Optional<@thick any P.Type.Type> // CHECK: %0 = enum $Optional{{.*}}, #Optional.none!enumelt // CHECK-NEXT: return %0 @inline(never) diff --git a/test/SILOptimizer/cast_folding_conditional_conformance.swift b/test/SILOptimizer/cast_folding_conditional_conformance.swift index 1421315f1e800..f428e36e577d7 100644 --- a/test/SILOptimizer/cast_folding_conditional_conformance.swift +++ b/test/SILOptimizer/cast_folding_conditional_conformance.swift @@ -8,7 +8,7 @@ extension Array: P where Element: P {} struct X {} // CHECK-LABEL: sil @$s36cast_folding_conditional_conformance5arrayyyF : $@convention(thin) () -> () { public func array() { - // CHECK: unconditional_checked_cast_addr Array in {{%[0-9]*}} : $*Array to P in {{%[0-9]*}} : $*P + // CHECK: unconditional_checked_cast_addr Array in {{%[0-9]*}} : $*Array to any P in {{%[0-9]*}} : $*any P var x = [X()] as! P } @@ -16,7 +16,7 @@ struct Y {} extension Y: P where T: P {} // CHECK-LABEL: sil @$s36cast_folding_conditional_conformance3fooyyxmlF : $@convention(thin) (@thick T.Type) -> () { public func foo(_: T.Type) { - // CHECK: unconditional_checked_cast_addr Y in {{%[0-9]*}} : $*Y to P in {{%[0-9]*}} : $*P + // CHECK: unconditional_checked_cast_addr Y in {{%[0-9]*}} : $*Y to any P in {{%[0-9]*}} : $*any P var x = Y() as! P } diff --git a/test/SILOptimizer/cast_folding_parameterized_protocol.swift b/test/SILOptimizer/cast_folding_parameterized_protocol.swift index 48637841ceef5..bfbb74641f48f 100644 --- a/test/SILOptimizer/cast_folding_parameterized_protocol.swift +++ b/test/SILOptimizer/cast_folding_parameterized_protocol.swift @@ -15,69 +15,69 @@ func use(_ t: T) {} // CHECK-LABEL: sil @$s35cast_folding_parameterized_protocol23concrete_to_existentialyyAA1XV_AA1YVyxGAFySiGtlF : $@convention(thin) (X, Y, Y) -> () public func concrete_to_existential(_ x: X, _ yt: Y, _ yi: Y) { - // CHECK:{{%.*}} = init_existential_addr %6 : $*P, $X + // CHECK:{{%.*}} = init_existential_addr %6 : $*any P, $X use(x as! any P) - // CHECK: unconditional_checked_cast_addr X in {{%.*}} : $*X to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr X in {{%.*}} : $*X to any P in {{%.*}} : $*any P use(x as! any P) - // CHECK: unconditional_checked_cast_addr X in {{%.*}} : $*X to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr X in {{%.*}} : $*X to any P in {{%.*}} : $*any P use(x as! any P) - // CHECK: unconditional_checked_cast_addr X in {{%.*}} : $*X to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr X in {{%.*}} : $*X to any P in {{%.*}} : $*any P use(x as! any P) - // CHECK: {{%.*}} = init_existential_addr {{%.*}} : $*Q, $X + // CHECK: {{%.*}} = init_existential_addr {{%.*}} : $*any Q, $X use(x as! any Q) - // CHECK: {{%.*}} = init_existential_addr {{%.*}} : $*P, $Y + // CHECK: {{%.*}} = init_existential_addr {{%.*}} : $*any P, $Y use(yt as! any P) - // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to any P in {{%.*}} : $*any P use(yt as! any P) - // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to any P in {{%.*}} : $*any P use(yt as! any P) - // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to any P in {{%.*}} : $*any P use(yt as! any P) - // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to Q in {{%.*}} : $*Q + // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to any Q in {{%.*}} : $*any Q use(yt as! any Q) - // CHECK: {{%.*}} = init_existential_addr {{%.*}} : $*P, $Y + // CHECK: {{%.*}} = init_existential_addr {{%.*}} : $*any P, $Y use(yi as! any P) - // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to any P in {{%.*}} : $*any P use(yi as! any P) - // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to any P in {{%.*}} : $*any P use(yi as! any P) - // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr Y in {{%.*}} : $*Y to any P in {{%.*}} : $*any P use(yi as! any P) - // CHECK: {{%.*}} = init_existential_addr {{%.*}} : $*Q, $Y + // CHECK: {{%.*}} = init_existential_addr {{%.*}} : $*any Q, $Y use(yi as! any Q) } -// CHECK-LABEL: sil @$s35cast_folding_parameterized_protocol23existential_to_concreteyyxm_AA1P_px1TRts_XPtlF : $@convention(thin) (@thick T.Type, @in_guaranteed P) -> () +// CHECK-LABEL: sil @$s35cast_folding_parameterized_protocol23existential_to_concreteyyxm_AA1P_px1TRts_XPtlF : $@convention(thin) (@thick T.Type, @in_guaranteed any P) -> () public func existential_to_concrete(_: T.Type, _ p: any P) { - // CHECK: unconditional_checked_cast_addr P in {{%.*}} : $*P to X in {{%.*}} : $*X + // CHECK: unconditional_checked_cast_addr any P in {{%.*}} : $*any P to X in {{%.*}} : $*X _ = p as! X - // CHECK: unconditional_checked_cast_addr P in {{%.*}} : $*P to Y in {{%.*}} : $*Y + // CHECK: unconditional_checked_cast_addr any P in {{%.*}} : $*any P to Y in {{%.*}} : $*Y _ = p as! Y - // CHECK: unconditional_checked_cast_addr P in {{%.*}} : $*P to Y in {{%.*}} : $*Y + // CHECK: unconditional_checked_cast_addr any P in {{%.*}} : $*any P to Y in {{%.*}} : $*Y _ = p as! Y - // CHECK: unconditional_checked_cast_addr P in {{%.*}} : $*P to Y in {{%.*}} : $*Y + // CHECK: unconditional_checked_cast_addr any P in {{%.*}} : $*any P to Y in {{%.*}} : $*Y _ = p as! Y } -// CHECK-LABEL: sil @$s35cast_folding_parameterized_protocol015existential_to_E0yyAA1P_px1TRts_XP_AA1Q_ptlF : $@convention(thin) (@in_guaranteed P, @in_guaranteed Q) -> () +// CHECK-LABEL: sil @$s35cast_folding_parameterized_protocol015existential_to_E0yyAA1P_px1TRts_XP_AA1Q_ptlF : $@convention(thin) (@in_guaranteed any P, @in_guaranteed any Q) -> () public func existential_to_existential(_ p: any P, _ q: any Q) { - // CHECK: unconditional_checked_cast_addr P in {{%.*}} : $*P to Q in {{%.*}} : $*Q + // CHECK: unconditional_checked_cast_addr any P in {{%.*}} : $*any P to any Q in {{%.*}} : $*any Q _ = p as! any Q - // CHECK: unconditional_checked_cast_addr P in {{%.*}} : $*P to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr any P in {{%.*}} : $*any P to any P in {{%.*}} : $*any P _ = p as! any P - // CHECK: unconditional_checked_cast_addr P in {{%.*}} : $*P to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr any P in {{%.*}} : $*any P to any P in {{%.*}} : $*any P _ = p as! any P - // CHECK: unconditional_checked_cast_addr P in {{%.*}} : $*P to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr any P in {{%.*}} : $*any P to any P in {{%.*}} : $*any P _ = p as! any P - // CHECK: unconditional_checked_cast_addr Q in {{%.*}} : $*Q to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr any Q in {{%.*}} : $*any Q to any P in {{%.*}} : $*any P _ = q as! any P - // CHECK: unconditional_checked_cast_addr Q in {{%.*}} : $*Q to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr any Q in {{%.*}} : $*any Q to any P in {{%.*}} : $*any P _ = q as! any P - // CHECK: unconditional_checked_cast_addr Q in {{%.*}} : $*Q to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr any Q in {{%.*}} : $*any Q to any P in {{%.*}} : $*any P _ = q as! any P - // CHECK: unconditional_checked_cast_addr Q in {{%.*}} : $*Q to P in {{%.*}} : $*P + // CHECK: unconditional_checked_cast_addr any Q in {{%.*}} : $*any Q to any P in {{%.*}} : $*any P _ = q as! any P } diff --git a/test/SILOptimizer/cast_optimizer_conditional_conformance.sil b/test/SILOptimizer/cast_optimizer_conditional_conformance.sil index 8e238f5fde3e0..3fa5170345558 100644 --- a/test/SILOptimizer/cast_optimizer_conditional_conformance.sil +++ b/test/SILOptimizer/cast_optimizer_conditional_conformance.sil @@ -32,15 +32,15 @@ extension S1 : HasFoo where T == UInt8 { // // CHECK-LABEL: sil shared [noinline] @testSpecializedS1 : $@convention(thin) (S1) -> () { // CHECK: bb0(%0 : $S1): -// CHECK: [[EXIS:%.*]] = alloc_stack $HasFoo +// CHECK: [[EXIS:%.*]] = alloc_stack $any HasFoo // CHECK: [[S1:%.*]] = alloc_stack $S1 // CHECK: store %0 to [[S1]] : $*S1 -// CHECK: [[HASFOO:%.*]] = alloc_stack $HasFoo -// CHECK: [[EXIS_ADDR:%.*]] = init_existential_addr [[HASFOO]] : $*HasFoo, $S1 +// CHECK: [[HASFOO:%.*]] = alloc_stack $any HasFoo +// CHECK: [[EXIS_ADDR:%.*]] = init_existential_addr [[HASFOO]] : $*any HasFoo, $S1 // CHECK: copy_addr [take] [[S1]] to [initialization] [[EXIS_ADDR]] : $*S1 -// CHECK: copy_addr [take] [[HASFOO]] to [initialization] [[EXIS]] : $*HasFoo -// CHECK: [[OPEN_EXIS_ADDR:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*HasFoo to $*@opened("4E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self -// CHECK: [[OPEN_ADDR:%.*]] = unchecked_addr_cast [[OPEN_EXIS_ADDR]] : $*@opened("4E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self to $*S1 +// CHECK: copy_addr [take] [[HASFOO]] to [initialization] [[EXIS]] : $*any HasFoo +// CHECK: [[OPEN_EXIS_ADDR:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*any HasFoo to $*@opened("4E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self +// CHECK: [[OPEN_ADDR:%.*]] = unchecked_addr_cast [[OPEN_EXIS_ADDR]] : $*@opened("4E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self to $*S1 // CHECK: [[F:%.*]] = function_ref @witnessS1 : $@convention(witness_method: HasFoo) (@in_guaranteed S1) -> () // CHECK: apply [[F]]([[OPEN_ADDR]]) : $@convention(witness_method: HasFoo) (@in_guaranteed S1) -> () // CHECK-LABEL: } // end sil function 'testSpecializedS1' @@ -91,18 +91,18 @@ bb6: // CHECK-LABEL: sil shared [noinline] @testSpecializedS1Negative : $@convention(thin) (S1) -> () { // CHECK: bb0(%0 : $S1): -// CHECK: [[EXIS:%.*]] = alloc_stack $HasFoo +// CHECK: [[EXIS:%.*]] = alloc_stack $any HasFoo // CHECK: [[VAL:%.*]] = alloc_stack $S1 // CHECK: store %0 to [[VAL]] : $*S1 -// CHECK: [[OPT:%.*]] = alloc_stack $Optional -// CHECK: [[IEDA:%.*]] = init_enum_data_addr [[OPT]] : $*Optional, #Optional.some!enumelt -// CHECK: checked_cast_addr_br take_always S1 in [[VAL]] : $*S1 to HasFoo in [[IEDA]] : $*HasFoo, bb1, bb2 +// CHECK: [[OPT:%.*]] = alloc_stack $Optional +// CHECK: [[IEDA:%.*]] = init_enum_data_addr [[OPT]] : $*Optional, #Optional.some!enumelt +// CHECK: checked_cast_addr_br take_always S1 in [[VAL]] : $*S1 to any HasFoo in [[IEDA]] : $*any HasFoo, bb1, bb2 // bbs... -// CHECK: [[UNWRAP:%.*]] = unchecked_take_enum_data_addr [[OPT]] : $*Optional, #Optional.some!enumelt -// CHECK: copy_addr [take] [[UNWRAP]] to [initialization] [[EXIS]] : $*HasFoo -// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*HasFoo to $*@opened("5E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self -// CHECK: [[WM:%.*]] = witness_method $@opened("5E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self, #HasFoo.foo : (Self) -> () -> (), [[OPEN]] : $*@opened("5E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self : $@convention(witness_method: HasFoo) <τ_0_0 where τ_0_0 : HasFoo> (@in_guaranteed τ_0_0) -> () -// CHECK: apply [[WM]]<@opened("5E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self>([[OPEN]]) : $@convention(witness_method: HasFoo) <τ_0_0 where τ_0_0 : HasFoo> (@in_guaranteed τ_0_0) -> () +// CHECK: [[UNWRAP:%.*]] = unchecked_take_enum_data_addr [[OPT]] : $*Optional, #Optional.some!enumelt +// CHECK: copy_addr [take] [[UNWRAP]] to [initialization] [[EXIS]] : $*any HasFoo +// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*any HasFoo to $*@opened("5E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self +// CHECK: [[WM:%.*]] = witness_method $@opened("5E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self, #HasFoo.foo : (Self) -> () -> (), [[OPEN]] : $*@opened("5E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self : $@convention(witness_method: HasFoo) <τ_0_0 where τ_0_0 : HasFoo> (@in_guaranteed τ_0_0) -> () +// CHECK: apply [[WM]]<@opened("5E16CBC0-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self>([[OPEN]]) : $@convention(witness_method: HasFoo) <τ_0_0 where τ_0_0 : HasFoo> (@in_guaranteed τ_0_0) -> () // CHECK-LABEL: } // end sil function 'testSpecializedS1Negative' sil shared [noinline] @testSpecializedS1Negative : $@convention(thin) (S1) -> () { bb0(%0 : $S1): @@ -163,15 +163,15 @@ struct IsP : P {} // CHECK-LABEL: sil shared [noinline] @testSpecializedS2 : $@convention(thin) (S2) -> () { // CHECK: bb0(%0 : $S2): -// CHECK: [[EXIS:%.*]] = alloc_stack $HasFoo +// CHECK: [[EXIS:%.*]] = alloc_stack $any HasFoo // CHECK: [[S2:%.*]] = alloc_stack $S2 // CHECK: store %0 to [[S2]] : $*S2 -// CHECK: [[HASFOO:%.*]] = alloc_stack $HasFoo -// CHECK: [[EXIS_ADDR:%.*]] = init_existential_addr [[HASFOO]] : $*HasFoo, $S2 +// CHECK: [[HASFOO:%.*]] = alloc_stack $any HasFoo +// CHECK: [[EXIS_ADDR:%.*]] = init_existential_addr [[HASFOO]] : $*any HasFoo, $S2 // CHECK: copy_addr [take] [[S2]] to [initialization] [[EXIS_ADDR]] : $*S2 -// CHECK: copy_addr [take] [[HASFOO]] to [initialization] [[EXIS]] : $*HasFoo -// CHECK: [[OPEN_EXIS_ADDR:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*HasFoo to $*@opened("4E16D1CE-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self -// CHECK: [[OPEN_ADDR:%.*]] = unchecked_addr_cast [[OPEN_EXIS_ADDR]] : $*@opened("4E16D1CE-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self to $*S2 +// CHECK: copy_addr [take] [[HASFOO]] to [initialization] [[EXIS]] : $*any HasFoo +// CHECK: [[OPEN_EXIS_ADDR:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*any HasFoo to $*@opened("4E16D1CE-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self +// CHECK: [[OPEN_ADDR:%.*]] = unchecked_addr_cast [[OPEN_EXIS_ADDR]] : $*@opened("4E16D1CE-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self to $*S2 // CHECK: [[F:%.*]] = function_ref @$s9witnessS24main3IsPV_Tg5 : $@convention(witness_method: HasFoo) (S2) -> () // CHECK: [[ARG:%.*]] = load [[OPEN_ADDR]] : $*S2 // CHECK: apply [[F]]([[ARG]]) : $@convention(witness_method: HasFoo) (S2) -> () @@ -235,15 +235,15 @@ extension S3 : HasFoo where T : AnyObject { // CHECK-LABEL: sil shared [noinline] @testSpecializedS3 : $@convention(thin) (S3) -> () { // CHECK: bb0(%0 : $S3): -// CHECK: [[EXIS:%.*]] = alloc_stack $HasFoo +// CHECK: [[EXIS:%.*]] = alloc_stack $any HasFoo // CHECK: [[S3:%.*]] = alloc_stack $S3 // CHECK: store %0 to [[S3]] : $*S3 -// CHECK: [[HASFOO:%.*]] = alloc_stack $HasFoo -// CHECK: [[EXIS_ADDR:%.*]] = init_existential_addr [[HASFOO]] : $*HasFoo, $S3 +// CHECK: [[HASFOO:%.*]] = alloc_stack $any HasFoo +// CHECK: [[EXIS_ADDR:%.*]] = init_existential_addr [[HASFOO]] : $*any HasFoo, $S3 // CHECK: copy_addr [take] [[S3]] to [initialization] [[EXIS_ADDR]] : $*S3 -// CHECK: copy_addr [take] [[HASFOO]] to [initialization] [[EXIS]] : $*HasFoo -// CHECK: [[OPEN_EXIS_ADDR:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*HasFoo to $*@opened("4E16D5E8-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self -// CHECK: [[OPEN_ADDR:%.*]] = unchecked_addr_cast [[OPEN_EXIS_ADDR]] : $*@opened("4E16D5E8-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self to $*S3 +// CHECK: copy_addr [take] [[HASFOO]] to [initialization] [[EXIS]] : $*any HasFoo +// CHECK: [[OPEN_EXIS_ADDR:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*any HasFoo to $*@opened("4E16D5E8-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self +// CHECK: [[OPEN_ADDR:%.*]] = unchecked_addr_cast [[OPEN_EXIS_ADDR]] : $*@opened("4E16D5E8-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self to $*S3 // CHECK: [[F:%.*]] = function_ref @$s9witnessS34main1CC_Tg5 : $@convention(witness_method: HasFoo) (S3) -> () // CHECK: [[ARG:%.*]] = load [[OPEN_ADDR]] : $*S3 // CHECK: apply [[F]]([[ARG]]) : $@convention(witness_method: HasFoo) (S3) -> () @@ -305,15 +305,15 @@ extension S4 : HasFoo where T : C { // CHECK-LABEL: sil shared [noinline] @testSpecializedS4 : $@convention(thin) (S4) -> () { // CHECK: bb0(%0 : $S4): -// CHECK: [[EXIS:%.*]] = alloc_stack $HasFoo +// CHECK: [[EXIS:%.*]] = alloc_stack $any HasFoo // CHECK: [[S3:%.*]] = alloc_stack $S4 // CHECK: store %0 to [[S3]] : $*S4 -// CHECK: [[HASFOO:%.*]] = alloc_stack $HasFoo -// CHECK: [[EXIS_ADDR:%.*]] = init_existential_addr [[HASFOO]] : $*HasFoo, $S4 +// CHECK: [[HASFOO:%.*]] = alloc_stack $any HasFoo +// CHECK: [[EXIS_ADDR:%.*]] = init_existential_addr [[HASFOO]] : $*any HasFoo, $S4 // CHECK: copy_addr [take] [[S3]] to [initialization] [[EXIS_ADDR]] : $*S4 -// CHECK: copy_addr [take] [[HASFOO]] to [initialization] [[EXIS]] : $*HasFoo -// CHECK: [[OPEN_EXIS_ADDR:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*HasFoo to $*@opened("4E16E402-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self -// CHECK: [[OPEN_ADDR:%.*]] = unchecked_addr_cast [[OPEN_EXIS_ADDR]] : $*@opened("4E16E402-FD9F-11E8-A311-D0817AD9F6DD", HasFoo) Self to $*S4 +// CHECK: copy_addr [take] [[HASFOO]] to [initialization] [[EXIS]] : $*any HasFoo +// CHECK: [[OPEN_EXIS_ADDR:%.*]] = open_existential_addr immutable_access [[EXIS]] : $*any HasFoo to $*@opened("4E16E402-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self +// CHECK: [[OPEN_ADDR:%.*]] = unchecked_addr_cast [[OPEN_EXIS_ADDR]] : $*@opened("4E16E402-FD9F-11E8-A311-D0817AD9F6DD", any HasFoo) Self to $*S4 // CHECK: [[F:%.*]] = function_ref @$s9witnessS44main4SubCC_Tg5 : $@convention(witness_method: HasFoo) (S4) -> () // CHECK: [[ARG:%.*]] = load [[OPEN_ADDR]] : $*S4 // CHECK: apply [[F]]([[ARG]]) : $@convention(witness_method: HasFoo) (S4) -> () diff --git a/test/SILOptimizer/castoptimizer-wrongscope.swift b/test/SILOptimizer/castoptimizer-wrongscope.swift index 4861589d6f85b..10d1d48bfb5e7 100644 --- a/test/SILOptimizer/castoptimizer-wrongscope.swift +++ b/test/SILOptimizer/castoptimizer-wrongscope.swift @@ -5,8 +5,8 @@ // RUN: -Xllvm -sil-print-after=diagnostic-constant-propagation \ // RUN: 2>&1 | %FileCheck %s -// CHECK: alloc_stack $R, loc {{.*}}, scope 2 -// CHECK-NEXT: init_existential_addr {{.*}} : $*R, $Float, loc {{.*}}, scope 2 +// CHECK: alloc_stack $any R, loc {{.*}}, scope 2 +// CHECK-NEXT: init_existential_addr {{.*}} : $*any R, $Float, loc {{.*}}, scope 2 // CHECK-NEXT: copy_addr [take] %8 to [initialization] {{.*}} : $*Float, loc {{.*}}, scope 2 protocol R {} diff --git a/test/SILOptimizer/closure_lifetime_fixup_objc.swift b/test/SILOptimizer/closure_lifetime_fixup_objc.swift index 9ffc3f950dddb..f7c2626ae81c7 100644 --- a/test/SILOptimizer/closure_lifetime_fixup_objc.swift +++ b/test/SILOptimizer/closure_lifetime_fixup_objc.swift @@ -14,8 +14,8 @@ public protocol DangerousEscaper { func malicious(_ mayActuallyEscape: () -> ()) } -// CHECK: sil @$s27closure_lifetime_fixup_objc19couldActuallyEscapeyyyyc_AA16DangerousEscaper_ptF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (), @guaranteed DangerousEscaper) -> () { -// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> (), [[SELF:%.*]] : $DangerousEscaper): +// CHECK: sil @$s27closure_lifetime_fixup_objc19couldActuallyEscapeyyyyc_AA16DangerousEscaper_ptF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (), @guaranteed any DangerousEscaper) -> () { +// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> (), [[SELF:%.*]] : $any DangerousEscaper): // CHECK: [[OE:%.*]] = open_existential_ref [[SELF]] // Extend the lifetime to the end of this function (2). @@ -43,8 +43,8 @@ public protocol DangerousEscaper { // CHECK: destroy_addr [[CLOSURE_ADDR]] : $*@callee_guaranteed () -> () // CHECK: dealloc_stack [[BLOCK_STORAGE]] : $*@block_storage @callee_guaranteed () -> () -// CHECK: [[METH:%.*]] = objc_method [[OE]] : $@opened("{{.*}}", DangerousEscaper) Self, #DangerousEscaper.malicious!foreign : (Self) -> (() -> ()) -> (), $@convention(objc_method) <τ_0_0 where τ_0_0 : DangerousEscaper> (@convention(block) @noescape () -> (), τ_0_0) -> () -// CHECK: apply [[METH]]<@opened("{{.*}}", DangerousEscaper) Self>([[BLOCK_COPY]], [[OE]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : DangerousEscaper> (@convention(block) @noescape () -> (), τ_0_0) -> () +// CHECK: [[METH:%.*]] = objc_method [[OE]] : $@opened("{{.*}}", any DangerousEscaper) Self, #DangerousEscaper.malicious!foreign : (Self) -> (() -> ()) -> (), $@convention(objc_method) <τ_0_0 where τ_0_0 : DangerousEscaper> (@convention(block) @noescape () -> (), τ_0_0) -> () +// CHECK: apply [[METH]]<@opened("{{.*}}", any DangerousEscaper) Self>([[BLOCK_COPY]], [[OE]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : DangerousEscaper> (@convention(block) @noescape () -> (), τ_0_0) -> () // Release sentinel closure copy (5). // CHECK: strong_release [[BLOCK_COPY]] : $@convention(block) @noescape () -> () @@ -64,7 +64,7 @@ public func couldActuallyEscape(_ closure: @escaping () -> (), _ villian: Danger // Make sure that we respect the ownership verifier. // -// CHECK-LABEL: sil @$s27closure_lifetime_fixup_objc27couldActuallyEscapeWithLoopyyyyc_AA16DangerousEscaper_ptF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (), @guaranteed DangerousEscaper) -> () { +// CHECK-LABEL: sil @$s27closure_lifetime_fixup_objc27couldActuallyEscapeWithLoopyyyyc_AA16DangerousEscaper_ptF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (), @guaranteed any DangerousEscaper) -> () { public func couldActuallyEscapeWithLoop(_ closure: @escaping () -> (), _ villian: DangerousEscaper) { for _ in 0..<2 { villian.malicious(closure) diff --git a/test/SILOptimizer/closure_specialize.sil b/test/SILOptimizer/closure_specialize.sil index e3bb8396af78b..cf0e04494457d 100644 --- a/test/SILOptimizer/closure_specialize.sil +++ b/test/SILOptimizer/closure_specialize.sil @@ -177,8 +177,8 @@ bb0(%0 : $@callee_owned (@owned A) -> ()): return %3 : $() } -// CHECK-LABEL: sil shared {{.*}} @$s17use_closure_throw{{.*}}Tf{{.*}} : $@convention(thin) (@owned A) -> @error Error { -sil hidden [noinline] @use_closure_throw : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> @error Error { +// CHECK-LABEL: sil shared {{.*}} @$s17use_closure_throw{{.*}}Tf{{.*}} : $@convention(thin) (@owned A) -> @error any Error { +sil hidden [noinline] @use_closure_throw : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> @error any Error { bb0(%0 : $@callee_owned (@owned A) -> ()): %1 = alloc_ref $A %2 = apply %0(%1) : $@callee_owned (@owned A) -> () @@ -395,7 +395,7 @@ bb3: // CHECK-NEXT: strong_release %0 // CHECK-NEXT: release_value %0 // CHECK-NEXT: br bb4 -// CHECK: bb3(%{{[0-9]+}} : $Error): +// CHECK: bb3(%{{[0-9]+}} : $any Error): // CHECK-NEXT: strong_release %0 // CHECK-NEXT: release_value %0 // CHECK-NEXT: br bb4 @@ -561,13 +561,13 @@ sil @testClosureConvertHelper : $(Int) -> () // specialized testClosureConvertThunk // FIXME: Need to handle closures with multiple exceptional exits. -// CHECK-LABEL: sil shared @$s23testClosureConvertThunk0abC6HelperSiTf1nc_n : $@convention(thin) (Int) -> (@out (), @error Error) { +// CHECK-LABEL: sil shared @$s23testClosureConvertThunk0abC6HelperSiTf1nc_n : $@convention(thin) (Int) -> (@out (), @error any Error) { // CHECK: bb0(%0 : $*(), %1 : $Int): // CHECK: [[F:%.*]] = function_ref @testClosureConvertHelper : $@convention(thin) (Int) -> () // CHECK: [[PA:%.*]] = partial_apply [[F]](%1) : $@convention(thin) (Int) -> () // CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_owned () -> () to $@noescape @callee_owned () -> () -// CHECK: [[CVT2:%.*]] = convert_function [[CVT1]] : $@noescape @callee_owned () -> () to $@noescape @callee_owned () -> @error Error -// CHECK: try_apply [[CVT2]]() : $@noescape @callee_owned () -> @error Error, normal bb1, error bb2 +// CHECK: [[CVT2:%.*]] = convert_function [[CVT1]] : $@noescape @callee_owned () -> () to $@noescape @callee_owned () -> @error any Error +// CHECK: try_apply [[CVT2]]() : $@noescape @callee_owned () -> @error any Error, normal bb1, error bb2 // CHECK: bb1 // CHECK: release_value [[PA]] // CHECK: return diff --git a/test/SILOptimizer/closure_specialize_consolidated.sil b/test/SILOptimizer/closure_specialize_consolidated.sil index 86e68f4fb40b5..99ce358a1f885 100644 --- a/test/SILOptimizer/closure_specialize_consolidated.sil +++ b/test/SILOptimizer/closure_specialize_consolidated.sil @@ -87,9 +87,9 @@ bb0(%0 : $@callee_owned () -> ()): // Check that a specialization of address_closure_noescape_user was generated which does not // take a closure as a parameter anymore. -// CHECK-LABEL: sil shared @{{.*}}address_closure_noescape_user{{.*}} : $@convention(thin) (@inout_aliasable P) -> () -// CHECK: function_ref @address_closure_existential : $@convention(thin) (@inout_aliasable P) -> () -// CHECK: partial_apply %{{.*}} : $@convention(thin) (@inout_aliasable P) -> () +// CHECK-LABEL: sil shared @{{.*}}address_closure_noescape_user{{.*}} : $@convention(thin) (@inout_aliasable any P) -> () +// CHECK: function_ref @address_closure_existential : $@convention(thin) (@inout_aliasable any P) -> () +// CHECK: partial_apply %{{.*}} : $@convention(thin) (@inout_aliasable any P) -> () // CHECK: apply // CHECK: return @@ -298,9 +298,9 @@ bb0(%0 : $*Q, %1 : $*Q, %2 : $*Q, %3 : $*Q): // Check that a specialization of address_closure_user_out_result was generated which does not // take a closure as a parameter anymore. -// CHECK-LABEL: sil shared @{{.*}}address_closure_user_out_result{{.*}} : $@convention(thin) (@inout_aliasable Q, @inout_aliasable Q) -> @out Q -// CHECK: function_ref @address_closure_out_result : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q -// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply %{{.*}} : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q +// CHECK-LABEL: sil shared @{{.*}}address_closure_user_out_result{{.*}} : $@convention(thin) (@inout_aliasable any Q, @inout_aliasable any Q) -> @out any Q +// CHECK: function_ref @address_closure_out_result : $@convention(thin) (@in any Q, @inout_aliasable any Q, @inout_aliasable any Q) -> @out any Q +// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply %{{.*}} : $@convention(thin) (@in any Q, @inout_aliasable any Q, @inout_aliasable any Q) -> @out any Q // CHECK: apply [[PARTIAL_APPLY]] // CHECK: return @@ -322,9 +322,9 @@ bb0(%0 : $*Q, %1 : $@noescape @callee_owned (@in Q) -> @out Q): // unsupported address type arguments (e.g. @in or @out), but the partial_apply has only // supported address type arguments, i.e. @inout or @inout_aliasable. // -// CHECK-LABEL: sil @address_caller_out_result : $@convention(thin) (@in Q, @in Q) -> @out Q +// CHECK-LABEL: sil @address_caller_out_result : $@convention(thin) (@in any Q, @in any Q) -> @out any Q // CHECK-NOT: partial_apply -// CHECK: [[SPECIALIZED_FN1:%.*]] = function_ref @{{.*}}address_closure_user_out_result{{.*}} : $@convention(thin) (@inout_aliasable Q, @inout_aliasable Q) -> @out Q +// CHECK: [[SPECIALIZED_FN1:%.*]] = function_ref @{{.*}}address_closure_user_out_result{{.*}} : $@convention(thin) (@inout_aliasable any Q, @inout_aliasable any Q) -> @out any Q // CHECK: apply [[SPECIALIZED_FN1]]{{.*}} // CHECK-NOT: partial_apply // CHECK: return @@ -343,8 +343,8 @@ bb0(%0 : $*Q, %1 : $*Q, %2 : $*Q): // CHECK-LABEL: sil @address_caller_existential // CHECK-NOT: partial_apply -// CHECK: [[SPECIALIZED_FN1:%.*]] = function_ref @{{.*}}address_closure_noescape_user{{.*}} : $@convention(thin) (@inout_aliasable P) -> () -// CHECK: [[SPECIALIZED_FN2:%.*]] = function_ref @{{.*}}address_closure_noescape_user{{.*}} : $@convention(thin) (@inout_aliasable P) -> () +// CHECK: [[SPECIALIZED_FN1:%.*]] = function_ref @{{.*}}address_closure_noescape_user{{.*}} : $@convention(thin) (@inout_aliasable any P) -> () +// CHECK: [[SPECIALIZED_FN2:%.*]] = function_ref @{{.*}}address_closure_noescape_user{{.*}} : $@convention(thin) (@inout_aliasable any P) -> () // CHECK: apply [[SPECIALIZED_FN2]]{{.*}} // CHECK: apply [[SPECIALIZED_FN1]]{{.*}} // CHECK-NOT: partial_apply @@ -564,8 +564,8 @@ bb0(%0 : $@callee_owned (Builtin.NativeObject, Builtin.Int32, @owned Builtin.Nat release_value %3 : $Builtin.NativeObject throw %5 : $Error } -// CHECK-LABEL: sil @thin_thick_and_partial_apply_test : $@convention(thin) (Builtin.NativeObject, Builtin.Int32, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject, @owned Error) -> () { -// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $Builtin.Int32, [[ARG2:%.*]] : $Builtin.NativeObject, [[ARG3:%.*]] : $Builtin.NativeObject, [[ARG4:%.*]] : $Error): +// CHECK-LABEL: sil @thin_thick_and_partial_apply_test : $@convention(thin) (Builtin.NativeObject, Builtin.Int32, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject, @owned any Error) -> () { +// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $Builtin.Int32, [[ARG2:%.*]] : $Builtin.NativeObject, [[ARG3:%.*]] : $Builtin.NativeObject, [[ARG4:%.*]] : $any Error): // CHECK: [[OLD_CLOSURE_CALLEE1:%.*]] = function_ref @large_closure_callee // CHECK: [[OLD_CLOSURE_CALLEE2:%.*]] = function_ref @small_closure_callee // CHECK: retain_value [[ARG0]] : $Builtin.NativeObject @@ -600,8 +600,8 @@ bb0(%0 : $@callee_owned (Builtin.NativeObject, Builtin.Int32, @owned Builtin.Nat // CHECK-NEXT: release_value [[DEAD_CLOSURE_1]] // CHECK-NOT: release_value [[DEAD_CLOSURE_2]] -// REMOVECLOSURES-LABEL: sil @thin_thick_and_partial_apply_test : $@convention(thin) (Builtin.NativeObject, Builtin.Int32, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject, @owned Error) -> () { -// REMOVECLOSURES: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $Builtin.Int32, [[ARG2:%.*]] : $Builtin.NativeObject, [[ARG3:%.*]] : $Builtin.NativeObject, [[ARG4:%.*]] : $Error): +// REMOVECLOSURES-LABEL: sil @thin_thick_and_partial_apply_test : $@convention(thin) (Builtin.NativeObject, Builtin.Int32, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject, @owned any Error) -> () { +// REMOVECLOSURES: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $Builtin.Int32, [[ARG2:%.*]] : $Builtin.NativeObject, [[ARG3:%.*]] : $Builtin.NativeObject, [[ARG4:%.*]] : $any Error): // REMOVECLOSURES: [[OLD_CLOSURE_CALLEE1:%.*]] = function_ref @large_closure_callee // REMOVECLOSURES: [[OLD_CLOSURE_CALLEE2:%.*]] = function_ref @small_closure_callee // REMOVECLOSURES: retain_value [[ARG0]] : $Builtin.NativeObject @@ -669,7 +669,7 @@ bb4: // Make sure we do not try to specialize a closure if we are not closing over a // direct function ref. -// CHECK-LABEL: @$s4test3barSiAA1P_p_SitF : $@convention(thin) (@in P, Int32) -> Int32 { +// CHECK-LABEL: @$s4test3barSiAA1P_p_SitF : $@convention(thin) (@in any P, Int32) -> Int32 { // CHECK: partial_apply // CHECK: apply sil [noinline] @$s4test3barSiAA1P_p_SitF : $@convention(thin) (@in P, Int32) -> Int32 { diff --git a/test/SILOptimizer/constant_propagation.sil b/test/SILOptimizer/constant_propagation.sil index 33aa4c65d5c15..666ea9424ccdf 100644 --- a/test/SILOptimizer/constant_propagation.sil +++ b/test/SILOptimizer/constant_propagation.sil @@ -906,10 +906,10 @@ bb0(%0 : $*MyError, %1 : $*E2): // Check casts to Error. // CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_error_existential // CHECK-NOT: unconditional_checked_cast_addr -// CHECK: [[ALLOC_BOX:%.*]] = alloc_existential_box $Error, $E1 -// CHECK: [[PROJ:%.*]] = project_existential_box $E1 in [[ALLOC_BOX]] : $Error +// CHECK: [[ALLOC_BOX:%.*]] = alloc_existential_box $any Error, $E1 +// CHECK: [[PROJ:%.*]] = project_existential_box $E1 in [[ALLOC_BOX]] : $any Error // CHECK: copy_addr [take] %1 to [initialization] [[PROJ]] -// CHECK: store [[ALLOC_BOX]] to %0 : $*Error +// CHECK: store [[ALLOC_BOX]] to %0 : $*any Error // CHECK: return sil @replace_unconditional_check_cast_addr_for_type_to_error_existential : $@convention(thin) (@in E1) -> (@out Error) { bb0(%0 : $*Error, %1 : $*E1): diff --git a/test/SILOptimizer/constant_propagation_ownership.sil b/test/SILOptimizer/constant_propagation_ownership.sil index da99f795b0afe..3abfd2f0aec72 100644 --- a/test/SILOptimizer/constant_propagation_ownership.sil +++ b/test/SILOptimizer/constant_propagation_ownership.sil @@ -1076,10 +1076,10 @@ bb0(%0 : $*MyError, %1 : $*E2): // Check casts to Error. // CHECK-LABEL: sil [ossa] @replace_unconditional_check_cast_addr_for_type_to_error_existential // CHECK-NOT: unconditional_checked_cast_addr -// CHECK: [[ALLOC_BOX:%.*]] = alloc_existential_box $Error, $E1 -// CHECK: [[PROJ:%.*]] = project_existential_box $E1 in [[ALLOC_BOX]] : $Error +// CHECK: [[ALLOC_BOX:%.*]] = alloc_existential_box $any Error, $E1 +// CHECK: [[PROJ:%.*]] = project_existential_box $E1 in [[ALLOC_BOX]] : $any Error // CHECK: copy_addr [take] %1 to [initialization] [[PROJ]] -// CHECK: store [[ALLOC_BOX]] to [init] %0 : $*Error +// CHECK: store [[ALLOC_BOX]] to [init] %0 : $*any Error // CHECK: return sil [ossa] @replace_unconditional_check_cast_addr_for_type_to_error_existential : $@convention(thin) (@in E1) -> (@out Error) { bb0(%0 : $*Error, %1 : $*E1): @@ -1088,7 +1088,7 @@ bb0(%0 : $*Error, %1 : $*E1): return %2 : $() } -// CHECK-LABEL: sil [ossa] @always_fail_protocolmeta_to_concretemeta_checkedcastbr : $@convention(thin) (@thin P.Protocol) -> Builtin.Int1 { +// CHECK-LABEL: sil [ossa] @always_fail_protocolmeta_to_concretemeta_checkedcastbr : $@convention(thin) (@thin (any P).Type) -> Builtin.Int1 { // CHECK: bb0( // CHECK-NEXT: metatype // CHECK-NEXT: br bb2 diff --git a/test/SILOptimizer/copy_propagation_borrow.sil b/test/SILOptimizer/copy_propagation_borrow.sil index 3e132e12f8e24..ebfebe3b940d8 100644 --- a/test/SILOptimizer/copy_propagation_borrow.sil +++ b/test/SILOptimizer/copy_propagation_borrow.sil @@ -1221,19 +1221,19 @@ bb0(%0 : @guaranteed $C): // // CHECK-NOSCOPES-LABEL: sil [ossa] @testEscapingEscapingCast : $@convention(method) (@guaranteed @callee_guaranteed (Int64) -> Int64) -> () { // CHECK-NOSCOPES: bb0(%0 : @guaranteed $@callee_guaranteed (Int64) -> Int64): -// CHECK-NOSCOPES-NEXT: %1 = convert_function %0 : $@callee_guaranteed (Int64) -> Int64 to $@callee_guaranteed (Int64) -> (Int64, @error Error) // user: %2 -// CHECK-NOSCOPES-NEXT: %2 = convert_escape_to_noescape %1 : $@callee_guaranteed (Int64) -> (Int64, @error Error) to $@noescape @callee_guaranteed (Int64) -> (Int64, @error Error) +// CHECK-NOSCOPES-NEXT: %1 = convert_function %0 : $@callee_guaranteed (Int64) -> Int64 to $@callee_guaranteed (Int64) -> (Int64, @error any Error) // user: %2 +// CHECK-NOSCOPES-NEXT: %2 = convert_escape_to_noescape %1 : $@callee_guaranteed (Int64) -> (Int64, @error any Error) to $@noescape @callee_guaranteed (Int64) -> (Int64, @error any Error) // CHECK-NOSCOPES-NEXT: = tuple () // CHECK-NOSCOPES-NEXT: return // CHECK-NOSCOPES-LABEL: } // end sil function 'testEscapingEscapingCast' sil [ossa] @testEscapingEscapingCast : $@convention(method) (@guaranteed @callee_guaranteed (Int64) -> Int64) -> () { bb0(%0 : @guaranteed $@callee_guaranteed (Int64) -> Int64): %1 = copy_value %0 : $@callee_guaranteed (Int64) -> Int64 - %2 = convert_function %1 : $@callee_guaranteed (Int64) -> Int64 to $@callee_guaranteed (Int64) -> (Int64, @error Error) - %3 = copy_value %2 : $@callee_guaranteed (Int64) -> (Int64, @error Error) - %4 = convert_escape_to_noescape %3 : $@callee_guaranteed (Int64) -> (Int64, @error Error) to $@noescape @callee_guaranteed (Int64) -> (Int64, @error Error) // user: %29 - destroy_value %3 : $@callee_guaranteed (Int64) -> (Int64, @error Error) - destroy_value %2 : $@callee_guaranteed (Int64) -> (Int64, @error Error) + %2 = convert_function %1 : $@callee_guaranteed (Int64) -> Int64 to $@callee_guaranteed (Int64) -> (Int64, @error any Error) + %3 = copy_value %2 : $@callee_guaranteed (Int64) -> (Int64, @error any Error) + %4 = convert_escape_to_noescape %3 : $@callee_guaranteed (Int64) -> (Int64, @error any Error) to $@noescape @callee_guaranteed (Int64) -> (Int64, @error any Error) // user: %29 + destroy_value %3 : $@callee_guaranteed (Int64) -> (Int64, @error any Error) + destroy_value %2 : $@callee_guaranteed (Int64) -> (Int64, @error any Error) %7 = tuple () return %7 : $() } diff --git a/test/SILOptimizer/copy_propagation_opaque.sil b/test/SILOptimizer/copy_propagation_opaque.sil index 8fda26d12dfcf..2945716659d39 100644 --- a/test/SILOptimizer/copy_propagation_opaque.sil +++ b/test/SILOptimizer/copy_propagation_opaque.sil @@ -464,14 +464,14 @@ sil @testThrows : $@convention(thin) <τ_0_0> (τ_0_0) -> (@error Error) // CHECK-LABEL: sil [ossa] @testTryApply : {{.*}} { // CHECK: bb0: // CHECK: [[INSTANCE:%[^,]+]] = apply -// CHECK: function_ref @testThrows : $@convention(thin) <τ_0_0> (τ_0_0) -> @error Error -// CHECK: try_apply %{{.*}}([[INSTANCE]]) : $@convention(thin) <τ_0_0> (τ_0_0) -> @error Error, normal bb1, error bb2 +// CHECK: function_ref @testThrows : $@convention(thin) <τ_0_0> (τ_0_0) -> @error any Error +// CHECK: try_apply %{{.*}}([[INSTANCE]]) : $@convention(thin) <τ_0_0> (τ_0_0) -> @error any Error, normal bb1, error bb2 // CHECK: bb1({{%[^,]+}} : $()): // CHECK: destroy_value [[INSTANCE]] : $T // CHECK: br bb3 -// CHECK: bb2(%{{.*}} : @owned $Error): +// CHECK: bb2(%{{.*}} : @owned $any Error): // CHECK: destroy_value [[INSTANCE]] : $T -// CHECK: destroy_value %{{.*}} : $Error +// CHECK: destroy_value %{{.*}} : $any Error // CHECK: br bb3 // CHECK: bb3: // CHECK-NOT: destroy @@ -511,16 +511,16 @@ sil @takeClosure : $@convention(thin) (@noescape @callee_guaranteed @substit // CHECK-LABEL: sil [ossa] @testConvertFunction : $@convention(thin) (@in_guaranteed T) -> @owned AnyObject { // CHECK: bb0(%0 : @guaranteed $T): // CHECK: [[CLOSURE:%.*]] = apply %{{.*}}(%{{.*}}) : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> @owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> Bool for <τ_0_0, τ_0_0> -// CHECK: [[CONVERT:%.*]] = convert_function [[CLOSURE]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> Bool for to $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error Error) for -// CHECK: [[COPY:%.*]] = copy_value [[CONVERT]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error Error) for -// CHECK: [[NOESCAPE:%.*]] = convert_escape_to_noescape [[COPY]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error Error) for to $@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error Error) for -// CHECK: try_apply %{{.*}}([[NOESCAPE]]) : $@convention(thin) <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error Error) for <τ_0_0, τ_0_0>) -> (@owned AnyObject, @error Error), normal bb1, error bb2 +// CHECK: [[CONVERT:%.*]] = convert_function [[CLOSURE]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> Bool for to $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for +// CHECK: [[COPY:%.*]] = copy_value [[CONVERT]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for +// CHECK: [[NOESCAPE:%.*]] = convert_escape_to_noescape [[COPY]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for to $@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for +// CHECK: try_apply %{{.*}}([[NOESCAPE]]) : $@convention(thin) <τ_0_0> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for <τ_0_0, τ_0_0>) -> (@owned AnyObject, @error any Error), normal bb1, error bb2 // CHECK: bb1 -// CHECK: destroy_value [[COPY]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error Error) for -// CHECK: destroy_value [[CONVERT]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error Error) for +// CHECK: destroy_value [[COPY]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for +// CHECK: destroy_value [[CONVERT]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for // CHECK: return // CHECK: bb2 -// CHECK: destroy_value [[COPY]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error Error) for +// CHECK: destroy_value [[COPY]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for // CHECK: unreachable // CHECK-LABEL: } // end sil function 'testConvertFunction' sil [ossa] @testConvertFunction : $@convention(thin) (@in_guaranteed T) -> @owned AnyObject { diff --git a/test/SILOptimizer/cross-module-optimization.swift b/test/SILOptimizer/cross-module-optimization.swift index 061bd887f96ca..8000614b1fe38 100644 --- a/test/SILOptimizer/cross-module-optimization.swift +++ b/test/SILOptimizer/cross-module-optimization.swift @@ -66,11 +66,11 @@ func testClass() { func testError() { // CHECK-OUTPUT: PrivateError() // CHECK-SIL2: struct $PrivateError () - // CHECK-SIL2: alloc_existential_box $Error, $PrivateError + // CHECK-SIL2: alloc_existential_box $any Error, $PrivateError print(returnPrivateError(27)) // CHECK-OUTPUT: InternalError() // CHECK-SIL2: struct $InternalError () - // CHECK-SIL2: alloc_existential_box $Error, $InternalError + // CHECK-SIL2: alloc_existential_box $any Error, $InternalError print(returnInternalError(27)) // CHECK-SIL2: } // end sil function '$s4Main9testErroryyF' } diff --git a/test/SILOptimizer/cse.sil b/test/SILOptimizer/cse.sil index 4563cdd499912..49c9d97c605b5 100644 --- a/test/SILOptimizer/cse.sil +++ b/test/SILOptimizer/cse.sil @@ -1049,7 +1049,7 @@ bb0(%0 : $*Airplane): } // CHECK-LABEL: _TF2p28trytoflyFPS_7Flyable_T_ -// CHECK: bb0(%0 : $*Flyable): +// CHECK: bb0(%0 : $*any Flyable): // CHECK-NEXT: open_existential_addr // CHECK-NEXT: witness_method // CHECK-NEXT: apply @@ -1090,12 +1090,12 @@ sil_witness_table hidden Airplane: Flyable module p2 { protocol Pingable { func ping() } // CHECK-LABEL: CSE_Existential_Simple -// CHECK: open_existential_addr immutable_access %0 : $*Pingable to $*@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) -// CHECK: witness_method $@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self, #Pingable.ping : {{.*}}, %2 -// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self>(%2) +// CHECK: open_existential_addr immutable_access %0 : $*any Pingable to $*@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) +// CHECK: witness_method $@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self, #Pingable.ping : {{.*}}, %2 +// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self>(%2) // CHECK: open_existential_addr immutable_access // CHECK: witness_method -// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self>(%2) +// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self>(%2) // CHECK: return sil hidden @CSE_Existential_Simple : $@convention(thin) (@in Pingable) -> () { bb0(%0 : $*Pingable): @@ -1119,7 +1119,7 @@ bb0(%0 : $*Pingable, %1 : $Int): %4 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self // users: %5, %6 %5 = witness_method $@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %4 : $*@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () // user: %6 - // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) + // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4) %6 = apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () %7 = integer_literal $Builtin.Int64, 3 // user: %9 %8 = integer_literal $Builtin.Int64, 3 // user: %9 @@ -1130,7 +1130,7 @@ bb1: // Preds: bb0 %11 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self // users: %12, %13 %12 = witness_method $@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %11 : $*@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () // user: %13 - // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) + // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4) %13 = apply %12<@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self>(%11) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () br bb2 // id: %14 @@ -1138,7 +1138,7 @@ bb2: // Preds: bb0 bb1 %15 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self // users: %16, %17 %16 = witness_method $@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %15 : $*@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () // user: %17 - // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) + // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4) %17 = apply %16<@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self>(%15) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () destroy_addr %0 : $*Pingable // id: %18 %19 = tuple () // user: %20 @@ -1169,14 +1169,14 @@ protocol Proto : class { // Check that all open_existential_ref instructions are CSEd // Any reference to the $@opened("1B685052-4796-11E6-B7DF-B8E856428C60", Proto) Self should be replaced by // references to $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", Proto) Self. -// CHECK-LABEL: sil @cse_open_existential : $@convention(thin) (@guaranteed Proto, Bool) -> () +// CHECK-LABEL: sil @cse_open_existential : $@convention(thin) (@guaranteed any Proto, Bool) -> () // CHECK: bb0 -// CHECK: %[[OPENED_EXISTENTIAL:[0-9]+]] = open_existential_ref %{{[0-9]+}} : $Proto to $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", Proto) Self -// CHECK: %[[WM1:[0-9]+]] = witness_method $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", Proto) Self, #Proto.doThis +// CHECK: %[[OPENED_EXISTENTIAL:[0-9]+]] = open_existential_ref %{{[0-9]+}} : $any Proto to $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", any Proto) Self +// CHECK: %[[WM1:[0-9]+]] = witness_method $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", any Proto) Self, #Proto.doThis // CHECK: apply %[[WM1]]{{.*}}(%[[OPENED_EXISTENTIAL]]) // CHECK: cond_br // CHECK: bb1: -// CHECK-NEXT: %[[WM2:[0-9]+]] = witness_method $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", Proto) Self, #Proto.doThat +// CHECK-NEXT: %[[WM2:[0-9]+]] = witness_method $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", any Proto) Self, #Proto.doThat // CHECK-NEXT: apply %[[WM2]]{{.*}}(%[[OPENED_EXISTENTIAL]]) // CHECK-NOT: 1B6851A6-4796-11E6-B7DF-B8E856428C60 // CHECK: br bb @@ -1294,9 +1294,9 @@ protocol SomeP {} public enum SpecialEnum : SomeP {} // CHECK-LABEL: sil @testCSEInitExistentialMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool { -// CHECK: [[EMT:%.*]] = init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type +// CHECK: [[EMT:%.*]] = init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick any Any.Type // CHECK-NOT: init_existential_metatype -// CHECK: builtin "is_same_metatype"([[EMT]] : $@thick Any.Type, [[EMT]] : $@thick Any.Type) : $Builtin.Int1 +// CHECK: builtin "is_same_metatype"([[EMT]] : $@thick any Any.Type, [[EMT]] : $@thick any Any.Type) : $Builtin.Int1 // CHECK-LABEL: } // end sil function 'testCSEInitExistentialMetatype' sil @testCSEInitExistentialMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool { bb0(%0 : $@thick SpecialEnum.Type): diff --git a/test/SILOptimizer/cse_metatype_conformance.swift b/test/SILOptimizer/cse_metatype_conformance.swift index 8f678eda7046d..6770d16c5c92d 100644 --- a/test/SILOptimizer/cse_metatype_conformance.swift +++ b/test/SILOptimizer/cse_metatype_conformance.swift @@ -20,12 +20,12 @@ func callFoo(ptype: P.Type) { // CHECK-LABEL: sil @$s24cse_metatype_conformance15testConformanceyyF : $@convention(thin) () -> () { // CHECK: [[MT:%.*]] = metatype $@thick A.Type -// CHECK: [[MTB:%.*]] = init_existential_metatype %0 : $@thick A.Type, $@thick P.Type -// CHECK: [[F:%.*]] = function_ref @$s24cse_metatype_conformance7callFoo5ptypey4moda1P_pXp_tF : $@convention(thin) (@thick P.Type) -> () -// CHECK: apply [[F]]([[MTB]]) : $@convention(thin) (@thick P.Type) -> () -// CHECK: apply [[F]]([[MTB]]) : $@convention(thin) (@thick P.Type) -> () -// CHECK: [[MTC:%.*]] = init_existential_metatype %0 : $@thick A.Type, $@thick P.Type -// CHECK: apply [[F]]([[MTC]]) : $@convention(thin) (@thick P.Type) -> () +// CHECK: [[MTB:%.*]] = init_existential_metatype %0 : $@thick A.Type, $@thick any P.Type +// CHECK: [[F:%.*]] = function_ref @$s24cse_metatype_conformance7callFoo5ptypey4moda1P_pXp_tF : $@convention(thin) (@thick any P.Type) -> () +// CHECK: apply [[F]]([[MTB]]) : $@convention(thin) (@thick any P.Type) -> () +// CHECK: apply [[F]]([[MTB]]) : $@convention(thin) (@thick any P.Type) -> () +// CHECK: [[MTC:%.*]] = init_existential_metatype %0 : $@thick A.Type, $@thick any P.Type +// CHECK: apply [[F]]([[MTC]]) : $@convention(thin) (@thick any P.Type) -> () // CHECK-LABEL: } // end sil function '$s24cse_metatype_conformance15testConformanceyyF' public func testConformance() { let ptb1: P.Type = getPFromB() diff --git a/test/SILOptimizer/cse_objc.sil b/test/SILOptimizer/cse_objc.sil index c86e46d8697cf..0324b6464eae3 100644 --- a/test/SILOptimizer/cse_objc.sil +++ b/test/SILOptimizer/cse_objc.sil @@ -97,7 +97,7 @@ bb0(%0 : $Bar): } // CHECK-LABEL: _TF4test9trytowalkFPS_8Walkable_T_ -// CHECK: bb0(%0 : $Walkable): +// CHECK: bb0(%0 : $any Walkable): // CHECK-NEXT: {{%.*}} = open_existential_ref // CHECK-NEXT: {{%.*}} = objc_method // CHECK-NEXT: {{%.*}} = apply @@ -198,9 +198,9 @@ class B {} // CHECK-LABEL: sil @nocse_existential_metatype_addr // CHECK: store -// CHECK: existential_metatype $@thick Any.Type +// CHECK: existential_metatype $@thick any Any.Type // CHECK: store -// CHECK: existential_metatype $@thick Any.Type +// CHECK: existential_metatype $@thick any Any.Type // CHECK: return sil @nocse_existential_metatype_addr : $@convention(thin) (@owned B, @owned B) -> (@thick Any.Type, @thick Any.Type) { bb0(%0 : $B, %1 : $B): diff --git a/test/SILOptimizer/cse_objc_ossa.sil b/test/SILOptimizer/cse_objc_ossa.sil index d27b80e778ca0..63491a212f7c6 100644 --- a/test/SILOptimizer/cse_objc_ossa.sil +++ b/test/SILOptimizer/cse_objc_ossa.sil @@ -91,7 +91,7 @@ bb0(%0 : @owned $Bar): } // CHECK-LABEL: sil hidden [ossa] @_TF4test9trytowalkFPS_8Walkable_T_ : -// CHECK: bb0(%0 : @owned $Walkable): +// CHECK: bb0(%0 : @owned $any Walkable): // CHECK-NEXT: {{%.*}} = open_existential_ref // CHECK-NEXT: {{%.*}} = objc_method // CHECK-NEXT: {{%.*}} = apply @@ -247,9 +247,9 @@ class B {} // CHECK-LABEL: sil [ossa] @nocse_existential_metatype_addr : // CHECK: store -// CHECK: existential_metatype $@thick Any.Type +// CHECK: existential_metatype $@thick any Any.Type // CHECK: store -// CHECK: existential_metatype $@thick Any.Type +// CHECK: existential_metatype $@thick any Any.Type // CHECK-LABEL: } // end sil function 'nocse_existential_metatype_addr' sil [ossa] @nocse_existential_metatype_addr : $@convention(thin) (@owned B, @owned B) -> (@thick Any.Type, @thick Any.Type) { bb0(%0 : @owned $B, %1 : @owned $B): diff --git a/test/SILOptimizer/cse_ossa.sil b/test/SILOptimizer/cse_ossa.sil index 4c38a418bc3f0..792e37bfa21bc 100644 --- a/test/SILOptimizer/cse_ossa.sil +++ b/test/SILOptimizer/cse_ossa.sil @@ -951,7 +951,7 @@ bb0(%0 : $*Airplane): } // CHECK-LABEL: sil hidden [ossa] @_TF2p28trytoflyFPS_7Flyable_T_ : -// CHECK: bb0(%0 : $*Flyable): +// CHECK: bb0(%0 : $*any Flyable): // CHECK-NEXT: open_existential_addr // CHECK-NEXT: witness_method // CHECK-NEXT: apply @@ -992,12 +992,12 @@ sil_witness_table hidden Airplane: Flyable module p2 { protocol Pingable { func ping() } // CHECK-LABEL: sil hidden [ossa] @CSE_Existential_Simple : -// CHECK: open_existential_addr immutable_access %0 : $*Pingable to $*@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) -// CHECK: witness_method $@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self, #Pingable.ping : {{.*}}, %2 -// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self>(%2) +// CHECK: open_existential_addr immutable_access %0 : $*any Pingable to $*@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) +// CHECK: witness_method $@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self, #Pingable.ping : {{.*}}, %2 +// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self>(%2) // CHECK: open_existential_addr immutable_access // CHECK: witness_method -// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self>(%2) +// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self>(%2) // CHECK-LABEL: } // end sil function 'CSE_Existential_Simple' sil hidden [ossa] @CSE_Existential_Simple : $@convention(thin) (@in Pingable) -> () { bb0(%0 : $*Pingable): @@ -1021,7 +1021,7 @@ bb0(%0 : $*Pingable, %1 : $Int): %4 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self %5 = witness_method $@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %4 : $*@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () - // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) + // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4) %6 = apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () %7 = integer_literal $Builtin.Int64, 3 %8 = integer_literal $Builtin.Int64, 3 @@ -1032,7 +1032,7 @@ bb1: %11 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self %12 = witness_method $@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %11 : $*@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () - // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) + // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4) %13 = apply %12<@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self>(%11) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () br bb3 @@ -1043,7 +1043,7 @@ bb3: %15 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self %16 = witness_method $@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %15 : $*@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () - // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) + // CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4) %17 = apply %16<@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self>(%15) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> () destroy_addr %0 : $*Pingable %19 = tuple () @@ -1121,9 +1121,9 @@ protocol SomeP {} public enum SpecialEnum : SomeP {} // CHECK-LABEL: sil [ossa] @testCSEInitExistentialMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool { -// CHECK: [[EMT:%.*]] = init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type +// CHECK: [[EMT:%.*]] = init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick any Any.Type // CHECK-NOT: init_existential_metatype -// CHECK: builtin "is_same_metatype"([[EMT]] : $@thick Any.Type, [[EMT]] : $@thick Any.Type) : $Builtin.Int1 +// CHECK: builtin "is_same_metatype"([[EMT]] : $@thick any Any.Type, [[EMT]] : $@thick any Any.Type) : $Builtin.Int1 // CHECK-LABEL: } // end sil function 'testCSEInitExistentialMetatype' sil [ossa] @testCSEInitExistentialMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool { bb0(%0 : $@thick SpecialEnum.Type): diff --git a/test/SILOptimizer/dead_code_elimination_nontrivial_ossa.sil b/test/SILOptimizer/dead_code_elimination_nontrivial_ossa.sil index 4ac9e14cb27f8..91c1c32645a99 100644 --- a/test/SILOptimizer/dead_code_elimination_nontrivial_ossa.sil +++ b/test/SILOptimizer/dead_code_elimination_nontrivial_ossa.sil @@ -23,7 +23,7 @@ case none case some(T) } -sil [ossa] @$testtryapplyklassgen : $@convention(thin) () -> (@owned Klass, @error Error) +sil [ossa] @$testtryapplyklassgen : $@convention(thin) () -> (@owned Klass, @error any Error) sil [ossa] @$use_klass1 : $@convention(thin) (@owned Klass) -> () sil [ossa] @$use_klass2 : $@convention(thin) (@guaranteed Klass) -> () sil [ossa] @$use_nontrivialstruct1 : $@convention(thin) (@owned NonTrivialStruct) -> () @@ -96,10 +96,10 @@ bb1(%2 : @guaranteed $Klass): // CHECK-LABEL: sil [ossa] @dce_dontoptarg3 : // CHECK: destroy_value // CHECK-LABEL: } // end sil function 'dce_dontoptarg3' -sil [ossa] @dce_dontoptarg3 : $@convention(thin) (@guaranteed Klass) -> @error Error { +sil [ossa] @dce_dontoptarg3 : $@convention(thin) (@guaranteed Klass) -> @error any Error { bb0(%0 : @guaranteed $Klass): - %2 = function_ref @$testtryapplyklassgen : $@convention(thin) () -> (@owned Klass, @error Error) - try_apply %2() : $@convention(thin) () -> (@owned Klass, @error Error), normal bb1, error bb2 + %2 = function_ref @$testtryapplyklassgen : $@convention(thin) () -> (@owned Klass, @error any Error) + try_apply %2() : $@convention(thin) () -> (@owned Klass, @error any Error), normal bb1, error bb2 bb1(%3 : @owned $Klass): destroy_value %3 : $Klass @@ -308,10 +308,10 @@ bb0(%0 : @owned $Klass): // CHECK-NEXT: destroy_value %3 // CHECK-NEXT: br bb3 // CHECK-LABEL: } // end sil function 'dce_insertdestroy2' -sil [ossa] @dce_insertdestroy2 : $@convention(thin) (@guaranteed Klass) -> @error Error { +sil [ossa] @dce_insertdestroy2 : $@convention(thin) (@guaranteed Klass) -> @error any Error { bb0(%0 : @guaranteed $Klass): - %2 = function_ref @$testtryapplyklassgen : $@convention(thin) () -> (@owned Klass, @error Error) - try_apply %2() : $@convention(thin) () -> (@owned Klass, @error Error), normal bb1, error bb2 + %2 = function_ref @$testtryapplyklassgen : $@convention(thin) () -> (@owned Klass, @error any Error) + try_apply %2() : $@convention(thin) () -> (@owned Klass, @error any Error), normal bb1, error bb2 bb1(%3 : @owned $Klass): br bb3(%3 : $Klass) diff --git a/test/SILOptimizer/definite-init-wrongscope.swift b/test/SILOptimizer/definite-init-wrongscope.swift index 4d8bbd05e79ef..b3a318b668ef4 100644 --- a/test/SILOptimizer/definite-init-wrongscope.swift +++ b/test/SILOptimizer/definite-init-wrongscope.swift @@ -28,7 +28,7 @@ public class M { // Make sure the expanded sequence gets the right scope. -// CHECK-LABEL: sil [ossa] @$s3del1MC4fromAcA12WithDelegate_p_tKcfc : $@convention(method) (@in WithDelegate, @owned M) -> (@owned M, @error Error) +// CHECK-LABEL: sil [ossa] @$s3del1MC4fromAcA12WithDelegate_p_tKcfc : $@convention(method) (@in any WithDelegate, @owned M) -> (@owned M, @error any Error) // CHECK: [[I:%.*]] = integer_literal $Builtin.Int2, 1, loc {{.*}}:20:12, scope 6 // CHECK: [[V:%.*]] = load [trivial] %2 : $*Builtin.Int2, loc {{.*}}:20:12, scope 6 @@ -38,10 +38,10 @@ public class M { // Make sure the dealloc_stack gets the same scope of the instructions surrounding it. -// CHECK: destroy_addr %0 : $*WithDelegate, loc {{.*}}:26:5, scope 6 +// CHECK: destroy_addr %0 : $*any WithDelegate, loc {{.*}}:26:5, scope 6 // CHECK-NEXT: dealloc_stack %2 : $*Builtin.Int2, loc {{.*}}:20:12, scope 6 -// CHECK: destroy_addr %0 : $*WithDelegate, loc {{.*}}:26:5, scope 6 +// CHECK: destroy_addr %0 : $*any WithDelegate, loc {{.*}}:26:5, scope 6 // CHECK-NEXT: dealloc_stack %2 : $*Builtin.Int2, loc {{.*}}:20:12, scope 6 -// CHECK-NEXT: throw %{{.*}} : $Error, loc {{.*}}:26:5, scope 6 +// CHECK-NEXT: throw %{{.*}} : $any Error, loc {{.*}}:26:5, scope 6 // CHECK: end sil function '$s3del1MC4fromAcA12WithDelegate_p_tKcfc' diff --git a/test/SILOptimizer/definite_init_actor.swift b/test/SILOptimizer/definite_init_actor.swift index ecdfc75ea84f0..1bd896baf5d96 100644 --- a/test/SILOptimizer/definite_init_actor.swift +++ b/test/SILOptimizer/definite_init_actor.swift @@ -193,7 +193,7 @@ actor MultiVarActor { var firstVar: Int var secondVar: Float - // CHECK-LABEL: sil hidden @$s4test13MultiVarActorC10doNotThrowACSb_tYaKcfc : $@convention(method) @async (Bool, @owned MultiVarActor) -> (@owned MultiVarActor, @error Error) { + // CHECK-LABEL: sil hidden @$s4test13MultiVarActorC10doNotThrowACSb_tYaKcfc : $@convention(method) @async (Bool, @owned MultiVarActor) -> (@owned MultiVarActor, @error any Error) { // CHECK: bb0({{%[0-9]+}} : $Bool, [[SELF:%[0-9]+]] : $MultiVarActor): // CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MultiVarActor, #MultiVarActor.firstVar // CHECK: [[VAR:%[0-9]+]] = begin_access [modify] [dynamic] [[REF]] : $*Int diff --git a/test/SILOptimizer/definite_init_closures.sil b/test/SILOptimizer/definite_init_closures.sil index 18c566d219966..1b90172a09288 100644 --- a/test/SILOptimizer/definite_init_closures.sil +++ b/test/SILOptimizer/definite_init_closures.sil @@ -31,9 +31,9 @@ bb0(%0 : $Bool): %8 = struct_element_addr %7 : $*SimpleStruct, #SimpleStruct.x assign %0 to %8 : $*Bool end_access %7 : $*SimpleStruct - %16 = function_ref @implicit_closure_struct : $@convention(thin) (@inout_aliasable SimpleStruct) -> (Bool, @error Error) - %17 = partial_apply [callee_guaranteed] %16(%2) : $@convention(thin) (@inout_aliasable SimpleStruct) -> (Bool, @error Error) - destroy_value %17 : $@callee_guaranteed () -> (Bool, @error Error) + %16 = function_ref @implicit_closure_struct : $@convention(thin) (@inout_aliasable SimpleStruct) -> (Bool, @error any Error) + %17 = partial_apply [callee_guaranteed] %16(%2) : $@convention(thin) (@inout_aliasable SimpleStruct) -> (Bool, @error any Error) + destroy_value %17 : $@callee_guaranteed () -> (Bool, @error any Error) %23 = begin_access [modify] [static] %2 : $*SimpleStruct %24 = struct_element_addr %23 : $*SimpleStruct, #SimpleStruct.y assign %0 to %24 : $*Bool @@ -43,7 +43,7 @@ bb0(%0 : $Bool): return %27 : $SimpleStruct } -sil private [transparent] [ossa] @implicit_closure_struct : $@convention(thin) (@inout_aliasable SimpleStruct) -> (Bool, @error Error) { +sil private [transparent] [ossa] @implicit_closure_struct : $@convention(thin) (@inout_aliasable SimpleStruct) -> (Bool, @error any Error) { bb0(%0 : $*SimpleStruct): debug_value %0 : $*SimpleStruct, var, name "self", argno 2, expr op_deref %3 = begin_access [read] [static] %0 : $*SimpleStruct @@ -61,17 +61,17 @@ bb0(%0 : $Bool, %1 : @owned $SimpleClass): assign %0 to %6 : $*Bool end_borrow %5 : $SimpleClass %9 = begin_borrow %4 : $SimpleClass - %11 = function_ref @implicit_closure_class : $@convention(thin) (@guaranteed SimpleClass) -> (Bool, @error Error) + %11 = function_ref @implicit_closure_class : $@convention(thin) (@guaranteed SimpleClass) -> (Bool, @error any Error) %12 = copy_value %4 : $SimpleClass - %13 = partial_apply [callee_guaranteed] %11(%12) : $@convention(thin) (@guaranteed SimpleClass) -> (Bool, @error Error) - destroy_value %13 : $@callee_guaranteed () -> (Bool, @error Error) + %13 = partial_apply [callee_guaranteed] %11(%12) : $@convention(thin) (@guaranteed SimpleClass) -> (Bool, @error any Error) + destroy_value %13 : $@callee_guaranteed () -> (Bool, @error any Error) %19 = ref_element_addr %9 : $SimpleClass, #SimpleClass.y assign %0 to %19 : $*Bool end_borrow %9 : $SimpleClass return %4 : $SimpleClass } -sil private [transparent] [ossa] @implicit_closure_class : $@convention(thin) (@guaranteed SimpleClass) -> (Bool, @error Error) { +sil private [transparent] [ossa] @implicit_closure_class : $@convention(thin) (@guaranteed SimpleClass) -> (Bool, @error any Error) { bb0(%0 : @guaranteed $SimpleClass): debug_value %0 : $SimpleClass, let, name "self", argno 2 %3 = ref_element_addr %0 : $SimpleClass, #SimpleClass.x diff --git a/test/SILOptimizer/definite_init_crashes.sil b/test/SILOptimizer/definite_init_crashes.sil index 5c326abce3754..b4cb2e6e3b2f7 100644 --- a/test/SILOptimizer/definite_init_crashes.sil +++ b/test/SILOptimizer/definite_init_crashes.sil @@ -94,20 +94,20 @@ public struct AStruct { @_hasStorage public let protoType: Proto.Type } -sil @mayThrow : $@convention(thin) () -> (@owned NonTrivial, @error Error) +sil @mayThrow : $@convention(thin) () -> (@owned NonTrivial, @error any Error) // CHECK-LABEL: sil [ossa] @assign_of_non_primitive_object_element_type -sil [ossa] @assign_of_non_primitive_object_element_type : $@convention(thin) (@thick Proto.Type) -> (@owned AStruct, @error Error) { +sil [ossa] @assign_of_non_primitive_object_element_type : $@convention(thin) (@thick Proto.Type) -> (@owned AStruct, @error any Error) { bb0(%0 : $@thick Proto.Type): %3 = alloc_stack $AStruct %4 = mark_uninitialized [rootself] %3 : $*AStruct - %7 = function_ref @mayThrow : $@convention(thin) () -> (@owned NonTrivial, @error Error) - try_apply %7() : $@convention(thin) () -> (@owned NonTrivial, @error Error), normal bb1, error bb3 + %7 = function_ref @mayThrow : $@convention(thin) () -> (@owned NonTrivial, @error any Error) + try_apply %7() : $@convention(thin) () -> (@owned NonTrivial, @error any Error), normal bb1, error bb3 bb1(%15 : @owned $NonTrivial): %16 = struct_element_addr %4 : $*AStruct, #AStruct.foobar assign %15 to %16 : $*NonTrivial - try_apply %7() : $@convention(thin) () -> (@owned NonTrivial, @error Error), normal bb2, error bb4 + try_apply %7() : $@convention(thin) () -> (@owned NonTrivial, @error any Error), normal bb2, error bb4 bb2(%26 : @owned $NonTrivial): %27 = struct_element_addr %4 : $*AStruct, #AStruct.name diff --git a/test/SILOptimizer/definite_init_failable_initializers.swift b/test/SILOptimizer/definite_init_failable_initializers.swift index e004d84c1dad6..d16d9c3145d03 100644 --- a/test/SILOptimizer/definite_init_failable_initializers.swift +++ b/test/SILOptimizer/definite_init_failable_initializers.swift @@ -320,7 +320,7 @@ struct ThrowStruct { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] init(failBeforeDelegation: Int) throws { @@ -342,11 +342,11 @@ struct ThrowStruct { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb4([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb4([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] init(failBeforeOrDuringDelegation: Int) throws { @@ -368,11 +368,11 @@ struct ThrowStruct { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb4([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb4([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] init(failBeforeOrDuringDelegation2: Int) throws { @@ -390,7 +390,7 @@ struct ThrowStruct { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] init(failDuringDelegation: Int) throws { @@ -411,7 +411,7 @@ struct ThrowStruct { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] @@ -441,12 +441,12 @@ struct ThrowStruct { // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb4([[ERROR:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb4([[ERROR:%.*]] : $any Error): // CHECK-NEXT: release_value [[NEW_SELF]] -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): // CHECK-NEXT: [[COND:%.*]] = load [[BITMAP_BOX]] // CHECK-NEXT: cond_br [[COND]], bb6, bb7 // CHECK: bb6: @@ -486,12 +486,12 @@ struct ThrowStruct { // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb4([[ERROR:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb4([[ERROR:%.*]] : $any Error): // CHECK-NEXT: release_value [[NEW_SELF]] -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): // CHECK-NEXT: [[COND:%.*]] = load [[BITMAP_BOX]] // CHECK-NEXT: cond_br [[COND]], bb6, bb7 // CHECK: bb6: @@ -513,7 +513,7 @@ struct ThrowStruct { // CHECK: bb0([[ARG1:%.*]] : $Int, [[ARG2:%.*]] : $@thin ThrowStruct.Type): // CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $ThrowStruct // CHECK: [[INIT_FN:%.*]] = function_ref @$s35definite_init_failable_initializers11ThrowStructV20failDuringDelegationACSi_tKcfC -// CHECK-NEXT: try_apply [[INIT_FN]]([[ARG1]], [[ARG2]]) : $@convention(method) (Int, @thin ThrowStruct.Type) -> (@owned ThrowStruct, @error Error), normal [[TRY_APPLY_SUCC_BB:bb[0-9]+]], error [[TRY_APPLY_FAIL_BB:bb[0-9]+]] +// CHECK-NEXT: try_apply [[INIT_FN]]([[ARG1]], [[ARG2]]) : $@convention(method) (Int, @thin ThrowStruct.Type) -> (@owned ThrowStruct, @error any Error), normal [[TRY_APPLY_SUCC_BB:bb[0-9]+]], error [[TRY_APPLY_FAIL_BB:bb[0-9]+]] // // CHECK: [[TRY_APPLY_SUCC_BB]]([[NEW_SELF:%.*]] : $ThrowStruct): // CHECK-NEXT: [[SELF_OPTIONAL:%.*]] = enum $Optional, #Optional.some!enumelt, [[NEW_SELF]] @@ -541,8 +541,8 @@ struct ThrowStruct { // CHECK: [[EPILOG_BB]]([[NEW_SELF:%.*]] : $Optional): // CHECK-NEXT: return [[NEW_SELF]] : $Optional // -// CHECK: [[TRY_APPLY_FAIL_BB]]([[ERROR:%.*]] : $Error): -// CHECK-NEXT: strong_release [[ERROR]] : $Error +// CHECK: [[TRY_APPLY_FAIL_BB]]([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: strong_release [[ERROR]] : $any Error // CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK-NEXT: br [[TRY_APPLY_CONT]]([[NEW_SELF]] : $Optional) init?(throwsToOptional: Int) { @@ -583,7 +583,7 @@ struct ThrowStruct { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] init(failDuringSelfReplacement: Int) throws { @@ -605,7 +605,7 @@ struct ThrowStruct { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: release_value [[NEW_SELF]] // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] @@ -935,7 +935,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[DERIVED_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] required init() throws { @@ -963,7 +963,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[DERIVED_SELF]] : $ThrowDerivedClass -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: [[RELOAD_SELF:%.*]] = load [[SELF_BOX]] // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick ThrowDerivedClass.Type // CHECK-NEXT: dealloc_partial_ref [[RELOAD_SELF]] : $ThrowDerivedClass, [[METATYPE]] : $@thick ThrowDerivedClass.Type @@ -998,11 +998,11 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] // CHECK-NEXT: return [[DERIVED_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb4([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb4([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): // CHECK-NEXT: [[COND:%.*]] = load [[BITMAP_BOX]] // CHECK-NEXT: cond_br [[COND]], bb6, bb7 // CHECK: bb6: @@ -1038,7 +1038,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[DERIVED_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: strong_release [[DERIVED_SELF]] // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] @@ -1072,12 +1072,12 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] // CHECK-NEXT: return [[DERIVED_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb4([[ERROR:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb4([[ERROR:%.*]] : $any Error): // CHECK-NEXT: strong_release [[DERIVED_SELF]] -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): // CHECK-NEXT: [[BITMAP:%.*]] = load [[BITMAP_BOX]] // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Int2, 1 // CHECK-NEXT: [[BITMAP_MSB:%.*]] = builtin "lshr_Int2"([[BITMAP]] : $Builtin.Int2, [[ONE]] : $Builtin.Int2) @@ -1125,12 +1125,12 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] // CHECK-NEXT: return [[DERIVED_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb4([[ERROR:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb4([[ERROR:%.*]] : $any Error): // CHECK-NEXT: strong_release [[DERIVED_SELF]] -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): // CHECK-NEXT: [[BITMAP:%.*]] = load [[BITMAP_BOX]] // CHECK-NEXT: [[COND:%.*]] = builtin "trunc_Int2_Int1"([[BITMAP]] : $Builtin.Int2) : $Builtin.Int1 // CHECK-NEXT: cond_br [[COND]], bb6, bb10 @@ -1155,7 +1155,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK: bb11: // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] -// CHECK-NEXT: throw [[ERROR]] : $Error +// CHECK-NEXT: throw [[ERROR]] : $any Error init(failBeforeFullInitialization: Int, failAfterFullInitialization: Int) throws { try unwrap(failBeforeFullInitialization) super.init(noFail: ()) @@ -1191,14 +1191,14 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] // CHECK-NEXT: return [[DERIVED_SELF]] -// CHECK: bb4([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb7([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb7([[ERROR]] : $Error) -// CHECK: bb6([[ERROR:%.*]] : $Error): +// CHECK: bb4([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb7([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb7([[ERROR]] : $any Error) +// CHECK: bb6([[ERROR:%.*]] : $any Error): // CHECK-NEXT: strong_release [[DERIVED_SELF]] -// CHECK-NEXT: br bb7([[ERROR]] : $Error) -// CHECK: bb7([[ERROR:%.*]] : $Error): +// CHECK-NEXT: br bb7([[ERROR]] : $any Error) +// CHECK: bb7([[ERROR:%.*]] : $any Error): // CHECK-NEXT: [[BITMAP:%.*]] = load [[BITMAP_BOX]] // CHECK-NEXT: [[COND:%.*]] = builtin "trunc_Int2_Int1"([[BITMAP]] : $Builtin.Int2) // CHECK-NEXT: cond_br [[COND]], bb8, bb12 @@ -1247,7 +1247,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR]] convenience init(failBeforeDelegation: Int) throws { @@ -1266,9 +1266,9 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] -// CHECK-NEXT: throw [[ERROR]] : $Error +// CHECK-NEXT: throw [[ERROR]] : $any Error convenience init(failDuringDelegation: Int) throws { try self.init() } @@ -1287,11 +1287,11 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb3([[ERROR1:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR1]] : $Error) -// CHECK: bb4([[ERROR2:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR2]] : $Error) -// CHECK: bb5([[ERROR3:%.*]] : $Error): +// CHECK: bb3([[ERROR1:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR1]] : $any Error) +// CHECK: bb4([[ERROR2:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR2]] : $any Error) +// CHECK: bb5([[ERROR3:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR3]] convenience init(failBeforeOrDuringDelegation: Int) throws { @@ -1313,11 +1313,11 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR1]] : $Error) -// CHECK: bb4([[ERROR2:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR2]] : $Error) -// CHECK: bb5([[ERROR3:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR1]] : $any Error) +// CHECK: bb4([[ERROR2:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR2]] : $any Error) +// CHECK: bb5([[ERROR3:%.*]] : $any Error): // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: throw [[ERROR3]] convenience init(failBeforeOrDuringDelegation2: Int) throws { @@ -1337,7 +1337,7 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb2([[ERROR:%.*]] : $Error): +// CHECK: bb2([[ERROR:%.*]] : $any Error): // CHECK-NEXT: strong_release [[NEW_SELF]] // CHECK-NEXT: destroy_addr [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[SELF_BOX]] @@ -1367,12 +1367,12 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb3([[ERROR1:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR1]] : $Error) -// CHECK: bb4([[ERROR2:%.*]] : $Error): +// CHECK: bb3([[ERROR1:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR1]] : $any Error) +// CHECK: bb4([[ERROR2:%.*]] : $any Error): // CHECK-NEXT: strong_release [[NEW_SELF]] -// CHECK-NEXT: br bb5([[ERROR2]] : $Error) -// CHECK: bb5([[ERROR3:%.*]] : $Error): +// CHECK-NEXT: br bb5([[ERROR2]] : $any Error) +// CHECK: bb5([[ERROR3:%.*]] : $any Error): // CHECK-NEXT: [[BITMAP:%.*]] = load [[BITMAP_BOX]] // CHECK: cond_br {{.*}}, bb6, bb7 // CHECK: bb6: @@ -1411,12 +1411,12 @@ class ThrowDerivedClass : ThrowBaseClass { // CHECK-NEXT: dealloc_stack [[SELF_BOX]] // CHECK-NEXT: dealloc_stack [[BITMAP_BOX]] // CHECK-NEXT: return [[NEW_SELF]] -// CHECK: bb3([[ERROR:%.*]] : $Error): -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb4([[ERROR:%.*]] : $Error): +// CHECK: bb3([[ERROR:%.*]] : $any Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb4([[ERROR:%.*]] : $any Error): // CHECK-NEXT: strong_release [[NEW_SELF]] -// CHECK-NEXT: br bb5([[ERROR]] : $Error) -// CHECK: bb5([[ERROR:%.*]] : $Error): +// CHECK-NEXT: br bb5([[ERROR]] : $any Error) +// CHECK: bb5([[ERROR:%.*]] : $any Error): // CHECK-NEXT: [[BITMAP:%.*]] = load [[BITMAP_BOX]] // CHECK: cond_br {{.*}}, bb6, bb7 // CHECK: bb6: diff --git a/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil b/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil index 238d35004e27a..d22f9f7eda0a6 100644 --- a/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil +++ b/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil @@ -31,7 +31,7 @@ class DerivedClassWithNontrivialStoredProperties : RootClassWithNontrivialStored override init() } -sil @getThrowingValue : $@convention(thin) () -> (Int, @error Error) +sil @getThrowingValue : $@convention(thin) () -> (Int, @error any Error) // CHECK-LABEL: @self_init_assert_instruction // CHECK: apply @@ -343,8 +343,8 @@ bb0(%0 : @owned $DerivedClassWithNontrivialStoredProperties): %2 = mark_uninitialized [delegatingselfallocated] %1 : $*DerivedClassWithNontrivialStoredProperties store %0 to [init] %2 : $*DerivedClassWithNontrivialStoredProperties %6 = load [take] %2 : $*DerivedClassWithNontrivialStoredProperties - %7 = function_ref @getThrowingValue : $@convention(thin) () -> (Int, @error Error) - try_apply %7() : $@convention(thin) () -> (Int, @error Error), normal bb1, error bb5 + %7 = function_ref @getThrowingValue : $@convention(thin) () -> (Int, @error any Error) + try_apply %7() : $@convention(thin) () -> (Int, @error any Error), normal bb1, error bb5 bb1(%9 : $Int): %10 = function_ref @selfinit_derivedclass_peerconvenience_init : $@convention (thin) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned DerivedClassWithNontrivialStoredProperties diff --git a/test/SILOptimizer/devirt_protocol_method_invocations.swift b/test/SILOptimizer/devirt_protocol_method_invocations.swift index a84d24441a21f..2c14ad6e0f846 100644 --- a/test/SILOptimizer/devirt_protocol_method_invocations.swift +++ b/test/SILOptimizer/devirt_protocol_method_invocations.swift @@ -273,11 +273,11 @@ extension Optional : ReabstractedP { func f() {} } -// CHECK-LABEL: sil hidden [noinline] {{.*}}@$s34devirt_protocol_method_invocations23testReabstractedWitnessyyAA0F1P_pF : $@convention(thin) (@in_guaranteed ReabstractedP) -> () { -// CHECK: bb0(%0 : $*ReabstractedP): -// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*ReabstractedP to $*@opened([[ID:.*]], ReabstractedP) Self -// CHECK: [[WM:%.*]] = witness_method $@opened([[ID]], ReabstractedP) Self, #ReabstractedP.f : (Self) -> () -> (), [[OPEN]] : $*@opened([[ID]], ReabstractedP) Self : $@convention(witness_method: ReabstractedP) <τ_0_0 where τ_0_0 : ReabstractedP> (@in_guaranteed τ_0_0) -> () -// CHECK: apply [[WM]]<@opened([[ID]], ReabstractedP) Self>([[OPEN]]) : $@convention(witness_method: ReabstractedP) <τ_0_0 where τ_0_0 : ReabstractedP> (@in_guaranteed τ_0_0) -> () +// CHECK-LABEL: sil hidden [noinline] {{.*}}@$s34devirt_protocol_method_invocations23testReabstractedWitnessyyAA0F1P_pF : $@convention(thin) (@in_guaranteed any ReabstractedP) -> () { +// CHECK: bb0(%0 : $*any ReabstractedP): +// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*any ReabstractedP to $*@opened([[ID:.*]], any ReabstractedP) Self +// CHECK: [[WM:%.*]] = witness_method $@opened([[ID]], any ReabstractedP) Self, #ReabstractedP.f : (Self) -> () -> (), [[OPEN]] : $*@opened([[ID]], any ReabstractedP) Self : $@convention(witness_method: ReabstractedP) <τ_0_0 where τ_0_0 : ReabstractedP> (@in_guaranteed τ_0_0) -> () +// CHECK: apply [[WM]]<@opened([[ID]], any ReabstractedP) Self>([[OPEN]]) : $@convention(witness_method: ReabstractedP) <τ_0_0 where τ_0_0 : ReabstractedP> (@in_guaranteed τ_0_0) -> () // CHECK-LABEL: } // end sil function '$s34devirt_protocol_method_invocations23testReabstractedWitnessyyAA0F1P_pF' @inline(never) func testReabstractedWitness(_ f: ReabstractedP) { diff --git a/test/SILOptimizer/devirt_speculative.sil b/test/SILOptimizer/devirt_speculative.sil index a6aca304276be..2834213128837 100644 --- a/test/SILOptimizer/devirt_speculative.sil +++ b/test/SILOptimizer/devirt_speculative.sil @@ -166,7 +166,7 @@ class S2 : Throw { override func mayThrow() throws } -sil hidden [thunk] @$S4main4ThrowC8mayThrowyyKF : $@convention(method) (@guaranteed Throw) -> @error Error { +sil hidden [thunk] @$S4main4ThrowC8mayThrowyyKF : $@convention(method) (@guaranteed Throw) -> @error any Error { bb0(%0 : $Throw): %1 = tuple () return %1 : $() @@ -178,7 +178,7 @@ bb0(%0 : $S1): return %1 : $() } -sil hidden [thunk] [always_inline] @$S4main2S2C8mayThrowyyKF : $@convention(method) (@guaranteed S2) -> @error Error { +sil hidden [thunk] [always_inline] @$S4main2S2C8mayThrowyyKF : $@convention(method) (@guaranteed S2) -> @error any Error { bb0(%0 : $S2): %1 = tuple () return %1 : $() @@ -190,8 +190,8 @@ bb0(%0 : $S2): sil hidden [noinline] @test_devirt_of_throw_without_error : $@convention(thin) (@owned Throw) -> () { bb0(%0 : $Throw): - %80 = class_method %0 : $Throw, #Throw.mayThrow : (Throw) -> () throws -> (), $@convention(method) (@guaranteed Throw) -> @error Error // user: %81 - try_apply %80(%0) : $@convention(method) (@guaranteed Throw) -> @error Error, normal bb7, error bb6 + %80 = class_method %0 : $Throw, #Throw.mayThrow : (Throw) -> () throws -> (), $@convention(method) (@guaranteed Throw) -> @error any Error // user: %81 + try_apply %80(%0) : $@convention(method) (@guaranteed Throw) -> @error any Error, normal bb7, error bb6 bb6(%82 : $Error): br bb1 diff --git a/test/SILOptimizer/devirt_try_apply.sil b/test/SILOptimizer/devirt_try_apply.sil index 807294901fd38..f61484894ae42 100644 --- a/test/SILOptimizer/devirt_try_apply.sil +++ b/test/SILOptimizer/devirt_try_apply.sil @@ -97,7 +97,7 @@ bb0(%0 : $Int32, %1 : $UnsafeMutablePointer>): sil [transparent] [serialized] @_TFs13_didEnterMainFTVs5Int324argvGVs20UnsafeMutablePointerGS0_Vs4Int8___T_ : $@convention(thin) (Int32, UnsafeMutablePointer>) -> () -sil hidden [noinline] @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Base) -> (Optional, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Base) -> (Optional, @error any Error) { bb0(%0 : $Base): debug_value %0 : $Base %2 = integer_literal $Builtin.Int32, 0 @@ -110,7 +110,7 @@ bb0(%0 : $Base): sil [transparent] [serialized] @_TFVs5Int32CfMS_FT22_builtinIntegerLiteralBI__S_ : $@convention(thin) (Builtin.IntLiteral, @thin Int32.Type) -> Int32 -sil hidden [noinline] @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Base) -> (@owned Base, @error any Error) { bb0(%0 : $Base): debug_value %0 : $Base strong_retain %0 : $Base @@ -118,7 +118,7 @@ bb0(%0 : $Base): } -sil hidden [noinline] @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Base) -> (@owned Optional, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Base) -> (@owned Optional, @error any Error) { bb0(%0 : $Base): debug_value %0 : $Base strong_retain %0 : $Base @@ -165,7 +165,7 @@ bb0(%0 : $@thick Base.Type): } -sil hidden [noinline] @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Derived1) -> (Optional, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Derived1) -> (Optional, @error any Error) { bb0(%0 : $Derived1): debug_value %0 : $Derived1 %2 = integer_literal $Builtin.Int32, 1 @@ -175,7 +175,7 @@ bb0(%0 : $Derived1): } -sil hidden [noinline] @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived1) -> (@owned Derived1, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived1) -> (@owned Derived1, @error any Error) { bb0(%0 : $Derived1): debug_value %0 : $Derived1 strong_retain %0 : $Derived1 @@ -183,7 +183,7 @@ bb0(%0 : $Derived1): } -sil hidden [noinline] @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Derived1) -> (@owned Optional, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Derived1) -> (@owned Optional, @error any Error) { bb0(%0 : $Derived1): debug_value %0 : $Derived1 strong_retain %0 : $Derived1 @@ -241,11 +241,11 @@ bb0(%0 : $@thick Derived1.Type): } -sil private @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Optional, @error Error) { +sil private @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Optional, @error any Error) { bb0(%0 : $Derived2): - %1 = function_ref @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error) - try_apply %1(%0) : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error), normal bb1, error bb2 + %1 = function_ref @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error any Error) + try_apply %1(%0) : $@convention(method) (@guaranteed Derived2) -> (Int32, @error any Error), normal bb1, error bb2 bb1(%3 : $Int32): %4 = enum $Optional, #Optional.some!enumelt, %3 : $Int32 @@ -257,7 +257,7 @@ bb2(%6 : $Error): } -sil hidden [noinline] @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error any Error) { bb0(%0 : $Derived2): debug_value %0 : $Derived2 %2 = integer_literal $Builtin.Int32, 2 @@ -266,7 +266,7 @@ bb0(%0 : $Derived2): } -sil hidden [noinline] @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error any Error) { bb0(%0 : $Derived2): debug_value %0 : $Derived2 strong_retain %0 : $Derived2 @@ -274,7 +274,7 @@ bb0(%0 : $Derived2): } -sil hidden [noinline] @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error Error) { +sil hidden [noinline] @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error any Error) { bb0(%0 : $Derived2): debug_value %0 : $Derived2 strong_retain %0 : $Derived2 @@ -321,7 +321,7 @@ bb0(%0 : $Derived2): } -sil @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP1) -> (Int32, @error Error) { +sil @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP1) -> (Int32, @error any Error) { bb0(%0 : $CP1): debug_value %0 : $CP1 %2 = integer_literal $Builtin.Int32, 1 @@ -368,12 +368,12 @@ bb0(%0 : $@thick CP1.Type): } -sil [transparent] [thunk] @_TTWC16devirt_try_apply3CP1S_1PS_FS1_3foouRq_S1__fq_FzT_Vs5Int32 : $@convention(witness_method: P) (@in_guaranteed CP1) -> (Int32, @error Error) { +sil [transparent] [thunk] @_TTWC16devirt_try_apply3CP1S_1PS_FS1_3foouRq_S1__fq_FzT_Vs5Int32 : $@convention(witness_method: P) (@in_guaranteed CP1) -> (Int32, @error any Error) { bb0(%0 : $*CP1): %1 = load %0 : $*CP1 strong_retain %1 : $CP1 - %3 = class_method %1 : $CP1, #CP1.foo : (CP1) -> () throws -> Int32, $@convention(method) (@guaranteed CP1) -> (Int32, @error Error) - try_apply %3(%1) : $@convention(method) (@guaranteed CP1) -> (Int32, @error Error), normal bb1, error bb2 + %3 = class_method %1 : $CP1, #CP1.foo : (CP1) -> () throws -> Int32, $@convention(method) (@guaranteed CP1) -> (Int32, @error any Error) + try_apply %3(%1) : $@convention(method) (@guaranteed CP1) -> (Int32, @error any Error), normal bb1, error bb2 bb1(%5 : $Int32): strong_release %1 : $CP1 @@ -386,7 +386,7 @@ bb2(%8 : $Error): } -sil @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error) { +sil @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error) { bb0(%0 : $CP2): debug_value %0 : $CP2 %2 = integer_literal $Builtin.Int32, 2 @@ -459,8 +459,8 @@ bb0(%0 : $Base): %6 = load %3 : $*Optional store %6 to %1 : $*Optional dealloc_stack %3 : $*Optional - %9 = class_method %0 : $Base, #Base.foo : (Base) -> () throws -> Int32?, $@convention(method) (@guaranteed Base) -> (Optional, @error Error) - try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (Optional, @error Error), normal bb1, error bb4 + %9 = class_method %0 : $Base, #Base.foo : (Base) -> () throws -> Int32?, $@convention(method) (@guaranteed Base) -> (Optional, @error any Error) + try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (Optional, @error any Error), normal bb1, error bb4 bb1(%11 : $Optional): store %11 to %1 : $*Optional @@ -499,8 +499,8 @@ bb0(%0 : $Base): %6 = load %3 : $*Optional store %6 to %1 : $*Optional dealloc_stack %3 : $*Optional - %9 = class_method %0 : $Base, #Base.boo1 : (Base) -> () throws -> Base, $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error) - try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error), normal bb1, error bb4 + %9 = class_method %0 : $Base, #Base.boo1 : (Base) -> () throws -> Base, $@convention(method) (@guaranteed Base) -> (@owned Base, @error any Error) + try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Base, @error any Error), normal bb1, error bb4 bb1(%11 : $Base): %12 = enum $Optional, #Optional.some!enumelt, %11 : $Base @@ -540,8 +540,8 @@ bb0(%0 : $Base): %6 = load %3 : $*Optional store %6 to %1 : $*Optional dealloc_stack %3 : $*Optional - %9 = class_method %0 : $Base, #Base.boo2 : (Base) -> () throws -> Base?, $@convention(method) (@guaranteed Base) -> (@owned Optional, @error Error) - try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Optional, @error Error), normal bb1, error bb4 + %9 = class_method %0 : $Base, #Base.boo2 : (Base) -> () throws -> Base?, $@convention(method) (@guaranteed Base) -> (@owned Optional, @error any Error) + try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Optional, @error any Error), normal bb1, error bb4 bb1(%11 : $Optional): store %11 to %1 : $*Optional @@ -629,8 +629,8 @@ bb0: %5 = integer_literal $Builtin.Int32, 0 %6 = struct $Int32 (%5 : $Builtin.Int32) store %6 to %0 : $*Int32 - %8 = class_method %3 : $CP2, #CP2.foo : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error Error) - try_apply %8(%3) : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error), normal bb1, error bb4 + %8 = class_method %3 : $CP2, #CP2.foo : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error) + try_apply %8(%3) : $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error), normal bb1, error bb4 bb1(%10 : $Int32): store %10 to %0 : $*Int32 @@ -670,8 +670,8 @@ bb0: %8 = struct $Int32 (%7 : $Builtin.Int32) store %8 to %0 : $*Int32 %10 = open_existential_addr immutable_access %1 : $*P to $*@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self - %11 = witness_method $@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self, #P.foo, %10 : $*@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (Int32, @error Error) - try_apply %11<@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self>(%10) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (Int32, @error Error), normal bb1, error bb4 + %11 = witness_method $@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self, #P.foo, %10 : $*@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (Int32, @error any Error) + try_apply %11<@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self>(%10) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (Int32, @error any Error), normal bb1, error bb4 bb1(%13 : $Int32): store %13 to %0 : $*Int32 @@ -715,8 +715,8 @@ bb0: %6 = struct $Int32 (%5 : $Builtin.Int32) %7 = enum $Optional, #Optional.some!enumelt, %6 : $Int32 store %7 to %0 : $*Optional - %9 = class_method %3 : $Derived1, #Derived1.foo : (Derived1) -> () throws -> Int32?, $@convention(method) (@guaranteed Derived1) -> (Optional, @error Error) - try_apply %9(%3) : $@convention(method) (@guaranteed Derived1) -> (Optional, @error Error), normal bb1, error bb4 + %9 = class_method %3 : $Derived1, #Derived1.foo : (Derived1) -> () throws -> Int32?, $@convention(method) (@guaranteed Derived1) -> (Optional, @error any Error) + try_apply %9(%3) : $@convention(method) (@guaranteed Derived1) -> (Optional, @error any Error), normal bb1, error bb4 bb1(%11 : $Optional): store %11 to %0 : $*Optional @@ -758,8 +758,8 @@ bb0: %5 = integer_literal $Builtin.Int32, 0 %6 = struct $Int32 (%5 : $Builtin.Int32) store %6 to %0 : $*Int32 - %8 = class_method %1 : $CP2, #CP2.foo : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error Error) - try_apply %8(%1) : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error), normal bb1, error bb4 + %8 = class_method %1 : $CP2, #CP2.foo : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error) + try_apply %8(%1) : $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error), normal bb1, error bb4 bb1(%10 : $Int32): store %10 to %0 : $*Int32 @@ -801,12 +801,12 @@ class D3 : D1 { } // devirt_try_apply.D1.f1 () throws -> Swift.Optional -sil @_TFC16devirt_try_apply2D12f1fzT_GSqCS_1A_ : $@convention(method) (@guaranteed D1) -> (@owned Optional, @error Error) +sil @_TFC16devirt_try_apply2D12f1fzT_GSqCS_1A_ : $@convention(method) (@guaranteed D1) -> (@owned Optional, @error any Error) // devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A -sil @_TFC16devirt_try_apply2D32f1fzT_CS_1A : $@convention(method) (@guaranteed D3) -> (@owned A, @error Error) +sil @_TFC16devirt_try_apply2D32f1fzT_CS_1A : $@convention(method) (@guaranteed D3) -> (@owned A, @error any Error) -sil @compute_something : $@convention(thin) () -> (@owned Optional, @error Error) +sil @compute_something : $@convention(thin) () -> (@owned Optional, @error any Error) // CHECK-MANDATORY-INLINING-LABEL: sil @test_devirt_try_apply_at_Onone // CHECK-MANDATORY-INLINING: bb0: @@ -818,17 +818,17 @@ sil @compute_something : $@convention(thin) () -> (@owned Optional, @error Er // CHECK-MANDATORY-INLINING: return // Check that error BB was reused, because it only had a single predecessor and thus // no critical edge would be created by this reuse. -// CHECK-MANDATORY-INLINING: [[ERROR]]({{%[0-9]+}} : $Error): +// CHECK-MANDATORY-INLINING: [[ERROR]]({{%[0-9]+}} : $any Error): // CHECK-MANDATORY-INLINING: strong_release // CHECK-MANDATORY-INLINING: throw // CHECK-MANDATORY-INLINING-NOT: bb3 // CHECK-MANDATORY-INLINING: } -sil @test_devirt_try_apply_at_Onone : $@convention(thin) () -> (@owned Optional, @error Error) { +sil @test_devirt_try_apply_at_Onone : $@convention(thin) () -> (@owned Optional, @error any Error) { bb0: %2 = alloc_ref $D3 %3 = upcast %2 : $D3 to $D1 - %4 = class_method %3 : $D1, #D1.f1 : (D1) -> () throws -> Optional, $@convention(method) (@guaranteed D1) -> (@owned Optional, @error Error) - try_apply %4(%3) : $@convention(method) (@guaranteed D1) -> (@owned Optional, @error Error), normal bb1, error bb2 + %4 = class_method %3 : $D1, #D1.f1 : (D1) -> () throws -> Optional, $@convention(method) (@guaranteed D1) -> (@owned Optional, @error any Error) + try_apply %4(%3) : $@convention(method) (@guaranteed D1) -> (@owned Optional, @error any Error), normal bb1, error bb2 bb1(%6 : $Optional): strong_release %2 : $D3 diff --git a/test/SILOptimizer/devirt_try_apply_ownership.sil b/test/SILOptimizer/devirt_try_apply_ownership.sil index e9f87e931047a..f06a003fd3d3a 100644 --- a/test/SILOptimizer/devirt_try_apply_ownership.sil +++ b/test/SILOptimizer/devirt_try_apply_ownership.sil @@ -96,7 +96,7 @@ bb0(%0 : $Int32, %1 : $UnsafeMutablePointer>): sil [transparent] [serialized] [ossa] @_TFs13_didEnterMainFTVs5Int324argvGVs20UnsafeMutablePointerGS0_Vs4Int8___T_ : $@convention(thin) (Int32, UnsafeMutablePointer>) -> () -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Base) -> (Optional, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Base) -> (Optional, @error any Error) { bb0(%0 : @guaranteed $Base): debug_value %0 : $Base %2 = integer_literal $Builtin.Int32, 0 @@ -109,14 +109,14 @@ bb0(%0 : @guaranteed $Base): sil [transparent] [serialized] [ossa] @_TFVs5Int32CfMS_FT22_builtinIntegerLiteralBI__S_ : $@convention(thin) (Builtin.IntLiteral, @thin Int32.Type) -> Int32 -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Base) -> (@owned Base, @error any Error) { bb0(%0 : @guaranteed $Base): %1 = copy_value %0 : $Base return %1 : $Base } -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Base) -> (@owned Optional, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Base) -> (@owned Optional, @error any Error) { bb0(%0 : @guaranteed $Base): %1 = copy_value %0 : $Base %2 = enum $Optional, #Optional.some!enumelt, %1 : $Base @@ -157,7 +157,7 @@ bb0(%0 : $@thick Base.Type): return %3 : $Base } -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Derived1) -> (Optional, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ : $@convention(method) (@guaranteed Derived1) -> (Optional, @error any Error) { bb0(%0 : @guaranteed $Derived1): %2 = integer_literal $Builtin.Int32, 1 %3 = struct $Int32 (%2 : $Builtin.Int32) @@ -165,14 +165,14 @@ bb0(%0 : @guaranteed $Derived1): return %4 : $Optional } -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived1) -> (@owned Derived1, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived1) -> (@owned Derived1, @error any Error) { bb0(%0 : @guaranteed $Derived1): %1 = copy_value %0 : $Derived1 return %1 : $Derived1 } -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Derived1) -> (@owned Optional, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ : $@convention(method) (@guaranteed Derived1) -> (@owned Optional, @error any Error) { bb0(%0 : @guaranteed $Derived1): %1 = copy_value %0 : $Derived1 %2 = enum $Optional, #Optional.some!enumelt, %1 : $Derived1 @@ -226,10 +226,10 @@ bb0(%0 : $@thick Derived1.Type): } -sil private [ossa] @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Optional, @error Error) { +sil private [ossa] @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Optional, @error any Error) { bb0(%0 : @guaranteed $Derived2): - %1 = function_ref @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error) - try_apply %1(%0) : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error), normal bb1, error bb2 + %1 = function_ref @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error any Error) + try_apply %1(%0) : $@convention(method) (@guaranteed Derived2) -> (Int32, @error any Error), normal bb1, error bb2 bb1(%3 : $Int32): %4 = enum $Optional, #Optional.some!enumelt, %3 : $Int32 @@ -241,7 +241,7 @@ bb2(%6 : @owned $Error): } -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed Derived2) -> (Int32, @error any Error) { bb0(%0 : @guaranteed $Derived2): %2 = integer_literal $Builtin.Int32, 2 %3 = struct $Int32 (%2 : $Builtin.Int32) @@ -249,14 +249,14 @@ bb0(%0 : @guaranteed $Derived2): } -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error any Error) { bb0(%0 : @guaranteed $Derived2): %1 = copy_value %0 : $Derived2 return %1 : $Derived2 } -sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error Error) { +sil hidden [noinline] [ossa] @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ : $@convention(method) (@guaranteed Derived2) -> (@owned Derived2, @error any Error) { bb0(%0 : @guaranteed $Derived2): %1 = copy_value %0 : $Derived2 return %1 : $Derived2 @@ -301,7 +301,7 @@ bb0(%0 : @owned $Derived2): } -sil [ossa] @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP1) -> (Int32, @error Error) { +sil [ossa] @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP1) -> (Int32, @error any Error) { bb0(%0 : @guaranteed $CP1): %2 = integer_literal $Builtin.Int32, 1 %3 = struct $Int32 (%2 : $Builtin.Int32) @@ -344,11 +344,11 @@ bb0(%0 : $@thick CP1.Type): } -sil [transparent] [thunk] [ossa] @_TTWC16devirt_try_apply3CP1S_1PS_FS1_3foouRq_S1__fq_FzT_Vs5Int32 : $@convention(witness_method: P) (@in_guaranteed CP1) -> (Int32, @error Error) { +sil [transparent] [thunk] [ossa] @_TTWC16devirt_try_apply3CP1S_1PS_FS1_3foouRq_S1__fq_FzT_Vs5Int32 : $@convention(witness_method: P) (@in_guaranteed CP1) -> (Int32, @error any Error) { bb0(%0 : $*CP1): %1 = load [copy] %0 : $*CP1 - %3 = class_method %1 : $CP1, #CP1.foo : (CP1) -> () throws -> Int32, $@convention(method) (@guaranteed CP1) -> (Int32, @error Error) - try_apply %3(%1) : $@convention(method) (@guaranteed CP1) -> (Int32, @error Error), normal bb1, error bb2 + %3 = class_method %1 : $CP1, #CP1.foo : (CP1) -> () throws -> Int32, $@convention(method) (@guaranteed CP1) -> (Int32, @error any Error) + try_apply %3(%1) : $@convention(method) (@guaranteed CP1) -> (Int32, @error any Error), normal bb1, error bb2 bb1(%5 : $Int32): destroy_value %1 : $CP1 @@ -361,7 +361,7 @@ bb2(%8 : @owned $Error): } -sil [ossa] @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error) { +sil [ossa] @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 : $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error) { bb0(%0 : @guaranteed $CP2): %2 = integer_literal $Builtin.Int32, 2 %3 = struct $Int32 (%2 : $Builtin.Int32) @@ -431,8 +431,8 @@ bb0(%0 : @owned $Base): %6 = load [trivial] %3 : $*Optional store %6 to [trivial] %1 : $*Optional dealloc_stack %3 : $*Optional - %9 = class_method %0 : $Base, #Base.foo : (Base) -> () throws -> Int32?, $@convention(method) (@guaranteed Base) -> (Optional, @error Error) - try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (Optional, @error Error), normal bb1, error bb4 + %9 = class_method %0 : $Base, #Base.foo : (Base) -> () throws -> Int32?, $@convention(method) (@guaranteed Base) -> (Optional, @error any Error) + try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (Optional, @error any Error), normal bb1, error bb4 bb1(%11 : $Optional): store %11 to [trivial] %1 : $*Optional @@ -469,8 +469,8 @@ bb0(%0 : @owned $Base): %6 = load [take] %3 : $*Optional store %6 to [init] %1 : $*Optional dealloc_stack %3 : $*Optional - %9 = class_method %0 : $Base, #Base.boo1 : (Base) -> () throws -> Base, $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error) - try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Base, @error Error), normal bb1, error bb4 + %9 = class_method %0 : $Base, #Base.boo1 : (Base) -> () throws -> Base, $@convention(method) (@guaranteed Base) -> (@owned Base, @error any Error) + try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Base, @error any Error), normal bb1, error bb4 bb1(%11 : @owned $Base): %12 = enum $Optional, #Optional.some!enumelt, %11 : $Base @@ -506,8 +506,8 @@ bb0(%0 : @owned $Base): %6 = load [take] %3 : $*Optional store %6 to [init] %1 : $*Optional dealloc_stack %3 : $*Optional - %9 = class_method %0 : $Base, #Base.boo2 : (Base) -> () throws -> Base?, $@convention(method) (@guaranteed Base) -> (@owned Optional, @error Error) - try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Optional, @error Error), normal bb1, error bb4 + %9 = class_method %0 : $Base, #Base.boo2 : (Base) -> () throws -> Base?, $@convention(method) (@guaranteed Base) -> (@owned Optional, @error any Error) + try_apply %9(%0) : $@convention(method) (@guaranteed Base) -> (@owned Optional, @error any Error), normal bb1, error bb4 bb1(%11 : @owned $Optional): store %11 to [assign] %1 : $*Optional @@ -587,8 +587,8 @@ bb0: %5 = integer_literal $Builtin.Int32, 0 %6 = struct $Int32 (%5 : $Builtin.Int32) store %6 to [trivial] %0 : $*Int32 - %8 = class_method %3 : $CP2, #CP2.foo : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error Error) - try_apply %8(%3) : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error), normal bb1, error bb4 + %8 = class_method %3 : $CP2, #CP2.foo : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error) + try_apply %8(%3) : $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error), normal bb1, error bb4 bb1(%10 : $Int32): store %10 to [trivial] %0 : $*Int32 @@ -628,8 +628,8 @@ bb0: %8 = struct $Int32 (%7 : $Builtin.Int32) store %8 to [trivial] %0 : $*Int32 %10 = open_existential_addr immutable_access %1 : $*P to $*@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self - %11 = witness_method $@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self, #P.foo, %10 : $*@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (Int32, @error Error) - try_apply %11<@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self>(%10) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (Int32, @error Error), normal bb1, error bb4 + %11 = witness_method $@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self, #P.foo, %10 : $*@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (Int32, @error any Error) + try_apply %11<@opened("3F4928FC-364E-11E5-9488-B8E856428C60", P) Self>(%10) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> (Int32, @error any Error), normal bb1, error bb4 bb1(%13 : $Int32): store %13 to [trivial] %0 : $*Int32 @@ -671,8 +671,8 @@ bb0: %6 = struct $Int32 (%5 : $Builtin.Int32) %7 = enum $Optional, #Optional.some!enumelt, %6 : $Int32 store %7 to [trivial] %0 : $*Optional - %9 = class_method %3 : $Derived1, #Derived1.foo : (Derived1) -> () throws -> Int32?, $@convention(method) (@guaranteed Derived1) -> (Optional, @error Error) - try_apply %9(%3) : $@convention(method) (@guaranteed Derived1) -> (Optional, @error Error), normal bb1, error bb4 + %9 = class_method %3 : $Derived1, #Derived1.foo : (Derived1) -> () throws -> Int32?, $@convention(method) (@guaranteed Derived1) -> (Optional, @error any Error) + try_apply %9(%3) : $@convention(method) (@guaranteed Derived1) -> (Optional, @error any Error), normal bb1, error bb4 bb1(%11 : $Optional): store %11 to [trivial] %0 : $*Optional @@ -714,8 +714,8 @@ bb0: %5 = integer_literal $Builtin.Int32, 0 %6 = struct $Int32 (%5 : $Builtin.Int32) store %6 to [trivial] %0 : $*Int32 - %8 = class_method %1 : $CP2, #CP2.foo : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error Error) - try_apply %8(%1) : $@convention(method) (@guaranteed CP2) -> (Int32, @error Error), normal bb1, error bb4 + %8 = class_method %1 : $CP2, #CP2.foo : (CP2) -> () throws -> Int32, $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error) + try_apply %8(%1) : $@convention(method) (@guaranteed CP2) -> (Int32, @error any Error), normal bb1, error bb4 bb1(%10 : $Int32): store %10 to [trivial] %0 : $*Int32 @@ -757,12 +757,12 @@ class D3 : D1 { } // devirt_try_apply.D1.f1 () throws -> Swift.Optional -sil [ossa] @_TFC16devirt_try_apply2D12f1fzT_GSqCS_1A_ : $@convention(method) (@guaranteed D1) -> (@owned Optional, @error Error) +sil [ossa] @_TFC16devirt_try_apply2D12f1fzT_GSqCS_1A_ : $@convention(method) (@guaranteed D1) -> (@owned Optional, @error any Error) // devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A -sil [ossa] @_TFC16devirt_try_apply2D32f1fzT_CS_1A : $@convention(method) (@guaranteed D3) -> (@owned A, @error Error) +sil [ossa] @_TFC16devirt_try_apply2D32f1fzT_CS_1A : $@convention(method) (@guaranteed D3) -> (@owned A, @error any Error) -sil [ossa] @compute_something : $@convention(thin) () -> (@owned Optional, @error Error) +sil [ossa] @compute_something : $@convention(thin) () -> (@owned Optional, @error any Error) // CHECK-MANDATORY-INLINING-LABEL: sil [ossa] @test_devirt_try_apply_at_Onone // CHECK-MANDATORY-INLINING: bb0: @@ -774,17 +774,17 @@ sil [ossa] @compute_something : $@convention(thin) () -> (@owned Optional, @e // CHECK-MANDATORY-INLINING: return // Check that error BB was reused, because it only had a single predecessor and thus // no critical edge would be created by this reuse. -// CHECK-MANDATORY-INLINING: [[ERROR]]({{%[0-9]+}} : @owned $Error): +// CHECK-MANDATORY-INLINING: [[ERROR]]({{%[0-9]+}} : @owned $any Error): // CHECK-MANDATORY-INLINING: destroy_value // CHECK-MANDATORY-INLINING: throw // CHECK-MANDATORY-INLINING-NOT: bb3 // CHECK-MANDATORY-INLINING: } -sil [ossa] @test_devirt_try_apply_at_Onone : $@convention(thin) () -> (@owned Optional, @error Error) { +sil [ossa] @test_devirt_try_apply_at_Onone : $@convention(thin) () -> (@owned Optional, @error any Error) { bb0: %2 = alloc_ref $D3 %3 = upcast %2 : $D3 to $D1 - %4 = class_method %3 : $D1, #D1.f1 : (D1) -> () throws -> Optional, $@convention(method) (@guaranteed D1) -> (@owned Optional, @error Error) - try_apply %4(%3) : $@convention(method) (@guaranteed D1) -> (@owned Optional, @error Error), normal bb1, error bb2 + %4 = class_method %3 : $D1, #D1.f1 : (D1) -> () throws -> Optional, $@convention(method) (@guaranteed D1) -> (@owned Optional, @error any Error) + try_apply %4(%3) : $@convention(method) (@guaranteed D1) -> (@owned Optional, @error any Error), normal bb1, error bb2 bb1(%6 : @owned $Optional): destroy_value %3 : $D1 diff --git a/test/SILOptimizer/di-conditional-destroy-scope.swift b/test/SILOptimizer/di-conditional-destroy-scope.swift index 03294094b474a..4bd05e5c3bf8c 100644 --- a/test/SILOptimizer/di-conditional-destroy-scope.swift +++ b/test/SILOptimizer/di-conditional-destroy-scope.swift @@ -8,7 +8,7 @@ // CHECK: [[ADR:%.*]] = ref_element_addr %{{.*}} : $RecursibleDirectoryContentsGenerator, #RecursibleDirectoryContentsGenerator.fileSystem, loc {{.*}}:39:5, scope 2 // CHECK: [[ADR_ACCESS:%.*]] = begin_access [deinit] [static] [[ADR]] -// CHECK: destroy_addr [[ADR_ACCESS]] : $*FileSystem, loc {{.*}}:39:5, scope 2 +// CHECK: destroy_addr [[ADR_ACCESS]] : $*any FileSystem, loc {{.*}}:39:5, scope 2 import Foundation diff --git a/test/SILOptimizer/diagnose_unreachable.sil b/test/SILOptimizer/diagnose_unreachable.sil index f1935e1d0b8a4..841835ccbb21f 100644 --- a/test/SILOptimizer/diagnose_unreachable.sil +++ b/test/SILOptimizer/diagnose_unreachable.sil @@ -386,17 +386,17 @@ bb0: unreachable } -sil @throwing_noreturn : $@convention(thin) () -> (Never, @error Error) +sil @throwing_noreturn : $@convention(thin) () -> (Never, @error any Error) // CHECK-LABEL:sil @try_apply_1 // CHECK: bb1( // CHECK-NEXT: {{ unreachable}} // CHECK: bb2( // CHECK-NEXT: throw -sil @try_apply_1 : $@convention(thin) () -> @error Error { +sil @try_apply_1 : $@convention(thin) () -> @error any Error { bb0: - %0 = function_ref @throwing_noreturn : $@convention(thin) () -> (Never, @error Error) - try_apply %0() : $@convention(thin) () -> (Never, @error Error), normal bb1, error bb2 + %0 = function_ref @throwing_noreturn : $@convention(thin) () -> (Never, @error any Error) + try_apply %0() : $@convention(thin) () -> (Never, @error any Error), normal bb1, error bb2 bb1(%1 : $Never): %2 = tuple () return %2 : $() @@ -404,7 +404,7 @@ bb2(%3 : $Error): throw %3 : $Error } -sil_scope 0 { loc "f.swift":1:1 parent @try_apply_2 : $@convention(thin) (Builtin.Int1) -> @error Error } +sil_scope 0 { loc "f.swift":1:1 parent @try_apply_2 : $@convention(thin) (Builtin.Int1) -> @error any Error } // CHECK: sil_scope [[F:[0-9]+]] { loc "f.swift":1:1 parent @try_apply_2 sil_scope 1 { loc "f.swift":2:1 parent 0 } // CHECK: sil_scope [[S:[0-9]+]] { loc "f.swift":2:1 parent [[F]] } @@ -413,17 +413,17 @@ sil_scope 1 { loc "f.swift":2:1 parent 0 } // CHECK-NEXT: {{ unreachable }}, scope [[F]] // CHECK: bb5({{.*}}$Never): // CHECK-NEXT: {{ unreachable }}, scope [[S]] -// CHECK: bb7({{.*}} : $Error): +// CHECK: bb7({{.*}} : $any Error): // CHECK-NEXT: throw // CHECK-LABEL: } // end sil function 'try_apply_2' -sil @try_apply_2 : $@convention(thin) (Builtin.Int1) -> @error Error { +sil @try_apply_2 : $@convention(thin) (Builtin.Int1) -> @error any Error { bb0(%0 : $Builtin.Int1): - %1 = function_ref @throwing_noreturn : $@convention(thin) () -> (Never, @error Error) + %1 = function_ref @throwing_noreturn : $@convention(thin) () -> (Never, @error any Error) cond_br %0, bb1, bb2 bb1: - try_apply %1() : $@convention(thin) () -> (Never, @error Error), normal bb3, error bb4, scope 0 + try_apply %1() : $@convention(thin) () -> (Never, @error any Error), normal bb3, error bb4, scope 0 bb2: - try_apply %1() : $@convention(thin) () -> (Never, @error Error), normal bb5, error bb6, scope 1 + try_apply %1() : $@convention(thin) () -> (Never, @error any Error), normal bb5, error bb6, scope 1 bb3(%2 : $Never): br bb7 bb4(%4 : $Error): @@ -444,15 +444,15 @@ bb8(%9 : $Error): // CHECK: bb1: // CHECK-NOT: {{ unreachable}} // CHECK: try_apply -// CHECK: bb3({{.*}} : $Error): +// CHECK: bb3({{.*}} : $any Error): // CHECK-NEXT: throw -sil @try_apply_3 : $@convention(thin) (Never) -> @error Error { +sil @try_apply_3 : $@convention(thin) (Never) -> @error any Error { bb0(%0 : $Never): br bb1(%0 : $Never) bb1(%1 : $Never): - %2 = function_ref @throwing_noreturn : $@convention(thin) () -> (Never, @error Error) - try_apply %2() : $@convention(thin) () -> (Never, @error Error), normal bb2, error bb3 + %2 = function_ref @throwing_noreturn : $@convention(thin) () -> (Never, @error any Error) + try_apply %2() : $@convention(thin) () -> (Never, @error any Error), normal bb2, error bb3 bb2(%3 : $Never): br bb1(%3 : $Never) diff --git a/test/SILOptimizer/eager_specialize.sil b/test/SILOptimizer/eager_specialize.sil index a0f387f74565a..4b2c5fd550ff4 100644 --- a/test/SILOptimizer/eager_specialize.sil +++ b/test/SILOptimizer/eager_specialize.sil @@ -149,7 +149,7 @@ bb0(%0 : $*T, %1 : $*T): } // divideNum (A, den : A) throws -> A -sil [_specialize where T == Int] @$s16eager_specialize9divideNum_3denxx_xtKs13SignedIntegerRzlF : $@convention(thin) (@in T, @in T) -> (@out T, @error Error) { +sil [_specialize where T == Int] @$s16eager_specialize9divideNum_3denxx_xtKs13SignedIntegerRzlF : $@convention(thin) (@in T, @in T) -> (@out T, @error any Error) { bb0(%0 : $*T, %1 : $*T, %2 : $*T): // function_ref static != infix (A, A) -> Bool %5 = function_ref @$ss2neoiySbx_xts9EquatableRzlFZ : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@in τ_0_0, @in τ_0_0) -> Bool @@ -183,14 +183,14 @@ bb2: } // specialized divideNum (A, den : A) throws -> A -// CHECK-LABEL: sil shared @$s16eager_specialize9divideNum_3denxx_xtKSZRzlFSi_Tg5 : $@convention(thin) (Int, Int) -> (Int, @error Error) { +// CHECK-LABEL: sil shared @$s16eager_specialize9divideNum_3denxx_xtKSZRzlFSi_Tg5 : $@convention(thin) (Int, Int) -> (Int, @error any Error) { // CHECK: bb0(%0 : $Int, %1 : $Int): // CHECK: return %{{.*}} // CHECK: throw %{{.*}} // Generic with specialized dispatch. No more [specialize] attribute. // -// CHECK-LABEL: sil @$s16eager_specialize9divideNum_3denxx_xtKs13SignedIntegerRzlF : $@convention(thin) (@in T, @in T) -> (@out T, @error Error) { +// CHECK-LABEL: sil @$s16eager_specialize9divideNum_3denxx_xtKs13SignedIntegerRzlF : $@convention(thin) (@in T, @in T) -> (@out T, @error any Error) { // CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T): // CHECK: %3 = metatype $@thick T.Type // CHECK: %4 = metatype $@thick Int.Type @@ -204,10 +204,10 @@ bb2: // CHECK: cond_br %{{.*}}, bb5, bb3 // CHECK: bb3: -// CHECK: br bb4(%{{.*}} : $Error) +// CHECK: br bb4(%{{.*}} : $any Error) -// CHECK: bb4(%{{.*}} : $Error): -// CHECK: throw %{{.*}} : $Error +// CHECK: bb4(%{{.*}} : $any Error): +// CHECK: throw %{{.*}} : $any Error // CHECK: bb5: // CHECK: %{{.*}} = witness_method $T, #BinaryInteger."/" : {{.*}} : $@convention(witness_method: BinaryInteger) <τ_0_0 where τ_0_0 : BinaryInteger> (@in τ_0_0, @in τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0 @@ -225,11 +225,11 @@ bb2: // CHECK: %{{.*}} = unchecked_addr_cast %2 : $*T to $*Int // CHECK: %{{.*}} = load %{{.*}} : $*Int // CHECK: // function_ref specialized divideNum(_:den:) -// CHECK: %{{.*}} = function_ref @$s16eager_specialize9divideNum_3denxx_xtKSZRzlFSi_Tg5 : $@convention(thin) (Int, Int) -> (Int, @error Error) -// CHECK: try_apply %{{.*}}(%{{.*}}, %{{.*}}) : $@convention(thin) (Int, Int) -> (Int, @error Error), normal bb9, error bb8 +// CHECK: %{{.*}} = function_ref @$s16eager_specialize9divideNum_3denxx_xtKSZRzlFSi_Tg5 : $@convention(thin) (Int, Int) -> (Int, @error any Error) +// CHECK: try_apply %{{.*}}(%{{.*}}, %{{.*}}) : $@convention(thin) (Int, Int) -> (Int, @error any Error), normal bb9, error bb8 -// CHECK: bb8(%{{.*}} : $Error): -// CHECK: br bb4(%{{.*}} : $Error) +// CHECK: bb8(%{{.*}} : $any Error): +// CHECK: br bb4(%{{.*}} : $any Error) // CHECK: bb9(%{{.*}} : $Int): // CHECK: store %{{.*}} to %{{.*}} : $*Int @@ -764,10 +764,10 @@ class ClassUsingThrowingP { } // Int64.action() -sil @$ss5Int64V34eager_specialize_throwing_functionE6actionAByKF : $@convention(method) (Int64) -> (Int64, @error Error) +sil @$ss5Int64V34eager_specialize_throwing_functionE6actionAByKF : $@convention(method) (Int64) -> (Int64, @error any Error) // protocol witness for ThrowingP.action() in conformance Int64 -sil @$ss5Int64V34eager_specialize_throwing_function9ThrowingPA2cDP6actionAByKFTW : $@convention(witness_method: ThrowingP) (@in_guaranteed Int64) -> (Int64, @error Error) +sil @$ss5Int64V34eager_specialize_throwing_function9ThrowingPA2cDP6actionAByKFTW : $@convention(witness_method: ThrowingP) (@in_guaranteed Int64) -> (Int64, @error any Error) sil @$s34eager_specialize_throwing_function19ClassUsingThrowingPCACycfc : $@convention(method) (@owned ClassUsingThrowingP) -> @owned ClassUsingThrowingP @@ -784,12 +784,12 @@ sil @$s34eager_specialize_throwing_function19ClassUsingThrowingPCfD : $@conventi // It should dispatch to its specialized version, but use apply [nothrow] to invoke // the specialized version. -// CHECK-LABEL: sil @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error Error) -// CHECK: [[SPECIALIZED:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZs5Int64V_Tg5 : $@convention(method) (Int64, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error Error) +// CHECK-LABEL: sil @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error any Error) +// CHECK: [[SPECIALIZED:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZs5Int64V_Tg5 : $@convention(method) (Int64, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error any Error) // CHECK: apply [nothrow] [[SPECIALIZED]] // CHECK: // end sil function '$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ' // static ClassUsingThrowingP.f(_:) -sil [_specialize exported: false, kind: full, where T == Int64] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error Error) { +sil [_specialize exported: false, kind: full, where T == Int64] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error any Error) { bb0(%0 : $*T, %1 : $@thick ClassUsingThrowingP.Type): destroy_addr %0 : $*T %4 = unchecked_trivial_bit_cast %1 : $@thick ClassUsingThrowingP.Type to $@thick @dynamic_self ClassUsingThrowingP.Type @@ -807,16 +807,16 @@ bb0(%0 : $*T, %1 : $@thick ClassUsingThrowingP.Type): // It should dispatch to its specialized version and use try_apply to invoke // the specialized version. -// CHECK-LABEL: sil @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) -// CHECK: [[SPECIALIZED:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZAF_Tg5 : $@convention(method) (Int64, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) +// CHECK-LABEL: sil @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) +// CHECK: [[SPECIALIZED:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZAF_Tg5 : $@convention(method) (Int64, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) // CHECK: try_apply [[SPECIALIZED]] // CHECK: // end sil function '$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ' // static ClassUsingThrowingP.g(_:) -sil [_specialize exported: false, kind: full, where T == Int64] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) { +sil [_specialize exported: false, kind: full, where T == Int64] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) { bb0(%0 : $*T, %1 : $@thick ClassUsingThrowingP.Type): - %5 = witness_method $T, #ThrowingP.action : (Self) -> () throws -> Int64 : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error Error) - try_apply %5(%0) : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error Error), normal bb1, error bb2 + %5 = witness_method $T, #ThrowingP.action : (Self) -> () throws -> Int64 : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error any Error) + try_apply %5(%0) : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error any Error), normal bb1, error bb2 bb1(%7 : $Int64): // Preds: bb0 destroy_addr %0 : $*T diff --git a/test/SILOptimizer/eager_specialize_ossa.sil b/test/SILOptimizer/eager_specialize_ossa.sil index d240b15f1aaa4..27aca92a50485 100644 --- a/test/SILOptimizer/eager_specialize_ossa.sil +++ b/test/SILOptimizer/eager_specialize_ossa.sil @@ -309,7 +309,7 @@ bb0(%0 : $*T, %1 : $*T): } // divideNum (A, den : A) throws -> A -sil [_specialize where T == Int] [ossa] @$s16eager_specialize9divideNum_3denxx_xtKs13SignedIntegerRzlF : $@convention(thin) (@in T, @in T) -> (@out T, @error Error) { +sil [_specialize where T == Int] [ossa] @$s16eager_specialize9divideNum_3denxx_xtKs13SignedIntegerRzlF : $@convention(thin) (@in T, @in T) -> (@out T, @error any Error) { bb0(%0 : $*T, %1 : $*T, %2 : $*T): // function_ref static != infix (A, A) -> Bool %5 = function_ref @$ss2neoiySbx_xts9EquatableRzlFZ : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@in τ_0_0, @in τ_0_0) -> Bool @@ -343,14 +343,14 @@ bb2: } // specialized divideNum (A, den : A) throws -> A -// CHECK-LABEL: sil shared [ossa] @$s16eager_specialize9divideNum_3denxx_xtKSZRzlFSi_Tg5 : $@convention(thin) (Int, Int) -> (Int, @error Error) { +// CHECK-LABEL: sil shared [ossa] @$s16eager_specialize9divideNum_3denxx_xtKSZRzlFSi_Tg5 : $@convention(thin) (Int, Int) -> (Int, @error any Error) { // CHECK: bb0(%0 : $Int, %1 : $Int): // CHECK: return %{{.*}} // CHECK: throw %{{.*}} // Generic with specialized dispatch. No more [specialize] attribute. // -// CHECK-LABEL: sil [ossa] @$s16eager_specialize9divideNum_3denxx_xtKs13SignedIntegerRzlF : $@convention(thin) (@in T, @in T) -> (@out T, @error Error) { +// CHECK-LABEL: sil [ossa] @$s16eager_specialize9divideNum_3denxx_xtKs13SignedIntegerRzlF : $@convention(thin) (@in T, @in T) -> (@out T, @error any Error) { // CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T): // CHECK: %{{.*}} = metatype $@thick T.Type // CHECK: %{{.*}} = metatype $@thick Int.Type @@ -367,10 +367,10 @@ bb2: // CHECK: cond_br %{{.*}}, bb5, bb3 // CHECK: bb3: -// CHECK: br bb4(%{{.*}} : $Error) +// CHECK: br bb4(%{{.*}} : $any Error) -// CHECK: bb4(%{{.*}} : @owned $Error): -// CHECK: throw %{{.*}} : $Error +// CHECK: bb4(%{{.*}} : @owned $any Error): +// CHECK: throw %{{.*}} : $any Error // CHECK: bb5: // CHECK: %{{.*}} = witness_method $T, #BinaryInteger."/" : {{.*}} : $@convention(witness_method: BinaryInteger) <τ_0_0 where τ_0_0 : BinaryInteger> (@in τ_0_0, @in τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0 @@ -388,11 +388,11 @@ bb2: // CHECK: %{{.*}} = unchecked_addr_cast %2 : $*T to $*Int // CHECK: %{{.*}} = load [trivial] %{{.*}} : $*Int // CHECK: // function_ref specialized divideNum(_:den:) -// CHECK: %{{.*}} = function_ref @$s16eager_specialize9divideNum_3denxx_xtKSZRzlFSi_Tg5 : $@convention(thin) (Int, Int) -> (Int, @error Error) -// CHECK: try_apply %{{.*}}(%{{.*}}, %{{.*}}) : $@convention(thin) (Int, Int) -> (Int, @error Error), normal bb9, error bb8 +// CHECK: %{{.*}} = function_ref @$s16eager_specialize9divideNum_3denxx_xtKSZRzlFSi_Tg5 : $@convention(thin) (Int, Int) -> (Int, @error any Error) +// CHECK: try_apply %{{.*}}(%{{.*}}, %{{.*}}) : $@convention(thin) (Int, Int) -> (Int, @error any Error), normal bb9, error bb8 -// CHECK: bb8(%{{.*}} : @owned $Error): -// CHECK: br bb4(%{{.*}} : $Error) +// CHECK: bb8(%{{.*}} : @owned $any Error): +// CHECK: br bb4(%{{.*}} : $any Error) // CHECK: bb9(%{{.*}} : $Int): // CHECK: store %{{.*}} to [trivial] %{{.*}} : $*Int @@ -965,10 +965,10 @@ class ClassUsingThrowingP { } // Int64.action() -sil @$ss5Int64V34eager_specialize_throwing_functionE6actionAByKF : $@convention(method) (Int64) -> (Int64, @error Error) +sil @$ss5Int64V34eager_specialize_throwing_functionE6actionAByKF : $@convention(method) (Int64) -> (Int64, @error any Error) // protocol witness for ThrowingP.action() in conformance Int64 -sil @$ss5Int64V34eager_specialize_throwing_function9ThrowingPA2cDP6actionAByKFTW : $@convention(witness_method: ThrowingP) (@in_guaranteed Int64) -> (Int64, @error Error) +sil @$ss5Int64V34eager_specialize_throwing_function9ThrowingPA2cDP6actionAByKFTW : $@convention(witness_method: ThrowingP) (@in_guaranteed Int64) -> (Int64, @error any Error) sil @$s34eager_specialize_throwing_function19ClassUsingThrowingPCACycfc : $@convention(method) (@owned ClassUsingThrowingP) -> @owned ClassUsingThrowingP @@ -985,12 +985,12 @@ sil @$s34eager_specialize_throwing_function19ClassUsingThrowingPCfD : $@conventi // It should dispatch to its specialized version, but use apply [nothrow] to invoke // the specialized version. -// CHECK-LABEL: sil [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error Error) -// CHECK: [[SPECIALIZED:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZs5Int64V_Tg5 : $@convention(method) (Int64, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error Error) +// CHECK-LABEL: sil [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error any Error) +// CHECK: [[SPECIALIZED:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZs5Int64V_Tg5 : $@convention(method) (Int64, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error any Error) // CHECK: apply [nothrow] [[SPECIALIZED]] // CHECK: // end sil function '$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ' // static ClassUsingThrowingP.f(_:) -sil [_specialize exported: false, kind: full, where T == Int64] [_specialize exported: false, kind: full, where T == Klass] [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error Error) { +sil [_specialize exported: false, kind: full, where T == Int64] [_specialize exported: false, kind: full, where T == Klass] [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1fyACXDxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (@owned ClassUsingThrowingP, @error any Error) { bb0(%0 : $*T, %1 : $@thick ClassUsingThrowingP.Type): destroy_addr %0 : $*T %4 = unchecked_trivial_bit_cast %1 : $@thick ClassUsingThrowingP.Type to $@thick @dynamic_self ClassUsingThrowingP.Type @@ -1008,16 +1008,16 @@ bb0(%0 : $*T, %1 : $@thick ClassUsingThrowingP.Type): // It should dispatch to its specialized version and use try_apply to invoke // the specialized version. -// CHECK-LABEL: sil [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) -// CHECK: [[SPECIALIZED:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZAF_Tg5 : $@convention(method) (Int64, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) +// CHECK-LABEL: sil [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) +// CHECK: [[SPECIALIZED:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZAF_Tg5 : $@convention(method) (Int64, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) // CHECK: try_apply [[SPECIALIZED]] // CHECK: // end sil function '$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ' // static ClassUsingThrowingP.g(_:) -sil [_specialize exported: false, kind: full, where T == Int64] [_specialize exported: false, kind: full, where T == Klass] [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) { +sil [_specialize exported: false, kind: full, where T == Int64] [_specialize exported: false, kind: full, where T == Klass] [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1gys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in T, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) { bb0(%0 : $*T, %1 : $@thick ClassUsingThrowingP.Type): - %5 = witness_method $T, #ThrowingP.action : (Self) -> () throws -> Int64 : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error Error) - try_apply %5(%0) : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error Error), normal bb1, error bb2 + %5 = witness_method $T, #ThrowingP.action : (Self) -> () throws -> Int64 : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error any Error) + try_apply %5(%0) : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error any Error), normal bb1, error bb2 bb1(%7 : $Int64): // Preds: bb0 destroy_addr %0 : $*T @@ -1032,15 +1032,15 @@ bb2(%10 : @owned $Error): // Preds: bb0 // load_borrows when reabstracting. Make sure that we put the end_borrow in the // same place. // -// CHECK-LABEL: sil [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1hys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in_guaranteed T, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) { -// CHECK: [[SPECIALIZED_1:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1hys5Int64VxKAA0G1PRzlFZ4main5KlassC_Tg5 : $@convention(method) (@guaranteed Klass, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) +// CHECK-LABEL: sil [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1hys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in_guaranteed T, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) { +// CHECK: [[SPECIALIZED_1:%.*]] = function_ref @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1hys5Int64VxKAA0G1PRzlFZ4main5KlassC_Tg5 : $@convention(method) (@guaranteed Klass, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) // CHECK: try_apply [[SPECIALIZED_1]] // CHECK: } // end sil function '$s34eager_specialize_throwing_function19ClassUsingThrowingPC1hys5Int64VxKAA0G1PRzlFZ' -sil [_specialize exported: false, kind: full, where T == Int64] [_specialize exported: false, kind: full, where T == Klass] [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1hys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in_guaranteed T, @thick ClassUsingThrowingP.Type) -> (Int64, @error Error) { +sil [_specialize exported: false, kind: full, where T == Int64] [_specialize exported: false, kind: full, where T == Klass] [ossa] @$s34eager_specialize_throwing_function19ClassUsingThrowingPC1hys5Int64VxKAA0G1PRzlFZ : $@convention(method) (@in_guaranteed T, @thick ClassUsingThrowingP.Type) -> (Int64, @error any Error) { bb0(%0 : $*T, %1 : $@thick ClassUsingThrowingP.Type): - %5 = witness_method $T, #ThrowingP.action : (Self) -> () throws -> Int64 : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error Error) - try_apply %5(%0) : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error Error), normal bb1, error bb2 + %5 = witness_method $T, #ThrowingP.action : (Self) -> () throws -> Int64 : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error any Error) + try_apply %5(%0) : $@convention(witness_method: ThrowingP) <τ_0_0 where τ_0_0 : ThrowingP> (@in_guaranteed τ_0_0) -> (Int64, @error any Error), normal bb1, error bb2 bb1(%7 : $Int64): // Preds: bb0 return %7 : $Int64 diff --git a/test/SILOptimizer/escape_analysis.sil b/test/SILOptimizer/escape_analysis.sil index 9359a40768178..8d7aa1e8da089 100644 --- a/test/SILOptimizer/escape_analysis.sil +++ b/test/SILOptimizer/escape_analysis.sil @@ -731,10 +731,10 @@ bb2(%5 : $LinkedNode): // CHECK-NEXT: Val [ref] %3 Esc: , Succ: (%0.1), %0 // CHECK-NEXT: Ret [ref] return Esc: , Succ: %3 // CHECK-NEXT: End -sil @call_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error Error) { +sil @call_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error any Error) { bb0(%0 : $X): - %1 = function_ref @throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error Error) - try_apply %1(%0) : $@convention(thin) (@owned X) -> (@owned X, @error Error), normal bb1, error bb2 + %1 = function_ref @throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error any Error) + try_apply %1(%0) : $@convention(thin) (@owned X) -> (@owned X, @error any Error), normal bb1, error bb2 bb1(%3 : $X): return %3 : $X @@ -751,7 +751,7 @@ bb2(%5 : $Error): // CHECK-NEXT: Con [ref] %3.1 Esc: G, Succ: // CHECK-NEXT: Ret [ref] return Esc: , Succ: %0 // CHECK-NEXT: End -sil @throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error Error) { +sil @throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error any Error) { bb0(%0 : $X): cond_br undef, bb1, bb2 @@ -777,10 +777,10 @@ bb2: // CHECK-NEXT: Con [ref] %3.2 Esc: G, Succ: // CHECK-NEXT: Ret [ref] return Esc: , Succ: %3 // CHECK-NEXT: End -sil @call_unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error Error) { +sil @call_unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error any Error) { bb0(%0 : $X): - %1 = function_ref @unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error Error) - try_apply %1(%0) : $@convention(thin) (@owned X) -> (@owned X, @error Error), normal bb1, error bb2 + %1 = function_ref @unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error any Error) + try_apply %1(%0) : $@convention(thin) (@owned X) -> (@owned X, @error any Error), normal bb1, error bb2 bb1(%3 : $X): return %3 : $X @@ -789,7 +789,7 @@ bb2(%5 : $Error): throw %5 : $Error } -sil @unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error Error) +sil @unknown_throwing_func : $@convention(thin) (@owned X) -> (@owned X, @error any Error) // Test that the deinit of a box itself does not capture anything. @@ -1319,12 +1319,12 @@ bb0(%0 : $Array): // CHECK-NEXT: Val %3 Esc: , Succ: (%3.1) // CHECK-NEXT: Con [ref] %3.1 Esc: %4, Succ: // CHECK-NEXT: End -sil @arraysemantics_withUnsafeMutableBufferPointer : $@convention(thin) (@inout Array, @owned @callee_owned (@inout X) -> (@out (), @error Error)) -> () { -bb(%0 : $*Array, %1 : $@callee_owned (@inout X) -> (@out (), @error Error)): +sil @arraysemantics_withUnsafeMutableBufferPointer : $@convention(thin) (@inout Array, @owned @callee_owned (@inout X) -> (@out (), @error any Error)) -> () { +bb(%0 : $*Array, %1 : $@callee_owned (@inout X) -> (@out (), @error any Error)): - %2 = function_ref @withUnsafeMutableBufferPointer : $@convention(method) (@owned @callee_owned (@inout X) -> (@out (), @error Error), @inout Array) -> (@out (), @error Error) + %2 = function_ref @withUnsafeMutableBufferPointer : $@convention(method) (@owned @callee_owned (@inout X) -> (@out (), @error any Error), @inout Array) -> (@out (), @error any Error) %3 = alloc_stack $() - %4 = apply [nothrow] %2(%3, %1, %0) : $@convention(method) (@owned @callee_owned (@inout X) -> (@out (), @error Error), @inout Array) -> (@out (), @error Error) + %4 = apply [nothrow] %2(%3, %1, %0) : $@convention(method) (@owned @callee_owned (@inout X) -> (@out (), @error any Error), @inout Array) -> (@out (), @error any Error) dealloc_stack %3 : $*() %r = tuple() @@ -1374,7 +1374,7 @@ bb0(%0 : @owned $X): return %5 : $Array } -sil [_semantics "array.withUnsafeMutableBufferPointer"] @withUnsafeMutableBufferPointer : $@convention(method) (@owned @callee_owned (@inout X) -> (@out (), @error Error), @inout Array) -> (@out (), @error Error) +sil [_semantics "array.withUnsafeMutableBufferPointer"] @withUnsafeMutableBufferPointer : $@convention(method) (@owned @callee_owned (@inout X) -> (@out (), @error any Error), @inout Array) -> (@out (), @error any Error) sil [_semantics "array.props.isNativeTypeChecked"] @is_native_type_checked : $@convention(method) (@guaranteed Array) -> Bool sil [_semantics "array.check_subscript"] @check_subscript : $@convention(method) (Int32, Bool, @guaranteed Array) -> () sil [_semantics "array.check_index"] @check_index : $@convention(method) (Int32, @guaranteed Array) -> () diff --git a/test/SILOptimizer/escape_analysis_invalidate.sil b/test/SILOptimizer/escape_analysis_invalidate.sil index 4f5f2e1acbe70..5ec16523f22d9 100644 --- a/test/SILOptimizer/escape_analysis_invalidate.sil +++ b/test/SILOptimizer/escape_analysis_invalidate.sil @@ -28,20 +28,20 @@ struct SomeStruct { var someRef: SomeClass } -// CHECK-LABEL: sil @testTempRvalueEscapeAnalysisUpdate : $@convention(thin) (@in_guaranteed SomeProtocol, @guaranteed SomeClass) -> () { -// CHECK: bb0(%0 : $*SomeProtocol, %1 : $SomeClass): +// CHECK-LABEL: sil @testTempRvalueEscapeAnalysisUpdate : $@convention(thin) (@in_guaranteed any SomeProtocol, @guaranteed SomeClass) -> () { +// CHECK: bb0(%0 : $*any SomeProtocol, %1 : $SomeClass): // CHECK: alloc_ref $SomeClass // CHECK: alloc_stack $SomeStruct -// CHECK-NOT: alloc_stack $SomeProtocol +// CHECK-NOT: alloc_stack $any SomeProtocol // CHECK-NOT: copy_addr -// CHECK: init_existential_addr %{{.*}} : $*SomeProtocol, $SomeInstance -// CHECK: [[OPEN1:%.*]] = open_existential_addr immutable_access %0 : $*SomeProtocol to $*@opened("6419340C-0B14-11EA-9897-ACDE48001122", SomeProtocol) Self -// CHECK: apply %{{.*}}<@opened("6419340C-0B14-11EA-9897-ACDE48001122", SomeProtocol) Self>([[OPEN1]]) : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> () +// CHECK: init_existential_addr %{{.*}} : $*any SomeProtocol, $SomeInstance +// CHECK: [[OPEN1:%.*]] = open_existential_addr immutable_access %0 : $*any SomeProtocol to $*@opened("6419340C-0B14-11EA-9897-ACDE48001122", any SomeProtocol) Self +// CHECK: apply %{{.*}}<@opened("6419340C-0B14-11EA-9897-ACDE48001122", any SomeProtocol) Self>([[OPEN1]]) : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> () // CHECK-NOT: destroy_addr -// CHECK-NOT: alloc_stack $SomeProtocol +// CHECK-NOT: alloc_stack $any SomeProtocol // CHECK-NOT: copy_addr -// CHECK: [[OPEN2:%.*]] = open_existential_addr immutable_access %{{.*}} : $*SomeProtocol to $*@opened("6419340C-0B14-11EA-9897-ACDE48001123", SomeProtocol) Self -// CHECK: apply %{{.*}}<@opened("6419340C-0B14-11EA-9897-ACDE48001123", SomeProtocol) Self>([[OPEN2]]) : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> () +// CHECK: [[OPEN2:%.*]] = open_existential_addr immutable_access %{{.*}} : $*any SomeProtocol to $*@opened("6419340C-0B14-11EA-9897-ACDE48001123", any SomeProtocol) Self +// CHECK: apply %{{.*}}<@opened("6419340C-0B14-11EA-9897-ACDE48001123", any SomeProtocol) Self>([[OPEN2]]) : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> () // CHECK-NOT: destroy_addr // CHECK-LABEL: } // end sil function 'testTempRvalueEscapeAnalysisUpdate' sil @testTempRvalueEscapeAnalysisUpdate : $@convention(thin) (@in_guaranteed SomeProtocol, @guaranteed SomeClass) -> () { diff --git a/test/SILOptimizer/escape_analysis_release_hoisting.sil b/test/SILOptimizer/escape_analysis_release_hoisting.sil index 527725b0b9838..6fe10e8054048 100644 --- a/test/SILOptimizer/escape_analysis_release_hoisting.sil +++ b/test/SILOptimizer/escape_analysis_release_hoisting.sil @@ -18,12 +18,12 @@ struct ArrayElementStruct : ArrayElementProtocol { } // CHECK-LABEL: sil @testArrayStorageInitAfterFree : $@convention(thin) () -> () { -// CHECK: [[ARRAY:%.*]] = alloc_ref [stack] [tail_elems $ArrayElementProtocol * undef : $Builtin.Word] $_ContiguousArrayStorage -// CHECK: [[CAST:%.*]] = upcast [[ARRAY]] : $_ContiguousArrayStorage to $__ContiguousArrayStorageBase -// CHECK: [[TAIL:%.*]] = ref_tail_addr [[CAST]] : $__ContiguousArrayStorageBase, $ArrayElementProtocol -// CHECK: [[ADR:%.*]] = init_existential_addr [[TAIL]] : $*ArrayElementProtocol, $ArrayElementStruct +// CHECK: [[ARRAY:%.*]] = alloc_ref [stack] [tail_elems $any ArrayElementProtocol * undef : $Builtin.Word] $_ContiguousArrayStorage +// CHECK: [[CAST:%.*]] = upcast [[ARRAY]] : $_ContiguousArrayStorage to $__ContiguousArrayStorageBase +// CHECK: [[TAIL:%.*]] = ref_tail_addr [[CAST]] : $__ContiguousArrayStorageBase, $any ArrayElementProtocol +// CHECK: [[ADR:%.*]] = init_existential_addr [[TAIL]] : $*any ArrayElementProtocol, $ArrayElementStruct // CHECK: store %{{.*}} to [[ADR]] : $*ArrayElementStruct -// CHECK: strong_release [[ARRAY]] : $_ContiguousArrayStorage +// CHECK: strong_release [[ARRAY]] : $_ContiguousArrayStorage // CHECK-LABEL: } // end sil function 'testArrayStorageInitAfterFree' sil @testArrayStorageInitAfterFree : $@convention(thin) () -> () { bb0: diff --git a/test/SILOptimizer/exclusivity_static_diagnostics_inlined.swift b/test/SILOptimizer/exclusivity_static_diagnostics_inlined.swift index fc4af0812cb1e..7a8c54365254c 100644 --- a/test/SILOptimizer/exclusivity_static_diagnostics_inlined.swift +++ b/test/SILOptimizer/exclusivity_static_diagnostics_inlined.swift @@ -21,10 +21,10 @@ struct Some : SomeP { // existential. // // INLINE-LABEL: $s5Onone16testNestedAccessyyF -// INLINE: [[OUTER:%.*]] = begin_access [modify] [static] %0 : $*SomeP -// INLINE: [[INNERREAD:%.*]] = begin_access [read] [static] [[OUTER]] : $*SomeP -// INLINE: [[INNERMOD:%.*]] = begin_access [modify] [static] [[OUTER]] : $*SomeP -// INLINE: %{{.*}} = open_existential_addr mutable_access [[INNERMOD]] : $*SomeP to $*@opened("{{.*}}", SomeP) Self +// INLINE: [[OUTER:%.*]] = begin_access [modify] [static] %0 : $*any SomeP +// INLINE: [[INNERREAD:%.*]] = begin_access [read] [static] [[OUTER]] : $*any SomeP +// INLINE: [[INNERMOD:%.*]] = begin_access [modify] [static] [[OUTER]] : $*any SomeP +// INLINE: %{{.*}} = open_existential_addr mutable_access [[INNERMOD]] : $*any SomeP to $*@opened("{{.*}}", any SomeP) Self // public func testNestedAccess() { var s: SomeP = Some() diff --git a/test/SILOptimizer/existential_specializer_indirect_class.sil b/test/SILOptimizer/existential_specializer_indirect_class.sil index 4a1881aa4464f..cfdf1362db960 100644 --- a/test/SILOptimizer/existential_specializer_indirect_class.sil +++ b/test/SILOptimizer/existential_specializer_indirect_class.sil @@ -8,10 +8,10 @@ protocol ClassProtocol: AnyObject { func method() } class C: ClassProtocol { func method() {} } -// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] {{.*}}@test_indirect_class_protocol : $@convention(thin) (@in ClassProtocol) -> () +// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] {{.*}}@test_indirect_class_protocol : $@convention(thin) (@in any ClassProtocol) -> () sil @test_indirect_class_protocol : $@convention(thin) (@in ClassProtocol) -> () { // CHECK-NEXT: // -// CHECK-NEXT: bb0(%0 : $*ClassProtocol): +// CHECK-NEXT: bb0(%0 : $*any ClassProtocol): bb0(%0 : $*ClassProtocol): // CHECK-NEXT: %1 = load %0 // CHECK-NEXT: strong_release %1 diff --git a/test/SILOptimizer/existential_specializer_soletype.sil b/test/SILOptimizer/existential_specializer_soletype.sil index a2bd3b389d147..5fa5372a0cb90 100644 --- a/test/SILOptimizer/existential_specializer_soletype.sil +++ b/test/SILOptimizer/existential_specializer_soletype.sil @@ -165,9 +165,9 @@ extension ClassImpl { sil @$s6testProtocolMethod : $@convention(method) <τ_0_0 where τ_0_0 : BaseProtocol> (@in_guaranteed τ_0_0) -> @out τ_0_0 // Verify that the optimization was not performance and that we don't hang as a result. -// CHECK-LABEL: sil hidden @$s6test1_ConcreteInitExistential : $@convention(method) (@in SubProtocol) -> () { -// CHECK: [[E:%.*]] = init_existential_addr %{{.*}} : $*SubProtocol, $@opened("{{.*}}", SubProtocol) Self -// CHECK: apply %{{.*}}<@opened("{{.*}}", SubProtocol) Self>([[E]], %{{.*}}) : $@convention(method) <τ_0_0 where τ_0_0 : BaseProtocol> (@in_guaranteed τ_0_0) -> @out τ_0_0 +// CHECK-LABEL: sil hidden @$s6test1_ConcreteInitExistential : $@convention(method) (@in any SubProtocol) -> () { +// CHECK: [[E:%.*]] = init_existential_addr %{{.*}} : $*any SubProtocol, $@opened("{{.*}}", any SubProtocol) Self +// CHECK: apply %{{.*}}<@opened("{{.*}}", any SubProtocol) Self>([[E]], %{{.*}}) : $@convention(method) <τ_0_0 where τ_0_0 : BaseProtocol> (@in_guaranteed τ_0_0) -> @out τ_0_0 // CHECK-LABEL: } // end sil function '$s6test1_ConcreteInitExistential' sil hidden @$s6test1_ConcreteInitExistential : $@convention(method) (@in SubProtocol) -> () { bb0(%0 : $*SubProtocol): @@ -194,42 +194,42 @@ public struct S : P { } // Check the thunk. -// CHECK-LABEL: sil hidden [signature_optimized_thunk] [always_inline] @$s6test2_6storePyyAA1P_p_AaC_pztF : $@convention(thin) (@in P, @inout P) -> () { -// CHECK: bb0(%0 : $*P, %1 : $*P): -// CHECK: [[F:%.*]] = function_ref @$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @inout P) -> () -// CHECK: [[ADR:%.*]] = open_existential_addr mutable_access %0 : $*P to $*@opened([[TY:".*"]], P) Self -// CHECK: [[ALLOC:%.*]] = alloc_stack $@opened([[TY]], P) Self -// CHECK: copy_addr [[ADR]] to [initialization] [[ALLOC]] : $*@opened([[TY]], P) Self -// CHECK: apply [[F]]<@opened("{{.*}}", P) Self>([[ALLOC]], %1) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @inout P) -> () -// CHECK: destroy_addr %0 : $*P -// CHECK: dealloc_stack [[ALLOC]] : $*@opened([[TY]], P) Self +// CHECK-LABEL: sil hidden [signature_optimized_thunk] [always_inline] @$s6test2_6storePyyAA1P_p_AaC_pztF : $@convention(thin) (@in any P, @inout any P) -> () { +// CHECK: bb0(%0 : $*any P, %1 : $*any P): +// CHECK: [[F:%.*]] = function_ref @$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @inout any P) -> () +// CHECK: [[ADR:%.*]] = open_existential_addr mutable_access %0 : $*any P to $*@opened([[TY:".*"]], any P) Self +// CHECK: [[ALLOC:%.*]] = alloc_stack $@opened([[TY]], any P) Self +// CHECK: copy_addr [[ADR]] to [initialization] [[ALLOC]] : $*@opened([[TY]], any P) Self +// CHECK: apply [[F]]<@opened("{{.*}}", any P) Self>([[ALLOC]], %1) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @inout any P) -> () +// CHECK: destroy_addr %0 : $*any P +// CHECK: dealloc_stack [[ALLOC]] : $*@opened([[TY]], any P) Self // CHECK: return // CHECK-LABEL: } // end sil function '$s6test2_6storePyyAA1P_p_AaC_pztF' // Check the existential to generic specialization. -// CHECK-LABEL: sil shared [noinline] @$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @inout P) -> () { -// CHECK: bb0(%0 : $*τ_0_0, %1 : $*P): -// CHECK: [[ALLOC:%.*]] = alloc_stack $P -// CHECK: [[IEA:%.*]] = init_existential_addr [[ALLOC]] : $*P, $τ_0_0 +// CHECK-LABEL: sil shared [noinline] @$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @inout any P) -> () { +// CHECK: bb0(%0 : $*τ_0_0, %1 : $*any P): +// CHECK: [[ALLOC:%.*]] = alloc_stack $any P +// CHECK: [[IEA:%.*]] = init_existential_addr [[ALLOC]] : $*any P, $τ_0_0 // CHECK: copy_addr [take] %0 to [initialization] [[IEA]] : $*τ_0_0 // CHECK-NOT: destroy -// CHECK: copy_addr [[ALLOC]] to [initialization] %1 : $*P +// CHECK: copy_addr [[ALLOC]] to [initialization] %1 : $*any P // CHECK-NOT: destroy -// CHECK: destroy_addr [[ALLOC]] : $*P +// CHECK: destroy_addr [[ALLOC]] : $*any P // CHECK-NOT: destroy // CHECK-LABEL: } // end sil function '$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n' // Check the generic to concrete specialization. -// CHECK-LABEL: sil shared [noinline] @$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n4main1SV_Tg5 : $@convention(thin) (@owned S, @inout P) -> () { -// CHECK: bb0(%0 : $S, %1 : $*P): +// CHECK-LABEL: sil shared [noinline] @$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n4main1SV_Tg5 : $@convention(thin) (@owned S, @inout any P) -> () { +// CHECK: bb0(%0 : $S, %1 : $*any P): // CHECK: [[ALLOCS:%.*]] = alloc_stack $S -// CHECK: [[ALLOCP:%.*]] = alloc_stack $P -// CHECK: [[IEA:%.*]] = init_existential_addr [[ALLOCP]] : $*P, $S +// CHECK: [[ALLOCP:%.*]] = alloc_stack $any P +// CHECK: [[IEA:%.*]] = init_existential_addr [[ALLOCP]] : $*any P, $S // CHECK: copy_addr [take] [[ALLOCS]] to [initialization] [[IEA]] : $*S // CHECK-NOT: destroy -// CHECK: copy_addr [[ALLOCP]] to [initialization] %1 : $*P -// CHECK: destroy_addr [[ALLOCP]] : $*P +// CHECK: copy_addr [[ALLOCP]] to [initialization] %1 : $*any P +// CHECK: destroy_addr [[ALLOCP]] : $*any P // CHECK: dealloc_stack [[ALLOCP]] // CHECK: dealloc_stack [[ALLOCS]] // CHECK-LABEL: } // end sil function '$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n4main1SV_Tg5' @@ -241,15 +241,15 @@ bb0(%0 : $*P, %1 : $*P): return %5 : $() } -// CHECK-LABEL: sil @$s6test2_6storeS1s1qyAA1SV_AA1P_pztF : $@convention(thin) (S, @inout P) -> () { -// CHECK: bb0(%0 : $S, %1 : $*P): +// CHECK-LABEL: sil @$s6test2_6storeS1s1qyAA1SV_AA1P_pztF : $@convention(thin) (S, @inout any P) -> () { +// CHECK: bb0(%0 : $S, %1 : $*any P): // CHECK: [[ALLOCS1:%.*]] = alloc_stack $S // CHECK: store %0 to [[ALLOCS1]] : $*S // CHECK: [[ALLOCS2:%.*]] = alloc_stack $S // CHECK: copy_addr [[ALLOCS1]] to [initialization] [[ALLOCS2]] : $*S -// CHECK: [[F:%.*]] = function_ref @$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n4main1SV_Tg5 : $@convention(thin) (@owned S, @inout P) -> () +// CHECK: [[F:%.*]] = function_ref @$s6test2_6storePyyAA1P_p_AaC_pztFTf4en_n4main1SV_Tg5 : $@convention(thin) (@owned S, @inout any P) -> () // CHECK: [[S:%.*]] = load [[ALLOCS2]] : $*S -// CHECK: apply [[F]]([[S]], %1) : $@convention(thin) (@owned S, @inout P) -> () +// CHECK: apply [[F]]([[S]], %1) : $@convention(thin) (@owned S, @inout any P) -> () // CHECK-NEXT: dealloc_stack [[ALLOCS2]] : $*S // CHECK-NEXT: destroy_addr [[ALLOCS1]] : $*S // CHECK-NEXT: dealloc_stack [[ALLOCS1]] : $*S @@ -274,27 +274,27 @@ sil_witness_table S: P module test {} // Test an existential in_guaranteed argument. //===----------------------------------------------------------------------===// -// CHECK-LABEL: sil hidden [signature_optimized_thunk] [always_inline] @$s6test3_6storePyyAA1P_pz_AaC_pztF : $@convention(thin) (@in_guaranteed P, @inout P) -> () { -// CHECK: bb0(%0 : $*P, %1 : $*P): -// CHECK: [[F:%.*]] = function_ref @$s6test3_6storePyyAA1P_pz_AaC_pztFTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @inout P) -> () -// CHECK: [[ADR:%.*]] = open_existential_addr immutable_access %0 : $*P to $*@opened("{{.*}}", P) Self -// CHECK: apply [[F]]<@opened("{{.*}}", P) Self>([[ADR]], %1) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @inout P) -> () +// CHECK-LABEL: sil hidden [signature_optimized_thunk] [always_inline] @$s6test3_6storePyyAA1P_pz_AaC_pztF : $@convention(thin) (@in_guaranteed any P, @inout any P) -> () { +// CHECK: bb0(%0 : $*any P, %1 : $*any P): +// CHECK: [[F:%.*]] = function_ref @$s6test3_6storePyyAA1P_pz_AaC_pztFTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @inout any P) -> () +// CHECK: [[ADR:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*@opened("{{.*}}", any P) Self +// CHECK: apply [[F]]<@opened("{{.*}}", any P) Self>([[ADR]], %1) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @inout any P) -> () // CHECK-LABEL: } // end sil function '$s6test3_6storePyyAA1P_pz_AaC_pztF' // The guaranteed concrete argument cannot be consumed. The // existential created in the prolog must be destroyed before // returing. // -// CHECK-LABEL: sil shared @$s6test3_6storePyyAA1P_pz_AaC_pztFTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @inout P) -> () { -// CHECK: bb0(%0 : $*τ_0_0, %1 : $*P): -// CHECK: [[ALLOCP1:%.*]] = alloc_stack $P -// CHECK: [[ADR:%.*]] = init_existential_addr [[ALLOCP1]] : $*P, $τ_0_0 +// CHECK-LABEL: sil shared @$s6test3_6storePyyAA1P_pz_AaC_pztFTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0, @inout any P) -> () { +// CHECK: bb0(%0 : $*τ_0_0, %1 : $*any P): +// CHECK: [[ALLOCP1:%.*]] = alloc_stack $any P +// CHECK: [[ADR:%.*]] = init_existential_addr [[ALLOCP1]] : $*any P, $τ_0_0 // CHECK: copy_addr %0 to [initialization] [[ADR]] : $*τ_0_0 -// CHECK: [[ALLOCP2:%.*]] = alloc_stack $P -// CHECK: copy_addr [[ALLOCP1]] to [initialization] [[ALLOCP2]] : $*P -// CHECK: copy_addr [take] [[ALLOCP2]] to %1 : $*P -// CHECK: destroy_addr [[ALLOCP1]] : $*P -// CHECK: dealloc_stack [[ALLOCP1]] : $*P +// CHECK: [[ALLOCP2:%.*]] = alloc_stack $any P +// CHECK: copy_addr [[ALLOCP1]] to [initialization] [[ALLOCP2]] : $*any P +// CHECK: copy_addr [take] [[ALLOCP2]] to %1 : $*any P +// CHECK: destroy_addr [[ALLOCP1]] : $*any P +// CHECK: dealloc_stack [[ALLOCP1]] : $*any P // CHECK-LABEL: } // end sil function '$s6test3_6storePyyAA1P_pz_AaC_pztFTf4en_n' sil hidden @$s6test3_6storePyyAA1P_pz_AaC_pztF : $@convention(thin) (@in_guaranteed P, @inout P) -> () { bb0(%0 : $*P, %1 : $*P): @@ -306,19 +306,19 @@ bb0(%0 : $*P, %1 : $*P): return %12 : $() } -// CHECK-LABEL: sil shared @$s6test3_6storePyyAA1P_pz_AaC_pztFTf4en_n4main1SV_Tg5 : $@convention(thin) (@guaranteed S, @inout P) -> () { -// CHECK: bb0(%0 : $S, %1 : $*P): +// CHECK-LABEL: sil shared @$s6test3_6storePyyAA1P_pz_AaC_pztFTf4en_n4main1SV_Tg5 : $@convention(thin) (@guaranteed S, @inout any P) -> () { +// CHECK: bb0(%0 : $S, %1 : $*any P): // CHECK: [[ALLOC1:%.*]] = alloc_stack $S // CHECK: store %0 to [[ALLOC1]] : $*S -// CHECK: [[ALLOC2:%.*]] = alloc_stack $P -// CHECK: [[ADR:%.*]] = init_existential_addr [[ALLOC2]] : $*P, $S +// CHECK: [[ALLOC2:%.*]] = alloc_stack $any P +// CHECK: [[ADR:%.*]] = init_existential_addr [[ALLOC2]] : $*any P, $S // CHECK: copy_addr [[ALLOC1]] to [initialization] [[ADR]] : $*S -// CHECK: [[ALLOC3:%.*]] = alloc_stack $P -// CHECK: copy_addr [[ALLOC2]] to [initialization] [[ALLOC3]] : $*P -// CHECK: copy_addr [take] [[ALLOC3]] to %1 : $*P -// CHECK: dealloc_stack [[ALLOC3]] : $*P -// CHECK: destroy_addr [[ALLOC2]] : $*P -// CHECK: dealloc_stack %4 : $*P +// CHECK: [[ALLOC3:%.*]] = alloc_stack $any P +// CHECK: copy_addr [[ALLOC2]] to [initialization] [[ALLOC3]] : $*any P +// CHECK: copy_addr [take] [[ALLOC3]] to %1 : $*any P +// CHECK: dealloc_stack [[ALLOC3]] : $*any P +// CHECK: destroy_addr [[ALLOC2]] : $*any P +// CHECK: dealloc_stack %4 : $*any P // CHECK: dealloc_stack %2 : $*S // CHECK-LABEL: } // end sil function '$s6test3_6storePyyAA1P_pz_AaC_pztFTf4en_n4main1SV_Tg5' sil hidden @$s6test3_6storeS1s1qyAA1SV_AA1P_pztF : $@convention(thin) (S, @inout P) -> () { @@ -339,12 +339,12 @@ bb0(%0 : $S, %1 : $*P): //===----------------------------------------------------------------------===// // The ExistentialSpecializer cannot specialize on an @inout argument -// CHECK-LABEL: sil hidden @$s6test4_6storePyyAA1P_pz_AaC_pztF : $@convention(thin) (@inout P, @inout P) -> () { -// CHECK: bb0(%0 : $*P, %1 : $*P): -// CHECK: [[ALLOC:%.*]] = alloc_stack $P -// CHECK: copy_addr %0 to [initialization] [[ALLOC]] : $*P -// CHECK: copy_addr [take] [[ALLOC]] to %1 : $*P -// CHECK: dealloc_stack [[ALLOC]] : $*P +// CHECK-LABEL: sil hidden @$s6test4_6storePyyAA1P_pz_AaC_pztF : $@convention(thin) (@inout any P, @inout any P) -> () { +// CHECK: bb0(%0 : $*any P, %1 : $*any P): +// CHECK: [[ALLOC:%.*]] = alloc_stack $any P +// CHECK: copy_addr %0 to [initialization] [[ALLOC]] : $*any P +// CHECK: copy_addr [take] [[ALLOC]] to %1 : $*any P +// CHECK: dealloc_stack [[ALLOC]] : $*any P // CHECK-LABEL: } // end sil function '$s6test4_6storePyyAA1P_pz_AaC_pztF' sil hidden @$s6test4_6storePyyAA1P_pz_AaC_pztF : $@convention(thin) (@inout P, @inout P) -> () { bb0(%0 : $*P, %1 : $*P): @@ -357,16 +357,16 @@ bb0(%0 : $*P, %1 : $*P): } // ...and there's currently no way to propagate the concrete value to the inout argument! -// CHECK-LABEL: sil hidden @$s6test4_6storeS1s1qyAA1SV_AA1P_pztF : $@convention(thin) (S, @inout P) -> () { -// CHECK: bb0(%0 : $S, %1 : $*P): -// CHECK: [[ALLOC:%.*]] = alloc_stack $P, var, name "sp" -// CHECK: [[ADR1:%.*]] = init_existential_addr [[ALLOC]] : $*P, $S +// CHECK-LABEL: sil hidden @$s6test4_6storeS1s1qyAA1SV_AA1P_pztF : $@convention(thin) (S, @inout any P) -> () { +// CHECK: bb0(%0 : $S, %1 : $*any P): +// CHECK: [[ALLOC:%.*]] = alloc_stack $any P, var, name "sp" +// CHECK: [[ADR1:%.*]] = init_existential_addr [[ALLOC]] : $*any P, $S // CHECK: store %0 to [[ADR1]] : $*S -// CHECK: [[ALLOC2:%.*]] = alloc_stack $P -// CHECK: copy_addr %2 to [initialization] %5 : $*P -// CHECK: copy_addr [take] %5 to %1 : $*P -// CHECK: destroy_addr [[ALLOC]] : $*P -// CHECK: dealloc_stack [[ALLOC]] : $*P +// CHECK: [[ALLOC2:%.*]] = alloc_stack $any P +// CHECK: copy_addr %2 to [initialization] %5 : $*any P +// CHECK: copy_addr [take] %5 to %1 : $*any P +// CHECK: destroy_addr [[ALLOC]] : $*any P +// CHECK: dealloc_stack [[ALLOC]] : $*any P // CHECK-LABEL: } // end sil function '$s6test4_6storeS1s1qyAA1SV_AA1P_pztF' sil hidden @$s6test4_6storeS1s1qyAA1SV_AA1P_pztF : $@convention(thin) (S, @inout P) -> () { bb0(%0 : $S, %1 : $*P): @@ -415,9 +415,9 @@ extension ClassB : ProtocolA {} // Pass an existential argument that happens to also have a generic constraint. // // CHECK-LABEL: sil @testExistentialGenericConstraint : $@convention(thin) (@guaranteed ClassB) -> Int { -// CHECK: [[E:%.*]] = init_existential_ref %0 : $ClassB : $ClassB, $ClassA & ProtocolA -// CHECK: [[F:%.*]] = function_ref @testExistentialGenericConstraintHelper : $@convention(thin) <τ_0_0> (@guaranteed ClassA<τ_0_0> & ProtocolA) -> Int -// CHECK: apply [[F]]([[E]]) : $@convention(thin) <τ_0_0> (@guaranteed ClassA<τ_0_0> & ProtocolA) -> Int +// CHECK: [[E:%.*]] = init_existential_ref %0 : $ClassB : $ClassB, $any ClassA & ProtocolA +// CHECK: [[F:%.*]] = function_ref @testExistentialGenericConstraintHelper : $@convention(thin) <τ_0_0> (@guaranteed any ClassA<τ_0_0> & ProtocolA) -> Int +// CHECK: apply [[F]]([[E]]) : $@convention(thin) <τ_0_0> (@guaranteed any ClassA<τ_0_0> & ProtocolA) -> Int // CHECK-LABEL: } // end sil function 'testExistentialGenericConstraint' sil @testExistentialGenericConstraint : $@convention(thin) (@guaranteed ClassB) -> Int { bb0(%0 : $ClassB): @@ -431,8 +431,8 @@ bb0(%0 : $ClassB): // This generic function should not be "specialized" by ExistentialSpecializer, which would add more generic parameters. // -// CHECK-LABEL: sil hidden @testExistentialGenericConstraintHelper : $@convention(thin) (@guaranteed ClassA & ProtocolA) -> Int { -// CHECK: bb0(%0 : $ClassA & ProtocolA): +// CHECK-LABEL: sil hidden @testExistentialGenericConstraintHelper : $@convention(thin) (@guaranteed any ClassA & ProtocolA) -> Int { +// CHECK: bb0(%0 : $any ClassA & ProtocolA): // CHECK-LABEL: } // end sil function 'testExistentialGenericConstraintHelper' sil hidden @testExistentialGenericConstraintHelper : $@convention(thin) (@guaranteed ClassA & ProtocolA) -> Int { bb0(%0 : $ClassA & ProtocolA): diff --git a/test/SILOptimizer/existential_spl_witness_method.swift b/test/SILOptimizer/existential_spl_witness_method.swift index 69b7d3198a450..ab1dc456721db 100644 --- a/test/SILOptimizer/existential_spl_witness_method.swift +++ b/test/SILOptimizer/existential_spl_witness_method.swift @@ -27,13 +27,13 @@ class D : Q { } } -// CHECK-LABEL: @$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTW : $@convention(witness_method: P) (@in_guaranteed Q, @in_guaranteed C) -> Int { +// CHECK-LABEL: @$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTW : $@convention(witness_method: P) (@in_guaranteed any Q, @in_guaranteed C) -> Int { // CHECK: [[FR1:%.*]] = function_ref @$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTWTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (@in_guaranteed τ_0_0, @in_guaranteed C) -> Int // CHECK: apply [[FR1]] // CHECK-LABEL: } // end sil function '$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTW' // CHECK-LABEL : @$s30existential_spl_witness_method3bazyyAA1P_p_AA1Q_ptFTf4ee_n : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P, τ_0_1 : Q> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> () { -// CHECK: [[FR2:%.*]] = function_ref @$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTW : $@convention(witness_method: P) (@in_guaranteed Q, @in_guaranteed C) -> Int +// CHECK: [[FR2:%.*]] = function_ref @$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTW : $@convention(witness_method: P) (@in_guaranteed any Q, @in_guaranteed C) -> Int // CHECK: apply [[FR2]] // CHECK-LABEL: } // end sil function '$s30existential_spl_witness_method3bazyyAA1P_p_AA1Q_ptFTf4ee_n' @inline(never) diff --git a/test/SILOptimizer/existential_transform_extras.sil b/test/SILOptimizer/existential_transform_extras.sil index 4d3e732627c1c..cb60f7bb91c31 100644 --- a/test/SILOptimizer/existential_transform_extras.sil +++ b/test/SILOptimizer/existential_transform_extras.sil @@ -58,8 +58,8 @@ bb0: return %31 : $Int32 } -// CHECK-LABEL: sil public_external [serialized] @$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF : $@convention(thin) (@inout P) -> Int32 { -// CHECK: bb0(%0 : $*P): +// CHECK-LABEL: sil public_external [serialized] @$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF : $@convention(thin) (@inout any P) -> Int32 { +// CHECK: bb0(%0 : $*any P): // CHECK: debug_value {{.*}} expr op_deref // CHECK: alloc_stack // CHECK: copy_addr @@ -92,8 +92,8 @@ bb0: sil_global hidden [let] @$global_var : $P -// CHECK-LABEL: sil hidden [noinline] @$helper : $@convention(thin) (@in P) -> Int32 { -// CHECK: bb0(%0 : $*P): +// CHECK-LABEL: sil hidden [noinline] @$helper : $@convention(thin) (@in any P) -> Int32 { +// CHECK: bb0(%0 : $*any P): // CHECK: debug_value {{.*}} expr op_deref // CHECK: alloc_stack // CHECK: copy_addr @@ -237,9 +237,9 @@ struct Container { // requirements). Relies on assertions during specialization and on // the SILVerifier to catch other inconsistencies. // -// CHECK-LABEL: sil shared @$s40testExistentialSpecializeCompositeHelperTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : PlotLayer, τ_0_0 : InView> (@owned τ_0_0, @inout Container) -> () { -// CHECK: bb0(%0 : $τ_0_0, %1 : $*Container): -// CHECK: init_existential_ref %0 : $τ_0_0 : $τ_0_0, $PlotLayer & InView & Plotable +// CHECK-LABEL: sil shared @$s40testExistentialSpecializeCompositeHelperTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : PlotLayer, τ_0_0 : InView> (@owned τ_0_0, @inout Container) -> () { +// CHECK: bb0(%0 : $τ_0_0, %1 : $*Container): +// CHECK: init_existential_ref %0 : $τ_0_0 : $τ_0_0, $any PlotLayer & InView & Plotable // CHECK-LABEL: } // end sil function '$s40testExistentialSpecializeCompositeHelperTf4en_n' sil shared @testExistentialSpecializeCompositeHelper : $@convention(method) (@owned PlotLayer & Plotable & InView, @inout Container) -> () { bb0(%0 : $PlotLayer & Plotable & InView, %1 : $*Container): diff --git a/test/SILOptimizer/existential_transform_extras_ossa.sil b/test/SILOptimizer/existential_transform_extras_ossa.sil index 51b1ab9a24f2a..11bfb2b7e66b3 100644 --- a/test/SILOptimizer/existential_transform_extras_ossa.sil +++ b/test/SILOptimizer/existential_transform_extras_ossa.sil @@ -78,8 +78,8 @@ bb0: return %31 : $Int32 } -// CHECK-LABEL: sil public_external [serialized] [ossa] @$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF : $@convention(thin) (@inout P) -> Int32 { -// CHECK: bb0(%0 : $*P): +// CHECK-LABEL: sil public_external [serialized] [ossa] @$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF : $@convention(thin) (@inout any P) -> Int32 { +// CHECK: bb0(%0 : $*any P): // CHECK: debug_value {{.*}} expr op_deref // CHECK: alloc_stack // CHECK: copy_addr @@ -112,8 +112,8 @@ bb0: sil_global hidden [let] @$global_var : $P -// CHECK-LABEL: sil hidden [noinline] [ossa] @$helper : $@convention(thin) (@in P) -> Int32 { -// CHECK: bb0(%0 : $*P): +// CHECK-LABEL: sil hidden [noinline] [ossa] @$helper : $@convention(thin) (@in any P) -> Int32 { +// CHECK: bb0(%0 : $*any P): // CHECK: debug_value {{.*}} expr op_deref // CHECK: alloc_stack // CHECK: copy_addr @@ -260,9 +260,9 @@ struct Container { // requirements). Relies on assertions during specialization and on // the SILVerifier to catch other inconsistencies. // -// CHECK-LABEL: sil shared [ossa] @$s40testExistentialSpecializeCompositeHelperTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : PlotLayer, τ_0_0 : InView> (@owned τ_0_0, @inout Container) -> () { -// CHECK: bb0(%0 : @owned $τ_0_0, %1 : $*Container): -// CHECK: init_existential_ref %0 : $τ_0_0 : $τ_0_0, $PlotLayer & InView & Plotable +// CHECK-LABEL: sil shared [ossa] @$s40testExistentialSpecializeCompositeHelperTf4en_n : $@convention(thin) <τ_0_0 where τ_0_0 : PlotLayer, τ_0_0 : InView> (@owned τ_0_0, @inout Container) -> () { +// CHECK: bb0(%0 : @owned $τ_0_0, %1 : $*Container): +// CHECK: init_existential_ref %0 : $τ_0_0 : $τ_0_0, $any PlotLayer & InView & Plotable // CHECK-LABEL: } // end sil function '$s40testExistentialSpecializeCompositeHelperTf4en_n' sil shared [ossa] @testExistentialSpecializeCompositeHelper : $@convention(method) (@owned PlotLayer & Plotable & InView, @inout Container) -> () { bb0(%0 : @owned $PlotLayer & Plotable & InView, %1 : $*Container): diff --git a/test/SILOptimizer/existential_transform_respecialize.sil b/test/SILOptimizer/existential_transform_respecialize.sil index 15fe394de30ae..9a495a895b06e 100644 --- a/test/SILOptimizer/existential_transform_respecialize.sil +++ b/test/SILOptimizer/existential_transform_respecialize.sil @@ -44,7 +44,7 @@ sil [noinline] @$s1t9SomeClassC3fooSiyF : $@convention(method) (@guaranteed Some // The original "wrapFoo" function prior to existential specialization. // // This will be replaced with a thunk by existential specialization. -// CHECK-LABEL: sil hidden [signature_optimized_thunk] [always_inline] @$s1t7wrapFoo1a1bSi_SitAA12SomeProtocol_p_AaE_ptF : $@convention(thin) (@guaranteed SomeProtocol, @guaranteed SomeProtocol) -> (Int, Int) { +// CHECK-LABEL: sil hidden [signature_optimized_thunk] [always_inline] @$s1t7wrapFoo1a1bSi_SitAA12SomeProtocol_p_AaE_ptF : $@convention(thin) (@guaranteed any SomeProtocol, @guaranteed any SomeProtocol) -> (Int, Int) { sil hidden [noinline] @$s1t7wrapFoo1a1bSi_SitAA12SomeProtocol_p_AaE_ptF : $@convention(thin) (@guaranteed SomeProtocol, @guaranteed SomeProtocol) -> (Int, Int) { bb0(%0 : $SomeProtocol, %1 : $SomeProtocol): debug_value %0 : $SomeProtocol, let, name "a", argno 1 diff --git a/test/SILOptimizer/existential_transform_soletype.swift b/test/SILOptimizer/existential_transform_soletype.swift index a477d58285163..00d328ddd168c 100644 --- a/test/SILOptimizer/existential_transform_soletype.swift +++ b/test/SILOptimizer/existential_transform_soletype.swift @@ -17,8 +17,8 @@ internal class SCC: SPP { return opt2(b:b) } -// CHECK-LABEL: sil hidden [noinline] @$s30existential_transform_soletype4opt11bs5Int32VAA3SPP_p_tF : $@convention(thin) (@in_guaranteed SPP) -> Int32 { -// CHECK: bb0(%0 : $*SPP): +// CHECK-LABEL: sil hidden [noinline] @$s30existential_transform_soletype4opt11bs5Int32VAA3SPP_p_tF : $@convention(thin) (@in_guaranteed any SPP) -> Int32 { +// CHECK: bb0(%0 : $*any SPP): // CHECK: debug_value {{.*}} expr op_deref // CHECK: function_ref @$s30existential_transform_soletype4opt21bs5Int32VAA3SPP_p_tFTf4e_n : $@convention(thin) <τ_0_0 where τ_0_0 : SPP> (@in_guaranteed τ_0_0) -> Int32 // user: %4 // CHECK: open_existential_addr diff --git a/test/SILOptimizer/for_each_loop_unroll_test.sil b/test/SILOptimizer/for_each_loop_unroll_test.sil index 31030a1860676..652a71e505096 100644 --- a/test/SILOptimizer/for_each_loop_unroll_test.sil +++ b/test/SILOptimizer/for_each_loop_unroll_test.sil @@ -8,9 +8,9 @@ import Builtin sil [_semantics "array.uninitialized_intrinsic"] @_allocateUninitializedArray : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) -sil [_semantics "sequence.forEach"] @forEach : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error Error, @in_guaranteed τ_0_0) -> @error Error +sil [_semantics "sequence.forEach"] @forEach : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error any Error, @in_guaranteed τ_0_0) -> @error any Error -sil @forEachBody : $@convention(thin) (@in_guaranteed Builtin.Int64) -> @error Error +sil @forEachBody : $@convention(thin) (@in_guaranteed Builtin.Int64) -> @error any Error sil hidden [ossa] @forEachLoopUnrollTest : $@convention(thin) () -> () { bb0: @@ -28,9 +28,9 @@ bb0: %21 = begin_borrow %3 : $Array %22 = alloc_stack $Array %23 = store_borrow %21 to %22 : $*Array - %24 = function_ref @forEachBody : $@convention(thin) (@in_guaranteed Builtin.Int64) -> @error Error - %25 = convert_function %24 : $@convention(thin) (@in_guaranteed Builtin.Int64) -> @error Error to $@convention(thin) @noescape (@in_guaranteed Builtin.Int64) -> @error Error - %26 = thin_to_thick_function %25 : $@convention(thin) @noescape (@in_guaranteed Builtin.Int64) -> @error Error to $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error Error + %24 = function_ref @forEachBody : $@convention(thin) (@in_guaranteed Builtin.Int64) -> @error any Error + %25 = convert_function %24 : $@convention(thin) (@in_guaranteed Builtin.Int64) -> @error any Error to $@convention(thin) @noescape (@in_guaranteed Builtin.Int64) -> @error any Error + %26 = thin_to_thick_function %25 : $@convention(thin) @noescape (@in_guaranteed Builtin.Int64) -> @error any Error to $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error any Error // A stub for Sequence.forEach(_:) %30 = function_ref @forEach : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error Error, @in_guaranteed τ_0_0) -> @error Error try_apply %30<[Builtin.Int64]>(%26, %23) : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error Error, @in_guaranteed τ_0_0) -> @error Error, normal bb1, error bb2 @@ -53,17 +53,17 @@ bb2(%39 : @owned $Error): // CHECK-NOT: forEach // CHECK: [[STACK:%[0-9]+]] = alloc_stack $Builtin.Int64 // CHECK: store [[LIT1]] to [trivial] [[STACK]] -// CHECK: try_apply [[BODYCLOSURE]]([[STACK]]) : $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error Error, normal [[NORMAL:bb[0-9]+]], error [[ERROR:bb[0-9]+]] +// CHECK: try_apply [[BODYCLOSURE]]([[STACK]]) : $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error any Error, normal [[NORMAL:bb[0-9]+]], error [[ERROR:bb[0-9]+]] -// CHECK: [[ERROR]]([[ERRPARAM:%[0-9]+]] : @owned $Error): -// CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM]] : $Error) +// CHECK: [[ERROR]]([[ERRPARAM:%[0-9]+]] : @owned $any Error): +// CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM]] : $any Error) // CHECK: [[NORMAL]](%{{.*}} : $()): // CHECK: store [[LIT2]] to [trivial] [[STACK]] : $*Builtin.Int64 -// CHECK: try_apply [[BODYCLOSURE]]([[STACK]]) : $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error Error, normal [[NORMAL2:bb[0-9]+]], error [[ERROR2:bb[0-9]+]] +// CHECK: try_apply [[BODYCLOSURE]]([[STACK]]) : $@noescape @callee_guaranteed (@in_guaranteed Builtin.Int64) -> @error any Error, normal [[NORMAL2:bb[0-9]+]], error [[ERROR2:bb[0-9]+]] -// CHECK: [[ERROR2]]([[ERRPARAM2:%[0-9]+]] : @owned $Error): -// CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM2]] : $Error) +// CHECK: [[ERROR2]]([[ERRPARAM2:%[0-9]+]] : @owned $any Error): +// CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM2]] : $any Error) // CHECK: [[NORMAL2]](%{{.*}} : $()): // CHECK: dealloc_stack [[STACK]] @@ -71,11 +71,11 @@ bb2(%39 : @owned $Error): // will be cleaned up when the forEach call is removed. // CHECK: destroy_value -// CHECK: [[ERROR3]]([[ERRPARAM3:%[0-9]+]] : @owned $Error): +// CHECK: [[ERROR3]]([[ERRPARAM3:%[0-9]+]] : @owned $any Error): // CHECK: dealloc_stack [[STACK]] // CHECK: unreachable -sil @forEachBody2 : $@convention(thin) (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error Error +sil @forEachBody2 : $@convention(thin) (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error any Error sil hidden [ossa] @nonTrivialForEachLoopUnrollTest : $@convention(thin) (@owned @callee_guaranteed @substituted () -> @out A for , @owned @callee_guaranteed @substituted () -> @out A for ) -> () { bb0(%0: @owned $@callee_guaranteed @substituted () -> @out A for , %1: @owned $@callee_guaranteed @substituted () -> @out A for ): @@ -91,9 +91,9 @@ bb0(%0: @owned $@callee_guaranteed @substituted () -> @out A for , %1: %21 = begin_borrow %5 : $Array<()->Int> %22 = alloc_stack $Array<()->Int> %23 = store_borrow %21 to %22 : $*Array<()->Int> - %24 = function_ref @forEachBody2 : $@convention(thin) (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error Error - %25 = convert_function %24 : $@convention(thin) (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error Error to $@convention(thin) @noescape (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error Error - %26 = thin_to_thick_function %25 : $@convention(thin) @noescape (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error Error to $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error Error + %24 = function_ref @forEachBody2 : $@convention(thin) (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error any Error + %25 = convert_function %24 : $@convention(thin) (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error any Error to $@convention(thin) @noescape (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error any Error + %26 = thin_to_thick_function %25 : $@convention(thin) @noescape (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error any Error to $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted () -> @out A for ) -> @error any Error // A stub for Sequence.forEach(_:) %30 = function_ref @forEach : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error Error, @in_guaranteed τ_0_0) -> @error Error try_apply %30<[() -> Int]>(%26, %23) : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error Error, @in_guaranteed τ_0_0) -> @error Error, normal bb1, error bb2 @@ -119,19 +119,19 @@ bb2(%39 : @owned $Error): // CHECK: [[STACK:%[0-9]+]] = alloc_stack $@callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for // CHECK: [[ELEM1BORROW:%[0-9]+]] = begin_borrow [[ELEM1]] // CHECK: [[SB1:%.*]] = store_borrow [[ELEM1BORROW]] to [[STACK]] -// CHECK: try_apply [[BODYCLOSURE]]([[SB1]]) : $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for ) -> @error Error, normal [[NORMAL:bb[0-9]+]], error [[ERROR:bb[0-9]+]] +// CHECK: try_apply [[BODYCLOSURE]]([[SB1]]) : $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for ) -> @error any Error, normal [[NORMAL:bb[0-9]+]], error [[ERROR:bb[0-9]+]] -// CHECK: [[ERROR]]([[ERRPARAM:%[0-9]+]] : @owned $Error): -// CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM]] : $Error) +// CHECK: [[ERROR]]([[ERRPARAM:%[0-9]+]] : @owned $any Error): +// CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM]] : $any Error) // CHECK: [[NORMAL]](%{{.*}} : $()): // CHECK: end_borrow [[ELEM1BORROW]] // CHECK: [[ELEM2BORROW:%[0-9]+]] = begin_borrow [[ELEM2]] // CHECK: [[SB2:%.*]] = store_borrow [[ELEM2BORROW]] to [[STACK]] -// CHECK: try_apply [[BODYCLOSURE]]([[SB2]]) : $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for ) -> @error Error, normal [[NORMAL2:bb[0-9]+]], error [[ERROR2:bb[0-9]+]] +// CHECK: try_apply [[BODYCLOSURE]]([[SB2]]) : $@noescape @callee_guaranteed (@in_guaranteed @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for ) -> @error any Error, normal [[NORMAL2:bb[0-9]+]], error [[ERROR2:bb[0-9]+]] -// CHECK: [[ERROR2]]([[ERRPARAM2:%[0-9]+]] : @owned $Error): -// CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM2]] : $Error) +// CHECK: [[ERROR2]]([[ERRPARAM2:%[0-9]+]] : @owned $any Error): +// CHECK: br [[ERROR3:bb[0-9]+]]([[ERRPARAM2]] : $any Error) // CHECK: [[NORMAL2]](%{{.*}} : $()): // CHECK: dealloc_stack [[STACK]] @@ -140,7 +140,7 @@ bb2(%39 : @owned $Error): // will be cleaned up when the forEach call is removed. // CHECK: destroy_value -// CHECK: [[ERROR3]]([[ERRPARAM3:%[0-9]+]] : @owned $Error): +// CHECK: [[ERROR3]]([[ERRPARAM3:%[0-9]+]] : @owned $any Error): // CHECK: dealloc_stack [[STACK]] // CHECK: unreachable @@ -185,7 +185,7 @@ bb2(%39 : @owned $Error): unreachable } // CHECK-LABEL: @checkIndirectFixLifetimeUsesAreIgnored -// CHECK-NOT: function_ref @forEach : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error Error, @in_guaranteed τ_0_0) -> @error Error +// CHECK-NOT: function_ref @forEach : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error any Error, @in_guaranteed τ_0_0) -> @error any Error // CHECK: end sil function 'checkIndirectFixLifetimeUsesAreIgnored' sil hidden [ossa] @testUnrollOfArrayWithPhiArguments : $@convention(thin) () -> () { @@ -225,6 +225,6 @@ bb4(%39 : @owned $Error): unreachable } // CHECK-LABEL: @testUnrollOfArrayWithPhiArguments -// CHECK-NOT: function_ref @forEach : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error Error, @in_guaranteed τ_0_0) -> @error Error +// CHECK-NOT: function_ref @forEach : $@convention(method) <τ_0_0 where τ_0_0 : Sequence> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @error any Error, @in_guaranteed τ_0_0) -> @error any Error // CHECK: end sil function 'testUnrollOfArrayWithPhiArguments' diff --git a/test/SILOptimizer/functionsigopts.sil b/test/SILOptimizer/functionsigopts.sil index c4faee425fc26..42247565c676d 100644 --- a/test/SILOptimizer/functionsigopts.sil +++ b/test/SILOptimizer/functionsigopts.sil @@ -554,8 +554,8 @@ bb3(%35 : $IndirectEnum): // Make sure we do not move the retain_value in the throw block. // -// CHECK-LABEL: sil [serialized] [signature_optimized_thunk] [always_inline] @owned_to_unowned_retval_with_error_result : $@convention(thin) (@owned boo) -> (@owned boo, @error Error) { -// CHECK: function_ref @$s41owned_to_unowned_retval_with_error_resultTfq4n_g : $@convention(thin) (@owned boo) -> (boo, @error Error) +// CHECK-LABEL: sil [serialized] [signature_optimized_thunk] [always_inline] @owned_to_unowned_retval_with_error_result : $@convention(thin) (@owned boo) -> (@owned boo, @error any Error) { +// CHECK: function_ref @$s41owned_to_unowned_retval_with_error_resultTfq4n_g : $@convention(thin) (@owned boo) -> (boo, @error any Error) // CHECK: bb1 // CHECK-NOT: retain_value // CHECK: bb2 @@ -864,13 +864,13 @@ bb0(%0 : $goo): //======================================== // @owned => @guaranteed with error result -// CHECK-LABEL: sil [serialized] [signature_optimized_thunk] [always_inline] @owned_to_guaranteed_with_error_result : $@convention(thin) (@owned Builtin.NativeObject, Int) -> (Int, @error Error) { +// CHECK-LABEL: sil [serialized] [signature_optimized_thunk] [always_inline] @owned_to_guaranteed_with_error_result : $@convention(thin) (@owned Builtin.NativeObject, Int) -> (Int, @error any Error) { // CHECK: [[FUNC_REF:%[0-9]+]] = function_ref @$s37owned_to_guaranteed_with_error_resultTfq4gn_n : $@convention(thin) (@guaranteed Builtin.NativeObject, Int) // CHECK: try_apply [[FUNC_REF]]({{.*}}, normal bb1, error bb2 // CHECK: bb1([[NORMRET:%[0-9]+]] : $Int): // CHECK-NEXT: release_value // CHECK-NEXT: return [[NORMRET]] -// CHECK: bb2([[THROW:%[0-9]+]] : $Error): +// CHECK: bb2([[THROW:%[0-9]+]] : $any Error): // CHECK-NEXT: release_value // CHECK-NEXT: throw [[THROW]] sil [serialized] @owned_to_guaranteed_with_error_result : $@convention(thin) (@owned Builtin.NativeObject, Int) -> (Int, @error Error) { @@ -912,12 +912,12 @@ bb2: throw undef : $Error } -// CHECK-LABEL: sil [serialized] @owned_to_guaranteed_with_error_caller : $@convention(thin) (Builtin.NativeObject, Int) -> (Int, @error Error) { +// CHECK-LABEL: sil [serialized] @owned_to_guaranteed_with_error_caller : $@convention(thin) (Builtin.NativeObject, Int) -> (Int, @error any Error) { // CHECK: [[FUNC_REF:%[0-9]+]] = function_ref @$s37owned_to_guaranteed_with_error_resultTfq4gn_n : $@convention(thin) (@guaranteed Builtin.NativeObject, Int) // CHECK: try_apply [[FUNC_REF]]({{.*}}, normal bb1, error bb2 // CHECK: bb1([[NORMRET:%[0-9]+]] : $Int): // CHECK-NEXT: release_value -// CHECK: bb2([[THROW:%[0-9]+]] : $Error): +// CHECK: bb2([[THROW:%[0-9]+]] : $any Error): // CHECK-NEXT: release_value sil [serialized] @owned_to_guaranteed_with_error_caller : $@convention(thin) (Builtin.NativeObject, Int) -> (Int, @error Error) { bb0(%0 : $Builtin.NativeObject, %1 : $Int): @@ -936,7 +936,7 @@ bb2(%a2 : $Error): // CHECK: try_apply [[FUNC_REF]]({{.*}}, normal bb1, error bb2 // CHECK: bb1([[NORMRET:%[0-9]+]] : $Int): // CHECK-NEXT: release_value -// CHECK: bb2([[THROW:%[0-9]+]] : $Error): +// CHECK: bb2([[THROW:%[0-9]+]] : $any Error): // CHECK-NEXT: release_value sil [serialized] @owned_to_guaranteed_with_nothrow_caller : $@convention(thin) (Builtin.NativeObject, Int) -> Int { bb0(%0 : $Builtin.NativeObject, %1 : $Int): @@ -950,7 +950,7 @@ bb0(%0 : $Builtin.NativeObject, %1 : $Int): sil @test_dealloc_partial_ref_callee : $@convention(thin) () -> ((), @error Error) -// CHECK-LABEL: sil hidden @test_dealloc_partial_ref : $@convention(thin) (@owned foo) -> (@owned foo, @error Error) { +// CHECK-LABEL: sil hidden @test_dealloc_partial_ref : $@convention(thin) (@owned foo) -> (@owned foo, @error any Error) { // CHECK-NOT: @guaranteed // CHECK: function_ref @test_dealloc_partial_ref_callee // CHECK-NOT: @guaranteed @@ -1826,7 +1826,7 @@ bb0(%0 : $*T): // CHECK-NOT: retain_value // CHECK: return -// CHECK-LABEL: @$s41owned_to_unowned_retval_with_error_resultTfq4n_g : $@convention(thin) (@owned boo) -> (boo, @error Error) { +// CHECK-LABEL: @$s41owned_to_unowned_retval_with_error_resultTfq4n_g : $@convention(thin) (@owned boo) -> (boo, @error any Error) { // CHECK: bb2 // CHECK: retain_value // CHECK: throw @@ -1851,7 +1851,7 @@ bb0(%0 : $*T): // CHECK-LABEL: sil private @$s31private_dead_arg_with_callsitesTf4dn_n : $@convention(thin) (Builtin.NativeObject) -> () { // CHECK: bb0( -// CHECK-LABEL: sil shared [serialized] @$s37owned_to_guaranteed_with_error_resultTfq4gn_n : $@convention(thin) (@guaranteed Builtin.NativeObject, Int) -> (Int, @error Error) { +// CHECK-LABEL: sil shared [serialized] @$s37owned_to_guaranteed_with_error_resultTfq4gn_n : $@convention(thin) (@guaranteed Builtin.NativeObject, Int) -> (Int, @error any Error) { // CHECK-NOT: release // CHECK: throw diff --git a/test/SILOptimizer/inline_lifetime.sil b/test/SILOptimizer/inline_lifetime.sil index 8838f9c5e7c77..fccd1618e9b31 100644 --- a/test/SILOptimizer/inline_lifetime.sil +++ b/test/SILOptimizer/inline_lifetime.sil @@ -414,7 +414,7 @@ bb2: // tests -// CHECK-LABEL: sil [ossa] @caller_owned_callee_error_owned : $@convention(thin) (@owned C) -> @error Error { +// CHECK-LABEL: sil [ossa] @caller_owned_callee_error_owned : $@convention(thin) (@owned C) -> @error any Error { // CHECK-NOT: begin_borrow [lexical] // CHECK-LABEL: } // end sil function 'caller_owned_callee_error_owned' sil [ossa] @caller_owned_callee_error_owned : $@convention(thin) (@owned C) -> @error Error { @@ -429,7 +429,7 @@ bb2(%12 : @owned $Error): throw %12 : $Error } -// CHECK-LABEL: sil [ossa] @caller_owned_callee_error_guaranteed : $@convention(thin) (@owned C) -> @error Error { +// CHECK-LABEL: sil [ossa] @caller_owned_callee_error_guaranteed : $@convention(thin) (@owned C) -> @error any Error { // CHECK: {{bb[^,]+}}([[INSTANCE:%[^,]+]] : @owned $C): // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INSTANCE]] // CHECK: cond_br undef, [[THROW_BLOCK:bb[^,]+]], [[REGULAR_BLOCK:bb[0-9]+]] @@ -457,7 +457,7 @@ bb2(%12 : @owned $Error): throw %12 : $Error } -// CHECK-LABEL: sil [ossa] @caller_guaranteed_callee_error_owned : $@convention(thin) (@guaranteed C) -> @error Error { +// CHECK-LABEL: sil [ossa] @caller_guaranteed_callee_error_owned : $@convention(thin) (@guaranteed C) -> @error any Error { // CHECK-NOT: begin_borrow [lexical] // CHECK-LABEL: } // end sil function 'caller_guaranteed_callee_error_owned' sil [ossa] @caller_guaranteed_callee_error_owned : $@convention(thin) (@guaranteed C) -> @error Error { @@ -472,7 +472,7 @@ bb2(%12 : @owned $Error): throw %12 : $Error } -// CHECK-LABEL: sil [ossa] @caller_guaranteed_callee_error_guaranteed : $@convention(thin) (@guaranteed C) -> @error Error { +// CHECK-LABEL: sil [ossa] @caller_guaranteed_callee_error_guaranteed : $@convention(thin) (@guaranteed C) -> @error any Error { // CHECK: {{bb[^,]+}}([[INSTANCE:%[^,]+]] : @guaranteed $C): // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INSTANCE]] // CHECK: cond_br undef, [[THROW_BLOCK:bb[^,]+]], [[REGULAR_BLOCK:bb[0-9]+]] @@ -496,7 +496,7 @@ bb2(%12 : @owned $Error): throw %12 : $Error } -// CHECK-LABEL: sil hidden [ossa] @caller_trivial_callee_error_trivial : $@convention(thin) (S) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @caller_trivial_callee_error_trivial : $@convention(thin) (S) -> @error any Error { // CHECK: {{bb[^,]+}}({{%[^,]+}} : $S): // CHECK: cond_br undef, [[THROW_BLOCK:bb[^,]+]], [[REGULAR_BLOCK:bb[0-9]+]] // CHECK: [[THROW_BLOCK]]: @@ -517,7 +517,7 @@ bb2(%12 : @owned $Error): throw %12 : $Error } -// CHECK-LABEL: sil hidden [ossa] @caller_in_callee_error_in : $@convention(thin) (@in S) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @caller_in_callee_error_in : $@convention(thin) (@in S) -> @error any Error { // CHECK: {{bb[^,]+}}({{%[^,]+}} : $*S): // CHECK: cond_br undef, [[THROW_BLOCK:bb[0-9]+]], [[REGULAR_BLOCK:bb[0-9]+]] // CHECK: [[THROW_BLOCK]]: @@ -538,7 +538,7 @@ bb2(%12 : @owned $Error): throw %12 : $Error } -// CHECK-LABEL: sil hidden [ossa] @caller_inguaranteed_callee_error_inguaranteed : $@convention(thin) (@in_guaranteed T) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @caller_inguaranteed_callee_error_inguaranteed : $@convention(thin) (@in_guaranteed T) -> @error any Error { // CHECK-NOT: begin_borrow [lexical] // CHECK-LABEL: // end sil function 'caller_inguaranteed_callee_error_inguaranteed' sil hidden [ossa] @caller_inguaranteed_callee_error_inguaranteed : $@convention(thin) (@in_guaranteed T) -> @error Error { diff --git a/test/SILOptimizer/inline_subclass_existential.swift b/test/SILOptimizer/inline_subclass_existential.swift index 3c949bd08a875..e865ebe4cf409 100644 --- a/test/SILOptimizer/inline_subclass_existential.swift +++ b/test/SILOptimizer/inline_subclass_existential.swift @@ -5,16 +5,16 @@ protocol P { func f() } -// CHECK-LABEL: sil hidden [transparent] @$s27inline_subclass_existential3fooyyAA1P_AA1CCyxGXclF : $@convention(thin) (@guaranteed C & P) -> () { -// CHECK: open_existential_ref %0 : $C & P to $@opened("{{.*}}", C & P) Self +// CHECK-LABEL: sil hidden [transparent] @$s27inline_subclass_existential3fooyyAA1P_AA1CCyxGXclF : $@convention(thin) (@guaranteed any C & P) -> () { +// CHECK: open_existential_ref %0 : $any C & P to $@opened("{{.*}}", any C & P) Self // CHECK: return @_transparent func foo(_ x: C & P) { x.f() } -// CHECK-LABEL: sil hidden @$s27inline_subclass_existential3baryyAA1P_AA1CCySiGXcF : $@convention(thin) (@guaranteed C & P) -> () { -// CHECK: open_existential_ref %0 : $C & P to $@opened("{{.*}}", C & P) Self +// CHECK-LABEL: sil hidden @$s27inline_subclass_existential3baryyAA1P_AA1CCySiGXcF : $@convention(thin) (@guaranteed any C & P) -> () { +// CHECK: open_existential_ref %0 : $any C & P to $@opened("{{.*}}", any C & P) Self // CHECK: return func bar(_ x: C & P) { foo(x) diff --git a/test/SILOptimizer/inline_tryApply.sil b/test/SILOptimizer/inline_tryApply.sil index 6f423e5ff2a2b..c4e160b616595 100644 --- a/test/SILOptimizer/inline_tryApply.sil +++ b/test/SILOptimizer/inline_tryApply.sil @@ -9,7 +9,7 @@ import SwiftShims //CHECK-LABEL: sil @caller_function //CHECK-NOT: try_apply -//CHECK: throw {{.*}} : $Error +//CHECK: throw {{.*}} : $any Error sil @caller_function : $@convention(thin) () -> @error Error { bb0: // function_ref main.inner () throws -> () diff --git a/test/SILOptimizer/lexical_destroy_hoisting.sil b/test/SILOptimizer/lexical_destroy_hoisting.sil index 8cff942dcdc00..cca95d5ce2931 100644 --- a/test/SILOptimizer/lexical_destroy_hoisting.sil +++ b/test/SILOptimizer/lexical_destroy_hoisting.sil @@ -385,7 +385,7 @@ bad(%15 : @owned $Error): // CHECK: try_apply undef() : {{.*}}, normal [[GOOD:bb[0-9]+]], error [[BAD:bb[0-9]+]] // CHECK: [[GOOD]]({{%[^,]+}} : $()): // CHECK: destroy_value [[INSTANCE]] -// CHECK: [[BAD]]([[ERROR:%[^,]+]] : @owned $Error): +// CHECK: [[BAD]]([[ERROR:%[^,]+]] : @owned $any Error): // CHECK: destroy_value [[INSTANCE]] // CHECK: throw [[ERROR]] // CHECK-LABEL: } // end sil function 'dont_hoist_over_try_apply_barrier' diff --git a/test/SILOptimizer/licm.sil b/test/SILOptimizer/licm.sil index 46966d3c6e9fd..3cedfd7af761d 100644 --- a/test/SILOptimizer/licm.sil +++ b/test/SILOptimizer/licm.sil @@ -229,7 +229,7 @@ public protocol P : class { // CHECK-LABEL: sil @dont_hoist_metatype // CHECK-NOT: metatype // CHECK-NOT: witness_method -// CHECK: bb1({{%.*}} : $P) +// CHECK: bb1({{%.*}} : $any P) // CHECK-NOT: metatype // CHECK-NOT: witness_method // CHECK: open_existential_ref diff --git a/test/SILOptimizer/mandatory_combiner.sil b/test/SILOptimizer/mandatory_combiner.sil index 487cdeda26307..67aadff9008a7 100644 --- a/test/SILOptimizer/mandatory_combiner.sil +++ b/test/SILOptimizer/mandatory_combiner.sil @@ -348,7 +348,7 @@ bb0: ///////////////// // All existential arguments. Partial apply arguments. Apply arguments. -// CHECK-LABEL: sil hidden @existential_capture_args : $@convention(thin) () -> @out Proto { +// CHECK-LABEL: sil hidden @existential_capture_args : $@convention(thin) () -> @out any Proto { // CHECK: [[FUNCTION_REF:%.*]] = function_ref @first_of_three_protos // CHECK: [[PARTIAL_APPLY_RESULT:%.*]] = partial_apply [callee_guaranteed] [[FUNCTION_REF]]({{%.*}}, {{%.*}}) : // Use %0 explicitly because that is the out parameter. @@ -392,7 +392,7 @@ bb0(%0 : $*Proto): /////////// // Mixed arguments. Trivial partial apply argument. Existential argument. -// CHECK-LABEL: sil hidden @mixed_trivialcapture_existentialarg : $@convention(thin) () -> @out Proto { +// CHECK-LABEL: sil hidden @mixed_trivialcapture_existentialarg : $@convention(thin) () -> @out any Proto { // CHECK: [[FUNCTION_REF:%.*]] = function_ref @proto_from_proto_and_myint // CHECK: [[PARTIAL_APPLY_RESULT:%.*]] = partial_apply [callee_guaranteed] [[FUNCTION_REF]]({{%.*}}) : // Use %0 explicitly because that is the out parameter. @@ -748,7 +748,7 @@ bb0: ///////////////// // All existential arguments. Partial apply arguments. Apply arguments. OSSA. -// CHECK-LABEL: sil [ossa] @existential_capture_args_ossa : $@convention(thin) () -> @out Proto { +// CHECK-LABEL: sil [ossa] @existential_capture_args_ossa : $@convention(thin) () -> @out any Proto { // CHECK: [[FUNCTION_REF:%.*]] = function_ref @first_of_three_protos // CHECK: [[PARTIAL_APPLY_RESULT:%.*]] = partial_apply [callee_guaranteed] [[FUNCTION_REF]]({{%.*}}, {{%.*}}) : // Use %0 explicitly because that is the out parameter. @@ -790,7 +790,7 @@ bb0(%0 : $*Proto): /////////// // Mixed arguments. Trivial partial apply argument. Existential argument. OSSA. -// CHECK-LABEL: sil [ossa] @mixed_trivialcapture_existentialarg_ossa : $@convention(thin) () -> @out Proto { +// CHECK-LABEL: sil [ossa] @mixed_trivialcapture_existentialarg_ossa : $@convention(thin) () -> @out any Proto { // CHECK: [[FUNCTION_REF:%.*]] = function_ref @proto_from_proto_and_myint // CHECK: [[PARTIAL_APPLY_RESULT:%.*]] = partial_apply [callee_guaranteed] [[FUNCTION_REF]]({{%.*}}) : // Use %0 explicitly because that is the out parameter. diff --git a/test/SILOptimizer/mandatory_inlining.sil b/test/SILOptimizer/mandatory_inlining.sil index 813c21e8ed423..cab348fb1e121 100644 --- a/test/SILOptimizer/mandatory_inlining.sil +++ b/test/SILOptimizer/mandatory_inlining.sil @@ -182,7 +182,7 @@ bb0(%0 : $Int64): protocol SomeProtocol { } -// CHECK-LABEL: sil [transparent] @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type +// CHECK-LABEL: sil [transparent] @test_existential_metatype : $@convention(thin) (@in any SomeProtocol) -> @thick any SomeProtocol.Type sil [transparent] @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type { bb0(%0 : $*SomeProtocol): %1 = alloc_box ${ var SomeProtocol } @@ -197,15 +197,15 @@ bb0(%0 : $*SomeProtocol): return %6 : $@thick SomeProtocol.Type } -// CHECK-LABEL: sil @inline_test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type +// CHECK-LABEL: sil @inline_test_existential_metatype : $@convention(thin) (@in any SomeProtocol) -> @thick any SomeProtocol.Type sil @inline_test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type { -// CHECK: [[BB0:.*]]([[VAL0:%.*]] : $*SomeProtocol): - // CHECK: [[VAL1:%.*]] = alloc_box ${ var SomeProtocol } +// CHECK: [[BB0:.*]]([[VAL0:%.*]] : $*any SomeProtocol): + // CHECK: [[VAL1:%.*]] = alloc_box ${ var any SomeProtocol } // CHECK: [[PB1:%.*]] = project_box [[VAL1]] // CHECK: copy_addr [take] %0 to [initialization] [[PB1]] - // CHECK: [[VAL4:%.*]] = alloc_stack $SomeProtocol + // CHECK: [[VAL4:%.*]] = alloc_stack $any SomeProtocol // CHECK: copy_addr [[PB1]] to [initialization] [[VAL4]] - // CHECK: [[VAL6:%.*]] = existential_metatype $@thick SomeProtocol.Type, [[VAL4]] + // CHECK: [[VAL6:%.*]] = existential_metatype $@thick any SomeProtocol.Type, [[VAL4]] // CHECK: destroy_addr [[VAL4]] // CHECK: dealloc_stack [[VAL4]] // CHECK: strong_release [[VAL1]] @@ -726,11 +726,11 @@ sil @_TF2t222outer_open_existentialFT3cp1PS_2CP_3cp2PS0___T_ : $@convention(thin bb0(%0 : $CP, %1 : $CP): %4 = function_ref @_TF2t222inner_open_existentialFT2cpPS_2CP__T_ : $@convention(thin) (@owned CP) -> () // user: %6 strong_retain %0 : $CP // id: %5 - // CHECK: open_existential_ref %0 : $CP to $@opened([[N1:".*"]], CP) Self + // CHECK: open_existential_ref %0 : $any CP to $@opened([[N1:".*"]], any CP) Self %6 = apply %4(%0) : $@convention(thin) (@owned CP) -> () %7 = function_ref @_TF2t222inner_open_existentialFT2cpPS_2CP__T_ : $@convention(thin) (@owned CP) -> () // user: %9 strong_retain %1 : $CP // id: %8 - // CHECK: open_existential_ref %1 : $CP to $@opened([[N2:".*"]], CP) Self + // CHECK: open_existential_ref %1 : $any CP to $@opened([[N2:".*"]], any CP) Self %9 = apply %7(%1) : $@convention(thin) (@owned CP) -> () strong_release %1 : $CP // id: %10 strong_release %0 : $CP // id: %11 @@ -840,8 +840,8 @@ bb0(%0 : $Foo): %2 = function_ref @protocolConstrained : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@owned τ_0_0) -> () strong_retain %0 : $Foo // CHECK-NOT: apply - // CHECK: [[METHOD:%[a-zA-Z0-9]+]] = objc_method %0 : $Foo, #Foo.foo!foreign : {{.*}}, $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () - // CHECK: apply [[METHOD]](%0) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () + // CHECK: [[METHOD:%[a-zA-Z0-9]+]] = objc_method %0 : $any Foo, #Foo.foo!foreign : {{.*}}, $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () + // CHECK: apply [[METHOD]](%0) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () %4 = apply %2(%0) : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@owned τ_0_0) -> () strong_release %0 : $Foo %6 = tuple () @@ -988,7 +988,7 @@ bb0(%0 : $*Self): // Check that P2_s call can be properly inlined and the resulting witness_method instruction // uses the opened archetype from the caller. // CHECK-LABEL: sil hidden @L_start -// CHECK: open_existential_addr immutable_access {{.*}}$*@[[OPENED_ARCHETYPE:opened\("[A-Z0-9-]+", P2\) Self]] +// CHECK: open_existential_addr immutable_access {{.*}}$*@[[OPENED_ARCHETYPE:opened\("[A-Z0-9-]+", any P2\) Self]] // CHECK: witness_method $@[[OPENED_ARCHETYPE]], #P2.c!getter : {{.*}}, %{{[0-9]+}} : $*@[[OPENED_ARCHETYPE]] // CHECK: return sil hidden @L_start : $@convention(method) (@in_guaranteed L) -> Int32 { @@ -1023,11 +1023,11 @@ bb0(%0 : $Optional): // CHECK-LABEL: sil @testMandatoryConverted : $@convention(thin) (C) -> C { // CHECK: bb0(%0 : $C): // CHECK: [[F1:%.*]] = function_ref @testMandatoryConvertedHelper : $@convention(thin) (C) -> C -// CHECK: [[CVT1:%.*]] = convert_function [[F1]] : $@convention(thin) (C) -> C to $@convention(thin) (C) -> (C, @error Error) -// CHECK: try_apply [[CVT1]](%0) : $@convention(thin) (C) -> (C, @error Error), normal bb1, error bb2 +// CHECK: [[CVT1:%.*]] = convert_function [[F1]] : $@convention(thin) (C) -> C to $@convention(thin) (C) -> (C, @error any Error) +// CHECK: try_apply [[CVT1]](%0) : $@convention(thin) (C) -> (C, @error any Error), normal bb1, error bb2 // CHECK: bb1(%{{.*}} : $C): // CHECK: br bb3(%{{.*}} : $C) -// CHECK: bb2(%{{.*}} : $Error): +// CHECK: bb2(%{{.*}} : $any Error): // CHECK: [[F2:%.*]] = function_ref @testMandatoryConvertedHelper2 : $@convention(thin) (Optional) -> C // CHECK: [[CVT2:%.*]] = convert_function [[F2]] : $@convention(thin) (Optional) -> C to $@convention(thin) (C) -> C // CHECK: %{{.*}} = apply [[CVT2]](%0) : $@convention(thin) (C) -> C diff --git a/test/SILOptimizer/mandatory_inlining_devirt.swift b/test/SILOptimizer/mandatory_inlining_devirt.swift index d6c836abab40d..16152e7c35e19 100644 --- a/test/SILOptimizer/mandatory_inlining_devirt.swift +++ b/test/SILOptimizer/mandatory_inlining_devirt.swift @@ -42,10 +42,10 @@ public struct Concrete : Thrower { public func fail() throws {} } -// CHECK-LABEL: sil @$s4test6calleryyAA8ConcreteVKF : $@convention(thin) (Concrete) -> @error Error +// CHECK-LABEL: sil @$s4test6calleryyAA8ConcreteVKF : $@convention(thin) (Concrete) -> @error any Error public func caller(_ c: Concrete) throws { // CHECK: [[ARG:%.*]] = struct $Concrete () - // CHECK: [[FN:%.*]] = function_ref @$s4test8ConcreteV4failyyKF : $@convention(method) (Concrete) -> @error Error - // CHECK: try_apply [[FN]]([[ARG]]) : $@convention(method) (Concrete) -> @error Error + // CHECK: [[FN:%.*]] = function_ref @$s4test8ConcreteV4failyyKF : $@convention(method) (Concrete) -> @error any Error + // CHECK: try_apply [[FN]]([[ARG]]) : $@convention(method) (Concrete) -> @error any Error try callee(c) } diff --git a/test/SILOptimizer/mandatory_inlining_open_existential.swift b/test/SILOptimizer/mandatory_inlining_open_existential.swift index 0492d66c3e2d4..88ee18ee0b246 100644 --- a/test/SILOptimizer/mandatory_inlining_open_existential.swift +++ b/test/SILOptimizer/mandatory_inlining_open_existential.swift @@ -10,9 +10,9 @@ protocol P { } // CHECK-LABEL: sil hidden [always_inline] @$s35mandatory_inlining_open_existential6callee1pAA1P_pAaD_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access {{%[0-9]+}} : $*P to $*[[OPENED_TY:@opened\("[-A-F0-9]+", P\) Self]] +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access {{%[0-9]+}} : $*any P to $*[[OPENED_TY:@opened\("[-A-F0-9]+", any P\) Self]] // CHECK: [[WITNESS:%[0-9]+]] = witness_method $[[OPENED_TY]], #P.f : (Self) -> () -> Self.Assoc -// CHECK: [[RESULT:%[0-9]+]] = init_existential_addr {{%[0-9]+}} : $*P, $[[OPENED_TY]].Assoc +// CHECK: [[RESULT:%[0-9]+]] = init_existential_addr {{%[0-9]+}} : $*any P, $[[OPENED_TY]].Assoc // CHECK: apply [[WITNESS]]<[[OPENED_TY]]>([[RESULT]], [[OPENED]]) // CHECK: } @inline(__always) @@ -21,9 +21,9 @@ func callee(p: any P) -> any P { } // CHECK-LABEL: sil hidden @$s35mandatory_inlining_open_existential6caller1pAA1P_pAaD_p_tF -// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access {{%[0-9]+}} : $*P to $*[[OPENED_TY:@opened\("[-A-F0-9]+", P\) Self]] +// CHECK: [[OPENED:%[0-9]+]] = open_existential_addr immutable_access {{%[0-9]+}} : $*any P to $*[[OPENED_TY:@opened\("[-A-F0-9]+", any P\) Self]] // CHECK: [[WITNESS:%[0-9]+]] = witness_method $[[OPENED_TY]], #P.f : (Self) -> () -> Self.Assoc -// CHECK: [[RESULT:%[0-9]+]] = init_existential_addr {{%[0-9]+}} : $*P, $[[OPENED_TY]].Assoc +// CHECK: [[RESULT:%[0-9]+]] = init_existential_addr {{%[0-9]+}} : $*any P, $[[OPENED_TY]].Assoc // CHECK: apply [[WITNESS]]<[[OPENED_TY]]>([[RESULT]], [[OPENED]]) // CHECK: } func caller(p: any P) -> any P { diff --git a/test/SILOptimizer/mandatory_inlining_ownership.sil b/test/SILOptimizer/mandatory_inlining_ownership.sil index 22a891f22e85e..edf79a6c09627 100644 --- a/test/SILOptimizer/mandatory_inlining_ownership.sil +++ b/test/SILOptimizer/mandatory_inlining_ownership.sil @@ -61,16 +61,16 @@ bb2: return %2 : $Builtin.Int64 } -// CHECK-LABEL: sil [ossa] @callerWithThrow : $@convention(thin) (@owned C) -> (Builtin.Int64, @error Error) { +// CHECK-LABEL: sil [ossa] @callerWithThrow : $@convention(thin) (@owned C) -> (Builtin.Int64, @error any Error) { // CHECK: bb0(%0 : @owned $C): // CHECK: [[BORROW:%.*]] = begin_borrow [lexical] %0 : $C // CHECK: [[ADDR:%.*]] = ref_element_addr [[BORROW]] : $C, #C.i // CHECK: [[VAL:%.*]] = load [trivial] [[ADDR]] : $*Builtin.Int64 // CHECK: bb{{.*}}: -// CHECK: [[ERR:%.*]] = alloc_existential_box $Error, $MyError +// CHECK: [[ERR:%.*]] = alloc_existential_box $any Error, $MyError // CHECK: end_borrow [[BORROW]] : $C // CHECK: destroy_value %0 : $C -// CHECK: throw [[ERR]] : $Error +// CHECK: throw [[ERR]] : $any Error // CHECK: bb{{.*}}: // CHECK: end_borrow [[BORROW]] : $C // CHECK: destroy_value %0 : $C @@ -488,7 +488,7 @@ bb2: unwind } -// CHECK-LABEL: sil [ossa] @begin_apply_caller : $@convention(method) (@guaranteed Klass) -> @error Error { +// CHECK-LABEL: sil [ossa] @begin_apply_caller : $@convention(method) (@guaranteed Klass) -> @error any Error { // CHECK-NOT: begin_apply // CHECK: } // end sil function 'begin_apply_caller' sil [ossa] @begin_apply_caller : $@convention(method) (@guaranteed Klass) -> @error Error { @@ -502,7 +502,7 @@ bb0(%0 : @guaranteed $Klass): return %19 : $() } -// CHECK-LABEL: sil [ossa] @begin_apply_caller_2 : $@convention(method) (@guaranteed Klass) -> @error Error { +// CHECK-LABEL: sil [ossa] @begin_apply_caller_2 : $@convention(method) (@guaranteed Klass) -> @error any Error { // CHECK-NOT: begin_apply // CHECK: } // end sil function 'begin_apply_caller_2' sil [ossa] @begin_apply_caller_2 : $@convention(method) (@guaranteed Klass) -> @error Error { @@ -516,7 +516,7 @@ bb0(%0 : @guaranteed $Klass): return %19 : $() } -// CHECK-LABEL: sil [ossa] @begin_apply_caller_3 : $@convention(method) (@guaranteed Klass) -> @error Error { +// CHECK-LABEL: sil [ossa] @begin_apply_caller_3 : $@convention(method) (@guaranteed Klass) -> @error any Error { // CHECK-NOT: begin_apply // CHECK: } // end sil function 'begin_apply_caller_3' sil [ossa] @begin_apply_caller_3 : $@convention(method) (@guaranteed Klass) -> @error Error { @@ -559,7 +559,7 @@ bb2: // Just make sure we actually inlined the begin_apply. We just want to make sure // we are not breaking ownership invariants by not properly borrowing %0. -// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller : $@convention(method) (@owned C2) -> @error Error { +// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller : $@convention(method) (@owned C2) -> @error any Error { // CHECK-NOT: begin_apply // CHECK: } // end sil function 'begin_apply_devirt_caller' sil [ossa] @begin_apply_devirt_caller : $@convention(method) (@owned C2) -> @error Error { @@ -575,7 +575,7 @@ bb1: return %9999 : $() } -// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller_2 : $@convention(method) (@owned C2) -> @error Error { +// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller_2 : $@convention(method) (@owned C2) -> @error any Error { // CHECK-NOT: begin_apply // CHECK: } // end sil function 'begin_apply_devirt_caller_2' sil [ossa] @begin_apply_devirt_caller_2 : $@convention(method) (@owned C2) -> @error Error { @@ -591,7 +591,7 @@ bb1: return %9999 : $() } -// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller_3 : $@convention(method) (@owned C2) -> @error Error { +// CHECK-LABEL: sil [ossa] @begin_apply_devirt_caller_3 : $@convention(method) (@owned C2) -> @error any Error { // CHECK-NOT: begin_apply // CHECK: } // end sil function 'begin_apply_devirt_caller_3' sil [ossa] @begin_apply_devirt_caller_3 : $@convention(method) (@owned C2) -> @error Error { diff --git a/test/SILOptimizer/mandatory_inlining_ownership2.sil b/test/SILOptimizer/mandatory_inlining_ownership2.sil index 87c79bf1cf821..d770ad5ff8196 100644 --- a/test/SILOptimizer/mandatory_inlining_ownership2.sil +++ b/test/SILOptimizer/mandatory_inlining_ownership2.sil @@ -180,7 +180,7 @@ bb0(%0 : $Int64): protocol SomeProtocol { } -// CHECK-LABEL: sil [transparent] [ossa] @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type +// CHECK-LABEL: sil [transparent] [ossa] @test_existential_metatype : $@convention(thin) (@in any SomeProtocol) -> @thick any SomeProtocol.Type sil [transparent] [ossa] @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type { bb0(%0 : $*SomeProtocol): %1 = alloc_box ${ var SomeProtocol } @@ -195,15 +195,15 @@ bb0(%0 : $*SomeProtocol): return %6 : $@thick SomeProtocol.Type } -// CHECK-LABEL: sil [ossa] @inline_test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type +// CHECK-LABEL: sil [ossa] @inline_test_existential_metatype : $@convention(thin) (@in any SomeProtocol) -> @thick any SomeProtocol.Type sil [ossa] @inline_test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type { -// CHECK: [[BB0:.*]]([[VAL0:%.*]] : $*SomeProtocol): - // CHECK: [[VAL1:%.*]] = alloc_box ${ var SomeProtocol } +// CHECK: [[BB0:.*]]([[VAL0:%.*]] : $*any SomeProtocol): + // CHECK: [[VAL1:%.*]] = alloc_box ${ var any SomeProtocol } // CHECK: [[PB1:%.*]] = project_box [[VAL1]] // CHECK: copy_addr [take] %0 to [initialization] [[PB1]] - // CHECK: [[VAL4:%.*]] = alloc_stack $SomeProtocol + // CHECK: [[VAL4:%.*]] = alloc_stack $any SomeProtocol // CHECK: copy_addr [[PB1]] to [initialization] [[VAL4]] - // CHECK: [[VAL6:%.*]] = existential_metatype $@thick SomeProtocol.Type, [[VAL4]] + // CHECK: [[VAL6:%.*]] = existential_metatype $@thick any SomeProtocol.Type, [[VAL4]] // CHECK: destroy_addr [[VAL4]] // CHECK: dealloc_stack [[VAL4]] // CHECK: destroy_value [[VAL1]] @@ -723,14 +723,14 @@ bb0(%0 : @owned $CP): } // CHECK-LABEL: sil [ossa] @_TF2t222outer_open_existentialFT3cp1PS_2CP_3cp2PS0___T_ : -// CHECK: bb0([[ARG0:%.*]] : @owned $CP, [[ARG1:%.*]] : @owned $CP): +// CHECK: bb0([[ARG0:%.*]] : @owned $any CP, [[ARG1:%.*]] : @owned $any CP): // CHECK: [[ARG0_COPY:%.*]] = copy_value [[ARG0]] // CHECK: [[ARG0_COPY_COPY:%.*]] = copy_value [[ARG0_COPY]] -// CHECK: open_existential_ref [[ARG0_COPY_COPY]] : $CP to $@opened([[N1:".*"]], CP) Self +// CHECK: open_existential_ref [[ARG0_COPY_COPY]] : $any CP to $@opened([[N1:".*"]], any CP) Self // // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] // CHECK: [[ARG1_COPY_COPY:%.*]] = copy_value [[ARG1_COPY]] -// CHECK: open_existential_ref [[ARG1_COPY_COPY]] : $CP to $@opened([[N1:".*"]], CP) Self +// CHECK: open_existential_ref [[ARG1_COPY_COPY]] : $any CP to $@opened([[N1:".*"]], any CP) Self // CHECK: } // end sil function '_TF2t222outer_open_existentialFT3cp1PS_2CP_3cp2PS0___T_' sil [ossa] @_TF2t222outer_open_existentialFT3cp1PS_2CP_3cp2PS0___T_ : $@convention(thin) (@owned CP, @owned CP) -> () { bb0(%0 : @owned $CP, %1 : @owned $CP): @@ -842,12 +842,12 @@ bb0(%0 : @owned $T): } // CHECK-LABEL: sil hidden [ossa] @protocolTypedParam : -// CHECK: bb0([[ARG:%.*]] : @owned $Foo): +// CHECK: bb0([[ARG:%.*]] : @owned $any Foo): // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] // CHECK: [[ARG_COPY_2:%.*]] = copy_value [[ARG_COPY]] // CHECK-NOT: apply -// CHECK: [[METHOD:%[a-zA-Z0-9]+]] = objc_method [[ARG_COPY]] : $Foo, #Foo.foo!foreign : {{.*}}, $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () -// CHECK: apply [[METHOD]]([[ARG_COPY_2]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () +// CHECK: [[METHOD:%[a-zA-Z0-9]+]] = objc_method [[ARG_COPY]] : $any Foo, #Foo.foo!foreign : {{.*}}, $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () +// CHECK: apply [[METHOD]]([[ARG_COPY_2]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> () // CHECK: destroy_value [[ARG_COPY_2]] // CHECK: destroy_value [[ARG_COPY]] // CHECK: destroy_value [[ARG]] @@ -1010,7 +1010,7 @@ bb0(%0 : $*Self): // Check that P2_s call can be properly inlined and the resulting witness_method instruction // uses the opened archetype from the caller. // CHECK-LABEL: sil hidden [ossa] @L_start -// CHECK: open_existential_addr immutable_access {{.*}}$*@[[OPENED_ARCHETYPE:opened\("[A-Z0-9-]+", P2\) Self]] +// CHECK: open_existential_addr immutable_access {{.*}}$*@[[OPENED_ARCHETYPE:opened\("[A-Z0-9-]+", any P2\) Self]] // CHECK: witness_method $@[[OPENED_ARCHETYPE]], #P2.c!getter : {{.*}}, %{{[0-9]+}} : $*@[[OPENED_ARCHETYPE]] // CHECK: return sil hidden [ossa] @L_start : $@convention(method) (@in_guaranteed L) -> Int32 { @@ -1046,13 +1046,13 @@ bb0(%0 : @owned $Optional): // CHECK: bb0([[ARG:%.*]] : @owned $C): // CHECK: [[F1:%.*]] = function_ref @testMandatoryConvertedHelper : $@convention(thin) (@owned C) -> @owned C // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] -// CHECK: [[CVT1:%.*]] = convert_function [[F1]] : $@convention(thin) (@owned C) -> @owned C to $@convention(thin) (@owned C) -> (@owned C, @error Error) -// CHECK: try_apply [[CVT1]]([[ARG_COPY]]) : $@convention(thin) (@owned C) -> (@owned C, @error Error), normal bb1, error bb2 +// CHECK: [[CVT1:%.*]] = convert_function [[F1]] : $@convention(thin) (@owned C) -> @owned C to $@convention(thin) (@owned C) -> (@owned C, @error any Error) +// CHECK: try_apply [[CVT1]]([[ARG_COPY]]) : $@convention(thin) (@owned C) -> (@owned C, @error any Error), normal bb1, error bb2 // // CHECK: bb1(%{{.*}} : @owned $C): // CHECK: br bb3(%{{.*}} : $C) // -// CHECK: bb2(%{{.*}} : @owned $Error): +// CHECK: bb2(%{{.*}} : @owned $any Error): // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] // CHECK: [[F2:%.*]] = function_ref @testMandatoryConvertedHelper2 : $@convention(thin) (@owned Optional) -> @owned C // CHECK: [[CVT2:%.*]] = convert_function [[F2]] : $@convention(thin) (@owned Optional) -> @owned C to $@convention(thin) (@owned C) -> @owned C diff --git a/test/SILOptimizer/mem-behavior.sil b/test/SILOptimizer/mem-behavior.sil index dd91ab2836cfb..61ce68225c747 100644 --- a/test/SILOptimizer/mem-behavior.sil +++ b/test/SILOptimizer/mem-behavior.sil @@ -259,11 +259,11 @@ bb0(%0 : $UInt8): // CHECK-LABEL: @tryapply_allocstack_and_copyaddr // CHECK: PAIR #2. -// CHECK-NEXT: try_apply %3(%0) : $@convention(thin) (@in Int32) -> (Int32, @error Error), normal bb1, error bb2 +// CHECK-NEXT: try_apply %3(%0) : $@convention(thin) (@in Int32) -> (Int32, @error any Error), normal bb1, error bb2 // CHECK-NEXT: %0 = argument of bb0 : $*Int32 // CHECK-NEXT: r=1,w=1 // CHECK: PAIR #3. -// CHECK-NEXT: try_apply %3(%0) : $@convention(thin) (@in Int32) -> (Int32, @error Error), normal bb1, error bb2 +// CHECK-NEXT: try_apply %3(%0) : $@convention(thin) (@in Int32) -> (Int32, @error any Error), normal bb1, error bb2 // CHECK-NEXT: %1 = alloc_stack $Int32 // CHECK-NEXT: r=0,w=0 sil @tryapply_allocstack_and_copyaddr : $@convention(thin) (@in Int32) -> Int32 { diff --git a/test/SILOptimizer/mem2reg_lifetime.sil b/test/SILOptimizer/mem2reg_lifetime.sil index e887ee3519417..d449c9c4b0323 100644 --- a/test/SILOptimizer/mem2reg_lifetime.sil +++ b/test/SILOptimizer/mem2reg_lifetime.sil @@ -1367,17 +1367,17 @@ exit(%sub_out : @owned $D): return %sub_out : $D } -// CHECK-LABEL: sil hidden [ossa] @term_5 : $@convention(thin) (@owned C) -> @error Error { +// CHECK-LABEL: sil hidden [ossa] @term_5 : $@convention(thin) (@owned C) -> @error any Error { // CHECK: {{bb[^,]+}}([[INSTANCE:%[^,]+]] : @owned $C): // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INSTANCE]] // CHECK: [[LIFETIME_OWNED:%[^,]+]] = copy_value [[LIFETIME]] // CHECK: end_borrow [[LIFETIME]] // CHECK: destroy_value [[INSTANCE]] // CHECK: [[CALLEE_ERROR_OWNED:%[^,]+]] = function_ref @callee_error_owned -// CHECK: try_apply [[CALLEE_ERROR_OWNED]]([[LIFETIME_OWNED]]) : $@convention(thin) (@owned C) -> @error Error, normal [[REGULAR_BLOCK:bb[^,]+]], error [[THROW_BLOCK:bb[0-9]+]] +// CHECK: try_apply [[CALLEE_ERROR_OWNED]]([[LIFETIME_OWNED]]) : $@convention(thin) (@owned C) -> @error any Error, normal [[REGULAR_BLOCK:bb[^,]+]], error [[THROW_BLOCK:bb[0-9]+]] // CHECK: [[REGULAR_BLOCK]]({{%[^,]+}} : $()): // CHECK: br [[EXIT:bb[0-9]+]] -// CHECK: [[THROW_BLOCK]]([[ERROR:%[^,]+]] : @owned $Error): +// CHECK: [[THROW_BLOCK]]([[ERROR:%[^,]+]] : @owned $any Error): // CHECK: destroy_value [[ERROR]] // CHECK: br [[EXIT]] // CHECK: [[EXIT]]: diff --git a/test/SILOptimizer/partial_specialization.sil b/test/SILOptimizer/partial_specialization.sil index 8700753f1fc38..71a95436819ee 100644 --- a/test/SILOptimizer/partial_specialization.sil +++ b/test/SILOptimizer/partial_specialization.sil @@ -126,7 +126,7 @@ bb0(%0 : $*U): // Check that partial specialization is not performed for generic type parameters where // the substitution contains an open existential. -// CHECK-LABEL: sil @simple_generic_caller4 : $@convention(thin) (@in P, Builtin.Int1) -> () +// CHECK-LABEL: sil @simple_generic_caller4 : $@convention(thin) (@in any P, Builtin.Int1) -> () // CHECK: function_ref @$s21simple_generic_calleexBi1_Bi1_Rs_r0_lIetiy_Tp5 : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int1> (@in τ_0_0, Builtin.Int1) -> () // CHECK: // end sil function 'simple_generic_caller4' sil @simple_generic_caller4 : $@convention(thin) (@in P, Builtin.Int1) -> () { diff --git a/test/SILOptimizer/retain_release_code_motion.sil b/test/SILOptimizer/retain_release_code_motion.sil index 4175e83a1b35d..f8fda457e0363 100644 --- a/test/SILOptimizer/retain_release_code_motion.sil +++ b/test/SILOptimizer/retain_release_code_motion.sil @@ -319,7 +319,7 @@ bb3: return %5 : $() } -// CHECK-LABEL: sil [serialized] @try_apply_blocks_release_hoisting : $@convention(thin) (Builtin.NativeObject) -> @error Error { +// CHECK-LABEL: sil [serialized] @try_apply_blocks_release_hoisting : $@convention(thin) (Builtin.NativeObject) -> @error any Error { // CHECK: bb0( // CHECK: strong_retain // CHECK: try_apply @@ -842,9 +842,9 @@ bb3(%24 : $Optional): return %24 : $Optional } -// CHECK-LABEL: sil @moveOverClassToExistentialCast : $@convention(thin) (@guaranteed fuzz) -> Optional

+// CHECK-LABEL: sil @moveOverClassToExistentialCast : $@convention(thin) (@guaranteed fuzz) -> Optional // CHECK: checked_cast_br %0 -// CHECK: enum $Optional

, #Optional.some!enumelt +// CHECK: enum $Optional, #Optional.some!enumelt // CHECK: strong_retain %0 // CHECK-NOT: release // CHECK: } // end sil function 'moveOverClassToExistentialCast' @@ -866,7 +866,7 @@ bb3(%24 : $Optional

): return %24 : $Optional

} -// CHECK-LABEL: sil @dontMoveOverExistentialToExistentialCast : $@convention(thin) (@guaranteed AnyObject) -> Optional

+// CHECK-LABEL: sil @dontMoveOverExistentialToExistentialCast : $@convention(thin) (@guaranteed AnyObject) -> Optional // CHECK: strong_retain %0 // CHECK: checked_cast_br %0 // CHECK: } // end sil function 'dontMoveOverExistentialToExistentialCast' diff --git a/test/SILOptimizer/shrink_borrow_scope.sil b/test/SILOptimizer/shrink_borrow_scope.sil index 59e0f28b9986d..d349a48a1bb66 100644 --- a/test/SILOptimizer/shrink_borrow_scope.sil +++ b/test/SILOptimizer/shrink_borrow_scope.sil @@ -841,7 +841,7 @@ bad(%15 : @owned $Error): // CHECK: [[GOOD]]({{%[^,]+}} : $()): // CHECK: end_borrow [[LIFETIME]] // CHECK: destroy_value [[INSTANCE]] -// CHECK: [[BAD]]([[ERROR:%[^,]+]] : @owned $Error): +// CHECK: [[BAD]]([[ERROR:%[^,]+]] : @owned $any Error): // CHECK: end_borrow [[LIFETIME]] // CHECK: destroy_value [[INSTANCE]] // CHECK: throw [[ERROR]] @@ -927,7 +927,7 @@ entry(%instance : @owned $C, %input : $S): // which can have the same sorts of side-effects as function calls. // // CHECK-LABEL: sil [ossa] @dont_hoist_over_abort_apply : {{.*}} { -// CHECK: {{bb[0-9]+}}([[REGISTER_1:%[^,]+]] : $Error): +// CHECK: {{bb[0-9]+}}([[REGISTER_1:%[^,]+]] : $any Error): // CHECK: abort_apply // CHECK: end_borrow // CHECK: destroy_value diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil index 19da4ed17ce0c..569dc934e9bde 100644 --- a/test/SILOptimizer/sil_combine.sil +++ b/test/SILOptimizer/sil_combine.sil @@ -2841,8 +2841,8 @@ struct T : Q { // CHECK: metatype $@thick T.Type // CHECK-NOT: checked_cast_addr_br // CHECK: checked_cast_br -// CHECK: bb1(%[[ARG:[0-9]+]] : $@thick Q.Type) -// CHECK: store %[[ARG]] to {{.*}} : $*@thick Q.Type +// CHECK: bb1(%[[ARG:[0-9]+]] : $@thick any Q.Type) +// CHECK: store %[[ARG]] to {{.*}} : $*@thick any Q.Type // CHECK: } sil @silcombine_checked_cast_addr_br_on_metatype_into_checked_cast_br_on_metatype : $@convention(thin) () -> Bool { bb0: @@ -3019,7 +3019,7 @@ struct OtherError: Error { // CHECK-NOT: unconditional_checked_cast_addr // CHECK: retain_value %0 // CHECK-NOT: unconditional_checked_cast_addr -// CHECK: [[E:%[0-9]+]] = alloc_stack $Error +// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error // CHECK-NOT: unconditional_checked_cast_addr // CHECK: [[T:%[0-9]+]] = alloc_stack $TestError // CHECK-NEXT: destroy_addr [[E]] @@ -3193,7 +3193,7 @@ bb0(%0 : $TestError): // CHECK-LABEL: sil @unconditional_existential_box_cast_not_dominating : // CHECK: retain_value %0 -// CHECK: [[E:%[0-9]+]] = alloc_stack $Error +// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error // CHECK: [[T:%[0-9]+]] = alloc_stack $TestError // CHECK-NEXT: destroy_addr [[E]] // CHECK-NEXT: store %0 to [[T]] @@ -3231,7 +3231,7 @@ bb4: // CHECK-LABEL: sil @conditional_existential_box_cast // CHECK: retain_value %0 -// CHECK: [[E:%[0-9]+]] = alloc_stack $Error +// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error // CHECK: [[T:%[0-9]+]] = alloc_stack $TestError // CHECK-NEXT: store %0 to [[T]] // CHECK-NEXT: [[I:%[0-9]+]] = integer_literal $Builtin.Int1, -1 @@ -3266,7 +3266,7 @@ bb2: // CHECK-LABEL: sil @taking_conditional_existential_box_cast // CHECK: retain_value %0 -// CHECK: [[E:%[0-9]+]] = alloc_stack $Error +// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error // CHECK: [[T:%[0-9]+]] = alloc_stack $TestError // CHECK-NEXT: destroy_addr [[E]] // CHECK-NEXT: store %0 to [[T]] @@ -3504,7 +3504,7 @@ sil @minus : $@convention(method) (@in_guaranteed Self) - // CHECK-LABEL: sil @silcombine_dont_change_allocstack_for_opened_archetypes // CHECK-NOT: alloc_stack{{.*}}opened -// CHECK: open_existential_addr immutable_access {{%[0-9]+}} : $*PM to $*@opened("090C3DB0-1C76-11E6-81C4-B8E856428C60", PM) Self +// CHECK: open_existential_addr immutable_access {{%[0-9]+}} : $*any PM to $*@opened("090C3DB0-1C76-11E6-81C4-B8E856428C60", any PM) Self // CHECK: return sil @silcombine_dont_change_allocstack_for_opened_archetypes : $@convention(thin) (@owned VV) -> () { bb0(%0 : $VV): @@ -3777,10 +3777,10 @@ sil @getMetaType : $@convention(thin) () -> @thick Prot2.Type // CHECK-LABEL: meta_existential // CHECK:bb0: -// CHECK: [[APPLY:%.*]] = apply {{%.*}}() : $@convention(thin) () -> @thick Prot2.Type -// CHECK: [[OE:%.*]] = open_existential_metatype [[APPLY]] : $@thick Prot2.Type to $@thick (@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self).Type -// CHECK: [[WM:%.*]] = witness_method $@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self, #Prot1.newWithConfig : (Self.Type) -> () throws -> Builtin.Int32, [[OE]] : $@thick (@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self).Type : $@convention(witness_method: Prot1) <τ_0_0 where τ_0_0 : Prot1> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType) -// CHECK: try_apply [[WM]]<@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self>([[OE]]) : $@convention(witness_method: Prot1) <τ_0_0 where τ_0_0 : Prot1> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType) +// CHECK: [[APPLY:%.*]] = apply {{%.*}}() : $@convention(thin) () -> @thick any Prot2.Type +// CHECK: [[OE:%.*]] = open_existential_metatype [[APPLY]] : $@thick any Prot2.Type to $@thick (@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", any Prot1) Self).Type +// CHECK: [[WM:%.*]] = witness_method $@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", any Prot1) Self, #Prot1.newWithConfig : (Self.Type) -> () throws -> Builtin.Int32, [[OE]] : $@thick (@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", any Prot1) Self).Type : $@convention(witness_method: Prot1) <τ_0_0 where τ_0_0 : Prot1> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType) +// CHECK: try_apply [[WM]]<@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", any Prot1) Self>([[OE]]) : $@convention(witness_method: Prot1) <τ_0_0 where τ_0_0 : Prot1> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType) sil @meta_existential : $@convention(thin) () -> (Builtin.Int32, @error MyErrorType) { bb0: %fref = function_ref @getMetaType : $@convention(thin) () -> @thick Prot2.Type diff --git a/test/SILOptimizer/sil_combine1.swift b/test/SILOptimizer/sil_combine1.swift index a5a60c27ce380..5f2d3e7b3ba90 100644 --- a/test/SILOptimizer/sil_combine1.swift +++ b/test/SILOptimizer/sil_combine1.swift @@ -25,7 +25,7 @@ func compose(_ x: P, _ y: P, _ z: P) -> Int32 { } //CHECK-LABEL: sil [noinline] @$s12sil_combine120test_compose_closures5Int32VyF : $@convention(thin) () -> Int32 { -//CHECK: [[OEADDR:%.*]] = open_existential_addr immutable_access {{%.*}} : $*P to $*@opened +//CHECK: [[OEADDR:%.*]] = open_existential_addr immutable_access {{%.*}} : $*any P to $*@opened //CHECK: [[ADDRCAST:%.*]] = unchecked_addr_cast [[OEADDR]] : $*@opened //CHECK: struct_element_addr [[ADDRCAST]] : $*CP, #CP.v @inline(never) diff --git a/test/SILOptimizer/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil index ac71dee1152e7..4c7303788ce44 100644 --- a/test/SILOptimizer/sil_combine_apply.sil +++ b/test/SILOptimizer/sil_combine_apply.sil @@ -204,7 +204,7 @@ bb4: sil @try_apply_func : $@convention(thin) () -> (Builtin.Int32, @error Error) -// CHECK-LABEL: sil @sil_combine_dead_partial_apply_try_apply : $@convention(thin) () -> ((), @error Error) { +// CHECK-LABEL: sil @sil_combine_dead_partial_apply_try_apply : $@convention(thin) () -> ((), @error any Error) { // CHECK: bb1: // CHECK-NEXT: [[ORIGINAL_ALLOC_STACK:%.*]] = alloc_stack $S1 // CHECK-NEXT: [[NEW_ALLOC_STACK:%.*]] = alloc_stack $S1 @@ -320,7 +320,7 @@ bb0(%0 : $*T, %1 : $*T): return %r : $() } -// CHECK-LABEL: sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in_guaranteed SwiftP) -> () { +// CHECK-LABEL: sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in_guaranteed any SwiftP) -> () { // CHECK: bb0({{.*}}): // CHECK: [[EX:%.*]] = open_existential_addr // CHECK: [[METHOD:%.*]] = witness_method @@ -369,7 +369,7 @@ bb0(%0 : $*MutatingProto, %1 : $MStruct): %11 = open_existential_addr mutable_access %9 : $*MutatingProto to $*@opened("FC5F3CFA-A7A4-11E7-911F-685B35C48C83", MutatingProto) Self // CHECK: [[M:%[0-9]+]] = witness_method $MStruct, %12 = witness_method $@opened("FC5F3CFA-A7A4-11E7-911F-685B35C48C83", MutatingProto) Self, #MutatingProto.mutatingMethod : (inout Self) -> () -> (), %11 : $*@opened("FC5F3CFA-A7A4-11E7-911F-685B35C48C83", MutatingProto) Self : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () - // CHECK: [[C:%[0-9]+]] = unchecked_addr_cast [[E]] : $*@opened("FC5F3CFA-A7A4-11E7-911F-685B35C48C83", MutatingProto) Self to $*MStruct + // CHECK: [[C:%[0-9]+]] = unchecked_addr_cast [[E]] : $*@opened("FC5F3CFA-A7A4-11E7-911F-685B35C48C83", any MutatingProto) Self to $*MStruct // CHECK: apply [[M]]([[C]]) : %13 = apply %12<@opened("FC5F3CFA-A7A4-11E7-911F-685B35C48C83", MutatingProto) Self>(%11) : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () copy_addr [take] %9 to [initialization] %0 : $*MutatingProto @@ -390,7 +390,7 @@ bb0(%0 : $*MutatingProto, %1 : $@thick MutatingProto.Type): copy_addr %alloc1 to [initialization] %alloc2 : $*MutatingProto %oeaddr = open_existential_addr mutable_access %alloc2 : $*MutatingProto to $*@opened("6E02DCF6-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self %witmethod = witness_method $@opened("66A6DAFC-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self, #MutatingProto.mutatingMethod : (inout Self) -> () -> (), %openType : $@thick (@opened("66A6DAFC-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self).Type : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () - // CHECK: apply {{%.*}}<@opened("6E02DCF6-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self>({{%.*}}) : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () // type-defs + // CHECK: apply {{%.*}}<@opened("6E02DCF6-AF78-11E7-8F3B-28CFE9213F4F", any MutatingProto) Self>({{%.*}}) : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () // type-defs %apply = apply %witmethod<@opened("6E02DCF6-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self>(%oeaddr) : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () dealloc_stack %alloc2 : $*MutatingProto dealloc_stack %alloc1 : $*MutatingProto @@ -465,8 +465,8 @@ bb0(%0 : $Builtin.Int32): // CHECK: [[F:%.*]] = function_ref @testCombineClosureHelper : $@convention(thin) (Builtin.Int32) -> () // CHECK: [[PA:%.*]] = partial_apply [[F]](%0) : $@convention(thin) (Builtin.Int32) -> () // CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_owned () -> () to $@noescape @callee_owned () -> () -// CHECK: [[CVT2:%.*]] = convert_function [[CVT1]] : $@noescape @callee_owned () -> () to $@noescape @callee_owned () -> @error Error -// CHECK: try_apply [[CVT2]]() : $@noescape @callee_owned () -> @error Error, normal bb1, error bb2 +// CHECK: [[CVT2:%.*]] = convert_function [[CVT1]] : $@noescape @callee_owned () -> () to $@noescape @callee_owned () -> @error any Error +// CHECK: try_apply [[CVT2]]() : $@noescape @callee_owned () -> @error any Error, normal bb1, error bb2 // CHECK-LABEL: } // end sil function 'testCombineClosureConvert' sil @testCombineClosureConvert : $(Builtin.Int32) -> () { bb0(%0 : $Builtin.Int32): @@ -699,8 +699,8 @@ bb0(%0 : $Klass): // CHECK-LABEL: sil @convert_function_simplification_caller : $@convention(thin) (@guaranteed Klass) -> () { // CHECK: [[FUNC:%.*]] = function_ref @convert_function_simplification_callee : $@convention(thin) (@guaranteed Klass) -> () // CHECK: apply [[FUNC]]({{.*}}) : $@convention(thin) (@guaranteed Klass) -> () -// CHECK: [[FUNC:%.*]] = function_ref @convert_function_simplification_callee_with_error : $@convention(thin) (@guaranteed Klass) -> @error Error -// CHECK: apply [nothrow] [[FUNC]]({{.*}}) : $@convention(thin) (@guaranteed Klass) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @convert_function_simplification_callee_with_error : $@convention(thin) (@guaranteed Klass) -> @error any Error +// CHECK: apply [nothrow] [[FUNC]]({{.*}}) : $@convention(thin) (@guaranteed Klass) -> @error any Error // CHECK: } // end sil function 'convert_function_simplification_caller' sil @convert_function_simplification_caller : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : $Klass): @@ -959,18 +959,18 @@ bb2: } // CHECK-LABEL: sil @test_existential_partial_apply_apply -// CHECK: bb0(%0 : $*FakeProtocol): +// CHECK: bb0(%0 : $*any FakeProtocol): // CHECK-NEXT: [[OPEN:%.*]] = open_existential_addr immutable_access // CHECK-NEXT: [[FN:%.*]] = witness_method -// CHECK-NEXT: apply [[FN]]<@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", FakeProtocol) Self>([[OPEN]]) +// CHECK-NEXT: apply [[FN]]<@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", any FakeProtocol) Self>([[OPEN]]) // CHECK-NEXT: tuple // CHECK-NEXT: return -sil @test_existential_partial_apply_apply : $@convention(thin) (@in FakeProtocol) -> () { +sil @test_existential_partial_apply_apply : $@convention(thin) (@in any FakeProtocol) -> () { bb0(%0: $*FakeProtocol): - %o = open_existential_addr immutable_access %0 : $*FakeProtocol to $*@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", FakeProtocol) Self - %f1 = witness_method $@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", FakeProtocol) Self, #FakeProtocol.requirement, %o : $*@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", FakeProtocol) Self : $@convention(witness_method: FakeProtocol) (@in_guaranteed T) -> () - %pa = partial_apply %f1<@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", FakeProtocol) Self>() : $@convention(witness_method: FakeProtocol) (@in_guaranteed T) -> () - %a1 = apply %pa(%o) : $@callee_owned (@in_guaranteed @opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", FakeProtocol) Self) -> () + %o = open_existential_addr immutable_access %0 : $*any FakeProtocol to $*@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", any FakeProtocol) Self + %f1 = witness_method $@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", any FakeProtocol) Self, #FakeProtocol.requirement, %o : $*@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", any FakeProtocol) Self : $@convention(witness_method: FakeProtocol) (@in_guaranteed T) -> () + %pa = partial_apply %f1<@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", any FakeProtocol) Self>() : $@convention(witness_method: FakeProtocol) (@in_guaranteed T) -> () + %a1 = apply %pa(%o) : $@callee_owned (@in_guaranteed @opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", any FakeProtocol) Self) -> () %r = tuple () return %r : $() diff --git a/test/SILOptimizer/sil_combine_apply_ossa.sil b/test/SILOptimizer/sil_combine_apply_ossa.sil index ee43e30ce2090..4df462af1021f 100644 --- a/test/SILOptimizer/sil_combine_apply_ossa.sil +++ b/test/SILOptimizer/sil_combine_apply_ossa.sil @@ -218,7 +218,7 @@ bb4: sil [ossa] @try_apply_func : $@convention(thin) () -> (Builtin.Int32, @error Error) -// CHECK-LABEL: sil [ossa] @sil_combine_dead_partial_apply_try_apply : $@convention(thin) (@in S1) -> ((), @error Error) { +// CHECK-LABEL: sil [ossa] @sil_combine_dead_partial_apply_try_apply : $@convention(thin) (@in S1) -> ((), @error any Error) { // CHECK: bb0([[ARG:%.*]] : $*S1): // CHECK: bb1: // CHECK-NEXT: [[ORIGINAL_ALLOC_STACK:%.*]] = alloc_stack $S1 @@ -342,7 +342,7 @@ bb0(%0 : $*T, %1 : $*T): return %r : $() } -// CHECK-LABEL: sil [ossa] @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in_guaranteed SwiftP) -> () { +// CHECK-LABEL: sil [ossa] @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in_guaranteed any SwiftP) -> () { // CHECK: bb0({{.*}}): // CHECK: [[EX:%.*]] = open_existential_addr // CHECK: [[METHOD:%.*]] = witness_method @@ -410,7 +410,7 @@ bb0(%0 : $*MutatingProto, %1 : $@thick MutatingProto.Type, %2 : $*MutatingProto) copy_addr %2 to [initialization] %alloc2 : $*MutatingProto %oeaddr = open_existential_addr mutable_access %alloc2 : $*MutatingProto to $*@opened("6E02DCF6-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self %witmethod = witness_method $@opened("66A6DAFC-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self, #MutatingProto.mutatingMethod : (inout Self) -> () -> (), %openType : $@thick (@opened("66A6DAFC-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self).Type : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () - // CHECK: apply {{%.*}}<@opened("6E02DCF6-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self>({{%.*}}) : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () // type-defs + // CHECK: apply {{%.*}}<@opened("6E02DCF6-AF78-11E7-8F3B-28CFE9213F4F", any MutatingProto) Self>({{%.*}}) : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () // type-defs %apply = apply %witmethod<@opened("6E02DCF6-AF78-11E7-8F3B-28CFE9213F4F", MutatingProto) Self>(%oeaddr) : $@convention(witness_method: MutatingProto) <τ_0_0 where τ_0_0 : MutatingProto> (@inout τ_0_0) -> () copy_addr [take] %alloc2 to [initialization] %0 : $*MutatingProto dealloc_stack %alloc2 : $*MutatingProto @@ -486,8 +486,8 @@ bb0(%0 : $Builtin.Int32): // CHECK: [[F:%.*]] = function_ref @testCombineClosureHelper : $@convention(thin) (Builtin.Int32) -> () // CHECK: [[PA:%.*]] = partial_apply [[F]](%0) : $@convention(thin) (Builtin.Int32) -> () // CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_owned () -> () to $@noescape @callee_owned () -> () -// CHECK: [[CVT2:%.*]] = convert_function [[CVT1]] : $@noescape @callee_owned () -> () to $@noescape @callee_owned () -> @error Error -// CHECK: try_apply [[CVT2]]() : $@noescape @callee_owned () -> @error Error, normal bb1, error bb2 +// CHECK: [[CVT2:%.*]] = convert_function [[CVT1]] : $@noescape @callee_owned () -> () to $@noescape @callee_owned () -> @error any Error +// CHECK: try_apply [[CVT2]]() : $@noescape @callee_owned () -> @error any Error, normal bb1, error bb2 // CHECK-LABEL: } // end sil function 'testCombineClosureConvert' sil [ossa] @testCombineClosureConvert : $(Builtin.Int32) -> () { bb0(%0 : $Builtin.Int32): @@ -544,7 +544,7 @@ sil [ossa] @guaranteed_closure_throws : $@convention(thin) (@guaranteed C, Built // CHECK: bb1({{.*}}): // CHECK-NOT: destroy_value // CHECK: br bb3 -// CHECK: bb2([[ERROR:%.*]] : @owned $Error): +// CHECK: bb2([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_value [[ERROR]] // CHECK-NEXT: br bb3 // CHECK: bb3: @@ -792,8 +792,8 @@ bb0(%0 : @guaranteed $Klass): // CHECK-LABEL: sil [ossa] @convert_function_simplification_caller : $@convention(thin) (@guaranteed Klass) -> () { // CHECK: [[FUNC:%.*]] = function_ref @convert_function_simplification_callee : $@convention(thin) (@guaranteed Klass) -> () // CHECK: apply [[FUNC]]({{.*}}) : $@convention(thin) (@guaranteed Klass) -> () -// CHECK: [[FUNC:%.*]] = function_ref @convert_function_simplification_callee_with_error : $@convention(thin) (@guaranteed Klass) -> @error Error -// CHECK: apply [nothrow] [[FUNC]]({{.*}}) : $@convention(thin) (@guaranteed Klass) -> @error Error +// CHECK: [[FUNC:%.*]] = function_ref @convert_function_simplification_callee_with_error : $@convention(thin) (@guaranteed Klass) -> @error any Error +// CHECK: apply [nothrow] [[FUNC]]({{.*}}) : $@convention(thin) (@guaranteed Klass) -> @error any Error // CHECK: } // end sil function 'convert_function_simplification_caller' sil [ossa] @convert_function_simplification_caller : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): @@ -1091,10 +1091,10 @@ bb2: // CHECK-LABEL: sil [ossa] @test_existential_partial_apply_apply -// CHECK: bb0(%0 : $*FakeProtocol): +// CHECK: bb0(%0 : $*any FakeProtocol): // CHECK-NEXT: [[OPEN:%.*]] = open_existential_addr immutable_access // CHECK-NEXT: [[FN:%.*]] = witness_method -// CHECK-NEXT: apply [[FN]]<@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", FakeProtocol) Self>([[OPEN]]) +// CHECK-NEXT: apply [[FN]]<@opened("5DD6F3D0-808A-11E6-93A0-34363BD08DA0", any FakeProtocol) Self>([[OPEN]]) // CHECK-NEXT: tuple // CHECK-NEXT: return sil [ossa] @test_existential_partial_apply_apply : $@convention(thin) (@in_guaranteed FakeProtocol) -> () { diff --git a/test/SILOptimizer/sil_combine_concrete_existential.sil b/test/SILOptimizer/sil_combine_concrete_existential.sil index 8d3a740735d1f..9f5312575b3af 100644 --- a/test/SILOptimizer/sil_combine_concrete_existential.sil +++ b/test/SILOptimizer/sil_combine_concrete_existential.sil @@ -48,15 +48,15 @@ sil @$s21extension_return_self1CCACycfC : $@convention(method) (@thick C.Type) - // } // Neither apply responds to type propagation. // -// CHECK-LABEL: sil @$s21extension_return_self14testReturnSelfAA1P_pyF : $@convention(thin) () -> @owned P { -// CHECK: [[E1:%.*]] = init_existential_ref %{{.*}} : $C : $C, $P -// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $P to $@opened("{{.*}}", P) Self +// CHECK-LABEL: sil @$s21extension_return_self14testReturnSelfAA1P_pyF : $@convention(thin) () -> @owned any P { +// CHECK: [[E1:%.*]] = init_existential_ref %{{.*}} : $C : $C, $any P +// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $any P to $@opened("{{.*}}", any P) Self // CHECK: [[F1:%.*]] = function_ref @$s21extension_return_self1PPAAE0B4SelfxyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: [[C1:%.*]] = apply [[F1]]<@opened("{{.*}}", P) Self>([[O1]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: [[E2:%.*]] = init_existential_ref [[C1]] : $@opened("{{.*}}", P) Self : $@opened("{{.*}}", P) Self, $P -// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $P to $@opened("{{.*}}", P) Self +// CHECK: [[C1:%.*]] = apply [[F1]]<@opened("{{.*}}", any P) Self>([[O1]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: [[E2:%.*]] = init_existential_ref [[C1]] : $@opened("{{.*}}", any P) Self : $@opened("{{.*}}", any P) Self, $any P +// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $any P to $@opened("{{.*}}", any P) Self // CHECK: [[F2:%.*]] = function_ref @$s21extension_return_self1PPAAE0B4SelfxyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: apply [[F2]]<@opened("{{.*}}", P) Self>([[O2]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: apply [[F2]]<@opened("{{.*}}", any P) Self>([[O2]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 // CHECK-LABEL: } // end sil function '$s21extension_return_self14testReturnSelfAA1P_pyF' sil @$s21extension_return_self14testReturnSelfAA1P_pyF : $@convention(thin) () -> @owned P { bb0: @@ -114,15 +114,15 @@ sil @$s28witness_return_optional_self2CCCACycfC : $@convention(method) (@thick C // The second witness_method is rewritten for the first opened existential type. // Neither apply is rewritten. // -// CHECK-LABEL: sil @$s28witness_return_optional_self29testWitnessReturnOptionalSelfAA2PP_pSgyF : $@convention(thin) () -> @owned Optional { -// CHECK: [[E1:%.*]] = init_existential_ref %{{.*}} : $CC : $CC, $PP -// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $PP to $@opened("{{.*}}", PP) Self +// CHECK-LABEL: sil @$s28witness_return_optional_self29testWitnessReturnOptionalSelfAA2PP_pSgyF : $@convention(thin) () -> @owned Optional { +// CHECK: [[E1:%.*]] = init_existential_ref %{{.*}} : $CC : $CC, $any PP +// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $any PP to $@opened("{{.*}}", any PP) Self // CHECK: [[W1:%.*]] = witness_method $CC, #PP.returnOptionalSelf : (Self) -> () -> Self? : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> -// CHECK: apply [[W1]]<@opened("{{.*}}", PP) Self>([[O1]]) : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> -// CHECK: [[E2:%.*]] = init_existential_ref %{{.*}} : $@opened("{{.*}}", PP) Self : $@opened("{{.*}}", PP) Self, $PP -// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $PP to $@opened("{{.*}}", PP) Self -// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", PP) Self, #PP.returnOptionalSelf : (Self) -> () -> Self?, [[O1]] : $@opened("{{.*}}", PP) Self : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> -// CHECK: apply [[W2]]<@opened("{{.*}}", PP) Self>([[O2]]) : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> +// CHECK: apply [[W1]]<@opened("{{.*}}", any PP) Self>([[O1]]) : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> +// CHECK: [[E2:%.*]] = init_existential_ref %{{.*}} : $@opened("{{.*}}", any PP) Self : $@opened("{{.*}}", any PP) Self, $any PP +// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $any PP to $@opened("{{.*}}", any PP) Self +// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", any PP) Self, #PP.returnOptionalSelf : (Self) -> () -> Self?, [[O1]] : $@opened("{{.*}}", any PP) Self : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> +// CHECK: apply [[W2]]<@opened("{{.*}}", any PP) Self>([[O2]]) : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> // CHECK-LABEL: } // end sil function '$s28witness_return_optional_self29testWitnessReturnOptionalSelfAA2PP_pSgyF' sil @$s28witness_return_optional_self29testWitnessReturnOptionalSelfAA2PP_pSgyF : $@convention(thin) () -> @owned Optional { bb0: @@ -179,15 +179,15 @@ sil @$s37witness_return_optional_indirect_self1SVACycfC : $@convention(method) ( // rewrite the witness_method. The devirtualizer could then handle the first call. // // CHECK-LABEL: sil @$s37witness_return_optional_indirect_self37testWitnessReturnOptionalIndirectSelfyyF : $@convention(thin) () -> () { -// CHECK: [[O1:%.*]] = open_existential_addr immutable_access %0 : $*PPP to $*@opened("83DE9694-7315-11E8-955C-ACDE48001122", PPP) Self -// CHECK: [[R1:%.*]] = alloc_stack $Optional<@opened("83DE9694-7315-11E8-955C-ACDE48001122", PPP) Self> +// CHECK: [[O1:%.*]] = open_existential_addr immutable_access %0 : $*any PPP to $*@opened("83DE9694-7315-11E8-955C-ACDE48001122", any PPP) Self +// CHECK: [[R1:%.*]] = alloc_stack $Optional<@opened("83DE9694-7315-11E8-955C-ACDE48001122", any PPP) Self> // CHECK: [[W1:%.*]] = witness_method $S, #PPP.returnsOptionalIndirect : (Self) -> () -> Self? : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> -// CHECK: apply [[W1]]<@opened("83DE9694-7315-11E8-955C-ACDE48001122", PPP) Self>([[R1]], [[O1]]) : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> +// CHECK: apply [[W1]]<@opened("83DE9694-7315-11E8-955C-ACDE48001122", any PPP) Self>([[R1]], [[O1]]) : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> // CHECK: [[E1:%.*]] = unchecked_take_enum_data_addr -// CHECK: [[O2:%.*]] = open_existential_addr immutable_access {{.*}} : $*PPP to $*@opened("83DE97CA-7315-11E8-955C-ACDE48001122", PPP) Self -// CHECK: [[R2:%.*]] = alloc_stack $Optional<@opened("83DE97CA-7315-11E8-955C-ACDE48001122", PPP) Self> -// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", PPP) Self, #PPP.returnsOptionalIndirect -// CHECK: apply [[W2]]<@opened("83DE97CA-7315-11E8-955C-ACDE48001122", PPP) Self>([[R2]], [[O2]]) : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> +// CHECK: [[O2:%.*]] = open_existential_addr immutable_access {{.*}} : $*any PPP to $*@opened("83DE97CA-7315-11E8-955C-ACDE48001122", any PPP) Self +// CHECK: [[R2:%.*]] = alloc_stack $Optional<@opened("83DE97CA-7315-11E8-955C-ACDE48001122", any PPP) Self> +// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", any PPP) Self, #PPP.returnsOptionalIndirect +// CHECK: apply [[W2]]<@opened("83DE97CA-7315-11E8-955C-ACDE48001122", any PPP) Self>([[R2]], [[O2]]) : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> // CHECK-LABEL: } // end sil function '$s37witness_return_optional_indirect_self37testWitnessReturnOptionalIndirectSelfyyF' sil @$s37witness_return_optional_indirect_self37testWitnessReturnOptionalIndirectSelfyyF : $@convention(thin) () -> () { bb0: @@ -254,10 +254,10 @@ class CCCC : PPPP { sil [noinline] @takeOptionalSelf : $@convention(method) (@in_guaranteed Optional, @in_guaranteed Self) -> () // CHECK-LABEL: sil @testOptionalSelfArg : $@convention(thin) (@guaranteed CCCC) -> () { -// CHECK: init_existential_addr [[A:%.*]] : $*PPPP, $CCCC // user: %4 -// CHECK: [[OE:%.*]] = open_existential_addr immutable_access [[A]] : $*PPPP to $*@opened("{{.*}}", PPPP) Self // users: %11, %11, %8, %6 +// CHECK: init_existential_addr [[A:%.*]] : $*any PPPP, $CCCC // user: %4 +// CHECK: [[OE:%.*]] = open_existential_addr immutable_access [[A]] : $*any PPPP to $*@opened("{{.*}}", any PPPP) Self // users: %11, %11, %8, %6 // CHECK: [[F:%.*]] = function_ref @takeOptionalSelf : $@convention(method) <τ_0_0 where τ_0_0 : PPPP> (@in_guaranteed Optional<τ_0_0>, @in_guaranteed τ_0_0) -> () // user: %11 -// CHECK: apply [[F]]<@opened("{{.*}}", PPPP) Self>(%{{.*}}, [[OE]]) : $@convention(method) <τ_0_0 where τ_0_0 : PPPP> (@in_guaranteed Optional<τ_0_0>, @in_guaranteed τ_0_0) -> () // type-defs: %5 +// CHECK: apply [[F]]<@opened("{{.*}}", any PPPP) Self>(%{{.*}}, [[OE]]) : $@convention(method) <τ_0_0 where τ_0_0 : PPPP> (@in_guaranteed Optional<τ_0_0>, @in_guaranteed τ_0_0) -> () // type-defs: %5 // CHECK-LABEL: } // end sil function 'testOptionalSelfArg' sil @testOptionalSelfArg : $@convention(thin) (@guaranteed CCCC) -> () { bb0(%0 : $CCCC): @@ -413,7 +413,7 @@ bb0: sil @takeany : $@convention(thin) (@in_guaranteed AnyP) -> () // CHECK-LABEL: sil @testWitnessCopiedSelfWithIndirectResult2 : $@convention(thin) () -> () { -// CHECK: [[IN:%[0-9]+]] = alloc_stack $AnyP +// CHECK: [[IN:%[0-9]+]] = alloc_stack $any AnyP // CHECK: [[EA:%[0-9]+]] = init_existential_addr [[IN]] // CHECK: [[OUT:%[0-9]+]] = alloc_stack $StructOfAnyP // CHECK: witness_method $StructOfAnyP, #AnyP.returnsSelf : (Self) -> () -> Self : $@convention(witness_method: AnyP) <τ_0_0 where τ_0_0 : AnyP> (@in_guaranteed τ_0_0) -> @out StructOfAnyP @@ -461,18 +461,18 @@ sil [transparent] [reabstraction_thunk] @testDevirtExistentialEnumThunk : $@conv // insert a cast of the opened existential. // // CHECK-LABEL: sil shared [noinline] @testDevirtExistentialEnum : $@convention(thin) (@guaranteed Array) -> () { -// CHECK: [[ALLOC_EXISTENTIAL:%.*]] = alloc_stack $ContiguousBytes -// CHECK: [[ALLOC_ENUM:%.*]] = alloc_stack $ContiguousBytes -// CHECK: [[INIT_DATA:%.*]] = init_existential_addr [[ALLOC_ENUM]] : $*ContiguousBytes, $Array +// CHECK: [[ALLOC_EXISTENTIAL:%.*]] = alloc_stack $any ContiguousBytes +// CHECK: [[ALLOC_ENUM:%.*]] = alloc_stack $any ContiguousBytes +// CHECK: [[INIT_DATA:%.*]] = init_existential_addr [[ALLOC_ENUM]] : $*any ContiguousBytes, $Array // CHECK: store %0 to [[INIT_DATA]] : $*Array -// CHECK: copy_addr [take] [[ALLOC_ENUM]] to [initialization] [[ALLOC_EXISTENTIAL]] : $*ContiguousBytes -// CHECK: [[OPENED:%.*]] = open_existential_addr immutable_access [[ALLOC_EXISTENTIAL]] : $*ContiguousBytes to $*@opened("8402EC1A-F35D-11E8-950A-D0817AD9F6DD", ContiguousBytes) Self -// CHECK: [[THUNK:%.*]] = function_ref @testDevirtExistentialEnumThunk : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error Error) -// CHECK: [[TTF:%.*]] = thin_to_thick_function [[THUNK:%.*]] : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error Error) to $@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out (), @error Error) -// CHECK: [[WM:%.*]] = witness_method $Array, #ContiguousBytes.withUnsafeBytes : (Self) -> ((UnsafeRawBufferPointer) throws -> R) throws -> R : $@convention(witness_method: ContiguousBytes) <τ_0_0 where τ_0_0 : ContiguousBytes><τ_1_0> (@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out τ_1_0, @error Error), @in_guaranteed τ_0_0) -> (@out τ_1_0, @error Error) +// CHECK: copy_addr [take] [[ALLOC_ENUM]] to [initialization] [[ALLOC_EXISTENTIAL]] : $*any ContiguousBytes +// CHECK: [[OPENED:%.*]] = open_existential_addr immutable_access [[ALLOC_EXISTENTIAL]] : $*any ContiguousBytes to $*@opened("8402EC1A-F35D-11E8-950A-D0817AD9F6DD", any ContiguousBytes) Self +// CHECK: [[THUNK:%.*]] = function_ref @testDevirtExistentialEnumThunk : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error any Error) +// CHECK: [[TTF:%.*]] = thin_to_thick_function [[THUNK:%.*]] : $@convention(thin) (UnsafeRawBufferPointer) -> (@out (), @error any Error) to $@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out (), @error any Error) +// CHECK: [[WM:%.*]] = witness_method $Array, #ContiguousBytes.withUnsafeBytes : (Self) -> ((UnsafeRawBufferPointer) throws -> R) throws -> R : $@convention(witness_method: ContiguousBytes) <τ_0_0 where τ_0_0 : ContiguousBytes><τ_1_0> (@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out τ_1_0, @error any Error), @in_guaranteed τ_0_0) -> (@out τ_1_0, @error any Error) // CHECK: [[CAST:%.*]] = unchecked_addr_cast [[OPENED]] -// CHECK: apply [nothrow] [[WM]], ()>(%{{.*}}, [[TTF]], [[CAST]]) : $@convention(witness_method: ContiguousBytes) <τ_0_0 where τ_0_0 : ContiguousBytes><τ_1_0> (@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out τ_1_0, @error Error), @in_guaranteed τ_0_0) -> (@out τ_1_0, @error Error) -// CHECK: destroy_addr [[ALLOC_EXISTENTIAL]] : $*ContiguousBytes +// CHECK: apply [nothrow] [[WM]], ()>(%{{.*}}, [[TTF]], [[CAST]]) : $@convention(witness_method: ContiguousBytes) <τ_0_0 where τ_0_0 : ContiguousBytes><τ_1_0> (@noescape @callee_guaranteed (UnsafeRawBufferPointer) -> (@out τ_1_0, @error any Error), @in_guaranteed τ_0_0) -> (@out τ_1_0, @error any Error) +// CHECK: destroy_addr [[ALLOC_EXISTENTIAL]] : $*any ContiguousBytes // CHECK-LABEL: } // end sil function 'testDevirtExistentialEnum' sil shared [noinline] @testDevirtExistentialEnum : $@convention(thin) (@guaranteed Array) -> () { bb0(%0 : $Array): @@ -657,19 +657,19 @@ extension MyObject : SubscriptionViewControllerDelegate { } sil @callee2 : $@convention(thin) <τ_0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder -// CHECK: sil @test_opend_archeype_concrete_conformance_substitution : $@convention(method) (@guaranteed ResourceKitProtocol, @guaranteed ViewController) -> () { -// CHECK: bb0([[ARG:%.*]] : $ResourceKitProtocol, [[ARG2:%.*]] : $ViewController): +// CHECK: sil @test_opend_archeype_concrete_conformance_substitution : $@convention(method) (@guaranteed any ResourceKitProtocol, @guaranteed ViewController) -> () { +// CHECK: bb0([[ARG:%.*]] : $any ResourceKitProtocol, [[ARG2:%.*]] : $ViewController): // CHECK: [[T1:%.*]] = metatype $@thick SubscriptionViewControllerBuilder.Type -// CHECK: [[T2:%.*]] = open_existential_ref [[ARG]] : $ResourceKitProtocol to $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", ResourceKitProtocol) Self -// CHECK: [[T3:%.*]] = alloc_stack $SubscriptionViewControllerDelegate -// CHECK: [[T4:%.*]] = init_existential_addr [[T3]] : $*SubscriptionViewControllerDelegate, $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", ResourceKitProtocol) Self -// CHECK: store [[T2]] to [[T4]] : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", ResourceKitProtocol) Self +// CHECK: [[T2:%.*]] = open_existential_ref [[ARG]] : $any ResourceKitProtocol to $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", any ResourceKitProtocol) Self +// CHECK: [[T3:%.*]] = alloc_stack $any SubscriptionViewControllerDelegate +// CHECK: [[T4:%.*]] = init_existential_addr [[T3]] : $*any SubscriptionViewControllerDelegate, $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", any ResourceKitProtocol) Self +// CHECK: store [[T2]] to [[T4]] : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", any ResourceKitProtocol) Self // CHECK: [[T5:%.*]] = function_ref @callee2 : $@convention(thin) <τ_0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder -// CHECK: [[T6:%.*]] = alloc_stack $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", ResourceKitProtocol) Self -// CHECK: copy_addr [[T4]] to [initialization] [[T6]] : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", ResourceKitProtocol) Self +// CHECK: [[T6:%.*]] = alloc_stack $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", any ResourceKitProtocol) Self +// CHECK: copy_addr [[T4]] to [initialization] [[T6]] : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", any ResourceKitProtocol) Self // CHECK: Generic specialization information for call-site callee2 conformances <(inherited_conformance type=ResourceKitProtocol protocol=SubscriptionViewControllerDelegate // CHECK: (normal_conformance type=MyObject protocol=SubscriptionViewControllerDelegate))>: -// CHECK: apply [[T5]]<@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", ResourceKitProtocol) Self>([[T6]], [[T1]]) +// CHECK: apply [[T5]]<@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122", any ResourceKitProtocol) Self>([[T6]], [[T1]]) sil @test_opend_archeype_concrete_conformance_substitution : $@convention(method) (@guaranteed ResourceKitProtocol, @guaranteed ViewController) -> () { bb0(%0 : $ResourceKitProtocol, %1 : $ViewController): @@ -747,13 +747,13 @@ sil @callee3 : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> () // CHECK-LABEL: sil @testMutatingCopiedOpenExistential : $@convention(thin) (S) -> () { // CHECK: bb0(%0 : $S): -// CHECK: [[EXISCP:%.*]] = alloc_stack [lexical] $PPP, var, name "mergedCommand" +// CHECK: [[EXISCP:%.*]] = alloc_stack [lexical] $any PPP, var, name "mergedCommand" // CHECK: apply %{{.*}} : $@convention(method) (@inout S) -> () -// CHECK: [[OPENED:%.*]] = open_existential_addr mutable_access [[EXISCP]] : $*PPP to $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D", PPP) Self -// CHECK: [[OPENEDCP:%.*]] = alloc_stack $@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D", PPP) Self -// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENEDCP]] : $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D", PPP) Self +// CHECK: [[OPENED:%.*]] = open_existential_addr mutable_access [[EXISCP]] : $*any PPP to $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D", any PPP) Self +// CHECK: [[OPENEDCP:%.*]] = alloc_stack $@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D", any PPP) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[OPENEDCP]] : $*@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D", any PPP) Self // CHECK: [[CALLEE3:%.*]] = function_ref @callee3 : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> () -// CHECK: apply [[CALLEE3]]<@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D", PPP) Self>([[OPENEDCP]]) : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> () +// CHECK: apply [[CALLEE3]]<@opened("381F6B6A-89A1-11EC-999A-D0817AD9985D", any PPP) Self>([[OPENEDCP]]) : $@convention(thin) <τ_0_0 where τ_0_0 : PPP> (@in τ_0_0) -> () // CHECK-LABEL: } // end sil function 'testMutatingCopiedOpenExistential' sil @testMutatingCopiedOpenExistential : $@convention(thin) (S) -> () { bb0(%0 : $S): diff --git a/test/SILOptimizer/sil_combine_concrete_existential.swift b/test/SILOptimizer/sil_combine_concrete_existential.swift index a1d140f7c2bca..a5b3ef7a81048 100644 --- a/test/SILOptimizer/sil_combine_concrete_existential.swift +++ b/test/SILOptimizer/sil_combine_concrete_existential.swift @@ -20,14 +20,14 @@ extension P { } final class C: P {} -// CHECK-LABEL: sil @$s32sil_combine_concrete_existential14testReturnSelfAA1P_pyF : $@convention(thin) () -> @owned P { -// CHECK: [[E1:%.*]] = init_existential_ref %0 : $C : $C, $P -// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $P to $@opened("{{.*}}", P) Self +// CHECK-LABEL: sil @$s32sil_combine_concrete_existential14testReturnSelfAA1P_pyF : $@convention(thin) () -> @owned any P { +// CHECK: [[E1:%.*]] = init_existential_ref %0 : $C : $C, $any P +// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $any P to $@opened("{{.*}}", any P) Self // CHECK: [[F1:%.*]] = function_ref @$s32sil_combine_concrete_existential1PPAAE10returnSelfxyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: [[C1:%.*]] = apply [[F1]]<@opened("{{.*}}", P) Self>([[O1]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 -// CHECK: [[E2:%.*]] = init_existential_ref [[C1]] : $@opened("{{.*}}", P) Self : $@opened("{{.*}}", P) Self, $P -// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $P to $@opened("{{.*}}", P) Self -// CHECK: apply [[F1]]<@opened("{{.*}}", P) Self>([[O2]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: [[C1:%.*]] = apply [[F1]]<@opened("{{.*}}", any P) Self>([[O1]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 +// CHECK: [[E2:%.*]] = init_existential_ref [[C1]] : $@opened("{{.*}}", any P) Self : $@opened("{{.*}}", any P) Self, $any P +// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $any P to $@opened("{{.*}}", any P) Self +// CHECK: apply [[F1]]<@opened("{{.*}}", any P) Self>([[O2]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 // CHECK-LABEL: } // end sil function '$s32sil_combine_concrete_existential14testReturnSelfAA1P_pyF' public func testReturnSelf() -> P { let p: P = C() @@ -55,13 +55,13 @@ final class CC: PP { } // The first apply has been devirtualized and inlined. The second remains unspecialized. -// CHECK-LABEL: sil @$s32sil_combine_concrete_existential29testWitnessReturnOptionalSelfAA2PP_pSgyF : $@convention(thin) () -> @owned Optional { -// CHECK: [[E1:%.*]] = init_existential_ref %0 : $CC : $CC, $PP -// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $PP to $@opened("{{.*}}", PP) Self -// CHECK: [[E2:%.*]] = init_existential_ref %{{.*}} : $@opened("{{.*}}", PP) Self : $@opened("{{.*}}", PP) Self, $PP -// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $PP to $@opened("{{.*}}", PP) Self -// CHECK: [[W:%.*]] = witness_method $@opened("{{.*}}", PP) Self, #PP.returnOptionalSelf : (Self) -> () -> Self?, [[O1]] : $@opened("{{.*}}", PP) Self : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> -// CHECK: apply [[W]]<@opened("{{.*}}", PP) Self>([[O2]]) : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> +// CHECK-LABEL: sil @$s32sil_combine_concrete_existential29testWitnessReturnOptionalSelfAA2PP_pSgyF : $@convention(thin) () -> @owned Optional { +// CHECK: [[E1:%.*]] = init_existential_ref %0 : $CC : $CC, $any PP +// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $any PP to $@opened("{{.*}}", any PP) Self +// CHECK: [[E2:%.*]] = init_existential_ref %{{.*}} : $@opened("{{.*}}", any PP) Self : $@opened("{{.*}}", any PP) Self, $any PP +// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $any PP to $@opened("{{.*}}", any PP) Self +// CHECK: [[W:%.*]] = witness_method $@opened("{{.*}}", any PP) Self, #PP.returnOptionalSelf : (Self) -> () -> Self?, [[O1]] : $@opened("{{.*}}", any PP) Self : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> +// CHECK: apply [[W]]<@opened("{{.*}}", any PP) Self>([[O2]]) : $@convention(witness_method: PP) <τ_0_0 where τ_0_0 : PP> (@guaranteed τ_0_0) -> @owned Optional<τ_0_0> // CHECK-LABEL: } // end sil function '$s32sil_combine_concrete_existential29testWitnessReturnOptionalSelfAA2PP_pSgyF' public func testWitnessReturnOptionalSelf() -> PP? { let p: PP = CC() @@ -95,11 +95,11 @@ struct SS: PPP { // The first apply has been devirtualized and inlined. The second remains unspecialized. // CHECK-LABEL: sil @$s32sil_combine_concrete_existential37testWitnessReturnOptionalIndirectSelfyyF : $@convention(thin) () -> () { -// CHECK: [[O1:%.*]] = open_existential_addr immutable_access %{{.*}} : $*PPP to $*@opened("{{.*}}", PPP) Self -// CHECK: switch_enum_addr %{{.*}} : $*Optional<@opened("{{.*}}", PPP) Self>, case #Optional.some!enumelt: bb{{.*}}, case #Optional.none!enumelt: bb{{.*}} -// CHECK: [[O2:%.*]] = open_existential_addr immutable_access %{{.*}} : $*PPP to $*@opened("{{.*}}", PPP) Self -// CHECK: [[W:%.*]] = witness_method $@opened("{{.*}}", PPP) Self, #PPP.returnsOptionalIndirect : (Self) -> () -> Self?, [[O1]] : $*@opened("{{.*}}", PPP) Self : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> -// CHECK: apply [[W]]<@opened("{{.*}}", PPP) Self>(%{{.*}}, [[O2]]) : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> +// CHECK: [[O1:%.*]] = open_existential_addr immutable_access %{{.*}} : $*any PPP to $*@opened("{{.*}}", any PPP) Self +// CHECK: switch_enum_addr %{{.*}} : $*Optional<@opened("{{.*}}", any PPP) Self>, case #Optional.some!enumelt: bb{{.*}}, case #Optional.none!enumelt: bb{{.*}} +// CHECK: [[O2:%.*]] = open_existential_addr immutable_access %{{.*}} : $*any PPP to $*@opened("{{.*}}", any PPP) Self +// CHECK: [[W:%.*]] = witness_method $@opened("{{.*}}", any PPP) Self, #PPP.returnsOptionalIndirect : (Self) -> () -> Self?, [[O1]] : $*@opened("{{.*}}", any PPP) Self : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> +// CHECK: apply [[W]]<@opened("{{.*}}", any PPP) Self>(%{{.*}}, [[O2]]) : $@convention(witness_method: PPP) <τ_0_0 where τ_0_0 : PPP> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> // CHECK-LABEL: } // end sil function '$s32sil_combine_concrete_existential37testWitnessReturnOptionalIndirectSelfyyF' public func testWitnessReturnOptionalIndirectSelf() { let p: PPP = S() diff --git a/test/SILOptimizer/sil_combine_enum_addr.sil b/test/SILOptimizer/sil_combine_enum_addr.sil index 7cf7f96280898..8ca923a1cec41 100644 --- a/test/SILOptimizer/sil_combine_enum_addr.sil +++ b/test/SILOptimizer/sil_combine_enum_addr.sil @@ -84,7 +84,7 @@ bb3: // CHECK: store // CHECK-NOT: checked_cast_addr_br // CHECK-NOT: bb1 -// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.some!enumelt +// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.some!enumelt // CHECK: dealloc_stack // CHECK: return sil @convert_checked_cast_addr_br_into_unconditional_checked_cast_addr_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> () { @@ -138,10 +138,10 @@ private class D : C { // // CHECK-LABEL: sil @convert_checked_cast_addr_br_with_internal_type : $@convention(thin) (@in A, @inout _Stdout) -> () // CHECK: checked_cast_addr_br -// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.some!enumelt +// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.some!enumelt // CHECK: dealloc_stack // CHECK: return -// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.none!enumelt +// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.none!enumelt // CHECK: } sil @convert_checked_cast_addr_br_with_internal_type : $@convention(thin) (@in A, @inout _Stdout) -> () { bb0(%0 : $*A, %1 : $*_Stdout): @@ -180,7 +180,7 @@ bb22: // CHECK: store // CHECK-NOT: checked_cast_addr_br // CHECK-NOT: bb1 -// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.none!enumelt +// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.none!enumelt // CHECK: dealloc_stack // CHECK: return sil @convert_checked_cast_addr_br_with_private_type : $@convention(thin) (@in B, @inout _Stdout) -> () { @@ -218,10 +218,10 @@ bb22: // // CHECK-LABEL: sil @convert_checked_cast_addr_br_with_non_private_superclass : $@convention(thin) (@in D, @inout _Stdout) -> () // CHECK: checked_cast_addr_br -// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.some!enumelt +// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.some!enumelt // CHECK: dealloc_stack // CHECK: return -// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.none!enumelt +// CHECK: inject_enum_addr %{{.*}} : $*Optional, #Optional.none!enumelt // CHECK: } sil @convert_checked_cast_addr_br_with_non_private_superclass : $@convention(thin) (@in D, @inout _Stdout) -> () { bb0(%0 : $*D, %1 : $*_Stdout): diff --git a/test/SILOptimizer/sil_combine_enum_addr_ossa.sil b/test/SILOptimizer/sil_combine_enum_addr_ossa.sil index 8671ed20245e9..eb214afcc654e 100644 --- a/test/SILOptimizer/sil_combine_enum_addr_ossa.sil +++ b/test/SILOptimizer/sil_combine_enum_addr_ossa.sil @@ -5,7 +5,7 @@ sil_stage canonical import Builtin import Swift -// CHECK-LABEL: sil [ossa] @convert_inject_enum_addr_select_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout, @in_guaranteed CustomStringConvertible) -> () +// CHECK-LABEL: sil [ossa] @convert_inject_enum_addr_select_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout, @in_guaranteed any CustomStringConvertible) -> () // XHECK-NOT: init_existential_addr // XHECK-NOT: inject_enum_addr // XHECK-NOT: select_enum_addr @@ -47,7 +47,7 @@ bb2: } -// CHECK-LABEL: sil [ossa] @convert_inject_enum_addr_switch_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout, @in_guaranteed CustomStringConvertible) -> () +// CHECK-LABEL: sil [ossa] @convert_inject_enum_addr_switch_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout, @in_guaranteed any CustomStringConvertible) -> () // XHECK-NOT: init_existential_addr // XHECK-NOT: inject_enum_addr // XHECK-NOT: switch_enum_addr diff --git a/test/SILOptimizer/sil_combine_objc_bridge.sil b/test/SILOptimizer/sil_combine_objc_bridge.sil index 4896cf6a95f1b..903a8a95377c1 100644 --- a/test/SILOptimizer/sil_combine_objc_bridge.sil +++ b/test/SILOptimizer/sil_combine_objc_bridge.sil @@ -37,7 +37,7 @@ enum AddressOnlyError : Error { // Test that we emit a copy_addr for the address-only value initialization. // CHECK-LABEL: sil @unconditional_checked_cast_addr_address_only_type -// CHECK: alloc_stack $Error +// CHECK: alloc_stack $any Error // CHECK: alloc_stack $AddressOnlyError // CHECK: copy_addr // CHECK: alloc_existential_box diff --git a/test/SILOptimizer/sil_combine_objc_bridge_ossa.sil b/test/SILOptimizer/sil_combine_objc_bridge_ossa.sil index fb371f992b00a..0a5040316b862 100644 --- a/test/SILOptimizer/sil_combine_objc_bridge_ossa.sil +++ b/test/SILOptimizer/sil_combine_objc_bridge_ossa.sil @@ -37,7 +37,7 @@ enum AddressOnlyError : Error { // Test that we emit a copy_addr for the address-only value initialization. // CHECK-LABEL: sil [ossa] @unconditional_checked_cast_addr_address_only_type -// CHECK: alloc_stack $Error +// CHECK: alloc_stack $any Error // CHECK: alloc_stack $AddressOnlyError // CHECK: copy_addr // CHECK: alloc_existential_box diff --git a/test/SILOptimizer/sil_combine_ossa.sil b/test/SILOptimizer/sil_combine_ossa.sil index 0c119a8a0bbaa..f6a8cc6248971 100644 --- a/test/SILOptimizer/sil_combine_ossa.sil +++ b/test/SILOptimizer/sil_combine_ossa.sil @@ -3230,8 +3230,8 @@ struct T : Q { // CHECK: metatype $@thick T.Type // CHECK-NOT: checked_cast_addr_br // CHECK: checked_cast_br -// CHECK: bb1(%[[ARG:[0-9]+]] : $@thick Q.Type) -// CHECK: store %[[ARG]] to {{.*}} : $*@thick Q.Type +// CHECK: bb1(%[[ARG:[0-9]+]] : $@thick any Q.Type) +// CHECK: store %[[ARG]] to {{.*}} : $*@thick any Q.Type // CHECK: } sil [ossa] @silcombine_checked_cast_addr_br_on_metatype_into_checked_cast_br_on_metatype : $@convention(thin) () -> Bool { bb0: @@ -3417,7 +3417,7 @@ struct OtherError: Error { // CHECK: [[ERROR_COPY_2:%.*]] = copy_value [[ERROR]] // CHECK: [[BOX:%.*]] = alloc_existential_box // CHECK: [[ERROR_COPY_1:%.*]] = copy_value [[ERROR]] -// CHECK: [[E:%[0-9]+]] = alloc_stack $Error +// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error // CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] // CHECK: store [[BOX_COPY]] to [init] [[E]] // CHECK: [[T:%[0-9]+]] = alloc_stack $TestError @@ -3638,7 +3638,7 @@ bb4: // CHECK-LABEL: sil [ossa] @conditional_existential_box_cast : // CHECK: [[LIFETIME_EXTENDING_COPY:%.*]] = copy_value %0 -// CHECK: [[E:%[0-9]+]] = alloc_stack $Error +// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error // CHECK: [[T:%[0-9]+]] = alloc_stack $TestError // CHECK: store [[LIFETIME_EXTENDING_COPY]] to [init] [[T]] // CHECK-NEXT: [[I:%[0-9]+]] = integer_literal $Builtin.Int1, -1 @@ -3674,7 +3674,7 @@ bb2: // CHECK-LABEL: sil [ossa] @taking_conditional_existential_box_cast : // CHECK: [[LIFETIME_EXTENDING_COPY:%.*]] = copy_value %0 -// CHECK: [[E:%[0-9]+]] = alloc_stack $Error +// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error // CHECK: [[T:%[0-9]+]] = alloc_stack $TestError // CHECK: destroy_addr [[E]] // CHECK-NEXT: store [[LIFETIME_EXTENDING_COPY]] to [init] [[T]] diff --git a/test/SILOptimizer/sil_combine_peephole_thick_to_objc_metatype.sil b/test/SILOptimizer/sil_combine_peephole_thick_to_objc_metatype.sil index 6cfa1250e59bf..5d63313c591d8 100644 --- a/test/SILOptimizer/sil_combine_peephole_thick_to_objc_metatype.sil +++ b/test/SILOptimizer/sil_combine_peephole_thick_to_objc_metatype.sil @@ -36,7 +36,7 @@ bb0: // (thick_to_objc_metatype (existential_metatype @thick)) -> (existential_metatype @objc_metatype) // -// CHECK-LABEL: sil @_TF31peephole_thick_to_objc_metatype48test_thick_to_objc_metatype_existential_metatypeFPS_1X_Ps9AnyObject_ : $@convention(thin) (@owned X) -> @owned AnyObject +// CHECK-LABEL: sil @_TF31peephole_thick_to_objc_metatype48test_thick_to_objc_metatype_existential_metatypeFPS_1X_Ps9AnyObject_ : $@convention(thin) (@owned any X) -> @owned AnyObject // CHECK-NOT: existential_metatype $@thick // CHECK-NOT: {{thick_to_objc_metatype }} // CHECK: existential_metatype $@objc_metatype @@ -88,7 +88,7 @@ bb0: // (objc_to_objc_metatype (existential_metatype @objc_metatype)) -> (existential_metatype @thick) // -// CHECK-LABEL: sil @_TF31peephole_thick_to_objc_metatype48test_objc_to_thick_metatype_existential_metatypeFPS_1X_Ps9AnyObject_ : $@convention(thin) (@owned X) -> @thick X.Type +// CHECK-LABEL: sil @_TF31peephole_thick_to_objc_metatype48test_objc_to_thick_metatype_existential_metatypeFPS_1X_Ps9AnyObject_ : $@convention(thin) (@owned any X) -> @thick any X.Type // CHECK-NOT: existential_metatype $@objc_metatype // CHECK-NOT: {{objc_to_thick_metatype }} // CHECK: existential_metatype $@thick @@ -122,7 +122,7 @@ bb0(%0 : $T): // CHECK: [[T:%.*]] = apply // CHECK-NOT: objc_to_thick_metatype // CHECK-NOT: thick_to_objc_metatype -// CHECK: enum $Optional<@objc_metatype AnyObject.Type>, #Optional.some!enumelt, [[T]] : $@objc_metatype AnyObject.Type +// CHECK: enum $Optional<@objc_metatype any AnyObject.Type>, #Optional.some!enumelt, [[T]] : $@objc_metatype any AnyObject.Type // CHECK: } // end sil function '$test_peephole_objc_to_thick_to_objc' sil @$test_peephole_objc_to_thick_to_objc : $@convention(thin) (@guaranteed NSObject) -> Optional> { diff --git a/test/SILOptimizer/sil_combine_peephole_thick_to_objc_metatype_ossa.sil b/test/SILOptimizer/sil_combine_peephole_thick_to_objc_metatype_ossa.sil index 15859522aece3..95260bc0a4ef5 100644 --- a/test/SILOptimizer/sil_combine_peephole_thick_to_objc_metatype_ossa.sil +++ b/test/SILOptimizer/sil_combine_peephole_thick_to_objc_metatype_ossa.sil @@ -36,7 +36,7 @@ bb0: // (thick_to_objc_metatype (existential_metatype @thick)) -> (existential_metatype @objc_metatype) // -// CHECK-LABEL: sil [ossa] @_TF31peephole_thick_to_objc_metatype48test_thick_to_objc_metatype_existential_metatypeFPS_1X_Ps9AnyObject_ : $@convention(thin) (@owned X) -> @owned AnyObject +// CHECK-LABEL: sil [ossa] @_TF31peephole_thick_to_objc_metatype48test_thick_to_objc_metatype_existential_metatypeFPS_1X_Ps9AnyObject_ : $@convention(thin) (@owned any X) -> @owned AnyObject // CHECK-NOT: existential_metatype $@thick // CHECK-NOT: {{thick_to_objc_metatype }} // CHECK: existential_metatype $@objc_metatype @@ -88,7 +88,7 @@ bb0: // (objc_to_objc_metatype (existential_metatype @objc_metatype)) -> (existential_metatype @thick) // -// CHECK-LABEL: sil [ossa] @_TF31peephole_thick_to_objc_metatype48test_objc_to_thick_metatype_existential_metatypeFPS_1X_Ps9AnyObject_ : $@convention(thin) (@owned X) -> @thick X.Type +// CHECK-LABEL: sil [ossa] @_TF31peephole_thick_to_objc_metatype48test_objc_to_thick_metatype_existential_metatypeFPS_1X_Ps9AnyObject_ : $@convention(thin) (@owned any X) -> @thick any X.Type // CHECK-NOT: existential_metatype $@objc_metatype // CHECK-NOT: {{objc_to_thick_metatype }} // CHECK: existential_metatype $@thick @@ -122,7 +122,7 @@ bb0(%0 : @owned $T): // CHECK: [[T:%.*]] = apply // CHECK-NOT: objc_to_thick_metatype // CHECK-NOT: thick_to_objc_metatype -// CHECK: enum $Optional<@objc_metatype AnyObject.Type>, #Optional.some!enumelt, [[T]] : $@objc_metatype AnyObject.Type +// CHECK: enum $Optional<@objc_metatype any AnyObject.Type>, #Optional.some!enumelt, [[T]] : $@objc_metatype any AnyObject.Type // CHECK: } // end sil function '$test_peephole_objc_to_thick_to_objc' sil [ossa] @$test_peephole_objc_to_thick_to_objc : $@convention(thin) (@guaranteed NSObject) -> Optional> { diff --git a/test/SILOptimizer/sil_combine_protocol_conf.swift b/test/SILOptimizer/sil_combine_protocol_conf.swift index 79c5db9c5e5ff..10317522c5212 100644 --- a/test/SILOptimizer/sil_combine_protocol_conf.swift +++ b/test/SILOptimizer/sil_combine_protocol_conf.swift @@ -118,9 +118,9 @@ public class Other { // CHECK: debug_value // CHECK: integer_literal // CHECK: [[R1:%.*]] = ref_element_addr %0 : $Other, #Other.z -// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[R1]] : $*DerivedProtocol to $*@opened("{{.*}}", DerivedProtocol) Self -// CHECK: [[W1:%.*]] = witness_method $@opened("{{.*}}", DerivedProtocol) Self, #DerivedProtocol.foo : (Self) -> () -> Int, [[O1]] : $*@opened("{{.*}}", DerivedProtocol) Self : $@convention(witness_method: DerivedProtocol) <τ_0_0 where τ_0_0 : DerivedProtocol> (@in_guaranteed τ_0_0) -> Int -// CHECK: apply [[W1]]<@opened("{{.*}}", DerivedProtocol) Self>([[O1]]) : $@convention(witness_method: DerivedProtocol) <τ_0_0 where τ_0_0 : DerivedProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[R1]] : $*any DerivedProtocol to $*@opened("{{.*}}", any DerivedProtocol) Self +// CHECK: [[W1:%.*]] = witness_method $@opened("{{.*}}", any DerivedProtocol) Self, #DerivedProtocol.foo : (Self) -> () -> Int, [[O1]] : $*@opened("{{.*}}", any DerivedProtocol) Self : $@convention(witness_method: DerivedProtocol) <τ_0_0 where τ_0_0 : DerivedProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: apply [[W1]]<@opened("{{.*}}", any DerivedProtocol) Self>([[O1]]) : $@convention(witness_method: DerivedProtocol) <τ_0_0 where τ_0_0 : DerivedProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK: struct_extract // CHECK: integer_literal // CHECK: builtin @@ -128,9 +128,9 @@ public class Other { // CHECK: tuple_extract // CHECK: cond_fail // CHECK: [[R2:%.*]] = ref_element_addr %0 : $Other, #Other.p -// CHECK: [[O2:%.*]] = open_existential_addr immutable_access [[R2]] : $*PublicProtocol to $*@opened("{{.*}}", PublicProtocol) Self -// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", PublicProtocol) Self, #PublicProtocol.foo : (Self) -> () -> Int, [[O2]] : $*@opened("{{.*}}", PublicProtocol) Self : $@convention(witness_method: PublicProtocol) <τ_0_0 where τ_0_0 : PublicProtocol> (@in_guaranteed τ_0_0) -> Int -// CHECK: apply [[W2]]<@opened("{{.*}}", PublicProtocol) Self>([[O2]]) : $@convention(witness_method: PublicProtocol) <τ_0_0 where τ_0_0 : PublicProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: [[O2:%.*]] = open_existential_addr immutable_access [[R2]] : $*any PublicProtocol to $*@opened("{{.*}}", any PublicProtocol) Self +// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", any PublicProtocol) Self, #PublicProtocol.foo : (Self) -> () -> Int, [[O2]] : $*@opened("{{.*}}", any PublicProtocol) Self : $@convention(witness_method: PublicProtocol) <τ_0_0 where τ_0_0 : PublicProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: apply [[W2]]<@opened("{{.*}}", any PublicProtocol) Self>([[O2]]) : $@convention(witness_method: PublicProtocol) <τ_0_0 where τ_0_0 : PublicProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK: struct_extract // CHECK: builtin // CHECK: tuple_extract @@ -142,18 +142,18 @@ public class Other { // CHECK: tuple_extract // CHECK: cond_fail // CHECK: [[R3:%.*]] = ref_element_addr %0 : $Other, #Other.r -// CHECK: [[O3:%.*]] = open_existential_addr immutable_access [[R3]] : $*GenericProtocol to $*@opened("{{.*}}", GenericProtocol) Self -// CHECK: [[W3:%.*]] = witness_method $@opened("{{.*}}", GenericProtocol) Self, #GenericProtocol.foo : (Self) -> () -> Int, [[O3]] : $*@opened("{{.*}}", GenericProtocol) Self : $@convention(witness_method: GenericProtocol) <τ_0_0 where τ_0_0 : GenericProtocol> (@in_guaranteed τ_0_0) -> Int -// CHECK: apply [[W3]]<@opened("{{.*}}", GenericProtocol) Self>([[O3]]) : $@convention(witness_method: GenericProtocol) <τ_0_0 where τ_0_0 : GenericProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: [[O3:%.*]] = open_existential_addr immutable_access [[R3]] : $*any GenericProtocol to $*@opened("{{.*}}", any GenericProtocol) Self +// CHECK: [[W3:%.*]] = witness_method $@opened("{{.*}}", any GenericProtocol) Self, #GenericProtocol.foo : (Self) -> () -> Int, [[O3]] : $*@opened("{{.*}}", any GenericProtocol) Self : $@convention(witness_method: GenericProtocol) <τ_0_0 where τ_0_0 : GenericProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: apply [[W3]]<@opened("{{.*}}", any GenericProtocol) Self>([[O3]]) : $@convention(witness_method: GenericProtocol) <τ_0_0 where τ_0_0 : GenericProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK: struct_extract // CHECK: builtin // CHECK: tuple_extract // CHECK: tuple_extract // CHECK: cond_fail // CHECK: [[R4:%.*]] = ref_element_addr %0 : $Other, #Other.s -// CHECK: [[O4:%.*]] = open_existential_addr immutable_access %36 : $*MultipleConformanceProtocol to $*@opened("{{.*}}", MultipleConformanceProtocol) Self -// CHECK: [[W4:%.*]] = witness_method $@opened("{{.*}}", MultipleConformanceProtocol) Self, #MultipleConformanceProtocol.foo : (Self) -> () -> Int, %37 : $*@opened("{{.*}}", MultipleConformanceProtocol) Self : $@convention(witness_method: MultipleConformanceProtocol) <τ_0_0 where τ_0_0 : MultipleConformanceProtocol> (@in_guaranteed τ_0_0) -> Int -// CHECK: apply [[W4]]<@opened("{{.*}}", MultipleConformanceProtocol) Self>(%37) : $@convention(witness_method: MultipleConformanceProtocol) <τ_0_0 where τ_0_0 : MultipleConformanceProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: [[O4:%.*]] = open_existential_addr immutable_access %36 : $*any MultipleConformanceProtocol to $*@opened("{{.*}}", any MultipleConformanceProtocol) Self +// CHECK: [[W4:%.*]] = witness_method $@opened("{{.*}}", any MultipleConformanceProtocol) Self, #MultipleConformanceProtocol.foo : (Self) -> () -> Int, %37 : $*@opened("{{.*}}", any MultipleConformanceProtocol) Self : $@convention(witness_method: MultipleConformanceProtocol) <τ_0_0 where τ_0_0 : MultipleConformanceProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: apply [[W4]]<@opened("{{.*}}", any MultipleConformanceProtocol) Self>(%37) : $@convention(witness_method: MultipleConformanceProtocol) <τ_0_0 where τ_0_0 : MultipleConformanceProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK: struct_extract // CHECK: builtin // CHECK: tuple_extract @@ -239,18 +239,18 @@ public class OtherClass { // CHECK: debug_value // CHECK: [[R1:%.*]] = ref_element_addr [[ARG]] : $OtherClass, #OtherClass.arg1 // CHECK: [[ACC1:%.*]] = begin_access [read] [static] [no_nested_conflict] [[R1]] -// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[ACC1]] : $*PropProtocol to $*@opened("{{.*}}", PropProtocol) Self -// CHECK: [[U1:%.*]] = unchecked_addr_cast [[O1]] : $*@opened("{{.*}}", PropProtocol) Self to $*PropClass +// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[ACC1]] : $*any PropProtocol to $*@opened("{{.*}}", any PropProtocol) Self +// CHECK: [[U1:%.*]] = unchecked_addr_cast [[O1]] : $*@opened("{{.*}}", any PropProtocol) Self to $*PropClass // CHECK: [[S1:%.*]] = struct_element_addr [[U1]] : $*PropClass, #PropClass.val // CHECK: [[S11:%.*]] = struct_element_addr [[S1]] : $*Int, #Int._value // CHECK: load [[S11]] // CHECK: [[R2:%.*]] = ref_element_addr [[ARG]] : $OtherClass, #OtherClass.arg2 // CHECK: [[ACC2:%.*]] = begin_access [read] [static] [no_nested_conflict] [[R2]] -// CHECK: [[O2:%.*]] = open_existential_addr immutable_access [[ACC2]] : $*GenericPropProtocol to $*@opened("{{.*}}", GenericPropProtocol) Self +// CHECK: [[O2:%.*]] = open_existential_addr immutable_access [[ACC2]] : $*any GenericPropProtocol to $*@opened("{{.*}}", any GenericPropProtocol) Self // CHECK: [[T1:%.*]] = alloc_stack $@opened // CHECK: copy_addr [[O2]] to [initialization] [[T1]] -// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", GenericPropProtocol) Self, #GenericPropProtocol.val!getter : (Self) -> () -> Int, [[O2]] : $*@opened("{{.*}}", GenericPropProtocol) Self : $@convention(witness_method: GenericPropProtocol) <τ_0_0 where τ_0_0 : GenericPropProtocol> (@in_guaranteed τ_0_0) -> Int -// CHECK: apply [[W2]]<@opened("{{.*}}", GenericPropProtocol) Self>([[T1]]) : $@convention(witness_method: GenericPropProtocol) <τ_0_0 where τ_0_0 : GenericPropProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", any GenericPropProtocol) Self, #GenericPropProtocol.val!getter : (Self) -> () -> Int, [[O2]] : $*@opened("{{.*}}", any GenericPropProtocol) Self : $@convention(witness_method: GenericPropProtocol) <τ_0_0 where τ_0_0 : GenericPropProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: apply [[W2]]<@opened("{{.*}}", any GenericPropProtocol) Self>([[T1]]) : $@convention(witness_method: GenericPropProtocol) <τ_0_0 where τ_0_0 : GenericPropProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK: struct_extract // CHECK: integer_literal // CHECK: builtin @@ -259,8 +259,8 @@ public class OtherClass { // CHECK: cond_fail // CHECK: [[R4:%.*]] = ref_element_addr [[ARG]] : $OtherClass, #OtherClass.arg3 // CHECK: [[ACC4:%.*]] = begin_access [read] [static] [no_nested_conflict] [[R4]] -// CHECK: [[O4:%.*]] = open_existential_addr immutable_access [[ACC4]] : $*NestedPropProtocol to $*@opened("{{.*}}", NestedPropProtocol) Self -// CHECK: [[U4:%.*]] = unchecked_addr_cast [[O4]] : $*@opened("{{.*}}", NestedPropProtocol) Self to $*Outer.Inner +// CHECK: [[O4:%.*]] = open_existential_addr immutable_access [[ACC4]] : $*any NestedPropProtocol to $*@opened("{{.*}}", any NestedPropProtocol) Self +// CHECK: [[U4:%.*]] = unchecked_addr_cast [[O4]] : $*@opened("{{.*}}", any NestedPropProtocol) Self to $*Outer.Inner // CHECK: [[S4:%.*]] = struct_element_addr [[U4]] : $*Outer.Inner, #Outer.Inner.val // CHECK: [[S41:%.*]] = struct_element_addr [[S4]] : $*Int, #Int._value // CHECK: load [[S41]] @@ -270,11 +270,11 @@ public class OtherClass { // CHECK: cond_fail // CHECK: [[R5:%.*]] = ref_element_addr [[ARG]] : $OtherClass, #OtherClass.arg4 // CHECK: [[ACC5:%.*]] = begin_access [read] [static] [no_nested_conflict] [[R5]] -// CHECK: [[O5:%.*]] = open_existential_addr immutable_access [[ACC5]] : $*GenericNestedPropProtocol to $*@opened("{{.*}}", GenericNestedPropProtocol) Self +// CHECK: [[O5:%.*]] = open_existential_addr immutable_access [[ACC5]] : $*any GenericNestedPropProtocol to $*@opened("{{.*}}", any GenericNestedPropProtocol) Self // CHECK: [[T2:%.*]] = alloc_stack $@opened // CHECK: copy_addr [[O5]] to [initialization] [[T2]] -// CHECK: [[W5:%.*]] = witness_method $@opened("{{.*}}", GenericNestedPropProtocol) Self, #GenericNestedPropProtocol.val!getter : (Self) -> () -> Int, [[O5:%.*]] : $*@opened("{{.*}}", GenericNestedPropProtocol) Self : $@convention(witness_method: GenericNestedPropProtocol) <τ_0_0 where τ_0_0 : GenericNestedPropProtocol> (@in_guaranteed τ_0_0) -> Int -// CHECK: apply [[W5]]<@opened("{{.*}}", GenericNestedPropProtocol) Self>([[T2]]) : $@convention(witness_method: GenericNestedPropProtocol) <τ_0_0 where τ_0_0 : GenericNestedPropProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: [[W5:%.*]] = witness_method $@opened("{{.*}}", any GenericNestedPropProtocol) Self, #GenericNestedPropProtocol.val!getter : (Self) -> () -> Int, [[O5:%.*]] : $*@opened("{{.*}}", any GenericNestedPropProtocol) Self : $@convention(witness_method: GenericNestedPropProtocol) <τ_0_0 where τ_0_0 : GenericNestedPropProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: apply [[W5]]<@opened("{{.*}}", any GenericNestedPropProtocol) Self>([[T2]]) : $@convention(witness_method: GenericNestedPropProtocol) <τ_0_0 where τ_0_0 : GenericNestedPropProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK: struct_extract // CHECK: builtin // CHECK: tuple_extract @@ -341,11 +341,11 @@ public class OtherKlass { // CHECK: integer_literal // CHECK: [[R1:%.*]] = ref_element_addr [[ARG]] : $OtherKlass, #OtherKlass.arg2 // CHECK: [[ACC1:%.*]] = begin_access [read] [static] [no_nested_conflict] [[R1]] -// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[ACC1]] : $*AGenericProtocol to $*@opened("{{.*}}", AGenericProtocol) Self +// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[ACC1]] : $*any AGenericProtocol to $*@opened("{{.*}}", any AGenericProtocol) Self // CHECK: [[T1:%.*]] = alloc_stack $@opened // CHECK: copy_addr [[O1]] to [initialization] [[T1]] -// CHECK: [[W1:%.*]] = witness_method $@opened("{{.*}}", AGenericProtocol) Self, #AGenericProtocol.val!getter : (Self) -> () -> Int, [[O1]] : $*@opened("{{.*}}", AGenericProtocol) Self : $@convention(witness_method: AGenericProtocol) <τ_0_0 where τ_0_0 : AGenericProtocol> (@in_guaranteed τ_0_0) -> Int -// CHECK: apply [[W1]]<@opened("{{.*}}", AGenericProtocol) Self>([[T1]]) : $@convention(witness_method: AGenericProtocol) <τ_0_0 where τ_0_0 : AGenericProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: [[W1:%.*]] = witness_method $@opened("{{.*}}", any AGenericProtocol) Self, #AGenericProtocol.val!getter : (Self) -> () -> Int, [[O1]] : $*@opened("{{.*}}", any AGenericProtocol) Self : $@convention(witness_method: AGenericProtocol) <τ_0_0 where τ_0_0 : AGenericProtocol> (@in_guaranteed τ_0_0) -> Int +// CHECK: apply [[W1]]<@opened("{{.*}}", any AGenericProtocol) Self>([[T1]]) : $@convention(witness_method: AGenericProtocol) <τ_0_0 where τ_0_0 : AGenericProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK: struct_extract // CHECK: integer_literal // CHECK: builtin diff --git a/test/SILOptimizer/sil_combiner_concrete_prop_all_args.sil b/test/SILOptimizer/sil_combiner_concrete_prop_all_args.sil index 00a606da43ded..c7c2b2d1a69d5 100644 --- a/test/SILOptimizer/sil_combiner_concrete_prop_all_args.sil +++ b/test/SILOptimizer/sil_combiner_concrete_prop_all_args.sil @@ -347,12 +347,12 @@ bb0(%0 : $K): return %2 : $Int32 } // end sil function '$s21existential_transform1KCAA1PA2aDP3foos5Int32VyFTW' -// CHECK-LABEL: sil hidden [noinline] @$s21existential_transform18do_not_optimize_cp1as5Int32VAA1P_p_tF : $@convention(thin) (@guaranteed P) -> Int32 { -// CHECK: bb0(%0 : $P): -// CHECK: debug_value %0 : $P, let, name "a", argno 1 -// CHECK: %2 = open_existential_ref %0 : $P to $@opened("{{.*}}", P) Self -// CHECK: %3 = witness_method $@opened("{{.*}}", P) Self, #P.foo : (Self) -> () -> Int32, %2 : $@opened("{{.*}}", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> Int32 -// CHECK: %4 = apply %3<@opened("{{.*}}", P) Self>(%2) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> Int32 +// CHECK-LABEL: sil hidden [noinline] @$s21existential_transform18do_not_optimize_cp1as5Int32VAA1P_p_tF : $@convention(thin) (@guaranteed any P) -> Int32 { +// CHECK: bb0(%0 : $any P): +// CHECK: debug_value %0 : $any P, let, name "a", argno 1 +// CHECK: %2 = open_existential_ref %0 : $any P to $@opened("{{.*}}", any P) Self +// CHECK: %3 = witness_method $@opened("{{.*}}", any P) Self, #P.foo : (Self) -> () -> Int32, %2 : $@opened("{{.*}}", any P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> Int32 +// CHECK: %4 = apply %3<@opened("{{.*}}", any P) Self>(%2) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> Int32 // CHECK: return %4 : $Int32 // CHECK-LABEL: } // end sil function '$s21existential_transform18do_not_optimize_cp1as5Int32VAA1P_p_tF' sil hidden [noinline] @$s21existential_transform18do_not_optimize_cp1as5Int32VAA1P_p_tF : $@convention(thin) (@guaranteed P) -> Int32 { @@ -393,16 +393,16 @@ bb0(%0 : $*PP): // CHECK-LABEL: sil hidden [noinline] @$s21existential_transform24do_not_optimize_inout_cpyyF : $@convention(thin) () -> () { // CHECK: bb0: -// CHECK: %0 = alloc_stack $PP, var, name "magic5" +// CHECK: %0 = alloc_stack $any PP, var, name "magic5" // CHECK: %1 = alloc_ref $KK // CHECK: debug_value %1 : $KK, let, name "self", argno 1 -// CHECK: %3 = init_existential_ref %1 : $KK : $KK, $PP -// CHECK: store %3 to %0 : $*PP -// CHECK: %5 = function_ref @$s21existential_transform13wrap_inout_cp1as5Int32VAA2PP_pz_tF : $@convention(thin) (@inout PP) -> Int32 -// CHECK: %6 = apply %5(%0) : $@convention(thin) (@inout PP) -> Int32 -// CHECK: %7 = load %0 : $*PP -// CHECK: strong_release %7 : $PP -// CHECK: dealloc_stack %0 : $*PP +// CHECK: %3 = init_existential_ref %1 : $KK : $KK, $any PP +// CHECK: store %3 to %0 : $*any PP +// CHECK: %5 = function_ref @$s21existential_transform13wrap_inout_cp1as5Int32VAA2PP_pz_tF : $@convention(thin) (@inout any PP) -> Int32 +// CHECK: %6 = apply %5(%0) : $@convention(thin) (@inout any PP) -> Int32 +// CHECK: %7 = load %0 : $*any PP +// CHECK: strong_release %7 : $any PP +// CHECK: dealloc_stack %0 : $*any PP // CHECK: %10 = tuple () // CHECK: return %10 : $() // CHECK: } // end sil function '$s21existential_transform24do_not_optimize_inout_cpyyF' @@ -449,13 +449,13 @@ bb0(%0 : $*PPP): // // CHECK-LABEL: sil hidden [noinline] @$s21existential_transform9inout_ncpyyF : $@convention(thin) () -> () { // CHECK: bb0: -// CHECK: [[ALLOC:%.*]] = alloc_stack $PPP, var, name "magic6" +// CHECK: [[ALLOC:%.*]] = alloc_stack $any PPP, var, name "magic6" // CHECK: alloc_ref $KKK -// CHECK: [[ADR:%.*]] = open_existential_addr mutable_access [[ALLOC]] : $*PPP to $*@opened("{{.*}}", PPP) Self +// CHECK: [[ADR:%.*]] = open_existential_addr mutable_access [[ALLOC]] : $*any PPP to $*@opened("{{.*}}", any PPP) Self // CHECK: [[CAST:%.*]] = unchecked_addr_cast [[ADR]] // CHECK: [[F:%.*]] = function_ref @$s21existential_transform14wrap_inout_ncp1as5Int32VAA3PPP_pz_tFTf4e_n4main3KKKC_Tg5 : $@convention(thin) (@inout KKK) -> Int32 // CHECK: apply [[F]]([[CAST]]) -// CHECK: dealloc_stack %0 : $*PPP +// CHECK: dealloc_stack %0 : $*any PPP // CHECK-LABEL: } // end sil function '$s21existential_transform9inout_ncpyyF' sil hidden [noinline] @$s21existential_transform9inout_ncpyyF : $@convention(thin) () -> () { bb0: @@ -499,13 +499,13 @@ bb0(%0 : $*PPPP): // // CHECK-LABEL: sil hidden [noinline] @$s21existential_transform16struct_inout_ncpyyF : $@convention(thin) () -> () { // CHECK: bb0: -// CHECK: [[ALLOC:%.*]] = alloc_stack $PPPP, var, name "magic7" +// CHECK: [[ALLOC:%.*]] = alloc_stack $any PPPP, var, name "magic7" // CHECK: struct $SSSS () -// CHECK: [[ADR:%.*]] = open_existential_addr mutable_access %0 : $*PPPP to $*@opened("{{.*}}", PPPP) Self +// CHECK: [[ADR:%.*]] = open_existential_addr mutable_access %0 : $*any PPPP to $*@opened("{{.*}}", any PPPP) Self // CHECK: [[CAST:%.*]] = unchecked_addr_cast [[ADR]] // CHECK: [[F:%.*]] = function_ref @$s21existential_transform21wrap_struct_inout_ncp1as5Int32VAA4PPPP_pz_tFTf4e_n4main4SSSSV_Tg5 : $@convention(thin) (@inout SSSS) -> Int32 // CHECK: apply [[F]]([[CAST]]) -// CHECK: dealloc_stack [[ALLOC]] : $*PPPP +// CHECK: dealloc_stack [[ALLOC]] : $*any PPPP // CHECK-LABEL: } // end sil function '$s21existential_transform16struct_inout_ncpyyF' sil hidden [noinline] @$s21existential_transform16struct_inout_ncpyyF : $@convention(thin) () -> () { bb0: diff --git a/test/SILOptimizer/sil_simplify_instrs.sil b/test/SILOptimizer/sil_simplify_instrs.sil index 07aad636b05cf..0945c366bdc6b 100644 --- a/test/SILOptimizer/sil_simplify_instrs.sil +++ b/test/SILOptimizer/sil_simplify_instrs.sil @@ -359,8 +359,8 @@ protocol SomeP {} public enum SpecialEnum : SomeP {} // CHECK-LABEL: sil @testSimplifyMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool { -// CHECK: init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type -// CHECK: init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type +// CHECK: init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick any Any.Type +// CHECK: init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick any Any.Type // CHECK-LABEL: } // end sil function 'testSimplifyMetatype' sil @testSimplifyMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool { bb0(%0 : $@thick SpecialEnum.Type): diff --git a/test/SILOptimizer/sil_simplify_instrs_ossa.sil b/test/SILOptimizer/sil_simplify_instrs_ossa.sil index dc64a57c27cbb..50452387088d0 100644 --- a/test/SILOptimizer/sil_simplify_instrs_ossa.sil +++ b/test/SILOptimizer/sil_simplify_instrs_ossa.sil @@ -405,8 +405,8 @@ protocol SomeP {} public enum SpecialEnum : SomeP {} // CHECK-LABEL: sil [ossa] @testSimplifyMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool { -// CHECK: init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type -// CHECK: init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type +// CHECK: init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick any Any.Type +// CHECK: init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick any Any.Type // CHECK: } // end sil function 'testSimplifyMetatype' sil [ossa] @testSimplifyMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool { bb0(%0 : $@thick SpecialEnum.Type): diff --git a/test/SILOptimizer/simplify-cfg-debugonly.sil b/test/SILOptimizer/simplify-cfg-debugonly.sil index 30a251de7540b..1cfc14444f3b4 100644 --- a/test/SILOptimizer/simplify-cfg-debugonly.sil +++ b/test/SILOptimizer/simplify-cfg-debugonly.sil @@ -16,8 +16,8 @@ sil @getKlass : $@convention(thin) () -> @owned Klass // Verify that checked-cast jump-threading kicks in and generates verifiable SIL. // -// CHECK: Condition is the same if reached over {{.*}} parent @$testCheckCastJumpThread : $@convention(thin) (@guaranteed Klass) -> @owned OtherKlass } -// CHECK-NEXT: bb3(%{{.*}} : $OtherKlass): +// CHECK: Condition is the same if reached over {{.*}} parent @$testCheckCastJumpThread : $@convention(thin) (@guaranteed Klass) -> @owned any OtherKlass } +// CHECK-NEXT: bb3(%{{.*}} : $any OtherKlass): // CHECK-NEXT: br bb5(%{{.*}} : $Klass) sil shared @$testCheckCastJumpThread : $@convention(thin) (@guaranteed Klass) -> @owned OtherKlass { bb0(%0 : $Klass): diff --git a/test/SILOptimizer/simplify_cfg.sil b/test/SILOptimizer/simplify_cfg.sil index c2c1ca575c87f..6f003a9d1154f 100644 --- a/test/SILOptimizer/simplify_cfg.sil +++ b/test/SILOptimizer/simplify_cfg.sil @@ -2481,7 +2481,7 @@ sil @rethrow_function : $@convention(thin) (@owned @callee_owned (Int) -> (Int, sil @non_throwing_closure : $@convention(thin) (Int) -> Int // CHECK-LABEL: sil @replace_try_apply_with_apply -// CHECK: [[R:%[0-9]+]] = apply [nothrow] %1(%{{[0-9]+}}) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error) +// CHECK: [[R:%[0-9]+]] = apply [nothrow] %1(%{{[0-9]+}}) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error any Error)) -> (Int, @error any Error) // CHECK-NEXT: dealloc_stack // CHECK-NEXT: return [[R]] : $Int sil @replace_try_apply_with_apply : $@convention(thin) () -> Int { @@ -2948,10 +2948,10 @@ class IsQ : Q {} // --- // CHECK-LABEL: sil @test_dead_checked_cast_br : $@convention(thin) (@in IsQ) -> () { // CHECK: bb0(%0 : $*IsQ): -// CHECK: [[Q:%.*]] = alloc_stack $Q +// CHECK: [[Q:%.*]] = alloc_stack $any Q // CHECK: [[LD:%.*]] = load %0 : $*IsQ // CHECK: strong_release [[LD]] : $IsQ -// CHECK: dealloc_stack [[Q]] : $*Q +// CHECK: dealloc_stack [[Q]] : $*any Q // CHECK: [[R:%.*]] = tuple () // CHECK: return [[R]] : $() // CHECK-LABEL: } // end sil function 'test_dead_checked_cast_br' diff --git a/test/SILOptimizer/simplify_cfg_ossa.sil b/test/SILOptimizer/simplify_cfg_ossa.sil index 65365268265de..5a7cdfeed9c0d 100644 --- a/test/SILOptimizer/simplify_cfg_ossa.sil +++ b/test/SILOptimizer/simplify_cfg_ossa.sil @@ -1566,10 +1566,10 @@ class IsQ : Q {} // --- // CHECK-LABEL: sil [ossa] @test_dead_checked_cast_br : $@convention(thin) (@in IsQ) -> () { // CHECK: bb0(%0 : $*IsQ): -// CHECK: [[Q:%.*]] = alloc_stack $Q +// CHECK: [[Q:%.*]] = alloc_stack $any Q // CHECK: [[LD:%.*]] = load [take] %0 : $*IsQ // CHECK: destroy_value [[LD]] : $IsQ -// CHECK: dealloc_stack [[Q]] : $*Q +// CHECK: dealloc_stack [[Q]] : $*any Q // CHECK: [[R:%.*]] = tuple () // CHECK: return [[R]] : $() // CHECK-LABEL: } // end sil function 'test_dead_checked_cast_br' diff --git a/test/SILOptimizer/simplify_cfg_tryapply.sil b/test/SILOptimizer/simplify_cfg_tryapply.sil index a2542ddac1612..3ba5c3a6560f3 100644 --- a/test/SILOptimizer/simplify_cfg_tryapply.sil +++ b/test/SILOptimizer/simplify_cfg_tryapply.sil @@ -44,7 +44,7 @@ sil [ossa] @rethrowGuaranteed : $@convention(thin) (@guaranteed (Optional, B) sil [ossa] @rethrowOwned : $@convention(thin) (@owned (Optional, B)) -> Int // CHECK-LABEL: sil [ossa] @replace_try_apply_with_apply -// CHECK: [[R:%[0-9]+]] = apply [nothrow] %1(%{{[0-9]+}}) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error) +// CHECK: [[R:%[0-9]+]] = apply [nothrow] %1(%{{[0-9]+}}) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error any Error)) -> (Int, @error any Error) // CHECK-NEXT: dealloc_stack // CHECK-NEXT: return [[R]] : $Int sil [ossa] @replace_try_apply_with_apply : $@convention(thin) () -> Int { @@ -71,7 +71,7 @@ bb2(%8 : @owned $Error): // CHECK: [[COPY:%.*]] = copy_value [[INIT]] : $@callee_owned (@owned EE) -> @owned CC // CHECK: [[CVT:%.*]] = convert_function [[INIT]] // CHECK-NOT: try_apply -// CHECK: destroy_value [[CVT]] : $@callee_owned (@owned EE) -> (@owned Optional, @error Error) +// CHECK: destroy_value [[CVT]] : $@callee_owned (@owned EE) -> (@owned Optional, @error any Error) // CHECK: apply [[COPY]] // Check that return value is properly casted // CHECK-NEXT: enum $Optional, #Optional.some!enumelt, %{{.*}} : $CC @@ -266,15 +266,15 @@ bb2(%16 : @owned $Error): // CHECK-LABEL: sil [ossa] @test_owned_callee : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 { // CHECK: [[PA:%.*]] = partial_apply %2(%0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 // CHECK: [[COPY:%.*]] = copy_value [[PA]] : $@callee_owned (Builtin.Int32) -> Builtin.Int32 -// CHECK: [[CVT:%.*]] = convert_function [[PA]] : $@callee_owned (Builtin.Int32) -> Builtin.Int32 to $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error Error) +// CHECK: [[CVT:%.*]] = convert_function [[PA]] : $@callee_owned (Builtin.Int32) -> Builtin.Int32 to $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error any Error) // CHECK: cond_br undef, bb1, bb2 // CHECK: bb1: -// CHECK: destroy_value %5 : $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error Error) +// CHECK: destroy_value %5 : $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error any Error) // CHECK: [[CALL:%.*]] = apply [[COPY]] // CHECK: br bb3([[CALL]] : $Builtin.Int32) // CHECK: bb2: // Preds: bb0 // CHECK: destroy_value [[COPY]] : $@callee_owned (Builtin.Int32) -> Builtin.Int32 -// CHECK: destroy_value [[CVT]] : $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error Error) +// CHECK: destroy_value [[CVT]] : $@callee_owned (Builtin.Int32) -> (Builtin.Int32, @error any Error) // CHECK: br bb3( // CHECK: bb3( // CHECK-NEXT: return diff --git a/test/SILOptimizer/specialize.sil b/test/SILOptimizer/specialize.sil index 007e00ad51a86..b34b61c596934 100644 --- a/test/SILOptimizer/specialize.sil +++ b/test/SILOptimizer/specialize.sil @@ -613,7 +613,7 @@ sil @action_thunk : $@convention(thin) (@owned @callee_owned () -> (Never, @erro // // CHECK-LABEL: sil @testGenericClosureSpecialization // Call of the generic specialization of invokeGenericClosure -// CHECK: function_ref @$s20invokeGenericClosures5NeverO_Tg5 : $@convention(thin) (@owned @callee_owned () -> (@out Never, @error Error)) -> (Never, @error Error) +// CHECK: function_ref @$s20invokeGenericClosures5NeverO_Tg5 : $@convention(thin) (@owned @callee_owned () -> (@out Never, @error any Error)) -> (Never, @error any Error) // CHECK: apply [nothrow] // CHECK: unreachable // CHECK: end sil function 'testGenericClosureSpecialization' diff --git a/test/SILOptimizer/specialize_metatypes_with_nondefault_representation.sil b/test/SILOptimizer/specialize_metatypes_with_nondefault_representation.sil index 6e8e4197fd61d..1af029f5ad9d7 100644 --- a/test/SILOptimizer/specialize_metatypes_with_nondefault_representation.sil +++ b/test/SILOptimizer/specialize_metatypes_with_nondefault_representation.sil @@ -22,9 +22,9 @@ bb0(%0 : $*T): } // CHECK-LABEL: sil @tmp2 : $@convention(thin) () -> () { -// CHECK: [[FUN1:%[0-9]+]] = function_ref @$s3tmp4main9AnyObject_pXmT_Tg5 : $@convention(thin) () -> @thick AnyObject.Type +// CHECK: [[FUN1:%[0-9]+]] = function_ref @$s3tmp4main9AnyObject_pXmT_Tg5 : $@convention(thin) () -> @thick any AnyObject.Type // CHECK-NEXT: apply [[FUN1]] -// CHECK: [[FUN2:%[0-9]+]] = function_ref @$s3tmp4main9AnyObject_pXmo_Tg5 : $@convention(thin) () -> @objc_metatype AnyObject.Type +// CHECK: [[FUN2:%[0-9]+]] = function_ref @$s3tmp4main9AnyObject_pXmo_Tg5 : $@convention(thin) () -> @objc_metatype any AnyObject.Type // CHECK-NEXT: apply [[FUN2]] // CHECK: [[FUN3:%[0-9]+]] = function_ref @$s3tmpBi32_XMT_Tg5 : $@convention(thin) () -> @thick Builtin.Int32.Type // CHECK-NEXT: apply [[FUN3]] diff --git a/test/SILOptimizer/specialize_metatypes_with_nondefault_representation_ossa.sil b/test/SILOptimizer/specialize_metatypes_with_nondefault_representation_ossa.sil index ac662bc2918b1..c009a7bd08f3e 100644 --- a/test/SILOptimizer/specialize_metatypes_with_nondefault_representation_ossa.sil +++ b/test/SILOptimizer/specialize_metatypes_with_nondefault_representation_ossa.sil @@ -22,9 +22,9 @@ bb0(%0 : $*T): } // CHECK-LABEL: sil [ossa] @tmp2 : $@convention(thin) () -> () { -// CHECK: [[FUN1:%[0-9]+]] = function_ref @$s3tmp4main9AnyObject_pXmT_Tg5 : $@convention(thin) () -> @thick AnyObject.Type +// CHECK: [[FUN1:%[0-9]+]] = function_ref @$s3tmp4main9AnyObject_pXmT_Tg5 : $@convention(thin) () -> @thick any AnyObject.Type // CHECK-NEXT: apply [[FUN1]] -// CHECK: [[FUN2:%[0-9]+]] = function_ref @$s3tmp4main9AnyObject_pXmo_Tg5 : $@convention(thin) () -> @objc_metatype AnyObject.Type +// CHECK: [[FUN2:%[0-9]+]] = function_ref @$s3tmp4main9AnyObject_pXmo_Tg5 : $@convention(thin) () -> @objc_metatype any AnyObject.Type // CHECK-NEXT: apply [[FUN2]] // CHECK: [[FUN3:%[0-9]+]] = function_ref @$s3tmpBi32_XMT_Tg5 : $@convention(thin) () -> @thick Builtin.Int32.Type // CHECK-NEXT: apply [[FUN3]] diff --git a/test/SILOptimizer/specialize_opaque_type_archetypes.swift b/test/SILOptimizer/specialize_opaque_type_archetypes.swift index 1fc79e1b9394b..1493f9b95181e 100644 --- a/test/SILOptimizer/specialize_opaque_type_archetypes.swift +++ b/test/SILOptimizer/specialize_opaque_type_archetypes.swift @@ -414,7 +414,7 @@ func testIt(cl: (Int64) throws -> T) { // CHECK: store %0 to [[PA]] : $*PA // CHECK: [[F:%.*]] = function_ref @$s1A16testPartialApplyyyxAA2P4RzlF2ATQzs5Int64Vcxcfu_AeGcfu0_AA2PAV_TG5 : $@convention(thin) (Int64, @in_guaranteed PA) -> @out Int64 // CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[PA]]) : $@convention(thin) (Int64, @in_guaranteed PA) -> @out Int64 -// CHECK: convert_function [[C]] : $@callee_guaranteed (Int64) -> @out Int64 to $@callee_guaranteed @substituted <τ_0_0> (Int64) -> (@out τ_0_0, @error Error) for +// CHECK: convert_function [[C]] : $@callee_guaranteed (Int64) -> @out Int64 to $@callee_guaranteed @substituted <τ_0_0> (Int64) -> (@out τ_0_0, @error any Error) for @inline(never) func testPartialApply(_ t: T) { let fun = t.foo diff --git a/test/SILOptimizer/specialize_ossa.sil b/test/SILOptimizer/specialize_ossa.sil index 7a3b9dd004be7..51eed1e4c7558 100644 --- a/test/SILOptimizer/specialize_ossa.sil +++ b/test/SILOptimizer/specialize_ossa.sil @@ -661,7 +661,7 @@ sil @action_thunk : $@convention(thin) (@owned @callee_owned () -> (Never, @erro // // CHECK-LABEL: sil [ossa] @testGenericClosureSpecialization // Call of the generic specialization of invokeGenericClosure -// CHECK: function_ref @$s20invokeGenericClosures5NeverO_Tg5 : $@convention(thin) (@owned @callee_owned () -> (@out Never, @error Error)) -> (Never, @error Error) +// CHECK: function_ref @$s20invokeGenericClosures5NeverO_Tg5 : $@convention(thin) (@owned @callee_owned () -> (@out Never, @error any Error)) -> (Never, @error any Error) // CHECK: apply [nothrow] // CHECK: unreachable // CHECK: end sil function 'testGenericClosureSpecialization' @@ -955,8 +955,8 @@ bb2(%e : @owned $Error): // Just make sure we pass the verifiers. // // CHECK-LABEL: sil [ossa] @test_try_apply : $@convention(thin) (Builtin.Int32, @guaranteed Builtin.NativeObject) -> () { -// CHECK: try_apply {{%.*}}({{%.*}}) : $@convention(thin) (Builtin.Int32) -> @error Error, normal bb1, error bb2 -// CHECK: try_apply {{%.*}}({{%.*}}) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error Error, normal bb4, error bb5 +// CHECK: try_apply {{%.*}}({{%.*}}) : $@convention(thin) (Builtin.Int32) -> @error any Error, normal bb1, error bb2 +// CHECK: try_apply {{%.*}}({{%.*}}) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @error any Error, normal bb4, error bb5 // CHECK: } // end sil function 'test_try_apply' sil [ossa] @test_try_apply : $@convention(thin) (Builtin.Int32, @guaranteed Builtin.NativeObject) -> () { bb0(%0 : $Builtin.Int32, %1 : @guaranteed $Builtin.NativeObject): diff --git a/test/SILOptimizer/specialize_partial_apply.swift b/test/SILOptimizer/specialize_partial_apply.swift index 0a6e13a30cdd4..0e6ea909eb466 100644 --- a/test/SILOptimizer/specialize_partial_apply.swift +++ b/test/SILOptimizer/specialize_partial_apply.swift @@ -94,7 +94,7 @@ func testit3(_ b: Bool) -> Int { // CHECK-LABEL: sil shared [noinline] @$s4test25generic_get_func_throwingyxxKcSblFSi_Tg5 : // CHECK: [[F:%[0-9]+]] = function_ref @$s4test25generic_get_func_throwingyxxKcSblF0B0L_yxxKlFSi_TG5 : -// CHECK: [[PA:%[0-9]+]] = partial_apply [callee_guaranteed] [[F]](%0) : $@convention(thin) (@in_guaranteed Int, Bool) -> (@out Int, @error Error) +// CHECK: [[PA:%[0-9]+]] = partial_apply [callee_guaranteed] [[F]](%0) : $@convention(thin) (@in_guaranteed Int, Bool) -> (@out Int, @error any Error) // CHECK: [[CONV:%[0-9]+]] = convert_function [[PA]] // CHECK: return [[CONV]] : @inline(never) @@ -111,13 +111,13 @@ func generic_get_func_throwing(_ b: Bool) -> (T) throws -> T { return generic } -// CHECK-LABEL: sil hidden [noinline] @$s4test16testit1_throwingyS2iKcSbF : $@convention(thin) (Bool) -> @owned @callee_guaranteed (Int) -> (Int, @error Error) { +// CHECK-LABEL: sil hidden [noinline] @$s4test16testit1_throwingyS2iKcSbF : $@convention(thin) (Bool) -> @owned @callee_guaranteed (Int) -> (Int, @error any Error) { // CHECK: [[F:%[0-9]+]] = function_ref @$s4test25generic_get_func_throwingyxxKcSblFSi_Tg5 : // CHECK: [[CL:%[0-9]+]] = apply [[F]](%0) : // CHECK: [[CONV:%[0-9]+]] = convert_function [[CL]] // CHECK: [[TH:%[0-9]+]] = function_ref @$sS2is5Error_pIegnrzo_S2isAA_pIegydzo_TR : // CHECK: [[RET:%[0-9]+]] = partial_apply [callee_guaranteed] [[TH]]([[CONV]]) -// CHECK: return [[RET]] : $@callee_guaranteed (Int) -> (Int, @error Error) +// CHECK: return [[RET]] : $@callee_guaranteed (Int) -> (Int, @error any Error) @inline(never) func testit1_throwing(_ b: Bool) -> (Int) throws -> Int { return generic_get_func_throwing(b) @@ -135,10 +135,10 @@ func generic2_throwing(_ t1: T, b: Bool) throws -> T { // No reabstraction thunk is needed because the returned closure expects direct // args/result anyway. -// CHECK-LABEL: sil hidden [noinline] @$s4test26concrete_get_func_throwingS2i_SbtKcyF : $@convention(thin) () -> @owned @callee_guaranteed (Int, Bool) -> (Int, @error Error) { -// CHECK: [[F:%[0-9]+]] = function_ref @$s4test17generic2_throwing_1bxx_SbtKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error Error) -// CHECK: [[RET:%[0-9]+]] = thin_to_thick_function [[F]] : $@convention(thin) (Int, Bool) -> (Int, @error Error) to $@callee_guaranteed (Int, Bool) -> (Int, @error Error) -// CHECK: return [[RET]] : $@callee_guaranteed (Int, Bool) -> (Int, @error Error) +// CHECK-LABEL: sil hidden [noinline] @$s4test26concrete_get_func_throwingS2i_SbtKcyF : $@convention(thin) () -> @owned @callee_guaranteed (Int, Bool) -> (Int, @error any Error) { +// CHECK: [[F:%[0-9]+]] = function_ref @$s4test17generic2_throwing_1bxx_SbtKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error any Error) +// CHECK: [[RET:%[0-9]+]] = thin_to_thick_function [[F]] : $@convention(thin) (Int, Bool) -> (Int, @error any Error) to $@callee_guaranteed (Int, Bool) -> (Int, @error any Error) +// CHECK: return [[RET]] : $@callee_guaranteed (Int, Bool) -> (Int, @error any Error) @inline(never) func concrete_get_func_throwing() -> (Int, Bool) throws -> Int { return generic2_throwing @@ -162,8 +162,8 @@ func generic3_throwing(_ t1: T, _ b: Bool) throws -> T { // No reabstraction thunk is needed because we directly apply the returned closure. // CHECK-LABEL: sil hidden [noinline] @$s4test16testit3_throwingySiSbF : $@convention(thin) (Bool) -> Int { -// CHECK: [[F:%[0-9]+]] = function_ref @$s4test17generic3_throwingyxx_SbtKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error Error) -// CHECK: try_apply [[F]](%{{[0-9]+}}, %0) : $@convention(thin) (Int, Bool) -> (Int, @error Error), normal bb{{[0-9]+}}, error bb{{[0-9]+}} +// CHECK: [[F:%[0-9]+]] = function_ref @$s4test17generic3_throwingyxx_SbtKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error any Error) +// CHECK: try_apply [[F]](%{{[0-9]+}}, %0) : $@convention(thin) (Int, Bool) -> (Int, @error any Error), normal bb{{[0-9]+}}, error bb{{[0-9]+}} // CHECK: } @inline(never) func testit3_throwing(_ b: Bool) -> Int { @@ -183,16 +183,16 @@ func testit3_throwing(_ b: Bool) -> Int { // CHECK: store [[RET]] to %0 : $*Int // CHECK: return %{{[0-9]*}} : $() -// CHECK-LABEL: sil shared [transparent] [thunk] @$s4test25generic_get_func_throwingyxxKcSblF0B0L_yxxKlFSi_TG5 : $@convention(thin) (@in_guaranteed Int, Bool) -> (@out Int, @error Error) { +// CHECK-LABEL: sil shared [transparent] [thunk] @$s4test25generic_get_func_throwingyxxKcSblF0B0L_yxxKlFSi_TG5 : $@convention(thin) (@in_guaranteed Int, Bool) -> (@out Int, @error any Error) { // CHECK: bb0(%0 : $*Int, %1 : $*Int, %2 : $Bool): // CHECK: [[LD:%[0-9]+]] = load %1 : $*Int -// CHECK: [[F:%[0-9]+]] = function_ref @$s4test25generic_get_func_throwingyxxKcSblF0B0L_yxxKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error Error) -// CHECK: try_apply [[F]]([[LD]], %2) : $@convention(thin) (Int, Bool) -> (Int, @error Error), normal bb1, error bb2 +// CHECK: [[F:%[0-9]+]] = function_ref @$s4test25generic_get_func_throwingyxxKcSblF0B0L_yxxKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error any Error) +// CHECK: try_apply [[F]]([[LD]], %2) : $@convention(thin) (Int, Bool) -> (Int, @error any Error), normal bb1, error bb2 // CHECK: bb1([[NORMAL:%[0-9]+]] : $Int): // CHECK: store [[NORMAL]] to %0 : $*Int // CHECK: return %{{[0-9]*}} : $() -// CHECK: bb2([[ERROR:%[0-9]+]] : $Error): -// CHECK: throw [[ERROR]] : $Error +// CHECK: bb2([[ERROR:%[0-9]+]] : $any Error): +// CHECK: throw [[ERROR]] : $any Error // The main program. diff --git a/test/SILOptimizer/specialize_self_conforming.swift b/test/SILOptimizer/specialize_self_conforming.swift index 1ea49007dda71..40aea0ce9bbb3 100644 --- a/test/SILOptimizer/specialize_self_conforming.swift +++ b/test/SILOptimizer/specialize_self_conforming.swift @@ -15,9 +15,9 @@ func callsTakesP(_ t: T) { takesP(t) } -// CHECK-LABEL: sil hidden @$s26specialize_self_conforming16callsTakesPWithPyyAA1P_pF : $@convention(thin) (@guaranteed P) -> () { +// CHECK-LABEL: sil hidden @$s26specialize_self_conforming16callsTakesPWithPyyAA1P_pF : $@convention(thin) (@guaranteed any P) -> () { // CHECK: [[FN:%.*]] = function_ref @$s26specialize_self_conforming6takesPyyxAA1PRzlF : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> () -// CHECK: apply [[FN]]

(%0) : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : P> (@guaranteed Ï„_0_0) -> () +// CHECK: apply [[FN]](%0) : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : P> (@guaranteed Ï„_0_0) -> () // CHECK: return func callsTakesPWithP(_ p: P) { diff --git a/test/SILOptimizer/specialize_self_conforming_error.swift b/test/SILOptimizer/specialize_self_conforming_error.swift index 2c6bd1b091c3d..3273f0d5f4127 100644 --- a/test/SILOptimizer/specialize_self_conforming_error.swift +++ b/test/SILOptimizer/specialize_self_conforming_error.swift @@ -14,11 +14,11 @@ func callsTakesError(_ error: U) { takesError(error) } -// CHECK-LABEL: sil hidden @$s26specialize_self_conforming5test1yys5Error_pF : $@convention(thin) (@guaranteed Error) -> () { -// CHECK: [[TEMP:%.*]] = alloc_stack $Error +// CHECK-LABEL: sil hidden @$s26specialize_self_conforming5test1yys5Error_pF : $@convention(thin) (@guaranteed any Error) -> () { +// CHECK: [[TEMP:%.*]] = alloc_stack $any Error // CHECK: store %0 to [[TEMP]] // CHECK: [[FN:%.*]] = function_ref @$s26specialize_self_conforming10takesErroryyxs0E0RzlF : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : Error> (@in_guaranteed Ï„_0_0) -> () -// CHECK: apply [[FN]]([[TEMP]]) : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : Error> (@in_guaranteed Ï„_0_0) -> () +// CHECK: apply [[FN]]([[TEMP]]) : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : Error> (@in_guaranteed Ï„_0_0) -> () // CHECK: dealloc_stack [[TEMP]] // CHECK: return @@ -37,11 +37,11 @@ func callsTakesErrorWithError(_ error: Error, _ value : U) { takesError(error) } -// CHECK-LABEL: sil hidden @$s26specialize_self_conforming5test2yys5Error_pF : $@convention(thin) (@guaranteed Error) -> () { -// CHECK: [[TEMP:%.*]] = alloc_stack $Error +// CHECK-LABEL: sil hidden @$s26specialize_self_conforming5test2yys5Error_pF : $@convention(thin) (@guaranteed any Error) -> () { +// CHECK: [[TEMP:%.*]] = alloc_stack $any Error // CHECK: store %0 to [[TEMP]] // CHECK: [[FN:%.*]] = function_ref @$s26specialize_self_conforming10takesErroryyxs0E0RzlF : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : Error> (@in_guaranteed Ï„_0_0) -> () -// CHECK: apply [[FN]]([[TEMP]]) : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : Error> (@in_guaranteed Ï„_0_0) -> () +// CHECK: apply [[FN]]([[TEMP]]) : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : Error> (@in_guaranteed Ï„_0_0) -> () // CHECK: dealloc_stack [[TEMP]] // CHECK: return @@ -63,11 +63,11 @@ func callsTakesErrorAndValueWithError(_ error: Error, _ value : U) { takesErrorAndValue(error, value) } -// CHECK-LABEL: sil hidden @$s26specialize_self_conforming5test3yys5Error_pF : $@convention(thin) (@guaranteed Error) -> () { -// CHECK: [[TEMP:%.*]] = alloc_stack $Error +// CHECK-LABEL: sil hidden @$s26specialize_self_conforming5test3yys5Error_pF : $@convention(thin) (@guaranteed any Error) -> () { +// CHECK: [[TEMP:%.*]] = alloc_stack $any Error // CHECK: store %0 to [[TEMP]] // CHECK: [[FN:%.*]] = function_ref @$s26specialize_self_conforming18takesErrorAndValueyyx_q_ts0E0Rzr0_lF : $@convention(thin) <Ï„_0_0, Ï„_0_1 where Ï„_0_0 : Error> (@in_guaranteed Ï„_0_0, @in_guaranteed Ï„_0_1) -> () -// CHECK: apply [[FN]]([[TEMP]], {{%.*}}) : +// CHECK: apply [[FN]]([[TEMP]], {{%.*}}) : // CHECK: dealloc_stack [[TEMP]] // CHECK: return diff --git a/test/SILOptimizer/specialized_anyobject_conformance.swift b/test/SILOptimizer/specialized_anyobject_conformance.swift index b6bc31f1aa4ee..ddfbd8297a306 100644 --- a/test/SILOptimizer/specialized_anyobject_conformance.swift +++ b/test/SILOptimizer/specialized_anyobject_conformance.swift @@ -17,7 +17,7 @@ public func callee(_ t: C?, _ p: P) { p.use(t!) } -// CHECK-LABEL: sil @$s33specialized_anyobject_conformance7caller11pyAA1P_p_tF : $@convention(thin) (@in_guaranteed P) -> () { +// CHECK-LABEL: sil @$s33specialized_anyobject_conformance7caller11pyAA1P_p_tF : $@convention(thin) (@in_guaranteed any P) -> () { public func caller1(p: P) { callee(C(), p) } diff --git a/test/SILOptimizer/sr-5068.sil b/test/SILOptimizer/sr-5068.sil index b9f0844b62cab..955fa8276bacd 100644 --- a/test/SILOptimizer/sr-5068.sil +++ b/test/SILOptimizer/sr-5068.sil @@ -57,15 +57,15 @@ sil @GetRawPointer : $@convention(thin) () -> Builtin.RawPointer sil @GetOptionalModel : $@convention(method) (@in ReadonlyExternalFramework, @thin ModelDataService.Type) -> @owned Optional // CHECK-LABEL: sil hidden @BuggyFunction : $@convention(thin) () -> @owned Model { -// CHECK: [[ALLOC:%.*]] = alloc_stack $ReadonlyExternalFramework, let, name "ExternalFramework" -// CHECK-NEXT: [[INITE:%.*]] = init_existential_addr [[ALLOC]] : $*ReadonlyExternalFramework, $ExternalFramework -// CHECK: [[TALLOC1:%.*]] = alloc_stack $ReadonlyExternalFramework -// CHECK-NEXT: copy_addr [[ALLOC]] to [initialization] [[TALLOC1]] : $*ReadonlyExternalFramework -// CHECK-NEXT: apply {{%.*}}([[TALLOC1]], {{%.*}}) : $@convention(method) (@in ReadonlyExternalFramework, @thin ModelDataService.Type) -> @owned Optional -// CHECK: [[TALLOC2:%.*]] = alloc_stack $ReadonlyExternalFramework -// CHECK-NEXT: copy_addr [[ALLOC]] to [initialization] [[TALLOC2]] : $*ReadonlyExternalFramework +// CHECK: [[ALLOC:%.*]] = alloc_stack $any ReadonlyExternalFramework, let, name "ExternalFramework" +// CHECK-NEXT: [[INITE:%.*]] = init_existential_addr [[ALLOC]] : $*any ReadonlyExternalFramework, $ExternalFramework +// CHECK: [[TALLOC1:%.*]] = alloc_stack $any ReadonlyExternalFramework +// CHECK-NEXT: copy_addr [[ALLOC]] to [initialization] [[TALLOC1]] : $*any ReadonlyExternalFramework +// CHECK-NEXT: apply {{%.*}}([[TALLOC1]], {{%.*}}) : $@convention(method) (@in any ReadonlyExternalFramework, @thin ModelDataService.Type) -> @owned Optional +// CHECK: [[TALLOC2:%.*]] = alloc_stack $any ReadonlyExternalFramework +// CHECK-NEXT: copy_addr [[ALLOC]] to [initialization] [[TALLOC2]] : $*any ReadonlyExternalFramework // CHECK-NEXT: destroy_addr [[ALLOC]] -// CHECK: [[OEADDR:%.*]] = open_existential_addr immutable_access [[TALLOC2]] : $*ReadonlyExternalFramework +// CHECK: [[OEADDR:%.*]] = open_existential_addr immutable_access [[TALLOC2]] : $*any ReadonlyExternalFramework sil hidden @BuggyFunction : $@convention(thin) () -> @owned Model { bb0: %0 = alloc_stack $ReadonlyExternalFramework, let, name "ExternalFramework" // users: %1, %166, %72, %163, %71, %168, %10 diff --git a/test/SILOptimizer/stack-nesting-wrong-scope.swift b/test/SILOptimizer/stack-nesting-wrong-scope.swift index 82321b8a9c6f3..7886ef3b41ebd 100644 --- a/test/SILOptimizer/stack-nesting-wrong-scope.swift +++ b/test/SILOptimizer/stack-nesting-wrong-scope.swift @@ -3,9 +3,9 @@ // RUN: -sil-print-functions=$s3red19ThrowAddrOnlyStructV016throwsOptionalToG0ACyxGSgSi_tcfC \ // RUN: -Xllvm -sil-print-debuginfo -o %t -module-name red 2>&1 | %FileCheck %s -// CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : @owned $Error): +// CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : @owned $any Error): // CHECK: dealloc_stack %{{[0-9]+}} : $*ThrowAddrOnlyStruct, loc {{.*}}:26:68, scope 2 -// CHECK: br bb{{[0-9]+}}(%{{[0-9]+}} : $Error), loc {{.*}}:26:15, scope 2 +// CHECK: br bb{{[0-9]+}}(%{{[0-9]+}} : $any Error), loc {{.*}}:26:15, scope 2 protocol Patatino { init() diff --git a/test/SILOptimizer/stack_promotion.sil b/test/SILOptimizer/stack_promotion.sil index 9e0909fd6b1a4..0bebf5b6e5424 100644 --- a/test/SILOptimizer/stack_promotion.sil +++ b/test/SILOptimizer/stack_promotion.sil @@ -1110,12 +1110,12 @@ bb0(%0 : $XX): return %1 : $XX } -// CHECK-LABEL: sil @testUsedByTryApply : $@convention(thin) () -> (@owned XX, @error Error) { +// CHECK-LABEL: sil @testUsedByTryApply : $@convention(thin) () -> (@owned XX, @error any Error) { // CHECK: alloc_ref [stack] $XX // CHECK: try_apply // CHECK: bb1(%{{.*}} : $XX): // CHECK-NEXT: dealloc_stack_ref -// CHECK: bb2(%{{.*}}: $Error): +// CHECK: bb2(%{{.*}}: $any Error): // CHECK-NEXT: dealloc_stack_ref // CHECK-LABEL: } // end sil function 'testUsedByTryApply' sil @testUsedByTryApply : $@convention(thin) () -> (@owned XX, @error Error) { diff --git a/test/SILOptimizer/temp_rvalue_opt.sil b/test/SILOptimizer/temp_rvalue_opt.sil index 0df3b5a980a95..dccd70117695e 100644 --- a/test/SILOptimizer/temp_rvalue_opt.sil +++ b/test/SILOptimizer/temp_rvalue_opt.sil @@ -604,7 +604,7 @@ bb3: br bb2 } // CHECK-LABEL: sil @open_existential_addr_blocks_optimization : $@convention(thin) () -> () { -// CHECK: [[P:%.*]] = alloc_stack $P +// CHECK: [[P:%.*]] = alloc_stack $any P // CHECK: copy_addr {{.*}} to [initialization] [[P]] // CHECK: } sil @open_existential_addr_blocks_optimization : $@convention(thin) () -> () { @@ -638,7 +638,7 @@ bb3: } // CHECK-LABEL: sil @witness_method_blocks_optimization : $@convention(thin) () -> () { -// CHECK: [[P:%.*]] = alloc_stack $P +// CHECK: [[P:%.*]] = alloc_stack $any P // CHECK: copy_addr {{.*}} to [initialization] [[P]] // CHECK: } sil @witness_method_blocks_optimization : $@convention(thin) () -> () { diff --git a/test/SILOptimizer/temp_rvalue_opt_ossa.sil b/test/SILOptimizer/temp_rvalue_opt_ossa.sil index bdbffb100b131..34a5186ffd870 100644 --- a/test/SILOptimizer/temp_rvalue_opt_ossa.sil +++ b/test/SILOptimizer/temp_rvalue_opt_ossa.sil @@ -665,7 +665,7 @@ bb3: br bb2 } // CHECK-LABEL: sil [ossa] @open_existential_addr_blocks_optimization : $@convention(thin) () -> () { -// CHECK: [[P:%.*]] = alloc_stack $P +// CHECK: [[P:%.*]] = alloc_stack $any P // CHECK: copy_addr {{.*}} to [initialization] [[P]] // CHECK: } sil [ossa] @open_existential_addr_blocks_optimization : $@convention(thin) () -> () { @@ -699,7 +699,7 @@ bb3: } // CHECK-LABEL: sil [ossa] @witness_method_blocks_optimization : $@convention(thin) () -> () { -// CHECK: [[P:%.*]] = alloc_stack $P +// CHECK: [[P:%.*]] = alloc_stack $any P // CHECK: copy_addr {{.*}} to [initialization] [[P]] // CHECK: } sil [ossa] @witness_method_blocks_optimization : $@convention(thin) () -> () { diff --git a/test/SILOptimizer/templvalueopt.sil b/test/SILOptimizer/templvalueopt.sil index 42b6d63ed236a..8b9d409d47d37 100644 --- a/test/SILOptimizer/templvalueopt.sil +++ b/test/SILOptimizer/templvalueopt.sil @@ -49,7 +49,7 @@ struct ConformingStruct : Proto { } // CHECK-LABEL: sil @test_existential : -// CHECK: bb0(%0 : $*Proto, %1 : $*ConformingStruct): +// CHECK: bb0(%0 : $*any Proto, %1 : $*ConformingStruct): // CHECK-NEXT: [[E:%[0-9]+]] = init_existential_addr %0 // CHECK-NEXT: copy_addr [take] %1 to [initialization] [[E]] // CHECK-NOT: copy_addr @@ -162,8 +162,8 @@ struct StructWithEnum : Proto { } // CHECK-LABEL: sil @move_projections : -// CHECK: bb0(%0 : $*Proto, %1 : $*Any): -// CHECK-NEXT: [[S:%[0-9]+]] = init_existential_addr %0 : $*Proto, $StructWithEnum +// CHECK: bb0(%0 : $*any Proto, %1 : $*Any): +// CHECK-NEXT: [[S:%[0-9]+]] = init_existential_addr %0 : $*any Proto, $StructWithEnum // CHECK-NEXT: [[E:%[0-9]+]] = struct_element_addr [[S]] : $*StructWithEnum, #StructWithEnum.e // CHECK-NEXT: [[ENUMA:%[0-9]+]] = init_enum_data_addr [[E]] : $*Enum, #Enum.A!enumelt // CHECK-NEXT: [[OPTIONAL:%[0-9]+]] = init_enum_data_addr [[ENUMA]] : $*Optional, #Optional.some!enumelt diff --git a/test/SILOptimizer/templvalueopt_ossa.sil b/test/SILOptimizer/templvalueopt_ossa.sil index 3f4ef3f48bb2c..b4af1dd12acc2 100644 --- a/test/SILOptimizer/templvalueopt_ossa.sil +++ b/test/SILOptimizer/templvalueopt_ossa.sil @@ -49,7 +49,7 @@ struct ConformingStruct : Proto { } // CHECK-LABEL: sil [ossa] @test_existential : -// CHECK: bb0(%0 : $*Proto, %1 : $*ConformingStruct): +// CHECK: bb0(%0 : $*any Proto, %1 : $*ConformingStruct): // CHECK-NEXT: [[E:%[0-9]+]] = init_existential_addr %0 // CHECK-NEXT: copy_addr [take] %1 to [initialization] [[E]] // CHECK-NOT: copy_addr @@ -162,8 +162,8 @@ struct StructWithEnum : Proto { } // CHECK-LABEL: sil [ossa] @move_projections : -// CHECK: bb0(%0 : $*Proto, %1 : $*Any): -// CHECK-NEXT: [[S:%[0-9]+]] = init_existential_addr %0 : $*Proto, $StructWithEnum +// CHECK: bb0(%0 : $*any Proto, %1 : $*Any): +// CHECK-NEXT: [[S:%[0-9]+]] = init_existential_addr %0 : $*any Proto, $StructWithEnum // CHECK-NEXT: [[E:%[0-9]+]] = struct_element_addr [[S]] : $*StructWithEnum, #StructWithEnum.e // CHECK-NEXT: [[ENUMA:%[0-9]+]] = init_enum_data_addr [[E]] : $*Enum, #Enum.A!enumelt // CHECK-NEXT: [[OPTIONAL:%[0-9]+]] = init_enum_data_addr [[ENUMA]] : $*Optional, #Optional.some!enumelt diff --git a/test/SILOptimizer/throw_inline.swift b/test/SILOptimizer/throw_inline.swift index 0dff4d317849d..ea79a60049e65 100644 --- a/test/SILOptimizer/throw_inline.swift +++ b/test/SILOptimizer/throw_inline.swift @@ -8,7 +8,7 @@ public func foo() throws -> Int32 { } // CHECK-LABEL: $s12throw_inline3foos5Int32VyKF -// CHECK: debug_value undef : $Error, var, name "$error", argno 1 +// CHECK: debug_value undef : $any Error, var, name "$error", argno 1 // CHECK: %1 = integer_literal $Builtin.Int32, 999 // CHECK: %[[POS:.*]] = struct $Int32 (%1 : $Builtin.Int32) // CHECK: return %[[POS]] : $Int32 diff --git a/test/SILOptimizer/typed-access-tb-aa.sil b/test/SILOptimizer/typed-access-tb-aa.sil index 20e4a6ee6a73d..046554358557b 100644 --- a/test/SILOptimizer/typed-access-tb-aa.sil +++ b/test/SILOptimizer/typed-access-tb-aa.sil @@ -625,7 +625,7 @@ sil @enum_tests : $@convention(thin) () -> () { // CHECK-NEXT: MayAlias // CHECK: PAIR #82. // CHECK-NEXT: %3 = project_box %0 : $<Ï„_0_0> { var Ï„_0_0 } , 0 -// CHECK-NEXT: %16 = project_box %9 : $<Ï„_0_0> { var Ï„_0_0 } , 0 +// CHECK-NEXT: %16 = project_box %9 : $<Ï„_0_0> { var Ï„_0_0 } , 0 // CHECK-NEXT: MayAlias // CHECK: PAIR #83. // CHECK-NEXT: %3 = project_box %0 : $<Ï„_0_0> { var Ï„_0_0 } , 0 @@ -670,7 +670,7 @@ sil @enum_tests : $@convention(thin) () -> () { // CHECK-NEXT: NoAlias // CHECK: PAIR #102. // CHECK-NEXT: %4 = project_box %1 : $<Ï„_0_0> { var Ï„_0_0 } , 0 -// CHECK-NEXT: %16 = project_box %9 : $<Ï„_0_0> { var Ï„_0_0 } , 0 +// CHECK-NEXT: %16 = project_box %9 : $<Ï„_0_0> { var Ï„_0_0 } , 0 // CHECK-NEXT: MayAlias // CHECK: PAIR #103. // CHECK-NEXT: %4 = project_box %1 : $<Ï„_0_0> { var Ï„_0_0 } , 0 @@ -711,7 +711,7 @@ sil @enum_tests : $@convention(thin) () -> () { // CHECK-NEXT: MayAlias // CHECK: PAIR #121. // CHECK-NEXT: %5 = project_box %2 : $<Ï„_0_0> { var Ï„_0_0 } , 0 -// CHECK-NEXT: %16 = project_box %9 : $<Ï„_0_0> { var Ï„_0_0 } , 0 +// CHECK-NEXT: %16 = project_box %9 : $<Ï„_0_0> { var Ï„_0_0 } , 0 // CHECK-NEXT: MayAlias // CHECK: PAIR #122. // CHECK-NEXT: %5 = project_box %2 : $<Ï„_0_0> { var Ï„_0_0 } , 0 diff --git a/test/SILOptimizer/unexpected_error.sil b/test/SILOptimizer/unexpected_error.sil index 6196db463c3db..5fb2449778c13 100644 --- a/test/SILOptimizer/unexpected_error.sil +++ b/test/SILOptimizer/unexpected_error.sil @@ -1,7 +1,7 @@ // RUN: %target-sil-opt -enable-sil-verify-all -dce %s | %FileCheck %s import Swift -// CHECK-LABEL: sil @unexpected_error : $@convention(thin) (Error) -> () { +// CHECK-LABEL: sil @unexpected_error : $@convention(thin) (any Error) -> () { sil @unexpected_error : $@convention(thin) (Error) -> () { entry(%10 : $Error): // CHECK: builtin "unexpectedError" @@ -9,7 +9,7 @@ entry(%10 : $Error): unreachable } -// CHECK-LABEL: sil @error_in_main : $@convention(thin) (Error) -> () { +// CHECK-LABEL: sil @error_in_main : $@convention(thin) (any Error) -> () { sil @error_in_main : $@convention(thin) (Error) -> () { entry(%10 : $Error): // CHECK: builtin "errorInMain" diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil index 9d81fe31e9dfc..c3049498542a0 100644 --- a/test/Serialization/Inputs/def_basic.sil +++ b/test/Serialization/Inputs/def_basic.sil @@ -154,7 +154,7 @@ protocol P { func doIt() } -// CHECK-LABEL: @existentials : $@convention(thin) (@in P) -> () { +// CHECK-LABEL: @existentials : $@convention(thin) (@in any P) -> () { sil [transparent] [serialized] @existentials : $@convention(thin) (@in P) -> () { bb0(%0 : $*P): %1 = open_existential_addr mutable_access %0 : $*P to $*@opened("01234567-89ab-cdef-0123-000000000000", P) Self // CHECK: open_existential_addr mutable_access %0 @@ -165,12 +165,12 @@ bb0(%0 : $*P): // CHECK: witness_method ${{.*}}, #P.doIt %2 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", P) Self, #P.doIt, %1 : $*@opened("01234567-89ab-cdef-0123-000000000000", P) Self : $@convention(witness_method: P) (@inout T) -> () // Make sure we have the correct scope for generic parameters. - // CHECK: witness_method $@opened("{{.*}}", P) Self, #P.doIt + // CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.doIt %7 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", P) Self, #P.doIt, %1 : $*@opened("01234567-89ab-cdef-0123-000000000000", P) Self : $@convention(witness_method: P) (@inout T) -> () // CHECK: apply %3 = apply %2<@opened("01234567-89ab-cdef-0123-000000000000", P) Self>(%1) : $@convention(witness_method: P) (@inout T) -> () %4 = tuple () // CHECK: tuple () - destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*P + destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*any P return %4 : $() // CHECK: return } @@ -243,17 +243,17 @@ protocol Runcible { protocol Bendable { } -// CHECK-LABEL: $@convention(thin) (@in Bendable & Runcible) -> @out Runcible +// CHECK-LABEL: $@convention(thin) (@in any Bendable & Runcible) -> @out any Runcible sil [transparent] [serialized] @$s4todo18erasure_from_proto1xAA8Runcible_pAaD_AA8Bendablep_tF : $@convention(thin) (@in Bendable & Runcible) -> (@out Runcible) { bb0(%0 : $*Runcible, %1 : $*Bendable & Runcible): // CHECK: alloc_box %2 = alloc_box $<Ï„_0_0> { var Ï„_0_0 } <(Bendable & Runcible)> %2a = project_box %2 : $<Ï„_0_0> { var Ï„_0_0 } , 0 - // CHECK: copy_addr [take] {{.*}} to [initialization] {{.*}} : $*Bendable & Runcible + // CHECK: copy_addr [take] {{.*}} to [initialization] {{.*}} : $*any Bendable & Runcible copy_addr [take] %1 to [initialization] %2a : $*Bendable & Runcible // CHECK: alloc_stack %4 = alloc_stack $Bendable & Runcible - // CHECK: copy_addr {{.*}} to [initialization] {{.*}} : $*Bendable & Runcible + // CHECK: copy_addr {{.*}} to [initialization] {{.*}} : $*any Bendable & Runcible copy_addr %2a to [initialization] %4 : $*Bendable & Runcible %7 = tuple () // CHECK: destroy_addr @@ -269,7 +269,7 @@ protocol ClassBound : class { func classBoundMethod() } -// CHECK-LABEL: @$s4todo18class_bound_method1xyAA10ClassBound_p_tF : $@convention(thin) (@owned ClassBound) -> () +// CHECK-LABEL: @$s4todo18class_bound_method1xyAA10ClassBound_p_tF : $@convention(thin) (@owned any ClassBound) -> () sil [transparent] [serialized] @$s4todo18class_bound_method1xyAA10ClassBound_p_tF : $@convention(thin) (@owned ClassBound) -> () { bb0(%0 : $ClassBound): %1 = alloc_box $<Ï„_0_0> { var Ï„_0_0 } @@ -277,7 +277,7 @@ bb0(%0 : $ClassBound): store %0 to %1a : $*ClassBound %3 = load %1a : $*ClassBound strong_retain %3 : $ClassBound // CHECK: strong_retain - // CHECK: open_existential_ref {{%.*}} : $ClassBound to $@opened({{.*}}, ClassBound) Self + // CHECK: open_existential_ref {{%.*}} : $any ClassBound to $@opened({{.*}}, any ClassBound) Self %5 = open_existential_ref %3 : $ClassBound to $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self // CHECK: witness_method %6 = witness_method $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self, #ClassBound.classBoundMethod, %5 : $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self : $@convention(witness_method: ClassBound) (T) -> () @@ -367,7 +367,7 @@ bb0(%0 : $*Gimel): return %t : $() } -// CHECK-LABEL: @test_union_addr_data_case : $@convention(thin) (@in Q) -> @out Gimel { +// CHECK-LABEL: @test_union_addr_data_case : $@convention(thin) (@in any Q) -> @out Gimel { sil [transparent] [serialized] @test_union_addr_data_case : $@convention(thin) (@in Q) -> @out Gimel { bb0(%0 : $*Gimel, %1 : $*Q): // CHECK: {{%.*}} = init_enum_data_addr {{%.*}} : $*Gimel, #Gimel.DataCase!enumelt @@ -555,18 +555,18 @@ bb0(%0 : $SomeClass, %1 : $SomeSubclass): return %15 : $(@thick SomeClass.Type, @thick SomeClass.Type) } -// CHECK-LABEL: @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type { +// CHECK-LABEL: @test_existential_metatype : $@convention(thin) (@in any SomeProtocol) -> @thick any SomeProtocol.Type { sil [transparent] [serialized] @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type { bb0(%0 : $*SomeProtocol): %1 = alloc_box $<Ï„_0_0> { var Ï„_0_0 } %1a = project_box %1 : $<Ï„_0_0> { var Ï„_0_0 } , 0 - // CHECK: copy_addr [take] %0 to [initialization] %{{.*}} : $*SomeProtocol + // CHECK: copy_addr [take] %0 to [initialization] %{{.*}} : $*any SomeProtocol copy_addr [take] %0 to [initialization] %1a : $*SomeProtocol // CHECK: alloc_stack %4 = alloc_stack $SomeProtocol - // CHECK: copy_addr %{{.*}} to [initialization] %{{.*}} : $*SomeProtocol + // CHECK: copy_addr %{{.*}} to [initialization] %{{.*}} : $*any SomeProtocol copy_addr %1a to [initialization] %4 : $*SomeProtocol - // CHECK: existential_metatype $@thick SomeProtocol.Type, {{%.*}} : $*SomeProtocol + // CHECK: existential_metatype $@thick any SomeProtocol.Type, {{%.*}} : $*any SomeProtocol %6 = existential_metatype $@thick SomeProtocol.Type, %4 : $*SomeProtocol destroy_addr %4 : $*SomeProtocol dealloc_stack %4 : $*SomeProtocol @@ -854,15 +854,15 @@ class ConcreteClass : ClassP { struct Spoon : Bendable { } -// CHECK-LABEL: sil public_external [transparent] @test_init_existential : $@convention(thin) (Spoon) -> @out Bendable +// CHECK-LABEL: sil public_external [transparent] @test_init_existential : $@convention(thin) (Spoon) -> @out any Bendable sil [transparent] [serialized] @test_init_existential : $@convention(thin) (Spoon) -> @out Bendable { bb0(%0 : $*Bendable, %1 : $Spoon): %2 = alloc_box $<Ï„_0_0> { var Ï„_0_0 } %2a = project_box %2 : $<Ï„_0_0> { var Ï„_0_0 } , 0 store %1 to %2a : $*Spoon - // CHECK: init_existential_addr %{{.*}} : $*Bendable, $Spoon + // CHECK: init_existential_addr %{{.*}} : $*any Bendable, $Spoon %4 = init_existential_addr %0 : $*Bendable, $Spoon - // CHECK: deinit_existential_addr %{{.*}} : $*Bendable + // CHECK: deinit_existential_addr %{{.*}} : $*any Bendable deinit_existential_addr %0 : $*Bendable %5 = load %2a : $*Spoon store %5 to %4 : $*Spoon @@ -871,7 +871,7 @@ bb0(%0 : $*Bendable, %1 : $Spoon): return %8 : $() } -// CHECK-LABEL: sil public_external [transparent] @test_existential_ref : $@convention(thin) (ConcreteClass) -> ClassP +// CHECK-LABEL: sil public_external [transparent] @test_existential_ref : $@convention(thin) (ConcreteClass) -> any ClassP sil [transparent] [serialized] @test_existential_ref : $@convention(thin) (ConcreteClass) -> ClassP { bb0(%0 : $ConcreteClass): %1 = alloc_box $<Ï„_0_0> { var Ï„_0_0 } @@ -879,7 +879,7 @@ bb0(%0 : $ConcreteClass): store %0 to %1a : $*ConcreteClass %3 = load %1a : $*ConcreteClass strong_retain %3 : $ConcreteClass - // CHECK: init_existential_ref %{{.*}} : $ConcreteClass : $ConcreteClass, $ClassP + // CHECK: init_existential_ref %{{.*}} : $ConcreteClass : $ConcreteClass, $any ClassP %5 = init_existential_ref %3 : $ConcreteClass : $ConcreteClass, $ClassP strong_release %1 : $<Ï„_0_0> { var Ï„_0_0 } return %5 : $ClassP @@ -1123,10 +1123,10 @@ sil [transparent] [serialized] @block_invoke : $@convention(c) (@inout_aliasable // Test try_apply and throws // rdar://20925014 -// CHECK-LABEL: sil public_external [transparent] @test_try_apply : $@convention(thin) (@convention(thin) () -> @error Error) -> @error Error { +// CHECK-LABEL: sil public_external [transparent] @test_try_apply : $@convention(thin) (@convention(thin) () -> @error any Error) -> @error any Error { sil [transparent] [serialized] @test_try_apply : $@convention(thin) (@convention(thin) () -> @error Error) -> @error Error { bb0(%0 : $@convention(thin) () -> @error Error): - // CHECK: try_apply %0() : $@convention(thin) () -> @error Error, normal bb2, error bb1 + // CHECK: try_apply %0() : $@convention(thin) () -> @error any Error, normal bb2, error bb1 try_apply %0() : $@convention(thin) () -> @error Error, normal bb1, error bb2 bb1(%1 : $()): @@ -1138,10 +1138,10 @@ bb2(%3 : $Error): } // Test apply with the nothrow attribute -// CHECK-LABEL: sil public_external [transparent] @test_try_nothrow : $@convention(thin) (@convention(thin) () -> @error Error) -> () { +// CHECK-LABEL: sil public_external [transparent] @test_try_nothrow : $@convention(thin) (@convention(thin) () -> @error any Error) -> () { sil [transparent] [serialized] @test_try_nothrow : $@convention(thin) (@convention(thin) () -> @error Error) -> () { bb0(%0 : $@convention(thin) () -> @error Error): - // CHECK: apply [nothrow] %0() : $@convention(thin) () -> @error Error + // CHECK: apply [nothrow] %0() : $@convention(thin) () -> @error any Error apply [nothrow] %0() : $@convention(thin) () -> @error Error %2 = tuple () return %2 : $() @@ -1225,18 +1225,18 @@ struct SomeError: Error { // CHECK-LABEL: sil public_external [transparent] @existential_box : $@convention(thin) (SomeError) -> () { sil [transparent] [serialized] @existential_box : $@convention(thin) (SomeError) -> () { bb0(%0 : $SomeError): - // CHECK: %1 = alloc_existential_box $Error, $SomeError + // CHECK: %1 = alloc_existential_box $any Error, $SomeError %1 = alloc_existential_box $Error, $SomeError - // CHECK: %2 = project_existential_box $SomeError in %1 : $Error + // CHECK: %2 = project_existential_box $SomeError in %1 : $any Error %2 = project_existential_box $SomeError in %1 : $Error // CHECK: store %0 to %2 : $*SomeError store %0 to %2 : $*SomeError - // CHECK: %4 = open_existential_box %1 : $Error to $*[[OPENED:@opened\(".*", Error\) Self]] - %4 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self + // CHECK: %4 = open_existential_box %1 : $any Error to $*[[OPENED:@opened\(".*", any Error\) Self]] + %4 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", any Error) Self // CHECK: destroy_addr %4 : $*[[OPENED]] - destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self - // CHECK: dealloc_existential_box %1 : $Error, $SomeError - dealloc_existential_box %1 : $Error, $SomeError + destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", any Error) Self + // CHECK: dealloc_existential_box %1 : $any Error, $SomeError + dealloc_existential_box %1 : $any Error, $SomeError return undef : $() } diff --git a/test/Serialization/Inputs/def_basic_objc.sil b/test/Serialization/Inputs/def_basic_objc.sil index bc69c44781a6b..e5b1463e56f2d 100644 --- a/test/Serialization/Inputs/def_basic_objc.sil +++ b/test/Serialization/Inputs/def_basic_objc.sil @@ -33,7 +33,7 @@ protocol SomeClassProtocol : class {} // CHECK-LABEL: sil public_external [transparent] @metatype_to_object // CHECK: {{%.*}} = objc_metatype_to_object {{%.*}} : $@objc_metatype SomeClass.Type to $AnyObject -// CHECK: {{%.*}} = objc_existential_metatype_to_object {{%.*}} : $@objc_metatype SomeClassProtocol.Type to $AnyObject +// CHECK: {{%.*}} = objc_existential_metatype_to_object {{%.*}} : $@objc_metatype any SomeClassProtocol.Type to $AnyObject sil [transparent] [serialized] [ossa] @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject) { entry(%a : $@objc_metatype SomeClass.Type, %b : $@objc_metatype SomeClassProtocol.Type): %x = objc_metatype_to_object %a : $@objc_metatype SomeClass.Type to $AnyObject diff --git a/test/Serialization/function.swift b/test/Serialization/function.swift index a7e14fcf53555..c0ce0483a2415 100644 --- a/test/Serialization/function.swift +++ b/test/Serialization/function.swift @@ -113,8 +113,8 @@ do { try throws1() _ = try throws2(1) } catch _ {} -// SIL: sil @$s8def_func7throws1yyKF : $@convention(thin) () -> @error Error -// SIL: sil @$s8def_func7throws2{{[_0-9a-zA-Z]*}}F : $@convention(thin) <Ï„_0_0> (@in_guaranteed Ï„_0_0) -> (@out Ï„_0_0, @error Error) +// SIL: sil @$s8def_func7throws1yyKF : $@convention(thin) () -> @error any Error +// SIL: sil @$s8def_func7throws2{{[_0-9a-zA-Z]*}}F : $@convention(thin) <Ï„_0_0> (@in_guaranteed Ï„_0_0) -> (@out Ï„_0_0, @error any Error) // LLVM: } diff --git a/test/Serialization/objc.swift b/test/Serialization/objc.swift index 76c30cda1c024..8fae93b70977b 100644 --- a/test/Serialization/objc.swift +++ b/test/Serialization/objc.swift @@ -7,9 +7,9 @@ import def_objc -// SIL: sil hidden [ossa] @$s4objc9testProto3objy04def_A09ObjCProto_p_tF : $@convention(thin) (@guaranteed ObjCProto) -> () { +// SIL: sil hidden [ossa] @$s4objc9testProto3objy04def_A09ObjCProto_p_tF : $@convention(thin) (@guaranteed any ObjCProto) -> () { func testProto(obj obj: ObjCProto) { - // SIL: = objc_method {{%.*}} : $@opened({{.*}}, ObjCProto) Self, #ObjCProto.doSomething!foreign + // SIL: = objc_method {{%.*}} : $@opened({{.*}}, any ObjCProto) Self, #ObjCProto.doSomething!foreign obj.doSomething() } diff --git a/test/Serialization/transparent.swift b/test/Serialization/transparent.swift index 8342a0e6fe97a..d870178a6775b 100644 --- a/test/Serialization/transparent.swift +++ b/test/Serialization/transparent.swift @@ -70,7 +70,7 @@ func test_wrapper() { // SIL-LABEL: sil public_external [transparent] @$s15def_transparent17open_existentials1p2cpyAA1P_p_AA2CP_ptF func test_open_existentials(p: P, cp: CP) { - // SIL: open_existential_addr immutable_access [[EXIST:%[0-9]+]] : $*P to $*@opened([[N:".*"]], P) Self - // SIL: open_existential_ref [[EXIST:%[0-9]+]] : $CP to $@opened([[M:".*"]], CP) Self + // SIL: open_existential_addr immutable_access [[EXIST:%[0-9]+]] : $*any P to $*@opened([[N:".*"]], any P) Self + // SIL: open_existential_ref [[EXIST:%[0-9]+]] : $any CP to $@opened([[M:".*"]], any CP) Self open_existentials(p: p, cp: cp) } diff --git a/test/TypeDecoder/lowered_function_types.swift b/test/TypeDecoder/lowered_function_types.swift index ce50b653b10ce..3b12352f0f9b9 100644 --- a/test/TypeDecoder/lowered_function_types.swift +++ b/test/TypeDecoder/lowered_function_types.swift @@ -26,4 +26,4 @@ do { // CHECK: @callee_guaranteed (Int, @guaranteed Class, @owned Class, @in_guaranteed Any, @inout Int) -> (Int, @owned Class, @out Any) // CHECK: @callee_guaranteed () -> @error Error -// CHECK: @callee_guaranteed (@in_constant Int) -> @owned Int \ No newline at end of file +// CHECK: @callee_guaranteed (@in_constant Int) -> @owned Int diff --git a/test/TypeDecoder/lowered_metatypes.swift b/test/TypeDecoder/lowered_metatypes.swift index fb6582d0ff109..04c01d03a61ed 100644 --- a/test/TypeDecoder/lowered_metatypes.swift +++ b/test/TypeDecoder/lowered_metatypes.swift @@ -20,4 +20,4 @@ protocol Proto {} // DEMANGLE: $s17lowered_metatypes5ProtoPXmo // CHECK: @thick Proto.Type -// CHECK: @objc_metatype Proto.Type \ No newline at end of file +// CHECK: @objc_metatype Proto.Type diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift index 0a440a517abc1..4dca66fd925cc 100644 --- a/test/attr/attr_objc.swift +++ b/test/attr/attr_objc.swift @@ -1399,10 +1399,10 @@ class infer_instanceVar1 { weak var var_Weak7: Protocol_ObjC1? weak var var_Weak8: (Protocol_ObjC1 & Protocol_ObjC2)? -// CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak1: @sil_weak Class_ObjC1 -// CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak2: @sil_weak Protocol_ObjC1 -// CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak5: @sil_weak AnyObject -// CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak7: @sil_weak Protocol_ObjC1 +// CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak1: @sil_weak Class_ObjC1? +// CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak2: @sil_weak Protocol_ObjC1? +// CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak5: @sil_weak AnyObject? +// CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak7: @sil_weak Protocol_ObjC1? // CHECK-LABEL: @objc @_hasInitialValue weak var var_Weak8: @sil_weak (Protocol_ObjC1 & Protocol_ObjC2)? weak var var_Weak_fail1: PlainClass? diff --git a/test/decl/protocol/special/coding/class_codable_inherited.swift b/test/decl/protocol/special/coding/class_codable_inherited.swift index 44312bef59a8c..b55616ba92531 100644 --- a/test/decl/protocol/special/coding/class_codable_inherited.swift +++ b/test/decl/protocol/special/coding/class_codable_inherited.swift @@ -14,10 +14,10 @@ func sr8083(decoder: Decoder) throws { // CHECK-LABEL: sil_vtable SR8083_Base { // CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> () -> SR8083_Base : @$s23class_codable_inherited11SR8083_BaseCACycfC -// CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> (Decoder) throws -> SR8083_Base : @$s23class_codable_inherited11SR8083_BaseC4fromACs7Decoder_p_tKcfC +// CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> (any Decoder) throws -> SR8083_Base : @$s23class_codable_inherited11SR8083_BaseC4fromACs7Decoder_p_tKcfC // CHECK: {{^}$}} // CHECK-LABEL: sil_vtable SR8083_Sub { // CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> () -> SR8083_Base : @$s23class_codable_inherited10SR8083_SubCACycfC [override] -// CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> (Decoder) throws -> SR8083_Base : @$s23class_codable_inherited10SR8083_SubC4fromACs7Decoder_p_tKcfC [override] // SR8083_Sub.__allocating_init(from:) +// CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> (any Decoder) throws -> SR8083_Base : @$s23class_codable_inherited10SR8083_SubC4fromACs7Decoder_p_tKcfC [override] // SR8083_Sub.__allocating_init(from:) // CHECK: {{^}$}} diff --git a/test/stdlib/unmanaged_rc.swift b/test/stdlib/unmanaged_rc.swift index 711032b233361..c937c18c6b228 100644 --- a/test/stdlib/unmanaged_rc.swift +++ b/test/stdlib/unmanaged_rc.swift @@ -16,11 +16,11 @@ public func myPrint(_ k: Klass) { print(k) } // Check the codegen of _withUnsafeGuaranteedRef // -// CHECK-LABEL: sil public_external [transparent] @$ss9UnmanagedV24_withUnsafeGuaranteedRefyqd__qd__xKXEKlF : $@convention(method) (@noescape @callee_guaranteed @substituted <Ï„_0_0, Ï„_0_1 where Ï„_0_0 : AnyObject> (@guaranteed Ï„_0_0) -> (@out Ï„_0_1, @error Error) for , Unmanaged) -> (@out Result, @error Error) { -// CHECK: bb0([[RESULT:%.*]] : $*Result, [[FUNC:%.*]] : $@noescape @callee_guaranteed @substituted <Ï„_0_0, Ï„_0_1 where Ï„_0_0 : AnyObject> (@guaranteed Ï„_0_0) -> (@out Ï„_0_1, @error Error) for , [[UNMANAGED:%.*]] : $Unmanaged): +// CHECK-LABEL: sil public_external [transparent] @$ss9UnmanagedV24_withUnsafeGuaranteedRefyqd__qd__xKXEKlF : $@convention(method) (@noescape @callee_guaranteed @substituted <Ï„_0_0, Ï„_0_1 where Ï„_0_0 : AnyObject> (@guaranteed Ï„_0_0) -> (@out Ï„_0_1, @error any Error) for , Unmanaged) -> (@out Result, @error any Error) { +// CHECK: bb0([[RESULT:%.*]] : $*Result, [[FUNC:%.*]] : $@noescape @callee_guaranteed @substituted <Ï„_0_0, Ï„_0_1 where Ï„_0_0 : AnyObject> (@guaranteed Ï„_0_0) -> (@out Ï„_0_1, @error any Error) for , [[UNMANAGED:%.*]] : $Unmanaged): // CHECK: [[UNMANAGED_REF:%.*]] = struct_extract [[UNMANAGED]] // CHECK: [[REF:%.*]] = unmanaged_to_ref [[UNMANAGED_REF]] -// CHECK: try_apply {{%.*}}([[RESULT]], [[REF]]) : $@noescape @callee_guaranteed @substituted <Ï„_0_0, Ï„_0_1 where Ï„_0_0 : AnyObject> (@guaranteed Ï„_0_0) -> (@out Ï„_0_1, @error Error) for , normal bb2, error bb1 +// CHECK: try_apply {{%.*}}([[RESULT]], [[REF]]) : $@noescape @callee_guaranteed @substituted <Ï„_0_0, Ï„_0_1 where Ï„_0_0 : AnyObject> (@guaranteed Ï„_0_0) -> (@out Ï„_0_1, @error any Error) for , normal bb2, error bb1 // CHECK-NOT: destroy_value // CHECK: } // end sil function '$ss9UnmanagedV24_withUnsafeGuaranteedRefyqd__qd__xKXEKlF' From 968a64eb8b40b448665ec37d703b7cf78a97ed6f Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 18 Aug 2022 17:04:11 +0900 Subject: [PATCH 183/491] Apply suggestions from code review Co-authored-by: Yim Lee --- .../public/Distributed/DistributedActor.swift | 44 ++++++++--------- .../Distributed/DistributedActorSystem.swift | 48 +++++++++---------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/stdlib/public/Distributed/DistributedActor.swift b/stdlib/public/Distributed/DistributedActor.swift index f8fd243be0ca9..060fefdc99ccd 100644 --- a/stdlib/public/Distributed/DistributedActor.swift +++ b/stdlib/public/Distributed/DistributedActor.swift @@ -25,7 +25,7 @@ import _Concurrency /// It is not possible to conform to this protocol manually by any other type /// than a `distributed actor`. /// -/// It is possible to require a type conform to the +/// It is possible to require a type to conform to the /// ``DistributedActor`` protocol by refining it with another protocol, /// or by using a generic constraint. /// @@ -38,7 +38,7 @@ import _Concurrency /// - the ``SerializationRequirement`` that will be used at compile time to /// verify `distributed` target declarations are well formed, /// - if the distributed actor is `Codable`, based on the ``ID`` being Codable or not, -/// - the type of the `ActorSystem` accepted in the synthesized default initializer. +/// - the type of the ``ActorSystem`` accepted in the synthesized default initializer. /// /// A distributed actor must declare what type of actor system it is ready to /// work with by fulfilling the ``ActorSystem`` type member requirement: @@ -54,7 +54,7 @@ import _Concurrency /// ### The DefaultDistributedActorSystem type alias /// Since it is fairly common to only be using one specific type of actor system /// within a module or entire codebase, it is possible to declare the default type -/// or actor system all distributed actors will be using in a module by declaring +/// of actor system all distributed actors will be using in a module by declaring /// a `DefaultDistributedActorSystem` module wide typealias: /// /// ```swift @@ -66,8 +66,8 @@ import _Concurrency /// distributed actor Greeter {} // ActorSystem == AmazingActorSystem /// ``` /// -/// This declaration makes all `distributed actor` declarations, -/// which do not explicitly specify an ``ActorSystem`` typealias, to assume the +/// This declaration makes all `distributed actor` declarations +/// that do not explicitly specify an ``ActorSystem`` type alias to assume the /// `AmazingActorSystem` as their `ActorSystem`. /// /// It is possible for a specific actor to override the system it is using, @@ -95,8 +95,8 @@ import _Concurrency /// /// The accepted actor system must be of the `Self.ActorSystem` type, which /// must conform to the ``DistributedActorSystem`` protocol. This is required -/// because of how distributed actors are always managed by, a concrete -/// distributed actor system, and cannot exist on their own without one. +/// because distributed actors are always managed by a concrete +/// distributed actor system and cannot exist on their own without one. /// /// It is possible to explicitly declare an parameter-free initializer (`init()`), /// however the `actorSystem` property still must be assigned a concrete actor @@ -105,7 +105,7 @@ import _Concurrency /// In general it is recommended to always have an `actorSystem` parameter as /// the last non-defaulted non-closure parameter in every distributed actors /// initializer parameter list. This way it is simple to swap in a "test actor -// system" instance in unit tests, and avoid relying on global state which could +/// system" instance in unit tests, and avoid relying on global state which could /// make testing more difficult. /// /// ## Implicit properties @@ -114,7 +114,7 @@ import _Concurrency /// /// ### Property: Actor System /// The ``actorSystem`` property is an important part of every distributed actor's lifecycle management. -/// Initialization as well as de-initialization both require interactions with the actor system, +/// Both initialization as well as de-initialization require interactions with the actor system, /// and it is the actor system that delivers /// /// @@ -131,23 +131,23 @@ import _Concurrency /// ``` /// /// ### Property: Distributed Actor Identity -/// The ``id`` is assigned by the actor system during the distributed actor's +/// ``id`` is assigned by the actor system during the distributed actor's /// initialization, and cannot be set or mutated by the actor itself. /// -/// The ``id`` is the effective identity of the actor, and is used in equality checks. +/// ``id`` is the effective identity of the actor, and is used in equality checks. /// /// ## Automatic Conformances /// /// ### Hashable and Identifiable conformance -/// Every distributed actor conforms to the Hashable and Identifiable protocols. -/// Its identity is strictly driven by its `id`, and therefore hash and equality -/// implementations directly delegate to the `id` property. +/// Every distributed actor conforms to the `Hashable` and `Identifiable` protocols. +/// Its identity is strictly driven by its ``id``, and therefore hash and equality +/// implementations directly delegate to the ``id`` property. /// /// Comparing a local distributed actor instance and a remote reference to it /// (both using the same ``id``) always returns true, as they both conceptually /// point at the same distributed actor. /// -/// It is not possible to implement those protocols relying on the actual actor's +/// It is not possible to implement these protocols relying on the actual actor's /// state, because it may be remote and the state may not be available. In other /// words, since these protocols must be implemented using `nonisolated` functions, /// only `nonisolated` `id` and `actorSystem` properties are accessible for their @@ -225,12 +225,12 @@ public protocol DistributedActor: AnyActor, Identifiable, Hashable @available(SwiftStdlib 5.7, *) extension DistributedActor { - /// A distributed actor's hash and equality is implemented by directly delegating to it's ``id``. + /// A distributed actor's hash and equality is implemented by directly delegating to its ``id``. nonisolated public func hash(into hasher: inout Hasher) { self.id.hash(into: &hasher) } - /// A distributed actor's hash and equality is implemented by directly delegating to it's ``id``. + /// A distributed actor's hash and equality is implemented by directly delegating to its ``id``. nonisolated public static func ==(lhs: Self, rhs: Self) -> Bool { lhs.id == rhs.id } @@ -244,8 +244,8 @@ extension CodingUserInfoKey { /// to `init(from:)` a `DistributedActor`. The stored value under this key must /// conform to ``DistributedActorSystem``. /// - /// Missing to set this key will result in that initializer throwing, because - /// an actor system is required + /// Forgetting to set this key will result in that initializer throwing, because + /// an actor system is required. @available(SwiftStdlib 5.7, *) public static let actorSystemKey = CodingUserInfoKey(rawValue: "$distributed_actor_system")! } @@ -254,14 +254,14 @@ extension CodingUserInfoKey { extension DistributedActor /*: implicitly Decodable */ where Self.ID: Decodable { /// Initializes an instance of this distributed actor by decoding its ``id``, - /// and passing it to the ``DistributedActorSystem`` obtained from `decoder.userInfo[`actorSystemKey]`. + /// and passing it to the ``DistributedActorSystem`` obtained from `decoder.userInfo[actorSystemKey]`. /// /// ## Requires: The decoder must have the ``CodingUserInfoKey/actorSystemKey`` set to /// the ``ActorSystem`` that this actor expects, as it will be used to call ``DistributedActor/resolve(id:using:)`` /// on, in order to obtain the instance this initializer should return. /// /// - Parameter decoder: used to decode the ``ID`` of this distributed actor. - /// - Throws: If the actor system value in `decoder.userInfo` is missing, or mis-typed; + /// - Throws: If the actor system value in `decoder.userInfo` is missing or mis-typed; /// the `ID` fails to decode from the passed `decoder`; // or if the ``DistributedActor/resolve(id:using:)`` method invoked by this initializer throws. nonisolated public init(from decoder: Decoder) throws { @@ -279,7 +279,7 @@ extension DistributedActor /*: implicitly Decodable */ where Self.ID: Decodable @available(SwiftStdlib 5.7, *) extension DistributedActor /*: implicitly Encodable */ where Self.ID: Encodable { - /// Encodes the ``actor.id`` as a single value into the passed `encoder`. + /// Encodes the `actor.id` as a single value into the passed `encoder`. nonisolated public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(self.id) diff --git a/stdlib/public/Distributed/DistributedActorSystem.swift b/stdlib/public/Distributed/DistributedActorSystem.swift index 92742378fa781..4b583e4889399 100644 --- a/stdlib/public/Distributed/DistributedActorSystem.swift +++ b/stdlib/public/Distributed/DistributedActorSystem.swift @@ -15,7 +15,7 @@ import _Concurrency /// A distributed actor system underpins and implements all functionality of distributed actors. /// /// A ``DistributedActor`` is always initialized in association with some concrete actor system. -/// And that actor system instance is then used to manage the identity of the actor, as well as +/// That actor system instance is then used to manage the identity of the actor, as well as /// handle all remote interactions of the distributed actor. /// /// ## Using a DistributedActorSystem library @@ -28,7 +28,7 @@ import _Concurrency /// `typealias DefaultDistributedActorSystem`. Refer to the ``DistributedActor`` documentation to learn more /// about the tradeoffs of these approaches. /// -/// Once an actor has declared the system it is able to work with, such system instance must provided +/// Once an actor has declared the system it is able to work with, an instance of the system must be provided /// at initialization time, in order for the system to be able to take over the actor's identity management. /// /// For example, a simple distributed actor may look like this: @@ -45,11 +45,11 @@ import _Concurrency /// This property is later used for identity management and other remote interactions of the actor. /// For more details refer to ``DistributedActor`` which explains more about declaring distributed actors. /// -/// For more details about how the specific actor system implementation deals with remote message transports, +/// For more details about how the specific actor system implementation deals with remote message transports /// and serialization, please refer to the specific system's documentation. /// /// > Note: For example, you may refer to the [Swift Distributed Actors cluster library](https://github.com/apple/swift-distributed-actors/) documentation, -/// > which is one example of such feature complete distributed actor system implementation: +/// > which is one example of such feature complete distributed actor system implementation. /// /// ## Implementing a DistributedActorSystem /// @@ -99,9 +99,9 @@ import _Concurrency /// /// > Tip: Take note that throwing or failable initializers complicate this somewhat. Thankfully, the compiler /// > will always emit the right code such that every ``assignID(_:)`` is balanced with a ``resignID(_:)`` call, -/// > when the actor either failed to initialize, or deinitialized property. +/// > when the actor either failed to initialize or deinitialize properly. /// > -/// > It is also possible that a throwing initializer throws before assigning the actorSystem, and id properties. +/// > It is also possible that a throwing initializer throws before assigning the `actorSystem` and `id` properties. /// > In such case, no `assignID` nor `resignID` calls are made. There is no risk of the compiler ever attempting /// > to call a `resignID(_:)` without first having assigned given ID. /// @@ -141,18 +141,18 @@ import _Concurrency /// > Note: Generally actor systems should retain actors _weakly_ in order to allow them be deinitialized when no longer in use. /// > /// > Sometimes though, it can be quite useful to have the system retain certain "well known" actors, for example when it is expected -/// > that other nodes in the distributed system will need to interact with them, even if end-user code does no longer hold +/// > that other nodes in the distributed system will need to interact with them, even if end-user code no longer holds /// > strong references to them. An example of such "retain while actor system is active" distributed actors would be any kind /// > of actor which implements discovery or health check mechanisms between clustered nodes, sometimes called "system actors", -/// i.e. actors that serve the actor system directly. +/// > i.e. actors that serve the actor system directly. /// -/// Next, we will discuss the the just mentioned resolve method, which is closely tied to readying actors. +/// Next, we will discuss the just mentioned `resolve` method, which is closely tied to readying actors. /// /// ### Resolving (potentially remote) Distributed Actors /// /// An important functionality of any distributed actor system is being able to turn a ``DistributedActor`` type and ``ActorID`` -/// into an reference to such actor, regardless where the actor is located. The ID should have enough information stored -/// to be able to make the decision _where_ the actor is located, without having to contact remote nodes. Specifically, +/// into a reference to such actor, regardless where the actor is located. The ID should have enough information stored +/// to be able to make the decision of _where_ the actor is located, without having to contact remote nodes. Specifically, /// the implementation of ``DistributedActorSystem/resolve(id:as:)`` is _not_ `async` and should _not_ perform long running /// or blocking operations in order to return. /// @@ -172,11 +172,11 @@ import _Concurrency /// `remoteCall(on:target:invocation:returning:throwing:)` (or `remoteCallVoid(on:target:invocation:throwing:)` for Void returning methods). /// /// Implementing the remote calls correctly and efficiently is one of the most important tasks for a distributed actor system library. -/// Since those methods are not currently expressible as protocol requirements Swift, and therefore will not appear in -/// the protocol's documentation as explicit requirements, due to their advanced use of generics, we present their -/// signatures that a conforming type one has to implement here: +/// Since those methods are not currently expressible as protocol requirements in Swift due to their advanced use +/// of generics, and therefore will not appear in the protocol's documentation as explicit requirements, we present +/// their signatures that a conforming type has to implement here: /// -/// > Note: Although the the `remoteCall` methods are not expressed as protocol requirements in source, +/// > Note: Although the `remoteCall` methods are not expressed as protocol requirements in source, /// > the compiler will provide the same errors as-if they were declared explicitly in this protocol. /// /// ```swift @@ -225,19 +225,19 @@ import _Concurrency /// Err: Error /// ``` /// -/// Implementations of remote calls generally will serialize the `actor.id`, `target` and `invocation` +/// Implementations of remote calls generally will serialize `actor.id`, `target` and `invocation` /// into some form of wire envelope, and send it over the network (or process boundary) using some -/// transport mechanism of their choice. As they do so, they need to suspend the remoteCall function, -/// and resume it once a reply to the call arrives; Unless the transport layer is also async/await aware, +/// transport mechanism of their choice. As they do so, they need to suspend the `remoteCall` function, +/// and resume it once a reply to the call arrives. Unless the transport layer is also async/await aware, /// this will often require making use of a ``CheckedContinuation``. /// /// While implementing remote calls please keep in mind any potential failure scenarios that may occur, -/// such as message loss, connection failures and similar issues. Such situations should all should be -/// surfaced by resuming the remoteCall by throwing an error conforming to ``DistributedActorSystemError``. +/// such as message loss, connection failures and similar issues. Such situations should all be +/// surfaced by resuming the `remoteCall` by throwing an error conforming to ``DistributedActorSystemError``. /// /// While it is not _required_ to conform error thrown out of these methods to ``DistributedActorSystemError``, /// the general guideline about conforming errors to this protocol is that errors which are outside of the user's control, -/// but are thrown because transport or actor system issues happening, should conform to it. This is to simplify +/// but are thrown because transport or actor system issues, should conform to it. This is to simplify /// separating "business logic errors" from transport errors. /// /// @@ -253,9 +253,9 @@ public protocol DistributedActorSystem: Sendable { /// The type ID that will be assigned to any distributed actor managed by this actor system. /// /// ### A note on Codable IDs - /// If this type is Codable, then any `distributed actor` using this `ActorID` as its ``DistributedActor/ID``, + /// If this type is ``Codable``, then any `distributed actor` using this `ActorID` as its ``DistributedActor/ID`` /// will gain a synthesized ``Codable`` conformance which is implemented by encoding the `ID`. - /// The decoding counter part of the Codable conformance is implemented by decoding the `ID` and passing it to + /// The decoding counter part of the ``Codable`` conformance is implemented by decoding the `ID` and passing it to // the ``DistributedActor/resolve(id:using:)`` method. associatedtype ActorID: Sendable & Hashable @@ -823,7 +823,7 @@ public struct ExecuteDistributedTargetError: DistributedActorSystemError { /// Error thrown by distributed actor systems while encountering encoding/decoding /// issues. /// -/// Also thrown when attempt to decode ``DistributedActor`` is made, +/// Also thrown when an attempt to decode ``DistributedActor`` is made, /// but no ``DistributedActorSystem`` is available in the `Decoder`'s /// `userInfo[.actorSystemKey]`, as it is required to perform the resolve call. @available(SwiftStdlib 5.7, *) From 49ae51c37c72689e1c0afe1d439d954b74e0f4d3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 18 Aug 2022 17:49:17 +0900 Subject: [PATCH 184/491] small cleanups --- .../public/Distributed/DistributedActor.swift | 109 +++++++++++++----- .../Distributed/DistributedActorSystem.swift | 20 ++-- 2 files changed, 90 insertions(+), 39 deletions(-) diff --git a/stdlib/public/Distributed/DistributedActor.swift b/stdlib/public/Distributed/DistributedActor.swift index 060fefdc99ccd..10e0e5e6b6752 100644 --- a/stdlib/public/Distributed/DistributedActor.swift +++ b/stdlib/public/Distributed/DistributedActor.swift @@ -15,23 +15,28 @@ import _Concurrency // ==== Distributed Actor ----------------------------------------------------- - - /// Common protocol to which all distributed actors conform implicitly. /// /// The `DistributedActor` protocol generalizes over all distributed actor types. /// Distributed actor types implicitly conform to this protocol. /// -/// It is not possible to conform to this protocol manually by any other type -/// than a `distributed actor`. +/// It is not possible to conform to this protocol by any other declaration other than a `distributed actor`. /// /// It is possible to require a type to conform to the /// ``DistributedActor`` protocol by refining it with another protocol, /// or by using a generic constraint. /// +/// ## Synthesized properties +/// For every concrete distributed actor declaration, the compiler synthesizes two properties: `actorSystem` and `id`. +/// They witness the ``actorSystem`` and ``id`` protocol requirements of the ``DistributedActor`` protocol. +/// +/// It is not possible to implement these properties explicitly in user code. +/// These properties are `nonisolated` and accessible even if the instance is _remote_, +/// because _all_ distributed actor references must store the actor system remote calls +/// will be delivered through, as well as the id identifying the target of those calls. /// /// ## The ActorSystem associated type -/// Every distributed actor must declare what type of distributed actor system +/// Every distributed actor must declare what type of actor system /// it is part of by implementing the ``ActorSystem`` associated type requirement. /// /// This causes a number of other properties of the actor to be inferred: @@ -98,12 +103,12 @@ import _Concurrency /// because distributed actors are always managed by a concrete /// distributed actor system and cannot exist on their own without one. /// -/// It is possible to explicitly declare an parameter-free initializer (`init()`), +/// It is possible to explicitly declare a parameter-free initializer (`init()`), /// however the `actorSystem` property still must be assigned a concrete actor /// system instance the actor shall be part of. /// /// In general it is recommended to always have an `actorSystem` parameter as -/// the last non-defaulted non-closure parameter in every distributed actors +/// the last non-defaulted non-closure parameter in every actor's /// initializer parameter list. This way it is simple to swap in a "test actor /// system" instance in unit tests, and avoid relying on global state which could /// make testing more difficult. @@ -114,9 +119,10 @@ import _Concurrency /// /// ### Property: Actor System /// The ``actorSystem`` property is an important part of every distributed actor's lifecycle management. -/// Both initialization as well as de-initialization require interactions with the actor system, -/// and it is the actor system that delivers /// +/// Both initialization as well as de-initialization require interactions with the actor system, +/// and it is the actor system that handles all remote interactions of an actor, by both sending +/// or receiving remote calls made on the actor. /// /// The ``actorSystem`` property must be assigned in every designated initializer /// of a distributed actor explicitly. It is highly recommended to make it a @@ -130,11 +136,23 @@ import _Concurrency /// } /// ``` /// +/// Forgetting to initialize the actor system, will result in a compile time error: +/// +/// ```swift +/// // BAD +/// init(name: String, actorSystem: Self.ActorSystem) { +/// self.name = name +/// // BAD, will cause compile-time error; the `actorSystem` was not initialized. +/// } +/// ``` +/// /// ### Property: Distributed Actor Identity /// ``id`` is assigned by the actor system during the distributed actor's /// initialization, and cannot be set or mutated by the actor itself. /// -/// ``id`` is the effective identity of the actor, and is used in equality checks. +/// ``id`` is the effective identity of the actor, and is used in equality checks, +/// as well as the actor's synthesized ``Codable`` conformance if the ``ID`` type +/// conforms to ``Codable``. /// /// ## Automatic Conformances /// @@ -153,22 +171,26 @@ import _Concurrency /// only `nonisolated` `id` and `actorSystem` properties are accessible for their /// implementations. /// -/// ### Implicit `Codable` conformance -/// If created with an actor system whose `ActorID` is `Codable`, the +/// ### Implicit Codable conformance +/// If created with an actor system whose ``DistributedActorSystem/ActorID`` is ``Codable``, the /// compiler will synthesize code for the concrete distributed actor to conform -/// to `Codable` as well. +/// to ``Codable`` as well. /// /// This is necessary to support distributed calls where the `SerializationRequirement` -/// is `Codable` and thus users may want to pass actors as arguments to remote calls. +/// is ``Codable`` and thus users may want to pass actors as arguments to remote calls. /// -/// The synthesized implementations use a single `SingleValueContainer` to -/// encode/decode the `self.id` property of the actor. The `Decoder` required -/// `init(from:)` is implemented by retrieving an actor system from the -/// decoders' `userInfo`, effectively like this: -/// `decoder.userInfo[.actorSystemKey] as? ActorSystem`. The obtained actor -/// system is then used to `resolve(id:using:)` the decoded ID. +/// The synthesized implementations use a single ``SingleValueEncodingContainer`` to +/// encode/decode the ``id`` property of the actor. The ``Decoder`` required +/// ``Decoder/init(from:)`` is implemented by retrieving an actor system from the +/// decoders' `userInfo`, effectively like as follows: /// -/// Use the `CodingUserInfoKey.actorSystemKey` to provide the necessary +/// ```swift +/// decoder.userInfo[.actorSystemKey] as? ActorSystem +// ``` +/// +/// The such obtained actor system is then used to ``resolve(id:using:)`` the decoded ``ID``. +/// +/// Use the ``CodingUserInfoKey/actorSystemKey`` to provide the necessary /// actor system for the decoding initializer when decoding a distributed actor. /// /// - SeeAlso: ``DistributedActorSystem`` @@ -192,17 +214,32 @@ public protocol DistributedActor: AnyActor, Identifiable, Hashable /// to return the same exact resolved actor instance, however all the references would /// represent logically references to the same distributed actor, e.g. on a different node. /// - /// Conformance to this requirement is synthesized automatically for any - /// `distributed actor` declaration. + /// Depending on the capabilities of the actor system producing the identifiers, + /// the `ID` may also be used to store instance specific metadata. + /// + /// ## Synthesized property + /// + /// In concrete distributed actor declarations, a witness for this protocol requirement is synthesized by the compiler. + /// + /// It is not possible to assign a value to the `id` directly; instead, it is assigned during an actors `init` (or `resolve`), + /// by the managing actor system. nonisolated override var id: ID { get } - /// The `ActorSystem` that is managing this distributed actor. + /// The ``DistributedActorSystem`` that is managing this distributed actor. + /// + /// It is immutable and equal to the system assigned during the distributed actor's local initializer + /// (or to the system passed to the ``resolve(id:using:)`` static function). /// - /// It is immutable and equal to the system passed in the local/resolve - /// initializer. + /// ## Synthesized property /// - /// Conformance to this requirement is synthesized automatically for any - /// `distributed actor` declaration. + /// In concrete distributed actor declarations, a witness for this protocol requirement is synthesized by the compiler. + /// + /// It is required to assign an initial value to the `actorSystem` property inside a distributed actor's designated initializer. + /// Semantically, it can be treated as a `let` declaration, that must be assigned in order to fully-initialize the instance. + /// + /// If a distributed actor declares no initializer, its default initializer will take the shape of `init(actorSystem:)`, + /// and initialize this property using the passed ``DistributedActorSystem``. If any user-defined initializer exists, + /// the default initializer is not synthesized, and all the user-defined initializers must take care to initialize this property. nonisolated var actorSystem: ActorSystem { get } /// Resolves the passed in `id` against the `system`, returning @@ -215,6 +252,8 @@ public protocol DistributedActor: AnyActor, Identifiable, Hashable /// the system, allowing it to take over the remote messaging with the /// remote actor instance. /// + /// - Postcondition: upon successful return, the returned actor's ``id`` and ``actorSystem`` properties + /// will be equal to the values passed as parameters to this method. /// - Parameter id: identity uniquely identifying a, potentially remote, actor in the system /// - Parameter system: `system` which should be used to resolve the `identity`, and be associated with the returned actor static func resolve(id: ID, using system: ActorSystem) throws -> Self @@ -226,11 +265,15 @@ public protocol DistributedActor: AnyActor, Identifiable, Hashable extension DistributedActor { /// A distributed actor's hash and equality is implemented by directly delegating to its ``id``. + /// + /// For more details see the "Hashable and Identifiable conformance" section of ``DistributedActor``. nonisolated public func hash(into hasher: inout Hasher) { self.id.hash(into: &hasher) } /// A distributed actor's hash and equality is implemented by directly delegating to its ``id``. + /// + /// For more details see the "Hashable and Identifiable conformance" section of ``DistributedActor``. nonisolated public static func ==(lhs: Self, rhs: Self) -> Bool { lhs.id == rhs.id } @@ -245,7 +288,7 @@ extension CodingUserInfoKey { /// conform to ``DistributedActorSystem``. /// /// Forgetting to set this key will result in that initializer throwing, because - /// an actor system is required. + /// an actor system is required in order to call ``DistributedActor/resolve(id:using:)`` using it. @available(SwiftStdlib 5.7, *) public static let actorSystemKey = CodingUserInfoKey(rawValue: "$distributed_actor_system")! } @@ -315,9 +358,17 @@ extension DistributedActor { // ==== isRemote / isLocal ----------------------------------------------------- +/// Verifies if the passed ``DistributedActor`` conforming type is a remote reference. +/// Passing a type not conforming to ``DistributedActor`` may result in undefined behavior. +/// +/// Official API to perform this task is `whenLocal`. @_silgen_name("swift_distributed_actor_is_remote") public func __isRemoteActor(_ actor: AnyObject) -> Bool +/// Verifies if the passed ``DistributedActor`` conforming type is a local reference. +/// Passing a type not conforming to ``DistributedActor`` may result in undefined behavior. +/// +/// Official API to perform this task is `whenLocal`. public func __isLocalActor(_ actor: AnyObject) -> Bool { return !__isRemoteActor(actor) } diff --git a/stdlib/public/Distributed/DistributedActorSystem.swift b/stdlib/public/Distributed/DistributedActorSystem.swift index 4b583e4889399..5f2ec13e62a82 100644 --- a/stdlib/public/Distributed/DistributedActorSystem.swift +++ b/stdlib/public/Distributed/DistributedActorSystem.swift @@ -53,12 +53,12 @@ import _Concurrency /// /// ## Implementing a DistributedActorSystem /// -/// The following section is dedicated to distributed actor system library authors, and generally can be skipped over +/// This section is dedicated to distributed actor system library authors, and generally can be skipped over /// by library users, as it explains the interactions of synthesized code and specific distributed actor system methods /// and how they must be implemented. /// /// Methods discussed in this section are generally not intended to be called directly, but instead will have calls -/// generated to them from distributed actor declarations in appropriate places (such as initializers, `distributed func` calls etc). +/// generated to them from distributed actor declarations in appropriate places (such as initializers, `distributed func` calls, or `distributed` computed properties). /// /// ### Assigning and Resigning Actor Identifiers /// @@ -91,7 +91,7 @@ import _Concurrency /// It can be as small as an integer based identifier, or as large as a series of key-value pairs identifying the actor. /// /// The actor system must retain a mapping from the ``ActorID`` to the specific actor _instance_ which it is given in -/// ``actorReady(_)`` in order to implement the ``resolve(id:using:)`` method, which is how incoming and outgoing remote calls are made possible. +/// ``actorReady(_:)`` in order to implement the ``resolve(id:using:)`` method, which is how incoming and outgoing remote calls are made possible. /// /// Users have no control over this assignment, nor are they allowed to set the `id` property explicitly. /// The ``DistributedActor/id`` is used to implement the distributed actor's ``Hashable``, ``Equatable``, @@ -150,8 +150,8 @@ import _Concurrency /// /// ### Resolving (potentially remote) Distributed Actors /// -/// An important functionality of any distributed actor system is being able to turn a ``DistributedActor`` type and ``ActorID`` -/// into a reference to such actor, regardless where the actor is located. The ID should have enough information stored +/// An important aspect of any distributed actor system is being able to turn a ``DistributedActor`` type and ``ActorID`` +/// into a reference to an actor (instance), regardless where the actor is located. The ID should have enough information stored /// to be able to make the decision of _where_ the actor is located, without having to contact remote nodes. Specifically, /// the implementation of ``DistributedActorSystem/resolve(id:as:)`` is _not_ `async` and should _not_ perform long running /// or blocking operations in order to return. @@ -159,7 +159,7 @@ import _Concurrency /// > Note: Currently only concrete distributed actors types can be resolved. /// /// The actor system's ``DistributedActorSystem/resolve(id:as:)`` method is called by the compiler whenever end-users -/// call the ``DistributedActor``'s ``resolve(id:using:)`` method. The return types of those methods differ, +/// call the ``DistributedActor``'s ``DistributedActor/resolve(id:using:)`` method. The return types of those methods differ, /// as the actor system's return type is `Act?` (and it may throw if unable to resolve the `ActorID`). /// /// The actor system's `resolve` returning `nil` means that the ``ActorID`` passed to it refers to a _remote_ @@ -171,10 +171,10 @@ import _Concurrency /// Finally, calls on a _remote_ distributed actor reference's distributed methods are turned into invocations of /// `remoteCall(on:target:invocation:returning:throwing:)` (or `remoteCallVoid(on:target:invocation:throwing:)` for Void returning methods). /// -/// Implementing the remote calls correctly and efficiently is one of the most important tasks for a distributed actor system library. -/// Since those methods are not currently expressible as protocol requirements in Swift due to their advanced use -/// of generics, and therefore will not appear in the protocol's documentation as explicit requirements, we present -/// their signatures that a conforming type has to implement here: +/// Implementing the remote calls correctly and efficiently is the important task for a distributed actor system library. +/// Since those methods are not currently expressible as protocol requirements due to advanced use of generics +/// combined with type aliases, they will not appear in the protocol's documentation as explicit requirements. +/// Instead, we present their signatures that a conforming type has to implement here: /// /// > Note: Although the `remoteCall` methods are not expressed as protocol requirements in source, /// > the compiler will provide the same errors as-if they were declared explicitly in this protocol. From dd49a2f5f82339fef383c91511de6483eb896762 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 18 Aug 2022 09:00:01 -0700 Subject: [PATCH 185/491] Add missing executable_test to Interpreter/resilient_multipayload_enum.swift --- test/Interpreter/resilient_multipayload_enum.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Interpreter/resilient_multipayload_enum.swift b/test/Interpreter/resilient_multipayload_enum.swift index 5392a06413d40..6810741822ef8 100644 --- a/test/Interpreter/resilient_multipayload_enum.swift +++ b/test/Interpreter/resilient_multipayload_enum.swift @@ -14,6 +14,8 @@ // RUN: %target-codesign %t/main // RUN: %target-run %t/main %t/%target-library-name(ResilientEnum) | %FileCheck %s +// REQUIRES: executable_test + import ResilientEnum @inline(never) From c09ef05433e14e7b0fe417582ab344e410ff8c1c Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 18 Aug 2022 10:17:30 -0700 Subject: [PATCH 186/491] [Syntax] Add 'UnresolvedTernaryExpr' that resembles `IfExpr` before folding in AST parsing. --- utils/gyb_syntax_support/ExprNodes.py | 14 ++++++++++++++ utils/gyb_syntax_support/NodeSerializationCodes.py | 1 + 2 files changed, 15 insertions(+) diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py index 2402d773f7a10..c0416098da9cf 100644 --- a/utils/gyb_syntax_support/ExprNodes.py +++ b/utils/gyb_syntax_support/ExprNodes.py @@ -311,7 +311,21 @@ ]) ]), + # ? expr : + # Ternary expression without the condition and the second choice. + # NOTE: This appears only in SequenceExpr. + Node('UnresolvedTernaryExpr', kind='Expr', + children=[ + Child("QuestionMark", kind='InfixQuestionMarkToken'), + Child("FirstChoice", kind='Expr'), + Child("ColonMark", kind='ColonToken'), + ]), + + # a ? 1 : 0 + # NOTE: This won't come directly out of the parser. Rather, it is the + # result of "folding" a SequenceExpr based on knowing the precedence + # relationships amongst the different infix operators. Node('TernaryExpr', kind='Expr', children=[ Child("ConditionExpression", kind='Expr'), diff --git a/utils/gyb_syntax_support/NodeSerializationCodes.py b/utils/gyb_syntax_support/NodeSerializationCodes.py index 63d4b02238e6f..8550d640ad519 100644 --- a/utils/gyb_syntax_support/NodeSerializationCodes.py +++ b/utils/gyb_syntax_support/NodeSerializationCodes.py @@ -271,6 +271,7 @@ 'LabeledStmt': 267, 'InfixOperatorExpr': 268, 'MoveExpr': 269, + 'UnresolvedTernaryExpr': 270, } From 1eed8675f7313a4a996e2a441b7acfbd4f649bb6 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 18 Aug 2022 10:32:03 -0700 Subject: [PATCH 187/491] [Parse] Parser update for UnresolvedTernaryExprSyntax --- lib/Parse/ParseExpr.cpp | 13 ++----------- .../Outputs/round_trip_parse_gen.swift.withkinds | 6 +++--- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 486e0be0e305f..fb1c4bba559dc 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -182,7 +182,6 @@ ParserResult Parser::parseExprSequence(Diag<> Message, SmallVector SequencedExprs; SourceLoc startLoc = Tok.getLoc(); ParserStatus SequenceStatus; - bool PendingTernary = false; while (true) { if (isForConditionalDirective && Tok.isAtStartOfLine()) @@ -205,12 +204,6 @@ ParserResult Parser::parseExprSequence(Diag<> Message, } SequencedExprs.push_back(Primary.get()); - // We know we can make a syntax node for ternary expression. - if (PendingTernary) { - SyntaxContext->createNodeInPlace(SyntaxKind::TernaryExpr); - PendingTernary = false; - } - if (SequenceStatus.isError() && !SequenceStatus.hasCodeCompletion()) break; @@ -245,6 +238,8 @@ ParserResult Parser::parseExprSequence(Diag<> Message, } case tok::question_infix: { + SyntaxParsingContext TernaryCtx(SyntaxContext, + SyntaxKind::UnresolvedTernaryExpr); // Save the '?'. SourceLoc questionLoc = consumeToken(); @@ -280,10 +275,6 @@ ParserResult Parser::parseExprSequence(Diag<> Message, colonLoc); SequencedExprs.push_back(unresolvedIf); Message = diag::expected_expr_after_if_colon; - - // Wait for the next expression to make a syntax node for ternary - // expression. - PendingTernary = true; break; } diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds index 8e78636902470..7a35b64b61a7a 100644 --- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds +++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds @@ -60,8 +60,8 @@ class C { func boolOr() -> Bool { return true || false } func foo2() { - _ = true ? 1 : 0 - _ = (true ? 1 : 0) ? (true ? 1 : 0) : (true ? 1 : 0) + _ = true ? 1 : 0 + _ = (true ? 1 : 0) ? (true ? 1 : 0) : (true ? 1 : 0) _ = (1, 2) _ = (first: 1, second: 2) _ = (1) @@ -196,7 +196,7 @@ protocol P: class (_ _: Int, a b: Int = 3 + 2, _ c: Int = 2, - d _: Int = true ? 2: 3, + d _: Int = true ? 2: 3, @objc e: X = true, f: inout Int, g: Int..., From 9c840a71565d29ea3fbf67c42f774cf9bfc34f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Wed, 17 Aug 2022 13:21:54 -0700 Subject: [PATCH 188/491] [Serialization] Suggest solution for SDK mods causing deserialization failures Many deserialization failures at this points are caused by archives installed over the SDK. Let's extend the current error message with a solution for such a case. rdar://86280699 --- lib/Serialization/ModuleFileSharedCore.cpp | 2 ++ test/Serialization/Recovery/crash-recovery.swift | 2 ++ test/Serialization/Recovery/crash-xref.swift | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/lib/Serialization/ModuleFileSharedCore.cpp b/lib/Serialization/ModuleFileSharedCore.cpp index 87ab1da6506ac..632cd4892e505 100644 --- a/lib/Serialization/ModuleFileSharedCore.cpp +++ b/lib/Serialization/ModuleFileSharedCore.cpp @@ -564,6 +564,8 @@ void ModuleFileSharedCore::fatal(llvm::Error error) const { llvm::raw_svector_ostream out(errorStr); out << "*** DESERIALIZATION FAILURE ***\n"; + out << "*** If any module named here was modified in the SDK, please delete the ***\n"; + out << "*** new swiftmodule files from the SDK and keep only swiftinterfaces. ***\n"; outputDiagnosticInfo(out); out << "\n"; if (error) { diff --git a/test/Serialization/Recovery/crash-recovery.swift b/test/Serialization/Recovery/crash-recovery.swift index b49bcc665b8dd..c99c7851f6778 100644 --- a/test/Serialization/Recovery/crash-recovery.swift +++ b/test/Serialization/Recovery/crash-recovery.swift @@ -17,5 +17,7 @@ public class Sub: Base { // CHECK-CRASH-4_2: Compiling with effective version 4.2 // CHECK-CRASH: While loading members for 'Sub' (in module 'Lib') // CHECK-CRASH-LABEL: *** DESERIALIZATION FAILURE *** +// CHECK-CRASH-LABEL: *** If any module named here was modified in the SDK, please delete the *** +// CHECK-CRASH-LABEL: *** new swiftmodule files from the SDK and keep only swiftinterfaces. *** // CHECK-CRASH: module 'Lib' with full misc version {{.*}}4.1.50 // CHECK-CRASH: could not find 'disappearingMethod()' in parent class diff --git a/test/Serialization/Recovery/crash-xref.swift b/test/Serialization/Recovery/crash-xref.swift index d8a0bd59d877f..345d43e62a43d 100644 --- a/test/Serialization/Recovery/crash-xref.swift +++ b/test/Serialization/Recovery/crash-xref.swift @@ -23,6 +23,8 @@ // RUN: cat %t/normal_stderr | %FileCheck %s -check-prefixes=NORMALFAILURE // NORMALFAILURE-LABEL: *** DESERIALIZATION FAILURE *** +// NORMALFAILURE-LABEL: *** If any module named here was modified in the SDK, please delete the *** +// NORMALFAILURE-LABEL: *** new swiftmodule files from the SDK and keep only swiftinterfaces. *** // NORMALFAILURE-NEXT: module 'Client' with full misc version {{.*}}' // NORMALFAILURE-NEXT: Could not deserialize type for 'foo()' // NORMALFAILURE-NEXT: Caused by: top-level value not found @@ -33,6 +35,8 @@ // RUN: cat %t/error_stderr | %FileCheck %s -check-prefixes=ALLOWFAILURE // ALLOWFAILURE-LABEL: *** DESERIALIZATION FAILURE *** +// ALLOWFAILURE-LABEL: *** If any module named here was modified in the SDK, please delete the *** +// ALLOWFAILURE-LABEL: *** new swiftmodule files from the SDK and keep only swiftinterfaces. *** // ALLOWFAILURE-NEXT: module 'Client' with full misc version {{.*}}' (built with -experimental-allow-module-with-compiler-errors) // ALLOWFAILURE-NEXT: Could not deserialize type for 'foo()' // ALLOWFAILURE-NEXT: Caused by: top-level value not found From 7f9fadb7d87921a2009b5007fd54a83c6334c161 Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Thu, 18 Aug 2022 12:31:40 -0700 Subject: [PATCH 189/491] Fix type for resilient enum case global variables --- lib/PrintAsClang/PrintClangValueType.cpp | 2 +- test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index d6d5efc90f8dd..89876e2b0cae4 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -127,7 +127,7 @@ void ClangValueTypePrinter::printValueTypeDecl( os << typeDecl->getName().str() << '\n'; os << "extern \"C\" {\n"; for (const auto &pair : elementTagMapping) { - os << "extern int " + os << "extern unsigned " << pair.second.globalVariableName << ";\n"; } os << "}\n"; diff --git a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift index 2795cc2d9ffbd..22f3502a8b130 100644 --- a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift +++ b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift @@ -34,8 +34,8 @@ public func printFoo(_ x: Foo) { // CHECK: // Tags for resilient enum Foo // CHECK-NEXT: extern "C" { -// CHECK-NEXT: extern int $s5Enums3FooO1ayACSdcACmFWC; -// NEW_CASE-NEXT: extern int $s5Enums3FooO1byACSicACmFWC; +// CHECK-NEXT: extern unsigned $s5Enums3FooO1ayACSdcACmFWC; +// NEW_CASE-NEXT: extern unsigned $s5Enums3FooO1byACSicACmFWC; // CHECK-NEXT: } // CHECK-EMPTY: // CHECK-NEXT: } // namespace _impl From be01f28f7703b2899aa9c3bfb9f885434834704c Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Thu, 18 Aug 2022 12:32:29 -0700 Subject: [PATCH 190/491] update test case --- test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp index d53c089659e7d..091f1ade8e2aa 100644 --- a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp +++ b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp @@ -10,5 +10,5 @@ void test(void *p) { getEnumTagi32(p); } -// CHECK: declare zeroext i8 @_Z12getEnumTagi8Pv(i8*) #1 -// CHECK: declare i32 @_Z13getEnumTagi32Pv(i8*) #1 +// CHECK: declare noundef zeroext i8 @_Z12getEnumTagi8Pv(i8* noundef) #1 +// CHECK: declare noundef i32 @_Z13getEnumTagi32Pv(i8* noundef) #1 From 958138df059e370eb8f3af2bf9cc5792ea377665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Thu, 18 Aug 2022 14:25:27 -0700 Subject: [PATCH 191/491] [Sema] Only warn on uses of an implicitly imported conformances in API Until Swift 6, always downgrade to a warning the diagnostic on the use in API of a conformance that wasn't imported by the local source file. rdar://98851314 --- lib/Sema/ResilienceDiagnostics.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Sema/ResilienceDiagnostics.cpp b/lib/Sema/ResilienceDiagnostics.cpp index 597f331cf4ad7..63e3b324eadb5 100644 --- a/lib/Sema/ResilienceDiagnostics.cpp +++ b/lib/Sema/ResilienceDiagnostics.cpp @@ -241,8 +241,9 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc, static_cast(*reason), M->getName(), static_cast(originKind)) - .warnUntilSwiftVersionIf(useConformanceAvailabilityErrorsOption && - !ctx.LangOpts.EnableConformanceAvailabilityErrors, + .warnUntilSwiftVersionIf((useConformanceAvailabilityErrorsOption && + !ctx.LangOpts.EnableConformanceAvailabilityErrors) || + originKind == DisallowedOriginKind::ImplicitlyImported, 6); return true; } From 92087a8f620ebb5bac6741012aef2ef82c3b6b33 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 18 Aug 2022 15:13:24 -0600 Subject: [PATCH 192/491] [stdlib] add explanations to _debugPrecondition calls --- stdlib/public/core/UnsafeBufferPointer.swift.gyb | 12 +++++++----- stdlib/public/core/UnsafePointer.swift | 10 ++++++++-- stdlib/public/core/UnsafeRawBufferPointer.swift.gyb | 3 ++- stdlib/public/core/UnsafeRawPointer.swift | 6 ++++-- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb index 5ece3632ba1ab..966508c07a96d 100644 --- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb @@ -742,19 +742,21 @@ extension Unsafe${Mutable}BufferPointer { return try body(.init(start: nil, count: 0)) } + _debugPrecondition( + Int(bitPattern: .init(base)) & (MemoryLayout.alignment-1) == 0, + "baseAddress must be a properly aligned pointer for types Element and T" + ) + let newCount: Int if MemoryLayout.stride == MemoryLayout.stride { newCount = count - _debugPrecondition( - MemoryLayout.alignment == MemoryLayout.alignment - ) } else { newCount = count * MemoryLayout.stride / MemoryLayout.stride _debugPrecondition( - Int(bitPattern: .init(base)) & (MemoryLayout.alignment-1) == 0 && MemoryLayout.stride > MemoryLayout.stride ? MemoryLayout.stride % MemoryLayout.stride == 0 - : MemoryLayout.stride % MemoryLayout.stride == 0 + : MemoryLayout.stride % MemoryLayout.stride == 0, + "Buffer must contain a whole number of Element instances" ) } let binding = Builtin.bindMemory(base, newCount._builtinWordValue, T.self) diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index 526c4769de5d3..86b7e405c6fd2 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -319,7 +319,10 @@ public struct UnsafePointer: _Pointer { ( MemoryLayout.stride > MemoryLayout.stride ? MemoryLayout.stride % MemoryLayout.stride == 0 : MemoryLayout.stride % MemoryLayout.stride == 0 - ))) + ) + ), + "self must be a properly aligned pointer for types Pointee and T" + ) let binding = Builtin.bindMemory(_rawValue, count._builtinWordValue, T.self) defer { Builtin.rebindMemory(_rawValue, binding) } return try body(.init(_rawValue)) @@ -1026,7 +1029,10 @@ public struct UnsafeMutablePointer: _Pointer { ( MemoryLayout.stride > MemoryLayout.stride ? MemoryLayout.stride % MemoryLayout.stride == 0 : MemoryLayout.stride % MemoryLayout.stride == 0 - ))) + ) + ), + "self must be a properly aligned pointer for types Pointee and T" + ) let binding = Builtin.bindMemory(_rawValue, count._builtinWordValue, T.self) defer { Builtin.rebindMemory(_rawValue, binding) } return try body(.init(_rawValue)) diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb index 21bd0b2e624e7..1df4cff6dba8a 100644 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb @@ -868,7 +868,8 @@ extension Unsafe${Mutable}RawBufferPointer { return try body(.init(start: nil, count: 0)) } _debugPrecondition( - Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0 + Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0, + "baseAddress must be a properly aligned pointer for type T" ) // initializer ensures _end is nil only when _position is nil. _internalInvariant(_end != nil) diff --git a/stdlib/public/core/UnsafeRawPointer.swift b/stdlib/public/core/UnsafeRawPointer.swift index 7c83233ead1d2..b41895574a83a 100644 --- a/stdlib/public/core/UnsafeRawPointer.swift +++ b/stdlib/public/core/UnsafeRawPointer.swift @@ -378,7 +378,8 @@ public struct UnsafeRawPointer: _Pointer { _ body: (_ pointer: UnsafePointer) throws -> Result ) rethrows -> Result { _debugPrecondition( - Int(bitPattern: self) & (MemoryLayout.alignment-1) == 0 + Int(bitPattern: self) & (MemoryLayout.alignment-1) == 0, + "self must be a properly aligned pointer for type T" ) let binding = Builtin.bindMemory(_rawValue, count._builtinWordValue, T.self) defer { Builtin.rebindMemory(_rawValue, binding) } @@ -934,7 +935,8 @@ public struct UnsafeMutableRawPointer: _Pointer { _ body: (_ pointer: UnsafeMutablePointer) throws -> Result ) rethrows -> Result { _debugPrecondition( - Int(bitPattern: self) & (MemoryLayout.alignment-1) == 0 + Int(bitPattern: self) & (MemoryLayout.alignment-1) == 0, + "self must be a properly aligned pointer for type T" ) let binding = Builtin.bindMemory(_rawValue, count._builtinWordValue, T.self) defer { Builtin.rebindMemory(_rawValue, binding) } From cc1a835d9b50efac2e24a3502cc528502132c8aa Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 18 Aug 2022 11:23:21 -0700 Subject: [PATCH 193/491] [CSBindings] Add potential bindings that are inferred from literals to type variable and binding printing. --- lib/Sema/CSBindings.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 96500cff65836..925ddf7901822 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -1710,7 +1710,7 @@ void BindingSet::dump(llvm::raw_ostream &out, unsigned indent) const { } case LiteralBindingKind::Float: case LiteralBindingKind::None: - out << getLiteralBindingKind(literalKind).str(); + out << getLiteralBindingKind(literalKind).str(); break; } if (attributes.empty()) { @@ -1755,8 +1755,20 @@ void BindingSet::dump(llvm::raw_ostream &out, unsigned indent) const { out << "[with possible bindings: "; interleave(Bindings, printBinding, [&]() { out << "; "; }); - if (Bindings.empty()) + if (!Literals.empty()) { + std::vector defaultLiterals; + for (const auto &literal : Literals) { + if (literal.second.viableAsBinding()) { + auto defaultWithType = "(default type of literal) " + + literal.second.getDefaultType().getString(PO); + defaultLiterals.push_back(defaultWithType); + } + } + interleave(defaultLiterals, out, ", "); + } + if (Bindings.empty() && Literals.empty()) { out << ""; + } out << "]"; if (!Defaults.empty()) { From 6acae62c0cdbb6eedc5f4dfcd4a84deb466ea3a8 Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Wed, 17 Aug 2022 20:18:14 -0700 Subject: [PATCH 194/491] [NFC] Remove vector not in use. --- lib/Sema/CSBindings.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 925ddf7901822..16cc21d05aaa4 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -636,8 +636,6 @@ void BindingSet::determineLiteralCoverage() { if (Literals.empty()) return; - SmallVector adjustedBindings; - bool allowsNil = canBeNil(); for (auto &entry : Literals) { @@ -648,7 +646,6 @@ void BindingSet::determineLiteralCoverage() { for (auto binding = Bindings.begin(); binding != Bindings.end(); ++binding) { - bool isCovered = false; Type adjustedTy; From d3f482ab9eee4bd87662bae1138a9c5a8bdc65ae Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Wed, 17 Aug 2022 11:38:55 -0700 Subject: [PATCH 195/491] SIL: Don't eagerly erase instructions in builder peepholes. Even if the operand doesn't currently have any uses after the peephole, the caller may intend to use the operand for other purposes. If the operand is really unused in the end, then dead code elimination ought to clean it up. Fixes rdar://98418860. --- lib/SIL/IR/SILBuilder.cpp | 28 +++++++------------ .../use_thick_metatype_after_objc.swift | 23 +++++++++++++++ 2 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 test/SILGen/use_thick_metatype_after_objc.swift diff --git a/lib/SIL/IR/SILBuilder.cpp b/lib/SIL/IR/SILBuilder.cpp index 87ba1d9a6b361..3b4ddc201a304 100644 --- a/lib/SIL/IR/SILBuilder.cpp +++ b/lib/SIL/IR/SILBuilder.cpp @@ -480,16 +480,12 @@ SILBuilder::emitDestroyValue(SILLocation Loc, SILValue Operand) { SILValue SILBuilder::emitThickToObjCMetatype(SILLocation Loc, SILValue Op, SILType Ty) { - // If the operand is an otherwise-unused 'metatype' instruction in the - // same basic block, zap it and create a 'metatype' instruction that - // directly produces an Objective-C metatype. + // If the operand is a 'metatype' instruction accessing a known static type's + // metadata, create a 'metatype' instruction that + // directly produces the Objective-C class object representation instead. if (auto metatypeInst = dyn_cast(Op)) { - if (metatypeInst->use_empty() && - metatypeInst->getParent() == getInsertionBB()) { - auto origLoc = metatypeInst->getLoc(); - metatypeInst->eraseFromParent(); - return createMetatype(origLoc, Ty); - } + auto origLoc = metatypeInst->getLoc(); + return createMetatype(origLoc, Ty); } // Just create the thick_to_objc_metatype instruction. @@ -498,16 +494,12 @@ SILValue SILBuilder::emitThickToObjCMetatype(SILLocation Loc, SILValue Op, SILValue SILBuilder::emitObjCToThickMetatype(SILLocation Loc, SILValue Op, SILType Ty) { - // If the operand is an otherwise-unused 'metatype' instruction in the - // same basic block, zap it and create a 'metatype' instruction that - // directly produces a thick metatype. + // If the operand is a 'metatype' instruction accessing a known static type's + // metadata, create a 'metatype' instruction that directly produces the + // Swift metatype representation instead. if (auto metatypeInst = dyn_cast(Op)) { - if (metatypeInst->use_empty() && - metatypeInst->getParent() == getInsertionBB()) { - auto origLoc = metatypeInst->getLoc(); - metatypeInst->eraseFromParent(); - return createMetatype(origLoc, Ty); - } + auto origLoc = metatypeInst->getLoc(); + return createMetatype(origLoc, Ty); } // Just create the objc_to_thick_metatype instruction. diff --git a/test/SILGen/use_thick_metatype_after_objc.swift b/test/SILGen/use_thick_metatype_after_objc.swift new file mode 100644 index 0000000000000..de45e7245ca18 --- /dev/null +++ b/test/SILGen/use_thick_metatype_after_objc.swift @@ -0,0 +1,23 @@ +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -enable-implicit-dynamic -verify %s +// rdar://98418860 + +// REQUIRES: objc_interop + +import Foundation + +@propertyWrapper +struct ExamplePropertyWrapper { + var wrappedValue: Bool = false +} + +@objcMembers +class ExampleClass { + @ExamplePropertyWrapper + static var exampleProperty: Bool +} + +class ExampleCallingClass { + func exampleSegfaultingCall() { + ExampleClass.exampleProperty.toggle() + } +} From 672908d5b381943bcc0f52e2fdc4a3ef2b7b6d51 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 19 Aug 2022 05:45:43 +0300 Subject: [PATCH 196/491] Gardening: Migrate test suite to GH issues: Constraints (4/5) --- test/Constraints/closures.swift | 284 ++++++++++-------- .../keypath_dynamic_member_lookup.swift | 150 ++++----- 2 files changed, 243 insertions(+), 191 deletions(-) diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift index e0002b60f3f78..a13085f2b348e 100644 --- a/test/Constraints/closures.swift +++ b/test/Constraints/closures.swift @@ -86,9 +86,11 @@ func test13811882() { } -// QoI: "Unexpected trailing closure" should have a fixit to insert a 'do' statement -// -func r21544303() { +/// +/// https://github.com/apple/swift/issues/46256 +/// QoI: "Unexpected trailing closure" should have a fixit to insert a `do` +/// statement +do { var inSubcall = true { // expected-error {{closure expression is unused}} expected-note {{did you mean to use a 'do' statement?}} } @@ -106,8 +108,8 @@ func r21544303() { } -// -func SR3671() { +// https://github.com/apple/swift/issues/46256 +do { let n = 42 func consume(_ x: Int) {} @@ -258,7 +260,8 @@ func typeCheckMultiStmtClosureCrash() { } } -// SR-832 - both these should be ok +// https://github.com/apple/swift/issues/43444 + func someFunc(_ foo: ((String) -> String)?, bar: @escaping (String) -> String) { let _: (String) -> String = foo != nil ? foo! : bar @@ -270,25 +273,31 @@ func verify_NotAC_to_AC_failure(_ arg: () -> ()) { takesAC(arg) // expected-error {{add () to forward @autoclosure parameter}} {{14-14=()}} } -// SR-1069 - Error diagnostic refers to wrong argument -class SR1069_W { - func append(value: T, forKey key: Key) where Key: Hashable {} -} -class SR1069_C { let w: SR1069_W<(AnyObject, T) -> ()> = SR1069_W() } -struct S { - let cs: [SR1069_C] = [] - - func subscribe(object: Object?, method: (Object, T) -> ()) where Object: Hashable { - let wrappedMethod = { (object: AnyObject, value: T) in } - cs.forEach { $0.w.append(value: wrappedMethod, forKey: object) } - // expected-error@-1 {{value of optional type 'Object?' must be unwrapped to a value of type 'Object'}} - // expected-note@-2 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} - // expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} +// https://github.com/apple/swift/issues/43681 +// Error diagnostic refers to wrong argument +do { + class C1 { + func append(value: T, forKey key: Key) where Key: Hashable {} + } + class C2 { + let c1: C1<(AnyObject, T) -> ()> = C1() + } + struct S { + let cs: [C2] = [] + + func subscribe(object: Object?, method: (Object, T) -> ()) where Object: Hashable { + let wrappedMethod = { (object: AnyObject, value: T) in } + cs.forEach { $0.c1.append(value: wrappedMethod, forKey: object) } + // expected-error@-1 {{value of optional type 'Object?' must be unwrapped to a value of type 'Object'}} + // expected-note@-2 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} + // expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} + } } } -// Similar to SR1069 but with multiple generic arguments -func simplified1069() { +// Similar to https://github.com/apple/swift/issues/43681 but with multiple +// generic arguments. +do { class C {} struct S { func genericallyNonOptional(_ a: T, _ b: T, _ c: T) { } @@ -415,39 +424,38 @@ func r20789423() { } -// In the example below, SR-2505 started preferring C_SR_2505.test(_:) over -// test(it:). Prior to Swift 5.1, we emulated the old behavior. However, -// that behavior is inconsistent with the typical approach of preferring -// overloads from the concrete type over one from a protocol, so we removed -// the hack. -protocol SR_2505_Initable { init() } -struct SR_2505_II : SR_2505_Initable {} +/// In the example below, https://github.com/apple/swift/issues/45110 started +/// preferring `C_45110.test(_:)` over `P_45110.test(it:)`. Prior to Swift 5.1, +/// we emulated the old behavior. However, that behavior is inconsistent with +/// the typical approach of preferring overloads from the concrete type over one +/// from a protocol, so we removed the hack. +protocol Initable_45110 { init() } -protocol P_SR_2505 { - associatedtype T: SR_2505_Initable +protocol P_45110 { + associatedtype T: Initable_45110 } - -extension P_SR_2505 { +extension P_45110 { func test(it o: (T) -> Bool) -> Bool { return o(T.self()) } } -class C_SR_2505 : P_SR_2505 { - typealias T = SR_2505_II +struct S_45110 : Initable_45110 {} +class C_45110 : P_45110 { + typealias T = S_45110 func test(_ o: Any) -> Bool { return false } - func call(_ c: C_SR_2505) -> Bool { + func call(_ c: C_45110) -> Bool { // Note: the diagnostic about capturing 'self', indicates that we have // selected test(_) rather than test(it:) return c.test { o in test(o) } // expected-error{{call to method 'test' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} expected-note{{reference 'self.' explicitly}} } } -let _ = C_SR_2505().call(C_SR_2505()) +let _ = C_45110().call(C_45110()) // Returning incorrect result type from method invocation can result in nonsense diagnostic extension Collection { @@ -461,25 +469,30 @@ func fn_r28909024(n: Int) { } } -// SR-2994: Unexpected ambiguous expression in closure with generics -struct S_2994 { - var dataOffset: Int -} -class C_2994 { - init(arg: (R) -> Void) {} -} -func f_2994(arg: String) {} -func g_2994(arg: Int) -> Double { - return 2 -} -C_2994(arg: { (r: S_2994) in f_2994(arg: g_2994(arg: r.dataOffset)) }) // expected-error {{cannot convert value of type 'Double' to expected argument type 'String'}} +// https://github.com/apple/swift/issues/45584 +// Unexpected ambiguous expression in closure with generics +do { + struct S { + var dataOffset: Int + } + class C { + init(arg: (R) -> Void) {} + } + func f(arg: String) {} + func g(arg: Int) -> Double { + return 2 + } + + C(arg: { (r: S) in f(arg: g(arg: r.dataOffset)) }) // expected-error {{cannot convert value of type 'Double' to expected argument type 'String'}} -let _ = { $0[$1] }(1, 1) // expected-error {{value of type 'Int' has no subscripts}} -// FIXME: Better diagnostic here would be `assigning a variable to itself` but binding ordering change exposed a but in diagnostics -let _ = { $0 = ($0 = {}) } // expected-error {{function produces expected type '()'; did you mean to call it with '()'?}} -let _ = { $0 = $0 = 42 } // expected-error {{assigning a variable to itself}} + let _ = { $0[$1] }(1, 1) // expected-error {{value of type 'Int' has no subscripts}} + // FIXME: Better diagnostic here would be `assigning a variable to itself` but + // binding ordering change exposed a bug in diagnostics. + let _ = { $0 = ($0 = {}) } // expected-error {{function produces expected type '()'; did you mean to call it with '()'?}} + let _ = { $0 = $0 = 42 } // expected-error {{assigning a variable to itself}} +} -// https://bugs.swift.org/browse/SR-403 +// https://github.com/apple/swift/issues/43020 // The () -> T => () -> () implicit conversion was kicking in anywhere // inside a closure result, not just at the top-level. let mismatchInClosureResultType : (String) -> ((Int) -> Void) = { @@ -488,40 +501,64 @@ let mismatchInClosureResultType : (String) -> ((Int) -> Void) = { // expected-error@-1 {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}} {{13-13= _ in}} } -// SR-3520: Generic function taking closure with inout parameter can result in a variety of compiler errors or EXC_BAD_ACCESS -func sr3520_1(_ g: (inout T) -> Int) {} -sr3520_1 { $0 = 1 } // expected-error {{cannot convert value of type '()' to closure result type 'Int'}} +// https://github.com/apple/swift/issues/46108 +// Generic function taking closure with in-out parameter can result in a variety +// of compiler errors or EXC_BAD_ACCESS +do { + func f(_ g: (inout T) -> Int) {} + f { $0 = 1 } // expected-error {{cannot convert value of type '()' to closure result type 'Int'}} -// This test makes sure that having closure with inout argument doesn't crash with member lookup -struct S_3520 { - var number1: Int + // This test makes sure that having closure with in-out parameter doesn't + // crash with member lookup. + struct S { + var number1: Int + } + func set_via_closure(_ closure: (inout T, U) -> ()) {} // expected-note {{in call to function 'set_via_closure'}} + set_via_closure({ $0.number1 = $1 }) + // expected-error@-1 {{generic parameter 'T' could not be inferred}} + // expected-error@-2 {{unable to infer type of a closure parameter '$1' in the current context}} + + func f2(_ item: T, _ update: (inout T) -> Void) { + var x = item + update(&x) + } + var arg = 42 + f2(arg) { $0 += 3 } // ok } -func sr3520_set_via_closure(_ closure: (inout S, T) -> ()) {} // expected-note {{in call to function 'sr3520_set_via_closure'}} -sr3520_set_via_closure({ $0.number1 = $1 }) -// expected-error@-1 {{generic parameter 'S' could not be inferred}} -// expected-error@-2 {{unable to infer type of a closure parameter '$1' in the current context}} - -// SR-3073: UnresolvedDotExpr in single expression closure -struct SR3073Lense { - let set: (inout Whole, Part) -> () +/// https://github.com/apple/swift/issues/44585 +/// https://github.com/apple/swift/issues/45663 +/// Inference of `inout` +do { + func f(_ closure: (inout T) -> Void) {} + f({ $0 += 2 }) // ok } -struct SR3073 { - var number1: Int - func lenses() { - let _: SR3073Lense = SR3073Lense( - set: { $0.number1 = $1 } // ok - ) + +/// https://github.com/apple/swift/issues/45663 +/// `UnresolvedDotExpr` in single expression closure +do { + struct Lense { + let set: (inout Whole, Part) -> () + } + struct S { + var number1: Int + func lenses() { + let _: Lense = Lense( + set: { $0.number1 = $1 } // ok + ) + } } } -// SR-3479: Segmentation fault and other error for closure with inout parameter -func sr3497_unfold(_ a0: A, next: (inout A) -> B) {} -func sr3497() { - let _ = sr3497_unfold((0, 0)) { s in 0 } // ok +// https://github.com/apple/swift/issues/46067 +// Segmentation fault and other error for closure with in-out parameter +do { + func unfold(_ a0: A, next: (inout A) -> B) {} + unfold((0, 0)) { s in 0 } // ok } -// SR-3758: Swift 3.1 fails to compile 3.0 code involving closures and IUOs +// https://github.com/apple/swift/issues/46343 +// Swift 3.1 fails to compile 3.0 code involving closures and IUOs let _: ((Any?) -> Void) = { (arg: Any!) in } // This example was rejected in 3.0 as well, but accepting it is correct. let _: ((Int?) -> Void) = { (arg: Int!) in } @@ -558,24 +595,26 @@ r32432145 { _,_ in [1, 2].first { $0.foo = 3 } // expected-error@-1 {{value of type 'Int' has no member 'foo'}} -// rdar://problem/32433193, SR-5030 - Higher-order function diagnostic mentions the wrong contextual type conversion problem -protocol A_SR_5030 { +// rdar://problem/32433193 +// https://github.com/apple/swift/issues/47606 +// Higher-order function diagnostic mentions the wrong contextual type +// conversion problem + +protocol P_47606 { associatedtype Value - func map(_ t : @escaping (Self.Value) -> U) -> B_SR_5030 + func map(_ t : @escaping (Self.Value) -> U) -> S_47606 } -struct B_SR_5030 : A_SR_5030 { +struct S_47606 : P_47606 { typealias Value = T - func map(_ t : @escaping (T) -> U) -> B_SR_5030 { fatalError() } + func map(_ t : @escaping (T) -> U) -> S_47606 { fatalError() } } -func sr5030_exFalso() -> T { - fatalError() -} +func exFalso_47606() -> T {} -extension A_SR_5030 { - func foo() -> B_SR_5030 { - let tt : B_SR_5030 = sr5030_exFalso() +extension P_47606 { + func foo() -> S_47606 { + let tt : S_47606 = exFalso_47606() return tt.map { x in (idx: x) } // expected-error@-1 {{cannot convert value of type '(idx: Int)' to closure result type 'Int'}} } @@ -590,17 +629,20 @@ let u = rdar33296619().element //expected-error {{cannot find 'rdar33296619' in // expected-note@-1 {{overloads for '+' exist with these partially matching parameter lists: (Int, Int), (String, String)}} } -class SR5666 { - var property: String? -} +// https://github.com/apple/swift/issues/48236 +do { + class C { + var property: String? + } -func testSR5666(cs: [SR5666?]) -> [String?] { - return cs.map({ c in - let a = c.propertyWithTypo ?? "default" - // expected-error@-1 {{value of type 'SR5666?' has no member 'propertyWithTypo'}} - let b = "\(a)" - return b - }) + func test(cs: [C?]) -> [String?] { + return cs.map({ c in + let a = c.propertyWithTypo ?? "default" + // expected-error@-1 {{value of type 'C?' has no member 'propertyWithTypo'}} + let b = "\(a)" + return b + }) + } } // Ensure that we still do the appropriate pointer conversion here. @@ -612,25 +654,17 @@ _ = { (offset) -> T in // expected-error {{cannot find type 'T' in scope}} return offset ? 0 : 0 } -struct SR5202 { - func map(fn: (T) -> R) {} -} - -SR5202<()>().map{ return 0 } -SR5202<()>().map{ _ in return 0 } -SR5202().map{ return 0 } -SR5202().map{ _ in return 0 } +// https://github.com/apple/swift/issues/47778 +do { + struct S { + func map(fn: (T) -> R) {} + } -func sr3520_2(_ item: T, _ update: (inout T) -> Void) { - var x = item - update(&x) + S<()>().map{ return 0 } + S<()>().map{ _ in return 0 } + S().map{ return 0 } + S().map{ _ in return 0 } } -var sr3250_arg = 42 -sr3520_2(sr3250_arg) { $0 += 3 } // ok - -// SR-1976/SR-3073: Inference of inout -func sr1976(_ closure: (inout T) -> Void) {} -sr1976({ $0 += 2 }) // ok // rdar://problem/33429010 @@ -1000,9 +1034,12 @@ func rdar52204414() { // expected-error@-1 {{declared closure result 'Void' is incompatible with return type 'Int'}} {{19-23=Int}} } -// SR-12291 - trailing closure is used as an argument to the last (positionally) parameter. +// https://github.com/apple/swift/issues/54719 +// Trailing closure is used as an argument to the last (positionally) parameter. +// // Note that this was accepted prior to Swift 5.3. SE-0286 changed the // order of argument resolution and made it ambiguous. + func overloaded_with_default(a: () -> Int, b: Int = 0, c: Int = 0) {} // expected-note{{found this candidate}} func overloaded_with_default(b: Int = 0, c: Int = 0, a: () -> Int) {} // expected-note{{found this candidate}} @@ -1014,8 +1051,10 @@ func overloaded_with_default_and_autoclosure(b: Int = 0, c: @escaping () -> T overloaded_with_default_and_autoclosure { 42 } // Ok overloaded_with_default_and_autoclosure(42) // Ok -// SR-12815 - `error: type of expression is ambiguous without more context` in many cases where methods are missing -func sr12815() { +/// https://github.com/apple/swift/issues/55261 +/// "error: type of expression is ambiguous without more context" in many cases +/// where methods are missing. +do { let _ = { a, b in } // expected-error@-1 {{unable to infer type of a closure parameter 'a' in the current context}} // expected-error@-2 {{unable to infer type of a closure parameter 'b' in the current context}} @@ -1069,7 +1108,8 @@ func rdar_74435602(error: Error?) { }) } -// SR-14280 +// https://github.com/apple/swift/issues/56639 + let _: (@convention(block) () -> Void)? = Bool.random() ? nil : {} // OK let _: (@convention(thin) () -> Void)? = Bool.random() ? nil : {} // OK let _: (@convention(c) () -> Void)? = Bool.random() ? nil : {} // OK on type checking, diagnostics are deferred to SIL @@ -1098,7 +1138,7 @@ struct R_76250381 { } } -// SR-13483 +// https://github.com/apple/swift/issues/55926 (0..<10).map { x, y in } // expected-error@-1 {{contextual closure type '(Range.Element) throws -> ()' (aka '(Int) throws -> ()') expects 1 argument, but 2 were used in closure body}} (0..<10).map { x, y, z in } diff --git a/test/Constraints/keypath_dynamic_member_lookup.swift b/test/Constraints/keypath_dynamic_member_lookup.swift index 7ba1166b9dc1a..36e5bb9489bdd 100644 --- a/test/Constraints/keypath_dynamic_member_lookup.swift +++ b/test/Constraints/keypath_dynamic_member_lookup.swift @@ -369,10 +369,12 @@ func make_sure_delayed_keypath_dynamic_member_works() { } -// SR-11465 - Ambiguity in expression which matches both dynamic member lookup and declaration from constrained extension +// https://github.com/apple/swift/issues/53865 +// Ambiguity in expression which matches both dynamic member lookup and +// declaration from constrained extension @dynamicMemberLookup -struct SR_11465 { +struct S_53865 { var rawValue: RawValue subscript(dynamicMember keyPath: KeyPath) -> Subject { @@ -380,155 +382,165 @@ struct SR_11465 { } } -extension SR_11465: Hashable, Equatable where RawValue: Hashable { +extension S_53865: Hashable, Equatable where RawValue: Hashable { func hash(into hasher: inout Hasher) { hasher.combine(self.rawValue) } } func test_constrained_ext_vs_dynamic_member() { - // CHECK: function_ref @$s29keypath_dynamic_member_lookup8SR_11465VAASHRzlE9hashValueSivg - _ = SR_11465(rawValue: 1).hashValue // Ok, keep choice from constrained extension + // CHECK: function_ref @$s29keypath_dynamic_member_lookup7S_53865VAASHRzlE9hashValueSivg + _ = S_53865(rawValue: 1).hashValue // Ok, keep choice from constrained extension } -// SR-11893: Make sure we properly handle IUO unwraps for key path dynamic members. -struct SR_11893_Base { +// https://github.com/apple/swift/issues/54310 +// https://github.com/apple/swift/issues/57571 +// Make sure we properly handle IUO unwraps for key path dynamic members. + +struct S_54310_Base { var i: Int! subscript(_ x: Int) -> Int! { x } } @dynamicMemberLookup -struct SR_11893 { - subscript(dynamicMember kp: KeyPath) -> Void { () } +struct S_54310 { + subscript(dynamicMember kp: KeyPath) -> Void { () } } @dynamicMemberLookup -struct SR_15249 { - subscript(dynamicMember kp: KeyPath) -> Int! { 0 } +struct S_57571 { + subscript(dynamicMember kp: KeyPath) -> Int! { 0 } } -// CHECK-LABEL: sil hidden @$s29keypath_dynamic_member_lookup13testIUOUnwrapyyAA8SR_11893V_AA0G6_15249VtF -func testIUOUnwrap(_ x: SR_11893, _ y: SR_15249) { - // CHECK: keypath $KeyPath, (root $SR_11893_Base; stored_property #SR_11893_Base.i : $Optional; optional_force : $Int) +// CHECK-LABEL: sil hidden @$s29keypath_dynamic_member_lookup13testIUOUnwrapyyAA7S_54310V_AA7S_57571VtF +func testIUOUnwrap(_ x: S_54310, _ y: S_57571) { + // CHECK: keypath $KeyPath, (root $S_54310_Base; stored_property #S_54310_Base.i : $Optional; optional_force : $Int) x.i - // CHECK: keypath $KeyPath, (root $SR_11893_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicig : $@convention(method) (Int, SR_11893_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed SR_11893_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) + // CHECK: keypath $KeyPath, (root $S_54310_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicig : $@convention(method) (Int, S_54310_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed S_54310_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) x[5] - // CHECK: [[INNER_KP:%[0-9]+]] = keypath $KeyPath, (root $SR_11893_Base; stored_property #SR_11893_Base.i : $Optional; optional_force : $Int) - // CHECK: keypath $KeyPath, (root $SR_11893; gettable_property $(), id @$s29keypath_dynamic_member_lookup8SR_11893V0B6Memberys7KeyPathCyAA0E11_11893_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, SR_11893) -> (), getter @$s29keypath_dynamic_member_lookup8SR_11893V0B6Memberys7KeyPathCyAA0E11_11893_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed SR_11893, UnsafeRawPointer) -> @out (), indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_KP]]) - _ = \SR_11893.i + // CHECK: [[INNER_KP:%[0-9]+]] = keypath $KeyPath, (root $S_54310_Base; stored_property #S_54310_Base.i : $Optional; optional_force : $Int) + // CHECK: keypath $KeyPath, (root $S_54310; gettable_property $(), id @$s29keypath_dynamic_member_lookup7S_54310V0B6Memberys7KeyPathCyAA12S_54310_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, S_54310) -> (), getter @$s29keypath_dynamic_member_lookup7S_54310V0B6Memberys7KeyPathCyAA12S_54310_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed S_54310, UnsafeRawPointer) -> @out (), indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_KP]]) + _ = \S_54310.i - // CHECK: [[INNER_SUB_KP:%[0-9]+]] = keypath $KeyPath, (root $SR_11893_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicig : $@convention(method) (Int, SR_11893_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed SR_11893_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) - // CHECK: keypath $KeyPath, (root $SR_11893; gettable_property $(), id @$s29keypath_dynamic_member_lookup8SR_11893V0B6Memberys7KeyPathCyAA0E11_11893_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, SR_11893) -> (), getter @$s29keypath_dynamic_member_lookup8SR_11893V0B6Memberys7KeyPathCyAA0E11_11893_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed SR_11893, UnsafeRawPointer) -> @out (), indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_SUB_KP]]) - _ = \SR_11893.[5] + // CHECK: [[INNER_SUB_KP:%[0-9]+]] = keypath $KeyPath, (root $S_54310_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicig : $@convention(method) (Int, S_54310_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed S_54310_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) + // CHECK: keypath $KeyPath, (root $S_54310; gettable_property $(), id @$s29keypath_dynamic_member_lookup7S_54310V0B6Memberys7KeyPathCyAA12S_54310_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, S_54310) -> (), getter @$s29keypath_dynamic_member_lookup7S_54310V0B6Memberys7KeyPathCyAA12S_54310_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed S_54310, UnsafeRawPointer) -> @out (), indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_SUB_KP]]) + _ = \S_54310.[5] - // SR-15249: Make sure we can handle IUO unwraps in both the inner and outer - // key-paths. + // https://github.com/apple/swift/issues/57571: Make sure we can handle IUO + // unwraps in both the inner and outer key paths. - // CHECK: [[INNER_KP2:%[0-9]+]] = keypath $KeyPath, (root $SR_11893_Base; stored_property #SR_11893_Base.i : $Optional; optional_force : $Int) - // CHECK: keypath $KeyPath>, (root $SR_15249; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup8SR_15249V0B6MemberSiSgs7KeyPathCyAA0E11_11893_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, SR_15249) -> Optional, getter @$s29keypath_dynamic_member_lookup8SR_15249V0B6MemberSiSgs7KeyPathCyAA0E11_11893_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed SR_15249, UnsafeRawPointer) -> @out Optional, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_KP2]]) - _ = \SR_15249.i + // CHECK: [[INNER_KP2:%[0-9]+]] = keypath $KeyPath, (root $S_54310_Base; stored_property #S_54310_Base.i : $Optional; optional_force : $Int) + // CHECK: keypath $KeyPath>, (root $S_57571; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup7S_57571V0B6MemberSiSgs7KeyPathCyAA12S_54310_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, S_57571) -> Optional, getter @$s29keypath_dynamic_member_lookup7S_57571V0B6MemberSiSgs7KeyPathCyAA12S_54310_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed S_57571, UnsafeRawPointer) -> @out Optional, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_KP2]]) + _ = \S_57571.i - // CHECK: [[INNER_KP3:%[0-9]+]] = keypath $KeyPath, (root $SR_11893_Base; stored_property #SR_11893_Base.i : $Optional; optional_force : $Int) - // CHECK: keypath $KeyPath, (root $SR_15249; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup8SR_15249V0B6MemberSiSgs7KeyPathCyAA0E11_11893_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, SR_15249) -> Optional, getter @$s29keypath_dynamic_member_lookup8SR_15249V0B6MemberSiSgs7KeyPathCyAA0E11_11893_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed SR_15249, UnsafeRawPointer) -> @out Optional, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) ([[INNER_KP3]]) - let _: KeyPath = \SR_15249.i + // CHECK: [[INNER_KP3:%[0-9]+]] = keypath $KeyPath, (root $S_54310_Base; stored_property #S_54310_Base.i : $Optional; optional_force : $Int) + // CHECK: keypath $KeyPath, (root $S_57571; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup7S_57571V0B6MemberSiSgs7KeyPathCyAA12S_54310_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, S_57571) -> Optional, getter @$s29keypath_dynamic_member_lookup7S_57571V0B6MemberSiSgs7KeyPathCyAA12S_54310_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed S_57571, UnsafeRawPointer) -> @out Optional, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) ([[INNER_KP3]]) + let _: KeyPath = \S_57571.i - // CHECK: [[INNER_KP4:%[0-9]+]] = keypath $KeyPath, (root $SR_11893_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicig : $@convention(method) (Int, SR_11893_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed SR_11893_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) - // CHECK: keypath $KeyPath>, (root $SR_15249; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup8SR_15249V0B6MemberSiSgs7KeyPathCyAA0E11_11893_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, SR_15249) -> Optional, getter @$s29keypath_dynamic_member_lookup8SR_15249V0B6MemberSiSgs7KeyPathCyAA0E11_11893_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed SR_15249, UnsafeRawPointer) -> @out Optional, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_KP4]]) - _ = \SR_15249.[0] + // CHECK: [[INNER_KP4:%[0-9]+]] = keypath $KeyPath, (root $S_54310_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicig : $@convention(method) (Int, S_54310_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed S_54310_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) + // CHECK: keypath $KeyPath>, (root $S_57571; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup7S_57571V0B6MemberSiSgs7KeyPathCyAA12S_54310_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, S_57571) -> Optional, getter @$s29keypath_dynamic_member_lookup7S_57571V0B6MemberSiSgs7KeyPathCyAA12S_54310_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed S_57571, UnsafeRawPointer) -> @out Optional, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_KP4]]) + _ = \S_57571.[0] - // CHECK: [[INNER_KP5:%[0-9]+]] = keypath $KeyPath, (root $SR_11893_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicig : $@convention(method) (Int, SR_11893_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed SR_11893_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) - // CHECK: keypath $KeyPath, (root $SR_15249; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup8SR_15249V0B6MemberSiSgs7KeyPathCyAA0E11_11893_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, SR_15249) -> Optional, getter @$s29keypath_dynamic_member_lookup8SR_15249V0B6MemberSiSgs7KeyPathCyAA0E11_11893_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed SR_15249, UnsafeRawPointer) -> @out Optional, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup13SR_11893_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) ([[INNER_KP5]]) - let _: KeyPath = \SR_15249.[0] + // CHECK: [[INNER_KP5:%[0-9]+]] = keypath $KeyPath, (root $S_54310_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicig : $@convention(method) (Int, S_54310_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed S_54310_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) + // CHECK: keypath $KeyPath, (root $S_57571; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup7S_57571V0B6MemberSiSgs7KeyPathCyAA12S_54310_BaseVSiG_tcig : $@convention(method) (@guaranteed KeyPath, S_57571) -> Optional, getter @$s29keypath_dynamic_member_lookup7S_57571V0B6MemberSiSgs7KeyPathCyAA12S_54310_BaseVSiG_tcipACTK : $@convention(thin) (@in_guaranteed S_57571, UnsafeRawPointer) -> @out Optional, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup12S_54310_BaseVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) ([[INNER_KP5]]) + let _: KeyPath = \S_57571.[0] - // CHECK: [[INNER_KP6:%[0-9]+]] = keypath $KeyPath, (root $SR_11893_Base; stored_property #SR_11893_Base.i : $Optional; optional_force : $Int) - // CHECK: [[YI_OPT:%[0-9]+]] = apply {{%[0-9]+}}([[INNER_KP6]], {{%[0-9]+}}) : $@convention(method) (@guaranteed KeyPath, SR_15249) -> Optional + // CHECK: [[INNER_KP6:%[0-9]+]] = keypath $KeyPath, (root $S_54310_Base; stored_property #S_54310_Base.i : $Optional; optional_force : $Int) + // CHECK: [[YI_OPT:%[0-9]+]] = apply {{%[0-9]+}}([[INNER_KP6]], {{%[0-9]+}}) : $@convention(method) (@guaranteed KeyPath, S_57571) -> Optional // CHECK: switch_enum [[YI_OPT]] // CHECK: unreachable // CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : $Int) let _: Int = y.i - // CHECK: [[INNER_KP7:%[0-9]+]] = keypath $KeyPath, (root $SR_11893_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicig : $@convention(method) (Int, SR_11893_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup13SR_11893_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed SR_11893_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) - // CHECK: [[Y0_OPT:%[0-9]+]] = apply {{%[0-9]+}}([[INNER_KP7]], {{%[0-9]+}}) : $@convention(method) (@guaranteed KeyPath, SR_15249) -> Optional + // CHECK: [[INNER_KP7:%[0-9]+]] = keypath $KeyPath, (root $S_54310_Base; gettable_property $Optional, id @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicig : $@convention(method) (Int, S_54310_Base) -> Optional, getter @$s29keypath_dynamic_member_lookup12S_54310_BaseVySiSgSicipACTK : $@convention(thin) (@in_guaranteed S_54310_Base, UnsafeRawPointer) -> @out Optional, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int; optional_force : $Int) + // CHECK: [[Y0_OPT:%[0-9]+]] = apply {{%[0-9]+}}([[INNER_KP7]], {{%[0-9]+}}) : $@convention(method) (@guaranteed KeyPath, S_57571) -> Optional // CHECK: switch_enum [[Y0_OPT]] // CHECK: unreachable // CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : $Int) let _: Int = y[0] } -// SR-11896: Make sure the outer key path reflects the mutability of the 'dynamicMember:' subscript. -struct SR_11896_Base { +// https://github.com/apple/swift/issues/54313 +// Make sure the outer key path reflects the mutability of the +// 'dynamicMember:' subscript. + +struct S_54313_Base { var mutable: Int let immutable: Int } @dynamicMemberLookup -struct SR_11896_Mutable { - subscript(dynamicMember kp: KeyPath) -> Int { +struct S_54313_Mutable { + subscript(dynamicMember kp: KeyPath) -> Int { get { 5 } set {} } } @dynamicMemberLookup -struct SR_11896_Immutable { - subscript(dynamicMember kp: KeyPath) -> Int { +struct S_54313_Immutable { + subscript(dynamicMember kp: KeyPath) -> Int { get { 5 } } } // CHECK-LABEL: sil hidden @$s29keypath_dynamic_member_lookup21testKeyPathMutabilityyyF : $@convention(thin) () -> () func testKeyPathMutability() { - // CHECK: keypath $KeyPath, (root $SR_11896_Base; stored_property #SR_11896_Base.mutable : $Int) - // CHECK: keypath $WritableKeyPath, (root $SR_11896_Mutable; settable_property $Int - _ = \SR_11896_Mutable.mutable + // CHECK: keypath $KeyPath, (root $S_54313_Base; stored_property #S_54313_Base.mutable : $Int) + // CHECK: keypath $WritableKeyPath, (root $S_54313_Mutable; settable_property $Int + _ = \S_54313_Mutable.mutable - // CHECK: keypath $KeyPath, (root $SR_11896_Base; stored_property #SR_11896_Base.immutable : $Int) - // CHECK: keypath $WritableKeyPath, (root $SR_11896_Mutable; settable_property $Int - _ = \SR_11896_Mutable.immutable + // CHECK: keypath $KeyPath, (root $S_54313_Base; stored_property #S_54313_Base.immutable : $Int) + // CHECK: keypath $WritableKeyPath, (root $S_54313_Mutable; settable_property $Int + _ = \S_54313_Mutable.immutable - // CHECK: keypath $KeyPath, (root $SR_11896_Base; stored_property #SR_11896_Base.mutable : $Int) - // CHECK: keypath $KeyPath, (root $SR_11896_Immutable; gettable_property $Int - _ = \SR_11896_Immutable.mutable + // CHECK: keypath $KeyPath, (root $S_54313_Base; stored_property #S_54313_Base.mutable : $Int) + // CHECK: keypath $KeyPath, (root $S_54313_Immutable; gettable_property $Int + _ = \S_54313_Immutable.mutable - // CHECK: keypath $KeyPath, (root $SR_11896_Base; stored_property #SR_11896_Base.immutable : $Int) - // CHECK: keypath $KeyPath, (root $SR_11896_Immutable; gettable_property $Int - _ = \SR_11896_Immutable.immutable + // CHECK: keypath $KeyPath, (root $S_54313_Base; stored_property #S_54313_Base.immutable : $Int) + // CHECK: keypath $KeyPath, (root $S_54313_Immutable; gettable_property $Int + _ = \S_54313_Immutable.immutable } -// SR-11933: Make sure we properly handle default arguments. +// https://github.com/apple/swift/issues/54352 +// Make sure we properly handle default arguments. + struct HasDefaultedSubscript { subscript(_ x: Int = 0) -> Int { x } } @dynamicMemberLookup -struct SR_11933 { +struct S_54352 { subscript(dynamicMember kp: KeyPath) -> Int { 0 } } -// CHECK-LABEL: sil hidden @$s29keypath_dynamic_member_lookup28testDynamicMemberWithDefaultyyAA8SR_11933VF : $@convention(thin) (SR_11933) -> () -func testDynamicMemberWithDefault(_ x: SR_11933) { +// CHECK-LABEL: sil hidden @$s29keypath_dynamic_member_lookup28testDynamicMemberWithDefaultyyAA7S_54352VF : $@convention(thin) (S_54352) -> () +func testDynamicMemberWithDefault(_ x: S_54352) { // CHECK: [[DEF_FN:%[0-9]+]] = function_ref @$s29keypath_dynamic_member_lookup21HasDefaultedSubscriptVyS2icipfA_ : $@convention(thin) () -> Int // CHECK: [[DEF_ARG:%[0-9]+]] = apply [[DEF_FN]]() // CHECK: [[KP:%[0-9]+]] = keypath $KeyPath, (root $HasDefaultedSubscript; gettable_property $Int, id @$s29keypath_dynamic_member_lookup21HasDefaultedSubscriptVyS2icig : $@convention(method) (Int, HasDefaultedSubscript) -> Int, getter @$s29keypath_dynamic_member_lookup21HasDefaultedSubscriptVyS2icipACTK : $@convention(thin) (@in_guaranteed HasDefaultedSubscript, UnsafeRawPointer) -> @out Int, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[DEF_ARG]]) - // CHECK: [[SUB_GET:%[0-9]+]] = function_ref @$s29keypath_dynamic_member_lookup8SR_11933V0B6MemberSis7KeyPathCyAA21HasDefaultedSubscriptVSiG_tcig : $@convention(method) (@guaranteed KeyPath, SR_11933) -> Int + // CHECK: [[SUB_GET:%[0-9]+]] = function_ref @$s29keypath_dynamic_member_lookup7S_54352V0B6MemberSis7KeyPathCyAA21HasDefaultedSubscriptVSiG_tcig : $@convention(method) (@guaranteed KeyPath, S_54352) -> Int // CHECK: apply [[SUB_GET]]([[KP]], {{%[0-9]+}}) _ = x[] // CHECK: [[DEF_FN:%[0-9]+]] = function_ref @$s29keypath_dynamic_member_lookup21HasDefaultedSubscriptVyS2icipfA_ : $@convention(thin) () -> Int // CHECK: [[DEF_ARG:%[0-9]+]] = apply [[DEF_FN]]() // CHECK: [[INNER_KP:%[0-9]+]] = keypath $KeyPath, (root $HasDefaultedSubscript; gettable_property $Int, id @$s29keypath_dynamic_member_lookup21HasDefaultedSubscriptVyS2icig : $@convention(method) (Int, HasDefaultedSubscript) -> Int, getter @$s29keypath_dynamic_member_lookup21HasDefaultedSubscriptVyS2icipACTK : $@convention(thin) (@in_guaranteed HasDefaultedSubscript, UnsafeRawPointer) -> @out Int, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[DEF_ARG]]) - // CHECK: [[OUTER_KP:%[0-9]+]] = keypath $KeyPath, (root $SR_11933; gettable_property $Int, id @$s29keypath_dynamic_member_lookup8SR_11933V0B6MemberSis7KeyPathCyAA21HasDefaultedSubscriptVSiG_tcig : $@convention(method) (@guaranteed KeyPath, SR_11933) -> Int, getter @$s29keypath_dynamic_member_lookup8SR_11933V0B6MemberSis7KeyPathCyAA21HasDefaultedSubscriptVSiG_tcipACTK : $@convention(thin) (@in_guaranteed SR_11933, UnsafeRawPointer) -> @out Int, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup21HasDefaultedSubscriptVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup21HasDefaultedSubscriptVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_KP]]) - _ = \SR_11933.[] + // CHECK: [[OUTER_KP:%[0-9]+]] = keypath $KeyPath, (root $S_54352; gettable_property $Int, id @$s29keypath_dynamic_member_lookup7S_54352V0B6MemberSis7KeyPathCyAA21HasDefaultedSubscriptVSiG_tcig : $@convention(method) (@guaranteed KeyPath, S_54352) -> Int, getter @$s29keypath_dynamic_member_lookup7S_54352V0B6MemberSis7KeyPathCyAA21HasDefaultedSubscriptVSiG_tcipACTK : $@convention(thin) (@in_guaranteed S_54352, UnsafeRawPointer) -> @out Int, indices [%$0 : $KeyPath : $KeyPath], indices_equals @$ss7KeyPathCy29keypath_dynamic_member_lookup21HasDefaultedSubscriptVSiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$ss7KeyPathCy29keypath_dynamic_member_lookup21HasDefaultedSubscriptVSiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[INNER_KP]]) + _ = \S_54352.[] } -// SR-11743 - KeyPath Dynamic Member Lookup crash +// https://github.com/apple/swift/issues/54150 +// Key path dynamic member lookup crash + @dynamicMemberLookup -protocol SR_11743_P { +protocol P_54150 { subscript(dynamicMember member: KeyPath) -> Any { get } } -extension SR_11743_P { +extension P_54150 { subscript(dynamicMember member: KeyPath) -> Any { self[keyPath: member] // Ok // CHECK: function_ref @swift_getAtKeyPath @@ -537,12 +549,12 @@ extension SR_11743_P { } @dynamicMemberLookup -struct SR_11743_Struct { +struct S_54150 { let value: Int subscript(dynamicMember member: KeyPath) -> T { return self[keyPath: member] // CHECK: function_ref @swift_getAtKeyPath - // CHECK-NEXT: apply %{{.*}}({{.*}}) + // CHECK-NEXT: apply %{{.*}}({{.*}}) } } From e51ef47b37226520e394c8169a5ff0f76b095b95 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 19 Aug 2022 06:34:46 +0300 Subject: [PATCH 197/491] Gardening: Migrate test suite to GH issues: Constraints (5/5) --- test/Constraints/casts.swift | 276 +++++++++++++++-------------- test/Constraints/diagnostics.swift | 250 ++++++++++++++------------ 2 files changed, 280 insertions(+), 246 deletions(-) diff --git a/test/Constraints/casts.swift b/test/Constraints/casts.swift index 4038c2cc92b8a..3727987a127b4 100644 --- a/test/Constraints/casts.swift +++ b/test/Constraints/casts.swift @@ -245,7 +245,8 @@ func ^^^ (lhs: T?, rhs: @autoclosure () -> T?) -> T? { lhs! } func ohno(_ x: T) -> T? { nil } -// SR-12369: Make sure we don't drop the coercion constraint. +// https://github.com/apple/swift/issues/54803 +// Make sure we don't drop the coercion constraint. func test_coercions_with_overloaded_operator(str: String, optStr: String?, veryOptString: String????) { _ = (str ?? "") as String // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} _ = (optStr ?? "") as String @@ -357,15 +358,6 @@ func test_compatibility_coercions(_ arr: [Int], _ optArr: [Int]?, _ dict: [Strin _ = [i: stringAnyDict] as! [String: Any] } -// SR-13088 -protocol JSON { } -protocol JSONLeaf: JSON {} -extension Int: JSONLeaf { } -extension Array: JSON where Element: JSON { } - -protocol SR13035Error: Error {} -class ChildError: SR13035Error {} - protocol AnyC { func foo() } @@ -393,48 +385,40 @@ enum ConcreteA: EventA { } } -protocol ProtocolP1 {} -protocol ProtocolQ1 {} -typealias Composition = ProtocolP1 & ProtocolQ1 - -protocol ProtocolP {} -protocol ProtocolQ {} - -class ConcreteP: ProtocolP {} -class ConcreteQ: ProtocolQ {} -class ConcretePQ: ProtocolP, ProtocolQ {} -class ConcreteCPQ: ConcreteP, ProtocolQ {} +protocol JSON { } +protocol JSONLeaf: JSON {} +extension Int: JSONLeaf { } +extension Array: JSON where Element: JSON { } -class ConcreteP1: ProtocolP1 {} -class ConcretePQ1: ProtocolP1, ProtocolQ1 {} +protocol MyError: Error {} +class MyErrorClass: MyError {} -class ConcretePPQ1: ProtocolP, ProtocolP1, ProtocolQ1 {} -class NotConforms {} -struct StructNotComforms {} -final class NotConformsFinal {} +// https://github.com/apple/swift/issues/55534 (Umbrella issue) +func test_always_fail_casts() { -func tests_SR13088_false_positive_always_fail_casts() { - // SR-13081 + // https://github.com/apple/swift/issues/55527 let x: JSON = [4] // [4] _ = x as? [Any] // Ok - // SR-13035 - func SR13035(_ child: Result, _: Result) { - let _ = child as? Result // Ok - } - - func SR13035_1(_ child: Result, parent: Result) { - _ = child as? Result // Ok + // https://github.com/apple/swift/issues/55481 + func f_55481( + _ parent: Result, + _ childGeneric: Result, + _ childConcrete: Result + ) { + _ = childConcrete as? Result // Ok + _ = childGeneric as? Result // Ok _ = parent as? Result // OK } - // SR-11434 and SR-12321 + // https://github.com/apple/swift/issues/53835 + // https://github.com/apple/swift/issues/54751 func encodable(_ value: Encodable) { _ = value as! [String : Encodable] // Ok _ = value as? [String: Encodable] // Ok } - // SR-13025 + // https://github.com/apple/swift/issues/55470 func coordinate(_ event: AnyEvent, from c: AnyC) { switch (event, c) { case let container as Container: // OK @@ -444,7 +428,7 @@ func tests_SR13088_false_positive_always_fail_casts() { } } - // SR-7187 + // https://github.com/apple/swift/issues/49735 let a: [Any] = [String?.some("hello") as Any, String?.none as Any] let b: [AnyObject] = [String?.some("hello") as AnyObject, String?.none as AnyObject] @@ -453,7 +437,7 @@ func tests_SR13088_false_positive_always_fail_casts() { _ = b is [String?] // Ok _ = b as? [String?] as AnyObject // OK - // SR-6192 + // https://github.com/apple/swift/issues/48744 let items = [String]() let dict = [String: Any]() let set = Set() @@ -472,6 +456,26 @@ func tests_SR13088_false_positive_always_fail_casts() { } +protocol ProtocolP1 {} +protocol ProtocolQ1 {} +typealias Composition = ProtocolP1 & ProtocolQ1 + +protocol ProtocolP {} +protocol ProtocolQ {} + +class ConcreteP: ProtocolP {} +class ConcreteQ: ProtocolQ {} +class ConcretePQ: ProtocolP, ProtocolQ {} +class ConcreteCPQ: ConcreteP, ProtocolQ {} + +class ConcreteP1: ProtocolP1 {} +class ConcretePQ1: ProtocolP1, ProtocolQ1 {} + +class ConcretePPQ1: ProtocolP, ProtocolP1, ProtocolQ1 {} +class NotConforms {} +struct StructNotComforms {} +final class NotConformsFinal {} + // Protocol composition func protocol_composition(_ c: ProtocolP & ProtocolQ, _ c1: ProtocolP & Composition) { _ = c as? ConcretePQ // Ok @@ -489,64 +493,67 @@ func protocol_composition(_ c: ProtocolP & ProtocolQ, _ c1: ProtocolP & Composit _ = c1 as? NotConformsFinal // expected-warning {{cast from 'any ProtocolP & Composition' (aka 'any ProtocolP & ProtocolP1 & ProtocolQ1') to unrelated type 'NotConformsFinal' always fails}} } -// SR-13899 -class SR13899_Base {} -class SR13899_Derived: SR13899_Base {} - -protocol SR13899_P {} -class SR13899_A: SR13899_P {} - -typealias DA = SR13899_Derived -typealias BA = SR13899_Base -typealias ClosureType = (SR13899_Derived) -> Void - -let blockp = { (_: SR13899_A) in } -let block = { (_: SR13899_Base) in } -let derived = { (_: SR13899_Derived) in } - -let blockalias = { (_: BA) in } -let derivedalias = { (_: DA) in } - -let _ = block is ClosureType // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to 'ClosureType' (aka '(SR13899_Derived) -> ()') is not supported; 'is' test always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-17=as}} -let _ = blockalias is (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(SR13899_Base) -> ()') to '(SR13899_Derived) -> Void' is not supported; 'is' test always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{20-22=as}} -let _ = block is (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; 'is' test always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-17=as}} -let _ = block is (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; 'is' test always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-17=as}} - -let _ = block as! ClosureType // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to 'ClosureType' (aka '(SR13899_Derived) -> ()') is not supported; cast always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}} -let _ = blockalias as! (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(SR13899_Base) -> ()') to '(SR13899_Derived) -> Void' is not supported; cast always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{20-23=as}} -let _ = block as! (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; cast always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}} -let _ = block as! (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; cast always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}} - -let _ = block as? ClosureType // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to 'ClosureType' (aka '(SR13899_Derived) -> ()') is not supported; cast always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}} -let _ = blockalias as? (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(SR13899_Base) -> ()') to '(SR13899_Derived) -> Void' is not supported; cast always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{20-23=as}} -let _ = block as? (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; cast always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}} -let _ = block as? (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; cast always fails}} -// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}} - - -let _ = derived is (SR13899_Base) -> Void // expected-warning{{always fails}} -let _ = blockp is (SR13899_P) -> Void // expected-warning{{always fails}} - -// Types are trivially equal. -let _ = block is (SR13899_Base) -> Void // expected-warning{{'is' test is always true}} -let _ = block is (SR13899_Base) throws -> Void // expected-warning{{'is' test is always true}} -let _ = derivedalias is (SR13899_Derived) -> Void // expected-warning{{'is' test is always true}} -let _ = derivedalias is (SR13899_Derived) throws -> Void // expected-warning{{'is' test is always true}} -let _ = derived is (SR13899_Derived) -> Void // expected-warning{{'is' test is always true}} -let _ = derived is (SR13899_Derived) throws -> Void // expected-warning{{'is' test is always true}} -let _ = blockp is (SR13899_A) -> Void //expected-warning{{'is' test is always true}} -let _ = blockp is (SR13899_A) throws -> Void //expected-warning{{'is' test is always true}} +// https://github.com/apple/swift/issues/56297 + +class C1_56297_Base {} +class C1_56297_Sub: C1_56297_Base {} + +protocol P_56297 {} +class C2_56297: P_56297 {} + +do { + typealias DA = C1_56297_Sub + typealias BA = C1_56297_Base + typealias ClosureType = (C1_56297_Sub) -> Void + + let blockp = { (_: C2_56297) in } + let block = { (_: C1_56297_Base) in } + let derived = { (_: C1_56297_Sub) in } + + let blockalias = { (_: BA) in } + let derivedalias = { (_: DA) in } + + let _ = block is ClosureType // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to 'ClosureType' (aka '(C1_56297_Sub) -> ()') is not supported; 'is' test always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-19=as}} + let _ = blockalias is (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(C1_56297_Base) -> ()') to '(C1_56297_Sub) -> Void' is not supported; 'is' test always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{22-24=as}} + let _ = block is (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to '(C1_56297_Sub) -> Void' is not supported; 'is' test always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-19=as}} + let _ = block is (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to '(C1_56297_Sub) -> Void' is not supported; 'is' test always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-19=as}} + + let _ = block as! ClosureType // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to 'ClosureType' (aka '(C1_56297_Sub) -> ()') is not supported; cast always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-20=as}} + let _ = blockalias as! (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(C1_56297_Base) -> ()') to '(C1_56297_Sub) -> Void' is not supported; cast always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{22-25=as}} + let _ = block as! (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to '(C1_56297_Sub) -> Void' is not supported; cast always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-20=as}} + let _ = block as! (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to '(C1_56297_Sub) -> Void' is not supported; cast always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-20=as}} + + let _ = block as? ClosureType // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to 'ClosureType' (aka '(C1_56297_Sub) -> ()') is not supported; cast always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-20=as}} + let _ = blockalias as? (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(C1_56297_Base) -> ()') to '(C1_56297_Sub) -> Void' is not supported; cast always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{22-25=as}} + let _ = block as? (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to '(C1_56297_Sub) -> Void' is not supported; cast always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-20=as}} + let _ = block as? (C1_56297_Sub) -> Void // expected-warning{{runtime conversion from '(C1_56297_Base) -> ()' to '(C1_56297_Sub) -> Void' is not supported; cast always fails}} + // expected-note@-1 {{consider using 'as' coercion instead}} {{17-20=as}} + + + let _ = derived is (C1_56297_Base) -> Void // expected-warning{{always fails}} + let _ = blockp is (P_56297) -> Void // expected-warning{{always fails}} + + // Types are trivially equal. + let _ = block is (C1_56297_Base) -> Void // expected-warning{{'is' test is always true}} + let _ = block is (C1_56297_Base) throws -> Void // expected-warning{{'is' test is always true}} + let _ = derivedalias is (C1_56297_Sub) -> Void // expected-warning{{'is' test is always true}} + let _ = derivedalias is (C1_56297_Sub) throws -> Void // expected-warning{{'is' test is always true}} + let _ = derived is (C1_56297_Sub) -> Void // expected-warning{{'is' test is always true}} + let _ = derived is (C1_56297_Sub) throws -> Void // expected-warning{{'is' test is always true}} + let _ = blockp is (C2_56297) -> Void //expected-warning{{'is' test is always true}} + let _ = blockp is (C2_56297) throws -> Void //expected-warning{{'is' test is always true}} +} protocol PP1 { } protocol PP2: PP1 { } @@ -554,7 +561,8 @@ extension Optional: PP1 where Wrapped == PP2 { } nil is PP1 // expected-error {{'nil' requires a contextual type}} -// SR-15039 +// https://github.com/apple/swift/issues/57366 + enum ChangeType { case initial(T) case delta(previous: T, next: T) @@ -568,7 +576,8 @@ extension ChangeType where T == String? { var bar: String? { self.delta?.next } } -// SR-15038 +// https://github.com/apple/swift/issues/57365 + protocol ExperimentDeserializable { static func deserializeExperiment(_ value: Any) -> Self? } @@ -633,45 +642,48 @@ func decodeStringOrIntDictionary() -> [Int: T] { } -// SR-15281 -struct SR15281_A { } -struct SR15281_B { - init(a: SR15281_A) { } -} +// https://github.com/apple/swift/issues/57603 +do { + struct S1 { } + struct S2 { + init(a: S1) { } + } -struct SR15281_S { - var a: SR15281_A? = SR15281_A() + struct S3 { + var a: S1? = S1() - var b: SR15281_B { - a.flatMap(SR15281_B.init(a:)) // expected-error{{cannot convert return expression of type 'SR15281_B?' to return type 'SR15281_B'}} {{34-34=!}} - } + var b: S2 { + a.flatMap(S2.init(a:)) + // expected-error@-1 {{cannot convert return expression of type 'S2?' to return type 'S2'}} {{29-29=!}} + } - var b1: SR15281_B { - a.flatMap(SR15281_B.init(a:)) as! SR15281_B - // expected-warning@-1 {{forced cast from 'SR15281_B?' to 'SR15281_B' only unwraps optionals; did you mean to use '!'?}} {{34-34=!}} {{34-48=}} + var b1: S2 { + a.flatMap(S2.init(a:)) as! S2 + // expected-warning@-1 {{forced cast from 'S2?' to 'S2' only unwraps optionals; did you mean to use '!'?}} {{29-29=!}} {{29-36=}} + } } -} -class SR15281_AC {} -class SR15281_BC { - init(a: SR15281_AC) { } -} -class SR15281_CC: SR15281_BC {} + class C1 {} + class C2 { + init(a: C1) { } + } + class C3: C2 {} -struct SR15281_SC { - var a: SR15281_AC? = SR15281_AC() + struct S4 { + var a: C1? = C1() - var b: SR15281_BC { - a.flatMap(SR15281_BC.init(a:)) // expected-error{{cannot convert return expression of type 'SR15281_BC?' to return type 'SR15281_BC'}} {{35-35=!}} - } + var b: C2 { + a.flatMap(C2.init(a:)) // expected-error{{cannot convert return expression of type 'C2?' to return type 'C2'}} {{29-29=!}} + } - var c: SR15281_BC { - a.flatMap(SR15281_CC.init(a:)) // expected-error{{cannot convert return expression of type 'SR15281_CC?' to return type 'SR15281_BC'}} {{35-35=!}} + var c: C2 { + a.flatMap(C3.init(a:)) // expected-error{{cannot convert return expression of type 'C3?' to return type 'C2'}} {{29-29=!}} + } } } -// SR-15562 -func test_SR_15562() { +// https://github.com/apple/swift/issues/57865 +do { let foo: [Int: Int] = [:] let bar = [1, 2, 3, 4] @@ -681,17 +693,17 @@ func test_SR_15562() { } } -// SR-16058 +// https://github.com/apple/swift/issues/58319 extension Dictionary { - func SR16058(_: Key) -> Value?? { nil } + func f_58319(_: Key) -> Value?? { nil } } -func SR_16058_tests() { +do { let dict: [Int: String?] = [:] let foo: Int? = 1 let _: String? = foo.flatMap { dict[$0] } as? String // OK // More than one optionality wrapping - let _: String? = foo.flatMap { dict.SR16058(_: $0) } as? String // OK + let _: String? = foo.flatMap { dict.f_58319(_: $0) } as? String // OK } // https://github.com/apple/swift/issues/59405 diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index 95aea18158a33..e725725d3052a 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -170,7 +170,8 @@ func rdar20142523() { // Bad diagnostic for invalid method call in boolean expression: (_, ExpressibleByIntegerLiteral)' is not convertible to 'ExpressibleByIntegerLiteral func rdar21080030() { var s = "Hello" - // SR-7599: This should be `cannot_call_non_function_value` + // https://github.com/apple/swift/issues/50141 + // This should be 'cannot_call_non_function_value'. if s.count() == 0 {} // expected-error{{cannot call value of non-function type 'Int'}} {{13-15=}} } @@ -337,7 +338,7 @@ variadic(0, [1,2,3,], 4) // expected-error {{cannot pass array of type '[Int]' a variadic(arrayWithOtherEltType) // expected-error {{cannot convert value of type '[String]' to expected argument type 'Int'}} variadic(1, arrayWithOtherEltType) // expected-error {{cannot convert value of type '[String]' to expected argument type 'Int'}} -// FIXME: SR-11104 +// FIXME: https://github.com/apple/swift/issues/53499 variadic(["hello", "world"]) // expected-error 2 {{cannot convert value of type 'String' to expected element type 'Int'}} // expected-error@-1 {{cannot pass array of type '[Int]' as variadic arguments of type 'Int'}} // expected-note@-2 {{remove brackets to pass array elements directly}} @@ -738,9 +739,10 @@ func r21523291(_ bytes : UnsafeMutablePointer) { } -// SR-1594: Wrong error description when using === on non-class types -class SR1594 { - func sr1594(bytes : UnsafeMutablePointer, _ i : Int?) { +// https://github.com/apple/swift/issues/44203 +// Wrong error description when using '===' on non-class types +class C_44203 { + func f(bytes : UnsafeMutablePointer, _ i : Int?) { _ = (i === nil) // expected-error {{value of type 'Int?' cannot be compared by reference; did you mean to compare by value?}} {{12-15===}} _ = (bytes === nil) // expected-error {{type 'UnsafeMutablePointer' is not optional, value can never be nil}} _ = (self === nil) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' always returns false}} @@ -819,15 +821,18 @@ func rdar24202058(a : Int) { // expected-note@-2 {{did you mean to add a return type?}} } -// SR-1752: Warning about unused result with ternary operator - -struct SR1752 { - func foo() {} -} +// https://github.com/apple/swift/issues/44361 +// Warning about unused result with ternary operator +do { + struct S { + func foo() {} + } -let sr1752: SR1752? + let x: S? -true ? nil : sr1752?.foo() // don't generate a warning about unused result since foo returns Void + // Don't generate a warning about unused result since 'foo' returns 'Void'. + true ? nil : x?.foo() +} // Make sure RawRepresentable fix-its don't crash in the presence of type variables class NSCache { @@ -844,29 +849,31 @@ func valueForKey(_ key: K) -> CacheValue? { return cache.object(forKey: key)?.value // expected-error {{no exact matches in reference to instance method 'value'}} } -// SR-1255 -func foo1255_1() { - return true || false - // expected-error@-1 {{unexpected non-void return value in void function}} - // expected-note@-2 {{did you mean to add a return type?}} -} -func foo1255_2() -> Int { - return true || false // expected-error {{cannot convert return expression of type 'Bool' to return type 'Int'}} -} - -// Diagnostic message for initialization with binary operations as right side -let foo1255_3: String = 1 + 2 + 3 // expected-error {{cannot convert value of type 'Int' to specified type 'String'}} -let foo1255_4: Dictionary = ["hello": 1 + 2] // expected-error {{cannot convert value of type 'Int' to expected dictionary value type 'String'}} -let foo1255_5: Dictionary = [(1 + 2): "world"] // expected-error {{cannot convert value of type 'Int' to expected dictionary key type 'String'}} -let foo1255_6: [String] = [1 + 2 + 3] // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}} +// https://github.com/apple/swift/issues/43863 +do { + func f1() { + return true || false + // expected-error@-1 {{unexpected non-void return value in void function}} + // expected-note@-2 {{did you mean to add a return type?}} + } + func f2() -> Int { + return true || false // expected-error {{cannot convert return expression of type 'Bool' to return type 'Int'}} + } -// SR-2208 -struct Foo2208 { - func bar(value: UInt) {} + // Diagnostic message for initialization with binary operations as right side. + let _: String = 1 + 2 + 3 // expected-error {{cannot convert value of type 'Int' to specified type 'String'}} + let _: Dictionary = ["hello": 1 + 2] // expected-error {{cannot convert value of type 'Int' to expected dictionary value type 'String'}} + let _: Dictionary = [(1 + 2): "world"] // expected-error {{cannot convert value of type 'Int' to expected dictionary key type 'String'}} + let _: [String] = [1 + 2 + 3] // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}} } -func test2208() { - let foo = Foo2208() +// https://github.com/apple/swift/issues/44815 +do { + struct S { + func bar(value: UInt) {} + } + + let foo = S() let a: Int = 1 let b: Int = 2 let result = a / b @@ -875,41 +882,43 @@ func test2208() { foo.bar(value: UInt(result)) // Ok } -// SR-2164: Erroneous diagnostic when unable to infer generic type +// https://github.com/apple/swift/issues/44772 +// Erroneous diagnostic when unable to infer generic type +do { + struct S { // expected-note 4 {{'B' declared as parameter to type 'S'}} expected-note 2 {{'A' declared as parameter to type 'S'}} expected-note * {{generic type 'S' declared here}} + init(a: A) {} + init(b: B) {} + init(c: Int) {} + init(_ d: A) {} + init(e: A?) {} + } -struct SR_2164 { // expected-note 4 {{'B' declared as parameter to type 'SR_2164'}} expected-note 2 {{'A' declared as parameter to type 'SR_2164'}} expected-note * {{generic type 'SR_2164' declared here}} - init(a: A) {} - init(b: B) {} - init(c: Int) {} - init(_ d: A) {} - init(e: A?) {} -} + struct S_Array { // expected-note {{'B' declared as parameter to type 'S_Array'}} expected-note * {{generic type 'S_Array' declared here}} + init(_ a: [A]) {} + } -struct SR_2164_Array { // expected-note {{'B' declared as parameter to type 'SR_2164_Array'}} expected-note * {{generic type 'SR_2164_Array' declared here}} - init(_ a: [A]) {} -} + struct S_Dict { // expected-note {{'B' declared as parameter to type 'S_Dict'}} expected-note * {{generic type 'S_Dict' declared here}} + init(a: [A: Double]) {} + } -struct SR_2164_Dict { // expected-note {{'B' declared as parameter to type 'SR_2164_Dict'}} expected-note * {{generic type 'SR_2164_Dict' declared here}} - init(a: [A: Double]) {} + S(a: 0) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} + S(b: 1) // expected-error {{generic parameter 'A' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} + S(c: 2) + // expected-error@-1 {{generic parameter 'A' could not be inferred}} + // expected-error@-2 {{generic parameter 'B' could not be inferred}} + // expected-note@-3 {{explicitly specify the generic arguments to fix this issue}} {{4-4=}} + S(3) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} + S_Array([4]) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} + S(e: 5) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} + S_Dict(a: ["pi": 3.14]) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} + S(a: 0) // expected-error {{generic type 'S' specialized with too few type parameters (got 1, but expected 2)}} + S(b: 1) // expected-error {{generic type 'S' specialized with too few type parameters (got 1, but expected 2)}} + let _ = S(a: 0) // Ok + let _ = S(b: true) // Ok + S(a: 0) // expected-error {{generic type 'S' specialized with too many type parameters (got 3, but expected 2)}} + S(b: 0) // expected-error {{generic type 'S' specialized with too many type parameters (got 3, but expected 2)}} } -SR_2164(a: 0) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} -SR_2164(b: 1) // expected-error {{generic parameter 'A' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} -SR_2164(c: 2) -// expected-error@-1 {{generic parameter 'A' could not be inferred}} -// expected-error@-2 {{generic parameter 'B' could not be inferred}} -// expected-note@-3 {{explicitly specify the generic arguments to fix this issue}} {{8-8=}} -SR_2164(3) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} -SR_2164_Array([4]) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} -SR_2164(e: 5) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} -SR_2164_Dict(a: ["pi": 3.14]) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} -SR_2164(a: 0) // expected-error {{generic type 'SR_2164' specialized with too few type parameters (got 1, but expected 2)}} -SR_2164(b: 1) // expected-error {{generic type 'SR_2164' specialized with too few type parameters (got 1, but expected 2)}} -let _ = SR_2164(a: 0) // Ok -let _ = SR_2164(b: true) // Ok -SR_2164(a: 0) // expected-error {{generic type 'SR_2164' specialized with too many type parameters (got 3, but expected 2)}} -SR_2164(b: 0) // expected-error {{generic type 'SR_2164' specialized with too many type parameters (got 3, but expected 2)}} - // Swift compiler misreports type error in ternary expression let r29850459_flag = true @@ -925,9 +934,10 @@ let _ = (r29850459() ? r29850459_a : r29850459_b) + 42.0 // expected-error {{bin let _ = ((r29850459_flag || r29850459()) ? r29850459_a : r29850459_b) + 42.0 // expected-error {{binary operator '+' cannot be applied to operands of type 'Int' and 'Double'}} // expected-note@-1 {{overloads for '+' exist with these partially matching parameter lists: (Double, Double), (Int, Int)}} -// SR-6272: Tailored diagnostics with fixits for numerical conversions +// https://github.com/apple/swift/issues/48822 +// Tailored diagnostics with fixits for numerical conversions -func SR_6272_a() { +do { enum Foo: Int { case bar } @@ -942,8 +952,7 @@ func SR_6272_a() { // expected-note@+1 {{overloads for '*' exist with these partially matching parameter lists: (Float, Float), (Int, Int)}} Foo.bar.rawValue * Float(0) } - -func SR_6272_b() { +do { let lhs = Float(3) let rhs = Int(0) @@ -957,8 +966,7 @@ func SR_6272_b() { // expected-note@+1 {{overloads for '*' exist with these partially matching parameter lists: (Float, Float), (Int, Int)}} lhs * rhs } - -func SR_6272_c() { +do { // expected-error@+1 {{cannot convert value of type 'String' to expected argument type 'Int'}} {{none}} Int(3) * "0" @@ -967,25 +975,26 @@ func SR_6272_c() { Int(10) * S() } -struct SR_6272_D: ExpressibleByIntegerLiteral { +// FIXME: Operator lookup does not reach local types, so this must be a +// top-level struct (https://github.com/apple/swift/issues/51378). +struct S_48822: ExpressibleByIntegerLiteral { typealias IntegerLiteralType = Int init(integerLiteral: Int) {} - static func +(lhs: SR_6272_D, rhs: Int) -> Float { return 42.0 } + static func +(lhs: S_48822, rhs: Int) -> Float { return 42.0 } } - -func SR_6272_d() { +do { let x: Float = 1.0 - // expected-error@+2 {{binary operator '+' cannot be applied to operands of type 'SR_6272_D' and 'Float'}} {{none}} - // expected-note@+1 {{overloads for '+' exist with these partially matching parameter lists: (Float, Float), (SR_6272_D, Int)}} - let _: Float = SR_6272_D(integerLiteral: 42) + x + // expected-error@+2 {{binary operator '+' cannot be applied to operands of type 'S_48822' and 'Float'}} {{none}} + // expected-note@+1 {{overloads for '+' exist with these partially matching parameter lists: (Float, Float), (S_48822, Int)}} + let _: Float = S_48822(integerLiteral: 42) + x - // expected-error@+1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} {{50-50=Int(}} {{54-54=)}} - let _: Float = SR_6272_D(integerLiteral: 42) + 42.0 + // expected-error@+1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} {{48-48=Int(}} {{52-52=)}} + let _: Float = S_48822(integerLiteral: 42) + 42.0 - // expected-error@+2 {{binary operator '+' cannot be applied to operands of type 'SR_6272_D' and 'Float'}} {{none}} - // expected-note@+1 {{overloads for '+' exist with these partially matching parameter lists: (Float, Float), (SR_6272_D, Int)}} - let _: Float = SR_6272_D(integerLiteral: 42) + x + 1.0 + // expected-error@+2 {{binary operator '+' cannot be applied to operands of type 'S_48822' and 'Float'}} {{none}} + // expected-note@+1 {{overloads for '+' exist with these partially matching parameter lists: (Float, Float), (S_48822, Int)}} + let _: Float = S_48822(integerLiteral: 42) + x + 1.0 } // Ambiguous overload inside a trailing closure @@ -997,22 +1006,23 @@ func takesClosure(fn: () -> ()) {} takesClosure() { ambiguousCall() } // expected-error {{ambiguous use of 'ambiguousCall()'}} -// SR-4692: Useless diagnostics calling non-static method +// https://github.com/apple/swift/issues/47269 +// Useless diagnostics calling non-static method -class SR_4692_a { +class C1_47269 { private static func foo(x: Int, y: Bool) { self.bar(x: x) - // expected-error@-1 {{instance member 'bar' cannot be used on type 'SR_4692_a'}} + // expected-error@-1 {{instance member 'bar' cannot be used on type 'C1_47269'}} } private func bar(x: Int) { } } -class SR_4692_b { +class C2_47269 { static func a() { self.f(x: 3, y: true) - // expected-error@-1 {{instance member 'f' cannot be used on type 'SR_4692_b'}} + // expected-error@-1 {{instance member 'f' cannot be used on type 'C2_47269'}} } private func f(a: Int, b: Bool, c: String) { @@ -1040,8 +1050,10 @@ for var i in 0..<10 { // expected-warning {{variable 'i' was never mutated; cons _ = i + 1 } -// SR-5045 - Attempting to return result of reduce(_:_:) in a method with no return produces ambiguous error -func sr5045() { +// https://github.com/apple/swift/issues/47621 +// Attempting to return result of 'reduce(_:_:)' in a method with no return +// produces ambiguous error +func f_47621() { let doubles: [Double] = [1, 2, 3] return doubles.reduce(0, +) // expected-error@-1 {{unexpected non-void return value in void function}} @@ -1102,7 +1114,8 @@ class ListExpr_28456467 : AST_28456467, Expr_28456467 { } } -func sr5081() { +// https://github.com/apple/swift/issues/47657 +do { var a = ["1", "2", "3", "4", "5"] var b = [String]() b = a[2...4] // expected-error {{cannot assign value of type 'ArraySlice' to type '[String]'}} @@ -1126,8 +1139,9 @@ func rdar17170728() { } } -// https://bugs.swift.org/browse/SR-5934 - failure to emit diagnostic for bad -// generic constraints +// https://github.com/apple/swift/issues/48493 +// Failure to emit diagnostic for bad generic constraints + func elephant(_: T) where T : Collection, T.Element == U, T.Element : Hashable {} // expected-note {{where 'U' = 'T'}} func platypus(a: [T]) { @@ -1287,7 +1301,8 @@ class ClassWithPropContainingSetter { } } -// https://bugs.swift.org/browse/SR-11964 +// https://github.com/apple/swift/issues/54389 + struct Rect { let width: Int let height: Int @@ -1316,23 +1331,26 @@ let f12: (Int) -> Void = { _ in } func f12(_ n: T, _ f: @escaping (T) -> T) {} // expected-note {{where 'T' = 'Int'}} f12(3, f4)// expected-error {{global function 'f12' requires that 'Int' conform to 'P2'}} -// SR-15293: Bad diagnostic for var + func overload with mismatched call -func f13(x: Int, y: Int) {} -var f13: Any = 0 -f13(0, x: 0) // expected-error {{incorrect argument labels in call (have '_:x:', expected 'x:y:')}} +/// https://github.com/apple/swift/issues/57615 +/// Bad diagnostic for `var` + `func` overload with mismatched call +// FIXME: Diagnostic still bad in local scope. +func f_57615(x: Int, y: Int) {} +var f_57615: Any = 0 +f_57615(0, x: 0) // expected-error {{incorrect argument labels in call (have '_:x:', expected 'x:y:')}} + +// https://github.com/apple/swift/issues/54669 -// SR-12242 -struct SR_12242_R {} -struct SR_12242_T {} +struct S1_54669 {} +struct S2_54669 {} -protocol SR_12242_P {} +protocol P_54669 {} -func fSR_12242() -> SR_12242_R<[SR_12242_T]> {} +func f_54669() -> S1_54669<[S2_54669]> {} -func genericFunc(_ completion: @escaping (SR_12242_R<[SR_12242_T]>) -> Void) { - let t = fSR_12242() - completion(t) // expected-error {{cannot convert value of type 'diagnostics.SR_12242_R<[diagnostics.SR_12242_T]>' to expected argument type 'diagnostics.SR_12242_R<[SR_12242_T]>'}} - // expected-note@-1 {{arguments to generic parameter 'Element' ('diagnostics.SR_12242_T' and 'SR_12242_T') are expected to be equal}} +func genericFunc(_ completion: @escaping (S1_54669<[S2_54669]>) -> Void) { + let t = f_54669() + completion(t) // expected-error {{cannot convert value of type 'diagnostics.S1_54669<[diagnostics.S2_54669]>' to expected argument type 'diagnostics.S1_54669<[S2_54669]>'}} + // expected-note@-1 {{arguments to generic parameter 'Element' ('diagnostics.S2_54669' and 'S2_54669') are expected to be equal}} } func assignGenericMismatch() { @@ -1376,12 +1394,14 @@ func gericArgToParamInout(_ x: inout [[Int]]) { // expected-note {{change variab // expected-error@-2 {{inout argument could be set to a value with a type other than '[[Int]]'; use a value declared as type '[[String]]?' instead}} } -// SR-12725 -struct SR12725 {} // expected-note {{arguments to generic parameter 'E' ('Int' and 'Double') are expected to be equal}} -func generic(_ value: inout T, _ closure: (SR12725) -> Void) {} +// https://github.com/apple/swift/issues/55169 +do { + struct S {} // expected-note {{arguments to generic parameter 'E' ('Int' and 'Double') are expected to be equal}} + func generic(_ value: inout T, _ closure: (S) -> Void) {} -let arg: Int -generic(&arg) { (g: SR12725) -> Void in } // expected-error {{cannot convert value of type '(SR12725) -> Void' to expected argument type '(SR12725) -> Void'}} + let arg: Int + generic(&arg) { (g: S) -> Void in } // expected-error {{cannot convert value of type '(S) -> Void' to expected argument type '(S) -> Void'}} +} // rdar://problem/62428353 - bad error message for passing `T` where `inout T` was expected func rdar62428353(_ t: inout T) { @@ -1410,12 +1430,14 @@ func rdar62989214() { } } -// SR-5688 -func SR5688_1() -> String? { "" } -SR5688_1!.count // expected-error {{function 'SR5688_1' was used as a property; add () to call it}} {{9-9=()}} +// https://github.com/apple/swift/issues/48258 +do { + func f1() -> String? {} + f1!.count // expected-error {{function 'f1' was used as a property; add () to call it}} {{5-5=()}} -func SR5688_2() -> Int? { 0 } -let _: Int = SR5688_2! // expected-error {{function 'SR5688_2' was used as a property; add () to call it}} {{22-22=()}} + func f2() -> Int? { 0 } + let _: Int = f2! // expected-error {{function 'f2' was used as a property; add () to call it}} {{18-18=()}} +} // rdar://74696023 - Fallback error when passing incorrect optional type to `==` operator From da8d035b0b04ca64dbf407030b94293dbfcfd800 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 17 Aug 2022 15:56:14 +0300 Subject: [PATCH 198/491] Gardening: Migrate test suite to GH issues: Constraints (2/5) --- test/Constraints/argument_matching.swift | 50 +++++++++---------- test/Constraints/array_literal.swift | 37 ++++++++------- test/Constraints/construction.swift | 37 ++++++++------- test/Constraints/diagnostics_swift4.swift | 29 +++++++----- test/Constraints/fixes.swift | 30 +++++++----- test/Constraints/iuo.swift | 31 +++++++----- test/Constraints/keypath.swift | 36 +++++++------- test/Constraints/operator.swift | 44 ++++++++++------- test/Constraints/optional.swift | 58 +++++++++++++---------- 9 files changed, 196 insertions(+), 156 deletions(-) diff --git a/test/Constraints/argument_matching.swift b/test/Constraints/argument_matching.swift index a83ca9694e63a..4547cedff82c4 100644 --- a/test/Constraints/argument_matching.swift +++ b/test/Constraints/argument_matching.swift @@ -89,27 +89,24 @@ somekeywords1(x: 1, y: 2, z: 3) // expected-error{{extraneous argument label 'x: somekeywords1(1, 2, 3) // expected-error{{missing argument labels 'y:z:' in call}}{{18-18=y: }}{{21-21=z: }} somekeywords1(x: 1, 2, z: 3) // expected-error{{incorrect argument labels in call (have 'x:_:z:', expected '_:y:z:')}}{{15-18=}}{{21-21=y: }} -// SR-2242: poor diagnostic when argument label is omitted - -func r27212391(x: Int, _ y: Int) { - let _: Int = x + y -} - -func r27212391(a: Int, x: Int, _ y: Int) { - let _: Int = a + x + y +// https://github.com/apple/swift/issues/44849 +// Poor diagnostic when argument label is omitted +do { + func f(x: Int, _ y: Int) {} + func f(a: Int, x: Int, _ y: Int) {} + + f(3, 5) // expected-error {{missing argument label 'x:' in call}} + f(3, y: 5) // expected-error {{incorrect argument labels in call (have '_:y:', expected 'x:_:')}} + f(3, x: 5) // expected-error {{argument 'x' must precede unnamed argument #1}} {{5-5=x: 5, }} {{6-12=}} + f(y: 3, x: 5) // expected-error {{incorrect argument labels in call (have 'y:x:', expected 'x:_:')}} {{5-6=x}} {{11-14=}} + f(y: 3, 5) // expected-error {{incorrect argument label in call (have 'y:_:', expected 'x:_:')}} + f(x: 3, x: 5) // expected-error {{extraneous argument label 'x:' in call}} + f(a: 1, 3, y: 5) // expected-error {{incorrect argument labels in call (have 'a:_:y:', expected 'a:x:_:')}} + f(1, x: 3, y: 5) // expected-error {{incorrect argument labels in call (have '_:x:y:', expected 'a:x:_:')}} + f(a: 1, y: 3, x: 5) // expected-error {{incorrect argument labels in call (have 'a:y:x:', expected 'a:x:_:')}} + f(a: 1, 3, x: 5) // expected-error {{argument 'x' must precede unnamed argument #2}} {{11-11=x: 5, }} {{12-18=}} } -r27212391(3, 5) // expected-error {{missing argument label 'x:' in call}} -r27212391(3, y: 5) // expected-error {{incorrect argument labels in call (have '_:y:', expected 'x:_:')}} -r27212391(3, x: 5) // expected-error {{argument 'x' must precede unnamed argument #1}} {{11-11=x: 5, }} {{12-18=}} -r27212391(y: 3, x: 5) // expected-error {{incorrect argument labels in call (have 'y:x:', expected 'x:_:')}} {{11-12=x}} {{17-20=}} -r27212391(y: 3, 5) // expected-error {{incorrect argument label in call (have 'y:_:', expected 'x:_:')}} -r27212391(x: 3, x: 5) // expected-error {{extraneous argument label 'x:' in call}} -r27212391(a: 1, 3, y: 5) // expected-error {{incorrect argument labels in call (have 'a:_:y:', expected 'a:x:_:')}} -r27212391(1, x: 3, y: 5) // expected-error {{incorrect argument labels in call (have '_:x:y:', expected 'a:x:_:')}} -r27212391(a: 1, y: 3, x: 5) // expected-error {{incorrect argument labels in call (have 'a:y:x:', expected 'a:x:_:')}} -r27212391(a: 1, 3, x: 5) // expected-error {{argument 'x' must precede unnamed argument #2}} {{17-17=x: 5, }} {{18-24=}} - // ------------------------------------------- // Out-of-order keywords // ------------------------------------------- @@ -1718,8 +1715,10 @@ struct DiagnoseAllLabels { } } -// SR-13135: Type inference regression in Swift 5.3 - can't infer a type of @autoclosure result. -func sr13135() { +/// https://github.com/apple/swift/issues/55581 +/// Type inference regression in Swift 5.3 - can't infer a type of +/// `@autoclosure` result +do { struct Foo { var bar: [Int] = [] } @@ -1734,12 +1733,13 @@ func sr13135() { foo(Foo().bar, [baz]) } -// SR-13240 -func twoargs(_ x: String, _ y: String) {} +// https://github.com/apple/swift/issues/55681 +do { + func twoargs(_ x: String, _ y: String) {} -func test() { let x = 1 - twoargs(x, x) // expected-error 2 {{cannot convert value of type 'Int' to expected argument type 'String'}} + twoargs(x, x) + // expected-error@-1 2 {{cannot convert value of type 'Int' to expected argument type 'String'}} } infix operator --- diff --git a/test/Constraints/array_literal.swift b/test/Constraints/array_literal.swift index 8276bd5632e66..1e7c5c353ea63 100644 --- a/test/Constraints/array_literal.swift +++ b/test/Constraints/array_literal.swift @@ -318,12 +318,15 @@ let routerFruit = Company( ] ) -// Infer [[Int]] for SR3786aa. -// FIXME: As noted in SR-3786, this was the behavior in Swift 3, but -// it seems like the wrong choice and is less by design than by -// accident. -let SR3786a: [Int] = [1, 2, 3] -let SR3786aa = [SR3786a.reversed(), SR3786a] +// https://github.com/apple/swift/issues/46371 +do { + let x: [Int] = [1, 2, 3] + + // Infer '[[Int]]'. + // FIXME: As noted in the issue, this was the behavior in Swift 3, but + // it seems like the wrong choice and is less by design than by accident. + let _ = [x.reversed(), x] +} // Conditional conformance protocol P { } @@ -344,19 +347,19 @@ func testConditional(i: Int, s: String) { } -// SR-8385 -enum SR8385: ExpressibleByStringLiteral { - case text(String) - init(stringLiteral value: String) { - self = .text(value) +// https://github.com/apple/swift/issues/50912 +do { + enum Enum: ExpressibleByStringLiteral { + case text(String) + init(stringLiteral value: String) { + self = .text(value) + } } -} -func testSR8385() { - let _: [SR8385] = [SR8385("hello")] - let _: [SR8385] = [.text("hello")] - let _: [SR8385] = ["hello", SR8385.text("world")] - let _: [SR8385] = ["hello", .text("world")] + let _: [Enum] = [Enum("hello")] + let _: [Enum] = [.text("hello")] + let _: [Enum] = ["hello", Enum.text("world")] + let _: [Enum] = ["hello", .text("world")] } struct TestMultipleOverloadedInits { diff --git a/test/Constraints/construction.swift b/test/Constraints/construction.swift index d4857ad08d633..463a0de41fedb 100644 --- a/test/Constraints/construction.swift +++ b/test/Constraints/construction.swift @@ -153,23 +153,26 @@ extension S3 { let s3b = S3(maybe: s3a) -// SR-5245 - Erroneous diagnostic - Type of expression is ambiguous without more context -class SR_5245 { - struct S { - enum E { - case e1 - case e2 - } - - let e: [E] - } +// https://github.com/apple/swift/issues/47820 +// Erroneous diagnostic: type of expression is ambiguous without more context +do { + class C { + struct S { + enum E { + case e1 + case e2 + } + + let e: [E] + } + + init(s: S) {} + } - init(s: S) {} + C(s: C.S(f: [.e1, .e2])) + // expected-error@-1 {{incorrect argument label in call (have 'f:', expected 'e:')}} {{12-13=e}} } -SR_5245(s: SR_5245.S(f: [.e1, .e2])) -// expected-error@-1 {{incorrect argument label in call (have 'f:', expected 'e:')}} {{22-23=e}} - // rdar://problem/34670592 - Compiler crash on heterogeneous collection literal _ = Array([1, "hello"]) // Ok @@ -219,8 +222,10 @@ func rdar_50668864() { } } -// SR-10837 (rdar://problem/51442825) - init partial application regression -func sr_10837() { +/// rdar://problem/51442825 +/// https://github.com/apple/swift/issues/53227 +/// `init` partial application regression +do { struct S { let value: Int diff --git a/test/Constraints/diagnostics_swift4.swift b/test/Constraints/diagnostics_swift4.swift index 3cffe9d38ab67..c95d498418f34 100644 --- a/test/Constraints/diagnostics_swift4.swift +++ b/test/Constraints/diagnostics_swift4.swift @@ -1,30 +1,33 @@ // RUN: %target-typecheck-verify-swift -swift-version 4 -// SR-2505: "Call arguments did not match up" assertion - -func sr_2505(_ a: Any) {} // expected-note {{}} -sr_2505() // expected-error {{missing argument for parameter #1 in call}} -sr_2505(a: 1) // expected-error {{extraneous argument label 'a:' in call}} -sr_2505(1, 2) // expected-error {{extra argument in call}} -sr_2505(a: 1, 2) // expected-error {{extra argument in call}} +// https://github.com/apple/swift/issues/45110 +// Call arguments did not match up assertion + +func f_45110(_ a: Any) {} // expected-note {{}} +do { + f_45110() // expected-error {{missing argument for parameter #1 in call}} + f_45110(a: 1) // expected-error {{extraneous argument label 'a:' in call}} + f_45110(1, 2) // expected-error {{extra argument in call}} + f_45110(a: 1, 2) // expected-error {{extra argument in call}} +} -struct C_2505 { +struct S_45110 { init(_ arg: Any) { } } -protocol P_2505 { +protocol P_45110 { } -extension C_2505 { - init(from: [T]) where T: P_2505 { +extension S_45110 { + init(from: [T]) where T: P_45110 { } } -class C2_2505: P_2505 { +class C_45110: P_45110 { } -let c_2505 = C_2505(arg: [C2_2505()]) // expected-error {{extraneous argument label 'arg:' in call}} +let _ = S_45110(arg: [C_45110()]) // expected-error {{extraneous argument label 'arg:' in call}} // rdar://problem/31898542 - Swift 4: 'type of expression is ambiguous without more context' errors, without a fixit diff --git a/test/Constraints/fixes.swift b/test/Constraints/fixes.swift index 4221d7b6cdec2..4effe7857a806 100644 --- a/test/Constraints/fixes.swift +++ b/test/Constraints/fixes.swift @@ -153,7 +153,7 @@ var someInt = co.a // expected-error{{value of optional type 'C?' must be unwrap // expected-note@-1{{chain the optional using '?' to access member 'a' only for non-'nil' base values}}{{17-17=?}} // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{17-17=!}} -// SR-839 +// https://github.com/apple/swift/issues/43451 struct Q { let s: String? } @@ -172,19 +172,22 @@ let c = q.s.utf8 // expected-error{{value of optional type 'String?' must be unw // expected-note@-1{{chain the optional using '?' to access member 'utf8' only for non-'nil' base values}}{{12-12=?}} // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{12-12=!}} -// SR-1116 -struct S1116 { - var s: Int? -} +// https://github.com/apple/swift/issues/43729 +do { + struct S { + var s: Int? + } -let a1116: [S1116] = [] -var s1116 = Set(1...10).subtracting(a1116.map({ $0.s })) // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}} -// expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{53-53= ?? <#default value#>}} -// expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{53-53=!}} + let x: [S] = [] + var y = Set(1...10).subtracting(x.map({ $0.s })) // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}} + // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{47-47= ?? <#default value#>}} + // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{47-47=!}} +} func makeArray(_ x: T) -> [T] { [x] } -func sr12399(_ x: Int?) { +// https://github.com/apple/swift/issues/54837 +func f_54837(_ x: Int?) { _ = Set(0...10).subtracting(makeArray(x)) // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}} // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{42-42= ?? <#default value#>}} // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{42-42=!}} @@ -320,7 +323,7 @@ let _: Int? = thing?.f() // expected-error {{value of optional type 'Int??' must // expected-note@-1{{coalesce}} // expected-note@-2{{force-unwrap}} -// SR-9851 - https://bugs.swift.org/browse/SR-9851 +// https://github.com/apple/swift/issues/52262 func coalesceWithParensRootExprFix() { let optionalBool: Bool? = false if !optionalBool { } // expected-error{{value of optional type 'Bool?' must be unwrapped to a value of type 'Bool'}} @@ -342,7 +345,7 @@ func test_explicit_call_with_overloads() { // expected-error@-1 {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{14-14=()}} } -// SR-11476 +// https://github.com/apple/swift/issues/53876 func testKeyPathSubscriptArgFixes(_ fn: @escaping () -> Int) { struct S { subscript(x: Int) -> Int { x } @@ -357,7 +360,8 @@ func testKeyPathSubscriptArgFixes(_ fn: @escaping () -> Int) { _ = \S.[fn] // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{13-13=()}} } -func sr12426(a: Any, _ str: String?) { +// https://github.com/apple/swift/issues/54865 +func f_54865(a: Any, _ str: String?) { a == str // expected-error {{binary operator '==' cannot be applied to operands of type 'Any' and 'String?'}} // expected-note@-1 {{overloads for '==' exist with these partially matching parameter lists: (String, String)}} } diff --git a/test/Constraints/iuo.swift b/test/Constraints/iuo.swift index 19bdb79bd7941..b3b05bd0f563a 100644 --- a/test/Constraints/iuo.swift +++ b/test/Constraints/iuo.swift @@ -216,23 +216,30 @@ func conditionalDowncastToObject(b: B?) -> D { // expected-warning@-3 {{using '!' here is deprecated and will be removed in a future release}} } +// https://github.com/apple/swift/issues/49536 // Ensure that we select the overload that does *not* involve forcing an IUO. -func sr6988(x: Int?, y: Int?) -> Int { return x! } -func sr6988(x: Int, y: Int) -> Float { return Float(x) } +do { + func f(x: Int?, y: Int?) -> Int { return x! } + func f(x: Int, y: Int) -> Float { return Float(x) } -var x: Int! = nil -var y: Int = 2 + let x: Int! = nil + let y: Int = 2 -let r = sr6988(x: x, y: y) -let _: Int = r + let r = f(x: x, y: y) + let _: Int = r +} -// SR-11998 / rdar://problem/58455441 -class C {} -var sub: C! = C() +// rdar://problem/58455441 +// https://github.com/apple/swift/issues/54432 +do { + class C {} + let _: C! = C() +} -// SR-15219 (rdar://83352038): Make sure we don't crash if an IUO param becomes -// a placeholder. -func rdar83352038() { +// rdar://problem/83352038 +// https://github.com/apple/swift/issues/57541 +// Make sure we don't crash if an IUO param becomes a placeholder. +do { func foo(_: UnsafeRawPointer) -> Undefined {} // expected-error {{cannot find type 'Undefined' in scope}} let _ = { (cnode: AlsoUndefined!) -> UnsafeMutableRawPointer in // expected-error {{cannot find type 'AlsoUndefined' in scope}} return foo(cnode) diff --git a/test/Constraints/keypath.swift b/test/Constraints/keypath.swift index 8ef9bc973bed3..5f6aa6f8ef067 100644 --- a/test/Constraints/keypath.swift +++ b/test/Constraints/keypath.swift @@ -20,7 +20,8 @@ func test() { let _ = C()[keyPath: \.i] // no warning for a read } -// SR-7339 +// https://github.com/apple/swift/issues/49887 + class Some { // expected-note {{'V' declared as parameter to type 'Some'}} init(keyPath: KeyPath Void)?>) { } @@ -49,15 +50,16 @@ func testFunc() { let _: (S) -> Int = f // expected-error {{cannot convert value of type 'KeyPath' to specified type '(S) -> Int'}} } -struct SR_12432 { - static func takesKeyPath(_: KeyPath) -> String { "" } +// https://github.com/apple/swift/issues/54871 +struct S_54871 { + static func takesKeyPath(_: KeyPath) -> String { "" } struct S { let text: String = takesKeyPath(\.text) // okay } } -// SR-11234 +// https://github.com/apple/swift/issues/53635 public extension Array { func sorted>(by keyPath: K) -> Array { let sortedA = self.sorted(by: { $0[keyPath: keyPath] < $1[keyPath: keyPath] }) @@ -138,19 +140,17 @@ func test_mismatch_with_contextual_optional_result() { // expected-error@-1 {{key path value type '[Int]' cannot be converted to contextual type '[Int]?'}} } -// SR-11184 -class SR11184 {} - -func fSR11184(_ c: SR11184!, _ kp: ReferenceWritableKeyPath, _ str: String) { +// https://github.com/apple/swift/issues/53581 +class C_53581 {} +func f_53581(_ c: C_53581!, _ kp: ReferenceWritableKeyPath, + _ str: String, _ o_str: String?) { c[keyPath: kp] = str // OK c![keyPath: kp] = str // OK c?[keyPath: kp] = str // OK -} -func fSR11184_O(_ c: SR11184!, _ kp: ReferenceWritableKeyPath, _ str: String?) { - c[keyPath: kp] = str // OK - c![keyPath: kp] = str // OK - c?[keyPath: kp] = str // OK + c[keyPath: kp] = o_str // OK + c![keyPath: kp] = o_str // OK + c?[keyPath: kp] = o_str // OK } class KeyPathBase {} @@ -180,12 +180,12 @@ func key_path_root_mismatch(_ base: KeyPathBase?, subBase: KeyPathBaseSubtype } -// SR-13442 -func SR13442(_ x: KeyPath) -> T { "1"[keyPath: x] } +// https://github.com/apple/swift/issues/55884 +func f_55884() { + func f(_ x: KeyPath) -> T { "1"[keyPath: x] } -func testSR13442() { - _ = SR13442(\.!.count) // OK - _ = SR13442(\String?.!.count) // OK + _ = f(\.!.count) // OK + _ = f(\String?.!.count) // OK let _: KeyPath = \Optional.! } diff --git a/test/Constraints/operator.swift b/test/Constraints/operator.swift index cbaf4206155f6..ded5ab49d5042 100644 --- a/test/Constraints/operator.swift +++ b/test/Constraints/operator.swift @@ -1,7 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/43735 // Test constraint simplification of chains of binary operators. -// do { let a: String? = "a" let b: String? = "b" @@ -11,13 +11,15 @@ do { let x: Double = 1 _ = x + x + x - let sr3483: Double? = 1 - _ = sr3483! + sr3483! + sr3483! + // https://github.com/apple/swift/issues/46071 + let y1: Double? = 1 + _ = y1! + y1! + y1! - let sr2636: [String: Double] = ["pizza": 10.99, "ice cream": 4.99, "salad": 7.99] - _ = sr2636["pizza"]! - _ = sr2636["pizza"]! + sr2636["salad"]! - _ = sr2636["pizza"]! + sr2636["salad"]! + sr2636["ice cream"]! + // https://github.com/apple/swift/issues/45241 + let y2: [String: Double] = ["pizza": 10.99, "ice cream": 4.99, "salad": 7.99] + _ = y2["pizza"]! + _ = y2["pizza"]! + y2["salad"]! + _ = y2["pizza"]! + y2["salad"]! + y2["ice cream"]! } // Use operators defined within a type. @@ -202,7 +204,7 @@ func rdar37290898(_ arr: inout [P_37290898], _ element: S_37290898?) { arr += [element].compactMap { $0 } // Ok } -// SR-8221 +// https://github.com/apple/swift/issues/50753 infix operator ??= func ??= (lhs: inout T?, rhs: T?) {} var c: Int = 0 // expected-note {{change variable type to 'Int?' if it doesn't need to be declared as 'Int'}} @@ -223,21 +225,24 @@ func rdar46459603() { // expected-error@-2 {{cannot convert value of type 'Dictionary.Values' to expected element type '[E]'}} } -// SR-10843 +// https://github.com/apple/swift/issues/53233 + infix operator ^^^ func ^^^ (lhs: String, rhs: String) {} -struct SR10843 { - static func ^^^ (lhs: SR10843, rhs: SR10843) {} +// FIXME: Operator lookup does not reach local types so this must be a +// top-level struct (https://github.com/apple/swift/issues/51378). +struct S_53233 { + static func ^^^ (lhs: S_53233, rhs: S_53233) {} } - -func sr10843() { - let s = SR10843() +do { + let s = S_53233() (^^^)(s, s) _ = (==)(0, 0) } -// SR-10970 +// https://github.com/apple/swift/issues/53359 + precedencegroup PowerPrecedence { lowerThan: BitwiseShiftPrecedence higherThan: AdditionPrecedence @@ -273,8 +278,9 @@ func rdar60727310() { myAssertion(e, ==, nil) // expected-error {{binary operator '==' cannot be applied to two '(any Error)?' operands}} } -// FIXME(SR-12438): Bad diagnostic. -func sr12438(_ e: Error) { +// https://github.com/apple/swift/issues/54877 +// FIXME: Bad diagnostic. +func f_54877(_ e: Error) { func foo(_ a: T, _ op: ((T, T) -> Bool)) {} foo(e, ==) // expected-error {{type of expression is ambiguous without more context}} } @@ -291,7 +297,9 @@ func rdar_62054241() { } } -// SR-11399 - Operator returning IUO doesn't implicitly unwrap +// https://github.com/apple/swift/issues/53800 +// Operator returning IUO doesn't implicitly unwrap + postfix operator ^^^ postfix func ^^^ (lhs: Int) -> Int! { 0 } diff --git a/test/Constraints/optional.swift b/test/Constraints/optional.swift index 26f8b992ad6bd..8f59203edf978 100644 --- a/test/Constraints/optional.swift +++ b/test/Constraints/optional.swift @@ -201,29 +201,32 @@ func compare(v: T, u: T!) -> Bool { return v ++++ u } -func sr2752(x: String?, y: String?) { +// https://github.com/apple/swift/issues/45356 +func f_45356(x: String?, y: String?) { _ = x.map { xx in y.map { _ in "" } ?? "\(xx)" } } -// SR-3248 - Invalid diagnostic calling implicitly unwrapped closure -var sr3248 : ((Int) -> ())! -sr3248?(a: 2) // expected-error {{extraneous argument label 'a:' in call}} -sr3248!(a: 2) // expected-error {{extraneous argument label 'a:' in call}} -sr3248(a: 2) // expected-error {{extraneous argument label 'a:' in call}} +// https://github.com/apple/swift/issues/45836 +// Invalid diagnostic calling implicitly unwrapped closure +do { + var x : ((Int) -> ())! + x?(a: 2) // expected-error {{extraneous argument label 'a:' in call}} + x!(a: 2) // expected-error {{extraneous argument label 'a:' in call}} + x(a: 2) // expected-error {{extraneous argument label 'a:' in call}} -struct SR_3248 { + struct S { var callback: (([AnyObject]) -> Void)! -} - -SR_3248().callback?("test") // expected-error {{cannot convert value of type 'String' to expected argument type '[AnyObject]'}} -SR_3248().callback!("test") // expected-error {{cannot convert value of type 'String' to expected argument type '[AnyObject]'}} -SR_3248().callback("test") // expected-error {{cannot convert value of type 'String' to expected argument type '[AnyObject]'}} + } -_? = nil // expected-error {{'nil' requires a contextual type}} -_?? = nil // expected-error {{'nil' requires a contextual type}} + S().callback?("test") // expected-error {{cannot convert value of type 'String' to expected argument type '[AnyObject]'}} + S().callback!("test") // expected-error {{cannot convert value of type 'String' to expected argument type '[AnyObject]'}} + S().callback("test") // expected-error {{cannot convert value of type 'String' to expected argument type '[AnyObject]'}} + _? = nil // expected-error {{'nil' requires a contextual type}} + _?? = nil // expected-error {{'nil' requires a contextual type}} +} // rdar://problem/29993596 func takeAnyObjects(_ lhs: AnyObject?, _ rhs: AnyObject?) { } @@ -238,7 +241,8 @@ func testAnyObjectImplicitForce(lhs: AnyObject?!, rhs: AnyObject?) { takeAnyObjects(lhs, rhs) } -// SR-4056 +// https://github.com/apple/swift/issues/46639 + protocol P1 { } class C1: P1 { } @@ -305,8 +309,11 @@ func rdar45218255(_ i: Int) { _ = S([i!]) // expected-error {{cannot force unwrap value of non-optional type 'Int'}} {{16-17=}} } -// rdar://problem/47967277 - cannot assign through '!': '$0' is immutable -func sr_9893_1() { +// rdar://problem/47967277 +// https://github.com/apple/swift/issues/52299 +// Cannot assign through '!': '$0' is immutable + +func f1_52299() { func foo(_: @autoclosure () throws -> T, _: @autoclosure () throws -> T) {} @@ -321,7 +328,7 @@ func sr_9893_1() { foo(Set(arr1.map { $0.bar! }), Set([r1, r2].map { $0.bar! })) // Ok } -func sr_9893_2(cString: UnsafePointer) { +func f2_52299(cString: UnsafePointer) { struct S { var a: Int32 = 0 var b = ContiguousArray(repeating: 0, count: 10) @@ -376,8 +383,9 @@ func rdar_53238058() { } } -// SR-8411 - Inconsistent ambiguity with optional and non-optional inout-to-pointer -func sr8411() { +// https://github.com/apple/swift/issues/50936 +// Inconsistent ambiguity with optional and non-optional inout-to-pointer +do { struct S { init(_ x: UnsafeMutablePointer) {} init(_ x: UnsafeMutablePointer?) {} @@ -397,8 +405,9 @@ func sr8411() { S.bar(&foo, 42) // Ok } -// SR-11104 - Slightly misleading diagnostics for contextual failures with multiple fixes -func sr_11104() { +// https://github.com/apple/swift/issues/53499 +// Slightly misleading diagnostics for contextual failures with multiple fixes +do { func bar(_: Int) {} bar(["hello"].first) @@ -430,8 +439,9 @@ func invalidOptionalChaining(a: Any) { // expected-note@-2 {{requirement from conditional conformance of 'Any?' to 'Equatable'}} expected-note@-2 {{only concrete types such as structs, enums and classes can conform to protocols}} } -// SR-12309 - Force unwrapping 'nil' compiles without warning -func sr_12309() { +/// https://github.com/apple/swift/issues/54739 +/// Force unwrapping `nil` compiles without warning +do { struct S { var foo: Int } From 613ef8cd47359fdbb320f6f615704cfb4fa9c606 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Fri, 19 Aug 2022 00:07:57 +0200 Subject: [PATCH 199/491] [SwiftSyntax] Adjustment for changed RawSyntax API --- utils/gyb_syntax_support/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/gyb_syntax_support/__init__.py b/utils/gyb_syntax_support/__init__.py index 9f9ab7c74c541..b54ef4da14227 100644 --- a/utils/gyb_syntax_support/__init__.py +++ b/utils/gyb_syntax_support/__init__.py @@ -121,7 +121,8 @@ def make_missing_swift_child(child): tok_kind = token.swift_kind() if token else "unknown" if not token or not token.text: tok_kind += '("")' - return 'RawSyntax.missingToken(TokenKind.%s)' % tok_kind + return f'RawSyntax.makeMissingToken(kind: TokenKind.{tok_kind}, ' + \ + 'arena: .default)' else: if child.syntax_kind == "Syntax": missing_kind = "unknown" @@ -129,7 +130,8 @@ def make_missing_swift_child(child): missing_kind = f"missing{child.syntax_kind}" else: missing_kind = child.swift_syntax_kind - return 'RawSyntax.missing(SyntaxKind.%s)' % missing_kind + return f'RawSyntax.makeEmptyLayout(kind: SyntaxKind.{missing_kind}, ' + \ + 'arena: .default)' def create_node_map(): From d915202cfdb39d3b8fcf42b96917bf9454f3d39f Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 19 Aug 2022 14:03:39 +0100 Subject: [PATCH 200/491] [AST] Allow configurable lazy initializer walking Allow ASTWalker subclasses to specify whether they want to visit lazy variable initializers as part of the pattern binding, getter body, or not at all. --- include/swift/AST/ASTWalker.h | 35 +++++++++++++++++++++++--------- include/swift/AST/Expr.h | 1 + lib/AST/ASTVerifier.cpp | 4 ++-- lib/AST/ASTWalker.cpp | 37 ++++++++++++++++++++++++---------- lib/Sema/TypeCheckCaptures.cpp | 4 ++-- 5 files changed, 57 insertions(+), 24 deletions(-) diff --git a/include/swift/AST/ASTWalker.h b/include/swift/AST/ASTWalker.h index 7ca7344a2b872..1d0e16aa84a32 100644 --- a/include/swift/AST/ASTWalker.h +++ b/include/swift/AST/ASTWalker.h @@ -50,6 +50,25 @@ struct ReferenceMetaData { : Kind(Kind), AccKind(AccKind), isImplicit(isImplicit) {} }; +/// Specifies how the initialization expression of a \c lazy variable should be +/// walked by the ASTWalker. +enum class LazyInitializerWalking { + /// No lazy initialization expressions will be walked. + None, + + /// The lazy initialization expression will only be walked as a part of + /// the variable's pattern binding decl. This is the default behavior, and is + /// consistent with the initializer being syntactically part of the pattern + /// binding. + InPatternBinding, + + /// The lazy initialization expression will only be walked as part of the + /// body of the synthesized accessor for the lazy variable. In such an + /// accessor, the expression is denoted by LazyInitializerExpr. This is mainly + /// useful for code emission. + InAccessor +}; + /// An abstract class used to traverse an AST. class ASTWalker { public: @@ -193,15 +212,13 @@ class ASTWalker { /// params in AbstractFunctionDecl and NominalTypeDecl. virtual bool shouldWalkIntoGenericParams() { return false; } - /// This method configures whether the walker should walk into the - /// initializers of lazy variables. These initializers are semantically - /// different from other initializers in their context and so sometimes - /// should not be visited. - /// - /// Note that visiting the body of the lazy getter will find a - /// LazyInitializerExpr with the initializer as its sub-expression. - /// However, ASTWalker does not walk into LazyInitializerExprs on its own. - virtual bool shouldWalkIntoLazyInitializers() { return true; } + /// This method configures how the walker should walk the initializers of + /// lazy variables. These initializers are semantically different from other + /// initializers in their context and so sometimes should be visited as part + /// of the synthesized getter, or should not be visited at all. + virtual LazyInitializerWalking getLazyInitializerWalkingBehavior() { + return LazyInitializerWalking::InPatternBinding; + } /// This method configures whether the walker should visit the body of a /// closure that was checked separately from its enclosing expression. diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index a5fa92b7ba9fc..c076091f43336 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -5314,6 +5314,7 @@ class LazyInitializerExpr : public Expr { SourceLoc getLoc() const { return SubExpr->getLoc(); } Expr *getSubExpr() const { return SubExpr; } + void setSubExpr(Expr *subExpr) { SubExpr = subExpr; } static bool classof(const Expr *E) { return E->getKind() == ExprKind::LazyInitializer; diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index 587e6b135d648..15731bcb30801 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -2338,11 +2338,11 @@ class Verifier : public ASTWalker { verifyCheckedBase(VD); } - bool shouldWalkIntoLazyInitializers() override { + LazyInitializerWalking getLazyInitializerWalkingBehavior() override { // We don't want to walk into lazy initializers because they should // have been reparented to their synthesized getter, which will // invalidate various invariants. - return false; + return LazyInitializerWalking::None; } void verifyChecked(PatternBindingDecl *binding) { diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 4f47d45558848..9bbf905236949 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -195,18 +195,23 @@ class Traversal : public ASTVisitorsetPattern(idx, Pat, PBD->getInitContext(idx)); else return true; - if (PBD->getInit(idx) && - !isPropertyWrapperBackingProperty && - (!PBD->isInitializerSubsumed(idx) || - Walker.shouldWalkIntoLazyInitializers())) { + + if (!PBD->getInit(idx) || isPropertyWrapperBackingProperty) + continue; + + if (PBD->isInitializerSubsumed(idx) && + Walker.getLazyInitializerWalkingBehavior() != + LazyInitializerWalking::InPatternBinding) { + break; + } + #ifndef NDEBUG - PrettyStackTraceDecl debugStack("walking into initializer for", PBD); + PrettyStackTraceDecl debugStack("walking into initializer for", PBD); #endif - if (Expr *E2 = doIt(PBD->getInit(idx))) - PBD->setInit(idx, E2); - else - return true; - } + if (Expr *E2 = doIt(PBD->getInit(idx))) + PBD->setInit(idx, E2); + else + return true; } return false; } @@ -1073,7 +1078,17 @@ class Traversal : public ASTVisitorgetSubExpr()); + if (!sub) + return nullptr; + + E->setSubExpr(sub); return E; } diff --git a/lib/Sema/TypeCheckCaptures.cpp b/lib/Sema/TypeCheckCaptures.cpp index 6c1fabc2f04a1..b20519eb7383a 100644 --- a/lib/Sema/TypeCheckCaptures.cpp +++ b/lib/Sema/TypeCheckCaptures.cpp @@ -210,11 +210,11 @@ class FindCapturedVars : public ASTWalker { checkType(VD->getInterfaceType(), VD->getLoc()); } - bool shouldWalkIntoLazyInitializers() override { + LazyInitializerWalking getLazyInitializerWalkingBehavior() override { // We don't want to walk into lazy initializers because they're not // really present at this level. We'll catch them when processing // the getter. - return false; + return LazyInitializerWalking::None; } std::pair walkToDeclRefExpr(DeclRefExpr *DRE) { From 64fcbd9412cf0cb2ae2d368f6d975ba491bc2469 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 19 Aug 2022 14:03:40 +0100 Subject: [PATCH 201/491] [Profiler] Support lazy variable initializers Start visiting LazyInitializerExpr for profiling, such that we emit a profile counter when initializing the initial value for the first time. rdar://43393937 --- lib/SIL/IR/SILProfiler.cpp | 47 +++++++++++++++++++++++------- lib/SILGen/SILGenExpr.cpp | 13 ++++++++- test/Profiler/coverage_class.swift | 8 ----- test/Profiler/coverage_lazy.swift | 29 ++++++++++++++++++ test/Profiler/pgo_lazy.swift | 41 ++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 20 deletions(-) create mode 100644 test/Profiler/coverage_lazy.swift create mode 100644 test/Profiler/pgo_lazy.swift diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index 1017559b71446..b3faf2c2a5274 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -196,6 +196,13 @@ static bool skipExpr(Expr *E) { return !E->getStartLoc().isValid() || !E->getEndLoc().isValid(); } +/// Whether the children of an unmapped decl should still be walked. +static bool shouldWalkUnmappedDecl(const Decl *D) { + // We want to walk into the initializer for a pattern binding decl. This + // allows us to map LazyInitializerExprs. + return isa(D); +} + /// An ASTWalker that maps ASTNodes to profiling counters. struct MapRegionCounters : public ASTWalker { /// The next counter value to assign. @@ -207,6 +214,12 @@ struct MapRegionCounters : public ASTWalker { MapRegionCounters(llvm::DenseMap &CounterMap) : CounterMap(CounterMap) {} + LazyInitializerWalking getLazyInitializerWalkingBehavior() override { + // We want to walk lazy initializers present in the synthesized getter for + // a lazy variable. + return LazyInitializerWalking::InAccessor; + } + void mapRegion(ASTNode N) { CounterMap[N] = NextCounter; @@ -225,7 +238,7 @@ struct MapRegionCounters : public ASTWalker { bool walkToDeclPre(Decl *D) override { if (isUnmapped(D)) - return false; + return shouldWalkUnmappedDecl(D); if (auto *AFD = dyn_cast(D)) { return visitFunctionDecl(*this, AFD, [&] { mapRegion(AFD->getBody()); }); @@ -274,14 +287,8 @@ struct MapRegionCounters : public ASTWalker { mapRegion(IE->getThenExpr()); } - // rdar://42792053 - // TODO: There's an outstanding issue here with LazyInitializerExpr. A LIE - // is copied into the body of a property getter after type-checking (before - // coverage). ASTWalker only visits this expression once via the property's - // VarDecl, and does not visit it again within the getter. This results in - // missing coverage. SILGen treats the init expr as part of the getter, but - // its SILProfiler has no information about the init because the LIE isn't - // visited here. + if (isa(E)) + mapRegion(E); return {true, E}; } @@ -579,7 +586,7 @@ struct PGOMapping : public ASTWalker { bool walkToDeclPre(Decl *D) override { if (isUnmapped(D)) - return false; + return shouldWalkUnmappedDecl(D); if (auto *AFD = dyn_cast(D)) { return visitFunctionDecl(*this, AFD, [&] { setKnownExecutionCount(AFD->getBody()); @@ -591,6 +598,12 @@ struct PGOMapping : public ASTWalker { return true; } + LazyInitializerWalking getLazyInitializerWalkingBehavior() override { + // We want to walk lazy initializers present in the synthesized getter for + // a lazy variable. + return LazyInitializerWalking::InAccessor; + } + std::pair walkToStmtPre(Stmt *S) override { unsigned parent = getParentCounter(); auto parentCount = LoadedCounts.Counts[parent]; @@ -674,6 +687,9 @@ struct PGOMapping : public ASTWalker { } setExecutionCount(elseExpr, subtract(count, thenCount)); } + if (isa(E)) + setKnownExecutionCount(E); + return {true, E}; } }; @@ -903,6 +919,12 @@ struct CoverageMapping : public ASTWalker { public: CoverageMapping(const SourceManager &SM) : SM(SM) {} + LazyInitializerWalking getLazyInitializerWalkingBehavior() override { + // We want to walk lazy initializers present in the synthesized getter for + // a lazy variable. + return LazyInitializerWalking::InAccessor; + } + /// Generate the coverage counter mapping regions from collected /// source regions. SILCoverageMap *emitSourceRegions( @@ -930,7 +952,7 @@ struct CoverageMapping : public ASTWalker { bool walkToDeclPre(Decl *D) override { if (isUnmapped(D)) - return false; + return shouldWalkUnmappedDecl(D); if (auto *AFD = dyn_cast(D)) { return visitFunctionDecl(*this, AFD, [&] { @@ -1124,6 +1146,9 @@ struct CoverageMapping : public ASTWalker { } } + if (isa(E)) + assignCounter(E); + if (hasCounter(E) && !Parent.isNull()) pushRegion(E); return {true, E}; diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index f204f328a4554..8ef949af0405d 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -415,7 +415,9 @@ namespace { return RValue(SGF, E, SGF.emitAddressOfLValue(E->getSubExpr(), std::move(lv))); } - + + RValue visitLazyInitializerExpr(LazyInitializerExpr *E, SGFContext C); + RValue visitApplyExpr(ApplyExpr *E, SGFContext C); RValue visitDiscardAssignmentExpr(DiscardAssignmentExpr *E, SGFContext C) { @@ -708,6 +710,15 @@ tryEmitAsBridgingConversion(SILGenFunction &SGF, Expr *E, bool isExplicit, return SGF.emitConvertedRValue(subExpr, conversion, C); } +RValue RValueEmitter::visitLazyInitializerExpr(LazyInitializerExpr *E, + SGFContext C) { + // We need to emit a profiler count increment specifically for the lazy + // initialization, as we don't want to record an increment for every call to + // the getter. + SGF.emitProfilerIncrement(E); + return visit(E->getSubExpr(), C); +} + RValue RValueEmitter::visitApplyExpr(ApplyExpr *E, SGFContext C) { return SGF.emitApplyExpr(E, C); } diff --git a/test/Profiler/coverage_class.swift b/test/Profiler/coverage_class.swift index 11cd0b4290b89..1473a4909b8a8 100644 --- a/test/Profiler/coverage_class.swift +++ b/test/Profiler/coverage_class.swift @@ -52,11 +52,3 @@ struct S2 { // CHECK-NEXT: [[@LINE+1]]:17 -> [[@LINE+1]]:27 : 0 var m1: Int = g1 ? 0 : 1 } - -// Test that the crash from SR-8429 is avoided. Follow-up work is -// needed to generate the correct coverage mapping here. Coverage for -// `offset` should be associated with its getter, not the class -// constructor. -class C2 { - lazy var offset: Int = true ? 30 : 55 -} diff --git a/test/Profiler/coverage_lazy.swift b/test/Profiler/coverage_lazy.swift new file mode 100644 index 0000000000000..3a6f5a479f19c --- /dev/null +++ b/test/Profiler/coverage_lazy.swift @@ -0,0 +1,29 @@ +// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sil -module-name coverage_lazy %s | %FileCheck %s +// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -emit-ir %s + +// Test that the crash from SR-8429 is avoided, and that we generate the +// correct coverage. +class C { + // CHECK-LABEL: sil hidden [lazy_getter] [noinline] @$s13coverage_lazy1CC6offsetSivg : $@convention(method) (@guaranteed C) -> Int + // CHECK: switch_enum {{%[0-9]+}} : $Optional, case #Optional.some!enumelt: {{bb[0-9]}}, case #Optional.none!enumelt: [[INITBB:bb[0-9]]] + // CHECK: [[INITBB]] + // CHECK-NEXT: string_literal + // CHECK-NEXT: integer_literal $Builtin.Int64, 0 + // CHECK-NEXT: integer_literal $Builtin.Int32, 4 + // CHECK-NEXT: integer_literal $Builtin.Int32, 2 + // CHECK-NEXT: int_instrprof_increment + // CHECK: function_ref @$sSb6randomSbyFZ : $@convention(method) (@thin Bool.Type) -> Bool + // CHECK: cond_br {{%[0-9]+}}, [[TRUEBB:bb[0-9]]], {{bb[0-9]}} + // CHECK: [[TRUEBB]] + // CHECK-NEXT: string_literal + // CHECK-NEXT: integer_literal $Builtin.Int64, 0 + // CHECK-NEXT: integer_literal $Builtin.Int32, 4 + // CHECK-NEXT: integer_literal $Builtin.Int32, 3 + + // CHECK-LABEL: sil_coverage_map {{.*}} // coverage_lazy.C.offset.getter : Swift.Int + // CHECK-NEXT: [[@LINE+4]]:38 -> [[@LINE+4]]:40 : 3 + // CHECK-NEXT: [[@LINE+3]]:43 -> [[@LINE+3]]:45 : (2 - 3) + // CHECK-NEXT: [[@LINE+2]]:26 -> [[@LINE+2]]:45 : 2 + // CHECK-NEXT: } + lazy var offset: Int = .random() ? 30 : 55 +} diff --git a/test/Profiler/pgo_lazy.swift b/test/Profiler/pgo_lazy.swift new file mode 100644 index 0000000000000..4b44797843edd --- /dev/null +++ b/test/Profiler/pgo_lazy.swift @@ -0,0 +1,41 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_lazy -o %t/main + +// This unusual use of 'sh' allows the path of the profraw file to be +// substituted by %target-run. +// RUN: %target-codesign %t/main +// RUN: %target-run sh -c 'env LLVM_PROFILE_FILE=$1 $2' -- %t/default.profraw %t/main + +// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata + +// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_lazy -o - | %FileCheck %s --check-prefix=SIL +// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_lazy -o - | %FileCheck %s --check-prefix=SIL +// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_lazy -o - | %FileCheck %s --check-prefix=IR +// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_lazy -o - | %FileCheck %s --check-prefix=IR + +// REQUIRES: profile_runtime +// REQUIRES: executable_test +// REQUIRES: OS=macosx + +var cond = true + +public struct S { + // SIL-LABEL: sil [lazy_getter] [noinline] @$s8pgo_lazy1SV1xSivg : $@convention(method) (@inout S) -> Int !function_entry_count(35) + // SIL: cond_br {{.*}} !true_count(5) !false_count(30) + public lazy var x = cond ? 2 : 3 +} + +func triggerLazy() -> Int { + var s = S() + return s.x +} +public var total = 0 +for _ in 0 ..< 5 { + total += triggerLazy() +} +cond = false +for _ in 0 ..< 30 { + total += triggerLazy() +} + +// IR: !{!"branch_weights", i32 6, i32 31} From 6a6ba8300c6d7292936dd7c715b2a91fe9da5cc2 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 19 Aug 2022 14:03:41 +0100 Subject: [PATCH 202/491] [Profiler] Re-enable an assertion This was disabled as it was hit when attempting to profile lazy variables. Now that we handle them correctly, re-enable it. --- lib/SILGen/SILGenFunction.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index d43badae82ea4..5ce6784eaa06b 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -1163,9 +1163,8 @@ void SILGenFunction::emitProfilerIncrement(ASTNode N) { const auto &RegionCounterMap = SP->getRegionCounterMap(); auto CounterIt = RegionCounterMap.find(N); - // TODO: Assert that this cannot happen (rdar://42792053). - if (CounterIt == RegionCounterMap.end()) - return; + assert(CounterIt != RegionCounterMap.end() && + "cannot increment non-existent counter"); auto Int32Ty = getLoweredType(BuiltinIntegerType::get(32, C)); auto Int64Ty = getLoweredType(BuiltinIntegerType::get(64, C)); From 92a8fbd3a75a4e8a38147ea6ca4abc7f148ce830 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 19 Aug 2022 15:06:11 +0100 Subject: [PATCH 203/491] [Profiler] Assert that counters are present --- lib/SIL/IR/SILProfiler.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index 1017559b71446..3d91c30e460d3 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -395,8 +395,9 @@ class CounterExpr { expand(llvm::coverage::CounterExpressionBuilder &Builder, const llvm::DenseMap &Counters) const { return expand(Builder, [&](auto Node) { - // FIXME: We ought to assert that the node is present. - return Counters.lookup(Node); + auto Result = Counters.find(Node); + assert(Result != Counters.end() && "Counter not found"); + return Result->second; }); } From d8bab13469ec975dc4bfc9698fa15060f8a1192f Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 19 Aug 2022 15:06:11 +0100 Subject: [PATCH 204/491] [Profiler] Fix counters following DoStmts Previously we weren't compensating for label jumps and returns, i.e we assumed the exit count is the same as the entry count. Ensure we follow the same logic that other labeled statements follow such that control flow is accounted for. rdar://98881045 --- lib/SIL/IR/SILProfiler.cpp | 4 +- test/Profiler/coverage_do.swift | 69 +++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 test/Profiler/coverage_do.swift diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index 3d91c30e460d3..e26855093ebd0 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -784,7 +784,7 @@ struct CoverageMapping : public ASTWalker { CounterExpr *JumpsToLabel = nullptr; Stmt *ParentStmt = Parent.getAsStmt(); if (ParentStmt) { - if (isa(ParentStmt) || isa(ParentStmt)) + if (isa(ParentStmt)) return; auto caseStmt = dyn_cast_or_null(ParentStmt); if (caseStmt && caseStmt->getParentKind() == CaseParentKind::DoCatch) @@ -999,8 +999,8 @@ struct CoverageMapping : public ASTWalker { if (caseStmt->getParentKind() == CaseParentKind::Switch) pushRegion(S); } else if (auto *DS = dyn_cast(S)) { + assignCounter(DS, CounterExpr::Zero()); assignCounter(DS->getBody(), CounterExpr::Ref(getCurrentCounter())); - assignCounter(DS); } else if (auto *DCS = dyn_cast(S)) { // The do-catch body is visited the same number of times as its parent. diff --git a/test/Profiler/coverage_do.swift b/test/Profiler/coverage_do.swift new file mode 100644 index 0000000000000..c8a540b773e95 --- /dev/null +++ b/test/Profiler/coverage_do.swift @@ -0,0 +1,69 @@ +// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -suppress-warnings -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_do %s | %FileCheck %s +// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -emit-ir %s + +// CHECK-LABEL: sil hidden @$s11coverage_do3fooyyF : $@convention(thin) () -> () + +// CHECK: string_literal +// CHECK-NEXT: integer_literal $Builtin.Int64, 0 +// CHECK-NEXT: integer_literal $Builtin.Int32, 3 +// CHECK-NEXT: integer_literal $Builtin.Int32, 0 +// CHECK-NEXT: int_instrprof_increment +// CHECK: function_ref @$sSb6randomSbyFZ +// CHECK: cond_br {{%[0-9]+}}, [[EXITBB:bb[0-9]]], [[BB1:bb[0-9]]] + +// CHECK: [[BB1]] +// CHECK: function_ref @$sSb6randomSbyFZ +// CHECK: cond_br {{%[0-9]+}}, [[BRKBB:bb[0-9]]], {{bb[0-9]}} + +// CHECK: [[BRKBB]] +// CHECK-NEXT: string_literal +// CHECK-NEXT: integer_literal $Builtin.Int64, 0 +// CHECK-NEXT: integer_literal $Builtin.Int32, 3 +// CHECK-NEXT: integer_literal $Builtin.Int32, 2 + +// CHECK: [[EXITBB]] +// CHECK-NEXT: string_literal +// CHECK-NEXT: integer_literal $Builtin.Int64, 0 +// CHECK-NEXT: integer_literal $Builtin.Int32, 3 +// CHECK-NEXT: integer_literal $Builtin.Int32, 1 + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s11coverage_do3fooyyF" +// CHECK-NEXT: [[@LINE+11]]:12 -> [[@LINE+18]]:2 : 0 +// CHECK-NEXT: [[@LINE+11]]:9 -> [[@LINE+15]]:4 : 0 +// CHECK-NEXT: [[@LINE+11]]:8 -> [[@LINE+11]]:17 : 0 +// CHECK-NEXT: [[@LINE+10]]:18 -> [[@LINE+10]]:28 : 1 +// CHECK-NEXT: [[@LINE+9]]:28 -> [[@LINE+12]]:4 : (0 - 1) +// CHECK-NEXT: [[@LINE+9]]:8 -> [[@LINE+9]]:17 : (0 - 1) +// CHECK-NEXT: [[@LINE+8]]:18 -> [[@LINE+8]]:29 : 2 +// CHECK-NEXT: [[@LINE+7]]:29 -> [[@LINE+8]]:11 : ((0 - 1) - 2) +// CHECK-NEXT: [[@LINE+8]]:4 -> [[@LINE+10]]:2 : 2 +// CHECK-NEXT: [[@LINE+8]]:6 -> [[@LINE+8]]:8 : 2 +// CHECK-NEXT: [[@LINE+7]]:8 -> [[@LINE+8]]:2 : 2 +func foo() { + x: do { + if .random() { return } + if .random() { break x } + return + } + do {} +} +// CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s11coverage_do4foobyyF" +func foob() { + x: do { + do { + if .random() { return } + // CHECK: [[@LINE+1]]:6 -> [[@LINE+10]]:4 : (0 - 1) + } + do { + if .random() { break x } + // CHECK: [[@LINE+1]]:6 -> [[@LINE+6]]:4 : ((0 - 1) - 2) + } + do { + return + // CHECK-NOT: zero + } + } + do {} +} From 23734210431213eebdee8df5c98e64e3bc96dc8f Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Fri, 19 Aug 2022 09:23:19 -0700 Subject: [PATCH 205/491] [Windows]: explicitly set closure captures MSVC isn't seeing that `CheckDefaultInitializer` is declared and being implicitly captured by reference by the closure going into the `forEachVariable`. Capturing `HasStorage` and `CheckDefaultInitializer` explicitly. --- lib/Sema/CodeSynthesis.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 8928dab39be30..e3b801b85af4c 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -847,15 +847,16 @@ bool AreAllStoredPropertiesDefaultInitableRequest::evaluate( for (auto idx : range(pbd->getNumPatternEntries())) { bool HasStorage = false; bool CheckDefaultInitializer = true; - pbd->getPattern(idx)->forEachVariable([&](VarDecl *VD) { - // If one of the bound variables is @NSManaged, go ahead no matter - // what. - if (VD->getAttrs().hasAttribute()) - CheckDefaultInitializer = false; - - if (VD->hasStorageOrWrapsStorage()) - HasStorage = true; - }); + pbd->getPattern(idx)->forEachVariable( + [&HasStorage, &CheckDefaultInitializer](VarDecl *VD) { + // If one of the bound variables is @NSManaged, go ahead no matter + // what. + if (VD->getAttrs().hasAttribute()) + CheckDefaultInitializer = false; + + if (VD->hasStorageOrWrapsStorage()) + HasStorage = true; + }); if (!HasStorage) continue; From f2d9bc7bf69d7a1f1b26a0e241e87a2b051be274 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Thu, 18 Aug 2022 15:10:59 -0700 Subject: [PATCH 206/491] Add dealloc_stack_ref as a non-write in LoadBorrowImmutabilityAnalysis --- lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp b/lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp index 522ea2ca810e7..51aeb4af390b0 100644 --- a/lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp +++ b/lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp @@ -94,6 +94,7 @@ bool GatherWritesVisitor::visitUse(Operand *op, AccessUseType useTy) { case SILInstructionKind::SelectEnumAddrInst: case SILInstructionKind::SwitchEnumAddrInst: case SILInstructionKind::DeallocStackInst: + case SILInstructionKind::DeallocStackRefInst: case SILInstructionKind::DeallocBoxInst: case SILInstructionKind::WitnessMethodInst: case SILInstructionKind::ExistentialMetatypeInst: From 8769cbec07416fe4461d85f2b0e5c34d9f922962 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 15 Jun 2022 21:26:32 -0700 Subject: [PATCH 207/491] Simplify SILMem2Reg by using computeDominatedBoundaryBlocks api instead of computing in-place --- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 46 ++++------------------ 1 file changed, 8 insertions(+), 38 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 17edabd70d4bd..57a59860e79bf 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -1719,45 +1719,15 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) { // block which are the only instructions involving this alloc_stack. // This can only happen if all paths from this block end in unreachable. // - // We need to end the lexical lifetime at the last possible location, either - // just before an unreachable instruction or just before a branch to a block - // that is not dominated by parentBlock. - - // Walk forward from parentBlock until finding blocks which either - // (1) terminate in unreachable - // (2) have successors which are not dominated by parentBlock - GraphNodeWorklist worklist; - worklist.initialize(parentBlock); - while (auto *block = worklist.pop()) { - assert(domInfo->dominates(parentBlock, block)); + // We need to end the lexical lifetime at the last possible location, at the + // boundary blocks which are the predecessors of dominance frontier + // dominated by the alloc_stack. + SmallVector boundary; + computeDominatedBoundaryBlocks(asi->getParent(), domInfo, boundary); + for (auto *block : boundary) { auto *terminator = block->getTerminator(); - if (isa(terminator)) { - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/terminator, ctx, - runningVals->value); - continue; - } - SILBasicBlock *successor = nullptr; - // If any successor is not dominated by the parentBlock, then we must end - // the lifetime before that successor. - // - // Suppose that a successor is not dominated by parentBlock. Recall that - // block _is_ dominated by parentBlock. Thus that successor must have - // more than one predecessor: block, and at least one other. (Otherwise - // it would be dominated by parentBlock contrary to our assumption.) - // Recall that SIL does not allow critical edges. Therefore block has - // only a single successor. - // - // Use the above fact to only look for lack of domination of a successor - // if that successor is the single successor of block. - if ((successor = block->getSingleSuccessorBlock()) && - (!domInfo->dominates(parentBlock, successor))) { - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/terminator, ctx, - runningVals->value); - continue; - } - for (auto *successor : block->getSuccessorBlocks()) { - worklist.insert(successor); - } + endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/terminator, ctx, + runningVals->value); } } } From 40eb1422bb71f639573ae95a7c79775624d68f99 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 12 Aug 2022 16:56:05 -0700 Subject: [PATCH 208/491] IRGen/SIL: Fix IR linkage computation for inlined function references from modules imported `@_weakLinked`. Include the parent `ModuleDecl` when serializing a `SILFunction` so that it is available on deserialized functions even though the full `DeclContext` is not present. With the parent module always available we can reliably compute whether the `SILFunction` comes from a module that was imported `@_weakLinked`. Serialize the `DeclContext` member of `SILFunction` so that it can be used to look up the module that a function belongs to in order to compute weak import status. Resolves rdar://98521248 --- include/swift/AST/Module.h | 5 +-- include/swift/SIL/SILFunction.h | 41 +++++++++++-------- lib/AST/Decl.cpp | 2 +- lib/AST/Module.cpp | 5 +-- lib/IRGen/GenDecl.cpp | 20 +++++---- lib/IRGen/Linking.cpp | 2 +- lib/SIL/IR/Linker.cpp | 5 +-- lib/SIL/IR/SILFunction.cpp | 11 ++--- lib/SIL/IR/SILFunctionBuilder.cpp | 9 +--- lib/SIL/Parser/ParseSIL.cpp | 4 +- lib/Serialization/DeserializeSIL.cpp | 20 +++++---- lib/Serialization/ModuleFormat.h | 2 +- lib/Serialization/SILFormat.h | 1 + lib/Serialization/SerializeSIL.cpp | 6 ++- test/IRGen/weaklinked_import.swift | 5 +-- test/IRGen/weaklinked_import_inlining.swift | 39 ++++++++++++++++++ test/IRGen/weaklinked_import_transitive.swift | 5 ++- 17 files changed, 112 insertions(+), 70 deletions(-) create mode 100644 test/IRGen/weaklinked_import_inlining.swift diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 309ed9aa357c7..340614de02b21 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -685,9 +685,8 @@ class ModuleDecl // Is \p spiGroup accessible as an explicitly imported SPI from this module? bool isImportedAsSPI(Identifier spiGroup, const ModuleDecl *fromModule) const; - /// Is \p targetDecl from a module that is imported as \c @_weakLinked from - /// this module? - bool isImportedAsWeakLinked(const Decl *targetDecl) const; + /// Is \p module imported as \c @_weakLinked from this module? + bool isImportedAsWeakLinked(const ModuleDecl *module) const; /// \sa getImportedModules enum class ImportFilterKind { diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index cc625a883b3d4..a8aa8db8c157d 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -19,6 +19,7 @@ #include "swift/AST/ASTNode.h" #include "swift/AST/Availability.h" +#include "swift/AST/Module.h" #include "swift/AST/ResilienceExpansion.h" #include "swift/Basic/ProfileCounter.h" #include "swift/Basic/SwiftObjectHeader.h" @@ -64,11 +65,6 @@ enum IsDistributed_t { IsNotDistributed, IsDistributed, }; -enum IsWeakImported_t { - IsNotWeakImported, - IsWeakImportedByModule, - IsAlwaysWeakImported, -}; enum class PerformanceConstraints : uint8_t { None = 0, @@ -222,6 +218,10 @@ class SILFunction /// The AST decl context of the function. DeclContext *DeclCtxt = nullptr; + /// The module that defines this function. This member should only be set as + /// a fallback when a \c DeclCtxt is unavailable. + ModuleDecl *ParentModule = nullptr; + /// The profiler for instrumentation based profiling, or null if profiling is /// disabled. SILProfiler *Profiler = nullptr; @@ -322,8 +322,9 @@ class SILFunction /// would indicate. unsigned HasCReferences : 1; - /// Whether cross-module references to this function should use weak linking. - unsigned IsWeakImported : 2; + /// Whether cross-module references to this function should always use weak + /// linking. + unsigned IsAlwaysWeakImported : 1; /// Whether the implementation can be dynamically replaced. unsigned IsDynamicReplaceable : 1; @@ -801,19 +802,11 @@ class SILFunction /// Returns whether this function's symbol must always be weakly referenced /// across module boundaries. - bool isAlwaysWeakImported() const { - return IsWeakImported == IsWeakImported_t::IsAlwaysWeakImported; - } - - /// Returns whether this function's symbol was referenced by a module that - /// imports the defining module \c @_weakLinked. - bool isWeakImportedByModule() const { - return IsWeakImported == IsWeakImported_t::IsWeakImportedByModule; - } + bool isAlwaysWeakImported() const { return IsAlwaysWeakImported; } - void setIsWeakImported(IsWeakImported_t value) { IsWeakImported = value; } + void setIsAlwaysWeakImported(bool value) { IsAlwaysWeakImported = value; } - bool isWeakImported() const; + bool isWeakImported(ModuleDecl *module) const; /// Returns whether this function implementation can be dynamically replaced. IsDynamicallyReplaceable_t isDynamicallyReplaceable() const { @@ -960,6 +953,18 @@ class SILFunction DeclCtxt = (DS ? DebugScope->Loc.getAsDeclContext() : nullptr); } + /// Returns the module that defines this function. + ModuleDecl *getParentModule() const { + return DeclCtxt ? DeclCtxt->getParentModule() : ParentModule; + } + + /// Sets \c ParentModule as fallback if \c DeclCtxt is not available to + /// provide the parent module. + void setParentModule(ModuleDecl *module) { + assert(!DeclCtxt && "already have a DeclCtxt"); + ParentModule = module; + } + /// Initialize the debug scope for debug info on SIL level /// (-sil-based-debuginfo). void setSILDebugScope(const SILDebugScope *DS) { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7efe326bb5218..8fa5a636320e6 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1002,7 +1002,7 @@ bool Decl::isWeakImported(ModuleDecl *fromModule) const { if (isAlwaysWeakImported()) return true; - if (fromModule->isImportedAsWeakLinked(this)) + if (fromModule->isImportedAsWeakLinked(this->getModuleContext())) return true; auto availability = getAvailabilityForLinkage(); diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index c7c9b56fe1b46..c0eacd4e57507 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -2663,10 +2663,9 @@ bool ModuleDecl::isImportedAsSPI(Identifier spiGroup, return importedSPIGroups.count(spiGroup); } -bool ModuleDecl::isImportedAsWeakLinked(const Decl *targetDecl) const { - const auto *declaringModule = targetDecl->getModuleContext(); +bool ModuleDecl::isImportedAsWeakLinked(const ModuleDecl *module) const { for (auto file : getFiles()) { - if (file->importsModuleAsWeakLinked(declaringModule)) + if (file->importsModuleAsWeakLinked(module)) return true; } return false; diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 896bb93e590c5..9767314cddc3e 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -2520,7 +2520,8 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var, // FIXME: We should be able to set the linkage unconditionally here but // some fixes are needed for Cxx interop. if (auto globalVar = dyn_cast(addr)) { - if (getSwiftModule()->isImportedAsWeakLinked(var->getDecl())) + auto varModule = var->getDecl()->getModuleContext(); + if (getSwiftModule()->isImportedAsWeakLinked(varModule)) globalVar->setLinkage(link.getLinkage()); } @@ -3275,13 +3276,16 @@ llvm::Function *IRGenModule::getAddrOfSILFunction( fn = dyn_cast(clangAddr->stripPointerCasts()); if (fn) { - // Override the linkage computed by Clang if the decl is from another - // module that imported @_weakLinked. - // - // FIXME: We should be able to set the linkage unconditionally here but - // some fixes are needed for Cxx interop. - if (!forDefinition && f->isWeakImportedByModule()) - fn->setLinkage(link.getLinkage()); + if (!forDefinition) { + // Override the linkage computed by Clang if the decl is from another + // module that imported @_weakLinked. + // + // FIXME: We should be able to set the linkage unconditionally here but + // some fixes are needed for Cxx interop. + if (auto *DC = f->getDeclContext()) + if (getSwiftModule()->isImportedAsWeakLinked(DC->getParentModule())) + fn->setLinkage(link.getLinkage()); + } // If we have a function, move it to the appropriate position. if (hasOrderNumber) { diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp index 98a41119720c3..1120a5b53bb4e 100644 --- a/lib/IRGen/Linking.cpp +++ b/lib/IRGen/Linking.cpp @@ -1177,7 +1177,7 @@ bool LinkEntity::isWeakImported(ModuleDecl *module) const { case Kind::DynamicallyReplaceableFunctionVariable: case Kind::SILFunction: case Kind::DistributedAccessor: { - return getSILFunction()->isWeakImported(); + return getSILFunction()->isWeakImported(module); } case Kind::AssociatedConformanceDescriptor: diff --git a/lib/SIL/IR/Linker.cpp b/lib/SIL/IR/Linker.cpp index a5d8d504edcb6..c5b1b3e20d19f 100644 --- a/lib/SIL/IR/Linker.cpp +++ b/lib/SIL/IR/Linker.cpp @@ -16,10 +16,7 @@ /// deserializing functions, vtables and witness tables. /// /// The behavior of the linker is controlled by a LinkMode value. The LinkMode -/// has three possible values: -/// -/// - LinkNone: The linker does not deserialize anything. This is only used for -/// debugging and testing purposes, and never during normal operation. +/// has two possible values: /// /// - LinkNormal: The linker deserializes bodies for declarations that must be /// emitted into the client because they do not have definitions available diff --git a/lib/SIL/IR/SILFunction.cpp b/lib/SIL/IR/SILFunction.cpp index 349770d4098aa..e4db0daad650b 100644 --- a/lib/SIL/IR/SILFunction.cpp +++ b/lib/SIL/IR/SILFunction.cpp @@ -182,7 +182,7 @@ void SILFunction::init( this->InlineStrategy = inlineStrategy; this->Linkage = unsigned(Linkage); this->HasCReferences = false; - this->IsWeakImported = false; + this->IsAlwaysWeakImported = false; this->IsDynamicReplaceable = isDynamic; this->ExactSelfClass = isExactSelfClass; this->IsDistributed = isDistributed; @@ -260,7 +260,7 @@ void SILFunction::createSnapshot(int id) { newSnapshot->perfConstraints = perfConstraints; newSnapshot->GlobalInitFlag = GlobalInitFlag; newSnapshot->HasCReferences = HasCReferences; - newSnapshot->IsWeakImported = IsWeakImported; + newSnapshot->IsAlwaysWeakImported = IsAlwaysWeakImported; newSnapshot->HasOwnership = HasOwnership; newSnapshot->IsWithoutActuallyEscapingThunk = IsWithoutActuallyEscapingThunk; newSnapshot->OptMode = OptMode; @@ -452,9 +452,10 @@ bool SILFunction::isTypeABIAccessible(SILType type) const { return getModule().isTypeABIAccessible(type, TypeExpansionContext(*this)); } -bool SILFunction::isWeakImported() const { - if (isWeakImportedByModule()) - return true; +bool SILFunction::isWeakImported(ModuleDecl *module) const { + if (auto *parent = getParentModule()) + if (module->isImportedAsWeakLinked(parent)) + return true; // For imported functions check the Clang declaration. if (ClangNodeOwner) diff --git a/lib/SIL/IR/SILFunctionBuilder.cpp b/lib/SIL/IR/SILFunctionBuilder.cpp index 88b0f0fdea355..3461a04ca9fd1 100644 --- a/lib/SIL/IR/SILFunctionBuilder.cpp +++ b/lib/SIL/IR/SILFunctionBuilder.cpp @@ -312,14 +312,7 @@ SILFunction *SILFunctionBuilder::getOrCreateFunction( F->setClangNodeOwner(decl); F->setAvailabilityForLinkage(decl->getAvailabilityForLinkage()); - - if (decl->isAlwaysWeakImported()) { - F->setIsWeakImported(IsWeakImported_t::IsAlwaysWeakImported); - } else if (decl->isWeakImported(mod.getSwiftModule())) { - F->setIsWeakImported(IsWeakImported_t::IsWeakImportedByModule); - } else { - F->setIsWeakImported(IsWeakImported_t::IsNotWeakImported); - } + F->setIsAlwaysWeakImported(decl->isAlwaysWeakImported()); if (auto *accessor = dyn_cast(decl)) { auto *storage = accessor->getStorage(); diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index efb4c00d95179..24c8655dfc7cf 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -6514,9 +6514,7 @@ bool SILParserState::parseDeclSIL(Parser &P) { if (!objCReplacementFor.empty()) FunctionState.F->setObjCReplacement(objCReplacementFor); FunctionState.F->setSpecialPurpose(specialPurpose); - FunctionState.F->setIsWeakImported( - isWeakImported ? IsWeakImported_t::IsAlwaysWeakImported - : IsWeakImported_t::IsNotWeakImported); + FunctionState.F->setIsAlwaysWeakImported(isWeakImported); FunctionState.F->setAvailabilityForLinkage(availability); FunctionState.F->setWithoutActuallyEscapingThunk( isWithoutActuallyEscapingThunk); diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 1bd6b4f090cc4..50876a02df8d9 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -519,6 +519,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, (void)kind; DeclID clangNodeOwnerID; + ModuleID parentModuleID; TypeID funcTyID; IdentifierID replacedFunctionID; IdentifierID usedAdHocWitnessFunctionID; @@ -538,7 +539,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), isDynamic, isExactSelfClass, isDistributed, funcTyID, replacedFunctionID, usedAdHocWitnessFunctionID, - genericSigID, clangNodeOwnerID, SemanticsIDs); + genericSigID, clangNodeOwnerID, parentModuleID, SemanticsIDs); if (funcTyID == 0) { MF->fatal("SILFunction typeID is 0"); @@ -661,9 +662,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, fn->setEffectsKind(EffectsKind(effect)); fn->setOptimizationMode(OptimizationMode(optimizationMode)); fn->setPerfConstraints((PerformanceConstraints)perfConstr); - fn->setIsWeakImported(isWeakImported - ? IsWeakImported_t::IsAlwaysWeakImported - : IsWeakImported_t::IsNotWeakImported); + fn->setIsAlwaysWeakImported(isWeakImported); fn->setClassSubclassScope(SubclassScope(subclassScope)); fn->setHasCReferences(bool(hasCReferences)); @@ -705,12 +704,16 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, fn->setWasDeserializedCanonical(); fn->setBare(IsBare); - const SILDebugScope *DS = fn->getDebugScope(); - if (!DS) { - DS = new (SILMod) SILDebugScope(loc, fn); + if (!fn->getDebugScope()) { + const SILDebugScope *DS = new (SILMod) SILDebugScope(loc, fn); fn->setDebugScope(DS); } + // If we don't already have a DeclContext to use to find a parent module, + // attempt to deserialize a parent module reference directly. + if (!fn->getDeclContext() && parentModuleID) + fn->setParentModule(MF->getModule(parentModuleID)); + // Read and instantiate the specialize attributes. bool shouldAddSpecAttrs = fn->getSpecializeAttrs().empty(); bool shouldAddEffectAttrs = !fn->hasArgumentEffects(); @@ -3014,6 +3017,7 @@ bool SILDeserializer::hasSILFunction(StringRef Name, // TODO: If this results in any noticeable performance problems, Cache the // linkage to avoid re-reading it from the bitcode each time? DeclID clangOwnerID; + ModuleID parentModuleID; TypeID funcTyID; IdentifierID replacedFunctionID; IdentifierID usedAdHocWitnessFunctionID; @@ -3033,7 +3037,7 @@ bool SILDeserializer::hasSILFunction(StringRef Name, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), isDynamic, isExactSelfClass, isDistributed, funcTyID, replacedFunctionID, usedAdHocWitnessFunctionID, - genericSigID, clangOwnerID, SemanticsIDs); + genericSigID, clangOwnerID, parentModuleID, SemanticsIDs); auto linkage = fromStableSILLinkage(rawLinkage); if (!linkage) { LLVM_DEBUG(llvm::dbgs() << "invalid linkage code " << rawLinkage diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index b65ee1c3f15cc..79983aaf15f2a 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 701; // opened archetype serialization +const uint16_t SWIFTMODULE_VERSION_MINOR = 702; // SILFunction DeclCtxt /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h index 0338168d37152..cfe1ce5a1715b 100644 --- a/lib/Serialization/SILFormat.h +++ b/lib/Serialization/SILFormat.h @@ -287,6 +287,7 @@ namespace sil_block { DeclIDField, // SILFunction name or 0 (used ad-hoc requirement witness function) GenericSignatureIDField, DeclIDField, // ClangNode owner + ModuleIDField, // Parent ModuleDecl * BCArray // Semantics Attribute // followed by specialize and argument effects attributes // followed by generic param list, if any diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 75d5559c6c0b2..86657f2d8cf60 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -459,6 +459,10 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) { if (F.hasClangNode()) clangNodeOwnerID = S.addDeclRef(F.getClangNodeOwner()); + ModuleID parentModuleID; + if (auto *parentModule = F.getParentModule()) + parentModuleID = S.addModuleRef(parentModule); + IdentifierID replacedFunctionID = 0; if (auto *fun = F.getDynamicallyReplacedFunction()) { addReferencedSILFunction(fun, true); @@ -505,7 +509,7 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) { (unsigned)F.isExactSelfClass(), (unsigned)F.isDistributed(), FnID, replacedFunctionID, usedAdHocWitnessFunctionID, - genericSigID, clangNodeOwnerID, SemanticsIDs); + genericSigID, clangNodeOwnerID, parentModuleID, SemanticsIDs); F.visitArgEffects( [&](int effectIdx, bool isDerived, SILFunction::ArgEffectKind) { diff --git a/test/IRGen/weaklinked_import.swift b/test/IRGen/weaklinked_import.swift index 6649d3f09ed55..9a1a84b27d683 100644 --- a/test/IRGen/weaklinked_import.swift +++ b/test/IRGen/weaklinked_import.swift @@ -159,10 +159,7 @@ protocol RefinesP: BaseP {} extension S: RefinesP {} func testInlining() { - // FIXME: usableFromInlineFn() should be extern_weak but isn't because - // inlining doesn't respect @_weakLinked import yet. - // CHECK-DAG: define linkonce_odr hidden {{.+}} @"$s24weaklinked_import_helper22alwaysEmitIntoClientFnyyF"() - // CHECK-DAG: declare swiftcc {{.+}} @"$s24weaklinked_import_helper18usableFromInlineFnyyF" + // CHECK-DAG: declare extern_weak {{.+}} @"$s24weaklinked_import_helper18usableFromInlineFnyyF" alwaysEmitIntoClientFn() } diff --git a/test/IRGen/weaklinked_import_inlining.swift b/test/IRGen/weaklinked_import_inlining.swift new file mode 100644 index 0000000000000..4f35babd04602 --- /dev/null +++ b/test/IRGen/weaklinked_import_inlining.swift @@ -0,0 +1,39 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module -emit-module-path %t/weaklinked_import_helper.swiftmodule -parse-as-library %S/Inputs/weaklinked_import_helper.swift -enable-library-evolution +// RUN: %target-swift-frontend -emit-module -emit-module-path %t/Intermediate.swiftmodule -parse-as-library %t/Intermediate.swift -I %t -enable-library-evolution +// +// RUN: %target-swift-frontend -primary-file %t/Client.swift -I %t -emit-ir | %FileCheck %s + +// UNSUPPORTED: OS=windows-msvc + +//--- Intermediate.swift + +import weaklinked_import_helper + +public func hasDefaultArgument(_ s: S = S()) { } + +@_alwaysEmitIntoClient +public func aeicFuncCallingFn() { + fn() +} + +//--- Client.swift + +import Intermediate +@_weakLinked import weaklinked_import_helper + +// Symbols from `weaklinked_import_helper` should have weak linkage even +// when the references to them are inlined from `Intermediate`, which imported +// `weaklinked_import_helper` without `@_weakLinked`. + +func testDefaultArguments() { + // CHECK: declare extern_weak {{.+}} @"$s24weaklinked_import_helper1SVMa" + hasDefaultArgument() +} + +func testAlwaysEmitIntoClient() { + // CHECK-DAG: declare extern_weak {{.+}} @"$s24weaklinked_import_helper2fnyyF"() + aeicFuncCallingFn() +} diff --git a/test/IRGen/weaklinked_import_transitive.swift b/test/IRGen/weaklinked_import_transitive.swift index 2e603e23c60a9..9cb9cf8839e3e 100644 --- a/test/IRGen/weaklinked_import_transitive.swift +++ b/test/IRGen/weaklinked_import_transitive.swift @@ -12,8 +12,9 @@ import intermediate import weaklinked_import_helper -// Symbols from weaklinked_import_helper should be strong, despite intermediate -// importining the module @_weakLinked. +// The `@_weakLinked` attribute on the import of `weaklinked_import_helper` in +// the module `intermediate` should not apply transitively to the import from +// this module. // CHECK-DAG: declare swiftcc {{.+}} @"$s24weaklinked_import_helper2fnyyF"() fn() From cc0e12212506e13fe85e7dd9d78465da1771e00e Mon Sep 17 00:00:00 2001 From: buttaface Date: Fri, 19 Aug 2022 22:54:05 +0530 Subject: [PATCH 209/491] [Driver] Work around lld 13+ issue with --gc-sections for ELF by adding -z nostart-stop-gc (#60544) Fixes #60406 Ran the linux x86_64 compiler validation suite on this pull with `-use-ld=lld -Xlinker --gc-sections`, then without stripping as in the linked issue, and only saw the 20 unrelated failures just like @drodriguez had. --- lib/Driver/UnixToolChains.cpp | 11 +++++++++++ test/Driver/link-time-opt.swift | 2 ++ 2 files changed, 13 insertions(+) diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index dc14e7782c79a..6f85e245a002e 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -184,6 +184,17 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, #else Arguments.push_back(context.Args.MakeArgString("-fuse-ld=" + Linker)); #endif + // Starting with lld 13, Swift stopped working with the lld --gc-sections + // implementation for ELF, unless -z nostart-stop-gc is also passed to lld: + // + // https://reviews.llvm.org/D96914 + if (Linker == "lld" || (Linker.length() > 5 && + Linker.substr(Linker.length() - 6) == "ld.lld")) { + Arguments.push_back("-Xlinker"); + Arguments.push_back("-z"); + Arguments.push_back("-Xlinker"); + Arguments.push_back("nostart-stop-gc"); + } } // Configure the toolchain. diff --git a/test/Driver/link-time-opt.swift b/test/Driver/link-time-opt.swift index b0684b2425a9d..10d6fc8ca1b45 100644 --- a/test/Driver/link-time-opt.swift +++ b/test/Driver/link-time-opt.swift @@ -16,6 +16,7 @@ // CHECK-SIMPLE-THIN-linux-gnu: clang // CHECK-SIMPLE-THIN-linux-gnu-DAG: -flto=thin // CHECK-SIMPLE-THIN-linux-gnu-DAG: -fuse-ld=lld +// CHECK-SIMPLE-THIN-linux-gnu-DAG: -Xlinker -z -Xlinker nostart-stop-gc // CHECK-SIMPLE-THIN-linux-gnu-DAG: [[BITCODEFILE]] // CHECK-SIMPLE-THIN-linux-gnu-NOT: swift-autolink-extract @@ -37,6 +38,7 @@ // CHECK-SIMPLE-FULL-linux-gnu: clang // CHECK-SIMPLE-FULL-linux-gnu-DAG: -flto=full // CHECK-SIMPLE-FULL-linux-gnu-DAG: -fuse-ld=lld +// CHECK-SIMPLE-FULL-linux-gnu-DAG: -Xlinker -z -Xlinker nostart-stop-gc // CHECK-SIMPLE-FULL-linux-gnu-DAG: [[BITCODEFILE]] // CHECK-SIMPLE-FULL-linux-gnu-NOT: swift-autolink-extract From 8ec4264d9b467dc89393a2bceb049d48006b4f3d Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 19 Aug 2022 10:31:38 -0700 Subject: [PATCH 210/491] IRGen: Fix IR linkage computation for inlined function references from clang modules imported `@_weakLinked`. Part of rdar://98521248 --- lib/IRGen/GenDecl.cpp | 4 +- .../weaklinked_import_inlining_clang.swift | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 test/IRGen/weaklinked_import_inlining_clang.swift diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 9767314cddc3e..62f87b785567f 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -3282,8 +3282,8 @@ llvm::Function *IRGenModule::getAddrOfSILFunction( // // FIXME: We should be able to set the linkage unconditionally here but // some fixes are needed for Cxx interop. - if (auto *DC = f->getDeclContext()) - if (getSwiftModule()->isImportedAsWeakLinked(DC->getParentModule())) + if (auto *parentModule = f->getParentModule()) + if (getSwiftModule()->isImportedAsWeakLinked(parentModule)) fn->setLinkage(link.getLinkage()); } diff --git a/test/IRGen/weaklinked_import_inlining_clang.swift b/test/IRGen/weaklinked_import_inlining_clang.swift new file mode 100644 index 0000000000000..1d91ce2352e1d --- /dev/null +++ b/test/IRGen/weaklinked_import_inlining_clang.swift @@ -0,0 +1,56 @@ +// RUN: %empty-directory(%t) +// RUN: %build-irgen-test-overlays +// RUN: split-file %s %t + +// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -emit-module-path %t/Intermediate.swiftmodule -parse-as-library %t/Intermediate.swift -enable-library-evolution +// +// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %t/Client.swift -emit-ir | %FileCheck %s + +// REQUIRES: objc_interop + +//--- Intermediate.swift + +import Foundation + +public func hasDefaultArgument(_ n: NSNotification = NSNotification()) { } + +@_alwaysEmitIntoClient +public func aeicFuncUsingWeakVar() { + _ = weak_variable +} + +@_alwaysEmitIntoClient +public func aeicFuncUsingStrongVar() { + _ = strong_variable +} + +@_alwaysEmitIntoClient +public func aeicFuncCallingAlwaysAvailableFunc() { + always_available_function() +} + + +//--- Client.swift + +import Intermediate +@_weakLinked import Foundation + +// Symbols from `Foundation` should have weak linkage even when the references +// to them are inlined from `Intermediate`, which imported `Foundation` without +// `@_weakLinked`. + +func testDefaultArguments() { + // CHECK-DAG: @"OBJC_CLASS_$_NSNotification" = extern_weak global %objc_class + hasDefaultArgument() +} + +func testAlwaysEmitIntoClient() { + // CHECK-DAG: @weak_variable = extern_weak global + aeicFuncUsingWeakVar() + + // CHECK-DAG: @strong_variable = extern_weak global + aeicFuncUsingStrongVar() + + // CHECK-DAG: declare extern_weak void @always_available_function() + aeicFuncCallingAlwaysAvailableFunc() +} From d744af576f12d26e3b59a405cfd0f8a522319d12 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Fri, 19 Aug 2022 10:52:59 -0700 Subject: [PATCH 211/491] [Test] Disabled test to investigate. The test validation-test/SILOptimizer/hoist_destroy_addr.sil is failing to parse with invalid SIL. The input will need to be updated. rdar://98890125 --- validation-test/SILOptimizer/hoist_destroy_addr.sil | 1 + 1 file changed, 1 insertion(+) diff --git a/validation-test/SILOptimizer/hoist_destroy_addr.sil b/validation-test/SILOptimizer/hoist_destroy_addr.sil index fe5912e4d007a..1aea0b18aad67 100644 --- a/validation-test/SILOptimizer/hoist_destroy_addr.sil +++ b/validation-test/SILOptimizer/hoist_destroy_addr.sil @@ -1,6 +1,7 @@ // RUN: %target-sil-opt -opt-mode=none -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEB // RUN: %target-sil-opt -opt-mode=speed -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKOPT +// REQUIRES: rdar98890125 // REQUIRES: long_test // REQUIRES: objc_interop // SIL includes assumption of 64-bit wordsize From 514996e755129ed4bba5a965d531de0ce3ba9972 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Thu, 18 Aug 2022 16:11:54 -0700 Subject: [PATCH 212/491] [Compile Time Constant Extraction] Use 'Expr::printConstExprValue' instead of rolling it ourselves. --- lib/ConstExtract/ConstExtract.cpp | 24 ++++--------------- lib/Option/features.json | 2 +- test/ConstExtraction/fields.swift | 40 +++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index 10739129f46da..b8e78070f7c6e 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -103,27 +103,11 @@ extractPropertyInitializationValue(VarDecl *propertyDecl) { if (binding) { auto originalInit = binding->getOriginalInit(0); if (originalInit) { - // Integer Literals - if (auto integerExpr = - dyn_cast_or_null(originalInit)) { - std::string LiteralOutput; - llvm::raw_string_ostream OutputStream(LiteralOutput); - integerExpr->printConstExprValue(&OutputStream, nullptr); - OutputStream.flush(); + std::string LiteralOutput; + llvm::raw_string_ostream OutputStream(LiteralOutput); + originalInit->printConstExprValue(&OutputStream, nullptr); + if (!LiteralOutput.empty()) return std::make_shared(LiteralOutput); - // Float Literals - } else if (auto floatExpr = - dyn_cast_or_null(originalInit)) { - std::string LiteralOutput; - llvm::raw_string_ostream OutputStream(LiteralOutput); - floatExpr->printConstExprValue(&OutputStream, nullptr); - OutputStream.flush(); - return std::make_shared(LiteralOutput); - // String Literals - } else if (auto stringExpr = - dyn_cast_or_null(originalInit)) { - return std::make_shared(stringExpr->getValue().str()); - } } } diff --git a/lib/Option/features.json b/lib/Option/features.json index 7cbaf102ce192..45e206580d860 100644 --- a/lib/Option/features.json +++ b/lib/Option/features.json @@ -23,6 +23,6 @@ }, { "name": "enable-bare-slash-regex-updated" - } + } ] } diff --git a/test/ConstExtraction/fields.swift b/test/ConstExtraction/fields.swift index 10483508eef9d..36c071a24c642 100644 --- a/test/ConstExtraction/fields.swift +++ b/test/ConstExtraction/fields.swift @@ -18,6 +18,41 @@ // CHECK-NEXT: "value": "Hello, World" // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "label": "p5", +// CHECK-NEXT: "type": "[Int]", +// CHECK-NEXT: "isStatic": "false", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "value": "[1, 2, 3, 4, 5, 6, 7, 8, 9]" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "label": "p6", +// CHECK-NEXT: "type": "Bool", +// CHECK-NEXT: "isStatic": "false", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "value": "false" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "label": "p7", +// CHECK-NEXT: "type": "Bool?", +// CHECK-NEXT: "isStatic": "false", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "value": "nil" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "label": "p8", +// CHECK-NEXT: "type": "(Int, Float)", +// CHECK-NEXT: "isStatic": "false", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "value": "(42, 6.6)" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "label": "p9", +// CHECK-NEXT: "type": "[String : Int]", +// CHECK-NEXT: "isStatic": "false", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "value": "[(\"One\", 1), (\"Two\", 2), (\"Three\", 3)]" +// CHECK-NEXT: }, +// CHECK-NEXT: { // CHECK-NEXT: "label": "p0", // CHECK-NEXT: "type": "Int", // CHECK-NEXT: "isStatic": "true", @@ -57,6 +92,11 @@ public struct Foo { static let p2: Float = 42.2 var p3: Int {3} static var p4: Int {3} + let p5: [Int] = [1,2,3,4,5,6,7,8,9] + let p6: Bool = false + let p7: Bool? = nil + let p8: (Int, Float) = (42, 6.6) + let p9: [String: Int] = ["One": 1, "Two": 2, "Three": 3] } extension Foo : MyProto {} From 4d039686fd6f8d28b2a32d164f7b61cac8e3fd36 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 19 Aug 2022 11:39:40 -0700 Subject: [PATCH 213/491] [CSSimplify] Failure to bind type variable to invalid dependent member makes it a hole If the failure is not reflected in constraint system it would let the solver to form a _valid_ solution as if the constraint between the type variable and the unresolved dependent member type never existed. Resolves: https://github.com/apple/swift/issues/60649 --- lib/Sema/CSSimplify.cpp | 7 +++++ .../issue60649.swift | 26 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 validation-test/Sema/type_checker_crashers_fixed/issue60649.swift diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 5a2302033112b..8c1fa9a1d926e 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3814,6 +3814,13 @@ ConstraintSystem::matchTypesBindTypeVar( // let's ignore this mismatch and mark affected type variable as a hole // because something else has to be fixed already for this to happen. if (type->is() && !type->hasTypeVariable()) { + // Since the binding couldn't be performed, the type variable is a + // hole regardless whether it would be bound later to some other + // type or not. If this is not reflected in constraint system + // it would let the solver to form a _valid_ solution as if the + // constraint between the type variable and the unresolved dependent + // member type never existed. + increaseScore(SK_Hole); recordPotentialHole(typeVar); return getTypeMatchSuccess(); } diff --git a/validation-test/Sema/type_checker_crashers_fixed/issue60649.swift b/validation-test/Sema/type_checker_crashers_fixed/issue60649.swift new file mode 100644 index 0000000000000..93d5bf6134f02 --- /dev/null +++ b/validation-test/Sema/type_checker_crashers_fixed/issue60649.swift @@ -0,0 +1,26 @@ +// RUN: %target-typecheck-verify-swift + +protocol P {} + +protocol Key { + associatedtype A: P + // expected-note@-1 {{unable to infer associated type 'A' for protocol 'Key'}} + static var value: A { get } +} + +struct Values { + subscript(type: K.Type) -> K.A { + fatalError() + } +} + +enum MyKey: Key { // expected-error {{type 'MyKey' does not conform to protocol 'Key'}} + static let value = 1 + // expected-note@-1 {{candidate would match and infer 'A' = 'Int' if 'Int' conformed to 'P'}} +} + +extension Values { + var myValue: Int { + get { self[MyKey.self] } + } +} From 38455e29f3fc965145179cec793fc08c6eb8d93f Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Fri, 19 Aug 2022 11:38:20 -0700 Subject: [PATCH 214/491] [Compile Time Constant Extraction] Print fully-qualified type names --- lib/ConstExtract/ConstExtract.cpp | 17 ++++++++++++++--- test/ConstExtraction/fields.swift | 22 +++++++++++----------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index b8e78070f7c6e..0da5503d23583 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -48,6 +48,17 @@ class NominalTypeConformanceCollector : public swift::ASTWalker { } }; +std::string toFullyQualifiedTypeNameString(const swift::Type &Type) { + std::string TypeNameOutput; + llvm::raw_string_ostream OutputStream(TypeNameOutput); + swift::PrintOptions Options; + Options.FullyQualifiedTypes = true; + Options.PreferTypeRepr = true; + Type.print(OutputStream, Options); + OutputStream.flush(); + return TypeNameOutput; +} + } // namespace namespace swift { @@ -171,7 +182,7 @@ gatherConstValuesForPrimary(const std::unordered_set &Protocols, return Result; } -static std::string toString(const CompileTimeValue *Value) { +std::string toString(const CompileTimeValue *Value) { switch (Value->getKind()) { case CompileTimeValue::RawLiteral: return cast(Value)->getValue(); @@ -193,7 +204,7 @@ bool writeAsJSONToFile(const std::vector &ConstValueInfos, for (const auto &TypeInfo : ConstValueInfos) { JSON.object([&] { const auto *TypeDecl = TypeInfo.TypeDecl; - JSON.attribute("typeName", TypeDecl->getName().str().str()); + JSON.attribute("typeName", toFullyQualifiedTypeNameString(TypeDecl->getDeclaredInterfaceType())); JSON.attribute( "kind", TypeDecl->getDescriptiveKindName(TypeDecl->getDescriptiveKind()) @@ -203,7 +214,7 @@ bool writeAsJSONToFile(const std::vector &ConstValueInfos, JSON.object([&] { const auto *PropertyDecl = PropertyInfo.VarDecl; JSON.attribute("label", PropertyDecl->getName().str().str()); - JSON.attribute("type", PropertyDecl->getType().getString()); + JSON.attribute("type", toFullyQualifiedTypeNameString(PropertyDecl->getType())); JSON.attribute("isStatic", PropertyDecl->isStatic() ? "true" : "false"); JSON.attribute("isComputed", diff --git a/test/ConstExtraction/fields.swift b/test/ConstExtraction/fields.swift index 36c071a24c642..3b9c518f304e6 100644 --- a/test/ConstExtraction/fields.swift +++ b/test/ConstExtraction/fields.swift @@ -7,75 +7,75 @@ // CHECK: [ // CHECK-NEXT: // CHECK-NEXT: { -// CHECK-NEXT: "typeName": "Foo", +// CHECK-NEXT: "typeName": "fields.Foo", // CHECK-NEXT: "kind": "struct", // CHECK-NEXT: "properties": [ // CHECK-NEXT: { // CHECK-NEXT: "label": "p1", -// CHECK-NEXT: "type": "String", +// CHECK-NEXT: "type": "Swift.String", // CHECK-NEXT: "isStatic": "false", // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "value": "Hello, World" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p5", -// CHECK-NEXT: "type": "[Int]", +// CHECK-NEXT: "type": "[Swift.Int]", // CHECK-NEXT: "isStatic": "false", // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "value": "[1, 2, 3, 4, 5, 6, 7, 8, 9]" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p6", -// CHECK-NEXT: "type": "Bool", +// CHECK-NEXT: "type": "Swift.Bool", // CHECK-NEXT: "isStatic": "false", // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "value": "false" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p7", -// CHECK-NEXT: "type": "Bool?", +// CHECK-NEXT: "type": "Swift.Bool?", // CHECK-NEXT: "isStatic": "false", // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "value": "nil" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p8", -// CHECK-NEXT: "type": "(Int, Float)", +// CHECK-NEXT: "type": "(Swift.Int, Swift.Float)", // CHECK-NEXT: "isStatic": "false", // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "value": "(42, 6.6)" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p9", -// CHECK-NEXT: "type": "[String : Int]", +// CHECK-NEXT: "type": "[Swift.String : Swift.Int]", // CHECK-NEXT: "isStatic": "false", // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "value": "[(\"One\", 1), (\"Two\", 2), (\"Three\", 3)]" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p0", -// CHECK-NEXT: "type": "Int", +// CHECK-NEXT: "type": "Swift.Int", // CHECK-NEXT: "isStatic": "true", // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "value": "11" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p2", -// CHECK-NEXT: "type": "Float", +// CHECK-NEXT: "type": "Swift.Float", // CHECK-NEXT: "isStatic": "true", // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "value": "42.2" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p3", -// CHECK-NEXT: "type": "Int", +// CHECK-NEXT: "type": "Swift.Int", // CHECK-NEXT: "isStatic": "false", // CHECK-NEXT: "isComputed": "true", // CHECK-NEXT: "value": "Unknown" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "label": "p4", -// CHECK-NEXT: "type": "Int", +// CHECK-NEXT: "type": "Swift.Int", // CHECK-NEXT: "isStatic": "true", // CHECK-NEXT: "isComputed": "true", // CHECK-NEXT: "value": "Unknown" From 869e70f99333e605937970ddea9ce999ce8883c3 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Fri, 19 Aug 2022 11:40:08 -0700 Subject: [PATCH 215/491] [Compile Time Constant Extraction] Add 'features.json' entry for ability to emit constant value side-car file --- lib/Option/features.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Option/features.json b/lib/Option/features.json index 45e206580d860..aec42f89ffcb2 100644 --- a/lib/Option/features.json +++ b/lib/Option/features.json @@ -23,6 +23,9 @@ }, { "name": "enable-bare-slash-regex-updated" + }, + { + "name": "emit-const-value-sidecar" } ] } From 9e3f5f9cea01d9e8b1eafb85fc4e06c3fb80a2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Fri, 19 Aug 2022 10:31:21 -0700 Subject: [PATCH 216/491] [ModuleInterface] Print missing imports in swiftinterface Hack to fix swiftinterfaces in case of missing imports. We can get rid of this logic when we don't leak the use of non-locally imported things in API. --- include/swift/AST/FileUnit.h | 4 +++ include/swift/AST/Module.h | 4 +++ include/swift/AST/SourceFile.h | 9 +++++++ .../swift/Frontend/ModuleInterfaceSupport.h | 3 +++ include/swift/Option/FrontendOptions.td | 5 ++++ lib/AST/Module.cpp | 25 +++++++++++++++++++ lib/Frontend/CompilerInvocation.cpp | 2 ++ lib/Frontend/ModuleInterfaceSupport.cpp | 4 +++ .../implicit-import-in-inlinable-code.swift | 8 ++++++ test/Sema/implicit-import-typealias.swift | 13 ++++++++++ 10 files changed, 77 insertions(+) diff --git a/include/swift/AST/FileUnit.h b/include/swift/AST/FileUnit.h index 63f7b6d0aab84..e9b85c8313dd2 100644 --- a/include/swift/AST/FileUnit.h +++ b/include/swift/AST/FileUnit.h @@ -271,6 +271,10 @@ class FileUnit : public DeclContext, public ASTAllocated { getImportedModules(SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const {} + /// Lists modules that are not imported from this file and used in API. + virtual void + getMissingImportedModules(SmallVectorImpl &imports) const {} + /// \see ModuleDecl::getImportedModulesForLookup virtual void getImportedModulesForLookup( SmallVectorImpl &imports) const { diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 309ed9aa357c7..459bf282756c9 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -713,6 +713,10 @@ class ModuleDecl void getImportedModules(SmallVectorImpl &imports, ImportFilter filter = ImportFilterKind::Exported) const; + /// Lists modules that are not imported from a file and used in API. + void + getMissingImportedModules(SmallVectorImpl &imports) const; + /// Looks up which modules are imported by this module, ignoring any that /// won't contain top-level decls. /// diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index ff87515cf265e..1075bd0563c84 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -399,6 +399,15 @@ class SourceFile final : public FileUnit { SWIFT_DEBUG_DUMPER(dumpSeparatelyImportedOverlays()); + llvm::SmallDenseSet MissingImportedModules; + + void addMissingImportedModule(ImportedModule module) const { + const_cast(this)->MissingImportedModules.insert(module); + } + + void getMissingImportedModules( + SmallVectorImpl &imports) const override; + void cacheVisibleDecls(SmallVectorImpl &&globals) const; const SmallVectorImpl &getCachedVisibleDecls() const; diff --git a/include/swift/Frontend/ModuleInterfaceSupport.h b/include/swift/Frontend/ModuleInterfaceSupport.h index 3a335327c802c..51d8d5332b3e0 100644 --- a/include/swift/Frontend/ModuleInterfaceSupport.h +++ b/include/swift/Frontend/ModuleInterfaceSupport.h @@ -53,6 +53,9 @@ struct ModuleInterfaceOptions { /// when PrintSPIs is true. bool ExperimentalSPIImports = false; + /// Print imports that are missing from the source and used in API. + bool PrintMissingImports = true; + /// Intentionally print invalid syntax into the file. bool DebugPrintInvalidSyntax = false; diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 9260e6a84e94c..dc063aaa5bc09 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -900,6 +900,11 @@ def experimental_spi_imports : Flag<["-"], "experimental-spi-imports">, HelpText<"Enable experimental support for SPI imports">; +def disable_print_missing_imports_in_module_interface : + Flag<["-"], "disable-print-missing-imports-in-module-interface">, + HelpText<"Disable adding to the module interface imports used from API and " + "missing from the sources">; + // [FIXME: Clang-type-plumbing] Make this a SIL-only option once we start // unconditionally emitting non-canonical Clang types in swiftinterfaces. def experimental_print_full_convention : diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index c7c9b56fe1b46..dd927a9ca39bc 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1570,6 +1570,11 @@ void ModuleDecl::getImportedModules(SmallVectorImpl &modules, FORWARD(getImportedModules, (modules, filter)); } +void ModuleDecl::getMissingImportedModules( + SmallVectorImpl &imports) const { + FORWARD(getMissingImportedModules, (imports)); +} + void SourceFile::getImportedModules(SmallVectorImpl &modules, ModuleDecl::ImportFilter filter) const { @@ -1604,6 +1609,12 @@ SourceFile::getImportedModules(SmallVectorImpl &modules, } } +void SourceFile::getMissingImportedModules( + SmallVectorImpl &modules) const { + for (auto module : MissingImportedModules) + modules.push_back(module); +} + void SourceFile::dumpSeparatelyImportedOverlays() const { for (auto &pair : separatelyImportedOverlays) { auto &underlying = std::get<0>(pair); @@ -2535,6 +2546,20 @@ RestrictedImportKind SourceFile::getRestrictedImportKind(const ModuleDecl *modul if (imports.isImportedBy(module, getParentModule())) return RestrictedImportKind::None; + if (importKind == RestrictedImportKind::Implicit && + module->getLibraryLevel() == LibraryLevel::API) { + // Hack to fix swiftinterfaces in case of missing imports. + // We can get rid of this logic when we don't leak the use of non-locally + // imported things in API. + ImportPath::Element pathElement = {module->getName(), SourceLoc()}; + auto pathArray = getASTContext().AllocateCopy( + llvm::makeArrayRef(pathElement)); + auto missingImport = ImportedModule( + ImportPath::Access(pathArray), + const_cast(module)); + addMissingImportedModule(missingImport); + } + return importKind; } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index f52fe884217be..6f43c13006f39 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -373,6 +373,8 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts, Args.hasArg(OPT_experimental_spi_imports); Opts.DebugPrintInvalidSyntax |= Args.hasArg(OPT_debug_emit_invalid_swiftinterface_syntax); + Opts.PrintMissingImports = + !Args.hasArg(OPT_disable_print_missing_imports_in_module_interface); if (const Arg *A = Args.getLastArg(OPT_library_level)) { StringRef contents = A->getValue(); diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 49983e30ecdfb..515d21b42ef3b 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -219,6 +219,10 @@ static void printImports(raw_ostream &out, SmallVector allImports; M->getImportedModules(allImports, allImportFilter); + + if (Opts.PrintMissingImports) + M->getMissingImportedModules(allImports); + ImportedModule::removeDuplicates(allImports); diagnoseScopedImports(M->getASTContext().Diags, allImports); diff --git a/test/Sema/implicit-import-in-inlinable-code.swift b/test/Sema/implicit-import-in-inlinable-code.swift index 467d9e5758f19..35be4816cc4b9 100644 --- a/test/Sema/implicit-import-in-inlinable-code.swift +++ b/test/Sema/implicit-import-in-inlinable-code.swift @@ -16,6 +16,14 @@ /// In Swift 6, it's an error. // RUN: %target-swift-frontend -emit-module %t/clientFileA-Swift6.swift %t/clientFileB.swift -module-name client -o %t/client.swiftmodule -I %t -verify -swift-version 6 +/// The swiftinterface is broken by the missing import without the workaround. +// RUN: %target-swift-emit-module-interface(%t/ClientBroken.swiftinterface) %t/clientFileA-Swift5.swift %t/clientFileB.swift -I %t -disable-print-missing-imports-in-module-interface +// RUN: not %target-swift-typecheck-module-from-interface(%t/ClientBroken.swiftinterface) -I %t + +/// The swiftinterface parses fine with the workaround adding the missing imports. +// RUN: %target-swift-emit-module-interface(%t/ClientFixed.swiftinterface) %t/clientFileA-Swift5.swift %t/clientFileB.swift -I %t +// RUN: %target-swift-typecheck-module-from-interface(%t/ClientFixed.swiftinterface) -I %t + // REQUIRES: asserts // BEGIN empty.swift diff --git a/test/Sema/implicit-import-typealias.swift b/test/Sema/implicit-import-typealias.swift index 50e940a687c27..51c2f6595e4ea 100644 --- a/test/Sema/implicit-import-typealias.swift +++ b/test/Sema/implicit-import-typealias.swift @@ -11,6 +11,19 @@ // RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesImplementationOnlyImport.swift -I %t // RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesWithImport.swift -I %t +/// The swiftinterface is broken by the missing import without the workaround. +// RUN: %target-swift-emit-module-interface(%t/UsesAliasesNoImport.swiftinterface) %t/UsesAliasesNoImport.swift -I %t \ +// RUN: -disable-print-missing-imports-in-module-interface +// RUN: not %target-swift-typecheck-module-from-interface(%t/UsesAliasesNoImport.swiftinterface) -I %t + +/// The swiftinterface parses fine with the workaround adding the missing imports. +// RUN: %target-swift-emit-module-interface(%t/UsesAliasesNoImportFixed.swiftinterface) %t/UsesAliasesNoImport.swift -I %t +// RUN: %target-swift-typecheck-module-from-interface(%t/UsesAliasesNoImportFixed.swiftinterface) -I %t + +/// The module with an implementation-only import is not affected by the workaround and remains broken. +// RUN: %target-swift-emit-module-interface(%t/UsesAliasesImplementationOnlyImport.swiftinterface) %t/UsesAliasesImplementationOnlyImport.swift -I %t \ +// RUN: -disable-print-missing-imports-in-module-interface +// RUN: not %target-swift-typecheck-module-from-interface(%t/UsesAliasesImplementationOnlyImport.swiftinterface) -I %t //--- Original.swift From cf9a7478c3d1691d26f71229809ebfa959d8c8d7 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 19 Aug 2022 12:50:12 -0700 Subject: [PATCH 217/491] Apply `@_unsafeInheritExecutor` to `with(Throwing)TaskGroup`. Fixes rdar://98461630. --- stdlib/public/Concurrency/TaskGroup.swift | 2 ++ .../unsafe_inherit_executor_lib.swift | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 test/Concurrency/unsafe_inherit_executor_lib.swift diff --git a/stdlib/public/Concurrency/TaskGroup.swift b/stdlib/public/Concurrency/TaskGroup.swift index 4313b9b9be848..ffc2384076ed5 100644 --- a/stdlib/public/Concurrency/TaskGroup.swift +++ b/stdlib/public/Concurrency/TaskGroup.swift @@ -65,6 +65,7 @@ import Swift /// use the `withThrowingTaskGroup(of:returning:body:)` method instead. @available(SwiftStdlib 5.1, *) @_silgen_name("$ss13withTaskGroup2of9returning4bodyq_xm_q_mq_ScGyxGzYaXEtYar0_lF") +@_unsafeInheritExecutor @inlinable public func withTaskGroup( of childTaskResultType: ChildTaskResult.Type, @@ -157,6 +158,7 @@ public func withTaskGroup( /// or to let the group rethrow the error. @available(SwiftStdlib 5.1, *) @_silgen_name("$ss21withThrowingTaskGroup2of9returning4bodyq_xm_q_mq_Scgyxs5Error_pGzYaKXEtYaKr0_lF") +@_unsafeInheritExecutor @inlinable public func withThrowingTaskGroup( of childTaskResultType: ChildTaskResult.Type, diff --git a/test/Concurrency/unsafe_inherit_executor_lib.swift b/test/Concurrency/unsafe_inherit_executor_lib.swift new file mode 100644 index 0000000000000..7883df0e9d3a9 --- /dev/null +++ b/test/Concurrency/unsafe_inherit_executor_lib.swift @@ -0,0 +1,16 @@ +// RUN: %target-swift-frontend -typecheck -verify -disable-availability-checking %s -strict-concurrency=complete + +actor A { + func g() { } + func h() throws { } + + func f() async throws { + await withTaskGroup(of: Int.self, returning: Void.self) { group in + g() + } + + try await withThrowingTaskGroup(of: Int.self, returning: Void.self) { group in + try h() + } + } +} From ee4f6b1f75267f75ed5240a3f0902185484af8e2 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 19 Aug 2022 13:03:54 -0700 Subject: [PATCH 218/491] Make CheckedContinuation and UnsafeContinuation unconditionally Sendable. The continuation types were conditionally `Sendable` based on whether the result type of the continuation was `Sendable`. However, conceptually, the return value is never leaving the current task, so it is never actually crossing concurrency boundaries. Therefore, we can make the continuation types unconditionally `Sendable`. Fixes rdar://98462858. --- .../public/BackDeployConcurrency/CheckedContinuation.swift | 5 +---- stdlib/public/BackDeployConcurrency/PartialAsyncTask.swift | 5 +---- stdlib/public/Concurrency/CheckedContinuation.swift | 5 +---- stdlib/public/Concurrency/PartialAsyncTask.swift | 5 +---- test/Concurrency/async_tasks.swift | 3 +-- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/stdlib/public/BackDeployConcurrency/CheckedContinuation.swift b/stdlib/public/BackDeployConcurrency/CheckedContinuation.swift index aadc8cfa39ff8..64363e43920c9 100644 --- a/stdlib/public/BackDeployConcurrency/CheckedContinuation.swift +++ b/stdlib/public/BackDeployConcurrency/CheckedContinuation.swift @@ -119,7 +119,7 @@ internal final class CheckedContinuationCanary: @unchecked Sendable { /// you can replace one with the other in most circumstances, /// without making other changes. @available(SwiftStdlib 5.1, *) -public struct CheckedContinuation { +public struct CheckedContinuation: Sendable { private let canary: CheckedContinuationCanary /// Creates a checked continuation from an unsafe continuation. @@ -186,9 +186,6 @@ public struct CheckedContinuation { } } -@available(SwiftStdlib 5.1, *) -extension CheckedContinuation: Sendable where T: Sendable { } - @available(SwiftStdlib 5.1, *) extension CheckedContinuation { /// Resume the task awaiting the continuation by having it either diff --git a/stdlib/public/BackDeployConcurrency/PartialAsyncTask.swift b/stdlib/public/BackDeployConcurrency/PartialAsyncTask.swift index 4c2618a104570..a40ca1b6fb243 100644 --- a/stdlib/public/BackDeployConcurrency/PartialAsyncTask.swift +++ b/stdlib/public/BackDeployConcurrency/PartialAsyncTask.swift @@ -69,7 +69,7 @@ public struct UnownedJob: Sendable { /// without making other changes. @available(SwiftStdlib 5.1, *) @frozen -public struct UnsafeContinuation { +public struct UnsafeContinuation: Sendable { @usableFromInline internal var context: Builtin.RawUnsafeContinuation @_alwaysEmitIntoClient @@ -144,9 +144,6 @@ public struct UnsafeContinuation { } } -@available(SwiftStdlib 5.1, *) -extension UnsafeContinuation: Sendable where T: Sendable { } - @available(SwiftStdlib 5.1, *) extension UnsafeContinuation { /// Resume the task that's awaiting the continuation diff --git a/stdlib/public/Concurrency/CheckedContinuation.swift b/stdlib/public/Concurrency/CheckedContinuation.swift index 22317e112de5b..03b1426bdd8ea 100644 --- a/stdlib/public/Concurrency/CheckedContinuation.swift +++ b/stdlib/public/Concurrency/CheckedContinuation.swift @@ -119,7 +119,7 @@ internal final class CheckedContinuationCanary: @unchecked Sendable { /// you can replace one with the other in most circumstances, /// without making other changes. @available(SwiftStdlib 5.1, *) -public struct CheckedContinuation { +public struct CheckedContinuation: Sendable { private let canary: CheckedContinuationCanary /// Creates a checked continuation from an unsafe continuation. @@ -186,9 +186,6 @@ public struct CheckedContinuation { } } -@available(SwiftStdlib 5.1, *) -extension CheckedContinuation: Sendable where T: Sendable { } - @available(SwiftStdlib 5.1, *) extension CheckedContinuation { /// Resume the task awaiting the continuation by having it either diff --git a/stdlib/public/Concurrency/PartialAsyncTask.swift b/stdlib/public/Concurrency/PartialAsyncTask.swift index 0e888117fac65..75d4b5705176b 100644 --- a/stdlib/public/Concurrency/PartialAsyncTask.swift +++ b/stdlib/public/Concurrency/PartialAsyncTask.swift @@ -69,7 +69,7 @@ public struct UnownedJob: Sendable { /// without making other changes. @available(SwiftStdlib 5.1, *) @frozen -public struct UnsafeContinuation { +public struct UnsafeContinuation: Sendable { @usableFromInline internal var context: Builtin.RawUnsafeContinuation @_alwaysEmitIntoClient @@ -144,9 +144,6 @@ public struct UnsafeContinuation { } } -@available(SwiftStdlib 5.1, *) -extension UnsafeContinuation: Sendable where T: Sendable { } - @available(SwiftStdlib 5.1, *) extension UnsafeContinuation { /// Resume the task that's awaiting the continuation diff --git a/test/Concurrency/async_tasks.swift b/test/Concurrency/async_tasks.swift index e35f963bee526..e134ec9eebe42 100644 --- a/test/Concurrency/async_tasks.swift +++ b/test/Concurrency/async_tasks.swift @@ -89,7 +89,6 @@ func test_unsafeThrowingContinuations() async throws { // ==== Sendability ------------------------------------------------------------ class NotSendable { } -// expected-note@-1{{class 'NotSendable' does not conform to the 'Sendable' protocol}} @available(SwiftStdlib 5.1, *) func test_nonsendableContinuation() async throws { @@ -99,7 +98,7 @@ func test_nonsendableContinuation() async throws { let _: NotSendable = try await withUnsafeThrowingContinuation { continuation in Task { - continuation.resume(returning: NotSendable()) // expected-warning{{capture of 'continuation' with non-sendable type 'UnsafeContinuation' in a `@Sendable` closure}} + continuation.resume(returning: NotSendable()) // okay } } } From 489c16e906d1b4d5a3b04754c5296954bf90c458 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Fri, 19 Aug 2022 13:10:48 -0700 Subject: [PATCH 219/491] [interop][SwiftToCxx] fix the circular depedency issue for struct emission --- lib/PrintAsClang/DeclAndTypePrinter.cpp | 14 +- lib/PrintAsClang/DeclAndTypePrinter.h | 5 +- lib/PrintAsClang/ModuleContentsWriter.cpp | 47 ++++--- lib/PrintAsClang/PrintClangValueType.cpp | 7 + lib/PrintAsClang/PrintClangValueType.h | 2 + .../imported-enum-refs-in-cxx.swift | 17 ++- .../imported-struct-refs-in-cxx.swift | 24 ++-- .../SwiftToCxx/initializers/init-in-cxx.swift | 51 +++---- .../SwiftToCxx/methods/method-in-cxx.swift | 41 +++--- .../methods/mutating-method-in-cxx.swift | 32 ++--- .../SwiftToCxx/properties/getter-in-cxx.swift | 124 +++++++++--------- .../SwiftToCxx/properties/setter-in-cxx.swift | 104 +++++++-------- .../structs/resilient-struct-in-cxx.swift | 57 ++++---- ...swift-struct-circular-dependent-defs.swift | 44 +++++++ 14 files changed, 315 insertions(+), 254 deletions(-) create mode 100644 test/Interop/SwiftToCxx/structs/swift-struct-circular-dependent-defs.swift diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index dc08e8abfc87d..6ffcc26596fae 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -114,8 +114,6 @@ class DeclAndTypePrinter::Implementation SmallVector openFunctionTypes; - std::string outOfLineDefinitions; - ASTContext &getASTContext() const { return owningPrinter.M.getASTContext(); } @@ -218,7 +216,6 @@ class DeclAndTypePrinter::Implementation template void printMembers(R &&members) { bool protocolMembersOptional = false; - assert(outOfLineDefinitions.empty()); for (const Decl *member : members) { auto VD = dyn_cast(member); if (!VD || !shouldInclude(VD) || isa(VD)) @@ -302,8 +299,6 @@ class DeclAndTypePrinter::Implementation // FIXME: Print availability. ClangClassTypePrinter(os).printClassTypeDecl( CD, [&]() { printMembers(CD->getMembers()); }); - os << outOfLineDefinitions; - outOfLineDefinitions.clear(); return; } @@ -356,8 +351,6 @@ class DeclAndTypePrinter::Implementation owningPrinter.interopContext); printer.printValueTypeDecl( SD, /*bodyPrinter=*/[&]() { printMembers(SD->getMembers()); }); - os << outOfLineDefinitions; - outOfLineDefinitions.clear(); } void visitExtensionDecl(ExtensionDecl *ED) { @@ -580,8 +573,6 @@ class DeclAndTypePrinter::Implementation os << " }\n"; // operator cases()'s closing bracket os << "\n"; }); - os << outOfLineDefinitions; - outOfLineDefinitions.clear(); } void visitEnumDecl(EnumDecl *ED) { @@ -767,10 +758,9 @@ class DeclAndTypePrinter::Implementation /*isDefinition=*/false); } - llvm::raw_string_ostream defOS(outOfLineDefinitions); DeclAndTypeClangFunctionPrinter defPrinter( - defOS, owningPrinter.prologueOS, owningPrinter.typeMapping, - owningPrinter.interopContext); + owningPrinter.outOfLineDefinitionsOS, owningPrinter.prologueOS, + owningPrinter.typeMapping, owningPrinter.interopContext); if (auto *accessor = dyn_cast(AFD)) { diff --git a/lib/PrintAsClang/DeclAndTypePrinter.h b/lib/PrintAsClang/DeclAndTypePrinter.h index 31fdd04437a96..cf99c981622b0 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.h +++ b/lib/PrintAsClang/DeclAndTypePrinter.h @@ -42,6 +42,7 @@ class DeclAndTypePrinter { ModuleDecl &M; raw_ostream &os; raw_ostream &prologueOS; + raw_ostream &outOfLineDefinitionsOS; const DelayedMemberSet &delayedMembers; PrimitiveTypeMapping &typeMapping; SwiftToClangInteropContext &interopContext; @@ -57,11 +58,13 @@ class DeclAndTypePrinter { public: DeclAndTypePrinter(ModuleDecl &mod, raw_ostream &out, raw_ostream &prologueOS, + raw_ostream &outOfLineDefinitionsOS, DelayedMemberSet &delayed, PrimitiveTypeMapping &typeMapping, SwiftToClangInteropContext &interopContext, AccessLevel access, OutputLanguageMode outputLang) - : M(mod), os(out), prologueOS(prologueOS), delayedMembers(delayed), + : M(mod), os(out), prologueOS(prologueOS), + outOfLineDefinitionsOS(outOfLineDefinitionsOS), delayedMembers(delayed), typeMapping(typeMapping), interopContext(interopContext), minRequiredAccess(access), outputLang(outputLang) {} diff --git a/lib/PrintAsClang/ModuleContentsWriter.cpp b/lib/PrintAsClang/ModuleContentsWriter.cpp index 5be6c7470c02f..1ef36275073b7 100644 --- a/lib/PrintAsClang/ModuleContentsWriter.cpp +++ b/lib/PrintAsClang/ModuleContentsWriter.cpp @@ -16,6 +16,7 @@ #include "DeclAndTypePrinter.h" #include "OutputLanguageMode.h" #include "PrimitiveTypeMapping.h" +#include "PrintClangValueType.h" #include "PrintSwiftToClangCoreScaffold.h" #include "swift/AST/ExistentialLayout.h" @@ -126,6 +127,8 @@ class ModuleWriter { std::vector declsToWrite; DelayedMemberSet delayedMembers; PrimitiveTypeMapping typeMapping; + std::string outOfLineDefinitions; + llvm::raw_string_ostream outOfLineDefinitionsOS; DeclAndTypePrinter printer; OutputLanguageMode outputLangMode; @@ -135,8 +138,9 @@ class ModuleWriter { SwiftToClangInteropContext &interopContext, AccessLevel access, OutputLanguageMode outputLang) : os(os), imports(imports), M(mod), - printer(M, os, prologueOS, delayedMembers, typeMapping, interopContext, - access, outputLang), + outOfLineDefinitionsOS(outOfLineDefinitions), + printer(M, os, prologueOS, outOfLineDefinitionsOS, delayedMembers, + typeMapping, interopContext, access, outputLang), outputLangMode(outputLang) {} PrimitiveTypeMapping &getTypeMapping() { return typeMapping; } @@ -238,14 +242,8 @@ class ModuleWriter { os << "@protocol " << getNameForObjC(PD) << ";\n"; }); } - - void forwardDeclare(const EnumDecl *ED) { - // TODO: skip for now; will overhaul the forward decals for c++ in the - // future - if (outputLangMode == swift::OutputLanguageMode::Cxx) { - return; - } + void forwardDeclare(const EnumDecl *ED) { assert(ED->isObjC() || ED->hasClangNode()); forwardDeclare(ED, [&]{ @@ -256,6 +254,14 @@ class ModuleWriter { } void forwardDeclareType(const TypeDecl *TD) { + if (outputLangMode == OutputLanguageMode::Cxx) { + if (isa(TD) || isa(TD)) { + auto *NTD = cast(TD); + forwardDeclare( + NTD, [&]() { ClangValueTypePrinter::forwardDeclType(os, NTD); }); + } + return; + } if (auto CD = dyn_cast(TD)) { if (!forwardDeclare(CD)) { (void)addImport(CD); @@ -274,9 +280,6 @@ class ModuleWriter { forwardDeclare(ED); } else if (isa(TD)) { llvm_unreachable("should not see type params here"); - } else if (isa(TD)) { - // FIXME: add support here. - return; } else { assert(false && "unknown local type decl"); } @@ -290,6 +293,11 @@ class ModuleWriter { case DeclKind::Protocol: case DeclKind::Extension: break; + case DeclKind::Struct: + case DeclKind::Enum: + if (outputLangMode == OutputLanguageMode::Cxx) + break; + LLVM_FALLTHROUGH; default: llvm_unreachable("unexpected container kind"); } @@ -346,11 +354,12 @@ class ModuleWriter { } // Protocols should be delayed wholesale unless we might have a cycle. - auto *proto = cast(container); - if (!hasBeenRequested(proto) || !hasBeenRequested(TD)) { - if (!require(TD)) - hadAnyDelayedMembers = true; - return; + if (auto *proto = dyn_cast(container)) { + if (!hasBeenRequested(proto) || !hasBeenRequested(TD)) { + if (!require(TD)) + hadAnyDelayedMembers = true; + return; + } } // Otherwise, we have a cyclic dependency. Give up and continue with @@ -426,6 +435,8 @@ class ModuleWriter { bool writeStruct(const StructDecl *SD) { if (addImport(SD)) return true; + if (outputLangMode == OutputLanguageMode::Cxx) + (void)forwardDeclareMemberTypes(SD->getMembers(), SD); printer.print(SD); return true; } @@ -646,6 +657,8 @@ class ModuleWriter { } printer.printAdHocCategory(make_range(groupBegin, delayedMembers.end())); } + // Print any out of line definitions. + os << outOfLineDefinitionsOS.str(); } }; } // end anonymous namespace diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index 75f926ab17b95..527a44b49f262 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -80,6 +80,13 @@ printCValueTypeStorageStruct(raw_ostream &os, const NominalTypeDecl *typeDecl, os << "};\n\n"; } +void ClangValueTypePrinter::forwardDeclType(raw_ostream &os, + const NominalTypeDecl *typeDecl) { + os << "class "; + ClangSyntaxPrinter(os).printBaseName(typeDecl); + os << ";\n"; +} + void ClangValueTypePrinter::printValueTypeDecl( const NominalTypeDecl *typeDecl, llvm::function_ref bodyPrinter) { diff --git a/lib/PrintAsClang/PrintClangValueType.h b/lib/PrintAsClang/PrintClangValueType.h index a457506f28784..a8b9b8247f5a7 100644 --- a/lib/PrintAsClang/PrintClangValueType.h +++ b/lib/PrintAsClang/PrintClangValueType.h @@ -98,6 +98,8 @@ class ClangValueTypePrinter { const NominalTypeDecl *typeDecl, StringRef typeMetadataFuncName); + static void forwardDeclType(raw_ostream &os, const NominalTypeDecl *typeDecl); + private: /// Prints out the C stub name used to pass/return value directly for the /// given value type. diff --git a/test/Interop/SwiftToCxx/cross-module-refs/imported-enum-refs-in-cxx.swift b/test/Interop/SwiftToCxx/cross-module-refs/imported-enum-refs-in-cxx.swift index 89a1161c54701..08e595597cfec 100644 --- a/test/Interop/SwiftToCxx/cross-module-refs/imported-enum-refs-in-cxx.swift +++ b/test/Interop/SwiftToCxx/cross-module-refs/imported-enum-refs-in-cxx.swift @@ -21,6 +21,14 @@ public struct UsesEnumsLargeEnum { public let x: LargeEnum } +public func inoutLargeEnum(_ s: inout LargeEnum) { + return s = LargeEnum.B +} + +// CHECK: inline void inoutLargeEnum(Enums::LargeEnum& s) noexcept { +// CHECK-NEXT: return _impl::$s9UsesEnums14inoutLargeEnumyy0B00dE0OzF(Enums::_impl::_impl_LargeEnum::getOpaquePointer(s)); +// CHECK-NEXT: } + // CHECK: inline Enums::LargeEnum UsesEnumsLargeEnum::passThroughStructSeveralI64(const Enums::LargeEnum& y) const { // CHECK-NEXT: return Enums::_impl::_impl_LargeEnum::returnNewValue([&](void * _Nonnull result) { // CHECK-NEXT: _impl::$s9UsesEnums0aB9LargeEnumV27passThroughStructSeveralI64y0B00cD0OAGF(result, Enums::_impl::_impl_LargeEnum::getOpaquePointer(y), _getOpaquePointer()); @@ -31,12 +39,3 @@ public struct UsesEnumsLargeEnum { // CHECK-NEXT: _impl::$s9UsesEnums0aB9LargeEnumV1x0B00cD0Ovg(result, _getOpaquePointer()); // CHECK-NEXT: }); // CHECK-NEXT: } - - -public func inoutLargeEnum(_ s: inout LargeEnum) { - return s = LargeEnum.B -} - -// CHECK: inline void inoutLargeEnum(Enums::LargeEnum& s) noexcept { -// CHECK-NEXT: return _impl::$s9UsesEnums14inoutLargeEnumyy0B00dE0OzF(Enums::_impl::_impl_LargeEnum::getOpaquePointer(s)); -// CHECK-NEXT: } diff --git a/test/Interop/SwiftToCxx/cross-module-refs/imported-struct-refs-in-cxx.swift b/test/Interop/SwiftToCxx/cross-module-refs/imported-struct-refs-in-cxx.swift index 89a7606f8eab3..95004197fea45 100644 --- a/test/Interop/SwiftToCxx/cross-module-refs/imported-struct-refs-in-cxx.swift +++ b/test/Interop/SwiftToCxx/cross-module-refs/imported-struct-refs-in-cxx.swift @@ -24,18 +24,6 @@ public struct UsesStructsStruct { // CHECK: inline Structs::StructSeveralI64 passThroughStructSeveralI64(const Structs::StructSeveralI64& y) const; // CHECK-NEXT: inline Structs::StructSeveralI64 getX() const; -// CHECK: inline Structs::StructSeveralI64 UsesStructsStruct::passThroughStructSeveralI64(const Structs::StructSeveralI64& y) const { -// CHECK-NEXT: return Structs::_impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) { -// CHECK-NEXT: _impl::$s11UsesStructs0aB6StructV011passThroughC10SeveralI64y0B00cfG0VAGF(result, Structs::_impl::_impl_StructSeveralI64::getOpaquePointer(y), _getOpaquePointer()); -// CHECK-NEXT: }); -// CHECK-NEXT: } - -// CHECK: inline Structs::StructSeveralI64 UsesStructsStruct::getX() const { -// CHECK-NEXT: return Structs::_impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) { -// CHECK-NEXT: _impl::$s11UsesStructs0aB6StructV1x0B00C10SeveralI64Vvg(result, _getOpaquePointer()); -// CHECK-NEXT: }); -// CHECK-NEXT: } - public func passThroughStructSeveralI64(_ x: StructSeveralI64) -> StructSeveralI64 { return Structs.passThroughStructSeveralI64(i: 0, x, j: 2) @@ -65,3 +53,15 @@ public func passThroughStructSmallDirect(_ x: SmallStructDirectPassing) -> Small // CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_SmallStructDirectPassing(result, _impl::$s11UsesStructs28passThroughStructSmallDirecty0B00feG7PassingVAEF(_impl::swift_interop_passDirect_Structs_SmallStructDirectPassing(Structs::_impl::_impl_SmallStructDirectPassing::getOpaquePointer(x)))); // CHECK-NEXT: }); // CHECK-NEXT: } + +// CHECK: inline Structs::StructSeveralI64 UsesStructsStruct::passThroughStructSeveralI64(const Structs::StructSeveralI64& y) const { +// CHECK-NEXT: return Structs::_impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) { +// CHECK-NEXT: _impl::$s11UsesStructs0aB6StructV011passThroughC10SeveralI64y0B00cfG0VAGF(result, Structs::_impl::_impl_StructSeveralI64::getOpaquePointer(y), _getOpaquePointer()); +// CHECK-NEXT: }); +// CHECK-NEXT: } + +// CHECK: inline Structs::StructSeveralI64 UsesStructsStruct::getX() const { +// CHECK-NEXT: return Structs::_impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) { +// CHECK-NEXT: _impl::$s11UsesStructs0aB6StructV1x0B00C10SeveralI64Vvg(result, _getOpaquePointer()); +// CHECK-NEXT: }); +// CHECK-NEXT: } diff --git a/test/Interop/SwiftToCxx/initializers/init-in-cxx.swift b/test/Interop/SwiftToCxx/initializers/init-in-cxx.swift index 449a00ef94123..e5f7ae9deb54f 100644 --- a/test/Interop/SwiftToCxx/initializers/init-in-cxx.swift +++ b/test/Interop/SwiftToCxx/initializers/init-in-cxx.swift @@ -38,20 +38,6 @@ public struct FirstSmallStruct { // CHECK-NEXT: static inline FirstSmallStruct init(swift::Int x); // CHECK-NEXT: private: -// CHECK: inline uint32_t FirstSmallStruct::getX() const { -// CHECK-NEXT: return _impl::$s4Init16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Init_FirstSmallStruct(_getOpaquePointer())); -// CHECK-NEXT: } -// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init() { -// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { -// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVACycfC()); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init(swift::Int x) { -// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { -// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVyACSicfC(x)); -// CHECK-NEXT: }); -// CHECK-NEXT: } - public struct LargeStruct { public let x1, x2, x3, x4, x5, x6: Int @@ -80,17 +66,6 @@ public struct LargeStruct { // CHECK-NEXT: static inline LargeStruct init(swift::Int x, const FirstSmallStruct& y); // CHECK-NEXT: private: -// CHECK: inline LargeStruct LargeStruct::init() { -// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { -// CHECK-NEXT: _impl::$s4Init11LargeStructVACycfC(result); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK-NEXT: inline LargeStruct LargeStruct::init(swift::Int x, const FirstSmallStruct& y) { -// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { -// CHECK-NEXT: _impl::$s4Init11LargeStructV1x1yACSi_AA010FirstSmallC0VtcfC(result, x, _impl::swift_interop_passDirect_Init_FirstSmallStruct(_impl::_impl_FirstSmallStruct::getOpaquePointer(y))); -// CHECK-NEXT: }); -// CHECK-NEXT: } - private class RefCountedClass { let x: Int @@ -118,6 +93,32 @@ public struct StructWithRefCountStoredProp { // CHECK: static inline StructWithRefCountStoredProp init(); // CHECK-NEXT: static inline StructWithRefCountStoredProp init(swift::Int x); + +// CHECK: inline uint32_t FirstSmallStruct::getX() const { +// CHECK-NEXT: return _impl::$s4Init16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Init_FirstSmallStruct(_getOpaquePointer())); +// CHECK-NEXT: } +// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init() { +// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { +// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVACycfC()); +// CHECK-NEXT: }); +// CHECK-NEXT: } +// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init(swift::Int x) { +// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { +// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVyACSicfC(x)); +// CHECK-NEXT: }); +// CHECK-NEXT: } + +// CHECK: inline LargeStruct LargeStruct::init() { +// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { +// CHECK-NEXT: _impl::$s4Init11LargeStructVACycfC(result); +// CHECK-NEXT: }); +// CHECK-NEXT: } +// CHECK-NEXT: inline LargeStruct LargeStruct::init(swift::Int x, const FirstSmallStruct& y) { +// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { +// CHECK-NEXT: _impl::$s4Init11LargeStructV1x1yACSi_AA010FirstSmallC0VtcfC(result, x, _impl::swift_interop_passDirect_Init_FirstSmallStruct(_impl::_impl_FirstSmallStruct::getOpaquePointer(y))); +// CHECK-NEXT: }); +// CHECK-NEXT: } + // CHECK: inline StructWithRefCountStoredProp StructWithRefCountStoredProp::init() { // CHECK-NEXT: return _impl::_impl_StructWithRefCountStoredProp::returnNewValue([&](char * _Nonnull result) { // CHECK-NEXT: _impl::swift_interop_returnDirect_Init_StructWithRefCountStoredProp(result, _impl::$s4Init28StructWithRefCountStoredPropVACycfC()); diff --git a/test/Interop/SwiftToCxx/methods/method-in-cxx.swift b/test/Interop/SwiftToCxx/methods/method-in-cxx.swift index c16076e7a86cd..b843ab7ea05e5 100644 --- a/test/Interop/SwiftToCxx/methods/method-in-cxx.swift +++ b/test/Interop/SwiftToCxx/methods/method-in-cxx.swift @@ -84,6 +84,27 @@ public final class PassStructInClassMethod { // CHECK-NEXT: inline void mutate(); // CHECK-NEXT: inline ClassWithMethods deepCopy(swift::Int x); +// CHECK: class LargeStruct final { +// CHECK: inline LargeStruct(LargeStruct &&) = default; +// CHECK-NEXT: inline LargeStruct doubled() const; +// CHECK-NEXT: inline void dump() const; +// CHECK-NEXT: inline LargeStruct scaled(swift::Int x, swift::Int y) const; +// CHECK-NEXT: inline LargeStruct added(const LargeStruct& x) const; +// CHECK-NEXT: private + +public func createClassWithMethods(_ x: Int) -> ClassWithMethods { + return ClassWithMethods(x) +} + +public func createLargeStruct() -> LargeStruct { + return LargeStruct(x1: -1, x2: 2, x3: -100, x4: 42, x5: 67, x6: -10101) +} + +public func createPassStructInClassMethod() -> PassStructInClassMethod { + return PassStructInClassMethod() +} + + // CHECK: inline void ClassWithMethods::dump() { // CHECK-NEXT: return _impl::$s7Methods09ClassWithA0C4dumpyyF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); // CHECK-NEXT: } @@ -97,14 +118,6 @@ public final class PassStructInClassMethod { // CHECK-NEXT: return _impl::_impl_ClassWithMethods::makeRetained(_impl::$s7Methods09ClassWithA0C8deepCopyyACSiF(x, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this))); // CHECK-NEXT: } -// CHECK: class LargeStruct final { -// CHECK: inline LargeStruct(LargeStruct &&) = default; -// CHECK-NEXT: inline LargeStruct doubled() const; -// CHECK-NEXT: inline void dump() const; -// CHECK-NEXT: inline LargeStruct scaled(swift::Int x, swift::Int y) const; -// CHECK-NEXT: inline LargeStruct added(const LargeStruct& x) const; -// CHECK-NEXT: private - // CHECK: inline LargeStruct LargeStruct::doubled() const { // CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { // CHECK-NEXT: _impl::$s7Methods11LargeStructV7doubledACyF(result, _getOpaquePointer()); @@ -132,15 +145,3 @@ public final class PassStructInClassMethod { // CHECK-NEXT: inline void PassStructInClassMethod::updateStruct(swift::Int x, const LargeStruct& y) { // CHECK-NEXT: return _impl::$s7Methods23PassStructInClassMethodC06updateC0yySi_AA05LargeC0VtF(x, _impl::_impl_LargeStruct::getOpaquePointer(y), ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); // CHECK-NEXT: } - -public func createClassWithMethods(_ x: Int) -> ClassWithMethods { - return ClassWithMethods(x) -} - -public func createLargeStruct() -> LargeStruct { - return LargeStruct(x1: -1, x2: 2, x3: -100, x4: 42, x5: 67, x6: -10101) -} - -public func createPassStructInClassMethod() -> PassStructInClassMethod { - return PassStructInClassMethod() -} diff --git a/test/Interop/SwiftToCxx/methods/mutating-method-in-cxx.swift b/test/Interop/SwiftToCxx/methods/mutating-method-in-cxx.swift index 6036690577507..8ee2ba21d2cfc 100644 --- a/test/Interop/SwiftToCxx/methods/mutating-method-in-cxx.swift +++ b/test/Interop/SwiftToCxx/methods/mutating-method-in-cxx.swift @@ -63,6 +63,22 @@ public struct SmallStruct { // CHECK-NEXT: inline LargeStruct scale(swift::Int x, swift::Int y); // CHECK-NEXT: private +// CHECK: class SmallStruct final { +// CHECK: inline SmallStruct(SmallStruct &&) = default; +// CHECK-NEXT: inline void dump() const; +// CHECK-NEXT: inline SmallStruct scale(float y); +// CHECK-NEXT: inline void invert(); +// CHECK-NEXT: private: + + +public func createLargeStruct() -> LargeStruct { + return LargeStruct(x1: 1, x2: -5, x3: 9, x4: 11, x5: 0xbeef, x6: -77) +} + +public func createSmallStruct(x: Float) -> SmallStruct { + return SmallStruct(x: x) +} + // CHECK: inline void LargeStruct::dump() const { // CHECK-NEXT: return _impl::$s7Methods11LargeStructV4dumpyyF(_getOpaquePointer()); // CHECK-NEXT: } @@ -75,13 +91,6 @@ public struct SmallStruct { // CHECK-NEXT: }); // CHECK-NEXT: } -// CHECK: class SmallStruct final { -// CHECK: inline SmallStruct(SmallStruct &&) = default; -// CHECK-NEXT: inline void dump() const; -// CHECK-NEXT: inline SmallStruct scale(float y); -// CHECK-NEXT: inline void invert(); -// CHECK-NEXT: private: - // CHECK: inline void SmallStruct::dump() const { // CHECK-NEXT: return _impl::$s7Methods11SmallStructV4dumpyyF(_impl::swift_interop_passDirect_Methods_SmallStruct(_getOpaquePointer())); // CHECK-NEXT: } @@ -93,12 +102,3 @@ public struct SmallStruct { // CHECK-NEXT: inline void SmallStruct::invert() { // CHECK-NEXT: return _impl::$s7Methods11SmallStructV6invertyyF(_getOpaquePointer()); // CHECK-NEXT: } - - -public func createLargeStruct() -> LargeStruct { - return LargeStruct(x1: 1, x2: -5, x3: 9, x4: 11, x5: 0xbeef, x6: -77) -} - -public func createSmallStruct(x: Float) -> SmallStruct { - return SmallStruct(x: x) -} diff --git a/test/Interop/SwiftToCxx/properties/getter-in-cxx.swift b/test/Interop/SwiftToCxx/properties/getter-in-cxx.swift index 7128c6ebc14fb..b5237c758b9f3 100644 --- a/test/Interop/SwiftToCxx/properties/getter-in-cxx.swift +++ b/test/Interop/SwiftToCxx/properties/getter-in-cxx.swift @@ -14,10 +14,6 @@ public struct FirstSmallStruct { // CHECK-NEXT: inline uint32_t getX() const; // CHECK-NEXT: private: -// CHECK: inline uint32_t FirstSmallStruct::getX() const { -// CHECK-NEXT: return _impl::$s10Properties16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Properties_FirstSmallStruct(_getOpaquePointer())); -// CHECK-NEXT: } - public struct LargeStruct { public let x1, x2, x3, x4, x5, x6: Int @@ -43,35 +39,6 @@ public struct LargeStruct { // CHECK-NEXT: inline FirstSmallStruct getFirstSmallStruct() const; // CHECK-NEXT: private: -// CHECK: inline swift::Int LargeStruct::getX1() const { -// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x1Sivg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int LargeStruct::getX2() const { -// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x2Sivg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int LargeStruct::getX3() const { -// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x3Sivg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int LargeStruct::getX4() const { -// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x4Sivg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int LargeStruct::getX5() const { -// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x5Sivg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int LargeStruct::getX6() const { -// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x6Sivg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline LargeStruct LargeStruct::getAnotherLargeStruct() const { -// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { -// CHECK-NEXT: _impl::$s10Properties11LargeStructV07anotherbC0ACvg(result, _getOpaquePointer()); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK-NEXT: inline FirstSmallStruct LargeStruct::getFirstSmallStruct() const { -// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { -// CHECK-NEXT: _impl::swift_interop_returnDirect_Properties_FirstSmallStruct(result, _impl::$s10Properties11LargeStructV010firstSmallC0AA05FirsteC0Vvg(_getOpaquePointer())); -// CHECK-NEXT: }); -// CHECK-NEXT: } - public final class PropertiesInClass { public let storedInt: Int32 @@ -94,18 +61,6 @@ public final class PropertiesInClass { // CHECK-NEXT: inline swift::Int getComputedInt(); // CHECK-NEXT: inline FirstSmallStruct getSmallStruct(); -// CHECK: inline int32_t PropertiesInClass::getStoredInt() { -// CHECK-NEXT: return _impl::$s10Properties0A7InClassC9storedInts5Int32Vvg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int PropertiesInClass::getComputedInt() { -// CHECK-NEXT: return _impl::$s10Properties0A7InClassC11computedIntSivg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); -// CHECK-NEXT: } -// CHECK-NEXT: inline FirstSmallStruct PropertiesInClass::getSmallStruct() { -// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { -// CHECK-NEXT: _impl::swift_interop_returnDirect_Properties_FirstSmallStruct(result, _impl::$s10Properties0A7InClassC11smallStructAA010FirstSmallE0Vvg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this))); -// CHECK-NEXT: }); -// CHECK-NEXT: } - public func createPropsInClass(_ x: Int32) -> PropertiesInClass { return PropertiesInClass(x) } @@ -134,23 +89,6 @@ public struct SmallStructWithGetters { // CHECK-NEXT: inline SmallStructWithGetters getSmallStruct() const; // CHECK-NEXT: private: -// CHECK: inline uint32_t SmallStructWithGetters::getStoredInt() const { -// CHECK-NEXT: return _impl::$s10Properties22SmallStructWithGettersV9storedInts6UInt32Vvg(_impl::swift_interop_passDirect_Properties_SmallStructWithGetters(_getOpaquePointer())); -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int SmallStructWithGetters::getComputedInt() const { -// CHECK-NEXT: return _impl::$s10Properties22SmallStructWithGettersV11computedIntSivg(_impl::swift_interop_passDirect_Properties_SmallStructWithGetters(_getOpaquePointer())); -// CHECK-NEXT: } -// CHECK-NEXT: inline LargeStruct SmallStructWithGetters::getLargeStruct() const { -// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { -// CHECK-NEXT: _impl::$s10Properties22SmallStructWithGettersV05largeC0AA05LargeC0Vvg(result, _impl::swift_interop_passDirect_Properties_SmallStructWithGetters(_getOpaquePointer())); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK-NEXT: inline SmallStructWithGetters SmallStructWithGetters::getSmallStruct() const { -// CHECK-NEXT: return _impl::_impl_SmallStructWithGetters::returnNewValue([&](char * _Nonnull result) { -// CHECK-NEXT: _impl::swift_interop_returnDirect_Properties_SmallStructWithGetters(result, _impl::$s10Properties22SmallStructWithGettersV05smallC0ACvg(_impl::swift_interop_passDirect_Properties_SmallStructWithGetters(_getOpaquePointer()))); -// CHECK-NEXT: }); -// CHECK-NEXT: } - public func createSmallStructWithGetter() -> SmallStructWithGetters { return SmallStructWithGetters(storedInt: 21) } @@ -182,3 +120,65 @@ public struct StructWithRefCountStoredProp { public func createStructWithRefCountStoredProp() -> StructWithRefCountStoredProp { return StructWithRefCountStoredProp(x: 0) } + +// CHECK: inline uint32_t FirstSmallStruct::getX() const { +// CHECK-NEXT: return _impl::$s10Properties16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Properties_FirstSmallStruct(_getOpaquePointer())); +// CHECK-NEXT: } + +// CHECK: inline swift::Int LargeStruct::getX1() const { +// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x1Sivg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int LargeStruct::getX2() const { +// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x2Sivg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int LargeStruct::getX3() const { +// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x3Sivg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int LargeStruct::getX4() const { +// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x4Sivg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int LargeStruct::getX5() const { +// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x5Sivg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int LargeStruct::getX6() const { +// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x6Sivg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline LargeStruct LargeStruct::getAnotherLargeStruct() const { +// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { +// CHECK-NEXT: _impl::$s10Properties11LargeStructV07anotherbC0ACvg(result, _getOpaquePointer()); +// CHECK-NEXT: }); +// CHECK-NEXT: } +// CHECK-NEXT: inline FirstSmallStruct LargeStruct::getFirstSmallStruct() const { +// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { +// CHECK-NEXT: _impl::swift_interop_returnDirect_Properties_FirstSmallStruct(result, _impl::$s10Properties11LargeStructV010firstSmallC0AA05FirsteC0Vvg(_getOpaquePointer())); +// CHECK-NEXT: }); +// CHECK-NEXT: } + +// CHECK: inline int32_t PropertiesInClass::getStoredInt() { +// CHECK-NEXT: return _impl::$s10Properties0A7InClassC9storedInts5Int32Vvg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int PropertiesInClass::getComputedInt() { +// CHECK-NEXT: return _impl::$s10Properties0A7InClassC11computedIntSivg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); +// CHECK-NEXT: } +// CHECK-NEXT: inline FirstSmallStruct PropertiesInClass::getSmallStruct() { +// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { +// CHECK-NEXT: _impl::swift_interop_returnDirect_Properties_FirstSmallStruct(result, _impl::$s10Properties0A7InClassC11smallStructAA010FirstSmallE0Vvg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this))); +// CHECK-NEXT: }); +// CHECK-NEXT: } + +// CHECK: inline uint32_t SmallStructWithGetters::getStoredInt() const { +// CHECK-NEXT: return _impl::$s10Properties22SmallStructWithGettersV9storedInts6UInt32Vvg(_impl::swift_interop_passDirect_Properties_SmallStructWithGetters(_getOpaquePointer())); +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int SmallStructWithGetters::getComputedInt() const { +// CHECK-NEXT: return _impl::$s10Properties22SmallStructWithGettersV11computedIntSivg(_impl::swift_interop_passDirect_Properties_SmallStructWithGetters(_getOpaquePointer())); +// CHECK-NEXT: } +// CHECK-NEXT: inline LargeStruct SmallStructWithGetters::getLargeStruct() const { +// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { +// CHECK-NEXT: _impl::$s10Properties22SmallStructWithGettersV05largeC0AA05LargeC0Vvg(result, _impl::swift_interop_passDirect_Properties_SmallStructWithGetters(_getOpaquePointer())); +// CHECK-NEXT: }); +// CHECK-NEXT: } +// CHECK-NEXT: inline SmallStructWithGetters SmallStructWithGetters::getSmallStruct() const { +// CHECK-NEXT: return _impl::_impl_SmallStructWithGetters::returnNewValue([&](char * _Nonnull result) { +// CHECK-NEXT: _impl::swift_interop_returnDirect_Properties_SmallStructWithGetters(result, _impl::$s10Properties22SmallStructWithGettersV05smallC0ACvg(_impl::swift_interop_passDirect_Properties_SmallStructWithGetters(_getOpaquePointer()))); +// CHECK-NEXT: }); +// CHECK-NEXT: } diff --git a/test/Interop/SwiftToCxx/properties/setter-in-cxx.swift b/test/Interop/SwiftToCxx/properties/setter-in-cxx.swift index 3b2090350bb2d..78aaed3a982ee 100644 --- a/test/Interop/SwiftToCxx/properties/setter-in-cxx.swift +++ b/test/Interop/SwiftToCxx/properties/setter-in-cxx.swift @@ -15,13 +15,6 @@ public struct FirstSmallStruct { // CHECK-NEXT: inline void setX(uint32_t value); // CHECK-NEXT: private: -// CHECK: inline uint32_t FirstSmallStruct::getX() const { -// CHECK-NEXT: return _impl::$s10Properties16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Properties_FirstSmallStruct(_getOpaquePointer())); -// CHECK-NEXT: } -// CHECK-NEXT: inline void FirstSmallStruct::setX(uint32_t value) { -// CHECK-NEXT: return _impl::$s10Properties16FirstSmallStructV1xs6UInt32Vvs(value, _getOpaquePointer()); -// CHECK-NEXT: } - public struct LargeStruct { public var x1, x2, x3, x4, x5, x6: Int } @@ -43,13 +36,6 @@ public struct LargeStruct { // CHECK-NEXT: inline void setX6(swift::Int value); // CHECK-NEXT: private: -// CHECK: inline swift::Int LargeStruct::getX1() const { -// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x1Sivg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline void LargeStruct::setX1(swift::Int value) { -// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x1Sivs(value, _getOpaquePointer()); -// CHECK-NEXT: } - public struct LargeStructWithProps { public var storedLargeStruct: LargeStruct public var storedSmallStruct: FirstSmallStruct @@ -62,23 +48,6 @@ public struct LargeStructWithProps { // CHECK-NEXT: inline FirstSmallStruct getStoredSmallStruct() const; // CHECK-NEXT: inline void setStoredSmallStruct(const FirstSmallStruct& value); -// CHECK: inline LargeStruct LargeStructWithProps::getStoredLargeStruct() const { -// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { -// CHECK-NEXT: _impl::$s10Properties20LargeStructWithPropsV06storedbC0AA0bC0Vvg(result, _getOpaquePointer()); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK-NEXT: inline void LargeStructWithProps::setStoredLargeStruct(const LargeStruct& value) { -// CHECK-NEXT: return _impl::$s10Properties20LargeStructWithPropsV06storedbC0AA0bC0Vvs(_impl::_impl_LargeStruct::getOpaquePointer(value), _getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline FirstSmallStruct LargeStructWithProps::getStoredSmallStruct() const { -// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { -// CHECK-NEXT: _impl::swift_interop_returnDirect_Properties_FirstSmallStruct(result, _impl::$s10Properties20LargeStructWithPropsV011storedSmallC0AA05FirstgC0Vvg(_getOpaquePointer())); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK-NEXT: inline void LargeStructWithProps::setStoredSmallStruct(const FirstSmallStruct& value) { -// CHECK-NEXT: return _impl::$s10Properties20LargeStructWithPropsV011storedSmallC0AA05FirstgC0Vvs(_impl::swift_interop_passDirect_Properties_FirstSmallStruct(_impl::_impl_FirstSmallStruct::getOpaquePointer(value)), _getOpaquePointer()); -// CHECK-NEXT: } - public final class PropertiesInClass { public var storedInt: Int32 @@ -102,19 +71,6 @@ public final class PropertiesInClass { // CHECK-NEXT: inline swift::Int getComputedInt(); // CHECK-NEXT: inline void setComputedInt(swift::Int newValue); -// CHECK: inline int32_t PropertiesInClass::getStoredInt() { -// CHECK-NEXT: return _impl::$s10Properties0A7InClassC9storedInts5Int32Vvg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); -// CHECK-NEXT: } -// CHECK-NEXT: inline void PropertiesInClass::setStoredInt(int32_t value) { -// CHECK-NEXT: return _impl::$s10Properties0A7InClassC9storedInts5Int32Vvs(value, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int PropertiesInClass::getComputedInt() { -// CHECK-NEXT: return _impl::$s10Properties0A7InClassC11computedIntSivg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); -// CHECK-NEXT: } -// CHECK-NEXT: inline void PropertiesInClass::setComputedInt(swift::Int newValue) { -// CHECK-NEXT: return _impl::$s10Properties0A7InClassC11computedIntSivs(newValue, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); -// CHECK-NEXT: } - public func createPropsInClass(_ x: Int32) -> PropertiesInClass { return PropertiesInClass(x) } @@ -150,6 +106,58 @@ public struct SmallStructWithProps { // CHECK-NEXT: inline void setLargeStructWithProps(const LargeStructWithProps& newValue); // CHECK-NEXT: private: +public func createSmallStructWithProps() -> SmallStructWithProps { + return SmallStructWithProps(storedInt: 21) +} + +public func createFirstSmallStruct(_ x: UInt32) -> FirstSmallStruct { + return FirstSmallStruct(x: x) +} + +// CHECK: inline uint32_t FirstSmallStruct::getX() const { +// CHECK-NEXT: return _impl::$s10Properties16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Properties_FirstSmallStruct(_getOpaquePointer())); +// CHECK-NEXT: } +// CHECK-NEXT: inline void FirstSmallStruct::setX(uint32_t value) { +// CHECK-NEXT: return _impl::$s10Properties16FirstSmallStructV1xs6UInt32Vvs(value, _getOpaquePointer()); +// CHECK-NEXT: } + +// CHECK: inline swift::Int LargeStruct::getX1() const { +// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x1Sivg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline void LargeStruct::setX1(swift::Int value) { +// CHECK-NEXT: return _impl::$s10Properties11LargeStructV2x1Sivs(value, _getOpaquePointer()); +// CHECK-NEXT: } + +// CHECK: inline LargeStruct LargeStructWithProps::getStoredLargeStruct() const { +// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) { +// CHECK-NEXT: _impl::$s10Properties20LargeStructWithPropsV06storedbC0AA0bC0Vvg(result, _getOpaquePointer()); +// CHECK-NEXT: }); +// CHECK-NEXT: } +// CHECK-NEXT: inline void LargeStructWithProps::setStoredLargeStruct(const LargeStruct& value) { +// CHECK-NEXT: return _impl::$s10Properties20LargeStructWithPropsV06storedbC0AA0bC0Vvs(_impl::_impl_LargeStruct::getOpaquePointer(value), _getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline FirstSmallStruct LargeStructWithProps::getStoredSmallStruct() const { +// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) { +// CHECK-NEXT: _impl::swift_interop_returnDirect_Properties_FirstSmallStruct(result, _impl::$s10Properties20LargeStructWithPropsV011storedSmallC0AA05FirstgC0Vvg(_getOpaquePointer())); +// CHECK-NEXT: }); +// CHECK-NEXT: } +// CHECK-NEXT: inline void LargeStructWithProps::setStoredSmallStruct(const FirstSmallStruct& value) { +// CHECK-NEXT: return _impl::$s10Properties20LargeStructWithPropsV011storedSmallC0AA05FirstgC0Vvs(_impl::swift_interop_passDirect_Properties_FirstSmallStruct(_impl::_impl_FirstSmallStruct::getOpaquePointer(value)), _getOpaquePointer()); +// CHECK-NEXT: } + +// CHECK: inline int32_t PropertiesInClass::getStoredInt() { +// CHECK-NEXT: return _impl::$s10Properties0A7InClassC9storedInts5Int32Vvg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); +// CHECK-NEXT: } +// CHECK-NEXT: inline void PropertiesInClass::setStoredInt(int32_t value) { +// CHECK-NEXT: return _impl::$s10Properties0A7InClassC9storedInts5Int32Vvs(value, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int PropertiesInClass::getComputedInt() { +// CHECK-NEXT: return _impl::$s10Properties0A7InClassC11computedIntSivg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); +// CHECK-NEXT: } +// CHECK-NEXT: inline void PropertiesInClass::setComputedInt(swift::Int newValue) { +// CHECK-NEXT: return _impl::$s10Properties0A7InClassC11computedIntSivs(newValue, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)); +// CHECK-NEXT: } + // CHECK: inline uint32_t SmallStructWithProps::getStoredInt() const { // CHECK-NEXT: return _impl::$s10Properties20SmallStructWithPropsV9storedInts6UInt32Vvg(_impl::swift_interop_passDirect_Properties_SmallStructWithProps(_getOpaquePointer())); // CHECK-NEXT: } @@ -170,11 +178,3 @@ public struct SmallStructWithProps { // CHECK-NEXT: inline void SmallStructWithProps::setLargeStructWithProps(const LargeStructWithProps& newValue) { // CHECK-NEXT: return _impl::$s10Properties20SmallStructWithPropsV05largecdE0AA05LargecdE0Vvs(_impl::_impl_LargeStructWithProps::getOpaquePointer(newValue), _getOpaquePointer()); // CHECK-NEXT: } - -public func createSmallStructWithProps() -> SmallStructWithProps { - return SmallStructWithProps(storedInt: 21) -} - -public func createFirstSmallStruct(_ x: UInt32) -> FirstSmallStruct { - return FirstSmallStruct(x: x) -} diff --git a/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx.swift b/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx.swift index b32a83165a46a..d9bb7bd51f441 100644 --- a/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx.swift +++ b/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx.swift @@ -89,19 +89,6 @@ public struct FirstSmallStruct { // CHECK-EMPTY: // CHECK-NEXT: namespace Structs { -// CHECK: inline uint32_t FirstSmallStruct::getX() const { -// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV1xs6UInt32Vvg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK: inline void FirstSmallStruct::setX(uint32_t value) { -// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV1xs6UInt32Vvs(value, _getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline void FirstSmallStruct::dump() const { -// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV4dumpyyF(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline void FirstSmallStruct::mutate() { -// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV6mutateyyF(_getOpaquePointer()); -// CHECK-NEXT: } - @frozen public struct FrozenStruct { private let storedInt: Int32 } @@ -155,18 +142,6 @@ public struct LargeStruct { // CHECK-NEXT: friend class _impl::_impl_LargeStruct; // CHECK-NEXT: }; -// CHECK: inline swift::Int LargeStruct::getX1() const { -// CHECK-NEXT: return _impl::$s7Structs11LargeStructV2x1Sivg(_getOpaquePointer()); -// CHECK-NEXT: } -// CHECK-NEXT: inline FirstSmallStruct LargeStruct::getFirstSmallStruct() const { -// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](void * _Nonnull result) { -// CHECK-NEXT: _impl::$s7Structs11LargeStructV010firstSmallC0AA05FirsteC0Vvg(result, _getOpaquePointer()); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK-NEXT: inline void LargeStruct::dump() const { -// CHECK-NEXT: return _impl::$s7Structs11LargeStructV4dumpyyF(_getOpaquePointer()); -// CHECK-NEXT: } - private class RefCountedClass { let x: Int @@ -192,9 +167,6 @@ public struct StructWithRefCountStoredProp { } // CHECK: inline StructWithRefCountStoredProp(swift::_impl::ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable->size, vwTable->getAlignment()) {} -// CHECK: inline void StructWithRefCountStoredProp::dump() const { -// CHECK-NEXT: return _impl::$s7Structs28StructWithRefCountStoredPropV4dumpyyF(_getOpaquePointer()); -// CHECK-NEXT: } public func createLargeStruct(_ x: Int) -> LargeStruct { return LargeStruct(x1: x, x2: -x, x3: x * 2, x4: x - 4, x5: 0, x6: 21) @@ -238,3 +210,32 @@ public func mutateSmall(_ x: inout FirstSmallStruct) { // CHECK: inline void printSmallAndLarge(const FirstSmallStruct& x, const LargeStruct& y) noexcept { // CHECK-NEXT: return _impl::$s7Structs18printSmallAndLargeyyAA05FirstC6StructV_AA0eG0VtF(_impl::_impl_FirstSmallStruct::getOpaquePointer(x), _impl::_impl_LargeStruct::getOpaquePointer(y)); // CHECK-NEXT: } + +// CHECK: inline uint32_t FirstSmallStruct::getX() const { +// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV1xs6UInt32Vvg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK: inline void FirstSmallStruct::setX(uint32_t value) { +// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV1xs6UInt32Vvs(value, _getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline void FirstSmallStruct::dump() const { +// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV4dumpyyF(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline void FirstSmallStruct::mutate() { +// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV6mutateyyF(_getOpaquePointer()); +// CHECK-NEXT: } + +// CHECK: inline swift::Int LargeStruct::getX1() const { +// CHECK-NEXT: return _impl::$s7Structs11LargeStructV2x1Sivg(_getOpaquePointer()); +// CHECK-NEXT: } +// CHECK-NEXT: inline FirstSmallStruct LargeStruct::getFirstSmallStruct() const { +// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](void * _Nonnull result) { +// CHECK-NEXT: _impl::$s7Structs11LargeStructV010firstSmallC0AA05FirsteC0Vvg(result, _getOpaquePointer()); +// CHECK-NEXT: }); +// CHECK-NEXT: } +// CHECK-NEXT: inline void LargeStruct::dump() const { +// CHECK-NEXT: return _impl::$s7Structs11LargeStructV4dumpyyF(_getOpaquePointer()); +// CHECK-NEXT: } + +// CHECK: inline void StructWithRefCountStoredProp::dump() const { +// CHECK-NEXT: return _impl::$s7Structs28StructWithRefCountStoredPropV4dumpyyF(_getOpaquePointer()); +// CHECK-NEXT: } diff --git a/test/Interop/SwiftToCxx/structs/swift-struct-circular-dependent-defs.swift b/test/Interop/SwiftToCxx/structs/swift-struct-circular-dependent-defs.swift new file mode 100644 index 0000000000000..b857b28aa96ce --- /dev/null +++ b/test/Interop/SwiftToCxx/structs/swift-struct-circular-dependent-defs.swift @@ -0,0 +1,44 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -typecheck -module-name Structs -clang-header-expose-public-decls -emit-clang-header-path %t/structs.h +// RUN: %FileCheck %s < %t/structs.h + +// RUN: %check-interop-cxx-header-in-clang(%t/structs.h) + +struct Large { + let x: (Int64, Int64, Int64, Int64, Int64, Int64) = (0, 0, 0, 0, 0, 0) +} + +public struct A { + public func returnsB() -> B { + return B() + } + + let v: Large = Large() +} + +public struct B { + public func returnsA() -> A { + return A() + } + + let v: Large = Large() +} + +// CHECK: class B; +// CHECK-NEXT: namespace _impl { +// CHECK-EMPTY: +// CHECK-NEXT: class _impl_A; + +// CHECK: class A final { + +// CHECK: B returnsB() const; + +// CHECK: class A; +// CHECK-NEXT: namespace _impl { +// CHECK-EMPTY: +// CHECK-NEXT: class _impl_B; + +// CHECK: class B final { + +// CHECK: inline B A::returnsB() const { +// CHECK: inline A B::returnsA() const { From 20be955eedeabcf07b198b6020a16f0ae7589b56 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 19 Aug 2022 11:49:26 -0700 Subject: [PATCH 220/491] Open existential actors when retrieving their executors. Fixes rdar://91448324. --- lib/SILGen/SILGenProlog.cpp | 9 +++++++++ test/SILGen/isolated_parameters.swift | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index 3a5e75a963598..bf04fe3b9960d 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -843,6 +843,15 @@ SILValue SILGenFunction::emitLoadActorExecutor(SILLocation loc, else actorV = actor.borrow(*this, loc).getValue(); + // Open an existential actor type. + CanType actorType = actor.getType().getASTType(); + if (actorType->isExistentialType()) { + actorType = OpenedArchetypeType::get( + actorType, F.getGenericSignature())->getCanonicalType(); + SILType loweredActorType = getLoweredType(actorType); + actorV = B.createOpenExistentialRef(loc, actorV, loweredActorType); + } + // For now, we just want to emit a hop_to_executor directly to the // actor; LowerHopToActor will add the emission logic necessary later. return actorV; diff --git a/test/SILGen/isolated_parameters.swift b/test/SILGen/isolated_parameters.swift index dc63c2ae2c85c..7f15092f6bae6 100644 --- a/test/SILGen/isolated_parameters.swift +++ b/test/SILGen/isolated_parameters.swift @@ -24,3 +24,14 @@ public func takeClosureWithIsolatedParam(body: (isolated A) async -> Void) { } public func testClosureWithIsolatedParam() { takeClosureWithIsolatedParam { _ in } } + +// CHECK-LABEL: sil{{.*}} [ossa] @$s4test0A19IsolatedExistentialyyScA_pYiYaF +// CHECK: bb0([[ACTOR:%.*]] : @guaranteed $any Actor) +@available(SwiftStdlib 5.1, *) +public func testIsolatedExistential(_ a: isolated Actor) async { + // CHECK: [[ACTOR_COPY:%.*]] = copy_value [[ACTOR]] : $any Actor + // CHECK: [[ACTOR_BORROW:%.*]] = begin_borrow [[ACTOR_COPY]] : $any Actor + // CHECK: [[ACTOR_OPENED:%.*]] = open_existential_ref [[ACTOR_BORROW]] : $any Actor to $@opened("{{.*}}", any Actor) Self + // CHECK: hop_to_executor [[ACTOR_OPENED]] : $@opened("{{.*}}", any Actor) Self + // CHECK: return +} From b57104961af00a16230f78f7326fa7c52c2844fd Mon Sep 17 00:00:00 2001 From: Casper Jeukendrup <48658420+cbjeukendrup@users.noreply.github.com> Date: Fri, 19 Aug 2022 18:38:30 +0200 Subject: [PATCH 221/491] Fix typo in docs/DevelopmentTips.md: `boostrapping` -> `bootstrapping` --- docs/DevelopmentTips.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/DevelopmentTips.md b/docs/DevelopmentTips.md index 4fbc5c5ec523e..bcf8f59556890 100644 --- a/docs/DevelopmentTips.md +++ b/docs/DevelopmentTips.md @@ -21,7 +21,7 @@ Going further, for various reasons the standard library has lots of warnings. Th Copy the invocation that has ` -o /swift-macosx-x86_64/stdlib/public/core/iphonesimulator/i386/Swift.o`, so that we can perform the actual call to swiftc ourselves. Tack on `-suppress-warnings` at the end, and now we have the command to just build `Swift.o` for i386 while only displaying the actual errors. ### Choosing the bootstrapping mode -By default, the compiler builds with the `boostrapping-with-hostlibs` (macOS) or `bootstrapping` (Linux) bootstrapping mode. To speed up local development it's recommended to build with the `hosttools` mode: `utils/build-script --bootstrapping=hosttools`. +By default, the compiler builds with the `bootstrapping-with-hostlibs` (macOS) or `bootstrapping` (Linux) bootstrapping mode. To speed up local development it's recommended to build with the `hosttools` mode: `utils/build-script --bootstrapping=hosttools`. It requires a recently new swift toolchain to be installed on your build machine. You might need to download and install a nightly Swift toolchain to build the Swift project in `hosttools` mode. @@ -29,9 +29,9 @@ Not that changing the bootstrapping mode needs a reconfiguration. #### Using a locally built Swift toolchain -If you do not want to install a nightly Swift toolchain, or you need to debug Swift code within SwiftCompilerSources, you can build the Swift toolchain in `boostrapping-with-hostlibs` mode on your local machine once, and then use this toolchain to iterate on your changes with the `hosttools` mode: +If you do not want to install a nightly Swift toolchain, or you need to debug Swift code within SwiftCompilerSources, you can build the Swift toolchain in `bootstrapping-with-hostlibs` mode on your local machine once, and then use this toolchain to iterate on your changes with the `hosttools` mode: -* Build the toolchain locally in `boostrapping-with-hostlibs` mode: `./utils/build-toolchain com.yourname`. +* Build the toolchain locally in `bootstrapping-with-hostlibs` mode: `./utils/build-toolchain com.yourname`. * Copy the `swift-LOCAL-YYYY-MM-DD.xctoolchain` file from `./swift-nightly-install/Library/Developer/Toolchains` to `/Library/Developer/Toolchains`. * Launch Xcode, in the menu bar select _Xcode_ > _Toolchains_ > _Local Swift Development Snapshot YYYY-MM-DD_. * Remove the Swift build directory: `./build`. @@ -124,4 +124,4 @@ To setup this environment a few steps are necessary: Now you are all set. You can build and debug like with a native Xcode project. -If the project structure changes, e.g. new source files are added or deleted, you just have to re-create the LLVM and Swift projects with `utils/build-script --skip-build --xcode --skip-early-swift-driver`. \ No newline at end of file +If the project structure changes, e.g. new source files are added or deleted, you just have to re-create the LLVM and Swift projects with `utils/build-script --skip-build --xcode --skip-early-swift-driver`. From d081251ddc1da0d45b785910125ae3ea3c75861f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 19 Aug 2022 15:13:21 -0700 Subject: [PATCH 222/491] Witness thunk does not need to hop when the witness decl is acessible from anywhere Fixes rdar://96906314. --- lib/Sema/TypeCheckProtocol.cpp | 5 +++++ test/SILGen/async_conversion.swift | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index cc499e24aa585..71bba4f50b95d 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -3083,6 +3083,11 @@ Optional ConformanceChecker::checkActorIsolation( diagnoseNonSendableTypesInReference( getConcreteWitness(), DC, loc, SendableCheckReason::Conformance); + // If the witness is accessible across actors, we don't need to consider it + // isolated. + if (isAccessibleAcrossActors(witness, refResult.isolation, DC)) + return None; + if (refResult.isolation.isActorIsolated() && isAsyncDecl(requirement) && !isAsyncDecl(witness)) return refResult.isolation; diff --git a/test/SILGen/async_conversion.swift b/test/SILGen/async_conversion.swift index 6a624f4c7cdad..ffa6345a1aa5f 100644 --- a/test/SILGen/async_conversion.swift +++ b/test/SILGen/async_conversion.swift @@ -21,3 +21,15 @@ struct X: P { // CHECK: function_ref @$s4test1XV1fySSSgSi_SStF : $@convention(method) (Int, @guaranteed String, X) -> @owned Optional func f(_: Int, _: String) -> String? { nil } } + +protocol P2 { + init() async +} + +actor A: P2 { + // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s4test1ACAA2P2A2aDPxyYacfCTW + // CHECK-NOT: hop_to_executor + // CHECK: function_ref @$s4test1ACACycfC : $@convention(method) (@thick A.Type) -> @owned A // user: %3 + // CHECK-NEXT: apply + // CHECK: return +} From 268f6e25d1747b8ec04f8aa7eb228c50f9555c03 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 19 Aug 2022 21:36:06 -0400 Subject: [PATCH 223/491] [Diagnostics] Improve the diagnostics for invalid associatedtype or typealias access on existential types by mentioning the base type in the error message. --- include/swift/AST/DiagnosticsSema.def | 10 ++++++---- lib/Sema/CSDiagnostics.cpp | 4 ++-- lib/Sema/TypeCheckType.cpp | 4 ++-- test/decl/typealias/associated_types.swift | 6 +++--- test/decl/typealias/protocol.swift | 6 +++--- test/type/subclass_composition.swift | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index b2dfc26399396..203daab9880e0 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2465,11 +2465,13 @@ WARNING(append_interpolation_access_control,none, // Protocols and existentials ERROR(assoc_type_outside_of_protocol,none, - "associated type %0 can only be used with a concrete type or " - "generic parameter base", (DeclNameRef)) + "cannot access associated type %0 from %1; use a concrete type or " + "generic parameter base instead", + (DeclNameRef, Type)) ERROR(typealias_outside_of_protocol,none, - "type alias %0 can only be used with a concrete type or " - "generic parameter base", (DeclNameRef)) + "cannot access type alias %0 from %1; use a concrete type or " + "generic parameter base instead", + (DeclNameRef, Type)) ERROR(objc_protocol_inherits_non_objc_protocol,none, "@objc protocol %0 cannot refine non-@objc protocol %1", (Type, Type)) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 5ab1333ff8a28..8aafd4c7d86ba 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -4405,10 +4405,10 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { // static members doesn't make a whole lot of sense if (isa(Member)) { Diag.emplace( - emitDiagnostic(diag::typealias_outside_of_protocol, Name)); + emitDiagnostic(diag::typealias_outside_of_protocol, Name, instanceTy)); } else if (isa(Member)) { Diag.emplace( - emitDiagnostic(diag::assoc_type_outside_of_protocol, Name)); + emitDiagnostic(diag::assoc_type_outside_of_protocol, Name, instanceTy)); } else if (isa(Member)) { Diag.emplace( emitDiagnostic(diag::construct_protocol_by_name, instanceTy)); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index d47288a4b041e..40441ecf5c6ae 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -1656,12 +1656,12 @@ static Type resolveNestedIdentTypeComponent(TypeResolution resolution, case TypeChecker::UnsupportedMemberTypeAccessKind::TypeAliasOfExistential: diags.diagnose(comp->getNameLoc(), diag::typealias_outside_of_protocol, - comp->getNameRef()); + comp->getNameRef(), parentTy); return ErrorType::get(ctx); case TypeChecker::UnsupportedMemberTypeAccessKind::AssociatedTypeOfExistential: diags.diagnose(comp->getNameLoc(), diag::assoc_type_outside_of_protocol, - comp->getNameRef()); + comp->getNameRef(), parentTy); return ErrorType::get(ctx); } diff --git a/test/decl/typealias/associated_types.swift b/test/decl/typealias/associated_types.swift index 9f53579d2cffe..ad176135be3ba 100644 --- a/test/decl/typealias/associated_types.swift +++ b/test/decl/typealias/associated_types.swift @@ -4,16 +4,16 @@ protocol BaseProto { associatedtype AssocTy } var a: BaseProto.AssocTy = 4 -// expected-error@-1{{associated type 'AssocTy' can only be used with a concrete type or generic parameter base}} +// expected-error@-1{{cannot access associated type 'AssocTy' from 'BaseProto'; use a concrete type or generic parameter base instead}} var a = BaseProto.AssocTy.self -// expected-error@-1{{associated type 'AssocTy' can only be used with a concrete type or generic parameter base}} +// expected-error@-1{{cannot access associated type 'AssocTy' from 'BaseProto'; use a concrete type or generic parameter base instead}} protocol DerivedProto : BaseProto { func associated() -> AssocTy // no-warning func existential() -> BaseProto.AssocTy - // expected-error@-1{{associated type 'AssocTy' can only be used with a concrete type or generic parameter base}} + // expected-error@-1{{cannot access associated type 'AssocTy' from 'BaseProto'; use a concrete type or generic parameter base instead}} } diff --git a/test/decl/typealias/protocol.swift b/test/decl/typealias/protocol.swift index 4ce7a8265b4c1..a468850df6ead 100644 --- a/test/decl/typealias/protocol.swift +++ b/test/decl/typealias/protocol.swift @@ -176,8 +176,8 @@ struct T5 : P5 { var a: P5.T1 // OK // Invalid -- cannot represent associated type of existential - var v2: P5.T2 // expected-error {{type alias 'T2' can only be used with a concrete type or generic parameter base}} - var v3: P5.X // expected-error {{type alias 'X' can only be used with a concrete type or generic parameter base}} + var v2: P5.T2 // expected-error {{cannot access type alias 'T2' from 'P5'; use a concrete type or generic parameter base instead}} + var v3: P5.X // expected-error {{cannot access type alias 'X' from 'P5'; use a concrete type or generic parameter base instead}} // Unqualified reference to typealias from a protocol conformance var v4: T1 // OK @@ -188,7 +188,7 @@ struct T5 : P5 { var v7: T5.T2 // OK var v8 = P6.A.self - var v9 = P6.B.self // expected-error {{type alias 'B' can only be used with a concrete type or generic parameter base}} + var v9 = P6.B.self // expected-error {{cannot access type alias 'B' from 'P6'; use a concrete type or generic parameter base instead}} } // Unqualified lookup finds typealiases in protocol extensions diff --git a/test/type/subclass_composition.swift b/test/type/subclass_composition.swift index 6fbab0c420c34..1cdd8ba14a9a3 100644 --- a/test/type/subclass_composition.swift +++ b/test/type/subclass_composition.swift @@ -322,7 +322,7 @@ func dependentMemberTypes( _: T.FullyConcrete, _: BaseIntAndP2.DependentInConcreteConformance, // FIXME expected-error {{}} - _: BaseIntAndP2.DependentProtocol, // expected-error {{type alias 'DependentProtocol' can only be used with a concrete type or generic parameter base}} + _: BaseIntAndP2.DependentProtocol, // expected-error {{cannot access type alias 'DependentProtocol' from 'BaseIntAndP2' (aka 'Base & P2'); use a concrete type or generic parameter base instead}} _: BaseIntAndP2.DependentClass, _: BaseIntAndP2.FullyConcrete) {} From 6d1b8d4a0cf558089ed37635bd9bcde3e63b8dde Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 19 Aug 2022 21:43:35 -0400 Subject: [PATCH 224/491] [TypeResolution] Diagnose invalid dependent member types of existential types. --- lib/Sema/TypeCheckType.cpp | 22 ++++++++++++++++++++-- test/decl/typealias/protocol.swift | 10 ++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 40441ecf5c6ae..dcd28359876a1 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -126,6 +126,7 @@ Type TypeResolution::resolveDependentMemberType( // FIXME(ModQual): Reject qualified names immediately; they cannot be // dependent member types. Identifier refIdentifier = ref->getNameRef().getBaseIdentifier(); + ASTContext &ctx = DC->getASTContext(); switch (stage) { case TypeResolutionStage::Structural: @@ -146,8 +147,6 @@ Type TypeResolution::resolveDependentMemberType( // Record the type we found. ref->setValue(nestedType, nullptr); } else { - ASTContext &ctx = DC->getASTContext(); - // Resolve the base to a potential archetype. // Perform typo correction. TypoCorrectionResults corrections(ref->getNameRef(), ref->getNameLoc()); @@ -188,6 +187,25 @@ Type TypeResolution::resolveDependentMemberType( auto *concrete = ref->getBoundDecl(); + if (auto concreteBase = genericSig->getConcreteType(baseTy)) { + bool hasUnboundOpener = !!getUnboundTypeOpener(); + switch (TypeChecker::isUnsupportedMemberTypeAccess(concreteBase, concrete, + hasUnboundOpener)) { + case TypeChecker::UnsupportedMemberTypeAccessKind::TypeAliasOfExistential: + ctx.Diags.diagnose(ref->getNameLoc(), + diag::typealias_outside_of_protocol, + ref->getNameRef(), concreteBase); + break; + case TypeChecker::UnsupportedMemberTypeAccessKind::AssociatedTypeOfExistential: + ctx.Diags.diagnose(ref->getNameLoc(), + diag::assoc_type_outside_of_protocol, + ref->getNameRef(), concreteBase); + break; + default: + break; + }; + } + // If the nested type has been resolved to an associated type, use it. if (auto assocType = dyn_cast(concrete)) { return DependentMemberType::get(baseTy, assocType); diff --git a/test/decl/typealias/protocol.swift b/test/decl/typealias/protocol.swift index a468850df6ead..655c8bf7fcb5c 100644 --- a/test/decl/typealias/protocol.swift +++ b/test/decl/typealias/protocol.swift @@ -189,6 +189,16 @@ struct T5 : P5 { var v8 = P6.A.self var v9 = P6.B.self // expected-error {{cannot access type alias 'B' from 'P6'; use a concrete type or generic parameter base instead}} + + struct Generic { + func okay(value: T.A) where T == any P6 {} + + func invalid1(value: T.B) where T == any P6 {} + // expected-error@-1 {{cannot access type alias 'B' from 'any P6'; use a concrete type or generic parameter base instead}} + + func invalid2(value: T.A) where T == any P5 {} + // expected-error@-1 {{cannot access associated type 'A' from 'any P5'; use a concrete type or generic parameter base instead}} + } } // Unqualified lookup finds typealiases in protocol extensions From ddb5c13ef548bb2dbbc34f7104caa1c9339c9ec8 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 19 Aug 2022 22:09:33 -0400 Subject: [PATCH 225/491] [Diagnostics] Improve the diagnostics for invalid type access on an existential type in expression context. --- lib/Sema/CSDiagnostics.cpp | 3 ++- test/decl/typealias/protocol.swift | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 8aafd4c7d86ba..9745d762be3d7 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -4297,7 +4297,8 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } } - if (BaseType->is() && !Member->isStatic()) { + bool isStaticOrTypeMember = Member->isStatic() || isa(Member); + if (BaseType->is() && !isStaticOrTypeMember) { auto instanceTy = BaseType; if (auto *AMT = instanceTy->getAs()) { diff --git a/test/decl/typealias/protocol.swift b/test/decl/typealias/protocol.swift index 655c8bf7fcb5c..0102b23acb401 100644 --- a/test/decl/typealias/protocol.swift +++ b/test/decl/typealias/protocol.swift @@ -190,6 +190,9 @@ struct T5 : P5 { var v8 = P6.A.self var v9 = P6.B.self // expected-error {{cannot access type alias 'B' from 'P6'; use a concrete type or generic parameter base instead}} + var v10 = (any P6).A.self + var v11 = (any P6).B.self // expected-error {{cannot access type alias 'B' from 'any P6'; use a concrete type or generic parameter base instead}} + struct Generic { func okay(value: T.A) where T == any P6 {} From 4d620c807d726e51dc46c0c272e775c708f2e22e Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 19 Aug 2022 14:37:49 -0700 Subject: [PATCH 226/491] Sema: Diagnose when the access level of the global actor for a declaration is inconsistent with the access level of the declaration. Resolves rdar://98200658 and https://github.com/apple/swift/issues/60420. --- include/swift/AST/DiagnosticsSema.def | 5 ++++ lib/Sema/TypeCheckAccess.cpp | 29 ++++++++++++++++++++++ test/attr/global_actor.swift | 35 +++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 3e19342d7982b..0170bc142fe10 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -4882,6 +4882,11 @@ ERROR(global_actor_non_final_class,none, "non-final class %0 cannot be a global actor", (DeclName)) ERROR(global_actor_top_level_var,none, "top-level code variables cannot have a global actor", ()) +ERROR(global_actor_access,none, + "%select{private|fileprivate|internal|public|open}0 %1 %2 " + "cannot have %select{private|fileprivate|internal|%error|%error}3 " + "global actor %4", + (AccessLevel, DescriptiveDeclKind, DeclName, AccessLevel, DeclName)) ERROR(actor_isolation_multiple_attr,none, "%0 %1 has multiple actor-isolation attributes ('%2' and '%3')", diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 99021c873ea1e..23748d5e1fe2e 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -108,6 +108,8 @@ class AccessControlCheckerBase { void checkGenericParamAccess( const GenericContext *ownerCtx, const ValueDecl *ownerDecl); + + void checkGlobalActorAccess(const ValueDecl *D); }; class TypeAccessScopeDiagnoser : private ASTWalker { @@ -409,6 +411,30 @@ void AccessControlCheckerBase::checkGenericParamAccess( ownerDecl->getFormalAccess()); } +void AccessControlCheckerBase::checkGlobalActorAccess(const ValueDecl *D) { + auto globalActorAttr = D->getGlobalActorAttr(); + if (!globalActorAttr) + return; + + auto customAttr = globalActorAttr->first; + auto globalActorDecl = globalActorAttr->second; + checkTypeAccess( + customAttr->getType(), customAttr->getTypeRepr(), D, + /*mayBeInferred*/ false, + [&](AccessScope typeAccessScope, const TypeRepr *complainRepr, + DowngradeToWarning downgradeToWarning) { + auto globalActorAccess = typeAccessScope.accessLevelForDiagnostics(); + bool isExplicit = D->getAttrs().hasAttribute(); + auto declAccess = isExplicit + ? D->getFormalAccess() + : typeAccessScope.requiredAccessForDiagnostics(); + auto diag = D->diagnose(diag::global_actor_access, declAccess, + D->getDescriptiveKind(), D->getName(), + globalActorAccess, globalActorDecl->getName()); + highlightOffendingType(diag, complainRepr); + }); +} + namespace { class AccessControlChecker : public AccessControlCheckerBase, public DeclVisitor { @@ -425,6 +451,9 @@ class AccessControlChecker : public AccessControlCheckerBase, return; DeclVisitor::visit(D); + + if (const auto *VD = dyn_cast(D)) + checkGlobalActorAccess(VD); } // Force all kinds to be handled at a lower level. diff --git a/test/attr/global_actor.swift b/test/attr/global_actor.swift index 4e6faf7b7bbc9..e90483e9f7cb0 100644 --- a/test/attr/global_actor.swift +++ b/test/attr/global_actor.swift @@ -100,3 +100,38 @@ struct Container { extension SomeActor { @GA1 nonisolated func conflict1() { } // expected-error 3{{instance method 'conflict1()' has multiple actor-isolation attributes ('nonisolated' and 'GA1')}} } + + +// ----------------------------------------------------------------------- +// Access +// ----------------------------------------------------------------------- + +@globalActor +private struct PrivateGA { // expected-note 2 {{type declared here}} + actor Actor {} + static let shared = Actor() +} + +@globalActor +internal struct InternalGA { // expected-note 1 {{type declared here}} + actor Actor {} + static let shared = Actor() +} + +@globalActor +public struct PublicGA { + public actor Actor {} + public static let shared = Actor() +} + +@PrivateGA private struct PrivateStructPrivateGA {} +@InternalGA private struct PrivateStructInternalGA {} +@PublicGA private struct PrivateStructPublicGA {} + +@PrivateGA internal struct InternalStructPrivateGA {} // expected-error {{internal struct 'InternalStructPrivateGA' cannot have private global actor 'PrivateGA'}} +@InternalGA internal struct InternalStructInternalGA {} +@PublicGA internal struct InternalStructPublicGA {} + +@PrivateGA open class OpenClassPrivateGA {} // expected-error {{open class 'OpenClassPrivateGA' cannot have private global actor 'PrivateGA'}} +@InternalGA open class OpenClassInternalGA {} // expected-error {{open class 'OpenClassInternalGA' cannot have internal global actor 'InternalGA'}} +@PublicGA open class OpenClassPublicGA {} From 0e90e6a54abf8ff8abdafee35856906f8a66de41 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 19 Aug 2022 16:12:50 -0700 Subject: [PATCH 227/491] Sema: Diagnose use of global actor types with insufficient access on `@usableFromInline` declarations. --- include/swift/AST/DiagnosticsSema.def | 3 ++ lib/Sema/TypeCheckAccess.cpp | 26 +++++++++++----- test/attr/attr_inlinable_global_actor.swift | 33 +++++++++++++++++++++ 3 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 test/attr/attr_inlinable_global_actor.swift diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 0170bc142fe10..e4c3a2c645659 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -4887,6 +4887,9 @@ ERROR(global_actor_access,none, "cannot have %select{private|fileprivate|internal|%error|%error}3 " "global actor %4", (AccessLevel, DescriptiveDeclKind, DeclName, AccessLevel, DeclName)) +ERROR(global_actor_not_usable_from_inline,none, + "global actor for %0 %1 must be '@usableFromInline' or public", + (DescriptiveDeclKind, DeclName)) ERROR(actor_isolation_multiple_attr,none, "%0 %1 has multiple actor-isolation attributes ('%2' and '%3')", diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 23748d5e1fe2e..0678ad3a73688 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -109,7 +109,7 @@ class AccessControlCheckerBase { const GenericContext *ownerCtx, const ValueDecl *ownerDecl); - void checkGlobalActorAccess(const ValueDecl *D); + void checkGlobalActorAccess(const Decl *D); }; class TypeAccessScopeDiagnoser : private ASTWalker { @@ -411,7 +411,11 @@ void AccessControlCheckerBase::checkGenericParamAccess( ownerDecl->getFormalAccess()); } -void AccessControlCheckerBase::checkGlobalActorAccess(const ValueDecl *D) { +void AccessControlCheckerBase::checkGlobalActorAccess(const Decl *D) { + auto VD = dyn_cast(D); + if (!VD) + return; + auto globalActorAttr = D->getGlobalActorAttr(); if (!globalActorAttr) return; @@ -419,17 +423,24 @@ void AccessControlCheckerBase::checkGlobalActorAccess(const ValueDecl *D) { auto customAttr = globalActorAttr->first; auto globalActorDecl = globalActorAttr->second; checkTypeAccess( - customAttr->getType(), customAttr->getTypeRepr(), D, + customAttr->getType(), customAttr->getTypeRepr(), VD, /*mayBeInferred*/ false, [&](AccessScope typeAccessScope, const TypeRepr *complainRepr, DowngradeToWarning downgradeToWarning) { + if (checkUsableFromInline) { + auto diag = D->diagnose(diag::global_actor_not_usable_from_inline, + D->getDescriptiveKind(), VD->getName()); + highlightOffendingType(diag, complainRepr); + return; + } + auto globalActorAccess = typeAccessScope.accessLevelForDiagnostics(); bool isExplicit = D->getAttrs().hasAttribute(); auto declAccess = isExplicit - ? D->getFormalAccess() + ? VD->getFormalAccess() : typeAccessScope.requiredAccessForDiagnostics(); auto diag = D->diagnose(diag::global_actor_access, declAccess, - D->getDescriptiveKind(), D->getName(), + D->getDescriptiveKind(), VD->getName(), globalActorAccess, globalActorDecl->getName()); highlightOffendingType(diag, complainRepr); }); @@ -451,9 +462,7 @@ class AccessControlChecker : public AccessControlCheckerBase, return; DeclVisitor::visit(D); - - if (const auto *VD = dyn_cast(D)) - checkGlobalActorAccess(VD); + checkGlobalActorAccess(D); } // Force all kinds to be handled at a lower level. @@ -1076,6 +1085,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, return; DeclVisitor::visit(D); + checkGlobalActorAccess(D); } // Force all kinds to be handled at a lower level. diff --git a/test/attr/attr_inlinable_global_actor.swift b/test/attr/attr_inlinable_global_actor.swift new file mode 100644 index 0000000000000..14f9e57806d74 --- /dev/null +++ b/test/attr/attr_inlinable_global_actor.swift @@ -0,0 +1,33 @@ +// RUN: %target-typecheck-verify-swift -swift-version 5 + +// REQUIRES: concurrency + +@globalActor +private struct PrivateGA { // expected-note 2 {{type declared here}} + actor Actor {} + static let shared = Actor() +} + +@globalActor +internal struct InternalGA { // expected-note {{type declared here}} + actor Actor {} + static let shared = Actor() +} + +@globalActor @usableFromInline +internal struct UFIGA { + @usableFromInline actor Actor {} + @usableFromInline static let shared = Actor() +} + +@globalActor +public struct PublicGA { + public actor Actor {} + public static let shared = Actor() +} + +// expected-error@+1 {{internal struct 'UFIStructPrivateGA' cannot have private global actor 'PrivateGA'}} +@PrivateGA @usableFromInline internal struct UFIStructPrivateGA {} // expected-error {{global actor for struct 'UFIStructPrivateGA' must be '@usableFromInline' or public}} +@InternalGA @usableFromInline internal struct UFIStructInternalGA {} // expected-error {{global actor for struct 'UFIStructInternalGA' must be '@usableFromInline' or public}} +@UFIGA @usableFromInline internal struct UFIStructUFIGA {} +@PublicGA @usableFromInline internal struct UFIStructPublicGA {} From fe309fc6b9de86d3bcb6b6aad32e06bc720143a3 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Fri, 19 Aug 2022 13:32:13 -0700 Subject: [PATCH 228/491] Move completion handler usage to availablity The completion handler async replacement moved from being its own attribute to being an availability attribute. This patch moves the checking from being its own pass to being part of the availability checking under the async availability checking diagnostic pass. --- lib/Sema/MiscDiagnostics.cpp | 61 ---------------- lib/Sema/TypeCheckAvailability.cpp | 30 ++++++-- lib/Sema/TypeCheckConstraints.cpp | 4 -- lib/Sema/TypeCheckStmt.cpp | 1 - .../attr/attr_availability_async_rename.swift | 72 ++++++++++++++----- 5 files changed, 80 insertions(+), 88 deletions(-) diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index a5313d09d557f..83501d41679bb 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -5187,67 +5187,6 @@ diagnoseDictionaryLiteralDuplicateKeyEntries(const Expr *E, const_cast(E)->walk(Walker); } -namespace { - -class CompletionHandlerUsageChecker final : public ASTWalker { - ASTContext &ctx; - -public: - CompletionHandlerUsageChecker(ASTContext &ctx) : ctx(ctx) {} - - bool walkToDeclPre(Decl *D) override { return !isa(D); } - - std::pair walkToExprPre(Expr *expr) override { - if (expr->getType().isNull()) - return {false, expr}; // Something failed to typecheck, bail out - - if (auto *closure = dyn_cast(expr)) - return {closure->isBodyAsync(), closure}; - - if (auto *call = dyn_cast(expr)) { - if (auto *fn = dyn_cast(call->getFn())) { - if (auto *afd = dyn_cast(fn->getDecl())) { - auto *asyncFunc = afd->getAsyncAlternative(); - if (!asyncFunc) - return {false, call}; - ctx.Diags.diagnose(call->getLoc(), diag::warn_use_async_alternative); - - if (auto *accessor = dyn_cast(asyncFunc)) { - SmallString<32> name; - llvm::raw_svector_ostream os(name); - accessor->printUserFacingName(os); - ctx.Diags.diagnose(asyncFunc->getLoc(), - diag::descriptive_decl_declared_here, name); - } else { - ctx.Diags.diagnose(asyncFunc->getLoc(), diag::decl_declared_here, - asyncFunc->getName()); - } - } - } - } - return {true, expr}; - } -}; - -} // namespace - -void swift::checkFunctionAsyncUsage(AbstractFunctionDecl *decl) { - if (!decl->isAsyncContext()) - return; - CompletionHandlerUsageChecker checker(decl->getASTContext()); - BraceStmt *body = decl->getBody(); - if (body) - body->walk(checker); -} - -void swift::checkPatternBindingDeclAsyncUsage(PatternBindingDecl *decl) { - CompletionHandlerUsageChecker checker(decl->getASTContext()); - for (Expr *init : decl->initializers()) { - if (auto closure = dyn_cast_or_null(init)) - closure->walk(checker); - } -} - //===----------------------------------------------------------------------===// // High-level entry points. //===----------------------------------------------------------------------===// diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 28007da02a0da..a4eb012a61801 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -3573,12 +3573,11 @@ bool ExprAvailabilityWalker::diagnoseDeclRefAvailability( return false; } -/// Diagnose uses of API annotated '@unavailableFromAsync' when used from -/// asynchronous contexts. -/// Returns true if a diagnostic was emitted, false otherwise. +/// Diagnose misuses of API in asynchronous contexts. +/// Returns true if a fatal diagnostic was emitted, false otherwise. static bool -diagnoseDeclUnavailableFromAsync(const ValueDecl *D, SourceRange R, - const Expr *call, const ExportContext &Where) { +diagnoseDeclAsyncAvailability(const ValueDecl *D, SourceRange R, + const Expr *call, const ExportContext &Where) { // FIXME: I don't think this is right, but I don't understand the issue well // enough to fix it properly. If the decl context is an abstract // closure, we need it to have a type assigned to it before we can @@ -3612,6 +3611,25 @@ diagnoseDeclUnavailableFromAsync(const ValueDecl *D, SourceRange R, return false; ASTContext &ctx = Where.getDeclContext()->getASTContext(); + + if (const AbstractFunctionDecl *afd = dyn_cast(D)) { + if (const AbstractFunctionDecl *asyncAlt = afd->getAsyncAlternative()) { + assert(call && "No call calling async alternative function"); + ctx.Diags.diagnose(call->getLoc(), diag::warn_use_async_alternative); + + if (auto *accessor = dyn_cast(asyncAlt)) { + SmallString<32> name; + llvm::raw_svector_ostream os(name); + accessor->printUserFacingName(os); + ctx.Diags.diagnose(asyncAlt->getLoc(), + diag::descriptive_decl_declared_here, name); + } else { + ctx.Diags.diagnose(asyncAlt->getLoc(), diag::decl_declared_here, + asyncAlt->getName()); + } + } + } + // @available(noasync) spelling if (const AvailableAttr *attr = D->getAttrs().getNoAsync(ctx)) { SourceLoc diagLoc = call ? call->getLoc() : R.Start; @@ -3676,7 +3694,7 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R, if (diagnoseExplicitUnavailability(D, R, Where, call, Flags)) return true; - if (diagnoseDeclUnavailableFromAsync(D, R, call, Where)) + if (diagnoseDeclAsyncAvailability(D, R, call, Where)) return true; // Make sure not to diagnose an accessor's deprecation if we already diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 1301631219e20..fe8f68d6c8cc7 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -829,11 +829,7 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD, if (hadError) PBD->setInvalid(); - PBD->setInitializerChecked(patternNumber); - - checkPatternBindingDeclAsyncUsage(PBD); - return hadError; } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 4ba74d0cb4833..1ca79c1845d58 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -2114,7 +2114,6 @@ TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator, TypeChecker::computeCaptures(AFD); if (!AFD->getDeclContext()->isLocalContext()) { checkFunctionActorIsolation(AFD); - checkFunctionAsyncUsage(AFD); TypeChecker::checkFunctionEffects(AFD); } diff --git a/test/attr/attr_availability_async_rename.swift b/test/attr/attr_availability_async_rename.swift index 66855960c73af..7bcfae31a2854 100644 --- a/test/attr/attr_availability_async_rename.swift +++ b/test/attr/attr_availability_async_rename.swift @@ -1,8 +1,8 @@ // REQUIRES: concurrency // REQUIRES: objc_interop -// RUN: %target-typecheck-verify-swift -disable-availability-checking -verify-ignore-unknown -I %S/Inputs/custom-modules -// RUN: %target-typecheck-verify-swift -disable-availability-checking -verify-ignore-unknown -parse-as-library -I %S/Inputs/custom-modules +// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs/custom-modules +// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -parse-as-library -I %S/Inputs/custom-modules import ObjcAsync @@ -12,62 +12,74 @@ import ObjcAsync func goodFunc1(value: String, completionHandler: @escaping (Int) -> Void) {} @available(*, renamed: "asyncFunc(_:)") func goodFunc2(value: String, completionHandler: @escaping (Int) -> Void) {} -// expected-note@+1 4 {{'asyncFunc' declared here}} +// expected-note@+2 4 {{'asyncFunc' declared here}} +@available(SwiftStdlib 5.5, *) func asyncFunc(_ text: String) async -> Int { } // Ambiguous but only one is async @available(*, renamed: "overloaded()") func asyncOnlyOverload(completionHandler: @escaping () -> Void) { } func overloaded() { } -// expected-note@+1 {{'overloaded()' declared here}} +// expected-note@+2 {{'overloaded()' declared here}} +@available(SwiftStdlib 5.5, *) func overloaded() async { } // Renamed decl is ambiguous but the params only match a single case @available(*, renamed: "overloadedAsyncFunc(value:)") func nonAmbiguousFunc(value: Int, handler: @escaping () -> Void) {} -// expected-note@+1 {{'overloadedAsyncFunc(value:)' declared here}} +// expected-note@+2 {{'overloadedAsyncFunc(value:)' declared here}} +@available(SwiftStdlib 5.5, *) func overloadedAsyncFunc(value: Int) async {} +@available(SwiftStdlib 5.5, *) func overloadedAsyncFunc(value: String) async {} // More parameters in async but they have defaults and different labels @available(*, renamed: "defaultedParamsStart(newArg:arg:)") func defaultedParamsStart(arg: Int, completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'defaultedParamsStart(newArg:arg:)' declared here}} +// expected-note@+2 {{'defaultedParamsStart(newArg:arg:)' declared here}} +@available(SwiftStdlib 5.5, *) func defaultedParamsStart(newArg: String = "", arg: Int) async { } @available(*, renamed: "defaultedParamsStart2(newArg:arg:)") func defaultedParamsStart2(arg: Int, completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'defaultedParamsStart2(newArg:arg:)' declared here}} +// expected-note@+2 {{'defaultedParamsStart2(newArg:arg:)' declared here}} +@available(SwiftStdlib 5.5, *) func defaultedParamsStart2(newArg: Int = 0, arg: Int) async { } @available(*, renamed: "defaultedParamsMiddle(arg1:newArg:arg2:)") func defaultedParamsMiddle(arg1: Int, arg2: Int, completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'defaultedParamsMiddle(arg1:newArg:arg2:)' declared here}} +// expected-note@+2 {{'defaultedParamsMiddle(arg1:newArg:arg2:)' declared here}} +@available(SwiftStdlib 5.5, *) func defaultedParamsMiddle(arg1: Int, newArg: String = "", arg2: Int) async { } @available(*, renamed: "defaultedParamsMiddle2(arg1:newArg:arg2:)") func defaultedParamsMiddle2(arg1: Int, arg2: Int, completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'defaultedParamsMiddle2(arg1:newArg:arg2:)' declared here}} +// expected-note@+2 {{'defaultedParamsMiddle2(arg1:newArg:arg2:)' declared here}} +@available(SwiftStdlib 5.5, *) func defaultedParamsMiddle2(arg1: Int, newArg: Int = 0, arg2: Int) async { } @available(*, renamed: "defaultedParamsEnd(arg:newArg:)") func defaultedParamsEnd(arg: Int, completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'defaultedParamsEnd(arg:newArg:)' declared here}} +// expected-note@+2 {{'defaultedParamsEnd(arg:newArg:)' declared here}} +@available(SwiftStdlib 5.5, *) func defaultedParamsEnd(arg: Int, newArg: String = "") async { } @available(*, renamed: "defaultedParamsEnd2(arg:newArg:)") func defaultedParamsEnd2(arg: Int, completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'defaultedParamsEnd2(arg:newArg:)' declared here}} +// expected-note@+2 {{'defaultedParamsEnd2(arg:newArg:)' declared here}} +@available(SwiftStdlib 5.5, *) func defaultedParamsEnd2(arg: Int, newArg: Int = 0) async { } @available(*, renamed: "defaultedParamsEnd3(newArg:arg:)") func defaultedParamsEnd3(arg: Int, completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'defaultedParamsEnd3(newArg:arg:)' declared here}} +// expected-note@+2 {{'defaultedParamsEnd3(newArg:arg:)' declared here}} +@available(SwiftStdlib 5.5, *) func defaultedParamsEnd3(newArg: Int, arg: String = "") async { } @available(*, renamed: "defaultedParamsEnd4(newArg:arg:)") func defaultedParamsEnd4(arg: Int, completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'defaultedParamsEnd4(newArg:arg:)' declared here}} +// expected-note@+2 {{'defaultedParamsEnd4(newArg:arg:)' declared here}} +@available(SwiftStdlib 5.5, *) func defaultedParamsEnd4(newArg: Int, arg: Int = 0) async { } @available(*, deprecated) @@ -77,18 +89,22 @@ func defaultedParamsEnd4(newArg: Int, arg: Int = 0) async { } @available(macOS, deprecated: 12, renamed: "manyAttrsOld()") @available(*, deprecated) func manyAttrs(completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'manyAttrsNew()' declared here}} +// expected-note@+2 {{'manyAttrsNew()' declared here}} +@available(SwiftStdlib 5.5, *) func manyAttrsNew() async { } @available(macOS, introduced: 12, renamed: "platformOnlyNew()") func platformOnly(completionHandler: @escaping () -> Void) { } -// expected-note@+1 {{'platformOnlyNew()' declared here}} +// expected-note@+2 {{'platformOnlyNew()' declared here}} +@available(SwiftStdlib 5.5, *) func platformOnlyNew() async { } +@available(SwiftStdlib 5.5, *) struct AnotherStruct { var otherInstanceProp: Int { get async { 1 } } } +@available(SwiftStdlib 5.5, *) struct SomeStruct { @available(*, renamed: "structFunc") func structFunc(continuation: @escaping () -> Void) { } @@ -138,6 +154,7 @@ func badFunc(value: String, completionHandler: @escaping (Int) -> Void) {} // Not a completion handler @available(*, renamed: "notCompletionRenamed()") func notCompletion() {} +@available(SwiftStdlib 5.5, *) func notCompletionRenamed() async {} // Corresponding function isn't async @@ -148,22 +165,27 @@ func completionNotAsyncRenamed() {} // Renamed decl is ambiguous and there's multiple matches @available(*, renamed: "asyncFuncDifferentParamNames") func ambiguousFunc(value: Int, handler: @escaping () -> Void) {} +@available(SwiftStdlib 5.5, *) func asyncFuncDifferentParamNames(value: Int) async {} +@available(SwiftStdlib 5.5, *) func asyncFuncDifferentParamNames(value2: Int) async {} // Renamed decl doesn't have enough params @available(*, renamed: "fewerParamsFunc()") func fewerParamsFunc(value: Int, handler: @escaping () -> Void) {} +@available(SwiftStdlib 5.5, *) func fewerParamsFunc() async {} // Renamed decl has more params @available(*, renamed: "moreParamsFunc()") func moreParamsFunc(handler: @escaping () -> Void) {} +@available(SwiftStdlib 5.5, *) func moreParamsFunc(value: Int) async {} // Renamed decl params types don't match @available(*, renamed: "noMatchingParamsIntFunc(value:)") func noMatchingParamsFunc(value: Character, handler: @escaping () -> Void) {} +@available(SwiftStdlib 5.5, *) func noMatchingParamsIntFunc(value: Int) async {} // Matching function isn't async @@ -173,33 +195,40 @@ func noMatchingSyncFunc(value: Int) {} @available(*, renamed: "sameLabelsDifferentOrder(arg2:arg:)") func sameLabelsDifferentOrder(arg: Int, arg2: String, completionHandler: @escaping () -> Void) { } +@available(SwiftStdlib 5.5, *) func sameLabelsDifferentOrder(arg2: String, arg: Int) async { } @available(*, renamed: "handlerNotRemoved(newArg:completionHandler:)") func handlerNotRemoved(arg: Int, completionHandler: @escaping () -> Void) {} +@available(SwiftStdlib 5.5, *) func handlerNotRemoved(newArg: Int, completionHandler: @escaping () -> Void) async {} // Extra arguments. Even though there's defaults, they match the previous // labels so they shouldn't be skipped. Thus the functions do not match. @available(*, renamed: "defaultedParamsStartBad(arg:newArg:)") func defaultedParamsStartBad(arg: Int, completionHandler: @escaping () -> Void) { } +@available(SwiftStdlib 5.5, *) func defaultedParamsStartBad(arg: String = "", newArg: Int) async { } @available(*, renamed: "defaultedParamsStartBad2(arg:newArg:)") func defaultedParamsStartBad2(arg: Int, completionHandler: @escaping () -> Void) { } +@available(SwiftStdlib 5.5, *) func defaultedParamsStartBad2(arg: Int = 0, newArg: Int) async { } @available(*, renamed: "defaultedParamsMiddleBad(arg1:arg2:newArg:)") func defaultedParamsMiddleBad(arg1: Int, arg2: Int, completionHandler: @escaping () -> Void) { } +@available(SwiftStdlib 5.5, *) func defaultedParamsMiddleBad(arg1: Int, arg2: String = "", newArg: Int) async { } @available(*, renamed: "defaultedParamsMiddleBad2(arg1:arg2:newArg:)") func defaultedParamsMiddleBad2(arg1: Int, arg2: Int, completionHandler: @escaping () -> Void) { } +@available(SwiftStdlib 5.5, *) func defaultedParamsMiddleBad2(arg1: Int, arg2: Int = 0, newArg: Int) async { } // Suggest using async alternative function in async context +@available(SwiftStdlib 5.5, *) func asyncContext(t: HandlerTest) async { // expected-warning@+1{{consider using asynchronous alternative function}} goodFunc1(value: "Hello") { _ in } @@ -217,6 +246,14 @@ func asyncContext(t: HandlerTest) async { let _ = await asyncFunc("World") + defer { + goodFunc1(value: "Hello") { _ in } + } + + func syncFunc() { + goodFunc1(value: "Hello") { _ in } + } + // expected-warning@+1{{consider using asynchronous alternative function}} asyncOnlyOverload() { } // expected-warning@+1{{consider using asynchronous alternative function}} @@ -237,7 +274,8 @@ func asyncContext(t: HandlerTest) async { defaultedParamsEnd3(arg: 1) { } // expected-warning@+1{{consider using asynchronous alternative function}} defaultedParamsEnd4(arg: 1) { } - // expected-warning@+1{{consider using asynchronous alternative function}} + // expected-warning@+2{{consider using asynchronous alternative function}} + // expected-warning@+1{{'manyAttrs(completionHandler:)' is deprecated}} manyAttrs() { } // expected-warning@+1{{consider using asynchronous alternative function}} platformOnly() { } @@ -287,6 +325,7 @@ func asyncContext(t: HandlerTest) async { t.asyncImportSame(1, replyTo: { _ in }) } +@available(SwiftStdlib 5.5, *) func syncContext(t: HandlerTest) { goodFunc1(value: "Hello") { _ in } t.simple { _ in } @@ -303,6 +342,7 @@ let asyncGlobalClosure = { () async -> () in goodFunc1(value: "neat") { _ in } } +@available(SwiftStdlib 5.5, *) class ClassCallingAsyncStuff { struct NestedStruct { @available(*, renamed: "structFunc()") From 144395e1b0b68af4f9a3ae13644a42ecbdb71aaf Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Fri, 19 Aug 2022 13:59:01 -0700 Subject: [PATCH 229/491] Fix top-level crash/missing diagnostic This patch fixes the crash on assertion builds and the missing diagnostic on normal builds when operating on declarations in the top-level context. --- lib/Sema/TypeCheckAttr.cpp | 4 ++++ ...r_availability_async_rename_toplevel.swift | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 test/attr/attr_availability_async_rename_toplevel.swift diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 08a6afed1c123..6b76ba97eb082 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2733,6 +2733,10 @@ static void lookupReplacedDecl(DeclNameRef replacedDeclName, SmallVectorImpl &results) { auto *declCtxt = replacement->getDeclContext(); + // Hop up to the FileUnit if we're in top-level code + if (auto *toplevel = dyn_cast(declCtxt)) + declCtxt = toplevel->getDeclContext(); + // Look at the accessors' storage's context. if (auto *accessor = dyn_cast(replacement)) { auto *storage = accessor->getStorage(); diff --git a/test/attr/attr_availability_async_rename_toplevel.swift b/test/attr/attr_availability_async_rename_toplevel.swift new file mode 100644 index 0000000000000..d53d34ad584d9 --- /dev/null +++ b/test/attr/attr_availability_async_rename_toplevel.swift @@ -0,0 +1,22 @@ +// REQUIRES: concurrency + +// RUN: %target-typecheck-verify-swift + +if #available(macOS 12.0, *) { + @available(*, renamed: "process(data:)") + func process(data: [Int], completion: @escaping ([Int]) -> Void) { completion(data) } + // expected-note@+1{{'process(data:)' declared here}} + func process(data: [Int]) async -> [Int] { return data } + + func asyncFunc(data: [Int]) async { + defer { + process(data: data, completion: { print($0) }) + } + + func b() { + process(data: data, completion: { print($0) }) + } + // expected-warning@+1{{consider using asynchronous alternative function}} + process(data: data, completion: { print($0) }) + } +} From 390d8cc44bf6bd3ac33e05a9de91112f8019c282 Mon Sep 17 00:00:00 2001 From: Suyash Srijan Date: Sat, 20 Aug 2022 15:36:15 +0100 Subject: [PATCH 230/491] [IDE] Add result builder code completion for buildPartialBlock (#60669) --- include/swift/Sema/IDETypeChecking.h | 2 ++ lib/IDE/CompletionOverrideLookup.cpp | 11 +++++++++++ lib/Sema/BuilderTransform.cpp | 7 +++++++ test/IDE/complete_result_builder.swift | 6 +++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index cee45e2f21d32..25dd12bb0d03c 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -304,6 +304,8 @@ namespace swift { BuildArray, BuildLimitedAvailability, BuildFinalResult, + BuildPartialBlockFirst, + BuildPartialBlockAccumulated, }; /// Try to infer the component type of a result builder from the type diff --git a/lib/IDE/CompletionOverrideLookup.cpp b/lib/IDE/CompletionOverrideLookup.cpp index f4cd3e4e79ae1..4c5862f176684 100644 --- a/lib/IDE/CompletionOverrideLookup.cpp +++ b/lib/IDE/CompletionOverrideLookup.cpp @@ -462,6 +462,11 @@ StringRef CompletionOverrideLookup::getResultBuilderDocComment( case ResultBuilderBuildFunction::BuildOptional: return "Enables support for `if` statements that do not have an `else`"; + case ResultBuilderBuildFunction::BuildPartialBlockFirst: + return "Builds a partial result component from the first component"; + case ResultBuilderBuildFunction::BuildPartialBlockAccumulated: + return "Builds a partial result component by combining an accumulated " + "component and a new component"; } } @@ -514,6 +519,12 @@ void CompletionOverrideLookup::addResultBuilderBuildCompletions( ResultBuilderBuildFunction::BuildLimitedAvailability); addResultBuilderBuildCompletion(builder, componentType, ResultBuilderBuildFunction::BuildFinalResult); + addResultBuilderBuildCompletion( + builder, componentType, + ResultBuilderBuildFunction::BuildPartialBlockFirst); + addResultBuilderBuildCompletion( + builder, componentType, + ResultBuilderBuildFunction::BuildPartialBlockAccumulated); } void CompletionOverrideLookup::getOverrideCompletions(SourceLoc Loc) { diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index f7d7a84c24b46..e1d3ba18cce75 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -2930,6 +2930,13 @@ void swift::printResultBuilderBuildFunction( << ") -> <#Result#>"; printedResult = true; break; + case ResultBuilderBuildFunction::BuildPartialBlockFirst: + printer << "buildPartialBlock(first: " << componentTypeString << ")"; + break; + case ResultBuilderBuildFunction::BuildPartialBlockAccumulated: + printer << "buildPartialBlock(accumulated: " << componentTypeString + << ", next: " << componentTypeString << ")"; + break; } if (!printedResult) diff --git a/test/IDE/complete_result_builder.swift b/test/IDE/complete_result_builder.swift index 9038b18a904cb..bd34b232b5a37 100644 --- a/test/IDE/complete_result_builder.swift +++ b/test/IDE/complete_result_builder.swift @@ -105,7 +105,7 @@ struct AnyBuilder { static func #^IN_RESULT_BUILDER_DECL^# } -// IN_RESULT_BUILDER_DECL: Begin completions, 8 items +// IN_RESULT_BUILDER_DECL: Begin completions, 10 items // IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildBlock(_ components: Any...) -> Any {|}; name=buildBlock(_ components: Any...) -> Any; comment=Required by every // IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildExpression(_ expression: <#Expression#>) -> Any {|}; name=buildExpression(_ expression: <#Expression#>) -> Any; comment= // IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildOptional(_ component: Any?) -> Any {|}; name=buildOptional(_ component: Any?) -> Any; comment= @@ -114,6 +114,8 @@ struct AnyBuilder { // IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildArray(_ components: [Any]) -> Any {|}; name=buildArray(_ components: [Any]) -> Any; comment= // IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildLimitedAvailability(_ component: Any) -> Any {|}; name=buildLimitedAvailability(_ component: Any) -> Any; comment= // IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildFinalResult(_ component: Any) -> <#Result#> {|}; name=buildFinalResult(_ component: Any) -> <#Result#>; comment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildPartialBlock(first: Any) -> Any {|}; name=buildPartialBlock(first: Any) -> Any; comment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildPartialBlock(accumulated: Any, next: Any) -> Any {|}; name=buildPartialBlock(accumulated: Any, next: Any) -> Any; comment= // IN_RESULT_BUILDER_DECL: End completions // IN_RESULT_BUILDER_DECL_PREFIX: Begin completions @@ -125,4 +127,6 @@ struct AnyBuilder { // IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildArray(_ components: [Any]) -> Any {|}; name=static func buildArray(_ components: [Any]) -> Any; comment= // IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildLimitedAvailability(_ component: Any) -> Any {|}; name=static func buildLimitedAvailability(_ component: Any) -> Any; comment= // IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildFinalResult(_ component: Any) -> <#Result#> {|}; name=static func buildFinalResult(_ component: Any) -> <#Result#>; comment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildPartialBlock(first: Any) -> Any {|}; name=static func buildPartialBlock(first: Any) -> Any; comment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildPartialBlock(accumulated: Any, next: Any) -> Any {|}; name=static func buildPartialBlock(accumulated: Any, next: Any) -> Any; comment= // IN_RESULT_BUILDER_DECL_PREFIX: End completions From 05b61be2a65c8846116f6978c3cc8a200d8ce877 Mon Sep 17 00:00:00 2001 From: YR Chen Date: Sat, 20 Aug 2022 23:23:53 +0800 Subject: [PATCH 231/491] [build-windows] Don't download ICU ...until we want to build Foundation. --- utils/build-windows.bat | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/build-windows.bat b/utils/build-windows.bat index 3047ed567fec8..b23b639be680e 100644 --- a/utils/build-windows.bat +++ b/utils/build-windows.bat @@ -68,9 +68,10 @@ set RunTest=1 if "%1"=="-notest" set RunTest=0 call :clone_repositories %exitOnError% -call :download_icu %exitOnError% +:: TODO: Disabled until we need Foundation in this build script. +:: call :download_icu %exitOnError% :: TODO: Disabled until we need LLBuild/SwiftPM in this build script. -:: call :download_sqlite3 +:: call :download_sqlite3 %exitOnError% call :build_llvm %exitOnError% path %PATH%;%install_directory%\bin @@ -85,7 +86,7 @@ call :build_lldb %exitOnError% path %PATH%;C:\Program Files\Git\usr\bin call :build_libdispatch %exitOnError% -path %source_root%\icu-%icu_version%\bin64;%install_directory%\bin;%build_root%\swift\bin;%build_root%\swift\libdispatch-prefix\bin;%PATH% +path %install_directory%\bin;%build_root%\swift\bin;%build_root%\swift\libdispatch-prefix\bin;%PATH% if %RunTest%==1 ( call :test_swift %exitOnError% @@ -134,8 +135,7 @@ endlocal :download_icu -:: Downloads ICU, which will be used as a dependency for the Swift Standard -:: Library and Foundation. +:: Downloads ICU, which will be used as a dependency for Foundation. setlocal enableextensions enabledelayedexpansion set file_name=icu4c-%icu_version%-Win64-MSVC2017.zip From 92c85a062c474bab163af5f5a9a03723070217df Mon Sep 17 00:00:00 2001 From: YR Chen Date: Sat, 20 Aug 2022 23:24:42 +0800 Subject: [PATCH 232/491] [build-windows] Remove hard-coded `C:` .. and use `%SystemDrive%` instead to enhance robustness. --- utils/build-windows.bat | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/build-windows.bat b/utils/build-windows.bat index b23b639be680e..f7f8b76804ff7 100644 --- a/utils/build-windows.bat +++ b/utils/build-windows.bat @@ -83,7 +83,7 @@ call :build_swift %exitOnError% call :build_lldb %exitOnError% -path %PATH%;C:\Program Files\Git\usr\bin +path %PATH%;%SystemDrive%\Program Files\Git\usr\bin call :build_libdispatch %exitOnError% path %install_directory%\bin;%build_root%\swift\bin;%build_root%\swift\libdispatch-prefix\bin;%PATH% @@ -142,7 +142,7 @@ set file_name=icu4c-%icu_version%-Win64-MSVC2017.zip curl -L -O "https://github.com/unicode-org/icu/releases/download/release-%icu_version_dashed%/%file_name%" %exitOnError% :: unzip warns about the paths in the zip using slashes, which raises the :: errorLevel to 1. We cannot use exitOnError, and have to ignore errors. -"C:\Program Files\Git\usr\bin\unzip.exe" -o %file_name% -d "%source_root%\icu-%icu_version%" +"%SystemDrive%\Program Files\Git\usr\bin\unzip.exe" -o %file_name% -d "%source_root%\icu-%icu_version%" exit /b 0 goto :eof @@ -156,7 +156,7 @@ setlocal enableextensions enabledelayedexpansion set file_name=sqlite-amalgamation-3270200.zip curl -L -O "https://www.sqlite.org/2019/%file_name%" %exitOnError% -"C:\Program Files\Git\usr\bin\unzip.exe" -o %file_name% %exitOnError% +"%SystemDrive%\Program Files\Git\usr\bin\unzip.exe" -o %file_name% %exitOnError% goto :eof endlocal From d820fcf7318bd32919e128af7f65c63457ddfc6f Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Sun, 21 Aug 2022 02:57:40 +0300 Subject: [PATCH 233/491] Gardening: Migrate test suite to GH issues: CrossImport --- test/CrossImport/horrible.swift | 3 ++- test/CrossImport/remark-option.swift | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/CrossImport/horrible.swift b/test/CrossImport/horrible.swift index d94acc330bc11..803283f6d8042 100644 --- a/test/CrossImport/horrible.swift +++ b/test/CrossImport/horrible.swift @@ -16,7 +16,8 @@ import UnitaryGoose // expected-error@-1 {{cannot list cross-import overlays for 'UnitaryGoose':}} // FIXME: It might be better to diagnose these errors on HorribleGoose's import -// decl, since they actually belong to HorribleGoose. (SR-12223) +// decl, since they actually belong to HorribleGoose. +// (https://github.com/apple/swift/issues/54649) import FlockOfGoose // expected-error@-1 {{cannot load cross-import overlay for 'HorribleGoose' and 'FlockOfGoose':}} diff --git a/test/CrossImport/remark-option.swift b/test/CrossImport/remark-option.swift index 820fd287017b2..4854d911d769d 100644 --- a/test/CrossImport/remark-option.swift +++ b/test/CrossImport/remark-option.swift @@ -4,6 +4,7 @@ // RUN: %target-typecheck-verify-swift -enable-cross-import-overlays -Rcross-import -I %t/include -I %t/lib/swift -F %t/Frameworks import DeclaringLibrary -// FIXME: Similarly to horrible.swift, ideally we would emit this remark on DeclaringLibrary -// decl, since the cross-import overlay actually belongs to the DeclaringLibrary. (SR-12223) +// FIXME: Similarly to horrible.swift, ideally we would emit this remark on +// DeclaringLibrary decl, since the cross-import overlay actually belongs to +// the DeclaringLibrary. (https://github.com/apple/swift/issues/54649) import BystandingLibrary // expected-remark {{import of 'DeclaringLibrary' and 'BystandingLibrary' triggered a cross-import of '_OverlayLibrary'}} From f8f9b5f8d078c2c4256375e5856608c45e6b3bde Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Sun, 21 Aug 2022 03:00:44 +0300 Subject: [PATCH 234/491] Gardening: Migrate test suite to GH issues: DebugInfo --- test/DebugInfo/debug_variable.sil | 4 ++-- test/DebugInfo/optimizer_pipeline.swift | 4 +++- test/DebugInfo/retroactive_conformance_witness_thunk.swift | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/DebugInfo/debug_variable.sil b/test/DebugInfo/debug_variable.sil index 0041930374a7d..985c9e5c3f7ef 100644 --- a/test/DebugInfo/debug_variable.sil +++ b/test/DebugInfo/debug_variable.sil @@ -6,8 +6,8 @@ import Swift sil_scope 2 { loc "simple.swift":1:2 parent @test_debug_value : $@convention(thin) (Int) -> () } -// SR-14868: Incorrect source location on `llvm.dbg.declare` when the input -// is SIL file. +// https://github.com/apple/swift/issues/57215 +// Incorrect source location on 'llvm.dbg.declare' when the input is a SIL file // CHECK: @test_debug_value // CHECK-SAME: !dbg ![[FUNC_DI:[0-9]+]] diff --git a/test/DebugInfo/optimizer_pipeline.swift b/test/DebugInfo/optimizer_pipeline.swift index 05984193ded0d..9d316911ea54f 100644 --- a/test/DebugInfo/optimizer_pipeline.swift +++ b/test/DebugInfo/optimizer_pipeline.swift @@ -5,7 +5,9 @@ import Swift // Test that DCE correctly preserves debug locations. -// SR-15300: Compiler crash when using Builtin.unreachable in initializers + +// https://github.com/apple/swift/issues/57622 +// Compiler crash when using 'Builtin.unreachable' in initializers // // CHECK: sil_scope [[S1:[0-9]+]] { {{.*}} parent @$s18optimizer_pipeline1AVyACs13KeyValuePairsVyypypGcfC // CHECK: sil_scope [[S2:[0-9]+]] { {{.*}} parent [[S1]] } diff --git a/test/DebugInfo/retroactive_conformance_witness_thunk.swift b/test/DebugInfo/retroactive_conformance_witness_thunk.swift index 86c939d4f7c65..bde0f76b844c0 100644 --- a/test/DebugInfo/retroactive_conformance_witness_thunk.swift +++ b/test/DebugInfo/retroactive_conformance_witness_thunk.swift @@ -1,6 +1,6 @@ // RUN: %target-swift-frontend -emit-ir -g -primary-file %s -// https://bugs.swift.org/browse/SR-14016 +// https://github.com/apple/swift/issues/56409 public struct PowerCollection : Collection { public typealias Index = [C.Index] From c13dd18ef8dbf875ba7e77391c3e64ba587b0e90 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 19 Aug 2022 22:23:31 -0700 Subject: [PATCH 235/491] Sema: Diagnose the availability of global actor attributes. This includes SPI and resilience diagnostics. --- lib/Sema/TypeCheckAccess.cpp | 9 +++++ test/ClangImporter/objc_async.swift | 2 + .../concurrent_value_inference.swift | 3 ++ .../flow_isolation_nonstrict.swift | 1 + .../require-explicit-sendable.swift | 6 +++ .../sendable_conformance_checking.swift | 3 ++ test/SILGen/functions_uninhabited_param.swift | 1 + test/SPI/spi_global_actor.swift | 20 ++++++++++ test/Sema/availability_global_actor.swift | 37 +++++++++++++++++++ test/attr/attr_inlinable_global_actor.swift | 33 ++++++++++++++++- 10 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 test/SPI/spi_global_actor.swift create mode 100644 test/Sema/availability_global_actor.swift diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 0678ad3a73688..f792499b12b8e 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -1677,6 +1677,15 @@ class DeclAvailabilityChecker : public DeclVisitor { explicit DeclAvailabilityChecker(ExportContext where) : Where(where) {} + void visit(Decl *D) { + DeclVisitor::visit(D); + + if (auto globalActor = D->getGlobalActorAttr()) { + auto customAttr = globalActor->first; + checkType(customAttr->getType(), customAttr->getTypeRepr(), D); + } + } + // Force all kinds to be handled at a lower level. void visitDecl(Decl *D) = delete; void visitValueDecl(ValueDecl *D) = delete; diff --git a/test/ClangImporter/objc_async.swift b/test/ClangImporter/objc_async.swift index c7f56649326b5..8bacc478a54c0 100644 --- a/test/ClangImporter/objc_async.swift +++ b/test/ClangImporter/objc_async.swift @@ -311,6 +311,7 @@ class BazFrame: NotIsolatedPictureFrame { } } +@available(SwiftStdlib 5.5, *) @SomeGlobalActor class BazFrameIso: PictureFrame { // expected-error {{global actor 'SomeGlobalActor'-isolated class 'BazFrameIso' has different actor isolation from main actor-isolated superclass 'PictureFrame'}} } @@ -387,6 +388,7 @@ extension SomeWrapper: Sendable where T: Sendable {} // rdar://96830159 +@available(SwiftStdlib 5.5, *) @MainActor class SendableCompletionHandler { var isolatedThing: [String] = [] // expected-note@-1 {{property declared here}} diff --git a/test/Concurrency/concurrent_value_inference.swift b/test/Concurrency/concurrent_value_inference.swift index 21ca49cc77ce2..c08f932ae2c71 100644 --- a/test/Concurrency/concurrent_value_inference.swift +++ b/test/Concurrency/concurrent_value_inference.swift @@ -91,9 +91,11 @@ actor MyGlobalActor { static let shared = MyGlobalActor() } +@available(SwiftStdlib 5.1, *) @MyGlobalActor class C3 { } +@available(SwiftStdlib 5.1, *) class C4: C3 { } // Make Sendable unavailable, but be sure not to diagnose it. @@ -104,6 +106,7 @@ struct S2 { @available(*, unavailable) extension S2: Sendable { } +@available(SwiftStdlib 5.1, *) func testCV( c1: C1, c2: C2, c3: C3, c4: C4, s1: S1, e1: E1, e2: E2, gs1: GS1, gs2: GS2, diff --git a/test/Concurrency/flow_isolation_nonstrict.swift b/test/Concurrency/flow_isolation_nonstrict.swift index 34a56fb2bf3e3..96a101cd25a5f 100644 --- a/test/Concurrency/flow_isolation_nonstrict.swift +++ b/test/Concurrency/flow_isolation_nonstrict.swift @@ -30,6 +30,7 @@ actor CheckDeinitFromActor { } } +@available(SwiftStdlib 5.1, *) @MainActor class X { var ns: NonSendableType = NonSendableType() diff --git a/test/Concurrency/require-explicit-sendable.swift b/test/Concurrency/require-explicit-sendable.swift index c9ebb6d92c0da..0b57b2861f0f0 100644 --- a/test/Concurrency/require-explicit-sendable.swift +++ b/test/Concurrency/require-explicit-sendable.swift @@ -101,10 +101,16 @@ struct S11: Sendable { @_nonSendable public struct S12 { } // Don't complain about global-actor-qualified classes or their subclasses. +@available(SwiftStdlib 5.1, *) @MainActor open class TestThing {} + +@available(SwiftStdlib 5.1, *) open class TestSubThing : TestThing {} +@available(SwiftStdlib 5.1, *) @MainActor(unsafe) open class TestThing2 {} + +@available(SwiftStdlib 5.1, *) open class TestSubThing2 : TestThing2 {} diff --git a/test/Concurrency/sendable_conformance_checking.swift b/test/Concurrency/sendable_conformance_checking.swift index 08a602aaa1a34..fc79c5ac3ba7a 100644 --- a/test/Concurrency/sendable_conformance_checking.swift +++ b/test/Concurrency/sendable_conformance_checking.swift @@ -159,7 +159,10 @@ final class SubKlass: Klass<[S]> {} public struct S {} // rdar://88700507 - redundant conformance of @MainActor-isolated subclass to 'Sendable' +@available(SwiftStdlib 5.1, *) @MainActor class MainSuper {} + +@available(SwiftStdlib 5.1, *) class MainSub: MainSuper, @unchecked Sendable {} class SendableSuper: @unchecked Sendable {} diff --git a/test/SILGen/functions_uninhabited_param.swift b/test/SILGen/functions_uninhabited_param.swift index bb04b6e91bee7..24727e1824e2d 100644 --- a/test/SILGen/functions_uninhabited_param.swift +++ b/test/SILGen/functions_uninhabited_param.swift @@ -25,6 +25,7 @@ enum E { static func f(_: E) {} } +@available(SwiftStdlib 5.1, *) @MainActor class Bar { var foo: (E) -> Void = { _ in } diff --git a/test/SPI/spi_global_actor.swift b/test/SPI/spi_global_actor.swift new file mode 100644 index 0000000000000..01a5c08ce130d --- /dev/null +++ b/test/SPI/spi_global_actor.swift @@ -0,0 +1,20 @@ +// RUN: %target-typecheck-verify-swift + +// REQUIRES: concurrency + +@available(SwiftStdlib 5.1, *) +@_spi(Foo) +@globalActor +public struct SPIGA { // expected-note {{type declared here}} + public actor Actor {} + public static let shared = Actor() +} + +@available(SwiftStdlib 5.1, *) +@SPIGA // expected-error {{cannot use struct 'SPIGA' here; it is SPI}} +public struct PublicStruct {} + +@available(SwiftStdlib 5.1, *) +@_spi(Foo) +@SPIGA +public struct SPIStruct {} diff --git a/test/Sema/availability_global_actor.swift b/test/Sema/availability_global_actor.swift new file mode 100644 index 0000000000000..f1b971f5224bd --- /dev/null +++ b/test/Sema/availability_global_actor.swift @@ -0,0 +1,37 @@ +// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.50 + +// REQUIRES: concurrency +// REQUIRES: OS=macosx + +actor SomeActor {} + +@globalActor struct AlwaysAvailableGA { + static let shared = SomeActor() +} + +@available(macOS 10.51, *) +@globalActor struct Available10_51GA { + static let shared = SomeActor() +} + +@available(*, unavailable) +@globalActor struct UnavailableGA { // expected-note {{'UnavailableGA' has been explicitly marked unavailable here}} + static let shared = SomeActor() +} + +@AlwaysAvailableGA +struct AlwaysAvailableWithAlwaysAvailableGA {} + +@Available10_51GA // expected-error {{'Available10_51GA' is only available in macOS 10.51 or newer}} +struct AlwaysAvailableWithAvailable10_51GA {} // expected-note {{add @available attribute to enclosing struct}} + +@available(macOS 10.51, *) +@Available10_51GA +struct Always10_51WithAvailable10_51GA {} + +@UnavailableGA // expected-error {{'UnavailableGA' is unavailable}} +struct AlwaysAvailableWithUnavailableGA {} + +@available(*, unavailable) +@UnavailableGA +struct UnavailableWithUnavailableGA {} diff --git a/test/attr/attr_inlinable_global_actor.swift b/test/attr/attr_inlinable_global_actor.swift index 14f9e57806d74..53215adfdd7de 100644 --- a/test/attr/attr_inlinable_global_actor.swift +++ b/test/attr/attr_inlinable_global_actor.swift @@ -2,32 +2,61 @@ // REQUIRES: concurrency +@available(SwiftStdlib 5.1, *) @globalActor private struct PrivateGA { // expected-note 2 {{type declared here}} actor Actor {} static let shared = Actor() } +@available(SwiftStdlib 5.1, *) @globalActor internal struct InternalGA { // expected-note {{type declared here}} actor Actor {} static let shared = Actor() } -@globalActor @usableFromInline +@available(SwiftStdlib 5.1, *) +@globalActor +@usableFromInline internal struct UFIGA { @usableFromInline actor Actor {} @usableFromInline static let shared = Actor() } +@available(SwiftStdlib 5.1, *) @globalActor public struct PublicGA { public actor Actor {} public static let shared = Actor() } -// expected-error@+1 {{internal struct 'UFIStructPrivateGA' cannot have private global actor 'PrivateGA'}} +// expected-error@+2 {{internal struct 'UFIStructPrivateGA' cannot have private global actor 'PrivateGA'}} +@available(SwiftStdlib 5.1, *) @PrivateGA @usableFromInline internal struct UFIStructPrivateGA {} // expected-error {{global actor for struct 'UFIStructPrivateGA' must be '@usableFromInline' or public}} +@available(SwiftStdlib 5.1, *) @InternalGA @usableFromInline internal struct UFIStructInternalGA {} // expected-error {{global actor for struct 'UFIStructInternalGA' must be '@usableFromInline' or public}} +@available(SwiftStdlib 5.1, *) @UFIGA @usableFromInline internal struct UFIStructUFIGA {} +@available(SwiftStdlib 5.1, *) @PublicGA @usableFromInline internal struct UFIStructPublicGA {} + +@available(SwiftStdlib 5.1, *) +@inlinable public func testNestedFuncs() { + // FIXME: Functions isolated to non-resilient global actors nested in + // inlinable functions should be diagnosed. + @PrivateGA func inlineFuncPrivateGA() {} + @InternalGA func inlineFuncInternalGA() {} + @UFIGA func inlineFuncUFIGA() {} + @PublicGA func inlineFuncPublicGA() {} +} + +@available(SwiftStdlib 5.1, *) +@inlinable public func testNestedClosures() { + // FIXME: Closures isolated to non-resilient global actors nested in + // inlinable functions should be diagnosed. + _ = { @PrivateGA in } + _ = { @InternalGA in } + _ = { @UFIGA in } + _ = { @PublicGA in } +} From 67d807d9e0ca27aee134b6cff908712b0e3503fb Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 7 Jul 2022 18:52:21 -0700 Subject: [PATCH 236/491] [CSStep] List type variables in scope under consideration for each component step. --- lib/Sema/CSStep.h | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/Sema/CSStep.h b/lib/Sema/CSStep.h index a117776651b5e..79f69d2c2748a 100644 --- a/lib/Sema/CSStep.h +++ b/lib/Sema/CSStep.h @@ -466,11 +466,29 @@ class ComponentStep final : public SolverStep { // to preliminary modify constraint system or log anything. if (IsSingle) return; - - if (CS.isDebugMode()) - getDebugLogger() << "(solving component #" << Index << '\n'; - + + if (CS.isDebugMode()) { + auto &log = getDebugLogger(); + log << "(solving component #" << Index << '\n'; + } + ComponentScope = std::make_unique(*this); + + if (CS.isDebugMode()) { + auto &log = getDebugLogger(); + log << "Type variables in scope = " + << "["; + auto typeVars = CS.getTypeVariables(); + PrintOptions PO; + PO.PrintTypesForDebugging = true; + interleave(typeVars, [&](TypeVariableType *typeVar) { + Type(typeVar).print(log, PO); + }, + [&] { + log << ", "; + }); + log << "]" << '\n'; + } // If this component has orphaned constraint attached, // let's return it to the graph. From e3e446b91853e488810d0c53f4765b48778dbfac Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 7 Jul 2022 18:56:45 -0700 Subject: [PATCH 237/491] [CSStep] Remove previous "Initial binding" output. --- lib/Sema/CSStep.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/Sema/CSStep.cpp b/lib/Sema/CSStep.cpp index 0bd838b6fe0fa..9f8058911bc23 100644 --- a/lib/Sema/CSStep.cpp +++ b/lib/Sema/CSStep.cpp @@ -486,23 +486,6 @@ StepResult ComponentStep::finalize(bool isSuccess) { void TypeVariableStep::setup() { ++CS.solverState->NumTypeVariablesBound; - if (CS.isDebugMode()) { - PrintOptions PO; - PO.PrintTypesForDebugging = true; - auto &log = getDebugLogger(); - - auto initialBindings = Producer.getCurrentBindings(); - log << "Initial bindings: "; - interleave( - initialBindings.begin(), initialBindings.end(), - [&](const Binding &binding) { - log << TypeVar->getString(PO) - << " := " << binding.BindingType->getString(PO); - }, - [&log] { log << ", "; }); - - log << '\n'; - } } bool TypeVariableStep::attempt(const TypeVariableBinding &choice) { From 177f13616488cdd560ce7dc1cbcb829440321efa Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 7 Jul 2022 22:16:36 -0700 Subject: [PATCH 238/491] [CSStep] Add disjunction and conjunction printing to initial state displayed during component step. --- lib/Sema/CSStep.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSStep.cpp b/lib/Sema/CSStep.cpp index 9f8058911bc23..b891ca3fd3748 100644 --- a/lib/Sema/CSStep.cpp +++ b/lib/Sema/CSStep.cpp @@ -346,8 +346,31 @@ StepResult ComponentStep::take(bool prevFailed) { /// Try to figure out what this step is going to be, /// after the scope has been established. - auto *disjunction = CS.selectDisjunction(); auto bestBindings = CS.determineBestBindings(); + auto *disjunction = CS.selectDisjunction(); + auto *conjunction = CS.selectConjunction(); + + if (CS.isDebugMode()) { + PrintOptions PO; + PO.PrintTypesForDebugging = true; + + if (disjunction) { + auto &log = getDebugLogger(); + log.indent(2); + log << "Disjunction(s) = ["; + auto constraints = disjunction->getNestedConstraints(); + log << constraints[0]->getFirstType()->getString(PO); + log << "])\n"; + } + if (conjunction) { + auto &log = getDebugLogger(); + log.indent(2); + log << "Conjunction(s) = ["; + auto constraints = conjunction->getNestedConstraints(); + log << constraints[0]->getFirstType()->getString(PO); + log << "])\n"; + } + } if (CS.shouldAttemptFixes()) { if ((bestBindings && From bd2968e2c12f131f1bf348d5173dbb46509a5d31 Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Fri, 12 Aug 2022 14:59:57 -0700 Subject: [PATCH 239/491] [ConstraintGraph] Make Changes member types public and create accessor for Active Scope starting index for use in printing. --- include/swift/Sema/ConstraintGraph.h | 2 +- include/swift/Sema/ConstraintGraphScope.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/swift/Sema/ConstraintGraph.h b/include/swift/Sema/ConstraintGraph.h index 8006a055bd414..706b2a5ede057 100644 --- a/include/swift/Sema/ConstraintGraph.h +++ b/include/swift/Sema/ConstraintGraph.h @@ -458,6 +458,7 @@ class ConstraintGraph { /// Each change can be undone (once, and in reverse order) by calling the /// undo() method. class Change { + public: /// The kind of change. ChangeKind Kind; @@ -482,7 +483,6 @@ class ConstraintGraph { } Binding; }; - public: Change() : Kind(ChangeKind::AddedTypeVariable), TypeVar(nullptr) { } /// Create a change that added a type variable. diff --git a/include/swift/Sema/ConstraintGraphScope.h b/include/swift/Sema/ConstraintGraphScope.h index c3e594a5ccd13..e6316126c781a 100644 --- a/include/swift/Sema/ConstraintGraphScope.h +++ b/include/swift/Sema/ConstraintGraphScope.h @@ -50,6 +50,11 @@ class ConstraintGraphScope { public: explicit ConstraintGraphScope(ConstraintGraph &CG); ~ConstraintGraphScope(); + + /// Get number of changes recorded at the start of the current active scope. + unsigned getStartIdx() { + return NumChanges; + } }; } // end namespace constraints From d10381557b390095fc6a612afeb9a1e7c02f8401 Mon Sep 17 00:00:00 2001 From: YOCKOW Date: Sun, 21 Aug 2022 16:07:07 +0900 Subject: [PATCH 240/491] [NFC] Python Lint: Fix E275(missing whitespace after keyword) issues. --- .../Inputs/filelists/check-filelist-abc.py | 20 ++++++++--------- test/Serialization/Inputs/binary_sub.py | 2 +- .../bindings/python/sourcekitd/capi.py | 2 +- utils/GYBUnicodeDataUtils.py | 22 +++++++++---------- utils/backtrace-check | 6 ++--- utils/bug_reducer/bug_reducer/list_reducer.py | 4 ++-- utils/bug_reducer/bug_reducer/swift_tools.py | 16 +++++++------- .../tests/build_swift/test_cache_utils.py | 2 +- .../tests/build_swift/test_shell.py | 4 ++-- utils/dev-scripts/scurve_printer.py | 2 +- utils/gyb_syntax_support/Node.py | 2 +- utils/jobstats/jobstats.py | 8 +++---- utils/line-directive | 4 ++-- utils/process-stats-dir.py | 2 +- utils/scale-test | 6 ++--- .../swift_build_support/build_graph.py | 6 ++--- .../build_script_invocation.py | 2 +- .../swift_build_support/compiler_stage.py | 2 +- .../productpipeline_list_builder.py | 22 +++++++++---------- .../swift_build_support/shell.py | 2 +- 20 files changed, 68 insertions(+), 68 deletions(-) diff --git a/test/Driver/Inputs/filelists/check-filelist-abc.py b/test/Driver/Inputs/filelists/check-filelist-abc.py index 8a2247740946a..be198bf9825b2 100755 --- a/test/Driver/Inputs/filelists/check-filelist-abc.py +++ b/test/Driver/Inputs/filelists/check-filelist-abc.py @@ -28,12 +28,12 @@ with open(filelistFile, 'r') as f: lines = f.readlines() - assert(lines[0].endswith("/a.swift\n") or - lines[0].endswith("/a.swiftmodule\n")) - assert(lines[1].endswith("/b.swift\n") or - lines[1].endswith("/b.swiftmodule\n")) - assert(lines[2].endswith("/c.swift\n") or - lines[2].endswith("/c.swiftmodule\n")) + assert (lines[0].endswith("/a.swift\n") or + lines[0].endswith("/a.swiftmodule\n")) + assert (lines[1].endswith("/b.swift\n") or + lines[1].endswith("/b.swiftmodule\n")) + assert (lines[2].endswith("/c.swift\n") or + lines[2].endswith("/c.swiftmodule\n")) if primaryFile: print("Command-line primary", os.path.basename(primaryFile)) @@ -42,7 +42,7 @@ primaryFilelistFile = sys.argv[sys.argv.index('-primary-filelist') + 1] with open(primaryFilelistFile, 'r') as f: lines = f.readlines() - assert(len(lines) == 1) + assert len(lines) == 1 print("Handled", os.path.basename(lines[0]).rstrip()) elif lines[0].endswith(".swiftmodule\n"): print("Handled modules") @@ -63,7 +63,7 @@ outputListFile = sys.argv[sys.argv.index('-output-filelist') + 1] with open(outputListFile, 'r') as f: lines = f.readlines() - assert(lines[0].endswith("/a.o\n") or lines[0].endswith("/a.bc\n")) - assert(lines[1].endswith("/b.o\n") or lines[1].endswith("/b.bc\n")) - assert(lines[2].endswith("/c.o\n") or lines[2].endswith("/c.bc\n")) + assert lines[0].endswith("/a.o\n") or lines[0].endswith("/a.bc\n") + assert lines[1].endswith("/b.o\n") or lines[1].endswith("/b.bc\n") + assert lines[2].endswith("/c.o\n") or lines[2].endswith("/c.bc\n") print("...with output!") diff --git a/test/Serialization/Inputs/binary_sub.py b/test/Serialization/Inputs/binary_sub.py index b1b3378db4ae1..b667b923fc5fc 100755 --- a/test/Serialization/Inputs/binary_sub.py +++ b/test/Serialization/Inputs/binary_sub.py @@ -3,7 +3,7 @@ import sys (_, old, new) = sys.argv -assert(len(old) == len(new)) +assert len(old) == len(new) if sys.version_info[0] < 3: data = sys.stdin.read() diff --git a/tools/SourceKit/bindings/python/sourcekitd/capi.py b/tools/SourceKit/bindings/python/sourcekitd/capi.py index 58b92358ed283..6d43a7f8c8e26 100644 --- a/tools/SourceKit/bindings/python/sourcekitd/capi.py +++ b/tools/SourceKit/bindings/python/sourcekitd/capi.py @@ -232,7 +232,7 @@ def to_python_object(self): elif var_ty == VariantType.UID: return UIdent(conf.lib.sourcekitd_variant_uid_get_value(self)) else: - assert(var_ty == VariantType.BOOL) + assert var_ty == VariantType.BOOL return conf.lib.sourcekitd_variant_bool_get_value(self) def to_python_array(self): diff --git a/utils/GYBUnicodeDataUtils.py b/utils/GYBUnicodeDataUtils.py index 3c541c4d5076c..73a72c6b084b2 100644 --- a/utils/GYBUnicodeDataUtils.py +++ b/utils/GYBUnicodeDataUtils.py @@ -339,7 +339,7 @@ def verify(self, unicode_property): for cp in range(0, 0x110000): expected_value = unicode_property.get_value(cp) actual_value = self.get_value(cp) - assert(expected_value == actual_value) + assert expected_value == actual_value def freeze(self): """Compress internal trie representation. @@ -405,12 +405,12 @@ def map_index(idx): def _int_to_le_bytes(self, data, width): if width == 1: - assert(data & ~0xff == 0) + assert data & ~0xff == 0 return [data] if width == 2: - assert(data & ~0xffff == 0) + assert data & ~0xffff == 0 return [data & 0xff, data & 0xff00] - assert(False) + assert False def _int_list_to_le_bytes(self, ints, width): return [ @@ -512,7 +512,7 @@ def get_extended_grapheme_cluster_rules_matrix(grapheme_cluster_break_table): rules_matrix[first][second] = action # Make sure we can pack one row of the matrix into a 'uint16_t'. - assert(len(any_value) <= 16) + assert len(any_value) <= 16 result = [] for first in any_value: @@ -572,9 +572,9 @@ def _convert_line(line): return (test, boundaries) # Self-test. - assert(_convert_line(u'÷ 0903 × 0308 ÷ AC01 ÷ # abc') == ( - '\\xe0\\xa4\\x83\\xcc\\x88\\xea\\xb0\\x81', [0, 5, 8])) - assert(_convert_line(u'÷ D800 ÷ # abc') == ('\\xe2\\x80\\x8b', [0, 3])) + assert (_convert_line(u'÷ 0903 × 0308 ÷ AC01 ÷ # abc') == + ('\\xe0\\xa4\\x83\\xcc\\x88\\xea\\xb0\\x81', [0, 5, 8])) + assert _convert_line(u'÷ D800 ÷ # abc') == ('\\xe2\\x80\\x8b', [0, 3]) result = [] @@ -627,9 +627,9 @@ def _convert_line(line): return (test, boundaries) # Self-test. - assert(_convert_line('÷ 0903 × 0308 ÷ AC01 ÷ # abc') == ([ - 0x0903, 0x0308, 0xac01], [0, 2, 3])) - assert(_convert_line('÷ D800 ÷ # abc') == ([0x200b], [0, 1])) + assert (_convert_line('÷ 0903 × 0308 ÷ AC01 ÷ # abc') == + ([0x0903, 0x0308, 0xac01], [0, 2, 3])) + assert _convert_line('÷ D800 ÷ # abc') == ([0x200b], [0, 1]) result = [] diff --git a/utils/backtrace-check b/utils/backtrace-check index 350992b4374a7..aa60eba7aec99 100755 --- a/utils/backtrace-check +++ b/utils/backtrace-check @@ -75,7 +75,7 @@ def main(): # First see if we found the start of our stack trace start. If so, set # the found stack trace flag and continue. if line == 'Current stack trace:': - assert(not found_stack_trace_start) + assert not found_stack_trace_start found_stack_trace_start = True continue @@ -97,11 +97,11 @@ def main(): # Check for unavailable symbols, if that was requested. if args.check_unavailable: - assert('unavailable' not in matches.group('routine')) + assert 'unavailable' not in matches.group('routine') # Once we have processed all of the lines, make sure that we found at least # one stack trace entry. - assert(found_stack_trace_entry) + assert found_stack_trace_entry if __name__ == '__main__': diff --git a/utils/bug_reducer/bug_reducer/list_reducer.py b/utils/bug_reducer/bug_reducer/list_reducer.py index 6940e0a566b65..d7de360c54cb5 100644 --- a/utils/bug_reducer/bug_reducer/list_reducer.py +++ b/utils/bug_reducer/bug_reducer/list_reducer.py @@ -92,7 +92,7 @@ def _test_prefix_suffix(self, mid, prefix, suffix): self._reset_progress() return False - assert(result == TESTRESULT_NOFAILURE) + assert result == TESTRESULT_NOFAILURE # The property does not hold. Some of the elements we removed must # be necessary to maintain the property. self.mid_top = mid @@ -165,7 +165,7 @@ def _trim_try_backjump_and_trim_suffix(self): def reduce_list(self): random.seed(0x6e5ea738) # Seed the random number generator (result, self.target_list, kept) = self.run_test(self.target_list, []) - assert(result in TESTRESULTS) + assert result in TESTRESULTS (should_continue, result) = self._should_continue(result) if not should_continue: return result diff --git a/utils/bug_reducer/bug_reducer/swift_tools.py b/utils/bug_reducer/bug_reducer/swift_tools.py index 38497ace952aa..c52a2b9267591 100644 --- a/utils/bug_reducer/bug_reducer/swift_tools.py +++ b/utils/bug_reducer/bug_reducer/swift_tools.py @@ -157,8 +157,8 @@ def tool(self): return self.tools.sil_opt def _cmdline(self, input_file, passes, emit_sib, output_file='-'): - assert(isinstance(emit_sib, bool)) - assert(isinstance(output_file, str)) + assert isinstance(emit_sib, bool) + assert isinstance(output_file, str) base_args = self.base_args(emit_sib) sanity_check_file_exists(input_file) base_args.extend([input_file, '-o', output_file]) @@ -189,12 +189,12 @@ def tool(self): def _cmdline(self, input_file, funclist_path, emit_sib, output_file='-', invert=False): - assert(isinstance(emit_sib, bool)) - assert(isinstance(output_file, str)) + assert isinstance(emit_sib, bool) + assert isinstance(output_file, str) sanity_check_file_exists(input_file) sanity_check_file_exists(funclist_path) - assert(isinstance(funclist_path, str)) + assert isinstance(funclist_path, str) base_args = self.base_args(emit_sib) base_args.extend([input_file, '-o', output_file, '-func-file=%s' % funclist_path]) @@ -204,7 +204,7 @@ def _cmdline(self, input_file, funclist_path, emit_sib, output_file='-', def _invoke(self, input_file, funclist_path, output_filename, invert=False): - assert(isinstance(funclist_path, str)) + assert isinstance(funclist_path, str) cmdline = self._cmdline(input_file, funclist_path, True, @@ -214,7 +214,7 @@ def _invoke(self, input_file, funclist_path, output_filename, def invoke_with_functions(self, funclist_path, output_filename, invert=False): - assert(isinstance(funclist_path, str)) + assert isinstance(funclist_path, str) return self._invoke(self.input_file, funclist_path, output_filename, invert) @@ -236,5 +236,5 @@ def get_symbols(self, input_file): output = subprocess.check_output(cmdline) for line in output.split("\n")[:-1]: t = tuple(line.split(" ")) - assert(len(t) == 2) + assert len(t) == 2 yield t diff --git a/utils/build_swift/tests/build_swift/test_cache_utils.py b/utils/build_swift/tests/build_swift/test_cache_utils.py index 38a9391fe74e0..6230db2404603 100644 --- a/utils/build_swift/tests/build_swift/test_cache_utils.py +++ b/utils/build_swift/tests/build_swift/test_cache_utils.py @@ -47,7 +47,7 @@ def test_replaced_with_functools_lru_cache_python_3_2(self): def func(): return None - assert(mock_lru_cache.called) + assert mock_lru_cache.called def test_call_with_no_args(self): # Increments the counter once per unique call. diff --git a/utils/build_swift/tests/build_swift/test_shell.py b/utils/build_swift/tests/build_swift/test_shell.py index b179127e9b248..d2bd3d2160a39 100644 --- a/utils/build_swift/tests/build_swift/test_shell.py +++ b/utils/build_swift/tests/build_swift/test_shell.py @@ -115,7 +115,7 @@ def test_echo_command(self): mock_stream.write.assert_called_with( '>>> {}\n'.format(shell.quote(test_command))) - assert(mock_stream.flush.called) + assert mock_stream.flush.called @utils.requires_module('unittest.mock') def test_echo_command_custom_prefix(self): @@ -124,7 +124,7 @@ def test_echo_command_custom_prefix(self): shell._echo_command('ls', mock_stream, prefix='$ ') mock_stream.write.assert_called_with('$ ls\n') - assert(mock_stream.flush.called) + assert mock_stream.flush.called # ------------------------------------------------------------------------- # _normalize_args diff --git a/utils/dev-scripts/scurve_printer.py b/utils/dev-scripts/scurve_printer.py index 1a77477dc591f..e302ba5beccbb 100755 --- a/utils/dev-scripts/scurve_printer.py +++ b/utils/dev-scripts/scurve_printer.py @@ -73,7 +73,7 @@ def main(): ax.set_xlim(0.0, 1.0) y_min = args.y_axis_min or 1.0 - y_limit y_max = args.y_axis_max or 1.0 + y_limit - assert(y_min <= y_max) + assert y_min <= y_max ax.set_ylim(y_min, y_max) ax.grid(True) ax.xaxis.set_ticks(np.arange(0.0, 1.0, 0.05)) diff --git a/utils/gyb_syntax_support/Node.py b/utils/gyb_syntax_support/Node.py index 3192e422d7f0f..f9531374c859c 100644 --- a/utils/gyb_syntax_support/Node.py +++ b/utils/gyb_syntax_support/Node.py @@ -59,7 +59,7 @@ def __init__(self, name, description=None, kind=None, traits=None, self.omit_when_empty = omit_when_empty self.collection_element = element or "" # For SyntaxCollections make sure that the element_name is set. - assert(not self.is_syntax_collection() or element_name or element) + assert not self.is_syntax_collection() or element_name or element # If there's a preferred name for the collection element that differs # from its supertype, use that. self.collection_element_name = element_name or self.collection_element diff --git a/utils/jobstats/jobstats.py b/utils/jobstats/jobstats.py index 4acce6874ea7f..d52f06ffb0131 100644 --- a/utils/jobstats/jobstats.py +++ b/utils/jobstats/jobstats.py @@ -66,17 +66,17 @@ def __init__(self, jobkind, jobid, module, start_usec, dur_usec, def driver_jobs_ran(self): """Return the count of a driver job's ran sub-jobs""" - assert(self.is_driver_job()) + assert self.is_driver_job() return self.stats.get("Driver.NumDriverJobsRun", 0) def driver_jobs_skipped(self): """Return the count of a driver job's skipped sub-jobs""" - assert(self.is_driver_job()) + assert self.is_driver_job() return self.stats.get("Driver.NumDriverJobsSkipped", 0) def driver_jobs_total(self): """Return the total count of a driver job's ran + skipped sub-jobs""" - assert(self.is_driver_job()) + assert self.is_driver_job() return self.driver_jobs_ran() + self.driver_jobs_skipped() def merged_with(self, other, merge_by="sum"): @@ -126,7 +126,7 @@ def divided_by(self, n): def incrementality_percentage(self): """Assuming the job is a driver job, return the amount of jobs that actually ran, as a percentage of the total number.""" - assert(self.is_driver_job()) + assert self.is_driver_job() ran = self.driver_jobs_ran() total = self.driver_jobs_total() return round((float(ran) / float(total)) * 100.0, 2) diff --git a/utils/line-directive b/utils/line-directive index 7642fe3f6e3ed..e55e677197343 100755 --- a/utils/line-directive +++ b/utils/line-directive @@ -134,7 +134,7 @@ def map_line_to_source_file(target_filename, target_line_num): >>> t.close() >>> os.remove(t.name) """ - assert(target_line_num > 0) + assert target_line_num > 0 map = fline_map(target_filename) index = bisect.bisect_left(map, (target_line_num, '', 0)) base = map[index - 1] @@ -191,7 +191,7 @@ def map_line_from_source_file(source_filename, source_line_num, >>> t.close() >>> os.remove(t.name) """ - assert(source_line_num > 0) + assert source_line_num > 0 map = fline_map(target_filename) for i, (target_line_num, found_source_filename, diff --git a/utils/process-stats-dir.py b/utils/process-stats-dir.py index 8180310d912e0..2c023c76ac859 100755 --- a/utils/process-stats-dir.py +++ b/utils/process-stats-dir.py @@ -77,7 +77,7 @@ def vars_of_args(args): # of each of "old" and "new", and the stats are those found in the respective # dirs. def load_paired_stats_dirs(args): - assert(len(args.remainder) == 2) + assert len(args.remainder) == 2 paired_stats = [] (old, new) = args.remainder vargs = vars_of_args(args) diff --git a/utils/scale-test b/utils/scale-test index a48d745705e84..61759f0505a01 100755 --- a/utils/scale-test +++ b/utils/scale-test @@ -274,7 +274,7 @@ def converged(ctr, simplex, epsilon): def Nelder_Mead_simplex(objective, params, bounds, epsilon=1.0e-6): # By the book: https://en.wikipedia.org/wiki/Nelder%E2%80%93Mead_method ndim = len(params) - assert(ndim >= 2) + assert ndim >= 2 def named(tup): return params.__new__(params.__class__, *tup) @@ -332,7 +332,7 @@ def Nelder_Mead_simplex(objective, params, bounds, epsilon=1.0e-6): continue # 5. Contraction - assert(vr >= simplex[-2].val) + assert vr >= simplex[-2].val xc = tup_add(x0, tup_mul(rho, tup_sub(xw, x0))) vc = f(xc) if vc < vw: @@ -362,7 +362,7 @@ def Nelder_Mead_simplex(objective, params, bounds, epsilon=1.0e-6): # perfectly") and finally returns (fit_params, r_squared). def fit_function_to_data_by_least_squares(objective, params, bounds, xs, ys): - assert(len(ys) > 0) + assert len(ys) > 0 mean_y = sum(ys) / len(ys) ss_total = sum((y - mean_y) ** 2 for y in ys) data = list(zip(xs, ys)) diff --git a/utils/swift_build_support/swift_build_support/build_graph.py b/utils/swift_build_support/swift_build_support/build_graph.py index 70f2ecccb739a..4814d078d1883 100644 --- a/utils/swift_build_support/swift_build_support/build_graph.py +++ b/utils/swift_build_support/swift_build_support/build_graph.py @@ -52,7 +52,7 @@ def _get_po_ordered_nodes(root, invertedDepMap): # Then grab the dependents of our node. deps = invertedDepMap.get(node, set([])) - assert(isinstance(deps, set)) + assert isinstance(deps, set) # Then visit those and see if we have not visited any of them. Push # any such nodes onto the worklist and continue. If we have already @@ -92,13 +92,13 @@ def add_edge(self, pred, succ): def set_root(self, root): # Assert that we always only have one root. - assert(self.root is None) + assert self.root is None self.root = root def produce_schedule(self): # Grab the root and make sure it is not None root = self.root - assert(root is not None) + assert root is not None # Then perform a post order traversal from root using our inverted # dependency map to compute a list of our nodes in post order. diff --git a/utils/swift_build_support/swift_build_support/build_script_invocation.py b/utils/swift_build_support/swift_build_support/build_script_invocation.py index 7f4f0232b3605..e1a877a25efb5 100644 --- a/utils/swift_build_support/swift_build_support/build_script_invocation.py +++ b/utils/swift_build_support/swift_build_support/build_script_invocation.py @@ -692,7 +692,7 @@ def execute(self): if is_impl: self._execute_impl(pipeline, all_hosts, perform_epilogue_opts) else: - assert(index != last_impl_index) + assert index != last_impl_index if index > last_impl_index: non_darwin_cross_compile_hostnames = [ target for target in self.args.cross_compile_hosts if not diff --git a/utils/swift_build_support/swift_build_support/compiler_stage.py b/utils/swift_build_support/swift_build_support/compiler_stage.py index e2b3189f7101a..e116f92c8499f 100644 --- a/utils/swift_build_support/swift_build_support/compiler_stage.py +++ b/utils/swift_build_support/swift_build_support/compiler_stage.py @@ -16,7 +16,7 @@ def __init__(self, stage, args): self.__dict__['postfix'] = stage.postfix self.__dict__['stage'] = stage self.__dict__['args'] = args - assert(not isinstance(self.args, StageArgs)) + assert not isinstance(self.args, StageArgs) def _get_stage_prefix(self): return self.__dict__['postfix'] diff --git a/utils/swift_build_support/swift_build_support/productpipeline_list_builder.py b/utils/swift_build_support/swift_build_support/productpipeline_list_builder.py index a6588259eef92..09c16611090ef 100644 --- a/utils/swift_build_support/swift_build_support/productpipeline_list_builder.py +++ b/utils/swift_build_support/swift_build_support/productpipeline_list_builder.py @@ -24,7 +24,7 @@ class ProductPipeline(object): This class is meant to just be state. """ def __init__(self, should_run_epilogue_operations, identity, is_impl): - assert(isinstance(identity, int)) + assert isinstance(identity, int) self.identity = identity self.products = [] self.is_impl = is_impl @@ -95,16 +95,16 @@ def reset(self): def add_product(self, product_cls, is_enabled): """Add a non-impl product to the current pipeline begin constructed""" - assert(self.current_pipeline is not None) - assert(not self.is_current_pipeline_impl) - assert(not product_cls.is_build_script_impl_product()) + assert self.current_pipeline is not None + assert not self.is_current_pipeline_impl + assert not product_cls.is_build_script_impl_product() self.current_pipeline.append(product_cls, is_enabled) def add_impl_product(self, product_cls, is_enabled): """Add a non-impl product to the current pipeline begin constructed""" - assert(self.current_pipeline is not None) - assert(self.is_current_pipeline_impl) - assert(product_cls.is_build_script_impl_product()) + assert self.current_pipeline is not None + assert self.is_current_pipeline_impl + assert product_cls.is_build_script_impl_product() self.current_pipeline.append(product_cls, is_enabled) def infer(self): @@ -120,7 +120,7 @@ def infer(self): for pipeline_i in range(len(pipeline)): (p, is_enabled) = pipeline[pipeline_i] # Make sure p has not been added multiple times to the builder. - assert(p not in products_to_generation_index) + assert p not in products_to_generation_index products_to_generation_index[p] = (i, pipeline_i) if is_enabled: final_pipeline.append(p) @@ -133,8 +133,8 @@ def infer(self): # our product are from our generation or earlier. If we find such a # dependency error. for (p, is_enabled) in pipeline: - assert(all(d in products_to_generation_index for d in - p.get_dependencies())) + assert (all(d in products_to_generation_index for d in + p.get_dependencies())) for i in range(len(inferred_pipeline_list)): pipeline = inferred_pipeline_list[i] @@ -166,7 +166,7 @@ def infer(self): (gen_offset, index) = products_to_generation_index[p] # If we are from an earlier generation, our position in the # inferred pipeline list may be None. Initialize it now. - assert(gen_offset <= i) + assert gen_offset <= i inferred_pipeline_list[gen_offset][index] = p filtered_results = [] diff --git a/utils/swift_build_support/swift_build_support/shell.py b/utils/swift_build_support/swift_build_support/shell.py index 222d540dd2c95..024c45ea6a431 100644 --- a/utils/swift_build_support/swift_build_support/shell.py +++ b/utils/swift_build_support/swift_build_support/shell.py @@ -213,7 +213,7 @@ def run(*args, **kwargs): prefix = kwargs.pop('prefix', '') if dry_run: _echo_command(dry_run, *args, env=env, prompt="{0}+ ".format(prefix)) - return(None, 0, args) + return (None, 0, args) my_pipe = subprocess.Popen( *args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, From 4e61c087964b5d6a8cd1235cc9d8281522b16df5 Mon Sep 17 00:00:00 2001 From: stevapple Date: Sun, 21 Aug 2022 15:16:02 +0800 Subject: [PATCH 241/491] [build-windows] Fix typo --- utils/build-windows.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build-windows.bat b/utils/build-windows.bat index f7f8b76804ff7..d8a1b789c9db9 100644 --- a/utils/build-windows.bat +++ b/utils/build-windows.bat @@ -105,7 +105,7 @@ setlocal enableextensions enabledelayedexpansion if defined REPO_SCHEME SET "scheme_arg=--scheme %REPO_SCHEME%" git -C "%source_root%\swift" config --local core.autocrlf input -git -C "%source_root%\swift" config --local core.symlink true +git -C "%source_root%\swift" config --local core.symlinks true git -C "%source_root%\swift" checkout-index --force --all :: Always skip Swift, since it is checked out by Jenkins From 16653c51827a76683c60071584ea599b5a5d9281 Mon Sep 17 00:00:00 2001 From: stevapple Date: Sun, 21 Aug 2022 15:23:28 +0800 Subject: [PATCH 242/491] [build-windows] Update dependency version ... to keep in sync with `build-windows-toolchain` and CI environment. --- utils/build-windows.bat | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/build-windows.bat b/utils/build-windows.bat index d8a1b789c9db9..d2acfd0f76f32 100644 --- a/utils/build-windows.bat +++ b/utils/build-windows.bat @@ -28,8 +28,8 @@ setlocal enableextensions enabledelayedexpansion PATH=%PATH%;%PYTHON_HOME% -set icu_version_major=64 -set icu_version_minor=2 +set icu_version_major=69 +set icu_version_minor=1 set icu_version=%icu_version_major%_%icu_version_minor% set icu_version_dashed=%icu_version_major%-%icu_version_minor% @@ -138,7 +138,7 @@ endlocal :: Downloads ICU, which will be used as a dependency for Foundation. setlocal enableextensions enabledelayedexpansion -set file_name=icu4c-%icu_version%-Win64-MSVC2017.zip +set file_name=icu4c-%icu_version%-Win64-MSVC2019.zip curl -L -O "https://github.com/unicode-org/icu/releases/download/release-%icu_version_dashed%/%file_name%" %exitOnError% :: unzip warns about the paths in the zip using slashes, which raises the :: errorLevel to 1. We cannot use exitOnError, and have to ignore errors. @@ -154,8 +154,8 @@ endlocal :: Swift Package Manager. setlocal enableextensions enabledelayedexpansion -set file_name=sqlite-amalgamation-3270200.zip -curl -L -O "https://www.sqlite.org/2019/%file_name%" %exitOnError% +set file_name=sqlite-amalgamation-3360000.zip +curl -L -O "https://www.sqlite.org/2021/%file_name%" %exitOnError% "%SystemDrive%\Program Files\Git\usr\bin\unzip.exe" -o %file_name% %exitOnError% goto :eof From 3e520075624db604ee6e0e678986e52fc9e42932 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 19 Aug 2022 14:38:20 -0700 Subject: [PATCH 243/491] [builtin] Remove "unsafeGuaranteed" and related code since Unmanaged now has an Ownership SSA based implementation that works completely in SILGen. This isn't used in the stdlib anymore as well. --- docs/SIL.rst | 30 - include/swift/AST/Builtins.def | 6 - .../swift/SILOptimizer/Analysis/ARCAnalysis.h | 29 - .../swift/SILOptimizer/PassManager/Passes.def | 2 - lib/AST/Builtins.cpp | 6 - lib/IRGen/GenBuiltin.cpp | 16 - lib/SIL/IR/OperandOwnership.cpp | 2 - lib/SIL/IR/ValueOwnership.cpp | 2 - lib/SIL/Utils/MemAccessUtils.cpp | 2 - lib/SILOptimizer/Analysis/ARCAnalysis.cpp | 124 ---- lib/SILOptimizer/PassManager/PassPipeline.cpp | 2 - .../AccessEnforcementReleaseSinking.cpp | 2 - lib/SILOptimizer/Transforms/CMakeLists.txt | 3 +- .../Transforms/SpeculativeDevirtualizer.cpp | 11 - .../Transforms/UnsafeGuaranteedPeephole.cpp | 249 ------- lib/Serialization/ModuleFormat.h | 2 +- test/IRGen/builtins.swift | 31 - test/SIL/OwnershipVerifier/use_verifier.sil | 12 - test/SILGen/builtins.swift | 52 -- test/SILGen/guaranteed_normal_args.swift | 12 - test/SILOptimizer/devirt_speculative.sil | 18 - .../unsafe_guaranteed_peephole.sil | 626 ------------------ 22 files changed, 2 insertions(+), 1237 deletions(-) delete mode 100644 lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp delete mode 100644 test/SILOptimizer/unsafe_guaranteed_peephole.sil diff --git a/docs/SIL.rst b/docs/SIL.rst index b4e374423aecd..be2df9cd805e6 100644 --- a/docs/SIL.rst +++ b/docs/SIL.rst @@ -4862,36 +4862,6 @@ into a ``copy_block`` and a ``is_escaping``/``cond_fail``/``destroy_value`` at the end of the lifetime of the objective c closure parameter to check whether the sentinel closure was escaped. -builtin "unsafeGuaranteed" -`````````````````````````` - -:: - - sil-instruction := 'builtin' '"unsafeGuaranteed"' '<' sil-type '>' '(' sil-operand')' ':' sil-type - - %1 = builtin "unsafeGuaranteed"(%0 : $T) : ($T, Builtin.Int1) - // $T must be of AnyObject type. - -Asserts that there exists another reference of the value ``%0`` for the scope -delineated by the call of this builtin up to the first call of a ``builtin -"unsafeGuaranteedEnd"`` instruction that uses the second element ``%1.1`` of the -returned value. If no such instruction can be found nothing can be assumed. This -assertion holds for uses of the first tuple element of the returned value -``%1.0`` within this scope. The returned reference value equals the input -``%0``. - -builtin "unsafeGuaranteedEnd" -````````````````````````````` - -:: - - sil-instruction := 'builtin' '"unsafeGuaranteedEnd"' '(' sil-operand')' - - %1 = builtin "unsafeGuaranteedEnd"(%0 : $Builtin.Int1) - // $T must be of AnyObject type. - -Ends the scope for the ``builtin "unsafeGuaranteed"`` instruction. - Literals ~~~~~~~~ diff --git a/include/swift/AST/Builtins.def b/include/swift/AST/Builtins.def index 2afd34ad13bb2..cae81e6cd0168 100644 --- a/include/swift/AST/Builtins.def +++ b/include/swift/AST/Builtins.def @@ -723,12 +723,6 @@ BUILTIN_MISC_OPERATION(AssignTakeArray, "assignTakeArray", "", Special) /// This builtin indicates to the optimizer that the buffer is not mutable. BUILTIN_MISC_OPERATION(COWBufferForReading, "COWBufferForReading", "n", Special) -// unsafeGuaranteed has type T -> (T, Builtin.Int8) -BUILTIN_MISC_OPERATION(UnsafeGuaranteed, "unsafeGuaranteed", "", Special) - -// unsafeGuaranteedEnd has type (Builtin.Int8) -> () -BUILTIN_MISC_OPERATION(UnsafeGuaranteedEnd, "unsafeGuaranteedEnd", "", Special) - // getObjCTypeEncoding has type T.Type -> RawPointer BUILTIN_MISC_OPERATION(GetObjCTypeEncoding, "getObjCTypeEncoding", "n", Special) diff --git a/include/swift/SILOptimizer/Analysis/ARCAnalysis.h b/include/swift/SILOptimizer/Analysis/ARCAnalysis.h index 393e74efedd77..4e996e4160e07 100644 --- a/include/swift/SILOptimizer/Analysis/ARCAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/ARCAnalysis.h @@ -392,35 +392,6 @@ class ConsumedArgToEpilogueReleaseMatcher { /// Match a call to a trap BB with no ARC relevant side effects. bool isARCInertTrapBB(const SILBasicBlock *BB); -/// Get the two result values of the builtin "unsafeGuaranteed" instruction. -/// -/// Gets the (GuaranteedValue, Token) tuple from a call to "unsafeGuaranteed" -/// if the tuple elements are identified by a single tuple_extract use. -/// Otherwise, returns a (nullptr, nullptr) tuple. -std::pair -getSingleUnsafeGuaranteedValueResult(BuiltinInst *UnsafeGuaranteedInst); - -/// Get the single builtin "unsafeGuaranteedEnd" user of a builtin -/// "unsafeGuaranteed"'s token. -BuiltinInst *getUnsafeGuaranteedEndUser(SILValue UnsafeGuaranteedToken); - -/// Walk forwards from an unsafeGuaranteedEnd builtin instruction looking for a -/// release on the reference returned by the matching unsafeGuaranteed builtin -/// ignoring releases on the way. -/// Return nullptr if no release is found. -/// -/// %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) -/// %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 -/// %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 -/// %12 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() -/// strong_release %5 : $Foo // <-- Matching release. -/// -/// Alternatively, look for the release before the unsafeGuaranteedEnd. -SILInstruction *findReleaseToMatchUnsafeGuaranteedValue( - SILInstruction *UnsafeGuaranteedEndI, SILInstruction *UnsafeGuaranteedI, - SILValue UnsafeGuaranteedValue, SILBasicBlock &BB, - RCIdentityFunctionInfo &RCFI); - } // end namespace swift #endif diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def index 160ab2adcad38..d188bc7258605 100644 --- a/include/swift/SILOptimizer/PassManager/Passes.def +++ b/include/swift/SILOptimizer/PassManager/Passes.def @@ -410,8 +410,6 @@ PASS(StringOptimization, "string-optimization", "Optimization for String operations") PASS(SwiftArrayPropertyOpt, "array-property-opt", "Loop Specialization for Array Properties") -PASS(UnsafeGuaranteedPeephole, "unsafe-guaranteed-peephole", - "SIL retain/release Peephole Removal for Builtin.unsafeGuaranteed") PASS(UsePrespecialized, "use-prespecialized", "Use Pre-Specialized Functions") PASS(OwnershipDumper, "ownership-dumper", diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index f17ae736c4de2..4e042fd73993a 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -2804,12 +2804,6 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) { case BuiltinValueKind::COWBufferForReading: return getCOWBufferForReading(Context, Id); - case BuiltinValueKind::UnsafeGuaranteed: - return getUnsafeGuaranteed(Context, Id); - - case BuiltinValueKind::UnsafeGuaranteedEnd: - return getUnsafeGuaranteedEnd(Context, Id); - case BuiltinValueKind::ApplyDerivative: case BuiltinValueKind::ApplyTranspose: llvm_unreachable("Handled above"); diff --git a/lib/IRGen/GenBuiltin.cpp b/lib/IRGen/GenBuiltin.cpp index 6ef1d93af2a3a..13f8a73dc2482 100644 --- a/lib/IRGen/GenBuiltin.cpp +++ b/lib/IRGen/GenBuiltin.cpp @@ -135,22 +135,6 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin, return; } - if (Builtin.ID == BuiltinValueKind::UnsafeGuaranteedEnd) { - // Just consume the incoming argument. - assert(args.size() == 1 && "Expecting one incoming argument"); - (void)args.claimAll(); - return; - } - - if (Builtin.ID == BuiltinValueKind::UnsafeGuaranteed) { - // Just forward the incoming argument. - assert(args.size() == 1 && "Expecting one incoming argument"); - out = std::move(args); - // This is a token. - out.add(llvm::ConstantInt::get(IGF.IGM.Int8Ty, 0)); - return; - } - if (Builtin.ID == BuiltinValueKind::OnFastPath) { // The onFastPath builtin has only an effect on SIL level, so we lower it // to a no-op. diff --git a/lib/SIL/IR/OperandOwnership.cpp b/lib/SIL/IR/OperandOwnership.cpp index 69f3836cb2c69..76954d8818246 100644 --- a/lib/SIL/IR/OperandOwnership.cpp +++ b/lib/SIL/IR/OperandOwnership.cpp @@ -784,7 +784,6 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, USubOver) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, UToSCheckedTrunc) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, UToUCheckedTrunc) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Unreachable) -BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, UnsafeGuaranteedEnd) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Xor) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GenericXor) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, ZExt) @@ -806,7 +805,6 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, CreateTaskGroup) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, DestroyTaskGroup) BUILTIN_OPERAND_OWNERSHIP(ForwardingConsume, COWBufferForReading) -BUILTIN_OPERAND_OWNERSHIP(ForwardingConsume, UnsafeGuaranteed) const int PARAMETER_INDEX_CREATE_ASYNC_TASK_FUTURE_FUNCTION = 2; const int PARAMETER_INDEX_CREATE_ASYNC_TASK_GROUP_FUTURE_FUNCTION = 3; diff --git a/lib/SIL/IR/ValueOwnership.cpp b/lib/SIL/IR/ValueOwnership.cpp index 8bc793c7725ee..a86d99e0c6e28 100644 --- a/lib/SIL/IR/ValueOwnership.cpp +++ b/lib/SIL/IR/ValueOwnership.cpp @@ -386,7 +386,6 @@ struct ValueOwnershipKindBuiltinVisitor // This returns a value at +1 that is destroyed strictly /after/ the // UnsafeGuaranteedEnd. This provides the guarantee that we want. CONSTANT_OWNERSHIP_BUILTIN(Owned, COWBufferForReading) -CONSTANT_OWNERSHIP_BUILTIN(Owned, UnsafeGuaranteed) CONSTANT_OWNERSHIP_BUILTIN(None, AShr) CONSTANT_OWNERSHIP_BUILTIN(None, GenericAShr) CONSTANT_OWNERSHIP_BUILTIN(None, Add) @@ -507,7 +506,6 @@ CONSTANT_OWNERSHIP_BUILTIN(None, Unreachable) CONSTANT_OWNERSHIP_BUILTIN(None, AtomicRMW) CONSTANT_OWNERSHIP_BUILTIN(None, CondUnreachable) -CONSTANT_OWNERSHIP_BUILTIN(None, UnsafeGuaranteedEnd) CONSTANT_OWNERSHIP_BUILTIN(None, GetObjCTypeEncoding) CONSTANT_OWNERSHIP_BUILTIN(None, CanBeObjCClass) CONSTANT_OWNERSHIP_BUILTIN(None, WillThrow) diff --git a/lib/SIL/Utils/MemAccessUtils.cpp b/lib/SIL/Utils/MemAccessUtils.cpp index 017a314ec1904..b67e8b281b78c 100644 --- a/lib/SIL/Utils/MemAccessUtils.cpp +++ b/lib/SIL/Utils/MemAccessUtils.cpp @@ -2484,8 +2484,6 @@ static void visitBuiltinAddress(BuiltinInst *builtin, case BuiltinValueKind::Unreachable: case BuiltinValueKind::CondUnreachable: case BuiltinValueKind::DestroyArray: - case BuiltinValueKind::UnsafeGuaranteed: - case BuiltinValueKind::UnsafeGuaranteedEnd: case BuiltinValueKind::Swift3ImplicitObjCEntrypoint: case BuiltinValueKind::PoundAssert: case BuiltinValueKind::IntInstrprofIncrement: diff --git a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp index 83d9c3fabde95..6b155c721996d 100644 --- a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp @@ -1059,127 +1059,3 @@ bool swift::isARCInertTrapBB(const SILBasicBlock *BB) { // ARC perspective in an unreachable BB. return true; } - -//===----------------------------------------------------------------------===// -// Analysis of builtin "unsafeGuaranteed" instructions -//===----------------------------------------------------------------------===// -std::pair -swift::getSingleUnsafeGuaranteedValueResult(BuiltinInst *BI) { - assert(BI->getBuiltinKind() && - *BI->getBuiltinKind() == BuiltinValueKind::UnsafeGuaranteed && - "Expecting a unsafeGuaranteed builtin"); - - SingleValueInstruction *GuaranteedValue = nullptr; - SingleValueInstruction *Token = nullptr; - - auto Failed = std::make_pair(nullptr, nullptr); - - for (auto *Operand : getNonDebugUses(BI)) { - auto *Usr = Operand->getUser(); - if (isa(Usr) || isa(Usr)) - continue; - - auto *TE = dyn_cast(Usr); - if (!TE || TE->getOperand() != BI) - return Failed; - - if (TE->getFieldIndex() == 0 && !GuaranteedValue) { - GuaranteedValue = TE; - continue; - } - if (TE->getFieldIndex() == 1 && !Token) { - Token = TE; - continue; - } - return Failed; - } - - if (!GuaranteedValue || !Token) - return Failed; - - return std::make_pair(GuaranteedValue, Token); -} - -BuiltinInst *swift::getUnsafeGuaranteedEndUser(SILValue UnsafeGuaranteedToken) { - BuiltinInst *UnsafeGuaranteedEndI = nullptr; - - for (auto *Operand : getNonDebugUses(UnsafeGuaranteedToken)) { - if (UnsafeGuaranteedEndI) { - LLVM_DEBUG(llvm::dbgs() << " multiple unsafeGuaranteedEnd users\n"); - UnsafeGuaranteedEndI = nullptr; - break; - } - auto *BI = dyn_cast(Operand->getUser()); - if (!BI || !BI->getBuiltinKind() || - *BI->getBuiltinKind() != BuiltinValueKind::UnsafeGuaranteedEnd) { - LLVM_DEBUG(llvm::dbgs() << " wrong unsafeGuaranteed token user " - << *Operand->getUser()); - break; - } - - UnsafeGuaranteedEndI = BI; - } - return UnsafeGuaranteedEndI; -} - -static bool hasUnsafeGuaranteedOperand(SILValue UnsafeGuaranteedValue, - SILValue UnsafeGuaranteedValueOperand, - RCIdentityFunctionInfo &RCII, - SILInstruction &Release) { - assert(isa(Release) || - isa(Release) && "Expecting a release"); - - auto RCRoot = RCII.getRCIdentityRoot(Release.getOperand(0)); - - return RCRoot == UnsafeGuaranteedValue || - RCRoot == UnsafeGuaranteedValueOperand; -} - -SILInstruction *swift::findReleaseToMatchUnsafeGuaranteedValue( - SILInstruction *UnsafeGuaranteedEndI, SILInstruction *UnsafeGuaranteedI, - SILValue UnsafeGuaranteedValue, SILBasicBlock &BB, - RCIdentityFunctionInfo &RCFI) { - - auto UnsafeGuaranteedRoot = RCFI.getRCIdentityRoot(UnsafeGuaranteedValue); - auto UnsafeGuaranteedOpdRoot = - RCFI.getRCIdentityRoot(UnsafeGuaranteedI->getOperand(0)); - - // Try finding it after the "unsafeGuaranteedEnd". - for (auto ForwardIt = std::next(UnsafeGuaranteedEndI->getIterator()), - End = BB.end(); - ForwardIt != End; ++ForwardIt) { - SILInstruction &CurInst = *ForwardIt; - - // Is this a release? - if (isa(CurInst) || isa(CurInst)) { - if (hasUnsafeGuaranteedOperand(UnsafeGuaranteedRoot, - UnsafeGuaranteedOpdRoot, RCFI, CurInst)) - return &CurInst; - continue; - } - - if (CurInst.mayHaveSideEffects() && !DebugValueInst::hasAddrVal(&CurInst)) - break; - } - - // Otherwise, Look before the "unsafeGuaranteedEnd". - for (auto ReverseIt = ++UnsafeGuaranteedEndI->getIterator().getReverse(), - End = BB.rend(); - ReverseIt != End; ++ReverseIt) { - SILInstruction &CurInst = *ReverseIt; - - // Is this a release? - if (isa(CurInst) || isa(CurInst)) { - if (hasUnsafeGuaranteedOperand(UnsafeGuaranteedRoot, - UnsafeGuaranteedOpdRoot, RCFI, CurInst)) - return &CurInst; - continue; - } - - if (CurInst.mayHaveSideEffects() && !DebugValueInst::hasAddrVal(&CurInst)) - break; - } - - return nullptr; -} - diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index 4fc850df776a8..18728e61fa1a1 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -525,8 +525,6 @@ void addFunctionPasses(SILPassPipelinePlan &P, P.addSimplifyCFG(); if (OpLevel == OptimizationLevelKind::LowLevel) { - // Remove retain/releases based on Builtin.unsafeGuaranteed - P.addUnsafeGuaranteedPeephole(); // Only hoist releases very late. P.addLateCodeMotion(); } else diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp index 053b8823c2bd4..c910a87ff4f1c 100644 --- a/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp +++ b/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp @@ -175,10 +175,8 @@ static bool isBarrier(SILInstruction *inst) { case BuiltinValueKind::AssignCopyArrayFrontToBack: case BuiltinValueKind::AssignCopyArrayBackToFront: case BuiltinValueKind::AssignTakeArray: - case BuiltinValueKind::UnsafeGuaranteed: case BuiltinValueKind::Move: case BuiltinValueKind::Copy: - case BuiltinValueKind::UnsafeGuaranteedEnd: case BuiltinValueKind::CancelAsyncTask: case BuiltinValueKind::StartAsyncLet: case BuiltinValueKind::CreateAsyncTask: diff --git a/lib/SILOptimizer/Transforms/CMakeLists.txt b/lib/SILOptimizer/Transforms/CMakeLists.txt index 404ab58a06ebd..4ac8f1389a320 100644 --- a/lib/SILOptimizer/Transforms/CMakeLists.txt +++ b/lib/SILOptimizer/Transforms/CMakeLists.txt @@ -42,5 +42,4 @@ target_sources(swiftSILOptimizer PRIVATE SpeculativeDevirtualizer.cpp StringOptimization.cpp TempLValueOpt.cpp - TempRValueElimination.cpp - UnsafeGuaranteedPeephole.cpp) + TempRValueElimination.cpp) diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp index da94880277ce1..5a14e2e240bba 100644 --- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp +++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp @@ -372,17 +372,6 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA, OptRemark::Emitter &ORE) { ClassMethodInst *CMI = cast(AI.getCallee()); - // Don't devirtualize withUnsafeGuaranteed 'self' as this would prevent - // retain/release removal. - // unmanged._withUnsafeGuaranteedRef { $0.method() } - if (auto *TupleExtract = dyn_cast(CMI->getOperand())) - if (auto *UnsafeGuaranteedSelf = - dyn_cast(TupleExtract->getOperand())) - if (UnsafeGuaranteedSelf->getBuiltinKind() == - BuiltinValueKind::UnsafeGuaranteed && - TupleExtract->getFieldIndex() == 0) - return false; - // Strip any upcasts off of our 'self' value, potentially leaving us // with a value whose type is closer (in the class hierarchy) to the // actual dynamic type. diff --git a/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp b/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp deleted file mode 100644 index 25a3e25af7d3e..0000000000000 --- a/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp +++ /dev/null @@ -1,249 +0,0 @@ -//===--- UnsafeGuaranteedPeephole.cpp - UnsafeGuaranteed Peephole ---------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 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 -// -//===----------------------------------------------------------------------===// -// -// Optimize retain/release pairs based on Builtin.unsafeGuaranteed -// -// strong_retain %0 : $Foo -// %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) -// %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 -// %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 -// %9 = function_ref @beep : $@convention(method) (@guaranteed Foo) -> () -// %10 = apply %9(%0) : $@convention(method) (@guaranteed Foo) -> () -// strong_release %5 : $Foo -// %12 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() -// -// Based on the assertion that there is another reference to "%0" that keeps -// "%0" alive for the scope between the two builtin calls we can remove the -// retain/release pair and the builtins. -// -// %9 = function_ref @beep : $@convention(method) (@guaranteed Foo) -> () -// %10 = apply %9(%0) : $@convention(method) (@guaranteed Foo) -> () -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "unsafe-guaranteed-peephole" -#include "swift/SIL/DebugUtils.h" -#include "swift/SIL/SILFunction.h" -#include "swift/SIL/SILInstruction.h" -#include "swift/SIL/SILModule.h" -#include "swift/SILOptimizer/Analysis/ARCAnalysis.h" -#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" -#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" -#include "swift/SILOptimizer/PassManager/Passes.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/InstOptUtils.h" - -using namespace swift; - -/// Pattern match and remove "retain(self), apply(self), release(self)" calls -/// inbetween unsafeGuaranteed pairs and remove the retain/release pairs. -static void tryRemoveRetainReleasePairsBetween( - RCIdentityFunctionInfo &RCFI, SILInstruction *UnsafeGuaranteedI, - SILInstruction *Retain, SILInstruction *Release, - SILInstruction *UnsafeGuaranteedEndI) { - auto *BB = UnsafeGuaranteedI->getParent(); - if (BB != UnsafeGuaranteedEndI->getParent() || BB != Retain->getParent() || - BB != Release->getParent()) - return; - - SILInstruction *CandidateRetain = nullptr; - SmallVector InstsToDelete; - - SILBasicBlock::iterator It(UnsafeGuaranteedI); - while (It != BB->end() && It != SILBasicBlock::iterator(Release) && - It != SILBasicBlock::iterator(UnsafeGuaranteedEndI)) { - auto *CurInst = &*It++; - if (CurInst != Retain && - (isa(CurInst) || isa(CurInst)) && - RCFI.getRCIdentityRoot(CurInst->getOperand(0)) - ->getDefiningInstruction() == UnsafeGuaranteedI) { - CandidateRetain = CurInst; - continue; - } - if (!CurInst->mayHaveSideEffects()) - continue; - - if (isa(CurInst)) - continue; - - if (isa(CurInst) || isa(CurInst)) - continue; - - if (CandidateRetain != nullptr && CurInst != Release && - (isa(CurInst) || isa(CurInst)) && - RCFI.getRCIdentityRoot(CurInst->getOperand(0)) - ->getDefiningInstruction() == UnsafeGuaranteedI) { - // Delete the retain/release pair. - InstsToDelete.push_back(CandidateRetain); - InstsToDelete.push_back(CurInst); - } - - // Otherwise, reset our scan. - CandidateRetain = nullptr; - } - for (auto *Inst: InstsToDelete) - Inst->eraseFromParent(); -} - -/// Remove retain/release pairs around builtin "unsafeGuaranteed" instruction -/// sequences. -static bool removeGuaranteedRetainReleasePairs(SILFunction &F, - RCIdentityFunctionInfo &RCIA, - PostDominanceAnalysis *PDA) { - LLVM_DEBUG(llvm::dbgs() << "Running on function " << F.getName() << "\n"); - bool Changed = false; - - // Lazily compute post-dominance info only when we really need it. - PostDominanceInfo *PDI = nullptr; - - for (auto &BB : F) { - auto It = BB.begin(), End = BB.end(); - llvm::DenseMap LastRetain; - while (It != End) { - auto *CurInst = &*It; - ++It; - - // Memorize the last retain. - if (isa(CurInst) || isa(CurInst)) { - LastRetain[RCIA.getRCIdentityRoot(CurInst->getOperand(0))] = CurInst; - continue; - } - - // Look for a builtin "unsafeGuaranteed" instruction. - auto *UnsafeGuaranteedI = dyn_cast(CurInst); - if (!UnsafeGuaranteedI || !UnsafeGuaranteedI->getBuiltinKind() || - *UnsafeGuaranteedI->getBuiltinKind() != - BuiltinValueKind::UnsafeGuaranteed) - continue; - - auto Opd = UnsafeGuaranteedI->getOperand(0); - auto RCIdOpd = RCIA.getRCIdentityRoot(UnsafeGuaranteedI->getOperand(0)); - if (!LastRetain.count(RCIdOpd)) { - LLVM_DEBUG(llvm::dbgs() << "LastRetain failed\n"); - continue; - } - - // This code is very conservative. Check that there is a matching retain - // before the unsafeGuaranteed builtin with only retains inbetween. - auto *LastRetainInst = LastRetain[RCIdOpd]; - auto NextInstIter = std::next(SILBasicBlock::iterator(LastRetainInst)); - while (NextInstIter != BB.end() && &*NextInstIter != CurInst && - (isa(*NextInstIter) || - isa(*NextInstIter) || - !NextInstIter->mayHaveSideEffects() || - isa(*NextInstIter))) - ++NextInstIter; - if (&*NextInstIter != CurInst) { - LLVM_DEBUG(llvm::dbgs() << "Last retain right before match failed\n"); - continue; - } - - LLVM_DEBUG(llvm::dbgs() << "Saw " << *UnsafeGuaranteedI); - LLVM_DEBUG(llvm::dbgs() << " with operand " << *Opd); - - // Match the reference and token result. - // %4 = builtin "unsafeGuaranteed"(%0 : $Foo) - // %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - // %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - SingleValueInstruction *UnsafeGuaranteedValue; - SingleValueInstruction *UnsafeGuaranteedToken; - std::tie(UnsafeGuaranteedValue, UnsafeGuaranteedToken) = - getSingleUnsafeGuaranteedValueResult(UnsafeGuaranteedI); - - if (!UnsafeGuaranteedValue) { - LLVM_DEBUG(llvm::dbgs() << " no single unsafeGuaranteed value use\n"); - continue; - } - - // Look for a builtin "unsafeGuaranteedEnd" instruction that uses the - // token. - // builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - auto *UnsafeGuaranteedEndI = - getUnsafeGuaranteedEndUser(UnsafeGuaranteedToken); - if (!UnsafeGuaranteedEndI) { - LLVM_DEBUG(llvm::dbgs()<<" no single unsafeGuaranteedEnd use found\n"); - continue; - } - - if (!PDI) - PDI = PDA->get(&F); - - // It needs to post-dominated the end instruction, since we need to remove - // the release along all paths to exit. - if (!PDI->properlyDominates(UnsafeGuaranteedEndI, UnsafeGuaranteedI)) - continue; - - - // Find the release to match with the unsafeGuaranteedValue. - auto &UnsafeGuaranteedEndBB = *UnsafeGuaranteedEndI->getParent(); - auto LastRelease = findReleaseToMatchUnsafeGuaranteedValue( - UnsafeGuaranteedEndI, UnsafeGuaranteedI, UnsafeGuaranteedValue, - UnsafeGuaranteedEndBB, RCIA); - if (!LastRelease) { - LLVM_DEBUG(llvm::dbgs() << " no release before/after " - "unsafeGuaranteedEnd found\n"); - continue; - } - - // Restart iteration before the earliest instruction we remove. - bool RestartAtBeginningOfBlock = false; - auto LastRetainIt = SILBasicBlock::iterator(LastRetainInst); - if (LastRetainIt != BB.begin()) { - It = std::prev(LastRetainIt); - } else RestartAtBeginningOfBlock = true; - - // Okay we found a post dominating release. Let's remove the - // retain/unsafeGuaranteed/release combo. - // - // Before we do this check whether there are any pairs of retain releases - // we can safely remove. - tryRemoveRetainReleasePairsBetween(RCIA, UnsafeGuaranteedI, - LastRetainInst, LastRelease, - UnsafeGuaranteedEndI); - - LastRetainInst->eraseFromParent(); - LastRelease->eraseFromParent(); - UnsafeGuaranteedEndI->eraseFromParent(); - deleteAllDebugUses(UnsafeGuaranteedValue); - deleteAllDebugUses(UnsafeGuaranteedToken); - deleteAllDebugUses(UnsafeGuaranteedI); - UnsafeGuaranteedValue->replaceAllUsesWith(Opd); - UnsafeGuaranteedValue->eraseFromParent(); - UnsafeGuaranteedToken->eraseFromParent(); - UnsafeGuaranteedI->replaceAllUsesWith(Opd); - UnsafeGuaranteedI->eraseFromParent(); - - if (RestartAtBeginningOfBlock) - It = BB.begin(); - - Changed = true; - } - } - return Changed; -} - -namespace { -class UnsafeGuaranteedPeephole : public swift::SILFunctionTransform { - - void run() override { - auto &RCIA = *getAnalysis()->get(getFunction()); - auto *PostDominance = getAnalysis(); - if (removeGuaranteedRetainReleasePairs(*getFunction(), RCIA, PostDominance)) - invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); - } - -}; -} // end anonymous namespace - -SILTransform *swift::createUnsafeGuaranteedPeephole() { - return new UnsafeGuaranteedPeephole(); -} diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 79983aaf15f2a..5cac55d804d67 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 702; // SILFunction DeclCtxt +const uint16_t SWIFTMODULE_VERSION_MINOR = 703; // remove builtin unsafe guaran /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/test/IRGen/builtins.swift b/test/IRGen/builtins.swift index a079c93d36b27..f934277407ebe 100644 --- a/test/IRGen/builtins.swift +++ b/test/IRGen/builtins.swift @@ -779,37 +779,6 @@ func is_same_metatype_test(_ t1: Any.Type, _ t2: Any.Type) { var t = Builtin.is_same_metatype(t1, t2) } -// CHECK-LABEL: define {{.*}} @{{.*}}generic_unsafeGuaranteed_test -// CHECK: call {{.*}}* @{{.*}}swift_{{.*}}etain({{.*}}* returned %0) -// CHECK: ret {{.*}}* %0 -func generic_unsafeGuaranteed_test(_ t : T) -> T { - let (g, _) = Builtin.unsafeGuaranteed(t) - return g -} - -// CHECK-LABEL: define {{.*}} @{{.*}}unsafeGuaranteed_test -// CHECK: [[LOCAL1:%.*]] = alloca %swift.refcounted* -// CHECK: [[LOCAL2:%.*]] = alloca %swift.refcounted* -// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned %0) -// CHECK: store %swift.refcounted* %0, %swift.refcounted** [[LOCAL2]] -// CHECK-NOT: call void @swift_release(%swift.refcounted* %0) -// CHECK: ret %swift.refcounted* %0 -func unsafeGuaranteed_test(_ x: Builtin.NativeObject) -> Builtin.NativeObject { - var (g,t) = Builtin.unsafeGuaranteed(x) - Builtin.unsafeGuaranteedEnd(t) - return g -} - -// CHECK-LABEL: define {{.*}} @{{.*}}unsafeGuaranteedEnd_test -// CHECK-NEXT: {{.*}}: -// CHECK-NEXT: alloca -// CHECK-NEXT: memset -// CHECK-NEXT: store -// CHECK-NEXT: ret void -func unsafeGuaranteedEnd_test(_ x: Builtin.Int8) { - Builtin.unsafeGuaranteedEnd(x) -} - // CHECK-LABEL: define {{.*}} @{{.*}}atomicload func atomicload(_ p: Builtin.RawPointer) { // CHECK: [[A:%.*]] = load atomic i8*, i8** {{%.*}} unordered, align 8 diff --git a/test/SIL/OwnershipVerifier/use_verifier.sil b/test/SIL/OwnershipVerifier/use_verifier.sil index a8e0f83aabfa6..e92413bace83a 100644 --- a/test/SIL/OwnershipVerifier/use_verifier.sil +++ b/test/SIL/OwnershipVerifier/use_verifier.sil @@ -312,18 +312,6 @@ bb0: return %9999 : $() } -sil [ossa] @unsafeGuaranteedTest : $@convention(thin) (@owned Ref) -> () { -bb0(%0 : @owned $Ref): - %1 = builtin "unsafeGuaranteed"(%0 : $Ref) : $(Ref, Builtin.Int8) - %2 = begin_borrow %1 : $(Ref, Builtin.Int8) - %3 = tuple_extract %2 : $(Ref, Builtin.Int8), 1 - end_borrow %2 : $(Ref, Builtin.Int8) - builtin "unsafeGuaranteedEnd"(%3 : $Builtin.Int8) : $() - destroy_value %1 : $(Ref, Builtin.Int8) - %9999 = tuple() - return %9999 : $() -} - sil [ossa] @unchecked_enum_data_propagates_ownership : $@convention(thin) (@owned Optional) -> @owned Builtin.NativeObject { bb0(%0 : @owned $Optional): %1 = begin_borrow %0 : $Optional diff --git a/test/SILGen/builtins.swift b/test/SILGen/builtins.swift index de751260ea5a7..78480b91d63bc 100644 --- a/test/SILGen/builtins.swift +++ b/test/SILGen/builtins.swift @@ -737,58 +737,6 @@ func refcast_any_punknown(_ o: AnyObject) -> PUnknown { return Builtin.castReference(o) } -// => SEMANTIC ARC TODO: This function is missing a borrow + extract + copy. -// -// CHECK-LABEL: sil hidden [ossa] @$s8builtins22unsafeGuaranteed_class{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[P:%.*]] : @guaranteed $A): -// CHECK: [[P_COPY:%.*]] = copy_value [[P]] -// CHECK: [[T:%.*]] = builtin "unsafeGuaranteed"([[P_COPY]] : $A) -// CHECK: ([[R:%.*]], [[K:%.*]]) = destructure_tuple [[T]] -// CHECK: destroy_value [[R]] -// CHECK: [[P_COPY:%.*]] = copy_value [[P]] -// CHECK: return [[P_COPY]] : $A -// CHECK: } -func unsafeGuaranteed_class(_ a: A) -> A { - Builtin.unsafeGuaranteed(a) - return a -} - -// CHECK-LABEL: $s8builtins24unsafeGuaranteed_generic{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[P:%.*]] : @guaranteed $T): -// CHECK: [[P_COPY:%.*]] = copy_value [[P]] -// CHECK: [[T:%.*]] = builtin "unsafeGuaranteed"([[P_COPY]] : $T) -// CHECK: ([[R:%.*]], [[K:%.*]]) = destructure_tuple [[T]] -// CHECK: destroy_value [[R]] -// CHECK: [[P_RETURN:%.*]] = copy_value [[P]] -// CHECK: return [[P_RETURN]] : $T -// CHECK: } -func unsafeGuaranteed_generic (_ a: T) -> T { - Builtin.unsafeGuaranteed(a) - return a -} - -// CHECK_LABEL: sil hidden [ossa] @$s8builtins31unsafeGuaranteed_generic_return{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[P:%.*]] : @guaranteed $T): -// CHECK: [[P_COPY:%.*]] = copy_value [[P]] -// CHECK: [[T:%.*]] = builtin "unsafeGuaranteed"([[P_COPY]] : $T) -// CHECK: ([[R:%.*]], [[K:%.*]]) = destructure_tuple [[T]] -// CHECK: [[S:%.*]] = tuple ([[R]] : $T, [[K]] : $Builtin.Int8) -// CHECK: return [[S]] : $(T, Builtin.Int8) -// CHECK: } -func unsafeGuaranteed_generic_return (_ a: T) -> (T, Builtin.Int8) { - return Builtin.unsafeGuaranteed(a) -} - -// CHECK-LABEL: sil hidden [ossa] @$s8builtins19unsafeGuaranteedEnd{{[_0-9a-zA-Z]*}}F -// CHECK: bb0([[P:%.*]] : $Builtin.Int8): -// CHECK: builtin "unsafeGuaranteedEnd"([[P]] : $Builtin.Int8) -// CHECK: [[S:%.*]] = tuple () -// CHECK: return [[S]] : $() -// CHECK: } -func unsafeGuaranteedEnd(_ t: Builtin.Int8) { - Builtin.unsafeGuaranteedEnd(t) -} - // CHECK-LABEL: sil hidden [ossa] @$s8builtins10bindMemory{{[_0-9a-zA-Z]*}}F // CHECK: bb0([[P:%.*]] : $Builtin.RawPointer, [[I:%.*]] : $Builtin.Word, [[T:%.*]] : $@thick T.Type): // CHECK: %{{.*}} = bind_memory [[P]] : $Builtin.RawPointer, [[I]] : $Builtin.Word to $*T diff --git a/test/SILGen/guaranteed_normal_args.swift b/test/SILGen/guaranteed_normal_args.swift index 47aa6843c5189..fc3ea6d26b8f8 100644 --- a/test/SILGen/guaranteed_normal_args.swift +++ b/test/SILGen/guaranteed_normal_args.swift @@ -200,18 +200,6 @@ extension FakeDictionary { } } -extension Unmanaged { - // Just make sure that we do not crash on this. - func unsafeGuaranteedTest( - _ body: (Instance) -> Result - ) -> Result { - let (guaranteedInstance, token) = Builtin.unsafeGuaranteed(_value) - let result = body(guaranteedInstance) - Builtin.unsafeGuaranteedEnd(token) - return result - } -} - // Make sure that we properly forward x into memory and don't crash. public func forwardIntoMemory(fromNative x: AnyObject, y: Builtin.Word) -> Builtin.BridgeObject { // y would normally be 0._builtinWordValue. We don't want to define that diff --git a/test/SILOptimizer/devirt_speculative.sil b/test/SILOptimizer/devirt_speculative.sil index 2834213128837..4efebb56cea80 100644 --- a/test/SILOptimizer/devirt_speculative.sil +++ b/test/SILOptimizer/devirt_speculative.sil @@ -117,24 +117,6 @@ bb0(%0: $Base2): // CHECK: bb[[GENCALL]]{{.*}}: // CHECK: apply [[METH]] -// Don't devirtualize 'unsafeGuaranteed' self calls. -// CHECK-LABEL: sil @test_unsafeGuaranteed -// CHECK-NOT: check_cast_br -// CHECK: return -sil @test_unsafeGuaranteed : $@convention(thin) (@guaranteed Base2) -> () { -bb0(%0: $Base2): - strong_retain %0 : $Base2 - %4 = builtin "unsafeGuaranteed"(%0 : $Base2) : $(Base2, Builtin.Int8) - %5 = tuple_extract %4 : $(Base2, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Base2, Builtin.Int8), 1 - %1 = class_method %0 : $Base2, #Base2.foo : (Base2) -> () -> (), $@convention(method) (@guaranteed Base2) -> () - %2 = apply %1(%5) : $@convention(method) (@guaranteed Base2) -> () - strong_release %5 : $Base2 - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %3 = tuple() - return %3 : $() -} - // Check that NoReturn functions are devirtualized properly. // The new apply should be followed by an unreachable instruction // instead of a branch instruction. diff --git a/test/SILOptimizer/unsafe_guaranteed_peephole.sil b/test/SILOptimizer/unsafe_guaranteed_peephole.sil deleted file mode 100644 index 23af73fe4fdb1..0000000000000 --- a/test/SILOptimizer/unsafe_guaranteed_peephole.sil +++ /dev/null @@ -1,626 +0,0 @@ -// RUN: %target-sil-opt -enable-sil-verify-all -unsafe-guaranteed-peephole %s | %FileCheck %s -sil_stage canonical - -import Builtin -import Swift - -public class Base { - public func beep() -} - -public class Foo : Base { - public override func beep() -} - -sil @beep : $@convention(thin) () -> () -sil @beep2 : $@convention(thin) (@owned Foo) -> () -sil @beep_or_throw : $@convention(thin) () -> @error Error - -// CHECK-LABEL: sil @testUnsafeGuaranteed_simple -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_simple : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_simple_after -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK-NOT: release -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_simple_after : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - strong_release %5 : $Foo - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_simple_after2 -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK-NOT: release -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_simple_after2 : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - release_value %4 : $(Foo, Builtin.Int8) - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_simple_after3 -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK-NOT: release -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_simple_after3 : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - release_value %0 : $Foo - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_noretain -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK: [[G:%.*]] = builtin "unsafeGuaranteed" -// CHECK: [[GV:%.*]] = tuple_extract [[G]]{{.*}}, 0 -// CHECK: [[M:%.*]] = class_method [[GV]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[GV]]) -// CHECK: release -// CHECK: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_noretain : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_norelease -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK: retain [[P]] -// CHECK: [[G:%.*]] = builtin "unsafeGuaranteed" -// CHECK: [[GV:%.*]] = tuple_extract [[G]]{{.*}}, 0 -// CHECK: [[M:%.*]] = class_method [[GV]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[GV]]) -// CHECK: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_norelease : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_skip_rr -// CHECK: bb0([[P:%.*]] : $Foo, [[P2:%.*]] : $Foo): -// CHECK-NOT: retain [[P]] -// CHECK-NOT: unsafeGuaranteed -// CHECK: retain [[P2]] -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release [[P]] -// CHECK: release [[P2]] -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_skip_rr : $@convention(method) (@guaranteed Foo, @guaranteed Foo) -> () { -bb0(%0 : $Foo, %1: $Foo): - strong_retain %0 : $Foo - strong_retain %1 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - strong_release %1 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_other_inst_between_retain -// CHECK: bb0 -// CHECK: strong_retain [[P]] -// CHECK: cond_fail -// CHECK: builtin "unsafeGuaranteed" -// CHECK: class_method {{.*}} : $Foo, #Foo.beep -// CHECK: apply -// CHECK: strong_release -// CHECK: builtin "unsafeGuaranteedEnd" -// CHECK: } -sil @testUnsafeGuaranteed_other_inst_between_retain: $@convention(method) (@guaranteed Foo, Builtin.Int1) -> () { -bb0(%0 : $Foo, %1 : $Builtin.Int1): - strong_retain %0 : $Foo - cond_fail %1 : $Builtin.Int1 - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_other_inst_between_release -// CHECK: bb0 -// CHECK: strong_retain [[P]] -// CHECK: builtin "unsafeGuaranteed" -// CHECK: class_method {{.*}} : $Foo, #Foo.beep -// CHECK: apply -// CHECK: strong_release -// CHECK: cond_fail -// CHECK: builtin "unsafeGuaranteedEnd" -// CHECK: } -sil @testUnsafeGuaranteed_other_inst_between_release: $@convention(method) (@guaranteed Foo, Builtin.Int1) -> () { -bb0(%0 : $Foo, %1 : $Builtin.Int1): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - cond_fail %1 : $Builtin.Int1 - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_cfg -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: checked_cast_br [exact] [[P]] : $Foo to Foo, bb1, bb3 -// CHECK: bb1([[P2:%.*]] : $Foo): -// CHECK: function_ref @beep : $@convention(thin) () -> () -// CHECK: %4 = apply %3() : $@convention(thin) () -> () -// CHECK: br bb2 -// CHECK: bb2: -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: bb3: -// CHECK: [[M:%.*]] = class_method %0 : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK: br bb2 -// CHECK: } -sil @testUnsafeGuaranteed_cfg : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - checked_cast_br [exact] %5 : $Foo to Foo, bb1, bb3 - -bb1(%11 : $Foo): - %12 = function_ref @beep : $@convention(thin) () -> () - %13 = apply %12() : $@convention(thin) () -> () - br bb2 - -bb2: - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() - -bb3: - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - br bb2 -} - -/// CHECK-LABEL: sil @testUnsafeGuaranteed_cfg_2 -/// CHECK: unsafeGuaranteed -/// CHECK: unsafeGuaranteedEnd -/// CHECK: } -sil @testUnsafeGuaranteed_cfg_2 : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - checked_cast_br [exact] %5 : $Foo to Foo, bb1, bb3 - -bb1(%11 : $Foo): - %12 = function_ref @beep : $@convention(thin) () -> () - %13 = apply %12() : $@convention(thin) () -> () - br bb2 - -bb2: -// Make sure we don't crash on an unsafeGuaranteedEnd walking backwards in the -// block. - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() - -bb3: - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - br bb2 -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_debug_inst -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_debug_inst : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - debug_value %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - debug_value %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_retain_release -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: strong_retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: retain_value [[P]] -// CHECK: [[M:%.*]] = function_ref @beep2 -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_retain_release : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - retain_value %4 : $(Foo, Builtin.Int8) - %19 = function_ref @beep2 : $@convention(thin) (@owned Foo) -> () - %20 = apply %19(%5) : $@convention(thin) (@owned Foo) -> () - release_value %4 : $(Foo, Builtin.Int8) - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -struct MyInt { - @_hasStorage var val: Builtin.Int32 -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_sideeffectfree_inst -// CHECK: bb0([[P:%.*]] : $Foo -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_sideeffectfree_inst : $@convention(method) (@guaranteed Foo, Builtin.Int32) -> () { -bb0(%0 : $Foo, %1: $Builtin.Int32): - strong_retain %0 : $Foo - debug_value %0 : $Foo - %3 = struct $MyInt(%1 : $Builtin.Int32) - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - %21 = struct $MyInt(%1 : $Builtin.Int32) - debug_value %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_sideeffect_inst -// CHECK: bb0([[P:%.*]] : $Foo -// CHECK: retain -// CHECK: unsafeGuaranteed -// CHECK: release -// CHECK: unsafeGuaranteedEnd -// CHECK: } -sil @testUnsafeGuaranteed_sideeffect_inst : $@convention(method) (@guaranteed Foo, @inout Builtin.Int32, Builtin.Int32) -> () { -bb0(%0 : $Foo, %1: $*Builtin.Int32, %2: $Builtin.Int32): - strong_retain %0 : $Foo - store %2 to %1 : $*Builtin.Int32 - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_sideeffect_inst2 -// CHECK: bb0([[P:%.*]] : $Foo -// CHECK: retain -// CHECK: unsafeGuaranteed -// CHECK: release -// CHECK: unsafeGuaranteedEnd -// CHECK: } -sil @testUnsafeGuaranteed_sideeffect_inst2 : $@convention(method) (@guaranteed Foo, @inout Builtin.Int32, Builtin.Int32) -> () { -bb0(%0 : $Foo, %1: $*Builtin.Int32, %2: $Builtin.Int32): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - store %2 to %1 : $*Builtin.Int32 - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_cast_inst -// CHECK: bb0([[P:%.*]] : $Foo -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[U:%.*]] = upcast [[P]] : $Foo to $Base -// CHECK: [[M:%.*]] = class_method [[U]] : $Base, #Base.beep -// CHECK: apply [[M]]([[U]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_cast_inst : $@convention(method) (@guaranteed Foo, Builtin.Int32) -> () { -bb0(%0 : $Foo, %1: $Builtin.Int32): - strong_retain %0 : $Foo - debug_value %0 : $Foo - %3 = struct $MyInt(%1 : $Builtin.Int32) - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %7 = upcast %5 : $Foo to $Base - %19 = class_method %7 : $Base, #Base.beep : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> () - %20 = apply %19(%7) : $@convention(method) (@guaranteed Base) -> () - strong_release %7 : $Base - %21 = struct $MyInt(%1 : $Builtin.Int32) - debug_value %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_cast2_inst -// CHECK: bb0([[P:%.*]] : $AnyObject -// CHECK: [[C:%.*]] = unchecked_ref_cast [[P]] : $AnyObject to $Foo -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[U:%.*]] = upcast [[C]] : $Foo to $Base -// CHECK: [[M:%.*]] = class_method [[U]] : $Base, #Base.beep -// CHECK: apply [[M]]([[U]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_cast2_inst : $@convention(method) (@guaranteed AnyObject, Builtin.Int32) -> () { -bb0(%0 : $AnyObject, %1: $Builtin.Int32): - %2 = unchecked_ref_cast %0 : $AnyObject to $Foo - strong_retain %0 : $AnyObject - debug_value %0 : $AnyObject - %3 = struct $MyInt(%1 : $Builtin.Int32) - %4 = builtin "unsafeGuaranteed"(%2 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %7 = upcast %5 : $Foo to $Base - %19 = class_method %7 : $Base, #Base.beep : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> () - %20 = apply %19(%7) : $@convention(method) (@guaranteed Base) -> () - strong_release %7 : $Base - %21 = struct $MyInt(%1 : $Builtin.Int32) - debug_value %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_throw -// CHECK:bb0 -// CHECK: unsafeGuaranteed -// CHECK:bb1 -// CHECK: unsafeGuaranteedEnd -// CHECK: return -// CHECK:bb2 -// CHECK: throw -sil @testUnsafeGuaranteed_throw : $@convention(method) (@guaranteed Foo) -> @error Error { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %7 = function_ref @beep_or_throw : $@convention(thin) () -> @error Error - try_apply %7() : $@convention(thin) () -> @error Error, normal bb1, error bb2 - -bb1(%15: $()): - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() - -bb2(%9: $Error): - strong_release %5 : $Foo - throw %9: $Error -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_simple_retain_release_pair -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_simple_retain_release_pair : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - retain_value %4 : $(Foo, Builtin.Int8) - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} - -// CHECK-LABEL: sil @testUnsafeGuaranteed_simple_retain_release_pair2 -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK-NOT: retain -// CHECK-NOT: unsafeGuaranteed -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: apply [[M]]([[P]]) -// CHECK-NOT: release -// CHECK-NOT: unsafeGuaranteedEnd -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_simple_retain_release_pair2 : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - retain_value %4 : $(Foo, Builtin.Int8) - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - strong_release %5 : $Foo - %17 = tuple () - return %17 : $() -} - - -// CHECK-LABEL: sil @testUnsafeGuaranteed_simple_retain_release_pair_not_safe -// CHECK: bb0([[P:%.*]] : $Foo): -// CHECK: [[M:%.*]] = class_method [[P]] : $Foo, #Foo.beep -// CHECK: retain -// CHECK: release -// CHECK: apply [[M]]([[P]]) -// CHECK: release -// CHECK: [[T:%.*]] = tuple () -// CHECK: return [[T]] -// CHECK: } -sil @testUnsafeGuaranteed_simple_retain_release_pair_not_safe : $@convention(method) (@guaranteed Foo) -> () { -bb0(%0 : $Foo): - strong_retain %0 : $Foo - %4 = builtin "unsafeGuaranteed"(%0 : $Foo) : $(Foo, Builtin.Int8) - %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0 - %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1 - %19 = class_method %5 : $Foo, #Foo.beep : (Foo) -> () -> (), $@convention(method) (@guaranteed Foo) -> () - retain_value %4 : $(Foo, Builtin.Int8) - strong_release %0 : $Foo - %20 = apply %19(%5) : $@convention(method) (@guaranteed Foo) -> () - strong_release %5 : $Foo - strong_release %5 : $Foo - %16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $() - %17 = tuple () - return %17 : $() -} From d8b95440d341fa90de9d2cfca61f0a7ef28c82fa Mon Sep 17 00:00:00 2001 From: Jager-yoo Date: Sun, 21 Aug 2022 23:53:44 +0900 Subject: [PATCH 244/491] [docs] Fix typo in DevelopmentTips.md --- docs/DevelopmentTips.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DevelopmentTips.md b/docs/DevelopmentTips.md index bcf8f59556890..4068ca7d15fe4 100644 --- a/docs/DevelopmentTips.md +++ b/docs/DevelopmentTips.md @@ -16,7 +16,7 @@ Going further, ninja can spawn a web browser for you to navigate dependencies an Clicking around a little bit, we can find `lib/swift/iphonesimulator/i386/libswiftCore.dylib` as a commonly-depended-upon target. This will perform just what is needed to compile the standard library for i386 and nothing else. -Going further, for various reasons the standard library has lots of warnings. This is actively being addressed, but fixing all of them may require language features, etc. In the mean time, let’s suppress warnings in our build so that we just see the errors. `ninja -nv lib/swift/iphonesimulator/i386/libswiftCore.dylib` will show us the actual commands ninja will issue to build the i386 stdlib. (You’ll notice that an incremental build here is merely 3 commands as opposed to ~150 for `swift-stdlib-iphonesimulator-i386`). +Going further, for various reasons the standard library has lots of warnings. This is actively being addressed, but fixing all of them may require language features, etc. In the meantime, let’s suppress warnings in our build so that we just see the errors. `ninja -nv lib/swift/iphonesimulator/i386/libswiftCore.dylib` will show us the actual commands ninja will issue to build the i386 stdlib. (You’ll notice that an incremental build here is merely 3 commands as opposed to ~150 for `swift-stdlib-iphonesimulator-i386`). Copy the invocation that has ` -o /swift-macosx-x86_64/stdlib/public/core/iphonesimulator/i386/Swift.o`, so that we can perform the actual call to swiftc ourselves. Tack on `-suppress-warnings` at the end, and now we have the command to just build `Swift.o` for i386 while only displaying the actual errors. From 01ea11b34a32adc7c34b45365f52eab16f1a065c Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Fri, 12 Aug 2022 15:29:53 -0700 Subject: [PATCH 245/491] [ConstraintGraph] Collect and print changes in current Active Scope. --- include/swift/Sema/ConstraintGraph.h | 1 + lib/Sema/CSStep.h | 7 ++ lib/Sema/ConstraintGraph.cpp | 117 +++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) diff --git a/include/swift/Sema/ConstraintGraph.h b/include/swift/Sema/ConstraintGraph.h index 706b2a5ede057..e2f72077118be 100644 --- a/include/swift/Sema/ConstraintGraph.h +++ b/include/swift/Sema/ConstraintGraph.h @@ -387,6 +387,7 @@ class ConstraintGraph { /// Print the graph. void print(ArrayRef typeVars, llvm::raw_ostream &out); void dump(llvm::raw_ostream &out); + void dumpActiveScopeChanges(llvm::raw_ostream &out, unsigned indent = 0); // FIXME: Potentially side-effectful. SWIFT_DEBUG_HELPER(void dump()); diff --git a/lib/Sema/CSStep.h b/lib/Sema/CSStep.h index 79f69d2c2748a..b662defcd6c54 100644 --- a/lib/Sema/CSStep.h +++ b/lib/Sema/CSStep.h @@ -545,6 +545,13 @@ template class BindingStep : public SolverStep { auto scope = std::make_unique(CS); if (attempt(*choice)) { ActiveChoice.emplace(std::move(scope), *choice); + + if (CS.isDebugMode()) { + auto &log = llvm::errs(); + auto &CG = CS.getConstraintGraph(); + CG.dumpActiveScopeChanges(log, CS.solverState->getCurrentIndent()); + } + return suspend(std::make_unique(CS, Solutions)); } } diff --git a/lib/Sema/ConstraintGraph.cpp b/lib/Sema/ConstraintGraph.cpp index 216d34dd14993..6c02b1f91fc61 100644 --- a/lib/Sema/ConstraintGraph.cpp +++ b/lib/Sema/ConstraintGraph.cpp @@ -1558,6 +1558,123 @@ void ConstraintGraph::dump(llvm::raw_ostream &out) { print(CS.getTypeVariables(), out); } +void ConstraintGraph::dumpActiveScopeChanges(llvm::raw_ostream &out, + unsigned indent) { + if (Changes.empty()) + return; + + // Collect Changes for printing. + std::map tvWithboundTypes; + std::vector addedTypeVars; + std::vector equivTypeVars; + std::set addedConstraints; + std::set removedConstraints; + for (unsigned int i = ActiveScope->getStartIdx(); i < Changes.size(); i++) { + auto change = Changes[i]; + switch (change.Kind) { + case ChangeKind::BoundTypeVariable: + tvWithboundTypes.insert(std::pair( + change.Binding.TypeVar, change.Binding.FixedType)); + break; + case ChangeKind::AddedTypeVariable: + addedTypeVars.push_back(change.TypeVar); + break; + case ChangeKind::ExtendedEquivalenceClass: + equivTypeVars.push_back(change.EquivClass.TypeVar); + break; + case ChangeKind::AddedConstraint: + addedConstraints.insert(change.TheConstraint); + break; + case ChangeKind::RemovedConstraint: + removedConstraints.insert(change.TheConstraint); + break; + } + } + + // If there are any constraints that were both added and removed in this set + // of Changes, remove them from both. + std::set intersects; + set_intersection(addedConstraints.begin(), addedConstraints.end(), + removedConstraints.begin(), removedConstraints.end(), + std::inserter(intersects, intersects.begin())); + llvm::set_subtract(addedConstraints, intersects); + llvm::set_subtract(removedConstraints, intersects); + + // Print out Changes. + PrintOptions PO; + PO.PrintTypesForDebugging = true; + out.indent(indent); + out << "(Changes:\n"; + if (!tvWithboundTypes.empty()) { + out.indent(indent + 2); + out << "(Newly Bound: \n"; + for (const auto &tvWithType : tvWithboundTypes) { + out.indent(indent + 4); + out << "> $T" << tvWithType.first->getImpl().getID() << " := "; + tvWithType.second->print(out, PO); + out << '\n'; + } + out.indent(indent + 2); + out << ")\n"; + } + if (!addedTypeVars.empty()) { + out.indent(indent + 2); + auto heading = (addedTypeVars.size() > 1) ? "(New Type Variables: \n" + : "(New Type Variable: \n"; + out << heading; + for (const auto &typeVar : addedTypeVars) { + out.indent(indent + 4); + out << "> $T" << typeVar->getImpl().getID(); + out << '\n'; + } + out.indent(indent + 2); + out << ")\n"; + } + if (!equivTypeVars.empty()) { + out.indent(indent + 2); + auto heading = (equivTypeVars.size() > 1) ? "(New Equivalences: \n" + : "(New Equivalence: \n"; + out << heading; + for (const auto &typeVar : equivTypeVars) { + out.indent(indent + 4); + out << "> $T" << typeVar->getImpl().getID(); + out << '\n'; + } + out.indent(indent + 2); + out << ")\n"; + } + if (!addedConstraints.empty()) { + out.indent(indent + 2); + auto heading = (addedConstraints.size() > 1) ? "(Added Constraints: \n" + : "(Added Constraint: \n"; + out << heading; + for (const auto &constraint : addedConstraints) { + out.indent(indent + 4); + out << "> "; + constraint->print(out, &CS.getASTContext().SourceMgr); + out << '\n'; + } + out.indent(indent + 2); + out << ")\n"; + } + if (!removedConstraints.empty()) { + out.indent(indent + 2); + auto heading = (removedConstraints.size() > 1) ? "(Removed Constraints: \n" + : "(Removed Constraint: \n"; + out << heading; + for (const auto &constraint : removedConstraints) { + out.indent(indent + 4); + out << "> "; + constraint->print(out, &CS.getASTContext().SourceMgr); + out << '\n'; + } + out.indent(indent + 2); + out << ")\n"; + } + out.indent(indent); + out << ")\n"; +} + void ConstraintGraph::printConnectedComponents( ArrayRef typeVars, llvm::raw_ostream &out) { From d750d382fab166cea2ea52c48f99f97a2d192c0f Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 18 Aug 2022 17:52:16 -0700 Subject: [PATCH 246/491] [CSBindings] Consolidate BindingSet dump into single function. --- include/swift/Sema/CSBindings.h | 2 -- lib/Sema/CSBindings.cpp | 17 ++++++----------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/include/swift/Sema/CSBindings.h b/include/swift/Sema/CSBindings.h index 59b4623080688..713e150bd8c5d 100644 --- a/include/swift/Sema/CSBindings.h +++ b/include/swift/Sema/CSBindings.h @@ -546,8 +546,6 @@ class BindingSet { } void dump(llvm::raw_ostream &out, unsigned indent) const; - void dump(TypeVariableType *typeVar, llvm::raw_ostream &out, - unsigned indent = 0) const LLVM_ATTRIBUTE_USED; private: void addBinding(PotentialBinding binding); diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 16cc21d05aaa4..cf30d06e3418d 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -805,7 +805,7 @@ Optional ConstraintSystem::determineBestBindings() { continue; if (isDebugMode()) { - bindings.dump(typeVar, llvm::errs(), solverState->getCurrentIndent()); + bindings.dump(llvm::errs(), solverState->getCurrentIndent()); } // If these are the first bindings, or they are better than what @@ -1652,21 +1652,15 @@ static std::string getCollectionLiteralAsString(KnownProtocolKind KPK) { #undef ENTRY } -void BindingSet::dump(TypeVariableType *typeVar, llvm::raw_ostream &out, - unsigned indent) const { - out.indent(indent); - out << "("; - if (typeVar) - out << "$T" << typeVar->getImpl().getID(); - dump(out, 1); - out << ")\n"; -} - void BindingSet::dump(llvm::raw_ostream &out, unsigned indent) const { PrintOptions PO; PO.PrintTypesForDebugging = true; out.indent(indent); + out << "("; + if (auto typeVar = getTypeVariable()) + out << "$T" << typeVar->getImpl().getID() << " "; + std::vector attributes; if (isDirectHole()) attributes.push_back("hole"); @@ -1778,6 +1772,7 @@ void BindingSet::dump(llvm::raw_ostream &out, unsigned indent) const { } out << "] "; } + out << ")\n"; } // Given a possibly-Optional type, return the direct superclass of the From 14f7d07cffb0899df578e300368386f1a3b0b416 Mon Sep 17 00:00:00 2001 From: "DylanPerry5@gmail.com" Date: Sun, 21 Aug 2022 19:08:54 -0400 Subject: [PATCH 247/491] Updating to clean up the type checker document a little bit - fixed a couple typos --- docs/TypeChecker.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/TypeChecker.md b/docs/TypeChecker.md index e01d00d170cf2..096355afe16c6 100644 --- a/docs/TypeChecker.md +++ b/docs/TypeChecker.md @@ -455,7 +455,7 @@ Hindley-Milner type inference algorithm requires exponential time, and the Swift type system introduces additional complications, especially overload resolution. However, the problem size for any particular expression is still fairly small, and the constraint solver can employ -a number of tricks to improve performance. The Performance_ section +a number of tricks to improve performance. The [Performance](#Performance) section describes some tricks that have been implemented or are planned, and it is expected that the solver will be extended with additional tricks going forward. @@ -530,7 +530,7 @@ The member name may refer to a set of overloaded declarations. In this case, the type ``C`` is a fresh type variable (call it ``T0``). A disjunction constraint is introduced, each term of which new overload set binds a different declaration's type to ``T0``, as described in -the section on Overloading_. +the section on [Overloading](#Overloading). The kind of member constraint---type or value---also affects the declaration type ``C``. A type constraint can only refer to member @@ -677,7 +677,7 @@ resolved overloads explicit. This application process walks the expression tree from the leaves to the root, rewriting each expression node based on the kind of expression: -*Declaration references* +#### *Declaration references* Declaration references are rewritten with the precise type of the declaration as referenced. For overloaded declaration references, the ``Overload*Expr`` node is replaced with a simple declaration @@ -685,19 +685,20 @@ node based on the kind of expression: members of generic types, a ``SpecializeExpr`` node is introduced to provide substitutions for all of the generic parameters. -*Member references* +#### *Member references* References to members are similar to declaration references. However, they have the added constraint that the base expression needs to be a reference. Therefore, an rvalue of non-reference type will be materialized to produce the necessary reference. -*Literals* +#### *Literals* Literals are converted to the appropriate literal type, which typically involves introducing calls to the witnesses for the appropriate literal protocols. -*Closures* +#### *Closures* + Since the closure has acquired a complete function type, the body of the closure is type-checked with that complete function type. From 0659e16846defaf77d69af4efb2589d11d735142 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 15 Aug 2022 08:50:39 -0700 Subject: [PATCH 248/491] [SILGen] Use decl for noImplicitCopy attr. Rather than using the SILValue of the ManagedValue generated for that argument, which is not always a SILFunctionArgument, just look directly at the ParmDecl for the attribute. --- lib/SILGen/SILGenProlog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index bf04fe3b9960d..d406c623b35c8 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -264,9 +264,9 @@ struct ArgumentInitHelper { if (!SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) return value; - bool isNoImplicitCopy = false; - if (auto *arg = dyn_cast(value)) - isNoImplicitCopy = arg->isNoImplicitCopy(); + // Look for the following annotations on the function argument: + // - @noImplicitCopy + auto isNoImplicitCopy = pd->isNoImplicitCopy(); // If we have a no implicit copy argument and the argument is trivial, // we need to use copyable to move only to convert it to its move only From 8450e37ddb317d9bbc8506622cba401428f5d860 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 15 Aug 2022 15:31:17 -0700 Subject: [PATCH 249/491] [SIL] Removed SILArgument::isNoImplicitCopy. The attribute can't be applied to non-function arguments and may cause confusion by being available on them. --- include/swift/SIL/SILArgument.h | 8 -------- lib/Serialization/SerializeSIL.cpp | 4 +++- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/include/swift/SIL/SILArgument.h b/include/swift/SIL/SILArgument.h index 284a043354cfd..3211ed5c16804 100644 --- a/include/swift/SIL/SILArgument.h +++ b/include/swift/SIL/SILArgument.h @@ -113,8 +113,6 @@ class SILArgument : public ValueBase { node->getKind() <= SILNodeKind::Last_SILArgument; } - bool isNoImplicitCopy() const; - unsigned getIndex() const; /// Return non-null if \p value is a phi. @@ -408,12 +406,6 @@ inline SILPhiArgument *SILArgument::isTerminatorResult(SILValue value) { return nullptr; } -inline bool SILArgument::isNoImplicitCopy() const { - if (auto *fArg = dyn_cast(this)) - return fArg->isNoImplicitCopy(); - return false; -} - inline bool SILArgument::isTerminatorResult() const { switch (getKind()) { case SILArgumentKind::SILPhiArgument: diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 86657f2d8cf60..e4ef7a356a8df 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -624,7 +624,9 @@ void SILSerializer::writeSILBasicBlock(const SILBasicBlock &BB) { unsigned packedMetadata = 0; packedMetadata |= unsigned(SA->getType().getCategory()); // 8 bits packedMetadata |= unsigned(SA->getOwnershipKind()) << 8; // 8 bits - packedMetadata |= unsigned(SA->isNoImplicitCopy()) << 16; // 1 bit + if (auto *SFA = dyn_cast(SA)) { + packedMetadata |= unsigned(SFA->isNoImplicitCopy()) << 16; // 1 bit + } // Used: 17 bits. Free: 15. // // TODO: We should be able to shrink the packed metadata of the first two. From b467319cce58c51d55f20b695f5071841d63bceb Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 1 Aug 2022 10:03:30 -0700 Subject: [PATCH 250/491] [NFC] Removed unused variable. --- lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp b/lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp index 9bdc626e5fd9c..f62f8825531a9 100644 --- a/lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp +++ b/lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp @@ -187,7 +187,6 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization( // scope, regardless of whether the end of the scope is inside a dead-end // block. { - SmallVector scratchSpace; if (llvm::any_of(borrowScopeIntroducers, [&](BorrowedValue borrowScope) { return !borrowScope.areUsesWithinTransitiveScope( lr.getAllConsumingUses(), nullptr); From 46fe0f7128cbce1e38e4dc0e60b66abc83520ca8 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 1 Aug 2022 10:03:45 -0700 Subject: [PATCH 251/491] [Gardening] Tweaked comment grammar. --- lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp b/lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp index f62f8825531a9..6b95186702eb2 100644 --- a/lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp +++ b/lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp @@ -172,7 +172,7 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization( // destroy_values. Check if: // // 1. All of our destroys are joint post-dominated by our end borrow scope - // set. If they do not, then the copy_value is lifetime extending the + // set. If they are not, then the copy_value is lifetime extending the // guaranteed value, we can not eliminate it. // // 2. If all of our destroy_values are dead end. In such a case, the linear From 7ea2d5c54d35d62db6b757ab9be81cd516e3911f Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Tue, 16 Aug 2022 13:45:06 -0700 Subject: [PATCH 252/491] [Gardening] Tweaked argument label. --- lib/SILGen/SILGenProlog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index d406c623b35c8..98c247e004f75 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -301,7 +301,7 @@ struct ArgumentInitHelper { if (value->getType().isTrivial(SGF.F)) { value = SGF.B.createOwnedCopyableToMoveOnlyWrapperValue(loc, value); - value = SGF.B.createMoveValue(loc, value, true /*is lexical*/); + value = SGF.B.createMoveValue(loc, value, /*isLexical=*/true); // If our argument was owned, we use no implicit copy. Otherwise, we // use no copy. From 31b2d8166eac5547c13f5e54c03d2281a53ba4ab Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Tue, 16 Aug 2022 13:59:16 -0700 Subject: [PATCH 253/491] [SILGen] Added TODO. --- lib/SILGen/Scope.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/SILGen/Scope.cpp b/lib/SILGen/Scope.cpp index ebcbba6930e8e..860ae9e835e93 100644 --- a/lib/SILGen/Scope.cpp +++ b/lib/SILGen/Scope.cpp @@ -57,6 +57,8 @@ static void lifetimeExtendAddressOnlyRValueSubValues( "addresses must be address only."); auto boxTy = SILBoxType::get(v->getType().getASTType()); SILValue box = SGF.B.createAllocBox(loc, boxTy); + // TODO: Should these boxes that extend lifetimes for rvalue subobjects ever + // be lexical? if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) { box = SGF.B.createBeginBorrow(loc, box, /*isLexical=*/true); } From 2a48efe221f384f74b23d45c1d9eb5993add4161 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 15 Aug 2022 12:27:30 -0700 Subject: [PATCH 254/491] [AST] Add simple LifetimeAnnotation enum. The enum just provides a convenience around mutually exclusive attributes which may be applied to decls and to SILFunctionArguments. This way we can switch over the flavor of annotation that a decl enjoys rather than having to remember the list of which might affect it, a list which is likely to grow. --- include/swift/AST/LifetimeAnnotation.h | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 include/swift/AST/LifetimeAnnotation.h diff --git a/include/swift/AST/LifetimeAnnotation.h b/include/swift/AST/LifetimeAnnotation.h new file mode 100644 index 0000000000000..866703d96ef4b --- /dev/null +++ b/include/swift/AST/LifetimeAnnotation.h @@ -0,0 +1,49 @@ +//===--- LifetimeAnnotation.h - Lifetime-affecting attributes ---*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 +// +//===----------------------------------------------------------------------===// +// +// Defines a simple type-safe wrapper around the annotations that affect value +// lifetimes. Used for both Decls and SILFunctionArguments. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_AST_LIFETIMEANNOTATION_H +#define SWIFT_AST_LIFETIMEANNOTATION_H + +#include + +namespace swift { + +/// The annotation on a value (or type) explicitly indicating the lifetime that +/// it (or its instances) should have. +/// +/// A LifetimeAnnotation is one of the following three values: +/// +/// 1) None: No annotation has been applied. +/// 2) EagerMove: The @_eagerMove attribute has been applied. +/// 3) Lexical: The @_lexical attribute has been applied. +struct LifetimeAnnotation { + enum Case : uint8_t { + None, + EagerMove, + Lexical, + } value; + + LifetimeAnnotation(Case newValue) : value(newValue) {} + + operator Case() const { return value; } + + bool isSome() { return value != None; } +}; + +} // namespace swift + +#endif From f3ea548a3e55afe8cef6eaec78272a136b1e59c1 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Fri, 19 Aug 2022 13:09:52 -0700 Subject: [PATCH 255/491] [SIL] Added simple Lifetime enum. The new enum makes keeping track of what flavor of lifetime values ought to have a little bit type-safer. --- include/swift/SIL/Lifetime.h | 71 ++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 include/swift/SIL/Lifetime.h diff --git a/include/swift/SIL/Lifetime.h b/include/swift/SIL/Lifetime.h new file mode 100644 index 0000000000000..361cd5da20cba --- /dev/null +++ b/include/swift/SIL/Lifetime.h @@ -0,0 +1,71 @@ +//===---- Lifetime.h - How long a value should be kept alive ----*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 +// +//===----------------------------------------------------------------------===// +// +// Defines a simple type-safe wrapper type to indicate the kind of lifetime that +// a value has--whether it is tied to a lexical scope or not. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/LifetimeAnnotation.h" + +#ifndef SWIFT_SIL_LIFETIME_H +#define SWIFT_SIL_LIFETIME_H + +namespace swift { + +/// How long a value (such as instances of a type) should be kept alive--how +/// aggressively its destroys may be hoisted. +/// +/// By default, types have lifetimes inferred from their structure, see +/// TypeLowering::RecursiveProperties::isLexical. It can be overridden both on +/// the type level and the value level via attributes. +struct Lifetime { + enum Storage : uint8_t { + /// No lifetime. Applicable to values which aren't destroyed. + None, + /// A lifetime independent from the lexical scope of the value: its + /// releases are hoisted without respect to deinit barriers. + EagerMove, + /// A lifetime tied to the lexical scope of the value: its releases are + /// not hoisted over deinit barriers. + Lexical, + } value; + + Lifetime(decltype(value) newValue) : value(newValue) {} + + operator Storage() const { return value; } + + bool isLexical() { return value == Lifetime::Lexical; } + + bool isEagerMove() { return value == Lifetime::EagerMove; } + + /// Given a lifetime for a type and the lifetime annotation on a value of that + /// type, the lifetime appropriate for that value. + /// + /// Value annotations override a type's lifetime, so the result is just the + /// lifetime indicated by the annotation, if there is one; otherwise its the + /// lifetime from the type. + Lifetime getLifetimeForAnnotatedValue(LifetimeAnnotation annotation) const { + switch (annotation) { + case LifetimeAnnotation::None: + return *this; + case LifetimeAnnotation::EagerMove: + return Lifetime::EagerMove; + case LifetimeAnnotation::Lexical: + return Lifetime::Lexical; + } + } +}; + +} // end swift namespace + +#endif From 8074ce087d6e7ab0b46c913eb0cec740679e6c7f Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 11 Aug 2022 11:48:15 -0700 Subject: [PATCH 256/491] [SIL] Function args may have lifetime annotations. By default, whether a function argument's lifetime is determined by its type. To allow that behavior to be overridden on an argument-by-argument basis, the argument may have its own lifetime. --- include/swift/SIL/SILArgument.h | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/include/swift/SIL/SILArgument.h b/include/swift/SIL/SILArgument.h index 3211ed5c16804..2087ff451bac1 100644 --- a/include/swift/SIL/SILArgument.h +++ b/include/swift/SIL/SILArgument.h @@ -13,10 +13,12 @@ #ifndef SWIFT_SIL_SILARGUMENT_H #define SWIFT_SIL_SILARGUMENT_H +#include "swift/AST/LifetimeAnnotation.h" #include "swift/Basic/Compiler.h" +#include "swift/SIL/Lifetime.h" #include "swift/SIL/SILArgumentConvention.h" -#include "swift/SIL/SILValue.h" #include "swift/SIL/SILFunctionConventions.h" +#include "swift/SIL/SILValue.h" namespace swift { @@ -327,14 +329,17 @@ class SILFunctionArgument : public SILArgument { friend class SILBasicBlock; bool noImplicitCopy = false; + LifetimeAnnotation lifetimeAnnotation = LifetimeAnnotation::None; - SILFunctionArgument(SILBasicBlock *parentBlock, SILType type, - ValueOwnershipKind ownershipKind, - const ValueDecl *decl = nullptr, - bool isNoImplicitCopy = false) + SILFunctionArgument( + SILBasicBlock *parentBlock, SILType type, + ValueOwnershipKind ownershipKind, const ValueDecl *decl = nullptr, + bool isNoImplicitCopy = false, + LifetimeAnnotation lifetimeAnnotation = LifetimeAnnotation::None) : SILArgument(ValueKind::SILFunctionArgument, parentBlock, type, ownershipKind, decl), - noImplicitCopy(isNoImplicitCopy) {} + noImplicitCopy(isNoImplicitCopy), + lifetimeAnnotation(lifetimeAnnotation) {} // A special constructor, only intended for use in // SILBasicBlock::replaceFunctionArg. explicit SILFunctionArgument(SILType type, ValueOwnershipKind ownershipKind, @@ -347,6 +352,20 @@ class SILFunctionArgument : public SILArgument { void setNoImplicitCopy(bool newValue) { noImplicitCopy = newValue; } + LifetimeAnnotation getLifetimeAnnotation() const { + return lifetimeAnnotation; + } + + void setLifetimeAnnotation(LifetimeAnnotation newValue) { + lifetimeAnnotation = newValue; + } + + Lifetime getLifetime() const { + return getType() + .getLifetime(*getFunction()) + .getLifetimeForAnnotatedValue(getLifetimeAnnotation()); + } + bool isIndirectResult() const; SILArgumentConvention getArgumentConvention() const; From 93f65489505b1ab5a1e2fd2a66ee9d6effdb1b5b Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 11 Aug 2022 13:33:10 -0700 Subject: [PATCH 257/491] [Textual SIL] Explicit function arg lifetimes. Print and parse @_eagerMove and @_lexical on function arguments. --- include/swift/AST/DiagnosticsParse.def | 3 ++ lib/SIL/IR/SILPrinter.cpp | 27 ++++++++--- lib/SIL/Parser/ParseSIL.cpp | 39 +++++++++++++--- .../function_argument_lifetime_annotation.sil | 46 +++++++++++++++++++ 4 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 test/SIL/Parser/function_argument_lifetime_annotation.sil diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index fdf3974c99c6b..becc1240ee144 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -517,6 +517,9 @@ ERROR(silfunc_and_silarg_have_incompatible_sil_value_ownership,none, "SILFunction and SILArgument have mismatching ValueOwnershipKinds. " "Function type specifies: '@%0'. SIL argument specifies: '@%1'.", (StringRef, StringRef)) +ERROR(sil_arg_both_lexical_and_eagerMove,none, + "Function argument is annotated both @_eagerMove and @_lexical, " + "but these are incompatible alternatives", ()) ERROR(expected_sil_colon,none, "expected ':' before %0", (StringRef)) ERROR(expected_sil_tuple_index,none, diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index d155afe87b30d..5847426a84c3f 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -28,6 +28,7 @@ #include "swift/Demangling/Demangle.h" #include "swift/SIL/ApplySite.h" #include "swift/SIL/CFG.h" +#include "swift/SIL/SILArgument.h" #include "swift/SIL/SILCoverageMap.h" #include "swift/SIL/SILDebugScope.h" #include "swift/SIL/SILDeclRef.h" @@ -157,6 +158,7 @@ struct SILValuePrinterInfo { SILType Type; Optional OwnershipKind; bool IsNoImplicitCopy = false; + LifetimeAnnotation Lifetime = LifetimeAnnotation::None; SILValuePrinterInfo(ID ValueID) : ValueID(ValueID), Type(), OwnershipKind() {} SILValuePrinterInfo(ID ValueID, SILType Type) @@ -165,12 +167,14 @@ struct SILValuePrinterInfo { ValueOwnershipKind OwnershipKind) : ValueID(ValueID), Type(Type), OwnershipKind(OwnershipKind) {} SILValuePrinterInfo(ID ValueID, SILType Type, - ValueOwnershipKind OwnershipKind, bool IsNoImplicitCopy) + ValueOwnershipKind OwnershipKind, bool IsNoImplicitCopy, + LifetimeAnnotation Lifetime) : ValueID(ValueID), Type(Type), OwnershipKind(OwnershipKind), - IsNoImplicitCopy(IsNoImplicitCopy) {} - SILValuePrinterInfo(ID ValueID, SILType Type, bool IsNoImplicitCopy) + IsNoImplicitCopy(IsNoImplicitCopy), Lifetime(Lifetime) {} + SILValuePrinterInfo(ID ValueID, SILType Type, bool IsNoImplicitCopy, + LifetimeAnnotation Lifetime) : ValueID(ValueID), Type(Type), OwnershipKind(), - IsNoImplicitCopy(IsNoImplicitCopy) {} + IsNoImplicitCopy(IsNoImplicitCopy), Lifetime(Lifetime) {} }; /// Return the fully qualified dotted path for DeclContext. @@ -639,6 +643,16 @@ class SILPrinter : public SILInstructionVisitor { *this << " : "; if (i.IsNoImplicitCopy) *this << "@noImplicitCopy "; + switch (i.Lifetime) { + case LifetimeAnnotation::EagerMove: + *this << "@_eagerMove "; + break; + case LifetimeAnnotation::None: + break; + case LifetimeAnnotation::Lexical: + *this << "@_lexical "; + break; + } if (i.OwnershipKind && *i.OwnershipKind != OwnershipKind::None) { *this << "@" << i.OwnershipKind.getValue() << " "; } @@ -672,14 +686,15 @@ class SILPrinter : public SILInstructionVisitor { return {Ctx.getID(V), V ? V->getType() : SILType()}; } SILValuePrinterInfo getIDAndType(SILFunctionArgument *arg) { - return {Ctx.getID(arg), arg->getType(), arg->isNoImplicitCopy()}; + return {Ctx.getID(arg), arg->getType(), arg->isNoImplicitCopy(), + arg->getLifetimeAnnotation()}; } SILValuePrinterInfo getIDAndTypeAndOwnership(SILValue V) { return {Ctx.getID(V), V ? V->getType() : SILType(), V->getOwnershipKind()}; } SILValuePrinterInfo getIDAndTypeAndOwnership(SILFunctionArgument *arg) { return {Ctx.getID(arg), arg->getType(), arg->getOwnershipKind(), - arg->isNoImplicitCopy()}; + arg->isNoImplicitCopy(), arg->getLifetimeAnnotation()}; } //===--------------------------------------------------------------------===// diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 24c8655dfc7cf..e7de6212bb421 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -310,19 +310,19 @@ namespace swift { return parseASTType(result, genericSig, genericParams); } - bool parseIsNoImplicitCopy() { + Optional parseOptionalAttribute(ArrayRef expected) { // We parse here @ . if (P.Tok.getKind() != tok::at_sign) - return false; + return llvm::None; - // Make sure our text is no implicit copy. - if (P.peekToken().getText() != "noImplicitCopy") - return false; + auto name = P.peekToken().getText(); + if (!is_contained(expected, name)) + return llvm::None; // Ok, we can do this. P.consumeToken(tok::at_sign); P.consumeToken(tok::identifier); - return true; + return name; } bool parseSILOwnership(ValueOwnershipKind &OwnershipKind) { @@ -6369,7 +6369,31 @@ bool SILParser::parseSILBasicBlock(SILBuilder &B) { P.parseToken(tok::colon, diag::expected_sil_colon_value_ref)) return true; - bool foundNoImplicitCopy = parseIsNoImplicitCopy(); + bool foundNoImplicitCopy = false; + bool foundLexical = false; + bool foundEagerMove = false; + while (auto attributeName = parseOptionalAttribute( + {"noImplicitCopy", "_lexical", "_eagerMove"})) { + if (*attributeName == "noImplicitCopy") + foundNoImplicitCopy = true; + else if (*attributeName == "_lexical") + foundLexical = true; + else if (*attributeName == "_eagerMove") + foundEagerMove = true; + else { + llvm_unreachable("Unexpected attribute!"); + } + } + + LifetimeAnnotation lifetime = LifetimeAnnotation::None; + if (foundEagerMove && foundLexical) { + P.diagnose(NameLoc, diag::sil_arg_both_lexical_and_eagerMove); + return true; + } else if (foundEagerMove) { + lifetime = LifetimeAnnotation::EagerMove; + } else if (foundLexical) { + lifetime = LifetimeAnnotation::Lexical; + } // If SILOwnership is enabled and we are not assuming that we are // parsing unqualified SIL, look for printed value ownership kinds. @@ -6384,6 +6408,7 @@ bool SILParser::parseSILBasicBlock(SILBuilder &B) { if (IsEntry) { auto *fArg = BB->createFunctionArgument(Ty); fArg->setNoImplicitCopy(foundNoImplicitCopy); + fArg->setLifetimeAnnotation(lifetime); Arg = fArg; // Today, we construct the ownership kind straight from the function diff --git a/test/SIL/Parser/function_argument_lifetime_annotation.sil b/test/SIL/Parser/function_argument_lifetime_annotation.sil new file mode 100644 index 0000000000000..71c517d4e27e7 --- /dev/null +++ b/test/SIL/Parser/function_argument_lifetime_annotation.sil @@ -0,0 +1,46 @@ +// RUN: %target-sil-opt -enable-objc-interop -enable-lexical-lifetimes=true -enable-sil-verify-all=true %s | %target-sil-opt -enable-objc-interop -enable-lexical-lifetimes=true -enable-sil-verify-all=true | %FileCheck %s + +sil_stage canonical + +class C {} + +// CHECK-LABEL: sil [ossa] @one_arg_eager_move : {{.*}} { +// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove @owned $C): +// CHECK-LABEL: } // end sil function 'one_arg_eager_move' +sil [ossa] @one_arg_eager_move : $@convention(thin) (@owned C) -> () { +bb0(%instance : @_eagerMove @owned $C): + destroy_value %instance : $C + %retval = tuple() + return %retval : $() +} + +// CHECK-LABEL: sil [ossa] @one_arg_eager_move_and_no_implicit_copy : {{.*}} { +// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @noImplicitCopy @_eagerMove @owned $C): +// CHECK-LABEL: } // end sil function 'one_arg_eager_move_and_no_implicit_copy' +sil [ossa] @one_arg_eager_move_and_no_implicit_copy : $(@owned C) -> () { +bb0(%instance : @noImplicitCopy @_eagerMove @owned $C): + destroy_value %instance : $C + %retval = tuple() + return %retval : $() +} + +// CHECK-LABEL: sil [ossa] @one_arg_lexical : {{.*}} { +// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_lexical @owned $C): +// CHECK-LABEL: } // end sil function 'one_arg_lexical' +sil [ossa] @one_arg_lexical : $@convention(thin) (@owned C) -> () { +bb0(%instance : @_lexical @owned $C): + destroy_value %instance : $C + %retval = tuple() + return %retval : $() +} + +// CHECK-LABEL: sil [ossa] @one_arg_lexical_and_no_implicit_copy : {{.*}} { +// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @noImplicitCopy @_lexical @owned $C): +// CHECK-LABEL: } // end sil function 'one_arg_lexical_and_no_implicit_copy' +sil [ossa] @one_arg_lexical_and_no_implicit_copy : $@convention(thin) (@owned C) -> () { +bb0(%instance : @noImplicitCopy @_lexical @owned $C): + destroy_value %instance : $C + %retval = tuple() + return %retval : $() +} + From dc3106f3f2664d9c6cb60e6bbc6c4d6b147c7714 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 11 Aug 2022 14:27:06 -0700 Subject: [PATCH 258/491] [Serialization] Explicit function arg lifetimes. --- lib/Serialization/DeserializeSIL.cpp | 2 ++ lib/Serialization/ModuleFormat.h | 2 +- lib/Serialization/SerializeSIL.cpp | 3 +- .../function_argument_lifetime_annotation.sil | 30 +++++++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 test/SIL/Serialization/function_argument_lifetime_annotation.sil diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 50876a02df8d9..a4f144f8e2776 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -946,6 +946,8 @@ SILBasicBlock *SILDeserializer::readSILBasicBlock(SILFunction *Fn, auto *fArg = CurrentBB->createFunctionArgument(SILArgTy); bool isNoImplicitCopy = (Args[I + 1] >> 16) & 0x1; fArg->setNoImplicitCopy(isNoImplicitCopy); + auto lifetime = (LifetimeAnnotation::Case)((Args[I + 1] >> 17) & 0x3); + fArg->setLifetimeAnnotation(lifetime); Arg = fArg; } else { auto OwnershipKind = ValueOwnershipKind((Args[I + 1] >> 8) & 0xF); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 5cac55d804d67..eed474946e0dc 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 703; // remove builtin unsafe guaran +const uint16_t SWIFTMODULE_VERSION_MINOR = 704; // _eagerMove/_lexical function argument attributes /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index e4ef7a356a8df..5d187083c4cf1 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -626,8 +626,9 @@ void SILSerializer::writeSILBasicBlock(const SILBasicBlock &BB) { packedMetadata |= unsigned(SA->getOwnershipKind()) << 8; // 8 bits if (auto *SFA = dyn_cast(SA)) { packedMetadata |= unsigned(SFA->isNoImplicitCopy()) << 16; // 1 bit + packedMetadata |= unsigned(SFA->getLifetimeAnnotation()) << 17; // 2 bits } - // Used: 17 bits. Free: 15. + // Used: 19 bits. Free: 13. // // TODO: We should be able to shrink the packed metadata of the first two. Args.push_back(packedMetadata); diff --git a/test/SIL/Serialization/function_argument_lifetime_annotation.sil b/test/SIL/Serialization/function_argument_lifetime_annotation.sil new file mode 100644 index 0000000000000..b8ff47130a13f --- /dev/null +++ b/test/SIL/Serialization/function_argument_lifetime_annotation.sil @@ -0,0 +1,30 @@ +// First parse this and then emit a *.sib. Then read in the *.sib, then recreate + +// RUN: %empty-directory(%t) +// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name eager_move +// RUN: %target-sil-opt %t/tmp.sib -module-name eager_move | %FileCheck %s + +sil_stage canonical + +class C {} + +// CHECK-LABEL: sil [serialized] [ossa] @one_arg_eager_move : {{.*}} { +// CHECK: bb0(%0 : @_eagerMove @owned $C): +// CHECK: } // end sil function 'one_arg_eager_move' +sil [serialized] [ossa] @one_arg_eager_move : $@convention(thin) (@owned C) -> () { +bb0(%instance : @_eagerMove @owned $C): + destroy_value %instance : $C + %retval = tuple() + return %retval : $() +} + +// CHECK-LABEL: sil [serialized] [ossa] @one_arg_lexical : {{.*}} { +// CHECK: bb0(%0 : @_lexical @owned $C): +// CHECK: } // end sil function 'one_arg_lexical' +sil [serialized] [ossa] @one_arg_lexical : $@convention(thin) (@owned C) -> () { +bb0(%instance : @_lexical @owned $C): + destroy_value %instance : $C + %retval = tuple() + return %retval : $() +} + From 0383415d5aac0073738cfcb8d55bd44a8745c26e Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 11 Aug 2022 15:56:52 -0700 Subject: [PATCH 259/491] [SILInliner] Respect explicit argument lifetimes. --- lib/SILOptimizer/Utils/SILInliner.cpp | 16 +- test/SILOptimizer/inline_lifetime.sil | 434 ++++++++++++++++++++++++++ 2 files changed, 445 insertions(+), 5 deletions(-) diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp index 7a89f2fd92f15..56c04b8160859 100644 --- a/lib/SILOptimizer/Utils/SILInliner.cpp +++ b/lib/SILOptimizer/Utils/SILInliner.cpp @@ -286,7 +286,8 @@ class SILInlineCloner void cloneInline(ArrayRef AppliedArgs); protected: - SILValue borrowFunctionArgument(SILValue callArg, FullApplySite AI); + SILValue borrowFunctionArgument(SILValue callArg, FullApplySite AI, + unsigned index); void visitDebugValueInst(DebugValueInst *Inst); void visitHopToExecutorInst(HopToExecutorInst *Inst); @@ -466,7 +467,7 @@ void SILInlineCloner::cloneInline(ArrayRef AppliedArgs) { } else { // Insert begin/end borrow for guaranteed arguments. if (paramInfo.isGuaranteed()) { - if (SILValue newValue = borrowFunctionArgument(callArg, Apply)) { + if (SILValue newValue = borrowFunctionArgument(callArg, Apply, idx)) { callArg = newValue; borrowedArgs[idx] = true; } @@ -612,7 +613,8 @@ void SILInlineCloner::postFixUp(SILFunction *calleeFunction) { } SILValue SILInlineCloner::borrowFunctionArgument(SILValue callArg, - FullApplySite AI) { + FullApplySite AI, + unsigned index) { auto &mod = Apply.getFunction()->getModule(); auto enableLexicalLifetimes = mod.getASTContext().SILOpts.supportsLexicalLifetimes(mod); @@ -631,9 +633,13 @@ SILValue SILInlineCloner::borrowFunctionArgument(SILValue callArg, return SILValue(); } + SILFunctionArgument *argument = cast( + getCalleeFunction()->getEntryBlock()->getArgument(index)); + SILBuilderWithScope beginBuilder(AI.getInstruction(), getBuilder()); - return beginBuilder.createBeginBorrow(AI.getLoc(), callArg, - /*isLexical=*/enableLexicalLifetimes); + auto isLexical = + enableLexicalLifetimes && argument->getLifetime().isLexical(); + return beginBuilder.createBeginBorrow(AI.getLoc(), callArg, isLexical); } void SILInlineCloner::visitDebugValueInst(DebugValueInst *Inst) { diff --git a/test/SILOptimizer/inline_lifetime.sil b/test/SILOptimizer/inline_lifetime.sil index fccd1618e9b31..298eeebd6089e 100644 --- a/test/SILOptimizer/inline_lifetime.sil +++ b/test/SILOptimizer/inline_lifetime.sil @@ -4,6 +4,62 @@ import Swift class C {} +@_eagerMove +class EagerC {} + +struct InferredEagerD1S1 { + var c1: EagerC + var c2: EagerC +} + +struct InferredEagerD1S2 { + @_eagerMove var c1: C + var c2: EagerC +} + +struct InferredEagerD1S3 { + @_eagerMove var c1: C + @_eagerMove let c2: C +} + +struct InferredEagerD1S4 { + @_eagerMove var c1: (one: C, two: C) + @_eagerMove let c2: C +} + +struct InferredEagerD2S1 { + var i1: InferredEagerD1S1 + var i2: InferredEagerD1S2 + var i3: InferredEagerD1S3 + var i4: InferredEagerD1S4 +} + +@_lexical +struct LexicalS { + var i: InferredEagerD2S1 +} + +struct InferredLexicalD1S1 { + var c1: C + var c2: C + var c3: C + var c4: C +} + +struct InferredLexicalD1S2 { + @_lexical var i: InferredEagerD2S1 +} + +struct InferredLexicalD1S3 { + @_lexical var i: InferredEagerD2S1 + var j: InferredEagerD2S1 +} + +struct InferredLexicalD1S4 { + var i: C + var j: InferredEagerD2S1 +} + struct S {} //////////////////////////////////////////////////////////////////////////////// @@ -19,12 +75,146 @@ entry(%instance : @owned $C): return %retval : $() } +sil [ossa] [always_inline] @callee_owned_eager_move : $@convention(thin) (@owned C) -> () { +entry(%instance : @_eagerMove @owned $C): + destroy_value %instance : $C + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_owned_eager_move__type_annotation : $@convention(thin) (@owned EagerC) -> () { +entry(%instance : @owned $EagerC): + destroy_value %instance : $EagerC + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_owned_eager_move__type_inferred_d1_s1 : $@convention(thin) (@owned InferredEagerD1S1) -> () { +entry(%instance : @owned $InferredEagerD1S1): + destroy_value %instance : $InferredEagerD1S1 + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_owned_eager_move__type_inferred_d1_s2 : $@convention(thin) (@owned InferredEagerD1S2) -> () { +entry(%instance : @owned $InferredEagerD1S2): + destroy_value %instance : $InferredEagerD1S2 + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_owned_eager_move__type_inferred_d1_s3 : $@convention(thin) (@owned InferredEagerD1S3) -> () { +entry(%instance : @owned $InferredEagerD1S3): + destroy_value %instance : $InferredEagerD1S3 + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_owned_eager_move__type_inferred_d1_s4 : $@convention(thin) (@owned InferredEagerD1S4) -> () { +entry(%instance : @owned $InferredEagerD1S4): + destroy_value %instance : $InferredEagerD1S4 + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_owned_eager_move__type_inferred_d2_s1 : $@convention(thin) (@owned InferredEagerD2S1) -> () { +entry(%instance : @owned $InferredEagerD2S1): + destroy_value %instance : $InferredEagerD2S1 + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_owned_lexical : $@convention(thin) (@owned InferredEagerD2S1) -> () { +entry(%instance : @_lexical @owned $InferredEagerD2S1): + destroy_value %instance : $InferredEagerD2S1 + %retval = tuple () + return %retval : $() +} + sil [ossa] [always_inline] @callee_guaranteed : $@convention(thin) (@guaranteed C) -> () { entry(%instance : @guaranteed $C): %retval = tuple () return %retval : $() } +sil [ossa] [always_inline] @callee_guaranteed_eager_move : $@convention(thin) (@guaranteed C) -> () { +entry(%instance : @_eagerMove @guaranteed $C): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_eager_move__type_annotation : $@convention(thin) (@guaranteed EagerC) -> () { +entry(%instance : @guaranteed $EagerC): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_eager_move__type_inferred_d1_s1 : $@convention(thin) (@guaranteed InferredEagerD1S1) -> () { +entry(%instance : @guaranteed $InferredEagerD1S1): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_eager_move__type_inferred_d1_s2 : $@convention(thin) (@guaranteed InferredEagerD1S2) -> () { +entry(%instance : @guaranteed $InferredEagerD1S2): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_eager_move__type_inferred_d1_s3 : $@convention(thin) (@guaranteed InferredEagerD1S3) -> () { +entry(%instance : @guaranteed $InferredEagerD1S3): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_eager_move__type_inferred_d1_s4 : $@convention(thin) (@guaranteed InferredEagerD1S4) -> () { +entry(%instance : @guaranteed $InferredEagerD1S4): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_eager_move__type_inferred_d2_s1 : $@convention(thin) (@guaranteed InferredEagerD2S1) -> () { +entry(%instance : @guaranteed $InferredEagerD2S1): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_lexical : $@convention(thin) (@guaranteed InferredEagerD2S1) -> () { +entry(%instance : @_lexical @guaranteed $InferredEagerD2S1): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_lexical__type_annotation : $@convention(thin) (@guaranteed LexicalS) -> () { +entry(%instance : @guaranteed $LexicalS): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_lexical__type_inferred_d1_s1 : $@convention(thin) (@guaranteed InferredLexicalD1S1) -> () { +entry(%instance : @guaranteed $InferredLexicalD1S1): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_lexical__type_inferred_d1_s2 : $@convention(thin) (@guaranteed InferredLexicalD1S2) -> () { +entry(%instance : @guaranteed $InferredLexicalD1S2): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_lexical__type_inferred_d1_s3 : $@convention(thin) (@guaranteed InferredLexicalD1S3) -> () { +entry(%instance : @guaranteed $InferredLexicalD1S3): + %retval = tuple () + return %retval : $() +} + +sil [ossa] [always_inline] @callee_guaranteed_lexical__type_inferred_d1_s4 : $@convention(thin) (@guaranteed InferredLexicalD1S4) -> () { +entry(%instance : @guaranteed $InferredLexicalD1S4): + %retval = tuple () + return %retval : $() +} + sil [ossa] [always_inline] @callee_trivial : $@convention(thin) (S) -> () { entry(%instance : $S): %retval = tuple () @@ -55,6 +245,86 @@ entry(%instance : @owned $C): return %result : $() } +// CHECK-LABEL: sil [ossa] @caller_owned_callee_owned_eager_move : $@convention(thin) (@owned C) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_owned_eager_move' +sil [ossa] @caller_owned_callee_owned_eager_move : $@convention(thin) (@owned C) -> () { +entry(%instance : @owned $C): + %callee_owned = function_ref @callee_owned_eager_move : $@convention(thin) (@owned C) -> () + %result = apply %callee_owned(%instance) : $@convention(thin) (@owned C) -> () + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_owned_eager_move__type_annotation : {{.*}} { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_owned_eager_move__type_annotation' +sil [ossa] @caller_owned_callee_owned_eager_move__type_annotation : $@convention(thin) (@owned EagerC) -> () { +entry(%instance : @owned $EagerC): + %callee_owned = function_ref @callee_owned_eager_move__type_annotation : $@convention(thin) (@owned EagerC) -> () + %result = apply %callee_owned(%instance) : $@convention(thin) (@owned EagerC) -> () + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d1_s1 : {{.*}} { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_owned_eager_move__type_inferred_d1_s1' +sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d1_s1 : $@convention(thin) (@owned InferredEagerD1S1) -> () { +entry(%instance : @owned $InferredEagerD1S1): + %callee_owned = function_ref @callee_owned_eager_move__type_inferred_d1_s1 : $@convention(thin) (@owned InferredEagerD1S1) -> () + %result = apply %callee_owned(%instance) : $@convention(thin) (@owned InferredEagerD1S1) -> () + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d1_s2 : {{.*}} { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_owned_eager_move__type_inferred_d1_s2' +sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d1_s2 : $@convention(thin) (@owned InferredEagerD1S2) -> () { +entry(%instance : @owned $InferredEagerD1S2): + %callee_owned = function_ref @callee_owned_eager_move__type_inferred_d1_s2 : $@convention(thin) (@owned InferredEagerD1S2) -> () + %result = apply %callee_owned(%instance) : $@convention(thin) (@owned InferredEagerD1S2) -> () + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d1_s3 : {{.*}} { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_owned_eager_move__type_inferred_d1_s3' +sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d1_s3 : $@convention(thin) (@owned InferredEagerD1S3) -> () { +entry(%instance : @owned $InferredEagerD1S3): + %callee_owned = function_ref @callee_owned_eager_move__type_inferred_d1_s3 : $@convention(thin) (@owned InferredEagerD1S3) -> () + %result = apply %callee_owned(%instance) : $@convention(thin) (@owned InferredEagerD1S3) -> () + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d1_s4 : {{.*}} { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_owned_eager_move__type_inferred_d1_s4' +sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d1_s4 : $@convention(thin) (@owned InferredEagerD1S4) -> () { +entry(%instance : @owned $InferredEagerD1S4): + %callee_owned = function_ref @callee_owned_eager_move__type_inferred_d1_s4 : $@convention(thin) (@owned InferredEagerD1S4) -> () + %result = apply %callee_owned(%instance) : $@convention(thin) (@owned InferredEagerD1S4) -> () + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d2_s1 : {{.*}} { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_owned_eager_move__type_inferred_d2_s1' +sil [ossa] @caller_owned_callee_owned_eager_move__type_inferred_d2_s1 : $@convention(thin) (@owned InferredEagerD2S1) -> () { +entry(%instance : @owned $InferredEagerD2S1): + %callee_owned = function_ref @callee_owned_eager_move__type_inferred_d2_s1 : $@convention(thin) (@owned InferredEagerD2S1) -> () + %result = apply %callee_owned(%instance) : $@convention(thin) (@owned InferredEagerD2S1) -> () + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_owned_lexical : {{.*}} { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_owned_lexical' +sil [ossa] @caller_owned_callee_owned_lexical : $@convention(thin) (@owned InferredEagerD2S1) -> () { +entry(%instance : @owned $InferredEagerD2S1): + %callee_owned = function_ref @callee_owned_lexical : $@convention(thin) (@owned InferredEagerD2S1) -> () + %result = apply %callee_owned(%instance) : $@convention(thin) (@owned InferredEagerD2S1) -> () + return %result : $() +} + // CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed : $@convention(thin) (@owned C) -> () { // CHECK: {{bb[^,]+}}([[INSTANCE:%[^,]+]] : @owned $C): // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INSTANCE]] @@ -71,6 +341,149 @@ entry(%instance : @owned $C): return %result : $() } +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_eager_move : $@convention(thin) (@owned C) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_eager_move' +sil [ossa] @caller_owned_callee_guaranteed_eager_move : $@convention(thin) (@owned C) -> () { +entry(%instance : @owned $C): + %callee_guaranteed = function_ref @callee_guaranteed_eager_move : $@convention(thin) (@guaranteed C) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed C) -> () + destroy_value %instance : $C + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_annotation : $@convention(thin) (@owned EagerC) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_eager_move__type_annotation' +sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_annotation : $@convention(thin) (@owned EagerC) -> () { +entry(%instance : @owned $EagerC): + %callee_guaranteed = function_ref @callee_guaranteed_eager_move__type_annotation : $@convention(thin) (@guaranteed EagerC) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed EagerC) -> () + destroy_value %instance : $EagerC + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s1 : $@convention(thin) (@owned InferredEagerD1S1) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s1' +sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s1 : $@convention(thin) (@owned InferredEagerD1S1) -> () { +entry(%instance : @owned $InferredEagerD1S1): + %callee_guaranteed = function_ref @callee_guaranteed_eager_move__type_inferred_d1_s1 : $@convention(thin) (@guaranteed InferredEagerD1S1) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredEagerD1S1) -> () + destroy_value %instance : $InferredEagerD1S1 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s2 : $@convention(thin) (@owned InferredEagerD1S2) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s2' +sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s2 : $@convention(thin) (@owned InferredEagerD1S2) -> () { +entry(%instance : @owned $InferredEagerD1S2): + %callee_guaranteed = function_ref @callee_guaranteed_eager_move__type_inferred_d1_s2 : $@convention(thin) (@guaranteed InferredEagerD1S2) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredEagerD1S2) -> () + destroy_value %instance : $InferredEagerD1S2 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s3 : $@convention(thin) (@owned InferredEagerD1S3) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s3' +sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s3 : $@convention(thin) (@owned InferredEagerD1S3) -> () { +entry(%instance : @owned $InferredEagerD1S3): + %callee_guaranteed = function_ref @callee_guaranteed_eager_move__type_inferred_d1_s3 : $@convention(thin) (@guaranteed InferredEagerD1S3) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredEagerD1S3) -> () + destroy_value %instance : $InferredEagerD1S3 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s4 : $@convention(thin) (@owned InferredEagerD1S4) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s4' +sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d1_s4 : $@convention(thin) (@owned InferredEagerD1S4) -> () { +entry(%instance : @owned $InferredEagerD1S4): + %callee_guaranteed = function_ref @callee_guaranteed_eager_move__type_inferred_d1_s4 : $@convention(thin) (@guaranteed InferredEagerD1S4) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredEagerD1S4) -> () + destroy_value %instance : $InferredEagerD1S4 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d2_s1 : $@convention(thin) (@owned InferredEagerD2S1) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_eager_move__type_inferred_d2_s1' +sil [ossa] @caller_owned_callee_guaranteed_eager_move__type_inferred_d2_s1 : $@convention(thin) (@owned InferredEagerD2S1) -> () { +entry(%instance : @owned $InferredEagerD2S1): + %callee_guaranteed = function_ref @callee_guaranteed_eager_move__type_inferred_d2_s1 : $@convention(thin) (@guaranteed InferredEagerD2S1) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredEagerD2S1) -> () + destroy_value %instance : $InferredEagerD2S1 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_lexical : {{.*}} { +// CHECK: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_lexical' +sil [ossa] @caller_owned_callee_guaranteed_lexical : $@convention(thin) (@owned InferredEagerD2S1) -> () { +entry(%instance : @owned $InferredEagerD2S1): + %callee_guaranteed = function_ref @callee_guaranteed_lexical : $@convention(thin) (@guaranteed InferredEagerD2S1) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredEagerD2S1) -> () + destroy_value %instance : $InferredEagerD2S1 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_lexical__type_annotation : {{.*}} { +// CHECK: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_lexical__type_annotation' +sil [ossa] @caller_owned_callee_guaranteed_lexical__type_annotation : $@convention(thin) (@owned LexicalS) -> () { +entry(%instance : @owned $LexicalS): + %callee_guaranteed = function_ref @callee_guaranteed_lexical__type_annotation : $@convention(thin) (@guaranteed LexicalS) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed LexicalS) -> () + destroy_value %instance : $LexicalS + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_lexical__type_inferred_d1_s1 : {{.*}} { +// CHECK: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_lexical__type_inferred_d1_s1' +sil [ossa] @caller_owned_callee_guaranteed_lexical__type_inferred_d1_s1 : $@convention(thin) (@owned InferredLexicalD1S1) -> () { +entry(%instance : @owned $InferredLexicalD1S1): + %callee_guaranteed = function_ref @callee_guaranteed_lexical__type_inferred_d1_s1 : $@convention(thin) (@guaranteed InferredLexicalD1S1) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredLexicalD1S1) -> () + destroy_value %instance : $InferredLexicalD1S1 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_lexical__type_inferred_d1_s2 : {{.*}} { +// CHECK: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_lexical__type_inferred_d1_s2' +sil [ossa] @caller_owned_callee_guaranteed_lexical__type_inferred_d1_s2 : $@convention(thin) (@owned InferredLexicalD1S2) -> () { +entry(%instance : @owned $InferredLexicalD1S2): + %callee_guaranteed = function_ref @callee_guaranteed_lexical__type_inferred_d1_s2 : $@convention(thin) (@guaranteed InferredLexicalD1S2) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredLexicalD1S2) -> () + destroy_value %instance : $InferredLexicalD1S2 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_lexical__type_inferred_d1_s3 : {{.*}} { +// CHECK: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_lexical__type_inferred_d1_s3' +sil [ossa] @caller_owned_callee_guaranteed_lexical__type_inferred_d1_s3 : $@convention(thin) (@owned InferredLexicalD1S3) -> () { +entry(%instance : @owned $InferredLexicalD1S3): + %callee_guaranteed = function_ref @callee_guaranteed_lexical__type_inferred_d1_s3 : $@convention(thin) (@guaranteed InferredLexicalD1S3) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredLexicalD1S3) -> () + destroy_value %instance : $InferredLexicalD1S3 + return %result : $() +} + +// CHECK-LABEL: sil [ossa] @caller_owned_callee_guaranteed_lexical__type_inferred_d1_s4 : {{.*}} { +// CHECK: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_owned_callee_guaranteed_lexical__type_inferred_d1_s4' +sil [ossa] @caller_owned_callee_guaranteed_lexical__type_inferred_d1_s4 : $@convention(thin) (@owned InferredLexicalD1S4) -> () { +entry(%instance : @owned $InferredLexicalD1S4): + %callee_guaranteed = function_ref @callee_guaranteed_lexical__type_inferred_d1_s4 : $@convention(thin) (@guaranteed InferredLexicalD1S4) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed InferredLexicalD1S4) -> () + destroy_value %instance : $InferredLexicalD1S4 + return %result : $() +} + // CHECK-LABEL: sil [ossa] @caller_guaranteed_callee_guaranteed : $@convention(thin) (@guaranteed C) -> () { // CHECK: {{bb[^,]+}}([[INSTANCE:%[^,]+]] : @guaranteed $C): // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INSTANCE]] @@ -85,6 +498,16 @@ entry(%instance : @guaranteed $C): return %result : $() } +// CHECK-LABEL: sil [ossa] @caller_guaranteed_callee_guaranteed_eager_move : $@convention(thin) (@guaranteed C) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_guaranteed_callee_guaranteed_eager_move' +sil [ossa] @caller_guaranteed_callee_guaranteed_eager_move : $@convention(thin) (@guaranteed C) -> () { +entry(%instance : @guaranteed $C): + %callee_guaranteed = function_ref @callee_guaranteed_eager_move : $@convention(thin) (@guaranteed C) -> () + %result = apply %callee_guaranteed(%instance) : $@convention(thin) (@guaranteed C) -> () + return %result : $() +} + // CHECK-LABEL: sil [ossa] @caller_guaranteed_callee_owned : $@convention(thin) (@guaranteed C) -> () { // CHECK-NOT: begin_borrow [lexical] // CHECK-LABEL: } // end sil function 'caller_guaranteed_callee_owned' @@ -96,6 +519,17 @@ entry(%instance : @guaranteed $C): return %result : $() } +// CHECK-LABEL: sil [ossa] @caller_guaranteed_callee_owned_eager_move : $@convention(thin) (@guaranteed C) -> () { +// CHECK-NOT: begin_borrow [lexical] +// CHECK-LABEL: } // end sil function 'caller_guaranteed_callee_owned_eager_move' +sil [ossa] @caller_guaranteed_callee_owned_eager_move : $@convention(thin) (@guaranteed C) -> () { +entry(%instance : @guaranteed $C): + %copy = copy_value %instance : $C + %callee_owned = function_ref @callee_owned_eager_move : $@convention(thin) (@owned C) -> () + %result = apply %callee_owned(%copy) : $@convention(thin) (@owned C) -> () + return %result : $() +} + // CHECK-LABEL: sil [ossa] @caller_trivial_callee_trivial : $@convention(thin) (S) -> () { // CHECK: {{bb[^,]+}}({{%[^,]+}} : $S): // CHECK: [[RETVAL:%[^,]+]] = tuple () From b3ae13ddbe56df8c788dfd52f8e61c87d17663d2 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Tue, 16 Aug 2022 10:49:58 -0700 Subject: [PATCH 260/491] [Sema] Added _eagerMove and _lexical attributes. The new attributes affect how the lifetimes of values may be shortened. --- docs/ReferenceGuides/UnderscoredAttributes.md | 35 ++++++++++++++++++- include/swift/AST/Attr.def | 14 ++++++-- include/swift/AST/Decl.h | 10 ++++++ include/swift/AST/DiagnosticsSema.def | 4 +++ lib/AST/ASTDumper.cpp | 21 +++++++++++ lib/Sema/TypeCheckAttr.cpp | 13 +++++++ lib/Sema/TypeCheckDeclOverride.cpp | 3 ++ test/attr/lexical.swift | 31 ++++++++++++++++ 8 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 test/attr/lexical.swift diff --git a/docs/ReferenceGuides/UnderscoredAttributes.md b/docs/ReferenceGuides/UnderscoredAttributes.md index 3f4c1aae786e1..8146f5d491878 100644 --- a/docs/ReferenceGuides/UnderscoredAttributes.md +++ b/docs/ReferenceGuides/UnderscoredAttributes.md @@ -131,6 +131,23 @@ library), instead of at an arbitrary point in time. For more details, see the forum post on [dynamic method replacement](https://forums.swift.org/t/dynamic-method-replacement/16619). +## `@_eagerMove` + +When applied to a value, indicates that the value's lifetime is _not_ lexical, +that releases of the value may be hoisted without respect to deinit barriers. + +When applied to a type, indicates that all values which are _statically_ +instances of that type are themselves `@_eagerMove` as above, unless overridden +with `@_lexical`. + +Aggregates all of whose fields are `@_eagerMove` or trivial are inferred to be +`@_eagerMove`. + +Note that a value of an `@_eagerMove` type that is passed to a generic API (to a +parameter not annotated `@_eagerMove` will, in that generic function's context, +not be statically an instance of the `@_eagerMove` type. As a result it will +have a lexical lifetime in that function. + ## `@_effects(effectname)` Tells the compiler that the implementation of the defined function is limited @@ -473,12 +490,28 @@ initializers from its superclass. This implies that all designated initializers overridden. This attribute is often printed alongside `@_hasMissingDesignatedInitializers` in this case. +## `@_lexical` + +When applied to a value, indicates that the value's lifetime is lexical, that +releases of the value may not be hoisted over deinit barriers. + +This is the default behavior, unless the value's type is annotated +`@_eagerMove`, in which case this attribute overrides that type-level +annotation. + +When applied to a type, indicates that all values which are instances of that +type are themselves `@_lexical` as above. + +This is the default behavior, unless the type annotated is an aggregate that +consists entirely of `@_eagerMove` or trivial values, in which case the +attribute overrides the inferred type-level annotation. + ## `@_marker` Indicates that a protocol is a marker protocol. Marker protocols represent some meaningful property at compile-time but have no runtime representation. -For more details, see [SE-0302](https://github.com/apple/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md#marker-protocols), which introduces marker protocols. +For more details, see [](https://github.com/apple/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md#marker-protocols), which introduces marker protocols. At the moment, the language only has one marker protocol: `Sendable`. Fun fact: Rust has a very similar concept called diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def index 8ce4e6628dc71..29f4ba97643c3 100644 --- a/include/swift/AST/Attr.def +++ b/include/swift/AST/Attr.def @@ -662,7 +662,12 @@ SIMPLE_DECL_ATTR(_inheritActorContext, InheritActorContext, ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove, 116) -// 117 was 'spawn' and is now unused +SIMPLE_DECL_ATTR(_eagerMove, EagerMove, + UserInaccessible | + ABIStableToAdd | ABIStableToRemove | + APIStableToAdd | APIStableToRemove | + OnParam | OnVar | OnNominalType, + 117) CONTEXTUAL_SIMPLE_DECL_ATTR(distributed, DistributedActor, DeclModifier | OnClass | OnFunc | OnAccessor | OnVar | @@ -670,7 +675,12 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(distributed, DistributedActor, APIBreakingToAdd | APIBreakingToRemove, 118) -// 119 is unused +SIMPLE_DECL_ATTR(_lexical, Lexical, + UserInaccessible | + ABIStableToAdd | ABIStableToRemove | + APIStableToAdd | APIStableToRemove | + OnParam | OnVar | OnNominalType, + 119) SIMPLE_DECL_ATTR(_assemblyVision, EmitAssemblyVisionRemarks, OnFunc | UserInaccessible | NotSerialized | OnNominalType | diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 42883114f659d..11f3ce7117ea2 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -29,6 +29,7 @@ #include "swift/AST/GenericParamKey.h" #include "swift/AST/IfConfigClause.h" #include "swift/AST/LayoutConstraint.h" +#include "swift/AST/LifetimeAnnotation.h" #include "swift/AST/ReferenceCounting.h" #include "swift/AST/RequirementSignature.h" #include "swift/AST/StorageImpl.h" @@ -2713,6 +2714,15 @@ class ValueDecl : public Decl { /// 'func foo(Int) -> () -> Self?'. GenericParameterReferenceInfo findExistentialSelfReferences( Type baseTy, bool treatNonResultCovariantSelfAsInvariant) const; + + LifetimeAnnotation getLifetimeAnnotation() const { + auto &attrs = getAttrs(); + if (attrs.hasAttribute()) + return LifetimeAnnotation::EagerMove; + if (attrs.hasAttribute()) + return LifetimeAnnotation::Lexical; + return LifetimeAnnotation::None; + } }; /// This is a common base class for declarations which declare a type. diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 3e19342d7982b..fd23cb27749e9 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -3207,6 +3207,10 @@ ERROR(reasync_without_async_parameter,none, ERROR(inherits_executor_without_async,none, "non-async functions cannot inherit an executor", ()) +ERROR(eagermove_and_lexical_combined,none, + "@_eagerMove and @_lexical attributes are alternate styles of lifetimes " + "and can't be combined", ()) + ERROR(autoclosure_function_type,none, "@autoclosure attribute only applies to function types", ()) diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index fc0cd7595fe39..5f95c2dc2d721 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -690,6 +690,16 @@ namespace { OS << attr->getReplacedFunctionName(); OS << "\")"; } + switch (VD->getLifetimeAnnotation()) { + case LifetimeAnnotation::EagerMove: + OS << " _eagerMove"; + break; + case LifetimeAnnotation::Lexical: + OS << " _lexical"; + break; + case LifetimeAnnotation::None: + break; + } } void printCommon(NominalTypeDecl *NTD, const char *Name, @@ -958,6 +968,17 @@ namespace { if (P->getAttrs().hasAttribute()) OS << " nonEphemeral"; + switch (P->getLifetimeAnnotation()) { + case LifetimeAnnotation::EagerMove: + OS << " _eagerMove"; + break; + case LifetimeAnnotation::Lexical: + OS << " _lexical"; + break; + case LifetimeAnnotation::None: + break; + } + if (P->getAttrs().hasAttribute()) OS << " noImplicitCopy"; diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 08a6afed1c123..7951d5616109a 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -318,6 +318,9 @@ class AttributeChecker : public AttributeVisitor { void visitUnsafeInheritExecutorAttr(UnsafeInheritExecutorAttr *attr); + void visitEagerMoveAttr(EagerMoveAttr *attr); + void visitLexicalAttr(LexicalAttr *attr); + void visitCompilerInitializedAttr(CompilerInitializedAttr *attr); void checkBackDeployAttrs(ArrayRef Attrs); @@ -6217,6 +6220,16 @@ void AttributeChecker::visitUnsafeInheritExecutorAttr( } } +void AttributeChecker::visitEagerMoveAttr(EagerMoveAttr *attr) {} + +void AttributeChecker::visitLexicalAttr(LexicalAttr *attr) { + // @_lexical and @_eagerMove are opposites and can't be combined. + if (D->getAttrs().hasAttribute()) { + diagnoseAndRemoveAttr(attr, diag::eagermove_and_lexical_combined); + return; + } +} + void AttributeChecker::visitCompilerInitializedAttr( CompilerInitializedAttr *attr) { auto var = cast(D); diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index bc497b8abf133..8a9f2c0976050 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1614,6 +1614,9 @@ namespace { UNINTERESTING_ATTR(UnsafeInheritExecutor) UNINTERESTING_ATTR(CompilerInitialized) UNINTERESTING_ATTR(AlwaysEmitConformanceMetadata) + + UNINTERESTING_ATTR(EagerMove) + UNINTERESTING_ATTR(Lexical) #undef UNINTERESTING_ATTR void visitAvailableAttr(AvailableAttr *attr) { diff --git a/test/attr/lexical.swift b/test/attr/lexical.swift new file mode 100644 index 0000000000000..b923bee5bd02f --- /dev/null +++ b/test/attr/lexical.swift @@ -0,0 +1,31 @@ +// RUN: %target-typecheck-verify-swift + +struct S {} + +class C {} + +enum E {} + +@_eagerMove // expected-error {{'@_eagerMove' attribute cannot be applied to this declaration}} +typealias EagerTuple = (C, C) + +func foo(@_lexical @_eagerMove _ e: E) {} // expected-error {{@_eagerMove and @_lexical attributes are alternate styles of lifetimes and can't be combined}} + +func bar(@_lexical _ s: S) {} // okay + +func baz(@_eagerMove _ c: C) {} // okay + +struct S2 { + @_eagerMove let c: C // okay + @_lexical let e: E // okay +} + +func foo() { + @_lexical let s1 = S() + @_eagerMove var s2 = S() + @_lexical @_eagerMove let s3 = S() // expected-error {{@_eagerMove and @_lexical attributes are alternate styles of lifetimes and can't be combined}} + _ = s1 + s2 = S() + _ = s2 + _ = s3 +} From d63ac994b7141f87579c6d7ae342db5047cb7444 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Sun, 21 Aug 2022 22:11:16 -0700 Subject: [PATCH 261/491] Delete dead code around UnsafeGuaranteed that I removed recently. --- lib/AST/Builtins.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index 4e042fd73993a..478c6f5d79741 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -1195,23 +1195,6 @@ static ValueDecl *getCOWBufferForReading(ASTContext &C, Identifier Id) { return builder.build(Id); } -static ValueDecl *getUnsafeGuaranteed(ASTContext &C, Identifier Id) { - // T -> (T, Int8Ty) - // - BuiltinFunctionBuilder builder(C); - auto T = makeGenericParam(); - builder.addParameter(T); - Type Int8Ty = BuiltinIntegerType::get(8, C); - builder.setResult(makeTuple(T, makeConcrete(Int8Ty))); - return builder.build(Id); -} - -static ValueDecl *getUnsafeGuaranteedEnd(ASTContext &C, Identifier Id) { - // Int8Ty -> () - Type Int8Ty = BuiltinIntegerType::get(8, C); - return getBuiltinFunction(Id, { Int8Ty }, TupleType::getEmpty(C)); -} - static ValueDecl *getIntInstrprofIncrement(ASTContext &C, Identifier Id) { // (Builtin.RawPointer, Builtin.Int64, Builtin.Int32, Builtin.Int32) -> () Type Int64Ty = BuiltinIntegerType::get(64, C); From 6440e1644042855ec89d3da71b66687f6ec98124 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Sun, 21 Aug 2022 22:07:40 -0700 Subject: [PATCH 262/491] [move-only] Move object checking before PredMemOpts. Otherwise in certain cases due to load promotion, we emit incorrect errors. As an example: let x = ... var y = x print(y) would show an error that x is consumed twice... which is incorrect. --- .../Mandatory/PredictableMemOpt.cpp | 5 ++ lib/SILOptimizer/PassManager/PassPipeline.cpp | 8 ++- test/SILOptimizer/moveonly_diagnostics.swift | 54 +++++++++---------- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp index 823f3da27368e..adff40169048d 100644 --- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp +++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp @@ -2841,6 +2841,11 @@ static AllocationInst *getOptimizableAllocation(SILInstruction *i) { if (getMemoryType(alloc).aggregateHasUnreferenceableStorage()) return nullptr; + // Do not perform this on move only values since we introduce copies to + // promote things. + if (getMemoryType(alloc).isMoveOnly()) + return nullptr; + // Otherwise we are good to go. Lets try to optimize this memory! return alloc; } diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index 18728e61fa1a1..821ecb1f7e533 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -163,6 +163,12 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) { P.addMoveFunctionCanonicalization(); P.addMoveKillsCopyableAddressesChecker(); + // Now perform move object checking. We again do this before predictable + // memory access opts to ensure that we do not get any non-source related + // diagnostics due to value promotion. + P.addMoveOnlyObjectChecker(); // Check noImplicitCopy and move only + // types. + // Promote loads as necessary to ensure we have enough SSA formation to emit // SSA based diagnostics. P.addPredictableMemoryAccessOptimizations(); @@ -171,8 +177,6 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) { // SSA based move function checking and no implicit copy checking. P.addMoveKillsCopyableValuesChecker(); // No uses after _move of copyable // value. - P.addMoveOnlyObjectChecker(); // Check noImplicitCopy and move only - // types. // Now that we have run move only checking, eliminate SILMoveOnly wrapped // trivial types from the IR. We cannot introduce extra "copies" of trivial diff --git a/test/SILOptimizer/moveonly_diagnostics.swift b/test/SILOptimizer/moveonly_diagnostics.swift index d65ab48663c0f..df899400fbca0 100644 --- a/test/SILOptimizer/moveonly_diagnostics.swift +++ b/test/SILOptimizer/moveonly_diagnostics.swift @@ -225,7 +225,7 @@ public func classAssignToVar1(_ x: Klass) { // expected-error {{'x' has guarante var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } // TODO: We shouldn't see a consuming use on x3. @@ -234,7 +234,7 @@ public func classAssignToVar1Arg(_ x: Klass, _ x2: Klass) { // expected-error {{ var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } // NOTE: print(x3) shouldn't be marked! This is most likely due to some form of @@ -245,7 +245,7 @@ public func classAssignToVar1OwnedArg(_ x: Klass, _ x2: __owned Klass) { // expe var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func classAssignToVar2(_ x: Klass) { // expected-error {{'x' has guaranteed ownership but was consumed}} @@ -273,7 +273,7 @@ public func classAssignToVar3(_ x: Klass) { // expected-error {{'x' has guarante let x2 = x // expected-note {{consuming use}} var x3 = x2 x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } // NOTE: print(x3) is a bug. @@ -281,14 +281,14 @@ public func classAssignToVar3Arg(_ x: Klass, _ x2: Klass) { // expected-error {{ // expected-error @-1 {{'x' has guaranteed ownership but was consumed}} var x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } // This is a bug around print(x3) public func classAssignToVar3OwnedArg(_ x: Klass, _ x2: __owned Klass) { // expected-error {{'x' has guaranteed ownership but was consumed}} var x3 = x2 x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func classAssignToVar4(_ x: Klass) { // expected-error {{'x' has guaranteed ownership but was consumed}} @@ -319,7 +319,7 @@ public func classAssignToVar5(_ x: Klass) { // expected-error {{'x' has guarant // appropriately though. classUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func classAssignToVar5Arg(_ x: Klass, _ x2: Klass) { // expected-error {{'x2' has guaranteed ownership but was consumed}} @@ -329,7 +329,7 @@ public func classAssignToVar5Arg(_ x: Klass, _ x2: Klass) { // expected-error {{ // appropriately though. classUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func classAssignToVar5OwnedArg(_ x: Klass, _ x2: __owned Klass) { // expected-error {{'x2' consumed more than once}} @@ -339,7 +339,7 @@ public func classAssignToVar5OwnedArg(_ x: Klass, _ x2: __owned Klass) { // expe // appropriately though. classUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func classAccessAccessField(_ x: Klass) { // expected-error {{'x' has guaranteed ownership but was consumed}} @@ -576,7 +576,7 @@ public func finalClassAssignToVar1(_ x: FinalKlass) { // expected-error {{'x' ha var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAssignToVar1Arg(_ x: FinalKlass, _ x2: FinalKlass) { // expected-error {{'x2' has guaranteed ownership but was consumed}} @@ -584,7 +584,7 @@ public func finalClassAssignToVar1Arg(_ x: FinalKlass, _ x2: FinalKlass) { // ex var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAssignToVar1OwnedArg(_ x: FinalKlass, _ x2: __owned FinalKlass) { // expected-error {{'x2' consumed more than once}} @@ -592,7 +592,7 @@ public func finalClassAssignToVar1OwnedArg(_ x: FinalKlass, _ x2: __owned FinalK var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAssignToVar2(_ x: FinalKlass) { // expected-error {{'x' has guaranteed ownership but was consumed}} @@ -619,20 +619,20 @@ public func finalClassAssignToVar3(_ x: FinalKlass) { // expected-error {{'x' ha let x2 = x // expected-note {{consuming use}} var x3 = x2 x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAssignToVar3Arg(_ x: FinalKlass, _ x2: FinalKlass) { // expected-error {{'x2' has guaranteed ownership but was consumed}} // expected-error @-1 {{'x' has guaranteed ownership but was consumed}} var x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAssignToVar3OwnedArg(_ x: FinalKlass, _ x2: __owned FinalKlass) { // expected-error {{'x' has guaranteed ownership but was consumed}} var x3 = x2 x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAssignToVar4(_ x: FinalKlass) { // expected-error {{'x' has guaranteed ownership but was consumed}} @@ -663,7 +663,7 @@ public func finalClassAssignToVar5(_ x: FinalKlass) { // expected-error {{'x' ha // appropriately though. finalClassUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAssignToVar5Arg(_ x: FinalKlass, _ x2: FinalKlass) { // expected-error {{'x2' has guaranteed ownership but was consumed}} @@ -673,7 +673,7 @@ public func finalClassAssignToVar5Arg(_ x: FinalKlass, _ x2: FinalKlass) { // ex // appropriately though. finalClassUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAssignToVar5OwnedArg(_ x: FinalKlass, _ x2: __owned FinalKlass) { // expected-error {{'x2' consumed more than once}} @@ -683,7 +683,7 @@ public func finalClassAssignToVar5OwnedArg(_ x: FinalKlass, _ x2: __owned FinalK // appropriately though. finalClassUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func finalClassAccessField(_ x: FinalKlass) { // expected-error {{'x' has guaranteed ownership but was consumed}} @@ -1734,7 +1734,7 @@ public func enumAssignToVar1(_ x: EnumTy) { // expected-error {{'x' has guarante var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumAssignToVar1Arg(_ x: EnumTy, _ x2: EnumTy) { // expected-error {{'x2' has guaranteed ownership but was consumed}} @@ -1742,7 +1742,7 @@ public func enumAssignToVar1Arg(_ x: EnumTy, _ x2: EnumTy) { // expected-error { var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumAssignToVar1OwnedArg(_ x: EnumTy, _ x2: __owned EnumTy) { // expected-error {{'x2' consumed more than once}} @@ -1750,7 +1750,7 @@ public func enumAssignToVar1OwnedArg(_ x: EnumTy, _ x2: __owned EnumTy) { // exp var x3 = x2 // expected-note {{consuming use}} x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumAssignToVar2(_ x: EnumTy) { // expected-error {{'x' has guaranteed ownership but was consumed}} @@ -1777,20 +1777,20 @@ public func enumAssignToVar3(_ x: EnumTy) { // expected-error {{'x' has guarante let x2 = x // expected-note {{consuming use}} var x3 = x2 x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumAssignToVar3Arg(_ x: EnumTy, _ x2: EnumTy) { // expected-error {{'x2' has guaranteed ownership but was consumed}} // expected-error @-1 {{'x' has guaranteed ownership but was consumed}} var x3 = x2 // expected-note {{consuming use}} x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumAssignToVar3OwnedArg(_ x: EnumTy, _ x2: __owned EnumTy) { // expected-error {{'x' has guaranteed ownership but was consumed}} var x3 = x2 x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumAssignToVar4(_ x: EnumTy) { // expected-error {{'x' has guaranteed ownership but was consumed}} @@ -1821,7 +1821,7 @@ public func enumAssignToVar5(_ x: EnumTy) { // expected-error {{'x' has guarante // appropriately though. enumUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumAssignToVar5Arg(_ x: EnumTy, _ x2: EnumTy) { // expected-error {{'x2' has guaranteed ownership but was consumed}} @@ -1831,7 +1831,7 @@ public func enumAssignToVar5Arg(_ x: EnumTy, _ x2: EnumTy) { // expected-error { // appropriately though. enumUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumAssignToVar5OwnedArg(_ x: EnumTy, _ x2: __owned EnumTy) { // expected-error {{'x2' consumed more than once}} @@ -1841,7 +1841,7 @@ public func enumAssignToVar5OwnedArg(_ x: EnumTy, _ x2: __owned EnumTy) { // exp // appropriately though. enumUseMoveOnlyWithoutEscaping(x2) x3 = x // expected-note {{consuming use}} - print(x3) // expected-note {{consuming use}} + print(x3) } public func enumPatternMatchIfLet1(_ x: EnumTy) { // expected-error {{'x' has guaranteed ownership but was consumed}} From 3a897fcdaaadfca7fac71b0775a257ecf24e5a78 Mon Sep 17 00:00:00 2001 From: WeZZard Date: Sun, 21 Aug 2022 16:52:56 +0800 Subject: [PATCH 263/491] Makes build-script to support None and string object SystemExit.code --- utils/build-script | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/utils/build-script b/utils/build-script index c7497c09665b6..f2bc5167eb882 100755 --- a/utils/build-script +++ b/utils/build-script @@ -182,6 +182,28 @@ def tar(source, destination): shell.call(args + [source], stderr=shell.DEVNULL) +def process_system_exit(e: SystemExit) -> int: + # According to Python's documents, `SystemExit.code` is the exit status + # or error message that is passed to the constructor. (Defaults to None.) + # + # This means that `SystemExit.code` is either `None`, an `int` object or + # a `string` object of error message. + if e.code is None: + # Fallback to 1 if there is no error code but a `SystemExit`. + return 1 + try: + numeric_code = int(e.code) + return numeric_code + except ValueError: + # Fallback to 1 if it is an error message and print that message. + print(e) + return 1 + finally: + # Fallback to 1 and do nothing, since there is only ValueError as + # expected exception. + return 1 + + # ----------------------------------------------------------------------------- # Argument Validation @@ -719,7 +741,8 @@ if __name__ == "__main__": try: exit_code = main() except SystemExit as e: - os._exit(e.code) + error_code = process_system_exit(e) + os._exit(error_code) except KeyboardInterrupt: sys.exit(1) finally: From 3367fdd04d361dad695fa6d8831477eb4edc0169 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 19 Aug 2022 13:30:04 +0200 Subject: [PATCH 264/491] SmallProjectionPath: add `mayOverlap(with:)` "Overlapping" means that both paths may project the same field. --- .../Sources/SIL/SmallProjectionPath.swift | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/SwiftCompilerSources/Sources/SIL/SmallProjectionPath.swift b/SwiftCompilerSources/Sources/SIL/SmallProjectionPath.swift index 78d7981ba77e8..8d54d6a60529c 100644 --- a/SwiftCompilerSources/Sources/SIL/SmallProjectionPath.swift +++ b/SwiftCompilerSources/Sources/SIL/SmallProjectionPath.swift @@ -373,7 +373,37 @@ public struct SmallProjectionPath : CustomStringConvertible, CustomReflectable, } return Self(.anything) } + + /// Returns true if this path may overlap with `rhs`. + /// + /// "Overlapping" means that both paths may project the same field. + /// For example: + /// `s0.s1` and `s0.s1` overlap (the paths are identical) + /// `s0.s1` and `s0.s2` don't overlap + /// `s0.s1` and `s0` overlap (the second path is a sub-path of the first one) + /// `s0.v**` and `s0.s1` overlap + public func mayOverlap(with rhs: SmallProjectionPath) -> Bool { + if isEmpty || rhs.isEmpty { + return true + } + let (lhsKind, lhsIdx, lhsBits) = top + let (rhsKind, rhsIdx, rhsBits) = rhs.top + + if lhsKind == .anything || rhsKind == .anything { + return true + } + if lhsKind == .anyValueFields || rhsKind == .anyValueFields { + return popAllValueFields().mayOverlap(with: rhs.popAllValueFields()) + } + if (lhsKind == rhsKind && lhsIdx == rhsIdx) || + (lhsKind == .anyClassField && rhsKind.isClassField) || + (lhsKind.isClassField && rhsKind == .anyClassField) { + return pop(numBits: lhsBits).mayOverlap(with: rhs.pop(numBits: rhsBits)) + } + return false + } + public var customMirror: Mirror { Mirror(self, children: []) } } @@ -505,6 +535,7 @@ extension SmallProjectionPath { parsing() merging() matching() + overlapping() predicates() path2path() @@ -617,6 +648,38 @@ extension SmallProjectionPath { precondition(result == expect) } + func overlapping() { + testOverlap("s0.s1.s2", "s0.s1.s2", expect: true) + testOverlap("s0.s1.s2", "s0.s2.s2", expect: false) + testOverlap("s0.s1.s2", "s0.e1.s2", expect: false) + testOverlap("s0.s1.s2", "s0.s1", expect: true) + testOverlap("s0.s1.s2", "s1.s2", expect: false) + + testOverlap("s0.c*.s2", "s0.ct.s2", expect: true) + testOverlap("s0.c*.s2", "s0.c1.s2", expect: true) + testOverlap("s0.c*.s2", "s0.c1.c2.s2", expect: false) + testOverlap("s0.c*.s2", "s0.s2", expect: false) + + testOverlap("s0.v**.s2", "s0.s3", expect: true) + testOverlap("s0.v**.s2.c2", "s0.s3.c1", expect: false) + testOverlap("s0.v**.s2", "s1.s3", expect: false) + testOverlap("s0.v**.s2", "s0.v**.s3", expect: true) + + testOverlap("s0.**", "s0.s3.c1", expect: true) + testOverlap("**", "s0.s3.c1", expect: true) + } + + func testOverlap(_ lhsStr: String, _ rhsStr: String, expect: Bool) { + var lhsParser = StringParser(lhsStr) + let lhs = try! lhsParser.parseProjectionPathFromSIL() + var rhsParser = StringParser(rhsStr) + let rhs = try! rhsParser.parseProjectionPathFromSIL() + let result = lhs.mayOverlap(with: rhs) + precondition(result == expect) + let reversedResult = rhs.mayOverlap(with: lhs) + precondition(reversedResult == expect) + } + func predicates() { testPredicate("v**", \.hasNoClassProjection, expect: true) testPredicate("c0", \.hasNoClassProjection, expect: false) From 05d62293e66c52e25666182146480b786b59b23e Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 19 Aug 2022 15:19:18 +0200 Subject: [PATCH 265/491] Swift SIL: add `NominalFieldsArray.getNameOfField(withIndex:)` --- SwiftCompilerSources/Sources/SIL/Type.swift | 4 ++++ include/swift/SIL/SILBridging.h | 1 + lib/SIL/Utils/SILBridging.cpp | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/SwiftCompilerSources/Sources/SIL/Type.swift b/SwiftCompilerSources/Sources/SIL/Type.swift index d5d20751a23e1..7343e1cf120f4 100644 --- a/SwiftCompilerSources/Sources/SIL/Type.swift +++ b/SwiftCompilerSources/Sources/SIL/Type.swift @@ -80,6 +80,10 @@ public struct NominalFieldsArray : RandomAccessCollection, FormattedLikeArray { } return idx >= 0 ? idx : nil } + + public func getNameOfField(withIndex idx: Int) -> StringRef { + StringRef(bridged: SILType_getNominalFieldName(type.bridged, idx)) + } } public struct TupleElementArray : RandomAccessCollection, FormattedLikeArray { diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index d2b7f2a02f60b..bd04266bad540 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -274,6 +274,7 @@ BridgedType SILType_getNominalFieldType(BridgedType type, SwiftInt index, BridgedFunction function); SwiftInt SILType_getFieldIdxOfNominalType(BridgedType type, llvm::StringRef fieldName); +llvm::StringRef SILType_getNominalFieldName(BridgedType type, SwiftInt index); SwiftInt SILType_getCaseIdxOfEnumType(BridgedType type, llvm::StringRef caseName); diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index b6f522aad7e79..14af248bfc635 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -461,6 +461,14 @@ BridgedType SILType_getNominalFieldType(BridgedType type, SwiftInt index, return {fieldType.getOpaqueValue()}; } +StringRef SILType_getNominalFieldName(BridgedType type, SwiftInt index) { + SILType silType = castToSILType(type); + + NominalTypeDecl *decl = silType.getNominalOrBoundGenericNominal(); + VarDecl *field = getIndexedField(decl, (unsigned)index); + return field->getName().str(); +} + SwiftInt SILType_getFieldIdxOfNominalType(BridgedType type, StringRef fieldName) { SILType ty = castToSILType(type); From 20a8f450dd3ab639a850d43dd9842438cfc7aa12 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Mon, 22 Aug 2022 13:21:49 +0200 Subject: [PATCH 266/491] Swift AccessUtils: improvements and bug fixes While I was using the new AccessUtils for a new optimization pass I discovered some areas for improvements. Also I found some bugs. Changes: * AccessBase: remove the unhealthy redundancy between `kind` and `baseAddress` types. Now AccessBase is single enum with the relevant base objects/addresses as payloads. * AccessBase: for `global`, store the `GlobalValue` and not a `global_address` instruction, which is more accurate (because there can be multiple `global_addr`s for a single global variable) * AccessBase: drop the support for function argument "pointers". The `pointer` is now always a `pointer_to_address` instruction. This also simplifies `PointerIdentification`: either it finds a matching `address_to_pointer` or it bails. * AccessBase: improve `func isDistinct(from:)`. There are more possibilities to prove that two access bases do not alias. * AccessBase: replace `var isUniquelyIdentified` with `var hasKnownStorageKind` which is more useful for aliasing checking. * AccessPath: fix `func isDistinct(from:)`. `SmallProjectionPath.matches` is the wrong way to check if two expression paths may overlap. Instead use the new `SmallProjectionPath.mayOverlap`. * AccessStoragePathWalker: rename `getAccessStorage` -> `visitAccessStorageRoots` and let it return false if it's not a class/reference AccessBase. * add tests for `AccessPath.isDistinct(from:)` --- .../FunctionPasses/AccessDumper.swift | 53 ++- .../Optimizer/Utilities/AccessUtils.swift | 392 +++++++++--------- .../Sources/SIL/Argument.swift | 6 +- .../Sources/SIL/GlobalVariable.swift | 16 +- .../Sources/SIL/Instruction.swift | 4 + test/SILOptimizer/accessutils.sil | 296 ++++++++++--- 6 files changed, 483 insertions(+), 284 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AccessDumper.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AccessDumper.swift index 66955294bc26c..cfd318536e91c 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AccessDumper.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AccessDumper.swift @@ -10,25 +10,35 @@ // //===----------------------------------------------------------------------===// +import Basic import SIL /// Dumps access information for memory accesses (`load` and `store`) /// instructions. +/// Also verifies that `AccessPath.isDistinct(from:)` is correct. This does not actually +/// dumps anything, but aborts if the result is wrong. /// /// This pass is used for testing `AccessUtils`. let accessDumper = FunctionPass(name: "dump-access", { (function: Function, context: PassContext) in print("Accesses for \(function.name)") - var apw = AccessPathWalker() - var arw = AccessStoragePathVisitor() for block in function.blocks { for instr in block.instructions { switch instr { case let st as StoreInst: - printAccessInfo(st.destinationOperand.value, &apw, &arw, context) + printAccessInfo(address: st.destination) case let load as LoadInst: - printAccessInfo(load.operand, &apw, &arw, context) + printAccessInfo(address: load.operand) + case let apply as ApplyInst: + guard let callee = apply.referencedFunction else { + break + } + if callee.name == "_isDistinct" { + checkAliasInfo(forArgumentsOf: apply, expectDistinct: true) + } else if callee.name == "_isNotDistinct" { + checkAliasInfo(forArgumentsOf: apply, expectDistinct: false) + } default: break } @@ -46,10 +56,11 @@ private struct AccessStoragePathVisitor : AccessStoragePathWalker { } } -private func printAccessInfo(_ value: Value, _ apw: inout AccessPathWalker, _ aspw: inout AccessStoragePathVisitor, - _ ctx: PassContext) { - print("Value: \(value)") - let (ap, scope) = apw.getAccessPathWithScope(of: value) +private func printAccessInfo(address: Value) { + print("Value: \(address)") + + var apw = AccessPathWalker() + let (ap, scope) = apw.getAccessPathWithScope(of: address) if let scope = scope { switch scope { case let .scope(ba): @@ -63,6 +74,30 @@ private func printAccessInfo(_ value: Value, _ apw: inout AccessPathWalker, _ as print(" Base: \(ap.base)") print(" Path: \"\(ap.projectionPath)\"") - aspw.getAccessStorage(for: ap) + var arw = AccessStoragePathVisitor() + if !arw.visitAccessStorageRoots(of: ap) { + print(" no Storage paths") + } + } +} + +private func checkAliasInfo(forArgumentsOf apply: ApplyInst, expectDistinct: Bool) { + let address1 = apply.arguments[0] + let address2 = apply.arguments[1] + var apw = AccessPathWalker() + guard let path1 = apw.getAccessPath(of: address1), + let path2 = apw.getAccessPath(of: address2) else { + return + } + if path1.isDistinct(from: path2) != expectDistinct { + print("wrong isDistinct result of \(apply)") + } else if path2.isDistinct(from: path1) != expectDistinct { + print("wrong reverse isDistinct result of \(apply)") + } else { + return } + + print("in function") + print(apply.function) + fatalError() } diff --git a/SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift b/SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift index e59d46176ebc2..b0371d9e16a74 100644 --- a/SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift +++ b/SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift @@ -30,166 +30,188 @@ //===----------------------------------------------------------------------===// import SIL -/// "AccessBase describes the base address of a memory access (e.g. of a `load` or `store``). -/// The access address is either the base address directly or an address -/// projection of it. +/// AccessBase describes the base address of a memory access (e.g. of a `load` or `store``). +/// The "base address" is defined as the address which is obtained from the access address by +/// looking through all address projections. +/// This means that the base address is either the same as the access address or: +/// the access address is a chain of address projections of the base address. /// The following snippets show examples of memory accesses and their respective bases. /// /// ``` -/// %base1 = ref_element_addr %ref, #Obj.field -/// %base2 = alloc_stack $S -/// %base3 = global_addr @gaddr +/// %base1 = ref_element_addr %ref, #Obj.field // A `class` base +/// %base2 = alloc_stack $S // A `stack` base +/// %base3 = global_addr @gaddr // A `global` base /// %addr1 = struct_element_addr %base1 /// %access1 = store %v1 to [trivial] %addr1 // accessed address is offset from base /// %access2 = store %v2 to [trivial] %base2 // accessed address is base itself /// ``` /// /// The base address is never inside an access scope. -struct AccessBase : CustomStringConvertible { - - public enum Kind { - case box - case stack - case global - case `class` - case tail - case argument - case yield - case pointer - - var isObject: Bool { self == .class || self == .tail } - } - - let baseAddress: Value - let kind: Kind +enum AccessBase : CustomStringConvertible, Hashable { + + /// The address of a boxed variable, i.e. a field of an `alloc_box`. + case box(ProjectBoxInst) + + /// The address of a stack-allocated value, i.e. an `alloc_stack` + case stack(AllocStackInst) + + /// The address of a global variable. + case global(GlobalVariable) + + /// The address of a stored property of a class instance. + case `class`(RefElementAddrInst) + + /// The base address of the tail allocated elements of a class instance. + case tail(RefTailAddrInst) + + /// An indirect function argument, like `@inout`. + case argument(FunctionArgument) + + /// An indirect result of a `begin_apply`. + case yield(BeginApplyInst) + + /// An address which is derived from a `Builtin.RawPointer`. + case pointer(PointerToAddressInst) init?(baseAddress: Value) { switch baseAddress { - case is RefElementAddrInst : kind = .class - case is RefTailAddrInst : kind = .tail - case is ProjectBoxInst : kind = .box - case is AllocStackInst : kind = .stack - case is FunctionArgument : kind = .argument - case is GlobalAddrInst : kind = .global - default: - if baseAddress.definingInstruction is BeginApplyInst && - baseAddress.type.isAddress { - kind = .yield + case let rea as RefElementAddrInst : self = .class(rea) + case let rta as RefTailAddrInst : self = .tail(rta) + case let pbi as ProjectBoxInst : self = .box(pbi) + case let asi as AllocStackInst : self = .stack(asi) + case let arg as FunctionArgument : self = .argument(arg) + case let ga as GlobalAddrInst : self = .global(ga.global) + case let mvr as MultipleValueInstructionResult: + if let ba = mvr.instruction as? BeginApplyInst, baseAddress.type.isAddress { + self = .yield(ba) } else { return nil } + default: + return nil } - - self.baseAddress = baseAddress - } - - init(baseAddress: Value, kind: Kind) { - self.baseAddress = baseAddress - self.kind = kind } var description: String { - "\(kind) - \(baseAddress)" + switch self { + case .box(let pbi): return "box - \(pbi)" + case .stack(let asi): return "stack - \(asi)" + case .global(let gl): return "global - @\(gl.name)" + case .class(let rea): return "class - \(rea)" + case .tail(let rta): return "tail - \(rta.operand)" + case .argument(let arg): return "argument - \(arg)" + case .yield(let ba): return "yield - \(ba)" + case .pointer(let p): return "pointer - \(p)" + } } - /// Returns `true` if this is an access to a class instance + /// True, if this is an access to a class instance. var isObjectAccess: Bool { - return kind == .class || kind == .tail + switch self { + case .class, .tail: + return true + case .box, .stack, .global, .argument, .yield, .pointer: + return false + } } - /// Returns a value of reference type if this is a reference projection (class, box, tail) + /// The reference value if this is an access to a referenced objecct (class, box, tail). var reference: Value? { - switch baseAddress { - case let rea as RefElementAddrInst: - return rea.operand - case let pb as ProjectBoxInst: - return pb.operand - case let rta as RefTailAddrInst: - return rta.operand - default: - return nil + switch self { + case .box(let pbi): return pbi.operand + case .class(let rea): return rea.operand + case .tail(let rta): return rta.operand + case .stack, .global, .argument, .yield, .pointer: + return nil } } - - /// Returns `true` if the baseAddress is of an immutable property/global variable + /// True, if the baseAddress is of an immutable property or global variable var isLet: Bool { - switch baseAddress { - case let rea as RefElementAddrInst: - return rea.fieldIsLet - case let ga as GlobalAddrInst: - return ga.global.isLet - default: - return false + switch self { + case .class(let rea): return rea.fieldIsLet + case .global(let g): return g.isLet + case .box, .stack, .tail, .argument, .yield, .pointer: + return false } } - /// Returns `true` if the address is immediately produced by a stack or box allocation + /// True, if the address is immediately produced by an allocation in its function. var isLocal: Bool { - switch kind { - case .box: - // The operand of the projection can be an argument, in which - // case it wouldn't be local - return (baseAddress as! ProjectBoxInst).operand is AllocBoxInst - case .class: - let op = (baseAddress as! RefElementAddrInst).operand - return op is AllocRefInst || op is AllocRefDynamicInst - case .stack: - return true - default: - return false + switch self { + case .box(let pbi): return pbi.operand is AllocBoxInst + case .class(let rea): return rea.operand is AllocRefInstBase + case .tail(let rta): return rta.operand is AllocRefInstBase + case .stack: return true + case .global, .argument, .yield, .pointer: + return false } } - /// Returns `true` if we can reliably compare this `AccessBase` - /// with another `AccessBase` for equality. - /// When comparing two uniquely identified access bases and they are not equal, - /// it follows that the accessed memory addresses do not alias. - /// This is e.g. not the case for class references: two different references - /// may still point to the same object. - var isUniquelyIdentified: Bool { - switch kind { - case .box: - // The operand `%op` in `%baseAddress = project_box %op` can - // be `alloc_box` or an argument. Only if it's a fresh allocation it is - // uniquelyIdentified, otherwise it is aliasable, as all the other references. - return (baseAddress as! ProjectBoxInst).operand is AllocBoxInst - case .stack, .global: - return true - case .argument: - // An argument address that is non-aliasable - return (baseAddress as! FunctionArgument).isExclusiveIndirectParameter - case .class: - let op = (baseAddress as! RefElementAddrInst).operand - return op is AllocRefInst || op is AllocRefDynamicInst - case .tail, .yield, .pointer: - // References (.class and .tail) may alias, and so do pointers and - // yield results - return false + /// True, if the kind of storage of the access is known (e.g. a class property, or global variable). + var hasKnownStorageKind: Bool { + switch self { + case .box, .class, .tail, .stack, .global: + return true + case .argument, .yield, .pointer: + return false } } - /// Returns `true` if the two access bases do not alias + /// Returns `true` if the two access bases do not alias. func isDistinct(from other: AccessBase) -> Bool { - switch (baseAddress, other.baseAddress) { - case is (AllocStackInst, AllocStackInst): - return baseAddress != other.baseAddress - case let (this as ProjectBoxInst, that as ProjectBoxInst) - where this.operand is AllocBoxInst && that.operand is AllocBoxInst: - return this.operand != that.operand - case let (this as GlobalAddrInst, that as GlobalAddrInst): - return this.global != that.global - case let (this as FunctionArgument, that as FunctionArgument): - return (this.isExclusiveIndirectParameter || that.isExclusiveIndirectParameter) && this != that - case let (this as RefElementAddrInst, that as RefElementAddrInst): - return (this.fieldIndex != that.fieldIndex) + + func isDifferentAllocation(_ lhs: Value, _ rhs: Value) -> Bool { + switch (lhs, rhs) { + case (is Allocation, is Allocation): + return lhs != rhs + case (is Allocation, is FunctionArgument), + (is FunctionArgument, is Allocation): + // A local allocation cannot alias with something passed to the function. + return true + default: + return false + } + } + + func argIsDistinct(_ arg: FunctionArgument, from other: AccessBase) -> Bool { + if arg.isExclusiveIndirectParameter { + // Exclusive indirect arguments cannot alias with an address for which we know that it + // is not derived from that argument (which might be the case for `pointer` and `yield`). + return other.hasKnownStorageKind + } + // Non-exclusive argument still cannot alias with anything allocated locally in the function. + return other.isLocal + } + + switch (self, other) { + + // First handle all pairs of the same kind (except `yield` and `pointer`). + case (.box(let pb), .box(let otherPb)): + return pb.fieldIndex != otherPb.fieldIndex || + isDifferentAllocation(pb.operand, otherPb.operand) + case (.stack(let asi), .stack(let otherAsi)): + return asi != otherAsi + case (.global(let global), .global(let otherGlobal)): + return global != otherGlobal + case (.class(let rea), .class(let otherRea)): + return rea.fieldIndex != otherRea.fieldIndex || + isDifferentAllocation(rea.operand, otherRea.operand) + case (.tail(let rta), .tail(let otherRta)): + return isDifferentAllocation(rta.operand, otherRta.operand) + case (.argument(let arg), .argument(let otherArg)): + return (arg.isExclusiveIndirectParameter || otherArg.isExclusiveIndirectParameter) && arg != otherArg + + // Handle arguments vs non-arguments + case (.argument(let arg), _): + return argIsDistinct(arg, from: other) + case (_, .argument(let otherArg)): + return argIsDistinct(otherArg, from: self) + default: - let selfIsUniquelyIdentified = isUniquelyIdentified - let otherIsUniquelyIdentified = other.isUniquelyIdentified - if selfIsUniquelyIdentified && otherIsUniquelyIdentified && kind != other.kind { return true } - // property: `isUniquelyIdentified` XOR `isObject` - if selfIsUniquelyIdentified && other.kind.isObject { return true } - if kind.isObject && otherIsUniquelyIdentified { return true } - return false + // As we already handled pairs of the same kind, here we handle pairs with different kinds. + // Different storage kinds cannot alias, regardless where the storage comes from. + // E.g. a class property address cannot alias with a global variable address. + return hasKnownStorageKind && other.hasKnownStorageKind } } } @@ -207,11 +229,18 @@ struct AccessPath : CustomStringConvertible { } func isDistinct(from other: AccessPath) -> Bool { - return - base.isDistinct(from: other.base) || // The base is distinct, in which case we are done. OR - (base.baseAddress == other.base.baseAddress && // (The base is the exact same AND - !(projectionPath.matches(pattern: other.projectionPath) // the projection paths do not overlap) - || (other.projectionPath.matches(pattern: projectionPath)))) + if base.isDistinct(from: other.base) { + // We can already derived from the bases that there is no alias. + // No need to look at the projection paths. + return true + } + if base == other.base || + (base.hasKnownStorageKind && other.base.hasKnownStorageKind) { + if !projectionPath.mayOverlap(with: other.projectionPath) { + return true + } + } + return false } } @@ -240,45 +269,22 @@ private func canBeOperandOfIndexAddr(_ value: Value) -> Bool { } } -enum AddressOrPointerArgument { - case address(Value) - case pointer(FunctionArgument) -} - -extension AddressOrPointerArgument : Equatable { - static func ==(lhs: AddressOrPointerArgument, rhs: AddressOrPointerArgument) -> Bool { - switch (lhs, rhs) { - case let (.address(left), .address(right)): - return left == right - case let (.pointer(left), .pointer(right)): - return left == right - default: - return false - } - } -} - /// Given a `%addr = pointer_to_address %ptr_operand` instruction tries to identify -/// the address the pointer operand `ptr_operand` originates from, if any exists. +/// where the pointer operand `ptr_operand` originates from. /// This is useful to identify patterns like /// ``` /// %orig_addr = global_addr @... /// %ptr = address_to_pointer %orig_addr /// %addr = pointer_to_address %ptr /// ``` -/// which might arise when `[global_init]` functions for global addressors are inlined. -/// -/// Alternatively, if the pointer originates from a ``FunctionArgument``, the argument is returned. -/// -/// This underlying use-def traversal might cross phi arguments to identify the originating address -/// to handle diamond-shaped control-flow with common originating -/// address which might arise due to transformations ([example] (https://github.com/apple/swift/blob/8f9c5339542b17af9033f51ad7a0b95a043cad1b/test/SILOptimizer/access_storage_analysis_ossa.sil#L669-L705)) . struct PointerIdentification { private var walker = PointerIdentificationUseDefWalker() - mutating func getOriginatingAddressOrArgument(_ atp: PointerToAddressInst) -> AddressOrPointerArgument? { - walker.start(atp.type) - if walker.walkUp(value: atp.operand, path: SmallProjectionPath()) == .abortWalk { + mutating func getOriginatingAddress(of pointerToAddr: PointerToAddressInst) -> Value? { + defer { walker.clear() } + + walker.start(pointerToAddr.type) + if walker.walkUp(value: pointerToAddr.operand, path: SmallProjectionPath()) == .abortWalk { return nil } return walker.result @@ -286,37 +292,31 @@ struct PointerIdentification { private struct PointerIdentificationUseDefWalker : ValueUseDefWalker { private var addrType: Type! - private(set) var result: AddressOrPointerArgument? + private(set) var result: Value? + var walkUpCache = WalkerCache() mutating func start(_ addrType: Type) { self.addrType = addrType + assert(result == nil) + } + + mutating func clear() { result = nil walkUpCache.clear() } mutating func rootDef(value: Value, path: SmallProjectionPath) -> WalkResult { - switch value { - case let arg as FunctionArgument: - if let res = result, res != self.result { - self.result = nil - return .abortWalk - } - self.result = .pointer(arg) - return .continueWalk - case let atp as AddressToPointerInst: - if case let .address(result) = result, atp.operand != result { - self.result = nil + if let atp = value as? AddressToPointerInst { + if let res = result, atp.operand != res { return .abortWalk } - if addrType == atp.operand.type, path.isEmpty { - self.result = .address(atp.operand) - return .continueWalk - } - default: - break + if addrType != atp.operand.type { return .abortWalk } + if !path.isEmpty { return .abortWalk } + + self.result = atp.operand + return .continueWalk } - self.result = nil return .abortWalk } @@ -327,12 +327,9 @@ struct PointerIdentification { is FunctionArgument, is AddressToPointerInst: return walkUpDefault(value: value, path: path) default: - self.result = nil return .abortWalk } } - - var walkUpCache = WalkerCache() } } @@ -438,17 +435,13 @@ struct AccessPathWalker { } mutating func rootDef(address: Value, path: Path) -> WalkResult { + assert(result == nil, "rootDef should only called once") // Try identifying the address a pointer originates from if let p2ai = address as? PointerToAddressInst { - if let addrOrArg = pointerId.getOriginatingAddressOrArgument(p2ai) { - switch addrOrArg { - case let .address(newAddress): - return walkUp(address: newAddress, path: path) - case let .pointer(arg): - self.result = AccessPath(base: AccessBase(baseAddress: arg, kind: .pointer), projectionPath: path.projectionPath) - } + if let originatingAddr = pointerId.getOriginatingAddress(of: p2ai) { + return walkUp(address: originatingAddr, path: path) } else { - self.result = AccessPath(base: AccessBase(baseAddress: p2ai, kind: .pointer), projectionPath: path.projectionPath) + self.result = AccessPath(base: .pointer(p2ai), projectionPath: path.projectionPath) return .continueWalk } } @@ -481,29 +474,30 @@ struct AccessPathWalker { } } -/// A ValueUseDef walker that identifies which values a reference might +/// A ValueUseDef walker that identifies which values a reference of an access path might /// originate from. protocol AccessStoragePathWalker : ValueUseDefWalker where Path == SmallProjectionPath { mutating func visit(access: AccessStoragePath) } extension AccessStoragePathWalker { - // Main entry point - /// Given an `ap: AccessPath` where the base address is a projection - /// from a reference type, returns the set of reference definitions - /// that the address of the access may originate from. - mutating func getAccessStorage(for accessPath: AccessPath) { + /// The main entry point. + /// Given an `accessPath` where the access base is a reference (class, tail, box), call + /// the `visit` function for all storage roots with a the corresponding path. + /// Returns true on success. + /// Returns false if not all storage roots could be identified or if `accessPath` has not a "reference" base. + mutating func visitAccessStorageRoots(of accessPath: AccessPath) -> Bool { walkUpCache.clear() let path = accessPath.projectionPath - switch accessPath.base.baseAddress { - case let rea as RefElementAddrInst: - _ = walkUp(value: rea.operand, path: path.push(.classField, index: rea.fieldIndex)) - case let pb as ProjectBoxInst: - _ = walkUp(value: pb.operand, path: path.push(.classField, index: pb.fieldIndex)) - case let rta as RefTailAddrInst: - _ = walkUp(value: rta.operand, path: path.push(.tailElements, index: 0)) - default: - visit(access: AccessStoragePath(storage: accessPath.base.baseAddress, path: accessPath.projectionPath)) + switch accessPath.base { + case .box(let pbi): + return walkUp(value: pbi.operand, path: path.push(.classField, index: pbi.fieldIndex)) != .abortWalk + case .class(let rea): + return walkUp(value: rea.operand, path: path.push(.classField, index: rea.fieldIndex)) != .abortWalk + case .tail(let rta): + return walkUp(value: rta.operand, path: path.push(.tailElements, index: 0)) != .abortWalk + case .stack, .global, .argument, .yield, .pointer: + return false } } diff --git a/SwiftCompilerSources/Sources/SIL/Argument.swift b/SwiftCompilerSources/Sources/SIL/Argument.swift index 107768411250c..4c43ab127d919 100644 --- a/SwiftCompilerSources/Sources/SIL/Argument.swift +++ b/SwiftCompilerSources/Sources/SIL/Argument.swift @@ -16,7 +16,7 @@ import SILBridging /// A basic block argument. /// /// Maps to both, SILPhiArgument and SILFunctionArgument. -public class Argument : Value, Equatable { +public class Argument : Value, Hashable { public var definingInstruction: Instruction? { nil } public var definingBlock: BasicBlock { block } @@ -33,6 +33,10 @@ public class Argument : Value, Equatable { public static func ==(lhs: Argument, rhs: Argument) -> Bool { lhs === rhs } + + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } } final public class FunctionArgument : Argument { diff --git a/SwiftCompilerSources/Sources/SIL/GlobalVariable.swift b/SwiftCompilerSources/Sources/SIL/GlobalVariable.swift index 9c3c4038686e1..aaab8eed04554 100644 --- a/SwiftCompilerSources/Sources/SIL/GlobalVariable.swift +++ b/SwiftCompilerSources/Sources/SIL/GlobalVariable.swift @@ -13,7 +13,7 @@ import Basic import SILBridging -final public class GlobalVariable : CustomStringConvertible, HasShortDescription { +final public class GlobalVariable : CustomStringConvertible, HasShortDescription, Hashable { public var name: StringRef { return StringRef(bridged: SILGlobalVariable_getName(bridged)) } @@ -29,15 +29,15 @@ final public class GlobalVariable : CustomStringConvertible, HasShortDescription // TODO: initializer instructions - var bridged: BridgedGlobalVar { BridgedGlobalVar(obj: SwiftObject(self)) } -} + public static func ==(lhs: GlobalVariable, rhs: GlobalVariable) -> Bool { + lhs === rhs + } -public func ==(_ lhs: GlobalVariable, _ rhs: GlobalVariable) -> Bool { - return lhs === rhs -} + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } -public func !=(_ lhs: GlobalVariable, _ rhs: GlobalVariable) -> Bool { - return (lhs !== rhs) + var bridged: BridgedGlobalVar { BridgedGlobalVar(obj: SwiftObject(self)) } } // Bridging utilities diff --git a/SwiftCompilerSources/Sources/SIL/Instruction.swift b/SwiftCompilerSources/Sources/SIL/Instruction.swift index ebfa5321e544d..8bdf695255366 100644 --- a/SwiftCompilerSources/Sources/SIL/Instruction.swift +++ b/SwiftCompilerSources/Sources/SIL/Instruction.swift @@ -139,6 +139,10 @@ public class SingleValueInstruction : Instruction, Value { fileprivate final override var resultCount: Int { 1 } fileprivate final override func getResult(index: Int) -> Value { self } + + public static func ==(lhs: SingleValueInstruction, rhs: SingleValueInstruction) -> Bool { + lhs === rhs + } } public final class MultipleValueInstructionResult : Value { diff --git a/test/SILOptimizer/accessutils.sil b/test/SILOptimizer/accessutils.sil index b6d0c8c807089..534ec10ef5cb7 100644 --- a/test/SILOptimizer/accessutils.sil +++ b/test/SILOptimizer/accessutils.sil @@ -21,6 +21,11 @@ struct S { var y: Int64 } +struct TwoInts { + var a: Int64 + var b: Int64 +} + struct Ptr { var p: Int64 } @@ -30,8 +35,7 @@ struct Ptr { // CHECK-NEXT: Scope: base // CHECK-NEXT: Base: argument - %0 = argument of bb0 : $*Int64 // CHECK-NEXT: Path: "" -// CHECK-NEXT: Storage: %0 = argument of bb0 : $*Int64 -// CHECK-NEXT: Path: "" +// CHECK-NEXT: no Storage paths // CHECK-NEXT: End accesses for readIdentifiedArg sil [ossa] @readIdentifiedArg : $@convention(thin) (@in Int64) -> Int64 { bb0(%0 : $*Int64): @@ -44,8 +48,7 @@ bb0(%0 : $*Int64): // CHECK-NEXT: Scope: base // CHECK-NEXT: Base: argument - %0 = argument of bb0 : $*Int64 // CHECK-NEXT: Path: "" -// CHECK-NEXT: Storage: %0 = argument of bb0 : $*Int64 -// CHECK-NEXT: Path: "" +// CHECK-NEXT: no Storage paths // CHECK-NEXT: End accesses for writeIdentifiedArg sil [ossa] @writeIdentifiedArg : $@convention(thin) (@inout Int64) -> () { bb0(%0 : $*Int64): @@ -56,15 +59,15 @@ bb0(%0 : $*Int64): return %5 : $() } -// CHECK-LABEL: Accesses for $writeToHead +// CHECK-LABEL: Accesses for writeToHead // CHECK-NEXT: Value: %7 = begin_access [modify] [dynamic] %6 : $*Int64 // CHECK-NEXT: Scope: %7 = begin_access [modify] [dynamic] %6 : $*Int64 // CHECK-NEXT: Base: class - %6 = ref_element_addr %5 : $List, #List.x // CHECK-NEXT: Path: "" // CHECK-NEXT: Storage: %0 = argument of bb0 : $S // CHECK-NEXT: Path: "s0.c0" -// CHECK-NEXT: End accesses for $writeToHead -sil [ossa] @$writeToHead : $@convention(thin) (@guaranteed S) -> () { +// CHECK-NEXT: End accesses for writeToHead +sil [ossa] @writeToHead : $@convention(thin) (@guaranteed S) -> () { bb0(%0 : @guaranteed $S): debug_value %0 : $S, let, name "s", argno 1 %2 = struct_extract %0 : $S, #S.l @@ -95,32 +98,32 @@ bb0(%0 : @guaranteed $S): // CHECK-NEXT: Path: "c0" // CHECK-NEXT: End accesses for storeToArgs sil [ossa] @storeToArgs : $@convention(thin) (@guaranteed List, @guaranteed List) -> () { -bb0(%1 : @guaranteed $List, %2 : @guaranteed $List): +bb0(%0 : @guaranteed $List, %1 : @guaranteed $List): cond_br undef, bb1, bb2 bb1: - %8 = integer_literal $Builtin.Int64, 10 - %9 = struct $Int64 (%8 : $Builtin.Int64) - %10 = ref_element_addr %1 : $List, #List.x - %11 = begin_access [modify] [dynamic] %10 : $*Int64 - store %9 to [trivial] %11 : $*Int64 - end_access %11 : $*Int64 - %14 = tuple () + %3 = integer_literal $Builtin.Int64, 10 + %4 = struct $Int64 (%3 : $Builtin.Int64) + %5 = ref_element_addr %0 : $List, #List.x + %6 = begin_access [modify] [dynamic] %5 : $*Int64 + store %4 to [trivial] %6 : $*Int64 + end_access %6 : $*Int64 + %9 = tuple () br bb3 bb2: - %16 = integer_literal $Builtin.Int64, 20 - %17 = struct $Int64 (%16 : $Builtin.Int64) - %18 = ref_element_addr %2 : $List, #List.x - %19 = begin_access [modify] [dynamic] %18 : $*Int64 - store %17 to [trivial] %19 : $*Int64 - end_access %19 : $*Int64 - %22 = tuple () + %11 = integer_literal $Builtin.Int64, 20 + %12 = struct $Int64 (%11 : $Builtin.Int64) + %13 = ref_element_addr %1 : $List, #List.x + %14 = begin_access [modify] [dynamic] %13 : $*Int64 + store %12 to [trivial] %14 : $*Int64 + end_access %14 : $*Int64 + %17 = tuple () br bb3 bb3: - %24 = tuple () - return %24 : $() + %19 = tuple () + return %19 : $() } // CHECK-LABEL: Accesses for storeMaybeLocalPhi @@ -134,28 +137,29 @@ bb3: // CHECK-NEXT: Path: "c0" // CHECK-NEXT: End accesses for storeMaybeLocalPhi sil @storeMaybeLocalPhi : $@convention(thin) (@guaranteed List) -> () { -bb0(%1 : $List): +bb0(%0 : $List): cond_br undef, bb1, bb2 bb1: - strong_retain %1 : $List - br bb3(%1 : $List) + strong_retain %0 : $List + br bb3(%0 : $List) bb2: - %10 = alloc_ref $List - br bb3(%10 : $List) - -bb3(%12 : $List): - %14 = integer_literal $Builtin.Int64, 20 - %15 = struct $Int64 (%14 : $Builtin.Int64) - %16 = ref_element_addr %12 : $List, #List.x - %17 = begin_access [modify] [dynamic] %16 : $*Int64 - store %15 to %17 : $*Int64 - end_access %17 : $*Int64 - %20 = tuple () - strong_release %12 : $List - %22 = tuple () - return %22 : $() + %4 = alloc_ref $List + br bb3(%4 : $List) + + +bb3(%6 : $List): + %7 = integer_literal $Builtin.Int64, 20 + %8 = struct $Int64 (%7 : $Builtin.Int64) + %9 = ref_element_addr %6 : $List, #List.x + %10 = begin_access [modify] [dynamic] %9 : $*Int64 + store %8 to %10 : $*Int64 + end_access %10 : $*Int64 + %13 = tuple () + strong_release %6 : $List + %15 = tuple () + return %15 : $() } @@ -164,8 +168,7 @@ bb3(%12 : $List): // CHECK-NEXT: Scope: base // CHECK-NEXT: Base: argument - %0 = argument of bb0 : $*Ptr // CHECK-NEXT: Path: "s0" -// CHECK-NEXT: Storage: %0 = argument of bb0 : $*Ptr -// CHECK-NEXT: Path: "s0" +// CHECK-NEXT: no Storage paths // CHECK-NEXT: End accesses for testStructPhiCommon sil [ossa] @testStructPhiCommon : $@convention(thin) (@inout Ptr) -> () { bb0(%0 : $*Ptr): @@ -180,13 +183,13 @@ bb2: %5 = address_to_pointer %2 : $*Int64 to $Builtin.RawPointer br bb3(%5 : $Builtin.RawPointer) -bb3(%6 : $Builtin.RawPointer) : +bb3(%6 : $Builtin.RawPointer): %7 = pointer_to_address %6 : $Builtin.RawPointer to $*Int64 %8 = integer_literal $Builtin.Int64, 2 %9 = struct $Int64 (%8 : $Builtin.Int64) store %9 to [trivial] %7 : $*Int64 - %22 = tuple () - return %22 : $() + %11 = tuple () + return %11 : $() } // CHECK-LABEL: Accesses for testStructPhiDivergent @@ -194,35 +197,34 @@ bb3(%6 : $Builtin.RawPointer) : // CHECK-NEXT: Scope: base // CHECK-NEXT: Base: pointer - %10 = pointer_to_address %9 : $Builtin.RawPointer to $*Int64 // user: %13 // CHECK-NEXT: Path: "" -// CHECK-NEXT: Storage: %10 = pointer_to_address %9 : $Builtin.RawPointer to $*Int64 // user: %13 -// CHECK-NEXT: Path: "" +// CHECK-NEXT: no Storage paths // CHECK-NEXT: End accesses for testStructPhiDivergent sil [ossa] @testStructPhiDivergent : $@convention(thin) (@inout Ptr) -> () { bb0(%0 : $*Ptr): - %ptr = alloc_stack $Ptr + %1 = alloc_stack $Ptr cond_br undef, bb1, bb2 bb1: - %2 = struct_element_addr %ptr : $*Ptr, #Ptr.p - %3 = address_to_pointer %2 : $*Int64 to $Builtin.RawPointer - br bb3(%3 : $Builtin.RawPointer) + %3 = struct_element_addr %1 : $*Ptr, #Ptr.p + %4 = address_to_pointer %3 : $*Int64 to $Builtin.RawPointer + br bb3(%4 : $Builtin.RawPointer) bb2: - %4 = struct_element_addr %0 : $*Ptr, #Ptr.p - %5 = address_to_pointer %4 : $*Int64 to $Builtin.RawPointer - br bb3(%5 : $Builtin.RawPointer) - -bb3(%6 : $Builtin.RawPointer) : - %7 = pointer_to_address %6 : $Builtin.RawPointer to $*Int64 - %8 = integer_literal $Builtin.Int64, 2 - %9 = struct $Int64 (%8 : $Builtin.Int64) - store %9 to [trivial] %7 : $*Int64 - dealloc_stack %ptr : $*Ptr - %22 = tuple () - return %22 : $() + %6 = struct_element_addr %0 : $*Ptr, #Ptr.p + %7 = address_to_pointer %6 : $*Int64 to $Builtin.RawPointer + br bb3(%7 : $Builtin.RawPointer) + + +bb3(%9 : $Builtin.RawPointer): + %10 = pointer_to_address %9 : $Builtin.RawPointer to $*Int64 + %11 = integer_literal $Builtin.Int64, 2 + %12 = struct $Int64 (%11 : $Builtin.Int64) + store %12 to [trivial] %10 : $*Int64 + dealloc_stack %1 : $*Ptr + %15 = tuple () + return %15 : $() } - // CHECK-LABEL: Accesses for readIdentifiedBoxArg // CHECK-NEXT: Value: %2 = begin_access [read] [dynamic] %1 : $*Int64 // CHECK-NEXT: Scope: %2 = begin_access [read] [dynamic] %1 : $*Int64 @@ -246,6 +248,7 @@ class A { } class B : A { var prop1: Int64 + var prop2: Int64 } // CHECK-LABEL: Accesses for testNonUniquePropertyIndex @@ -308,13 +311,13 @@ struct MyArray { // CHECK-NEXT: Path: "s0.s0.s0.c0.s0.s0.s0" // CHECK-NEXT: Value: %11 = struct_element_addr %10 : $*String, #String._guts // CHECK-NEXT: Scope: base -// CHECK-NEXT: Base: tail - %10 = ref_tail_addr [immutable] %4 : $MyContiguousArrayStorageBase, $String +// CHECK-NEXT: Base: tail - %4 = unchecked_ref_cast %3 : $Builtin.BridgeObject to $MyContiguousArrayStorageBase // CHECK-NEXT: Path: "s0" // CHECK-NEXT: Storage: %0 = argument of bb0 : $MyArray // CHECK-NEXT: Path: "s0.s0.s0.ct.s0" // CHECK-NEXT: Value: %10 = ref_tail_addr [immutable] %4 : $MyContiguousArrayStorageBase, $String // CHECK-NEXT: Scope: base -// CHECK-NEXT: Base: tail - %10 = ref_tail_addr [immutable] %4 : $MyContiguousArrayStorageBase, $String +// CHECK-NEXT: Base: tail - %4 = unchecked_ref_cast %3 : $Builtin.BridgeObject to $MyContiguousArrayStorageBase // CHECK-NEXT: Path: "" // CHECK-NEXT: Storage: %0 = argument of bb0 : $MyArray // CHECK-NEXT: Path: "s0.s0.s0.ct" @@ -337,3 +340,162 @@ bb0(%0 : $MyArray): %14 = tuple () return %14 : $() } + +sil_global @global1 : $Int64 +sil_global @global2 : $Int64 + +sil @coro : $@yield_once @convention(thin) () -> @yields @inout Int64 + +sil @_isDistinct : $@convention(thin) (@inout T1, @inout T2) -> () +sil @_isNotDistinct : $@convention(thin) (@inout T1, @inout T2) -> () + +// CHECK-LABEL: Accesses for testAccessBaseAliasing +// CHECK-NEXT: End accesses for testAccessBaseAliasing +sil @testAccessBaseAliasing : $@convention(thin) (@inout Int64, @inout_aliasable Int64, @inout_aliasable Int64, Builtin.RawPointer, Builtin.RawPointer, @guaranteed B, @guaranteed B, @guaranteed { var Int64, var Int64 }, @guaranteed { var Int64, var Int64 }) -> () { +bb0(%inoutArg : $*Int64, %aliasableArg1 : $*Int64, %aliasableArg2 : $*Int64, %3 : $Builtin.RawPointer, %4 : $Builtin.RawPointer, %5 : $B, %6 : $B, %7 : ${ var Int64, var Int64 }, %8 : ${ var Int64, var Int64 }): + %pointer1 = pointer_to_address %3 : $Builtin.RawPointer to $*Int64 + %pointer2 = pointer_to_address %4 : $Builtin.RawPointer to $*Int64 + + %stack1 = alloc_stack $Int64 + %stack2 = alloc_stack $Int64 + + %20 = alloc_ref $B + %21 = alloc_ref $B + %prop1OfClassArg1 = ref_element_addr %5 : $B, #B.prop1 + %prop1OfClassArg2 = ref_element_addr %6 : $B, #B.prop1 + %prop2OfClassArg2 = ref_element_addr %6 : $B, #B.prop2 + %prop1OfLocalClass1 = ref_element_addr %20 : $B, #B.prop1 + %prop1OfLocalClass2 = ref_element_addr %21 : $B, #B.prop1 + %prop2OfLocalClass2 = ref_element_addr %21 : $B, #B.prop2 + %tailOfClassArg1 = ref_tail_addr %5 : $B, $Int64 + %tailOfClassArg2 = ref_tail_addr %6 : $B, $Int64 + %tailOfLocalClass1 = ref_tail_addr %20 : $B, $Int64 + %tailOfLocalClass2 = ref_tail_addr %21 : $B, $Int64 + + %30 = alloc_box ${ var Int64, var Int64 } + %31 = alloc_box ${ var Int64, var Int64 } + %field0OfBoxArg1 = project_box %7 : ${ var Int64, var Int64 }, 0 + %field0OfBoxArg2 = project_box %8 : ${ var Int64, var Int64 }, 0 + %field1OfBoxArg2 = project_box %8 : ${ var Int64, var Int64 }, 1 + %field0OfLocalBox1 = project_box %30 : ${ var Int64, var Int64 }, 0 + %field0OfLocalBox2 = project_box %31 : ${ var Int64, var Int64 }, 0 + %field1OfLocalBox2 = project_box %31 : ${ var Int64, var Int64 }, 1 + + %global1 = global_addr @global1 : $*Int64 + %global2 = global_addr @global2 : $*Int64 + + %50 = function_ref @coro : $@yield_once @convention(thin) () -> @yields @inout Int64 + (%yield1, %52) = begin_apply %50() : $@yield_once @convention(thin) () -> @yields @inout Int64 + end_apply %52 + (%yield2, %55) = begin_apply %50() : $@yield_once @convention(thin) () -> @yields @inout Int64 + end_apply %55 + + %isDistinct = function_ref @_isDistinct : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %isNotDistinct = function_ref @_isNotDistinct : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Function arguments + %101 = apply %isDistinct(%inoutArg, %aliasableArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %102 = apply %isNotDistinct(%aliasableArg1, %aliasableArg2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Pointers + %103 = apply %isNotDistinct(%pointer1, %pointer2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Stack allocations + %104 = apply %isNotDistinct(%stack1, %stack1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %105 = apply %isDistinct(%stack1, %stack2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Classes + %121 = apply %isNotDistinct(%prop1OfClassArg1, %prop1OfClassArg2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %122 = apply %isDistinct(%prop1OfClassArg1, %prop2OfClassArg2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %123 = apply %isNotDistinct(%prop1OfLocalClass1, %prop1OfLocalClass1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %124 = apply %isDistinct(%prop1OfLocalClass1, %prop1OfLocalClass2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %125 = apply %isDistinct(%prop1OfLocalClass1, %prop2OfLocalClass2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %126 = apply %isDistinct(%prop1OfLocalClass1, %prop1OfClassArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Tail elements + %127 = apply %isNotDistinct(%tailOfClassArg1, %tailOfClassArg2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %128 = apply %isDistinct(%tailOfClassArg1, %tailOfLocalClass1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %129 = apply %isDistinct(%tailOfLocalClass1, %tailOfLocalClass2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %130 = apply %isNotDistinct(%tailOfLocalClass1, %tailOfLocalClass1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Boxes + %131 = apply %isNotDistinct(%field0OfBoxArg1, %field0OfBoxArg2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %132 = apply %isDistinct(%field0OfBoxArg1, %field1OfBoxArg2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %133 = apply %isNotDistinct(%field0OfLocalBox1, %field0OfLocalBox1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %134 = apply %isDistinct(%field0OfLocalBox1, %field0OfLocalBox2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %135 = apply %isDistinct(%field0OfLocalBox1, %field1OfLocalBox2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %136 = apply %isDistinct(%field0OfLocalBox1, %field0OfBoxArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Globals + %140 = apply %isNotDistinct(%global1, %global1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %141 = apply %isDistinct(%global1, %global2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Yields + %145 = apply %isNotDistinct(%yield1, %yield1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %146 = apply %isNotDistinct(%yield1, %yield2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Function arguments vs others + %150 = apply %isNotDistinct(%inoutArg, %pointer1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %151 = apply %isNotDistinct(%aliasableArg1, %pointer1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %152 = apply %isDistinct(%inoutArg, %stack1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %153 = apply %isDistinct(%aliasableArg1, %stack1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %154 = apply %isDistinct(%inoutArg, %prop1OfClassArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %155 = apply %isNotDistinct(%aliasableArg1, %prop1OfClassArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %156 = apply %isDistinct(%inoutArg, %prop1OfLocalClass1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %157 = apply %isDistinct(%aliasableArg1, %prop1OfLocalClass1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %158 = apply %isDistinct(%inoutArg, %tailOfClassArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %159 = apply %isDistinct(%aliasableArg1, %tailOfLocalClass1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %160 = apply %isDistinct(%inoutArg, %field0OfBoxArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %161 = apply %isNotDistinct(%aliasableArg1, %field0OfBoxArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %162 = apply %isDistinct(%inoutArg, %field0OfLocalBox1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %163 = apply %isDistinct(%aliasableArg1, %field0OfLocalBox1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %164 = apply %isNotDistinct(%inoutArg, %yield1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %165 = apply %isNotDistinct(%aliasableArg1, %yield2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Classes vs others + %170 = apply %isNotDistinct(%prop1OfClassArg1, %pointer1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %171 = apply %isNotDistinct(%prop1OfLocalClass1, %pointer1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %172 = apply %isDistinct(%prop1OfClassArg1, %stack1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %173 = apply %isDistinct(%prop1OfClassArg1, %tailOfClassArg2) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %174 = apply %isDistinct(%prop1OfClassArg1, %field0OfBoxArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %175 = apply %isDistinct(%prop1OfClassArg1, %global1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %176 = apply %isNotDistinct(%prop1OfClassArg1, %yield1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Tail elements vs others + %180 = apply %isNotDistinct(%tailOfClassArg1, %pointer1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %181 = apply %isNotDistinct(%tailOfLocalClass1, %pointer1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %182 = apply %isDistinct(%tailOfClassArg1, %stack1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %183 = apply %isDistinct(%tailOfClassArg1, %field0OfBoxArg1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %184 = apply %isDistinct(%tailOfClassArg1, %global1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %185 = apply %isNotDistinct(%tailOfClassArg1, %yield1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // Yields vs others + %190 = apply %isNotDistinct(%yield1, %pointer1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %191 = apply %isNotDistinct(%yield1, %stack1) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + dealloc_stack %stack2 : $*Int64 + dealloc_stack %stack1 : $*Int64 + %200 = tuple () + return %200 : $() +} + +// CHECK-LABEL: Accesses for testAccessPathAliasing +// CHECK-NEXT: End accesses for testAccessPathAliasing +sil @testAccessPathAliasing : $@convention(thin) (@inout TwoInts) -> () { +bb0(%twoInts: $*TwoInts): + %a = struct_element_addr %twoInts : $*TwoInts, #TwoInts.a + %b = struct_element_addr %twoInts : $*TwoInts, #TwoInts.b + + %isDistinct = function_ref @_isDistinct : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %isNotDistinct = function_ref @_isNotDistinct : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + %10 = apply %isNotDistinct(%twoInts, %twoInts) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %11 = apply %isNotDistinct(%twoInts, %a) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %12 = apply %isNotDistinct(%b, %twoInts) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + %13 = apply %isDistinct(%a, %b) : $@convention(thin) <Ï„_0_0, Ï„_0_1> (@inout Ï„_0_0, @inout Ï„_0_1) -> () + + // More complex paths are tested in the unit test for `SmallProjectionPath.mayOverlap`. + + %200 = tuple () + return %200 : $() +} From b9f9eac7d96aa38739dd491c8b40723815fa6f19 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 22 Aug 2022 16:24:08 +0100 Subject: [PATCH 267/491] [cxx-interop] NFC: Remove unused source file `libcxxshim.swift` is not referenced from CMakeLists, and is not needed because libcxxshim is a pure C++ module. --- stdlib/public/Cxx/cxxshim/libcxxshim.swift | 1 - 1 file changed, 1 deletion(-) delete mode 100644 stdlib/public/Cxx/cxxshim/libcxxshim.swift diff --git a/stdlib/public/Cxx/cxxshim/libcxxshim.swift b/stdlib/public/Cxx/cxxshim/libcxxshim.swift deleted file mode 100644 index ecd332d341ba3..0000000000000 --- a/stdlib/public/Cxx/cxxshim/libcxxshim.swift +++ /dev/null @@ -1 +0,0 @@ -@_exported import CxxShim // Clang module \ No newline at end of file From 45b81f6456ac11dabc34e337ec1155df6b91cafc Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 17 Aug 2022 17:07:12 -0600 Subject: [PATCH 268/491] [stdlib] add overflow checks for some pointer arithmetic - Overflow checks added for recent additions to pointer arithmetic (rounding and property pointers). - The basic `advanced(by:)` functions will need to be dealt with separately. --- stdlib/public/core/UnsafePointer.swift | 15 +++++++++++++++ stdlib/public/core/UnsafeRawPointer.swift | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index 526c4769de5d3..310955a162b38 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -371,6 +371,11 @@ public struct UnsafePointer: _Pointer { to property: KeyPath ) -> UnsafePointer? { guard let o = property._storedInlineOffset else { return nil } + _internalInvariant(o >= 0) + _debugPrecondition( + o == 0 || UnsafeRawPointer(self) < UnsafeRawPointer(bitPattern: 0 &- o)!, + "Overflow in pointer arithmetic" + ) return .init(Builtin.gepRaw_Word(_rawValue, o._builtinWordValue)) } @@ -1088,6 +1093,11 @@ public struct UnsafeMutablePointer: _Pointer { to property: KeyPath ) -> UnsafePointer? { guard let o = property._storedInlineOffset else { return nil } + _internalInvariant(o >= 0) + _debugPrecondition( + o == 0 || UnsafeRawPointer(self) < UnsafeRawPointer(bitPattern: 0 &- o)!, + "Overflow in pointer arithmetic" + ) return .init(Builtin.gepRaw_Word(_rawValue, o._builtinWordValue)) } @@ -1105,6 +1115,11 @@ public struct UnsafeMutablePointer: _Pointer { to property: WritableKeyPath ) -> UnsafeMutablePointer? { guard let o = property._storedInlineOffset else { return nil } + _internalInvariant(o >= 0) + _debugPrecondition( + o == 0 || UnsafeRawPointer(self) < UnsafeRawPointer(bitPattern: 0 &- o)!, + "Overflow in pointer arithmetic" + ) return .init(Builtin.gepRaw_Word(_rawValue, o._builtinWordValue)) } diff --git a/stdlib/public/core/UnsafeRawPointer.swift b/stdlib/public/core/UnsafeRawPointer.swift index 7c83233ead1d2..25272a86db727 100644 --- a/stdlib/public/core/UnsafeRawPointer.swift +++ b/stdlib/public/core/UnsafeRawPointer.swift @@ -499,6 +499,7 @@ extension UnsafeRawPointer { public func alignedUp(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = (UInt(Builtin.ptrtoint_Word(_rawValue)) &+ mask) & ~mask + _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } @@ -515,6 +516,7 @@ extension UnsafeRawPointer { public func alignedDown(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = UInt(Builtin.ptrtoint_Word(_rawValue)) & ~mask + _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } @@ -536,6 +538,7 @@ extension UnsafeRawPointer { "alignment must be a whole power of 2." ) let bits = (UInt(Builtin.ptrtoint_Word(_rawValue)) &+ mask) & ~mask + _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } @@ -557,6 +560,7 @@ extension UnsafeRawPointer { "alignment must be a whole power of 2." ) let bits = UInt(Builtin.ptrtoint_Word(_rawValue)) & ~mask + _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } } @@ -1351,6 +1355,7 @@ extension UnsafeMutableRawPointer { public func alignedUp(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = (UInt(Builtin.ptrtoint_Word(_rawValue)) &+ mask) & ~mask + _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } @@ -1367,6 +1372,7 @@ extension UnsafeMutableRawPointer { public func alignedDown(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = UInt(Builtin.ptrtoint_Word(_rawValue)) & ~mask + _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } @@ -1388,6 +1394,7 @@ extension UnsafeMutableRawPointer { "alignment must be a whole power of 2." ) let bits = (UInt(Builtin.ptrtoint_Word(_rawValue)) &+ mask) & ~mask + _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } @@ -1409,6 +1416,7 @@ extension UnsafeMutableRawPointer { "alignment must be a whole power of 2." ) let bits = UInt(Builtin.ptrtoint_Word(_rawValue)) & ~mask + _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } } From 7c416ee1228c59b210f9dd052de44bae3e181abf Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 22 Aug 2022 09:22:04 -0700 Subject: [PATCH 269/491] [Localization] Implement `.def` to `.strings` converter Format is as follows: - Comment: /* ... */ - Diagnostic: "" = ""; --- .../swift/Localization/LocalizationFormat.h | 39 ++++ lib/Localization/LocalizationFormat.cpp | 169 +++++++++++++++++- 2 files changed, 204 insertions(+), 4 deletions(-) diff --git a/include/swift/Localization/LocalizationFormat.h b/include/swift/Localization/LocalizationFormat.h index 63b6e7d85f2ef..50ec3927a8e21 100644 --- a/include/swift/Localization/LocalizationFormat.h +++ b/include/swift/Localization/LocalizationFormat.h @@ -64,6 +64,20 @@ class DefToYAMLConverter { void convert(llvm::raw_ostream &out); }; +class DefToStringsConverter { + llvm::ArrayRef IDs; + llvm::ArrayRef Messages; + +public: + DefToStringsConverter(llvm::ArrayRef ids, + llvm::ArrayRef messages) + : IDs(ids), Messages(messages) { + assert(IDs.size() == Messages.size()); + } + + void convert(llvm::raw_ostream &out); +}; + class LocalizationWriterInfo { public: using key_type = uint32_t; @@ -225,6 +239,31 @@ class YAMLLocalizationProducer final : public LocalizationProducer { llvm::StringRef getMessage(swift::DiagID id) const override; }; +class StringsLocalizationProducer final : public LocalizationProducer { + std::string filePath; + + std::vector diagnostics; + +public: + explicit StringsLocalizationProducer(llvm::StringRef filePath, + bool printDiagnosticNames = false) + : LocalizationProducer(printDiagnosticNames), filePath(filePath) {} + + /// Iterate over all of the available (non-empty) translations + /// maintained by this producer, callback gets each translation + /// with its unique identifier. + void forEachAvailable( + llvm::function_ref callback); + +protected: + bool initializeImpl() override; + llvm::StringRef getMessage(swift::DiagID id) const override; + +private: + static void readStringsFile(llvm::MemoryBuffer *in, + std::vector &diagnostics); +}; + class SerializedLocalizationProducer final : public LocalizationProducer { using SerializedLocalizationTable = llvm::OnDiskIterableChainedHashTable; diff --git a/lib/Localization/LocalizationFormat.cpp b/lib/Localization/LocalizationFormat.cpp index 53c47c880d4d4..40368b6b5fac6 100644 --- a/lib/Localization/LocalizationFormat.cpp +++ b/lib/Localization/LocalizationFormat.cpp @@ -184,7 +184,6 @@ void YAMLLocalizationProducer::forEachAvailable( std::unique_ptr LocalizationProducer::producerFor(llvm::StringRef locale, llvm::StringRef path, bool printDiagnosticNames) { - std::unique_ptr producer; llvm::SmallString<128> filePath(path); llvm::sys::path::append(filePath, locale); llvm::sys::path::replace_extension(filePath, ".db"); @@ -193,7 +192,7 @@ LocalizationProducer::producerFor(llvm::StringRef locale, llvm::StringRef path, // fallback to the `YAML` file. if (llvm::sys::fs::exists(filePath)) { if (auto file = llvm::MemoryBuffer::getFile(filePath)) { - producer = std::make_unique( + return std::make_unique( std::move(file.get()), printDiagnosticNames); } } else { @@ -201,12 +200,18 @@ LocalizationProducer::producerFor(llvm::StringRef locale, llvm::StringRef path, // In case of missing localization files, we should fallback to messages // from `.def` files. if (llvm::sys::fs::exists(filePath)) { - producer = std::make_unique( + return std::make_unique( + filePath.str(), printDiagnosticNames); + } + + llvm::sys::path::replace_extension(filePath, ".strings"); + if (llvm::sys::fs::exists(filePath)) { + return std::make_unique( filePath.str(), printDiagnosticNames); } } - return producer; + return std::unique_ptr(); } llvm::Optional LocalizationInput::readID(llvm::yaml::IO &io) { @@ -289,5 +294,161 @@ void DefToYAMLConverter::convert(llvm::raw_ostream &out) { } } +void DefToStringsConverter::convert(llvm::raw_ostream &out) { + // "" = ""; + for (auto i : swift::indices(IDs)) { + out << "\"" << IDs[i] << "\""; + out << " = "; + + const std::string &msg = Messages[i]; + + out << "\""; + for (unsigned j = 0; j < msg.length(); ++j) { + // Escape '"' found in the message. + if (msg[j] == '"') + out << '\\'; + + out << msg[j]; + } + + out << "\";\r\n"; + } +} + +bool StringsLocalizationProducer::initializeImpl() { + auto FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(filePath); + llvm::MemoryBuffer *document = FileBufOrErr->get(); + readStringsFile(document, diagnostics); + return true; +} + +llvm::StringRef +StringsLocalizationProducer::getMessage(swift::DiagID id) const { + return diagnostics[(unsigned)id]; +} + +void StringsLocalizationProducer::forEachAvailable( + llvm::function_ref callback) { + initializeIfNeeded(); + if (getState() == FailedInitialization) { + return; + } + + for (uint32_t i = 0, n = diagnostics.size(); i != n; ++i) { + auto translation = diagnostics[i]; + if (!translation.empty()) + callback(static_cast(i), translation); + } +} + +void StringsLocalizationProducer::readStringsFile( + llvm::MemoryBuffer *in, std::vector &diagnostics) { + std::map diagLocs; +#define DIAG(KIND, ID, Options, Text, Signature) \ + diagLocs[#ID] = static_cast(LocalDiagID::ID); +#include "swift/AST/DiagnosticsAll.def" +#undef DIAG + + // Allocate enough slots to fit all the possible diagnostics + // this helps to identify which diagnostics are missing. + diagnostics.resize(LocalDiagID::NumDiags); + + // The format is as follows: + // + // - comment: /* ... */ + // - translation: "" = ""; + auto buffer = in->getBuffer(); + while (!buffer.empty()) { + // consume comment. + if (buffer.startswith("/*")) { + auto endOfComment = buffer.find("*/"); + assert(endOfComment != std::string::npos); + // Consume the comment and trailing `*/` + buffer = buffer.drop_front(endOfComment + 2).ltrim(); + continue; + } + + assert(buffer.startswith("\"") && "malformed diagnostics file"); + + // Consume leading `"` + buffer = buffer.drop_front(); + + // Valid diagnostic id cannot have any `"` in it. + auto idSize = buffer.find_first_of('\"'); + assert(idSize != std::string::npos); + + std::string id(buffer.data(), idSize); + + // consume id and `" = "`. There could be a variable number of + // spaces on each side of `=`. + { + // Consume id, trailing `"`, and all spaces before `=` + buffer = buffer.drop_front(idSize + 1).ltrim(' '); + + // Consume `=` and all trailing spaces until `"` + { + assert(!buffer.empty() && buffer.front() == '='); + buffer = buffer.drop_front().ltrim(' '); + } + + // Consume `"` at the beginning of the diagnostic message. + { + assert(!buffer.empty() && buffer.front() == '\"'); + buffer = buffer.drop_front(); + } + } + + llvm::SmallString<64> msg; + { + bool isValid = false; + // Look for `";` which denotes the end of message + for (unsigned i = 0, n = buffer.size(); i != n; ++i) { + if (buffer[i] != '\"') { + msg.push_back(buffer[i]); + continue; + } + + // Leading `"` has been comsumed. + assert(i > 0); + + // Let's check whether this `"` is escaped, and if so - continue + // because `"` is part of the message. + if (buffer[i - 1] == '\\') { + // Drop `\` added for escaping. + msg.pop_back(); + msg.push_back(buffer[i]); + continue; + } + + // If current `"` was not escaped and it's followed by `;` - + // we have reached the end of the message, otherwise + // the input is malformed. + if (i + 1 < n && buffer[i + 1] == ';') { + // Consume the message and its trailing info. + buffer = buffer.drop_front(i + 2).ltrim(); + // Mark message as valid. + isValid = true; + break; + } else { + llvm_unreachable("malformed diagnostics file"); + } + } + + assert(isValid && "malformed diagnostic message"); + } + + // Check whether extracted diagnostic still exists in the + // system and if not - record as unknown. + { + auto existing = diagLocs.find(id); + if (existing != diagLocs.end()) { + diagnostics[existing->second] = std::string(msg); + } else { + llvm::errs() << "[!] Unknown diagnostic: " << id << '\n'; + } + } + } +} + } // namespace diag } // namespace swift From 799fff6750980f952202b9134255dfa026a60029 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 22 Aug 2022 09:24:43 -0700 Subject: [PATCH 270/491] [Localization] Implement `.def` to `.strings` converter tool --- tools/CMakeLists.txt | 1 + .../CMakeLists.txt | 7 ++ .../swift-def-to-strings-converter.cpp | 104 ++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 tools/swift-def-to-strings-converter/CMakeLists.txt create mode 100644 tools/swift-def-to-strings-converter/swift-def-to-strings-converter.cpp diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 60b0ae223681e..b2edb7bb68b46 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -23,6 +23,7 @@ add_swift_tool_subdirectory(swift-dependency-tool) add_swift_tool_subdirectory(swift-demangle) add_swift_tool_subdirectory(swift-demangle-yamldump) add_swift_tool_subdirectory(swift-def-to-yaml-converter) +add_swift_tool_subdirectory(swift-def-to-strings-converter) add_swift_tool_subdirectory(swift-serialize-diagnostics) add_swift_tool_subdirectory(sil-func-extractor) add_swift_tool_subdirectory(sil-llvm-gen) diff --git a/tools/swift-def-to-strings-converter/CMakeLists.txt b/tools/swift-def-to-strings-converter/CMakeLists.txt new file mode 100644 index 0000000000000..2bfd9145a5a30 --- /dev/null +++ b/tools/swift-def-to-strings-converter/CMakeLists.txt @@ -0,0 +1,7 @@ +add_swift_host_tool(swift-def-to-strings-converter + swift-def-to-strings-converter.cpp + SWIFT_COMPONENT tools +) + +target_link_libraries(swift-def-to-strings-converter PRIVATE + swiftLocalization) diff --git a/tools/swift-def-to-strings-converter/swift-def-to-strings-converter.cpp b/tools/swift-def-to-strings-converter/swift-def-to-strings-converter.cpp new file mode 100644 index 0000000000000..0d745a7d44d23 --- /dev/null +++ b/tools/swift-def-to-strings-converter/swift-def-to-strings-converter.cpp @@ -0,0 +1,104 @@ +//===--- swift-def-to-strings-converter.cpp -------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// +// +// Create a .strings file from the diagnostic messages text in `.def` files. +// +//===----------------------------------------------------------------------===// + +#include "swift/Basic/LLVMInitialize.h" +#include "swift/Basic/Compiler.h" +#include "swift/Localization/LocalizationFormat.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +static constexpr const char *const diagnosticID[] = { +#define DIAG(KIND, ID, Options, Text, Signature) #ID, +#include "swift/AST/DiagnosticsAll.def" +}; + +static constexpr const char *const diagnosticMessages[] = { +#define DIAG(KIND, ID, Options, Text, Signature) Text, +#include "swift/AST/DiagnosticsAll.def" +}; + +enum LocalDiagID : uint32_t { +#define DIAG(KIND, ID, Options, Text, Signature) ID, +#include "swift/AST/DiagnosticsAll.def" + NumDiags +}; + +namespace options { + +static llvm::cl::OptionCategory + Category("swift-def-to-strings-converter Options"); + +static llvm::cl::opt + OutputDirectory("output-directory", + llvm::cl::desc("Directory for the output file"), + llvm::cl::cat(Category)); + +static llvm::cl::opt + OutputFilename("output-filename", + llvm::cl::desc("Filename for the output file"), + llvm::cl::cat(Category)); + +} // namespace options + +int main(int argc, char *argv[]) { + PROGRAM_START(argc, argv); + + llvm::cl::HideUnrelatedOptions(options::Category); + llvm::cl::ParseCommandLineOptions(argc, argv, + "Swift `.def` to `.strings` Converter\n"); + + llvm::SmallString<128> LocalizedFilePath; + if (options::OutputFilename.empty()) { + // The default language for localization is English + std::string defaultLocaleCode = "en"; + LocalizedFilePath = options::OutputDirectory; + llvm::sys::path::append(LocalizedFilePath, defaultLocaleCode); + llvm::sys::path::replace_extension(LocalizedFilePath, ".strings"); + } else { + LocalizedFilePath = options::OutputFilename; + } + + std::error_code error; + llvm::raw_fd_ostream OS(LocalizedFilePath.str(), error, + llvm::sys::fs::OF_None); + + if (OS.has_error() || error) { + llvm::errs() << "Error has occurred while trying to write to " + << LocalizedFilePath.str() + << " with error code: " << error.message() << "\n"; + return EXIT_FAILURE; + } + + llvm::ArrayRef ids(diagnosticID, LocalDiagID::NumDiags); + llvm::ArrayRef messages(diagnosticMessages, + LocalDiagID::NumDiags); + + swift::diag::DefToStringsConverter converter(ids, messages); + converter.convert(OS); + + return EXIT_SUCCESS; +} From c954130be0130c08d7120228e1ea2cb8e5a32114 Mon Sep 17 00:00:00 2001 From: Eric Miotto <1094986+edymtt@users.noreply.github.com> Date: Mon, 22 Aug 2022 09:37:52 -0700 Subject: [PATCH 271/491] Add a flag to infer appropriate cross compile hosts on Darwin Addresses rdar://98787335, apple#60348 --- utils/build-script | 15 +++++++++++++++ .../build_swift/driver_arguments.py | 5 +++++ utils/build_swift/tests/expected_options.py | 2 ++ ...er-cross-compile-hosts-on-darwin-linux.test | 13 +++++++++++++ ...r-cross-compile-hosts-on-darwin-macosx.test | 18 ++++++++++++++++++ 5 files changed, 53 insertions(+) create mode 100644 validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-linux.test create mode 100644 validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test diff --git a/utils/build-script b/utils/build-script index 1f9f32b653385..514579f6a2e8e 100755 --- a/utils/build-script +++ b/utils/build-script @@ -389,6 +389,21 @@ def apply_default_arguments(toolchain, args): '-DSWIFT_DARWIN_MODULE_ARCHS:STRING={}'.format( args.swift_darwin_module_archs)) + if (args.infer_cross_compile_hosts_on_darwin and + platform.system() == "Darwin"): + args.cross_compile_hosts = _infer_cross_compile_hosts_on_darwin() + print("Inferred the following hosts for cross compilations: " + f"{args.cross_compile_hosts}") + sys.stdout.flush() + + +def _infer_cross_compile_hosts_on_darwin(): + if platform.machine() == "x86_64": + return ["macosx-arm64"] + else: + return ["macosx-x86_64"] + + # ----------------------------------------------------------------------------- # Main (preset) diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index cb5fe04bb132e..6f8bddb019c68 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -580,6 +580,11 @@ def create_argument_parser(): help='A space separated list of targets to cross-compile host ' 'Swift tools for. Can be used multiple times.') + option('--infer-cross-compile-hosts-on-darwin', toggle_true, + help="When building on Darwin, automatically populate cross-compile-hosts " + "based on the architecture build-script is running on. " + "Has precedence over cross-compile-hosts") + option('--cross-compile-deps-path', store_path, help='The path to a directory that contains prebuilt cross-compiled ' 'library dependencies of the corelibs and other Swift repos, ' diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py index 16b89217332cd..7f7f896f6168d 100644 --- a/utils/build_swift/tests/expected_options.py +++ b/utils/build_swift/tests/expected_options.py @@ -133,6 +133,7 @@ 'cross_compile_append_host_target_to_destdir': True, 'cross_compile_deps_path': None, 'cross_compile_hosts': [], + 'infer_cross_compile_hosts_on_darwin': False, 'darwin_deployment_version_ios': defaults.DARWIN_DEPLOYMENT_VERSION_IOS, 'darwin_deployment_version_osx': @@ -732,6 +733,7 @@ class BuildScriptImplOption(_BaseOption): IntOption('--dsymutil-jobs', dest='dsymutil_jobs'), AppendOption('--cross-compile-hosts'), + SetTrueOption('--infer-cross-compile-hosts-on-darwin'), AppendOption('--extra-cmake-options'), AppendOption('--extra-swift-args'), AppendOption('--test-paths'), diff --git a/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-linux.test b/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-linux.test new file mode 100644 index 0000000000000..a8e2b20c87a1a --- /dev/null +++ b/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-linux.test @@ -0,0 +1,13 @@ +# REQUIRES: standalone_build +# REQUIRES: OS=linux-gnu + +# RUN: %empty-directory(%t) +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin --cmake %cmake 2>&1 | %FileCheck --check-prefix=NO-INFER-CROSS-COMPILE-HOSTS-ON-DARWIN %s +# RUN: %empty-directory(%t) +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin=1 --cmake %cmake 2>&1 | %FileCheck --check-prefix=NO-INFER-CROSS-COMPILE-HOSTS-ON-DARWIN %s +# RUN: %empty-directory(%t) +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --cmake %cmake 2>&1 | %FileCheck --check-prefix=NO-INFER-CROSS-COMPILE-HOSTS-ON-DARWIN %s +# RUN: %empty-directory(%t) +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin=0 --cmake %cmake 2>&1 | %FileCheck --check-prefix=NO-INFER-CROSS-COMPILE-HOSTS-ON-DARWIN %s + +# NO-INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-NOT: Inferred the following hosts for cross compilations: diff --git a/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test b/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test new file mode 100644 index 0000000000000..b5f1aed98d41c --- /dev/null +++ b/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test @@ -0,0 +1,18 @@ +# REQUIRES: standalone_build +# REQUIRES: OS=macosx + +# RUN: %empty-directory(%t) +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin --cmake %cmake 2>&1 | %FileCheck --check-prefix=INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-%target-cpu %s +# RUN: %empty-directory(%t) +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin=1 --cmake %cmake 2>&1 | %FileCheck --check-prefix=INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-%target-cpu %s + +# INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-x86_64: Inferred the following hosts for cross compilations: ['macosx-arm64'] +# INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-arm64: Inferred the following hosts for cross compilations: ['macosx-x86_64'] + + +# RUN: %empty-directory(%t) +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --cmake %cmake 2>&1 | %FileCheck --check-prefix=NO-INFER-CROSS-COMPILE-HOSTS-ON-DARWIN %s +# RUN: %empty-directory(%t) +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin=0 --cmake %cmake 2>&1 | %FileCheck --check-prefix=NO-INFER-CROSS-COMPILE-HOSTS-ON-DARWIN %s + +# NO-INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-NOT: Inferred the following hosts for cross compilations: From 778c7382a4d0c36223e93518676fd7551bbc98cf Mon Sep 17 00:00:00 2001 From: Eric Miotto <1094986+edymtt@users.noreply.github.com> Date: Mon, 22 Aug 2022 09:38:21 -0700 Subject: [PATCH 272/491] Infer automatically cross compile hosts for macOS package presets Addresses rdar://98787335, apple#60348 --- utils/build-presets.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build-presets.ini b/utils/build-presets.ini index 86acc0f63c6a0..d87a1239452a3 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -1237,7 +1237,7 @@ release-debuginfo compiler-vendor=apple # Cross compile for Apple Silicon -cross-compile-hosts=macosx-arm64 +infer-cross-compile-hosts-on-darwin lldb-use-system-debugserver lldb-build-type=Release From 5a164c5f8aaaa1e5794db72200fc95a9408c6f39 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 22 Aug 2022 10:22:41 -0700 Subject: [PATCH 273/491] [Frontend] Switch from YAML to `.strings` based localization --- lib/Frontend/CompilerInvocation.cpp | 2 +- localization/CMakeLists.txt | 7 +-- .../Localization/Inputs/en.strings | 25 ++++++++++ test/diagnostics/Localization/Inputs/en.yaml | 30 ------------ .../Localization/Inputs/fr.strings | 27 +++++++++++ test/diagnostics/Localization/Inputs/fr.yaml | 30 ------------ .../fr_debug_diagnostic_name.swift | 4 +- .../Localization/fr_localization.swift | 4 +- ...no_localization_files_and_wrong_path.swift | 2 +- .../swift-serialize-diagnostics.cpp | 48 ++++++++++++------- unittests/Localization/CMakeLists.txt | 2 +- ...sts.cpp => DefToStringsConverterTests.cpp} | 14 +++--- unittests/Localization/LocalizationTest.h | 12 ++--- unittests/Localization/SerializationTests.cpp | 37 +++++++------- 14 files changed, 127 insertions(+), 117 deletions(-) create mode 100644 test/diagnostics/Localization/Inputs/en.strings delete mode 100644 test/diagnostics/Localization/Inputs/en.yaml create mode 100644 test/diagnostics/Localization/Inputs/fr.strings delete mode 100644 test/diagnostics/Localization/Inputs/fr.yaml rename unittests/Localization/{DefToYAMLConverterTests.cpp => DefToStringsConverterTests.cpp} (85%) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index f52fe884217be..83490d354e36a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1450,7 +1450,7 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, // for the specified locale code. llvm::SmallString<128> localizationPath(A->getValue()); llvm::sys::path::append(localizationPath, Opts.LocalizationCode); - llvm::sys::path::replace_extension(localizationPath, ".yaml"); + llvm::sys::path::replace_extension(localizationPath, ".strings"); if (!llvm::sys::fs::exists(localizationPath)) { Diags.diagnose(SourceLoc(), diag::warning_cannot_find_locale_file, Opts.LocalizationCode, localizationPath); diff --git a/localization/CMakeLists.txt b/localization/CMakeLists.txt index 07a3585a66c55..537303164ea50 100644 --- a/localization/CMakeLists.txt +++ b/localization/CMakeLists.txt @@ -6,16 +6,16 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/diagnostics/ ${CMAKE_BINARY_DIR}/share/swift/diagnostics/ COMMAND - "${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/swift-def-to-yaml-converter" + "${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/swift-def-to-strings-converter" --output-directory ${CMAKE_BINARY_DIR}/share/swift/diagnostics/ COMMAND "${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/swift-serialize-diagnostics" - --input-file-path ${CMAKE_BINARY_DIR}/share/swift/diagnostics/en.yaml + --input-file-path ${CMAKE_BINARY_DIR}/share/swift/diagnostics/en.strings --output-directory ${CMAKE_BINARY_DIR}/share/swift/diagnostics/ COMMAND ${CMAKE_COMMAND} -E touch ${diagnostic_witness} DEPENDS - swift-def-to-yaml-converter + swift-def-to-strings-converter swift-serialize-diagnostics # Add files in diagnostics subdirectory when they're created ) @@ -31,4 +31,5 @@ swift_install_in_component( FILES_MATCHING PATTERN "*.db" PATTERN "*.yaml" + PATTERN "*.strings" ) diff --git a/test/diagnostics/Localization/Inputs/en.strings b/test/diagnostics/Localization/Inputs/en.strings new file mode 100644 index 0000000000000..2ca51b4296adf --- /dev/null +++ b/test/diagnostics/Localization/Inputs/en.strings @@ -0,0 +1,25 @@ +/** + *--- en.strings - Localized diagnostic messages for English --------------===* + * + * This source file is part of the Swift.org open source project + * + * Copyright (c) 2014 - 2022 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 + * + *===----------------------------------------------------------------------===* + * + * This file defines the diagnostic messages for the English language. + * Each diagnostic is described in the following format: + * "" = ""; + * + *===----------------------------------------------------------------------===* + * + */ +"lex_unterminated_string" = "unterminated string literal"; +"var_init_self_referential" = "variable used within its own initial value"; +/* Tests different number of spaces between id and diagnostic message */ +"cannot_find_in_scope"= "cannot %select{find|find operator}1 %0 in scope"; +"warning_invalid_locale_code" = "unsupported locale code; supported locale codes are '%0'"; diff --git a/test/diagnostics/Localization/Inputs/en.yaml b/test/diagnostics/Localization/Inputs/en.yaml deleted file mode 100644 index b85686db42cf9..0000000000000 --- a/test/diagnostics/Localization/Inputs/en.yaml +++ /dev/null @@ -1,30 +0,0 @@ -#===--- en.yaml - Localized diagnostic messages for English ---*- YAML -*-===# -# -# This source file is part of the Swift.org open source project -# -# Copyright (c) 2014 - 2020 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 -# -#===----------------------------------------------------------------------===# -# -# This file defines the diagnostic messages for the English language. -# Each diagnostic is described in the following format: -# - id: "" -# msg: "" -# -#===----------------------------------------------------------------------===# - -- id: "lex_unterminated_string" - msg: "unterminated string literal" - -- id: "var_init_self_referential" - msg: "variable used within its own initial value" - -- id: "cannot_find_in_scope" - msg: "cannot %select{find|find operator}1 %0 in scope" - -- id: "warning_invalid_locale_code" - msg: "unsupported locale code; supported locale codes are '%0'" diff --git a/test/diagnostics/Localization/Inputs/fr.strings b/test/diagnostics/Localization/Inputs/fr.strings new file mode 100644 index 0000000000000..76c5be6ffc9d8 --- /dev/null +++ b/test/diagnostics/Localization/Inputs/fr.strings @@ -0,0 +1,27 @@ +/** + *===--- fr.strings - Localized diagnostic messages for French ------------===* + * + * This source file is part of the Swift.org open source project + * + * Copyright (c) 2014 - 2022 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 + * + *===----------------------------------------------------------------------===* + * + * This file defines the diagnostic messages for the French language. + * Each diagnostic is described in the following format: + * "" = ""; + * + */ + +/* Different order from `en.strings` */ +"var_init_self_referential" = "variable utilisée dans sa propre valeur initiale"; + +"lex_unterminated_string" = "chaîne non terminée littérale"; + +"cannot_find_in_scope" = "impossible %select{de trouver|de trouver opérateur}1 %0 portée"; + +"warning_invalid_locale_code" = "code de paramètres régionaux non pris en charge; les codes pris en charge sont '%0'"; diff --git a/test/diagnostics/Localization/Inputs/fr.yaml b/test/diagnostics/Localization/Inputs/fr.yaml deleted file mode 100644 index e2a12327bf58a..0000000000000 --- a/test/diagnostics/Localization/Inputs/fr.yaml +++ /dev/null @@ -1,30 +0,0 @@ -#===--- fr.yaml - Localized diagnostic messages for French ---*- YAML -*-===# -# -# This source file is part of the Swift.org open source project -# -# Copyright (c) 2014 - 2020 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 -# -#===----------------------------------------------------------------------===# -# -# This file defines the diagnostic messages for the French language. -# Each diagnostic is described in the following format: -# - id: "" -# msg: "" -# -#===----------------------------------------------------------------------===# - -- id: "lex_unterminated_string" - msg: "chaîne non terminée littérale" - -- id: "var_init_self_referential" - msg: "variable utilisée dans sa propre valeur initiale" - -- id: "cannot_find_in_scope" - msg: "impossible %select{de trouver|de trouver opérateur}1 %0 portée" - -- id: "warning_invalid_locale_code" - msg: "code de paramètres régionaux non pris en charge; les codes pris en charge sont '%0'" diff --git a/test/diagnostics/Localization/fr_debug_diagnostic_name.swift b/test/diagnostics/Localization/fr_debug_diagnostic_name.swift index 0046cbc9ff2a0..70e0cd7af54ac 100644 --- a/test/diagnostics/Localization/fr_debug_diagnostic_name.swift +++ b/test/diagnostics/Localization/fr_debug_diagnostic_name.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.yaml --output-directory=%t/ -// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/ +// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.strings --output-directory=%t/ +// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.strings --output-directory=%t/ // RUN: not %target-swift-frontend -debug-diagnostic-names -localization-path %S/Inputs -locale fr -typecheck %s 2>&1 | %FileCheck %s --check-prefix=CHECK_NAMES _ = "HI! diff --git a/test/diagnostics/Localization/fr_localization.swift b/test/diagnostics/Localization/fr_localization.swift index 0c84ee6e56cc5..206fd65d57900 100644 --- a/test/diagnostics/Localization/fr_localization.swift +++ b/test/diagnostics/Localization/fr_localization.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.yaml --output-directory=%t/ -// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/ +// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.strings --output-directory=%t/ +// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.strings --output-directory=%t/ // RUN: %target-typecheck-verify-swift -localization-path %t -locale fr _ = "HI! diff --git a/test/diagnostics/Localization/no_localization_files_and_wrong_path.swift b/test/diagnostics/Localization/no_localization_files_and_wrong_path.swift index b17b8523a7ee6..5394acfc4c050 100644 --- a/test/diagnostics/Localization/no_localization_files_and_wrong_path.swift +++ b/test/diagnostics/Localization/no_localization_files_and_wrong_path.swift @@ -1,6 +1,6 @@ // RUN: %target-typecheck-verify-swift -localization-path /Nonexistent_path -locale en -// :0: warning: cannot find translations for 'en' at '/Nonexistent_path/en.yaml': no such file +// :0: warning: cannot find translations for 'en' at '/Nonexistent_path/en.strings': no such file // :0: warning: specified localization directory '/Nonexistent_path' does not exist, translation is disabled _ = "HI! diff --git a/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp b/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp index 6021df2b28af1..6564153774052 100644 --- a/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp +++ b/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp @@ -42,7 +42,7 @@ static llvm::cl::OptionCategory Category("swift-serialize-diagnostics Options"); static llvm::cl::opt InputFilePath("input-file-path", - llvm::cl::desc("Path to the YAML input file"), + llvm::cl::desc("Path to the YAML or `.strings` input file"), llvm::cl::cat(Category)); static llvm::cl::opt @@ -60,22 +60,44 @@ int main(int argc, char *argv[]) { "Swift Serialize Diagnostics Tool\n"); if (!llvm::sys::fs::exists(options::InputFilePath)) { - llvm::errs() << "YAML file not found\n"; + llvm::errs() << "diagnostics file not found\n"; return EXIT_FAILURE; } - YAMLLocalizationProducer yaml(options::InputFilePath); - auto localeCode = llvm::sys::path::filename(options::InputFilePath); llvm::SmallString<128> SerializedFilePath(options::OutputDirectory); llvm::sys::path::append(SerializedFilePath, localeCode); llvm::sys::path::replace_extension(SerializedFilePath, ".db"); SerializedLocalizationWriter Serializer; - yaml.forEachAvailable( - [&Serializer](swift::DiagID id, llvm::StringRef translation) { - Serializer.insert(id, translation); - }); + + if (llvm::sys::path::extension(options::InputFilePath) == ".yaml") { + YAMLLocalizationProducer yaml(options::InputFilePath); + + yaml.forEachAvailable( + [&Serializer](swift::DiagID id, llvm::StringRef translation) { + Serializer.insert(id, translation); + }); + + // Print out the diagnostics IDs that are available in YAML but not + // available in `.def` + if (!yaml.unknownIDs.empty()) { + llvm::errs() << "These diagnostic IDs are no longer available: '"; + llvm::interleave( + yaml.unknownIDs, [&](std::string id) { llvm::errs() << id; }, + [&] { llvm::errs() << ", "; }); + llvm::errs() << "'\n"; + } + } else { + assert(llvm::sys::path::extension(options::InputFilePath) == ".strings"); + + StringsLocalizationProducer strings(options::InputFilePath); + + strings.forEachAvailable( + [&Serializer](swift::DiagID id, llvm::StringRef translation) { + Serializer.insert(id, translation); + }); + } if (Serializer.emit(SerializedFilePath.str())) { llvm::errs() << "Cannot serialize diagnostic file " @@ -83,15 +105,5 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - // Print out the diagnostics IDs that are available in YAML but not available - // in `.def` - if (!yaml.unknownIDs.empty()) { - llvm::errs() << "These diagnostic IDs are no longer available: '"; - llvm::interleave( - yaml.unknownIDs, [&](std::string id) { llvm::errs() << id; }, - [&] { llvm::errs() << ", "; }); - llvm::errs() << "'\n"; - } - return EXIT_SUCCESS; } diff --git a/unittests/Localization/CMakeLists.txt b/unittests/Localization/CMakeLists.txt index 618d892709403..c2c5d96122824 100644 --- a/unittests/Localization/CMakeLists.txt +++ b/unittests/Localization/CMakeLists.txt @@ -1,5 +1,5 @@ add_swift_unittest(swiftLocalizationTests - DefToYAMLConverterTests.cpp + DefToStringsConverterTests.cpp SerializationTests.cpp) target_link_libraries(swiftLocalizationTests diff --git a/unittests/Localization/DefToYAMLConverterTests.cpp b/unittests/Localization/DefToStringsConverterTests.cpp similarity index 85% rename from unittests/Localization/DefToYAMLConverterTests.cpp rename to unittests/Localization/DefToStringsConverterTests.cpp index 1683537cdb05b..a2b74a311a5ed 100644 --- a/unittests/Localization/DefToYAMLConverterTests.cpp +++ b/unittests/Localization/DefToStringsConverterTests.cpp @@ -1,8 +1,8 @@ -//===--- DefToYAMLConverterTests.cpp -------------------------------------===// +//===--- DefToStringsConverterTests.cpp -----------------------------------===// // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2022 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 @@ -49,22 +49,22 @@ TEST_F(LocalizationTest, MissingLocalizationFiles) { ASSERT_TRUE(llvm::sys::fs::exists(getDefaultLocalizationPath())); llvm::SmallString<128> EnglishLocalization(getDefaultLocalizationPath()); llvm::sys::path::append(EnglishLocalization, "en"); - llvm::sys::path::replace_extension(EnglishLocalization, ".yaml"); + llvm::sys::path::replace_extension(EnglishLocalization, ".strings"); ASSERT_TRUE(llvm::sys::fs::exists(EnglishLocalization)); llvm::sys::path::replace_extension(EnglishLocalization, ".db"); ASSERT_TRUE(llvm::sys::fs::exists(EnglishLocalization)); } TEST_F(LocalizationTest, ConverterTestMatchDiagnosticMessagesSequentially) { - YAMLLocalizationProducer yaml(YAMLPath); - yaml.forEachAvailable([](swift::DiagID id, llvm::StringRef translation) { + StringsLocalizationProducer strings(DiagsPath); + strings.forEachAvailable([](swift::DiagID id, llvm::StringRef translation) { llvm::StringRef msg = diagnosticMessages[static_cast(id)]; ASSERT_EQ(msg, translation); }); } TEST_F(LocalizationTest, ConverterTestMatchDiagnosticMessagesRandomly) { - YAMLLocalizationProducer yaml(YAMLPath); + StringsLocalizationProducer strings(DiagsPath); std::random_device rd; std::mt19937 gen(rd()); @@ -74,7 +74,7 @@ TEST_F(LocalizationTest, ConverterTestMatchDiagnosticMessagesRandomly) { unsigned randomNum = RandNumber(LocalDiagID::NumDiags); DiagID randomId = static_cast(randomNum); llvm::StringRef msg = diagnosticMessages[randomNum]; - llvm::StringRef translation = yaml.getMessageOr(randomId, ""); + llvm::StringRef translation = strings.getMessageOr(randomId, ""); ASSERT_EQ(msg, translation); } } diff --git a/unittests/Localization/LocalizationTest.h b/unittests/Localization/LocalizationTest.h index 6b78628c59a21..7ca13314fcdfa 100644 --- a/unittests/Localization/LocalizationTest.h +++ b/unittests/Localization/LocalizationTest.h @@ -53,15 +53,15 @@ struct LocalizationTest : public ::testing::Test { llvm::SmallVector TempFiles; public: - std::string YAMLPath; + std::string DiagsPath; LocalizationTest() { - YAMLPath = std::string(createTemporaryFile("en", "yaml")); + DiagsPath = std::string(createTemporaryFile("en", "strings")); } void SetUp() override { - bool failed = convertDefIntoYAML(YAMLPath); - assert(!failed && "failed to generate a YAML file"); + bool failed = convertDefIntoStrings(DiagsPath); + assert(!failed && "failed to generate a `.strings` file"); } void TearDown() override { @@ -85,7 +85,7 @@ struct LocalizationTest : public ::testing::Test { unsigned RandNumber(unsigned n) { return unsigned(rand()) % n; } protected: - static bool convertDefIntoYAML(std::string outputPath) { + static bool convertDefIntoStrings(std::string outputPath) { std::error_code error; llvm::raw_fd_ostream OS(outputPath, error, llvm::sys::fs::OF_None); if (OS.has_error() || error) @@ -95,7 +95,7 @@ struct LocalizationTest : public ::testing::Test { llvm::ArrayRef messages(diagnosticMessages, LocalDiagID::NumDiags); - DefToYAMLConverter converter(ids, messages); + DefToStringsConverter converter(ids, messages); converter.convert(OS); OS.flush(); diff --git a/unittests/Localization/SerializationTests.cpp b/unittests/Localization/SerializationTests.cpp index 5eea041977759..cf3048db6a950 100644 --- a/unittests/Localization/SerializationTests.cpp +++ b/unittests/Localization/SerializationTests.cpp @@ -24,8 +24,8 @@ using namespace swift::diag; using namespace swift::unittests; -TEST_F(LocalizationTest, TestYAMLSerialization) { - YAMLLocalizationProducer yaml(YAMLPath); +TEST_F(LocalizationTest, TestStringsSerialization) { + StringsLocalizationProducer strings(DiagsPath); auto dbFile = createTemporaryFile("en", "db"); @@ -33,9 +33,10 @@ TEST_F(LocalizationTest, TestYAMLSerialization) { { SerializedLocalizationWriter writer; - yaml.forEachAvailable([&writer](swift::DiagID id, llvm::StringRef translation) { - writer.insert(id, translation); - }); + strings.forEachAvailable( + [&writer](swift::DiagID id, llvm::StringRef translation) { + writer.insert(id, translation); + }); ASSERT_FALSE(writer.emit(dbFile)); } @@ -45,9 +46,10 @@ TEST_F(LocalizationTest, TestYAMLSerialization) { ASSERT_TRUE(dbContent); SerializedLocalizationProducer db(std::move(dbContent.get())); - yaml.forEachAvailable([&db](swift::DiagID id, llvm::StringRef translation) { - ASSERT_EQ(translation, db.getMessageOr(id, "")); - }); + strings.forEachAvailable( + [&db](swift::DiagID id, llvm::StringRef translation) { + ASSERT_EQ(translation, db.getMessageOr(id, "")); + }); } TEST_F(LocalizationTest, TestSerializationOfEmptyFile) { @@ -55,7 +57,7 @@ TEST_F(LocalizationTest, TestSerializationOfEmptyFile) { SerializedLocalizationWriter writer; ASSERT_FALSE(writer.emit(dbFile)); - YAMLLocalizationProducer yaml(YAMLPath); + StringsLocalizationProducer strings(DiagsPath); // Reading of the empty `db` file should always return default message. { @@ -63,7 +65,8 @@ TEST_F(LocalizationTest, TestSerializationOfEmptyFile) { ASSERT_TRUE(dbContent); SerializedLocalizationProducer db(std::move(dbContent.get())); - yaml.forEachAvailable([&db](swift::DiagID id, llvm::StringRef translation) { + strings.forEachAvailable([&db](swift::DiagID id, + llvm::StringRef translation) { ASSERT_EQ("<<>>", db.getMessageOr(id, "<<>>")); }); @@ -80,16 +83,17 @@ TEST_F(LocalizationTest, TestSerializationWithGaps) { includedMessages.flip(position); } - YAMLLocalizationProducer yaml(YAMLPath); + StringsLocalizationProducer strings(DiagsPath); auto dbFile = createTemporaryFile("en", "db"); { SerializedLocalizationWriter writer; - yaml.forEachAvailable([&](swift::DiagID id, llvm::StringRef translation) { - if (includedMessages.test((unsigned)id)) - writer.insert(id, translation); - }); + strings.forEachAvailable( + [&](swift::DiagID id, llvm::StringRef translation) { + if (includedMessages.test((unsigned)id)) + writer.insert(id, translation); + }); ASSERT_FALSE(writer.emit(dbFile)); } @@ -100,7 +104,8 @@ TEST_F(LocalizationTest, TestSerializationWithGaps) { ASSERT_TRUE(dbContent); SerializedLocalizationProducer db(std::move(dbContent.get())); - yaml.forEachAvailable([&](swift::DiagID id, llvm::StringRef translation) { + strings.forEachAvailable([&](swift::DiagID id, + llvm::StringRef translation) { auto position = (unsigned)id; std::string expectedMessage = includedMessages.test(position) From 10b609caecdb6b8169126b169b464f71bb9cf8df Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 22 Aug 2022 10:53:51 -0700 Subject: [PATCH 274/491] [Localization] Remove YAML format and tool --- .../swift/Localization/LocalizationFormat.h | 69 +-------- lib/ConstExtract/ConstExtract.cpp | 2 + lib/Localization/LocalizationFormat.cpp | 143 +----------------- tools/CMakeLists.txt | 1 - .../CMakeLists.txt | 7 - .../swift-def-to-yaml-converter.cpp | 103 ------------- .../swift-serialize-diagnostics.cpp | 21 +-- 7 files changed, 9 insertions(+), 337 deletions(-) delete mode 100644 tools/swift-def-to-yaml-converter/CMakeLists.txt delete mode 100644 tools/swift-def-to-yaml-converter/swift-def-to-yaml-converter.cpp diff --git a/include/swift/Localization/LocalizationFormat.h b/include/swift/Localization/LocalizationFormat.h index 50ec3927a8e21..6c276dc9251c6 100644 --- a/include/swift/Localization/LocalizationFormat.h +++ b/include/swift/Localization/LocalizationFormat.h @@ -27,8 +27,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/StringSaver.h" -#include "llvm/Support/YAMLParser.h" -#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -50,20 +48,6 @@ enum LocalizationProducerState : uint8_t { FailedInitialization }; -class DefToYAMLConverter { - llvm::ArrayRef IDs; - llvm::ArrayRef Messages; - -public: - DefToYAMLConverter(llvm::ArrayRef ids, - llvm::ArrayRef messages) - : IDs(ids), Messages(messages) { - assert(IDs.size() == Messages.size()); - } - - void convert(llvm::raw_ostream &out); -}; - class DefToStringsConverter { llvm::ArrayRef IDs; llvm::ArrayRef Messages; @@ -195,9 +179,9 @@ class LocalizationProducer { llvm::StringRef defaultMessage); /// \returns a `SerializedLocalizationProducer` pointer if the serialized - /// diagnostics file available, otherwise returns a `YAMLLocalizationProducer` - /// if the `YAML` file is available. If both files aren't available returns a - /// `nullptr`. + /// diagnostics file available, otherwise returns a + /// `StringsLocalizationProducer` if the `.strings` file is available. If both + /// files aren't available returns a `nullptr`. static std::unique_ptr producerFor(llvm::StringRef locale, llvm::StringRef path, bool printDiagnosticNames); @@ -218,27 +202,6 @@ class LocalizationProducer { virtual llvm::StringRef getMessage(swift::DiagID id) const = 0; }; -class YAMLLocalizationProducer final : public LocalizationProducer { - std::vector diagnostics; - std::string filePath; - -public: - /// The diagnostics IDs that are no longer available in `.def` - std::vector unknownIDs; - explicit YAMLLocalizationProducer(llvm::StringRef filePath, - bool printDiagnosticNames = false); - - /// Iterate over all of the available (non-empty) translations - /// maintained by this producer, callback gets each translation - /// with its unique identifier. - void forEachAvailable( - llvm::function_ref callback); - -protected: - bool initializeImpl() override; - llvm::StringRef getMessage(swift::DiagID id) const override; -}; - class StringsLocalizationProducer final : public LocalizationProducer { std::string filePath; @@ -281,32 +244,6 @@ class SerializedLocalizationProducer final : public LocalizationProducer { llvm::StringRef getMessage(swift::DiagID id) const override; }; -class LocalizationInput : public llvm::yaml::Input { - using Input::Input; - - /// Read diagnostics in the YAML file iteratively - template - friend typename std::enable_if::value, - void>::type - readYAML(llvm::yaml::IO &io, T &Seq, T &unknownIDs, bool, Context &Ctx); - - template - friend typename std::enable_if::value, - LocalizationInput &>::type - operator>>(LocalizationInput &yin, T &diagnostics); - -public: - /// A vector that keeps track of the diagnostics IDs that are available in - /// YAML and not available in `.def` files. - std::vector unknownIDs; - - /// A diagnostic ID might be present in YAML and not in `.def` file, if that's - /// the case the `id` won't have a `DiagID` value. - /// If the `id` is available in `.def` file this method will return the `id`'s - /// value, otherwise this method won't return a value. - static llvm::Optional readID(llvm::yaml::IO &io); -}; - } // namespace diag } // namespace swift diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index 10739129f46da..09f789a4dc265 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -21,6 +21,8 @@ #include "swift/AST/TypeCheckRequests.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/JSON.h" +#include "llvm/Support/YAMLParser.h" +#include "llvm/Support/YAMLTraits.h" #include #include diff --git a/lib/Localization/LocalizationFormat.cpp b/lib/Localization/LocalizationFormat.cpp index 40368b6b5fac6..f21631d4215ce 100644 --- a/lib/Localization/LocalizationFormat.cpp +++ b/lib/Localization/LocalizationFormat.cpp @@ -24,9 +24,8 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" -#include "llvm/Support/YAMLParser.h" -#include "llvm/Support/YAMLTraits.h" #include +#include #include #include #include @@ -47,24 +46,6 @@ static constexpr const char *const diagnosticNameStrings[] = { } // namespace -namespace llvm { -namespace yaml { - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &io, LocalDiagID &value) { -#define DIAG(KIND, ID, Options, Text, Signature) \ - io.enumCase(value, #ID, LocalDiagID::ID); -#include "swift/AST/DiagnosticsAll.def" - // Ignore diagnostic IDs that are available in the YAML file and not - // available in the `.def` file. - if (io.matchEnumFallback()) - value = LocalDiagID::NumDiags; - } -}; - -} // namespace yaml -} // namespace llvm - namespace swift { namespace diag { @@ -149,38 +130,6 @@ SerializedLocalizationProducer::getMessage(swift::DiagID id) const { return {(const char *)value.getDataPtr(), value.getDataLen()}; } -YAMLLocalizationProducer::YAMLLocalizationProducer(llvm::StringRef filePath, - bool printDiagnosticNames) - : LocalizationProducer(printDiagnosticNames), filePath(filePath) { -} - -bool YAMLLocalizationProducer::initializeImpl() { - auto FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(filePath); - llvm::MemoryBuffer *document = FileBufOrErr->get(); - diag::LocalizationInput yin(document->getBuffer()); - yin >> diagnostics; - unknownIDs = std::move(yin.unknownIDs); - return true; -} - -llvm::StringRef YAMLLocalizationProducer::getMessage(swift::DiagID id) const { - return diagnostics[(unsigned)id]; -} - -void YAMLLocalizationProducer::forEachAvailable( - llvm::function_ref callback) { - initializeIfNeeded(); - if (getState() == FailedInitialization) { - return; - } - - for (uint32_t i = 0, n = diagnostics.size(); i != n; ++i) { - auto translation = diagnostics[i]; - if (!translation.empty()) - callback(static_cast(i), translation); - } -} - std::unique_ptr LocalizationProducer::producerFor(llvm::StringRef locale, llvm::StringRef path, bool printDiagnosticNames) { @@ -189,21 +138,13 @@ LocalizationProducer::producerFor(llvm::StringRef locale, llvm::StringRef path, llvm::sys::path::replace_extension(filePath, ".db"); // If the serialized diagnostics file not available, - // fallback to the `YAML` file. + // fallback to the `.strings` file. if (llvm::sys::fs::exists(filePath)) { if (auto file = llvm::MemoryBuffer::getFile(filePath)) { return std::make_unique( std::move(file.get()), printDiagnosticNames); } } else { - llvm::sys::path::replace_extension(filePath, ".yaml"); - // In case of missing localization files, we should fallback to messages - // from `.def` files. - if (llvm::sys::fs::exists(filePath)) { - return std::make_unique( - filePath.str(), printDiagnosticNames); - } - llvm::sys::path::replace_extension(filePath, ".strings"); if (llvm::sys::fs::exists(filePath)) { return std::make_unique( @@ -214,86 +155,6 @@ LocalizationProducer::producerFor(llvm::StringRef locale, llvm::StringRef path, return std::unique_ptr(); } -llvm::Optional LocalizationInput::readID(llvm::yaml::IO &io) { - LocalDiagID diagID; - io.mapRequired("id", diagID); - if (diagID == LocalDiagID::NumDiags) - return llvm::None; - return static_cast(diagID); -} - -template -typename std::enable_if::value, void>::type -readYAML(llvm::yaml::IO &io, T &Seq, T &unknownIDs, bool, Context &Ctx) { - unsigned count = io.beginSequence(); - if (count) { - Seq.resize(LocalDiagID::NumDiags); - } - - for (unsigned i = 0; i < count; ++i) { - void *SaveInfo; - if (io.preflightElement(i, SaveInfo)) { - io.beginMapping(); - - // If the current diagnostic ID is available in YAML and in `.def`, add it - // to the diagnostics array. Otherwise, re-parse the current diagnostic - // id as a string and store it in `unknownIDs` array. - if (auto id = LocalizationInput::readID(io)) { - // YAML file isn't guaranteed to have diagnostics in order of their - // declaration in `.def` files, to accommodate that we need to leave - // holes in diagnostic array for diagnostics which haven't yet been - // localized and for the ones that have `id` indicates their position. - io.mapRequired("msg", Seq[*id]); - } else { - std::string unknownID, message; - // Read "raw" id since it doesn't exist in `.def` file. - io.mapRequired("id", unknownID); - io.mapRequired("msg", message); - unknownIDs.push_back(unknownID); - } - io.endMapping(); - io.postflightElement(SaveInfo); - } - } - io.endSequence(); -} - -template -typename std::enable_if::value, - LocalizationInput &>::type -operator>>(LocalizationInput &yin, T &diagnostics) { - llvm::yaml::EmptyContext Ctx; - if (yin.setCurrentDocument()) { - // If YAML file's format doesn't match the current format in - // DiagnosticMessageFormat, will throw an error. - readYAML(yin, diagnostics, yin.unknownIDs, true, Ctx); - } - return yin; -} - -void DefToYAMLConverter::convert(llvm::raw_ostream &out) { - for (auto i : swift::indices(IDs)) { - out << "- id: " << IDs[i] << "\n"; - - const std::string &msg = Messages[i]; - - out << " msg: \""; - // Add an escape character before a double quote `"` or a backslash `\`. - for (unsigned j = 0; j < msg.length(); ++j) { - if (msg[j] == '"') { - out << '\\'; - out << '"'; - } else if (msg[j] == '\\') { - out << '\\'; - out << '\\'; - } else { - out << msg[j]; - } - } - out << "\"\r\n"; - } -} - void DefToStringsConverter::convert(llvm::raw_ostream &out) { // "" = ""; for (auto i : swift::indices(IDs)) { diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index b2edb7bb68b46..d87fe16236a2b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -22,7 +22,6 @@ add_swift_tool_subdirectory(sil-opt) add_swift_tool_subdirectory(swift-dependency-tool) add_swift_tool_subdirectory(swift-demangle) add_swift_tool_subdirectory(swift-demangle-yamldump) -add_swift_tool_subdirectory(swift-def-to-yaml-converter) add_swift_tool_subdirectory(swift-def-to-strings-converter) add_swift_tool_subdirectory(swift-serialize-diagnostics) add_swift_tool_subdirectory(sil-func-extractor) diff --git a/tools/swift-def-to-yaml-converter/CMakeLists.txt b/tools/swift-def-to-yaml-converter/CMakeLists.txt deleted file mode 100644 index 558a737c8257e..0000000000000 --- a/tools/swift-def-to-yaml-converter/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_swift_host_tool(swift-def-to-yaml-converter - swift-def-to-yaml-converter.cpp - SWIFT_COMPONENT tools -) - -target_link_libraries(swift-def-to-yaml-converter PRIVATE - swiftLocalization) diff --git a/tools/swift-def-to-yaml-converter/swift-def-to-yaml-converter.cpp b/tools/swift-def-to-yaml-converter/swift-def-to-yaml-converter.cpp deleted file mode 100644 index 34018341aafee..0000000000000 --- a/tools/swift-def-to-yaml-converter/swift-def-to-yaml-converter.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//===--- swift-def-to-yaml-converter.cpp ----------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2020 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 -// -//===----------------------------------------------------------------------===// -// -// Create a YAML file from the diagnostic messages text in `.def` files. -// -//===----------------------------------------------------------------------===// - -#include "swift/Basic/LLVMInitialize.h" -#include "swift/Basic/Compiler.h" -#include "swift/Localization/LocalizationFormat.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/EndianStream.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include - -static constexpr const char *const diagnosticID[] = { -#define DIAG(KIND, ID, Options, Text, Signature) #ID, -#include "swift/AST/DiagnosticsAll.def" -}; - -static constexpr const char *const diagnosticMessages[] = { -#define DIAG(KIND, ID, Options, Text, Signature) Text, -#include "swift/AST/DiagnosticsAll.def" -}; - -enum LocalDiagID : uint32_t { -#define DIAG(KIND, ID, Options, Text, Signature) ID, -#include "swift/AST/DiagnosticsAll.def" - NumDiags -}; - -namespace options { - -static llvm::cl::OptionCategory Category("swift-def-to-yaml-converter Options"); - -static llvm::cl::opt - OutputDirectory("output-directory", - llvm::cl::desc("Directory for the output file"), - llvm::cl::cat(Category)); - -static llvm::cl::opt - OutputFilename("output-filename", - llvm::cl::desc("Filename for the output file"), - llvm::cl::cat(Category)); - -} // namespace options - -int main(int argc, char *argv[]) { - PROGRAM_START(argc, argv); - - llvm::cl::HideUnrelatedOptions(options::Category); - llvm::cl::ParseCommandLineOptions(argc, argv, - "Swift `.def` to YAML Converter\n"); - - llvm::SmallString<128> LocalizedFilePath; - if (options::OutputFilename.empty()) { - // The default language for localization is English - std::string defaultLocaleCode = "en"; - LocalizedFilePath = options::OutputDirectory; - llvm::sys::path::append(LocalizedFilePath, defaultLocaleCode); - llvm::sys::path::replace_extension(LocalizedFilePath, ".yaml"); - } else { - LocalizedFilePath = options::OutputFilename; - } - - std::error_code error; - llvm::raw_fd_ostream OS(LocalizedFilePath.str(), error, - llvm::sys::fs::OF_None); - - if (OS.has_error() || error) { - llvm::errs() << "Error has occurred while trying to write to " - << LocalizedFilePath.str() - << " with error code: " << error.message() << "\n"; - return EXIT_FAILURE; - } - - llvm::ArrayRef ids(diagnosticID, LocalDiagID::NumDiags); - llvm::ArrayRef messages(diagnosticMessages, - LocalDiagID::NumDiags); - - swift::diag::DefToYAMLConverter converter(ids, messages); - converter.convert(OS); - - return EXIT_SUCCESS; -} diff --git a/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp b/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp index 6564153774052..0f81bf0030b73 100644 --- a/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp +++ b/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp @@ -42,7 +42,7 @@ static llvm::cl::OptionCategory Category("swift-serialize-diagnostics Options"); static llvm::cl::opt InputFilePath("input-file-path", - llvm::cl::desc("Path to the YAML or `.strings` input file"), + llvm::cl::desc("Path to the `.strings` input file"), llvm::cl::cat(Category)); static llvm::cl::opt @@ -71,24 +71,7 @@ int main(int argc, char *argv[]) { SerializedLocalizationWriter Serializer; - if (llvm::sys::path::extension(options::InputFilePath) == ".yaml") { - YAMLLocalizationProducer yaml(options::InputFilePath); - - yaml.forEachAvailable( - [&Serializer](swift::DiagID id, llvm::StringRef translation) { - Serializer.insert(id, translation); - }); - - // Print out the diagnostics IDs that are available in YAML but not - // available in `.def` - if (!yaml.unknownIDs.empty()) { - llvm::errs() << "These diagnostic IDs are no longer available: '"; - llvm::interleave( - yaml.unknownIDs, [&](std::string id) { llvm::errs() << id; }, - [&] { llvm::errs() << ", "; }); - llvm::errs() << "'\n"; - } - } else { + { assert(llvm::sys::path::extension(options::InputFilePath) == ".strings"); StringsLocalizationProducer strings(options::InputFilePath); From f96bfb2914fc6f1930833588e1d3423c2fb14a10 Mon Sep 17 00:00:00 2001 From: a4z Date: Mon, 22 Aug 2022 20:21:04 +0200 Subject: [PATCH 275/491] Adopt Cxx header/implementation in example * Fix header/implemenation content in C++ code listning * Minor whitespace fix in caption --- .../GettingStartedWithC++Interop.md | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/CppInteroperability/GettingStartedWithC++Interop.md b/docs/CppInteroperability/GettingStartedWithC++Interop.md index 4b828d22eb6be..5235379cce1d9 100644 --- a/docs/CppInteroperability/GettingStartedWithC++Interop.md +++ b/docs/CppInteroperability/GettingStartedWithC++Interop.md @@ -1,4 +1,4 @@ -# Getting started with C++ Interoperability +# Getting started with C++ Interoperability This document is designed to get you started with bidirectional API-level interoperability between Swift and C++. @@ -32,10 +32,10 @@ module Cxx { - In your xcode project, follow the steps [Creating a Module to contain your C++ source code](#creating-a-module-to-contain-your-c-source-code) in your project directory Add the C++ module to the include path and enable C++ interop: -- Navigate to your project directory +- Navigate to your project directory - In `Project` navigate to `Build Settings` -> `Swift Compiler` - Under `Custom Flags` -> `Other Swift Flags` add`-enable-experimental-cxx-interop` -- Under `Search Paths` -> `Import Paths` add your search path to the C++ module (i.e, `./ProjectName/Cxx`). Repeat this step in `Other Swift Flags` +- Under `Search Paths` -> `Import Paths` add your search path to the C++ module (i.e, `./ProjectName/Cxx`). Repeat this step in `Other Swift Flags` ``` //Add to Other Swift Flags and Import Paths respectively @@ -64,9 +64,8 @@ struct ContentView: View { #ifndef Cxx_hpp #define Cxx_hpp -int cxxFunction(int n) { - return n; -} +int cxxFunction(int n); + #endif ``` @@ -74,8 +73,10 @@ int cxxFunction(int n) { //In Cxx.cpp #include "Cxx.hpp" -int cxxFunction(int n); +int cxxFunction(int n) { + return n; +} ``` @@ -134,7 +135,7 @@ let package = Package( import Cxx public struct CxxInterop { - + public func callCxxFunction(n: Int32) -> Int32 { return cxxFunction(n: n) } @@ -152,7 +153,7 @@ After creating your project follow the steps [Creating a Module to contain your - In`add_library` invoke `cxx-support` with the path to the C++ implementation file - Add the `target_include_directories` with `cxx-support` and path to the C++ Module `${CMAKE_SOURCE_DIR}/Sources/Cxx` - Add the `add_executable` to the specific files/directory you would like to generate source, with`SHELL:-enable-experimental-cxx-interop`. -- In the example below we will be following the file structure used in [Creating a Swift Package](#Creating-a-Swift-Package) +- In the example below we will be following the file structure used in [Creating a Swift Package](#Creating-a-Swift-Package) ``` //In CMakeLists.txt @@ -199,7 +200,7 @@ CxxInterop.main() - In your project's directory, run `cmake` to generate the systems build files -- To generate an Xcode project run `cmake -GXcode` +- To generate an Xcode project run `cmake -GXcode` - To generate with Ninja run `cmake -GNinja` - For more information on `cmake` see the 'GettingStarted' documentation: (https://github.com/apple/swift/blob/main/docs/HowToGuides/GettingStarted.md) From a16ffa4bc620c2df8193ee1fa38ec93a579d42a2 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Mon, 22 Aug 2022 11:38:14 -0700 Subject: [PATCH 276/491] [test] Fix availability incantation in attr_availability_rename_toplevel --- test/attr/attr_availability_async_rename_toplevel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/attr/attr_availability_async_rename_toplevel.swift b/test/attr/attr_availability_async_rename_toplevel.swift index d53d34ad584d9..5c9ed7c8bd564 100644 --- a/test/attr/attr_availability_async_rename_toplevel.swift +++ b/test/attr/attr_availability_async_rename_toplevel.swift @@ -2,7 +2,7 @@ // RUN: %target-typecheck-verify-swift -if #available(macOS 12.0, *) { +if #available(SwiftStdlib 5.5, *) { @available(*, renamed: "process(data:)") func process(data: [Int], completion: @escaping ([Int]) -> Void) { completion(data) } // expected-note@+1{{'process(data:)' declared here}} From 04144d8214ec2fb100b78d8a23622828326a95e6 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 19 Aug 2022 15:16:22 -0700 Subject: [PATCH 277/491] [pruned-liveness] Change PrunedLiveBlocks so that it can propagate multiple bits of liveness rather than just one. This is useful for making a form of PrunedLiveness that is sensitive to address fields. I wired up the current PrunedLiveness to just use PrunedLiveBlocks with num bits set to 1. --- include/swift/SIL/PrunedLiveness.h | 50 ++++++++++++++++++------------ lib/SIL/Utils/PrunedLiveness.cpp | 22 +++++++------ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/include/swift/SIL/PrunedLiveness.h b/include/swift/SIL/PrunedLiveness.h index 6851386b4fb70..785a8955979e6 100644 --- a/include/swift/SIL/PrunedLiveness.h +++ b/include/swift/SIL/PrunedLiveness.h @@ -115,6 +115,11 @@ class DeadEndBlocks; /// which the def block's predecessors incorrectly remain dead. This situation /// could be handled by adding an updateForUseBeforeFirstDef() API. /// +/// We allow for multiple bits of liveness information to be tracked by +/// internally using a SmallBitVector. We default to only tracking a single +/// bit. The multiple bit tracking is useful when tracking state for multiple +/// fields of the same root value. +/// /// TODO: This can be made space-efficient if all clients can maintain a block /// numbering so liveness info can be represented as bitsets across the blocks. class PrunedLiveBlocks { @@ -136,19 +141,24 @@ class PrunedLiveBlocks { enum IsLive { Dead, LiveWithin, LiveOut }; private: - // Map all blocks in which current def is live to a flag indicating whether - // the value is also liveout of the block. - llvm::SmallDenseMap liveBlocks; + /// Map all blocks in which current def is live to a SmallBitVector indicating + /// whether the value represented by said bit is also liveout of the block. + llvm::SmallDenseMap liveBlocks; + + /// Number of bits of liveness to track. By default 1. Used to track multiple + /// liveness bits. + unsigned numBitsToTrack; - // Optional vector of live blocks for clients that deterministically iterate. + /// Optional vector of live blocks for clients that deterministically iterate. SmallVectorImpl *discoveredBlocks; - // Once the first use has been seen, no definitions can be added. + /// Once the first use has been seen, no definitions can be added. SWIFT_ASSERT_ONLY_DECL(bool seenUse = false); public: - PrunedLiveBlocks(SmallVectorImpl *discoveredBlocks = nullptr) - : discoveredBlocks(discoveredBlocks) { + PrunedLiveBlocks(unsigned numBitsToTrack, + SmallVectorImpl *discoveredBlocks = nullptr) + : numBitsToTrack(numBitsToTrack), discoveredBlocks(discoveredBlocks) { assert(!discoveredBlocks || discoveredBlocks->empty()); } @@ -167,36 +177,38 @@ class PrunedLiveBlocks { return *discoveredBlocks; } - void initializeDefBlock(SILBasicBlock *defBB) { - markBlockLive(defBB, LiveWithin); + void initializeDefBlock(SILBasicBlock *defBB, unsigned bitNo) { + markBlockLive(defBB, LiveWithin, bitNo); } /// Update this liveness result for a single use. - IsLive updateForUse(SILInstruction *user); + IsLive updateForUse(SILInstruction *user, unsigned bitNo); - IsLive getBlockLiveness(SILBasicBlock *bb) const { + IsLive getBlockLiveness(SILBasicBlock *bb, unsigned bitNo) const { auto liveBlockIter = liveBlocks.find(bb); if (liveBlockIter == liveBlocks.end()) return Dead; - return liveBlockIter->second ? LiveOut : LiveWithin; + assert(liveBlockIter->second.size() == 1); + return liveBlockIter->second[bitNo] ? LiveOut : LiveWithin; } protected: - void markBlockLive(SILBasicBlock *bb, IsLive isLive) { + void markBlockLive(SILBasicBlock *bb, IsLive isLive, unsigned bitNo) { assert(isLive != Dead && "erasing live blocks isn't implemented."); bool isLiveOut = (isLive == LiveOut); auto iterAndInserted = - liveBlocks.insert(std::make_pair(bb, isLiveOut)); + liveBlocks.insert(std::make_pair(bb, SmallBitVector(numBitsToTrack))); if (iterAndInserted.second) { + iterAndInserted.first->getSecond()[bitNo] = isLiveOut; if (discoveredBlocks) discoveredBlocks->push_back(bb); } else if (isLiveOut) { // Update the existing entry to be live-out. - iterAndInserted.first->getSecond() = true; + iterAndInserted.first->getSecond()[bitNo] = true; } } - void computeUseBlockLiveness(SILBasicBlock *userBB); + void computeUseBlockLiveness(SILBasicBlock *userBB, unsigned bitNo); }; /// PrunedLiveness tracks PrunedLiveBlocks along with "interesting" use @@ -252,7 +264,7 @@ class PrunedLiveness { PrunedLiveness(SmallVectorImpl *discoveredBlocks = nullptr, SmallSetVector *nonLifetimeEndingUsesInLiveOut = nullptr) - : liveBlocks(discoveredBlocks), + : liveBlocks(1 /*num bits*/, discoveredBlocks), nonLifetimeEndingUsesInLiveOut(nonLifetimeEndingUsesInLiveOut) {} bool empty() const { @@ -317,7 +329,7 @@ class PrunedLiveness { } void initializeDefBlock(SILBasicBlock *defBB) { - liveBlocks.initializeDefBlock(defBB); + liveBlocks.initializeDefBlock(defBB, 0); } /// For flexibility, \p lifetimeEnding is provided by the @@ -335,7 +347,7 @@ class PrunedLiveness { void extendAcrossLiveness(PrunedLiveness &otherLiveness); PrunedLiveBlocks::IsLive getBlockLiveness(SILBasicBlock *bb) const { - return liveBlocks.getBlockLiveness(bb); + return liveBlocks.getBlockLiveness(bb, 0); } enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse }; diff --git a/lib/SIL/Utils/PrunedLiveness.cpp b/lib/SIL/Utils/PrunedLiveness.cpp index 20f448eaf81e5..2fb8a31f9cd18 100644 --- a/lib/SIL/Utils/PrunedLiveness.cpp +++ b/lib/SIL/Utils/PrunedLiveness.cpp @@ -19,10 +19,11 @@ using namespace swift; /// Mark blocks live during a reverse CFG traversal from one specific block /// containing a user. -void PrunedLiveBlocks::computeUseBlockLiveness(SILBasicBlock *userBB) { - // If we are visiting this block, then it is not already LiveOut. Mark it +void PrunedLiveBlocks::computeUseBlockLiveness(SILBasicBlock *userBB, + unsigned bitNo) { + // If, we are visiting this block, then it is not already LiveOut. Mark it // LiveWithin to indicate a liveness boundary within the block. - markBlockLive(userBB, LiveWithin); + markBlockLive(userBB, LiveWithin, bitNo); SmallVector predBBWorklist({userBB}); while (!predBBWorklist.empty()) { @@ -33,12 +34,12 @@ void PrunedLiveBlocks::computeUseBlockLiveness(SILBasicBlock *userBB) { // Traversal terminates at any previously visited block, including the // blocks initialized as definition blocks. for (auto *predBB : bb->getPredecessorBlocks()) { - switch (getBlockLiveness(predBB)) { + switch (getBlockLiveness(predBB, bitNo)) { case Dead: predBBWorklist.push_back(predBB); LLVM_FALLTHROUGH; case LiveWithin: - markBlockLive(predBB, LiveOut); + markBlockLive(predBB, LiveOut, bitNo); break; case LiveOut: break; @@ -52,11 +53,12 @@ void PrunedLiveBlocks::computeUseBlockLiveness(SILBasicBlock *userBB) { /// Return the updated liveness of the \p use block (LiveOut or LiveWithin). /// /// Terminators are not live out of the block. -PrunedLiveBlocks::IsLive PrunedLiveBlocks::updateForUse(SILInstruction *user) { +PrunedLiveBlocks::IsLive PrunedLiveBlocks::updateForUse(SILInstruction *user, + unsigned bitNo) { SWIFT_ASSERT_ONLY(seenUse = true); auto *bb = user->getParent(); - switch (getBlockLiveness(bb)) { + switch (getBlockLiveness(bb, bitNo)) { case LiveOut: return LiveOut; case LiveWithin: @@ -64,8 +66,8 @@ PrunedLiveBlocks::IsLive PrunedLiveBlocks::updateForUse(SILInstruction *user) { case Dead: { // This use block has not yet been marked live. Mark it and its predecessor // blocks live. - computeUseBlockLiveness(bb); - return getBlockLiveness(bb); + computeUseBlockLiveness(bb, bitNo); + return getBlockLiveness(bb, bitNo); } } llvm_unreachable("covered switch"); @@ -76,7 +78,7 @@ PrunedLiveBlocks::IsLive PrunedLiveBlocks::updateForUse(SILInstruction *user) { //===----------------------------------------------------------------------===// void PrunedLiveness::updateForUse(SILInstruction *user, bool lifetimeEnding) { - auto useBlockLive = liveBlocks.updateForUse(user); + auto useBlockLive = liveBlocks.updateForUse(user, 0); // Record all uses of blocks on the liveness boundary. For blocks marked // LiveWithin, the boundary is considered to be the last use in the block. // From 4c484af381c41b86a29315361869bac24c33e7c2 Mon Sep 17 00:00:00 2001 From: Dario Rexin Date: Mon, 22 Aug 2022 13:18:52 -0700 Subject: [PATCH 278/491] [Benchmarks] Disable a few noisy Array benchmarks (#60705) --- benchmark/single-source/ArrayAppend.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/benchmark/single-source/ArrayAppend.swift b/benchmark/single-source/ArrayAppend.swift index 38d43948a93f8..2024c7c9a368d 100644 --- a/benchmark/single-source/ArrayAppend.swift +++ b/benchmark/single-source/ArrayAppend.swift @@ -26,7 +26,7 @@ public let benchmarks = [ BenchmarkInfo(name: "ArrayAppendGenericStructs", runFunction: run_ArrayAppendGenericStructs, tags: t, setUpFunction: { otherStructs = Array(repeating: S(x: 3, y: 4.2), count: 10_000) }, tearDownFunction: { otherStructs = nil }, legacyFactor: 10), - BenchmarkInfo(name: "ArrayAppendLatin1", runFunction: run_ArrayAppendLatin1, tags: t, legacyFactor: 34), + BenchmarkInfo(name: "ArrayAppendLatin1", runFunction: run_ArrayAppendLatin1, tags: t + [.skip], legacyFactor: 34), BenchmarkInfo(name: "ArrayAppendLatin1Substring", runFunction: run_ArrayAppendLatin1Substring, tags: t, legacyFactor: 36), BenchmarkInfo(name: "ArrayAppendLazyMap", runFunction: run_ArrayAppendLazyMap, tags: t, setUpFunction: { blackHole(array) }, legacyFactor: 10), @@ -39,15 +39,15 @@ public let benchmarks = [ BenchmarkInfo(name: "ArrayAppendStrings", runFunction: run_ArrayAppendStrings, tags: t, setUpFunction: { otherStrings = stride(from: 0, to: 10_000, by: 1).map { "\($0)" } }, tearDownFunction: { otherStrings = nil }, legacyFactor: 10), - BenchmarkInfo(name: "ArrayAppendToFromGeneric", runFunction: run_ArrayAppendToFromGeneric, tags: t, + BenchmarkInfo(name: "ArrayAppendToFromGeneric", runFunction: run_ArrayAppendToFromGeneric, tags: t + [.skip], setUpFunction: ones, tearDownFunction: releaseOnes, legacyFactor: 10), BenchmarkInfo(name: "ArrayAppendToGeneric", runFunction: run_ArrayAppendToGeneric, tags: t, setUpFunction: ones, tearDownFunction: releaseOnes, legacyFactor: 10), - BenchmarkInfo(name: "ArrayAppendUTF16", runFunction: run_ArrayAppendUTF16, tags: t, legacyFactor: 34), + BenchmarkInfo(name: "ArrayAppendUTF16", runFunction: run_ArrayAppendUTF16, tags: t + [.skip], legacyFactor: 34), BenchmarkInfo(name: "ArrayAppendUTF16Substring", runFunction: run_ArrayAppendUTF16Substring, tags: t, legacyFactor: 36), BenchmarkInfo(name: "ArrayPlusEqualArrayOfInt", runFunction: run_ArrayPlusEqualArrayOfInt, tags: t + [.unstable], setUpFunction: ones, tearDownFunction: releaseOnes, legacyFactor: 10), - BenchmarkInfo(name: "ArrayPlusEqualFiveElementCollection", runFunction: run_ArrayPlusEqualFiveElementCollection, tags: t, legacyFactor: 37), + BenchmarkInfo(name: "ArrayPlusEqualFiveElementCollection", runFunction: run_ArrayPlusEqualFiveElementCollection, tags: t + [.skip], legacyFactor: 37), BenchmarkInfo(name: "ArrayPlusEqualSingleElementCollection", runFunction: run_ArrayPlusEqualSingleElementCollection, tags: t, legacyFactor: 47), BenchmarkInfo(name: "ArrayPlusEqualThreeElements", runFunction: run_ArrayPlusEqualThreeElements, tags: t, legacyFactor: 10), ] From e51e17fa5e2f2e6108deb5ea09525ba624645b29 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Sat, 20 Aug 2022 17:01:08 -0700 Subject: [PATCH 279/491] [pruned-liveness] Change the internal bit-vector to use 2 bits to represent its state instead of 1 + missing value in DenseMap. The reason why I am doing this is that in order to be able to use PrunedLivenessBlocks with multiple elements, we can no longer rely on dead being represented by a block not having any state, since a dead bit could have a neighboring live bit. That being said, the only place that this is used now is the current PrunedLiveness implementation which only stores a single bit... but that still at least exercises the code and lets us know that it works. --- include/swift/SIL/PrunedLiveness.h | 147 +++++++++++++++++++++++++---- lib/SIL/Utils/PrunedLiveness.cpp | 70 ++++++++------ 2 files changed, 171 insertions(+), 46 deletions(-) diff --git a/include/swift/SIL/PrunedLiveness.h b/include/swift/SIL/PrunedLiveness.h index 785a8955979e6..c96672de1cf44 100644 --- a/include/swift/SIL/PrunedLiveness.h +++ b/include/swift/SIL/PrunedLiveness.h @@ -96,6 +96,8 @@ #include "swift/SIL/SILBasicBlock.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" namespace swift { @@ -116,9 +118,12 @@ class DeadEndBlocks; /// could be handled by adding an updateForUseBeforeFirstDef() API. /// /// We allow for multiple bits of liveness information to be tracked by -/// internally using a SmallBitVector. We default to only tracking a single -/// bit. The multiple bit tracking is useful when tracking state for multiple -/// fields of the same root value. +/// internally using a SmallBitVector. The multiple bit tracking is useful when +/// tracking state for multiple fields of the same root value. To do this, we +/// actually track 2 bits per actual needed bit so we can represent 3 Dead, +/// LiveOut, LiveWithin. This was previously unnecessary since we could just +/// represent dead by not having liveness state for a block. With multiple bits +/// possible this is no longer true. /// /// TODO: This can be made space-efficient if all clients can maintain a block /// numbering so liveness info can be represented as bitsets across the blocks. @@ -138,12 +143,81 @@ class PrunedLiveBlocks { /// /// LiveOut blocks are live on at least one successor path. LiveOut blocks may /// or may not contain defs or uses. - enum IsLive { Dead, LiveWithin, LiveOut }; + /// + /// NOTE: The values below for Dead, LiveWithin, LiveOut were picked to ensure + /// that given a 2 bit representation of the value, a value is Dead if the + /// first bit is 0 and is LiveOut if the second bit is set. + enum IsLive { + Dead = 0, + LiveWithin = 1, + LiveOut = 3, + }; + + /// A bit vector that stores information about liveness. This is composed + /// with SmallBitVector since it contains two bits per liveness so that it + /// can represent 3 states, Dead, LiveWithin, LiveOut. We take advantage of + /// their numeric values to make testing easier \see documentation on IsLive. + class LivenessSmallBitVector { + SmallBitVector bits; + + public: + LivenessSmallBitVector() : bits() {} + + void init(unsigned numBits) { + assert(bits.size() == 0); + assert(numBits != 0); + bits.resize(numBits * 2); + } + + unsigned size() const { return bits.size() / 2; } + + IsLive getLiveness(unsigned bitNo) const { + SmallVector foundLiveness; + getLiveness(bitNo, bitNo + 1, foundLiveness); + return foundLiveness[0]; + } + + void getLiveness(unsigned startBitNo, unsigned endBitNo, + SmallVectorImpl &resultingFoundLiveness) const { + unsigned actualStartBitNo = startBitNo * 2; + unsigned actualEndBitNo = endBitNo * 2; + + // NOTE: We pad both before/after with Dead to ensure that we are + // returning an array that acts as a bit mask and thus can be directly + // compared against other such bitmasks. This invariant is used when + // computing boundaries. + for (unsigned i = 0; i != startBitNo; ++i) { + resultingFoundLiveness.push_back(Dead); + } + for (unsigned i = actualStartBitNo, e = actualEndBitNo; i != e; i += 2) { + if (!bits[i]) { + resultingFoundLiveness.push_back(Dead); + continue; + } + + resultingFoundLiveness.push_back(bits[i + 1] ? LiveOut : LiveWithin); + } + for (unsigned i = endBitNo, e = size(); i != e; ++i) { + resultingFoundLiveness.push_back(Dead); + } + } + + void setLiveness(unsigned startBitNo, unsigned endBitNo, IsLive isLive) { + for (unsigned i = startBitNo * 2, e = endBitNo * 2; i != e; i += 2) { + bits[i] = isLive & 1; + bits[i + 1] = isLive & 2; + } + } + + void setLiveness(unsigned bitNo, IsLive isLive) { + setLiveness(bitNo, bitNo + 1, isLive); + } + }; private: /// Map all blocks in which current def is live to a SmallBitVector indicating /// whether the value represented by said bit is also liveout of the block. - llvm::SmallDenseMap liveBlocks; + llvm::SmallDenseMap liveBlocks; /// Number of bits of liveness to track. By default 1. Used to track multiple /// liveness bits. @@ -178,37 +252,76 @@ class PrunedLiveBlocks { } void initializeDefBlock(SILBasicBlock *defBB, unsigned bitNo) { - markBlockLive(defBB, LiveWithin, bitNo); + markBlockLive(defBB, bitNo, LiveWithin); + } + + void initializeDefBlock(SILBasicBlock *defBB, unsigned startBitNo, + unsigned endBitNo) { + markBlockLive(defBB, startBitNo, endBitNo, LiveWithin); } /// Update this liveness result for a single use. - IsLive updateForUse(SILInstruction *user, unsigned bitNo); + IsLive updateForUse(SILInstruction *user, unsigned bitNo) { + SmallVector resultingLiveness; + updateForUse(user, bitNo, bitNo + 1, resultingLiveness); + return resultingLiveness[0]; + } + + /// Update this range of liveness results for a single use. + void updateForUse(SILInstruction *user, unsigned startBitNo, + unsigned endBitNo, + SmallVectorImpl &resultingLiveness); IsLive getBlockLiveness(SILBasicBlock *bb, unsigned bitNo) const { + SmallVector isLive; + getBlockLiveness(bb, bitNo, bitNo + 1, isLive); + return isLive[0]; + } + + void getBlockLiveness(SILBasicBlock *bb, unsigned startBitNo, + unsigned endBitNo, + SmallVectorImpl &foundLivenessInfo) const { auto liveBlockIter = liveBlocks.find(bb); - if (liveBlockIter == liveBlocks.end()) - return Dead; + if (liveBlockIter == liveBlocks.end()) { + for (unsigned i : range(numBitsToTrack)) { + (void)i; + foundLivenessInfo.push_back(Dead); + } + return; + } + assert(liveBlockIter->second.size() == 1); - return liveBlockIter->second[bitNo] ? LiveOut : LiveWithin; + liveBlockIter->second.getLiveness(startBitNo, endBitNo, foundLivenessInfo); } protected: - void markBlockLive(SILBasicBlock *bb, IsLive isLive, unsigned bitNo) { + void markBlockLive(SILBasicBlock *bb, unsigned bitNo, IsLive isLive) { + markBlockLive(bb, bitNo, bitNo + 1, isLive); + } + + void markBlockLive(SILBasicBlock *bb, unsigned startBitNo, unsigned endBitNo, + IsLive isLive) { assert(isLive != Dead && "erasing live blocks isn't implemented."); - bool isLiveOut = (isLive == LiveOut); auto iterAndInserted = - liveBlocks.insert(std::make_pair(bb, SmallBitVector(numBitsToTrack))); + liveBlocks.insert(std::make_pair(bb, LivenessSmallBitVector())); if (iterAndInserted.second) { - iterAndInserted.first->getSecond()[bitNo] = isLiveOut; + // We initialize the size of the small bit vector here rather than in + // liveBlocks.insert above to prevent us from allocating upon failure if + // we have more than SmallBitVector's small size number of bits. + auto &insertedBV = iterAndInserted.first->getSecond(); + insertedBV.init(numBitsToTrack); + insertedBV.setLiveness(startBitNo, endBitNo, isLive); if (discoveredBlocks) discoveredBlocks->push_back(bb); - } else if (isLiveOut) { + } else if (isLive == LiveOut) { // Update the existing entry to be live-out. - iterAndInserted.first->getSecond()[bitNo] = true; + iterAndInserted.first->getSecond().setLiveness(startBitNo, endBitNo, + LiveOut); } } - void computeUseBlockLiveness(SILBasicBlock *userBB, unsigned bitNo); + void computeUseBlockLiveness(SILBasicBlock *userBB, unsigned startBitNo, + unsigned endBitNo); }; /// PrunedLiveness tracks PrunedLiveBlocks along with "interesting" use diff --git a/lib/SIL/Utils/PrunedLiveness.cpp b/lib/SIL/Utils/PrunedLiveness.cpp index 2fb8a31f9cd18..a2a3847aafc19 100644 --- a/lib/SIL/Utils/PrunedLiveness.cpp +++ b/lib/SIL/Utils/PrunedLiveness.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "swift/SIL/PrunedLiveness.h" +#include "swift/Basic/Defer.h" #include "swift/SIL/BasicBlockDatastructures.h" #include "swift/SIL/BasicBlockUtils.h" #include "swift/SIL/OwnershipUtils.h" @@ -20,29 +21,35 @@ using namespace swift; /// Mark blocks live during a reverse CFG traversal from one specific block /// containing a user. void PrunedLiveBlocks::computeUseBlockLiveness(SILBasicBlock *userBB, - unsigned bitNo) { + unsigned startBitNo, + unsigned endBitNo) { // If, we are visiting this block, then it is not already LiveOut. Mark it // LiveWithin to indicate a liveness boundary within the block. - markBlockLive(userBB, LiveWithin, bitNo); + markBlockLive(userBB, startBitNo, endBitNo, LiveWithin); - SmallVector predBBWorklist({userBB}); - while (!predBBWorklist.empty()) { - SILBasicBlock *bb = predBBWorklist.pop_back_val(); + SmallVector predLivenessInfo; + BasicBlockWorklist worklist(userBB->getFunction()); + worklist.push(userBB); + while (auto *block = worklist.pop()) { // The popped `bb` is live; now mark all its predecessors LiveOut. // // Traversal terminates at any previously visited block, including the // blocks initialized as definition blocks. - for (auto *predBB : bb->getPredecessorBlocks()) { - switch (getBlockLiveness(predBB, bitNo)) { - case Dead: - predBBWorklist.push_back(predBB); - LLVM_FALLTHROUGH; - case LiveWithin: - markBlockLive(predBB, LiveOut, bitNo); - break; - case LiveOut: - break; + for (auto *predBlock : block->getPredecessorBlocks()) { + SWIFT_DEFER { predLivenessInfo.clear(); }; + getBlockLiveness(predBlock, startBitNo, endBitNo, predLivenessInfo); + for (unsigned i : indices(predLivenessInfo)) { + switch (predLivenessInfo[i]) { + case Dead: + worklist.pushIfNotVisited(predBlock); + LLVM_FALLTHROUGH; + case LiveWithin: + markBlockLive(predBlock, startBitNo, endBitNo, LiveOut); + break; + case LiveOut: + break; + } } } } @@ -53,24 +60,29 @@ void PrunedLiveBlocks::computeUseBlockLiveness(SILBasicBlock *userBB, /// Return the updated liveness of the \p use block (LiveOut or LiveWithin). /// /// Terminators are not live out of the block. -PrunedLiveBlocks::IsLive PrunedLiveBlocks::updateForUse(SILInstruction *user, - unsigned bitNo) { +void PrunedLiveBlocks::updateForUse( + SILInstruction *user, unsigned startBitNo, unsigned endBitNo, + SmallVectorImpl &resultingLivenessInfo) { SWIFT_ASSERT_ONLY(seenUse = true); auto *bb = user->getParent(); - switch (getBlockLiveness(bb, bitNo)) { - case LiveOut: - return LiveOut; - case LiveWithin: - return LiveWithin; - case Dead: { - // This use block has not yet been marked live. Mark it and its predecessor - // blocks live. - computeUseBlockLiveness(bb, bitNo); - return getBlockLiveness(bb, bitNo); - } + getBlockLiveness(bb, startBitNo, endBitNo, resultingLivenessInfo); + + for (auto isLive : resultingLivenessInfo) { + switch (isLive) { + case LiveOut: + case LiveWithin: + continue; + case Dead: { + // This use block has not yet been marked live. Mark it and its + // predecessor blocks live. + computeUseBlockLiveness(bb, startBitNo, endBitNo); + resultingLivenessInfo.clear(); + return getBlockLiveness(bb, startBitNo, endBitNo, resultingLivenessInfo); + } + } + llvm_unreachable("covered switch"); } - llvm_unreachable("covered switch"); } //===----------------------------------------------------------------------===// From cd7bc86bb1c3e4d3801412e78504045c67a7adf3 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 22 Aug 2022 17:07:25 -0400 Subject: [PATCH 280/491] [Test] Update error message in validation test. --- .../compiler_crashers_2_fixed/0159-rdar40009245.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift b/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift index 9becb7b44a2a1..dc0696f00f675 100644 --- a/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift +++ b/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift @@ -4,5 +4,5 @@ protocol P { associatedtype A : P where A.X == Self // expected-error@-1{{'X' is not a member type of type 'Self.A'}} associatedtype X : P where P.A == Self - // expected-error@-1{{associated type 'A' can only be used with a concrete type or generic parameter base}} + // expected-error@-1{{cannot access associated type 'A' from 'P'; use a concrete type or generic parameter base instead}} } From ffab0c541f56cd7fd1a79b16a14a2627bb57b82d Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Mon, 22 Aug 2022 14:16:12 -0700 Subject: [PATCH 281/491] =?UTF-8?q?[test]=20UnicodeScalarProperties:=20Dis?= =?UTF-8?q?able=20when=20Unicode=20data=20files=20aren=E2=80=99t=20availab?= =?UTF-8?q?le?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To reenable, the test needs to be configured to upload these files to the remote machine that executes the tests. --- validation-test/stdlib/UnicodeScalarProperties.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/validation-test/stdlib/UnicodeScalarProperties.swift b/validation-test/stdlib/UnicodeScalarProperties.swift index 3fea3908a1288..58a52de56cdc9 100644 --- a/validation-test/stdlib/UnicodeScalarProperties.swift +++ b/validation-test/stdlib/UnicodeScalarProperties.swift @@ -4,6 +4,11 @@ // REQUIRES: optimized_stdlib // REQUIRES: objc_interop +// This test requires access to Unicode data files in the source tree, so +// it doesn't currently support testing on a remote device. (rdar://98993795) +// UNSUPPORTED: remote_run +// UNSUPPORTED: device_run + @_spi(_Unicode) import Swift From 7f6fd0bcf8545b90be3d908a3851cb27d39dceaf Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Thu, 16 Jun 2022 13:10:15 -0700 Subject: [PATCH 282/491] Reorganize if to reduce indentation --- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 66 +++++++++++----------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 57a59860e79bf..397cb79a02d99 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -732,21 +732,22 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( // Replace destroys with a release of the value. if (auto *dai = dyn_cast(inst)) { - if (dai->getOperand() == asi) { - if (runningVals) { - replaceDestroy(dai, runningVals->value.replacement(asi, dai), ctx, - deleter, instructionsToDelete); - if (shouldAddLexicalLifetime(asi)) { - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/dai, ctx, - runningVals->value); - } - runningVals->isStorageValid = false; - if (lastStoreInst) - lastStoreInst->isStorageValid = false; - } else { - assert(!deinitializationPoints[blockPromotingWithin]); - deinitializationPoints[blockPromotingWithin] = dai; + if (dai->getOperand() != asi) { + continue; + } + if (runningVals) { + replaceDestroy(dai, runningVals->value.replacement(asi, dai), ctx, + deleter, instructionsToDelete); + if (shouldAddLexicalLifetime(asi)) { + endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/dai, ctx, + runningVals->value); } + runningVals->isStorageValid = false; + if (lastStoreInst) + lastStoreInst->isStorageValid = false; + } else { + assert(!deinitializationPoints[blockPromotingWithin]); + deinitializationPoints[blockPromotingWithin] = dai; } continue; } @@ -1636,26 +1637,27 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) { // Remove stores and record the value that we are saving as the running // value. if (auto *si = dyn_cast(inst)) { - if (si->getDest() == asi) { - if (si->getOwnershipQualifier() == StoreOwnershipQualifier::Assign) { - assert(runningVals && runningVals->isStorageValid); - SILBuilderWithScope(si, ctx).createDestroyValue( - si->getLoc(), runningVals->value.replacement(asi, si)); - } - auto oldRunningVals = runningVals; - runningVals = {LiveValues::toReplace(asi, /*replacement=*/si->getSrc()), - /*isStorageValid=*/true}; - if (shouldAddLexicalLifetime(asi)) { - if (oldRunningVals && oldRunningVals->isStorageValid) { - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/si, ctx, - oldRunningVals->value); - } - runningVals = beginLexicalLifetimeAfterStore(asi, si); - } - deleter.forceDelete(inst); - ++NumInstRemoved; + if (si->getDest() != asi) { continue; } + if (si->getOwnershipQualifier() == StoreOwnershipQualifier::Assign) { + assert(runningVals && runningVals->isStorageValid); + SILBuilderWithScope(si, ctx).createDestroyValue( + si->getLoc(), runningVals->value.replacement(asi, si)); + } + auto oldRunningVals = runningVals; + runningVals = {LiveValues::toReplace(asi, /*replacement=*/si->getSrc()), + /*isStorageValid=*/true}; + if (shouldAddLexicalLifetime(asi)) { + if (oldRunningVals && oldRunningVals->isStorageValid) { + endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/si, ctx, + oldRunningVals->value); + } + runningVals = beginLexicalLifetimeAfterStore(asi, si); + } + deleter.forceDelete(inst); + ++NumInstRemoved; + continue; } // Replace debug_value w/ address value with debug_value of From 0c2fd6b419babfb4639eace7d060f5d096883f8f Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Thu, 16 Jun 2022 13:10:54 -0700 Subject: [PATCH 283/491] Remove unnecessary edge case --- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 397cb79a02d99..dac5dc832c300 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -752,16 +752,6 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( continue; } - if (auto *dvi = dyn_cast(inst)) { - if (runningVals && - dvi->getOperand() == runningVals->value.replacement(asi, dvi)) { - // Reset LastStore. - // So that we don't end up passing dead values as phi args in - // StackAllocationPromoter::fixBranchesAndUses - lastStoreInst = llvm::None; - } - } - // Stop on deallocation. if (auto *dsi = dyn_cast(inst)) { if (dsi->getOperand() == asi) From 13223f6edfac48b1ef63f612673b9dfeb70218e7 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Thu, 16 Jun 2022 19:53:58 -0700 Subject: [PATCH 284/491] Remove fake use of lexical copy --- .../swift/SILOptimizer/Utils/CFGOptUtils.h | 5 ++-- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 20 ++-------------- lib/SILOptimizer/Utils/CFGOptUtils.cpp | 24 ++++++++++++------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/include/swift/SILOptimizer/Utils/CFGOptUtils.h b/include/swift/SILOptimizer/Utils/CFGOptUtils.h index 1c1b0eb6a4675..d8ab3d4401d4b 100644 --- a/include/swift/SILOptimizer/Utils/CFGOptUtils.h +++ b/include/swift/SILOptimizer/Utils/CFGOptUtils.h @@ -65,13 +65,14 @@ TermInst *changeEdgeValue(TermInst *branch, SILBasicBlock *dest, size_t idx, /// specified index. Asserts internally that the argument along the edge does /// not have uses. TermInst *deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock, - size_t argIndex); + size_t argIndex, bool cleanupDeadPhiOp = true); /// Erase the \p argIndex phi argument from \p block. Asserts that the argument /// is a /real/ phi argument. Removes all incoming values for the argument from /// predecessor terminators. Asserts internally that it only ever is given /// "true" phi argument. -void erasePhiArgument(SILBasicBlock *block, unsigned argIndex); +void erasePhiArgument(SILBasicBlock *block, unsigned argIndex, + bool cleanupDeadPhiOp = true); /// Replace a branch target. /// diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index dac5dc832c300..0b9473f5add60 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -698,23 +698,6 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( oldRunningVals->value); } runningVals = beginLexicalLifetimeAfterStore(asi, si); - // Create a use of the newly created copy in order to keep phi pruning - // from deleting our lifetime beginning instructions. - // - // TODO: Remove this hack, it is only necessary because erasePhiArgument - // calls deleteEdgeValue which calls - // deleteTriviallyDeadOperandsOfDeadArgument and deletes the copy - // and borrow that we added and want not to have deleted. - SILBuilderWithScope::insertAfter( - runningVals->value.copy->getDefiningInstruction(), - [&](auto builder) { - SILLocation loc = RegularLocation::getAutoGeneratedLocation(); - auto *useOfCopy = - builder.createCopyValue(loc, runningVals->value.copy); - // Note that we don't call prepareToDelete useOfCopy because we - // specifically want this instruction to remain a use of copy. - instructionsToDelete.push_back(useOfCopy); - }); } continue; } @@ -1060,7 +1043,8 @@ void StackAllocationPromoter::fixBranchesAndUses(BlockSetVector &phiBlocks, auto *phi = cast( block->getArgument(block->getNumArguments() - 1)); phi->replaceAllUsesWithUndef(); - erasePhiArgument(block, block->getNumArguments() - 1); + erasePhiArgument(block, block->getNumArguments() - 1, + /*cleanupDeadPhiOp*/ false); }; for (auto *block : phiBlocks) { auto *proactivePhi = cast( diff --git a/lib/SILOptimizer/Utils/CFGOptUtils.cpp b/lib/SILOptimizer/Utils/CFGOptUtils.cpp index aaca172bc27dc..5854b6377e1c9 100644 --- a/lib/SILOptimizer/Utils/CFGOptUtils.cpp +++ b/lib/SILOptimizer/Utils/CFGOptUtils.cpp @@ -88,7 +88,7 @@ deleteTriviallyDeadOperandsOfDeadArgument(MutableArrayRef termOperands, // Our implementation assumes that our caller is attempting to remove a dead // SILPhiArgument from a SILBasicBlock and has already RAUWed the argument. TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock, - size_t argIndex) { + size_t argIndex, bool cleanupDeadPhiOps) { if (auto *cbi = dyn_cast(branch)) { SmallVector trueArgs; SmallVector falseArgs; @@ -97,14 +97,18 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock, llvm::copy(cbi->getFalseArgs(), std::back_inserter(falseArgs)); if (destBlock == cbi->getTrueBB()) { - deleteTriviallyDeadOperandsOfDeadArgument(cbi->getTrueOperands(), - argIndex); + if (cleanupDeadPhiOps) { + deleteTriviallyDeadOperandsOfDeadArgument(cbi->getTrueOperands(), + argIndex); + } trueArgs.erase(trueArgs.begin() + argIndex); } if (destBlock == cbi->getFalseBB()) { - deleteTriviallyDeadOperandsOfDeadArgument(cbi->getFalseOperands(), - argIndex); + if (cleanupDeadPhiOps) { + deleteTriviallyDeadOperandsOfDeadArgument(cbi->getFalseOperands(), + argIndex); + } falseArgs.erase(falseArgs.begin() + argIndex); } @@ -120,8 +124,9 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock, if (auto *bi = dyn_cast(branch)) { SmallVector args; llvm::copy(bi->getArgs(), std::back_inserter(args)); - - deleteTriviallyDeadOperandsOfDeadArgument(bi->getAllOperands(), argIndex); + if (cleanupDeadPhiOps) { + deleteTriviallyDeadOperandsOfDeadArgument(bi->getAllOperands(), argIndex); + } args.erase(args.begin() + argIndex); auto *result = SILBuilderWithScope(bi).createBranch(bi->getLoc(), bi->getDestBB(), args); @@ -132,7 +137,8 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock, llvm_unreachable("unsupported terminator"); } -void swift::erasePhiArgument(SILBasicBlock *block, unsigned argIndex) { +void swift::erasePhiArgument(SILBasicBlock *block, unsigned argIndex, + bool cleanupDeadPhiOps) { assert(block->getArgument(argIndex)->isPhi() && "Only should be used on phi arguments"); block->eraseArgument(argIndex); @@ -149,7 +155,7 @@ void swift::erasePhiArgument(SILBasicBlock *block, unsigned argIndex) { predBlocks.insert(pred); for (auto *pred : predBlocks) - deleteEdgeValue(pred->getTerminator(), block, argIndex); + deleteEdgeValue(pred->getTerminator(), block, argIndex, cleanupDeadPhiOps); } /// Changes the edge value between a branch and destination basic block From d3b0219f3256612304b7b9bad11b4bd4504c2a25 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Fri, 24 Jun 2022 15:00:25 -0700 Subject: [PATCH 285/491] Update test --- test/SILOptimizer/OSLogFullOptTest.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/SILOptimizer/OSLogFullOptTest.swift b/test/SILOptimizer/OSLogFullOptTest.swift index 4a8f45e5c970a..fcf0cdd8c8f84 100644 --- a/test/SILOptimizer/OSLogFullOptTest.swift +++ b/test/SILOptimizer/OSLogFullOptTest.swift @@ -131,6 +131,7 @@ func testNSObjectInterpolation(nsArray: NSArray) { // TODO: check why the ARC optimizer cannot eliminate the many retain/release pairs here. // CHECK: entry: // CHECK-NEXT: bitcast %TSo7NSArrayC* %0 to i8* + // CHECK-NEXT: [[COPY:%.+]] = tail call i8* @llvm.objc.retain // CHECK-NEXT: [[NSARRAY_ARG:%.+]] = tail call i8* @llvm.objc.retain // CHECK: tail call swiftcc i1 @"${{.*}}isLoggingEnabled{{.*}}"() // CHECK-NEXT: br i1 {{%.*}}, label %[[ENABLED:[0-9]+]], label %[[NOT_ENABLED:[0-9]+]] @@ -138,6 +139,7 @@ func testNSObjectInterpolation(nsArray: NSArray) { // CHECK: [[NOT_ENABLED]]: // CHECK-NEXT: tail call void @swift_release // CHECK-NEXT: tail call void @llvm.objc.release + // CHECK-NEXT: tail call void @llvm.objc.release // CHECK: br label %[[EXIT:[0-9]+]] // CHECK: [[ENABLED]]: @@ -167,6 +169,7 @@ func testNSObjectInterpolation(nsArray: NSArray) { // CHECK-NEXT: [[BITCASTED_SRC2:%.+]] = bitcast i8* {{.*}} to %TSo7NSArrayC* // CHECK-64-NEXT: store %TSo7NSArrayC* [[BITCASTED_SRC2]], %TSo7NSArrayC** [[BITCASTED_DEST2]], align 8 // CHECK-32-NEXT: store %TSo7NSArrayC* [[BITCASTED_SRC2]], %TSo7NSArrayC** [[BITCASTED_DEST2]], align 4 + // CHECK-NEXT: tail call void @llvm.objc.release(i8* [[NSARRAY_ARG]]) // CHECK-64: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @{{.*}}, i64 0, i64 0), i8* {{(nonnull )?}}[[BUFFER]], i32 12) // CHECK-32: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @{{.*}}, i32 0, i32 0), i8* {{(nonnull )?}}[[BUFFER]], i32 8) // CHECK: [[BITCASTED_OBJ_STORAGE:%.+]] = bitcast i8* [[OBJ_STORAGE]] to %swift.opaque* From 6f582336bfefcdb381425de33c6d11f00e2eefae Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Wed, 17 Aug 2022 18:40:10 -0700 Subject: [PATCH 286/491] [TypeLowering] Record whether a type is lexical. Used RecursiveProperties to keep track of whether a type is lexical. This is done in the usual way by OR'ing together whether components are lexicial. The the values to be OR'd together come from primitives: everything is non-lexical except reference types and resilient types (because they could become reference types). Those values can however be affected by user annotations: marking a class @_lexical makes the value for that primitive lexical; markinig an enum or struct @_eagerMove overrides the value obtained by OR'ing together its components and makes it be non-lexical. --- include/swift/SIL/TypeLowering.h | 30 +++++++++-- lib/SIL/IR/TypeLowering.cpp | 90 ++++++++++++++++++++++++++++---- 2 files changed, 107 insertions(+), 13 deletions(-) diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index 156fd83914145..810d8a6a80617 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -169,6 +169,12 @@ enum IsInfiniteType_t : bool { IsInfiniteType = true, }; +/// Does this type contain at least one non-trivial, non-eager-move type? +enum IsLexical_t : bool { + IsNotLexical = false, + IsLexical = true, +}; + /// Extended type information used by SIL. class TypeLowering { public: @@ -184,6 +190,7 @@ class TypeLowering { TypeExpansionSensitiveFlag = 1 << 4, InfiniteFlag = 1 << 5, HasRawPointerFlag = 1 << 6, + LexicalFlag = 1 << 7, }; // clang-format on @@ -198,13 +205,15 @@ class TypeLowering { IsAddressOnly_t isAddressOnly, IsResilient_t isResilient, IsTypeExpansionSensitive_t isTypeExpansionSensitive = IsNotTypeExpansionSensitive, - HasRawPointer_t hasRawPointer = DoesNotHaveRawPointer) + HasRawPointer_t hasRawPointer = DoesNotHaveRawPointer, + IsLexical_t isLexical = IsNotLexical) : Flags((isTrivial ? 0U : NonTrivialFlag) | (isFixedABI ? 0U : NonFixedABIFlag) | (isAddressOnly ? AddressOnlyFlag : 0U) | (isResilient ? ResilientFlag : 0U) | (isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0U) | - (hasRawPointer ? HasRawPointerFlag : 0U)) {} + (hasRawPointer ? HasRawPointerFlag : 0U) | + (isLexical ? LexicalFlag : 0U)) {} constexpr bool operator==(RecursiveProperties p) const { return Flags == p.Flags; @@ -220,11 +229,13 @@ class TypeLowering { } static constexpr RecursiveProperties forReference() { - return {IsNotTrivial, IsFixedABI, IsNotAddressOnly, IsNotResilient}; + return {IsNotTrivial, IsFixedABI, IsNotAddressOnly, IsNotResilient, + IsNotTypeExpansionSensitive, DoesNotHaveRawPointer, IsLexical}; } static constexpr RecursiveProperties forOpaque() { - return {IsNotTrivial, IsNotFixedABI, IsAddressOnly, IsNotResilient}; + return {IsNotTrivial, IsNotFixedABI, IsAddressOnly, IsNotResilient, + IsNotTypeExpansionSensitive, DoesNotHaveRawPointer, IsLexical}; } static constexpr RecursiveProperties forResilient() { @@ -257,6 +268,9 @@ class TypeLowering { IsInfiniteType_t isInfinite() const { return IsInfiniteType_t((Flags & InfiniteFlag) != 0); } + IsLexical_t isLexical() const { + return IsLexical_t((Flags & LexicalFlag) != 0); + } void setNonTrivial() { Flags |= NonTrivialFlag; } void setNonFixedABI() { Flags |= NonFixedABIFlag; } @@ -267,6 +281,9 @@ class TypeLowering { (isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0); } void setInfinite() { Flags |= InfiniteFlag; } + void setLexical(IsLexical_t isLexical) { + Flags = (Flags & ~LexicalFlag) | (isLexical ? LexicalFlag : 0); + } }; private: @@ -368,6 +385,11 @@ class TypeLowering { return Properties.isTypeExpansionSensitive(); } + /// Should a value of this type have its lifetime tied to its lexical scope? + bool isLexical() const { + return Properties.isLexical(); + } + ResilienceExpansion getResilienceExpansion() const { return expansionContext.getResilienceExpansion(); } diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index 7c4e20dffc6fc..6d8429fbd073e 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -232,6 +232,21 @@ namespace { return props; } + RecursiveProperties applyLifetimeAnnotation(LifetimeAnnotation annotation, + RecursiveProperties props) { + switch (annotation) { + case LifetimeAnnotation::None: + break; + case LifetimeAnnotation::Lexical: + props.setLexical(IsLexical); + break; + case LifetimeAnnotation::EagerMove: + props.setLexical(IsNotLexical); + break; + } + return props; + } + RecursiveProperties getTrivialRecursiveProperties(IsTypeExpansionSensitive_t isSensitive) { return mergeIsTypeExpansionSensitive(isSensitive, @@ -267,8 +282,6 @@ namespace { IMPL(BuiltinBridgeObject, Reference) IMPL(BuiltinVector, Trivial) IMPL(SILToken, Trivial) - IMPL(Class, Reference) - IMPL(BoundGenericClass, Reference) IMPL(AnyMetatype, Trivial) IMPL(Module, Trivial) @@ -288,7 +301,9 @@ namespace { IsTypeExpansionSensitive_t isSensitive) { return asImpl().handleAddressOnly(type, {IsNotTrivial, IsFixedABI, IsAddressOnly, IsNotResilient, - isSensitive}); + isSensitive, + DoesNotHaveRawPointer, + IsLexical}); } RetTy visitBuiltinDefaultActorStorageType( @@ -297,7 +312,9 @@ namespace { IsTypeExpansionSensitive_t isSensitive) { return asImpl().handleAddressOnly(type, {IsNotTrivial, IsFixedABI, IsAddressOnly, IsNotResilient, - isSensitive}); + isSensitive, + DoesNotHaveRawPointer, + IsLexical}); } RetTy visitAnyFunctionType(CanAnyFunctionType type, @@ -479,7 +496,9 @@ namespace { IsFixedABI, \ IsAddressOnly, \ IsNotResilient, \ - isSensitive}); \ + isSensitive, \ + DoesNotHaveRawPointer, \ + IsLexical}); \ } #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ RetTy visit##Name##StorageType(Can##Name##StorageType type, \ @@ -502,7 +521,9 @@ namespace { IsFixedABI, \ IsAddressOnly, \ IsNotResilient, \ - isSensitive}); \ + isSensitive, \ + DoesNotHaveRawPointer, \ + IsLexical}); \ } \ RetTy visit##Name##StorageType(Can##Name##StorageType type, \ AbstractionPattern origType, \ @@ -579,7 +600,9 @@ namespace { IsFixedABI, IsAddressOnly, IsNotResilient, - isSensitive}); + isSensitive, + DoesNotHaveRawPointer, + IsLexical}); // Class-constrained and boxed existentials are refcounted. case ExistentialRepresentation::Class: case ExistentialRepresentation::Boxed: @@ -608,6 +631,20 @@ namespace { return visitExistentialType(type, origType, isSensitive); } + // Classes depend on their attributes. + RetTy visitClassType(CanClassType type, AbstractionPattern origType, + IsTypeExpansionSensitive_t isSensitive) { + return asImpl().visitAnyClassType(type, origType, type->getDecl(), + isSensitive); + } + + RetTy visitBoundGenericClassType(CanBoundGenericClassType type, + AbstractionPattern origType, + IsTypeExpansionSensitive_t isSensitive) { + return asImpl().visitAnyClassType(type, origType, type->getDecl(), + isSensitive); + } + // Enums depend on their enumerators. RetTy visitEnumType(CanEnumType type, AbstractionPattern origType, IsTypeExpansionSensitive_t isSensitive) { @@ -671,7 +708,9 @@ namespace { IsFixedABI, IsAddressOnly, IsNotResilient, - isSensitive}); + isSensitive, + DoesNotHaveRawPointer, + IsLexical}); } RetTy visitSILBoxType(CanSILBoxType type, @@ -723,6 +762,14 @@ namespace { return properties; } + RecursiveProperties + visitAnyClassType(CanType type, AbstractionPattern origType, ClassDecl *D, + IsTypeExpansionSensitive_t isSensitive) { + // Consult the type lowering. + auto &lowering = TC.getTypeLowering(origType, type, Expansion); + return handleClassificationFromLowering(type, lowering, isSensitive); + } + RecursiveProperties visitAnyEnumType(CanType type, AbstractionPattern origType, EnumDecl *D, @@ -1743,7 +1790,8 @@ namespace { IsTypeExpansionSensitive_t isSensitive) : AddressOnlyTypeLowering(type, {IsNotTrivial, IsFixedABI, - IsAddressOnly, IsNotResilient, isSensitive}, + IsAddressOnly, IsNotResilient, isSensitive, + DoesNotHaveRawPointer, IsLexical}, forExpansion) {} void emitCopyInto(SILBuilder &B, SILLocation loc, @@ -2019,6 +2067,18 @@ namespace { return false; } + TypeLowering *visitAnyClassType(CanType classType, + AbstractionPattern origType, ClassDecl *C, + IsTypeExpansionSensitive_t isSensitive) { + RecursiveProperties properties = + getReferenceRecursiveProperties(isSensitive); + + if (C->getLifetimeAnnotation() == LifetimeAnnotation::EagerMove) + properties.setLexical(IsNotLexical); + + return handleReference(classType, properties); + } + TypeLowering *visitAnyStructType(CanType structType, AbstractionPattern origType, StructDecl *D, @@ -2061,8 +2121,14 @@ namespace { properties.addSubobject(classifyType(origFieldType, substFieldType, TC, Expansion)); + properties = + applyLifetimeAnnotation(field->getLifetimeAnnotation(), properties); } + // Type-level annotations override inferred behavior. + properties = + applyLifetimeAnnotation(D->getLifetimeAnnotation(), properties); + return handleAggregateByProperties(structType, properties); } @@ -2119,8 +2185,14 @@ namespace { ->getReducedType(D->getGenericSignature())); properties.addSubobject(classifyType(origEltType, substEltType, TC, Expansion)); + properties = + applyLifetimeAnnotation(elt->getLifetimeAnnotation(), properties); } + // Type-level annotations override inferred behavior. + properties = + applyLifetimeAnnotation(D->getLifetimeAnnotation(), properties); + return handleAggregateByProperties(enumType, properties); } From eb3f8002edac9a6e819e7a0f144ad4ceefb6b2a2 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Tue, 16 Aug 2022 13:30:10 -0700 Subject: [PATCH 287/491] [SIL] Added SILType::getLifetime. The function describes the lifetime that variables of that type have by default (unless otherwise annotated). This is done by looking at leaf nodes until one that is not eager move is found, at which point the lifetime is known to be lexical. Otherwise, the lifetime is eager move (i.e. if every leaf is eager move). --- include/swift/SIL/SILType.h | 12 +++++++++++- lib/SIL/IR/SILType.cpp | 9 +++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index 498149791e903..4b25d5835afef 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -20,9 +20,10 @@ #include "swift/AST/SILLayout.h" #include "swift/AST/Types.h" +#include "swift/SIL/Lifetime.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/ADT/Hashing.h" namespace swift { @@ -351,6 +352,15 @@ class SILType { return getASTType().hasReferenceSemantics(); } + /// The lifetime of values of this type (which are not otherwise annotated). + /// + /// Trivial types are ::None. + /// Non-trivial types are ::Lexical by default. + /// Non-trivial types which are annotated @_eagerMove are ::EagerMove. + /// Aggregates which consist entirely of ::EagerMove fields are ::EagerMove. + /// All other types are ::Lexical. + Lifetime getLifetime(const SILFunction &F) const; + /// Returns true if the referenced type is any sort of class-reference type, /// meaning anything with reference semantics that is not a function type. bool isAnyClassReferenceType() const { diff --git a/lib/SIL/IR/SILType.cpp b/lib/SIL/IR/SILType.cpp index ad2b693b70a04..b5d869303dd4e 100644 --- a/lib/SIL/IR/SILType.cpp +++ b/lib/SIL/IR/SILType.cpp @@ -161,6 +161,15 @@ bool SILType::isNoReturnFunction(SILModule &M, return false; } +Lifetime SILType::getLifetime(const SILFunction &F) const { + auto contextType = hasTypeParameter() ? F.mapTypeIntoContext(*this) : *this; + const auto &lowering = F.getTypeLowering(contextType); + auto properties = lowering.getRecursiveProperties(); + if (properties.isTrivial()) + return Lifetime::None; + return properties.isLexical() ? Lifetime::Lexical : Lifetime::EagerMove; +} + std::string SILType::getMangledName() const { Mangle::ASTMangler mangler; return mangler.mangleTypeWithoutPrefix(getRawASTType()); From 8d55e09bf30f7dff1b736fc49fa8b8bca6ea8c38 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Tue, 16 Aug 2022 13:59:49 -0700 Subject: [PATCH 288/491] [SSADestroyHoisting] Lifetimes alter arg hoisting. Arguments whose lifetimes are not lexical should be hoisted without respect to deinit barriers. On the other hand, inout arguments explicitly annotated @_lexical should respect deinit barriers. --- lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp b/lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp index f40612cf784d8..b7880f40233be 100644 --- a/lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp +++ b/lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp @@ -966,17 +966,20 @@ void SSADestroyHoisting::run() { remainingDestroyAddrs, deleter); } // Arguments enclose everything. - for (auto *arg : getFunction()->getArguments()) { + for (auto *uncastArg : getFunction()->getArguments()) { + auto *arg = cast(uncastArg); if (arg->getType().isAddress()) { - auto convention = cast(arg)->getArgumentConvention(); + auto convention = arg->getArgumentConvention(); // This is equivalent to writing // // convention == SILArgumentConvention::Indirect_Inout // // but communicates the rationale: in order to ignore deinit barriers, the // address must be exclusively accessed and be a modification. - bool ignoreDeinitBarriers = convention.isInoutConvention() && - convention.isExclusiveIndirectParameter(); + bool ignoredByConvention = convention.isInoutConvention() && + convention.isExclusiveIndirectParameter(); + auto lifetime = arg->getLifetime(); + bool ignoreDeinitBarriers = ignoredByConvention || lifetime.isEagerMove(); changed |= hoistDestroys(arg, ignoreDeinitBarriers, remainingDestroyAddrs, deleter); } From 3c78a0bb906f67b6a138461cc4747f0d0a8cfef4 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Tue, 16 Aug 2022 14:09:46 -0700 Subject: [PATCH 289/491] [SILGen] Only lexical types get lexical lifetimes. Only emit `begin_borrow [lexical]` and only mark `alloc_stack`s `[lexical]` when the variable in question's lifetime is lexical, not eager move. --- include/swift/SIL/SILFunction.h | 7 ++ lib/SILGen/ResultPlan.cpp | 7 +- lib/SILGen/SILGenApply.cpp | 7 +- lib/SILGen/SILGenBuilder.cpp | 17 ++-- lib/SILGen/SILGenBuilder.h | 5 +- lib/SILGen/SILGenDecl.cpp | 56 +++++++++---- lib/SILGen/SILGenProlog.cpp | 42 +++++++--- lib/SILGen/Scope.cpp | 5 +- .../SILOptimizer/activity_analysis.swift | 24 +++--- test/DebugInfo/debug_value_addr.swift | 2 +- ...pe-classification-non-trivial-silgen.swift | 14 ++-- test/SILGen/closures.swift | 28 +++---- test/SILGen/copy_lvalue_peepholes.swift | 9 +- test/SILGen/decls.swift | 40 +++------ test/SILGen/default_constructor.swift | 3 +- test/SILGen/dynamic_lookup.swift | 15 ++-- test/SILGen/enum_resilience.swift | 3 +- test/SILGen/errors.swift | 4 +- test/SILGen/existential_metatypes.swift | 3 +- test/SILGen/expressions.swift | 18 ++-- test/SILGen/functions.swift | 9 +- test/SILGen/guaranteed_closure_context.swift | 12 +-- test/SILGen/init_delegation_optional.swift | 14 +--- test/SILGen/init_ref_delegation.swift | 12 +-- test/SILGen/let_decls.swift | 7 +- test/SILGen/lifetime.swift | 24 ++---- test/SILGen/metatype_abstraction.swift | 6 +- test/SILGen/noimplicitcopy.swift | 12 +-- test/SILGen/observers.swift | 6 +- test/SILGen/optional-cast.swift | 4 +- test/SILGen/pointer_conversion.swift | 3 +- test/SILGen/properties.swift | 9 +- test/SILGen/properties_swift4.swift | 9 +- test/SILGen/properties_swift5.swift | 9 +- test/SILGen/property_wrapper_local.swift | 5 +- test/SILGen/property_wrappers.swift | 4 +- test/SILGen/protocol_optional.swift | 6 +- test/SILGen/statements.swift | 8 +- test/SILGen/switch_fallthrough.swift | 4 +- test/SILGen/switch_var.swift | 82 +++++-------------- test/SILGen/tuples.swift | 6 +- test/SILGen/types.swift | 3 +- test/SILGen/unsafevalue.swift | 8 +- test/SILOptimizer/access_marker_verify.swift | 11 +-- .../capturepromotion-wrong-lexicalscope.swift | 39 +++++---- 45 files changed, 261 insertions(+), 360 deletions(-) diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index a8aa8db8c157d..75bafcdff811b 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -1346,6 +1346,13 @@ class SILFunction // Miscellaneous //===--------------------------------------------------------------------===// + /// A value's lifetime, determined by looking at annotations on its decl and + /// the default lifetime for the type. + Lifetime getLifetime(VarDecl *decl, SILType ty) { + return ty.getLifetime(*this).getLifetimeForAnnotatedValue( + decl->getLifetimeAnnotation()); + } + /// verify - Run the IR verifier to make sure that the SILFunction follows /// invariants. void verify(bool SingleFunction = true) const; diff --git a/lib/SILGen/ResultPlan.cpp b/lib/SILGen/ResultPlan.cpp index 11f8d50867b01..6e862c49b341f 100644 --- a/lib/SILGen/ResultPlan.cpp +++ b/lib/SILGen/ResultPlan.cpp @@ -68,9 +68,10 @@ class IndirectOpenedSelfCleanup final : public Cleanup { assert(box && "buffer never emitted before activating cleanup?!"); auto theBox = box; if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) { - auto *bbi = cast(theBox); - SGF.B.createEndBorrow(loc, bbi); - theBox = bbi->getOperand(); + if (auto *bbi = cast(theBox)) { + SGF.B.createEndBorrow(loc, bbi); + theBox = bbi->getOperand(); + } } SGF.B.createDeallocBox(loc, theBox); } diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 40a10304b9bbd..e34eaab0ce105 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -3656,9 +3656,10 @@ class DeallocateUninitializedBox : public Cleanup { void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override { auto theBox = box; if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) { - auto *bbi = cast(theBox); - SGF.B.createEndBorrow(l, bbi); - theBox = bbi->getOperand(); + if (auto *bbi = cast(theBox)) { + SGF.B.createEndBorrow(l, bbi); + theBox = bbi->getOperand(); + } } SGF.B.createDeallocBox(l, theBox); } diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp index c7efd8cebe3d5..6b62139a49632 100644 --- a/lib/SILGen/SILGenBuilder.cpp +++ b/lib/SILGen/SILGenBuilder.cpp @@ -433,16 +433,17 @@ ManagedValue SILGenBuilder::createLoadCopy(SILLocation loc, ManagedValue v, return SGF.emitManagedRValueWithCleanup(result, lowering); } -static ManagedValue createInputFunctionArgument(SILGenBuilder &B, SILType type, - SILLocation loc, - ValueDecl *decl = nullptr, - bool isNoImplicitCopy = false) { +static ManagedValue createInputFunctionArgument( + SILGenBuilder &B, SILType type, SILLocation loc, ValueDecl *decl = nullptr, + bool isNoImplicitCopy = false, + LifetimeAnnotation lifetimeAnnotation = LifetimeAnnotation::None) { auto &SGF = B.getSILGenFunction(); SILFunction &F = B.getFunction(); assert((F.isBare() || decl) && "Function arguments of non-bare functions must have a decl"); auto *arg = F.begin()->createFunctionArgument(type, decl); arg->setNoImplicitCopy(isNoImplicitCopy); + arg->setLifetimeAnnotation(lifetimeAnnotation); switch (arg->getArgumentConvention()) { case SILArgumentConvention::Indirect_In_Guaranteed: case SILArgumentConvention::Direct_Guaranteed: @@ -476,11 +477,11 @@ static ManagedValue createInputFunctionArgument(SILGenBuilder &B, SILType type, llvm_unreachable("bad parameter convention"); } -ManagedValue SILGenBuilder::createInputFunctionArgument(SILType type, - ValueDecl *decl, - bool isNoImplicitCopy) { +ManagedValue SILGenBuilder::createInputFunctionArgument( + SILType type, ValueDecl *decl, bool isNoImplicitCopy, + LifetimeAnnotation lifetimeAnnotation) { return ::createInputFunctionArgument(*this, type, SILLocation(decl), decl, - isNoImplicitCopy); + isNoImplicitCopy, lifetimeAnnotation); } ManagedValue diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h index bdde2ada064c0..c777f1a01e025 100644 --- a/lib/SILGen/SILGenBuilder.h +++ b/lib/SILGen/SILGenBuilder.h @@ -226,8 +226,9 @@ class SILGenBuilder : public SILBuilder { /// Create a SILArgument for an input parameter. Asserts if used to create a /// function argument for an out parameter. - ManagedValue createInputFunctionArgument(SILType type, ValueDecl *decl, - bool isNoImplicitCopy = false); + ManagedValue createInputFunctionArgument( + SILType type, ValueDecl *decl, bool isNoImplicitCopy = false, + LifetimeAnnotation lifetimeAnnotation = LifetimeAnnotation::None); /// Create a SILArgument for an input parameter. Uses \p loc to create any /// copies necessary. Asserts if used to create a function argument for an out diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index af5f53cce751b..4f4de8dff6e86 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -299,9 +299,10 @@ class DeallocateUninitializedLocalVariable : public Cleanup { ForUnwind_t forUnwind) override { auto box = Box; if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) { - auto *bbi = cast(box); - SGF.B.createEndBorrow(l, bbi); - box = bbi->getOperand(); + if (auto *bbi = dyn_cast(box)) { + SGF.B.createEndBorrow(l, bbi); + box = bbi->getOperand(); + } } SGF.B.createDeallocBox(l, box); } @@ -367,7 +368,11 @@ class LocalVariableInitialization : public SingleBufferInitialization { Box = SGF.B.createMarkUninitialized(decl, Box, kind.getValue()); if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) { - Box = SGF.B.createBeginBorrow(decl, Box, /*isLexical=*/true); + auto loweredType = SGF.getTypeLowering(decl->getType()).getLoweredType(); + auto lifetime = SGF.F.getLifetime(decl, loweredType); + if (lifetime.isLexical()) { + Box = SGF.B.createBeginBorrow(decl, Box, /*isLexical=*/true); + } } Addr = SGF.B.createProjectBox(decl, Box, 0); @@ -489,11 +494,13 @@ class LetValueInitialization : public Initialization { } if (needsTemporaryBuffer) { - bool isLexical = + bool lexicalLifetimesEnabled = SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule()); + auto lifetime = SGF.F.getLifetime(vd, lowering->getLoweredType()); + auto isLexical = lexicalLifetimesEnabled && lifetime.isLexical(); address = SGF.emitTemporaryAllocation(vd, lowering->getLoweredType(), - false /*hasDynamicLifetime*/, isLexical); + /*hasDynamicLifetime=*/false, isLexical); if (isUninitialized) address = SGF.B.createMarkUninitializedVar(vd, address); DestroyCleanup = SGF.enterDormantTemporaryCleanup(address, *lowering); @@ -575,9 +582,14 @@ class LetValueInitialization : public Initialization { PrologueLoc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy); } - // Then if we don't have move only, just perform a lexical borrow. - if (!SGF.getASTContext().LangOpts.Features.count(Feature::MoveOnly)) - return SGF.B.createBeginBorrow(PrologueLoc, value, /*isLexical*/ true); + // Then if we don't have move only, just perform a lexical borrow if the + // lifetime is lexical. + if (!SGF.getASTContext().LangOpts.Features.count(Feature::MoveOnly)) { + if (SGF.F.getLifetime(vd, value->getType()).isLexical()) + return SGF.B.createBeginBorrow(PrologueLoc, value, /*isLexical*/ true); + else + return value; + } // Otherwise, we need to perform some additional processing. First, if we // have an owned moveonly value that had a cleanup, then create a move_value @@ -612,10 +624,14 @@ class LetValueInitialization : public Initialization { PrologueLoc, value, MarkMustCheckInst::CheckKind::NoImplicitCopy); } - // Otherwise, if we do not have a no implicit copy variable, just do a - // borrow lexical. This is the "normal path". - if (!vd->getAttrs().hasAttribute()) - return SGF.B.createBeginBorrow(PrologueLoc, value, /*isLexical*/ true); + // Otherwise, if we do not have a no implicit copy variable, just follow + // the "normal path": perform a lexical borrow if the lifetime is lexical. + if (!vd->getAttrs().hasAttribute()) { + if (SGF.F.getLifetime(vd, value->getType()).isLexical()) + return SGF.B.createBeginBorrow(PrologueLoc, value, /*isLexical*/ true); + else + return value; + } // If we have a no implicit copy lexical, emit the instruction stream so // that the move checker knows to check this variable. @@ -1830,10 +1846,13 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) { return; } - auto *bbi = cast(loc.box); - B.createEndBorrow(silLoc, bbi); - B.emitDestroyValueOperation(silLoc, bbi->getOperand()); + if (auto *bbi = dyn_cast(loc.box)) { + B.createEndBorrow(silLoc, bbi); + B.emitDestroyValueOperation(silLoc, bbi->getOperand()); + return; + } + B.emitDestroyValueOperation(silLoc, loc.box); return; } @@ -1855,6 +1874,11 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) { return; } + if (!F.getLifetime(vd, Val->getType()).isLexical()) { + B.emitDestroyValueOperation(silLoc, Val); + return; + } + // This handles any case where we copy + begin_borrow or copyable_to_moveonly // + begin_borrow. In either case we just need to end the lifetime of the // begin_borrow's operand. diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index 98c247e004f75..14e4cf7648fe3 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -58,12 +58,15 @@ class EmitBBArguments : public CanTypeVisitor ¶meters; bool isNoImplicitCopy; + LifetimeAnnotation lifetimeAnnotation; EmitBBArguments(SILGenFunction &sgf, SILBasicBlock *parent, SILLocation l, CanSILFunctionType fnTy, - ArrayRef ¶meters, bool isNoImplicitCopy) + ArrayRef ¶meters, bool isNoImplicitCopy, + LifetimeAnnotation lifetimeAnnotation) : SGF(sgf), parent(parent), loc(l), fnTy(fnTy), parameters(parameters), - isNoImplicitCopy(isNoImplicitCopy) {} + isNoImplicitCopy(isNoImplicitCopy), + lifetimeAnnotation(lifetimeAnnotation) {} ManagedValue visitType(CanType t, AbstractionPattern orig) { return visitType(t, orig, /*isInOut=*/false); @@ -90,7 +93,8 @@ class EmitBBArguments : public CanTypeVisitor(), isNoImplicitCopy); + paramType, loc.getAsASTNode(), isNoImplicitCopy, + lifetimeAnnotation); // This is a hack to deal with the fact that Self.Type comes in as a static // metatype, but we have to downcast it to a dynamic Self metatype to get @@ -239,13 +243,14 @@ struct ArgumentInitHelper { unsigned getNumArgs() const { return ArgNo; } ManagedValue makeArgument(Type ty, bool isInOut, bool isNoImplicitCopy, - SILBasicBlock *parent, SILLocation l) { + LifetimeAnnotation lifetime, SILBasicBlock *parent, + SILLocation l) { assert(ty && "no type?!"); // Create an RValue by emitting destructured arguments into a basic block. CanType canTy = ty->getCanonicalType(); EmitBBArguments argEmitter(SGF, parent, l, f.getLoweredFunctionType(), - parameters, isNoImplicitCopy); + parameters, isNoImplicitCopy, lifetime); // Note: inouts of tuples are not exploded, so we bypass visit(). AbstractionPattern origTy = OrigFnType @@ -266,17 +271,24 @@ struct ArgumentInitHelper { // Look for the following annotations on the function argument: // - @noImplicitCopy + // - @_eagerMove + // - @_lexical auto isNoImplicitCopy = pd->isNoImplicitCopy(); + auto lifetime = SGF.F.getLifetime(pd, value->getType()); // If we have a no implicit copy argument and the argument is trivial, // we need to use copyable to move only to convert it to its move only // form. if (!isNoImplicitCopy) { if (!value->getType().isMoveOnly()) { + // Follow the "normal path": perform a lexical borrow if the lifetime is + // lexical. if (value->getOwnershipKind() == OwnershipKind::Owned) { - value = - SILValue(SGF.B.createBeginBorrow(loc, value, /*isLexical*/ true)); - SGF.Cleanups.pushCleanup(value); + if (lifetime.isLexical()) { + value = SILValue( + SGF.B.createBeginBorrow(loc, value, /*isLexical*/ true)); + SGF.Cleanups.pushCleanup(value); + } } return value; } @@ -343,8 +355,8 @@ struct ArgumentInitHelper { SILLocation loc(pd); loc.markAsPrologue(); - ManagedValue argrv = - makeArgument(ty, pd->isInOut(), pd->isNoImplicitCopy(), parent, loc); + ManagedValue argrv = makeArgument(ty, pd->isInOut(), pd->isNoImplicitCopy(), + pd->getLifetimeAnnotation(), parent, loc); if (pd->isInOut()) { assert(argrv.getType().isAddress() && "expected inout to be address"); @@ -362,7 +374,10 @@ struct ArgumentInitHelper { } else { if (auto *allocStack = dyn_cast(value)) { allocStack->setArgNo(ArgNo); - allocStack->setIsLexical(); + if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes( + SGF.getModule()) && + SGF.F.getLifetime(pd, value->getType()).isLexical()) + allocStack->setIsLexical(); } else { SGF.B.createDebugValueAddr(loc, value, varinfo); } @@ -397,8 +412,9 @@ struct ArgumentInitHelper { Scope discardScope(SGF.Cleanups, CleanupLocation(PD)); // Manage the parameter. - auto argrv = makeArgument(type, PD->isInOut(), PD->isNoImplicitCopy(), - &*f.begin(), paramLoc); + auto argrv = + makeArgument(type, PD->isInOut(), PD->isNoImplicitCopy(), + PD->getLifetimeAnnotation(), &*f.begin(), paramLoc); // Emit debug information for the argument. SILLocation loc(PD); diff --git a/lib/SILGen/Scope.cpp b/lib/SILGen/Scope.cpp index 860ae9e835e93..294c4e16adfb2 100644 --- a/lib/SILGen/Scope.cpp +++ b/lib/SILGen/Scope.cpp @@ -60,7 +60,10 @@ static void lifetimeExtendAddressOnlyRValueSubValues( // TODO: Should these boxes that extend lifetimes for rvalue subobjects ever // be lexical? if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) { - box = SGF.B.createBeginBorrow(loc, box, /*isLexical=*/true); + if (v->getType().getLifetime(SGF.F).isLexical()) { + box = SGF.B.createBeginBorrow(loc, box, + /*isLexical=*/true); + } } SILValue addr = SGF.B.createProjectBox(loc, box, 0); SGF.B.createCopyAddr(loc, v, addr, IsTake, IsInitialization); diff --git a/test/AutoDiff/SILOptimizer/activity_analysis.swift b/test/AutoDiff/SILOptimizer/activity_analysis.swift index dfecc3f25757c..d6bf143e78fc3 100644 --- a/test/AutoDiff/SILOptimizer/activity_analysis.swift +++ b/test/AutoDiff/SILOptimizer/activity_analysis.swift @@ -18,7 +18,7 @@ func testNoDerivativeStructProjection(_ s: HasNoDerivativeProperty) -> Float { // CHECK-LABEL: [AD] Activity info for ${{.*}}testNoDerivativeStructProjection{{.*}} at parameter indices (0) and result indices (0): // CHECK: [ACTIVE] %0 = argument of bb0 : $HasNoDerivativeProperty -// CHECK: [ACTIVE] %2 = alloc_stack [lexical] $HasNoDerivativeProperty, var, name "tmp" +// CHECK: [ACTIVE] %2 = alloc_stack $HasNoDerivativeProperty, var, name "tmp" // CHECK: [ACTIVE] %4 = begin_access [read] [static] %2 : $*HasNoDerivativeProperty // CHECK: [ACTIVE] %5 = struct_element_addr %4 : $*HasNoDerivativeProperty, #HasNoDerivativeProperty.x // CHECK: [VARIED] %6 = load [trivial] %5 : $*Float @@ -76,7 +76,7 @@ func TF_781(_ x: Float, _ y: Float) -> Float { // CHECK-LABEL: [AD] Activity info for ${{.*}}TF_781{{.*}} at parameter indices (0) and result indices (0) // CHECK: [ACTIVE] %0 = argument of bb0 : $Float // CHECK: [USEFUL] %1 = argument of bb0 : $Float -// CHECK: [ACTIVE] %4 = alloc_stack [lexical] $Float, var, name "result" +// CHECK: [ACTIVE] %4 = alloc_stack $Float, var, name "result" // CHECK: [ACTIVE] %19 = begin_access [read] [static] %4 : $*Float // CHECK: [ACTIVE] %20 = load [trivial] %19 : $*Float // CHECK: [ACTIVE] %23 = apply %22(%20, %0, %18) : $@convention(method) (Float, Float, @thin Float.Type) -> Float @@ -103,9 +103,9 @@ func TF_954(_ x: Float) -> Float { // CHECK-LABEL: [AD] Activity info for ${{.*}}TF_954{{.*}} at parameter indices (0) and result indices (0) // CHECK: bb0: // CHECK: [ACTIVE] %0 = argument of bb0 : $Float -// CHECK: [ACTIVE] %2 = alloc_stack [lexical] $Float, var, name "outer" +// CHECK: [ACTIVE] %2 = alloc_stack $Float, var, name "outer" // CHECK: bb1: -// CHECK: [ACTIVE] %10 = alloc_stack [lexical] $Float, var, name "inner" +// CHECK: [ACTIVE] %10 = alloc_stack $Float, var, name "inner" // CHECK: [ACTIVE] %11 = begin_access [read] [static] %2 : $*Float // CHECK: [USEFUL] %14 = metatype $@thin Float.Type // CHECK: [ACTIVE] %15 = begin_access [read] [static] %10 : $*Float @@ -286,7 +286,7 @@ func testArrayUninitializedIntrinsicAddress(_ x: Float, _ y: Float) -> [Float] { // CHECK-LABEL: [AD] Activity info for ${{.*}}testArrayUninitializedIntrinsicAddress{{.*}} at parameter indices (0, 1) and result indices (0) // CHECK: [ACTIVE] %0 = argument of bb0 : $Float // CHECK: [ACTIVE] %1 = argument of bb0 : $Float -// CHECK: [ACTIVE] %4 = alloc_stack [lexical] $Float, var, name "result" +// CHECK: [ACTIVE] %4 = alloc_stack $Float, var, name "result" // CHECK: [ACTIVE] %7 = begin_access [read] [static] %4 : $*Float // CHECK: [ACTIVE] %8 = load [trivial] %7 : $*Float // CHECK: [NONE] // function_ref static Float.* infix(_:_:) @@ -440,7 +440,7 @@ func activeInoutArgMutatingMethod(_ x: Mut) -> Mut { // CHECK-LABEL: [AD] Activity info for ${{.*}}28activeInoutArgMutatingMethodyAA3MutVADF at parameter indices (0) and result indices (0) // CHECK: [ACTIVE] %0 = argument of bb0 : $Mut -// CHECK: [ACTIVE] %2 = alloc_stack [lexical] $Mut, var, name "result" +// CHECK: [ACTIVE] %2 = alloc_stack $Mut, var, name "result" // CHECK: [ACTIVE] %4 = begin_access [read] [static] %2 : $*Mut // CHECK: [ACTIVE] %5 = load [trivial] %4 : $*Mut // CHECK: [ACTIVE] %7 = begin_access [modify] [static] %2 : $*Mut @@ -459,7 +459,7 @@ func activeInoutArgMutatingMethodVar(_ nonactive: inout Mut, _ x: Mut) { // CHECK_LABEL: [AD] Activity info for ${{.*}}31activeInoutArgMutatingMethodVaryyAA3MutVz_ADtF at (parameters=(1) results=(0)) // CHECK: [ACTIVE] %0 = argument of bb0 : $*Mut // CHECK: [ACTIVE] %1 = argument of bb0 : $Mut -// CHECK: [ACTIVE] %4 = alloc_stack [lexical] $Mut, var, name "result" +// CHECK: [ACTIVE] %4 = alloc_stack $Mut, var, name "result" // CHECK: [ACTIVE] %5 = begin_access [read] [static] %0 : $*Mut // CHECK: [ACTIVE] %8 = begin_access [modify] [static] %4 : $*Mut // CHECK: [NONE] // function_ref Mut.mutatingMethod(_:) @@ -480,7 +480,7 @@ func activeInoutArgMutatingMethodTuple(_ nonactive: inout Mut, _ x: Mut) { // CHECK-LABEL: [AD] Activity info for ${{.*}}33activeInoutArgMutatingMethodTupleyyAA3MutVz_ADtF at parameter indices (1) and result indices (0) // CHECK: [ACTIVE] %0 = argument of bb0 : $*Mut // CHECK: [ACTIVE] %1 = argument of bb0 : $Mut -// CHECK: [ACTIVE] %4 = alloc_stack [lexical] $(Mut, Mut), var, name "result" +// CHECK: [ACTIVE] %4 = alloc_stack $(Mut, Mut), var, name "result" // CHECK: [ACTIVE] %5 = tuple_element_addr %4 : $*(Mut, Mut), 0 // CHECK: [ACTIVE] %6 = tuple_element_addr %4 : $*(Mut, Mut), 1 // CHECK: [ACTIVE] %7 = begin_access [read] [static] %0 : $*Mut @@ -507,7 +507,7 @@ func activeInoutArg(_ x: Float) -> Float { // CHECK-LABEL: [AD] Activity info for ${{.*}}activeInoutArg{{.*}} at parameter indices (0) and result indices (0) // CHECK: [ACTIVE] %0 = argument of bb0 : $Float -// CHECK: [ACTIVE] %2 = alloc_stack [lexical] $Float, var, name "result" +// CHECK: [ACTIVE] %2 = alloc_stack $Float, var, name "result" // CHECK: [ACTIVE] %5 = begin_access [modify] [static] %2 : $*Float // CHECK: [NONE] // function_ref static Float.+= infix(_:_:) // CHECK: [NONE] %7 = apply %6(%5, %0, %4) : $@convention(method) (@inout Float, Float, @thin Float.Type) -> () @@ -523,7 +523,7 @@ func activeInoutArgNonactiveInitialResult(_ x: Float) -> Float { // CHECK-LABEL: [AD] Activity info for ${{.*}}activeInoutArgNonactiveInitialResult{{.*}} at parameter indices (0) and result indices (0) // CHECK: [ACTIVE] %0 = argument of bb0 : $Float -// CHECK: [ACTIVE] %2 = alloc_stack [lexical] $Float, var, name "result" +// CHECK: [ACTIVE] %2 = alloc_stack $Float, var, name "result" // CHECK: [NONE] // function_ref Float.init(_builtinIntegerLiteral:) // CHECK: [USEFUL] %6 = apply %5(%3, %4) : $@convention(method) (Builtin.IntLiteral, @thin Float.Type) -> Float // CHECK: [USEFUL] %8 = metatype $@thin Float.Type @@ -584,7 +584,7 @@ func testAccessorCoroutines(_ x: HasCoroutineAccessors) -> HasCoroutineAccessors // CHECK-LABEL: [AD] Activity info for ${{.*}}testAccessorCoroutines{{.*}} at parameter indices (0) and result indices (0) // CHECK: [ACTIVE] %0 = argument of bb0 : $HasCoroutineAccessors -// CHECK: [ACTIVE] %2 = alloc_stack [lexical] $HasCoroutineAccessors, var, name "x" +// CHECK: [ACTIVE] %2 = alloc_stack $HasCoroutineAccessors, var, name "x" // CHECK: [ACTIVE] %4 = begin_access [read] [static] %2 : $*HasCoroutineAccessors // CHECK: [ACTIVE] %5 = load [trivial] %4 : $*HasCoroutineAccessors // CHECK: [NONE] // function_ref HasCoroutineAccessors.computed.read @@ -754,7 +754,7 @@ func testActiveOptional(_ x: Float) -> Float { // CHECK-LABEL: [AD] Activity info for ${{.*}}testActiveOptional{{.*}} at parameter indices (0) and result indices (0) // CHECK: bb0: // CHECK: [ACTIVE] %0 = argument of bb0 : $Float -// CHECK: [ACTIVE] %2 = alloc_stack [lexical] $Optional, var, name "maybe" +// CHECK: [ACTIVE] %2 = alloc_stack $Optional, var, name "maybe" // CHECK: [USEFUL] %3 = integer_literal $Builtin.IntLiteral, 10 // CHECK: [USEFUL] %4 = metatype $@thin Float.Type // CHECK: [NONE] // function_ref Float.init(_builtinIntegerLiteral:) diff --git a/test/DebugInfo/debug_value_addr.swift b/test/DebugInfo/debug_value_addr.swift index 707d42c7bbae7..bcd90ff9563ea 100644 --- a/test/DebugInfo/debug_value_addr.swift +++ b/test/DebugInfo/debug_value_addr.swift @@ -28,7 +28,7 @@ func use(_ t : T) {} // CHECK-SIL: sil hidden @$s16debug_value_addr11GenericSelfV1xACyxGx_tcfC : $@convention(method) (@in T, @thin GenericSelf.Type) -> GenericSelf { // CHECK-SIL: bb0(%0 : $*T, %1 : $@thin GenericSelf.Type): // -// CHECK-SIL-NEXT: alloc_stack [lexical] $GenericSelf, var, name "self", implicit, loc {{.*}} +// CHECK-SIL-NEXT: alloc_stack $GenericSelf, var, name "self", implicit, loc {{.*}} // CHECK-SIL-NEXT: debug_value %0 : $*T, let, name "x", argno 1, expr op_deref, loc {{.*}} struct GenericSelf { init(x: T) { diff --git a/test/Interop/Cxx/class/type-classification-non-trivial-silgen.swift b/test/Interop/Cxx/class/type-classification-non-trivial-silgen.swift index 412f7265ca27b..b72df37a6753a 100644 --- a/test/Interop/Cxx/class/type-classification-non-trivial-silgen.swift +++ b/test/Interop/Cxx/class/type-classification-non-trivial-silgen.swift @@ -5,7 +5,7 @@ import TypeClassification // Make sure that "StructWithDestructor" is marked as non-trivial by checking for a // "destroy_addr". // CHECK-LABEL: sil [ossa] @$s4main24testStructWithDestructoryyF -// CHECK: [[AS:%.*]] = alloc_stack [lexical] $StructWithDestructor +// CHECK: [[AS:%.*]] = alloc_stack $StructWithDestructor // CHECK: [[FN:%.*]] = function_ref @{{_ZN20StructWithDestructorC1Ev|\?\?0StructWithDestructor@@QEAA@XZ}} : $@convention(c) () -> @out StructWithDestructor // CHECK: apply [[FN]]([[AS]]) : $@convention(c) () -> @out StructWithDestructor // CHECK: destroy_addr [[AS]] @@ -20,7 +20,7 @@ public func testStructWithDestructor() { // Make sure that "HasMemberWithDestructor" is marked as non-trivial by checking // for a "destroy_addr". // CHECK-LABEL: sil [ossa] @$s4main33testStructWithSubobjectDestructoryyF : $@convention(thin) () -> () -// CHECK: [[AS:%.*]] = alloc_stack [lexical] $StructWithSubobjectDestructor +// CHECK: [[AS:%.*]] = alloc_stack $StructWithSubobjectDestructor // CHECK: [[FN:%.*]] = function_ref @{{_ZN29StructWithSubobjectDestructorC1Ev|\?\?0StructWithSubobjectDestructor@@QEAA@XZ}} : $@convention(c) () -> @out StructWithSubobjectDestructor // CHECK: apply [[FN]]([[AS]]) : $@convention(c) () -> @out StructWithSubobjectDestructor // CHECK: destroy_addr [[AS]] @@ -32,7 +32,7 @@ public func testStructWithSubobjectDestructor() { } // CHECK-LABEL: sil [ossa] @$s4main37testStructWithCopyConstructorAndValueSbyF -// CHECK: [[AS:%.*]] = alloc_stack [lexical] $StructWithCopyConstructorAndValue +// CHECK: [[AS:%.*]] = alloc_stack $StructWithCopyConstructorAndValue // CHECK: [[FN:%.*]] = function_ref @{{_ZN33StructWithCopyConstructorAndValueC1Ei|\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue // CHECK: apply [[FN]]([[AS]], %{{.*}}) : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue // CHECK: [[OBJ_VAL_ADDR:%.*]] = struct_element_addr [[AS]] : $*StructWithCopyConstructorAndValue, #StructWithCopyConstructorAndValue.value @@ -53,10 +53,10 @@ public func testStructWithCopyConstructorAndValue() -> Bool { } // CHECK-LABEL: sil [ossa] @$s4main46testStructWithSubobjectCopyConstructorAndValueSbyF : $@convention(thin) () -> Bool -// CHECK: [[MEMBER_0:%.*]] = alloc_stack [lexical] $StructWithCopyConstructorAndValue +// CHECK: [[MEMBER_0:%.*]] = alloc_stack $StructWithCopyConstructorAndValue // CHECK: [[MAKE_MEMBER_FN:%.*]] = function_ref @{{_ZN33StructWithCopyConstructorAndValueC1Ei|\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue // CHECK: apply [[MAKE_MEMBER_FN]]([[MEMBER_0]], %{{.*}}) : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue -// CHECK: [[AS:%.*]] = alloc_stack [lexical] $StructWithSubobjectCopyConstructorAndValue +// CHECK: [[AS:%.*]] = alloc_stack $StructWithSubobjectCopyConstructorAndValue // CHECK: [[META:%.*]] = metatype $@thin StructWithSubobjectCopyConstructorAndValue.Type // CHECK: [[MEMBER_1:%.*]] = alloc_stack $StructWithCopyConstructorAndValue // CHECK: copy_addr %0 to [initialization] [[MEMBER_1]] : $*StructWithCopyConstructorAndValue @@ -87,10 +87,10 @@ public func testStructWithSubobjectCopyConstructorAndValue() -> Bool { // testStructWithCopyConstructorAndSubobjectCopyConstructorAndValue() // CHECK-LABEL: sil [ossa] @$s4main041testStructWithCopyConstructorAndSubobjectefG5ValueSbyF : $@convention(thin) () -> Bool -// CHECK: [[MEMBER_0:%.*]] = alloc_stack [lexical] $StructWithCopyConstructorAndValue +// CHECK: [[MEMBER_0:%.*]] = alloc_stack $StructWithCopyConstructorAndValue // CHECK: [[CREATE_MEMBER_FN:%.*]] = function_ref @{{_ZN33StructWithCopyConstructorAndValueC1Ei|\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue // CHECK: apply [[CREATE_MEMBER_FN]]([[MEMBER_0]], %{{.*}}) : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue -// CHECK: [[AS:%.*]] = alloc_stack [lexical] $StructWithCopyConstructorAndSubobjectCopyConstructorAndValue +// CHECK: [[AS:%.*]] = alloc_stack $StructWithCopyConstructorAndSubobjectCopyConstructorAndValue // CHECK: [[MEMBER_1:%.*]] = alloc_stack $StructWithCopyConstructorAndValue // CHECK: copy_addr [[MEMBER_0]] to [initialization] [[MEMBER_1]] : $*StructWithCopyConstructorAndValue // CHECK: [[FN:%.*]] = function_ref @{{_ZN60StructWithCopyConstructorAndSubobjectCopyConstructorAndValueC1E33StructWithCopyConstructorAndValue|\?\?0StructWithCopyConstructorAndSubobjectCopyConstructorAndValue@@QEAA@UStructWithCopyConstructorAndValue@@@Z}} : $@convention(c) (@in StructWithCopyConstructorAndValue) -> @out StructWithCopyConstructorAndSubobjectCopyConstructorAndValue diff --git a/test/SILGen/closures.swift b/test/SILGen/closures.swift index 3ed7db255e6f9..63191ab45b344 100644 --- a/test/SILGen/closures.swift +++ b/test/SILGen/closures.swift @@ -33,10 +33,10 @@ func read_only_capture(_ x: Int) -> Int { var x = x // CHECK: bb0([[X:%[0-9]+]] : $Int): // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XBOX]] // SEMANTIC ARC TODO: This is incorrect. We need to do the project_box on the copy. - // CHECK: [[PROJECT:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[PROJECT:%.*]] = project_box [[XBOX]] // CHECK: store [[X]] to [trivial] [[PROJECT]] + // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [[XBOX]] func cap() -> Int { return x @@ -66,14 +66,13 @@ func write_to_capture(_ x: Int) -> Int { var x = x // CHECK: bb0([[X:%[0-9]+]] : $Int): // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XBOX]] - // CHECK: [[XBOX_PB:%[0-9]+]] = project_box [[XLIFETIME]] + // CHECK: [[XBOX_PB:%[0-9]+]] = project_box [[XBOX]] // CHECK: store [[X]] to [trivial] [[XBOX_PB]] // CHECK: [[X2BOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[X2LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[X2BOX]] - // CHECK: [[X2BOX_PB:%.*]] = project_box [[X2LIFETIME]] + // CHECK: [[X2BOX_PB:%.*]] = project_box [[X2BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[XBOX_PB]] : $*Int // CHECK: copy_addr [[ACCESS]] to [initialization] [[X2BOX_PB]] + // CHECK: [[X2LIFETIME:%[0-9]+]] = begin_borrow [[X2BOX]] // CHECK: mark_function_escape [[X2BOX_PB]] var x2 = x @@ -122,15 +121,14 @@ func capture_local_func(_ x: Int) -> () -> () -> Int { // CHECK: bb0([[ARG:%.*]] : $Int): var x = x // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XBOX]] - // CHECK: [[XBOX_PB:%[0-9]+]] = project_box [[XLIFETIME]] + // CHECK: [[XBOX_PB:%[0-9]+]] = project_box [[XBOX]] // CHECK: store [[ARG]] to [trivial] [[XBOX_PB]] func aleph() -> Int { return x } func beth() -> () -> Int { return aleph } // CHECK: [[BETH_REF:%.*]] = function_ref @[[BETH_NAME:\$s8closures18capture_local_funcySiycycSiF4bethL_SiycyF]] : $@convention(thin) (@guaranteed { var Int }) -> @owned @callee_guaranteed () -> Int - // CHECK: [[XBOX_COPY:%.*]] = copy_value [[XLIFETIME]] + // CHECK: [[XBOX_COPY:%.*]] = copy_value [[XBOX]] // SEMANTIC ARC TODO: This is incorrect. This should be a project_box from XBOX_COPY. // CHECK: mark_function_escape [[XBOX_PB]] // CHECK: [[BETH_CLOSURE:%[0-9]+]] = partial_apply [callee_guaranteed] [[BETH_REF]]([[XBOX_COPY]]) @@ -160,8 +158,7 @@ func anon_read_only_capture(_ x: Int) -> Int { var x = x // CHECK: bb0([[X:%[0-9]+]] : $Int): // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XBOX]] - // CHECK: [[PB:%[0-9]+]] = project_box [[XLIFETIME]] + // CHECK: [[PB:%[0-9]+]] = project_box [[XBOX]] return ({ x })() // -- func expression @@ -183,8 +180,7 @@ func small_closure_capture(_ x: Int) -> Int { var x = x // CHECK: bb0([[X:%[0-9]+]] : $Int): // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XBOX]] - // CHECK: [[PB:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[XBOX]] return { x }() // -- func expression @@ -206,12 +202,11 @@ func small_closure_capture(_ x: Int) -> Int { func small_closure_capture_with_argument(_ x: Int) -> (_ y: Int) -> Int { var x = x // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XBOX]] return { x + $0 } // -- func expression // CHECK: [[ANON:%[0-9]+]] = function_ref @[[CLOSURE_NAME:\$s8closures35small_closure_capture_with_argument.*]] : $@convention(thin) (Int, @guaranteed { var Int }) -> Int - // CHECK: [[XBOX_COPY:%.*]] = copy_value [[XLIFETIME]] + // CHECK: [[XBOX_COPY:%.*]] = copy_value [[XBOX]] // CHECK: [[ANON_CLOSURE_APP:%[0-9]+]] = partial_apply [callee_guaranteed] [[ANON]]([[XBOX_COPY]]) // -- return // CHECK: destroy_value [[XBOX]] @@ -244,8 +239,7 @@ func uncaptured_locals(_ x: Int) -> (Int, Int) { // -- locals without captures are stack-allocated // CHECK: bb0([[XARG:%[0-9]+]] : $Int): // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[PB:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[XADDR]] // CHECK: store [[XARG]] to [trivial] [[PB]] var y = zero diff --git a/test/SILGen/copy_lvalue_peepholes.swift b/test/SILGen/copy_lvalue_peepholes.swift index b11786bcd8d0a..ac8c66dfc9bd9 100644 --- a/test/SILGen/copy_lvalue_peepholes.swift +++ b/test/SILGen/copy_lvalue_peepholes.swift @@ -9,11 +9,9 @@ func getInt() -> Int { return zero } // CHECK-LABEL: sil hidden [ossa] @$s21copy_lvalue_peepholes014init_var_from_B0{{[_0-9a-zA-Z]*}}F // CHECK: [[X:%.*]] = alloc_box ${ var Builtin.Int64 } -// CHECK: [[XLIFETIME:%[^,]+]] = begin_borrow [lexical] [[X]] -// CHECK: [[PBX:%.*]] = project_box [[XLIFETIME]] +// CHECK: [[PBX:%.*]] = project_box [[X]] // CHECK: [[Y:%.*]] = alloc_box ${ var Builtin.Int64 } -// CHECK: [[YLIFETIME:%[^,]+]] = begin_borrow [lexical] [[Y]] -// CHECK: [[PBY:%.*]] = project_box [[YLIFETIME]] +// CHECK: [[PBY:%.*]] = project_box [[Y]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBX]] // CHECK: copy_addr [[READ]] to [initialization] [[PBY]] : $*Builtin.Int64 func init_var_from_lvalue(x: Int) { @@ -40,8 +38,7 @@ func init_var_from_computed_lvalue() { // CHECK-LABEL: sil hidden [ossa] @$s21copy_lvalue_peepholes021assign_computed_from_B0{{[_0-9a-zA-Z]*}}F // CHECK: [[Y:%.*]] = alloc_box -// CHECK: [[YLIFETIME:%[^,]+]] = begin_borrow [lexical] [[Y]] -// CHECK: [[PBY:%.*]] = project_box [[YLIFETIME]] +// CHECK: [[PBY:%.*]] = project_box [[Y]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBY]] // CHECK: [[Y_VAL:%.*]] = load [trivial] [[READ]] // CHECK: [[SETTER:%.*]] = function_ref @$s21copy_lvalue_peepholes8computedBi64_vs diff --git a/test/SILGen/decls.swift b/test/SILGen/decls.swift index ecd6e1dec8f83..20949bf1dc0a8 100644 --- a/test/SILGen/decls.swift +++ b/test/SILGen/decls.swift @@ -33,34 +33,27 @@ func tuple_patterns() { var (a, b) : (Int, Float) // CHECK: [[ABOX:%[0-9]+]] = alloc_box ${ var Int } // CHECK: [[AADDR:%[0-9]+]] = mark_uninitialized [var] [[ABOX]] - // CHECK: [[A_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[AADDR]] - // CHECK: [[PBA:%.*]] = project_box [[A_LIFETIME]] + // CHECK: [[PBA:%.*]] = project_box [[AADDR]] // CHECK: [[BBOX:%[0-9]+]] = alloc_box ${ var Float } // CHECK: [[BADDR:%[0-9]+]] = mark_uninitialized [var] [[BBOX]] - // CHECK: [[B_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BADDR]] - // CHECK: [[PBB:%.*]] = project_box [[B_LIFETIME]] + // CHECK: [[PBB:%.*]] = project_box [[BADDR]] var (c, d) = (a, b) // CHECK: [[CADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[C_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[CADDR]] - // CHECK: [[PBC:%.*]] = project_box [[C_LIFETIME]] + // CHECK: [[PBC:%.*]] = project_box [[CADDR]] // CHECK: [[DADDR:%[0-9]+]] = alloc_box ${ var Float } - // CHECK: [[D_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[DADDR]] - // CHECK: [[PBD:%.*]] = project_box [[D_LIFETIME]] + // CHECK: [[PBD:%.*]] = project_box [[DADDR]] // CHECK: [[READA:%.*]] = begin_access [read] [unknown] [[PBA]] : $*Int // CHECK: copy_addr [[READA]] to [initialization] [[PBC]] // CHECK: [[READB:%.*]] = begin_access [read] [unknown] [[PBB]] : $*Float // CHECK: copy_addr [[READB]] to [initialization] [[PBD]] // CHECK: [[EADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[E_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[EADDR]] - // CHECK: [[PBE:%.*]] = project_box [[E_LIFETIME]] + // CHECK: [[PBE:%.*]] = project_box [[EADDR]] // CHECK: [[FADDR:%[0-9]+]] = alloc_box ${ var Float } - // CHECK: [[F_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[FADDR]] - // CHECK: [[PBF:%.*]] = project_box [[F_LIFETIME]] + // CHECK: [[PBF:%.*]] = project_box [[FADDR]] // CHECK: [[GADDR:%[0-9]+]] = alloc_box ${ var () } // CHECK: [[HADDR:%[0-9]+]] = alloc_box ${ var Double } - // CHECK: [[H_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[HADDR]] - // CHECK: [[PBH:%.*]] = project_box [[H_LIFETIME]] + // CHECK: [[PBH:%.*]] = project_box [[HADDR]] // CHECK: [[EFGH:%[0-9]+]] = apply // CHECK: ([[E:%[0-9]+]], [[F:%[0-9]+]], [[H:%[0-9]+]]) = destructure_tuple // CHECK: store [[E]] to [trivial] [[PBE]] @@ -69,8 +62,7 @@ func tuple_patterns() { var (e,f,g,h) : (Int, Float, (), Double) = MRV() // CHECK: [[IADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[I_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[IADDR]] - // CHECK: [[PBI:%.*]] = project_box [[I_LIFETIME]] + // CHECK: [[PBI:%.*]] = project_box [[IADDR]] // CHECK-NOT: alloc_box ${ var Float } // CHECK: [[READA:%.*]] = begin_access [read] [unknown] [[PBA]] : $*Int // CHECK: copy_addr [[READA]] to [initialization] [[PBI]] @@ -80,11 +72,9 @@ func tuple_patterns() { var (i,_) = (a, b) // CHECK: [[JADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[J_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[JADDR]] - // CHECK: [[PBJ:%.*]] = project_box [[J_LIFETIME]] + // CHECK: [[PBJ:%.*]] = project_box [[JADDR]] // CHECK-NOT: alloc_box ${ var Float } // CHECK: [[KADDR:%[0-9]+]] = alloc_box ${ var () } - // CHECK: [[K_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[KADDR]] // CHECK-NOT: alloc_box ${ var Double } // CHECK: [[J_K_:%[0-9]+]] = apply // CHECK: ([[J:%[0-9]+]], [[K:%[0-9]+]], {{%[0-9]+}}) = destructure_tuple @@ -95,12 +85,10 @@ func tuple_patterns() { // CHECK-LABEL: sil hidden [ossa] @$s5decls16simple_arguments{{[_0-9a-zA-Z]*}}F // CHECK: bb0(%0 : $Int, %1 : $Int): // CHECK: [[X:%[0-9]+]] = alloc_box ${ var Int } -// CHECK: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X]] -// CHECK-NEXT: [[PBX:%.*]] = project_box [[X_LIFETIME]] +// CHECK-NEXT: [[PBX:%.*]] = project_box [[X]] // CHECK-NEXT: store %0 to [trivial] [[PBX]] // CHECK-NEXT: [[Y:%[0-9]+]] = alloc_box ${ var Int } -// CHECK-NEXT: [[Y_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[Y]] -// CHECK-NEXT: [[PBY:%[0-9]+]] = project_box [[Y_LIFETIME]] +// CHECK-NEXT: [[PBY:%[0-9]+]] = project_box [[Y]] // CHECK-NEXT: store %1 to [trivial] [[PBY]] func simple_arguments(x: Int, y: Int) -> Int { var x = x @@ -118,8 +106,7 @@ func tuple_argument(x: (Int, Float, ())) { // CHECK-LABEL: sil hidden [ossa] @$s5decls14inout_argument{{[_0-9a-zA-Z]*}}F // CHECK: bb0(%0 : $*Int, %1 : $Int): // CHECK: [[X_LOCAL:%[0-9]+]] = alloc_box ${ var Int } -// CHECK: [[X_LOCAL_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X_LOCAL]] -// CHECK: [[PBX:%.*]] = project_box [[X_LOCAL_LIFETIME]] +// CHECK: [[PBX:%.*]] = project_box [[X_LOCAL]] func inout_argument(x: inout Int, y: Int) { var y = y x = y @@ -143,8 +130,7 @@ func store_to_global(x: Int) { var x = x global = x // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[PBX:%.*]] = project_box [[X_LIFETIME]] + // CHECK: [[PBX:%.*]] = project_box [[XADDR]] // CHECK: [[ACCESSOR:%[0-9]+]] = function_ref @$s5decls6globalSivau // CHECK: [[PTR:%[0-9]+]] = apply [[ACCESSOR]]() // CHECK: [[ADDR:%[0-9]+]] = pointer_to_address [[PTR]] diff --git a/test/SILGen/default_constructor.swift b/test/SILGen/default_constructor.swift index 45406338697a4..c0707c10a0379 100644 --- a/test/SILGen/default_constructor.swift +++ b/test/SILGen/default_constructor.swift @@ -30,8 +30,7 @@ struct D { // CHECK-LABEL: sil hidden [ossa] @$s19default_constructor1DV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin D.Type) -> D // CHECK: [[THISBOX:%[0-9]+]] = alloc_box ${ var D } // CHECK: [[THIS:%[0-9]+]] = mark_uninit -// CHECK: [[THISLIFE:%[^,]+]] = begin_borrow [lexical] [[THIS]] -// CHECK: [[PB_THIS:%.*]] = project_box [[THISLIFE]] +// CHECK: [[PB_THIS:%.*]] = project_box [[THIS]] // CHECK: [[IADDR:%[0-9]+]] = struct_element_addr [[PB_THIS]] : $*D, #D.i // CHECK: [[JADDR:%[0-9]+]] = struct_element_addr [[PB_THIS]] : $*D, #D.j // CHECK: [[INIT:%[0-9]+]] = function_ref @$s19default_constructor1DV1iSivpfi diff --git a/test/SILGen/dynamic_lookup.swift b/test/SILGen/dynamic_lookup.swift index a7b307adc877c..b8902ca8c4e74 100644 --- a/test/SILGen/dynamic_lookup.swift +++ b/test/SILGen/dynamic_lookup.swift @@ -175,8 +175,7 @@ func opt_to_property(_ obj: AnyObject) { // CHECK: [[OBJ_COPY:%.*]] = copy_value [[OBJ]] // CHECK: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject // CHECK: [[INT_BOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[INT_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INT_BOX]] - // CHECK: project_box [[INT_LIFETIME]] + // CHECK: project_box [[INT_BOX]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]] // CHECK: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject // CHECK: [[RAWOBJ_SELF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject @@ -206,8 +205,7 @@ func opt_to_property(_ obj: AnyObject) { // GUARANTEED: [[OBJ_COPY:%.*]] = copy_value [[OBJ]] // GUARANTEED: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject // GUARANTEED: [[INT_BOX:%[0-9]+]] = alloc_box ${ var Int } - // GUARANTEED: [[INT_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INT_BOX]] - // GUARANTEED: project_box [[INT_LIFETIME]] + // GUARANTEED: project_box [[INT_BOX]] // GUARANTEED: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]] // GUARANTEED: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject // GUARANTEED: [[RAWOBJ_SELF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject @@ -237,8 +235,7 @@ func direct_to_subscript(_ obj: AnyObject, i: Int) { // CHECK: [[OBJ_COPY:%.*]] = copy_value [[OBJ]] // CHECK: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject // CHECK: [[I_BOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[I_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[I_BOX]] - // CHECK: [[PBI:%.*]] = project_box [[I_LIFETIME]] + // CHECK: [[PBI:%.*]] = project_box [[I_BOX]] // CHECK: store [[I]] to [trivial] [[PBI]] : $*Int // CHECK: alloc_box ${ var Int } // CHECK: project_box @@ -273,8 +270,7 @@ func direct_to_subscript(_ obj: AnyObject, i: Int) { // GUARANTEED: [[OBJ_COPY:%.*]] = copy_value [[OBJ]] // GUARANTEED: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject // GUARANTEED: [[I_BOX:%[0-9]+]] = alloc_box ${ var Int } - // GUARANTEED: [[I_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[I_BOX]] - // GUARANTEED: [[PBI:%.*]] = project_box [[I_LIFETIME]] + // GUARANTEED: [[PBI:%.*]] = project_box [[I_BOX]] // GUARANTEED: store [[I]] to [trivial] [[PBI]] : $*Int // GUARANTEED: alloc_box ${ var Int } // GUARANTEED: project_box @@ -309,8 +305,7 @@ func opt_to_subscript(_ obj: AnyObject, i: Int) { // CHECK: [[OBJ_COPY:%.*]] = copy_value [[OBJ]] // CHECK: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject // CHECK: [[I_BOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[I_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[I_BOX]] - // CHECK: [[PBI:%.*]] = project_box [[I_LIFETIME]] + // CHECK: [[PBI:%.*]] = project_box [[I_BOX]] // CHECK: store [[I]] to [trivial] [[PBI]] : $*Int // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]] // CHECK: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject diff --git a/test/SILGen/enum_resilience.swift b/test/SILGen/enum_resilience.swift index 40b98fdcd0f7e..8de6952f2c5fc 100644 --- a/test/SILGen/enum_resilience.swift +++ b/test/SILGen/enum_resilience.swift @@ -119,8 +119,7 @@ public enum MyResilientEnum { // CHECK-LABEL: sil hidden [ossa] @$s15enum_resilience15MyResilientEnumOACycfC : $@convention(method) (@thin MyResilientEnum.Type) -> @out MyResilientEnum // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var MyResilientEnum }, var, name "self" // CHECK: [[SELF_TMP:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]] : ${ var MyResilientEnum } - // CHECK: [[SELF_LIFETIME:%.*]] = begin_borrow [lexical] [[SELF_TMP]] - // CHECK: [[SELF_ADDR:%.*]] = project_box [[SELF_LIFETIME]] : ${ var MyResilientEnum }, 0 + // CHECK: [[SELF_ADDR:%.*]] = project_box [[SELF_TMP]] : ${ var MyResilientEnum }, 0 // CHECK: [[NEW_SELF:%.*]] = enum $MyResilientEnum, #MyResilientEnum.loki!enumelt // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[SELF_ADDR]] : $*MyResilientEnum // CHECK: assign [[NEW_SELF]] to [[ACCESS]] : $*MyResilientEnum diff --git a/test/SILGen/errors.swift b/test/SILGen/errors.swift index 95219eefc4cde..03d4167c14272 100644 --- a/test/SILGen/errors.swift +++ b/test/SILGen/errors.swift @@ -980,12 +980,10 @@ func testOptionalTryNeverFails() { // CHECK-LABEL: sil hidden [ossa] @$s6errors28testOptionalTryNeverFailsVaryyF // CHECK: bb0: // CHECK-NEXT: [[BOX:%.+]] = alloc_box ${ var Optional<()> } -// CHECK-NEXT: [[LIFETIME:%.+]] = begin_borrow [lexical] [[BOX]] -// CHECK-NEXT: [[PB:%.*]] = project_box [[LIFETIME]] +// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]] // CHECK-NEXT: [[VALUE:%.+]] = tuple () // CHECK-NEXT: [[ENUM:%.+]] = enum $Optional<()>, #Optional.some!enumelt, [[VALUE]] // CHECK-NEXT: store [[ENUM]] to [trivial] [[PB]] : -// CHECK-NEXT: end_borrow [[LIFETIME]] // CHECK-NEXT: destroy_value [[BOX]] : ${ var Optional<()> } // CHECK-NEXT: [[VOID:%.+]] = tuple () // CHECK-NEXT: return [[VOID]] : $() diff --git a/test/SILGen/existential_metatypes.swift b/test/SILGen/existential_metatypes.swift index cfa7ffdad71a4..d625b42d10e7c 100644 --- a/test/SILGen/existential_metatypes.swift +++ b/test/SILGen/existential_metatypes.swift @@ -65,8 +65,7 @@ func existentialMetatypeUpcast2(_ x: (P & Q).Type) -> P.Type { // CHECK-LABEL: sil hidden [ossa] @$s21existential_metatypes0A19MetatypeVarPropertyAA5ValueVyF : $@convention(thin) () -> Value func existentialMetatypeVarProperty() -> Value { // CHECK: [[BOX:%.*]] = alloc_box ${ var @thick any P.Type } - // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK: [[ADDR:%.*]] = project_box [[BOX_LIFETIME]] : ${ var @thick any P.Type }, 0 + // CHECK: [[ADDR:%.*]] = project_box [[BOX]] : ${ var @thick any P.Type }, 0 // CHECK: [[T0:%.*]] = metatype $@thick S.Type // CHECK: [[T1:%.*]] = init_existential_metatype [[T0]] // CHECK: store [[T1]] to [trivial] [[ADDR]] : diff --git a/test/SILGen/expressions.swift b/test/SILGen/expressions.swift index 7e12d05ac7845..5b556e8062259 100644 --- a/test/SILGen/expressions.swift +++ b/test/SILGen/expressions.swift @@ -392,8 +392,7 @@ func tuple() -> (Int, Float) { return (1, 1.0) } func tuple_element(_ x: (Int, Float)) { var x = x // CHECK: [[XADDR:%.*]] = alloc_box ${ var (Int, Float) } - // CHECK: [[XLIFETIME:%.*]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[PB:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[XADDR]] int(x.0) // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] @@ -428,20 +427,15 @@ func if_expr(_ a: Bool, b: Bool, x: Int, y: Int, z: Int) -> Int { var z = z // CHECK: bb0({{.*}}): // CHECK: [[AB:%[0-9]+]] = alloc_box ${ var Bool } - // CHECK: [[AL:%[0-9]+]] = begin_borrow [lexical] [[AB]] - // CHECK: [[PBA:%.*]] = project_box [[AL]] + // CHECK: [[PBA:%.*]] = project_box [[AB]] // CHECK: [[BB:%[0-9]+]] = alloc_box ${ var Bool } - // CHECK: [[BL:%[0-9]+]] = begin_borrow [lexical] [[BB]] - // CHECK: [[PBB:%.*]] = project_box [[BL]] + // CHECK: [[PBB:%.*]] = project_box [[BB]] // CHECK: [[XB:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XL:%[0-9]+]] = begin_borrow [lexical] [[XB]] - // CHECK: [[PBX:%.*]] = project_box [[XL]] + // CHECK: [[PBX:%.*]] = project_box [[XB]] // CHECK: [[YB:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[YL:%[0-9]+]] = begin_borrow [lexical] [[YB]] - // CHECK: [[PBY:%.*]] = project_box [[YL]] + // CHECK: [[PBY:%.*]] = project_box [[YB]] // CHECK: [[ZB:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[ZL:%[0-9]+]] = begin_borrow [lexical] [[ZB]] - // CHECK: [[PBZ:%.*]] = project_box [[ZL]] + // CHECK: [[PBZ:%.*]] = project_box [[ZB]] return a ? x diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift index b5c2dc3c74fd9..de1b4c58c9b66 100644 --- a/test/SILGen/functions.swift +++ b/test/SILGen/functions.swift @@ -103,14 +103,11 @@ func calls(_ i:Int, j:Int, k:Int) { var k = k // CHECK: bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $Builtin.Int64): // CHECK: [[IBOX:%[0-9]+]] = alloc_box ${ var Builtin.Int64 } - // CHECK: [[ILIFETIME:%[^,]+]] = begin_borrow [lexical] [[IBOX]] - // CHECK: [[IADDR:%.*]] = project_box [[ILIFETIME]] + // CHECK: [[IADDR:%.*]] = project_box [[IBOX]] // CHECK: [[JBOX:%[0-9]+]] = alloc_box ${ var Builtin.Int64 } - // CHECK: [[JLIFETIME:%[^,]+]] = begin_borrow [lexical] [[JBOX]] - // CHECK: [[JADDR:%.*]] = project_box [[JLIFETIME]] + // CHECK: [[JADDR:%.*]] = project_box [[JBOX]] // CHECK: [[KBOX:%[0-9]+]] = alloc_box ${ var Builtin.Int64 } - // CHECK: [[KLIFETIME:%[^,]+]] = begin_borrow [lexical] [[KBOX]] - // CHECK: [[KADDR:%.*]] = project_box [[KLIFETIME]] + // CHECK: [[KADDR:%.*]] = project_box [[KBOX]] // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]] // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]] diff --git a/test/SILGen/guaranteed_closure_context.swift b/test/SILGen/guaranteed_closure_context.swift index 54e3aca506db0..4f6eadac38d4d 100644 --- a/test/SILGen/guaranteed_closure_context.swift +++ b/test/SILGen/guaranteed_closure_context.swift @@ -11,7 +11,6 @@ struct S {} // CHECK-LABEL: sil hidden [ossa] @$s26guaranteed_closure_context0A9_capturesyyF func guaranteed_captures() { // CHECK: [[MUTABLE_TRIVIAL_BOX:%.*]] = alloc_box ${ var S } - // CHECK: [[MUTABLE_TRIVIAL_BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[MUTABLE_TRIVIAL_BOX]] var mutableTrivial = S() // CHECK: [[MUTABLE_RETAINABLE_BOX:%.*]] = alloc_box ${ var C } // CHECK: [[MUTABLE_RETAINABLE_BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[MUTABLE_RETAINABLE_BOX]] @@ -33,23 +32,24 @@ func guaranteed_captures() { immutableTrivial, immutableRetainable, immutableAddressOnly)) } - // CHECK-NOT: copy_value [[MUTABLE_TRIVIAL_BOX_LIFETIME]] + // CHECK-NOT: copy_value [[MUTABLE_TRIVIAL_BOX]] // CHECK-NOT: copy_value [[MUTABLE_RETAINABLE_BOX_LIFETIME]] // CHECK-NOT: copy_value [[MUTABLE_ADDRESS_ONLY_BOX_LIFETIME]] // CHECK-NOT: copy_value [[IMMUTABLE_RETAINABLE]] + // CHECK: [[MUTABLE_TRIVIAL_BOX_BORROW:%[^,]+]] = begin_borrow [[MUTABLE_TRIVIAL_BOX]] // CHECK: [[FN:%.*]] = function_ref [[FN_NAME:@\$s26guaranteed_closure_context0A9_capturesyyF17captureEverythingL_yyF]] - // CHECK: apply [[FN]]([[MUTABLE_TRIVIAL_BOX_LIFETIME]], [[MUTABLE_RETAINABLE_BOX_LIFETIME]], [[MUTABLE_ADDRESS_ONLY_BOX_LIFETIME]], [[IMMUTABLE_TRIVIAL]], [[B_IMMUTABLE_RETAINABLE]], [[IMMUTABLE_ADDRESS_ONLY]]) + // CHECK: apply [[FN]]([[MUTABLE_TRIVIAL_BOX_BORROW]], [[MUTABLE_RETAINABLE_BOX_LIFETIME]], [[MUTABLE_ADDRESS_ONLY_BOX_LIFETIME]], [[IMMUTABLE_TRIVIAL]], [[B_IMMUTABLE_RETAINABLE]], [[IMMUTABLE_ADDRESS_ONLY]]) captureEverything() - // CHECK-NOT: copy_value [[MUTABLE_TRIVIAL_BOX_LIFETIME]] + // CHECK-NOT: copy_value [[MUTABLE_TRIVIAL_BOX]] // CHECK-NOT: copy_value [[MUTABLE_RETAINABLE_BOX_LIFETIME]] // CHECK-NOT: copy_value [[MUTABLE_ADDRESS_ONLY_BOX_LIFETIME]] // CHECK-NOT: copy_value [[IMMUTABLE_RETAINABLE]] // -- partial_apply still takes ownership of its arguments. // CHECK: [[FN:%.*]] = function_ref [[FN_NAME]] - // CHECK: [[MUTABLE_TRIVIAL_BOX_COPY:%.*]] = copy_value [[MUTABLE_TRIVIAL_BOX_LIFETIME]] + // CHECK: [[MUTABLE_TRIVIAL_BOX_COPY:%.*]] = copy_value [[MUTABLE_TRIVIAL_BOX]] // CHECK: [[MUTABLE_RETAINABLE_BOX_COPY:%.*]] = copy_value [[MUTABLE_RETAINABLE_BOX_LIFETIME]] // CHECK: [[MUTABLE_ADDRESS_ONLY_BOX_COPY:%.*]] = copy_value [[MUTABLE_ADDRESS_ONLY_BOX_LIFETIME]] // CHECK: [[IMMUTABLE_RETAINABLE_COPY:%.*]] = copy_value [[B_IMMUTABLE_RETAINABLE]] @@ -58,7 +58,7 @@ func guaranteed_captures() { // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE]] // CHECK: apply {{.*}}[[CONVERT]] - // CHECK-NOT: copy_value [[MUTABLE_TRIVIAL_BOX_LIFETIME]] + // CHECK-NOT: copy_value [[MUTABLE_TRIVIAL_BOX]] // CHECK-NOT: copy_value [[MUTABLE_RETAINABLE_BOX_LIFETIME]] // CHECK-NOT: copy_value [[MUTABLE_ADDRESS_ONLY_BOX_LIFETIME]] // CHECK-NOT: copy_value [[IMMUTABLE_RETAINABLE]] diff --git a/test/SILGen/init_delegation_optional.swift b/test/SILGen/init_delegation_optional.swift index b499494605e5d..0bd6ed44ae22c 100644 --- a/test/SILGen/init_delegation_optional.swift +++ b/test/SILGen/init_delegation_optional.swift @@ -365,8 +365,7 @@ extension Optional where Wrapped == Optional { // CHECK: bb0([[SELF_META:%[0-9]+]] : $@thin Optional>.Type): // CHECK-NEXT: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var Optional> }, var // CHECK-NEXT: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]] - // CHECK-NEXT: [[SELF_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[MARKED_SELF_BOX]] - // CHECK-NEXT: [[PB:%[0-9]+]] = project_box [[SELF_LIFETIME]] + // CHECK-NEXT: [[PB:%[0-9]+]] = project_box [[MARKED_SELF_BOX]] // CHECK: [[RESULT_ADDR:%[0-9]+]] = alloc_stack $Optional> // CHECK: [[DELEG_INIT:%[0-9]+]] = function_ref @$sSq24init_delegation_optionalE12nonFailable1xSgyt_tcfC // CHECK-NEXT: apply [[DELEG_INIT]]([[RESULT_ADDR]], [[SELF_META]]) @@ -375,7 +374,6 @@ extension Optional where Wrapped == Optional { // CHECK-NEXT: dealloc_stack [[RESULT_ADDR]] // CHECK-NEXT: [[RESULT:%[0-9]+]] = load [trivial] [[PB]] // CHECK-NEXT: [[INJECT_INTO_OPT:%[0-9]+]] = enum $Optional>>, #Optional.some!enumelt, [[RESULT]] - // CHECK-NEXT: end_borrow [[SELF_LIFETIME]] // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: br bb2([[INJECT_INTO_OPT]] : $Optional>>) // @@ -393,8 +391,7 @@ extension Optional where Wrapped == Optional { // CHECK: bb0([[SELF_META:%[0-9]+]] : $@thin Optional>.Type): // CHECK-NEXT: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var Optional> }, var // CHECK-NEXT: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]] - // CHECK-NEXT: [[SELF_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[MARKED_SELF_BOX]] - // CHECK-NEXT: [[PB:%[0-9]+]] = project_box [[SELF_LIFETIME]] + // CHECK-NEXT: [[PB:%[0-9]+]] = project_box [[MARKED_SELF_BOX]] // CHECK: [[DELEG_INIT:%[0-9]+]] = function_ref @$sSq24init_delegation_optionalSbSgRszlE13SpecFailable1ABSgSgyt_tcfC // CHECK-NEXT: [[OPT_RESULT:%[0-9]+]] = apply [[DELEG_INIT]]([[SELF_META]]) // CHECK: [[SELECT:%[0-9]+]] = select_enum [[OPT_RESULT]] @@ -408,12 +405,10 @@ extension Optional where Wrapped == Optional { // CHECK-NEXT: assign [[RESULT]] to [[PB]] // CHECK-NEXT: [[RESULT:%[0-9]+]] = load [trivial] [[PB]] // CHECK-NEXT: [[INJECT_INTO_OPT:%[0-9]+]] = enum $Optional>>, #Optional.some!enumelt, [[RESULT]] - // CHECK-NEXT: end_borrow [[SELF_LIFETIME]] // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: br bb4([[INJECT_INTO_OPT]] : $Optional>>) // // CHECK: bb3: - // CHECK-NEXT: end_borrow [[SELF_LIFETIME]] // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: [[NIL:%[0-9]+]] = enum $Optional>>, #Optional.none!enumelt // CHECK-NEXT: br bb4([[NIL]] : $Optional>>) @@ -433,8 +428,7 @@ extension Optional where Wrapped == Optional { // CHECK: bb0([[SELF_META:%[0-9]+]] : $@thin Optional>.Type): // CHECK-NEXT: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var Optional> }, var // CHECK-NEXT: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]] - // CHECK-NEXT: [[SELF_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[MARKED_SELF_BOX]] - // CHECK-NEXT: [[PB:%[0-9]+]] = project_box [[SELF_LIFETIME]] + // CHECK-NEXT: [[PB:%[0-9]+]] = project_box [[MARKED_SELF_BOX]] // CHECK: [[DELEG_INIT:%[0-9]+]] = function_ref @$sSq24init_delegation_optionalSbSgRszlE21SpecFailableAndThrowsABSgSgyt_tKcfC // CHECK-NEXT: try_apply [[DELEG_INIT]]([[SELF_META]]) : {{.*}}, normal [[SUCC_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] // @@ -464,12 +458,10 @@ extension Optional where Wrapped == Optional { // CHECK-NEXT: assign [[RESULT]] to [[PB]] // CHECK-NEXT: [[RESULT:%[0-9]+]] = load [trivial] [[PB]] // CHECK-NEXT: [[INJECT_INTO_OPT:%[0-9]+]] = enum $Optional>>, #Optional.some!enumelt, [[RESULT]] - // CHECK-NEXT: end_borrow [[SELF_LIFETIME]] // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: br bb9([[INJECT_INTO_OPT]] : $Optional>>) // // CHECK: bb8: - // CHECK-NEXT: end_borrow [[SELF_LIFETIME]] // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] // CHECK-NEXT: [[NIL:%[0-9]+]] = enum $Optional>>, #Optional.none!enumelt // CHECK-NEXT: br bb9([[NIL]] : $Optional>>) diff --git a/test/SILGen/init_ref_delegation.swift b/test/SILGen/init_ref_delegation.swift index 9315b88edd23f..e7ade4d3f76c9 100644 --- a/test/SILGen/init_ref_delegation.swift +++ b/test/SILGen/init_ref_delegation.swift @@ -9,8 +9,7 @@ struct S { // CHECK: bb0([[SELF_META:%[0-9]+]] : $@thin S.Type): // CHECK-NEXT: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var S } // CHECK-NEXT: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]] - // CHECK-NEXT: [[SELF_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[MARKED_SELF_BOX]] - // CHECK-NEXT: [[PB:%.*]] = project_box [[SELF_LIFETIME]] + // CHECK-NEXT: [[PB:%.*]] = project_box [[MARKED_SELF_BOX]] // CHECK-NEXT: [[X_META:%[0-9]+]] = metatype $@thin X.Type // CHECK: [[X_CTOR:%[0-9]+]] = function_ref @$s19init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X @@ -20,7 +19,6 @@ struct S { self.init(x: X()) // CHECK-NEXT: assign [[REPLACEMENT_SELF]] to [[PB]] : $*S // CHECK-NEXT: [[SELF_BOX1:%[0-9]+]] = load [trivial] [[PB]] : $*S - // CHECK-NEXT: end_borrow [[SELF_LIFETIME]] // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]] : ${ var S } // CHECK-NEXT: return [[SELF_BOX1]] : $S } @@ -38,8 +36,7 @@ enum E { // CHECK: bb0([[E_META:%[0-9]+]] : $@thin E.Type): // CHECK: [[E_BOX:%[0-9]+]] = alloc_box ${ var E } // CHECK: [[MARKED_E_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[E_BOX]] - // CHECK: [[E_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[MARKED_E_BOX]] - // CHECK: [[PB:%.*]] = project_box [[E_LIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[MARKED_E_BOX]] // CHECK: [[X_META:%[0-9]+]] = metatype $@thin X.Type // CHECK: [[E_DELEG_INIT:%[0-9]+]] = function_ref @$s19init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X @@ -49,7 +46,6 @@ enum E { // CHECK: assign [[S:%[0-9]+]] to [[PB]] : $*E // CHECK: [[E_BOX1:%[0-9]+]] = load [trivial] [[PB]] : $*E self.init(x: X()) - // CHECK: end_borrow [[E_LIFETIME]] // CHECK: destroy_value [[MARKED_E_BOX]] : ${ var E } // CHECK: return [[E_BOX1:%[0-9]+]] : $E } @@ -64,8 +60,7 @@ struct S2 { // CHECK: bb0([[S2_META:%[0-9]+]] : $@thin S2.Type): // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var S2 } // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]] - // CHECK: [[SELF_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[MARKED_SELF_BOX]] - // CHECK: [[PB:%.*]] = project_box [[SELF_LIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[MARKED_SELF_BOX]] // CHECK: [[X_META:%[0-9]+]] = metatype $@thin X.Type // CHECK: [[X_INIT:%[0-9]+]] = function_ref @$s19init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X @@ -78,7 +73,6 @@ struct S2 { // CHECK: assign [[SELF_BOX1]] to [[PB]] : $*S2 // CHECK: [[SELF_BOX4:%[0-9]+]] = load [trivial] [[PB]] : $*S2 self.init(t: X()) - // CHECK: end_borrow [[SELF_LIFETIME]] // CHECK: destroy_value [[MARKED_SELF_BOX]] : ${ var S2 } // CHECK: return [[SELF_BOX4]] : $S2 } diff --git a/test/SILGen/let_decls.swift b/test/SILGen/let_decls.swift index 3ee79c4f6f923..12b1acdfca9e2 100644 --- a/test/SILGen/let_decls.swift +++ b/test/SILGen/let_decls.swift @@ -233,8 +233,7 @@ struct WeirdPropertyTest { func test_weird_property(_ v : WeirdPropertyTest, i : Int) -> Int { var v = v // CHECK: [[VBOX:%[0-9]+]] = alloc_box ${ var WeirdPropertyTest } - // CHECK: [[VLIFETIME:%[^,]+]] = begin_borrow [lexical] [[VBOX]] - // CHECK: [[PB:%.*]] = project_box [[VLIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[VBOX]] // CHECK: store %0 to [trivial] [[PB]] // The setter isn't mutating, so we need to load the box. @@ -466,13 +465,11 @@ struct LetPropertyStruct { // CHECK-LABEL: sil hidden [ossa] @{{.*}}testLetPropertyAccessOnLValueBase // CHECK: bb0(%0 : $LetPropertyStruct): // CHECK: [[ABOX:%[0-9]+]] = alloc_box ${ var LetPropertyStruct } -// CHECK: [[ALIFETIME:%[^,]+]] = begin_borrow [lexical] [[ABOX]] -// CHECK: [[A:%[0-9]+]] = project_box [[ALIFETIME]] +// CHECK: [[A:%[0-9]+]] = project_box [[ABOX]] // CHECK: store %0 to [trivial] [[A]] : $*LetPropertyStruct // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[A]] // CHECK: [[STRUCT:%[0-9]+]] = load [trivial] [[READ]] : $*LetPropertyStruct // CHECK: [[PROP:%[0-9]+]] = struct_extract [[STRUCT]] : $LetPropertyStruct, #LetPropertyStruct.lp -// CHECK: end_borrow [[ALIFETIME]] // CHECK: destroy_value [[ABOX]] : ${ var LetPropertyStruct } // CHECK: return [[PROP]] : $Int func testLetPropertyAccessOnLValueBase(_ a : LetPropertyStruct) -> Int { diff --git a/test/SILGen/lifetime.swift b/test/SILGen/lifetime.swift index fd2524c8343b0..08cd4bd1c489f 100644 --- a/test/SILGen/lifetime.swift +++ b/test/SILGen/lifetime.swift @@ -18,8 +18,6 @@ func local_valtype() { var b: Val // CHECK: [[B:%[0-9]+]] = alloc_box ${ var Val } // CHECK: [[MARKED_B:%.*]] = mark_uninitialized [var] [[B]] - // CHECK: [[MARKED_B_LIFETIME:%.*]] = begin_borrow [lexical] [[MARKED_B]] - // CHECK: end_borrow [[MARKED_B_LIFETIME]] // CHECK: destroy_value [[MARKED_B]] // CHECK: return } @@ -37,7 +35,6 @@ func local_valtype_branch(_ a: Bool) { var x:Int // CHECK: [[X:%[0-9]+]] = alloc_box ${ var Int } // CHECK: [[MARKED_X:%.*]] = mark_uninitialized [var] [[X]] - // CHECK: [[MARKED_X_LIFETIME:%.*]] = begin_borrow [lexical] [[MARKED_B]] if a { return } // CHECK: cond_br @@ -62,12 +59,10 @@ func local_valtype_branch(_ a: Bool) { var y:Int // CHECK: [[Y:%[0-9]+]] = alloc_box ${ var Int } // CHECK: [[MARKED_Y:%.*]] = mark_uninitialized [var] [[Y]] - // CHECK: [[MARKED_Y_LIFETIME:%.*]] = begin_borrow [lexical] [[MARKED_Y]] if a { break } // CHECK: cond_br // CHECK: {{bb.*:}} - // CHECK: end_borrow [[MARKED_Y_LIFETIME]] // CHECK: destroy_value [[MARKED_Y]] // CHECK-NOT: destroy_value [[MARKED_X]] // CHECK-NOT: destroy_value [[A]] @@ -84,7 +79,6 @@ func local_valtype_branch(_ a: Bool) { var z:Int // CHECK: [[Z:%[0-9]+]] = alloc_box ${ var Int } // CHECK: [[MARKED_Z:%.*]] = mark_uninitialized [var] [[Z]] - // CHECK: [[MARKED_Z_LIFETIME:%.*]] = begin_borrow [lexical] [[MARKED_Z]] if a { break } // CHECK: cond_br @@ -361,12 +355,10 @@ func logical_lvalue_lifetime(_ r: RefWithProp, _ i: Int, _ v: Val) { // CHECK: [[R_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[RADDR]] // CHECK: [[PR:%[0-9]+]] = project_box [[R_LIFETIME]] // CHECK: [[IADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[I_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[IADDR]] - // CHECK: [[PI:%[0-9]+]] = project_box [[I_LIFETIME]] + // CHECK: [[PI:%[0-9]+]] = project_box [[IADDR]] // CHECK: store %1 to [trivial] [[PI]] // CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var Val } - // CHECK: [[V_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[VADDR]] - // CHECK: [[PV:%[0-9]+]] = project_box [[V_LIFETIME]] + // CHECK: [[PV:%[0-9]+]] = project_box [[VADDR]] // -- Reference types need to be copy_valued as property method args. r.int_prop = i @@ -480,8 +472,7 @@ class Foo { // -- Then we create a box that we will use to perform a copy_addr into #Foo.x a bit later. // CHECK: [[CHIADDR:%[0-9]+]] = alloc_box ${ var Int }, var, name "chi" - // CHECK: [[CHI_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[CHIADDR]] - // CHECK: [[PCHI:%[0-9]+]] = project_box [[CHI_LIFETIME]] + // CHECK: [[PCHI:%[0-9]+]] = project_box [[CHIADDR]] // CHECK: store [[CHI]] to [trivial] [[PCHI]] // -- Then we initialize #Foo.z @@ -666,8 +657,7 @@ struct Bar { // CHECK: bb0([[METATYPE:%[0-9]+]] : $@thin Bar.Type): // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var Bar } // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [rootself] [[SELF_BOX]] - // CHECK: [[SELF_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[MARKED_SELF_BOX]] - // CHECK: [[PB_BOX:%.*]] = project_box [[SELF_LIFETIME]] + // CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]] x = bar() // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_BOX]] @@ -732,12 +722,10 @@ class D : B { // CHECK: [[PB_BOX:%[0-9]+]] = project_box [[SELF_LIFETIME]] // CHECK: store [[SELF]] to [init] [[PB_BOX]] // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[PX:%[0-9]+]] = project_box [[XLIFETIME]] + // CHECK: [[PX:%[0-9]+]] = project_box [[XADDR]] // CHECK: store [[X]] to [trivial] [[PX]] // CHECK: [[YADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[Y_LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[YADDR]] - // CHECK: [[PY:%[0-9]+]] = project_box [[Y_LIFETIME]] + // CHECK: [[PY:%[0-9]+]] = project_box [[YADDR]] // CHECK: store [[Y]] to [trivial] [[PY]] super.init(y: y) diff --git a/test/SILGen/metatype_abstraction.swift b/test/SILGen/metatype_abstraction.swift index bb45fd1d8b8d2..4ef4ffcc93e91 100644 --- a/test/SILGen/metatype_abstraction.swift +++ b/test/SILGen/metatype_abstraction.swift @@ -57,8 +57,7 @@ func genericMetatypeFromGenericMetatype(_ x: GenericMetatype)-> T.Type { } // CHECK-LABEL: sil hidden [ossa] @$ss026dynamicMetatypeFromGenericB0ys1CCms0dB0VyACGF // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var GenericMetatype } -// CHECK: [[XBOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[XBOX]] -// CHECK: [[PX:%[0-9]+]] = project_box [[XBOX_LIFETIME]] +// CHECK: [[PX:%[0-9]+]] = project_box [[XBOX]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PX]] : $*GenericMetatype // CHECK: [[ADDR:%.*]] = struct_element_addr [[READ]] : $*GenericMetatype, #GenericMetatype.value // CHECK: [[META:%.*]] = load [trivial] [[ADDR]] : $*@thick C.Type @@ -95,8 +94,7 @@ func dynamicMetatypeToGeneric(_ x: C.Type) { } // CHECK-LABEL: sil hidden [ossa] @$ss024dynamicMetatypeToGenericB0yys1CCmF // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var @thick C.Type } -// CHECK: [[XBOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[XBOX]] -// CHECK: [[PX:%[0-9]+]] = project_box [[XBOX_LIFETIME]] +// CHECK: [[PX:%[0-9]+]] = project_box [[XBOX]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PX]] : $*@thick C.Type // CHECK: [[META:%.*]] = load [trivial] [[READ]] : $*@thick C.Type // CHECK: apply {{%.*}}([[META]]) : $@convention(thin) <Ï„_0_0> (@thick Ï„_0_0.Type) -> () diff --git a/test/SILGen/noimplicitcopy.swift b/test/SILGen/noimplicitcopy.swift index b760394d9afcd..fc20a4eb5a6d9 100644 --- a/test/SILGen/noimplicitcopy.swift +++ b/test/SILGen/noimplicitcopy.swift @@ -91,8 +91,7 @@ func printIntArg(@_noImplicitCopy _ x: Int) { // CHECK: apply [[FUNC]]([[VALUE]]) // // CHECK: [[Y_BOX:%.*]] = alloc_box ${ var Int } -// CHECK: [[Y_BOX_BORROWED:%.*]] = begin_borrow [lexical] [[Y_BOX]] -// CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX_BORROWED]] +// CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX]] // CHECK: [[Y_BOX_PROJECT_ACCESS:%.*]] = begin_access [read] [unknown] [[Y_BOX_PROJECT]] // CHECK: [[Y_VALUE:%.*]] = load [trivial] [[Y_BOX_PROJECT_ACCESS]] // CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy11printIntArgyySiF : $@convention(thin) (Int) -> () @@ -141,8 +140,7 @@ func printIntOwnedArg(@_noImplicitCopy _ x: __owned Int) { // CHECK: apply [[FUNC]]([[VALUE]]) // // CHECK: [[Y_BOX:%.*]] = alloc_box ${ var Int } -// CHECK: [[Y_BOX_BORROWED:%.*]] = begin_borrow [lexical] [[Y_BOX]] -// CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX_BORROWED]] +// CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX]] // CHECK: [[Y_BOX_PROJECT_ACCESS:%.*]] = begin_access [read] [unknown] [[Y_BOX_PROJECT]] // CHECK: [[Y_VALUE:%.*]] = load [trivial] [[Y_BOX_PROJECT_ACCESS]] // CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy16printIntOwnedArgyySinF : $@convention(thin) (Int) -> () @@ -191,8 +189,7 @@ func printIntArgThrows(@_noImplicitCopy _ x: Int) throws { // CHECK: try_apply [[FUNC]]([[VALUE]]) // // CHECK: [[Y_BOX:%.*]] = alloc_box ${ var Int } -// CHECK: [[Y_BOX_BORROWED:%.*]] = begin_borrow [lexical] [[Y_BOX]] -// CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX_BORROWED]] +// CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX]] // CHECK: [[Y_BOX_PROJECT_ACCESS:%.*]] = begin_access [read] [unknown] [[Y_BOX_PROJECT]] // CHECK: [[Y_VALUE:%.*]] = load [trivial] [[Y_BOX_PROJECT_ACCESS]] // CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy17printIntArgThrowsyySiKF : $@convention(thin) (Int) -> @error any Error @@ -232,8 +229,7 @@ func printIntOwnedArgThrows(@_noImplicitCopy _ x: __owned Int) throws { // CHECK: try_apply [[FUNC]]([[VALUE]]) // // CHECK: [[Y_BOX:%.*]] = alloc_box ${ var Int } -// CHECK: [[Y_BOX_BORROWED:%.*]] = begin_borrow [lexical] [[Y_BOX]] -// CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX_BORROWED]] +// CHECK: [[Y_BOX_PROJECT:%.*]] = project_box [[Y_BOX]] // CHECK: [[Y_BOX_PROJECT_ACCESS:%.*]] = begin_access [read] [unknown] [[Y_BOX_PROJECT]] // CHECK: [[Y_VALUE:%.*]] = load [trivial] [[Y_BOX_PROJECT_ACCESS]] // CHECK: [[FUNC:%.*]] = function_ref @$s14noimplicitcopy22printIntOwnedArgThrowsyySinKF : $@convention(thin) (Int) -> @error any Error diff --git a/test/SILGen/observers.swift b/test/SILGen/observers.swift index f0b774dc94d68..4c4fe2df25d20 100644 --- a/test/SILGen/observers.swift +++ b/test/SILGen/observers.swift @@ -18,8 +18,7 @@ public struct DidSetWillSetTests { // CHECK: bb0(%0 : $Int, %1 : $@thin DidSetWillSetTests.Type): // CHECK: [[SELF:%.*]] = mark_uninitialized [rootself] - // CHECK: [[SELF_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[SELF]] - // CHECK: [[PB_SELF:%.*]] = project_box [[SELF_LIFETIME]] + // CHECK: [[PB_SELF:%.*]] = project_box [[SELF]] // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_SELF]] // CHECK: [[P1:%.*]] = struct_element_addr [[WRITE]] : $*DidSetWillSetTests, #DidSetWillSetTests.a // CHECK-NEXT: assign %0 to [[P1]] @@ -318,8 +317,7 @@ func local_observing_property(_ arg: Int) { // Alloc and initialize the property to the argument value. // CHECK: bb0([[ARG:%[0-9]+]] : $Int) // CHECK: [[BOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK: [[PB:%.*]] = project_box [[LIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[BOX]] // CHECK: store [[ARG]] to [trivial] [[PB]] } diff --git a/test/SILGen/optional-cast.swift b/test/SILGen/optional-cast.swift index aecb329d3f628..560ba142bbf68 100644 --- a/test/SILGen/optional-cast.swift +++ b/test/SILGen/optional-cast.swift @@ -201,10 +201,8 @@ public struct TestAddressOnlyStruct { // CHECK: bb0(%0 : $Optional): // CHECK-NEXT: debug_value %0 : $Optional, let, name "a" // CHECK-NEXT: [[X:%.*]] = alloc_box ${ var Optional }, var, name "x" -// CHECK-NEXT: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X]] -// CHECK-NEXT: [[PB:%.*]] = project_box [[X_LIFETIME]] +// CHECK-NEXT: [[PB:%.*]] = project_box [[X]] // CHECK-NEXT: store %0 to [trivial] [[PB]] : $*Optional -// CHECK-NEXT: end_borrow [[X_LIFETIME]] // CHECK-NEXT: destroy_value [[X]] : ${ var Optional } func testContextualInitOfNonAddrOnlyType(_ a : Int?) { var x: Int! = a diff --git a/test/SILGen/pointer_conversion.swift b/test/SILGen/pointer_conversion.swift index d60f11386b5e8..1302caa286ea2 100644 --- a/test/SILGen/pointer_conversion.swift +++ b/test/SILGen/pointer_conversion.swift @@ -174,8 +174,7 @@ func stringToPointer(_ s: String) { func inoutToPointer() { var int = 0 // CHECK: [[INT:%.*]] = alloc_box ${ var Int } - // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[INT]] - // CHECK: [[PB:%.*]] = project_box [[LIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[INT]] takesMutablePointer(&int) // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]] diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift index 836105dc7c66b..d862ed2dd1acf 100644 --- a/test/SILGen/properties.swift +++ b/test/SILGen/properties.swift @@ -13,8 +13,7 @@ func physical_tuple_lvalue(_ c: Int) { var x : (Int, Int) // CHECK: [[BOX:%[0-9]+]] = alloc_box ${ var (Int, Int) } // CHECK: [[MARKED_BOX:%[0-9]+]] = mark_uninitialized [var] [[BOX]] - // CHECK: [[LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[MARKED_BOX]] - // CHECK: [[XADDR:%.*]] = project_box [[LIFETIME]] + // CHECK: [[XADDR:%.*]] = project_box [[MARKED_BOX]] x.1 = c // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[XADDR]] // CHECK: [[X_1:%[0-9]+]] = tuple_element_addr [[WRITE]] : {{.*}}, 1 @@ -344,8 +343,7 @@ func inout_arg(_ x: inout Int) {} func physical_inout(_ x: Int) { var x = x // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[LIFETIME:%[0-9]+]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[PB:%.*]] = project_box [[LIFETIME]] + // CHECK: [[PB:%.*]] = project_box [[XADDR]] inout_arg(&x) // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] // CHECK: [[INOUT_ARG:%[0-9]+]] = function_ref @$s10properties9inout_arg{{[_0-9a-zA-Z]*}}F @@ -781,8 +779,7 @@ struct MutatingGetterStruct { // CHECK-LABEL: sil hidden [ossa] @$s10properties20MutatingGetterStructV4test // CHECK: [[X:%.*]] = alloc_box ${ var MutatingGetterStruct }, var, name "x" - // CHECK: [[LIFETIME:%.*]] = begin_borrow [lexical] [[X]] - // CHECK-NEXT: [[PB:%.*]] = project_box [[LIFETIME]] + // CHECK-NEXT: [[PB:%.*]] = project_box [[X]] // CHECK: store {{.*}} to [trivial] [[PB]] : $*MutatingGetterStruct // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] // CHECK: apply {{%.*}}([[WRITE]]) : $@convention(method) (@inout MutatingGetterStruct) -> Int diff --git a/test/SILGen/properties_swift4.swift b/test/SILGen/properties_swift4.swift index 0a509670dd598..6a759ec316ef0 100644 --- a/test/SILGen/properties_swift4.swift +++ b/test/SILGen/properties_swift4.swift @@ -33,8 +33,7 @@ struct DidSetWillSetTests: ForceAccessors { var unrelatedValue = DidSetWillSetTests.defaultValue // CHECK: [[BOX:%.*]] = alloc_box ${ var DidSetWillSetTests }, var, name "unrelatedValue" - // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX_LIFETIME]] : ${ var DidSetWillSetTests }, 0 + // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX]] : ${ var DidSetWillSetTests }, 0 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin DidSetWillSetTests.Type // CHECK-NEXT: // function_ref static properties.DidSetWillSetTests.defaultValue.getter : properties.DidSetWillSetTests // CHECK-NEXT: [[DEFAULTVALUE_FN:%.*]] = function_ref @$s10properties{{[_0-9a-zA-Z]*}}vgZ : $@convention(method) (@thin DidSetWillSetTests.Type) -> DidSetWillSetTests @@ -76,8 +75,7 @@ struct DidSetWillSetTests: ForceAccessors { var unrelatedValue = DidSetWillSetTests.defaultValue // CHECK: [[BOX:%.*]] = alloc_box ${ var DidSetWillSetTests }, var, name "unrelatedValue" - // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX_LIFETIME]] : ${ var DidSetWillSetTests }, 0 + // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX]] : ${ var DidSetWillSetTests }, 0 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin DidSetWillSetTests.Type // CHECK-NEXT: // function_ref static properties.DidSetWillSetTests.defaultValue.getter : properties.DidSetWillSetTests // CHECK-NEXT: [[DEFAULTVALUE_FN:%.*]] = function_ref @$s10properties{{[_0-9a-zA-Z]*}}vgZ : $@convention(method) (@thin DidSetWillSetTests.Type) -> DidSetWillSetTests @@ -104,8 +102,7 @@ struct DidSetWillSetTests: ForceAccessors { var other = self // CHECK: [[BOX:%.*]] = alloc_box ${ var DidSetWillSetTests }, var, name "other" - // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX_LIFETIME]] : ${ var DidSetWillSetTests }, 0 + // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX]] : ${ var DidSetWillSetTests }, 0 // CHECK-NEXT: [[READ_SELF:%.*]] = begin_access [read] [unknown] %0 : $*DidSetWillSetTests // CHECK-NEXT: copy_addr [[READ_SELF]] to [initialization] [[BOXADDR]] : $*DidSetWillSetTests // CHECK-NEXT: end_access [[READ_SELF]] : $*DidSetWillSetTests diff --git a/test/SILGen/properties_swift5.swift b/test/SILGen/properties_swift5.swift index 89a27774832cd..07bb50aca4ff4 100644 --- a/test/SILGen/properties_swift5.swift +++ b/test/SILGen/properties_swift5.swift @@ -33,8 +33,7 @@ struct DidSetWillSetTests: ForceAccessors { var unrelatedValue = DidSetWillSetTests.defaultValue // CHECK: [[BOX:%.*]] = alloc_box ${ var DidSetWillSetTests }, var, name "unrelatedValue" - // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[LIFETIME]] : ${ var DidSetWillSetTests }, 0 + // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX]] : ${ var DidSetWillSetTests }, 0 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin DidSetWillSetTests.Type // CHECK-NEXT: // function_ref static properties.DidSetWillSetTests.defaultValue.getter : properties.DidSetWillSetTests // CHECK-NEXT: [[DEFAULTVALUE_FN:%.*]] = function_ref @$s10properties{{[_0-9a-zA-Z]*}}vgZ : $@convention(method) (@thin DidSetWillSetTests.Type) -> DidSetWillSetTests @@ -78,8 +77,7 @@ struct DidSetWillSetTests: ForceAccessors { var unrelatedValue = DidSetWillSetTests.defaultValue // CHECK: [[BOX:%.*]] = alloc_box ${ var DidSetWillSetTests }, var, name "unrelatedValue" - // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[LIFETIME]] : ${ var DidSetWillSetTests }, 0 + // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX]] : ${ var DidSetWillSetTests }, 0 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin DidSetWillSetTests.Type // CHECK-NEXT: // function_ref static properties.DidSetWillSetTests.defaultValue.getter : properties.DidSetWillSetTests // CHECK-NEXT: [[DEFAULTVALUE_FN:%.*]] = function_ref @$s10properties{{[_0-9a-zA-Z]*}}vgZ : $@convention(method) (@thin DidSetWillSetTests.Type) -> DidSetWillSetTests @@ -108,8 +106,7 @@ struct DidSetWillSetTests: ForceAccessors { var other = self // CHECK: [[BOX:%.*]] = alloc_box ${ var DidSetWillSetTests }, var, name "other" - // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[LIFETIME]] : ${ var DidSetWillSetTests }, 0 + // CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX]] : ${ var DidSetWillSetTests }, 0 // CHECK-NEXT: [[READ_SELF:%.*]] = begin_access [read] [unknown] %0 : $*DidSetWillSetTests // CHECK-NEXT: copy_addr [[READ_SELF]] to [initialization] [[BOXADDR]] : $*DidSetWillSetTests // CHECK-NEXT: end_access [[READ_SELF]] : $*DidSetWillSetTests diff --git a/test/SILGen/property_wrapper_local.swift b/test/SILGen/property_wrapper_local.swift index a2faca1ce3f1d..21dc1a7d1b5c1 100644 --- a/test/SILGen/property_wrapper_local.swift +++ b/test/SILGen/property_wrapper_local.swift @@ -17,14 +17,13 @@ func testLocalWrapper() { @Wrapper var value: Int // CHECK: [[A:%.*]] = alloc_box ${ var Wrapper }, var, name "_value" // CHECK: [[W:%.*]] = mark_uninitialized [var] [[A]] : ${ var Wrapper } - // CHECK: [[L:%[^,]+]] = begin_borrow [lexical] [[W]] - // CHECK: [[P:%.*]] = project_box [[L]] : ${ var Wrapper } + // CHECK: [[P:%.*]] = project_box [[W]] : ${ var Wrapper } value = 10 // CHECK: [[I:%.*]] = function_ref @$s22property_wrapper_local16testLocalWrapperyyF5valueL_SivpfP : $@convention(thin) (Int) -> Wrapper // CHECK: [[IPA:%.*]] = partial_apply [callee_guaranteed] [[I]]() : $@convention(thin) (Int) -> Wrapper // CHECK: [[S:%.*]] = function_ref @$s22property_wrapper_local16testLocalWrapperyyF5valueL_Sivs : $@convention(thin) (Int, @guaranteed { var Wrapper }) -> () - // CHECK-NEXT: [[C:%.*]] = copy_value [[L]] : ${ var Wrapper } + // CHECK-NEXT: [[C:%.*]] = copy_value [[W]] : ${ var Wrapper } // CHECK-NOT: mark_function_escape // CHECK-NEXT: [[SPA:%.*]] = partial_apply [callee_guaranteed] [[S]]([[C]]) : $@convention(thin) (Int, @guaranteed { var Wrapper }) -> () // CHECK-NEXT: assign_by_wrapper {{%.*}} : $Int to [[P]] : $*Wrapper, init [[IPA]] : $@callee_guaranteed (Int) -> Wrapper, set [[SPA]] : $@callee_guaranteed (Int) -> () diff --git a/test/SILGen/property_wrappers.swift b/test/SILGen/property_wrappers.swift index b901d267ea7b8..459913918815c 100644 --- a/test/SILGen/property_wrappers.swift +++ b/test/SILGen/property_wrappers.swift @@ -972,14 +972,12 @@ struct SR_15940_C { // CHECK: bb0(%0 : $SR_15940_C): // CHECK-NEXT: debug_value %0 : $SR_15940_C, let, name "self", argno 1, implicit // CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ var SR_15940Foo }, var, name "_b" -// CHECK-NEXT: [[LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] : ${ var SR_15940Foo } -// CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[LIFETIME]] : ${ var SR_15940Foo }, 0 +// CHECK-NEXT: [[BOXADDR:%.*]] = project_box [[BOX]] : ${ var SR_15940Foo }, 0 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin SR_15940Foo.Type // CHECK-NEXT: // function_ref SR_15940Foo.init() // CHECK-NEXT: [[DEFAULTVALUE_FN:%.*]] = function_ref @$s17property_wrappers11SR_15940FooVACycfC : $@convention(method) (@thin SR_15940Foo.Type) -> SR_15940Foo // CHECK-NEXT: [[DEFAULTRESULT:%.*]] = apply [[DEFAULTVALUE_FN]]([[METATYPE]]) : $@convention(method) (@thin SR_15940Foo.Type) -> SR_15940Foo // CHECK-NEXT: store [[DEFAULTRESULT]] to [trivial] [[BOXADDR]] : $*SR_15940Foo -// CHECK-NEXT: end_borrow [[LIFETIME]] : ${ var SR_15940Foo } // CHECK-NEXT: destroy_value [[BOX]] : ${ var SR_15940Foo } // CHECK-NEXT: [[TUPLE:%.*]] = tuple () // CHECK-NEXT: return [[TUPLE]] : $() diff --git a/test/SILGen/protocol_optional.swift b/test/SILGen/protocol_optional.swift index 8714cac6d19f9..8b7d4f56202a7 100644 --- a/test/SILGen/protocol_optional.swift +++ b/test/SILGen/protocol_optional.swift @@ -103,8 +103,7 @@ func optionalPropertyGeneric(t t : T) { // CHECK: [[T_COPY:%.*]] = copy_value [[T]] // CHECK: store [[T_COPY]] to [init] [[PT]] : $*T // CHECK: [[OPT_BOX:%[0-9]+]] = alloc_box ${ var Optional } - // CHECK: [[OPT_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[OPT_BOX]] - // CHECK: project_box [[OPT_LIFETIME]] + // CHECK: project_box [[OPT_BOX]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PT]] : $*T // CHECK: [[T:%[0-9]+]] = load [copy] [[READ]] : $*T // CHECK: alloc_stack $Optional @@ -123,8 +122,7 @@ func optionalSubscriptGeneric(t t : T) { // CHECK: [[T_COPY:%.*]] = copy_value [[T]] // CHECK: store [[T_COPY]] to [init] [[PT]] : $*T // CHECK: [[OPT_BOX:%[0-9]+]] = alloc_box ${ var Optional } - // CHECK: [[OPT_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[OPT_BOX]] - // CHECK: project_box [[OPT_LIFETIME]] + // CHECK: project_box [[OPT_BOX]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PT]] : $*T // CHECK: [[T:%[0-9]+]] = load [copy] [[READ]] : $*T // CHECK: [[FIVELIT:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 5 diff --git a/test/SILGen/statements.swift b/test/SILGen/statements.swift index 66060a008ee67..11423b28e1dd1 100644 --- a/test/SILGen/statements.swift +++ b/test/SILGen/statements.swift @@ -526,12 +526,10 @@ func defer_mutable(_ x: Int) { var x = x // expected-warning@-1 {{variable 'x' was never mutated; consider changing to 'let' constant}} // CHECK: [[BOX:%.*]] = alloc_box ${ var Int } - // CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK-NEXT: project_box [[LIFETIME]] - // CHECK-NOT: [[LIFETIME]] + // CHECK-NEXT: project_box [[BOX]] + // CHECK-NOT: [[BOX]] // CHECK: function_ref @$s10statements13defer_mutableyySiF6$deferL_yyF : $@convention(thin) (@inout_aliasable Int) -> () - // CHECK-NOT: [[LIFETIME]] - // CHECK: end_borrow [[LIFETIME]] + // CHECK-NOT: [[BOX]] // CHECK: destroy_value [[BOX]] defer { _ = x } // expected-warning {{'defer' statement at end of scope always executes immediately}}{{3-8=do}} } diff --git a/test/SILGen/switch_fallthrough.swift b/test/SILGen/switch_fallthrough.swift index 40cad436b49e4..4be37a1adf6c4 100644 --- a/test/SILGen/switch_fallthrough.swift +++ b/test/SILGen/switch_fallthrough.swift @@ -139,11 +139,9 @@ func test5() { case (var n, foo()): // Check that the var is boxed and unboxed and the final value is the one that falls through into the next case // CHECK: [[BOX:%.*]] = alloc_box ${ var Int }, var, name "n" - // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] - // CHECK: [[N_BOX:%.*]] = project_box [[BOX_LIFETIME]] : ${ var Int }, 0 + // CHECK: [[N_BOX:%.*]] = project_box [[BOX]] : ${ var Int }, 0 // CHECK: function_ref @$s18switch_fallthrough1ayyF // CHECK: [[N:%.*]] = load [trivial] [[N_BOX]] : $*Int - // CHECK: end_borrow [[BOX_LIFETIME]] // CHECK: destroy_value [[BOX]] : ${ var Int } // CHECK: br [[CASE2:bb[0-9]+]]([[N]] : $Int) a() diff --git a/test/SILGen/switch_var.swift b/test/SILGen/switch_var.swift index f5eddc212a65b..038c6a58e4ff0 100644 --- a/test/SILGen/switch_var.swift +++ b/test/SILGen/switch_var.swift @@ -47,14 +47,12 @@ func test_var_1() { // CHECK: function_ref @$s10switch_var3fooSiyF switch foo() { // CHECK: [[XADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%.+]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[X:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[X:%.*]] = project_box [[XADDR]] // CHECK-NOT: br bb case var x: // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var1a1xySi_tF - // CHECK: end_borrow [[XLIFETIME]] // CHECK: destroy_value [[XADDR]] a(x: x) } @@ -67,8 +65,7 @@ func test_var_2() { // CHECK: function_ref @$s10switch_var3fooSiyF switch foo() { // CHECK: [[XADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%.*]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[X:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[X:%.*]] = project_box [[XADDR]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var6runced1xSbSi_tF @@ -79,14 +76,12 @@ func test_var_2() { // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var1a1xySi_tF - // CHECK: end_borrow [[XLIFETIME]] // CHECK: destroy_value [[XADDR]] // CHECK: br [[CONT:bb[0-9]+]] a(x: x) // CHECK: [[NO_CASE1]]: // CHECK: [[YADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[YLIFETIME:%[^,]+]] = begin_borrow [lexical] [[YADDR]] - // CHECK: [[Y:%.*]] = project_box [[YLIFETIME]] + // CHECK: [[Y:%.*]] = project_box [[YADDR]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var6funged1xSbSi_tF @@ -96,19 +91,16 @@ func test_var_2() { // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var1b1xySi_tF - // CHECK: end_borrow [[YLIFETIME]] // CHECK: destroy_value [[YADDR]] // CHECK: br [[CONT]] b(x: y) case var z: // CHECK: [[NO_CASE2]]: // CHECK: [[ZADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[ZLIFETIME:%[^,]+]] = begin_borrow [lexical] [[ZADDR]] - // CHECK: [[Z:%.*]] = project_box [[ZLIFETIME]] + // CHECK: [[Z:%.*]] = project_box [[ZADDR]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var1c1xySi_tF - // CHECK: end_borrow [[ZLIFETIME]] // CHECK: destroy_value [[ZADDR]] // CHECK: br [[CONT]] c(x: z) @@ -124,8 +116,7 @@ func test_var_3() { // CHECK: function_ref @$s10switch_var3barSiyF switch (foo(), bar()) { // CHECK: [[XADDR:%.*]] = alloc_box ${ var (Int, Int) } - // CHECK: [[XLIFETIME:%[^,]+]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[X:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[X:%.*]] = project_box [[XADDR]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]] // CHECK: tuple_element_addr [[READ]] : {{.*}}, 0 // CHECK: function_ref @$s10switch_var6runced1xSbSi_tF @@ -135,18 +126,15 @@ func test_var_3() { // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var2aa1xySi_Sit_tF - // CHECK: end_borrow [[XLIFETIME]] // CHECK: destroy_value [[XADDR]] // CHECK: br [[CONT:bb[0-9]+]] aa(x: x) // CHECK: [[NO_CASE1]]: // CHECK: [[YADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[YLIFETIME:%[^,]+]] = begin_borrow [lexical] [[YADDR]] - // CHECK: [[Y:%.*]] = project_box [[YLIFETIME]] + // CHECK: [[Y:%.*]] = project_box [[YADDR]] // CHECK: [[ZADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[ZLIFETIME:%[^,]+]] = begin_borrow [lexical] [[ZADDR]] - // CHECK: [[Z:%.*]] = project_box [[ZLIFETIME]] + // CHECK: [[Z:%.*]] = project_box [[ZADDR]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var6funged1xSbSi_tF @@ -159,17 +147,14 @@ func test_var_3() { // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var1b1xySi_tF - // CHECK: end_borrow [[ZLIFETIME]] // CHECK: destroy_value [[ZADDR]] - // CHECK: end_borrow [[YLIFETIME]] // CHECK: destroy_value [[YADDR]] // CHECK: br [[CONT]] a(x: y) b(x: z) // CHECK: [[NO_CASE2]]: // CHECK: [[WADDR:%.*]] = alloc_box ${ var (Int, Int) } - // CHECK: [[WLIFETIME:%[^,]+]] = begin_borrow [lexical] [[WADDR]] - // CHECK: [[W:%.*]] = project_box [[WLIFETIME]] + // CHECK: [[W:%.*]] = project_box [[WADDR]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[W]] // CHECK: tuple_element_addr [[READ]] : {{.*}}, 0 // CHECK: function_ref @$s10switch_var5ansed1xSbSi_tF @@ -182,16 +167,13 @@ func test_var_3() { // CHECK: br [[CONT]] bb(x: w) // CHECK: [[NO_CASE3]]: - // CHECK: end_borrow [[WLIFETIME]] // CHECK: destroy_value [[WADDR]] case var v: // CHECK: [[VADDR:%.*]] = alloc_box ${ var (Int, Int) } - // CHECK: [[VLIFETIME:%[^,]+]] = begin_borrow [lexical] [[VADDR]] - // CHECK: [[V:%.*]] = project_box [[VLIFETIME]] + // CHECK: [[V:%.*]] = project_box [[VADDR]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[V]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var2cc1xySi_Sit_tF - // CHECK: end_borrow [[VLIFETIME]] // CHECK: destroy_value [[VADDR]] // CHECK: br [[CONT]] cc(x: v) @@ -222,8 +204,7 @@ func test_var_4(p p: P) { // CHECK: [[IS_X]]: // CHECK: [[T0:%.*]] = load [trivial] [[TMP]] : $*X // CHECK: [[XADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%.+]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[X:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[X:%.*]] = project_box [[XADDR]] // CHECK: store [[PAIR_1]] to [trivial] [[X]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]] // CHECK: load [trivial] [[READ]] @@ -232,7 +213,6 @@ func test_var_4(p p: P) { case (is X, var x) where runced(x: x): // CHECK: [[CASE1]]: // CHECK: function_ref @$s10switch_var1a1xySi_tF - // CHECK: end_borrow [[XLIFETIME]] // CHECK: destroy_value [[XADDR]] // CHECK: dealloc_stack [[TMP]] // CHECK: destroy_addr [[PAIR_0]] : $*any P @@ -255,8 +235,7 @@ func test_var_4(p p: P) { // CHECK: [[IS_Y]]: // CHECK: [[T0:%.*]] = load [trivial] [[TMP]] : $*Y // CHECK: [[YADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[YLIFETIME:%.+]] = begin_borrow [lexical] [[YADDR]] - // CHECK: [[Y:%.*]] = project_box [[YLIFETIME]] + // CHECK: [[Y:%.*]] = project_box [[YADDR]] // CHECK: store [[PAIR_1]] to [trivial] [[Y]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]] // CHECK: load [trivial] [[READ]] @@ -268,7 +247,6 @@ func test_var_4(p p: P) { // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var1b1xySi_tF - // CHECK: end_borrow [[YLIFETIME]] // CHECK: destroy_value [[YADDR]] // CHECK: dealloc_stack [[TMP]] // CHECK: destroy_addr [[PAIR_0]] : $*any P @@ -277,7 +255,6 @@ func test_var_4(p p: P) { b(x: y) // CHECK: [[NO_CASE2]]: - // CHECK: end_borrow [[YLIFETIME]] // CHECK: destroy_value [[YADDR]] // CHECK: dealloc_stack [[TMP]] // CHECK: br [[NEXT:bb[0-9]+]] @@ -312,12 +289,10 @@ func test_var_4(p p: P) { case (_, var w): // CHECK: [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(any P, Int), 0 // CHECK: [[WADDR:%.*]] = alloc_box ${ var Int } - // CHECK: [[WLIFETIME:%.+]] = begin_borrow [lexical] [[WADDR]] - // CHECK: [[W:%.*]] = project_box [[WLIFETIME]] + // CHECK: [[W:%.*]] = project_box [[WADDR]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[W]] // CHECK: load [trivial] [[READ]] // CHECK: function_ref @$s10switch_var1d1xySi_tF - // CHECK: end_borrow [[WLIFETIME]] // CHECK: destroy_value [[WADDR]] // CHECK-NEXT: destroy_addr [[PAIR_0]] : $*any P // CHECK-NEXT: dealloc_stack [[PAIR]] @@ -334,8 +309,7 @@ func test_var_5() { // CHECK: function_ref @$s10switch_var3barSiyF switch (foo(), bar()) { // CHECK: [[XADDR:%.*]] = alloc_box ${ var (Int, Int) } - // CHECK: [[XLIFETIME:%.*]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[X:%.*]] = project_box [[XLIFETIME]] + // CHECK: [[X:%.*]] = project_box [[XADDR]] // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]] case var x where runced(x: x.0): // CHECK: [[CASE1]]: @@ -343,24 +317,18 @@ func test_var_5() { a() // CHECK: [[NO_CASE1]]: // CHECK: [[YADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[YLIFETIME:%[^,]+]] = begin_borrow [lexical] [[YADDR]] - // CHECK: [[Y:%[0-9]+]] = project_box [[YLIFETIME]] + // CHECK: [[Y:%[0-9]+]] = project_box [[YADDR]] // CHECK: [[ZADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[ZLIFETIME:%[^,]+]] = begin_borrow [lexical] [[ZADDR]] - // CHECK: [[Z:%[0-9]+]] = project_box [[ZLIFETIME]] + // CHECK: [[Z:%[0-9]+]] = project_box [[ZADDR]] // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]] case (var y, var z) where funged(x: y): // CHECK: [[CASE2]]: - // CHECK: end_borrow [[ZLIFETIME]] // CHECK: destroy_value [[ZADDR]] - // CHECK: end_borrow [[YLIFETIME]] // CHECK: destroy_value [[YADDR]] // CHECK: br [[CONT]] b() // CHECK: [[NO_CASE2]]: - // CHECK: end_borrow [[ZLIFETIME]] // CHECK: destroy_value [[ZADDR]] - // CHECK: end_borrow [[YLIFETIME]] // CHECK: destroy_value [[YADDR]] // CHECK: cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]] case (_, _) where runced(): @@ -381,49 +349,39 @@ func test_var_return() { switch (foo(), bar()) { case var x where runced(): // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var (Int, Int) } - // CHECK: [[XLIFETIME:%[^,]+]] = begin_borrow [lexical] [[XADDR]] - // CHECK: [[X:%[0-9]+]] = project_box [[XLIFETIME]] + // CHECK: [[X:%[0-9]+]] = project_box [[XADDR]] // CHECK: function_ref @$s10switch_var1ayyF - // CHECK: end_borrow [[XLIFETIME]] // CHECK: destroy_value [[XADDR]] // CHECK: br [[EPILOG:bb[0-9]+]] a() return // CHECK: [[YADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[YLIFETIME:%[^,]+]] = begin_borrow [lexical] [[YADDR]] - // CHECK: [[Y:%[0-9]+]] = project_box [[YLIFETIME]] + // CHECK: [[Y:%[0-9]+]] = project_box [[YADDR]] // CHECK: [[ZADDR:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[ZLIFETIME:%[^,]+]] = begin_borrow [lexical] [[ZADDR]] - // CHECK: [[Z:%[0-9]+]] = project_box [[ZLIFETIME]] + // CHECK: [[Z:%[0-9]+]] = project_box [[ZADDR]] case (var y, var z) where funged(): // CHECK: function_ref @$s10switch_var1byyF - // CHECK: end_borrow [[ZLIFETIME]] // CHECK: destroy_value [[ZADDR]] - // CHECK: end_borrow [[YLIFETIME]] // CHECK: destroy_value [[YADDR]] // CHECK: br [[EPILOG]] b() return case var w where ansed(): // CHECK: [[WADDR:%[0-9]+]] = alloc_box ${ var (Int, Int) } - // CHECK: [[WLIFETIME:%[^,]+]] = begin_borrow [lexical] [[WADDR]] - // CHECK: [[W:%[0-9]+]] = project_box [[WLIFETIME]] + // CHECK: [[W:%[0-9]+]] = project_box [[WADDR]] // CHECK: function_ref @$s10switch_var1cyyF // CHECK-NOT: destroy_value [[ZADDR]] // CHECK-NOT: destroy_value [[YADDR]] - // CHECK: end_borrow [[WLIFETIME]] // CHECK: destroy_value [[WADDR]] // CHECK: br [[EPILOG]] c() return case var v: // CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var (Int, Int) } - // CHECK: [[VLIFETIME:%[^,]+]] = begin_borrow [lexical] [[VADDR]] - // CHECK: [[V:%[0-9]+]] = project_box [[VLIFETIME]] + // CHECK: [[V:%[0-9]+]] = project_box [[VADDR]] // CHECK: function_ref @$s10switch_var1dyyF // CHECK-NOT: destroy_value [[ZADDR]] // CHECK-NOT: destroy_value [[YADDR]] - // CHECK: end_borrow [[VLIFETIME]] // CHECK: destroy_value [[VADDR]] // CHECK: br [[EPILOG]] d() diff --git a/test/SILGen/tuples.swift b/test/SILGen/tuples.swift index 5e46052162092..c7a370886969d 100644 --- a/test/SILGen/tuples.swift +++ b/test/SILGen/tuples.swift @@ -28,8 +28,7 @@ func testShuffleOpaque() { // CHECK: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X]] // CHECK-NEXT: [[PBX:%.*]] = project_box [[X_LIFETIME]] // CHECK: [[Y:%.*]] = alloc_box ${ var Int } - // CHECK: [[Y_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[Y]] - // CHECK-NEXT: [[PBY:%.*]] = project_box [[Y_LIFETIME]] + // CHECK-NEXT: [[PBY:%.*]] = project_box [[Y]] // CHECK-NEXT: [[TMP:%.*]] = alloc_stack $any P // CHECK: [[T0:%.*]] = function_ref @$s6tuples7make_xySi1x_AA1P_p1ytyF @@ -73,8 +72,7 @@ func testShuffleTuple() { // CHECK: [[X_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[X]] // CHECK-NEXT: [[PBX:%.*]] = project_box [[X_LIFETIME]] // CHECK: [[Y:%.*]] = alloc_box ${ var Int } - // CHECK: [[Y_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[Y]] - // CHECK-NEXT: [[PBY:%.*]] = project_box [[Y_LIFETIME]] + // CHECK-NEXT: [[PBY:%.*]] = project_box [[Y]] // CHECK-NEXT: // function_ref // CHECK-NEXT: [[T0:%.*]] = function_ref @$s6tuples8make_intSiyF // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]() diff --git a/test/SILGen/types.swift b/test/SILGen/types.swift index 9770300c57873..7dede2585a9db 100644 --- a/test/SILGen/types.swift +++ b/test/SILGen/types.swift @@ -28,8 +28,7 @@ struct S { // CHECK: bb0([[X:%[0-9]+]] : $Int, [[THIS:%[0-9]+]] : $*S): member = x // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int } - // CHECK: [[XLIFETIME:%[^,]+]] = begin_borrow [lexical] [[XBOX]] - // CHECK: [[XADDR:%[0-9]+]] = project_box [[XLIFETIME]] + // CHECK: [[XADDR:%[0-9]+]] = project_box [[XBOX]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[XADDR]] : $*Int // CHECK: [[X:%.*]] = load [trivial] [[READ]] : $*Int // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[THIS]] : $*S diff --git a/test/SILGen/unsafevalue.swift b/test/SILGen/unsafevalue.swift index 4ca0018add2df..c318d8747f458 100644 --- a/test/SILGen/unsafevalue.swift +++ b/test/SILGen/unsafevalue.swift @@ -29,8 +29,7 @@ public struct UnsafeValue { // CHECK: bb0([[INPUT_ELEMENT:%.*]] : @guaranteed $Element, // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[UNINIT_BOX:%.*]] = mark_uninitialized [rootself] [[BOX]] - // CHECK: [[UNINIT_BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[UNINIT_BOX]] - // CHECK: [[PROJECT_UNINIT_BOX:%.*]] = project_box [[UNINIT_BOX_LIFETIME]] + // CHECK: [[PROJECT_UNINIT_BOX:%.*]] = project_box [[UNINIT_BOX]] // CHECK: [[COPY_INPUT_ELEMENT:%.*]] = copy_value [[INPUT_ELEMENT]] // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_UNINIT_BOX]] // CHECK: [[STRUCT_ACCESS:%.*]] = struct_element_addr [[ACCESS]] @@ -39,7 +38,6 @@ public struct UnsafeValue { // CHECK: destroy_value [[COPY_INPUT_ELEMENT]] // CHECK: end_access [[ACCESS]] // CHECK: [[RESULT:%.*]] = load [trivial] [[PROJECT_UNINIT_BOX]] - // CHECK: end_borrow [[UNINIT_BOX_LIFETIME]] // CHECK: destroy_value [[UNINIT_BOX]] // CHECK: return [[RESULT]] // CHECK: } // end sil function '$s11unsafevalue11UnsafeValueV14unsafelyAssignACyxGxh_tcfC' @@ -72,8 +70,7 @@ public struct UnsafeValue { // CHECK-LABEL: sil [transparent] [serialized] [ossa] @$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF : // CHECK: bb0([[RESULT:%.*]] : $*Result, [[BASE:%.*]] : $*Base, [[CLOSURE:%.*]] : $@noescape @callee_guaranteed {{.*}}, [[UNSAFE_VALUE:%.*]] : $UnsafeValue): // CHECK: [[COPY_BOX:%.*]] = alloc_box - // CHECK: [[COPY_BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[COPY_BOX]] - // CHECK: [[COPY_PROJ:%.*]] = project_box [[COPY_BOX_LIFETIME]] + // CHECK: [[COPY_PROJ:%.*]] = project_box [[COPY_BOX]] // CHECK: store [[UNSAFE_VALUE]] to [trivial] [[COPY_PROJ]] // CHECK: [[VALUE_ADDR:%.*]] = begin_access [read] [unknown] [[COPY_PROJ]] // CHECK: [[STR_VALUE_ADDR:%.*]] = struct_element_addr [[VALUE_ADDR]] @@ -84,7 +81,6 @@ public struct UnsafeValue { // CHECK: end_access [[VALUE_ADDR]] // CHECK: apply [[CLOSURE]]([[RESULT]], [[GUARANTEED_REF_DEP_ON_BASE]]) // CHECK: end_borrow [[GUARANTEED_REF]] - // CHECK: end_borrow [[COPY_BOX_LIFETIME]] // CHECK: destroy_value [[COPY_BOX]] // CHECK: } // end sil function '$s11unsafevalue11UnsafeValueV20withGuaranteeingBase4base_qd_0_qd___qd_0_xXEtr0_lF' // diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift index 1b12d9c8f605c..1b6222765d217 100644 --- a/test/SILOptimizer/access_marker_verify.swift +++ b/test/SILOptimizer/access_marker_verify.swift @@ -53,15 +53,13 @@ struct StructOfInt { // CHECK: bb0(%0 : $@thin StructOfInt.Type): // CHECK: [[BOX:%.*]] = alloc_box ${ var StructOfInt }, var, name "self" // CHECK: [[UNINIT:%.*]] = mark_uninitialized [rootself] [[BOX]] : ${ var StructOfInt } -// CHECK: [[UNINIT_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[UNINIT]] -// CHECK: [[PROJ:%.*]] = project_box [[UNINIT_LIFETIME]] : ${ var StructOfInt }, 0 +// CHECK: [[PROJ:%.*]] = project_box [[UNINIT]] : ${ var StructOfInt }, 0 // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJ]] : $*StructOfInt // CHECK: [[ADR:%.*]] = struct_element_addr [[ACCESS]] : $*StructOfInt, #StructOfInt.i // CHECK: assign %{{.*}} to [[ADR]] : $*Int // CHECK: end_access [[ACCESS]] : $*StructOfInt // CHECK-NOT: begin_access // CHECK: [[VAL:%.*]] = load [trivial] [[PROJ]] : $*StructOfInt -// CHECK: end_borrow [[UNINIT_LIFETIME]] // CHECK: destroy_value [[UNINIT]] : ${ var StructOfInt } // CHECK: return [[VAL]] : $StructOfInt // CHECK-LABEL: } // end sil function '$s20access_marker_verify11StructOfIntVACycfC' @@ -222,12 +220,11 @@ func testCaptureLocal() -> ()->() { // CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify16testCaptureLocalyycyF : $@convention(thin) () -> @owned @callee_guaranteed () -> () { // CHECK: bb0: // CHECK: [[BOX:%.*]] = alloc_box ${ var Int }, var, name "x" -// CHECK: [[LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] -// CHECK: [[PROJ:%.*]] = project_box [[LIFETIME]] +// CHECK: [[PROJ:%.*]] = project_box [[BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[PROJ]] : $*Int // CHECK: store %{{.*}} to [trivial] [[ACCESS]] // CHECK: end_access -// CHECK: [[CAPTURE:%.*]] = copy_value [[LIFETIME]] : ${ var Int } +// CHECK: [[CAPTURE:%.*]] = copy_value [[BOX]] : ${ var Int } // CHECK: partial_apply [callee_guaranteed] %{{.*}}([[CAPTURE]]) : $@convention(thin) (@guaranteed { var Int }) -> () // CHECK: begin_access [read] [unknown] [[PROJ]] // CHECK: [[VAL:%.*]] = load [trivial] @@ -296,7 +293,7 @@ func testCopyS(_ arg: StructOfInt) -> StructOfInt { } // CHECK-LABEL: sil hidden [ossa] @$s20access_marker_verify9testCopySyAA11StructOfIntVADF : $@convention(thin) (StructOfInt) -> StructOfInt { // CHECK: bb0(%0 : $StructOfInt): -// CHECK: alloc_stack [lexical] $StructOfInt, let, name "lhs" +// CHECK: alloc_stack $StructOfInt, let, name "lhs" // CHECK: [[UNINIT:%.*]] = mark_uninitialized [var] // CHECK-NOT: begin_access // CHECK: assign %0 to [[UNINIT]] : $*StructOfInt diff --git a/test/SILOptimizer/capturepromotion-wrong-lexicalscope.swift b/test/SILOptimizer/capturepromotion-wrong-lexicalscope.swift index 430b504dce95e..f3594555b481c 100644 --- a/test/SILOptimizer/capturepromotion-wrong-lexicalscope.swift +++ b/test/SILOptimizer/capturepromotion-wrong-lexicalscope.swift @@ -4,28 +4,27 @@ // CHECK: sil hidden [ossa] @$s4null19captureStackPromoteSiycyF : $@convention(thin) () -> @owned @callee_guaranteed () -> Int { // CHECK: bb0: -// CHECK: [[BOX:%[^,]+]] = alloc_box ${ var Int }, var, name "x", loc {{.*}}:33:7, scope 3 -// CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]] -// CHECK: [[BOX_ADDR:%[^,]+]] = project_box [[BOX_LIFETIME]] : ${ var Int }, 0, loc {{.*}}:33:7, scope 3 -// CHECK: [[ONE:%[^,]+]] = integer_literal $Builtin.IntLiteral, 1, loc {{.*}}:33:11, scope 3 -// CHECK: [[THIN_INT_TYPE:%[^,]+]] = metatype $@thin Int.Type, loc {{.*}}:33:11, scope 3 -// CHECK: [[INTEGER_LITERAL:%[^,]+]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int, loc {{.*}}:33:11, scope 3 -// CHECK: [[ONE_INT:%[^,]+]] = apply [[INTEGER_LITERAL]]([[ONE]], [[THIN_INT_TYPE]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int, loc {{.*}}:33:11, scope 3 -// CHECK: store [[ONE_INT]] to [trivial] [[BOX_ADDR]] : $*Int, loc {{.*}}:33:11, scope 3 -// CHECK: [[BOX_COPY:%[^,]+]] = copy_value [[BOX_LIFETIME]] : ${ var Int }, loc {{.*}}:34:11, scope 3 -// CHECK: [[BOX_COPY_ADDR:%[^,]+]] = project_box [[BOX_COPY]] : ${ var Int }, 0, loc {{.*}}:34:11, scope 3 -// CHECK: mark_function_escape [[BOX_ADDR]] : $*Int, loc {{.*}}:34:11, scope 3 -// CHECK: [[SPECIALIZED_F:%[^,]+]] = function_ref @$s4null19captureStackPromoteSiycyFSiycfU_Tf2i_n : $@convention(thin) (Int) -> Int, loc {{.*}}:34:11, scope 3 -// CHECK: [[REGISTER_11:%[^,]+]] = load [trivial] [[BOX_COPY_ADDR]] : $*Int, loc {{.*}}:34:11, scope 3 -// CHECK: destroy_value [[BOX_COPY]] : ${ var Int }, loc {{.*}}:34:11, scope 3 -// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[SPECIALIZED_F]]([[REGISTER_11]]) : $@convention(thin) (Int) -> Int, loc {{.*}}:34:11, scope 3 +// CHECK: [[BOX:%[^,]+]] = alloc_box ${ var Int }, var, name "x", loc {{.*}}:32:7, scope 3 +// CHECK: [[BOX_ADDR:%[^,]+]] = project_box [[BOX]] : ${ var Int }, 0, loc {{.*}}:32:7, scope 3 +// CHECK: [[ONE:%[^,]+]] = integer_literal $Builtin.IntLiteral, 1, loc {{.*}}:32:11, scope 3 +// CHECK: [[THIN_INT_TYPE:%[^,]+]] = metatype $@thin Int.Type, loc {{.*}}:32:11, scope 3 +// CHECK: [[INTEGER_LITERAL:%[^,]+]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int, loc {{.*}}:32:11, scope 3 +// CHECK: [[ONE_INT:%[^,]+]] = apply [[INTEGER_LITERAL]]([[ONE]], [[THIN_INT_TYPE]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int, loc {{.*}}:32:11, scope 3 +// CHECK: store [[ONE_INT]] to [trivial] [[BOX_ADDR]] : $*Int, loc {{.*}}:32:11, scope 3 +// CHECK: [[BOX_COPY:%[^,]+]] = copy_value [[BOX]] : ${ var Int }, loc {{.*}}:33:11, scope 3 +// CHECK: [[BOX_COPY_ADDR:%[^,]+]] = project_box [[BOX_COPY]] : ${ var Int }, 0, loc {{.*}}:33:11, scope 3 +// CHECK: mark_function_escape [[BOX_ADDR]] : $*Int, loc {{.*}}:33:11, scope 3 +// CHECK: [[SPECIALIZED_F:%[^,]+]] = function_ref @$s4null19captureStackPromoteSiycyFSiycfU_Tf2i_n : $@convention(thin) (Int) -> Int, loc {{.*}}:33:11, scope 3 +// CHECK: [[REGISTER_11:%[^,]+]] = load [trivial] [[BOX_COPY_ADDR]] : $*Int, loc {{.*}}:33:11, scope 3 +// CHECK: destroy_value [[BOX_COPY]] : ${ var Int }, loc {{.*}}:33:11, scope 3 +// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[SPECIALIZED_F]]([[REGISTER_11]]) : $@convention(thin) (Int) -> Int, loc {{.*}}:33:11, scope 3 // CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [[CLOSURE]] -// CHECK: debug_value [[BORROW]] : $@callee_guaranteed () -> Int, let, name "f", loc {{.*}}:34:7, scope 3 -// CHECK: [[CLOSURE_COPY:%[^,]+]] = copy_value [[BORROW]] : $@callee_guaranteed () -> Int, loc {{.*}}:35:10, scope 3 +// CHECK: debug_value [[BORROW]] : $@callee_guaranteed () -> Int, let, name "f", loc {{.*}}:33:7, scope 3 +// CHECK: [[CLOSURE_COPY:%[^,]+]] = copy_value [[BORROW]] : $@callee_guaranteed () -> Int, loc {{.*}}:34:10, scope 3 // There used to be an end_borrow here. We leave an emptyline here to preserve line numbers. -// CHECK: destroy_value [[CLOSURE]] : $@callee_guaranteed () -> Int, loc {{.*}}:36:1, scope 3 -// CHECK: destroy_value [[BOX]] : ${ var Int }, loc {{.*}}:36:1, scope 3 -// CHECK: return [[CLOSURE_COPY]] : $@callee_guaranteed () -> Int, loc {{.*}}:35:3, scope 3 +// CHECK: destroy_value [[CLOSURE]] : $@callee_guaranteed () -> Int, loc {{.*}}:35:1, scope 3 +// CHECK: destroy_value [[BOX]] : ${ var Int }, loc {{.*}}:35:1, scope 3 +// CHECK: return [[CLOSURE_COPY]] : $@callee_guaranteed () -> Int, loc {{.*}}:34:3, scope 3 // CHECK: } From 921c7f69c865c9a3f7d055cc3eb1b287f37e4872 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Tue, 16 Aug 2022 15:10:16 -0700 Subject: [PATCH 290/491] [SIL] Only lexical owned args are lexical. Previously, every owned argument was considered lexical. That included owned arguments with eager move lifetimes. Here, only owned arguments whose lifetimes are lexical (i.e. not those whose lifetimes are eager move) are considered lexical. --- lib/SIL/IR/SILValue.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/SIL/IR/SILValue.cpp b/lib/SIL/IR/SILValue.cpp index 84895884891f5..b8d1ecf9f729f 100644 --- a/lib/SIL/IR/SILValue.cpp +++ b/lib/SIL/IR/SILValue.cpp @@ -106,8 +106,11 @@ ValueBase::getDefiningInstructionResult() { } bool ValueBase::isLexical() const { - if (auto *argument = dyn_cast(this)) - return argument->getOwnershipKind() == OwnershipKind::Owned; + if (auto *argument = dyn_cast(this)) { + // TODO: Recognize guaranteed arguments as lexical too. + return argument->getOwnershipKind() == OwnershipKind::Owned && + argument->getLifetime().isLexical(); + } if (auto *bbi = dyn_cast(this)) return bbi->isLexical(); if (auto *mvi = dyn_cast(this)) From e2698edb7ceccbed30de02ac3c4062e40dd823fe Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 18 Aug 2022 17:48:11 -0700 Subject: [PATCH 291/491] [MemAccessUtils] Non-trivial Cxx node is leaf. Nodes which are non-trivial C++ decls must be destroyed, they cannot be destroyed by way of destroying their subobjects. This was exposed by producing more non-lexical alloc_stacks which enjoy more aggressive destroy_addr hoisting. --- lib/SIL/Utils/MemAccessUtils.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/SIL/Utils/MemAccessUtils.cpp b/lib/SIL/Utils/MemAccessUtils.cpp index b67e8b281b78c..3dc04f127739e 100644 --- a/lib/SIL/Utils/MemAccessUtils.cpp +++ b/lib/SIL/Utils/MemAccessUtils.cpp @@ -1415,6 +1415,10 @@ void swift::visitProductLeafAccessPathNodes( visitor(AccessPath::PathNode(node), silType); continue; } + if (decl->isCxxNonTrivial()) { + visitor(AccessPath::PathNode(node), silType); + continue; + } unsigned index = 0; for (auto *field : decl->getStoredProperties()) { auto *fieldNode = node->getChild(index); From 496c1d219414a3082b07a28e03a74e2b34155068 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Wed, 10 Aug 2022 17:30:28 -0700 Subject: [PATCH 292/491] [SIL] Added SILType::isAggregate. --- include/swift/SIL/SILType.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index 4b25d5835afef..867f4932e8c9f 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -232,6 +232,13 @@ class SILType { return value.getPointer()->isVoid(); } + /// Whether the type is an enum, struct, or tuple. + bool isAggregate() { + return is() || is() || + is() || is() || + is(); + } + /// Retrieve the ClassDecl for a type that maps to a Swift class or /// bound generic class type. ClassDecl *getClassOrBoundGenericClass() const { From e9595ab84504b07fac92b60de1d8e99ab154b367 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 22 Aug 2022 15:01:36 -0700 Subject: [PATCH 293/491] [TypeLowering] Verify lexical property. Check that if a type is non-trivial then either (1) it is lexical or (2) its non-trivial leaves are @_eagerMove. --- include/swift/SIL/SILType.h | 19 +++++++ include/swift/SIL/TypeLowering.h | 6 ++ lib/SIL/IR/SILType.cpp | 64 +++++++++++++++++++++ lib/SIL/IR/TypeLowering.cpp | 96 ++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+) diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index 867f4932e8c9f..9af89080bf1de 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -753,6 +753,25 @@ class SILType { void dump() const; void print(raw_ostream &OS, const PrintOptions &PO = PrintOptions::printSIL()) const; + +#ifndef NDEBUG + /// Visit the distinct types of the fields out of which a type is aggregated. + /// + /// As we walk into the field types, if an aggregate is encountered, it may + /// still be a leaf. It is a leaf if the \p isLeafAggregate predicate + /// returns true. + /// + /// Returns false if the leaves cannot be visited or if any invocation of the + /// visitor returns false. + /// + /// NOTE: This function is meant for use in verification. For real use-cases, + /// recursive walks of type leaves should be done via + /// TypeLowering::RecursiveProperties. + bool visitAggregateLeaves( + Lowering::TypeConverter &TC, TypeExpansionContext context, + std::function isLeafAggregate, + std::function visit) const; +#endif }; // Statically prevent SILTypes from being directly cast to a type diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index 810d8a6a80617..1566451b49f07 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -1245,6 +1245,12 @@ class TypeConverter { CanType result, Bridgeability bridging, bool suppressOptional); +#ifndef NDEBUG + /// Check the result of + /// getTypeLowering(AbstractionPattern,Type,TypeExpansionContext). + void verifyLowering(const TypeLowering &, AbstractionPattern origType, + Type origSubstType, TypeExpansionContext forExpansion); +#endif }; } // namespace Lowering diff --git a/lib/SIL/IR/SILType.cpp b/lib/SIL/IR/SILType.cpp index b5d869303dd4e..a21772fb67f6b 100644 --- a/lib/SIL/IR/SILType.cpp +++ b/lib/SIL/IR/SILType.cpp @@ -22,6 +22,7 @@ #include "swift/SIL/SILFunctionConventions.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/TypeLowering.h" +#include using namespace swift; using namespace swift::Lowering; @@ -941,3 +942,66 @@ bool SILType::isMoveOnly() const { return true; return isMoveOnlyWrapped(); } + +#ifndef NDEBUG +bool SILType::visitAggregateLeaves( + Lowering::TypeConverter &TC, TypeExpansionContext context, + std::function isLeaf, + std::function visit) const { + + llvm::SmallSet, + 16> + visited; + llvm::SmallVector< + std::tuple, 16> + worklist; + auto insertIntoWorklist = [&visited, &worklist](SILType parent, SILType type, + VarDecl *decl) -> bool { + if (!visited.insert({parent.value, type.value, decl}).second) { + return false; + } + worklist.push_back({parent.value, type.value, decl}); + return true; + }; + auto popFromWorklist = + [&worklist]() -> std::tuple { + SILType::ValueType parentOpaqueType; + SILType::ValueType opaqueType; + VarDecl *decl; + std::tie(parentOpaqueType, opaqueType, decl) = worklist.pop_back_val(); + return {parentOpaqueType, opaqueType, decl}; + }; + insertIntoWorklist(SILType(), *this, nullptr); + while (!worklist.empty()) { + SILType parent; + SILType ty; + VarDecl *decl; + std::tie(parent, ty, decl) = popFromWorklist(); + if (ty.isAggregate() && !isLeaf(parent, ty, decl)) { + if (auto tupleTy = ty.getAs()) { + for (unsigned index = 0, num = tupleTy->getNumElements(); index < num; + ++index) { + insertIntoWorklist(ty, ty.getTupleElementType(index), nullptr); + } + } else if (auto *decl = ty.getStructOrBoundGenericStruct()) { + for (auto *field : decl->getStoredProperties()) { + insertIntoWorklist(ty, ty.getFieldType(field, TC, context), field); + } + } else if (auto *decl = ty.getEnumOrBoundGenericEnum()) { + for (auto *field : decl->getStoredProperties()) { + insertIntoWorklist(ty, ty.getFieldType(field, TC, context), field); + } + } else { + llvm_unreachable("unknown aggregate kind!"); + } + continue; + } + + // This type is a leaf. Visit it. + auto success = visit(parent, ty, decl); + if (!success) + return false; + } + return true; +} +#endif diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index 6d8429fbd073e..451c0a02c5447 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -2420,9 +2420,105 @@ TypeConverter::getTypeLowering(AbstractionPattern origType, removeNullEntry(key.getKeyForMinimalExpansion()); #endif } + +#ifndef NDEBUG + verifyLowering(*lowering, origType, origSubstType, forExpansion); +#endif + return *lowering; } +#ifndef NDEBUG +void TypeConverter::verifyLowering(const TypeLowering &lowering, + AbstractionPattern origType, + Type origSubstType, + TypeExpansionContext forExpansion) { + // Non-trivial lowerings should always be lexical unless all non-trivial + // fields are eager move. + if (!lowering.isTrivial() && !lowering.isLexical()) { + auto getLifetimeAnnotation = [](SILType ty) -> LifetimeAnnotation { + NominalTypeDecl *nominal; + if (!(nominal = ty.getASTType().getAnyNominal())) + return LifetimeAnnotation::None; + return nominal->getLifetimeAnnotation(); + }; + auto loweredType = lowering.getLoweredType(); + bool hasNoNontrivialLexicalLeaf = loweredType.visitAggregateLeaves( + *this, forExpansion, + /*isLeaf=*/ + [&](auto parent, auto ty, auto *fieldDecl) -> bool { + // The field's type is an aggregate. Treat it as a leaf if it + // has a lifetime annotation. + + // If we don't have a field decl, it's either a field of a tuple + // or the top-level type. Either way, there's no var decl on + // which to look for an attribute. + // + // It's a leaf if the type has a lifetime annotation. + if (!fieldDecl) + return getLifetimeAnnotation(ty).isSome(); + + // It's a field of a struct or an enum. It's a leaf if the type + // or the var decl has a lifetime annotation. + return fieldDecl->getLifetimeAnnotation().isSome() || + getLifetimeAnnotation(ty); + }, + /*visit=*/ + [&](auto parent, auto ty, auto *fieldDecl) -> bool { + // Look at each leaf: if it is non-trivial, verify that it is + // attributed @_eagerMove. + + // If the leaf is the whole type, verify that it is annotated + // @_eagerMove. + if (ty == loweredType) + return getLifetimeAnnotation(ty) == LifetimeAnnotation::EagerMove; + + // Get ty's lowering. + CanGenericSignature sig; + if (fieldDecl) { + AbstractionPattern origFieldTy = getAbstractionPattern(fieldDecl); + CanType substFieldTy; + if (fieldDecl->hasClangNode()) { + substFieldTy = origFieldTy.getType(); + } else { + substFieldTy = parent.getASTType() + ->getTypeOfMember(&M, fieldDecl) + ->getCanonicalType(); + } + sig = getAbstractionPattern(fieldDecl).getGenericSignatureOrNull(); + } else { + sig = CanGenericSignature(); + } + auto &tyLowering = getTypeLowering(ty, forExpansion, sig); + + // Leaves which are trivial aren't of interest. + if (tyLowering.isTrivial()) + return true; + + // We're visiting a non-trival leaf of a type whose lowering is + // not lexical. The leaf must be annotated @_eagerMove. + // Otherwise, the whole type would be lexical. + + if (!fieldDecl) { + // The field is non-trivial and the whole type is non-lexical. + // If there's no field decl which might be annotated + // @_eagerMove, we have a problem. + return false; + } + + // The field is non-trivial and the whole type is non-lexical. + // That's fine as long as the field or its type is annotated + // @_eagerMove. + return fieldDecl->getLifetimeAnnotation() == + LifetimeAnnotation::EagerMove || + getLifetimeAnnotation(ty) == LifetimeAnnotation::EagerMove; + }); + assert(hasNoNontrivialLexicalLeaf && + "Found non-trivial lexical leaf in non-trivial non-lexical type?!"); + } +} +#endif + CanType TypeConverter::computeLoweredRValueType(TypeExpansionContext forExpansion, AbstractionPattern origType, From fefbbb6a1b8f9cf2e47b3919fdb942484ae8b035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Mon, 22 Aug 2022 15:47:49 -0700 Subject: [PATCH 294/491] [Sema] Note that the missing import is added automatically --- include/swift/AST/DiagnosticsSema.def | 4 ++++ lib/Sema/ResilienceDiagnostics.cpp | 16 ++++++++++++++++ .../Sema/implicit-import-in-inlinable-code.swift | 3 +++ test/Sema/implicit-import-typealias.swift | 15 ++++++++++----- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index b2dfc26399396..61f51ee311919 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5849,6 +5849,10 @@ ERROR(inlinable_typealias_desugars_to_type_from_hidden_module, "%4 was not imported by this file}5", (DeclName, StringRef, StringRef, unsigned, Identifier, unsigned)) +NOTE(missing_import_inserted, + none, "The missing import of module %0 will be added implicitly", + (Identifier)) + ERROR(availability_macro_in_inlinable, none, "availability macro cannot be used in " FRAGILE_FUNC_KIND "0", (unsigned)) diff --git a/lib/Sema/ResilienceDiagnostics.cpp b/lib/Sema/ResilienceDiagnostics.cpp index 597f331cf4ad7..38fef70d20a2d 100644 --- a/lib/Sema/ResilienceDiagnostics.cpp +++ b/lib/Sema/ResilienceDiagnostics.cpp @@ -144,6 +144,11 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc, } D->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type); + if (originKind == DisallowedOriginKind::ImplicitlyImported && + !ctx.LangOpts.isSwiftVersionAtLeast(6)) + ctx.Diags.diagnose(loc, diag::missing_import_inserted, + definingModule->getName()); + return true; } @@ -190,7 +195,13 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D, D->getDescriptiveKind(), D->getName(), fragileKind.getSelector(), definingModule->getName(), static_cast(originKind)); + + if (originKind == DisallowedOriginKind::ImplicitlyImported && + downgradeToWarning == DowngradeToWarning::Yes) + ctx.Diags.diagnose(loc, diag::missing_import_inserted, + definingModule->getName()); } + return true; } @@ -244,5 +255,10 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc, .warnUntilSwiftVersionIf(useConformanceAvailabilityErrorsOption && !ctx.LangOpts.EnableConformanceAvailabilityErrors, 6); + + if (originKind == DisallowedOriginKind::ImplicitlyImported && + !ctx.LangOpts.isSwiftVersionAtLeast(6)) + ctx.Diags.diagnose(loc, diag::missing_import_inserted, + M->getName()); return true; } diff --git a/test/Sema/implicit-import-in-inlinable-code.swift b/test/Sema/implicit-import-in-inlinable-code.swift index 35be4816cc4b9..0c39149b5a0ed 100644 --- a/test/Sema/implicit-import-in-inlinable-code.swift +++ b/test/Sema/implicit-import-in-inlinable-code.swift @@ -53,11 +53,13 @@ import libA @inlinable public func bar() { let a = ImportedType() a.implicitlyImportedMethod() // expected-warning {{instance method 'implicitlyImportedMethod()' cannot be used in an '@inlinable' function because 'libB' was not imported by this file; this is an error in Swift 6}} + // expected-note@-1 {{The missing import of module 'libB' will be added implicitly}} // Expected implicit imports are still fine a.localModuleMethod() conformanceUse(a) // expected-warning {{cannot use conformance of 'ImportedType' to 'SomeProtocol' here; 'libB' was not imported by this file; this is an error in Swift 6}} + // expected-note@-1 {{The missing import of module 'libB' will be added implicitly}} } // BEGIN clientFileA-OldCheck.swift @@ -72,6 +74,7 @@ import libA a.localModuleMethod() conformanceUse(a) // expected-warning {{cannot use conformance of 'ImportedType' to 'SomeProtocol' here; 'libB' was not imported by this file; this is an error in Swift 6}} + // expected-note@-1 {{The missing import of module 'libB' will be added implicitly}} } // BEGIN clientFileA-Swift6.swift diff --git a/test/Sema/implicit-import-typealias.swift b/test/Sema/implicit-import-typealias.swift index 51c2f6595e4ea..053dc011b4146 100644 --- a/test/Sema/implicit-import-typealias.swift +++ b/test/Sema/implicit-import-typealias.swift @@ -60,23 +60,28 @@ public typealias WrapperAlias = Wrapper import Aliases -// expected-warning@+1 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used here because 'Original' was not imported by this file; this is an error in Swift 6}} +// expected-warning@+2 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used here because 'Original' was not imported by this file; this is an error in Swift 6}} +// expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} public class InheritsFromClazzAlias: ClazzAlias {} @inlinable public func inlinableFunc() { - // expected-warning@+1 {{'StructAlias' aliases 'Original.Struct' and cannot be used in an '@inlinable' function because 'Original' was not imported by this file; this is an error in Swift 6}} + // expected-warning@+2 {{'StructAlias' aliases 'Original.Struct' and cannot be used in an '@inlinable' function because 'Original' was not imported by this file; this is an error in Swift 6}} + // expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} _ = StructAlias.self } -// expected-warning@+1 {{'ProtoAlias' aliases 'Original.Proto' and cannot be used here because 'Original' was not imported by this file; this is an error in Swift 6}} +// expected-warning@+2 {{'ProtoAlias' aliases 'Original.Proto' and cannot be used here because 'Original' was not imported by this file; this is an error in Swift 6}} +// expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} public func takesGeneric(_ t: T) {} public struct HasMembers { - // expected-warning@+1 {{'WrapperAlias' aliases 'Original.Wrapper' and cannot be used as property wrapper here because 'Original' was not imported by this file; this is an error in Swift 6}} + // expected-warning@+2 {{'WrapperAlias' aliases 'Original.Wrapper' and cannot be used as property wrapper here because 'Original' was not imported by this file; this is an error in Swift 6}} + // expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} @WrapperAlias public var wrapped: Int } -// expected-warning@+1 {{'StructAlias' aliases 'Original.Struct' and cannot be used in an extension with public or '@usableFromInline' members because 'Original' was not imported by this file; this is an error in Swift 6}} +// expected-warning@+2 {{'StructAlias' aliases 'Original.Struct' and cannot be used in an extension with public or '@usableFromInline' members because 'Original' was not imported by this file; this is an error in Swift 6}} +// expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} extension StructAlias { public func someFunc() {} } From baec3154a0d04e775fb858ee86a14b702a025954 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Mon, 22 Aug 2022 13:29:03 -0700 Subject: [PATCH 295/491] [Dependency Scan] Remove redundant recombination of arguments in 'initCompilerInstanceForScan' into a string, before being re-parsed. This does not seem to serve a purpose other than corrupting arguments with whitespaces - they get merged into one large string where the whitespace boundary between arguments and whitespaces within arguments are blurred. Part of rdar://98985453 --- lib/DependencyScan/DependencyScanningTool.cpp | 15 +++------------ unittests/DependencyScan/ModuleDeps.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/lib/DependencyScan/DependencyScanningTool.cpp b/lib/DependencyScan/DependencyScanningTool.cpp index e70576ccadf4b..563f0a7fa3634 100644 --- a/lib/DependencyScan/DependencyScanningTool.cpp +++ b/lib/DependencyScan/DependencyScanningTool.cpp @@ -160,13 +160,13 @@ DependencyScanningTool::initScannerForAction( llvm::ErrorOr> DependencyScanningTool::initCompilerInstanceForScan( - ArrayRef Command) { + ArrayRef CommandArgs) { // State unique to an individual scan auto Instance = std::make_unique(); Instance->addDiagnosticConsumer(&PDC); // Basic error checking on the arguments - if (Command.empty()) { + if (CommandArgs.empty()) { Instance->getDiags().diagnose(SourceLoc(), diag::error_no_frontend_args); return std::make_error_code(std::errc::invalid_argument); } @@ -180,16 +180,7 @@ DependencyScanningTool::initCompilerInstanceForScan( // We must do so because LLVM options parsing is done using a managed // static `GlobalParser`. llvm::cl::ResetAllOptionOccurrences(); - - // Parse arguments. - std::string CommandString; - for (const auto *c : Command) { - CommandString.append(c); - CommandString.append(" "); - } - SmallVector Args; - llvm::cl::TokenizeGNUCommandLine(CommandString, Saver, Args); - if (Invocation.parseArgs(Args, Instance->getDiags())) { + if (Invocation.parseArgs(CommandArgs, Instance->getDiags())) { return std::make_error_code(std::errc::invalid_argument); } diff --git a/unittests/DependencyScan/ModuleDeps.cpp b/unittests/DependencyScan/ModuleDeps.cpp index 705df2c5caee2..3d49d2d6e4fbf 100644 --- a/unittests/DependencyScan/ModuleDeps.cpp +++ b/unittests/DependencyScan/ModuleDeps.cpp @@ -157,11 +157,11 @@ export *\n\ llvm::sys::path::append(StdLibDir, getPlatformNameForTriple(Target)); std::vector CommandStrArr = { - std::string("'") + TestPathStr + std::string("'"), - std::string("-I ") + std::string("'") + SwiftDirPath + std::string("'"), - std::string("-I ") + std::string("'") + CHeadersDirPath + std::string("'"), - std::string("-I ") + std::string("'") + StdLibDir.str().str() + std::string("'"), - std::string("-I ") + std::string("'") + ShimsLibDir.str().str() + std::string("'") + TestPathStr, + std::string("-I ") + SwiftDirPath, + std::string("-I ") + CHeadersDirPath, + std::string("-I ") + StdLibDir.str().str(), + std::string("-I ") + ShimsLibDir.str().str(), }; // On Windows we need to add an extra escape for path separator characters because otherwise From 51281c54c48d75f9e4a4376ef55f1557d7faa394 Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Tue, 19 Jul 2022 13:50:12 -0700 Subject: [PATCH 296/491] [CSBindings] Move binding printing out of determineBestBindings and check that bindings exist before printing. --- include/swift/Sema/ConstraintSystem.h | 5 ++++- lib/Sema/CSBindings.cpp | 7 +++---- lib/Sema/CSStep.cpp | 24 +++++++++++++++++++----- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 12457af2c1849..d10165bc78848 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -5557,7 +5557,10 @@ class ConstraintSystem { Type wrapperType, Type paramType, ParamDecl *param, Identifier argLabel, ConstraintKind matchKind, ConstraintLocatorBuilder locator); - Optional determineBestBindings(); + /// Determine whether given type variable with its set of bindings is viable + /// to be attempted on the next step of the solver. + Optional determineBestBindings( + llvm::function_ref onCandidate); /// Get bindings for the given type variable based on current /// state of the constraint system. diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index cf30d06e3418d..83d8da4ea9c0e 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -742,7 +742,8 @@ BindingSet::BindingScore BindingSet::formBindingScore(const BindingSet &b) { -numNonDefaultableBindings); } -Optional ConstraintSystem::determineBestBindings() { +Optional ConstraintSystem::determineBestBindings( + llvm::function_ref onCandidate) { // Look for potential type variable bindings. Optional bestBindings; llvm::SmallDenseMap cache; @@ -804,9 +805,7 @@ Optional ConstraintSystem::determineBestBindings() { if (!bindings || !isViable) continue; - if (isDebugMode()) { - bindings.dump(llvm::errs(), solverState->getCurrentIndent()); - } + onCandidate(bindings); // If these are the first bindings, or they are better than what // we saw before, use them instead. diff --git a/lib/Sema/CSStep.cpp b/lib/Sema/CSStep.cpp index b891ca3fd3748..00bc4a0b1ecf4 100644 --- a/lib/Sema/CSStep.cpp +++ b/lib/Sema/CSStep.cpp @@ -346,7 +346,15 @@ StepResult ComponentStep::take(bool prevFailed) { /// Try to figure out what this step is going to be, /// after the scope has been established. - auto bestBindings = CS.determineBestBindings(); + SmallString<64> potentialBindings; + llvm::raw_svector_ostream bos(potentialBindings); + + auto bestBindings = CS.determineBestBindings([&](const BindingSet &bindings) { + if (CS.isDebugMode() && bindings.hasViableBindings()) { + bindings.dump(bos, CS.solverState->getCurrentIndent() + 2); + } + }); + auto *disjunction = CS.selectDisjunction(); auto *conjunction = CS.selectConjunction(); @@ -354,22 +362,28 @@ StepResult ComponentStep::take(bool prevFailed) { PrintOptions PO; PO.PrintTypesForDebugging = true; + auto &log = getDebugLogger(); + if (!potentialBindings.empty()) { + log << "(Potential Binding(s): " << '\n'; + log << potentialBindings; + } + log.indent(CS.solverState->getCurrentIndent()); + if (disjunction) { - auto &log = getDebugLogger(); log.indent(2); log << "Disjunction(s) = ["; auto constraints = disjunction->getNestedConstraints(); log << constraints[0]->getFirstType()->getString(PO); - log << "])\n"; + log << "]"; } if (conjunction) { - auto &log = getDebugLogger(); log.indent(2); log << "Conjunction(s) = ["; auto constraints = conjunction->getNestedConstraints(); log << constraints[0]->getFirstType()->getString(PO); - log << "])\n"; + log << "]"; } + log << ")\n"; } if (CS.shouldAttemptFixes()) { From 6d55c5270bf36ac54b5432670d0bb4fbab8b95e1 Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Thu, 18 Aug 2022 18:58:12 -0700 Subject: [PATCH 297/491] [Test] Update failing test. --- test/Constraints/one_way_solve.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Constraints/one_way_solve.swift b/test/Constraints/one_way_solve.swift index a2f2272ec7955..f4239c75c9524 100644 --- a/test/Constraints/one_way_solve.swift +++ b/test/Constraints/one_way_solve.swift @@ -28,16 +28,16 @@ func testTernaryOneWayOverload(b: Bool) { // CHECK: 0: $T2 $T3 $T4 // CHECK: solving component #1 - // CHECK: Initial bindings: $T11 := Int8, $T11 := Int16 + // CHECK: (attempting type variable $T11 := Int8 // CHECK: solving component #1 - // CHECK: Initial bindings: $T11 := Int8, $T11 := Int16 + // CHECK: (attempting type variable $T11 := Int8 // CHECK: solving component #1 - // CHECK: Initial bindings: $T11 := Int8, $T11 := Int16 + // CHECK: (attempting type variable $T11 := Int8 // CHECK: solving component #1 - // CHECK: Initial bindings: $T11 := Int8 + // CHECK: (attempting type variable $T11 := Int8 // CHECK: (found solution: [non-default literal(s) = 2] [use of overloaded unapplied function(s) = 2]) // CHECK: (composed solution: [non-default literal(s) = 2] [use of overloaded unapplied function(s) = 2]) From b5066bbcaf31093c91479c38445f4b42430deb1d Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Mon, 22 Aug 2022 14:47:45 -0700 Subject: [PATCH 298/491] Sema: Check the availability of property wrappers attached to VarDecls in named patterns. The availability of property wrappers was previously checked for typed patterns but not named patterns. Resolves rdar://86698223. --- lib/Sema/TypeCheckAccess.cpp | 5 ++ test/Sema/property_wrapper_availability.swift | 78 +++++++++++++++++++ .../Sema/SwiftUI/radar88971160.swift | 1 + .../Sema/SwiftUI/rdar74447308.swift | 1 + 4 files changed, 85 insertions(+) create mode 100644 test/Sema/property_wrapper_availability.swift diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 99021c873ea1e..63b20316f4560 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -1683,6 +1683,11 @@ class DeclAvailabilityChecker : public DeclVisitor { return; checkType(theVar->getValueInterfaceType(), /*typeRepr*/nullptr, theVar); + + for (auto attr : theVar->getAttachedPropertyWrappers()) { + checkType(attr->getType(), attr->getTypeRepr(), theVar, + ExportabilityReason::PropertyWrapper); + } } /// \see visitPatternBindingDecl diff --git a/test/Sema/property_wrapper_availability.swift b/test/Sema/property_wrapper_availability.swift new file mode 100644 index 0000000000000..a284e0c5da6dd --- /dev/null +++ b/test/Sema/property_wrapper_availability.swift @@ -0,0 +1,78 @@ +// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.50 + +// REQUIRES: OS=macosx + +struct S {} + +@propertyWrapper +struct AlwaysAvailableWrapper { + var wrappedValue: T +} + +@available(macOS 10.51, *) +@propertyWrapper +struct Available10_51Wrapper { + var wrappedValue: T +} + +@available(*, unavailable) +@propertyWrapper +struct UnavailableWrapper { // expected-note 6 {{'UnavailableWrapper' has been explicitly marked unavailable here}} + var wrappedValue: T +} + + +struct AlwaysAvailableStruct { // expected-note 2 {{add @available attribute to enclosing struct}} + @AlwaysAvailableWrapper var alwaysAvailableExplicit: S + @AlwaysAvailableWrapper var alwaysAvailableInferred = S() + + @Available10_51Wrapper var available10_51Explicit: S // expected-error {{'Available10_51Wrapper' is only available in macOS 10.51 or newer}} + @Available10_51Wrapper var available10_51Inferred = S() // expected-error {{'Available10_51Wrapper' is only available in macOS 10.51 or newer}} + + @UnavailableWrapper var unavailableExplicit: S // expected-error {{'UnavailableWrapper' is unavailable}} + @UnavailableWrapper var unavailableInferred = S() // expected-error {{'UnavailableWrapper' is unavailable}} +} + +@available(macOS 10.51, *) +struct Available10_51Struct { + @AlwaysAvailableWrapper var alwaysAvailableExplicit: S + @AlwaysAvailableWrapper var alwaysAvailableInferred = S() + + @Available10_51Wrapper var available10_51Explicit: S + @Available10_51Wrapper var available10_51Inferred = S() + + @UnavailableWrapper var unavailableExplicit: S // expected-error {{'UnavailableWrapper' is unavailable}} + @UnavailableWrapper var unavailableInferred = S() // expected-error {{'UnavailableWrapper' is unavailable}} +} + +@available(*, unavailable) +struct UnavailableStruct { + @AlwaysAvailableWrapper var alwaysAvailableExplicit: S + @AlwaysAvailableWrapper var alwaysAvailableInferred = S() + + @Available10_51Wrapper var available10_51Explicit: S // expected-error {{'Available10_51Wrapper' is only available in macOS 10.51 or newer}} + @Available10_51Wrapper var available10_51Inferred = S() // expected-error {{'Available10_51Wrapper' is only available in macOS 10.51 or newer}} + + @UnavailableWrapper var unavailableExplicit: S + @UnavailableWrapper var unavailableInferred = S() +} + +func alwaysAvailableFunc( // expected-note {{add @available attribute to enclosing global function}} + @AlwaysAvailableWrapper _ alwaysAvailable: S, + @Available10_51Wrapper _ available10_51: S, // expected-error {{'Available10_51Wrapper' is only available in macOS 10.51 or newer}} + @UnavailableWrapper _ unavailable: S // expected-error {{'UnavailableWrapper' is unavailable}} +) {} + +@available(macOS 10.51, *) +func available10_51Func( + @AlwaysAvailableWrapper _ alwaysAvailable: S, + @Available10_51Wrapper _ available10_51: S, + @UnavailableWrapper _ unavailable: S // expected-error {{'UnavailableWrapper' is unavailable}} +) {} + +@available(*, unavailable) +func unavailableFunc( + @AlwaysAvailableWrapper _ alwaysAvailable: S, + @Available10_51Wrapper _ available10_51: S, + @UnavailableWrapper _ unavailable: S +) {} diff --git a/validation-test/Sema/SwiftUI/radar88971160.swift b/validation-test/Sema/SwiftUI/radar88971160.swift index 4f78c8b1bab6d..cce09e2707ee3 100644 --- a/validation-test/Sema/SwiftUI/radar88971160.swift +++ b/validation-test/Sema/SwiftUI/radar88971160.swift @@ -7,6 +7,7 @@ import SwiftUI @MainActor class ContentState: ObservableObject { } +@available(SwiftStdlib 5.3, *) struct SomeView: View { @StateObject private var contentState = ContentState() diff --git a/validation-test/Sema/SwiftUI/rdar74447308.swift b/validation-test/Sema/SwiftUI/rdar74447308.swift index cc95f373d1395..ee1601eb79e7b 100644 --- a/validation-test/Sema/SwiftUI/rdar74447308.swift +++ b/validation-test/Sema/SwiftUI/rdar74447308.swift @@ -14,6 +14,7 @@ class ItemList: ObservableObject { @Published var items = [Item]() } +@available(SwiftStdlib 5.3, *) struct ContentView: View { @StateObject var list = ItemList() From 66a994baa9995978bd40341c5d548b64fac671b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Mon, 22 Aug 2022 17:08:56 -0700 Subject: [PATCH 299/491] [Sema] Insert missing imports from any non-API modules We can insert imports to any module from a source file that's part of a non-API module without risking breaking the public swiftinterface. --- lib/AST/Module.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index dd927a9ca39bc..de31fcb67657b 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -2547,7 +2547,8 @@ RestrictedImportKind SourceFile::getRestrictedImportKind(const ModuleDecl *modul return RestrictedImportKind::None; if (importKind == RestrictedImportKind::Implicit && - module->getLibraryLevel() == LibraryLevel::API) { + (module->getLibraryLevel() == LibraryLevel::API || + getParentModule()->getLibraryLevel() != LibraryLevel::API)) { // Hack to fix swiftinterfaces in case of missing imports. // We can get rid of this logic when we don't leak the use of non-locally // imported things in API. From 7361639a853bf256d784def4c496a43f7057e30f Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Mon, 22 Aug 2022 12:10:12 -0700 Subject: [PATCH 300/491] [move-only] Add support for explicit_copy_addr in a few places in MemAccessUtils that I missed when introducing the instruction. I discovered these were missing when using explicit_copy_addr with the move only address checker. --- lib/SIL/Utils/MemAccessUtils.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/SIL/Utils/MemAccessUtils.cpp b/lib/SIL/Utils/MemAccessUtils.cpp index b67e8b281b78c..ddd1d46611e97 100644 --- a/lib/SIL/Utils/MemAccessUtils.cpp +++ b/lib/SIL/Utils/MemAccessUtils.cpp @@ -2108,6 +2108,7 @@ bool GatherUniqueStorageUses::visitUse(Operand *use, AccessUseType useTy) { case SILInstructionKind::InjectEnumAddrInst: return visitor.visitStore(use); + case SILInstructionKind::ExplicitCopyAddrInst: case SILInstructionKind::CopyAddrInst: if (operIdx == CopyLikeInstruction::Dest) { return visitor.visitStore(use); @@ -2146,6 +2147,10 @@ bool swift::memInstMustInitialize(Operand *memOper) { auto *CAI = cast(memInst); return CAI->getDest() == address && CAI->isInitializationOfDest(); } + case SILInstructionKind::ExplicitCopyAddrInst: { + auto *CAI = cast(memInst); + return CAI->getDest() == address && CAI->isInitializationOfDest(); + } case SILInstructionKind::MarkUnresolvedMoveAddrInst: { return cast(memInst)->getDest() == address; } @@ -2594,6 +2599,11 @@ void swift::visitAccessedAddress(SILInstruction *I, visitor(&I->getAllOperands()[CopyAddrInst::Dest]); return; + case SILInstructionKind::ExplicitCopyAddrInst: + visitor(&I->getAllOperands()[ExplicitCopyAddrInst::Src]); + visitor(&I->getAllOperands()[ExplicitCopyAddrInst::Dest]); + return; + case SILInstructionKind::MarkUnresolvedMoveAddrInst: visitor(&I->getAllOperands()[MarkUnresolvedMoveAddrInst::Src]); visitor(&I->getAllOperands()[MarkUnresolvedMoveAddrInst::Dest]); From 9d22ef0787f719168fca77ca83c9232a4ebc448b Mon Sep 17 00:00:00 2001 From: Angela Laar Date: Mon, 22 Aug 2022 20:12:18 -0700 Subject: [PATCH 301/491] [Sema] The property wrapper missing wrappedValue check should add fixit on a new line --- lib/Sema/TypeCheckPropertyWrapper.cpp | 2 +- test/decl/var/property_wrappers.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Sema/TypeCheckPropertyWrapper.cpp b/lib/Sema/TypeCheckPropertyWrapper.cpp index 4a785cea83b25..080f971e66ba3 100644 --- a/lib/Sema/TypeCheckPropertyWrapper.cpp +++ b/lib/Sema/TypeCheckPropertyWrapper.cpp @@ -58,7 +58,7 @@ static VarDecl *findValueProperty(ASTContext &ctx, NominalTypeDecl *nominal, auto fixitLocation = nominal->getBraces().Start; nominal->diagnose(diag::property_wrapper_no_value_property, nominal->getDeclaredType(), name) - .fixItInsertAfter(fixitLocation, fixIt); + .fixItInsertAfter(fixitLocation, "\n"+fixIt); } return nullptr; diff --git a/test/decl/var/property_wrappers.swift b/test/decl/var/property_wrappers.swift index 668a24f97d465..86bf544ec58e3 100644 --- a/test/decl/var/property_wrappers.swift +++ b/test/decl/var/property_wrappers.swift @@ -58,13 +58,13 @@ struct WrapperAcceptingAutoclosure { @propertyWrapper struct MissingValue { } -// expected-error@-1{{property wrapper type 'MissingValue' does not contain a non-static property named 'wrappedValue'}} {{educational-notes=property-wrapper-requirements}}{{25-25=var wrappedValue: <#Value#>}} +// expected-error@-1{{property wrapper type 'MissingValue' does not contain a non-static property named 'wrappedValue'}} {{educational-notes=property-wrapper-requirements}}{{25-25=\nvar wrappedValue: <#Value#>}} @propertyWrapper struct StaticValue { static var wrappedValue: Int = 17 } -// expected-error@-3{{property wrapper type 'StaticValue' does not contain a non-static property named 'wrappedValue'}}{{21-21=var wrappedValue: <#Value#>}} +// expected-error@-3{{property wrapper type 'StaticValue' does not contain a non-static property named 'wrappedValue'}}{{21-21=\nvar wrappedValue: <#Value#>}} // expected-error@+1{{'@propertyWrapper' attribute cannot be applied to this declaration}} From f0907d3e105d522e60f7e9f2f81c17aed07210b9 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:29:57 -0400 Subject: [PATCH 302/491] APIDigester: Stop calling getAllConformances() on protocols --- lib/APIDigester/ModuleAnalyzerNodes.cpp | 51 ++++++++++++++++--------- test/api-digester/Outputs/cake-abi.json | 14 +++---- test/api-digester/Outputs/cake.json | 14 +++---- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/lib/APIDigester/ModuleAnalyzerNodes.cpp b/lib/APIDigester/ModuleAnalyzerNodes.cpp index a6612e0076639..ed3b9dd75ea63 100644 --- a/lib/APIDigester/ModuleAnalyzerNodes.cpp +++ b/lib/APIDigester/ModuleAnalyzerNodes.cpp @@ -50,7 +50,7 @@ struct swift::ide::api::SDKNodeInitInfo { SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD); SDKNodeInitInfo(SDKContext &Ctx, OperatorDecl *D); SDKNodeInitInfo(SDKContext &Ctx, ImportDecl *ID); - SDKNodeInitInfo(SDKContext &Ctx, ProtocolConformance *Conform); + SDKNodeInitInfo(SDKContext &Ctx, ProtocolConformanceRef Conform); SDKNodeInitInfo(SDKContext &Ctx, Type Ty, TypeInitInfo Info = TypeInitInfo()); SDKNode* createSDKNode(SDKNodeKind Kind); }; @@ -1459,17 +1459,21 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ImportDecl *ID): Name = PrintedName = Ctx.buffer(content); } -SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ProtocolConformance *Conform): - SDKNodeInitInfo(Ctx, Conform->getProtocol()) { +SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ProtocolConformanceRef Conform): + SDKNodeInitInfo(Ctx, Conform.getRequirement()) { // The conformance can be conditional. The generic signature keeps track of // the requirements. - GenericSig = printGenericSignature(Ctx, Conform, Ctx.checkingABI()); - SugaredGenericSig = Ctx.checkingABI() ? - printGenericSignature(Ctx, Conform, false): StringRef(); - // Whether this conformance is ABI placeholder depends on the decl context - // of this conformance. - IsABIPlaceholder = isABIPlaceholderRecursive(Conform->getDeclContext()-> - getAsDecl()); + if (Conform.isConcrete()) { + auto *Concrete = Conform.getConcrete(); + + GenericSig = printGenericSignature(Ctx, Concrete, Ctx.checkingABI()); + SugaredGenericSig = Ctx.checkingABI() ? + printGenericSignature(Ctx, Concrete, false): StringRef(); + // Whether this conformance is ABI placeholder depends on the decl context + // of this conformance. + IsABIPlaceholder = isABIPlaceholderRecursive(Concrete->getDeclContext()-> + getAsDecl()); + } } static bool isProtocolRequirement(ValueDecl *VD) { @@ -1910,7 +1914,7 @@ SwiftDeclCollector::constructConformanceNode(ProtocolConformance *Conform) { if (Ctx.checkingABI()) Conform = Conform->getCanonicalConformance(); auto ConfNode = cast(SDKNodeInitInfo(Ctx, - Conform).createSDKNode(SDKNodeKind::Conformance)); + ProtocolConformanceRef(Conform)).createSDKNode(SDKNodeKind::Conformance)); Conform->forEachTypeWitness( [&](AssociatedTypeDecl *assoc, Type ty, TypeDecl *typeDecl) -> bool { ConfNode->addChild(constructTypeWitnessNode(assoc, ty)); @@ -1922,12 +1926,25 @@ SwiftDeclCollector::constructConformanceNode(ProtocolConformance *Conform) { void swift::ide::api:: SwiftDeclCollector::addConformancesToTypeDecl(SDKNodeDeclType *Root, NominalTypeDecl *NTD) { - // Avoid adding the same conformance twice. - SmallPtrSet Seen; - for (auto &Conf: NTD->getAllConformances()) { - if (!Ctx.shouldIgnore(Conf->getProtocol()) && !Seen.count(Conf)) - Root->addConformance(constructConformanceNode(Conf)); - Seen.insert(Conf); + if (auto *PD = dyn_cast(NTD)) { + PD->walkInheritedProtocols([&](ProtocolDecl *inherited) { + if (PD != inherited && !Ctx.shouldIgnore(inherited)) { + ProtocolConformanceRef Conf(inherited); + auto ConfNode = SDKNodeInitInfo(Ctx, Conf) + .createSDKNode(SDKNodeKind::Conformance); + Root->addConformance(ConfNode); + } + + return TypeWalker::Action::Continue; + }); + } else { + // Avoid adding the same conformance twice. + SmallPtrSet Seen; + for (auto &Conf: NTD->getAllConformances()) { + if (!Ctx.shouldIgnore(Conf->getProtocol()) && !Seen.count(Conf)) + Root->addConformance(constructConformanceNode(Conf)); + Seen.insert(Conf); + } } } diff --git a/test/api-digester/Outputs/cake-abi.json b/test/api-digester/Outputs/cake-abi.json index e3faa96fe7851..da16ab123132b 100644 --- a/test/api-digester/Outputs/cake-abi.json +++ b/test/api-digester/Outputs/cake-abi.json @@ -100,19 +100,19 @@ "genericSig": "<Ï„_0_0 : cake.P1, Ï„_0_0 : cake.P2>", "sugared_genericSig": "", "conformances": [ - { - "kind": "Conformance", - "name": "P2", - "printedName": "P2", - "usr": "s:4cake2P2P", - "mangledName": "$s4cake2P2P" - }, { "kind": "Conformance", "name": "P1", "printedName": "P1", "usr": "s:4cake2P1P", "mangledName": "$s4cake2P1P" + }, + { + "kind": "Conformance", + "name": "P2", + "printedName": "P2", + "usr": "s:4cake2P2P", + "mangledName": "$s4cake2P2P" } ] }, diff --git a/test/api-digester/Outputs/cake.json b/test/api-digester/Outputs/cake.json index 539fc48bb7029..5f9b18a5266e7 100644 --- a/test/api-digester/Outputs/cake.json +++ b/test/api-digester/Outputs/cake.json @@ -98,19 +98,19 @@ "moduleName": "cake", "genericSig": "", "conformances": [ - { - "kind": "Conformance", - "name": "P2", - "printedName": "P2", - "usr": "s:4cake2P2P", - "mangledName": "$s4cake2P2P" - }, { "kind": "Conformance", "name": "P1", "printedName": "P1", "usr": "s:4cake2P1P", "mangledName": "$s4cake2P1P" + }, + { + "kind": "Conformance", + "name": "P2", + "printedName": "P2", + "usr": "s:4cake2P2P", + "mangledName": "$s4cake2P2P" } ] }, From d9a3f2e5ce29cc5e1fe2faf247000bbd67daef36 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:30:30 -0400 Subject: [PATCH 303/491] AST: Stop calling getAllConformances() on protocols --- lib/AST/ASTPrinter.cpp | 10 ++++++---- lib/AST/ConformanceLookupTable.cpp | 14 ++++---------- lib/AST/NameLookup.cpp | 15 +++++++++++---- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 268dc6885666e..9e121cc4db6a4 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -2314,10 +2314,12 @@ void PrintAST::printMembersOfDecl(Decl *D, bool needComma, AddMembers(Ext); } if (Options.PrintExtensionFromConformingProtocols) { - for (auto Conf : NTD->getAllConformances()) { - for (auto Ext : Conf->getProtocol()->getExtensions()) { - if (Options.printExtensionContentAsMembers(Ext)) - AddMembers(Ext); + if (!isa(NTD)) { + for (auto Conf : NTD->getAllConformances()) { + for (auto Ext : Conf->getProtocol()->getExtensions()) { + if (Options.printExtensionContentAsMembers(Ext)) + AddMembers(Ext); + } } } } diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp index 5e376ce84331a..6ff952da6af94 100644 --- a/lib/AST/ConformanceLookupTable.cpp +++ b/lib/AST/ConformanceLookupTable.cpp @@ -620,20 +620,14 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances( // If the explicit protocol for the left-hand side is implied by // the explicit protocol for the right-hand side, the left-hand // side supersedes the right-hand side. - for (auto rhsProtocol : rhsExplicitProtocol->getAllProtocols()) { - if (rhsProtocol == lhsExplicitProtocol) { - return Ordering::Before; - } - } + if (rhsExplicitProtocol->inheritsFrom(lhsExplicitProtocol)) + return Ordering::Before; // If the explicit protocol for the right-hand side is implied by // the explicit protocol for the left-hand side, the right-hand // side supersedes the left-hand side. - for (auto lhsProtocol : lhsExplicitProtocol->getAllProtocols()) { - if (lhsProtocol == rhsExplicitProtocol) { - return Ordering::After; - } - } + if (lhsExplicitProtocol->inheritsFrom(rhsExplicitProtocol)) + return Ordering::After; } // Prefer the least conditional implier, which we approximate by seeing if one diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 51229134389e5..3decda3919073 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -3121,10 +3121,17 @@ static bool checkForDynamicAttribute(Evaluator &eval, NominalTypeDecl *decl) { return evaluateOrDefault(eval, Req{decl}, false); }; - // Check the protocols the type conforms to. - for (auto *proto : decl->getAllProtocols()) { - if (hasAttribute(proto)) - return true; + if (auto *proto = dyn_cast(decl)) { + // Check inherited protocols of a protocol. + for (auto *otherProto : proto->getInheritedProtocols()) + if (hasAttribute(otherProto)) + return true; + } else { + // Check the protocols the type conforms to. + for (auto *otherProto : decl->getAllProtocols()) { + if (hasAttribute(otherProto)) + return true; + } } // Check the superclass if present. From 82bd81e127ab61e4eb515c7c72e6ee9b088169f1 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:31:10 -0400 Subject: [PATCH 304/491] ClangImporter: Stop calling getAllConformances() on protocols --- lib/ClangImporter/ImportDecl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index a33dfa4258f82..b2244a5f10bc9 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -6598,8 +6598,8 @@ void SwiftDeclConverter::importObjCProtocols( SmallVectorImpl &inheritedTypes) { SmallVector protocols; llvm::SmallPtrSet knownProtocols; - if (auto nominal = dyn_cast(decl)) { - nominal->getImplicitProtocols(protocols); + if (auto classDecl = dyn_cast(decl)) { + classDecl->getImplicitProtocols(protocols); knownProtocols.insert(protocols.begin(), protocols.end()); } From ecc552f8d71a8358528af881def7791056c645f8 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:31:31 -0400 Subject: [PATCH 305/491] ConstExtract: Stop calling getAllConformances() on protocols --- lib/ConstExtract/ConstExtract.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index 0da5503d23583..93881fd061e38 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -26,24 +26,27 @@ #include #include +using namespace swift; + namespace { /// A helper class to collect all nominal type declarations that conform to /// specific protocols provided as input. -class NominalTypeConformanceCollector : public swift::ASTWalker { +class NominalTypeConformanceCollector : public ASTWalker { const std::unordered_set &Protocols; - std::vector &ConformanceTypeDecls; + std::vector &ConformanceTypeDecls; public: NominalTypeConformanceCollector( const std::unordered_set &Protocols, - std::vector &ConformanceDecls) + std::vector &ConformanceDecls) : Protocols(Protocols), ConformanceTypeDecls(ConformanceDecls) {} - bool walkToDeclPre(swift::Decl *D) override { - if (auto *NTD = llvm::dyn_cast(D)) - for (auto &Protocol : NTD->getAllProtocols()) - if (Protocols.count(Protocol->getName().str().str()) != 0) - ConformanceTypeDecls.push_back(NTD); + bool walkToDeclPre(Decl *D) override { + if (auto *NTD = llvm::dyn_cast(D)) + if (!isa(NTD)) + for (auto &Protocol : NTD->getAllProtocols()) + if (Protocols.count(Protocol->getName().str().str()) != 0) + ConformanceTypeDecls.push_back(NTD); return true; } }; From b254dc2141dadbe6223db8bda0b2e4e9ab3fd702 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:32:02 -0400 Subject: [PATCH 306/491] PrintAsClang: Stop calling getAllConformances() on protocols --- lib/PrintAsClang/DeclAndTypePrinter.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 6ffcc26596fae..bd762641e9207 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -1742,6 +1742,9 @@ class DeclAndTypePrinter::Implementation if (nominal->hasClangNode()) return nullptr; + if (isa(nominal)) + return nullptr; + auto &ctx = nominal->getASTContext(); // Dig out the ObjectiveCBridgeable protocol. From e8dc19a70b96a0bfac1ccbae92651e34bdf7065c Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:32:28 -0400 Subject: [PATCH 307/491] Sema: Stop calling getAllConformances() on protocols --- lib/Sema/CSSimplify.cpp | 12 ++++-------- lib/Sema/ConstraintSystem.cpp | 13 ++++--------- lib/Sema/TypeCheckAttr.cpp | 22 +++++++++++++++------- lib/Sema/TypeCheckProtocol.cpp | 2 ++ lib/Sema/TypeCheckStmt.cpp | 3 +-- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 8c1fa9a1d926e..46d60899fef41 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -8093,16 +8093,12 @@ allFromConditionalConformances(DeclContext *DC, Type baseTy, } if (auto *protocol = candidateDC->getSelfProtocolDecl()) { - SmallVector conformances; - if (!NTD->lookupConformance(protocol, conformances)) + auto conformance = DC->getParentModule()->lookupConformance( + baseTy, protocol); + if (!conformance.isConcrete()) return false; - // This is opportunistic, there should be a way to narrow the - // list down to a particular declaration member comes from. - return llvm::any_of( - conformances, [](const ProtocolConformance *conformance) { - return !conformance->getConditionalRequirements().empty(); - }); + return !conformance.getConcrete()->getConditionalRequirements().empty(); } return false; diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index a675f32f7849d..d571c2461e4fe 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -6947,15 +6947,10 @@ bool TypeVarBindingProducer::requiresOptionalAdjustment( // produce an optional of that type as a potential binding. We // overwrite the binding in place because the non-optional type // will fail to type-check against the nil-literal conformance. - bool conformsToExprByNilLiteral = false; - if (auto *nominalBindingDecl = type->getAnyNominal()) { - SmallVector conformances; - conformsToExprByNilLiteral = nominalBindingDecl->lookupConformance( - CS.getASTContext().getProtocol( - KnownProtocolKind::ExpressibleByNilLiteral), - conformances); - } - return !conformsToExprByNilLiteral; + auto *proto = CS.getASTContext().getProtocol( + KnownProtocolKind::ExpressibleByNilLiteral); + + return !proto->getParentModule()->lookupConformance(type, proto); } else if (binding.isDefaultableBinding() && binding.BindingType->isAny()) { return true; } diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 9f6ad5b8397c0..48421c9cd73e4 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -3306,14 +3306,22 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) { // Check that the decl we're decorating is a member of a type that actually // conforms to the specified protocol. NominalTypeDecl *NTD = DC->getSelfNominalTypeDecl(); - SmallVector conformances; - if (!NTD->lookupConformance(PD, conformances)) { - diagnose(attr->getLocation(), - diag::implements_attr_protocol_not_conformed_to, - NTD->getName(), PD->getName()) - .highlight(attr->getProtocolTypeRepr()->getSourceRange()); + if (auto *OtherPD = dyn_cast(NTD)) { + if (!OtherPD->inheritsFrom(PD)) { + diagnose(attr->getLocation(), + diag::implements_attr_protocol_not_conformed_to, + NTD->getName(), PD->getName()) + .highlight(attr->getProtocolTypeRepr()->getSourceRange()); + } + } else { + SmallVector conformances; + if (!NTD->lookupConformance(PD, conformances)) { + diagnose(attr->getLocation(), + diag::implements_attr_protocol_not_conformed_to, + NTD->getName(), PD->getName()) + .highlight(attr->getProtocolTypeRepr()->getSourceRange()); + } } - } else { diagnose(attr->getLocation(), diag::implements_attr_non_protocol_type) .highlight(attr->getProtocolTypeRepr()->getSourceRange()); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 29eec6c8160de..057293663a943 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -6762,7 +6762,9 @@ swift::findWitnessedObjCRequirements(const ValueDecl *witness, auto dc = witness->getDeclContext(); auto nominal = dc->getSelfNominalTypeDecl(); + if (!nominal) return result; + if (isa(nominal)) return result; DeclName name = witness->getName(); Optional accessorKind; diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 1ca79c1845d58..8126c3806d9bf 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -229,8 +229,7 @@ static void tryDiagnoseUnnecessaryCastOverOptionSet(ASTContext &Ctx, auto optionSetType = dyn_cast_or_null(Ctx.getOptionSetDecl()); if (!optionSetType) return; - SmallVector conformances; - if (!(optionSetType && NTD->lookupConformance(optionSetType, conformances))) + if (!module->lookupConformance(ResultType, optionSetType)) return; auto *CE = dyn_cast(E); From 701f782a2bbc45ea5a809878735f75d2d5770040 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:32:38 -0400 Subject: [PATCH 308/491] SILOptimizer: Stop calling getAllConformances() on protocols --- .../Analysis/ProtocolConformanceAnalysis.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/SILOptimizer/Analysis/ProtocolConformanceAnalysis.cpp b/lib/SILOptimizer/Analysis/ProtocolConformanceAnalysis.cpp index 9a6bee3b9cee9..9342baec7d78b 100644 --- a/lib/SILOptimizer/Analysis/ProtocolConformanceAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/ProtocolConformanceAnalysis.cpp @@ -37,10 +37,12 @@ class NominalTypeWalker : public ASTWalker { bool walkToDeclPre(Decl *D) override { /// (1) Walk over all NominalTypeDecls to determine conformances. if (auto *NTD = dyn_cast(D)) { - auto Protocols = NTD->getAllProtocols(); - for (auto &Protocol : Protocols) { - if (Protocol->getEffectiveAccess() <= AccessLevel::Internal) { - ProtocolConformanceCache[Protocol].push_back(NTD); + if (!isa(NTD)) { + auto Protocols = NTD->getAllProtocols(); + for (auto &Protocol : Protocols) { + if (Protocol->getEffectiveAccess() <= AccessLevel::Internal) { + ProtocolConformanceCache[Protocol].push_back(NTD); + } } } } From eb77da1ca34303c1eb1b26674049f09e50ea0fbd Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:32:48 -0400 Subject: [PATCH 309/491] SymbolGraph: Stop calling getAllConformances() on protocols --- lib/SymbolGraphGen/SymbolGraph.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/SymbolGraphGen/SymbolGraph.cpp b/lib/SymbolGraphGen/SymbolGraph.cpp index bed736aac1953..7103341fecf52 100644 --- a/lib/SymbolGraphGen/SymbolGraph.cpp +++ b/lib/SymbolGraphGen/SymbolGraph.cpp @@ -448,11 +448,24 @@ void SymbolGraph::recordConformanceRelationships(Symbol S) { const auto VD = S.getSymbolDecl(); if (const auto *NTD = dyn_cast(VD)) { - for (const auto *Conformance : NTD->getAllConformances()) { - recordEdge(Symbol(this, VD, nullptr), - Symbol(this, Conformance->getProtocol(), nullptr), - RelationshipKind::ConformsTo(), - dyn_cast_or_null(Conformance->getDeclContext())); + if (auto *PD = dyn_cast(NTD)) { + PD->walkInheritedProtocols([&](ProtocolDecl *inherited) { + if (inherited != PD) { + recordEdge(Symbol(this, VD, nullptr), + Symbol(this, inherited, nullptr), + RelationshipKind::ConformsTo(), + nullptr); + } + + return TypeWalker::Action::Continue; + }); + } else { + for (const auto *Conformance : NTD->getAllConformances()) { + recordEdge(Symbol(this, VD, nullptr), + Symbol(this, Conformance->getProtocol(), nullptr), + RelationshipKind::ConformsTo(), + dyn_cast_or_null(Conformance->getDeclContext())); + } } } } From e307860d73aa5d81d7608caaf790b8ef11439897 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 20:03:48 -0400 Subject: [PATCH 310/491] IDE: Stop calling getAllConformances() on protocols --- lib/IDE/CodeCompletionResultType.cpp | 53 +++++++++++++++++----------- lib/IDE/CompletionLookup.cpp | 7 ++-- lib/IDE/CompletionOverrideLookup.cpp | 3 ++ 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/lib/IDE/CodeCompletionResultType.cpp b/lib/IDE/CodeCompletionResultType.cpp index 918a7736cac03..908e2b8fac58f 100644 --- a/lib/IDE/CodeCompletionResultType.cpp +++ b/lib/IDE/CodeCompletionResultType.cpp @@ -208,32 +208,45 @@ const USRBasedType *USRBasedType::fromType(Type Ty, USRBasedTypeArena &Arena) { } SmallVector Supertypes; + ; if (auto Nominal = Ty->getAnyNominal()) { - auto Conformances = Nominal->getAllConformances(); - Supertypes.reserve(Conformances.size()); - for (auto Conformance : Conformances) { - if (Conformance->getDeclContext()->getParentModule() != - Nominal->getModuleContext()) { - // Only include conformances that are declared within the module of the - // type to avoid caching retroactive conformances which might not - // exist when using the code completion cache from a different module. - continue; - } - if (Conformance->getProtocol()->isSpecificProtocol(KnownProtocolKind::Sendable)) { - // FIXME: Sendable conformances are lazily synthesized as they are - // needed by the compiler. Depending on whether we checked whether a - // type conforms to Sendable before constructing the USRBasedType, we - // get different results for its conformance. For now, always drop the - // Sendable conformance. - continue; + if (auto *Proto = dyn_cast(Nominal)) { + Proto->walkInheritedProtocols([&](ProtocolDecl *inherited) { + if (Proto != inherited && + !inherited->isSpecificProtocol(KnownProtocolKind::Sendable)) { + Supertypes.push_back(USRBasedType::fromType( + inherited->getDeclaredInterfaceType(), Arena)); + } + + return TypeWalker::Action::Continue; + }); + } else { + auto Conformances = Nominal->getAllConformances(); + Supertypes.reserve(Conformances.size()); + for (auto Conformance : Conformances) { + if (Conformance->getDeclContext()->getParentModule() != + Nominal->getModuleContext()) { + // Only include conformances that are declared within the module of the + // type to avoid caching retroactive conformances which might not + // exist when using the code completion cache from a different module. + continue; + } + if (Conformance->getProtocol()->isSpecificProtocol(KnownProtocolKind::Sendable)) { + // FIXME: Sendable conformances are lazily synthesized as they are + // needed by the compiler. Depending on whether we checked whether a + // type conforms to Sendable before constructing the USRBasedType, we + // get different results for its conformance. For now, always drop the + // Sendable conformance. + continue; + } + Supertypes.push_back(USRBasedType::fromType( + Conformance->getProtocol()->getDeclaredInterfaceType(), Arena)); } - Supertypes.push_back(USRBasedType::fromType( - Conformance->getProtocol()->getDeclaredInterfaceType(), Arena)); } } // You would think that superclass + conformances form a DAG. You are wrong! - // We can achieve a circular supertype hierarcy with + // We can achieve a circular supertype hierarchy with // // protocol Proto : Class {} // class Class : Proto {} diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index 7399616826be9..061196f47dc46 100644 --- a/lib/IDE/CompletionLookup.cpp +++ b/lib/IDE/CompletionLookup.cpp @@ -2483,7 +2483,7 @@ void CompletionLookup::addTypeRelationFromProtocol( // The literal can produce any type that conforms to its ExpressibleBy // protocol. Figure out as which type we want to show it in code completion. - auto *P = Ctx.getProtocol(protocolForLiteralKind(kind)); + auto *PD = Ctx.getProtocol(protocolForLiteralKind(kind)); for (auto T : expectedTypeContext.getPossibleTypes()) { if (!T) continue; @@ -2497,9 +2497,8 @@ void CompletionLookup::addTypeRelationFromProtocol( } // Check for conformance to the literal protocol. - if (auto *NTD = T->getAnyNominal()) { - SmallVector conformances; - if (NTD->lookupConformance(P, conformances)) { + if (T->getAnyNominal()) { + if (CurrModule->lookupConformance(T, PD)) { literalType = T; break; } diff --git a/lib/IDE/CompletionOverrideLookup.cpp b/lib/IDE/CompletionOverrideLookup.cpp index 4c5862f176684..a3a212e2179eb 100644 --- a/lib/IDE/CompletionOverrideLookup.cpp +++ b/lib/IDE/CompletionOverrideLookup.cpp @@ -411,6 +411,9 @@ void CompletionOverrideLookup::addAssociatedTypes(NominalTypeDecl *NTD) { hasOverride || hasOverridabilityModifier || hasStaticOrClass)) return; + if (isa(NTD)) + return; + for (auto Conformance : NTD->getAllConformances()) { auto Proto = Conformance->getProtocol(); if (!Proto->isAccessibleFrom(CurrDeclContext)) From 9d090a5fd37d96fce1bd1cbc91bb08e28d448b77 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 311/491] AST: The conforming type of a normal conformance should be the self, not declared, interface type Builtin.TheTupleType's self interface type is (T...), and the declared interface type is the non-substitutable Builtin.TheTupleType. --- lib/AST/ConformanceLookupTable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp index 6ff952da6af94..df59e3a0afd99 100644 --- a/lib/AST/ConformanceLookupTable.cpp +++ b/lib/AST/ConformanceLookupTable.cpp @@ -875,7 +875,7 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal, ctx.getInheritedConformance(type, inheritedConformance.getConcrete()); } else { // Create or find the normal conformance. - Type conformingType = conformingDC->getDeclaredInterfaceType(); + Type conformingType = conformingDC->getSelfInterfaceType(); SourceLoc conformanceLoc = conformingNominal == conformingDC ? conformingNominal->getLoc() From 50aaaa4b117abc88fec8fcdbadaac8b83b5e5d17 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 19:33:54 -0400 Subject: [PATCH 312/491] AST: Assert if attempting to do conformance lookup table things on a protocol Unlike structs, enums and classes, protocols should not have a conformance lookup table with normal conformances in it. --- lib/AST/ConformanceLookupTable.cpp | 7 ++++++- lib/AST/ProtocolConformance.cpp | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp index df59e3a0afd99..68c4343207ced 100644 --- a/lib/AST/ConformanceLookupTable.cpp +++ b/lib/AST/ConformanceLookupTable.cpp @@ -874,13 +874,18 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal, entry->Conformance = ctx.getInheritedConformance(type, inheritedConformance.getConcrete()); } else { - // Create or find the normal conformance. + // Protocols don't have conformance lookup tables. Self-conformance is + // handled directly in lookupConformance(). + assert(!isa(conformingNominal)); + assert(!isa(conformingDC->getSelfNominalTypeDecl())); Type conformingType = conformingDC->getSelfInterfaceType(); + SourceLoc conformanceLoc = conformingNominal == conformingDC ? conformingNominal->getLoc() : cast(conformingDC)->getLoc(); + // Create or find the normal conformance. auto normalConf = ctx.getConformance(conformingType, protocol, conformanceLoc, conformingDC, ProtocolConformanceState::Incomplete, diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index 24240be911018..76b79a2a32643 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -1224,6 +1224,9 @@ ProtocolConformance::getInheritedConformance(ProtocolDecl *protocol) const { #pragma mark Protocol conformance lookup void NominalTypeDecl::prepareConformanceTable() const { + assert(!isa(this) && + "Protocols don't have a conformance table"); + if (ConformanceTable) return; @@ -1292,6 +1295,10 @@ void NominalTypeDecl::prepareConformanceTable() const { bool NominalTypeDecl::lookupConformance( ProtocolDecl *protocol, SmallVectorImpl &conformances) const { + assert(!isa(this) && + "Self-conformances are only found by the higher-level " + "ModuleDecl::lookupConformance() entry point"); + prepareConformanceTable(); return ConformanceTable->lookupConformance( const_cast(this), @@ -1301,6 +1308,10 @@ bool NominalTypeDecl::lookupConformance( SmallVector NominalTypeDecl::getAllProtocols(bool sorted) const { + assert(!isa(this) && + "For inherited protocols, use ProtocolDecl::inheritsFrom() or " + "ProtocolDecl::getInheritedProtocols()"); + prepareConformanceTable(); SmallVector result; ConformanceTable->getAllProtocols(const_cast(this), result, From 28e1c304cf9e4d12d7ec44d4d78d7af9f8d70c0b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 22 Aug 2022 21:45:25 -0700 Subject: [PATCH 313/491] Allow declaration recovery to consume attributes. Fixes https://github.com/apple/swift/issues/60702 / rdar://98967894 --- include/swift/Parse/Parser.h | 2 +- .../compiler_crashers_2_fixed/0213-issue60702.swift | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 validation-test/compiler_crashers_2_fixed/0213-issue60702.swift diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 6737f7b22fa35..c72c33d23d674 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -695,7 +695,7 @@ class Parser { tok::pound_else, tok::pound_elseif, tok::code_complete) && !isStartOfStmt() && - !isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false)) { + !isStartOfSwiftDecl(/*allowPoundIfAttributes=*/true)) { skipSingle(); } } diff --git a/validation-test/compiler_crashers_2_fixed/0213-issue60702.swift b/validation-test/compiler_crashers_2_fixed/0213-issue60702.swift new file mode 100644 index 0000000000000..fa22750cd1796 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/0213-issue60702.swift @@ -0,0 +1,5 @@ +// RUN: not %target-swift-frontend -parse %s +@ +#if true + print("x") +#endif From 7e1050b98c59cf23c12e521eca82912be462abf6 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 12 Aug 2022 14:23:14 +0100 Subject: [PATCH 314/491] [IRGen] Fix witness table miscompilation. If a foreign type conforms to a protocol, and that conformance is not resilient, we were emitting an instantantiation function but it would never be called because we weren't emitting the `GenericWitnessTable` that would have contained a reference to it. This was happening because of a missing `isSynthesizedNonUnique()` call in `isDependentConformance()`. rdar://97290618 --- lib/IRGen/GenProto.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index c536f4e350f6d..e389b08c5d8b0 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -920,6 +920,12 @@ static bool hasDependentTypeWitness( return false; } +static bool isSynthesizedNonUnique(const RootProtocolConformance *conformance) { + if (auto normal = dyn_cast(conformance)) + return normal->isSynthesizedNonUnique(); + return false; +} + static bool isDependentConformance( IRGenModule &IGM, const RootProtocolConformance *rootConformance, @@ -961,11 +967,15 @@ static bool isDependentConformance( if (assocConformance.isInvalid()) return false; - if (assocConformance.isAbstract() || - isDependentConformance(IGM, - assocConformance.getConcrete() - ->getRootConformance(), - visited)) + if (assocConformance.isAbstract()) + return true; + + auto rootConformance = assocConformance.getConcrete()->getRootConformance(); + + // [*] This condition must be true if getConformanceInfo() would return + // an AccessorConformanceInfo(). + if (isSynthesizedNonUnique(rootConformance) || + isDependentConformance(IGM, rootConformance, visited)) return true; } @@ -986,12 +996,6 @@ bool IRGenModule::isDependentConformance( return ::isDependentConformance(*this, conformance, visited); } -static bool isSynthesizedNonUnique(const RootProtocolConformance *conformance) { - if (auto normal = dyn_cast(conformance)) - return normal->isSynthesizedNonUnique(); - return false; -} - static llvm::Value * emitConditionalConformancesBuffer(IRGenFunction &IGF, const ProtocolConformance *substConformance) { @@ -2142,6 +2146,9 @@ IRGenModule::getConformanceInfo(const ProtocolDecl *protocol, // so in theory we could allocate them on a BumpPtrAllocator. But there's not // a good one for us to use. (The ASTContext's outlives the IRGenModule in // batch mode.) + // + // N.B. If you change this condition, you may need to update the condition + // marked [*] in isDependentConformance(). if (isDependentConformance(rootConformance) || // Foreign types need to go through the accessor to unique the witness // table. From 62f54019afd4ec57687d9624db5340a9dd1c182a Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Mon, 22 Aug 2022 13:16:53 +0100 Subject: [PATCH 315/491] [IRGen] Rearrange fix slightly and add a test case. isDependentConformance() should always check for synthesized conformances, so do that further up the function. Also add a test. rdar://97290618 --- lib/IRGen/GenProto.cpp | 26 +- test/IRGen/Inputs/module.modulemap | 5 + test/IRGen/Inputs/synthesized_protocol.h | 12 + test/IRGen/protocol_synthesized.swift | 303 +++++++++++++++++++++++ 4 files changed, 330 insertions(+), 16 deletions(-) create mode 100644 test/IRGen/Inputs/synthesized_protocol.h create mode 100644 test/IRGen/protocol_synthesized.swift diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index e389b08c5d8b0..efb2c562e34b5 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -871,7 +871,7 @@ bool IRGenModule::isResilientConformance( // across module boundaries. if (conformanceModule == getSwiftModule() && conformanceModule->getName().str() == - conformance->getProtocol()->getAlternateModuleName()) + conformance->getProtocol()->getAlternateModuleName()) return false; // If the protocol and the conformance are in the same module and the @@ -946,8 +946,9 @@ static bool isDependentConformance( if (!visited.insert(conformance).second) return false; - // If the conformance is resilient, this is always true. - if (IGM.isResilientConformance(conformance)) + // If the conformance is resilient or synthesized, this is always true. + if (IGM.isResilientConformance(conformance) + || isSynthesizedNonUnique(conformance)) return true; // Check whether any of the conformances are dependent. @@ -967,15 +968,11 @@ static bool isDependentConformance( if (assocConformance.isInvalid()) return false; - if (assocConformance.isAbstract()) - return true; - - auto rootConformance = assocConformance.getConcrete()->getRootConformance(); - - // [*] This condition must be true if getConformanceInfo() would return - // an AccessorConformanceInfo(). - if (isSynthesizedNonUnique(rootConformance) || - isDependentConformance(IGM, rootConformance, visited)) + if (assocConformance.isAbstract() || + isDependentConformance(IGM, + assocConformance.getConcrete() + ->getRootConformance(), + visited)) return true; } @@ -985,7 +982,7 @@ static bool isDependentConformance( // Check if there are any conditional conformances. Other forms of conditional // requirements don't exist in the witness table. return SILWitnessTable::enumerateWitnessTableConditionalConformances( - conformance, [](unsigned, CanType, ProtocolDecl *) { return true; }); + conformance, [](unsigned, CanType, ProtocolDecl *) { return true; }); } /// Is there anything about the given conformance that requires witness @@ -2146,9 +2143,6 @@ IRGenModule::getConformanceInfo(const ProtocolDecl *protocol, // so in theory we could allocate them on a BumpPtrAllocator. But there's not // a good one for us to use. (The ASTContext's outlives the IRGenModule in // batch mode.) - // - // N.B. If you change this condition, you may need to update the condition - // marked [*] in isDependentConformance(). if (isDependentConformance(rootConformance) || // Foreign types need to go through the accessor to unique the witness // table. diff --git a/test/IRGen/Inputs/module.modulemap b/test/IRGen/Inputs/module.modulemap index 3bfde113260d3..66015402a353e 100644 --- a/test/IRGen/Inputs/module.modulemap +++ b/test/IRGen/Inputs/module.modulemap @@ -26,3 +26,8 @@ module AtomicBoolModule { header "atomic_bool.h" export * } + +module SynthesizedProtocol { + header "synthesized_protocol.h" + export * +} diff --git a/test/IRGen/Inputs/synthesized_protocol.h b/test/IRGen/Inputs/synthesized_protocol.h new file mode 100644 index 0000000000000..edba874ed4300 --- /dev/null +++ b/test/IRGen/Inputs/synthesized_protocol.h @@ -0,0 +1,12 @@ +#ifndef SYNTHESIZED_PROTOCOL_H_ +#define SYNTHESIZED_PROTOCOL_H_ + +typedef enum __attribute__((flag_enum,enum_extensibility(open))) { + One = 0x0001, + Two = 0x0002, + Four = 0x0004, + Eight = 0x0008, + Sixteen = 0x0010 +} Flags; + +#endif /* SYNTHESIZED_PROTOCOL_H_ */ diff --git a/test/IRGen/protocol_synthesized.swift b/test/IRGen/protocol_synthesized.swift new file mode 100644 index 0000000000000..ebd1b95b32772 --- /dev/null +++ b/test/IRGen/protocol_synthesized.swift @@ -0,0 +1,303 @@ +// RUN: %target-swift-frontend -emit-ir -parse-stdlib -module-name=Swift -I%S/Inputs %s | %FileCheck %s + +// This module contains an enum that gets imported by the compiler as an +// OptionSet. What we're trying to test here is that a *non-resilient* +// synthesized protocol conformance works correctly; in particular, it needs +// to emit a GenericWitnessTable in the ProtocolConformanceDescriptor so that +// the initializer for the protocol witness table actually runs. +// (see rdar://97290618) + +import SynthesizedProtocol + +// CHECK: @"$sSo5Flagsas9OptionSetSCMc" = linkonce_odr hidden constant { i32, i32, i32, i32, i16, i16, i32, i32 } { i32 trunc (i64 sub (i64 ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %swift.protocol_requirement, %swift.protocol_requirement }>* @"$ss9OptionSetMp" to i64), i64 ptrtoint ({ i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc" to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32 }>* @"$sSo5FlagsaMn" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 1) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([3 x i8*]* @"$sSo5Flagsas9OptionSetSCWP" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 2) to i64)) to i32), i32 131200, i16 3, i16 1, i32 trunc (i64 sub (i64 ptrtoint (void (i8**, %swift.type*, i8**)* @"$sSo5Flagsas9OptionSetSCWI" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 6) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([16 x i8*]* @"$sSo5Flagsas9OptionSetSCMcMK" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 7) to i64)) to i32) }, section "__TEXT,__const", align 4 + +// Triggers the inclusion of the relevant ProtocolConformanceDescriptor +public func doFlags(f: Flags) -> Any +{ + return f.contains(.Two) +} + +// Because the standard library is usually resilient by default, we need to +// implement a minimal subset of it for this test (so that it *isn't* resilient). +// (If we use the resilient version, the compiler will always generate the +// GenericWitnessTable because we're resilient, which invalidates this test.) + +// .. Precedence ............................................................... + +precedencegroup AssignmentPrecedence { + assignment: true + associativity: right +} +precedencegroup AdditionPrecedence { + associativity: left + higherThan: AssignmentPrecedence +} +precedencegroup MultiplicationPrecedence { + associativity: left + higherThan: AdditionPrecedence +} + +// .. Operators ................................................................ + +infix operator &: MultiplicationPrecedence +infix operator |: AdditionPrecedence +infix operator ^: AdditionPrecedence + +infix operator &=: AssignmentPrecedence +infix operator ^=: AssignmentPrecedence +infix operator |=: AssignmentPrecedence + +// .. ExpressibleByIntegerLiteral .............................................. + +public protocol _ExpressibleByBuiltinIntegerLiteral { + init(_builtinIntegerLiteral value: Builtin.IntLiteral) +} + +public protocol ExpressibleByIntegerLiteral { + associatedtype IntegerLiteralType: _ExpressibleByBuiltinIntegerLiteral + init(integerLiteral value: IntegerLiteralType) +} + +extension ExpressibleByIntegerLiteral + where Self: _ExpressibleByBuiltinIntegerLiteral { + @_transparent + public init(integerLiteral value: Self) { + self = value + } +} + +// .. (U)Int32 ................................................................. + +@frozen +public struct Int32 : FixedWidthInteger, _ExpressibleByBuiltinIntegerLiteral { + public typealias IntegerLiteralType = Int32 + public var _value: Builtin.Int32 + + @_transparent + public init(_builtinIntegerLiteral x: Builtin.IntLiteral) { + _value = Builtin.s_to_s_checked_trunc_IntLiteral_Int32(x).0 + } + + @_transparent + public init(bitPattern x: UInt32) { + _value = x._value + } + + @_transparent + public init(_ _value: Builtin.Int32) { + self._value = _value + } + + public static func |=(_ x: inout Int32, _ y: Int32) { + x = Int32(Builtin.or_Int32(x._value, y._value)) + } + public static func &=(_ x: inout Int32, _ y: Int32) { + x = Int32(Builtin.and_Int32(x._value, y._value)) + } + public static func ^=(_ x: inout Int32, _ y: Int32) { + x = Int32(Builtin.xor_Int32(x._value, y._value)) + } +} + +@frozen +public struct UInt32 : FixedWidthInteger, _ExpressibleByBuiltinIntegerLiteral { + public typealias IntegerLiteralType = UInt32 + public var _value: Builtin.Int32 + + @_transparent + public init(_builtinIntegerLiteral x: Builtin.IntLiteral) { + _value = Builtin.s_to_u_checked_trunc_IntLiteral_Int32(x).0 + } + + @_transparent + public init(bitPattern x: Int32) { + _value = x._value + } + + @_transparent + public init(_ _value: Builtin.Int32) { + self._value = _value + } + + public static func |=(x: inout UInt32, y: UInt32) { + x = UInt32(Builtin.or_Int32(x._value, y._value)) + } + public static func &=(x: inout UInt32, y: UInt32) { + x = UInt32(Builtin.and_Int32(x._value, y._value)) + } + public static func ^=(x: inout UInt32, y: UInt32) { + x = UInt32(Builtin.xor_Int32(x._value, y._value)) + } +} + +// .. C types .................................................................. + +typealias CInt = Int32 +typealias CUnsignedInt = UInt32 + +// .. SetAlgebra ............................................................... + +public protocol SetAlgebra { + associatedtype Element + + func contains(_ member: Element) -> Any + __consuming func union(_ other: __owned Self) -> Self + __consuming func intersection(_ other: Self) -> Self + __consuming func symmetricDifference(_ other: __owned Self) -> Self + mutating func insert(_ newMember: __owned Element) + mutating func remove(_ member: Element) + mutating func update(with newMember: __owned Element) + mutating func formUnion(_ other: __owned Self) + mutating func formIntersection(_ other: Self) + mutating func formSymmetricDifference(_ other: __owned Self) + + static func |(_ lhs: Self, _ rhs: Self) -> Self + static func &(_ lhs: Self, _ rhs: Self) -> Self + static func ^(_ lhs: Self, _ rhs: Self) -> Self + static func |=(_ lhs: inout Self, _ rhs: Self) + static func &=(_ lhs: inout Self, _ rhs: Self) + static func ^=(_ lhs: inout Self, _ rhs: Self) +} + +extension SetAlgebra { + @_transparent + public static func & (_ lhs: Self, _ rhs: Self) -> Self { + return lhs.intersection(rhs) + } + + @_transparent + public static func | (_ lhs: Self, _ rhs: Self) -> Self { + return lhs.union(rhs) + } + + @_transparent + public static func ^ (_ lhs: Self, _ rhs: Self) -> Self { + return lhs.symmetricDifference(rhs) + } + + public static func &=(_ lhs: inout Self, _ rhs: Self) { + lhs.formIntersection(rhs) + } + + public static func |=(_ lhs: inout Self, _ rhs: Self) { + lhs.formUnion(rhs) + } + + public static func ^=(_ lhs: inout Self, _ rhs: Self) { + lhs.formSymmetricDifference(rhs) + } +} + +// .. RawRepresentable ......................................................... + +public protocol RawRepresentable { + associatedtype RawValue + init(rawValue: RawValue) + var rawValue: RawValue { get } +} + +// .. OptionSet ................................................................ + +public protocol OptionSet: SetAlgebra, RawRepresentable { + associatedtype Element = Self + init(rawValue: RawValue) +} + +extension OptionSet { + @inlinable + public func union(_ other: Self) -> Self { + var r = Self(rawValue: self.rawValue) + r.formUnion(other) + return r + } + + @inlinable + public func intersection(_ other: Self) -> Self { + var r = Self(rawValue: self.rawValue) + r.formIntersection(other) + return r + } + + @inlinable + public func symmetricDifference(_ other: Self) -> Self { + var r = Self(rawValue: self.rawValue) + r.formSymmetricDifference(other) + return r + } +} + +extension OptionSet where Element == Self { + public func contains(_ member: Self) -> Any { + return self + } + + public mutating func insert(_ newMember: Element) { + } + + public mutating func remove(_ member: Element) { + } + + public mutating func update(with newMember: Element) { + } +} + +extension OptionSet where RawValue: FixedWidthInteger { + @inlinable + public mutating func formUnion(_ other: Self) { + self = Self(rawValue: self.rawValue | other.rawValue) + } + + @inlinable + public mutating func formIntersection(_ other: Self) { + self = Self(rawValue: self.rawValue & other.rawValue) + } + + @inlinable + public mutating func formSymmetricDifference(_ other: Self) { + self = Self(rawValue: self.rawValue ^ other.rawValue) + } +} + +// .. FixedWidthInteger ........................................................ + +public protocol FixedWidthInteger { + static func |(_ lhs: Self, _ rhs: Self) -> Self + static func &(_ lhs: Self, _ rhs: Self) -> Self + static func ^(_ lhs: Self, _ rhs: Self) -> Self + static func |=(_ lhs: inout Self, _ rhs: Self) + static func &=(_ lhs: inout Self, _ rhs: Self) + static func ^=(_ lhs: inout Self, _ rhs: Self) +} + +extension FixedWidthInteger { + @_transparent + public static func & (_ lhs: Self, _ rhs: Self) -> Self { + var lhs = lhs + lhs &= rhs + return lhs + } + + @_transparent + public static func | (_ lhs: Self, _ rhs: Self) -> Self { + var lhs = lhs + lhs |= rhs + return lhs + } + + @_transparent + public static func ^ (_ lhs: Self, _ rhs: Self) -> Self { + var lhs = lhs + lhs ^= rhs + return lhs + } +} + +// .. ExpressibleByArrayLiteral ................................................ + +public protocol ExpressibleByArrayLiteral { +} + +// .. Equatable ................................................................ + +public protocol Equatable { +} From 428789dc8304c0234de9e0943209c9babd4b7c81 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Tue, 23 Aug 2022 09:47:39 +0100 Subject: [PATCH 316/491] [IRGen][Tests] Fix test case to work for 32-bit architectures. Changed the test case to pattern match various parts to make it work on 32-bit. rdar://97290618 --- test/IRGen/protocol_synthesized.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IRGen/protocol_synthesized.swift b/test/IRGen/protocol_synthesized.swift index ebd1b95b32772..1931501ba4796 100644 --- a/test/IRGen/protocol_synthesized.swift +++ b/test/IRGen/protocol_synthesized.swift @@ -9,7 +9,7 @@ import SynthesizedProtocol -// CHECK: @"$sSo5Flagsas9OptionSetSCMc" = linkonce_odr hidden constant { i32, i32, i32, i32, i16, i16, i32, i32 } { i32 trunc (i64 sub (i64 ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %swift.protocol_requirement, %swift.protocol_requirement }>* @"$ss9OptionSetMp" to i64), i64 ptrtoint ({ i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc" to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32 }>* @"$sSo5FlagsaMn" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 1) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([3 x i8*]* @"$sSo5Flagsas9OptionSetSCWP" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 2) to i64)) to i32), i32 131200, i16 3, i16 1, i32 trunc (i64 sub (i64 ptrtoint (void (i8**, %swift.type*, i8**)* @"$sSo5Flagsas9OptionSetSCWI" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 6) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([16 x i8*]* @"$sSo5Flagsas9OptionSetSCMcMK" to i64), i64 ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 7) to i64)) to i32) }, section "__TEXT,__const", align 4 +// CHECK: @"$sSo5Flagsas9OptionSetSCMc" = linkonce_odr hidden constant { i32, i32, i32, i32, i16, i16, i32, i32 } { i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %swift.protocol_requirement, %swift.protocol_requirement }>* @"$ss9OptionSetMp" to {{i(32|64)}}), {{i(32|64)}} ptrtoint ({ i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc" to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32 }>* @"$sSo5FlagsaMn" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 1) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([3 x i8*]* @"$sSo5Flagsas9OptionSetSCWP" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 2) to {{i(32|64)}})){{( to i32\))?}}, i32 131200, i16 3, i16 1, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (void (i8**, %swift.type*, i8**)* @"$sSo5Flagsas9OptionSetSCWI" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 6) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([16 x i8*]* @"$sSo5Flagsas9OptionSetSCMcMK" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 7) to {{i(32|64)}})) {{(to i32\) )?}}}, section "__TEXT,__const", align 4 // Triggers the inclusion of the relevant ProtocolConformanceDescriptor public func doFlags(f: Flags) -> Any From bb741308181feafe7f4114abd2d3047987cffba4 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Tue, 23 Aug 2022 13:56:10 +0100 Subject: [PATCH 317/491] [IRGen][Tests] Fix test case to work for Windows. Windows adds a `comdat` flag. rdar://97290618 --- test/IRGen/protocol_synthesized.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IRGen/protocol_synthesized.swift b/test/IRGen/protocol_synthesized.swift index 1931501ba4796..529c4edb86eb5 100644 --- a/test/IRGen/protocol_synthesized.swift +++ b/test/IRGen/protocol_synthesized.swift @@ -9,7 +9,7 @@ import SynthesizedProtocol -// CHECK: @"$sSo5Flagsas9OptionSetSCMc" = linkonce_odr hidden constant { i32, i32, i32, i32, i16, i16, i32, i32 } { i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %swift.protocol_requirement, %swift.protocol_requirement }>* @"$ss9OptionSetMp" to {{i(32|64)}}), {{i(32|64)}} ptrtoint ({ i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc" to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32 }>* @"$sSo5FlagsaMn" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 1) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([3 x i8*]* @"$sSo5Flagsas9OptionSetSCWP" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 2) to {{i(32|64)}})){{( to i32\))?}}, i32 131200, i16 3, i16 1, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (void (i8**, %swift.type*, i8**)* @"$sSo5Flagsas9OptionSetSCWI" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 6) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([16 x i8*]* @"$sSo5Flagsas9OptionSetSCMcMK" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 7) to {{i(32|64)}})) {{(to i32\) )?}}}, section "__TEXT,__const", align 4 +// CHECK: @"$sSo5Flagsas9OptionSetSCMc" = linkonce_odr hidden constant { i32, i32, i32, i32, i16, i16, i32, i32 } { i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %swift.protocol_requirement, %swift.protocol_requirement }>* @"$ss9OptionSetMp" to {{i(32|64)}}), {{i(32|64)}} ptrtoint ({ i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc" to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32 }>* @"$sSo5FlagsaMn" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 1) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([3 x i8*]* @"$sSo5Flagsas9OptionSetSCWP" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 2) to {{i(32|64)}})){{( to i32\))?}}, i32 131200, i16 3, i16 1, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (void (i8**, %swift.type*, i8**)* @"$sSo5Flagsas9OptionSetSCWI" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 6) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([16 x i8*]* @"$sSo5Flagsas9OptionSetSCMcMK" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 7) to {{i(32|64)}})) {{(to i32\) )?}}}, section "__TEXT,__const"{{(, comdat)?}}, align 4 // Triggers the inclusion of the relevant ProtocolConformanceDescriptor public func doFlags(f: Flags) -> Any From 741478908a5109c6788078b4b3dcc0dd825f091c Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Tue, 23 Aug 2022 06:59:44 -0700 Subject: [PATCH 318/491] [IRGen][Tests] Fix test to work on Linux. Linux uses different section names. rdar://97690618 --- test/IRGen/protocol_synthesized.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IRGen/protocol_synthesized.swift b/test/IRGen/protocol_synthesized.swift index 529c4edb86eb5..9004878165402 100644 --- a/test/IRGen/protocol_synthesized.swift +++ b/test/IRGen/protocol_synthesized.swift @@ -9,7 +9,7 @@ import SynthesizedProtocol -// CHECK: @"$sSo5Flagsas9OptionSetSCMc" = linkonce_odr hidden constant { i32, i32, i32, i32, i16, i16, i32, i32 } { i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %swift.protocol_requirement, %swift.protocol_requirement }>* @"$ss9OptionSetMp" to {{i(32|64)}}), {{i(32|64)}} ptrtoint ({ i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc" to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32 }>* @"$sSo5FlagsaMn" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 1) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([3 x i8*]* @"$sSo5Flagsas9OptionSetSCWP" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 2) to {{i(32|64)}})){{( to i32\))?}}, i32 131200, i16 3, i16 1, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (void (i8**, %swift.type*, i8**)* @"$sSo5Flagsas9OptionSetSCWI" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 6) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([16 x i8*]* @"$sSo5Flagsas9OptionSetSCMcMK" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 7) to {{i(32|64)}})) {{(to i32\) )?}}}, section "__TEXT,__const"{{(, comdat)?}}, align 4 +// CHECK: @"$sSo5Flagsas9OptionSetSCMc" = linkonce_odr hidden constant { i32, i32, i32, i32, i16, i16, i32, i32 } { i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %swift.protocol_requirement, %swift.protocol_requirement }>* @"$ss9OptionSetMp" to {{i(32|64)}}), {{i(32|64)}} ptrtoint ({ i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc" to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (<{ i32, i32, i32, i32, i32, i32, i32, i32 }>* @"$sSo5FlagsaMn" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 1) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([3 x i8*]* @"$sSo5Flagsas9OptionSetSCWP" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 2) to {{i(32|64)}})){{( to i32\))?}}, i32 131200, i16 3, i16 1, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint (void (i8**, %swift.type*, i8**)* @"$sSo5Flagsas9OptionSetSCWI" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 6) to {{i(32|64)}})){{( to i32\))?}}, i32 {{(trunc \(i64 )?}}sub ({{i(32|64)}} ptrtoint ([16 x i8*]* @"$sSo5Flagsas9OptionSetSCMcMK" to {{i(32|64)}}), {{i(32|64)}} ptrtoint (i32* getelementptr inbounds ({ i32, i32, i32, i32, i16, i16, i32, i32 }, { i32, i32, i32, i32, i16, i16, i32, i32 }* @"$sSo5Flagsas9OptionSetSCMc", i32 0, i32 7) to {{i(32|64)}})) {{(to i32\) )?}}}, section "{{[^"]*}}"{{(, comdat)?}}, align 4 // Triggers the inclusion of the relevant ProtocolConformanceDescriptor public func doFlags(f: Flags) -> Any From ae37591c06fb6043b3d9aacaa8be33476758d9ae Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 319/491] AST: Add a count type field to PackExpansionType Even if we can't spell them in source, we want to model expansions where the pattern does not depend on any pack type parameters, eg func f(_ c: C...) { let x = (c.count...) } Here, the type of 'x' is notionally 'Int * C.count'. --- include/swift/AST/Types.h | 33 ++++++++++++++------- lib/AST/ASTContext.cpp | 43 +++++++++++++++++++--------- lib/AST/ASTDumper.cpp | 1 + lib/AST/Type.cpp | 24 +++++++++------- lib/Sema/TypeCheckDecl.cpp | 16 +++++++++-- lib/Sema/TypeCheckType.cpp | 19 ++++++++++-- test/Constraints/type_sequence.swift | 2 +- 7 files changed, 98 insertions(+), 40 deletions(-) diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 4d26b2801bfb2..25f8d6229861d 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -6378,7 +6378,7 @@ class PackType final : public TypeBase, public llvm::FoldingSetNode, } public: - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, getElementTypes()); } static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef Elements); @@ -6427,24 +6427,33 @@ class PackExpansionType : public TypeBase, public llvm::FoldingSetNode { friend class ASTContext; Type patternType; + Type countType; public: /// Create a pack expansion type from the given pattern type. /// - /// It is not required that the pattern type actually contain a reference to - /// a variadic generic parameter. - static PackExpansionType *get(Type pattern); + /// It is not required that \p pattern actually contain a reference to + /// a variadic generic parameter, but any variadic generic parameters + /// appearing in the pattern type must have the same count as \p countType. + /// + /// As for \p countType itself, it must be a type sequence generic parameter + /// type, or a sequence archetype type. + static PackExpansionType *get(Type pattern, Type countType); public: /// Retrieves the pattern type of this pack expansion. Type getPatternType() const { return patternType; } + /// Retrieves the count type of this pack expansion. + Type getCountType() const { return countType; } + public: void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPatternType()); + Profile(ID, getPatternType(), getCountType()); } - static void Profile(llvm::FoldingSetNodeID &ID, Type patternType); + static void Profile(llvm::FoldingSetNodeID &ID, + Type patternType, Type countType); // Implement isa/cast/dyncast/etc. static bool classof(const TypeBase *T) { @@ -6452,16 +6461,18 @@ class PackExpansionType : public TypeBase, public llvm::FoldingSetNode { } private: - PackExpansionType(Type patternType, const ASTContext *CanCtx) - : TypeBase(TypeKind::PackExpansion, CanCtx, - patternType->getRecursiveProperties()), patternType(patternType) { - assert(patternType); - } + PackExpansionType(Type patternType, Type countType, + RecursiveTypeProperties properties, + const ASTContext *ctx); }; BEGIN_CAN_TYPE_WRAPPER(PackExpansionType, Type) CanType getPatternType() const { return CanType(getPointer()->getPatternType()); } + + CanType getCountType() const { + return CanType(getPointer()->getCountType()); + } END_CAN_TYPE_WRAPPER(PackExpansionType, Type) /// getASTContext - Return the ASTContext that this type belongs to. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 4b443e7a1c671..f412856ed7a63 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2897,33 +2897,48 @@ TupleTypeElt::TupleTypeElt(Type ty, Identifier name) assert(!ty->is() && "Cannot have InOutType in a tuple"); } -PackExpansionType *PackExpansionType::get(Type patternTy) { - assert(patternTy && "Missing pattern type in expansion"); +PackExpansionType::PackExpansionType(Type patternType, Type countType, + RecursiveTypeProperties properties, + const ASTContext *canCtx) + : TypeBase(TypeKind::PackExpansion, canCtx, properties), + patternType(patternType), countType(countType) { + assert(countType->is() || + countType->is() || + countType->castTo()->isTypeSequence()); +} + +PackExpansionType *PackExpansionType::get(Type patternType, Type countType) { + auto properties = patternType->getRecursiveProperties(); + properties |= countType->getRecursiveProperties(); - auto properties = patternTy->getRecursiveProperties(); auto arena = getArena(properties); - auto &context = patternTy->getASTContext(); + auto &context = patternType->getASTContext(); llvm::FoldingSetNodeID id; - PackExpansionType::Profile(id, patternTy); + PackExpansionType::Profile(id, patternType, countType); void *insertPos; if (PackExpansionType *expType = - context.getImpl() - .getArena(arena) - .PackExpansionTypes.FindNodeOrInsertPos(id, insertPos)) + context.getImpl().getArena(arena) + .PackExpansionTypes.FindNodeOrInsertPos(id, insertPos)) return expType; - const ASTContext *canCtx = patternTy->isCanonical() ? &context : nullptr; - PackExpansionType *expansionTy = new (context, AllocationArena::Permanent) - PackExpansionType(patternTy, canCtx); - context.getImpl().getArena(arena).PackExpansionTypes.InsertNode(expansionTy, + const ASTContext *canCtx = + (patternType->isCanonical() && countType->isCanonical()) + ? &context : nullptr; + PackExpansionType *expansionType = + new (context, arena) PackExpansionType(patternType, countType, properties, + canCtx); + context.getImpl().getArena(arena).PackExpansionTypes.InsertNode(expansionType, insertPos); - return expansionTy; + return expansionType; } -void PackExpansionType::Profile(llvm::FoldingSetNodeID &ID, Type patternType) { +void PackExpansionType::Profile(llvm::FoldingSetNodeID &ID, + Type patternType, + Type countType) { ID.AddPointer(patternType.getPointer()); + ID.AddPointer(countType.getPointer()); } PackType *PackType::getEmpty(const ASTContext &C) { diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 5f95c2dc2d721..6a6d07389a7b5 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -3686,6 +3686,7 @@ namespace { void visitPackExpansionType(PackExpansionType *T, StringRef label) { printCommon(label, "pack_expansion_type"); printField("pattern", T->getPatternType()); + printField("count", T->getCountType()); PrintWithColorRAII(OS, ParenthesisColor) << ')'; } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index a6e64593e543a..92536fc1c87c8 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1593,8 +1593,9 @@ CanType TypeBase::computeCanonicalType() { case TypeKind::PackExpansion: { auto *expansion = cast(this); - auto pattern = expansion->getPatternType()->getCanonicalType(); - Result = PackExpansionType::get(pattern); + auto patternType = expansion->getPatternType()->getCanonicalType(); + auto countType = expansion->getCountType()->getCanonicalType(); + Result = PackExpansionType::get(patternType, countType); break; } @@ -5535,12 +5536,9 @@ case TypeKind::Id: return remap; } - if (input->is()) { - if (auto *PT = (*remap)->getAs()) { - maxArity = std::max(maxArity, PT->getNumElements()); - cache.insert({input, PT}); - } - } else if (input->isTypeSequenceParameter()) { + if (input->is() || + input->isTypeSequenceParameter() || + input->is()) { if (auto *PT = (*remap)->getAs()) { maxArity = std::max(maxArity, PT->getNumElements()); cache.insert({input, PT}); @@ -5563,7 +5561,13 @@ case TypeKind::Id: if (!transformedPat) return Type(); - if (transformedPat.getPointer() == expand->getPatternType().getPointer()) + Type transformedCount = + expand->getCountType().transformWithPosition(pos, gather); + if (!transformedCount) + return Type(); + + if (transformedPat.getPointer() == expand->getPatternType().getPointer() && + transformedCount.getPointer() == expand->getCountType().getPointer()) return *this; llvm::DenseMap expansions; @@ -5573,7 +5577,7 @@ case TypeKind::Id: // If we didn't find any expansions, either the caller wasn't interested // in expanding this pack, or something has gone wrong. Leave off the // expansion and return the transformed type. - return PackExpansionType::get(transformedPat); + return PackExpansionType::get(transformedPat, transformedCount); } SmallVector elts; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 9f910c1ebe39b..3ffff5cf16688 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2227,10 +2227,22 @@ static Type validateParameterType(ParamDecl *decl) { } if (decl->isVariadic()) { + // Find the first type sequence parameter and use that as the count type. + Type countTy; + (void) Ty.findIf([&](Type t) -> bool { + if (auto *paramTy = t->getAs()) { + if (paramTy->isTypeSequence()) { + countTy = paramTy; + return true; + } + } + + return false; + }); // Handle the monovariadic/polyvariadic interface type split. - if (Ty->hasTypeSequence()) { + if (countTy) { // Polyvariadic types (T...) for resolve to pack expansions. - Ty = PackExpansionType::get(Ty); + Ty = PackExpansionType::get(Ty, countTy); } else { // Monovariadic types (T...) for resolve to [T]. Ty = VariadicSequenceType::get(Ty); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index dcd28359876a1..360c3acb719e0 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -4018,13 +4018,28 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr, if (patternTy->hasError()) complained = true; + // Find the first type sequence parameter and use that as the count type. + Type countTy; + (void) patternTy.get().findIf([&](Type t) -> bool { + if (auto *paramTy = t->getAs()) { + if (paramTy->isTypeSequence()) { + countTy = paramTy; + return true; + } + } + + return false; + }); + // If there's no reference to a variadic generic parameter, complain // - the pack won't actually expand to anything meaningful. - if (!patternTy->hasTypeSequence()) + if (!countTy) { diagnose(repr->getLoc(), diag::expansion_not_variadic, patternTy) .highlight(repr->getParens()); + return ErrorType::get(getASTContext()); + } - return PackExpansionType::get(patternTy); + return PackExpansionType::get(patternTy, countTy); } else { // Variadic tuples are not permitted. // diff --git a/test/Constraints/type_sequence.swift b/test/Constraints/type_sequence.swift index ad0ee71bf0b06..e9f1b47d77661 100644 --- a/test/Constraints/type_sequence.swift +++ b/test/Constraints/type_sequence.swift @@ -65,7 +65,7 @@ func bindPrefixAndSuffix() { func invalidPacks() { func monovariadic1() -> (String...) {} // expected-error {{cannot create expansion with non-variadic type 'String'}} - func monovariadic2() -> (T...) {} // expected-error 2 {{cannot create expansion with non-variadic type 'T'}} + func monovariadic2() -> (T...) {} // expected-error {{cannot create expansion with non-variadic type 'T'}} func monovariadic3() -> (T, U...) {} // expected-error {{cannot create a variadic tuple}} } From 7a16b0275b4e5c6f036abc32426aae8055f2dd96 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 320/491] AST: Allow one-element tuple types to be constructed These will never appear in the source language, but can arise after substitution when the original type is a tuple type with a pack expansion type. Two examples: - original type: (Int, T...), substitution T := {} - original type: (T...), substitution T := {Int} We need to model these correctly to maintain invariants. Callers that previously used to rely on TupleType::get() returning a ParenType now explicitly check for the one-element case instead. --- include/swift/AST/Pattern.h | 7 ----- include/swift/AST/Types.h | 9 +++--- lib/AST/ASTContext.cpp | 7 ++--- lib/AST/Pattern.cpp | 7 ++++- lib/AST/Type.cpp | 2 +- lib/ClangImporter/ImportType.cpp | 3 ++ lib/IRGen/MetadataRequest.cpp | 5 +-- lib/SILGen/SILGenExpr.cpp | 31 ++++++++++++------- lib/SILGen/SILGenPoly.cpp | 5 ++- .../Transforms/PartialApplySimplification.cpp | 14 ++++++--- lib/Sema/CSRanking.cpp | 3 ++ lib/Sema/CSSimplify.cpp | 2 +- lib/Sema/TypeCheckPattern.cpp | 6 ++-- lib/Sema/TypeCheckRegex.cpp | 3 +- lib/Sema/TypeCheckType.cpp | 3 ++ unittests/AST/IndexSubsetTests.cpp | 4 +-- 16 files changed, 64 insertions(+), 47 deletions(-) diff --git a/include/swift/AST/Pattern.h b/include/swift/AST/Pattern.h index 69cff5fb74e09..4dd661cd87435 100644 --- a/include/swift/AST/Pattern.h +++ b/include/swift/AST/Pattern.h @@ -260,9 +260,6 @@ class ParenPattern : public Pattern { /// /// The fully general form of this is something like: /// label: (pattern) = initexpr -/// -/// The Init and DefArgKind fields are only used in argument lists for -/// functions. They are not parsed as part of normal pattern grammar. class TuplePatternElt { Identifier Label; SourceLoc LabelLoc; @@ -277,10 +274,6 @@ class TuplePatternElt { Identifier getLabel() const { return Label; } SourceLoc getLabelLoc() const { return LabelLoc; } - void setLabel(Identifier I, SourceLoc Loc) { - Label = I; - LabelLoc = Loc; - } Pattern *getPattern() { return ThePattern; } const Pattern *getPattern() const { diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 25f8d6229861d..42c597bfddf50 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -2270,10 +2270,11 @@ class TupleType final : public TypeBase, public llvm::FoldingSetNode, public: /// get - Return the uniqued tuple type with the specified elements. - /// Returns a ParenType instead if there is exactly one element which - /// is unlabeled and not varargs, so it doesn't accidentally construct - /// a tuple which is impossible to write. - static Type get(ArrayRef Elements, const ASTContext &C); + /// + /// This can construct one-element tuple types, which are impossible to + /// write in the source language. The caller should check for that case + /// first it a bona fide 'r-value' type is desired. + static TupleType *get(ArrayRef Elements, const ASTContext &C); /// getEmpty - Return the empty tuple type '()'. static CanTypeWrapper getEmpty(const ASTContext &C); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f412856ed7a63..df573a5c605ed 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2853,10 +2853,7 @@ void TupleType::Profile(llvm::FoldingSetNodeID &ID, } /// getTupleType - Return the uniqued tuple type with the specified elements. -Type TupleType::get(ArrayRef Fields, const ASTContext &C) { - if (Fields.size() == 1 && !Fields[0].hasName()) - return ParenType::get(C, Fields[0].getType()); - +TupleType *TupleType::get(ArrayRef Fields, const ASTContext &C) { RecursiveTypeProperties properties; for (const TupleTypeElt &Elt : Fields) { auto eltTy = Elt.getType(); @@ -3608,6 +3605,8 @@ Type AnyFunctionType::composeTuple(ASTContext &ctx, ArrayRef params, } elements.emplace_back(param.getParameterType(), param.getLabel()); } + if (elements.size() == 1 && !elements[0].hasName()) + return ParenType::get(ctx, elements[0].getType()); return TupleType::get(elements, ctx); } diff --git a/lib/AST/Pattern.cpp b/lib/AST/Pattern.cpp index 9ad387167ecc4..a3707780b48f8 100644 --- a/lib/AST/Pattern.cpp +++ b/lib/AST/Pattern.cpp @@ -372,6 +372,11 @@ Identifier NamedPattern::getBoundName() const { TuplePattern *TuplePattern::create(ASTContext &C, SourceLoc lp, ArrayRef elts, SourceLoc rp) { +#ifndef NDEBUG + if (elts.size() == 1) + assert(!elts[0].getLabel().empty()); +#endif + unsigned n = elts.size(); void *buffer = C.Allocate(totalSizeToAlloc(n), alignof(TuplePattern)); @@ -387,7 +392,7 @@ Pattern *TuplePattern::createSimple(ASTContext &C, SourceLoc lp, assert(lp.isValid() == rp.isValid()); if (elements.size() == 1 && - elements[0].getPattern()->getBoundName().empty()) { + elements[0].getLabel().empty()) { auto &first = const_cast(elements.front()); return new (C) ParenPattern(lp, first.getPattern(), rp); } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 92536fc1c87c8..fdc4bc35d0021 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -6255,7 +6255,7 @@ TypeBase::getAutoDiffTangentSpace(LookupConformanceFn lookupConformance) { TangentSpace::getTuple(ctx.TheEmptyTupleType->castTo())); if (newElts.size() == 1) return cache(TangentSpace::getTangentVector(newElts.front().getType())); - auto *tupleType = TupleType::get(newElts, ctx)->castTo(); + auto *tupleType = TupleType::get(newElts, ctx); return cache(TangentSpace::getTuple(tupleType)); } diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 49d7ea4a29b12..82f319e04cf08 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -619,6 +619,9 @@ namespace { if (size > 4096) return Type(); + if (size == 1) + return ParenType::get(elementType->getASTContext(), elementType); + SmallVector elts{static_cast(size), elementType}; return TupleType::get(elts, elementType->getASTContext()); } diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index bb8cf82428fc9..88245e9d0b1e3 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -3197,10 +3197,7 @@ class EmitTypeMetadataRefForLayout if (!changed) return ty; - // The cast should succeed, because if we end up with a one-element - // tuple type here, it must have a label. - return cast( - CanType(TupleType::get(loweredElts, ty->getASTContext()))); + return CanTupleType(TupleType::get(loweredElts, ty->getASTContext())); } CanType visitAnyFunctionType(CanAnyFunctionType ty) { diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 8ef949af0405d..641ea69568c9d 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -3165,12 +3165,12 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM, static void getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, - SILLocation loc, - GenericEnvironment *genericEnv, - ResilienceExpansion expansion, - ArrayRef indexes, - SILFunction *&equals, - SILFunction *&hash) { + SILLocation loc, + GenericEnvironment *genericEnv, + ResilienceExpansion expansion, + ArrayRef indexes, + SILFunction *&equals, + SILFunction *&hash) { if (indexes.empty()) { equals = nullptr; hash = nullptr; @@ -3198,14 +3198,21 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, for (auto &index : indexes) indexTypes.push_back(index.FormalType); - SmallVector indexElts; - for (auto &elt : indexes) { - indexElts.push_back(GenericEnvironment::mapTypeIntoContext(genericEnv, - elt.FormalType)); + CanType indexTupleTy; + if (indexes.size() == 1) { + indexTupleTy = GenericEnvironment::mapTypeIntoContext( + genericEnv, indexes[0].FormalType)->getCanonicalType(); + } else { + SmallVector indexElts; + for (auto &elt : indexes) { + indexElts.push_back(GenericEnvironment::mapTypeIntoContext( + genericEnv, elt.FormalType)); + } + + indexTupleTy = TupleType::get(indexElts, SGM.getASTContext()) + ->getCanonicalType(); } - auto indexTupleTy = TupleType::get(indexElts, SGM.getASTContext()) - ->getCanonicalType(); RValue indexValue(indexTupleTy); auto indexLoweredTy = diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index 064bcf8aa7f44..0b35df41916d8 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -934,9 +934,8 @@ namespace { assert(!param.isInOut()); elts.emplace_back(param.getParameterType()); } - auto outputSubstType = cast( - TupleType::get(elts, SGF.getASTContext()) - ->getCanonicalType()); + auto outputSubstType = CanTupleType( + TupleType::get(elts, SGF.getASTContext())); // Translate the input tuple value into the output tuple value. Note // that the output abstraction pattern is a tuple, and we explode tuples diff --git a/lib/SILOptimizer/Transforms/PartialApplySimplification.cpp b/lib/SILOptimizer/Transforms/PartialApplySimplification.cpp index 69ce756fd727b..fe01db3e6e51a 100644 --- a/lib/SILOptimizer/Transforms/PartialApplySimplification.cpp +++ b/lib/SILOptimizer/Transforms/PartialApplySimplification.cpp @@ -485,11 +485,17 @@ rewriteKnownCalleeWithExplicitContext(SILFunction *callee, // TODO: SILBoxType is only implemented for a single field right now, and we // don't yet have a corresponding type for nonescaping captures, so // represent the captures as a tuple for now. - llvm::SmallVector tupleElts; - for (auto field : boxFields) { - tupleElts.push_back(TupleTypeElt(field.getLoweredType())); + CanType tupleTy; + + if (boxFields.size() == 1) { + tupleTy = boxFields[0].getLoweredType(); + } else { + llvm::SmallVector tupleElts; + for (auto field : boxFields) { + tupleElts.push_back(TupleTypeElt(field.getLoweredType())); + } + tupleTy = TupleType::get(tupleElts, C)->getCanonicalType(); } - auto tupleTy = TupleType::get(tupleElts, C)->getCanonicalType(); CanType contextTy; SILParameterInfo contextParam; diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index 6dcbbfd738644..0af0e1f00ecb7 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -662,6 +662,9 @@ Comparison TypeChecker::compareDeclarations(DeclContext *dc, static Type getUnlabeledType(Type type, ASTContext &ctx) { return type.transform([&](Type type) -> Type { if (auto *tupleType = dyn_cast(type.getPointer())) { + if (tupleType->getNumElements() == 1) + return ParenType::get(ctx, tupleType->getElementType(0)); + SmallVector elts; for (auto elt : tupleType->getElements()) { elts.push_back(elt.getWithoutName()); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 46d60899fef41..7969cd587d3e5 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -12892,7 +12892,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( } } auto matchingType = - TupleType::get(newTupleTypes, getASTContext())->castTo(); + TupleType::get(newTupleTypes, getASTContext()); if (recordFix(fix)) return SolutionKind::Error; return matchTupleTypes(matchingType, smaller, matchKind, subflags, locator); diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index a463a3cd920ec..2f9facf5ee3dc 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -1037,13 +1037,13 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern, && !isa(semantic)) { if (auto tupleType = type->getAs()) { if (tupleType->getNumElements() == 1) { - auto elementTy = tupleType->getElementType(0); + auto element = tupleType->getElement(0); sub = coercePatternToType( - pattern.forSubPattern(sub, /*retainTopLevel=*/true), elementTy, + pattern.forSubPattern(sub, /*retainTopLevel=*/true), element.getType(), subOptions); if (!sub) return nullptr; - TuplePatternElt elt(sub); + TuplePatternElt elt(element.getName(), SourceLoc(), sub); P = TuplePattern::create(Context, PP->getLParenLoc(), elt, PP->getRParenLoc()); if (PP->isImplicit()) diff --git a/lib/Sema/TypeCheckRegex.cpp b/lib/Sema/TypeCheckRegex.cpp index d8f86b3d8d8e7..68b39b833ffa0 100644 --- a/lib/Sema/TypeCheckRegex.cpp +++ b/lib/Sema/TypeCheckRegex.cpp @@ -95,8 +95,9 @@ bool swift::decodeRegexCaptureTypes(ASTContext &ctx, break; case RegexCaptureStructureCode::EndTuple: { auto children = scopes.pop_back_val(); + assert(children.size() > 1); auto type = TupleType::get(children, ctx); - scopes.back().push_back(type); + scopes.back().push_back(Type(type)); break; } case RegexCaptureStructureCode::CaseCount: diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 360c3acb719e0..82045a86230f3 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -4096,6 +4096,9 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr, diagnose(repr->getLoc(), diag::tuple_duplicate_label); } + if (elements.size() == 1 && !elements[0].hasName()) + return ParenType::get(getASTContext(), elements[0].getType()); + return TupleType::get(elements, getASTContext()); } diff --git a/unittests/AST/IndexSubsetTests.cpp b/unittests/AST/IndexSubsetTests.cpp index 2630c7614a13f..135243297a231 100644 --- a/unittests/AST/IndexSubsetTests.cpp +++ b/unittests/AST/IndexSubsetTests.cpp @@ -260,8 +260,8 @@ TEST(IndexSubset, Lowering) { FunctionType::get({ FunctionType::Param(C.TheAnyType), FunctionType::Param( - TupleType::get({ - TupleType::get({C.TheAnyType, C.TheAnyType}, C)}, C)), + ParenType::get(C, + TupleType::get({C.TheAnyType, C.TheAnyType}, C))), FunctionType::Param( TupleType::get({C.TheAnyType, C.TheAnyType}, C)), FunctionType::Param(C.TheAnyType)}, From 7a335d6c66740c9a6e0d5403026c72ac8d4cf0fc Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 321/491] AST: Introduce @tuple (T) syntax for one-element tuples in SIL mode --- include/swift/AST/Attr.def | 1 + include/swift/AST/Attr.h | 3 +++ lib/AST/ASTPrinter.cpp | 6 ++++++ lib/AST/TypeRepr.cpp | 3 +++ lib/Parse/ParseDecl.cpp | 9 +++++++++ lib/Sema/TypeCheckType.cpp | 12 ++++++++++++ test/SIL/Parser/one_element_tuple.sil | 19 +++++++++++++++++++ 7 files changed, 53 insertions(+) create mode 100644 test/SIL/Parser/one_element_tuple.sil diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def index 29f4ba97643c3..1c0f34e329221 100644 --- a/include/swift/AST/Attr.def +++ b/include/swift/AST/Attr.def @@ -58,6 +58,7 @@ TYPE_ATTR(Sendable) TYPE_ATTR(unchecked) TYPE_ATTR(_typeSequence) TYPE_ATTR(_local) +TYPE_ATTR(tuple) // SIL-specific attributes TYPE_ATTR(block_storage) diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index d05c68a2bcd8e..44d74bdb6569e 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -2504,6 +2504,9 @@ class TypeAttributes { }; Optional OpaqueReturnTypeOf; + // Force construction of a one-element tuple type. + bool IsTuple = false; + TypeAttributes() {} bool isValid() const { return AtLoc.isValid(); } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 9e121cc4db6a4..d30e48e5c58da 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -5549,6 +5549,12 @@ class TypePrinter : public TypeVisitor { Printer.callPrintStructurePre(PrintStructureKind::TupleType); SWIFT_DEFER { Printer.printStructurePost(PrintStructureKind::TupleType); }; + // Single-element tuples can only appear in SIL mode. + if (T->getNumElements() == 1 && + !T->getElement(0).hasName()) { + Printer << "@tuple "; + } + Printer << "("; auto Fields = T->getElements(); diff --git a/lib/AST/TypeRepr.cpp b/lib/AST/TypeRepr.cpp index b4c79cfa9f3f2..583bc4c85b9f0 100644 --- a/lib/AST/TypeRepr.cpp +++ b/lib/AST/TypeRepr.cpp @@ -257,6 +257,9 @@ void AttributedTypeRepr::printAttrs(ASTPrinter &Printer, Printer.printSimpleAttr("@async") << " "; if (hasAttr(TAK_opened)) Printer.printSimpleAttr("@opened") << " "; + + if (hasAttr(TAK_tuple)) + Printer.printSimpleAttr("@tuple") << " "; } IdentTypeRepr *IdentTypeRepr::create(ASTContext &C, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 43ae1e676b983..913b99ea6f84e 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3798,6 +3798,15 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes, Attributes.setOpaqueReturnTypeOf(mangling, index); break; } + + case TAK_tuple: { + if (!isInSILMode()) { + diagnose(AtLoc, diag::only_allowed_in_sil, "tuple"); + return makeParserSuccess(); + } + + Attributes.IsTuple = true; + } } Attributes.setAttr(attr, AtLoc); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 82045a86230f3..5187b3b971290 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -2860,6 +2860,18 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr, if (!ty) ty = resolveType(repr, instanceOptions); if (!ty || ty->hasError()) return ty; + // In SIL mode only, build one-element tuples. + if (attrs.has(TAK_tuple)) { + SmallVector elements; + if (auto *parenTy = dyn_cast(ty.getPointer())) + ty = parenTy->getUnderlyingType(); + + elements.emplace_back(ty); + ty = TupleType::get(elements, getASTContext()); + + attrs.clearAttribute(TAK_tuple); + } + // Type aliases inside protocols are not yet resolved in the structural // stage of type resolution if (ty->is() && diff --git a/test/SIL/Parser/one_element_tuple.sil b/test/SIL/Parser/one_element_tuple.sil new file mode 100644 index 0000000000000..d7b244df23caf --- /dev/null +++ b/test/SIL/Parser/one_element_tuple.sil @@ -0,0 +1,19 @@ +// RUN: %target-sil-opt %s | %target-sil-opt | %FileCheck %s + +sil_stage canonical + +import Swift + +// CHECK-LABEL: sil [ossa] @tuple_test : $@convention(thin) (@tuple (Int)) -> @tuple (Int) { +// CHECK: bb0(%0 : $@tuple (Int)): +// CHECK-NEXT: %1 = tuple_extract %0 : $@tuple (Int), 0 +// CHECK-NEXT: %2 = tuple (%1 : $Int) +// CHECK-NEXT: return %2 : $@tuple (Int) +// CHECK-NEXT: } + +sil [ossa] @tuple_test : $@convention(thin) (@tuple (Int)) -> @tuple (Int) { +bb0(%0 : $@tuple (Int)): + %1 = tuple_extract %0 : $@tuple (Int), 0 + %2 = tuple $@tuple (Int) (%1) + return %2 : $@tuple (Int) +} From 5c32f2136ece4213adfdb27461721a6ba4ac672a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 322/491] AST: Introduce RequirementKind::SameCount --- include/swift/AST/DiagnosticsSema.def | 4 +- include/swift/AST/Requirement.h | 1 + include/swift/AST/RequirementBase.h | 7 ++- include/swift/SIL/SILWitnessVisitor.h | 3 ++ lib/AST/ASTDemangler.cpp | 2 + lib/AST/ASTMangler.cpp | 19 ++++++-- lib/AST/ASTPrinter.cpp | 17 +++++++- lib/AST/Decl.cpp | 3 ++ lib/AST/GenericSignature.cpp | 43 +++++++++++++++++++ .../ConcreteContraction.cpp | 6 +++ lib/AST/RequirementMachine/Diagnostics.cpp | 3 ++ .../RequirementLowering.cpp | 6 +++ lib/AST/RequirementMachine/RuleBuilder.cpp | 3 ++ lib/AST/Type.cpp | 2 + lib/AST/TypeWalker.cpp | 1 + lib/IRGen/GenMeta.cpp | 3 ++ lib/IRGen/GenProto.cpp | 1 + lib/SIL/IR/AbstractionPattern.cpp | 3 ++ lib/SIL/IR/SIL.cpp | 1 + .../Mandatory/Differentiation.cpp | 3 ++ lib/SILOptimizer/Utils/Generics.cpp | 2 + lib/Sema/CSFix.cpp | 6 +++ lib/Sema/CSSimplify.cpp | 6 +++ lib/Sema/ConstraintLocator.cpp | 3 ++ lib/Sema/ConstraintSystem.cpp | 5 +++ lib/Sema/TypeCheckAccess.cpp | 1 + lib/Sema/TypeCheckAttr.cpp | 3 ++ lib/Sema/TypeCheckConstraints.cpp | 3 ++ lib/Sema/TypeCheckDeclPrimary.cpp | 1 + lib/Sema/TypeCheckGeneric.cpp | 4 ++ lib/Sema/TypeCheckProtocol.cpp | 6 +++ lib/Sema/TypeCheckProtocolInference.cpp | 8 ++++ lib/Serialization/ModuleFormat.h | 13 +++--- lib/Serialization/Serialization.cpp | 3 +- lib/SymbolGraphGen/JSON.cpp | 3 ++ stdlib/public/Reflection/TypeRef.cpp | 42 ++++++++++-------- tools/swift-ide-test/ModuleAPIDiff.cpp | 1 + 37 files changed, 209 insertions(+), 32 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 1f4e6b9c29926..98c05b53c45b3 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2340,10 +2340,10 @@ NOTE(protocol_witness_type_conflict,none, "candidate has non-matching type %0%1", (Type, StringRef)) NOTE(protocol_witness_missing_requirement,none, "candidate would match if %0 %select{conformed to|subclassed|" - "was the same type as}2 %1", (Type, Type, unsigned)) + "was the same type as|%error|%error}2 %1", (Type, Type, unsigned)) NOTE(protocol_type_witness_missing_requirement,none, "candidate would match if the conformance required that %0 " - "%select{conformed to|subclassed|was the same type as}2 %1", + "%select{conformed to|subclassed|was the same type as|%error|%error}2 %1", (Type, Type, unsigned)) NOTE(protocol_witness_optionality_conflict,none, diff --git a/include/swift/AST/Requirement.h b/include/swift/AST/Requirement.h index d1acb9034f87a..489e332fdedeb 100644 --- a/include/swift/AST/Requirement.h +++ b/include/swift/AST/Requirement.h @@ -58,6 +58,7 @@ class Requirement Requirement subst(Args &&...args) const { auto newFirst = getFirstType().subst(std::forward(args)...); switch (getKind()) { + case RequirementKind::SameCount: case RequirementKind::Conformance: case RequirementKind::Superclass: case RequirementKind::SameType: { diff --git a/include/swift/AST/RequirementBase.h b/include/swift/AST/RequirementBase.h index 8a33684ede78e..ead10647edc46 100644 --- a/include/swift/AST/RequirementBase.h +++ b/include/swift/AST/RequirementBase.h @@ -36,8 +36,11 @@ enum class RequirementKind : unsigned { /// A layout bound T : L, where T is a type that depends on a generic /// parameter and L is some layout specification that should bound T. Layout, + /// A same-count requirement T.count == U.count, where T and U are pack + /// parameters. + SameCount - // Note: there is code that packs this enum in a 2-bit bitfield. Audit users + // Note: there is code that packs this enum in a 3-bit bitfield. Audit users // when adding enumerators. }; @@ -102,6 +105,7 @@ class RequirementBase { hash_value(requirement.FirstTypeAndKind.getOpaqueValue()); llvm::hash_code second; switch (requirement.getKind()) { + case RequirementKind::SameCount: case RequirementKind::Conformance: case RequirementKind::Superclass: case RequirementKind::SameType: @@ -123,6 +127,7 @@ class RequirementBase { return false; switch (lhs.getKind()) { + case RequirementKind::SameCount: case RequirementKind::Conformance: case RequirementKind::Superclass: case RequirementKind::SameType: diff --git a/include/swift/SIL/SILWitnessVisitor.h b/include/swift/SIL/SILWitnessVisitor.h index f4ecf7f3f08bc..4f204276b6c25 100644 --- a/include/swift/SIL/SILWitnessVisitor.h +++ b/include/swift/SIL/SILWitnessVisitor.h @@ -57,6 +57,9 @@ template class SILWitnessVisitor : public ASTVisitor { auto requirements = protocol->getRequirementSignature().getRequirements(); for (const auto &reqt : requirements) { switch (reqt.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + // These requirements don't show up in the witness table. case RequirementKind::Superclass: case RequirementKind::SameType: diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index dfea8569906bc..4a6511c1ece78 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -635,6 +635,8 @@ Type ASTBuilder::createConstrainedExistentialType( llvm::SmallDenseMap cmap; for (const auto &req : constraints) { switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); case RequirementKind::Conformance: case RequirementKind::Superclass: case RequirementKind::Layout: diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index 166a95f7593c5..93db5c596c623 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -2862,8 +2862,10 @@ void ASTMangler::appendRequirement(const Requirement &reqt, Type FirstTy = reqt.getFirstType()->getCanonicalType(); switch (reqt.getKind()) { - case RequirementKind::Layout: { - } break; + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Layout: + break; case RequirementKind::Conformance: { // If we don't allow marker protocols but we have one here, skip it. if (!AllowMarkerProtocols && @@ -2876,12 +2878,15 @@ void ASTMangler::appendRequirement(const Requirement &reqt, case RequirementKind::SameType: { Type SecondTy = reqt.getSecondType(); appendType(SecondTy->getCanonicalType(), sig); - } break; + break; + } } if (auto *DT = FirstTy->getAs()) { if (tryMangleTypeSubstitution(DT, sig)) { switch (reqt.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); case RequirementKind::Conformance: return appendOperator("RQ"); case RequirementKind::Layout: @@ -2901,6 +2906,8 @@ void ASTMangler::appendRequirement(const Requirement &reqt, addTypeSubstitution(DT, sig); assert(gpBase); switch (reqt.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); case RequirementKind::Conformance: return appendOpWithGenericParamIndex(isAssocTypeAtDepth ? "RP" : "Rp", gpBase, lhsBaseIsProtocolSelf); @@ -2920,6 +2927,8 @@ void ASTMangler::appendRequirement(const Requirement &reqt, } GenericTypeParamType *gpBase = FirstTy->castTo(); switch (reqt.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); case RequirementKind::Conformance: return appendOpWithGenericParamIndex("R", gpBase); case RequirementKind::Layout: @@ -3479,6 +3488,8 @@ void ASTMangler::appendConcreteProtocolConformance( bool firstRequirement = true; for (const auto &conditionalReq : conformance->getConditionalRequirements()) { switch (conditionalReq.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); case RequirementKind::Layout: case RequirementKind::SameType: case RequirementKind::Superclass: @@ -3628,6 +3639,8 @@ void ASTMangler::appendConstrainedExistential(Type base, GenericSignature sig, bool firstRequirement = true; for (const auto &reqt : requirements) { switch (reqt.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); case RequirementKind::Layout: case RequirementKind::Conformance: case RequirementKind::Superclass: diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index d30e48e5c58da..90142c91446c9 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -240,6 +240,7 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint, if (!isPublicOrUsableFromInline(req.getSecondType())) return false; break; + case RequirementKind::SameCount: case RequirementKind::Layout: break; } @@ -1414,6 +1415,8 @@ bestRequirementPrintLocation(ProtocolDecl *proto, const Requirement &req) { bool inWhereClause; switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirements not supported here"); case RequirementKind::Layout: case RequirementKind::Conformance: case RequirementKind::Superclass: { @@ -1505,7 +1508,8 @@ static unsigned getDepthOfRequirement(const Requirement &req) { return getDepthOfType(req.getFirstType()); case RequirementKind::Superclass: - case RequirementKind::SameType: { + case RequirementKind::SameType: + case RequirementKind::SameCount: { // Return the max valid depth of firstType and secondType. unsigned firstDepth = getDepthOfType(req.getFirstType()); unsigned secondDepth = getDepthOfType(req.getSecondType()); @@ -1752,6 +1756,9 @@ void PrintAST::printSingleDepthOfGenericSignature( // We only print the second part of a requirement in the "inherited" // clause. switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Layout: req.getLayoutConstraint()->print(Printer, Options); break; @@ -1780,6 +1787,11 @@ void PrintAST::printSingleDepthOfGenericSignature( void PrintAST::printRequirement(const Requirement &req) { printTransformedType(req.getFirstType()); switch (req.getKind()) { + case RequirementKind::SameCount: + Printer << ".count == "; + printTransformedType(req.getSecondType()); + Printer << ".count"; + return; case RequirementKind::Layout: Printer << " : "; req.getLayoutConstraint()->print(Printer, Options); @@ -6659,6 +6671,9 @@ void Requirement::dump() const { } void Requirement::dump(raw_ostream &out) const { switch (getKind()) { + case RequirementKind::SameCount: + out << "same_count: "; + break; case RequirementKind::Conformance: out << "conforms_to: "; break; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 8fa5a636320e6..4f409449baa93 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -4044,6 +4044,9 @@ findGenericParameterReferences(CanGenericSignature genericSig, auto opaqueSig = opaque->getDecl()->getOpaqueInterfaceGenericSignature(); for (const auto &req : opaqueSig.getRequirements()) { switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: case RequirementKind::Layout: continue; diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 28f247f0539f6..44ef29a1c9650 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -599,6 +599,7 @@ bool Requirement::isCanonical() const { return false; switch (getKind()) { + case RequirementKind::SameCount: case RequirementKind::Conformance: case RequirementKind::SameType: case RequirementKind::Superclass: @@ -618,6 +619,7 @@ Requirement Requirement::getCanonical() const { Type firstType = getFirstType()->getCanonicalType(); switch (getKind()) { + case RequirementKind::SameCount: case RequirementKind::Conformance: case RequirementKind::SameType: case RequirementKind::Superclass: { @@ -640,6 +642,9 @@ bool Requirement::isSatisfied(ArrayRef &conditionalRequirements, bool allowMissing) const { switch (getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirements not supported here"); + case RequirementKind::Conformance: { auto *proto = getProtocolDecl(); auto *module = proto->getParentModule(); @@ -678,6 +683,9 @@ Requirement::isSatisfied(ArrayRef &conditionalRequirements, bool Requirement::canBeSatisfied() const { switch (getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirements not supported here"); + case RequirementKind::Conformance: return getFirstType()->is(); @@ -705,6 +713,7 @@ bool Requirement::canBeSatisfied() const { /// Determine the canonical ordering of requirements. static unsigned getRequirementKindOrder(RequirementKind kind) { switch (kind) { + case RequirementKind::SameCount: return 4; case RequirementKind::Conformance: return 2; case RequirementKind::Superclass: return 0; case RequirementKind::SameType: return 3; @@ -852,6 +861,36 @@ void GenericSignature::verify(ArrayRef reqts) const { // Check canonicalization of requirement itself. switch (reqt.getKind()) { + case RequirementKind::SameCount: + if (!reqt.getFirstType()->is()) { + llvm::errs() << "Left hand side is not a generic parameter: "; + reqt.dump(llvm::errs()); + llvm::errs() << "\n"; + abort(); + } + + if (!reqt.getFirstType()->castTo()->isTypeSequence()) { + llvm::errs() << "Left hand side is not a type sequence: "; + reqt.dump(llvm::errs()); + llvm::errs() << "\n"; + abort(); + } + + if (!reqt.getSecondType()->is()) { + llvm::errs() << "Right hand side is not a generic parameter: "; + reqt.dump(llvm::errs()); + llvm::errs() << "\n"; + abort(); + } + + if (!reqt.getSecondType()->castTo()->isTypeSequence()) { + llvm::errs() << "Right hand side is not a type sequence: "; + reqt.dump(llvm::errs()); + llvm::errs() << "\n"; + abort(); + } + + break; case RequirementKind::Superclass: if (!canSig->isReducedType(reqt.getSecondType())) { llvm::errs() << "Right-hand side is not reduced: "; @@ -1020,6 +1059,10 @@ static Requirement stripBoundDependentMemberTypes(Requirement req) { auto subjectType = stripBoundDependentMemberTypes(req.getFirstType()); switch (req.getKind()) { + case RequirementKind::SameCount: + // Same-count requirements do not involve dependent member types. + return req; + case RequirementKind::Conformance: return Requirement(RequirementKind::Conformance, subjectType, req.getSecondType()); diff --git a/lib/AST/RequirementMachine/ConcreteContraction.cpp b/lib/AST/RequirementMachine/ConcreteContraction.cpp index b48001fa32071..c953cf8742d4c 100644 --- a/lib/AST/RequirementMachine/ConcreteContraction.cpp +++ b/lib/AST/RequirementMachine/ConcreteContraction.cpp @@ -371,6 +371,9 @@ ConcreteContraction::substRequirement(const Requirement &req) const { auto firstType = req.getFirstType(); switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Superclass: case RequirementKind::SameType: { auto position = (req.getKind() == RequirementKind::Superclass @@ -550,6 +553,9 @@ bool ConcreteContraction::performConcreteContraction( auto kind = req.req.getKind(); switch (kind) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::SameType: { auto constraintType = req.req.getSecondType(); diff --git a/lib/AST/RequirementMachine/Diagnostics.cpp b/lib/AST/RequirementMachine/Diagnostics.cpp index 9d90125f37346..31b684509b59b 100644 --- a/lib/AST/RequirementMachine/Diagnostics.cpp +++ b/lib/AST/RequirementMachine/Diagnostics.cpp @@ -168,6 +168,9 @@ bool swift::rewriting::diagnoseRequirementErrors( break; switch (requirement.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::SameType: ctx.Diags.diagnose(loc, diag::redundant_same_type_to_concrete, requirement.getFirstType(), diff --git a/lib/AST/RequirementMachine/RequirementLowering.cpp b/lib/AST/RequirementMachine/RequirementLowering.cpp index 30a3c1ed95821..2d2f0b4adf625 100644 --- a/lib/AST/RequirementMachine/RequirementLowering.cpp +++ b/lib/AST/RequirementMachine/RequirementLowering.cpp @@ -361,6 +361,9 @@ swift::rewriting::desugarRequirement(Requirement req, SourceLoc loc, auto firstType = req.getFirstType(); switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: desugarConformanceRequirement(firstType, req.getSecondType(), loc, result, errors); @@ -574,6 +577,9 @@ void swift::rewriting::realizeRequirement( auto *moduleForInference = dc->getParentModule(); switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Superclass: case RequirementKind::Conformance: { auto secondType = req.getSecondType(); diff --git a/lib/AST/RequirementMachine/RuleBuilder.cpp b/lib/AST/RequirementMachine/RuleBuilder.cpp index dd6338528052f..999f24fc5e01b 100644 --- a/lib/AST/RequirementMachine/RuleBuilder.cpp +++ b/lib/AST/RequirementMachine/RuleBuilder.cpp @@ -298,6 +298,9 @@ void RuleBuilder::addRequirement(const Requirement &req, MutableTerm constraintTerm; switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: { // A conformance requirement T : P becomes a rewrite rule // diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index fdc4bc35d0021..7599f72c5a7ac 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -4179,6 +4179,8 @@ CanType ProtocolCompositionType::getMinimalCanonicalType( } switch (Req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); case RequirementKind::Superclass: case RequirementKind::Conformance: MinimalMembers.push_back(Req.getSecondType()); diff --git a/lib/AST/TypeWalker.cpp b/lib/AST/TypeWalker.cpp index 8c11d3c805a80..d7cd7ce080442 100644 --- a/lib/AST/TypeWalker.cpp +++ b/lib/AST/TypeWalker.cpp @@ -114,6 +114,7 @@ class Traversal : public TypeVisitor return true; switch (req.getKind()) { + case RequirementKind::SameCount: case RequirementKind::SameType: case RequirementKind::Conformance: case RequirementKind::Superclass: diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 0d1e4b5ed5973..367f14ed9c1ef 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -5903,6 +5903,9 @@ GenericRequirementsMetadata irgen::addGenericRequirements( GenericRequirementsMetadata metadata; for (auto &requirement : requirements) { switch (auto kind = requirement.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Layout: ++metadata.NumRequirements; diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index c536f4e350f6d..2f64c9743bccc 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -267,6 +267,7 @@ irgen::enumerateGenericSignatureRequirements(CanGenericSignature signature, for (auto &reqt : signature.getRequirements()) { switch (reqt.getKind()) { // Ignore these; they don't introduce extra requirements. + case RequirementKind::SameCount: case RequirementKind::Superclass: case RequirementKind::SameType: case RequirementKind::Layout: diff --git a/lib/SIL/IR/AbstractionPattern.cpp b/lib/SIL/IR/AbstractionPattern.cpp index 826802e7dff97..60989810fd5fe 100644 --- a/lib/SIL/IR/AbstractionPattern.cpp +++ b/lib/SIL/IR/AbstractionPattern.cpp @@ -1635,6 +1635,9 @@ class SubstFunctionTypePatternVisitor for (auto reqt : nomGenericSig.getRequirements()) { auto firstTy = reqt.getFirstType().subst(substGPMap); switch (auto kind = reqt.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::SameType: // Skip same-type constraints that define away primary generic params, // since we didn't duplicate those params. diff --git a/lib/SIL/IR/SIL.cpp b/lib/SIL/IR/SIL.cpp index bb7815b12cbbe..bc459bf44685c 100644 --- a/lib/SIL/IR/SIL.cpp +++ b/lib/SIL/IR/SIL.cpp @@ -163,6 +163,7 @@ FormalLinkage swift::getGenericSignatureLinkage(CanGenericSignature sig) { // a dependent type. switch (req.getKind()) { + case RequirementKind::SameCount: case RequirementKind::Layout: continue; diff --git a/lib/SILOptimizer/Mandatory/Differentiation.cpp b/lib/SILOptimizer/Mandatory/Differentiation.cpp index 653b0c2a9d0d6..fb5fe28b10fa3 100644 --- a/lib/SILOptimizer/Mandatory/Differentiation.cpp +++ b/lib/SILOptimizer/Mandatory/Differentiation.cpp @@ -227,6 +227,9 @@ static bool diagnoseUnsatisfiedRequirements(ADContext &context, } } switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + // Check layout requirements. case RequirementKind::Layout: { auto layout = req.getLayoutConstraint(); diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp index a4389a87e3753..585cba0899972 100644 --- a/lib/SILOptimizer/Utils/Generics.cpp +++ b/lib/SILOptimizer/Utils/Generics.cpp @@ -960,6 +960,7 @@ static bool hasNonSelfContainedRequirements(ArchetypeType *Archetype, // FIXME: Second type of a superclass requirement may contain // generic parameters. continue; + case RequirementKind::SameCount: case RequirementKind::SameType: { // Check if this requirement contains more than one generic param. // If this is the case, then these archetypes are interdependent and @@ -1011,6 +1012,7 @@ static void collectRequirements(ArchetypeType *Archetype, GenericSignature Sig, CurrentGP) CollectedReqs.push_back(Req); continue; + case RequirementKind::SameCount: case RequirementKind::SameType: { // Check if this requirement contains more than one generic param. // If this is the case, then these archetypes are interdependent and diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 5fbff6ca998c8..305103e4153a9 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -2413,6 +2413,9 @@ bool AddExplicitExistentialCoercion::isRequired( ArrayRef requirements) { for (const auto &req : requirements) { switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Superclass: case RequirementKind::Conformance: case RequirementKind::Layout: { @@ -2446,6 +2449,9 @@ bool AddExplicitExistentialCoercion::isRequired( auto requirementSig = protocol->getRequirementSignature(); for (const auto &req : requirementSig.getRequirements()) { switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: case RequirementKind::Layout: case RequirementKind::Superclass: { diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 7969cd587d3e5..77fdbaeb6f4b4 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3979,6 +3979,9 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1, auto *reqLoc = cs.getConstraintLocator(anchor, path); switch (req.getRequirementKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::SameType: { return SkipSameTypeRequirement::create(cs, type1, type2, reqLoc); } @@ -13435,6 +13438,9 @@ void ConstraintSystem::addConstraint(Requirement req, bool conformsToAnyObject = false; Optional kind; switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: kind = ConstraintKind::ConformsTo; break; diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp index 571e63335baf5..9a70d9274ddca 100644 --- a/lib/Sema/ConstraintLocator.cpp +++ b/lib/Sema/ConstraintLocator.cpp @@ -122,6 +122,9 @@ void LocatorPathElt::dump(raw_ostream &out) const { auto dumpReqKind = [&out](RequirementKind kind) { out << " ("; switch (kind) { + case RequirementKind::SameCount: + out << "same_length"; + break; case RequirementKind::Conformance: out << "conformance"; break; diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index d571c2461e4fe..47a625c1af7a0 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1773,6 +1773,8 @@ void ConstraintSystem::openGenericRequirement( auto kind = req.getKind(); switch (kind) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); case RequirementKind::Conformance: { auto protoDecl = req.getProtocolDecl(); // Determine whether this is the protocol 'Self' constraint we should @@ -6566,6 +6568,9 @@ static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase( for (const auto &req : sig.getRequirements()) { switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Superclass: { if (req.getFirstType()->getRootGenericParam()->getDepth() > 0 && req.getSecondType().walk(isDependentOnSelfWalker)) { diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 99021c873ea1e..3a99c4a9540af 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -41,6 +41,7 @@ static void forAllRequirementTypes( std::move(source).visitRequirements(TypeResolutionStage::Interface, [&](const Requirement &req, RequirementRepr *reqRepr) { switch (req.getKind()) { + case RequirementKind::SameCount: case RequirementKind::Conformance: case RequirementKind::SameType: case RequirementKind::Superclass: diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 48421c9cd73e4..099c545b0d047 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2493,6 +2493,9 @@ static void checkSpecializeAttrRequirements(SpecializeAttr *attr, } switch (specializedReq.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: case RequirementKind::Superclass: ctx.Diags.diagnose(attr->getLocation(), diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index fe8f68d6c8cc7..13ac1fe7ff5d1 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -642,6 +642,9 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue, auto &requirement = requirements[reqIdx]; switch (requirement.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::SameType: { auto lhsTy = requirement.getFirstType(); auto rhsTy = requirement.getSecondType(); diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 05ced7bc9bed0..2cfd7ba1dcb61 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1132,6 +1132,7 @@ static void checkProtocolSelfRequirements(ProtocolDecl *proto, TypeResolutionStage::Interface, [proto](const Requirement &req, RequirementRepr *reqRepr) { switch (req.getKind()) { + case RequirementKind::SameCount: case RequirementKind::Conformance: case RequirementKind::Layout: case RequirementKind::Superclass: diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 947a300f205a1..e3a10ff2ff6d6 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -356,6 +356,7 @@ void TypeChecker::checkReferencedGenericParams(GenericContext *dc) { Type second; switch (req.getKind()) { + case RequirementKind::SameCount: case RequirementKind::Superclass: case RequirementKind::SameType: second = req.getSecondType(); @@ -786,6 +787,9 @@ void TypeChecker::diagnoseRequirementFailure( const auto reqKind = req.getKind(); switch (reqKind) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: { diagnoseConformanceFailure(substReq.getFirstType(), substReq.getProtocolDecl(), module, errorLoc); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 057293663a943..ea4f7d8a3a380 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -4896,6 +4896,9 @@ hasInvariantSelfRequirement(const ProtocolDecl *proto, for (auto req : reqSig) { switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::SameType: if (req.getSecondType()->isTypeParameter()) { if (req.getFirstType()->isEqual(selfTy)) @@ -4927,6 +4930,9 @@ static void diagnoseInvariantSelfRequirement( unsigned kind = 0; switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::SameType: if (req.getSecondType()->isTypeParameter()) { // eg, 'Self == Self.A.B' diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 2278a8f4171f7..5cf4b71d3b210 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -317,6 +317,9 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses( for (auto &reqt : witnessContext->getGenericSignatureOfContext() .getRequirements()) { switch (reqt.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: case RequirementKind::Superclass: case RequirementKind::Layout: @@ -1067,6 +1070,9 @@ static void sanitizeProtocolRequirements( for (const auto &req : requirements) { switch (req.getKind()) { + case RequirementKind::SameCount: + llvm_unreachable("Same-count requirement not supported here"); + case RequirementKind::Conformance: case RequirementKind::SameType: case RequirementKind::Superclass: { @@ -1732,6 +1738,7 @@ static Comparison compareDeclsForInference(DeclContext *DC, ValueDecl *decl1, class1 = reqt.getSecondType(); break; + case RequirementKind::SameCount: case RequirementKind::SameType: case RequirementKind::Layout: break; @@ -1764,6 +1771,7 @@ static Comparison compareDeclsForInference(DeclContext *DC, ValueDecl *decl1, class2 = reqt.getSecondType(); break; + case RequirementKind::SameCount: case RequirementKind::SameType: case RequirementKind::Layout: break; diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index eed474946e0dc..d5f9e212923af 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 704; // _eagerMove/_lexical function argument attributes +const uint16_t SWIFTMODULE_VERSION_MINOR = 705; // same-length requirements /// A standard hash seed used for all string hashes in a serialized module. /// @@ -435,12 +435,13 @@ static inline OperatorFixity getASTOperatorFixity(OperatorKind fixity) { // These IDs must \em not be renumbered or reordered without incrementing // the module version. enum GenericRequirementKind : uint8_t { - Conformance = 0, - SameType = 1, - Superclass = 2, - Layout = 3, + SameCount = 0, + Conformance = 1, + SameType = 2, + Superclass = 3, + Layout = 4, }; -using GenericRequirementKindField = BCFixed<2>; +using GenericRequirementKindField = BCFixed<3>; // These IDs must \em not be renumbered or reordered without incrementing // the module version. diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 716662be9b68a..0904c6e7cdd8c 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1,4 +1,4 @@ -//===--- Serialization.cpp - Read and write Swift modules -----------------===// + //===--- Serialization.cpp - Read and write Swift modules -----------------===// // // This source file is part of the Swift.org open source project // @@ -1337,6 +1337,7 @@ static uint8_t getRawStableRequirementKind(RequirementKind kind) { return GenericRequirementKind::KIND; switch (kind) { + CASE(SameCount) CASE(Conformance) CASE(Superclass) CASE(SameType) diff --git a/lib/SymbolGraphGen/JSON.cpp b/lib/SymbolGraphGen/JSON.cpp index 575e13d2a3dc1..c0614dbaa7fd5 100644 --- a/lib/SymbolGraphGen/JSON.cpp +++ b/lib/SymbolGraphGen/JSON.cpp @@ -90,6 +90,9 @@ void swift::symbolgraphgen::serialize(const Requirement &Req, llvm::json::OStream &OS) { StringRef Kind; switch (Req.getKind()) { + case RequirementKind::SameCount: + Kind = "sameLength"; + break; case RequirementKind::Conformance: Kind = "conformance"; break; diff --git a/stdlib/public/Reflection/TypeRef.cpp b/stdlib/public/Reflection/TypeRef.cpp index f29b88a77c170..2072cfc58ddb4 100644 --- a/stdlib/public/Reflection/TypeRef.cpp +++ b/stdlib/public/Reflection/TypeRef.cpp @@ -314,6 +314,12 @@ class PrintTypeRef : public TypeRefVisitor { void visitTypeRefRequirement(const TypeRefRequirement &req) { printHeader("requirement "); switch (req.getKind()) { + case RequirementKind::SameCount: + printRec(req.getFirstType()); + stream << ".count == "; + printRec(req.getSecondType()); + stream << ".count"; + break; case RequirementKind::Conformance: case RequirementKind::Superclass: printRec(req.getFirstType()); @@ -892,25 +898,24 @@ class DemanglingForTypeRef Demangle::NodePointer visitTypeRefRequirement(const TypeRefRequirement &req) { switch (req.getKind()) { - case RequirementKind::Conformance: - case RequirementKind::Superclass: + case RequirementKind::SameCount: { + // Not implemented. + return nullptr; + } + case RequirementKind::Conformance: { + auto r = Dem.createNode(Node::Kind::DependentGenericConformanceRequirement); + r->addChild(visit(req.getFirstType()), Dem); + r->addChild(visit(req.getSecondType()), Dem); + return r; + } + case RequirementKind::Superclass: { + auto r = Dem.createNode(Node::Kind::DependentGenericConformanceRequirement); + r->addChild(visit(req.getFirstType()), Dem); + r->addChild(visit(req.getSecondType()), Dem); + return r; + } case RequirementKind::SameType: { - Node::Kind kind; - switch (req.getKind()) { - case RequirementKind::Conformance: - kind = Node::Kind::DependentGenericConformanceRequirement; - break; - case RequirementKind::Superclass: - // A DependentGenericSuperclasseRequirement kind seems to be missing. - kind = Node::Kind::DependentGenericConformanceRequirement; - break; - case RequirementKind::SameType: - kind = Node::Kind::DependentGenericSameTypeRequirement; - break; - default: - llvm_unreachable("Unhandled requirement kind"); - } - auto r = Dem.createNode(kind); + auto r = Dem.createNode(Node::Kind::DependentGenericSameTypeRequirement); r->addChild(visit(req.getFirstType()), Dem); r->addChild(visit(req.getSecondType()), Dem); return r; @@ -1299,6 +1304,7 @@ class TypeRefSubstitution return None; switch (req.getKind()) { + case RequirementKind::SameCount: case RequirementKind::Conformance: case RequirementKind::Superclass: case RequirementKind::SameType: { diff --git a/tools/swift-ide-test/ModuleAPIDiff.cpp b/tools/swift-ide-test/ModuleAPIDiff.cpp index 18336629d77b1..d34fe56e87bb4 100644 --- a/tools/swift-ide-test/ModuleAPIDiff.cpp +++ b/tools/swift-ide-test/ModuleAPIDiff.cpp @@ -756,6 +756,7 @@ class SMAModelGenerator : public DeclVisitor { convertToTypeName(Req.getSecondType())}); break; case RequirementKind::Layout: + case RequirementKind::SameCount: // FIXME assert(false && "Not implemented"); break; From 22dc9882b0d2757b68da7541df49148d236f7343 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 323/491] AST: Stub out ASTContext::getOpenedElementSignature() --- include/swift/AST/ASTContext.h | 7 ++++ lib/AST/ASTContext.cpp | 75 ++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index 359ac897fa7a4..d321e6bd7faca 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -1346,6 +1346,13 @@ class ASTContext final { CanGenericSignature getOpenedExistentialSignature(Type type, GenericSignature parentSig); + /// Get a generic signature where the generic parameter Ï„_d_i represents + /// the element of the pack generic parameter Ï„_d_i… in \p baseGenericSig. + /// + /// This drops the @_typeSequence attribute from each generic parameter, + /// and converts same-element requirements to same-type requirements. + CanGenericSignature getOpenedElementSignature(CanGenericSignature baseGenericSig); + GenericSignature getOverrideGenericSignature(const ValueDecl *base, const ValueDecl *derived); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index df573a5c605ed..009dbfbf6ba6f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -342,6 +342,11 @@ struct ASTContext::Implementation { llvm::DenseMap, CanGenericSignature> ExistentialSignatures; + /// The element signature for a generic signature, constructed by dropping + /// @_typeSequence attributes from generic parameters. + llvm::DenseMap ElementSignatures; + /// Overridden declarations. llvm::DenseMap> Overrides; @@ -5256,6 +5261,76 @@ ASTContext::getOpenedExistentialSignature(Type type, GenericSignature parentSig) return canGenericSig; } +CanGenericSignature +ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) { + auto &sigs = getImpl().ElementSignatures; + auto found = sigs.find(baseGenericSig.getPointer()); + if (found != sigs.end()) + return found->second; + + // This operation doesn't make sense if the input signature does not contain` + // any pack generic parameters. +#ifndef NDEBUG + { + auto found = std::find_if(baseGenericSig.getGenericParams().begin(), + baseGenericSig.getGenericParams().end(), + [](GenericTypeParamType *paramType) { + return paramType->isTypeSequence(); + }); + assert(found != baseGenericSig.getGenericParams().end()); + } +#endif + + SmallVector genericParams; + SmallVector requirements; + + auto eraseTypeSequence = [&](GenericTypeParamType *paramType) { + return GenericTypeParamType::get( + paramType->getDepth(), paramType->getIndex(), + /*isTypeSequence=*/false, *this); + }; + + for (auto paramType : baseGenericSig.getGenericParams()) { + genericParams.push_back(eraseTypeSequence(paramType)); + } + + auto eraseTypeSequenceRec = [&](Type type) -> Type { + return type.transformRec([&](Type t) -> Optional { + if (auto *paramType = t->getAs()) + return Type(eraseTypeSequence(paramType)); + return None; + }); + }; + + for (auto requirement : baseGenericSig.getRequirements()) { + switch (requirement.getKind()) { + case RequirementKind::SameCount: + // Drop same-length requirements from the element signature. + break; + case RequirementKind::Conformance: + case RequirementKind::Superclass: + case RequirementKind::SameType: + requirements.emplace_back( + requirement.getKind(), + eraseTypeSequenceRec(requirement.getFirstType()), + eraseTypeSequenceRec(requirement.getSecondType())); + break; + case RequirementKind::Layout: + requirements.emplace_back( + requirement.getKind(), + eraseTypeSequenceRec(requirement.getFirstType()), + requirement.getLayoutConstraint()); + break; + } + } + + auto elementSig = buildGenericSignature( + *this, GenericSignature(), genericParams, requirements) + .getCanonicalSignature(); + sigs[baseGenericSig.getPointer()] = elementSig; + return elementSig; +} + GenericSignature ASTContext::getOverrideGenericSignature(const ValueDecl *base, const ValueDecl *derived) { From 3992b18e0b7d7b874f9ea1e2a7d36fdc883ff51c Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 324/491] AST: Move some code from ASTPrinter.cpp to ASTDumper.cpp --- lib/AST/ASTDumper.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++ lib/AST/ASTPrinter.cpp | 66 ---------------------------------------- 2 files changed, 68 insertions(+), 66 deletions(-) diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 6a6d07389a7b5..49063d787972f 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -4188,3 +4188,71 @@ void StableSerializationPath::dump(llvm::raw_ostream &os) const { os << "\n"; } } + +void RequirementRepr::dump() const { + print(llvm::errs()); + llvm::errs() << "\n"; +} + +void GenericParamList::dump() const { + print(llvm::errs()); + llvm::errs() << '\n'; +} + +void LayoutConstraint::dump() const { + if (!*this) { + llvm::errs() << "(null)\n"; + return; + } + getPointer()->print(llvm::errs()); +} + +void GenericSignature::dump() const { + print(llvm::errs()); + llvm::errs() << '\n'; +} + +void Requirement::dump() const { + dump(llvm::errs()); + llvm::errs() << '\n'; +} +void Requirement::dump(raw_ostream &out) const { + switch (getKind()) { + case RequirementKind::SameCount: + out << "same_count: "; + break; + case RequirementKind::Conformance: + out << "conforms_to: "; + break; + case RequirementKind::Layout: + out << "layout: "; + break; + case RequirementKind::Superclass: + out << "superclass: "; + break; + case RequirementKind::SameType: + out << "same_type: "; + break; + } + + PrintOptions opts; + opts.ProtocolQualifiedDependentMemberTypes = true; + + getFirstType().print(out, opts); + out << " "; + + if (getKind() != RequirementKind::Layout && getSecondType()) + getSecondType().print(out, opts); + else if (getLayoutConstraint()) + out << getLayoutConstraint(); +} + +void SILParameterInfo::dump() const { + print(llvm::errs()); + llvm::errs() << '\n'; +} + +void SILResultInfo::dump() const { + print(llvm::errs()); + llvm::errs() << '\n'; +} diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 90142c91446c9..32eef577b483a 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -6629,14 +6629,6 @@ void LayoutConstraintInfo::print(ASTPrinter &Printer, } } -void LayoutConstraint::dump() const { - if (!*this) { - llvm::errs() << "(null)\n"; - return; - } - getPointer()->print(llvm::errs()); -} - void GenericSignatureImpl::print(raw_ostream &OS, PrintOptions PO) const { GenericSignature(const_cast(this)).print(OS, PO); } @@ -6660,46 +6652,6 @@ void GenericSignature::print(ASTPrinter &Printer, PrintAST::PrintRequirements); } -void GenericSignature::dump() const { - print(llvm::errs()); - llvm::errs() << '\n'; -} - -void Requirement::dump() const { - dump(llvm::errs()); - llvm::errs() << '\n'; -} -void Requirement::dump(raw_ostream &out) const { - switch (getKind()) { - case RequirementKind::SameCount: - out << "same_count: "; - break; - case RequirementKind::Conformance: - out << "conforms_to: "; - break; - case RequirementKind::Layout: - out << "layout: "; - break; - case RequirementKind::Superclass: - out << "superclass: "; - break; - case RequirementKind::SameType: - out << "same_type: "; - break; - } - - PrintOptions opts; - opts.ProtocolQualifiedDependentMemberTypes = true; - - getFirstType().print(out, opts); - out << " "; - - if (getKind() != RequirementKind::Layout && getSecondType()) - getSecondType().print(out, opts); - else if (getLayoutConstraint()) - out << getLayoutConstraint(); -} - void Requirement::print(raw_ostream &os, const PrintOptions &opts) const { StreamPrinter printer(os); PrintAST(printer, opts).printRequirement(*this); @@ -6756,10 +6708,6 @@ StringRef swift::getCheckedCastKindName(CheckedCastKind kind) { llvm_unreachable("bad checked cast name"); } -void SILParameterInfo::dump() const { - print(llvm::errs()); - llvm::errs() << '\n'; -} void SILParameterInfo::print(raw_ostream &OS, const PrintOptions &Opts) const { StreamPrinter Printer(OS); print(Printer, Opts); @@ -6788,10 +6736,6 @@ static StringRef getStringForResultConvention(ResultConvention conv) { llvm_unreachable("bad result convention"); } -void SILResultInfo::dump() const { - print(llvm::errs()); - llvm::errs() << '\n'; -} void SILResultInfo::print(raw_ostream &OS, const PrintOptions &Opts) const { StreamPrinter Printer(OS); print(Printer, Opts); @@ -7056,11 +7000,6 @@ swift::getInheritedForPrinting( // Generic param list printing. //===----------------------------------------------------------------------===// -void RequirementRepr::dump() const { - print(llvm::errs()); - llvm::errs() << "\n"; -} - void RequirementRepr::print(raw_ostream &out) const { StreamPrinter printer(out); print(printer); @@ -7103,11 +7042,6 @@ void RequirementRepr::print(ASTPrinter &out) const { } } -void GenericParamList::dump() const { - print(llvm::errs()); - llvm::errs() << '\n'; -} - void GenericParamList::print(raw_ostream &out, const PrintOptions &PO) const { StreamPrinter printer(out); print(printer, PO); From e08e525063ee66ae4f64163cf7d35e8fba24a529 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 325/491] AST: Split off ProtocolConformanceRef.cpp from ProtocolConformance.cpp --- lib/AST/CMakeLists.txt | 1 + lib/AST/ProtocolConformance.cpp | 283 +------------------------- lib/AST/ProtocolConformanceRef.cpp | 305 +++++++++++++++++++++++++++++ 3 files changed, 307 insertions(+), 282 deletions(-) create mode 100644 lib/AST/ProtocolConformanceRef.cpp diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 39629f01cfaeb..a63679c3148ee 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -74,6 +74,7 @@ add_swift_host_library(swiftAST STATIC PlatformKind.cpp PrettyStackTrace.cpp ProtocolConformance.cpp + ProtocolConformanceRef.cpp RawComment.cpp RequirementEnvironment.cpp RequirementMachine/ConcreteContraction.cpp diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index 76b79a2a32643..f86dfde7c40d6 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the protocol conformance data structures. +// This file implements the ProtocolConformance class hierarchy. // //===----------------------------------------------------------------------===// @@ -25,13 +25,9 @@ #include "swift/AST/LazyResolver.h" #include "swift/AST/Module.h" #include "swift/AST/TypeCheckRequests.h" -#include "swift/AST/TypeWalker.h" #include "swift/AST/Types.h" -#include "swift/AST/TypeCheckRequests.h" #include "swift/Basic/Statistic.h" -#include "llvm/ADT/MapVector.h" #include "llvm/ADT/Statistic.h" -#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SaveAndRestore.h" @@ -79,128 +75,6 @@ void Witness::dump(llvm::raw_ostream &out) const { } } -ProtocolConformanceRef::ProtocolConformanceRef(ProtocolDecl *protocol, - ProtocolConformance *conf) { - assert(protocol != nullptr && - "cannot construct ProtocolConformanceRef with null protocol"); - if (conf) { - assert(protocol == conf->getProtocol() && "protocol conformance mismatch"); - Union = conf; - } else { - Union = protocol; - } -} - -ProtocolDecl *ProtocolConformanceRef::getRequirement() const { - assert(!isInvalid()); - - if (isConcrete()) { - return getConcrete()->getProtocol(); - } else { - return getAbstract(); - } -} - -ProtocolConformanceRef -ProtocolConformanceRef::subst(Type origType, - SubstitutionMap subMap, - SubstOptions options) const { - return subst(origType, - QuerySubstitutionMap{subMap}, - LookUpConformanceInSubstitutionMap(subMap), - options); -} - -ProtocolConformanceRef -ProtocolConformanceRef::subst(Type origType, - TypeSubstitutionFn subs, - LookupConformanceFn conformances, - SubstOptions options) const { - if (isInvalid()) - return *this; - - // If we have a concrete conformance, we need to substitute the - // conformance to apply to the new type. - if (isConcrete()) - return ProtocolConformanceRef(getConcrete()->subst(subs, conformances, - options)); - // If the type is an opaque archetype, the conformance will remain abstract, - // unless we're specifically substituting opaque types. - if (auto origArchetype = origType->getAs()) { - if (!options.contains(SubstFlags::SubstituteOpaqueArchetypes) - && isa(origArchetype)) { - return *this; - } - } - - // Otherwise, compute the substituted type. - auto substType = origType.subst(subs, conformances, options); - - auto *proto = getRequirement(); - - // If the type is an existential, it must be self-conforming. - if (substType->isExistentialType()) { - auto optConformance = - proto->getModuleContext()->lookupExistentialConformance(substType, - proto); - if (optConformance) - return optConformance; - - return ProtocolConformanceRef::forInvalid(); - } - - // Check the conformance map. - return conformances(origType->getCanonicalType(), substType, proto); -} - -ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() const { - if (!isConcrete()) - return *this; - - auto *concrete = getConcrete()->subst( - [](SubstitutableType *type) -> Type { - if (auto *archetypeType = type->getAs()) - return archetypeType->getInterfaceType(); - return type; - }, - MakeAbstractConformanceForGenericType()); - return ProtocolConformanceRef(concrete); -} - -Type -ProtocolConformanceRef::getTypeWitnessByName(Type type, Identifier name) const { - assert(!isInvalid()); - - // Find the named requirement. - ProtocolDecl *proto = getRequirement(); - auto *assocType = proto->getAssociatedType(name); - - // FIXME: Shouldn't this be a hard error? - if (!assocType) - return ErrorType::get(proto->getASTContext()); - - return assocType->getDeclaredInterfaceType().subst( - SubstitutionMap::getProtocolSubstitutions(proto, type, *this)); -} - -ConcreteDeclRef -ProtocolConformanceRef::getWitnessByName(Type type, DeclName name) const { - // Find the named requirement. - auto *proto = getRequirement(); - auto *requirement = proto->getSingleRequirement(name); - if (requirement == nullptr) - return ConcreteDeclRef(); - - // For a type with dependent conformance, just return the requirement from - // the protocol. There are no protocol conformance tables. - if (!isConcrete()) { - auto subs = SubstitutionMap::getProtocolSubstitutions(proto, type, *this); - return ConcreteDeclRef(requirement, subs); - } - - return getConcrete()->getWitnessDeclRef(requirement); -} - #define CONFORMANCE_SUBCLASS_DISPATCH(Method, Args) \ switch (getKind()) { \ case ProtocolConformanceKind::Normal: \ @@ -455,26 +329,6 @@ ArrayRef ProtocolConformance::getConditionalRequirements() const { CONFORMANCE_SUBCLASS_DISPATCH(getConditionalRequirements, ()); } -Optional> -ProtocolConformanceRef::getConditionalRequirementsIfAvailable() const { - if (isConcrete()) - return getConcrete()->getConditionalRequirementsIfAvailable(); - else - // An abstract conformance is never conditional: any conditionality in the - // concrete types that will eventually pass through this at runtime is - // completely pre-checked and packaged up. - return ArrayRef(); -} - -ArrayRef -ProtocolConformanceRef::getConditionalRequirements() const { - if (isConcrete()) - return getConcrete()->getConditionalRequirements(); - else - // An abstract conformance is never conditional, as above. - return {}; -} - Optional> NormalProtocolConformance::getConditionalRequirementsIfAvailable() const { const auto &eval = getDeclContext()->getASTContext().evaluator; @@ -682,54 +536,6 @@ Type ProtocolConformance::getAssociatedType(Type assocType) const { return ref.getAssociatedType(getType(), assocType); } -Type ProtocolConformanceRef::getAssociatedType(Type conformingType, - Type assocType) const { - assert(!isConcrete() || getConcrete()->getType()->isEqual(conformingType)); - - auto type = assocType->getCanonicalType(); - auto proto = getRequirement(); - - // Fast path for generic parameters. - if (isa(type)) { - assert(type->isEqual(proto->getSelfInterfaceType()) && - "type parameter in protocol was not Self"); - return conformingType; - } - - // Fast path for dependent member types on 'Self' of our associated types. - auto memberType = cast(type); - if (memberType.getBase()->isEqual(proto->getSelfInterfaceType()) && - memberType->getAssocType()->getProtocol() == proto && - isConcrete()) - return getConcrete()->getTypeWitness(memberType->getAssocType()); - - // General case: consult the substitution map. - auto substMap = - SubstitutionMap::getProtocolSubstitutions(proto, conformingType, *this); - return type.subst(substMap); -} - -ProtocolConformanceRef -ProtocolConformanceRef::getAssociatedConformance(Type conformingType, - Type assocType, - ProtocolDecl *protocol) const { - // If this is a concrete conformance, look up the associated conformance. - if (isConcrete()) { - auto conformance = getConcrete(); - assert(conformance->getType()->isEqual(conformingType)); - return conformance->getAssociatedConformance(assocType, protocol); - } - - // Otherwise, apply the substitution {self -> conformingType} - // to the abstract conformance requirement laid upon the dependent type - // by the protocol. - auto subMap = - SubstitutionMap::getProtocolSubstitutions(getRequirement(), - conformingType, *this); - auto abstractConf = ProtocolConformanceRef(protocol); - return abstractConf.subst(assocType, subMap); -} - ProtocolConformanceRef ProtocolConformance::getAssociatedConformance(Type assocType, ProtocolDecl *protocol) const { @@ -1669,20 +1475,6 @@ ProtocolConformance *ProtocolConformance::getCanonicalConformance() { llvm_unreachable("bad ProtocolConformanceKind"); } -/// Check of all types used by the conformance are canonical. -bool ProtocolConformanceRef::isCanonical() const { - if (isAbstract() || isInvalid()) - return true; - return getConcrete()->isCanonical(); -} - -ProtocolConformanceRef -ProtocolConformanceRef::getCanonicalConformanceRef() const { - if (isAbstract() || isInvalid()) - return *this; - return ProtocolConformanceRef(getConcrete()->getCanonicalConformance()); -} - BuiltinProtocolConformance::BuiltinProtocolConformance( Type conformingType, ProtocolDecl *protocol, GenericSignature genericSig, @@ -1742,76 +1534,3 @@ void swift::simple_display(llvm::raw_ostream &out, SourceLoc swift::extractNearestSourceLoc(const ProtocolConformance *conformance) { return extractNearestSourceLoc(conformance->getDeclContext()); } - -void swift::simple_display(llvm::raw_ostream &out, ProtocolConformanceRef conformanceRef) { - if (conformanceRef.isAbstract()) { - simple_display(out, conformanceRef.getAbstract()); - } else if (conformanceRef.isConcrete()) { - simple_display(out, conformanceRef.getConcrete()); - } -} - -SourceLoc swift::extractNearestSourceLoc(const ProtocolConformanceRef conformanceRef) { - if (conformanceRef.isAbstract()) { - return extractNearestSourceLoc(conformanceRef.getAbstract()); - } else if (conformanceRef.isConcrete()) { - return extractNearestSourceLoc(conformanceRef.getConcrete()); - } - return SourceLoc(); -} - -bool ProtocolConformanceRef::hasUnavailableConformance() const { - if (isInvalid()) - return false; - - // Abstract conformances are never unavailable. - if (!isConcrete()) - return false; - - // Check whether this conformance is on an unavailable extension. - auto concrete = getConcrete(); - auto ext = dyn_cast(concrete->getDeclContext()); - if (ext && AvailableAttr::isUnavailable(ext)) - return true; - - // Check the conformances in the substitution map. - auto module = concrete->getDeclContext()->getParentModule(); - auto subMap = concrete->getSubstitutions(module); - for (auto subConformance : subMap.getConformances()) { - if (subConformance.hasUnavailableConformance()) - return true; - } - - return false; -} - -bool ProtocolConformanceRef::hasMissingConformance(ModuleDecl *module) const { - return forEachMissingConformance(module, - [](BuiltinProtocolConformance *builtin) { - return true; - }); -} - -bool ProtocolConformanceRef::forEachMissingConformance( - ModuleDecl *module, - llvm::function_ref fn) const { - if (!isConcrete()) - return false; - - // Is this a missing conformance? - ProtocolConformance *concreteConf = getConcrete(); - RootProtocolConformance *rootConf = concreteConf->getRootConformance(); - if (auto builtinConformance = dyn_cast(rootConf)){ - if (builtinConformance->isMissing() && fn(builtinConformance)) - return true; - } - - // Check conformances that are part of this conformance. - auto subMap = concreteConf->getSubstitutions(module); - for (auto conformance : subMap.getConformances()) { - if (conformance.forEachMissingConformance(module, fn)) - return true; - } - - return false; -} diff --git a/lib/AST/ProtocolConformanceRef.cpp b/lib/AST/ProtocolConformanceRef.cpp new file mode 100644 index 0000000000000..1a15136b701fa --- /dev/null +++ b/lib/AST/ProtocolConformanceRef.cpp @@ -0,0 +1,305 @@ +//===--- ProtocolConformance.cpp - AST Protocol Conformance Reference -----===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements the ProtocolConformanceRef structure, which wraps a +// concrete or abstract conformance, or is invalid. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/ProtocolConformanceRef.h" +#include "swift/AST/ASTContext.h" +#include "swift/AST/Availability.h" +#include "swift/AST/Decl.h" +#include "swift/AST/Module.h" +#include "swift/AST/TypeCheckRequests.h" +#include "swift/AST/Types.h" + +#define DEBUG_TYPE "AST" + +using namespace swift; + +ProtocolConformanceRef::ProtocolConformanceRef(ProtocolDecl *protocol, + ProtocolConformance *conf) { + assert(protocol != nullptr && + "cannot construct ProtocolConformanceRef with null protocol"); + if (conf) { + assert(protocol == conf->getProtocol() && "protocol conformance mismatch"); + Union = conf; + } else { + Union = protocol; + } +} + +ProtocolDecl *ProtocolConformanceRef::getRequirement() const { + assert(!isInvalid()); + + if (isConcrete()) { + return getConcrete()->getProtocol(); + } else { + return getAbstract(); + } +} + +ProtocolConformanceRef +ProtocolConformanceRef::subst(Type origType, + SubstitutionMap subMap, + SubstOptions options) const { + return subst(origType, + QuerySubstitutionMap{subMap}, + LookUpConformanceInSubstitutionMap(subMap), + options); +} + +ProtocolConformanceRef +ProtocolConformanceRef::subst(Type origType, + TypeSubstitutionFn subs, + LookupConformanceFn conformances, + SubstOptions options) const { + if (isInvalid()) + return *this; + + // If we have a concrete conformance, we need to substitute the + // conformance to apply to the new type. + if (isConcrete()) + return ProtocolConformanceRef(getConcrete()->subst(subs, conformances, + options)); + // If the type is an opaque archetype, the conformance will remain abstract, + // unless we're specifically substituting opaque types. + if (auto origArchetype = origType->getAs()) { + if (!options.contains(SubstFlags::SubstituteOpaqueArchetypes) + && isa(origArchetype)) { + return *this; + } + } + + // Otherwise, compute the substituted type. + auto substType = origType.subst(subs, conformances, options); + + auto *proto = getRequirement(); + + // If the type is an existential, it must be self-conforming. + if (substType->isExistentialType()) { + auto optConformance = + proto->getModuleContext()->lookupExistentialConformance(substType, + proto); + if (optConformance) + return optConformance; + + return ProtocolConformanceRef::forInvalid(); + } + + // Check the conformance map. + return conformances(origType->getCanonicalType(), substType, proto); +} + +ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() const { + if (!isConcrete()) + return *this; + + auto *concrete = getConcrete()->subst( + [](SubstitutableType *type) -> Type { + if (auto *archetypeType = type->getAs()) + return archetypeType->getInterfaceType(); + return type; + }, + MakeAbstractConformanceForGenericType()); + return ProtocolConformanceRef(concrete); +} + +Type +ProtocolConformanceRef::getTypeWitnessByName(Type type, Identifier name) const { + assert(!isInvalid()); + + // Find the named requirement. + ProtocolDecl *proto = getRequirement(); + auto *assocType = proto->getAssociatedType(name); + + // FIXME: Shouldn't this be a hard error? + if (!assocType) + return ErrorType::get(proto->getASTContext()); + + return assocType->getDeclaredInterfaceType().subst( + SubstitutionMap::getProtocolSubstitutions(proto, type, *this)); +} + +ConcreteDeclRef +ProtocolConformanceRef::getWitnessByName(Type type, DeclName name) const { + // Find the named requirement. + auto *proto = getRequirement(); + auto *requirement = proto->getSingleRequirement(name); + if (requirement == nullptr) + return ConcreteDeclRef(); + + // For a type with dependent conformance, just return the requirement from + // the protocol. There are no protocol conformance tables. + if (!isConcrete()) { + auto subs = SubstitutionMap::getProtocolSubstitutions(proto, type, *this); + return ConcreteDeclRef(requirement, subs); + } + + return getConcrete()->getWitnessDeclRef(requirement); +} + +Optional> +ProtocolConformanceRef::getConditionalRequirementsIfAvailable() const { + if (isConcrete()) + return getConcrete()->getConditionalRequirementsIfAvailable(); + else + // An abstract conformance is never conditional: any conditionality in the + // concrete types that will eventually pass through this at runtime is + // completely pre-checked and packaged up. + return ArrayRef(); +} + +ArrayRef +ProtocolConformanceRef::getConditionalRequirements() const { + if (isConcrete()) + return getConcrete()->getConditionalRequirements(); + else + // An abstract conformance is never conditional, as above. + return {}; +} + +Type ProtocolConformanceRef::getAssociatedType(Type conformingType, + Type assocType) const { + assert(!isConcrete() || getConcrete()->getType()->isEqual(conformingType)); + + auto type = assocType->getCanonicalType(); + auto proto = getRequirement(); + + // Fast path for generic parameters. + if (isa(type)) { + assert(type->isEqual(proto->getSelfInterfaceType()) && + "type parameter in protocol was not Self"); + return conformingType; + } + + // Fast path for dependent member types on 'Self' of our associated types. + auto memberType = cast(type); + if (memberType.getBase()->isEqual(proto->getSelfInterfaceType()) && + memberType->getAssocType()->getProtocol() == proto && + isConcrete()) + return getConcrete()->getTypeWitness(memberType->getAssocType()); + + // General case: consult the substitution map. + auto substMap = + SubstitutionMap::getProtocolSubstitutions(proto, conformingType, *this); + return type.subst(substMap); +} + +ProtocolConformanceRef +ProtocolConformanceRef::getAssociatedConformance(Type conformingType, + Type assocType, + ProtocolDecl *protocol) const { + // If this is a concrete conformance, look up the associated conformance. + if (isConcrete()) { + auto conformance = getConcrete(); + assert(conformance->getType()->isEqual(conformingType)); + return conformance->getAssociatedConformance(assocType, protocol); + } + + // Otherwise, apply the substitution {self -> conformingType} + // to the abstract conformance requirement laid upon the dependent type + // by the protocol. + auto subMap = + SubstitutionMap::getProtocolSubstitutions(getRequirement(), + conformingType, *this); + auto abstractConf = ProtocolConformanceRef(protocol); + return abstractConf.subst(assocType, subMap); +} + +/// Check of all types used by the conformance are canonical. +bool ProtocolConformanceRef::isCanonical() const { + if (isAbstract() || isInvalid()) + return true; + return getConcrete()->isCanonical(); +} + +ProtocolConformanceRef +ProtocolConformanceRef::getCanonicalConformanceRef() const { + if (isAbstract() || isInvalid()) + return *this; + return ProtocolConformanceRef(getConcrete()->getCanonicalConformance()); +} + +bool ProtocolConformanceRef::hasUnavailableConformance() const { + if (isInvalid()) + return false; + + // Abstract conformances are never unavailable. + if (!isConcrete()) + return false; + + // Check whether this conformance is on an unavailable extension. + auto concrete = getConcrete(); + auto ext = dyn_cast(concrete->getDeclContext()); + if (ext && AvailableAttr::isUnavailable(ext)) + return true; + + // Check the conformances in the substitution map. + auto module = concrete->getDeclContext()->getParentModule(); + auto subMap = concrete->getSubstitutions(module); + for (auto subConformance : subMap.getConformances()) { + if (subConformance.hasUnavailableConformance()) + return true; + } + + return false; +} + +bool ProtocolConformanceRef::hasMissingConformance(ModuleDecl *module) const { + return forEachMissingConformance(module, + [](BuiltinProtocolConformance *builtin) { + return true; + }); +} + +bool ProtocolConformanceRef::forEachMissingConformance( + ModuleDecl *module, + llvm::function_ref fn) const { + if (!isConcrete()) + return false; + + // Is this a missing conformance? + ProtocolConformance *concreteConf = getConcrete(); + RootProtocolConformance *rootConf = concreteConf->getRootConformance(); + if (auto builtinConformance = dyn_cast(rootConf)){ + if (builtinConformance->isMissing() && fn(builtinConformance)) + return true; + } + + // Check conformances that are part of this conformance. + auto subMap = concreteConf->getSubstitutions(module); + for (auto conformance : subMap.getConformances()) { + if (conformance.forEachMissingConformance(module, fn)) + return true; + } + + return false; +} + +void swift::simple_display(llvm::raw_ostream &out, ProtocolConformanceRef conformanceRef) { + if (conformanceRef.isAbstract()) { + simple_display(out, conformanceRef.getAbstract()); + } else if (conformanceRef.isConcrete()) { + simple_display(out, conformanceRef.getConcrete()); + } +} + +SourceLoc swift::extractNearestSourceLoc(const ProtocolConformanceRef conformanceRef) { + if (conformanceRef.isAbstract()) { + return extractNearestSourceLoc(conformanceRef.getAbstract()); + } else if (conformanceRef.isConcrete()) { + return extractNearestSourceLoc(conformanceRef.getConcrete()); + } + return SourceLoc(); +} From e75174e51dc9e314b7251ac581a114c851a262c3 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 326/491] AST: Introduce TypeBase::getTypeSequenceParameters() --- include/swift/AST/Types.h | 5 +++++ lib/AST/Type.cpp | 22 ++++++++++++++++++++++ lib/Sema/TypeCheckDecl.cpp | 16 ++++------------ lib/Sema/TypeCheckType.cpp | 17 ++++------------- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 42c597bfddf50..68c366041ed37 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -654,6 +654,11 @@ class alignas(1 << TypeAlignInBits) TypeBase void getRootOpenedExistentials( SmallVectorImpl &rootOpenedArchetypes) const; + /// Retrieve the set of type sequence generic parameters that occur + /// within this type. + void getTypeSequenceParameters( + SmallVectorImpl &rootTypeSequenceParams) const; + /// Replace opened archetypes with the given root with their most /// specific non-dependent upper bounds throughout this type. Type typeEraseOpenedArchetypesWithRoot(const OpenedArchetypeType *root, diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 7599f72c5a7ac..fa18d17d8bbe0 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -580,6 +580,28 @@ Type TypeBase::typeEraseOpenedArchetypesWithRoot( return transformFn(type); } +void TypeBase::getTypeSequenceParameters( + SmallVectorImpl &rootTypeSequenceParams) const { + llvm::SmallDenseSet visited; + + auto recordType = [&](Type t) { + if (visited.insert(t->getCanonicalType()).second) + rootTypeSequenceParams.push_back(t); + }; + + Type(const_cast(this)).visit([&](Type t) { + if (auto *paramTy = t->getAs()) { + if (paramTy->isTypeSequence()) { + recordType(paramTy); + } + } else if (auto *archetypeTy = t->getAs()) { + if (archetypeTy->isRoot()) { + recordType(t); + } + } + }); +} + Type TypeBase::addCurriedSelfType(const DeclContext *dc) { if (!dc->isTypeContext()) return this; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 3ffff5cf16688..686842510d745 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2228,21 +2228,13 @@ static Type validateParameterType(ParamDecl *decl) { if (decl->isVariadic()) { // Find the first type sequence parameter and use that as the count type. - Type countTy; - (void) Ty.findIf([&](Type t) -> bool { - if (auto *paramTy = t->getAs()) { - if (paramTy->isTypeSequence()) { - countTy = paramTy; - return true; - } - } + SmallVector rootTypeSequenceParams; + Ty->getTypeSequenceParameters(rootTypeSequenceParams); - return false; - }); // Handle the monovariadic/polyvariadic interface type split. - if (countTy) { + if (!rootTypeSequenceParams.empty()) { // Polyvariadic types (T...) for resolve to pack expansions. - Ty = PackExpansionType::get(Ty, countTy); + Ty = PackExpansionType::get(Ty, rootTypeSequenceParams[0]); } else { // Monovariadic types (T...) for resolve to [T]. Ty = VariadicSequenceType::get(Ty); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 5187b3b971290..eed633a73d52e 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -4031,27 +4031,18 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr, complained = true; // Find the first type sequence parameter and use that as the count type. - Type countTy; - (void) patternTy.get().findIf([&](Type t) -> bool { - if (auto *paramTy = t->getAs()) { - if (paramTy->isTypeSequence()) { - countTy = paramTy; - return true; - } - } - - return false; - }); + SmallVector rootTypeSequenceParams; + patternTy->getTypeSequenceParameters(rootTypeSequenceParams); // If there's no reference to a variadic generic parameter, complain // - the pack won't actually expand to anything meaningful. - if (!countTy) { + if (rootTypeSequenceParams.empty()) { diagnose(repr->getLoc(), diag::expansion_not_variadic, patternTy) .highlight(repr->getParens()); return ErrorType::get(getASTContext()); } - return PackExpansionType::get(patternTy, countTy); + return PackExpansionType::get(patternTy, rootTypeSequenceParams[0]); } else { // Variadic tuples are not permitted. // From 74723a99d7352b605ff2766ad21b25c157aa9bda Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Tue, 23 Aug 2022 13:31:46 +0100 Subject: [PATCH 327/491] [cxx-interop] Move included stdlib headers from `libstdcxx.h` to the modulemap By referencing a C++ stdlib header directly from the modulemap, we make sure that the header is treated as a part of the stdlib, not a part of the first clang module to include it. Addresses the issue described in https://forums.swift.org/t/llvm-fails-to-build-with-modules/59700/8. --- stdlib/public/Cxx/std/libstdcxx.h | 52 ---------------------- stdlib/public/Cxx/std/libstdcxx.modulemap | 53 +++++++++++++++++++++++ 2 files changed, 53 insertions(+), 52 deletions(-) diff --git a/stdlib/public/Cxx/std/libstdcxx.h b/stdlib/public/Cxx/std/libstdcxx.h index edb832db976f3..6533cb298456f 100644 --- a/stdlib/public/Cxx/std/libstdcxx.h +++ b/stdlib/public/Cxx/std/libstdcxx.h @@ -1,55 +1,3 @@ -#include "algorithm" -#include "bitset" -#include "complex" -#include "deque" -#include "exception" -#include "fstream" -#include "functional" -#include "iomanip" -#include "ios" -#include "iosfwd" -#include "iostream" -#include "istream" -#include "iterator" -#include "limits" -#include "list" -#include "locale" -#include "map" -#include "memory" -#include "new" -#include "numeric" -#include "ostream" -#include "queue" -#include "set" -#include "sstream" -#include "stack" -#include "stdexcept" -#include "streambuf" -#include "string" -#include "utility" -#include "typeinfo" -#include "valarray" -#include "vector" -#include "array" -#include "atomic" -#include "chrono" -#include "condition_variable" -#include "forward_list" -#include "future" -#include "initializer_list" -#include "mutex" -#include "random" -#include "ratio" -#include "regex" -#include "scoped_allocator" -#include "system_error" -#include "thread" -#include "tuple" -#include "typeindex" -#include "type_traits" -#include "unordered_map" -#include "unordered_set" - // libstdc++ 4.8.5 bundled with CentOS 7 does not include corecvt. #if __has_include("codecvt") #include "codecvt" diff --git a/stdlib/public/Cxx/std/libstdcxx.modulemap b/stdlib/public/Cxx/std/libstdcxx.modulemap index d8200ec6cf2e0..dea858c436ca7 100644 --- a/stdlib/public/Cxx/std/libstdcxx.modulemap +++ b/stdlib/public/Cxx/std/libstdcxx.modulemap @@ -18,6 +18,59 @@ module std { header "libstdcxx.h" + + header "algorithm" + header "bitset" + header "complex" + header "deque" + header "exception" + header "fstream" + header "functional" + header "iomanip" + header "ios" + header "iosfwd" + header "iostream" + header "istream" + header "iterator" + header "limits" + header "list" + header "locale" + header "map" + header "memory" + header "new" + header "numeric" + header "ostream" + header "queue" + header "set" + header "sstream" + header "stack" + header "stdexcept" + header "streambuf" + header "string" + header "utility" + header "typeinfo" + header "valarray" + header "vector" + header "array" + header "atomic" + header "chrono" + header "condition_variable" + header "forward_list" + header "future" + header "initializer_list" + header "mutex" + header "random" + header "ratio" + header "regex" + header "scoped_allocator" + header "system_error" + header "thread" + header "tuple" + header "typeindex" + header "type_traits" + header "unordered_map" + header "unordered_set" + requires cplusplus export * From f13a6ac0500f43ab15f063c96943372fc846015c Mon Sep 17 00:00:00 2001 From: Eric Miotto <1094986+edymtt@users.noreply.github.com> Date: Tue, 23 Aug 2022 12:09:54 -0700 Subject: [PATCH 328/491] Bootstrapping0: copy all the legacy layouts for the host platform (#60724) When cross compiling we are forcing the usage of the resource directory from the bootstrapping0 compiler to ensure we are picking up the stdlib from the SDK. As a result we need to ensure to have legacy layouts for all the architectures in that folder. Addresses rdar://98899578 --- stdlib/toolchain/legacy_layouts/CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/stdlib/toolchain/legacy_layouts/CMakeLists.txt b/stdlib/toolchain/legacy_layouts/CMakeLists.txt index a504aa37985bc..ad18c6b1b32d7 100644 --- a/stdlib/toolchain/legacy_layouts/CMakeLists.txt +++ b/stdlib/toolchain/legacy_layouts/CMakeLists.txt @@ -56,8 +56,15 @@ foreach(sdk ${SWIFT_SDKS}) endforeach() if(${BOOTSTRAPPING_MODE} MATCHES "BOOTSTRAPPING.*") - # Bootstrapping - level 0 - add_layout_copying( ${SWIFT_HOST_VARIANT_SDK} ${SWIFT_HOST_VARIANT_ARCH} "0") + # The resource dir for bootstrapping0 may be used explicitly + # to cross compile for other architectures, so we would need + # to have all the legacy layouts in there + foreach(arch + ${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_ARCHITECTURES} + ${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_MODULE_ARCHITECTURES}) + # Bootstrapping - level 0 + add_layout_copying( ${SWIFT_HOST_VARIANT_SDK} ${arch} "0") + endforeach() # Bootstrapping - level 1 add_layout_copying( ${SWIFT_HOST_VARIANT_SDK} ${SWIFT_HOST_VARIANT_ARCH} "1") From ed34dfc637732c600f9143fde6cee56a79848e9e Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 23 Aug 2022 10:56:58 -0700 Subject: [PATCH 329/491] [Syntax] Introduce UnresolvedIsExpr/UnresolvedAsExpr SequenceExprSyntax should have odd number elements. Previously 'a as b' was parsed like: ``` (sequence_expr (identifier_expr "a"), (as_expr 'as' (typeidentifier "b"))) ``` So it had even number elements. Now it's parsed ``` (sequence_expr (identifier_expr "a"), (unresolved_as_expr 'as') (type_expr (typeidentifier "b"))) ``` --- lib/Parse/ParseExpr.cpp | 32 +++++++++++------ lib/Parse/SyntaxParsingContext.cpp | 3 +- .../round_trip_parse_gen.swift.withkinds | 8 ++--- utils/gyb_syntax_support/ExprNodes.py | 34 +++++++++++++++++-- .../NodeSerializationCodes.py | 2 ++ 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index fb1c4bba559dc..c18a08f425395 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -72,9 +72,15 @@ ParserResult Parser::parseExprImpl(Diag<> Message, /// expr-is: /// 'is' type ParserResult Parser::parseExprIs() { - SourceLoc isLoc = consumeToken(tok::kw_is); + SourceLoc isLoc; + { + SyntaxParsingContext IsExprCtx(SyntaxContext, SyntaxKind::UnresolvedIsExpr); + isLoc = consumeToken(tok::kw_is); + } ParserResult type = parseType(diag::expected_type_after_is); + SyntaxContext->createNodeInPlace(SyntaxKind::TypeExpr); + if (type.hasCodeCompletion()) return makeParserCodeCompletionResult(); if (type.isNull()) @@ -89,19 +95,25 @@ ParserResult Parser::parseExprIs() { /// 'as?' type /// 'as!' type ParserResult Parser::parseExprAs() { - // Parse the 'as'. - SourceLoc asLoc = consumeToken(tok::kw_as); - - // Parse the postfix '?'. + SourceLoc asLoc; SourceLoc questionLoc; SourceLoc exclaimLoc; - if (Tok.is(tok::question_postfix)) { - questionLoc = consumeToken(tok::question_postfix); - } else if (Tok.is(tok::exclaim_postfix)) { - exclaimLoc = consumeToken(tok::exclaim_postfix); + + { + SyntaxParsingContext AsExprCtx(SyntaxContext, SyntaxKind::UnresolvedAsExpr); + // Parse the 'as'. + asLoc = consumeToken(tok::kw_as); + + // Parse the postfix '?'. + if (Tok.is(tok::question_postfix)) { + questionLoc = consumeToken(tok::question_postfix); + } else if (Tok.is(tok::exclaim_postfix)) { + exclaimLoc = consumeToken(tok::exclaim_postfix); + } } ParserResult type = parseType(diag::expected_type_after_as); + SyntaxContext->createNodeInPlace(SyntaxKind::TypeExpr); if (type.hasCodeCompletion()) return makeParserCodeCompletionResult(); @@ -295,7 +307,6 @@ ParserResult Parser::parseExprSequence(Diag<> Message, } case tok::kw_is: { - SyntaxParsingContext IsContext(SyntaxContext, SyntaxKind::IsExpr); // Parse a type after the 'is' token instead of an expression. ParserResult is = parseExprIs(); if (is.isNull() || is.hasCodeCompletion()) @@ -313,7 +324,6 @@ ParserResult Parser::parseExprSequence(Diag<> Message, } case tok::kw_as: { - SyntaxParsingContext AsContext(SyntaxContext, SyntaxKind::AsExpr); ParserResult as = parseExprAs(); if (as.isNull() || as.hasCodeCompletion()) return as; diff --git a/lib/Parse/SyntaxParsingContext.cpp b/lib/Parse/SyntaxParsingContext.cpp index 81fb7ffcf0021..ad1bc3eb76fd6 100644 --- a/lib/Parse/SyntaxParsingContext.cpp +++ b/lib/Parse/SyntaxParsingContext.cpp @@ -278,7 +278,8 @@ void SyntaxParsingContext::createNodeInPlace(SyntaxKind Kind, case SyntaxKind::AvailabilityLabeledArgument: case SyntaxKind::MetatypeType: case SyntaxKind::OptionalType: - case SyntaxKind::ImplicitlyUnwrappedOptionalType: { + case SyntaxKind::ImplicitlyUnwrappedOptionalType: + case SyntaxKind::TypeExpr: { auto Pair = SyntaxFactory::countChildren(Kind); assert(Pair.first == Pair.second); createNodeInPlace(Kind, Pair.first, nodeCreateK); diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds index 7a35b64b61a7a..4f34a50944133 100644 --- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds +++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds @@ -78,8 +78,8 @@ class C { _ = a.b _ = 1.a (1 + 1).a.b.foo - _ = a as Bool || a as! Bool || a as? Bool - _ = a is Bool + _ = a as Bool || a as! Bool || a as? Bool + _ = a is Bool _ = self _ = Self } @@ -326,13 +326,13 @@ private final class D { switch foo { case let a: break - case let a as Int: break + case let a as Int: break case let (a, b): break case (let a, var b): break case is Int: break case let .bar(x): break case MyEnum.foo: break - case let a as Int: break + case let a as Int: break case let a?: break } } diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py index c0416098da9cf..8224f72ea0887 100644 --- a/utils/gyb_syntax_support/ExprNodes.py +++ b/utils/gyb_syntax_support/ExprNodes.py @@ -351,16 +351,46 @@ is_optional=True), ]), - # is TypeName + # 'is' + # "is" type casting ooperator without operands. + # NOTE: This appears only in SequenceExpr. + Node('UnresolvedIsExpr', kind='Expr', + children=[ + Child("IsTok", kind='IsToken'), + ]), + + # expression is TypeName + # NOTE: This won't come directly out of the parser. Rather, it is the + # result of "folding" a SequenceExpr based on knowing the precedence + # relationships amongst the different infix operators. Node('IsExpr', kind='Expr', children=[ + Child("Expression", kind="Expr"), Child("IsTok", kind='IsToken'), Child("TypeName", kind='Type') ]), - # as TypeName + # 'as' ('?'|'!') + # "as" type casting ooperator without operands. + # NOTE: This appears only in SequenceExpr. + Node('UnresolvedAsExpr', kind='Expr', + children=[ + Child("AsTok", kind='AsToken'), + Child("QuestionOrExclamationMark", kind='Token', + is_optional=True, + token_choices=[ + 'PostfixQuestionMarkToken', + 'ExclamationMarkToken', + ]), + ]), + + # expression as TypeName + # NOTE: This won't come directly out of the parser. Rather, it is the + # result of "folding" a SequenceExpr based on knowing the precedence + # relationships amongst the different infix operators. Node('AsExpr', kind='Expr', children=[ + Child("Expression", kind="Expr"), Child("AsTok", kind='AsToken'), Child("QuestionOrExclamationMark", kind='Token', is_optional=True, diff --git a/utils/gyb_syntax_support/NodeSerializationCodes.py b/utils/gyb_syntax_support/NodeSerializationCodes.py index 8550d640ad519..a868dce363d47 100644 --- a/utils/gyb_syntax_support/NodeSerializationCodes.py +++ b/utils/gyb_syntax_support/NodeSerializationCodes.py @@ -272,6 +272,8 @@ 'InfixOperatorExpr': 268, 'MoveExpr': 269, 'UnresolvedTernaryExpr': 270, + 'UnresolvedIsExpr': 271, + 'UnresolvedAsExpr': 272, } From 3fcf2a204644a962348e0fedc90ab7c3d44ab732 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Thu, 18 Aug 2022 11:49:52 -0600 Subject: [PATCH 330/491] [test] pointer arithmetic overflow checks --- test/stdlib/UnsafePointer.swift.gyb | 22 ++++++ .../stdlib/UnsafeRawPointerInternal.swift | 72 +++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/test/stdlib/UnsafePointer.swift.gyb b/test/stdlib/UnsafePointer.swift.gyb index eb24e850589eb..6ffd35fd751cd 100644 --- a/test/stdlib/UnsafePointer.swift.gyb +++ b/test/stdlib/UnsafePointer.swift.gyb @@ -537,6 +537,28 @@ ${SelfName}TestSuite.test("pointer(to:)") { % end } +${SelfName}TestSuite.test("pointer(to:).overflow") { + struct Example { + var a = false + var b = 0 + var c: String { "\(a),\(b)" } + var d = 0.0 + } + let o = MemoryLayout.offset(of: \.b)! + let p = UnsafePointer(bitPattern: -o) + expectNotNil(p) + guard let p else { fatalError() } + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let intPointer = p.pointer(to: \.b) + expectNil(intPointer) // nil because of overflow + let stringPointer = p.pointer(to: \.c) + expectNil(stringPointer) // nil because c is a computed property + let doublePointer = p.pointer(to: \.d) + expectNotNil(doublePointer) +} + % end runAllTests() diff --git a/validation-test/stdlib/UnsafeRawPointerInternal.swift b/validation-test/stdlib/UnsafeRawPointerInternal.swift index 128358d9d64ff..967eae2958c4a 100644 --- a/validation-test/stdlib/UnsafeRawPointerInternal.swift +++ b/validation-test/stdlib/UnsafeRawPointerInternal.swift @@ -58,4 +58,76 @@ UnsafeRawPointerTestSuite.test("load.unaligned.largeAlignment.mutablePointer") } } +UnsafeRawPointerTestSuite.test("alignedUp.for.overflow") { + let p = UnsafeRawPointer(bitPattern: 1-MemoryLayout.stride)! + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let up = p.alignedUp(for: Int.self) + expectEqual(Int(bitPattern: up), 0) +} + +UnsafeRawPointerTestSuite.test("alignedUp.toMultiple.overflow") { + let p = UnsafeRawPointer(bitPattern: -7)! + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let up = p.alignedUp(toMultipleOf: 8) + expectEqual(Int(bitPattern: up), 0) +} + +UnsafeRawPointerTestSuite.test("alignedUp.for.overflow") { + let p = UnsafeRawPointer(bitPattern: MemoryLayout.stride-1)! + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let up = p.alignedDown(for: Int64.self) + expectEqual(Int(bitPattern: up), 0) +} + +UnsafeRawPointerTestSuite.test("alignedUp.toMultiple.overflow") { + let p = UnsafeRawPointer(bitPattern: 13)! + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let up = p.alignedDown(toMultipleOf: 16) + expectEqual(Int(bitPattern: up), 0) +} + +UnsafeRawPointerTestSuite.test("alignedUp.for.overflow.mutable") { + let p = UnsafeMutableRawPointer(bitPattern: 1-MemoryLayout.stride)! + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let up = p.alignedUp(for: Int.self) + expectEqual(Int(bitPattern: up), 0) +} + +UnsafeRawPointerTestSuite.test("alignedUp.toMultiple.overflow.mutable") { + let p = UnsafeMutableRawPointer(bitPattern: -7)! + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let up = p.alignedUp(toMultipleOf: 8) + expectEqual(Int(bitPattern: up), 0) +} + +UnsafeRawPointerTestSuite.test("alignedUp.for.overflow.mutable") { + let p = UnsafeMutableRawPointer(bitPattern: MemoryLayout.stride-1)! + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let up = p.alignedDown(for: Int64.self) + expectEqual(Int(bitPattern: up), 0) +} + +UnsafeRawPointerTestSuite.test("alignedUp.toMultiple.overflow.mutable") { + let p = UnsafeMutableRawPointer(bitPattern: 13)! + if _isDebugAssertConfiguration() { + expectCrashLater() + } + let up = p.alignedDown(toMultipleOf: 16) + expectEqual(Int(bitPattern: up), 0) +} + runAllTests() From fbfb4d5227ec2829b0fd8f635434bc1d1cec8e59 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 23 Aug 2022 13:35:37 -0700 Subject: [PATCH 331/491] Sema: Check the availability of result builder attributes on function parameters. Resolves https://github.com/apple/swift/issues/60391 and rdar://99006375 --- lib/Sema/TypeCheckAccess.cpp | 3 +++ test/Constraints/result_builder_availability.swift | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 63b20316f4560..7c289203cd705 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -1819,6 +1819,9 @@ class DeclAvailabilityChecker : public DeclVisitor { checkType(wrapperType, wrapperAttrs[index]->getTypeRepr(), fn); } + if (auto attr = P->getAttachedResultBuilder()) + checkType(P->getResultBuilderType(), attr->getTypeRepr(), fn); + checkType(P->getInterfaceType(), P->getTypeRepr(), fn); } } diff --git a/test/Constraints/result_builder_availability.swift b/test/Constraints/result_builder_availability.swift index 7c765ad5aa983..314a7980c0bd5 100644 --- a/test/Constraints/result_builder_availability.swift +++ b/test/Constraints/result_builder_availability.swift @@ -5,13 +5,16 @@ @available(*, unavailable) @resultBuilder struct UnavailableBuilder { -// expected-note@-1 {{'UnavailableBuilder' has been explicitly marked unavailable here}} +// expected-note@-1 2 {{'UnavailableBuilder' has been explicitly marked unavailable here}} static func buildBlock() {} } @UnavailableBuilder public func usesUnavailableBuilder() {} // expected-error@-1 {{'UnavailableBuilder' is unavailable}} +public func takesUnavailableBuilder(@UnavailableBuilder _ fn: () -> ()) {} +// expected-error@-1 {{'UnavailableBuilder' is unavailable}} + enum Either { case first(T) case second(U) From 0d8f5d9113d4f58ca09a81aaacc9ad6fee971939 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Tue, 23 Aug 2022 14:55:12 -0700 Subject: [PATCH 332/491] [test] Interpreter/autolinking: Require local execution --- test/Interpreter/SDK/autolinking.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/Interpreter/SDK/autolinking.swift b/test/Interpreter/SDK/autolinking.swift index 02d2252e8a96c..83626af6a5c64 100644 --- a/test/Interpreter/SDK/autolinking.swift +++ b/test/Interpreter/SDK/autolinking.swift @@ -16,6 +16,9 @@ // REQUIRES: swift_interpreter // REQUIRES: OS=macosx +// This requires executable tests to be run on the same machine as the compiler. +// (rdar://99051588) +// UNSUPPORTED: remote_run || device_run import Darwin #if IMPORT From bc0cab92e7476b78803c7f618c97247998ae9d0c Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Tue, 23 Aug 2022 16:07:07 -0700 Subject: [PATCH 333/491] [test] lit.cfg: Disable swift_interpreter tests when testing remotely --- test/lit.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/lit.cfg b/test/lit.cfg index 378f50ac29eca..624cc675d6f7b 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -1953,6 +1953,9 @@ def configure_remote_run(): config.target_swift_reflection_test = os.path.join( remote_tmp_dir, 'bin', swift_reflection_test_name) config.available_features.add('remote_run') + # Interpreter runs require local execution. + config.available_features.discard('swift_interpreter') + config.substitutions.append(("%target-sdk-name", config.target_sdk_name)) From 6549e0e168ccb47dfd0bac3d4d0549e05b304b2a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 334/491] AST: Introduce representation for pack conformances --- include/swift/AST/PackConformance.h | 95 +++++++ include/swift/AST/TypeAlignments.h | 2 + lib/AST/ASTContext.cpp | 46 ++++ lib/AST/ASTDumper.cpp | 27 ++ lib/AST/CMakeLists.txt | 1 + lib/AST/PackConformance.cpp | 404 ++++++++++++++++++++++++++++ 6 files changed, 575 insertions(+) create mode 100644 include/swift/AST/PackConformance.h create mode 100644 lib/AST/PackConformance.cpp diff --git a/include/swift/AST/PackConformance.h b/include/swift/AST/PackConformance.h new file mode 100644 index 0000000000000..b81a2eac6c39d --- /dev/null +++ b/include/swift/AST/PackConformance.h @@ -0,0 +1,95 @@ +//===--- PackConformance.h - Variadic Protocol Conformance ------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the PackConformance structure, which describes the +// conformance of a type pack parameter to a protocol. +// +//===----------------------------------------------------------------------===// +#ifndef SWIFT_AST_PACKCONFORMANCE_H +#define SWIFT_AST_PACKCONFORMANCE_H + +#include "swift/AST/ASTAllocated.h" +#include "swift/AST/ProtocolConformanceRef.h" +#include "swift/AST/Type.h" +#include "swift/AST/TypeAlignments.h" +#include "swift/Basic/Compiler.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/TrailingObjects.h" + +namespace swift { + +class PackType; + +class alignas(1 << DeclAlignInBits) PackConformance final + : public ASTAllocated, + public llvm::FoldingSetNode, + private llvm::TrailingObjects { + friend class ASTContext; + friend TrailingObjects; + + /// The pack type conforming to the protocol. + PackType *ConformingType; + + /// The conformed-to protocol. + ProtocolDecl *Protocol; + +public: + void Profile(llvm::FoldingSetNodeID &ID) const; + static void Profile(llvm::FoldingSetNodeID &ID, + PackType *conformingType, + ProtocolDecl *protocol, + ArrayRef conformances); + +private: + PackConformance(PackType *conformingType, + ProtocolDecl *protocol, + ArrayRef conformances); + + size_t numTrailingObjects(OverloadToken) const; + +public: + static PackConformance *get(PackType *conformingType, + ProtocolDecl *protocol, + ArrayRef conformances); + + PackType *getType() const { return ConformingType; } + + ProtocolDecl *getProtocol() const { return Protocol; } + + ArrayRef getPatternConformances() const; + + bool isCanonical() const; + + PackConformance *getCanonicalConformance() const; + + PackType *getAssociatedType(Type assocType) const; + + PackConformance * + getAssociatedConformance(Type assocType, ProtocolDecl *protocol) const; + + PackConformance *subst(SubstitutionMap subMap, + SubstOptions options=None) const; + + PackConformance *subst(TypeSubstitutionFn subs, + LookupConformanceFn conformances, + SubstOptions options=None) const; + + SWIFT_DEBUG_DUMP; + void dump(llvm::raw_ostream &out, unsigned indent = 0) const; +}; + +void simple_display(llvm::raw_ostream &out, PackConformance *conformance); + +} // end namespace swift + +#endif // SWIFT_AST_PACKCONFORMANCE_H \ No newline at end of file diff --git a/include/swift/AST/TypeAlignments.h b/include/swift/AST/TypeAlignments.h index 911c29494ff19..827e9ba1313d6 100644 --- a/include/swift/AST/TypeAlignments.h +++ b/include/swift/AST/TypeAlignments.h @@ -46,6 +46,7 @@ namespace swift { class NormalProtocolConformance; class OpaqueValueExpr; class OperatorDecl; + class PackConformance; class Pattern; class ProtocolDecl; class ProtocolConformance; @@ -133,6 +134,7 @@ LLVM_DECLARE_TYPE_ALIGNMENT(swift::Expr, swift::ExprAlignInBits) LLVM_DECLARE_TYPE_ALIGNMENT(swift::CaptureListExpr, swift::ExprAlignInBits) LLVM_DECLARE_TYPE_ALIGNMENT(swift::AbstractClosureExpr, swift::ExprAlignInBits) LLVM_DECLARE_TYPE_ALIGNMENT(swift::OpaqueValueExpr, swift::ExprAlignInBits) +LLVM_DECLARE_TYPE_ALIGNMENT(swift::PackConformance, swift::DeclAlignInBits) LLVM_DECLARE_TYPE_ALIGNMENT(swift::ProtocolConformance, swift::DeclAlignInBits) LLVM_DECLARE_TYPE_ALIGNMENT(swift::NormalProtocolConformance, swift::DeclAlignInBits) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 009dbfbf6ba6f..01218cc997116 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -37,6 +37,7 @@ #include "swift/AST/ModuleDependencies.h" #include "swift/AST/ModuleLoader.h" #include "swift/AST/NameLookup.h" +#include "swift/AST/PackConformance.h" #include "swift/AST/ParameterList.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/PropertyWrappers.h" @@ -445,6 +446,9 @@ struct ASTContext::Implementation { llvm::DenseMap, BuiltinProtocolConformance *> BuiltinConformances; + /// The set of pack conformances. + llvm::FoldingSet PackConformances; + /// The set of substitution maps (uniqued by their storage). llvm::FoldingSet SubstitutionMaps; @@ -2473,6 +2477,48 @@ ASTContext::getInheritedConformance(Type type, ProtocolConformance *inherited) { return result; } +PackConformance *PackConformance::get(PackType *conformingType, + ProtocolDecl *protocol, + ArrayRef conformances) { + auto properties = conformingType->getRecursiveProperties(); + + for (auto conformance : conformances) { + if (conformance.isAbstract() || conformance.isInvalid()) + continue; + + auto *concrete = conformance.getConcrete(); + properties |= concrete->getType()->getRecursiveProperties(); + } + + auto &ctx = protocol->getASTContext(); + + llvm::FoldingSetNodeID id; + PackConformance::Profile(id, conformingType, protocol, conformances); + + // Figure out which arena this conformance should go into. + AllocationArena arena = getArena(properties); + + // Did we already record the pack conformance? + void *insertPos; + auto &packConformances = ctx.getImpl().getArena(arena).PackConformances; + if (auto result = packConformances.FindNodeOrInsertPos(id, insertPos)) + return result; + + // Build a new pack conformance. + auto size = totalSizeToAlloc(conformances.size()); + auto mem = ctx.Allocate(size, alignof(PackConformance), arena); + + auto result + = new (mem) PackConformance(conformingType, protocol, + conformances); + auto node = packConformances.FindNodeOrInsertPos(id, insertPos); + (void)node; + assert(!node); + packConformances.InsertNode(result, insertPos); + + return result; +} + LazyContextData *ASTContext::getOrCreateLazyContextData( const DeclContext *dc, LazyMemberLoader *lazyLoader) { diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 49063d787972f..fd5e78e9b37a4 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -23,6 +23,7 @@ #include "swift/AST/ForeignErrorConvention.h" #include "swift/AST/GenericEnvironment.h" #include "swift/AST/Initializer.h" +#include "swift/AST/PackConformance.h" #include "swift/AST/ParameterList.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SourceFile.h" @@ -3404,6 +3405,27 @@ static void dumpProtocolConformanceRec( PrintWithColorRAII(out, ParenthesisColor) << ')'; } +static void dumpPackConformanceRec( + const PackConformance *conformance, llvm::raw_ostream &out, + unsigned indent, + llvm::SmallPtrSetImpl &visited) { + out.indent(indent); + PrintWithColorRAII(out, ParenthesisColor) << '('; + out << "pack_conformance type=" << Type(conformance->getType()) + << " protocol=" << conformance->getProtocol()->getName(); + + auto conformances = conformance->getPatternConformances(); + if (!conformances.empty()) { + out << "\n"; + + for (auto conformanceRef : conformances) { + dumpProtocolConformanceRefRec(conformanceRef, out, indent, visited); + } + } + + PrintWithColorRAII(out, ParenthesisColor) << ')'; +} + static void dumpSubstitutionMapRec( SubstitutionMap map, llvm::raw_ostream &out, SubstitutionMap::DumpStyle style, unsigned indent, @@ -3501,6 +3523,11 @@ void ProtocolConformance::dump(llvm::raw_ostream &out, unsigned indent) const { dumpProtocolConformanceRec(this, out, indent, visited); } +void PackConformance::dump(llvm::raw_ostream &out, unsigned indent) const { + llvm::SmallPtrSet visited; + dumpPackConformanceRec(this, out, indent, visited); +} + void SubstitutionMap::dump(llvm::raw_ostream &out, DumpStyle style, unsigned indent) const { llvm::SmallPtrSet visited; diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index a63679c3148ee..4307918441256 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -69,6 +69,7 @@ add_swift_host_library(swiftAST STATIC NameLookup.cpp NameLookupRequests.cpp OperatorNameLookup.cpp + PackConformance.cpp Parameter.cpp Pattern.cpp PlatformKind.cpp diff --git a/lib/AST/PackConformance.cpp b/lib/AST/PackConformance.cpp new file mode 100644 index 0000000000000..ccb242eb99312 --- /dev/null +++ b/lib/AST/PackConformance.cpp @@ -0,0 +1,404 @@ +//===--- PackConformance.cpp - Variadic Protocol Conformance --------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements the PackConformance structure, which describes the +// conformance of a type pack parameter to a protocol. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/PackConformance.h" +#include "swift/AST/ASTContext.h" +#include "swift/AST/Decl.h" +#include "swift/AST/Module.h" +#include "swift/AST/Types.h" + +#define DEBUG_TYPE "AST" + +using namespace swift; + +void PackConformance::Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, ConformingType, Protocol, getPatternConformances()); +} + +void PackConformance::Profile(llvm::FoldingSetNodeID &ID, + PackType *conformingType, + ProtocolDecl *protocol, + ArrayRef conformances) { + ID.AddPointer(conformingType); + ID.AddPointer(protocol); + for (auto conformance : conformances) + ID.AddPointer(conformance.getOpaqueValue()); +} + +PackConformance::PackConformance(PackType *conformingType, + ProtocolDecl *protocol, + ArrayRef conformances) + : ConformingType(conformingType), Protocol(protocol) { + + assert(ConformingType->getNumElements() == conformances.size()); + std::uninitialized_copy(conformances.begin(), conformances.end(), + getTrailingObjects()); +} + +size_t PackConformance::numTrailingObjects( + OverloadToken) const { + return ConformingType->getNumElements(); +} + +ArrayRef +PackConformance::getPatternConformances() const { + return {getTrailingObjects(), + ConformingType->getNumElements()}; +} + +bool PackConformance::isCanonical() const { + if (!ConformingType->isCanonical()) + return false; + + for (auto conformance : getPatternConformances()) + if (!conformance.isCanonical()) + return false; + + return true; +} + +PackConformance *PackConformance::getCanonicalConformance() const { + if (isCanonical()) + return const_cast(this); + + SmallVector conformances; + for (auto conformance : getPatternConformances()) + conformances.push_back(conformance.getCanonicalConformanceRef()); + + auto canonical = PackConformance::get( + cast(ConformingType->getCanonicalType()), + Protocol, conformances); + + assert(canonical->isCanonical()); + return canonical; +} + +/// Project the corresponding associated type from each pack element +/// of the conforming type, collecting the results into a new pack type +/// that has the same pack expansion structure as the conforming type. +PackType *PackConformance::getAssociatedType(Type assocType) const { + SmallVector packElements; + + auto conformances = getPatternConformances(); + for (unsigned i : indices(conformances)) { + auto packElement = ConformingType->getElementType(i); + + // If the pack element is a pack expansion, build a new pack expansion + // with the same count type as the original element, and the pattern + // type replaced with the associated type witness from the pattern + // conformance. + if (auto *packExpansion = packElement->getAs()) { + auto assocTypePattern = + conformances[i].getAssociatedType(packExpansion->getPatternType(), + assocType); + + packElements.push_back(PackExpansionType::get( + assocTypePattern, packExpansion->getCountType())); + + // If the pack element is a scalar type, replace the scalar type with + // the associated type witness from the pattern conformance. + } else { + auto assocTypeScalar = + conformances[i].getAssociatedType(packElement, assocType); + packElements.push_back(assocTypeScalar); + } + } + + return PackType::get(Protocol->getASTContext(), packElements); +} + +/// Project the corresponding associated conformance from each pack element +/// of the conforming type, collecting the results into a new pack conformnace +/// whose conforming type has the same pack expansion structure as our +/// conforming type. +PackConformance *PackConformance::getAssociatedConformance( + Type assocType, ProtocolDecl *protocol) const { + SmallVector packElements; + SmallVector packConformances; + + auto conformances = getPatternConformances(); + for (unsigned i : indices(conformances)) { + auto packElement = ConformingType->getElementType(i); + + if (auto *packExpansion = packElement->getAs()) { + auto assocTypePattern = + conformances[i].getAssociatedType(packExpansion->getPatternType(), + assocType); + packElements.push_back(PackExpansionType::get( + assocTypePattern, packExpansion->getCountType())); + + auto assocConformancePattern = + conformances[i].getAssociatedConformance(packExpansion->getPatternType(), + assocType, protocol); + packConformances.push_back(assocConformancePattern); + } else { + auto assocTypeScalar = + conformances[i].getAssociatedType(packElement, assocType); + packElements.push_back(assocTypeScalar); + + auto assocConformanceScalar = + conformances[i].getAssociatedConformance(packElement, assocType, protocol); + packConformances.push_back(assocConformanceScalar); + } + } + + auto conformingType = PackType::get(Protocol->getASTContext(), packElements); + return PackConformance::get(conformingType, protocol, packConformances); +} + +PackConformance *PackConformance::subst(SubstitutionMap subMap, + SubstOptions options) const { + return subst(QuerySubstitutionMap{subMap}, + LookUpConformanceInSubstitutionMap(subMap), + options); +} + +// TODO: Move this elsewhere since it's generally useful +static bool arePackShapesEqual(PackType *lhs, PackType *rhs) { + if (lhs->getNumElements() != rhs->getNumElements()) + return false; + + for (unsigned i = 0, e = lhs->getNumElements(); i < e; ++i) { + auto lhsElt = lhs->getElementType(i); + auto rhsElt = rhs->getElementType(i); + + if (lhsElt->is() != rhsElt->is()) + return false; + } + + return true; +} + +static bool isRootTypeSequenceParameter(Type t) { + if (auto *paramTy = t->getAs()) { + return paramTy->isTypeSequence(); + } else if (auto *archetypeTy = t->getAs()) { + return archetypeTy->isRoot(); + } + + return false; +} + +static bool isRootedInTypeSequenceParameter(Type t) { + if (auto *archetypeTy = t->getAs()) { + return true; + } + + return t->getRootGenericParam()->isTypeSequence(); +} + +namespace { + +template +class PackExpander { +protected: + TypeSubstitutionFn subs; + LookupConformanceFn conformances; + SubstOptions options; + + PackExpander(TypeSubstitutionFn subs, + LookupConformanceFn conformances, + SubstOptions options) + : subs(subs), conformances(conformances), options(options) {} + + ImplClass *asImpl() { + return static_cast(this); + } + + /// We're replacing a pack expansion type with a pack -- flatten the pack + /// using the pack expansion's pattern. + void addExpandedExpansion(Type origPatternType, PackType *expandedCountType, + unsigned i) { + + // Get all pack parameters referenced from the pattern. + SmallVector rootTypeSequenceParams; + origPatternType->getTypeSequenceParameters(rootTypeSequenceParams); + + // Each pack parameter referenced from the pattern must be replaced + // with a pack type, and all pack types must have the same shape as + // the expanded count pack type. + llvm::SmallDenseMap expandedPacks; + for (auto origParamType : rootTypeSequenceParams) { + auto substParamType = origParamType.subst(subs, conformances, options); + + if (auto expandedParamType = substParamType->template getAs()) { + assert(arePackShapesEqual(expandedParamType, expandedCountType) && + "TODO: Return an invalid conformance if this fails"); + + auto inserted = expandedPacks.insert( + std::make_pair(origParamType->getCanonicalType(), + expandedParamType)).second; + assert(inserted && + "getTypeSequenceParameters() should not return duplicates"); + } else { + assert(false && + "TODO: Return an invalid conformance if this fails"); + } + } + + // For each element of the expanded count, compute the substituted + // pattern type. + for (unsigned j = 0, ee = expandedCountType->getNumElements(); j < ee; ++j) { + auto projectedSubs = [&](SubstitutableType *type) -> Type { + // Nested sequence archetypes get passed in here, but we must + // handle them via the standard nested type path. + if (auto *archetypeType = dyn_cast(type)) { + if (!archetypeType->isRoot()) + return Type(); + } + + // Compute the substituted type using our parent substitutions. + auto substType = Type(type).subst(subs, conformances, options); + + // If the substituted type is a pack, project the jth element. + if (isRootTypeSequenceParameter(type)) { + // FIXME: What if you have something like G... where G<> is + // variadic? + assert(substType->template is() && + "TODO: Return an invalid conformance if this fails"); + auto *packType = substType->template castTo(); + assert(arePackShapesEqual(packType, expandedCountType) && + "TODO: Return an invalid conformance if this fails"); + + return packType->getElementType(j); + } + + return subs(type); + }; + + auto projectedConformances = [&](CanType origType, Type substType, + ProtocolDecl *proto) -> ProtocolConformanceRef { + auto substConformance = conformances(origType, substType, proto); + + if (isRootedInTypeSequenceParameter(origType)) { + // FIXME: get the corresponding pack conformance + return ProtocolConformanceRef::forInvalid(); + } + + return substConformance; + }; + + auto origCountElement = expandedCountType->getElementType(j); + auto substCountElement = origCountElement.subst( + projectedSubs, projectedConformances, options); + + asImpl()->add(origCountElement, substCountElement, i); + } + } + + /// A pack expansion remains unexpanded, so we substitute the pattern and + /// form a new pack expansion. + void addUnexpandedExpansion(Type origPatternType, Type substCountType, + unsigned i) { + auto substPatternType = origPatternType.subst(subs, conformances, options); + auto substExpansion = PackExpansionType::get(substPatternType, substCountType); + + asImpl()->add(origPatternType, substExpansion, i); + } + + /// Scalar elements of the original pack are substituted and added to the + /// flattened pack. + void addScalar(Type origElement, unsigned i) { + auto substElement = origElement.subst(subs, conformances, options); + + asImpl()->add(origElement, substElement, i); + } + + /// Potentially expand an element of the original pack. + void maybeExpandExpansion(PackExpansionType *origExpansion, unsigned i) { + auto origPatternType = origExpansion->getPatternType(); + auto origCountType = origExpansion->getCountType(); + + auto substCountType = origCountType.subst(subs, conformances, options); + + // If the substituted count type is a pack, we're expanding the + // original element. + if (auto *expandedCountType = substCountType->template getAs()) { + addExpandedExpansion(origPatternType, expandedCountType, i); + return; + } + + addUnexpandedExpansion(origPatternType, substCountType, i); + } + +public: + void expand(PackType *origPackType) { + for (unsigned i = 0, e = origPackType->getNumElements(); i < e; ++i) { + auto origElement = origPackType->getElementType(i); + + // Check if the original element is potentially being expanded. + if (auto *origExpansion = origElement->getAs()) { + maybeExpandExpansion(origExpansion, i); + continue; + } + + addScalar(origElement, i); + } + } +}; + +class PackConformanceExpander : public PackExpander { +public: + SmallVector substElements; + SmallVector substConformances; + + ArrayRef origConformances; + + PackConformanceExpander(TypeSubstitutionFn subs, + LookupConformanceFn conformances, + SubstOptions options, + ArrayRef origConformances) + : PackExpander(subs, conformances, options), + origConformances(origConformances) {} + + void add(Type origType, Type substType, unsigned i) { + substElements.push_back(substType); + + // FIXME: Pass down projection callbacks + substConformances.push_back(origConformances[i].subst( + origType, subs, conformances, options)); + } +}; + +} + +PackConformance *PackConformance::subst(TypeSubstitutionFn subs, + LookupConformanceFn conformances, + SubstOptions options) const { + PackConformanceExpander expander(subs, conformances, options, + getPatternConformances()); + expander.expand(ConformingType); + + auto &ctx = Protocol->getASTContext(); + auto *substConformingType = PackType::get(ctx, expander.substElements); + + return PackConformance::get(substConformingType, Protocol, + expander.substConformances); +} + +void swift::simple_display(llvm::raw_ostream &out, PackConformance *conformance) { + out << conformance->getType() << " : {"; + bool first = true; + for (auto patternConformance : conformance->getPatternConformances()) { + if (first) { + out << ", "; + first = false; + } + simple_display(out, patternConformance); + } + out << "}"; +} \ No newline at end of file From 0f26d02fb140511ee4ac61a83befa1bdd0337968 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 335/491] AST: ProtocolConformanceRef can store a pack conformance --- include/swift/AST/PackConformance.h | 16 +++-- include/swift/AST/ProtocolConformanceRef.h | 18 ++++- lib/AST/ASTDumper.cpp | 10 ++- lib/AST/PackConformance.cpp | 19 ++--- lib/AST/ProtocolConformanceRef.cpp | 83 +++++++++++++++++----- 5 files changed, 113 insertions(+), 33 deletions(-) diff --git a/include/swift/AST/PackConformance.h b/include/swift/AST/PackConformance.h index b81a2eac6c39d..eee457af99ff2 100644 --- a/include/swift/AST/PackConformance.h +++ b/include/swift/AST/PackConformance.h @@ -77,12 +77,16 @@ class alignas(1 << DeclAlignInBits) PackConformance final PackConformance * getAssociatedConformance(Type assocType, ProtocolDecl *protocol) const; - PackConformance *subst(SubstitutionMap subMap, - SubstOptions options=None) const; - - PackConformance *subst(TypeSubstitutionFn subs, - LookupConformanceFn conformances, - SubstOptions options=None) const; + /// The ProtocolConformanceRef either stores a pack conformance, or + /// it is invalid in the case of substitution failure. + ProtocolConformanceRef subst(SubstitutionMap subMap, + SubstOptions options=None) const; + + /// The ProtocolConformanceRef either stores a pack conformance, or + /// it is invalid in the case of substitution failure. + ProtocolConformanceRef subst(TypeSubstitutionFn subs, + LookupConformanceFn conformances, + SubstOptions options=None) const; SWIFT_DEBUG_DUMP; void dump(llvm::raw_ostream &out, unsigned indent = 0) const; diff --git a/include/swift/AST/ProtocolConformanceRef.h b/include/swift/AST/ProtocolConformanceRef.h index 414943b8621e3..67ef66d9f9262 100644 --- a/include/swift/AST/ProtocolConformanceRef.h +++ b/include/swift/AST/ProtocolConformanceRef.h @@ -33,6 +33,7 @@ namespace swift { class BuiltinProtocolConformance; class ConcreteDeclRef; +class PackConformance; class ProtocolConformance; enum class EffectKind : uint8_t; @@ -50,7 +51,9 @@ enum class EffectKind : uint8_t; /// ProtocolConformanceRef allows the efficient recovery of the protocol /// even when the conformance is abstract. class ProtocolConformanceRef { - using UnionType = llvm::PointerUnion; + using UnionType = llvm::PointerUnion; UnionType Union; explicit ProtocolConformanceRef(UnionType value) : Union(value) {} @@ -68,6 +71,12 @@ class ProtocolConformanceRef { "cannot construct ProtocolConformanceRef with null"); } + /// Create a pack protocol conformance reference. + explicit ProtocolConformanceRef(PackConformance *conf) : Union(conf) { + assert(conf != nullptr && + "cannot construct ProtocolConformanceRef with null"); + } + ProtocolConformanceRef(std::nullptr_t = nullptr) : Union((ProtocolDecl *)nullptr) {} @@ -98,6 +107,13 @@ class ProtocolConformanceRef { return Union.get(); } + bool isPack() const { + return !isInvalid() && Union.is(); + } + PackConformance *getPack() const { + return Union.get(); + } + bool isAbstract() const { return !isInvalid() && Union.is(); } diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index fd5e78e9b37a4..c0b438d4e7eff 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -3260,6 +3260,11 @@ static void dumpProtocolConformanceRec( unsigned indent, llvm::SmallPtrSetImpl &visited); +static void dumpPackConformanceRec( + const PackConformance *conformance, llvm::raw_ostream &out, + unsigned indent, + llvm::SmallPtrSetImpl &visited); + static void dumpProtocolConformanceRefRec( const ProtocolConformanceRef conformance, llvm::raw_ostream &out, unsigned indent, @@ -3268,7 +3273,11 @@ static void dumpProtocolConformanceRefRec( out.indent(indent) << "(invalid_conformance)"; } else if (conformance.isConcrete()) { dumpProtocolConformanceRec(conformance.getConcrete(), out, indent, visited); + } else if (conformance.isPack()) { + dumpPackConformanceRec(conformance.getPack(), out, indent, visited); } else { + assert(conformance.isAbstract()); + out.indent(indent) << "(abstract_conformance protocol=" << conformance.getAbstract()->getName(); PrintWithColorRAII(out, ParenthesisColor) << ')'; @@ -3509,7 +3518,6 @@ void ProtocolConformanceRef::dump(llvm::raw_ostream &out, unsigned indent, void ProtocolConformanceRef::print(llvm::raw_ostream &out) const { llvm::SmallPtrSet visited; dumpProtocolConformanceRefRec(*this, out, 0, visited); - } void ProtocolConformance::dump() const { diff --git a/lib/AST/PackConformance.cpp b/lib/AST/PackConformance.cpp index ccb242eb99312..ffb6e29db280a 100644 --- a/lib/AST/PackConformance.cpp +++ b/lib/AST/PackConformance.cpp @@ -160,8 +160,8 @@ PackConformance *PackConformance::getAssociatedConformance( return PackConformance::get(conformingType, protocol, packConformances); } -PackConformance *PackConformance::subst(SubstitutionMap subMap, - SubstOptions options) const { +ProtocolConformanceRef PackConformance::subst(SubstitutionMap subMap, + SubstOptions options) const { return subst(QuerySubstitutionMap{subMap}, LookUpConformanceInSubstitutionMap(subMap), options); @@ -284,9 +284,9 @@ class PackExpander { ProtocolDecl *proto) -> ProtocolConformanceRef { auto substConformance = conformances(origType, substType, proto); + // If the substituted conformance is a pack, project the jth element. if (isRootedInTypeSequenceParameter(origType)) { - // FIXME: get the corresponding pack conformance - return ProtocolConformanceRef::forInvalid(); + return substConformance.getPack()->getPatternConformances()[j]; } return substConformance; @@ -376,9 +376,9 @@ class PackConformanceExpander : public PackExpander { } -PackConformance *PackConformance::subst(TypeSubstitutionFn subs, - LookupConformanceFn conformances, - SubstOptions options) const { +ProtocolConformanceRef PackConformance::subst(TypeSubstitutionFn subs, + LookupConformanceFn conformances, + SubstOptions options) const { PackConformanceExpander expander(subs, conformances, options, getPatternConformances()); expander.expand(ConformingType); @@ -386,8 +386,9 @@ PackConformance *PackConformance::subst(TypeSubstitutionFn subs, auto &ctx = Protocol->getASTContext(); auto *substConformingType = PackType::get(ctx, expander.substElements); - return PackConformance::get(substConformingType, Protocol, - expander.substConformances); + auto substConformance = PackConformance::get(substConformingType, Protocol, + expander.substConformances); + return ProtocolConformanceRef(substConformance); } void swift::simple_display(llvm::raw_ostream &out, PackConformance *conformance) { diff --git a/lib/AST/ProtocolConformanceRef.cpp b/lib/AST/ProtocolConformanceRef.cpp index 1a15136b701fa..8d03945413c7d 100644 --- a/lib/AST/ProtocolConformanceRef.cpp +++ b/lib/AST/ProtocolConformanceRef.cpp @@ -20,6 +20,8 @@ #include "swift/AST/Availability.h" #include "swift/AST/Decl.h" #include "swift/AST/Module.h" +#include "swift/AST/PackConformance.h" +#include "swift/AST/ProtocolConformance.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/AST/Types.h" @@ -44,6 +46,8 @@ ProtocolDecl *ProtocolConformanceRef::getRequirement() const { if (isConcrete()) { return getConcrete()->getProtocol(); + } else if (isPack()) { + return getPack()->getProtocol(); } else { return getAbstract(); } @@ -67,11 +71,14 @@ ProtocolConformanceRef::subst(Type origType, if (isInvalid()) return *this; - // If we have a concrete conformance, we need to substitute the - // conformance to apply to the new type. if (isConcrete()) return ProtocolConformanceRef(getConcrete()->subst(subs, conformances, options)); + if (isPack()) + return getPack()->subst(subs, conformances, options); + + // Handle abstract conformances below: + // If the type is an opaque archetype, the conformance will remain abstract, // unless we're specifically substituting opaque types. if (auto origArchetype = origType->getAs()) { @@ -102,17 +109,26 @@ ProtocolConformanceRef::subst(Type origType, } ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() const { - if (!isConcrete()) - return *this; + if (isConcrete()) { + auto *concrete = getConcrete()->subst( + [](SubstitutableType *type) -> Type { + if (auto *archetypeType = type->getAs()) + return archetypeType->getInterfaceType(); + return type; + }, + MakeAbstractConformanceForGenericType()); + return ProtocolConformanceRef(concrete); + } else if (isPack()) { + return getPack()->subst( + [](SubstitutableType *type) -> Type { + if (auto *archetypeType = type->getAs()) + return archetypeType->getInterfaceType(); + return type; + }, + MakeAbstractConformanceForGenericType()); + } - auto *concrete = getConcrete()->subst( - [](SubstitutableType *type) -> Type { - if (auto *archetypeType = type->getAs()) - return archetypeType->getInterfaceType(); - return type; - }, - MakeAbstractConformanceForGenericType()); - return ProtocolConformanceRef(concrete); + return *this; } Type @@ -171,6 +187,12 @@ ProtocolConformanceRef::getConditionalRequirements() const { Type ProtocolConformanceRef::getAssociatedType(Type conformingType, Type assocType) const { + if (isPack()) { + auto *pack = getPack(); + assert(conformingType->isEqual(pack->getType())); + return pack->getAssociatedType(assocType); + } + assert(!isConcrete() || getConcrete()->getType()->isEqual(conformingType)); auto type = assocType->getCanonicalType(); @@ -200,6 +222,14 @@ ProtocolConformanceRef ProtocolConformanceRef::getAssociatedConformance(Type conformingType, Type assocType, ProtocolDecl *protocol) const { + // If this is a pack conformance, project the associated conformances. + if (isPack()) { + auto *pack = getPack(); + assert(conformingType->isEqual(pack->getType())); + return ProtocolConformanceRef( + pack->getAssociatedConformance(assocType, protocol)); + } + // If this is a concrete conformance, look up the associated conformance. if (isConcrete()) { auto conformance = getConcrete(); @@ -221,23 +251,33 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType, bool ProtocolConformanceRef::isCanonical() const { if (isAbstract() || isInvalid()) return true; + if (isPack()) + return getPack()->isCanonical(); return getConcrete()->isCanonical(); + } ProtocolConformanceRef ProtocolConformanceRef::getCanonicalConformanceRef() const { if (isAbstract() || isInvalid()) return *this; + if (isPack()) + return ProtocolConformanceRef(getPack()->getCanonicalConformance()); return ProtocolConformanceRef(getConcrete()->getCanonicalConformance()); } bool ProtocolConformanceRef::hasUnavailableConformance() const { - if (isInvalid()) + if (isInvalid() || isAbstract()) return false; - // Abstract conformances are never unavailable. - if (!isConcrete()) + if (isPack()) { + for (auto conformance : getPack()->getPatternConformances()) { + if (conformance.hasUnavailableConformance()) + return true; + } + return false; + } // Check whether this conformance is on an unavailable extension. auto concrete = getConcrete(); @@ -266,8 +306,17 @@ bool ProtocolConformanceRef::hasMissingConformance(ModuleDecl *module) const { bool ProtocolConformanceRef::forEachMissingConformance( ModuleDecl *module, llvm::function_ref fn) const { - if (!isConcrete()) + if (isInvalid() || isAbstract()) + return false; + + if (isPack()) { + for (auto conformance : getPack()->getPatternConformances()) { + if (conformance.forEachMissingConformance(module, fn)) + return true; + } + return false; + } // Is this a missing conformance? ProtocolConformance *concreteConf = getConcrete(); @@ -292,6 +341,8 @@ void swift::simple_display(llvm::raw_ostream &out, ProtocolConformanceRef confor simple_display(out, conformanceRef.getAbstract()); } else if (conformanceRef.isConcrete()) { simple_display(out, conformanceRef.getConcrete()); + } else if (conformanceRef.isPack()) { + simple_display(out, conformanceRef.getPack()); } } From ad31fa3d572b1d4380504d2d1fb5e03dc4a0d1e5 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Aug 2022 22:27:11 -0400 Subject: [PATCH 336/491] AST: Fix printing of one-element tuples containing a pack expansion --- lib/AST/ASTPrinter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 32eef577b483a..150df1018aa62 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -5552,9 +5552,8 @@ class TypePrinter : public TypeVisitor { } void visitPackExpansionType(PackExpansionType *T) { - Printer << "("; visit(T->getPatternType()); - Printer << "..." << ")"; + Printer << "..."; } void visitTupleType(TupleType *T) { @@ -5563,7 +5562,8 @@ class TypePrinter : public TypeVisitor { // Single-element tuples can only appear in SIL mode. if (T->getNumElements() == 1 && - !T->getElement(0).hasName()) { + !T->getElement(0).hasName() && + !T->getElementType(0)->is()) { Printer << "@tuple "; } From 8b9d5276f042263082d32bf7359bff70b697199f Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 22 Aug 2022 22:21:34 -0400 Subject: [PATCH 337/491] Sema: Don't assume ConformanceChecker::Adoptee is a nominal type For tuple conformances, it will be the tuple type (T...). --- lib/Sema/TypeCheckProtocol.cpp | 35 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index ea4f7d8a3a380..decff75439346 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1283,7 +1283,7 @@ WitnessChecker::lookupValueWitnessesViaImplementsAttr( ValueDecl *req, SmallVector &witnesses) { auto name = req->createNameRef(); - auto *nominal = Adoptee->getAnyNominal(); + auto *nominal = DC->getSelfNominalTypeDecl(); NLOptions subOptions = (NL_ProtocolMembers | NL_IncludeAttributeImplements); @@ -1338,7 +1338,7 @@ WitnessChecker::lookupValueWitnesses(ValueDecl *req, bool *ignoringNames) { } if (doQualifiedLookup) { - auto *nominal = Adoptee->getAnyNominal(); + auto *nominal = DC->getSelfNominalTypeDecl(); nominal->synthesizeSemanticMembersIfNeeded(reqName.getFullName()); // Unqualified lookup would have already found candidates from protocol @@ -1551,7 +1551,7 @@ AccessScope WitnessChecker::getRequiredAccessScope() { bool witnessesMustBeUsableFromInline = false; if (Adoptee) { - const NominalTypeDecl *adoptingNominal = Adoptee->getAnyNominal(); + const NominalTypeDecl *adoptingNominal = DC->getSelfNominalTypeDecl(); // Compute the intersection of the conforming type's access scope // and the protocol's access scope. @@ -2012,7 +2012,6 @@ checkIndividualConformance(NormalProtocolConformance *conformance, // Dig out some of the fields from the conformance. Type T = conformance->getType(); - auto canT = T->getCanonicalType(); DeclContext *DC = conformance->getDeclContext(); auto Proto = conformance->getProtocol(); auto ProtoType = Proto->getDeclaredInterfaceType(); @@ -2030,7 +2029,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance, } // If the protocol requires a class, non-classes are a non-starter. - if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) { + if (Proto->requiresClass() && !DC->getSelfClassDecl()) { C.Diags.diagnose(ComplainLoc, diag::non_class_cannot_conform_to_class_protocol, T, ProtoType); @@ -2060,7 +2059,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance, if (Proto->isObjC()) { // Foreign classes cannot conform to objc protocols. - if (auto clazz = canT->getClassOrBoundGenericClass()) { + if (auto clazz = DC->getSelfClassDecl()) { Optional diagKind; switch (clazz->getForeignClassKind()) { @@ -2114,7 +2113,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance, // Not every protocol/type is compatible with conditional conformances. auto conditionalReqs = conformance->getConditionalRequirementsIfAvailable(); if (conditionalReqs && !conditionalReqs->empty()) { - auto nestedType = canT; + auto nestedType = DC->getSelfNominalTypeDecl()->getDeclaredInterfaceType(); // Obj-C generics cannot be looked up at runtime, so we don't support // conditional conformances involving them. Check the full stack of nested // types for any obj-c ones. @@ -2129,7 +2128,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance, } } - nestedType = nestedType.getNominalParent(); + nestedType = nestedType->getNominalParent(); } // If the protocol to which we are conditionally conforming is not a marker @@ -3212,7 +3211,7 @@ bool ConformanceChecker::checkObjCTypeErasedGenerics( if (!ctx.LangOpts.EnableObjCInterop && type->hasError()) return false; - auto classDecl = Adoptee->getClassOrBoundGenericClass(); + auto classDecl = DC->getSelfClassDecl(); if (!classDecl) return false; if (!classDecl->isTypeErasedGenericClass()) return false; @@ -3784,7 +3783,7 @@ diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind) { for (auto &Missing : LocalMissing) { auto requirement = Missing.requirement; auto matches = Missing.matches; - auto nominal = Adoptee->getAnyNominal(); + auto nominal = DC->getSelfNominalTypeDecl(); diagnoseOrDefer(requirement, true, [requirement, matches, nominal](NormalProtocolConformance *conformance) { @@ -4014,7 +4013,7 @@ getAdopteeSelfSameTypeConstraint(ClassDecl *selfClass, ValueDecl *witness) { void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement, ValueDecl *witness) { - auto *classDecl = Adoptee->getClassOrBoundGenericClass(); + auto *classDecl = DC->getSelfClassDecl(); // If we have an initializer requirement and the conforming type // is a non-final class, the witness must be 'required'. @@ -4161,7 +4160,7 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement, ResolveWitnessResult ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { assert(!isa(requirement) && "Use resolveTypeWitnessVia*"); - auto *nominal = Adoptee->getAnyNominal(); + auto *nominal = DC->getSelfNominalTypeDecl(); // Resolve all associated types before trying to resolve this witness. resolveTypeWitnesses(); @@ -4435,7 +4434,7 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { break; } - if (auto *classDecl = Adoptee->getClassOrBoundGenericClass()) { + if (auto *classDecl = DC->getSelfClassDecl()) { if (!classDecl->isSemanticallyFinal()) { checkNonFinalClassWitness(requirement, witness); } @@ -4519,7 +4518,7 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDerivation( // Find the declaration that derives the protocol conformance. NominalTypeDecl *derivingTypeDecl = nullptr; - auto *nominal = Adoptee->getAnyNominal(); + auto *nominal = DC->getSelfNominalTypeDecl(); if (DerivedConformance::derivesProtocolConformance(DC, nominal, Proto)) derivingTypeDecl = nominal; @@ -4694,7 +4693,7 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( // Look for a member type with the same name as the associated type. SmallVector candidates; - DC->lookupQualified(Adoptee->getAnyNominal(), + DC->lookupQualified(DC->getSelfNominalTypeDecl(), assocType->createNameRef(), subOptions, candidates); @@ -4734,7 +4733,7 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( if (typeAliasDecl->getUnderlyingType()->isNever()) { if (typeAliasDecl->getParentModule()->getName().is("SwiftUI")) { if (typeAliasDecl->getDeclContext()->getSelfNominalTypeDecl() == - Adoptee->getAnyNominal()) { + DC->getSelfNominalTypeDecl()) { const auto reqs = typeAliasDecl->getGenericSignature().requirementsNotSatisfiedBy( DC->getGenericSignatureOfContext()); @@ -4980,7 +4979,7 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() { // an error, we can handle it as part of the above checkGenericArguments() // call by passing in a superclass-bound archetype for the 'self' type // instead of the concrete class type itself. - if (auto *classDecl = Adoptee->getClassOrBoundGenericClass()) { + if (auto *classDecl = DC->getSelfClassDecl()) { if (!classDecl->isSemanticallyFinal()) { if (auto req = hasInvariantSelfRequirement(proto, reqSig)) { diagnoseInvariantSelfRequirement(Loc, Adoptee, proto, *req, diags); @@ -5399,7 +5398,7 @@ void ConformanceChecker::checkConformance(MissingWitnessDiagnosisKind Kind) { // Note that we check the module name to smooth over the difference // between an imported Objective-C module and its overlay. if (Proto->isSpecificProtocol(KnownProtocolKind::ObjectiveCBridgeable)) { - auto nominal = Adoptee->getAnyNominal(); + auto nominal = DC->getSelfNominalTypeDecl(); if (!getASTContext().isTypeBridgedInExternalModule(nominal)) { auto clangLoader = getASTContext().getClangModuleLoader(); if (nominal->getParentModule() != DC->getParentModule() && From 40c2678e3826e3058a1043582172a75bf37ea1b0 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Aug 2022 23:37:53 -0400 Subject: [PATCH 338/491] Sema: Fix existential opening for arguments to self.init/super.init delegation Fixes rdar://problem/98404682. --- lib/Sema/CSApply.cpp | 14 +++++----- lib/Sema/MiscDiagnostics.cpp | 26 ++++++++++++++++--- ...pened_existential_in_init_delegation.swift | 16 ++++++++++++ 3 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 test/SILGen/opened_existential_in_init_delegation.swift diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 32190a7da0cdf..0062c66d75163 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -726,6 +726,8 @@ namespace { return inout->getSubExpr(); } else if (auto force = dyn_cast(expr)) { return force->getSubExpr(); + } else if (auto rebind = dyn_cast(expr)) { + return rebind->getSubExpr(); } else { return nullptr; } @@ -817,11 +819,6 @@ namespace { unsigned maxArgCount = member->getNumCurryLevels(); unsigned depth = ExprStack.size() - getArgCount(maxArgCount); - // Invalid case -- direct call of a metatype. Has one less argument - // application because there's no ".init". - if (isa(ExprStack.back())) - depth++; - // Create the opaque opened value. If we started with a // metatype, it's a metatype. Type opaqueType = archetype; @@ -3757,7 +3754,12 @@ namespace { expr->setSubExpr(newSubExpr); } - return expr; + // We might have opened existentials in the argument list of the + // constructor call. + Expr *result = expr; + closeExistentials(result, cs.getConstraintLocator(expr)); + + return result; } Expr *visitIfExpr(IfExpr *expr) { diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 83501d41679bb..c92944c95f067 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -109,6 +109,7 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, SmallPtrSet AlreadyDiagnosedBitCasts; bool IsExprStmt; + unsigned ExprNestingDepth; bool HasReachedSemanticsProvidingExpr; ASTContext &Ctx; @@ -116,7 +117,8 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, public: DiagnoseWalker(const DeclContext *DC, bool isExprStmt) - : IsExprStmt(isExprStmt), HasReachedSemanticsProvidingExpr(false), + : IsExprStmt(isExprStmt), ExprNestingDepth(0), + HasReachedSemanticsProvidingExpr(false), Ctx(DC->getASTContext()), DC(DC) {} std::pair walkToPatternPre(Pattern *P) override { @@ -130,6 +132,10 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, bool shouldWalkIntoTapExpression() override { return false; } std::pair walkToExprPre(Expr *E) override { + if (isa(E)) { + // Don't increase ExprNestingDepth. + return { true, E }; + } if (auto collection = dyn_cast(E)) { if (collection->isTypeDefaulted()) { @@ -275,9 +281,11 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, } // Diagnose 'self.init' or 'super.init' nested in another expression - // or closure. + // or closure. The ExprNestingDepth thing is to allow this to be nested + // inside of an OpenExistentialExpr that is at the top level. if (auto *rebindSelfExpr = dyn_cast(E)) { - if (!Parent.isNull() || !IsExprStmt || DC->getParent()->isLocalContext()) { + if (ExprNestingDepth > 0 || !IsExprStmt || + DC->getParent()->isLocalContext()) { bool isChainToSuper; (void)rebindSelfExpr->getCalledConstructor(isChainToSuper); Ctx.Diags.diagnose(E->getLoc(), diag::init_delegation_nested, @@ -346,9 +354,20 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, HasReachedSemanticsProvidingExpr = true; } + ++ExprNestingDepth; + return { true, E }; } + Expr *walkToExprPost(Expr *E) override { + if (isa(E)) + return E; + + assert(ExprNestingDepth != 0); + --ExprNestingDepth; + return E; + } + /// Visit each component of the keypath and emit a diagnostic if they /// refer to a member that has effects. void checkForEffectfulKeyPath(KeyPathExpr *keyPath) { @@ -1500,6 +1519,7 @@ static void diagRecursivePropertyAccess(const Expr *E, const DeclContext *DC) { }; DiagnoseWalker walker(var, fn); + const_cast(E)->walk(walker); } diff --git a/test/SILGen/opened_existential_in_init_delegation.swift b/test/SILGen/opened_existential_in_init_delegation.swift new file mode 100644 index 0000000000000..f23298a4d73ef --- /dev/null +++ b/test/SILGen/opened_existential_in_init_delegation.swift @@ -0,0 +1,16 @@ +// RUN: %target-swift-emit-silgen %s | %FileCheck %s + +protocol P {} +class C { + init(x: some P) {} + + convenience init(y: any P) { self.init(x: y) } +} + +// CHECK-LABEL: sil hidden [ossa] @$s37opened_existential_in_init_delegation1CC1yAcA1P_p_tcfC : $@convention(method) (@in any P, @thick C.Type) -> @owned C { +// CHECK: [[OPENED:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*@opened("{{.*}}", any P) Self +// CHECK: [[COPIED:%.*]] = alloc_stack $@opened("{{.*}}", any P) Self +// CHECK: copy_addr [[OPENED]] to [initialization] [[COPIED]] : $*@opened("{{.*}}", any P) Self +// CHECK: [[FN:%.*]] = class_method %1 : $@thick C.Type, #C.init!allocator : (C.Type) -> (some P) -> C, $@convention(method) <Ï„_0_0 where Ï„_0_0 : P> (@in Ï„_0_0, @thick C.Type) -> @owned C +// CHECK: apply [[FN]]<@opened("{{.*}}", any P) Self>([[COPIED]], %1) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : P> (@in Ï„_0_0, @thick C.Type) -> @owned C +// CHECK: dealloc_stack [[COPIED]] : $*@opened("{{.*}}", any P) Self From 141ffc2b8d3958d5d8b42ea9fc68c1012ddfccfd Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 22 Aug 2022 17:34:31 -0700 Subject: [PATCH 339/491] Model isolated parameters in ActorIsolation. A function can be actor instance-isolated to one of its parameters. Make sure that this is reflected in ActorIsolation, so such a function doesn't get a different actor isolation. --- include/swift/AST/ActorIsolation.h | 36 +++++++++---- lib/AST/Decl.cpp | 3 +- lib/SILGen/SILGenPoly.cpp | 1 + lib/SILGen/SILGenProlog.cpp | 25 +++++---- lib/Sema/TypeCheckConcurrency.cpp | 62 ++++++++++++++++++---- test/Concurrency/isolated_parameters.swift | 11 +++- 6 files changed, 103 insertions(+), 35 deletions(-) diff --git a/include/swift/AST/ActorIsolation.h b/include/swift/AST/ActorIsolation.h index afc72633fea48..3f697b772166f 100644 --- a/include/swift/AST/ActorIsolation.h +++ b/include/swift/AST/ActorIsolation.h @@ -74,14 +74,17 @@ class ActorIsolation { Type globalActor; void *pointer; }; - uint8_t kind : 3; - uint8_t isolatedByPreconcurrency : 1; + unsigned kind : 3; + unsigned isolatedByPreconcurrency : 1; + unsigned parameterIndex : 28; - ActorIsolation(Kind kind, NominalTypeDecl *actor) - : actor(actor), kind(kind), isolatedByPreconcurrency(false) { } + ActorIsolation(Kind kind, NominalTypeDecl *actor, unsigned parameterIndex) + : actor(actor), kind(kind), isolatedByPreconcurrency(false), + parameterIndex(parameterIndex) { } ActorIsolation(Kind kind, Type globalActor) - : globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false) { } + : globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false), + parameterIndex(0) { } public: static ActorIsolation forUnspecified() { @@ -92,8 +95,13 @@ class ActorIsolation { return ActorIsolation(Independent, nullptr); } - static ActorIsolation forActorInstance(NominalTypeDecl *actor) { - return ActorIsolation(ActorInstance, actor); + static ActorIsolation forActorInstanceSelf(NominalTypeDecl *actor) { + return ActorIsolation(ActorInstance, actor, 0); + } + + static ActorIsolation forActorInstanceParameter(NominalTypeDecl *actor, + unsigned parameterIndex) { + return ActorIsolation(ActorInstance, actor, parameterIndex + 1); } static ActorIsolation forGlobalActor(Type globalActor, bool unsafe) { @@ -109,6 +117,14 @@ class ActorIsolation { bool isIndependent() const { return kind == Independent; } + /// Retrieve the parameter to which actor-instance isolation applies. + /// + /// Parameter 0 is `self`. + unsigned getActorInstanceParameter() const { + assert(getKind() == ActorInstance); + return parameterIndex; + } + bool isActorIsolated() const { switch (getKind()) { case ActorInstance: @@ -169,7 +185,7 @@ class ActorIsolation { return true; case ActorInstance: - return lhs.actor == rhs.actor; + return lhs.actor == rhs.actor && lhs.parameterIndex == rhs.parameterIndex; case GlobalActor: case GlobalActorUnsafe: @@ -183,7 +199,9 @@ class ActorIsolation { } friend llvm::hash_code hash_value(const ActorIsolation &state) { - return llvm::hash_combine(state.kind, state.pointer); + return llvm::hash_combine( + state.kind, state.pointer, state.isolatedByPreconcurrency, + state.parameterIndex); } }; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 8fa5a636320e6..5fcf83aa76d53 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -9232,7 +9232,8 @@ ActorIsolation swift::getActorIsolationOfContext(DeclContext *dc) { auto actor = selfDecl->getType()->getReferenceStorageReferent() ->getAnyActor(); assert(actor && "Bad closure actor isolation?"); - return ActorIsolation::forActorInstance(actor) + // FIXME: This could be a parameter... or a capture... hmmm. + return ActorIsolation::forActorInstanceSelf(actor) .withPreconcurrency(isolation.preconcurrency()); } } diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index 064bcf8aa7f44..a9bced27bdb18 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -4438,6 +4438,7 @@ void SILGenFunction::emitProtocolWitness( // For an instance actor, get the actor 'self'. if (*enterIsolation == ActorIsolation::ActorInstance) { + assert(enterIsolation->getActorInstanceParameter() == 0 && "Not self?"); auto actorSelfVal = origParams.back(); if (actorSelfVal.getType().isAddress()) { diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index 14e4cf7648fe3..0829a0e8cb6ef 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -670,16 +670,6 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo, switch (actorIsolation.getKind()) { case ActorIsolation::Unspecified: case ActorIsolation::Independent: - // If this is an async function that has an isolated parameter, hop - // to it. - if (F.isAsync()) { - for (auto param : *funcDecl->getParameters()) { - if (param->isIsolated()) { - loadExpectedExecutorForLocalVar(param); - break; - } - } - } break; case ActorIsolation::ActorInstance: { @@ -693,10 +683,19 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo, .getIsolatedParamCapture()) { loadExpectedExecutorForLocalVar(isolatedParam); } else { - assert(selfParam && "no self parameter for ActorInstance isolation"); auto loc = RegularLocation::getAutoGeneratedLocation(F.getLocation()); - ManagedValue selfArg = ManagedValue::forUnmanaged(F.getSelfArgument()); - ExpectedExecutor = emitLoadActorExecutor(loc, selfArg); + ManagedValue actorArg; + if (actorIsolation.getActorInstanceParameter() == 0) { + assert(selfParam && "no self parameter for ActorInstance isolation"); + auto selfArg = ManagedValue::forUnmanaged(F.getSelfArgument()); + ExpectedExecutor = emitLoadActorExecutor(loc, selfArg); + } else { + unsigned isolatedParamIdx = + actorIsolation.getActorInstanceParameter() - 1; + auto param = funcDecl->getParameters()->get(isolatedParamIdx); + assert(param->isIsolated()); + loadExpectedExecutorForLocalVar(param); + } } } break; diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index c6d5b47fec33f..92b32c20b934b 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -136,7 +136,7 @@ bool swift::usesFlowSensitiveIsolation(AbstractFunctionDecl const *fn) { return true; // construct an isolation corresponding to the type. - auto actorTypeIso = ActorIsolation::forActorInstance(nominal); + auto actorTypeIso = ActorIsolation::forActorInstanceSelf(nominal); return requiresFlowIsolation(actorTypeIso, cast(fn)); } @@ -2521,7 +2521,6 @@ namespace { return false; // Check for isolated parameters. - Optional isolatedParamIdx; for (unsigned paramIdx : range(fnType->getNumParams())) { // We only care about isolated parameters. if (!fnType->getParams()[paramIdx].isIsolated()) @@ -2545,8 +2544,8 @@ namespace { KnownProtocolKind::Actor); } - unsatisfiedIsolation = ActorIsolation::forActorInstance(nominal); - isolatedParamIdx = paramIdx; + unsatisfiedIsolation = + ActorIsolation::forActorInstanceParameter(nominal, paramIdx); break; } @@ -2595,7 +2594,8 @@ namespace { case ActorIsolation::ActorInstance: apply->setImplicitlyAsync( - ImplicitActorHopTarget::forIsolatedParameter(*isolatedParamIdx)); + ImplicitActorHopTarget::forIsolatedParameter( + unsatisfiedIsolation->getActorInstanceParameter() - 1)); break; case ActorIsolation::Unspecified: @@ -2847,8 +2847,12 @@ namespace { if (partialApply && result.isolation.isGlobalActor()) return false; - // A call to a global-actor-isolated function is diagnosed elsewhere. - if (!partialApply && result.isolation.isGlobalActor() && + // A call to a global-actor-isolated function, or a function with an + // isolated parameter, is diagnosed elsewhere. + if (!partialApply && + (result.isolation.isGlobalActor() || + (result.isolation == ActorIsolation::ActorInstance && + result.isolation.getActorInstanceParameter() > 0)) && isa(decl)) return false; @@ -3654,6 +3658,22 @@ static OverrideIsolationResult validOverrideIsolation( } } +/// Retrieve the index of the first isolated parameter of the given +/// declaration, if there is one. +static Optional getIsolatedParamIndex(ValueDecl *value) { + auto params = getParameterList(value); + if (!params) + return None; + + for (unsigned paramIdx : range(params->size())) { + auto param = params->get(paramIdx); + if (param->isIsolated()) + return paramIdx; + } + + return None; +} + ActorIsolation ActorIsolationRequest::evaluate( Evaluator &evaluator, ValueDecl *value) const { // If this declaration has actor-isolated "self", it's isolated to that @@ -3661,7 +3681,22 @@ ActorIsolation ActorIsolationRequest::evaluate( if (evaluateOrDefault(evaluator, HasIsolatedSelfRequest{value}, false)) { auto actor = value->getDeclContext()->getSelfNominalTypeDecl(); assert(actor && "could not find the actor that 'self' is isolated to"); - return ActorIsolation::forActorInstance(actor); + return ActorIsolation::forActorInstanceSelf(actor); + } + + // If this declaration has an isolated parameter, it's isolated to that + // parameter. + if (auto paramIdx = getIsolatedParamIndex(value)) { + // FIXME: This doesn't allow us to find an Actor or DistributedActor + // bound on the parameter type effectively. + auto param = getParameterList(value)->get(*paramIdx); + Type paramType = param->getInterfaceType(); + if (paramType->isTypeParameter()) { + paramType = param->getDeclContext()->mapTypeIntoContext(paramType); + } + + if (auto actor = paramType->getAnyActor()) + return ActorIsolation::forActorInstanceParameter(actor, *paramIdx); } auto isolationFromAttr = getIsolationFromAttributes(value); @@ -3947,6 +3982,10 @@ bool HasIsolatedSelfRequest::evaluate( value = accessor->getStorage(); } + // If there is an isolated parameter, then "self" is not isolated. + if (getIsolatedParamIndex(value)) + return false; + // Check whether this member can be isolated to an actor at all. auto memberIsolation = getMemberIsolationPropagation(value); if (!memberIsolation) @@ -4950,7 +4989,7 @@ static ActorIsolation getActorIsolationForReference( // as needing to enter the actor. if (auto nominal = ctor->getDeclContext()->getSelfNominalTypeDecl()) { if (nominal->isAnyActor()) - return ActorIsolation::forActorInstance(nominal); + return ActorIsolation::forActorInstanceSelf(nominal); } // Fall through to treat initializers like any other declaration. @@ -4966,7 +5005,7 @@ static ActorIsolation getActorIsolationForReference( declIsolation.isIndependent()) { if (auto nominal = var->getDeclContext()->getSelfNominalTypeDecl()) { if (nominal->isAnyActor()) - return ActorIsolation::forActorInstance(nominal); + return ActorIsolation::forActorInstanceSelf(nominal); auto nominalIsolation = getActorIsolation(nominal); if (nominalIsolation.isGlobalActor()) @@ -5137,7 +5176,8 @@ ActorReferenceResult ActorReferenceResult::forReference( // The declaration we are accessing is actor-isolated. First, check whether // we are on the same actor already. - if (actorInstance && declIsolation == ActorIsolation::ActorInstance) { + if (actorInstance && declIsolation == ActorIsolation::ActorInstance && + declIsolation.getActorInstanceParameter() == 0) { // If this instance is isolated, we're in the same concurrency domain. if (actorInstance->isIsolated()) return forSameConcurrencyDomain(declIsolation); diff --git a/test/Concurrency/isolated_parameters.swift b/test/Concurrency/isolated_parameters.swift index 7a8bc526dde77..451790c1859a9 100644 --- a/test/Concurrency/isolated_parameters.swift +++ b/test/Concurrency/isolated_parameters.swift @@ -41,7 +41,7 @@ func testIsolatedParamCalls(a: isolated A, b: A) { globalFunc(b) globalFuncIsolated(a) - globalFuncIsolated(b) // expected-error{{call to actor-isolated global function 'globalFuncIsolated' in a synchronous nonisolated context}} + globalFuncIsolated(b) // expected-error{{call to actor-isolated global function 'globalFuncIsolated' in a synchronous actor-isolated context}} } @available(SwiftStdlib 5.1, *) @@ -63,6 +63,7 @@ typealias MyFn = (isolated: Int) -> Void // expected-error {{function types cann typealias MyFnFixed = (_: isolated MyActor) -> Void func standalone(_: isolated MyActor) {} + func check() { let _: MyFnFixed = standalone let _: MyFnFixed = { (_: isolated MyActor) in () } @@ -148,6 +149,14 @@ func testExistentialIsolated(a: isolated P2, b: P2) async { // "isolated" parameters of closures make the closure itself isolated. extension TestActor { func isolatedMethod() { } + // expected-note@-1{{calls to instance method 'isolatedMethod()' from outside of its actor context are implicitly asynchronous}} + + func isolatedToParameter(_ other: isolated TestActor) { + isolatedMethod() + // expected-error@-1{{actor-isolated instance method 'isolatedMethod()' can not be referenced on a non-isolated actor instance}} + + other.isolatedMethod() + } } @available(SwiftStdlib 5.1, *) From 5191c315e1003ece325d1aba482360ba7789b0b5 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 23 Aug 2022 23:17:24 -0700 Subject: [PATCH 340/491] Eliminate ImplicitActorHopTarget in favor of ActorIsolation. The generalized ActorIsolation is enough to represent everything that ImplicitActorHopTarget can do, and we were mapping between the two way too often, so collapse them. --- include/swift/AST/Expr.h | 89 ++++++------------------------- lib/SILGen/SILGenApply.cpp | 26 +++++---- lib/SILGen/SILGenFunction.h | 4 +- lib/SILGen/SILGenLValue.cpp | 12 +---- lib/Sema/TypeCheckConcurrency.cpp | 31 ++--------- 5 files changed, 39 insertions(+), 123 deletions(-) diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index c076091f43336..bcf9b80ba98d9 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -1163,80 +1163,19 @@ class DiscardAssignmentExpr : public Expr { } }; -/// Describes the actor to which an implicit-async expression will hop. -struct ImplicitActorHopTarget { - enum Kind { - /// The "self" instance. - InstanceSelf, - /// A global actor with the given type. - GlobalActor, - /// An isolated parameter in a call. - IsolatedParameter, - }; - -private: - /// The lower two bits are the Kind, and the remaining bits are used for - /// the payload, which might by a TypeBase * (for a global actor) or a - /// integer value (for an isolated parameter). - uintptr_t bits; - - constexpr ImplicitActorHopTarget(uintptr_t bits) : bits(bits) { } - -public: - /// Default-initialized to instance "self". - constexpr ImplicitActorHopTarget() : bits(0) { } - - static ImplicitActorHopTarget forInstanceSelf() { - return ImplicitActorHopTarget(InstanceSelf); - } - - static ImplicitActorHopTarget forGlobalActor(Type globalActor) { - uintptr_t bits = - reinterpret_cast(globalActor.getPointer()) | GlobalActor; - return ImplicitActorHopTarget(bits); - } - - static ImplicitActorHopTarget forIsolatedParameter(unsigned index) { - uintptr_t bits = static_cast(index) << 2 | IsolatedParameter; - return ImplicitActorHopTarget(bits); - } - - /// Determine the kind of implicit actor hop being performed. - Kind getKind() const { - return static_cast(bits & 0x03); - } - - operator Kind() const { - return getKind(); - } - - /// Retrieve the global actor type for an implicit hop to a global actor. - Type getGlobalActor() const { - assert(getKind() == GlobalActor); - return Type(reinterpret_cast(bits & ~0x03)); - } - - /// Retrieve the (zero-based) parameter index for the isolated parameter - /// in a call. - unsigned getIsolatedParameterIndex() const { - assert(getKind() == IsolatedParameter); - return bits >> 2; - } -}; - - /// DeclRefExpr - A reference to a value, "x". class DeclRefExpr : public Expr { /// The declaration pointer. ConcreteDeclRef D; DeclNameLoc Loc; - ImplicitActorHopTarget implicitActorHopTarget; + ActorIsolation implicitActorHopTarget; public: DeclRefExpr(ConcreteDeclRef D, DeclNameLoc Loc, bool Implicit, AccessSemantics semantics = AccessSemantics::Ordinary, Type Ty = Type()) - : Expr(ExprKind::DeclRef, Implicit, Ty), D(D), Loc(Loc) { + : Expr(ExprKind::DeclRef, Implicit, Ty), D(D), Loc(Loc), + implicitActorHopTarget(ActorIsolation::forUnspecified()) { Bits.DeclRefExpr.Semantics = (unsigned) semantics; Bits.DeclRefExpr.FunctionRefKind = static_cast(Loc.isCompound() ? FunctionRefKind::Compound @@ -1258,7 +1197,7 @@ class DeclRefExpr : public Expr { /// Determine whether this reference needs to happen asynchronously, i.e., /// guarded by hop_to_executor, and if so describe the target. - Optional isImplicitlyAsync() const { + Optional isImplicitlyAsync() const { if (!Bits.DeclRefExpr.IsImplicitlyAsync) return None; @@ -1266,7 +1205,7 @@ class DeclRefExpr : public Expr { } /// Note that this reference is implicitly async and set the target. - void setImplicitlyAsync(ImplicitActorHopTarget target) { + void setImplicitlyAsync(ActorIsolation target) { Bits.DeclRefExpr.IsImplicitlyAsync = true; implicitActorHopTarget = target; } @@ -1600,12 +1539,13 @@ class UnresolvedDeclRefExpr : public Expr { class LookupExpr : public Expr { Expr *Base; ConcreteDeclRef Member; - ImplicitActorHopTarget implicitActorHopTarget; + ActorIsolation implicitActorHopTarget; protected: explicit LookupExpr(ExprKind Kind, Expr *base, ConcreteDeclRef member, bool Implicit) - : Expr(Kind, Implicit), Base(base), Member(member) { + : Expr(Kind, Implicit), Base(base), Member(member), + implicitActorHopTarget(ActorIsolation::forUnspecified()) { Bits.LookupExpr.IsSuper = false; Bits.LookupExpr.IsImplicitlyAsync = false; Bits.LookupExpr.IsImplicitlyThrows = false; @@ -1640,7 +1580,7 @@ class LookupExpr : public Expr { /// Determine whether this reference needs to happen asynchronously, i.e., /// guarded by hop_to_executor, and if so describe the target. - Optional isImplicitlyAsync() const { + Optional isImplicitlyAsync() const { if (!Bits.LookupExpr.IsImplicitlyAsync) return None; @@ -1648,7 +1588,7 @@ class LookupExpr : public Expr { } /// Note that this reference is implicitly async and set the target. - void setImplicitlyAsync(ImplicitActorHopTarget target) { + void setImplicitlyAsync(ActorIsolation target) { Bits.LookupExpr.IsImplicitlyAsync = true; implicitActorHopTarget = target; } @@ -4482,12 +4422,13 @@ class ApplyExpr : public Expr { /// The list of arguments to call the function with. ArgumentList *ArgList; - ImplicitActorHopTarget implicitActorHopTarget; + ActorIsolation implicitActorHopTarget; protected: ApplyExpr(ExprKind kind, Expr *fn, ArgumentList *argList, bool implicit, Type ty = Type()) - : Expr(kind, implicit, ty), Fn(fn), ArgList(argList) { + : Expr(kind, implicit, ty), Fn(fn), ArgList(argList), + implicitActorHopTarget(ActorIsolation::forUnspecified()) { assert(ArgList); assert(classof((Expr*)this) && "ApplyExpr::classof out of date"); Bits.ApplyExpr.ThrowsIsSet = false; @@ -4553,7 +4494,7 @@ class ApplyExpr : public Expr { /// /// When the application is implicitly async, the result describes /// the actor to which we need to need to hop. - Optional isImplicitlyAsync() const { + Optional isImplicitlyAsync() const { if (!Bits.ApplyExpr.ImplicitlyAsync) return None; @@ -4561,7 +4502,7 @@ class ApplyExpr : public Expr { } /// Note that this application is implicitly async and set the target. - void setImplicitlyAsync(ImplicitActorHopTarget target) { + void setImplicitlyAsync(ActorIsolation target) { Bits.ApplyExpr.ImplicitlyAsync = true; implicitActorHopTarget = target; } diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index e34eaab0ce105..35459db698b02 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -3886,7 +3886,7 @@ class CallEmission { Callee callee; FormalEvaluationScope initialWritebackScope; - Optional implicitActorHopTarget; + Optional implicitActorHopTarget; bool implicitlyThrows; public: @@ -3937,7 +3937,7 @@ class CallEmission { /// implicitly async, i.e., it requires a hop_to_executor prior to /// invoking the sync callee, etc. void setImplicitlyAsync( - Optional implicitActorHopTarget) { + Optional implicitActorHopTarget) { this->implicitActorHopTarget = implicitActorHopTarget; } @@ -4573,7 +4573,7 @@ RValue SILGenFunction::emitApply( ArrayRef args, const CalleeTypeInfo &calleeTypeInfo, ApplyOptions options, SGFContext evalContext, - Optional implicitActorHopTarget) { + Optional implicitActorHopTarget) { auto substFnType = calleeTypeInfo.substFnType; auto substResultType = calleeTypeInfo.substResultType; @@ -4672,18 +4672,24 @@ RValue SILGenFunction::emitApply( SILValue executor; switch (*implicitActorHopTarget) { - case ImplicitActorHopTarget::InstanceSelf: - executor = emitLoadActorExecutor(loc, args.back()); + case ActorIsolation::ActorInstance: + if (unsigned paramIndex = + implicitActorHopTarget->getActorInstanceParameter()) { + executor = emitLoadActorExecutor(loc, args[paramIndex-1]); + } else { + executor = emitLoadActorExecutor(loc, args.back()); + } break; - case ImplicitActorHopTarget::GlobalActor: + case ActorIsolation::GlobalActor: + case ActorIsolation::GlobalActorUnsafe: executor = emitLoadGlobalActorExecutor( implicitActorHopTarget->getGlobalActor()); break; - case ImplicitActorHopTarget::IsolatedParameter: - executor = emitLoadActorExecutor( - loc, args[implicitActorHopTarget->getIsolatedParameterIndex()]); + case ActorIsolation::Unspecified: + case ActorIsolation::Independent: + llvm_unreachable("Not isolated"); break; } @@ -5897,7 +5903,7 @@ RValue SILGenFunction::emitGetAccessor( PreparedArguments &&subscriptIndices, SGFContext c, bool isOnSelfParameter, - Optional implicitActorHopTarget) { + Optional implicitActorHopTarget) { // Scope any further writeback just within this operation. FormalEvaluationScope writebackScope(*this); diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index f192cf553f6f1..094c1cfd06239 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -1451,7 +1451,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction bool isDirectAccessorUse, PreparedArguments &&optionalSubscripts, SGFContext C, bool isOnSelfParameter, - Optional implicitActorHopTarget = None); + Optional implicitActorHopTarget = None); void emitSetAccessor(SILLocation loc, SILDeclRef setter, SubstitutionMap substitutions, @@ -1684,7 +1684,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction ArrayRef args, const CalleeTypeInfo &calleeTypeInfo, ApplyOptions options, SGFContext evalContext, - Optional implicitActorHopTarget); + Optional implicitActorHopTarget); RValue emitApplyOfDefaultArgGenerator(SILLocation loc, ConcreteDeclRef defaultArgsOwner, diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index 1256bcd570789..b2978d3486c22 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -1648,23 +1648,13 @@ namespace { RValue rvalue; FormalEvaluationScope scope(SGF); - // FIXME: This somewhat silly, because the original expression should - // already have one of these. - Optional implicitActorHopTarget; - if (ActorIso) { - implicitActorHopTarget = ActorIso->isGlobalActor() - ? ImplicitActorHopTarget::forGlobalActor( - ActorIso->getGlobalActor()) - : ImplicitActorHopTarget::forInstanceSelf(); - } - auto args = std::move(*this).prepareAccessorArgs(SGF, loc, base, getter); rvalue = SGF.emitGetAccessor( loc, getter, Substitutions, std::move(args.base), IsSuper, IsDirectAccessorUse, std::move(args.Indices), c, - IsOnSelfParameter, implicitActorHopTarget); + IsOnSelfParameter, ActorIso); return rvalue; } diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 92b32c20b934b..e818eacf78e11 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -1783,7 +1783,7 @@ namespace { /// /// and we reach up to mark the CallExpr. void markNearestCallAsImplicitly( - Optional setAsync, + Optional setAsync, bool setThrows = false, bool setDistributedThunk = false) { assert(applyStack.size() > 0 && "not contained within an Apply?"); @@ -2369,7 +2369,7 @@ namespace { AsyncMarkingResult tryMarkImplicitlyAsync(SourceLoc declLoc, ConcreteDeclRef concDeclRef, Expr* context, - ImplicitActorHopTarget target, + ActorIsolation target, bool isDistributed) { ValueDecl *decl = concDeclRef.getDecl(); AsyncMarkingResult result = AsyncMarkingResult::NotFound; @@ -2583,25 +2583,8 @@ namespace { } // Mark as implicitly async. - if (!fnType->getExtInfo().isAsync()) { - switch (*unsatisfiedIsolation) { - case ActorIsolation::GlobalActor: - case ActorIsolation::GlobalActorUnsafe: - apply->setImplicitlyAsync( - ImplicitActorHopTarget::forGlobalActor( - unsatisfiedIsolation->getGlobalActor())); - break; - - case ActorIsolation::ActorInstance: - apply->setImplicitlyAsync( - ImplicitActorHopTarget::forIsolatedParameter( - unsatisfiedIsolation->getActorInstanceParameter() - 1)); - break; - - case ActorIsolation::Unspecified: - case ActorIsolation::Independent: - llvm_unreachable("Not actor-isolated"); - } + if (!fnType->getExtInfo().isAsync() && unsatisfiedIsolation) { + apply->setImplicitlyAsync(*unsatisfiedIsolation); } // Check for sendability of the parameter types. @@ -2879,12 +2862,8 @@ namespace { ActorReferenceResult::Flags::Distributed); // Determine the actor hop. - ImplicitActorHopTarget target = result.isolation.isGlobalActor() - ? ImplicitActorHopTarget::forGlobalActor( - result.isolation.getGlobalActor()) - : ImplicitActorHopTarget::forInstanceSelf(); auto implicitAsyncResult = tryMarkImplicitlyAsync( - loc, declRef, context, target, isDistributed); + loc, declRef, context, result.isolation, isDistributed); switch (implicitAsyncResult) { case AsyncMarkingResult::FoundAsync: // Success! We're done. From 3bba7caacc9227991b9d0bced55eda1d489dfb10 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 10 Aug 2022 19:25:39 +0200 Subject: [PATCH 341/491] Swift SIL: add `var Function.instructions` To be used to iterate over all instructions in a function without the need of two loops - one for blocks and one for instructions. --- .../Optimizer/DataStructures/Set.swift | 8 ++- .../FunctionPasses/AssumeSingleThreaded.swift | 8 ++- .../FunctionPasses/EscapeInfoDumper.swift | 50 +++++++++---------- .../ObjCBridgingOptimization.swift | 10 ++-- .../FunctionPasses/RangeDumper.swift | 34 ++++++------- .../FunctionPasses/StackPromotion.swift | 30 ++++++----- .../Sources/SIL/Function.swift | 5 ++ 7 files changed, 68 insertions(+), 77 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/DataStructures/Set.swift b/SwiftCompilerSources/Sources/Optimizer/DataStructures/Set.swift index ffbe04c80312c..a1bfb36860667 100644 --- a/SwiftCompilerSources/Sources/Optimizer/DataStructures/Set.swift +++ b/SwiftCompilerSources/Sources/Optimizer/DataStructures/Set.swift @@ -150,11 +150,9 @@ struct InstructionSet : CustomStringConvertible, CustomReflectable { var description: String { let function = NodeSet_getFunction(bridged).function var d = "{\n" - for block in function.blocks { - for inst in block.instructions { - if contains(inst) { - d += inst.description - } + for inst in function.instructions { + if contains(inst) { + d += inst.description } } d += "}\n" diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AssumeSingleThreaded.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AssumeSingleThreaded.swift index b1a8b9af27a75..8247534a45038 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AssumeSingleThreaded.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AssumeSingleThreaded.swift @@ -29,12 +29,10 @@ import SIL let assumeSingleThreadedPass = FunctionPass( name: "sil-assume-single-threaded", { function, context in - for block in function.blocks { - for inst in block.instructions { - guard let rcInst = inst as? RefCountingInst else { continue } + for inst in function.instructions { + guard let rcInst = inst as? RefCountingInst else { continue } - rcInst.setAtomicity(isAtomic: false, context) - } + rcInst.setAtomicity(isAtomic: false, context) } } ) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/EscapeInfoDumper.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/EscapeInfoDumper.swift index f82d3b3c16577..611c1fd6cfacd 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/EscapeInfoDumper.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/EscapeInfoDumper.swift @@ -43,24 +43,22 @@ let escapeInfoDumper = FunctionPass(name: "dump-escape-info", { } - for block in function.blocks { - for inst in block.instructions { - if let allocRef = inst as? AllocRefInst { - - var walker = EscapeInfo(calleeAnalysis: context.calleeAnalysis, visitor: Visitor()) - let escapes = walker.isEscaping(object: allocRef) - let results = walker.visitor.results - - let res: String - if escapes { - res = "global" - } else if results.isEmpty { - res = " - " - } else { - res = Array(results).sorted().joined(separator: ",") - } - print("\(res): \(allocRef)") + for inst in function.instructions { + if let allocRef = inst as? AllocRefInst { + + var walker = EscapeInfo(calleeAnalysis: context.calleeAnalysis, visitor: Visitor()) + let escapes = walker.isEscaping(object: allocRef) + let results = walker.visitor.results + + let res: String + if escapes { + res = "global" + } else if results.isEmpty { + res = " - " + } else { + res = Array(results).sorted().joined(separator: ",") } + print("\(res): \(allocRef)") } } print("End function \(function.name)\n") @@ -81,16 +79,14 @@ let addressEscapeInfoDumper = FunctionPass(name: "dump-addr-escape-info", { var valuesToCheck = [Value]() var applies = [Instruction]() - for block in function.blocks { - for inst in block.instructions { - switch inst { - case let fli as FixLifetimeInst: - valuesToCheck.append(fli.operand) - case is FullApplySite: - applies.append(inst) - default: - break - } + for inst in function.instructions { + switch inst { + case let fli as FixLifetimeInst: + valuesToCheck.append(fli.operand) + case is FullApplySite: + applies.append(inst) + default: + break } } diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ObjCBridgingOptimization.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ObjCBridgingOptimization.swift index c849efb8b486d..73db276924609 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ObjCBridgingOptimization.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ObjCBridgingOptimization.swift @@ -48,12 +48,10 @@ let objCBridgingOptimization = FunctionPass(name: "objc-bridging-opt", { } // Now try to optimize non-optional and optional -> non-optional bridging. - for block in function.blocks { - for inst in block.instructions { - if let apply = inst as? ApplyInst { - if !optimizeNonOptionalBridging(apply, context) { - return - } + for inst in function.instructions { + if let apply = inst as? ApplyInst { + if !optimizeNonOptionalBridging(apply, context) { + return } } } diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RangeDumper.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RangeDumper.swift index d31526417aa89..d39b7813ed75a 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RangeDumper.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RangeDumper.swift @@ -25,24 +25,22 @@ let rangeDumper = FunctionPass(name: "dump-ranges", { var outs = Stack(context) defer { outs.deinitialize() } - for block in function.blocks { - for inst in block.instructions { - if let sli = inst as? StringLiteralInst { - switch sli.string { - case "begin": - precondition(begin == nil, "more than one begin instruction") - begin = sli - case "end": - ends.append(sli) - case "interior": - interiors.append(sli) - case "inside": - ins.append(sli) - case "outside": - outs.append(sli) - default: - break - } + for inst in function.instructions { + if let sli = inst as? StringLiteralInst { + switch sli.string { + case "begin": + precondition(begin == nil, "more than one begin instruction") + begin = sli + case "end": + ends.append(sli) + case "interior": + interiors.append(sli) + case "inside": + ins.append(sli) + case "outside": + outs.append(sli) + default: + break } } } diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift index 6cca6101fe16f..e9fc445d001ff 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift @@ -44,23 +44,21 @@ let stackPromotion = FunctionPass(name: "stack-promotion", { let deadEndBlocks = context.deadEndBlocks var changed = false - for block in function.blocks { - for inst in block.instructions { - if let ar = inst as? AllocRefInstBase { - if deadEndBlocks.isDeadEnd(block) { - // Don't stack promote any allocation inside a code region which ends up - // in a no-return block. Such allocations may missing their final release. - // We would insert the deallocation too early, which may result in a - // use-after-free problem. - continue - } - if !context.continueWithNextSubpassRun(for: ar) { - break - } + for inst in function.instructions { + if let ar = inst as? AllocRefInstBase { + if deadEndBlocks.isDeadEnd(ar.block) { + // Don't stack promote any allocation inside a code region which ends up + // in a no-return block. Such allocations may missing their final release. + // We would insert the deallocation too early, which may result in a + // use-after-free problem. + continue + } + if !context.continueWithNextSubpassRun(for: ar) { + break + } - if tryPromoteAlloc(ar, deadEndBlocks, context) { - changed = true - } + if tryPromoteAlloc(ar, deadEndBlocks, context) { + changed = true } } } diff --git a/SwiftCompilerSources/Sources/SIL/Function.swift b/SwiftCompilerSources/Sources/SIL/Function.swift index 82709bc1d8386..b82bbf3e91099 100644 --- a/SwiftCompilerSources/Sources/SIL/Function.swift +++ b/SwiftCompilerSources/Sources/SIL/Function.swift @@ -41,6 +41,11 @@ final public class Function : CustomStringConvertible, HasShortDescription { entryBlock.arguments.lazy.map { $0 as! FunctionArgument } } + /// All instructions of all blocks. + public var instructions: LazySequence, List>>> { + blocks.lazy.flatMap { $0.instructions } + } + public var numIndirectResultArguments: Int { SILFunction_numIndirectResultArguments(bridged) } From beebd5a9208b15f062b3a3db16a0f56e33de9bf1 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Thu, 11 Aug 2022 10:51:28 +0200 Subject: [PATCH 342/491] PassManager: add a invalidation kind for non-body function data E.g. used if function effects are changed. This tells the passmanager that something changed, but no SIL-specific analysis have to be invalidated. --- .../Sources/Optimizer/PassManager/PassContext.swift | 6 +++++- include/swift/SIL/SILBridging.h | 3 ++- include/swift/SILOptimizer/Analysis/Analysis.h | 8 +++++++- lib/SILOptimizer/PassManager/PassManager.cpp | 3 +++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassContext.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassContext.swift index 162fbed1aad51..da1520e30d717 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassContext.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassContext.swift @@ -117,8 +117,8 @@ struct PassContext { } func modifyEffects(in function: Function, _ body: (inout FunctionEffects) -> ()) { + notifyFunctionDataChanged() function._modifyEffects(body) - // TODO: do we need to notify any changes? } //===--------------------------------------------------------------------===// @@ -136,6 +136,10 @@ struct PassContext { fileprivate func notifyBranchesChanged() { PassContext_notifyChanges(_bridged, branchesChanged) } + + fileprivate func notifyFunctionDataChanged() { + PassContext_notifyChanges(_bridged, functionDataChanged) + } } //===----------------------------------------------------------------------===// diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index bd04266bad540..0b9b47b4daa31 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -29,7 +29,8 @@ enum { enum ChangeNotificationKind { instructionsChanged, callsChanged, - branchesChanged + branchesChanged, + functionDataChanged }; typedef struct { diff --git a/include/swift/SILOptimizer/Analysis/Analysis.h b/include/swift/SILOptimizer/Analysis/Analysis.h index e0c5c931574e5..57eadf138569d 100644 --- a/include/swift/SILOptimizer/Analysis/Analysis.h +++ b/include/swift/SILOptimizer/Analysis/Analysis.h @@ -64,6 +64,12 @@ class SILAnalysis { /// has been modified. Branches = 0x4, + /// Any function data other than its body. + /// + /// It does not trigger any analysis invalidation, but tells the pass + /// manager that some changes were made. + FunctionData = 0x8, + /// Convenience states: FunctionBody = Calls | Branches | Instructions, @@ -71,7 +77,7 @@ class SILAnalysis { BranchesAndInstructions = Branches | Instructions, - Everything = Calls | Branches | Instructions, + Everything = Calls | Branches | Instructions | FunctionData, }; private: diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index 641ac38bab6c2..01e962985398c 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -1380,6 +1380,9 @@ void PassContext_notifyChanges(BridgedPassContext passContext, case branchesChanged: inv->notifyChanges(SILAnalysis::InvalidationKind::BranchesAndInstructions); break; + case functionDataChanged: + inv->notifyChanges(SILAnalysis::InvalidationKind::FunctionData); + break; } } From 306e5b0c9c88db5ad7c5423b4404f5b8842e8360 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Thu, 11 Aug 2022 16:07:24 +0200 Subject: [PATCH 343/491] Swift SIL: make `Function` hashable --- SwiftCompilerSources/Sources/SIL/Function.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SwiftCompilerSources/Sources/SIL/Function.swift b/SwiftCompilerSources/Sources/SIL/Function.swift index b82bbf3e91099..02f99c0c6e37e 100644 --- a/SwiftCompilerSources/Sources/SIL/Function.swift +++ b/SwiftCompilerSources/Sources/SIL/Function.swift @@ -13,7 +13,7 @@ import Basic import SILBridging -final public class Function : CustomStringConvertible, HasShortDescription { +final public class Function : CustomStringConvertible, HasShortDescription, Hashable { public private(set) var effects = FunctionEffects() public var name: StringRef { @@ -27,6 +27,10 @@ final public class Function : CustomStringConvertible, HasShortDescription { public var shortDescription: String { name.string } + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } + public var hasOwnership: Bool { SILFunction_hasOwnership(bridged) != 0 } public var entryBlock: BasicBlock { From c2ef10661a99d4ddc0a9b770fcacbc9f92df4527 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 23 Aug 2022 16:31:11 +0200 Subject: [PATCH 344/491] Swift Optimizer: move function passes which are only used for unit testing to their own `TestPasses` directory. --- .../Sources/Optimizer/CMakeLists.txt | 1 + .../Optimizer/FunctionPasses/CMakeLists.txt | 5 ----- .../PassManager/PassRegistration.swift | 17 +++++++++++------ .../AccessDumper.swift | 0 .../Sources/Optimizer/TestPasses/CMakeLists.txt | 15 +++++++++++++++ .../EscapeInfoDumper.swift | 0 .../RangeDumper.swift | 0 .../RunUnitTests.swift | 0 .../SILPrinter.swift | 0 9 files changed, 27 insertions(+), 11 deletions(-) rename SwiftCompilerSources/Sources/Optimizer/{FunctionPasses => TestPasses}/AccessDumper.swift (100%) create mode 100644 SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt rename SwiftCompilerSources/Sources/Optimizer/{FunctionPasses => TestPasses}/EscapeInfoDumper.swift (100%) rename SwiftCompilerSources/Sources/Optimizer/{FunctionPasses => TestPasses}/RangeDumper.swift (100%) rename SwiftCompilerSources/Sources/Optimizer/{FunctionPasses => TestPasses}/RunUnitTests.swift (100%) rename SwiftCompilerSources/Sources/Optimizer/{FunctionPasses => TestPasses}/SILPrinter.swift (100%) diff --git a/SwiftCompilerSources/Sources/Optimizer/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/CMakeLists.txt index ed754dd792c94..7bb7e9703c5cc 100644 --- a/SwiftCompilerSources/Sources/Optimizer/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/Optimizer/CMakeLists.txt @@ -16,4 +16,5 @@ add_subdirectory(DataStructures) add_subdirectory(InstructionPasses) add_subdirectory(PassManager) add_subdirectory(FunctionPasses) +add_subdirectory(TestPasses) add_subdirectory(Utilities) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt index 8280018e458a4..8e31099932145 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt @@ -8,14 +8,9 @@ swift_compiler_sources(Optimizer AssumeSingleThreaded.swift - AccessDumper.swift ComputeEffects.swift - EscapeInfoDumper.swift ObjCBridgingOptimization.swift - SILPrinter.swift MergeCondFails.swift - RangeDumper.swift ReleaseDevirtualizer.swift - RunUnitTests.swift StackPromotion.swift ) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift index 99f0629addce4..351bfa000b61f 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift @@ -38,20 +38,25 @@ private func registerPass( } private func registerSwiftPasses() { - registerPass(silPrinterPass, { silPrinterPass.run($0) }) + // Function passes registerPass(mergeCondFailsPass, { mergeCondFailsPass.run($0) }) - registerPass(escapeInfoDumper, { escapeInfoDumper.run($0) }) - registerPass(addressEscapeInfoDumper, { addressEscapeInfoDumper.run($0) }) - registerPass(accessDumper, { accessDumper.run($0) }) registerPass(computeEffects, { computeEffects.run($0) }) registerPass(objCBridgingOptimization, { objCBridgingOptimization.run($0) }) registerPass(stackPromotion, { stackPromotion.run($0) }) + registerPass(assumeSingleThreadedPass, { assumeSingleThreadedPass.run($0) }) + registerPass(releaseDevirtualizerPass, { releaseDevirtualizerPass.run($0) }) + + // Instruction passes registerPass(simplifyBeginCOWMutationPass, { simplifyBeginCOWMutationPass.run($0) }) registerPass(simplifyGlobalValuePass, { simplifyGlobalValuePass.run($0) }) registerPass(simplifyStrongRetainPass, { simplifyStrongRetainPass.run($0) }) registerPass(simplifyStrongReleasePass, { simplifyStrongReleasePass.run($0) }) - registerPass(assumeSingleThreadedPass, { assumeSingleThreadedPass.run($0) }) + + // Test passes + registerPass(silPrinterPass, { silPrinterPass.run($0) }) + registerPass(escapeInfoDumper, { escapeInfoDumper.run($0) }) + registerPass(addressEscapeInfoDumper, { addressEscapeInfoDumper.run($0) }) + registerPass(accessDumper, { accessDumper.run($0) }) registerPass(rangeDumper, { rangeDumper.run($0) }) registerPass(runUnitTests, { runUnitTests.run($0) }) - registerPass(releaseDevirtualizerPass, { releaseDevirtualizerPass.run($0) }) } diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AccessDumper.swift b/SwiftCompilerSources/Sources/Optimizer/TestPasses/AccessDumper.swift similarity index 100% rename from SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AccessDumper.swift rename to SwiftCompilerSources/Sources/Optimizer/TestPasses/AccessDumper.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt new file mode 100644 index 0000000000000..856ffe7e4454d --- /dev/null +++ b/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt @@ -0,0 +1,15 @@ +# This source file is part of the Swift.org open source project +# +# Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors +# Licensed under Apache License v2.0 with Runtime Library Exception +# +# See http://swift.org/LICENSE.txt for license information +# See http://swift.org/CONTRIBUTORS.txt for Swift project authors + +swift_compiler_sources(Optimizer + AccessDumper.swift + EscapeInfoDumper.swift + SILPrinter.swift + RangeDumper.swift + RunUnitTests.swift +) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/EscapeInfoDumper.swift b/SwiftCompilerSources/Sources/Optimizer/TestPasses/EscapeInfoDumper.swift similarity index 100% rename from SwiftCompilerSources/Sources/Optimizer/FunctionPasses/EscapeInfoDumper.swift rename to SwiftCompilerSources/Sources/Optimizer/TestPasses/EscapeInfoDumper.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RangeDumper.swift b/SwiftCompilerSources/Sources/Optimizer/TestPasses/RangeDumper.swift similarity index 100% rename from SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RangeDumper.swift rename to SwiftCompilerSources/Sources/Optimizer/TestPasses/RangeDumper.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RunUnitTests.swift b/SwiftCompilerSources/Sources/Optimizer/TestPasses/RunUnitTests.swift similarity index 100% rename from SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RunUnitTests.swift rename to SwiftCompilerSources/Sources/Optimizer/TestPasses/RunUnitTests.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/SILPrinter.swift b/SwiftCompilerSources/Sources/Optimizer/TestPasses/SILPrinter.swift similarity index 100% rename from SwiftCompilerSources/Sources/Optimizer/FunctionPasses/SILPrinter.swift rename to SwiftCompilerSources/Sources/Optimizer/TestPasses/SILPrinter.swift From 50155557374d8d40c4c803e9371f3b21c801ec8a Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 12 Aug 2022 13:07:15 +0200 Subject: [PATCH 345/491] Swift SIL: add a utility protocol `BridgedRandomAccessCollection` It fixes the default reflection for bridged random access collections, which usually have a `bridged` stored property. Conforming to this protocol displays the "real" children of a bridged random access collection and not just `bridged`. --- SwiftCompilerSources/Sources/SIL/Utils.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/SwiftCompilerSources/Sources/SIL/Utils.swift b/SwiftCompilerSources/Sources/SIL/Utils.swift index 80f1fcec2ff9f..5c5e9ed63835e 100644 --- a/SwiftCompilerSources/Sources/SIL/Utils.swift +++ b/SwiftCompilerSources/Sources/SIL/Utils.swift @@ -131,6 +131,20 @@ extension FormattedLikeArray { } } +/// RandomAccessCollection which bridges to some C++ array. +/// +/// It fixes the default reflection for bridged random access collections, which usually have a +/// `bridged` stored property. +/// Conforming to this protocol displays the "real" children not just `bridged`. +public protocol BridgedRandomAccessCollection : RandomAccessCollection, CustomReflectable { +} + +extension BridgedRandomAccessCollection { + public var customMirror: Mirror { + Mirror(self, children: self.map { (label: nil, value: $0 as Any) }) + } +} + /// A Sequence which is not consuming and therefore behaves like a Collection. /// /// Many sequences in SIL and the optimizer should be collections but cannot From fe40707d5e0758a5964d30074945238d42374fe4 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 12 Aug 2022 16:55:37 +0200 Subject: [PATCH 346/491] Swift SIL: add `Function.isPossiblyUsedExternally` and `Function.isAvailableExternally` --- SwiftCompilerSources/Sources/SIL/Function.swift | 16 ++++++++++++++++ include/swift/SIL/SILBridging.h | 2 ++ lib/SIL/Utils/SILBridging.cpp | 8 ++++++++ 3 files changed, 26 insertions(+) diff --git a/SwiftCompilerSources/Sources/SIL/Function.swift b/SwiftCompilerSources/Sources/SIL/Function.swift index 02f99c0c6e37e..ca0206ffd5ae1 100644 --- a/SwiftCompilerSources/Sources/SIL/Function.swift +++ b/SwiftCompilerSources/Sources/SIL/Function.swift @@ -74,6 +74,22 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash return nil } + /// True, if the linkage of the function indicates that it is visible outside the current + /// compilation unit and therefore not all of its uses are known. + /// + /// For example, `public` linkage. + public var isPossiblyUsedExternally: Bool { + return SILFunction_isPossiblyUsedExternally(bridged) != 0 + } + + /// True, if the linkage of the function indicates that it has a definition outside the + /// current compilation unit. + /// + /// For example, `public_external` linkage. + public var isAvailableExternally: Bool { + return SILFunction_isAvailableExternally(bridged) != 0 + } + public func hasSemanticsAttribute(_ attr: StaticString) -> Bool { attr.withUTF8Buffer { (buffer: UnsafeBufferPointer) in SILFunction_hasSemanticsAttr(bridged, llvm.StringRef(buffer.baseAddress!, buffer.count)) != 0 diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index 0b9b47b4daa31..e36f0493ced75 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -224,6 +224,8 @@ SwiftInt SILFunction_getNumSILArguments(BridgedFunction function); BridgedType SILFunction_getSILArgumentType(BridgedFunction function, SwiftInt idx); BridgedType SILFunction_getSILResultType(BridgedFunction function); SwiftInt SILFunction_isSwift51RuntimeAvailable(BridgedFunction function); +SwiftInt SILFunction_isPossiblyUsedExternally(BridgedFunction function); +SwiftInt SILFunction_isAvailableExternally(BridgedFunction function); SwiftInt SILFunction_hasSemanticsAttr(BridgedFunction function, llvm::StringRef attrName); diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index 14af248bfc635..74e68ee1ea457 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -217,6 +217,14 @@ SwiftInt SILFunction_isSwift51RuntimeAvailable(BridgedFunction function) { ctxt.getSwift51Availability()); } +SwiftInt SILFunction_isPossiblyUsedExternally(BridgedFunction function) { + return castToFunction(function)->isPossiblyUsedExternally() ? 1 : 0; +} + +SwiftInt SILFunction_isAvailableExternally(BridgedFunction function) { + return castToFunction(function)->isAvailableExternally() ? 1 : 0; +} + SwiftInt SILFunction_hasSemanticsAttr(BridgedFunction function, StringRef attrName) { SILFunction *f = castToFunction(function); From de6e539a0a64ed1430d24d6c95fb13a98761e2ad Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 23 Aug 2022 09:00:10 +0200 Subject: [PATCH 347/491] Swift Optimizer: make the set's insert functions return a Bool. Returning true if the element was not contained in the set before inserting --- .../DataStructures/BasicBlockRange.swift | 3 +-- .../DataStructures/BasicBlockWorklist.swift | 3 +-- .../Sources/Optimizer/DataStructures/Set.swift | 18 ++++++++++++------ include/swift/SILOptimizer/OptimizerBridging.h | 6 +++--- lib/SILOptimizer/PassManager/PassManager.cpp | 12 ++++++------ 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockRange.swift b/SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockRange.swift index fa5a5a92e2f3a..e2027d7dad7e0 100644 --- a/SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockRange.swift +++ b/SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockRange.swift @@ -78,8 +78,7 @@ struct BasicBlockRange : CustomStringConvertible, CustomReflectable { /// Insert a potential end block. mutating func insert(_ block: BasicBlock) { - if !wasInserted.contains(block) { - wasInserted.insert(block) + if wasInserted.insert(block) { inserted.append(block) } worklist.pushIfNotVisited(block) diff --git a/SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockWorklist.swift b/SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockWorklist.swift index d30348a7ea753..e7214fe09e75f 100644 --- a/SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockWorklist.swift +++ b/SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockWorklist.swift @@ -34,8 +34,7 @@ struct BasicBlockWorklist : CustomStringConvertible, CustomReflectable { /// Pushes \p block onto the worklist if \p block has never been pushed before. mutating func pushIfNotVisited(_ block: BasicBlock) { - if !pushedBlocks.contains(block) { - pushedBlocks.insert(block); + if pushedBlocks.insert(block) { worklist.append(block) } } diff --git a/SwiftCompilerSources/Sources/Optimizer/DataStructures/Set.swift b/SwiftCompilerSources/Sources/Optimizer/DataStructures/Set.swift index a1bfb36860667..845249886770a 100644 --- a/SwiftCompilerSources/Sources/Optimizer/DataStructures/Set.swift +++ b/SwiftCompilerSources/Sources/Optimizer/DataStructures/Set.swift @@ -35,8 +35,10 @@ struct BasicBlockSet : CustomStringConvertible, CustomReflectable { BasicBlockSet_contains(bridged, block.bridged) != 0 } - mutating func insert(_ block: BasicBlock) { - BasicBlockSet_insert(bridged, block.bridged) + /// Returns true if `block` was not contained in the set before inserting. + @discardableResult + mutating func insert(_ block: BasicBlock) -> Bool { + BasicBlockSet_insert(bridged, block.bridged) != 0 } mutating func erase(_ block: BasicBlock) { @@ -80,8 +82,10 @@ struct ValueSet : CustomStringConvertible, CustomReflectable { NodeSet_containsValue(bridged, value.bridged) != 0 } - mutating func insert(_ value: Value) { - NodeSet_insertValue(bridged, value.bridged) + /// Returns true if `value` was not contained in the set before inserting. + @discardableResult + mutating func insert(_ value: Value) -> Bool { + NodeSet_insertValue(bridged, value.bridged) != 0 } mutating func erase(_ value: Value) { @@ -139,8 +143,10 @@ struct InstructionSet : CustomStringConvertible, CustomReflectable { NodeSet_containsInstruction(bridged, inst.bridged) != 0 } - mutating func insert(_ inst: Instruction) { - NodeSet_insertInstruction(bridged, inst.bridged) + /// Returns true if `inst` was not contained in the set before inserting. + @discardableResult + mutating func insert(_ inst: Instruction) -> Bool { + NodeSet_insertInstruction(bridged, inst.bridged) != 0 } mutating func erase(_ inst: Instruction) { diff --git a/include/swift/SILOptimizer/OptimizerBridging.h b/include/swift/SILOptimizer/OptimizerBridging.h index 115b094315887..9589ab92f9efc 100644 --- a/include/swift/SILOptimizer/OptimizerBridging.h +++ b/include/swift/SILOptimizer/OptimizerBridging.h @@ -135,7 +135,7 @@ BridgedBasicBlockSet PassContext_allocBasicBlockSet(BridgedPassContext context); void PassContext_freeBasicBlockSet(BridgedPassContext context, BridgedBasicBlockSet set); SwiftInt BasicBlockSet_contains(BridgedBasicBlockSet set, BridgedBasicBlock block); -void BasicBlockSet_insert(BridgedBasicBlockSet set, BridgedBasicBlock block); +SwiftInt BasicBlockSet_insert(BridgedBasicBlockSet set, BridgedBasicBlock block); void BasicBlockSet_erase(BridgedBasicBlockSet set, BridgedBasicBlock block); BridgedFunction BasicBlockSet_getFunction(BridgedBasicBlockSet set); @@ -143,10 +143,10 @@ BridgedNodeSet PassContext_allocNodeSet(BridgedPassContext context); void PassContext_freeNodeSet(BridgedPassContext context, BridgedNodeSet set); SwiftInt NodeSet_containsValue(BridgedNodeSet set, BridgedValue value); -void NodeSet_insertValue(BridgedNodeSet set, BridgedValue value); +SwiftInt NodeSet_insertValue(BridgedNodeSet set, BridgedValue value); void NodeSet_eraseValue(BridgedNodeSet set, BridgedValue value); SwiftInt NodeSet_containsInstruction(BridgedNodeSet set, BridgedInstruction inst); -void NodeSet_insertInstruction(BridgedNodeSet set, BridgedInstruction inst); +SwiftInt NodeSet_insertInstruction(BridgedNodeSet set, BridgedInstruction inst); void NodeSet_eraseInstruction(BridgedNodeSet set, BridgedInstruction inst); BridgedFunction NodeSet_getFunction(BridgedNodeSet set); diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index 01e962985398c..50f5b3a55f1d1 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -1469,8 +1469,8 @@ SwiftInt BasicBlockSet_contains(BridgedBasicBlockSet set, BridgedBasicBlock bloc return castToBlockSet(set)->contains(castToBasicBlock(block)) ? 1 : 0; } -void BasicBlockSet_insert(BridgedBasicBlockSet set, BridgedBasicBlock block) { - castToBlockSet(set)->insert(castToBasicBlock(block)); +SwiftInt BasicBlockSet_insert(BridgedBasicBlockSet set, BridgedBasicBlock block) { + return castToBlockSet(set)->insert(castToBasicBlock(block)) ? 1 : 0; } void BasicBlockSet_erase(BridgedBasicBlockSet set, BridgedBasicBlock block) { @@ -1494,8 +1494,8 @@ SwiftInt NodeSet_containsValue(BridgedNodeSet set, BridgedValue value) { return castToNodeSet(set)->contains(castToSILValue(value)) ? 1 : 0; } -void NodeSet_insertValue(BridgedNodeSet set, BridgedValue value) { - castToNodeSet(set)->insert(castToSILValue(value)); +SwiftInt NodeSet_insertValue(BridgedNodeSet set, BridgedValue value) { + return castToNodeSet(set)->insert(castToSILValue(value)) ? 1 : 0; } void NodeSet_eraseValue(BridgedNodeSet set, BridgedValue value) { @@ -1506,8 +1506,8 @@ SwiftInt NodeSet_containsInstruction(BridgedNodeSet set, BridgedInstruction inst return castToNodeSet(set)->contains(castToInst(inst)->asSILNode()) ? 1 : 0; } -void NodeSet_insertInstruction(BridgedNodeSet set, BridgedInstruction inst) { - castToNodeSet(set)->insert(castToInst(inst)->asSILNode()); +SwiftInt NodeSet_insertInstruction(BridgedNodeSet set, BridgedInstruction inst) { + return castToNodeSet(set)->insert(castToInst(inst)->asSILNode()) ? 1 : 0; } void NodeSet_eraseInstruction(BridgedNodeSet set, BridgedInstruction inst) { From 7b9b97fb76389e16ab28d97cee46497cc298ab23 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 23 Aug 2022 15:33:23 +0200 Subject: [PATCH 348/491] Swift SIL: fix `BeginAccessInst.endInstructions` --- SwiftCompilerSources/Sources/SIL/Instruction.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftCompilerSources/Sources/SIL/Instruction.swift b/SwiftCompilerSources/Sources/SIL/Instruction.swift index 8bdf695255366..7b1b808151989 100644 --- a/SwiftCompilerSources/Sources/SIL/Instruction.swift +++ b/SwiftCompilerSources/Sources/SIL/Instruction.swift @@ -534,7 +534,7 @@ extension BeginAccessInst : ScopedInstruction { public typealias EndInstructions = LazyMapSequence>, EndAccessInst> public var endInstructions: EndInstructions { - uses.lazy.compactMap({ $0.value.definingInstruction as? EndAccessInst }) + uses.lazy.compactMap({ $0.instruction as? EndAccessInst }) } } From 87f2f41d512cd0269fdd8377d0f84d7a631a1fcb Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 10 Aug 2022 21:16:04 +0200 Subject: [PATCH 349/491] Swift Optimizer: add infrastructure for module passes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To add a module pass in `Passes.def` use the new `SWIFT_MODULE_PASS` macro. On the swift side, create a `ModulePass`. It’s run function receives a `ModulePassContext`, which provides access to all functions of a module. But it doesn't provide any APIs to modify functions. In order to modify a function, a module pass must use `ModulePassContext.transform(function:)`. --- .../Optimizer/PassManager/CMakeLists.txt | 1 + .../PassManager/ModulePassContext.swift | 51 +++++++++++++++++++ .../PassManager/PassRegistration.swift | 8 +++ .../Optimizer/PassManager/Passes.swift | 17 +++++++ .../swift/SILOptimizer/OptimizerBridging.h | 13 ++++- .../SILOptimizer/PassManager/PassManager.h | 18 +++++++ .../swift/SILOptimizer/PassManager/Passes.def | 12 +++++ lib/SILOptimizer/PassManager/PassManager.cpp | 40 +++++++++++++++ lib/SILOptimizer/PassManager/Passes.cpp | 43 ++++++++++++++-- 9 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/PassManager/CMakeLists.txt index 2d081f91e45e0..58aef5bb7e5bf 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/CMakeLists.txt @@ -7,6 +7,7 @@ # See http://swift.org/CONTRIBUTORS.txt for Swift project authors swift_compiler_sources(Optimizer + ModulePassContext.swift Passes.swift PassContext.swift PassRegistration.swift) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift new file mode 100644 index 0000000000000..13a623d551dbc --- /dev/null +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift @@ -0,0 +1,51 @@ +//===--- ModulePassContext.swift ------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 SIL +import OptimizerBridging + +/// The context which is passed to a `ModulePass`'s run-function. +/// +/// It provides access to all functions of a module, but it doesn't provide any +/// APIs to modify functions. +/// In order to modify a function, a module pass must use `transform(function:)`. +struct ModulePassContext { + let _bridged: BridgedPassContext + + struct FunctionList : CollectionLikeSequence, IteratorProtocol { + private var currentFunction: Function? + + fileprivate init(first: Function?) { currentFunction = first } + + mutating func next() -> Function? { + if let f = currentFunction { + currentFunction = PassContext_nextFunctionInModule(f.bridged).function + return f + } + return nil + } + } + + var functions: FunctionList { + FunctionList(first: PassContext_firstFunctionInModule(_bridged).function) + } + + /// Run a closure with a `PassContext` for a function, which allows to modify that function. + /// + /// Only a single `transform` can be alive at the same time, i.e. it's not allowed to nest + /// calls to `transform`. + func transform(function: Function, _ runOnFunction: (PassContext) -> ()) { + PassContext_beginTransformFunction(function.bridged, _bridged) + runOnFunction(PassContext(_bridged: _bridged)) + PassContext_endTransformFunction(_bridged); + } +} diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift index 351bfa000b61f..1a81f56043338 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift @@ -21,6 +21,14 @@ public func initializeSwiftModules() { initializeSwiftParseModules() } +private func registerPass( + _ pass: ModulePass, + _ runFn: @escaping (@convention(c) (BridgedPassContext) -> ())) { + pass.name._withStringRef { nameStr in + SILPassManager_registerModulePass(nameStr, runFn) + } +} + private func registerPass( _ pass: FunctionPass, _ runFn: @escaping (@convention(c) (BridgedFunctionPassCtxt) -> ())) { diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/Passes.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/Passes.swift index 5d0f60c14e028..d4df586db3f7d 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/Passes.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/Passes.swift @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// import SIL +import OptimizerBridging struct FunctionPass { @@ -47,3 +48,19 @@ struct InstructionPass { } } +struct ModulePass { + + let name: String + let runFunction: (ModulePassContext) -> () + + public init(name: String, + _ runFunction: @escaping (ModulePassContext) -> ()) { + self.name = name + self.runFunction = runFunction + } + + func run(_ bridgedCtxt: BridgedPassContext) { + let context = ModulePassContext(_bridged: bridgedCtxt) + runFunction(context) + } +} diff --git a/include/swift/SILOptimizer/OptimizerBridging.h b/include/swift/SILOptimizer/OptimizerBridging.h index 9589ab92f9efc..7fbc1e8b63add 100644 --- a/include/swift/SILOptimizer/OptimizerBridging.h +++ b/include/swift/SILOptimizer/OptimizerBridging.h @@ -77,12 +77,14 @@ typedef struct { void * _Nonnull functionInfo; } BridgedRCIdentityFunctionInfo; +typedef void (* _Nonnull BridgedModulePassRunFn)(BridgedPassContext); typedef void (* _Nonnull BridgedFunctionPassRunFn)(BridgedFunctionPassCtxt); typedef void (* _Nonnull BridgedInstructionPassRunFn)(BridgedInstructionPassCtxt); +void SILPassManager_registerModulePass(llvm::StringRef name, + BridgedModulePassRunFn runFn); void SILPassManager_registerFunctionPass(llvm::StringRef name, BridgedFunctionPassRunFn runFn); - void SILCombine_registerInstructionPass(llvm::StringRef name, BridgedInstructionPassRunFn runFn); @@ -156,6 +158,15 @@ BridgedSubstitutionMap PassContext_getContextSubstitutionMap(BridgedPassContext context, BridgedType bridgedType); +void PassContext_beginTransformFunction(BridgedFunction function, + BridgedPassContext ctxt); +void PassContext_endTransformFunction(BridgedPassContext ctxt); + +OptionalBridgedFunction +PassContext_firstFunctionInModule(BridgedPassContext context); +OptionalBridgedFunction +PassContext_nextFunctionInModule(BridgedFunction function); + OptionalBridgedFunction PassContext_loadFunction(BridgedPassContext context, llvm::StringRef name); diff --git a/include/swift/SILOptimizer/PassManager/PassManager.h b/include/swift/SILOptimizer/PassManager/PassManager.h index ea19eb28c4913..9889d30f3f28f 100644 --- a/include/swift/SILOptimizer/PassManager/PassManager.h +++ b/include/swift/SILOptimizer/PassManager/PassManager.h @@ -108,17 +108,35 @@ class SwiftPassInvocation { /// Called by the pass when changes are made to the SIL. void notifyChanges(SILAnalysis::InvalidationKind invalidationKind); + /// Called by the pass manager before the pass starts running. + void startModulePassRun(SILModuleTransform *transform); + /// Called by the pass manager before the pass starts running. void startFunctionPassRun(SILFunctionTransform *transform); /// Called by the SILCombiner before the instruction pass starts running. void startInstructionPassRun(SILInstruction *inst); + /// Called by the pass manager when the pass has finished. + void finishedModulePassRun(); + /// Called by the pass manager when the pass has finished. void finishedFunctionPassRun(); /// Called by the SILCombiner when the instruction pass has finished. void finishedInstructionPassRun(); + + void beginTransformFunction(SILFunction *function) { + assert(!this->function && transform && "not running a module pass"); + this->function = function; + } + + void endTransformFunction() { + assert(function && "beginTransformFunction not called"); + function = nullptr; + assert(numBlockSetsAllocated == 0 && "Not all BasicBlockSets deallocated"); + assert(numNodeSetsAllocated == 0 && "Not all NodeSets deallocated"); + } }; /// The SIL pass manager. diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def index d188bc7258605..2cb87b88abe34 100644 --- a/include/swift/SILOptimizer/PassManager/Passes.def +++ b/include/swift/SILOptimizer/PassManager/Passes.def @@ -43,6 +43,17 @@ #define IRGEN_PASS(Id, Tag, Description) PASS(Id, Tag, Description) #endif +/// SWIFT_MODULE_PASS(Id, Tag, Description) +/// This macro follows the same conventions as PASS(Id, Tag, Description), +/// but is used for module passes which are implemented in Swift. +/// +/// No further code is need on the C++ side. On the swift swift a module +/// pass with the same name must be registered with 'registerPass()'. +/// +#ifndef SWIFT_MODULE_PASS +#define SWIFT_MODULE_PASS(Id, Tag, Description) PASS(Id, Tag, Description) +#endif + /// SWIFT_FUNCTION_PASS(Id, Tag, Description) /// This macro follows the same conventions as PASS(Id, Tag, Description), /// but is used for function passes which are implemented in Swift. @@ -468,6 +479,7 @@ SWIFT_INSTRUCTION_PASS_WITH_LEGACY(StrongRetainInst, "simplify-strong_retain") SWIFT_INSTRUCTION_PASS_WITH_LEGACY(StrongReleaseInst, "simplify-strong_release") #undef IRGEN_PASS +#undef SWIFT_MODULE_PASS #undef SWIFT_FUNCTION_PASS #undef SWIFT_FUNCTION_PASS_WITH_LEGACY #undef SWIFT_INSTRUCTION_PASS diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index 50f5b3a55f1d1..160a2b1cd153b 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -727,11 +727,14 @@ void SILPassManager::runModulePass(unsigned TransIdx) { verifyAnalyses(); } + swiftPassInvocation.startModulePassRun(SMT); + llvm::sys::TimePoint<> StartTime = std::chrono::system_clock::now(); assert(analysesUnlocked() && "Expected all analyses to be unlocked!"); SMT->run(); assert(analysesUnlocked() && "Expected all analyses to be unlocked!"); Mod->flushDeletedInsts(); + swiftPassInvocation.finishedModulePassRun(); std::chrono::nanoseconds duration = std::chrono::system_clock::now() - StartTime; totalPassRuntime += duration; @@ -1279,6 +1282,12 @@ void SwiftPassInvocation::freeNodeSet(NodeSet *set) { } } +void SwiftPassInvocation::startModulePassRun(SILModuleTransform *transform) { + assert(!this->function && !this->transform && "a pass is already running"); + this->function = nullptr; + this->transform = transform; +} + void SwiftPassInvocation::startFunctionPassRun(SILFunctionTransform *transform) { assert(!this->function && !this->transform && "a pass is already running"); this->function = transform->getFunction(); @@ -1290,6 +1299,12 @@ void SwiftPassInvocation::startInstructionPassRun(SILInstruction *inst) { "running instruction pass on wrong function"); } +void SwiftPassInvocation::finishedModulePassRun() { + endPassRunChecks(); + assert(!function && transform && "not running a pass"); + transform = nullptr; +} + void SwiftPassInvocation::finishedFunctionPassRun() { endPassRunChecks(); assert(function && transform && "not running a pass"); @@ -1533,6 +1548,31 @@ PassContext_getContextSubstitutionMap(BridgedPassContext context, return {type.getASTType()->getContextSubstitutionMap(m, ntd).getOpaqueValue()}; } +void PassContext_beginTransformFunction(BridgedFunction function, BridgedPassContext ctxt) { + castToPassInvocation(ctxt)->beginTransformFunction(castToFunction(function)); +} + +void PassContext_endTransformFunction(BridgedPassContext ctxt) { + castToPassInvocation(ctxt)->endTransformFunction(); +} + +OptionalBridgedFunction +PassContext_firstFunctionInModule(BridgedPassContext context) { + SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule(); + if (mod->getFunctions().empty()) + return {nullptr}; + return {&*mod->getFunctions().begin()}; +} + +OptionalBridgedFunction +PassContext_nextFunctionInModule(BridgedFunction function) { + auto *f = castToFunction(function); + auto nextIter = std::next(f->getIterator()); + if (nextIter == f->getModule().getFunctions().end()) + return {nullptr}; + return {&*nextIter}; +} + OptionalBridgedFunction PassContext_loadFunction(BridgedPassContext context, StringRef name) { SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule(); diff --git a/lib/SILOptimizer/PassManager/Passes.cpp b/lib/SILOptimizer/PassManager/Passes.cpp index ab198d04b5fc5..002c7fcc27f12 100644 --- a/lib/SILOptimizer/PassManager/Passes.cpp +++ b/lib/SILOptimizer/PassManager/Passes.cpp @@ -217,9 +217,30 @@ void swift::runSILLoweringPasses(SILModule &Module) { } /// Registered briged pass run functions. -static llvm::StringMap bridgedPassRunFunctions; +static llvm::StringMap bridgedModulePassRunFunctions; +static llvm::StringMap bridgedFunctionPassRunFunctions; static bool passesRegistered = false; +/// Runs a bridged module pass. +/// +/// \p runFunction is a cache for the run function, so that it has to be looked +/// up only once in bridgedPassRunFunctions. +static void runBridgedModulePass(BridgedModulePassRunFn &runFunction, + SILPassManager *passManager, + StringRef passName) { + if (!runFunction) { + runFunction = bridgedModulePassRunFunctions[passName]; + if (!runFunction) { + if (passesRegistered) { + llvm::errs() << "Swift pass " << passName << " is not registered\n"; + abort(); + } + return; + } + } + runFunction({passManager->getSwiftPassInvocation()}); +} + /// Runs a bridged function pass. /// /// \p runFunction is a cache for the run function, so that it has to be looked @@ -228,7 +249,7 @@ static void runBridgedFunctionPass(BridgedFunctionPassRunFn &runFunction, SILPassManager *passManager, SILFunction *f, StringRef passName) { if (!runFunction) { - runFunction = bridgedPassRunFunctions[passName]; + runFunction = bridgedFunctionPassRunFunctions[passName]; if (!runFunction) { if (passesRegistered) { llvm::errs() << "Swift pass " << passName << " is not registered\n"; @@ -245,9 +266,15 @@ static void runBridgedFunctionPass(BridgedFunctionPassRunFn &runFunction, } // Called from initializeSwiftModules(). +void SILPassManager_registerModulePass(llvm::StringRef name, + BridgedModulePassRunFn runFn) { + bridgedModulePassRunFunctions[name] = runFn; + passesRegistered = true; +} + void SILPassManager_registerFunctionPass(llvm::StringRef name, BridgedFunctionPassRunFn runFn) { - bridgedPassRunFunctions[name] = runFn; + bridgedFunctionPassRunFunctions[name] = runFn; passesRegistered = true; } @@ -263,6 +290,16 @@ BridgedFunctionPassRunFn ID##Pass::runFunction = nullptr; \ #define PASS(ID, TAG, DESCRIPTION) #define SWIFT_INSTRUCTION_PASS(INST, TAG) +#define SWIFT_MODULE_PASS(ID, TAG, DESCRIPTION) \ +class ID##Pass : public SILModuleTransform { \ + static BridgedModulePassRunFn runFunction; \ + void run() override { \ + runBridgedModulePass(runFunction, PM, TAG); \ + } \ +}; \ +BridgedModulePassRunFn ID##Pass::runFunction = nullptr; \ +SILTransform *swift::create##ID() { return new ID##Pass(); } \ + #define SWIFT_FUNCTION_PASS(ID, TAG, DESCRIPTION) \ SWIFT_FUNCTION_PASS_COMMON(ID, TAG) \ SILTransform *swift::create##ID() { return new ID##Pass(); } \ From 7816513f0d53dee642075edd1e85b4ac455532d3 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Thu, 11 Aug 2022 16:10:44 +0200 Subject: [PATCH 350/491] Swift SIL: add bridging for vTables --- .../PassManager/ModulePassContext.swift | 22 +++++++- .../Sources/SIL/CMakeLists.txt | 3 +- SwiftCompilerSources/Sources/SIL/VTable.swift | 55 +++++++++++++++++++ include/swift/SIL/SILBridging.h | 16 +++++- include/swift/SIL/SILBridgingUtils.h | 9 +++ .../swift/SILOptimizer/OptimizerBridging.h | 6 ++ lib/SIL/Utils/SILBridging.cpp | 32 +++++++++++ lib/SILOptimizer/PassManager/PassManager.cpp | 6 ++ 8 files changed, 144 insertions(+), 5 deletions(-) create mode 100644 SwiftCompilerSources/Sources/SIL/VTable.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift index 13a623d551dbc..71572927f20b6 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift @@ -15,8 +15,8 @@ import OptimizerBridging /// The context which is passed to a `ModulePass`'s run-function. /// -/// It provides access to all functions of a module, but it doesn't provide any -/// APIs to modify functions. +/// It provides access to all functions, v-tables and witness tables of a module, +/// but it doesn't provide any APIs to modify functions. /// In order to modify a function, a module pass must use `transform(function:)`. struct ModulePassContext { let _bridged: BridgedPassContext @@ -34,11 +34,27 @@ struct ModulePassContext { return nil } } - + + struct VTableArray : BridgedRandomAccessCollection { + fileprivate let bridged: BridgedVTableArray + + var startIndex: Int { return 0 } + var endIndex: Int { return Int(bridged.count) } + + subscript(_ index: Int) -> VTable { + precondition(index >= 0 && index < bridged.count) + return VTable(bridged: bridged.vTables![index]) + } + } + var functions: FunctionList { FunctionList(first: PassContext_firstFunctionInModule(_bridged).function) } + var vTables: VTableArray { + VTableArray(bridged: PassContext_getVTables(_bridged)) + } + /// Run a closure with a `PassContext` for a function, which allows to modify that function. /// /// Only a single `transform` can be alive at the same time, i.e. it's not allowed to nest diff --git a/SwiftCompilerSources/Sources/SIL/CMakeLists.txt b/SwiftCompilerSources/Sources/SIL/CMakeLists.txt index a9e8073c786e2..d69d492bcd18d 100644 --- a/SwiftCompilerSources/Sources/SIL/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/SIL/CMakeLists.txt @@ -25,5 +25,6 @@ add_swift_compiler_module(SIL SubstitutionMap.swift Type.swift Utils.swift - Value.swift) + Value.swift + VTable.swift) diff --git a/SwiftCompilerSources/Sources/SIL/VTable.swift b/SwiftCompilerSources/Sources/SIL/VTable.swift new file mode 100644 index 0000000000000..7c2f3150fe37e --- /dev/null +++ b/SwiftCompilerSources/Sources/SIL/VTable.swift @@ -0,0 +1,55 @@ +//===--- VTable.swift -----------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 SILBridging + +public struct VTable : CustomStringConvertible, CustomReflectable { + let bridged: BridgedVTable + + public init(bridged: BridgedVTable) { self.bridged = bridged } + + public struct Entry : CustomStringConvertible, CustomReflectable { + fileprivate let bridged: BridgedVTableEntry + + public var function: Function { SILVTableEntry_getFunction(bridged).function } + + public var description: String { + let stdString = SILVTableEntry_debugDescription(bridged) + return String(_cxxString: stdString) + } + + public var customMirror: Mirror { Mirror(self, children: []) } + } + + public struct EntryArray : BridgedRandomAccessCollection { + fileprivate let bridgedArray: BridgedArrayRef + + public var startIndex: Int { return 0 } + public var endIndex: Int { return Int(bridgedArray.numElements) } + + public subscript(_ index: Int) -> Entry { + precondition(index >= 0 && index < endIndex) + return Entry(bridged: BridgedVTableEntry(ptr: bridgedArray.data! + index &* BridgedVTableEntrySize)) + } + } + + public var entries: EntryArray { + EntryArray(bridgedArray: SILVTable_getEntries(bridged)) + } + + public var description: String { + let stdString = SILVTable_debugDescription(bridged) + return String(_cxxString: stdString) + } + + public var customMirror: Mirror { Mirror(self, children: []) } +} diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index e36f0493ced75..0e308ab5e2759 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -23,7 +23,8 @@ SWIFT_BEGIN_NULLABILITY_ANNOTATIONS enum { BridgedOperandSize = 4 * sizeof(uintptr_t), - BridgedSuccessorSize = 4 * sizeof(uintptr_t) + sizeof(uint64_t) + BridgedSuccessorSize = 4 * sizeof(uintptr_t) + sizeof(uint64_t), + BridgedVTableEntrySize = 5 * sizeof(uintptr_t) }; enum ChangeNotificationKind { @@ -68,6 +69,14 @@ typedef struct { const void * _Nullable succ; } OptionalBridgedSuccessor; +typedef struct { + const void * _Nonnull ptr; +} BridgedVTable; + +typedef struct { + const void * _Nonnull ptr; +} BridgedVTableEntry; + typedef struct { SwiftObject obj; } BridgedFunction; @@ -233,6 +242,11 @@ llvm::StringRef SILGlobalVariable_getName(BridgedGlobalVar global); std::string SILGlobalVariable_debugDescription(BridgedGlobalVar global); SwiftInt SILGlobalVariable_isLet(BridgedGlobalVar global); +std::string SILVTable_debugDescription(BridgedVTable vTable); +BridgedArrayRef SILVTable_getEntries(BridgedVTable vTable); +std::string SILVTableEntry_debugDescription(BridgedVTableEntry entry); +BridgedFunction SILVTableEntry_getFunction(BridgedVTableEntry entry); + OptionalBridgedBasicBlock SILBasicBlock_next(BridgedBasicBlock block); OptionalBridgedBasicBlock SILBasicBlock_previous(BridgedBasicBlock block); BridgedFunction SILBasicBlock_getFunction(BridgedBasicBlock block); diff --git a/include/swift/SIL/SILBridgingUtils.h b/include/swift/SIL/SILBridgingUtils.h index 4483505a39547..5f66d56051c08 100644 --- a/include/swift/SIL/SILBridgingUtils.h +++ b/include/swift/SIL/SILBridgingUtils.h @@ -16,6 +16,7 @@ #include "swift/SIL/SILBridging.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILGlobalVariable.h" +#include "swift/SIL/SILVTable.h" #include "llvm/ADT/StringRef.h" #include @@ -84,6 +85,14 @@ inline SILGlobalVariable *castToGlobal(BridgedGlobalVar global) { return static_cast(global.obj); } +inline const SILVTable *castToVTable(BridgedVTable vTable) { + return static_cast(vTable.ptr); +} + +inline const SILVTableEntry *castToVTableEntry(BridgedVTableEntry entry) { + return static_cast(entry.ptr); +} + inline ValueOwnershipKind castToOwnership(BridgedOwnership ownership) { switch (ownership) { case Ownership_Unowned: return OwnershipKind::Unowned; diff --git a/include/swift/SILOptimizer/OptimizerBridging.h b/include/swift/SILOptimizer/OptimizerBridging.h index 7fbc1e8b63add..afcc017154e25 100644 --- a/include/swift/SILOptimizer/OptimizerBridging.h +++ b/include/swift/SILOptimizer/OptimizerBridging.h @@ -27,6 +27,11 @@ typedef struct { BridgedPassContext passContext; } BridgedInstructionPassCtxt; +typedef struct { + const BridgedVTable * _Nullable vTables; + size_t count; +} BridgedVTableArray; + typedef struct { const void * _Nonnull aliasAnalysis; } BridgedAliasAnalysis; @@ -166,6 +171,7 @@ OptionalBridgedFunction PassContext_firstFunctionInModule(BridgedPassContext context); OptionalBridgedFunction PassContext_nextFunctionInModule(BridgedFunction function); +BridgedVTableArray PassContext_getVTables(BridgedPassContext context); OptionalBridgedFunction PassContext_loadFunction(BridgedPassContext context, llvm::StringRef name); diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index 74e68ee1ea457..170d8870333fd 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -549,6 +549,38 @@ SwiftInt SILGlobalVariable_isLet(BridgedGlobalVar global) { return castToGlobal(global)->isLet(); } +//===----------------------------------------------------------------------===// +// SILVTable +//===----------------------------------------------------------------------===// + +static_assert(BridgedVTableEntrySize == sizeof(SILVTableEntry), + "wrong bridged VTableEntry size"); + +std::string SILVTable_debugDescription(BridgedVTable vTable) { + std::string str; + llvm::raw_string_ostream os(str); + castToVTable(vTable)->print(os); + str.pop_back(); // Remove trailing newline. + return str; +} + +BridgedArrayRef SILVTable_getEntries(BridgedVTable vTable) { + auto entries = castToVTable(vTable)->getEntries(); + return {(const unsigned char *)entries.data(), entries.size()}; +} + +std::string SILVTableEntry_debugDescription(BridgedVTableEntry entry) { + std::string str; + llvm::raw_string_ostream os(str); + castToVTableEntry(entry)->print(os); + str.pop_back(); // Remove trailing newline. + return str; +} + +BridgedFunction SILVTableEntry_getFunction(BridgedVTableEntry entry) { + return {castToVTableEntry(entry)->getImplementation()}; +} + //===----------------------------------------------------------------------===// // SILInstruction //===----------------------------------------------------------------------===// diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index 160a2b1cd153b..9ead83915b145 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -1573,6 +1573,12 @@ PassContext_nextFunctionInModule(BridgedFunction function) { return {&*nextIter}; } +BridgedVTableArray PassContext_getVTables(BridgedPassContext context) { + SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule(); + auto vTables = mod->getVTables(); + return {(const BridgedVTable *)vTables.data(), vTables.size()}; +} + OptionalBridgedFunction PassContext_loadFunction(BridgedPassContext context, StringRef name) { SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule(); From fbb694bcdee1e2d3246b66b048efcc56dbbb58e5 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 12 Aug 2022 13:13:11 +0200 Subject: [PATCH 351/491] Swift SIL: add bridging for witness and default witness tables --- .../PassManager/ModulePassContext.swift | 36 ++++++ .../Sources/SIL/CMakeLists.txt | 4 +- .../Sources/SIL/WitnessTable.swift | 114 ++++++++++++++++++ include/swift/SIL/SILBridging.h | 38 +++++- include/swift/SIL/SILBridgingUtils.h | 16 +++ include/swift/SIL/SILDefaultWitnessTable.h | 2 + include/swift/SIL/SILWitnessTable.h | 2 + .../swift/SILOptimizer/OptimizerBridging.h | 8 ++ lib/SIL/Utils/SILBridging.cpp | 61 ++++++++++ lib/SILOptimizer/PassManager/PassManager.cpp | 34 ++++++ 10 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 SwiftCompilerSources/Sources/SIL/WitnessTable.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift index 71572927f20b6..511457ffa849c 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift @@ -47,6 +47,34 @@ struct ModulePassContext { } } + struct WitnessTableList : CollectionLikeSequence, IteratorProtocol { + private var currentTable: WitnessTable? + + fileprivate init(first: WitnessTable?) { currentTable = first } + + mutating func next() -> WitnessTable? { + if let t = currentTable { + currentTable = PassContext_nextWitnessTableInModule(t.bridged).table + return t + } + return nil + } + } + + struct DefaultWitnessTableList : CollectionLikeSequence, IteratorProtocol { + private var currentTable: DefaultWitnessTable? + + fileprivate init(first: DefaultWitnessTable?) { currentTable = first } + + mutating func next() -> DefaultWitnessTable? { + if let t = currentTable { + currentTable = PassContext_nextDefaultWitnessTableInModule(t.bridged).table + return t + } + return nil + } + } + var functions: FunctionList { FunctionList(first: PassContext_firstFunctionInModule(_bridged).function) } @@ -55,6 +83,14 @@ struct ModulePassContext { VTableArray(bridged: PassContext_getVTables(_bridged)) } + var witnessTables: WitnessTableList { + WitnessTableList(first: PassContext_firstWitnessTableInModule(_bridged).table) + } + + var defaultWitnessTables: DefaultWitnessTableList { + DefaultWitnessTableList(first: PassContext_firstDefaultWitnessTableInModule(_bridged).table) + } + /// Run a closure with a `PassContext` for a function, which allows to modify that function. /// /// Only a single `transform` can be alive at the same time, i.e. it's not allowed to nest diff --git a/SwiftCompilerSources/Sources/SIL/CMakeLists.txt b/SwiftCompilerSources/Sources/SIL/CMakeLists.txt index d69d492bcd18d..dd737835f5bc7 100644 --- a/SwiftCompilerSources/Sources/SIL/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/SIL/CMakeLists.txt @@ -26,5 +26,5 @@ add_swift_compiler_module(SIL Type.swift Utils.swift Value.swift - VTable.swift) - + VTable.swift + WitnessTable.swift) diff --git a/SwiftCompilerSources/Sources/SIL/WitnessTable.swift b/SwiftCompilerSources/Sources/SIL/WitnessTable.swift new file mode 100644 index 0000000000000..3d110c9908f2f --- /dev/null +++ b/SwiftCompilerSources/Sources/SIL/WitnessTable.swift @@ -0,0 +1,114 @@ +//===--- WitnessTable.swift -----------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 SILBridging + +public struct WitnessTable : CustomStringConvertible, CustomReflectable { + public let bridged: BridgedWitnessTable + + public init(bridged: BridgedWitnessTable) { self.bridged = bridged } + + public struct Entry : CustomStringConvertible, CustomReflectable { + fileprivate let bridged: BridgedWitnessTableEntry + + public enum Kind { + case method + case associatedType + case associatedTypeProtocol + case baseProtocol + } + + public var kind: Kind { + switch SILWitnessTableEntry_getKind(bridged) { + case SILWitnessTableEntry_Method: return .method + case SILWitnessTableEntry_AssociatedType: return .associatedType + case SILWitnessTableEntry_AssociatedTypeProtocol: return .associatedTypeProtocol + case SILWitnessTableEntry_BaseProtocol: return .baseProtocol + default: + fatalError("unknown witness table kind") + } + } + + public var methodFunction: Function? { + assert(kind == .method) + return SILWitnessTableEntry_getMethodFunction(bridged).function + } + + public var description: String { + let stdString = SILWitnessTableEntry_debugDescription(bridged) + return String(_cxxString: stdString) + } + + public var customMirror: Mirror { Mirror(self, children: []) } + } + + public struct EntryArray : BridgedRandomAccessCollection { + fileprivate let bridged: BridgedArrayRef + + public var startIndex: Int { return 0 } + public var endIndex: Int { return Int(bridged.numElements) } + + public subscript(_ index: Int) -> Entry { + precondition(index >= 0 && index < endIndex) + return Entry(bridged: BridgedWitnessTableEntry(ptr: bridged.data! + index &* BridgedWitnessTableEntrySize)) + } + } + + public var entries: EntryArray { + EntryArray(bridged: SILWitnessTable_getEntries(bridged)) + } + + public var description: String { + let stdString = SILWitnessTable_debugDescription(bridged) + return String(_cxxString: stdString) + } + + public var customMirror: Mirror { Mirror(self, children: []) } +} + +public struct DefaultWitnessTable : CustomStringConvertible, CustomReflectable { + public let bridged: BridgedDefaultWitnessTable + + public init(bridged: BridgedDefaultWitnessTable) { self.bridged = bridged } + + public typealias Entry = WitnessTable.Entry + public typealias EntryArray = WitnessTable.EntryArray + + public var entries: EntryArray { + EntryArray(bridged: SILDefaultWitnessTable_getEntries(bridged)) + } + + public var description: String { + let stdString = SILDefaultWitnessTable_debugDescription(bridged) + return String(_cxxString: stdString) + } + + public var customMirror: Mirror { Mirror(self, children: []) } +} + +extension OptionalBridgedWitnessTable { + public var table: WitnessTable? { + if let p = ptr { + return WitnessTable(bridged: BridgedWitnessTable(ptr: p)) + } + return nil + } +} + +extension OptionalBridgedDefaultWitnessTable { + public var table: DefaultWitnessTable? { + if let p = ptr { + return DefaultWitnessTable(bridged: BridgedDefaultWitnessTable(ptr: p)) + } + return nil + } +} diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index 0e308ab5e2759..1496f269bf80c 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -24,7 +24,8 @@ SWIFT_BEGIN_NULLABILITY_ANNOTATIONS enum { BridgedOperandSize = 4 * sizeof(uintptr_t), BridgedSuccessorSize = 4 * sizeof(uintptr_t) + sizeof(uint64_t), - BridgedVTableEntrySize = 5 * sizeof(uintptr_t) + BridgedVTableEntrySize = 5 * sizeof(uintptr_t), + BridgedWitnessTableEntrySize = 5 * sizeof(uintptr_t) }; enum ChangeNotificationKind { @@ -77,6 +78,33 @@ typedef struct { const void * _Nonnull ptr; } BridgedVTableEntry; +typedef struct { + const void * _Nonnull ptr; +} BridgedWitnessTable; + +typedef struct { + const void * _Nullable ptr; +} OptionalBridgedWitnessTable; + +typedef struct { + const void * _Nonnull ptr; +} BridgedDefaultWitnessTable; + +typedef struct { + const void * _Nullable ptr; +} OptionalBridgedDefaultWitnessTable; + +typedef struct { + const void * _Nonnull ptr; +} BridgedWitnessTableEntry; + +typedef enum { + SILWitnessTableEntry_Method, + SILWitnessTableEntry_AssociatedType, + SILWitnessTableEntry_AssociatedTypeProtocol, + SILWitnessTableEntry_BaseProtocol +} SILWitnessTableEntryKind; + typedef struct { SwiftObject obj; } BridgedFunction; @@ -247,6 +275,14 @@ BridgedArrayRef SILVTable_getEntries(BridgedVTable vTable); std::string SILVTableEntry_debugDescription(BridgedVTableEntry entry); BridgedFunction SILVTableEntry_getFunction(BridgedVTableEntry entry); +std::string SILWitnessTable_debugDescription(BridgedWitnessTable table); +BridgedArrayRef SILWitnessTable_getEntries(BridgedWitnessTable table); +std::string SILDefaultWitnessTable_debugDescription(BridgedDefaultWitnessTable table); +BridgedArrayRef SILDefaultWitnessTable_getEntries(BridgedDefaultWitnessTable table); +std::string SILWitnessTableEntry_debugDescription(BridgedWitnessTableEntry entry); +SILWitnessTableEntryKind SILWitnessTableEntry_getKind(BridgedWitnessTableEntry entry); +OptionalBridgedFunction SILWitnessTableEntry_getMethodFunction(BridgedWitnessTableEntry entry); + OptionalBridgedBasicBlock SILBasicBlock_next(BridgedBasicBlock block); OptionalBridgedBasicBlock SILBasicBlock_previous(BridgedBasicBlock block); BridgedFunction SILBasicBlock_getFunction(BridgedBasicBlock block); diff --git a/include/swift/SIL/SILBridgingUtils.h b/include/swift/SIL/SILBridgingUtils.h index 5f66d56051c08..7da0e24b6e2bd 100644 --- a/include/swift/SIL/SILBridgingUtils.h +++ b/include/swift/SIL/SILBridgingUtils.h @@ -17,6 +17,8 @@ #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILGlobalVariable.h" #include "swift/SIL/SILVTable.h" +#include "swift/SIL/SILWitnessTable.h" +#include "swift/SIL/SILDefaultWitnessTable.h" #include "llvm/ADT/StringRef.h" #include @@ -93,6 +95,20 @@ inline const SILVTableEntry *castToVTableEntry(BridgedVTableEntry entry) { return static_cast(entry.ptr); } +inline const SILWitnessTable *castToWitnessTable(BridgedWitnessTable table) { + return static_cast(table.ptr); +} + +inline const SILDefaultWitnessTable * +castToDefaultWitnessTable(BridgedDefaultWitnessTable table) { + return static_cast(table.ptr); +} + +inline const SILWitnessTable::Entry * +castToWitnessTableEntry(BridgedWitnessTableEntry entry) { + return static_cast(entry.ptr); +} + inline ValueOwnershipKind castToOwnership(BridgedOwnership ownership) { switch (ownership) { case Ownership_Unowned: return OwnershipKind::Unowned; diff --git a/include/swift/SIL/SILDefaultWitnessTable.h b/include/swift/SIL/SILDefaultWitnessTable.h index aeed5f89827e9..8fc0072174ffc 100644 --- a/include/swift/SIL/SILDefaultWitnessTable.h +++ b/include/swift/SIL/SILDefaultWitnessTable.h @@ -105,6 +105,8 @@ class SILDefaultWitnessTable : public llvm::ilist_node, ~SILDefaultWitnessTable(); + SILModule &getModule() const { return Mod; } + /// Return true if this is a declaration with no body. bool isDeclaration() const { return IsDeclaration; } diff --git a/include/swift/SIL/SILWitnessTable.h b/include/swift/SIL/SILWitnessTable.h index 92c0efbe5a065..3a3cbb74550d9 100644 --- a/include/swift/SIL/SILWitnessTable.h +++ b/include/swift/SIL/SILWitnessTable.h @@ -223,6 +223,8 @@ class SILWitnessTable : public llvm::ilist_node, RootProtocolConformance *conformance); ~SILWitnessTable(); + + SILModule &getModule() const { return Mod; } /// Return the AST ProtocolConformance this witness table represents. RootProtocolConformance *getConformance() const { diff --git a/include/swift/SILOptimizer/OptimizerBridging.h b/include/swift/SILOptimizer/OptimizerBridging.h index afcc017154e25..53405267adc4b 100644 --- a/include/swift/SILOptimizer/OptimizerBridging.h +++ b/include/swift/SILOptimizer/OptimizerBridging.h @@ -172,6 +172,14 @@ PassContext_firstFunctionInModule(BridgedPassContext context); OptionalBridgedFunction PassContext_nextFunctionInModule(BridgedFunction function); BridgedVTableArray PassContext_getVTables(BridgedPassContext context); +OptionalBridgedWitnessTable +PassContext_firstWitnessTableInModule(BridgedPassContext context); +OptionalBridgedWitnessTable +PassContext_nextWitnessTableInModule(BridgedWitnessTable table); +OptionalBridgedDefaultWitnessTable +PassContext_firstDefaultWitnessTableInModule(BridgedPassContext context); +OptionalBridgedDefaultWitnessTable +PassContext_nextDefaultWitnessTableInModule(BridgedDefaultWitnessTable table); OptionalBridgedFunction PassContext_loadFunction(BridgedPassContext context, llvm::StringRef name); diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index 170d8870333fd..10b1f5e16e01c 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -581,6 +581,67 @@ BridgedFunction SILVTableEntry_getFunction(BridgedVTableEntry entry) { return {castToVTableEntry(entry)->getImplementation()}; } +//===----------------------------------------------------------------------===// +// SILVWitnessTable, SILDefaultWitnessTable +//===----------------------------------------------------------------------===// + +static_assert(BridgedWitnessTableEntrySize == sizeof(SILWitnessTable::Entry), + "wrong bridged WitnessTable entry size"); + +std::string SILWitnessTable_debugDescription(BridgedWitnessTable table) { + std::string str; + llvm::raw_string_ostream os(str); + castToWitnessTable(table)->print(os); + str.pop_back(); // Remove trailing newline. + return str; +} + +BridgedArrayRef SILWitnessTable_getEntries(BridgedWitnessTable table) { + auto entries = castToWitnessTable(table)->getEntries(); + return {(const unsigned char *)entries.data(), entries.size()}; +} + +std::string SILDefaultWitnessTable_debugDescription(BridgedDefaultWitnessTable table) { + std::string str; + llvm::raw_string_ostream os(str); + castToDefaultWitnessTable(table)->print(os); + str.pop_back(); // Remove trailing newline. + return str; +} + +BridgedArrayRef SILDefaultWitnessTable_getEntries(BridgedDefaultWitnessTable table) { + auto entries = castToDefaultWitnessTable(table)->getEntries(); + return {(const unsigned char *)entries.data(), entries.size()}; +} + +std::string SILWitnessTableEntry_debugDescription(BridgedWitnessTableEntry entry) { + std::string str; + llvm::raw_string_ostream os(str); + castToWitnessTableEntry(entry)->print(os, /*verbose=*/ false, + PrintOptions::printSIL()); + str.pop_back(); // Remove trailing newline. + return str; +} + +SILWitnessTableEntryKind SILWitnessTableEntry_getKind(BridgedWitnessTableEntry entry) { + switch (castToWitnessTableEntry(entry)->getKind()) { + case SILWitnessTable::Method: + return SILWitnessTableEntry_Method; + case SILWitnessTable::AssociatedType: + return SILWitnessTableEntry_AssociatedType; + case SILWitnessTable::AssociatedTypeProtocol: + return SILWitnessTableEntry_AssociatedTypeProtocol; + case SILWitnessTable::BaseProtocol: + return SILWitnessTableEntry_BaseProtocol; + default: + llvm_unreachable("wrong witness table entry kind"); + } +} + +OptionalBridgedFunction SILWitnessTableEntry_getMethodFunction(BridgedWitnessTableEntry entry) { + return {castToWitnessTableEntry(entry)->getMethodWitness().Witness}; +} + //===----------------------------------------------------------------------===// // SILInstruction //===----------------------------------------------------------------------===// diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index 9ead83915b145..47a1a3225d4e2 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -1579,6 +1579,40 @@ BridgedVTableArray PassContext_getVTables(BridgedPassContext context) { return {(const BridgedVTable *)vTables.data(), vTables.size()}; } +OptionalBridgedWitnessTable +PassContext_firstWitnessTableInModule(BridgedPassContext context) { + SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule(); + if (mod->getWitnessTables().empty()) + return {nullptr}; + return {&*mod->getWitnessTables().begin()}; +} + +OptionalBridgedWitnessTable +PassContext_nextWitnessTableInModule(BridgedWitnessTable table) { + auto *t = castToWitnessTable(table); + auto nextIter = std::next(t->getIterator()); + if (nextIter == t->getModule().getWitnessTables().end()) + return {nullptr}; + return {&*nextIter}; +} + +OptionalBridgedDefaultWitnessTable +PassContext_firstDefaultWitnessTableInModule(BridgedPassContext context) { + SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule(); + if (mod->getDefaultWitnessTables().empty()) + return {nullptr}; + return {&*mod->getDefaultWitnessTables().begin()}; +} + +OptionalBridgedDefaultWitnessTable +PassContext_nextDefaultWitnessTableInModule(BridgedDefaultWitnessTable table) { + auto *t = castToDefaultWitnessTable(table); + auto nextIter = std::next(t->getIterator()); + if (nextIter == t->getModule().getDefaultWitnessTables().end()) + return {nullptr}; + return {&*nextIter}; +} + OptionalBridgedFunction PassContext_loadFunction(BridgedPassContext context, StringRef name) { SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule(); From 90c83be7a67acf49bd2439bd2329c90e0086dfc8 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 16 Aug 2022 09:36:51 +0200 Subject: [PATCH 352/491] Swift Optimizer: make the `Stack` data structure also work with a `ModulePassContext` --- .../Sources/Optimizer/DataStructures/Stack.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/DataStructures/Stack.swift b/SwiftCompilerSources/Sources/Optimizer/DataStructures/Stack.swift index 1c436a361e21b..f8fe9ecfdf4fd 100644 --- a/SwiftCompilerSources/Sources/Optimizer/DataStructures/Stack.swift +++ b/SwiftCompilerSources/Sources/Optimizer/DataStructures/Stack.swift @@ -26,7 +26,7 @@ import SIL /// destruct this data structure, e.g. in a `defer {}` block. struct Stack : CollectionLikeSequence { - private let context: PassContext + private let bridgedContext: BridgedPassContext private var firstSlab = BridgedSlab(data: nil) private var lastSlab = BridgedSlab(data: nil) private var endIndex: Int = 0 @@ -61,7 +61,8 @@ struct Stack : CollectionLikeSequence { } } - init(_ context: PassContext) { self.context = context } + init(_ context: PassContext) { self.bridgedContext = context._bridged } + init(_ context: ModulePassContext) { self.bridgedContext = context._bridged } func makeIterator() -> Iterator { return Iterator(slab: firstSlab, index: 0, lastSlab: lastSlab, endIndex: endIndex) @@ -77,11 +78,11 @@ struct Stack : CollectionLikeSequence { mutating func push(_ element: Element) { if endIndex >= Stack.slabCapacity { - lastSlab = PassContext_allocSlab(context._bridged, lastSlab) + lastSlab = PassContext_allocSlab(bridgedContext, lastSlab) endIndex = 0 } else if firstSlab.data == nil { assert(endIndex == 0) - firstSlab = PassContext_allocSlab(context._bridged, lastSlab) + firstSlab = PassContext_allocSlab(bridgedContext, lastSlab) lastSlab = firstSlab } (Stack.bind(lastSlab) + endIndex).initialize(to: element) @@ -109,12 +110,12 @@ struct Stack : CollectionLikeSequence { if endIndex == 0 { if lastSlab.data == firstSlab.data { - _ = PassContext_freeSlab(context._bridged, lastSlab) + _ = PassContext_freeSlab(bridgedContext, lastSlab) firstSlab.data = nil lastSlab.data = nil endIndex = 0 } else { - lastSlab = PassContext_freeSlab(context._bridged, lastSlab) + lastSlab = PassContext_freeSlab(bridgedContext, lastSlab) endIndex = Stack.slabCapacity } } From bfb284f827f898b651e1aa98e63f09dbb8e0b1be Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 24 Aug 2022 11:47:52 +0200 Subject: [PATCH 353/491] Swift SIL: add a few instructions and `Instruction.visitReferencedFunctions` * add `DynamicFunctionRefInst` and `PreviousDynamicFunctionRefInst` * add a common base class to all function-referencing instructions: `FunctionRefBaseInst` * add `KeyPathInst` * add `IndexAddrInst.base` and `IndexAddrInst.index` getters * add `Instruction.visitReferencedFunctions` to visit all functions which are referenced by an instruction --- .../Sources/SIL/Instruction.swift | 44 +++++++++++++++++-- .../Sources/SIL/Registration.swift | 3 ++ include/swift/SIL/SILBridging.h | 10 ++++- include/swift/SIL/SILNodes.def | 6 +-- lib/SIL/Utils/SILBridging.cpp | 19 +++++++- 5 files changed, 73 insertions(+), 9 deletions(-) diff --git a/SwiftCompilerSources/Sources/SIL/Instruction.swift b/SwiftCompilerSources/Sources/SIL/Instruction.swift index 7b1b808151989..ce5426f2efaf1 100644 --- a/SwiftCompilerSources/Sources/SIL/Instruction.swift +++ b/SwiftCompilerSources/Sources/SIL/Instruction.swift @@ -104,6 +104,9 @@ public class Instruction : ListNode, CustomStringConvertible, Hashable { return SILInstruction_mayRelease(bridged) } + public func visitReferencedFunctions(_ cl: (Function) -> ()) { + } + public static func ==(lhs: Instruction, rhs: Instruction) -> Bool { lhs === rhs } @@ -344,7 +347,10 @@ final public class PointerToAddressInst : SingleValueInstruction, UnaryInstruction {} final public -class IndexAddrInst : SingleValueInstruction {} +class IndexAddrInst : SingleValueInstruction { + public var base: Value { operands[0].value } + public var index: Value { operands[1].value } +} final public class InitExistentialRefInst : SingleValueInstruction, UnaryInstruction {} @@ -388,12 +394,25 @@ public class GlobalAccessInst : SingleValueInstruction { } } -final public class FunctionRefInst : GlobalAccessInst { +public class FunctionRefBaseInst : SingleValueInstruction { public var referencedFunction: Function { - FunctionRefInst_getReferencedFunction(bridged).function + FunctionRefBaseInst_getReferencedFunction(bridged).function + } + + public override func visitReferencedFunctions(_ cl: (Function) -> ()) { + cl(referencedFunction) } } +final public class FunctionRefInst : FunctionRefBaseInst { +} + +final public class DynamicFunctionRefInst : FunctionRefBaseInst { +} + +final public class PreviousDynamicFunctionRefInst : FunctionRefBaseInst { +} + final public class GlobalAddrInst : GlobalAccessInst {} final public class GlobalValueInst : GlobalAccessInst {} @@ -458,6 +477,25 @@ final public class RefElementAddrInst : SingleValueInstruction, UnaryInstruction final public class RefTailAddrInst : SingleValueInstruction, UnaryInstruction {} +final public class KeyPathInst : SingleValueInstruction { + public override func visitReferencedFunctions(_ cl: (Function) -> ()) { + var results = KeyPathFunctionResults() + var componentIdx = 0 + repeat { + componentIdx = KeyPathInst_getReferencedFunctions(bridged, componentIdx, &results) + let numFuncs = results.numFunctions + withUnsafePointer(to: &results) { + $0.withMemoryRebound(to: BridgedFunction.self, capacity: numFuncs) { + let functions = UnsafeBufferPointer(start: $0, count: numFuncs) + for idx in 0..= 0 + } +} + final public class UnconditionalCheckedCastInst : SingleValueInstruction, UnaryInstruction { public override var mayTrap: Bool { true } diff --git a/SwiftCompilerSources/Sources/SIL/Registration.swift b/SwiftCompilerSources/Sources/SIL/Registration.swift index 1b1415fce1212..e739fb6f82dac 100644 --- a/SwiftCompilerSources/Sources/SIL/Registration.swift +++ b/SwiftCompilerSources/Sources/SIL/Registration.swift @@ -83,6 +83,8 @@ public func registerSILClasses() { register(ValueMetatypeInst.self) register(ExistentialMetatypeInst.self) register(FunctionRefInst.self) + register(DynamicFunctionRefInst.self) + register(PreviousDynamicFunctionRefInst.self) register(GlobalAddrInst.self) register(GlobalValueInst.self) register(IntegerLiteralInst.self) @@ -99,6 +101,7 @@ public func registerSILClasses() { register(UncheckedTakeEnumDataAddrInst.self) register(RefElementAddrInst.self) register(RefTailAddrInst.self) + register(KeyPathInst.self) register(UnconditionalCheckedCastInst.self) register(ConvertFunctionInst.self) register(ThinToThickFunctionInst.self) diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index 1496f269bf80c..4e03975c5ad2e 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -357,7 +357,7 @@ BridgedArrayRef TermInst_getSuccessors(BridgedInstruction term); llvm::StringRef CondFailInst_getMessage(BridgedInstruction cfi); BridgedBuiltinID BuiltinInst_getID(BridgedInstruction bi); BridgedGlobalVar GlobalAccessInst_getGlobal(BridgedInstruction globalInst); -BridgedFunction FunctionRefInst_getReferencedFunction(BridgedInstruction fri); +BridgedFunction FunctionRefBaseInst_getReferencedFunction(BridgedInstruction fri); llvm::StringRef StringLiteralInst_getValue(BridgedInstruction sli); SwiftInt TupleExtractInst_fieldIndex(BridgedInstruction tei); SwiftInt TupleElementAddrInst_fieldIndex(BridgedInstruction teai); @@ -391,6 +391,14 @@ void RefCountingInst_setIsAtomic(BridgedInstruction rc, bool isAtomic); bool RefCountingInst_getIsAtomic(BridgedInstruction rc); SwiftInt CondBranchInst_getNumTrueArgs(BridgedInstruction cbr); +struct KeyPathFunctionResults { + enum { maxFunctions = 5 }; + BridgedFunction functions[maxFunctions]; + SwiftInt numFunctions; +}; +SwiftInt KeyPathInst_getReferencedFunctions(BridgedInstruction kpi, SwiftInt componentIdx, + KeyPathFunctionResults * _Nonnull results); + BridgedSubstitutionMap ApplySite_getSubstitutionMap(BridgedInstruction inst); BridgedArgumentConvention ApplySite_getArgumentConvention(BridgedInstruction inst, SwiftInt calleeArgIdx); diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def index 53782e387185e..58065234591fe 100644 --- a/include/swift/SIL/SILNodes.def +++ b/include/swift/SIL/SILNodes.def @@ -341,9 +341,9 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction) ABSTRACT_SINGLE_VALUE_INST(LiteralInst, SingleValueInstruction) BRIDGED_SINGLE_VALUE_INST(FunctionRefInst, function_ref, LiteralInst, None, DoesNotRelease) - SINGLE_VALUE_INST(DynamicFunctionRefInst, dynamic_function_ref, + BRIDGED_SINGLE_VALUE_INST(DynamicFunctionRefInst, dynamic_function_ref, LiteralInst, None, DoesNotRelease) - SINGLE_VALUE_INST(PreviousDynamicFunctionRefInst, prev_dynamic_function_ref, + BRIDGED_SINGLE_VALUE_INST(PreviousDynamicFunctionRefInst, prev_dynamic_function_ref, LiteralInst, None, DoesNotRelease) BRIDGED_SINGLE_VALUE_INST(GlobalAddrInst, global_addr, LiteralInst, None, DoesNotRelease) @@ -644,7 +644,7 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction) // Key paths // TODO: The only "side effect" is potentially retaining the returned key path // object; is there a more specific effect? - SINGLE_VALUE_INST(KeyPathInst, keypath, + BRIDGED_SINGLE_VALUE_INST(KeyPathInst, keypath, SingleValueInstruction, MayHaveSideEffects, DoesNotRelease) // BindMemory and RebindMemory have no physical side effect. Semantically they diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index 10b1f5e16e01c..e0b72d0c14bb3 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -730,8 +730,8 @@ BridgedGlobalVar GlobalAccessInst_getGlobal(BridgedInstruction globalInst) { return {castToInst(globalInst)->getReferencedGlobal()}; } -BridgedFunction FunctionRefInst_getReferencedFunction(BridgedInstruction fri) { - return {castToInst(fri)->getReferencedFunction()}; +BridgedFunction FunctionRefBaseInst_getReferencedFunction(BridgedInstruction fri) { + return {castToInst(fri)->getInitiallyReferencedFunction()}; } llvm::StringRef StringLiteralInst_getValue(BridgedInstruction sli) { @@ -877,6 +877,21 @@ SwiftInt CondBranchInst_getNumTrueArgs(BridgedInstruction cbr) { return castToInst(cbr)->getNumTrueArgs(); } +SwiftInt KeyPathInst_getReferencedFunctions(BridgedInstruction kpi, SwiftInt componentIdx, + KeyPathFunctionResults * _Nonnull results) { + KeyPathPattern *pattern = castToInst(kpi)->getPattern(); + const KeyPathPatternComponent &comp = pattern->getComponents()[componentIdx]; + results->numFunctions = 0; + + comp.visitReferencedFunctionsAndMethods([results](SILFunction *func) { + assert(results->numFunctions < KeyPathFunctionResults::maxFunctions); + results->functions[results->numFunctions++] = {func}; + }, [](SILDeclRef) {}); + + ++componentIdx; + return componentIdx < (int)pattern->getComponents().size() ? componentIdx : -1; +} + BridgedSubstitutionMap ApplySite_getSubstitutionMap(BridgedInstruction inst) { auto as = ApplySite(castToInst(inst)); return {as.getSubstitutionMap().getOpaqueValue()}; From 0e59dde0fae8fbac5be77a14aef86ba09624252e Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 24 Aug 2022 11:48:24 +0200 Subject: [PATCH 354/491] Swift SIL: add the `TermInst.isFunctionExiting` property --- SwiftCompilerSources/Sources/SIL/Instruction.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SwiftCompilerSources/Sources/SIL/Instruction.swift b/SwiftCompilerSources/Sources/SIL/Instruction.swift index ce5426f2efaf1..b33ec1f2cdc63 100644 --- a/SwiftCompilerSources/Sources/SIL/Instruction.swift +++ b/SwiftCompilerSources/Sources/SIL/Instruction.swift @@ -689,21 +689,26 @@ public class TermInst : Instruction { final public var successors: SuccessorArray { SuccessorArray(succArray: TermInst_getSuccessors(bridged)) } + + public var isFunctionExiting: Bool { false } } final public class UnreachableInst : TermInst { } final public class ReturnInst : TermInst, UnaryInstruction { + public override var isFunctionExiting: Bool { true } } final public class ThrowInst : TermInst, UnaryInstruction { + public override var isFunctionExiting: Bool { true } } final public class YieldInst : TermInst { } final public class UnwindInst : TermInst { + public override var isFunctionExiting: Bool { true } } final public class TryApplyInst : TermInst, FullApplySite { From 2fe1ee5533c348e6b553ee120f85ae89481fa9d3 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 24 Aug 2022 11:49:54 +0200 Subject: [PATCH 355/491] Swift SIL: add a few `Builder` functions * add `createAllocStack` * add `createDeallocStack` * add `createCopyAddr` * add `@discardableResult` to the existing `createDeallocStackRef` --- .../FunctionPasses/StackPromotion.swift | 4 +-- .../Sources/SIL/Builder.swift | 26 +++++++++++++++++- include/swift/SIL/SILBridging.h | 8 ++++++ lib/SIL/Utils/SILBridging.cpp | 27 +++++++++++++++++++ 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift index e9fc445d001ff..8572f6861808a 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift @@ -175,13 +175,13 @@ func tryPromoteAlloc(_ allocRef: AllocRefInstBase, for exitInst in innerRange.exits { if !deadEndBlocks.isDeadEnd(exitInst.block) { let builder = Builder(at: exitInst, context) - _ = builder.createDeallocStackRef(allocRef) + builder.createDeallocStackRef(allocRef) } } for endInst in innerRange.ends { Builder.insert(after: endInst, location: allocRef.location, context) { - (builder) in _ = builder.createDeallocStackRef(allocRef) + (builder) in builder.createDeallocStackRef(allocRef) } } diff --git a/SwiftCompilerSources/Sources/SIL/Builder.swift b/SwiftCompilerSources/Sources/SIL/Builder.swift index e5e180e7aa7e1..d2087e919f48b 100644 --- a/SwiftCompilerSources/Sources/SIL/Builder.swift +++ b/SwiftCompilerSources/Sources/SIL/Builder.swift @@ -82,7 +82,23 @@ public struct Builder { let literal = SILBuilder_createIntegerLiteral(bridged, type.bridged, value) return literal.getAs(IntegerLiteralInst.self) } - + + public func createAllocStack(_ type: Type, hasDynamicLifetime: Bool = false, + isLexical: Bool = false, wasMoved: Bool = false) -> AllocStackInst { + notifyInstructionsChanged() + let dr = SILBuilder_createAllocStack(bridged, type.bridged, hasDynamicLifetime ? 1 : 0, + isLexical ? 1 : 0, wasMoved ? 1 : 0) + return dr.getAs(AllocStackInst.self) + } + + @discardableResult + public func createDeallocStack(_ operand: Value) -> DeallocStackInst { + notifyInstructionsChanged() + let dr = SILBuilder_createDeallocStack(bridged, operand.bridged) + return dr.getAs(DeallocStackInst.self) + } + + @discardableResult public func createDeallocStackRef(_ operand: Value) -> DeallocStackRefInst { notifyInstructionsChanged() let dr = SILBuilder_createDeallocStackRef(bridged, operand.bridged) @@ -113,6 +129,14 @@ public struct Builder { return SILBuilder_createCopyValue(bridged, operand.bridged).getAs(CopyValueInst.self) } + @discardableResult + public func createCopyAddr(from fromAddr: Value, to toAddr: Value, + takeSource: Bool = false, initializeDest: Bool = false) -> CopyAddrInst { + notifyInstructionsChanged() + return SILBuilder_createCopyAddr(bridged, fromAddr.bridged, toAddr.bridged, + takeSource ? 1 : 0, initializeDest ? 1 : 0).getAs(CopyAddrInst.self) + } + @discardableResult public func createDestroyValue(operand: Value) -> DestroyValueInst { notifyInstructionsChanged() diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index 4e03975c5ad2e..a24c6a2443ef8 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -412,6 +412,11 @@ BridgedInstruction SILBuilder_createCondFail(BridgedBuilder builder, BridgedValue condition, llvm::StringRef message); BridgedInstruction SILBuilder_createIntegerLiteral(BridgedBuilder builder, BridgedType type, SwiftInt value); +BridgedInstruction SILBuilder_createAllocStack(BridgedBuilder builder, + BridgedType type, SwiftInt hasDynamicLifetime, SwiftInt isLexical, + SwiftInt wasMoved); +BridgedInstruction SILBuilder_createDeallocStack(BridgedBuilder builder, + BridgedValue operand); BridgedInstruction SILBuilder_createDeallocStackRef(BridgedBuilder builder, BridgedValue operand); BridgedInstruction SILBuilder_createUncheckedRefCast(BridgedBuilder builder, @@ -422,6 +427,9 @@ BridgedInstruction SILBuilder_createFunctionRef(BridgedBuilder builder, BridgedFunction function); BridgedInstruction SILBuilder_createCopyValue(BridgedBuilder builder, BridgedValue op); +BridgedInstruction SILBuilder_createCopyAddr(BridgedBuilder builder, + BridgedValue from, BridgedValue to, + SwiftInt takeSource, SwiftInt initializeDest); BridgedInstruction SILBuilder_createDestroyValue(BridgedBuilder builder, BridgedValue op); BridgedInstruction SILBuilder_createApply(BridgedBuilder builder, diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index e0b72d0c14bb3..04c76f34c522b 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -960,6 +960,23 @@ BridgedInstruction SILBuilder_createIntegerLiteral(BridgedBuilder b, getSILType(type), value)}; } +BridgedInstruction SILBuilder_createAllocStack(BridgedBuilder b, + BridgedType type, SwiftInt hasDynamicLifetime, SwiftInt isLexical, + SwiftInt wasMoved) { + SILBuilder builder(castToInst(b.insertBefore), castToBasicBlock(b.insertAtEnd), + getSILDebugScope(b.loc)); + return {builder.createAllocStack(getRegularLocation(b.loc), getSILType(type), + None, hasDynamicLifetime != 0, isLexical != 0, wasMoved != 0)}; +} + +BridgedInstruction SILBuilder_createDeallocStack(BridgedBuilder b, + BridgedValue operand) { + SILBuilder builder(castToInst(b.insertBefore), castToBasicBlock(b.insertAtEnd), + getSILDebugScope(b.loc)); + return {builder.createDeallocStack(getRegularLocation(b.loc), + castToSILValue(operand))}; +} + BridgedInstruction SILBuilder_createDeallocStackRef(BridgedBuilder b, BridgedValue operand) { SILBuilder builder(castToInst(b.insertBefore), castToBasicBlock(b.insertAtEnd), @@ -1005,6 +1022,16 @@ BridgedInstruction SILBuilder_createCopyValue(BridgedBuilder b, castToSILValue(op))}; } +BridgedInstruction SILBuilder_createCopyAddr(BridgedBuilder b, + BridgedValue from, BridgedValue to, + SwiftInt takeSource, SwiftInt initializeDest) { + SILBuilder builder(castToInst(b.insertBefore), castToBasicBlock(b.insertAtEnd), + getSILDebugScope(b.loc)); + return {builder.createCopyAddr(getRegularLocation(b.loc), castToSILValue(from), + castToSILValue(to), IsTake_t(takeSource != 0), + IsInitialization_t(initializeDest != 0))}; +} + BridgedInstruction SILBuilder_createDestroyValue(BridgedBuilder b, BridgedValue op) { SILBuilder builder(castToInst(b.insertBefore), castToBasicBlock(b.insertAtEnd), From a12e33e9e99de4376031723acae8cc648c6d3407 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 24 Aug 2022 09:40:56 +0200 Subject: [PATCH 356/491] Swift Optimizer: add the `FunctionUses` utility Provides a list of instructions, which reference a function. A function "use" is an instruction in another (or the same) function which references the function. In most cases those are `function_ref` instructions, but can also be e.g. `keypath` instructions. 'FunctionUses' performs an analysis of all functions in the module and collects instructions which reference other functions. This utility can be used to do inter-procedural caller-analysis. --- .../Optimizer/DataStructures/CMakeLists.txt | 1 + .../DataStructures/FunctionUses.swift | 166 +++++++++++++++ .../PassManager/PassRegistration.swift | 1 + .../Optimizer/TestPasses/CMakeLists.txt | 1 + .../TestPasses/FunctionUsesDumper.swift | 28 +++ .../swift/SILOptimizer/PassManager/Passes.def | 2 + test/SILOptimizer/function_uses.sil | 194 ++++++++++++++++++ 7 files changed, 393 insertions(+) create mode 100644 SwiftCompilerSources/Sources/Optimizer/DataStructures/FunctionUses.swift create mode 100644 SwiftCompilerSources/Sources/Optimizer/TestPasses/FunctionUsesDumper.swift create mode 100644 test/SILOptimizer/function_uses.sil diff --git a/SwiftCompilerSources/Sources/Optimizer/DataStructures/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/DataStructures/CMakeLists.txt index 70c2c425c5d4c..0e63f95183dee 100644 --- a/SwiftCompilerSources/Sources/Optimizer/DataStructures/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/Optimizer/DataStructures/CMakeLists.txt @@ -9,6 +9,7 @@ swift_compiler_sources(Optimizer BasicBlockRange.swift BasicBlockWorklist.swift + FunctionUses.swift InstructionRange.swift Set.swift Stack.swift) diff --git a/SwiftCompilerSources/Sources/Optimizer/DataStructures/FunctionUses.swift b/SwiftCompilerSources/Sources/Optimizer/DataStructures/FunctionUses.swift new file mode 100644 index 0000000000000..c51b42cd042f0 --- /dev/null +++ b/SwiftCompilerSources/Sources/Optimizer/DataStructures/FunctionUses.swift @@ -0,0 +1,166 @@ +//===--- FunctionUses.swift -----------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 SIL + +/// Provides a list of instructions, which reference a function. +/// +/// A function "use" is an instruction in another (or the same) function which +/// references the function. In most cases those are `function_ref` instructions, +/// but can also be e.g. `keypath` instructions. +/// +/// 'FunctionUses' performs an analysis of all functions in the module and collects +/// instructions which reference other functions. This utility can be used to do +/// inter-procedural caller-analysis. +/// +/// In order to use `FunctionUses`, first call `collect()` and then get use-lists of +/// functions with `getUses(of:)`. +struct FunctionUses { + + // Function uses are stored in a single linked list, whereas the "next" is not a pointer + // but an index into `FunctionUses.useStorage`. + fileprivate struct Use { + // The index of the next use in `FunctionUses.useStorage`. + let next: Int? + + // The instruction which references the function. + let usingInstruction: Instruction + } + + // The head of the single-linked list of function uses. + fileprivate struct FirstUse { + // The head of the use-list. + var first: Int? + + // True if the function has unknown uses + var hasUnknownUses: Bool + + init(of function: Function) { + self.hasUnknownUses = function.isPossiblyUsedExternally || function.isAvailableExternally + } + + mutating func insert(_ inst: Instruction, _ uses: inout [Use]) { + let newFirst = uses.count + uses.append(Use(next: first, usingInstruction: inst)) + first = newFirst + } + } + + /// The list of uses of a function. + struct UseList : CollectionLikeSequence, CustomStringConvertible { + struct Iterator : IteratorProtocol { + fileprivate let useStorage: [Use] + fileprivate var currentUseIdx: Int? + + mutating func next() -> Instruction? { + if let useIdx = currentUseIdx { + let use = useStorage[useIdx] + currentUseIdx = use.next + return use.usingInstruction + } + return nil + } + } + + // The "storage" for all function uses. + fileprivate let useStorage: [Use] + + // The head of the single-linked use list. + fileprivate let firstUse: FirstUse + + /// True if the function has unknown uses in addition to the list of referencing instructions. + /// + /// This is the case, e.g. if the function has public linkage or if the function + /// is referenced from a vtable or witness table. + var hasUnknownUses: Bool { firstUse.hasUnknownUses } + + func makeIterator() -> Iterator { + return Iterator(useStorage: useStorage, currentUseIdx: firstUse.first) + } + + var description: String { + var result = "[\n" + if hasUnknownUses { + result += "\n" + } + for inst in self { + result += "@\(inst.function.name): \(inst)\n" + + } + result += "]" + return result + } + + var customMirror: Mirror { Mirror(self, children: []) } + } + + // The "storage" for all function uses. + private var useStorage: [Use] = [] + + // The use-list head for each function. + private var uses: [Function: FirstUse] = [:] + + init() { + // Already start with a reasonable big capacity to reduce the number of + // re-allocations when appending to the data structures. + useStorage.reserveCapacity(128) + uses.reserveCapacity(64) + } + + /// Returns the use-list of `function`. + /// + /// Note that `collect` must be called before `getUses` can be used. + func getUses(of function: Function) -> UseList { + UseList(useStorage: useStorage, firstUse: uses[function, default: FirstUse(of: function)]) + } + + /// Collects all uses of all function in the module. + mutating func collect(context: ModulePassContext) { + + // Mark all functions, which are referenced from tables, to have "unknown" uses. + + for vTable in context.vTables { + for entry in vTable.entries { + markUnknown(entry.function) + } + } + + for witnessTable in context.witnessTables { + for entry in witnessTable.entries { + if entry.kind == .method, let f = entry.methodFunction { + markUnknown(f) + } + } + } + + for witnessTable in context.defaultWitnessTables { + for entry in witnessTable.entries { + if entry.kind == .method, let f = entry.methodFunction { + markUnknown(f) + } + } + } + + // Collect all instructions, which reference functions, in the module. + for function in context.functions { + for inst in function.instructions { + inst.visitReferencedFunctions { referencedFunc in + uses[referencedFunc, default: FirstUse(of: referencedFunc)].insert(inst, &useStorage) + } + } + } + } + + private mutating func markUnknown(_ function: Function) { + uses[function, default: FirstUse(of: function)].hasUnknownUses = true + } +} diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift index 1a81f56043338..7c74a2e077517 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift @@ -61,6 +61,7 @@ private func registerSwiftPasses() { registerPass(simplifyStrongReleasePass, { simplifyStrongReleasePass.run($0) }) // Test passes + registerPass(functionUsesDumper, { functionUsesDumper.run($0) }) registerPass(silPrinterPass, { silPrinterPass.run($0) }) registerPass(escapeInfoDumper, { escapeInfoDumper.run($0) }) registerPass(addressEscapeInfoDumper, { addressEscapeInfoDumper.run($0) }) diff --git a/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt index 856ffe7e4454d..9ea5877525d7b 100644 --- a/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt @@ -7,6 +7,7 @@ # See http://swift.org/CONTRIBUTORS.txt for Swift project authors swift_compiler_sources(Optimizer + FunctionUsesDumper.swift AccessDumper.swift EscapeInfoDumper.swift SILPrinter.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/TestPasses/FunctionUsesDumper.swift b/SwiftCompilerSources/Sources/Optimizer/TestPasses/FunctionUsesDumper.swift new file mode 100644 index 0000000000000..316314af9defd --- /dev/null +++ b/SwiftCompilerSources/Sources/Optimizer/TestPasses/FunctionUsesDumper.swift @@ -0,0 +1,28 @@ +//===--- FunctionUsesDumper.swift -----------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 SIL + +let functionUsesDumper = ModulePass(name: "dump-function-uses", { + (context: ModulePassContext) in + + var functionUses = FunctionUses() + functionUses.collect(context: context) + + for function in context.functions { + let uses = functionUses.getUses(of: function) + + print("Uses of \(function.name)") + print(uses) + print("End function \(function.name)\n") + } +}) diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def index 2cb87b88abe34..39a85d45aab11 100644 --- a/include/swift/SILOptimizer/PassManager/Passes.def +++ b/include/swift/SILOptimizer/PassManager/Passes.def @@ -399,6 +399,8 @@ SWIFT_FUNCTION_PASS(RunUnitTests, "run-unit-tests", "Runs the compiler internal unit tests") SWIFT_FUNCTION_PASS(SILPrinter, "sil-printer", "Test pass which prints the SIL of a function") +SWIFT_MODULE_PASS(FunctionUsesDumper, "dump-function-uses", + "Dump the results of FunctionUses") PASS(SROA, "sroa", "Scalar Replacement of Aggregate Stack Objects") PASS(SROABBArgs, "sroa-bb-args", diff --git a/test/SILOptimizer/function_uses.sil b/test/SILOptimizer/function_uses.sil new file mode 100644 index 0000000000000..d176e59199ad5 --- /dev/null +++ b/test/SILOptimizer/function_uses.sil @@ -0,0 +1,194 @@ +// RUN: %target-sil-opt -wmo -dump-function-uses %s -o /dev/null | %FileCheck %s + +// REQUIRES: swift_in_compiler + +sil_stage canonical + +import Builtin +import Swift +import SwiftShims + +// CHECK-LABEL: Uses of public_func +// CHECK-NEXT: [ +// CHECK-NEXT: +// CHECK-NEXT: @other_public_func: +// CHECK-NEXT: %0 = function_ref @public_func +// CHECK-NEXT: @internal_func: +// CHECK-NEXT: %1 = function_ref @public_func +// CHECK-NEXT: @internal_func: +// CHECK-NEXT: %0 = function_ref @public_func +// CHECK-NEXT: ] +// CHECK-NEXT: End function public_func +sil @public_func : $@convention(thin) () -> () + +// CHECK-LABEL: Uses of internal_func +// CHECK-NEXT: [ +// CHECK-NEXT: @other_public_func: +// CHECK-NEXT: %1 = dynamic_function_ref @internal_func +// CHECK-NEXT: ] +// CHECK-NEXT: End function internal_func +sil hidden [dynamically_replacable] @internal_func : $@convention(thin) () -> () { +bb0: + %0 = function_ref @public_func : $@convention(thin) () -> () + %1 = function_ref @public_func : $@convention(thin) () -> () + %7 = tuple () + return %7 : $() +} + +// CHECK-LABEL: Uses of other_public_func +// CHECK-NEXT: [ +// CHECK-NEXT: +// CHECK-NEXT: ] +// CHECK-NEXT: End function other_public_func +sil @other_public_func : $@convention(thin) () -> () { +bb0: + %0 = function_ref @public_func : $@convention(thin) () -> () + %1 = dynamic_function_ref @internal_func : $@convention(thin) () -> () + %7 = tuple () + return %7 : $() +} + +struct S: Hashable { + var x: Int + let y: String + var z: C + + func hash(into hasher: inout Hasher) + static func ==(x: S, y: S) -> Bool +} + +class C: Hashable { + final var x: Int + final let y: String + final var z: S + + init() + var overridable: Int { + get set + } + + func hash(into hasher: inout Hasher) + static func ==(x: C, y: C) -> Bool +} + +// CHECK-LABEL: Uses of id_a +// CHECK-NEXT: [ +// CHECK-NEXT: @test_keypath: %2 = keypath {{.*}} +// CHECK-NEXT: ] +// CHECK-NEXT: End function id_a +sil hidden @id_a : $@convention(thin) () -> () { +bb0: + unreachable +} + +// CHECK-LABEL: Uses of get_s_int_subs +// CHECK-NEXT: [ +// CHECK-NEXT: @test_keypath: %2 = keypath {{.*}} +// CHECK-NEXT: ] +// CHECK-NEXT: End function get_s_int_subs +sil hidden @get_s_int_subs : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int { +bb0(%0 : $*Int, %1 : $*S, %2 : $UnsafeRawPointer): + unreachable +} + +// CHECK-LABEL: Uses of set_s_int_subs +// CHECK-NEXT: [ +// CHECK-NEXT: @test_keypath: %2 = keypath {{.*}} +// CHECK-NEXT: ] +// CHECK-NEXT: End function set_s_int_subs + +sil hidden @set_s_int_subs : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S, UnsafeRawPointer) -> () { +bb0(%0 : $*Int, %1 : $*S, %2 : $UnsafeRawPointer): + unreachable +} + +// CHECK-LABEL: Uses of subs_eq +// CHECK-NEXT: [ +// CHECK-NEXT: @test_keypath: %2 = keypath {{.*}} +// CHECK-NEXT: ] +// CHECK-NEXT: End function subs_eq +sil hidden @subs_eq : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool { +bb0(%0 : $UnsafeRawPointer, %1 : $UnsafeRawPointer): + unreachable +} + +// CHECK-LABEL: Uses of subs_hash +// CHECK-NEXT: [ +// CHECK-NEXT: @test_keypath: %2 = keypath {{.*}} +// CHECK-NEXT: ] +// CHECK-NEXT: End function subs_hash +sil hidden @subs_hash : $@convention(thin) (UnsafeRawPointer) -> Int { +bb0(%0 : $UnsafeRawPointer): + unreachable +} + +// CHECK-LABEL: Uses of test_keypath +// CHECK-NEXT: [ +// CHECK-NEXT: +// CHECK-NEXT: ] +// CHECK-NEXT: End function test_keypath +sil @test_keypath : $@convention(thin) (S, C) -> () { +bb0(%0 : $S, %1 : $C): + %2 = keypath $KeyPath, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int_subs : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int, setter @set_s_int_subs : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S, UnsafeRawPointer) -> (), indices [%$0 : $S : $S, %$1 : $C : $C], indices_equals @subs_eq : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @subs_hash : $@convention(thin) (UnsafeRawPointer) -> Int) (%0, %1) + %7 = tuple () + return %7 : $() +} + +public protocol RP { + func default_witness() +} + +// CHECK-LABEL: Uses of default_witness +// CHECK-NEXT: [ +// CHECK-NEXT: +// CHECK-NEXT: ] +// CHECK-NEXT: End function default_witness +sil hidden @default_witness : $@convention(witness_method: RP) (@in_guaranteed Self) -> () { +bb0(%0 : $*Self): + %7 = tuple () + return %7 : $() +} + +sil_default_witness_table RP { + method #RP.default_witness: @default_witness +} + +protocol P { + func witness() +} + +struct SP : P { + func witness() +} + +// CHECK-LABEL: Uses of witness +// CHECK-NEXT: [ +// CHECK-NEXT: +// CHECK-NEXT: ] +// CHECK-NEXT: End function witness +sil @witness : $@convention(witness_method: P) (@inout SP) -> () { +bb0(%0 : $*SP): + %7 = tuple () + return %7 : $() +} + +sil_witness_table SP: P module witness_tables { + method #P.witness: @witness +} + +// CHECK-LABEL: Uses of hash_func +// CHECK-NEXT: [ +// CHECK-NEXT: +// CHECK-NEXT: ] +// CHECK-NEXT: End function hash_func +sil hidden @hash_func : $@convention(method) (@inout Hasher, @guaranteed C) -> () { +bb0(%0 : $*Hasher, %1 : $C): + %4 = tuple () + return %4 : $() +} + +sil_vtable C { + #C.hash: (C) -> (inout Hasher) -> () : @hash_func +} + + From 1407846656969c237db66a1d61aa2882644cbec8 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 24 Aug 2022 18:18:09 +0200 Subject: [PATCH 357/491] docs: update `SIL-Utilities.md` And move it out of the "proposals" folder, directly into "docs". It's now more a documentation of what we have and useful as a programming guide. --- docs/{proposals => }/SIL-Utilities.md | 145 ++++++++++++++++---------- 1 file changed, 88 insertions(+), 57 deletions(-) rename docs/{proposals => }/SIL-Utilities.md (70%) diff --git a/docs/proposals/SIL-Utilities.md b/docs/SIL-Utilities.md similarity index 70% rename from docs/proposals/SIL-Utilities.md rename to docs/SIL-Utilities.md index a1bd23f89b7cb..e826f2c1ea123 100644 --- a/docs/proposals/SIL-Utilities.md +++ b/docs/SIL-Utilities.md @@ -1,30 +1,44 @@ # Utilities for SIL optimizer passes This document lists a set of SIL utilities to be used by the Swift implementation of the SIL optimizer. -The purpose of this proposal is to do a better planning of what utilities we need in SIL optimizer passes. +Some of the utilities presented in this document are still in the design phase and are not implemented yet (see **Status**). +### Goals for utilities We want to avoid a situation like we have in the C++ SIL optimizer, where a huge amount of (partly) redundant utilities exist. Many of those utilities have overlapping functionality, are difficult to discover and are poorly designed. We want to do better in the Swift SIL optimizer. ## Basic Data-Structures + #### `Stack` An allocation-free, array like data structure. To be used instead of `Swift.Array` wherever random-access is not needed. **Related C++ utilities:** `llvm::SmallVector`, `Stack` -**Status:** done +**Status:** done #### `BasicBlockSet` An extremely efficient implementation of a set of basic blocks. **Related C++ utilities:** `BasicBlockSet` -**Status:** done +**Status:** done + +#### `ValueSet` +An extremely efficient implementation of a set of values. + +**Related C++ utilities:** `ValueSet` +**Status:** done + +#### `InstructionSet` +An extremely efficient implementation of a set of instructions. + +**Related C++ utilities:** `InstructionSet ` +**Status:** done #### `BasicBlockWorklist` To be used for all kind of basic-block work-list algorithms. **Uses:** `Stack`, `BasicBlockSet` **Related C++ utilities:** `BasicBlockWorklist` -**Status:** done +**Status:** done ## Building SIL @@ -32,7 +46,76 @@ To be used for all kind of basic-block work-list algorithms. Useful to insert instructions after a (potential) terminator instruction. **Related C++ utilities:** `SILBuilderWithScope::insertAfter()` -**Status:** done +**Status:** done + +## SSA Traversal Utilities + +#### Walk Utils +This consists of four protocols, which can be implemented to walk up or down the SSA graph: +* `ValueDefUseWalker` +* `AddressDefUseWalker` +* `ValueUseDefWalker` +* `AddressUseDefWalker` + +**Uses:** instruction classifications +**Related C++ utilities:** `AccessPath`, `RCIdentityAnalysis`, various def-use/use-def walkers in optimization passes. +**Status:** done + +#### `SmallProjectionPath` +Describes a path of projections. + +**Related C++ utilities:** `AccessPath`, `ProjectionPath` +**Status:** done + +#### `EscapeInfo` +Escape analysis, which is used e.g. in stack promotion or alias analysis. + +**Uses:** Walk Utils, `SmallProjectionPath` +**Related C++ utilities:** `EscapeAnalysis`, various def-use walkers in optimization passes. +**Status:** done + +#### Access Utils +A set of utilities for analyzing memory accesses. It defines the following concepts: +* `AccessBase`: represents the base address of a memory access. +* `AccessPath`: a pair of an `AccessBase` and `SmallProjectionPath` with the path describing the specific address (in terms of projections) of the access. +* `AccessStoragePath`: identifies the reference (or a value which contains a reference) an address originates from. + +**Uses:** Walk utils +**Related C++ utilities:** `AccessPath` and other access utilities. +**Status:** done + +## Control- and Dataflow + +#### `BasicBlockRange` +Defines a range from a dominating "begin" block to one or more "end" blocks. To be used for all kind of backward block reachability analysis. + +**Uses:** `Stack`, `BasicBlockSet`, `BasicBlockWorklist` +**Related C++ utilities:** `PrunedLiveBlocks`, `findJointPostDominatingSet()` +**Status:** done + +#### `InstructionRange` +Like `BasicBlockRange`, but at the granularity of instructions. + +**Uses:** `BasicBlockRange` +**Related C++ utilities:** `PrunedLiveness`, `ValueLifetimeAnalysis` +**Status:** done + +## Utilities for Inter-procedural Analysis + +### `FunctionUses` +Provides a list of instructions, which reference a function. This utility performs an analysis of all functions in the module and collects instructions which reference other functions. It can be used to do inter-procedural caller-analysis. + +**Related C++ utilities:** `CallerAnalysis` +**Status:** done + +## OSSA Utilities + +#### `Value.makeAvailable()` and `Value.copy(at:)` +To be used where a value is copied in one block and used in another block. + +**Uses:** `BasicBlockRange` +**Related C++ utilities:** `makeValueAvailable()`, `OwnershipLifetimeExtender` +**Status:** done ## Instruction classifications We want to classify certain instructions into common groups so that passes can deal deal with the group instead of individual instruction opcodes. Optimization passes then don't need to be updated if new instructions are added to a group. @@ -78,55 +161,3 @@ Maybe it's better to not do this as a protocol but just add an extension functio **Conforming instructions:** `BeginBorrowInst`, `Argument` with guaranteed ownership (however will do that), `LoadBorrowInst` **Status:** to-do -## SSA Traversal Utilities - -#### Basic Walkers -This is currently in progress. We'll probably have an up-walkers and down-walkers for both, addresses and non-address values. - -**Uses:** instruction classifications -**Related C++ utilities:** `AccessPath`, `RCIdentityAnalysis`, various def-use/use-def walkers in optimization passes. -**Status:** in progress - -#### `SmallProjectionPath` -Describes a path of projections. - -**Related C++ utilities:** `AccessPath`, `ProjectionPath` -**Status:** done - -#### `EscapeInfo` -Escape analysis, which is used e.g. in stack promotion or alias analysis. - -**Uses:** basic walkers, `SmallProjectionPath` -**Related C++ utilities:** `EscapeAnalysis`, various def-use walkers in optimization passes. -**Status:** done, but factoring out the walkers is in progress - -#### `AccessPath` -Details need to be decided. - -**Uses:** basic walkers -**Related C++ utilities:** `AccessPath` -**Status:** to-do - -## Control- and Dataflow - -#### `BasicBlockRange` -Defines a range from a dominating "begin" block to one or more "end" blocks. To be used for all kind of backward block reachability analysis. - -**Uses:** `Stack`, `BasicBlockSet`, `BasicBlockWorklist` -**Related C++ utilities:** `PrunedLiveBlocks`, `findJointPostDominatingSet()` -**Status:** done - -#### `InstructionRange` -Like `BasicBlockRange`, but at the granularity of instructions. - -**Uses:** `BasicBlockRange` -**Related C++ utilities:** `PrunedLiveness`, `ValueLifetimeAnalysis` -**Status:** done - -## OSSA Utilities -#### `Value.makeAvailable()` and `Value.copy(at:)` -To be used where a value is copied in one block and used in another block. - -**Uses:** `BasicBlockRange` -**Related C++ utilities:** `makeValueAvailable()`, `OwnershipLifetimeExtender` -**Status:** done From 8de79390be0be8d5b52c53d380157867623a00ca Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 22 Aug 2022 16:09:29 -0700 Subject: [PATCH 358/491] [interop][SwiftToCxx] add @_expose(Cxx) attribute support This attribute instructs the compiler that this declaration should be included in the generated C++ bindings --- docs/ReferenceGuides/UnderscoredAttributes.md | 16 ++++ include/swift/AST/Attr.def | 6 ++ include/swift/AST/Attr.h | 17 ++++ include/swift/AST/DiagnosticsSema.def | 5 ++ include/swift/AST/SwiftNameTranslation.h | 6 ++ lib/AST/Attr.cpp | 10 +++ lib/AST/SwiftNameTranslation.cpp | 14 +++ lib/Parse/ParseDecl.cpp | 40 +++++++-- lib/PrintAsClang/ClangSyntaxPrinter.cpp | 3 +- lib/PrintAsClang/DeclAndTypePrinter.cpp | 12 ++- lib/PrintAsClang/DeclAndTypePrinter.h | 8 +- lib/PrintAsClang/ModuleContentsWriter.cpp | 13 +-- lib/PrintAsClang/ModuleContentsWriter.h | 4 +- lib/PrintAsClang/PrintAsClang.cpp | 13 ++- lib/PrintAsClang/PrintClangFunction.cpp | 8 +- lib/Sema/TypeCheckAttr.cpp | 24 ++++++ lib/Sema/TypeCheckDeclOverride.cpp | 1 + lib/Serialization/Deserialization.cpp | 8 ++ lib/Serialization/ModuleFormat.h | 7 +- lib/Serialization/Serialization.cpp | 8 ++ .../expose-swift-decls-to-cxx.swift | 86 +++++++++++++++++++ test/attr/attr_expose.swift | 26 ++++++ 22 files changed, 307 insertions(+), 28 deletions(-) create mode 100644 test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift create mode 100644 test/attr/attr_expose.swift diff --git a/docs/ReferenceGuides/UnderscoredAttributes.md b/docs/ReferenceGuides/UnderscoredAttributes.md index 8146f5d491878..6bac35ce8f2b2 100644 --- a/docs/ReferenceGuides/UnderscoredAttributes.md +++ b/docs/ReferenceGuides/UnderscoredAttributes.md @@ -358,6 +358,22 @@ func g() { } ``` +## `@_expose()` + +Indicates that a particular declaration should be included +in the emitted specified foreign language binding. + +When applied to a nominal type declaration, all of the +public declarations inside this type become exposed as well. + +### `_expose(Cxx[, <"cxxName">])` + +Indicates that a particular declaration should be included +in the generated C++ binding header. + +The optional "cxxName" string will be used as the name of +the generated C++ declaration. + ## `@_fixed_layout` Same as `@frozen` but also works for classes. diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def index 1c0f34e329221..1df82de37cac8 100644 --- a/include/swift/AST/Attr.def +++ b/include/swift/AST/Attr.def @@ -757,6 +757,12 @@ SIMPLE_DECL_ATTR(_alwaysEmitConformanceMetadata, AlwaysEmitConformanceMetadata, OnProtocol | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, 132) +DECL_ATTR(_expose, Expose, + OnFunc | OnNominalType | OnVar | + LongAttribute | UserInaccessible | + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + 133) + // If you're adding a new underscored attribute here, please document it in // docs/ReferenceGuides/UnderscoredAttributes.md. diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 44d74bdb6569e..d299e93cc0336 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -2226,6 +2226,23 @@ class BackDeployAttr: public DeclAttribute { } }; +/// Defines the `@_expose` attribute, used to expose declarations in the +/// header used by C/C++ to interoperate with Swift. +class ExposeAttr : public DeclAttribute { +public: + ExposeAttr(StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit) + : DeclAttribute(DAK_Expose, AtLoc, Range, Implicit), Name(Name) {} + + ExposeAttr(StringRef Name, bool Implicit) + : ExposeAttr(Name, SourceLoc(), SourceRange(), Implicit) {} + + /// The exposed declaration name. + const StringRef Name; + + static bool classof(const DeclAttribute *DA) { + return DA->getKind() == DAK_Expose; + } +}; /// Attributes that may be applied to declarations. class DeclAttributes { diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 8c17d0bc6b72f..df75bf4a2e063 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1481,6 +1481,11 @@ ERROR(cdecl_empty_name,none, ERROR(cdecl_throws,none, "raising errors from @_cdecl functions is not supported", ()) +ERROR(expose_only_non_other_attr,none, + "@_expose attribute cannot be applied to an '%0' declaration", (StringRef)) +ERROR(expose_inside_unexposed_decl,none, + "@_expose attribute cannot be applied inside of unexposed declaration %0", (DeclName)) + ERROR(attr_methods_only,none, "only methods can be declared %0", (DeclAttribute)) ERROR(attr_decl_async,none, diff --git a/include/swift/AST/SwiftNameTranslation.h b/include/swift/AST/SwiftNameTranslation.h index 8e63b9bd14431..9803eefbf85a2 100644 --- a/include/swift/AST/SwiftNameTranslation.h +++ b/include/swift/AST/SwiftNameTranslation.h @@ -57,6 +57,12 @@ namespace objc_translation { namespace cxx_translation { +using objc_translation::CustomNamesOnly_t; + +StringRef +getNameForCxx(const ValueDecl *VD, + CustomNamesOnly_t customNamesOnly = objc_translation::Normal); + /// Returns true if the given value decl D is visible to C++ of its /// own accord (i.e. without considering its context) bool isVisibleToCxx(const ValueDecl *VD, AccessLevel minRequiredAccess, diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 043789fc86cf1..77e3844018320 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -1046,6 +1046,14 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, Printer << "@_cdecl(\"" << cast(this)->Name << "\")"; break; + case DAK_Expose: + Printer.printAttrName("@_expose"); + Printer << "(Cxx"; + if (!cast(this)->Name.empty()) + Printer << ", \"" << cast(this)->Name << "\""; + Printer << ")"; + break; + case DAK_ObjC: { Printer.printAttrName("@objc"); llvm::SmallString<32> scratch; @@ -1440,6 +1448,8 @@ StringRef DeclAttribute::getAttrName() const { return "_unavailableFromAsync"; case DAK_BackDeploy: return "_backDeploy"; + case DAK_Expose: + return "_expose"; } llvm_unreachable("bad DeclAttrKind"); } diff --git a/lib/AST/SwiftNameTranslation.cpp b/lib/AST/SwiftNameTranslation.cpp index 0ef7c77cbc132..a7ecd825a6950 100644 --- a/lib/AST/SwiftNameTranslation.cpp +++ b/lib/AST/SwiftNameTranslation.cpp @@ -151,6 +151,20 @@ isVisibleToObjC(const ValueDecl *VD, AccessLevel minRequiredAccess, return false; } +StringRef +swift::cxx_translation::getNameForCxx(const ValueDecl *VD, + CustomNamesOnly_t customNamesOnly) { + if (const auto *Expose = VD->getAttrs().getAttribute()) { + if (!Expose->Name.empty()) + return Expose->Name; + } + + if (customNamesOnly) + return StringRef(); + + return VD->getBaseIdentifier().str(); +} + bool swift::cxx_translation::isVisibleToCxx(const ValueDecl *VD, AccessLevel minRequiredAccess, bool checkParent) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 913b99ea6f84e..7600e9718702c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2376,6 +2376,7 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc, } case DAK_CDecl: + case DAK_Expose: case DAK_SILGenName: { if (!consumeIf(tok::l_paren)) { diagnose(Loc, diag::attr_expected_lparen, AttrName, @@ -2383,20 +2384,37 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc, return false; } - if (Tok.isNot(tok::string_literal)) { - diagnose(Loc, diag::attr_expected_string_literal, AttrName); - return false; + bool ParseSymbolName = true; + if (DK == DAK_Expose) { + if (Tok.isNot(tok::identifier) || Tok.getText() != "Cxx") { + diagnose(Tok.getLoc(), diag::attr_expected_option_such_as, AttrName, + "Cxx"); + if (Tok.isNot(tok::identifier)) + return false; + DiscardAttribute = true; + } + consumeToken(tok::identifier); + ParseSymbolName = consumeIf(tok::comma); } - Optional AsmName = getStringLiteralIfNotInterpolated( - Loc, ("'" + AttrName + "'").str()); + Optional AsmName; + if (ParseSymbolName) { + if (Tok.isNot(tok::string_literal)) { + diagnose(Loc, diag::attr_expected_string_literal, AttrName); + return false; + } - consumeToken(tok::string_literal); + AsmName = + getStringLiteralIfNotInterpolated(Loc, ("'" + AttrName + "'").str()); - if (AsmName.hasValue()) + consumeToken(tok::string_literal); + + if (AsmName.hasValue()) + AttrRange = SourceRange(Loc, Tok.getRange().getStart()); + else + DiscardAttribute = true; + } else AttrRange = SourceRange(Loc, Tok.getRange().getStart()); - else - DiscardAttribute = true; if (!consumeIf(tok::r_paren)) { diagnose(Loc, diag::attr_expected_rparen, AttrName, @@ -2419,6 +2437,10 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc, else if (DK == DAK_CDecl) Attributes.add(new (Context) CDeclAttr(AsmName.getValue(), AtLoc, AttrRange, /*Implicit=*/false)); + else if (DK == DAK_Expose) + Attributes.add(new (Context) ExposeAttr( + AsmName ? AsmName.getValue() : StringRef(""), AtLoc, AttrRange, + /*Implicit=*/false)); else llvm_unreachable("out of sync with switch"); } diff --git a/lib/PrintAsClang/ClangSyntaxPrinter.cpp b/lib/PrintAsClang/ClangSyntaxPrinter.cpp index bb2b75a9e6c77..37b0f01f375ac 100644 --- a/lib/PrintAsClang/ClangSyntaxPrinter.cpp +++ b/lib/PrintAsClang/ClangSyntaxPrinter.cpp @@ -14,6 +14,7 @@ #include "swift/ABI/MetadataValues.h" #include "swift/AST/Decl.h" #include "swift/AST/Module.h" +#include "swift/AST/SwiftNameTranslation.h" using namespace swift; using namespace cxx_synthesis; @@ -52,7 +53,7 @@ void ClangSyntaxPrinter::printIdentifier(StringRef name) { void ClangSyntaxPrinter::printBaseName(const ValueDecl *decl) { assert(decl->getName().isSimpleName()); - printIdentifier(decl->getBaseIdentifier().str()); + printIdentifier(cxx_translation::getNameForCxx(decl)); } void ClangSyntaxPrinter::printModuleNameCPrefix(const ModuleDecl &mod) { diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index bd762641e9207..8b05f4d2a86f8 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -1203,7 +1203,7 @@ class DeclAndTypePrinter::Implementation DeclAndTypeClangFunctionPrinter::FunctionSignatureModifiers modifiers; modifiers.isInline = true; funcPrinter.printFunctionSignature( - FD, FD->getName().getBaseIdentifier().get(), resultTy, + FD, cxx_translation::getNameForCxx(FD), resultTy, DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CxxInlineThunk, {}, modifiers); // FIXME: Support throwing exceptions for Swift errors. @@ -2393,8 +2393,16 @@ static bool isAsyncAlternativeOfOtherDecl(const ValueDecl *VD) { return false; } +static bool hasExposeAttr(const ValueDecl *VD) { + if (VD->getAttrs().hasAttribute()) + return true; + if (const auto *NMT = dyn_cast(VD->getDeclContext())) + return hasExposeAttr(NMT); + return false; +} + bool DeclAndTypePrinter::shouldInclude(const ValueDecl *VD) { - return !VD->isInvalid() && + return !VD->isInvalid() && (!requiresExposedAttribute || hasExposeAttr(VD)) && (outputLang == OutputLanguageMode::Cxx ? cxx_translation::isVisibleToCxx(VD, minRequiredAccess) : isVisibleToObjC(VD, minRequiredAccess)) && diff --git a/lib/PrintAsClang/DeclAndTypePrinter.h b/lib/PrintAsClang/DeclAndTypePrinter.h index cf99c981622b0..8c4c89a68455d 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.h +++ b/lib/PrintAsClang/DeclAndTypePrinter.h @@ -47,6 +47,7 @@ class DeclAndTypePrinter { PrimitiveTypeMapping &typeMapping; SwiftToClangInteropContext &interopContext; AccessLevel minRequiredAccess; + bool requiresExposedAttribute; OutputLanguageMode outputLang; /// The name 'CFTypeRef'. @@ -62,11 +63,14 @@ class DeclAndTypePrinter { DelayedMemberSet &delayed, PrimitiveTypeMapping &typeMapping, SwiftToClangInteropContext &interopContext, - AccessLevel access, OutputLanguageMode outputLang) + AccessLevel access, bool requiresExposedAttribute, + OutputLanguageMode outputLang) : M(mod), os(out), prologueOS(prologueOS), outOfLineDefinitionsOS(outOfLineDefinitionsOS), delayedMembers(delayed), typeMapping(typeMapping), interopContext(interopContext), - minRequiredAccess(access), outputLang(outputLang) {} + minRequiredAccess(access), + requiresExposedAttribute(requiresExposedAttribute), + outputLang(outputLang) {} /// Returns true if \p VD should be included in a compatibility header for /// the options the printer was constructed with. diff --git a/lib/PrintAsClang/ModuleContentsWriter.cpp b/lib/PrintAsClang/ModuleContentsWriter.cpp index 1ef36275073b7..8a9dd1e5b5a5b 100644 --- a/lib/PrintAsClang/ModuleContentsWriter.cpp +++ b/lib/PrintAsClang/ModuleContentsWriter.cpp @@ -136,11 +136,12 @@ class ModuleWriter { ModuleWriter(raw_ostream &os, raw_ostream &prologueOS, llvm::SmallPtrSetImpl &imports, ModuleDecl &mod, SwiftToClangInteropContext &interopContext, AccessLevel access, - OutputLanguageMode outputLang) + bool requiresExposedAttribute, OutputLanguageMode outputLang) : os(os), imports(imports), M(mod), outOfLineDefinitionsOS(outOfLineDefinitions), printer(M, os, prologueOS, outOfLineDefinitionsOS, delayedMembers, - typeMapping, interopContext, access, outputLang), + typeMapping, interopContext, access, requiresExposedAttribute, + outputLang), outputLangMode(outputLang) {} PrimitiveTypeMapping &getTypeMapping() { return typeMapping; } @@ -672,13 +673,14 @@ void swift::printModuleContentsAsObjC( ModuleDecl &M, SwiftToClangInteropContext &interopContext) { llvm::raw_null_ostream prologueOS; ModuleWriter(os, prologueOS, imports, M, interopContext, getRequiredAccess(M), - OutputLanguageMode::ObjC) + /*requiresExposedAttribute=*/false, OutputLanguageMode::ObjC) .write(); } void swift::printModuleContentsAsCxx( raw_ostream &os, llvm::SmallPtrSetImpl &imports, - ModuleDecl &M, SwiftToClangInteropContext &interopContext) { + ModuleDecl &M, SwiftToClangInteropContext &interopContext, + bool requiresExposedAttribute) { std::string moduleContentsBuf; llvm::raw_string_ostream moduleOS{moduleContentsBuf}; std::string modulePrologueBuf; @@ -686,7 +688,8 @@ void swift::printModuleContentsAsCxx( // FIXME: Use getRequiredAccess once @expose is supported. ModuleWriter writer(moduleOS, prologueOS, imports, M, interopContext, - AccessLevel::Public, OutputLanguageMode::Cxx); + AccessLevel::Public, requiresExposedAttribute, + OutputLanguageMode::Cxx); writer.write(); os << "#ifndef SWIFT_PRINTED_CORE\n"; diff --git a/lib/PrintAsClang/ModuleContentsWriter.h b/lib/PrintAsClang/ModuleContentsWriter.h index 3bbd19b430301..aa7fe97823b4f 100644 --- a/lib/PrintAsClang/ModuleContentsWriter.h +++ b/lib/PrintAsClang/ModuleContentsWriter.h @@ -23,6 +23,7 @@ namespace clang { } namespace swift { +class Decl; class ModuleDecl; class SwiftToClangInteropContext; @@ -40,7 +41,8 @@ void printModuleContentsAsObjC(raw_ostream &os, void printModuleContentsAsCxx(raw_ostream &os, llvm::SmallPtrSetImpl &imports, ModuleDecl &M, - SwiftToClangInteropContext &interopContext); + SwiftToClangInteropContext &interopContext, + bool requiresExposedAttribute); } // end namespace swift diff --git a/lib/PrintAsClang/PrintAsClang.cpp b/lib/PrintAsClang/PrintAsClang.cpp index bef167d3b38f3..67cc2dc1f585d 100644 --- a/lib/PrintAsClang/PrintAsClang.cpp +++ b/lib/PrintAsClang/PrintAsClang.cpp @@ -491,11 +491,13 @@ static std::string computeMacroGuard(const ModuleDecl *M) { static std::string getModuleContentsCxxString(ModuleDecl &M, - SwiftToClangInteropContext &interopContext) { + SwiftToClangInteropContext &interopContext, + bool requiresExposedAttribute) { SmallPtrSet imports; std::string moduleContentsBuf; llvm::raw_string_ostream moduleContents{moduleContentsBuf}; - printModuleContentsAsCxx(moduleContents, imports, M, interopContext); + printModuleContentsAsCxx(moduleContents, imports, M, interopContext, + requiresExposedAttribute); return moduleContents.str(); } @@ -518,8 +520,11 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M, emitObjCConditional(os, [&] { os << objcModuleContents.str(); }); emitCxxConditional(os, [&] { // FIXME: Expose Swift with @expose by default. - if (ExposePublicDeclsInClangHeader) { - os << getModuleContentsCxxString(*M, interopContext); + if (ExposePublicDeclsInClangHeader || + M->DeclContext::getASTContext().LangOpts.EnableCXXInterop) { + os << getModuleContentsCxxString( + *M, interopContext, + /*requiresExposedAttribute=*/!ExposePublicDeclsInClangHeader); } }); writeEpilogue(os); diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index e7e1a00d49597..cb587d0d77632 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -21,6 +21,7 @@ #include "swift/AST/Decl.h" #include "swift/AST/GenericParamList.h" #include "swift/AST/ParameterList.h" +#include "swift/AST/SwiftNameTranslation.h" #include "swift/AST/Type.h" #include "swift/AST/TypeVisitor.h" #include "swift/ClangImporter/ClangImporter.h" @@ -701,8 +702,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod( modifiers.isConst = !isa(typeDeclContext) && !isMutating && !isConstructor; printFunctionSignature( - FD, isConstructor ? "init" : FD->getName().getBaseIdentifier().get(), - resultTy, FunctionSignatureKind::CxxInlineThunk, {}, modifiers); + FD, isConstructor ? "init" : cxx_translation::getNameForCxx(FD), resultTy, + FunctionSignatureKind::CxxInlineThunk, {}, modifiers); if (!isDefinition) { os << ";\n"; return; @@ -734,7 +735,8 @@ static bool canRemapBoolPropertyNameDirectly(StringRef name) { static std::string remapPropertyName(const AccessorDecl *accessor, Type resultTy) { // For a getter or setter, go through the variable or subscript decl. - StringRef propertyName = accessor->getStorage()->getBaseIdentifier().str(); + StringRef propertyName = + cxx_translation::getNameForCxx(accessor->getStorage()); // Boolean property getters can be remapped directly in certain cases. if (accessor->isGetter() && resultTy->isBool() && diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 099c545b0d047..febce6745b5ad 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -245,6 +245,7 @@ class AttributeChecker : public AttributeVisitor { void visitAvailableAttr(AvailableAttr *attr); void visitCDeclAttr(CDeclAttr *attr); + void visitExposeAttr(ExposeAttr *attr); void visitDynamicCallableAttr(DynamicCallableAttr *attr); @@ -1843,6 +1844,29 @@ void AttributeChecker::visitCDeclAttr(CDeclAttr *attr) { diagnose(attr->getLocation(), diag::cdecl_empty_name); } +void AttributeChecker::visitExposeAttr(ExposeAttr *attr) { + const auto *VD = cast(D); + // Expose cannot be mixed with '@objc'/'@_cdecl' declarations. + if (VD->isObjC()) + diagnose(attr->getLocation(), diag::expose_only_non_other_attr, "@objc"); + if (VD->getAttrs().hasAttribute()) + diagnose(attr->getLocation(), diag::expose_only_non_other_attr, "@_cdecl"); + + // Nested exposed declarations are expected to be inside + // of other exposed declarations. + bool hasExpose = true; + const ValueDecl *decl = VD; + while (const NominalTypeDecl *NMT = + dyn_cast(decl->getDeclContext())) { + decl = NMT; + hasExpose = NMT->getAttrs().hasAttribute(); + } + if (!hasExpose) { + diagnose(attr->getLocation(), diag::expose_inside_unexposed_decl, + decl->getName()); + } +} + void AttributeChecker::visitUnsafeNoObjCTaggedPointerAttr( UnsafeNoObjCTaggedPointerAttr *attr) { // Only class protocols can have the attribute. diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 8a9f2c0976050..4297fcf41c021 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1513,6 +1513,7 @@ namespace { UNINTERESTING_ATTR(NoAllocation) UNINTERESTING_ATTR(Inlinable) UNINTERESTING_ATTR(Effects) + UNINTERESTING_ATTR(Expose) UNINTERESTING_ATTR(Final) UNINTERESTING_ATTR(MoveOnly) UNINTERESTING_ATTR(FixedLayout) diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 3e3fcb77aa00a..06bf366690eea 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -5050,6 +5050,14 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() { break; } + case decls_block::Expose_DECL_ATTR: { + bool isImplicit; + serialization::decls_block::ExposeDeclAttrLayout::readRecord( + scratch, isImplicit); + Attr = new (ctx) ExposeAttr(blobData, isImplicit); + break; + } + #define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \ case decls_block::CLASS##_DECL_ATTR: { \ bool isImplicit; \ diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index d5f9e212923af..2cdcdff28a282 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 705; // same-length requirements +const uint16_t SWIFTMODULE_VERSION_MINOR = 706; // @_expose attribute /// A standard hash seed used for all string hashes in a serialized module. /// @@ -2105,6 +2105,11 @@ namespace decls_block { BCVBR<5> // platform >; + using ExposeDeclAttrLayout = BCRecordLayout, // implicit flag + BCBlob // declaration name + >; + #undef SYNTAX_SUGAR_TYPE_LAYOUT #undef TYPE_LAYOUT #undef TYPE_LAYOUT_IMPL diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 0904c6e7cdd8c..fc348cdd76550 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -2863,6 +2863,14 @@ class Serializer::DeclSerializer : public DeclVisitor { theAttr->Message); return; } + + case DAK_Expose: { + auto *theAttr = cast(DA); + auto abbrCode = S.DeclTypeAbbrCodes[ExposeDeclAttrLayout::Code]; + ExposeDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, + theAttr->isImplicit(), theAttr->Name); + return; + } } } diff --git a/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift b/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift new file mode 100644 index 0000000000000..0e1b2263d5d8f --- /dev/null +++ b/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift @@ -0,0 +1,86 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -typecheck -module-name Expose -enable-experimental-cxx-interop -emit-clang-header-path %t/expose.h +// RUN: %FileCheck %s < %t/expose.h + +// RUN: %check-interop-cxx-header-in-clang(%t/expose.h -Wno-error=unused-function) + +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -emit-module -module-name Expose -o %t +// RUN: %target-swift-frontend -parse-as-library %t/Expose.swiftmodule -typecheck -module-name Expose -enable-experimental-cxx-interop -emit-clang-header-path %t/expose.h +// RUN: %FileCheck %s < %t/expose.h + +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -enable-library-evolution -typecheck -emit-module-interface-path %t/Expose.swiftinterface -module-name Expose +// RUN: %target-swift-frontend -parse-as-library %t/Expose.swiftinterface -enable-library-evolution -disable-objc-attr-requires-foundation-module -typecheck -module-name Expose -enable-experimental-cxx-interop -emit-clang-header-path %t/expose.h +// RUN: %FileCheck %s < %t/expose.h + +@_expose(Cxx) +public func exposed1() { +} + +public func exposed2NotExposed() { +} + +@_expose(Cxx) +public func exposed3() { +} + +@_expose(Cxx, "exposed4") +public func exposed4Renamed() { +} + +@_expose(Cxx) +public struct ExposedStruct { + public var x: Int + + public func method() {} +} + +@_expose(Cxx, "ExposedStruct2") +public struct ExposedStructRenamed { + public var y: Int + + @_expose(Cxx, "renamedProp") + public var prop: Int + + @_expose(Cxx, "prop3") + public let prop2: Int + + @_expose(Cxx, "renamedMethod") + public func method() {} +} + +@_expose(Cxx) +public final class ExposedClass { + public func method() {} +} + +// CHECK: class ExposedClass final +// CHECK: class ExposedStruct final { +// CHECK: class ExposedStruct2 final { + +// CHECK: inline void exposed1() noexcept { +// CHECK-NEXT: return _impl::$s6Expose8exposed1yyF(); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline void exposed3() noexcept { +// CHECK-NEXT: return _impl::$s6Expose8exposed3yyF(); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline void exposed4() noexcept { +// CHECK-NEXT: return _impl::$s6Expose15exposed4RenamedyyF(); +// CHECK-NEXT: } + +// CHECK: void ExposedClass::method() +// CHECK: swift::Int ExposedStruct::getX() const { +// CHECK: void ExposedStruct::setX(swift::Int value) { +// CHECK: void ExposedStruct::method() const { +// CHECK: swift::Int ExposedStruct2::getY() const { +// CHECK: void ExposedStruct2::setY(swift::Int value) { +// CHECK: swift::Int ExposedStruct2::getRenamedProp() const { +// CHECK: void ExposedStruct2::setRenamedProp(swift::Int value) { +// CHECK: swift::Int ExposedStruct2::getProp3() const { +// CHECK: void ExposedStruct2::renamedMethod() const { + diff --git a/test/attr/attr_expose.swift b/test/attr/attr_expose.swift new file mode 100644 index 0000000000000..be5aa25472e94 --- /dev/null +++ b/test/attr/attr_expose.swift @@ -0,0 +1,26 @@ +// RUN: %target-typecheck-verify-swift + +@_cdecl("cdecl_foo") func foo(x: Int) -> Int { return x } + +@_expose(Cxx) func test() {} +@_expose(Cxx, "renamed") func renamedFunc() {} +@_expose(Cxx, "") func emptyNameOk() {} + +@_expose // expected-error {{expected '(' in '_expose' attribute}} +func exposeWithoutArgs() {} + +@_expose(CplusPlus) // expected-error {{expected '_expose' option such as 'Cxx'}} +func incorrectLangSpecifier() {} + +@_expose(Cxx) @_cdecl("test") // expected-error {{@_expose attribute cannot be applied to an '@_cdecl' declaration}} +func cdeclAndExpose() {} + +func hasNested() { + @_expose(Cxx) // expected-error{{can only be used in a non-local scope}} + func nested() { } +} + +struct NotExposedStruct { + @_expose(Cxx) // expected-error {{@_expose attribute cannot be applied inside of unexposed declaration 'NotExposedStruct'}} + func errorOnInnerExpose() {} +} From a0ef942e19a9a91b5cfc6860c93111bf2419b016 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 24 Aug 2022 10:30:11 -0700 Subject: [PATCH 359/491] IRGen: Use the clang type descriminator for TaskContinuationFunction* rdar://98992498 --- include/swift/ABI/MetadataValues.h | 3 +++ include/swift/AST/IRGenOptions.h | 3 +++ lib/IRGen/GenCall.cpp | 4 +++- lib/IRGen/GenFunc.cpp | 3 ++- lib/IRGen/IRGen.cpp | 4 ++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h index 0f00de982a69b..4f8327c8d6660 100644 --- a/include/swift/ABI/MetadataValues.h +++ b/include/swift/ABI/MetadataValues.h @@ -1428,6 +1428,9 @@ namespace SpecialPointerAuthDiscriminators { /// Swift async context parameter stored in the extended frame info. const uint16_t SwiftAsyncContextExtendedFrameEntry = 0xc31a; // = 49946 + // C type TaskContinuationFunction* descriminator. + const uint16_t ClangTypeTaskContinuationFunction = 0x2abe; // = 10942 + /// Dispatch integration. const uint16_t DispatchInvokeFunction = 0xf493; // = 62611 diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 652b1d7b153bc..154e6be2ed076 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -195,6 +195,9 @@ struct PointerAuthOptions : clang::PointerAuthOptions { /// Extended existential type shapes in flight. PointerAuthSchema ExtendedExistentialTypeShape; + // The c type descriminator for TaskContinuationFunction*. + PointerAuthSchema ClangTypeTaskContinuationFunction; + /// Non-unique extended existential type shapes in flight. PointerAuthSchema NonUniqueExtendedExistentialTypeShape; }; diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 31b1ff579a9cf..979682fa1e45a 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -2730,8 +2730,10 @@ class AsyncCallEmission final : public CallEmission { auto signedResumeFn = currentResumeFn; // Sign the task resume function with the C function pointer schema. if (auto schema = IGF.IGM.getOptions().PointerAuth.FunctionPointers) { - // TODO: use the Clang type for TaskContinuationFunction* + // Use the Clang type for TaskContinuationFunction* // to make this work with type diversity. + schema = + IGF.IGM.getOptions().PointerAuth.ClangTypeTaskContinuationFunction; auto authInfo = PointerAuthInfo::emit(IGF, schema, nullptr, PointerAuthEntity()); signedResumeFn = emitPointerAuthSign(IGF, signedResumeFn, authInfo); diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index b7bc23fdbf7ba..19d0cefa8e247 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -2469,8 +2469,9 @@ llvm::Function *IRGenFunction::createAsyncSuspendFn() { // Sign the task resume function with the C function pointer schema. if (auto schema = IGM.getOptions().PointerAuth.FunctionPointers) { - // TODO: use the Clang type for TaskContinuationFunction* + // Use the Clang type for TaskContinuationFunction* // to make this work with type diversity. + schema = IGM.getOptions().PointerAuth.ClangTypeTaskContinuationFunction; auto authInfo = PointerAuthInfo::emit(suspendIGF, schema, nullptr, PointerAuthEntity()); resumeFunction = emitPointerAuthSign(suspendIGF, resumeFunction, authInfo); diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index 5ccf75c90b1a1..34dd55efbf7b1 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -994,6 +994,10 @@ static void setPointerAuthOptions(PointerAuthOptions &opts, Discrimination::Constant, SpecialPointerAuthDiscriminators ::NonUniqueExtendedExistentialTypeShape); + + opts.ClangTypeTaskContinuationFunction = PointerAuthSchema( + codeKey, /*address*/ false, Discrimination::Constant, + SpecialPointerAuthDiscriminators::ClangTypeTaskContinuationFunction); } std::unique_ptr From 730bf2403582f35e85a13045416f7a761d0552d2 Mon Sep 17 00:00:00 2001 From: fibrechannelscsi <110562401+fibrechannelscsi@users.noreply.github.com> Date: Wed, 24 Aug 2022 12:55:05 -0600 Subject: [PATCH 360/491] Add benchmarks that measure KeyPath read and write performance. (#60383) * Add benchmarks that measure KeyPath read and write performance. * Added setUpFunctions. Revised number of iterations per benchmark. * Include n as a factor in the number of iterations. * Increased number of iterations for KeyPathDirectAccess by a factor of 25. * One last tweak to the number of iterations on testDirectAccess to get them above 20 us. * Made revisions based on feedback. Added three new benchmarks. * Added benchmarks to exhaustively benchmark all KeyPathComponent types. Removed benchmarks dealing with an inlining issue. * Wrapped additional keypaths with identity() where needed. More cleanup and documentation. * Moved KeyPaths for KeyPathRead and Write into FixedSizeArrayHolder. Renamed GetSet to Getset. * Added inline(never) to both versions of getKeypathToElement(). * Moved identity() wraps so that they're called once per variable per benchmark. * Moving destinationKeyPaths into FixedSizeArrayHolder to try to reduce long setup overhead errors. * Additional moving of the identity() wrapping into the singleton's init() to try to reduce setup time errors. --- benchmark/CMakeLists.txt | 1 + .../KeyPathPerformanceTests.swift | 1701 +++++++++++++++++ benchmark/utils/main.swift | 2 + 3 files changed, 1704 insertions(+) create mode 100644 benchmark/single-source/KeyPathPerformanceTests.swift diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index cc4ad3ec083c6..37e0aa50b6ffb 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -106,6 +106,7 @@ set(SWIFT_BENCH_MODULES single-source/Integrate single-source/IterateData single-source/Join + single-source/KeyPathPerformanceTests single-source/LazyFilter single-source/LinkedList single-source/LuhnAlgoEager diff --git a/benchmark/single-source/KeyPathPerformanceTests.swift b/benchmark/single-source/KeyPathPerformanceTests.swift new file mode 100644 index 0000000000000..f1d5c69c9347f --- /dev/null +++ b/benchmark/single-source/KeyPathPerformanceTests.swift @@ -0,0 +1,1701 @@ +//===--- KeyPathPerformanceTests.swift -------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2022 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 TestsUtils + +public let benchmarks = [ + BenchmarkInfo( + name: "KeyPathNestedStructs", + runFunction: run_KeyPathNestedStructs, + tags: [.validation, .api], + setUpFunction: setupKeyPathNestedStructs + ), + BenchmarkInfo( + name: "KeyPathDirectAccess", + runFunction: run_testDirectAccess, + tags: [.validation, .api, .skip], + setUpFunction: setupSingleton + ), + BenchmarkInfo( + name: "KeyPathReadPerformance", + runFunction: run_testKeyPathReadPerformance, + tags: [.validation, .api], + setUpFunction: setupSingleton + ), + BenchmarkInfo( + name: "KeyPathWritePerformance", + runFunction: run_testKeyPathWritePerformance, + tags: [.validation, .api], + setUpFunction: setupSingleton + ), + BenchmarkInfo( + name: "KeyPathsSmallStruct", + runFunction: run_testKeyPathSmallStruct, + tags: [.validation, .api], + setUpFunction: setupSingleton + ), + BenchmarkInfo( + name: "KeyPathMutatingGetset", + runFunction: run_KeyPathMutatingGetset, + tags: [.validation, .api], + setUpFunction: setupKeyPathNestedStructs + ), + BenchmarkInfo( + name: "KeyPathGet", + runFunction: run_KeyPathGet, + tags: [.validation, .api], + setUpFunction: setupKeyPathNestedStructs + ), + BenchmarkInfo( + name: "KeyPathOptionals", + runFunction: run_KeyPathOptionals, + tags: [.validation, .api], + setUpFunction: setupKeyPathNestedStructs + ), + BenchmarkInfo( + name: "KeyPathNestedClasses", + runFunction: run_KeyPathNestedClasses, + tags: [.validation, .api], + setUpFunction: setupKeyPathNestedStructs + ), +] + +/** + There are several types of KeyPathComponents. + The following table indicates which type is featured in which benchmark. + Note that some types may be observed in other benchmarks as well. + + | KeyPathComponent Type |Featured in Benchmark | + |-----------------------|:---------------------------------| + | struct |*run_KeyPathNestedStruct()* | + | class |*run_KeyPathNestedClasses()* | + | get |*run_KeyPathGet()* | + | mutatingGetset |*run_KeyPathMutatingGetset()* | + | nonmutatingGetset |*run_KeyPathNonmutatingGetset()* | + | optionalChain |*run_KeyPathOptionals()* | + | optionalForce |*run_KeyPathOptionals()* | + | optionalWrap |*run_KeyPathOptionals()* | + */ + +let numberOfElementsForNestedStructs = 20000 +let expectedIntForNestedItems = 3 + +// Make it easy to switch between primitives of different types (Int, Float, Double, etc.). +typealias ElementType = Double + +// The purpose of this class is to hold arrays used during the course of the benchmarks. +// This is to avoid storing them in the global scope, which can slow things down. +class FixedSizeArrayHolder { + var fixedSizeArray100: FixedSizeArray100 + var fixedSizeArray10: FixedSizeArray10 + var mainArrayForNestedStructs: [A] + var arrayForMutatingGetset: [MutatingGetsetNested1] + var arrayForGet: [GetNested1] + var arrayForOptionals: [Optional1] + var arrayForNestedClasses: [C1] + var arrayForNonMutatingGetset: [M] + var keypathForMutatingGetSet: WritableKeyPath + var keypathForGet: KeyPath + var keypathForOptional: KeyPath + var keypathForNestedClasses: KeyPath + var keypathForNonMutatingGetset: WritableKeyPath + + // Same order as in KeyPathWritePerformance + var kp46: WritableKeyPath, ElementType> + var kp43: WritableKeyPath, ElementType> + var kp81: WritableKeyPath, ElementType> + var kp31: WritableKeyPath, ElementType> + var kp35: WritableKeyPath, ElementType> + var kp14: WritableKeyPath, ElementType> + var kp51: WritableKeyPath, ElementType> + var kp24: WritableKeyPath, ElementType> + var kp90: WritableKeyPath, ElementType> + var kp80: WritableKeyPath, ElementType> + var kp47: WritableKeyPath, ElementType> + var kp92: WritableKeyPath, ElementType> + var kp78: WritableKeyPath, ElementType> + var kp79: WritableKeyPath, ElementType> + var kp48: WritableKeyPath, ElementType> + var kp64: WritableKeyPath, ElementType> + var kp65: WritableKeyPath, ElementType> + var kp19: WritableKeyPath, ElementType> + var kp66: WritableKeyPath, ElementType> + var kp10: WritableKeyPath, ElementType> + var kp89: WritableKeyPath, ElementType> + var kp16: WritableKeyPath, ElementType> + var kp06: WritableKeyPath, ElementType> + var kp26: WritableKeyPath, ElementType> + var kp83: WritableKeyPath, ElementType> + + // Same order as in KeyPathReadPerformance, with duplicates removed. + var kp99: WritableKeyPath, ElementType> + var kp27: WritableKeyPath, ElementType> + var kp09: WritableKeyPath, ElementType> + var kp84: WritableKeyPath, ElementType> + var kp22: WritableKeyPath, ElementType> + var kp82: WritableKeyPath, ElementType> + var kp86: WritableKeyPath, ElementType> + var kp49: WritableKeyPath, ElementType> + var kp18: WritableKeyPath, ElementType> + var kp97: WritableKeyPath, ElementType> + var kp69: WritableKeyPath, ElementType> + var kp76: WritableKeyPath, ElementType> + var kp32: WritableKeyPath, ElementType> + var kp52: WritableKeyPath, ElementType> + var kp87: WritableKeyPath, ElementType> + var kp67: WritableKeyPath, ElementType> + var kp12: WritableKeyPath, ElementType> + var kp21: WritableKeyPath, ElementType> + var kp77: WritableKeyPath, ElementType> + var kp40: WritableKeyPath, ElementType> + var kp60: WritableKeyPath, ElementType> + var kp50: WritableKeyPath, ElementType> + + // Same order as in KeyPathSmallStruct. + var kp0: WritableKeyPath, ElementType> + var kp1: WritableKeyPath, ElementType> + var kp2: WritableKeyPath, ElementType> + var kp3: WritableKeyPath, ElementType> + var kp4: WritableKeyPath, ElementType> + var kp5: WritableKeyPath, ElementType> + var kp6: WritableKeyPath, ElementType> + var kp7: WritableKeyPath, ElementType> + var kp8: WritableKeyPath, ElementType> + var kp9: WritableKeyPath, ElementType> + + static let shared = FixedSizeArrayHolder() + init() { + fixedSizeArray100 = initializeFixedSizeArray100() + fixedSizeArray10 = initializeFixedSizeArray10() + mainArrayForNestedStructs = [A]() + arrayForMutatingGetset = [MutatingGetsetNested1]() + arrayForGet = [GetNested1]() + arrayForOptionals = [Optional1]() + arrayForNestedClasses = [C1]() + arrayForNonMutatingGetset = [M]() + + kp46 = identity(FixedSizeArray100.getKeypathToElement(index: 46)) + kp43 = identity(FixedSizeArray100.getKeypathToElement(index: 43)) + kp81 = identity(FixedSizeArray100.getKeypathToElement(index: 81)) + kp31 = identity(FixedSizeArray100.getKeypathToElement(index: 31)) + kp35 = identity(FixedSizeArray100.getKeypathToElement(index: 35)) + kp14 = identity(FixedSizeArray100.getKeypathToElement(index: 14)) + kp51 = identity(FixedSizeArray100.getKeypathToElement(index: 51)) + kp24 = identity(FixedSizeArray100.getKeypathToElement(index: 24)) + kp90 = identity(FixedSizeArray100.getKeypathToElement(index: 90)) + kp80 = identity(FixedSizeArray100.getKeypathToElement(index: 80)) + kp47 = identity(FixedSizeArray100.getKeypathToElement(index: 47)) + kp92 = identity(FixedSizeArray100.getKeypathToElement(index: 92)) + kp78 = identity(FixedSizeArray100.getKeypathToElement(index: 78)) + kp79 = identity(FixedSizeArray100.getKeypathToElement(index: 79)) + kp48 = identity(FixedSizeArray100.getKeypathToElement(index: 48)) + kp64 = identity(FixedSizeArray100.getKeypathToElement(index: 64)) + kp65 = identity(FixedSizeArray100.getKeypathToElement(index: 65)) + kp19 = identity(FixedSizeArray100.getKeypathToElement(index: 19)) + kp66 = identity(FixedSizeArray100.getKeypathToElement(index: 66)) + kp10 = identity(FixedSizeArray100.getKeypathToElement(index: 10)) + kp89 = identity(FixedSizeArray100.getKeypathToElement(index: 89)) + kp16 = identity(FixedSizeArray100.getKeypathToElement(index: 16)) + kp06 = identity(FixedSizeArray100.getKeypathToElement(index: 06)) + kp26 = identity(FixedSizeArray100.getKeypathToElement(index: 26)) + kp83 = identity(FixedSizeArray100.getKeypathToElement(index: 83)) + + kp99 = identity(FixedSizeArray100.getKeypathToElement(index: 99)) + kp27 = identity(FixedSizeArray100.getKeypathToElement(index: 27)) + kp09 = identity(FixedSizeArray100.getKeypathToElement(index: 09)) + kp84 = identity(FixedSizeArray100.getKeypathToElement(index: 84)) + kp22 = identity(FixedSizeArray100.getKeypathToElement(index: 22)) + kp82 = identity(FixedSizeArray100.getKeypathToElement(index: 82)) + kp86 = identity(FixedSizeArray100.getKeypathToElement(index: 86)) + kp49 = identity(FixedSizeArray100.getKeypathToElement(index: 49)) + kp18 = identity(FixedSizeArray100.getKeypathToElement(index: 18)) + kp97 = identity(FixedSizeArray100.getKeypathToElement(index: 97)) + kp69 = identity(FixedSizeArray100.getKeypathToElement(index: 69)) + kp76 = identity(FixedSizeArray100.getKeypathToElement(index: 76)) + kp32 = identity(FixedSizeArray100.getKeypathToElement(index: 32)) + kp52 = identity(FixedSizeArray100.getKeypathToElement(index: 52)) + kp24 = identity(FixedSizeArray100.getKeypathToElement(index: 24)) + kp87 = identity(FixedSizeArray100.getKeypathToElement(index: 87)) + kp67 = identity(FixedSizeArray100.getKeypathToElement(index: 67)) + kp65 = identity(FixedSizeArray100.getKeypathToElement(index: 65)) + kp43 = identity(FixedSizeArray100.getKeypathToElement(index: 43)) + kp12 = identity(FixedSizeArray100.getKeypathToElement(index: 12)) + kp21 = identity(FixedSizeArray100.getKeypathToElement(index: 21)) + kp77 = identity(FixedSizeArray100.getKeypathToElement(index: 77)) + kp40 = identity(FixedSizeArray100.getKeypathToElement(index: 40)) + kp60 = identity(FixedSizeArray100.getKeypathToElement(index: 60)) + kp50 = identity(FixedSizeArray100.getKeypathToElement(index: 50)) + + kp0 = identity(FixedSizeArray10.getKeypathToElement(index: 0)) + kp1 = identity(FixedSizeArray10.getKeypathToElement(index: 1)) + kp2 = identity(FixedSizeArray10.getKeypathToElement(index: 2)) + kp3 = identity(FixedSizeArray10.getKeypathToElement(index: 3)) + kp4 = identity(FixedSizeArray10.getKeypathToElement(index: 4)) + kp5 = identity(FixedSizeArray10.getKeypathToElement(index: 5)) + kp6 = identity(FixedSizeArray10.getKeypathToElement(index: 6)) + kp7 = identity(FixedSizeArray10.getKeypathToElement(index: 7)) + kp8 = identity(FixedSizeArray10.getKeypathToElement(index: 8)) + kp9 = identity(FixedSizeArray10.getKeypathToElement(index: 9)) + + keypathForMutatingGetSet = identity(\MutatingGetsetNested1.nestedItem.nestedItem.nestedItem + .nestedItem.storage) + keypathForGet = identity(\GetNested1.nestedItem.nestedItem.nestedItem.nestedItem.storage) + keypathForOptional = identity(\Optional1._nestedItemStorage?!._nestedItemStorage?! + ._nestedItemStorage?!._nestedItemStorage?!._storage) + keypathForNestedClasses = identity(\C1.r.r.r.r.a) + keypathForNonMutatingGetset = identity(\M.n.o.p.q.q) + } +} + +// Setup Functions. +public func setupKeyPathNestedStructs() { + let holder = FixedSizeArrayHolder.shared + for _ in 0 ..< numberOfElementsForNestedStructs { + let instance = A(a: 0, b: B(b: 0, c: C(c: 0, d: D(d: 0, e: E(e: expectedIntForNestedItems))))) + holder.mainArrayForNestedStructs.append(instance) + + var mutatingGetsetInstance = MutatingGetsetNested1() + mutatingGetsetInstance.nestedItem.nestedItem.nestedItem.nestedItem + .storage = expectedIntForNestedItems + holder.arrayForMutatingGetset.append(mutatingGetsetInstance) + holder.arrayForGet.append(GetNested1()) + holder.arrayForOptionals.append(Optional1()) + holder.arrayForNestedClasses.append(C1()) + holder.arrayForNonMutatingGetset + .append(M(n: N(o: O(p: P(q: Q(q: expectedIntForNestedItems)))))) + } +} + +public func setupSingleton() { + blackHole(FixedSizeArrayHolder.shared) +} + +// We would like to compute the sums of the arrays once the iterations finish, +// and doing it this way it likely faster than using keypaths via getKeypathToElement(). +func computeSumOfFixedSizeArray100(fixedSizeArray100: inout FixedSizeArray100) + -> ElementType +{ + var sum = ElementType(0) + withUnsafeBytes(of: fixedSizeArray100) { + var pointer = $0.baseAddress.unsafelyUnwrapped + for _ in 0 ..< fixedSizeArray100.count { + sum += pointer.assumingMemoryBound(to: ElementType.self).pointee + pointer = pointer.advanced(by: MemoryLayout.size) + } + } + return sum +} + +func computeSumOfFixedSizeArray10(fixedSizeArray10: inout FixedSizeArray10) + -> ElementType +{ + var sum = ElementType(0) + withUnsafeBytes(of: fixedSizeArray10) { + var pointer = $0.baseAddress.unsafelyUnwrapped + for _ in 0 ..< fixedSizeArray10.count { + sum += pointer.assumingMemoryBound(to: ElementType.self).pointee + pointer = pointer.advanced(by: MemoryLayout.size) + } + } + return sum +} + +// Used for run_KeyPathNestedStructs(). +struct A { + var a: Int + var b: B +} + +struct B { + var b: Int + var c: C +} + +struct C { + var c: Int + var d: D +} + +struct D { + var d: Int + var e: E +} + +struct E { + var e: Int +} + +// Used for run_KeyPathNestedClasses() +class C1 { + let a: Int = 0 + let r: C2 = .init() + class C2 { + let b: Int = 0 + let r: C3 = .init() + class C3 { + let a: Int = 0 + let r: C4 = .init() + class C4 { + let a: Int = 0 + let r: C5 = .init() + class C5 { + let a: Int = expectedIntForNestedItems + } + } + } + } +} + +// Used for run_KeyPathNonmutatingGetset() +class M { + var n: N + init(n: N) { self.n = n } +} + +class N { + var o: O + init(o: O) { self.o = o } +} + +class O { + var p: P + init(p: P) { self.p = p } +} + +class P { + var q: Q + init(q: Q) { self.q = q } +} + +class Q { + var q: Int + init(q: Int) { self.q = q } +} + +// Used for run_KeyPathMutatingGetset() +struct MutatingGetsetNested1 { + var _storage: Int + var _nestedItemStorage: MutatingGetsetNested2 + var storage: Int { + get { return _storage } + set { _storage = newValue } + } + + var nestedItem: MutatingGetsetNested2 { + get { return _nestedItemStorage } + set { _nestedItemStorage = newValue } + } + + init() { + _storage = 0 + _nestedItemStorage = MutatingGetsetNested2() + } +} + +struct MutatingGetsetNested2 { + var _storage: Int + var _nestedItemStorage: MutatingGetsetNested3 + var storage: Int { + get { return _storage } + set { _storage = newValue } + } + + var nestedItem: MutatingGetsetNested3 { + get { return _nestedItemStorage } + set { _nestedItemStorage = newValue } + } + + init() { + _storage = 0 + _nestedItemStorage = MutatingGetsetNested3() + } +} + +struct MutatingGetsetNested3 { + var _storage: Int + var _nestedItemStorage: MutatingGetsetNested4 + var storage: Int { + get { return _storage } + set { _storage = newValue } + } + + var nestedItem: MutatingGetsetNested4 { + get { return _nestedItemStorage } + set { _nestedItemStorage = newValue } + } + + init() { + _storage = 0 + _nestedItemStorage = MutatingGetsetNested4() + } +} + +struct MutatingGetsetNested4 { + var _storage: Int + var _nestedItemStorage: MutatingGetsetNested5 + var storage: Int { + get { return _storage } + set { _storage = newValue } + } + + var nestedItem: MutatingGetsetNested5 { + get { return _nestedItemStorage } + set { _nestedItemStorage = newValue } + } + + init() { + _storage = 0 + _nestedItemStorage = MutatingGetsetNested5() + } +} + +struct MutatingGetsetNested5 { + var _storage: Int + var storage: Int { + get { return _storage } + set { _storage = newValue } + } + + init() { + _storage = 10 + } +} + +// Used for run_KeyPathGet(). +struct GetNested1 { + var _storage: Int + var _nestedItemStorage: GetNested2 + var storage: Int { return _storage } + var nestedItem: GetNested2 { return _nestedItemStorage } + init() { + _storage = 0 + _nestedItemStorage = GetNested2() + } +} + +struct GetNested2 { + var _storage: Int + var _nestedItemStorage: GetNested3 + var storage: Int { return _storage } + var nestedItem: GetNested3 { return _nestedItemStorage } + init() { + _storage = 0 + _nestedItemStorage = GetNested3() + } +} + +struct GetNested3 { + var _storage: Int + var _nestedItemStorage: GetNested4 + var storage: Int { return _storage } + var nestedItem: GetNested4 { return _nestedItemStorage } + init() { + _storage = 0 + _nestedItemStorage = GetNested4() + } +} + +struct GetNested4 { + var _storage: Int + var _nestedItemStorage: GetNested5 + var storage: Int { return _storage } + var nestedItem: GetNested5 { return _nestedItemStorage } + init() { + _storage = 0 + _nestedItemStorage = GetNested5() + } +} + +struct GetNested5 { + var _storage: Int + var storage: Int { return _storage } + init() { + _storage = expectedIntForNestedItems + } +} + +// Used for run_KeyPathOptionals(). +struct Optional1 { + var _storage: Int + var _nestedItemStorage: Optional2?? + init() { + _storage = 0 + _nestedItemStorage = Optional2() + } +} + +struct Optional2 { + var _storage: Int + var _nestedItemStorage: Optional3?? + init() { + _storage = 0 + _nestedItemStorage = Optional3() + } +} + +struct Optional3 { + var _storage: Int + var _nestedItemStorage: Optional4?? + init() { + _storage = 0 + _nestedItemStorage = Optional4() + } +} + +struct Optional4 { + var _storage: Int + var _nestedItemStorage: Optional5?? + init() { + _storage = 0 + _nestedItemStorage = Optional5() + } +} + +struct Optional5 { + public var _storage: Int + init() { + _storage = expectedIntForNestedItems + } +} + +// Used for run_KeyPathFixedSizeArrayAccess() and run_testDirectAccess(). +struct FixedSizeArray100: Sequence, IteratorProtocol { + let count: Int = 100 + + public init( + element0: Element, + element1: Element, + element2: Element, + element3: Element, + element4: Element, + element5: Element, + element6: Element, + element7: Element, + element8: Element, + element9: Element, + element10: Element, + element11: Element, + element12: Element, + element13: Element, + element14: Element, + element15: Element, + element16: Element, + element17: Element, + element18: Element, + element19: Element, + element20: Element, + element21: Element, + element22: Element, + element23: Element, + element24: Element, + element25: Element, + element26: Element, + element27: Element, + element28: Element, + element29: Element, + element30: Element, + element31: Element, + element32: Element, + element33: Element, + element34: Element, + element35: Element, + element36: Element, + element37: Element, + element38: Element, + element39: Element, + element40: Element, + element41: Element, + element42: Element, + element43: Element, + element44: Element, + element45: Element, + element46: Element, + element47: Element, + element48: Element, + element49: Element, + element50: Element, + element51: Element, + element52: Element, + element53: Element, + element54: Element, + element55: Element, + element56: Element, + element57: Element, + element58: Element, + element59: Element, + element60: Element, + element61: Element, + element62: Element, + element63: Element, + element64: Element, + element65: Element, + element66: Element, + element67: Element, + element68: Element, + element69: Element, + element70: Element, + element71: Element, + element72: Element, + element73: Element, + element74: Element, + element75: Element, + element76: Element, + element77: Element, + element78: Element, + element79: Element, + element80: Element, + element81: Element, + element82: Element, + element83: Element, + element84: Element, + element85: Element, + element86: Element, + element87: Element, + element88: Element, + element89: Element, + element90: Element, + element91: Element, + element92: Element, + element93: Element, + element94: Element, + element95: Element, + element96: Element, + element97: Element, + element98: Element, + element99: Element + ) { + self.element0 = element0 + self.element1 = element1 + self.element2 = element2 + self.element3 = element3 + self.element4 = element4 + self.element5 = element5 + self.element6 = element6 + self.element7 = element7 + self.element8 = element8 + self.element9 = element9 + self.element10 = element10 + self.element11 = element11 + self.element12 = element12 + self.element13 = element13 + self.element14 = element14 + self.element15 = element15 + self.element16 = element16 + self.element17 = element17 + self.element18 = element18 + self.element19 = element19 + self.element20 = element20 + self.element21 = element21 + self.element22 = element22 + self.element23 = element23 + self.element24 = element24 + self.element25 = element25 + self.element26 = element26 + self.element27 = element27 + self.element28 = element28 + self.element29 = element29 + self.element30 = element30 + self.element31 = element31 + self.element32 = element32 + self.element33 = element33 + self.element34 = element34 + self.element35 = element35 + self.element36 = element36 + self.element37 = element37 + self.element38 = element38 + self.element39 = element39 + self.element40 = element40 + self.element41 = element41 + self.element42 = element42 + self.element43 = element43 + self.element44 = element44 + self.element45 = element45 + self.element46 = element46 + self.element47 = element47 + self.element48 = element48 + self.element49 = element49 + self.element50 = element50 + self.element51 = element51 + self.element52 = element52 + self.element53 = element53 + self.element54 = element54 + self.element55 = element55 + self.element56 = element56 + self.element57 = element57 + self.element58 = element58 + self.element59 = element59 + self.element60 = element60 + self.element61 = element61 + self.element62 = element62 + self.element63 = element63 + self.element64 = element64 + self.element65 = element65 + self.element66 = element66 + self.element67 = element67 + self.element68 = element68 + self.element69 = element69 + self.element70 = element70 + self.element71 = element71 + self.element72 = element72 + self.element73 = element73 + self.element74 = element74 + self.element75 = element75 + self.element76 = element76 + self.element77 = element77 + self.element78 = element78 + self.element79 = element79 + self.element80 = element80 + self.element81 = element81 + self.element82 = element82 + self.element83 = element83 + self.element84 = element84 + self.element85 = element85 + self.element86 = element86 + self.element87 = element87 + self.element88 = element88 + self.element89 = element89 + self.element90 = element90 + self.element91 = element91 + self.element92 = element92 + self.element93 = element93 + self.element94 = element94 + self.element95 = element95 + self.element96 = element96 + self.element97 = element97 + self.element98 = element98 + self.element99 = element99 + } + + var element0: Element + var element1: Element + var element2: Element + var element3: Element + var element4: Element + var element5: Element + var element6: Element + var element7: Element + var element8: Element + var element9: Element + var element10: Element + var element11: Element + var element12: Element + var element13: Element + var element14: Element + var element15: Element + var element16: Element + var element17: Element + var element18: Element + var element19: Element + var element20: Element + var element21: Element + var element22: Element + var element23: Element + var element24: Element + var element25: Element + var element26: Element + var element27: Element + var element28: Element + var element29: Element + var element30: Element + var element31: Element + var element32: Element + var element33: Element + var element34: Element + var element35: Element + var element36: Element + var element37: Element + var element38: Element + var element39: Element + var element40: Element + var element41: Element + var element42: Element + var element43: Element + var element44: Element + var element45: Element + var element46: Element + var element47: Element + var element48: Element + var element49: Element + var element50: Element + var element51: Element + var element52: Element + var element53: Element + var element54: Element + var element55: Element + var element56: Element + var element57: Element + var element58: Element + var element59: Element + var element60: Element + var element61: Element + var element62: Element + var element63: Element + var element64: Element + var element65: Element + var element66: Element + var element67: Element + var element68: Element + var element69: Element + var element70: Element + var element71: Element + var element72: Element + var element73: Element + var element74: Element + var element75: Element + var element76: Element + var element77: Element + var element78: Element + var element79: Element + var element80: Element + var element81: Element + var element82: Element + var element83: Element + var element84: Element + var element85: Element + var element86: Element + var element87: Element + var element88: Element + var element89: Element + var element90: Element + var element91: Element + var element92: Element + var element93: Element + var element94: Element + var element95: Element + var element96: Element + var element97: Element + var element98: Element + var element99: Element + + @inline(never) + static func getKeypathToElement(index: Int) + -> WritableKeyPath, Element> + { + switch index { + case 0: + return \FixedSizeArray100.element0 + case 1: + return \FixedSizeArray100.element1 + case 2: + return \FixedSizeArray100.element2 + case 3: + return \FixedSizeArray100.element3 + case 4: + return \FixedSizeArray100.element4 + case 5: + return \FixedSizeArray100.element5 + case 6: + return \FixedSizeArray100.element6 + case 7: + return \FixedSizeArray100.element7 + case 8: + return \FixedSizeArray100.element8 + case 9: + return \FixedSizeArray100.element9 + case 10: + return \FixedSizeArray100.element10 + case 11: + return \FixedSizeArray100.element11 + case 12: + return \FixedSizeArray100.element12 + case 13: + return \FixedSizeArray100.element13 + case 14: + return \FixedSizeArray100.element14 + case 15: + return \FixedSizeArray100.element15 + case 16: + return \FixedSizeArray100.element16 + case 17: + return \FixedSizeArray100.element17 + case 18: + return \FixedSizeArray100.element18 + case 19: + return \FixedSizeArray100.element19 + case 20: + return \FixedSizeArray100.element20 + case 21: + return \FixedSizeArray100.element21 + case 22: + return \FixedSizeArray100.element22 + case 23: + return \FixedSizeArray100.element23 + case 24: + return \FixedSizeArray100.element24 + case 25: + return \FixedSizeArray100.element25 + case 26: + return \FixedSizeArray100.element26 + case 27: + return \FixedSizeArray100.element27 + case 28: + return \FixedSizeArray100.element28 + case 29: + return \FixedSizeArray100.element29 + case 30: + return \FixedSizeArray100.element30 + case 31: + return \FixedSizeArray100.element31 + case 32: + return \FixedSizeArray100.element32 + case 33: + return \FixedSizeArray100.element33 + case 34: + return \FixedSizeArray100.element34 + case 35: + return \FixedSizeArray100.element35 + case 36: + return \FixedSizeArray100.element36 + case 37: + return \FixedSizeArray100.element37 + case 38: + return \FixedSizeArray100.element38 + case 39: + return \FixedSizeArray100.element39 + case 40: + return \FixedSizeArray100.element40 + case 41: + return \FixedSizeArray100.element41 + case 42: + return \FixedSizeArray100.element42 + case 43: + return \FixedSizeArray100.element43 + case 44: + return \FixedSizeArray100.element44 + case 45: + return \FixedSizeArray100.element45 + case 46: + return \FixedSizeArray100.element46 + case 47: + return \FixedSizeArray100.element47 + case 48: + return \FixedSizeArray100.element48 + case 49: + return \FixedSizeArray100.element49 + case 50: + return \FixedSizeArray100.element50 + case 51: + return \FixedSizeArray100.element51 + case 52: + return \FixedSizeArray100.element52 + case 53: + return \FixedSizeArray100.element53 + case 54: + return \FixedSizeArray100.element54 + case 55: + return \FixedSizeArray100.element55 + case 56: + return \FixedSizeArray100.element56 + case 57: + return \FixedSizeArray100.element57 + case 58: + return \FixedSizeArray100.element58 + case 59: + return \FixedSizeArray100.element59 + case 60: + return \FixedSizeArray100.element60 + case 61: + return \FixedSizeArray100.element61 + case 62: + return \FixedSizeArray100.element62 + case 63: + return \FixedSizeArray100.element63 + case 64: + return \FixedSizeArray100.element64 + case 65: + return \FixedSizeArray100.element65 + case 66: + return \FixedSizeArray100.element66 + case 67: + return \FixedSizeArray100.element67 + case 68: + return \FixedSizeArray100.element68 + case 69: + return \FixedSizeArray100.element69 + case 70: + return \FixedSizeArray100.element70 + case 71: + return \FixedSizeArray100.element71 + case 72: + return \FixedSizeArray100.element72 + case 73: + return \FixedSizeArray100.element73 + case 74: + return \FixedSizeArray100.element74 + case 75: + return \FixedSizeArray100.element75 + case 76: + return \FixedSizeArray100.element76 + case 77: + return \FixedSizeArray100.element77 + case 78: + return \FixedSizeArray100.element78 + case 79: + return \FixedSizeArray100.element79 + case 80: + return \FixedSizeArray100.element80 + case 81: + return \FixedSizeArray100.element81 + case 82: + return \FixedSizeArray100.element82 + case 83: + return \FixedSizeArray100.element83 + case 84: + return \FixedSizeArray100.element84 + case 85: + return \FixedSizeArray100.element85 + case 86: + return \FixedSizeArray100.element86 + case 87: + return \FixedSizeArray100.element87 + case 88: + return \FixedSizeArray100.element88 + case 89: + return \FixedSizeArray100.element89 + case 90: + return \FixedSizeArray100.element90 + case 91: + return \FixedSizeArray100.element91 + case 92: + return \FixedSizeArray100.element92 + case 93: + return \FixedSizeArray100.element93 + case 94: + return \FixedSizeArray100.element94 + case 95: + return \FixedSizeArray100.element95 + case 96: + return \FixedSizeArray100.element96 + case 97: + return \FixedSizeArray100.element97 + case 98: + return \FixedSizeArray100.element98 + case 99: + return \FixedSizeArray100.element99 + default: + fatalError() + } + } + + // Conformance to Iterator. + mutating func next() -> Element? { + var iter_count = 0 + if iter_count == count { + return nil + } else { + defer { iter_count += 1 } + return self[keyPath: FixedSizeArray100.getKeypathToElement(index: iter_count)] + } + } +} + +// Used for run_testKeyPathSmallStruct(). +struct FixedSizeArray10: Sequence, IteratorProtocol { + let count: Int = 10 + + public init( + element0: Element, + element1: Element, + element2: Element, + element3: Element, + element4: Element, + element5: Element, + element6: Element, + element7: Element, + element8: Element, + element9: Element + + ) { + self.element0 = element0 + self.element1 = element1 + self.element2 = element2 + self.element3 = element3 + self.element4 = element4 + self.element5 = element5 + self.element6 = element6 + self.element7 = element7 + self.element8 = element8 + self.element9 = element9 + } + + var element0: Element + var element1: Element + var element2: Element + var element3: Element + var element4: Element + var element5: Element + var element6: Element + var element7: Element + var element8: Element + var element9: Element + + @inline(never) + static func getKeypathToElement(index: Int) + -> WritableKeyPath, Element> + { + switch index { + case 0: + return \FixedSizeArray10.element0 + case 1: + return \FixedSizeArray10.element1 + case 2: + return \FixedSizeArray10.element2 + case 3: + return \FixedSizeArray10.element3 + case 4: + return \FixedSizeArray10.element4 + case 5: + return \FixedSizeArray10.element5 + case 6: + return \FixedSizeArray10.element6 + case 7: + return \FixedSizeArray10.element7 + case 8: + return \FixedSizeArray10.element8 + case 9: + return \FixedSizeArray10.element9 + + default: + fatalError() + } + } + + // Conformance to Iterator. + mutating func next() -> Element? { + var iter_count = 0 + if iter_count == count { + return nil + } else { + defer { iter_count += 1 } + return self[keyPath: FixedSizeArray10.getKeypathToElement(index: iter_count)] + } + } +} + +func initializeFixedSizeArray10() -> FixedSizeArray10 { + return FixedSizeArray10( + element0: 0, + element1: 1, + element2: 2, + element3: 3, + element4: 4, + element5: 5, + element6: 6, + element7: 7, + element8: 8, + element9: 9 + ) +} + +func initializeFixedSizeArray100() -> FixedSizeArray100 { + return FixedSizeArray100( + element0: 0, + element1: 1, + element2: 2, + element3: 3, + element4: 4, + element5: 5, + element6: 6, + element7: 7, + element8: 8, + element9: 9, + element10: 10, + element11: 11, + element12: 12, + element13: 13, + element14: 14, + element15: 15, + element16: 16, + element17: 17, + element18: 18, + element19: 19, + element20: 20, + element21: 21, + element22: 22, + element23: 23, + element24: 24, + element25: 25, + element26: 26, + element27: 27, + element28: 28, + element29: 29, + element30: 30, + element31: 31, + element32: 32, + element33: 33, + element34: 34, + element35: 35, + element36: 36, + element37: 37, + element38: 38, + element39: 39, + element40: 40, + element41: 41, + element42: 42, + element43: 43, + element44: 44, + element45: 45, + element46: 46, + element47: 47, + element48: 48, + element49: 49, + element50: 50, + element51: 51, + element52: 52, + element53: 53, + element54: 54, + element55: 55, + element56: 56, + element57: 57, + element58: 58, + element59: 59, + element60: 60, + element61: 61, + element62: 62, + element63: 63, + element64: 64, + element65: 65, + element66: 66, + element67: 67, + element68: 68, + element69: 69, + element70: 70, + element71: 71, + element72: 72, + element73: 73, + element74: 74, + element75: 75, + element76: 76, + element77: 77, + element78: 78, + element79: 79, + element80: 80, + element81: 81, + element82: 82, + element83: 83, + element84: 84, + element85: 85, + element86: 86, + element87: 87, + element88: 88, + element89: 89, + element90: 90, + element91: 91, + element92: 92, + element93: 93, + element94: 94, + element95: 95, + element96: 96, + element97: 97, + element98: 98, + element99: 99 + ) +} + +// This measures the performance of keypath reads though nested structs. +@inline(never) +public func run_KeyPathNestedStructs(n: Int) { + var sum = 0 + var index = 0 + let iterationMultipier = 200 + + let singleHopKeyPath0: WritableKeyPath = \A.b + let singleHopKeyPath1: WritableKeyPath = \B.c + let singleHopKeyPath2: WritableKeyPath = \C.d + let singleHopKeyPath3: WritableKeyPath = \D.e + let singleHopKeyPath4: WritableKeyPath = \E.e + + let appendedKeyPath = identity(singleHopKeyPath0.appending(path: singleHopKeyPath1) + .appending(path: singleHopKeyPath2).appending(path: singleHopKeyPath3) + .appending(path: singleHopKeyPath4)) + + let elementCount = FixedSizeArrayHolder.shared.mainArrayForNestedStructs.count + for _ in 1 ... iterationMultipier * n { + let element = FixedSizeArrayHolder.shared.mainArrayForNestedStructs[index] + sum += element[keyPath: appendedKeyPath] + index = (index + 1) % elementCount + } + check(sum == iterationMultipier * n * expectedIntForNestedItems) +} + +// This is meant as a baseline, from a timing perspective, +// for run_testKeyPathReadPerformance() and run_testKeyPathWritePerformance(). +// It's currently set to ".skip", but is useful for comparing the performance between keypath operations and direct dot-notation. +@inline(never) +public func run_testDirectAccess(n: Int) { + var fixedSizeArray100 = FixedSizeArrayHolder.shared.fixedSizeArray100 + let iterationMultipier = 125_000 + for t in 1 ... iterationMultipier * n { + fixedSizeArray100.element50 += fixedSizeArray100.element1 + ElementType(t) + fixedSizeArray100.element46 += fixedSizeArray100.element63 - fixedSizeArray100.element99 + fixedSizeArray100.element43 += fixedSizeArray100.element39 * fixedSizeArray100.element27 + fixedSizeArray100.element81 += fixedSizeArray100.element49 / fixedSizeArray100.element9 + fixedSizeArray100.element31 += fixedSizeArray100.element90 + fixedSizeArray100.element84 + fixedSizeArray100.element35 += fixedSizeArray100.element6 - fixedSizeArray100.element22 + fixedSizeArray100.element14 += fixedSizeArray100.element67 * fixedSizeArray100.element82 + fixedSizeArray100.element51 += fixedSizeArray100.element40 / fixedSizeArray100.element86 + fixedSizeArray100.element24 += fixedSizeArray100.element23 + fixedSizeArray100.element49 + fixedSizeArray100.element90 += fixedSizeArray100.element95 - fixedSizeArray100.element18 + fixedSizeArray100.element80 += fixedSizeArray100.element45 * fixedSizeArray100.element97 + fixedSizeArray100.element47 += fixedSizeArray100.element65 / fixedSizeArray100.element69 + fixedSizeArray100.element92 += fixedSizeArray100.element80 + fixedSizeArray100.element76 + fixedSizeArray100.element78 += fixedSizeArray100.element32 - fixedSizeArray100.element32 + fixedSizeArray100.element79 += fixedSizeArray100.element59 * fixedSizeArray100.element52 + fixedSizeArray100.element46 += fixedSizeArray100.element60 / fixedSizeArray100.element24 + fixedSizeArray100.element64 += fixedSizeArray100.element41 + fixedSizeArray100.element87 + fixedSizeArray100.element65 += fixedSizeArray100.element72 - fixedSizeArray100.element67 + fixedSizeArray100.element19 += fixedSizeArray100.element81 * fixedSizeArray100.element65 + fixedSizeArray100.element66 += fixedSizeArray100.element55 / fixedSizeArray100.element43 + fixedSizeArray100.element10 += fixedSizeArray100.element52 + fixedSizeArray100.element12 + fixedSizeArray100.element81 += fixedSizeArray100.element50 - fixedSizeArray100.element21 + fixedSizeArray100.element16 += fixedSizeArray100.element80 * fixedSizeArray100.element77 + fixedSizeArray100.element6 += fixedSizeArray100.element62 / fixedSizeArray100.element40 + fixedSizeArray100.element26 += fixedSizeArray100.element65 + fixedSizeArray100.element65 + fixedSizeArray100.element83 += fixedSizeArray100.element78 - fixedSizeArray100.element50 + } + let sum = computeSumOfFixedSizeArray100(fixedSizeArray100: &fixedSizeArray100) + check(sum > ElementType(0)) +} + +// This measures read performance of keypaths. +@inline(never) +public func run_testKeyPathReadPerformance(n: Int) { + var fixedSizeArray100 = FixedSizeArrayHolder.shared.fixedSizeArray100 + let iterationMultipier = 25 + + let kp99 = FixedSizeArrayHolder.shared.kp99 + let kp27 = FixedSizeArrayHolder.shared.kp27 + let kp09 = FixedSizeArrayHolder.shared.kp09 + let kp84 = FixedSizeArrayHolder.shared.kp84 + let kp22 = FixedSizeArrayHolder.shared.kp22 + let kp82 = FixedSizeArrayHolder.shared.kp82 + let kp86 = FixedSizeArrayHolder.shared.kp86 + let kp49 = FixedSizeArrayHolder.shared.kp49 + let kp18 = FixedSizeArrayHolder.shared.kp18 + let kp97 = FixedSizeArrayHolder.shared.kp97 + let kp69 = FixedSizeArrayHolder.shared.kp69 + let kp76 = FixedSizeArrayHolder.shared.kp76 + let kp32 = FixedSizeArrayHolder.shared.kp32 + let kp52 = FixedSizeArrayHolder.shared.kp52 + let kp24 = FixedSizeArrayHolder.shared.kp24 + let kp87 = FixedSizeArrayHolder.shared.kp87 + let kp67 = FixedSizeArrayHolder.shared.kp67 + let kp65 = FixedSizeArrayHolder.shared.kp65 + let kp43 = FixedSizeArrayHolder.shared.kp43 + let kp12 = FixedSizeArrayHolder.shared.kp12 + let kp21 = FixedSizeArrayHolder.shared.kp21 + let kp77 = FixedSizeArrayHolder.shared.kp77 + let kp40 = FixedSizeArrayHolder.shared.kp40 + let kp60 = FixedSizeArrayHolder.shared.kp60 + let kp50 = FixedSizeArrayHolder.shared.kp50 + + for t in 1 ... iterationMultipier * n { + fixedSizeArray100.element50 += fixedSizeArray100.element1 + ElementType(t) + fixedSizeArray100.element46 += fixedSizeArray100 + .element63 - fixedSizeArray100[keyPath: kp99] + fixedSizeArray100.element43 += fixedSizeArray100 + .element39 * fixedSizeArray100[keyPath: kp27] + fixedSizeArray100.element81 += fixedSizeArray100 + .element49 / fixedSizeArray100[keyPath: kp09] + fixedSizeArray100.element31 += fixedSizeArray100 + .element90 + fixedSizeArray100[keyPath: kp84] + fixedSizeArray100.element35 += fixedSizeArray100 + .element6 - fixedSizeArray100[keyPath: kp22] + fixedSizeArray100.element14 += fixedSizeArray100 + .element67 * fixedSizeArray100[keyPath: kp82] + fixedSizeArray100.element51 += fixedSizeArray100 + .element40 / fixedSizeArray100[keyPath: kp86] + fixedSizeArray100.element24 += fixedSizeArray100 + .element23 + fixedSizeArray100[keyPath: kp49] + fixedSizeArray100.element90 += fixedSizeArray100 + .element95 - fixedSizeArray100[keyPath: kp18] + fixedSizeArray100.element80 += fixedSizeArray100 + .element45 * fixedSizeArray100[keyPath: kp97] + fixedSizeArray100.element47 += fixedSizeArray100 + .element65 / fixedSizeArray100[keyPath: kp69] + fixedSizeArray100.element92 += fixedSizeArray100 + .element80 + fixedSizeArray100[keyPath: kp76] + fixedSizeArray100.element78 += fixedSizeArray100 + .element32 - fixedSizeArray100[keyPath: kp32] + fixedSizeArray100.element79 += fixedSizeArray100 + .element59 * fixedSizeArray100[keyPath: kp52] + fixedSizeArray100.element46 += fixedSizeArray100 + .element60 / fixedSizeArray100[keyPath: kp24] + fixedSizeArray100.element64 += fixedSizeArray100 + .element41 + fixedSizeArray100[keyPath: kp87] + fixedSizeArray100.element65 += fixedSizeArray100 + .element72 - fixedSizeArray100[keyPath: kp67] + fixedSizeArray100.element19 += fixedSizeArray100 + .element81 * fixedSizeArray100[keyPath: kp65] + fixedSizeArray100.element66 += fixedSizeArray100 + .element55 / fixedSizeArray100[keyPath: kp43] + fixedSizeArray100.element10 += fixedSizeArray100 + .element52 + fixedSizeArray100[keyPath: kp12] + fixedSizeArray100.element81 += fixedSizeArray100 + .element50 - fixedSizeArray100[keyPath: kp21] + fixedSizeArray100.element16 += fixedSizeArray100 + .element80 * fixedSizeArray100[keyPath: kp77] + fixedSizeArray100.element6 += fixedSizeArray100 + .element62 / fixedSizeArray100[keyPath: kp40] + fixedSizeArray100.element26 += fixedSizeArray100 + .element65 + fixedSizeArray100[keyPath: kp60] + fixedSizeArray100.element83 += fixedSizeArray100 + .element78 - fixedSizeArray100[keyPath: kp50] + } + let sum = computeSumOfFixedSizeArray100(fixedSizeArray100: &fixedSizeArray100) + check(sum > ElementType(0)) +} + +// This measures write performance of keypaths. +@inline(never) +public func run_testKeyPathWritePerformance(n: Int) { + var fixedSizeArray100 = FixedSizeArrayHolder.shared.fixedSizeArray100 + let iterationMultipier = 150 + + let kp46 = FixedSizeArrayHolder.shared.kp46 + let kp43 = FixedSizeArrayHolder.shared.kp43 + let kp81 = FixedSizeArrayHolder.shared.kp81 + let kp31 = FixedSizeArrayHolder.shared.kp31 + let kp35 = FixedSizeArrayHolder.shared.kp35 + let kp14 = FixedSizeArrayHolder.shared.kp14 + let kp51 = FixedSizeArrayHolder.shared.kp51 + let kp24 = FixedSizeArrayHolder.shared.kp24 + let kp90 = FixedSizeArrayHolder.shared.kp90 + let kp80 = FixedSizeArrayHolder.shared.kp80 + let kp47 = FixedSizeArrayHolder.shared.kp47 + let kp92 = FixedSizeArrayHolder.shared.kp92 + let kp78 = FixedSizeArrayHolder.shared.kp78 + let kp79 = FixedSizeArrayHolder.shared.kp79 + let kp48 = FixedSizeArrayHolder.shared.kp48 + let kp64 = FixedSizeArrayHolder.shared.kp64 + let kp65 = FixedSizeArrayHolder.shared.kp65 + let kp19 = FixedSizeArrayHolder.shared.kp19 + let kp66 = FixedSizeArrayHolder.shared.kp66 + let kp10 = FixedSizeArrayHolder.shared.kp10 + let kp89 = FixedSizeArrayHolder.shared.kp89 + let kp16 = FixedSizeArrayHolder.shared.kp16 + let kp06 = FixedSizeArrayHolder.shared.kp06 + let kp26 = FixedSizeArrayHolder.shared.kp26 + let kp83 = FixedSizeArrayHolder.shared.kp83 + + for t in 1 ... iterationMultipier * n { + fixedSizeArray100.element50 += fixedSizeArray100.element1 + ElementType(t) + fixedSizeArray100[keyPath: kp46] += fixedSizeArray100.element63 - fixedSizeArray100 + .element99 + fixedSizeArray100[keyPath: kp43] += fixedSizeArray100.element39 * fixedSizeArray100 + .element27 + fixedSizeArray100[keyPath: kp81] += fixedSizeArray100.element49 / fixedSizeArray100 + .element9 + fixedSizeArray100[keyPath: kp31] += fixedSizeArray100.element90 + fixedSizeArray100 + .element84 + fixedSizeArray100[keyPath: kp35] += fixedSizeArray100.element6 - fixedSizeArray100 + .element22 + fixedSizeArray100[keyPath: kp14] += fixedSizeArray100.element67 * fixedSizeArray100 + .element82 + fixedSizeArray100[keyPath: kp51] += fixedSizeArray100.element40 / fixedSizeArray100 + .element86 + fixedSizeArray100[keyPath: kp24] += fixedSizeArray100.element23 + fixedSizeArray100 + .element49 + fixedSizeArray100[keyPath: kp90] += fixedSizeArray100.element95 - fixedSizeArray100 + .element18 + fixedSizeArray100[keyPath: kp80] += fixedSizeArray100.element45 * fixedSizeArray100 + .element97 + fixedSizeArray100[keyPath: kp47] += fixedSizeArray100.element65 / fixedSizeArray100 + .element69 + fixedSizeArray100[keyPath: kp92] += fixedSizeArray100.element80 + fixedSizeArray100 + .element76 + fixedSizeArray100[keyPath: kp78] += fixedSizeArray100.element32 - fixedSizeArray100 + .element32 + fixedSizeArray100[keyPath: kp79] += fixedSizeArray100.element59 * fixedSizeArray100 + .element52 + fixedSizeArray100[keyPath: kp48] += fixedSizeArray100.element60 / fixedSizeArray100 + .element24 + fixedSizeArray100[keyPath: kp64] += fixedSizeArray100.element41 + fixedSizeArray100 + .element87 + fixedSizeArray100[keyPath: kp65] += fixedSizeArray100.element72 - fixedSizeArray100 + .element67 + fixedSizeArray100[keyPath: kp19] += fixedSizeArray100.element81 * fixedSizeArray100 + .element65 + fixedSizeArray100[keyPath: kp66] += fixedSizeArray100.element55 / fixedSizeArray100 + .element43 + fixedSizeArray100[keyPath: kp10] += fixedSizeArray100.element52 + fixedSizeArray100 + .element12 + fixedSizeArray100[keyPath: kp89] += fixedSizeArray100.element50 - fixedSizeArray100 + .element21 + fixedSizeArray100[keyPath: kp16] += fixedSizeArray100.element80 * fixedSizeArray100 + .element77 + fixedSizeArray100[keyPath: kp06] += fixedSizeArray100.element62 / fixedSizeArray100 + .element40 + fixedSizeArray100[keyPath: kp26] += fixedSizeArray100.element65 + fixedSizeArray100 + .element65 + fixedSizeArray100[keyPath: kp83] += fixedSizeArray100.element78 - fixedSizeArray100 + .element50 + } + let sum = computeSumOfFixedSizeArray100(fixedSizeArray100: &fixedSizeArray100) + check(sum > ElementType(0)) +} + +// Intended to showcase the difference in performance between 10 and 100-element structs. +@inline(never) +public func run_testKeyPathSmallStruct(n: Int) { + var fixedSizeArray10 = FixedSizeArrayHolder.shared.fixedSizeArray10 + let iterationMultipier = 25 + + let kp0 = FixedSizeArrayHolder.shared.kp0 + let kp1 = FixedSizeArrayHolder.shared.kp1 + let kp2 = FixedSizeArrayHolder.shared.kp2 + let kp3 = FixedSizeArrayHolder.shared.kp3 + let kp4 = FixedSizeArrayHolder.shared.kp4 + let kp5 = FixedSizeArrayHolder.shared.kp5 + let kp6 = FixedSizeArrayHolder.shared.kp6 + let kp7 = FixedSizeArrayHolder.shared.kp7 + let kp8 = FixedSizeArrayHolder.shared.kp8 + let kp9 = FixedSizeArrayHolder.shared.kp9 + + for t in 1 ... iterationMultipier * n { + fixedSizeArray10.element0 += fixedSizeArray10.element1 + ElementType(t) + fixedSizeArray10.element6 += fixedSizeArray10 + .element3 - fixedSizeArray10[keyPath: kp9] + fixedSizeArray10.element3 += fixedSizeArray10 + .element9 * fixedSizeArray10[keyPath: kp7] + fixedSizeArray10.element1 += fixedSizeArray10 + .element9 / fixedSizeArray10[keyPath: kp9] + fixedSizeArray10.element1 += fixedSizeArray10 + .element0 + fixedSizeArray10[keyPath: kp4] + fixedSizeArray10.element5 += fixedSizeArray10 + .element6 - fixedSizeArray10[keyPath: kp2] + fixedSizeArray10.element4 += fixedSizeArray10 + .element7 * fixedSizeArray10[keyPath: kp2] + fixedSizeArray10.element1 += fixedSizeArray10 + .element0 / fixedSizeArray10[keyPath: kp6] + fixedSizeArray10.element4 += fixedSizeArray10 + .element3 + fixedSizeArray10[keyPath: kp9] + fixedSizeArray10.element0 += fixedSizeArray10 + .element5 - fixedSizeArray10[keyPath: kp8] + fixedSizeArray10.element0 += fixedSizeArray10 + .element5 * fixedSizeArray10[keyPath: kp7] + fixedSizeArray10.element7 += fixedSizeArray10 + .element5 / fixedSizeArray10[keyPath: kp9] + fixedSizeArray10.element2 += fixedSizeArray10 + .element0 + fixedSizeArray10[keyPath: kp6] + fixedSizeArray10.element8 += fixedSizeArray10 + .element2 - fixedSizeArray10[keyPath: kp2] + fixedSizeArray10.element9 += fixedSizeArray10 + .element9 * fixedSizeArray10[keyPath: kp2] + fixedSizeArray10.element6 += fixedSizeArray10 + .element0 / fixedSizeArray10[keyPath: kp4] + fixedSizeArray10.element4 += fixedSizeArray10 + .element1 + fixedSizeArray10[keyPath: kp7] + fixedSizeArray10.element5 += fixedSizeArray10 + .element2 - fixedSizeArray10[keyPath: kp7] + fixedSizeArray10.element9 += fixedSizeArray10 + .element1 * fixedSizeArray10[keyPath: kp5] + fixedSizeArray10.element6 += fixedSizeArray10 + .element5 / fixedSizeArray10[keyPath: kp3] + fixedSizeArray10.element0 += fixedSizeArray10 + .element2 + fixedSizeArray10[keyPath: kp2] + fixedSizeArray10.element1 += fixedSizeArray10 + .element0 - fixedSizeArray10[keyPath: kp1] + fixedSizeArray10.element6 += fixedSizeArray10 + .element0 * fixedSizeArray10[keyPath: kp7] + fixedSizeArray10.element6 += fixedSizeArray10 + .element2 / fixedSizeArray10[keyPath: kp0] + fixedSizeArray10.element6 += fixedSizeArray10 + .element5 + fixedSizeArray10[keyPath: kp0] + fixedSizeArray10.element3 += fixedSizeArray10 + .element8 - fixedSizeArray10[keyPath: kp0] + } + let sum = computeSumOfFixedSizeArray10(fixedSizeArray10: &fixedSizeArray10) + blackHole(sum) +} + +// Benchmarks traversal through `KeyPathComponents` of type `.mutatingGetset`. +public func run_KeyPathMutatingGetset(n: Int) { + var sum = 0 + var index = 0 + let iterationMultipier = 200 + + let destinationKeyPath = FixedSizeArrayHolder.shared.keypathForMutatingGetSet + let elementCount = FixedSizeArrayHolder.shared.arrayForMutatingGetset.count + for _ in 1 ... iterationMultipier * n { + let element = FixedSizeArrayHolder.shared.arrayForMutatingGetset[index] + sum += element[keyPath: destinationKeyPath] + index = (index + 1) % elementCount + } + check(sum == iterationMultipier * n * expectedIntForNestedItems) +} + +// Benchmarks traversal through `KeyPathComponents` of type `.get`. +public func run_KeyPathGet(n: Int) { + var sum = 0 + var index = 0 + let iterationMultipier = 200 + + let destinationKeyPath = FixedSizeArrayHolder.shared.keypathForGet + let elementCount = FixedSizeArrayHolder.shared.arrayForGet.count + for _ in 1 ... iterationMultipier * n { + let element = FixedSizeArrayHolder.shared.arrayForGet[index] + sum += element[keyPath: destinationKeyPath] + index = (index + 1) % elementCount + } + check(sum == iterationMultipier * n * expectedIntForNestedItems) +} + +// Benchmarks traversal through `KeyPathComponents` of type `.optionalChain,` `.optionalForce,` and `.optionalWrap`. +// Note: The decision that `optionalChains` and `optionalForces` are merged into a single benchmark is arbitrary. +// TODO: Write a benchmark with more than one `.optionalWrap`. +public func run_KeyPathOptionals(n: Int) { + var sum = 0 + var index = 0 + let iterationMultipier = 200 + + let destinationKeyPath = FixedSizeArrayHolder.shared.keypathForOptional + let elementCount = FixedSizeArrayHolder.shared.arrayForOptionals.count + for _ in 1 ... iterationMultipier * n { + let element = FixedSizeArrayHolder.shared.arrayForOptionals[index] + sum += element[keyPath: destinationKeyPath]! + index = (index + 1) % elementCount + } + check(sum == iterationMultipier * n * expectedIntForNestedItems) +} + +// Benchmarks traversal through `KeyPathComponents` of type `.class`. +public func run_KeyPathNestedClasses(n: Int) { + var sum = 0 + var index = 0 + let iterationMultipier = 200 + + let destinationKeyPath = FixedSizeArrayHolder.shared.keypathForNestedClasses + let elementCount = FixedSizeArrayHolder.shared.arrayForNestedClasses.count + for _ in 1 ... iterationMultipier * n { + let element = FixedSizeArrayHolder.shared.arrayForNestedClasses[index] + sum += element[keyPath: destinationKeyPath] + index = (index + 1) % elementCount + } + check(sum == iterationMultipier * n * expectedIntForNestedItems) +} + +// Benchmarks traversal through `KeyPathComponents` of type `.nonmutatingGetset`. +// Note: There may be other, simpler ways of getting consecutive `.nonmutatingGetset`. components. +public func run_KeyPathNonmutatingGetset(n: Int) { + var sum = 0 + var index = 0 + let iterationMultipier = 200 + + let destinationKeyPath = FixedSizeArrayHolder.shared.keypathForNonMutatingGetset + let elementCount = FixedSizeArrayHolder.shared.arrayForNonMutatingGetset.count + for _ in 1 ... iterationMultipier * n { + let element = FixedSizeArrayHolder.shared.arrayForNonMutatingGetset[index] + sum += element[keyPath: destinationKeyPath] + index = (index + 1) % elementCount + } + check(sum == iterationMultipier * n * expectedIntForNestedItems) +} diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift index 9470afc27d258..d330e60eb69cd 100644 --- a/benchmark/utils/main.swift +++ b/benchmark/utils/main.swift @@ -97,6 +97,7 @@ import IntegerParsing import Integrate import IterateData import Join +import KeyPathPerformanceTests import LazyFilter import LinkedList import LuhnAlgoEager @@ -279,6 +280,7 @@ register(Integrate.benchmarks) register(IterateData.benchmarks) register(Join.benchmarks) register(LazyFilter.benchmarks) +register(KeyPathPerformanceTests.benchmarks) register(LinkedList.benchmarks) register(LuhnAlgoEager.benchmarks) register(LuhnAlgoLazy.benchmarks) From 0bdef6e845c0bff00fe6f88c3d1fd9eaab93392c Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 24 Aug 2022 12:52:52 -0700 Subject: [PATCH 361/491] [test] IRGen/opaque_result_alwaysInlineIntoClient: Try again --- test/IRGen/opaque_result_alwaysInlineIntoClient.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/IRGen/opaque_result_alwaysInlineIntoClient.swift b/test/IRGen/opaque_result_alwaysInlineIntoClient.swift index 2a35ff951f4ed..82674435a2fd3 100644 --- a/test/IRGen/opaque_result_alwaysInlineIntoClient.swift +++ b/test/IRGen/opaque_result_alwaysInlineIntoClient.swift @@ -1,14 +1,23 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/AlwaysInlineIntoWithOpaque.swiftmodule -module-name AlwaysInlineIntoWithOpaque %S/Inputs/AlwaysInlineIntoWithOpaque.swift -o %t/%target-library-name(AlwaysInlineIntoWithOpaque) +// RUN: %target-codesign %t/%target-library-name(AlwaysInlineIntoWithOpaque) // RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -lAlwaysInlineIntoWithOpaque -module-name main -I %t -L %t %s -o %t/a.out +// RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out | %FileCheck %s // RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/AlwaysInlineIntoWithOpaque.swiftmodule -module-name AlwaysInlineIntoWithOpaque %S/Inputs/AlwaysInlineIntoWithOpaqueReplacement.swift -o %t/%target-library-name(AlwaysInlineIntoWithOpaque) +// RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: OS=macosx && (CPU=x86_64 || CPU=arm64) // REQUIRES: executable_test +// This test requires executable tests to be run on the same machine as the +// compiler, as it links with a dylib that it doesn't arrange to get uploaded +// to remote executors. +// (rdar://97995151) +// UNSUPPORTED: remote_run || device_run + import AlwaysInlineIntoWithOpaque public func test() { From 11eee5574f4c4537d91f32a9fb94e31a46dfb593 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Wed, 24 Aug 2022 14:13:43 -0700 Subject: [PATCH 362/491] Tests: Disable attr_backDeploy_evolution.swift for back_deployment_runtime. Resolves rdar://99100512 --- test/attr/attr_backDeploy_evolution.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/attr/attr_backDeploy_evolution.swift b/test/attr/attr_backDeploy_evolution.swift index 26497ddbbfc72..f986db5f1d263 100644 --- a/test/attr/attr_backDeploy_evolution.swift +++ b/test/attr/attr_backDeploy_evolution.swift @@ -32,6 +32,10 @@ // REQUIRES: executable_test // REQUIRES: OS=macosx +// The deployment targets and availability versions hardcoded into this test +// aren't compatible with the environment of the back deployment CI bots. +// UNSUPPORTED: back_deployment_runtime + // ---- (0) Prepare SDK // RUN: %empty-directory(%t) // RUN: %empty-directory(%t/SDK_ABI) From 8f421a7e0691a86502bbb3661938c6faaa2a2fee Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Wed, 24 Aug 2022 21:12:23 +0200 Subject: [PATCH 363/491] [SourceKit] Fix a crash because the API for retrieving intherited protocols of a ProtocolDecl changed apple/swift#60716 changed `NominalTypeDecl::getAllProtocols` to no longer work on `ProtocolDecl`. Add a new wrapper to Refactoring.cpp that dispatches to either `getInheritedProtocols` or `getAllProtocols` depending on whether the type is a protocol or not. rdar://99096663 --- lib/IDE/Refactoring.cpp | 44 +++++++++++++------ test/SourceKit/CursorInfo/rdar_99096663.swift | 4 ++ 2 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 test/SourceKit/CursorInfo/rdar_99096663.swift diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp index 250bad9fe3c11..a8c2b73ab0060 100644 --- a/lib/IDE/Refactoring.cpp +++ b/lib/IDE/Refactoring.cpp @@ -3309,6 +3309,18 @@ bool RefactoringActionMemberwiseInitLocalRefactoring::performChange() { return false; } +/// If \p NTD is a protocol, return all the protocols it inherits from. If it's +/// a type, return all the protocols it conforms to. +static SmallVector getAllProtocols(NominalTypeDecl *NTD) { + if (auto Proto = dyn_cast(NTD)) { + return SmallVector( + Proto->getInheritedProtocols().begin(), + Proto->getInheritedProtocols().end()); + } else { + return NTD->getAllProtocols(); + } +} + class AddEquatableContext { /// Declaration context @@ -3366,19 +3378,23 @@ class AddEquatableContext { std::vector getUserAccessibleProperties(); public: + AddEquatableContext(NominalTypeDecl *Decl) + : DC(Decl), Adopter(Decl->getDeclaredType()), + StartLoc(Decl->getBraces().Start), + ProtocolsLocations(Decl->getInherited()), + Protocols(getAllProtocols(Decl)), + ProtInsertStartLoc(Decl->getNameLoc()), + StoredProperties(Decl->getStoredProperties()), + Range(Decl->getMembers()){}; - AddEquatableContext(NominalTypeDecl *Decl) : DC(Decl), - Adopter(Decl->getDeclaredType()), StartLoc(Decl->getBraces().Start), - ProtocolsLocations(Decl->getInherited()), - Protocols(Decl->getAllProtocols()), ProtInsertStartLoc(Decl->getNameLoc()), - StoredProperties(Decl->getStoredProperties()), Range(Decl->getMembers()) {}; - - AddEquatableContext(ExtensionDecl *Decl) : DC(Decl), - Adopter(Decl->getExtendedType()), StartLoc(Decl->getBraces().Start), - ProtocolsLocations(Decl->getInherited()), - Protocols(Decl->getExtendedNominal()->getAllProtocols()), - ProtInsertStartLoc(Decl->getExtendedTypeRepr()->getEndLoc()), - StoredProperties(Decl->getExtendedNominal()->getStoredProperties()), Range(Decl->getMembers()) {}; + AddEquatableContext(ExtensionDecl *Decl) + : DC(Decl), Adopter(Decl->getExtendedType()), + StartLoc(Decl->getBraces().Start), + ProtocolsLocations(Decl->getInherited()), + Protocols(getAllProtocols(Decl->getExtendedNominal())), + ProtInsertStartLoc(Decl->getExtendedTypeRepr()->getEndLoc()), + StoredProperties(Decl->getExtendedNominal()->getStoredProperties()), + Range(Decl->getMembers()){}; AddEquatableContext() : DC(nullptr), Adopter(), ProtocolsLocations(), Protocols(), StoredProperties(), Range(nullptr, nullptr) {}; @@ -3583,11 +3599,11 @@ class AddCodableContext { public: AddCodableContext(NominalTypeDecl *Decl) : DC(Decl), StartLoc(Decl->getBraces().Start), - Protocols(Decl->getAllProtocols()), Range(Decl->getMembers()){}; + Protocols(getAllProtocols(Decl)), Range(Decl->getMembers()){}; AddCodableContext(ExtensionDecl *Decl) : DC(Decl), StartLoc(Decl->getBraces().Start), - Protocols(Decl->getExtendedNominal()->getAllProtocols()), + Protocols(getAllProtocols(Decl->getExtendedNominal())), Range(Decl->getMembers()){}; AddCodableContext() : DC(nullptr), Protocols(), Range(nullptr, nullptr){}; diff --git a/test/SourceKit/CursorInfo/rdar_99096663.swift b/test/SourceKit/CursorInfo/rdar_99096663.swift new file mode 100644 index 0000000000000..95327d3a6f824 --- /dev/null +++ b/test/SourceKit/CursorInfo/rdar_99096663.swift @@ -0,0 +1,4 @@ +// This should not crash +// RUN: %sourcekitd-test -req=cursor -cursor-action -pos=4:11 %s -- %s + +extension RandomAccessCollection From afb78b402d68d206d7a2b4c95044df0bbff0744a Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 24 Aug 2022 14:27:13 -0700 Subject: [PATCH 364/491] [Tests] NFC: Disable remote/device execution of opaque result type cross module test Resolves: rdar://99100097 --- .../opaque_with_availability_cross_module.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Serialization/opaque_with_availability_cross_module.swift b/test/Serialization/opaque_with_availability_cross_module.swift index 5f04c136c5435..936075855a4fc 100644 --- a/test/Serialization/opaque_with_availability_cross_module.swift +++ b/test/Serialization/opaque_with_availability_cross_module.swift @@ -6,6 +6,11 @@ // REQUIRES: OS=macosx && (CPU=x86_64 || CPU=arm64) // REQUIRES: executable_test +// This requires executable tests to be run on the same machine as the compiler, +// as it links with a dylib that it doesn't arrange to get uploaded to remote executors. +// (rdar://99051588) +// UNSUPPORTED: remote_run || device_run + import LimitedAvailOpaque struct S: P { From 70213f0630ddc630b9e2f1a74bb49bf2a5797fa1 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Wed, 24 Aug 2022 14:52:14 -0700 Subject: [PATCH 365/491] [SILInliner] Handled null access storage base. During inlining, lexical-ness of arguments is preserved. In the case of address arguments that come from alloc_stacks, the alloc_stacks are marked lexical. The base of the storage which is passed to the address is obtained via AccessStorageWithBase. In some circumstances, a base is not found. Handled that case by changing a dyn_cast of the base to a dyn_cast_or_null. rdar://99087653 --- lib/SILOptimizer/Utils/SILInliner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp index 56c04b8160859..d80af2809a2e3 100644 --- a/lib/SILOptimizer/Utils/SILInliner.cpp +++ b/lib/SILOptimizer/Utils/SILInliner.cpp @@ -462,7 +462,7 @@ void SILInlineCloner::cloneInline(ArrayRef AppliedArgs) { continue; auto storage = AccessStorageWithBase::compute(callArg); - if (auto *asi = dyn_cast(storage.base)) + if (auto *asi = dyn_cast_or_null(storage.base)) asi->setIsLexical(); } else { // Insert begin/end borrow for guaranteed arguments. From bd2771e75633493f3b2f6f945166dbffc3de93a3 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Wed, 24 Aug 2022 23:52:21 +0200 Subject: [PATCH 366/491] [CodeComplete] Show global completions from modules that are imported as `@_spi` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a module is imported as `@_spi`, we didn’t receive any global completions from it. rdar://99027179 --- include/swift/IDE/CodeCompletionCache.h | 26 +++++++- lib/IDE/CodeCompletion.cpp | 20 +++++- lib/IDE/CodeCompletionCache.cpp | 19 +++++- test/IDE/complete_from_swift_module_spi.swift | 61 +++++++++++++++++++ 4 files changed, 118 insertions(+), 8 deletions(-) create mode 100644 test/IDE/complete_from_swift_module_spi.swift diff --git a/include/swift/IDE/CodeCompletionCache.h b/include/swift/IDE/CodeCompletionCache.h index a595b13fa3d36..4fd97e15363a4 100644 --- a/include/swift/IDE/CodeCompletionCache.h +++ b/include/swift/IDE/CodeCompletionCache.h @@ -45,6 +45,8 @@ class CodeCompletionCache { bool ResultsHaveLeadingDot; bool ForTestableLookup; bool ForPrivateImportLookup; + /// Must be sorted alphabetically for stable identity. + llvm::SmallVector SpiGroups; bool AddInitsInToplevel; bool AddCallWithNoDefaultArgs; bool Annotated; @@ -56,6 +58,7 @@ class CodeCompletionCache { LHS.ResultsHaveLeadingDot == RHS.ResultsHaveLeadingDot && LHS.ForTestableLookup == RHS.ForTestableLookup && LHS.ForPrivateImportLookup == RHS.ForPrivateImportLookup && + LHS.SpiGroups == RHS.SpiGroups && LHS.AddInitsInToplevel == RHS.AddInitsInToplevel && LHS.AddCallWithNoDefaultArgs == RHS.AddCallWithNoDefaultArgs && LHS.Annotated == RHS.Annotated; @@ -125,16 +128,35 @@ template<> struct DenseMapInfo { using KeyTy = swift::ide::CodeCompletionCache::Key; static inline KeyTy getEmptyKey() { - return KeyTy{"", "", {}, false, false, false, false, false, false}; + return KeyTy{/*ModuleFilename=*/"", + /*ModuleName=*/"", + /*AccessPath=*/{}, + /*ResultsHaveLeadingDot=*/false, + /*ForTestableLookup=*/false, + /*ForPrivateImportLookup=*/false, + /*SpiGroups=*/{}, + /*AddInitsInToplevel=*/false, + /*AddCallWithNoDefaultArgs=*/false, + /*Annotated=*/false}; } static inline KeyTy getTombstoneKey() { - return KeyTy{"", "", {}, true, false, false, false, false, false}; + return KeyTy{/*ModuleFilename=*/"", + /*ModuleName=*/"", + /*AccessPath=*/{}, + /*ResultsHaveLeadingDot=*/true, + /*ForTestableLookup=*/false, + /*ForPrivateImportLookup=*/false, + /*SpiGroups=*/{}, + /*AddInitsInToplevel=*/false, + /*AddCallWithNoDefaultArgs=*/false, + /*Annotated=*/false}; } static unsigned getHashValue(const KeyTy &Val) { return llvm::hash_combine( Val.ModuleFilename, Val.ModuleName, llvm::hash_combine_range(Val.AccessPath.begin(), Val.AccessPath.end()), Val.ResultsHaveLeadingDot, Val.ForTestableLookup, + llvm::hash_combine_range(Val.SpiGroups.begin(), Val.SpiGroups.end()), Val.ForPrivateImportLookup, Val.AddInitsInToplevel, Val.AddCallWithNoDefaultArgs, Val.Annotated); } diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index ec9a158dd3fbf..4f8b8b4842ef9 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -1301,6 +1301,16 @@ void swift::ide::deliverCompletionResults( // ModuleFilename can be empty if something strange happened during // module loading, for example, the module file is corrupted. if (!ModuleFilename.empty()) { + llvm::SmallVector spiGroups; + for (auto Import : SF.getImports()) { + if (Import.module.importedModule == TheModule) { + for (auto SpiGroup : Import.spiGroups) { + spiGroups.push_back(SpiGroup.str().str()); + } + break; + } + } + llvm::sort(spiGroups); CodeCompletionCache::Key K{ ModuleFilename.str(), std::string(TheModule->getName()), @@ -1312,6 +1322,7 @@ void swift::ide::deliverCompletionResults( SF.hasTestableOrPrivateImport( AccessLevel::Internal, TheModule, SourceFile::ImportQueryKind::PrivateOnly), + spiGroups, CompletionContext.getAddInitsToTopLevel(), CompletionContext.addCallWithNoDefaultArgs(), CompletionContext.getAnnotateResult()}; @@ -1351,9 +1362,12 @@ void swift::ide::deliverCompletionResults( // Add results for all imported modules. SmallVector Imports; SF.getImportedModules( - Imports, {ModuleDecl::ImportFilterKind::Exported, - ModuleDecl::ImportFilterKind::Default, - ModuleDecl::ImportFilterKind::ImplementationOnly}); + Imports, { + ModuleDecl::ImportFilterKind::Exported, + ModuleDecl::ImportFilterKind::Default, + ModuleDecl::ImportFilterKind::ImplementationOnly, + ModuleDecl::ImportFilterKind::SPIAccessControl, + }); for (auto Imported : Imports) { for (auto Import : namelookup::getAllImports(Imported.importedModule)) diff --git a/lib/IDE/CodeCompletionCache.cpp b/lib/IDE/CodeCompletionCache.cpp index 6ff2b888b4447..6706928e6fcf1 100644 --- a/lib/IDE/CodeCompletionCache.cpp +++ b/lib/IDE/CodeCompletionCache.cpp @@ -484,6 +484,12 @@ static std::string getName(StringRef cacheDirectory, << (K.AddInitsInToplevel ? "-inits" : "") << (K.AddCallWithNoDefaultArgs ? "-nodefaults" : "") << (K.Annotated ? "-annotated" : ""); + if (K.SpiGroups.size() > 0) { + OSS << "-spi"; + for (auto SpiGroup : K.SpiGroups) { + OSS << "-" << SpiGroup; + } + } // name[-access-path-components] for (StringRef component : K.AccessPath) @@ -548,9 +554,16 @@ OnDiskCodeCompletionCache::getFromFile(StringRef filename) { return None; // Make up a key for readCachedModule. - CodeCompletionCache::Key K{filename.str(), "", {}, - false, false, false, - false, false, false}; + CodeCompletionCache::Key K{/*ModuleFilename=*/filename.str(), + /*ModuleName=*/"", + /*AccessPath=*/{}, + /*ResultsHaveLeadingDot=*/false, + /*ForTestableLookup=*/false, + /*ForPrivateImportLookup=*/false, + /*SpiGroups=*/{}, + /*AddInitsInToplevel=*/false, + /*AddCallWithNoDefaultArgs=*/false, + /*Annotated=*/false}; // Read the cached results. auto V = CodeCompletionCache::createValue(); diff --git a/test/IDE/complete_from_swift_module_spi.swift b/test/IDE/complete_from_swift_module_spi.swift new file mode 100644 index 0000000000000..e7ee98f50b07e --- /dev/null +++ b/test/IDE/complete_from_swift_module_spi.swift @@ -0,0 +1,61 @@ +// RUN: %empty-directory(%t/split) +// RUN: %empty-directory(%t/build) +// RUN: %{python} %utils/split_file.py -o %t/split %s + +// RUN: %target-swift-frontend -emit-module -o %t/build %t/split/pck.swift + +// First SPI completion then completion in file without SPI import +// RUN: %empty-directory(%t/cc-cache) +// RUN: %target-swift-ide-test -code-completion -completion-cache-path %t/cc-cache -source-filename %t/split/with-spi-import.swift -I %t/build -code-completion-token=COMPLETE | %FileCheck %s --check-prefix=WITH_SPI +// RUN: %target-swift-ide-test -code-completion -completion-cache-path %t/cc-cache -source-filename %t/split/with-different-spi-import.swift -I %t/build -code-completion-token=COMPLETE | %FileCheck %s --check-prefix=WITHOUT_SPI +// RUN: %target-swift-ide-test -code-completion -completion-cache-path %t/cc-cache -source-filename %t/split/with-normal-import.swift -I %t/build -code-completion-token=COMPLETE | %FileCheck %s --check-prefix=WITHOUT_SPI + +// First completion in file without SPI import, then with SPI import +// RUN: %empty-directory(%t/cc-cache) +// RUN: %target-swift-ide-test -code-completion -completion-cache-path %t/cc-cache -source-filename %t/split/with-normal-import.swift -I %t/build -code-completion-token=COMPLETE | %FileCheck %s --check-prefix=WITHOUT_SPI +// RUN: %target-swift-ide-test -code-completion -completion-cache-path %t/cc-cache -source-filename %t/split/with-different-spi-import.swift -I %t/build -code-completion-token=COMPLETE | %FileCheck %s --check-prefix=WITHOUT_SPI +// RUN: %target-swift-ide-test -code-completion -completion-cache-path %t/cc-cache -source-filename %t/split/with-spi-import.swift -I %t/build -code-completion-token=COMPLETE | %FileCheck %s --check-prefix=WITH_SPI + +// WITH_SPI: Begin completions +// WITH_SPI-DAG: Decl[FreeFunction]/OtherModule[pck]: apiFunc()[#Void#]; name=apiFunc() +// WITH_SPI-DAG: Decl[FreeFunction]/OtherModule[pck]: spiFunc()[#Void#]; name=spiFunc() +// WITH_SPI: End completions + +// WITHOUT_SPI: Begin completions +// WITHOUT_SPI-NOT: spiFunc +// WITHOUT_SPI-DAG: Decl[FreeFunction]/OtherModule[pck]: apiFunc()[#Void#]; name=apiFunc() +// WITHOUT_SPI-NOT: spiFunc +// WITHOUT_SPI: End completions + + +// BEGIN pck.swift + +public func apiFunc() {} + +@_spi(MySPI) +public func spiFunc() {} + +// BEGIN with-spi-import.swift + +@_spi(MySPI) import pck + +func test() { + #^COMPLETE^# +} + +// BEGIN with-different-spi-import.swift + +@_spi(OtherSPI) import pck + +func test() { + #^COMPLETE^# +} + + +// BEGIN with-normal-import.swift + +import pck + +func test() { + #^COMPLETE^# +} From e9450cf80be619da96e92ecfad2465fa7f4bc037 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 23 Aug 2022 10:00:22 -0700 Subject: [PATCH 367/491] [interop][SwiftToCxx] add a test to print out empty Swift stdlib module --- lib/PrintAsClang/ModuleContentsWriter.cpp | 4 ++++ test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift diff --git a/lib/PrintAsClang/ModuleContentsWriter.cpp b/lib/PrintAsClang/ModuleContentsWriter.cpp index 8a9dd1e5b5a5b..0e5b54696acd9 100644 --- a/lib/PrintAsClang/ModuleContentsWriter.cpp +++ b/lib/PrintAsClang/ModuleContentsWriter.cpp @@ -281,6 +281,10 @@ class ModuleWriter { forwardDeclare(ED); } else if (isa(TD)) { llvm_unreachable("should not see type params here"); + } else if (isa(TD) && + TD->getModuleContext()->isStdlibModule()) { + // stdlib has some @_cdecl functions with structs. + return; } else { assert(false && "unknown local type decl"); } diff --git a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift new file mode 100644 index 0000000000000..d9a1c6ca3a9fc --- /dev/null +++ b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift @@ -0,0 +1,8 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -parse-as-library %platform-module-dir/Swift.swiftmodule/%module-target-triple.swiftinterface -enable-library-evolution -disable-objc-attr-requires-foundation-module -typecheck -module-name Swift -parse-stdlib -enable-experimental-cxx-interop -emit-clang-header-path %t/Swift.h -experimental-skip-all-function-bodies +// RUN: %FileCheck %s < %t/Swift.h + +// RUN: %check-interop-cxx-header-in-clang(%t/Swift.h -Wno-unused-private-field -Wno-unused-function) + +// CHECK: namespace Swift { +// CHECK: } // namespace Swift From c1e154a9cb5f6001f0cf3e06ac6db9bd4261ba01 Mon Sep 17 00:00:00 2001 From: YOCKOW Date: Thu, 25 Aug 2022 16:08:36 +0900 Subject: [PATCH 368/491] [Gardening] Remove trailing whitespaces in Python scripts. (W291) That has been marked as 'FIXME' for three years. This commit fixes it. --- .flake8 | 3 --- benchmark/scripts/create_benchmark.py | 2 +- utils/build_swift/build_swift/driver_arguments.py | 2 +- utils/build_swift/build_swift/presets.py | 4 ++-- utils/gyb_syntax_support/CommonNodes.py | 2 +- utils/gyb_syntax_support/ExprNodes.py | 8 ++++---- utils/gyb_syntax_support/Node.py | 8 ++++---- utils/gyb_syntax_support/StmtNodes.py | 4 ++-- utils/gyb_syntax_support/Token.py | 4 ++-- utils/gyb_syntax_support/__init__.py | 2 +- utils/scale-test | 2 +- .../swift_build_support/build_script_invocation.py | 2 +- .../swift_build_support/products/swiftsyntax.py | 12 ++++++------ utils/update_checkout/tests/test_update_worktree.py | 8 ++++---- .../update_checkout/update_checkout.py | 2 +- 15 files changed, 31 insertions(+), 34 deletions(-) diff --git a/.flake8 b/.flake8 index 549c9aa559695..8cdd12811f02c 100644 --- a/.flake8 +++ b/.flake8 @@ -51,9 +51,6 @@ ignore = # compliant (https://github.com/psf/black#slices). E203, - # FIXME: We should not have trailing whitespace. - W291, - # Line breaks before binary operators are not explicitly disallowed in # PEP8, rather it should be consistent throughout the project. The black # tool puts them on new lines which is to be considered a best practice diff --git a/benchmark/scripts/create_benchmark.py b/benchmark/scripts/create_benchmark.py index e097d8f799a63..230e46f2adfb9 100755 --- a/benchmark/scripts/create_benchmark.py +++ b/benchmark/scripts/create_benchmark.py @@ -61,7 +61,7 @@ def create_benchmark_file(name): def add_import_benchmark(name): - """Adds an `import` statement to the `main.swift` file for the new + """Adds an `import` statement to the `main.swift` file for the new benchmark. """ relative_path = create_relative_path("../utils/main.swift") diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index 6f8bddb019c68..801f1ddc9c8be 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -352,7 +352,7 @@ def create_argument_parser(): help='enable code coverage analysis in Swift (false, not-merged, ' 'merged).') - option('--swift-disable-dead-stripping', toggle_true, + option('--swift-disable-dead-stripping', toggle_true, help="Turn off Darwin-specific dead stripping for Swift host tools") option('--build-subdir', store, diff --git a/utils/build_swift/build_swift/presets.py b/utils/build_swift/build_swift/presets.py index afb77bdaba03d..af70f15914be8 100644 --- a/utils/build_swift/build_swift/presets.py +++ b/utils/build_swift/build_swift/presets.py @@ -352,9 +352,9 @@ def _get_preset(self, name): def _interpolate_preset_vars(self, preset, vars): interpolated_options = [] for (name, value) in preset.options: - # If the option is a key-value pair, e.g. + # If the option is a key-value pair, e.g. # install-destdir=%(install_dir)s - # interpolate the value. If it is a raw option, e.g. + # interpolate the value. If it is a raw option, e.g. # %(some_flag)s # is a raw option without a value, expand the name. if value: diff --git a/utils/gyb_syntax_support/CommonNodes.py b/utils/gyb_syntax_support/CommonNodes.py index daaa6b8f94544..c37eb3bce869d 100644 --- a/utils/gyb_syntax_support/CommonNodes.py +++ b/utils/gyb_syntax_support/CommonNodes.py @@ -59,7 +59,7 @@ Child('LeftBrace', kind='LeftBraceToken'), Child('Statements', kind='CodeBlockItemList', collection_element_name='Statement', is_indented=True), - Child('RightBrace', kind='RightBraceToken', + Child('RightBrace', kind='RightBraceToken', requires_leading_newline=True), ]), diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py index 8224f72ea0887..9a5a13a687485 100644 --- a/utils/gyb_syntax_support/ExprNodes.py +++ b/utils/gyb_syntax_support/ExprNodes.py @@ -446,7 +446,7 @@ Node('ClosureSignature', kind='Syntax', children=[ - Child('Attributes', kind='AttributeList', + Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), Child('Capture', kind='ClosureCaptureSignature', is_optional=True), @@ -568,7 +568,7 @@ traits=['Parenthesized'], children=[ Child('Backslash', kind='BackslashToken'), - Child('Delimiter', kind='RawStringDelimiterToken', + Child('Delimiter', kind='RawStringDelimiterToken', is_optional=True), Child('LeftParen', kind='LeftParenToken', classification='StringInterpolationAnchor', @@ -581,7 +581,7 @@ # e.g. "abc \(foo()) def" Node('StringLiteralExpr', kind='Expr', children=[ - Child('OpenDelimiter', kind='RawStringDelimiterToken', + Child('OpenDelimiter', kind='RawStringDelimiterToken', is_optional=True), Child('OpenQuote', kind='Token', token_choices=[ @@ -595,7 +595,7 @@ 'StringQuoteToken', 'MultilineStringQuoteToken', ]), - Child('CloseDelimiter', kind='RawStringDelimiterToken', + Child('CloseDelimiter', kind='RawStringDelimiterToken', is_optional=True), ]), diff --git a/utils/gyb_syntax_support/Node.py b/utils/gyb_syntax_support/Node.py index f9531374c859c..2b341a0ec03c2 100644 --- a/utils/gyb_syntax_support/Node.py +++ b/utils/gyb_syntax_support/Node.py @@ -13,7 +13,7 @@ class Node(object): def __init__(self, name, description=None, kind=None, traits=None, children=[], element=None, element_name=None, - element_choices=None, omit_when_empty=False, + element_choices=None, omit_when_empty=False, elements_separated_by_newline=False): self.syntax_kind = name self.element_name = element_name @@ -24,7 +24,7 @@ def __init__(self, name, description=None, kind=None, traits=None, self.traits = traits or [] self.children = [] - # Add implicitly generated UnexpectedNodes children in between any two + # Add implicitly generated UnexpectedNodes children in between any two # defined children if kind != 'SyntaxCollection': for i in range(2 * len(children)): @@ -35,8 +35,8 @@ def __init__(self, name, description=None, kind=None, traits=None, name = 'UnexpectedBetween%sAnd%s' % \ (children[int(i / 2) - 1].name, children[int(i / 2)].name) self.children.append(Child( - name, - kind='UnexpectedNodes', + name, + kind='UnexpectedNodes', collection_element_name=name, is_optional=True )) diff --git a/utils/gyb_syntax_support/StmtNodes.py b/utils/gyb_syntax_support/StmtNodes.py index f1ba2ae9e1b5d..a78d4bb0dee45 100644 --- a/utils/gyb_syntax_support/StmtNodes.py +++ b/utils/gyb_syntax_support/StmtNodes.py @@ -75,14 +75,14 @@ Child('GuardResult', kind='Expr'), ]), - # for-in-stmt -> label? ':'? + # for-in-stmt -> label? ':'? # 'for' 'try'? 'await'? 'case'? pattern 'in' expr 'where'? # expr code-block ';'? Node('ForInStmt', kind='Stmt', traits=['WithCodeBlock'], children=[ Child('ForKeyword', kind='ForToken'), - Child('TryKeyword', kind='TryToken', + Child('TryKeyword', kind='TryToken', is_optional=True), Child('AwaitKeyword', kind='IdentifierToken', classification='Keyword', diff --git a/utils/gyb_syntax_support/Token.py b/utils/gyb_syntax_support/Token.py index d21fde0e9bcfb..60bd7b463415d 100644 --- a/utils/gyb_syntax_support/Token.py +++ b/utils/gyb_syntax_support/Token.py @@ -232,7 +232,7 @@ def macro_name(self): serialization_code=92), Punctuator('RightSquareBracket', 'r_square', text=']', serialization_code=93), - Punctuator('LeftAngle', 'l_angle', text='<', requires_leading_space=True, + Punctuator('LeftAngle', 'l_angle', text='<', requires_leading_space=True, requires_trailing_space=True, serialization_code=94), Punctuator('RightAngle', 'r_angle', text='>', requires_leading_space=True, requires_trailing_space=True, serialization_code=95), @@ -253,7 +253,7 @@ def macro_name(self): Punctuator('Pound', 'pound', text='#', serialization_code=81), Punctuator('PrefixAmpersand', 'amp_prefix', text='&', - requires_leading_space=True, requires_trailing_space=True, + requires_leading_space=True, requires_trailing_space=True, serialization_code=96), Punctuator('Arrow', 'arrow', text='->', requires_leading_space=True, requires_trailing_space=True, serialization_code=78), diff --git a/utils/gyb_syntax_support/__init__.py b/utils/gyb_syntax_support/__init__.py index b54ef4da14227..1d24a156fcb21 100644 --- a/utils/gyb_syntax_support/__init__.py +++ b/utils/gyb_syntax_support/__init__.py @@ -129,7 +129,7 @@ def make_missing_swift_child(child): elif child.syntax_kind in SYNTAX_BASE_KINDS: missing_kind = f"missing{child.syntax_kind}" else: - missing_kind = child.swift_syntax_kind + missing_kind = child.swift_syntax_kind return f'RawSyntax.makeEmptyLayout(kind: SyntaxKind.{missing_kind}, ' + \ 'arena: .default)' diff --git a/utils/scale-test b/utils/scale-test index 61759f0505a01..6fd00e69ca4ba 100755 --- a/utils/scale-test +++ b/utils/scale-test @@ -173,7 +173,7 @@ def run_once_with_primary(args, ast, rng, primary_idx): if not args.save_temps: shutil.rmtree(d) - return {k: v for (k, v) in r.items() if args.select in k and + return {k: v for (k, v) in r.items() if args.select in k and not (args.exclude_timers and k.startswith('time.'))} diff --git a/utils/swift_build_support/swift_build_support/build_script_invocation.py b/utils/swift_build_support/swift_build_support/build_script_invocation.py index e1a877a25efb5..1d0e726537cec 100644 --- a/utils/swift_build_support/swift_build_support/build_script_invocation.py +++ b/utils/swift_build_support/swift_build_support/build_script_invocation.py @@ -636,7 +636,7 @@ def compute_product_pipelines(self): builder.add_product(products.SwiftDocC, is_enabled=self.args.build_swiftdocc) builder.add_product(products.SwiftDocCRender, - is_enabled=self.args.install_swiftdocc) + is_enabled=self.args.install_swiftdocc) # Keep SwiftDriver at last. # swift-driver's integration with the build scripts is not fully diff --git a/utils/swift_build_support/swift_build_support/products/swiftsyntax.py b/utils/swift_build_support/swift_build_support/products/swiftsyntax.py index 961aa27828fbb..07e91c80f1190 100644 --- a/utils/swift_build_support/swift_build_support/products/swiftsyntax.py +++ b/utils/swift_build_support/swift_build_support/products/swiftsyntax.py @@ -78,7 +78,7 @@ def build(self, host_target): self.run_swiftsyntax_build_script(target=host_target, command='verify-source-code') - self.run_swiftsyntax_build_script(target=host_target, + self.run_swiftsyntax_build_script(target=host_target, command='build') def should_test(self, host_target): @@ -91,9 +91,9 @@ def test(self, host_target): self.run_swiftsyntax_build_script(target=host_target, command='test', additional_params=[ - '--filecheck-exec', - os.path.join(llvm_build_dir, - 'bin', + '--filecheck-exec', + os.path.join(llvm_build_dir, + 'bin', 'FileCheck') ]) @@ -101,8 +101,8 @@ def should_install(self, host_target): return self.args.install_swiftsyntax def install(self, target_name): - # SwiftSyntax doesn't produce any products thate should be installed - # into the toolchein. All tools using it link against SwiftSyntax + # SwiftSyntax doesn't produce any products thate should be installed + # into the toolchein. All tools using it link against SwiftSyntax # statically. pass diff --git a/utils/update_checkout/tests/test_update_worktree.py b/utils/update_checkout/tests/test_update_worktree.py index 384ed3ea88825..a50df1ab063e7 100644 --- a/utils/update_checkout/tests/test_update_worktree.py +++ b/utils/update_checkout/tests/test_update_worktree.py @@ -29,8 +29,8 @@ def setup_worktree(workspace_path, local_path, worktree_name): for project in os.listdir(local_path): local_project_path = os.path.join(local_path, project) worktree_project_path = os.path.join(worktree_path, project) - call_quietly(['git', - '-C', local_project_path, + call_quietly(['git', + '-C', local_project_path, 'worktree', 'add', worktree_project_path]) @@ -39,8 +39,8 @@ def teardown_worktree(workspace_path, local_path, worktree_name): for project in os.listdir(local_path): local_project_path = os.path.join(local_path, project) worktree_project_path = os.path.join(worktree_path, project) - call_quietly(['git', - '-C', local_project_path, + call_quietly(['git', + '-C', local_project_path, 'worktree', 'remove', worktree_project_path]) diff --git a/utils/update_checkout/update_checkout/update_checkout.py b/utils/update_checkout/update_checkout/update_checkout.py index 83610b6330025..52b6e7b463721 100755 --- a/utils/update_checkout/update_checkout/update_checkout.py +++ b/utils/update_checkout/update_checkout/update_checkout.py @@ -509,7 +509,7 @@ def main(): action="append") parser.add_argument( "--all-repositories", - help="""Includes repositories not required for current platform. + help="""Includes repositories not required for current platform. This will not override '--skip-repositories'""", action='store_true') parser.add_argument( From a12490fd8655cf095071797d8416580e06dbb988 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Thu, 25 Aug 2022 09:14:10 +0100 Subject: [PATCH 369/491] [Runtime] Move swiftCompatibilityThreading to toolchain. This is the right place for it, and simplifies a few other things. rdar://99125585 --- CMakeLists.txt | 3 --- lib/Threading/CMakeLists.txt | 6 +++--- stdlib/public/Threading/CMakeLists.txt | 16 ---------------- stdlib/toolchain/CMakeLists.txt | 1 + .../CompatibilityThreading/CMakeLists.txt | 14 ++++++++++++++ 5 files changed, 18 insertions(+), 22 deletions(-) create mode 100644 stdlib/toolchain/CompatibilityThreading/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ba128f40a5ce..75c8159de9a26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1163,9 +1163,6 @@ endif() if(SWIFT_BUILD_STDLIB) add_subdirectory(stdlib) else() - # Some of the things below depend on the threading library - add_subdirectory(stdlib/public/Threading) - if(SWIFT_BUILD_STDLIB_EXTRA_TOOLCHAIN_CONTENT) add_subdirectory(stdlib/toolchain) endif() diff --git a/lib/Threading/CMakeLists.txt b/lib/Threading/CMakeLists.txt index c43deec244bef..29ef76c4fff4c 100644 --- a/lib/Threading/CMakeLists.txt +++ b/lib/Threading/CMakeLists.txt @@ -1,9 +1,9 @@ # If you update this, you also need to update the CMakeLists.txt file in -# stdlib/public/Threading +# stdlib/public/Threading AND the one in stdlib/toolchain/Threading # Note that it is *not* an error that Errors.cpp is only listed here. -# It shouldn't be in stdlib/public/Threading because that is an OBJECT_LIBRARY -# and things that use that should be defining their own fatal error handler. +# It shouldn't be in the other places because those are OBJECT_LIBRARYs +# and things that use them should be defining their own fatal error handler. add_swift_host_library(swiftThreading STATIC C11.cpp diff --git a/stdlib/public/Threading/CMakeLists.txt b/stdlib/public/Threading/CMakeLists.txt index 53fa558513ded..007289ed3fac7 100644 --- a/stdlib/public/Threading/CMakeLists.txt +++ b/stdlib/public/Threading/CMakeLists.txt @@ -10,19 +10,3 @@ add_swift_target_library(swiftThreading OBJECT_LIBRARY "${SWIFT_SOURCE_DIR}/lib/Threading/Pthreads.cpp" "${SWIFT_SOURCE_DIR}/lib/Threading/Win32.cpp" INSTALL_IN_COMPONENT never_install) - -if(SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT) - # This is only used by the compatibility libraries - add_swift_target_library(swiftCompatibilityThreading OBJECT_LIBRARY - "${SWIFT_SOURCE_DIR}/lib/Threading/C11.cpp" - "${SWIFT_SOURCE_DIR}/lib/Threading/Linux.cpp" - "${SWIFT_SOURCE_DIR}/lib/Threading/Pthreads.cpp" - "${SWIFT_SOURCE_DIR}/lib/Threading/Win32.cpp" - INSTALL_IN_COMPONENT never_install - TARGET_SDKS ${SWIFT_DARWIN_PLATFORMS} - DEPLOYMENT_VERSION_OSX ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_OSX} - DEPLOYMENT_VERSION_IOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_IOS} - DEPLOYMENT_VERSION_TVOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_TVOS} - DEPLOYMENT_VERSION_WATCHOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_WATCHOS} - ) -endif() diff --git a/stdlib/toolchain/CMakeLists.txt b/stdlib/toolchain/CMakeLists.txt index 20a75bddaedaa..2dece25db801b 100644 --- a/stdlib/toolchain/CMakeLists.txt +++ b/stdlib/toolchain/CMakeLists.txt @@ -52,4 +52,5 @@ if(SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT) add_subdirectory(Compatibility51) add_subdirectory(CompatibilityDynamicReplacements) add_subdirectory(CompatibilityConcurrency) + add_subdirectory(CompatibilityThreading) endif() diff --git a/stdlib/toolchain/CompatibilityThreading/CMakeLists.txt b/stdlib/toolchain/CompatibilityThreading/CMakeLists.txt new file mode 100644 index 0000000000000..b6951c606d0ae --- /dev/null +++ b/stdlib/toolchain/CompatibilityThreading/CMakeLists.txt @@ -0,0 +1,14 @@ +# This is the counterpart to lib/Threading/CMakeLists.txt. Any updates +# need to be reflected in both places. + +add_swift_target_library(swiftCompatibilityThreading OBJECT_LIBRARY + "${SWIFT_SOURCE_DIR}/lib/Threading/C11.cpp" + "${SWIFT_SOURCE_DIR}/lib/Threading/Linux.cpp" + "${SWIFT_SOURCE_DIR}/lib/Threading/Pthreads.cpp" + "${SWIFT_SOURCE_DIR}/lib/Threading/Win32.cpp" + INSTALL_IN_COMPONENT never_install + TARGET_SDKS ${SWIFT_DARWIN_PLATFORMS} + DEPLOYMENT_VERSION_OSX ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_OSX} + DEPLOYMENT_VERSION_IOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_IOS} + DEPLOYMENT_VERSION_TVOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_TVOS} + DEPLOYMENT_VERSION_WATCHOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_WATCHOS}) From 21b165afe40f8e7ac2f4ca402e36eac3546178b2 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Thu, 25 Aug 2022 09:16:45 +0100 Subject: [PATCH 370/491] [Threading] Fix comment. I changed the directory name but not the comment here. rdar://99125585 --- lib/Threading/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Threading/CMakeLists.txt b/lib/Threading/CMakeLists.txt index 29ef76c4fff4c..029a52b68e1e3 100644 --- a/lib/Threading/CMakeLists.txt +++ b/lib/Threading/CMakeLists.txt @@ -1,5 +1,5 @@ # If you update this, you also need to update the CMakeLists.txt file in -# stdlib/public/Threading AND the one in stdlib/toolchain/Threading +# stdlib/public/Threading AND the one in stdlib/toolchain/CompatibilityThreading # Note that it is *not* an error that Errors.cpp is only listed here. # It shouldn't be in the other places because those are OBJECT_LIBRARYs From dfecad916e34141c483b5519b7dbcf887dcf7064 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 25 Aug 2022 06:47:36 -0700 Subject: [PATCH 371/491] Disable resilient_multipayload_enum.swift test that fails on older runtimes Older runtimes have a bug that was fixed by PR #42131 that this test exercises. rdar://99099912 --- test/Interpreter/resilient_multipayload_enum.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/Interpreter/resilient_multipayload_enum.swift b/test/Interpreter/resilient_multipayload_enum.swift index 6810741822ef8..85e23efb0a971 100644 --- a/test/Interpreter/resilient_multipayload_enum.swift +++ b/test/Interpreter/resilient_multipayload_enum.swift @@ -16,6 +16,9 @@ // REQUIRES: executable_test +// Older runtimes have a bug (fixed by PR#42131) that causes this test to fail. +// UNSUPPORTED: use_os_stdlib || back_deployment_runtime + import ResilientEnum @inline(never) From 7d55dea4aec50b7b78d315e2025939a694bdbade Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 24 Aug 2022 14:09:18 -0700 Subject: [PATCH 372/491] Reduce semantic dependencies in contextRequiresStrictConcurrencyChecking. We don't need fully-checked isolation as computed from attributes to determine whether we're in a concurrency context. Use a cheaper predicate, which can also avoid spurious cycles. Fixes rdar://99013488. --- lib/Sema/TypeCheckConcurrency.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index c6d5b47fec33f..9fe36839dbe84 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -3115,6 +3115,23 @@ swift::determineClosureActorIsolation(AbstractClosureExpr *closure) { return checker.determineClosureIsolation(closure); } +/// Determine whethere there is an explicit isolation attribute +/// of any kind. +static bool hasExplicitIsolationAttribute(const Decl *decl) { + if (auto nonisolatedAttr = + decl->getAttrs().getAttribute()) { + if (!nonisolatedAttr->isImplicit()) + return true; + } + + if (auto globalActorAttr = decl->getGlobalActorAttr()) { + if (!globalActorAttr->first->isImplicit()) + return true; + } + + return false; +} + /// Determine actor isolation solely from attributes. /// /// \returns the actor isolation determined from attributes alone (with no @@ -4085,8 +4102,7 @@ bool swift::contextRequiresStrictConcurrencyChecking( } else if (auto decl = dc->getAsDecl()) { // If any isolation attributes are present, we're using concurrency // features. - if (getIsolationFromAttributes( - decl, /*shouldDiagnose=*/false, /*onlyExplicit=*/true)) + if (hasExplicitIsolationAttribute(decl)) return true; if (auto func = dyn_cast(decl)) { @@ -4097,9 +4113,7 @@ bool swift::contextRequiresStrictConcurrencyChecking( // If we're in an accessor declaration, also check the storage // declaration. if (auto accessor = dyn_cast(decl)) { - if (getIsolationFromAttributes( - accessor->getStorage(), /*shouldDiagnose=*/false, - /*onlyExplicit=*/true)) + if (hasExplicitIsolationAttribute(accessor->getStorage())) return true; } } From 40bb60822f4d64f4448b60e08d046005af875d70 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Thu, 25 Aug 2022 17:30:33 +0100 Subject: [PATCH 373/491] [Profiler] NFC: Add some comments --- lib/SIL/IR/SILProfiler.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index c0b1c029b901b..f5fd376810117 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -695,6 +695,9 @@ struct PGOMapping : public ASTWalker { } }; +/// Produce coverage mapping information for a function. This involves taking +/// the counters computed by MapRegionCounters, and annotating the source with +/// regions that are defined in terms of those counters. struct CoverageMapping : public ASTWalker { private: const SourceManager &SM; @@ -976,6 +979,8 @@ struct CoverageMapping : public ASTWalker { if (S->isImplicit() && S != ImplicitTopLevelBody) return {true, S}; + // If we're in an 'incomplete' region, update it to include this node. This + // ensures we only create the region if needed. if (!RegionStack.empty()) extendRegion(S); @@ -986,7 +991,13 @@ struct CoverageMapping : public ASTWalker { } else if (auto *IS = dyn_cast(S)) { if (auto *Cond = getConditionNode(IS->getCond())) assignCounter(Cond, CounterExpr::Ref(getCurrentCounter())); + + // The counter for the if statement itself tracks the number of jumps to + // it by break statements. assignCounter(IS, CounterExpr::Zero()); + + // We emit a counter for the then block, and define the else block in + // terms of it. CounterExpr &ThenCounter = assignCounter(IS->getThenStmt()); if (IS->getElseStmt()) assignCounter(IS->getElseStmt(), @@ -996,18 +1007,26 @@ struct CoverageMapping : public ASTWalker { assignCounter(GS->getBody()); } else if (auto *WS = dyn_cast(S)) { + // The counter for the while statement itself tracks the number of jumps + // to it by break and continue statements. assignCounter(WS, CounterExpr::Zero()); + if (auto *E = getConditionNode(WS->getCond())) assignCounter(E, CounterExpr::Ref(getCurrentCounter())); assignCounter(WS->getBody()); } else if (auto *RWS = dyn_cast(S)) { + // The counter for the while statement itself tracks the number of jumps + // to it by break and continue statements. assignCounter(RWS, CounterExpr::Zero()); + CounterExpr &BodyCounter = assignCounter(RWS->getBody()); assignCounter(RWS->getCond(), CounterExpr::Ref(BodyCounter)); RepeatWhileStack.push_back(RWS); } else if (auto *FES = dyn_cast(S)) { + // The counter for the for statement itself tracks the number of jumps + // to it by break and continue statements. assignCounter(FES, CounterExpr::Zero()); assignCounter(FES->getBody()); @@ -1021,7 +1040,10 @@ struct CoverageMapping : public ASTWalker { if (caseStmt->getParentKind() == CaseParentKind::Switch) pushRegion(S); } else if (auto *DS = dyn_cast(S)) { + // The counter for the do statement itself tracks the number of jumps + // to it by break statements. assignCounter(DS, CounterExpr::Zero()); + assignCounter(DS->getBody(), CounterExpr::Ref(getCurrentCounter())); } else if (auto *DCS = dyn_cast(S)) { @@ -1125,6 +1147,8 @@ struct CoverageMapping : public ASTWalker { if (isa(E) && !Parent.isNull()) return {false, E}; + // If we're in an 'incomplete' region, update it to include this node. This + // ensures we only create the region if needed. if (!RegionStack.empty()) extendRegion(E); From 05e230978898192196b5b823791e65c48f017d84 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Thu, 25 Aug 2022 17:30:34 +0100 Subject: [PATCH 374/491] [Profiler] Fix coverage mapping for switches Previously we assumed the exit counter was the same as the entry counter. Update the logic such that we track break statements (including implicitly at the end of a case), as well as early returns and jumps to parent statements. This follows a similar logic to what we do for if statements. rdar://99141044 --- lib/SIL/IR/SILProfiler.cpp | 59 ++++++----- lib/SILGen/SILGenPattern.cpp | 1 - test/Profiler/coverage_switch.swift | 145 +++++++++++++++++++++++----- 3 files changed, 156 insertions(+), 49 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index f5fd376810117..2f88704f997af 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -259,8 +259,6 @@ struct MapRegionCounters : public ASTWalker { mapRegion(RWS->getBody()); } else if (auto *FES = dyn_cast(S)) { mapRegion(FES->getBody()); - } else if (auto *SS = dyn_cast(S)) { - mapRegion(SS); } else if (auto *CS = dyn_cast(S)) { mapRegion(getProfilerStmtForCase(CS)); } @@ -647,8 +645,6 @@ struct PGOMapping : public ASTWalker { } else if (auto *FES = dyn_cast(S)) { setKnownExecutionCount(FES->getBody()); setExecutionCount(FES, parentCount); - } else if (auto *SS = dyn_cast(S)) { - setKnownExecutionCount(SS); } else if (auto *CS = dyn_cast(S)) { setKnownExecutionCount(getProfilerStmtForCase(CS)); } @@ -823,17 +819,7 @@ struct CoverageMapping : public ASTWalker { if (ControlFlowAdjust) Count = &createCounter(CounterExpr::Sub(*Count, *ControlFlowAdjust)); - if (Count->isSemanticallyZero()) { - // If the counter is semantically zero, form an 'incomplete' region with - // no starting location. This prevents forming unreachable regions unless - // there is a following statement or expression to extend the region. - RegionStack.emplace_back(ASTNode(), *Count, None, None); - } else { - // Otherwise, we have a non-zero counter, so form a new region starting - // at the end of the previous scope. This ensures the user covers both - // branches of a condition. - RegionStack.emplace_back(ASTNode(), *Count, getEndLoc(Scope), None); - } + replaceCount(Count, getEndLoc(Scope)); } /// Push a region covering \c Node onto the stack. @@ -847,10 +833,24 @@ struct CoverageMapping : public ASTWalker { }); } - /// Replace the current region's count by pushing an incomplete region. - void replaceCount(CounterExpr &&Expr, Optional Start = None) { - CounterExpr &Counter = createCounter(std::move(Expr)); - RegionStack.emplace_back(ASTNode(), Counter, Start, None); + /// Replace the current region at \p Start with a new counter. If \p Start is + /// \c None, or the counter is semantically zero, an 'incomplete' region is + /// formed, which is not recorded unless followed by additional AST nodes. + void replaceCount(CounterExpr *Counter, Optional Start) { + // If the counter is semantically zero, form an 'incomplete' region with + // no starting location. This prevents forming unreachable regions unless + // there is a following statement or expression to extend the region. + if (Start && Counter->isSemanticallyZero()) + Start = None; + + RegionStack.emplace_back(ASTNode(), *Counter, Start, None); + } + + /// Replace the current region at \p Start with a new counter. If \p Start is + /// \c None, or the counter is semantically zero, an 'incomplete' region is + /// formed, which is not recorded unless followed by additional AST nodes. + void replaceCount(CounterExpr &&Expr, Optional Start) { + replaceCount(&createCounter(std::move(Expr)), Start); } /// Get the location for the end of the last token in \c Node. @@ -912,7 +912,7 @@ struct CoverageMapping : public ASTWalker { SourceMappingRegion &Region = getRegion(); if (!Region.hasEndLoc()) Region.setEndLoc(getEndLoc(S)); - replaceCount(CounterExpr::Zero()); + replaceCount(CounterExpr::Zero(), /*Start*/ None); } Expr *getConditionNode(StmtCondition SC) { @@ -1031,7 +1031,14 @@ struct CoverageMapping : public ASTWalker { assignCounter(FES->getBody()); } else if (auto *SS = dyn_cast(S)) { - assignCounter(SS); + // The counter for the switch statement itself tracks the number of jumps + // to it by break statements, including the implicit breaks at the end of + // cases. + assignCounter(SS, CounterExpr::Zero()); + + assignCounter(SS->getSubjectExpr(), + CounterExpr::Ref(getCurrentCounter())); + // Assign counters for cases so they're available for fallthrough. for (CaseStmt *Case : SS->getCases()) assignCounter(Case); @@ -1097,7 +1104,8 @@ struct CoverageMapping : public ASTWalker { Stmt *BreakTarget = BS->getTarget(); if (auto *RWS = dyn_cast(BreakTarget)) { subtractFromCounter(RWS->getCond(), getCurrentCounter()); - } else if (!isa(BreakTarget)) { + } else { + // Update the exit counter for the target. addToCounter(BS->getTarget(), getCurrentCounter()); } @@ -1115,9 +1123,12 @@ struct CoverageMapping : public ASTWalker { replaceCount(CounterExpr::Ref(getCounter(S)), getEndLoc(S)); } else if (auto caseStmt = dyn_cast(S)) { - if (caseStmt->getParentKind() == CaseParentKind::Switch) + if (caseStmt->getParentKind() == CaseParentKind::Switch) { + // The end of a case block is an implicit break, update the exit + // counter to reflect this. + addToCounter(caseStmt->getParentStmt(), getCurrentCounter()); popRegions(S); - + } } else if (auto *DCS = dyn_cast(S)) { assert(DoCatchStack.back() == DCS && "Malformed do-catch stack"); DoCatchStack.pop_back(); diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index 7665c359e294b..58d7b10529d49 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -2814,7 +2814,6 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) { emission.emitAddressOnlyAllocations(); SILBasicBlock *contBB = createBasicBlock(); - emitProfilerIncrement(S); JumpDest contDest(contBB, Cleanups.getCleanupsDepth(), CleanupLocation(S)); LexicalScope switchScope(*this, CleanupLocation(S)); diff --git a/test/Profiler/coverage_switch.swift b/test/Profiler/coverage_switch.swift index b5248d0a94c1b..ecc39ff515e7d 100644 --- a/test/Profiler/coverage_switch.swift +++ b/test/Profiler/coverage_switch.swift @@ -1,19 +1,61 @@ // RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_switch %s | %FileCheck %s // RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -emit-ir %s +// CHECK-LABEL: sil hidden @$s15coverage_switch2f1yys5Int32VF : $@convention(thin) (Int32) -> () +// CHECK: string_literal +// CHECK-NEXT: integer_literal $Builtin.Int64, 0 +// CHECK-NEXT: integer_literal $Builtin.Int32, 4 +// CHECK-NEXT: integer_literal $Builtin.Int32, 0 +// CHECK-NEXT: int_instrprof_increment + +// CHECK: integer_literal $Builtin.Int32, 1 +// CHECK: cmp_eq_Int32 +// CHECK: cond_br {{%[0-9]+}}, [[CASE1:bb[0-9]+]], [[NOTCASE1:bb[0-9]+]] + +// CHECK: [[NOTCASE1]] +// CHECK: integer_literal $Builtin.Int32, 2 +// CHECK: cmp_eq_Int32 +// CHECK: cond_br {{%[0-9]+}}, [[CASE2:bb[0-9]+]], [[NOTCASE2:bb[0-9]+]] + +// CHECK: [[NOTCASE2]] +// CHECK-NEXT: string_literal +// CHECK-NEXT: integer_literal $Builtin.Int64, 0 +// CHECK-NEXT: integer_literal $Builtin.Int32, 4 +// CHECK-NEXT: integer_literal $Builtin.Int32, 3 +// CHECK-NEXT: int_instrprof_increment +// CHECK-NEXT: br [[DEFAULT:bb[0-9]+]] + +// CHECK: [[CASE2]] +// CHECK-NEXT: string_literal +// CHECK-NEXT: integer_literal $Builtin.Int64, 0 +// CHECK-NEXT: integer_literal $Builtin.Int32, 4 +// CHECK-NEXT: integer_literal $Builtin.Int32, 2 +// CHECK-NEXT: int_instrprof_increment +// CHECK-NEXT: br [[DEFAULT]] + +// CHECK: [[DEFAULT]] +// CHECK: function_ref @$s15coverage_switch2f1yys5Int32VF : $@convention(thin) (Int32) -> () + +// CHECK: [[CASE1]] +// CHECK-NEXT: string_literal +// CHECK-NEXT: integer_literal $Builtin.Int64, 0 +// CHECK-NEXT: integer_literal $Builtin.Int32, 4 +// CHECK-NEXT: integer_literal $Builtin.Int32, 1 +// CHECK-NEXT: int_instrprof_increment + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_switch.f1 -func f1(_ x : Int32) { - switch (x) { - case 1: // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:10 : 2 +func f1(_ x : Int32) { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+11]]:2 : 0 + switch (x) { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:13 : 0 + case 1: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:10 : 1 break - case 2: // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:16 : 3 + case 2: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:16 : 2 fallthrough - default: // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:14 : (3 + 4) + default: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:14 : (2 + 3) f1(x - 1) - } // CHECK: [[@LINE]]:4 -> [[@LINE+3]]:2 : 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+3]]:2 : ((1 + 2) + 3) var y = x -} +} // CHECK-NEXT: } enum Algebraic { case Type1(Int32, Int32) @@ -25,41 +67,96 @@ enum Algebraic { func nop() {} // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_switch.f2 -func f2(_ x : Algebraic) -> Int32 { - switch(x) { - case let .Type1(y, z): // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:10 : 2 +func f2(_ x : Algebraic) -> Int32 { // CHECK-NEXT: [[@LINE]]:35 -> [[@LINE+15]]:2 : 0 + switch(x) { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:12 : 0 + case let .Type1(y, z): // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:10 : 1 nop() - case .Type2(let b): // CHECK: [[@LINE]]:3 -> [[@LINE+2]]:16 : 3 + case .Type2(let b): // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+2]]:16 : 2 nop() fallthrough - case .Type3: // CHECK: [[@LINE]]:3 -> [[@LINE+3]]:6 : (3 + 4) - if (false) { // CHECK: [[@LINE]]:16 -> [[@LINE+2]]:6 : 5 - fallthrough - } - case .Type4: // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:10 : (5 + 6) + case .Type3: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+3]]:6 : (2 + 3) + if (false) { // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:15 : (2 + 3) + fallthrough // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:6 : 4 + } // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:6 : ((2 + 3) - 4) + case .Type4: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:10 : (4 + 5) break - } // CHECK: [[@LINE]]:4 -> [[@LINE+1]]:11 : 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (((1 + 2) + 3) + 5) return 0 -} +} // CHECK-NEXT: } public enum Simple { case First, Second } // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_switch.f3 -func f3(_ x : Simple) -> Int32 { - switch (x) { - case .First: // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:13 : 2 +func f3(_ x : Simple) -> Int32 { // CHECK-NEXT: [[@LINE]]:32 -> [[@LINE+9]]:2 : 0 + switch (x) { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:13 : 0 + case .First: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:13 : 1 return 1 - case .Second: // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:10 : 3 + case .Second: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:10 : 2 break - } // CHECK: [[@LINE]]:4 -> [[@LINE+2]]:11 : 1 + } // CHECK: [[@LINE]]:4 -> [[@LINE+2]]:11 : 2 return 0 -} +} // CHECK-NEXT: } f1(3) f2(Algebraic.Type1(1, 1)) f2(Algebraic.Type2(false)) f2(Algebraic.Type3) f3(Simple.Second) + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_switch.f4 +func f4(_ x: Int) throws -> Int { // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE+21]]:2 : 0 + y: do { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE+18]]:4 : 0 + switch x { // CHECK-NEXT: [[@LINE]]:12 -> [[@LINE]]:13 : 0 + case 1, 2, 3: // CHECK-NEXT: [[@LINE]]:5 -> [[@LINE+4]]:18 : 1 + if .random() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:19 : 1 + return 5 // CHECK-NEXT: [[@LINE-1]]:20 -> [[@LINE+1]]:8 : 2 + } // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+1]]:18 : (1 - 2) + fallthrough + case 4: // CHECK-NEXT: [[@LINE]]:5 -> [[@LINE+4]]:8 : ((1 + 3) - 2) + if .random() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:19 : ((1 + 3) - 2) + struct E : Error {} // CHECK-NEXT: [[@LINE-1]]:20 -> [[@LINE+2]]:8 : 4 + throw E() + } // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:8 : (((1 + 3) - 2) - 4) + default: // CHECK-NEXT: [[@LINE]]:5 -> [[@LINE+3]]:8 : 5 + if .random() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:19 : 5 + break y // CHECK-NEXT: [[@LINE-1]]:20 -> [[@LINE+1]]:8 : 6 + } // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:8 : (5 - 6) + } + f1(0) // CHECK-NEXT: [[@LINE-1]]:6 -> [[@LINE+1]]:4 : (((((1 + 3) + 5) - 2) - 4) - 6) + } + return 1 // CHECK-NEXT: [[@LINE-1]]:4 -> [[@LINE]]:11 : ((((1 + 3) + 5) - 2) - 4) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_switch.f5 +func f5(_ x: Simple) -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+7]]:2 : 0 + switch x { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:11 : 0 + case .First: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:13 : 1 + return 0 + case .Second: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:13 : 2 + return 1 + } +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_switch.f6 +func f6(_ x: Simple) -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+5]]:2 : 0 + switch x { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:11 : 0 + case .First: return 0 // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE]]:25 : 1 + case .Second: return 1 // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE]]:25 : 2 + } +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_switch.f7 +func f7() -> Int { // CHECK-NEXT: [[@LINE]]:18 -> [[@LINE+10]]:2 : 0 + switch .random() ? Simple.First : .Second { + // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE-1]]:44 : 0 + // CHECK-NEXT: [[@LINE-2]]:22 -> [[@LINE-2]]:34 : 1 + // CHECK-NEXT: [[@LINE-3]]:37 -> [[@LINE-3]]:44 : (0 - 1) + case .First: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:13 : 2 + return 0 + case .Second: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:13 : 3 + return 1 + } +} // CHECK-NEXT: } From 1f3600ac7f28c4edeb850c88263918a70e6354e3 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Thu, 25 Aug 2022 09:30:38 -0700 Subject: [PATCH 375/491] [Dependency Scanner] Move the Clang scanning shared state out into local (per-scan) cache. Having it be in the potentially-persistent global cache state seems to be causing issues with search paths of subsequent scans. While I investigate the cause, moving this state to the local cache works around the problem. --- include/swift/AST/ModuleDependencies.h | 48 ++++++++++---------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index 9709352a68842..3db6a218f0d4c 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -515,18 +515,6 @@ class GlobalModuleDependenciesCache { /// The triples used by scanners using this cache, in the order in which they were used std::vector AllTriples; - /// Additional information needed for Clang dependency scanning. - ClangModuleDependenciesCacheImpl *clangImpl = nullptr; - - /// Function that will delete \c clangImpl properly. - void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *) = nullptr; - - /// Free up the storage associated with the Clang implementation. - void destroyClangImpl() { - if (this->clangImplDeleter) - this->clangImplDeleter(this->clangImpl); - } - /// Retrieve the dependencies map that corresponds to the given dependency /// kind. llvm::StringMap & @@ -540,7 +528,7 @@ class GlobalModuleDependenciesCache { GlobalModuleDependenciesCache & operator=(const GlobalModuleDependenciesCache &) = delete; - virtual ~GlobalModuleDependenciesCache() { destroyClangImpl(); } + virtual ~GlobalModuleDependenciesCache() {} void configureForTriple(std::string triple); @@ -553,19 +541,6 @@ class GlobalModuleDependenciesCache { /// wrapped in an instance of `ModuleDependenciesCache`. friend class ModuleDependenciesCache; - /// Set the Clang-specific implementation data. - virtual void - setClangImpl(ClangModuleDependenciesCacheImpl *clangImpl, - void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *)) { - destroyClangImpl(); - - this->clangImpl = clangImpl; - this->clangImplDeleter = clangImplDeleter; - } - - /// Retrieve the Clang-specific implementation data; - ClangModuleDependenciesCacheImpl *getClangImpl() const { return clangImpl; } - /// Whether we have cached dependency information for the given module. bool hasDependencies(StringRef moduleName, ModuleLookupSpecifics details) const; @@ -632,6 +607,18 @@ class ModuleDependenciesCache { /// the current scanning action. ModuleDependenciesKindRefMap ModuleDependenciesMap; + /// Additional information needed for Clang dependency scanning. + ClangModuleDependenciesCacheImpl *clangImpl = nullptr; + + /// Function that will delete \c clangImpl properly. + void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *) = nullptr; + + /// Free up the storage associated with the Clang implementation. + void destroyClangImpl() { + if (this->clangImplDeleter) + this->clangImplDeleter(this->clangImpl); + } + /// Retrieve the dependencies map that corresponds to the given dependency /// kind. llvm::StringMap & @@ -654,19 +641,22 @@ class ModuleDependenciesCache { ModuleDependenciesCache(GlobalModuleDependenciesCache &globalCache); ModuleDependenciesCache(const ModuleDependenciesCache &) = delete; ModuleDependenciesCache &operator=(const ModuleDependenciesCache &) = delete; - virtual ~ModuleDependenciesCache() {} + virtual ~ModuleDependenciesCache() { destroyClangImpl(); } public: /// Set the Clang-specific implementation data. void setClangImpl(ClangModuleDependenciesCacheImpl *clangImpl, void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *)) { - globalCache.setClangImpl(clangImpl, clangImplDeleter); + destroyClangImpl(); + + this->clangImpl = clangImpl; + this->clangImplDeleter = clangImplDeleter; } /// Retrieve the Clang-specific implementation data; ClangModuleDependenciesCacheImpl *getClangImpl() const { - return globalCache.getClangImpl(); + return clangImpl; } /// Whether we have cached dependency information for the given module. From f04a0c95ec16b5c584511ec3c84ca0b4cf22801e Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 25 Aug 2022 10:10:40 -0700 Subject: [PATCH 376/491] IRGen: Only use clang type based task continuation function pointer descriminator schema if descrimination is requested rdar://99142574 --- lib/IRGen/GenCall.cpp | 5 +++-- lib/IRGen/GenFunc.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 979682fa1e45a..d388b8a9eb12c 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -2732,8 +2732,9 @@ class AsyncCallEmission final : public CallEmission { if (auto schema = IGF.IGM.getOptions().PointerAuth.FunctionPointers) { // Use the Clang type for TaskContinuationFunction* // to make this work with type diversity. - schema = - IGF.IGM.getOptions().PointerAuth.ClangTypeTaskContinuationFunction; + if (schema.hasOtherDiscrimination()) + schema = + IGF.IGM.getOptions().PointerAuth.ClangTypeTaskContinuationFunction; auto authInfo = PointerAuthInfo::emit(IGF, schema, nullptr, PointerAuthEntity()); signedResumeFn = emitPointerAuthSign(IGF, signedResumeFn, authInfo); diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 19d0cefa8e247..d4da65fc9f00a 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -2471,7 +2471,8 @@ llvm::Function *IRGenFunction::createAsyncSuspendFn() { if (auto schema = IGM.getOptions().PointerAuth.FunctionPointers) { // Use the Clang type for TaskContinuationFunction* // to make this work with type diversity. - schema = IGM.getOptions().PointerAuth.ClangTypeTaskContinuationFunction; + if (schema.hasOtherDiscrimination()) + schema = IGM.getOptions().PointerAuth.ClangTypeTaskContinuationFunction; auto authInfo = PointerAuthInfo::emit(suspendIGF, schema, nullptr, PointerAuthEntity()); resumeFunction = emitPointerAuthSign(suspendIGF, resumeFunction, authInfo); From 8df9fca041609f8c69db88eecda2e5e0482fcfeb Mon Sep 17 00:00:00 2001 From: zoecarver Date: Thu, 25 Aug 2022 10:45:12 -0700 Subject: [PATCH 377/491] [cxx-interop] Don't import constructors of foreign reference types. The logic is here for this in the importer, which means the module interface tests make it appear that the behavior is correct, but lazy member lookup still finds the constructors, so this patch fixes that part. --- lib/ClangImporter/ClangImporter.cpp | 4 +++ .../foreign-reference/no-ctor-errors.swift | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/Interop/Cxx/foreign-reference/no-ctor-errors.swift diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index fe1747bfb6ae2..b93884a961415 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -4940,6 +4940,10 @@ TinyPtrVector ClangRecordMemberLookup::evaluate( auto named = found.get(); if (dyn_cast(named->getDeclContext()) == recordDecl->getClangDecl()) { + // Don't import constructors on foreign reference types. + if (isa(named) && isa(recordDecl)) + continue; + if (auto import = clangModuleLoader->importDeclDirectly(named)) result.push_back(cast(import)); } diff --git a/test/Interop/Cxx/foreign-reference/no-ctor-errors.swift b/test/Interop/Cxx/foreign-reference/no-ctor-errors.swift new file mode 100644 index 0000000000000..b8155509e8f9a --- /dev/null +++ b/test/Interop/Cxx/foreign-reference/no-ctor-errors.swift @@ -0,0 +1,25 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: not %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop 2>&1 | %FileCheck %s + +//--- Inputs/module.modulemap +module Test { + header "test.h" + requires cplusplus +} + +//--- Inputs/test.h +struct + __attribute__((swift_attr("import_reference"))) + __attribute__((swift_attr("retain:immortal"))) + __attribute__((swift_attr("release:immortal"))) +HasCtor { + HasCtor(int a) {} +}; + +//--- test.swift + +import Test + +// CHECK: error: 'HasCtor' cannot be constructed because it has no accessible initializers +let x = HasCtor(42) \ No newline at end of file From baac27d04c545df17af2c56f646efd053ee11080 Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Tue, 23 Aug 2022 10:58:11 -0700 Subject: [PATCH 378/491] update test case for windows --- .../core/unsigned-return-type-no-zext-msvc.cpp | 17 +++++++++++++++++ .../core/unsigned-return-type-no-zext.cpp | 3 +++ 2 files changed, 20 insertions(+) create mode 100644 test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext-msvc.cpp diff --git a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext-msvc.cpp b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext-msvc.cpp new file mode 100644 index 0000000000000..88f0b539a2bac --- /dev/null +++ b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext-msvc.cpp @@ -0,0 +1,17 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-interop-build-clangxx -c %s -I %t -S -emit-llvm -o %t/ir.ll +// RUN: %FileCheck %s < %t/ir.ll + +// REQUIRES: OS=windows-msvc + +unsigned char getEnumTagi8(void *p); +unsigned getEnumTagi32(void *p); + +void test(void *p) { + getEnumTagi8(p); + getEnumTagi32(p); +} + +// CHECK: declare dso_local noundef i8 @"?getEnumTagi8@@YAEPEAX@Z"(i8* noundef) #1 +// CHECK: declare dso_local noundef i32 @"?getEnumTagi32@@YAIPEAX@Z"(i8* noundef) #1 diff --git a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp index 091f1ade8e2aa..9e50d6a549c3a 100644 --- a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp +++ b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp @@ -1,7 +1,10 @@ // RUN: %empty-directory(%t) + // RUN: %target-interop-build-clangxx -c %s -I %t -S -emit-llvm -o %t/ir.ll // RUN: %FileCheck %s < %t/ir.ll +// UNSUPPORTED: OS=windows-msvc + unsigned char getEnumTagi8(void *p); unsigned getEnumTagi32(void *p); From af7b722db8e81dfcdd2085c514132a6609d575a9 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 25 Aug 2022 12:38:08 -0700 Subject: [PATCH 379/491] [ConstraintLocator] Introduce `endsWith` convenience function --- include/swift/Sema/ConstraintLocator.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/swift/Sema/ConstraintLocator.h b/include/swift/Sema/ConstraintLocator.h index 53c0c7c44afd6..cbaf487acbcbd 100644 --- a/include/swift/Sema/ConstraintLocator.h +++ b/include/swift/Sema/ConstraintLocator.h @@ -1295,6 +1295,16 @@ class ConstraintLocatorBuilder { return None; } + /// Check whether this locator has the given locator path element + /// at the end of its path. + template + bool endsWith() const { + if (auto lastElt = last()) { + return lastElt->is(); + } + return false; + } + /// Produce a debugging dump of this locator. SWIFT_DEBUG_DUMPER(dump(SourceManager *SM)); SWIFT_DEBUG_DUMPER(dump(ConstraintSystem *CS)); From 8e9117dda3998a481ac5e0cf669bd7d2471e2058 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Thu, 9 Jun 2022 14:52:28 -0700 Subject: [PATCH 380/491] Handle store_borrow in SILMem2Reg --- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 427 +++++++++++----- test/SILOptimizer/mem2reg_borrows.sil | 50 +- .../SILOptimizer/mem2reg_lifetime_borrows.sil | 454 ++++++++++++++++++ 3 files changed, 777 insertions(+), 154 deletions(-) create mode 100644 test/SILOptimizer/mem2reg_lifetime_borrows.sil diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 0b9473f5add60..ad47fe7d54323 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -55,6 +55,7 @@ STATISTIC(NumAllocStackCaptured, "Number of AllocStack captured"); STATISTIC(NumInstRemoved, "Number of Instructions removed"); static bool shouldAddLexicalLifetime(AllocStackInst *asi); +static bool isGuaranteedLexicalValue(SILValue src); namespace { @@ -89,16 +90,23 @@ struct LiveValues { /// The value with which usages of the provided AllocStackInst should be /// replaced. - /// - /// For lexical AllocStackInsts, that is the copy made of the borrowed value. - /// For those that are non-lexical, that is the value that was stored into the - /// storage. SILValue replacement(AllocStackInst *asi, SILInstruction *toReplace) { + if (!shouldAddLexicalLifetime(asi)) { + return stored; + } + // For lexical AllocStackInsts, which are store_borrow locations, we may + // have created a borrow if the stored value is a non-lexical guaranteed + // value. Otherwise we would have created a borrow of the @owned stored + // value and a copy of the borrowed value. + assert(stored->getOwnershipKind() != OwnershipKind::Guaranteed || + isGuaranteedLexicalValue(stored) || borrow); + assert(stored->getOwnershipKind() != OwnershipKind::Owned || + copy && borrow); if (isa(toReplace)) { - return shouldAddLexicalLifetime(asi) ? borrow : stored; + return borrow ? borrow : stored; } - return shouldAddLexicalLifetime(asi) ? copy : stored; - }; + return copy ? copy : borrow ? borrow : stored; + } }; /// A transient structure used only by promoteAllocationInBlock and @@ -217,8 +225,12 @@ static bool isLoadFromStack(SILInstruction *i, AllocStackInst *asi) { ValueBase *op = i->getOperand(0); while (op != asi) { if (!isa(op) && !isa(op) && - !isa(op)) + !isa(op) && !isa(op)) return false; + if (auto *sbi = dyn_cast(op)) { + op = sbi->getDest(); + continue; + } op = cast(op)->getOperand(0); } return true; @@ -253,9 +265,14 @@ replaceLoad(SILInstruction *inst, SILValue newValue, AllocStackInst *asi, while (op != asi) { assert(isa(op) || isa(op) || - isa(op) && + isa(op) || + isa(op) && "found instruction that should have been skipped in " "isLoadFromStack"); + if (auto *sbi = dyn_cast(op)) { + op = sbi->getDest(); + continue; + } auto *projInst = cast(op); projections.push_back(Projection(projInst)); op = projInst->getOperand(0); @@ -285,7 +302,7 @@ replaceLoad(SILInstruction *inst, SILValue newValue, AllocStackInst *asi, if (auto *lbi = dyn_cast(inst)) { if (shouldAddLexicalLifetime(asi)) { - assert(isa(newValue) || isa(newValue)); + assert(newValue->getOwnershipKind() == OwnershipKind::Guaranteed); SmallVector endBorrows; for (auto *ebi : lbi->getUsersOfType()) { endBorrows.push_back(ebi); @@ -319,7 +336,13 @@ replaceLoad(SILInstruction *inst, SILValue newValue, AllocStackInst *asi, while (op != asi && op->use_empty()) { assert(isa(op) || isa(op) || - isa(op)); + isa(op) || isa(op)); + if (auto *sbi = dyn_cast(op)) { + SILValue next = sbi->getDest(); + deleter.forceDelete(sbi); + op = next; + continue; + } auto *inst = cast(op); SILValue next = inst->getOperand(0); deleter.forceDelete(inst); @@ -354,6 +377,29 @@ static bool shouldAddLexicalLifetime(AllocStackInst *asi) { !asi->getElementType().isTrivial(*asi->getFunction()); } +static bool isGuaranteedLexicalValue(SILValue src) { + if (src->getOwnershipKind() != OwnershipKind::Guaranteed) { + return false; + } + if (isa(src)) { + return true; + } + if (auto *bbi = dyn_cast(src)) { + return bbi->isLexical(); + } + return false; +} + +/// Returns true if we have enough information to end the lifetime. +/// +/// The lifetime cannot be ended during this if we don't have enough information +/// to end it. That can occur when the running value associated with a +/// store_borrow does not have a borrow, because the source already guarantees +/// lexical lifetime or we have a load which was not preceeded by a store in the +/// basic block. In that case, the lifetime end will be added later, when we +/// have enough information, namely the live in values, to end it. +static bool canEndLexicalLifetime(LiveValues values) { return values.borrow; } + /// Begin a lexical borrow scope for the value stored into the provided /// StoreInst after that instruction. /// @@ -361,24 +407,36 @@ static bool shouldAddLexicalLifetime(AllocStackInst *asi) { /// /// %lifetime = begin_borrow %original /// %copy = copy_value %lifetime +/// For a StoreBorrowInst, begin a lexical borrow scope only if the stored value +/// is non-lexical. static StorageStateTracking -beginLexicalLifetimeAfterStore(AllocStackInst *asi, StoreInst *si) { +beginLexicalLifetimeAfterStore(AllocStackInst *asi, SILInstruction *inst) { + assert(isa(inst) || isa(inst)); assert(shouldAddLexicalLifetime(asi)); + SILValue stored = inst->getOperand(CopyLikeInstruction::Src); + SILLocation loc = RegularLocation::getAutoGeneratedLocation(inst->getLoc()); + + if (auto *sbi = dyn_cast(inst)) { + if (isGuaranteedLexicalValue(sbi->getSrc())) { + return {{stored, SILValue(), SILValue()}, /*isStorageValid*/ true}; + } + auto *borrow = SILBuilderWithScope(sbi).createBeginBorrow( + loc, stored, /*isLexical*/ true); + return {{stored, borrow, SILValue()}, /*isStorageValid*/ true}; + } BeginBorrowInst *bbi = nullptr; CopyValueInst *cvi = nullptr; - SILBuilderWithScope::insertAfter(si, [&](SILBuilder &builder) { - SILLocation loc = RegularLocation::getAutoGeneratedLocation(si->getLoc()); - bbi = builder.createBeginBorrow(loc, si->getSrc(), - /*isLexical*/ true); + SILBuilderWithScope::insertAfter(inst, [&](SILBuilder &builder) { + bbi = builder.createBeginBorrow(loc, stored, /*isLexical*/ true); cvi = builder.createCopyValue(loc, bbi); }); - StorageStateTracking vals = {{si->getSrc(), bbi, cvi}, + StorageStateTracking vals = {{stored, bbi, cvi}, /*isStorageValid=*/true}; return vals; } -/// End the lexical borrow scope described by the provided LiveValues struct -/// before the specified instruction. +/// End the lexical borrow scope for an @owned stored value described by the +/// provided LiveValues struct before the specified instruction. /// /// The end of the scope looks like /// @@ -390,10 +448,10 @@ beginLexicalLifetimeAfterStore(AllocStackInst *asi, StoreInst *si) { /// /// %lifetime = begin_borrow %original /// %copy = copy_value %lifetime -static void endLexicalLifetimeBeforeInst(AllocStackInst *asi, - SILInstruction *beforeInstruction, - SILBuilderContext &ctx, - LiveValues values) { +static void endOwnedLexicalLifetimeBeforeInst(AllocStackInst *asi, + SILInstruction *beforeInstruction, + SILBuilderContext &ctx, + LiveValues values) { assert(shouldAddLexicalLifetime(asi)); assert(beforeInstruction); @@ -401,7 +459,21 @@ static void endLexicalLifetimeBeforeInst(AllocStackInst *asi, SILLocation loc = RegularLocation::getAutoGeneratedLocation(beforeInstruction->getLoc()); builder.createEndBorrow(loc, values.borrow); - builder.emitDestroyValueOperation(loc, values.stored); + builder.createDestroyValue(loc, values.stored); +} + +/// End the lexical borrow scope for an @guaranteed stored value described by +/// the provided LiveValues struct before the specified instruction. +static void endGuaranteedLexicalLifetimeBeforeInst( + AllocStackInst *asi, SILInstruction *beforeInstruction, + SILBuilderContext &ctx, LiveValues values) { + assert(shouldAddLexicalLifetime(asi)); + assert(beforeInstruction); + assert(values.borrow); + + SILBuilderWithScope builder(beforeInstruction); + builder.createEndBorrow(RegularLocation::getAutoGeneratedLocation(), + values.borrow); } //===----------------------------------------------------------------------===// @@ -456,11 +528,13 @@ class StackAllocationPromoter { /// /// The live-out values for every block can be derived from these. /// - /// For non-lexical alloc_stacks, that is just a StoreInst. For lexical - /// alloc_stacks, that is the StoreInst, a BeginBorrowInst of the + /// For non-lexical alloc_stacks, that is just a StoreInst or a + /// StoreBorrowInst. + /// For lexical alloc_stacks, that is the StoreInst, a BeginBorrowInst of the /// value stored into the StoreInst and a CopyValueInst of the result of the - /// BeginBorrowInst. - BlockToInstMap initializationPoints; + /// BeginBorrowInst or a StoreBorrowInst, and a BeginBorrowInst of the stored + /// value if it did not have a guaranteed lexical scope. + BlockToInstMap<> initializationPoints; /// The first instruction in each block that deinitializes the storage that is /// not preceeded by an instruction that initializes it. @@ -469,7 +543,8 @@ class StackAllocationPromoter { /// store /// destroy_addr /// load [take] - /// + /// Or + /// end_borrow /// Ending lexical lifetimes before these instructions is one way that the /// cross-block lexical lifetimes of initializationPoints can be ended in /// StackAllocationPromoter::endLexicalLifetime. @@ -566,12 +641,12 @@ class StackAllocationPromoter { /// for the first load and the last store. /// \returns the last StoreInst found, whose storage was not subsequently /// deinitialized - StoreInst *promoteAllocationInBlock(SILBasicBlock *block); + SILInstruction *promoteAllocationInBlock(SILBasicBlock *block); }; } // end of namespace -StoreInst *StackAllocationPromoter::promoteAllocationInBlock( +SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( SILBasicBlock *blockPromotingWithin) { LLVM_DEBUG(llvm::dbgs() << "*** Promoting ASI in block: " << *asi); @@ -580,20 +655,7 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( Optional> runningVals; // Keep track of the last StoreInst that we found and the BeginBorrowInst and // CopyValueInst that we created in response if the alloc_stack was lexical. - Optional> lastStoreInst; - - /// Returns true if we have enough information to end the lifetime during - /// promoteAllocationInBlock. - /// - /// The lifetime cannot be ended during this function's execution if we don't - /// yet have enough information to end it. That occurs when the running - /// values are from a load which was not preceeded by a store. In that case, - /// the lifetime end will be added later, when we have enough information, - /// namely the live in values, to end it. - auto canEndLexicalLifetime = - [](StorageStateTracking values) -> bool { - return values.value.borrow; - }; + Optional> lastStoreInst; // For all instructions in the block. for (auto bbi = blockPromotingWithin->begin(), @@ -609,10 +671,10 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( if (shouldAddLexicalLifetime(asi)) { // End the lexical lifetime at a load [take]. The storage is no // longer keeping the value alive. - if (runningVals && canEndLexicalLifetime(*runningVals)) { + if (runningVals && canEndLexicalLifetime(runningVals->value)) { // End it right now if we have enough information. - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/li, ctx, - runningVals->value); + endOwnedLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/li, + ctx, runningVals->value); } else { // If we dont't have enough information, end it endLexicalLifetime. assert(!deinitializationPoints[blockPromotingWithin]); @@ -674,12 +736,12 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( // If we met a store before this one, delete it. if (lastStoreInst) { - assert(lastStoreInst->value->getOwnershipQualifier() != + assert(cast(lastStoreInst->value)->getOwnershipQualifier() != StoreOwnershipQualifier::Assign && "store [assign] to the stack location should have been " "transformed to a store [init]"); - LLVM_DEBUG(llvm::dbgs() - << "*** Removing redundant store: " << *lastStoreInst->value); + LLVM_DEBUG(llvm::dbgs() << "*** Removing redundant store: " + << *lastStoreInst->value); ++NumInstRemoved; prepareForDeletion(lastStoreInst->value, instructionsToDelete); } @@ -690,15 +752,64 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( /*isStorageValid=*/true}; // The current store is now the lastStoreInst (until we see // another). - lastStoreInst = {si, /*isStorageValid=*/true}; + lastStoreInst = {inst, /*isStorageValid=*/true}; if (shouldAddLexicalLifetime(asi)) { if (oldRunningVals && oldRunningVals->isStorageValid && - canEndLexicalLifetime(*oldRunningVals)) { - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/si, ctx, - oldRunningVals->value); + canEndLexicalLifetime(oldRunningVals->value)) { + endOwnedLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/inst, + ctx, oldRunningVals->value); } - runningVals = beginLexicalLifetimeAfterStore(asi, si); + runningVals = beginLexicalLifetimeAfterStore(asi, inst); + } + continue; + } + + if (auto *sbi = dyn_cast(inst)) { + if (sbi->getDest() != asi) + continue; + + // If we met a store before this one, delete it. + if (lastStoreInst) { + LLVM_DEBUG(llvm::dbgs() << "*** Removing redundant store: " + << *lastStoreInst->value); + ++NumInstRemoved; + prepareForDeletion(lastStoreInst->value, instructionsToDelete); + } + + // The stored value is the new running value. + runningVals = {LiveValues::toReplace(asi, sbi->getSrc()), + /*isStorageValid=*/true}; + // The current store is now the lastStoreInst. + lastStoreInst = {inst, /*isStorageValid=*/true}; + if (shouldAddLexicalLifetime(asi)) { + runningVals = beginLexicalLifetimeAfterStore(asi, inst); + } + continue; + } + + // End the lexical lifetime of the store_borrow source. + if (auto *ebi = dyn_cast(inst)) { + if (!shouldAddLexicalLifetime(asi)) { + continue; + } + auto *sbi = dyn_cast(ebi->getOperand()); + if (!sbi) { + continue; + } + if (!runningVals.hasValue()) { + assert(!deinitializationPoints[blockPromotingWithin]); + deinitializationPoints[blockPromotingWithin] = inst; + continue; + } + if (sbi->getSrc() != runningVals->value.stored) { + continue; + } + runningVals->isStorageValid = false; + if (!canEndLexicalLifetime(runningVals->value)) { + continue; } + endGuaranteedLexicalLifetimeBeforeInst(asi, ebi->getNextInstruction(), + ctx, runningVals->value); continue; } @@ -722,8 +833,8 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( replaceDestroy(dai, runningVals->value.replacement(asi, dai), ctx, deleter, instructionsToDelete); if (shouldAddLexicalLifetime(asi)) { - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/dai, ctx, - runningVals->value); + endOwnedLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/dai, ctx, + runningVals->value); } runningVals->isStorageValid = false; if (lastStoreInst) @@ -743,8 +854,9 @@ StoreInst *StackAllocationPromoter::promoteAllocationInBlock( } if (lastStoreInst && lastStoreInst->isStorageValid) { - assert(lastStoreInst->value->getOwnershipQualifier() != - StoreOwnershipQualifier::Assign && + assert((isa(lastStoreInst->value) || + (cast(lastStoreInst->value)->getOwnershipQualifier() != + StoreOwnershipQualifier::Assign)) && "store [assign] to the stack location should have been " "transformed to a store [init]"); LLVM_DEBUG(llvm::dbgs() << "*** Finished promotion. Last store: " @@ -782,18 +894,29 @@ StackAllocationPromoter::getLiveOutValues(BlockSetVector &phiBlocks, SILBasicBlock *domBlock = domNode->getBlock(); // If there is a store (that must come after the phi), use its value. - BlockToInstMap::iterator it = - initializationPoints.find(domBlock); + BlockToInstMap<>::iterator it = initializationPoints.find(domBlock); if (it != initializationPoints.end()) { - auto *si = it->second; - LLVM_DEBUG(llvm::dbgs() << "*** Found Store def " << si->getSrc()); - SILValue stored = si->getSrc(); - SILValue borrow = SILValue(); - SILValue copy = SILValue(); - if (shouldAddLexicalLifetime(asi)) { - borrow = cast(&*std::next(si->getIterator())); - copy = cast(borrow->getNextInstruction()); + auto *inst = it->second; + assert(isa(inst) || isa(inst)); + + SILValue stored = inst->getOperand(CopyLikeInstruction::Src); + LLVM_DEBUG(llvm::dbgs() << "*** Found Store def " << stored); + + if (!shouldAddLexicalLifetime(asi)) { + LiveValues values = {stored, SILValue(), SILValue()}; + return values; } + if (auto *sbi = dyn_cast(inst)) { + if (isGuaranteedLexicalValue(sbi->getSrc())) { + LiveValues values = {stored, SILValue(), SILValue()}; + return values; + } + auto borrow = cast(sbi->getNextInstruction()); + LiveValues values = {stored, borrow, SILValue()}; + return values; + } + auto borrow = cast(inst->getNextInstruction()); + auto copy = cast(borrow->getNextInstruction()); LiveValues values = {stored, borrow, copy}; return values; } @@ -954,9 +1077,21 @@ void StackAllocationPromoter::fixBranchesAndUses(BlockSetVector &phiBlocks, BlockSetVector &phiBlocksOut) { // First update uses of the value. SmallVector collectedLoads; + // Collect all alloc_stack uses. + SmallVector uses(asi->getUses()); + + // Collect uses of store_borrows to alloc_stack. + for (unsigned i = 0; i < uses.size(); i++) { + auto *use = uses[i]; + if (auto *sbi = dyn_cast(use->getUser())) { + for (auto *sbuse : sbi->getUses()) { + uses.push_back(sbuse); + } + } + } - for (auto ui = asi->use_begin(), ue = asi->use_end(); ui != ue;) { - auto *user = ui->getUser(); + for (auto ui = uses.begin(), ue = uses.end(); ui != ue;) { + auto *user = (*ui)->getUser(); ++ui; bool removedUser = false; @@ -1160,8 +1295,18 @@ void StackAllocationPromoter::endLexicalLifetime(BlockSetVector &phiBlocks) { case AvailableValuesKind::In: { if (auto *inst = deinitializationPoints[bb]) { auto values = getLiveInValues(phiBlocks, bb); - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/inst, ctx, - *values); + if (isa(inst)) { + // Not all store_borrows will have a begin_borrow [lexical] that needs + // to be ended. If the source is already lexical, we don't create it. + if (!canEndLexicalLifetime(*values)) { + continue; + } + endGuaranteedLexicalLifetimeBeforeInst( + asi, /*beforeInstruction=*/inst, ctx, *values); + continue; + } + endOwnedLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/inst, ctx, + *values); continue; } worklist.insert({bb, AvailableValuesKind::Out}); @@ -1175,7 +1320,15 @@ void StackAllocationPromoter::endLexicalLifetime(BlockSetVector &phiBlocks) { }; if (terminatesInUnreachable || uniqueSuccessorLacksLiveInValues()) { auto values = getLiveOutValues(phiBlocks, bb); - endLexicalLifetimeBeforeInst( + if (values->stored->getOwnershipKind() == OwnershipKind::Guaranteed) { + if (!canEndLexicalLifetime(*values)) { + continue; + } + endGuaranteedLexicalLifetimeBeforeInst( + asi, /*beforeInstruction=*/bb->getTerminator(), ctx, *values); + continue; + } + endOwnedLexicalLifetimeBeforeInst( asi, /*beforeInstruction=*/bb->getTerminator(), ctx, *values); continue; } @@ -1222,7 +1375,7 @@ void StackAllocationPromoter::promoteAllocationToPhi() { for (auto *use : asi->getUses()) { SILInstruction *user = use->getUser(); // We need to place Phis for this block. - if (isa(user)) { + if (isa(user) || isa(user)) { // If the block is in the dom tree (dominated by the entry block). if (auto *node = domInfo->getNode(user->getParent())) priorityQueue.push(std::make_pair(node, domTreeLevels[node])); @@ -1379,8 +1532,8 @@ class MemoryToRegisters { return *domTreeLevels; } - /// Check if the AllocStackInst \p ASI is only written into. - bool isWriteOnlyAllocation(AllocStackInst *asi); + /// Check if \p def is a write-only allocation. + bool isWriteOnlyAllocation(SILValue def); /// Promote all of the AllocStacks in a single basic block in one /// linear scan. Note: This function deletes all of the users of the @@ -1487,13 +1640,13 @@ static bool isDeadAddrProjection(SILInstruction *inst) { return true; } -/// Returns true if this AllocStacks is captured. -/// Sets \p inSingleBlock to true if all uses of \p asi are in a single block. -static bool isCaptured(AllocStackInst *asi, bool *inSingleBlock) { - SILBasicBlock *singleBlock = asi->getParent(); +/// Returns true if this \p def is captured. +/// Sets \p inSingleBlock to true if all uses of \p def are in a single block. +static bool isCaptured(SILValue def, bool *inSingleBlock) { + SILBasicBlock *singleBlock = def->getParentBlock(); - // For all users of the AllocStack instruction. - for (auto *use : asi->getUses()) { + // For all users of the def + for (auto *use : def->getUses()) { SILInstruction *user = use->getUser(); if (user->getParent() != singleBlock) @@ -1506,14 +1659,26 @@ static bool isCaptured(AllocStackInst *asi, bool *inSingleBlock) { // We can store into an AllocStack (but not the pointer). if (auto *si = dyn_cast(user)) - if (si->getDest() == asi) + if (si->getDest() == def) + continue; + + if (auto *sbi = dyn_cast(user)) { + if (sbi->getDest() == def) { + if (isCaptured(sbi, inSingleBlock)) { + return true; + } continue; + } + } // Deallocation is also okay, as are DebugValue w/ address value. We will // promote the latter into normal DebugValue. if (isa(user) || DebugValueInst::hasAddrVal(user)) continue; + if (isa(user)) + continue; + // Destroys of loadable types can be rewritten as releases, so // they are fine. if (auto *dai = dyn_cast(user)) @@ -1530,25 +1695,35 @@ static bool isCaptured(AllocStackInst *asi, bool *inSingleBlock) { return false; } -/// Returns true if the AllocStack is only stored into. -bool MemoryToRegisters::isWriteOnlyAllocation(AllocStackInst *asi) { - // For all users of the AllocStack: - for (auto *use : asi->getUses()) { +/// Returns true if the \p def is only stored into. +bool MemoryToRegisters::isWriteOnlyAllocation(SILValue def) { + assert(isa(def) || isa(def)); + + // For all users of the def: + for (auto *use : def->getUses()) { SILInstruction *user = use->getUser(); - // It is okay to store into this AllocStack. + // It is okay to store into the AllocStack. if (auto *si = dyn_cast(user)) if (!isa(si->getSrc())) continue; - if (auto *sbi = dyn_cast(user)) - if (!isa(sbi->getSrc())) - continue; + if (auto *sbi = dyn_cast(user)) { + // Since all uses of the alloc_stack will be via store_borrow, check if + // there are any non-writes from the store_borrow location. + if (!isWriteOnlyAllocation(sbi)) { + return false; + } + continue; + } // Deallocation is also okay. if (isa(user)) continue; + if (isa(user)) + continue; + // If we haven't already promoted the AllocStack, we may see // DebugValue uses. if (DebugValueInst::hasAddrVal(user)) @@ -1597,8 +1772,8 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) { if (shouldAddLexicalLifetime(asi)) { // End the lexical lifetime at a load [take]. The storage is no // longer keeping the value alive. - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/inst, ctx, - runningVals->value); + endOwnedLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/inst, + ctx, runningVals->value); } runningVals->isStorageValid = false; } @@ -1624,8 +1799,8 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) { /*isStorageValid=*/true}; if (shouldAddLexicalLifetime(asi)) { if (oldRunningVals && oldRunningVals->isStorageValid) { - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/si, ctx, - oldRunningVals->value); + endOwnedLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/si, ctx, + oldRunningVals->value); } runningVals = beginLexicalLifetimeAfterStore(asi, si); } @@ -1634,6 +1809,38 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) { continue; } + if (auto *sbi = dyn_cast(inst)) { + if (sbi->getDest() != asi) { + continue; + } + runningVals = {LiveValues::toReplace(asi, /*replacement=*/sbi->getSrc()), + /*isStorageValid=*/true}; + if (shouldAddLexicalLifetime(asi)) { + runningVals = beginLexicalLifetimeAfterStore(asi, inst); + } + continue; + } + + if (auto *ebi = dyn_cast(inst)) { + auto *sbi = dyn_cast(ebi->getOperand()); + if (!sbi) { + continue; + } + if (!runningVals.hasValue()) { + continue; + } + if (sbi->getSrc() != runningVals->value.stored) { + continue; + } + runningVals->isStorageValid = false; + if (!canEndLexicalLifetime(runningVals->value)) { + continue; + } + endGuaranteedLexicalLifetimeBeforeInst(asi, ebi->getNextInstruction(), + ctx, runningVals->value); + continue; + } + // Replace debug_value w/ address value with debug_value of // the promoted value. if (auto *dvi = DebugValueInst::hasAddrVal(inst)) { @@ -1658,8 +1865,8 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) { replaceDestroy(dai, runningVals->value.replacement(asi, dai), ctx, deleter, instructionsToDelete); if (shouldAddLexicalLifetime(asi)) { - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/dai, ctx, - runningVals->value); + endOwnedLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/dai, ctx, + runningVals->value); } runningVals->isStorageValid = false; } @@ -1689,8 +1896,10 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) { } } - if (runningVals && runningVals->isStorageValid && - shouldAddLexicalLifetime(asi)) { + if (shouldAddLexicalLifetime(asi) && runningVals && + runningVals->isStorageValid && + runningVals->value.stored->getOwnershipKind().isCompatibleWith( + OwnershipKind::Owned)) { // There is still valid storage after visiting all instructions in this // block which are the only instructions involving this alloc_stack. // This can only happen if all paths from this block end in unreachable. @@ -1702,8 +1911,8 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) { computeDominatedBoundaryBlocks(asi->getParent(), domInfo, boundary); for (auto *block : boundary) { auto *terminator = block->getTerminator(); - endLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/terminator, ctx, - runningVals->value); + endOwnedLexicalLifetimeBeforeInst(asi, /*beforeInstruction=*/terminator, + ctx, runningVals->value); } } } @@ -1743,17 +1952,7 @@ bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc) { LLVM_DEBUG(llvm::dbgs() << "*** Deleting single block AllocStackInst: " << *alloc); - if (alloc->use_empty()) { - deleter.forceDelete(alloc); - } else { - // Handle a corner case where the ASI still has uses: - // This can come up if the source contains a withUnsafePointer where - // the pointer escapes. It's illegal code but we should not crash. - // Re-insert a dealloc_stack so that the verifier is happy. - auto *next = alloc->getNextInstruction(); - SILBuilderWithScope b(next, ctx); - b.createDeallocStack(next->getLoc(), alloc); - } + deleter.forceDeleteWithUsers(alloc); return true; } else { // For enums we require that all uses are in the same block. diff --git a/test/SILOptimizer/mem2reg_borrows.sil b/test/SILOptimizer/mem2reg_borrows.sil index 35310a76abe52..e99b5c38257e5 100644 --- a/test/SILOptimizer/mem2reg_borrows.sil +++ b/test/SILOptimizer/mem2reg_borrows.sil @@ -79,23 +79,6 @@ bb0(%0 : @owned $Klass): return %6 : $() } -// CHECK-LABEL: sil [ossa] @test_no_storeborrow4 : -// CHECK-NOT: alloc_stack -// CHECK-LABEL: } // end sil function 'test_no_storeborrow4' -sil [ossa] @test_no_storeborrow4 : $@convention(thin) (@owned Klass) -> () { -bb0(%0 : @owned $Klass): - %1 = alloc_stack [lexical] $Klass - store %0 to [init] %1 : $*Klass - %2 = load_borrow %1 : $*Klass - %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () - %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () - end_borrow %2 : $Klass - destroy_addr %1 : $*Klass - dealloc_stack %1 : $*Klass - %6 = tuple () - return %6 : $() -} - // load_borrow of projections are not optimized // CHECK-LABEL: sil [ossa] @test_with_structs_and_borrows1 : // CHECK: alloc_stack @@ -114,10 +97,10 @@ bb0(%0 : @guaranteed $WrapperStruct): %r = tuple () return %r : $() } -// CHECK-LABEL: sil [ossa] @store_only_allocas : -// CHECK: alloc_stack -// CHECK-LABEL: } // end sil function 'store_only_allocas' -sil [ossa] @store_only_allocas : $@convention(thin) (@guaranteed Klass) -> () { +// CHECK-LABEL: sil [ossa] @storeborrow_only_allocas : +// CHECK-NOT: alloc_stack +// CHECK-LABEL: } // end sil function 'storeborrow_only_allocas' +sil [ossa] @storeborrow_only_allocas : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): %1 = alloc_stack $Klass %2 = store_borrow %0 to %1 : $*Klass @@ -127,21 +110,8 @@ bb0(%0 : @guaranteed $Klass): return %6 : $() } -// CHECK-LABEL: sil [ossa] @store_only_lexicalallocas : -// CHECK: alloc_stack -// CHECK-LABEL: } // end sil function 'store_only_lexicalallocas' -sil [ossa] @store_only_lexicalallocas : $@convention(thin) (@guaranteed Klass) -> () { -bb0(%0 : @guaranteed $Klass): - %1 = alloc_stack [lexical] $Klass - %2 = store_borrow %0 to %1 : $*Klass - end_borrow %2 : $*Klass - dealloc_stack %1 : $*Klass - %6 = tuple () - return %6 : $() -} - // CHECK-LABEL: sil [ossa] @test1 : -// CHECK: alloc_stack +// CHECK-NOT: alloc_stack // CHECK-LABEL: } // end sil function 'test1' sil [ossa] @test1 : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): @@ -158,7 +128,7 @@ bb0(%0 : @guaranteed $Klass): } // CHECK-LABEL: sil [ossa] @test1_lexical : -// CHECK: alloc_stack +// CHECK-NOT: alloc_stack // CHECK-LABEL: } // end sil function 'test1_lexical' sil [ossa] @test1_lexical : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): @@ -175,7 +145,7 @@ bb0(%0 : @guaranteed $Klass): } // CHECK-LABEL: sil [ossa] @test2 : -// CHECK: alloc_stack +// CHECK-NOT: alloc_stack // CHECK-LABEL: } // end sil function 'test2' sil [ossa] @test2 : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): @@ -196,7 +166,7 @@ bb0(%0 : @guaranteed $Klass): } // CHECK-LABEL: sil [ossa] @test3 : -// CHECK: alloc_stack +// CHECK-NOT: alloc_stack // CHECK-LABEL: } // end sil function 'test3' sil [ossa] @test3 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): @@ -218,7 +188,7 @@ bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): } // CHECK-LABEL: sil [ossa] @test4 : -// CHECK: alloc_stack +// CHECK-NOT: alloc_stack // CHECK-LABEL: } // end sil function 'test4' sil [ossa] @test4 : $@convention(thin) (@guaranteed Klass) -> () { bb0(%0 : @guaranteed $Klass): @@ -238,7 +208,7 @@ bb0(%0 : @guaranteed $Klass): } // CHECK-LABEL: sil [ossa] @test6 : -// CHECK: alloc_stack +// CHECK-NOT: alloc_stack // CHECK-LABEL: } // end sil function 'test6' sil [ossa] @test6 : $@convention(thin) (@owned Klass) -> () { bb0(%0 : @owned $Klass): diff --git a/test/SILOptimizer/mem2reg_lifetime_borrows.sil b/test/SILOptimizer/mem2reg_lifetime_borrows.sil new file mode 100644 index 0000000000000..94c1e4f71af0c --- /dev/null +++ b/test/SILOptimizer/mem2reg_lifetime_borrows.sil @@ -0,0 +1,454 @@ +// RUN: %target-sil-opt -enable-sil-verify-all -enable-lexical-lifetimes %s -mem2reg | %FileCheck %s +import Builtin + +class Klass {} + +struct WrapperStruct { + var val:Klass +} + +public enum FakeOptional { + case none + case some(Klass) +} + +sil [ossa] @use_inguaranteed : $@convention(thin) (@in_guaranteed Klass) -> () +sil [ossa] @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () +sil [ossa] @use_owned : $@convention(thin) (@owned Klass) -> () +sil [ossa] @get_owned : $@convention(thin) () -> @owned Klass + +// CHECK-LABEL: sil [ossa] @test_no_storeborrow1 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_no_storeborrow1' +sil [ossa] @test_no_storeborrow1 : $@convention(thin) (@owned Klass) -> () { +bb0(%0 : @owned $Klass): + %stk = alloc_stack [lexical] $Klass + store %0 to [init] %stk : $*Klass + %ld = load_borrow %stk : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%ld) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %ld : $Klass + destroy_addr %stk : $*Klass + dealloc_stack %stk : $*Klass + %6 = tuple () + return %6 : $() +} + +// CHECK-LABEL: sil [ossa] @test_no_storeborrow2 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_no_storeborrow2' +sil [ossa] @test_no_storeborrow2 : $@convention(method) (@owned Klass) -> () { +bb0(%0 : @owned $Klass): + %stk = alloc_stack [lexical] $Klass + store %0 to [init] %stk : $*Klass + %ld1 = load_borrow %stk : $*Klass + %f = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + apply %f(%ld1) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %ld1 : $Klass + cond_br undef, bb3, bb1 + +bb1: + %ld2 = load_borrow %stk : $*Klass + apply %f(%ld2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %ld2 : $Klass + %tk1 = load [take] %stk : $*Klass + destroy_value %tk1 : $Klass + dealloc_stack %stk : $*Klass + br bb4 + +bb3: + %tk2 = load [take] %stk : $*Klass + destroy_value %tk2 : $Klass + dealloc_stack %stk : $*Klass + br bb4 + +bb4: + %ret = tuple () + return %ret : $() +} + +// CHECK-LABEL: sil [ossa] @test_no_storeborrow3 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_no_storeborrow3' +sil [ossa] @test_no_storeborrow3 : $@convention(thin) (@owned Klass) -> () { +bb0(%0 : @owned $Klass): + %1 = alloc_stack [lexical] $Klass + store %0 to [init] %1 : $*Klass + %2 = load_borrow %1 : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %2 : $Klass + destroy_addr %1 : $*Klass + dealloc_stack %1 : $*Klass + %6 = tuple () + return %6 : $() +} + +// CHECK-LABEL: sil [ossa] @test_no_storeborrow4 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_no_storeborrow4' +sil [ossa] @test_no_storeborrow4 : $@convention(thin) (@owned Klass) -> () { +bb0(%0 : @owned $Klass): + %1 = alloc_stack [lexical] $Klass + store %0 to [init] %1 : $*Klass + %2 = load_borrow %1 : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %2 : $Klass + destroy_addr %1 : $*Klass + dealloc_stack %1 : $*Klass + %6 = tuple () + return %6 : $() +} + +// load_borrow of projections are not optimized +// CHECK-LABEL: sil [ossa] @test_with_structs_and_borrows1 : +// CHECK: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_with_structs_and_borrows1' +sil [ossa] @test_with_structs_and_borrows1 : $@convention(thin) (@guaranteed WrapperStruct) -> () { +bb0(%0 : @guaranteed $WrapperStruct): + %stk = alloc_stack [lexical] $WrapperStruct + %sb = store_borrow %0 to %stk : $*WrapperStruct + %ele = struct_element_addr %sb : $*WrapperStruct, #WrapperStruct.val + %ld = load_borrow %ele : $*Klass + %f = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + apply %f(%ld) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %ld : $Klass + end_borrow %sb : $*WrapperStruct + dealloc_stack %stk : $*WrapperStruct + %r = tuple () + return %r : $() +} + +// CHECK-LABEL: sil [ossa] @storeborrow_only_lexicalallocas : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'storeborrow_only_lexicalallocas' +sil [ossa] @storeborrow_only_lexicalallocas : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %1 = alloc_stack [lexical] $Klass + %sb = store_borrow %0 to %1 : $*Klass + end_borrow %sb : $*Klass + dealloc_stack %1 : $*Klass + %6 = tuple () + return %6 : $() +} + +// CHECK-LABEL: sil [ossa] @test1 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test1' +sil [ossa] @test1 : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %1 = alloc_stack [lexical] $Klass + %sb = store_borrow %0 to %1 : $*Klass + %2 = load_borrow %sb : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %2 : $Klass + end_borrow %sb : $*Klass + dealloc_stack %1 : $*Klass + %6 = tuple () + return %6 : $() +} + +// CHECK-LABEL: sil [ossa] @test2 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test2' +sil [ossa] @test2 : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %1 = alloc_stack [lexical] $Klass + %sb = store_borrow %0 to %1 : $*Klass + %2 = load_borrow %sb : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %2 : $Klass + %5 = load_borrow %sb : $*Klass + %6 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %7 = apply %3(%5) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %5 : $Klass + end_borrow %sb : $*Klass + dealloc_stack %1 : $*Klass + %8 = tuple () + return %8 : $() +} + +// CHECK-LABEL: sil [ossa] @test3 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test3' +sil [ossa] @test3 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): + %2 = alloc_stack [lexical] $Klass + %sb1 = store_borrow %0 to %2 : $*Klass + %3 = load_borrow %sb1 : $*Klass + %4 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %5 = apply %4(%3) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %3 : $Klass + end_borrow %sb1 : $*Klass + %sb2 = store_borrow %1 to %2 : $*Klass + %6 = load_borrow %sb2 : $*Klass + %7 = apply %4(%6) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %6 : $Klass + end_borrow %sb2 : $*Klass + dealloc_stack %2 : $*Klass + %9 = tuple () + return %9 : $() +} + +// CHECK-LABEL: sil [ossa] @test4 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test4' +sil [ossa] @test4 : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %1 = alloc_stack [lexical] $Klass + %sb = store_borrow %0 to %1 : $*Klass + %2 = load_borrow %sb : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %2 : $Klass + %5 = load [copy] %sb : $*Klass + end_borrow %sb : $*Klass + %6 = function_ref @use_owned : $@convention(thin) (@owned Klass) -> () + %7 = apply %6(%5) : $@convention(thin) (@owned Klass) -> () + dealloc_stack %1 : $*Klass + %8 = tuple () + return %8 : $() +} + +// CHECK-LABEL: sil [ossa] @test6 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test6' +sil [ossa] @test6 : $@convention(thin) (@owned Klass) -> () { +bb0(%0 : @owned $Klass): + %1 = alloc_stack [lexical] $Klass + %b = begin_borrow %0 : $Klass + %sb = store_borrow %b to %1 : $*Klass + %2 = load_borrow %sb : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %2 : $Klass + end_borrow %sb : $*Klass + end_borrow %b : $Klass + destroy_value %0 : $Klass + dealloc_stack %1 : $*Klass + %6 = tuple () + return %6 : $() +} + +// CHECK-LABEL: sil [ossa] @test7 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test7' +sil [ossa] @test7 : $@convention(thin) (@owned Klass) -> () { +bb0(%0 : @owned $Klass): + %1 = alloc_stack [lexical] $Klass + %b = begin_borrow %0 : $Klass + %sb = store_borrow %b to %1 : $*Klass + %2 = load_borrow %sb : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %2 : $Klass + end_borrow %sb : $*Klass + end_borrow %b : $Klass + destroy_value %0 : $Klass + unreachable +} + +// CHECK-LABEL: sil [ossa] @test8 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test8' +sil [ossa] @test8 : $@convention(thin) (@owned Klass) -> () { +bb0(%0 : @owned $Klass): + %1 = alloc_stack [lexical] $Klass + %b = begin_borrow %0 : $Klass + %sb = store_borrow %b to %1 : $*Klass + %2 = load [copy] %sb : $*Klass + end_borrow %sb : $*Klass + end_borrow %b : $Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + destroy_value %2 : $Klass + destroy_value %0 : $Klass + dealloc_stack %1 : $*Klass + %6 = tuple () + return %6 : $() +} + +// CHECK-LABEL: sil [ossa] @test_control_flow4 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_control_flow4' +sil [ossa] @test_control_flow4 : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack [lexical] $Klass + %sb = store_borrow %0 to %stk : $*Klass + cond_br undef, bb1, bb2 + +bb1: + %ld1 = load_borrow %sb : $*Klass + fix_lifetime %ld1 : $Klass + end_borrow %ld1 : $Klass + end_borrow %sb : $*Klass + dealloc_stack %stk : $*Klass + %r = tuple () + return %r : $() + +bb2: + %ld2 = load_borrow %sb : $*Klass + fix_lifetime %ld2 : $Klass + end_borrow %ld2 : $Klass + end_borrow %sb : $*Klass + dealloc_stack %stk : $*Klass + unreachable +} + +// CHECK-LABEL: sil [ossa] @test_control_flow5 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_control_flow5' +sil [ossa] @test_control_flow5 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass): + %stk = alloc_stack [lexical] $Klass + cond_br undef, bb1, bb2 + +bb1: + %copy1 = copy_value %0 : $Klass + store %copy1 to [init] %stk : $*Klass + br bb3 + +bb2: + %copy2 = copy_value %1 : $Klass + store %copy2 to [init] %stk : $*Klass + br bb3 + +bb3: + %2 = load_borrow %stk : $*Klass + %3 = function_ref @use_guaranteed : $@convention(thin) (@guaranteed Klass) -> () + %4 = apply %3(%2) : $@convention(thin) (@guaranteed Klass) -> () + end_borrow %2 : $Klass + destroy_addr %stk : $*Klass + dealloc_stack %stk : $*Klass + %8 = tuple () + return %8 : $() +} + +// Test no ownership verifier error +// CHECK-LABEL: sil [ossa] @test_control_flow6 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_control_flow6' +sil [ossa] @test_control_flow6 : $@convention(thin) () -> () { +bb0: + %0 = function_ref @get_owned : $@convention(thin) () -> @owned Klass + %1 = alloc_stack [lexical] $Klass + %2 = apply %0() : $@convention(thin) () -> @owned Klass + store %2 to [init] %1 : $*Klass + cond_br undef, bb1, bb2 + +bb1: + %5 = apply %0() : $@convention(thin) () -> @owned Klass + store %5 to [assign] %1 : $*Klass + br bb3 + +bb2: + br bb3 + +bb3: + %9 = load_borrow %1 : $*Klass + end_borrow %9 : $Klass + br bb4 + +bb4: + cond_br undef, bb8, bb9 + +bb8: + br bb4 + +bb9: + cond_br undef, bb10, bb11 + +bb10: + br bb12 + +bb11: + %19 = load [copy] %1 : $*Klass + %20 = function_ref @use_owned : $@convention(thin) (@owned Klass) -> () + %21 = apply %20(%19) : $@convention(thin) (@owned Klass) -> () + br bb12 + +bb12: + %23 = apply %0() : $@convention(thin) () -> @owned Klass + store %23 to [assign] %1 : $*Klass + cond_br undef, bb13, bb14 + +bb13: + %26 = load [take] %1 : $*Klass + destroy_value %26 : $Klass + dealloc_stack %1 : $*Klass + %29 = tuple () + return %29 : $() + +bb14: + unreachable +} + +// CHECK-LABEL: sil [ossa] @test_control_flow7 : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_control_flow7' +sil [ossa] @test_control_flow7 : $@convention(thin) () -> () { +bb0: + %4 = alloc_stack [lexical] $Klass + %f = function_ref @get_owned : $@convention(thin) () -> @owned Klass + %5 = apply %f() : $@convention(thin) () -> @owned Klass + store %5 to [init] %4 : $*Klass + %7 = load_borrow %4 : $*Klass + end_borrow %7 : $Klass + cond_br undef, bb1, bb2 + +bb1: + br bb3 + +bb2: + %28 = load_borrow %4 : $*Klass + end_borrow %28 : $Klass + br bb3 + +bb3: + destroy_addr %4 : $*Klass + dealloc_stack %4 : $*Klass + %r = tuple () + return %r : $() +} + +// Test no ownership verifier error +// CHECK-LABEL: sil [ossa] @test_two_stacklocs : +// CHECK: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_two_stacklocs' +sil [ossa] @test_two_stacklocs : $@convention(method) (@guaranteed WrapperStruct) -> () { +bb0(%0 : @guaranteed $WrapperStruct): + %2 = struct_extract %0 : $WrapperStruct, #WrapperStruct.val + %3 = alloc_stack [lexical] $Klass + %4 = store_borrow %2 to %3 : $*Klass + %5 = load_borrow %4 : $*Klass + %6 = alloc_stack [lexical] $Klass + %7 = store_borrow %5 to %6 : $*Klass + %f = function_ref @use_inguaranteed : $@convention(thin) (@in_guaranteed Klass) -> () + apply %f(%7) : $@convention(thin) (@in_guaranteed Klass) -> () + end_borrow %7 : $*Klass + end_borrow %5 : $Klass + end_borrow %4 : $*Klass + dealloc_stack %6 : $*Klass + dealloc_stack %3 : $*Klass + %t = tuple () + return %t : $() +} + +// CHECK-LABEL: sil [ossa] @test_optional : +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_optional' +sil [ossa] @test_optional : $@convention(thin) () -> () { +bb0: + %stk = alloc_stack [lexical] $FakeOptional + %none = enum $FakeOptional, #FakeOptional.none!enumelt + %sb = store_borrow %none to %stk : $*FakeOptional + %ld1 = load_borrow %sb : $*FakeOptional + end_borrow %ld1 : $FakeOptional + end_borrow %sb : $*FakeOptional + dealloc_stack %stk : $*FakeOptional + %r = tuple () + return %r : $() +} From 847c060eaf85092763e848dad1f92e6cb3ec096a Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 25 Aug 2022 16:31:17 -0400 Subject: [PATCH 381/491] Fix a potential use-after-free in lazy global emission. Extended existential type shapes can trigger this by introducing more entities (and thus causing GlobalVars to be rehashed) during the lazy-emission callback. Fixes rdar://98995607 --- lib/IRGen/GenDecl.cpp | 26 +++++++++++++++--------- validation-test/IRGen/98995607.swift.gyb | 21 +++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 validation-test/IRGen/98995607.swift.gyb diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 62f87b785567f..c974807734971 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -3509,9 +3509,9 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, ? overrideDeclType : entity.getDefaultDeclarationType(*this); - auto &entry = GlobalVars[entity]; - if (entry) { - auto existing = cast(entry); + auto existingGlobal = GlobalVars[entity]; + if (existingGlobal) { + auto existing = cast(existingGlobal); // If we're looking to define something, we may need to replace a // forward declaration. @@ -3531,12 +3531,12 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, // Fall out to the case below, clearing the name so that // createVariable doesn't detect a collision. - entry->setName(""); + existingGlobal->setName(""); // Otherwise, we have a previous declaration or definition which // we need to ensure has the right type. } else { - return getElementBitCast(entry, defaultType); + return getElementBitCast(existingGlobal, defaultType); } } @@ -3580,11 +3580,17 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, lazyInitializer->Create(var); } + if (lazyInitializer) { + // Protect against self-references that might've been created during + // the lazy emission. + existingGlobal = GlobalVars[entity]; + } + // If we have an existing entry, destroy it, replacing it with the - // new variable. - if (entry) { - auto existing = cast(entry); - auto castVar = llvm::ConstantExpr::getBitCast(var, entry->getType()); + // new variable. We only really have to do + if (existingGlobal) { + auto existing = cast(existingGlobal); + auto castVar = llvm::ConstantExpr::getBitCast(var, existing->getType()); existing->replaceAllUsesWith(castVar); existing->eraseFromParent(); } @@ -3607,7 +3613,7 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, } // Cache and return. - entry = var; + GlobalVars[entity] = var; return var; } diff --git a/validation-test/IRGen/98995607.swift.gyb b/validation-test/IRGen/98995607.swift.gyb new file mode 100644 index 0000000000000..35d2959fd0b47 --- /dev/null +++ b/validation-test/IRGen/98995607.swift.gyb @@ -0,0 +1,21 @@ +// RUN: %target-run-simple-swiftgyb + +%for N in range(0, 100): + +protocol P${N} { + associatedtype A + associatedtype B +} + +%end + +var array : [Any.Type] = [ +%for N in range(0, 100): + (any P${N}).self, +%end +%for N in range(0, 100): + (any P${N}).self, +%end +] + +print(array) From ed7788fff1734cf17eecdf021902375c06f07820 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Thu, 25 Aug 2022 13:20:24 -0700 Subject: [PATCH 382/491] Get rid of isStorageValid flag on lastStoreInst --- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 36 ++++++++++------------ 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index ad47fe7d54323..3cdc1f8e4101c 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -655,7 +655,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( Optional> runningVals; // Keep track of the last StoreInst that we found and the BeginBorrowInst and // CopyValueInst that we created in response if the alloc_stack was lexical. - Optional> lastStoreInst; + Optional lastStoreInst; // For all instructions in the block. for (auto bbi = blockPromotingWithin->begin(), @@ -683,8 +683,6 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( } if (runningVals) runningVals->isStorageValid = false; - if (lastStoreInst) - lastStoreInst->isStorageValid = false; } if (runningVals) { @@ -736,14 +734,14 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( // If we met a store before this one, delete it. if (lastStoreInst) { - assert(cast(lastStoreInst->value)->getOwnershipQualifier() != + assert(cast(*lastStoreInst)->getOwnershipQualifier() != StoreOwnershipQualifier::Assign && "store [assign] to the stack location should have been " "transformed to a store [init]"); - LLVM_DEBUG(llvm::dbgs() << "*** Removing redundant store: " - << *lastStoreInst->value); + LLVM_DEBUG(llvm::dbgs() + << "*** Removing redundant store: " << *lastStoreInst); ++NumInstRemoved; - prepareForDeletion(lastStoreInst->value, instructionsToDelete); + prepareForDeletion(*lastStoreInst, instructionsToDelete); } auto oldRunningVals = runningVals; @@ -752,7 +750,7 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( /*isStorageValid=*/true}; // The current store is now the lastStoreInst (until we see // another). - lastStoreInst = {inst, /*isStorageValid=*/true}; + lastStoreInst = inst; if (shouldAddLexicalLifetime(asi)) { if (oldRunningVals && oldRunningVals->isStorageValid && canEndLexicalLifetime(oldRunningVals->value)) { @@ -770,17 +768,17 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( // If we met a store before this one, delete it. if (lastStoreInst) { - LLVM_DEBUG(llvm::dbgs() << "*** Removing redundant store: " - << *lastStoreInst->value); + LLVM_DEBUG(llvm::dbgs() + << "*** Removing redundant store: " << *lastStoreInst); ++NumInstRemoved; - prepareForDeletion(lastStoreInst->value, instructionsToDelete); + prepareForDeletion(*lastStoreInst, instructionsToDelete); } // The stored value is the new running value. runningVals = {LiveValues::toReplace(asi, sbi->getSrc()), /*isStorageValid=*/true}; // The current store is now the lastStoreInst. - lastStoreInst = {inst, /*isStorageValid=*/true}; + lastStoreInst = inst; if (shouldAddLexicalLifetime(asi)) { runningVals = beginLexicalLifetimeAfterStore(asi, inst); } @@ -837,8 +835,6 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( runningVals->value); } runningVals->isStorageValid = false; - if (lastStoreInst) - lastStoreInst->isStorageValid = false; } else { assert(!deinitializationPoints[blockPromotingWithin]); deinitializationPoints[blockPromotingWithin] = dai; @@ -853,15 +849,15 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( } } - if (lastStoreInst && lastStoreInst->isStorageValid) { - assert((isa(lastStoreInst->value) || - (cast(lastStoreInst->value)->getOwnershipQualifier() != + if (lastStoreInst && runningVals->isStorageValid) { + assert((isa(*lastStoreInst) || + (cast(*lastStoreInst)->getOwnershipQualifier() != StoreOwnershipQualifier::Assign)) && "store [assign] to the stack location should have been " "transformed to a store [init]"); - LLVM_DEBUG(llvm::dbgs() << "*** Finished promotion. Last store: " - << *lastStoreInst->value); - return lastStoreInst->value; + LLVM_DEBUG(llvm::dbgs() + << "*** Finished promotion. Last store: " << *lastStoreInst); + return *lastStoreInst; } LLVM_DEBUG(llvm::dbgs() << "*** Finished promotion with no stores.\n"); From b23f1c23e9b95aba6c975242cf1a1f9b0e2ac4a8 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 25 Aug 2022 13:48:14 -0700 Subject: [PATCH 383/491] [CSApply] Adjust contextual locator of single expression closure before coercion Contextual conversion constraint is placed on `result of closure body` and solution application logic should match that. --- lib/Sema/CSApply.cpp | 32 +++++++++++++++++++++++++++----- lib/Sema/CSClosure.cpp | 2 +- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 32190a7da0cdf..132728a69f781 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -6792,7 +6792,12 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, case ConversionRestrictionKind::DoubleToCGFloat: { auto conversionKind = knownRestriction->second; - auto *argExpr = locator.trySimplifyToExpr(); + // If conversion wraps the whole body of a single-expression closure, + // let's use the passed-in expression since the closure itself doesn't + // get updated until coercion is done. + auto *argExpr = locator.endsWith() + ? expr + : locator.trySimplifyToExpr(); assert(argExpr); // Source requires implicit conversion to match destination @@ -9081,11 +9086,28 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) { // If we're supposed to convert the expression to some particular type, // do so now. if (shouldCoerceToContextualType()) { + ConstraintLocator *locator = nullptr; + // Bodies of single-expression closures use a special locator + // for contextual type conversion to make sure that result is + // convertible to `Void` when `return` is not used explicitly. + if (target.getExprContextualTypePurpose() == CTP_ClosureResult) { + auto *closure = cast(target.getDeclContext()); + auto *returnStmt = + castToStmt(closure->getBody()->getLastElement()); + + locator = cs.getConstraintLocator( + closure, LocatorPathElt::ClosureBody( + /*hasReturn=*/!returnStmt->isImplicit())); + } else { + locator = cs.getConstraintLocator( + resultExpr, LocatorPathElt::ContextualType( + target.getExprContextualTypePurpose())); + } + + assert(locator); + resultExpr = Rewriter.coerceToType( - resultExpr, solution.simplifyType(convertType), - cs.getConstraintLocator(resultExpr, - LocatorPathElt::ContextualType( - target.getExprContextualTypePurpose()))); + resultExpr, solution.simplifyType(convertType), locator); } else if (cs.getType(resultExpr)->hasLValueType() && !target.isDiscardedExpr()) { // We referenced an lvalue. Load it. diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp index a32cbea20a064..0b0b7e5d97ea8 100644 --- a/lib/Sema/CSClosure.cpp +++ b/lib/Sema/CSClosure.cpp @@ -1662,7 +1662,7 @@ class SyntacticElementSolutionApplication assert(isSingleExpression); resultTarget = SolutionApplicationTarget( resultExpr, context.getAsDeclContext(), - mode == convertToResult ? CTP_ReturnStmt : CTP_Unused, + mode == convertToResult ? CTP_ClosureResult : CTP_Unused, mode == convertToResult ? resultType : Type(), /*isDiscarded=*/false); } From 932c6b40c57cf0e14b91733b278711186b0938f8 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 25 Aug 2022 13:52:13 -0700 Subject: [PATCH 384/491] [ConstraintSystem] Don't use special locator for value-to-value conversions related to contextual type Previously locator for value-to-value conversion would just drop all the contextual information if the conversion occurred while converting expression to a contextual type. This is incorrect for i.e. `return` statements and other targets because because they are solved separately and using the same locator would result in a clash when solutions are merged. --- lib/Sema/CSApply.cpp | 36 +++++++++++++------ lib/Sema/ConstraintSystem.cpp | 9 ----- .../implicit_double_cgfloat_conversion.swift | 30 ++++++++++++++++ 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 132728a69f781..a65f49b1b8387 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -6792,12 +6792,25 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, case ConversionRestrictionKind::DoubleToCGFloat: { auto conversionKind = knownRestriction->second; - // If conversion wraps the whole body of a single-expression closure, - // let's use the passed-in expression since the closure itself doesn't - // get updated until coercion is done. - auto *argExpr = locator.endsWith() - ? expr - : locator.trySimplifyToExpr(); + auto shouldUseCoercedExpr = [&]() { + // If conversion wraps the whole body of a single-expression closure, + // let's use the passed-in expression since the closure itself doesn't + // get updated until coercion is done. + if (locator.endsWith()) + return true; + + // Contextual type locator always uses the original version of + // expression (before any coercions have been applied) because + // otherwise it wouldn't be possible to find the overload choice. + if (locator.endsWith()) + return true; + + // In all other cases use the expression associated with locator. + return false; + }; + + auto *argExpr = + shouldUseCoercedExpr() ? expr : locator.trySimplifyToExpr(); assert(argExpr); // Source requires implicit conversion to match destination @@ -8575,7 +8588,7 @@ static Optional applySolutionToInitialization( // Convert the initializer to the type of the pattern. auto &cs = solution.getConstraintSystem(); auto locator = cs.getConstraintLocator( - initializer, LocatorPathElt::ContextualType(CTP_Initialization)); + target.getAsExpr(), LocatorPathElt::ContextualType(CTP_Initialization)); initializer = solution.coerceToType(initializer, initType, locator); if (!initializer) return None; @@ -9087,10 +9100,12 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) { // do so now. if (shouldCoerceToContextualType()) { ConstraintLocator *locator = nullptr; + + auto contextualTypePurpose = target.getExprContextualTypePurpose(); // Bodies of single-expression closures use a special locator // for contextual type conversion to make sure that result is // convertible to `Void` when `return` is not used explicitly. - if (target.getExprContextualTypePurpose() == CTP_ClosureResult) { + if (contextualTypePurpose == CTP_ClosureResult) { auto *closure = cast(target.getDeclContext()); auto *returnStmt = castToStmt(closure->getBody()->getLastElement()); @@ -9100,8 +9115,7 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) { /*hasReturn=*/!returnStmt->isImplicit())); } else { locator = cs.getConstraintLocator( - resultExpr, LocatorPathElt::ContextualType( - target.getExprContextualTypePurpose())); + expr, LocatorPathElt::ContextualType(contextualTypePurpose)); } assert(locator); @@ -9113,7 +9127,7 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) { // We referenced an lvalue. Load it. resultExpr = Rewriter.coerceToType( resultExpr, cs.getType(resultExpr)->getRValueType(), - cs.getConstraintLocator(resultExpr, + cs.getConstraintLocator(expr, LocatorPathElt::ContextualType( target.getExprContextualTypePurpose()))); } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 47a625c1af7a0..93553a4fd98bc 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -444,15 +444,6 @@ ConstraintLocator *ConstraintSystem::getImplicitValueConversionLocator( break; } - // If the conversion is associated with a contextual type e.g. - // `_: Double = CGFloat(1)` then drop `ContextualType` so that - // it's easy to find when the underlying expression has been - // rewritten. - if (!path.empty() && path.back().is()) { - anchor = ASTNode(); - path.clear(); - } - // If conversion is for a tuple element, let's drop `TupleType` // components from the path since they carry information for // diagnostics that `ExprRewriter` won't be able to re-construct diff --git a/test/Constraints/implicit_double_cgfloat_conversion.swift b/test/Constraints/implicit_double_cgfloat_conversion.swift index 8f1ce5766446d..9388e1efdb56f 100644 --- a/test/Constraints/implicit_double_cgfloat_conversion.swift +++ b/test/Constraints/implicit_double_cgfloat_conversion.swift @@ -285,3 +285,33 @@ func test_conversion_inside_tuple_elements() -> (a: CGFloat, b: (c: Int, d: CGFl let x: Double = 0.0 return (a: x, b: (c: 42, d: x)) // Ok } + +do { + struct Data { + var prop: CGFloat + } + + func single(get: () -> Double) {} + func multiple(get1: () -> Double, + get2: () -> CGFloat = { Double(1) }, + get3: () -> Double) {} + + func test(data: Data) { + single { data.prop } // Ok + single { return data.prop } // Ok + + single { + _ = 42 + if true { + return data.prop // Ok + } + return data.prop // Ok + } + + multiple { + data.prop // Ok + } get3: { + return data.prop // Ok + } + } +} From 288e4cb566c0155b1e58ae7448937719eb4884f2 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 25 Aug 2022 13:13:24 -0700 Subject: [PATCH 385/491] [interop][SwiftToCxx] do not emit functions/methods that use unexposed types --- lib/PrintAsClang/DeclAndTypePrinter.cpp | 23 +++++++------ lib/PrintAsClang/PrintClangFunction.cpp | 34 +++++++++++++------ lib/PrintAsClang/PrintClangFunction.h | 7 ++-- .../expose-swift-decls-to-cxx.swift | 23 +++++++++++++ 4 files changed, 65 insertions(+), 22 deletions(-) diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 8b05f4d2a86f8..81e5dd9a8d282 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -426,7 +426,7 @@ class DeclAndTypePrinter::Implementation // Printing struct, is, and get functions for each case DeclAndTypeClangFunctionPrinter clangFuncPrinter( os, owningPrinter.prologueOS, owningPrinter.typeMapping, - owningPrinter.interopContext); + owningPrinter.interopContext, owningPrinter); auto printIsFunction = [&](StringRef caseName, EnumDecl *ED) { os << " inline bool is"; @@ -745,9 +745,9 @@ class DeclAndTypePrinter::Implementation return; owningPrinter.prologueOS << cFuncPrologueOS.str(); - DeclAndTypeClangFunctionPrinter declPrinter(os, owningPrinter.prologueOS, - owningPrinter.typeMapping, - owningPrinter.interopContext); + DeclAndTypeClangFunctionPrinter declPrinter( + os, owningPrinter.prologueOS, owningPrinter.typeMapping, + owningPrinter.interopContext, owningPrinter); if (auto *accessor = dyn_cast(AFD)) { declPrinter.printCxxPropertyAccessorMethod( typeDeclContext, accessor, funcABI->getSymbolName(), resultTy, @@ -760,7 +760,8 @@ class DeclAndTypePrinter::Implementation DeclAndTypeClangFunctionPrinter defPrinter( owningPrinter.outOfLineDefinitionsOS, owningPrinter.prologueOS, - owningPrinter.typeMapping, owningPrinter.interopContext); + owningPrinter.typeMapping, owningPrinter.interopContext, + owningPrinter); if (auto *accessor = dyn_cast(AFD)) { @@ -1131,7 +1132,7 @@ class DeclAndTypePrinter::Implementation DeclAndTypeClangFunctionPrinter funcPrinter( cRepresentationOS, owningPrinter.prologueOS, owningPrinter.typeMapping, - owningPrinter.interopContext); + owningPrinter.interopContext, owningPrinter); auto ABIparams = owningPrinter.interopContext.getIrABIDetails() .getFunctionABIAdditionalParams(FD); llvm::SmallVector @@ -1191,9 +1192,9 @@ class DeclAndTypePrinter::Implementation auto resultTy = getForeignResultType(FD, funcTy, asyncConvention, errorConvention); - DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.prologueOS, - owningPrinter.typeMapping, - owningPrinter.interopContext); + DeclAndTypeClangFunctionPrinter funcPrinter( + os, owningPrinter.prologueOS, owningPrinter.typeMapping, + owningPrinter.interopContext, owningPrinter); llvm::SmallVector additionalParams; auto ABIparams = owningPrinter.interopContext.getIrABIDetails() @@ -1202,10 +1203,12 @@ class DeclAndTypePrinter::Implementation convertABIAdditionalParams(FD, resultTy, ABIparams, additionalParams); DeclAndTypeClangFunctionPrinter::FunctionSignatureModifiers modifiers; modifiers.isInline = true; - funcPrinter.printFunctionSignature( + auto result = funcPrinter.printFunctionSignature( FD, cxx_translation::getNameForCxx(FD), resultTy, DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CxxInlineThunk, {}, modifiers); + assert( + !result.isUnsupported()); // The C signature should be unsupported too. // FIXME: Support throwing exceptions for Swift errors. if (!funcTy->isThrowing()) os << " noexcept"; diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index cb587d0d77632..d6c17b6a79473 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -96,13 +96,14 @@ class CFunctionSignatureTypePrinter PrimitiveTypeMapping &typeMapping, OutputLanguageMode languageMode, SwiftToClangInteropContext &interopContext, CFunctionSignatureTypePrinterModifierDelegate modifiersDelegate, - const ModuleDecl *moduleContext, + const ModuleDecl *moduleContext, DeclAndTypePrinter &declPrinter, FunctionSignatureTypeUse typeUseKind = FunctionSignatureTypeUse::ParamType) : ClangSyntaxPrinter(os), cPrologueOS(cPrologueOS), typeMapping(typeMapping), interopContext(interopContext), languageMode(languageMode), modifiersDelegate(modifiersDelegate), - moduleContext(moduleContext), typeUseKind(typeUseKind) {} + moduleContext(moduleContext), declPrinter(declPrinter), + typeUseKind(typeUseKind) {} void printInoutTypeModifier() { os << (languageMode == swift::OutputLanguageMode::Cxx ? " &" @@ -197,6 +198,9 @@ class CFunctionSignatureTypePrinter // Handle known type names. if (printIfKnownSimpleType(decl, optionalKind, isInOutParam)) return ClangRepresentation::representable; + if (!declPrinter.shouldInclude(decl)) + return ClangRepresentation::unsupported; // FIXME: propagate why it's not + // exposed. // FIXME: Handle optional structures. if (typeUseKind == FunctionSignatureTypeUse::ParamType) { if (languageMode != OutputLanguageMode::Cxx && @@ -292,6 +296,7 @@ class CFunctionSignatureTypePrinter OutputLanguageMode languageMode; CFunctionSignatureTypePrinterModifierDelegate modifiersDelegate; const ModuleDecl *moduleContext; + DeclAndTypePrinter &declPrinter; FunctionSignatureTypeUse typeUseKind; }; @@ -304,7 +309,7 @@ DeclAndTypeClangFunctionPrinter::printClangFunctionReturnType( CFunctionSignatureTypePrinter typePrinter( os, cPrologueOS, typeMapping, outputLang, interopContext, CFunctionSignatureTypePrinterModifierDelegate(), moduleContext, - FunctionSignatureTypeUse::ReturnType); + declPrinter, FunctionSignatureTypeUse::ReturnType); // Param for indirect return cannot be marked as inout return typePrinter.visit(ty, optKind, /*isInOutParam=*/false); } @@ -344,9 +349,9 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature( -> ClangRepresentation { // FIXME: add support for noescape and PrintMultiPartType, // see DeclAndTypePrinter::print. - CFunctionSignatureTypePrinter typePrinter(os, cPrologueOS, typeMapping, - outputLang, interopContext, - delegate, emittedModule); + CFunctionSignatureTypePrinter typePrinter( + os, cPrologueOS, typeMapping, outputLang, interopContext, delegate, + emittedModule, declPrinter); auto result = typePrinter.visit(ty, optionalKind, isInOutParam); if (!name.empty()) { @@ -385,6 +390,12 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature( .isUnsupported()) return resultingRepresentation; } else { + // FIXME: also try to figure out if indirect is representable using a type + // visitor? + if (const auto *NT = resultTy->getNominalOrBoundGenericNominal()) { + if (!declPrinter.shouldInclude(NT)) + return ClangRepresentation::unsupported; + } os << "void"; } @@ -701,9 +712,11 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod( isa(FD) ? cast(FD)->isMutating() : false; modifiers.isConst = !isa(typeDeclContext) && !isMutating && !isConstructor; - printFunctionSignature( + auto result = printFunctionSignature( FD, isConstructor ? "init" : cxx_translation::getNameForCxx(FD), resultTy, FunctionSignatureKind::CxxInlineThunk, {}, modifiers); + assert(!result.isUnsupported() && "C signature should be unsupported too"); + if (!isDefinition) { os << ";\n"; return; @@ -763,9 +776,10 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod( modifiers.qualifierContext = typeDeclContext; modifiers.isInline = true; modifiers.isConst = accessor->isGetter() && !isa(typeDeclContext); - printFunctionSignature(accessor, remapPropertyName(accessor, resultTy), - resultTy, FunctionSignatureKind::CxxInlineThunk, {}, - modifiers); + auto result = printFunctionSignature( + accessor, remapPropertyName(accessor, resultTy), resultTy, + FunctionSignatureKind::CxxInlineThunk, {}, modifiers); + assert(!result.isUnsupported() && "C signature should be unsupported too!"); if (!isDefinition) { os << ";\n"; return; diff --git a/lib/PrintAsClang/PrintClangFunction.h b/lib/PrintAsClang/PrintClangFunction.h index 3ed58e3c854ee..d575f6481a7dc 100644 --- a/lib/PrintAsClang/PrintClangFunction.h +++ b/lib/PrintAsClang/PrintClangFunction.h @@ -35,6 +35,7 @@ class ParamDecl; class ParameterList; class PrimitiveTypeMapping; class SwiftToClangInteropContext; +class DeclAndTypePrinter; struct ClangRepresentation { enum Kind { representable, unsupported }; @@ -61,9 +62,10 @@ class DeclAndTypeClangFunctionPrinter { public: DeclAndTypeClangFunctionPrinter(raw_ostream &os, raw_ostream &cPrologueOS, PrimitiveTypeMapping &typeMapping, - SwiftToClangInteropContext &interopContext) + SwiftToClangInteropContext &interopContext, + DeclAndTypePrinter &declPrinter) : os(os), cPrologueOS(cPrologueOS), typeMapping(typeMapping), - interopContext(interopContext) {} + interopContext(interopContext), declPrinter(declPrinter) {} /// What kind of function signature should be emitted for the given Swift /// function. @@ -150,6 +152,7 @@ class DeclAndTypeClangFunctionPrinter { raw_ostream &cPrologueOS; PrimitiveTypeMapping &typeMapping; SwiftToClangInteropContext &interopContext; + DeclAndTypePrinter &declPrinter; }; } // end namespace swift diff --git a/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift b/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift index 0e1b2263d5d8f..4cb581b227b71 100644 --- a/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift +++ b/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift @@ -36,6 +36,10 @@ public struct ExposedStruct { public func method() {} } +public struct NotExposedStruct { + public var x: Int +} + @_expose(Cxx, "ExposedStruct2") public struct ExposedStructRenamed { public var y: Int @@ -48,6 +52,15 @@ public struct ExposedStructRenamed { @_expose(Cxx, "renamedMethod") public func method() {} + + public func getNonExposedStruct() -> NotExposedStruct { + return NotExposedStruct(x: 2) + } + // FIXME: if 'getNonExposedStruct' has explicit @_expose we should error in Sema. + + public func passNonExposedStruct(_ x: NotExposedStruct) { + } + // FIXME: if 'passNonExposedStruct' has explicit @_expose we should error in Sema. } @_expose(Cxx) @@ -58,6 +71,14 @@ public final class ExposedClass { // CHECK: class ExposedClass final // CHECK: class ExposedStruct final { // CHECK: class ExposedStruct2 final { +// CHECK: ExposedStruct2(ExposedStruct2 &&) = default; +// CHECK-NEXT: swift::Int getY() const; +// CHECK-NEXT: void setY(swift::Int value); +// CHECK-NEXT: swift::Int getRenamedProp() const; +// CHECK-NEXT: void setRenamedProp(swift::Int value); +// CHECK-NEXT: swift::Int getProp3() const; +// CHECK-NEXT: void renamedMethod() const; +// CHECK-NEXT: private: // CHECK: inline void exposed1() noexcept { // CHECK-NEXT: return _impl::$s6Expose8exposed1yyF(); @@ -84,3 +105,5 @@ public final class ExposedClass { // CHECK: swift::Int ExposedStruct2::getProp3() const { // CHECK: void ExposedStruct2::renamedMethod() const { +// CHECK-NOT: NonExposedStruct + From bd8c874e174042a998c9b2702ac39ed1ea243fab Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 25 Aug 2022 13:32:36 -0700 Subject: [PATCH 386/491] [interop][SwiftToCxx] experimentally expose Swift::String type to C++ The only member that's currently exposed is the default initializer, everything else is in extensions --- lib/PrintAsClang/DeclAndTypePrinter.cpp | 5 +++++ .../SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 81e5dd9a8d282..4f75066753b8a 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -2397,6 +2397,11 @@ static bool isAsyncAlternativeOfOtherDecl(const ValueDecl *VD) { } static bool hasExposeAttr(const ValueDecl *VD) { + if (isa(VD) && VD->getModuleContext()->isStdlibModule()) { + if (VD == VD->getASTContext().getStringDecl()) + return true; + return false; + } if (VD->getAttrs().hasAttribute()) return true; if (const auto *NMT = dyn_cast(VD->getDeclContext())) diff --git a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift index d9a1c6ca3a9fc..482fe3cc5f185 100644 --- a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift +++ b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift @@ -5,4 +5,15 @@ // RUN: %check-interop-cxx-header-in-clang(%t/Swift.h -Wno-unused-private-field -Wno-unused-function) // CHECK: namespace Swift { + +// CHECK: class String final { +// CHECK-NEXT: public: +// CHECK-NEXT: inline ~String() { +// CHECK: } +// CHECK-NEXT: inline String(const String &other) { +// CHECK: } +// CHECK-NEXT: inline String(String &&) = default; +// CHECK-NEXT: static inline String init(); +// CHECK-NEXT: private: + // CHECK: } // namespace Swift From 06d9fd24d45665266c5699006137060ed24fcf1e Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 25 Aug 2022 15:06:43 -0700 Subject: [PATCH 387/491] [interop][SwiftToCxx] add experimental Swift::String -> NSString conversion operator --- lib/PrintAsClang/ClangSyntaxPrinter.cpp | 13 ++++ lib/PrintAsClang/ClangSyntaxPrinter.h | 6 ++ lib/PrintAsClang/PrintClangValueType.cpp | 26 +++++++ test/Interop/SwiftToCxx/lit.local.cfg | 2 +- .../stdlib/string/string-to-nsstring.mm | 68 +++++++++++++++++++ .../stdlib/swift-stdlib-in-cxx.swift | 6 ++ 6 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 test/Interop/SwiftToCxx/stdlib/string/string-to-nsstring.mm diff --git a/lib/PrintAsClang/ClangSyntaxPrinter.cpp b/lib/PrintAsClang/ClangSyntaxPrinter.cpp index 37b0f01f375ac..48192ddea8bba 100644 --- a/lib/PrintAsClang/ClangSyntaxPrinter.cpp +++ b/lib/PrintAsClang/ClangSyntaxPrinter.cpp @@ -98,10 +98,23 @@ void ClangSyntaxPrinter::printExternC( os << "#endif\n"; } +void ClangSyntaxPrinter::printObjCBlock( + llvm::function_ref bodyPrinter) const { + os << "#if defined(__OBJC__)\n"; + bodyPrinter(os); + os << "\n#endif\n"; +} + void ClangSyntaxPrinter::printSwiftImplQualifier() const { os << "swift::" << cxx_synthesis::getCxxImplNamespaceName() << "::"; } +void ClangSyntaxPrinter::printInlineForThunk() const { + // FIXME: make a macro and add 'nodebug', and + // migrate all other 'inline' uses. + os << "inline __attribute__((always_inline)) "; +} + void ClangSyntaxPrinter::printNullability( Optional kind, NullabilityPrintKind printKind) const { if (!kind) diff --git a/lib/PrintAsClang/ClangSyntaxPrinter.h b/lib/PrintAsClang/ClangSyntaxPrinter.h index 7561660ddfaf4..6fc38c599027b 100644 --- a/lib/PrintAsClang/ClangSyntaxPrinter.h +++ b/lib/PrintAsClang/ClangSyntaxPrinter.h @@ -70,6 +70,10 @@ class ClangSyntaxPrinter { void printExternC(llvm::function_ref bodyPrinter) const; + /// Print an #ifdef __OBJC__ block. + void + printObjCBlock(llvm::function_ref bodyPrinter) const; + /// Print the `swift::_impl::` namespace qualifier. void printSwiftImplQualifier() const; @@ -80,6 +84,8 @@ class ClangSyntaxPrinter { ContextSensitive, }; + void printInlineForThunk() const; + void printNullability( Optional kind, NullabilityPrintKind printKind = NullabilityPrintKind::After) const; diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index 527a44b49f262..3987bac71f88c 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -87,6 +87,30 @@ void ClangValueTypePrinter::forwardDeclType(raw_ostream &os, os << ";\n"; } +static void addCppExtensionsToStdlibType(const NominalTypeDecl *typeDecl, + ClangSyntaxPrinter &printer, + raw_ostream &cPrologueOS) { + if (typeDecl == typeDecl->getASTContext().getStringDecl()) { + // Perform String -> NSString conversion using + // _bridgeToObjectiveCImpl. + // FIXME: This is an extension, we should + // just expose the method to C once extensions are + // supported. + cPrologueOS << "SWIFT_EXTERN void *_Nonnull " + "$sSS23_bridgeToObjectiveCImplyXlyF(swift_interop_stub_" + "Swift_String) SWIFT_NOEXCEPT SWIFT_CALL;\n"; + printer.printObjCBlock([](raw_ostream &os) { + os << " "; + ClangSyntaxPrinter(os).printInlineForThunk(); + os << "operator NSString * _Nonnull () const noexcept {\n"; + os << " return (__bridge_transfer NSString " + "*)(_impl::$sSS23_bridgeToObjectiveCImplyXlyF(_impl::swift_interop_" + "passDirect_Swift_String(_getOpaquePointer())));\n"; + os << " }\n"; + }); + } +} + void ClangValueTypePrinter::printValueTypeDecl( const NominalTypeDecl *typeDecl, llvm::function_ref bodyPrinter) { @@ -193,6 +217,8 @@ void ClangValueTypePrinter::printValueTypeDecl( os << " &&) = default;\n"; bodyPrinter(); + if (typeDecl->isStdlibDecl()) + addCppExtensionsToStdlibType(typeDecl, printer, cPrologueOS); os << "private:\n"; diff --git a/test/Interop/SwiftToCxx/lit.local.cfg b/test/Interop/SwiftToCxx/lit.local.cfg index 27c9e57438c46..c55f1dcb05f0f 100644 --- a/test/Interop/SwiftToCxx/lit.local.cfg +++ b/test/Interop/SwiftToCxx/lit.local.cfg @@ -1 +1 @@ -config.suffixes = ['.swift', '.cpp'] +config.suffixes = ['.swift', '.cpp', '.mm'] diff --git a/test/Interop/SwiftToCxx/stdlib/string/string-to-nsstring.mm b/test/Interop/SwiftToCxx/stdlib/string/string-to-nsstring.mm new file mode 100644 index 0000000000000..e7c99da22fc73 --- /dev/null +++ b/test/Interop/SwiftToCxx/stdlib/string/string-to-nsstring.mm @@ -0,0 +1,68 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -parse-as-library %platform-module-dir/Swift.swiftmodule/%module-target-triple.swiftinterface -enable-library-evolution -disable-objc-attr-requires-foundation-module -typecheck -module-name Swift -parse-stdlib -enable-experimental-cxx-interop -emit-clang-header-path %t/Swift.h -experimental-skip-all-function-bodies + +// RUN: %target-swift-frontend -typecheck %t/create_string.swift -typecheck -module-name StringCreator -enable-experimental-cxx-interop -emit-clang-header-path %t/StringCreator.h + +// RUN: %target-interop-build-clangxx -fobjc-arc -c %t/string-to-nsstring.mm -I %t -o %t/swift-stdlib-execution.o +// RUN: %target-build-swift %t/use_foundation.swift %t/create_string.swift -o %t/swift-stdlib-execution -Xlinker %t/swift-stdlib-execution.o -module-name StringCreator -Xfrontend -entry-point-function-name -Xfrontend swiftMain -lc++ +// RUN: %target-codesign %t/swift-stdlib-execution +// RUN: %target-run %t/swift-stdlib-execution + +// RUN: %target-interop-build-clangxx -fobjc-arc -c %t/string-to-nsstring-one-arc-op.mm -I %t -Xclang -emit-llvm -S -o - -O1 | %FileCheck --check-prefix=CHECKARC %s + +// REQUIRES: executable_test +// REQUIRES: objc_interop + +//--- use_foundation.swift +import Foundation + +//--- create_string.swift +@_expose(Cxx) +public func createString(_ ptr: UnsafePointer) -> String { + return String(cString: ptr) +} + +//--- string-to-nsstring-one-arc-op.mm + +#include "Swift.h" + +int main() { + using namespace Swift; + auto emptyString = String::init(); + NSString *nsStr = emptyString; +} + +// CHECKARC: %[[VAL:.*]] = call swiftcc i8* @"$sSS23_bridgeToObjectiveCImplyXlyF" +// CHECKARC: call i8* @llvm.objc.autorelease(i8* %[[VAL]]) +// CHECKARC: @llvm.objc. +// CHECKARC-SAME: autorelease(i8*) +// CHECKARC-NOT: @llvm.objc. + +//--- string-to-nsstring.mm + +#include +#include +#include "Swift.h" +#include "StringCreator.h" + +int main() { + using namespace Swift; + + auto emptyString = String::init(); + + { + NSString *nsStr = emptyString; + assert(std::string(nsStr.UTF8String) == ""); + assert([nsStr isEqualToString:@""]); + } + + auto aStr = StringCreator::createString("hello"); + { + NSString *nsStr = aStr; + assert(std::string(nsStr.UTF8String) == "hello"); + assert([nsStr isEqualToString:@"hello"]); + } + return 0; +} diff --git a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift index 482fe3cc5f185..e054bc06034a8 100644 --- a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift +++ b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift @@ -14,6 +14,12 @@ // CHECK: } // CHECK-NEXT: inline String(String &&) = default; // CHECK-NEXT: static inline String init(); +// CHECK-NEXT: #if defined(__OBJC__) +// CHECK-NEXT: inline __attribute__((always_inline)) operator NSString * _Nonnull () const noexcept { +// CHECK-NEXT: return (__bridge_transfer NSString *)(_impl::$sSS23_bridgeToObjectiveCImplyXlyF(_impl::swift_interop_passDirect_Swift_String(_getOpaquePointer()))); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: #endif // CHECK-NEXT: private: // CHECK: } // namespace Swift From 72190ed7fa86c425319a5120deeee7cc43e56b48 Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Tue, 23 Aug 2022 15:18:03 -0700 Subject: [PATCH 388/491] [CSStep] Print disjunctions with bindOverload choices. Print all disjunctions in scope, not just the one selected. Remove conjunction printing. --- lib/Sema/CSStep.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/Sema/CSStep.cpp b/lib/Sema/CSStep.cpp index 00bc4a0b1ecf4..0d644c6ec5108 100644 --- a/lib/Sema/CSStep.cpp +++ b/lib/Sema/CSStep.cpp @@ -356,7 +356,6 @@ StepResult ComponentStep::take(bool prevFailed) { }); auto *disjunction = CS.selectDisjunction(); - auto *conjunction = CS.selectConjunction(); if (CS.isDebugMode()) { PrintOptions PO; @@ -369,19 +368,29 @@ StepResult ComponentStep::take(bool prevFailed) { } log.indent(CS.solverState->getCurrentIndent()); - if (disjunction) { - log.indent(2); - log << "Disjunction(s) = ["; + SmallVector disjunctions; + CS.collectDisjunctions(disjunctions); + std::vector overloadDisjunctions; + for (const auto &disjunction : disjunctions) { + PrintOptions PO; + PO.PrintTypesForDebugging = true; + auto constraints = disjunction->getNestedConstraints(); - log << constraints[0]->getFirstType()->getString(PO); - log << "]"; + if (constraints[0]->getKind() == ConstraintKind::BindOverload) + overloadDisjunctions.push_back( + constraints[0]->getFirstType()->getString(PO)); } - if (conjunction) { + if (!overloadDisjunctions.empty()) { + auto &log = getDebugLogger(); log.indent(2); - log << "Conjunction(s) = ["; - auto constraints = conjunction->getNestedConstraints(); - log << constraints[0]->getFirstType()->getString(PO); - log << "]"; + log << "Disjunction(s) = ["; + interleave(overloadDisjunctions, log, ", "); + log << "]\n"; + + if (!potentialBindings.empty() || !overloadDisjunctions.empty()) { + auto &log = getDebugLogger(); + log << ")\n"; + } } log << ")\n"; } From f683c2ca168aa80518ba546d17cf5e29dd260831 Mon Sep 17 00:00:00 2001 From: Amritpan Kaur Date: Wed, 24 Aug 2022 17:47:04 -0700 Subject: [PATCH 389/491] [CSStep] Remove extraneous ) printing after PotentialBindings/Disjunctions. Moved `debugLogger` into each if-block so it's indentation doesn't affect next `isDebugMode`. --- lib/Sema/CSStep.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/Sema/CSStep.cpp b/lib/Sema/CSStep.cpp index 0d644c6ec5108..f817e21250e0d 100644 --- a/lib/Sema/CSStep.cpp +++ b/lib/Sema/CSStep.cpp @@ -358,15 +358,11 @@ StepResult ComponentStep::take(bool prevFailed) { auto *disjunction = CS.selectDisjunction(); if (CS.isDebugMode()) { - PrintOptions PO; - PO.PrintTypesForDebugging = true; - - auto &log = getDebugLogger(); if (!potentialBindings.empty()) { + auto &log = getDebugLogger(); log << "(Potential Binding(s): " << '\n'; log << potentialBindings; } - log.indent(CS.solverState->getCurrentIndent()); SmallVector disjunctions; CS.collectDisjunctions(disjunctions); @@ -392,7 +388,6 @@ StepResult ComponentStep::take(bool prevFailed) { log << ")\n"; } } - log << ")\n"; } if (CS.shouldAttemptFixes()) { From 64b90e8245ca59c3f3eb120b97bd3716d1e2f497 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 25 Aug 2022 15:25:41 -0700 Subject: [PATCH 390/491] [interop][SwiftToCxx] docs: add section on converting Swift's String to NSString * --- .../UserGuide-CallingSwiftFromC++.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md b/docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md index 3d7e76bc790f4..6d869f57285ff 100644 --- a/docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md +++ b/docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md @@ -1323,6 +1323,16 @@ void setSwiftString(swift::String &other, const std::string &str) { } ``` +In Objective-C++ mode, you can also convert a `swift::String` to an `NSString *` value using +a cast or by assigning to an `NSString *` value directly: + +```c++ +void useObjCString(const swift::String &swStr) { + // This cast will bridge the Swift String to an Objective-C NSString value. + NSString *nsStr = swStr; +} +``` + Open questions: * How do the `StringLiteralConvertible` rules work in practice? From 284f8d4fdd42ffbdc5c9ef1c47d15761a5c671b9 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 25 Aug 2022 16:08:33 -0700 Subject: [PATCH 391/491] Fix Substring.removeSubrange for entire substring (#60744) fix start and end fix test --- .../core/StringGutsRangeReplaceable.swift | 21 +++++++++++----- test/stdlib/StringIndex.swift | 25 +++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/stdlib/public/core/StringGutsRangeReplaceable.swift b/stdlib/public/core/StringGutsRangeReplaceable.swift index 55dbb654a1ea5..f92b48797a952 100644 --- a/stdlib/public/core/StringGutsRangeReplaceable.swift +++ b/stdlib/public/core/StringGutsRangeReplaceable.swift @@ -483,9 +483,13 @@ extension _StringGuts { let newUTF8Count = oldUTF8Count + newUTF8Subrange.count - oldUTF8SubrangeCount - // Get the character stride in the entire string, not just the substring. - // (Characters in a substring may end beyond the bounds of it.) - let newStride = _opaqueCharacterStride(startingAt: utf8StartOffset) + var newStride = 0 + + if !newUTF8Subrange.isEmpty { + // Get the character stride in the entire string, not just the substring. + // (Characters in a substring may end beyond the bounds of it.) + newStride = _opaqueCharacterStride(startingAt: utf8StartOffset) + } startIndex = String.Index( encodedOffset: utf8StartOffset, @@ -522,9 +526,14 @@ extension _StringGuts { // needs to look ahead by more than one Unicode scalar.) let oldStride = startIndex.characterStride ?? 0 if oldRange.lowerBound <= oldBounds.lowerBound &+ oldStride { - // Get the character stride in the entire string, not just the substring. - // (Characters in a substring may end beyond the bounds of it.) - let newStride = _opaqueCharacterStride(startingAt: newBounds.lowerBound) + var newStride = 0 + + if !newBounds.isEmpty { + // Get the character stride in the entire string, not just the substring. + // (Characters in a substring may end beyond the bounds of it.) + newStride = _opaqueCharacterStride(startingAt: newBounds.lowerBound) + } + var newStart = String.Index( encodedOffset: newBounds.lowerBound, characterStride: newStride diff --git a/test/stdlib/StringIndex.swift b/test/stdlib/StringIndex.swift index 0639fdb73073d..4e2fcec9c750d 100644 --- a/test/stdlib/StringIndex.swift +++ b/test/stdlib/StringIndex.swift @@ -1059,3 +1059,28 @@ suite.test("String.replaceSubrange index validation") } } } + +suite.test("Substring.removeSubrange entire range") { + guard #available(SwiftStdlib 5.7, *) else { + // This is a regression found in 5.7+ + return + } + + var a: Substring = "abcdef" + let aStart = a.startIndex + let aEnd = a.endIndex + + a.removeSubrange(aStart ..< aEnd) + + expectTrue(a.isEmpty) + +#if _runtime(_ObjC) + var b: Substring = ("å∫ç∂éƒ" as NSString) as Substring + let bStart = b.startIndex + let bEnd = b.endIndex + + b.removeSubrange(bStart ..< bEnd) + + expectTrue(b.isEmpty) +#endif +} From c20bd860071e6490eb1607d4252c016edd25cea7 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Wed, 24 Aug 2022 08:25:34 -0700 Subject: [PATCH 392/491] [Freestanding] Disable checked continuations. In the task-to-thread model, there are no threading mechanisms by which work could be offloaded onto another thread. As such, callback based asynchronous APIs which are not Swift async do not make sense. rdar://99047747 --- .../Concurrency/CheckedContinuation.swift | 64 +++++++++++++++++++ test/stdlib/freestanding_diags_stdlib.swift | 7 ++ 2 files changed, 71 insertions(+) diff --git a/stdlib/public/Concurrency/CheckedContinuation.swift b/stdlib/public/Concurrency/CheckedContinuation.swift index 03b1426bdd8ea..d29dcbc3b1906 100644 --- a/stdlib/public/Concurrency/CheckedContinuation.swift +++ b/stdlib/public/Concurrency/CheckedContinuation.swift @@ -16,6 +16,7 @@ import Swift @_silgen_name("swift_continuation_logFailedCheck") internal func logFailedCheck(_ message: UnsafeRawPointer) +#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY /// Implementation class that holds the `UnsafeContinuation` instance for /// a `CheckedContinuation`. @available(SwiftStdlib 5.1, *) @@ -82,7 +83,9 @@ internal final class CheckedContinuationCanary: @unchecked Sendable { } } } +#endif +#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY /// A mechanism to interface /// between synchronous and asynchronous code, /// logging correctness violations. @@ -296,4 +299,65 @@ public func withCheckedThrowingContinuation( body(CheckedContinuation(continuation: $0, function: function)) } } +#else +@available(SwiftStdlib 5.1, *) +@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") +public struct CheckedContinuation: Sendable { + @available(SwiftStdlib 5.1, *) + @available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") + public init(continuation: UnsafeContinuation, function: String = #function) { + fatalError("Unavailable in task-to-thread concurrency model") + } + + @available(SwiftStdlib 5.1, *) + @available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") + public func resume(returning value: __owned T) { + fatalError("Unavailable in task-to-thread concurrency model") + } + + @available(SwiftStdlib 5.1, *) + @available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") + public func resume(throwing error: __owned E) { + fatalError("Unavailable in task-to-thread concurrency model") + } +} +@available(SwiftStdlib 5.1, *) +@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") +extension CheckedContinuation { + @available(SwiftStdlib 5.1, *) + @available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") + public func resume(with result: Result) where E == Error { + fatalError("Unavailable in task-to-thread concurrency model") + } + + @available(SwiftStdlib 5.1, *) + @available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") + public func resume(with result: Result) { + fatalError("Unavailable in task-to-thread concurrency model") + } + @available(SwiftStdlib 5.1, *) + @available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") + public func resume() where T == Void { + fatalError("Unavailable in task-to-thread concurrency model") + } +} + +@available(SwiftStdlib 5.1, *) +@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") +public func withCheckedContinuation( + function: String = #function, + _ body: (CheckedContinuation) -> Void +) async -> T { + fatalError("Unavailable in task-to-thread concurrency model") +} + +@available(SwiftStdlib 5.1, *) +@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model") +public func withCheckedThrowingContinuation( + function: String = #function, + _ body: (CheckedContinuation) -> Void +) async throws -> T { + fatalError("Unavailable in task-to-thread concurrency model") +} +#endif diff --git a/test/stdlib/freestanding_diags_stdlib.swift b/test/stdlib/freestanding_diags_stdlib.swift index 040b888e5e53a..64a29fe900859 100644 --- a/test/stdlib/freestanding_diags_stdlib.swift +++ b/test/stdlib/freestanding_diags_stdlib.swift @@ -24,6 +24,13 @@ func foo() async { asyncDetached { () async -> () in } // expected-error{{Unavailable in task-to-thread concurrency model}} asyncDetached { () async throws -> () in } // expected-error{{Unavailable in task-to-thread concurrency model}} _ = MainActor.self // expected-error{{Unavailable in task-to-thread concurrency model}} + let _: Int = await withCheckedContinuation { _ in } // expected-error{{Unavailable in task-to-thread concurrency model}} + do { + let _: Int = try await withCheckedThrowingContinuation { _ in } // expected-error{{Unavailable in task-to-thread concurrency model}} + } catch let error { + _ = error + } + _ = CheckedContinuation.self // expected-error{{Unavailable in task-to-thread concurrency model}} } func foo2( From cdded2ba9fb39d0313141c641581ba480578bdd4 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Sun, 21 Aug 2022 21:05:10 +0300 Subject: [PATCH 393/491] Gardening: Migrate test suite to GH issues: decl --- test/decl/circularity.swift | 10 +-- test/decl/overload.swift | 110 ++++++++++++++++---------------- test/decl/overload_swift4.swift | 12 ++-- test/decl/overload_swift5.swift | 31 +++++---- 4 files changed, 83 insertions(+), 80 deletions(-) diff --git a/test/decl/circularity.swift b/test/decl/circularity.swift index 4cd53f05c7d4a..82b951c37664f 100644 --- a/test/decl/circularity.swift +++ b/test/decl/circularity.swift @@ -110,10 +110,10 @@ class D4 : C4, P1 { // expected-note 3 {{through reference here}} } } -// SR-12236 +// https://github.com/apple/swift/issues/54662 // N.B. This used to compile in 5.1. -protocol SR12236 { } -class SR12236_A { // expected-note {{through reference here}} - typealias Nest = SR12236 // expected-error {{circular reference}} expected-note {{through reference here}} +protocol P_54662 { } +class C_54662 { // expected-note {{through reference here}} + typealias Nest = P_54662 // expected-error {{circular reference}} expected-note {{through reference here}} } -extension SR12236_A: SR12236_A.Nest { } +extension C_54662: C_54662.Nest { } diff --git a/test/decl/overload.swift b/test/decl/overload.swift index a30394c0a515c..306271be9b6cf 100644 --- a/test/decl/overload.swift +++ b/test/decl/overload.swift @@ -465,25 +465,29 @@ protocol r21783216b { associatedtype `Protocol` // ok } -struct SR7249 { - var x: T { fatalError() } // expected-note {{previously declared}} +// https://github.com/apple/swift/issues/49797 + +struct S_49797 { + var x: T { get {} } // expected-note {{previously declared}} var y: Int // expected-note {{previously declared}} var z: Int // expected-note {{previously declared}} } -extension SR7249 { - var x: Int { fatalError() } // expected-warning{{redeclaration of 'x' is deprecated and will be an error in Swift 5}} - var y: T { fatalError() } // expected-warning{{redeclaration of 'y' is deprecated and will be an error in Swift 5}} - var z: Int { fatalError() } // expected-error{{invalid redeclaration of 'z'}} +extension S_49797 { + var x: Int { get {} } // expected-warning{{redeclaration of 'x' is deprecated and will be an error in Swift 5}} + var y: T { get {} } // expected-warning{{redeclaration of 'y' is deprecated and will be an error in Swift 5}} + var z: Int { get {} } // expected-error{{invalid redeclaration of 'z'}} } // A constrained extension is okay. -extension SR7249 where T : P1 { - var x: Int { fatalError() } - var y: T { fatalError() } - var z: Int { fatalError() } +extension S_49797 where T : P1 { + var x: Int { get {} } + var y: T { get {} } + var z: Int { get {} } } +// https://github.com/apple/swift/issues/49798 + protocol P3 { var i: Int { get } subscript(i: Int) -> String { get } @@ -494,135 +498,129 @@ extension P3 { subscript(i: Int) -> String { return "" } } -struct SR7250 : P3 {} +struct S_49798 : P3 {} -extension SR7250 where T : P3 { - var i: Int { return 0 } - subscript(i: Int) -> String { return "" } +extension S_49798 where T : P3 { + var i: Int { get {} } + subscript(i: Int) -> String { get {} } } -// SR-10084 +// https://github.com/apple/swift/issues/52486 -struct SR_10084_S { +struct S_52486 { let name: String } -enum SR_10084_E { - case foo(SR_10084_S) // expected-note {{'foo' previously declared here}} +enum E_52486 { + case foo(S_52486) // expected-note {{'foo' previously declared here}} - static func foo(_ name: String) -> SR_10084_E { // Okay - return .foo(SR_10084_S(name: name)) + static func foo(_ name: String) -> E_52486 { // Okay + return .foo(S_52486(name: name)) } - func foo(_ name: Bool) -> SR_10084_E { // Okay - return .foo(SR_10084_S(name: "Test")) + func foo(_ name: Bool) -> E_52486 { // Okay + return .foo(S_52486(name: "Test")) } - static func foo(_ value: SR_10084_S) -> SR_10084_E { // expected-error {{invalid redeclaration of 'foo'}} + static func foo(_ value: S_52486) -> E_52486 { // expected-error {{invalid redeclaration of 'foo'}} return .foo(value) } } -enum SR_10084_E_1 { - static func foo(_ name: String) -> SR_10084_E_1 { // Okay - return .foo(SR_10084_S(name: name)) +enum E1_52486 { + static func foo(_ name: String) -> E1_52486 { // Okay + return .foo(S_52486(name: name)) } - static func foo(_ value: SR_10084_S) -> SR_10084_E_1 { // expected-note {{'foo' previously declared here}} + static func foo(_ value: S_52486) -> E1_52486 { // expected-note {{'foo' previously declared here}} return .foo(value) } - case foo(SR_10084_S) // expected-error {{invalid redeclaration of 'foo'}} + case foo(S_52486) // expected-error {{invalid redeclaration of 'foo'}} } -enum SR_10084_E_2 { +enum E2_52486 { case fn(() -> Void) // expected-note {{'fn' previously declared here}} - static func fn(_ x: @escaping () -> Void) -> SR_10084_E_2 { // expected-error {{invalid redeclaration of 'fn'}} - fatalError() - } + static func fn(_ x: @escaping () -> Void) -> E2_52486 {} // expected-error {{invalid redeclaration of 'fn'}} - static func fn(_ x: @escaping () -> Int) -> SR_10084_E_2 { // Okay - fatalError() - } + static func fn(_ x: @escaping () -> Int) -> E2_52486 {} // Okay - static func fn(_ x: @escaping () -> Bool) -> SR_10084_E_2 { // Okay - fatalError() - } + static func fn(_ x: @escaping () -> Bool) -> E2_52486 {} // Okay } // N.B. Redeclaration checks don't see this case because `protocol A` is invalid. -enum SR_10084_E_3 { +enum E3_52486 { protocol A {} //expected-error {{protocol 'A' cannot be nested inside another declaration}} case A } -enum SR_10084_E_4 { +enum E4_52486 { class B {} // expected-note {{'B' previously declared here}} case B // expected-error {{invalid redeclaration of 'B'}} } -enum SR_10084_E_5 { +enum E5_52486 { struct C {} // expected-note {{'C' previously declared here}} case C // expected-error {{invalid redeclaration of 'C'}} } // N.B. Redeclaration checks don't see this case because `protocol D` is invalid. -enum SR_10084_E_6 { +enum E6_52486 { case D protocol D {} //expected-error {{protocol 'D' cannot be nested inside another declaration}} } -enum SR_10084_E_7 { +enum E7_52486 { case E // expected-note {{'E' previously declared here}} class E {} // expected-error {{invalid redeclaration of 'E'}} } -enum SR_10084_E_8 { +enum E8_52486 { case F // expected-note {{'F' previously declared here}} struct F {} // expected-error {{invalid redeclaration of 'F'}} } -enum SR_10084_E_9 { +enum E9_52486 { case A // expected-note {{'A' previously declared here}} expected-note {{found this candidate}} - static let A: SR_10084_E_9 = .A // expected-error {{invalid redeclaration of 'A'}} + static let A: E9_52486 = .A // expected-error {{invalid redeclaration of 'A'}} // expected-error@-1 {{ambiguous use of 'A'}} expected-note@-1 {{found this candidate}} } -enum SR_10084_E_10 { - static let A: SR_10084_E_10 = .A // expected-note {{'A' previously declared here}} +enum E10_52486 { + static let A: E10_52486 = .A // expected-note {{'A' previously declared here}} // expected-error@-1 {{ambiguous use of 'A'}} expected-note@-1 {{found this candidate}} case A // expected-error {{invalid redeclaration of 'A'}} expected-note {{found this candidate}} } -enum SR_10084_E_11 { +enum E11_52486 { case A // expected-note {{'A' previously declared here}} expected-note {{found this candidate}} - static var A: SR_10084_E_11 = .A // expected-error {{invalid redeclaration of 'A'}} + static var A: E11_52486 = .A // expected-error {{invalid redeclaration of 'A'}} // expected-error@-1 {{ambiguous use of 'A'}} expected-note@-1 {{found this candidate}} } -enum SR_10084_E_12 { - static var A: SR_10084_E_12 = .A // expected-note {{'A' previously declared here}} +enum E12_52486 { + static var A: E12_52486 = .A // expected-note {{'A' previously declared here}} // expected-error@-1 {{ambiguous use of 'A'}} expected-note@-1 {{found this candidate}} case A // expected-error {{invalid redeclaration of 'A'}} expected-note {{found this candidate}} } -enum SR_10084_E_13 { +enum E13_52486 { case X // expected-note {{'X' previously declared here}} struct X {} // expected-error {{invalid redeclaration of 'X'}} } -enum SR_10084_E_14 { +enum E14_52486 { struct X {} // expected-note {{'X' previously declared here}} case X // expected-error {{invalid redeclaration of 'X'}} } -enum SR_10084_E_15 { +enum E15_52486 { case Y // expected-note {{'Y' previously declared here}} typealias Y = Int // expected-error {{invalid redeclaration of 'Y'}} } -enum SR_10084_E_16 { +enum E16_52486 { typealias Z = Int // expected-note {{'Z' previously declared here}} case Z // expected-error {{invalid redeclaration of 'Z'}} } diff --git a/test/decl/overload_swift4.swift b/test/decl/overload_swift4.swift index 05917938c99e4..1170cdb1964e2 100644 --- a/test/decl/overload_swift4.swift +++ b/test/decl/overload_swift4.swift @@ -1,18 +1,20 @@ // RUN: %target-typecheck-verify-swift -swift-version 4 -struct SR7251 { +// https://github.com/apple/swift/issues/49799 + +struct S1 { struct j {} // expected-note {{previously declared here}} - static var k: Int { return 0 } // expected-note {{previously declared here}} + static var k: Int { get {} } // expected-note {{previously declared here}} } -extension SR7251 { - static var i: Int { return 0 } +extension S1 { + static var i: Int { get {} } // expected-note@-1 {{previously declared here}} // expected-note@-2 {{previously declared here}} struct i {} // expected-warning {{redeclaration of 'i' is deprecated and will be an error in Swift 5}} typealias i = Int // expected-warning {{redeclaration of 'i' is deprecated and will be an error in Swift 5}} - static var j: Int { return 0 } // expected-warning {{redeclaration of 'j' is deprecated and will be an error in Swift 5}} + static var j: Int { get {} } // expected-warning {{redeclaration of 'j' is deprecated and will be an error in Swift 5}} struct k {} // expected-error{{invalid redeclaration of 'k'}} } diff --git a/test/decl/overload_swift5.swift b/test/decl/overload_swift5.swift index 99c274f02e104..bc68cb39afcea 100644 --- a/test/decl/overload_swift5.swift +++ b/test/decl/overload_swift5.swift @@ -1,24 +1,27 @@ // RUN: %target-typecheck-verify-swift -swift-version 5 -struct SR7251 { +// https://github.com/apple/swift/issues/49799 + +struct S1 { struct j {} // expected-note {{previously declared here}} - static var k: Int { return 0 } // expected-note {{previously declared here}} + static var k: Int { get {} } // expected-note {{previously declared here}} } -extension SR7251 { - static var i: Int { return 0 } // expected-note {{previously declared here}} +extension S1 { + static var i: Int { get {} } // expected-note {{previously declared here}} struct i {} // expected-error{{invalid redeclaration of 'i'}} - static var j: Int { return 0 } // expected-error{{invalid redeclaration of 'j'}} + static var j: Int { get {} } // expected-error{{invalid redeclaration of 'j'}} struct k {} // expected-error{{invalid redeclaration of 'k'}} } -struct SR7249 { - var x: T { fatalError() } // expected-note {{previously declared}} - var y: Int // expected-note {{previously declared}} - var z: Int // expected-note {{previously declared}} -} +// https://github.com/apple/swift/issues/49797 -extension SR7249 { - var x: Int { fatalError() } // expected-error{{invalid redeclaration of 'x'}} - var y: T { fatalError() } // expected-error{{invalid redeclaration of 'y'}} - var z: Int { fatalError() } // expected-error{{invalid redeclaration of 'z'}} +struct S2 { + var x: T { get {} } // expected-note {{previously declared}} + var y: Int // expected-note {{previously declared}} + var z: Int // expected-note {{previously declared}} +} +extension S2 { + var x: Int { get {} } // expected-error{{invalid redeclaration of 'x'}} + var y: T { get {} } // expected-error{{invalid redeclaration of 'y'}} + var z: Int { get {} } // expected-error{{invalid redeclaration of 'z'}} } From da566542b4da53975949c8c4b6e64d2bfbc581e4 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Sun, 21 Aug 2022 21:36:24 +0300 Subject: [PATCH 394/491] Gardening: Migrate test suite to GH issues: decl/enum --- test/decl/enum/enumtest.swift | 10 ++++++---- test/decl/enum/special_case_name.swift | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/decl/enum/enumtest.swift b/test/decl/enum/enumtest.swift index be3691db927ca..6f7d02e597998 100644 --- a/test/decl/enum/enumtest.swift +++ b/test/decl/enum/enumtest.swift @@ -299,7 +299,8 @@ func testSimpleEnum() { let _ : SimpleEnum=.X // expected-error {{'=' must have consistent whitespace on both sides}} } -enum SR510: String { +// https://github.com/apple/swift/issues/43127 +enum E_43127: String { case Thing = "thing" case Bob = {"test"} // expected-error {{raw value for enum case must be a literal}} } @@ -337,7 +338,8 @@ enum HasVariadic { case variadic(x: Int...) // expected-error {{variadic enum cases are not supported}} } -// SR-2176 +// https://github.com/apple/swift/issues/44784 + enum Foo { case bar case none @@ -446,7 +448,7 @@ protocol P {} enum E : C & P {} // expected-error@-1 {{inheritance from class-constrained protocol composition type 'C & P'}} -// SR-11522 +// https://github.com/apple/swift/issues/53923 enum EnumWithStaticNone1 { case a @@ -573,7 +575,7 @@ let _: EnumWithTypealiasNone? = .none // Okay let _: EnumWithBothStructAndComputedNone? = .none // Okay let _: EnumWithBothTypealiasAndComputedNone? = .none // Okay -// SR-12063 +// https://github.com/apple/swift/issues/54499 let foo1: Foo? = Foo.none let foo2: Foo?? = Foo.none diff --git a/test/decl/enum/special_case_name.swift b/test/decl/enum/special_case_name.swift index b24e88cecca64..90e37218a4b2d 100644 --- a/test/decl/enum/special_case_name.swift +++ b/test/decl/enum/special_case_name.swift @@ -1,6 +1,6 @@ // RUN: %target-typecheck-verify-swift -swift-version 5 -// https://bugs.swift.org/browse/SR-1660 +// https://github.com/apple/swift/issues/44269 enum DayOfTheWeek : Int { case monday = 0 From 0c749b2651d5d36447466cfc38ca814530ee4c61 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 23 Aug 2022 01:02:28 +0300 Subject: [PATCH 395/491] Gardening: Migrate test suite to GH issues: decl/ext --- test/decl/ext/extensions.swift | 17 +++++++++-------- test/decl/ext/generic.swift | 2 +- test/decl/ext/ordering.swift | 2 +- test/decl/ext/protocol.swift | 4 +++- test/decl/ext/specialize.swift | 2 +- test/decl/ext/sr_12460.swift | 5 ++++- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/test/decl/ext/extensions.swift b/test/decl/ext/extensions.swift index 91dedddad0a17..c6ef3c72b488e 100644 --- a/test/decl/ext/extensions.swift +++ b/test/decl/ext/extensions.swift @@ -122,9 +122,9 @@ extension X3 { func foo() -> Int { return 0 } } -// Make sure the test case from https://bugs.swift.org/browse/SR-3847 doesn't -// cause problems when the later extension is incorrectly nested inside another -// declaration. +// Make sure the test case from https://github.com/apple/swift/issues/46432 +// doesn't cause problems when the later extension is incorrectly nested inside +// another declaration. extension C1.NestedStruct { static let originalValue = 0 } @@ -135,7 +135,7 @@ struct WrapperContext { } // Class-constrained extension where protocol does not impose class requirement -// SR-11298 +// https://github.com/apple/swift/issues/53699 protocol DoesNotImposeClassReq_1 {} @@ -352,11 +352,12 @@ extension Tree.BoughPayload.Contents { // expected-note@-2 {{did you mean to extend 'Nest' instead?}} } -// SR-10466 Check 'where' clause when referencing type defined inside extension -struct SR_10466 { - var a : A // expected-error {{'SR_10466.A' (aka 'Int') requires the types 'T' and 'Never' be equivalent}} +// https://github.com/apple/swift/issues/52866 +// Check 'where' clause when referencing type defined inside extension. +struct S_52866 { + var a : A // expected-error {{'S_52866.A' (aka 'Int') requires the types 'T' and 'Never' be equivalent}} } -extension SR_10466 where T == Never { // expected-note {{requirement specified as 'T' == 'Never' [with T = T]}} +extension S_52866 where T == Never { // expected-note {{requirement specified as 'T' == 'Never' [with T = T]}} typealias A = Int } diff --git a/test/decl/ext/generic.swift b/test/decl/ext/generic.swift index 91c26bddab20e..753f87b2131c4 100644 --- a/test/decl/ext/generic.swift +++ b/test/decl/ext/generic.swift @@ -175,7 +175,7 @@ extension Array2 where QQQ : VVV {} // expected-error@-1 {{cannot find type 'QQQ' in scope}} // expected-error@-2 {{cannot find type 'VVV' in scope}} -// https://bugs.swift.org/browse/SR-9009 +// https://github.com/apple/swift/issues/51512 func foo() { extension Array where Element : P1 { // expected-error@-1 {{declaration is only valid at file scope}} diff --git a/test/decl/ext/ordering.swift b/test/decl/ext/ordering.swift index f08b3e44f868e..4e418f218f3cd 100644 --- a/test/decl/ext/ordering.swift +++ b/test/decl/ext/ordering.swift @@ -122,7 +122,7 @@ extension OtherOuter5 { class Super {} } -/// SR-5993 +/// https://github.com/apple/swift/issues/48550 enum Outer5A {} diff --git a/test/decl/ext/protocol.swift b/test/decl/ext/protocol.swift index 612e236b0469e..985bc960cce5e 100644 --- a/test/decl/ext/protocol.swift +++ b/test/decl/ext/protocol.swift @@ -288,7 +288,9 @@ extension ExtendedProtocol where Self : DerivedWithAlias { func f4(x: NestedNominal) {} } -// rdar://problem/21991470 & https://bugs.swift.org/browse/SR-5022 +// rdar://problem/21991470 +// https://github.com/apple/swift/issues/47598 + class NonPolymorphicInit { init() { } // expected-note {{selected non-required initializer 'init()'}} } diff --git a/test/decl/ext/specialize.swift b/test/decl/ext/specialize.swift index 2c91aa5ab5428..2312e8c2d245e 100644 --- a/test/decl/ext/specialize.swift +++ b/test/decl/ext/specialize.swift @@ -15,7 +15,7 @@ let _ = [1, 2, 3].makeString() // expected-error 3 {{cannot convert value of typ extension Set<_> {} // expected-error {{cannot extend a type that contains placeholders}} -// https://bugs.swift.org/browse/SR-4875 +// https://github.com/apple/swift/issues/47452 struct Foo { var x: T diff --git a/test/decl/ext/sr_12460.swift b/test/decl/ext/sr_12460.swift index a281d464639ee..5482c1b9db67b 100644 --- a/test/decl/ext/sr_12460.swift +++ b/test/decl/ext/sr_12460.swift @@ -1,6 +1,9 @@ // RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s 2>&1 | %FileCheck -check-prefix CHECK %s -// Test that we don't crash when validating members inside an extension with no type name. +// https://github.com/apple/swift/issues/54900 +// +// Test that we don't crash when validating members inside an extension with no +// type name. // CHECK: :[[@LINE+1]]:11: error: expected type name in extension declaration extension { From edd4010664af27dab0db9312f0cfde0525019e80 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 23 Aug 2022 03:14:43 +0300 Subject: [PATCH 396/491] Gardening: Migrate test suite to GH issues: decl/func --- test/decl/func/default-values-swift4.swift | 2 +- test/decl/func/default-values.swift | 23 +++++++++++-------- test/decl/func/functions.swift | 2 +- test/decl/func/rethrows.swift | 16 ++++++++----- .../func/throwing_functions_without_try.swift | 8 +++---- test/decl/func/trailing_closures.swift | 3 ++- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/test/decl/func/default-values-swift4.swift b/test/decl/func/default-values-swift4.swift index c0116bedb35ec..5da6ad50506ff 100644 --- a/test/decl/func/default-values-swift4.swift +++ b/test/decl/func/default-values-swift4.swift @@ -93,7 +93,7 @@ public func publicFunctionWithDefaultValue( y: Int = internalIntFunction()) {} // expected-error@-1 {{global function 'internalIntFunction()' is internal and cannot be referenced from a default argument value}} -// https://bugs.swift.org/browse/SR-5559 +// https://github.com/apple/swift/issues/48131 public class MyClass { public func method(_: T.Type = T.self) -> T { } } diff --git a/test/decl/func/default-values.swift b/test/decl/func/default-values.swift index c08c5bf8581ef..391488e3dbe3b 100644 --- a/test/decl/func/default-values.swift +++ b/test/decl/func/default-values.swift @@ -123,7 +123,7 @@ struct X { let testXa: X = .foo(i: 0) let testXb: X = .bar -// SR-10062 +// https://github.com/apple/swift/issues/52464 var aLiteral = 1 let bLiteral = 2 @@ -175,16 +175,21 @@ let fooThing5 = Foo(a: 0, d: 1, h: nil) // expected-error {{missing arguments fo let fooThing6 = Foo(a: 0, d: 1, e: 2, h: nil) // expected-error {{missing argument for parameter 'f' in call}} // expected-note@-29 {{'init(a:b:d:e:f:g:h:)' declared here}} -// SR-11085 -func sr_11085(x: Int) {} -func sr_11085(line: String = #line) {} // expected-error {{default argument value of type 'Int' cannot be converted to type 'String'}} -sr_11085() +// https://github.com/apple/swift/issues/53477 + do { + func f(x: Int) {} + func f(line: String = #line) {} // expected-error {{default argument value of type 'Int' cannot be converted to type 'String'}} + f() -class SR_11085_C { init(line: String = #line) {} } // expected-error {{default argument value of type 'Int' cannot be converted to type 'String'}} -let _ = SR_11085_C() + class C { init(line: String = #line) {} } // expected-error {{default argument value of type 'Int' cannot be converted to type 'String'}} + let _ = C() +} + +// https://github.com/apple/swift/issues/54034 -// SR-11623 -func badGenericMagicLiteral(_ x: T = #function) -> T { x } // expected-error {{default argument value of type 'String' cannot be converted to type 'T'}} +// FIXME: Bad diagnostic +// expected-error@+1 {{default argument value of type 'String' cannot be converted to type 'T'}} +func badGenericMagicLiteral(_ x: T = #function) -> T { x } let _: Int = badGenericMagicLiteral() func genericMagicLiteral(_ x: T = #line) -> T { x } // expected-note {{where 'T' = 'String'}} diff --git a/test/decl/func/functions.swift b/test/decl/func/functions.swift index 3432e021e2f58..0f0706306795a 100644 --- a/test/decl/func/functions.swift +++ b/test/decl/func/functions.swift @@ -181,7 +181,7 @@ func parentheticalInout2(_ fn: (((inout Int)), Int) -> ()) { fn(&value, 0) } -// SR-11724 +// https://github.com/apple/swift/issues/54133 // FIXME: None of these diagnostics is particularly good. func bogusDestructuring() { struct Bar {} diff --git a/test/decl/func/rethrows.swift b/test/decl/func/rethrows.swift index 5dc3fb05bc38a..115da18c293ae 100644 --- a/test/decl/func/rethrows.swift +++ b/test/decl/func/rethrows.swift @@ -536,7 +536,7 @@ func testDoRethrow() { DoRethrowGeneric().method(fn:) { (a, b) in return a } } -// https://bugs.swift.org/browse/SR-7120 - capture lists +// https://github.com/apple/swift/issues/49668 func rethrowsWithCaptureList( array: [T], operation: (Int) throws -> R @@ -553,10 +553,10 @@ public func rdar40472018() { } -// https://bugs.swift.org/browse/SR-6299 +// https://github.com/apple/swift/issues/48849 // Verify that we do not emit an invalid // "... can throw but the expression is not marked with 'try'" -// error on the use of the operators. +// error on the use of operators. infix operator <|: infixr0 infix operator |>: infixl1 @@ -613,12 +613,16 @@ func rdar_47550715() { func bar(_: A? = .none) {} // Ok } -// SR-14270 - test case for diagnostic note 'because_rethrows_default_argument_throws' +// https://github.com/apple/swift/issues/56630 +// Test cases for diagnostic note 'because_rethrows_default_argument_throws' + func nonThrowableDefaultRethrows(_ f: () throws -> () = {}) rethrows { try f() } -// NOTE: This should compile and not emit a diagnostic because ideally the compiler could statically -// know the default argument value could never throw. See SR-1524. + +// FIXME: This should compile and not emit a diagnostic because ideally the +// compiler could statically know the default argument value could never throw. +// (https://github.com/apple/swift/issues/44143) nonThrowableDefaultRethrows() // expected-error {{call can throw but is not marked with 'try'}} // expected-note@-1 {{call is to 'rethrows' function, but a defaulted argument function can throw}} diff --git a/test/decl/func/throwing_functions_without_try.swift b/test/decl/func/throwing_functions_without_try.swift index 793fbe71840da..6610fb818e524 100644 --- a/test/decl/func/throwing_functions_without_try.swift +++ b/test/decl/func/throwing_functions_without_try.swift @@ -52,14 +52,14 @@ func baz2() -> Int { return x } -// SR-11016 +// https://github.com/apple/swift/issues/53406 -protocol SR_11016_P { +protocol P_53406 { func bar() throws } -class SR_11016_C { - var foo: SR_11016_P? +class C_53406 { + var foo: P_53406? func someMethod() throws { foo?.bar() // expected-error {{call can throw but is not marked with 'try'}} diff --git a/test/decl/func/trailing_closures.swift b/test/decl/func/trailing_closures.swift index 4de57495a7515..c5b82752a8589 100644 --- a/test/decl/func/trailing_closures.swift +++ b/test/decl/func/trailing_closures.swift @@ -1,5 +1,6 @@ // RUN: %target-typecheck-verify-swift -// SR-4205: Don't warn about non-trailing closures followed by parameters with +// https://github.com/apple/swift/issues/46788 +// Don't warn about non-trailing closures followed by parameters with // default arguments. func f1(_ f: () -> (), bar: Int = 10) { } // no-warning From 6704aabb20236ca910d8b042b54bd381e76c6821 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 23 Aug 2022 03:19:22 +0300 Subject: [PATCH 397/491] Gardening: Migrate test suite to GH issues: decl/inherit --- test/decl/inherit/inherit.swift | 2 +- test/decl/inherit/initializer.swift | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/decl/inherit/inherit.swift b/test/decl/inherit/inherit.swift index b84eb537d1c05..ccea58739e525 100644 --- a/test/decl/inherit/inherit.swift +++ b/test/decl/inherit/inherit.swift @@ -18,7 +18,7 @@ class C : B, A { } // expected-error{{multiple inheritance from classes 'B' and // Superclass in the wrong position class D : P, A { } // expected-error{{superclass 'A' must appear first in the inheritance clause}}{{12-15=}}{{11-11=A, }} -// SR-8160 +// https://github.com/apple/swift/issues/50692 class D1 : Any, A { } // expected-error{{superclass 'A' must appear first in the inheritance clause}}{{15-18=}}{{12-12=A, }} class D2 : P & P1, A { } // expected-error{{superclass 'A' must appear first in the inheritance clause}}{{18-21=}}{{12-12=A, }} diff --git a/test/decl/inherit/initializer.swift b/test/decl/inherit/initializer.swift index 7e08f4295a445..dd01bb0bb81f8 100644 --- a/test/decl/inherit/initializer.swift +++ b/test/decl/inherit/initializer.swift @@ -111,21 +111,21 @@ func testClassInGenericFunc(t: T) { } -// Required convenience init inhibits inheritance - -class SR5056A { +// https://github.com/apple/swift/issues/47632 +// Required convenience 'init' inhibits inheritance +do { + class A { required init(a: Int) {} -} + } -class SR5056B : SR5056A { + class B : A { required convenience init(b: Int) { self.init(a: b) } -} + } -class SR5056C : SR5056B {} + class C : B {} -func useSR5056C() { - _ = SR5056C(a: 0) - _ = SR5056C(b: 0) + _ = C(a: 0) + _ = C(b: 0) } From b5e6fb3f1a5ec99dc462ed3544c5a3e8ba883a0c Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 23 Aug 2022 03:24:05 +0300 Subject: [PATCH 398/491] Gardening: Migrate test suite to GH issues: decl/nested --- test/decl/nested/type_in_type.swift | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/decl/nested/type_in_type.swift b/test/decl/nested/type_in_type.swift index e50daca7dc4b7..1a8ef97e6ce35 100644 --- a/test/decl/nested/type_in_type.swift +++ b/test/decl/nested/type_in_type.swift @@ -340,7 +340,9 @@ class DerivedClass : BaseClass { } } -// https://bugs.swift.org/browse/SR-3847: Resolve members in inner types. +// https://github.com/apple/swift/issues/46432 +// Resolve members in inner types. +// // This first extension isn't necessary; we could have put 'originalValue' in // the original declaration. extension OuterNonGenericClass.InnerNonGenericBase { @@ -372,7 +374,8 @@ extension OuterGeneric.MidGeneric where D == Int, F == String { } } -// https://bugs.swift.org/browse/SR-4672 +// https://github.com/apple/swift/issues/47249 + protocol ExpressibleByCatLiteral {} protocol ExpressibleByDogLiteral {} @@ -393,10 +396,10 @@ func something() -> T { while true {} } -func test() { +do { let _: Claws.Fangs = pets(fur: Puppy()) - // + // https://github.com/apple/swift/issues/48172 let _: Claws.Fangs = pets(fur: Puppy()) let _: Claws.Fangs = Claws.Fangs() let _: Claws.Fangs = Claws.Fangs() @@ -410,7 +413,7 @@ func test() { // expected-note@-3 {{explicitly specify the generic arguments to fix this issue}} {{12-12=<<#A: ExpressibleByCatLiteral#>>}} } -// https://bugs.swift.org/browse/SR-4379 +// https://github.com/apple/swift/issues/46958 extension OuterGeneric.MidNonGeneric { func doStuff() -> OuterGeneric { return OuterGeneric() From 6a91ae3f555e5c2899ecd3b2f2bb4dd6ef46e5db Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 23 Aug 2022 03:28:53 +0300 Subject: [PATCH 399/491] Gardening: Migrate test suite to GH issues: decl/typealias --- test/decl/typealias/on_constrained_protocol.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/decl/typealias/on_constrained_protocol.swift b/test/decl/typealias/on_constrained_protocol.swift index a2e8010ae1f5b..e4e21a20cab9f 100644 --- a/test/decl/typealias/on_constrained_protocol.swift +++ b/test/decl/typealias/on_constrained_protocol.swift @@ -41,7 +41,8 @@ extension DoubleOverloadedSameTypealias where MyAssocType == Int { } func useDoubleOverloadedSameTypealias() -> DoubleOverloadedSameTypealias.Content {} -// Overload associatedtype with typealias (SR-8274) +// Overload associatedtype with typealias +// https://github.com/apple/swift/issues/50805 protocol MarkerProtocol {} protocol ProtocolWithAssoctype { From 93c964fa8170849131a3be62e5cb6cc4bb36c79f Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 23 Aug 2022 04:34:11 +0300 Subject: [PATCH 400/491] Gardening: Migrate test suite to GH issues: decl/subscript --- test/decl/subscript/subscripting.swift | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/test/decl/subscript/subscripting.swift b/test/decl/subscript/subscripting.swift index 842a1106cc6f4..f670c9e066a6d 100644 --- a/test/decl/subscript/subscripting.swift +++ b/test/decl/subscript/subscripting.swift @@ -424,7 +424,8 @@ func testSubscript1(_ s2 : SubscriptTest2) { let v: (Int?, [Int]?) = (nil [17]) // expected-error {{cannot subscript a nil literal value}} } -// sr-114 & rdar://22007370 +// rdar://22007370 +// https://github.com/apple/swift/issues/42736 class Foo { subscript(key: String) -> String { // expected-note {{'subscript(_:)' previously declared here}} @@ -447,17 +448,19 @@ protocol r23952125 { var c : Int // expected-error {{property in protocol must have explicit { get } or { get set } specifier}} {{14-14= { get <#set#> \}}} } -// SR-2575 -struct SR2575 { - subscript() -> Int { // expected-note {{declared here}} - return 1 +// https://github.com/apple/swift/issues/45180 +do { + struct S { + subscript() -> Int { // expected-note {{declared here}} + return 1 + } } -} -SR2575().subscript() -// expected-error@-1 {{value of type 'SR2575' has no property or method named 'subscript'; did you mean to use the subscript operator?}} {{9-10=}} {{10-19=}} {{19-20=[}} {{20-21=]}} + S().subscript() + // expected-error@-1 {{value of type 'S' has no property or method named 'subscript'; did you mean to use the subscript operator?}} {{6-7=}} {{7-16=}} {{16-17=[}} {{17-18=]}} +} -// SR-7890 +// https://github.com/apple/swift/issues/50425 struct InOutSubscripts { subscript(x1: inout Int) -> Int { return 0 } From 97e122fee76a95449682de10d5bda91aa52674e1 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Thu, 25 Aug 2022 05:25:06 +0300 Subject: [PATCH 401/491] Gardening: Migrate test suite to GH issues: decl/var --- test/decl/var/NSManaged_properties.swift | 2 +- test/decl/var/didset_oldvalue.swift | 2 +- test/decl/var/lazy_properties.swift | 3 +- test/decl/var/properties.swift | 93 ++++---- .../property_wrapper_generic_aliases.swift | 2 +- test/decl/var/property_wrappers.swift | 202 ++++++++++-------- .../var/result_builders_availability.swift | 4 +- test/decl/var/usage.swift | 18 +- test/decl/var/variables.swift | 4 +- 9 files changed, 176 insertions(+), 154 deletions(-) diff --git a/test/decl/var/NSManaged_properties.swift b/test/decl/var/NSManaged_properties.swift index 9f9e9f6df36e4..c45609aceecca 100644 --- a/test/decl/var/NSManaged_properties.swift +++ b/test/decl/var/NSManaged_properties.swift @@ -52,7 +52,7 @@ class SwiftGizmo : A { @NSManaged class func mutableArrayValueForA() {} // expected-error {{@NSManaged only allowed on an instance property or method}} // expected-error@-1 {{@NSManaged method cannot have a body; it must be provided at runtime}} - // SR-1050: don't assert + // (https://github.com/apple/swift/issues/43662) Don't assert. @NSManaged var multiA, multiB, multiC : NSNumber? override init() {} diff --git a/test/decl/var/didset_oldvalue.swift b/test/decl/var/didset_oldvalue.swift index 03e998f9d032b..afaf8acd78265 100644 --- a/test/decl/var/didset_oldvalue.swift +++ b/test/decl/var/didset_oldvalue.swift @@ -3,7 +3,7 @@ import Swift -// SR-11297 +// https://github.com/apple/swift/issues/53698 // Do not call the getter to fetch the oldValue when oldValue is not // referenced in the body diff --git a/test/decl/var/lazy_properties.swift b/test/decl/var/lazy_properties.swift index ba7c5c5204458..042b52da4ba40 100644 --- a/test/decl/var/lazy_properties.swift +++ b/test/decl/var/lazy_properties.swift @@ -124,7 +124,8 @@ struct Outer { } } -// https://bugs.swift.org/browse/SR-2616 +// https://github.com/apple/swift/issues/45221 + struct Construction { init(x: Int, y: Int? = 42) { } } diff --git a/test/decl/var/properties.swift b/test/decl/var/properties.swift index 43a0e2384cb91..4ff98e2dd742a 100644 --- a/test/decl/var/properties.swift +++ b/test/decl/var/properties.swift @@ -1227,40 +1227,42 @@ class r24314506 { // expected-error {{class 'r24314506' has no initializers}} } -// https://bugs.swift.org/browse/SR-3893 +// https://github.com/apple/swift/issues/46478 // Generic type is not inferenced from its initial value for properties with -// will/didSet -struct SR3893Box { - let value: Foo -} +// observers. +do { + struct Box { + let value: Foo + } -struct SR3893 { - // Each of these "bad" properties used to produce errors. - var bad: SR3893Box = SR3893Box(value: 0) { - willSet { - print(newValue.value) + struct S { + // Each of these "bad" properties used to produce errors. + var bad: Box = Box(value: 0) { + willSet { + print(newValue.value) + } } - } - var bad2: SR3893Box = SR3893Box(value: 0) { - willSet(new) { - print(new.value) + var bad2: Box = Box(value: 0) { + willSet(new) { + print(new.value) + } } - } - var bad3: SR3893Box = SR3893Box(value: 0) { - didSet { - print(oldValue.value) + var bad3: Box = Box(value: 0) { + didSet { + print(oldValue.value) + } } - } - var good: SR3893Box = SR3893Box(value: 0) { - didSet { - print(oldValue.value) + var good: Box = Box(value: 0) { + didSet { + print(oldValue.value) + } } - } - var plain: SR3893Box = SR3893Box(value: 0) + var plain: Box = Box(value: 0) + } } protocol WFI_P1 : class {} @@ -1276,19 +1278,19 @@ class WeakFixItTest { weak var bar : WFI_P1 & WFI_P2 } -// SR-8811 (Warning) +// https://github.com/apple/swift/issues/51319 (Warning) -let sr8811a = fatalError() // expected-warning {{constant 'sr8811a' inferred to have type 'Never', which is an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}} {{12-12=: Never}} +let c1_51319 = fatalError() // expected-warning {{constant 'c1_51319' inferred to have type 'Never', which is an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}} {{13-13=: Never}} -let sr8811b: Never = fatalError() // Ok +let c2_51319: Never = fatalError() // Ok -let sr8811c = (16, fatalError()) // expected-warning {{constant 'sr8811c' inferred to have type '(Int, Never)', which contains an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}} {{12-12=: (Int, Never)}} +let c3_51319 = (16, fatalError()) // expected-warning {{constant 'c3_51319' inferred to have type '(Int, Never)', which contains an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}} {{13-13=: (Int, Never)}} -let sr8811d: (Int, Never) = (16, fatalError()) // Ok +let c4_51319: (Int, Never) = (16, fatalError()) // Ok -// SR-10995 +// https://github.com/apple/swift/issues/53385 -class SR_10995 { +class C_53385 { func makeDoubleOptionalNever() -> Never?? { return nil } @@ -1297,7 +1299,7 @@ class SR_10995 { return nil } - func sr_10995_foo() { + func f_53385() { let doubleOptionalNever = makeDoubleOptionalNever() // expected-warning {{constant 'doubleOptionalNever' inferred to have type 'Never??', which may be unexpected}} // expected-note@-1 {{add an explicit type annotation to silence this warning}} {{28-28=: Never??}} // expected-warning@-2 {{initialization of immutable value 'doubleOptionalNever' was never used; consider replacing with assignment to '_' or removing it}} @@ -1307,33 +1309,33 @@ class SR_10995 { } } -// SR-9267 +// https://github.com/apple/swift/issues/51744 -class SR_9267 {} -extension SR_9267 { +class C1_51744 {} +extension C1_51744 { var foo: String = { // expected-error {{extensions must not contain stored properties}} // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'foo' a computed property}}{{19-21=}} return "Hello" } } -enum SR_9267_E { - var SR_9267_prop: String = { // expected-error {{enums must not contain stored properties}} // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop' a computed property}}{{28-30=}} +enum E_51744 { + var prop: String = { // expected-error {{enums must not contain stored properties}} // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'prop' a computed property}}{{20-22=}} return "Hello" } } -var SR_9267_prop_1: Int = { // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_1' a computed property}}{{25-27=}} +var v_51744: Int = { // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'v_51744' a computed property}}{{18-20=}} return 0 } -class SR_9267_C { - var SR_9267_prop_2: String = { // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_2' a computed property}}{{30-32=}} +class C2_51744 { + var prop: String = { // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'prop' a computed property}}{{20-22=}} return "Hello" } } -class SR_9267_C2 { - let SR_9267_prop_3: Int = { return 0 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_3' a computed property}}{{3-6=var}}{{27-29=}} +class C3_51744 { + let prop: Int = { return 0 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'prop' a computed property}}{{3-6=var}}{{17-19=}} } class LazyPropInClass { @@ -1341,11 +1343,12 @@ class LazyPropInClass { // expected-note@-1 {{Remove '=' to make 'foo' a computed property}}{{21-23=}}{{3-8=}} } -// SR-15657 -enum SR15657 { +// https://github.com/apple/swift/issues/57936 + +enum E1_57936 { var foo: Int {} // expected-error{{missing return in accessor expected to return 'Int'}} } -enum SR15657_G { +enum E2_57936 { var foo: T {} // expected-error{{missing return in accessor expected to return 'T'}} } diff --git a/test/decl/var/property_wrapper_generic_aliases.swift b/test/decl/var/property_wrapper_generic_aliases.swift index fe509284a4611..bbe396f2259ab 100644 --- a/test/decl/var/property_wrapper_generic_aliases.swift +++ b/test/decl/var/property_wrapper_generic_aliases.swift @@ -1,6 +1,6 @@ // RUN: %target-typecheck-verify-swift -// https://bugs.swift.org/browse/SR-14143 +// https://github.com/apple/swift/issues/56522 @propertyWrapper struct SomeLongFooName { diff --git a/test/decl/var/property_wrappers.swift b/test/decl/var/property_wrappers.swift index 668a24f97d465..9a9a10108f622 100644 --- a/test/decl/var/property_wrappers.swift +++ b/test/decl/var/property_wrappers.swift @@ -900,7 +900,8 @@ class TestInvalidRedeclaration1 { // expected-error@-3 {{invalid redeclaration of synthesized property '_i'}} } -// SR-12839 +// https://github.com/apple/swift/issues/55285 + struct TestInvalidRedeclaration2 { var _foo1 = 123 // expected-error {{invalid redeclaration of synthesized property '_foo1'}} @WrapperWithInitialValue var foo1 = 123 // expected-note {{'_foo1' synthesized for property wrapper backing storage}} @@ -1001,28 +1002,36 @@ struct UsesWrapperRequiringP { // expected-error@-3{{type annotation missing in pattern}} } -// SR-10899 / rdar://problem/51588022 -@propertyWrapper -struct SR_10899_Wrapper { - var wrappedValue: String { "hi" } -} +// rdar://problem/51588022 +// https://github.com/apple/swift/issues/53289 +do { + @propertyWrapper + struct Wrapper { + var wrappedValue: String { "hi" } + } -struct SR_10899_Usage { - @SR_10899_Wrapper var thing: Bool // expected-error{{property type 'Bool' does not match 'wrappedValue' type 'String'}} + struct S { + @Wrapper var thing: Bool // expected-error{{property type 'Bool' does not match 'wrappedValue' type 'String'}} + } } -// https://bugs.swift.org/browse/SR-14730 -@propertyWrapper -struct StringWrappedValue { - var wrappedValue: String -} +// https://github.com/apple/swift/issues/57080 +do { + @propertyWrapper + struct StringWrappedValue { + var wrappedValue: String + } -struct SR_14730 { - // expected-error@+1 {{property type '() -> String' does not match 'wrappedValue' type 'String'}} - @StringWrappedValue var value: () -> String + struct S { + // expected-error@+1 {{property type '() -> String' does not match 'wrappedValue' type 'String'}} + @StringWrappedValue var value: () -> String + } } -// SR-11061 / rdar://problem/52593304 assertion with DeclContext mismatches +// rdar://problem/52593304 +// https://github.com/apple/swift/issues/53453 +// Assertion with DeclContext mismatches + class SomeValue { @SomeA(closure: { $0 }) var some: Int = 100 } @@ -1306,7 +1315,7 @@ struct MissingPropertyWrapperUnwrap { self.x[q: "ultimate question", 42] // expected-error {{referencing subscript 'subscript(q:_:)' requires wrapper 'Foo'}} {{10-10=_}} self.x[q: "ultimate question", 42] = true // expected-error {{referencing subscript 'subscript(q:_:)' requires wrapper 'Foo'}} {{10-10=_}} - // SR-11476 + // https://github.com/apple/swift/issues/53876 _ = \Self.[takesFoo: self.x] // expected-error {{cannot convert value 'x' of type 'Int' to expected type 'Foo', use wrapper instead}}{{31-31=_}} _ = \Foo.[x: self._x] // expected-error {{cannot convert value '_x' of type 'Foo' to expected type 'Int', use wrapped value instead}} {{26-27=}} } @@ -1321,22 +1330,23 @@ struct InvalidPropertyDelegateUse { } } -// SR-11060 +// https://github.com/apple/swift/issues/53452 +do { + class C { + @Wrapper var property: Int = 1234 // expected-error {{missing argument for parameter 'string' in property wrapper initializer; add 'wrappedValue' and 'string' arguments in '@Wrapper(...)'}} + } -class SR_11060_Class { - @SR_11060_Wrapper var property: Int = 1234 // expected-error {{missing argument for parameter 'string' in property wrapper initializer; add 'wrappedValue' and 'string' arguments in '@SR_11060_Wrapper(...)'}} -} + @propertyWrapper + struct Wrapper { + var wrappedValue: Int -@propertyWrapper -struct SR_11060_Wrapper { - var wrappedValue: Int - - init(wrappedValue: Int, string: String) { // expected-note {{'init(wrappedValue:string:)' declared here}} - self.wrappedValue = wrappedValue + init(wrappedValue: Int, string: String) { // expected-note {{'init(wrappedValue:string:)' declared here}} + self.wrappedValue = wrappedValue + } } } -// SR-11138 +// https://github.com/apple/swift/issues/53534 // Check that all possible compositions of nonmutating/mutating accessors // on wrappers produce wrapped properties with the correct settability and // mutatiness in all compositions. @@ -1737,69 +1747,70 @@ func test_missing_method_with_lvalue_base() { } } -// SR-11288 -// Look into the protocols that the type conforms to +// https://github.com/apple/swift/issues/53689 +// Look into the protocols that the type conforms to. // typealias as propertyWrapper // @propertyWrapper -struct SR_11288_S0 { +struct W_53689 { var wrappedValue: Int } -protocol SR_11288_P1 { - typealias SR_11288_Wrapper1 = SR_11288_S0 +protocol P1_53689 { + typealias Wrapper1_53689 = W_53689 } -struct SR_11288_S1: SR_11288_P1 { - @SR_11288_Wrapper1 var answer = 42 // Okay +struct S1_53689: P1_53689 { + @Wrapper1_53689 var answer = 42 // Okay } // associatedtype as propertyWrapper // -protocol SR_11288_P2 { - associatedtype SR_11288_Wrapper2 = SR_11288_S0 +protocol P2_53689 { + associatedtype Wrapper2_53689 = W_53689 } -struct SR_11288_S2: SR_11288_P2 { - @SR_11288_Wrapper2 var answer = 42 // expected-error {{unknown attribute 'SR_11288_Wrapper2'}} +struct S2_53689: P2_53689 { + @Wrapper2_53689 var answer = 42 // expected-error {{unknown attribute 'Wrapper2_53689'}} } -protocol SR_11288_P3 { - associatedtype SR_11288_Wrapper3 +protocol P3_53689 { + associatedtype Wrapper3_53689 } -struct SR_11288_S3: SR_11288_P3 { - typealias SR_11288_Wrapper3 = SR_11288_S0 - @SR_11288_Wrapper3 var answer = 42 // Okay +struct S3_53689: P3_53689 { + typealias Wrapper3_53689 = W_53689 + @Wrapper3_53689 var answer = 42 // Okay } // typealias as propertyWrapper in a constrained protocol extension // -protocol SR_11288_P4 {} -extension SR_11288_P4 where Self: AnyObject { // expected-note {{requirement specified as 'Self' : 'AnyObject' [with Self = SR_11288_S4]}} - typealias SR_11288_Wrapper4 = SR_11288_S0 +protocol P4_53689 {} +extension P4_53689 where Self: AnyObject { // expected-note {{requirement specified as 'Self' : 'AnyObject' [with Self = S4_53689]}} + typealias Wrapper4_53689 = W_53689 } -struct SR_11288_S4: SR_11288_P4 { - @SR_11288_Wrapper4 var answer = 42 // expected-error {{'Self.SR_11288_Wrapper4' (aka 'SR_11288_S0') requires that 'SR_11288_S4' be a class type}} +struct S4_53689: P4_53689 { + @Wrapper4_53689 var answer = 42 // expected-error {{'Self.Wrapper4_53689' (aka 'W_53689') requires that 'S4_53689' be a class type}} } -class SR_11288_C0: SR_11288_P4 { - @SR_11288_Wrapper4 var answer = 42 // Okay +class C4_53689: P4_53689 { + @Wrapper4_53689 var answer = 42 // Okay } // typealias as propertyWrapper in a generic type // -protocol SR_11288_P5 { - typealias SR_11288_Wrapper5 = SR_11288_S0 +protocol P5_53689 { + typealias Wrapper5_53689 = W_53689 } -struct SR_11288_S5: SR_11288_P5 { - @SR_11288_Wrapper5 var answer = 42 // Okay +struct S5_53689: P5_53689 { + @Wrapper5_53689 var answer = 42 // Okay } -// SR-11393 +// https://github.com/apple/swift/issues/53794 + protocol Copyable: AnyObject { func copy() -> Self } @@ -1862,37 +1873,37 @@ struct UseNonMutatingProjectedValueSet { } } -// SR-11478 - +// https://github.com/apple/swift/issues/53878 +do { @propertyWrapper -struct SR_11478_W { - var wrappedValue: Value -} + struct Wrapper { + var wrappedValue: Value + } -class SR_11478_C1 { - @SR_11478_W static var bool1: Bool = true // Ok - @SR_11478_W class var bool2: Bool = true // expected-error {{class stored properties not supported in classes; did you mean 'static'?}} - @SR_11478_W class final var bool3: Bool = true // expected-error {{class stored properties not supported in classes; did you mean 'static'?}} -} + class C1 { + @Wrapper static var bool1: Bool = true // Ok + @Wrapper class var bool2: Bool = true // expected-error {{class stored properties not supported in classes; did you mean 'static'?}} + @Wrapper class final var bool3: Bool = true // expected-error {{class stored properties not supported in classes; did you mean 'static'?}} + } -final class SR_11478_C2 { - @SR_11478_W static var bool1: Bool = true // Ok - @SR_11478_W class var bool2: Bool = true // expected-error {{class stored properties not supported in classes; did you mean 'static'?}} - @SR_11478_W class final var bool3: Bool = true // expected-error {{class stored properties not supported in classes; did you mean 'static'?}} + final class C2 { + @Wrapper static var bool1: Bool = true // Ok + @Wrapper class var bool2: Bool = true // expected-error {{class stored properties not supported in classes; did you mean 'static'?}} + @Wrapper class final var bool3: Bool = true // expected-error {{class stored properties not supported in classes; did you mean 'static'?}} + } } -// SR-11381 - +// https://github.com/apple/swift/issues/53782 +do { @propertyWrapper -struct SR_11381_W { - init(wrappedValue: T) {} - var wrappedValue: T { - fatalError() + struct Wrapper { + init(wrappedValue: T) {} + var wrappedValue: T { get {} } } -} -struct SR_11381_S { - @SR_11381_W var foo: Int = nil // expected-error {{'nil' is not compatible with expected argument type 'Int'}} + struct S { + @Wrapper var foo: Int = nil // expected-error {{'nil' is not compatible with expected argument type 'Int'}} + } } // rdar://problem/53349209 - regression in property wrapper inference @@ -1921,12 +1932,12 @@ struct TestConcrete1 { } } -// SR-11477 +// https://github.com/apple/swift/issues/53877 // Two initializers that can default initialize the wrapper // @propertyWrapper -struct SR_11477_W1 { // Okay +struct W1_53877 { // Okay let name: String init() { @@ -1945,7 +1956,7 @@ struct SR_11477_W1 { // Okay // Two initializers with default arguments that can default initialize the wrapper // @propertyWrapper -struct SR_11477_W2 { // Okay +struct W2_53877 { // Okay let name: String init(anotherName: String = "DefaultParamInit1") { @@ -1964,7 +1975,7 @@ struct SR_11477_W2 { // Okay // Single initializer that can default initialize the wrapper // @propertyWrapper -struct SR_11477_W3 { // Okay +struct W3_53877 { // Okay let name: String init() { @@ -2025,7 +2036,7 @@ struct Rdar57411331 { var other: Int } -// SR-11994 +// https://github.com/apple/swift/issues/54428 @propertyWrapper open class OpenPropertyWrapperWithPublicInit { public init(wrappedValue: String) { // Okay @@ -2035,21 +2046,22 @@ open class OpenPropertyWrapperWithPublicInit { open var wrappedValue: String = "Hello, world" } -// SR-11654 +// https://github.com/apple/swift/issues/54065 +do { + struct S {} -struct SR_11654_S {} + class C { + @Foo var property: S? + } -class SR_11654_C { - @Foo var property: SR_11654_S? -} + func f(_ argument: T?) -> T? { + return argument + } -func sr_11654_generic_func(_ argument: T?) -> T? { - return argument + let c = C() + _ = f(c.property) // Okay } -let sr_11654_c = SR_11654_C() -_ = sr_11654_generic_func(sr_11654_c.property) // Okay - // rdar://problem/59471019 - property wrapper initializer requires empty parens // for default init @propertyWrapper diff --git a/test/decl/var/result_builders_availability.swift b/test/decl/var/result_builders_availability.swift index 7606a22a382aa..ff7c02c62e18f 100644 --- a/test/decl/var/result_builders_availability.swift +++ b/test/decl/var/result_builders_availability.swift @@ -88,8 +88,8 @@ tuplify(true) { x in @available(*, unavailable) func unavailableFunc(_ x: Bool) -> Bool {} // expected-note {{'unavailableFunc' has been explicitly marked unavailable here}} -// SR-13260: Availability checking not working in the where clause of a for -// loop. +// https://github.com/apple/swift/issues/55700 +// Availability checking not working in the 'where' clause of a 'for' loop tuplify(true) { b in for x in [b] where unavailableFunc(x) { // expected-error {{'unavailableFunc' is unavailable}} "" diff --git a/test/decl/var/usage.swift b/test/decl/var/usage.swift index ba79bd1a31350..922b75a33e0ab 100644 --- a/test/decl/var/usage.swift +++ b/test/decl/var/usage.swift @@ -330,7 +330,9 @@ func test(_ a : Int?, b : Any) { if let x = b as? Int { // expected-warning {{value 'x' was defined but never used; consider replacing with boolean test}} {{6-14=}} {{16-19=is}} } - // SR-14646. Special case, turn this into an 'is' test with optional value. + // Special case, turn these into an 'is' test with optional value. + // https://github.com/apple/swift/issues/56998 + let bb: Any? = 3 if let bbb = bb as? Int {} // expected-warning {{value 'bbb' was defined but never used; consider replacing with boolean test}} {{6-16=}} {{19-22=is}} if let bbb = (bb) as? Int {} // expected-warning {{value 'bbb' was defined but never used; consider replacing with boolean test}} {{6-16=}} {{21-24=is}} @@ -367,7 +369,8 @@ func test(_ a : Int?, b : Any) { let cc: (Any?, Any) = (1, 2) if let (cc1, cc2) = cc as? (Int, Int) {} // expected-warning {{immutable value 'cc1' was never used; consider replacing with '_' or removing it}} expected-warning {{immutable value 'cc2' was never used; consider replacing with '_' or removing it}} - // SR-1112 + // https://github.com/apple/swift/issues/43725 + let xxx: Int? = 0 if let yyy = xxx { } // expected-warning{{with boolean test}} {{6-16=}} {{19-19= != nil}} @@ -404,14 +407,14 @@ for i in 0..<10 { // expected-warning {{immutable value 'i' was never used; cons print("") } -// Tests fix to SR-2421 -func sr2421() { +// https://github.com/apple/swift/issues/45026 +do { let x: Int // expected-warning {{immutable value 'x' was never used; consider removing it}} x = 42 } -// Tests fix to SR-964 -func sr964() { +// Thttps://github.com/apple/swift/issues/43576 +do { var noOpSetter: String { get { return "" } set { } // No warning @@ -540,7 +543,8 @@ func testVariablesBoundInPatterns() { break } } -// Tests fix to SR-14646 + +// https://github.com/apple/swift/issues/56998 func testUselessCastWithInvalidParam(foo: Any?) -> Int { class Foo { } if let bar = foo as? Foo { return 42 } // expected-warning {{value 'bar' was defined but never used; consider replacing with boolean test}} {{6-16=}} {{20-23=is}} diff --git a/test/decl/var/variables.swift b/test/decl/var/variables.swift index be6a5bd5ee9e0..7c373ce9b0843 100644 --- a/test/decl/var/variables.swift +++ b/test/decl/var/variables.swift @@ -73,7 +73,9 @@ func testAnyObjectOptional() -> AnyObject? { return x } -// SR-11511 Warning for inferring an array of empty tuples +// https://github.com/apple/swift/issues/53912 +// Warning for inferring an array of empty tuples + var arrayOfEmptyTuples = [""].map { print($0) } // expected-warning {{variable 'arrayOfEmptyTuples' inferred to have type '[()]'}} \ // expected-note {{add an explicit type annotation to silence this warning}} {{23-23=: [()]}} From 0c35771b723b64815d71e5b048d5c7125253d6eb Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Tue, 23 Aug 2022 14:43:44 +0100 Subject: [PATCH 402/491] [cxx-interop] Emit `-enable-experimental-cxx-interop` flag into the module interface This makes sure that when Swift is generating a `.swiftinterface` file for a Swift module with a dependency on C++ module, `-enable-experimental-cxx-interop` is emitted under `// swift-module-flags:`. The module interface might refer to C++ symbols which are not available in Swift without C++ interop enabled. This caused a build error for Swift LLVM bindings during `verify-module-interface` stage: Swift tried to import the module interface and couldn't find C++ stdlib headers because C++ interop was disabled. --- include/swift/Option/Options.td | 2 +- test/Interop/Cxx/modules/Inputs/module.modulemap | 2 +- .../Cxx/modules/Inputs/namespace-extension-lib.swift | 2 +- test/Interop/Cxx/modules/emit-module-interface.swift | 9 +++++++++ .../Cxx/modules/use-namespace-extension-lib.swift | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 test/Interop/Cxx/modules/emit-module-interface.swift diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 3e6901c488c0b..83068c859969b 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -614,7 +614,7 @@ def enable_experimental_concise_pound_file : Flag<["-"], def enable_experimental_cxx_interop : Flag<["-"], "enable-experimental-cxx-interop">, - Flags<[FrontendOption, HelpHidden]>, + Flags<[FrontendOption, HelpHidden, ModuleInterfaceOption]>, HelpText<"Enable experimental C++ interop code generation and config directives">; def experimental_cxx_stdlib : diff --git a/test/Interop/Cxx/modules/Inputs/module.modulemap b/test/Interop/Cxx/modules/Inputs/module.modulemap index 99dc27ee62eeb..43533ccd3ee96 100644 --- a/test/Interop/Cxx/modules/Inputs/module.modulemap +++ b/test/Interop/Cxx/modules/Inputs/module.modulemap @@ -1,4 +1,4 @@ -module Namespace { +module Namespaces { header "namespace.h" requires cplusplus } diff --git a/test/Interop/Cxx/modules/Inputs/namespace-extension-lib.swift b/test/Interop/Cxx/modules/Inputs/namespace-extension-lib.swift index 78045e6effe12..8369220b04a26 100644 --- a/test/Interop/Cxx/modules/Inputs/namespace-extension-lib.swift +++ b/test/Interop/Cxx/modules/Inputs/namespace-extension-lib.swift @@ -1,4 +1,4 @@ -import Namespace +import Namespaces extension Namespace.Parent { public static func test() -> Int { 42 } diff --git a/test/Interop/Cxx/modules/emit-module-interface.swift b/test/Interop/Cxx/modules/emit-module-interface.swift new file mode 100644 index 0000000000000..8a9046f03c93f --- /dev/null +++ b/test/Interop/Cxx/modules/emit-module-interface.swift @@ -0,0 +1,9 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-emit-module-interface(%t/UsesCxxStruct.swiftinterface) %s -I %S/Inputs -enable-library-evolution -swift-version 5 -enable-experimental-cxx-interop %S/Inputs/namespace-extension-lib.swift +// RUN: %target-swift-typecheck-module-from-interface(%t/UsesCxxStruct.swiftinterface) -I %S/Inputs +// RUN: %FileCheck --input-file=%t/UsesCxxStruct.swiftinterface %s +// CHECK: -enable-experimental-cxx-interop + +import Namespaces + +var x: Namespace.Parent? = nil diff --git a/test/Interop/Cxx/modules/use-namespace-extension-lib.swift b/test/Interop/Cxx/modules/use-namespace-extension-lib.swift index 623d6fba2756e..7e3cccb8a055d 100644 --- a/test/Interop/Cxx/modules/use-namespace-extension-lib.swift +++ b/test/Interop/Cxx/modules/use-namespace-extension-lib.swift @@ -9,7 +9,7 @@ // XFAIL: OS=windows-msvc import StdlibUnittest -import Namespace +import Namespaces import NamespaceExtensionLib var NamespacesTestSuite = TestSuite("Extension in library on namespace") From e090bc492a414b61bb5b6e0d4ac5796553ebf6ce Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 26 Aug 2022 17:49:02 +0200 Subject: [PATCH 403/491] PassManager: cleanup the analysis-invalidation mechanism for swift passes This fixes a bug with module passes. --- .../SILOptimizer/PassManager/PassManager.h | 28 ++++--------- lib/SILOptimizer/PassManager/PassManager.cpp | 40 +++++++++++++------ 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/include/swift/SILOptimizer/PassManager/PassManager.h b/include/swift/SILOptimizer/PassManager/PassManager.h index 9889d30f3f28f..959f4a9dab2eb 100644 --- a/include/swift/SILOptimizer/PassManager/PassManager.h +++ b/include/swift/SILOptimizer/PassManager/PassManager.h @@ -61,6 +61,10 @@ class SwiftPassInvocation { /// Non-null if this is an instruction pass, invoked from SILCombine. SILCombiner *silCombiner = nullptr; + /// Change notifications, collected during a pass run. + SILAnalysis::InvalidationKind changeNotifications = + SILAnalysis::InvalidationKind::Nothing; + /// All slabs, allocated by the pass. SILModule::SlabList allocatedSlabs; @@ -126,17 +130,9 @@ class SwiftPassInvocation { /// Called by the SILCombiner when the instruction pass has finished. void finishedInstructionPassRun(); - void beginTransformFunction(SILFunction *function) { - assert(!this->function && transform && "not running a module pass"); - this->function = function; - } + void beginTransformFunction(SILFunction *function); - void endTransformFunction() { - assert(function && "beginTransformFunction not called"); - function = nullptr; - assert(numBlockSetsAllocated == 0 && "Not all BasicBlockSets deallocated"); - assert(numNodeSetsAllocated == 0 && "Not all NodeSets deallocated"); - } + void endTransformFunction(); }; /// The SIL pass manager. @@ -184,10 +180,6 @@ class SILPassManager { /// For invoking Swift passes. SwiftPassInvocation swiftPassInvocation; - /// Change notifications, collected during a bridged pass run. - SILAnalysis::InvalidationKind changeNotifications = - SILAnalysis::InvalidationKind::Nothing; - /// A mask which has one bit for each pass. A one for a pass-bit means that /// the pass doesn't need to run, because nothing has changed since the /// previous run of that pass. @@ -341,11 +333,6 @@ class SILPassManager { CompletedPassesMap[F].reset(); } - void notifyPassChanges(SILAnalysis::InvalidationKind invalidationKind) { - changeNotifications = (SILAnalysis::InvalidationKind) - (changeNotifications | invalidationKind); - } - /// Reset the state of the pass manager and remove all transformation /// owned by the pass manager. Analysis passes will be kept. void resetAndRemoveTransformations(); @@ -440,7 +427,8 @@ class SILPassManager { inline void SwiftPassInvocation:: notifyChanges(SILAnalysis::InvalidationKind invalidationKind) { - passManager->notifyPassChanges(invalidationKind); + changeNotifications = (SILAnalysis::InvalidationKind) + (changeNotifications | invalidationKind); } } // end namespace swift diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index 47a1a3225d4e2..df5e1a5356171 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -530,9 +530,6 @@ void SILPassManager::runPassOnFunction(unsigned TransIdx, SILFunction *F) { forcePrecomputeAnalyses(F); } - assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing - && "change notifications not cleared"); - llvm::sys::TimePoint<> startTime = std::chrono::system_clock::now(); std::chrono::nanoseconds duration(0); @@ -553,24 +550,21 @@ void SILPassManager::runPassOnFunction(unsigned TransIdx, SILFunction *F) { // Run it! SFT->run(); - if (CurrentPassHasInvalidated || - changeNotifications != SILAnalysis::InvalidationKind::Nothing) { + swiftPassInvocation.finishedFunctionPassRun(); + + if (CurrentPassHasInvalidated) { // Pause time measurement while invalidating analysis and restoring the snapshot. duration += (std::chrono::system_clock::now() - startTime); if (runIdx < numRepeats - 1) { invalidateAnalysis(F, SILAnalysis::InvalidationKind::Everything); F->restoreFromSnapshot(SnapshotID); - } else if (changeNotifications != SILAnalysis::InvalidationKind::Nothing) { - invalidateAnalysis(F, changeNotifications); } - changeNotifications = SILAnalysis::InvalidationKind::Nothing; // Continue time measurement (including flushing deleted instructions). startTime = std::chrono::system_clock::now(); } Mod->flushDeletedInsts(); - swiftPassInvocation.finishedFunctionPassRun(); } duration += (std::chrono::system_clock::now() - startTime); @@ -1289,9 +1283,9 @@ void SwiftPassInvocation::startModulePassRun(SILModuleTransform *transform) { } void SwiftPassInvocation::startFunctionPassRun(SILFunctionTransform *transform) { - assert(!this->function && !this->transform && "a pass is already running"); - this->function = transform->getFunction(); + assert(!this->transform && "a pass is already running"); this->transform = transform; + beginTransformFunction(transform->getFunction()); } void SwiftPassInvocation::startInstructionPassRun(SILInstruction *inst) { @@ -1302,13 +1296,15 @@ void SwiftPassInvocation::startInstructionPassRun(SILInstruction *inst) { void SwiftPassInvocation::finishedModulePassRun() { endPassRunChecks(); assert(!function && transform && "not running a pass"); + assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing + && "unhandled change notifications at end of module pass"); transform = nullptr; } void SwiftPassInvocation::finishedFunctionPassRun() { endPassRunChecks(); - assert(function && transform && "not running a pass"); - function = nullptr; + endTransformFunction(); + assert(allocatedSlabs.empty() && "StackList is leaking slabs"); transform = nullptr; } @@ -1322,6 +1318,24 @@ void SwiftPassInvocation::endPassRunChecks() { assert(numNodeSetsAllocated == 0 && "Not all NodeSets deallocated"); } +void SwiftPassInvocation::beginTransformFunction(SILFunction *function) { + assert(!this->function && transform && "not running a pass"); + assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing + && "change notifications not cleared"); + this->function = function; +} + +void SwiftPassInvocation::endTransformFunction() { + assert(function && transform && "not running a pass"); + if (changeNotifications != SILAnalysis::InvalidationKind::Nothing) { + passManager->invalidateAnalysis(function, changeNotifications); + changeNotifications = SILAnalysis::InvalidationKind::Nothing; + } + function = nullptr; + assert(numBlockSetsAllocated == 0 && "Not all BasicBlockSets deallocated"); + assert(numNodeSetsAllocated == 0 && "Not all NodeSets deallocated"); +} + //===----------------------------------------------------------------------===// // Swift Bridging //===----------------------------------------------------------------------===// From 2745565a839b8f64387c0ba51f56ef249f87079d Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 26 Aug 2022 17:54:43 +0200 Subject: [PATCH 404/491] Swift SIL: correctly bridge "invalid" witness table entries. Originally, I thought that couldn't appear in valid SIL, but there are "no_default" entries in default witness tables, which map to "invalid" entries. --- .../Sources/SIL/WitnessTable.swift | 2 ++ include/swift/SIL/SILBridging.h | 1 + lib/SIL/Utils/SILBridging.cpp | 4 +-- test/SILOptimizer/function_uses.sil | 26 +++++++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/SwiftCompilerSources/Sources/SIL/WitnessTable.swift b/SwiftCompilerSources/Sources/SIL/WitnessTable.swift index 3d110c9908f2f..8cf16dc04effe 100644 --- a/SwiftCompilerSources/Sources/SIL/WitnessTable.swift +++ b/SwiftCompilerSources/Sources/SIL/WitnessTable.swift @@ -21,6 +21,7 @@ public struct WitnessTable : CustomStringConvertible, CustomReflectable { fileprivate let bridged: BridgedWitnessTableEntry public enum Kind { + case invalid case method case associatedType case associatedTypeProtocol @@ -29,6 +30,7 @@ public struct WitnessTable : CustomStringConvertible, CustomReflectable { public var kind: Kind { switch SILWitnessTableEntry_getKind(bridged) { + case SILWitnessTableEntry_Invalid: return .invalid case SILWitnessTableEntry_Method: return .method case SILWitnessTableEntry_AssociatedType: return .associatedType case SILWitnessTableEntry_AssociatedTypeProtocol: return .associatedTypeProtocol diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index a24c6a2443ef8..2ea36bcf2fa57 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -99,6 +99,7 @@ typedef struct { } BridgedWitnessTableEntry; typedef enum { + SILWitnessTableEntry_Invalid, SILWitnessTableEntry_Method, SILWitnessTableEntry_AssociatedType, SILWitnessTableEntry_AssociatedTypeProtocol, diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index 04c76f34c522b..2d471558e3e1f 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -625,6 +625,8 @@ std::string SILWitnessTableEntry_debugDescription(BridgedWitnessTableEntry entry SILWitnessTableEntryKind SILWitnessTableEntry_getKind(BridgedWitnessTableEntry entry) { switch (castToWitnessTableEntry(entry)->getKind()) { + case SILWitnessTable::Invalid: + return SILWitnessTableEntry_Invalid; case SILWitnessTable::Method: return SILWitnessTableEntry_Method; case SILWitnessTable::AssociatedType: @@ -633,8 +635,6 @@ SILWitnessTableEntryKind SILWitnessTableEntry_getKind(BridgedWitnessTableEntry e return SILWitnessTableEntry_AssociatedTypeProtocol; case SILWitnessTable::BaseProtocol: return SILWitnessTableEntry_BaseProtocol; - default: - llvm_unreachable("wrong witness table entry kind"); } } diff --git a/test/SILOptimizer/function_uses.sil b/test/SILOptimizer/function_uses.sil index d176e59199ad5..48110a6df0d41 100644 --- a/test/SILOptimizer/function_uses.sil +++ b/test/SILOptimizer/function_uses.sil @@ -153,12 +153,26 @@ sil_default_witness_table RP { method #RP.default_witness: @default_witness } +public protocol RP2 { +} + +sil_default_witness_table RP2 { + no_default +} + protocol P { func witness() + func witness2() } struct SP : P { func witness() + func witness2() +} + +struct SP2 : P { + func witness() + func witness2() } // CHECK-LABEL: Uses of witness @@ -172,8 +186,20 @@ bb0(%0 : $*SP): return %7 : $() } +sil @witness2 : $@convention(witness_method: P) (@inout SP) -> () { +bb0(%0 : $*SP): + %7 = tuple () + return %7 : $() +} + sil_witness_table SP: P module witness_tables { method #P.witness: @witness + method #P.witness2: @witness2 +} + +sil_witness_table SP2: P module witness_tables { + method #P.witness: @witness + method #P.witness2: @witness2 } // CHECK-LABEL: Uses of hash_func From f6e6b2ecf3efb0db736cb6308905aa56b4124ab3 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 26 Aug 2022 17:56:35 +0200 Subject: [PATCH 405/491] Swift SIL: add the possibility to pass a custom location to `Builder` initializers. And add the static property `Location.autoGeneratedLocation` --- .../Optimizer/PassManager/PassContext.swift | 19 +++++++++++++++---- .../Sources/SIL/Location.swift | 4 ++++ include/swift/SIL/SILBridging.h | 2 ++ lib/SIL/Utils/SILBridging.cpp | 9 +++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassContext.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassContext.swift index da1520e30d717..fe62576bce1db 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassContext.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassContext.swift @@ -157,20 +157,31 @@ extension Builder { self.init(insertAt: .before(insPnt), location: insPnt.location, passContext: context._bridged) } - /// Creates a builder which inserts _after_ `insPnt`, using the location of `insPnt`. - init(after insPnt: Instruction, _ context: PassContext) { + /// Creates a builder which inserts _after_ `insPnt`, using a custom `location`. + init(after insPnt: Instruction, location: Location, _ context: PassContext) { if let nextInst = insPnt.next { - self.init(insertAt: .before(nextInst), location: insPnt.location, passContext: context._bridged) + self.init(insertAt: .before(nextInst), location: location, passContext: context._bridged) } else { - self.init(insertAt: .atEndOf(insPnt.block), location: insPnt.location, passContext: context._bridged) + self.init(insertAt: .atEndOf(insPnt.block), location: location, passContext: context._bridged) } } + /// Creates a builder which inserts _after_ `insPnt`, using the location of `insPnt`. + init(after insPnt: Instruction, _ context: PassContext) { + self.init(after: insPnt, location: insPnt.location, context) + } + /// Creates a builder which inserts at the end of `block`, using a custom `location`. init(atEndOf block: BasicBlock, location: Location, _ context: PassContext) { self.init(insertAt: .atEndOf(block), location: location, passContext: context._bridged) } + /// Creates a builder which inserts at the begin of `block`, using a custom `location`. + init(atBeginOf block: BasicBlock, location: Location, _ context: PassContext) { + let firstInst = block.instructions.first! + self.init(insertAt: .before(firstInst), location: location, passContext: context._bridged) + } + /// Creates a builder which inserts at the begin of `block`, using the location of the first /// instruction of `block`. init(atBeginOf block: BasicBlock, _ context: PassContext) { diff --git a/SwiftCompilerSources/Sources/SIL/Location.swift b/SwiftCompilerSources/Sources/SIL/Location.swift index 875d84d1f84d4..64f22641a0fe9 100644 --- a/SwiftCompilerSources/Sources/SIL/Location.swift +++ b/SwiftCompilerSources/Sources/SIL/Location.swift @@ -14,4 +14,8 @@ import SILBridging public struct Location { let bridged: BridgedLocation + + public static var autoGeneratedLocation: Location { + Location(bridged: SILLocation_getAutogeneratedLocation()) + } } diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index 2ea36bcf2fa57..fc07b77678c7d 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -334,6 +334,8 @@ SwiftInt SILType_getCaseIdxOfEnumType(BridgedType type, BridgedSubstitutionMap SubstitutionMap_getEmpty(); +BridgedLocation SILLocation_getAutogeneratedLocation(); + BridgedBasicBlock SILArgument_getParent(BridgedArgument argument); SwiftInt SILArgument_isExclusiveIndirectParameter(BridgedArgument argument); diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index 2d471558e3e1f..4e14490491856 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -529,6 +529,15 @@ BridgedSubstitutionMap SubstitutionMap_getEmpty() { return {SubstitutionMap().getOpaqueValue()}; } +//===----------------------------------------------------------------------===// +// SILLocation +//===----------------------------------------------------------------------===// + +BridgedLocation SILLocation_getAutogeneratedLocation() { + SILDebugLocation loc; + return *reinterpret_cast(&loc); +} + //===----------------------------------------------------------------------===// // SILGlobalVariable //===----------------------------------------------------------------------===// From f7aaa350920d85af27a05753862211b12ee57625 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 26 Aug 2022 17:57:59 +0200 Subject: [PATCH 406/491] Swift SIL: fix `KeyPathInst.visitReferencedFunctions` It crashed for keypath instructions with zero components. --- SwiftCompilerSources/Sources/SIL/Instruction.swift | 7 +++---- include/swift/SIL/SILBridging.h | 3 ++- lib/SIL/Utils/SILBridging.cpp | 12 ++++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/SwiftCompilerSources/Sources/SIL/Instruction.swift b/SwiftCompilerSources/Sources/SIL/Instruction.swift index b33ec1f2cdc63..9dca3c8afd9c7 100644 --- a/SwiftCompilerSources/Sources/SIL/Instruction.swift +++ b/SwiftCompilerSources/Sources/SIL/Instruction.swift @@ -480,9 +480,8 @@ final public class RefTailAddrInst : SingleValueInstruction, UnaryInstruction {} final public class KeyPathInst : SingleValueInstruction { public override func visitReferencedFunctions(_ cl: (Function) -> ()) { var results = KeyPathFunctionResults() - var componentIdx = 0 - repeat { - componentIdx = KeyPathInst_getReferencedFunctions(bridged, componentIdx, &results) + for componentIdx in 0..= 0 + } } } diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index fc07b77678c7d..6e540b94d5c4a 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -399,7 +399,8 @@ struct KeyPathFunctionResults { BridgedFunction functions[maxFunctions]; SwiftInt numFunctions; }; -SwiftInt KeyPathInst_getReferencedFunctions(BridgedInstruction kpi, SwiftInt componentIdx, +SwiftInt KeyPathInst_getNumComponents(BridgedInstruction kpi); +void KeyPathInst_getReferencedFunctions(BridgedInstruction kpi, SwiftInt componentIdx, KeyPathFunctionResults * _Nonnull results); BridgedSubstitutionMap ApplySite_getSubstitutionMap(BridgedInstruction inst); diff --git a/lib/SIL/Utils/SILBridging.cpp b/lib/SIL/Utils/SILBridging.cpp index 4e14490491856..14c3a9998a698 100644 --- a/lib/SIL/Utils/SILBridging.cpp +++ b/lib/SIL/Utils/SILBridging.cpp @@ -886,7 +886,14 @@ SwiftInt CondBranchInst_getNumTrueArgs(BridgedInstruction cbr) { return castToInst(cbr)->getNumTrueArgs(); } -SwiftInt KeyPathInst_getReferencedFunctions(BridgedInstruction kpi, SwiftInt componentIdx, +SwiftInt KeyPathInst_getNumComponents(BridgedInstruction kpi) { + if (KeyPathPattern *pattern = castToInst(kpi)->getPattern()) { + return (SwiftInt)pattern->getComponents().size(); + } + return 0; +} + +void KeyPathInst_getReferencedFunctions(BridgedInstruction kpi, SwiftInt componentIdx, KeyPathFunctionResults * _Nonnull results) { KeyPathPattern *pattern = castToInst(kpi)->getPattern(); const KeyPathPatternComponent &comp = pattern->getComponents()[componentIdx]; @@ -896,9 +903,6 @@ SwiftInt KeyPathInst_getReferencedFunctions(BridgedInstruction kpi, SwiftInt com assert(results->numFunctions < KeyPathFunctionResults::maxFunctions); results->functions[results->numFunctions++] = {func}; }, [](SILDeclRef) {}); - - ++componentIdx; - return componentIdx < (int)pattern->getComponents().size() ? componentIdx : -1; } BridgedSubstitutionMap ApplySite_getSubstitutionMap(BridgedInstruction inst) { From c8a7e55f6af916890c488859d0e7ed5920ac1eb7 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 25 Aug 2022 13:02:51 +0200 Subject: [PATCH 407/491] [SourceKit] Workaround a bug that parameterized protocols without 'any' cannot be mangled `typealias` is currently allowed to refer to a protocol without the `any` keyword. This breaks mangling the typealias type into a USR will crash because parameterized protocols are expected to be `any` types. Implement a SourceKit-specific minimal workaround for that problem by not computing USRs for parameterized protocols. rdar://98623438 --- lib/IDE/CodeCompletionResultType.cpp | 10 +++++++ ...type_alias_to_parameterized_protocol.swift | 30 +++++++++++++++++++ ...type_alias_to_parameterized_protocol.swift | 13 ++++++++ .../lib/SwiftLang/SwiftSourceDocInfo.cpp | 16 ++++++++++ 4 files changed, 69 insertions(+) create mode 100644 test/IDE/complete_from_module_with_type_alias_to_parameterized_protocol.swift create mode 100644 test/SourceKit/CursorInfo/cursor_from_module_with_type_alias_to_parameterized_protocol.swift diff --git a/lib/IDE/CodeCompletionResultType.cpp b/lib/IDE/CodeCompletionResultType.cpp index 908e2b8fac58f..6cbc92de34849 100644 --- a/lib/IDE/CodeCompletionResultType.cpp +++ b/lib/IDE/CodeCompletionResultType.cpp @@ -195,6 +195,16 @@ const USRBasedType *USRBasedType::fromType(Type Ty, USRBasedTypeArena &Arena) { return USRBasedType::null(Arena); } + // ParameterizedProtocolType should always be wrapped in ExistentialType and + // cannot be mangled on its own. + // But ParameterizedProtocolType can currently occur in 'typealias' + // declarations. rdar://99176683 + // To avoid crashing in USR generation, simply return a null type until the + // underlying issue has been fixed. + if (Ty->is()) { + return USRBasedType::null(Arena); + } + SmallString<32> USR; llvm::raw_svector_ostream OS(USR); printTypeUSR(Ty, OS); diff --git a/test/IDE/complete_from_module_with_type_alias_to_parameterized_protocol.swift b/test/IDE/complete_from_module_with_type_alias_to_parameterized_protocol.swift new file mode 100644 index 0000000000000..fc1e5146dad02 --- /dev/null +++ b/test/IDE/complete_from_module_with_type_alias_to_parameterized_protocol.swift @@ -0,0 +1,30 @@ +// RUN: %empty-directory(%t/split) +// RUN: %empty-directory(%t/build) +// RUN: %{python} %utils/split_file.py -o %t/split %s + +// RUN: %target-swift-frontend -emit-module -o %t/build %t/split/pck.swift + +// RUN: %target-swift-ide-test -code-completion -source-filename %t/split/test.swift -I %t/build -code-completion-token=COMPLETE | %FileCheck %s + +// BEGIN pck.swift + +public protocol Foo { + associatedtype Bar +} + +public typealias Problem = Foo + +public protocol EmptyProto {} +public typealias ConstrainedBar = Foo + +// BEGIN test.swift + +import pck + +#^COMPLETE^# + +// CHECK: Begin completions +// CHECK-DAG: Decl[Protocol]/OtherModule[pck]/Flair[RareType]: Foo[#Foo#]; +// CHECK-DAG: Decl[TypeAlias]/OtherModule[pck]: Problem[#Foo#]; +// CHECK-DAG: Decl[TypeAlias]/OtherModule[pck]: ConstrainedBar[#Foo#]; +// CHECK: End completions diff --git a/test/SourceKit/CursorInfo/cursor_from_module_with_type_alias_to_parameterized_protocol.swift b/test/SourceKit/CursorInfo/cursor_from_module_with_type_alias_to_parameterized_protocol.swift new file mode 100644 index 0000000000000..a85beb334e1f2 --- /dev/null +++ b/test/SourceKit/CursorInfo/cursor_from_module_with_type_alias_to_parameterized_protocol.swift @@ -0,0 +1,13 @@ +// Testing that these requests don't crash + +public protocol Foo { + associatedtype Bar +} +// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):11 %s -- %s +typealias Problem = Foo + +protocol EmptyProto {} +// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):11 %s -- %s +typealias ConstrainedBar = Foo +// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):11 %s -- %s +typealias ConstrainedBarMetatype = Foo.Type diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp index 6adf5eedd1444..c9929d579f0d9 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp @@ -948,6 +948,22 @@ fillSymbolInfo(CursorSymbolInfo &Symbol, const DeclInfo &DInfo, } Symbol.TypeName = copyAndClearString(Allocator, Buffer); + // ParameterizedProtocolType should always be wrapped in ExistentialType and + // cannot be mangled on its own. + // But ParameterizedProtocolType can currently occur in 'typealias' + // declarations. rdar://99176683 + // To avoid crashing in USR generation, return an error for now. + if (auto Ty = DInfo.VD->getInterfaceType()) { + while (auto MetaTy = Ty->getAs()) { + Ty = MetaTy->getInstanceType(); + } + if (Ty && Ty->getCanonicalType()->is()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Cannot mangle USR for ParameterizedProtocolType without 'any'."); + } + } + SwiftLangSupport::printDeclTypeUSR(DInfo.VD, OS); Symbol.TypeUSR = copyAndClearString(Allocator, Buffer); From 9fcd2029180cfad3dad4d03951b75bcafa253f1e Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Thu, 25 Aug 2022 16:04:50 -0700 Subject: [PATCH 408/491] [Dependency Scanning] Do not add underlying Clang moduel to persistent (global) scanner cache When we are building a Swift module which has an underlying Clang module, and which generates an ObjC interface ('-Swift.h'), the mechanism for building the latter involves a VFS redirect of its modulemap to one that does not yet have the generated Swift code, because it must be built before the Swift portion is built because the Swift portion depends on it. This means that the invocation to build this module is different to one used by the clients which depend on this module. To avoid the subsequent client scans from re-using the partial (VFS-redirected) module, ensure that we do not store dependency info of the underlying Clang module into the global scanner cache. This will cause subsequent client scans to re-scan for this module, and find the fully-resolved modulemap without a VFS redirect. Resolves rdar://88309064 --- include/swift/AST/ModuleDependencies.h | 12 +++++- lib/AST/ModuleDependencies.cpp | 23 +++++++++--- lib/DependencyScan/DependencyScanningTool.cpp | 6 ++- lib/DependencyScan/ScanDependencies.cpp | 37 +++++++++++-------- 4 files changed, 53 insertions(+), 25 deletions(-) diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index 3db6a218f0d4c..f9c22bcd9d424 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -610,6 +610,15 @@ class ModuleDependenciesCache { /// Additional information needed for Clang dependency scanning. ClangModuleDependenciesCacheImpl *clangImpl = nullptr; + /// Name of the main Swift module of this scan + StringRef mainModuleName; + /// Underlying Clang module is seen differently by the main + /// module and by module clients. For this reason, we do not wish subsequent + /// scans to be able to re-use this dependency info and therefore we avoid + /// adding it to the global cache. The dependency storage is therefore tied + /// to this, local, cache. + std::unique_ptr underlyingClangModuleDependency = nullptr; + /// Function that will delete \c clangImpl properly. void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *) = nullptr; @@ -638,7 +647,8 @@ class ModuleDependenciesCache { Optional kind) const; public: - ModuleDependenciesCache(GlobalModuleDependenciesCache &globalCache); + ModuleDependenciesCache(GlobalModuleDependenciesCache &globalCache, + StringRef mainModuleName); ModuleDependenciesCache(const ModuleDependenciesCache &) = delete; ModuleDependenciesCache &operator=(const ModuleDependenciesCache &) = delete; virtual ~ModuleDependenciesCache() { destroyClangImpl(); } diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 19ed8fd808878..39871f4e906af 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -517,8 +517,9 @@ ModuleDependenciesCache::getDependencyReferencesMap( } ModuleDependenciesCache::ModuleDependenciesCache( - GlobalModuleDependenciesCache &globalCache) - : globalCache(globalCache) { + GlobalModuleDependenciesCache &globalCache, + StringRef mainModuleName) + : globalCache(globalCache), mainModuleName(mainModuleName) { for (auto kind = ModuleDependenciesKind::FirstKind; kind != ModuleDependenciesKind::LastKind; ++kind) { ModuleDependenciesMap.insert( @@ -566,11 +567,21 @@ bool ModuleDependenciesCache::hasDependencies( void ModuleDependenciesCache::recordDependencies( StringRef moduleName, ModuleDependencies dependencies) { - auto globalDepPtr = globalCache.recordDependencies(moduleName, dependencies); - auto kind = globalDepPtr->getKind(); - auto &map = getDependencyReferencesMap(kind); + auto dependenciesKind = dependencies.getKind(); + + // The underlying Clang module needs to be cached in this invocation, + // but should not make it to the global cache since it will look slightly + // differently for clients of this module than it does for the module itself. + const ModuleDependencies* recordedDependencies; + if (moduleName == mainModuleName && dependencies.isClangModule()) { + underlyingClangModuleDependency = std::make_unique(std::move(dependencies)); + recordedDependencies = underlyingClangModuleDependency.get(); + } else + recordedDependencies = globalCache.recordDependencies(moduleName, dependencies); + + auto &map = getDependencyReferencesMap(dependenciesKind); assert(map.count(moduleName) == 0 && "Already added to map"); - map.insert({moduleName, globalDepPtr}); + map.insert({moduleName, recordedDependencies}); } void ModuleDependenciesCache::updateDependencies( diff --git a/lib/DependencyScan/DependencyScanningTool.cpp b/lib/DependencyScan/DependencyScanningTool.cpp index 563f0a7fa3634..f3571e0b73067 100644 --- a/lib/DependencyScan/DependencyScanningTool.cpp +++ b/lib/DependencyScan/DependencyScanningTool.cpp @@ -73,7 +73,8 @@ DependencyScanningTool::getDependencies( auto Instance = std::move(*InstanceOrErr); // Local scan cache instance, wrapping the shared global cache. - ModuleDependenciesCache cache(*SharedCache); + ModuleDependenciesCache cache(*SharedCache, + Instance->getMainModule()->getNameStr()); // Execute the scanning action, retrieving the in-memory result auto DependenciesOrErr = performModuleScan(*Instance.get(), cache); if (DependenciesOrErr.getError()) @@ -113,7 +114,8 @@ DependencyScanningTool::getDependencies( auto Instance = std::move(*InstanceOrErr); // Local scan cache instance, wrapping the shared global cache. - ModuleDependenciesCache cache(*SharedCache); + ModuleDependenciesCache cache(*SharedCache, + Instance->getMainModule()->getNameStr()); auto BatchScanResults = performBatchModuleScan( *Instance.get(), cache, VersionedPCMInstanceCacheCache.get(), Saver, BatchInput); diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index 15f99958cbb95..1f1662e0c2af0 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -1089,32 +1089,33 @@ forEachBatchEntry(CompilerInstance &invocationInstance, // Create a new instance by the arguments and save it in the map. auto newGlobalCache = std::make_unique(); - subInstanceMap->insert( - {entry.arguments, - std::make_tuple(std::make_unique(), - std::move(newGlobalCache), - std::make_unique(*newGlobalCache))}); + auto newInstance = std::make_unique(); - pInstance = std::get<0>((*subInstanceMap)[entry.arguments]).get(); - auto globalCache = std::get<1>((*subInstanceMap)[entry.arguments]).get(); - pCache = std::get<2>((*subInstanceMap)[entry.arguments]).get(); SmallVector args; llvm::cl::TokenizeGNUCommandLine(entry.arguments, saver, args); CompilerInvocation subInvoke = invoke; - pInstance->addDiagnosticConsumer(&FDC); + newInstance->addDiagnosticConsumer(&FDC); if (subInvoke.parseArgs(args, diags)) { invocationInstance.getDiags().diagnose( SourceLoc(), diag::scanner_arguments_invalid, entry.arguments); return true; } std::string InstanceSetupError; - if (pInstance->setup(subInvoke, InstanceSetupError)) { + if (newInstance->setup(subInvoke, InstanceSetupError)) { invocationInstance.getDiags().diagnose( SourceLoc(), diag::scanner_arguments_invalid, entry.arguments); return true; } - globalCache->configureForTriple(pInstance->getInvocation() - .getLangOptions().Target.str()); + newGlobalCache->configureForTriple( + newInstance->getInvocation().getLangOptions().Target.str()); + auto newLocalCache = std::make_unique( + *newGlobalCache, newInstance->getMainModule()->getNameStr()); + pInstance = newInstance.get(); + pCache = newLocalCache.get(); + subInstanceMap->insert( + {entry.arguments, + std::make_tuple(std::move(newInstance), std::move(newGlobalCache), + std::move(newLocalCache))}); } assert(pInstance); assert(pCache); @@ -1252,7 +1253,8 @@ bool swift::dependencies::scanDependencies(CompilerInstance &instance) { if (opts.ReuseDependencyScannerCache) deserializeDependencyCache(instance, globalCache); - ModuleDependenciesCache cache(globalCache); + ModuleDependenciesCache cache(globalCache, + instance.getMainModule()->getNameStr()); // Execute scan auto dependenciesOrErr = performModuleScan(instance, cache); @@ -1287,7 +1289,8 @@ bool swift::dependencies::prescanDependencies(CompilerInstance &instance) { GlobalModuleDependenciesCache singleUseGlobalCache; singleUseGlobalCache.configureForTriple(instance.getInvocation() .getLangOptions().Target.str()); - ModuleDependenciesCache cache(singleUseGlobalCache); + ModuleDependenciesCache cache(singleUseGlobalCache, + instance.getMainModule()->getNameStr()); if (out.has_error() || EC) { Context.Diags.diagnose(SourceLoc(), diag::error_opening_output, path, EC.message()); @@ -1318,7 +1321,8 @@ bool swift::dependencies::batchScanDependencies( GlobalModuleDependenciesCache singleUseGlobalCache; singleUseGlobalCache.configureForTriple(instance.getInvocation() .getLangOptions().Target.str()); - ModuleDependenciesCache cache(singleUseGlobalCache); + ModuleDependenciesCache cache(singleUseGlobalCache, + instance.getMainModule()->getNameStr()); (void)instance.getMainModule(); llvm::BumpPtrAllocator alloc; llvm::StringSaver saver(alloc); @@ -1353,7 +1357,8 @@ bool swift::dependencies::batchPrescanDependencies( GlobalModuleDependenciesCache singleUseGlobalCache; singleUseGlobalCache.configureForTriple(instance.getInvocation() .getLangOptions().Target.str()); - ModuleDependenciesCache cache(singleUseGlobalCache); + ModuleDependenciesCache cache(singleUseGlobalCache, + instance.getMainModule()->getNameStr()); (void)instance.getMainModule(); llvm::BumpPtrAllocator alloc; llvm::StringSaver saver(alloc); From 477461b89d03ce9ffe0b5fa5ab379d61cfe9673a Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 25 Aug 2022 20:27:15 -0700 Subject: [PATCH 409/491] [CopyProp] Don't extend lifetime over end_access. If there is a consuming use of the value inside an access scope, the lifetime should not be extended over the end_access instruction. --- .../Utils/CanonicalOSSALifetime.h | 5 ++ .../Utils/CanonicalOSSALifetime.cpp | 49 ++++++++++++--- test/SILOptimizer/copy_propagation.sil | 60 +++++++++++++++---- 3 files changed, 95 insertions(+), 19 deletions(-) diff --git a/include/swift/SILOptimizer/Utils/CanonicalOSSALifetime.h b/include/swift/SILOptimizer/Utils/CanonicalOSSALifetime.h index bf92aba9e95ad..7526d7ecb031d 100644 --- a/include/swift/SILOptimizer/Utils/CanonicalOSSALifetime.h +++ b/include/swift/SILOptimizer/Utils/CanonicalOSSALifetime.h @@ -298,6 +298,11 @@ class CanonicalizeOSSALifetime { /// ending". end_borrows do not end a liverange that may include owned copies. PrunedLiveness liveness; + /// The destroys of the value. These are not uses, but need to be recorded so + /// that we know when the last use in a consuming block is (without having to + /// repeatedly do use-def walks from destroys). + SmallPtrSet destroys; + /// remnantLiveOutBlocks are part of the original extended lifetime that are /// not in canonical pruned liveness. There is a path from a PrunedLiveness /// boundary to an original destroy that passes through a remnant block. diff --git a/lib/SILOptimizer/Utils/CanonicalOSSALifetime.cpp b/lib/SILOptimizer/Utils/CanonicalOSSALifetime.cpp index 40ec62793d9ae..3b634b9f194d1 100644 --- a/lib/SILOptimizer/Utils/CanonicalOSSALifetime.cpp +++ b/lib/SILOptimizer/Utils/CanonicalOSSALifetime.cpp @@ -162,8 +162,10 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() { liveness.updateForUse(user, /*lifetimeEnding*/ true); break; case OperandOwnership::DestroyingConsume: - // destroy_value does not force pruned liveness (but store etc. does). - if (!isa(user)) { + if (isa(user)) { + destroys.insert(user); + } else { + // destroy_value does not force pruned liveness (but store etc. does). liveness.updateForUse(user, /*lifetimeEnding*/ true); } recordConsumingUse(use); @@ -335,18 +337,33 @@ void CanonicalizeOSSALifetime::extendLivenessThroughOverlappingAccess() { bool changed = true; while (changed) { changed = false; - blockWorklist.initializeRange(consumingBlocks); - while (auto *bb = blockWorklist.pop()) { + // The blocks in which we may have to extend liveness over access scopes. + // + // It must be populated first so that we can test membership during the loop + // (see findLastConsume). + BasicBlockSetVector blocksToVisit(currentDef->getFunction()); + for (auto *block : consumingBlocks) { + blocksToVisit.insert(block); + } + for (auto iterator = blocksToVisit.begin(); iterator != blocksToVisit.end(); + ++iterator) { + auto *bb = *iterator; + // If the block isn't dead, then we won't need to extend liveness within + // any of its predecessors (though we may within it). + if (liveness.getBlockLiveness(bb) != PrunedLiveBlocks::Dead) + continue; + // Continue searching upward to find the pruned liveness boundary. + for (auto *predBB : bb->getPredecessorBlocks()) { + blocksToVisit.insert(predBB); + } + } + for (auto *bb : blocksToVisit) { auto blockLiveness = liveness.getBlockLiveness(bb); // Ignore blocks within pruned liveness. if (blockLiveness == PrunedLiveBlocks::LiveOut) { continue; } if (blockLiveness == PrunedLiveBlocks::Dead) { - // Continue searching upward to find the pruned liveness boundary. - for (auto *predBB : bb->getPredecessorBlocks()) { - blockWorklist.insert(predBB); - } // Otherwise, ignore dead blocks with no nonlocal end_access. if (!accessBlocks->containsNonLocalEndAccess(bb)) { continue; @@ -356,7 +373,23 @@ void CanonicalizeOSSALifetime::extendLivenessThroughOverlappingAccess() { // Find the latest partially overlapping access scope, if one exists: // use %def // pruned liveness ends here // end_access + + // Whether to look for the last consume in the block. + // + // We need to avoid extending liveness over end_accesses that occur after + // original liveness ended. + bool findLastConsume = + consumingBlocks.contains(bb) && + llvm::none_of(bb->getSuccessorBlocks(), [&](auto *successor) { + return blocksToVisit.contains(successor) && + liveness.getBlockLiveness(successor) == + PrunedLiveBlocks::Dead; + }); for (auto &inst : llvm::reverse(*bb)) { + if (findLastConsume) { + findLastConsume = !destroys.contains(&inst); + continue; + } // Stop at the latest use. An earlier end_access does not overlap. if (blockHasUse && liveness.isInterestingUser(&inst)) { break; diff --git a/test/SILOptimizer/copy_propagation.sil b/test/SILOptimizer/copy_propagation.sil index 611194d5de72c..a8872d6e96746 100644 --- a/test/SILOptimizer/copy_propagation.sil +++ b/test/SILOptimizer/copy_propagation.sil @@ -616,10 +616,6 @@ bb2: // Original Overlapping (unnecessarilly extends pruned liveness): // -// TODO: this copy could be avoided but is probably an unusual case, -// and sinking the destroy outside the access scope might help to -// optimize the access itself. -// // %def // begin_access // access scope unrelated to def // use %def // pruned liveness ends here @@ -627,13 +623,14 @@ bb2: // end_access // // CHECK-LABEL: sil [ossa] @testOriginalOverlapInLiveBlock : $@convention(thin) () -> () { -// CHECK: [[DEF:%.*]] = apply %{{.*}}() : $@convention(thin) () -> @owned AnyObject -// CHECK: begin_access -// CHECK: [[COPY:%.*]] = copy_value [[DEF]] : $AnyObject -// CHECK: store [[COPY]] to [init] %{{.*}} : $*AnyObject -// CHECK: end_access -// CHECK: destroy_value [[DEF]] : $AnyObject -// CHECK: br bb1 +// CHECK: [[DEF:%.*]] = apply %{{.*}}() : $@convention(thin) () -> @owned AnyObject +// CHECK: begin_access +// CHECK-OPT: store [[DEF]] to [init] %{{.*}} : $*AnyObject +// CHECK-ONONE: [[COPY:%[^,]+]] = copy_value [[DEF]] +// CHECK-ONONE: store [[COPY]] to [init] %{{.*}} : $*AnyObject +// CHECK-ONONE: destroy_value [[DEF]] +// CHECK: end_access +// CHECK: br bb1 // CHECK-LABEL: } // end sil function 'testOriginalOverlapInLiveBlock' sil [ossa] @testOriginalOverlapInLiveBlock : $@convention(thin) () -> () { bb0: @@ -901,3 +898,44 @@ exit: %retval = tuple () return %retval : $() } + +// CHECK-LABEL: sil [ossa] @dont_extend_beyond_nonoverlapping_end_access_after_store_in_consuming_block : {{.*}} { +// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C +// CHECK: [[COPY:%[^,]+]] = copy_value [[INSTANCE]] +// CHECK: begin_access +// CHECK-NOT: copy_value +// CHECK: store [[COPY]] to [init] {{%[^,]+}} +// CHECK-LABEL: } // end sil function 'dont_extend_beyond_nonoverlapping_end_access_after_store_in_consuming_block' +sil [ossa] @dont_extend_beyond_nonoverlapping_end_access_after_store_in_consuming_block : $@convention(thin) (@owned C) -> () { +bb0(%instance : @owned $C): + %addr = alloc_stack [lexical] $C, var + %borrow = begin_borrow %instance : $C + %copy = copy_value %borrow : $C + end_borrow %borrow : $C + destroy_value %instance : $C + %access = begin_access [static] [modify] %addr : $*C + store %copy to [init] %addr : $*C + end_access %access : $*C + destroy_addr %addr : $*C + dealloc_stack %addr : $*C + %retval = tuple() + return %retval : $() +} + +// CHECK-LABEL: sil [ossa] @dont_extend_beyond_nonoverlapping_endaccess_after_destroyvalue_in_consuming_block : $@convention(thin) () -> () { +// CHECK: begin_access +// CHECK: destroy_value +// CHECK: end_access +// CHECK-NOT: destroy_value +// CHECK-LABEL: } // end sil function 'dont_extend_beyond_nonoverlapping_endaccess_after_destroyvalue_in_consuming_block' +sil [ossa] @dont_extend_beyond_nonoverlapping_endaccess_after_destroyvalue_in_consuming_block : $@convention(thin) () -> () { + %instance = apply undef() : $@convention(thin) () -> @owned C + %addr = alloc_stack [lexical] $C, var + %access = begin_access [static] [modify] %addr : $*C + apply undef(%instance) : $@convention(thin) (@guaranteed C) -> () + destroy_value %instance : $C + end_access %access : $*C + dealloc_stack %addr : $*C + %retval = tuple() + return %retval : $() +} From dd1da22b1650a784f3cd21d85c1795c160829829 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 26 Aug 2022 19:45:02 +0100 Subject: [PATCH 410/491] [CS] Separate availability checking from `SupportedOps` cache Previously we would cache the result of the first query, with any further query of `ResultBuilder::supports` ignoring the `checkAvailability` parameter. Separate out the availability checking such that we compute the information up front, and adjust the result depending on `checkAvailability`. --- include/swift/Sema/ConstraintSystem.h | 31 ++++++++++++++- lib/Sema/BuilderTransform.cpp | 57 +++++++++++++++++---------- lib/Sema/TypeChecker.h | 14 ++++++- 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index d10165bc78848..a16b7c86bcf8f 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -107,6 +107,33 @@ enum class FreeTypeVariableBinding { UnresolvedType }; +/// Describes whether or not a result builder method is supported. +struct ResultBuilderOpSupport { + enum Classification { + Unsupported, + Unavailable, + Supported + }; + Classification Kind; + + ResultBuilderOpSupport(Classification Kind) : Kind(Kind) {} + + /// Returns whether or not the builder method is supported. If + /// \p requireAvailable is true, an unavailable method will be considered + /// unsupported. + bool isSupported(bool requireAvailable) const { + switch (Kind) { + case Unsupported: + return false; + case Unavailable: + return !requireAvailable; + case Supported: + return true; + } + llvm_unreachable("Unhandled case in switch!"); + } +}; + namespace constraints { struct ResultBuilder { @@ -115,7 +142,9 @@ struct ResultBuilder { /// An implicit variable that represents `Self` type of the result builder. VarDecl *BuilderSelf; Type BuilderType; - llvm::SmallDenseMap SupportedOps; + + /// Cache of supported result builder operations. + llvm::SmallDenseMap SupportedOps; Identifier BuildOptionalId; diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index e1d3ba18cce75..8bdd4ea0d2538 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -2770,11 +2770,22 @@ std::vector TypeChecker::findReturnStatements(AnyFunctionRef fn) { return precheck.getReturnStmts(); } -bool TypeChecker::typeSupportsBuilderOp( +ResultBuilderOpSupport TypeChecker::checkBuilderOpSupport( Type builderType, DeclContext *dc, Identifier fnName, - ArrayRef argLabels, SmallVectorImpl *allResults, - bool checkAvailability) { + ArrayRef argLabels, SmallVectorImpl *allResults) { + + auto isUnavailable = [&](Decl *D) -> bool { + if (AvailableAttr::isUnavailable(D)) + return true; + + auto loc = extractNearestSourceLoc(dc); + auto context = ExportContext::forFunctionBody(dc, loc); + return TypeChecker::checkDeclarationAvailability(D, context).hasValue(); + }; + bool foundMatch = false; + bool foundUnavailable = false; + SmallVector foundDecls; dc->lookupQualified( builderType, DeclNameRef(fnName), @@ -2793,17 +2804,12 @@ bool TypeChecker::typeSupportsBuilderOp( continue; } - // If we are checking availability, the candidate must have enough - // availability in the calling context. - if (checkAvailability) { - if (AvailableAttr::isUnavailable(func)) - continue; - if (TypeChecker::checkDeclarationAvailability( - func, ExportContext::forFunctionBody( - dc, extractNearestSourceLoc(dc)))) - continue; + // Check if the the candidate has a suitable availability for the + // calling context. + if (isUnavailable(func)) { + foundUnavailable = true; + continue; } - foundMatch = true; break; } @@ -2812,7 +2818,18 @@ bool TypeChecker::typeSupportsBuilderOp( if (allResults) allResults->append(foundDecls.begin(), foundDecls.end()); - return foundMatch; + if (!foundMatch) { + return foundUnavailable ? ResultBuilderOpSupport::Unavailable + : ResultBuilderOpSupport::Unsupported; + } + return ResultBuilderOpSupport::Supported; +} + +bool TypeChecker::typeSupportsBuilderOp( + Type builderType, DeclContext *dc, Identifier fnName, + ArrayRef argLabels, SmallVectorImpl *allResults) { + return checkBuilderOpSupport(builderType, dc, fnName, argLabels, allResults) + .isSupported(/*requireAvailable*/ false); } Type swift::inferResultBuilderComponentType(NominalTypeDecl *builder) { @@ -2976,13 +2993,13 @@ bool ResultBuilder::supports(Identifier fnBaseName, bool checkAvailability) { DeclName name(DC->getASTContext(), fnBaseName, argLabels); auto known = SupportedOps.find(name); - if (known != SupportedOps.end()) { - return known->second; - } + if (known != SupportedOps.end()) + return known->second.isSupported(checkAvailability); - return SupportedOps[name] = TypeChecker::typeSupportsBuilderOp( - BuilderType, DC, fnBaseName, argLabels, /*allResults*/ {}, - checkAvailability); + auto support = TypeChecker::checkBuilderOpSupport( + BuilderType, DC, fnBaseName, argLabels, /*allResults*/ {}); + SupportedOps.insert({name, support}); + return support.isSupported(checkAvailability); } Expr *ResultBuilder::buildCall(SourceLoc loc, Identifier fnName, diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index c577519e490e3..6e7f39ed85270 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -1234,10 +1234,20 @@ UnresolvedMemberExpr *getUnresolvedMemberChainBase(Expr *expr); /// Checks whether a result builder type has a well-formed result builder /// method with the given name. If provided and non-empty, the argument labels /// are verified against any candidates. +ResultBuilderOpSupport +checkBuilderOpSupport(Type builderType, DeclContext *dc, Identifier fnName, + ArrayRef argLabels = {}, + SmallVectorImpl *allResults = nullptr); + +/// Checks whether a result builder type has a well-formed result builder +/// method with the given name. If provided and non-empty, the argument labels +/// are verified against any candidates. +/// +/// This will return \c true even if the builder method is unavailable. Use +/// \c checkBuilderOpSupport if availability should be checked. bool typeSupportsBuilderOp(Type builderType, DeclContext *dc, Identifier fnName, ArrayRef argLabels = {}, - SmallVectorImpl *allResults = nullptr, - bool checkAvailability = false); + SmallVectorImpl *allResults = nullptr); /// Forces all changes specified by the module's access notes file to be /// applied to this declaration. It is safe to call this function more than From cebcbb07679250e467abcb81e92effdcad97d862 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 26 Aug 2022 19:45:03 +0100 Subject: [PATCH 411/491] [CS] Improve diagnostics when `buildPartialBlock` is unavailable If `buildBlock` is also unavailable, or the builder itself is unavailable, continue to solve using `buildPartialBlock` to get better diagnostics. This behavior technically differs from what is specified in SE-0348, but only affects the invalid case where no builder methods are available to use. In particular, this improves diagnostics for RegexComponentBuilder when the deployment target is too low. Previously we would try to solve using `buildBlock` (as `buildPartialBlock` is unavailable), but RegexComponentBuilder only defines `buildBlock` for the empty body case, leading to unhelpful diagnostics that ultimately preferred not to use the result builder at all. rdar://97533700 --- include/swift/Sema/ConstraintSystem.h | 7 +++ lib/Sema/BuilderTransform.cpp | 45 +++++++++++---- .../result_builder_availability.swift | 56 +++++++++++++++++++ .../Sema/regex_builder_unavailable.swift | 28 ++++++++++ 4 files changed, 124 insertions(+), 12 deletions(-) create mode 100644 test/StringProcessing/Sema/regex_builder_unavailable.swift diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index a16b7c86bcf8f..5a2b9bce4724d 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -172,6 +172,13 @@ struct ResultBuilder { bool supportsOptional() { return supports(getBuildOptionalId()); } + /// Checks whether the `buildPartialBlock` method is supported. + bool supportsBuildPartialBlock(bool checkAvailability); + + /// Checks whether the builder can use `buildPartialBlock` to combine + /// expressions, instead of `buildBlock`. + bool canUseBuildPartialBlock(); + Expr *buildCall(SourceLoc loc, Identifier fnName, ArrayRef argExprs, ArrayRef argLabels) const; diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index 8bdd4ea0d2538..6100e7d986250 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -432,12 +432,7 @@ class BuilderClosureVisitor // If the builder supports `buildPartialBlock(first:)` and // `buildPartialBlock(accumulated:next:)`, use this to combine // subexpressions pairwise. - if (!expressions.empty() && - builder.supports(ctx.Id_buildPartialBlock, {ctx.Id_first}, - /*checkAvailability*/ true) && - builder.supports(ctx.Id_buildPartialBlock, - {ctx.Id_accumulated, ctx.Id_next}, - /*checkAvailability*/ true)) { + if (!expressions.empty() && builder.canUseBuildPartialBlock()) { // NOTE: The current implementation uses one-way constraints in between // subexpressions. It's functionally equivalent to the following: // let v0 = Builder.buildPartialBlock(first: arg_0) @@ -1087,12 +1082,7 @@ class ResultBuilderTransform // If the builder supports `buildPartialBlock(first:)` and // `buildPartialBlock(accumulated:next:)`, use this to combine // sub-expressions pairwise. - if (!buildBlockArguments.empty() && - builder.supports(ctx.Id_buildPartialBlock, {ctx.Id_first}, - /*checkAvailability*/ true) && - builder.supports(ctx.Id_buildPartialBlock, - {ctx.Id_accumulated, ctx.Id_next}, - /*checkAvailability*/ true)) { + if (!buildBlockArguments.empty() && builder.canUseBuildPartialBlock()) { // let v0 = Builder.buildPartialBlock(first: arg_0) // let v1 = Builder.buildPartialBlock(accumulated: v0, next: arg_1) // ... @@ -2822,6 +2812,12 @@ ResultBuilderOpSupport TypeChecker::checkBuilderOpSupport( return foundUnavailable ? ResultBuilderOpSupport::Unavailable : ResultBuilderOpSupport::Unsupported; } + // If the builder type itself isn't available, don't consider any builder + // method available. + if (auto *D = builderType->getAnyNominal()) { + if (isUnavailable(D)) + return ResultBuilderOpSupport::Unavailable; + } return ResultBuilderOpSupport::Supported; } @@ -2988,6 +2984,31 @@ ResultBuilder::ResultBuilder(ConstraintSystem *CS, DeclContext *DC, } } +bool ResultBuilder::supportsBuildPartialBlock(bool checkAvailability) { + auto &ctx = DC->getASTContext(); + return supports(ctx.Id_buildPartialBlock, {ctx.Id_first}, + checkAvailability) && + supports(ctx.Id_buildPartialBlock, {ctx.Id_accumulated, ctx.Id_next}, + checkAvailability); +} + +bool ResultBuilder::canUseBuildPartialBlock() { + // If buildPartialBlock doesn't exist at all, we can't use it. + if (!supportsBuildPartialBlock(/*checkAvailability*/ false)) + return false; + + // If buildPartialBlock exists and is available, use it. + if (supportsBuildPartialBlock(/*checkAvailability*/ true)) + return true; + + // We have buildPartialBlock, but it is unavailable. We can however still + // use it if buildBlock is also unavailable. + auto &ctx = DC->getASTContext(); + return supports(ctx.Id_buildBlock) && + !supports(ctx.Id_buildBlock, /*labels*/ {}, + /*checkAvailability*/ true); +} + bool ResultBuilder::supports(Identifier fnBaseName, ArrayRef argLabels, bool checkAvailability) { diff --git a/test/Constraints/result_builder_availability.swift b/test/Constraints/result_builder_availability.swift index 314a7980c0bd5..0ed6c9ddb40d9 100644 --- a/test/Constraints/result_builder_availability.swift +++ b/test/Constraints/result_builder_availability.swift @@ -167,3 +167,59 @@ tuplifyWithAvailabilityErasure(true) { cond in globalFuncAvailableOn10_52() } } + +// rdar://97533700 – Make sure we can prefer an unavailable buildPartialBlock if +// buildBlock also isn't available. + +@resultBuilder +struct UnavailableBuildPartialBlock { + static func buildPartialBlock(first: Int) -> Int { 0 } + + @available(*, unavailable) + static func buildPartialBlock(accumulated: Int, next: Int) -> Int { 0 } + + static func buildBlock(_ x: Int...) -> Int { 0 } +} + +@UnavailableBuildPartialBlock +func testUnavailableBuildPartialBlock() -> Int { + // We can use buildBlock here. + 2 + 3 +} + +@resultBuilder +struct UnavailableBuildPartialBlockAndBuildBlock { + @available(*, unavailable) + static func buildPartialBlock(first: Int) -> Int { 0 } + // expected-note@-1 {{'buildPartialBlock(first:)' has been explicitly marked unavailable here}} + + static func buildPartialBlock(accumulated: Int, next: Int) -> Int { 0 } + + @available(*, unavailable) + static func buildBlock(_ x: Int...) -> Int { 0 } +} + +// We can still use buildPartialBlock here as both are unavailable. +@UnavailableBuildPartialBlockAndBuildBlock +func testUnavailableBuildPartialBlockAndBuildBlock() -> Int { + // expected-error@-1 {{'buildPartialBlock(first:)' is unavailable}} + 2 + 3 +} + +@available(*, unavailable) +@resultBuilder +struct UnavailableBuilderWithPartialBlock { // expected-note {{'UnavailableBuilderWithPartialBlock' has been explicitly marked unavailable here}} + @available(*, unavailable) + static func buildPartialBlock(first: String) -> Int { 0 } + static func buildPartialBlock(accumulated: Int, next: Int) -> Int { 0 } + static func buildBlock(_ x: Int...) -> Int { 0 } +} + +@UnavailableBuilderWithPartialBlock // expected-error {{'UnavailableBuilderWithPartialBlock' is unavailable}} +func testUnavailableBuilderWithPartialBlock() -> Int { + // The builder itself is unavailable, so we can still opt for buildPartialBlock. + 2 // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} + 3 +} diff --git a/test/StringProcessing/Sema/regex_builder_unavailable.swift b/test/StringProcessing/Sema/regex_builder_unavailable.swift new file mode 100644 index 0000000000000..89b40f9c518e7 --- /dev/null +++ b/test/StringProcessing/Sema/regex_builder_unavailable.swift @@ -0,0 +1,28 @@ +// RUN: %target-typecheck-verify-swift -enable-bare-slash-regex -target %target-cpu-apple-macosx12.0 + +// REQUIRES: OS=macosx + +import RegexBuilder + +// rdar://97533700 – Make sure we can emit an availability diagnostic here. + +let _ = Regex { // expected-error {{'Regex' is only available in macOS 13.0 or newer}} + // expected-error@-1 {{'init(_:)' is only available in macOS 13.0 or newer}} + // expected-note@-2 2{{add 'if #available' version check}} + + Capture {} // expected-error {{'Capture' is only available in macOS 13.0 or newer}} + // expected-error@-1 {{'init(_:)' is only available in macOS 13.0 or newer}} + // expected-note@-2 2{{add 'if #available' version check}} +} + +let _ = Regex { // expected-error {{'Regex' is only available in macOS 13.0 or newer}} + // expected-error@-1 {{'init(_:)' is only available in macOS 13.0 or newer}} + // expected-error@-2 {{'buildPartialBlock(accumulated:next:)' is only available in macOS 13.0 or newer}} + // expected-note@-3 3{{add 'if #available' version check}} + + /abc/ // expected-error {{'Regex' is only available in macOS 13.0 or newer}} + // expected-note@-1 {{add 'if #available' version check}} + + /def/ // expected-error {{'Regex' is only available in macOS 13.0 or newer}} + // expected-note@-1 {{add 'if #available' version check}} +} From 38765fbd9aaed958ed7f71e95550c52ae4107973 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 26 Jul 2022 10:37:50 -0700 Subject: [PATCH 412/491] [AST] Add a new `@typeWrapper` attribute --- include/swift/AST/Attr.def | 5 + include/swift/AST/DiagnosticsSema.def | 35 +++++ lib/Sema/TypeCheckAttr.cpp | 178 +++++++++++++++++++++++++ lib/Sema/TypeCheckDeclOverride.cpp | 1 + lib/Serialization/ModuleFormat.h | 2 +- test/IDE/complete_decl_attribute.swift | 5 + test/type/type_wrapper.swift | 84 ++++++++++++ 7 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 test/type/type_wrapper.swift diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def index 1df82de37cac8..23c2e438b0092 100644 --- a/include/swift/AST/Attr.def +++ b/include/swift/AST/Attr.def @@ -763,6 +763,11 @@ DECL_ATTR(_expose, Expose, ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, 133) +SIMPLE_DECL_ATTR(typeWrapper, TypeWrapper, + OnStruct | OnClass | OnEnum | + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + 134) + // If you're adding a new underscored attribute here, please document it in // docs/ReferenceGuides/UnderscoredAttributes.md. diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index df75bf4a2e063..3b2a563189ed6 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -6476,5 +6476,40 @@ ERROR(moveOnly_not_allowed_here,none, ERROR(move_expression_not_passed_lvalue,none, "'move' can only be applied to lvalues", ()) +//------------------------------------------------------------------------------ +// MARK: Type Wrappers +//------------------------------------------------------------------------------ + +ERROR(type_wrapper_attribute_not_allowed_here,none, + "type wrapper attribute %0 can only be applied to a class, struct", + (Identifier)) + +ERROR(type_wrapper_requires_a_single_generic_param,none, + "type wrapper has to declare a single generic parameter " + "for underlying storage type", ()) + +ERROR(type_wrapper_requires_memberwise_init,none, + "type wrapper type %0 does not contain a required initializer" + " - init(memberwise:)", + (DeclName)) + +ERROR(type_wrapper_requires_subscript,none, + "type wrapper type %0 does not contain a required subscript" + " - subscript(storedKeyPath:)", + (DeclName)) + +ERROR(type_wrapper_failable_init,none, + "type wrapper initializer %0 cannot be failable", (DeclName)) + +ERROR(type_wrapper_invalid_subscript_param_type, none, + "type wrapper subscript expects a key path parameter type (got: %0)", + (Type)) + +ERROR(type_wrapper_type_requirement_not_accessible,none, + "%select{private|fileprivate|internal|public|open}0 %1 %2 cannot have " + "more restrictive access than its enclosing type wrapper type %3 " + "(which is %select{private|fileprivate|internal|public|open}4)", + (AccessLevel, DescriptiveDeclKind, DeclName, Type, AccessLevel)) + #define UNDEFINE_DIAGNOSTIC_MACROS #include "DefineDiagnosticMacros.h" diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index febce6745b5ad..281362d4c599c 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -292,6 +292,7 @@ class AttributeChecker : public AttributeVisitor { void visitCustomAttr(CustomAttr *attr); void visitPropertyWrapperAttr(PropertyWrapperAttr *attr); + void visitTypeWrapperAttr(TypeWrapperAttr *attr); void visitResultBuilderAttr(ResultBuilderAttr *attr); void visitImplementationOnlyAttr(ImplementationOnlyAttr *attr); @@ -3457,6 +3458,18 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) { return; } + if (nominal->getAttrs().hasAttribute()) { + if (!(isa(D) || isa(D))) { + diagnose(attr->getLocation(), + diag::type_wrapper_attribute_not_allowed_here, + nominal->getName()); + attr->setInvalid(); + return; + } + + return; + } + // If the nominal type is a result builder type, verify that D is a // function, storage with an explicit getter, or parameter of function type. if (nominal->getAttrs().hasAttribute()) { @@ -3573,6 +3586,171 @@ void AttributeChecker::visitPropertyWrapperAttr(PropertyWrapperAttr *attr) { (void)nominal->getPropertyWrapperTypeInfo(); } +void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) { + auto nominal = dyn_cast(D); + if (!nominal) + return; + + auto &ctx = D->getASTContext(); + + auto isLessAccessibleThanType = [&](ValueDecl *decl) { + return decl->getFormalAccess() < + std::min(nominal->getFormalAccess(), AccessLevel::Public); + }; + + enum class UnviabilityReason { Failable, InvalidType, Inaccessible }; + + auto findMembersOrDiagnose = [&](DeclName memberName, + SmallVectorImpl &results, + Diag notFoundDiagnostic) -> bool { + nominal->lookupQualified(nominal, DeclNameRef(memberName), + NL_QualifiedDefault, results); + + if (results.empty()) { + diagnose(nominal->getLoc(), notFoundDiagnostic, nominal->getName()); + attr->setInvalid(); + return true; + } + return false; + }; + + // Check whether type marked as @typeWrapper is valid: + // + // - Has a single generic parameter + // - Has `init(memberwise: )` + // - Has at least one `subscript(storedKeyPath: KeyPath<...>)` overload + + // Has a single generic parameter. + { + auto *genericParams = nominal->getGenericParams(); + if (!genericParams || genericParams->size() != 1) { + diagnose(nominal->getLoc(), + diag::type_wrapper_requires_a_single_generic_param); + attr->setInvalid(); + return; + } + } + + // `init(memberwise:)` + { + DeclName initName(ctx, DeclBaseName::createConstructor(), + ArrayRef(ctx.getIdentifier("memberwise"))); + + SmallVector inits; + if (findMembersOrDiagnose(initName, inits, + diag::type_wrapper_requires_memberwise_init)) + return; + + llvm::SmallDenseMap, 2> + nonViableInits; + for (auto *decl : inits) { + auto *init = cast(decl); + + if (init->isFailable()) + nonViableInits[init].push_back(UnviabilityReason::Failable); + + if (isLessAccessibleThanType(init)) + nonViableInits[init].push_back(UnviabilityReason::Inaccessible); + } + + // If there are no viable initializers, let's complain. + if (inits.size() - nonViableInits.size() == 0) { + for (const auto &entry : nonViableInits) { + auto *init = entry.first; + + for (auto reason : entry.second) { + switch (reason) { + case UnviabilityReason::Failable: + diagnose(init, diag::type_wrapper_failable_init, init->getName()); + break; + + case UnviabilityReason::Inaccessible: + diagnose(init, diag::type_wrapper_type_requirement_not_accessible, + init->getFormalAccess(), init->getDescriptiveKind(), + init->getName(), nominal->getDeclaredType(), + nominal->getFormalAccess()); + break; + + case UnviabilityReason::InvalidType: + llvm_unreachable("init(memberwise:) type is not checked"); + } + } + } + + attr->setInvalid(); + return; + } + } + + // subscript(storedKeypath: KeyPath<...>) + { + DeclName subscriptName( + ctx, DeclBaseName::createSubscript(), + ArrayRef(ctx.getIdentifier("storageKeyPath"))); + + SmallVector subscripts; + if (findMembersOrDiagnose(subscriptName, subscripts, + diag::type_wrapper_requires_subscript)) + return; + + llvm::SmallDenseMap, 2> + nonViableSubscripts; + + for (auto *decl : subscripts) { + auto *subscript = cast(decl); + + auto *keyPathParam = subscript->getIndices()->get(0); + + if (auto *BGT = + keyPathParam->getInterfaceType()->getAs()) { + if (!(BGT->isKeyPath() || BGT->isWritableKeyPath() || + BGT->isReferenceWritableKeyPath())) { + nonViableSubscripts[subscript].push_back( + UnviabilityReason::InvalidType); + } + } else { + nonViableSubscripts[subscript].push_back( + UnviabilityReason::InvalidType); + } + + if (isLessAccessibleThanType(subscript)) + nonViableSubscripts[subscript].push_back( + UnviabilityReason::Inaccessible); + } + + if (subscripts.size() - nonViableSubscripts.size() == 0) { + for (const auto &entry : nonViableSubscripts) { + auto *subscript = entry.first; + + for (auto reason : entry.second) { + switch (reason) { + case UnviabilityReason::InvalidType: { + auto paramTy = subscript->getIndices()->get(0)->getInterfaceType(); + diagnose(subscript, diag::type_wrapper_invalid_subscript_param_type, + paramTy); + break; + } + + case UnviabilityReason::Inaccessible: + diagnose(subscript, + diag::type_wrapper_type_requirement_not_accessible, + subscript->getFormalAccess(), + subscript->getDescriptiveKind(), subscript->getName(), + nominal->getDeclaredType(), nominal->getFormalAccess()); + break; + + case UnviabilityReason::Failable: + llvm_unreachable("subscripts cannot be failable"); + } + } + } + + attr->setInvalid(); + return; + } + } +} + void AttributeChecker::visitResultBuilderAttr(ResultBuilderAttr *attr) { auto *nominal = dyn_cast(D); auto &ctx = D->getASTContext(); diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 4297fcf41c021..5071591c636ae 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1584,6 +1584,7 @@ namespace { UNINTERESTING_ATTR(ImplementationOnly) UNINTERESTING_ATTR(Custom) UNINTERESTING_ATTR(PropertyWrapper) + UNINTERESTING_ATTR(TypeWrapper) UNINTERESTING_ATTR(DisfavoredOverload) UNINTERESTING_ATTR(ResultBuilder) UNINTERESTING_ATTR(ProjectedValueProperty) diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 2cdcdff28a282..037480054ca7b 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 706; // @_expose attribute +const uint16_t SWIFTMODULE_VERSION_MINOR = 707; // @typeWrapper attribute /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/test/IDE/complete_decl_attribute.swift b/test/IDE/complete_decl_attribute.swift index 21dd3a05f10ae..13a7168a7e7bc 100644 --- a/test/IDE/complete_decl_attribute.swift +++ b/test/IDE/complete_decl_attribute.swift @@ -117,6 +117,7 @@ actor MyGlobalActor { // KEYWORD3-NEXT: Keyword/None: resultBuilder[#Class Attribute#]; name=resultBuilder // KEYWORD3-NEXT: Keyword/None: globalActor[#Class Attribute#]; name=globalActor // KEYWORD3-NEXT: Keyword/None: preconcurrency[#Class Attribute#]; name=preconcurrency +// KEYWORD3-NEXT: Keyword/None: typeWrapper[#Class Attribute#]; name=typeWrapper // KEYWORD3-NEXT: End completions @#^KEYWORD3_2^#IB class C2 {} @@ -135,6 +136,7 @@ actor MyGlobalActor { // KEYWORD4-NEXT: Keyword/None: resultBuilder[#Enum Attribute#]; name=resultBuilder // KEYWORD4-NEXT: Keyword/None: globalActor[#Enum Attribute#]; name=globalActor // KEYWORD4-NEXT: Keyword/None: preconcurrency[#Enum Attribute#]; name=preconcurrency +// KEYWORD4-NEXT: Keyword/None: typeWrapper[#Enum Attribute#]; name=typeWrapper // KEYWORD4-NEXT: End completions @@ -150,6 +152,7 @@ actor MyGlobalActor { // KEYWORD5-NEXT: Keyword/None: resultBuilder[#Struct Attribute#]; name=resultBuilder // KEYWORD5-NEXT: Keyword/None: globalActor[#Struct Attribute#]; name=globalActor // KEYWORD5-NEXT: Keyword/None: preconcurrency[#Struct Attribute#]; name=preconcurrency +// KEYWORD5-NEXT: Keyword/None: typeWrapper[#Struct Attribute#]; name=typeWrapper // KEYWORD5-NEXT: End completions @#^ON_GLOBALVAR^# var globalVar @@ -305,6 +308,7 @@ struct _S { // ON_MEMBER_LAST-DAG: Keyword/None: Sendable[#Declaration Attribute#]; name=Sendable // ON_MEMBER_LAST-DAG: Keyword/None: exclusivity[#Declaration Attribute#]; name=exclusivity // ON_MEMBER_LAST-DAG: Keyword/None: preconcurrency[#Declaration Attribute#]; name=preconcurrency +// ON_MEMBER_LAST-DAG: Keyword/None: typeWrapper[#Declaration Attribute#]; name=typeWrapper // ON_MEMBER_LAST-NOT: Keyword // ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct // ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper @@ -374,6 +378,7 @@ func dummy2() {} // KEYWORD_LAST-DAG: Keyword/None: Sendable[#Declaration Attribute#]; name=Sendable // KEYWORD_LAST-DAG: Keyword/None: exclusivity[#Declaration Attribute#]; name=exclusivity // KEYWORD_LAST-DAG: Keyword/None: preconcurrency[#Declaration Attribute#]; name=preconcurrency +// KEYWORD_LAST-DAG: Keyword/None: typeWrapper[#Declaration Attribute#]; name=typeWrapper // KEYWORD_LAST-NOT: Keyword // KEYWORD_LAST-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct // KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper diff --git a/test/type/type_wrapper.swift b/test/type/type_wrapper.swift new file mode 100644 index 0000000000000..d09a64a366ded --- /dev/null +++ b/test/type/type_wrapper.swift @@ -0,0 +1,84 @@ +// RUN: %target-typecheck-verify-swift + +@typeWrapper +struct ConcreteTypeWrapper { // expected-error {{type wrapper has to declare a single generic parameter for underlying storage type}} + init(memberwise: Int) {} +} + +@typeWrapper +struct EmptyTypeWrapper { // expected-error {{type wrapper type 'EmptyTypeWrapper' does not contain a required initializer - init(memberwise:)}} +} + +@typeWrapper +struct NoMemberwiseInit { + // expected-error@-1 {{type wrapper type 'NoMemberwiseInit' does not contain a required initializer - init(memberwise:)}} + + subscript(storageKeyPath path: KeyPath) -> V { + get { fatalError() } + } +} + +@typeWrapper +struct FailableInit { + init?(memberwise: S) { // expected-error {{type wrapper initializer 'init(memberwise:)' cannot be failable}} + } + + subscript(storageKeyPath path: KeyPath) -> V { + get { fatalError() } + } +} + +// Okay because there is a valid `init(memberwise:)` overload. +@typeWrapper +struct FailableAndValidInit { + init(memberwise: S) { + } + + init?(memberwise: S) where S == Int { + } + + subscript(storageKeyPath path: KeyPath) -> V { + get { fatalError() } + } +} + +@typeWrapper +public struct InaccessibleInit { + fileprivate init(memberwise: S) { + // expected-error@-1 {{fileprivate initializer 'init(memberwise:)' cannot have more restrictive access than its enclosing type wrapper type 'InaccessibleInit' (which is public)}} + } + + private init?(memberwise: S) where S: AnyObject { + // expected-error@-1 {{private initializer 'init(memberwise:)' cannot have more restrictive access than its enclosing type wrapper type 'InaccessibleInit' (which is public)}} + // expected-error@-2 {{type wrapper initializer 'init(memberwise:)' cannot be failable}} + } + + subscript(storageKeyPath path: KeyPath) -> V { + get { fatalError() } + } +} + +@typeWrapper +struct NoSubscripts { + // expected-error@-1 {{type wrapper type 'NoSubscripts' does not contain a required subscript - subscript(storedKeyPath:)}} + init(memberwise: S) {} +} + +@typeWrapper +struct InaccessibleOrInvalidSubscripts { + init(memberwise: S) {} + + fileprivate subscript(storageKeyPath path: KeyPath) -> V { + // expected-error@-1 {{fileprivate subscript 'subscript(storageKeyPath:)' cannot have more restrictive access than its enclosing type wrapper type 'InaccessibleOrInvalidSubscripts' (which is internal)}} + get { fatalError() } + } + + private subscript(storageKeyPath path: KeyPath) -> [V] { + // expected-error@-1 {{private subscript 'subscript(storageKeyPath:)' cannot have more restrictive access than its enclosing type wrapper type 'InaccessibleOrInvalidSubscripts' (which is internal)}} + get { fatalError() } + } + + subscript(storageKeyPath path: Int) -> Bool { // expected-error {{type wrapper subscript expects a key path parameter type (got: 'Int')}} + get { true } + } +} From 69d80dc738a8db914f093b8bc2e6755230420874 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 26 Jul 2022 10:42:21 -0700 Subject: [PATCH 413/491] [AST] Add a way to check whether type has a type wrapper --- include/swift/AST/Decl.h | 6 ++ include/swift/AST/DiagnosticsSema.def | 3 + include/swift/AST/TypeCheckRequests.h | 16 ++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 + lib/Sema/CMakeLists.txt | 1 + lib/Sema/TypeCheckTypeWrapper.cpp | 62 +++++++++++++++++++++ 6 files changed, 91 insertions(+) create mode 100644 lib/Sema/TypeCheckTypeWrapper.cpp diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 11f3ce7117ea2..1cebb75affb6f 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3754,6 +3754,12 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { return getGlobalActorInstance() != nullptr; } + /// Returns true if this type has a type wrapper custom attribute. + bool hasTypeWrapper() const { return bool(getTypeWrapper()); } + + /// Return a type wrapper (if any) associated with this type. + NominalTypeDecl *getTypeWrapper() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_NominalTypeDecl && diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 3b2a563189ed6..ffead969c6238 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -6488,6 +6488,9 @@ ERROR(type_wrapper_requires_a_single_generic_param,none, "type wrapper has to declare a single generic parameter " "for underlying storage type", ()) +ERROR(cannot_use_multiple_type_wrappers,none, + "type %0 cannot use more than one type wrapper", ()) + ERROR(type_wrapper_requires_memberwise_init,none, "type wrapper type %0 does not contain a required initializer" " - init(memberwise:)", diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 88afc583edcf0..81b68bee7245c 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3499,6 +3499,22 @@ class GetSourceFileAsyncNode bool isCached() const { return true; } }; +/// Return a type wrapper (if any) associated with the given declaration. +class GetTypeWrapper + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + NominalTypeDecl *evaluate(Evaluator &evaluator, NominalTypeDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 56ec61eeb2051..932ea201c4ddc 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -399,3 +399,6 @@ SWIFT_REQUEST(TypeChecker, ClosureEffectsRequest, SWIFT_REQUEST(TypeChecker, GetSourceFileAsyncNode, AwaitExpr *(const SourceFile *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, GetTypeWrapper, + NominalTypeDecl *(NominalTypeDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 18b2bce38a322..4fe5be9a6c061 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -61,6 +61,7 @@ add_swift_host_library(swiftSema STATIC TypeCheckNameLookup.cpp TypeCheckPattern.cpp TypeCheckPropertyWrapper.cpp + TypeCheckTypeWrapper.cpp TypeCheckProtocol.cpp TypeCheckProtocolInference.cpp TypeCheckRegex.cpp diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp new file mode 100644 index 0000000000000..374d97ff1cec2 --- /dev/null +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -0,0 +1,62 @@ +//===--- TypeCheckTypeWrapper.cpp - type wrappers -------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2022 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for type wrappers. +// +//===----------------------------------------------------------------------===// +#include "TypeChecker.h" +#include "swift/AST/ASTContext.h" +#include "swift/AST/Decl.h" +#include "swift/AST/NameLookupRequests.h" +#include "swift/AST/TypeCheckRequests.h" +#include "swift/Basic/LLVM.h" +#include "swift/Basic/SourceLoc.h" + +using namespace swift; + +NominalTypeDecl *NominalTypeDecl::getTypeWrapper() const { + auto *mutableSelf = const_cast(this); + return evaluateOrDefault(getASTContext().evaluator, + GetTypeWrapper{mutableSelf}, nullptr); +} + +NominalTypeDecl *GetTypeWrapper::evaluate(Evaluator &evaluator, + NominalTypeDecl *decl) const { + auto &ctx = decl->getASTContext(); + + // Note that we don't actually care whether there are duplicates, + // using the same type wrapper multiple times is still an error. + SmallVector typeWrappers; + + for (auto *attr : decl->getAttrs().getAttributes()) { + auto *mutableAttr = const_cast(attr); + auto *nominal = evaluateOrDefault( + ctx.evaluator, CustomAttrNominalRequest{mutableAttr, decl}, nullptr); + + if (!nominal) + continue; + + auto *typeWrapper = nominal->getAttrs().getAttribute(); + if (typeWrapper && typeWrapper->isValid()) + typeWrappers.push_back(nominal); + } + + if (typeWrappers.empty()) + return nullptr; + + if (typeWrappers.size() != 1) { + ctx.Diags.diagnose(decl, diag::cannot_use_multiple_type_wrappers); + return nullptr; + } + + return typeWrappers.front(); +} From eb51a115287fef61bc52bdd5a34efe6165dda2d3 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 1 Aug 2022 10:09:04 -0700 Subject: [PATCH 414/491] [AST] Add a way to obtain a type of type wrapper --- include/swift/AST/TypeCheckRequests.h | 21 ++++++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 ++ lib/AST/TypeCheckRequests.cpp | 4 ++ lib/Sema/TypeCheckType.cpp | 3 +- lib/Sema/TypeCheckTypeWrapper.cpp | 46 +++++++++++++++++---- 5 files changed, 68 insertions(+), 9 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 81b68bee7245c..c6c032db571ee 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3364,6 +3364,10 @@ enum class CustomAttrTypeKind { /// unbound generic types. PropertyWrapper, + /// Just like property wrappers, type wrappers are represented + /// as custom type attributes and allow unbound generic types. + TypeWrapper, + /// Global actors are represented as custom type attributes. They don't /// have any particularly interesting semantics. GlobalActor, @@ -3515,6 +3519,23 @@ class GetTypeWrapper bool isCached() const { return true; } }; +/// Return a type of the type wrapper (if any) associated with the given +/// declaration. +class GetTypeWrapperType + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + Type evaluate(Evaluator &evaluator, NominalTypeDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 932ea201c4ddc..ffdb8a9daf749 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -402,3 +402,6 @@ SWIFT_REQUEST(TypeChecker, GetSourceFileAsyncNode, SWIFT_REQUEST(TypeChecker, GetTypeWrapper, NominalTypeDecl *(NominalTypeDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, GetTypeWrapperType, + Type(NominalTypeDecl *), + Cached, NoLocationInfo) diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index c4fc3c22e1324..72daff4ba6d82 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1531,6 +1531,10 @@ void swift::simple_display(llvm::raw_ostream &out, CustomAttrTypeKind value) { out << "property-wrapper"; return; + case CustomAttrTypeKind::TypeWrapper: + out << "type-wrapper"; + return; + case CustomAttrTypeKind::GlobalActor: out << "global-actor"; return; diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index eed633a73d52e..cf3295c866ca2 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -4706,7 +4706,8 @@ Type CustomAttrTypeRequest::evaluate(Evaluator &eval, CustomAttr *attr, OpenUnboundGenericTypeFn unboundTyOpener = nullptr; // Property delegates allow their type to be an unbound generic. - if (typeKind == CustomAttrTypeKind::PropertyWrapper) { + if (typeKind == CustomAttrTypeKind::PropertyWrapper || + typeKind == CustomAttrTypeKind::TypeWrapper) { unboundTyOpener = [](auto unboundTy) { // FIXME: Don't let unbound generic types // escape type resolution. For now, just diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 374d97ff1cec2..434b22515da22 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -29,14 +29,11 @@ NominalTypeDecl *NominalTypeDecl::getTypeWrapper() const { GetTypeWrapper{mutableSelf}, nullptr); } -NominalTypeDecl *GetTypeWrapper::evaluate(Evaluator &evaluator, - NominalTypeDecl *decl) const { +static void getTypeWrappers( + NominalTypeDecl *decl, + SmallVectorImpl> &typeWrappers) { auto &ctx = decl->getASTContext(); - // Note that we don't actually care whether there are duplicates, - // using the same type wrapper multiple times is still an error. - SmallVector typeWrappers; - for (auto *attr : decl->getAttrs().getAttributes()) { auto *mutableAttr = const_cast(attr); auto *nominal = evaluateOrDefault( @@ -47,8 +44,19 @@ NominalTypeDecl *GetTypeWrapper::evaluate(Evaluator &evaluator, auto *typeWrapper = nominal->getAttrs().getAttribute(); if (typeWrapper && typeWrapper->isValid()) - typeWrappers.push_back(nominal); + typeWrappers.push_back({mutableAttr, nominal}); } +} + +NominalTypeDecl *GetTypeWrapper::evaluate(Evaluator &evaluator, + NominalTypeDecl *decl) const { + auto &ctx = decl->getASTContext(); + + // Note that we don't actually care whether there are duplicates, + // using the same type wrapper multiple times is still an error. + SmallVector, 2> typeWrappers; + + getTypeWrappers(decl, typeWrappers); if (typeWrappers.empty()) return nullptr; @@ -58,5 +66,27 @@ NominalTypeDecl *GetTypeWrapper::evaluate(Evaluator &evaluator, return nullptr; } - return typeWrappers.front(); + return typeWrappers.front().second; +} + +Type GetTypeWrapperType::evaluate(Evaluator &evaluator, + NominalTypeDecl *decl) const { + SmallVector, 2> typeWrappers; + + getTypeWrappers(decl, typeWrappers); + + if (typeWrappers.size() != 1) + return Type(); + + auto *typeWrapperAttr = typeWrappers.front().first; + auto type = evaluateOrDefault( + evaluator, + CustomAttrTypeRequest{typeWrapperAttr, decl->getDeclContext(), + CustomAttrTypeKind::TypeWrapper}, + Type()); + + if (!type || type->hasError()) { + return ErrorType::get(decl->getASTContext()); + } + return type; } From 029d6d7f8703370ce8f91ad8573c3af507bd4942 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 26 Jul 2022 10:48:45 -0700 Subject: [PATCH 415/491] [AST] TypeWrappers: Add a way to inject `$Storage` into a type `$Storage` type is going to used as a type of `$_storage` variable and contains all of the stored properties of the type it's attached to. --- include/swift/AST/KnownIdentifiers.def | 3 +++ include/swift/AST/TypeCheckRequests.h | 18 ++++++++++++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 +++ lib/Sema/TypeCheckTypeWrapper.cpp | 23 +++++++++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index c099657ff9a86..a7380114984bb 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -307,6 +307,9 @@ IDENTIFIER(decodeNextArgument) IDENTIFIER(SerializationRequirement) IDENTIFIER_WITH_NAME(builderSelf, "$builderSelf") +// Type wrappers +IDENTIFIER_WITH_NAME(TypeWrapperStorage, "$Storage") + #undef IDENTIFIER #undef IDENTIFIER_ #undef IDENTIFIER_WITH_NAME diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index c6c032db571ee..8913ffb205761 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3536,6 +3536,24 @@ class GetTypeWrapperType bool isCached() const { return true; } }; +/// Inject or get `$Storage` type which has all of the stored properties +/// of the given type with a type wrapper. +class GetTypeWrapperStorage + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + NominalTypeDecl *evaluate(Evaluator &evaluator, NominalTypeDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index ffdb8a9daf749..76e42012a390f 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -405,3 +405,6 @@ SWIFT_REQUEST(TypeChecker, GetTypeWrapper, SWIFT_REQUEST(TypeChecker, GetTypeWrapperType, Type(NominalTypeDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, GetTypeWrapperStorage, + NominalTypeDecl *(NominalTypeDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 434b22515da22..3376fb9737626 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -90,3 +90,26 @@ Type GetTypeWrapperType::evaluate(Evaluator &evaluator, } return type; } + +NominalTypeDecl * +GetTypeWrapperStorage::evaluate(Evaluator &evaluator, + NominalTypeDecl *parent) const { + if (!parent->hasTypeWrapper()) + return nullptr; + + auto &ctx = parent->getASTContext(); + + auto *storage = + new (ctx) StructDecl(/*StructLoc=*/SourceLoc(), ctx.Id_TypeWrapperStorage, + /*NameLoc=*/SourceLoc(), + /*Inheritted=*/{}, + /*GenericParams=*/nullptr, parent); + + storage->setImplicit(); + storage->setSynthesized(); + storage->copyFormalAccessFrom(parent, /*sourceIsParentContext=*/true); + + parent->addMember(storage); + + return storage; +} From ccd7e4f0225500394e14b444c70c1a93a6a42f42 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 26 Jul 2022 12:52:12 -0700 Subject: [PATCH 416/491] [AST] TypeWrappers: Add a request to inject or get `$_storage` property This is the property that would get used to route stored property accesses through a type wrapper. --- include/swift/AST/KnownIdentifiers.def | 1 + include/swift/AST/TypeCheckRequests.h | 17 +++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 ++ lib/Sema/TypeCheckTypeWrapper.cpp | 55 +++++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index a7380114984bb..7526690772b5a 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -309,6 +309,7 @@ IDENTIFIER_WITH_NAME(builderSelf, "$builderSelf") // Type wrappers IDENTIFIER_WITH_NAME(TypeWrapperStorage, "$Storage") +IDENTIFIER_WITH_NAME(TypeWrapperProperty, "$_storage") #undef IDENTIFIER #undef IDENTIFIER_ diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 8913ffb205761..abf7a64d4bc25 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3554,6 +3554,23 @@ class GetTypeWrapperStorage bool isCached() const { return true; } }; +/// Inject or get `$_storage` property which is used to route accesses through +/// to all stored properties of a type that has a type wrapper. +class GetTypeWrapperProperty + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + VarDecl *evaluate(Evaluator &evaluator, NominalTypeDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 76e42012a390f..e25c1c262a4dc 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -408,3 +408,6 @@ SWIFT_REQUEST(TypeChecker, GetTypeWrapperType, SWIFT_REQUEST(TypeChecker, GetTypeWrapperStorage, NominalTypeDecl *(NominalTypeDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, GetTypeWrapperProperty, + VarDecl *(NominalTypeDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 3376fb9737626..417263ff4bb47 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -17,12 +17,41 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/Decl.h" #include "swift/AST/NameLookupRequests.h" +#include "swift/AST/Pattern.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/SourceLoc.h" using namespace swift; +/// Create a property declaration and inject it into the given type. +static VarDecl *injectProperty(NominalTypeDecl *parent, Identifier name, + Type type, VarDecl::Introducer introducer, + Expr *initializer = nullptr) { + auto &ctx = parent->getASTContext(); + + auto *var = new (ctx) VarDecl(/*isStatic=*/false, introducer, + /*nameLoc=*/SourceLoc(), name, parent); + + var->setImplicit(); + var->setSynthesized(); + var->copyFormalAccessFrom(parent, /*sourceIsParentContext=*/true); + var->setInterfaceType(type); + + Pattern *pattern = NamedPattern::createImplicit(ctx, var); + pattern->setType(type); + + pattern = TypedPattern::createImplicit(ctx, pattern, type); + + auto *PBD = PatternBindingDecl::createImplicit(ctx, StaticSpellingKind::None, + pattern, initializer, parent); + + parent->addMember(PBD); + parent->addMember(var); + + return var; +} + NominalTypeDecl *NominalTypeDecl::getTypeWrapper() const { auto *mutableSelf = const_cast(this); return evaluateOrDefault(getASTContext().evaluator, @@ -113,3 +142,29 @@ GetTypeWrapperStorage::evaluate(Evaluator &evaluator, return storage; } + +VarDecl * +GetTypeWrapperProperty::evaluate(Evaluator &evaluator, + NominalTypeDecl *parent) const { + auto &ctx = parent->getASTContext(); + + auto *typeWrapper = parent->getTypeWrapper(); + if (!typeWrapper) + return nullptr; + + auto *storage = + evaluateOrDefault(ctx.evaluator, GetTypeWrapperStorage{parent}, nullptr); + + auto *typeWrapperType = + evaluateOrDefault(ctx.evaluator, GetTypeWrapperType{parent}, Type()) + ->castTo(); + assert(typeWrapperType); + + // $_storage: Wrapper<$Storage> + auto propertyTy = BoundGenericType::get( + typeWrapper, /*Parent=*/typeWrapperType->getParent(), + /*genericArgs=*/{storage->getInterfaceType()->getMetatypeInstanceType()}); + + return injectProperty(parent, ctx.Id_TypeWrapperProperty, + propertyTy, VarDecl::Introducer::Var); +} From 43feefd581894fc370d4589da91d786a488893b1 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 27 Jul 2022 00:09:20 -0700 Subject: [PATCH 417/491] [AST] TypeWrappers: Add a request to create and get "mirror" type wrapper property Given a stored property associated with a type wrapped type, produce a property that mirrors it in the type wrapper context. --- include/swift/AST/TypeCheckRequests.h | 17 ++++++++++++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 +++ lib/Sema/TypeCheckTypeWrapper.cpp | 22 +++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index abf7a64d4bc25..b49881ac26d53 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3571,6 +3571,23 @@ class GetTypeWrapperProperty bool isCached() const { return true; } }; +/// Given a stored property associated with a type wrapped type, +/// produce a property that mirrors it in the type wrapper context. +class GetTypeWrapperStorageForProperty + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + VarDecl *evaluate(Evaluator &evaluator, VarDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index e25c1c262a4dc..add1bbd9b6b73 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -411,3 +411,6 @@ SWIFT_REQUEST(TypeChecker, GetTypeWrapperStorage, SWIFT_REQUEST(TypeChecker, GetTypeWrapperProperty, VarDecl *(NominalTypeDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, GetTypeWrapperStorageForProperty, + VarDecl *(VarDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 417263ff4bb47..e6b700c300786 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -168,3 +168,25 @@ GetTypeWrapperProperty::evaluate(Evaluator &evaluator, return injectProperty(parent, ctx.Id_TypeWrapperProperty, propertyTy, VarDecl::Introducer::Var); } + +VarDecl *GetTypeWrapperStorageForProperty::evaluate(Evaluator &evaluator, + VarDecl *property) const { + auto *wrappedType = property->getDeclContext()->getSelfNominalTypeDecl(); + if (!(wrappedType && wrappedType->hasTypeWrapper())) + return nullptr; + + // Type wrappers support only stored `var`s. + if (property->isStatic() || property->isLet() || !property->hasStorage()) + return nullptr; + + auto &ctx = wrappedType->getASTContext(); + + auto *storage = evaluateOrDefault( + ctx.evaluator, GetTypeWrapperStorage{wrappedType}, nullptr); + assert(storage); + + return injectProperty( + storage, property->getName(), + storage->mapTypeIntoContext(property->getValueInterfaceType()), + property->getIntroducer()); +} From 3dc441b3d3435028ceecba8c573bc7045d331390 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 27 Jul 2022 14:16:29 -0700 Subject: [PATCH 418/491] [TypeChecker] Synthesize getters for stored properties of a type wrapped type A getter routes accesses through a subscript of `$_storage` variable injected into a wrapped type. --- include/swift/AST/Decl.h | 6 +- include/swift/AST/KnownIdentifiers.def | 1 + include/swift/AST/TypeCheckRequests.h | 17 ++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 + lib/Sema/TypeCheckStorage.cpp | 15 ++++ lib/Sema/TypeCheckTypeWrapper.cpp | 88 +++++++++++++++++++-- 6 files changed, 124 insertions(+), 6 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 1cebb75affb6f..05f3557c9af91 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -5555,7 +5555,11 @@ class VarDecl : public AbstractStorageDecl { /// Return true if this property either has storage or has an attached property /// wrapper that has storage. bool hasStorageOrWrapsStorage() const; - + + /// Whether this property belongs to a type wrapped type and has + /// all access to it routed through a type wrapper. + bool isAccessedViaTypeWrapper() const; + /// Visit all auxiliary declarations to this VarDecl. /// /// An auxiliary declaration is a declaration synthesized by the compiler to support diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index 7526690772b5a..3d9bb1ce996b9 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -310,6 +310,7 @@ IDENTIFIER_WITH_NAME(builderSelf, "$builderSelf") // Type wrappers IDENTIFIER_WITH_NAME(TypeWrapperStorage, "$Storage") IDENTIFIER_WITH_NAME(TypeWrapperProperty, "$_storage") +IDENTIFIER(storageKeyPath) #undef IDENTIFIER #undef IDENTIFIER_ diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index b49881ac26d53..178c978e6769e 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3588,6 +3588,23 @@ class GetTypeWrapperStorageForProperty bool isCached() const { return true; } }; +/// Synthesize the body of a getter for a stored property that belongs to +/// a type wrapped type. +class SynthesizeTypeWrappedPropertyGetterBody + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + BraceStmt *evaluate(Evaluator &evaluator, AccessorDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index add1bbd9b6b73..7e23b0580d1c2 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -414,3 +414,6 @@ SWIFT_REQUEST(TypeChecker, GetTypeWrapperProperty, SWIFT_REQUEST(TypeChecker, GetTypeWrapperStorageForProperty, VarDecl *(VarDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedPropertyGetterBody, + BraceStmt *(AccessorDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 57fe732879b32..e047e2d097cec 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -1498,12 +1498,27 @@ synthesizeInvalidAccessor(AccessorDecl *accessor, ASTContext &ctx) { return { BraceStmt::create(ctx, loc, ArrayRef(), loc, true), true }; } +/// Synthesize the body of a getter for a stored property that belongs to +/// a type wrapped type. +static std::pair +synthesizeTypeWrappedPropertyGetterBody(AccessorDecl *getter, ASTContext &ctx) { + auto *body = evaluateOrDefault( + ctx.evaluator, SynthesizeTypeWrappedPropertyGetterBody{getter}, nullptr); + return body ? std::make_pair(body, /*isTypeChecked=*/false) + : synthesizeInvalidAccessor(getter, ctx); +} + static std::pair synthesizeGetterBody(AccessorDecl *getter, ASTContext &ctx) { auto storage = getter->getStorage(); // Synthesize the getter for a lazy property or property wrapper. if (auto var = dyn_cast(storage)) { + // If the type this stored property belongs to has a type wrapper + // we need to route getter/setter through the wrapper. + if (var->isAccessedViaTypeWrapper()) + return synthesizeTypeWrappedPropertyGetterBody(getter, ctx); + if (var->getAttrs().hasAttribute()) { auto *storage = var->getLazyStorageProperty(); return synthesizeLazyGetterBody(getter, var, storage, ctx); diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index e6b700c300786..c8c6b523fd5e8 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -18,6 +18,7 @@ #include "swift/AST/Decl.h" #include "swift/AST/NameLookupRequests.h" #include "swift/AST/Pattern.h" +#include "swift/AST/Stmt.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/SourceLoc.h" @@ -52,6 +53,23 @@ static VarDecl *injectProperty(NominalTypeDecl *parent, Identifier name, return var; } +bool VarDecl::isAccessedViaTypeWrapper() const { + auto *parent = getDeclContext()->getSelfNominalTypeDecl(); + if (!(parent && parent->hasTypeWrapper())) + return false; + + if (isStatic() || isLet() || !hasStorage()) + return false; + + if (getAttrs().hasAttribute()) + return false; + + if (hasAttachedPropertyWrapper()) + return false; + + return true; +} + NominalTypeDecl *NominalTypeDecl::getTypeWrapper() const { auto *mutableSelf = const_cast(this); return evaluateOrDefault(getASTContext().evaluator, @@ -176,7 +194,7 @@ VarDecl *GetTypeWrapperStorageForProperty::evaluate(Evaluator &evaluator, return nullptr; // Type wrappers support only stored `var`s. - if (property->isStatic() || property->isLet() || !property->hasStorage()) + if (!property->isAccessedViaTypeWrapper()) return nullptr; auto &ctx = wrappedType->getASTContext(); @@ -185,8 +203,68 @@ VarDecl *GetTypeWrapperStorageForProperty::evaluate(Evaluator &evaluator, ctx.evaluator, GetTypeWrapperStorage{wrappedType}, nullptr); assert(storage); - return injectProperty( - storage, property->getName(), - storage->mapTypeIntoContext(property->getValueInterfaceType()), - property->getIntroducer()); + return injectProperty(storage, property->getName(), + property->getValueInterfaceType(), + property->getIntroducer()); +} + +/// Given the property create a subscript to reach its type wrapper storage: +/// `$_storage[storageKeyPath: \$Storage.]`. +static SubscriptExpr *subscriptTypeWrappedProperty(VarDecl *var, + AccessorDecl *useDC) { + auto &ctx = useDC->getASTContext(); + auto *parent = var->getDeclContext()->getSelfNominalTypeDecl(); + + if (!(parent && parent->hasTypeWrapper())) + return nullptr; + + auto *typeWrapperVar = + evaluateOrDefault(ctx.evaluator, GetTypeWrapperProperty{parent}, nullptr); + auto *storageVar = evaluateOrDefault( + ctx.evaluator, GetTypeWrapperStorageForProperty{var}, nullptr); + + assert(typeWrapperVar); + assert(storageVar); + + // \$Storage. + auto *argExpr = KeyPathExpr::createImplicit( + ctx, /*backslashLoc=*/SourceLoc(), + {KeyPathExpr::Component::forProperty( + {storageVar}, + useDC->mapTypeIntoContext(storageVar->getInterfaceType()), + /*Loc=*/SourceLoc())}, + /*endLoc=*/SourceLoc()); + + auto *subscriptBaseExpr = UnresolvedDotExpr::createImplicit( + ctx, + new (ctx) DeclRefExpr({useDC->getImplicitSelfDecl()}, + /*Loc=*/DeclNameLoc(), /*Implicit=*/true), + typeWrapperVar->getName()); + + // $_storage[storageKeyPath: \$Storage.] + return SubscriptExpr::create( + ctx, subscriptBaseExpr, + ArgumentList::forImplicitSingle(ctx, ctx.Id_storageKeyPath, argExpr), + ConcreteDeclRef(), /*implicit=*/true); +} + +BraceStmt * +SynthesizeTypeWrappedPropertyGetterBody::evaluate(Evaluator &evaluator, + AccessorDecl *getter) const { + assert(getter->isGetter()); + + auto &ctx = getter->getASTContext(); + + auto *var = dyn_cast(getter->getStorage()); + if (!var) + return nullptr; + + auto *subscript = subscriptTypeWrappedProperty(var, getter); + if (!subscript) + return nullptr; + + ASTNode body = new (ctx) ReturnStmt(SourceLoc(), subscript, + /*isImplicit=*/true); + return BraceStmt::create(ctx, /*lbloc=*/var->getLoc(), body, + /*rbloc=*/var->getLoc(), /*implicit=*/true); } From 1e0976b213ec07ffaca289d8b0f256e25d07344c Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 28 Jul 2022 09:53:33 -0700 Subject: [PATCH 419/491] [TypeChecker] Synthesize setters for stored properties of a type wrapped type A setter routes assignment through a subscript of `$_storage` variable injected into a wrapped type - `$_storage[storageKeyPath: \$Storage.] = newValue` --- include/swift/AST/TypeCheckRequests.h | 17 +++++++++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 +++ lib/Sema/TypeCheckStorage.cpp | 13 ++++++++++ lib/Sema/TypeCheckTypeWrapper.cpp | 28 +++++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 178c978e6769e..157599f760da6 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3605,6 +3605,23 @@ class SynthesizeTypeWrappedPropertyGetterBody bool isCached() const { return true; } }; +/// Synthesize the body of a setter for a stored property that belongs to +/// a type wrapped type. +class SynthesizeTypeWrappedPropertySetterBody + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + BraceStmt *evaluate(Evaluator &evaluator, AccessorDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 7e23b0580d1c2..48d6cc8f93ef2 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -417,3 +417,6 @@ SWIFT_REQUEST(TypeChecker, GetTypeWrapperStorageForProperty, SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedPropertyGetterBody, BraceStmt *(AccessorDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedPropertySetterBody, + BraceStmt *(AccessorDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index e047e2d097cec..89afc0884a480 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -1508,6 +1508,14 @@ synthesizeTypeWrappedPropertyGetterBody(AccessorDecl *getter, ASTContext &ctx) { : synthesizeInvalidAccessor(getter, ctx); } +static std::pair +synthesizeTypeWrappedPropertySetterBody(AccessorDecl *getter, ASTContext &ctx) { + auto *body = evaluateOrDefault( + ctx.evaluator, SynthesizeTypeWrappedPropertySetterBody{getter}, nullptr); + return body ? std::make_pair(body, /*isTypeChecked=*/false) + : synthesizeInvalidAccessor(getter, ctx); +} + static std::pair synthesizeGetterBody(AccessorDecl *getter, ASTContext &ctx) { auto storage = getter->getStorage(); @@ -1755,6 +1763,11 @@ synthesizeSetterBody(AccessorDecl *setter, ASTContext &ctx) { // Synthesize the setter for a lazy property or property wrapper. if (auto var = dyn_cast(storage)) { + // If the type this stored property belongs to has a type wrapper + // we need to route getter/setter through the wrapper. + if (var->isAccessedViaTypeWrapper()) + return synthesizeTypeWrappedPropertySetterBody(setter, ctx); + if (var->getAttrs().hasAttribute()) { // Lazy property setters write to the underlying storage. if (var->hasObservers()) { diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index c8c6b523fd5e8..4e00d340e9218 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -268,3 +268,31 @@ SynthesizeTypeWrappedPropertyGetterBody::evaluate(Evaluator &evaluator, return BraceStmt::create(ctx, /*lbloc=*/var->getLoc(), body, /*rbloc=*/var->getLoc(), /*implicit=*/true); } + +BraceStmt * +SynthesizeTypeWrappedPropertySetterBody::evaluate(Evaluator &evaluator, + AccessorDecl *setter) const { + assert(setter->isSetter()); + + auto &ctx = setter->getASTContext(); + + auto *var = dyn_cast(setter->getStorage()); + if (!var) + return nullptr; + + auto *subscript = subscriptTypeWrappedProperty(var, setter); + if (!subscript) + return nullptr; + + VarDecl *newValueParam = setter->getParameters()->get(0); + + auto *assignment = new (ctx) AssignExpr( + subscript, /*EqualLoc=*/SourceLoc(), + new (ctx) DeclRefExpr(newValueParam, DeclNameLoc(), /*IsImplicit=*/true), + /*Implicit=*/true); + + ASTNode body = new (ctx) ReturnStmt(SourceLoc(), assignment, + /*isImplicit=*/true); + return BraceStmt::create(ctx, /*lbloc=*/var->getLoc(), body, + /*rbloc=*/var->getLoc(), /*implicit=*/true); +} From 0711d774b70a061e945253008c11f6116b70b3ed Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 28 Jul 2022 10:12:12 -0700 Subject: [PATCH 420/491] [Sema] Don't attempt init synthesis for type wrapped types Compiler cannot synthesize regular memberwise or default initializers for type wrapped types because stored properties of such a type cannot be accessed directly. A special initializer would be synthesized instead, it is going to initialize `$_storage` variable and handle default initialization of stored properties. --- lib/Sema/CodeSynthesis.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index e3b801b85af4c..6ac9b53f4644e 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1113,6 +1113,10 @@ static bool shouldAttemptInitializerSynthesis(const NominalTypeDecl *decl) { if (decl->isInvalid()) return false; + // Don't attempt if the decl has a type wrapper. + if (decl->hasTypeWrapper()) + return false; + return true; } From d50dec4125b6b4b2022cf4b4128789d43b2541df Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 28 Jul 2022 22:20:41 -0700 Subject: [PATCH 421/491] [AST] TypeWrapper: Turn `VarDecl::isAccessibleViaTypeWrapper()` into a cached request --- include/swift/AST/TypeCheckRequests.h | 17 ++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 + lib/Sema/TypeCheckTypeWrapper.cpp | 61 ++++++++++++++++----- 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 157599f760da6..dcbf2b4c3984c 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3622,6 +3622,23 @@ class SynthesizeTypeWrappedPropertySetterBody bool isCached() const { return true; } }; +/// Inject or get `$Storage` type which has all of the stored properties +/// of the given type with a type wrapper. +class IsPropertyAccessedViaTypeWrapper + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + bool evaluate(Evaluator &evaluator, VarDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 48d6cc8f93ef2..8e61ec3c8066f 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -420,3 +420,6 @@ SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedPropertyGetterBody, SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedPropertySetterBody, BraceStmt *(AccessorDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, IsPropertyAccessedViaTypeWrapper, + bool(VarDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 4e00d340e9218..485a340c5c6af 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -54,20 +54,10 @@ static VarDecl *injectProperty(NominalTypeDecl *parent, Identifier name, } bool VarDecl::isAccessedViaTypeWrapper() const { - auto *parent = getDeclContext()->getSelfNominalTypeDecl(); - if (!(parent && parent->hasTypeWrapper())) - return false; - - if (isStatic() || isLet() || !hasStorage()) - return false; - - if (getAttrs().hasAttribute()) - return false; - - if (hasAttachedPropertyWrapper()) - return false; - - return true; + auto *mutableSelf = const_cast(this); + return evaluateOrDefault(getASTContext().evaluator, + IsPropertyAccessedViaTypeWrapper{mutableSelf}, + false); } NominalTypeDecl *NominalTypeDecl::getTypeWrapper() const { @@ -296,3 +286,46 @@ SynthesizeTypeWrappedPropertySetterBody::evaluate(Evaluator &evaluator, return BraceStmt::create(ctx, /*lbloc=*/var->getLoc(), body, /*rbloc=*/var->getLoc(), /*implicit=*/true); } + +bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator, + VarDecl *property) const { + auto *parent = property->getDeclContext()->getSelfNominalTypeDecl(); + if (!(parent && parent->hasTypeWrapper())) + return false; + + // Don't attempt to wrap the `$_storage` property. + if (property->getName() == property->getASTContext().Id_TypeWrapperProperty) + return false; + + if (property->isStatic() || property->isLet()) + return false; + + // `lazy` properties are not wrapped. + if (property->getAttrs().hasAttribute()) + return false; + + // properties with attached property wrappers are not yet supported. + if (property->hasAttachedPropertyWrapper()) + return false; + + // Check whether this is a computed property. + { + auto declaresAccessor = [&](ArrayRef kinds) -> bool { + return llvm::any_of(kinds, [&](const AccessorKind &kind) { + return bool(property->getParsedAccessor(kind)); + }); + }; + + // property has a getter. + if (declaresAccessor( + {AccessorKind::Get, AccessorKind::Read, AccessorKind::Address})) + return false; + + // property has a setter. + if (declaresAccessor({AccessorKind::Set, AccessorKind::Modify, + AccessorKind::MutableAddress})) + return false; + } + + return true; +} From 39f5b69bce53c39a4cbf13ecda17f402621a74b0 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 Jul 2022 09:31:51 -0700 Subject: [PATCH 422/491] [TypeChecker] Synthesize initializer for a type wrapped declaration Synthesize an `init` declaration which is going to initialize type wrapper instance property `$_storage` via user provided values for all stored properties. --- include/swift/AST/Decl.h | 4 + include/swift/AST/KnownIdentifiers.def | 1 + include/swift/AST/TypeCheckRequests.h | 16 ++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 + lib/Sema/CodeSynthesis.cpp | 99 +++++++++++++++++++++ lib/Sema/TypeCheckAttr.cpp | 2 +- lib/Sema/TypeCheckTypeWrapper.cpp | 7 ++ 7 files changed, 131 insertions(+), 1 deletion(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 05f3557c9af91..9e8ed8aa87801 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3760,6 +3760,10 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { /// Return a type wrapper (if any) associated with this type. NominalTypeDecl *getTypeWrapper() const; + /// Get an initializer that could be used to instantiate a + /// type wrapped type. + ConstructorDecl *getTypeWrapperInitializer() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_NominalTypeDecl && diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index 3d9bb1ce996b9..787b2d2ca836c 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -311,6 +311,7 @@ IDENTIFIER_WITH_NAME(builderSelf, "$builderSelf") IDENTIFIER_WITH_NAME(TypeWrapperStorage, "$Storage") IDENTIFIER_WITH_NAME(TypeWrapperProperty, "$_storage") IDENTIFIER(storageKeyPath) +IDENTIFIER(memberwise) #undef IDENTIFIER #undef IDENTIFIER_ diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index dcbf2b4c3984c..d7635ed44c52a 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3639,6 +3639,22 @@ class IsPropertyAccessedViaTypeWrapper bool isCached() const { return true; } }; +class SynthesizeTypeWrapperInitializer + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + ConstructorDecl *evaluate(Evaluator &evaluator, NominalTypeDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 8e61ec3c8066f..933c911826e0f 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -423,3 +423,6 @@ SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedPropertySetterBody, SWIFT_REQUEST(TypeChecker, IsPropertyAccessedViaTypeWrapper, bool(VarDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrapperInitializer, + ConstructorDecl *(NominalTypeDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 6ac9b53f4644e..bfdb9bd63fbf9 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -202,6 +202,9 @@ enum class ImplicitConstructorKind { /// the instance variables from a parameter of the same type and /// name. Memberwise, + /// The constructor of a type wrapped type which is going to + /// initialize underlying storage for all applicable properties. + TypeWrapper, }; /// Create an implicit struct or class constructor. @@ -318,6 +321,24 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl, arg->setInterfaceType(systemTy); arg->setImplicit(); + params.push_back(arg); + } + } else if (ICK == ImplicitConstructorKind::TypeWrapper) { + // Access to the initializer should match that of its parent type. + accessLevel = decl->getEffectiveAccess(); + + for (auto *member : decl->getMembers()) { + auto *var = dyn_cast(member); + if (!(var && var->isAccessedViaTypeWrapper())) + continue; + + auto *arg = new (ctx) ParamDecl(SourceLoc(), Loc, var->getName(), Loc, + var->getName(), decl); + + arg->setSpecifier(ParamSpecifier::Default); + arg->setInterfaceType(var->getValueInterfaceType()); + arg->setImplicit(); + params.push_back(arg); } } @@ -1126,6 +1147,11 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) { return; if (!shouldAttemptInitializerSynthesis(decl)) { + // If declaration is type wrapped, synthesize a + // special initializer that would instantiate storage. + if (decl->hasTypeWrapper()) + (void)decl->getTypeWrapperInitializer(); + decl->setAddedImplicitInitializers(); return; } @@ -1445,3 +1471,76 @@ void swift::addNonIsolatedToSynthesized( ASTContext &ctx = nominal->getASTContext(); value->getAttrs().add(new (ctx) NonisolatedAttr(/*isImplicit=*/true)); } + +static std::pair +synthesizeTypeWrapperInitializerBody(AbstractFunctionDecl *fn, void *context) { + auto *ctor = cast(fn); + auto &ctx = ctor->getASTContext(); + auto *parent = ctor->getDeclContext()->getSelfNominalTypeDecl(); + + // self.$_storage = .init(memberwise: $Storage(...)) + auto *storageType = + evaluateOrDefault(ctx.evaluator, GetTypeWrapperStorage{parent}, nullptr); + assert(storageType); + + auto *typeWrapperVar = + evaluateOrDefault(ctx.evaluator, GetTypeWrapperProperty{parent}, nullptr); + assert(typeWrapperVar); + + auto *storageVarRef = UnresolvedDotExpr::createImplicit( + ctx, + new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()}, + /*Loc=*/DeclNameLoc(), /*Implicit=*/true), + typeWrapperVar->getName()); + + SmallVector arguments; + { + for (auto *param : *ctor->getParameters()) { + arguments.push_back({/*labelLoc=*/SourceLoc(), param->getName(), + new (ctx) DeclRefExpr(param, /*Loc=*/DeclNameLoc(), + /*Implicit=*/true)}); + } + } + + auto *storageInit = CallExpr::createImplicit( + ctx, + TypeExpr::createImplicitForDecl( + /*Loc=*/DeclNameLoc(), storageType, ctor, + ctor->mapTypeIntoContext(storageType->getInterfaceType())), + ArgumentList::createImplicit(ctx, arguments)); + + auto *initRef = new (ctx) UnresolvedMemberExpr( + /*dotLoc=*/SourceLoc(), /*declNameLoc=*/DeclNameLoc(), + DeclNameRef::createConstructor(), /*implicit=*/true); + { initRef->setFunctionRefKind(FunctionRefKind::DoubleApply); } + + // .init($Storage(...)) + Expr *typeWrapperInit = CallExpr::createImplicit( + ctx, initRef, + ArgumentList::forImplicitSingle(ctx, ctx.Id_memberwise, storageInit)); + + auto *assignment = new (ctx) + AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(), typeWrapperInit, + /*Implicit=*/true); + + return {BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), + /*body=*/{assignment}, + /*rbloc=*/ctor->getLoc(), /*implicit=*/true), + /*isTypeChecked=*/false}; +} + +ConstructorDecl * +SynthesizeTypeWrapperInitializer::evaluate(Evaluator &evaluator, + NominalTypeDecl *wrappedType) const { + if (!wrappedType->hasTypeWrapper()) + return nullptr; + + // Create the implicit memberwise constructor. + auto &ctx = wrappedType->getASTContext(); + auto ctor = createImplicitConstructor( + wrappedType, ImplicitConstructorKind::TypeWrapper, ctx); + wrappedType->addMember(ctor); + + ctor->setBodySynthesizer(synthesizeTypeWrapperInitializerBody); + return ctor; +} diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 281362d4c599c..e6af45d283550 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -3634,7 +3634,7 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) { // `init(memberwise:)` { DeclName initName(ctx, DeclBaseName::createConstructor(), - ArrayRef(ctx.getIdentifier("memberwise"))); + ArrayRef(ctx.Id_memberwise)); SmallVector inits; if (findMembersOrDiagnose(initName, inits, diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 485a340c5c6af..7d2a42598085b 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -128,6 +128,13 @@ Type GetTypeWrapperType::evaluate(Evaluator &evaluator, return type; } +ConstructorDecl *NominalTypeDecl::getTypeWrapperInitializer() const { + auto *mutableSelf = const_cast(this); + return evaluateOrDefault(getASTContext().evaluator, + SynthesizeTypeWrapperInitializer{mutableSelf}, + nullptr); +} + NominalTypeDecl * GetTypeWrapperStorage::evaluate(Evaluator &evaluator, NominalTypeDecl *parent) const { From a672db9cb736cd58d588a277575b8214bf08a1ee Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 Jul 2022 11:05:37 -0700 Subject: [PATCH 423/491] [Sema] TypeWrappers: Make sure that type wrapped properties are always "computed" --- lib/Sema/TypeCheckStorage.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 89afc0884a480..2b22fbdee0963 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -3277,6 +3277,8 @@ static void finishStorageImplInfo(AbstractStorageDecl *storage, finishNSManagedImplInfo(var, info); } else if (var->hasAttachedPropertyWrapper()) { finishPropertyWrapperImplInfo(var, info); + } else if (var->isAccessedViaTypeWrapper()) { + info = StorageImplInfo::getMutableComputed(); } } From b3ed4d32ff0d5fc9eaf306edc42183edab6cd5d6 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 Jul 2022 11:33:30 -0700 Subject: [PATCH 424/491] [AST] Make it possible to access type wrapper storage of a var This is important because we need to force existance of the underlying storage at the right moment. --- include/swift/AST/Decl.h | 7 +++++++ lib/Sema/TypeCheckStorage.cpp | 6 +++++- lib/Sema/TypeCheckTypeWrapper.cpp | 10 ++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 9e8ed8aa87801..d2cec186ff43e 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -5564,6 +5564,13 @@ class VarDecl : public AbstractStorageDecl { /// all access to it routed through a type wrapper. bool isAccessedViaTypeWrapper() const; + /// For type wrapped properties (see \c isAccessedViaTypeWrapper) + /// all access is routed through a type wrapper. + /// + /// \returns an underlying type wrapper property which is a + /// storage endpoint for all access to this property. + VarDecl *getUnderlyingTypeWrapperStorage() const; + /// Visit all auxiliary declarations to this VarDecl. /// /// An auxiliary declaration is a declaration synthesized by the compiler to support diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 2b22fbdee0963..0247ffdc02c88 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -104,7 +104,7 @@ static bool hasStoredProperties(NominalTypeDecl *decl) { static void computeLoweredStoredProperties(NominalTypeDecl *decl) { // Just walk over the members of the type, forcing backing storage - // for lazy properties and property wrappers to be synthesized. + // for lazy properties, property and type wrappers to be synthesized. for (auto *member : decl->getMembers()) { auto *var = dyn_cast(member); if (!var || var->isStatic()) @@ -117,6 +117,10 @@ static void computeLoweredStoredProperties(NominalTypeDecl *decl) { (void) var->getPropertyWrapperAuxiliaryVariables(); (void) var->getPropertyWrapperInitializerInfo(); } + + if (var->isAccessedViaTypeWrapper()) { + (void)var->getUnderlyingTypeWrapperStorage(); + } } // If this is an actor, check conformance to the Actor protocol to diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 7d2a42598085b..15c628014fc1c 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -60,6 +60,13 @@ bool VarDecl::isAccessedViaTypeWrapper() const { false); } +VarDecl *VarDecl::getUnderlyingTypeWrapperStorage() const { + auto *mutableSelf = const_cast(this); + return evaluateOrDefault(getASTContext().evaluator, + GetTypeWrapperStorageForProperty{mutableSelf}, + nullptr); +} + NominalTypeDecl *NominalTypeDecl::getTypeWrapper() const { auto *mutableSelf = const_cast(this); return evaluateOrDefault(getASTContext().evaluator, @@ -217,8 +224,7 @@ static SubscriptExpr *subscriptTypeWrappedProperty(VarDecl *var, auto *typeWrapperVar = evaluateOrDefault(ctx.evaluator, GetTypeWrapperProperty{parent}, nullptr); - auto *storageVar = evaluateOrDefault( - ctx.evaluator, GetTypeWrapperStorageForProperty{var}, nullptr); + auto *storageVar = var->getUnderlyingTypeWrapperStorage(); assert(typeWrapperVar); assert(storageVar); From d341c4128c1a97c9695abb8f53788ea04ae165de Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 Jul 2022 11:47:44 -0700 Subject: [PATCH 425/491] [AST] Make it possible to access type wrapper property (storage) This is important because we need to force existance of the underlying storage at the right moment. --- include/swift/AST/Decl.h | 5 +++++ lib/Sema/TypeCheckStorage.cpp | 5 +++++ lib/Sema/TypeCheckTypeWrapper.cpp | 9 +++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index d2cec186ff43e..984bd8d602242 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3760,6 +3760,11 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { /// Return a type wrapper (if any) associated with this type. NominalTypeDecl *getTypeWrapper() const; + /// If this declaration has a type wrapper return a property that + /// is used for all type wrapper related operations (mainly for + /// applicable property access routing). + VarDecl *getTypeWrapperProperty() const; + /// Get an initializer that could be used to instantiate a /// type wrapped type. ConstructorDecl *getTypeWrapperInitializer() const; diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 0247ffdc02c88..710afc6b29905 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -103,6 +103,11 @@ static bool hasStoredProperties(NominalTypeDecl *decl) { } static void computeLoweredStoredProperties(NominalTypeDecl *decl) { + // If declaration has a type wrapper, make sure that + // `$_storage` property is synthesized. + if (decl->hasTypeWrapper()) + (void)decl->getTypeWrapperProperty(); + // Just walk over the members of the type, forcing backing storage // for lazy properties, property and type wrappers to be synthesized. for (auto *member : decl->getMembers()) { diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 15c628014fc1c..bcd356563d498 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -135,6 +135,12 @@ Type GetTypeWrapperType::evaluate(Evaluator &evaluator, return type; } +VarDecl *NominalTypeDecl::getTypeWrapperProperty() const { + auto *mutableSelf = const_cast(this); + return evaluateOrDefault(getASTContext().evaluator, + GetTypeWrapperProperty{mutableSelf}, nullptr); +} + ConstructorDecl *NominalTypeDecl::getTypeWrapperInitializer() const { auto *mutableSelf = const_cast(this); return evaluateOrDefault(getASTContext().evaluator, @@ -222,8 +228,7 @@ static SubscriptExpr *subscriptTypeWrappedProperty(VarDecl *var, if (!(parent && parent->hasTypeWrapper())) return nullptr; - auto *typeWrapperVar = - evaluateOrDefault(ctx.evaluator, GetTypeWrapperProperty{parent}, nullptr); + auto *typeWrapperVar = parent->getTypeWrapperProperty(); auto *storageVar = var->getUnderlyingTypeWrapperStorage(); assert(typeWrapperVar); From 047f51f16272bae2d5506c77a36b7aaaa42ba5c2 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 Jul 2022 12:00:50 -0700 Subject: [PATCH 426/491] [Sema] TypeWrappers: Make sure that synthesized accessors for wrapped vars are not transparent Type wrapped variables loose their storage and are accessed through `$Storage` and synthesized accessors cannot be transparent. --- lib/Sema/TypeCheckStorage.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 710afc6b29905..8b77518476c7c 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2475,6 +2475,12 @@ IsAccessorTransparentRequest::evaluate(Evaluator &evaluator, switch (accessor->getAccessorKind()) { case AccessorKind::Get: + // Synthesized getter for a type wrapped variable is never transparent. + if (auto var = dyn_cast(storage)) { + if (var->isAccessedViaTypeWrapper()) + return false; + } + break; case AccessorKind::Set: @@ -2493,6 +2499,10 @@ IsAccessorTransparentRequest::evaluate(Evaluator &evaluator, PropertyWrapperSynthesizedPropertyKind::Projection)) { break; } + + // Synthesized setter for a type wrapped variable is never transparent. + if (var->isAccessedViaTypeWrapper()) + return false; } if (auto subscript = dyn_cast(storage)) { From 7d28a4fa78388e24f5850d9cf6dab15457141d34 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 1 Aug 2022 11:09:28 -0700 Subject: [PATCH 427/491] [TypeChecker] NFC: Add more property wrapper tests --- .../Inputs/type_wrapper_defs.swift | 26 ++++++++ test/Interpreter/type_wrappers.swift | 39 +++++++++++ test/type/type_wrapper.swift | 65 +++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 test/Interpreter/Inputs/type_wrapper_defs.swift create mode 100644 test/Interpreter/type_wrappers.swift diff --git a/test/Interpreter/Inputs/type_wrapper_defs.swift b/test/Interpreter/Inputs/type_wrapper_defs.swift new file mode 100644 index 0000000000000..3fef5fcbf547b --- /dev/null +++ b/test/Interpreter/Inputs/type_wrapper_defs.swift @@ -0,0 +1,26 @@ +@typeWrapper +public struct Wrapper { + var underlying: S + + public init(memberwise: S) { + print("Wrapper.init(\(memberwise))") + self.underlying = memberwise + } + + public subscript(storageKeyPath path: WritableKeyPath) -> V { + get { + print("in getter") + return underlying[keyPath: path] + } + set { + print("in setter => \(newValue)") + underlying[keyPath: path] = newValue + } + } +} + +@Wrapper +public class Person { + public var name: String + public var projects: [T] +} diff --git a/test/Interpreter/type_wrappers.swift b/test/Interpreter/type_wrappers.swift new file mode 100644 index 0000000000000..d1199227e989d --- /dev/null +++ b/test/Interpreter/type_wrappers.swift @@ -0,0 +1,39 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -parse-as-library -emit-library -emit-module-path %t/type_wrapper_defs.swiftmodule -module-name type_wrapper_defs %S/Inputs/type_wrapper_defs.swift -o %t/%target-library-name(type_wrapper_defs) +// RUN: %target-build-swift -ltype_wrapper_defs -module-name main -I %t -L %t %s -o %t/a.out +// RUN: %target-run %t/a.out | %FileCheck %s + +import type_wrapper_defs + +var p: Person = .init(name: "P", projects: ["A", "B"]) +// CHECK: Wrapper.init($Storage(name: "P", projects: ["A", "B"])) + +print(p.name) +// CHECK: in getter +// CHECK-NEXT: P +print(p.projects) +// CHECK: in getter +// CHECK-NEXT: ["A", "B"] + +p.name = "OtherP" +// CHECK: in setter => OtherP +p.projects.append("C") +// CHECK: in getter +// CHECK-NEXT: in setter => ["A", "B", "C"] + + +func addProjects(p: inout Person, _ newProjects: [T]) { + p.projects.append(contentsOf: newProjects) +} + +addProjects(p: &p, ["D"]) +// CHECK: in getter +// CHECK: in setter => ["A", "B", "C", "D"] + +print(p.name) +// CHECK: in getter +// CHECK-NEXT: OtherP + +print(p.projects) +// CHECK: in getter +// CHECK-NEXT: ["A", "B", "C", "D"] diff --git a/test/type/type_wrapper.swift b/test/type/type_wrapper.swift index d09a64a366ded..85a36fb7a2be9 100644 --- a/test/type/type_wrapper.swift +++ b/test/type/type_wrapper.swift @@ -82,3 +82,68 @@ struct InaccessibleOrInvalidSubscripts { get { true } } } + +@typeWrapper +struct NoopWrapper { + init(memberwise: S) {} + + subscript(storageKeyPath path: KeyPath) -> V { + get { fatalError() } + set { } + } +} + +@NoopWrapper +struct A { + var a: String + var b: Int +} + +@NoopWrapper +class GenericA { + var data: [K: V] +} + +@NoopWrapper // expected-error {{type wrapper attribute 'NoopWrapper' can only be applied to a class, struct}} +protocol P { +} + +@NoopWrapper // expected-error {{type wrapper attribute 'NoopWrapper' can only be applied to a class, struct}} +enum E { + var x: Int { get { 42 } } +} + +func testWrappedTypeAccessChecking() { + let a = A(a: "", b: 42) // synthesized init + let b = GenericA(data: ["ultimate question": 42]) // generic synthesized init + + _ = a.a // Ok + _ = b.data // Ok +} + +struct Parent { + @typeWrapper + struct Wrapper { + init(memberwise: S) {} + + subscript(storageKeyPath path: KeyPath) -> V { + get { fatalError() } + set { } + } + } +} + +func testLocalWithNestedWrapper() { + @Parent.Wrapper + class WithNestedWrapper { + var test: [T] + + var computed: String { + get { "" } + } + } + + let t = WithNestedWrapper(test: [1, 2]) // synthesized init + _ = t.test // Ok + _ = t.computed // Ok +} From a3b54308d2718ced9289b808bfa2bc4d2f66cdc2 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 1 Aug 2022 12:10:38 -0700 Subject: [PATCH 428/491] [Frontend] Mark 'Type Wrappers' as experimental feature that has to be enabled --- include/swift/AST/DiagnosticsSema.def | 3 +++ include/swift/Basic/Features.def | 5 +++++ lib/AST/ASTPrinter.cpp | 4 ++++ lib/Sema/TypeCheckAttr.cpp | 6 ++++++ test/Interpreter/type_wrappers.swift | 2 +- test/type/type_wrapper.swift | 2 +- 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index ffead969c6238..c9cb5ab58258c 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -6480,6 +6480,9 @@ ERROR(move_expression_not_passed_lvalue,none, // MARK: Type Wrappers //------------------------------------------------------------------------------ +ERROR(type_wrappers_are_experimental,none, + "type wrappers are an experimental feature", ()) + ERROR(type_wrapper_attribute_not_allowed_here,none, "type wrapper attribute %0 can only be applied to a class, struct", (Identifier)) diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index e8c1bba7e5f45..f19e543334edd 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -122,6 +122,11 @@ EXPERIMENTAL_FEATURE(SendableCompletionHandlers) /// Enables opaque type erasure without also enabling implict dynamic EXPERIMENTAL_FEATURE(OpaqueTypeErasure) +/// Whether to enable experimental @typeWrapper feature which allows to +/// declare a type that controls access to all stored properties of the +/// wrapped type. +EXPERIMENTAL_FEATURE(TypeWrappers) + #undef EXPERIMENTAL_FEATURE #undef UPCOMING_FEATURE #undef SUPPRESSIBLE_LANGUAGE_FEATURE diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 150df1018aa62..55e769b025591 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -2935,6 +2935,10 @@ static bool usesFeatureSpecializeAttributeWithAvailability(Decl *decl) { return false; } +static bool usesFeatureTypeWrappers(Decl *decl) { + return decl->getAttrs().hasAttribute(); +} + static void suppressingFeatureSpecializeAttributeWithAvailability( PrintOptions &options, llvm::function_ref action) { diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index e6af45d283550..0476ce49dafcd 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -3587,6 +3587,12 @@ void AttributeChecker::visitPropertyWrapperAttr(PropertyWrapperAttr *attr) { } void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) { + if (!Ctx.LangOpts.hasFeature(Feature::TypeWrappers)) { + diagnose(attr->getLocation(), diag::type_wrappers_are_experimental); + attr->setInvalid(); + return; + } + auto nominal = dyn_cast(D); if (!nominal) return; diff --git a/test/Interpreter/type_wrappers.swift b/test/Interpreter/type_wrappers.swift index d1199227e989d..2b8cbf68e82f4 100644 --- a/test/Interpreter/type_wrappers.swift +++ b/test/Interpreter/type_wrappers.swift @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift -parse-as-library -emit-library -emit-module-path %t/type_wrapper_defs.swiftmodule -module-name type_wrapper_defs %S/Inputs/type_wrapper_defs.swift -o %t/%target-library-name(type_wrapper_defs) +// RUN: %target-build-swift -enable-experimental-feature TypeWrappers -parse-as-library -emit-library -emit-module-path %t/type_wrapper_defs.swiftmodule -module-name type_wrapper_defs %S/Inputs/type_wrapper_defs.swift -o %t/%target-library-name(type_wrapper_defs) // RUN: %target-build-swift -ltype_wrapper_defs -module-name main -I %t -L %t %s -o %t/a.out // RUN: %target-run %t/a.out | %FileCheck %s diff --git a/test/type/type_wrapper.swift b/test/type/type_wrapper.swift index 85a36fb7a2be9..150e9d900c7c9 100644 --- a/test/type/type_wrapper.swift +++ b/test/type/type_wrapper.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -enable-experimental-feature TypeWrappers @typeWrapper struct ConcreteTypeWrapper { // expected-error {{type wrapper has to declare a single generic parameter for underlying storage type}} From 39b15662402733c6f37f69ebc999c3e7788e5b33 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 1 Aug 2022 16:38:49 -0700 Subject: [PATCH 429/491] [Sema] TypeWrappers: convert variable init expr into initializer default All of the stored properties are wrapped which means that their initializers are subsummed and moved to the synthesized `init` as default arguments. --- lib/Sema/CodeSynthesis.cpp | 24 ++++++++++ .../Inputs/type_wrapper_defs.swift | 6 +++ test/Interpreter/type_wrappers.swift | 45 +++++++++++++++++++ test/type/type_wrapper.swift | 15 +++++++ 4 files changed, 90 insertions(+) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index bfdb9bd63fbf9..bdf8fd48330e3 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -188,6 +188,28 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var, arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty); } +static void maybeAddTypeWrapperDefaultArg(ParamDecl *arg, VarDecl *var, + ASTContext &ctx) { + assert(var->isAccessedViaTypeWrapper()); + + if (!var->getParentPattern()->getSingleVar()) + return; + + auto *PBD = var->getParentPatternBinding(); + + auto *initExpr = PBD->getInit(/*index=*/0); + if (!initExpr) + return; + + // Type wrapper variables are never initialized directly, + // initialization expression (if any) becomes an default + // argument of the initializer synthesized by the type wrapper. + PBD->setInitializerSubsumed(/*index=*/0); + + arg->setDefaultExpr(initExpr, /*isTypeChecked=*/false); + arg->setDefaultArgumentKind(DefaultArgumentKind::Normal); +} + /// Describes the kind of implicit constructor that will be /// generated. enum class ImplicitConstructorKind { @@ -339,6 +361,8 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl, arg->setInterfaceType(var->getValueInterfaceType()); arg->setImplicit(); + maybeAddTypeWrapperDefaultArg(arg, var, ctx); + params.push_back(arg); } } diff --git a/test/Interpreter/Inputs/type_wrapper_defs.swift b/test/Interpreter/Inputs/type_wrapper_defs.swift index 3fef5fcbf547b..783e76f6dfac9 100644 --- a/test/Interpreter/Inputs/type_wrapper_defs.swift +++ b/test/Interpreter/Inputs/type_wrapper_defs.swift @@ -24,3 +24,9 @@ public class Person { public var name: String public var projects: [T] } + +@Wrapper +public struct PersonWithDefaults { + public var name: String = "" + public var age: Int = 99 +} diff --git a/test/Interpreter/type_wrappers.swift b/test/Interpreter/type_wrappers.swift index 2b8cbf68e82f4..f3ddf6e05da1c 100644 --- a/test/Interpreter/type_wrappers.swift +++ b/test/Interpreter/type_wrappers.swift @@ -37,3 +37,48 @@ print(p.name) print(p.projects) // CHECK: in getter // CHECK-NEXT: ["A", "B", "C", "D"] + +var pDefaults = PersonWithDefaults() +// CHECK: Wrapper.init($Storage(name: "", age: 99)) + +print(pDefaults.name) +// CHECK: in getter +// CHECK: + +print(pDefaults.age) +// CHECK: in getter +// CHECK: 99 + +pDefaults.name = "Actual Name" +// CHECK-NEXT: in setter => Actual Name + +pDefaults.age = 0 +// CHECK-NEXT: in setter => 0 + +print(pDefaults.name) +// CHECK: in getter +// CHECK: Actual Name + +print(pDefaults.age) +// CHECK: in getter +// CHECK: 0 + +let pDefaultsAge = PersonWithDefaults(name: "Actual Name") + +print(pDefaultsAge.name) +// CHECK: in getter +// CHECK: Actual Name + +print(pDefaultsAge.age) +// CHECK: in getter +// CHECK: 99 + +let pDefaultsName = PersonWithDefaults(age: 31337) + +print(pDefaultsName.name) +// CHECK: in getter +// CHECK: + +print(pDefaultsName.age) +// CHECK: in getter +// CHECK: 31337 diff --git a/test/type/type_wrapper.swift b/test/type/type_wrapper.swift index 150e9d900c7c9..cd3dc82120959 100644 --- a/test/type/type_wrapper.swift +++ b/test/type/type_wrapper.swift @@ -147,3 +147,18 @@ func testLocalWithNestedWrapper() { _ = t.test // Ok _ = t.computed // Ok } + +func testTypeWrapperWithDefaults() { + @NoopWrapper + struct A { + var question: String = "Ultimate Question" + var answer: Int = 42 + } + + let a = A() + _ = a.question + _ = a.answer + + _ = A(question: "") + _ = A(answer: 0) +} From ecc363d3f78ed9f9fdfc81120f5ed7b17cc92def Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 10 Aug 2022 11:00:40 -0700 Subject: [PATCH 430/491] [Sema] TypeWrappers: Allow wrapping stored properties with attached property wrappers Type wrapper doesn't wrap anything expect to a private backing storage property. This means that type wrapper is applied first and subsequent `.wrappedValue` and/or `.projectedValue` is referenced for the returned property wrapper type. --- lib/Sema/TypeCheckStorage.cpp | 8 ++++++-- lib/Sema/TypeCheckTypeWrapper.cpp | 24 +++++++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 8b77518476c7c..b2a23fa501f45 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -923,7 +923,9 @@ static Expr *buildStorageReference(AccessorDecl *accessor, underlyingVars.push_back({ wrappedValue, isWrapperRefLValue }); } } - semantics = AccessSemantics::DirectToStorage; + semantics = backing->isAccessedViaTypeWrapper() + ? AccessSemantics::DirectToImplementation + : AccessSemantics::DirectToStorage; selfAccessKind = SelfAccessorKind::Peer; break; } @@ -952,7 +954,9 @@ static Expr *buildStorageReference(AccessorDecl *accessor, { var->getAttachedPropertyWrapperTypeInfo(0).projectedValueVar, isLValue }); } - semantics = AccessSemantics::DirectToStorage; + semantics = backing->isAccessedViaTypeWrapper() + ? AccessSemantics::DirectToImplementation + : AccessSemantics::DirectToStorage; selfAccessKind = SelfAccessorKind::Peer; break; } diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index bcd356563d498..2e08c13701601 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -322,9 +322,27 @@ bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator, if (property->getAttrs().hasAttribute()) return false; - // properties with attached property wrappers are not yet supported. - if (property->hasAttachedPropertyWrapper()) - return false; + // Properties with attached property wrappers are not considered + // accessible via type wrapper directly, only their backing storage is. + { + // Wrapped property itself `` + if (property->hasAttachedPropertyWrapper()) + return false; + + // Projection - `$` + if (property->getOriginalWrappedProperty( + PropertyWrapperSynthesizedPropertyKind::Projection)) + return false; + + // Backing storage (or wrapper property) - `_`. + // + // This is the only thing that wrapper needs to handle because + // all access to the wrapped variable and it's projection + // is routed through it. + if (property->getOriginalWrappedProperty( + PropertyWrapperSynthesizedPropertyKind::Backing)) + return true; + } // Check whether this is a computed property. { From 20a52d2f97c3f871b9c41327d1cd2cb495da220d Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 10 Aug 2022 13:46:32 -0700 Subject: [PATCH 431/491] [Sema] TypeWrappers/NFC: Move initializer synthesis into a request --- include/swift/AST/TypeCheckRequests.h | 16 ++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 3 + lib/Sema/CodeSynthesis.cpp | 64 ++------------------- lib/Sema/TypeCheckTypeWrapper.cpp | 55 ++++++++++++++++++ 4 files changed, 80 insertions(+), 58 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index d7635ed44c52a..9a038cd292b4e 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3655,6 +3655,22 @@ class SynthesizeTypeWrapperInitializer bool isCached() const { return true; } }; +class SynthesizeTypeWrapperInitializerBody + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + BraceStmt *evaluate(Evaluator &evaluator, ConstructorDecl *) const; + +public: + bool isCached() const { return true; } +}; + void simple_display(llvm::raw_ostream &out, ASTNode node); void simple_display(llvm::raw_ostream &out, Type value); void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR); diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 933c911826e0f..6308c13f30747 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -426,3 +426,6 @@ SWIFT_REQUEST(TypeChecker, IsPropertyAccessedViaTypeWrapper, SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrapperInitializer, ConstructorDecl *(NominalTypeDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrapperInitializerBody, + BraceStmt *(ConstructorDecl *), + Cached, NoLocationInfo) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index bdf8fd48330e3..acc0f53a8ac1e 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1496,63 +1496,6 @@ void swift::addNonIsolatedToSynthesized( value->getAttrs().add(new (ctx) NonisolatedAttr(/*isImplicit=*/true)); } -static std::pair -synthesizeTypeWrapperInitializerBody(AbstractFunctionDecl *fn, void *context) { - auto *ctor = cast(fn); - auto &ctx = ctor->getASTContext(); - auto *parent = ctor->getDeclContext()->getSelfNominalTypeDecl(); - - // self.$_storage = .init(memberwise: $Storage(...)) - auto *storageType = - evaluateOrDefault(ctx.evaluator, GetTypeWrapperStorage{parent}, nullptr); - assert(storageType); - - auto *typeWrapperVar = - evaluateOrDefault(ctx.evaluator, GetTypeWrapperProperty{parent}, nullptr); - assert(typeWrapperVar); - - auto *storageVarRef = UnresolvedDotExpr::createImplicit( - ctx, - new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()}, - /*Loc=*/DeclNameLoc(), /*Implicit=*/true), - typeWrapperVar->getName()); - - SmallVector arguments; - { - for (auto *param : *ctor->getParameters()) { - arguments.push_back({/*labelLoc=*/SourceLoc(), param->getName(), - new (ctx) DeclRefExpr(param, /*Loc=*/DeclNameLoc(), - /*Implicit=*/true)}); - } - } - - auto *storageInit = CallExpr::createImplicit( - ctx, - TypeExpr::createImplicitForDecl( - /*Loc=*/DeclNameLoc(), storageType, ctor, - ctor->mapTypeIntoContext(storageType->getInterfaceType())), - ArgumentList::createImplicit(ctx, arguments)); - - auto *initRef = new (ctx) UnresolvedMemberExpr( - /*dotLoc=*/SourceLoc(), /*declNameLoc=*/DeclNameLoc(), - DeclNameRef::createConstructor(), /*implicit=*/true); - { initRef->setFunctionRefKind(FunctionRefKind::DoubleApply); } - - // .init($Storage(...)) - Expr *typeWrapperInit = CallExpr::createImplicit( - ctx, initRef, - ArgumentList::forImplicitSingle(ctx, ctx.Id_memberwise, storageInit)); - - auto *assignment = new (ctx) - AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(), typeWrapperInit, - /*Implicit=*/true); - - return {BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), - /*body=*/{assignment}, - /*rbloc=*/ctor->getLoc(), /*implicit=*/true), - /*isTypeChecked=*/false}; -} - ConstructorDecl * SynthesizeTypeWrapperInitializer::evaluate(Evaluator &evaluator, NominalTypeDecl *wrappedType) const { @@ -1565,6 +1508,11 @@ SynthesizeTypeWrapperInitializer::evaluate(Evaluator &evaluator, wrappedType, ImplicitConstructorKind::TypeWrapper, ctx); wrappedType->addMember(ctor); - ctor->setBodySynthesizer(synthesizeTypeWrapperInitializerBody); + auto *body = evaluateOrDefault( + evaluator, SynthesizeTypeWrapperInitializerBody{ctor}, nullptr); + if (!body) + return nullptr; + + ctor->setBody(body, AbstractFunctionDecl::BodyKind::Parsed); return ctor; } diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 2e08c13701601..2110cb5ce84df 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -365,3 +365,58 @@ bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator, return true; } + +BraceStmt * +SynthesizeTypeWrapperInitializerBody::evaluate(Evaluator &evaluator, + ConstructorDecl *ctor) const { + auto &ctx = ctor->getASTContext(); + auto *parent = ctor->getDeclContext()->getSelfNominalTypeDecl(); + + // self.$_storage = .init(memberwise: $Storage(...)) + auto *storageType = + evaluateOrDefault(ctx.evaluator, GetTypeWrapperStorage{parent}, nullptr); + assert(storageType); + + auto *typeWrapperVar = parent->getTypeWrapperProperty(); + assert(typeWrapperVar); + + auto *storageVarRef = UnresolvedDotExpr::createImplicit( + ctx, + new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()}, + /*Loc=*/DeclNameLoc(), /*Implicit=*/true), + typeWrapperVar->getName()); + + SmallVector arguments; + { + for (auto *param : *ctor->getParameters()) { + arguments.push_back({/*labelLoc=*/SourceLoc(), param->getName(), + new (ctx) DeclRefExpr(param, /*Loc=*/DeclNameLoc(), + /*Implicit=*/true)}); + } + } + + auto *storageInit = CallExpr::createImplicit( + ctx, + TypeExpr::createImplicitForDecl( + /*Loc=*/DeclNameLoc(), storageType, ctor, + ctor->mapTypeIntoContext(storageType->getInterfaceType())), + ArgumentList::createImplicit(ctx, arguments)); + + auto *initRef = new (ctx) UnresolvedMemberExpr( + /*dotLoc=*/SourceLoc(), /*declNameLoc=*/DeclNameLoc(), + DeclNameRef::createConstructor(), /*implicit=*/true); + { initRef->setFunctionRefKind(FunctionRefKind::DoubleApply); } + + // .init($Storage(...)) + Expr *typeWrapperInit = CallExpr::createImplicit( + ctx, initRef, + ArgumentList::forImplicitSingle(ctx, ctx.Id_memberwise, storageInit)); + + auto *assignment = new (ctx) + AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(), typeWrapperInit, + /*Implicit=*/true); + + return BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), + /*body=*/{assignment}, + /*rbloc=*/ctor->getLoc(), /*implicit=*/true); +} From bf2519aed97dde80643138d8faf7e1401ab5b53c Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 11 Aug 2022 09:56:15 -0700 Subject: [PATCH 432/491] [Sema] Allow implicit parameter decls to have property wrapper attributes --- lib/AST/Decl.cpp | 3 ++- lib/Sema/TypeCheckStorage.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 4f409449baa93..288c35c9ccd5e 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -6733,7 +6733,8 @@ bool VarDecl::hasStorageOrWrapsStorage() const { } void VarDecl::visitAuxiliaryDecls(llvm::function_ref visit) const { - if (getDeclContext()->isTypeContext() || isImplicit()) + if (getDeclContext()->isTypeContext() || + (isImplicit() && !isa(this))) return; if (getAttrs().hasAttribute()) { diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index b2a23fa501f45..ee5e68e8f2841 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2981,7 +2981,8 @@ PropertyWrapperAuxiliaryVariablesRequest::evaluate(Evaluator &evaluator, PropertyWrapperInitializerInfo PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator, VarDecl *var) const { - if (!var->hasAttachedPropertyWrapper() || var->isImplicit()) + if (!var->hasAttachedPropertyWrapper() || + (var->isImplicit() && !isa(var))) return PropertyWrapperInitializerInfo(); auto wrapperInfo = var->getAttachedPropertyWrapperTypeInfo(0); From 0500f35537e7fced047814ab681a0fe9d2f6ad24 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 12 Aug 2022 14:09:19 -0700 Subject: [PATCH 433/491] [Sema] TypeWrappers: Synthesize init parameters for property wrapped members Since properties with property wrappers are not supported, default init synthesis needs to handle them as well by using correct interface type depending on outer wrapper capabilities and setting correct default expression. --- lib/Sema/CodeSynthesis.cpp | 77 ++++- lib/Sema/TypeCheckTypeWrapper.cpp | 14 +- .../Inputs/type_wrapper_defs.swift | 91 ++++++ test/Interpreter/type_wrappers.swift | 264 ++++++++++++++++++ test/type/type_wrapper.swift | 170 +++++++++++ 5 files changed, 606 insertions(+), 10 deletions(-) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index acc0f53a8ac1e..b48432a0dc568 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -190,23 +190,44 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var, static void maybeAddTypeWrapperDefaultArg(ParamDecl *arg, VarDecl *var, ASTContext &ctx) { - assert(var->isAccessedViaTypeWrapper()); + assert(var->isAccessedViaTypeWrapper() || var->hasAttachedPropertyWrapper()); - if (!var->getParentPattern()->getSingleVar()) + if (!(var->getParentPattern() && var->getParentPattern()->getSingleVar())) return; auto *PBD = var->getParentPatternBinding(); - auto *initExpr = PBD->getInit(/*index=*/0); + Expr *initExpr = nullptr; + + if (var->hasAttachedPropertyWrapper()) { + auto initInfo = var->getPropertyWrapperInitializerInfo(); + + if (initInfo.hasInitFromWrappedValue()) { + initExpr = + initInfo.getWrappedValuePlaceholder()->getOriginalWrappedValue(); + } + } else { + initExpr = PBD->getInit(/*index=*/0); + } + if (!initExpr) return; // Type wrapper variables are never initialized directly, // initialization expression (if any) becomes an default // argument of the initializer synthesized by the type wrapper. - PBD->setInitializerSubsumed(/*index=*/0); + { + // Since type wrapper is applied to backing property, that's + // the the initializer it subsumes. + if (var->hasAttachedPropertyWrapper()) { + auto *backingVar = var->getPropertyWrapperBackingProperty(); + PBD = backingVar->getParentPatternBinding(); + } - arg->setDefaultExpr(initExpr, /*isTypeChecked=*/false); + PBD->setInitializerSubsumed(/*index=*/0); + } + + arg->setDefaultExpr(initExpr, PBD->isInitializerChecked(/*index=*/0)); arg->setDefaultArgumentKind(DefaultArgumentKind::Normal); } @@ -354,11 +375,51 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl, if (!(var && var->isAccessedViaTypeWrapper())) continue; - auto *arg = new (ctx) ParamDecl(SourceLoc(), Loc, var->getName(), Loc, - var->getName(), decl); + Identifier argName = var->getName(); + Identifier paramName = argName; + + auto paramInterfaceType = var->getValueInterfaceType(); + DeclAttributes attrs; + + // If this is a backing storage of a property wrapped property + // let's use wrapped property as a parameter and synthesize + // appropriate property wrapper initialization upon assignment. + if (auto *wrappedVar = var->getOriginalWrappedProperty( + PropertyWrapperSynthesizedPropertyKind::Backing)) { + // If there is `init(wrappedValue:)` or default value for a wrapped + // property we should use wrapped type, otherwise let's proceed with + // wrapper type. + if (wrappedVar->isPropertyMemberwiseInitializedWithWrappedType()) { + var = wrappedVar; + // If parameter have to get wrapped type, let's re-map both argument + // and parameter name to match wrapped property and let property + // wrapper attributes generate wrapped value and projection variables. + argName = wrappedVar->getName(); + paramName = argName; + + paramInterfaceType = var->getPropertyWrapperInitValueInterfaceType(); + // The parameter needs to have all of the property wrapper + // attributes to generate projection and wrapper variables. + for (auto *attr : wrappedVar->getAttachedPropertyWrappers()) + attrs.add(attr); + } else { + // If parameter has to have wrapper type then argument type should + // match that of a wrapped property but parameter name stays the same + // since it represents the type of backing storage and could be passed + // to `$Storage` constructor directly. + argName = wrappedVar->getName(); + } + } + + if (!paramInterfaceType || paramInterfaceType->hasError()) + continue; + + auto *arg = + new (ctx) ParamDecl(SourceLoc(), Loc, argName, Loc, paramName, decl); + arg->getAttrs().add(attrs); arg->setSpecifier(ParamSpecifier::Default); - arg->setInterfaceType(var->getValueInterfaceType()); + arg->setInterfaceType(paramInterfaceType); arg->setImplicit(); maybeAddTypeWrapperDefaultArg(arg, var, ctx); diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 2110cb5ce84df..cc5838f3e345c 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -389,8 +389,18 @@ SynthesizeTypeWrapperInitializerBody::evaluate(Evaluator &evaluator, SmallVector arguments; { for (auto *param : *ctor->getParameters()) { - arguments.push_back({/*labelLoc=*/SourceLoc(), param->getName(), - new (ctx) DeclRefExpr(param, /*Loc=*/DeclNameLoc(), + VarDecl *arg = param; + + // type wrappers wrap only backing storage of a wrapped + // property, so in this case we need to pass `_` to + // `$Storage` constructor. + if (param->hasAttachedPropertyWrapper()) { + arg = param->getPropertyWrapperBackingProperty(); + (void)param->getPropertyWrapperBackingPropertyType(); + } + + arguments.push_back({/*labelLoc=*/SourceLoc(), arg->getName(), + new (ctx) DeclRefExpr(arg, /*Loc=*/DeclNameLoc(), /*Implicit=*/true)}); } } diff --git a/test/Interpreter/Inputs/type_wrapper_defs.swift b/test/Interpreter/Inputs/type_wrapper_defs.swift index 783e76f6dfac9..99dece208c0d9 100644 --- a/test/Interpreter/Inputs/type_wrapper_defs.swift +++ b/test/Interpreter/Inputs/type_wrapper_defs.swift @@ -19,6 +19,64 @@ public struct Wrapper { } } +@propertyWrapper +public struct PropWrapper { + public var value: Value + + public init(wrappedValue: Value) { + self.value = wrappedValue + } + + public var projectedValue: Self { return self } + + public var wrappedValue: Value { + get { + self.value + } + set { + self.value = newValue + } + } +} + +@propertyWrapper +public struct PropWrapperWithoutInit { + public var value: Value + + public init(value: Value) { + self.value = value + } + + public var projectedValue: Self { return self } + + public var wrappedValue: Value { + get { + self.value + } + set { + self.value = newValue + } + } +} + +@propertyWrapper +public struct PropWrapperWithoutProjection { + public var value: Value + + public init(wrappedValue: Value) { + self.value = wrappedValue + } + + public var wrappedValue: Value { + get { + self.value + } + set { + self.value = newValue + } + } +} + @Wrapper public class Person { public var name: String @@ -30,3 +88,36 @@ public struct PersonWithDefaults { public var name: String = "" public var age: Int = 99 } + +@Wrapper +public struct PropWrapperTest { + @PropWrapper public var test: Int +} + +@Wrapper +public struct DefaultedPropWrapperTest { + @PropWrapper public var test: Int = 0 +} + +@Wrapper +public struct DefaultedPropWrapperWithArgTest { + @PropWrapper(wrappedValue: 3) public var test: Int +} + +@Wrapper +public struct PropWrapperNoInitTest { + @PropWrapperWithoutInit public var a: Int + @PropWrapperWithoutInit(value: "b") public var b: String +} + +@Wrapper +public struct PropWrapperNoProjectionTest { + @PropWrapperWithoutProjection public var a: Int = 0 + @PropWrapperWithoutProjection(wrappedValue: PropWrapper(wrappedValue: "b")) @PropWrapper public var b: String +} + +@Wrapper +public struct ComplexPropWrapperTest { + @PropWrapper public var a: [String] = ["a"] + @PropWrapperWithoutInit(value: PropWrapper(wrappedValue: [1, 2, 3])) @PropWrapper public var b: [Int] +} diff --git a/test/Interpreter/type_wrappers.swift b/test/Interpreter/type_wrappers.swift index f3ddf6e05da1c..f2b8b796bba71 100644 --- a/test/Interpreter/type_wrappers.swift +++ b/test/Interpreter/type_wrappers.swift @@ -82,3 +82,267 @@ print(pDefaultsName.name) print(pDefaultsName.age) // CHECK: in getter // CHECK: 31337 + +func testPropertyWrappers() { + var wrapped1 = PropWrapperTest(test: 42) + // CHECK: Wrapper.init($Storage(_test: type_wrapper_defs.PropWrapper(value: 42))) + do { + print(wrapped1.test) + // CHECK: in getter + // CHECK-NEXT: 42 + + wrapped1.test = 0 + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper(value: 0) + + print(wrapped1.test) + // CHECK: in getter + // CHECK-NEXT: 0 + } + + var wrapped2 = DefaultedPropWrapperTest() + // CHECK: Wrapper.init($Storage(_test: type_wrapper_defs.PropWrapper(value: 0))) + do { + print(wrapped2.test) + // CHECK: in getter + // CHECK-NEXT: 0 + + wrapped2.test = 42 + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper(value: 42) + + print(wrapped2.test) + // CHECK: in getter + // CHECK-NEXT: 42 + } + + var wrapped3 = DefaultedPropWrapperTest(test: 1) + // CHECK: Wrapper.init($Storage(_test: type_wrapper_defs.PropWrapper(value: 1))) + do { + print(wrapped3.test) + // CHECK: in getter + // CHECK-NEXT: 1 + + wrapped3.test = 31337 + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper(value: 31337) + + print(wrapped3.test) + // CHECK: in getter + // CHECK-NEXT: 31337 + } + + var wrapped4 = DefaultedPropWrapperWithArgTest() + // CHECK: Wrapper.init($Storage(_test: type_wrapper_defs.PropWrapper(value: 3))) + do { + print(wrapped4.test) + // CHECK: in getter + // CHECK-NEXT: 3 + + wrapped4.test = 0 + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper(value: 0) + + print(wrapped4.test) + // CHECK: in getter + // CHECK-NEXT: 0 + } + + var wrapped5 = PropWrapperNoInitTest(a: PropWrapperWithoutInit(value: 1)) + // CHECK: Wrapper.init($Storage(_a: type_wrapper_defs.PropWrapperWithoutInit(value: 1), _b: type_wrapper_defs.PropWrapperWithoutInit(value: "b"))) + do { + print(wrapped5.a) + // CHECK: in getter + // CHECK-NEXT: 1 + + print(wrapped5.b) + // CHECK: in getter + // CHECK-NEXT: b + + wrapped5.a = 42 + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutInit(value: 42) + + wrapped5.b = "not b" + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutInit(value: "not b") + + print(wrapped5.a) + // CHECK: in getter + // CHECK-NEXT: 42 + + print(wrapped5.b) + // CHECK: in getter + // CHECK-NEXT: not b + } + + var wrapped6 = PropWrapperNoInitTest(a: PropWrapperWithoutInit(value: 1), b: PropWrapperWithoutInit(value: "hello")) + // CHECK: Wrapper.init($Storage(_a: type_wrapper_defs.PropWrapperWithoutInit(value: 1), _b: type_wrapper_defs.PropWrapperWithoutInit(value: "hello"))) + do { + print(wrapped6.a) + // CHECK: in getter + // CHECK-NEXT: 1 + + print(wrapped6.b) + // CHECK: in getter + // CHECK-NEXT: hello + + wrapped6.a = 42 + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutInit(value: 42) + + wrapped6.b = "b" + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutInit(value: "b") + + print(wrapped6.a) + // CHECK: in getter + // CHECK-NEXT: 42 + + print(wrapped6.b) + // CHECK: in getter + // CHECK-NEXT: b + } + + var wrapped7 = ComplexPropWrapperTest() + // CHECK: Wrapper.init($Storage(_a: type_wrapper_defs.PropWrapper>(value: ["a"]), _b: type_wrapper_defs.PropWrapperWithoutInit>>(value: type_wrapper_defs.PropWrapper>(value: [1, 2, 3])))) + do { + print(wrapped7.a) + // CHECK: in getter + // CHECK-NEXT: ["a"] + + print(wrapped7.b) + // CHECK: in getter + // CHECK-NEXT: [1, 2, 3] + + wrapped7.a = ["a", "b", "c"] + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper>(value: ["a", "b", "c"]) + + print(wrapped7.a) + // CHECK: in getter + // CHECK-NEXT: ["a", "b", "c"] + + wrapped7.b = [0] + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutInit>>(value: type_wrapper_defs.PropWrapper>(value: [0])) + + print(wrapped7.b) + // CHECK: in getter + // CHECK-NEXT: [0] + } + + var wrapped8 = ComplexPropWrapperTest(a: ["a", "b"]) + // CHECK: Wrapper.init($Storage(_a: type_wrapper_defs.PropWrapper>(value: ["a", "b"]), _b: type_wrapper_defs.PropWrapperWithoutInit>>(value: type_wrapper_defs.PropWrapper>(value: [1, 2, 3])))) + do { + print(wrapped8.a) + // CHECK: in getter + // CHECK-NEXT: ["a", "b"] + + print(wrapped8.b) + // CHECK: in getter + // CHECK-NEXT: [1, 2, 3] + + wrapped8.a = ["a", "b", "c"] + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper>(value: ["a", "b", "c"]) + + print(wrapped8.a) + // CHECK: in getter + // CHECK-NEXT: ["a", "b", "c"] + + wrapped8.b = [0] + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutInit>>(value: type_wrapper_defs.PropWrapper>(value: [0])) + + print(wrapped8.b) + // CHECK: in getter + // CHECK-NEXT: [0] + } + + var wrapped9 = ComplexPropWrapperTest(b: PropWrapperWithoutInit(value: PropWrapper(wrappedValue: [0]))) + // CHECK: Wrapper.init($Storage(_a: type_wrapper_defs.PropWrapper>(value: ["a"]), _b: type_wrapper_defs.PropWrapperWithoutInit>>(value: type_wrapper_defs.PropWrapper>(value: [0])))) + do { + print(wrapped9.a) + // CHECK: in getter + // CHECK-NEXT: ["a"] + + print(wrapped9.b) + // CHECK: in getter + // CHECK-NEXT: [0] + + wrapped9.a = ["a", "b", "c"] + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper>(value: ["a", "b", "c"]) + + print(wrapped9.a) + // CHECK: in getter + // CHECK-NEXT: ["a", "b", "c"] + + wrapped9.b = [1, 2, 3] + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutInit>>(value: type_wrapper_defs.PropWrapper>(value: [1, 2, 3])) + + print(wrapped9.b) + // CHECK: in getter + // CHECK-NEXT: [1, 2, 3] + } + + var wrapped10 = ComplexPropWrapperTest(a: [], b: PropWrapperWithoutInit(value: PropWrapper(wrappedValue: [0]))) + // CHECK: Wrapper.init($Storage(_a: type_wrapper_defs.PropWrapper>(value: []), _b: type_wrapper_defs.PropWrapperWithoutInit>>(value: type_wrapper_defs.PropWrapper>(value: [0])))) + do { + print(wrapped10.a) + // CHECK: in getter + // CHECK-NEXT: [] + + print(wrapped10.b) + // CHECK: in getter + // CHECK-NEXT: [0] + + wrapped10.a = ["a", "b", "c"] + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper>(value: ["a", "b", "c"]) + + print(wrapped10.a) + // CHECK: in getter + // CHECK-NEXT: ["a", "b", "c"] + + wrapped10.b = [1, 2, 3] + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutInit>>(value: type_wrapper_defs.PropWrapper>(value: [1, 2, 3])) + + print(wrapped10.b) + // CHECK: in getter + // CHECK-NEXT: [1, 2, 3] + } + + var wrapped11 = PropWrapperNoProjectionTest() + // CHECK: Wrapper.init($Storage(_a: type_wrapper_defs.PropWrapperWithoutProjection(value: 0), _b: type_wrapper_defs.PropWrapperWithoutProjection>(value: type_wrapper_defs.PropWrapper(value: "b")))) + do { + print(wrapped11.a) + // CHECK: in getter + // CHECK-NEXT: 0 + + print(wrapped11.b) + // CHECK: in getter + // CHECK-NEXT: b + + wrapped11.a = 42 + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutProjection(value: 42) + + wrapped11.b = "not b" + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapperWithoutProjection>(value: type_wrapper_defs.PropWrapper(value: "not b")) + + print(wrapped11.a) + // CHECK: in getter + // CHECK-NEXT: 42 + + print(wrapped11.b) + // CHECK: in getter + // CHECK-NEXT: not b + } +} + +testPropertyWrappers() diff --git a/test/type/type_wrapper.swift b/test/type/type_wrapper.swift index cd3dc82120959..d906aeb54363b 100644 --- a/test/type/type_wrapper.swift +++ b/test/type/type_wrapper.swift @@ -162,3 +162,173 @@ func testTypeWrapperWithDefaults() { _ = A(question: "") _ = A(answer: 0) } + +/// Properties with property wrappers + +@propertyWrapper +struct Wrapper { + public var value: Value + + init(wrappedValue: Value) { + self.value = wrappedValue + } + + var projectedValue: Self { return self } + + var wrappedValue: Value { + get { + self.value + } + set { + self.value = newValue + } + } +} + +@propertyWrapper +struct WrapperWithoutInit { + public var value: Value + + var projectedValue: Self { return self } + + var wrappedValue: Value { + get { + self.value + } + set { + self.value = newValue + } + } +} + +@propertyWrapper +struct WrapperWithoutProjection { + public var value: Value + + init(wrappedValue: Value) { + self.value = wrappedValue + } + + var wrappedValue: Value { + get { + self.value + } + set { + self.value = newValue + } + } +} + +func propertyWrapperTests() { + @NoopWrapper + struct WrapperTest { + @Wrapper var test: Int + } + + _ = WrapperTest(test: 42) // Ok + + @NoopWrapper + struct DefaultedWrapperTest { + @Wrapper var test: Int = 42 + } + + _ = DefaultedWrapperTest() // Ok + _ = DefaultedWrapperTest(test: 42) // Ok + + @NoopWrapper + struct NoInitTest { + @WrapperWithoutInit var test: Int + } + + _ = NoInitTest(test: WrapperWithoutInit(value: 42)) // Ok + + @NoopWrapper + struct DefaultedNoInitTest { + @WrapperWithoutInit(value: 42) var test: Int + } + + _ = DefaultedNoInitTest() // Ok + _ = DefaultedNoInitTest(test: WrapperWithoutInit(value: 0)) // Ok + + @NoopWrapper + struct NoProjection { + @WrapperWithoutProjection var test: Int // expected-note {{'test' declared here}} + } + + let noProj = NoProjection(test: 42) // Ok + _ = noProj.test // Ok + _ = noProj.$test // expected-error {{value of type 'NoProjection' has no member '$test'}} + + @NoopWrapper + struct NoInitComposition1 { + @Wrapper @WrapperWithoutInit var test: Int + } + + _ = NoInitComposition1(test: Wrapper(wrappedValue: WrapperWithoutInit(value: 42))) // Ok + + @NoopWrapper + struct NoInitComposition2 { + @WrapperWithoutInit @Wrapper var test: Int + } + + _ = NoInitComposition2(test: WrapperWithoutInit(value: Wrapper(wrappedValue: 42))) // Ok + + @NoopWrapper + struct NoInitCompositionWithDefault { + @Wrapper(wrappedValue: WrapperWithoutInit(value: 42)) @WrapperWithoutInit var test: Int + } + + _ = NoInitCompositionWithDefault() // Ok + _ = NoInitCompositionWithDefault(test: Wrapper(wrappedValue: WrapperWithoutInit(value: 0))) // Ok + + @NoopWrapper + struct Complex1 { + @Wrapper var a: Int = 42 + var b: String = "" + } + + _ = Complex1() + _ = Complex1(b: "hello") // Ok + _ = Complex1(a: 0) // Ok + _ = Complex1(a: 0, b: "") // Ok + + @NoopWrapper + struct Complex2 { + @Wrapper var a: Int = 42 + @WrapperWithoutInit @Wrapper var b: String + } + + _ = Complex2(b: WrapperWithoutInit(value: Wrapper(wrappedValue: "hello"))) // Ok + _ = Complex2(a: 0, b: WrapperWithoutInit(value: Wrapper(wrappedValue: "hello"))) // Ok + _ = Complex2(b: WrapperWithoutInit(value: Wrapper(wrappedValue: "wrong")), a: 0) // expected-error {{argument 'a' must precede argument 'b'}} + + @NoopWrapper + struct Complex3 { + @Wrapper var a: Int = 42 + var b: String = "" + @WrapperWithoutProjection var c: [Int] = [] + } + + _ = Complex3() + _ = Complex3(b: "hello") // Ok + _ = Complex3(c: [1, 2, 3]) // Ok + _ = Complex3(a: 0) // Ok + _ = Complex3(a: 0, b: "") // Ok + _ = Complex3(a: 0, b: "", c: [1, 2, 3]) // Ok + + @NoopWrapper + struct Invalid { + @Wrapper(wrappedValue: "") var a: Int + // expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'Int'}} + + @Wrapper var b: Int = "" + // expected-error@-1 {{cannot convert value of type 'String' to specified type 'Int'}} + + @Wrapper(wrappedValue: 0) var c: Int = 1 + // expected-error@-1 {{extra argument 'wrappedValue' in call}} + + @Wrapper(other: "") var d: Float + // expected-error@-1 {{incorrect argument label in call (have 'other:', expected 'wrappedValue:')}} + // expected-error@-2 {{cannot convert value of type 'String' to expected argument type 'Float'}} + } +} From 8c0f6e15cd352c1a74165ca6bbc75e8f2d72b1e7 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 18 Aug 2022 12:51:56 -0700 Subject: [PATCH 434/491] [TypeWrappers] NFC: Fix type wrapper executable test on Linux --- test/Interpreter/type_wrappers.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/Interpreter/type_wrappers.swift b/test/Interpreter/type_wrappers.swift index f2b8b796bba71..d6bcc9f4665f9 100644 --- a/test/Interpreter/type_wrappers.swift +++ b/test/Interpreter/type_wrappers.swift @@ -1,7 +1,10 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift -enable-experimental-feature TypeWrappers -parse-as-library -emit-library -emit-module-path %t/type_wrapper_defs.swiftmodule -module-name type_wrapper_defs %S/Inputs/type_wrapper_defs.swift -o %t/%target-library-name(type_wrapper_defs) -// RUN: %target-build-swift -ltype_wrapper_defs -module-name main -I %t -L %t %s -o %t/a.out -// RUN: %target-run %t/a.out | %FileCheck %s +// RUN: %target-build-swift -ltype_wrapper_defs -module-name main -I %t -L %t %s -o %t/main %target-rpath(%t) +// RUN: %target-codesign %t/main +// RUN: %target-run %t/main %t/%target-library-name(type_wrapper_defs) | %FileCheck %s + +// REQUIRES: executable_test import type_wrapper_defs From 5a73b48599081ac13f47e02809a578090d18843e Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 24 Aug 2022 09:22:50 -0700 Subject: [PATCH 435/491] [Sema] CodeSynthesis: Extract logic to synthesize a parameter for memberwise `init` --- lib/Sema/CodeSynthesis.cpp | 135 +++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index b48432a0dc568..ce854186e131a 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -128,7 +128,7 @@ ArgumentList *swift::buildForwardingArgumentList(ArrayRef params, } static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var, - unsigned paramSize, ASTContext &ctx) { + ASTContext &ctx) { // First and foremost, if this is a constant don't bother. if (var->isLet()) return; @@ -250,6 +250,74 @@ enum class ImplicitConstructorKind { TypeWrapper, }; +static ParamDecl *createMemberwiseInitParameter(DeclContext *DC, + SourceLoc paramLoc, + VarDecl *var) { + auto &ctx = var->getASTContext(); + auto varInterfaceType = var->getValueInterfaceType(); + bool isAutoClosure = false; + + if (var->getAttrs().hasAttribute()) { + // If var is a lazy property, its value is provided for the underlying + // storage. We thus take an optional of the property's type. We only + // need to do this because the implicit initializer is added before all + // the properties are type checked. Perhaps init() synth should be + // moved later. + varInterfaceType = OptionalType::get(varInterfaceType); + } else if (Type backingPropertyType = + var->getPropertyWrapperBackingPropertyType()) { + // For a property that has a wrapper, writing the initializer + // with an '=' implies that the memberwise initializer should also + // accept a value of the original property type. Otherwise, the + // memberwise initializer will be in terms of the backing storage + // type. + if (var->isPropertyMemberwiseInitializedWithWrappedType()) { + varInterfaceType = var->getPropertyWrapperInitValueInterfaceType(); + + auto initInfo = var->getPropertyWrapperInitializerInfo(); + isAutoClosure = initInfo.getWrappedValuePlaceholder()->isAutoClosure(); + } else { + varInterfaceType = backingPropertyType; + } + } + + Type resultBuilderType = var->getResultBuilderType(); + if (resultBuilderType) { + // If the variable's type is structurally a function type, use that + // type. Otherwise, form a non-escaping function type for the function + // parameter. + bool isStructuralFunctionType = + varInterfaceType->lookThroughAllOptionalTypes()->is(); + if (!isStructuralFunctionType) { + auto extInfo = ASTExtInfoBuilder().withNoEscape().build(); + varInterfaceType = FunctionType::get({}, varInterfaceType, extInfo); + } + } + + // Create the parameter. + auto *arg = new (ctx) ParamDecl(SourceLoc(), paramLoc, var->getName(), + paramLoc, var->getName(), DC); + arg->setSpecifier(ParamSpecifier::Default); + arg->setInterfaceType(varInterfaceType); + arg->setImplicit(); + arg->setAutoClosure(isAutoClosure); + + // Don't allow the parameter to accept temporary pointer conversions. + arg->setNonEphemeralIfPossible(); + + // Attach a result builder attribute if needed. + if (resultBuilderType) { + auto typeExpr = TypeExpr::createImplicit(resultBuilderType, ctx); + auto attr = + CustomAttr::create(ctx, SourceLoc(), typeExpr, /*implicit=*/true); + arg->getAttrs().add(attr); + } + + maybeAddMemberwiseDefaultArg(arg, var, ctx); + + return arg; +} + /// Create an implicit struct or class constructor. /// /// \param decl The struct or class for which a constructor will be created. @@ -281,70 +349,7 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl, accessLevel = std::min(accessLevel, var->getFormalAccess()); - auto varInterfaceType = var->getValueInterfaceType(); - bool isAutoClosure = false; - - if (var->getAttrs().hasAttribute()) { - // If var is a lazy property, its value is provided for the underlying - // storage. We thus take an optional of the property's type. We only - // need to do this because the implicit initializer is added before all - // the properties are type checked. Perhaps init() synth should be - // moved later. - varInterfaceType = OptionalType::get(varInterfaceType); - } else if (Type backingPropertyType = - var->getPropertyWrapperBackingPropertyType()) { - // For a property that has a wrapper, writing the initializer - // with an '=' implies that the memberwise initializer should also - // accept a value of the original property type. Otherwise, the - // memberwise initializer will be in terms of the backing storage - // type. - if (var->isPropertyMemberwiseInitializedWithWrappedType()) { - varInterfaceType = var->getPropertyWrapperInitValueInterfaceType(); - - auto initInfo = var->getPropertyWrapperInitializerInfo(); - isAutoClosure = initInfo.getWrappedValuePlaceholder()->isAutoClosure(); - } else { - varInterfaceType = backingPropertyType; - } - } - - Type resultBuilderType= var->getResultBuilderType(); - if (resultBuilderType) { - // If the variable's type is structurally a function type, use that - // type. Otherwise, form a non-escaping function type for the function - // parameter. - bool isStructuralFunctionType = - varInterfaceType->lookThroughAllOptionalTypes() - ->is(); - if (!isStructuralFunctionType) { - auto extInfo = ASTExtInfoBuilder().withNoEscape().build(); - varInterfaceType = FunctionType::get({ }, varInterfaceType, extInfo); - } - } - - // Create the parameter. - auto *arg = new (ctx) - ParamDecl(SourceLoc(), Loc, - var->getName(), Loc, var->getName(), decl); - arg->setSpecifier(ParamSpecifier::Default); - arg->setInterfaceType(varInterfaceType); - arg->setImplicit(); - arg->setAutoClosure(isAutoClosure); - - // Don't allow the parameter to accept temporary pointer conversions. - arg->setNonEphemeralIfPossible(); - - // Attach a result builder attribute if needed. - if (resultBuilderType) { - auto typeExpr = TypeExpr::createImplicit(resultBuilderType, ctx); - auto attr = CustomAttr::create( - ctx, SourceLoc(), typeExpr, /*implicit=*/true); - arg->getAttrs().add(attr); - } - - maybeAddMemberwiseDefaultArg(arg, var, params.size(), ctx); - - params.push_back(arg); + params.push_back(createMemberwiseInitParameter(decl, Loc, var)); } } else if (ICK == ImplicitConstructorKind::DefaultDistributedActor) { auto classDecl = dyn_cast(decl); From 347e85ddc421a6a0908b5585b9a7702b3d6cf931 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 24 Aug 2022 14:18:32 -0700 Subject: [PATCH 436/491] [Sema] TypeWrappers: Add unamanged stored properties to the synthesized memberwise `init` If a stored property would be in a default memberwise initializer it would be added to the `init` synthesized for a type wrapped type as well i.e. a `let` property without a default. --- lib/Sema/CodeSynthesis.cpp | 20 ++++++- lib/Sema/TypeCheckTypeWrapper.cpp | 53 +++++++++++++++---- .../Inputs/type_wrapper_defs.swift | 15 ++++++ test/Interpreter/type_wrappers.swift | 26 +++++++++ test/type/type_wrapper.swift | 46 ++++++++++++++++ 5 files changed, 148 insertions(+), 12 deletions(-) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index ce854186e131a..c44d4bd2f6300 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -377,9 +377,27 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl, for (auto *member : decl->getMembers()) { auto *var = dyn_cast(member); - if (!(var && var->isAccessedViaTypeWrapper())) + if (!var) continue; + if (!var->isAccessedViaTypeWrapper()) { + // $_storage itself. + if (var->getName() == ctx.Id_TypeWrapperProperty) + continue; + + // Computed properties are not included. + if (!var->hasStorage()) + continue; + + // If this is a memberwise initializeable property include + // it into the type wrapper initializer otherwise the instance + // of type wrapped type wouldn't be completely initialized. + if (var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true)) + params.push_back(createMemberwiseInitParameter(decl, Loc, var)); + + continue; + } + Identifier argName = var->getName(); Identifier paramName = argName; diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index cc5838f3e345c..1d1a06501e835 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -319,7 +319,8 @@ bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator, return false; // `lazy` properties are not wrapped. - if (property->getAttrs().hasAttribute()) + if (property->getAttrs().hasAttribute() || + property->isLazyStorageProperty()) return false; // Properties with attached property wrappers are not considered @@ -386,11 +387,42 @@ SynthesizeTypeWrapperInitializerBody::evaluate(Evaluator &evaluator, /*Loc=*/DeclNameLoc(), /*Implicit=*/true), typeWrapperVar->getName()); - SmallVector arguments; + // Check whether given parameter requires a direct assignment to + // intialize the property. + // + // If `$Storage` doesn't have a member that corresponds + // to the current parameter it means that this is a property + // that not managed by the type wrapper which has to be + // initialized by direct assignment: `self. = ` + auto useDirectAssignment = [&](ParamDecl *param) { + // Properties with property wrappers are always managed by the type wrapper + if (param->hasAttachedPropertyWrapper()) + return false; + return storageType->lookupDirect(param->getName()).empty(); + }; + + SmallVector body; + + SmallVector initArgs; { for (auto *param : *ctor->getParameters()) { VarDecl *arg = param; + if (useDirectAssignment(param)) { + auto *propRef = UnresolvedDotExpr::createImplicit( + ctx, + new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()}, + /*Loc=*/DeclNameLoc(), /*Implicit=*/true), + arg->getName()); + + body.push_back(new (ctx) AssignExpr( + propRef, /*EqualLoc=*/SourceLoc(), + new (ctx) DeclRefExpr({arg}, /*DeclNameLoc=*/DeclNameLoc(), + /*Implicit=*/true), + /*Implicit=*/true)); + continue; + } + // type wrappers wrap only backing storage of a wrapped // property, so in this case we need to pass `_` to // `$Storage` constructor. @@ -399,9 +431,9 @@ SynthesizeTypeWrapperInitializerBody::evaluate(Evaluator &evaluator, (void)param->getPropertyWrapperBackingPropertyType(); } - arguments.push_back({/*labelLoc=*/SourceLoc(), arg->getName(), - new (ctx) DeclRefExpr(arg, /*Loc=*/DeclNameLoc(), - /*Implicit=*/true)}); + initArgs.push_back({/*labelLoc=*/SourceLoc(), arg->getName(), + new (ctx) DeclRefExpr(arg, /*Loc=*/DeclNameLoc(), + /*Implicit=*/true)}); } } @@ -410,7 +442,7 @@ SynthesizeTypeWrapperInitializerBody::evaluate(Evaluator &evaluator, TypeExpr::createImplicitForDecl( /*Loc=*/DeclNameLoc(), storageType, ctor, ctor->mapTypeIntoContext(storageType->getInterfaceType())), - ArgumentList::createImplicit(ctx, arguments)); + ArgumentList::createImplicit(ctx, initArgs)); auto *initRef = new (ctx) UnresolvedMemberExpr( /*dotLoc=*/SourceLoc(), /*declNameLoc=*/DeclNameLoc(), @@ -422,11 +454,10 @@ SynthesizeTypeWrapperInitializerBody::evaluate(Evaluator &evaluator, ctx, initRef, ArgumentList::forImplicitSingle(ctx, ctx.Id_memberwise, storageInit)); - auto *assignment = new (ctx) - AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(), typeWrapperInit, - /*Implicit=*/true); + body.push_back(new (ctx) AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(), + typeWrapperInit, + /*Implicit=*/true)); - return BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), - /*body=*/{assignment}, + return BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), body, /*rbloc=*/ctor->getLoc(), /*implicit=*/true); } diff --git a/test/Interpreter/Inputs/type_wrapper_defs.swift b/test/Interpreter/Inputs/type_wrapper_defs.swift index 99dece208c0d9..a9ab5031582c7 100644 --- a/test/Interpreter/Inputs/type_wrapper_defs.swift +++ b/test/Interpreter/Inputs/type_wrapper_defs.swift @@ -121,3 +121,18 @@ public struct ComplexPropWrapperTest { @PropWrapper public var a: [String] = ["a"] @PropWrapperWithoutInit(value: PropWrapper(wrappedValue: [1, 2, 3])) @PropWrapper public var b: [Int] } + +@Wrapper +public struct PersonWithUnmanagedTest { + public let name: String + + public lazy var age: Int = { + 30 + }() + + public var placeOfBirth: String { + get { "Earth" } + } + + @PropWrapper public var favoredColor: String = "red" +} diff --git a/test/Interpreter/type_wrappers.swift b/test/Interpreter/type_wrappers.swift index d6bcc9f4665f9..304678f506776 100644 --- a/test/Interpreter/type_wrappers.swift +++ b/test/Interpreter/type_wrappers.swift @@ -349,3 +349,29 @@ func testPropertyWrappers() { } testPropertyWrappers() + +do { + var person = PersonWithUnmanagedTest(name: "Arthur Dent") + // CHECK: Wrapper.init($Storage(_favoredColor: type_wrapper_defs.PropWrapper(value: "red"))) + + print(person.name) + // CHECK: Arthur Dent + + print(person.age) + // CHECK: 30 + + print(person.placeOfBirth) + // CHECK: Earth + + print(person.favoredColor) + // CHECK: in getter + // CHECK-NEXT: red + + person.favoredColor = "yellow" + // CHECK: in getter + // CHECK-NEXT: in setter => PropWrapper(value: "yellow") + + print(person.favoredColor) + // CHECK: in getter + // CHECK-NEXT: yellow +} diff --git a/test/type/type_wrapper.swift b/test/type/type_wrapper.swift index d906aeb54363b..887362c1da55d 100644 --- a/test/type/type_wrapper.swift +++ b/test/type/type_wrapper.swift @@ -332,3 +332,49 @@ func propertyWrapperTests() { // expected-error@-2 {{cannot convert value of type 'String' to expected argument type 'Float'}} } } + +func testDeclarationsWithUnmanagedProperties() { + @NoopWrapper + struct WithLet { // expected-note {{'init(name:age:)' declared here}} + let name: String + var age: Int + } + _ = WithLet(age: 0) // expected-error {{missing argument for parameter 'name' in call}} + _ = WithLet(name: "", age: 0) // Ok + + @NoopWrapper + struct WithDefaultedLet { + let name: String = "Arthur Dent" + var age: Int + } + + _ = WithDefaultedLet(age: 32) // Ok + _ = WithDefaultedLet(name: "", age: 0) // expected-error {{extra argument 'name' in call}} + + @NoopWrapper + struct WithLazy { + lazy var name: String = { + "Arthur Dent" + }() + + var age: Int = 30 + } + + _ = WithLazy() // Ok + _ = WithLazy(name: "") // expected-error {{extra argument 'name' in call}} + _ = WithLazy(name: "", age: 0) // expected-error {{extra argument 'name' in call}} + _ = WithLazy(age: 0) // Ok + + @NoopWrapper + struct OnlyLazyLetAndComputed { + let name: String + lazy var age: Int = { + 30 + }() + var planet: String { + get { "Earth" } + } + } + + _ = OnlyLazyLetAndComputed(name: "Arthur Dent") // Ok +} From 3aa2bb958ac57066c54913ca4f82d1355d52e6cc Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 26 Aug 2022 00:06:14 -0700 Subject: [PATCH 437/491] [Sema] TypeWrappers: Mark `$Storage` struct as `internal` --- lib/Sema/TypeCheckTypeWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 1d1a06501e835..32f546e5fd1e4 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -164,7 +164,7 @@ GetTypeWrapperStorage::evaluate(Evaluator &evaluator, storage->setImplicit(); storage->setSynthesized(); - storage->copyFormalAccessFrom(parent, /*sourceIsParentContext=*/true); + storage->setAccess(AccessLevel::Internal); parent->addMember(storage); From 491defb682e3b125e47223a15299383fbe59f86d Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 26 Aug 2022 12:25:08 -0700 Subject: [PATCH 438/491] [Sema] TypeWrappers: Mark `$_storage` as `private` and all `$Storage` properties as `internal` --- lib/Sema/TypeCheckTypeWrapper.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 32f546e5fd1e4..2c0a1d11da56e 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -28,6 +28,7 @@ using namespace swift; /// Create a property declaration and inject it into the given type. static VarDecl *injectProperty(NominalTypeDecl *parent, Identifier name, Type type, VarDecl::Introducer introducer, + AccessLevel accessLevel, Expr *initializer = nullptr) { auto &ctx = parent->getASTContext(); @@ -36,7 +37,7 @@ static VarDecl *injectProperty(NominalTypeDecl *parent, Identifier name, var->setImplicit(); var->setSynthesized(); - var->copyFormalAccessFrom(parent, /*sourceIsParentContext=*/true); + var->setAccess(accessLevel); var->setInterfaceType(type); Pattern *pattern = NamedPattern::createImplicit(ctx, var); @@ -193,8 +194,8 @@ GetTypeWrapperProperty::evaluate(Evaluator &evaluator, typeWrapper, /*Parent=*/typeWrapperType->getParent(), /*genericArgs=*/{storage->getInterfaceType()->getMetatypeInstanceType()}); - return injectProperty(parent, ctx.Id_TypeWrapperProperty, - propertyTy, VarDecl::Introducer::Var); + return injectProperty(parent, ctx.Id_TypeWrapperProperty, propertyTy, + VarDecl::Introducer::Var, AccessLevel::Private); } VarDecl *GetTypeWrapperStorageForProperty::evaluate(Evaluator &evaluator, @@ -215,7 +216,7 @@ VarDecl *GetTypeWrapperStorageForProperty::evaluate(Evaluator &evaluator, return injectProperty(storage, property->getName(), property->getValueInterfaceType(), - property->getIntroducer()); + property->getIntroducer(), AccessLevel::Internal); } /// Given the property create a subscript to reach its type wrapper storage: From f82a4e7899a12c6189824feb4d702dc470b7ad12 Mon Sep 17 00:00:00 2001 From: Butta Date: Sat, 27 Aug 2022 01:24:25 +0530 Subject: [PATCH 439/491] [ClangImporter] Add the sysroot directly to the clang Driver used to find the libc header path `getToolChain()` and `AddClangSystemIncludeArgs()` don't parse the arguments to set the sysroot, so set it directly instead. Also, remove a redundant check for a valid directory. Fixes #60224 --- lib/ClangImporter/ClangIncludePaths.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index 931e6c49c4063..09a8b10f15ae6 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -162,12 +162,8 @@ createClangArgs(const ASTContext &ctx, clang::driver::Driver &clangDriver) { // If an SDK path was explicitly passed to Swift, make sure to pass it to // Clang driver as well. It affects the resulting include paths. auto sdkPath = ctx.SearchPathOpts.getSDKPath(); - if (!sdkPath.empty()) { - unsigned argIndex = clangDriverArgs.MakeIndex("--sysroot", sdkPath); - clangDriverArgs.append(new llvm::opt::Arg( - clangDriver.getOpts().getOption(clang::driver::options::OPT__sysroot), - sdkPath, argIndex)); - } + if (!sdkPath.empty()) + clangDriver.SysRoot = sdkPath.str(); return clangDriverArgs; } @@ -212,13 +208,6 @@ getGlibcFileMapping(ASTContext &ctx) { // FIXME: Emit a warning of some kind. return {}; - // Only inject the module map if it actually exists. It may not, for example - // if `swiftc -target x86_64-unknown-linux-gnu -emit-ir` is invoked using - // a Swift compiler not built for Linux targets. - if (!llvm::sys::fs::exists(actualModuleMapPath)) - // FIXME: emit a warning of some kind. - return {}; - // TODO: remove the SwiftGlibc.h header and reference all Glibc headers // directly from the modulemap. Path actualHeaderPath = actualModuleMapPath; From 315ee2a167b873aec352279b85bc691335b9b0af Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 26 Aug 2022 15:28:59 -0700 Subject: [PATCH 440/491] Fix tuple keypath verifier (#60737) --- lib/SIL/Verifier/SILVerifier.cpp | 10 +++++----- test/SILGen/keypaths.swift | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index b566205f7c382..5cea342ce4502 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -418,19 +418,19 @@ void verifyKeyPathComponent(SILModule &M, break; } case KeyPathPatternComponent::Kind::TupleElement: { - require(loweredBaseTy.is(), + require(baseTy->is(), "invalid baseTy, should have been a TupleType"); - auto tupleTy = loweredBaseTy.castTo(); + auto tupleTy = baseTy->castTo(); auto eltIdx = component.getTupleIndex(); require(eltIdx < tupleTy->getNumElements(), "invalid element index, greater than # of tuple elements"); - auto eltTy = tupleTy.getElementType(eltIdx) - .getReferenceStorageReferent(); + auto eltTy = tupleTy->getElementType(eltIdx) + ->getReferenceStorageReferent(); - require(eltTy == componentTy, + require(eltTy->isEqual(componentTy), "tuple element type should match the type of the component"); break; diff --git a/test/SILGen/keypaths.swift b/test/SILGen/keypaths.swift index b750becd98b9c..7ae5e8c2d3c54 100644 --- a/test/SILGen/keypaths.swift +++ b/test/SILGen/keypaths.swift @@ -572,6 +572,14 @@ func tuples(_: T) { let _: ReferenceWritableKeyPath = \T.c.x.x // CHECK: keypath $KeyPath, (root $T; stored_property #T.c : $(x: C, y: C); tuple_element #0 : $C; stored_property #C.y : $String) let _: KeyPath = \T.c.x.y + + typealias Thing = (type: Any.Type, fn: () -> ()) + + // CHECK: keypath $WritableKeyPath<(type: any Any.Type, fn: () -> ()), any Any.Type>, (root $(type: any Any.Type, fn: () -> ()); tuple_element #0 : $any Any.Type) + let _: WritableKeyPath = \Thing.type + + // CHECK: keypath $WritableKeyPath<(type: any Any.Type, fn: () -> ()), () -> ()>, (root $(type: any Any.Type, fn: () -> ()); tuple_element #1 : $() -> ()) + let _: WritableKeyPath ()> = \Thing.fn } // CHECK-LABEL: sil hidden [ossa] @{{.*}}tuples_generic From 641d896a26d532a47774fa103c33f42caa159a55 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 26 Aug 2022 16:53:27 -0700 Subject: [PATCH 441/491] [Distributed] Use distributed thunk witnesses for DA protocol extensions. When a distributed member of an extension of a DistributedActor protocol is used to satisfy a distributed requirement for the same protocol, make sure we still use the distributed thunk. Noticed by inspection. --- lib/SILGen/SILGenType.cpp | 4 ---- test/SILGen/distributed_thunk.swift | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index 21015cc8106f0..8eceaac011e1b 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -707,10 +707,6 @@ SILFunction *SILGenModule::emitProtocolWitness( !requirement.getFuncDecl()->isDistributed() && witnessRef.hasDecl() && witnessRef.getFuncDecl() && witnessRef.getFuncDecl()->isDistributed()); - // We only need to use thunks when we go cross-actor: - shouldUseDistributedThunkWitness = shouldUseDistributedThunkWitness && - getActorIsolation(requirement.getDecl()) != - getActorIsolation(witness.getDecl()); if (shouldUseDistributedThunkWitness) { auto thunkDeclRef = SILDeclRef( witnessRef.getFuncDecl()->getDistributedThunk(), diff --git a/test/SILGen/distributed_thunk.swift b/test/SILGen/distributed_thunk.swift index 238d6f135a4f4..e789298bce0dd 100644 --- a/test/SILGen/distributed_thunk.swift +++ b/test/SILGen/distributed_thunk.swift @@ -59,3 +59,29 @@ distributed actor DA4: ServerProto { // CHECK: function_ref @$s17distributed_thunk3DA4C11doSomethingyyYaKFTE distributed func doSomething() throws { } } + +protocol Server2: DistributedActor { + distributed func sayHello() +} + +extension Server2 where ActorSystem == LocalTestingDistributedActorSystem { + // CHECK-LABEL: sil hidden [thunk] [distributed] [ref_adhoc_requirement_witness "$s11Distributed29LocalTestingInvocationDecoderC18decodeNextArgumentxyKSeRzSERzlF"] [ossa] @$s17distributed_thunk7Server2PAA11Distributed012LocalTestingD11ActorSystemC0gH0RtzrlE8sayHelloyyYaKFTE + // CHECK-NOT: return + // CHECK: function_ref @swift_distributed_actor_is_remote + distributed func sayHello() { /* default impl */ } + + // CHECK-LABEL: sil hidden [distributed] [ossa] @$s17distributed_thunk7Server2PAA11Distributed012LocalTestingD11ActorSystemC0gH0RtzrlE8sayHelloyyF + // CHECK-NOT: swift_distributed_actor_is_remote + // CHECK: return +} + +distributed actor DA5: Server2 { + typealias ActorSystem = LocalTestingDistributedActorSystem + // uses default impl + + // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk3DA5CAA7Server2A2aDP8sayHelloyyFTW + // CHECK: function_ref @$s17distributed_thunk7Server2PAA11Distributed012LocalTestingD11ActorSystemC0gH0RtzrlE8sayHelloyyF + + // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk3DA5CAA7Server2A2aDP8sayHelloyyFTWTE + // CHECK: function_ref @$s17distributed_thunk7Server2PAA11Distributed012LocalTestingD11ActorSystemC0gH0RtzrlE8sayHelloyyYaKFTE +} From f46ed6be13a94570b283943914023e17ff653447 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 26 Aug 2022 13:18:19 -0700 Subject: [PATCH 442/491] Put @_moveOnly type attribute behind the move only experimental flag. Just forgot to do this. --- lib/Sema/TypeCheckAttr.cpp | 7 +++++++ test/Sema/moveonly_decl_attr.swift | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index febce6745b5ad..b99c407950ca2 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1950,6 +1950,13 @@ void AttributeChecker::visitFinalAttr(FinalAttr *attr) { } void AttributeChecker::visitMoveOnlyAttr(MoveOnlyAttr *attr) { + if (!D->getASTContext().LangOpts.hasFeature(Feature::MoveOnly)) { + auto error = + diag::experimental_moveonly_feature_can_only_be_used_when_enabled; + diagnoseAndRemoveAttr(attr, error); + return; + } + if (isa(D)) return; diff --git a/test/Sema/moveonly_decl_attr.swift b/test/Sema/moveonly_decl_attr.swift index 6ec87fb876023..9888c31f2ed4d 100644 --- a/test/Sema/moveonly_decl_attr.swift +++ b/test/Sema/moveonly_decl_attr.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift -parse-stdlib -disable-availability-checking -verify-syntax-tree +// RUN: %target-typecheck-verify-swift -parse-stdlib -disable-availability-checking -verify-syntax-tree -enable-experimental-move-only import Swift From 09c24ef42048945e401085599b02c521f4ba0603 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Fri, 26 Aug 2022 17:46:06 -0700 Subject: [PATCH 443/491] [Gardening] Remove Unused Parse-Time Circularity Diagnostic --- include/swift/AST/DiagnosticsParse.def | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index becc1240ee144..391e205ba05f3 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -231,8 +231,6 @@ ERROR(disallowed_var_multiple_getset,none, ERROR(disallowed_init,none, "initial value is not allowed here", ()) -ERROR(var_init_self_referential,none, - "variable used within its own initial value", ()) ERROR(disallowed_enum_element,none, "enum 'case' is not allowed outside of an enum", ()) From a8b5e14d9da029583f9a8b1cca22662452c8b8f0 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Fri, 26 Aug 2022 17:46:58 -0700 Subject: [PATCH 444/491] [NFC] Remove An Unused Vector of Protocols --- lib/AST/NameLookup.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 3decda3919073..5c0a7bc2f88b9 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -2062,8 +2062,6 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC, if (!wantProtocolMembers && !currentIsProtocol) continue; - SmallVector protocols; - if (auto *protoDecl = dyn_cast(current)) { // If we haven't seen a class declaration yet, look into the protocol. if (!sawClassDecl) { From e771660526e33ebee4b0d107fd547b01d683c479 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sat, 27 Aug 2022 00:06:09 -0700 Subject: [PATCH 445/491] [build-script] Support building "early" SwiftSyntax via `--early-swiftsyntax` Similar to the way the early Swift Driver is built, introduce a build-script option `--early-swiftsyntax` that uses the host Swift and CMake to build the parts of the swift-syntax package that are expected to become be used in the compiler. Note that this does not obviate the need for the `--swiftsyntax` option, because that build product uses the just-built Swift compiler and SwiftPM to build, test, and install everything from the swift-syntax package. --- .../build_swift/driver_arguments.py | 3 + utils/build_swift/tests/expected_options.py | 2 + .../build_script_invocation.py | 4 + .../swift_build_support/products/__init__.py | 1 + .../products/earlyswiftsyntax.py | 97 +++++++++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 utils/swift_build_support/swift_build_support/products/earlyswiftsyntax.py diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index cb5fe04bb132e..73e427c19f253 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -651,6 +651,9 @@ def create_argument_parser(): option(['--swiftsyntax'], toggle_true('build_swiftsyntax'), help='build swiftSyntax') + option(['--early-swiftsyntax'], toggle_true('build_early_swiftsyntax'), + help='build early SwiftSyntax') + option(['--skstresstester'], toggle_true('build_skstresstester'), help='build the SourceKit stress tester') diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py index 16b89217332cd..69bf57a3fc22a 100644 --- a/utils/build_swift/tests/expected_options.py +++ b/utils/build_swift/tests/expected_options.py @@ -90,6 +90,7 @@ 'build_swiftpm': False, 'build_swift_driver': False, 'build_early_swift_driver': True, + 'build_early_swiftsyntax': False, 'build_swiftsyntax': False, 'build_libparser_only': False, 'build_skstresstester': False, @@ -516,6 +517,7 @@ class BuildScriptImplOption(_BaseOption): SetTrueOption('--skip-build'), SetTrueOption('--swiftpm', dest='build_swiftpm'), SetTrueOption('--swift-driver', dest='build_swift_driver'), + SetTrueOption('--early-swiftsyntax', dest='build_early_swiftsyntax'), SetTrueOption('--swiftsyntax', dest='build_swiftsyntax'), SetTrueOption('--build-libparser-only', dest='build_libparser_only'), SetTrueOption('--skstresstester', dest='build_skstresstester'), diff --git a/utils/swift_build_support/swift_build_support/build_script_invocation.py b/utils/swift_build_support/swift_build_support/build_script_invocation.py index 7f4f0232b3605..a0dee6ce05624 100644 --- a/utils/swift_build_support/swift_build_support/build_script_invocation.py +++ b/utils/swift_build_support/swift_build_support/build_script_invocation.py @@ -548,6 +548,10 @@ def compute_product_pipelines(self): builder = ProductPipelineListBuilder(self.args) builder.begin_pipeline() + + builder.add_product(products.EarlySwiftSyntax, + is_enabled=self.args.build_early_swiftsyntax) + # If --skip-early-swift-driver is passed in, swift will be built # as usual, but relying on its own C++-based (Legacy) driver. # Otherwise, we build an "early" swift-driver using the host diff --git a/utils/swift_build_support/swift_build_support/products/__init__.py b/utils/swift_build_support/swift_build_support/products/__init__.py index caac9fb7da6f7..e24f101de232b 100644 --- a/utils/swift_build_support/swift_build_support/products/__init__.py +++ b/utils/swift_build_support/swift_build_support/products/__init__.py @@ -14,6 +14,7 @@ from .benchmarks import Benchmarks from .cmark import CMark from .curl import LibCurl +from .earlyswiftsyntax import EarlySwiftSyntax from .earlyswiftdriver import EarlySwiftDriver from .foundation import Foundation from .indexstoredb import IndexStoreDB diff --git a/utils/swift_build_support/swift_build_support/products/earlyswiftsyntax.py b/utils/swift_build_support/swift_build_support/products/earlyswiftsyntax.py new file mode 100644 index 0000000000000..1f68f41c74e72 --- /dev/null +++ b/utils/swift_build_support/swift_build_support/products/earlyswiftsyntax.py @@ -0,0 +1,97 @@ +# swift_build_support/products/earlyswiftsyntax.py --------------*- python -*- +# +# This source file is part of the Swift.org open source project +# +# Copyright (c) 2014 - 2022 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 os + +from . import cmake_product +from . import product +from .. import shell +from .. import toolchain + + +# SwiftSyntax is a Swift module used to parse and manipulate Swift syntax. This +# build product is a "Special" SwiftSyntax that gets built with the host +# toolchain that can be linked into the Swift compiler itself, hence it does not +# depend on any other build product of `build-script`. +class EarlySwiftSyntax(cmake_product.CMakeProduct): + @classmethod + def product_source_name(cls): + return "swift-syntax" + + @classmethod + def is_build_script_impl_product(cls): + return False + + @classmethod + def is_before_build_script_impl_product(cls): + return True + + def should_build(self, host_target): + if self.args.build_early_swiftsyntax: + if toolchain.host_toolchain().find_tool("swift") is None: + warn_msg = 'Host toolchain could not locate a '\ + 'compiler to build early swift-syntax.' + print('-- Warning: {}', warn_msg) + return False + else: + return True + return False + + @classmethod + def get_dependencies(cls): + return [] + + def build(self, host_target): + self.cmake_options.define('CMAKE_BUILD_TYPE:STRING', + self.args.swift_build_variant) + self.cmake_options.define('BUILD_SHARED_LIBS:STRING', 'NO') + + (platform, arch) = host_target.split('-') + + common_c_flags = ' '.join(self.common_cross_c_flags(platform, arch)) + self.cmake_options.define('CMAKE_C_FLAGS', common_c_flags) + self.cmake_options.define('CMAKE_CXX_FLAGS', common_c_flags) + + if host_target.startswith("macosx") or \ + host_target.startswith("iphone") or \ + host_target.startswith("appletv") or \ + host_target.startswith("watch"): + toolchain_file = self.generate_darwin_toolchain_file(platform, arch) + self.cmake_options.define('CMAKE_TOOLCHAIN_FILE:PATH', toolchain_file) + elif platform == "linux": + toolchain_file = self.generate_linux_toolchain_file(platform, arch) + self.cmake_options.define('CMAKE_TOOLCHAIN_FILE:PATH', toolchain_file) + + self.build_with_cmake(["all"], self.args.swift_build_variant, []) + + def should_test(self, host_target): + # The normal SwiftSyntax target runs tests through SwiftPM. + return False + + def test(self, host_target): + pass + + def should_install(self, host_target): + # This product is for the swift-syntax used with the build-directory compiler. + # If a toolchain install is required, please use the SwiftSyntax (no 'Early') + # product with `--swift-syntax --install-swift-syntax`. + return False + + @classmethod + def is_ignore_install_all_product(cls): + # Ensures that `install_all` setting triggered by `--infer` does not + # affect products which specify `is_ignore_install_all_product` as + # True. This is useful for products which should not be installed into the + # toolchain (corresponding build products that use the just-built + # toolchain are the products that get installed, e.g. `swiftsyntax` to + # `earlyswiftsyntax`). + return True From aafb6e21bfbcea80bd59fb64f6e0ada9c578fce4 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Sat, 27 Aug 2022 12:58:19 +0100 Subject: [PATCH 446/491] [Build] Add back the reference to the threading library at top level. Without this, BackDeployConcurrency build will fail. rdar://99206914 --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75c8159de9a26..1ba128f40a5ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1163,6 +1163,9 @@ endif() if(SWIFT_BUILD_STDLIB) add_subdirectory(stdlib) else() + # Some of the things below depend on the threading library + add_subdirectory(stdlib/public/Threading) + if(SWIFT_BUILD_STDLIB_EXTRA_TOOLCHAIN_CONTENT) add_subdirectory(stdlib/toolchain) endif() From 5ae31c0029c7a7ab56eb3e430bae04e826805c3b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sat, 27 Aug 2022 07:25:32 -0700 Subject: [PATCH 447/491] Address Python linting failures --- .../swift_build_support/products/__init__.py | 3 ++- .../swift_build_support/products/earlyswiftsyntax.py | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/utils/swift_build_support/swift_build_support/products/__init__.py b/utils/swift_build_support/swift_build_support/products/__init__.py index e24f101de232b..3e8397a16fe44 100644 --- a/utils/swift_build_support/swift_build_support/products/__init__.py +++ b/utils/swift_build_support/swift_build_support/products/__init__.py @@ -14,8 +14,8 @@ from .benchmarks import Benchmarks from .cmark import CMark from .curl import LibCurl -from .earlyswiftsyntax import EarlySwiftSyntax from .earlyswiftdriver import EarlySwiftDriver +from .earlyswiftsyntax import EarlySwiftSyntax from .foundation import Foundation from .indexstoredb import IndexStoreDB from .libcxx import LibCXX @@ -64,6 +64,7 @@ 'SwiftPM', 'SwiftDriver', 'EarlySwiftDriver', + 'EarlySwiftSyntax', 'XCTest', 'SwiftSyntax', 'SKStressTester', diff --git a/utils/swift_build_support/swift_build_support/products/earlyswiftsyntax.py b/utils/swift_build_support/swift_build_support/products/earlyswiftsyntax.py index 1f68f41c74e72..8704fec2fb206 100644 --- a/utils/swift_build_support/swift_build_support/products/earlyswiftsyntax.py +++ b/utils/swift_build_support/swift_build_support/products/earlyswiftsyntax.py @@ -10,11 +10,7 @@ # # ---------------------------------------------------------------------------- -import os - from . import cmake_product -from . import product -from .. import shell from .. import toolchain From 109737551ef563bbaa1242741f575228aa9a22ac Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Sat, 27 Aug 2022 20:42:19 -0300 Subject: [PATCH 448/491] [Sema] Handle non-function type parameters for closure arguments in ambiguity diagnositc --- lib/Sema/ConstraintSystem.cpp | 7 +++++-- test/expr/closure/closures.swift | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 93553a4fd98bc..43508de5eb568 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -4039,7 +4039,8 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs, return fix->getKind() == FixKind::AllowArgumentTypeMismatch || fix->getKind() == FixKind::AllowFunctionTypeMismatch || fix->getKind() == FixKind::AllowTupleTypeMismatch || - fix->getKind() == FixKind::GenericArgumentsMismatch; + fix->getKind() == FixKind::GenericArgumentsMismatch || + fix->getKind() == FixKind::InsertCall; }); }); @@ -4515,7 +4516,9 @@ static bool diagnoseContextualFunctionCallGenericAmbiguity( auto argParamMatch = argMatching->second.parameterBindings[i]; auto param = applyFnType->getParams()[argParamMatch.front()]; - auto paramFnType = param.getPlainType()->castTo(); + auto paramFnType = param.getPlainType()->getAs(); + if (!paramFnType) + continue; if (cs.typeVarOccursInType(resultTypeVar, paramFnType->getResult())) closureArguments.push_back(closure); diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift index 9a751c0a559f9..b3e6e88c166d7 100644 --- a/test/expr/closure/closures.swift +++ b/test/expr/closure/closures.swift @@ -751,3 +751,15 @@ public class TestImplicitCaptureOfExplicitCaptureOfSelfInEscapingClosure { if s == "1" { return () } // expected-error{{cannot convert return expression of type '()' to return type 'Bool'}} return s.isEmpty }.filter { $0 } + +// https://github.com/apple/swift/issues/60781 +func f60781(_ x: T) -> T { x } +func f60781(_ x: T, _ y: T) -> T { x } + +func test60781() -> Int { + f60781({ 1 }) // expected-error{{conflicting arguments to generic parameter 'T' ('Int' vs. '() -> Int')}} +} + +func test60781_MultiArg() -> Int { + f60781({ 1 }, { 1 }) // expected-error{{conflicting arguments to generic parameter 'T' ('Int' vs. '() -> Int')}} +} From 31d1b3a6d8d45055d98dac4ec549997029579589 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Fri, 5 Aug 2022 01:00:39 -0700 Subject: [PATCH 449/491] Index expressible-by-literal expressions. When a value is initialized or coerced for a type that conforms to one of the `ExpressibleBy*Literal` protocols (or `ExpressibleByStringInterpolation`), this change records an implicit call to the corresponding `init(...Literal:)` in the indexstore, located at the beginning of the literal. --- lib/AST/Expr.cpp | 16 +-- lib/IDE/SourceEntityWalker.cpp | 36 +++-- lib/IDE/Utils.cpp | 7 + .../Index/index_expressible_by_literals.swift | 135 ++++++++++++++++++ .../Indexing/index_big_array.swift.response | 7 + 5 files changed, 182 insertions(+), 19 deletions(-) create mode 100644 test/Index/index_expressible_by_literals.swift diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index ef12e1e8d1c1d..5ad9f69ac0292 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -320,12 +320,12 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const { ->GetSubExpr()->getReferencedDecl(stopAtParenExpr) NO_REFERENCE(Error); - NO_REFERENCE(NilLiteral); - NO_REFERENCE(IntegerLiteral); - NO_REFERENCE(FloatLiteral); - NO_REFERENCE(BooleanLiteral); - NO_REFERENCE(StringLiteral); - NO_REFERENCE(InterpolatedStringLiteral); + SIMPLE_REFERENCE(NilLiteral, getInitializer); + SIMPLE_REFERENCE(IntegerLiteral, getInitializer); + SIMPLE_REFERENCE(FloatLiteral, getInitializer); + SIMPLE_REFERENCE(BooleanLiteral, getInitializer); + SIMPLE_REFERENCE(StringLiteral, getInitializer); + SIMPLE_REFERENCE(InterpolatedStringLiteral, getInitializer); NO_REFERENCE(RegexLiteral); NO_REFERENCE(ObjectLiteral); NO_REFERENCE(MagicIdentifierLiteral); @@ -371,8 +371,8 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const { PASS_THROUGH_REFERENCE(OptionalTry, getSubExpr); NO_REFERENCE(Tuple); - NO_REFERENCE(Array); - NO_REFERENCE(Dictionary); + SIMPLE_REFERENCE(Array, getInitializer); + SIMPLE_REFERENCE(Dictionary, getInitializer); case ExprKind::Subscript: { auto subscript = cast(this); diff --git a/lib/IDE/SourceEntityWalker.cpp b/lib/IDE/SourceEntityWalker.cpp index 449a283aaec77..1ab4fb25eec7f 100644 --- a/lib/IDE/SourceEntityWalker.cpp +++ b/lib/IDE/SourceEntityWalker.cpp @@ -386,18 +386,32 @@ std::pair SemaAnnotator::walkToExprPre(Expr *E) { } } - if (!isa(E) && - !isa(E) && - !isa(E) && + if (!isa(E) && !isa(E) && !isa(E) && !isa(E) && - !isa(E) && - !isa(E) && - !isa(E) && - !isa(E) && - E->isImplicit()) - return { true, E }; - - if (auto *DRE = dyn_cast(E)) { + !isa(E) && !isa(E) && + !isa(E) && !isa(E) && !isa(E) && + !isa(E) && E->isImplicit()) + return {true, E}; + + if (auto LE = dyn_cast(E)) { + if (LE->getInitializer() && + !passReference(LE->getInitializer().getDecl(), LE->getType(), {}, + LE->getSourceRange(), + ReferenceMetaData(SemaReferenceKind::DeclRef, OpAccess, + /*isImplicit=*/true))) { + return doStopTraversal(); + } + return {true, E}; + } else if (auto CE = dyn_cast(E)) { + if (CE->getInitializer() && + !passReference(CE->getInitializer().getDecl(), CE->getType(), {}, + CE->getSourceRange(), + ReferenceMetaData(SemaReferenceKind::DeclRef, OpAccess, + /*isImplicit=*/true))) { + return doStopTraversal(); + } + return {true, E}; + } else if (auto *DRE = dyn_cast(E)) { if (auto *module = dyn_cast(DRE->getDecl())) { if (!passReference(ModuleEntity(module), {module->getName(), E->getLoc()})) diff --git a/lib/IDE/Utils.cpp b/lib/IDE/Utils.cpp index b103a5186ff0d..a5bad2394d4c9 100644 --- a/lib/IDE/Utils.cpp +++ b/lib/IDE/Utils.cpp @@ -1203,6 +1203,13 @@ bool swift::ide::isBeingCalled(ArrayRef ExprStack) { Expr *Target = ExprStack.back(); auto UnderlyingDecl = getReferencedDecl(Target).second; for (Expr *E: reverse(ExprStack)) { + auto *LE = dyn_cast(E); + if (LE && getReferencedDecl(LE).second == UnderlyingDecl) + return true; + auto *CE = dyn_cast(E); + if (CE && getReferencedDecl(CE).second == UnderlyingDecl) + return true; + auto *AE = dyn_cast(E); if (!AE || AE->isImplicit()) continue; diff --git a/test/Index/index_expressible_by_literals.swift b/test/Index/index_expressible_by_literals.swift new file mode 100644 index 0000000000000..eb18aa15ab96f --- /dev/null +++ b/test/Index/index_expressible_by_literals.swift @@ -0,0 +1,135 @@ +// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s + +struct CustomInteger: ExpressibleByIntegerLiteral { + init(integerLiteral: Int) {} +} +struct CustomFloat: ExpressibleByFloatLiteral { + init(floatLiteral: Double) {} +} +struct CustomBool: ExpressibleByBooleanLiteral { + init(booleanLiteral: Bool) {} +} +struct CustomNil: ExpressibleByNilLiteral { + init(nilLiteral: ()) {} +} +struct CustomString: ExpressibleByStringLiteral { + init(stringLiteral: StaticString) {} +} +struct CustomScalar: ExpressibleByUnicodeScalarLiteral { + init(unicodeScalarLiteral: Unicode.Scalar) {} +} +struct CustomCharacter: ExpressibleByExtendedGraphemeClusterLiteral { + init(extendedGraphemeClusterLiteral: Character) {} +} +struct CustomArray: ExpressibleByArrayLiteral { + init(arrayLiteral: Int...) {} +} +struct CustomDictionary: ExpressibleByDictionaryLiteral { + init(dictionaryLiteral: (Int, Int)...) {} +} +struct CustomInterpolation: ExpressibleByStringInterpolation { + init(stringInterpolation: StringInterpolation) {} + init(stringLiteral: String) {} +} + +func customInteger() { + // CHECK: [[@LINE+2]]:26 | constructor/Swift | init(integerLiteral:) | s:14swift_ide_test13CustomIntegerV14integerLiteralACSi_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customInteger() | s:14swift_ide_test13customIntegeryyF + let _: CustomInteger = 100 + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(integerLiteral:) | s:14swift_ide_test13CustomIntegerV14integerLiteralACSi_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customInteger() | s:14swift_ide_test13customIntegeryyF + _ = 100 as CustomInteger + // CHECK: [[@LINE+2]]:21 | constructor/Swift | init(integerLiteral:) | s:14swift_ide_test13CustomIntegerV14integerLiteralACSi_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customInteger() | s:14swift_ide_test13customIntegeryyF + _ = CustomInteger(100) +} +func customFloat() { + // CHECK: [[@LINE+2]]:24 | constructor/Swift | init(floatLiteral:) | s:14swift_ide_test11CustomFloatV12floatLiteralACSd_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customFloat() | s:14swift_ide_test11customFloatyyF + let _: CustomFloat = -1.23 + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(floatLiteral:) | s:14swift_ide_test11CustomFloatV12floatLiteralACSd_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customFloat() | s:14swift_ide_test11customFloatyyF + _ = -1.23 as CustomFloat + // CHECK: [[@LINE+2]]:19 | constructor/Swift | init(floatLiteral:) | s:14swift_ide_test11CustomFloatV12floatLiteralACSd_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customFloat() | s:14swift_ide_test11customFloatyyF + _ = CustomFloat(-1.23) +} +func customBool() { + // CHECK: [[@LINE+2]]:23 | constructor/Swift | init(booleanLiteral:) | s:14swift_ide_test10CustomBoolV14booleanLiteralACSb_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customBool() | s:14swift_ide_test10customBoolyyF + let _: CustomBool = true + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(booleanLiteral:) | s:14swift_ide_test10CustomBoolV14booleanLiteralACSb_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customBool() | s:14swift_ide_test10customBoolyyF + _ = false as CustomBool + // CHECK: [[@LINE+2]]:18 | constructor/Swift | init(booleanLiteral:) | s:14swift_ide_test10CustomBoolV14booleanLiteralACSb_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customBool() | s:14swift_ide_test10customBoolyyF + _ = CustomBool(true) +} +func customNil() { + // CHECK: [[@LINE+2]]:22 | constructor/Swift | init(nilLiteral:) | s:14swift_ide_test9CustomNilV10nilLiteralACyt_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customNil() | s:14swift_ide_test9customNilyyF + let _: CustomNil = nil + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(nilLiteral:) | s:14swift_ide_test9CustomNilV10nilLiteralACyt_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customNil() | s:14swift_ide_test9customNilyyF + _ = nil as CustomNil +} +func customString() { + // CHECK: [[@LINE+2]]:25 | constructor/Swift | init(stringLiteral:) | s:14swift_ide_test12CustomStringV13stringLiteralACs06StaticE0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customString() | s:14swift_ide_test12customStringyyF + let _: CustomString = "abc" + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(stringLiteral:) | s:14swift_ide_test12CustomStringV13stringLiteralACs06StaticE0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customString() | s:14swift_ide_test12customStringyyF + _ = "abc" as CustomString + // CHECK: [[@LINE+2]]:20 | constructor/Swift | init(stringLiteral:) | s:14swift_ide_test12CustomStringV13stringLiteralACs06StaticE0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customString() | s:14swift_ide_test12customStringyyF + _ = CustomString("abc") +} +func customScalar() { + // CHECK: [[@LINE+2]]:25 | constructor/Swift | init(unicodeScalarLiteral:) | s:14swift_ide_test12CustomScalarV07unicodeE7LiteralACs7UnicodeO0E0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customScalar() | s:14swift_ide_test12customScalaryyF + let _: CustomScalar = "a" + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(unicodeScalarLiteral:) | s:14swift_ide_test12CustomScalarV07unicodeE7LiteralACs7UnicodeO0E0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customScalar() | s:14swift_ide_test12customScalaryyF + _ = "a" as CustomScalar + // CHECK: [[@LINE+2]]:20 | constructor/Swift | init(unicodeScalarLiteral:) | s:14swift_ide_test12CustomScalarV07unicodeE7LiteralACs7UnicodeO0E0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customScalar() | s:14swift_ide_test12customScalaryyF + _ = CustomScalar("a") +} +func customCharacter() { + // CHECK: [[@LINE+2]]:28 | constructor/Swift | init(extendedGraphemeClusterLiteral:) | s:14swift_ide_test15CustomCharacterV30extendedGraphemeClusterLiteralACSJ_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customCharacter() | s:14swift_ide_test15customCharacteryyF + let _: CustomCharacter = "a" + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(extendedGraphemeClusterLiteral:) | s:14swift_ide_test15CustomCharacterV30extendedGraphemeClusterLiteralACSJ_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customCharacter() | s:14swift_ide_test15customCharacteryyF + _ = "a" as CustomCharacter + // CHECK: [[@LINE+2]]:23 | constructor/Swift | init(extendedGraphemeClusterLiteral:) | s:14swift_ide_test15CustomCharacterV30extendedGraphemeClusterLiteralACSJ_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customCharacter() | s:14swift_ide_test15customCharacteryyF + _ = CustomCharacter("a") +} +func customArray() { + // CHECK: [[@LINE+2]]:24 | constructor/Swift | init(arrayLiteral:) | s:14swift_ide_test11CustomArrayV12arrayLiteralACSid_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customArray() | s:14swift_ide_test11customArrayyyF + let _: CustomArray = [1, 2, 3] + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(arrayLiteral:) | s:14swift_ide_test11CustomArrayV12arrayLiteralACSid_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customArray() | s:14swift_ide_test11customArrayyyF + _ = [1, 2, 3] as CustomArray +} +func customDictionary() { + // CHECK: [[@LINE+2]]:29 | constructor/Swift | init(dictionaryLiteral:) | s:14swift_ide_test16CustomDictionaryV17dictionaryLiteralACSi_Sitd_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customDictionary() | s:14swift_ide_test16customDictionaryyyF + let _: CustomDictionary = [1: 1, 2: 2, 3: 3] + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(dictionaryLiteral:) | s:14swift_ide_test16CustomDictionaryV17dictionaryLiteralACSi_Sitd_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customDictionary() | s:14swift_ide_test16customDictionaryyyF + _ = [1: 1, 2: 2, 3: 3] as CustomDictionary +} +func customInterpolation() { + // CHECK: [[@LINE+2]]:32 | constructor/Swift | init(stringInterpolation:) | s:14swift_ide_test19CustomInterpolationV06stringE0ACs013DefaultStringE0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customInterpolation() | s:14swift_ide_test19customInterpolationyyF + let _: CustomInterpolation = "a\(0)b" + // CHECK: [[@LINE+2]]:7 | constructor/Swift | init(stringInterpolation:) | s:14swift_ide_test19CustomInterpolationV06stringE0ACs013DefaultStringE0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customInterpolation() | s:14swift_ide_test19customInterpolationyyF + _ = "a\(0)b" as CustomInterpolation + // CHECK: [[@LINE+2]]:27 | constructor/Swift | init(stringInterpolation:) | s:14swift_ide_test19CustomInterpolationV06stringE0ACs013DefaultStringE0V_tcfc | Ref,Call,Impl,RelCall,RelCont | + // CHECK-NEXT: RelCall,RelCont | function/Swift | customInterpolation() | s:14swift_ide_test19customInterpolationyyF + _ = CustomInterpolation("a\(0)b") +} diff --git a/test/SourceKit/Indexing/index_big_array.swift.response b/test/SourceKit/Indexing/index_big_array.swift.response index 771e817e978e9..52372b4d322ae 100644 --- a/test/SourceKit/Indexing/index_big_array.swift.response +++ b/test/SourceKit/Indexing/index_big_array.swift.response @@ -38,6 +38,13 @@ key.usr: "s:Sf", key.line: 1, key.column: 23 + }, + { + key.kind: source.lang.swift.ref.function.constructor, + key.usr: "s:Sa12arrayLiteralSayxGxd_tcfc", + key.line: 1, + key.column: 32, + key.is_implicit: 1 } ] } From e0f8711b23e09a48eb3fa8e03e878be59e4c5b9d Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Sat, 27 Aug 2022 20:56:12 -0700 Subject: [PATCH 450/491] Fix SILMem2Reg while marking end_borrow of store_borrow as deinit point Fixes rdar://99229461 --- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 5 +-- .../SILOptimizer/mem2reg_lifetime_borrows.sil | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 3cdc1f8e4101c..d8e22b98510ca 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -795,14 +795,15 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( continue; } if (!runningVals.hasValue()) { - assert(!deinitializationPoints[blockPromotingWithin]); - deinitializationPoints[blockPromotingWithin] = inst; continue; } if (sbi->getSrc() != runningVals->value.stored) { continue; } + // Mark storage as invalid and mark end_borrow as a deinit point. runningVals->isStorageValid = false; + assert(!deinitializationPoints[blockPromotingWithin]); + deinitializationPoints[blockPromotingWithin] = inst; if (!canEndLexicalLifetime(runningVals->value)) { continue; } diff --git a/test/SILOptimizer/mem2reg_lifetime_borrows.sil b/test/SILOptimizer/mem2reg_lifetime_borrows.sil index 94c1e4f71af0c..c165e8b08d881 100644 --- a/test/SILOptimizer/mem2reg_lifetime_borrows.sil +++ b/test/SILOptimizer/mem2reg_lifetime_borrows.sil @@ -452,3 +452,35 @@ bb0: %r = tuple () return %r : $() } + +// CHECK-LABEL: sil [ossa] @test_deinit_point : +// CHECK: alloc_stack +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'test_deinit_point' +sil [ossa] @test_deinit_point : $@convention(thin) (@guaranteed Klass) -> () { +bb0(%0 : @guaranteed $Klass): + %stk = alloc_stack [lexical] $Klass + cond_br undef, bb1, bb2 + +bb1: + %tmp = alloc_stack $Klass + %sb = store_borrow %0 to %tmp : $*Klass + %f = function_ref @use_inguaranteed : $@convention(thin) (@in_guaranteed Klass) -> () + %c = apply %f(%sb) : $@convention(thin) (@in_guaranteed Klass) -> () + end_borrow %sb : $*Klass + dealloc_stack %tmp : $*Klass + %copy = copy_value %0 : $Klass + store %copy to [init] %stk : $*Klass + %l = load [take] %stk : $*Klass + destroy_value %l : $Klass + br bb3 + +bb2: + br bb3 + +bb3: + dealloc_stack %stk : $*Klass + %r = tuple () + return %r : $() +} + From 47ae4d9a53f3b2fa4b14ca0558d398f98e4b10bf Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Sat, 27 Aug 2022 17:41:45 -0400 Subject: [PATCH 451/491] Preliminary Linux-OpenBSD cross-compile support. With a properly prepared sysroot and toolchain file, these changes permit cross-compilation of Swift as well as LLVM, CMark, and Dispatch (picking, as usual, apple/swift-corelibs-libdispatch#556) from a Linux host generating OpenBSD binaries. The toolchain file must be specified as an environment variable to `build-script` and discussion on how to properly set up the sysroot and toolchain file will be handled later. --- cmake/modules/SwiftConfigureSDK.cmake | 5 +++++ utils/build-script-impl | 16 +++++++++++++++- .../swift_build_support/products/cmark.py | 4 ++++ .../swift_build_support/products/product.py | 3 +++ .../swift_build_support/targets.py | 10 +++++++++- 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake index d7454f573402f..327f2615bd2f7 100644 --- a/cmake/modules/SwiftConfigureSDK.cmake +++ b/cmake/modules/SwiftConfigureSDK.cmake @@ -404,6 +404,11 @@ macro(configure_sdk_unix name architectures) message(STATUS "OpenBSD Version: ${openbsd_system_version}") set(SWIFT_SDK_OPENBSD_ARCH_amd64_TRIPLE "amd64-unknown-openbsd${openbsd_system_version}") + + if(NOT CMAKE_SYSROOT STREQUAL "") + set(SWIFT_SDK_OPENBSD_ARCH_${arch}_PATH "${CMAKE_SYSROOT}${SWIFT_SDK_OPENBSD_ARCH_${arch}_PATH}" CACHE INTERNAL "sysroot path" FORCE) + set(SWIFT_SDK_OPENBSD_ARCH_${arch}_LIBC_INCLUDE_DIRECTORY "${CMAKE_SYSROOT}${SWIFT_SDK_OPENBSD_ARCH_${arch}_LIBC_INCLUDE_DIRECTORY}" CACHE INTERNAL "sysroot libc path" FORCE) + endif() elseif("${prefix}" STREQUAL "CYGWIN") if(NOT arch STREQUAL x86_64) message(FATAL_ERROR "unsupported arch for cygwin: ${arch}") diff --git a/utils/build-script-impl b/utils/build-script-impl index 3d81eaece16b3..940083fd80ff3 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -1082,7 +1082,7 @@ function false_true() { CROSS_COMPILE_HOSTS=($CROSS_COMPILE_HOSTS) for t in "${CROSS_COMPILE_HOSTS[@]}"; do case ${t} in - macosx* | iphone* | appletv* | watch* | linux-armv5 | linux-armv6 | linux-armv7 | android-* ) + macosx* | iphone* | appletv* | watch* | linux-armv5 | linux-armv6 | linux-armv7 | android-* | openbsd-* ) ;; *) echo "Unknown host to cross-compile for: ${t}" @@ -1605,6 +1605,13 @@ for host in "${ALL_HOSTS[@]}"; do -DCMAKE_BUILD_WITH_INSTALL_RPATH="1" ) fi + + if [[ "${host}" == "openbsd-"* && "${OPENBSD_USE_TOOLCHAIN_FILE}" != "" ]]; then + llvm_cmake_options=( + "${llvm_cmake_options[@]}" + -DCMAKE_TOOLCHAIN_FILE="${OPENBSD_USE_TOOLCHAIN_FILE}" + ) + fi fi llvm_cmake_options=( @@ -1887,6 +1894,13 @@ for host in "${ALL_HOSTS[@]}"; do ) fi + if [[ $(is_cross_tools_host ${host}) && "${host}" == "openbsd-"* && "${OPENBSD_USE_TOOLCHAIN_FILE}" != "" ]]; then + cmake_options=( + "${cmake_options[@]}" + -DCMAKE_TOOLCHAIN_FILE="${OPENBSD_USE_TOOLCHAIN_FILE}" + ) + fi + if [[ "${DARWIN_OVERLAY_TARGET}" != "" ]]; then # Split LOCAL_HOST into a pair ``arch-sdk`` # Example LOCAL_HOST: macosx-x86_64 diff --git a/utils/swift_build_support/swift_build_support/products/cmark.py b/utils/swift_build_support/swift_build_support/products/cmark.py index 97198ca064523..1079a4f49cd1a 100644 --- a/utils/swift_build_support/swift_build_support/products/cmark.py +++ b/utils/swift_build_support/swift_build_support/products/cmark.py @@ -69,6 +69,10 @@ def build(self, host_target): elif platform == "linux": toolchain_file = self.generate_linux_toolchain_file(platform, arch) self.cmake_options.define('CMAKE_TOOLCHAIN_FILE:PATH', toolchain_file) + elif platform == "openbsd": + toolchain_file = self.get_openbsd_toolchain_file() + if toolchain_file: + self.cmake_options.define('CMAKE_TOOLCHAIN_FILE:PATH', toolchain_file) self.build_with_cmake(["all"], self.args.cmark_build_variant, []) diff --git a/utils/swift_build_support/swift_build_support/products/product.py b/utils/swift_build_support/swift_build_support/products/product.py index 7d7ad24b8e301..f117305ddb275 100644 --- a/utils/swift_build_support/swift_build_support/products/product.py +++ b/utils/swift_build_support/swift_build_support/products/product.py @@ -366,6 +366,9 @@ def generate_linux_toolchain_file(self, platform, arch): return toolchain_file + def get_openbsd_toolchain_file(self): + return os.getenv('OPENBSD_USE_TOOLCHAIN_FILE') + def common_cross_c_flags(self, platform, arch): cross_flags = [] diff --git a/utils/swift_build_support/swift_build_support/targets.py b/utils/swift_build_support/swift_build_support/targets.py index 34ae000617df3..554eb82503672 100644 --- a/utils/swift_build_support/swift_build_support/targets.py +++ b/utils/swift_build_support/swift_build_support/targets.py @@ -205,6 +205,14 @@ def swiftpm_config(self, args, output_dir, swift_toolchain, resource_path): return config_file +class OpenBSDPlatform(Platform): + def cmake_options(self, args): + toolchain_file = os.getenv('OPENBSD_USE_TOOLCHAIN_FILE') + if not toolchain_file: + return '' + return f'-DCMAKE_TOOLCHAIN_FILE="${toolchain_file}"' + + class Target(object): """ Abstract representation of a target Swift can run on. @@ -265,7 +273,7 @@ class StdlibDeploymentTarget(object): FreeBSD = Platform("freebsd", archs=["x86_64"]) - OpenBSD = Platform("openbsd", archs=["amd64"]) + OpenBSD = OpenBSDPlatform("openbsd", archs=["amd64"]) Cygwin = Platform("cygwin", archs=["x86_64"]) From c528e966e89c7b5ca30e63e004f744ff158957fd Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 29 Aug 2022 06:17:18 -0700 Subject: [PATCH 452/491] Add missing REQUIRES: executable_test to the test IRGen/98995607.swift.gyb redar://99229421 --- validation-test/IRGen/98995607.swift.gyb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/validation-test/IRGen/98995607.swift.gyb b/validation-test/IRGen/98995607.swift.gyb index 35d2959fd0b47..6dcaa12ee5fd1 100644 --- a/validation-test/IRGen/98995607.swift.gyb +++ b/validation-test/IRGen/98995607.swift.gyb @@ -1,5 +1,7 @@ // RUN: %target-run-simple-swiftgyb +// REQUIRES: executable_test + %for N in range(0, 100): protocol P${N} { From 7bf7642d519dc5cfb5261ade4ef6bd7ff43b244b Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 29 Aug 2022 07:40:00 -0700 Subject: [PATCH 453/491] [interop][SwiftToCxx] support @_expose attribute on initializers --- include/swift/AST/Attr.def | 2 +- include/swift/AST/DiagnosticsSema.def | 3 +++ lib/PrintAsClang/PrintClangFunction.cpp | 16 ++++++++++++++-- lib/Sema/TypeCheckAttr.cpp | 8 ++++++++ .../expose-attr/expose-swift-decls-to-cxx.swift | 10 ++++++++++ test/attr/attr_expose.swift | 9 +++++++++ 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def index 1df82de37cac8..218387fa991ec 100644 --- a/include/swift/AST/Attr.def +++ b/include/swift/AST/Attr.def @@ -758,7 +758,7 @@ SIMPLE_DECL_ATTR(_alwaysEmitConformanceMetadata, AlwaysEmitConformanceMetadata, 132) DECL_ATTR(_expose, Expose, - OnFunc | OnNominalType | OnVar | + OnFunc | OnNominalType | OnVar | OnConstructor | LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, 133) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index df75bf4a2e063..92e6a9e3c261e 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1485,6 +1485,9 @@ ERROR(expose_only_non_other_attr,none, "@_expose attribute cannot be applied to an '%0' declaration", (StringRef)) ERROR(expose_inside_unexposed_decl,none, "@_expose attribute cannot be applied inside of unexposed declaration %0", (DeclName)) +ERROR(expose_invalid_name_pattern_init,none, + "invalid declaration name '%0' specified in an @_expose attribute; " + "exposed initializer name must start with 'init'", (StringRef)) ERROR(attr_methods_only,none, "only methods can be declared %0", (DeclAttribute)) diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index d6c17b6a79473..4aca72c8f4db7 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -697,6 +697,16 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody( } } +static StringRef getConstructorName(const AbstractFunctionDecl *FD) { + auto name = cxx_translation::getNameForCxx( + FD, cxx_translation::CustomNamesOnly_t::CustomNamesOnly); + if (!name.empty()) { + assert(name.startswith("init")); + return name; + } + return "init"; +} + void DeclAndTypeClangFunctionPrinter::printCxxMethod( const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD, StringRef swiftSymbolName, Type resultTy, bool isDefinition) { @@ -713,8 +723,10 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod( modifiers.isConst = !isa(typeDeclContext) && !isMutating && !isConstructor; auto result = printFunctionSignature( - FD, isConstructor ? "init" : cxx_translation::getNameForCxx(FD), resultTy, - FunctionSignatureKind::CxxInlineThunk, {}, modifiers); + FD, + isConstructor ? getConstructorName(FD) + : cxx_translation::getNameForCxx(FD), + resultTy, FunctionSignatureKind::CxxInlineThunk, {}, modifiers); assert(!result.isUnsupported() && "C signature should be unsupported too"); if (!isDefinition) { diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index febce6745b5ad..02952b1933909 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1865,6 +1865,14 @@ void AttributeChecker::visitExposeAttr(ExposeAttr *attr) { diagnose(attr->getLocation(), diag::expose_inside_unexposed_decl, decl->getName()); } + + // Verify that the name mentioned in the expose + // attribute matches the supported name pattern. + if (!attr->Name.empty()) { + if (isa(VD) && !attr->Name.startswith("init")) + diagnose(attr->getLocation(), diag::expose_invalid_name_pattern_init, + attr->Name); + } } void AttributeChecker::visitUnsafeNoObjCTaggedPointerAttr( diff --git a/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift b/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift index 4cb581b227b71..da25817facbdc 100644 --- a/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift +++ b/test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift @@ -44,6 +44,12 @@ public struct NotExposedStruct { public struct ExposedStructRenamed { public var y: Int + @_expose(Cxx) + public init() { y = 42; prop = 0; prop2 = 0; } + + @_expose(Cxx, "initWithValue") + public init(why x: Int) { y = x; prop = 0; prop2 = 0; } + @_expose(Cxx, "renamedProp") public var prop: Int @@ -74,6 +80,8 @@ public final class ExposedClass { // CHECK: ExposedStruct2(ExposedStruct2 &&) = default; // CHECK-NEXT: swift::Int getY() const; // CHECK-NEXT: void setY(swift::Int value); +// CHECK-NEXT: static inline ExposedStruct2 init(); +// CHECK-NEXT: static inline ExposedStruct2 initWithValue(swift::Int x); // CHECK-NEXT: swift::Int getRenamedProp() const; // CHECK-NEXT: void setRenamedProp(swift::Int value); // CHECK-NEXT: swift::Int getProp3() const; @@ -100,6 +108,8 @@ public final class ExposedClass { // CHECK: void ExposedStruct::method() const { // CHECK: swift::Int ExposedStruct2::getY() const { // CHECK: void ExposedStruct2::setY(swift::Int value) { +// CHECK: ExposedStruct2 ExposedStruct2::init() { +// CHECK: ExposedStruct2 ExposedStruct2::initWithValue(swift::Int x) { // CHECK: swift::Int ExposedStruct2::getRenamedProp() const { // CHECK: void ExposedStruct2::setRenamedProp(swift::Int value) { // CHECK: swift::Int ExposedStruct2::getProp3() const { diff --git a/test/attr/attr_expose.swift b/test/attr/attr_expose.swift index be5aa25472e94..22840a094b1cf 100644 --- a/test/attr/attr_expose.swift +++ b/test/attr/attr_expose.swift @@ -24,3 +24,12 @@ struct NotExposedStruct { @_expose(Cxx) // expected-error {{@_expose attribute cannot be applied inside of unexposed declaration 'NotExposedStruct'}} func errorOnInnerExpose() {} } + +@_expose(Cxx) +struct ExposedStruct { + @_expose(Cxx, "create") // expected-error {{invalid declaration name 'create' specified in an @_expose attribute; exposed initializer name must start with 'init'}} + init() {} + + @_expose(Cxx, "initWith") + init(with y: Int) {} +} From 3740a207bdd794e76b35527efbce7ba4dc8f07bb Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Mon, 29 Aug 2022 10:47:42 -0400 Subject: [PATCH 454/491] Apply suggestions from code review Co-authored-by: Saleem Abdulrasool --- cmake/modules/SwiftConfigureSDK.cmake | 2 +- utils/build-script-impl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake index 327f2615bd2f7..38108b181a9c9 100644 --- a/cmake/modules/SwiftConfigureSDK.cmake +++ b/cmake/modules/SwiftConfigureSDK.cmake @@ -405,7 +405,7 @@ macro(configure_sdk_unix name architectures) set(SWIFT_SDK_OPENBSD_ARCH_amd64_TRIPLE "amd64-unknown-openbsd${openbsd_system_version}") - if(NOT CMAKE_SYSROOT STREQUAL "") + if(CMAKE_SYSROOT) set(SWIFT_SDK_OPENBSD_ARCH_${arch}_PATH "${CMAKE_SYSROOT}${SWIFT_SDK_OPENBSD_ARCH_${arch}_PATH}" CACHE INTERNAL "sysroot path" FORCE) set(SWIFT_SDK_OPENBSD_ARCH_${arch}_LIBC_INCLUDE_DIRECTORY "${CMAKE_SYSROOT}${SWIFT_SDK_OPENBSD_ARCH_${arch}_LIBC_INCLUDE_DIRECTORY}" CACHE INTERNAL "sysroot libc path" FORCE) endif() diff --git a/utils/build-script-impl b/utils/build-script-impl index 940083fd80ff3..1b2ba03ce4611 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -1606,7 +1606,7 @@ for host in "${ALL_HOSTS[@]}"; do ) fi - if [[ "${host}" == "openbsd-"* && "${OPENBSD_USE_TOOLCHAIN_FILE}" != "" ]]; then + if [[ "${host}" == "openbsd-"* && -n "${OPENBSD_USE_TOOLCHAIN_FILE}" ]]; then llvm_cmake_options=( "${llvm_cmake_options[@]}" -DCMAKE_TOOLCHAIN_FILE="${OPENBSD_USE_TOOLCHAIN_FILE}" @@ -1894,7 +1894,7 @@ for host in "${ALL_HOSTS[@]}"; do ) fi - if [[ $(is_cross_tools_host ${host}) && "${host}" == "openbsd-"* && "${OPENBSD_USE_TOOLCHAIN_FILE}" != "" ]]; then + if [[ $(is_cross_tools_host ${host}) && "${host}" == "openbsd-"* && -n "${OPENBSD_USE_TOOLCHAIN_FILE}" ]]; then cmake_options=( "${cmake_options[@]}" -DCMAKE_TOOLCHAIN_FILE="${OPENBSD_USE_TOOLCHAIN_FILE}" From c08428cd56eb58068ad02e23255a4094f4bf3a21 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 29 Aug 2022 12:14:06 -0700 Subject: [PATCH 455/491] [interop][SwiftToCxx] do not support generics with requirements for now --- lib/PrintAsClang/PrintClangFunction.cpp | 44 +++++++++++-------- .../generics/generic-function-in-cxx.swift | 8 ++++ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index 4aca72c8f4db7..9d4addff2641e 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -318,24 +318,32 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature( const AbstractFunctionDecl *FD, StringRef name, Type resultTy, FunctionSignatureKind kind, ArrayRef additionalParams, FunctionSignatureModifiers modifiers) { - if (kind == FunctionSignatureKind::CxxInlineThunk && FD->isGeneric()) { - os << "template<"; - llvm::interleaveComma(FD->getGenericParams()->getParams(), os, - [&](const GenericTypeParamDecl *genericParam) { - os << "class "; - ClangSyntaxPrinter(os).printBaseName(genericParam); - }); - os << ">\n"; - os << "requires "; - llvm::interleave( - FD->getGenericParams()->getParams(), os, - [&](const GenericTypeParamDecl *genericParam) { - os << "swift::isUsableInGenericContext<"; - ClangSyntaxPrinter(os).printBaseName(genericParam); - os << ">"; - }, - " && "); - os << "\n"; + if (FD->isGeneric()) { + auto Signature = FD->getGenericSignature(); + auto Requirements = Signature.getRequirements(); + // FIXME: Support generic requirements. + if (!Requirements.empty()) + return ClangRepresentation::unsupported; + if (kind == FunctionSignatureKind::CxxInlineThunk) { + os << "template<"; + llvm::interleaveComma(FD->getGenericParams()->getParams(), os, + [&](const GenericTypeParamDecl *genericParam) { + os << "class "; + ClangSyntaxPrinter(os).printBaseName( + genericParam); + }); + os << ">\n"; + os << "requires "; + llvm::interleave( + FD->getGenericParams()->getParams(), os, + [&](const GenericTypeParamDecl *genericParam) { + os << "swift::isUsableInGenericContext<"; + ClangSyntaxPrinter(os).printBaseName(genericParam); + os << ">"; + }, + " && "); + os << "\n"; + } } auto emittedModule = FD->getModuleContext(); OutputLanguageMode outputLang = kind == FunctionSignatureKind::CFunctionProto diff --git a/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift b/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift index 71a16b49e158f..adcbf4c0af85c 100644 --- a/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift +++ b/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift @@ -35,6 +35,12 @@ public func genericRet(_ x: T) -> T { return x } +public func genericRequirementProtocol(_ x: T) { +} + +public func genericRequirementClass(_ x: T) where T: TestClass { +} + public class TestClass { let field: Int @@ -84,6 +90,8 @@ public func createTestSmallStruct(_ x: UInt32) -> TestSmallStruct { // CHECK-NEXT: SWIFT_EXTERN void $s9Functions10genericRetyxxlF(SWIFT_INDIRECT_RESULT void * _Nonnull, const void * _Nonnull x, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericRet(_:) // CHECK-NEXT: SWIFT_EXTERN void $s9Functions11genericSwapyyxz_xztlF(void * _Nonnull x, void * _Nonnull y, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericSwap(_:_:) +// CHECK-NOT: genericRequirement + // Skip templates in impl classes. // CHECK: _impl_TestSmallStruct // CHECK: template From c14059e92c67fc270660520cc63ce7c94cc81d15 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Mon, 29 Aug 2022 10:06:31 -0700 Subject: [PATCH 456/491] [comment] Add a semantics note to SIL BindMemory --- docs/SIL.rst | 25 ++++++++++++++++++------- include/swift/SIL/SILInstruction.h | 12 +++++++++++- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/docs/SIL.rst b/docs/SIL.rst index be2df9cd805e6..1348c689ffd20 100644 --- a/docs/SIL.rst +++ b/docs/SIL.rst @@ -4363,11 +4363,22 @@ bind_memory Binds memory at ``Builtin.RawPointer`` value ``%0`` to type ``$T`` with enough capacity to hold ``%1`` values. See SE-0107: UnsafeRawPointer. -Produces a opaque token representing the previous memory state. For -memory binding semantics, this state includes the type that the memory -was previously bound to. The token cannot, however, be used to -retrieve a metatype. It's value is only meaningful to the Swift -runtime for typed pointer verification. +Produces a opaque token representing the previous memory state for +memory binding semantics. This abstract state includes the type that +the memory was previously bound to along with the size of the affected +memory region, which can be derived from ``%1``. The token cannot, for +example, be used to retrieve a metatype. It only serves a purpose when +used by ``rebind_memory``, which has no static type information. The +token dynamically passes type information from the first bind_memory +into a chain of rebind_memory operations. + +Example:: + + %_ = bind_memory %0 : $Builtin.RawPointer, %numT : $Builtin.Word to $T // holds type 'T' + %token0 = bind_memory %0 : $Builtin.RawPointer, %numU : $Builtin.Word to $U // holds type 'U' + %token1 = rebind_memory %0 : $Builtin.RawPointer, %token0 : $Builtin.Word // holds type 'T' + %token2 = rebind_memory %0 : $Builtin.RawPointer, %token1 : $Builtin.Word // holds type 'U' + rebind_memory ````````````` @@ -4386,8 +4397,8 @@ This instruction's semantics are identical to ``bind_memory``, except that the types to which memory will be bound, and the extent of the memory region is unknown at compile time. Instead, the bound-types are represented by a token that was produced by a prior memory binding -operation. ``%in_token`` must be the result of bind_memory or -rebind_memory. +operation. ``%in_token`` must be the result of ``bind_memory`` or +``rebind_memory``. begin_access ```````````` diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 7737d6f90fdd0..e3f5f99e1ead8 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -5048,7 +5048,14 @@ class ExplicitCopyAddrInst /// to hold %1 values. /// /// %token is an opaque word representing the previously bound types of this -/// memory region, before binding it to a contiguous region of type $T. +/// memory region, before binding it to a contiguous region of type $T. This +/// token has no purpose unless it is consumed be a rebind_memory instruction. +/// +/// Semantics: changes the type information assocated with a memory region. This +/// affects all memory operations that alias with the given region of memory, +/// regardless of their type or address provenance. For optimizations that query +/// side effects, this is equivalent to writing and immediately reading an +/// unknown value to memory at `%0` of `%1` bytes. class BindMemoryInst final : public InstructionBaseWithTrailingOperands< SILInstructionKind::BindMemoryInst, BindMemoryInst, SingleValueInstruction> { @@ -5096,6 +5103,9 @@ class BindMemoryInst final : public InstructionBaseWithTrailingOperands< /// /// %out_token represents the previously bound types of this memory region, /// before binding it to %in_token. +/// +/// This has the same semantics as bind_memory except that the size of memory +/// affected must be derived from `%in_token`. class RebindMemoryInst final : public SingleValueInstruction { FixedOperandList<2> Operands; From 9ea86830ff5bd745660765c851d73de2b9e81ec3 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Mon, 29 Aug 2022 13:25:19 -0700 Subject: [PATCH 457/491] ABI checker: we should also print ABI breakages when diagnostics are serialized This ensures users can review ABI checker failures from build logs alone. rdar://98624267 --- .../swift/APIDigester/ModuleDiagsConsumer.h | 15 +++++------ lib/APIDigester/ModuleDiagsConsumer.cpp | 27 ++++++++++++++++--- lib/DriverTool/swift_api_digester_main.cpp | 11 +++++--- .../api-digester/serialized-diagnostics.swift | 3 ++- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/include/swift/APIDigester/ModuleDiagsConsumer.h b/include/swift/APIDigester/ModuleDiagsConsumer.h index cb23ef5d301ea..e1f013caaab20 100644 --- a/include/swift/APIDigester/ModuleDiagsConsumer.h +++ b/include/swift/APIDigester/ModuleDiagsConsumer.h @@ -44,23 +44,20 @@ class ModuleDifferDiagsConsumer: public PrintingDiagnosticConsumer { class FilteringDiagnosticConsumer: public DiagnosticConsumer { bool HasError = false; - std::unique_ptr subConsumer; + std::vector> subConsumers; std::unique_ptr> allowedBreakages; bool shouldProceed(const DiagnosticInfo &Info); public: - FilteringDiagnosticConsumer(std::unique_ptr subConsumer, + FilteringDiagnosticConsumer(std::vector> subConsumers, std::unique_ptr> allowedBreakages): - subConsumer(std::move(subConsumer)), + subConsumers(std::move(subConsumers)), allowedBreakages(std::move(allowedBreakages)) {} ~FilteringDiagnosticConsumer() = default; - bool finishProcessing() override { return subConsumer->finishProcessing(); } + void flush() override; + void informDriverOfIncompleteBatchModeCompilation() override; + bool finishProcessing() override; bool hasError() const { return HasError; } - void flush() override { subConsumer->flush(); } - - void informDriverOfIncompleteBatchModeCompilation() override { - subConsumer->informDriverOfIncompleteBatchModeCompilation(); - } void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override; diff --git a/lib/APIDigester/ModuleDiagsConsumer.cpp b/lib/APIDigester/ModuleDiagsConsumer.cpp index c73fd148d5947..071b67dd97d0f 100644 --- a/lib/APIDigester/ModuleDiagsConsumer.cpp +++ b/lib/APIDigester/ModuleDiagsConsumer.cpp @@ -124,8 +124,27 @@ swift::ide::api::ModuleDifferDiagsConsumer::~ModuleDifferDiagsConsumer() { } } -bool swift::ide::api:: -FilteringDiagnosticConsumer::shouldProceed(const DiagnosticInfo &Info) { +void swift::ide::api::FilteringDiagnosticConsumer::flush() { + for (auto &consumer: subConsumers) { + consumer->flush(); + } +} + +void swift::ide::api:: +FilteringDiagnosticConsumer::informDriverOfIncompleteBatchModeCompilation() { + for (auto &consumer: subConsumers) { + consumer->informDriverOfIncompleteBatchModeCompilation(); + } +} + +bool swift::ide::api::FilteringDiagnosticConsumer::finishProcessing() { + for (auto &consumer: subConsumers) { + consumer->finishProcessing(); + } + return false; +} + +bool swift::ide::api::FilteringDiagnosticConsumer::shouldProceed(const DiagnosticInfo &Info) { if (allowedBreakages->empty()) { return true; } @@ -145,6 +164,8 @@ FilteringDiagnosticConsumer::handleDiagnostic(SourceManager &SM, if (Info.Kind == DiagnosticKind::Error) { HasError = true; } - subConsumer->handleDiagnostic(SM, Info); + for (auto &consumer: subConsumers) { + consumer->handleDiagnostic(SM, Info); + } } } diff --git a/lib/DriverTool/swift_api_digester_main.cpp b/lib/DriverTool/swift_api_digester_main.cpp index d7269e8e5892a..d6045d81b8f5c 100644 --- a/lib/DriverTool/swift_api_digester_main.cpp +++ b/lib/DriverTool/swift_api_digester_main.cpp @@ -1827,19 +1827,22 @@ static void findTypeMemberDiffs(NodePtr leftSDKRoot, NodePtr rightSDKRoot, } } -static std::unique_ptr +static std::vector> createDiagConsumer(llvm::raw_ostream &OS, bool &FailOnError, bool DisableFailOnError, bool CompilerStyleDiags, StringRef SerializedDiagPath) { + std::vector> results; if (!SerializedDiagPath.empty()) { FailOnError = !DisableFailOnError; - return serialized_diagnostics::createConsumer(SerializedDiagPath); + results.emplace_back(std::make_unique()); + results.emplace_back(serialized_diagnostics::createConsumer(SerializedDiagPath)); } else if (CompilerStyleDiags) { FailOnError = !DisableFailOnError; - return std::make_unique(); + results.emplace_back(std::make_unique()); } else { FailOnError = false; - return std::make_unique(true, OS); + results.emplace_back(std::make_unique(true, OS)); } + return results; } static int readFileLineByLine(StringRef Path, llvm::StringSet<> &Lines) { diff --git a/test/api-digester/serialized-diagnostics.swift b/test/api-digester/serialized-diagnostics.swift index cc6a7c6eccce0..d311f0a185664 100644 --- a/test/api-digester/serialized-diagnostics.swift +++ b/test/api-digester/serialized-diagnostics.swift @@ -3,10 +3,11 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -emit-module -o %t/color.swiftmodule %S/Inputs/cake_baseline/color.swift -parse-as-library -enable-library-evolution %clang-importer-sdk-nosource -module-name color -// RUN: %api-digester -diagnose-sdk -serialize-diagnostics-path %t/result.dia -empty-baseline -I %t %clang-importer-sdk-nosource -module color -abi +// RUN: %api-digester -diagnose-sdk -serialize-diagnostics-path %t/result.dia -empty-baseline -I %t %clang-importer-sdk-nosource -module color -abi 2>&1 | %FileCheck %s -check-prefix CHECK-STDERR // RUN: c-index-test -read-diagnostics %t/result.dia 2>&1 | %FileCheck %s -check-prefix CHECK-DIA // RUN: %api-digester -diagnose-sdk -serialize-diagnostics-path %t/result.dia -empty-baseline -I %t %clang-importer-sdk-nosource -module color -abi -disable-fail-on-error // RUN: c-index-test -read-diagnostics %t/result.dia 2>&1 | %FileCheck %s -check-prefix CHECK-DIA // Ensure the 'api-digester-breaking-change' category is included in the serialized diagnostics file. // CHECK-DIA: warning: ABI breakage: enum Color is a new API without @available attribute [] [api-digester-breaking-change] +// CHECK-STDERR: warning: ABI breakage: enum Color is a new API without @available attribute From a89d4f3ced2c870e051db5fef2cd712988ac1de8 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 29 Aug 2022 14:11:33 -0700 Subject: [PATCH 458/491] [interop][SwiftToCxx] add support for generic methods --- lib/PrintAsClang/DeclAndTypePrinter.cpp | 57 +++++++++++-------- lib/PrintAsClang/PrintClangFunction.cpp | 13 ++--- lib/PrintAsClang/PrintClangFunction.h | 3 +- .../generics/generic-function-execution.cpp | 18 ++++++ .../generics/generic-function-in-cxx.swift | 46 +++++++++++++++ 5 files changed, 102 insertions(+), 35 deletions(-) diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 4f75066753b8a..e0329f699f4b9 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -753,9 +753,9 @@ class DeclAndTypePrinter::Implementation typeDeclContext, accessor, funcABI->getSymbolName(), resultTy, /*isDefinition=*/false); } else { - declPrinter.printCxxMethod(typeDeclContext, AFD, - funcABI->getSymbolName(), resultTy, - /*isDefinition=*/false); + declPrinter.printCxxMethod( + typeDeclContext, AFD, funcABI->getSymbolName(), resultTy, + /*isDefinition=*/false, funcABI->additionalParams); } DeclAndTypeClangFunctionPrinter defPrinter( @@ -769,9 +769,9 @@ class DeclAndTypePrinter::Implementation typeDeclContext, accessor, funcABI->getSymbolName(), resultTy, /*isDefinition=*/true); } else { - defPrinter.printCxxMethod(typeDeclContext, AFD, - funcABI->getSymbolName(), resultTy, - /*isDefinition=*/true); + defPrinter.printCxxMethod( + typeDeclContext, AFD, funcABI->getSymbolName(), resultTy, + /*isDefinition=*/true, funcABI->additionalParams); } // FIXME: SWIFT_WARN_UNUSED_RESULT @@ -1068,6 +1068,9 @@ class DeclAndTypePrinter::Implementation bool useMangledSymbolName() const { return !isCDecl; } + SmallVector + additionalParams; + private: bool isCDecl; StringRef symbolName; @@ -1078,7 +1081,8 @@ class DeclAndTypePrinter::Implementation AbstractFunctionDecl *FD, Type resultTy, llvm::SmallVector ABIparams, llvm::SmallVector - ¶ms) { + ¶ms, + Optional selfTypeDeclContext = None) { for (auto param : ABIparams) { if (param.role == IRABIDetailsProvider::ABIAdditionalParam:: ABIParameterRole::GenericRequirementRole) @@ -1090,7 +1094,9 @@ class DeclAndTypePrinter::Implementation IRABIDetailsProvider::ABIAdditionalParam::ABIParameterRole::Self) params.push_back( {DeclAndTypeClangFunctionPrinter::AdditionalParam::Role::Self, - resultTy->getASTContext().getOpaquePointerType(), + selfTypeDeclContext + ? (*selfTypeDeclContext)->getDeclaredType() + : resultTy->getASTContext().getOpaquePointerType(), /*isIndirect=*/ isa(FD) ? cast(FD)->isMutating() : false}); else if (param.role == IRABIDetailsProvider::ABIAdditionalParam:: @@ -1135,23 +1141,29 @@ class DeclAndTypePrinter::Implementation owningPrinter.interopContext, owningPrinter); auto ABIparams = owningPrinter.interopContext.getIrABIDetails() .getFunctionABIAdditionalParams(FD); - llvm::SmallVector - additionalParams; - if (selfTypeDeclContext && !isa(FD)) { - additionalParams.push_back( + // FIXME: Ideally direct 'self' would come from IR provider too. + if (selfTypeDeclContext && !isa(FD) && + llvm::find_if( + ABIparams, + [](const IRABIDetailsProvider::ABIAdditionalParam &Param) { + return Param.role == IRABIDetailsProvider::ABIAdditionalParam:: + ABIParameterRole::Self; + }) == ABIparams.end()) { + funcABI.additionalParams.push_back( {DeclAndTypeClangFunctionPrinter::AdditionalParam::Role::Self, (*selfTypeDeclContext)->getDeclaredType(), /*isIndirect=*/ isa(FD) ? cast(FD)->isMutating() : false}); } - // FIXME: Fix the method 'self' parameter. - if (!selfTypeDeclContext && !ABIparams.empty()) - convertABIAdditionalParams(FD, resultTy, ABIparams, additionalParams); + if (!ABIparams.empty()) + convertABIAdditionalParams(FD, resultTy, ABIparams, + funcABI.additionalParams, + /*selfContext=*/selfTypeDeclContext); auto representation = funcPrinter.printFunctionSignature( FD, funcABI.getSymbolName(), resultTy, DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto, - additionalParams); + funcABI.additionalParams); if (representation.isUnsupported()) { // FIXME: Emit remark about unemitted declaration. return None; @@ -1195,12 +1207,6 @@ class DeclAndTypePrinter::Implementation DeclAndTypeClangFunctionPrinter funcPrinter( os, owningPrinter.prologueOS, owningPrinter.typeMapping, owningPrinter.interopContext, owningPrinter); - llvm::SmallVector - additionalParams; - auto ABIparams = owningPrinter.interopContext.getIrABIDetails() - .getFunctionABIAdditionalParams(FD); - if (!ABIparams.empty()) - convertABIAdditionalParams(FD, resultTy, ABIparams, additionalParams); DeclAndTypeClangFunctionPrinter::FunctionSignatureModifiers modifiers; modifiers.isInline = true; auto result = funcPrinter.printFunctionSignature( @@ -1215,9 +1221,10 @@ class DeclAndTypePrinter::Implementation printFunctionClangAttributes(FD, funcTy); printAvailability(FD); os << " {\n"; - funcPrinter.printCxxThunkBody( - funcABI.getSymbolName(), FD->getModuleContext(), resultTy, - FD->getParameters(), additionalParams, funcTy->isThrowing(), funcTy); + funcPrinter.printCxxThunkBody(funcABI.getSymbolName(), + FD->getModuleContext(), resultTy, + FD->getParameters(), funcABI.additionalParams, + funcTy->isThrowing(), funcTy); os << "}\n"; } diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index 9d4addff2641e..47bde681ce5e8 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -717,7 +717,8 @@ static StringRef getConstructorName(const AbstractFunctionDecl *FD) { void DeclAndTypeClangFunctionPrinter::printCxxMethod( const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD, - StringRef swiftSymbolName, Type resultTy, bool isDefinition) { + StringRef swiftSymbolName, Type resultTy, bool isDefinition, + ArrayRef additionalParams) { bool isConstructor = isa(FD); os << " "; @@ -744,15 +745,9 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod( os << " {\n"; // FIXME: should it be objTy for resultTy? - SmallVector additionalParams; - if (!isConstructor) - additionalParams.push_back(AdditionalParam{ - AdditionalParam::Role::Self, - typeDeclContext->getDeclaredType(), - /*isIndirect=*/isMutating, - }); printCxxThunkBody(swiftSymbolName, FD->getModuleContext(), resultTy, - FD->getParameters(), additionalParams, FD->hasThrows()); + FD->getParameters(), additionalParams, FD->hasThrows(), + FD->getInterfaceType()->castTo()); os << " }\n"; } diff --git a/lib/PrintAsClang/PrintClangFunction.h b/lib/PrintAsClang/PrintClangFunction.h index d575f6481a7dc..cc8e778836050 100644 --- a/lib/PrintAsClang/PrintClangFunction.h +++ b/lib/PrintAsClang/PrintClangFunction.h @@ -126,7 +126,8 @@ class DeclAndTypeClangFunctionPrinter { /// constructors. void printCxxMethod(const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD, StringRef swiftSymbolName, - Type resultTy, bool isDefinition); + Type resultTy, bool isDefinition, + ArrayRef additionalParams); /// Print the C++ getter/setter method signature. void printCxxPropertyAccessorMethod(const NominalTypeDecl *typeDeclContext, diff --git a/test/Interop/SwiftToCxx/generics/generic-function-execution.cpp b/test/Interop/SwiftToCxx/generics/generic-function-execution.cpp index 716b9957357de..219f9109ee036 100644 --- a/test/Interop/SwiftToCxx/generics/generic-function-execution.cpp +++ b/test/Interop/SwiftToCxx/generics/generic-function-execution.cpp @@ -206,5 +206,23 @@ int main() { // CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 65233) // CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 4294902062) // CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 65233) + { + auto x = createTestSmallStruct(42); + int passThru = x.genericMethodPassThrough((int)555); + assert(passThru == 555); + auto xprime = x.genericMethodPassThrough(x); + genericPrintFunction(xprime); + x.genericMethodMutTake((uint32_t)16); + genericPrintFunction(xprime); + genericPrintFunction(x); + x.genericMethodMutTake(xprime); + genericPrintFunction(xprime); + genericPrintFunction(x); + } +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 42) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 42) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 58) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 42) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 57) return 0; } diff --git a/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift b/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift index adcbf4c0af85c..f33276b64411e 100644 --- a/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift +++ b/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift @@ -72,18 +72,34 @@ public func createTestLargeStruct(_ x: Int) -> TestLargeStruct { return TestLargeStruct(x) } +@frozen public struct TestSmallStruct { var x1: UInt32 public mutating func mut() { x1 = ~x1 } + + public func genericMethodPassThrough(_ x: T) -> T { + return x + } + + public mutating func genericMethodMutTake(_ x: T) { + if let y = x as? UInt32 { + x1 += y + } else { + x1 -= 1 + } + } } public func createTestSmallStruct(_ x: UInt32) -> TestSmallStruct { return TestSmallStruct(x1: x) } +// CHECK: SWIFT_EXTERN void $s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(SWIFT_INDIRECT_RESULT void * _Nonnull, const void * _Nonnull x, struct swift_interop_stub_Functions_TestSmallStruct _self, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericMethodPassThrough(_:) +// CHECK-NEXT: SWIFT_EXTERN void $s9Functions15TestSmallStructV20genericMethodMutTakeyyxlF(const void * _Nonnull x, void * _Nonnull , SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // genericMethodMutTake(_:) + // CHECK: SWIFT_EXTERN void $s9Functions20genericPrintFunctionyyxlF(const void * _Nonnull x, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunction(_:) // CHECK-NEXT: SWIFT_EXTERN void $s9Functions32genericPrintFunctionMultiGenericyySi_xxSiq_tr0_lF(ptrdiff_t x, const void * _Nonnull t1, const void * _Nonnull t1p, ptrdiff_t y, const void * _Nonnull t2, void * _Nonnull , void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunctionMultiGeneric(_:_:_:_:_:) // CHECK-NEXT: SWIFT_EXTERN void $s9Functions26genericPrintFunctionTwoArgyyx_SitlF(const void * _Nonnull x, ptrdiff_t y, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunctionTwoArg(_:_:) @@ -95,6 +111,13 @@ public func createTestSmallStruct(_ x: UInt32) -> TestSmallStruct { // Skip templates in impl classes. // CHECK: _impl_TestSmallStruct // CHECK: template +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: inline T genericMethodPassThrough(const T & x) const; +// CHECK-NEXT: template +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: inline void genericMethodMutTake(const T & x); +// CHECK: template +// CHECK-NEXT: returnNewValue // CHECK: template // CHECK-NEXT: requires swift::isUsableInGenericContext @@ -139,3 +162,26 @@ public func createTestSmallStruct(_ x: UInt32) -> TestSmallStruct { // CHECK-NEXT: inline void genericSwap(T & x, T & y) noexcept { // CHECK-NEXT: return _impl::$s9Functions11genericSwapyyxz_xztlF(swift::_impl::getOpaquePointer(x), swift::_impl::getOpaquePointer(y), swift::getTypeMetadata()); // CHECK-NEXT: } + +// CHECK: template +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: inline T TestSmallStruct::genericMethodPassThrough(const T & x) const { +// CHECK-NEXT: if constexpr (std::is_base_of<::swift::_impl::RefCountedClass, T>::value) { +// CHECK-NEXT: void *returnValue; +// CHECK-NEXT: _impl::$s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(reinterpret_cast(&returnValue), swift::_impl::getOpaquePointer(x), _impl::swift_interop_passDirect_Functions_TestSmallStruct(_getOpaquePointer()), swift::getTypeMetadata()); +// CHECK-NEXT: return ::swift::_impl::implClassFor::type::makeRetained(returnValue); +// CHECK-NEXT: } else if constexpr (::swift::_impl::isValueType) { +// CHECK-NEXT: return ::swift::_impl::implClassFor::type::returnNewValue([&](void * _Nonnull returnValue) { +// CHECK-NEXT: _impl::$s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(returnValue, swift::_impl::getOpaquePointer(x), _impl::swift_interop_passDirect_Functions_TestSmallStruct(_getOpaquePointer()), swift::getTypeMetadata()); +// CHECK-NEXT: }); +// CHECK-NEXT: } else { +// CHECK-NEXT: T returnValue; +// CHECK-NEXT: _impl::$s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(reinterpret_cast(&returnValue), swift::_impl::getOpaquePointer(x), _impl::swift_interop_passDirect_Functions_TestSmallStruct(_getOpaquePointer()), swift::getTypeMetadata()); +// CHECK-NEXT: return returnValue; +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: template +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: inline void TestSmallStruct::genericMethodMutTake(const T & x) { +// CHECK-NEXT: return _impl::$s9Functions15TestSmallStructV20genericMethodMutTakeyyxlF(swift::_impl::getOpaquePointer(x), swift::getTypeMetadata(), _getOpaquePointer()); +// CHECK-NEXT: } From eebebd9a5571b100b5042445cadc728352c34f4e Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Mon, 29 Aug 2022 11:43:04 -0700 Subject: [PATCH 459/491] [Dependency Scanning] Do not persist cached Clang module dependencies between scans. This change tweaks the 'GlobalModuleDependenciesCache', which persists across scanner invocations with the same 'DependencyScanningTool' to no longer cache discovered Clang modules. Doing so felt like a premature optimization, and we should instead attempt to share as much state as possible by keeping around the actual Clang scanner's state, which performs its own caching. Caching discovered dependencies both in the Clang scanner instance, and in our own cache is much more error-prone - the Clang scanner has a richer context for what is okay and not okay to cache/re-use. Instead, we still cache discovered Clang dependencies *within* a given scan, since those are discovered using a common Clang scanner instance and should be safe to keep for the duration of the scan. This change should make it simpler to pin down the core functionality and correctness of the scanner. Once we turn our attention to the scanner's performance, we can revisit this strategy and optimize the caching behaviour. --- include/swift/AST/ModuleDependencies.h | 22 +++------ include/swift/AST/ModuleLoader.h | 3 +- include/swift/Sema/SourceLoader.h | 11 ++--- lib/AST/ModuleDependencies.cpp | 46 +++++++++++++++---- lib/AST/ModuleLoader.cpp | 1 + lib/ClangImporter/ImporterImpl.h | 1 + lib/DependencyScan/DependencyScanningTool.cpp | 6 +-- lib/DependencyScan/ScanDependencies.cpp | 14 ++---- lib/Frontend/Frontend.cpp | 1 + lib/Sema/SourceLoader.cpp | 9 ++++ 10 files changed, 69 insertions(+), 45 deletions(-) diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index f9c22bcd9d424..5fbd50b991e21 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -527,7 +527,6 @@ class GlobalModuleDependenciesCache { GlobalModuleDependenciesCache(const GlobalModuleDependenciesCache &) = delete; GlobalModuleDependenciesCache & operator=(const GlobalModuleDependenciesCache &) = delete; - virtual ~GlobalModuleDependenciesCache() {} void configureForTriple(std::string triple); @@ -603,24 +602,18 @@ class ModuleDependenciesCache { private: GlobalModuleDependenciesCache &globalCache; - /// References to data in `globalCache` for dependencies accimulated during + /// References to data in `globalCache` for Swift dependencies and + /// `clangModuleDependencies` for Clang dependencies accimulated during /// the current scanning action. ModuleDependenciesKindRefMap ModuleDependenciesMap; - /// Additional information needed for Clang dependency scanning. - ClangModuleDependenciesCacheImpl *clangImpl = nullptr; - - /// Name of the main Swift module of this scan - StringRef mainModuleName; - /// Underlying Clang module is seen differently by the main - /// module and by module clients. For this reason, we do not wish subsequent - /// scans to be able to re-use this dependency info and therefore we avoid - /// adding it to the global cache. The dependency storage is therefore tied - /// to this, local, cache. - std::unique_ptr underlyingClangModuleDependency = nullptr; + /// Discovered Clang modules are only cached locally. + llvm::StringMap clangModuleDependencies; /// Function that will delete \c clangImpl properly. void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *) = nullptr; + /// Additional information needed for Clang dependency scanning. + ClangModuleDependenciesCacheImpl *clangImpl = nullptr; /// Free up the storage associated with the Clang implementation. void destroyClangImpl() { @@ -647,8 +640,7 @@ class ModuleDependenciesCache { Optional kind) const; public: - ModuleDependenciesCache(GlobalModuleDependenciesCache &globalCache, - StringRef mainModuleName); + ModuleDependenciesCache(GlobalModuleDependenciesCache &globalCache); ModuleDependenciesCache(const ModuleDependenciesCache &) = delete; ModuleDependenciesCache &operator=(const ModuleDependenciesCache &) = delete; virtual ~ModuleDependenciesCache() { destroyClangImpl(); } diff --git a/include/swift/AST/ModuleLoader.h b/include/swift/AST/ModuleLoader.h index 8c7520dcf0c16..b0d290656f155 100644 --- a/include/swift/AST/ModuleLoader.h +++ b/include/swift/AST/ModuleLoader.h @@ -19,13 +19,13 @@ #include "swift/AST/Identifier.h" #include "swift/AST/Import.h" -#include "swift/AST/ModuleDependencies.h" #include "swift/Basic/ArrayRefView.h" #include "swift/Basic/Fingerprint.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/Located.h" #include "swift/Basic/SourceLoc.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/VersionTuple.h" #include @@ -52,6 +52,7 @@ class NominalTypeDecl; class SourceFile; class TypeDecl; class CompilerInstance; +enum class ModuleDependenciesKind : int8_t; enum class KnownProtocolKind : uint8_t; diff --git a/include/swift/Sema/SourceLoader.h b/include/swift/Sema/SourceLoader.h index 8820417ab9f43..ca2cfe3eb92e9 100644 --- a/include/swift/Sema/SourceLoader.h +++ b/include/swift/Sema/SourceLoader.h @@ -13,7 +13,6 @@ #ifndef SWIFT_SEMA_SOURCELOADER_H #define SWIFT_SEMA_SOURCELOADER_H -#include "swift/AST/ModuleDependencies.h" #include "swift/AST/ModuleLoader.h" namespace swift { @@ -94,14 +93,10 @@ class SourceLoader : public ModuleLoader { // Parsing populates the Objective-C method tables. } - Optional getModuleDependencies( - StringRef moduleName, ModuleDependenciesCache &cache, - InterfaceSubContextDelegate &delegate) override { - // FIXME: Implement? - return None; - } + Optional + getModuleDependencies(StringRef moduleName, ModuleDependenciesCache &cache, + InterfaceSubContextDelegate &delegate) override; }; - } #endif diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 39871f4e906af..3261dd38b9eee 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -388,6 +388,9 @@ GlobalModuleDependenciesCache::findSourceModuleDependency( bool GlobalModuleDependenciesCache::hasDependencies( StringRef moduleName, ModuleLookupSpecifics details) const { + assert(details.kind != ModuleDependenciesKind::Clang && + "Attempting to query Clang dependency in persistent Dependency " + "Scanner Cache."); return findDependencies(moduleName, details).hasValue(); } @@ -397,6 +400,9 @@ GlobalModuleDependenciesCache::findAllDependenciesIrrespectiveOfSearchPaths( if (!kind) { for (auto kind = ModuleDependenciesKind::FirstKind; kind != ModuleDependenciesKind::LastKind; ++kind) { + if (kind == ModuleDependenciesKind::Clang) + continue; + auto deps = findAllDependenciesIrrespectiveOfSearchPaths(moduleName, kind); if (deps.hasValue()) @@ -446,6 +452,10 @@ static std::string modulePathForVerification(const ModuleDependencies &module) { const ModuleDependencies *GlobalModuleDependenciesCache::recordDependencies( StringRef moduleName, ModuleDependencies dependencies) { auto kind = dependencies.getKind(); + assert(kind != ModuleDependenciesKind::Clang && + "Attempting to cache Clang dependency in persistent Dependency " + "Scanner Cache."); + // Source-based dependencies are recorded independently of the invocation's // target triple. if (kind == swift::ModuleDependenciesKind::SwiftSource) { @@ -482,6 +492,10 @@ const ModuleDependencies *GlobalModuleDependenciesCache::recordDependencies( const ModuleDependencies *GlobalModuleDependenciesCache::updateDependencies( ModuleDependencyID moduleID, ModuleDependencies dependencies) { auto kind = dependencies.getKind(); + assert(kind != ModuleDependenciesKind::Clang && + "Attempting to update Clang dependency in persistent Dependency " + "Scanner Cache."); + // Source-based dependencies if (kind == swift::ModuleDependenciesKind::SwiftSource) { assert(SwiftSourceModuleDependenciesMap.count(moduleID.first) == 1 && @@ -517,9 +531,8 @@ ModuleDependenciesCache::getDependencyReferencesMap( } ModuleDependenciesCache::ModuleDependenciesCache( - GlobalModuleDependenciesCache &globalCache, - StringRef mainModuleName) - : globalCache(globalCache), mainModuleName(mainModuleName) { + GlobalModuleDependenciesCache &globalCache) + : globalCache(globalCache) { for (auto kind = ModuleDependenciesKind::FirstKind; kind != ModuleDependenciesKind::LastKind; ++kind) { ModuleDependenciesMap.insert( @@ -572,12 +585,29 @@ void ModuleDependenciesCache::recordDependencies( // The underlying Clang module needs to be cached in this invocation, // but should not make it to the global cache since it will look slightly // differently for clients of this module than it does for the module itself. - const ModuleDependencies* recordedDependencies; - if (moduleName == mainModuleName && dependencies.isClangModule()) { - underlyingClangModuleDependency = std::make_unique(std::move(dependencies)); - recordedDependencies = underlyingClangModuleDependency.get(); + const ModuleDependencies *recordedDependencies; + if (dependencies.getKind() == ModuleDependenciesKind::Clang) { + auto *clangDep = dependencies.getAsClangModule(); + assert(clangDep && "Unexpected NULL Clang dependency."); + // Cache may already have a dependency for this module + if (clangModuleDependencies.count(moduleName) != 0) { + // Do not record duplicate dependencies. + auto newModulePath = clangDep->moduleMapFile; + for (auto &existingDeps : clangModuleDependencies[moduleName]) { + if (modulePathForVerification(existingDeps) == newModulePath) + return; + } + clangModuleDependencies[moduleName].emplace_back(std::move(dependencies)); + recordedDependencies = clangModuleDependencies[moduleName].end() - 1; + } else { + clangModuleDependencies.insert( + {moduleName, ModuleDependenciesVector{std::move(dependencies)}}); + recordedDependencies = &(clangModuleDependencies[moduleName].front()); + } + } else - recordedDependencies = globalCache.recordDependencies(moduleName, dependencies); + recordedDependencies = + globalCache.recordDependencies(moduleName, dependencies); auto &map = getDependencyReferencesMap(dependenciesKind); assert(map.count(moduleName) == 0 && "Already added to map"); diff --git a/lib/AST/ModuleLoader.cpp b/lib/AST/ModuleLoader.cpp index 5f73a13f9c5e6..fc396eecc6d65 100644 --- a/lib/AST/ModuleLoader.cpp +++ b/lib/AST/ModuleLoader.cpp @@ -18,6 +18,7 @@ #include "swift/AST/DiagnosticsCommon.h" #include "swift/AST/FileUnit.h" #include "swift/AST/ModuleLoader.h" +#include "swift/AST/ModuleDependencies.h" #include "swift/Basic/FileTypes.h" #include "swift/Basic/Platform.h" #include "swift/Basic/SourceManager.h" diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index dd88c8d5e6180..f6d64e835ce59 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -53,6 +53,7 @@ #include #include #include +#include #include namespace llvm { diff --git a/lib/DependencyScan/DependencyScanningTool.cpp b/lib/DependencyScan/DependencyScanningTool.cpp index f3571e0b73067..563f0a7fa3634 100644 --- a/lib/DependencyScan/DependencyScanningTool.cpp +++ b/lib/DependencyScan/DependencyScanningTool.cpp @@ -73,8 +73,7 @@ DependencyScanningTool::getDependencies( auto Instance = std::move(*InstanceOrErr); // Local scan cache instance, wrapping the shared global cache. - ModuleDependenciesCache cache(*SharedCache, - Instance->getMainModule()->getNameStr()); + ModuleDependenciesCache cache(*SharedCache); // Execute the scanning action, retrieving the in-memory result auto DependenciesOrErr = performModuleScan(*Instance.get(), cache); if (DependenciesOrErr.getError()) @@ -114,8 +113,7 @@ DependencyScanningTool::getDependencies( auto Instance = std::move(*InstanceOrErr); // Local scan cache instance, wrapping the shared global cache. - ModuleDependenciesCache cache(*SharedCache, - Instance->getMainModule()->getNameStr()); + ModuleDependenciesCache cache(*SharedCache); auto BatchScanResults = performBatchModuleScan( *Instance.get(), cache, VersionedPCMInstanceCacheCache.get(), Saver, BatchInput); diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index 1f1662e0c2af0..8dc8f99058030 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -1109,7 +1109,7 @@ forEachBatchEntry(CompilerInstance &invocationInstance, newGlobalCache->configureForTriple( newInstance->getInvocation().getLangOptions().Target.str()); auto newLocalCache = std::make_unique( - *newGlobalCache, newInstance->getMainModule()->getNameStr()); + *newGlobalCache); pInstance = newInstance.get(); pCache = newLocalCache.get(); subInstanceMap->insert( @@ -1253,8 +1253,7 @@ bool swift::dependencies::scanDependencies(CompilerInstance &instance) { if (opts.ReuseDependencyScannerCache) deserializeDependencyCache(instance, globalCache); - ModuleDependenciesCache cache(globalCache, - instance.getMainModule()->getNameStr()); + ModuleDependenciesCache cache(globalCache); // Execute scan auto dependenciesOrErr = performModuleScan(instance, cache); @@ -1289,8 +1288,7 @@ bool swift::dependencies::prescanDependencies(CompilerInstance &instance) { GlobalModuleDependenciesCache singleUseGlobalCache; singleUseGlobalCache.configureForTriple(instance.getInvocation() .getLangOptions().Target.str()); - ModuleDependenciesCache cache(singleUseGlobalCache, - instance.getMainModule()->getNameStr()); + ModuleDependenciesCache cache(singleUseGlobalCache); if (out.has_error() || EC) { Context.Diags.diagnose(SourceLoc(), diag::error_opening_output, path, EC.message()); @@ -1321,8 +1319,7 @@ bool swift::dependencies::batchScanDependencies( GlobalModuleDependenciesCache singleUseGlobalCache; singleUseGlobalCache.configureForTriple(instance.getInvocation() .getLangOptions().Target.str()); - ModuleDependenciesCache cache(singleUseGlobalCache, - instance.getMainModule()->getNameStr()); + ModuleDependenciesCache cache(singleUseGlobalCache); (void)instance.getMainModule(); llvm::BumpPtrAllocator alloc; llvm::StringSaver saver(alloc); @@ -1357,8 +1354,7 @@ bool swift::dependencies::batchPrescanDependencies( GlobalModuleDependenciesCache singleUseGlobalCache; singleUseGlobalCache.configureForTriple(instance.getInvocation() .getLangOptions().Target.str()); - ModuleDependenciesCache cache(singleUseGlobalCache, - instance.getMainModule()->getNameStr()); + ModuleDependenciesCache cache(singleUseGlobalCache); (void)instance.getMainModule(); llvm::BumpPtrAllocator alloc; llvm::StringSaver saver(alloc); diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 2df1ce62c71e5..205ec027b0b8a 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -21,6 +21,7 @@ #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/FileSystem.h" #include "swift/AST/Module.h" +#include "swift/AST/ModuleDependencies.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/Basic/FileTypes.h" #include "swift/Basic/SourceManager.h" diff --git a/lib/Sema/SourceLoader.cpp b/lib/Sema/SourceLoader.cpp index 36b25f800b703..f6cf035d480cb 100644 --- a/lib/Sema/SourceLoader.cpp +++ b/lib/Sema/SourceLoader.cpp @@ -20,6 +20,7 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/Module.h" +#include "swift/AST/ModuleDependencies.h" #include "swift/AST/SourceFile.h" #include "swift/Parse/PersistentParserState.h" #include "swift/Basic/SourceManager.h" @@ -149,3 +150,11 @@ void SourceLoader::loadExtensions(NominalTypeDecl *nominal, // Type-checking the source automatically loads all extensions; there's // nothing to do here. } + +Optional +SourceLoader::getModuleDependencies(StringRef moduleName, + ModuleDependenciesCache &cache, + InterfaceSubContextDelegate &delegate) { + // FIXME: Implement? + return None; +} From 842aa60b5b77d34d8f738212c59aea66e3240745 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 29 Aug 2022 14:33:03 -0700 Subject: [PATCH 460/491] [ConstraintSystem] Teach partial application check about implicit conversions Implicit conversion used to erase path for contextual type conversions but it does so no longer, this means that invalid partial application check needs to know about existence of implicit conversions that are not reflected in the AST until solution is applied. Resolves: rdar://99282932 --- lib/Sema/ConstraintSystem.cpp | 7 +++++++ .../implicit_double_cgfloat_conversion.swift | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 93553a4fd98bc..f32af13c5fe16 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -2751,6 +2751,13 @@ static std::pair isInvalidPartialApplication(ConstraintSystem &cs, const AbstractFunctionDecl *member, ConstraintLocator *locator) { + // If this is a compiler synthesized implicit conversion, let's skip + // the check because the base of `UDE` is not the base of the injected + // initializer. + if (locator->isLastElement() && + locator->findFirst()) + return {false, 0}; + auto *UDE = getAsExpr(locator->getAnchor()); if (UDE == nullptr) return {false,0}; diff --git a/test/Constraints/implicit_double_cgfloat_conversion.swift b/test/Constraints/implicit_double_cgfloat_conversion.swift index 9388e1efdb56f..e32394cbe1f90 100644 --- a/test/Constraints/implicit_double_cgfloat_conversion.swift +++ b/test/Constraints/implicit_double_cgfloat_conversion.swift @@ -315,3 +315,18 @@ do { } } } + +// rdar://99282938 +func test_implicit_conversion_clash_with_partial_application_check() { + class C { + var duration: CGFloat { 0.3 } + + var use: Double { + duration // Ok + } + + func transitionDuration() -> TimeInterval { + duration // Ok + } + } +} From 4ee63da49873046578508e0a775e101d3c28506d Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 26 Aug 2022 03:00:11 +0300 Subject: [PATCH 461/491] Gardening: Migrate test suite to GH issues: decl/protocol --- .../protocol/conforms/associated_type.swift | 50 +++++----- .../conforms/circular_validation.swift | 7 +- .../protocol/conforms/fixit_stub_editor.swift | 3 +- .../objc_from_witness_corner_case.swift | 2 +- test/decl/protocol/conforms/self.swift | 34 +++---- .../invalid_accessors_implementation.swift | 2 +- test/decl/protocol/protocols.swift | 56 +++++------ .../decl/protocol/recursive_requirement.swift | 3 +- .../protocol/recursive_requirement_ok.swift | 12 ++- .../req/associated_type_inference.swift | 93 ++++++++++--------- .../protocol/req/missing_conformance.swift | 2 +- test/decl/protocol/req/sr15460.swift | 2 + .../Inputs/struct_codable_simple_multi1.swift | 5 +- .../coding/class_codable_inherited.swift | 22 +++-- ...mmutable_property_with_initial_value.swift | 3 +- ...struct_codable_member_name_confusion.swift | 3 +- .../struct_codable_member_type_lookup.swift | 3 +- .../coding/struct_codable_simple.swift | 10 +- test/decl/protocol/sr8767.swift | 5 +- test/decl/protocol/typealias_inference.swift | 7 +- 20 files changed, 174 insertions(+), 150 deletions(-) diff --git a/test/decl/protocol/conforms/associated_type.swift b/test/decl/protocol/conforms/associated_type.swift index 7583d449f4cb3..b3bfb568346ee 100644 --- a/test/decl/protocol/conforms/associated_type.swift +++ b/test/decl/protocol/conforms/associated_type.swift @@ -12,7 +12,7 @@ struct X : P { // expected-error{{type 'X' does not conform to protocol 'P'}} typealias AssocA = Int // expected-note{{possibly intended match 'X.AssocA' (aka 'Int') does not conform to 'AnyObject'}} } -// SR-5166 +// https://github.com/apple/swift/issues/47742 protocol FooType { associatedtype BarType @@ -113,60 +113,60 @@ struct X2d : P2 { // expected-error{{type 'X2d' does not conform to protocol 'P2 } -// SR-12707 +// https://github.com/apple/swift/issues/55151 -class SR_12707_C {} +class GenClass {} // Regular type witnesses -protocol SR_12707_P1 { +protocol P3a { associatedtype A - associatedtype B: SR_12707_C<(A, Self)> // expected-note {{'B' declared here}} + associatedtype B: GenClass<(A, Self)> // expected-note {{'B' declared here}} } -struct SR_12707_Conform_P1: SR_12707_P1 { +struct S3a: P3a { typealias A = Never - typealias B = SR_12707_C<(A, SR_12707_Conform_P1)> + typealias B = GenClass<(A, S3a)> } // Type witness in protocol extension -protocol SR_12707_P2: SR_12707_P1 {} -extension SR_12707_P2 { - typealias B = SR_12707_C<(A, Self)> // expected-warning {{typealias overriding associated type 'B' from protocol 'SR_12707_P1' is better expressed as same-type constraint on the protocol}} +protocol P3b: P3a {} +extension P3b { + typealias B = GenClass<(A, Self)> // expected-warning {{typealias overriding associated type 'B' from protocol 'P3a' is better expressed as same-type constraint on the protocol}} } -struct SR_12707_Conform_P2: SR_12707_P2 { +struct S3b: P3b { typealias A = Never } // FIXME: resolveTypeWitnessViaLookup must not happen independently in the // general case. -protocol SR_12707_FIXME_P3 { - associatedtype A: SR_12707_C // expected-note {{protocol requires nested type 'A'; do you want to add it?}} +protocol P4 { + associatedtype A: GenClass // expected-note {{protocol requires nested type 'A'; do you want to add it?}} associatedtype B } -struct SR_12707_FIXME_Conform_P3: SR_12707_FIXME_P3 { // expected-error {{type 'SR_12707_FIXME_Conform_P3' does not conform to protocol 'SR_12707_FIXME_P3'}} - typealias A = SR_12707_C // expected-note {{possibly intended match 'SR_12707_FIXME_Conform_P3.A' (aka 'SR_12707_C') does not inherit from 'SR_12707_C'}} +struct S4: P4 { // expected-error {{type 'S4' does not conform to protocol 'P4'}} + typealias A = GenClass // expected-note {{possibly intended match 'S4.A' (aka 'GenClass') does not inherit from 'GenClass'}} typealias B = Never } // FIXME: Associated type inference via value witnesses should consider // tentative witnesses when checking a candidate. -protocol SR_12707_FIXME_P4 { +protocol P5 { associatedtype X = Never - associatedtype A: SR_12707_C // expected-note {{unable to infer associated type 'A' for protocol 'SR_12707_FIXME_P4'}} + associatedtype A: GenClass // expected-note {{unable to infer associated type 'A' for protocol 'P5'}} func foo(arg: A) } -struct SR_12707_FIXME_Conform_P4: SR_12707_FIXME_P4 { // expected-error {{type 'SR_12707_FIXME_Conform_P4' does not conform to protocol 'SR_12707_FIXME_P4'}} - func foo(arg: SR_12707_C) {} // expected-note {{candidate would match and infer 'A' = 'SR_12707_C' if 'SR_12707_C' inherited from 'SR_12707_C'}} +struct S5: P5 { // expected-error {{type 'S5' does not conform to protocol 'P5'}} + func foo(arg: GenClass) {} // expected-note {{candidate would match and infer 'A' = 'GenClass' if 'GenClass' inherited from 'GenClass'}} } // Abstract type witnesses. -protocol SR_12707_P5a { +protocol P6a { associatedtype X = Never - associatedtype A: SR_12707_C - associatedtype B: SR_12707_C + associatedtype A: GenClass + associatedtype B: GenClass } -protocol SR_12707_P5b: SR_12707_P5a where B == SR_12707_C { - associatedtype C: SR_12707_C = SR_12707_C +protocol P6b: P6a where B == GenClass { + associatedtype C: GenClass = GenClass } -struct SR_12707_Conform_P5>: SR_12707_P5b {} +struct S6>: P6b {} diff --git a/test/decl/protocol/conforms/circular_validation.swift b/test/decl/protocol/conforms/circular_validation.swift index f288f6d56d8ab..d653ca27bb577 100644 --- a/test/decl/protocol/conforms/circular_validation.swift +++ b/test/decl/protocol/conforms/circular_validation.swift @@ -12,7 +12,8 @@ struct S : P { // expected-error {{type 'S' does not conform to protocol 'P'}} var x = S.x // expected-note {{candidate references itself}} } +// https://github.com/apple/swift/issues/51713 // FIXME: Lousy diagnostics on this case. -protocol SR9224_Foo: SR9224_Foobar {} // expected-error {{protocol 'SR9224_Foo' refines itself}} -protocol SR9224_Bar: SR9224_Foobar {} -typealias SR9224_Foobar = SR9224_Foo & SR9224_Bar +protocol P1_51713: P1P2_51713 {} // expected-error {{protocol 'P1_51713' refines itself}} +protocol P2_51713: P1P2_51713 {} +typealias P1P2_51713 = P1_51713 & P2_51713 diff --git a/test/decl/protocol/conforms/fixit_stub_editor.swift b/test/decl/protocol/conforms/fixit_stub_editor.swift index 787af46dfba29..0304f5ac84d59 100644 --- a/test/decl/protocol/conforms/fixit_stub_editor.swift +++ b/test/decl/protocol/conforms/fixit_stub_editor.swift @@ -102,7 +102,8 @@ class Class4 {} extension Class4: PropertyMutabilityProto { // expected-error{{type 'Class4' does not conform to protocol 'PropertyMutabilityProto'}} expected-note{{do you want to add protocol stubs?}} {{44-44=\n var computed: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n\n var stored: Int {\n get {\n <#code#>\n \}\n set {\n <#code#>\n \}\n \}\n}} } -// https://bugs.swift.org/browse/SR-9868 +// https://github.com/apple/swift/issues/52274 + protocol FooProto { typealias CompletionType = (Int) -> Void func doSomething(then completion: @escaping CompletionType) diff --git a/test/decl/protocol/conforms/objc_from_witness_corner_case.swift b/test/decl/protocol/conforms/objc_from_witness_corner_case.swift index 7e666d617fccc..734b25c1b4bfb 100644 --- a/test/decl/protocol/conforms/objc_from_witness_corner_case.swift +++ b/test/decl/protocol/conforms/objc_from_witness_corner_case.swift @@ -6,7 +6,7 @@ // to validateDecl() getting called on a declaration. In this case, we // did not infer @objc from witnessed protocol requirements as required. // -// https://bugs.swift.org/browse/SR-10257 +// https://github.com/apple/swift/issues/52657 @objc public protocol P { @objc optional func f() diff --git a/test/decl/protocol/conforms/self.swift b/test/decl/protocol/conforms/self.swift index 6f8603d288f8f..a28b964b23db5 100644 --- a/test/decl/protocol/conforms/self.swift +++ b/test/decl/protocol/conforms/self.swift @@ -48,8 +48,8 @@ class NonFinalClass : P { subscript(_: T) -> Self { self } } -// Test for default implementation that comes from a constrained extension -// - https://bugs.swift.org/browse/SR-7422 +// (https://github.com/apple/swift/issues/49965) Test for default implementation +// that comes from a constrained extension. // FIXME: Better error message here? @@ -78,7 +78,7 @@ extension HasDefault where Self : SeriousClass { extension SeriousClass : HasDefault {} -// https://bugs.swift.org/browse/SR-7428 +// https://github.com/apple/swift/issues/49971 protocol Node { associatedtype ValueType = Int @@ -94,28 +94,30 @@ extension Node { class IntNode: Node {} -// SR-8902 -protocol P8902 { +// https://github.com/apple/swift/issues/51408 + +protocol P_51408 { associatedtype A func f(_ x: A) -> Self } -struct S : P8902 { - func f(_ x: Bool) -> S { fatalError() } +struct S : P_51408 { + func f(_ x: Bool) -> S {} } -class C8902 : P8902 { - func f(_ x: Bool) -> C8902 { fatalError() } // expected-error {{method 'f' in non-final class 'C8902' must return 'Self' to conform to protocol 'P8902'}} +class C1_51408 : P_51408 { + func f(_ x: Bool) -> C1_51408 {} // expected-error {{method 'f' in non-final class 'C1_51408' must return 'Self' to conform to protocol 'P_51408'}} } -final class C8902b : P8902 { - func f(_ x: Bool) -> C8902b { fatalError() } +final class C2_51408 : P_51408 { + func f(_ x: Bool) -> C2_51408 {} } -class C8902c : P8902 { - func f(_ x: Bool) -> Self { fatalError() } +class C3_51408 : P_51408 { + func f(_ x: Bool) -> Self {} } -protocol P8902complex { + +protocol P_51408_Complex { associatedtype A func f() -> (A, Self?) } -final class C8902complex : P8902complex { - func f() -> (Bool, C8902complex?) { fatalError() } +final class C_51408_Complex : P_51408_Complex { + func f() -> (Bool, C_51408_Complex?) {} } diff --git a/test/decl/protocol/invalid_accessors_implementation.swift b/test/decl/protocol/invalid_accessors_implementation.swift index 4efa529ef1656..61c30a042b599 100644 --- a/test/decl/protocol/invalid_accessors_implementation.swift +++ b/test/decl/protocol/invalid_accessors_implementation.swift @@ -2,7 +2,7 @@ //===--- -// SR-13963 +// https://github.com/apple/swift/issues/56360 //===--- protocol Protocol1 { diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift index 202f5c7c5408c..6c82849f1ef01 100644 --- a/test/decl/protocol/protocols.swift +++ b/test/decl/protocol/protocols.swift @@ -477,70 +477,70 @@ extension LetThereBeCrash { // expected-error@-2 {{'let' property 'xs' may not be initialized directly; use "self.init(...)" or "self = ..." instead}} } -// SR-11412 +// https://github.com/apple/swift/issues/53813 // Offer fix-it to conform type of context to the missing protocols -protocol SR_11412_P1 {} -protocol SR_11412_P2 {} -protocol SR_11412_P3 {} -protocol SR_11412_P4: AnyObject {} +protocol P1_53813 {} +protocol P2_53813 {} +protocol P3_53813 {} +protocol P4_53813: AnyObject {} -class SR_11412_C0 { - var foo1: SR_11412_P1? - var foo2: (SR_11412_P1 & SR_11412_P2)? - weak var foo3: SR_11412_P4? +class C0_53813 { + var foo1: P1_53813? + var foo2: (P1_53813 & P2_53813)? + weak var foo3: P4_53813? } // Context has no inherited types and does not conform to protocol // -class SR_11412_C1 { - let c0 = SR_11412_C0() +class C1_53813 { + let c0 = C0_53813() func conform() { - c0.foo1 = self // expected-error {{cannot assign value of type 'SR_11412_C1' to type '(any SR_11412_P1)?'}} - // expected-note@-1 {{add missing conformance to 'SR_11412_P1' to class 'SR_11412_C1'}}{{18-18=: SR_11412_P1}} + c0.foo1 = self // expected-error {{cannot assign value of type 'C1_53813' to type '(any P1_53813)?'}} + // expected-note@-1 {{add missing conformance to 'P1_53813' to class 'C1_53813'}}{{15-15=: P1_53813}} } } // Context has no inherited types and does not conform to protocol composition // -class SR_11412_C2 { - let c0 = SR_11412_C0() +class C2_53813 { + let c0 = C0_53813() func conform() { - c0.foo2 = self // expected-error {{cannot assign value of type 'SR_11412_C2' to type '(any SR_11412_P1 & SR_11412_P2)?'}} - // expected-note@-1 {{add missing conformance to 'SR_11412_P1 & SR_11412_P2' to class 'SR_11412_C2'}}{{18-18=: SR_11412_P1 & SR_11412_P2}} + c0.foo2 = self // expected-error {{cannot assign value of type 'C2_53813' to type '(any P1_53813 & P2_53813)?'}} + // expected-note@-1 {{add missing conformance to 'P1_53813 & P2_53813' to class 'C2_53813'}}{{15-15=: P1_53813 & P2_53813}} } } // Context already has an inherited type, but does not conform to protocol // -class SR_11412_C3: SR_11412_P3 { - let c0 = SR_11412_C0() +class C3_53813: P3_53813 { + let c0 = C0_53813() func conform() { - c0.foo1 = self // expected-error {{cannot assign value of type 'SR_11412_C3' to type '(any SR_11412_P1)?'}} - // expected-note@-1 {{add missing conformance to 'SR_11412_P1' to class 'SR_11412_C3'}}{{31-31=, SR_11412_P1}} + c0.foo1 = self // expected-error {{cannot assign value of type 'C3_53813' to type '(any P1_53813)?'}} + // expected-note@-1 {{add missing conformance to 'P1_53813' to class 'C3_53813'}}{{25-25=, P1_53813}} } } // Context conforms to only one protocol in the protocol composition // -class SR_11412_C4: SR_11412_P1 { - let c0 = SR_11412_C0() +class C4_53813: P1_53813 { + let c0 = C0_53813() func conform() { - c0.foo2 = self // expected-error {{cannot assign value of type 'SR_11412_C4' to type '(any SR_11412_P1 & SR_11412_P2)?'}} - // expected-note@-1 {{add missing conformance to 'SR_11412_P1 & SR_11412_P2' to class 'SR_11412_C4'}}{{31-31=, SR_11412_P2}} + c0.foo2 = self // expected-error {{cannot assign value of type 'C4_53813' to type '(any P1_53813 & P2_53813)?'}} + // expected-note@-1 {{add missing conformance to 'P1_53813 & P2_53813' to class 'C4_53813'}}{{25-25=, P2_53813}} } } // Context is a value type, but protocol requires class // -struct SR_11412_S0 { - let c0 = SR_11412_C0() +struct S0_53813 { + let c0 = C0_53813() func conform() { - c0.foo3 = self // expected-error {{cannot assign value of type 'SR_11412_S0' to type '(any SR_11412_P4)?'}} + c0.foo3 = self // expected-error {{cannot assign value of type 'S0_53813' to type '(any P4_53813)?'}} } } diff --git a/test/decl/protocol/recursive_requirement.swift b/test/decl/protocol/recursive_requirement.swift index c8a841d7bc4a9..60817c7c83679 100644 --- a/test/decl/protocol/recursive_requirement.swift +++ b/test/decl/protocol/recursive_requirement.swift @@ -106,7 +106,8 @@ protocol AsExistentialAssocTypeAgainB { func aMethod(_ object : AsExistentialAssocTypeAgainA) // expected-error {{use of protocol 'AsExistentialAssocTypeAgainA' as a type must be written 'any AsExistentialAssocTypeAgainA'}} } -// SR-547 +// https://github.com/apple/swift/issues/43164 + protocol A { associatedtype B1: B associatedtype C1: C diff --git a/test/decl/protocol/recursive_requirement_ok.swift b/test/decl/protocol/recursive_requirement_ok.swift index 40ab6f5d79210..995a14b23a218 100644 --- a/test/decl/protocol/recursive_requirement_ok.swift +++ b/test/decl/protocol/recursive_requirement_ok.swift @@ -15,7 +15,8 @@ func testP(_ t: T) { testP(t.assoc.assoc.assoc.assoc.assoc.assoc.assoc) } -// SR-5485 +// https://github.com/apple/swift/issues/48057 + protocol P1 { associatedtype X : P2 } @@ -27,7 +28,8 @@ protocol P2 { associatedtype Z : P1 } -// SR-5473 +// https://github.com/apple/swift/issues/48045 + protocol P3 { associatedtype X : P4 } @@ -53,7 +55,8 @@ protocol P6 : P5 { // CHECK: Generic signature: extension P6 where X == Y.X { } -// SR-5601 +// https://github.com/apple/swift/issues/48173 + protocol P7 { associatedtype X: P9 where X.Q == Self, X.R == UInt8 associatedtype Y: P9 where Y.Q == Self, Y.R == UInt16 @@ -73,7 +76,8 @@ struct S9 : P9 { typealias Q = A7 } -// SR-5610 +// https://github.com/apple/swift/issues/48180 + protocol P10 { associatedtype X : P11 where X.Q == Self } diff --git a/test/decl/protocol/req/associated_type_inference.swift b/test/decl/protocol/req/associated_type_inference.swift index 66914988f7040..5b0b4ebdcac8f 100644 --- a/test/decl/protocol/req/associated_type_inference.swift +++ b/test/decl/protocol/req/associated_type_inference.swift @@ -382,7 +382,8 @@ struct Int8Vector : Vector { func process(elements: [Int8]) { } } -// SR-4486 +// https://github.com/apple/swift/issues/47063 + protocol P13 { associatedtype Arg // expected-note{{protocol requires nested type 'Arg'; do you want to add it?}} func foo(arg: Arg) @@ -563,51 +564,6 @@ extension S31 where T: P32 { func boo() -> Void {} } -// SR-12707 - -class SR_12707_C {} - -// Inference in the adoptee -protocol SR_12707_P1 { - associatedtype A - associatedtype B: SR_12707_C<(A, Self)> - - func foo(arg: B) -} -struct SR_12707_Conform_P1: SR_12707_P1 { - typealias A = Never - - func foo(arg: SR_12707_C<(A, SR_12707_Conform_P1)>) {} -} - -// Inference in protocol extension -protocol SR_12707_P2: SR_12707_P1 {} -extension SR_12707_P2 { - func foo(arg: SR_12707_C<(A, Self)>) {} -} -struct SR_12707_Conform_P2: SR_12707_P2 { - typealias A = Never -} - -// SR-13172: Inference when witness is an enum case -protocol SR_13172_P1 { - associatedtype Bar - static func bar(_ value: Bar) -> Self -} - -enum SR_13172_E1: SR_13172_P1 { - case bar(String) // Okay -} - -protocol SR_13172_P2 { - associatedtype Bar - static var bar: Bar { get } -} - -enum SR_13172_E2: SR_13172_P2 { - case bar // Okay -} - /** References to type parameters in type witnesses. */ // Circular reference through a fixed type witness. @@ -705,6 +661,51 @@ do { } } +// https://github.com/apple/swift/issues/55151 + +class GenClass {} + +// Inference in the adoptee +protocol P43a { + associatedtype A + associatedtype B: GenClass<(A, Self)> + + func foo(arg: B) +} +struct S43a: P43a { + typealias A = Never + + func foo(arg: GenClass<(A, S43a)>) {} +} + +// Inference in protocol extension +protocol P43b: P43a {} +extension P43b { + func foo(arg: GenClass<(A, Self)>) {} +} +struct S43b: P43b { + typealias A = Never +} + +// https://github.com/apple/swift/issues/55614 +// Inference when witness is an enum case + +protocol P44 { + associatedtype Bar + static func bar(_ value: Bar) -> Self +} +enum E44: P44 { + case bar(String) // Okay +} + +protocol P45 { + associatedtype Bar + static var bar: Bar { get } +} +enum E45: P45 { + case bar // Okay +} + // Fails to find the fixed type witness B == FIXME_S1. protocol FIXME_P1a { associatedtype A: Equatable = Never // expected-note {{protocol requires nested type 'A'}} diff --git a/test/decl/protocol/req/missing_conformance.swift b/test/decl/protocol/req/missing_conformance.swift index 53d0cc2ac96db..28024fca88296 100644 --- a/test/decl/protocol/req/missing_conformance.swift +++ b/test/decl/protocol/req/missing_conformance.swift @@ -128,7 +128,7 @@ struct S5: P14 { // expected-error {{type 'S5' does not conform to protocol 'P14 // expected-note@-1 {{cannot infer 'A' = 'any P11' because 'any P11' as a type cannot conform to protocols; did you mean to use an opaque result type?}}{{24-24=some }} } -// SR-12759 +// https://github.com/apple/swift/issues/55204 // Note: the conformance to collection should succeed struct CountSteps1 : Collection { diff --git a/test/decl/protocol/req/sr15460.swift b/test/decl/protocol/req/sr15460.swift index af53b0705895a..16984761f0cc0 100644 --- a/test/decl/protocol/req/sr15460.swift +++ b/test/decl/protocol/req/sr15460.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/57765 + public protocol P {} extension Array { diff --git a/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift b/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift index 2bd193260a0f2..774d235955db9 100644 --- a/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift +++ b/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift @@ -22,8 +22,9 @@ struct SimpleStruct : Codable { } } -// SR-13137 Ensure unqualified lookup installs CodingKeys regardless of the -// order of primaries. +// https://github.com/apple/swift/issues/55584 +// Ensure unqualified lookup installs CodingKeys regardless of the order +// of primaries. struct A: Codable { var property: String static let propertyName = CodingKeys.property.stringValue diff --git a/test/decl/protocol/special/coding/class_codable_inherited.swift b/test/decl/protocol/special/coding/class_codable_inherited.swift index b55616ba92531..ad4b905786d62 100644 --- a/test/decl/protocol/special/coding/class_codable_inherited.swift +++ b/test/decl/protocol/special/coding/class_codable_inherited.swift @@ -1,23 +1,25 @@ // RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s -class SR8083_Base: Codable { +// https://github.com/apple/swift/issues/50616 + +class Base: Codable { var thing: String { return "Abstract" } } -class SR8083_Sub: SR8083_Base { +class Sub: Base { override var thing: String { return "Yo" } } -func sr8083(decoder: Decoder) throws { - _ = try SR8083_Sub(from: decoder) +func f(decoder: Decoder) throws { + _ = try Sub(from: decoder) } -// CHECK-LABEL: sil_vtable SR8083_Base { -// CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> () -> SR8083_Base : @$s23class_codable_inherited11SR8083_BaseCACycfC -// CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> (any Decoder) throws -> SR8083_Base : @$s23class_codable_inherited11SR8083_BaseC4fromACs7Decoder_p_tKcfC +// CHECK-LABEL: sil_vtable Base { +// CHECK-DAG: #Base.init!allocator: (Base.Type) -> () -> Base : @$s23class_codable_inherited4BaseCACycfC +// CHECK-DAG: #Base.init!allocator: (Base.Type) -> (any Decoder) throws -> Base : @$s23class_codable_inherited4BaseC4fromACs7Decoder_p_tKcfC // CHECK: {{^}$}} -// CHECK-LABEL: sil_vtable SR8083_Sub { -// CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> () -> SR8083_Base : @$s23class_codable_inherited10SR8083_SubCACycfC [override] -// CHECK-DAG: #SR8083_Base.init!allocator: (SR8083_Base.Type) -> (any Decoder) throws -> SR8083_Base : @$s23class_codable_inherited10SR8083_SubC4fromACs7Decoder_p_tKcfC [override] // SR8083_Sub.__allocating_init(from:) +// CHECK-LABEL: sil_vtable Sub { +// CHECK-DAG: #Base.init!allocator: (Base.Type) -> () -> Base : @$s23class_codable_inherited3SubCACycfC [override] +// CHECK-DAG: #Base.init!allocator: (Base.Type) -> (any Decoder) throws -> Base : @$s23class_codable_inherited3SubC4fromACs7Decoder_p_tKcfC [override] // Sub.__allocating_init(from:) // CHECK: {{^}$}} diff --git a/test/decl/protocol/special/coding/codable_immutable_property_with_initial_value.swift b/test/decl/protocol/special/coding/codable_immutable_property_with_initial_value.swift index 6d8b07b138647..39598eb8cb000 100644 --- a/test/decl/protocol/special/coding/codable_immutable_property_with_initial_value.swift +++ b/test/decl/protocol/special/coding/codable_immutable_property_with_initial_value.swift @@ -1,6 +1,7 @@ // RUN: %target-typecheck-verify-swift -verify-ignore-unknown -// SR-11996 - Warning when a immutable decodable property has an initial value +// https://github.com/apple/swift/issues/54430 +// Warning when a immutable decodable property has an initial value // Implicit CodingKeys enum // diff --git a/test/decl/protocol/special/coding/struct_codable_member_name_confusion.swift b/test/decl/protocol/special/coding/struct_codable_member_name_confusion.swift index 562671ac522ee..153728fcdef69 100644 --- a/test/decl/protocol/special/coding/struct_codable_member_name_confusion.swift +++ b/test/decl/protocol/special/coding/struct_codable_member_name_confusion.swift @@ -1,7 +1,8 @@ // RUN: %target-typecheck-verify-swift +// https://github.com/apple/swift/issues/52448 // Tests that, when synthesizing init(from:), we don't accidentally confuse -// static and instance properties with the same name. (SR-10045) +// static and instance properties with the same name. // The test fails if this file produces errors. struct X: Codable { diff --git a/test/decl/protocol/special/coding/struct_codable_member_type_lookup.swift b/test/decl/protocol/special/coding/struct_codable_member_type_lookup.swift index 220dcf0349ef2..778e1e8dcce8d 100644 --- a/test/decl/protocol/special/coding/struct_codable_member_type_lookup.swift +++ b/test/decl/protocol/special/coding/struct_codable_member_type_lookup.swift @@ -653,7 +653,8 @@ struct GenericCodableStruct : Codable {} func foo(_: GenericCodableStruct.CodingKeys) // expected-error {{'CodingKeys' is inaccessible due to 'private' protection level}} -struct sr6886 { +// https://github.com/apple/swift/issues/49435 +struct S_49435 { struct Nested : Codable {} let Nested: Nested // Don't crash with a coding key that is the same as a nested type name } diff --git a/test/decl/protocol/special/coding/struct_codable_simple.swift b/test/decl/protocol/special/coding/struct_codable_simple.swift index 347673eb85096..13b835fd82efa 100644 --- a/test/decl/protocol/special/coding/struct_codable_simple.swift +++ b/test/decl/protocol/special/coding/struct_codable_simple.swift @@ -30,20 +30,22 @@ let _ = SimpleStruct.encode(to:) // struct. let _ = SimpleStruct.CodingKeys.self // expected-error {{'CodingKeys' is inaccessible due to 'private' protection level}} -// rdar://problem/59655704 -struct SR_12248_1: Codable { // expected-error {{type 'SR_12248_1' does not conform to protocol 'Encodable'}} expected-error {{type 'SR_12248_1' does not conform to protocol 'Decodable'}} +// rdar://problem/59655704 +// https://github.com/apple/swift/issues/54675 + +struct S1_54675: Codable { // expected-error {{type 'S1_54675' does not conform to protocol 'Encodable'}} expected-error {{type 'S1_54675' does not conform to protocol 'Decodable'}} var x: Int // expected-note {{'x' previously declared here}} var x: Int // expected-error {{invalid redeclaration of 'x'}} // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'Int' does not conform to 'Encodable'}} // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'Int' does not conform to 'Encodable'}} } -struct SR_12248_2: Decodable { // expected-error {{type 'SR_12248_2' does not conform to protocol 'Decodable'}} +struct S2_54675: Decodable { // expected-error {{type 'S2_54675' does not conform to protocol 'Decodable'}} var x: Int // expected-note {{'x' previously declared here}} var x: Int // expected-error {{invalid redeclaration of 'x'}} } -struct SR_12248_3: Encodable { // expected-error {{type 'SR_12248_3' does not conform to protocol 'Encodable'}} +struct S3_54675: Encodable { // expected-error {{type 'S3_54675' does not conform to protocol 'Encodable'}} var x: Int // expected-note {{'x' previously declared here}} var x: Int // expected-error {{invalid redeclaration of 'x'}} } diff --git a/test/decl/protocol/sr8767.swift b/test/decl/protocol/sr8767.swift index 6b0cb653af89b..fe8246f44b68c 100644 --- a/test/decl/protocol/sr8767.swift +++ b/test/decl/protocol/sr8767.swift @@ -1,7 +1,8 @@ // RUN: %target-typecheck-verify-swift -// SR-8767: a number of related problems with unqualified lookup of -// associated type names. +// https://github.com/apple/swift/issues/51275 +// A number of related problems with unqualified lookup of associated +// type names. // #1 diff --git a/test/decl/protocol/typealias_inference.swift b/test/decl/protocol/typealias_inference.swift index 89b9c8dfaf3f2..b12382e7d0280 100644 --- a/test/decl/protocol/typealias_inference.swift +++ b/test/decl/protocol/typealias_inference.swift @@ -1,7 +1,10 @@ // RUN: %target-typecheck-verify-swift -// SR-8813 -// By itself in this file because this particular expected error is omitted if there have been any other diagnostics. +// https://github.com/apple/swift/issues/51321 +// +// By itself in this file because this particular expected error is omitted if +// there have been any other diagnostics. + protocol BaseProtocol { associatedtype Value typealias Closure = () -> Value From 5170a2e494e83e86df70a516e6c55fc09d274fcf Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Fri, 26 Aug 2022 22:14:17 -0300 Subject: [PATCH 462/491] [Parse] Handle underscored integer in #sourceLocation line directive --- include/swift/Parse/Parser.h | 2 ++ lib/Parse/ParseDecl.cpp | 8 ++++++-- lib/Parse/ParseExpr.cpp | 11 +++++++++++ test/Parse/line-directive.swift | 10 ++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index c72c33d23d674..3ea993aed80b8 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -1653,6 +1653,8 @@ class Parser { ParserResult parseExprRegexLiteral(); StringRef copyAndStripUnderscores(StringRef text); + StringRef stripUnderscoresIfNeeded(StringRef text, + SmallVectorImpl &buffer); ParserStatus parseStringSegments(SmallVectorImpl &Segments, Token EntireTok, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 7600e9718702c..0d27898c4781a 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -5809,7 +5809,9 @@ ParserStatus Parser::parseLineDirective(bool isLine) { diagnose(Tok, diag::expected_line_directive_number); return makeParserError(); } - if (Tok.getText().getAsInteger(0, StartLine)) { + SmallString<16> buffer; + auto text = stripUnderscoresIfNeeded(Tok.getText(), buffer); + if (text.getAsInteger(0, StartLine)) { diagnose(Tok, diag::expected_line_directive_number); return makeParserError(); } @@ -5840,7 +5842,9 @@ ParserStatus Parser::parseLineDirective(bool isLine) { diagnose(Tok, diag::expected_line_directive_number); return makeParserError(); } - if (Tok.getText().getAsInteger(0, StartLine)) { + SmallString<16> buffer; + auto text = stripUnderscoresIfNeeded(Tok.getText(), buffer); + if (text.getAsInteger(0, StartLine)) { diagnose(Tok, diag::expected_line_directive_number); return makeParserError(); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index c18a08f425395..83ce0d29d32a6 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1009,6 +1009,17 @@ StringRef Parser::copyAndStripUnderscores(StringRef orig) { return StringRef(start, p - start); } +StringRef Parser::stripUnderscoresIfNeeded(StringRef text, + SmallVectorImpl &buffer) { + if (text.contains('_')) { + buffer.clear(); + llvm::copy_if(text, std::back_inserter(buffer), + [](char ch) { return ch != '_'; }); + return StringRef(buffer.data(), buffer.size()); + } + return text; +} + /// Disambiguate the parse after '{' token that is in a place that might be /// the start of a trailing closure, or start the variable accessor block. /// diff --git a/test/Parse/line-directive.swift b/test/Parse/line-directive.swift index 45bd84afaf947..99b8841056b29 100644 --- a/test/Parse/line-directive.swift +++ b/test/Parse/line-directive.swift @@ -67,3 +67,13 @@ enum E { // CHECK: sr8772.swift:400:2: error: expected member name following '.' // CHECK: sr8772.swift:400:3: error: consecutive statements on a line must be separated by ';' // CHECK: sr8772.swift:400:3: error: expected expression + +// https://github.com/apple/swift/issues/55049 +class I55049 { +#sourceLocation(file: "issue-55049.swift", line: 1_000) + let bar = 12 +#sourceLocation(file: "issue-55049.swift", line: 2_000) +} + +#line 1_000 "issue-55049.swift" +class I55049_1 {} From 3b03a5ed9dab6ac33486d9088c606f472dca4d5b Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 29 Aug 2022 16:19:30 -0400 Subject: [PATCH 463/491] AST: Work around shortcoming in abstract conformance representation when computing override substitutions Fixes rdar://problem/98404650. --- lib/AST/SubstitutionMap.cpp | 19 +++++++++++++++++-- .../default_arguments_inherited_generic.swift | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 test/SILGen/default_arguments_inherited_generic.swift diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 6f697083bfc1d..5707efb49cd50 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -534,10 +534,25 @@ OverrideSubsInfo::OverrideSubsInfo(const NominalTypeDecl *baseNominal, if (auto baseNominalSig = baseNominal->getGenericSignature()) { BaseDepth = baseNominalSig.getGenericParams().back()->getDepth() + 1; + auto *genericEnv = derivedNominal->getGenericEnvironment(); auto derivedNominalTy = derivedNominal->getDeclaredInterfaceType(); + + // FIXME: Map in and out of context to get more accurate + // conformance information. If the base generic signature + // is and the derived generic signature is + // where C is a class that conforms to P, then we want the + // substitution map to store the concrete conformance C: P + // and not the abstract conformance T: P. + if (genericEnv) { + derivedNominalTy = genericEnv->mapTypeIntoContext( + derivedNominalTy); + } + BaseSubMap = derivedNominalTy->getContextSubstitutionMap( - baseNominal->getParentModule(), baseNominal); - assert(!BaseSubMap.hasArchetypes()); + baseNominal->getParentModule(), baseNominal, + genericEnv); + + BaseSubMap = BaseSubMap.mapReplacementTypesOutOfContext(); } if (auto derivedNominalSig = derivedNominal->getGenericSignature()) diff --git a/test/SILGen/default_arguments_inherited_generic.swift b/test/SILGen/default_arguments_inherited_generic.swift new file mode 100644 index 0000000000000..1dd2521f97236 --- /dev/null +++ b/test/SILGen/default_arguments_inherited_generic.swift @@ -0,0 +1,16 @@ +// RUN: %target-swift-emit-silgen %s | %FileCheck %s + +class Base { + init(x: Int = 0) {} +} + +class Derived : Base {} + +protocol P {} +class C: P {} + +_ = Derived() + +// CHECK-LABEL: sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer>>) -> Int32 { +// CHECK: [[FN:%.*]] = function_ref @$s35default_arguments_inherited_generic4BaseC1xACyxGSi_tcfcfA_ : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : P> () -> Int +// CHECK: apply [[FN]]() : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : P> () -> Int From 007fe96aafb8332978e2a070186f893bd08ccd2e Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 29 Aug 2022 16:20:01 -0400 Subject: [PATCH 464/491] AST: Don't build useless inherited conformances --- include/swift/AST/ASTContext.h | 2 +- lib/AST/ASTContext.cpp | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index d321e6bd7faca..21609f4ad0ea2 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -1255,7 +1255,7 @@ class ASTContext final { /// \param type The type for which we are retrieving the conformance. /// /// \param inherited The inherited conformance. - InheritedProtocolConformance * + ProtocolConformance * getInheritedConformance(Type type, ProtocolConformance *inherited); /// Get the lazy data for the given declaration. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 01218cc997116..16c878bfe28f1 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2448,30 +2448,39 @@ ASTContext::getSpecializedConformance(Type type, return result; } -InheritedProtocolConformance * +ProtocolConformance * ASTContext::getInheritedConformance(Type type, ProtocolConformance *inherited) { // Collapse multiple levels of inherited conformance. - while (auto *otherInherited = dyn_cast(inherited)) + if (auto *otherInherited = dyn_cast(inherited)) inherited = otherInherited->getInheritedConformance(); assert(isa(inherited) || isa(inherited) || isa(inherited)); + // Collapse useless inherited conformances. Conformance lookup with aa + // archetype T that has a superclass bound C will return a concrete + // conformance if C conforms to the protocol P. This is wrapped in an + // inherited conformance with the archetype type T. If you then substitute + // T := C, you don't want to form an inherited conformance with a type of + // C, because the underlying conformance already has a type of C. + if (inherited->getType()->isEqual(type)) + return inherited; + llvm::FoldingSetNodeID id; InheritedProtocolConformance::Profile(id, type, inherited); // Figure out which arena this conformance should go into. AllocationArena arena = getArena(type->getRecursiveProperties()); - // Did we already record the normal protocol conformance? + // Did we already record the inherited protocol conformance? void *insertPos; auto &inheritedConformances = getImpl().getArena(arena).InheritedConformances; if (auto result = inheritedConformances.FindNodeOrInsertPos(id, insertPos)) return result; - // Build a new normal protocol conformance. + // Build a new inherited protocol conformance. auto result = new (*this, arena) InheritedProtocolConformance(type, inherited); inheritedConformances.InsertNode(result, insertPos); return result; From d7a33551f8dfb7691c15124cd96fa62572e27474 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Sat, 27 Aug 2022 16:01:30 +1000 Subject: [PATCH 465/491] [Option] Add all new driver arguments (without implementations) Various clients still use the old driver to convert a driver arguments to frontend arguments. This has to work when given new driver arguments, ie. not fail with an unknown argument error. Move all "extra options" from the new driver into `Options.td` and mark them as new driver only. --- include/swift/AST/DiagnosticsDriver.def | 2 +- include/swift/Option/Options.td | 144 ++++++++++++++++-- .../one-way-merge-module-fine.swift | 10 +- test/Driver/diagnose-new-driver-flags.swift | 2 +- 4 files changed, 141 insertions(+), 17 deletions(-) diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def index 65f803f1cd3f7..033bdf555e343 100644 --- a/include/swift/AST/DiagnosticsDriver.def +++ b/include/swift/AST/DiagnosticsDriver.def @@ -183,7 +183,7 @@ WARNING(warn_drv_darwin_sdk_invalid_settings, none, ()) WARNING(warning_unsupported_driver_option,none, - "option '%0' is ony supported in swift-driver", (StringRef)) + "option '%0' is only supported in swift-driver", (StringRef)) WARNING(old_driver_deprecated,none, "legacy driver is now deprecated; consider avoiding specifying '%0'", (StringRef)) diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index c4dbcbb451bb7..93ad218dd6445 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -626,16 +626,6 @@ def experimental_cxx_stdlib : Flags<[HelpHidden]>, HelpText<"C++ standard library to use; forwarded to Clang's -stdlib flag">; -def experimental_emit_module_separately: - Flag<["-"], "experimental-emit-module-separately">, - Flags<[NoInteractiveOption, HelpHidden]>, - HelpText<"Emit module files as a distinct job (new Driver only)">; - -def no_emit_module_separately: - Flag<["-"], "no-emit-module-separately">, - Flags<[NoInteractiveOption, HelpHidden]>, - HelpText<"Force using merge-module as the incremental build mode (new Driver only)">; - def experimental_hermetic_seal_at_link: Flag<["-"], "experimental-hermetic-seal-at-link">, Flags<[FrontendOption, HelpHidden]>, @@ -1543,4 +1533,138 @@ def use_interface_for_module: Separate<["-", "--"], "use-interface-for-module">, HelpText<"Prefer loading these modules via interface">, MetaVarName<"">; +// ONLY SUPPORTED IN NEW DRIVER + +// These flags only exist here so that the old driver doesn't fail with unknown +// arguments when they're given. The option definitions (and ie. their flags) +// matter since they are synced to the new swift-driver. The options themselves +// are completely unimplemented in the old driver, however. + +def driver_print_graphviz: + Flag<["-"], "driver-print-graphviz">, + Flags<[HelpHidden, DoesNotAffectIncrementalBuild, NewDriverOnlyOption]>, + HelpText<"Write the job graph as a graphviz file">; + +def driver_explicit_module_build: + Flag<["-"], "explicit-module-build">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Prebuild module dependencies to make them explicit">; + +def driver_experimental_explicit_module_build: + Flag<["-"], "experimental-explicit-module-build">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + Alias, + HelpText<"Prebuild module dependencies to make them explicit">; + +def driver_scan_dependencies_non_lib: + Flag<["-"], "nonlib-dependency-scanner">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Use calls to `swift-frontend -scan-dependencies` instead of " + "dedicated dependency scanning library">; + +def driver_warn_unused_options: + Flag<["-"], "driver-warn-unused-options">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Emit warnings for any provided options which are unused by the " + "driver">; + +def emit_module_separately: + Flag<["-"], "experimental-emit-module-separately">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Emit module files as a distinct job">; + +def no_emit_module_separately: + Flag<["-"], "no-emit-module-separately">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Force using merge-module as the incremental build mode">; + +def emit_module_separately_WMO: + Flag<["-"], "emit-module-separately-wmo">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Emit module files as a distinct job in wmo builds">; + +def no_emit_module_separately_WMO: + Flag<["-"], "no-emit-module-separately-wmo">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Force emitting the swiftmodule in the same job in wmo builds">; + +def emit_module_serialize_diagnostics_path: + Separate<["-"], "emit-module-serialize-diagnostics-path">, + Flags<[ArgumentIsPath, SupplementaryOutput, NewDriverOnlyOption]>, + HelpText<"Emit a serialized diagnostics file for the emit-module task to " + "">, + MetaVarName<"">; + +def emit_module_dependencies_path: + Separate<["-"], "emit-module-dependencies-path">, + Flags<[ArgumentIsPath, SupplementaryOutput, NewDriverOnlyOption]>, + HelpText<"Emit a discovered dependencies file for the emit-module task to " + "">, + MetaVarName<"">; + +def use_frontend_parseable_output: + Flag<["-"], "use-frontend-parseable-output">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Emit parseable-output from swift-frontend jobs instead of from " + "the driver">; + +def print_explicit_dependency_graph: + Flag<["-"], "print-explicit-dependency-graph">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Print the result of module dependency scanning after external " + "module resolution to output">; + +def print_preprocessed_explicit_dependency_graph: + Flag<["-"], "print-preprocessed-explicit-dependency-graph">, + Flags<[HelpHidden, NewDriverOnlyOption]>, + HelpText<"Print the result of module dependency scanning to output">; + +def emit_digester_baseline: + Flag<["-"], "emit-digester-baseline">, + Flags<[NoInteractiveOption, SupplementaryOutput, NewDriverOnlyOption]>, + HelpText<"Emit a baseline file for the module using the API digester">; + +def emit_digester_baseline_path: + Separate<["-"], "emit-digester-baseline-path">, + Flags<[NoInteractiveOption, ArgumentIsPath, SupplementaryOutput, + NewDriverOnlyOption]>, + HelpText<"Emit a baseline file for the module to using the API " + "digester">, + MetaVarName<"">; + +def compare_to_baseline_path: + Separate<["-"], "compare-to-baseline-path">, + Flags<[NoInteractiveOption, ArgumentIsPath, NewDriverOnlyOption]>, + HelpText<"Compare the built module to the baseline at and diagnose " + "breaking changes using the API digester">, + MetaVarName<"">; + +def serialize_breaking_changes_path: + Separate<["-"], "serialize-breaking-changes-path">, + Flags<[NoInteractiveOption, ArgumentIsPath, NewDriverOnlyOption]>, + HelpText<"Serialize breaking changes found by the API digester to ">, + MetaVarName<"">; + +def digester_breakage_allowlist_path: + Separate<["-"], "digester-breakage-allowlist-path">, + Flags<[NoInteractiveOption, ArgumentIsPath, NewDriverOnlyOption]>, + HelpText<"The path to a list of permitted breaking changes the API digester " + "should ignore">, + MetaVarName<"">; + +def digester_mode: + Separate<["-"], "digester-mode">, + Flags<[NoInteractiveOption, NewDriverOnlyOption]>, + HelpText<"Whether the API digester should run in API or ABI mode (defaults " + "to API checking)">, + MetaVarName<"">; + +def nostartfiles: + Flag<["-"], "nostartfiles">, + Flags<[FrontendOption, DoesNotAffectIncrementalBuild, NoInteractiveOption, + HelpHidden, NewDriverOnlyOption]>, + HelpText<"Do not link in the Swift language startup routines">; + +// END ONLY SUPPORTED IN NEW DRIVER + include "FrontendOptions.td" diff --git a/test/Driver/Dependencies/one-way-merge-module-fine.swift b/test/Driver/Dependencies/one-way-merge-module-fine.swift index 0a1831f367aed..0dddf0e783adf 100644 --- a/test/Driver/Dependencies/one-way-merge-module-fine.swift +++ b/test/Driver/Dependencies/one-way-merge-module-fine.swift @@ -4,17 +4,17 @@ // RUN: cp -r %S/Inputs/one-way-fine/* %t // RUN: touch -t 201401240005 %t/* -// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v -no-emit-module-separately 2>&1 | %FileCheck -check-prefix=CHECK-FIRST %s +// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v 2>&1 | %FileCheck -check-prefix=CHECK-FIRST %s // CHECK-FIRST-NOT: warning -// CHECK-FIRST: Handled main.swift -// CHECK-FIRST: Handled other.swift -// CHECK-FIRST: Produced master.swiftmodule +// CHECK-FIRST-DAG: Handled main.swift +// CHECK-FIRST-DAG: Handled other.swift +// CHECK-FIRST-DAG: Produced master.swiftmodule // swift-driver checks existence of all outputs // RUN: touch -t 201401240006 %t/{main,other,master}.swift{module,doc,sourceinfo} -// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v -no-emit-module-separately 2>&1 | %FileCheck -check-prefix=CHECK-SECOND %s +// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v 2>&1 | %FileCheck -check-prefix=CHECK-SECOND %s // CHECK-SECOND-NOT: warning // CHECK-SECOND-NOT: Handled diff --git a/test/Driver/diagnose-new-driver-flags.swift b/test/Driver/diagnose-new-driver-flags.swift index 73f55747cb5e4..d3fb59a7bd4a2 100644 --- a/test/Driver/diagnose-new-driver-flags.swift +++ b/test/Driver/diagnose-new-driver-flags.swift @@ -1,3 +1,3 @@ // RUN: %swiftc_driver -emit-module -user-module-version 999.999 %s -### 2>&1 | %FileCheck %s -// CHECK: warning: option '-user-module-version' is ony supported in swift-driver +// CHECK: warning: option '-user-module-version' is only supported in swift-driver From cbc23cbafc41ef75c8b1c7825d90daf8140e2117 Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Mon, 29 Aug 2022 19:55:16 -0700 Subject: [PATCH 466/491] [Interop][SwiftToCxx] Support enum creation from Cxx --- lib/PrintAsClang/ClangSyntaxPrinter.cpp | 2 + lib/PrintAsClang/ClangSyntaxPrinter.h | 3 + lib/PrintAsClang/DeclAndTypePrinter.cpp | 378 ++++++++---- lib/PrintAsClang/ModuleContentsWriter.cpp | 6 +- lib/PrintAsClang/PrintClangFunction.cpp | 41 ++ lib/PrintAsClang/PrintClangFunction.h | 11 + lib/PrintAsClang/PrintClangValueType.cpp | 12 + .../enums/resilient-enum-in-cxx.swift | 34 +- .../swift-enum-case-functions-execution.cpp | 169 ----- .../enums/swift-enum-case-functions.swift | 584 ------------------ .../enums/swift-enum-cases-in-cxx.swift | 47 -- .../swift-enum-extract-payload-execution.cpp | 58 -- .../enums/swift-enum-extract-payload.swift | 218 ------- .../swift-enum-implementation-execution.cpp | 77 +++ .../enums/swift-enum-implementation.swift | 263 ++++++++ 15 files changed, 705 insertions(+), 1198 deletions(-) delete mode 100644 test/Interop/SwiftToCxx/enums/swift-enum-case-functions-execution.cpp delete mode 100644 test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift delete mode 100644 test/Interop/SwiftToCxx/enums/swift-enum-cases-in-cxx.swift delete mode 100644 test/Interop/SwiftToCxx/enums/swift-enum-extract-payload-execution.cpp delete mode 100644 test/Interop/SwiftToCxx/enums/swift-enum-extract-payload.swift create mode 100644 test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp create mode 100644 test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift diff --git a/lib/PrintAsClang/ClangSyntaxPrinter.cpp b/lib/PrintAsClang/ClangSyntaxPrinter.cpp index 48192ddea8bba..cd32dd8f6dfd1 100644 --- a/lib/PrintAsClang/ClangSyntaxPrinter.cpp +++ b/lib/PrintAsClang/ClangSyntaxPrinter.cpp @@ -19,6 +19,8 @@ using namespace swift; using namespace cxx_synthesis; +StringRef cxx_synthesis::getCxxSwiftNamespaceName() { return "swift"; } + StringRef cxx_synthesis::getCxxImplNamespaceName() { return "_impl"; } StringRef cxx_synthesis::getCxxOpaqueStorageClassName() { diff --git a/lib/PrintAsClang/ClangSyntaxPrinter.h b/lib/PrintAsClang/ClangSyntaxPrinter.h index 6fc38c599027b..37ef51d0169e1 100644 --- a/lib/PrintAsClang/ClangSyntaxPrinter.h +++ b/lib/PrintAsClang/ClangSyntaxPrinter.h @@ -25,6 +25,9 @@ class NominalTypeDecl; namespace cxx_synthesis { +/// Return the name of the namespace for things exported from Swift stdlib +StringRef getCxxSwiftNamespaceName(); + /// Return the name of the implementation namespace that is used to hide /// declarations from the namespace that corresponds to the imported Swift /// module in C++. diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index 4f75066753b8a..d255ebfe16e79 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -398,15 +398,261 @@ class DeclAndTypePrinter::Implementation ClangValueTypePrinter valueTypePrinter(os, owningPrinter.prologueOS, owningPrinter.typeMapping, owningPrinter.interopContext); - valueTypePrinter.printValueTypeDecl(ED, /*bodyPrinter=*/[&]() { - ClangSyntaxPrinter syntaxPrinter(os); - auto elementTagMapping = - owningPrinter.interopContext.getIrABIDetails().getEnumTagMapping(ED); - // Sort cases based on their assigned tag indices - llvm::stable_sort(elementTagMapping, [](const auto &p1, const auto &p2) { - return p1.second.tag < p2.second.tag; - }); + ClangSyntaxPrinter syntaxPrinter(os); + DeclAndTypeClangFunctionPrinter clangFuncPrinter( + os, owningPrinter.prologueOS, owningPrinter.typeMapping, + owningPrinter.interopContext, owningPrinter); + + auto &outOfLineOS = owningPrinter.outOfLineDefinitionsOS; + ClangSyntaxPrinter outOfLineSyntaxPrinter(outOfLineOS); + DeclAndTypeClangFunctionPrinter outOfLineFuncPrinter( + owningPrinter.outOfLineDefinitionsOS, owningPrinter.prologueOS, + owningPrinter.typeMapping, owningPrinter.interopContext, owningPrinter); + ClangValueTypePrinter outOfLineValTyPrinter( + owningPrinter.outOfLineDefinitionsOS, owningPrinter.prologueOS, + owningPrinter.typeMapping, owningPrinter.interopContext); + + auto elementTagMapping = + owningPrinter.interopContext.getIrABIDetails().getEnumTagMapping(ED); + // Sort cases based on their assigned tag indices + llvm::stable_sort(elementTagMapping, [](const auto &p1, const auto &p2) { + return p1.second.tag < p2.second.tag; + }); + + auto printIsFunction = [&](StringRef caseName, EnumDecl *ED) { + std::string declName, defName, name; + llvm::raw_string_ostream declOS(declName), defOS(defName), nameOS(name); + ClangSyntaxPrinter(nameOS).printIdentifier(caseName); + name[0] = std::toupper(name[0]); + + os << " inline bool is" << name << "() const;\n"; + + outOfLineOS << " inline bool "; + outOfLineSyntaxPrinter.printBaseName(ED); + outOfLineOS << "::is" << name << "() const {\n"; + outOfLineOS << " return *this == "; + outOfLineSyntaxPrinter.printBaseName(ED); + outOfLineOS << "::"; + outOfLineSyntaxPrinter.printIdentifier(caseName); + outOfLineOS << ";\n"; + outOfLineOS << " }\n"; + }; + + auto printGetFunction = [&](EnumElementDecl *elementDecl) { + auto associatedValueList = elementDecl->getParameterList(); + // TODO: add tuple type support + if (!elementDecl->hasAssociatedValues() || + associatedValueList->size() > 1) { + return; + } + auto paramType = associatedValueList->front()->getType(); + Type objectType; + OptionalTypeKind optKind; + std::tie(objectType, optKind) = getObjectTypeAndOptionality( + paramType->getNominalOrBoundGenericNominal(), paramType); + auto objectTypeDecl = objectType->getNominalOrBoundGenericNominal(); + + std::string declName, defName, name; + llvm::raw_string_ostream declOS(declName), defOS(defName), nameOS(name); + ClangSyntaxPrinter(nameOS).printIdentifier(elementDecl->getNameStr()); + name[0] = std::toupper(name[0]); + + clangFuncPrinter.printCustomCxxFunction( + {paramType}, + [&](auto &types) { + // Printing function name and return type + os << " inline " << types[paramType] << " get" << name; + outOfLineOS << " inline " << types[paramType] << ' '; + outOfLineSyntaxPrinter.printBaseName(ED); + outOfLineOS << "::get" << name; + }, + [&](auto &types) {}, true, + [&](auto &types) { + // Printing function body + outOfLineOS << " if (!is" << name << "()) abort();\n"; + outOfLineOS << " alignas("; + outOfLineSyntaxPrinter.printBaseName(elementDecl->getParentEnum()); + outOfLineOS << ") unsigned char buffer[sizeof("; + outOfLineSyntaxPrinter.printBaseName(elementDecl->getParentEnum()); + outOfLineOS << ")];\n"; + outOfLineOS << " auto *thisCopy = new(buffer) "; + outOfLineSyntaxPrinter.printBaseName(elementDecl->getParentEnum()); + outOfLineOS << "(*this);\n"; + outOfLineOS << " char * _Nonnull payloadFromDestruction = " + "thisCopy->_destructiveProjectEnumData();\n"; + if (auto knownCxxType = + owningPrinter.typeMapping.getKnownCxxTypeInfo( + objectTypeDecl)) { + outOfLineOS << " " << types[paramType] << " result;\n"; + outOfLineOS << " " + "memcpy(&result, payloadFromDestruction, " + "sizeof(result));\n"; + outOfLineOS << " return result;\n "; + } else { + outOfLineOS << " return swift::"; + outOfLineOS << cxx_synthesis::getCxxImplNamespaceName(); + outOfLineOS << "::implClassFor<"; + outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded( + objectTypeDecl->getModuleContext(), + elementDecl->getParentEnum()->getModuleContext()); + outOfLineSyntaxPrinter.printBaseName(objectTypeDecl); + outOfLineOS << ">::type"; + outOfLineOS << "::returnNewValue([&](char * _Nonnull result) {\n"; + outOfLineOS << " swift::" + << cxx_synthesis::getCxxImplNamespaceName(); + outOfLineOS << "::implClassFor<"; + outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded( + objectTypeDecl->getModuleContext(), + elementDecl->getParentEnum()->getModuleContext()); + outOfLineSyntaxPrinter.printBaseName(objectTypeDecl); + outOfLineOS << ">::type"; + outOfLineOS + << "::initializeWithTake(result, payloadFromDestruction);\n"; + outOfLineOS << " });\n "; + } + }, + ED->getModuleContext(), outOfLineOS); + }; + + auto printStruct = [&](StringRef caseName, EnumElementDecl *elementDecl, + Optional + elementInfo) { + os << " static struct { // impl struct for case " << caseName << '\n'; + os << " inline constexpr operator cases() const {\n"; + os << " return cases::"; + syntaxPrinter.printIdentifier(caseName); + os << ";\n"; + os << " }\n"; + + if (elementDecl != nullptr) { + assert(elementInfo.hasValue()); + + Type paramType, objectType; + NominalTypeDecl *objectTypeDecl = nullptr; + OptionalTypeKind optKind; + // TODO: support tuple type + if (elementDecl->hasAssociatedValues() && + elementDecl->getParameterList()->size() == 1) { + paramType = elementDecl->getParameterList()->front()->getType(); + std::tie(objectType, optKind) = getObjectTypeAndOptionality( + paramType->getNominalOrBoundGenericNominal(), paramType); + objectTypeDecl = objectType->getNominalOrBoundGenericNominal(); + } + + SmallVector neededTypes; + if (paramType) { + neededTypes.push_back(paramType); + } + + clangFuncPrinter.printCustomCxxFunction( + neededTypes, + [&](auto &types) { + // Printing function name and return type + os << " inline "; + syntaxPrinter.printBaseName(elementDecl->getParentEnum()); + os << " operator()"; + + outOfLineOS << " inline "; + outOfLineSyntaxPrinter.printBaseName( + elementDecl->getParentEnum()); + outOfLineOS << ' '; + outOfLineSyntaxPrinter.printBaseName( + elementDecl->getParentEnum()); + outOfLineOS << "::_impl_" << elementDecl->getNameStr() + << "::operator()"; + }, + [&](auto &types) { + // Printing parameters + if (!paramType) { + return; + } + assert(objectTypeDecl != nullptr); + if (owningPrinter.typeMapping.getKnownCxxTypeInfo( + objectTypeDecl)) { + os << types[paramType] << " val"; + outOfLineOS << types[paramType] << " val"; + } else { + os << "const " << types[paramType] << " &val"; + outOfLineOS << "const " << types[paramType] << " &val"; + } + }, + true, + [&](auto &types) { + // Printing function body + outOfLineOS << " auto result = "; + outOfLineSyntaxPrinter.printBaseName( + elementDecl->getParentEnum()); + outOfLineOS << "::_make();\n"; + + if (paramType) { + assert(objectTypeDecl != nullptr); + + if (owningPrinter.typeMapping.getKnownCxxTypeInfo( + objectTypeDecl)) { + outOfLineOS << " memcpy(result._getOpaquePointer(), &val, " + "sizeof(val));\n"; + } else { + outOfLineOS << " alignas("; + outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded( + objectTypeDecl->getModuleContext(), + ED->getModuleContext()); + outOfLineSyntaxPrinter.printBaseName(objectTypeDecl); + outOfLineOS << ") unsigned char buffer[sizeof("; + outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded( + objectTypeDecl->getModuleContext(), + ED->getModuleContext()); + outOfLineSyntaxPrinter.printBaseName(objectTypeDecl); + outOfLineOS << ")];\n"; + outOfLineOS << " auto *valCopy = new(buffer) "; + outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded( + objectTypeDecl->getModuleContext(), + ED->getModuleContext()); + outOfLineSyntaxPrinter.printBaseName(objectTypeDecl); + outOfLineOS << "(val);\n"; + outOfLineOS << " "; + outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName() + << "::"; + outOfLineOS << cxx_synthesis::getCxxImplNamespaceName(); + outOfLineOS << "::implClassFor<"; + outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded( + objectTypeDecl->getModuleContext(), + ED->getModuleContext()); + outOfLineSyntaxPrinter.printBaseName(objectTypeDecl); + outOfLineOS << ">::type::initializeWithTake(result._" + "getOpaquePointer(), "; + outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName() + << "::"; + outOfLineOS << cxx_synthesis::getCxxImplNamespaceName(); + outOfLineOS << "::implClassFor<"; + outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded( + objectTypeDecl->getModuleContext(), + ED->getModuleContext()); + outOfLineSyntaxPrinter.printBaseName(objectTypeDecl); + outOfLineOS << ">::type::getOpaquePointer(*valCopy)"; + outOfLineOS << ");\n"; + } + } + + outOfLineOS << " result._destructiveInjectEnumTag("; + if (ED->isResilient()) { + outOfLineOS << cxx_synthesis::getCxxImplNamespaceName() + << "::" << elementInfo->globalVariableName; + } else { + outOfLineOS << elementInfo->tag; + } + outOfLineOS << ");\n"; + outOfLineOS << " return result;\n"; + outOfLineOS << " "; + }, + ED->getModuleContext(), outOfLineOS); + } + os << " } "; + syntaxPrinter.printIdentifier(caseName); + os << ";\n"; + }; + + valueTypePrinter.printValueTypeDecl(ED, /*bodyPrinter=*/[&]() { os << '\n'; os << " enum class cases {"; llvm::interleave( @@ -419,117 +665,14 @@ class DeclAndTypePrinter::Implementation // TODO: allow custom name for this special case auto resilientUnknownDefaultCaseName = "unknownDefault"; if (ED->isResilient()) { - os << ",\n " << resilientUnknownDefaultCaseName; + os << (ED->getNumElements() > 0 ? ",\n " : "\n ") + << resilientUnknownDefaultCaseName; } os << "\n };\n\n"; // enum class cases' closing bracket - // Printing struct, is, and get functions for each case - DeclAndTypeClangFunctionPrinter clangFuncPrinter( - os, owningPrinter.prologueOS, owningPrinter.typeMapping, - owningPrinter.interopContext, owningPrinter); - - auto printIsFunction = [&](StringRef caseName, EnumDecl *ED) { - os << " inline bool is"; - std::string name; - llvm::raw_string_ostream nameStream(name); - ClangSyntaxPrinter(nameStream).printIdentifier(caseName); - name[0] = std::toupper(name[0]); - os << name << "() const {\n"; - os << " return *this == "; - syntaxPrinter.printBaseName(ED); - os << "::"; - syntaxPrinter.printIdentifier(caseName); - os << ";\n"; - os << " }\n"; - }; - - auto printGetFunction = [&](EnumElementDecl *elementDecl) { - auto associatedValueList = elementDecl->getParameterList(); - // TODO: add tuple type support - if (associatedValueList->size() > 1) { - return; - } - auto firstType = associatedValueList->front()->getType(); - auto firstTypeDecl = firstType->getNominalOrBoundGenericNominal(); - OptionalTypeKind optKind; - std::tie(firstType, optKind) = - getObjectTypeAndOptionality(firstTypeDecl, firstType); - - auto name = elementDecl->getNameStr().str(); - name[0] = std::toupper(name[0]); - - // FIXME: may have to forward declare return type - os << " inline "; - clangFuncPrinter.printClangFunctionReturnType( - firstType, optKind, firstTypeDecl->getModuleContext(), - owningPrinter.outputLang); - os << " get" << name << "() const {\n"; - os << " if (!is" << name << "()) abort();\n"; - os << " alignas("; - syntaxPrinter.printBaseName(elementDecl->getParentEnum()); - os << ") unsigned char buffer[sizeof("; - syntaxPrinter.printBaseName(elementDecl->getParentEnum()); - os << ")];\n"; - os << " auto *thisCopy = new(buffer) "; - syntaxPrinter.printBaseName(elementDecl->getParentEnum()); - os << "(*this);\n"; - os << " char * _Nonnull payloadFromDestruction = " - "thisCopy->_destructiveProjectEnumData();\n"; - if (auto knownCxxType = - owningPrinter.typeMapping.getKnownCxxTypeInfo(firstTypeDecl)) { - os << " "; - clangFuncPrinter.printClangFunctionReturnType( - firstType, optKind, firstTypeDecl->getModuleContext(), - owningPrinter.outputLang); - os << " result;\n"; - os << " " - "memcpy(&result, payloadFromDestruction, sizeof(result));\n"; - os << " return result;\n"; - } else { - os << " return "; - syntaxPrinter.printModuleNamespaceQualifiersIfNeeded( - firstTypeDecl->getModuleContext(), - elementDecl->getParentEnum()->getModuleContext()); - os << cxx_synthesis::getCxxImplNamespaceName(); - os << "::"; - ClangValueTypePrinter::printCxxImplClassName(os, firstTypeDecl); - os << "::returnNewValue([&](char * _Nonnull result) {\n"; - os << " " << cxx_synthesis::getCxxImplNamespaceName(); - os << "::"; - ClangValueTypePrinter::printCxxImplClassName(os, firstTypeDecl); - os << "::initializeWithTake(result, payloadFromDestruction);\n"; - os << " });\n"; - } - os << " }\n"; // closing bracket of get function - }; - - auto printStruct = [&](StringRef caseName, EnumElementDecl *elementDecl) { - os << " static struct { // impl struct for case " << caseName << '\n'; - os << " inline constexpr operator cases() const {\n"; - os << " return cases::"; - syntaxPrinter.printIdentifier(caseName); - os << ";\n"; - os << " }\n"; - if (elementDecl != nullptr) { - os << " inline "; - syntaxPrinter.printBaseName(elementDecl->getParentEnum()); - os << " operator()("; - // TODO: implement parameter for associated value - os << ") const {\n"; - // TODO: print _make for now; need to print actual code making an enum - os << " return "; - syntaxPrinter.printBaseName(elementDecl->getParentEnum()); - os << "::_make();\n"; - os << " }\n"; - } - os << " } "; - syntaxPrinter.printIdentifier(caseName); - os << ";\n"; - }; - for (const auto &pair : elementTagMapping) { // Printing struct - printStruct(pair.first->getNameStr(), pair.first); + printStruct(pair.first->getNameStr(), pair.first, pair.second); // Printing `is` function printIsFunction(pair.first->getNameStr(), ED); if (pair.first->hasAssociatedValues()) { @@ -541,7 +684,8 @@ class DeclAndTypePrinter::Implementation if (ED->isResilient()) { // Printing struct for unknownDefault - printStruct(resilientUnknownDefaultCaseName, /* elementDecl */ nullptr); + printStruct(resilientUnknownDefaultCaseName, /* elementDecl */ nullptr, + /* elementInfo */ None); // Printing isUnknownDefault printIsFunction(resilientUnknownDefaultCaseName, ED); os << '\n'; @@ -551,7 +695,9 @@ class DeclAndTypePrinter::Implementation // Printing operator cases() os << " inline operator cases() const {\n"; if (ED->isResilient()) { - os << " auto tag = _getEnumTag();\n"; + if (!elementTagMapping.empty()) { + os << " auto tag = _getEnumTag();\n"; + } for (const auto &pair : elementTagMapping) { os << " if (tag == " << cxx_synthesis::getCxxImplNamespaceName(); os << "::" << pair.second.globalVariableName << ") return cases::"; diff --git a/lib/PrintAsClang/ModuleContentsWriter.cpp b/lib/PrintAsClang/ModuleContentsWriter.cpp index 0e5b54696acd9..b59143de5ba6d 100644 --- a/lib/PrintAsClang/ModuleContentsWriter.cpp +++ b/lib/PrintAsClang/ModuleContentsWriter.cpp @@ -503,7 +503,11 @@ class ModuleWriter { bool writeEnum(const EnumDecl *ED) { if (addImport(ED)) return true; - + + if (outputLangMode == OutputLanguageMode::Cxx) { + forwardDeclareMemberTypes(ED->getMembers(), ED); + } + if (seenTypes[ED].first == EmissionState::Defined) return true; diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index 9d4addff2641e..292703ded8f06 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -824,3 +824,44 @@ bool DeclAndTypeClangFunctionPrinter::hasKnownOptionalNullableCxxMapping( } return false; } + +void DeclAndTypeClangFunctionPrinter::printCustomCxxFunction( + const SmallVector &neededTypes, PrinterTy retTypeAndNamePrinter, + PrinterTy paramPrinter, bool isConstFunc, PrinterTy bodyPrinter, + ModuleDecl *emittedModule, raw_ostream &outOfLineOS) { + llvm::MapVector types; + + for (auto &type : neededTypes) { + std::string typeStr; + llvm::raw_string_ostream typeOS(typeStr); + OptionalTypeKind optKind; + Type objectType; + std::tie(objectType, optKind) = + DeclAndTypePrinter::getObjectTypeAndOptionality( + type->getNominalOrBoundGenericNominal(), type); + + // Use FunctionSignatureTypeUse::ReturnType to avoid printing extra const or + // references + CFunctionSignatureTypePrinter typePrinter( + typeOS, cPrologueOS, typeMapping, OutputLanguageMode::Cxx, + interopContext, CFunctionSignatureTypePrinterModifierDelegate(), + emittedModule, declPrinter, FunctionSignatureTypeUse::ReturnType); + typePrinter.visit(objectType, optKind, /* isInOutParam */ false); + + types.insert({type, typeStr}); + } + + retTypeAndNamePrinter(types); + os << '('; + outOfLineOS << '('; + paramPrinter(types); + os << ')'; + outOfLineOS << ')'; + if (isConstFunc) { + os << " const;\n"; + outOfLineOS << " const"; + } + outOfLineOS << " {\n"; + bodyPrinter(types); + outOfLineOS << "}\n"; +} diff --git a/lib/PrintAsClang/PrintClangFunction.h b/lib/PrintAsClang/PrintClangFunction.h index d575f6481a7dc..3e112f3414a76 100644 --- a/lib/PrintAsClang/PrintClangFunction.h +++ b/lib/PrintAsClang/PrintClangFunction.h @@ -19,6 +19,7 @@ #include "swift/Basic/LLVM.h" #include "swift/ClangImporter/ClangImporter.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" @@ -140,6 +141,16 @@ class DeclAndTypeClangFunctionPrinter { ModuleDecl *moduleContext, OutputLanguageMode outputLang); + using PrinterTy = + llvm::function_ref &)>; + + /// Print generated C++ helper function + void printCustomCxxFunction(const SmallVector &neededTypes, + PrinterTy retTypeAndNamePrinter, + PrinterTy paramPrinter, bool isConstFunc, + PrinterTy bodyPrinter, ModuleDecl *emittedModule, + raw_ostream &outOfLineOS); + private: void printCxxToCFunctionParameterUse( Type type, StringRef name, const ModuleDecl *moduleContext, bool isInOut, diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index 75f0bca7879f5..f60a2d17ffbf0 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -270,11 +270,23 @@ void ClangValueTypePrinter::printValueTypeDecl( "metadata._0);\n"; os << " return _getOpaquePointer();\n"; os << " }\n"; + os << " inline void _destructiveInjectEnumTag(unsigned tag) {\n"; + printEnumVWTableVariable(); + os << " enumVWTable->destructiveInjectEnumTag(_getOpaquePointer(), tag, " + "metadata._0);\n"; + os << " }\n"; os << " inline unsigned _getEnumTag() const {\n"; printEnumVWTableVariable(); os << " return enumVWTable->getEnumTag(_getOpaquePointer(), " "metadata._0);\n"; os << " }\n"; + + for (const auto &pair : interopContext.getIrABIDetails().getEnumTagMapping( + cast(typeDecl))) { + os << " using _impl_" << pair.first->getNameStr() << " = decltype("; + ClangSyntaxPrinter(os).printIdentifier(pair.first->getNameStr()); + os << ");\n"; + } } // Print out the storage for the value type. os << " "; diff --git a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift index 22f3502a8b130..8fcbc486230ff 100644 --- a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift +++ b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift @@ -32,6 +32,30 @@ public func printFoo(_ x: Foo) { print(x) } +public enum Empty { + +} + +// CHECK: // Tags for resilient enum Empty +// CHECK-NEXT: extern "C" { +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } // namespace _impl +// CHECK-EMPTY: +// CHECK-NEXT: class Empty final { +// CHECK: enum class cases { +// CHECK-NEXT: unknownDefault +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case unknownDefault +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::unknownDefault; +// CHECK-NEXT: } +// CHECK-NEXT: } unknownDefault; +// CHECK-NEXT: inline bool isUnknownDefault() const; +// CHECK: inline operator cases() const { +// CHECK-NEXT: return cases::unknownDefault; +// CHECK-NEXT: } // CHECK: // Tags for resilient enum Foo // CHECK-NEXT: extern "C" { // CHECK-NEXT: extern unsigned $s5Enums3FooO1ayACSdcACmFWC; @@ -48,14 +72,14 @@ public func printFoo(_ x: Foo) { // CHECK-NEXT: unknownDefault // CHECK-NEXT: } // CHECK: static struct { // impl struct for case unknownDefault -// CHECK-NEXT: constexpr operator cases() const { +// CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::unknownDefault; // CHECK-NEXT: } // CHECK-NEXT: } unknownDefault; -// CHECK-NEXT: inline bool isUnknownDefault() const { -// CHECK-NEXT: return *this == Foo::unknownDefault; -// CHECK-NEXT: } -// CHECK: inline operator cases() const { +// CHECK-NEXT: inline bool isUnknownDefault() const; +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline operator cases() const { // CHECK-NEXT: auto tag = _getEnumTag(); // CHECK-NEXT: if (tag == _impl::$s5Enums3FooO1ayACSdcACmFWC) return cases::a; // NEW_CASE-NEXT: if (tag == _impl::$s5Enums3FooO1byACSicACmFWC) return cases::b; diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions-execution.cpp b/test/Interop/SwiftToCxx/enums/swift-enum-case-functions-execution.cpp deleted file mode 100644 index 80b58deab69aa..0000000000000 --- a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions-execution.cpp +++ /dev/null @@ -1,169 +0,0 @@ -// RUN: %empty-directory(%t) - -// RUN: %target-swift-frontend %S/swift-enum-case-functions.swift -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h - -// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-enums-execution.o -// RUN: %target-interop-build-swift %S/swift-enum-case-functions.swift -o %t/swift-enums-execution -Xlinker %t/swift-enums-execution.o -module-name Enums -Xfrontend -entry-point-function-name -Xfrontend swiftMain - -// RUN: %target-codesign %t/swift-enums-execution -// RUN: %target-run %t/swift-enums-execution - -// REQUIRES: executable_test - -#include -#include "enums.h" - -using namespace Enums; - -void cxxCheckEnum(const DataCase &e) { - assert(e.isOne()); -} - -void cxxCheckEnum(const CLikeEnum &e) { - switch (e) { - case CLikeEnum::cases::one: - assert(checkCLikeEnum(e, 1)); - assert(e.isOne()); - break; - case CLikeEnum::cases::two: - assert(checkCLikeEnum(e, 2)); - assert(e.isTwo()); - break; - case CLikeEnum::cases::three: - assert(checkCLikeEnum(e, 3)); - assert(e.isThree()); - break; - } -} - -void cxxCheckEnum(const BoolWithCase &e) { - switch (e) { - case BoolWithCase::cases::first: - assert(checkBoolWithCase(e, 1)); - assert(e.isFirst()); - break; - case BoolWithCase::cases::second: - assert(checkBoolWithCase(e, 2)); - assert(e.isSecond()); - break; - case BoolWithCase::cases::third: - assert(checkBoolWithCase(e, 3)); - assert(e.isThird()); - break; - } -} - -void cxxCheckEnum(const IntOrInfinity &e) { - switch (e) { - case IntOrInfinity::cases::NegInfinity: - assert(checkIntOrInfinity(e, 1)); - assert(e.isNegInfinity()); - break; - case IntOrInfinity::cases::Int: - assert(checkIntOrInfinity(e, 2)); - assert(e.isInt()); - break; - case IntOrInfinity::cases::PosInfinity: - assert(checkIntOrInfinity(e, 3)); - assert(e.isPosInfinity()); - break; - } -} - -void cxxCheckEnum(const MultipleBoolWithCase &e) { - switch (e) { - case MultipleBoolWithCase::cases::first: - assert(checkMultipleBoolWithCase(e, 1)); - assert(e.isFirst()); - break; - case MultipleBoolWithCase::cases::second: - assert(checkMultipleBoolWithCase(e, 2)); - assert(e.isSecond()); - break; - case MultipleBoolWithCase::cases::third: - assert(checkMultipleBoolWithCase(e, 3)); - assert(e.isThird()); - break; - case MultipleBoolWithCase::cases::fourth: - assert(checkMultipleBoolWithCase(e, 4)); - assert(e.isFourth()); - break; - } -} - -void cxxCheckEnum(const IntDoubleOrBignum &e) { - switch (e) { - case IntDoubleOrBignum::cases::Int: - assert(checkIntDoubleOrBignum(e, 1)); - assert(e.isInt()); - break; - case IntDoubleOrBignum::cases::Double: - assert(checkIntDoubleOrBignum(e, 2)); - assert(e.isDouble()); - break; - case IntDoubleOrBignum::cases::Bignum: - assert(checkIntDoubleOrBignum(e, 3)); - assert(e.isBignum()); - break; - } -} - -int main() { - { - auto e1 = makeDataCase(); - cxxCheckEnum(e1); - } - - { - auto e1 = makeCLikeEnum(1); - auto e2 = makeCLikeEnum(2); - auto e3 = makeCLikeEnum(3); - - cxxCheckEnum(e1); - cxxCheckEnum(e2); - cxxCheckEnum(e3); - } - - { - auto e1 = makeBoolWithCase(1); - auto e2 = makeBoolWithCase(2); - auto e3 = makeBoolWithCase(3); - - cxxCheckEnum(e1); - cxxCheckEnum(e2); - cxxCheckEnum(e3); - } - - { - auto e1 = makeIntOrInfinity(1); - auto e2 = makeIntOrInfinity(2); - auto e3 = makeIntOrInfinity(3); - - cxxCheckEnum(e1); - cxxCheckEnum(e2); - cxxCheckEnum(e3); - } - - { - auto e1 = makeMultipleBoolWithCase(1); - auto e2 = makeMultipleBoolWithCase(2); - auto e3 = makeMultipleBoolWithCase(3); - auto e4 = makeMultipleBoolWithCase(4); - - cxxCheckEnum(e1); - cxxCheckEnum(e2); - cxxCheckEnum(e3); - cxxCheckEnum(e4); - } - - { - auto e1 = makeIntDoubleOrBignum(1); - auto e2 = makeIntDoubleOrBignum(2); - auto e3 = makeIntDoubleOrBignum(3); - - cxxCheckEnum(e1); - cxxCheckEnum(e2); - cxxCheckEnum(e3); - } - return 0; -} diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift b/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift deleted file mode 100644 index 92fa83885ff45..0000000000000 --- a/test/Interop/SwiftToCxx/enums/swift-enum-case-functions.swift +++ /dev/null @@ -1,584 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %s -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h -// RUN: %FileCheck %s < %t/enums.h - -// RUN: %check-interop-cxx-header-in-clang(%t/enums.h -Wno-unused-private-field -Wno-unused-function) - -// test case-related member functions and structs - -public enum DataCase { case one(_ x: Int) } - -public func makeDataCase() -> DataCase { return .one(10) } - -public enum CLikeEnum { case one, two, three } - -public func makeCLikeEnum(_ tag: Int) -> CLikeEnum { - switch tag { - case 1: - return .one - case 2: - return .two - default: - return .three - } -} - -public func checkCLikeEnum(_ x: CLikeEnum, tag: Int) -> Bool { - switch x { - case .one: - return tag == 1 - case .two: - return tag == 2 - case .three: - return ![1, 2].contains(tag) - } -} - -public enum BoolWithCase { - case first - case second(Bool) - case third -} - -public func makeBoolWithCase(_ tag: Int) -> BoolWithCase { - switch tag { - case 1: - return .first - case 2: - return .second(true) - default: - return .third - } -} - -public func checkBoolWithCase(_ x: BoolWithCase, tag: Int) -> Bool { - switch x { - case .first: - return tag == 1 - case .second: - return tag == 2 - case .third: - return ![1, 2].contains(tag) - } -} - -public enum IntOrInfinity { - case NegInfinity - case Int(Int) - case PosInfinity -} - -public func makeIntOrInfinity(_ tag: Int) -> IntOrInfinity { - switch tag { - case 1: - return .NegInfinity - case 2: - return .Int(123) - default: - return .PosInfinity - } -} - -public func checkIntOrInfinity(_ x: IntOrInfinity, tag: Int) -> Bool { - switch x { - case .NegInfinity: - return tag == 1 - case .Int: - return tag == 2 - case .PosInfinity: - return ![1, 2].contains(tag) - } -} - -public enum MultipleBoolWithCase { - case first - case second(Bool) - case third(Bool) - case fourth -} - -public func makeMultipleBoolWithCase(_ tag: Int) -> MultipleBoolWithCase { - switch tag { - case 1: - return .first - case 2: - return .second(true) - case 3: - return .third(false) - default: - return .fourth - } -} - -public func checkMultipleBoolWithCase(_ x: MultipleBoolWithCase, tag: Int) -> Bool { - switch x { - case .first: - return tag == 1 - case .second: - return tag == 2 - case .third: - return tag == 3 - case .fourth: - return ![1, 2, 3].contains(tag) - } -} - -public enum IntDoubleOrBignum { - case Int(Int) - case Double(Double) - case Bignum -} - -public func makeIntDoubleOrBignum(_ tag: Int) -> IntDoubleOrBignum { - switch tag { - case 1: - return .Int(10) - case 2: - return .Double(3.14) - default: - return .Bignum - } -} - -public func checkIntDoubleOrBignum(_ x: IntDoubleOrBignum, tag: Int) -> Bool { - switch x { - case .Int: - return tag == 1 - case .Double: - return tag == 2 - case .Bignum: - return ![1, 2].contains(tag) - } -} - -// CHECK: class BoolWithCase final { - -// CHECK: static struct { // impl struct for case second -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::second; -// CHECK-NEXT: } -// CHECK-NEXT: inline BoolWithCase operator()() const { -// CHECK-NEXT: return BoolWithCase::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } second; -// CHECK-NEXT: inline bool isSecond() const { -// CHECK-NEXT: return *this == BoolWithCase::second; -// CHECK-NEXT: } -// CHECK-NEXT: inline bool getSecond() const { -// CHECK-NEXT: if (!isSecond()) abort(); -// CHECK-NEXT: alignas(BoolWithCase) unsigned char buffer[sizeof(BoolWithCase)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) BoolWithCase(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: bool result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case first -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::first; -// CHECK-NEXT: } -// CHECK-NEXT: inline BoolWithCase operator()() const { -// CHECK-NEXT: return BoolWithCase::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } first; -// CHECK-NEXT: inline bool isFirst() const { -// CHECK-NEXT: return *this == BoolWithCase::first; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case third -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::third; -// CHECK-NEXT: } -// CHECK-NEXT: inline BoolWithCase operator()() const { -// CHECK-NEXT: return BoolWithCase::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } third; -// CHECK-NEXT: inline bool isThird() const { -// CHECK-NEXT: return *this == BoolWithCase::third; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK-NEXT: inline operator cases() const { -// CHECK-NEXT: switch (_getEnumTag()) { -// CHECK-NEXT: case 0: return cases::second; -// CHECK-NEXT: case 1: return cases::first; -// CHECK-NEXT: case 2: return cases::third; -// CHECK-NEXT: default: abort(); -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK: inline unsigned _getEnumTag() const { -// CHECK-NEXT: auto metadata = _impl::$s5Enums12BoolWithCaseOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); -// CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); -// CHECK-NEXT: } -// CHECK: }; -// CHECK-NEXT: decltype(BoolWithCase::first) BoolWithCase::first; -// CHECK-NEXT: decltype(BoolWithCase::second) BoolWithCase::second; -// CHECK-NEXT: decltype(BoolWithCase::third) BoolWithCase::third; - -// CHECK: class CLikeEnum final { - -// CHECK: static struct { // impl struct for case one -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::one; -// CHECK-NEXT: } -// CHECK-NEXT: inline CLikeEnum operator()() const { -// CHECK-NEXT: return CLikeEnum::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } one; -// CHECK-NEXT: inline bool isOne() const { -// CHECK-NEXT: return *this == CLikeEnum::one; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case two -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::two; -// CHECK-NEXT: } -// CHECK-NEXT: inline CLikeEnum operator()() const { -// CHECK-NEXT: return CLikeEnum::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } two; -// CHECK-NEXT: inline bool isTwo() const { -// CHECK-NEXT: return *this == CLikeEnum::two; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case three -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::three; -// CHECK-NEXT: } -// CHECK-NEXT: inline CLikeEnum operator()() const { -// CHECK-NEXT: return CLikeEnum::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } three; -// CHECK-NEXT: inline bool isThree() const { -// CHECK-NEXT: return *this == CLikeEnum::three; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK-NEXT: inline operator cases() const { -// CHECK-NEXT: switch (_getEnumTag()) { -// CHECK-NEXT: case 0: return cases::one; -// CHECK-NEXT: case 1: return cases::two; -// CHECK-NEXT: case 2: return cases::three; -// CHECK-NEXT: default: abort(); -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK: inline unsigned _getEnumTag() const { -// CHECK-NEXT: auto metadata = _impl::$s5Enums9CLikeEnumOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); -// CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); -// CHECK-NEXT: } -// CHECK: }; -// CHECK-NEXT: decltype(CLikeEnum::one) CLikeEnum::one; -// CHECK-NEXT: decltype(CLikeEnum::two) CLikeEnum::two; -// CHECK-NEXT: decltype(CLikeEnum::three) CLikeEnum::three; - -// CHECK: class DataCase final { - -// CHECK: static struct { // impl struct for case one -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::one; -// CHECK-NEXT: } -// CHECK-NEXT: inline DataCase operator()() const { -// CHECK-NEXT: return DataCase::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } one; -// CHECK-NEXT: inline bool isOne() const { -// CHECK-NEXT: return *this == DataCase::one; -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int getOne() const { -// CHECK-NEXT: if (!isOne()) abort(); -// CHECK-NEXT: alignas(DataCase) unsigned char buffer[sizeof(DataCase)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) DataCase(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: swift::Int result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK-NEXT: inline operator cases() const { -// CHECK-NEXT: switch (_getEnumTag()) { -// CHECK-NEXT: case 0: return cases::one; -// CHECK-NEXT: default: abort(); -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK: inline unsigned _getEnumTag() const { -// CHECK-NEXT: auto metadata = _impl::$s5Enums8DataCaseOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); -// CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); -// CHECK-NEXT: } -// CHECK: }; -// CHECK-NEXT: decltype(DataCase::one) DataCase::one; - -// CHECK: class IntDoubleOrBignum final { - -// CHECK: enum class cases { -// CHECK-NEXT: Int, -// CHECK-NEXT: Double, -// CHECK-NEXT: Bignum -// CHECK-NEXT: }; -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case Int -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::Int; -// CHECK-NEXT: } -// CHECK-NEXT: inline IntDoubleOrBignum operator()() const { -// CHECK-NEXT: return IntDoubleOrBignum::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } Int; -// CHECK-NEXT: inline bool isInt() const { -// CHECK-NEXT: return *this == IntDoubleOrBignum::Int; -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int getInt() const { -// CHECK-NEXT: if (!isInt()) abort(); -// CHECK-NEXT: alignas(IntDoubleOrBignum) unsigned char buffer[sizeof(IntDoubleOrBignum)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) IntDoubleOrBignum(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: swift::Int result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case Double -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::Double; -// CHECK-NEXT: } -// CHECK-NEXT: inline IntDoubleOrBignum operator()() const { -// CHECK-NEXT: return IntDoubleOrBignum::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } Double; -// CHECK-NEXT: inline bool isDouble() const { -// CHECK-NEXT: return *this == IntDoubleOrBignum::Double; -// CHECK-NEXT: } -// CHECK-NEXT: inline double getDouble() const { -// CHECK-NEXT: if (!isDouble()) abort(); -// CHECK-NEXT: alignas(IntDoubleOrBignum) unsigned char buffer[sizeof(IntDoubleOrBignum)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) IntDoubleOrBignum(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: double result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case Bignum -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::Bignum; -// CHECK-NEXT: } -// CHECK-NEXT: inline IntDoubleOrBignum operator()() const { -// CHECK-NEXT: return IntDoubleOrBignum::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } Bignum; -// CHECK-NEXT: inline bool isBignum() const { -// CHECK-NEXT: return *this == IntDoubleOrBignum::Bignum; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK-NEXT: inline operator cases() const { -// CHECK-NEXT: switch (_getEnumTag()) { -// CHECK-NEXT: case 0: return cases::Int; -// CHECK-NEXT: case 1: return cases::Double; -// CHECK-NEXT: case 2: return cases::Bignum; -// CHECK-NEXT: default: abort(); -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK: inline unsigned _getEnumTag() const { -// CHECK-NEXT: auto metadata = _impl::$s5Enums17IntDoubleOrBignumOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); -// CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); -// CHECK-NEXT: } -// CHECK: }; -// CHECK-NEXT: decltype(IntDoubleOrBignum::Int) IntDoubleOrBignum::Int; -// CHECK-NEXT: decltype(IntDoubleOrBignum::Double) IntDoubleOrBignum::Double; -// CHECK-NEXT: decltype(IntDoubleOrBignum::Bignum) IntDoubleOrBignum::Bignum; - -// CHECK: class IntOrInfinity final { - -// CHECK: static struct { // impl struct for case Int -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::Int; -// CHECK-NEXT: } -// CHECK-NEXT: inline IntOrInfinity operator()() const { -// CHECK-NEXT: return IntOrInfinity::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } Int; -// CHECK-NEXT: inline bool isInt() const { -// CHECK-NEXT: return *this == IntOrInfinity::Int; -// CHECK-NEXT: } -// CHECK-NEXT: inline swift::Int getInt() const { -// CHECK-NEXT: if (!isInt()) abort(); -// CHECK-NEXT: alignas(IntOrInfinity) unsigned char buffer[sizeof(IntOrInfinity)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) IntOrInfinity(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: swift::Int result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case NegInfinity -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::NegInfinity; -// CHECK-NEXT: } -// CHECK-NEXT: inline IntOrInfinity operator()() const { -// CHECK-NEXT: return IntOrInfinity::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } NegInfinity; -// CHECK-NEXT: inline bool isNegInfinity() const { -// CHECK-NEXT: return *this == IntOrInfinity::NegInfinity; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case PosInfinity -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::PosInfinity; -// CHECK-NEXT: } -// CHECK-NEXT: inline IntOrInfinity operator()() const { -// CHECK-NEXT: return IntOrInfinity::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } PosInfinity; -// CHECK-NEXT: inline bool isPosInfinity() const { -// CHECK-NEXT: return *this == IntOrInfinity::PosInfinity; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK-NEXT: inline operator cases() const { -// CHECK-NEXT: switch (_getEnumTag()) { -// CHECK-NEXT: case 0: return cases::Int; -// CHECK-NEXT: case 1: return cases::NegInfinity; -// CHECK-NEXT: case 2: return cases::PosInfinity; -// CHECK-NEXT: default: abort(); -// CHECK-NEXT: } -// CHECK: inline unsigned _getEnumTag() const { -// CHECK-NEXT: auto metadata = _impl::$s5Enums13IntOrInfinityOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); -// CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); -// CHECK-NEXT: } -// CHECK: }; -// CHECK-NEXT: decltype(IntOrInfinity::NegInfinity) IntOrInfinity::NegInfinity; -// CHECK-NEXT: decltype(IntOrInfinity::Int) IntOrInfinity::Int; -// CHECK-NEXT: decltype(IntOrInfinity::PosInfinity) IntOrInfinity::PosInfinity; - -// CHECK: class MultipleBoolWithCase final { - -// CHECK: static struct { // impl struct for case second -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::second; -// CHECK-NEXT: } -// CHECK-NEXT: inline MultipleBoolWithCase operator()() const { -// CHECK-NEXT: return MultipleBoolWithCase::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } second; -// CHECK-NEXT: inline bool isSecond() const { -// CHECK-NEXT: return *this == MultipleBoolWithCase::second; -// CHECK-NEXT: } -// CHECK-NEXT: inline bool getSecond() const { -// CHECK-NEXT: if (!isSecond()) abort(); -// CHECK-NEXT: alignas(MultipleBoolWithCase) unsigned char buffer[sizeof(MultipleBoolWithCase)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) MultipleBoolWithCase(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: bool result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case third -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::third; -// CHECK-NEXT: } -// CHECK-NEXT: inline MultipleBoolWithCase operator()() const { -// CHECK-NEXT: return MultipleBoolWithCase::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } third; -// CHECK-NEXT: inline bool isThird() const { -// CHECK-NEXT: return *this == MultipleBoolWithCase::third; -// CHECK-NEXT: } -// CHECK-NEXT: inline bool getThird() const { -// CHECK-NEXT: if (!isThird()) abort(); -// CHECK-NEXT: alignas(MultipleBoolWithCase) unsigned char buffer[sizeof(MultipleBoolWithCase)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) MultipleBoolWithCase(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: bool result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case first -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::first; -// CHECK-NEXT: } -// CHECK-NEXT: inline MultipleBoolWithCase operator()() const { -// CHECK-NEXT: return MultipleBoolWithCase::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } first; -// CHECK-NEXT: inline bool isFirst() const { -// CHECK-NEXT: return *this == MultipleBoolWithCase::first; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case fourth -// CHECK-NEXT: inline constexpr operator cases() const { -// CHECK-NEXT: return cases::fourth; -// CHECK-NEXT: } -// CHECK-NEXT: inline MultipleBoolWithCase operator()() const { -// CHECK-NEXT: return MultipleBoolWithCase::_make(); -// CHECK-NEXT: } -// CHECK-NEXT: } fourth; -// CHECK-NEXT: inline bool isFourth() const { -// CHECK-NEXT: return *this == MultipleBoolWithCase::fourth; -// CHECK-NEXT: } -// CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK-NEXT: inline operator cases() const { -// CHECK-NEXT: switch (_getEnumTag()) { -// CHECK-NEXT: case 0: return cases::second; -// CHECK-NEXT: case 1: return cases::third; -// CHECK-NEXT: case 2: return cases::first; -// CHECK-NEXT: case 3: return cases::fourth; -// CHECK-NEXT: default: abort(); -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK: inline unsigned _getEnumTag() const { -// CHECK-NEXT: auto metadata = _impl::$s5Enums20MultipleBoolWithCaseOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); -// CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); -// CHECK-NEXT: } -// CHECK: }; -// CHECK-NEXT: decltype(MultipleBoolWithCase::first) MultipleBoolWithCase::first; -// CHECK-NEXT: decltype(MultipleBoolWithCase::second) MultipleBoolWithCase::second; -// CHECK-NEXT: decltype(MultipleBoolWithCase::third) MultipleBoolWithCase::third; -// CHECK-NEXT: decltype(MultipleBoolWithCase::fourth) MultipleBoolWithCase::fourth; diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-cases-in-cxx.swift b/test/Interop/SwiftToCxx/enums/swift-enum-cases-in-cxx.swift deleted file mode 100644 index 991d9be94de7c..0000000000000 --- a/test/Interop/SwiftToCxx/enums/swift-enum-cases-in-cxx.swift +++ /dev/null @@ -1,47 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %s -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h -// RUN: %FileCheck %s < %t/enums.h - -// RUN: %check-interop-cxx-header-in-clang(%t/enums.h -Wno-unused-private-field -Wno-unused-function) - -public enum EnumMultipleElementsInSingleCase { case first, second } - -public enum EnumSingleElementInSingleCase { - case first - case second -} - -public enum EnumCaseIsSwiftKeyword { - case first(a: Int) - case `protocol`(b: Double) -} - -public enum EnumCaseIsCxxKeyword { - case first, second(x: Float) - case const -} - -// CHECK: class EnumCaseIsCxxKeyword final { -// CHECK: enum class cases { -// CHECK-NEXT: second, -// CHECK-NEXT: first, -// CHECK-NEXT: const_ -// CHECK-NEXT: }; - -// CHECK: class EnumCaseIsSwiftKeyword final { -// CHECK: enum class cases { -// CHECK-NEXT: first, -// CHECK-NEXT: protocol -// CHECK-NEXT: }; - -// CHECK: class EnumMultipleElementsInSingleCase final { -// CHECK: enum class cases { -// CHECK-NEXT: first, -// CHECK-NEXT: second -// CHECK-NEXT: }; - -// CHECK: class EnumSingleElementInSingleCase final { -// CHECK: enum class cases { -// CHECK-NEXT: first, -// CHECK-NEXT: second -// CHECK-NEXT: }; diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-extract-payload-execution.cpp b/test/Interop/SwiftToCxx/enums/swift-enum-extract-payload-execution.cpp deleted file mode 100644 index f6db08694b13d..0000000000000 --- a/test/Interop/SwiftToCxx/enums/swift-enum-extract-payload-execution.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// RUN: %empty-directory(%t) - -// RUN: %target-swift-frontend %S/swift-enum-extract-payload.swift -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h - -// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-enums-execution.o -// RUN: %target-interop-build-swift %S/swift-enum-extract-payload.swift -o %t/swift-enums-execution -Xlinker %t/swift-enums-execution.o -module-name Enums -Xfrontend -entry-point-function-name -Xfrontend swiftMain - -// RUN: %target-codesign %t/swift-enums-execution -// RUN: %target-run %t/swift-enums-execution - -// REQUIRES: executable_test - -#include -#include "enums.h" - -using namespace Enums; - -int main() { - { - auto xyz = makeXyz(1); - assert(xyz.isFirst()); - assert(checkFoo(Foo::init(1234), xyz.getFirst())); - assert(1234 == xyz.getFirst().getX()); - } - { - auto xyz = makeXyz(2); - assert(xyz.isSecond()); - assert(checkUvw(makeUvw(2), xyz.getSecond())); - assert(xyz.getSecond().isTwo()); - } - { - auto xyz = makeXyz(3); - assert(xyz.isThird()); - assert(checkBar(Bar::init(1.1, 2.2, 3.3, 4.4, 5.5, 6.6), xyz.getThird())); - assert(1.1 == xyz.getThird().getX1()); - assert(2.2 == xyz.getThird().getX2()); - assert(3.3 == xyz.getThird().getX3()); - assert(4.4 == xyz.getThird().getX4()); - assert(5.5 == xyz.getThird().getX5()); - assert(6.6 == xyz.getThird().getX6()); - } - { - auto e = makePrimitivePayload(1); - assert(e.isX()); - assert(e.getX() == 9999); - } - { - auto e = makePrimitivePayload(2); - assert(e.isY()); - assert(e.getY() == 3.14); - } - { - auto e = makePrimitivePayload(3); - assert(e.isZ()); - assert(e.getZ()); - } - return 0; -} diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-extract-payload.swift b/test/Interop/SwiftToCxx/enums/swift-enum-extract-payload.swift deleted file mode 100644 index f492bb907ba65..0000000000000 --- a/test/Interop/SwiftToCxx/enums/swift-enum-extract-payload.swift +++ /dev/null @@ -1,218 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %s -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h -// RUN: %FileCheck %s < %t/enums.h - -// RUN: %check-interop-cxx-header-in-clang(%t/enums.h -Wno-unused-private-field -Wno-unused-function) - -public enum PrimitivePayload { - case x(Int64) - case y(Double) - case z(Bool) -} - -public func makePrimitivePayload(_ x: Int) -> PrimitivePayload { - switch x { - case 1: - return .x(9999) - case 2: - return .y(3.14) - default: - return .z(true) - } -} - -public enum Uvw { - case one, two ,three -} - -public enum Xyz { - case first(Foo) - case second(Uvw) - case third(Bar) -} - -public struct Foo { - public var x: Int64 - public init(x: Int64) { - self.x = x - } -} - -public struct Bar { - public var x1, x2, x3, x4, x5, x6: Double - public init(x1: Double, x2: Double, x3: Double, x4: Double, x5: Double, x6: Double) { - self.x1 = x1 - self.x2 = x2 - self.x3 = x3 - self.x4 = x4 - self.x5 = x5 - self.x6 = x6 - } -} - -public func checkFoo(_ lhs: Foo, _ rhs: Foo) -> Bool { - return lhs.x == rhs.x -} - -public func checkBar(_ lhs: Bar, _ rhs: Bar) -> Bool { - return lhs.x1 == rhs.x1 && lhs.x2 == rhs.x2 && lhs.x3 == rhs.x3 && lhs.x4 == rhs.x4 && lhs.x5 == rhs.x5 && lhs.x6 == rhs.x6 -} - -public func checkUvw(_ lhs: Uvw, _ rhs: Uvw) -> Bool { - return lhs == rhs -} - -public func makeXyz(_ x: Int) -> Xyz { - switch x { - case 1: - return .first(Foo(x: 1234)) - case 2: - return .second(.two) - default: - return .third(Bar(x1: 1.1, x2: 2.2, x3: 3.3, x4: 4.4, x5: 5.5, x6: 6.6)) - } -} - -public func makeUvw(_ x: Int) -> Uvw { - switch x { - case 1: - return .one - case 2: - return .two - default: - return .three - } -} - -// CHECK: class _impl_Bar { -// CHECK: static inline void initializeWithTake(char * _Nonnull destStorage, char * _Nonnull srcStorage) { -// CHECK-NEXT: auto metadata = _impl::$s5Enums3BarVMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: vwTable->initializeWithTake(destStorage, srcStorage, metadata._0); -// CHECK-NEXT: } - -// CHECK: class _impl_Foo { -// CHECK: static inline void initializeWithTake(char * _Nonnull destStorage, char * _Nonnull srcStorage) { -// CHECK-NEXT: auto metadata = _impl::$s5Enums3FooVMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: vwTable->initializeWithTake(destStorage, srcStorage, metadata._0); -// CHECK-NEXT: } - -// CHECK: class PrimitivePayload final { -// CHECK: inline int64_t getX() const { -// CHECK-NEXT: if (!isX()) abort(); -// CHECK-NEXT: alignas(PrimitivePayload) unsigned char buffer[sizeof(PrimitivePayload)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) PrimitivePayload(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: int64_t result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK: inline double getY() const { -// CHECK-NEXT: if (!isY()) abort(); -// CHECK-NEXT: alignas(PrimitivePayload) unsigned char buffer[sizeof(PrimitivePayload)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) PrimitivePayload(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: double result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK: inline bool getZ() const { -// CHECK-NEXT: if (!isZ()) abort(); -// CHECK-NEXT: alignas(PrimitivePayload) unsigned char buffer[sizeof(PrimitivePayload)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) PrimitivePayload(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: bool result; -// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); -// CHECK-NEXT: return result; -// CHECK-NEXT: } -// CHECK: private: -// CHECK: inline char * _Nonnull _destructiveProjectEnumData() { -// CHECK-NEXT: auto metadata = _impl::$s5Enums16PrimitivePayloadOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); -// CHECK-NEXT: enumVWTable->destructiveProjectEnumData(_getOpaquePointer(), metadata._0); -// CHECK-NEXT: return _getOpaquePointer(); -// CHECK-NEXT: } -// CHECK: class _impl_PrimitivePayload { -// CHECK: static inline void initializeWithTake(char * _Nonnull destStorage, char * _Nonnull srcStorage) { -// CHECK-NEXT: auto metadata = _impl::$s5Enums16PrimitivePayloadOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: vwTable->initializeWithTake(destStorage, srcStorage, metadata._0); -// CHECK-NEXT: } - -// CHECK: class _impl_Uvw { -// CHECK: static inline void initializeWithTake(char * _Nonnull destStorage, char * _Nonnull srcStorage) { -// CHECK-NEXT: auto metadata = _impl::$s5Enums3UvwOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: vwTable->initializeWithTake(destStorage, srcStorage, metadata._0); -// CHECK-NEXT: } - -// CHECK: class Xyz final { -// CHECK: inline Foo getFirst() const { -// CHECK-NEXT: if (!isFirst()) abort(); -// CHECK-NEXT: alignas(Xyz) unsigned char buffer[sizeof(Xyz)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) Xyz(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: return _impl::_impl_Foo::returnNewValue([&](char * _Nonnull result) { -// CHECK-NEXT: _impl::_impl_Foo::initializeWithTake(result, payloadFromDestruction); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK: inline Bar getThird() const { -// CHECK-NEXT: if (!isThird()) abort(); -// CHECK-NEXT: alignas(Xyz) unsigned char buffer[sizeof(Xyz)]; -// CHECK-NEXT: auto *thisCopy = new(buffer) Xyz(*this); -// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); -// CHECK-NEXT: return _impl::_impl_Bar::returnNewValue([&](char * _Nonnull result) { -// CHECK-NEXT: _impl::_impl_Bar::initializeWithTake(result, payloadFromDestruction); -// CHECK-NEXT: }); -// CHECK-NEXT: } -// CHECK: private: -// CHECK: inline char * _Nonnull _destructiveProjectEnumData() { -// CHECK-NEXT: auto metadata = _impl::$s5Enums3XyzOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); -// CHECK-NEXT: enumVWTable->destructiveProjectEnumData(_getOpaquePointer(), metadata._0); -// CHECK-NEXT: return _getOpaquePointer(); -// CHECK-NEXT: } -// CHECK: class _impl_Xyz { -// CHECK: static inline void initializeWithTake(char * _Nonnull destStorage, char * _Nonnull srcStorage) { -// CHECK-NEXT: auto metadata = _impl::$s5Enums3XyzOMa(0); -// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; -// CHECK-NEXT: #ifdef __arm64e__ -// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); -// CHECK-NEXT: #else -// CHECK-NEXT: auto *vwTable = *vwTableAddr; -// CHECK-NEXT: #endif -// CHECK-NEXT: vwTable->initializeWithTake(destStorage, srcStorage, metadata._0); -// CHECK-NEXT: } diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp b/test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp new file mode 100644 index 0000000000000..3b1b60b37ad75 --- /dev/null +++ b/test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp @@ -0,0 +1,77 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend %S/swift-enum-implementation.swift -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h + +// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-enums-execution.o +// RUN: %target-interop-build-swift %S/swift-enum-implementation.swift -o %t/swift-enums-execution -Xlinker %t/swift-enums-execution.o -module-name Enums -Xfrontend -entry-point-function-name -Xfrontend swiftMain + +// RUN: %target-codesign %t/swift-enums-execution +// RUN: %target-run %t/swift-enums-execution + +// REQUIRES: executable_test + +#include +#include "enums.h" + +using namespace Enums; + +void switchTest(const E &e) { + switch (e) { + case E::x: + assert(e.isX()); + assert(e.getX() == 3.14); + break; + case E::y: + assert(e.isY()); + assert(e.getY() == nullptr); + break; + case E::z: + assert(e.isZ()); + assert(e.getZ().getX() == 1234); + break; + case E::w: + assert(e.isW()); + assert(e.getW() == 5678); + break; + case E::auto_: + assert(e.isAuto_()); + assert(e.getAuto_() == reinterpret_cast(1)); + break; + case E::foobar: + assert(e.isFoobar()); + break; + } +} + +int main() { + { + auto e = E::x(3.14); + switchTest(e); + } + + { + auto e = E::y(nullptr); + switchTest(e); + } + + { + auto e = E::z(S::init(1234)); + switchTest(e); + } + + { + auto e = E::w(5678); + switchTest(e); + } + + { + auto e = E::auto_(reinterpret_cast(1)); + switchTest(e); + } + + { + auto e = E::foobar(); + switchTest(e); + } + return 0; +} diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift b/test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift new file mode 100644 index 0000000000000..4ef1b9bdccd22 --- /dev/null +++ b/test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift @@ -0,0 +1,263 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h +// RUN: %FileCheck %s < %t/enums.h + +// RUN: %check-interop-cxx-header-in-clang(%t/enums.h -Wno-unused-private-field -Wno-unused-function) + +public enum E { + case x(Double) + case y(UnsafeRawPointer?) + case z(S) + case w(i: Int) + case auto(UnsafeMutableRawPointer) + case foobar +} + +public struct S { + public var x: Int64 + + public init(x: Int64) { + print("S.init()") + self.x = x + } +} + +// CHECK: class E final { +// CHECK: enum class cases { +// CHECK-NEXT: x, +// CHECK-NEXT: y, +// CHECK-NEXT: z, +// CHECK-NEXT: w, +// CHECK-NEXT: auto_, +// CHECK-NEXT: foobar +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case x +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::x; +// CHECK-NEXT: } +// CHECK-NEXT: inline E operator()(double val) const; +// CHECK-NEXT: } x; +// CHECK-NEXT: inline bool isX() const; +// CHECK-NEXT: inline double getX() const; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case y +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::y; +// CHECK-NEXT: } +// CHECK-NEXT: inline E operator()(void const * _Nullable val) const; +// CHECK-NEXT: } y; +// CHECK-NEXT: inline bool isY() const; +// CHECK-NEXT: inline void const * _Nullable getY() const; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case z +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::z; +// CHECK-NEXT: } +// CHECK-NEXT: inline E operator()(const S &val) const; +// CHECK-NEXT: } z; +// CHECK-NEXT: inline bool isZ() const; +// CHECK-NEXT: inline S getZ() const; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case w +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::w; +// CHECK-NEXT: } +// CHECK-NEXT: inline E operator()(swift::Int val) const; +// CHECK-NEXT: } w; +// CHECK-NEXT: inline bool isW() const; +// CHECK-NEXT: inline swift::Int getW() const; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case auto +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::auto_; +// CHECK-NEXT: } +// CHECK-NEXT: inline E operator()(void * _Nonnull val) const; +// CHECK-NEXT: } auto_; +// CHECK-NEXT: inline bool isAuto_() const; +// CHECK-NEXT: inline void * _Nonnull getAuto_() const; +// CHECK-EMPTY: +// CHECK-NEXT: static struct { // impl struct for case foobar +// CHECK-NEXT: inline constexpr operator cases() const { +// CHECK-NEXT: return cases::foobar; +// CHECK-NEXT: } +// CHECK-NEXT: inline E operator()() const; +// CHECK-NEXT: } foobar; +// CHECK-NEXT: inline bool isFoobar() const; +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: inline operator cases() const { +// CHECK-NEXT: switch (_getEnumTag()) { +// CHECK-NEXT: case 0: return cases::x; +// CHECK-NEXT: case 1: return cases::y; +// CHECK-NEXT: case 2: return cases::z; +// CHECK-NEXT: case 3: return cases::w; +// CHECK-NEXT: case 4: return cases::auto_; +// CHECK-NEXT: case 5: return cases::foobar; +// CHECK-NEXT: default: abort(); +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK: private: +// CHECK: inline char * _Nonnull _destructiveProjectEnumData() { +// CHECK-NEXT: auto metadata = _impl::$s5Enums1EOMa(0); +// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; +// CHECK-NEXT: #ifdef __arm64e__ +// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); +// CHECK-NEXT: #else +// CHECK-NEXT: auto *vwTable = *vwTableAddr; +// CHECK-NEXT: #endif +// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); +// CHECK-NEXT: enumVWTable->destructiveProjectEnumData(_getOpaquePointer(), metadata._0); +// CHECK-NEXT: return _getOpaquePointer(); +// CHECK-NEXT: } +// CHECK-NEXT: inline void _destructiveInjectEnumTag(unsigned tag) { +// CHECK-NEXT: auto metadata = _impl::$s5Enums1EOMa(0); +// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; +// CHECK-NEXT: #ifdef __arm64e__ +// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); +// CHECK-NEXT: #else +// CHECK-NEXT: auto *vwTable = *vwTableAddr; +// CHECK-NEXT: #endif +// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); +// CHECK-NEXT: enumVWTable->destructiveInjectEnumTag(_getOpaquePointer(), tag, metadata._0); +// CHECK-NEXT: } +// CHECK-NEXT: inline unsigned _getEnumTag() const { +// CHECK-NEXT: auto metadata = _impl::$s5Enums1EOMa(0); +// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; +// CHECK-NEXT: #ifdef __arm64e__ +// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); +// CHECK-NEXT: #else +// CHECK-NEXT: auto *vwTable = *vwTableAddr; +// CHECK-NEXT: #endif +// CHECK-NEXT: const auto *enumVWTable = reinterpret_cast(vwTable); +// CHECK-NEXT: return enumVWTable->getEnumTag(_getOpaquePointer(), metadata._0); +// CHECK-NEXT: } +// CHECK-NEXT: using _impl_x = decltype(x); +// CHECK-NEXT: using _impl_y = decltype(y); +// CHECK-NEXT: using _impl_z = decltype(z); +// CHECK-NEXT: using _impl_w = decltype(w); +// CHECK-NEXT: using _impl_auto = decltype(auto_); +// CHECK-NEXT: using _impl_foobar = decltype(foobar); +// CHECK: }; +// CHECK-NEXT: decltype(E::x) E::x; +// CHECK-NEXT: decltype(E::y) E::y; +// CHECK-NEXT: decltype(E::z) E::z; +// CHECK-NEXT: decltype(E::w) E::w; +// CHECK-NEXT: decltype(E::auto_) E::auto_; +// CHECK-NEXT: decltype(E::foobar) E::foobar; +// CHECK-EMPTY: +// CHECK-NEXT: namespace _impl { +// CHECK-EMPTY: +// CHECK-NEXT: class _impl_E { +// CHECK-NEXT: public: +// CHECK: static inline void initializeWithTake(char * _Nonnull destStorage, char * _Nonnull srcStorage) { +// CHECK-NEXT: auto metadata = _impl::$s5Enums1EOMa(0); +// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; +// CHECK-NEXT: #ifdef __arm64e__ +// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); +// CHECK-NEXT: #else +// CHECK-NEXT: auto *vwTable = *vwTableAddr; +// CHECK-NEXT: #endif +// CHECK-NEXT: vwTable->initializeWithTake(destStorage, srcStorage, metadata._0); +// CHECK-NEXT: } +// CHECK: namespace Enums { +// CHECK: inline E E::_impl_x::operator()(double val) const { +// CHECK-NEXT: auto result = E::_make(); +// CHECK-NEXT: memcpy(result._getOpaquePointer(), &val, sizeof(val)); +// CHECK-NEXT: result._destructiveInjectEnumTag(0); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline bool E::isX() const { +// CHECK-NEXT: return *this == E::x; +// CHECK-NEXT: } +// CHECK-NEXT: inline double E::getX() const { +// CHECK-NEXT: if (!isX()) abort(); +// CHECK-NEXT: alignas(E) unsigned char buffer[sizeof(E)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) E(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: double result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline E E::_impl_y::operator()(void const * _Nullable val) const { +// CHECK-NEXT: auto result = E::_make(); +// CHECK-NEXT: memcpy(result._getOpaquePointer(), &val, sizeof(val)); +// CHECK-NEXT: result._destructiveInjectEnumTag(1); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline bool E::isY() const { +// CHECK-NEXT: return *this == E::y; +// CHECK-NEXT: } +// CHECK-NEXT: inline void const * _Nullable E::getY() const { +// CHECK-NEXT: if (!isY()) abort(); +// CHECK-NEXT: alignas(E) unsigned char buffer[sizeof(E)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) E(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: void const * _Nullable result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline E E::_impl_z::operator()(const S &val) const { +// CHECK-NEXT: auto result = E::_make(); +// CHECK-NEXT: alignas(S) unsigned char buffer[sizeof(S)]; +// CHECK-NEXT: auto *valCopy = new(buffer) S(val); +// CHECK-NEXT: swift::_impl::implClassFor::type::initializeWithTake(result._getOpaquePointer(), swift::_impl::implClassFor::type::getOpaquePointer(*valCopy)); +// CHECK-NEXT: result._destructiveInjectEnumTag(2); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline bool E::isZ() const { +// CHECK-NEXT: return *this == E::z; +// CHECK-NEXT: } +// CHECK-NEXT: inline S E::getZ() const { +// CHECK-NEXT: if (!isZ()) abort(); +// CHECK-NEXT: alignas(E) unsigned char buffer[sizeof(E)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) E(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: return swift::_impl::implClassFor::type::returnNewValue([&](char * _Nonnull result) { +// CHECK-NEXT: swift::_impl::implClassFor::type::initializeWithTake(result, payloadFromDestruction); +// CHECK-NEXT: }); +// CHECK-NEXT: } +// CHECK-NEXT: inline E E::_impl_w::operator()(swift::Int val) const { +// CHECK-NEXT: auto result = E::_make(); +// CHECK-NEXT: memcpy(result._getOpaquePointer(), &val, sizeof(val)); +// CHECK-NEXT: result._destructiveInjectEnumTag(3); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline bool E::isW() const { +// CHECK-NEXT: return *this == E::w; +// CHECK-NEXT: } +// CHECK-NEXT: inline swift::Int E::getW() const { +// CHECK-NEXT: if (!isW()) abort(); +// CHECK-NEXT: alignas(E) unsigned char buffer[sizeof(E)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) E(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: swift::Int result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline E E::_impl_auto::operator()(void * _Nonnull val) const { +// CHECK-NEXT: auto result = E::_make(); +// CHECK-NEXT: memcpy(result._getOpaquePointer(), &val, sizeof(val)); +// CHECK-NEXT: result._destructiveInjectEnumTag(4); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline bool E::isAuto_() const { +// CHECK-NEXT: return *this == E::auto_; +// CHECK-NEXT: } +// CHECK-NEXT: inline void * _Nonnull E::getAuto_() const { +// CHECK-NEXT: if (!isAuto_()) abort(); +// CHECK-NEXT: alignas(E) unsigned char buffer[sizeof(E)]; +// CHECK-NEXT: auto *thisCopy = new(buffer) E(*this); +// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); +// CHECK-NEXT: void * _Nonnull result; +// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result)); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline E E::_impl_foobar::operator()() const { +// CHECK-NEXT: auto result = E::_make(); +// CHECK-NEXT: result._destructiveInjectEnumTag(5); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// CHECK-NEXT: inline bool E::isFoobar() const { +// CHECK-NEXT: return *this == E::foobar; +// CHECK-NEXT: } From e70fbbc73877b68318a474544ce68eefb53f310a Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Thu, 11 Aug 2022 18:04:55 -0700 Subject: [PATCH 467/491] [ConstraintSystem] correct the @preconcurrency adjustment of var references We intended to introduce AST conversions that strip concurrency attributes off of types associated with `@preconcurrency` decls. But for VarDecl references, we stripped it too early, leading to things like a MemberVarDecl that doesn't have `@Sendable` in its result type, but the VarDecl it refers to does have it. That caused crashes in SIL where types didn't match up. This patch fixes things by delaying the stripping until the right point. resolves rdar://98018067 --- include/swift/Sema/ConstraintSystem.h | 4 +++- lib/Sema/CSApply.cpp | 20 ++++++++++++++-- lib/Sema/ConstraintSystem.cpp | 33 +++++++++++++++++++++------ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 12457af2c1849..07fe88459d7a8 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4764,7 +4764,8 @@ class ConstraintSystem { Type getUnopenedTypeOfReference(VarDecl *value, Type baseType, DeclContext *UseDC, ConstraintLocator *memberLocator = nullptr, - bool wantInterfaceType = false); + bool wantInterfaceType = false, + bool adjustForPreconcurrency = true); /// Return the type-of-reference of the given value. /// @@ -4786,6 +4787,7 @@ class ConstraintSystem { llvm::function_ref getType, ConstraintLocator *memberLocator = nullptr, bool wantInterfaceType = false, + bool adjustForPreconcurrency = true, llvm::function_ref getClosureType = [](const AbstractClosureExpr *) { return Type(); diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 32190a7da0cdf..09f7c4560843d 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -919,6 +919,15 @@ namespace { auto &context = cs.getASTContext(); + // turn LValues into RValues first + if (openedType->hasLValueType()) { + assert(adjustedOpenedType->hasLValueType() && "lvalue-ness mismatch?"); + return adjustTypeForDeclReference(cs.coerceToRValue(expr), + openedType->getRValueType(), + adjustedOpenedType->getRValueType(), + getNewType); + } + // If we have an optional type, wrap it up in a monadic '?' and recurse. if (Type objectType = openedType->getOptionalObjectType()) { Type adjustedRefType = getNewType(adjustedOpenedType); @@ -1669,10 +1678,17 @@ namespace { adjustedRefTy = adjustedRefTy->replaceCovariantResultType( containerTy, 1); } - cs.setType(memberRefExpr, refTy->castTo()->getResult()); + + // \returns result of the given function type + auto resultType = [](Type fnTy) -> Type { + return fnTy->castTo()->getResult(); + }; + + cs.setType(memberRefExpr, resultType(refTy)); Expr *result = memberRefExpr; - result = adjustTypeForDeclReference(result, refTy, adjustedRefTy); + result = adjustTypeForDeclReference(result, resultType(refTy), + resultType(adjustedRefTy)); closeExistentials(result, locator); // If the property is of dynamic 'Self' type, wrap an implicit diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index a675f32f7849d..bba808a464926 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1259,7 +1259,8 @@ ClosureIsolatedByPreconcurrency::operator()(const ClosureExpr *expr) const { Type ConstraintSystem::getUnopenedTypeOfReference( VarDecl *value, Type baseType, DeclContext *UseDC, - ConstraintLocator *memberLocator, bool wantInterfaceType) { + ConstraintLocator *memberLocator, bool wantInterfaceType, + bool adjustForPreconcurrency) { return ConstraintSystem::getUnopenedTypeOfReference( value, baseType, UseDC, [&](VarDecl *var) -> Type { @@ -1272,22 +1273,25 @@ Type ConstraintSystem::getUnopenedTypeOfReference( return wantInterfaceType ? var->getInterfaceType() : var->getType(); }, - memberLocator, wantInterfaceType, GetClosureType{*this}, + memberLocator, wantInterfaceType, adjustForPreconcurrency, + GetClosureType{*this}, ClosureIsolatedByPreconcurrency{*this}); } Type ConstraintSystem::getUnopenedTypeOfReference( VarDecl *value, Type baseType, DeclContext *UseDC, llvm::function_ref getType, - ConstraintLocator *memberLocator, bool wantInterfaceType, + ConstraintLocator *memberLocator, + bool wantInterfaceType, bool adjustForPreconcurrency, llvm::function_ref getClosureType, llvm::function_ref isolatedByPreconcurrency) { Type requestedType = getType(value)->getWithoutSpecifierType()->getReferenceStorageReferent(); - // Adjust the type for concurrency. - requestedType = adjustVarTypeForConcurrency( - requestedType, value, UseDC, getClosureType, isolatedByPreconcurrency); + // Adjust the type for concurrency if requested. + if (adjustForPreconcurrency) + requestedType = adjustVarTypeForConcurrency( + requestedType, value, UseDC, getClosureType, isolatedByPreconcurrency); // If we're dealing with contextual types, and we referenced this type from // a different context, map the type. @@ -2309,9 +2313,14 @@ ConstraintSystem::getTypeOfMemberReference( FunctionType::ExtInfo info; refType = FunctionType::get(indices, elementTy, info); } else { + // Delay the adjustment for preconcurrency until after we've formed + // the function type for this kind of reference. Otherwise we will lose + // track of the adjustment in the formed function's return type. + refType = getUnopenedTypeOfReference(cast(value), baseTy, useDC, locator, - /*wantInterfaceType=*/true); + /*wantInterfaceType=*/true, + /*adjustForPreconcurrency=*/false); } auto selfTy = outerDC->getSelfInterfaceType(); @@ -2432,6 +2441,16 @@ ConstraintSystem::getTypeOfMemberReference( openedType = adjustFunctionTypeForConcurrency( origOpenedType->castTo(), subscript, useDC, /*numApplies=*/2, /*isMainDispatchQueue=*/false, replacements); + } else if (auto var = dyn_cast(value)) { + // Adjust the function's result type, since that's the Var's actual type. + auto origFnType = origOpenedType->castTo(); + + auto resultTy = adjustVarTypeForConcurrency( + origFnType->getResult(), var, useDC, GetClosureType{*this}, + ClosureIsolatedByPreconcurrency{*this}); + + openedType = FunctionType::get( + origFnType->getParams(), resultTy, origFnType->getExtInfo()); } // Compute the type of the reference. From 6c24bc57cbf318a5092c54943e1e21bbcdb7c537 Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Tue, 23 Aug 2022 18:02:57 -0700 Subject: [PATCH 468/491] [AST][SILGen] model ABI-safe casts of LValues We needed a way to describe an ABI-safe cast of an address representing an LValue to implement `@preconcurrency` and its injection of casts during accesses of members. This new AST node, `ABISafeConversionExpr` models what is essentially an `unchecked_addr_cast` in SIL when accessing the LVAlue. As of now I simply implemented it and the verification of the node for the concurrency needs to ensure that it's not misused by accident. If it finds use outside of that, feel free to update the verifier. --- include/swift/AST/Expr.h | 13 +++++++++++ include/swift/AST/ExprNodes.def | 1 + lib/AST/ASTDumper.cpp | 5 +++++ lib/AST/ASTPrinter.cpp | 3 +++ lib/AST/ASTVerifier.cpp | 39 +++++++++++++++++++++++++++++++++ lib/AST/Expr.cpp | 3 +++ lib/SILGen/LValue.h | 1 + lib/SILGen/SILGenExpr.cpp | 3 +++ lib/SILGen/SILGenLValue.cpp | 37 +++++++++++++++++++++++++++++++ lib/Sema/CSApply.cpp | 29 ++++++++++++------------ 10 files changed, 120 insertions(+), 14 deletions(-) diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index a5fa92b7ba9fc..bd20cd41110cc 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -3157,6 +3157,19 @@ class LoadExpr : public ImplicitConversionExpr { static bool classof(const Expr *E) { return E->getKind() == ExprKind::Load; } }; +/// ABISafeConversion - models a type conversion on an l-value that has no +/// material affect on the ABI of the type, while *preserving* the l-valueness +/// of the type. +class ABISafeConversionExpr : public ImplicitConversionExpr { +public: + ABISafeConversionExpr(Expr *subExpr, Type type) + : ImplicitConversionExpr(ExprKind::ABISafeConversion, subExpr, type) {} + + static bool classof(const Expr *E) { + return E->getKind() == ExprKind::ABISafeConversion; + } +}; + /// This is a conversion from an expression of UnresolvedType to an arbitrary /// other type, and from an arbitrary type to UnresolvedType. This node does /// not appear in valid code, only in code involving diagnostics. diff --git a/include/swift/AST/ExprNodes.def b/include/swift/AST/ExprNodes.def index a1833fca267f3..5475031f03bdf 100644 --- a/include/swift/AST/ExprNodes.def +++ b/include/swift/AST/ExprNodes.def @@ -152,6 +152,7 @@ ABSTRACT_EXPR(Apply, Expr) EXPR_RANGE(Apply, Call, ConstructorRefCall) ABSTRACT_EXPR(ImplicitConversion, Expr) EXPR(Load, ImplicitConversionExpr) + EXPR(ABISafeConversion, ImplicitConversionExpr) EXPR(DestructureTuple, ImplicitConversionExpr) EXPR(UnresolvedTypeConversion, ImplicitConversionExpr) EXPR(FunctionConversion, ImplicitConversionExpr) diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index fc0cd7595fe39..017c2cf64e881 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -2276,6 +2276,11 @@ class PrintExpr : public ExprVisitor { printRec(E->getSubExpr()); PrintWithColorRAII(OS, ParenthesisColor) << ')'; } + void visitABISafeConversionExpr(ABISafeConversionExpr *E) { + printCommon(E, "abi_safe_conversion_expr") << '\n'; + printRec(E->getSubExpr()); + PrintWithColorRAII(OS, ParenthesisColor) << ')'; + } void visitMetatypeConversionExpr(MetatypeConversionExpr *E) { printCommon(E, "metatype_conversion_expr") << '\n'; printRec(E->getSubExpr()); diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 268dc6885666e..6e01bf741d864 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -4793,6 +4793,9 @@ void PrintAST::visitConstructorRefCallExpr(ConstructorRefCallExpr *expr) { } } +void PrintAST::visitABISafeConversionExpr(ABISafeConversionExpr *expr) { +} + void PrintAST::visitFunctionConversionExpr(FunctionConversionExpr *expr) { } diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index 587e6b135d648..fec82a6fe5ea1 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -240,6 +240,17 @@ class Verifier : public ASTWalker { pushScope(DC); } + /// Emit an error message and abort, optionally dumping the expression. + /// \param E if non-null, the expression to dump() followed by a new-line. + void error(llvm::StringRef msg, Expr *E = nullptr) { + Out << msg << "\n"; + if (E) { + E->dump(Out); + Out << "\n"; + } + abort(); + } + public: Verifier(ModuleDecl *M, DeclContext *DC) : Verifier(PointerUnion(M), DC) {} @@ -2306,6 +2317,34 @@ class Verifier : public ASTWalker { verifyCheckedBase(E); } + void verifyChecked(ABISafeConversionExpr *E) { + PrettyStackTraceExpr debugStack(Ctx, "verify ABISafeConversionExpr", E); + + auto toType = E->getType(); + auto fromType = E->getSubExpr()->getType(); + + if (!fromType->hasLValueType()) + error("conversion source must be an l-value", E); + + if (!toType->hasLValueType()) + error("conversion result must be an l-value", E); + + { + // At the moment, "ABI Safe" means concurrency features can be stripped. + // Since we don't know how deeply the stripping is happening, to verify + // in a fuzzy way, strip everything to see if they're the same type. + auto strippedFrom = fromType->getRValueType() + ->stripConcurrency(/*recurse*/true, + /*dropGlobalActor*/true); + auto strippedTo = toType->getRValueType() + ->stripConcurrency(/*recurse*/true, + /*dropGlobalActor*/true); + + if (!strippedFrom->isEqual(strippedTo)) + error("possibly non-ABI safe conversion", E); + } + } + void verifyChecked(ValueDecl *VD) { if (VD->getInterfaceType()->hasError()) { Out << "checked decl cannot have error type\n"; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index ef12e1e8d1c1d..6f2898ca3de80 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -414,6 +414,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const { PASS_THROUGH_REFERENCE(Load, getSubExpr); NO_REFERENCE(DestructureTuple); NO_REFERENCE(UnresolvedTypeConversion); + PASS_THROUGH_REFERENCE(ABISafeConversion, getSubExpr); PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr); PASS_THROUGH_REFERENCE(CovariantFunctionConversion, getSubExpr); PASS_THROUGH_REFERENCE(CovariantReturnConversion, getSubExpr); @@ -741,6 +742,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const { return false; case ExprKind::Load: + case ExprKind::ABISafeConversion: case ExprKind::DestructureTuple: case ExprKind::UnresolvedTypeConversion: case ExprKind::FunctionConversion: @@ -914,6 +916,7 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const { case ExprKind::Load: case ExprKind::DestructureTuple: case ExprKind::UnresolvedTypeConversion: + case ExprKind::ABISafeConversion: case ExprKind::FunctionConversion: case ExprKind::CovariantFunctionConversion: case ExprKind::CovariantReturnConversion: diff --git a/lib/SILGen/LValue.h b/lib/SILGen/LValue.h index 13155beead466..9b16da86bedcb 100644 --- a/lib/SILGen/LValue.h +++ b/lib/SILGen/LValue.h @@ -105,6 +105,7 @@ class PathComponent { CoroutineAccessorKind, // coroutine accessor ValueKind, // random base pointer as an lvalue PhysicalKeyPathApplicationKind, // applying a key path + ABISafeConversionKind, // unchecked_addr_cast // Logical LValue kinds GetterSetterKind, // property or subscript getter/setter diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index f204f328a4554..58eb3644e7dad 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -451,6 +451,9 @@ namespace { RValue visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E, SGFContext C); RValue visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E, SGFContext C); + RValue visitABISafeConversionExpr(ABISafeConversionExpr *E, SGFContext C) { + llvm_unreachable("cannot appear in rvalue"); + } RValue visitFunctionConversionExpr(FunctionConversionExpr *E, SGFContext C); RValue visitCovariantFunctionConversionExpr( diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index 1256bcd570789..7598cde92713a 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -327,6 +327,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenLValue LValueOptions options); LValue visitMoveExpr(MoveExpr *e, SGFAccessKind accessKind, LValueOptions options); + LValue visitABISafeConversionExpr(ABISafeConversionExpr *e, + SGFAccessKind accessKind, + LValueOptions options); // Expressions that wrap lvalues @@ -2204,6 +2207,29 @@ namespace { OS.indent(indent) << "PhysicalKeyPathApplicationComponent\n"; } }; + + /// A physical component which performs an unchecked_addr_cast + class ABISafeConversionComponent final : public PhysicalPathComponent { + public: + ABISafeConversionComponent(LValueTypeData typeData) + : PhysicalPathComponent(typeData, ABISafeConversionKind, + /*actorIsolation=*/None) {} + + ManagedValue project(SILGenFunction &SGF, SILLocation loc, + ManagedValue base) && override { + auto toType = SGF.getLoweredType(getTypeData().SubstFormalType) + .getAddressType(); + + if (base.getType() == toType) + return base; // nothing to do + + return SGF.B.createUncheckedAddrCast(loc, base, toType); + } + + void dump(raw_ostream &OS, unsigned indent) const override { + OS.indent(indent) << "ABISafeConversionComponent\n"; + } + }; } // end anonymous namespace RValue @@ -3734,6 +3760,17 @@ LValue SILGenLValue::visitMoveExpr(MoveExpr *e, SGFAccessKind accessKind, toAddr->getType().getASTType()); } +LValue SILGenLValue::visitABISafeConversionExpr(ABISafeConversionExpr *e, + SGFAccessKind accessKind, + LValueOptions options) { + LValue lval = visitRec(e->getSubExpr(), accessKind, options); + auto typeData = getValueTypeData(SGF, accessKind, e); + + lval.add(typeData); + + return lval; +} + /// Emit an lvalue that refers to the given property. This is /// designed to work with ManagedValue 'base's that are either +0 or +1. LValue SILGenFunction::emitPropertyLValue(SILLocation loc, ManagedValue base, diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 09f7c4560843d..9708a01d98f23 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -919,13 +919,22 @@ namespace { auto &context = cs.getASTContext(); - // turn LValues into RValues first + // For an RValue function type, use a standard function conversion. + if (openedType->is()) { + expr = new (context) FunctionConversionExpr( + expr, getNewType(adjustedOpenedType)); + cs.cacheType(expr); + return expr; + } + + // For any kind of LValue, use an ABISafeConversion. if (openedType->hasLValueType()) { - assert(adjustedOpenedType->hasLValueType() && "lvalue-ness mismatch?"); - return adjustTypeForDeclReference(cs.coerceToRValue(expr), - openedType->getRValueType(), - adjustedOpenedType->getRValueType(), - getNewType); + assert(adjustedOpenedType->hasLValueType() && "lvalueness mismatch?"); + + expr = new (context) ABISafeConversionExpr( + expr, getNewType(adjustedOpenedType)); + cs.cacheType(expr); + return expr; } // If we have an optional type, wrap it up in a monadic '?' and recurse. @@ -944,14 +953,6 @@ namespace { return expr; } - // For a function type, perform a function conversion. - if (openedType->is()) { - expr = new (context) FunctionConversionExpr( - expr, getNewType(adjustedOpenedType)); - cs.cacheType(expr); - return expr; - } - assert(false && "Unhandled adjustment"); return expr; } From a4d661d3bbfa5777a2a7a6001e3ab1295455f736 Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Fri, 19 Aug 2022 15:36:24 -0700 Subject: [PATCH 469/491] Add tests for rdar://98018067 --- test/SILGen/Inputs/objc_preconcurrency.h | 9 ++++++++ test/SILGen/objc_preconcurrency.swift | 29 +++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 test/SILGen/Inputs/objc_preconcurrency.h diff --git a/test/SILGen/Inputs/objc_preconcurrency.h b/test/SILGen/Inputs/objc_preconcurrency.h new file mode 100644 index 0000000000000..2e91503a4f264 --- /dev/null +++ b/test/SILGen/Inputs/objc_preconcurrency.h @@ -0,0 +1,9 @@ +@import Foundation; + +#define SENDABLE __attribute__((__swift_attr__("@Sendable"))) + +SENDABLE +@interface NSTouchGrass : NSObject +@property (nullable, copy) void (SENDABLE ^cancellationHandler)(void); +@property (nonnull, copy) void (SENDABLE ^exceptionHandler)(void); +@end diff --git a/test/SILGen/objc_preconcurrency.swift b/test/SILGen/objc_preconcurrency.swift index a99ee36a6f96e..69fa8b9474703 100644 --- a/test/SILGen/objc_preconcurrency.swift +++ b/test/SILGen/objc_preconcurrency.swift @@ -1,9 +1,10 @@ -// RUN: %target-swift-emit-silgen -module-name objc_preconcurrency -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -disable-objc-attr-requires-foundation-module | %FileCheck %s +// RUN: %target-swift-emit-silgen -module-name objc_preconcurrency -sdk %S/Inputs -I %S/Inputs -enable-source-import -import-objc-header %S/Inputs/objc_preconcurrency.h %s -disable-objc-attr-requires-foundation-module | %FileCheck %s // REQUIRES: objc_interop @objc protocol P { @preconcurrency @objc optional func f(_ completionHandler: @Sendable @escaping () -> Void) + @preconcurrency var sendyHandler: @Sendable () -> Void { get set } } // CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency19testDynamicDispatch1p17completionHandleryAA1P_p_yyctF @@ -16,3 +17,29 @@ func testDynamicDispatch(p: P, completionHandler: @escaping () -> Void) { // CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : $@convention(objc_method) (@convention(block) @Sendable () -> (), @opened let _ = p.f } + +// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency21testOptionalVarAccessyySo12NSTouchGrassCF +// CHECK: unchecked_addr_cast {{.*}} : $*Optional<@Sendable @callee_guaranteed () -> ()> to $*Optional<@callee_guaranteed () -> ()> +// CHECK: } // end sil function '$s19objc_preconcurrency21testOptionalVarAccessyySo12NSTouchGrassCF' +func testOptionalVarAccess(_ grass: NSTouchGrass) { + grass.cancellationHandler?() +} + +func modify(_ v: inout () -> Void) { + v = {} +} + +// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency15testInoutAccessyySo12NSTouchGrassCF +// CHECK: unchecked_addr_cast {{.*}} : $*@Sendable @callee_guaranteed () -> () to $*@callee_guaranteed () -> () +// CHECK: } // end sil function '$s19objc_preconcurrency15testInoutAccessyySo12NSTouchGrassCF' +func testInoutAccess(_ grass: NSTouchGrass) { + modify(&grass.exceptionHandler) +} + + +// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency21testProtocolVarAccess1pyAA1P_p_tF +// CHECK: unchecked_addr_cast {{.*}} : $*@Sendable @callee_guaranteed () -> () to $*@callee_guaranteed () -> () +// CHECK: } // end sil function '$s19objc_preconcurrency21testProtocolVarAccess1pyAA1P_p_tF' +func testProtocolVarAccess(p: P) { + modify(&p.sendyHandler) +} From 8ba51888c65c1116cffba079bdc682410dd605ef Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 29 Aug 2022 22:10:36 -0700 Subject: [PATCH 470/491] [ConstraintSystem] Before applying the result builder transform to a function body, map the result builder type into context. This was already done for inferred result builder attributes; now, the constraint system will map the builder type into context for all result builder attributes applied to computed properties/functions. --- include/swift/Sema/ConstraintSystem.h | 3 +++ lib/Sema/BuilderTransform.cpp | 7 +++++++ lib/Sema/TypeCheckRequestFunctions.cpp | 11 ++++------- test/Constraints/result_builder_generic_infer.swift | 13 +++++++++++++ 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 1197e93169463..3713cf8476476 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -5528,6 +5528,9 @@ class ConstraintSystem { /// Apply the given result builder to the closure expression. /// + /// \note builderType must be a contexutal type - callers should + /// open the builder type or map it into context as appropriate. + /// /// \returns \c None when the result builder cannot be applied at all, /// otherwise the result of applying the result builder. Optional diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index f7d7a84c24b46..5dfe786957350 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -2335,6 +2335,12 @@ Optional TypeChecker::applyResultBuilderBodyTransform( log << '\n'; } + // Map type parameters into context. We don't want type + // parameters to appear in the result builder type, because + // the result builder type will only be used inside the body + // of this decl; it's not part of the interface type. + builderType = func->mapTypeIntoContext(builderType); + if (auto result = cs.matchResultBuilder( func, builderType, resultContextType, resultConstraintKind, cs.getConstraintLocator(func->getBody()))) { @@ -2425,6 +2431,7 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType, auto builder = builderType->getAnyNominal(); assert(builder && "Bad result builder type"); assert(builder->getAttrs().hasAttribute()); + assert(!builderType->hasTypeParameter()); if (InvalidResultBuilderBodies.count(fn)) { (void)recordFix(IgnoreInvalidResultBuilderBody::create( diff --git a/lib/Sema/TypeCheckRequestFunctions.cpp b/lib/Sema/TypeCheckRequestFunctions.cpp index 3e5fbab1c4bff..c4f51178c8776 100644 --- a/lib/Sema/TypeCheckRequestFunctions.cpp +++ b/lib/Sema/TypeCheckRequestFunctions.cpp @@ -287,16 +287,13 @@ static Type inferResultBuilderType(ValueDecl *decl) { continue; // Substitute Self and associated type witnesses into the - // result builder type. Then, map all type parameters from - // the conforming type into context. We don't want type - // parameters to appear in the result builder type, because - // the result builder type will only be used inside the body - // of this decl; it's not part of the interface type. + // result builder type. Type parameters will be mapped + // into context when applying the result builder to the + // function body in the constraint system. auto subs = SubstitutionMap::getProtocolSubstitutions( protocol, dc->getSelfInterfaceType(), ProtocolConformanceRef(conformance)); - Type subResultBuilderType = dc->mapTypeIntoContext( - resultBuilderType.subst(subs)); + Type subResultBuilderType = resultBuilderType.subst(subs); matches.push_back( Match::forConformance( diff --git a/test/Constraints/result_builder_generic_infer.swift b/test/Constraints/result_builder_generic_infer.swift index 9ee5b3ad355d0..d08dcdb1958d9 100644 --- a/test/Constraints/result_builder_generic_infer.swift +++ b/test/Constraints/result_builder_generic_infer.swift @@ -41,6 +41,19 @@ struct ArchetypeSubstitution: P { var x2: [S] { S() } } +// CHECK-LABEL: struct_decl{{.*}}ExplicitGenericAttribute +struct ExplicitGenericAttribute { + // CHECK: var_decl{{.*}}x1 + // CHECK: Builder.buildBlock{{.*}}(substitution_map generic_signature= (substitution T -> T)) + @Builder + var x1: [S] { S() } + + // CHECK: var_decl{{.*}}x2 + // CHECK: Builder.buildBlock{{.*}}(substitution_map generic_signature= (substitution T -> T.A)) + @Builder + var x2: [S] { S() } +} + // CHECK: struct_decl{{.*}}ConcreteTypeSubstitution struct ConcreteTypeSubstitution {} From 0a6974072e16f093e1ec4e72d4ae83dc44ea434c Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 29 Aug 2022 22:52:30 -0700 Subject: [PATCH 471/491] [test] update SwiftToCxx unsigned-return-type-no-zext.cpp test to work on Amazon Linux Zeroext is optional --- test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp index 9e50d6a549c3a..71e99c3a3554e 100644 --- a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp +++ b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp @@ -13,5 +13,5 @@ void test(void *p) { getEnumTagi32(p); } -// CHECK: declare noundef zeroext i8 @_Z12getEnumTagi8Pv(i8* noundef) #1 -// CHECK: declare noundef i32 @_Z13getEnumTagi32Pv(i8* noundef) #1 +// CHECK: declare noundef{{( zeroext)?}} i8 @_Z12getEnumTagi8Pv(i8* noundef) +// CHECK: declare noundef i32 @_Z13getEnumTagi32Pv(i8* noundef) From f7a11c7543e3a13dfcdc63941485c54d6f4ea7d2 Mon Sep 17 00:00:00 2001 From: Eric Miotto <1094986+edymtt@users.noreply.github.com> Date: Tue, 30 Aug 2022 00:10:40 -0700 Subject: [PATCH 472/491] Tests all cases of `infer-cross-compile-hosts-on-darwin` at once (#60824) The current implementation currently requires to have physical machine for each architecture supported by macOS, which is not desirable. To allow all cases to be tested on a random Mac machine, allow to inject an arbitratry current architecture into the inference of the cross compile hosts by means of an environment variable. Addresses rdar://99096874 --- utils/build-script | 24 ++++++++++++++++--- ...-cross-compile-hosts-on-darwin-macosx.test | 4 ++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/utils/build-script b/utils/build-script index 8c9c91c272bd5..2e13e980bb097 100755 --- a/utils/build-script +++ b/utils/build-script @@ -413,19 +413,37 @@ def apply_default_arguments(toolchain, args): if (args.infer_cross_compile_hosts_on_darwin and platform.system() == "Darwin"): - args.cross_compile_hosts = _infer_cross_compile_hosts_on_darwin() + args.cross_compile_hosts = _infer_cross_compile_hosts_on_darwin( + get_running_arch(args.dry_run)) print("Inferred the following hosts for cross compilations: " f"{args.cross_compile_hosts}") sys.stdout.flush() -def _infer_cross_compile_hosts_on_darwin(): - if platform.machine() == "x86_64": +def _infer_cross_compile_hosts_on_darwin(arch_we_are_running_on): + if arch_we_are_running_on == "x86_64": return ["macosx-arm64"] else: return ["macosx-x86_64"] +def get_running_arch(dry_run): + # We can override the detected arch to support + # BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test + # Given the narrow scenario, we preferred using + # an environment variable instead of a build-script + # argument to make this less discoverable on purpose + if dry_run: + injected_arch = os.environ.get( + 'ARCH_FOR_BUILDSYSTEM_TESTS', + platform.machine()) + print("DRY RUN: assume build-script is being run on a " + f"{injected_arch} machine") + return injected_arch + else: + return platform.machine() + + # ----------------------------------------------------------------------------- # Main (preset) diff --git a/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test b/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test index b5f1aed98d41c..e9ec29ade0443 100644 --- a/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test +++ b/validation-test/BuildSystem/infer-cross-compile-hosts-on-darwin-macosx.test @@ -2,9 +2,9 @@ # REQUIRES: OS=macosx # RUN: %empty-directory(%t) -# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin --cmake %cmake 2>&1 | %FileCheck --check-prefix=INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-%target-cpu %s +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t ARCH_FOR_BUILDSYSTEM_TESTS=x86_64 %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin --cmake %cmake 2>&1 | %FileCheck --check-prefix=INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-x86_64 %s # RUN: %empty-directory(%t) -# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin=1 --cmake %cmake 2>&1 | %FileCheck --check-prefix=INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-%target-cpu %s +# RUN: SKIP_XCODE_VERSION_CHECK=1 SWIFT_BUILD_ROOT=%t ARCH_FOR_BUILDSYSTEM_TESTS=arm64 %swift_src_root/utils/build-script --dry-run --infer-cross-compile-hosts-on-darwin=1 --cmake %cmake 2>&1 | %FileCheck --check-prefix=INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-arm64 %s # INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-x86_64: Inferred the following hosts for cross compilations: ['macosx-arm64'] # INFER-CROSS-COMPILE-HOSTS-ON-DARWIN-arm64: Inferred the following hosts for cross compilations: ['macosx-x86_64'] From a4bd91a57faba2d8411c0b1c19cd02c1184ff414 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Tue, 30 Aug 2022 09:58:29 +0200 Subject: [PATCH 473/491] [SwiftSyntax] Add a human readable name for diagnostics to all nodes --- utils/gyb_syntax_support/AttributeNodes.py | 59 ++++--- utils/gyb_syntax_support/AvailabilityNodes.py | 15 +- utils/gyb_syntax_support/Child.py | 6 +- utils/gyb_syntax_support/CommonNodes.py | 45 ++--- utils/gyb_syntax_support/DeclNodes.py | 149 +++++++++------- utils/gyb_syntax_support/ExprNodes.py | 162 +++++++++--------- utils/gyb_syntax_support/GenericNodes.py | 30 ++-- utils/gyb_syntax_support/Node.py | 5 +- utils/gyb_syntax_support/PatternNodes.py | 25 +-- utils/gyb_syntax_support/StmtNodes.py | 80 +++++---- utils/gyb_syntax_support/TypeNodes.py | 43 ++--- 11 files changed, 342 insertions(+), 277 deletions(-) diff --git a/utils/gyb_syntax_support/AttributeNodes.py b/utils/gyb_syntax_support/AttributeNodes.py index 9e76cee916099..b01aefeff2496 100644 --- a/utils/gyb_syntax_support/AttributeNodes.py +++ b/utils/gyb_syntax_support/AttributeNodes.py @@ -3,14 +3,14 @@ ATTRIBUTE_NODES = [ # token-list -> token? token-list? - Node('TokenList', kind='SyntaxCollection', + Node('TokenList', name_for_diagnostics='token list', kind='SyntaxCollection', element='Token'), # token-list -> token token-list? - Node('NonEmptyTokenList', kind='SyntaxCollection', - element='Token', omit_when_empty=True), + Node('NonEmptyTokenList', name_for_diagnostics='token list', + kind='SyntaxCollection', element='Token', omit_when_empty=True), - Node('CustomAttribute', kind='Syntax', + Node('CustomAttribute', name_for_diagnostics='attribute', kind='Syntax', description=''' A custom `@` attribute. ''', @@ -37,7 +37,7 @@ # | named-attribute-string-argument # | back-deploy-attr-spec-list # )? ')'? - Node('Attribute', kind='Syntax', + Node('Attribute', name_for_diagnostics='attribute', kind='Syntax', description=''' An `@` attribute. ''', @@ -89,7 +89,7 @@ ]), # attribute-list -> attribute attribute-list? - Node('AttributeList', kind='SyntaxCollection', + Node('AttributeList', name_for_diagnostics='attributes', kind='SyntaxCollection', omit_when_empty=True, element='Syntax', element_name='Attribute', element_choices=[ @@ -102,7 +102,8 @@ # specialize-spec-attr-list? # | generic-where-clause # specialize-spec-attr-list? - Node('SpecializeAttributeSpecList', kind='SyntaxCollection', + Node('SpecializeAttributeSpecList', + name_for_diagnostics="argument to '@_specialize", kind='SyntaxCollection', description=''' A collection of arguments for the `@_specialize` attribute ''', @@ -114,7 +115,7 @@ 'GenericWhereClause', ]), - Node('AvailabilityEntry', kind='Syntax', + Node('AvailabilityEntry', name_for_diagnostics='availability entry', kind='Syntax', description=''' The availability argument for the _specialize attribute ''', @@ -131,6 +132,7 @@ # Representation of e.g. 'exported: true,' # labeled-specialize-entry -> identifier ':' token ','? Node('LabeledSpecializeEntry', kind='Syntax', + name_for_diagnostics='attribute argument', description=''' A labeled argument for the `@_specialize` attribute like `exported: true` @@ -151,6 +153,7 @@ # Representation of e.g. 'exported: true,' # labeled-specialize-entry -> identifier ':' token ','? Node('TargetFunctionEntry', kind='Syntax', + name_for_diagnostics='attribute argument', description=''' A labeled argument for the `@_specialize` attribute with a function decl value like @@ -173,6 +176,7 @@ # The argument of '@_dynamic_replacement(for:)' or '@_private(sourceFile:)' # named-attribute-string-arg -> 'name': string-literal Node('NamedAttributeStringArgument', kind='Syntax', + name_for_diagnostics='attribute argument', description=''' The argument for the `@_dynamic_replacement` or `@_private` attribute of the form `for: "function()"` or `sourceFile: @@ -188,7 +192,7 @@ Child('Declname', kind='DeclName'), ]), ]), - Node('DeclName', kind='Syntax', children=[ + Node('DeclName', name_for_diagnostics='declaration name', kind='Syntax', children=[ Child('DeclBaseName', kind='Syntax', description=''' The base name of the protocol\'s requirement. ''', @@ -205,7 +209,8 @@ # The argument of '@_implements(...)' # implements-attr-arguments -> simple-type-identifier ',' # (identifier | operator) decl-name-arguments - Node('ImplementsAttributeArguments', kind='Syntax', + Node('ImplementsAttributeArguments', name_for_diagnostics='@_implements arguemnts', + kind='Syntax', description=''' The arguments for the `@_implements` attribute of the form `Type, methodName(arg1Label:arg2Label:)` @@ -234,7 +239,8 @@ ]), # objc-selector-piece -> identifier? ':'? - Node('ObjCSelectorPiece', kind='Syntax', + Node('ObjCSelectorPiece', name_for_diagnostics='Objective-C selector piece', + kind='Syntax', description=''' A piece of an Objective-C selector. Either consisting of just an identifier for a nullary selector, an identifier and a colon for a @@ -246,13 +252,15 @@ ]), # objc-selector -> objc-selector-piece objc-selector? - Node('ObjCSelector', kind='SyntaxCollection', element='ObjCSelectorPiece'), + Node('ObjCSelector', name_for_diagnostics='Objective-C selector', + kind='SyntaxCollection', element='ObjCSelectorPiece'), # The argument of '@differentiable(...)'. # differentiable-attr-arguments -> # differentiability-kind? '.'? differentiability-params-clause? ','? # generic-where-clause? - Node('DifferentiableAttributeArguments', kind='Syntax', + Node('DifferentiableAttributeArguments', + name_for_diagnostics="'@differentiable' arguments", kind='Syntax', description=''' The arguments for the `@differentiable` attribute: an optional differentiability kind, an optional differentiability parameter clause, @@ -276,7 +284,8 @@ # differentiability-params-clause -> # 'wrt' ':' (differentiability-param | differentiability-params) - Node('DifferentiabilityParamsClause', kind='Syntax', + Node('DifferentiabilityParamsClause', + name_for_diagnostics="'@differentiable' argument", kind='Syntax', description='A clause containing differentiability parameters.', children=[ Child('WrtLabel', kind='IdentifierToken', @@ -292,7 +301,8 @@ ]), # differentiability-params -> '(' differentiability-param-list ')' - Node('DifferentiabilityParams', kind='Syntax', + Node('DifferentiabilityParams', name_for_diagnostics='differentiability parameters', + kind='Syntax', description='The differentiability parameters.', children=[ Child('LeftParen', kind='LeftParenToken'), @@ -304,11 +314,13 @@ # differentiability-param-list -> # differentiability-param differentiability-param-list? - Node('DifferentiabilityParamList', kind='SyntaxCollection', + Node('DifferentiabilityParamList', + name_for_diagnostics='differentiability parameters', kind='SyntaxCollection', element='DifferentiabilityParam'), # differentiability-param -> ('self' | identifier | integer-literal) ','? - Node('DifferentiabilityParam', kind='Syntax', + Node('DifferentiabilityParam', name_for_diagnostics='differentiability parameter', + kind='Syntax', description=''' A differentiability parameter: either the "self" identifier, a function parameter name, or a function parameter index. @@ -330,7 +342,9 @@ # # derivative-registration-attr-arguments -> # 'of' ':' func-decl-name ','? differentiability-params-clause? - Node('DerivativeRegistrationAttributeArguments', kind='Syntax', + Node('DerivativeRegistrationAttributeArguments', + name_for_diagnostics='attribute arguments', + kind='Syntax', description=''' The arguments for the '@derivative(of:)' and '@transpose(of:)' attributes: the 'of:' label, the original declaration name, and an @@ -369,6 +383,7 @@ # base-type -> # member-type-identifier | base-type-identifier Node('QualifiedDeclName', kind='Syntax', + name_for_diagnostics='declaration name', description=''' An optionally qualified function declaration name (e.g. `+(_:_:)`, `A.B.C.foo(_:_:)`). @@ -402,6 +417,7 @@ # NOTE: This is duplicated with `DeclName` above. Change `DeclName` # description and use it if possible. Node('FunctionDeclName', kind='Syntax', + name_for_diagnostics='function declaration name', description='A function declaration name (e.g. `foo(_:_:)`).', children=[ Child('Name', kind='Syntax', description=''' @@ -423,6 +439,7 @@ # The arguments of '@_backDeploy(...)' # back-deploy-attr-spec-list -> 'before' ':' back-deploy-version-list Node('BackDeployAttributeSpecList', kind='Syntax', + name_for_diagnostics="'@_backDeploy' arguments", description=''' A collection of arguments for the `@_backDeploy` attribute ''', @@ -441,11 +458,11 @@ # back-deploy-version-list -> # back-deploy-version-entry back-deploy-version-list? - Node('BackDeployVersionList', kind='SyntaxCollection', - element='BackDeployVersionArgument'), + Node('BackDeployVersionList', name_for_diagnostics='version list', + kind='SyntaxCollection', element='BackDeployVersionArgument'), # back-deploy-version-entry -> availability-version-restriction ','? - Node('BackDeployVersionArgument', kind='Syntax', + Node('BackDeployVersionArgument', name_for_diagnostics='version', kind='Syntax', description=''' A single platform/version pair in a `@_backDeploy` attribute, e.g. `iOS 10.1`. diff --git a/utils/gyb_syntax_support/AvailabilityNodes.py b/utils/gyb_syntax_support/AvailabilityNodes.py index 2e462366a3249..d7c1ca1ae9cca 100644 --- a/utils/gyb_syntax_support/AvailabilityNodes.py +++ b/utils/gyb_syntax_support/AvailabilityNodes.py @@ -3,15 +3,16 @@ AVAILABILITY_NODES = [ # availability-spec-list -> availability-entry availability-spec-list? - Node('AvailabilitySpecList', kind='SyntaxCollection', - element='AvailabilityArgument'), + Node('AvailabilitySpecList', name_for_diagnostics="'@availability' arguments", + kind='SyntaxCollection', element='AvailabilityArgument'), # Wrapper for all the different entries that may occur inside @available # availability-entry -> '*' ','? # | identifier ','? # | availability-version-restriction ','? # | availability-versioned-argument ','? - Node('AvailabilityArgument', kind='Syntax', + Node('AvailabilityArgument', name_for_diagnostics="'@available' argument", + kind='Syntax', description=''' A single argument to an `@available` argument like `*`, `iOS 10.1`, or `message: "This has been deprecated"`. @@ -38,7 +39,8 @@ # Representation of 'deprecated: 2.3', 'message: "Hello world"' etc. # availability-versioned-argument -> identifier ':' version-tuple - Node('AvailabilityLabeledArgument', kind='Syntax', + Node('AvailabilityLabeledArgument', name_for_diagnostics="'@available' argument", + kind='Syntax', description=''' A argument to an `@available` attribute that consists of a label and a value, e.g. `message: "This has been deprecated"`. @@ -57,7 +59,8 @@ # Representation for 'iOS 10', 'swift 3.4' etc. # availability-version-restriction -> identifier version-tuple - Node('AvailabilityVersionRestriction', kind='Syntax', + Node('AvailabilityVersionRestriction', name_for_diagnostics="'@available' argument", + kind='Syntax', description=''' An argument to `@available` that restricts the availability on a certain platform to a version, e.g. `iOS 10` or `swift 3.4`. @@ -76,7 +79,7 @@ # version-tuple -> integer-literal # | float-literal # | float-literal '.' integer-literal - Node('VersionTuple', kind='Syntax', + Node('VersionTuple', name_for_diagnostics='version tuple', kind='Syntax', description=''' A version number of the form major.minor.patch in which the minor and patch part may be omitted. diff --git a/utils/gyb_syntax_support/Child.py b/utils/gyb_syntax_support/Child.py index ac37e76f35bc1..cbada6099811a 100644 --- a/utils/gyb_syntax_support/Child.py +++ b/utils/gyb_syntax_support/Child.py @@ -12,11 +12,11 @@ class Child(object): def __init__(self, name, kind, description=None, is_optional=False, token_choices=None, text_choices=None, node_choices=None, collection_element_name=None, - classification=None, force_classification=False, + classification=None, force_classification=False, is_indented=False, requires_leading_newline=False): """ - If a classification is passed, it specifies the color identifiers in - that subtree should inherit for syntax coloring. Must be a member of + If a classification is passed, it specifies the color identifiers in + that subtree should inherit for syntax coloring. Must be a member of SyntaxClassification in SyntaxClassifier.h.gyb If force_classification is also set to true, all child nodes (not only identifiers) inherit the syntax classification. diff --git a/utils/gyb_syntax_support/CommonNodes.py b/utils/gyb_syntax_support/CommonNodes.py index c37eb3bce869d..9f9afca400a92 100644 --- a/utils/gyb_syntax_support/CommonNodes.py +++ b/utils/gyb_syntax_support/CommonNodes.py @@ -2,30 +2,31 @@ from .Node import Node # noqa: I201 COMMON_NODES = [ - Node('Decl', kind='Syntax'), - Node('Expr', kind='Syntax'), - Node('Stmt', kind='Syntax'), - Node('Type', kind='Syntax'), - Node('Pattern', kind='Syntax'), - Node('UnknownDecl', kind='Decl'), - Node('UnknownExpr', kind='Expr'), - Node('UnknownStmt', kind='Stmt'), - Node('UnknownType', kind='Type'), - Node('UnknownPattern', kind='Pattern'), - Node('Missing', kind='Syntax'), - Node('MissingDecl', kind='Decl', children=[ + Node('Decl', name_for_diagnostics='declaration', kind='Syntax'), + Node('Expr', name_for_diagnostics='expression', kind='Syntax'), + Node('Stmt', name_for_diagnostics='statement', kind='Syntax'), + Node('Type', name_for_diagnostics='type', kind='Syntax'), + Node('Pattern', name_for_diagnostics='pattern', kind='Syntax'), + Node('UnknownDecl', name_for_diagnostics='declaration', kind='Decl'), + Node('UnknownExpr', name_for_diagnostics='expression', kind='Expr'), + Node('UnknownStmt', name_for_diagnostics='statement', kind='Stmt'), + Node('UnknownType', name_for_diagnostics='type', kind='Type'), + Node('UnknownPattern', name_for_diagnostics='pattern', kind='Pattern'), + Node('Missing', name_for_diagnostics=None, kind='Syntax'), + Node('MissingDecl', name_for_diagnostics='declaration', kind='Decl', children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), Child('Modifiers', kind='ModifierList', collection_element_name='Modifier', is_optional=True), ]), - Node('MissingExpr', kind='Expr'), - Node('MissingStmt', kind='Stmt'), - Node('MissingType', kind='Type'), - Node('MissingPattern', kind='Pattern'), + Node('MissingExpr', name_for_diagnostics='expression', kind='Expr'), + Node('MissingStmt', name_for_diagnostics='statement', kind='Stmt'), + Node('MissingType', name_for_diagnostics='type', kind='Type'), + Node('MissingPattern', name_for_diagnostics='pattern', kind='Pattern'), # code-block-item = (decl | stmt | expr) ';'? - Node('CodeBlockItem', kind='Syntax', omit_when_empty=True, + Node('CodeBlockItem', name_for_diagnostics=None, kind='Syntax', + omit_when_empty=True, description=""" A CodeBlockItem is any Syntax node that appears on its own line inside a CodeBlock. @@ -49,11 +50,12 @@ ]), # code-block-item-list -> code-block-item code-block-item-list? - Node('CodeBlockItemList', kind='SyntaxCollection', - element='CodeBlockItem', elements_separated_by_newline=True), + Node('CodeBlockItemList', name_for_diagnostics=None, + kind='SyntaxCollection', element='CodeBlockItem', + elements_separated_by_newline=True), # code-block -> '{' stmt-list '}' - Node('CodeBlock', kind='Syntax', + Node('CodeBlock', name_for_diagnostics=None, kind='Syntax', traits=['Braced', 'WithStatements'], children=[ Child('LeftBrace', kind='LeftBraceToken'), @@ -63,7 +65,8 @@ requires_leading_newline=True), ]), - Node('UnexpectedNodes', kind='SyntaxCollection', element='Syntax', + Node('UnexpectedNodes', name_for_diagnostics=None, kind='SyntaxCollection', + element='Syntax', description=''' A collection of syntax nodes that occurred in the source code but could not be used to form a valid syntax tree. diff --git a/utils/gyb_syntax_support/DeclNodes.py b/utils/gyb_syntax_support/DeclNodes.py index e3cf33217f663..01a353cd54198 100644 --- a/utils/gyb_syntax_support/DeclNodes.py +++ b/utils/gyb_syntax_support/DeclNodes.py @@ -5,7 +5,7 @@ DECL_NODES = [ # type-assignment -> '=' type - Node('TypeInitializerClause', kind='Syntax', + Node('TypeInitializerClause', name_for_diagnostics=None, kind='Syntax', children=[ Child('Equal', kind='EqualToken'), Child('Value', kind='Type'), @@ -15,7 +15,8 @@ # typealias-name generic-parameter-clause? # type-assignment # typealias-name -> identifier - Node('TypealiasDecl', kind='Decl', traits=['IdentifiedDecl'], + Node('TypealiasDecl', name_for_diagnostics='typealias declaration', kind='Decl', + traits=['IdentifiedDecl'], children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -35,7 +36,8 @@ # inheritance-clause? type-assignment? # generic-where-clause? # associatedtype-name -> identifier - Node('AssociatedtypeDecl', kind='Decl', traits=['IdentifiedDecl'], + Node('AssociatedtypeDecl', name_for_diagnostics='associatedtype declaration', + kind='Decl', traits=['IdentifiedDecl'], children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -51,10 +53,10 @@ is_optional=True), ]), - Node('FunctionParameterList', kind='SyntaxCollection', - element='FunctionParameter'), + Node('FunctionParameterList', name_for_diagnostics='function parameter list', + kind='SyntaxCollection', element='FunctionParameter'), - Node('ParameterClause', kind='Syntax', + Node('ParameterClause', name_for_diagnostics='parameter clause', kind='Syntax', traits=['Parenthesized'], children=[ Child('LeftParen', kind='LeftParenToken'), @@ -64,7 +66,7 @@ ]), # -> Type - Node('ReturnClause', kind='Syntax', + Node('ReturnClause', name_for_diagnostics='return clause', kind='Syntax', children=[ Child('Arrow', kind='ArrowToken'), Child('ReturnType', kind='Type'), @@ -72,7 +74,7 @@ # function-signature -> # '(' parameter-list? ')' async? (throws | rethrows)? '->'? type? - Node('FunctionSignature', kind='Syntax', + Node('FunctionSignature', name_for_diagnostics='function signature', kind='Syntax', children=[ Child('Input', kind='ParameterClause'), Child('AsyncOrReasyncKeyword', kind='ContextualKeywordToken', @@ -88,7 +90,8 @@ # if-config-clause -> # ('#if' | '#elseif' | '#else') expr? (stmt-list | switch-case-list) - Node('IfConfigClause', kind='Syntax', + Node('IfConfigClause', name_for_diagnostics="conditional compilation clause", + kind='Syntax', children=[ Child('PoundKeyword', kind='Token', classification='BuildConfigId', @@ -108,12 +111,13 @@ ]), ]), - Node('IfConfigClauseList', kind='SyntaxCollection', + Node('IfConfigClauseList', name_for_diagnostics=None, kind='SyntaxCollection', element='IfConfigClause'), # if-config-decl -> '#if' expr stmt-list else-if-directive-clause-list # else-clause? '#endif' - Node('IfConfigDecl', kind='Decl', + Node('IfConfigDecl', name_for_diagnostics='conditional compilation block', + kind='Decl', children=[ Child('Clauses', kind='IfConfigClauseList', collection_element_name='Clause'), @@ -121,7 +125,7 @@ classification='BuildConfigId'), ]), - Node('PoundErrorDecl', kind='Decl', + Node('PoundErrorDecl', name_for_diagnostics="'#error' directive", kind='Decl', traits=['Parenthesized'], children=[ Child('PoundError', kind='PoundErrorToken'), @@ -130,7 +134,7 @@ Child('RightParen', kind='RightParenToken') ]), - Node('PoundWarningDecl', kind='Decl', + Node('PoundWarningDecl', name_for_diagnostics="'#warning' directive", kind='Decl', traits=['Parenthesized'], children=[ Child('PoundWarning', kind='PoundWarningToken'), @@ -139,8 +143,8 @@ Child('RightParen', kind='RightParenToken') ]), - Node('PoundSourceLocation', kind='Decl', - traits=['Parenthesized'], + Node('PoundSourceLocation', name_for_diagnostics="'#sourceLocation' directive", + kind='Decl', traits=['Parenthesized'], children=[ Child('PoundSourceLocation', kind='PoundSourceLocationToken'), Child('LeftParen', kind='LeftParenToken'), @@ -148,7 +152,8 @@ Child('RightParen', kind='RightParenToken') ]), - Node('PoundSourceLocationArgs', kind='Syntax', + Node('PoundSourceLocationArgs', name_for_diagnostics="'#sourceLocation' arguments", + kind='Syntax', children=[ Child('FileArgLabel', kind='IdentifierToken', text_choices=['file']), @@ -161,7 +166,7 @@ Child('LineNumber', kind='IntegerLiteralToken'), ]), - Node('DeclModifierDetail', kind='Syntax', + Node('DeclModifierDetail', name_for_diagnostics=None, kind='Syntax', traits=['Parenthesized'], children=[ Child('LeftParen', kind='LeftParenToken'), @@ -169,7 +174,7 @@ Child('RightParen', kind='RightParenToken'), ]), - Node('DeclModifier', kind='Syntax', + Node('DeclModifier', name_for_diagnostics='modifier', kind='Syntax', children=[ Child('Name', kind='Token', classification='Attribute', text_choices=[ @@ -184,18 +189,19 @@ Child('Detail', kind='DeclModifierDetail', is_optional=True), ]), - Node('InheritedType', kind='Syntax', + Node('InheritedType', name_for_diagnostics='type', kind='Syntax', traits=['WithTrailingComma'], children=[ Child('TypeName', kind='Type'), Child('TrailingComma', kind='CommaToken', is_optional=True), ]), - Node('InheritedTypeList', kind='SyntaxCollection', + Node('InheritedTypeList', name_for_diagnostics=None, kind='SyntaxCollection', element='InheritedType'), # type-inheritance-clause -> ':' type - Node('TypeInheritanceClause', kind='Syntax', + Node('TypeInheritanceClause', name_for_diagnostics='inheritance clause', + kind='Syntax', children=[ Child('Colon', kind='ColonToken'), Child('InheritedTypeCollection', kind='InheritedTypeList', @@ -209,7 +215,7 @@ # generic-where-clause? # '{' class-members '}' # class-name -> identifier - Node('ClassDecl', kind='Decl', + Node('ClassDecl', name_for_diagnostics='class', kind='Decl', traits=['DeclGroup', 'IdentifiedDecl'], children=[ Child('Attributes', kind='AttributeList', @@ -234,7 +240,7 @@ # generic-where-clause? # '{' actor-members '}' # actor-name -> identifier - Node('ActorDecl', kind='Decl', + Node('ActorDecl', name_for_diagnostics='actor', kind='Decl', traits=['DeclGroup', 'IdentifiedDecl'], children=[ Child('Attributes', kind='AttributeList', @@ -259,7 +265,7 @@ # generic-where-clause? # '{' struct-members '}' # struct-name -> identifier - Node('StructDecl', kind='Decl', + Node('StructDecl', name_for_diagnostics='struct', kind='Decl', traits=['DeclGroup', 'IdentifiedDecl'], children=[ Child('Attributes', kind='AttributeList', @@ -277,7 +283,7 @@ Child('Members', kind='MemberDeclBlock'), ]), - Node('ProtocolDecl', kind='Decl', + Node('ProtocolDecl', name_for_diagnostics='protocol', kind='Decl', traits=['DeclGroup', 'IdentifiedDecl'], children=[ Child('Attributes', kind='AttributeList', @@ -302,7 +308,8 @@ # generic-where-clause? # '{' extension-members '}' # extension-name -> identifier - Node('ExtensionDecl', kind='Decl', traits=['DeclGroup'], + Node('ExtensionDecl', name_for_diagnostics='extension', kind='Decl', + traits=['DeclGroup'], children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -317,21 +324,23 @@ Child('Members', kind='MemberDeclBlock'), ]), - Node('MemberDeclBlock', kind='Syntax', traits=['Braced'], + Node('MemberDeclBlock', name_for_diagnostics=None, kind='Syntax', + traits=['Braced'], children=[ Child('LeftBrace', kind='LeftBraceToken'), Child('Members', kind='MemberDeclList', collection_element_name='Member', is_indented=True), - Child('RightBrace', kind='RightBraceToken', + Child('RightBrace', kind='RightBraceToken', requires_leading_newline=True), ]), # member-decl-list = member-decl member-decl-list? - Node('MemberDeclList', kind='SyntaxCollection', + Node('MemberDeclList', name_for_diagnostics=None, kind='SyntaxCollection', element='MemberDeclListItem', elements_separated_by_newline=True), # member-decl = decl ';'? - Node('MemberDeclListItem', kind='Syntax', omit_when_empty=True, + Node('MemberDeclListItem', name_for_diagnostics='member', kind='Syntax', + omit_when_empty=True, description=''' A member declaration of a type consisting of a declaration and an optional semicolon; @@ -344,7 +353,7 @@ ]), # source-file = code-block-item-list eof - Node('SourceFile', kind='Syntax', + Node('SourceFile', name_for_diagnostics='source file', kind='Syntax', traits=['WithStatements'], children=[ Child('Statements', kind='CodeBlockItemList', @@ -353,7 +362,7 @@ ]), # initializer -> '=' expr - Node('InitializerClause', kind='Syntax', + Node('InitializerClause', name_for_diagnostics=None, kind='Syntax', children=[ Child('Equal', kind='EqualToken'), Child('Value', kind='Expr'), @@ -362,7 +371,7 @@ # parameter -> # external-parameter-name? local-parameter-name ':' # type '...'? '='? expression? ','? - Node('FunctionParameter', kind='Syntax', + Node('FunctionParameter', name_for_diagnostics='function parameter', kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Attributes', kind='AttributeList', @@ -415,12 +424,13 @@ # | 'unowned(unsafe)' # | 'weak' # mutation-modifier -> 'mutating' | 'nonmutating' - Node('ModifierList', kind='SyntaxCollection', + Node('ModifierList', name_for_diagnostics=None, kind='SyntaxCollection', omit_when_empty=True, element='DeclModifier', element_name='Modifier'), - Node('FunctionDecl', kind='Decl', traits=['IdentifiedDecl'], + Node('FunctionDecl', name_for_diagnostics='function', kind='Decl', + traits=['IdentifiedDecl'], children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -444,7 +454,7 @@ Child('Body', kind='CodeBlock', is_optional=True), ]), - Node('InitializerDecl', kind='Decl', + Node('InitializerDecl', name_for_diagnostics='initializer', kind='Decl', children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -467,7 +477,7 @@ Child('Body', kind='CodeBlock', is_optional=True), ]), - Node('DeinitializerDecl', kind='Decl', + Node('DeinitializerDecl', name_for_diagnostics='deinitializer', kind='Decl', children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -477,7 +487,7 @@ Child('Body', kind='CodeBlock', is_optional=True), ]), - Node('SubscriptDecl', kind='Decl', + Node('SubscriptDecl', name_for_diagnostics='subscript', kind='Decl', children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -502,7 +512,8 @@ # | 'internal' | 'internal' '(' 'set' ')' # | 'public' | 'public' '(' 'set' ')' # | 'open' | 'open' '(' 'set' ')' - Node('AccessLevelModifier', kind='Syntax', + Node('AccessLevelModifier', name_for_diagnostics='access level modifier', + kind='Syntax', children=[ Child('Name', kind='IdentifierToken'), Child('Modifier', kind='DeclModifierDetail', @@ -510,16 +521,17 @@ ]), # FIXME: technically misnamed; should be "ImportPathComponent" - Node('AccessPathComponent', kind='Syntax', + Node('AccessPathComponent', name_for_diagnostics=None, kind='Syntax', children=[ Child('Name', kind='IdentifierToken'), Child('TrailingDot', kind='PeriodToken', is_optional=True), ]), # FIXME: technically misnamed; should be "ImportPath" - Node('AccessPath', kind='SyntaxCollection', element='AccessPathComponent'), + Node('AccessPath', name_for_diagnostics=None, kind='SyntaxCollection', + element='AccessPathComponent'), - Node('ImportDecl', kind='Decl', + Node('ImportDecl', name_for_diagnostics='import', kind='Decl', children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -537,7 +549,7 @@ ]), # (value) - Node('AccessorParameter', kind='Syntax', + Node('AccessorParameter', name_for_diagnostics=None, kind='Syntax', traits=['Parenthesized'], children=[ Child('LeftParen', kind='LeftParenToken'), @@ -545,7 +557,7 @@ Child('RightParen', kind='RightParenToken'), ]), - Node('AccessorDecl', kind='Decl', + Node('AccessorDecl', name_for_diagnostics='accessor', kind='Decl', children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -571,9 +583,10 @@ Child('Body', kind='CodeBlock', is_optional=True), ]), - Node('AccessorList', kind="SyntaxCollection", element='AccessorDecl'), + Node('AccessorList', name_for_diagnostics=None, kind="SyntaxCollection", + element='AccessorDecl'), - Node('AccessorBlock', kind="Syntax", traits=['Braced'], + Node('AccessorBlock', name_for_diagnostics=None, kind="Syntax", traits=['Braced'], children=[ Child('LeftBrace', kind='LeftBraceToken'), Child('Accessors', kind='AccessorList', @@ -582,7 +595,7 @@ ]), # Pattern: Type = Value { get {} }, - Node('PatternBinding', kind="Syntax", + Node('PatternBinding', name_for_diagnostics=None, kind="Syntax", traits=['WithTrailingComma'], children=[ Child('Pattern', kind='Pattern'), @@ -595,10 +608,10 @@ Child('TrailingComma', kind='CommaToken', is_optional=True), ]), - Node('PatternBindingList', kind="SyntaxCollection", + Node('PatternBindingList', name_for_diagnostics=None, kind="SyntaxCollection", element='PatternBinding'), - Node('VariableDecl', kind='Decl', + Node('VariableDecl', name_for_diagnostics='variable', kind='Decl', children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -612,7 +625,7 @@ collection_element_name='Binding'), ]), - Node('EnumCaseElement', kind='Syntax', + Node('EnumCaseElement', name_for_diagnostics=None, kind='Syntax', description=''' An element of an enum case, containing the name of the case and, optionally, either associated values or an assignment to a raw value. @@ -634,11 +647,11 @@ '''), ]), - Node('EnumCaseElementList', kind='SyntaxCollection', + Node('EnumCaseElementList', name_for_diagnostics=None, kind='SyntaxCollection', description='A collection of 0 or more `EnumCaseElement`s.', element='EnumCaseElement'), - Node('EnumCaseDecl', kind='Decl', + Node('EnumCaseDecl', name_for_diagnostics='enum case', kind='Decl', description=''' A `case` declaration of a Swift `enum`. It can have 1 or more `EnumCaseElement`s inside, each declaring a different case of the @@ -662,7 +675,8 @@ description='The elements this case declares.') ]), - Node('EnumDecl', kind='Decl', traits=['IdentifiedDecl'], + Node('EnumDecl', name_for_diagnostics='enum', kind='Decl', + traits=['IdentifiedDecl'], description='A Swift `enum` declaration.', children=[ Child('Attributes', kind='AttributeList', @@ -707,7 +721,8 @@ ]), # operator-decl -> attribute? modifiers? 'operator' operator - Node('OperatorDecl', kind='Decl', traits=['IdentifiedDecl'], + Node('OperatorDecl', name_for_diagnostics='operator', kind='Decl', + traits=['IdentifiedDecl'], description='A Swift `operator` declaration.', children=[ Child('Attributes', kind='AttributeList', @@ -737,11 +752,11 @@ is_optional=True), ]), - Node('IdentifierList', kind='SyntaxCollection', + Node('IdentifierList', name_for_diagnostics=None, kind='SyntaxCollection', element='IdentifierToken'), # infix-operator-group -> ':' identifier ','? identifier? - Node('OperatorPrecedenceAndTypes', kind='Syntax', + Node('OperatorPrecedenceAndTypes', name_for_diagnostics=None, kind='Syntax', description=''' A clause to specify precedence group in infix operator declarations, and designated types in any operator declaration. ''', @@ -757,7 +772,8 @@ # precedence-group-decl -> attributes? modifiers? 'precedencegroup' # identifier '{' precedence-group-attribute-list # '}' - Node('PrecedenceGroupDecl', kind='Decl', traits=['IdentifiedDecl'], + Node('PrecedenceGroupDecl', name_for_diagnostics='precedencegroup', kind='Decl', + traits=['IdentifiedDecl'], description='A Swift `precedencegroup` declaration.', children=[ Child('Attributes', kind='AttributeList', @@ -788,8 +804,9 @@ # precedence-group-attribute-list -> # (precedence-group-relation | precedence-group-assignment | # precedence-group-associativity )* - Node('PrecedenceGroupAttributeList', kind='SyntaxCollection', - element='Syntax', element_name='PrecedenceGroupAttribute', + Node('PrecedenceGroupAttributeList', name_for_diagnostics=None, + kind='SyntaxCollection', element='Syntax', + element_name='PrecedenceGroupAttribute', element_choices=[ 'PrecedenceGroupRelation', 'PrecedenceGroupAssignment', @@ -798,7 +815,8 @@ # precedence-group-relation -> # ('higherThan' | 'lowerThan') ':' precedence-group-name-list - Node('PrecedenceGroupRelation', kind='Syntax', + Node('PrecedenceGroupRelation', + name_for_diagnostics="'relation' property of precedencegroup", kind='Syntax', description=''' Specify the new precedence group's relation to existing precedence groups. @@ -823,9 +841,9 @@ # precedence-group-name-list -> # identifier (',' identifier)* - Node('PrecedenceGroupNameList', kind='SyntaxCollection', + Node('PrecedenceGroupNameList', name_for_diagnostics=None, kind='SyntaxCollection', element='PrecedenceGroupNameElement'), - Node('PrecedenceGroupNameElement', kind='Syntax', + Node('PrecedenceGroupNameElement', name_for_diagnostics=None, kind='Syntax', children=[ Child('Name', kind='IdentifierToken'), Child('TrailingComma', kind='CommaToken', @@ -834,7 +852,8 @@ # precedence-group-assignment -> # 'assignment' ':' ('true' | 'false') - Node('PrecedenceGroupAssignment', kind='Syntax', + Node('PrecedenceGroupAssignment', + name_for_diagnostics="'assignment' property of precedencegroup", kind='Syntax', description=''' Specifies the precedence of an operator when used in an operation that includes optional chaining. @@ -859,7 +878,9 @@ # precedence-group-associativity -> # 'associativity' ':' ('left' | 'right' | 'none') - Node('PrecedenceGroupAssociativity', kind='Syntax', + Node('PrecedenceGroupAssociativity', + name_for_diagnostics="'associativity' property of precedencegroup", + kind='Syntax', description=''' Specifies how a sequence of operators with the same precedence level are grouped together in the absence of grouping parentheses. diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py index 9a5a13a687485..9b17e2b6dfa99 100644 --- a/utils/gyb_syntax_support/ExprNodes.py +++ b/utils/gyb_syntax_support/ExprNodes.py @@ -4,28 +4,28 @@ EXPR_NODES = [ # An inout expression. # &x - Node('InOutExpr', kind='Expr', + Node('InOutExpr', name_for_diagnostics='inout expression', kind='Expr', children=[ Child('Ampersand', kind='PrefixAmpersandToken'), Child('Expression', kind='Expr'), ]), # A #column expression. - Node('PoundColumnExpr', kind='Expr', + Node('PoundColumnExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('PoundColumn', kind='PoundColumnToken'), ]), - Node('TupleExprElementList', kind='SyntaxCollection', + Node('TupleExprElementList', name_for_diagnostics=None, kind='SyntaxCollection', element='TupleExprElement'), - Node('ArrayElementList', kind='SyntaxCollection', + Node('ArrayElementList', name_for_diagnostics=None, kind='SyntaxCollection', element='ArrayElement'), - Node('DictionaryElementList', kind='SyntaxCollection', + Node('DictionaryElementList', name_for_diagnostics=None, kind='SyntaxCollection', element='DictionaryElement'), - Node('StringLiteralSegments', kind='SyntaxCollection', + Node('StringLiteralSegments', name_for_diagnostics=None, kind='SyntaxCollection', element='Syntax', element_name='Segment', element_choices=['StringSegment', 'ExpressionSegment']), @@ -33,7 +33,7 @@ # try foo() # try? foo() # try! foo() - Node('TryExpr', kind='Expr', + Node('TryExpr', name_for_diagnostics="'try' expression", kind='Expr', children=[ Child('TryKeyword', kind='TryToken'), Child('QuestionOrExclamationMark', kind='Token', @@ -47,7 +47,7 @@ # The await operator. # await foo() - Node('AwaitExpr', kind='Expr', + Node('AwaitExpr', name_for_diagnostics="'await' expression", kind='Expr', children=[ Child('AwaitKeyword', kind='ContextualKeywordToken', text_choices=['await']), @@ -55,7 +55,7 @@ ]), # The move expr - Node('MoveExpr', kind='Expr', + Node('MoveExpr', name_for_diagnostics="'_move' expression", kind='Expr', children=[ Child('MoveKeyword', kind='ContextualKeywordToken', text_choices=['_move']), @@ -65,14 +65,14 @@ # declname-arguments -> '(' declname-argument-list ')' # declname-argument-list -> declname-argument* # declname-argument -> identifier ':' - Node('DeclNameArgument', kind='Syntax', + Node('DeclNameArgument', name_for_diagnostics=None, kind='Syntax', children=[ Child('Name', kind='Token'), Child('Colon', kind='ColonToken'), ]), - Node('DeclNameArgumentList', kind='SyntaxCollection', + Node('DeclNameArgumentList', name_for_diagnostics=None, kind='SyntaxCollection', element='DeclNameArgument'), - Node('DeclNameArguments', kind='Syntax', + Node('DeclNameArguments', name_for_diagnostics=None, kind='Syntax', traits=['Parenthesized'], children=[ Child('LeftParen', kind='LeftParenToken'), @@ -82,7 +82,7 @@ ]), # An identifier expression. - Node('IdentifierExpr', kind='Expr', + Node('IdentifierExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Identifier', kind='Token', token_choices=[ @@ -97,37 +97,37 @@ ]), # An 'super' expression. - Node('SuperRefExpr', kind='Expr', + Node('SuperRefExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('SuperKeyword', kind='SuperToken'), ]), # A nil expression. - Node('NilLiteralExpr', kind='Expr', + Node('NilLiteralExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('NilKeyword', kind='NilToken'), ]), # A _ expression. - Node('DiscardAssignmentExpr', kind='Expr', + Node('DiscardAssignmentExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Wildcard', kind='WildcardToken'), ]), # An = expression. - Node('AssignmentExpr', kind='Expr', + Node('AssignmentExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('AssignToken', kind='EqualToken'), ]), # A flat list of expressions before sequence folding, e.g. 1 + 2 + 3. - Node('SequenceExpr', kind='Expr', + Node('SequenceExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Elements', kind='ExprList', collection_element_name='Element'), ]), - Node('ExprList', kind='SyntaxCollection', + Node('ExprList', name_for_diagnostics=None, kind='SyntaxCollection', element='Expr', element_name='Expression', description=''' @@ -136,43 +136,43 @@ '''), # A #line expression. - Node('PoundLineExpr', kind='Expr', + Node('PoundLineExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('PoundLine', kind='PoundLineToken'), ]), # A #file expression. - Node('PoundFileExpr', kind='Expr', + Node('PoundFileExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('PoundFile', kind='PoundFileToken'), ]), # A #fileID expression. - Node('PoundFileIDExpr', kind='Expr', + Node('PoundFileIDExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('PoundFileID', kind='PoundFileIDToken'), ]), # A #filePath expression. - Node('PoundFilePathExpr', kind='Expr', + Node('PoundFilePathExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('PoundFilePath', kind='PoundFilePathToken'), ]), # A #function expression. - Node('PoundFunctionExpr', kind='Expr', + Node('PoundFunctionExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('PoundFunction', kind='PoundFunctionToken'), ]), # A #dsohandle expression. - Node('PoundDsohandleExpr', kind='Expr', + Node('PoundDsohandleExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('PoundDsohandle', kind='PoundDsohandleToken'), ]), # symbolic-reference-expression -> identifier generic-argument-clause? - Node('SymbolicReferenceExpr', kind='Expr', + Node('SymbolicReferenceExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Identifier', kind='IdentifierToken'), Child('GenericArgumentClause', kind='GenericArgumentClause', @@ -182,7 +182,8 @@ # A prefix operator expression. # -x # !true - Node('PrefixOperatorExpr', kind='Expr', + Node('PrefixOperatorExpr', name_for_diagnostics='prefix operator expression', + kind='Expr', children=[ Child('OperatorToken', kind='PrefixOperatorToken', is_optional=True), @@ -191,14 +192,15 @@ # An operator like + or -. # NOTE: This appears only in SequenceExpr. - Node('BinaryOperatorExpr', kind='Expr', + Node('BinaryOperatorExpr', name_for_diagnostics=None, + kind='Expr', children=[ Child('OperatorToken', kind='BinaryOperatorToken'), ]), # arrow-expr -> 'async'? 'throws'? '->' # NOTE: This appears only in SequenceExpr. - Node('ArrowExpr', kind='Expr', + Node('ArrowExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('AsyncKeyword', kind='ContextualKeywordToken', text_choices=['async'], is_optional=True), @@ -211,7 +213,7 @@ # NOTE: This won't come directly out of the parser. Rather, it is the # result of "folding" a SequenceExpr based on knowing the precedence # relationships amongst the different infix operators. - Node('InfixOperatorExpr', kind='Expr', + Node('InfixOperatorExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('LeftOperand', kind='Expr'), Child('OperatorOperand', kind='Expr'), @@ -222,12 +224,12 @@ # 4.0 # -3.9 # +4e20 - Node('FloatLiteralExpr', kind='Expr', + Node('FloatLiteralExpr', name_for_diagnostics='floating literal', kind='Expr', children=[ Child('FloatingDigits', kind='FloatingLiteralToken'), ]), - Node('TupleExpr', kind='Expr', + Node('TupleExpr', name_for_diagnostics='tuple', kind='Expr', traits=['Parenthesized'], children=[ Child('LeftParen', kind='LeftParenToken'), @@ -237,7 +239,7 @@ ]), # Array literal, e.g. [1, 2, 3] - Node('ArrayExpr', kind='Expr', + Node('ArrayExpr', name_for_diagnostics='array', kind='Expr', children=[ Child('LeftSquare', kind='LeftSquareBracketToken'), Child('Elements', kind='ArrayElementList', @@ -246,7 +248,7 @@ ]), # Dictionary literal, e.g. [1:1, 2:2, 3:3] - Node('DictionaryExpr', kind='Expr', + Node('DictionaryExpr', name_for_diagnostics='dictionary', kind='Expr', children=[ Child('LeftSquare', kind='LeftSquareBracketToken'), Child('Content', kind='Syntax', @@ -258,7 +260,7 @@ ]), # An element inside a tuple element list - Node('TupleExprElement', kind='Syntax', + Node('TupleExprElement', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Label', kind='Token', @@ -275,7 +277,7 @@ ]), # element inside an array expression: expression ','? - Node('ArrayElement', kind='Syntax', + Node('ArrayElement', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Expression', kind='Expr'), @@ -283,7 +285,7 @@ ]), # element inside an array expression: expression ','? - Node('DictionaryElement', kind='Syntax', + Node('DictionaryElement', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('KeyExpression', kind='Expr'), @@ -296,13 +298,13 @@ # 3 # +3_400 # +0x4f - Node('IntegerLiteralExpr', kind='Expr', + Node('IntegerLiteralExpr', name_for_diagnostics='integer literal', kind='Expr', children=[ Child('Digits', kind='IntegerLiteralToken'), ]), # true or false - Node('BooleanLiteralExpr', kind='Expr', + Node('BooleanLiteralExpr', name_for_diagnostics='bool literal', kind='Expr', children=[ Child("BooleanLiteral", kind='Token', token_choices=[ @@ -314,7 +316,7 @@ # ? expr : # Ternary expression without the condition and the second choice. # NOTE: This appears only in SequenceExpr. - Node('UnresolvedTernaryExpr', kind='Expr', + Node('UnresolvedTernaryExpr', name_for_diagnostics=None, kind='Expr', children=[ Child("QuestionMark", kind='InfixQuestionMarkToken'), Child("FirstChoice", kind='Expr'), @@ -326,7 +328,7 @@ # NOTE: This won't come directly out of the parser. Rather, it is the # result of "folding" a SequenceExpr based on knowing the precedence # relationships amongst the different infix operators. - Node('TernaryExpr', kind='Expr', + Node('TernaryExpr', name_for_diagnostics='ternay expression', kind='Expr', children=[ Child("ConditionExpression", kind='Expr'), Child("QuestionMark", kind='InfixQuestionMarkToken'), @@ -336,7 +338,7 @@ ]), # expr?.name - Node('MemberAccessExpr', kind='Expr', + Node('MemberAccessExpr', name_for_diagnostics='member access', kind='Expr', children=[ # The base needs to be optional to parse expressions in key paths # like \.a @@ -354,7 +356,7 @@ # 'is' # "is" type casting ooperator without operands. # NOTE: This appears only in SequenceExpr. - Node('UnresolvedIsExpr', kind='Expr', + Node('UnresolvedIsExpr', name_for_diagnostics=None, kind='Expr', children=[ Child("IsTok", kind='IsToken'), ]), @@ -363,7 +365,7 @@ # NOTE: This won't come directly out of the parser. Rather, it is the # result of "folding" a SequenceExpr based on knowing the precedence # relationships amongst the different infix operators. - Node('IsExpr', kind='Expr', + Node('IsExpr', name_for_diagnostics="'is' expression", kind='Expr', children=[ Child("Expression", kind="Expr"), Child("IsTok", kind='IsToken'), @@ -373,7 +375,7 @@ # 'as' ('?'|'!') # "as" type casting ooperator without operands. # NOTE: This appears only in SequenceExpr. - Node('UnresolvedAsExpr', kind='Expr', + Node('UnresolvedAsExpr', name_for_diagnostics=None, kind='Expr', children=[ Child("AsTok", kind='AsToken'), Child("QuestionOrExclamationMark", kind='Token', @@ -388,7 +390,7 @@ # NOTE: This won't come directly out of the parser. Rather, it is the # result of "folding" a SequenceExpr based on knowing the precedence # relationships amongst the different infix operators. - Node('AsExpr', kind='Expr', + Node('AsExpr', name_for_diagnostics="'as' expression", kind='Expr', children=[ Child("Expression", kind="Expr"), Child("AsTok", kind='AsToken'), @@ -402,12 +404,13 @@ ]), # Type - Node('TypeExpr', kind='Expr', + Node('TypeExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Type', kind='Type'), ]), - Node('ClosureCaptureItem', kind='Syntax', + Node('ClosureCaptureItem', name_for_diagnostics='closure capture item', + kind='Syntax', traits=['WithTrailingComma'], children=[ # FIXME: Add a 'CaptureSpecifier' node kind for `Specifier`. @@ -419,10 +422,11 @@ Child('TrailingComma', kind='CommaToken', is_optional=True), ]), - Node('ClosureCaptureItemList', kind='SyntaxCollection', + Node('ClosureCaptureItemList', name_for_diagnostics=None, kind='SyntaxCollection', element='ClosureCaptureItem'), - Node('ClosureCaptureSignature', kind='Syntax', + Node('ClosureCaptureSignature', name_for_diagnostics='closure capture signature', + kind='Syntax', children=[ Child('LeftSquare', kind='LeftSquareBracketToken'), Child('Items', kind='ClosureCaptureItemList', @@ -430,7 +434,7 @@ Child('RightSquare', kind='RightSquareBracketToken'), ]), - Node('ClosureParam', kind='Syntax', + Node('ClosureParam', name_for_diagnostics='closure parameter', kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Name', kind='Token', @@ -442,9 +446,10 @@ ]), # a, b, c - Node('ClosureParamList', kind='SyntaxCollection', element='ClosureParam'), + Node('ClosureParamList', name_for_diagnostics=None, kind='SyntaxCollection', + element='ClosureParam'), - Node('ClosureSignature', kind='Syntax', + Node('ClosureSignature', name_for_diagnostics='closure signature', kind='Syntax', children=[ Child('Attributes', kind='AttributeList', collection_element_name='Attribute', is_optional=True), @@ -462,7 +467,7 @@ Child('InTok', kind='InToken'), ]), - Node('ClosureExpr', kind='Expr', + Node('ClosureExpr', name_for_diagnostics='closure', kind='Expr', traits=['Braced', 'WithStatements'], children=[ Child('LeftBrace', kind='LeftBraceToken'), @@ -474,13 +479,14 @@ ]), # unresolved-pattern-expr -> pattern - Node('UnresolvedPatternExpr', kind='Expr', + Node('UnresolvedPatternExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Pattern', kind='Pattern'), ]), # trailing-closure-element -> identifier ':' closure-expression - Node('MultipleTrailingClosureElement', kind='Syntax', + Node('MultipleTrailingClosureElement', name_for_diagnostics='trailing closure', + kind='Syntax', children=[ Child('Label', kind='Token', token_choices=[ @@ -491,12 +497,12 @@ Child('Closure', kind='ClosureExpr'), ]), - Node('MultipleTrailingClosureElementList', kind='SyntaxCollection', - element='MultipleTrailingClosureElement'), + Node('MultipleTrailingClosureElementList', name_for_diagnostics=None, + kind='SyntaxCollection', element='MultipleTrailingClosureElement'), # call-expr -> expr '(' call-argument-list ')' closure-expr? # | expr closure-expr - Node('FunctionCallExpr', kind='Expr', + Node('FunctionCallExpr', name_for_diagnostics='function call', kind='Expr', children=[ Child('CalledExpression', kind='Expr'), Child('LeftParen', kind='LeftParenToken', @@ -514,7 +520,7 @@ ]), # subscript-expr -> expr '[' call-argument-list ']' closure-expr? - Node('SubscriptExpr', kind='Expr', + Node('SubscriptExpr', name_for_diagnostics='subscript', kind='Expr', children=[ Child('CalledExpression', kind='Expr'), Child('LeftBracket', kind='LeftSquareBracketToken'), @@ -530,41 +536,41 @@ ]), # optional-chaining-expr -> expr '?' - Node('OptionalChainingExpr', kind='Expr', + Node('OptionalChainingExpr', name_for_diagnostics='optional chaining', kind='Expr', children=[ Child('Expression', kind='Expr'), Child('QuestionMark', kind='PostfixQuestionMarkToken'), ]), # forced-value-expr -> expr '!' - Node('ForcedValueExpr', kind='Expr', + Node('ForcedValueExpr', name_for_diagnostics='force unwrap', kind='Expr', children=[ Child('Expression', kind='Expr'), Child('ExclamationMark', kind='ExclamationMarkToken'), ]), # postfix-unary-expr -> expr postfix-operator - Node('PostfixUnaryExpr', kind='Expr', + Node('PostfixUnaryExpr', name_for_diagnostics='postfix expression', kind='Expr', children=[ Child('Expression', kind='Expr'), Child('OperatorToken', kind='PostfixOperatorToken'), ]), # specialize-expr -> expr generic-argument-clause? - Node('SpecializeExpr', kind='Expr', + Node('SpecializeExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Expression', kind='Expr'), Child('GenericArgumentClause', kind='GenericArgumentClause'), ]), # string literal segment in a string interpolation expression. - Node('StringSegment', kind='Syntax', + Node('StringSegment', name_for_diagnostics=None, kind='Syntax', children=[ Child('Content', kind='StringSegmentToken'), ]), # expression segment in a string interpolation expression. - Node('ExpressionSegment', kind='Syntax', + Node('ExpressionSegment', name_for_diagnostics=None, kind='Syntax', traits=['Parenthesized'], children=[ Child('Backslash', kind='BackslashToken'), @@ -579,7 +585,7 @@ ]), # e.g. "abc \(foo()) def" - Node('StringLiteralExpr', kind='Expr', + Node('StringLiteralExpr', name_for_diagnostics='string literal', kind='Expr', children=[ Child('OpenDelimiter', kind='RawStringDelimiterToken', is_optional=True), @@ -601,13 +607,13 @@ # e.g '(a|c)*', the contents of the literal is opaque to the C++ Swift # parser though. - Node('RegexLiteralExpr', kind='Expr', + Node('RegexLiteralExpr', name_for_diagnostics='regex literal', kind='Expr', children=[ Child('Regex', kind='RegexLiteralToken'), ]), # e.g. "\a.b[2].a" - Node('KeyPathExpr', kind='Expr', + Node('KeyPathExpr', name_for_diagnostics='key path', kind='Expr', children=[ Child('Backslash', kind='BackslashToken'), Child('RootExpr', kind='Expr', is_optional=True, @@ -621,23 +627,24 @@ # The period in the key path serves as the base on which the # right-hand-side of the key path is evaluated - Node('KeyPathBaseExpr', kind='Expr', + Node('KeyPathBaseExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Period', kind='PeriodToken'), ]), # e.g. "a." or "a" - Node('ObjcNamePiece', kind='Syntax', + Node('ObjcNamePiece', name_for_diagnostics=None, kind='Syntax', children=[ Child('Name', kind='IdentifierToken'), Child('Dot', kind='PeriodToken', is_optional=True), ]), # e.g. "a.b.c" - Node('ObjcName', kind='SyntaxCollection', element='ObjcNamePiece'), + Node('ObjcName', name_for_diagnostics=None, kind='SyntaxCollection', + element='ObjcNamePiece'), # e.g. "#keyPath(a.b.c)" - Node('ObjcKeyPathExpr', kind='Expr', + Node('ObjcKeyPathExpr', name_for_diagnostics="'#keyPath' expression", kind='Expr', traits=['Parenthesized'], children=[ Child('KeyPath', kind='PoundKeyPathToken'), @@ -648,7 +655,7 @@ ]), # e.g. "#selector(getter:Foo.bar)" - Node('ObjcSelectorExpr', kind='Expr', + Node('ObjcSelectorExpr', name_for_diagnostics="'#selector' expression", kind='Expr', traits=['Parenthesized'], children=[ Child('PoundSelector', kind='PoundSelectorToken'), @@ -663,19 +670,20 @@ ]), # postfix '#if' expression - Node('PostfixIfConfigExpr', kind='Expr', + Node('PostfixIfConfigExpr', name_for_diagnostics=None, kind='Expr', children=[ Child('Base', kind='Expr', is_optional=True), Child('Config', kind='IfConfigDecl'), ]), # <#content#> - Node('EditorPlaceholderExpr', kind='Expr', + Node('EditorPlaceholderExpr', name_for_diagnostics='editor placeholder', + kind='Expr', children=[ Child('Identifier', kind='IdentifierToken'), ]), # #fileLiteral(a, b, c) - Node('ObjectLiteralExpr', kind='Expr', + Node('ObjectLiteralExpr', name_for_diagnostics='object literal', kind='Expr', traits=['Parenthesized'], children=[ Child('Identifier', kind='Token', diff --git a/utils/gyb_syntax_support/GenericNodes.py b/utils/gyb_syntax_support/GenericNodes.py index 008238e4f8516..bff6bc35a9d80 100644 --- a/utils/gyb_syntax_support/GenericNodes.py +++ b/utils/gyb_syntax_support/GenericNodes.py @@ -3,20 +3,20 @@ GENERIC_NODES = [ # generic-where-clause -> 'where' requirement-list - Node('GenericWhereClause', kind='Syntax', + Node('GenericWhereClause', name_for_diagnostics="'where' clause", kind='Syntax', children=[ Child('WhereKeyword', kind='WhereToken'), Child('RequirementList', kind='GenericRequirementList', collection_element_name='Requirement'), ]), - Node('GenericRequirementList', kind='SyntaxCollection', + Node('GenericRequirementList', name_for_diagnostics=None, kind='SyntaxCollection', element='GenericRequirement', element_name='GenericRequirement'), # generic-requirement -> # (same-type-requirement|conformance-requirement|layout-requirement) ','? - Node('GenericRequirement', kind='Syntax', + Node('GenericRequirement', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Body', kind='Syntax', @@ -33,7 +33,8 @@ ]), # same-type-requirement -> type-identifier == type - Node('SameTypeRequirement', kind='Syntax', + Node('SameTypeRequirement', name_for_diagnostics='same type requirement', + kind='Syntax', children=[ Child('LeftTypeIdentifier', kind='Type'), Child('EqualityToken', kind='Token', @@ -48,7 +49,7 @@ # layout-requirement -> type-name : layout-constraint # layout-constraint -> identifier '('? integer-literal? ','? integer-literal? ')'? - Node('LayoutRequirement', kind='Syntax', + Node('LayoutRequirement', name_for_diagnostics='layout requirement', kind='Syntax', children=[ Child('TypeIdentifier', kind='Type'), Child('Colon', kind='ColonToken'), @@ -63,13 +64,13 @@ is_optional=True), ]), - Node('GenericParameterList', kind='SyntaxCollection', + Node('GenericParameterList', name_for_diagnostics=None, kind='SyntaxCollection', element='GenericParameter'), # generic-parameter -> type-name # | type-name : type-identifier # | type-name : protocol-composition-type - Node('GenericParameter', kind='Syntax', + Node('GenericParameter', name_for_diagnostics='generic parameter', kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Attributes', kind='AttributeList', @@ -83,11 +84,11 @@ is_optional=True), ]), - Node('PrimaryAssociatedTypeList', kind='SyntaxCollection', - element='PrimaryAssociatedType'), + Node('PrimaryAssociatedTypeList', name_for_diagnostics=None, + kind='SyntaxCollection', element='PrimaryAssociatedType'), # primary-associated-type -> type-name ','? - Node('PrimaryAssociatedType', kind='Syntax', + Node('PrimaryAssociatedType', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Name', kind='IdentifierToken'), @@ -96,7 +97,8 @@ ]), # generic-parameter-clause -> '<' generic-parameter-list '>' - Node('GenericParameterClause', kind='Syntax', + Node('GenericParameterClause', name_for_diagnostics='generic parameter clause', + kind='Syntax', children=[ Child('LeftAngleBracket', kind='LeftAngleToken'), Child('GenericParameterList', kind='GenericParameterList', @@ -105,7 +107,8 @@ ]), # conformance-requirement -> type-identifier : type-identifier - Node('ConformanceRequirement', kind='Syntax', + Node('ConformanceRequirement', name_for_diagnostics='conformance requirement', + kind='Syntax', children=[ Child('LeftTypeIdentifier', kind='Type'), Child('Colon', kind='ColonToken'), @@ -113,7 +116,8 @@ ]), # primary-associated-type-clause -> '<' primary-associated-type-list '>' - Node('PrimaryAssociatedTypeClause', kind='Syntax', + Node('PrimaryAssociatedTypeClause', + name_for_diagnostics='primary associated type clause', kind='Syntax', children=[ Child('LeftAngleBracket', kind='LeftAngleToken'), Child('PrimaryAssociatedTypeList', kind='PrimaryAssociatedTypeList', diff --git a/utils/gyb_syntax_support/Node.py b/utils/gyb_syntax_support/Node.py index 2b341a0ec03c2..38845c250ecb8 100644 --- a/utils/gyb_syntax_support/Node.py +++ b/utils/gyb_syntax_support/Node.py @@ -11,8 +11,8 @@ class Node(object): subclass. """ - def __init__(self, name, description=None, kind=None, traits=None, - children=[], element=None, element_name=None, + def __init__(self, name, name_for_diagnostics, description=None, kind=None, + traits=None, children=[], element=None, element_name=None, element_choices=None, omit_when_empty=False, elements_separated_by_newline=False): self.syntax_kind = name @@ -20,6 +20,7 @@ def __init__(self, name, description=None, kind=None, traits=None, self.swift_syntax_kind = lowercase_first_word(name) self.name = kind_to_type(self.syntax_kind) self.kind = kind + self.name_for_diagnostics = name_for_diagnostics self.description = description self.traits = traits or [] diff --git a/utils/gyb_syntax_support/PatternNodes.py b/utils/gyb_syntax_support/PatternNodes.py index 2b63ce66adf29..493c81b08c7c1 100644 --- a/utils/gyb_syntax_support/PatternNodes.py +++ b/utils/gyb_syntax_support/PatternNodes.py @@ -4,14 +4,14 @@ PATTERN_NODES = [ # type-annotation -> ':' type - Node('TypeAnnotation', kind='Syntax', + Node('TypeAnnotation', name_for_diagnostics='type annotation', kind='Syntax', children=[ Child('Colon', kind='ColonToken'), Child('Type', kind='Type'), ]), # enum-case-pattern -> type-identifier? '.' identifier tuple-pattern? - Node('EnumCasePattern', kind='Pattern', + Node('EnumCasePattern', name_for_diagnostics='enum case pattern', kind='Pattern', children=[ Child('Type', kind='Type', is_optional=True), @@ -22,21 +22,21 @@ ]), # is-type-pattern -> 'is' type - Node('IsTypePattern', kind='Pattern', + Node('IsTypePattern', name_for_diagnostics="'is' pattern", kind='Pattern', children=[ Child('IsKeyword', kind='IsToken'), Child('Type', kind='Type'), ]), # optional-pattern -> pattern '?' - Node('OptionalPattern', kind='Pattern', + Node('OptionalPattern', name_for_diagnostics='optional pattern', kind='Pattern', children=[ Child('SubPattern', kind='Pattern'), Child('QuestionMark', kind='PostfixQuestionMarkToken'), ]), # identifier-pattern -> identifier - Node('IdentifierPattern', kind='Pattern', + Node('IdentifierPattern', name_for_diagnostics='pattern', kind='Pattern', children=[ Child('Identifier', kind='Token', token_choices=[ @@ -46,7 +46,7 @@ ]), # as-pattern -> pattern 'as' type - Node('AsTypePattern', kind='Pattern', + Node('AsTypePattern', name_for_diagnostics="'as' pattern", kind='Pattern', children=[ Child('Pattern', kind='Pattern'), Child('AsKeyword', kind='AsToken'), @@ -54,7 +54,7 @@ ]), # tuple-pattern -> '(' tuple-pattern-element-list ')' - Node('TuplePattern', kind='Pattern', + Node('TuplePattern', name_for_diagnostics='tuple pattern', kind='Pattern', traits=['Parenthesized'], children=[ Child('LeftParen', kind='LeftParenToken'), @@ -64,7 +64,7 @@ ]), # wildcard-pattern -> '_' type-annotation? - Node('WildcardPattern', kind='Pattern', + Node('WildcardPattern', name_for_diagnostics='wildcard pattern', kind='Pattern', children=[ Child('Wildcard', kind='WildcardToken'), Child('TypeAnnotation', kind='TypeAnnotation', @@ -72,7 +72,7 @@ ]), # tuple-pattern-element -> identifier? ':' pattern ','? - Node('TuplePatternElement', kind='Syntax', + Node('TuplePatternElement', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('LabelName', kind='IdentifierToken', @@ -85,19 +85,20 @@ ]), # expr-pattern -> expr - Node('ExpressionPattern', kind='Pattern', + Node('ExpressionPattern', name_for_diagnostics='pattern', kind='Pattern', children=[ Child('Expression', kind='Expr'), ]), # tuple-pattern-element-list -> tuple-pattern-element # tuple-pattern-element-list? - Node('TuplePatternElementList', kind='SyntaxCollection', + Node('TuplePatternElementList', name_for_diagnostics=None, kind='SyntaxCollection', element='TuplePatternElement'), # value-binding-pattern -> 'let' pattern # | 'var' pattern - Node('ValueBindingPattern', kind='Pattern', + Node('ValueBindingPattern', name_for_diagnostics='value binding pattern', + kind='Pattern', children=[ Child('LetOrVarKeyword', kind='Token', token_choices=[ diff --git a/utils/gyb_syntax_support/StmtNodes.py b/utils/gyb_syntax_support/StmtNodes.py index a78d4bb0dee45..b51d21cdeda66 100644 --- a/utils/gyb_syntax_support/StmtNodes.py +++ b/utils/gyb_syntax_support/StmtNodes.py @@ -3,7 +3,7 @@ STMT_NODES = [ # labeled-stmt -> label ':' stmt - Node('LabeledStmt', kind='Stmt', + Node('LabeledStmt', name_for_diagnostics='labeled statement', kind='Stmt', children=[ Child('LabelName', kind='IdentifierToken'), Child('LabelColon', kind='ColonToken'), @@ -11,7 +11,7 @@ ]), # continue-stmt -> 'continue' label? ';'? - Node('ContinueStmt', kind='Stmt', + Node('ContinueStmt', name_for_diagnostics="'continue' statement", kind='Stmt', children=[ Child('ContinueKeyword', kind='ContinueToken'), Child('Label', kind='IdentifierToken', @@ -19,7 +19,7 @@ ]), # while-stmt -> label? ':'? 'while' condition-list code-block ';'? - Node('WhileStmt', kind='Stmt', + Node('WhileStmt', name_for_diagnostics="'while' statement", kind='Stmt', traits=['WithCodeBlock'], children=[ Child('WhileKeyword', kind='WhileToken'), @@ -29,7 +29,7 @@ ]), # defer-stmt -> 'defer' code-block ';'? - Node('DeferStmt', kind='Stmt', + Node('DeferStmt', name_for_diagnostics="'defer' statement", kind='Stmt', traits=['WithCodeBlock'], children=[ Child('DeferKeyword', kind='DeferToken'), @@ -37,19 +37,19 @@ ]), # expr-stmt -> expression ';'? - Node('ExpressionStmt', kind='Stmt', + Node('ExpressionStmt', name_for_diagnostics='expression', kind='Stmt', children=[ Child('Expression', kind='Expr'), ]), # switch-case-list -> switch-case switch-case-list? - Node('SwitchCaseList', kind='SyntaxCollection', + Node('SwitchCaseList', name_for_diagnostics=None, kind='SyntaxCollection', element='Syntax', element_name='SwitchCase', element_choices=['SwitchCase', 'IfConfigDecl'], elements_separated_by_newline=True), # repeat-while-stmt -> label? ':'? 'repeat' code-block 'while' expr ';'? - Node('RepeatWhileStmt', kind='Stmt', + Node('RepeatWhileStmt', name_for_diagnostics="'repeat' statement", kind='Stmt', traits=['WithCodeBlock'], children=[ Child('RepeatKeyword', kind='RepeatToken'), @@ -59,7 +59,7 @@ ]), # guard-stmt -> 'guard' condition-list 'else' code-block ';'? - Node('GuardStmt', kind='Stmt', + Node('GuardStmt', name_for_diagnostics="'guard' statement", kind='Stmt', traits=['WithCodeBlock'], children=[ Child('GuardKeyword', kind='GuardToken'), @@ -69,7 +69,7 @@ Child('Body', kind='CodeBlock'), ]), - Node('WhereClause', kind='Syntax', + Node('WhereClause', name_for_diagnostics="'where' clause", kind='Syntax', children=[ Child('WhereKeyword', kind='WhereToken'), Child('GuardResult', kind='Expr'), @@ -78,7 +78,7 @@ # for-in-stmt -> label? ':'? # 'for' 'try'? 'await'? 'case'? pattern 'in' expr 'where'? # expr code-block ';'? - Node('ForInStmt', kind='Stmt', + Node('ForInStmt', name_for_diagnostics="'for' statement", kind='Stmt', traits=['WithCodeBlock'], children=[ Child('ForKeyword', kind='ForToken'), @@ -101,7 +101,7 @@ # switch-stmt -> identifier? ':'? 'switch' expr '{' # switch-case-list '}' ';'? - Node('SwitchStmt', kind='Stmt', + Node('SwitchStmt', name_for_diagnostics="'switch' statement", kind='Stmt', traits=['Braced'], children=[ Child('SwitchKeyword', kind='SwitchToken'), @@ -114,11 +114,11 @@ ]), # catch-clause-list -> catch-clause catch-clause-list? - Node('CatchClauseList', kind='SyntaxCollection', - element='CatchClause'), + Node('CatchClauseList', name_for_diagnostics="'catch' clause", + kind='SyntaxCollection', element='CatchClause'), # do-stmt -> identifier? ':'? 'do' code-block catch-clause-list ';'? - Node('DoStmt', kind='Stmt', + Node('DoStmt', name_for_diagnostics="'do' statement", kind='Stmt', traits=['WithCodeBlock'], children=[ Child('DoKeyword', kind='DoToken'), @@ -128,7 +128,7 @@ ]), # return-stmt -> 'return' expr? ';'? - Node('ReturnStmt', kind='Stmt', + Node('ReturnStmt', name_for_diagnostics="'return' statement", kind='Stmt', children=[ Child('ReturnKeyword', kind='ReturnToken'), Child('Expression', kind='Expr', @@ -136,7 +136,7 @@ ]), # yield-stmt -> 'yield' '('? expr-list? ')'? - Node('YieldStmt', kind='Stmt', + Node('YieldStmt', name_for_diagnostics="'yield' statement", kind='Stmt', children=[ Child('YieldKeyword', kind='YieldToken'), Child('Yields', kind='Syntax', @@ -146,7 +146,7 @@ ]), ]), - Node('YieldList', kind='Syntax', + Node('YieldList', name_for_diagnostics=None, kind='Syntax', children=[ Child('LeftParen', kind='LeftParenToken'), Child('ElementList', kind='ExprList', @@ -156,13 +156,13 @@ ]), # fallthrough-stmt -> 'fallthrough' ';'? - Node('FallthroughStmt', kind='Stmt', + Node('FallthroughStmt', name_for_diagnostics="'fallthrough' statement", kind='Stmt', children=[ Child('FallthroughKeyword', kind='FallthroughToken'), ]), # break-stmt -> 'break' identifier? ';'? - Node('BreakStmt', kind='Stmt', + Node('BreakStmt', name_for_diagnostics="'break' statement", kind='Stmt', children=[ Child('BreakKeyword', kind='BreakToken'), Child('Label', kind='IdentifierToken', @@ -170,18 +170,18 @@ ]), # case-item-list -> case-item case-item-list? - Node('CaseItemList', kind='SyntaxCollection', + Node('CaseItemList', name_for_diagnostics=None, kind='SyntaxCollection', element='CaseItem'), # catch-item-list -> catch-item catch-item-list? - Node('CatchItemList', kind='SyntaxCollection', + Node('CatchItemList', name_for_diagnostics=None, kind='SyntaxCollection', element='CatchItem'), # condition -> expression # | availability-condition # | case-condition # | optional-binding-condition - Node('ConditionElement', kind='Syntax', + Node('ConditionElement', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Condition', kind='Syntax', @@ -199,7 +199,8 @@ ]), # availability-condition -> '#available' '(' availability-spec ')' - Node('AvailabilityCondition', kind='Syntax', + Node('AvailabilityCondition', name_for_diagnostics="'#availabile' condition", + kind='Syntax', children=[ Child('PoundAvailableKeyword', kind='PoundAvailableToken'), Child('LeftParen', kind='LeftParenToken'), @@ -208,6 +209,7 @@ Child('RightParen', kind='RightParenToken'), ]), Node('MatchingPatternCondition', kind='Syntax', + name_for_diagnostics='pattern matching', children=[ Child('CaseKeyword', kind='CaseToken'), Child('Pattern', kind='Pattern'), @@ -215,7 +217,8 @@ is_optional=True), Child('Initializer', kind='InitializerClause'), ]), - Node('OptionalBindingCondition', kind='Syntax', + Node('OptionalBindingCondition', name_for_diagnostics="optional binding", + kind='Syntax', children=[ Child('LetOrVarKeyword', kind='Token', token_choices=[ @@ -229,7 +232,8 @@ ]), # unavailability-condition -> '#unavailable' '(' availability-spec ')' - Node('UnavailabilityCondition', kind='Syntax', + Node('UnavailabilityCondition', name_for_diagnostics="'#unavailable' condition", + kind='Syntax', children=[ Child('PoundUnavailableKeyword', kind='PoundUnavailableToken'), Child('LeftParen', kind='LeftParenToken'), @@ -240,18 +244,18 @@ # condition-list -> condition # | condition ','? condition-list - Node('ConditionElementList', kind='SyntaxCollection', + Node('ConditionElementList', name_for_diagnostics=None, kind='SyntaxCollection', element='ConditionElement'), # A declaration in statement position. # struct Foo {}; - Node('DeclarationStmt', kind='Stmt', + Node('DeclarationStmt', name_for_diagnostics="declaration", kind='Stmt', children=[ Child('Declaration', kind='Decl'), ]), # throw-stmt -> 'throw' expr ';'? - Node('ThrowStmt', kind='Stmt', + Node('ThrowStmt', name_for_diagnostics="'throw' statement", kind='Stmt', children=[ Child('ThrowKeyword', kind='ThrowToken'), Child('Expression', kind='Expr'), @@ -259,7 +263,7 @@ # if-stmt -> identifier? ':'? 'if' condition-list code-block # else-clause ';'? - Node('IfStmt', kind='Stmt', + Node('IfStmt', name_for_diagnostics="'if' statement", kind='Stmt', traits=['WithCodeBlock'], children=[ Child('IfKeyword', kind='IfToken'), @@ -277,13 +281,13 @@ ]), # else-if-continuation -> label? ':'? 'while' condition-list code-block ';' - Node('ElseIfContinuation', kind='Syntax', + Node('ElseIfContinuation', name_for_diagnostics=None, kind='Syntax', children=[ Child('IfStatement', kind='IfStmt'), ]), # else-clause -> 'else' code-block - Node('ElseBlock', kind='Syntax', + Node('ElseBlock', name_for_diagnostics='else block', kind='Syntax', traits=['WithCodeBlock'], children=[ Child('ElseKeyword', kind='ElseToken'), @@ -292,7 +296,7 @@ # switch-case -> unknown-attr? switch-case-label stmt-list # | unknown-attr? switch-default-label stmt-list - Node('SwitchCase', kind='Syntax', + Node('SwitchCase', name_for_diagnostics='switch case', kind='Syntax', traits=['WithStatements'], children=[ Child('UnknownAttr', kind='Attribute', is_optional=True), @@ -307,14 +311,14 @@ ]), # switch-default-label -> 'default' ':' - Node('SwitchDefaultLabel', kind='Syntax', + Node('SwitchDefaultLabel', name_for_diagnostics=None, kind='Syntax', children=[ Child('DefaultKeyword', kind='DefaultToken'), Child('Colon', kind='ColonToken'), ]), # case-item -> pattern where-clause? ','? - Node('CaseItem', kind='Syntax', + Node('CaseItem', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Pattern', kind='Pattern'), @@ -325,7 +329,7 @@ ]), # catch-item -> pattern? where-clause? ','? - Node('CatchItem', kind='Syntax', + Node('CatchItem', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('Pattern', kind='Pattern', is_optional=True), @@ -336,7 +340,7 @@ ]), # switch-case-label -> 'case' case-item-list ':' - Node('SwitchCaseLabel', kind='Syntax', + Node('SwitchCaseLabel', name_for_diagnostics=None, kind='Syntax', children=[ Child('CaseKeyword', kind='CaseToken'), Child('CaseItems', kind='CaseItemList', @@ -345,7 +349,7 @@ ]), # catch-clause 'catch' case-item-list? code-block - Node('CatchClause', kind='Syntax', + Node('CatchClause', name_for_diagnostics="'catch' clause", kind='Syntax', traits=['WithCodeBlock'], children=[ Child('CatchKeyword', kind='CatchToken'), @@ -355,7 +359,7 @@ ]), # e.g. #assert(1 == 2) - Node('PoundAssertStmt', kind='Stmt', + Node('PoundAssertStmt', name_for_diagnostics="'#assert' statement", kind='Stmt', children=[ Child('PoundAssert', kind='PoundAssertToken'), Child('LeftParen', kind='LeftParenToken'), diff --git a/utils/gyb_syntax_support/TypeNodes.py b/utils/gyb_syntax_support/TypeNodes.py index 38f0144b580ce..01d18c562b226 100644 --- a/utils/gyb_syntax_support/TypeNodes.py +++ b/utils/gyb_syntax_support/TypeNodes.py @@ -3,7 +3,7 @@ TYPE_NODES = [ # simple-type-identifier -> identifier generic-argument-clause? - Node('SimpleTypeIdentifier', kind='Type', + Node('SimpleTypeIdentifier', name_for_diagnostics='type', kind='Type', children=[ Child('Name', kind='Token', classification='TypeIdentifier', token_choices=[ @@ -16,7 +16,7 @@ ]), # member-type-identifier -> type '.' identifier generic-argument-clause? - Node('MemberTypeIdentifier', kind='Type', + Node('MemberTypeIdentifier', name_for_diagnostics='member type', kind='Type', children=[ Child('BaseType', kind='Type'), Child('Period', kind='Token', @@ -35,12 +35,12 @@ ]), # class-restriction-type -> 'class' - Node('ClassRestrictionType', kind='Type', + Node('ClassRestrictionType', name_for_diagnostics=None, kind='Type', children=[ Child('ClassKeyword', kind='ClassToken'), ]), # array-type -> '[' type ']' - Node('ArrayType', kind='Type', + Node('ArrayType', name_for_diagnostics='array type', kind='Type', children=[ Child('LeftSquareBracket', kind='LeftSquareBracketToken'), Child('ElementType', kind='Type'), @@ -48,7 +48,7 @@ ]), # dictionary-type -> '[' type ':' type ']' - Node('DictionaryType', kind='Type', + Node('DictionaryType', name_for_diagnostics='dictionary type', kind='Type', children=[ Child('LeftSquareBracket', kind='LeftSquareBracketToken'), Child('KeyType', kind='Type'), @@ -59,7 +59,7 @@ # metatype-type -> type '.' 'Type' # | type '.' 'Protocol - Node('MetatypeType', kind='Type', + Node('MetatypeType', name_for_diagnostics='metatype', kind='Type', children=[ Child('BaseType', kind='Type'), Child('Period', kind='PeriodToken'), @@ -71,14 +71,14 @@ ]), # optional-type -> type '?' - Node('OptionalType', kind='Type', + Node('OptionalType', name_for_diagnostics='optional type', kind='Type', children=[ Child('WrappedType', kind='Type'), Child('QuestionMark', kind='PostfixQuestionMarkToken'), ]), # constrained-sugar-type -> ('some'|'any') type - Node('ConstrainedSugarType', kind='Type', + Node('ConstrainedSugarType', name_for_diagnostics='type', kind='Type', children=[ Child('SomeOrAnySpecifier', kind='IdentifierToken', classification='Keyword', @@ -87,14 +87,15 @@ ]), # implicitly-unwrapped-optional-type -> type '!' - Node('ImplicitlyUnwrappedOptionalType', kind='Type', + Node('ImplicitlyUnwrappedOptionalType', + name_for_diagnostics='implicitly unwrapped optional type', kind='Type', children=[ Child('WrappedType', kind='Type'), Child('ExclamationMark', kind='ExclamationMarkToken'), ]), # composition-type-element -> type '&' - Node('CompositionTypeElement', kind='Syntax', + Node('CompositionTypeElement', name_for_diagnostics=None, kind='Syntax', children=[ Child('Type', kind='Type'), Child('Ampersand', kind='Token', @@ -104,18 +105,19 @@ # composition-typeelement-list -> composition-type-element # composition-type-element-list? - Node('CompositionTypeElementList', kind='SyntaxCollection', + Node('CompositionTypeElementList', name_for_diagnostics=None, + kind='SyntaxCollection', element='CompositionTypeElement'), # composition-type -> composition-type-element-list - Node('CompositionType', kind='Type', + Node('CompositionType', name_for_diagnostics='type composition', kind='Type', children=[ Child('Elements', kind='CompositionTypeElementList', collection_element_name='Element'), ]), # tuple-type-element -> identifier? ':'? type-annotation ','? - Node('TupleTypeElement', kind='Syntax', + Node('TupleTypeElement', name_for_diagnostics=None, kind='Syntax', traits=['WithTrailingComma'], children=[ Child('InOut', kind='InoutToken', @@ -144,11 +146,11 @@ ]), # tuple-type-element-list -> tuple-type-element tuple-type-element-list? - Node('TupleTypeElementList', kind='SyntaxCollection', + Node('TupleTypeElementList', name_for_diagnostics=None, kind='SyntaxCollection', element='TupleTypeElement'), # tuple-type -> '(' tuple-type-element-list ')' - Node('TupleType', kind='Type', + Node('TupleType', name_for_diagnostics='tuple type', kind='Type', traits=['Parenthesized'], children=[ Child('LeftParen', kind='LeftParenToken'), @@ -160,7 +162,7 @@ # throwing-specifier -> 'throws' | 'rethrows' # function-type -> attribute-list '(' function-type-argument-list ')' # async? throwing-specifier? '->'? type? - Node('FunctionType', kind='Type', + Node('FunctionType', name_for_diagnostics='function type', kind='Type', traits=['Parenthesized'], children=[ Child('LeftParen', kind='LeftParenToken'), @@ -182,7 +184,7 @@ # attributed-type -> type-specifier? attribute-list? type # type-specifier -> 'inout' | '__owned' | '__unowned' - Node('AttributedType', kind='Type', + Node('AttributedType', name_for_diagnostics='type', kind='Type', children=[ Child('Specifier', kind='Token', text_choices=['inout', '__shared', '__owned'], @@ -193,13 +195,13 @@ ]), # generic-argument-list -> generic-argument generic-argument-list? - Node('GenericArgumentList', kind='SyntaxCollection', + Node('GenericArgumentList', name_for_diagnostics=None, kind='SyntaxCollection', element='GenericArgument'), # A generic argument. # Dictionary # ^~~~ ^~~~~~ - Node('GenericArgument', kind='Syntax', + Node('GenericArgument', name_for_diagnostics='generic argument', kind='Syntax', traits=['WithTrailingComma'], children=[ Child('ArgumentType', kind='Type'), @@ -208,7 +210,8 @@ ]), # generic-argument-clause -> '<' generic-argument-list '>' - Node('GenericArgumentClause', kind='Syntax', + Node('GenericArgumentClause', name_for_diagnostics='generic argument clause', + kind='Syntax', children=[ Child('LeftAngleBracket', kind='LeftAngleToken'), Child('Arguments', kind='GenericArgumentList', From 609edfba0571dac6abf0a4ac42469fac40a6a820 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 30 Aug 2022 08:08:22 -0700 Subject: [PATCH 474/491] [Tests] NFC: Limit type wrapper tests to assert builds only (#60846) Production compilers do not support experimental features. --- test/Interpreter/type_wrappers.swift | 1 + test/type/type_wrapper.swift | 2 ++ 2 files changed, 3 insertions(+) diff --git a/test/Interpreter/type_wrappers.swift b/test/Interpreter/type_wrappers.swift index 304678f506776..b50ff36b0f5dd 100644 --- a/test/Interpreter/type_wrappers.swift +++ b/test/Interpreter/type_wrappers.swift @@ -5,6 +5,7 @@ // RUN: %target-run %t/main %t/%target-library-name(type_wrapper_defs) | %FileCheck %s // REQUIRES: executable_test +// REQUIRES: asserts import type_wrapper_defs diff --git a/test/type/type_wrapper.swift b/test/type/type_wrapper.swift index 887362c1da55d..004f4c5bd9130 100644 --- a/test/type/type_wrapper.swift +++ b/test/type/type_wrapper.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift -enable-experimental-feature TypeWrappers +// REQUIRES: asserts + @typeWrapper struct ConcreteTypeWrapper { // expected-error {{type wrapper has to declare a single generic parameter for underlying storage type}} init(memberwise: Int) {} From 413fb37b706f88265d6ea2f6825d8042d47c1523 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 30 Aug 2022 11:01:51 -0700 Subject: [PATCH 475/491] [Print as C++] Don't crash on sugared types --- lib/PrintAsClang/PrintClangFunction.cpp | 8 +++++++- test/PrintAsCxx/function_with_array.swift | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 test/PrintAsCxx/function_with_array.swift diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index d6c17b6a79473..d74c7902d9a49 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -152,7 +152,13 @@ class CFunctionSignatureTypePrinter if (printIfKnownSimpleType(alias, optionalKind, isInOutParam)) return ClangRepresentation::representable; - return visitPart(aliasTy->getSinglyDesugaredType(), optionalKind, + return visitSugarType(aliasTy, optionalKind, isInOutParam); + } + + ClangRepresentation visitSugarType(SugarType *sugarTy, + Optional optionalKind, + bool isInOutParam) { + return visitPart(sugarTy->getSinglyDesugaredType(), optionalKind, isInOutParam); } diff --git a/test/PrintAsCxx/function_with_array.swift b/test/PrintAsCxx/function_with_array.swift new file mode 100644 index 0000000000000..8aa6da33ffbca --- /dev/null +++ b/test/PrintAsCxx/function_with_array.swift @@ -0,0 +1,9 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -typecheck -clang-header-expose-public-decls -emit-clang-header-path %t/function_with_array.h +// RUN: %FileCheck %s < %t/function_with_array.h + +// CHECK: namespace function_with_array +// FIXME: we don't actually emit a declaration for this, but for now at least +// check that we don't crash. +// CHECK-NOT: void f +public func f(_: [Int]) { } From aa05d4a2c91cff81d3454141579b9d97ad8b4ba6 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 30 Aug 2022 11:09:41 -0700 Subject: [PATCH 476/491] Move new test where it belongs --- .../SwiftToCxx/functions}/PrintAsCxx/function_with_array.swift | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{ => Interop/SwiftToCxx/functions}/PrintAsCxx/function_with_array.swift (100%) diff --git a/test/PrintAsCxx/function_with_array.swift b/test/Interop/SwiftToCxx/functions/PrintAsCxx/function_with_array.swift similarity index 100% rename from test/PrintAsCxx/function_with_array.swift rename to test/Interop/SwiftToCxx/functions/PrintAsCxx/function_with_array.swift From 17664c0c6074d6738551848ceef8ef7f4949a62c Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Tue, 30 Aug 2022 12:44:11 -0700 Subject: [PATCH 477/491] Fix store_borrow multi block handling in mem2reg --- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 11 +++++++---- test/SILOptimizer/mem2reg_lifetime_borrows.sil | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index d8e22b98510ca..c93a011911ba5 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -420,8 +420,8 @@ beginLexicalLifetimeAfterStore(AllocStackInst *asi, SILInstruction *inst) { if (isGuaranteedLexicalValue(sbi->getSrc())) { return {{stored, SILValue(), SILValue()}, /*isStorageValid*/ true}; } - auto *borrow = SILBuilderWithScope(sbi).createBeginBorrow( - loc, stored, /*isLexical*/ true); + auto *borrow = SILBuilderWithScope(sbi->getNextInstruction()) + .createBeginBorrow(loc, stored, /*isLexical*/ true); return {{stored, borrow, SILValue()}, /*isStorageValid*/ true}; } BeginBorrowInst *bbi = nullptr; @@ -794,6 +794,11 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( if (!sbi) { continue; } + if (sbi->getDest() != asi) { + continue; + } + assert(!deinitializationPoints[blockPromotingWithin]); + deinitializationPoints[blockPromotingWithin] = inst; if (!runningVals.hasValue()) { continue; } @@ -802,8 +807,6 @@ SILInstruction *StackAllocationPromoter::promoteAllocationInBlock( } // Mark storage as invalid and mark end_borrow as a deinit point. runningVals->isStorageValid = false; - assert(!deinitializationPoints[blockPromotingWithin]); - deinitializationPoints[blockPromotingWithin] = inst; if (!canEndLexicalLifetime(runningVals->value)) { continue; } diff --git a/test/SILOptimizer/mem2reg_lifetime_borrows.sil b/test/SILOptimizer/mem2reg_lifetime_borrows.sil index c165e8b08d881..b366c18872c61 100644 --- a/test/SILOptimizer/mem2reg_lifetime_borrows.sil +++ b/test/SILOptimizer/mem2reg_lifetime_borrows.sil @@ -484,3 +484,20 @@ bb3: return %r : $() } +// CHECK-NOT: alloc_stack [lexical] +// CHECK-LABEL: } // end sil function 'storeborrow_multi_only_lexicalallocas' +sil [ossa] @storeborrow_multi_only_lexicalallocas : $@convention(thin) (@in_guaranteed Klass) -> () { +bb0(%0 : $*Klass): + %l = load_borrow %0 : $*Klass + %1 = alloc_stack [lexical] $Klass + %sb = store_borrow %l to %1 : $*Klass + br bb1 + +bb1: + end_borrow %sb : $*Klass + end_borrow %l : $Klass + dealloc_stack %1 : $*Klass + %6 = tuple () + return %6 : $() +} + From 9bd2d4008452bd0695d8560c80ea91e68ad51cd6 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Tue, 30 Aug 2022 12:49:17 -0700 Subject: [PATCH 478/491] [ClangImporter] Update to match new DependencyScanningService API Update ClangImporter to match new DependencyScanningService API from clang depscan. --- lib/ClangImporter/ClangModuleDependencyScanner.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index e0d6f902e3951..df0fd5063d780 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -43,9 +43,9 @@ class swift::ClangModuleDependenciesCacheImpl { DependencyScanningTool tool; ClangModuleDependenciesCacheImpl() - : importHackFileCache(), - service(ScanningMode::DependencyDirectivesScan, - ScanningOutputFormat::Full, clang::CASOptions(), nullptr), + : importHackFileCache(), service(ScanningMode::DependencyDirectivesScan, + ScanningOutputFormat::Full, + clang::CASOptions(), nullptr, nullptr), tool(service) {} ~ClangModuleDependenciesCacheImpl(); From 64ab6fcb5e3dea5bd850e9bfc8806de8c25d48a0 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 30 Aug 2022 13:10:51 -0700 Subject: [PATCH 479/491] [test] update SwiftToCxx unsigned-return-type-no-zext.cpp test to work without noundef --- .../SwiftToCxx/core/unsigned-return-type-no-zext.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp index 71e99c3a3554e..379b0da94fab1 100644 --- a/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp +++ b/test/Interop/SwiftToCxx/core/unsigned-return-type-no-zext.cpp @@ -13,5 +13,7 @@ void test(void *p) { getEnumTagi32(p); } -// CHECK: declare noundef{{( zeroext)?}} i8 @_Z12getEnumTagi8Pv(i8* noundef) -// CHECK: declare noundef i32 @_Z13getEnumTagi32Pv(i8* noundef) +// NOTE: it's important to verify that i32 function does not zeroext/signext return value. + +// CHECK: declare{{( noundef)?}}{{( zeroext)?}} i8 @_Z12getEnumTagi8Pv(i8* noundef) +// CHECK: declare{{( noundef)?}} i32 @_Z13getEnumTagi32Pv(i8* noundef) From 259b2e2e81e73dbd020091555dc3ae1dd3f30e76 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 30 Aug 2022 15:55:13 -0400 Subject: [PATCH 480/491] AST: More error-proof getContextSubstitutions() The loop at the end is meant to fill in substitutions from the local context with corresponding context archetypes, but we can end up here if the getSuperclassForDecl() class failed above. In this case, fill in the replacement types with ErrorType instead to avoid surfacing archetypes from the wrong environment. --- lib/AST/Type.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index fa18d17d8bbe0..7e3dc72183af8 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -4886,11 +4886,15 @@ TypeBase::getContextSubstitutions(const DeclContext *dc, break; } + // Add any outer generic parameters from the local context. while (n > 0) { auto *gp = params[--n]; - auto substTy = (genericEnv - ? genericEnv->mapTypeIntoContext(gp) - : gp); + Type substTy = gp; + if (baseTy && baseTy->is()) + substTy = ErrorType::get(baseTy->getASTContext()); + else if (genericEnv) + substTy = genericEnv->mapTypeIntoContext(gp); + auto result = substitutions.insert( {gp->getCanonicalType()->castTo(), substTy}); From 850797d58899a0acd1ed99d379e54a4987a19e02 Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Tue, 30 Aug 2022 16:15:09 -0700 Subject: [PATCH 481/491] [SILGen] correct missing canonicalization of global actor resolves rdar://96309577 / https://github.com/apple/swift/issues/59705 --- lib/SILGen/SILGenProlog.cpp | 2 +- test/SILGen/hop_to_executor_async_prop.swift | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index 0829a0e8cb6ef..1ab213033dd3a 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -823,7 +823,7 @@ void SILGenFunction::emitPrologGlobalActorHop(SILLocation loc, } SILValue SILGenFunction::emitLoadGlobalActorExecutor(Type globalActor) { - CanType actorType = CanType(globalActor); + CanType actorType = globalActor->getCanonicalType(); NominalTypeDecl *nominal = actorType->getNominalOrBoundGenericNominal(); VarDecl *sharedInstanceDecl = nominal->getGlobalActorInstance(); assert(sharedInstanceDecl && "no shared actor field in global actor"); diff --git a/test/SILGen/hop_to_executor_async_prop.swift b/test/SILGen/hop_to_executor_async_prop.swift index a8104899da622..394f6f4ff1985 100644 --- a/test/SILGen/hop_to_executor_async_prop.swift +++ b/test/SILGen/hop_to_executor_async_prop.swift @@ -667,7 +667,9 @@ struct Blah { } } -@MainActor +typealias FancyActor = MainActor // helps cover rdar://96309577 + +@FancyActor func getTemperature() -> Int { return 0 } @MainActor From de94d8dd921a2cbbaeab42084c6fa932004773ac Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Tue, 30 Aug 2022 16:27:50 -0700 Subject: [PATCH 482/491] [TypeChecker] add defensive nullptr checks should resolve rdar://97339014 --- lib/Sema/TypeCheckConcurrency.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 55d25e43191cf..ba55948d58aec 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -124,10 +124,13 @@ bool swift::usesFlowSensitiveIsolation(AbstractFunctionDecl const *fn) { } auto *dc = fn->getDeclContext(); + if (!dc) + return false; // Must be part of a nominal type. auto *nominal = dc->getSelfNominalTypeDecl(); - assert(nominal && "init/deinit not part of a nominal?"); + if (!nominal) + return false; // If it's part of an actor type, then its deinit and some of its inits use // flow-isolation. From f7b366c6691b868730b8c7b6fc842489eebe85ae Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 30 Aug 2022 16:34:16 -0700 Subject: [PATCH 483/491] [Sema] TypeWrappers: Don't try to manage compiler synthesized properties Properties like `unownedExecutor` that are implicitly injected into a type should not be managed by a type wrapper. --- lib/Sema/CodeSynthesis.cpp | 4 ++-- lib/Sema/TypeCheckTypeWrapper.cpp | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index c44d4bd2f6300..ce86eaeea1313 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -381,8 +381,8 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl, continue; if (!var->isAccessedViaTypeWrapper()) { - // $_storage itself. - if (var->getName() == ctx.Id_TypeWrapperProperty) + // Compiler synthesized properties are not included. + if (var->isImplicit()) continue; // Computed properties are not included. diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 2c0a1d11da56e..a7e8ac281b58d 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -312,10 +312,6 @@ bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator, if (!(parent && parent->hasTypeWrapper())) return false; - // Don't attempt to wrap the `$_storage` property. - if (property->getName() == property->getASTContext().Id_TypeWrapperProperty) - return false; - if (property->isStatic() || property->isLet()) return false; @@ -346,6 +342,11 @@ bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator, return true; } + // Don't wrap any compiler synthesized properties except to + // property wrapper backing storage (checked above). + if (property->isImplicit()) + return false; + // Check whether this is a computed property. { auto declaresAccessor = [&](ArrayRef kinds) -> bool { From 960906a2cb6c9d374b872bb428ade87aec3cc8b2 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 30 Aug 2022 16:54:10 -0700 Subject: [PATCH 484/491] [Sema] TypeWrappers: Set `$_storage` access level to `internal` Otherwise it cannot be used as a protocol requirement witness. --- lib/Sema/TypeCheckTypeWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sema/TypeCheckTypeWrapper.cpp b/lib/Sema/TypeCheckTypeWrapper.cpp index 2c0a1d11da56e..e97f1d511be29 100644 --- a/lib/Sema/TypeCheckTypeWrapper.cpp +++ b/lib/Sema/TypeCheckTypeWrapper.cpp @@ -195,7 +195,7 @@ GetTypeWrapperProperty::evaluate(Evaluator &evaluator, /*genericArgs=*/{storage->getInterfaceType()->getMetatypeInstanceType()}); return injectProperty(parent, ctx.Id_TypeWrapperProperty, propertyTy, - VarDecl::Introducer::Var, AccessLevel::Private); + VarDecl::Introducer::Var, AccessLevel::Internal); } VarDecl *GetTypeWrapperStorageForProperty::evaluate(Evaluator &evaluator, From c310abd918e93456bdcfc2f42271e0b194b8eb77 Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Tue, 30 Aug 2022 17:06:53 -0700 Subject: [PATCH 485/491] add -emit-ast and -emit-parse as aliases for the -dump-* flags This is mainly to improve usability for Swift compiler developers. resolves rdar://99357128 --- include/swift/Option/Options.td | 4 ++++ test/Frontend/ast-dump.swift | 4 ++-- test/Frontend/dump-parse-syntactically-valid.swift | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 3cc89871f2c1d..76647558d338b 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1061,9 +1061,13 @@ def typecheck : Flag<["-"], "typecheck">, def dump_parse : Flag<["-"], "dump-parse">, HelpText<"Parse input file(s) and dump AST(s)">, ModeOpt, Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; +def emit_parse : Flag<["-"], "emit-parse">, Alias, + Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; def dump_ast : Flag<["-"], "dump-ast">, HelpText<"Parse and type-check input file(s) and dump AST(s)">, ModeOpt, Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; +def emit_ast : Flag<["-"], "emit-ast">, Alias, + Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; def dump_scope_maps : Separate<["-"], "dump-scope-maps">, HelpText<"Parse and type-check input file(s) and dump the scope map(s)">, MetaVarName<"">, diff --git a/test/Frontend/ast-dump.swift b/test/Frontend/ast-dump.swift index 1ca998f0b3eeb..c6180df6eb5f2 100644 --- a/test/Frontend/ast-dump.swift +++ b/test/Frontend/ast-dump.swift @@ -3,9 +3,9 @@ // RUN: echo 'public func b() { }' >%t/b.swift // RUN: echo 'public func main() {a(); b()}' >%t/main.swift -// Test printing to stdout +// Test printing to stdout (using either -dump-ast or -emit-ast) // RUN: %target-swift-frontend -dump-ast -primary-file %t/a.swift %t/b.swift %t/main.swift -module-name main -o - 2>%t/a.swift.stderr | %FileCheck -check-prefix A-AST %s -// RUN: %target-swift-frontend -dump-ast %t/a.swift -primary-file %t/b.swift %t/main.swift -module-name main -o - 2>%t/b.swift.stderr | %FileCheck -check-prefix B-AST %s +// RUN: %target-swift-frontend -emit-ast %t/a.swift -primary-file %t/b.swift %t/main.swift -module-name main -o - 2>%t/b.swift.stderr | %FileCheck -check-prefix B-AST %s // RUN: %target-swift-frontend -dump-ast %t/a.swift %t/b.swift -primary-file %t/main.swift -module-name main -o - 2>%t/main.swift.stderr | %FileCheck -check-prefix MAIN-AST %s // Test printing to files diff --git a/test/Frontend/dump-parse-syntactically-valid.swift b/test/Frontend/dump-parse-syntactically-valid.swift index 67ed48068a42e..16a97d10d09af 100644 --- a/test/Frontend/dump-parse-syntactically-valid.swift +++ b/test/Frontend/dump-parse-syntactically-valid.swift @@ -1,5 +1,8 @@ +// RUN: %target-swift-frontend -emit-parse %s // RUN: %target-swift-frontend -dump-parse %s +// Also makes sure -emit-parse and -dump-parse are both valid. + // Make sure we don't do any Sema and don't crash. extension X { typealias Y = Z From 911cfe9fbb5d02f5b71e3b9abc96e4ca6ba47798 Mon Sep 17 00:00:00 2001 From: Tongjie Wang Date: Tue, 30 Aug 2022 17:19:00 -0700 Subject: [PATCH 486/491] print static struct member as inline and improve test cases --- lib/PrintAsClang/DeclAndTypePrinter.cpp | 8 ++++-- lib/PrintAsClang/PrintClangValueType.cpp | 28 ------------------- .../enums/resilient-enum-in-cxx.swift | 20 +++++++++---- .../swift-enum-implementation-execution.cpp | 26 ++++++++--------- .../enums/swift-enum-implementation.swift | 22 ++++++--------- 5 files changed, 43 insertions(+), 61 deletions(-) diff --git a/lib/PrintAsClang/DeclAndTypePrinter.cpp b/lib/PrintAsClang/DeclAndTypePrinter.cpp index d255ebfe16e79..34e0c206ec24c 100644 --- a/lib/PrintAsClang/DeclAndTypePrinter.cpp +++ b/lib/PrintAsClang/DeclAndTypePrinter.cpp @@ -517,7 +517,8 @@ class DeclAndTypePrinter::Implementation auto printStruct = [&](StringRef caseName, EnumElementDecl *elementDecl, Optional elementInfo) { - os << " static struct { // impl struct for case " << caseName << '\n'; + os << " inline const static struct { " + << "// impl struct for case " << caseName << '\n'; os << " inline constexpr operator cases() const {\n"; os << " return cases::"; syntaxPrinter.printIdentifier(caseName); @@ -670,6 +671,9 @@ class DeclAndTypePrinter::Implementation } os << "\n };\n\n"; // enum class cases' closing bracket + os << "#pragma clang diagnostic push\n"; + os << "#pragma clang diagnostic ignored \"-Wc++17-extensions\" " + << "// allow use of inline static data member\n"; for (const auto &pair : elementTagMapping) { // Printing struct printStruct(pair.first->getNameStr(), pair.first, pair.second); @@ -690,7 +694,7 @@ class DeclAndTypePrinter::Implementation printIsFunction(resilientUnknownDefaultCaseName, ED); os << '\n'; } - os << '\n'; + os << "#pragma clang diagnostic pop\n"; // Printing operator cases() os << " inline operator cases() const {\n"; diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index f60a2d17ffbf0..e7c54b074292b 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -302,34 +302,6 @@ void ClangValueTypePrinter::printValueTypeDecl( printCxxImplClassName(os, typeDecl); os << ";\n"; os << "};\n"; - // Print the definition of enum static struct data memebers - if (isa(typeDecl)) { - auto tagMapping = interopContext.getIrABIDetails().getEnumTagMapping( - cast(typeDecl)); - for (const auto &pair : tagMapping) { - os << "decltype("; - printer.printBaseName(typeDecl); - os << "::"; - printer.printIdentifier(pair.first->getNameStr()); - os << ") "; - printer.printBaseName(typeDecl); - os << "::"; - printer.printIdentifier(pair.first->getNameStr()); - os << ";\n"; - } - if (isOpaqueLayout) { - os << "decltype("; - printer.printBaseName(typeDecl); - // TODO: allow custom name for this special case - os << "::"; - printer.printIdentifier("unknownDefault"); - os << ") "; - printer.printBaseName(typeDecl); - os << "::"; - printer.printIdentifier("unknownDefault"); - os << ";\n"; - } - } os << '\n'; const auto *moduleContext = typeDecl->getModuleContext(); diff --git a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift index 8fcbc486230ff..46a7b96d231e8 100644 --- a/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift +++ b/test/Interop/SwiftToCxx/enums/resilient-enum-in-cxx.swift @@ -46,8 +46,7 @@ public enum Empty { // CHECK: enum class cases { // CHECK-NEXT: unknownDefault // CHECK-NEXT: }; -// CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case unknownDefault +// CHECK: inline const static struct { // impl struct for case unknownDefault // CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::unknownDefault; // CHECK-NEXT: } @@ -71,17 +70,28 @@ public enum Empty { // NEW_CASE-NEXT: b, // CHECK-NEXT: unknownDefault // CHECK-NEXT: } -// CHECK: static struct { // impl struct for case unknownDefault +// CHECK: inline const static struct { // impl struct for case unknownDefault // CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::unknownDefault; // CHECK-NEXT: } // CHECK-NEXT: } unknownDefault; // CHECK-NEXT: inline bool isUnknownDefault() const; // CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK-NEXT: inline operator cases() const { +// CHECK: inline operator cases() const { // CHECK-NEXT: auto tag = _getEnumTag(); // CHECK-NEXT: if (tag == _impl::$s5Enums3FooO1ayACSdcACmFWC) return cases::a; // NEW_CASE-NEXT: if (tag == _impl::$s5Enums3FooO1byACSicACmFWC) return cases::b; // CHECK-NEXT: return cases::unknownDefault; // CHECK-NEXT: } +// CHECK: inline Foo Foo::_impl_a::operator()(double val) const { +// CHECK-NEXT: auto result = Foo::_make(); +// CHECK-NEXT: memcpy(result._getOpaquePointer(), &val, sizeof(val)); +// CHECK-NEXT: result._destructiveInjectEnumTag(_impl::$s5Enums3FooO1ayACSdcACmFWC); +// CHECK-NEXT: return result; +// CHECK-NEXT: } +// NEW_CASE: inline Foo Foo::_impl_b::operator()(swift::Int val) const { +// NEW_CASE-NEXT: auto result = Foo::_make(); +// NEW_CASE-NEXT: memcpy(result._getOpaquePointer(), &val, sizeof(val)); +// NEW_CASE-NEXT: result._destructiveInjectEnumTag(_impl::$s5Enums3FooO1byACSicACmFWC); +// NEW_CASE-NEXT: return result; +// NEW_CASE-NEXT: } diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp b/test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp index 3b1b60b37ad75..bba31a8c2c6b3 100644 --- a/test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp +++ b/test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp @@ -15,63 +15,63 @@ using namespace Enums; -void switchTest(const E &e) { +int switchTest(const E &e) { switch (e) { case E::x: assert(e.isX()); assert(e.getX() == 3.14); - break; + return 0; case E::y: assert(e.isY()); assert(e.getY() == nullptr); - break; + return 1; case E::z: assert(e.isZ()); assert(e.getZ().getX() == 1234); - break; + return 2; case E::w: assert(e.isW()); assert(e.getW() == 5678); - break; + return 3; case E::auto_: assert(e.isAuto_()); assert(e.getAuto_() == reinterpret_cast(1)); - break; + return 4; case E::foobar: assert(e.isFoobar()); - break; + return 5; } } int main() { { auto e = E::x(3.14); - switchTest(e); + assert(switchTest(e) == 0); } { auto e = E::y(nullptr); - switchTest(e); + assert(switchTest(e) == 1); } { auto e = E::z(S::init(1234)); - switchTest(e); + assert(switchTest(e) == 2); } { auto e = E::w(5678); - switchTest(e); + assert(switchTest(e) == 3); } { auto e = E::auto_(reinterpret_cast(1)); - switchTest(e); + assert(switchTest(e) == 4); } { auto e = E::foobar(); - switchTest(e); + assert(switchTest(e) == 5); } return 0; } diff --git a/test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift b/test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift index 4ef1b9bdccd22..1da0d54dda955 100644 --- a/test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift +++ b/test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift @@ -32,7 +32,9 @@ public struct S { // CHECK-NEXT: foobar // CHECK-NEXT: }; // CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case x +// CHECK-NEXT: #pragma clang diagnostic push +// CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions" // allow use of inline static data member +// CHECK-NEXT: inline const static struct { // impl struct for case x // CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::x; // CHECK-NEXT: } @@ -41,7 +43,7 @@ public struct S { // CHECK-NEXT: inline bool isX() const; // CHECK-NEXT: inline double getX() const; // CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case y +// CHECK-NEXT: inline const static struct { // impl struct for case y // CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::y; // CHECK-NEXT: } @@ -50,7 +52,7 @@ public struct S { // CHECK-NEXT: inline bool isY() const; // CHECK-NEXT: inline void const * _Nullable getY() const; // CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case z +// CHECK-NEXT: inline const static struct { // impl struct for case z // CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::z; // CHECK-NEXT: } @@ -59,7 +61,7 @@ public struct S { // CHECK-NEXT: inline bool isZ() const; // CHECK-NEXT: inline S getZ() const; // CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case w +// CHECK-NEXT: inline const static struct { // impl struct for case w // CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::w; // CHECK-NEXT: } @@ -68,7 +70,7 @@ public struct S { // CHECK-NEXT: inline bool isW() const; // CHECK-NEXT: inline swift::Int getW() const; // CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case auto +// CHECK-NEXT: inline const static struct { // impl struct for case auto // CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::auto_; // CHECK-NEXT: } @@ -77,7 +79,7 @@ public struct S { // CHECK-NEXT: inline bool isAuto_() const; // CHECK-NEXT: inline void * _Nonnull getAuto_() const; // CHECK-EMPTY: -// CHECK-NEXT: static struct { // impl struct for case foobar +// CHECK-NEXT: inline const static struct { // impl struct for case foobar // CHECK-NEXT: inline constexpr operator cases() const { // CHECK-NEXT: return cases::foobar; // CHECK-NEXT: } @@ -85,7 +87,7 @@ public struct S { // CHECK-NEXT: } foobar; // CHECK-NEXT: inline bool isFoobar() const; // CHECK-EMPTY: -// CHECK-EMPTY: +// CHECK-NEXT: #pragma clang diagnostic pop // CHECK-NEXT: inline operator cases() const { // CHECK-NEXT: switch (_getEnumTag()) { // CHECK-NEXT: case 0: return cases::x; @@ -139,12 +141,6 @@ public struct S { // CHECK-NEXT: using _impl_auto = decltype(auto_); // CHECK-NEXT: using _impl_foobar = decltype(foobar); // CHECK: }; -// CHECK-NEXT: decltype(E::x) E::x; -// CHECK-NEXT: decltype(E::y) E::y; -// CHECK-NEXT: decltype(E::z) E::z; -// CHECK-NEXT: decltype(E::w) E::w; -// CHECK-NEXT: decltype(E::auto_) E::auto_; -// CHECK-NEXT: decltype(E::foobar) E::foobar; // CHECK-EMPTY: // CHECK-NEXT: namespace _impl { // CHECK-EMPTY: From 7c452ca400d172832e7da361f5fd151941181032 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Sat, 20 Aug 2022 20:27:16 -0700 Subject: [PATCH 487/491] [pruned-liveness] Implement FieldSensitiveAddressPrunedLiveness. This is the same algorithm as pruned liveness but assumes that one is tracking liveness from an address and uses the same scheme as DI to track liveness as a bit vector. --- include/swift/SIL/PrunedLiveness.h | 288 ++++++++++++++++++++++++++++- lib/SIL/Utils/PrunedLiveness.cpp | 242 ++++++++++++++++++++++++ 2 files changed, 529 insertions(+), 1 deletion(-) diff --git a/include/swift/SIL/PrunedLiveness.h b/include/swift/SIL/PrunedLiveness.h index c96672de1cf44..adbfac36ad7dd 100644 --- a/include/swift/SIL/PrunedLiveness.h +++ b/include/swift/SIL/PrunedLiveness.h @@ -94,7 +94,9 @@ #ifndef SWIFT_SILOPTIMIZER_UTILS_PRUNEDLIVENESS_H #define SWIFT_SILOPTIMIZER_UTILS_PRUNEDLIVENESS_H +#include "swift/AST/TypeExpansionContext.h" #include "swift/SIL/SILBasicBlock.h" +#include "swift/SIL/SILFunction.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" @@ -236,6 +238,8 @@ class PrunedLiveBlocks { assert(!discoveredBlocks || discoveredBlocks->empty()); } + unsigned getNumBitsToTrack() const { return numBitsToTrack; } + bool empty() const { return liveBlocks.empty(); } void clear() { @@ -290,7 +294,6 @@ class PrunedLiveBlocks { return; } - assert(liveBlockIter->second.size() == 1); liveBlockIter->second.getLiveness(startBitNo, endBitNo, foundLivenessInfo); } @@ -553,6 +556,289 @@ struct PrunedLivenessBoundary { ArrayRef postDomBlocks); }; +/// Given a type T and a descendent field F in T's type tree, then the +/// sub-element number of F is the first leaf element of the type tree in its +/// linearized representation. +struct SubElementNumber { + unsigned number; + + SubElementNumber(unsigned number) : number(number) {} + + /// Given an arbitrary projection \p projectionFromRoot from the \p + /// rootAddress, compute the sub element number for that \p SILValue. The sub + /// element number of a type T is always the index of its first leaf node + /// descendent in the type tree. + /// + /// DISCUSSION: This works for non-leaf types in the type tree as well as + /// normal leaf elements. It is the index of the first leaf element that is a + /// sub element of the root SILType that this projection will effect. The rest + /// of the elements effected can be found by computing the number of leaf sub + /// elements of \p projectionFromRoot's type and adding this to the result of + /// this function. + /// + /// \returns None if we didn't know how to compute sub-element for this + /// projection. + static Optional compute(SILValue projectionFromRoot, + SILValue root); + + operator unsigned() const { return number; } +}; + +/// Given a type T, this is the number of leaf field types in T's type tree. A +/// leaf field type is a descendent field of T that does not have any +/// descendent's itself. +struct TypeSubElementCount { + unsigned number; + + TypeSubElementCount(unsigned number) : number(number) {} + + /// Given a type \p type, compute the total number of leaf sub-elements of \p + /// type in the type tree. + /// + /// Some interesting properties of this computation: + /// + /// 1. When applied to the root type, this equals the total number of bits of + /// liveness that we track. + /// + /// 2. When applied to a field type F of the type tree for a type T, + /// computeNumLeafSubElements(F) when added to F's start sub element number + /// will go to the next sibling node in the type tree, walking up the tree and + /// attempting to find siblings if no further siblings exist. + TypeSubElementCount(SILType type, SILModule &mod, + TypeExpansionContext context); + + TypeSubElementCount(SILValue value) + : TypeSubElementCount(value->getType(), *value->getModule(), + TypeExpansionContext(*value->getFunction())) {} + + operator unsigned() const { return number; } +}; + +/// A span of leaf elements in the sub-element break down of the linearization +/// of the type tree of a type T. +struct TypeTreeLeafTypeRange { + SubElementNumber startEltOffset; + SubElementNumber endEltOffset; + + /// The leaf type range for the entire type tree. + TypeTreeLeafTypeRange(SILValue rootAddress) + : startEltOffset(0), endEltOffset(TypeSubElementCount(rootAddress)) {} + + /// The leaf type sub-range of the type tree of \p rootAddress, consisting of + /// \p projectedAddress and all of \p projectedAddress's descendent fields in + /// the type tree. + TypeTreeLeafTypeRange(SILValue projectedAddress, SILValue rootAddress) + : startEltOffset( + *SubElementNumber::compute(projectedAddress, rootAddress)), + endEltOffset(startEltOffset + TypeSubElementCount(projectedAddress)) {} + + /// Is the given leaf type specified by \p singleLeafElementNumber apart of + /// our \p range of leaf type values in the our larger type. + bool contains(SubElementNumber singleLeafElementNumber) const { + return startEltOffset <= singleLeafElementNumber && + singleLeafElementNumber < endEltOffset; + } + + /// Returns true if either of this overlaps at all with the given range. + bool contains(TypeTreeLeafTypeRange range) const { + if (startEltOffset <= range.startEltOffset && + range.startEltOffset < endEltOffset) + return true; + + // If our start and end offsets, our extent is only 1 and we know that our + // value + unsigned rangeLastElt = range.endEltOffset - 1; + if (range.startEltOffset == rangeLastElt) + return false; + + // Othrwise, see if endEltOffset - 1 is within the range. + return startEltOffset <= rangeLastElt && rangeLastElt < endEltOffset; + } +}; + +/// This is exactly like pruned liveness except that instead of tracking a +/// single bit of liveness, it tracks multiple bits of liveness for leaf type +/// tree nodes of an allocation one is calculating pruned liveness for. +/// +/// DISCUSSION: One can view a type T as a tree with recursively each field F of +/// the type T being a child of T in the tree. We say recursively since the tree +/// unfolds for F and its children as well. +class FieldSensitiveAddressPrunedLiveness { + PrunedLiveBlocks liveBlocks; + + struct InterestingUser { + TypeTreeLeafTypeRange subEltSpan; + bool isConsuming; + + InterestingUser(TypeTreeLeafTypeRange subEltSpan, bool isConsuming) + : subEltSpan(subEltSpan), isConsuming(isConsuming) {} + + InterestingUser &operator&=(bool otherValue) { + isConsuming &= otherValue; + return *this; + } + }; + + /// Map all "interesting" user instructions in this def's live range to a pair + /// consisting of the SILValue that it uses and a flag indicating whether they + /// must end the lifetime. + /// + /// Lifetime-ending users are always on the boundary so are always + /// interesting. + /// + /// Non-lifetime-ending uses within a LiveWithin block are interesting because + /// they may be the last use in the block. + /// + /// Non-lifetime-ending within a LiveOut block are uninteresting. + llvm::SmallMapVector users; + + /// The root address of our type tree. + SILValue rootAddress; + +public: + FieldSensitiveAddressPrunedLiveness( + SILFunction *fn, SILValue rootValue, + SmallVectorImpl *discoveredBlocks = nullptr) + : liveBlocks(TypeSubElementCount(rootValue), discoveredBlocks), + rootAddress(rootValue) {} + + bool empty() const { + assert(!liveBlocks.empty() || users.empty()); + return liveBlocks.empty(); + } + + void clear() { + liveBlocks.clear(); + users.clear(); + } + + SILValue getRootAddress() const { return rootAddress; } + + unsigned numLiveBlocks() const { return liveBlocks.numLiveBlocks(); } + + /// If the constructor was provided with a vector to populate, then this + /// returns the list of all live blocks with no duplicates. + ArrayRef getDiscoveredBlocks() const { + return liveBlocks.getDiscoveredBlocks(); + } + + using UserRange = + iterator_range *>; + UserRange getAllUsers() const { + return llvm::make_range(users.begin(), users.end()); + } + + using UserBlockRange = TransformRange< + UserRange, function_ref &)>>; + UserBlockRange getAllUserBlocks() const { + function_ref &)> + op; + op = [](const std::pair &pair) + -> SILBasicBlock * { return pair.first->getParent(); }; + return UserBlockRange(getAllUsers(), op); + } + + void initializeDefBlock(SILBasicBlock *defBB, TypeTreeLeafTypeRange span) { + liveBlocks.initializeDefBlock(defBB, span.startEltOffset, + span.endEltOffset); + } + + /// For flexibility, \p lifetimeEnding is provided by the + /// caller. PrunedLiveness makes no assumptions about the def-use + /// relationships that generate liveness. For example, use->isLifetimeEnding() + /// cannot distinguish the end of the borrow scope that defines this extended + /// live range vs. a nested borrow scope within the extended live range. + /// + /// Also for flexibility, \p affectedAddress must be a derived projection from + /// the base that \p user is affecting. + void updateForUse(SILInstruction *user, TypeTreeLeafTypeRange span, + bool lifetimeEnding); + + void getBlockLiveness( + SILBasicBlock *bb, TypeTreeLeafTypeRange span, + SmallVectorImpl &resultingFoundLiveness) const { + liveBlocks.getBlockLiveness(bb, span.startEltOffset, span.endEltOffset, + resultingFoundLiveness); + } + + /// Return the liveness for this specific sub-element of our root value. + PrunedLiveBlocks::IsLive getBlockLiveness(SILBasicBlock *bb, + unsigned subElementNumber) const { + SmallVector isLive; + liveBlocks.getBlockLiveness(bb, subElementNumber, subElementNumber + 1, + isLive); + return isLive[0]; + } + + void getBlockLiveness( + SILBasicBlock *bb, + SmallVectorImpl &foundLiveness) const { + liveBlocks.getBlockLiveness(bb, 0, liveBlocks.getNumBitsToTrack(), + foundLiveness); + } + + enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse }; + + /// Return a result indicating whether the given user was identified as an + /// interesting use of the current def and whether it ends the lifetime. + std::pair> + isInterestingUser(SILInstruction *user) const { + auto useIter = users.find(user); + if (useIter == users.end()) + return {NonUser, None}; + auto isInteresting = + useIter->second.isConsuming ? LifetimeEndingUse : NonLifetimeEndingUse; + return {isInteresting, useIter->second.subEltSpan}; + } + + unsigned getNumSubElements() const { return liveBlocks.getNumBitsToTrack(); } + + /// Return true if \p inst occurs before the liveness boundary. Used when the + /// client already knows that inst occurs after the start of liveness. + void isWithinBoundary(SILInstruction *inst, SmallBitVector &outVector) const; +}; + +/// Record the last use points and CFG edges that form the boundary of +/// FieldSensitiveAddressPrunedLiveness. It does this on a per type tree leaf +/// node basis. +struct FieldSensitiveAddressPrunedLivenessBoundary { + /// The list of last users and an associated SILValue that is the address that + /// is being used. The address can be used to determine the start sub element + /// number of the user in the type tree and the end sub element number. + /// + /// TODO (MG): If we don't eventually need to store the SILValue here (I am + /// not sure yet...), just store a tuple with the start/end sub element + /// number. + SmallVector, 8> lastUsers; + + /// Blocks where the value was live out but had a successor that was dead. + SmallVector boundaryEdges; + + void clear() { + lastUsers.clear(); + boundaryEdges.clear(); + } + + /// Compute the boundary from the blocks discovered during liveness analysis. + /// + /// Precondition: \p liveness.getDiscoveredBlocks() is a valid list of all + /// live blocks with no duplicates. + /// + /// The computed boundary will completely post-dominate, including dead end + /// paths. The client should query DeadEndBlocks to ignore those dead end + /// paths. + void compute(const FieldSensitiveAddressPrunedLiveness &liveness); + +private: + void + findLastUserInBlock(SILBasicBlock *bb, + FieldSensitiveAddressPrunedLivenessBoundary &boundary, + const FieldSensitiveAddressPrunedLiveness &liveness, + unsigned subElementNumber); +}; + } // namespace swift #endif diff --git a/lib/SIL/Utils/PrunedLiveness.cpp b/lib/SIL/Utils/PrunedLiveness.cpp index a2a3847aafc19..e6c83f0a1617e 100644 --- a/lib/SIL/Utils/PrunedLiveness.cpp +++ b/lib/SIL/Utils/PrunedLiveness.cpp @@ -371,3 +371,245 @@ void PrunedLivenessBoundary::compute(const PrunedLiveness &liveness, } } } + +//===----------------------------------------------------------------------===// +// Field Sensitive PrunedLiveness +//===----------------------------------------------------------------------===// + +// We can only analyze components of structs whose storage is fully accessible +// from Swift. +static StructDecl *getFullyReferenceableStruct(SILType ktypeTy) { + auto structDecl = ktypeTy.getStructOrBoundGenericStruct(); + if (!structDecl || structDecl->hasUnreferenceableStorage()) + return nullptr; + return structDecl; +} + +TypeSubElementCount::TypeSubElementCount(SILType type, SILModule &mod, + TypeExpansionContext context) + : number(1) { + if (auto tupleType = type.getAs()) { + unsigned numElements = 0; + for (auto index : indices(tupleType.getElementTypes())) + numElements += + TypeSubElementCount(type.getTupleElementType(index), mod, context); + number = numElements; + return; + } + + if (auto *structDecl = getFullyReferenceableStruct(type)) { + unsigned numElements = 0; + for (auto *fieldDecl : structDecl->getStoredProperties()) + numElements += TypeSubElementCount( + type.getFieldType(fieldDecl, mod, context), mod, context); + number = numElements; + return; + } + + // If this isn't a tuple or struct, it is a single element. This was our + // default value, so we can just return. +} + +Optional +SubElementNumber::compute(SILValue projectionDerivedFromRoot, + SILValue rootAddress) { + unsigned finalSubElementNumber = 0; + SILModule &mod = *rootAddress->getModule(); + + while (1) { + // If we got to the root, we're done. + if (rootAddress == projectionDerivedFromRoot) + return {SubElementNumber(finalSubElementNumber)}; + + if (auto *pbi = dyn_cast(projectionDerivedFromRoot)) { + projectionDerivedFromRoot = pbi->getOperand(); + continue; + } + + if (auto *bai = dyn_cast(projectionDerivedFromRoot)) { + projectionDerivedFromRoot = bai->getSource(); + continue; + } + + if (auto *teai = + dyn_cast(projectionDerivedFromRoot)) { + SILType tupleType = teai->getOperand()->getType(); + + // Keep track of what subelement is being referenced. + for (unsigned i : range(teai->getFieldIndex())) { + finalSubElementNumber += TypeSubElementCount( + tupleType.getTupleElementType(i), mod, + TypeExpansionContext(*rootAddress->getFunction())); + } + projectionDerivedFromRoot = teai->getOperand(); + continue; + } + + if (auto *seai = + dyn_cast(projectionDerivedFromRoot)) { + SILType type = seai->getOperand()->getType(); + + // Keep track of what subelement is being referenced. + StructDecl *structDecl = seai->getStructDecl(); + for (auto *fieldDecl : structDecl->getStoredProperties()) { + if (fieldDecl == seai->getField()) + break; + auto context = TypeExpansionContext(*rootAddress->getFunction()); + finalSubElementNumber += TypeSubElementCount( + type.getFieldType(fieldDecl, mod, context), mod, context); + } + + projectionDerivedFromRoot = seai->getOperand(); + continue; + } + + // This fails when we visit unchecked_take_enum_data_addr. We should just + // add support for enums. +#ifndef NDEBUG + if (!isa(projectionDerivedFromRoot)) { + llvm::errs() << "Unknown access path instruction!\n"; + llvm::errs() << "Value: " << *projectionDerivedFromRoot; + llvm_unreachable("standard error"); + } +#endif + // Cannot promote loads and stores from within an existential projection. + return None; + } +} + +void FieldSensitiveAddressPrunedLiveness::updateForUse( + SILInstruction *user, TypeTreeLeafTypeRange range, bool lifetimeEnding) { + SmallVector resultingLiveness; + liveBlocks.updateForUse(user, range.startEltOffset, range.endEltOffset, + resultingLiveness); + + // Note that a user may use the current value from multiple operands. If any + // of the uses are non-lifetime-ending, then we must consider the user + // itself non-lifetime-ending; it cannot be a final destroy point because + // the value of the non-lifetime-ending operand must be kept alive until the + // end of the user. Consider a call that takes the same value using + // different conventions: + // + // apply %f(%val, %val) : $(@guaranteed, @owned) -> () + // + // This call is not considered the end of %val's lifetime. The @owned + // argument must be copied. + auto iterAndSuccess = + users.insert({user, InterestingUser(range, lifetimeEnding)}); + if (!iterAndSuccess.second) + iterAndSuccess.first->second &= lifetimeEnding; +} + +void FieldSensitiveAddressPrunedLiveness::isWithinBoundary( + SILInstruction *inst, SmallBitVector &outVector) const { + SILBasicBlock *block = inst->getParent(); + + SmallVector fieldLiveness; + getBlockLiveness(block, fieldLiveness); + outVector.resize(fieldLiveness.size()); + + for (auto pair : llvm::enumerate(fieldLiveness)) { + auto isLive = pair.value(); + unsigned subEltNumber = pair.index(); + switch (isLive) { + case PrunedLiveBlocks::Dead: + outVector[subEltNumber] = false; + continue; + case PrunedLiveBlocks::LiveOut: + outVector[subEltNumber] = true; + continue; + case PrunedLiveBlocks::LiveWithin: + // The boundary is within this block. This instruction is before the + // boundary iff any interesting uses occur after it. + bool foundValue = false; + for (SILInstruction &it : + make_range(std::next(inst->getIterator()), block->end())) { + auto interestingUser = isInterestingUser(&it); + switch (interestingUser.first) { + case FieldSensitiveAddressPrunedLiveness::NonUser: + break; + case FieldSensitiveAddressPrunedLiveness::NonLifetimeEndingUse: + case FieldSensitiveAddressPrunedLiveness::LifetimeEndingUse: + // Check the overlap in between the sub element number and + // interestingUser.second. If we don't overlap, just break. We aren't + // effected by this. + // + // TODO: Hoist this out! We should only be visited blocks like this + // once! + if (!interestingUser.second->contains(subEltNumber)) + break; + outVector[subEltNumber] = true; + foundValue = true; + break; + } + } + if (foundValue) + continue; + outVector[subEltNumber] = false; + } + } +} + +// Use \p liveness to find the last use in \p bb and add it to \p +// boundary.lastUsers. +void FieldSensitiveAddressPrunedLivenessBoundary::findLastUserInBlock( + SILBasicBlock *bb, FieldSensitiveAddressPrunedLivenessBoundary &boundary, + const FieldSensitiveAddressPrunedLiveness &liveness, + unsigned subElementNumber) { + // TODO: We should move this loop into the caller and only visit a block once + // for each sub-element of a type. + for (auto &inst : llvm::reverse(*bb)) { + auto pair = liveness.isInterestingUser(&inst); + if (pair.first == FieldSensitiveAddressPrunedLiveness::NonUser) + continue; + + // Do an intersection in between the range associated with this address and + // the sub-element number we are checking for. + auto &range = *pair.second; + if (!range.contains(subElementNumber)) + continue; + boundary.lastUsers.push_back({&inst, range}); + return; + } + llvm_unreachable("No user in LiveWithin block"); +} + +void FieldSensitiveAddressPrunedLivenessBoundary::compute( + const FieldSensitiveAddressPrunedLiveness &liveness) { + using IsLive = PrunedLiveBlocks::IsLive; + SmallVector perSubElementblockLivenessInfo; + SmallVector boundaryBlockLiveness; + + for (SILBasicBlock *bb : liveness.getDiscoveredBlocks()) { + SWIFT_DEFER { perSubElementblockLivenessInfo.clear(); }; + + // Process each block that has not been visited and is not LiveOut. + liveness.getBlockLiveness(bb, perSubElementblockLivenessInfo); + + // TODO: We should do this for all sub-element LiveWithin at the same time + // so that we can avoid iterating over the block multiple times. + for (auto pair : llvm::enumerate(perSubElementblockLivenessInfo)) { + switch (pair.value()) { + case PrunedLiveBlocks::LiveOut: + for (SILBasicBlock *succBB : bb->getSuccessors()) { + liveness.getBlockLiveness(succBB, boundaryBlockLiveness); + if (llvm::all_of(boundaryBlockLiveness, [](IsLive isDead) { + return isDead == PrunedLiveBlocks::Dead; + })) { + boundaryEdges.push_back(succBB); + } + } + break; + case PrunedLiveBlocks::LiveWithin: { + // The liveness boundary is inside this block. Find the last user. This + // is where we would insert a destroy to end the values lifetime for the + // specific subelementnumber + findLastUserInBlock(bb, *this, liveness, pair.index()); + break; + } + case PrunedLiveBlocks::Dead: + break; + } + } + } +} From bd295d73a695dc70ddee3fe52626627c299c0b94 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Tue, 30 Aug 2022 20:50:00 -0700 Subject: [PATCH 488/491] Move OwnershipLowering to just before SimplifyCFG --- lib/SILOptimizer/PassManager/PassPipeline.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index 821ecb1f7e533..17962b827b59e 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -396,6 +396,15 @@ void addFunctionPasses(SILPassPipelinePlan &P, P.addSROA(); } + // Promote stack allocations to values. + P.addMem2Reg(); + + // Run the existential specializer Pass. + P.addExistentialSpecializer(); + + // Cleanup, which is important if the inliner has restarted the pass pipeline. + P.addPerformanceConstantPropagation(); + if (!P.getOptions().EnableOSSAModules && !SILDisableLateOMEByDefault) { if (P.getOptions().StopOptimizationBeforeLoweringOwnership) return; @@ -406,15 +415,6 @@ void addFunctionPasses(SILPassPipelinePlan &P, P.addNonTransparentFunctionOwnershipModelEliminator(); } - // Promote stack allocations to values. - P.addMem2Reg(); - - // Run the existential specializer Pass. - P.addExistentialSpecializer(); - - // Cleanup, which is important if the inliner has restarted the pass pipeline. - P.addPerformanceConstantPropagation(); - addSimplifyCFGSILCombinePasses(P); P.addArrayElementPropagation(); From b6878ce752c59f159add431784f804ef04b2d444 Mon Sep 17 00:00:00 2001 From: Eric Miotto <1094986+edymtt@users.noreply.github.com> Date: Wed, 31 Aug 2022 02:18:19 -0700 Subject: [PATCH 489/491] Link all compatibility libraries when cross compiling and bootstrapping (#60728) Refactor the logic so to have a single target to reference the compatibility libraries for the host, and use that when needed. The main driver for this change is supporting the cross-compilation of x86-64 on Apple Silicon. Supports rdar://90307965 --- SwiftCompilerSources/CMakeLists.txt | 13 +++++++------ cmake/modules/AddSwift.cmake | 4 +--- stdlib/toolchain/CMakeLists.txt | 12 ++++++++++++ .../SourceKit/cmake/modules/AddSwiftSourceKit.cmake | 4 +--- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/SwiftCompilerSources/CMakeLists.txt b/SwiftCompilerSources/CMakeLists.txt index 16e1ff083bb1f..b33f56e73f8b6 100644 --- a/SwiftCompilerSources/CMakeLists.txt +++ b/SwiftCompilerSources/CMakeLists.txt @@ -301,12 +301,13 @@ else() endif() endif() if(SWIFT_HOST_VARIANT_SDK IN_LIST SWIFT_DARWIN_PLATFORMS AND SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT) - set(platform ${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}) - set(compatibility_libs - "swiftCompatibility50-${platform}" - "swiftCompatibility51-${platform}" - "swiftCompatibilityDynamicReplacements-${platform}") - + # We cannot specify directly HostCompatibilityLibs + # because ultimately is used to specify a dependency for a + # custom target and, unlike `target_link_libraries`, such dependency + # would be lost at the generation of the build system. + get_property(compatibility_libs + TARGET HostCompatibilityLibs + PROPERTY INTERFACE_LINK_LIBRARIES) list(APPEND b0_deps ${compatibility_libs}) list(APPEND b1_deps ${compatibility_libs}) endif() diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 252e17d9d71bf..c0b4b51a610c8 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -465,9 +465,7 @@ function(_add_swift_runtime_link_flags target relpath_to_lib_dir bootstrapping) # the stdlib is not picked up from there, but from the SDK. # This requires to explicitly add all the needed compatibility libraries. We # can take them from the current build. - set(vsuffix "-${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}-${SWIFT_HOST_VARIANT_ARCH}") - set(conctarget "swiftCompatibilityConcurrency${vsuffix}") - target_link_libraries(${target} PUBLIC ${conctarget}) + target_link_libraries(${target} PUBLIC HostCompatibilityLibs) # Add the SDK directory for the host platform. target_link_directories(${target} PRIVATE "${sdk_dir}") diff --git a/stdlib/toolchain/CMakeLists.txt b/stdlib/toolchain/CMakeLists.txt index 2dece25db801b..06e4d8bd1d135 100644 --- a/stdlib/toolchain/CMakeLists.txt +++ b/stdlib/toolchain/CMakeLists.txt @@ -53,4 +53,16 @@ if(SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT) add_subdirectory(CompatibilityDynamicReplacements) add_subdirectory(CompatibilityConcurrency) add_subdirectory(CompatibilityThreading) + + # This is a convenience target to have the list + # of all the compatibility libraries needed to build + # host tools in a single place + add_library(HostCompatibilityLibs INTERFACE) + set(vsuffix "-${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}-${SWIFT_HOST_VARIANT_ARCH}") + target_link_libraries(HostCompatibilityLibs INTERFACE + swiftCompatibilityConcurrency${vsuffix} + swiftCompatibilityDynamicReplacements${vsuffix} + swiftCompatibility50${vsuffix} + swiftCompatibility51${vsuffix}) + set_property(GLOBAL APPEND PROPERTY SWIFT_BUILDTREE_EXPORTS HostCompatibilityLibs) endif() diff --git a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake index 58cc7051dcc87..136249c4a9c3e 100644 --- a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake +++ b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake @@ -51,9 +51,7 @@ function(add_sourcekitd_swifrt_linking target path HAS_SWIFT_MODULES) # the stdlib is not picked up from there, but from the SDK. # This requires to explicitly add all the needed compatibility libraries. We # can take them from the current build. - set(vsuffix "-${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}-${SWIFT_HOST_VARIANT_ARCH}") - set(conctarget "swiftCompatibilityConcurrency${vsuffix}") - target_link_libraries(${target} PUBLIC ${conctarget}) + target_link_libraries(${target} PUBLIC HostCompatibilityLibs) # Add the SDK directory for the host platform. target_link_directories(${target} PRIVATE "${sdk_dir}") From ad25221215968c09946c27cea3119af117f5f64f Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 30 Aug 2022 16:42:32 -0700 Subject: [PATCH 490/491] [Tests] TypeWrappers: Add test-cases to cover applying type wrapper to an actor --- .../type_wrapper_with_actors.swift | 43 +++++++++++++++++++ test/type/type_wrapper.swift | 20 ++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 test/Interpreter/type_wrapper_with_actors.swift diff --git a/test/Interpreter/type_wrapper_with_actors.swift b/test/Interpreter/type_wrapper_with_actors.swift new file mode 100644 index 0000000000000..92325394f45cf --- /dev/null +++ b/test/Interpreter/type_wrapper_with_actors.swift @@ -0,0 +1,43 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -enable-experimental-feature TypeWrappers -parse-as-library -emit-library -emit-module-path %t/type_wrapper_defs.swiftmodule -module-name type_wrapper_defs %S/Inputs/type_wrapper_defs.swift -o %t/%target-library-name(type_wrapper_defs) +// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -ltype_wrapper_defs -module-name main -I %t -L %t %s -o %t/main %target-rpath(%t) +// RUN: %target-codesign %t/main +// RUN: %target-run %t/main %t/%target-library-name(type_wrapper_defs) | %FileCheck %s + +// REQUIRES: executable_test +// REQUIRES: asserts +// REQUIRES: concurrency + +// rdar://76038845 +// REQUIRES: concurrency_runtime +// UNSUPPORTED: back_deployment_runtime + +// REQUIRES: OS=macosx + +import type_wrapper_defs + +@Wrapper +public actor Actor { + public var name: String + @PropWrapper public var age: Int? = nil + + public func setAge(_ newAge: Int) async { + age = newAge + } +} + +let a = Actor(name: "Arhtur Dent") +await print(a.name) +// CHECK: in getter +// CHECK-NEXT: Arhtur Dent +await print(a.age) +// CHECK: in getter +// CHECK-NEXT: nil + +await a.setAge(30) +// CHECK: in getter +// CHECK-NEXT: in setter => PropWrapper>(value: Optional(30)) + +await print(a.age) +// CHECK: in getter +// CHECK-NEXT: 30 diff --git a/test/type/type_wrapper.swift b/test/type/type_wrapper.swift index 004f4c5bd9130..b757c2cafe976 100644 --- a/test/type/type_wrapper.swift +++ b/test/type/type_wrapper.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-feature TypeWrappers +// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature TypeWrappers // REQUIRES: asserts @@ -380,3 +380,21 @@ func testDeclarationsWithUnmanagedProperties() { _ = OnlyLazyLetAndComputed(name: "Arthur Dent") // Ok } + +func testActors() async { + @NoopWrapper + actor Person { + var name: String + // expected-note@-1 {{mutation of this property is only permitted within the actor}} + var age: Int + // expected-note@-1 {{mutation of this property is only permitted within the actor}} + } + + let person = Person(name: "Arthur Dent", age: 30) + + _ = await person.name + _ = await person.age + + person.name = "NoName" // expected-error {{actor-isolated property 'name' can not be mutated from a non-isolated context}} + person.age = 0 // expected-error {{actor-isolated property 'age' can not be mutated from a non-isolated context}} +} From 325b54dd3397761465ffc2f83744ec30e815b298 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 31 Aug 2022 09:40:11 -0700 Subject: [PATCH 491/491] [Tests] NFC: Disable remote/device execution of type wrapper tests --- test/Interpreter/type_wrapper_with_actors.swift | 5 +++++ test/Interpreter/type_wrappers.swift | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/test/Interpreter/type_wrapper_with_actors.swift b/test/Interpreter/type_wrapper_with_actors.swift index 92325394f45cf..0bcd66b3571b1 100644 --- a/test/Interpreter/type_wrapper_with_actors.swift +++ b/test/Interpreter/type_wrapper_with_actors.swift @@ -14,6 +14,11 @@ // REQUIRES: OS=macosx +// This requires executable tests to be run on the same machine as the compiler, +// as it links with a dylib that it doesn't arrange to get uploaded to remote executors. +// (rdar://99051588) +// UNSUPPORTED: remote_run || device_run + import type_wrapper_defs @Wrapper diff --git a/test/Interpreter/type_wrappers.swift b/test/Interpreter/type_wrappers.swift index b50ff36b0f5dd..6e69161795e4d 100644 --- a/test/Interpreter/type_wrappers.swift +++ b/test/Interpreter/type_wrappers.swift @@ -7,6 +7,11 @@ // REQUIRES: executable_test // REQUIRES: asserts +// This requires executable tests to be run on the same machine as the compiler, +// as it links with a dylib that it doesn't arrange to get uploaded to remote executors. +// (rdar://99051588) +// UNSUPPORTED: remote_run || device_run + import type_wrapper_defs var p: Person = .init(name: "P", projects: ["A", "B"])