diff --git a/SwiftCompilerSources/Sources/SIL/Function.swift b/SwiftCompilerSources/Sources/SIL/Function.swift index a66e487c7aa3e..ae9f149d63a7d 100644 --- a/SwiftCompilerSources/Sources/SIL/Function.swift +++ b/SwiftCompilerSources/Sources/SIL/Function.swift @@ -147,7 +147,7 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash case .IsNotSerialized: return .notSerialized case .IsSerialized: return .serialized case .IsSerializedForPackage: return .serializedForPackage - default: fatalError() + @unknown default: fatalError() } } @@ -156,7 +156,6 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash case .notSerialized: return .IsNotSerialized case .serialized: return .IsSerialized case .serializedForPackage: return .IsSerializedForPackage - default: fatalError() } } diff --git a/benchmark/single-source/CharacterRecognizer.swift b/benchmark/single-source/CharacterRecognizer.swift index 8662291cb9ec6..13017e2634f95 100644 --- a/benchmark/single-source/CharacterRecognizer.swift +++ b/benchmark/single-source/CharacterRecognizer.swift @@ -13,7 +13,7 @@ import TestsUtils public var benchmarks: [BenchmarkInfo] { - guard #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) else { + guard #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) else { return [] } return [ @@ -82,7 +82,7 @@ let _asciiString = #""" """# let asciiString = String(repeating: _asciiString, count: 10) -@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) +@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) func run(string: String, n: Int) { var state = Unicode._CharacterRecognizer() var c = 0 diff --git a/benchmark/single-source/StringTests.swift b/benchmark/single-source/StringTests.swift index 9fa313c73208f..bcc43a2633777 100644 --- a/benchmark/single-source/StringTests.swift +++ b/benchmark/single-source/StringTests.swift @@ -14,36 +14,43 @@ import TestsUtils @_spi(_Unicode) import Swift -public let benchmarks = [ - BenchmarkInfo( - name: "StringEqualPointerComparison", - runFunction: run_StringEqualPointerComparison, - tags: [.validation, .api, .String]), - BenchmarkInfo( - name: "StringHasPrefixAscii", - runFunction: run_StringHasPrefixAscii, - tags: [.validation, .api, .String], - legacyFactor: 10), - BenchmarkInfo( - name: "StringHasPrefixUnicode", - runFunction: run_StringHasPrefixUnicode, - tags: [.validation, .api, .String], - legacyFactor: 1000), - BenchmarkInfo( - name: "StringHasSuffixAscii", - runFunction: run_StringHasSuffixAscii, - tags: [.validation, .api, .String], - legacyFactor: 10), - BenchmarkInfo( - name: "StringHasSuffixUnicode", - runFunction: run_StringHasSuffixUnicode, - tags: [.validation, .api, .String], - legacyFactor: 1000), - BenchmarkInfo( - name: "StringIterateWords", - runFunction: run_iterateWords, - tags: [.validation, .String]), -] +public var benchmarks: [BenchmarkInfo] { + var result = [ + BenchmarkInfo( + name: "StringEqualPointerComparison", + runFunction: run_StringEqualPointerComparison, + tags: [.validation, .api, .String]), + BenchmarkInfo( + name: "StringHasPrefixAscii", + runFunction: run_StringHasPrefixAscii, + tags: [.validation, .api, .String], + legacyFactor: 10), + BenchmarkInfo( + name: "StringHasPrefixUnicode", + runFunction: run_StringHasPrefixUnicode, + tags: [.validation, .api, .String], + legacyFactor: 1000), + BenchmarkInfo( + name: "StringHasSuffixAscii", + runFunction: run_StringHasSuffixAscii, + tags: [.validation, .api, .String], + legacyFactor: 10), + BenchmarkInfo( + name: "StringHasSuffixUnicode", + runFunction: run_StringHasSuffixUnicode, + tags: [.validation, .api, .String], + legacyFactor: 1000), + ] + + if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { + result.append( + BenchmarkInfo( + name: "StringIterateWords", + runFunction: run_iterateWords, + tags: [.validation, .String])) + } + return result +} // FIXME(string) public func run_StringHasPrefixAscii(_ n: Int) { @@ -1644,11 +1651,8 @@ architecture on Linux.

extension String { @inline(never) - @available(SwiftStdlib 5.9, *) + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) var _words: [Substring] { - guard #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) else { - fatalError("Can't run this benchmark") - } var result: [Substring] = [] var i = startIndex @@ -1666,6 +1670,7 @@ extension String { } } +@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public func run_iterateWords(_ n: Int) { for _ in 0 ..< n { blackHole(swiftOrgHTML._words) diff --git a/docs/DebuggingTheCompiler.md b/docs/DebuggingTheCompiler.md index 5305c43199663..e919d4a9c3978 100644 --- a/docs/DebuggingTheCompiler.md +++ b/docs/DebuggingTheCompiler.md @@ -36,6 +36,7 @@ benefit of all Swift developers. - [Bisecting on SIL optimizer pass counts to identify optimizer bugs](#bisecting-on-sil-optimizer-pass-counts-to-identify-optimizer-bugs) - [Using git-bisect in the presence of branch forwarding/feature branches](#using-git-bisect-in-the-presence-of-branch-forwardingfeature-branches) - [Reducing SIL test cases using bug_reducer](#reducing-sil-test-cases-using-bug_reducer) + - [Disabling PCH Verification](#disabling-pch-verification) - [Debugging the Compiler Build](#debugging-the-compiler-build) - [Build Dry Run](#build-dry-run) - [Debugging the Compiler Driver](#debugging-the-compiler-driver-build) @@ -832,6 +833,19 @@ each time you change shas. To do this you can pass `--match-timestamp` to automatically checkout match the timestamp of the `apple/swift` repo across the other repos. +## Disabling PCH Verification + +Sometimes one needs to try to compile against PCH modules where the PCH version +verification checking is too strict. To work around this, one can disable the +checking by passing in to swift: + +```sh +-Xcc -Xclang -Xcc -fno-validate-pch +``` + +NOTE: If there are actual differences in between the on disk PCH format and the +format expected by the compiler crashes and undefined behavior may result. + # Debugging the Compiler Build ## Build Dry Run diff --git a/docs/EmbeddedSwift/ABI.md b/docs/EmbeddedSwift/ABI.md new file mode 100644 index 0000000000000..d7046239ceef6 --- /dev/null +++ b/docs/EmbeddedSwift/ABI.md @@ -0,0 +1,37 @@ +# Embedded Swift -- ABI + +**⚠️ Embedded Swift is experimental. This document might be out of date with latest development.** + +**‼️ Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.** + +For an introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/apple/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches. + +## ABI stability + +The ABI of code generated by Embedded Swift is not currently stable. For a concrete compiler version, it will be consistent, but do not mix code built with different compiler versions. + +Similarly, do not mix Embedded Swift code with full Swift code, as the ABIs are different. Details are described in the following sections. + +## Calling convention of Embedded Swift + +As of today, Embedded Swift has identical calling convention to full Swift. However, this does not need to continue in the future, and there should not be expectations that the ABI of Embedded Swift is compatible with full Swift. + +The compiler respects the ABIs and calling conventions of C and C++ when interoperating with code in those languages. Calling C/C++ functions from Embedded Swift code is supported, and similarly exporting Swift code via `@_extern`, `@_cdecl` or `@_expose` will match the right calling conventions that C/C++ expects. + +## Metadata ABI of Embedded Swift + +Embedded Swift eliminates almost all metadata compared to full Swift. However, class metadata is still used, because those serve as vtables for dynamic dispatch of methods to implement runtime polymorphism. The layout of Embedded Swift's class metadata is *different* from full Swift: + +- The **super pointer** pointing to the class metadata record for the superclass is stored at **offset 0**. If the class is a root class, it is null. +- The **destructor pointer** is stored at **offset 1**. This function is invoked by Swift's deallocator when the class instance is destroyed. +- The **ivar destroyer** is stored at **offset 2**. This function is invoked to destroy instance members when creation of the object is cancelled (e.g. in a failable initializer). +- Lastly, the **vtable** is stored at **offset 3**: For each Swift class in the class's inheritance hierarchy, in order starting + from the root class and working down to the most derived class, the function pointers to the implementation of every method of the class in declaration order in stored. + +## Heap object layout in Embedded Swift + +Heap objects have the following layout in Embedded Swift: + +- The **isa pointer** (pointer to the class metadata) is stored at **offset 0**. +- The **refcount** is stored inline at **offset 1**. +- Normal stored properties follow. diff --git a/docs/EmbeddedSwift/EmbeddedSwiftStatus.md b/docs/EmbeddedSwift/EmbeddedSwiftStatus.md index 35e347b6d84a8..4d85cf4b6e217 100644 --- a/docs/EmbeddedSwift/EmbeddedSwiftStatus.md +++ b/docs/EmbeddedSwift/EmbeddedSwiftStatus.md @@ -34,7 +34,7 @@ This status table describes which of the following standard library features can | Codable, Encodable, Decodable | No | | Collection + related protocols | Yes | | Collection algorithms (sort, reverse) | Yes | -| CustomStringConvertible, CustomDebugStringConvertible | No | +| CustomStringConvertible, CustomDebugStringConvertible | Yes, except those that require reflection (e.g. Array's .description) | | Dictionary (dynamic heap-allocated container) | Yes | | FixedWidthInteger + related protocols | Yes | | Hashable, Equatable, Comparable protocols | Yes | @@ -45,15 +45,15 @@ This status table describes which of the following standard library features can | Mirror (runtime reflection) | No, intentionally unsupported long-term | | Objective-C bridging | No, intentionally unsupported long-term | | Optional | Yes | -| print / debugPrint | Partial (only StaticStrings and integers) | +| print / debugPrint | Partial (only String, string interpolation, StaticStrings, integers, pointers and booleans) | | Range, ClosedRange, Stride | Yes | | Result | Yes | | Set (dynamic heap-allocated container) | Yes | | SIMD types | Yes | | StaticString | Yes | -| String (dynamic) | No (work in progress) | -| String Interpolations | No (work in progress) | -| Unicode | No | +| String (dynamic) | Yes | +| String Interpolations | Yes | +| Unicode | Yes | | Unsafe\[Mutable\]\[Raw\]\[Buffer\]Pointer | Yes | | VarArgs | No | diff --git a/docs/EmbeddedSwift/UserManual.md b/docs/EmbeddedSwift/UserManual.md index 46ad35a850887..e7e12012cb52f 100644 --- a/docs/EmbeddedSwift/UserManual.md +++ b/docs/EmbeddedSwift/UserManual.md @@ -20,13 +20,13 @@ The following document explains how to use Embedded Swift's support in the Swift A typical setup and build + run cycle for an embedded development board involves: - (1) Getting an SDK with the C compilers, headers and libraries for the target -- (2) Building the C source code, and Swift source code +- (2) Building the C source code, and Swift source code into object files. - (3) Linking all the libraries, C object files, and Swift object files. -- (4) Post-processing the linked firmware into a flashable format (UD2, BIN, or bespoke formats) +- (4) Post-processing the linked firmware into a flashable format (UF2, BIN, or bespoke formats) - (5) Uploading the flashable binary to the board over a USB cable using some vendor-provided JTAG/SWD tool or by copying it to a fake USB Mass Storage volume presented by the board. - (6) Restarting the board, observing physical effects of the firmware (LEDs light up) or UART output over USB, or presence on network, etc. -Most of these steps are out of scope for this document, instead refer to the vendor provided documentation and get familiar with the details of firmware development for your board without Swift in the mix first. Even if you want to build a completely pure Swift firmware, you are still very likely going to need the vendor provided tooling for linking, post-processing, uploading, etc. +Most of these steps are out of scope for this document, instead refer to the vendor provided documentation. This document only focuses on (2) from the list above, and it's important that you first get familiar with the details of firmware development for your board without Swift in the mix. Even if you want to build a completely pure Swift firmware, you are still going to need the vendor provided tooling for linking, post-processing, uploading, etc. ## Building code using Embedded Swift @@ -41,7 +41,7 @@ $ swiftc -target -enable-experimental-feature Embedded -wmo \ ### Building Swift firmware for an embedded target -To build Swift firmware (for now ingnoring integration with SDKs, libraries and other pre-existing C code), we can use the `-target` argument to specify the CPU architecture. The target triple also decides whether the output object file will be an ELF file, or a Mach-O. For example: +To build Swift firmware (for now ignoring integration with SDKs, libraries and other pre-existing C code), we can use the `-target` argument to specify the CPU architecture. The target triple also decides whether the output object file will be an ELF file, or a Mach-O. For example: ```bash # To build an ARMv7 Mach-O object file: @@ -49,7 +49,7 @@ $ swiftc -target armv7-apple-none-macho -enable-experimental-feature Embedded -w input1.swift input2.swift ... -c -o output.o # To build an ARMv7 ELF object file: -$ swiftc -target armv7-unknown-none-eabi -enable-experimental-feature Embedded -wmo \ +$ swiftc -target armv7-none-none-eabi -enable-experimental-feature Embedded -wmo \ input1.swift input2.swift ... -c -o output.o ``` @@ -59,7 +59,7 @@ For example, a Raspberry Pi Pico / Pico W should target the ARMv6-M architecture ```bash # To build an ELF object file for ARMv6-M with soft float ABI (floating-point arguments passed in integer registers) and "short enums": -$ swiftc -target armv6m-unknown-none-eabi -enable-experimental-feature Embedded -wmo \ +$ swiftc -target armv6m-none-none-eabi -enable-experimental-feature Embedded -wmo \ -Xcc -mfloat-abi=soft -Xcc -fshort-enums \ input1.swift input2.swift ... -c -o output.o ``` @@ -98,6 +98,58 @@ Segment __TEXT: 16384 ... ``` +## Strings + +Both StaticString and String types are available in Embedded Swift. As is the case in desktop Swift, certain operations on strings require Unicode data tables for strict Unicode compliance. In Embedded Swift. these data tables are provided as a separate static library (libUnicodeDataTables.a) that users need to link in manually – if they need to use these string operations. If the library is required, linking will fail due to missing on one or more of the following symbols: + +``` +_swift_stdlib_getAge +_swift_stdlib_getBinaryProperties +_swift_stdlib_getCaseMapping +_swift_stdlib_getComposition +_swift_stdlib_getDecompositionEntry +_swift_stdlib_getGeneralCategory +_swift_stdlib_getGraphemeBreakProperty +_swift_stdlib_getMapping +_swift_stdlib_getMphIdx +_swift_stdlib_getNameAlias +_swift_stdlib_getNormData +_swift_stdlib_getNumericType +_swift_stdlib_getNumericValue +_swift_stdlib_getScalarBitArrayIdx +_swift_stdlib_getScalarName +_swift_stdlib_getScript +_swift_stdlib_getScriptExtensions +_swift_stdlib_getSpecialMapping +_swift_stdlib_getWordBreakProperty +_swift_stdlib_isLinkingConsonant +_swift_stdlib_nfd_decompositions +``` + +To resolve this, link in the libswiftUnicodeDataTables.a that's in Swift toolchain's resource directory (`lib/swift/`) under the target triple that you're using: + +```bash +$ swiftc -target armv6m-none-none-eabi -enable-experimental-feature Embedded -wmo -c -o output.o +$ ld ... -o binary output.o $(dirname `which swiftc`)/../lib/swift/embedded/armv6m-none-none-eabi/libswiftUnicodeDataTables.a +``` + +**Unicode data tables are required for (list not exhaustive):** + +- Comparing String objects for equality +- Sorting Strings +- Using String's hash values, and in particular using String as dictionary keys +- Using String's .count property +- Using Unicode-aware string processing APIs (.split(), iterating characters, indexing) +- Using Unicode-aware conversion String APIs (.uppercased(), .lowercased(), etc.) + +**For contrast, unicode data tables are *not required for* (list not exhaustive):** + +- Using StaticString +- Creating, concatenating, string interpolating, and printing String objects +- Using .utf8, .utf16, and .unicodeScalars views of strings, including their .count property, using them as dictionary keys + +Manually linking libUnicodeDataTables.a is required for several reasons, including acknowledging that the data tables are desirable: Since they have a non-negligible size, it's useful to be aware that you are using them. + ## Conditionalizing compilation for Embedded Swift It's often useful to have source code be compilable under both regular Swift and Embedded Swift. The following syntax is available for that (but note that as the rest of Embedded Swift, it's experimental, subject to change and not considered source stable): @@ -133,8 +185,7 @@ Features that are not available: - **Not available**: Runtime reflection (`Mirror` APIs). - **Not available**: Values of protocol types ("existentials"), e.g. `let a: Hashable = ...`, are not allowed. `Any` and `AnyObject` are also not allowed. - **Not available**: Metatypes, e.g. `let t = SomeClass.Type` or `type(of: value)` are not allowed. -- **Not available yet (under development)**: The print() function for types other than StaticString and integers. -- **Not available yet (under development)**: String. (StaticString **is** available). +- **Not available**: Printing and stringification of arbitrary types (achieved via reflection in desktop Swift). - **Not available yet (under development)**: Swift Concurrency. For a more complete list of supported features in Embedded Swift, see [Embedded Swift -- Status](EmbeddedSwiftStatus.md). @@ -159,7 +210,14 @@ The Embedded Swift standard library is distributed in the toolchain the same way ## Allocating and non-allocating Embedded Swift mode -Embedded Swift does allow instantiating and using reference types (classes) which are refcounted objects allocated on the heap. A common case of needing those is for dynamic containers like arrays and sets (they use dynamically-sized heap-allocated class instances as their storage). Outside of creating class instances and explicitly calling allocation APIs (e.g. `UnsafeMutablePointer.allocate()`), Embedded Swift does not perform allocations or cause heap usage. +Embedded Swift does allow instantiating and using reference types (classes) which are refcounted objects allocated on the heap. A common case of needing those is for dynamic containers like arrays and sets (they use dynamically-sized heap-allocated class instances as their storage). There is only a handful of Swift language features that cause allocations: + +- creating class instances, +- escaping a closure that captures local variables, +- creating an indirect enum case with a payload referencing the enum itself +- explicitly calling allocation APIs (e.g. `UnsafeMutablePointer.allocate()`). + +Outside of those cases, Embedded Swift does not perform allocations or cause heap usage. Some embedded platforms don't have and/or don't want *any heap allocations whatsoever* and don't provide a heap at all. The `-no-allocations` compiler flag can be used to match that, which will cause the compiler to produce an error at compile time when creating class instances or calling allocation APIs. diff --git a/docs/HowToGuides/GettingStarted.md b/docs/HowToGuides/GettingStarted.md index 8c05222bf9ad7..d8f83e084b20d 100644 --- a/docs/HowToGuides/GettingStarted.md +++ b/docs/HowToGuides/GettingStarted.md @@ -262,7 +262,7 @@ Build the toolchain with optimizations, debuginfo, and assertions, using Ninja: - macOS: ```sh utils/build-script --skip-build-benchmarks \ - --skip-ios --skip-watchos --skip-tvos --swift-darwin-supported-archs "$(uname -m)" \ + --skip-ios --skip-watchos --skip-tvos --skip-xros --swift-darwin-supported-archs "$(uname -m)" \ --sccache --release-debuginfo --swift-disable-dead-stripping \ --bootstrapping=hosttools ``` diff --git a/include/swift/ABI/Executor.h b/include/swift/ABI/Executor.h index d7769211b0d43..95dc3c660ffa2 100644 --- a/include/swift/ABI/Executor.h +++ b/include/swift/ABI/Executor.h @@ -260,12 +260,6 @@ class TaskExecutorRef { return reinterpret_cast(table); } -// /// Do we have to do any work to start running as the requested -// /// executor? -// bool mustSwitchToRun(TaskExecutorRef newExecutor) const { -// return Identity != newExecutor.Identity; -// } - /// Get the raw value of the Implementation field, for tracing. uintptr_t getRawImplementation() const { return Implementation & WitnessTableMask; diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h index edd1ccfd5f932..3fdc23fb5f2e9 100644 --- a/include/swift/ABI/MetadataValues.h +++ b/include/swift/ABI/MetadataValues.h @@ -2697,7 +2697,8 @@ enum class TaskOptionRecordKind : uint8_t { /// Information about the result type of the task, used in embedded Swift. ResultTypeInfo = 4, /// Set the initial task executor preference of the task. - InitialTaskExecutor = 5, + InitialTaskExecutorUnowned = 5, + InitialTaskExecutorOwned = 6, /// Request a child task for swift_task_run_inline. RunInline = UINT8_MAX, }; diff --git a/include/swift/ABI/Task.h b/include/swift/ABI/Task.h index 4ef2550b8ca3e..1cefd0f45077d 100644 --- a/include/swift/ABI/Task.h +++ b/include/swift/ABI/Task.h @@ -419,12 +419,16 @@ class AsyncTask : public Job { /// Get the preferred task executor reference if there is one set for this /// task. - TaskExecutorRef getPreferredTaskExecutor(); + TaskExecutorRef getPreferredTaskExecutor(bool assumeHasRecord = false); /// WARNING: Only to be used during task creation, in other situations prefer /// to use `swift_task_pushTaskExecutorPreference` and /// `swift_task_popTaskExecutorPreference`. - void pushInitialTaskExecutorPreference(TaskExecutorRef preferred); + /// + /// The `owned` parameter indicates if the executor is owned by the task, + /// and must be released when the task completes. + void pushInitialTaskExecutorPreference( + TaskExecutorRef preferred, bool owned); /// WARNING: Only to be used during task completion (destroy). /// diff --git a/include/swift/ABI/TaskOptions.h b/include/swift/ABI/TaskOptions.h index 96cc3d88e6bc4..39775009bef4d 100644 --- a/include/swift/ABI/TaskOptions.h +++ b/include/swift/ABI/TaskOptions.h @@ -77,23 +77,58 @@ class TaskGroupTaskOptionRecord : public TaskOptionRecord { /// Task option to specify on what executor the task should be executed. /// -/// Not passing this option implies that an inferred (e.g. surrounding actor -/// when we inherit execution context) or the default executor should be used. +/// Not passing this option (or it's alternative "owned" version) implies that +/// an inferred (e.g. surrounding actor when we inherit execution context) +/// or the default executor should be used. /// /// Lack of this option usually means that the global concurrent executor, or /// the executor of the enclosing actor will be used. -class InitialTaskExecutorPreferenceTaskOptionRecord : public TaskOptionRecord { +class InitialTaskExecutorRefPreferenceTaskOptionRecord : public TaskOptionRecord { const TaskExecutorRef Executor; public: - InitialTaskExecutorPreferenceTaskOptionRecord(TaskExecutorRef executor) - : TaskOptionRecord(TaskOptionRecordKind::InitialTaskExecutor), + InitialTaskExecutorRefPreferenceTaskOptionRecord(TaskExecutorRef executor) + : TaskOptionRecord(TaskOptionRecordKind::InitialTaskExecutorUnowned), Executor(executor) {} TaskExecutorRef getExecutorRef() const { return Executor; } static bool classof(const TaskOptionRecord *record) { - return record->getKind() == TaskOptionRecordKind::InitialTaskExecutor; + return record->getKind() == TaskOptionRecordKind::InitialTaskExecutorUnowned; + } +}; + +/// This is quite similar to `InitialTaskExecutorRefPreferenceTaskOptionRecord` +/// however it takes a "raw" TaskExecutor existential in the form of an Identity +/// and WitnessTable - rather than the specific UnownedTaskExecutor which already +/// may have specific "flags" set on it. +/// +/// In order to use the executor in the runtime, we need to call into the type's +/// `asUnownedTaskExecutor` which is done by +/// `getExecutorRefFromUnownedTaskExecutor`. +class InitialTaskExecutorOwnedPreferenceTaskOptionRecord + : public TaskOptionRecord { + + // These look similar to TaskExecutorRef but are NOT the same! + // A TaskExecutorRef is obtained through calling user defined + // `asUnownedTaskExecutor` which is what we need to do on these to get a real executor ref. + HeapObject *Identity; + const TaskExecutorWitnessTable *WitnessTable; + +public: + InitialTaskExecutorOwnedPreferenceTaskOptionRecord( + HeapObject *executor, uintptr_t witnessTable) + : TaskOptionRecord(TaskOptionRecordKind::InitialTaskExecutorOwned), + Identity(executor) { + WitnessTable = reinterpret_cast(witnessTable); + } + + /// Invokes Swift implemented `asUnownedTaskExecutor` in order to obtain an + /// `TaskExecutorRef` which is properly populated with any flags it might need. + TaskExecutorRef getExecutorRefFromUnownedTaskExecutor() const; + + static bool classof(const TaskOptionRecord *record) { + return record->getKind() == TaskOptionRecordKind::InitialTaskExecutorOwned; } }; diff --git a/include/swift/ABI/TaskStatus.h b/include/swift/ABI/TaskStatus.h index 88702002189cf..5c3a38932baba 100644 --- a/include/swift/ABI/TaskStatus.h +++ b/include/swift/ABI/TaskStatus.h @@ -20,6 +20,7 @@ #ifndef SWIFT_ABI_TASKSTATUS_H #define SWIFT_ABI_TASKSTATUS_H +#include "swift/Basic/OptionSet.h" #include "swift/ABI/MetadataValues.h" #include "swift/ABI/Task.h" #include "swift/ABI/Executor.h" @@ -285,15 +286,35 @@ class EscalationNotificationStatusRecord : public TaskStatusRecord { /// innermost preference takes priority. class TaskExecutorPreferenceStatusRecord : public TaskStatusRecord { private: + enum class Flags : uint8_t { + /// The executor was retained during this task's creation, + /// and therefore must be released when this task completes. + /// + /// The only tasks which need to manually retain/release the task executor + /// are those which cannot structurally guarantee its lifetime. E.g. an async + /// let does not need to do so, because it structurally always will end + /// before/// we leave the scope in which it was defined -- and such scope + /// must have been keeping alive the executor. + HasRetainedExecutor = 1 << 0 + }; + OptionSet flags; const TaskExecutorRef Preferred; public: - TaskExecutorPreferenceStatusRecord(TaskExecutorRef executor) + TaskExecutorPreferenceStatusRecord(TaskExecutorRef executor, bool retainedExecutor) : TaskStatusRecord(TaskStatusRecordKind::TaskExecutorPreference), - Preferred(executor) {} + Preferred(executor) { + if (retainedExecutor) { + flags = Flags::HasRetainedExecutor; + } + } TaskExecutorRef getPreferredExecutor() { return Preferred; } + bool hasRetainedExecutor() const { + return flags.contains(Flags::HasRetainedExecutor); + } + static bool classof(const TaskStatusRecord *record) { return record->getKind() == TaskStatusRecordKind::TaskExecutorPreference; } diff --git a/include/swift/AST/ASTSynthesis.h b/include/swift/AST/ASTSynthesis.h index 6605cff3959cb..5ca157ff1de00 100644 --- a/include/swift/AST/ASTSynthesis.h +++ b/include/swift/AST/ASTSynthesis.h @@ -56,6 +56,7 @@ enum SingletonTypeSynthesizer { _serialExecutor, // the '_Concurrency.SerialExecutor' protocol _taskExecutor, // the '_Concurrency.TaskExecutor' protocol _actor, // the '_Concurrency.Actor' protocol + _distributedActor, // the 'Distributed.DistributedActor' protocol }; inline Type synthesizeType(SynthesisContext &SC, SingletonTypeSynthesizer kind) { @@ -77,11 +78,17 @@ inline Type synthesizeType(SynthesisContext &SC, return SC.Context.getProtocol(KnownProtocolKind::SerialExecutor) ->getDeclaredInterfaceType(); case _taskExecutor: - return SC.Context.getProtocol(KnownProtocolKind::TaskExecutor) - ->getDeclaredInterfaceType(); + if (auto ty = SC.Context.getProtocol(KnownProtocolKind::TaskExecutor)) { + return ty->getDeclaredInterfaceType(); + } else { + return nullptr; + } case _actor: return SC.Context.getProtocol(KnownProtocolKind::Actor) ->getDeclaredInterfaceType(); + case _distributedActor: + return SC.Context.getProtocol(KnownProtocolKind::DistributedActor) + ->getDeclaredInterfaceType(); case _copyable: return SC.Context.getProtocol(KnownProtocolKind::Copyable) ->getDeclaredInterfaceType(); @@ -171,6 +178,28 @@ Type synthesizeType(SynthesisContext &SC, return ExistentialType::get(synthesizeType(SC, M.Sub)); } +/// A synthesizer which generates an existential type from a requirement type. +template +struct BincompatIfTypeAvailableTypeSynthesizer { + bool condition; + S Sub; + FallbackS FallbackSub; +}; +template +constexpr BincompatIfTypeAvailableTypeSynthesizer _bincompatType( + bool bincompatCondition, S sub, FallbackS fallbackSub) { + return {bincompatCondition, sub, {fallbackSub}}; +} +template +Type synthesizeType(SynthesisContext &SC, + const BincompatIfTypeAvailableTypeSynthesizer &M) { + if (M.condition) { + return synthesizeType(SC, M.Sub); + } else { + return synthesizeType(SC, M.FallbackSub); + } +} + MetatypeRepresentation inline synthesizeMetatypeRepresentation(RepresentationSynthesizer rep) { switch (rep) { @@ -328,6 +357,10 @@ constexpr SpecifiedParamSynthesizer _owned(G sub) { return {ParamSpecifier::LegacyOwned, sub}; } template +constexpr SpecifiedParamSynthesizer _consuming(G sub) { + return {ParamSpecifier::Consuming, sub}; +} +template constexpr SpecifiedParamSynthesizer _inout(G sub) { return {ParamSpecifier::InOut, sub}; } diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 8522e73fd9b20..8c268fbb2c154 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -2705,6 +2705,10 @@ class DeclAttributes { return getUnavailable(ctx) != nullptr; } + bool isDeprecated(const ASTContext &ctx) const { + return getDeprecated(ctx) != nullptr; + } + /// Determine whether there is a swiftVersionSpecific attribute that's /// unavailable relative to the provided language version. bool diff --git a/include/swift/AST/Builtins.def b/include/swift/AST/Builtins.def index 6d4a8de8651e9..e654093a59e68 100644 --- a/include/swift/AST/Builtins.def +++ b/include/swift/AST/Builtins.def @@ -899,6 +899,25 @@ BUILTIN_MISC_OPERATION(StartAsyncLetWithLocalBuffer, "startAsyncLetWithLocalBuff /// This is only supported under the task-to-thread concurrency model. BUILTIN_MISC_OPERATION(TaskRunInline, "taskRunInline", "", Special) +/// flowSensitiveSelfIsolation(_ actor: T) -> (any Actor)? +/// +/// Used only in actor initializers, this builtin lowers to either 'actor' +/// (wrapped in an optional) or 'nil' depending on whether 'self' has been +/// initialized at this point. 'actor' is always an alias for the 'self' +/// being initialized. +BUILTIN_MISC_OPERATION(FlowSensitiveSelfIsolation, "flowSensitiveSelfIsolation", "", Special) + +/// flowSensitiveDistributedSelfIsolation( +/// _ actor: T +/// ) -> (any Actor)? +/// +/// Used only in distributed actor initializers, this builtin lowers to either +/// 'actor.asLocalActor' or 'nil' depending on whether 'self' has been +/// initialized at this point. 'actor' is always an alias for the 'self' +/// being initialized. +BUILTIN_MISC_OPERATION(FlowSensitiveDistributedSelfIsolation, + "flowSensitiveDistributedSelfIsolation", "", Special) + /// endAsyncLet(): (Builtin.RawPointer) -> Void /// /// DEPRECATED. The swift_asyncLet_finish intrinsic and endAsyncLetLifetime diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 2cf21b7d82ddc..123f8362e1dfd 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2301,32 +2301,32 @@ ERROR(pattern_type_not_usable_from_inline,none, "type referenced from a '@usableFromInline' " "%select{%select{variable|constant}0|property}1 " "must be '@usableFromInline' or public", - (bool, bool, /*ignored*/bool)) + (bool, bool)) WARNING(pattern_type_not_usable_from_inline_warn,none, "type referenced from a '@usableFromInline' " "%select{%select{variable|constant}0|property}1 " "should be '@usableFromInline' or public", - (bool, bool, /*ignored*/bool)) + (bool, bool)) ERROR(pattern_type_not_usable_from_inline_frozen,none, - "type referenced from a stored property in a '@frozen%select{| package}2' struct must " - "be '@usableFromInline'%select{ or public|, public, or package}2", - (/*ignored*/bool, /*ignored*/bool, bool)) + "type referenced from a stored property in a '@frozen' struct must " + "be '@usableFromInline' or public", + (/*ignored*/bool, /*ignored*/bool)) ERROR(pattern_type_not_usable_from_inline_inferred,none, "type referenced from a '@usableFromInline' " "%select{%select{variable|constant}0|property}1 " "with inferred type %2 " "must be '@usableFromInline' or public", - (bool, bool, Type, /*ignored*/bool)) + (bool, bool, Type)) WARNING(pattern_type_not_usable_from_inline_inferred_warn,none, "type referenced from a '@usableFromInline' " "%select{%select{variable|constant}0|property}1 " "with inferred type %2 " "should be '@usableFromInline' or public", - (bool, bool, Type, /*ignored*/bool)) + (bool, bool, Type)) ERROR(pattern_type_not_usable_from_inline_inferred_frozen,none, "type referenced from a stored property with inferred type %2 in a " - "'@frozen%select{| package}3' struct must be '@usableFromInline'%select{ or public|, public, or package}3", - (/*ignored*/bool, /*ignored*/bool, Type, bool)) + "'@frozen' struct must be '@usableFromInline' or public", + (/*ignored*/bool, /*ignored*/bool, Type)) ERROR(pattern_binds_no_variables,none, "%select{property|global variable}0 declaration does not bind any " @@ -3137,6 +3137,11 @@ ERROR(witness_unavailable,none, "unavailable %kind0 was used to satisfy a requirement of protocol %1%select{|: %2}2", (const ValueDecl *, Identifier, StringRef)) +WARNING(witness_deprecated,none, + "deprecated default implementation is used to satisfy %kind0 required by " + "protocol %1%select{|: %2}2", + (const ValueDecl *, Identifier, StringRef)) + ERROR(redundant_conformance,none, "redundant conformance of %0 to protocol %1", (Type, Identifier)) ERROR(redundant_conformance_conditional,none, @@ -3644,48 +3649,43 @@ ERROR(decl_from_hidden_module,none, "as result builder here|" "in an extension with public or '@usableFromInline' members|" "in an extension with conditional conformances|" - "in an extension with public, package, or '@usableFromInline' members|" - "in an extension with conditional conformances}1; " + "in a public or '@usableFromInline' conformance}1; " "%select{%2 has been imported as implementation-only|" "it is an SPI imported from %2|" "it is SPI|" "%2 was imported for SPI only|" "%2 was not imported by this file|" "C++ types from imported module %2 do not support library evolution|" - "%2 was not imported publicly|" - "%2 was imported as package}3" - "%select{||||| or as package| or as package}1", + "%2 was not imported publicly}3", (const Decl *, unsigned, Identifier, unsigned)) ERROR(typealias_desugars_to_type_from_hidden_module,none, "%0 aliases '%1.%2' and cannot be used %select{here|" "as property wrapper here|" "as result builder here|" "in an extension with public or '@usableFromInline' members|" - "in an extension with conditional conformances|" - "in an extension with public, package, or '@usableFromInline' members|" - "in an extension with conditional conformances}3 " + "in an extension with conditional conformance|" + "in a public or '@usableFromInline' conformance}3 " "because %select{%4 has been imported as implementation-only|" "it is an SPI imported from %4|" "<>|" "%4 was imported for SPI only|" "%4 was not imported by this file|" "C++ types from imported module %4 do not support library evolution|" - "%4 was not imported publicly|" - "%4 was imported as package}5", + "%4 was not imported publicly}5", (const TypeAliasDecl *, StringRef, StringRef, unsigned, Identifier, unsigned)) ERROR(conformance_from_implementation_only_module,none, "cannot use conformance of %0 to %1 %select{here|as property wrapper here|" "as result builder here|" "in an extension with public or '@usableFromInline' members|" - "in an extension with conditional conformances}2; " + "in an extension with conditional conformances|" + "<>}2; " "%select{%3 has been imported as implementation-only|" "the conformance is declared as SPI in %3|" "the conformance is declared as SPI|" "%3 was imported for SPI only|" "%3 was not imported by this file|" "C++ types from imported module %3 do not support library evolution|" - "%3 was not imported publicly|" - "%3 was imported as package}4", + "%3 was not imported publicly}4", (Type, Identifier, unsigned, Identifier, unsigned)) NOTE(assoc_conformance_from_implementation_only_module,none, "in associated type %0 (inferred as %1)", (Type, Type)) @@ -4015,6 +4015,9 @@ ERROR(autoclosure_function_input_nonunit,none, ERROR(escaping_non_function_parameter,none, "@escaping attribute may only be used in function parameter position", ()) +ERROR(escaping_inout_parameter,none, + "inout expression is implicitly escaping", ()) + ERROR(escaping_optional_type_argument, none, "closure is already escaping in optional type argument", ()) @@ -5763,8 +5766,12 @@ ERROR(any_not_existential,none, "'any' has no effect on %select{concrete type|type parameter}0 %1", (bool, Type)) ERROR(incorrect_optional_any,none, - "optional 'any' type must be written %0", - (Type)) + "using '!' is not allowed here; perhaps '?' was intended", + ()) + +ERROR(incorrect_iuo_any,none, + "force unwrapped 'any' type must be written (%0)!", + (StringRef)) ERROR(existential_requires_any,none, "use of %select{protocol |}2%0 as a type must be written %1", (Type, Type, bool)) @@ -6920,8 +6927,7 @@ ERROR(inlinable_decl_ref_from_hidden_module, "%2 was imported for SPI only|" "%2 was not imported by this file|" "C++ APIs from imported module %2 do not support library evolution|" - "%2 was not imported publicly|" - "%2 was imported as package}3", + "%2 was not imported publicly}3", (const ValueDecl *, unsigned, Identifier, unsigned)) WARNING(inlinable_decl_ref_from_hidden_module_warn, @@ -6939,8 +6945,7 @@ ERROR(inlinable_typealias_desugars_to_type_from_hidden_module, "%4 was imported for SPI only|" "%4 was not imported by this file|" "C++ types from imported module %4 do not support library evolution|" - "%4 was not imported publicly|" - "%4 was imported as package}5", + "%4 was not imported publicly}5", (const TypeAliasDecl *, StringRef, StringRef, unsigned, Identifier, unsigned)) NOTE(missing_import_inserted, @@ -6954,8 +6959,8 @@ ERROR(availability_macro_in_inlinable, none, #undef FRAGILE_FUNC_KIND NOTE(resilience_decl_declared_here, - none, "%kind0 is not '@usableFromInline'%select{ or public|, public, or package}1", - (const ValueDecl *, bool)) + none, "%kind0 is not '@usableFromInline' or public", + (const ValueDecl *)) ERROR(class_designated_init_inlinable_resilient,none, "initializer for class %0 is " @@ -7730,8 +7735,8 @@ ERROR(inverse_conflicts_explicit_composition, none, "composition cannot contain '~%0' when another member requires '%0'", (StringRef)) ERROR(inverse_extension, none, - "cannot suppress %0 in extension", - (Type)) + "cannot suppress '%0' in extension", + (StringRef)) ERROR(copyable_illegal_deinit, none, "deinitializer cannot be declared in %kind0 that conforms to 'Copyable'", (const ValueDecl *)) @@ -7801,6 +7806,9 @@ ERROR(suppress_nonsuppressable_protocol,none, "conformance to %0 cannot be suppressed", (const ProtocolDecl *)) WARNING(suppress_already_suppressed_protocol,none, "already suppressed conformance to %0", (const ProtocolDecl *)) +ERROR(extension_conforms_to_invertible_and_others, none, + "conformance to '%0' must be declared in a separate extension", + (StringRef)) // -- older ones below -- ERROR(noncopyable_parameter_requires_ownership, none, @@ -7973,6 +7981,8 @@ ERROR(lifetime_dependence_cannot_infer_ambiguous_candidate, none, "cannot infer lifetime dependence on a self which is BitwiseCopyable & " "Escapable", ()) +ERROR(lifetime_dependence_immortal_conflict_name, none, + "conflict between the parameter name and immortal keyword", ()) //===----------------------------------------------------------------------===// // MARK: Transferring @@ -7991,6 +8001,19 @@ ERROR(sending_only_on_parameters_and_results, none, "'sending' may only be used on parameters and results", ()) ERROR(sending_cannot_be_applied_to_tuple_elt, none, "'sending' cannot be applied to tuple elements", ()) +ERROR(sending_function_wrong_sending,none, + "converting a value of type %0 to type %1 risks causing data races", + (Type, Type)) +NOTE(sending_function_param_with_sending_param_note, none, + "converting a function typed value with a sending parameter to one " + "without risks allowing actor-isolated values to escape their isolation " + "domain as an argument to an invocation of value", + ()) +NOTE(sending_function_result_with_sending_param_note, none, + "converting a function typed value without a sending result as one with " + "risks allowing actor-isolated values to escape their " + "isolation domain through a result of an invocation of value", + ()) #define UNDEFINE_DIAGNOSTIC_MACROS #include "DefineDiagnosticMacros.h" diff --git a/include/swift/AST/FeatureAvailability.def b/include/swift/AST/FeatureAvailability.def index 4c9ccddb20105..b56e651f8abbe 100644 --- a/include/swift/AST/FeatureAvailability.def +++ b/include/swift/AST/FeatureAvailability.def @@ -64,12 +64,12 @@ FEATURE(ConcurrencyDiscardingTaskGroup, (5, 9)) FEATURE(ConcurrencyDistributedActorWithCustomExecutor, (5, 9)) FEATURE(SignedDescriptor, (5, 9)) -FEATURE(ObjCSymbolicReferences, (5, 11)) -FEATURE(TypedThrows, (5, 11)) -FEATURE(StaticReadOnlyArrays, (5, 11)) -FEATURE(SwiftExceptionPersonality, (5, 11)) +FEATURE(ObjCSymbolicReferences, (6, 0)) +FEATURE(TypedThrows, (6, 0)) +FEATURE(StaticReadOnlyArrays, (6, 0)) +FEATURE(SwiftExceptionPersonality, (6, 0)) // Metadata support for @isolated(any) function types -FEATURE(IsolatedAny, (5, 11)) +FEATURE(IsolatedAny, (6, 0)) FEATURE(TaskExecutor, FUTURE) FEATURE(Differentiation, FUTURE) diff --git a/include/swift/AST/LifetimeDependence.h b/include/swift/AST/LifetimeDependence.h index a4e12b8f61914..259b80c9ea527 100644 --- a/include/swift/AST/LifetimeDependence.h +++ b/include/swift/AST/LifetimeDependence.h @@ -43,7 +43,7 @@ enum class LifetimeDependenceKind : uint8_t { Inherit = 0, Scope }; class LifetimeDependenceSpecifier { public: - enum class SpecifierKind { Named, Ordered, Self }; + enum class SpecifierKind { Named, Ordered, Self, Immortal }; private: SourceLoc loc; @@ -76,6 +76,11 @@ class LifetimeDependenceSpecifier { return {loc, SpecifierKind::Named, kind, name}; } + static LifetimeDependenceSpecifier + getImmortalLifetimeDependenceSpecifier(SourceLoc loc) { + return {loc, SpecifierKind::Immortal, {}, {}}; + } + static LifetimeDependenceSpecifier getOrderedLifetimeDependenceSpecifier( SourceLoc loc, ParsedLifetimeDependenceKind kind, unsigned index) { return {loc, SpecifierKind::Ordered, kind, index}; @@ -113,6 +118,8 @@ class LifetimeDependenceSpecifier { return "self"; case SpecifierKind::Ordered: return std::to_string(value.Ordered.index); + case SpecifierKind::Immortal: + return "immortal"; } llvm_unreachable("Invalid LifetimeDependenceSpecifier::SpecifierKind"); } @@ -134,6 +141,7 @@ class LifetimeDependenceSpecifier { class LifetimeDependenceInfo { IndexSubset *inheritLifetimeParamIndices; IndexSubset *scopeLifetimeParamIndices; + bool immortal; static LifetimeDependenceInfo getForParamIndex(AbstractFunctionDecl *afd, unsigned index, @@ -149,12 +157,15 @@ class LifetimeDependenceInfo { public: LifetimeDependenceInfo() : inheritLifetimeParamIndices(nullptr), - scopeLifetimeParamIndices(nullptr) {} + scopeLifetimeParamIndices(nullptr), immortal(false) {} LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices, - IndexSubset *scopeLifetimeParamIndices) + IndexSubset *scopeLifetimeParamIndices, + bool isImmortal) : inheritLifetimeParamIndices(inheritLifetimeParamIndices), - scopeLifetimeParamIndices(scopeLifetimeParamIndices) { - assert(!empty()); + scopeLifetimeParamIndices(scopeLifetimeParamIndices), + immortal(isImmortal) { + assert(isImmortal || inheritLifetimeParamIndices || + scopeLifetimeParamIndices); assert(!inheritLifetimeParamIndices || !inheritLifetimeParamIndices->isEmpty()); assert(!scopeLifetimeParamIndices || !scopeLifetimeParamIndices->isEmpty()); @@ -163,10 +174,12 @@ class LifetimeDependenceInfo { operator bool() const { return !empty(); } bool empty() const { - return inheritLifetimeParamIndices == nullptr && + return !immortal && inheritLifetimeParamIndices == nullptr && scopeLifetimeParamIndices == nullptr; } + bool isImmortal() const { return immortal; } + bool hasInheritLifetimeParamIndices() const { return inheritLifetimeParamIndices != nullptr; } diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index de5819d870918..42f4a27b669a3 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -39,6 +39,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" #include +#include #include namespace clang { @@ -537,6 +538,11 @@ class ModuleDecl std::optional> declaringModuleAndBystander; + /// A cache of this module's visible Clang modules + /// parameterized by the Swift interface print mode. + using VisibleClangModuleSet = llvm::DenseMap; + std::unordered_map CachedVisibleClangModuleSet; + /// If this module is an underscored cross import overlay, gets the underlying /// module that declared it (which may itself be a cross-import overlay), /// along with the name of the required bystander module. Used by tooling to @@ -578,6 +584,14 @@ class ModuleDecl bool getRequiredBystandersIfCrossImportOverlay( ModuleDecl *declaring, SmallVectorImpl &bystanderNames); + /// Computes all Clang modules that are visible from this moule. + /// This includes any modules that are imported transitively through public + /// (`@_exported`) imports. + /// + /// The computed map associates each visible Clang module with the + /// corresponding Swift module. + const VisibleClangModuleSet & + getVisibleClangModules(PrintOptions::InterfaceMode contentMode); /// Walks and loads the declared, underscored cross-import overlays of this /// module and its underlying clang module, transitively, to find all cross diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h index 4437bd1bb7514..e415b08ead62d 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -681,7 +681,12 @@ class NormalProtocolConformance : public RootProtocolConformance, assert(sourceKind != ConformanceEntryKind::PreMacroExpansion && "cannot create conformance pre-macro-expansion"); Bits.NormalProtocolConformance.SourceKind = unsigned(sourceKind); - ImplyingConformance = implyingConformance; + if (auto implying = implyingConformance) { + ImplyingConformance = implying; + PreconcurrencyLoc = implying->getPreconcurrencyLoc(); + Bits.NormalProtocolConformance.IsPreconcurrency = + implying->isPreconcurrency(); + } } /// Determine whether this conformance is lazily loaded. diff --git a/include/swift/AST/RequirementMatch.h b/include/swift/AST/RequirementMatch.h index 128fd746511b4..b1443f29e571c 100644 --- a/include/swift/AST/RequirementMatch.h +++ b/include/swift/AST/RequirementMatch.h @@ -239,6 +239,10 @@ enum class CheckKind : unsigned { /// The witness itself is inaccessible. WitnessUnavailable, + + /// The witness is a deprecated default implementation provided by the + /// protocol. + DefaultWitnessDeprecated, }; /// Describes the suitability of the chosen witness for /// the requirement. @@ -464,4 +468,4 @@ struct RequirementMatch { } -#endif // SWIFT_AST_REQUIREMENTMATCH_H \ No newline at end of file +#endif // SWIFT_AST_REQUIREMENTMATCH_H diff --git a/include/swift/AST/RuntimeVersions.def b/include/swift/AST/RuntimeVersions.def index 2aa07fee075e3..37e8e59ffc61c 100644 --- a/include/swift/AST/RuntimeVersions.def +++ b/include/swift/AST/RuntimeVersions.def @@ -138,12 +138,24 @@ RUNTIME_VERSION( PLATFORM(xrOS, (1, 0, 0)) ) +END_MAJOR_VERSION(5) + +MAJOR_VERSION(6) + RUNTIME_VERSION( - (5, 11), + (6, 0), + PLATFORM(macOS, (15, 0, 0)) + PLATFORM(iOS, (18, 0, 0)) + PLATFORM(watchOS, (11, 0, 0)) + PLATFORM(xrOS, (2, 0, 0)) +) + +RUNTIME_VERSION( + (6, 1), FUTURE ) -END_MAJOR_VERSION(5) +END_MAJOR_VERSION(6) // .......................................................................... // diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index c4574f5152bd9..282565053774e 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -435,10 +435,6 @@ class SourceFile final : public FileUnit { void setImportUsedPreconcurrency( AttributedImport import); - /// True if the highest access level of the declarations referencing - /// this import in signature or inlinable code is internal or less. - bool isMaxAccessLevelUsingImportInternal(AttributedImport import) const; - /// Return the highest access level of the declarations referencing /// this import in signature or inlinable code. AccessLevel diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h index 9f3fdb6b68400..0ed93d4078ad9 100644 --- a/include/swift/AST/Stmt.h +++ b/include/swift/AST/Stmt.h @@ -1305,7 +1305,9 @@ class CaseStmt final SourceLoc getStartLoc() const { if (UnknownAttrLoc.isValid()) return UnknownAttrLoc; - return getLoc(); + if (ItemIntroducerLoc.isValid()) + return ItemIntroducerLoc; + return getBody()->getStartLoc(); } SourceLoc getEndLoc() const { return getBody()->getEndLoc(); } diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 055003687c791..c67e60e475d1d 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -3232,6 +3232,9 @@ class AnyFunctionType : public TypeBase { /// Whether the parameter is 'isolated'. bool isIsolated() const { return Flags.isIsolated(); } + /// Whether or not the parameter is 'sending'. + bool isSending() const { return Flags.isSending(); } + /// Whether the parameter is 'isCompileTimeConst'. bool isCompileTimeConst() const { return Flags.isCompileTimeConst(); } diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index 9535de9ab727d..60a51092bf8d5 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -198,6 +198,7 @@ SUPPRESSIBLE_LANGUAGE_FEATURE(BitwiseCopyable2, 426, "BitwiseCopyable feature") LANGUAGE_FEATURE(BodyMacros, 415, "Function body macros") LANGUAGE_FEATURE(TransferringArgsAndResults, 430, "Transferring args and results") SUPPRESSIBLE_LANGUAGE_FEATURE(SendingArgsAndResults, 430, "Sending arg and results") +LANGUAGE_FEATURE(BorrowingSwitch, 432, "Noncopyable type pattern matching") // Swift 6 UPCOMING_FEATURE(ConciseMagicFile, 274, 6) @@ -215,7 +216,6 @@ UPCOMING_FEATURE(RegionBasedIsolation, 414, 6) UPCOMING_FEATURE(DynamicActorIsolation, 423, 6) UPCOMING_FEATURE(NonfrozenEnumExhaustivity, 192, 6) UPCOMING_FEATURE(GlobalActorIsolatedTypesUsability, 0434, 6) -UPCOMING_FEATURE(BorrowingSwitch, 432, 6) // Swift 7 UPCOMING_FEATURE(ExistentialAny, 335, 7) @@ -227,7 +227,7 @@ EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false) EXPERIMENTAL_FEATURE(CodeItemMacros, false) EXPERIMENTAL_FEATURE(PreambleMacros, false) EXPERIMENTAL_FEATURE(TupleConformances, false) -EXPERIMENTAL_FEATURE(FullTypedThrows, true) +EXPERIMENTAL_FEATURE(FullTypedThrows, false) // Whether to enable @_used and @_section attributes EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true) diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h index 83f68ed05c1f7..3472cb4eff63b 100644 --- a/include/swift/ClangImporter/ClangImporter.h +++ b/include/swift/ClangImporter/ClangImporter.h @@ -678,6 +678,12 @@ getCxxReferencePointeeTypeOrNone(const clang::Type *type); /// Returns true if the given type is a C++ `const` reference type. bool isCxxConstReferenceType(const clang::Type *type); +/// Determine whether this typedef is a CF type. +bool isCFTypeDecl(const clang::TypedefNameDecl *Decl); + +/// Determine the imported CF type for the given typedef-name, or the empty +/// string if this is not an imported CF type name. +llvm::StringRef getCFTypeName(const clang::TypedefNameDecl *decl); } // namespace importer struct ClangInvocationFileMapping { diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def index c16d5d583024b..ea69bf07aea4c 100644 --- a/include/swift/Demangling/DemangleNodes.def +++ b/include/swift/Demangling/DemangleNodes.def @@ -164,6 +164,7 @@ NODE(LazyProtocolWitnessTableAccessor) NODE(LazyProtocolWitnessTableCacheVariable) NODE(LocalDeclName) NODE(Macro) +NODE(MacroExpansionLoc) NODE(MacroExpansionUniqueName) CONTEXT_NODE(MaterializeForSet) NODE(MemberAttachedMacroExpansion) diff --git a/include/swift/IDE/IDEBridging.h b/include/swift/IDE/IDEBridging.h index 379783f82ec82..dbbed37e48cbb 100644 --- a/include/swift/IDE/IDEBridging.h +++ b/include/swift/IDE/IDEBridging.h @@ -38,6 +38,13 @@ enum class LabelRangeType { /// `func foo([a b]: Int)` Param, + /// The parameter of an enum case declaration + /// + /// ### Examples + /// - `case myCase([a]: Int)` + /// - `case myCase([]Int)` + EnumCaseParam, + /// Parameters of a function that can't be collapsed if they are the same. /// /// This is the case for parameters of subscripts since subscripts have diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h index 3ca9b5de3b796..eb697d0615e1e 100644 --- a/include/swift/IDE/Utils.h +++ b/include/swift/IDE/Utils.h @@ -465,15 +465,34 @@ enum class RegionType { }; enum class RefactoringRangeKind { - BaseName, // func [foo](a b: Int) - KeywordBaseName, // [init](a: Int) - ParameterName, // func foo(a[ b]: Int) - NoncollapsibleParameterName, // subscript(a[ a]: Int) - DeclArgumentLabel, // func foo([a] b: Int) - CallArgumentLabel, // foo([a]: 1) - CallArgumentColon, // foo(a[: ]1) - CallArgumentCombined, // foo([]1) could expand to foo([a: ]1) - SelectorArgumentLabel, // foo([a]:) + /// `func [foo](a b: Int)` + BaseName, + + /// `[init](a: Int)` + KeywordBaseName, + + /// `func foo(a[ b]: Int)` + ParameterName, + + /// `subscript(a[ a]: Int)` + NoncollapsibleParameterName, + + /// `func foo([a] b: Int)` + DeclArgumentLabel, + + /// `foo([a]: 1)` + CallArgumentLabel, + + /// `foo(a[: ]1)` + CallArgumentColon, + + /// `foo([]1) could expand to foo([a: ]1)` + /// Also used for enum case declarations without a label, eg. + /// `case foo([]String)` should expand to `case foo([a: ]String)`. + CallArgumentCombined, + + /// `foo([a]:)` + SelectorArgumentLabel, }; struct NoteRegion { diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 1cbcc3e8a4341..2dc7e18b04240 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -207,9 +207,6 @@ def no_serialize_debugging_options : def autolink_library : Separate<["-"], "autolink-library">, HelpText<"Add dependent library">, Flags<[FrontendOption]>; -def public_autolink_library : Separate<["-"], "public-autolink-library">, - HelpText<"Add public dependent library">, Flags<[FrontendOption]>; - def disable_typo_correction : Flag<["-"], "disable-typo-correction">, HelpText<"Disable typo correction">; @@ -369,6 +366,10 @@ def enable_resilience : Flag<["-"], "enable-resilience">, def enable_experimental_async_top_level : Flag<["-"], "enable-experimental-async-top-level">, HelpText<"Enable experimental concurrency in top-level code">; + +def public_autolink_library : + Separate<["-"], "public-autolink-library">, + HelpText<"Add public dependent library">; } // HIDDEN FLAGS diff --git a/include/swift/SIL/MemAccessUtils.h b/include/swift/SIL/MemAccessUtils.h index 5230960314e85..62564ae220b0c 100644 --- a/include/swift/SIL/MemAccessUtils.h +++ b/include/swift/SIL/MemAccessUtils.h @@ -887,10 +887,10 @@ namespace swift { /// For convenience, encapsulate and AccessStorage value along with its /// accessed base address. struct AccessStorageWithBase { - /// Identical to AccessStorage::compute but preserves the access base. + /// Identical to AccessStorage::computeInScope but walks through begin_access. static AccessStorageWithBase compute(SILValue sourceAddress); - /// Identical to AccessStorage::computeInScope but preserves the base. + /// Identical to AccessStorage::compute but stops at begin_access static AccessStorageWithBase computeInScope(SILValue sourceAddress); AccessStorage storage; diff --git a/include/swift/SIL/OSSALifetimeCompletion.h b/include/swift/SIL/OSSALifetimeCompletion.h index ba8d9e05c830c..3365c8e44f746 100644 --- a/include/swift/SIL/OSSALifetimeCompletion.h +++ b/include/swift/SIL/OSSALifetimeCompletion.h @@ -57,11 +57,6 @@ class OSSALifetimeCompletion { // Availability: "As late as possible." Consume the value in the last blocks // beyond the non-consuming uses in which the value has been // consumed on no incoming paths. - // AvailabilityWithLeaks: "As late as possible or later." Consume the value - // in the last blocks beyond the non-consuming uses in - // which the value has been consumed on no incoming - // paths, unless that block's terminator isn't an - // unreachable, in which case, don't consume it there. // // This boundary works around bugs where SILGen emits // illegal OSSA lifetimes. @@ -69,7 +64,6 @@ class OSSALifetimeCompletion { enum Value : uint8_t { Liveness, Availability, - AvailabilityWithLeaks, }; Value value; @@ -115,11 +109,6 @@ class OSSALifetimeCompletion { : LifetimeCompletion::AlreadyComplete; } - enum AllowLeaks_t : bool { - AllowLeaks = true, - DoNotAllowLeaks = false, - }; - enum class LifetimeEnd : uint8_t { /// The lifetime ends at the boundary. Boundary, @@ -128,8 +117,7 @@ class OSSALifetimeCompletion { }; static void visitAvailabilityBoundary( - SILValue value, AllowLeaks_t allowLeaks, - const SSAPrunedLiveness &liveness, + SILValue value, const SSAPrunedLiveness &liveness, llvm::function_ref visit); protected: @@ -187,9 +175,6 @@ operator<<(llvm::raw_ostream &OS, OSSALifetimeCompletion::Boundary boundary) { case OSSALifetimeCompletion::Boundary::Availability: OS << "availability"; break; - case OSSALifetimeCompletion::Boundary::AvailabilityWithLeaks: - OS << "availability_with_leaks"; - break; } return OS; } diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 3338b82a322de..2107073c790ec 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -87,6 +87,10 @@ class SILCloner : protected SILInstructionVisitor { /// blocks. llvm::DenseMap BBMap; + /// Blocks, where edge-spitting may have "converted" terminator result + /// arguments to phi-arguments. + llvm::SmallVector blocksWithNewPhiArgs; + private: /// MARK: Private state hidden from CRTP extensions. @@ -872,9 +876,15 @@ void SILCloner::visitBlocksDepthFirst(SILBasicBlock *startBB) { && isa(BB->getTerminator())) { continue; } + TermInst *term = BB->getTerminator(); + + // After edge-spitting, terminator result arguments become phi arguments. + if (!isa(term)) + blocksWithNewPhiArgs.push_back(BB->getSuccessors()[succIdx]); + // This predecessor has multiple successors, so cloning it without // cloning its successors would create a critical edge. - splitEdge(BB->getTerminator(), succIdx, DomTree); + splitEdge(term, succIdx, DomTree); assert(!BBMap.count(BB->getSuccessors()[succIdx])); } // Map the successor to a new BB. Layout the cloned blocks in the order diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 155505220c783..76d7cc8344f7d 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -28,6 +28,8 @@ #include "swift/SIL/SILDeclRef.h" #include "swift/SIL/SILLinkage.h" #include "swift/SIL/SILPrintContext.h" +#include "swift/SIL/SILUndef.h" +#include "llvm/ADT/MapVector.h" namespace swift { @@ -337,12 +339,8 @@ class SILFunction PerformanceConstraints perfConstraints = PerformanceConstraints::None; - /// This is the set of undef values we've created, for uniquing purposes. - /// - /// We use a SmallDenseMap since in most functions, we will have only one type - /// of undef if we have any at all. In that case, by staying small we avoid - /// needing a heap allocation. - llvm::SmallDenseMap undefValues; + /// The undefs of each type in the function. + llvm::SmallMapVector undefValues; /// This is the number of uses of this SILFunction inside the SIL. /// It does not include references from debug scopes. @@ -1637,6 +1635,10 @@ class SILFunction decl->getLifetimeAnnotation()); } + ArrayRef> getUndefValues() { + return {undefValues.begin(), undefValues.end()}; + } + /// verify - Run the SIL verifier to make sure that the SILFunction follows /// invariants. void verify(CalleeCache *calleeCache = nullptr, diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 4d382b579de2d..e36b07f375a57 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -2678,6 +2678,8 @@ class ApplyInstBase : public Base { SpecializationInfo(specializationInfo), NumCallArguments(args.size()), NumTypeDependentOperands(typeDependentOperands.size()), Substitutions(subs) { + assert(!!subs == !!callee->getType().castTo() + ->getInvocationGenericSignature()); // Initialize the operands. auto allOperands = getAllOperands(); @@ -9160,7 +9162,7 @@ class MoveOnlyWrapperToCopyableBoxInst ValueOwnershipKind forwardingOwnershipKind) : UnaryInstructionBase( DebugLoc, operand, - operand->getType().removingMoveOnlyWrapperToBoxedType( + operand->getType().removingMoveOnlyWrapperFromBoxedType( operand->getFunction()), forwardingOwnershipKind) { assert( diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index a9f730b2bd3b3..f1af54aa97d91 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -366,6 +366,9 @@ class SILType { /// address-only. This is the opposite of isLoadable. bool isAddressOnly(const SILFunction &F) const; + /// For details see the comment of `IsFixedABI_t`. + bool isFixedABI(const SILFunction &F) const; + /// True if the underlying AST type is trivial, meaning it is loadable and can /// be trivially copied, moved or destroyed. Returns false for address types /// even though they are technically trivial. @@ -868,7 +871,15 @@ class SILType { /// /// DISCUSSION: This is separate from removingMoveOnlyWrapper since this API /// requires a SILFunction * and is specialized. - SILType removingMoveOnlyWrapperToBoxedType(const SILFunction *fn); + SILType removingMoveOnlyWrapperFromBoxedType(const SILFunction *fn); + + /// Whether there's a direct wrapper or a wrapper inside a box. + bool hasAnyMoveOnlyWrapping(const SILFunction *fn) { + return isMoveOnlyWrapped() || isBoxedMoveOnlyWrappedType(fn); + } + + /// Removes a direct wrapper from a type or a wrapper from a type in a box. + SILType removingAnyMoveOnlyWrapping(const SILFunction *fn); /// Returns a SILType with any archetypes mapped out of context. SILType mapTypeOutOfContext() const; diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h index 20dc42c382149..5dbb3c30e86f0 100644 --- a/include/swift/SIL/SILValue.h +++ b/include/swift/SIL/SILValue.h @@ -599,14 +599,9 @@ class ValueBase : public SILNode, public SILAllocated { /// NOTE: Please do not use this directly! It is only meant to be used by the /// optimizer pass: SILMoveOnlyWrappedTypeEliminator. bool unsafelyEliminateMoveOnlyWrapper(const SILFunction *fn) { - if (!Type.isMoveOnlyWrapped() && !Type.isBoxedMoveOnlyWrappedType(fn)) + if (!Type.hasAnyMoveOnlyWrapping(fn)) return false; - if (Type.isMoveOnlyWrapped()) { - Type = Type.removingMoveOnlyWrapper(); - } else { - assert(Type.isBoxedMoveOnlyWrappedType(fn)); - Type = Type.removingMoveOnlyWrapperToBoxedType(fn); - } + Type = Type.removingAnyMoveOnlyWrapping(fn); return true; } diff --git a/include/swift/SILOptimizer/Utils/PartitionUtils.h b/include/swift/SILOptimizer/Utils/PartitionUtils.h index 99ee99860416d..e1e2a1aed57ea 100644 --- a/include/swift/SILOptimizer/Utils/PartitionUtils.h +++ b/include/swift/SILOptimizer/Utils/PartitionUtils.h @@ -1025,14 +1025,6 @@ struct PartitionOpEvaluator { "Assign PartitionOp should be passed 2 arguments"); assert(p.isTrackingElement(op.getOpArgs()[1]) && "Assign PartitionOp's source argument should be already tracked"); - // If we are using a region that was transferred as our assignment source - // value... emit an error. - if (auto *transferredOperandSet = p.getTransferred(op.getOpArgs()[1])) { - for (auto transferredOperand : transferredOperandSet->data()) { - handleLocalUseAfterTransferHelper(op, op.getOpArgs()[1], - transferredOperand); - } - } p.assignElement(op.getOpArgs()[0], op.getOpArgs()[1]); return; case PartitionOpKind::AssignFresh: @@ -1122,20 +1114,6 @@ struct PartitionOpEvaluator { p.isTrackingElement(op.getOpArgs()[1]) && "Merge PartitionOp's arguments should already be tracked"); - // if attempting to merge a transferred region, handle the failure - if (auto *transferredOperandSet = p.getTransferred(op.getOpArgs()[0])) { - for (auto transferredOperand : transferredOperandSet->data()) { - handleLocalUseAfterTransferHelper(op, op.getOpArgs()[0], - transferredOperand); - } - } - if (auto *transferredOperandSet = p.getTransferred(op.getOpArgs()[1])) { - for (auto transferredOperand : transferredOperandSet->data()) { - handleLocalUseAfterTransferHelper(op, op.getOpArgs()[1], - transferredOperand); - } - } - p.merge(op.getOpArgs()[0], op.getOpArgs()[1]); return; case PartitionOpKind::Require: diff --git a/include/swift/Sema/CSFix.h b/include/swift/Sema/CSFix.h index bf418b6a2d21d..d38cfbb499482 100644 --- a/include/swift/Sema/CSFix.h +++ b/include/swift/Sema/CSFix.h @@ -471,6 +471,17 @@ enum class FixKind : uint8_t { /// Ignore situations when key path subscript index gets passed an invalid /// type as an argument (something that is not a key path). IgnoreKeyPathSubscriptIndexMismatch, + + /// Ignore the following situations: + /// + /// 1. Where we have a function that expects a function typed parameter + /// without a sendable parameter but is passed a function type with a sending + /// parameter. + /// + /// 2. Where we have a function that expects a function typed parameter with a + /// sending result, but is passed a function typeed parameter without a + /// sending result. + AllowSendingMismatch, }; class ConstraintFix { @@ -2619,6 +2630,49 @@ class TreatEphemeralAsNonEphemeral final : public AllowArgumentMismatch { } }; +/// Error if a user passes let f: (sending T) -> () as a (T) -> (). +/// +/// This prevents data races since f assumes its parameter if the parameter is +/// non-Sendable is safe to transfer onto other situations. The caller though +/// that this is being sent to does not enforce that invariants within its body. +class AllowSendingMismatch final : public ContextualMismatch { +public: + enum class Kind { + Parameter, + Result, + }; + +private: + Kind kind; + + AllowSendingMismatch(ConstraintSystem &cs, Type argType, Type paramType, + ConstraintLocator *locator, Kind kind, + FixBehavior fixBehavior) + : ContextualMismatch(cs, FixKind::AllowSendingMismatch, argType, + paramType, locator, fixBehavior), + kind(kind) {} + +public: + std::string getName() const override { + return "treat a function argument with sending parameter as a function " + "argument without sending parameters"; + } + + bool diagnose(const Solution &solution, bool asNote = false) const override; + + bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override { + return diagnose(*commonFixes.front().first); + } + + static AllowSendingMismatch *create(ConstraintSystem &cs, + ConstraintLocator *locator, Type srcType, + Type dstType, Kind kind); + + static bool classof(const ConstraintFix *fix) { + return fix->getKind() == FixKind::AllowSendingMismatch; + } +}; + class SpecifyBaseTypeForContextualMember final : public ConstraintFix { DeclNameRef MemberName; diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 45dc07602c1ac..3db029eb5c3c3 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -2826,6 +2826,10 @@ class ConstraintSystem { /// Associate an argument list with a call at a given locator. void associateArgumentList(ConstraintLocator *locator, ArgumentList *args); + /// If the given node is a function expression with a parent ApplyExpr, + /// returns the apply, otherwise returns the node itself. + ASTNode includingParentApply(ASTNode node); + std::optional findSelectedOverloadFor(ConstraintLocator *locator) const { auto result = ResolvedOverloads.find(locator); diff --git a/lib/APIDigester/ModuleAnalyzerNodes.cpp b/lib/APIDigester/ModuleAnalyzerNodes.cpp index 029d5e8fa3576..12d67c3453f61 100644 --- a/lib/APIDigester/ModuleAnalyzerNodes.cpp +++ b/lib/APIDigester/ModuleAnalyzerNodes.cpp @@ -1474,7 +1474,7 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, Decl *D): ObjCName(Ctx.getObjcName(D)), InitKind(Ctx.getInitKind(D)), IsImplicit(D->isImplicit()), - IsDeprecated(D->getAttrs().getDeprecated(D->getASTContext())), + IsDeprecated(D->getAttrs().isDeprecated(D->getASTContext())), IsABIPlaceholder(isABIPlaceholderRecursive(D)), IsFromExtension(isDeclaredInExtension(D)), DeclAttrs(collectDeclAttributes(D)) { diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index ae667d06a5e9c..d5e6754845ecc 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -755,36 +755,53 @@ Type ASTBuilder::createExistentialMetatypeType( Type ASTBuilder::createConstrainedExistentialType( Type base, ArrayRef constraints, ArrayRef inverseRequirements) { - // FIXME: Generalize to other kinds of bases. - if (!base->getAs()) - return Type(); - auto baseTy = base->castTo(); - auto baseDecl = baseTy->getDecl(); - llvm::SmallDenseMap cmap; - for (const auto &req : constraints) { - switch (req.getKind()) { - case RequirementKind::SameShape: - llvm_unreachable("Same-shape requirement not supported here"); - case RequirementKind::Conformance: - case RequirementKind::Superclass: - case RequirementKind::Layout: - continue; + Type constrainedBase; + + if (auto baseTy = base->getAs()) { + auto baseDecl = baseTy->getDecl(); + llvm::SmallDenseMap cmap; + for (const auto &req : constraints) { + switch (req.getKind()) { + case RequirementKind::SameShape: + llvm_unreachable("Same-shape requirement not supported here"); + case RequirementKind::Conformance: + case RequirementKind::Superclass: + case RequirementKind::Layout: + continue; - case RequirementKind::SameType: - if (auto *DMT = req.getFirstType()->getAs()) - cmap[DMT->getName()] = req.getSecondType(); + case RequirementKind::SameType: + if (auto *DMT = req.getFirstType()->getAs()) + cmap[DMT->getName()] = req.getSecondType(); + } } - } - llvm::SmallVector args; - for (auto *assocTy : baseDecl->getPrimaryAssociatedTypes()) { - auto argTy = cmap.find(assocTy->getName()); - if (argTy == cmap.end()) { - return Type(); + llvm::SmallVector args; + for (auto *assocTy : baseDecl->getPrimaryAssociatedTypes()) { + auto argTy = cmap.find(assocTy->getName()); + if (argTy == cmap.end()) { + return Type(); + } + args.push_back(argTy->getSecond()); + } + + // We may not have any arguments because the constrained existential is a + // plain protocol with an inverse requirement. + if (args.empty()) { + constrainedBase = + ProtocolType::get(baseDecl, baseTy, base->getASTContext()); + } else { + constrainedBase = + ParameterizedProtocolType::get(base->getASTContext(), baseTy, args); } - args.push_back(argTy->getSecond()); + } else if (base->isAny()) { + // The only other case should be that we got an empty PCT, which is equal to + // the Any type. The other constraints should have been encoded in the + // existential's generic signature (and arrive as BuiltInverseRequirement). + constrainedBase = base; + } else { + return Type(); } - Type constrainedBase = - ParameterizedProtocolType::get(base->getASTContext(), baseTy, args); + + assert(constrainedBase); // Handle inverse requirements. if (!inverseRequirements.empty()) { diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 7b22da4ec9a7f..17bdda599a2ec 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -482,21 +482,22 @@ namespace { raw_ostream &OS; unsigned Indent; public: + bool ParseIfNeeded; llvm::function_ref GetTypeOfExpr; llvm::function_ref GetTypeOfTypeRepr; llvm::function_ref GetTypeOfKeyPathComponent; char quote = '"'; - explicit PrintBase(raw_ostream &os, unsigned indent = 0, - llvm::function_ref getTypeOfExpr = defaultGetTypeOfExpr, - llvm::function_ref getTypeOfTypeRepr = nullptr, - llvm::function_ref - getTypeOfKeyPathComponent = - defaultGetTypeOfKeyPathComponent) - : OS(os), Indent(indent), GetTypeOfExpr(getTypeOfExpr), - GetTypeOfTypeRepr(getTypeOfTypeRepr), - GetTypeOfKeyPathComponent(getTypeOfKeyPathComponent) { } + explicit PrintBase( + raw_ostream &os, unsigned indent = 0, bool parseIfNeeded = false, + llvm::function_ref getTypeOfExpr = defaultGetTypeOfExpr, + llvm::function_ref getTypeOfTypeRepr = nullptr, + llvm::function_ref + getTypeOfKeyPathComponent = defaultGetTypeOfKeyPathComponent) + : OS(os), Indent(indent), ParseIfNeeded(parseIfNeeded), + GetTypeOfExpr(getTypeOfExpr), GetTypeOfTypeRepr(getTypeOfTypeRepr), + GetTypeOfKeyPathComponent(getTypeOfKeyPathComponent) {} bool hasNonStandardOutput() { return &OS != &llvm::errs() && &OS != &llvm::dbgs(); @@ -1301,7 +1302,9 @@ namespace { break; } - for (Decl *D : IDC->getMembers()) { + auto members = ParseIfNeeded ? IDC->getMembers() + : IDC->getCurrentMembersWithoutLoading(); + for (Decl *D : members) { printRec(D); } printFoot(); @@ -1313,7 +1316,9 @@ namespace { OS << SF.getFilename(); }); - if (auto items = SF.getCachedTopLevelItems()) { + auto items = + ParseIfNeeded ? SF.getTopLevelItems() : SF.getCachedTopLevelItems(); + if (items) { for (auto item : *items) { if (item.isImplicit()) continue; @@ -1556,7 +1561,7 @@ namespace { }); } - if (auto Body = D->getBody(/*canSynthesize=*/false)) { + if (auto Body = D->getBody(/*canSynthesize=*/ParseIfNeeded)) { printRec(Body, &D->getASTContext()); } } @@ -1858,13 +1863,7 @@ void SourceFile::dump() const { } void SourceFile::dump(llvm::raw_ostream &OS, bool parseIfNeeded) const { - // If we're allowed to parse the SourceFile, do so now. We need to force the - // parsing request as by default the dumping logic tries not to kick any - // requests. - if (parseIfNeeded) - (void)getTopLevelItems(); - - PrintDecl(OS).visitSourceFile(*this); + PrintDecl(OS, /*indent*/ 0, parseIfNeeded).visitSourceFile(*this); llvm::errs() << '\n'; } @@ -1889,13 +1888,16 @@ class PrintStmt : public StmtVisitor, using PrintBase::PrintBase; const ASTContext *Ctx; - PrintStmt(raw_ostream &os, const ASTContext *ctx, unsigned indent = 0, - llvm::function_ref getTypeOfExpr = defaultGetTypeOfExpr, - llvm::function_ref getTypeOfTypeRepr = nullptr, - llvm::function_ref - getTypeOfKeyPathComponent = defaultGetTypeOfKeyPathComponent) - : PrintBase(os, indent, getTypeOfExpr, getTypeOfTypeRepr, - getTypeOfKeyPathComponent), Ctx(ctx) { } + PrintStmt( + raw_ostream &os, const ASTContext *ctx, unsigned indent = 0, + bool parseIfNeeded = false, + llvm::function_ref getTypeOfExpr = defaultGetTypeOfExpr, + llvm::function_ref getTypeOfTypeRepr = nullptr, + llvm::function_ref + getTypeOfKeyPathComponent = defaultGetTypeOfKeyPathComponent) + : PrintBase(os, indent, parseIfNeeded, getTypeOfExpr, getTypeOfTypeRepr, + getTypeOfKeyPathComponent), + Ctx(ctx) {} using PrintBase::printRec; @@ -3259,8 +3261,8 @@ void Expr::dump(raw_ostream &OS, llvm::function_ref getTypeOfExpr, llvm::function_ref getTypeOfKeyPathComponent, unsigned Indent) const { - PrintExpr(OS, Indent, getTypeOfExpr, getTypeOfTypeRepr, - getTypeOfKeyPathComponent) + PrintExpr(OS, Indent, /*parseIfNeeded*/ false, getTypeOfExpr, + getTypeOfTypeRepr, getTypeOfKeyPathComponent) .visit(const_cast(this), ""); } @@ -3564,8 +3566,9 @@ void PrintBase::printRec(Decl *D, StringRef label) { printHead("", DeclColor, label); printFoot(); } else { - PrintDecl(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr, - GetTypeOfKeyPathComponent).visit(D, label); + PrintDecl(OS, Indent, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr, + GetTypeOfKeyPathComponent) + .visit(D, label); } }, label); } @@ -3575,8 +3578,9 @@ void PrintBase::printRec(Expr *E, StringRef label) { printHead("", ExprColor, label); printFoot(); } else { - PrintExpr(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr, - GetTypeOfKeyPathComponent).visit(E, label); + PrintExpr(OS, Indent, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr, + GetTypeOfKeyPathComponent) + .visit(E, label); } }, label); } @@ -3586,8 +3590,9 @@ void PrintBase::printRec(Stmt *S, const ASTContext *Ctx, StringRef label) { printHead("", ExprColor, label); printFoot(); } else { - PrintStmt(OS, Ctx, Indent, GetTypeOfExpr, GetTypeOfTypeRepr, - GetTypeOfKeyPathComponent).visit(S, label); + PrintStmt(OS, Ctx, Indent, ParseIfNeeded, GetTypeOfExpr, + GetTypeOfTypeRepr, GetTypeOfKeyPathComponent) + .visit(S, label); } }, label); } @@ -3597,8 +3602,9 @@ void PrintBase::printRec(TypeRepr *T, StringRef label) { printHead("", TypeReprColor, label); printFoot(); } else { - PrintTypeRepr(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr, - GetTypeOfKeyPathComponent).visit(T, label); + PrintTypeRepr(OS, Indent, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr, + GetTypeOfKeyPathComponent) + .visit(T, label); } }, label); } @@ -3608,9 +3614,9 @@ void PrintBase::printRec(const Pattern *P, StringRef label) { printHead("", PatternColor, label); printFoot(); } else { - PrintPattern(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr, - GetTypeOfKeyPathComponent).visit(const_cast(P), - label); + PrintPattern(OS, Indent, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr, + GetTypeOfKeyPathComponent) + .visit(const_cast(P), label); } }, label); } @@ -4536,8 +4542,9 @@ namespace { printHead("", DeclColor, label); printFoot(); } else { - PrintType(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr, - GetTypeOfKeyPathComponent).visit(type, label); + PrintType(OS, Indent, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr, + GetTypeOfKeyPathComponent) + .visit(type, label); } }, label); } diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index b3b456a888f07..88146e8429c12 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -3842,8 +3842,11 @@ CanType ASTMangler::getDeclTypeForMangling( parentGenericSig = GenericSignature(); auto &C = decl->getASTContext(); - if (decl->isInvalid()) { - if (isa(decl)) { + + auto ty = decl->getInterfaceType()->getReferenceStorageReferent(); + if (ty->hasError()) { + if (isa(decl) || isa(decl) || + isa(decl)) { // FIXME: Verify ExtInfo state is correct, not working by accident. CanFunctionType::ExtInfo info; return CanFunctionType::get({AnyFunctionType::Param(C.TheErrorType)}, @@ -3852,8 +3855,6 @@ CanType ASTMangler::getDeclTypeForMangling( return C.TheErrorType; } - Type ty = decl->getInterfaceType()->getReferenceStorageReferent(); - // If this declaration predates concurrency, adjust its type to not // contain type features that were not available pre-concurrency. This // cannot alter the ABI in any way. @@ -4440,10 +4441,21 @@ void ASTMangler::appendMacroExpansionContext( ASTContext &ctx = origDC->getASTContext(); SourceManager &sourceMgr = ctx.SourceMgr; + auto appendMacroExpansionLoc = [&]() { + appendIdentifier(origDC->getParentModule()->getName().str()); + + auto *SF = origDC->getParentSourceFile(); + appendIdentifier(llvm::sys::path::filename(SF->getFilename())); + + auto lineColumn = sourceMgr.getLineAndColumnInBuffer(loc); + appendOperator("fMX", Index(lineColumn.first), Index(lineColumn.second)); + }; + auto bufferID = sourceMgr.findBufferContainingLoc(loc); auto generatedSourceInfo = sourceMgr.getGeneratedSourceInfo(bufferID); - if (!generatedSourceInfo) - return appendContext(origDC, nullBase, StringRef()); + if (!generatedSourceInfo) { + return appendMacroExpansionLoc(); + } SourceLoc outerExpansionLoc; DeclContext *outerExpansionDC; @@ -4462,7 +4474,7 @@ void ASTMangler::appendMacroExpansionContext( case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::DefaultArgument: - return appendContext(origDC, nullBase, StringRef()); + return appendMacroExpansionLoc(); } switch (generatedSourceInfo->kind) { @@ -4519,7 +4531,7 @@ void ASTMangler::appendMacroExpansionContext( // If we hit the point where the structure is represented as a DeclContext, // we're done. if (origDC->isChildContextOf(outerExpansionDC)) - return appendContext(origDC, nullBase, StringRef()); + return appendMacroExpansionLoc(); // Append our own context and discriminator. appendMacroExpansionContext(outerExpansionLoc, origDC); diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 75fe2995540e5..3e298e5b03f45 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -2915,6 +2915,19 @@ void PrintAST::printExtendedTypeName(TypeLoc ExtendedTypeLoc) { printTypeLoc(TypeLoc(ExtendedTypeLoc.getTypeRepr(), Ty)); } +/// If an extension adds a conformance for an invertible protocol, then we +/// should not print inverses for its generic signature, because no conditional +/// requirements are inferred by default for such an extension. +static bool isExtensionAddingInvertibleConformance(const ExtensionDecl *ext) { + auto conformances = ext->getLocalConformances(); + for (auto *conf : conformances) { + if (conf->getProtocol()->getInvertibleProtocolKind()) { + assert(conformances.size() == 1 && "expected solo conformance"); + return true; + } + } + return false; +} void PrintAST::printSynthesizedExtension(Type ExtendedType, ExtensionDecl *ExtDecl) { @@ -3039,9 +3052,21 @@ void PrintAST::printExtension(ExtensionDecl *decl) { auto baseGenericSig = decl->getExtendedNominal()->getGenericSignature(); assert(baseGenericSig && "an extension can't be generic if the base type isn't"); + + auto genSigFlags = defaultGenericRequirementFlags() + | IncludeOuterInverses; + + // Disable printing inverses if the extension is adding a conformance + // for an invertible protocol itself, as we do not infer any requirements + // in such an extension. We need to print the whole signature: + // extension S: Copyable where T: Copyable + if (isExtensionAddingInvertibleConformance(decl)) { + genSigFlags &= ~PrintInverseRequirements; + genSigFlags &= ~IncludeOuterInverses; + } + printGenericSignature(genericSig, - defaultGenericRequirementFlags() - | IncludeOuterInverses, + genSigFlags, [baseGenericSig](const Requirement &req) -> bool { // Only include constraints that are not satisfied by the base type. return !baseGenericSig->isRequirementSatisfied(req); @@ -5724,8 +5749,6 @@ class TypePrinter : public TypeVisitor { ASTPrinter &Printer; const PrintOptions &Options; - std::optional> - VisibleClangModules; void printGenericArgs(ArrayRef flatArgs) { Printer << "<"; @@ -5799,56 +5822,6 @@ class TypePrinter : public TypeVisitor { return T->hasSimpleTypeRepr(); } - /// Computes the map that is cached by `getVisibleClangModules()`. - /// Do not call directly. - llvm::DenseMap - computeVisibleClangModules() { - assert(Options.CurrentModule && - "CurrentModule needs to be set to determine imported Clang modules"); - - llvm::DenseMap Result; - - // For the current module, consider both private and public imports. - ModuleDecl::ImportFilter Filter = ModuleDecl::ImportFilterKind::Exported; - Filter |= ModuleDecl::ImportFilterKind::Default; - - // For private or package swiftinterfaces, also look through @_spiOnly imports. - if (!Options.printPublicInterface()) - Filter |= ModuleDecl::ImportFilterKind::SPIOnly; - // Consider package import for package interface - if (Options.printPackageInterface()) - Filter |= ModuleDecl::ImportFilterKind::PackageOnly; - - SmallVector Imports; - Options.CurrentModule->getImportedModules(Imports, Filter); - - SmallVector ModulesToProcess; - for (const auto &Import : Imports) { - ModulesToProcess.push_back(Import.importedModule); - } - - SmallPtrSet Processed; - while (!ModulesToProcess.empty()) { - ModuleDecl *Mod = ModulesToProcess.back(); - ModulesToProcess.pop_back(); - - if (!Processed.insert(Mod).second) - continue; - - if (const clang::Module *ClangModule = Mod->findUnderlyingClangModule()) - Result[ClangModule] = Mod; - - // For transitive imports, consider only public imports. - Imports.clear(); - Mod->getImportedModules(Imports, ModuleDecl::ImportFilterKind::Exported); - for (const auto &Import : Imports) { - ModulesToProcess.push_back(Import.importedModule); - } - } - - return Result; - } - /// Returns all Clang modules that are visible from `Options.CurrentModule`. /// This includes any modules that are imported transitively through public /// (`@_exported`) imports. @@ -5857,10 +5830,7 @@ class TypePrinter : public TypeVisitor { /// corresponding Swift module. const llvm::DenseMap & getVisibleClangModules() { - if (!VisibleClangModules) { - VisibleClangModules = computeVisibleClangModules(); - } - return *VisibleClangModules; + return Options.CurrentModule->getVisibleClangModules(Options.InterfaceContentKind); } template diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index cffba1fb45d3a..43ff8ce5cb5ac 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -1526,6 +1526,9 @@ Type swift::getAsyncTaskAndContextType(ASTContext &ctx) { } static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id) { + auto taskExecutorIsAvailable = + ctx.getProtocol(swift::KnownProtocolKind::TaskExecutor) != nullptr; + return getBuiltinFunction( ctx, id, _thin, _generics(_unrestricted, _conformsToDefaults(0)), _parameters( @@ -1533,12 +1536,21 @@ static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id) { _label("initialSerialExecutor", _defaulted(_optional(_executor), _nil)), _label("taskGroup", _defaulted(_optional(_rawPointer), _nil)), _label("initialTaskExecutor", _defaulted(_optional(_executor), _nil)), - _label("operation", _function(_async(_throws(_sendable(_thick))), + _label("initialTaskExecutorConsuming", + _defaulted(_consuming(_optional(_bincompatType( + /*if*/ taskExecutorIsAvailable, + _existential(_taskExecutor), + /*else*/ _executor))), + _nil)), + _label("operation", _function(_async(_throws(_sendable(_thick))), _typeparam(0), _parameters()))), _tuple(_nativeObject, _rawPointer)); } static ValueDecl *getCreateDiscardingTask(ASTContext &ctx, Identifier id) { + auto taskExecutorIsAvailable = + ctx.getProtocol(swift::KnownProtocolKind::TaskExecutor) != nullptr; + return getBuiltinFunction( ctx, id, _thin, _parameters( @@ -1546,11 +1558,18 @@ static ValueDecl *getCreateDiscardingTask(ASTContext &ctx, Identifier id) { _label("initialSerialExecutor", _defaulted(_optional(_executor), _nil)), _label("taskGroup", _defaulted(_optional(_rawPointer), _nil)), _label("initialTaskExecutor", _defaulted(_optional(_executor), _nil)), + _label("initialTaskExecutorConsuming", + _defaulted(_consuming(_optional(_bincompatType( + /*if*/ taskExecutorIsAvailable, + _existential(_taskExecutor), + /*else*/ _executor))), + _nil)), _label("operation", _function(_async(_throws(_sendable(_thick))), _void, _parameters()))), _tuple(_nativeObject, _rawPointer)); } +// Legacy entry point, prefer `createAsyncTask` static ValueDecl *getCreateAsyncTask(ASTContext &ctx, Identifier id, bool inGroup, bool withTaskExecutor, bool isDiscarding) { @@ -1560,6 +1579,7 @@ static ValueDecl *getCreateAsyncTask(ASTContext &ctx, Identifier id, if (inGroup) { builder.addParameter(makeConcrete(ctx.TheRawPointerType)); // group } + if (withTaskExecutor) { builder.addParameter(makeConcrete(ctx.TheExecutorType)); // executor } @@ -2089,6 +2109,20 @@ static ValueDecl *getHopToActor(ASTContext &ctx, Identifier id) { return builder.build(id); } +static ValueDecl *getFlowSensitiveSelfIsolation( + ASTContext &ctx, Identifier id, bool isDistributed +) { + BuiltinFunctionBuilder builder(ctx); + return getBuiltinFunction( + ctx, id, _thin, + _generics(_unrestricted, + _conformsToDefaults(0), + _conformsTo(_typeparam(0), + isDistributed ? _distributedActor : _actor)), + _parameters(_typeparam(0)), + _optional(_existential(_actor))); +} + static ValueDecl *getDistributedActorAsAnyActor(ASTContext &ctx, Identifier id) { BuiltinFunctionBuilder builder(ctx); auto *distributedActorProto = ctx.getProtocol(KnownProtocolKind::DistributedActor); @@ -2976,7 +3010,7 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) { case BuiltinValueKind::FixLifetime: return getFixLifetimeOperation(Context, Id); - + case BuiltinValueKind::CanBeObjCClass: return getCanBeObjCClassOperation(Context, Id); @@ -3191,6 +3225,12 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) { case BuiltinValueKind::HopToActor: return getHopToActor(Context, Id); + case BuiltinValueKind::FlowSensitiveSelfIsolation: + return getFlowSensitiveSelfIsolation(Context, Id, false); + + case BuiltinValueKind::FlowSensitiveDistributedSelfIsolation: + return getFlowSensitiveSelfIsolation(Context, Id, true); + case BuiltinValueKind::AutoDiffCreateLinearMapContextWithType: return getAutoDiffCreateLinearMapContext(Context, Id); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 4ecf953e9215d..56685fd1ee074 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1809,18 +1809,25 @@ bool ExtensionDecl::isWrittenWithConstraints() const { typeSig->getRequirementsWithInverses(typeReqs, typeInverseReqs); // If the (non-inverse) requirements are different between the extension and - // the original type, it's written with constraints. Note that - // the extension can only add requirements, so we need only check the size - // (not the specific requirements). - if (extReqs.size() > typeReqs.size()) { + // the original type, it's written with constraints. + if (extReqs.size() != typeReqs.size()) { return true; } - assert(extReqs.size() == typeReqs.size()); + // In case of equal number of constraints, we have to check the specific + // requirements. Extensions can end up with fewer requirements than the type + // extended, due to a same-type requirement in the extension. + // + // This mirrors the 'same' check in `ASTMangler::gatherGenericSignatureParts` + for (size_t i = 0; i < extReqs.size(); i++) { + if (extReqs[i] != typeReqs[i]) + return true; + } // If the type has no inverse requirements, there are no extra constraints // to write. if (typeInverseReqs.empty()) { + assert(extInverseReqs.empty() && "extension retroactively added inverse?"); return false; } @@ -2314,7 +2321,7 @@ bool VarDecl::isLayoutExposedToClients() const { auto nominalAccess = parent->getFormalAccessScope(/*useDC=*/nullptr, /*treatUsableFromInlineAsPublic=*/true); - if (!nominalAccess.isPublicOrPackage()) return false; + if (!nominalAccess.isPublic()) return false; if (!parent->getAttrs().hasAttribute() && !parent->getAttrs().hasAttribute()) @@ -3054,9 +3061,6 @@ bool AbstractStorageDecl::isResilient(ModuleDecl *M, case ResilienceExpansion::Maximal: if (M == getModuleContext()) return false; - // Access non-resiliently if package optimization is enabled - if (bypassResilienceInPackage(M)) - return false; return isResilient(); } llvm_unreachable("bad resilience expansion"); @@ -4680,10 +4684,8 @@ bool ValueDecl::isMoreVisibleThan(ValueDecl *other) const { if (scope.isPublic()) return !otherScope.isPublic(); - else if (scope.isPackage()) - return !otherScope.isPublicOrPackage(); else if (scope.isInternal()) - return !otherScope.isPublicOrPackage() && !otherScope.isInternal(); + return !otherScope.isPublic() && !otherScope.isInternal(); else return false; } diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index 912bf50db0ad3..c55e6464f6712 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -486,7 +486,7 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator, auto effectiveAccess = VD->getFormalAccessScope(/*useDC=*/nullptr, /*treatUsableFromInlineAsPublic=*/true); - if (effectiveAccess.isPublicOrPackage()) { + if (effectiveAccess.isPublic()) { return {FragileFunctionKind::DefaultArgument}; } @@ -518,7 +518,7 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator, // If the function is not externally visible, we will not be serializing // its body. - if (!funcAccess.isPublicOrPackage()) { + if (!funcAccess.isPublic()) { return {FragileFunctionKind::None}; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 456e4738082f4..81657539820ea 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1934,7 +1934,12 @@ unsigned AbstractClosureExpr::getDiscriminator() const { Bits.AbstractClosureExpr.Discriminator = discriminator; } - assert(getRawDiscriminator() != InvalidDiscriminator); + if (getRawDiscriminator() == InvalidDiscriminator) { + llvm::errs() << "Closure does not have an assigned discriminator:\n"; + dump(llvm::errs()); + abort(); + } + return getRawDiscriminator(); } diff --git a/lib/AST/LifetimeDependence.cpp b/lib/AST/LifetimeDependence.cpp index aeca548950262..3ef2f162a6805 100644 --- a/lib/AST/LifetimeDependence.cpp +++ b/lib/AST/LifetimeDependence.cpp @@ -110,10 +110,12 @@ LifetimeDependenceInfo LifetimeDependenceInfo::getForParamIndex( auto indexSubset = IndexSubset::get(ctx, capacity, {index}); if (kind == LifetimeDependenceKind::Scope) { return LifetimeDependenceInfo{/*inheritLifetimeParamIndices*/ nullptr, - /*scopeLifetimeParamIndices*/ indexSubset}; + /*scopeLifetimeParamIndices*/ indexSubset, + /*isImmortal*/ false}; } return LifetimeDependenceInfo{/*inheritLifetimeParamIndices*/ indexSubset, - /*scopeLifetimeParamIndices*/ nullptr}; + /*scopeLifetimeParamIndices*/ nullptr, + /*isImmortal*/ false}; } void LifetimeDependenceInfo::getConcatenatedData( @@ -246,6 +248,18 @@ LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd) { for (auto specifier : lifetimeDependentRepr->getLifetimeDependencies()) { switch (specifier.getSpecifierKind()) { + case LifetimeDependenceSpecifier::SpecifierKind::Immortal: { + auto immortalParam = + std::find_if(afd->getParameters()->begin(), afd->getParameters()->end(), [](ParamDecl *param) { + return strcmp(param->getName().get(), "immortal") == 0; + }); + if (immortalParam != afd->getParameters()->end()) { + diags.diagnose(*immortalParam, + diag::lifetime_dependence_immortal_conflict_name); + } + + return LifetimeDependenceInfo(nullptr, nullptr, /*isImmortal*/ true); + } case LifetimeDependenceSpecifier::SpecifierKind::Named: { bool foundParamName = false; unsigned paramIndex = 0; @@ -315,7 +329,8 @@ LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd) { : nullptr, scopeLifetimeParamIndices.any() ? IndexSubset::get(ctx, scopeLifetimeParamIndices) - : nullptr); + : nullptr, + /*isImmortal*/ false); } // This utility is similar to its overloaded version that builds the @@ -360,18 +375,29 @@ std::optional LifetimeDependenceInfo::fromTypeRepr( }; for (auto specifier : lifetimeDependentRepr->getLifetimeDependencies()) { - assert(specifier.getSpecifierKind() == - LifetimeDependenceSpecifier::SpecifierKind::Ordered); - auto index = specifier.getIndex(); - if (index > capacity) { - diags.diagnose(specifier.getLoc(), - diag::lifetime_dependence_invalid_param_index, index); - return std::nullopt; + switch (specifier.getSpecifierKind()) { + case LifetimeDependenceSpecifier::SpecifierKind::Ordered: { + auto index = specifier.getIndex(); + if (index > capacity) { + diags.diagnose(specifier.getLoc(), + diag::lifetime_dependence_invalid_param_index, index); + return std::nullopt; + } + auto param = params[index]; + auto paramConvention = param.getConvention(); + if (updateLifetimeDependenceInfo(specifier, index, paramConvention)) { + return std::nullopt; + } + break; } - auto param = params[index]; - auto paramConvention = param.getConvention(); - if (updateLifetimeDependenceInfo(specifier, index, paramConvention)) { - return std::nullopt; + case LifetimeDependenceSpecifier::SpecifierKind::Immortal: { + return LifetimeDependenceInfo(/*inheritLifetimeParamIndices*/ nullptr, + /*scopeLifetimeParamIndices*/ nullptr, + /*isImmortal*/ true); + } + default: + llvm_unreachable("SIL can only have ordered or immortal lifetime " + "dependence specifier kind"); } } @@ -381,7 +407,8 @@ std::optional LifetimeDependenceInfo::fromTypeRepr( : nullptr, scopeLifetimeParamIndices.any() ? IndexSubset::get(ctx, scopeLifetimeParamIndices) - : nullptr); + : nullptr, + /*isImmortal*/ false); } std::optional @@ -510,18 +537,6 @@ LifetimeDependenceInfo::get(AbstractFunctionDecl *afd) { return LifetimeDependenceInfo::infer(afd); } -LifetimeDependenceInfo -LifetimeDependenceInfo::get(ASTContext &ctx, - const SmallBitVector &inheritLifetimeIndices, - const SmallBitVector &scopeLifetimeIndices) { - return LifetimeDependenceInfo{ - inheritLifetimeIndices.any() - ? IndexSubset::get(ctx, inheritLifetimeIndices) - : nullptr, - scopeLifetimeIndices.any() ? IndexSubset::get(ctx, scopeLifetimeIndices) - : nullptr}; -} - std::optional LifetimeDependenceInfo::getLifetimeDependenceOnParam(unsigned paramIndex) { if (inheritLifetimeParamIndices) { diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 24deaf7fb1101..86ad07fcc1dfc 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1719,6 +1719,54 @@ void ModuleDecl::getMissingImportedModules( FORWARD(getMissingImportedModules, (imports)); } +const llvm::DenseMap & +ModuleDecl::getVisibleClangModules(PrintOptions::InterfaceMode contentMode) { + if (CachedVisibleClangModuleSet.find(contentMode) != CachedVisibleClangModuleSet.end()) + return CachedVisibleClangModuleSet[contentMode]; + else + CachedVisibleClangModuleSet.emplace(contentMode, VisibleClangModuleSet{}); + VisibleClangModuleSet &result = CachedVisibleClangModuleSet[contentMode]; + + // For the current module, consider both private and public imports. + ModuleDecl::ImportFilter Filter = ModuleDecl::ImportFilterKind::Exported; + Filter |= ModuleDecl::ImportFilterKind::Default; + + // For private or package swiftinterfaces, also look through @_spiOnly imports. + if (contentMode != PrintOptions::InterfaceMode::Public) + Filter |= ModuleDecl::ImportFilterKind::SPIOnly; + // Consider package import for package interface + if (contentMode == PrintOptions::InterfaceMode::Package) + Filter |= ModuleDecl::ImportFilterKind::PackageOnly; + + SmallVector Imports; + getImportedModules(Imports, Filter); + + SmallVector ModulesToProcess; + for (const auto &Import : Imports) + ModulesToProcess.push_back(Import.importedModule); + + SmallPtrSet Processed; + while (!ModulesToProcess.empty()) { + ModuleDecl *Mod = ModulesToProcess.back(); + ModulesToProcess.pop_back(); + + if (!Processed.insert(Mod).second) + continue; + + if (const clang::Module *ClangModule = Mod->findUnderlyingClangModule()) + result[ClangModule] = Mod; + + // For transitive imports, consider only public imports. + Imports.clear(); + Mod->getImportedModules(Imports, ModuleDecl::ImportFilterKind::Exported); + for (const auto &Import : Imports) { + ModulesToProcess.push_back(Import.importedModule); + } + } + + return result; +} + void SourceFile::getImportedModules(SmallVectorImpl &modules, ModuleDecl::ImportFilter filter) const { @@ -2620,9 +2668,11 @@ ImportDeclRequest::evaluate(Evaluator &evaluator, const SourceFile *sf, auto &ctx = sf->getASTContext(); auto imports = sf->getImports(); + auto mutModule = const_cast(module); // Look to see if the owning module was directly imported. for (const auto &import : imports) { - if (import.module.importedModule == module) + if (import.module.importedModule + ->isSameModuleLookingThroughOverlays(mutModule)) return import; } @@ -2631,7 +2681,8 @@ ImportDeclRequest::evaluate(Evaluator &evaluator, const SourceFile *sf, for (const auto &import : imports) { auto &importSet = importCache.getImportSet(import.module.importedModule); for (const auto &transitive : importSet.getTransitiveImports()) { - if (transitive.importedModule == module) { + if (transitive.importedModule + ->isSameModuleLookingThroughOverlays(mutModule)) { return import; } } @@ -2650,12 +2701,6 @@ void SourceFile::setImportUsedPreconcurrency( PreconcurrencyImportsUsed.insert(import); } -bool SourceFile::isMaxAccessLevelUsingImportInternal( - AttributedImport import) const { - auto maxLevel = getMaxAccessLevelUsingImport(import.module.importedModule); - return maxLevel < AccessLevel::Package; -} - AccessLevel SourceFile::getMaxAccessLevelUsingImport( const ModuleDecl *mod) const { @@ -2674,6 +2719,26 @@ void SourceFile::registerAccessLevelUsingImport( ImportsUseAccessLevel[mod] = accessLevel; else ImportsUseAccessLevel[mod] = std::max(accessLevel, known->second); + + // Also register modules triggering the import of cross-import overlays. + auto declaringMod = mod->getDeclaringModuleIfCrossImportOverlay(); + if (!declaringMod) + return; + + SmallVector bystanders; + auto bystandersValid = + mod->getRequiredBystandersIfCrossImportOverlay(declaringMod, bystanders); + if (!bystandersValid) + return; + + for (auto &otherImport : *Imports) { + auto otherImportMod = otherImport.module.importedModule; + auto otherImportModName = otherImportMod->getName(); + if (otherImportMod == declaringMod || + llvm::find(bystanders, otherImportModName) != bystanders.end()) { + registerAccessLevelUsingImport(otherImport, accessLevel); + } + } } bool HasImportsMatchingFlagRequest::evaluate(Evaluator &evaluator, diff --git a/lib/AST/RequirementMachine/RequirementMachineRequests.cpp b/lib/AST/RequirementMachine/RequirementMachineRequests.cpp index 1b7b9eec45390..78922b3d4b11d 100644 --- a/lib/AST/RequirementMachine/RequirementMachineRequests.cpp +++ b/lib/AST/RequirementMachine/RequirementMachineRequests.cpp @@ -782,7 +782,6 @@ InferredGenericSignatureRequest::evaluate( unsigned numOuterParams = genericParams.size(); if (isExtension) { - assert(allowInverses); numOuterParams = 0; } diff --git a/lib/AST/UnqualifiedLookup.cpp b/lib/AST/UnqualifiedLookup.cpp index 08bbf0441b549..4797510d6b3d7 100644 --- a/lib/AST/UnqualifiedLookup.cpp +++ b/lib/AST/UnqualifiedLookup.cpp @@ -369,13 +369,6 @@ ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl(const DeclContext *baseDC) c return nullptr; } - auto selfDecl = ASTScope::lookupSingleLocalDecl( - DC->getParentSourceFile(), DeclName(Ctx.Id_self), Loc); - - if (!selfDecl) { - return nullptr; - } - bool capturesSelfWeakly = false; if (auto decl = closureExpr->getCapturedSelfDecl()) { if (auto a = decl->getAttrs().getAttribute()) { @@ -383,6 +376,17 @@ ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl(const DeclContext *baseDC) c } } + // Previously we didn't perform the lookup of 'self' for anything outside + // of a '[weak self]' closure, maintain that behavior until Swift 6 mode. + if (!Ctx.LangOpts.isSwiftVersionAtLeast(6) && !capturesSelfWeakly) + return nullptr; + + auto selfDecl = ASTScope::lookupSingleLocalDecl(DC->getParentSourceFile(), + DeclName(Ctx.Id_self), Loc); + if (!selfDecl) { + return nullptr; + } + // In Swift 5 mode, implicit self is allowed within non-escaping // `weak self` closures even before self is unwrapped. // For example, this is allowed: @@ -407,7 +411,7 @@ ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl(const DeclContext *baseDC) c // In these cases, using the Swift 6 lookup behavior doesn't affect // how the body is type-checked, so it can be used in Swift 5 mode // without breaking source compatibility for non-escaping closures. - if (capturesSelfWeakly && !Ctx.LangOpts.isSwiftVersionAtLeast(6) && + if (!Ctx.LangOpts.isSwiftVersionAtLeast(6) && !implicitSelfReferenceIsUnwrapped(selfDecl)) { return nullptr; } diff --git a/lib/ASTGen/Sources/SwiftIDEUtilsBridging/NameMatcherBridging.swift b/lib/ASTGen/Sources/SwiftIDEUtilsBridging/NameMatcherBridging.swift index 2f81023a3a8e3..30d198f48ffc1 100644 --- a/lib/ASTGen/Sources/SwiftIDEUtilsBridging/NameMatcherBridging.swift +++ b/lib/ASTGen/Sources/SwiftIDEUtilsBridging/NameMatcherBridging.swift @@ -50,6 +50,7 @@ fileprivate extension IDEBridging.LabelRangeType { case .noArguments: self = .None case .call: self = .CallArg case .parameters: self = .Param + case .enumCaseParameters: self = .EnumCaseParam case .noncollapsibleParameters: self = .NoncollapsibleParam case .selector: self = .CompoundName #if RESILIENT_SWIFT_SYNTAX @@ -72,6 +73,7 @@ extension BridgedResolvedLoc { case .noArguments: arguments = [] case .call(let arguments2, _): arguments = arguments2 case .parameters(let arguments2): arguments = arguments2 + case .enumCaseParameters(let arguments2): arguments = arguments2 case .noncollapsibleParameters(let arguments2): arguments = arguments2 case .selector(let arguments2): arguments = arguments2 #if RESILIENT_SWIFT_SYNTAX diff --git a/lib/ClangImporter/CFTypeInfo.h b/lib/ClangImporter/CFTypeInfo.h index 3597e60f05ef7..e62576f5d71f0 100644 --- a/lib/ClangImporter/CFTypeInfo.h +++ b/lib/ClangImporter/CFTypeInfo.h @@ -107,13 +107,6 @@ class CFPointeeInfo { return Decl.get(); } }; - -/// Determine whether this typedef is a CF type. -bool isCFTypeDecl(const clang::TypedefNameDecl *Decl); - -/// Determine the imported CF type for the given typedef-name, or the empty -/// string if this is not an imported CF type name. -llvm::StringRef getCFTypeName(const clang::TypedefNameDecl *decl); } } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 0fa135546da11..3e1827dcbd2ca 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -3734,6 +3734,18 @@ namespace { } Decl *VisitCXXMethodDecl(const clang::CXXMethodDecl *decl) { + // The static `operator ()` introduced in C++ 23 is still callable as an + // instance operator in C++, and we want to preserve the ability to call + // it as an instance method in Swift as well for source compatibility. + // Therefore, we synthesize a C++ instance member that invokes the + // operator and import it instead. + if (decl->getOverloadedOperator() == + clang::OverloadedOperatorKind::OO_Call && + decl->isStatic()) { + auto result = synthesizer.makeInstanceToStaticOperatorCallMethod(decl); + if (result) + return result; + } auto method = VisitFunctionDecl(decl); // Do not expose constructors of abstract C++ classes. diff --git a/lib/ClangImporter/SwiftDeclSynthesizer.cpp b/lib/ClangImporter/SwiftDeclSynthesizer.cpp index 3bd00a0dddbb8..b8d6614bd11c9 100644 --- a/lib/ClangImporter/SwiftDeclSynthesizer.cpp +++ b/lib/ClangImporter/SwiftDeclSynthesizer.cpp @@ -2021,9 +2021,12 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod( auto &clangCtx = ImporterImpl.getClangASTContext(); auto &clangSema = ImporterImpl.getClangSema(); + assert(!method->isStatic() || + method->getNameInfo().getName().getCXXOverloadedOperator() == + clang::OO_Call); // When emitting symbolic decls, the method might not have a concrete // record type as this type. - if (ImporterImpl.importSymbolicCXXDecls && + if (ImporterImpl.importSymbolicCXXDecls && !method->isStatic() && !method->getThisType()->getPointeeCXXRecordDecl()) return nullptr; @@ -2051,6 +2054,11 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod( (forwardingMethodKind == ForwardingMethodKind::Virtual ? "__synthesizedVirtualCall_operatorStar" : "__synthesizedBaseCall_operatorStar"))); + } else if (name.getCXXOverloadedOperator() == clang::OO_Call) { + assert(forwardingMethodKind != ForwardingMethodKind::Virtual); + name = clang::DeclarationName( + &ImporterImpl.getClangPreprocessor().getIdentifierTable().get( + "__synthesizedBaseCall_operatorCall")); } auto methodType = method->getType(); // Check if we need to drop the reference from the return type @@ -2093,7 +2101,8 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod( clangCtx, const_cast(derivedClass), method->getSourceRange().getBegin(), clang::DeclarationNameInfo(name, clang::SourceLocation()), methodType, - method->getTypeSourceInfo(), method->getStorageClass(), + method->getTypeSourceInfo(), + method->isStatic() ? clang::SC_None : method->getStorageClass(), method->UsesFPIntrin(), /*isInline=*/true, method->getConstexprKind(), method->getSourceRange().getEnd()); newMethod->setImplicit(); @@ -2264,6 +2273,27 @@ FuncDecl *SwiftDeclSynthesizer::makeVirtualMethod( return result; } +// MARK: C++ operators + +FuncDecl *SwiftDeclSynthesizer::makeInstanceToStaticOperatorCallMethod( + const clang::CXXMethodDecl *clangMethodDecl) { + auto clangDC = clangMethodDecl->getParent(); + auto &ctx = ImporterImpl.SwiftContext; + + assert(clangMethodDecl->isStatic() && "Expected a static operator"); + + auto newMethod = synthesizeCXXForwardingMethod( + clangDC, clangDC, clangMethodDecl, ForwardingMethodKind::Base, + ReferenceReturnTypeBehaviorForBaseMethodSynthesis::KeepReference, + /*forceConstQualifier*/ true); + newMethod->addAttr(clang::SwiftNameAttr::CreateImplicit( + clangMethodDecl->getASTContext(), "callAsFunction")); + + auto result = dyn_cast_or_null( + ctx.getClangModuleLoader()->importDeclDirectly(newMethod)); + return result; +} + // MARK: C++ properties static std::pair diff --git a/lib/ClangImporter/SwiftDeclSynthesizer.h b/lib/ClangImporter/SwiftDeclSynthesizer.h index ae54c8406ee53..e7ab62a46e7ab 100644 --- a/lib/ClangImporter/SwiftDeclSynthesizer.h +++ b/lib/ClangImporter/SwiftDeclSynthesizer.h @@ -319,6 +319,9 @@ class SwiftDeclSynthesizer { /// method that dispatches the call dynamically. FuncDecl *makeVirtualMethod(const clang::CXXMethodDecl *clangMethodDecl); + FuncDecl *makeInstanceToStaticOperatorCallMethod( + const clang::CXXMethodDecl *clangMethodDecl); + VarDecl *makeComputedPropertyFromCXXMethods(FuncDecl *getter, FuncDecl *setter); diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index f79f69853bb51..1290022c99d2e 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -4294,7 +4294,8 @@ static bool isMacroExpansionNodeKind(Node::Kind kind) { kind == Node::Kind::MemberAttachedMacroExpansion || kind == Node::Kind::PeerAttachedMacroExpansion || kind == Node::Kind::ConformanceAttachedMacroExpansion || - kind == Node::Kind::ExtensionAttachedMacroExpansion; + kind == Node::Kind::ExtensionAttachedMacroExpansion || + kind == Node::Kind::MacroExpansionLoc; } NodePointer Demangler::demangleMacroExpansion() { @@ -4323,6 +4324,20 @@ NodePointer Demangler::demangleMacroExpansion() { isFreestanding = false; break; + case 'X': { + kind = Node::Kind::MacroExpansionLoc; + + int line = demangleIndex(); + int col = demangleIndex(); + + auto lineNode = createNode(Node::Kind::Index, line); + auto colNode = createNode(Node::Kind::Index, col); + + NodePointer buffer = popNode(Node::Kind::Identifier); + NodePointer module = popNode(Node::Kind::Identifier); + return createWithChildren(kind, module, buffer, lineNode, colNode); + } + default: return nullptr; } diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 0094537d666fb..2dfa67193dc3d 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -457,6 +457,7 @@ class NodePrinter { case Node::Kind::LazyProtocolWitnessTableCacheVariable: case Node::Kind::LocalDeclName: case Node::Kind::Macro: + case Node::Kind::MacroExpansionLoc: case Node::Kind::MacroExpansionUniqueName: case Node::Kind::MaterializeForSet: case Node::Kind::MemberAttributeAttachedMacroExpansion: @@ -1544,6 +1545,24 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType, /*hasName*/true, "freestanding macro expansion #", (int)Node->getChild(2)->getIndex() + 1); + case Node::Kind::MacroExpansionLoc: + if (Node->getNumChildren() > 0) { + Printer << "module "; + print(Node->getChild(0), depth + 1); + } + if (Node->getNumChildren() > 1) { + Printer << " file "; + print(Node->getChild(1), depth + 1); + } + if (Node->getNumChildren() > 2) { + Printer << " line "; + print(Node->getChild(2), depth + 1); + } + if (Node->getNumChildren() > 3) { + Printer << " column "; + print(Node->getChild(3), depth + 1); + } + return nullptr; case Node::Kind::MacroExpansionUniqueName: return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType, /*hasName*/true, "unique name #", diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index 46529b2389382..1c115e1400515 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -1115,6 +1115,11 @@ ManglingError Remangler::mangleMacroExpansionUniqueName( return mangleChildNodes(node, depth + 1); } +ManglingError Remangler::mangleMacroExpansionLoc( + Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + ManglingError Remangler::mangleAccessor(Node *storageNode, StringRef accessorCode, EntityContext &ctx, unsigned depth) { diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index a5ae66913c80a..3aa0009c8862e 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -3120,6 +3120,21 @@ ManglingError Remangler::mangle##Name##AttachedMacroExpansion( \ } #include "swift/Basic/MacroRoles.def" +ManglingError Remangler::mangleMacroExpansionLoc( + Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1)); + RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); + + auto line = node->getChild(2)->getIndex(); + auto col = node->getChild(3)->getIndex(); + + Buffer << "fMX"; + mangleIndex(line); + mangleIndex(col); + + return ManglingError::Success; +} + ManglingError Remangler::mangleMacroExpansionUniqueName( Node *node, unsigned depth) { RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1)); diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 04670c6a5e3ae..5532de9c9e188 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -659,23 +659,40 @@ toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments, static unsigned getDWARFVersionForTriple(const llvm::Triple &triple) { llvm::VersionTuple osVersion; const DarwinPlatformKind kind = getDarwinPlatformKind(triple); + // Default to DWARF 2 on OS X 10.10 / iOS 8 and lower. + // Default to DWARF 4 on OS X 10.11 - macOS 14 / iOS - iOS 17. switch (kind) { case DarwinPlatformKind::MacOS: triple.getMacOSXVersion(osVersion); if (osVersion < llvm::VersionTuple(10, 11)) return 2; - return 4; + if (osVersion < llvm::VersionTuple(15)) + return 4; + return 5; case DarwinPlatformKind::IPhoneOSSimulator: case DarwinPlatformKind::IPhoneOS: case DarwinPlatformKind::TvOS: case DarwinPlatformKind::TvOSSimulator: osVersion = triple.getiOSVersion(); - if (osVersion < llvm::VersionTuple(9)) - return 2; - return 4; - default: - return 4; + if (osVersion < llvm::VersionTuple(9)) + return 2; + if (osVersion < llvm::VersionTuple(18)) + return 4; + return 5; + case DarwinPlatformKind::WatchOS: + case DarwinPlatformKind::WatchOSSimulator: + osVersion = triple.getWatchOSVersion(); + if (osVersion < llvm::VersionTuple(11)) + return 4; + return 5; + case DarwinPlatformKind::VisionOS: + case DarwinPlatformKind::VisionOSSimulator: + osVersion = triple.getOSVersion(); + if (osVersion < llvm::VersionTuple(2)) + return 4; + return 5; } + llvm_unreachable("unsupported platform kind"); } void toolchains::Darwin::addCommonFrontendArgs( diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index a0e2a2a167c3b..ec3d2544af6d6 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -14,6 +14,7 @@ #include "ArgsToFrontendInputsConverter.h" #include "ArgsToFrontendOutputsConverter.h" +#include "clang/Driver/Driver.h" #include "swift/AST/DiagnosticsFrontend.h" #include "swift/Basic/Platform.h" #include "swift/Frontend/Frontend.h" @@ -68,7 +69,7 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.ExplicitModulesOutputPath = A->getValue(); } else { SmallString<128> defaultPath; - llvm::sys::path::cache_directory(defaultPath); + clang::driver::Driver::getDefaultModuleCachePath(defaultPath); Opts.ExplicitModulesOutputPath = defaultPath.str().str(); } if (const Arg *A = Args.getLastArg(OPT_backup_module_interface_path)) { diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index a9e5c7b7c9ddc..80c0104086167 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -1650,11 +1650,6 @@ CompilerInstance::getSourceFileParsingOptions(bool forPrimary) const { action != ActionType::ScanDependencies) { opts |= ParsingFlags::DisablePoundIfEvaluation; } - - // If we need to dump the parse tree, disable delayed bodies as we want to - // show everything. - if (action == ActionType::DumpParse) - opts |= ParsingFlags::DisableDelayedBodies; } const auto &typeOpts = getASTContext().TypeCheckerOpts; diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index 23b7a496d1853..632b04008826f 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -276,6 +276,8 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface( SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName; SerializationOpts.AutolinkForceLoad = !Invocation.getIRGenOptions().ForceLoadSymbolName.empty(); + SerializationOpts.PublicDependentLibraries = + Invocation.getIRGenOptions().PublicLinkLibraries; SerializationOpts.UserModuleVersion = FEOpts.UserModuleVersion; SerializationOpts.AllowableClients = FEOpts.AllowableClients; StringRef SDKPath = Instance.getASTContext().SearchPathOpts.getSDKPath(); diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 491baa89e671e..586ed236757fa 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -240,7 +240,8 @@ static void printImports(raw_ostream &out, // it's not obvious what higher-level optimization would be factored out here. ModuleDecl::ImportFilter allImportFilter = { ModuleDecl::ImportFilterKind::Exported, - ModuleDecl::ImportFilterKind::Default}; + ModuleDecl::ImportFilterKind::Default, + ModuleDecl::ImportFilterKind::ShadowedByCrossImportOverlay}; // With -experimental-spi-imports: // When printing the private or package swiftinterface file, print implementation-only @@ -801,7 +802,7 @@ class InheritedProtocolCollector { } /// If there were any conditional conformances that couldn't be printed, - /// make a dummy extension that conforms to all of them, constrained by a + /// make dummy extension(s) that conforms to all of them, constrained by a /// fake protocol. bool printInaccessibleConformanceExtensionIfNeeded( raw_ostream &out, const PrintOptions &printOptions, @@ -810,20 +811,35 @@ class InheritedProtocolCollector { return false; assert(nominal->isGenericContext()); - if (!printOptions.printPublicInterface()) - out << "@_spi(" << DummyProtocolName << ")\n"; - out << "@available(*, unavailable)\nextension "; - nominal->getDeclaredType().print(out, printOptions); - out << " : "; - llvm::interleave( - ConditionalConformanceProtocols, - [&out, &printOptions](const ProtocolType *protoTy) { - protoTy->print(out, printOptions); - }, - [&out] { out << ", "; }); - out << " where " - << nominal->getGenericSignature().getGenericParams().front()->getName() - << " : " << DummyProtocolName << " {}\n"; + auto emitExtension = + [&](ArrayRef conformanceProtos) { + if (!printOptions.printPublicInterface()) + out << "@_spi(" << DummyProtocolName << ")\n"; + out << "@available(*, unavailable)\nextension "; + nominal->getDeclaredType().print(out, printOptions); + out << " : "; + llvm::interleave( + conformanceProtos, + [&out, &printOptions](const ProtocolType *protoTy) { + protoTy->print(out, printOptions); + }, + [&out] { out << ", "; }); + out << " where " + << nominal->getGenericSignature().getGenericParams()[0]->getName() + << " : " << DummyProtocolName << " {}\n"; + }; + + // We have to print conformances for invertible protocols in separate + // extensions, so do those first and save the rest for one extension. + SmallVector regulars; + for (auto *proto : ConditionalConformanceProtocols) { + if (proto->getDecl()->getInvertibleProtocolKind()) { + emitExtension(proto); + continue; + } + regulars.push_back(proto); + } + emitExtension(regulars); return true; } diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index ffb44e70c60d0..319e5073a3b6b 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -598,6 +598,8 @@ mapFrontendInvocationToAction(const CompilerInvocation &Invocation) { return "backend"; else return "compile"; + case FrontendOptions::ActionType::EmitModuleOnly: + return "emit-module"; default: return "compile"; } @@ -634,7 +636,8 @@ static swift::file_types::ID computeFileTypeForPath(const StringRef Path) { static DetailedTaskDescription constructDetailedTaskDescription(const CompilerInvocation &Invocation, ArrayRef PrimaryInputs, - ArrayRef Args) { + ArrayRef Args, + bool isEmitModuleOnly = false) { // Command line and arguments std::string Executable = Invocation.getFrontendOptions().MainExecutablePath; SmallVector Arguments; @@ -653,10 +656,12 @@ constructDetailedTaskDescription(const CompilerInvocation &Invocation, } for (const auto &input : PrimaryInputs) { - // Main outputs - auto OutputFile = input.outputFilename(); - if (!OutputFile.empty()) - Outputs.push_back(OutputPair(computeFileTypeForPath(OutputFile), OutputFile)); + if (!isEmitModuleOnly) { + // Main per-input outputs + auto OutputFile = input.outputFilename(); + if (!OutputFile.empty()) + Outputs.push_back(OutputPair(computeFileTypeForPath(OutputFile), OutputFile)); + } // Supplementary outputs const auto &primarySpecificFiles = input.getPrimarySpecificPaths(); @@ -2335,10 +2340,14 @@ int swift::performFrontend(ArrayRef Args, return false; }); } else { - // If no primary inputs are present, we are in WMO. + // If no primary inputs are present, we are in WMO or EmitModule. + bool isEmitModule = + Invocation.getFrontendOptions().RequestedAction == + FrontendOptions::ActionType::EmitModuleOnly; emitBeganMessage(llvm::errs(), mapFrontendInvocationToAction(Invocation), - constructDetailedTaskDescription(Invocation, IO.getAllInputs(), Args), + constructDetailedTaskDescription(Invocation, IO.getAllInputs(), + Args, isEmitModule), OSPid, ProcInfo); } }; diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 6135084c44799..5a66642d26639 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -1431,14 +1431,14 @@ void CodeCompletionCallbacksImpl::typeCheckWithLookup( /// decl it could be attached to. Type check it standalone. // First try to check it as an attached macro. - auto resolvedMacro = evaluateOrDefault( + (void)evaluateOrDefault( CurDeclContext->getASTContext().evaluator, ResolveMacroRequest{AttrWithCompletion, CurDeclContext}, ConcreteDeclRef()); // If that fails, type check as a call to the attribute's type. This is // how, e.g., property wrappers are modelled. - if (!resolvedMacro) { + if (!Lookup.gotCallback()) { ASTNode Call = CallExpr::create( CurDeclContext->getASTContext(), AttrWithCompletion->getTypeExpr(), AttrWithCompletion->getArgs(), /*implicit=*/true); diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 955e297c8a71e..18cecab04c1de 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -212,7 +212,7 @@ void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D) { CurrentModule = MD; } - if (D->getAttrs().getDeprecated(D->getASTContext())) + if (D->getAttrs().isDeprecated(D->getASTContext())) setContextFreeNotRecommended(ContextFreeNotRecommendedReason::Deprecated); else if (D->getAttrs().getSoftDeprecated(D->getASTContext())) setContextFreeNotRecommended( diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index e2a9f164e3373..a56861f397a0e 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -4299,11 +4299,12 @@ static void emitDirectForeignParameter(IRGenFunction &IGF, Explosion &in, // The ABI IR types for the entrypoint might differ from the // Swift IR types for the body of the function. + bool IsDirectFlattened = AI.isDirect() && AI.getCanBeFlattened(); + llvm::Type *coercionTy = AI.getCoerceToType(); ArrayRef expandedTys; - if (AI.isDirect() && AI.getCanBeFlattened() && - isa(coercionTy)) { + if (IsDirectFlattened && isa(coercionTy)) { const auto *ST = cast(coercionTy); expandedTys = llvm::ArrayRef(ST->element_begin(), ST->getNumElements()); } else if (coercionTy == paramTI.getStorageType()) { @@ -4344,7 +4345,8 @@ static void emitDirectForeignParameter(IRGenFunction &IGF, Explosion &in, Address coercedAddr = IGF.Builder.CreateElementBitCast(temporary, coercionTy); // Break down a struct expansion if necessary. - if (auto expansionTy = dyn_cast(coercionTy)) { + if (IsDirectFlattened && isa(coercionTy)) { + auto expansionTy = cast(coercionTy); auto layout = IGF.IGM.DataLayout.getStructLayout(expansionTy); for (unsigned i = 0, e = expansionTy->getNumElements(); i != e; ++i) { auto fieldOffset = Size(layout->getElementOffset(i)); diff --git a/lib/IRGen/GenConcurrency.cpp b/lib/IRGen/GenConcurrency.cpp index 428066d348d0c..db73ce029953a 100644 --- a/lib/IRGen/GenConcurrency.cpp +++ b/lib/IRGen/GenConcurrency.cpp @@ -472,7 +472,7 @@ static llvm::Value *addOptionRecord(IRGenFunction &IGF, } /// Add a task option record to the options list if the given value -/// is presernt. +/// is present. template static llvm::Value *maybeAddOptionRecord(IRGenFunction &IGF, llvm::Value *curRecordPointer, @@ -645,15 +645,15 @@ struct TaskGroupRecordTraits { } }; -struct InitialTaskExecutorRecordTraits { +struct InitialTaskExecutorUnownedRecordTraits { static StringRef getLabel() { - return "task_executor"; + return "task_executor_unowned"; } static llvm::StructType *getRecordType(IRGenModule &IGM) { - return IGM.SwiftInitialTaskExecutorPreferenceTaskOptionRecordTy; + return IGM.SwiftInitialTaskExecutorUnownedPreferenceTaskOptionRecordTy; } static TaskOptionRecordFlags getRecordFlags() { - return TaskOptionRecordFlags(TaskOptionRecordKind::InitialTaskExecutor); + return TaskOptionRecordFlags(TaskOptionRecordKind::InitialTaskExecutorUnowned); } static CanType getValueType(ASTContext &ctx) { return ctx.TheExecutorType; @@ -670,6 +670,36 @@ struct InitialTaskExecutorRecordTraits { } }; +struct InitialTaskExecutorOwnedRecordTraits { + static StringRef getLabel() { + return "task_executor_owned"; + } + static llvm::StructType *getRecordType(IRGenModule &IGM) { + return IGM.SwiftInitialTaskExecutorOwnedPreferenceTaskOptionRecordTy; + } + static TaskOptionRecordFlags getRecordFlags() { + return TaskOptionRecordFlags(TaskOptionRecordKind::InitialTaskExecutorOwned); + } + static CanType getValueType(ASTContext &ctx) { + return OptionalType::get(ctx.getProtocol(KnownProtocolKind::TaskExecutor) + ->getDeclaredInterfaceType()) + ->getCanonicalType(); + } + + void initialize(IRGenFunction &IGF, Address recordAddr, + Explosion &taskExecutor) const { + auto executorRecord = + IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize()); + + // This relies on the fact that the HeapObject is directly followed by a + // pointer to the witness table. + IGF.Builder.CreateStore(taskExecutor.claimNext(), + IGF.Builder.CreateStructGEP(executorRecord, 0, Size())); + IGF.Builder.CreateStore(taskExecutor.claimNext(), + IGF.Builder.CreateStructGEP(executorRecord, 1, Size())); + } +}; + } // end anonymous namespace static llvm::Value * @@ -693,15 +723,25 @@ maybeAddInitialTaskExecutorOptionRecord(IRGenFunction &IGF, llvm::Value *prevOptions, OptionalExplosion &taskExecutor) { return maybeAddOptionRecord(IGF, prevOptions, - InitialTaskExecutorRecordTraits(), + InitialTaskExecutorUnownedRecordTraits(), taskExecutor); } +static llvm::Value * +maybeAddInitialTaskExecutorOwnedOptionRecord(IRGenFunction &IGF, + llvm::Value *prevOptions, + OptionalExplosion &taskExecutorExistential) { + return maybeAddOptionRecord(IGF, prevOptions, + InitialTaskExecutorOwnedRecordTraits(), + taskExecutorExistential); +} + std::pair irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags, OptionalExplosion &serialExecutor, OptionalExplosion &taskGroup, - OptionalExplosion &taskExecutor, + OptionalExplosion &taskExecutorUnowned, + OptionalExplosion &taskExecutorExistential, Explosion &taskFunction, SubstitutionMap subs) { llvm::Value *taskOptions = @@ -729,8 +769,14 @@ irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags, taskOptions = maybeAddTaskGroupOptionRecord(IGF, taskOptions, taskGroup); // Add an option record for the initial task executor, if present. - taskOptions = - maybeAddInitialTaskExecutorOptionRecord(IGF, taskOptions, taskExecutor); + { + // Deprecated: This is the UnownedTaskExecutor? which is NOT consuming + taskOptions = maybeAddInitialTaskExecutorOptionRecord( + IGF, taskOptions, taskExecutorUnowned); + // Take an (any TaskExecutor)? which we retain until task has completed + taskOptions = maybeAddInitialTaskExecutorOwnedOptionRecord( + IGF, taskOptions, taskExecutorExistential); + } // In embedded Swift, create and pass result type info. taskOptions = maybeAddEmbeddedSwiftResultTypeInfo(IGF, taskOptions, resultType); diff --git a/lib/IRGen/GenConcurrency.h b/lib/IRGen/GenConcurrency.h index 0fbb5169445fc..ec4bc110118b7 100644 --- a/lib/IRGen/GenConcurrency.h +++ b/lib/IRGen/GenConcurrency.h @@ -104,7 +104,8 @@ std::pair emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags, OptionalExplosion &initialExecutor, OptionalExplosion &taskGroup, - OptionalExplosion &taskExecutor, + OptionalExplosion &taskExecutorUnowned, + OptionalExplosion &taskExecutorExistential, Explosion &taskFunction, SubstitutionMap subs); diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp index 51cdc11bf7ec1..8c24577a74e99 100644 --- a/lib/IRGen/GenOpaque.cpp +++ b/lib/IRGen/GenOpaque.cpp @@ -656,7 +656,14 @@ void IRGenFunction::emitDeallocateDynamicAlloca(StackAddress address, // NOTE: llvm does not support dynamic allocas in coroutines. auto allocToken = address.getExtraInfo(); - assert(allocToken && "dynamic alloca in coroutine without alloc token?"); + if (!allocToken) { +#ifndef NDEBUG + auto *alloca = cast(address.getAddress().getAddress()); + assert(isa(alloca->getArraySize()) && + "Dynamic alloca without a token?!"); +#endif + return; + } Builder.CreateIntrinsicCall(llvm::Intrinsic::coro_alloca_free, allocToken); return; } diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 0d9b66255f1ea..2811c362d3370 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -708,11 +708,16 @@ IRGenModule::IRGenModule(IRGenerator &irgen, SwiftTaskOptionRecordTy, // Base option record SwiftExecutorTy, // Executor }); - SwiftInitialTaskExecutorPreferenceTaskOptionRecordTy = + SwiftInitialTaskExecutorUnownedPreferenceTaskOptionRecordTy = createStructType(*this, "swift.task_executor_task_option", { SwiftTaskOptionRecordTy, // Base option record SwiftExecutorTy, // Executor }); + SwiftInitialTaskExecutorOwnedPreferenceTaskOptionRecordTy = + createStructType(*this, "swift.task_executor_owned_task_option", { + SwiftTaskOptionRecordTy, // Base option record + SwiftExecutorTy, // Executor + }); SwiftJobTy = createStructType(*this, "swift.job", { RefCountedStructTy, // object header Int8PtrTy, Int8PtrTy, // SchedulerPrivate @@ -1963,12 +1968,14 @@ bool IRGenModule::finalize() { } emitLazyPrivateDefinitions(); - // Finalize clang IR-generation. - finalizeClangCodeGen(); - + // Finalize Swift debug info before running Clang codegen, because it may + // delete the llvm module. if (DebugInfo) DebugInfo->finalize(); + // Finalize clang IR-generation. + finalizeClangCodeGen(); + // If that failed, report failure up and skip the final clean-up. if (!ClangCodeGen->GetModule()) return false; diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 9b1e8bf8386d8..c3820bf9e7106 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -821,7 +821,8 @@ class IRGenModule { llvm::StructType *SwiftTaskOptionRecordTy; llvm::StructType *SwiftInitialSerialExecutorTaskOptionRecordTy; llvm::StructType *SwiftTaskGroupTaskOptionRecordTy; - llvm::StructType *SwiftInitialTaskExecutorPreferenceTaskOptionRecordTy; + llvm::StructType *SwiftInitialTaskExecutorUnownedPreferenceTaskOptionRecordTy; + llvm::StructType *SwiftInitialTaskExecutorOwnedPreferenceTaskOptionRecordTy; llvm::StructType *SwiftResultTypeInfoTaskOptionRecordTy; llvm::PointerType *SwiftJobPtrTy; llvm::IntegerType *ExecutorFirstTy; diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index d5808be6d7de6..81aab201d0cbc 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -3559,6 +3559,11 @@ static llvm::Value *getStackAllocationSize(IRGenSILFunction &IGF, result = IGF.Builder.CreateMul(capacity, stride); } + if (auto constResult = dyn_cast(result)) { + if (!constResult->getUniqueInteger().isZero()) + return constResult; + } + // If the caller requests a zero-byte allocation, allocate one byte instead // to ensure that the resulting pointer is valid and unique on the stack. return IGF.Builder.CreateIntrinsicCall(llvm::Intrinsic::umax, @@ -3601,6 +3606,14 @@ static void emitBuiltinStackAlloc(IRGenSILFunction &IGF, IGF, i->getOperand(0), i->getOperand(1), loc); auto align = getStackAllocationAlignment(IGF, i->getOperand(2), loc); + // Emit a static alloca if the size is constant. + if (auto *constSize = dyn_cast(size)) { + auto stackAddress = IGF.createAlloca(IGF.IGM.Int8Ty, constSize, align, + "temp_alloc"); + IGF.setLoweredStackAddress(i, {stackAddress}); + return; + } + auto stackAddress = IGF.emitDynamicAlloca(IGF.IGM.Int8Ty, size, align, false, "temp_alloc"); IGF.setLoweredStackAddress(i, stackAddress); @@ -3620,14 +3633,18 @@ static void emitBuiltinStackDealloc(IRGenSILFunction &IGF, static void emitBuiltinCreateAsyncTask(IRGenSILFunction &IGF, swift::BuiltinInst *i) { + assert(i->getOperandValues().size() == 6 && + "createAsyncTask needs 6 operands"); auto flags = IGF.getLoweredSingletonExplosion(i->getOperand(0)); auto serialExecutor = IGF.getLoweredOptionalExplosion(i->getOperand(1)); auto taskGroup = IGF.getLoweredOptionalExplosion(i->getOperand(2)); - auto taskExecutor = IGF.getLoweredOptionalExplosion(i->getOperand(3)); - Explosion taskFunction = IGF.getLoweredExplosion(i->getOperand(4)); + auto taskExecutorUnowned = IGF.getLoweredOptionalExplosion(i->getOperand(3)); + auto taskExecutorOwned = IGF.getLoweredOptionalExplosion(i->getOperand(4)); + Explosion taskFunction = IGF.getLoweredExplosion(i->getOperand(5)); auto taskAndContext = - emitTaskCreate(IGF, flags, serialExecutor, taskGroup, taskExecutor, + emitTaskCreate(IGF, flags, serialExecutor, taskGroup, + taskExecutorUnowned, taskExecutorOwned, taskFunction, i->getSubstitutions()); Explosion out; out.add(taskAndContext.first); @@ -5109,6 +5126,7 @@ void IRGenSILFunction::visitCondBranchInst(swift::CondBranchInst *i) { } void IRGenSILFunction::visitRetainValueInst(swift::RetainValueInst *i) { + assert(!i->getOperand()->getType().isMoveOnly()); Explosion in = getLoweredExplosion(i->getOperand()); Explosion out; cast(getTypeInfo(i->getOperand()->getType())) @@ -5119,6 +5137,7 @@ void IRGenSILFunction::visitRetainValueInst(swift::RetainValueInst *i) { void IRGenSILFunction::visitRetainValueAddrInst(swift::RetainValueAddrInst *i) { SILValue operandValue = i->getOperand(); + assert(!operandValue->getType().isMoveOnly()); Address addr = getLoweredAddress(operandValue); SILType addrTy = operandValue->getType(); SILType objectT = addrTy.getObjectType(); diff --git a/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift b/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift index d82a8fce8b1bd..17feebbcf82f9 100644 --- a/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/DistributedResolvableMacro.swift @@ -104,7 +104,7 @@ extension DistributedResolvableMacro { static func stubFunctionBody() -> DeclSyntax { """ - if #available(SwiftStdlib 6.0, *) { + if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { Distributed._distributedStubFatalError() } else { fatalError() diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 068c2be02cab8..f5a707570878b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2456,7 +2456,7 @@ Parser::parseDocumentationAttribute(SourceLoc atLoc, SourceLoc loc) { StringRef finalMetadata = metadata.value_or(""); return makeParserResult( - new (Context) DocumentationAttr(loc, range, finalMetadata, + new (Context) DocumentationAttr(atLoc, range, finalMetadata, visibility, false)); } @@ -5122,10 +5122,16 @@ ParserStatus Parser::parseLifetimeDependenceSpecifiers( Identifier paramName; auto paramLoc = consumeIdentifier(paramName, /*diagnoseDollarPrefix=*/false); - specifierList.push_back( - LifetimeDependenceSpecifier:: - getNamedLifetimeDependenceSpecifier( - paramLoc, lifetimeDependenceKind, paramName)); + if (paramName.is("immortal")) { + specifierList.push_back( + LifetimeDependenceSpecifier:: + getImmortalLifetimeDependenceSpecifier(paramLoc)); + } else { + specifierList.push_back( + LifetimeDependenceSpecifier:: + getNamedLifetimeDependenceSpecifier( + paramLoc, lifetimeDependenceKind, paramName)); + } break; } case tok::integer_literal: { diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp index 278eb0b08e1c6..d768f9f43f3db 100644 --- a/lib/Parse/ParseIfConfig.cpp +++ b/lib/Parse/ParseIfConfig.cpp @@ -843,10 +843,16 @@ Result Parser::parseIfConfigRaw( // Error in the condition; isActive = false; isVersionCondition = false; - } else if (!foundActive && shouldEvaluate) { + } else if (!foundActive) { // Evaluate the condition only if we haven't found any active one and // we're not in parse-only mode. - isActive = evaluateIfConfigCondition(Condition, Context); + if (shouldEvaluate) { + isActive = evaluateIfConfigCondition(Condition, Context); + } + // Determine isVersionCondition regardless of whether we're active. + // This is necessary in some edge cases, e.g. where we're in a nested, + // inactive #if block, and we encounter an inactive `#if compiler` check, + // as we have to explicitly skip parsing in such edge cases. isVersionCondition = isVersionIfConfigCondition(Condition); } } diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index 4ee647533c4b3..b93fa1a640d5a 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -1551,6 +1551,8 @@ bool Parser::canParseType() { consumeToken(); } else if (Tok.isContextualKeyword("each")) { consumeToken(); + } else if (Tok.isContextualKeyword("sending")) { + consumeToken(); } switch (Tok.getKind()) { diff --git a/lib/PrintAsClang/ModuleContentsWriter.cpp b/lib/PrintAsClang/ModuleContentsWriter.cpp index 1bc8e55811ced..7b5ec02b35757 100644 --- a/lib/PrintAsClang/ModuleContentsWriter.cpp +++ b/lib/PrintAsClang/ModuleContentsWriter.cpp @@ -20,6 +20,7 @@ #include "PrintSwiftToClangCoreScaffold.h" #include "SwiftToClangInteropContext.h" +#include "swift/AST/Decl.h" #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/ExistentialLayout.h" #include "swift/AST/Module.h" @@ -671,6 +672,15 @@ class ModuleWriter { llvm_unreachable("unknown top-level ObjC decl"); }; + // When we visit a function, we might also generate a thunk that calls into the + // implementation of structs/enums to get the opaque pointers. To avoid + // referencing these methods before we see the definition for the generated + // classes, we want to visit function definitions last. + if (isa(*rhs) && isa(*lhs)) + return Descending; + if (isa(*lhs) && isa(*rhs)) + return Ascending; + // Sort by names. int result = getSortName(*rhs).compare(getSortName(*lhs)); if (result != 0) @@ -700,9 +710,9 @@ class ModuleWriter { // even when the variable might not actually be emitted by the emitter. // In that case, order the function before the variable. if (isa(*rhs) && isa(*lhs)) - return 1; + return Descending; if (isa(*lhs) && isa(*rhs)) - return -1; + return Ascending; // Prefer value decls to extensions. assert(!(isa(*lhs) && isa(*rhs))); @@ -874,6 +884,11 @@ class ModuleWriter { // Emit an unavailable stub for a Swift type. if (auto *nmtd = dyn_cast(vd)) { auto representation = cxx_translation::getDeclRepresentation(vd); + if (nmtd->isGeneric()) { + auto genericSignature = + nmtd->getGenericSignature().getCanonicalSignature(); + ClangSyntaxPrinter(os).printGenericSignature(genericSignature); + } os << "class "; ClangSyntaxPrinter(os).printBaseName(vd); os << " { } SWIFT_UNAVAILABLE_MSG(\""; diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index a85ce54802d99..d73e4756cd921 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -31,6 +31,7 @@ #include "swift/IRGen/IRABIDetailsProvider.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "llvm/ADT/STLExtras.h" @@ -273,8 +274,13 @@ class CFunctionSignatureTypePrinter bool isInOutParam) { auto *cd = CT->getDecl(); if (cd->hasClangNode()) { - ClangSyntaxPrinter(os).printClangTypeReference(cd->getClangDecl()); - os << " *" + const auto *clangDecl = cd->getClangDecl(); + ClangSyntaxPrinter(os).printClangTypeReference(clangDecl); + bool alreadyPointer = false; + if (const auto *typedefDecl = dyn_cast(clangDecl)) + if (importer::isCFTypeDecl(typedefDecl)) + alreadyPointer = true; + os << (alreadyPointer ? " " : " *") << (!optionalKind || *optionalKind == OTK_None ? "_Nonnull" : "_Nullable"); if (isInOutParam) { @@ -713,6 +719,17 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature( if (kind == FunctionSignatureKind::CxxInlineThunk) ClangSyntaxPrinter(os).printGenericSignature(Signature); } + if (const auto *enumDecl = FD->getDeclContext()->getSelfEnumDecl()) { + // We cannot emit functions with the same name as an enum case yet, the resulting header + // does not compiler. + // FIXME: either do not emit cases as inline members, or rename the cases or the + // colliding functions. + for (const auto *enumElement : enumDecl->getAllElements()) { + auto elementName = enumElement->getName(); + if (!elementName.isSpecial() && elementName.getBaseIdentifier().is(name)) + return ClangRepresentation::unsupported; + } + } auto emittedModule = FD->getModuleContext(); OutputLanguageMode outputLang = kind == FunctionSignatureKind::CFunctionProto ? OutputLanguageMode::ObjC @@ -1521,7 +1538,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod( auto result = printFunctionSignature( FD, signature, cxx_translation::getNameForCxx(FD), resultTy, FunctionSignatureKind::CxxInlineThunk, modifiers); - assert(!result.isUnsupported() && "C signature should be unsupported too"); + if (result.isUnsupported()) + return; declAndTypePrinter.printAvailability(os, FD); if (!isDefinition) { diff --git a/lib/Refactoring/SyntacticRenameRangeDetails.cpp b/lib/Refactoring/SyntacticRenameRangeDetails.cpp index 1e36c85c6c646..b22820f789349 100644 --- a/lib/Refactoring/SyntacticRenameRangeDetails.cpp +++ b/lib/Refactoring/SyntacticRenameRangeDetails.cpp @@ -146,6 +146,18 @@ void RenameRangeDetailCollector::splitAndRenameLabel(CharSourceRange Range, return splitAndRenameCallArg(Range, NameIndex); case LabelRangeType::Param: return splitAndRenameParamLabel(Range, NameIndex, /*IsCollapsible=*/true); + case LabelRangeType::EnumCaseParam: + if (Range.getByteLength() == 0) { + // If the associated value currently doesn't have a label, emit a + // `CallArgumentCombined` range, which will cause a new label followed by + // `:` to be inserted in the same fashion that call arguments get inserted + // to calls + return addRenameRange(Range, RefactoringRangeKind::CallArgumentCombined, NameIndex); + } else { + // If the associated value has a label already, we are in the same case as + // function parameters. + return splitAndRenameParamLabel(Range, NameIndex, /*IsCollapsible=*/true); + } case LabelRangeType::NoncollapsibleParam: return splitAndRenameParamLabel(Range, NameIndex, /*IsCollapsible=*/false); @@ -248,6 +260,7 @@ bool RenameRangeDetailCollector::labelRangeMatches(CharSourceRange Range, LLVM_FALLTHROUGH; case LabelRangeType::CallArg: case LabelRangeType::Param: + case LabelRangeType::EnumCaseParam: case LabelRangeType::CompoundName: return ExistingLabel == (Expected.empty() ? "_" : Expected); case LabelRangeType::None: diff --git a/lib/SIL/IR/Linker.cpp b/lib/SIL/IR/Linker.cpp index fffa14f3cd976..415c4b8ba1ede 100644 --- a/lib/SIL/IR/Linker.cpp +++ b/lib/SIL/IR/Linker.cpp @@ -59,6 +59,7 @@ #include "llvm/Support/Debug.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SubstitutionMap.h" +#include "swift/Basic/Require.h" #include "swift/ClangImporter/ClangModule.h" #include "swift/SIL/FormalLinkage.h" #include "swift/Serialization/SerializedSILLoader.h" @@ -101,9 +102,9 @@ void SILLinkerVisitor::deserializeAndPushToWorklist(SILFunction *F) { void SILLinkerVisitor::maybeAddFunctionToWorklist( SILFunction *F, SerializedKind_t callerSerializedKind) { SILLinkage linkage = F->getLinkage(); - assert((callerSerializedKind == IsNotSerialized || - F->hasValidLinkageForFragileRef(callerSerializedKind) || - hasSharedVisibility(linkage) || F->isExternForwardDeclaration()) && + require(callerSerializedKind == IsNotSerialized || + F->hasValidLinkageForFragileRef(callerSerializedKind) || + hasSharedVisibility(linkage) || F->isExternForwardDeclaration(), "called function has wrong linkage for serialized function"); if (!F->isExternalDeclaration()) { // The function is already in the module, so no need to de-serialized it. diff --git a/lib/SIL/IR/OperandOwnership.cpp b/lib/SIL/IR/OperandOwnership.cpp index 8025bc44fdca0..b66caf165213b 100644 --- a/lib/SIL/IR/OperandOwnership.cpp +++ b/lib/SIL/IR/OperandOwnership.cpp @@ -907,6 +907,8 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, EndAsyncLetLifetime) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, CreateTaskGroup) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, CreateTaskGroupWithFlags) BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, DestroyTaskGroup) +BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, FlowSensitiveSelfIsolation) +BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, FlowSensitiveDistributedSelfIsolation) BUILTIN_OPERAND_OWNERSHIP(ForwardingConsume, COWBufferForReading) @@ -928,6 +930,12 @@ ::visitStartAsyncLetWithLocalBuffer(BuiltinInst *bi, StringRef attr) { OperandOwnership OperandOwnershipBuiltinClassifier::visitCreateAsyncTask(BuiltinInst *bi, StringRef attr) { + if (&op == &bi->getOperandRef(4)) { + // The (any TaskExecutor)? (optional) must be consumed by the builtin, + // as we will keep it alive and later destroy it as the task runs to completion. + return OperandOwnership::ForwardingConsume; + } + // The function operand is consumed by the new task. if (&op == &bi->getArgumentOperands().back()) return OperandOwnership::DestroyingConsume; diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index cbf747d547890..e6fc550504118 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -464,7 +464,9 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) { return Limit::OnDemand; case Kind::GlobalAccessor: - return cast(d)->isStrictlyResilient() ? Limit::NeverPublic : Limit::None; + // global unsafeMutableAddressor should be kept hidden if its decl + // is resilient. + return cast(d)->isResilient() ? Limit::NeverPublic : Limit::None; case Kind::DefaultArgGenerator: // If the default argument is to be serialized, only use non-ABI public diff --git a/lib/SIL/IR/SILType.cpp b/lib/SIL/IR/SILType.cpp index d223556c64b4a..4a7747adcdccb 100644 --- a/lib/SIL/IR/SILType.cpp +++ b/lib/SIL/IR/SILType.cpp @@ -450,6 +450,11 @@ bool SILType::isAddressOnly(const SILFunction &F) const { return F.getTypeLowering(contextType).isAddressOnly(); } +bool SILType::isFixedABI(const SILFunction &F) const { + auto contextType = hasTypeParameter() ? F.mapTypeIntoContext(*this) : *this; + return F.getTypeLowering(contextType).isFixedABI(); +} + SILType SILType::substGenericArgs(SILModule &M, SubstitutionMap SubMap, TypeExpansionContext context) const { auto fnTy = castTo(); @@ -1266,7 +1271,7 @@ SILType SILType::addingMoveOnlyWrapperToBoxedType(const SILFunction *fn) { return SILType::getPrimitiveObjectType(newBoxType); } -SILType SILType::removingMoveOnlyWrapperToBoxedType(const SILFunction *fn) { +SILType SILType::removingMoveOnlyWrapperFromBoxedType(const SILFunction *fn) { auto boxTy = castTo(); auto *oldLayout = boxTy->getLayout(); auto oldField = oldLayout->getFields()[0]; @@ -1284,6 +1289,17 @@ SILType SILType::removingMoveOnlyWrapperToBoxedType(const SILFunction *fn) { return SILType::getPrimitiveObjectType(newBoxType); } +SILType SILType::removingAnyMoveOnlyWrapping(const SILFunction *fn) { + if (!isMoveOnlyWrapped() && !isBoxedMoveOnlyWrappedType(fn)) + return *this; + + if (isMoveOnlyWrapped()) + return removingMoveOnlyWrapper(); + + assert(isBoxedMoveOnlyWrappedType(fn)); + return removingMoveOnlyWrapperFromBoxedType(fn); +} + bool SILType::isSendable(SILFunction *fn) const { return getASTType()->isSendableType(); } diff --git a/lib/SIL/IR/ValueOwnership.cpp b/lib/SIL/IR/ValueOwnership.cpp index 335b17e4cab95..0d3509365d56f 100644 --- a/lib/SIL/IR/ValueOwnership.cpp +++ b/lib/SIL/IR/ValueOwnership.cpp @@ -630,6 +630,8 @@ CONSTANT_OWNERSHIP_BUILTIN(None, CreateTaskGroup) CONSTANT_OWNERSHIP_BUILTIN(None, CreateTaskGroupWithFlags) CONSTANT_OWNERSHIP_BUILTIN(None, DestroyTaskGroup) CONSTANT_OWNERSHIP_BUILTIN(None, TaskRunInline) +CONSTANT_OWNERSHIP_BUILTIN(Owned, FlowSensitiveSelfIsolation) +CONSTANT_OWNERSHIP_BUILTIN(Owned, FlowSensitiveDistributedSelfIsolation) CONSTANT_OWNERSHIP_BUILTIN(None, GetEnumTag) CONSTANT_OWNERSHIP_BUILTIN(None, InjectEnumTag) CONSTANT_OWNERSHIP_BUILTIN(Owned, DistributedActorAsAnyActor) diff --git a/lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp b/lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp index 837e575fc9273..c90701d0bbaae 100644 --- a/lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp +++ b/lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp @@ -164,6 +164,12 @@ SubElementOffset::computeForAddress(SILValue projectionDerivedFromRoot, continue; } + if (auto *iea = + dyn_cast(projectionDerivedFromRoot)) { + projectionDerivedFromRoot = iea->getOperand(); + continue; + } + if (auto *teai = dyn_cast(projectionDerivedFromRoot)) { SILType tupleType = teai->getOperand()->getType(); diff --git a/lib/SIL/Utils/InstructionUtils.cpp b/lib/SIL/Utils/InstructionUtils.cpp index b3cc52ef3d5f1..145ad02ae6e4c 100644 --- a/lib/SIL/Utils/InstructionUtils.cpp +++ b/lib/SIL/Utils/InstructionUtils.cpp @@ -618,7 +618,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) case SILInstructionKind::StructElementAddrInst: case SILInstructionKind::IndexAddrInst: // TODO: hasArchetype() ? - if (!inst->getOperand(0)->getType().isLoadable(*inst->getFunction())) { + if (!inst->getOperand(0)->getType().isFixedABI(*inst->getFunction())) { impactType = inst->getOperand(0)->getType(); return RuntimeEffect::MetaData; } diff --git a/lib/SIL/Utils/OSSALifetimeCompletion.cpp b/lib/SIL/Utils/OSSALifetimeCompletion.cpp index fa6cf09c53e4f..ba6a338431c29 100644 --- a/lib/SIL/Utils/OSSALifetimeCompletion.cpp +++ b/lib/SIL/Utils/OSSALifetimeCompletion.cpp @@ -168,21 +168,14 @@ class AvailabilityBoundaryVisitor { /// The value whose dead-end block lifetime ends are to be visited. SILValue value; - /// Whether to allow leaks. - /// - /// Here, that entails allowing walks to reach non-unreachable terminators and - /// not creating lifetime ends before them. - OSSALifetimeCompletion::AllowLeaks_t allowLeaks; - /// The non-lifetime-ending boundary of `value`. BasicBlockSet starts; /// The region between (inclusive) the `starts` and the unreachable blocks. BasicBlockSetVector region; public: - AvailabilityBoundaryVisitor(SILValue value, - OSSALifetimeCompletion::AllowLeaks_t allowLeaks) - : value(value), allowLeaks(allowLeaks), starts(value->getFunction()), + AvailabilityBoundaryVisitor(SILValue value) + : value(value), starts(value->getFunction()), region(value->getFunction()) {} using Visit = llvm::function_ref(block->getTerminator()) || allowLeaks); + assert(isa(block->getTerminator())); } for (auto *successor : block->getSuccessorBlocks()) { regionWorklist.pushIfNotVisited(successor); @@ -379,12 +369,6 @@ void AvailabilityBoundaryVisitor::visitAvailabilityBoundary( if (!block->succ_empty() && !hasUnavailableSuccessor()) { continue; } - if (allowLeaks && block->succ_empty() && - !isa(block->getTerminator())) { - // Availability extends to the end of a function-exiting-normally block. - // If leaks are allowed, don't visit. - continue; - } assert(hasUnavailableSuccessor() || isa(block->getTerminator())); visit(block->getTerminator(), @@ -394,10 +378,10 @@ void AvailabilityBoundaryVisitor::visitAvailabilityBoundary( } // end anonymous namespace void OSSALifetimeCompletion::visitAvailabilityBoundary( - SILValue value, AllowLeaks_t allowLeaks, const SSAPrunedLiveness &liveness, + SILValue value, const SSAPrunedLiveness &liveness, llvm::function_ref visit) { - AvailabilityBoundaryVisitor visitor(value, allowLeaks); + AvailabilityBoundaryVisitor visitor(value); AvailabilityBoundaryVisitor::Result result(value->getFunction()); visitor.visit(liveness, result, visit); @@ -410,12 +394,12 @@ void OSSALifetimeCompletion::visitAvailabilityBoundary( }); } -static bool endLifetimeAtAvailabilityBoundary( - SILValue value, OSSALifetimeCompletion::AllowLeaks_t allowLeaks, - const SSAPrunedLiveness &liveness) { +static bool +endLifetimeAtAvailabilityBoundary(SILValue value, + const SSAPrunedLiveness &liveness) { bool changed = false; OSSALifetimeCompletion::visitAvailabilityBoundary( - value, allowLeaks, liveness, [&](auto *unreachable, auto end) { + value, liveness, [&](auto *unreachable, auto end) { SILBuilderWithScope builder(unreachable); endOSSALifetime(value, end, builder); changed = true; @@ -442,12 +426,7 @@ bool OSSALifetimeCompletion::analyzeAndUpdateLifetime(SILValue value, changed |= endLifetimeAtLivenessBoundary(value, liveness.getLiveness()); break; case Boundary::Availability: - changed |= endLifetimeAtAvailabilityBoundary(value, DoNotAllowLeaks, - liveness.getLiveness()); - break; - case Boundary::AvailabilityWithLeaks: - changed |= endLifetimeAtAvailabilityBoundary(value, AllowLeaks, - liveness.getLiveness()); + changed |= endLifetimeAtAvailabilityBoundary(value, liveness.getLiveness()); break; } // TODO: Rebuild outer adjacent phis on demand (SILGen does not currently @@ -472,9 +451,7 @@ static FunctionTest OSSALifetimeCompletionTest( arguments.takeString()) .Case("liveness", OSSALifetimeCompletion::Boundary::Liveness) .Case("availability", - OSSALifetimeCompletion::Boundary::Availability) - .Case("availability_with_leaks", - OSSALifetimeCompletion::Boundary::AvailabilityWithLeaks); + OSSALifetimeCompletion::Boundary::Availability); llvm::outs() << "OSSA lifetime completion on " << kind << " boundary: " << value; OSSALifetimeCompletion completion(&function, /*domInfo*/ nullptr); diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index cee5db011b5ef..d4cecf02173bf 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -2383,8 +2383,8 @@ class SILVerifier : public SILVerifierBase { if (builtinKind == BuiltinValueKind::CreateAsyncTask) { requireType(BI->getType(), _object(_tuple(_nativeObject, _rawPointer)), "result of createAsyncTask"); - require(arguments.size() == 5, - "createAsyncTask expects five arguments"); + require(arguments.size() == 6, + "createAsyncTask expects six arguments"); requireType(arguments[0]->getType(), _object(_swiftInt), "first argument of createAsyncTask"); requireType(arguments[1]->getType(), _object(_optional(_executor)), @@ -2393,7 +2393,18 @@ class SILVerifier : public SILVerifierBase { "third argument of createAsyncTask"); requireType(arguments[3]->getType(), _object(_optional(_executor)), "fourth argument of createAsyncTask"); - auto fnType = requireObjectType(SILFunctionType, arguments[4], + if (F.getASTContext().getProtocol(swift::KnownProtocolKind::TaskExecutor)) { + requireType(arguments[4]->getType(), + _object(_optional(_existential(_taskExecutor))), + "fifth argument of createAsyncTask"); + } else { + // This is just a placeholder type for being able to pass 'nil' for it + // with SDKs which do not have the TaskExecutor type. + requireType(arguments[4]->getType(), + _object(_optional(_executor)), + "fifth argument of createAsyncTask"); + } + auto fnType = requireObjectType(SILFunctionType, arguments[5], "result of createAsyncTask"); auto expectedExtInfo = SILExtInfoBuilder().withAsync(true).withSendable(true).build(); @@ -6548,9 +6559,11 @@ class SILVerifier : public SILVerifierBase { "Operand value should be an object"); require(cvt->getOperand()->getType().isBoxedMoveOnlyWrappedType(cvt->getFunction()), "Operand should be move only wrapped"); - require(cvt->getType() == - cvt->getOperand()->getType().removingMoveOnlyWrapperToBoxedType(cvt->getFunction()), - "Result and operand must have the same type, today."); + require( + cvt->getType() == + cvt->getOperand()->getType().removingMoveOnlyWrapperFromBoxedType( + cvt->getFunction()), + "Result and operand must have the same type, today."); } void checkCopyableToMoveOnlyWrapperValueInst( diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 2eb9dbf3b97c7..f4f0c292e110f 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -1886,6 +1886,11 @@ static void emitRawApply(SILGenFunction &SGF, SILValue indirectErrorAddr, SmallVectorImpl &rawResults, ExecutorBreadcrumb prevExecutor) { + // We completely drop the generic signature if all generic parameters were + // concrete. + if (subs && subs.getGenericSignature()->areAllParamsConcrete()) + subs = SubstitutionMap(); + SILFunctionConventions substFnConv(substFnType, SGF.SGM.M); // Get the callee value. bool isConsumed = substFnType->isCalleeConsumed(); @@ -5857,6 +5862,11 @@ SILValue SILGenFunction::emitApplyWithRethrow(SILLocation loc, SILValue fn, SILType substFnType, SubstitutionMap subs, ArrayRef args) { + // We completely drop the generic signature if all generic parameters were + // concrete. + if (subs && subs.getGenericSignature()->areAllParamsConcrete()) + subs = SubstitutionMap(); + CanSILFunctionType silFnType = substFnType.castTo(); SILFunctionConventions fnConv(silFnType, SGM.M); SILType resultType = fnConv.getSILResultType(getTypeExpansionContext()); @@ -6858,22 +6868,21 @@ bool AccessorBaseArgPreparer::shouldLoadBaseAddress() const { ArgumentSource AccessorBaseArgPreparer::prepareAccessorAddressBaseArg() { // If the base is currently an address, we may have to copy it. if (shouldLoadBaseAddress()) { - if (selfParam.isConsumed() || - (base.getType().isAddressOnly(SGF.F) - // If a move-only base is borrowed, then we have to try our best to - // borrow it in-place without copying. - // TODO: Can we avoid copying a non-move-only value too in this - // circumstance? - && !base.getType().isMoveOnly())) { + if (selfParam.isConsumed() || base.getType().isAddressOnly(SGF.F)) { // The load can only be a take if the base is a +1 rvalue. auto shouldTake = IsTake_t(base.hasCleanup()); + auto isGuaranteed = selfParam.isGuaranteed(); + + auto context = + isGuaranteed ? SGFContext::AllowImmediatePlusZero : SGFContext(); + base = SGF.emitFormalAccessLoad(loc, base.forward(SGF), SGF.getTypeLowering(baseLoweredType), - SGFContext(), shouldTake); + context, shouldTake, isGuaranteed); return ArgumentSource(loc, RValue(SGF, loc, baseFormalType, base)); } - + // If the type is address-only, we can borrow the memory location as is. if (base.getType().isAddressOnly(SGF.F)) { return ArgumentSource(loc, RValue(SGF, loc, baseFormalType, base)); diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index f0f7ba95519a1..2654527ec85f7 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -1514,7 +1514,7 @@ SILFunction *SILGenFunction::emitNativeAsyncToForeignThunk(SILDeclRef thunk) { .withAsync() .withSendable() .build(); - auto closureTy = objcFnTy->getWithExtInfo(closureExtInfo); + auto closureTy = objcInfo.SILFnType->getWithExtInfo(closureExtInfo); SmallString<64> closureName(F.getName().begin(), F.getName().end()); // Trim off the thunk suffix and mangle this like a closure nested inside the @@ -1535,7 +1535,7 @@ SILFunction *SILGenFunction::emitNativeAsyncToForeignThunk(SILDeclRef thunk) { IsNotDistributed, IsNotRuntimeAccessible); auto closureRef = B.createFunctionRef(loc, closure); - + auto closureVal = B.createPartialApply(loc, closureRef, subs, closureArgs, ParameterConvention::Direct_Guaranteed); @@ -1575,15 +1575,17 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) { } } + // Use the same generic environment as the native entry point. + // We need to set this before we can call things like + // F.getForwardingSubstitutionMap(). + F.setGenericEnvironment(SGM.Types.getConstantGenericEnvironment(native)); + auto nativeInfo = getConstantInfo(getTypeExpansionContext(), native); auto subs = F.getForwardingSubstitutionMap(); auto substTy = nativeInfo.SILFnType->substGenericArgs( SGM.M, subs, getTypeExpansionContext()); SILFunctionConventions substConv(substTy, SGM.M); - // Use the same generic environment as the native entry point. - F.setGenericEnvironment(SGM.Types.getConstantGenericEnvironment(native)); - auto loc = thunk.getAsRegularLocation(); loc.markAutoGenerated(); Scope scope(Cleanups, CleanupLocation(loc)); @@ -1848,6 +1850,13 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) { // The immediate function result is an empty tuple. return SILUndef::get(&F, SGM.Types.getEmptyTupleType()); }; + + // If the function we're calling isn't actually polymorphic, drop the + // substitutions. This should only happen in concrete specializations. + if (subs && !nativeFn->getType().castTo()->isPolymorphic()) { + assert(subs.getGenericSignature()->areAllParamsConcrete()); + subs = SubstitutionMap(); + } if (!substTy->hasErrorResult()) { // Create the apply. diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp index bcbe3332560a9..059ed94bb984a 100644 --- a/lib/SILGen/SILGenBuiltin.cpp +++ b/lib/SILGen/SILGenBuiltin.cpp @@ -1595,7 +1595,7 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc, } }(); - ManagedValue taskExecutor = [&] { + ManagedValue taskExecutorDeprecated = [&] { if (options & CreateTaskOptions::OptionalEverything) { return nextArg().getAsSingleValue(SGF); } else if (options & CreateTaskOptions::TaskExecutor) { @@ -1604,6 +1604,19 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc, return emitOptionalNone(ctx.TheExecutorType); } }(); + ManagedValue taskExecutorConsuming = [&] { + if (options & CreateTaskOptions::OptionalEverything) { + return nextArg().getAsSingleValue(SGF); + } else if (auto theTaskExecutorProto = ctx.getProtocol(KnownProtocolKind::TaskExecutor)) { + return emitOptionalNone(theTaskExecutorProto->getDeclaredExistentialType() + ->getCanonicalType()); + } else { + // This builtin executor type here is just a placeholder type for being + // able to pass 'nil' for it with SDKs which do not have the TaskExecutor + // type. + return emitOptionalNone(ctx.TheExecutorType); + } + }(); auto functionValue = [&] { // No reabstraction required. @@ -1659,7 +1672,8 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc, flags.getUnmanagedValue(), initialExecutor.getUnmanagedValue(), taskGroup.getUnmanagedValue(), - taskExecutor.getUnmanagedValue(), + taskExecutorDeprecated.getUnmanagedValue(), + taskExecutorConsuming.forward(SGF), functionValue.forward(SGF) }; diff --git a/lib/SILGen/SILGenDestructor.cpp b/lib/SILGen/SILGenDestructor.cpp index 0fe3d83a5d88c..b8cb75c75f43f 100644 --- a/lib/SILGen/SILGenDestructor.cpp +++ b/lib/SILGen/SILGenDestructor.cpp @@ -118,9 +118,16 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) { SILValue baseSelf = B.createUpcast(cleanupLoc, selfValue, baseSILTy); ManagedValue dtorValue; SILType dtorTy; + auto subMap = superclassTy->getContextSubstitutionMap(SGM.M.getSwiftModule(), superclass); + + // We completely drop the generic signature if all generic parameters were + // concrete. + if (subMap && subMap.getGenericSignature()->areAllParamsConcrete()) + subMap = SubstitutionMap(); + std::tie(dtorValue, dtorTy) = emitSiblingMethodRef(cleanupLoc, baseSelf, dtorConstant, subMap); @@ -191,12 +198,11 @@ void SILGenFunction::emitDeallocatingClassDestructor(DestructorDecl *dd) { // Form a reference to the destroying destructor. SILDeclRef dtorConstant(dd, SILDeclRef::Kind::Destroyer); auto classTy = initialSelfValue->getType(); - auto classDecl = classTy.getASTType()->getAnyNominal(); + + auto subMap = F.getForwardingSubstitutionMap(); + ManagedValue dtorValue; SILType dtorTy; - auto subMap = classTy.getASTType() - ->getContextSubstitutionMap(SGM.M.getSwiftModule(), - classDecl); std::tie(dtorValue, dtorTy) = emitSiblingMethodRef(loc, initialSelfValue, dtorConstant, subMap); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 468f9b422800f..3abee825016bd 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -31,6 +31,7 @@ #include "swift/AST/CanTypeVisitor.h" #include "swift/AST/Decl.h" #include "swift/AST/DiagnosticsCommon.h" +#include "swift/AST/DistributedDecl.h" #include "swift/AST/ExistentialLayout.h" #include "swift/AST/Expr.h" #include "swift/AST/ForeignErrorConvention.h" @@ -6743,6 +6744,56 @@ RValue RValueEmitter::visitMacroExpansionExpr(MacroExpansionExpr *E, RValue RValueEmitter::visitCurrentContextIsolationExpr( CurrentContextIsolationExpr *E, SGFContext C) { + // If we are in an actor initializer that is isolated to, the current context + // isolation flow-sensitive: before 'self' has been initialized, it will be + // nil. After 'self' has been initialized, it will be 'self'. Introduce a + // custom builtin that Definite Initialization will rewrite appropriately. + if (auto ctor = dyn_cast_or_null( + SGF.F.getDeclRef().getDecl())) { + auto isolation = getActorIsolation(ctor); + if (ctor->isDesignatedInit() && + isolation == ActorIsolation::ActorInstance && + isolation.getActorInstance() == ctor->getImplicitSelfDecl()) { + ASTContext &ctx = SGF.getASTContext(); + auto builtinName = ctx.getIdentifier( + isolation.isDistributedActor() + ? getBuiltinName(BuiltinValueKind::FlowSensitiveDistributedSelfIsolation) + : getBuiltinName(BuiltinValueKind::FlowSensitiveSelfIsolation)); + SILType resultTy = SGF.getLoweredType(E->getType()); + + auto injection = cast(E->getActor()); + ProtocolConformanceRef conformance; + Expr *origActorExpr; + if (isolation.isDistributedActor()) { + // Create a reference to the asLocalActor getter. + auto asLocalActorDecl = getDistributedActorAsLocalActorComputedProperty( + SGF.F.getDeclContext()->getParentModule()); + auto asLocalActorGetter = asLocalActorDecl->getAccessor(AccessorKind::Get); + SILDeclRef asLocalActorRef = SILDeclRef( + asLocalActorGetter, SILDeclRef::Kind::Func); + SGF.emitGlobalFunctionRef(E, asLocalActorRef); + + // Extract the base ('self') and the DistributedActor conformance. + auto memberRef = cast(injection->getSubExpr()); + conformance = memberRef->getDecl().getSubstitutions() + .getConformances()[0]; + origActorExpr = memberRef->getBase(); + } else { + auto erasure = cast(injection->getSubExpr()); + conformance = erasure->getConformances()[0]; + origActorExpr = erasure->getSubExpr(); + } + SGF.SGM.useConformance(conformance); + + SubstitutionMap subs = SubstitutionMap::getProtocolSubstitutions( + conformance.getRequirement(), origActorExpr->getType(), conformance); + auto origActor = SGF.maybeEmitValueOfLocalVarDecl( + ctor->getImplicitSelfDecl(), AccessKind::Read).getValue(); + auto call = SGF.B.createBuiltin(E, builtinName, resultTy, subs, origActor); + return RValue(SGF, E, ManagedValue::forForwardedRValue(SGF, call)); + } + } + return visit(E->getActor(), C); } diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 3a8e90bf1dcd2..de405a05206a1 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -987,7 +987,13 @@ SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant, constant, loweredCaptureInfo, subs); } - if (subs) { + // We completely drop the generic signature if all generic parameters were + // concrete. + if (!pft->isPolymorphic()) { + subs = SubstitutionMap(); + } else { + assert(!subs.getGenericSignature()->areAllParamsConcrete()); + auto specialized = pft->substGenericArgs(F.getModule(), subs, getTypeExpansionContext()); functionTy = SILType::getPrimitiveObjectType(specialized); diff --git a/lib/SILGen/SILGenGlobalVariable.cpp b/lib/SILGen/SILGenGlobalVariable.cpp index cc3f3ed79df3b..815efa5d5dd10 100644 --- a/lib/SILGen/SILGenGlobalVariable.cpp +++ b/lib/SILGen/SILGenGlobalVariable.cpp @@ -42,8 +42,8 @@ SILGlobalVariable *SILGenModule::getSILGlobalVariable(VarDecl *gDecl, // Get the linkage for SILGlobalVariable. FormalLinkage formalLinkage; - if (gDecl->isResilient() && - !gDecl->getModuleContext()->serializePackageEnabled()) + // sil_global linkage should be kept private if its decl is resilient. + if (gDecl->isResilient()) formalLinkage = FormalLinkage::Private; else formalLinkage = getDeclLinkage(gDecl); diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp index 3c183882bd187..b1a238ef3a9dd 100644 --- a/lib/SILGen/SILGenStmt.cpp +++ b/lib/SILGen/SILGenStmt.cpp @@ -323,7 +323,7 @@ void StmtEmitter::visitBraceStmt(BraceStmt *S) { // PatternBindingBecls represent local variable bindings that execute // as part of the function's execution. - if (!isa(D)) { + if (!isa(D) && !isa(D)) { // Other decls define entities that may be used by the program, such as // local function declarations. So handle them here, before checking for // reachability, and then continue looping. @@ -429,12 +429,9 @@ void StmtEmitter::visitBraceStmt(BraceStmt *S) { SGF.emitIgnoredExpr(E); } else { auto *D = ESD.get(); - - // Only PatternBindingDecls should be emitted here. - // Other decls were handled above. - auto PBD = cast(D); - - SGF.visit(PBD); + assert((isa(D) || isa(D)) && + "other decls should be handled before the reachability check"); + SGF.visit(D); } } } diff --git a/lib/SILOptimizer/Analysis/RegionAnalysis.cpp b/lib/SILOptimizer/Analysis/RegionAnalysis.cpp index 773bff7eca002..bd36c7abbe53b 100644 --- a/lib/SILOptimizer/Analysis/RegionAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/RegionAnalysis.cpp @@ -1584,7 +1584,8 @@ class PartitionOpTranslator { void translateSILMultiAssign(const TargetRange &resultValues, const SourceRange &sourceValues, - SILIsolationInfo resultIsolationInfoOverride = {}) { + SILIsolationInfo resultIsolationInfoOverride = {}, + bool requireSrcValues = true) { SmallVector assignOperands; SmallVector assignResults; @@ -1631,9 +1632,17 @@ class PartitionOpTranslator { } } - // Require all srcs. - for (auto src : assignOperands) - builder.addRequire(src); + // Require all srcs if we are supposed to. (By default we do). + // + // DISCUSSION: The reason that this may be useful is for special + // instructions like store_borrow. On the one hand, we want store_borrow to + // act like a store in the sense that we want to combine the regions of its + // src and dest... but at the same time, we do not want to treat the store + // itself as a use of its parent value. We want that to be any subsequent + // uses of the store_borrow. + if (requireSrcValues) + for (auto src : assignOperands) + builder.addRequire(src); // Merge all srcs. for (unsigned i = 1; i < assignOperands.size(); i++) { @@ -2082,12 +2091,17 @@ class PartitionOpTranslator { } template - void translateSILMerge(SILValue dest, Collection collection) { + void translateSILMerge(SILValue dest, Collection collection, + bool requireOperands = true) { auto trackableDest = tryToTrackValue(dest); if (!trackableDest) return; for (SILValue elt : collection) { if (auto trackableSrc = tryToTrackValue(elt)) { + if (requireOperands) { + builder.addRequire(trackableSrc->getRepresentative().getValue()); + builder.addRequire(trackableDest->getRepresentative().getValue()); + } builder.addMerge(trackableDest->getRepresentative().getValue(), trackableSrc->getRepresentative().getValue()); } @@ -2095,8 +2109,10 @@ class PartitionOpTranslator { } template <> - void translateSILMerge(SILValue dest, SILValue src) { - return translateSILMerge(dest, TinyPtrVector(src)); + void translateSILMerge(SILValue dest, SILValue src, + bool requireOperands) { + return translateSILMerge(dest, TinyPtrVector(src), + requireOperands); } void translateSILAssignmentToTransferringParameter(TrackableValue destRoot, @@ -2572,7 +2588,6 @@ CONSTANT_TRANSLATION(InitExistentialValueInst, LookThrough) CONSTANT_TRANSLATION(CopyAddrInst, Store) CONSTANT_TRANSLATION(ExplicitCopyAddrInst, Store) CONSTANT_TRANSLATION(StoreInst, Store) -CONSTANT_TRANSLATION(StoreBorrowInst, Store) CONSTANT_TRANSLATION(StoreWeakInst, Store) CONSTANT_TRANSLATION(MarkUnresolvedMoveAddrInst, Store) CONSTANT_TRANSLATION(UncheckedRefCastAddrInst, Store) @@ -2804,6 +2819,44 @@ LOOKTHROUGH_IF_NONSENDABLE_RESULT_AND_OPERAND(UncheckedTakeEnumDataAddrInst) // Custom Handling // +TranslationSemantics +PartitionOpTranslator::visitStoreBorrowInst(StoreBorrowInst *sbi) { + // A store_borrow is an interesting instruction since we are essentially + // temporarily binding an object value to an address... so really any uses of + // the address, we want to consider to be uses of the parent object. So we + // basically put source/dest into the same region, but do not consider the + // store_borrow itself to be a require use. This prevents the store_borrow + // from causing incorrect diagnostics. + SILValue destValue = sbi->getDest(); + SILValue srcValue = sbi->getSrc(); + + auto nonSendableDest = tryToTrackValue(destValue); + if (!nonSendableDest) + return TranslationSemantics::Ignored; + + // In the following situations, we can perform an assign: + // + // 1. A store to unaliased storage. + // 2. A store that is to an entire value. + // + // DISCUSSION: If we have case 2, we need to merge the regions since we + // are not overwriting the entire region of the value. This does mean that + // we artificially include the previous region that was stored + // specifically in this projection... but that is better than + // miscompiling. For memory like this, we probably need to track it on a + // per field basis to allow for us to assign. + if (nonSendableDest.value().isNoAlias() && + !isProjectedFromAggregate(destValue)) { + translateSILMultiAssign(sbi->getResults(), sbi->getOperandValues(), + SILIsolationInfo(), false /*require src*/); + } else { + // Stores to possibly aliased storage must be treated as merges. + translateSILMerge(destValue, srcValue, false /*require src*/); + } + + return TranslationSemantics::Special; +} + TranslationSemantics PartitionOpTranslator::visitAllocStackInst(AllocStackInst *asi) { // Before we do anything, see if asi is Sendable or if it is non-Sendable, diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp index d3d2e0f5110ab..175b18d5db47e 100644 --- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp +++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp @@ -675,22 +675,30 @@ static bool isSupportedClosure(const SILInstruction *Closure) { return false; if (auto *PAI = dyn_cast(Closure)) { - // Bail if any of the arguments are passed by address and - // are not @inout. - // This is a temporary limitation. + // Check whether each argument is supported. auto ClosureCallee = FRI->getReferencedFunction(); auto ClosureCalleeConv = ClosureCallee->getConventions(); - unsigned ClosureArgIdx = + unsigned ClosureArgIdxBase = ClosureCalleeConv.getNumSILArguments() - PAI->getNumArguments(); - for (auto Arg : PAI->getArguments()) { + for (auto pair : llvm::enumerate(PAI->getArguments())) { + auto Arg = pair.value(); + auto ClosureArgIdx = pair.index() + ClosureArgIdxBase; + auto ArgConvention = + ClosureCalleeConv.getSILArgumentConvention(ClosureArgIdx); + SILType ArgTy = Arg->getType(); + // Specializing (currently) always produces a retain in the caller. + // That's not allowed for values of move-only type. + if (ArgTy.isMoveOnly()) { + return false; + } + + // Only @inout/@inout_aliasable addresses are (currently) supported. // If our argument is an object, continue... if (ArgTy.isObject()) { ++ClosureArgIdx; continue; } - auto ArgConvention = - ClosureCalleeConv.getSILArgumentConvention(ClosureArgIdx); if (ArgConvention != SILArgumentConvention::Indirect_Inout && ArgConvention != SILArgumentConvention::Indirect_InoutAliasable) return false; @@ -1394,7 +1402,7 @@ bool SILClosureSpecializerTransform::gatherCallSites( // foo({ c() }) // } // - // A limit of 2 is good enough and will not be exceed in "regular" + // A limit of 2 is good enough and will not be exceeded in "regular" // optimization scenarios. if (getSpecializationLevel(getClosureCallee(ClosureInst)) > SpecializationLevelLimit) { diff --git a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp index b2c82c236bdc8..b117ffdaa65fb 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp +++ b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp @@ -64,6 +64,7 @@ #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" #include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/OwnershipOptUtils.h" #include "swift/SILOptimizer/Utils/LoopUtils.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "llvm/ADT/SmallSet.h" @@ -835,6 +836,8 @@ class SwiftArrayPropertyOptPass : public SILFunctionTransform { if (getFunction()->getModule().getOptions().VerifyAll) getFunction()->verifyCriticalEdges(); + updateBorrowedFrom(getPassManager(), Fn); + // We preserve the dominator tree. Let's invalidate everything // else. DA->lockInvalidation(); diff --git a/lib/SILOptimizer/Mandatory/ConsumeOperatorCopyableAddressesChecker.cpp b/lib/SILOptimizer/Mandatory/ConsumeOperatorCopyableAddressesChecker.cpp index 6e1834b476a8e..9bf2358b0039b 100644 --- a/lib/SILOptimizer/Mandatory/ConsumeOperatorCopyableAddressesChecker.cpp +++ b/lib/SILOptimizer/Mandatory/ConsumeOperatorCopyableAddressesChecker.cpp @@ -2080,12 +2080,98 @@ bool ConsumeOperatorCopyableAddressesChecker::performClosureDataflow( closureConsumes); } +struct MoveConstraint { + enum Value : uint8_t { + None, + RequiresReinit, + Illegal, + } value; + + operator Value() { return value; } + MoveConstraint(Value value) : value(value) {} + + static MoveConstraint forGuaranteed(bool guaranteed) { + return guaranteed ? Illegal : None; + } + + bool isIllegal() { return value == Illegal; } +}; + +static MoveConstraint getMoveConstraint(SILValue addr) { + assert(addr->getType().isAddress()); + auto access = AccessPathWithBase::computeInScope(addr); + auto base = access.getAccessBase(); + switch (access.accessPath.getStorage().getKind()) { + case AccessRepresentation::Kind::Box: + // Even if the box is guaranteed, it may be permitted to consume its + // storage. + return MoveConstraint::None; + case AccessRepresentation::Kind::Stack: { + // An alloc_stack is guaranteed if it's a "store_borrow destination". + auto *asi = cast(base.getBaseAddress()); + return MoveConstraint::forGuaranteed( + !asi->getUsersOfType().empty()); + } + case AccessRepresentation::Kind::Global: + // A global can be consumed if it's reinitialized. + return MoveConstraint::RequiresReinit; + case AccessRepresentation::Kind::Class: + // A class field can be consumed if it's reinitialized. + return MoveConstraint::RequiresReinit; + case AccessRepresentation::Kind::Tail: + // A class field can be consumed if it's reinitialized. + return MoveConstraint::RequiresReinit; + case AccessRepresentation::Kind::Argument: { + // An indirect argument is guaranteed if it's @in_guaranteed. + auto *arg = base.getArgument(); + return MoveConstraint::forGuaranteed( + arg->getArgumentConvention().isGuaranteedConvention()); + } + case AccessRepresentation::Kind::Yield: { + auto baseAddr = base.getBaseAddress(); + auto *bai = cast( + cast(baseAddr)->getParent()); + auto index = *bai->getIndexOfResult(baseAddr); + auto info = bai->getSubstCalleeConv().getYieldInfoForOperandIndex(index); + return MoveConstraint::forGuaranteed(!info.isConsumed()); + } + case AccessRepresentation::Kind::Nested: { + auto *bai = cast(base.getBaseAddress()); + if (bai->getAccessKind() == SILAccessKind::Init || + bai->getAccessKind() == SILAccessKind::Read) + return MoveConstraint::Illegal; + // Allow moves from both modify and deinit. + return MoveConstraint::None; + } + case AccessRepresentation::Kind::Unidentified: + // Conservatively reject for now. + return MoveConstraint::Illegal; + } +} + // Returns true if we emitted a diagnostic and handled the single block // case. Returns false if we visited all of the uses and seeded the UseState // struct with the information needed to perform our interprocedural dataflow. bool ConsumeOperatorCopyableAddressesChecker::performSingleBasicBlockAnalysis( SILValue address, DebugVarCarryingInst addressDebugInst, MarkUnresolvedMoveAddrInst *mvi) { + if (getMoveConstraint(mvi->getSrc()).isIllegal()) { + auto &astCtx = mvi->getFunction()->getASTContext(); + StringRef name = getDebugVarName(address); + diagnose(astCtx, getSourceLocFromValue(address), + diag::sil_movechecking_guaranteed_value_consumed, name); + diagnose(astCtx, mvi->getLoc().getSourceLoc(), + diag::sil_movechecking_consuming_use_here); + + // Replace the marker instruction with a copy_addr to avoid subsequent + // diagnostics. + SILBuilderWithScope builder(mvi); + builder.createCopyAddr(mvi->getLoc(), mvi->getSrc(), mvi->getDest(), + IsNotTake, IsInitialization); + mvi->eraseFromParent(); + + return true; + } // First scan downwards to make sure we are move out of this block. auto &useState = dataflowState.useState; auto &applySiteToPromotedArgIndices = diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp index cb3615c3a564c..66566a5982ded 100644 --- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp +++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp @@ -1709,6 +1709,19 @@ void ElementUseCollector::collectClassSelfUses( Kind = DIUseKind::Escape; } + // Track flow-sensitive 'self' isolation builtins separately, because they + // aren't really uses of 'self' until after DI, once we've decided whether + // they have a fully-formed 'self' to use. + if (auto builtin = dyn_cast(User)) { + if (auto builtinKind = builtin->getBuiltinKind()) { + if (*builtinKind == BuiltinValueKind::FlowSensitiveSelfIsolation || + *builtinKind == + BuiltinValueKind::FlowSensitiveDistributedSelfIsolation) { + Kind = DIUseKind::FlowSensitiveSelfIsolation; + } + } + } + trackUse(DIMemoryUse(User, Kind, 0, TheMemory.getNumElements())); } } diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h index 860b6a0261a3c..c89167d99bde9 100644 --- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h +++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h @@ -298,7 +298,12 @@ enum DIUseKind { LoadForTypeOfSelf, /// This instruction is a value_metatype on the address of 'self'. - TypeOfSelf + TypeOfSelf, + + /// This instruction is the builtin for flow-sensitive current isolation + /// within an actor initializer. It will be replaced with either a copy of + /// its argument (injected into an (any Actor)?) or nil. + FlowSensitiveSelfIsolation, }; /// This struct represents a single classified access to the memory object diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 494c613d65c2e..a42a85cd2f49f 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -15,6 +15,7 @@ #include "DIMemoryUseCollector.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsSIL.h" +#include "swift/AST/DistributedDecl.h" #include "swift/AST/Expr.h" #include "swift/AST/Stmt.h" #include "swift/ClangImporter/ClangModule.h" @@ -491,6 +492,7 @@ namespace { void handleTypeOfSelfUse(DIMemoryUse &Use); void handleInOutUse(const DIMemoryUse &Use); void handleEscapeUse(const DIMemoryUse &Use); + void handleFlowSensitiveActorIsolationUse(const DIMemoryUse &Use); bool diagnoseReturnWithoutInitializingStoredProperties( const SILInstruction *Inst, SILLocation loc, const DIMemoryUse &Use); @@ -565,6 +567,7 @@ LifetimeChecker::LifetimeChecker(const DIMemoryObjectInfo &TheMemory, case DIUseKind::LoadForTypeOfSelf: case DIUseKind::TypeOfSelf: case DIUseKind::Escape: + case DIUseKind::FlowSensitiveSelfIsolation: continue; case DIUseKind::Assign: case DIUseKind::Set: @@ -1160,6 +1163,10 @@ void LifetimeChecker::doIt() { case DIUseKind::BadExplicitStore: diagnoseBadExplicitStore(Inst); break; + + case DIUseKind::FlowSensitiveSelfIsolation: + handleFlowSensitiveActorIsolationUse(Use); + break; } } @@ -1344,6 +1351,73 @@ void LifetimeChecker::handleTypeOfSelfUse(DIMemoryUse &Use) { } } +void LifetimeChecker::handleFlowSensitiveActorIsolationUse( + const DIMemoryUse &Use) { + bool IsSuperInitComplete, FailedSelfUse; + + ASTContext &ctx = F.getASTContext(); + auto builtinInst = cast(Use.Inst); + SILBuilderWithScope B(builtinInst); + SILValue replacement; + SILType optExistentialType = builtinInst->getType(); + SILLocation loc = builtinInst->getLoc(); + if (isInitializedAtUse(Use, &IsSuperInitComplete, &FailedSelfUse)) { + // 'self' is initialized, so replace this builtin with the appropriate + // operation to produce `any Actor. + + SILValue anyActorValue; + auto conformance = builtinInst->getSubstitutions().getConformances()[0]; + if (builtinInst->getBuiltinKind() == BuiltinValueKind::FlowSensitiveSelfIsolation) { + // Create a copy of the actor argument, which we intentionally did not + // copy in SILGen. + SILValue actor = B.createCopyValue(loc, builtinInst->getArguments()[0]); + + // Inject 'self' into 'any Actor'. + ProtocolConformanceRef conformances[1] = { conformance }; + SILType existentialType = optExistentialType.getOptionalObjectType(); + anyActorValue = B.createInitExistentialRef( + loc, existentialType, actor->getType().getASTType(), actor, + ctx.AllocateCopy(conformances)); + } else { + // Borrow the actor argument, which we need to form the appropriate + // call to the asLocalActor getter. + SILValue actor = B.createBeginBorrow(loc, builtinInst->getArguments()[0]); + + // Dig out the getter for asLocalActor. + auto asLocalActorDecl = getDistributedActorAsLocalActorComputedProperty( + F.getDeclContext()->getParentModule()); + auto asLocalActorGetter = asLocalActorDecl->getAccessor(AccessorKind::Get); + SILDeclRef asLocalActorRef = SILDeclRef( + asLocalActorGetter, SILDeclRef::Kind::Func); + SILFunction *asLocalActorFunc = F.getModule() + .lookUpFunction(asLocalActorRef); + SILValue asLocalActorValue = B.createFunctionRef(loc, asLocalActorFunc); + + // Call asLocalActor. It produces an 'any Actor'. + anyActorValue = B.createApply( + loc, + asLocalActorValue, + SubstitutionMap::get(asLocalActorGetter->getGenericSignature(), + { actor->getType().getASTType() }, + { conformance }), + { actor }); + B.createEndBorrow(loc, actor); + } + + // Then, wrap it in an optional. + replacement = B.createEnum( + loc, anyActorValue, ctx.getOptionalSomeDecl(), optExistentialType); + } else { + // 'self' is not initialized yet, so use 'nil'. + replacement = B.createEnum( + loc, SILValue(), ctx.getOptionalNoneDecl(), optExistentialType); + } + + // Introduce the replacement. + InstModCallbacks callbacks; + replaceAllUsesAndErase(builtinInst, replacement, callbacks); +} + void LifetimeChecker::emitSelfConsumedDiagnostic(SILInstruction *Inst) { if (!shouldEmitError(Inst)) return; diff --git a/lib/SILOptimizer/Mandatory/FlowIsolation.cpp b/lib/SILOptimizer/Mandatory/FlowIsolation.cpp index b845386a2fdbd..03cb2abe313ab 100644 --- a/lib/SILOptimizer/Mandatory/FlowIsolation.cpp +++ b/lib/SILOptimizer/Mandatory/FlowIsolation.cpp @@ -582,6 +582,12 @@ void AnalysisInfo::analyze(const SILArgument *selfParam) { worklist.pushUsesOfValueIfNotVisited(selfParam); while (Operand *operand = worklist.pop()) { + // A type-dependent use of `self` is an instruction that contains the + // DynamicSelfType. These instructions do not access any protected + // state. + if (operand->isTypeDependent()) + continue; + SILInstruction *user = operand->getUser(); // First, check if this is an apply that involves `self` diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp index 98d58a7e4519b..046f9a392c13c 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp @@ -2934,13 +2934,13 @@ bool GlobalLivenessChecker::testInstVectorLiveness( continue; case IsLive::LiveOut: { LLVM_DEBUG(llvm::dbgs() << " Live out block!\n"); - // If we see a live out block that is also a def block, we need to fa -#ifndef NDEBUG + // If we see a live out block that is also a def block, skip. SmallBitVector defBits(addressUseState.getNumSubelements()); liveness.isDefBlock(block, errorSpan, defBits); - assert((defBits & errorSpan).none() && - "If in def block... we are in liveness block"); -#endif + if (!(defBits & errorSpan).none()) { + LLVM_DEBUG(llvm::dbgs() << " Also a def block; skipping!\n"); + continue; + } [[clang::fallthrough]]; } case IsLive::LiveWithin: diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp index a7a583ab7d955..b606fd7c37107 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp @@ -51,12 +51,6 @@ namespace { struct SILMoveOnlyWrappedTypeEliminatorVisitor : SILInstructionVisitor { - const llvm::SmallSetVector &touchedArgs; - - SILMoveOnlyWrappedTypeEliminatorVisitor( - const llvm::SmallSetVector &touchedArgs) - : touchedArgs(touchedArgs) {} - bool visitSILInstruction(SILInstruction *inst) { llvm::errs() << "Unhandled SIL Instruction: " << *inst; llvm_unreachable("error"); @@ -294,56 +288,76 @@ static bool isMoveOnlyWrappedTrivial(SILValue value) { } bool SILMoveOnlyWrappedTypeEliminator::process() { - bool madeChange = true; + bool madeChange = false; - llvm::SmallSetVector touchedArgs; llvm::SmallSetVector touchedInsts; + // For each value whose type is move-only wrapped: + // - rewrite the value's type + // - record its users for later visitation + auto visitValue = [&touchedInsts, fn = fn, + trivialOnly = trivialOnly](SILValue value) -> bool { + if (!value->getType().hasAnyMoveOnlyWrapping(fn)) + return false; + + // If we are looking at trivial only, skip non-trivial function args. + if (trivialOnly && !isMoveOnlyWrappedTrivial(value)) + return false; + + for (auto *use : value->getNonTypeDependentUses()) + touchedInsts.insert(use->getUser()); + + if (isa(value)) + value->replaceAllUsesWith( + SILUndef::get(fn, value->getType().removingAnyMoveOnlyWrapping(fn))); + else + value->unsafelyEliminateMoveOnlyWrapper(fn); + + return true; + }; + for (auto &bb : *fn) { for (auto *arg : bb.getArguments()) { - if (!arg->getType().isMoveOnlyWrapped() && - !arg->getType().isBoxedMoveOnlyWrappedType(fn)) + bool relevant = visitValue(arg); + if (!relevant) continue; - // If we are looking at trivial only, skip non-trivial function args. - if (trivialOnly && - !arg->getType().removingMoveOnlyWrapper().isTrivial(*fn)) - continue; - - arg->unsafelyEliminateMoveOnlyWrapper(fn); - // If our new type is trivial, convert the arguments ownership to // None. Otherwise, preserve the ownership kind of the argument. if (arg->getType().isTrivial(*fn)) arg->setOwnershipKind(OwnershipKind::None); - touchedArgs.insert(arg); - for (auto *use : arg->getNonTypeDependentUses()) - touchedInsts.insert(use->getUser()); + + madeChange = true; } for (auto &ii : bb) { - for (SILValue v : ii.getResults()) { - if (!v->getType().isMoveOnlyWrapped() && - !v->getType().isBoxedMoveOnlyWrappedType(fn)) - continue; - - if (trivialOnly && - !isMoveOnlyWrappedTrivial(v)) + bool touched = false; + for (SILValue value : ii.getResults()) { + bool relevant = visitValue(value); + if (!relevant) continue; - v->unsafelyEliminateMoveOnlyWrapper(fn); - touchedInsts.insert(&ii); - - // Add all users as well. This ensures we visit things like - // destroy_value and end_borrow. - for (auto *use : v->getNonTypeDependentUses()) - touchedInsts.insert(use->getUser()); - madeChange = true; + touched = true; } + if (!touched) + continue; + touchedInsts.insert(&ii); + + madeChange = true; } } + // SILFunction::undefValues may grow during the loop. + SmallVector, 4> originalUndefs( + fn->getUndefValues()); + for (auto pair : originalUndefs) { + bool relevant = visitValue(pair.second); + if (!relevant) + continue; + + madeChange = true; + } - SILMoveOnlyWrappedTypeEliminatorVisitor visitor(touchedArgs); + SILMoveOnlyWrappedTypeEliminatorVisitor visitor; while (!touchedInsts.empty()) { visitor.visit(touchedInsts.pop_back_val()); } diff --git a/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp b/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp index caf325df576ea..446b4ced4280e 100644 --- a/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp +++ b/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp @@ -118,8 +118,7 @@ bool SILGenCleanup::completeOSSALifetimes(SILFunction *function) { for (SILInstruction &inst : reverse(*block)) { for (auto result : inst.getResults()) { if (completion.completeOSSALifetime( - result, - OSSALifetimeCompletion::Boundary::AvailabilityWithLeaks) == + result, OSSALifetimeCompletion::Boundary::Availability) == LifetimeCompletion::WasCompleted) { changed = true; } @@ -128,7 +127,7 @@ bool SILGenCleanup::completeOSSALifetimes(SILFunction *function) { for (SILArgument *arg : block->getArguments()) { assert(!arg->isReborrow() && "reborrows not legal at this SIL stage"); if (completion.completeOSSALifetime( - arg, OSSALifetimeCompletion::Boundary::AvailabilityWithLeaks) == + arg, OSSALifetimeCompletion::Boundary::Availability) == LifetimeCompletion::WasCompleted) { changed = true; } diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp index 516fdccb836a6..56b83125ef35a 100644 --- a/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp +++ b/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp @@ -159,6 +159,8 @@ static bool isBarrier(SILInstruction *inst) { case BuiltinValueKind::GetEnumTag: case BuiltinValueKind::InjectEnumTag: case BuiltinValueKind::ExtractFunctionIsolation: + case BuiltinValueKind::FlowSensitiveSelfIsolation: + case BuiltinValueKind::FlowSensitiveDistributedSelfIsolation: case BuiltinValueKind::AddressOfRawLayout: return false; diff --git a/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp b/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp index 142d6c7263f7b..a5fbe48dcc3f9 100644 --- a/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp +++ b/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp @@ -125,41 +125,47 @@ void BasicBlockCloner::updateSSAAfterCloning() { break; } } - if (!needsSSAUpdate) - return; - - SILSSAUpdater ssaUpdater(&updateSSAPhis); - for (auto availValPair : availVals) { - auto inst = availValPair.first; - if (inst->use_empty()) - continue; + if (needsSSAUpdate) { + SILSSAUpdater ssaUpdater(&updateSSAPhis); + for (auto availValPair : availVals) { + auto inst = availValPair.first; + if (inst->use_empty()) + continue; - SILValue newResult(availValPair.second); + SILValue newResult(availValPair.second); - SmallVector useList; - // Collect the uses of the value. - for (auto *use : inst->getUses()) - useList.push_back(UseWrapper(use)); + SmallVector useList; + // Collect the uses of the value. + for (auto *use : inst->getUses()) + useList.push_back(UseWrapper(use)); - ssaUpdater.initialize(inst->getFunction(), inst->getType(), - inst->getOwnershipKind()); - ssaUpdater.addAvailableValue(origBB, inst); - ssaUpdater.addAvailableValue(getNewBB(), newResult); + ssaUpdater.initialize(inst->getFunction(), inst->getType(), + inst->getOwnershipKind()); + ssaUpdater.addAvailableValue(origBB, inst); + ssaUpdater.addAvailableValue(getNewBB(), newResult); - if (useList.empty()) - continue; + if (useList.empty()) + continue; - // Update all the uses. - for (auto useWrapper : useList) { - Operand *use = useWrapper; // unwrap - SILInstruction *user = use->getUser(); - assert(user && "Missing user"); + // Update all the uses. + for (auto useWrapper : useList) { + Operand *use = useWrapper; // unwrap + SILInstruction *user = use->getUser(); + assert(user && "Missing user"); - // Ignore uses in the same basic block. - if (user->getParent() == origBB) - continue; + // Ignore uses in the same basic block. + if (user->getParent() == origBB) + continue; - ssaUpdater.rewriteUse(*use); + ssaUpdater.rewriteUse(*use); + } + } + } + for (SILBasicBlock *b : blocksWithNewPhiArgs) { + for (SILArgument *arg : b->getArguments()) { + if (arg->getOwnershipKind() == OwnershipKind::Guaranteed) { + updateSSAPhis.push_back(cast(arg)); + } } } updateBorrowedFromPhis(pm, updateSSAPhis); diff --git a/lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp b/lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp index 8db93617a9612..aad69dd8df034 100644 --- a/lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp +++ b/lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp @@ -274,8 +274,7 @@ void CanonicalizeOSSALifetime::extendLivenessToDeinitBarriers() { } OSSALifetimeCompletion::visitAvailabilityBoundary( - getCurrentDef(), OSSALifetimeCompletion::DoNotAllowLeaks, - completeLiveness, [&](auto *unreachable, auto end) { + getCurrentDef(), completeLiveness, [&](auto *unreachable, auto end) { if (end == OSSALifetimeCompletion::LifetimeEnd::Boundary) { recordUnreachableLifetimeEnd(unreachable); } diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp index fe177898f4a26..055fe930260fd 100644 --- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp +++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp @@ -14,6 +14,7 @@ #include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h" #include "swift/SILOptimizer/Utils/PerformanceInlinerUtils.h" #include "swift/AST/Module.h" +#include "swift/Basic/Require.h" #include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/CommandLine.h" @@ -851,8 +852,8 @@ SILFunction *swift::getEligibleFunction(FullApplySite AI, !Callee->hasValidLinkageForFragileRef(Caller->getSerializedKind())) { llvm::errs() << "caller: " << Caller->getName() << "\n"; llvm::errs() << "callee: " << Callee->getName() << "\n"; - llvm_unreachable("Should never be inlining a resilient function into " - "a fragile function"); + require(false, "Should never be inlining a resilient function into " + "a fragile function"); } return nullptr; } diff --git a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp index d64a150774aa6..a84dc8f97f303 100644 --- a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp +++ b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp @@ -813,26 +813,31 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) { } } - // Otherwise, see if we have an allocator decl ref. If we do and we have an - // actor instance isolation, then we know that we are actively just calling - // the initializer. To just make region isolation work, treat this as - // disconnected so we can construct the actor value. Users cannot write - // allocator functions so we just need to worry about compiler generated - // code. In the case of a non-actor, we can only have an allocator that is - // global actor isolated, so we will never hit this code path. + // Otherwise, see if we need to handle this isolation computation specially + // due to information from the decl ref if we have one. if (auto declRef = fArg->getFunction()->getDeclRef()) { + // First check if we have an allocator decl ref. If we do and we have an + // actor instance isolation, then we know that we are actively just calling + // the initializer. To just make region isolation work, treat this as + // disconnected so we can construct the actor value. Users cannot write + // allocator functions so we just need to worry about compiler generated + // code. In the case of a non-actor, we can only have an allocator that is + // global actor isolated, so we will never hit this code path. if (declRef.kind == SILDeclRef::Kind::Allocator) { if (fArg->getFunction()->getActorIsolation().isActorInstanceIsolated()) { return SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/); } } + // Then see if we have an init accessor that is isolated to an actor + // instance, but for which we have not actually passed self. In such a case, + // we need to pass in a "fake" ActorInstance that users know is a sentinel + // for the self value. if (auto functionIsolation = fArg->getFunction()->getActorIsolation()) { - if (declRef.getDecl()) { + if (functionIsolation.isActorInstanceIsolated() && declRef.getDecl()) { if (auto *accessor = dyn_cast_or_null(declRef.getFuncDecl())) { if (accessor->isInitAccessor()) { - assert(functionIsolation.isActorInstanceIsolated()); return SILIsolationInfo::getActorInstanceIsolated( fArg, ActorInstance::getForActorAccessorInit(), functionIsolation.getActor()); diff --git a/lib/Sema/AssociatedTypeInference.cpp b/lib/Sema/AssociatedTypeInference.cpp index 3147c4aa99cbc..8b4433f6b82aa 100644 --- a/lib/Sema/AssociatedTypeInference.cpp +++ b/lib/Sema/AssociatedTypeInference.cpp @@ -2425,7 +2425,9 @@ AssociatedTypeInference::computeFailureTypeWitness( // it. for (const auto &witness : valueWitnesses) { if (isAsyncIteratorProtocolNext(witness.first)) { - if (auto witnessFunc = dyn_cast(witness.second)) { + // We use a dyn_cast_or_null since we can get a nullptr here if we fail to + // match a witness. In such a case, we should just fail here. + if (auto witnessFunc = dyn_cast_or_null(witness.second)) { auto thrownError = witnessFunc->getEffectiveThrownErrorType(); // If it doesn't throw, Failure == Never. diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index c9ece81dcf7e2..618edb7c5503f 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -5557,7 +5557,6 @@ namespace { assert(OpenedExistentials.empty()); auto &ctx = cs.getASTContext(); - auto *module = dc->getParentModule(); // Look at all of the suspicious optional injections for (auto injection : SuspiciousOptionalInjections) { diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index ad0bf49a0bb70..e9394cb6b9a02 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -4230,7 +4230,7 @@ findImportedCaseWithMatchingSuffix(Type instanceTy, DeclNameRef name) { // Is one more available than the other? WORSE(->getAttrs().isUnavailable(ctx)); - WORSE(->getAttrs().getDeprecated(ctx)); + WORSE(->getAttrs().isDeprecated(ctx)); // Does one have a shorter name (so the non-matching prefix is shorter)? WORSE(->getName().getBaseName().userFacingName().size()); @@ -7918,6 +7918,24 @@ bool NonEphemeralConversionFailure::diagnoseAsError() { return true; } +bool SendingOnFunctionParameterMismatchFail::diagnoseAsError() { + emitDiagnosticAt(getLoc(), diag::sending_function_wrong_sending, + getFromType(), getToType()) + .warnUntilSwiftVersion(6); + emitDiagnosticAt(getLoc(), + diag::sending_function_param_with_sending_param_note); + return true; +} + +bool SendingOnFunctionResultMismatchFailure::diagnoseAsError() { + emitDiagnosticAt(getLoc(), diag::sending_function_wrong_sending, + getFromType(), getToType()) + .warnUntilSwiftVersion(6); + emitDiagnosticAt(getLoc(), + diag::sending_function_result_with_sending_param_note); + return true; +} + bool AssignmentTypeMismatchFailure::diagnoseMissingConformance() const { auto srcType = getFromType(); auto dstType = getToType()->lookThroughAllOptionalTypes(); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 8e76d917a879d..e436e0faabb1c 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2292,6 +2292,28 @@ class NonEphemeralConversionFailure final : public ArgumentMismatchFailure { void emitSuggestionNotes() const; }; +class SendingOnFunctionParameterMismatchFail final : public ContextualFailure { +public: + SendingOnFunctionParameterMismatchFail(const Solution &solution, Type srcType, + Type dstType, + ConstraintLocator *locator, + FixBehavior fixBehavior) + : ContextualFailure(solution, srcType, dstType, locator, fixBehavior) {} + + bool diagnoseAsError() override; +}; + +class SendingOnFunctionResultMismatchFailure final : public ContextualFailure { +public: + SendingOnFunctionResultMismatchFailure(const Solution &solution, Type srcType, + Type dstType, + ConstraintLocator *locator, + FixBehavior fixBehavior) + : ContextualFailure(solution, srcType, dstType, locator, fixBehavior) {} + + bool diagnoseAsError() override; +}; + class AssignmentTypeMismatchFailure final : public ContextualFailure { public: AssignmentTypeMismatchFailure(const Solution &solution, diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index a87dfef7e4159..82ac5e2003b3e 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1845,6 +1845,34 @@ std::string TreatEphemeralAsNonEphemeral::getName() const { return name; } +bool AllowSendingMismatch::diagnose(const Solution &solution, + bool asNote) const { + switch (kind) { + case Kind::Parameter: { + SendingOnFunctionParameterMismatchFail failure( + solution, getFromType(), getToType(), getLocator(), fixBehavior); + return failure.diagnose(asNote); + } + case Kind::Result: { + SendingOnFunctionResultMismatchFailure failure( + solution, getFromType(), getToType(), getLocator(), fixBehavior); + return failure.diagnose(asNote); + } + } + llvm_unreachable("Covered switch isn't covered?!"); +} + +AllowSendingMismatch *AllowSendingMismatch::create(ConstraintSystem &cs, + ConstraintLocator *locator, + Type srcType, Type dstType, + Kind kind) { + auto fixBehavior = cs.getASTContext().LangOpts.isSwiftVersionAtLeast(6) + ? FixBehavior::Error + : FixBehavior::DowngradeToWarning; + return new (cs.getAllocator()) + AllowSendingMismatch(cs, srcType, dstType, locator, kind, fixBehavior); +} + bool SpecifyBaseTypeForContextualMember::diagnose(const Solution &solution, bool asNote) const { MissingContextualBaseInMemberRefFailure failure(solution, MemberName, diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 20a1dd0565076..854bcd105ff0d 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1649,10 +1649,9 @@ namespace { } Type - resolveTypeReferenceInExpression(TypeRepr *repr, TypeResolverContext resCtx, + resolveTypeReferenceInExpression(TypeRepr *repr, + TypeResolutionOptions options, const ConstraintLocatorBuilder &locator) { - TypeResolutionOptions options(resCtx); - // Introduce type variables for unbound generics. const auto genericOpener = OpenUnboundGenericType(CS, locator); const auto placeholderHandler = HandlePlaceholderType(CS, locator); @@ -2541,9 +2540,11 @@ namespace { return declaredTy; } + auto options = + TypeResolutionOptions(TypeResolverContext::InExpression); + options.setContext(TypeResolverContext::ClosureExpr); const auto resolvedTy = resolveTypeReferenceInExpression( - closure->getExplicitResultTypeRepr(), - TypeResolverContext::InExpression, resultLocator); + closure->getExplicitResultTypeRepr(), options, resultLocator); if (resolvedTy) return resolvedTy; } diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index e62edf343e516..38fad7a2c9d96 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -1036,18 +1036,9 @@ SolutionCompareResult ConstraintSystem::compareSolutions( if (cs.isForCodeCompletion()) { // Don't rank based on overload choices of function calls that contain the // code completion token. - ASTNode anchor = simplifyLocatorToAnchor(overload.locator); - if (auto expr = getAsExpr(anchor)) { - // If the anchor is a called function, also don't rank overload choices - // if any of the arguments contain the code completion token. - if (auto apply = dyn_cast_or_null(cs.getParentExpr(expr))) { - if (apply->getFn() == expr) { - anchor = apply; - } - } - } - if (anchor && cs.containsIDEInspectionTarget(anchor)) { - continue; + if (auto anchor = simplifyLocatorToAnchor(overload.locator)) { + if (cs.containsIDEInspectionTarget(cs.includingParentApply(anchor))) + continue; } } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 9a9b2cdb365a4..f51506b0d4035 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3235,6 +3235,16 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, return getTypeMatchFailure(locator); } + // () -> sending T can be a subtype of () -> T... but not vis-a-versa. + if (func1->hasSendingResult() != func2->hasSendingResult() && + (!func1->hasSendingResult() || kind < ConstraintKind::Subtype)) { + auto *fix = AllowSendingMismatch::create( + *this, getConstraintLocator(locator), func1, func2, + AllowSendingMismatch::Kind::Result); + if (recordFix(fix)) + return getTypeMatchFailure(locator); + } + if (!matchFunctionIsolations(func1, func2, kind, flags, locator)) return getTypeMatchFailure(locator); @@ -3665,6 +3675,17 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, return getTypeMatchFailure(argumentLocator); } + // Do not allow for functions that expect a sending parameter to match + // with a function that expects a non-sending parameter. + if (func1Param.getParameterFlags().isSending() && + !func2Param.getParameterFlags().isSending()) { + auto *fix = AllowSendingMismatch::create( + *this, getConstraintLocator(argumentLocator), func1, func2, + AllowSendingMismatch::Kind::Parameter); + if (recordFix(fix)) + return getTypeMatchFailure(argumentLocator); + } + // FIXME: We should check value ownership too, but it's not completely // trivial because of inout-to-pointer conversions. @@ -11785,10 +11806,10 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, if (contextualParam->isIsolated() && !flags.isIsolated() && paramDecl) isolatedParams.insert(paramDecl); - param = - param.withFlags(flags.withInOut(contextualParam->isInOut()) - .withVariadic(contextualParam->isVariadic()) - .withIsolated(contextualParam->isIsolated())); + param = param.withFlags(flags.withInOut(contextualParam->isInOut()) + .withVariadic(contextualParam->isVariadic()) + .withIsolated(contextualParam->isIsolated()) + .withSending(contextualParam->isSending())); } } @@ -11915,6 +11936,12 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, closureExtInfo = closureExtInfo.withSendable(); } + // Propagate sending result from the contextual type to the closure. + if (auto contextualFnType = contextualType->getAs()) { + if (contextualFnType->hasExtInfo() && contextualFnType->hasSendingResult()) + closureExtInfo = closureExtInfo.withSendingResult(); + } + // Isolated parameters override any other kind of isolation we might infer. if (hasIsolatedParam) { closureExtInfo = closureExtInfo.withIsolation( @@ -15113,6 +15140,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( } } + case FixKind::AllowSendingMismatch: case FixKind::InsertCall: case FixKind::RemoveReturn: case FixKind::RemoveAddressOf: @@ -15201,7 +15229,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( locator.endsWith()) ? 1 : 0; - + // An overload choice that isn't settable is least interesting for diagnosis. + if (auto overload = findSelectedOverloadFor(getCalleeLocator(fix->getLocator()))) { + if (auto *var = dyn_cast_or_null(overload->choice.getDeclOrNull())) { + impact += !var->isSettableInSwift(DC) ? 1 : 0; + } + } return recordFix(fix, impact) ? SolutionKind::Error : SolutionKind::Solved; } diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 8b0be4fe8195c..df21d48cc2977 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -2064,9 +2064,20 @@ Constraint *ConstraintSystem::getUnboundBindOverloadDisjunction( // Performance hack: if there are two generic overloads, and one is // more specialized than the other, prefer the more-specialized one. -static Constraint *tryOptimizeGenericDisjunction( - DeclContext *dc, - ArrayRef constraints) { +static Constraint * +tryOptimizeGenericDisjunction(ConstraintSystem &cs, Constraint *disjunction, + ArrayRef constraints) { + auto *dc = cs.DC; + + // If we're solving for code completion, and have a child completion token, + // skip this optimization since the completion token being a placeholder can + // allow us to prefer an unhelpful disjunction choice. + if (cs.isForCodeCompletion()) { + auto anchor = disjunction->getLocator()->getAnchor(); + if (cs.containsIDEInspectionTarget(cs.includingParentApply(anchor))) + return nullptr; + } + llvm::SmallVector choices; for (auto *choice : constraints) { if (choices.size() > 2) @@ -2311,7 +2322,7 @@ void DisjunctionChoiceProducer::partitionDisjunction( SmallVectorImpl &PartitionBeginning) { // Apply a special-case rule for favoring one generic function over // another. - if (auto favored = tryOptimizeGenericDisjunction(CS.DC, Choices)) { + if (auto favored = tryOptimizeGenericDisjunction(CS, Disjunction, Choices)) { CS.favorConstraint(favored); } diff --git a/lib/Sema/CodeSynthesisDistributedActor.cpp b/lib/Sema/CodeSynthesisDistributedActor.cpp index 07c7ebe9e6851..236328ae5d50a 100644 --- a/lib/Sema/CodeSynthesisDistributedActor.cpp +++ b/lib/Sema/CodeSynthesisDistributedActor.cpp @@ -81,15 +81,15 @@ static VarDecl* // what already has a witness. static VarDecl *addImplicitDistributedActorIDProperty( ClassDecl *nominal) { - if (!nominal) - return nullptr; - if (!nominal->isDistributedActor()) + if (!nominal || !nominal->isDistributedActor()) return nullptr; auto &C = nominal->getASTContext(); // ==== Synthesize and add 'id' property to the actor decl Type propertyType = getDistributedActorIDType(nominal); + if (!propertyType || propertyType->hasError()) + return nullptr; auto *propDecl = new (C) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Let, diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 3dce3ebf1b379..8b457f14b274a 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1747,8 +1747,17 @@ FunctionType *ConstraintSystem::adjustFunctionTypeForConcurrency( }); if (Context.LangOpts.hasFeature(Feature::InferSendableFromCaptures)) { + DeclContext *DC = nullptr; if (auto *FD = dyn_cast(decl)) { - auto *DC = FD->getDeclContext(); + DC = FD->getDeclContext(); + } else if (auto EED = dyn_cast(decl)) { + if (EED->hasAssociatedValues() && + !locator.endsWith()) { + DC = EED->getDeclContext(); + } + } + + if (DC) { // All global functions should be @Sendable if (DC->isModuleScopeContext()) { if (!adjustedTy->getExtInfo().isSendable()) { @@ -6658,6 +6667,16 @@ static bool shouldHaveDirectCalleeOverload(const CallExpr *callExpr) { } #endif +ASTNode ConstraintSystem::includingParentApply(ASTNode node) { + if (auto *expr = getAsExpr(node)) { + if (auto apply = getAsExpr(getParentExpr(expr))) { + if (apply->getFn() == expr) + return apply; + } + } + return node; +} + Type Solution::resolveInterfaceType(Type type) const { auto resolvedType = type.transform([&](Type type) -> Type { if (auto *tvt = type->getAs()) { diff --git a/lib/Sema/DerivedConformanceCaseIterable.cpp b/lib/Sema/DerivedConformanceCaseIterable.cpp index 9f92ab7717989..8681c0b268f78 100644 --- a/lib/Sema/DerivedConformanceCaseIterable.cpp +++ b/lib/Sema/DerivedConformanceCaseIterable.cpp @@ -79,6 +79,8 @@ static Type deriveCaseIterable_AllCases(DerivedConformance &derived) { } ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) { + auto &C = requirement->getASTContext(); + // Conformance can't be synthesized in an extension. if (checkAndDiagnoseDisallowedContext(requirement)) return nullptr; @@ -102,6 +104,9 @@ ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) { SynthesizedIntroducer::Var, Context.Id_allCases, returnTy, returnTy, /*isStatic=*/true, /*isFinal=*/true); + propDecl->getAttrs().add( + new (C) NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true)); + // Define the getter. auto *getterDecl = addGetterToReadOnlyDerivedProperty(propDecl, returnTy); diff --git a/lib/Sema/DerivedConformanceDistributedActor.cpp b/lib/Sema/DerivedConformanceDistributedActor.cpp index 5b396655dee0a..e3a44b70d9221 100644 --- a/lib/Sema/DerivedConformanceDistributedActor.cpp +++ b/lib/Sema/DerivedConformanceDistributedActor.cpp @@ -474,6 +474,9 @@ static ValueDecl *deriveDistributedActor_actorSystem( auto classDecl = dyn_cast(derived.Nominal); assert(classDecl && derived.Nominal->isDistributedActor()); + if (!C.getLoadedModule(C.Id_Distributed)) + return nullptr; + // ``` // nonisolated let actorSystem: ActorSystem // ``` diff --git a/lib/Sema/IDETypeCheckingRequests.cpp b/lib/Sema/IDETypeCheckingRequests.cpp index 53488c7c9b3f7..b9c305fdcf9e7 100644 --- a/lib/Sema/IDETypeCheckingRequests.cpp +++ b/lib/Sema/IDETypeCheckingRequests.cpp @@ -116,29 +116,29 @@ class ContainsSpecializableArchetype : public TypeWalker { } }; -/// Returns `true` if `ED` is an extension of `PD` that binds `Self` to a -/// concrete type, like `extension MyProto where Self == MyStruct {}`. +/// Returns `true` if `ED` is an extension that binds `Self` to a +/// concrete type, like `extension MyProto where Self == MyStruct {}`. The +/// protocol being extended must either be `PD`, or `Self` must be a type +/// that conforms to `PD`. /// /// In these cases, it is possible to access static members defined in the /// extension when perfoming unresolved member lookup in a type context of /// `PD`. static bool isExtensionWithSelfBound(const ExtensionDecl *ED, ProtocolDecl *PD) { - if (!ED || !PD) { + if (!ED || !PD) return false; - } - if (ED->getExtendedNominal() != PD) { - return false; - } + GenericSignature genericSig = ED->getGenericSignature(); Type selfType = genericSig->getConcreteType(ED->getSelfInterfaceType()); - if (!selfType) { + if (!selfType) return false; - } - if (selfType->is()) { + + if (selfType->is()) return false; - } - return true; + + auto *M = ED->getParentModule(); + return ED->getExtendedNominal() == PD || M->checkConformance(selfType, PD); } static bool isExtensionAppliedInternal(const DeclContext *DC, Type BaseTy, diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index b3ee16614cf78..cfca7058db1c8 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -1365,6 +1365,13 @@ UnboundImport::UnboundImport( if (declaringOptions.contains(ImportFlags::ImplementationOnly) || bystandingOptions.contains(ImportFlags::ImplementationOnly)) import.options |= ImportFlags::ImplementationOnly; + if (declaringOptions.contains(ImportFlags::SPIOnly) || + bystandingOptions.contains(ImportFlags::SPIOnly)) + import.options |= ImportFlags::SPIOnly; + + // Pick the most restrictive access level. + import.accessLevel = std::min(declaringImport.accessLevel, + bystandingImport.accessLevel); // If either have a `@_documentation(visibility: )` attribute, the // cross-import has the more restrictive of the two. @@ -1385,12 +1392,6 @@ void ImportResolver::crossImport(ModuleDecl *M, UnboundImport &I) { // first bind all exported imports in all files, then bind all other imports // in each file. This may become simpler if we bind all ImportDecls before we // start computing cross-imports, but I haven't figured that part out yet. - // - // Fixing this is tracked within Apple by rdar://problem/59527118. I haven't - // filed an SR because I plan to address it myself, but if this comment is - // still here in April 2020 without an SR number, please file a Swift bug and - // harass @brentdax to fill in the details. - if (!SF.shouldCrossImport()) return; diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 789a6e02fc6b7..44d87bf29fdb8 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -1715,6 +1715,91 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, Closures.push_back(ACE); } + static bool + implicitWeakSelfReferenceIsValid510(const DeclRefExpr *DRE, + const AbstractClosureExpr *inClosure) { + ASTContext &Ctx = DRE->getDecl()->getASTContext(); + + // Check if the implicit self decl refers to a var in a conditional stmt + LabeledConditionalStmt *conditionalStmt = nullptr; + if (auto var = dyn_cast(DRE->getDecl())) { + if (auto parentStmt = var->getParentPatternStmt()) { + conditionalStmt = dyn_cast(parentStmt); + } + } + + if (!conditionalStmt) { + return false; + } + + // Require `LoadExpr`s when validating the self binding. + // This lets us reject invalid examples like: + // + // let `self` = self ?? .somethingElse + // guard let self = self else { return } + // method() // <- implicit self is not allowed + // + return conditionalStmt->rebindsSelf(Ctx, /*requiresCaptureListRef*/ false, + /*requireLoadExpr*/ true); + } + + static bool + isEnclosingSelfReference510(VarDecl *var, + const AbstractClosureExpr *inClosure) { + if (var->isSelfParameter()) + return true; + + // Capture variables have a DC of the parent function. + if (inClosure && var->isSelfParamCapture() && + var->getDeclContext() != inClosure->getParent()) + return true; + + return false; + } + + static bool + selfDeclAllowsImplicitSelf510(DeclRefExpr *DRE, Type ty, + const AbstractClosureExpr *inClosure) { + // If this is an explicit `weak self` capture, then implicit self is + // allowed once the closure's self param is unwrapped. We need to validate + // that the unwrapped `self` decl specifically refers to an unwrapped copy + // of the closure's `self` param, and not something else like in `guard + // let self = .someOptionalVariable else { return }` or `let self = + // someUnrelatedVariable`. If self hasn't been unwrapped yet and is still + // an optional, we would have already hit an error elsewhere. + if (closureHasWeakSelfCapture(inClosure)) { + return implicitWeakSelfReferenceIsValid510(DRE, inClosure); + } + + // Metatype self captures don't extend the lifetime of an object. + if (ty->is()) + return true; + + // If self does not have reference semantics, it is very unlikely that + // capturing it will create a reference cycle. + if (!ty->hasReferenceSemantics()) + return true; + + if (auto closureExpr = dyn_cast(inClosure)) { + if (auto selfDecl = closureExpr->getCapturedSelfDecl()) { + // If this capture is using the name `self` actually referring + // to some other variable (e.g. with `[self = "hello"]`) + // then implicit self is not allowed. + if (!selfDecl->isSelfParamCapture()) { + return false; + } + } + } + + if (auto var = dyn_cast(DRE->getDecl())) { + if (!isEnclosingSelfReference510(var, inClosure)) { + return true; + } + } + + return false; + } + /// Whether or not implicit self is allowed for self decl static bool selfDeclAllowsImplicitSelf(Expr *E, const AbstractClosureExpr *inClosure) { @@ -1731,6 +1816,11 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, if (!ty) return true; + // Prior to Swift 6, use the old validation logic. + auto &ctx = inClosure->getASTContext(); + if (!ctx.isSwiftVersionAtLeast(6)) + return selfDeclAllowsImplicitSelf510(DRE, ty, inClosure); + return selfDeclAllowsImplicitSelf(DRE->getDecl(), ty, inClosure, /*validateParentClosures:*/ true, /*validateSelfRebindings:*/ true); @@ -1745,7 +1835,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, ASTContext &ctx = inClosure->getASTContext(); auto requiresSelfQualification = - isClosureRequiringSelfQualification(inClosure, ctx); + isClosureRequiringSelfQualification(inClosure); // Metatype self captures don't extend the lifetime of an object. if (captureType->is()) { @@ -1783,7 +1873,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, // that defines self if present. if (validateSelfRebindings) { if (auto conditionalStmt = parentConditionalStmt(selfDecl)) { - if (!hasValidSelfRebinding(conditionalStmt, inClosure)) { + if (!hasValidSelfRebinding(conditionalStmt, ctx)) { return false; } } @@ -1793,7 +1883,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, // closure unwraps self. If not, implicit self is not allowed // in this closure or in any nested closure. if (closureHasWeakSelfCapture(inClosure) && - !hasValidSelfRebinding(parentConditionalStmt(selfDecl), inClosure)) { + !hasValidSelfRebinding(parentConditionalStmt(selfDecl), ctx)) { return false; } @@ -1967,7 +2057,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, static bool hasValidSelfRebinding(const LabeledConditionalStmt *conditionalStmt, - const AbstractClosureExpr *inClosure) { + ASTContext &ctx) { if (!conditionalStmt) { return false; } @@ -1980,8 +2070,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, // guard let self = self else { return } // method() // <- implicit self is not allowed // - return conditionalStmt->rebindsSelf(inClosure->getASTContext(), - /*requiresCaptureListRef*/ true); + return conditionalStmt->rebindsSelf(ctx, /*requiresCaptureListRef*/ true); } /// The `LabeledConditionalStmt` that contains the given `ValueDecl` if @@ -2065,8 +2154,8 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, /// use or capture of "self." for qualification of member references. static bool isClosureRequiringSelfQualification(const AbstractClosureExpr *CE, - ASTContext &Ctx) { - if (closureHasWeakSelfCapture(CE)) { + bool ignoreWeakSelf = false) { + if (!ignoreWeakSelf && closureHasWeakSelfCapture(CE)) { return true; } @@ -2112,9 +2201,20 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, bool shouldWalkCaptureInitializerExpressions() override { return true; } + bool shouldRecordClosure(const AbstractClosureExpr *E) { + // Record all closures in Swift 6 mode. + if (Ctx.isSwiftVersionAtLeast(6)) + return true; + + // Only record closures requiring self qualification prior to Swift 6 + // mode. + return isClosureRequiringSelfQualification(E); + } + PreWalkResult walkToExprPre(Expr *E) override { if (auto *CE = dyn_cast(E)) { - Closures.push_back(CE); + if (shouldRecordClosure(CE)) + Closures.push_back(CE); } // If we aren't in a closure, no diagnostics will be produced. @@ -2146,7 +2246,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, diag::property_use_in_closure_without_explicit_self, baseName.getIdentifier()) .warnUntilSwiftVersionIf( - invalidImplicitSelfShouldOnlyWarn(MRE->getBase(), ACE), 6); + invalidImplicitSelfShouldOnlyWarn510(MRE->getBase(), ACE), 6); } // Handle method calls with a specific diagnostic + fixit. @@ -2161,12 +2261,13 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, diag::method_call_in_closure_without_explicit_self, MethodExpr->getDecl()->getBaseIdentifier()) .warnUntilSwiftVersionIf( - invalidImplicitSelfShouldOnlyWarn(DSCE->getBase(), ACE), 6); + invalidImplicitSelfShouldOnlyWarn510(DSCE->getBase(), ACE), + 6); } if (memberLoc.isValid()) { const AbstractClosureExpr *parentDisallowingImplicitSelf = nullptr; - if (selfDRE && selfDRE->getDecl()) { + if (Ctx.isSwiftVersionAtLeast(6) && selfDRE && selfDRE->getDecl()) { parentDisallowingImplicitSelf = parentClosureDisallowingImplicitSelf( selfDRE->getDecl(), selfDRE->getType(), ACE); } @@ -2175,11 +2276,11 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, return Action::SkipNode(E); } - if (!selfDeclAllowsImplicitSelf(E, ACE)) + if (!selfDeclAllowsImplicitSelf(E, ACE)) { Diags.diagnose(E->getLoc(), diag::implicit_use_of_self_in_closure) - .warnUntilSwiftVersionIf(invalidImplicitSelfShouldOnlyWarn(E, ACE), - 6); - + .warnUntilSwiftVersionIf( + invalidImplicitSelfShouldOnlyWarn510(E, ACE), 6); + } return Action::Continue(E); } @@ -2189,9 +2290,10 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, return Action::Continue(E); } - assert(Closures.size() > 0); - Closures.pop_back(); - + if (shouldRecordClosure(ACE)) { + assert(Closures.size() > 0); + Closures.pop_back(); + } return Action::Continue(E); } @@ -2253,7 +2355,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, // to use implicit self, even after fixing any invalid parents. auto isEscapingAutoclosure = isa(ACE) && - isClosureRequiringSelfQualification(ACE, Ctx); + isClosureRequiringSelfQualification(ACE); if (!isEscapingAutoclosure) { closureForDiagnostics = parentDisallowingImplicitSelf; } @@ -2369,134 +2471,28 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, /// Whether or not this invalid usage of implicit self should be a warning /// in Swift 5 mode, to preserve source compatibility. - bool invalidImplicitSelfShouldOnlyWarn(Expr *selfRef, - AbstractClosureExpr *ACE) { + bool invalidImplicitSelfShouldOnlyWarn510(Expr *selfRef, + AbstractClosureExpr *ACE) { auto DRE = dyn_cast_or_null(selfRef); - if (!DRE) { + if (!DRE) return false; - } auto selfDecl = dyn_cast_or_null(DRE->getDecl()); - auto ty = DRE->getType(); - if (!selfDecl) { - return false; - } - - if (isInTypePreviouslyLackingValidation(ty)) { - return true; - } - - if (isPreviouslyPermittedWeakSelfUsage(ACE, selfDecl, ty)) { - return true; - } - - if (isUsageAlwaysPreviouslyRejected(selfDecl, ACE)) { + if (!selfDecl) return false; - } - - if (isPreviouslyPermittedStrongSelfUsage(selfDecl, ACE)) { - return true; - } - - return false; - } - bool isInTypePreviouslyLackingValidation(Type ty) { - // We previously didn't validate captures at all in structs or metadata - // types, so we must only warn in this case. - return !ty->hasReferenceSemantics() || ty->is(); - } - - /// Checks if this usage of implicit self in a weak self closure - /// was previously permitted in Swift 5.8. - bool isPreviouslyPermittedWeakSelfUsage(AbstractClosureExpr *ACE, - ValueDecl *selfDecl, Type ty) { - auto weakSelfDecl = weakSelfCapture(ACE); - if (!weakSelfDecl) { - return false; - } - - // Implicit self was permitted for weak self captures in - // non-escaping closures in Swift 5.7, so we must only warn. - if (isNonEscaping(ACE)) { - return true; - } - - // Implicit self was also permitted for weak self captures in closures - // passed to @_implicitSelfCapture parameters in Swift 5.7. - if (auto *CE = dyn_cast(ACE)) { - if (CE->allowsImplicitSelfCapture()) - return true; - } - - // Invalid captures like `[weak self = somethingElse]` - // were permitted in Swift 5.8, so we must only warn. - if (!isSimpleSelfCapture(weakSelfDecl)) { - return true; - } - - if (auto condStmt = parentConditionalStmt(selfDecl)) { - auto isValidSelfRebinding = hasValidSelfRebinding(condStmt, ACE); - - // Swfit 5.8 permitted implicit self without validating any - // parent closures. If implicit self is only disallowed due to - // an invalid parent, we must only warn. - if (isValidSelfRebinding && - implicitSelfDisallowedDueToInvalidParent(selfDecl, ty, ACE)) { - return true; - } - - // Swift 5.8 used `requiresLoadExpr` to validate self bindings. - // If the binding is valid when only checking for a load expr, - // then we must only warn. - auto usesLoadExpr = - condStmt->rebindsSelf(ACE->getASTContext(), - /*requiresCaptureListRef*/ false, - /*requireLoadExpr*/ true); - - if (!isValidSelfRebinding && usesLoadExpr) { - return true; - } - } - - return false; - } - - /// Checks if this implicit self usage was always previously rejected as - /// invalid, so can continue to be treated an error. - bool isUsageAlwaysPreviouslyRejected(ValueDecl *selfDecl, - AbstractClosureExpr *ACE) { - // If the self decl refers to a weak self unwrap condition - // in some parent closure, then there is no source-compatibility - // requirement to avoid an error. - return hasValidSelfRebinding(parentConditionalStmt(selfDecl), ACE); - } - - /// Checks if this is a usage of implicit self in a strong self closure - /// that was previously permitted in older versions like Swift 5.3. - bool isPreviouslyPermittedStrongSelfUsage(VarDecl *selfDecl, - AbstractClosureExpr *ACE) { - // Implicit self was accidentially allowed in examples like this - // in Swift 5.3-5.5, so check for this case and emit a warning - // instead of an error: - // - // withEscaping { [self] in - // withEscaping { - // x += 1 - // } - // } - // - bool isEscapingClosureWithExplicitSelfCapture = false; - if (!isNonEscaping(ACE)) { - if (auto closureExpr = dyn_cast(ACE)) { - if (closureExpr->getCapturedSelfDecl()) { - isEscapingClosureWithExplicitSelfCapture = true; - } - } + // If this implicit self decl is from a closure that captured self + // weakly, then we should always emit an error, since implicit self was + // only allowed starting in Swift 5.8 and later. + if (closureHasWeakSelfCapture(ACE)) { + // Implicit self was incorrectly permitted for weak self captures + // in non-escaping closures in Swift 5.7, so in that case we can + // only warn until Swift 6. + return !isClosureRequiringSelfQualification(ACE, + /*ignoreWeakSelf*/ true); } - return !selfDecl->isSelfParameter() && - !isEscapingClosureWithExplicitSelfCapture; + return !selfDecl->isSelfParameter(); } }; @@ -2507,7 +2503,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, // FIXME: This is happening too early, because closure->getType() isn't set. if (auto *closure = dyn_cast(DC)) if (closure->getType()) - if (DiagnoseWalker::isClosureRequiringSelfQualification(closure, ctx)) + if (DiagnoseWalker::isClosureRequiringSelfQualification(closure)) ACE = const_cast(closure); DC = DC->getParent(); } diff --git a/lib/Sema/ResilienceDiagnostics.cpp b/lib/Sema/ResilienceDiagnostics.cpp index 681d1e0ee4c48..0f855431a0e78 100644 --- a/lib/Sema/ResilienceDiagnostics.cpp +++ b/lib/Sema/ResilienceDiagnostics.cpp @@ -66,22 +66,17 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc, ImportAccessLevel problematicImport = D->getImportAccessFrom(DC); if (problematicImport.has_value()) { auto SF = DC->getParentSourceFile(); - if (SF) { - // The max used access level previously registered might be Package, - // in which case, don't reset it to Public here; this ensures proper - // diags between public and package. - if (SF->isMaxAccessLevelUsingImportInternal(problematicImport.value())) - SF->registerAccessLevelUsingImport(problematicImport.value(), - AccessLevel::Public); - - if (Context.LangOpts.EnableModuleApiImportRemarks) { - ModuleDecl *importedVia = problematicImport->module.importedModule, - *sourceModule = D->getModuleContext(); - Context.Diags.diagnose(loc, diag::module_api_import, - D, importedVia, sourceModule, - importedVia == sourceModule, - /*isImplicit*/false); - } + if (SF) + SF->registerAccessLevelUsingImport(problematicImport.value(), + AccessLevel::Public); + + if (Context.LangOpts.EnableModuleApiImportRemarks) { + ModuleDecl *importedVia = problematicImport->module.importedModule, + *sourceModule = D->getModuleContext(); + Context.Diags.diagnose(loc, diag::module_api_import, + D, importedVia, sourceModule, + importedVia == sourceModule, + /*isImplicit*/false); } } @@ -105,16 +100,6 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc, } DowngradeToWarning downgradeToWarning = DowngradeToWarning::No; - // Don't change the order of the getDisallowedOriginKind call; - // it can reset downgradeToWarning to NO so needs to be called here. - auto originKind = getDisallowedOriginKind(D, where, downgradeToWarning); - // For a default argument or property initializer, package type is - // allowed at the use site with package access scope. - auto allowedForPkgCtx = false; - if (originKind == DisallowedOriginKind::None || - originKind == DisallowedOriginKind::PackageImport) { - allowedForPkgCtx = where.isPackage() && declAccessScope.isPackage(); - } // Swift 4.2 did not perform any checks for type aliases. if (isa(D)) { @@ -134,17 +119,15 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc, if (isa(DC) && !Context.isSwiftVersionAtLeast(6)) downgradeToWarning = DowngradeToWarning::Yes; - if (!allowedForPkgCtx) { - auto diagID = diag::resilience_decl_unavailable; - if (downgradeToWarning == DowngradeToWarning::Yes) - diagID = diag::resilience_decl_unavailable_warn; + auto diagID = diag::resilience_decl_unavailable; + if (downgradeToWarning == DowngradeToWarning::Yes) + diagID = diag::resilience_decl_unavailable_warn; - AccessLevel diagAccessLevel = declAccessScope.accessLevelForDiagnostics(); - Context.Diags.diagnose(loc, diagID, D, diagAccessLevel, - fragileKind.getSelector()); + AccessLevel diagAccessLevel = declAccessScope.accessLevelForDiagnostics(); + Context.Diags.diagnose(loc, diagID, D, diagAccessLevel, + fragileKind.getSelector()); - Context.Diags.diagnose(D, diag::resilience_decl_declared_here, D, allowedForPkgCtx); - } + Context.Diags.diagnose(D, diag::resilience_decl_declared_here, D); if (problematicImport.has_value() && problematicImport->accessLevel < D->getFormalAccess()) { @@ -173,14 +156,10 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc, where.getDeclContext()); if (problematicImport.has_value()) { auto SF = where.getDeclContext()->getParentSourceFile(); - if (SF) { - // The max used access level previously registered might be Package, - // in which case, don't reset it to Public here; this ensures proper - // diags between public and package. - if (SF->isMaxAccessLevelUsingImportInternal(problematicImport.value())) - SF->registerAccessLevelUsingImport(problematicImport.value(), - AccessLevel::Public); - } + if (SF) + SF->registerAccessLevelUsingImport(problematicImport.value(), + AccessLevel::Public); + if (ctx.LangOpts.EnableModuleApiImportRemarks) { ModuleDecl *importedVia = problematicImport->module.importedModule, *sourceModule = D->getModuleContext(); @@ -207,8 +186,7 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc, auto definingModule = D->getModuleContext(); auto fragileKind = where.getFragileFunctionKind(); bool warnPreSwift6 = originKind != DisallowedOriginKind::SPIOnly && - originKind != DisallowedOriginKind::PackageImport && - originKind != DisallowedOriginKind::InternalOrLessImport; + originKind != DisallowedOriginKind::NonPublicImport; if (fragileKind.kind == FragileFunctionKind::None) { auto reason = where.getExportabilityReason(); ctx.Diags @@ -233,8 +211,7 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc, addMissingImport(loc, D, where); // If limited by an import, note which one. - if (originKind == DisallowedOriginKind::InternalOrLessImport || - originKind == DisallowedOriginKind::PackageImport) { + if (originKind == DisallowedOriginKind::NonPublicImport) { const DeclContext *DC = where.getDeclContext(); ImportAccessLevel limitImport = D->getImportAccessFrom(DC); assert(limitImport.has_value() && @@ -265,31 +242,33 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D, ImportAccessLevel import = D->getImportAccessFrom(DC); if (import.has_value() && reason.has_value()) { auto SF = DC->getParentSourceFile(); - if (SF) { - // The max used access level previously registered might be Package, - // in which case, don't reset it to Public here; this ensures proper - // diags between public and package. - if (SF->isMaxAccessLevelUsingImportInternal(import.value())) - SF->registerAccessLevelUsingImport(import.value(), - AccessLevel::Public); - } + if (SF) + SF->registerAccessLevelUsingImport(import.value(), + AccessLevel::Public); } // Access levels from imports are reported with the others access levels. - // Except for extensions, we report them here. - if (originKind == DisallowedOriginKind::InternalOrLessImport || - originKind == DisallowedOriginKind::PackageImport) { - if (reason != ExportabilityReason::ExtensionWithPublicMembers && - reason != ExportabilityReason::ExtensionWithPackageMembers && - reason != ExportabilityReason::ExtensionWithConditionalConformances && - reason != ExportabilityReason::ExtensionWithPackageConditionalConformances) + // Except for extensions and protocol conformances, we report them here. + if (originKind == DisallowedOriginKind::NonPublicImport) { + bool reportHere = [&] { + switch (*reason) { + case ExportabilityReason::ExtensionWithPublicMembers: + case ExportabilityReason::ExtensionWithConditionalConformances: + return true; + case ExportabilityReason::Inheritance: + return isa(D); + default: + return false; + } + }(); + if (!reportHere) return false; } if (ctx.LangOpts.EnableModuleApiImportRemarks && import.has_value() && where.isExported() && reason != ExportabilityReason::General && - originKind != DisallowedOriginKind::InternalOrLessImport) { + originKind != DisallowedOriginKind::NonPublicImport) { // These may be reported twice, for the Type and for the TypeRepr. ModuleDecl *importedVia = import->module.importedModule, *sourceModule = D->getModuleContext(); @@ -302,14 +281,6 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D, if (originKind == DisallowedOriginKind::None) return false; - // No diags needed for extensions with package members or - // conformance to types with package access scope. - if (originKind == DisallowedOriginKind::PackageImport) { - if (reason == ExportabilityReason::ExtensionWithPackageMembers || - reason == ExportabilityReason::ExtensionWithPackageConditionalConformances) - return false; - } - auto diagName = D->getName(); if (auto accessor = dyn_cast(D)) { // Only diagnose accessors if their disallowed origin kind differs from @@ -353,8 +324,7 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D, } // If limited by an import, note which one. - if (originKind == DisallowedOriginKind::InternalOrLessImport || - originKind == DisallowedOriginKind::PackageImport) { + if (originKind == DisallowedOriginKind::NonPublicImport) { assert(import.has_value() && import->accessLevel < AccessLevel::Public && "The import should still be non-public"); @@ -403,14 +373,10 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc, ImportAccessLevel problematicImport = ext->getImportAccessFrom(where.getDeclContext()); if (problematicImport.has_value()) { auto SF = where.getDeclContext()->getParentSourceFile(); - if (SF) { - // The max used access level previously registered might be Package, - // in which case, don't reset it to Public here; this ensures proper - // diags between public and package. - if (SF->isMaxAccessLevelUsingImportInternal(problematicImport.value())) - SF->registerAccessLevelUsingImport(problematicImport.value(), - AccessLevel::Public); - } + if (SF) + SF->registerAccessLevelUsingImport(problematicImport.value(), + AccessLevel::Public); + if (ctx.LangOpts.EnableModuleApiImportRemarks) { ModuleDecl *importedVia = problematicImport->module.importedModule, *sourceModule = ext->getModuleContext(); @@ -437,8 +403,7 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc, static_cast(originKind)) .warnUntilSwiftVersionIf((warnIfConformanceUnavailablePreSwift6 && originKind != DisallowedOriginKind::SPIOnly && - originKind != DisallowedOriginKind::PackageImport && - originKind != DisallowedOriginKind::InternalOrLessImport) || + originKind != DisallowedOriginKind::NonPublicImport) || originKind == DisallowedOriginKind::MissingImport, 6); @@ -447,8 +412,7 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc, addMissingImport(loc, ext, where); // If limited by an import, note which one. - if (originKind == DisallowedOriginKind::InternalOrLessImport || - originKind == DisallowedOriginKind::PackageImport) { + if (originKind == DisallowedOriginKind::NonPublicImport) { const DeclContext *DC = where.getDeclContext(); ImportAccessLevel limitImport = ext->getImportAccessFrom(DC); assert(limitImport.has_value() && diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 91361a33c6b61..696088116964a 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -404,12 +404,13 @@ static void noteLimitingImport(const Decl *userDecl, limitImport->accessLevel, limitImport->module.importedModule); - ctx.Diags.diagnose(limitImport->importLoc, - diag::decl_import_via_here, - VD, - limitImport->accessLevel, - limitImport->module.importedModule); - } else { + if (limitImport->importLoc.isValid()) + ctx.Diags.diagnose(limitImport->importLoc, + diag::decl_import_via_here, + VD, + limitImport->accessLevel, + limitImport->module.importedModule); + } else if (limitImport->importLoc.isValid()) { ctx.Diags.diagnose(limitImport->importLoc, diag::module_imported_here, limitImport->module.importedModule, limitImport->accessLevel); @@ -1424,16 +1425,13 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, ImportAccessLevel importLimit) { auto &Ctx = theVar->getASTContext(); auto diagID = diag::pattern_type_not_usable_from_inline_inferred; - auto hasPackageScope = false; if (fixedLayoutStructContext) { diagID = diag::pattern_type_not_usable_from_inline_inferred_frozen; - hasPackageScope = fixedLayoutStructContext->getFormalAccessScope(nullptr, true).isPackage(); } else if (!Ctx.isSwiftVersionAtLeast(5)) { diagID = diag::pattern_type_not_usable_from_inline_inferred_warn; } Ctx.Diags.diagnose(NP->getLoc(), diagID, theVar->isLet(), - isTypeContext, theVar->getInterfaceType(), - hasPackageScope); + isTypeContext, theVar->getInterfaceType()); noteLimitingImport(theVar, importLimit, complainRepr); }); } @@ -1466,14 +1464,12 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, ImportAccessLevel importLimit) { auto &Ctx = anyVar->getASTContext(); auto diagID = diag::pattern_type_not_usable_from_inline; - auto hasPackageScope = false; - if (fixedLayoutStructContext) { + if (fixedLayoutStructContext) diagID = diag::pattern_type_not_usable_from_inline_frozen; - hasPackageScope = fixedLayoutStructContext->getFormalAccessScope(nullptr, true).isPackage(); - } else if (!Ctx.isSwiftVersionAtLeast(5)) + else if (!Ctx.isSwiftVersionAtLeast(5)) diagID = diag::pattern_type_not_usable_from_inline_warn; auto diag = Ctx.Diags.diagnose(TP->getLoc(), diagID, anyVar->isLet(), - isTypeContext, hasPackageScope); + isTypeContext); highlightOffendingType(diag, complainRepr); noteLimitingImport(anyVar, importLimit, complainRepr); }); @@ -2016,20 +2012,9 @@ swift::getDisallowedOriginKind(const Decl *decl, // Report non-public import last as it can be ignored by the caller. // See \c diagnoseValueDeclRefExportability. auto importSource = decl->getImportAccessFrom(where.getDeclContext()); - if (importSource.has_value()) { - if (importSource->accessLevel == AccessLevel::Package) { - auto kind = where.getFragileFunctionKind().kind; - if (where.isPackage() && - (kind == FragileFunctionKind::None || - kind == FragileFunctionKind::DefaultArgument || - kind == FragileFunctionKind::PropertyInitializer)) - return DisallowedOriginKind::None; - return DisallowedOriginKind::PackageImport; - } - - if (importSource->accessLevel < AccessLevel::Package) - return DisallowedOriginKind::InternalOrLessImport; - } + if (importSource.has_value() && + importSource->accessLevel < AccessLevel::Public) + return DisallowedOriginKind::NonPublicImport; return DisallowedOriginKind::None; } @@ -2275,7 +2260,7 @@ class DeclAvailabilityChecker : public DeclVisitor { for (TypeLoc inherited : nominal->getInherited().getEntries()) { checkType(inherited.getType(), inherited.getTypeRepr(), nominal, - ExportabilityReason::General, flags); + ExportabilityReason::Inheritance, flags); } } @@ -2352,19 +2337,13 @@ class DeclAvailabilityChecker : public DeclVisitor { } void checkConstrainedExtensionRequirements(ExtensionDecl *ED, - bool hasExportedPublicMembers, - bool hasExportedPackageMembers, - bool hasPackageInheritance) { + bool hasExportedMembers) { if (!ED->getTrailingWhereClause()) return; - ExportabilityReason reason = ExportabilityReason::ExtensionWithConditionalConformances; - if (hasExportedPublicMembers) - reason = ExportabilityReason::ExtensionWithPublicMembers; - else if (hasExportedPackageMembers) - reason = ExportabilityReason::ExtensionWithPackageMembers; - else if (hasPackageInheritance) - reason = ExportabilityReason::ExtensionWithPackageConditionalConformances; + ExportabilityReason reason = + hasExportedMembers ? ExportabilityReason::ExtensionWithPublicMembers + : ExportabilityReason::ExtensionWithConditionalConformances; forAllRequirementTypes(ED, [&](Type type, TypeRepr *typeRepr) { checkType(type, typeRepr, ED, reason); @@ -2383,7 +2362,7 @@ class DeclAvailabilityChecker : public DeclVisitor { // must be exported. for (TypeLoc inherited : ED->getInherited().getEntries()) { checkType(inherited.getType(), inherited.getTypeRepr(), ED, - ExportabilityReason::General, + ExportabilityReason::Inheritance, DeclAvailabilityFlag::AllowPotentiallyUnavailableProtocol); } @@ -2391,61 +2370,23 @@ class DeclAvailabilityChecker : public DeclVisitor { // 2) If the extension contains exported members, the as-written // extended type should be exportable. - bool hasExportedPublicMembers = llvm::any_of(ED->getMembers(), + bool hasExportedMembers = llvm::any_of(ED->getMembers(), [](const Decl *member) -> bool { auto *valueMember = dyn_cast(member); if (!valueMember) return false; - return isExported(valueMember) && - !valueMember->getFormalAccessScope(nullptr, true).isPackage(); - - }); - - // Keep track of package (exported) members separately from public - // members for diags purposes. - bool hasExportedPackageMembers = llvm::any_of(ED->getMembers(), - [](const Decl *member) -> bool { - auto *valueMember = dyn_cast(member); - if (!valueMember) - return false; - return isExported(valueMember) && - valueMember->getFormalAccessScope(nullptr, true).isPackage(); - }); - - bool hasExportedMembers = hasExportedPublicMembers || hasExportedPackageMembers; - - // Keep track of inheritance with package access level for diags purposes. - bool hasPackageInheritance = llvm::any_of(ED->getInherited().getEntries(), - [](const InheritedEntry entry) -> bool { - if (!entry.wasValidated()) - return false; - auto enType = entry.getType(); - if (enType) { - if (const auto *ProtoD = dyn_cast_or_null(enType->getAnyNominal())) { - if (ProtoD && isExported(ProtoD) && - ProtoD->getFormalAccessScope(nullptr, true).isPackage()) - return true; - } - } - return false; + return isExported(valueMember); }); Where = wasWhere.withExported(hasExportedMembers); - - ExportabilityReason reason = ExportabilityReason::ExtensionWithPublicMembers; - if (!hasExportedPublicMembers && hasExportedPackageMembers) - reason = ExportabilityReason::ExtensionWithPackageMembers; - - checkType(ED->getExtendedType(), ED->getExtendedTypeRepr(), - ED, reason); + checkType(ED->getExtendedType(), ED->getExtendedTypeRepr(), ED, + ExportabilityReason::ExtensionWithPublicMembers); // 3) If the extension contains exported members or defines conformances, // the 'where' clause must only name exported types. Where = wasWhere.withExported(hasExportedMembers || !ED->getInherited().empty()); - checkConstrainedExtensionRequirements(ED, hasExportedPublicMembers, - hasExportedPackageMembers, - hasPackageInheritance); + checkConstrainedExtensionRequirements(ED, hasExportedMembers); if (!hasExportedMembers && !ED->getInherited().empty()) { @@ -2457,11 +2398,10 @@ class DeclAvailabilityChecker : public DeclVisitor { ImportAccessLevel import = extendedType->getImportAccessFrom(DC); if (import.has_value()) { auto SF = DC->getParentSourceFile(); - if (SF) { - if (SF->isMaxAccessLevelUsingImportInternal(import.value())) - SF->registerAccessLevelUsingImport(import.value(), - AccessLevel::Public); - } + if (SF) + SF->registerAccessLevelUsingImport(import.value(), + AccessLevel::Public); + auto &ctx = DC->getASTContext(); if (ctx.LangOpts.EnableModuleApiImportRemarks) { ModuleDecl *importedVia = import->module.importedModule, @@ -2611,6 +2551,49 @@ void swift::diagnoseUnnecessaryPublicImports(SourceFile &SF) { } } +/// Register the type extended by \p ED as being used in a package decl if +/// any member is a package decl. This patches a hole in the warnings on +/// superfluously public imports which usually relies on exportability checking +/// that is not currently executed for package decls. +void registerPackageAccessForPackageExtendedType(ExtensionDecl *ED) { + auto extendedType = ED->getExtendedNominal(); + if (!extendedType) + return; + + bool hasPackageMembers = llvm::any_of(ED->getMembers(), + [](const Decl *member) -> bool { + auto *VD = dyn_cast(member); + if (!VD) + return false; + + AccessScope accessScope = + VD->getFormalAccessScope(nullptr, + /*treatUsableFromInlineAsPublic*/true); + return accessScope.isPackage(); + }); + if (!hasPackageMembers) + return; + + DeclContext *DC = ED->getDeclContext(); + ImportAccessLevel import = extendedType->getImportAccessFrom(DC); + if (import.has_value()) { + auto SF = DC->getParentSourceFile(); + if (SF) + SF->registerAccessLevelUsingImport(import.value(), + AccessLevel::Package); + + auto &ctx = DC->getASTContext(); + if (ctx.LangOpts.EnableModuleApiImportRemarks) { + ModuleDecl *importedVia = import->module.importedModule, + *sourceModule = ED->getModuleContext(); + ED->diagnose(diag::module_api_import, + ED, importedVia, sourceModule, + importedVia == sourceModule, + /*isImplicit*/false); + } + } +} + void swift::checkAccessControl(Decl *D) { if (isa(D) || isa(D)) { bool allowInlineable = @@ -2619,6 +2602,7 @@ void swift::checkAccessControl(Decl *D) { UsableFromInlineChecker().visit(D); } else if (auto *ED = dyn_cast(D)) { checkExtensionGenericParamAccess(ED); + registerPackageAccessForPackageExtendedType(ED); } if (isa(D)) diff --git a/lib/Sema/TypeCheckAccess.h b/lib/Sema/TypeCheckAccess.h index b448da2fac608..6291c1de9d419 100644 --- a/lib/Sema/TypeCheckAccess.h +++ b/lib/Sema/TypeCheckAccess.h @@ -47,8 +47,7 @@ enum class DisallowedOriginKind : uint8_t { SPIOnly, MissingImport, FragileCxxAPI, - InternalOrLessImport, - PackageImport, + NonPublicImport, None }; diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index ec6312eb4f685..9ccb09655a4ec 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -44,12 +44,10 @@ using namespace swift; ExportContext::ExportContext( DeclContext *DC, AvailabilityContext runningOSVersion, - FragileFunctionKind kind, bool spi, bool isPackage, - bool exported, bool implicit, bool deprecated, - std::optional unavailablePlatformKind) + FragileFunctionKind kind, bool spi, bool exported, bool implicit, + bool deprecated, std::optional unavailablePlatformKind) : DC(DC), RunningOSVersion(runningOSVersion), FragileKind(kind) { SPI = spi; - IsPackage = isPackage; Exported = exported; Implicit = implicit; Deprecated = deprecated; @@ -74,7 +72,7 @@ bool swift::isExported(const ValueDecl *VD) { AccessScope accessScope = VD->getFormalAccessScope(nullptr, /*treatUsableFromInlineAsPublic*/true); - if (accessScope.isPublicOrPackage()) + if (accessScope.isPublic()) return true; // Is this a stored property in a @frozen struct or class? @@ -85,13 +83,13 @@ bool swift::isExported(const ValueDecl *VD) { return false; } -static bool hasConformancesToPublicOrPackageProtocols(const ExtensionDecl *ED) { +static bool hasConformancesToPublicProtocols(const ExtensionDecl *ED) { auto protocols = ED->getLocalProtocols(ConformanceLookupKind::OnlyExplicit); for (const ProtocolDecl *PD : protocols) { AccessScope scope = PD->getFormalAccessScope(/*useDC*/ nullptr, /*treatUsableFromInlineAsPublic*/ true); - if (scope.isPublicOrPackage()) + if (scope.isPublic()) return true; } @@ -113,7 +111,7 @@ bool swift::isExported(const ExtensionDecl *ED) { // If the extension declares a conformance to a public protocol then the // extension is exported. - if (hasConformancesToPublicOrPackageProtocols(ED)) + if (hasConformancesToPublicProtocols(ED)) return true; return false; @@ -186,20 +184,13 @@ static void forEachOuterDecl(DeclContext *DC, Fn fn) { } static void -computeExportContextBits(ASTContext &Ctx, Decl *D, - bool *spi, bool *isPackage, - bool *implicit, bool *deprecated, +computeExportContextBits(ASTContext &Ctx, Decl *D, bool *spi, bool *implicit, + bool *deprecated, std::optional *unavailablePlatformKind) { if (D->isSPI() || D->isAvailableAsSPI()) *spi = true; - if (auto VD = dyn_cast(D)) { - *isPackage = VD->getFormalAccessScope(nullptr, true).isPackage(); - } else if (auto ED = dyn_cast(D)) { - *isPackage = ED->getDefaultAccessLevel() == AccessLevel::Package; - } - // Defer bodies are desugared to an implicit closure expression. We need to // dilute the meaning of "implicit" to make sure we're still checking // availability inside of defer statements. @@ -207,7 +198,7 @@ computeExportContextBits(ASTContext &Ctx, Decl *D, if (D->isImplicit() && !isDeferBody) *implicit = true; - if (D->getAttrs().getDeprecated(Ctx)) + if (D->getAttrs().isDeprecated(Ctx)) *deprecated = true; if (auto *A = D->getAttrs().getUnavailable(Ctx)) { @@ -217,8 +208,8 @@ computeExportContextBits(ASTContext &Ctx, Decl *D, if (auto *PBD = dyn_cast(D)) { for (unsigned i = 0, e = PBD->getNumPatternEntries(); i < e; ++i) { if (auto *VD = PBD->getAnchoringVarDecl(i)) - computeExportContextBits(Ctx, VD, spi, isPackage, implicit, - deprecated, unavailablePlatformKind); + computeExportContextBits(Ctx, VD, spi, implicit, deprecated, + unavailablePlatformKind); } } } @@ -233,25 +224,23 @@ ExportContext ExportContext::forDeclSignature(Decl *D) { ? AvailabilityContext::alwaysAvailable() : TypeChecker::overApproximateAvailabilityAtLocation(D->getLoc(), DC)); bool spi = Ctx.LangOpts.LibraryLevel == LibraryLevel::SPI; - bool isPackage = false; bool implicit = false; bool deprecated = false; std::optional unavailablePlatformKind; - computeExportContextBits(Ctx, D, &spi, &isPackage, &implicit, - &deprecated, &unavailablePlatformKind); - + computeExportContextBits(Ctx, D, &spi, &implicit, &deprecated, + &unavailablePlatformKind); forEachOuterDecl(D->getDeclContext(), [&](Decl *D) { computeExportContextBits(Ctx, D, - &spi, &isPackage, &implicit, - &deprecated, &unavailablePlatformKind); + &spi, &implicit, &deprecated, + &unavailablePlatformKind); }); bool exported = ::isExported(D); return ExportContext(DC, runningOSVersion, fragileKind, - spi, isPackage, exported, implicit, - deprecated, unavailablePlatformKind); + spi, exported, implicit, deprecated, + unavailablePlatformKind); } ExportContext ExportContext::forFunctionBody(DeclContext *DC, SourceLoc loc) { @@ -266,20 +255,19 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC, SourceLoc loc) { bool spi = Ctx.LangOpts.LibraryLevel == LibraryLevel::SPI; bool implicit = false; bool deprecated = false; - bool isPackage = false; std::optional unavailablePlatformKind; forEachOuterDecl(DC, [&](Decl *D) { computeExportContextBits(Ctx, D, - &spi, &isPackage, &implicit, - &deprecated, &unavailablePlatformKind); + &spi, &implicit, &deprecated, + &unavailablePlatformKind); }); bool exported = false; return ExportContext(DC, runningOSVersion, fragileKind, - spi, isPackage, exported, implicit, - deprecated, unavailablePlatformKind); + spi, exported, implicit, deprecated, + unavailablePlatformKind); } ExportContext ExportContext::forConformance(DeclContext *DC, @@ -288,7 +276,7 @@ ExportContext ExportContext::forConformance(DeclContext *DC, auto where = forDeclSignature(DC->getInnermostDeclarationDeclContext()); where.Exported &= proto->getFormalAccessScope( - DC, /*usableFromInlineAsPublic*/true).isPublicOrPackage(); + DC, /*usableFromInlineAsPublic*/true).isPublic(); return where; } @@ -4487,7 +4475,7 @@ void swift::checkExplicitAvailability(Decl *decl) { return false; }); - auto hasProtocols = hasConformancesToPublicOrPackageProtocols(extension); + auto hasProtocols = hasConformancesToPublicProtocols(extension); if (!hasMembers && !hasProtocols) return; diff --git a/lib/Sema/TypeCheckAvailability.h b/lib/Sema/TypeCheckAvailability.h index 6a527918c0231..a8badf06c1246 100644 --- a/lib/Sema/TypeCheckAvailability.h +++ b/lib/Sema/TypeCheckAvailability.h @@ -73,10 +73,7 @@ enum class ExportabilityReason : unsigned { ResultBuilder, ExtensionWithPublicMembers, ExtensionWithConditionalConformances, - // Exported members of extension can be `package`. - ExtensionWithPackageMembers, - // Exported inheritance type can be `package`. - ExtensionWithPackageConditionalConformances + Inheritance }; /// A description of the restrictions on what declarations can be referenced @@ -84,12 +81,9 @@ enum class ExportabilityReason : unsigned { /// /// We say a declaration is "exported" if all of the following holds: /// -/// - the declaration is `public` or `@usableFromInline` +/// - the declaration is `public` or `@usableFromInline` /// - the declaration is not `@_spi` /// - the declaration was not imported from an `@_implementationOnly` import -/// - the declaration is `package`; while treated as exported, the -/// scope is limited compared to `public` or `@usableFromInline`; -/// the `IsPackage` bit is set to track the scope. /// /// The "signature" of a declaration is the set of all types written in the /// declaration (such as function parameter and return types), but not @@ -112,7 +106,6 @@ class ExportContext { AvailabilityContext RunningOSVersion; FragileFunctionKind FragileKind; unsigned SPI : 1; - unsigned IsPackage : 1; unsigned Exported : 1; unsigned Deprecated : 1; unsigned Implicit : 1; @@ -121,7 +114,7 @@ class ExportContext { unsigned Reason : 3; ExportContext(DeclContext *DC, AvailabilityContext runningOSVersion, - FragileFunctionKind kind, bool spi, bool isPackage, bool exported, + FragileFunctionKind kind, bool spi, bool exported, bool implicit, bool deprecated, std::optional unavailablePlatformKind); @@ -176,9 +169,6 @@ class ExportContext { /// If true, the context is SPI and can reference SPI declarations. bool isSPI() const { return SPI; } - /// If true, the context has a package access scope. - bool isPackage() const { return IsPackage; } - /// If true, the context is exported and cannot reference SPI declarations /// or declarations from `@_implementationOnly` imports. bool isExported() const { return Exported; } diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 705ba0638e43d..e4fa80b81d166 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -2152,7 +2152,11 @@ namespace { .limitBehaviorUntilSwiftVersion(behavior, 6); } - // Always emit the note with fix-it. + // Overrides cannot be isolated to a global actor; the isolation + // must match the overridden decl. + if (fn->getOverriddenDecl()) + return false; + fn->diagnose(diag::add_globalactor_to_function, globalActor->getWithoutParens().getString(), fn, globalActor) @@ -4941,6 +4945,7 @@ static OverrideIsolationResult validOverrideIsolation( ValueDecl *overridden, ActorIsolation overriddenIsolation) { ConcreteDeclRef valueRef = getDeclRefInContext(value); auto declContext = value->getInnermostDeclContext(); + auto &ctx = declContext->getASTContext(); auto refResult = ActorReferenceResult::forReference( valueRef, SourceLoc(), declContext, std::nullopt, std::nullopt, isolation, @@ -4964,8 +4969,10 @@ static OverrideIsolationResult validOverrideIsolation( // If the overridden declaration is from Objective-C with no actor // annotation, allow it. - if (overridden->hasClangNode() && !overriddenIsolation) + if (ctx.LangOpts.StrictConcurrencyLevel != StrictConcurrency::Complete && + overridden->hasClangNode() && !overriddenIsolation) { return OverrideIsolationResult::Allowed; + } return OverrideIsolationResult::Disallowed; } diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index a45b20741383f..a65e2c4b1484b 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -154,6 +154,28 @@ class CheckRepressions { } }; +/// If the extension adds a conformance to an invertible protocol, ensure that +/// it does not add a conformance to any other protocol. So these are illegal: +/// +/// extension S: Copyable & P {} +/// extension S: Q, Copyable {} +/// +/// This policy is in place because extensions adding a conformance to an +/// invertible protocol do _not_ add default requirements on generic parameters, +/// so it would be confusing to mix them together in the same extension. +static void checkExtensionAddsSoloInvertibleProtocol(const ExtensionDecl *ext) { + auto localConfs = ext->getLocalConformances(); + if (localConfs.size() <= 1) + return; + + for (auto *conf : localConfs) { + if (auto ip = conf->getProtocol()->getInvertibleProtocolKind()) { + ext->diagnose(diag::extension_conforms_to_invertible_and_others, + getInvertibleProtocolKindName(*ip)); + } + } +} + /// Check the inheritance clause of a type declaration or extension thereof. /// /// This routine performs detailed checking of the inheritance clause of the @@ -295,10 +317,15 @@ static void checkInheritanceClause( auto layout = inheritedTy->getExistentialLayout(); // An inverse on an extension is an error. - if (isa(decl)) - if (auto pct = inheritedTy->getAs()) - if (!pct->getInverses().empty()) - decl->diagnose(diag::inverse_extension, inheritedTy); + if (isa(decl)) { + auto canInheritedTy = inheritedTy->getCanonicalType(); + if (auto pct = canInheritedTy->getAs()) { + for (auto inverse : pct->getInverses()) { + decl->diagnose(diag::inverse_extension, + getProtocolName(getKnownProtocolKind(inverse))); + } + } + } // Subclass existentials are not allowed except on classes and // non-@objc protocols. @@ -3974,6 +4001,8 @@ class DeclChecker : public DeclVisitor { diagnoseExtensionOfMarkerProtocol(ED); checkTupleExtension(ED); + + checkExtensionAddsSoloInvertibleProtocol(ED); } void visitTopLevelCodeDecl(TopLevelCodeDecl *TLCD) { diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 8340a855cdc9a..be330146cbda9 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -684,6 +684,7 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, SmallVector inferenceSources; SmallVector extraReqs; SourceLoc loc; + bool inferInvertibleReqs = true; if (auto VD = dyn_cast(GC->getAsDecl())) { loc = VD->getLoc(); @@ -781,6 +782,35 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, } else if (auto *ext = dyn_cast(GC)) { loc = ext->getLoc(); + // The inherited entries influence the generic signature of the extension, + // because if it introduces conformance to invertible protocol IP, we do not + // we do not infer any requirements that the generic parameters to conform + // to invertible protocols. This forces people to write out the conditions. + const unsigned numEntries = ext->getInherited().size(); + for (unsigned i = 0; i < numEntries; ++i) { + InheritedTypeRequest request{ext, i, TypeResolutionStage::Structural}; + auto result = evaluateOrDefault(ctx.evaluator, request, + InheritedTypeResult::forDefault()); + Type inheritedTy; + switch (result) { + case InheritedTypeResult::Inherited: + inheritedTy = result.getInheritedType(); + break; + case InheritedTypeResult::Suppressed: + case InheritedTypeResult::Default: + continue; + } + + if (inheritedTy) { + if (auto kp = inheritedTy->getKnownProtocol()) { + if (getInvertibleProtocolKind(*kp)) { + inferInvertibleReqs = false; + break; + } + } + } + } + collectAdditionalExtensionRequirements(ext->getExtendedType(), extraReqs); auto *extendedNominal = ext->getExtendedNominal(); @@ -800,7 +830,7 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, genericParams, WhereClauseOwner(GC), extraReqs, inferenceSources, loc, /*isExtension=*/isa(GC), - /*allowInverses=*/true}; + /*allowInverses=*/inferInvertibleReqs}; return evaluateOrDefault(ctx.evaluator, request, GenericSignatureWithError()).getPointer(); } diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 0785b7ef65069..e49cc30d891c6 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -743,6 +743,15 @@ RequirementMatch swift::matchWitness( reqTypeIsIUO != witnessTypeIsIUO) return RequirementMatch(witness, MatchKind::TypeConflict, witnessType); + // If our requirement says that it has a sending result, then our witness + // must also have a sending result since otherwise, in generic contexts, + // we would be returning non-disconnected values as disconnected. + if (dc->getASTContext().LangOpts.isSwiftVersionAtLeast(6)) { + if (reqFnType->hasExtInfo() && reqFnType->hasSendingResult() && + (!witnessFnType->hasExtInfo() || !witnessFnType->hasSendingResult())) + return RequirementMatch(witness, MatchKind::TypeConflict, witnessType); + } + if (auto result = matchTypes(std::get<0>(types), std::get<1>(types))) { return std::move(result.value()); } @@ -775,6 +784,14 @@ RequirementMatch swift::matchWitness( if (reqParams[i].isInOut() != witnessParams[i].isInOut()) return RequirementMatch(witness, MatchKind::TypeConflict, witnessType); + // If we have a requirement without sending and our witness expects a + // sending parameter, error. + if (dc->getASTContext().isSwiftVersionAtLeast(6)) { + if (!reqParams[i].getParameterFlags().isSending() && + witnessParams[i].getParameterFlags().isSending()) + return RequirementMatch(witness, MatchKind::TypeConflict, witnessType); + } + auto reqParamDecl = reqParamList->get(i); auto witnessParamDecl = witnessParamList->get(i); @@ -1740,6 +1757,8 @@ checkWitnessAvailability(ValueDecl *requirement, RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement, const RequirementMatch &match) { + auto &ctx = getASTContext(); + if (!match.OptionalAdjustments.empty()) return CheckKind::OptionalityConflict; @@ -1769,7 +1788,7 @@ RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement, return RequirementCheck(CheckKind::Availability, requiredAvailability); } - if (requirement->getAttrs().isUnavailable(getASTContext()) && + if (requirement->getAttrs().isUnavailable(ctx) && match.Witness->getDeclContext() == DC) { return RequirementCheck(CheckKind::Unavailable); } @@ -1792,11 +1811,11 @@ RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement, } } - if (match.Witness->getAttrs().isUnavailable(getASTContext()) && - !requirement->getAttrs().isUnavailable(getASTContext())) { + if (match.Witness->getAttrs().isUnavailable(ctx) && + !requirement->getAttrs().isUnavailable(ctx)) { auto nominalOrExtensionIsUnavailable = [&]() { if (auto extension = dyn_cast(DC)) { - if (extension->getAttrs().isUnavailable(getASTContext())) + if (extension->getAttrs().isUnavailable(ctx)) return true; } @@ -1813,6 +1832,20 @@ RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement, return CheckKind::WitnessUnavailable; } + // Warn about deprecated default implementations if the requirement is + // not deprecated, and the conformance is not deprecated. + bool isDefaultWitness = false; + if (auto *nominal = match.Witness->getDeclContext()->getSelfNominalTypeDecl()) + isDefaultWitness = isa(nominal); + if (isDefaultWitness && + match.Witness->getAttrs().isDeprecated(ctx) && + !requirement->getAttrs().isDeprecated(ctx)) { + auto conformanceContext = ExportContext::forConformance(DC, Proto); + if (!conformanceContext.isDeprecated()) { + return RequirementCheck(CheckKind::DefaultWitnessDeprecated); + } + } + return CheckKind::Success; } @@ -4374,6 +4407,25 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { requirement->getName()); }); break; + + case CheckKind::DefaultWitnessDeprecated: + getASTContext().addDelayedConformanceDiag( + Conformance, /*isError=*/false, + [witness, requirement](NormalProtocolConformance *conformance) { + auto &ctx = witness->getASTContext(); + auto &diags = ctx.Diags; + SourceLoc diagLoc = getLocForDiagnosingWitness(conformance, witness); + auto *attr = witness->getAttrs().getDeprecated(ctx); + EncodedDiagnosticMessage EncodedMessage(attr->Message); + diags.diagnose(diagLoc, diag::witness_deprecated, + witness, conformance->getProtocol()->getName(), + EncodedMessage.Message); + emitDeclaredHereIfNeeded(diags, diagLoc, witness); + diags.diagnose(requirement, diag::kind_declname_declared_here, + DescriptiveDeclKind::Requirement, + requirement->getName()); + }); + break; } if (auto *classDecl = DC->getSelfClassDecl()) { diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 136d7b769ce33..c99907667359b 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -3393,6 +3393,10 @@ TypeResolver::resolveAttributedType(TypeRepr *repr, TypeResolutionOptions option diagnoseInvalid(repr, repr->getLoc(), diag::escaping_optional_type_argument) .fixItRemove(attrRange); + } else if (options.is(TypeResolverContext::InoutFunctionInput)) { + diagnoseInvalid(repr, repr->getLoc(), + diag::escaping_inout_parameter) + .fixItRemove(attrRange); } else { diagnoseInvalid(repr, loc, diag::escaping_non_function_parameter) .fixItRemove(attrRange); @@ -4960,7 +4964,8 @@ TypeResolver::resolveSendingTypeRepr(SendingTypeRepr *repr, return ErrorType::get(getASTContext()); } - if (!options.is(TypeResolverContext::FunctionResult) && + if (!options.is(TypeResolverContext::ClosureExpr) && + !options.is(TypeResolverContext::FunctionResult) && (!options.is(TypeResolverContext::FunctionInput) || options.hasBase(TypeResolverContext::EnumElementDecl))) { diagnoseInvalid(repr, repr->getSpecifierLoc(), @@ -5124,6 +5129,8 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType( bool doDiag = false; switch (options.getContext()) { + case TypeResolverContext::ExistentialConstraint: + break ; case TypeResolverContext::None: case TypeResolverContext::InoutFunctionInput: if (!isDirect || !(options & allowIUO)) @@ -5149,7 +5156,6 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType( case TypeResolverContext::TypeAliasDecl: case TypeResolverContext::GenericTypeAliasDecl: case TypeResolverContext::GenericRequirement: - case TypeResolverContext::ExistentialConstraint: case TypeResolverContext::SameTypeRequirement: case TypeResolverContext::ProtocolMetatypeBase: case TypeResolverContext::MetatypeBase: @@ -5645,6 +5651,20 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr, return composition; } + +bool shouldDiagnoseImplicitlyUnwrappedOptionalType(TypeResolutionOptions options) { + if ( + // to match `let _: (Int, any P!)` + options.is(TypeResolverContext::TupleElement) || + // to match `let _: G` + options.is(TypeResolverContext::ScalarGenericArgument) || + // because `let _ = (any P!) -> Void` is illegal, but not `let _ = any P!` + !options.is(TypeResolverContext::PatternBindingDecl)) { + return true; + } + return false; +} + NeverNullType TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr, TypeResolutionOptions options) { @@ -5659,6 +5679,23 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr, //TO-DO: generalize this and emit the same erorr for some P? if (!constraintType->isConstraintType()) { + auto wrapped = constraintType->getOptionalObjectType(); + + auto isWrappedExistential = (wrapped && (wrapped->is() || wrapped->is())) ; + auto shouldDiagnoseImplicitlyUnwrappedOptional = shouldDiagnoseImplicitlyUnwrappedOptionalType(options); + auto isImplicitlyUnwrapped = isa(repr->getConstraint()) ; + auto mm = dyn_cast(repr->getConstraint()); + // Handles cases like `let _: any P!` by suggesting `let _: (any P)! + // while making sure that it's not an existential wrapped in a tuple like `let _: (Int, any P!)` + // so we won't suggest `let _: (Int, (any P)!)` as it's illegal. + if (isImplicitlyUnwrapped && !shouldDiagnoseImplicitlyUnwrappedOptional && isWrappedExistential) { + diagnose(repr->getLoc(), + diag::incorrect_iuo_any, + wrapped->getMetatypeInstanceType().getString()) + .fixItReplace(repr->getSourceRange(), "(" + wrapped.getString() + ")!"); + return constraintType; + } + // Emit a tailored diagnostic for the incorrect optional // syntax 'any P?' with a fix-it to add parenthesis. auto wrapped = constraintType->getOptionalObjectType(); @@ -5667,8 +5704,7 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr, std::string fix; llvm::raw_string_ostream OS(fix); constraintType->print(OS, PrintOptions::forDiagnosticArguments()); - diagnose(repr->getLoc(), diag::incorrect_optional_any, - constraintType) + diagnose(repr->getLoc(), diag::incorrect_optional_any) .fixItReplace(repr->getSourceRange(), fix); return constraintType; } diff --git a/lib/Sema/TypeCheckType.h b/lib/Sema/TypeCheckType.h index e3ac2bd5388b1..40415a0614b56 100644 --- a/lib/Sema/TypeCheckType.h +++ b/lib/Sema/TypeCheckType.h @@ -118,7 +118,7 @@ enum class TypeResolverContext : uint8_t { /// Whether we are checking the parameter list of a subscript. SubscriptDecl, - /// Whether we are checking the parameter list of a closure. + /// Whether we are checking the parameter list or result of a closure. ClosureExpr, /// Whether we are in the input type of a function, or under one level of diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 752747a6f6c6c..1bdf847588bbc 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -8857,12 +8857,13 @@ ModuleFile::maybeReadLifetimeDependenceInfo(unsigned numParams) { return std::nullopt; } + bool isImmortal; bool hasInheritLifetimeParamIndices; bool hasScopeLifetimeParamIndices; ArrayRef lifetimeDependenceData; - LifetimeDependenceLayout::readRecord(scratch, hasInheritLifetimeParamIndices, - hasScopeLifetimeParamIndices, - lifetimeDependenceData); + LifetimeDependenceLayout::readRecord( + scratch, isImmortal, hasInheritLifetimeParamIndices, + hasScopeLifetimeParamIndices, lifetimeDependenceData); SmallBitVector inheritLifetimeParamIndices(numParams, false); SmallBitVector scopeLifetimeParamIndices(numParams, false); @@ -8891,5 +8892,6 @@ ModuleFile::maybeReadLifetimeDependenceInfo(unsigned numParams) { : nullptr, hasScopeLifetimeParamIndices ? IndexSubset::get(ctx, scopeLifetimeParamIndices) - : nullptr); + : nullptr, + isImmortal); } diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 9130c64b1b0ea..2ae35a9daae0c 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,8 @@ 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 = 877; // extend_lifetime instruction +const uint16_t SWIFTMODULE_VERSION_MINOR = + 878; // immortal bit in LifetimeDependence /// A standard hash seed used for all string hashes in a serialized module. /// @@ -2212,6 +2213,7 @@ namespace decls_block { using LifetimeDependenceLayout = BCRecordLayout, // isImmortal BCFixed<1>, // hasInheritLifetimeParamIndices BCFixed<1>, // hasScopeLifetimeParamIndices BCArray> // concatenated param indices diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 21dd5445f6165..51e4c1f74e2ad 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -2579,7 +2579,7 @@ void Serializer::writeLifetimeDependenceInfo( auto abbrCode = DeclTypeAbbrCodes[LifetimeDependenceLayout::Code]; LifetimeDependenceLayout::emitRecord( - Out, ScratchRecord, abbrCode, + Out, ScratchRecord, abbrCode, lifetimeDependenceInfo.isImmortal(), lifetimeDependenceInfo.hasInheritLifetimeParamIndices(), lifetimeDependenceInfo.hasScopeLifetimeParamIndices(), paramIndices); } diff --git a/stdlib/public/ClangOverlays/float.swift.gyb b/stdlib/public/ClangOverlays/float.swift.gyb index 2f29d1b8fdb48..e0b2e8af3ae3c 100644 --- a/stdlib/public/ClangOverlays/float.swift.gyb +++ b/stdlib/public/ClangOverlays/float.swift.gyb @@ -25,7 +25,7 @@ public let FLT_RADIX = Double.radix // significand bit, but Swift does not. Neither is really right or wrong. @available(swift, deprecated: 3.0, message: "Please use '${type}.significandBitCount + 1'.") @available(macOS 10.9, iOS 7.0, watchOS 2.0, tvOS 9.0, *) -@_originallyDefinedIn(module: "Darwin", macOS 9999, iOS 9999, watchOS 9999, tvOS 9999) +@_originallyDefinedIn(module: "Darwin", macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0) public let ${prefix}_MANT_DIG = ${type}.significandBitCount + 1 // Where does the 1 come from? C models floating-point numbers as having a @@ -34,32 +34,32 @@ public let ${prefix}_MANT_DIG = ${type}.significandBitCount + 1 // as well. @available(swift, deprecated: 3.0, message: "Please use '${type}.greatestFiniteMagnitude.exponent + 1'.") @available(macOS 10.9, iOS 7.0, watchOS 2.0, tvOS 9.0, *) -@_originallyDefinedIn(module: "Darwin", macOS 9999, iOS 9999, watchOS 9999, tvOS 9999) +@_originallyDefinedIn(module: "Darwin", macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0) public let ${prefix}_MAX_EXP = ${type}.greatestFiniteMagnitude.exponent + 1 @available(swift, deprecated: 3.0, message: "Please use '${type}.leastNormalMagnitude.exponent + 1'.") @available(macOS 10.9, iOS 7.0, watchOS 2.0, tvOS 9.0, *) -@_originallyDefinedIn(module: "Darwin", macOS 9999, iOS 9999, watchOS 9999, tvOS 9999) +@_originallyDefinedIn(module: "Darwin", macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0) public let ${prefix}_MIN_EXP = ${type}.leastNormalMagnitude.exponent + 1 @available(swift, deprecated: 3.0, message: "Please use '${type}.greatestFiniteMagnitude' or '.greatestFiniteMagnitude'.") @available(macOS 10.9, iOS 7.0, watchOS 2.0, tvOS 9.0, *) -@_originallyDefinedIn(module: "Darwin", macOS 9999, iOS 9999, watchOS 9999, tvOS 9999) +@_originallyDefinedIn(module: "Darwin", macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0) public let ${prefix}_MAX = ${type}.greatestFiniteMagnitude @available(swift, deprecated: 3.0, message: "Please use '${type}.ulpOfOne' or '.ulpOfOne'.") @available(macOS 10.9, iOS 7.0, watchOS 2.0, tvOS 9.0, *) -@_originallyDefinedIn(module: "Darwin", macOS 9999, iOS 9999, watchOS 9999, tvOS 9999) +@_originallyDefinedIn(module: "Darwin", macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0) public let ${prefix}_EPSILON = ${type}.ulpOfOne @available(swift, deprecated: 3.0, message: "Please use '${type}.leastNormalMagnitude' or '.leastNormalMagnitude'.") @available(macOS 10.9, iOS 7.0, watchOS 2.0, tvOS 9.0, *) -@_originallyDefinedIn(module: "Darwin", macOS 9999, iOS 9999, watchOS 9999, tvOS 9999) +@_originallyDefinedIn(module: "Darwin", macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0) public let ${prefix}_MIN = ${type}.leastNormalMagnitude @available(swift, deprecated: 3.0, message: "Please use '${type}.leastNonzeroMagnitude' or '.leastNonzeroMagnitude'.") @available(macOS 10.9, iOS 7.0, watchOS 2.0, tvOS 9.0, *) -@_originallyDefinedIn(module: "Darwin", macOS 9999, iOS 9999, watchOS 9999, tvOS 9999) +@_originallyDefinedIn(module: "Darwin", macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0) public let ${prefix}_TRUE_MIN = ${type}.leastNonzeroMagnitude % if type == "Float80": diff --git a/stdlib/public/Concurrency/Executor.swift b/stdlib/public/Concurrency/Executor.swift index b09d89b2cea05..c153988c3159c 100644 --- a/stdlib/public/Concurrency/Executor.swift +++ b/stdlib/public/Concurrency/Executor.swift @@ -498,8 +498,9 @@ internal func _task_serialExecutor_getExecutorRef(_ executor: E) -> Builtin.E /// The obtained executor ref will have all the user-defined flags set on the executor. @_unavailableInEmbedded @available(SwiftStdlib 6.0, *) -@_silgen_name("_task_executor_getTaskExecutorRef") -internal func _task_executor_getTaskExecutorRef(_ taskExecutor: any TaskExecutor) -> Builtin.Executor { +@_silgen_name("_task_taskExecutor_getTaskExecutorRef") +internal func _task_taskExecutor_getTaskExecutorRef(_ taskExecutor: E) -> Builtin.Executor + where E: TaskExecutor { return taskExecutor.asUnownedTaskExecutor().executor } diff --git a/stdlib/public/Concurrency/GlobalActor.swift b/stdlib/public/Concurrency/GlobalActor.swift index 72f0657a6de28..d866ec61aab45 100644 --- a/stdlib/public/Concurrency/GlobalActor.swift +++ b/stdlib/public/Concurrency/GlobalActor.swift @@ -22,6 +22,25 @@ import Swift /// such a declaration from another actor (or from nonisolated code), /// synchronization is performed through the shared actor instance to ensure /// mutually-exclusive access to the declaration. +/// +/// ## Custom Actor Executors +/// A global actor use a custom executor if it needs to customize its execution +/// semantics, for example, by making sure all of its invocations are run on a +/// specific thread or dispatch queue. +/// +/// This is done the same way as with normal non-global actors, by declaring a +/// ``Actor/unownedExecutor`` nonisolated property in the ``ActorType`` +/// underlying this global actor. +/// +/// It is *not* necessary to override the ``sharedUnownedExecutor`` static +/// property of the global actor, as its default implementation already +/// delegates to the ``shared.unownedExecutor``, which is the most reasonable +/// and correct implementation of this protocol requirement. +/// +/// You can find out more about custom executors, by referring to the +/// ``SerialExecutor`` protocol's documentation. +/// +/// - SeeAlso: ``SerialExecutor`` @available(SwiftStdlib 5.1, *) public protocol GlobalActor { /// The type of the shared actor instance that will be used to provide @@ -36,10 +55,22 @@ public protocol GlobalActor { /// instance. static var shared: ActorType { get } - /// The shared executor instance that will be used to provide - /// mutually-exclusive access for the global actor. + /// Shorthand for referring to the `shared.unownedExecutor` of this global actor. + /// + /// When declaring a global actor with a custom executor, prefer to implement + /// the underlying actor's ``Actor/unownedExecutor`` property, and leave this + /// `sharedUnownedExecutor` default implementation in-place as it will simply + /// delegate to the `shared.unownedExecutor`. + /// + /// The value of this property must be equivalent to `shared.unownedExecutor`, + /// as may be used by the Swift concurrency runtime or explicit user code. with + /// that assumption in mind. + /// + /// Returning different executors for different invocations of this computed + /// property is also illegal, as it could lead to inconsistent synchronization + /// of the underlying actor. /// - /// The value of this property must be equivalent to `shared.unownedExecutor`. + /// - SeeAlso: ``SerialExecutor`` static var sharedUnownedExecutor: UnownedSerialExecutor { get } } diff --git a/stdlib/public/Concurrency/GlobalExecutor.cpp b/stdlib/public/Concurrency/GlobalExecutor.cpp index b0d0d4334c411..f4c8ed1ee05ff 100644 --- a/stdlib/public/Concurrency/GlobalExecutor.cpp +++ b/stdlib/public/Concurrency/GlobalExecutor.cpp @@ -161,18 +161,6 @@ SerialExecutorRef _task_serialExecutor_getExecutorRef( const SerialExecutorWitnessTable *wtable); #pragma clang diagnostic pop -// Implemented in Swift because we need to obtain the user-defined flags on the executor ref. -// -// We could inline this with effort, though. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" -extern "C" SWIFT_CC(swift) -TaskExecutorRef _task_executor_getTaskExecutorRef( - HeapObject *executor, const Metadata *selfType, - const SerialExecutorWitnessTable *wtable); -#pragma clang diagnostic pop - - /// WARNING: This method is expected to CRASH in new runtimes, and cannot be /// used to implement "log warnings" mode. We would need a new entry point to /// implement a "only log warnings" actor isolation checking mode, and it would diff --git a/stdlib/public/Concurrency/Task+TaskExecutor.swift b/stdlib/public/Concurrency/Task+TaskExecutor.swift index ec0003d6542f1..18eee082a8e93 100644 --- a/stdlib/public/Concurrency/Task+TaskExecutor.swift +++ b/stdlib/public/Concurrency/Task+TaskExecutor.swift @@ -221,7 +221,7 @@ extension Task where Failure == Never { @discardableResult @_alwaysEmitIntoClient public init( - executorPreference taskExecutor: (any TaskExecutor)?, + executorPreference taskExecutor: consuming (any TaskExecutor)?, priority: TaskPriority? = nil, operation: __owned @Sendable @escaping () async -> Success ) { @@ -229,7 +229,7 @@ extension Task where Failure == Never { self = Self.init(priority: priority, operation: operation) return } - #if $BuiltinCreateAsyncTaskWithExecutor + #if $BuiltinCreateAsyncTaskWithExecutor && $BuiltinCreateTask // Set up the job flags for a new task. let flags = taskCreateFlags( priority: priority, isChildTask: false, copyTaskLocals: true, @@ -237,15 +237,14 @@ extension Task where Failure == Never { addPendingGroupTaskUnconditionally: false, isDiscardingTask: false) - // Create the asynchronous task. - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor + let (task, _) = Builtin.createTask( + flags: flags, + initialTaskExecutorConsuming: taskExecutor, + operation: operation) - let (task, _) = Builtin.createAsyncTaskWithExecutor( - flags, executorBuiltin, operation) self._task = task #else - fatalError("Unsupported Swift compiler, missing support for BuiltinCreateAsyncTaskWithExecutor") + fatalError("Unsupported Swift compiler, missing support for BuiltinCreateAsyncTaskWithExecutor or $BuiltinCreateTask") #endif } } @@ -282,7 +281,7 @@ extension Task where Failure == Error { @discardableResult @_alwaysEmitIntoClient public init( - executorPreference taskExecutor: (any TaskExecutor)?, + executorPreference taskExecutor: consuming (any TaskExecutor)?, priority: TaskPriority? = nil, operation: __owned @Sendable @escaping () async throws -> Success ) { @@ -290,7 +289,7 @@ extension Task where Failure == Error { self = Self.init(priority: priority, operation: operation) return } - #if $BuiltinCreateAsyncTaskWithExecutor + #if $BuiltinCreateAsyncTaskWithExecutor && $BuiltinCreateTask // Set up the job flags for a new task. let flags = taskCreateFlags( priority: priority, isChildTask: false, copyTaskLocals: true, @@ -298,14 +297,14 @@ extension Task where Failure == Error { addPendingGroupTaskUnconditionally: false, isDiscardingTask: false) - // Create the asynchronous task. - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - let (task, _) = Builtin.createAsyncTaskWithExecutor( - flags, executorBuiltin, operation) + let (task, _) = Builtin.createTask( + flags: flags, + initialTaskExecutorConsuming: taskExecutor, + operation: operation) + self._task = task #else - fatalError("Unsupported Swift compiler, missing support for $BuiltinCreateAsyncTaskWithExecutor") + fatalError("Unsupported Swift compiler, missing support for BuiltinCreateAsyncTaskWithExecutor or $BuiltinCreateTask") #endif } } @@ -348,7 +347,7 @@ extension Task where Failure == Never { guard let taskExecutor else { return Self.detached(priority: priority, operation: operation) } - #if $BuiltinCreateAsyncTaskWithExecutor + #if $BuiltinCreateAsyncTaskWithExecutor && $BuiltinCreateTask // Set up the job flags for a new task. let flags = taskCreateFlags( priority: priority, isChildTask: false, copyTaskLocals: false, @@ -356,15 +355,15 @@ extension Task where Failure == Never { addPendingGroupTaskUnconditionally: false, isDiscardingTask: false) - // Create the asynchronous task. - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - let (task, _) = Builtin.createAsyncTaskWithExecutor( - flags, executorBuiltin, operation) + let (task, _) = Builtin.createTask( + flags: flags, + // initialTaskExecutor: executorBuiltin, deprecated + initialTaskExecutorConsuming: taskExecutor, + operation: operation) return Task(task) #else - fatalError("Unsupported Swift compiler") + fatalError("Unsupported Swift compiler, missing support for BuiltinCreateAsyncTaskWithExecutor or $BuiltinCreateTask") #endif } } @@ -407,7 +406,7 @@ extension Task where Failure == Error { guard let taskExecutor else { return Self.detached(priority: priority, operation: operation) } - #if $BuiltinCreateAsyncTaskWithExecutor + #if $BuiltinCreateAsyncTaskWithExecutor && $BuiltinCreateTask // Set up the job flags for a new task. let flags = taskCreateFlags( priority: priority, isChildTask: false, copyTaskLocals: false, @@ -415,15 +414,14 @@ extension Task where Failure == Error { addPendingGroupTaskUnconditionally: false, isDiscardingTask: false) - // Create the asynchronous task. - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - let (task, _) = Builtin.createAsyncTaskWithExecutor( - flags, executorBuiltin, operation) + let (task, _) = Builtin.createTask( + flags: flags, + initialTaskExecutorConsuming: taskExecutor, + operation: operation) return Task(task) #else - fatalError("Unsupported Swift compiler") + fatalError("Unsupported Swift compiler, missing support for BuiltinCreateAsyncTaskWithExecutor or $BuiltinCreateTask") #endif } } diff --git a/stdlib/public/Concurrency/Task.cpp b/stdlib/public/Concurrency/Task.cpp index 13f8f19e759e7..499d85e34908d 100644 --- a/stdlib/public/Concurrency/Task.cpp +++ b/stdlib/public/Concurrency/Task.cpp @@ -192,6 +192,27 @@ FutureFragment::Status AsyncTask::waitFuture(AsyncTask *waitingTask, } } +// Implemented in Swift because we need to obtain the user-defined flags on the executor ref. +// +// We could inline this with effort, though. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +extern "C" SWIFT_CC(swift) +TaskExecutorRef _task_taskExecutor_getTaskExecutorRef( + HeapObject *executor, const Metadata *selfType, + const TaskExecutorWitnessTable *wtable); +#pragma clang diagnostic pop + +TaskExecutorRef +InitialTaskExecutorOwnedPreferenceTaskOptionRecord::getExecutorRefFromUnownedTaskExecutor() const { + TaskExecutorRef executorRef = _task_taskExecutor_getTaskExecutorRef( + Identity, + /*selfType=*/swift_getObjectType(Identity), + /*wtable=*/WitnessTable); + return executorRef; +} + + void NullaryContinuationJob::process(Job *_job) { auto *job = cast(_job); @@ -652,6 +673,7 @@ swift_task_create_commonImpl(size_t rawTaskCreateFlags, // Collect the options we know about. SerialExecutorRef serialExecutor = SerialExecutorRef::generic(); TaskExecutorRef taskExecutor = TaskExecutorRef::undefined(); + bool taskExecutorIsOwned = false; TaskGroup *group = nullptr; AsyncLet *asyncLet = nullptr; bool hasAsyncLetResultBuffer = false; @@ -663,10 +685,22 @@ swift_task_create_commonImpl(size_t rawTaskCreateFlags, ->getExecutorRef(); break; - case TaskOptionRecordKind::InitialTaskExecutor: - taskExecutor = cast(option) + case TaskOptionRecordKind::InitialTaskExecutorUnowned: + taskExecutor = cast(option) ->getExecutorRef(); jobFlags.task_setHasInitialTaskExecutorPreference(true); + taskExecutorIsOwned = false; + break; + + case TaskOptionRecordKind::InitialTaskExecutorOwned: + #if SWIFT_CONCURRENCY_EMBEDDED + swift_unreachable("owned TaskExecutor cannot be used in embedded Swift"); + #else + taskExecutor = cast(option) + ->getExecutorRefFromUnownedTaskExecutor(); + taskExecutorIsOwned = true; + jobFlags.task_setHasInitialTaskExecutorPreference(true); + #endif break; case TaskOptionRecordKind::TaskGroup: @@ -1078,7 +1112,8 @@ swift_task_create_commonImpl(size_t rawTaskCreateFlags, // Implementation note: we must do this AFTER `swift_taskGroup_attachChild` // because the group takes a fast-path when attaching the child record. assert(jobFlags.task_hasInitialTaskExecutorPreference()); - task->pushInitialTaskExecutorPreference(taskExecutor); + task->pushInitialTaskExecutorPreference( + taskExecutor, /*owned=*/taskExecutorIsOwned); } // If we're supposed to enqueue the task, do so now. diff --git a/stdlib/public/Concurrency/Task.swift b/stdlib/public/Concurrency/Task.swift index d9f67da42bc85..36380ac157bc0 100644 --- a/stdlib/public/Concurrency/Task.swift +++ b/stdlib/public/Concurrency/Task.swift @@ -101,7 +101,6 @@ import Swift /// var result: Work? /// /// deinit { -/// assert(work != nil) /// // even though the task is still retained, /// // once it completes it no longer causes a reference cycle with the actor /// @@ -124,7 +123,7 @@ import Swift /// And using it like this: /// /// ``` -/// await Actor().start() +/// await Worker().start() /// ``` /// /// Note that the actor is only retained by the start() method's use of `self`, @@ -135,7 +134,7 @@ import Swift /// /// Therefore, the above call will consistently result in the following output: /// -/// ``` +/// ```other /// start task work /// completed task work /// deinit actor diff --git a/stdlib/public/Concurrency/TaskGroup+TaskExecutor.swift b/stdlib/public/Concurrency/TaskGroup+TaskExecutor.swift index 199c90ba6afcc..20a5a6d885a7e 100644 --- a/stdlib/public/Concurrency/TaskGroup+TaskExecutor.swift +++ b/stdlib/public/Concurrency/TaskGroup+TaskExecutor.swift @@ -47,9 +47,6 @@ extension TaskGroup { addPendingGroupTaskUnconditionally: true, isDiscardingTask: false) - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - // Create the task in this group with an executor preference. #if $BuiltinCreateTask let builtinSerialExecutor = @@ -58,7 +55,7 @@ extension TaskGroup { _ = Builtin.createTask(flags: flags, initialSerialExecutor: builtinSerialExecutor, taskGroup: _group, - initialTaskExecutor: executorBuiltin, + initialTaskExecutorConsuming: taskExecutor, operation: operation) #else _ = Builtin.createAsyncTaskInGroupWithExecutor(flags, _group, executorBuiltin, operation) @@ -105,9 +102,6 @@ extension TaskGroup { addPendingGroupTaskUnconditionally: false, isDiscardingTask: false) - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - // Create the task in this group with an executor preference. #if $BuiltinCreateTask let builtinSerialExecutor = @@ -116,7 +110,7 @@ extension TaskGroup { _ = Builtin.createTask(flags: flags, initialSerialExecutor: builtinSerialExecutor, taskGroup: _group, - initialTaskExecutor: executorBuiltin, + initialTaskExecutorConsuming: taskExecutor, operation: operation) #else _ = Builtin.createAsyncTaskInGroupWithExecutor(flags, _group, executorBuiltin, operation) @@ -162,9 +156,6 @@ extension ThrowingTaskGroup { addPendingGroupTaskUnconditionally: true, isDiscardingTask: false) - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - // Create the task in this group with an executor preference. #if $BuiltinCreateTask let builtinSerialExecutor = @@ -173,7 +164,7 @@ extension ThrowingTaskGroup { _ = Builtin.createTask(flags: flags, initialSerialExecutor: builtinSerialExecutor, taskGroup: _group, - initialTaskExecutor: executorBuiltin, + initialTaskExecutorConsuming: taskExecutor, operation: operation) #else _ = Builtin.createAsyncTaskInGroupWithExecutor(flags, _group, executorBuiltin, operation) @@ -216,9 +207,6 @@ extension ThrowingTaskGroup { addPendingGroupTaskUnconditionally: false, isDiscardingTask: false) - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - // Create the task in this group with an executor preference. #if $BuiltinCreateTask let builtinSerialExecutor = @@ -227,7 +215,7 @@ extension ThrowingTaskGroup { _ = Builtin.createTask(flags: flags, initialSerialExecutor: builtinSerialExecutor, taskGroup: _group, - initialTaskExecutor: executorBuiltin, + initialTaskExecutorConsuming: taskExecutor, operation: operation) #else _ = Builtin.createAsyncTaskInGroupWithExecutor(flags, _group, executorBuiltin, operation) @@ -273,9 +261,6 @@ extension DiscardingTaskGroup { addPendingGroupTaskUnconditionally: true, isDiscardingTask: true) - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - // Create the task in this group with an executor preference. #if $BuiltinCreateTask let builtinSerialExecutor = @@ -284,7 +269,7 @@ extension DiscardingTaskGroup { _ = Builtin.createTask(flags: flags, initialSerialExecutor: builtinSerialExecutor, taskGroup: _group, - initialTaskExecutor: executorBuiltin, + initialTaskExecutorConsuming: taskExecutor, operation: operation) #else _ = Builtin.createAsyncDiscardingTaskInGroupWithExecutor(flags, _group, executorBuiltin, operation) @@ -332,9 +317,6 @@ extension DiscardingTaskGroup { addPendingGroupTaskUnconditionally: false, isDiscardingTask: true ) - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - // Create the task in this group with an executor preference. #if $BuiltinCreateTask let builtinSerialExecutor = @@ -343,7 +325,7 @@ extension DiscardingTaskGroup { _ = Builtin.createTask(flags: flags, initialSerialExecutor: builtinSerialExecutor, taskGroup: _group, - initialTaskExecutor: executorBuiltin, + initialTaskExecutorConsuming: taskExecutor, operation: operation) #else _ = Builtin.createAsyncDiscardingTaskInGroupWithExecutor(flags, _group, executorBuiltin, operation) @@ -389,9 +371,6 @@ extension ThrowingDiscardingTaskGroup { addPendingGroupTaskUnconditionally: true, isDiscardingTask: true) - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - // Create the task in this group with an executor preference. #if $BuiltinCreateTask let builtinSerialExecutor = @@ -400,7 +379,7 @@ extension ThrowingDiscardingTaskGroup { _ = Builtin.createTask(flags: flags, initialSerialExecutor: builtinSerialExecutor, taskGroup: _group, - initialTaskExecutor: executorBuiltin, + initialTaskExecutorConsuming: taskExecutor, operation: operation) #else _ = Builtin.createAsyncDiscardingTaskInGroupWithExecutor(flags, _group, executorBuiltin, operation) @@ -448,9 +427,6 @@ extension ThrowingDiscardingTaskGroup { addPendingGroupTaskUnconditionally: false, isDiscardingTask: true ) - let executorBuiltin: Builtin.Executor = - taskExecutor.asUnownedTaskExecutor().executor - // Create the task in this group with an executor preference. #if $BuiltinCreateTask let builtinSerialExecutor = @@ -459,7 +435,7 @@ extension ThrowingDiscardingTaskGroup { _ = Builtin.createTask(flags: flags, initialSerialExecutor: builtinSerialExecutor, taskGroup: _group, - initialTaskExecutor: executorBuiltin, + initialTaskExecutorConsuming: taskExecutor, operation: operation) #else _ = Builtin.createAsyncDiscardingTaskInGroupWithExecutor(flags, _group, executorBuiltin, operation) diff --git a/stdlib/public/Concurrency/TaskGroup.swift b/stdlib/public/Concurrency/TaskGroup.swift index 4692ad2451493..3376e7389fdd7 100644 --- a/stdlib/public/Concurrency/TaskGroup.swift +++ b/stdlib/public/Concurrency/TaskGroup.swift @@ -545,7 +545,7 @@ public struct TaskGroup { /// to wait for all the child tasks to complete, /// collecting the values they returned: /// - /// while let first = try await group.next() { + /// while let value = try await group.next() { /// collected += value /// } /// return collected @@ -1211,6 +1211,29 @@ extension TaskGroup: AsyncSequence { return element } + /// Advances to and returns the result of the next child task. + /// + /// The elements returned from this method + /// appear in the order that the tasks *completed*, + /// not in the order that those tasks were added to the task group. + /// After this method returns `nil`, + /// this iterator is guaranteed to never produce more values. + /// + /// For more information about the iteration order and semantics, + /// see `TaskGroup.next()`. + /// + /// - Returns: The value returned by the next child task that completes, + /// or `nil` if there are no remaining child tasks, + @available(SwiftStdlib 6.0, *) + public mutating func next(isolation actor: isolated (any Actor)?) async -> Element? { + guard !finished else { return nil } + guard let element = await group.next(isolation: actor) else { + finished = true + return nil + } + return element + } + public mutating func cancel() { finished = true group.cancelAll() @@ -1324,7 +1347,7 @@ extension ThrowingTaskGroup: AsyncSequence { public mutating func next(isolation actor: isolated (any Actor)?) async throws(Failure) -> Element? { guard !finished else { return nil } do { - guard let element = try await group.next() else { + guard let element = try await group.next(isolation: actor) else { finished = true return nil } diff --git a/stdlib/public/Concurrency/TaskPrivate.h b/stdlib/public/Concurrency/TaskPrivate.h index a7f9ed4af703b..247ecc51cdec5 100644 --- a/stdlib/public/Concurrency/TaskPrivate.h +++ b/stdlib/public/Concurrency/TaskPrivate.h @@ -791,7 +791,7 @@ struct AsyncTask::PrivateStorage { // elements are destroyed; in order to respect stack-discipline of // the task-local allocator. if (task->hasInitialTaskExecutorPreferenceRecord()) { - task->dropInitialTaskExecutorPreferenceRecord(); + task->dropInitialTaskExecutorPreferenceRecord(); } // Drain unlock the task and remove any overrides on thread as a diff --git a/stdlib/public/Concurrency/TaskStatus.cpp b/stdlib/public/Concurrency/TaskStatus.cpp index 6e8ff908308a7..d195ac66c807d 100644 --- a/stdlib/public/Concurrency/TaskStatus.cpp +++ b/stdlib/public/Concurrency/TaskStatus.cpp @@ -464,8 +464,8 @@ void swift::removeStatusRecordWhere( llvm::function_ref condition, llvm::function_ref updateStatus) { assert(condition && "condition is required"); - SWIFT_TASK_DEBUG_LOG("remove status record = %p, from task = %p", - record, task); + SWIFT_TASK_DEBUG_LOG("remove status record where(), from task = %p", + task); if (oldStatus.isStatusRecordLocked() && waitForStatusRecordUnlockIfNotSelfLocked(task, oldStatus)) { @@ -595,7 +595,7 @@ static bool swift_task_hasTaskGroupStatusRecordImpl() { ///************************** TASK EXECUTORS ********************************/ ///**************************************************************************/ -TaskExecutorRef AsyncTask::getPreferredTaskExecutor() { +TaskExecutorRef AsyncTask::getPreferredTaskExecutor(bool assumeHasRecord) { // We first check the executor preference status flag, in order to avoid // having to scan through the records of the task checking if there was // such record. @@ -644,7 +644,14 @@ swift_task_pushTaskExecutorPreferenceImpl(TaskExecutorRef taskExecutor) { void *allocation = _swift_task_alloc_specific( task, sizeof(class TaskExecutorPreferenceStatusRecord)); auto record = - ::new (allocation) TaskExecutorPreferenceStatusRecord(taskExecutor); + ::new (allocation) TaskExecutorPreferenceStatusRecord( + taskExecutor, + // we don't retain the executor by the task/record, because the "push" + // is implemented as a scope which keeps the executor alive by itself + // already, so we save the retain/release pair by the task doing it + // as well. In contrast, unstructured task creation always retains + // the executor. + /*retainedExecutor=*/false); SWIFT_TASK_DEBUG_LOG("[TaskExecutorPreference] Create task executor " "preference record %p for task:%p", allocation, task); @@ -669,7 +676,7 @@ static void swift_task_popTaskExecutorPreferenceImpl( TaskExecutorPreferenceStatusRecord *record) { SWIFT_TASK_DEBUG_LOG("[TaskExecutorPreference] Remove task executor " "preference record %p from task:%p", - allocation, swift_task_getCurrent()); + record, swift_task_getCurrent()); // We keep count of how many records there are because if there is more than // one, it means the task status flag should still be "has task preference". int preferenceRecordsCount = 0; @@ -703,11 +710,12 @@ static void swift_task_popTaskExecutorPreferenceImpl( } void AsyncTask::pushInitialTaskExecutorPreference( - TaskExecutorRef preferredExecutor) { + TaskExecutorRef preferredExecutor, bool owned) { void *allocation = _swift_task_alloc_specific( this, sizeof(class TaskExecutorPreferenceStatusRecord)); auto record = - ::new (allocation) TaskExecutorPreferenceStatusRecord(preferredExecutor); + ::new (allocation) TaskExecutorPreferenceStatusRecord( + preferredExecutor, /*ownsExecutor=*/owned); SWIFT_TASK_DEBUG_LOG("[InitialTaskExecutorPreference] Create a task " "preference record %p for task:%p", record, this); @@ -733,10 +741,20 @@ void AsyncTask::dropInitialTaskExecutorPreferenceRecord() { this); assert(this->hasInitialTaskExecutorPreferenceRecord()); + HeapObject *executorIdentityToRelease = nullptr; withStatusRecordLock(this, [&](ActiveTaskStatus status) { for (auto r : status.records()) { if (r->getKind() == TaskStatusRecordKind::TaskExecutorPreference) { auto record = cast(r); + + if (record->hasRetainedExecutor()) { + // Some tasks own their executor (i.e. take it consuming and guarantee + // its lifetime dynamically), while strictly structured tasks like + // async let do not retain it + executorIdentityToRelease = + record->getPreferredExecutor().getIdentity(); + } + removeStatusRecordLocked(status, record); _swift_task_dealloc_specific(this, record); return; @@ -748,6 +766,13 @@ void AsyncTask::dropInitialTaskExecutorPreferenceRecord() { assert(false && "dropInitialTaskExecutorPreferenceRecord must be " "guaranteed to drop the last preference"); }); + + // Release the "initial" preferred task executor, because it was specifically + // set in a Task initializer, which retained it. + // + // This should not be done for withTaskExecutorPreference executors, + // however in that case, we would not enter this function here to clean up. + swift_release(executorIdentityToRelease); } /**************************************************************************/ diff --git a/stdlib/public/Distributed/DistributedActor.swift b/stdlib/public/Distributed/DistributedActor.swift index d4529c04956c7..a2bc90e1bb3f7 100644 --- a/stdlib/public/Distributed/DistributedActor.swift +++ b/stdlib/public/Distributed/DistributedActor.swift @@ -362,6 +362,7 @@ extension DistributedActor { /// state. /// /// When the actor is remote, the closure won't be executed and this function will return nil. + @_alwaysEmitIntoClient public nonisolated func whenLocal( _ body: @Sendable (isolated Self) async throws(E) -> T ) async throws(E) -> T? { diff --git a/stdlib/public/Distributed/DistributedActorSystem.swift b/stdlib/public/Distributed/DistributedActorSystem.swift index 43583a90c301b..c9ab2b2700a2d 100644 --- a/stdlib/public/Distributed/DistributedActorSystem.swift +++ b/stdlib/public/Distributed/DistributedActorSystem.swift @@ -172,58 +172,6 @@ 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 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 associated types, 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 it was 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 `actor.id`, `target` and `invocation` /// into some form of wire envelope, and send it over the network (or process boundary) using some @@ -379,6 +327,10 @@ public protocol DistributedActorSystem: Sendable { /// /// This method should perform the actual remote function call, and await for its response. /// + /// ## Serialization Requirement + /// Implementations of this method must ensure that the `Argument` type parameter conforms + /// to the types' `SerializationRequirement`. + /// /// ## 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). @@ -405,6 +357,7 @@ public protocol DistributedActorSystem: Sendable { /// ## 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). + @available(SwiftStdlib 6.0, *) func remoteCallVoid( on actor: Act, target: RemoteCallTarget, @@ -713,32 +666,6 @@ func _executeDistributedTarget( /// Once encoded, the system should use some underlying transport mechanism to send the /// bytes serialized by the invocation to the remote peer. /// -/// ### Protocol requirements -/// Similar to the ``DistributedActorSystem`` and its `remoteCall` and `remoteCallVoid` protocol requirements, -/// the `DistributedTargetInvocationEncoder` contains a few methods which are not possible to express in source due to -/// advanced use of generics combined with associated types. Specifically, the `recordArgument` and `recordReturnType` -/// methods are not expressed in source as protocol requirements, but will be treated by the compiler as-if they were. -/// -/// > Note: Although the `recordArgument` method is not expressed as protocol requirement in source, -/// > the compiler will provide the same errors as-if it was declared explicitly in this protocol. -/// -/// In addition to the compiler offering compile errors if those witnesses are missing in an adopting type, -/// we present their signatures here for reference: -/// -/// ```swift -/// /// Record an argument of `Argument` type. -/// /// This will be invoked for every argument of the target, in declaration order. -/// mutating func recordArgument( -/// _ argument: DistributedTargetArgument -/// ) throws -/// -/// /// Ad-hoc requirement -/// /// -/// /// Record the return type of the distributed method. -/// /// This method will not be invoked if the target is returning `Void`. -/// mutating func recordReturnType(_ type: R.Type) throws -/// ``` -/// /// ## Decoding an invocation /// Since every actor system is going to deal with a concrete invocation type, they may /// implement decoding them whichever way is most optimal for the given system. @@ -762,6 +689,10 @@ public protocol DistributedTargetInvocationEncoder { /// Record an argument of `Argument` type. /// This will be invoked for every argument of the target, in declaration order. + /// + /// ### Serialization Requirement + /// Implementations of this method must ensure that the `Value` type parameter conforms + /// to the types' `SerializationRequirement`. @available(SwiftStdlib 6.0, *) mutating func recordArgument( _ argument: RemoteCallArgument @@ -775,6 +706,10 @@ public protocol DistributedTargetInvocationEncoder { /// Record the return type of the distributed method. /// This method will not be invoked if the target is returning `Void`. + /// + /// ### Serialization Requirement + /// Implementations of this method must ensure that the `R` type parameter conforms + /// to the types' `SerializationRequirement`. @available(SwiftStdlib 6.0, *) mutating func recordReturnType(_ type: R.Type) throws @@ -839,35 +774,6 @@ public struct RemoteCallArgument { /// Decoder that must be provided to `executeDistributedTarget` and is used /// by the Swift runtime to decode arguments of the invocation. /// -/// ### Protocol requirements -/// Similar to the ``DistributedTargetInvocationEncoder`` and its `recordArgument` and `recordReturnType` protocol requirements, -/// the `DistributedTargetInvocationDecoder` contains a method which is not possible to express in source due to -/// advanced use of generics combined with associated types. Specifically, the `decodeNextArgument` -/// method is not expressed in source as protocol requirement, but will be treated by the compiler as-if it was. -/// -/// > Note: Although the `decodeNextArgument` method is not expressed as protocol requirement in source, -/// > the compiler will provide the same errors as-if it was declared explicitly in this protocol. -/// -/// In addition to the compiler offering compile errors if this witness is missing in an adopting type, -/// we present its signature here for reference: -/// -/// ```swift -/// /// Ad-hoc protocol requirement -/// /// -/// /// Attempt to decode the next argument from the underlying buffers into pre-allocated storage -/// /// pointed at by 'pointer'. -/// /// -/// /// This method should throw if it has no more arguments available, if decoding the argument failed, -/// /// or, optionally, if the argument type we're trying to decode does not match the stored type. -/// /// -/// /// The result of the decoding operation must be stored into the provided 'pointer' rather than -/// /// returning a value. This pattern allows the runtime to use a heavily optimized, pre-allocated -/// /// buffer for all the arguments and their expected types. The 'pointer' passed here is a pointer -/// /// to a "slot" in that pre-allocated buffer. That buffer will then be passed to a thunk that -/// /// performs the actual distributed (local) instance method invocation. -/// mutating func decodeNextArgument() throws -> Argument -/// ``` -/// /// ### Decoding DistributedActor arguments using Codable /// When using an actor system where ``ActorID`` is ``Codable``, every distributed actor using that system /// is also implicitly ``Codable`` (see ``DistributedActorSystem``). Such distributed actors are encoded @@ -914,6 +820,10 @@ public protocol DistributedTargetInvocationDecoder { /// buffer for all the arguments and their expected types. The 'pointer' passed here is a pointer /// to a "slot" in that pre-allocated buffer. That buffer will then be passed to a thunk that /// performs the actual distributed (local) instance method invocation. + /// + /// ### Serialization Requirement + /// Implementations of this method must ensure that the `Argument` type parameter conforms + /// to the types' `SerializationRequirement`. @available(SwiftStdlib 6.0, *) mutating func decodeNextArgument() throws -> Argument @@ -936,26 +846,6 @@ public protocol DistributedTargetInvocationDecoder { /// ``executeDistributedTarget(on:target:invocationDecoder:handler:)`` while handling an incoming distributed call. /// /// The handler will then be invoked with the return value (or error) that the invoked target returned (or threw). -/// -/// ### Protocol requirements -/// Similar to the ``DistributedActorSystem`` and its `remoteCall` and `remoteCallVoid` protocol requirements, -/// the `DistributedTargetInvocationResultHandler` contains a method which is not possible to express in source due to -/// advanced use of generics combined with associated types. Specifically, the `onReturn` method is not expressed in -/// source as protocol requirement, but will be treated by the compiler as-if they were. -/// -/// > Note: Although the `onReturn` method is not expressed as protocol requirement in source, -/// > the compiler will provide the same errors as-if it was declared explicitly in this protocol. -/// -/// In addition to the compiler offering compile errors if this witnesses is missing in an adopting type, -/// we present its signature here for reference: -/// -/// ```swift -/// /// Ad-hoc protocol requirement -/// /// -/// /// Invoked when the distributed target execution returns successfully. -/// /// The `value` is the return value of the executed distributed invocation target. -/// func onReturn(value: Success) async throws -/// ``` @available(SwiftStdlib 5.7, *) public protocol DistributedTargetInvocationResultHandler { /// The serialization requirement that the value passed to `onReturn` is required to conform to. @@ -963,6 +853,10 @@ public protocol DistributedTargetInvocationResultHandler(value: Success) async throws diff --git a/stdlib/public/Platform/SwiftAndroidNDK.h b/stdlib/public/Platform/SwiftAndroidNDK.h index 791ac40ec4336..4d294ef96ad51 100644 --- a/stdlib/public/Platform/SwiftAndroidNDK.h +++ b/stdlib/public/Platform/SwiftAndroidNDK.h @@ -24,7 +24,14 @@ #include #include #include +#ifdef __cplusplus +// The Android r26 NDK contains an old libc++ modulemap that requires C++23 +// for 'stdatomic', which can't be imported unless we're using C++23. Thus, +// import stdatomic from the NDK directly, bypassing the stdatomic from the libc++. +#pragma clang module import _stdatomic +#else #include +#endif #include #include #include diff --git a/stdlib/public/Platform/SwiftBionic.h b/stdlib/public/Platform/SwiftBionic.h index b3e173030f18b..af4652d5ca7e6 100644 --- a/stdlib/public/Platform/SwiftBionic.h +++ b/stdlib/public/Platform/SwiftBionic.h @@ -24,7 +24,14 @@ #include #include #include +#ifdef __cplusplus +// The Android r26 NDK contains an old libc++ modulemap that requires C++23 +// for 'stdatomic', which can't be imported unless we're using C++23. Thus, +// import stdatomic from the NDK directly, bypassing the stdatomic from the libc++. +#pragma clang module import _stdatomic +#else #include +#endif #include #include #include diff --git a/stdlib/public/SwiftShims/swift/shims/RefCount.h b/stdlib/public/SwiftShims/swift/shims/RefCount.h index f218948704f10..9e1d04b0fedee 100644 --- a/stdlib/public/SwiftShims/swift/shims/RefCount.h +++ b/stdlib/public/SwiftShims/swift/shims/RefCount.h @@ -33,40 +33,40 @@ typedef InlineRefCountsPlaceholder InlineRefCounts; #include #include +#include "HeapObject.h" #include "swift/Basic/type_traits.h" #include "swift/Runtime/Atomic.h" #include "swift/Runtime/Config.h" #include "swift/Runtime/Debug.h" #include "swift/Runtime/Heap.h" - /* - An object conceptually has three refcounts. These refcounts + An object conceptually has three refcounts. These refcounts are stored either "inline" in the field following the isa or in a "side table entry" pointed to by the field following the isa. - - The strong RC counts strong references to the object. When the strong RC - reaches zero the object is deinited, unowned reference reads become errors, + + The strong RC counts strong references to the object. When the strong RC + reaches zero the object is deinited, unowned reference reads become errors, and weak reference reads become nil. The strong RC is stored as an extra count: when the physical field is 0 the logical value is 1. - The unowned RC counts unowned references to the object. The unowned RC - also has an extra +1 on behalf of the strong references; this +1 is - decremented after deinit completes. When the unowned RC reaches zero + The unowned RC counts unowned references to the object. The unowned RC + also has an extra +1 on behalf of the strong references; this +1 is + decremented after deinit completes. When the unowned RC reaches zero the object's allocation is freed. - The weak RC counts weak references to the object. The weak RC also has an - extra +1 on behalf of the unowned references; this +1 is decremented - after the object's allocation is freed. When the weak RC reaches zero + The weak RC counts weak references to the object. The weak RC also has an + extra +1 on behalf of the unowned references; this +1 is decremented + after the object's allocation is freed. When the weak RC reaches zero the object's side table entry is freed. Objects initially start with no side table. They can gain a side table when: - * a weak reference is formed + * a weak reference is formed and pending future implementation: * strong RC or unowned RC overflows (inline RCs will be small on 32-bit) * associated object storage is needed on an object * etc - Gaining a side table entry is a one-way operation; an object with a side + Gaining a side table entry is a one-way operation; an object with a side table entry never loses it. This prevents some thread races. Strong and unowned variables point at the object. @@ -92,7 +92,7 @@ typedef InlineRefCountsPlaceholder InlineRefCounts; atomic { strong RC + unowned RC + weak RC + flags } - } + } } InlineRefCounts and SideTableRefCounts share some implementation @@ -101,10 +101,10 @@ typedef InlineRefCountsPlaceholder InlineRefCounts; InlineRefCountBits and SideTableRefCountBits share some implementation via RefCountBitsT. - In general: The InlineRefCounts implementation tries to perform the - operation inline. If the object has a side table it calls the - HeapObjectSideTableEntry implementation which in turn calls the - SideTableRefCounts implementation. + In general: The InlineRefCounts implementation tries to perform the + operation inline. If the object has a side table it calls the + HeapObjectSideTableEntry implementation which in turn calls the + SideTableRefCounts implementation. Downside: this code is a bit twisted. Upside: this code has less duplication than it might otherwise @@ -115,11 +115,11 @@ typedef InlineRefCountsPlaceholder InlineRefCounts; The object is alive. Object's refcounts are initialized as 1 strong, 1 unowned, 1 weak. No side table. No weak RC storage. - Strong variable operations work normally. + Strong variable operations work normally. Unowned variable operations work normally. Weak variable load can't happen. Weak variable store adds the side table, becoming LIVE with side table. - When the strong RC reaches zero deinit() is called and the object + When the strong RC reaches zero deinit() is called and the object becomes DEINITING. LIVE with side table @@ -133,14 +133,14 @@ typedef InlineRefCountsPlaceholder InlineRefCounts; Unowned variable store works normally. Weak variable load can't happen. Weak variable store stores nil. - When deinit() completes, the generated code calls swift_deallocObject. - swift_deallocObject calls canBeFreedNow() checking for the fast path - of no weak or unowned references. - If canBeFreedNow() the object is freed and it becomes DEAD. + When deinit() completes, the generated code calls swift_deallocObject. + swift_deallocObject calls canBeFreedNow() checking for the fast path + of no weak or unowned references. + If canBeFreedNow() the object is freed and it becomes DEAD. Otherwise, it decrements the unowned RC and the object becomes DEINITED. DEINITING with side table - Weak variable load returns nil. + Weak variable load returns nil. Weak variable store stores nil. canBeFreedNow() is always false, so it never transitions directly to DEAD. Everything else is the same as DEINITING. @@ -156,7 +156,7 @@ typedef InlineRefCountsPlaceholder InlineRefCounts; DEINITED with side table Weak variable load returns nil. Weak variable store can't happen. - When the unowned RC reaches zero, the object is freed, the weak RC is + When the unowned RC reaches zero, the object is freed, the weak RC is decremented, and the object becomes FREED. Everything else is the same as DEINITED. @@ -169,7 +169,7 @@ typedef InlineRefCountsPlaceholder InlineRefCounts; Unowned variable operations can't happen. Weak variable load returns nil. Weak variable store can't happen. - When the weak RC reaches zero, the side table entry is freed and + When the weak RC reaches zero, the side table entry is freed and the object becomes DEAD. DEAD diff --git a/stdlib/public/Synchronization/CMakeLists.txt b/stdlib/public/Synchronization/CMakeLists.txt index dead46e532bbc..88cc673522ad1 100644 --- a/stdlib/public/Synchronization/CMakeLists.txt +++ b/stdlib/public/Synchronization/CMakeLists.txt @@ -33,7 +33,13 @@ set(SWIFT_SYNCHRONIZATION_GYB_SOURCES Atomics/AtomicStorage.swift.gyb ) -# Darwin sources +# Darwin dependencies and sources + +set(SWIFT_SYNCHRONIZATION_DARWIN_DEPENDENCIES) + +if(SWIFT_BUILD_SDK_OVERLAY) + set(SWIFT_SYNCHRONIZATION_DARWIN_DEPENDENCIES Darwin) +endif() set(SWIFT_SYNCHRONIZATION_DARWIN_SOURCES Mutex/DarwinImpl.swift @@ -96,15 +102,17 @@ add_swift_target_library(swiftSynchronization ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES Mutex/MutexUnavailable.swift SWIFT_MODULE_DEPENDS_OSX - Darwin + ${SWIFT_SYNCHRONIZATION_DARWIN_DEPENDENCIES} SWIFT_MODULE_DEPENDS_IOS - Darwin + ${SWIFT_SYNCHRONIZATION_DARWIN_DEPENDENCIES} SWIFT_MODULE_DEPENDS_TVOS - Darwin + ${SWIFT_SYNCHRONIZATION_DARWIN_DEPENDENCIES} SWIFT_MODULE_DEPENDS_WATCHOS - Darwin + ${SWIFT_SYNCHRONIZATION_DARWIN_DEPENDENCIES} SWIFT_MODULE_DEPENDS_XROS - Darwin + ${SWIFT_SYNCHRONIZATION_DARWIN_DEPENDENCIES} + SWIFT_MODULE_DEPENDS_MACCATALYST + ${SWIFT_SYNCHRONIZATION_DARWIN_DEPENDENCIES} SWIFT_MODULE_DEPENDS_LINUX Glibc SWIFT_MODULE_DEPENDS_ANDROID diff --git a/stdlib/public/Synchronization/Mutex/SpinLoopHint.swift b/stdlib/public/Synchronization/Mutex/SpinLoopHint.swift index 940310f4fb4a6..0084e1d056892 100644 --- a/stdlib/public/Synchronization/Mutex/SpinLoopHint.swift +++ b/stdlib/public/Synchronization/Mutex/SpinLoopHint.swift @@ -17,6 +17,8 @@ var _tries: Int { 100 } +#if arch(arm) + // The following are acceptable operands to the aarch64 hint intrinsic from // 'llvm-project/llvm/lib/Target/ARM/ARMInstrInfo.td': // @@ -28,9 +30,27 @@ var _tries: Int { // `sevl` = 5 // // There are others, but for the sake of spin loops, we only care about 'wfe'. +@_extern(c, "llvm.arm.hint") +func _hint(_: UInt32) + +#else + +// The following are acceptable operands to the aarch64 hint intrinsic from +// 'llvm-project/llvm/lib/Target/AArch64/AArch64InstrInfo.td': +// +// `nop` = 0 +// `yield` = 1 +// `wfe` = 2 +// `wfi` = 3 +// `sev` = 4 +// `sevl` = 5 +// +// There are others, but for the sake of spin loops, we only care about 'wfe'. @_extern(c, "llvm.aarch64.hint") func _hint(_: UInt32) +#endif + @inline(__always) func _wfe() { _hint(2) diff --git a/stdlib/public/core/Availability.swift b/stdlib/public/core/Availability.swift index 43da1ff6dfff6..0b85cae41f717 100644 --- a/stdlib/public/core/Availability.swift +++ b/stdlib/public/core/Availability.swift @@ -103,9 +103,11 @@ extension _SwiftStdlibVersion { public static var v5_10_0: Self { Self(_value: 0x050A00) } @_alwaysEmitIntoClient public static var v6_0_0: Self { Self(_value: 0x060000) } + @_alwaysEmitIntoClient + public static var v6_1_0: Self { Self(_value: 0x060100) } @available(SwiftStdlib 5.7, *) - public static var current: Self { .v6_0_0 } + public static var current: Self { .v6_1_0 } } @available(SwiftStdlib 5.7, *) diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index dbd8a572cc54c..fe3ee513a19f0 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -98,7 +98,7 @@ split_embedded_sources( EMBEDDED Integers.swift NORMAL Join.swift EMBEDDED KeyPath.swift - NORMAL KeyValuePairs.swift + EMBEDDED KeyValuePairs.swift EMBEDDED LazyCollection.swift EMBEDDED LazySequence.swift NORMAL LegacyABI.swift @@ -227,7 +227,7 @@ split_embedded_sources( EMBEDDED FloatingPointRandom.swift EMBEDDED Instant.swift EMBEDDED Int128.swift - NORMAL Mirror.swift + EMBEDDED Mirror.swift NORMAL PlaygroundDisplay.swift NORMAL CommandLine.swift EMBEDDED SliceBuffer.swift diff --git a/stdlib/public/core/EmbeddedRuntime.swift b/stdlib/public/core/EmbeddedRuntime.swift index d8d3819e21ea5..7ad57e4846809 100644 --- a/stdlib/public/core/EmbeddedRuntime.swift +++ b/stdlib/public/core/EmbeddedRuntime.swift @@ -187,6 +187,20 @@ func isValidPointerForNativeRetain(object: Builtin.RawPointer) -> Bool { public func swift_setDeallocating(object: Builtin.RawPointer) { } +@_cdecl("swift_dynamicCastClass") +public func swift_dynamicCastClass(object: UnsafeMutableRawPointer, targetMetadata: UnsafeRawPointer) -> UnsafeMutableRawPointer? { + let sourceObj = object.assumingMemoryBound(to: HeapObject.self) + var type = _swift_embedded_get_heap_object_metadata_pointer(sourceObj).assumingMemoryBound(to: ClassMetadata.self) + let targetType = targetMetadata.assumingMemoryBound(to: ClassMetadata.self) + while type != targetType { + guard let superType = type.pointee.superclassMetadata else { + return nil + } + type = UnsafeMutablePointer(superType) + } + return object +} + @_cdecl("swift_isUniquelyReferenced_native") public func swift_isUniquelyReferenced_native(object: Builtin.RawPointer) -> Bool { if !isValidPointerForNativeRetain(object: object) { return false } diff --git a/stdlib/public/core/EmbeddedStubs.swift b/stdlib/public/core/EmbeddedStubs.swift index 07e5dcc5cc33c..a11aa28565927 100644 --- a/stdlib/public/core/EmbeddedStubs.swift +++ b/stdlib/public/core/EmbeddedStubs.swift @@ -15,10 +15,9 @@ import SwiftShims /// String @_unavailableInEmbedded -extension String { - public init(describing instance: Subject) { fatalError() } - public init(reflecting instance: Subject) { fatalError() } -} +internal func _print_unlocked(_ value: T, _ target: inout String) { fatalError() } +@_unavailableInEmbedded +public func _debugPrint_unlocked(_ value: T, _ target: inout String) { fatalError() } /// Codable diff --git a/stdlib/public/core/ErrorType.swift b/stdlib/public/core/ErrorType.swift index 632e9da1b400c..5c5c2224fa98b 100644 --- a/stdlib/public/core/ErrorType.swift +++ b/stdlib/public/core/ErrorType.swift @@ -195,7 +195,7 @@ func _willThrowTypedImpl(_ error: E) @_alwaysEmitIntoClient @_silgen_name("swift_willThrowTyped") public func _willThrowTyped(_ error: E) { - if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999, *) { + if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { _willThrowTypedImpl(error) } } diff --git a/stdlib/public/core/KeyValuePairs.swift b/stdlib/public/core/KeyValuePairs.swift index 7e7e4704c07dd..b074ed0aab1fd 100644 --- a/stdlib/public/core/KeyValuePairs.swift +++ b/stdlib/public/core/KeyValuePairs.swift @@ -125,6 +125,7 @@ extension KeyValuePairs: RandomAccessCollection { } } +@_unavailableInEmbedded extension KeyValuePairs: CustomStringConvertible { /// A string that represents the contents of the dictionary. public var description: String { @@ -132,6 +133,7 @@ extension KeyValuePairs: CustomStringConvertible { } } +@_unavailableInEmbedded extension KeyValuePairs: CustomDebugStringConvertible { /// A string that represents the contents of the dictionary, suitable for /// debugging. diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift index 42faa37a5cdfd..5d94615ac7463 100644 --- a/stdlib/public/core/Mirror.swift +++ b/stdlib/public/core/Mirror.swift @@ -538,6 +538,7 @@ extension Mirror { //===--- General Utilities ------------------------------------------------===// +@_unavailableInEmbedded extension String { /// Creates a string representing the given value. /// diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift index 2313ac7040fe6..b6ecca2fd1f66 100644 --- a/stdlib/public/core/Optional.swift +++ b/stdlib/public/core/Optional.swift @@ -132,7 +132,7 @@ public enum Optional: ~Copyable { case some(Wrapped) } -extension Optional: Copyable /* where Wrapped: Copyable */ {} +extension Optional: Copyable where Wrapped: Copyable {} extension Optional: Sendable where Wrapped: ~Copyable & Sendable { } diff --git a/stdlib/public/core/Result.swift b/stdlib/public/core/Result.swift index 0c1dd43eeae01..24dddadc22305 100644 --- a/stdlib/public/core/Result.swift +++ b/stdlib/public/core/Result.swift @@ -21,7 +21,7 @@ public enum Result { case failure(Failure) } -extension Result: Copyable /* where Success: Copyable */ {} +extension Result: Copyable where Success: Copyable {} extension Result: Sendable where Success: Sendable & ~Copyable {} diff --git a/stdlib/public/runtime/DynamicCast.cpp b/stdlib/public/runtime/DynamicCast.cpp index 7f7b6128a779e..b9e6f4675a101 100644 --- a/stdlib/public/runtime/DynamicCast.cpp +++ b/stdlib/public/runtime/DynamicCast.cpp @@ -1864,8 +1864,8 @@ static DynamicCastResult tryCastToExtendedExistential( [&substitutions](unsigned depth, unsigned index) { return substitutions.getMetadata(depth, index).Ptr; }, - [&substitutions](unsigned ordinal) { - return substitutions.getMetadataOrdinal(ordinal).Ptr; + [&substitutions](unsigned fullOrdinal, unsigned keyOrdinal) { + return substitutions.getMetadataKeyArgOrdinal(keyOrdinal).Ptr; }, [](const Metadata *type, unsigned index) -> const WitnessTable * { swift_unreachable("Resolution of witness tables is not supported"); diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index 2bfce4254a6b3..3565f922af532 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -1195,7 +1195,7 @@ class SubstGenericParametersFromWrittenArgs { genericParamCounts(genericParamCounts) {} MetadataOrPack getMetadata(unsigned depth, unsigned index) const; - MetadataOrPack getMetadataOrdinal(unsigned ordinal) const; + MetadataOrPack getMetadataFullOrdinal(unsigned ordinal) const; const WitnessTable *getWitnessTable(const Metadata *type, unsigned index) const; }; @@ -1415,8 +1415,8 @@ _gatherGenericParameters(const ContextDescriptor *context, [&substitutions](unsigned depth, unsigned index) { return substitutions.getMetadata(depth, index).Ptr; }, - [&substitutions](unsigned ordinal) { - return substitutions.getMetadataOrdinal(ordinal).Ptr; + [&substitutions](unsigned fullOrdinal, unsigned keyOrdinal) { + return substitutions.getMetadataFullOrdinal(fullOrdinal).Ptr; }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); @@ -1849,12 +1849,12 @@ class DecodedMetadataBuilder { // FIXME: variadic generics return genArgs[index].getMetadata(); }, - [genArgs](unsigned ordinal) { - if (ordinal >= genArgs.size()) + [genArgs](unsigned fullOrdinal, unsigned keyOrdinal) { + if (fullOrdinal >= genArgs.size()) return (const Metadata*)nullptr; // FIXME: variadic generics - return genArgs[ordinal].getMetadata(); + return genArgs[fullOrdinal].getMetadata(); }, [](const Metadata *type, unsigned index) -> const WitnessTable * { swift_unreachable("never called"); @@ -2814,8 +2814,8 @@ swift_distributed_getWitnessTables(GenericEnvironmentDescriptor *genericEnv, [&substFn](unsigned depth, unsigned index) { return substFn.getMetadata(depth, index).Ptr; }, - [&substFn](unsigned ordinal) { - return substFn.getMetadataOrdinal(ordinal).Ptr; + [&substFn](unsigned fullOrdinal, unsigned keyOrdinal) { + return substFn.getMetadataKeyArgOrdinal(keyOrdinal).Ptr; }, [&substFn](const Metadata *type, unsigned index) { return substFn.getWitnessTable(type, index); @@ -3243,8 +3243,8 @@ SubstGenericParametersFromMetadata::getMetadata( return MetadataOrPack(genericArgs[flatIndex]); } -MetadataOrPack -SubstGenericParametersFromMetadata::getMetadataOrdinal(unsigned ordinal) const { +MetadataOrPack SubstGenericParametersFromMetadata::getMetadataKeyArgOrdinal( + unsigned ordinal) const { // Don't attempt anything if we have no generic parameters. if (genericArgs == nullptr) return MetadataOrPack(); @@ -3281,8 +3281,8 @@ MetadataOrPack SubstGenericParametersFromWrittenArgs::getMetadata( return MetadataOrPack(); } -MetadataOrPack SubstGenericParametersFromWrittenArgs::getMetadataOrdinal( - unsigned ordinal) const { +MetadataOrPack SubstGenericParametersFromWrittenArgs::getMetadataFullOrdinal( + unsigned ordinal) const { if (ordinal < allGenericArgs.size()) { return MetadataOrPack(allGenericArgs[ordinal]); } diff --git a/stdlib/public/runtime/Private.h b/stdlib/public/runtime/Private.h index 2274fbb62dc69..03d88d5530a4c 100644 --- a/stdlib/public/runtime/Private.h +++ b/stdlib/public/runtime/Private.h @@ -295,11 +295,13 @@ class TypeInfo { std::function; /// Callback used to provide the substitution of a generic parameter - /// (described by the ordinal, or "flat index") to its metadata. + /// (described by the ordinal, or "flat index") to its metadata. The index may + /// be "full" or it may be only relative to key arguments. The call is + /// provided both indexes and may use the one it requires. /// /// The return type here is a lie; it's actually a MetadataOrPack. using SubstGenericParameterOrdinalFn = - std::function; + std::function; /// Callback used to provide the substitution of a witness table based on /// its index into the enclosing generic environment. @@ -460,7 +462,7 @@ class TypeInfo { const void * const *getGenericArgs() const { return genericArgs; } MetadataOrPack getMetadata(unsigned depth, unsigned index) const; - MetadataOrPack getMetadataOrdinal(unsigned ordinal) const; + MetadataOrPack getMetadataKeyArgOrdinal(unsigned ordinal) const; const WitnessTable *getWitnessTable(const Metadata *type, unsigned index) const; }; diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index 92dc7f63a47fc..4efd4c3c46286 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -340,8 +340,8 @@ ProtocolConformanceDescriptor::getWitnessTable(const Metadata *type) const { [&substitutions](unsigned depth, unsigned index) { return substitutions.getMetadata(depth, index).Ptr; }, - [&substitutions](unsigned ordinal) { - return substitutions.getMetadataOrdinal(ordinal).Ptr; + [&substitutions](unsigned fullOrdinal, unsigned keyOrdinal) { + return substitutions.getMetadataKeyArgOrdinal(keyOrdinal).Ptr; }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); @@ -1843,8 +1843,8 @@ checkInvertibleRequirements(const Metadata *type, [&substFn](unsigned depth, unsigned index) { return substFn.getMetadata(depth, index).Ptr; }, - [&substFn](unsigned ordinal) { - return substFn.getMetadataOrdinal(ordinal).Ptr; + [&substFn](unsigned fullOrdinal, unsigned keyOrdinal) { + return substFn.getMetadataKeyArgOrdinal(keyOrdinal).Ptr; }, [&substFn](const Metadata *type, unsigned index) { return substFn.getWitnessTable(type, index); @@ -1886,6 +1886,7 @@ std::optional swift::_checkGenericRequirements( // Now, check all of the generic arguments for invertible protocols. unsigned numGenericParams = genericParams.size(); + unsigned keyIndex = 0; for (unsigned index = 0; index != numGenericParams; ++index) { // Non-key arguments don't need to be checked, because they are // aliased to another type. @@ -1896,7 +1897,7 @@ std::optional swift::_checkGenericRequirements( if (index < allSuppressed.size()) suppressed = allSuppressed[index]; - MetadataOrPack metadataOrPack(substGenericParamOrdinal(index)); + MetadataOrPack metadataOrPack(substGenericParamOrdinal(index, keyIndex)); switch (genericParams[index].getKind()) { case GenericParamKind::Type: { if (!metadataOrPack || metadataOrPack.isMetadataPack()) { @@ -1937,6 +1938,7 @@ std::optional swift::_checkGenericRequirements( return TYPE_LOOKUP_ERROR_FMT("unknown generic parameter kind %u", index); } + keyIndex++; } // Success! diff --git a/test/AutoDiff/SILGen/nil_coalescing.swift b/test/AutoDiff/SILGen/nil_coalescing.swift index 994fbeed691fa..c11be5586a3ed 100644 --- a/test/AutoDiff/SILGen/nil_coalescing.swift +++ b/test/AutoDiff/SILGen/nil_coalescing.swift @@ -7,7 +7,10 @@ import _Differentiation // CHECK: $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ): // CHECK: %[[ALLOC_OPT:.*]] = alloc_stack [lexical] $Optional // CHECK: copy_addr %[[ARG_OPT]] to [init] %[[ALLOC_OPT]] : $*Optional -// CHECK: switch_enum_addr %[[ALLOC_OPT]] : $*Optional, case #Optional.some!enumelt: {{.*}}, case #Optional.none!enumelt: {{.*}} +// We'd need to check that ALLOC_OPT is an argument of switch_enum_addr below. However, this code +// is inlined from the standard library and therefore could have a sequence of copies in between +// depending whether we're compiling against debug or release stdlib +// CHECK: switch_enum_addr %{{.*}} : $*Optional, case #Optional.some!enumelt: {{.*}}, case #Optional.none!enumelt: {{.*}} // CHECK: try_apply %[[ARG_PB]](%{{.*}}) : $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for , normal {{.*}}, error {{.*}} // @_silgen_name("test_nil_coalescing") diff --git a/test/ClangImporter/objc_isolation_complete.swift b/test/ClangImporter/objc_isolation_complete.swift index 251bad8fa9bfe..3bb95c4026895 100644 --- a/test/ClangImporter/objc_isolation_complete.swift +++ b/test/ClangImporter/objc_isolation_complete.swift @@ -15,3 +15,19 @@ func unsatisfiedPreconcurrencyIsolation(view: MyView) { // expected-warning@+1 {{main actor-isolated property 'isVisible' can not be referenced from a non-isolated context}} _ = view.isVisible } + +@preconcurrency @MainActor +class IsolatedSub: NXSender { + var mainActorState = 0 // expected-note {{property declared here}} + override func sendAny(_: any Sendable) -> any Sendable { + return mainActorState + // expected-warning@-1 {{main actor-isolated property 'mainActorState' can not be referenced from a non-isolated context}} + } + + @MainActor + override func sendOptionalAny(_: (any Sendable)?) -> (any Sendable)? { + // expected-warning@-1 {{main actor-isolated instance method 'sendOptionalAny' has different actor isolation from nonisolated overridden declaration; this is an error in the Swift 6 language mode}} + + return mainActorState + } +} diff --git a/test/Concurrency/CaseIterableIsolation.swift b/test/Concurrency/CaseIterableIsolation.swift new file mode 100644 index 0000000000000..9bbcfbf32b9f4 --- /dev/null +++ b/test/Concurrency/CaseIterableIsolation.swift @@ -0,0 +1,21 @@ +// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete +// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -enable-upcoming-feature RegionBasedIsolation + +// REQUIRES: executable_test +// REQUIRES: concurrency + +import StdlibUnittest + +var CaseIterableTests = TestSuite("CaseIterableTests") + +CaseIterableTests.test("MainActor Isolated Enums") { + @MainActor + enum EnumMainActor: CaseIterable { + case a, b + } + + expectEqual(EnumMainActor.allCases.count, 2) + expectEqual(EnumMainActor.allCases, [.a, .b]) +} + +runAllTests() diff --git a/test/Concurrency/Runtime/async_task_executor_and_serial_executor_nonisolated_async_func.swift b/test/Concurrency/Runtime/async_task_executor_and_serial_executor_nonisolated_async_func.swift index 0b41d5b39ce66..e4b9b825ed6c1 100644 --- a/test/Concurrency/Runtime/async_task_executor_and_serial_executor_nonisolated_async_func.swift +++ b/test/Concurrency/Runtime/async_task_executor_and_serial_executor_nonisolated_async_func.swift @@ -58,7 +58,7 @@ actor Worker { // the nonisolated async func properly executes on the task-executor await nonisolatedFunc(expectedExecutor: expectedExecutor) - /// the task-executor preference is inherited properly: + // the task-executor preference is inherited properly: async let val = { dispatchPrecondition(condition: .onQueue(expectedExecutor.queue)) expectedExecutor.preconditionIsolated() diff --git a/test/Concurrency/Runtime/async_task_executor_unstructured_task_ownership.swift b/test/Concurrency/Runtime/async_task_executor_unstructured_task_ownership.swift new file mode 100644 index 0000000000000..99b97844f85ac --- /dev/null +++ b/test/Concurrency/Runtime/async_task_executor_unstructured_task_ownership.swift @@ -0,0 +1,81 @@ +// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking %import-libdispatch -parse-as-library ) | %FileCheck %s + +// REQUIRES: executable_test +// REQUIRES: concurrency +// REQUIRES: libdispatch + +// REQUIRES: concurrency_runtime +// UNSUPPORTED: back_deployment_runtime + +import Dispatch +import StdlibUnittest +import _Concurrency + +final class NaiveQueueExecutor: TaskExecutor { + let queue: DispatchQueue + + init(_ queue: DispatchQueue) { + print("init \(Self.self)") + self.queue = queue + } + + deinit { + print("deinit \(Self.self)") + } + + public func enqueue(_ _job: consuming ExecutorJob) { + print("Enqueue on \(Self.self)!") + let job = UnownedJob(_job) + queue.async { + job.runSynchronously(on: self.asUnownedTaskExecutor()) + } + } + + @inlinable + public func asUnownedTaskExecutor() -> UnownedTaskExecutor { + print("\(Self.self).\(#function)") + return UnownedTaskExecutor(ordinary: self) + } +} + +nonisolated func nonisolatedFunc(expectedQueue queue: DispatchQueue) async { +// dispatchPrecondition(condition: .onQueue(queue)) + print("Invoked: \(#function)") +} + +@main struct Main { + + static func main() async { + let queue = DispatchQueue(label: "example-queue") + var executor: NaiveQueueExecutor? = NaiveQueueExecutor(queue) + + // Task retains the executor, so it should never deinit before the task completes + // CHECK: init NaiveQueueExecutor + + // The concurrency runtime invokes the... + // CHECK: NaiveQueueExecutor.asUnownedTaskExecutor + + // And we enqueue on the task executor... + // CHECK: Enqueue on NaiveQueueExecutor + // CHECK: Task start + + let task = Task(executorPreference: executor!) { + print("Task start") + // CHECK: Invoked: nonisolatedFunc + await nonisolatedFunc(expectedQueue: queue) + print("Task done") + } + + executor = nil + print("In main: executor = nil") + + await task.value + // The executor is ONLY released after the task has completed, + // regardless when the reference in main() was released. + // CHECK: Task done + // CHECK-NEXT: deinit NaiveQueueExecutor + + print("Done") + // CHECK: Done + } +} diff --git a/test/Concurrency/Runtime/custom_executors.swift b/test/Concurrency/Runtime/custom_executors.swift index 334f42267eb04..323e655e8676e 100644 --- a/test/Concurrency/Runtime/custom_executors.swift +++ b/test/Concurrency/Runtime/custom_executors.swift @@ -27,6 +27,8 @@ actor Custom { } func report() async { + simple.preconditionIsolated() // we're supposed to be on the same executor as 'simple' + print("custom.count == \(count)") count += 1 diff --git a/test/Concurrency/Runtime/custom_executors_globalActor.swift b/test/Concurrency/Runtime/custom_executors_globalActor.swift new file mode 100644 index 0000000000000..8342a70799c4e --- /dev/null +++ b/test/Concurrency/Runtime/custom_executors_globalActor.swift @@ -0,0 +1,101 @@ +// RUN: %target-run-simple-swift( %import-libdispatch -strict-concurrency=complete -parse-as-library) | %FileCheck %s + +// REQUIRES: concurrency +// REQUIRES: executable_test +// REQUIRES: libdispatch +// UNSUPPORTED: freestanding + +// UNSUPPORTED: back_deployment_runtime +// REQUIRES: concurrency_runtime + +import Dispatch + +let globalQueue = DispatchQueue(label: "SimpleQueue") + +@available(SwiftStdlib 6.0, *) +final class NaiveQueueExecutor: SerialExecutor { + public func enqueue(_ unowned: UnownedJob) { + globalQueue.sync { + unowned.runSynchronously(on: self.asUnownedSerialExecutor()) + } + } + + public func asUnownedSerialExecutor() -> UnownedSerialExecutor { + return UnownedSerialExecutor(ordinary: self) + } + + func checkIsolated() { + // ok + } +} + +@available(SwiftStdlib 6.0, *) +actor Simple { + var count = 0 + let exec = NaiveQueueExecutor() + + func report() { + print("simple.count == \(count)") + count += 1 + } + + nonisolated var unownedExecutor: UnownedSerialExecutor { + print("Simple.unownedExecutor") + return exec.asUnownedSerialExecutor() + } +} + +@globalActor +@available(SwiftStdlib 6.0, *) +actor MyGlobalActor { + static let simple = Simple() + static let shared = MyGlobalActor() + + static var sharedUnownedExecutor: UnownedSerialExecutor { + print("MyGlobalActor.sharedUnownedExecutor") + return simple.unownedExecutor + } + nonisolated var unownedExecutor: UnownedSerialExecutor { + print("MyGlobalActor.unownedExecutor") + return Self.simple.unownedExecutor + } +} + +@MyGlobalActor +@available(SwiftStdlib 6.0, *) +final class Custom { + var count = 0 + let simple = MyGlobalActor.simple + + nonisolated var unownedExecutor: UnownedSerialExecutor { + return simple.unownedExecutor + } + + func report() async { + simple.preconditionIsolated() + + print("custom.count == \(count)") + count += 1 + + await simple.report() + } +} + +@available(SwiftStdlib 6.0, *) +@main struct Main { + static func main() async { + print("begin") + let actor = Custom() + await actor.report() + print("end") + } +} + +// CHECK: begin +// CHECK-NEXT: MyGlobalActor.unownedExecutor +// CHECK-NEXT: Simple.unownedExecutor +// CHECK-NEXT: Simple.unownedExecutor +// CHECK-NEXT: custom.count == 0 +// CHECK-NEXT: Simple.unownedExecutor +// CHECK-NEXT: simple.count == 0 +// CHECK-NEXT: end diff --git a/test/Concurrency/actor_isolation.swift b/test/Concurrency/actor_isolation.swift index 15c209db04ce9..bc486815c5f7b 100644 --- a/test/Concurrency/actor_isolation.swift +++ b/test/Concurrency/actor_isolation.swift @@ -1492,9 +1492,6 @@ class None { // try to add inferred isolation while overriding @MainActor class MA_None1: None { - - // FIXME: bad note, since the problem is a mismatch in overridden vs inferred isolation; this wont help. - // expected-note@+1 {{add '@MainActor' to make instance method 'method()' part of global actor 'MainActor'}} override func method() { beets_ma() // expected-error {{call to main actor-isolated global function 'beets_ma()' in a synchronous nonisolated context}} } diff --git a/test/Concurrency/async_main.swift b/test/Concurrency/async_main.swift index 08aee73185859..c1d67b2fa5a47 100644 --- a/test/Concurrency/async_main.swift +++ b/test/Concurrency/async_main.swift @@ -69,12 +69,13 @@ func asyncFunc() async { // CHECK-SIL-NEXT: [[FLAGS:%.*]] = struct $Int ([[T0]] : $Builtin.Int64) // CHECK-SIL-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none // CHECK-SIL-NEXT: [[GROUP:%.*]] = enum $Optional, #Optional.none -// CHECK-SIL-NEXT: [[TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.none +// CHECK-SIL-NEXT: [[TASK_EXECUTOR_UNOWNED:%.*]] = enum $Optional, #Optional.none +// CHECK-SIL-NEXT: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional, #Optional.none // CHECK-SIL-NEXT: // function_ref thunk for @escaping @convention(thin) @async () -> () // CHECK-SIL-NEXT: [[THUNK_FN:%.*]] = function_ref @$sIetH_yts5Error_pIeghHrzo_TR : $@convention(thin) @Sendable @async (@convention(thin) @async () -> ()) -> (@out (), @error any Error) // CHECK-SIL-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]([[ASYNC_MAIN_FN]]) : $@convention(thin) @Sendable @async (@convention(thin) @async () -> ()) -> (@out (), @error any Error) // CHECK-SIL-NEXT: [[CONVERTED_THUNK:%.*]] = convert_function [[THUNK]] : $@Sendable @async @callee_guaranteed () -> (@out (), @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()> -// CHECK-SIL-NEXT: [[TASK_RESULT:%.*]] = builtin "createAsyncTask"<()>([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[CONVERTED_THUNK]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-SIL-NEXT: [[TASK_RESULT:%.*]] = builtin "createAsyncTask"<()>([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR_UNOWNED]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional, [[CONVERTED_THUNK]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>) : $(Builtin.NativeObject, Builtin.RawPointer) // CHECK-SIL-NEXT: [[TASK:%.*]] = tuple_extract [[TASK_RESULT]] : $(Builtin.NativeObject, Builtin.RawPointer), 0 // CHECK-SIL-NEXT: // function_ref swift_job_run // CHECK-SIL-NEXT: [[RUN_FN:%.*]] = function_ref @swift_job_run : $@convention(thin) (UnownedJob, UnownedSerialExecutor) -> () diff --git a/test/Concurrency/async_sequence_macosx.swift b/test/Concurrency/async_sequence_macosx.swift index 261f1a125e69b..99b312dbff0c2 100644 --- a/test/Concurrency/async_sequence_macosx.swift +++ b/test/Concurrency/async_sequence_macosx.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -target %target-cpu-apple-macos14.0 %s -emit-sil -o /dev/null -verify +// RUN: %target-swift-frontend -target %target-cpu-apple-macos14.0 %s -emit-sil -o /dev/null -verify -swift-version 6 // REQUIRES: concurrency, OS=macosx @@ -15,4 +15,21 @@ func f(s: S) async throws { } } +// Make sure we don't complain about crossing a concurrency boundary here. +@MainActor +class Store { + private func intercept(_ action: Action) async throws { + await withTaskGroup(of: Optional.self) { group in + for await case let nextAction? in group { + _ = nextAction + } + } + try await withThrowingTaskGroup(of: Optional.self) { group in + for try await case let nextAction? in group { + _ = nextAction + } + } + + } +} diff --git a/test/Concurrency/flow_isolation.swift b/test/Concurrency/flow_isolation.swift index b9bfde51d6134..a0b39ff37fa5c 100644 --- a/test/Concurrency/flow_isolation.swift +++ b/test/Concurrency/flow_isolation.swift @@ -684,8 +684,7 @@ actor OhBrother { static var DefaultResult: Int { 10 } init() { - // expected-note@+2 {{after this closure involving 'self', only non-isolated properties of 'self' can be accessed from this init}} - // expected-warning@+1 {{cannot access property 'giver' here in non-isolated initializer; this is an error in the Swift 6 language mode}} + // this is OK: we're using DynamicSelfType but that doesn't access protected state. self.giver = { (x: OhBrother) -> Int in Self.DefaultResult } } diff --git a/test/Concurrency/isolation_macro_local_functions.swift b/test/Concurrency/isolation_macro_local_functions.swift new file mode 100644 index 0000000000000..6123b89a464c8 --- /dev/null +++ b/test/Concurrency/isolation_macro_local_functions.swift @@ -0,0 +1,15 @@ +// RUN: %target-swift-frontend -emit-silgen %s -disable-availability-checking + +public func hasIsolatedParam(isolation: isolated (any Actor)? = #isolation) async -> T {} + +func callee(_: @autoclosure () -> T, _: @autoclosure () -> T) {} + +func outer() async { + func inner() async -> String { + let x = #isolation + return await hasIsolatedParam() + } + + var value = await inner() + callee(value, "hi") +} diff --git a/test/Concurrency/preconcurrency_conformances.swift b/test/Concurrency/preconcurrency_conformances.swift index 42a953fc8e8ff..a1c31e192eb11 100644 --- a/test/Concurrency/preconcurrency_conformances.swift +++ b/test/Concurrency/preconcurrency_conformances.swift @@ -182,3 +182,19 @@ do { func test() {} } } + +// https://github.com/apple/swift/issues/74294 +protocol Parent { + func a() +} + +protocol Child: Parent { + func b() +} + +do { + actor Test: @preconcurrency Child { + func a() {} // Ok + func b() {} // Ok + } +} diff --git a/test/Concurrency/predates_concurrency_import_foundation_darwin.swift b/test/Concurrency/predates_concurrency_import_foundation_darwin.swift new file mode 100644 index 0000000000000..3ebe07367a0e5 --- /dev/null +++ b/test/Concurrency/predates_concurrency_import_foundation_darwin.swift @@ -0,0 +1,12 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -swift-version 6 -I %t %s -emit-sil -o /dev/null -verify -parse-as-library + +// REQUIRES: OS=macosx + +import Foundation +@preconcurrency import Darwin + +func mach_task_self() -> mach_port_t { + return mach_task_self_ +} diff --git a/test/Concurrency/sendable_methods.swift b/test/Concurrency/sendable_methods.swift index d141121737673..988d035a271c1 100644 --- a/test/Concurrency/sendable_methods.swift +++ b/test/Concurrency/sendable_methods.swift @@ -42,6 +42,7 @@ struct InferredSendableS: P { enum InferredSendableE: P { case a, b + case c(Int) func f() { } } @@ -60,6 +61,13 @@ struct GenericS : P { func g() async { } } +enum GenericE { + case a + case b(T) +} + +extension GenericE: Sendable where T: Sendable { } + class NonSendable { func f() {} } @@ -265,3 +273,16 @@ do { true ? nil : c // Ok } } + +func acceptSendableFunc(_: @Sendable (T) -> U) { } + +acceptSendableFunc(InferredSendableE.c) +acceptSendableFunc(GenericE.b) +acceptSendableFunc(GenericE.b) + +// Make sure pattern matching isn't affected by @Sendable on cases. +func testPatternMatch(ge: [GenericE]) { + if case .b(let a) = ge.first { + _ = a + } +} diff --git a/test/Concurrency/sending_asynciteratornext_typechecker_error.swift b/test/Concurrency/sending_asynciteratornext_typechecker_error.swift new file mode 100644 index 0000000000000..e0054ba2b9c14 --- /dev/null +++ b/test/Concurrency/sending_asynciteratornext_typechecker_error.swift @@ -0,0 +1,77 @@ +// RUN: not %target-swift-frontend %s -c -swift-version 6 -module-name _Concurrency + +// READ THIS: This test is only supposed to be making sure that we do not crash +// when we fail to match a witness that doesn't match AsyncIteratorProtocol.next +// b/c of sending. It should fail... but not crash. + +@available(SwiftStdlib 5.1, *) +public protocol AsyncIteratorProtocol { + associatedtype Element + + /// The type of failure produced by iteration. + @available(SwiftStdlib 6.0, *) + associatedtype Failure: Error = any Error + + /// Asynchronously advances to the next element and returns it, or ends the + /// sequence if there is no next element. + /// + /// - Returns: The next element, if it exists, or `nil` to signal the end of + /// the sequence. + mutating func next() async throws -> sending Element? + + /// Asynchronously advances to the next element and returns it, or ends the + /// sequence if there is no next element. + /// + /// - Returns: The next element, if it exists, or `nil` to signal the end of + /// the sequence. + @available(SwiftStdlib 6.0, *) + mutating func next(isolation actor: isolated (any Actor)?) async throws(Failure) -> sending Element? +} + +@available(SwiftStdlib 5.1, *) +extension AsyncIteratorProtocol { + /// Default implementation of `next(isolation:)` in terms of `next()`, which + /// is required to maintain backward compatibility with existing async + /// iterators. + @available(SwiftStdlib 6.0, *) + @inlinable + public mutating func next(isolation actor: isolated (any Actor)?) async throws(Failure) -> sending Element? { + do { + return try await next() + } catch { + throw error as! Failure + } + } +} + +@available(SwiftStdlib 5.1, *) +extension AsyncIteratorProtocol { + /// Default implementation of `next()` in terms of `next(isolation:)`, which + /// is required to maintain backward compatibility with existing async + /// iterators. + @available(SwiftStdlib 6.0, *) + @inlinable + public mutating func next() async throws(Failure) -> sending Element? { +#if $OptionalIsolatedParameters + return try await next(isolation: nil) +#else + fatalError("unsupported compiler") +#endif + } +} + +public struct FakeMapSequence : AsyncIteratorProtocol { + typealias Element = T + + @available(SwiftStdlib 6.0, *) + @inlinable + public mutating func next(isolation actor: isolated (any Actor)?) async throws(Failure) -> Element? { + fatalError() + } + + @inlinable + public mutating func next() async throws -> Element? { + fatalError() + } +} + diff --git a/test/Concurrency/sending_closure_inference.swift b/test/Concurrency/sending_closure_inference.swift new file mode 100644 index 0000000000000..e8343ade2b8ff --- /dev/null +++ b/test/Concurrency/sending_closure_inference.swift @@ -0,0 +1,48 @@ +// RUN: %target-swift-frontend -swift-version 6 %s -emit-silgen | %FileCheck %s + +// READ THIS! This file only contains tests that validate that the relevant +// function subtyping rules for sending work. Please do not put other tests in +// the file! + +// REQUIRES: concurrency +// REQUIRES: asserts + +//////////////////////// +// MARK: Declarations // +//////////////////////// + +class NonSendableKlass {} + +///////////////// +// MARK: Tests // +///////////////// + +// CHECK: sil private [ossa] @$s25sending_closure_inference38testAnonymousParameterSendingInferenceyyFySSYucfU_ : $@convention(thin) (@sil_sending @guaranteed String) -> () { +func testAnonymousParameterSendingInference() { + let _: (sending String) -> () = { + print($0) + } +} + +// CHECK: sil private [ossa] @$s25sending_closure_inference38testNamedOnlyParameterSendingInferenceyyFySSYucfU_ : $@convention(thin) (@sil_sending @guaranteed String) -> () { +func testNamedOnlyParameterSendingInference() { + let _: (sending String) -> () = { x in + print(x) + } +} + +// CHECK: sil private [ossa] @$s25sending_closure_inference38testNamedTypeParameterSendingInferenceyyFySSnYucfU_ : $@convention(thin) (@sil_sending @owned String) -> () { +func testNamedTypeParameterSendingInference() { + let _: (sending String) -> () = { (x: sending String) in + print(x) + } +} + +// CHECK: sil private [ossa] @$s25sending_closure_inference26testSendingResultInferenceyyFSSyYTcfU_ : $@convention(thin) () -> @sil_sending @owned String { +func testSendingResultInference() { + let _: () -> sending String = { "" } +} + +func testSendingResultOnClosure() { + let _ = { (x: String) -> sending String in x } +} diff --git a/test/Concurrency/transfernonsendable.swift b/test/Concurrency/transfernonsendable.swift index c8fb0bc6c73a1..244ceaa6a3791 100644 --- a/test/Concurrency/transfernonsendable.swift +++ b/test/Concurrency/transfernonsendable.swift @@ -15,7 +15,7 @@ //////////////////////// /// Classes are always non-sendable, so this is non-sendable -class NonSendableKlass { // expected-complete-note 51{{}} +class NonSendableKlass { // expected-complete-note 53{{}} // expected-typechecker-only-note @-1 3{{}} // expected-tns-note @-2 {{}} var field: NonSendableKlass? = nil @@ -1688,6 +1688,19 @@ func initAccessorTests() { get { fatalError() } set { fatalError() } } + + @MainActor + var third: NonSendableKlass + @MainActor + var fourth: NonSendableKlass? = nil { + @storageRestrictions(initializes: third) + init(initialValue) { + third = initialValue! + } + + get { fatalError() } + set { fatalError() } + } } } @@ -1723,3 +1736,13 @@ func sendableGlobalActorIsolated() { } print(x) // expected-tns-note {{access can happen concurrently}} } + +// We do not get an error here since we are transferring x both times to a main +// actor isolated thing function. We used to emit an error when using region +// isolation since we would trip on the store_borrow we used to materialize the +// value. +func testIndirectParameterSameIsolationNoError() async { + let x = NonSendableKlass() + await transferToMain(x) // expected-complete-warning {{passing argument of non-sendable type 'NonSendableKlass' into main actor-isolated context may introduce data races}} + await transferToMain(x) // expected-complete-warning {{passing argument of non-sendable type 'NonSendableKlass' into main actor-isolated context may introduce data races}} +} diff --git a/test/Concurrency/transfernonsendable_asynclet.swift b/test/Concurrency/transfernonsendable_asynclet.swift index 462dbff8113d1..d41bed7366251 100644 --- a/test/Concurrency/transfernonsendable_asynclet.swift +++ b/test/Concurrency/transfernonsendable_asynclet.swift @@ -9,7 +9,7 @@ //////////////////////// /// Classes are always non-sendable, so this is non-sendable -class NonSendableKlass { // expected-complete-note 96{{}} +class NonSendableKlass { // expected-complete-note 99{{}} // expected-tns-note @-1 {{}} var field: NonSendableKlass? = nil var field2: NonSendableKlass? = nil @@ -34,6 +34,13 @@ final actor FinalActor { func useKlass(_ x: NonSendableKlass) {} } +actor CustomActorInstance {} + +@globalActor +struct CustomActor { + static let shared = CustomActorInstance() +} + func useInOut(_ x: inout T) {} @discardableResult func useValue(_ x: T) -> T { x } @@ -42,6 +49,7 @@ func useValueWrapInOptional(_ x: T) -> T? { x } @MainActor func returnValueFromMain() async -> T { fatalError() } @MainActor func transferToMain(_ t: T) async {} @MainActor func transferToMainInt(_ t: T) async -> Int { 5 } +@CustomActor func transferToCustomInt(_ t: T) async -> Int { 5 } @MainActor func transferToMainIntOpt(_ t: T) async -> Int? { 5 } func transferToNonIsolated(_ t: T) async {} @@ -306,18 +314,33 @@ func asyncLet_Let_ActorIsolated_CallBuriedInOtherExpr3() async { let _ = await y } -// Make sure that we emit an error for transferToMainInt in the async val -// function itself. +// Make sure that we do not emit an error for transferToMainInt in the async val +// function itself since we are sending the value to the same main actor +// isolated use and transferring it into one async let variable. func asyncLet_Let_ActorIsolated_CallBuriedInOtherExpr4() async { let x = NonSendableKlass() - async let y = useValue(transferToMainInt(x) + transferToMainInt(x)) // expected-tns-warning {{sending 'x' risks causing data races}} - // expected-tns-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMainInt' risks causing data races between main actor-isolated and local nonisolated uses}} - // expected-tns-note @-2:67 {{access can happen concurrently}} + async let y = useValue(transferToMainInt(x) + transferToMainInt(x)) + // expected-complete-warning @-1 {{capture of 'x' with non-sendable type 'NonSendableKlass' in 'async let' binding}} + // expected-complete-warning @-2 {{passing argument of non-sendable type 'NonSendableKlass' into main actor-isolated context may introduce data races}} + // expected-complete-warning @-3 {{passing argument of non-sendable type 'NonSendableKlass' into main actor-isolated context may introduce data races}} - // expected-complete-warning @-4 {{capture of 'x' with non-sendable type 'NonSendableKlass' in 'async let' binding}} - // expected-complete-warning @-5 {{passing argument of non-sendable type 'NonSendableKlass' into main actor-isolated context may introduce data races}} + let _ = await y +} + +// Make sure that we do emit an error since we are sending the value to two +// different isolation domains in the async let. +func asyncLet_Let_ActorIsolated_CallBuriedInOtherExpr5() async { + let x = NonSendableKlass() + + async let y = useValue(transferToMainInt(x) + transferToCustomInt(x)) + // expected-tns-warning @-1 {{sending 'x' risks causing data races}} + // expected-tns-note @-2 {{sending 'x' to main actor-isolated global function 'transferToMainInt' risks causing data races between main actor-isolated and local nonisolated uses}} + // expected-tns-note @-3:49 {{access can happen concurrently}} + + // expected-complete-warning @-5 {{capture of 'x' with non-sendable type 'NonSendableKlass' in 'async let' binding}} // expected-complete-warning @-6 {{passing argument of non-sendable type 'NonSendableKlass' into main actor-isolated context may introduce data races}} + // expected-complete-warning @-7 {{passing argument of non-sendable type 'NonSendableKlass' into global actor 'CustomActor'-isolated context may introduce data races}} let _ = await y } diff --git a/test/Concurrency/transfernonsendable_functionsubtyping.swift b/test/Concurrency/transfernonsendable_functionsubtyping.swift new file mode 100644 index 0000000000000..be18f172ed7f9 --- /dev/null +++ b/test/Concurrency/transfernonsendable_functionsubtyping.swift @@ -0,0 +1,111 @@ +// RUN: %target-typecheck-verify-swift -swift-version 6 + +// READ THIS! This file only contains tests that validate that the relevant +// function subtyping rules for sending work. Please do not put other tests in +// the file! + +// REQUIRES: concurrency +// REQUIRES: asserts + +//////////////////////// +// MARK: Declarations // +//////////////////////// + +class NonSendableKlass {} + +protocol ProtocolWithSendingReqs { + func sendingResult() -> sending NonSendableKlass // expected-note {{}} + func nonSendingParam(_ x: NonSendableKlass) // expected-note {{}} +} + +protocol ProtocolWithMixedReqs { + func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> sending NonSendableKlass // expected-note 4{{}} +} + +///////////////////////////////// +// MARK: Normal Function Tests // +///////////////////////////////// + +func functionWithSendingResult() -> sending NonSendableKlass { fatalError() } +func functionWithoutSendingResult() -> NonSendableKlass { fatalError() } +func functionWithSendingParameter(_ x: sending NonSendableKlass) { fatalError() } +func functionWithoutSendingParameter(_ x: NonSendableKlass) { fatalError() } + +func takeFnWithSendingResult(_ fn: () -> sending NonSendableKlass) {} +func takeFnWithoutSendingResult(_ fn: () -> NonSendableKlass) {} +func takeFnWithSendingParam(_ fn: (sending NonSendableKlass) -> ()) {} +func takeFnWithoutSendingParam(_ fn: (NonSendableKlass) -> ()) {} + +func testFunctionMatching() { + let _: (NonSendableKlass) -> () = functionWithSendingParameter + // expected-error @-1 {{converting a value of type '@Sendable (sending NonSendableKlass) -> ()' to type '(NonSendableKlass) -> ()' risks causing data races}} + // expected-note @-2 {{converting a function typed value with a sending parameter to one without risks allowing actor-isolated values to escape their isolation domain as an argument to an invocation of value}} + let _: (sending NonSendableKlass) -> () = functionWithSendingParameter + + let _: (NonSendableKlass) -> () = functionWithoutSendingParameter + let _: (sending NonSendableKlass) -> () = functionWithoutSendingParameter + + takeFnWithSendingParam(functionWithSendingParameter) + takeFnWithoutSendingParam(functionWithSendingParameter) + // expected-error @-1 {{converting a value of type '@Sendable (sending NonSendableKlass) -> ()' to type '(NonSendableKlass) -> ()' risks causing data races}} + // expected-note @-2 {{converting a function typed value with a sending parameter to one without risks allowing actor-isolated values to escape their isolation domain as an argument to an invocation of value}} + takeFnWithSendingParam(functionWithoutSendingParameter) + takeFnWithoutSendingParam(functionWithoutSendingParameter) +} + +func testReturnValueMatching() { + let _: () -> NonSendableKlass = functionWithSendingResult + let _: () -> sending NonSendableKlass = functionWithSendingResult + let _: () -> NonSendableKlass = functionWithoutSendingResult + let _: () -> sending NonSendableKlass = functionWithoutSendingResult + // expected-error @-1 {{converting a value of type '@Sendable () -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}} + // expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}} + + takeFnWithSendingResult(functionWithSendingResult) + takeFnWithSendingResult(functionWithoutSendingResult) + // expected-error @-1 {{converting a value of type '@Sendable () -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}} + // expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}} + let x: () -> NonSendableKlass = { fatalError() } + takeFnWithSendingResult(x) + // expected-error @-1 {{converting a value of type '() -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}} + // expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}} + + takeFnWithoutSendingResult(functionWithSendingResult) + takeFnWithoutSendingResult(functionWithoutSendingResult) + takeFnWithoutSendingResult(x) +} + +////////////////////////// +// MARK: Protocol Tests // +////////////////////////// + +struct MatchSuccess : ProtocolWithSendingReqs, ProtocolWithMixedReqs { + func sendingResult() -> sending NonSendableKlass { fatalError() } + func nonSendingParam(_ x: NonSendableKlass) -> () { fatalError() } + func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> sending NonSendableKlass { fatalError() } +} + +struct FailToMatch : ProtocolWithSendingReqs, ProtocolWithMixedReqs { // expected-error 2{{}} + func sendingResult() -> NonSendableKlass { fatalError() } + // expected-note @-1 {{candidate has non-matching type '() -> NonSendableKlass'}} + func nonSendingParam(_ x: sending NonSendableKlass) -> () { fatalError() } + // expected-note @-1 {{candidate has non-matching type '(sending NonSendableKlass) -> ()'}} + func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> NonSendableKlass { fatalError() } + // expected-note @-1 {{candidate has non-matching type '(sending NonSendableKlass) -> NonSendableKlass'}} +} + +struct FailToMatch2 : ProtocolWithMixedReqs { // expected-error {{}} + func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> NonSendableKlass { fatalError() } + // expected-note @-1 {{candidate has non-matching type '(sending NonSendableKlass) -> NonSendableKlass'}} +} + +struct FailToMatch3 : ProtocolWithMixedReqs { // expected-error {{}} + func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> NonSendableKlass { fatalError() } + // expected-note @-1 {{candidate has non-matching type '(NonSendableKlass) -> NonSendableKlass'}} +} + +struct FailToMatch4 : ProtocolWithMixedReqs { // expected-error {{}} + func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> sending NonSendableKlass { fatalError() } + // expected-note @-1 {{candidate has non-matching type '(sending NonSendableKlass) -> sending NonSendableKlass'}} +} + diff --git a/test/Concurrency/transfernonsendable_functionsubtyping_swift5.swift b/test/Concurrency/transfernonsendable_functionsubtyping_swift5.swift new file mode 100644 index 0000000000000..c57e2e05a40d8 --- /dev/null +++ b/test/Concurrency/transfernonsendable_functionsubtyping_swift5.swift @@ -0,0 +1,107 @@ +// RUN: %target-typecheck-verify-swift -swift-version 5 + +// READ THIS! This file only contains tests that validate how the relevant +// function subtyping rules for sending work in swift 5 mode +// specifically. Please do not put other tests in the file! +// +// We expect today that protocol mismatch errors are elided and function +// mismatch errors are warnings. + +// REQUIRES: concurrency +// REQUIRES: asserts + +//////////////////////// +// MARK: Declarations // +//////////////////////// + +class NonSendableKlass {} + +protocol ProtocolWithSendingReqs { + func sendingResult() -> sending NonSendableKlass + func nonSendingParam(_ x: NonSendableKlass) +} + +protocol ProtocolWithMixedReqs { + func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> sending NonSendableKlass +} + +///////////////////////////////// +// MARK: Normal Function Tests // +///////////////////////////////// + +func functionWithSendingResult() -> sending NonSendableKlass { fatalError() } +func functionWithoutSendingResult() -> NonSendableKlass { fatalError() } +func functionWithSendingParameter(_ x: sending NonSendableKlass) { fatalError() } +func functionWithoutSendingParameter(_ x: NonSendableKlass) { fatalError() } + +func takeFnWithSendingResult(_ fn: () -> sending NonSendableKlass) {} +func takeFnWithoutSendingResult(_ fn: () -> NonSendableKlass) {} +func takeFnWithSendingParam(_ fn: (sending NonSendableKlass) -> ()) {} +func takeFnWithoutSendingParam(_ fn: (NonSendableKlass) -> ()) {} + +func testFunctionMatching() { + let _: (NonSendableKlass) -> () = functionWithSendingParameter + // expected-warning @-1 {{converting a value of type '(sending NonSendableKlass) -> ()' to type '(NonSendableKlass) -> ()' risks causing data races}} + // expected-note @-2 {{converting a function typed value with a sending parameter to one without risks allowing actor-isolated values to escape their isolation domain as an argument to an invocation of value}} + let _: (sending NonSendableKlass) -> () = functionWithSendingParameter + + let _: (NonSendableKlass) -> () = functionWithoutSendingParameter + let _: (sending NonSendableKlass) -> () = functionWithoutSendingParameter + + takeFnWithSendingParam(functionWithSendingParameter) + takeFnWithoutSendingParam(functionWithSendingParameter) + // expected-warning @-1 {{converting a value of type '(sending NonSendableKlass) -> ()' to type '(NonSendableKlass) -> ()' risks causing data races}} + // expected-note @-2 {{converting a function typed value with a sending parameter to one without risks allowing actor-isolated values to escape their isolation domain as an argument to an invocation of value}} + takeFnWithSendingParam(functionWithoutSendingParameter) + takeFnWithoutSendingParam(functionWithoutSendingParameter) +} + +func testReturnValueMatching() { + let _: () -> NonSendableKlass = functionWithSendingResult + let _: () -> sending NonSendableKlass = functionWithSendingResult + let _: () -> NonSendableKlass = functionWithoutSendingResult + let _: () -> sending NonSendableKlass = functionWithoutSendingResult + // expected-warning @-1 {{converting a value of type '() -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}} + // expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}} + + takeFnWithSendingResult(functionWithSendingResult) + takeFnWithSendingResult(functionWithoutSendingResult) + // expected-warning @-1 {{converting a value of type '() -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}} + // expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}} + let x: () -> NonSendableKlass = { fatalError() } + takeFnWithSendingResult(x) + // expected-warning @-1 {{converting a value of type '() -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}} + // expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}} + + takeFnWithoutSendingResult(functionWithSendingResult) + takeFnWithoutSendingResult(functionWithoutSendingResult) + takeFnWithoutSendingResult(x) +} + +////////////////////////// +// MARK: Protocol Tests // +////////////////////////// + +struct MatchSuccess : ProtocolWithSendingReqs, ProtocolWithMixedReqs { + func sendingResult() -> sending NonSendableKlass { fatalError() } + func nonSendingParam(_ x: NonSendableKlass) -> () { fatalError() } + func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> sending NonSendableKlass { fatalError() } +} + +struct FailToMatch : ProtocolWithSendingReqs, ProtocolWithMixedReqs { + func sendingResult() -> NonSendableKlass { fatalError() } + func nonSendingParam(_ x: sending NonSendableKlass) -> () { fatalError() } + func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> NonSendableKlass { fatalError() } +} + +struct FailToMatch2 : ProtocolWithMixedReqs { + func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> NonSendableKlass { fatalError() } +} + +struct FailToMatch3 : ProtocolWithMixedReqs { + func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> NonSendableKlass { fatalError() } +} + +struct FailToMatch4 : ProtocolWithMixedReqs { + func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> sending NonSendableKlass { fatalError() } +} diff --git a/test/CrossImport/access-level-imports-errors.swift b/test/CrossImport/access-level-imports-errors.swift new file mode 100644 index 0000000000000..93363fd88696e --- /dev/null +++ b/test/CrossImport/access-level-imports-errors.swift @@ -0,0 +1,80 @@ +/// Check semantic verification cross-import overlays with non-public imports. + +// RUN: %empty-directory(%t) +// RUN: cp -r %S/Inputs/lib-templates/* %t/ +// RUN: split-file --leading-lines %s %t + +//--- SomeUnrelatedModule.swift +// RUN: %target-swift-emit-module-interface(%t/lib/swift/SomeUnrelatedModule.swiftinterface) %t/SomeUnrelatedModule.swift -module-name SomeUnrelatedModule + +//--- BothPublic.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/BothPublic.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -verify + +public import DeclaringLibrary +public import BystandingLibrary +public import SomeUnrelatedModule // expected-warning {{public import of 'SomeUnrelatedModule' was not used in public declarations or inlinable code}} + +public func fn(_: OverlayLibraryTy) {} + + +//--- BothHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/BothHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -verify + +internal import DeclaringLibrary +internal import BystandingLibrary + +public func fn(_: OverlayLibraryTy) {} +// expected-error @-1 {{function cannot be declared public because its parameter uses an internal type}} +// expected-note @-2 {{struct 'OverlayLibraryTy' is imported by this file as 'internal' from '_OverlayLibrary'}} + + +//--- FirstHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/FirstHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -verify + +internal import DeclaringLibrary +public import BystandingLibrary + +public func fn(_: OverlayLibraryTy) {} +// expected-error @-1 {{function cannot be declared public because its parameter uses an internal type}} +// expected-note @-2 {{struct 'OverlayLibraryTy' is imported by this file as 'internal' from '_OverlayLibrary'}} + + +//--- SecondHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/SecondHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -verify + +public import DeclaringLibrary +internal import BystandingLibrary + +public func fn(_: OverlayLibraryTy) {} +// expected-error @-1 {{function cannot be declared public because its parameter uses an internal type}} +// expected-note @-2 {{struct 'OverlayLibraryTy' is imported by this file as 'internal' from '_OverlayLibrary'}} + + +//--- PrivateVsInternal.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/PrivateVsInternal.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -verify + +private import DeclaringLibrary +internal import BystandingLibrary + +internal func fn(_: OverlayLibraryTy) {} +// expected-error @-1 {{function cannot be declared internal because its parameter uses a private type}} +// expected-note @-2 {{struct 'OverlayLibraryTy' is imported by this file as 'private' from '_OverlayLibrary'}} + + +//--- InternalVsPrivate.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/InternalVsPrivate.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -verify + +internal import DeclaringLibrary +private import BystandingLibrary + +internal func fn(_: OverlayLibraryTy) {} +// expected-error @-1 {{function cannot be declared internal because its parameter uses a private type}} +// expected-note @-2 {{struct 'OverlayLibraryTy' is imported by this file as 'private' from '_OverlayLibrary'}} + + +//--- UnusedOverlay.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/UnusedOverlay.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -verify + +public import DeclaringLibrary // expected-warning {{public import of 'DeclaringLibrary' was not used in public declarations or inlinable code}} +public import BystandingLibrary // expected-warning {{public import of 'BystandingLibrary' was not used in public declarations or inlinable code}} +public import SomeUnrelatedModule // expected-warning {{public import of 'SomeUnrelatedModule' was not used in public declarations or inlinable code}} diff --git a/test/CrossImport/module-interface.swift b/test/CrossImport/module-interface.swift index 991e1e52f3c69..2b0d52b70125f 100644 --- a/test/CrossImport/module-interface.swift +++ b/test/CrossImport/module-interface.swift @@ -10,7 +10,6 @@ // RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary // RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary // RUN: %FileCheck %s < %t.swiftinterface -// RUN: %FileCheck -check-prefix NEGATIVE %s < %t.swiftinterface // // Should fail with -disable-cross-import-overlays @@ -38,9 +37,9 @@ public func shadow(_: DeclaringLibrary.ShadowTy, _: ShadowTy) {} // CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary // CHECK-DAG: import Swift +// CHECK-DAG: import DeclaringLibrary // CHECK-DAG: import BystandingLibrary // CHECK-DAG: import _OverlayLibrary -// NEGATIVE-NOT: import DeclaringLibrary // CHECK-DAG: public func fn(_: DeclaringLibrary.DeclaringLibraryTy, _: BystandingLibrary.BystandingLibraryTy, _: _OverlayLibrary.OverlayLibraryTy) // CHECK-DAG: public func alias(_: _OverlayLibrary.OverlayLibraryTy) diff --git a/test/CrossImport/with-access-level-import.swift b/test/CrossImport/with-access-level-import.swift new file mode 100644 index 0000000000000..00cbf6123ae74 --- /dev/null +++ b/test/CrossImport/with-access-level-import.swift @@ -0,0 +1,71 @@ +/// Check cross-import overlays with non-public imports. + +// RUN: %empty-directory(%t) +// RUN: cp -r %S/Inputs/lib-templates/* %t/ +// RUN: split-file --leading-lines %s %t + +//--- BothPublic.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/BothPublic.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/BothPublic.swift < %t.swiftinterface + +public import DeclaringLibrary +public import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import DeclaringLibrary +// CHECK-DAG: import BystandingLibrary +// CHECK-DAG: import _OverlayLibrary + + +//--- BothHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/BothHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/BothHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/BothHidden.swift < %t.swiftinterface + +internal import DeclaringLibrary +internal import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// NEGATIVE-NOT: import DeclaringLibrary +// NEGATIVE-NOT: import BystandingLibrary +// NEGATIVE-NOT: import _OverlayLibrary + + +//--- FirstHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/FirstHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/FirstHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/FirstHidden.swift < %t.swiftinterface + +internal import DeclaringLibrary +public import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import BystandingLibrary +// NEGATIVE-NOT: import DeclaringLibrary +// NEGATIVE-NOT: import _OverlayLibrary + + +//--- SecondHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/SecondHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/SecondHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/SecondHidden.swift < %t.swiftinterface + +public import DeclaringLibrary +internal import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import DeclaringLibrary +// NEGATIVE-NOT: import BystandingLibrary +// NEGATIVE-NOT: import _OverlayLibrary diff --git a/test/CrossImport/with-implementation-only.swift b/test/CrossImport/with-implementation-only.swift new file mode 100644 index 0000000000000..a78c9d540bedd --- /dev/null +++ b/test/CrossImport/with-implementation-only.swift @@ -0,0 +1,71 @@ +/// Check cross-import overlays with @_implementationOnly imports. + +// RUN: %empty-directory(%t) +// RUN: cp -r %S/Inputs/lib-templates/* %t/ +// RUN: split-file --leading-lines %s %t + +//--- BothPublic.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/BothPublic.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/BothPublic.swift < %t.swiftinterface + +import DeclaringLibrary +import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import DeclaringLibrary +// CHECK-DAG: import BystandingLibrary +// CHECK-DAG: import _OverlayLibrary + + +//--- BothHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/BothHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/BothHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/BothHidden.swift < %t.swiftinterface + +@_implementationOnly import DeclaringLibrary +@_implementationOnly import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// NEGATIVE-NOT: import DeclaringLibrary +// NEGATIVE-NOT: import BystandingLibrary +// NEGATIVE-NOT: import _OverlayLibrary + + +//--- FirstHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/FirstHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/FirstHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/FirstHidden.swift < %t.swiftinterface + +@_implementationOnly import DeclaringLibrary +import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import BystandingLibrary +// NEGATIVE-NOT: import DeclaringLibrary +// NEGATIVE-NOT: import _OverlayLibrary + + +//--- SecondHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/SecondHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/SecondHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/SecondHidden.swift < %t.swiftinterface + +import DeclaringLibrary +@_implementationOnly import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import DeclaringLibrary +// NEGATIVE-NOT: import BystandingLibrary +// NEGATIVE-NOT: import _OverlayLibrary diff --git a/test/CrossImport/with-spi-only-import.swift b/test/CrossImport/with-spi-only-import.swift new file mode 100644 index 0000000000000..9ac2cb341deec --- /dev/null +++ b/test/CrossImport/with-spi-only-import.swift @@ -0,0 +1,86 @@ +/// Check cross-import overlays with @_spiOnly imports. + +// RUN: %empty-directory(%t) +// RUN: cp -r %S/Inputs/lib-templates/* %t/ +// RUN: split-file --leading-lines %s %t + +//--- BothPublic.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/BothPublic.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -emit-private-module-interface-path %t.private.swiftinterface -swift-version 6 +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.private.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/BothPublic.swift < %t.swiftinterface +// RUN: %FileCheck %t/BothPublic.swift < %t.private.swiftinterface + +import DeclaringLibrary +import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import DeclaringLibrary +// CHECK-DAG: import BystandingLibrary +// CHECK-DAG: import _OverlayLibrary + + +//--- BothHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/BothHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -emit-private-module-interface-path %t.private.swiftinterface -swift-version 6 +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.private.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/BothHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/BothHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefixes CHECK,PRIVATE %t/BothHidden.swift < %t.private.swiftinterface + +@_spiOnly import DeclaringLibrary +@_spiOnly import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// NEGATIVE-NOT: import DeclaringLibrary +// NEGATIVE-NOT: import BystandingLibrary +// NEGATIVE-NOT: import _OverlayLibrary +// PRIVATE-DAG: import DeclaringLibrary +// PRIVATE-DAG: import BystandingLibrary +// PRIVATE-DAG: import _OverlayLibrary + + +//--- FirstHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/FirstHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -emit-private-module-interface-path %t.private.swiftinterface -swift-version 6 +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.private.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/FirstHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/FirstHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefixes CHECK,PRIVATE %t/FirstHidden.swift < %t.private.swiftinterface + +@_spiOnly import DeclaringLibrary +import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import BystandingLibrary +// NEGATIVE-NOT: import DeclaringLibrary +// NEGATIVE-NOT: import _OverlayLibrary +// PRIVATE-DAG: import DeclaringLibrary +// PRIVATE-DAG: import _OverlayLibrary + + +//--- SecondHidden.swift +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/SecondHidden.swift -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary -emit-private-module-interface-path %t.private.swiftinterface -swift-version 6 +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %target-swift-typecheck-module-from-interface(%t.private.swiftinterface) -enable-cross-import-overlays -I %t/lib/swift -module-name ClientLibrary +// RUN: %FileCheck %t/SecondHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefix NEGATIVE %t/SecondHidden.swift < %t.swiftinterface +// RUN: %FileCheck -check-prefixes CHECK,PRIVATE %t/SecondHidden.swift < %t.private.swiftinterface + +import DeclaringLibrary +@_spiOnly import BystandingLibrary + +// CHECK: // swift-interface-format-version +// CHECK: // swift-module-flags: {{.*}} -module-name ClientLibrary +// CHECK-DAG: import Swift +// CHECK-DAG: import DeclaringLibrary +// NEGATIVE-NOT: import BystandingLibrary +// NEGATIVE-NOT: import _OverlayLibrary +// PRIVATE-DAG: import BystandingLibrary +// PRIVATE-DAG: import _OverlayLibrary diff --git a/test/DebugInfo/BridgingHeaderPCH.swift b/test/DebugInfo/BridgingHeaderPCH.swift index 966e8baf997f4..b7a6996658eba 100644 --- a/test/DebugInfo/BridgingHeaderPCH.swift +++ b/test/DebugInfo/BridgingHeaderPCH.swift @@ -5,8 +5,6 @@ // CHECK: !DICompileUnit(language: DW_LANG_Swift // CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}}, -// CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}}, -// CHECK-SAME: splitDebugFilename: "{{.*}}.pch" -// CHECK-SAME: dwoId: +// CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}}{{.*}}splitDebugFilename: "{{.*}}.pch",{{.*}}dwoId: Foo() diff --git a/test/DebugInfo/ClangModuleBreadcrumbs.swift b/test/DebugInfo/ClangModuleBreadcrumbs.swift index 185e3be067272..56948b57c0ace 100644 --- a/test/DebugInfo/ClangModuleBreadcrumbs.swift +++ b/test/DebugInfo/ClangModuleBreadcrumbs.swift @@ -16,29 +16,17 @@ import OtherClangModule.SubModule let _ = someFunc(0) // Check for Clang module breadcrumbs. -// CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}Swift -// CHECK-SAME: ClangModule -// CHECK-SAME: dwoId: +// CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}Swift{{.*}}ClangModule{{.*}}dwoId: -// CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}}, {{.*}} producer: "{{.*}}Swift -// CHECK-SAME: OtherClangModule -// CHECK-SAME: dwoId: +// CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}}, {{.*}} producer: "{{.*}}Swift{{.*}}OtherClangModule{{.*}}dwoId: -// CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}clang -// CHECK-SAME: ClangModule -// CHECK-SAME: dwoId: +// CHECK: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}clang{{.*}}ClangModule{{.*}}dwoId: // NONE: DICompileUnit({{.*}} // NONE-NOT: DICompileUnit({{.*}}ClangModule -// REMAP: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}Swift -// REMAP-SAME: PREFIX{{/|\\\\}}{{.*}}{{/|\\\\}}ClangModule -// REMAP-SAME: dwoId: +// REMAP: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}Swift{{.*}}PREFIX{{/|\\\\}}{{.*}}{{/|\\\\}}ClangModule{{.*}}dwoId: -// REMAP: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}Swift -// REMAP-SAME: PREFIX{{/|\\\\}}{{.*}}{{/|\\\\}}OtherClangModule -// REMAP-SAME: dwoId: +// REMAP: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}Swift{{.*}}PREFIX{{/|\\\\}}{{.*}}{{/|\\\\}}OtherClangModule{{.*}}dwoId: -// REMAP: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}clang -// REMAP-SAME: PREFIX{{/|\\\\}}{{.*}}{{/|\\\\}}ClangModule -// REMAP-SAME: dwoId: +// REMAP: !DICompileUnit(language: DW_LANG_{{ObjC|C99|C11}},{{.*}} producer: "{{.*}}clang{{.*}}PREFIX{{/|\\\\}}{{.*}}{{/|\\\\}}ClangModule{{.*}}dwoId: diff --git a/test/DebugInfo/sending_params_and_results.swift b/test/DebugInfo/sending_params_and_results.swift index 84bb6d475628a..756c688c4a7c1 100644 --- a/test/DebugInfo/sending_params_and_results.swift +++ b/test/DebugInfo/sending_params_and_results.swift @@ -14,11 +14,11 @@ public struct SendableStruct: Sendable { // // @escaping @callee_guaranteed (@guaranteed sending Swift.Result) -> () // -// CHECK: !{{[0-9]+}} = !DICompositeType(tag: DW_TAG_structure_type, name: "$ss6ResultOy4test14SendableStructVs5Error_pGIeggT_D", flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift) +// CHECK: !{{[0-9]+}} = !DICompositeType(tag: DW_TAG_structure_type, name: "$ss6ResultOy4test14SendableStructVs5Error_pGIeggT_D", func testReconstructingEscapingClosureWithSendingParam() async throws -> SendableStruct { func callSendableFunction(_ x: @Sendable () -> ()) {} - func helper(_ completion: @escaping (Result) -> Void) { + func helper(_ completion: @escaping (__shared sending Result) -> Void) { fatalError() } diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt index ba76838830686..0eae2180776ba 100644 --- a/test/Demangle/Inputs/manglings.txt +++ b/test/Demangle/Inputs/manglings.txt @@ -473,3 +473,5 @@ $sSRyxG15Synchronization19AtomicRepresentableABRi0_zrlMc ---> protocol conforman $sSRyxG15Synchronization19AtomicRepresentableABRi1_zrlMc ---> protocol conformance descriptor for < where A: ~Swift.> Swift.UnsafeBufferPointer : Synchronization.AtomicRepresentable in Synchronization $s23variadic_generic_opaque2G2VyAA2S1V_AA2S2VQPGAA1PHPAeA1QHPyHC_AgaJHPyHCHX_HC ---> concrete protocol conformance variadic_generic_opaque.G2 to protocol conformance ref (type's module) variadic_generic_opaque.P with conditional requirements: (pack protocol conformance (concrete protocol conformance variadic_generic_opaque.S1 to protocol conformance ref (type's module) variadic_generic_opaque.Q, concrete protocol conformance variadic_generic_opaque.S2 to protocol conformance ref (type's module) variadic_generic_opaque.Q)) + +$s9MacroUser0023macro_expandswift_elFCffMX436_4_23bitwidthNumberedStructsfMf_ ---> freestanding macro expansion #1 of bitwidthNumberedStructs in module MacroUser file macro_expand.swift line 437 column 5 diff --git a/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_inheritance.swift b/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_inheritance.swift index 713333052fd01..8717d594baa17 100644 --- a/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_inheritance.swift +++ b/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_inheritance.swift @@ -25,7 +25,7 @@ protocol Base: DistributedActor where ActorSystem: DistributedActorSystem Int { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() @@ -49,14 +49,14 @@ protocol G3: DistributedActor, Base where ActorSystem: DistributedA // CHECK: extension G3 where Self: Distributed._DistributedActorStub { // CHECK: distributed func get() -> String { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() // CHECK: } // CHECK: } // CHECK: distributed func greet(name: String) -> String { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() diff --git a/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_simple.swift b/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_simple.swift index 0bbd73f269b53..56c95d4b58eea 100644 --- a/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_simple.swift +++ b/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_simple.swift @@ -26,7 +26,7 @@ protocol Greeter: DistributedActor where ActorSystem: DistributedActorSystem String { -// CHECK-NEXT: if #available(SwiftStdlib 6.0, *) { +// CHECK-NEXT: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK-NEXT: Distributed._distributedStubFatalError() // CHECK-NEXT: } else { // CHECK-NEXT: fatalError() diff --git a/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_various_requirements.swift b/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_various_requirements.swift index 4e81514f752ee..061a0648d9ffc 100644 --- a/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_various_requirements.swift +++ b/test/Distributed/Macros/distributed_macro_expansion_DistributedProtocol_various_requirements.swift @@ -24,7 +24,7 @@ protocol Greeter: DistributedActor where ActorSystem == FakeActorSystem { // CHECK: extension Greeter where Self: Distributed._DistributedActorStub { // CHECK: distributed func greet(name: String) -> String { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() @@ -44,7 +44,7 @@ protocol Greeter2: DistributedActor where ActorSystem: DistributedActorSystem String { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() @@ -69,7 +69,7 @@ protocol Greeter3: DistributedActor where ActorSystem: DistributedActorSystem String { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() @@ -89,7 +89,7 @@ public protocol Greeter4: DistributedActor where ActorSystem == FakeActorSystem // CHECK: extension Greeter4 where Self: Distributed._DistributedActorStub { // CHECK: public distributed func greet(name: String) -> String { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() @@ -112,28 +112,28 @@ public protocol GreeterMore: DistributedActor where ActorSystem == FakeActorSyst // CHECK: extension GreeterMore where Self: Distributed._DistributedActorStub { // CHECK: public distributed var name : String { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() // CHECK: } // CHECK: } // CHECK: public distributed func greet(name: String) -> String { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() // CHECK: } // CHECK: } // CHECK: public distributed func another(string: String, int: Int) async throws -> Double { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() // CHECK: } // CHECK: } // CHECK: public distributed func generic(value: T, int: Int) async throws -> T { -// CHECK: if #available(SwiftStdlib 6.0, *) { +// CHECK: if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) { // CHECK: Distributed._distributedStubFatalError() // CHECK: } else { // CHECK: fatalError() diff --git a/test/Driver/options.swift b/test/Driver/options.swift index d001acde914ac..39aa6b3f40f90 100644 --- a/test/Driver/options.swift +++ b/test/Driver/options.swift @@ -109,6 +109,7 @@ // MISSING_OPTION_G_ERROR: error: option '-debug-info-format={{.*}}' is missing a required argument (-g) // RUN: %swift_driver -### -g -dwarf-version=3 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_3 %s +// DWARF_VERSION_5: -dwarf-version=5 // DWARF_VERSION_4: -dwarf-version=4 // DWARF_VERSION_3: -dwarf-version=3 // DWARF_VERSION_2: -dwarf-version=2 @@ -135,6 +136,17 @@ // RUN: %swift_driver -### -g -target arm64_32-apple-watchos10.0 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_4 %s // RUN: %swiftc_driver -### -g -target arm64_32-apple-watchos10.0 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_4 %s +// RUN: %swift_driver -### -g -target x86_64-apple-macosx15 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swiftc_driver -### -g -target x86_64-apple-macosx15 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swift_driver -### -g -target arm64-apple-ios18.0 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swiftc_driver -### -g -target arm64-apple-ios18.0 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swift_driver -### -g -target arm64-apple-ios18.0-macabi %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swiftc_driver -### -g -target arm64-apple-ios18.0-macabi %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swift_driver -### -g -target arm64-apple-tvos18 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swiftc_driver -### -g -target arm64-apple-tvos18 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swift_driver -### -g -target arm64_32-apple-watchos11 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s +// RUN: %swiftc_driver -### -g -target arm64_32-apple-watchos11 %s 2>&1 | %FileCheck -check-prefix DWARF_VERSION_5 %s + // RUN: not %swift_driver -gline-tables-only -debug-info-format=codeview %s 2>&1 | %FileCheck -check-prefix BAD_DEBUG_LEVEL_ERROR %s // RUN: not %swift_driver -gdwarf-types -debug-info-format=codeview %s 2>&1 | %FileCheck -check-prefix BAD_DEBUG_LEVEL_ERROR %s // RUN: not %swiftc_driver -gline-tables-only -debug-info-format=codeview %s 2>&1 | %FileCheck -check-prefix BAD_DEBUG_LEVEL_ERROR %s diff --git a/test/Frontend/parseable_output.swift b/test/Frontend/parseable_output.swift index 97260e4065a1d..fb54f9803cbb8 100644 --- a/test/Frontend/parseable_output.swift +++ b/test/Frontend/parseable_output.swift @@ -1,6 +1,6 @@ -// RUN: %target-swift-frontend -primary-file %s %S/Inputs/filelist-other.swift -o %t.out -module-name parseable_output -empty-abi-descriptor -emit-abi-descriptor-path %t.abi.json -emit-module -emit-module-path %t.swiftmodule -serialize-diagnostics -serialize-diagnostics-path %t.dia -frontend-parseable-output 2>&1 | %FileCheck %s +// RUN: %target-swift-frontend -c -primary-file %s %S/Inputs/filelist-other.swift -o %t.out -module-name parseable_output -empty-abi-descriptor -emit-abi-descriptor-path %t.abi.json -emit-module -emit-module-path %t.swiftmodule -serialize-diagnostics -serialize-diagnostics-path %t.dia -frontend-parseable-output 2>&1 | %FileCheck %s // Check without primary files (WMO): -// RUN: %target-swift-frontend %s %S/Inputs/filelist-other.swift -o %t.out -module-name parseable_output -empty-abi-descriptor -emit-abi-descriptor-path %t.abi.json -emit-module -emit-module-path %t.swiftmodule -serialize-diagnostics -serialize-diagnostics-path %t.dia -frontend-parseable-output 2>&1 | %FileCheck %s +// RUN: %target-swift-frontend -c %s %S/Inputs/filelist-other.swift -o %t.out -module-name parseable_output -empty-abi-descriptor -emit-abi-descriptor-path %t.abi.json -emit-module -emit-module-path %t.swiftmodule -serialize-diagnostics -serialize-diagnostics-path %t.dia -frontend-parseable-output 2>&1 | %FileCheck %s // CHECK: {{[1-9][0-9]*}} // CHECK-NEXT: { diff --git a/test/Frontend/parseable_output_batch.swift b/test/Frontend/parseable_output_batch.swift index da33ab772c5f9..1d131758e7c4c 100644 --- a/test/Frontend/parseable_output_batch.swift +++ b/test/Frontend/parseable_output_batch.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) // RUN: touch %t/test.swift // RUN: echo 'func foo() {}' > %t/test.swift -// RUN: %target-swift-frontend -primary-file %s -primary-file %t/test.swift -o %t.out -o test.tmp.out -module-name parseable_output_batch -emit-module -emit-module-path %t.swiftmodule -module-name test -emit-module -emit-module-path test.tmp.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s +// RUN: %target-swift-frontend -c -primary-file %s -primary-file %t/test.swift -o %t.out -o test.tmp.out -module-name parseable_output_batch -emit-module -emit-module-path %t.swiftmodule -module-name test -emit-module -emit-module-path test.tmp.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s // Despite only one frontend invocation, two compile jobs are "begin" and "finish", using quasi-PIDs, on per-primary and its outputs. diff --git a/test/Frontend/parseable_output_early.swift b/test/Frontend/parseable_output_early.swift index d2d0f3cfc8228..ceb4cf44c87ae 100644 --- a/test/Frontend/parseable_output_early.swift +++ b/test/Frontend/parseable_output_early.swift @@ -1,4 +1,4 @@ -// RUN: not %target-swift-frontend(mock-sdk: -sdk %/S/../ModuleInterface/Inputs/BadStdlib.sdk -module-cache-path %/t/module-cache -resource-dir %/S/../ModuleInterface/Inputs/BadStdlib.sdk) -primary-file %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -module-name parseable_output_early -frontend-parseable-output 2>&1 | %FileCheck %s +// RUN: not %target-swift-frontend(mock-sdk: -sdk %/S/../ModuleInterface/Inputs/BadStdlib.sdk -module-cache-path %/t/module-cache -resource-dir %/S/../ModuleInterface/Inputs/BadStdlib.sdk) -c -primary-file %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -module-name parseable_output_early -frontend-parseable-output 2>&1 | %FileCheck %s // CHECK: {{[1-9][0-9]*}} // CHECK-NEXT: { diff --git a/test/Frontend/parseable_output_emit_module.swift b/test/Frontend/parseable_output_emit_module.swift new file mode 100644 index 0000000000000..b943666e7e811 --- /dev/null +++ b/test/Frontend/parseable_output_emit_module.swift @@ -0,0 +1,56 @@ +// RUN: %target-swift-frontend -emit-module %s %S/Inputs/filelist-other.swift -module-name parseable_output_emit_module -empty-abi-descriptor -emit-abi-descriptor-path %t.abi.json -emit-module -emit-module-path %t.swiftmodule -serialize-diagnostics -serialize-diagnostics-path %t.dia -frontend-parseable-output 2>&1 | %FileCheck %s + +// CHECK: {{[1-9][0-9]*}} +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "began", +// CHECK-NEXT: "name": "emit-module", +// CHECK-NEXT: "command": "{{.*[\\/]}}swift-frontend{{(\.exe)?}}{{.*}} {{.*}} -emit-module {{.*[\\/]}}parseable_output_emit_module.swift {{.*[\\/]}}filelist-other.swift -module-name parseable_output_emit_module -empty-abi-descriptor -emit-abi-descriptor-path {{.*[\\/]}}parseable_output_emit_module.swift.tmp.abi.json -emit-module -emit-module-path {{.*[\\/]}}parseable_output_emit_module.swift.tmp.swiftmodule -serialize-diagnostics -serialize-diagnostics-path {{.*[\\/]}}parseable_output_emit_module.swift.tmp.dia -frontend-parseable-output", +// CHECK-NEXT: "command_executable": "{{.*[\\/]}}swift{{(-frontend|c)?(\.exe)?}}", +// CHECK-NEXT: "command_arguments": [ +// CHECK: "{{.*[\\/]}}parseable_output_emit_module.swift", +// CHECK-NEXT: "{{.*[\\/]}}filelist-other.swift", +// CHECK-NEXT: "-module-name", +// CHECK-NEXT: "parseable_output_emit_module", +// CHECK-NEXT: "-empty-abi-descriptor", +// CHECK-NEXT: "-emit-abi-descriptor-path", +// CHECK-NEXT: "{{.*[\\/]}}parseable_output_emit_module.swift.tmp.abi.json", +// CHECK-NEXT: "-emit-module", +// CHECK-NEXT: "-emit-module-path", +// CHECK-NEXT: "{{.*[\\/]}}parseable_output_emit_module.swift.tmp.swiftmodule", +// CHECK-NEXT: "-serialize-diagnostics", +// CHECK-NEXT: "-serialize-diagnostics-path" +// CHECK-NEXT: "{{.*[\\/]}}parseable_output_emit_module.swift.tmp.dia", +// CHECK-NEXT: "-frontend-parseable-output" +// CHECK-NEXT: ], +// CHECK-NEXT: "inputs": [ +// CHECK-NEXT: "{{.*[\\/]}}parseable_output_emit_module.swift" +// CHECK: "outputs": [ +// CHECK-NEXT: { +// CHECK-NEXT: "type": "swiftmodule", +// CHECK-NEXT: "path": "{{.*[\\/]}}parseable_output_emit_module.swift.tmp.swiftmodule" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "type": "diagnostics", +// CHECK-NEXT: "path": "{{.*[\\/]}}parseable_output_emit_module.swift.tmp.dia" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "type": "abi-baseline-json", +// CHECK-NEXT: "path": "{{.*[\\/]}}parseable_output_emit_module.swift.tmp.abi.json" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "pid": [[PID:[0-9]*]] +// CHECK-NEXT: "process": { +// CHECK-NEXT: "real_pid": [[PID]] +// CHECK-NEXT: } +// CHECK-NEXT: } + +// CHECK-NEXT: {{[1-9][0-9]*}} +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "finished", +// CHECK-NEXT: "name": "emit-module", +// CHECK-NEXT: "pid": [[PID]], +// CHECK-NEXT: "process": { +// CHECK-NEXT: "real_pid": [[PID]] +// CHECK-NEXT: }, +// CHECK-NEXT: "exit-status": 0 +// CHECK-NEXT: } diff --git a/test/Frontend/parseable_output_error.swift b/test/Frontend/parseable_output_error.swift index da1828be5b290..933bc6abc61ce 100644 --- a/test/Frontend/parseable_output_error.swift +++ b/test/Frontend/parseable_output_error.swift @@ -1,6 +1,6 @@ -// RUN: not %target-swift-frontend -primary-file %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s +// RUN: not %target-swift-frontend -c -primary-file %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s // Check without primary files (WMO): -// RUN: not %target-swift-frontend %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s +// RUN: not %target-swift-frontend -c %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s func foo() { return 11; diff --git a/test/Frontend/parseable_output_unknown_file_type.swift b/test/Frontend/parseable_output_unknown_file_type.swift index 3cc4b37a0cb7d..ce82be82117c2 100644 --- a/test/Frontend/parseable_output_unknown_file_type.swift +++ b/test/Frontend/parseable_output_unknown_file_type.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -primary-file %s %S/Inputs/filelist-other.swift -o %t.out -module-name parseable_output -empty-abi-descriptor -emit-abi-descriptor-path %t.abi.weird_file_extension -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s +// RUN: %target-swift-frontend -c -primary-file %s %S/Inputs/filelist-other.swift -o %t.out -module-name parseable_output -empty-abi-descriptor -emit-abi-descriptor-path %t.abi.weird_file_extension -emit-module -emit-module-path %t.swiftmodule -frontend-parseable-output 2>&1 | %FileCheck %s // CHECK: {{[1-9][0-9]*}} // CHECK-NEXT: { diff --git a/test/Generics/inverse_conditional_conformance_restriction.swift b/test/Generics/inverse_conditional_conformance_restriction.swift index f1face72c74bb..f44b00a6a8746 100644 --- a/test/Generics/inverse_conditional_conformance_restriction.swift +++ b/test/Generics/inverse_conditional_conformance_restriction.swift @@ -7,12 +7,15 @@ protocol Q {} class DoggoClass {} struct Blah: ~Copyable, ~Escapable {} -extension Blah: Copyable {} // expected-error {{conditional conformance to suppressible protocol 'Copyable' cannot depend on 'T: Escapable'}} -extension Blah: Escapable {} // expected-error {{conditional conformance to suppressible protocol 'Escapable' cannot depend on 'T: Copyable'}} +extension Blah: Copyable where T: Copyable & Escapable {} +// expected-error@-1 {{conditional conformance to suppressible protocol 'Copyable' cannot depend on 'T: Escapable'}} -struct Yuck: ~Copyable, ~Escapable {} -extension Yuck: Copyable where T: ~Escapable {} -extension Yuck: Escapable where T: ~Copyable {} +extension Blah: Escapable where T: Copyable, T: Escapable {} +// expected-error@-1 {{conditional conformance to suppressible protocol 'Escapable' cannot depend on 'T: Copyable'}} + +struct Fixed: ~Copyable, ~Escapable {} +extension Fixed: Copyable where T: Copyable {} +extension Fixed: Escapable where T: Escapable {} struct TryConformance: ~Copyable {} extension TryConformance: Copyable diff --git a/test/Generics/inverse_generics.swift b/test/Generics/inverse_generics.swift index c58d065e067d8..e38b09a7b1263 100644 --- a/test/Generics/inverse_generics.swift +++ b/test/Generics/inverse_generics.swift @@ -2,11 +2,26 @@ // RUN: -enable-experimental-feature NonescapableTypes \ // RUN: -enable-experimental-feature SuppressedAssociatedTypes +// expected-note@+1 {{'T' has '~Copyable' constraint preventing implicit 'Copyable' conformance}} +struct AttemptImplicitConditionalConformance: ~Copyable { + var t: T // expected-error {{stored property 't' of 'Copyable'-conforming generic struct 'AttemptImplicitConditionalConformance' has non-Copyable type 'T'}} +} +extension AttemptImplicitConditionalConformance: Copyable {} +// expected-error@-1 {{generic struct 'AttemptImplicitConditionalConformance' required to be 'Copyable' but is marked with '~Copyable'}} + +enum Hello: ~Escapable & ~Copyable {} +extension Hello: Escapable {} // expected-error {{generic enum 'Hello' required to be 'Escapable' but is marked with '~Escapable'}} +extension Hello: Copyable {} // expected-error {{generic enum 'Hello' required to be 'Copyable' but is marked with '~Copyable'}} + +enum HelloExplicitlyFixed: Escapable, Copyable {} +struct NoInverseBecauseNoDefault: ~Copyable {} +extension NoInverseBecauseNoDefault: Copyable where T: Copyable, T: ~Escapable {} +// expected-error@-1 {{cannot suppress '~Escapable' on generic parameter 'T' defined in outer scope}} // Check support for explicit conditional conformance public struct ExplicitCond: ~Copyable {} -extension ExplicitCond: Copyable {} +extension ExplicitCond: Copyable where T: Copyable {} // expected-note@-1 {{requirement from conditional conformance}} // expected-note@-2 {{requirement from conditional conformance of 'ExplicitCondAlias' (aka 'ExplicitCond') to 'Copyable'}} @@ -80,7 +95,7 @@ struct ConditionalContainment: ~Copyable { var y: NC // expected-error {{stored property 'y' of 'Copyable'-conforming generic struct 'ConditionalContainment' has non-Copyable type 'NC'}} } -extension ConditionalContainment: Copyable {} +extension ConditionalContainment: Copyable where T: Copyable {} func chk(_ T: RequireCopyable>) {} @@ -126,7 +141,7 @@ enum Maybe: ~Copyable { deinit {} // expected-error {{deinitializer cannot be declared in generic enum 'Maybe' that conforms to 'Copyable'}} } -extension Maybe: Copyable {} +extension Maybe: Copyable where Wrapped: Copyable {} // expected-note@+4{{requirement specified as 'NC' : 'Copyable'}} // expected-note@+3{{requirement from conditional conformance of 'Maybe' to 'Copyable'}} @@ -173,11 +188,11 @@ class NiceTry: ~Copyable, Copyable {} // expected-error {{classes cannot be '~Co struct Extendo: ~Copyable {} -extension Extendo: Copyable, ~Copyable {} // expected-error {{cannot suppress '~Copyable' in extension}} +extension Extendo: Copyable, ~Copyable {} // expected-error {{cannot suppress 'Copyable' in extension}} // expected-error@-1 {{struct 'Extendo' required to be 'Copyable' but is marked with '~Copyable'}} enum EnumExtendo {} -extension EnumExtendo: ~Copyable {} // expected-error {{cannot suppress '~Copyable' in extension}} +extension EnumExtendo: ~Copyable {} // expected-error {{cannot suppress 'Copyable' in extension}} extension NeedsCopyable where Self: ~Copyable {} // expected-error@-1 {{'Self' required to be 'Copyable' but is marked with '~Copyable'}} @@ -265,7 +280,7 @@ enum MaybeEscapes: ~Escapable { // expected-note {{generic enum ' case none } -extension MaybeEscapes: Escapable {} +extension MaybeEscapes: Escapable where T: Escapable {} struct Escapes { // expected-note {{consider adding '~Escapable' to struct 'Escapes'}} let t: MaybeEscapes // expected-error {{stored property 't' of 'Escapable'-conforming struct 'Escapes' has non-Escapable type 'MaybeEscapes'}} diff --git a/test/Generics/inverse_generics_stdlib.swift b/test/Generics/inverse_generics_stdlib.swift index 3eea8b8f7928c..200df47bd344a 100644 --- a/test/Generics/inverse_generics_stdlib.swift +++ b/test/Generics/inverse_generics_stdlib.swift @@ -21,7 +21,7 @@ public enum Optional: ~Copyable { case none } -extension Optional: Copyable {} +extension Optional: Copyable where T: Copyable {} public func wrapping(_ t: consuming T) -> T? { return .some(t) diff --git a/test/IDE/complete_rdar127844278.swift b/test/IDE/complete_rdar127844278.swift new file mode 100644 index 0000000000000..05740b2932452 --- /dev/null +++ b/test/IDE/complete_rdar127844278.swift @@ -0,0 +1,35 @@ +// RUN: %batch-code-completion + +// rdar://127844278 - Make sure we don't attempt to favor one buildExpression +// call over the other when there's a child code completion. + +protocol P {} +protocol Q: P {} + +struct S: P { + private init() {} +} + +extension S where T == () { + init(a: Void) {} +} +extension S: Q where T == String { + init(b: String) {} +} + +@resultBuilder struct Builder { + static func buildExpression(_ x: T) -> T { x } + static func buildExpression(_ x: T) -> T { x } + + static func buildBlock(_ x: T) -> some P { x } + static func buildBlock(_ x: T) -> some P { x } +} + +func foo(@Builder _: () -> T) where T: P {} +func foo(@Builder _: () -> T) where T: Q {} + +foo { + S(#^COMPLETE^#) +} +// COMPLETE-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#a: Void#}[')'][#S<()>#]; name=a: +// COMPLETE-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#b: String#}[')'][#S#]; name=b: diff --git a/test/IDE/complete_rdar129024996.swift b/test/IDE/complete_rdar129024996.swift new file mode 100644 index 0000000000000..d3f15c9b8539a --- /dev/null +++ b/test/IDE/complete_rdar129024996.swift @@ -0,0 +1,49 @@ +// RUN: %batch-code-completion + +protocol P {} +protocol Q : P {} + +// Applicable, S conforms to Q. +struct S : Q {} +extension P where Self == S { + static func foo() -> S { S() } +} + +// Not applicable, Q does not inherit from K. +protocol K {} +extension S : K {} +extension K where Self == S { + static func bar() -> S { S() } +} + +// Make sure we don't try and complete for this type's init. +struct R { + init(a: Int) {} +} + +// Not applicable, A does not conform to Q. +struct A: P {} +extension P where Self == A { + static func baz() -> A { A() } +} + +struct B: P {} +extension B: Q where T: Q {} + +// Applicable, B conforms to Q. +extension P where Self == B { + static func qux() -> Self { .init() } +} + +// Not applicable, B does not conform to Q. +extension P where Self == B { + static func flim() -> Self { .init() } +} + +@attached(peer) macro R(_: any Q) = #externalMacro(module: "", type: "") + +@R(.#^COMPLETE^#) +func bar() {} +// COMPLETE: Begin completions, 2 items +// COMPLETE-DAG: Decl[StaticMethod]/Super/TypeRelation[Convertible]: foo()[#S#]; name=foo() +// COMPLETE-DAG: Decl[StaticMethod]/Super/TypeRelation[Convertible]: qux()[#B#]; name=qux() diff --git a/test/IRGen/async/builtins.sil b/test/IRGen/async/builtins.sil index 53e3643c336f3..57c9eb38ba337 100644 --- a/test/IRGen/async/builtins.sil +++ b/test/IRGen/async/builtins.sil @@ -8,6 +8,7 @@ sil_stage canonical import Builtin import Swift +import _Concurrency // CHECK-LABEL: define hidden swift{{(tail)?}}cc void @get_task(ptr swiftasync %0) sil hidden [ossa] @get_task : $@async @convention(thin) () -> @owned Builtin.NativeObject { @@ -37,7 +38,8 @@ bb0(%flags : $Int, %taskFunction: @owned $@Sendable @async @callee_guaranteed @s %optSerialExecutor = enum $Optional, #Optional.none %optTaskGroup = enum $Optional, #Optional.none %optTaskExecutor = enum $Optional, #Optional.none - %20 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + %optTaskExecutorOwned = enum $Optional, #Optional.none + %20 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %optTaskExecutorOwned : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) destroy_value %20 : $(Builtin.NativeObject, Builtin.RawPointer) %21 = tuple () return %21 : $() @@ -62,7 +64,8 @@ bb0(%flags : $Int, %serialExecutor : $Builtin.Executor, %taskFunction: @owned $@ %optSerialExecutor = enum $Optional, #Optional.some, %serialExecutor : $Builtin.Executor %optTaskGroup = enum $Optional, #Optional.none %optTaskExecutor = enum $Optional, #Optional.none - %20 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + %optTaskExecutorOwned = enum $Optional, #Optional.none + %20 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %optTaskExecutorOwned : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) destroy_value %20 : $(Builtin.NativeObject, Builtin.RawPointer) %21 = tuple () return %21 : $() @@ -84,7 +87,8 @@ bb0(%taskGroup : $Builtin.RawPointer, %taskFunction : $@Sendable @async @callee_ %optSerialExecutor = enum $Optional, #Optional.none %optTaskGroup = enum $Optional, #Optional.some!enumelt, %taskGroup : $Builtin.RawPointer %optTaskExecutor = enum $Optional, #Optional.none - %9 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + %optTaskExecutorOwned = enum $Optional, #Optional.none + %9 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %optTaskExecutorOwned : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) %10 = tuple_extract %9 : $(Builtin.NativeObject, Builtin.RawPointer), 0 strong_release %10 : $Builtin.NativeObject %12 = tuple () @@ -113,7 +117,8 @@ bb0(%flags : $Int, %optTaskGroup : $Optional, %taskFunction: %optSerialExecutor = enum $Optional, #Optional.none %optTaskExecutor = enum $Optional, #Optional.none - %20 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + %optTaskExecutorOwned = enum $Optional, #Optional.none + %20 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %optTaskExecutorOwned : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) destroy_value %20 : $(Builtin.NativeObject, Builtin.RawPointer) %result = tuple () return %result : $() @@ -125,9 +130,10 @@ bb0(%taskGroup : $Builtin.RawPointer, %taskFunction : $@Sendable @async @callee_ %optSerialExecutor = enum $Optional, #Optional.none %optTaskGroup = enum $Optional, #Optional.some!enumelt, %taskGroup : $Builtin.RawPointer %optTaskExecutor = enum $Optional, #Optional.none + %optTaskExecutorOwned = enum $Optional, #Optional.none // CHECK-NOT: br i1 // CHECK: call swift{{(tail)?}}cc %swift.async_task_and_context @swift_task_create( - %9 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed () -> @error Error) : $(Builtin.NativeObject, Builtin.RawPointer) + %9 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %optTaskExecutorOwned : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed () -> @error Error) : $(Builtin.NativeObject, Builtin.RawPointer) %10 = tuple_extract %9 : $(Builtin.NativeObject, Builtin.RawPointer), 0 strong_release %10 : $Builtin.NativeObject %12 = tuple () @@ -140,6 +146,7 @@ bb0(%taskGroup : $Builtin.RawPointer, %taskExecutor : $Builtin.Executor, %taskFu %optSerialExecutor = enum $Optional, #Optional.none %optTaskGroup = enum $Optional, #Optional.some!enumelt, %taskGroup : $Builtin.RawPointer %optTaskExecutor = enum $Optional, #Optional.some!enumelt, %taskExecutor : $Builtin.Executor + %optTaskExecutorOwned = enum $Optional, #Optional.none // CHECK: [[GROUP_RECORD:%.*]] = alloca %swift.task_group_task_option // CHECK: [[EXECUTOR_RECORD:%.*]] = alloca %swift.task_executor_task_option // CHECK-NOT: br i1 @@ -164,7 +171,7 @@ bb0(%taskGroup : $Builtin.RawPointer, %taskExecutor : $Builtin.Executor, %taskFu // CHECK: store [[INT]] %2, ptr [[EXECUTOR_IMPL_GEP]], align // CHECK: call swift{{(tail)?}}cc %swift.async_task_and_context @swift_task_create([[INT]] %5, ptr [[EXECUTOR_RECORD]] - %9 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor: $Optional, %taskFunction : $@Sendable @async @callee_guaranteed () -> @error Error) : $(Builtin.NativeObject, Builtin.RawPointer) + %9 = builtin "createAsyncTask"(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor: $Optional, %optTaskExecutorOwned : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed () -> @error Error) : $(Builtin.NativeObject, Builtin.RawPointer) %10 = tuple_extract %9 : $(Builtin.NativeObject, Builtin.RawPointer), 0 strong_release %10 : $Builtin.NativeObject %12 = tuple () @@ -177,8 +184,9 @@ bb0(%flags : $Int, %taskGroup : $Builtin.RawPointer, %taskFunction: @owned $@Sen %optSerialExecutor = enum $Optional, #Optional.none %optTaskGroup = enum $Optional, #Optional.some!enumelt, %taskGroup : $Builtin.RawPointer %optTaskExecutor = enum $Optional, #Optional.none + %optTaskExecutorOwned = enum $Optional, #Optional.none // CHECK: [[NEW_TASK_AND_CONTEXT:%.*]] = call swift{{(tail)?}}cc %swift.async_task_and_context @swift_task_create( - %20 = builtin "createAsyncTask"<()>(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for <()>) : $(Builtin.NativeObject, Builtin.RawPointer) + %20 = builtin "createAsyncTask"<()>(%flags : $Int, %optSerialExecutor : $Optional, %optTaskGroup : $Optional, %optTaskExecutor : $Optional, %optTaskExecutorOwned : $Optional, %taskFunction : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for <()>) : $(Builtin.NativeObject, Builtin.RawPointer) destroy_value %20 : $(Builtin.NativeObject, Builtin.RawPointer) %21 = tuple () return %21 : $() diff --git a/test/IRGen/package_bypass_resilience_global_accessor.swift b/test/IRGen/package_bypass_resilience_global_accessor.swift deleted file mode 100644 index d95491c51edcc..0000000000000 --- a/test/IRGen/package_bypass_resilience_global_accessor.swift +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: %empty-directory(%t) - -// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-sil %s | %FileCheck %s --check-prefix=CHECK-SIL -// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-sil %s -enable-library-evolution | %FileCheck %s --check-prefix=CHECK-SIL-HID -// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-sil %s -enable-library-evolution -Xfrontend -experimental-allow-non-resilient-access | %FileCheck %s --check-prefix=CHECK-SIL -// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s | %FileCheck %s --check-prefix=CHECK-IR -// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution | %FileCheck %s --check-prefix=CHECK-IR-HID -// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution -Xfrontend -experimental-allow-non-resilient-access | %FileCheck %s --check-prefix=CHECK-IR - -public struct S { - public static var x = "hello world" -} - -// S.x.unsafeMutableAddressor -// CHECK-SIL: sil [global_init] @$s4File1SV1xSSvau : $@convention(thin) () -> Builtin.RawPointer { -// S.x.unsafeMutableAddressor -// CHECK-SIL-HID: sil hidden [global_init] @$s4File1SV1xSSvau : $@convention(thin) () -> Builtin.RawPointer { - -// CHECK-IR: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @"$s4File1SV1xSSvau"() -// CHECK-IR-HID: define hidden swiftcc ptr @"$s4File1SV1xSSvau"() - diff --git a/test/IRGen/package_global_accessor.swift b/test/IRGen/package_global_accessor.swift new file mode 100644 index 0000000000000..e7402ae800153 --- /dev/null +++ b/test/IRGen/package_global_accessor.swift @@ -0,0 +1,13 @@ + // RUN: %empty-directory(%t) + +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s | %FileCheck %s --check-prefix=CHECK-IR-NONRES +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution | %FileCheck %s --check-prefix=CHECK-IR-RES +// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution -Xfrontend -experimental-allow-non-resilient-access -Xfrontend -experimental-package-cmo | %FileCheck %s --check-prefix=CHECK-IR-RES + +public struct S { + public static var x = "hello world" +} + +// CHECK-IR-NONRES: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @"$s4File1SV1xSSvau"() +// CHECK-IR-RES: define hidden swiftcc ptr @"$s4File1SV1xSSvau"() + diff --git a/test/IRGen/temporary_allocation/async.swift b/test/IRGen/temporary_allocation/async.swift index d9453ff195236..be60d72733d43 100644 --- a/test/IRGen/temporary_allocation/async.swift +++ b/test/IRGen/temporary_allocation/async.swift @@ -9,5 +9,5 @@ func f() async { blackHole(buffer.baseAddress) } } -// CHECK: alloca [123 x i8], align 1 + // CHECK-NOT: swift_task_alloc diff --git a/test/IRGen/temporary_allocation/codegen.swift b/test/IRGen/temporary_allocation/codegen.swift index 815ff089bcee2..ba2c430279a08 100644 --- a/test/IRGen/temporary_allocation/codegen.swift +++ b/test/IRGen/temporary_allocation/codegen.swift @@ -10,10 +10,20 @@ do { blackHole(ptr) ptr.deallocate() } -// CHECK: ptrtoint ptr {{.*}} to [[WORD:i[0-9]+]] // MARK: Trivial Cases +// CHECK: [[ONE_BYTE_PTR_RAW:%temp_alloc[0-9]*]] = alloca i8, align 1 +// CHECK: [[FIVE_BYTE_PTR_RAW:%temp_alloc[0-9]*]] = alloca [5 x i8], align 1 +// CHECK: [[ONE_KB_PTR_RAW:%temp_alloc[0-9]*]] = alloca [1024 x i8], align 8 +// CHECK: [[ONE_KB_RAND_PTR_RAW:%temp_alloc[0-9]*]] = alloca [1024 x i8], align 16 +// CHECK: [[INT_PTR_RAW:%temp_alloc[0-9]*]] = alloca [16 x i8], align 4 +// CHECK: [[INT_PTR_RAW2:%temp_alloc[0-9]*]] = alloca [16 x i8], align 4 +// CHECK: [[VOID_PTR_RAW:%temp_alloc[0-9]*]] = alloca [2 x i8], align 1 + +// CHECK: ptrtoint ptr {{.*}} to [[WORD:i[0-9]+]] + + withUnsafeTemporaryAllocation(byteCount: 0, alignment: 1) { buffer in blackHole(buffer.baseAddress) } @@ -24,21 +34,18 @@ withUnsafeTemporaryAllocation(byteCount: 0, alignment: 1) { buffer in withUnsafeTemporaryAllocation(byteCount: 1, alignment: 1) { buffer in blackHole(buffer.baseAddress) } -// CHECK: [[ONE_BYTE_PTR_RAW:%temp_alloc[0-9]*]] = alloca i8, align 1 // CHECK: [[ONE_BYTE_PTR:%[0-9]+]] = ptrtoint ptr [[ONE_BYTE_PTR_RAW]] to [[WORD]] // CHECK: call swiftcc void @blackHole([[WORD]] [[ONE_BYTE_PTR]]) withUnsafeTemporaryAllocation(byteCount: 5, alignment: 1) { buffer in blackHole(buffer.baseAddress) } -// CHECK: [[FIVE_BYTE_PTR_RAW:%temp_alloc[0-9]*]] = alloca [5 x i8], align 1 // CHECK: [[FIVE_BYTE_PTR:%[0-9]+]] = ptrtoint ptr [[FIVE_BYTE_PTR_RAW]] to [[WORD]] // CHECK: call swiftcc void @blackHole([[WORD]] [[FIVE_BYTE_PTR]]) withUnsafeTemporaryAllocation(byteCount: 1024, alignment: 8) { buffer in blackHole(buffer.baseAddress) } -// CHECK: [[ONE_KB_PTR_RAW:%temp_alloc[0-9]*]] = alloca [1024 x i8], align 8 // CHECK: [[ONE_KB_PTR:%[0-9]+]] = ptrtoint ptr [[ONE_KB_PTR_RAW]] to [[WORD]] // CHECK: call swiftcc void @blackHole([[WORD]] [[ONE_KB_PTR]]) @@ -47,7 +54,6 @@ withUnsafeTemporaryAllocation(byteCount: 1024, alignment: 8) { buffer in withUnsafeTemporaryAllocation(byteCount: 1024, alignment: Int.random(in: 0 ..< 16)) { buffer in blackHole(buffer.baseAddress) } -// CHECK: [[ONE_KB_RAND_PTR_RAW:%temp_alloc[0-9]*]] = alloca [1024 x i8], align 16 // CHECK: [[ONE_KB_RAND_PTR:%[0-9]+]] = ptrtoint ptr [[ONE_KB_RAND_PTR_RAW]] to [[WORD]] // CHECK: call swiftcc void @blackHole([[WORD]] [[ONE_KB_RAND_PTR]]) @@ -56,21 +62,18 @@ withUnsafeTemporaryAllocation(byteCount: 1024, alignment: Int.random(in: 0 ..< 1 withUnsafeTemporaryAllocation(of: Int32.self, capacity: 4) { buffer in blackHole(buffer.baseAddress) } -// CHECK: [[INT_PTR_RAW:%temp_alloc[0-9]*]] = alloca [16 x i8], align 4 // CHECK: [[INT_PTR:%[0-9]+]] = ptrtoint ptr [[INT_PTR_RAW]] to [[WORD]] // CHECK: call swiftcc void @blackHole([[WORD]] [[INT_PTR]]) _withUnprotectedUnsafeTemporaryAllocation(of: Int32.self, capacity: 4) { buffer in blackHole(buffer.baseAddress) } -// CHECK: [[INT_PTR_RAW:%temp_alloc[0-9]*]] = alloca [16 x i8], align 4 -// CHECK: [[INT_PTR:%[0-9]+]] = ptrtoint ptr [[INT_PTR_RAW]] to [[WORD]] +// CHECK: [[INT_PTR:%[0-9]+]] = ptrtoint ptr [[INT_PTR_RAW2]] to [[WORD]] // CHECK: call swiftcc void @blackHole([[WORD]] [[INT_PTR]]) withUnsafeTemporaryAllocation(of: Void.self, capacity: 2) { buffer in blackHole(buffer.baseAddress) } -// CHECK: [[VOID_PTR_RAW:%temp_alloc[0-9]*]] = alloca [2 x i8], align 1 // CHECK: [[VOID_PTR:%[0-9]+]] = ptrtoint ptr [[VOID_PTR_RAW]] to [[WORD]] // CHECK: call swiftcc void @blackHole([[WORD]] [[VOID_PTR]]) diff --git a/test/IRGen/temporary_allocation/codegen_very_large_allocation.swift b/test/IRGen/temporary_allocation/codegen_very_large_allocation.swift index 335355724ecce..0773089e36cf7 100644 --- a/test/IRGen/temporary_allocation/codegen_very_large_allocation.swift +++ b/test/IRGen/temporary_allocation/codegen_very_large_allocation.swift @@ -24,7 +24,7 @@ withUnsafeTemporaryAllocation(byteCount: 0x0FFF_FFFF, alignment: 1) { buffer in // CHECK-LARGE-HEAP-ALLOC-NEXT: {{(tail )?}}call void @swift_slowDealloc(ptr [[HEAP_PTR_RAW]], [[WORD]] -1, [[WORD]] -1) // CHECK-LARGE-STACK-ALLOC: [[STACK_PTR_RAW:%temp_alloc[0-9]*]] = alloca [268435455 x i8], align 1 -// CHECK-LARGE-STACK-ALLOC-NEXT: [[STACK_PTR:%[0-9]+]] = ptrtoint ptr [[STACK_PTR_RAW]] to [[WORD]] +// CHECK-LARGE-STACK-ALLOC: [[STACK_PTR:%[0-9]+]] = ptrtoint ptr [[STACK_PTR_RAW]] to [[WORD]] // CHECK-LARGE-STACK-ALLOC-NEXT: call swiftcc void @blackHole([[WORD]] [[STACK_PTR]]) // CHECK-LARGE-ALLOC-DAG: [[IS_SAFE:%[0-9]+]] = {{(tail )?}}call {{(zeroext )?}}i1 @swift_stdlib_isStackAllocationSafe([[WORD]] 268435455, [[WORD]] 1) diff --git a/test/Index/enum_case_with_invalid_associated_type.swift b/test/Index/enum_case_with_invalid_associated_type.swift new file mode 100644 index 0000000000000..c7921e1fd4598 --- /dev/null +++ b/test/Index/enum_case_with_invalid_associated_type.swift @@ -0,0 +1,7 @@ +enum MyEnum { +// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s + case test(artifactID: String, hostTriple: Triple) +// CHECK: enumerator/Swift | test(artifactID:hostTriple:) +// CHECK: param/Swift | artifactID +// CHECK: param/Swift | hostTriple +} diff --git a/test/Index/rdar129065620.swift b/test/Index/rdar129065620.swift new file mode 100644 index 0000000000000..d3504b9feb592 --- /dev/null +++ b/test/Index/rdar129065620.swift @@ -0,0 +1,12 @@ +// RUN: %empty-directory(%t) +// RUN: not %target-swift-frontend -typecheck %s -index-store-path %t + +// rdar://129065620 - Make sure we don't crash when verifying the mangling. +enum Foo { + case bar(id: UInt32) + case bar(id: UInt32) +} + +struct S { + subscript(x: Invalid) -> Invalid {} +} diff --git a/test/Inputs/Swiftskell.swift b/test/Inputs/Swiftskell.swift index 9e4b96bf3a8bc..981d130c2a019 100644 --- a/test/Inputs/Swiftskell.swift +++ b/test/Inputs/Swiftskell.swift @@ -36,7 +36,7 @@ public enum Either: ~Copyable { case failure(Failure) } -extension Either: Copyable {} +extension Either: Copyable where Success: Copyable {} extension Either where Failure == Swift.Error { public init(catching body: () throws -> Success) { @@ -77,7 +77,7 @@ public enum Maybe: ~Copyable { case just(Wrapped) case nothing } -extension Maybe: Copyable {} +extension Maybe: Copyable where Wrapped: Copyable {} extension Maybe: Show where Wrapped: Show & ~Copyable { public borrowing func show() -> String { diff --git a/test/Interop/Cxx/class/Inputs/protocol-conformance.h b/test/Interop/Cxx/class/Inputs/protocol-conformance.h index aa504d1d9e36f..bc95f2a058bf8 100644 --- a/test/Interop/Cxx/class/Inputs/protocol-conformance.h +++ b/test/Interop/Cxx/class/Inputs/protocol-conformance.h @@ -72,4 +72,8 @@ struct HasVirtualMethod { virtual int return42() { return 42; } }; +struct HasStaticOperatorCall { + static int operator()(int x) { return x * 2; } +}; + #endif // TEST_INTEROP_CXX_CLASS_INPUTS_PROTOCOL_CONFORMANCE_H diff --git a/test/Interop/Cxx/class/move-only/inherited-field-access-silgen.swift b/test/Interop/Cxx/class/move-only/inherited-field-access-silgen.swift index c702bb9a80213..d69dbd39fe9d6 100644 --- a/test/Interop/Cxx/class/move-only/inherited-field-access-silgen.swift +++ b/test/Interop/Cxx/class/move-only/inherited-field-access-silgen.swift @@ -1,8 +1,6 @@ // RUN: %target-swift-emit-sil -I %S/Inputs -cxx-interoperability-mode=swift-6 %s -validate-tbd-against-ir=none | %FileCheck %s // RUN: %target-swift-emit-sil -I %S/Inputs -cxx-interoperability-mode=upcoming-swift %s -validate-tbd-against-ir=none | %FileCheck %s -// REQUIRES: rdar128424443 - import MoveOnlyCxxValueType func testGetX() -> CInt { @@ -19,10 +17,17 @@ func testSetX(_ x: CInt) { testSetX(2) -// CHECK: sil shared [transparent] @$sSo024NonCopyableHolderDerivedD0V1xSo0aB0Vvlu : $@convention(method) (@in_guaranteed NonCopyableHolderDerivedDerived) -> UnsafePointer -// CHECK: {{.*}}(%[[SELF_VAL:.*]] : $*NonCopyableHolderDerivedDerived): +// Beware: this test exhibits a subtle difference between open source Clang and AppleClang: +// AppleClang runs in an ABI compatibility mode with Clang <= 4, which uses a +// different criteria to determine whether a C++ type can be passed in +// registers. This causes Swift to assume that NonCopyableHolderDerivedDerived +// can be both loadable or address-only, depending on the compiler flavor used. +// (rdar://128424443) + +// CHECK: sil shared [transparent] @$sSo024NonCopyableHolderDerivedD0V1xSo0aB0Vvlu : $@convention(method) (@{{(in_)?}}guaranteed NonCopyableHolderDerivedDerived) -> UnsafePointer +// CHECK: {{.*}}(%[[SELF_VAL:.*]] : ${{(\*)?}}NonCopyableHolderDerivedDerived): // CHECK: function_ref @{{.*}}__synthesizedBaseCall___synthesizedBaseGetterAccessor{{.*}} : $@convention(cxx_method) (@in_guaranteed NonCopyableHolderDerivedDerived) -> UnsafePointer -// CHECK-NEXT: apply %{{.*}}(%[[SELF_VAL]]) +// CHECK-NEXT: apply %{{.*}} // CHECK: sil shared [transparent] @$sSo024NonCopyableHolderDerivedD0V1xSo0aB0Vvau : $@convention(method) (@inout NonCopyableHolderDerivedDerived) -> UnsafeMutablePointer // CHECK: function_ref @{{.*}}__synthesizedBaseCall___synthesizedBaseSetterAccessor{{.*}} : $@convention(cxx_method) (@inout NonCopyableHolderDerivedDerived) -> UnsafeMutablePointer diff --git a/test/Interop/Cxx/class/protocol-conformance-typechecker.swift b/test/Interop/Cxx/class/protocol-conformance-typechecker.swift index 4b9754b6be0c6..3fb6c0bab719b 100644 --- a/test/Interop/Cxx/class/protocol-conformance-typechecker.swift +++ b/test/Interop/Cxx/class/protocol-conformance-typechecker.swift @@ -49,3 +49,9 @@ protocol HasOperatorPlusEqualProtocol { } extension HasOperatorPlusEqualInt : HasOperatorPlusEqualProtocol {} + +protocol HasOperatorCall { + func callAsFunction(_ x: Int32) -> Int32 +} + +extension HasStaticOperatorCall : HasOperatorCall {} \ No newline at end of file diff --git a/test/Interop/Cxx/foreign-reference/reference-counted.swift b/test/Interop/Cxx/foreign-reference/reference-counted.swift index 7a5127a7eb250..0555fa39c9816 100644 --- a/test/Interop/Cxx/foreign-reference/reference-counted.swift +++ b/test/Interop/Cxx/foreign-reference/reference-counted.swift @@ -4,8 +4,9 @@ // REQUIRES: executable_test // XFAIL: OS=windows-msvc -// Temporarily disable on arm64e (rdar://128681137) -// UNSUPPORTED: CPU=arm64e +// Temporarily disable when running with an older runtime (rdar://128681137) +// UNSUPPORTED: use_os_stdlib +// UNSUPPORTED: back_deployment_runtime import StdlibUnittest import ReferenceCounted diff --git a/test/Interop/Cxx/operators/Inputs/member-inline.h b/test/Interop/Cxx/operators/Inputs/member-inline.h index c168de6a5bd89..b7f949ac089c8 100644 --- a/test/Interop/Cxx/operators/Inputs/member-inline.h +++ b/test/Interop/Cxx/operators/Inputs/member-inline.h @@ -477,4 +477,19 @@ struct HasOperatorCallWithDefaultArg { int operator()(int x = 0) const { return value + x; } }; +class HasStaticOperatorCallBase { +public: + static int operator()(int x) { return x + 42; } +}; + +class HasStaticOperatorCallDerived : public HasStaticOperatorCallBase {}; + +class HasStaticOperatorCallWithConstOperator { +public: + inline int operator()(int x, int y) const { return x + y; } + static int operator()(int x) { + return x - 1; + } +}; + #endif diff --git a/test/Interop/Cxx/operators/member-inline-module-interface.swift b/test/Interop/Cxx/operators/member-inline-module-interface.swift index e9a40f365a691..d5d454def2ffc 100644 --- a/test/Interop/Cxx/operators/member-inline-module-interface.swift +++ b/test/Interop/Cxx/operators/member-inline-module-interface.swift @@ -294,3 +294,16 @@ // CHECK: struct HasOperatorCallWithDefaultArg { // CHECK: func callAsFunction(_ x: Int32 = cxxDefaultArg) -> Int32 // CHECK: } + +// CHECK: struct HasStaticOperatorCallBase { +// CHECK: func callAsFunction(_ x: Int32) -> Int32 +// CHECK: } + +// CHECK: struct HasStaticOperatorCallDerived { +// CHECK: func callAsFunction(_ x: Int32) -> Int32 +// CHECK: } + +// CHECK: struct HasStaticOperatorCallWithConstOperator { +// CHECK: func callAsFunction(_ x: Int32, _ y: Int32) -> Int32 +// CHECK: func callAsFunction(_ x: Int32) -> Int32 +// CHECK: } diff --git a/test/Interop/Cxx/operators/member-inline.swift b/test/Interop/Cxx/operators/member-inline.swift index 8354e7cc04035..73540783ee53a 100644 --- a/test/Interop/Cxx/operators/member-inline.swift +++ b/test/Interop/Cxx/operators/member-inline.swift @@ -437,4 +437,24 @@ OperatorsTestSuite.test("HasOperatorCallWithDefaultArg.call") { expectEqual(444, res) } +OperatorsTestSuite.test("HasStaticOperatorCallBase.call") { + let h = HasStaticOperatorCallBase() + let res = h(1) + expectEqual(43, res) +} + +OperatorsTestSuite.test("HasStaticOperatorCallDerived.call") { + let h = HasStaticOperatorCallDerived() + let res = h(0) + expectEqual(42, res) +} + +OperatorsTestSuite.test("HasStaticOperatorCallWithConstOperator.call") { + let h = HasStaticOperatorCallWithConstOperator() + let res = h(10) + expectEqual(9, res) + let res2 = h(3, 5) + expectEqual(8, res2) +} + runAllTests() diff --git a/test/Interop/Cxx/stdlib/android-and-std-module.swift b/test/Interop/Cxx/stdlib/android-and-std-module.swift new file mode 100644 index 0000000000000..cff4db5e70ae8 --- /dev/null +++ b/test/Interop/Cxx/stdlib/android-and-std-module.swift @@ -0,0 +1,29 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -c -cxx-interoperability-mode=default -Xcc -std=c++14 -Xcc -fmodules-cache-path=%t +// RUN: %target-swift-frontend %s -c -cxx-interoperability-mode=default -Xcc -std=c++17 -Xcc -fmodules-cache-path=%t +// RUN: %target-swift-frontend %s -c -cxx-interoperability-mode=default -Xcc -std=c++20 -Xcc -fmodules-cache-path=%t + +// RUN: find %t | %FileCheck %s + +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend %s -c -cxx-interoperability-mode=default -Xcc -std=c++17 -Xcc -fmodules-cache-path=%t -DADD_CXXSTDLIB +// RUN: %target-swift-frontend %s -c -cxx-interoperability-mode=default -Xcc -std=c++20 -Xcc -fmodules-cache-path=%t -DADD_CXXSTDLIB + +// REQUIRES: OS=linux-android + +import Android +import Bionic + +#if ADD_CXXSTDLIB +import CxxStdlib +#endif + +func test() { +#if ADD_CXXSTDLIB + let _ = std.string() +#endif +} + +// CHECK-DAG: Android{{.*}}.pcm +// CHECK-DAG: std{{.*}}.pcm diff --git a/test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift b/test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift index 5b051632c5b27..2a774b7fc6c11 100644 --- a/test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift +++ b/test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift @@ -102,14 +102,14 @@ public final class ClassWithIntField { // CHECK-EMPTY: // CHECK-NEXT: namespace Class SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("Class") { -// CHECK: SWIFT_INLINE_THUNK ClassWithIntField passThroughClassWithIntField(const ClassWithIntField& x) noexcept SWIFT_SYMBOL("s:5Class011passThroughA12WithIntFieldyAA0adeF0CADF") SWIFT_WARN_UNUSED_RESULT { -// CHECK-NEXT: return _impl::_impl_ClassWithIntField::makeRetained(_impl::$s5Class011passThroughA12WithIntFieldyAA0adeF0CADF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(x))); -// CHECK-NEXT: } - public final class register { } // CHECK: class SWIFT_SYMBOL("s:5Class8registerC") register_ final : public swift::_impl::RefCountedClass { +// CHECK: SWIFT_INLINE_THUNK ClassWithIntField passThroughClassWithIntField(const ClassWithIntField& x) noexcept SWIFT_SYMBOL("s:5Class011passThroughA12WithIntFieldyAA0adeF0CADF") SWIFT_WARN_UNUSED_RESULT { +// CHECK-NEXT: return _impl::_impl_ClassWithIntField::makeRetained(_impl::$s5Class011passThroughA12WithIntFieldyAA0adeF0CADF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(x))); +// CHECK-NEXT: } + public func returnClassWithIntField() -> ClassWithIntField { return ClassWithIntField() } diff --git a/test/Interop/SwiftToCxx/enums/enum-element-method-name-clash.swift b/test/Interop/SwiftToCxx/enums/enum-element-method-name-clash.swift new file mode 100644 index 0000000000000..95162e70923a1 --- /dev/null +++ b/test/Interop/SwiftToCxx/enums/enum-element-method-name-clash.swift @@ -0,0 +1,35 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %s -typecheck -module-name Enums -clang-header-expose-decls=all-public -emit-clang-header-path %t/enums.h +// RUN: %FileCheck %s < %t/enums.h + +public enum Foo: Hashable, Sendable { + case bar(Parameters) + + // We do not want to generate C++ wrappers for this function yet + // because its name clashes with the enum element above preventing + // the generated header from compilation. + public static func bar(version: Int) -> Self { + Self.bar(Parameters(version: version)) + } +} + +extension Foo { + public struct Parameters: Hashable, Sendable { + public var version: Int + + public init(version: Int) { + self.version = version + } + } +} + +// CHECK-NOT: Foo bar(swift::Int version) + +// CHECK: switch (_getEnumTag()) { +// CHECK-NEXT: case 0: return cases::bar; +// CHECK-NEXT: default: abort(); +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-EMPTY: +// Before the fix, we had the static method's thunk here. +// CHECK-NEXT: swift::Int getHashValue() const \ No newline at end of file diff --git a/test/Interop/SwiftToCxx/functions/swift-operators.swift b/test/Interop/SwiftToCxx/functions/swift-operators.swift index 662b7f07875db..af9de28907042 100644 --- a/test/Interop/SwiftToCxx/functions/swift-operators.swift +++ b/test/Interop/SwiftToCxx/functions/swift-operators.swift @@ -2,9 +2,7 @@ // RUN: %target-swift-frontend %s -typecheck -module-name Operators -clang-header-expose-decls=all-public -emit-clang-header-path %t/operators.h // RUN: %FileCheck %s < %t/operators.h -// TODO: %check-interop-cxx-header-in-clang(%t/operators.h) -// unfortunately the header still triggers an error: -// error: no member named '_impl_IntBox' in namespace 'Operators::_impl' +// RUN: %check-interop-cxx-header-in-clang(%t/operators.h) // CHECK-LABEL: namespace Operators SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("Operators") { diff --git a/test/Interop/SwiftToCxx/stdlib/core-foundation-types-in-cxx.swift b/test/Interop/SwiftToCxx/stdlib/core-foundation-types-in-cxx.swift new file mode 100644 index 0000000000000..7c45fbddfeb64 --- /dev/null +++ b/test/Interop/SwiftToCxx/stdlib/core-foundation-types-in-cxx.swift @@ -0,0 +1,14 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -typecheck %s -typecheck -module-name UseCoreFoundation -enable-experimental-cxx-interop -clang-header-expose-decls=all-public -emit-clang-header-path %t/UseCoreFoundation.h +// RUN: %FileCheck %s < %t/UseCoreFoundation.h + +// REQUIRES: objc_interop + +import CoreFoundation + +public func foobar(_ a: CFData) -> Bool { + true +} + +// CHECK: SWIFT_EXTERN bool $s17UseCoreFoundation6foobarySbSo9CFDataRefaF(CFDataRef _Nonnull a) SWIFT_NOEXCEPT SWIFT_CALL; // foobar(_:) diff --git a/test/Interop/SwiftToCxx/unsupported/unsupported-generics-in-cxx.swift b/test/Interop/SwiftToCxx/unsupported/unsupported-generics-in-cxx.swift index a3b9dbb9a9f5d..b0f3d8eadb75b 100644 --- a/test/Interop/SwiftToCxx/unsupported/unsupported-generics-in-cxx.swift +++ b/test/Interop/SwiftToCxx/unsupported/unsupported-generics-in-cxx.swift @@ -47,17 +47,61 @@ public class Class1 { public var index1: Struct1 { .init(rawValue: 123) } } +public struct GlyphIndex { + private var value: IntType + + init(value: IntType) { + self.value = value + } +} + +public struct QueryResult { + public var glyphIDs: [GlyphIndex] +} + +public func makeQueryResult() -> QueryResult { .init(glyphIDs: []) } + // CHECK: supported // CHECK: class SWIFT_SYMBOL("s:5Decls6Class1C") Class1 : public swift::_impl::RefCountedClass { // CHECK: 'index1' cannot be printed +// CHECK: namespace Decls SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("Decls") { +// CHECK: namespace Decls SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("Decls") { +// CHECK: SWIFT_INLINE_THUNK void supportedFunc(const T_0_0& x) noexcept SWIFT_SYMBOL("s:5Decls13supportedFuncyyxlF") { + +// CHECK: template +// CHECK-NEXT: #ifdef __cpp_concepts +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: #endif // __cpp_concepts +// CHECK-NEXT: class GlyphIndex { } SWIFT_UNAVAILABLE_MSG("generic requirements for generic struct 'GlyphIndex' can not yet be represented in C++"); + +// CHECK: class Proto { } SWIFT_UNAVAILABLE_MSG("protocol 'Proto' can not yet be represented in C++"); + +// CHECK: template +// CHECK-NEXT: #ifdef __cpp_concepts +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: #endif // __cpp_concepts +// CHECK-NEXT: class QueryResult { } SWIFT_UNAVAILABLE_MSG("generic requirements for generic struct 'QueryResult' can not yet be represented in C++"); + // CHECK: class Struct1 { } SWIFT_UNAVAILABLE_MSG("generic requirements for generic struct 'Struct1' can not yet be represented in C++"); // CHECK: // Unavailable in C++: Swift global function 'unsupportedFunc(_:)'. -// CHECK: class unsupportedGenericClass { } SWIFT_UNAVAILABLE_MSG("generic generic class 'unsupportedGenericClass' can not yet be exposed to C++"); +// CHECK: template +// CHECK-NEXT: #ifdef __cpp_concepts +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: #endif // __cpp_concepts +// CHECK-NEXT: class unsupportedGenericClass { } SWIFT_UNAVAILABLE_MSG("generic generic class 'unsupportedGenericClass' can not yet be exposed to C++"); // CHECK-EMPTY: +// CHECK-NEXT: template +// CHECK-NEXT: #ifdef __cpp_concepts +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: #endif // __cpp_concepts // CHECK-NEXT: class unsupportedGenericEnum { } SWIFT_UNAVAILABLE_MSG("generic requirements for generic enum 'unsupportedGenericEnum' can not yet be represented in C++"); // CHECK-EMPTY: +// CHECK-NEXT: template +// CHECK-NEXT: #ifdef __cpp_concepts +// CHECK-NEXT: requires swift::isUsableInGenericContext +// CHECK-NEXT: #endif // __cpp_concepts // CHECK-NEXT: class unsupportedGenericStruct { } SWIFT_UNAVAILABLE_MSG("generic requirements for generic struct 'unsupportedGenericStruct' can not yet be represented in C++"); diff --git a/test/Interpreter/conditional_conformances_runtime.swift b/test/Interpreter/conditional_conformances_runtime.swift index fbb6223b85f78..8fdd7e9b41b8a 100644 --- a/test/Interpreter/conditional_conformances_runtime.swift +++ b/test/Interpreter/conditional_conformances_runtime.swift @@ -33,11 +33,35 @@ extension Dictionary: P where Value == (Key) -> Bool { let yx = Y(wrapped: X()) -assert(tryAsP(yx) == 11) +precondition(tryAsP(yx) == 11) let dict: [Int : (Int) -> Bool] = [:] -assert(tryAsP(dict) == 2) +precondition(tryAsP(dict) == 2) let yDict = Y(wrapped: dict) -assert(tryAsP(yDict) == 12) +precondition(tryAsP(yDict) == 12) +// Generic argument indexing runs off the end when a key +// argument comes after a non-key argument. +struct Outer {} + +extension Outer where T == Int { + struct Inner { + // Add some stored properties that will have field offsets in the metadata. + // If we read past the end of the generic arguments, we'll find these and + // crash on something that's definitely not a valid pointer. + var a: T? + var b: T? + var c: T? + var d: T? + } +} + +extension Outer.Inner: P where U == String { + func foo() -> Int { return 1 } +} + +let conformingInner: Any = Outer.Inner() +let nonconformingInner: Any = Outer.Inner() +precondition(conformingInner is P) +precondition(!(nonconformingInner is P)) diff --git a/test/Interpreter/moveonly_existentials.swift b/test/Interpreter/moveonly_existentials.swift new file mode 100644 index 0000000000000..f3ab9465e8036 --- /dev/null +++ b/test/Interpreter/moveonly_existentials.swift @@ -0,0 +1,30 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -g %s -o %t/bin +// RUN: %target-codesign %t/bin +// RUN: %target-run %t/bin | %FileCheck %s + +// REQUIRES: executable_test + +protocol Boopable: ~Copyable { + func boop() + mutating func bonk() +} + +struct S: ~Copyable, Boopable { + func boop() { print("boop") } + mutating func bonk() { print("hmm") } +} + +func borrow(_ b: borrowing any Boopable & ~Copyable) { + b.boop() +} + +func mutate(_ b: inout any Boopable & ~Copyable) { + b.bonk() +} + +// CHECK: boop +// CHECK: hmm +borrow(S()) +var s = S() as any Boopable & ~Copyable +mutate(&s) diff --git a/test/Interpreter/moveonly_generics_casting.swift b/test/Interpreter/moveonly_generics_casting.swift index 1b838817a30a7..abff30496b199 100644 --- a/test/Interpreter/moveonly_generics_casting.swift +++ b/test/Interpreter/moveonly_generics_casting.swift @@ -136,7 +136,7 @@ enum Maybe: ~Copyable { case just(Wrapped) case nothing } -extension Maybe: Copyable {} +extension Maybe: Copyable where Wrapped: Copyable {} extension Maybe: CustomDebugStringConvertible { var debugDescription: String { "cast succeeded" diff --git a/test/Interpreter/preconcurrency_conformances.swift b/test/Interpreter/preconcurrency_conformances.swift index c45872a98a14d..774504ed43fe0 100644 --- a/test/Interpreter/preconcurrency_conformances.swift +++ b/test/Interpreter/preconcurrency_conformances.swift @@ -34,6 +34,16 @@ // RUN: not --crash env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=legacy SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/crash4.out 2>&1 | %FileCheck %t/src/Crash4.swift --check-prefix=LEGACY_CHECK // RUN: not --crash env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=swift6 SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/crash4.out 2>&1 | %FileCheck %t/src/Crash4.swift --check-prefix=SWIFT6_CHECK --dump-input=always +// RUN: %target-build-swift -Xfrontend -enable-upcoming-feature -Xfrontend DynamicActorIsolation -I %t -L %t -l Types %t/src/Crash5.swift -o %t/crash5.out +// RUN: %target-codesign %t/crash5.out +// RUN: not --crash env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=legacy SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/crash5.out 2>&1 | %FileCheck %t/src/Crash5.swift --check-prefix=LEGACY_CHECK +// RUN: not --crash env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=swift6 SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/crash5.out 2>&1 | %FileCheck %t/src/Crash5.swift --check-prefix=SWIFT6_CHECK --dump-input=always + +// RUN: %target-build-swift -Xfrontend -enable-upcoming-feature -Xfrontend DynamicActorIsolation -I %t -L %t -l Types %t/src/Crash6.swift -o %t/crash6.out +// RUN: %target-codesign %t/crash6.out +// RUN: not --crash env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=legacy SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/crash6.out 2>&1 | %FileCheck %t/src/Crash6.swift --check-prefix=LEGACY_CHECK +// RUN: not --crash env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=swift6 SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/crash6.out 2>&1 | %FileCheck %t/src/Crash6.swift --check-prefix=SWIFT6_CHECK --dump-input=always + // REQUIRES: asserts // REQUIRES: concurrency // REQUIRES: concurrency_runtime @@ -51,6 +61,10 @@ public protocol P { func test() -> Int } +public protocol Q : P { + func childTest() +} + //--- Types.swift import Interface @@ -87,6 +101,21 @@ extension ActorTest : @preconcurrency P { public func test() -> Int { x } } +@MainActor +public struct TestWithParent : @preconcurrency Q { + public var prop: [String] = [] + + public init() {} + + public func test() -> Int { 42 } + public func childTest() {} +} + +public func runChildTest(_ type: T.Type) async { + let v = type.init() + return v.childTest() +} + //--- Crash1.swift import Types print(await runTest(Test.self)) @@ -122,3 +151,21 @@ print("OK") // SWIFT6_CHECK: Incorrect actor executor assumption // SWIFT6_CHECK-NOT: OK + +//--- Crash5.swift +import Types +print(await runTest(TestWithParent.self)) +print("OK") +// LEGACY_CHECK: data race detected: @MainActor function at Types/Types.swift:40 was not called on the main thread + +// Crash without good message, since via 'dispatch_assert_queue' +// SWIFT6_CHECK-NOT: OK + +//--- Crash6.swift +import Types +print(await runChildTest(TestWithParent.self)) +print("OK") +// LEGACY_CHECK: data race detected: @MainActor function at Types/Types.swift:40 was not called on the main thread + +// Crash without good message, since via 'dispatch_assert_queue' +// SWIFT6_CHECK-NOT: OK diff --git a/test/Interpreter/preconcurrency_conformances_with_disabled_checks.swift b/test/Interpreter/preconcurrency_conformances_with_disabled_checks.swift index c681e65748627..eb70d7cae4227 100644 --- a/test/Interpreter/preconcurrency_conformances_with_disabled_checks.swift +++ b/test/Interpreter/preconcurrency_conformances_with_disabled_checks.swift @@ -39,6 +39,18 @@ // RUN: env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=legacy SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/test4.out 2>&1 | %FileCheck %t/src/Test4.swift // RUN: env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=swift6 SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/test4.out 2>&1 | %FileCheck %t/src/Test4.swift +// RUN: %target-build-swift -I %t -L %t -l Types %t/src/Test5.swift -o %t/test5.out +// RUN: %target-codesign %t/test5.out +// RUN: env SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/test5.out 2>&1 | %FileCheck %t/src/Test5.swift +// RUN: env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=legacy SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/test5.out 2>&1 | %FileCheck %t/src/Test5.swift +// RUN: env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=swift6 SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/test5.out 2>&1 | %FileCheck %t/src/Test5.swift + +// RUN: %target-build-swift -I %t -L %t -l Types %t/src/Test6.swift -o %t/test6.out +// RUN: %target-codesign %t/test6.out +// RUN: env SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/test6.out 2>&1 | %FileCheck %t/src/Test6.swift +// RUN: env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=legacy SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/test6.out 2>&1 | %FileCheck %t/src/Test6.swift +// RUN: env SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=swift6 SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL=2 %target-run %t/test6.out 2>&1 | %FileCheck %t/src/Test6.swift + // REQUIRES: asserts // REQUIRES: concurrency // REQUIRES: concurrency_runtime @@ -56,6 +68,10 @@ public protocol P { func test() -> Int } +public protocol Q : P { + func childTest() +} + //--- Types.swift import Interface @@ -92,6 +108,21 @@ extension ActorTest : @preconcurrency P { public func test() -> Int { x } } +@MainActor +public struct TestWithParent : @preconcurrency Q { + public var prop: [String] = [] + + public init() {} + + public func test() -> Int { 42 } + public func childTest() {} +} + +public func runChildTest(_ type: T.Type) async { + let v = type.init() + return v.childTest() +} + //--- Test1.swift import Types print(await runTest(Test.self)) @@ -111,3 +142,13 @@ print(await runTest(ActorTest.self)) import Types print(await runAccessors(ActorTest.self)) // CHECK-NOT: Incorrect actor executor assumption + +//--- Test5.swift +import Types +print(await runTest(TestWithParent.self)) +// CHECK-NOT: Incorrect actor executor assumption + +//--- Test6.swift +import Types +print(await runChildTest(TestWithParent.self)) +// CHECK-NOT: Incorrect actor executor assumption diff --git a/test/Interpreter/rdar125864434.swift b/test/Interpreter/rdar125864434.swift deleted file mode 100644 index b5050eae2bde0..0000000000000 --- a/test/Interpreter/rdar125864434.swift +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %target-build-swift %s -o %t/bin -// RUN: %target-codesign %t/bin -// RUN: %target-run %t/bin | %FileCheck %s - -// REQUIRES: executable_test - -protocol Boopable: ~Copyable { - func boop() -} - -struct S: ~Copyable, Boopable { - func boop() { print("boop") } -} - -func check(_ b: borrowing any Boopable & ~Copyable) { - b.boop() -} - -// CHECK: boop -check(S()) diff --git a/test/Macros/freestanding_multifile.swift b/test/Macros/freestanding_multifile.swift index 920fe2b92b06b..2d511f6ff98ee 100644 --- a/test/Macros/freestanding_multifile.swift +++ b/test/Macros/freestanding_multifile.swift @@ -8,7 +8,7 @@ macro anonymousTypes(public: Bool, _: () -> String) = #externalMacro(module: "Ma // RUN: %target-swift-frontend -swift-version 5 -emit-ir -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser %S/Inputs/AnonTypes1.swift %S/Inputs/AnonTypes2.swift %s -o - -g | %FileCheck --check-prefix CHECK-IR %s -// CHECK-IR: $s9MacroUser33{{.*}}14anonymousTypesfMf_4namefMu_ -// CHECK-IR-NOT: $s9MacroUser33{{.*}}14anonymousTypesfMf0_4namefMu_ -// CHECK-IR: $s9MacroUser33{{.*}}14anonymousTypesfMf_4namefMu_ -// CHECK-IR-NOT: $s9MacroUser33{{.*}}14anonymousTypesfMf0_4namefMu_ +// CHECK-IR: $s9MacroUser{{.*}}fMX{{.*}}_33{{.*}}14anonymousTypesfMf_4namefMu_ +// CHECK-IR-NOT: $s9MacroUser{{.*}}fMX{{.*}}_33{{.*}}14anonymousTypesfMf0_4namefMu_ +// CHECK-IR: $s9MacroUser{{.*}}fMX{{.*}}_33{{.*}}14anonymousTypesfMf_4namefMu_ +// CHECK-IR-NOT: $s9MacroUser{{.*}}fMX{{.*}}_33{{.*}}14anonymousTypesfMf0_4namefMu_ diff --git a/test/Macros/macro_expand.swift b/test/Macros/macro_expand.swift index 1fffbde15d0bb..ad1b00e20a857 100644 --- a/test/Macros/macro_expand.swift +++ b/test/Macros/macro_expand.swift @@ -71,7 +71,7 @@ struct MemberNotCovered { // expected-note@-1 {{in expansion of macro 'NotCovered' here}} // CHECK-DIAGS: error: declaration name 'value' is not covered by macro 'NotCovered' - // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser16MemberNotCoveredV33_4361AD9339943F52AE6186DD51E04E91Ll0dE0fMf_.swift + // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX69_2_33_4361AD9339943F52AE6186DD51E04E91Ll10NotCoveredfMf_.swift // CHECK-DIAGS: var value: Int // CHECK-DIAGS: END CONTENTS OF FILE } @@ -137,7 +137,7 @@ macro AccidentalCodeItem() = #externalMacro(module: "MacroDefinition", type: "Fa func invalidDeclarationMacro() { #accidentalCodeItem // expected-note@-1 {{in expansion of macro 'accidentalCodeItem' here}} - // CHECK-DIAGS: @__swiftmacro_9MacroUser018invalidDeclarationA0yyF18accidentalCodeItemfMf_.swift:1:1: error: expected macro expansion to produce a declaration + // CHECK-DIAGS: @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_18accidentalCodeItemfMf_.swift:1:1: error: expected macro expansion to produce a declaration @AccidentalCodeItem struct S {} // expected-note@-1 {{in expansion of macro 'AccidentalCodeItem' on struct 'S' here}} @@ -155,9 +155,9 @@ func testFileID(a: Int, b: Int) { print("Result is \(#customFileID)") // CHECK-SIL: sil_scope [[SRC_SCOPE:[0-9]+]] { loc "{{.*}}macro_expand.swift":[[@LINE-3]]:6 parent {{.*}}testFileID // CHECK-SIL: sil_scope [[EXPANSION_SCOPE:[0-9]+]] { loc "{{.*}}macro_expand.swift":[[@LINE-2]]:22 parent [[SRC_SCOPE]] - // CHECK-SIL: sil_scope [[MACRO_SCOPE:[0-9]+]] { loc "@__swiftmacro{{.*}}":1:1 parent @$s9MacroUser10testFileID1a1bySi_SitF06customdE0fMf_ {{.*}} inlined_at [[EXPANSION_SCOPE]] } - // CHECK-SIL: string_literal utf8 "MacroUser/macro_expand.swift", loc "@__swiftmacro_9MacroUser10testFileID1a1bySi_SitF06customdE0fMf_.swift":1:1, scope [[MACRO_SCOPE]] - // CHECK-IR-DAG: !DISubprogram(name: "customFileID", linkageName: "$s9MacroUser10testFileID1a1bySi_SitF06customdE0fMf_" + // CHECK-SIL: sil_scope [[MACRO_SCOPE:[0-9]+]] { loc "@__swiftmacro{{.*}}":1:1 parent @$s9MacroUser0023macro_expandswift_elFCffMX{{.*}}_12customFileIDfMf_ {{.*}} inlined_at [[EXPANSION_SCOPE]] } + // CHECK-SIL: string_literal utf8 "MacroUser/macro_expand.swift", loc "@__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_12customFileIDfMf_.swift":1:1, scope [[MACRO_SCOPE]] + // CHECK-IR-DAG: !DISubprogram(name: "customFileID", linkageName: "$s9MacroUser0023macro_expandswift_elFCffMX{{.*}}_12customFileIDfMf_" // CHECK: Builtin result is MacroUser/macro_expand.swift // CHECK-AST: macro_expansion_expr type='String'{{.*}}name=line @@ -165,7 +165,7 @@ func testFileID(a: Int, b: Int) { print( // CHECK-IR-DAG: ![[L1:[0-9]+]] = distinct !DILocation(line: [[@LINE+3]], column: 5 // CHECK-IR-DAG: ![[L2:[0-9]+]] = distinct !DILocation({{.*}}inlinedAt: ![[L1]]) - // CHECK-IR-DAG: !DIFile(filename: "{{.*}}@__swiftmacro_9MacroUser10testFileID1a1bySi_SitF06customdE0fMf_.swift", {{.*}}source: "{{.*}}MacroUser/macro_expand.swift{{.*}}// original-source-range: {{.*}}") + // CHECK-IR-DAG: !DIFile(filename: "{{.*}}@__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_12customFileIDfMf_.swift", {{.*}}source: "{{.*}}MacroUser/macro_expand.swift{{.*}}// original-source-range: {{.*}}") #addBlocker( #stringify(a - b) ) @@ -278,7 +278,7 @@ func testNested() { _ = #stringify(#assertAny(Nested())) // expected-note@-1 {{in expansion of macro 'stringify' here}} // CHECK-DIAGS-NOT: error: cannot convert value of type 'Nested' to expected argument type 'Bool' -// CHECK-DIAGS: @__swiftmacro_9MacroUser10testNestedyyF9stringifyfMf_9assertAnyfMf_.swift:1:8: error: cannot convert value of type 'Nested' to expected argument type 'Bool' +// CHECK-DIAGS: @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_9stringifyfMf_9assertAnyfMf_.swift:1:8: error: cannot convert value of type 'Nested' to expected argument type 'Bool' // CHECK-DIAGS-NOT: error: cannot convert value of type 'Nested' to expected argument type 'Bool' // PRETTY-DIAGS: 1:8: error: cannot convert value of type 'Nested' to expected argument type 'Bool' @@ -299,7 +299,7 @@ func testStringifyWithThrows() throws { // FIXME: Lots of duplicate notes here _ = #stringify(maybeThrowing()) // expected-note 4{{in expansion of macro 'stringify' here}} - // CHECK-DIAGS: @__swiftmacro_9MacroUser23testStringifyWithThrowsyyKF9stringifyfMf1_.swift:1:2: error: call can throw but is not marked with 'try' + // CHECK-DIAGS: @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_9stringifyfMf1_.swift:1:2: error: call can throw but is not marked with 'try' #endif // The macro adds the 'try' for us. @@ -328,8 +328,8 @@ func testAddBlocker(a: Int, b: Int, c: Int, oa: OnlyAdds) { // expected-note@-1{{in expansion of macro 'addBlocker' here}} // expected-note@-2{{use '-'}}{{22-23=-}} - // CHECK-DIAGS: @__swiftmacro_9MacroUser14testAddBlocker1a1b1c2oaySi_S2iAA8OnlyAddsVtF03addE0fMf1_.swift:1:4: error: binary operator '-' cannot be applied to two 'OnlyAdds' operands [] [] - // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser14testAddBlocker1a1b1c2oaySi_S2iAA8OnlyAddsVtF03addE0fMf1_.swift: + // CHECK-DIAGS: @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_10addBlockerfMf1_.swift:1:4: error: binary operator '-' cannot be applied to two 'OnlyAdds' operands [] [] + // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_10addBlockerfMf1_.swift: // CHECK-DIAGS-NEXT: Original source range: {{.*}}macro_expand.swift:[[@LINE-6]]:7 - {{.*}}macro_expand.swift:[[@LINE-6]]:27 // CHECK-DIAGS-NEXT: oa - oa // CHECK-DIAGS-NEXT: END CONTENTS OF FILE @@ -373,7 +373,7 @@ func testNestedDeclInExpr() { macro defineDeclsWithKnownNames() = #externalMacro(module: "MacroDefinition", type: "DefineDeclsWithKnownNamesMacro") // Freestanding macros are not in inlined scopes. -// CHECK-SIL: sil_scope {{.*}} { loc "@__swiftmacro_9MacroUser016testFreestandingA9ExpansionyyF4Foo2L_V25defineDeclsWithKnownNamesfMf_.swift"{{.*}} -> Int } +// CHECK-SIL: sil_scope {{.*}} { loc "@__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_25defineDeclsWithKnownNamesfMf_.swift"{{.*}} -> Int } // FIXME: Macros producing arbitrary names are not supported yet #if false @@ -436,10 +436,10 @@ func testFreestandingMacroExpansion() { struct Foo3 { #bitwidthNumberedStructs("BUG", blah: false) // expected-note@-1 4{{in expansion of macro 'bitwidthNumberedStructs' here}} - // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfMf_.swift + // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX{{.*}}_23bitwidthNumberedStructsfMf_.swift // CHECK-DIAGS: struct BUG { - // CHECK-DIAGS: func $s9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfMf_6methodfMu_() - // CHECK-DIAGS: func $s9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfMf_6methodfMu0{{_?}}() + // CHECK-DIAGS: func $s9MacroUser0023macro_expandswift_elFCffMX{{.*}}_23bitwidthNumberedStructsfMf_6methodfMu_() + // CHECK-DIAGS: func $s9MacroUser0023macro_expandswift_elFCffMX{{.*}}_23bitwidthNumberedStructsfMf_6methodfMu0{{_?}}() } #endif diff --git a/test/Macros/macro_expand_closure.swift b/test/Macros/macro_expand_closure.swift index 441782da016b6..28feb98b40d32 100644 --- a/test/Macros/macro_expand_closure.swift +++ b/test/Macros/macro_expand_closure.swift @@ -19,12 +19,12 @@ func multiStatementInference() -> Int { // The closure intruduced by the macro expansion should not contain any inline // locations, but instead point directly into the macro buffer. -// CHECK-SIL: sil_scope [[S0:[0-9]+]] { loc "@__swiftmacro_9MacroUser23multiStatementInferenceSiyF0cD0fMf_.swift":1:1 parent @$s9MacroUser23multiStatementInferenceSiyFSiyXEfU_ -// CHECK-SIL: sil_scope [[S2:[0-9]+]] { loc "@__swiftmacro_9MacroUser23multiStatementInferenceSiyF0cD0fMf_.swift":2:14 parent [[S0]] } +// CHECK-SIL: sil_scope [[S0:[0-9]+]] { loc "@__swiftmacro_9MacroUser0031macro_expand_closureswift_yFFIifMX16_2_14multiStatementfMf_.swift":1:1 parent @$s9MacroUser23multiStatementInferenceSiyFSiyXEfU_ +// CHECK-SIL: sil_scope [[S2:[0-9]+]] { loc "@__swiftmacro_9MacroUser0031macro_expand_closureswift_yFFIifMX16_2_14multiStatementfMf_.swift":2:14 parent [[S0]] } // CHECK-SIL: sil {{.*}} @$s9MacroUser23multiStatementInferenceSiyFSiyXEfU_ // CHECK-SIL-NOT: return -// CHECK-SIL: %0 = integer_literal $Builtin.Int{{64|32}}, 10, loc "@__swiftmacro_9MacroUser23multiStatementInferenceSiyF0cD0fMf_.swift":2:14, scope [[S2]] +// CHECK-SIL: %0 = integer_literal $Builtin.Int{{64|32}}, 10, loc "@__swiftmacro_9MacroUser0031macro_expand_closureswift_yFFIifMX16_2_14multiStatementfMf_.swift":2:14, scope [[S2]] // CHECK: 10 print(multiStatementInference()) diff --git a/test/Macros/macro_expand_codeitems.swift b/test/Macros/macro_expand_codeitems.swift index 7d8e14c53374c..4cb673e6ba7d9 100644 --- a/test/Macros/macro_expand_codeitems.swift +++ b/test/Macros/macro_expand_codeitems.swift @@ -21,7 +21,7 @@ func testFreestandingMacroExpansion() { // CHECK: from stmt // CHECK: from usedInExpandedStmt // CHECK: from expr - // CHECK-DIAGS: struct $s9MacroUser016testFreestandingA9ExpansionyyF9codeItemsfMf_3foofMu_ { + // CHECK-DIAGS: struct $s9MacroUser0033macro_expand_codeitemsswift_DbGHjfMX25_2_9codeItemsfMf_3foofMu_ { // CHECK-DIAGS: END CONTENTS OF FILE #codeItems diff --git a/test/Macros/macros_diagnostics.swift b/test/Macros/macros_diagnostics.swift index 28e3e48488a52..6f207bf662398 100644 --- a/test/Macros/macros_diagnostics.swift +++ b/test/Macros/macros_diagnostics.swift @@ -220,3 +220,8 @@ struct SomeType { macro multipleFreestandingRoles(_: T) -> Void = #externalMacro(module: "A", type: "B") // expected-warning@-1{{external macro implementation type}} // expected-error@-2{{macro can only have a single freestanding role}} + +@_documentation(visibility: private) +@attached(peer) +macro Foo() = #externalMacro(module: "ThisMacroModuleDoesNotExist", type: "ThisMacroTypeDoesNotExist") +// expected-warning@-1{{external macro implementation type}} diff --git a/test/Macros/skip_non_exportable_decls.swift b/test/Macros/skip_non_exportable_decls.swift index e2e38f81c2fe4..fe2a87a637b44 100644 --- a/test/Macros/skip_non_exportable_decls.swift +++ b/test/Macros/skip_non_exportable_decls.swift @@ -10,8 +10,11 @@ @freestanding(declaration) macro anonymousTypes(public: Bool = false, causeErrors: Bool = false, _: () -> String) = #externalMacro(module: "MacroDefinition", type: "DefineAnonymousTypesMacro") -// CHECK: sil @$s9MacroUser03$s9A70User33_B2D49A1BE4DC7AF5CC327EB8EE2214BDLl14anonymousTypesfMf_4namefMu_C5helloSSyF : $@convention(method) (@guaranteed $s9MacroUser33_B2D49A1BE4DC7AF5CC327EB8EE2214BDLl14anonymousTypesfMf_4namefMu_) -> @owned String { +// CHECK: sil @$s9MacroUser03$s9A118User0036skip_non_exportable_declsswift_tjBBlfMX14_0_33_B2D49A1BE4DC7AF5CC327EB8EE2214BDLl14anonymousTypesfMf_4namefMu_C5helloSSyF : $@convention(method) (@guaranteed $s9MacroUser0036skip_non_exportable_declsswift_tjBBlfMX14_0_33_B2D49A1BE4DC7AF5CC327EB8EE2214BDLl14anonymousTypesfMf_4namefMu_) -> @owned String { + #anonymousTypes(public: true) { "hello" } -// CHECK-NOT: s9MacroUser03$s9A71User33_B2D49A1BE4DC7AF5CC327EB8EE2214BDLl14anonymousTypesfMf_4namefMu0_O5helloSSyF #anonymousTypes(public: false) { "goodbye" } + +// FIXME: Changing 'public: false' to 'public: true' above doesn't seem to +// have any effect on the generated SIL. Perhaps there is a bug here. diff --git a/test/Macros/top_level_freestanding.swift b/test/Macros/top_level_freestanding.swift index 7db7a67249161..9d280b82842bc 100644 --- a/test/Macros/top_level_freestanding.swift +++ b/test/Macros/top_level_freestanding.swift @@ -60,7 +60,7 @@ func lookupGlobalFreestandingExpansion() { #anonymousTypes(public: true) { "hello" } -// CHECK-SIL: sil @$s9MacroUser03$s9A70User33_082AE7CFEFA6960C804A9FE7366EB5A0Ll14anonymousTypesfMf_4namefMu_C5helloSSyF +// CHECK-SIL: sil @$s9MacroUser03$s9A115User0033top_level_freestandingswift_DbGHjfMX60_0_33_082AE7CFEFA6960C804A9FE7366EB5A0Ll14anonymousTypesfMf_4namefMu_C5helloSSyF @main struct Main { @@ -94,8 +94,8 @@ func testArbitraryAtGlobal() { } #endif -// DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser33_{{.*}}9stringifyfMf1_{{.*}}warning: 'deprecated()' is deprecated -// DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser33_{{.*}}9stringifyfMf2_{{.*}}warning: 'deprecated()' is deprecated +// DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser0039top_level_freestanding_otherswift_jrGEmfMX12_17_33_7FDB3F9D78D0279543373AD342C3C331Ll9stringifyfMf1{{.*}}: warning: 'deprecated()' is deprecated +// DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser0039top_level_freestanding_otherswift_jrGEmfMX16_17_33_7FDB3F9D78D0279543373AD342C3C331Ll9stringifyfMf2{{.*}}: warning: 'deprecated()' is deprecated #varValue @@ -107,8 +107,8 @@ func testGlobalVariable() { // expected-note @+1 6 {{in expansion of macro 'anonymousTypes' here}} #anonymousTypes(causeErrors: true) { "foo" } -// DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser33{{.*}}anonymousTypesfMf0_{{.*}}error: use of protocol 'Equatable' as a type must be written 'any Equatable' -// DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser03{{.*}}anonymousTypes{{.*}}introduceTypeCheckingErrorsfMf_{{.*}}error: use of protocol 'Hashable' as a type must be written 'any Hashable' +// DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser0033top_level_freestandingswift_DbGHjfMX108_0_33_082AE7CFEFA6960C804A9FE7366EB5A0Ll14anonymousTypesfMf0_{{.*}}: error: use of protocol 'Equatable' as a type must be written 'any Equatable' +// DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser00142___swiftmacro_9MacroUser0033top_level_freestandingswift_DbGHjfMX108_0_33_082AE7CFEFA6960C804A9FE7366EB5A0Ll14anonymousTypesfMf0_swift_DAIABdjIbfMX23_2_33_082AE7CFEFA6960C804A9FE7366EB5A0Ll27introduceTypeCheckingErrorsfMf_{{.*}}: error: use of protocol 'Hashable' as a type must be written 'any Hashable' // expected-note @+1 2 {{in expansion of macro 'anonymousTypes' here}} #anonymousTypes { () -> String in diff --git a/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift b/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift index 4efd9e23b6508..9b2dffec8f25e 100644 --- a/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift +++ b/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift @@ -55,12 +55,12 @@ public struct _Toys { public struct ExplicitHello: ~Copyable { let thing: T } -extension ExplicitHello: Copyable {} +extension ExplicitHello: Copyable where T: Copyable {} public struct Hello: ~Copyable, ~Escapable where T: ~Escapable {} -extension Hello: Escapable where T: ~Copyable {} -extension Hello: Copyable where T: ~Escapable {} +extension Hello: Escapable where T: Escapable {} +extension Hello: Copyable where T: Copyable {} public protocol TestAssocTypes { associatedtype A: ~Copyable, _NoCopyP = Int @@ -94,11 +94,11 @@ public struct Outer: ~Copyable { public struct InnerVariation2: ~Copyable, ~Escapable {} } -extension Outer: Copyable {} -extension Outer.InnerStruct: Copyable {} +extension Outer: Copyable where A: Copyable {} +extension Outer.InnerStruct: Copyable where C: Copyable, A: Copyable {} -extension Outer.InnerVariation1: Copyable {} -extension Outer.InnerVariation2: Escapable where A: ~Copyable {} +extension Outer.InnerVariation1: Copyable where A: Copyable, D: Copyable & Escapable {} +extension Outer.InnerVariation2: Escapable where A: Escapable, D: Escapable {} extension Outer.InnerStruct { public func hello(_ t: T) {} diff --git a/test/ModuleInterface/distributed-actor.swift b/test/ModuleInterface/distributed-actor.swift index 7aef5a6f1ced0..2edb8c2efbe15 100644 --- a/test/ModuleInterface/distributed-actor.swift +++ b/test/ModuleInterface/distributed-actor.swift @@ -67,7 +67,7 @@ public distributed actor DAG where ActorSystem: DistributedActorSys // CHECK: get // CHECK: } // CHECK: public init(actorSystem system: ActorSystem) -// CHECK: @available(iOS 9999, tvOS 9999, watchOS 9999, visionOS 9999, macOS 9999, *) +// CHECK: @available(iOS 18.0, tvOS 18.0, watchOS 11.0, visionOS 2.0, macOS 15.0, *) // CHECK: @_semantics("defaultActor") nonisolated final public var unownedExecutor: _Concurrency.UnownedSerialExecutor { // CHECK: get // CHECK: } @@ -84,7 +84,7 @@ public distributed actor DAG where ActorSystem: DistributedActorSys // CHECK-NEXT:extension Library.DA : Swift.Decodable {} // CHECK-NOT: #if compiler(>=5.3) && $Actors -// CHECK: @available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999, *) +// CHECK: @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) // CHECK-NEXT: extension Library.DAG : Distributed.DistributedActor {} //--- Client.swift diff --git a/test/ModuleInterface/invertible_constraints.swift b/test/ModuleInterface/invertible_constraints.swift index 890567057e32a..4ecd3ec136bcd 100644 --- a/test/ModuleInterface/invertible_constraints.swift +++ b/test/ModuleInterface/invertible_constraints.swift @@ -26,14 +26,14 @@ public protocol P: ~Copyable { public struct X: ~Copyable { } // CHECK: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK: extension Test.X : Swift.Copyable { +// CHECK: extension Test.X : Swift.Copyable where T : Swift.Copyable { // CHECK-NEXT: func f() // CHECK: } // CHECK: #else // CHECK: extension Test.X { // CHECK-NEXT: func f() // CHECK: } -extension X: Copyable { +extension X: Copyable where T: Copyable { public func f() { } } diff --git a/test/ModuleInterface/noncopyable_generics.swift b/test/ModuleInterface/noncopyable_generics.swift index d1806d76c2278..b96241d9fbef0 100644 --- a/test/ModuleInterface/noncopyable_generics.swift +++ b/test/ModuleInterface/noncopyable_generics.swift @@ -77,18 +77,18 @@ import NoncopyableGenerics_Misc // CHECK-MISC-NEXT: public struct ExplicitHello : ~Swift.Copyable where T : ~Copyable { // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-MISC-NEXT: extension {{.*}}.ExplicitHello : Swift.Copyable { +// CHECK-MISC-NEXT: extension {{.*}}.ExplicitHello : Swift.Copyable where T : Swift.Copyable { // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics // CHECK-MISC-NEXT: public struct Hello : ~Swift.Copyable, ~Swift.Escapable where T : ~Copyable, T : ~Escapable { // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-MISC-NEXT: extension NoncopyableGenerics_Misc.Hello : Swift.Escapable where T : ~Copyable { +// CHECK-MISC-NEXT: extension NoncopyableGenerics_Misc.Hello : Swift.Escapable where T : Swift.Escapable { // CHECK-MISC-NEXT: } // CHECK-MISC: #endif // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-MISC-NEXT: extension NoncopyableGenerics_Misc.Hello : Swift.Copyable where T : ~Escapable { +// CHECK-MISC-NEXT: extension NoncopyableGenerics_Misc.Hello : Swift.Copyable where T : Swift.Copyable { // CHECK-MISC-NEXT: } // CHECK-MISC: #endif @@ -121,19 +121,19 @@ import NoncopyableGenerics_Misc // CHECK-MISC: public struct InnerVariation2 : ~Swift.Copyable, ~Swift.Escapable where D : ~Escapable // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-MISC-NEXT: extension {{.*}}.Outer : Swift.Copyable { +// CHECK-MISC-NEXT: extension {{.*}}.Outer : Swift.Copyable where A : Swift.Copyable { // CHECK-MISC: #endif // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-MISC-NEXT: extension {{.*}}.Outer.InnerStruct : Swift.Copyable { +// CHECK-MISC-NEXT: extension {{.*}}.Outer.InnerStruct : Swift.Copyable where A : Swift.Copyable, C : Swift.Copyable { // CHECK-MISC: #endif // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-MISC-NEXT: extension {{.*}}.Outer.InnerVariation1 : Swift.Copyable { +// CHECK-MISC-NEXT: extension {{.*}}.Outer.InnerVariation1 : Swift.Copyable where A : Swift.Copyable, D : Swift.Copyable { // CHECK-MISC: #endif // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-MISC-NEXT: extension {{.*}}.Outer.InnerVariation2 : Swift.Escapable where A : ~Copyable { +// CHECK-MISC-NEXT: extension {{.*}}.Outer.InnerVariation2 : Swift.Escapable where D : Swift.Escapable { // CHECK-MISC: #endif // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics @@ -250,7 +250,7 @@ import Swiftskell // CHECK: #endif // CHECK: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-NEXT: extension Swiftskell.Pair : Swift.Copyable { +// CHECK-NEXT: extension Swiftskell.Pair : Swift.Copyable where L : Swift.Copyable, R : Swift.Copyable { // CHECK: #endif // CHECK: #if compiler(>=5.3) && $NoncopyableGenerics @@ -258,7 +258,7 @@ import Swiftskell // CHECK: #endif // CHECK: #if compiler(>=5.3) && $NoncopyableGenerics -// CHECK-NEXT: extension Swiftskell.Maybe : Swift.Copyable { +// CHECK-NEXT: extension Swiftskell.Maybe : Swift.Copyable where Wrapped : Swift.Copyable { // CHECK: #endif // CHECK: #if compiler(>=5.3) && $NoncopyableGenerics diff --git a/test/ModuleInterface/public-autolink-library.swift b/test/ModuleInterface/public-autolink-library.swift new file mode 100644 index 0000000000000..e19e02256a617 --- /dev/null +++ b/test/ModuleInterface/public-autolink-library.swift @@ -0,0 +1,6 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -typecheck -module-name Foo -emit-module-interface-path %t/Foo.swiftinterface %s -module-link-name Foo -enable-library-evolution -public-autolink-library Bar +// RUN: %target-swift-frontend -compile-module-from-interface -o %t/Foo.swiftmodule %t/Foo.swiftinterface +// RUN: %target-swift-ide-test -print-module-metadata -module-to-print Foo -I %t -source-filename %s | %FileCheck %s + +// CHECK: link library: Bar diff --git a/test/Parse/ConditionalCompilation/compiler.swift b/test/Parse/ConditionalCompilation/compiler.swift index d54ef05d61599..25c682c90fd7f 100644 --- a/test/Parse/ConditionalCompilation/compiler.swift +++ b/test/Parse/ConditionalCompilation/compiler.swift @@ -28,3 +28,21 @@ // There should be no error here. foo bar #endif + +#if compiler(>=4.1) + let _: Int = 1 +#else + #if false + // There should be no error here. + foo bar + #endif +#endif + +#if false + #if compiler(>=4.1) + let _: Int = 1 + #else + // There should be no error here. + foo bar + #endif +#endif diff --git a/test/Parse/explicit_lifetime_dependence_specifiers.swift b/test/Parse/explicit_lifetime_dependence_specifiers.swift index 9f221a7fa38b2..0f9561aeda470 100644 --- a/test/Parse/explicit_lifetime_dependence_specifiers.swift +++ b/test/Parse/explicit_lifetime_dependence_specifiers.swift @@ -153,3 +153,15 @@ struct Wrapper : ~Escapable { return view } } + +enum FakeOptional: ~Escapable { + case none, some(Wrapped) +} + +extension FakeOptional: Escapable where Wrapped: Escapable {} + +extension FakeOptional where Wrapped: ~Escapable { + init(nilLiteral: ()) -> dependsOn(immortal) Self { + self = .none + } +} diff --git a/test/Parse/inverses.swift b/test/Parse/inverses.swift index 3ddafa9340574..587badfe3cbb0 100644 --- a/test/Parse/inverses.swift +++ b/test/Parse/inverses.swift @@ -52,7 +52,7 @@ protocol Rope: Hashable, ~Copyable { // expected-error {{'Self' requir associatedtype Element: ~Copyable } -extension S: ~Copyable {} // expected-error {{cannot suppress '~Copyable' in extension}} +extension S: ~Copyable {} // expected-error {{cannot suppress 'Copyable' in extension}} struct S: ~U, // expected-error {{type 'U' cannot be suppressed}} ~Copyable {} @@ -123,3 +123,26 @@ func typeInExpression() { func param3(_ t: borrowing any ~Copyable) {} func param4(_ t: any ~Copyable.Type) {} + +protocol P: ~Copyable {} +protocol Q: ~Copyable {} +protocol R: ~Copyable {} +struct Blooper: ~Copyable {} +extension Blooper: (Q & (R & (~Copyable & P))) {} // expected-error {{cannot suppress 'Copyable' in extension}} + +protocol Edible {} +protocol Portable {} +typealias Alias = Portable & Copyable + +struct Burrito: ~Copyable {} +extension Burrito: Alias {} // expected-error {{conformance to 'Copyable' must be declared in a separate extension}} +// expected-note@-1 {{'Burrito' declares conformance to protocol 'Copyable' here}} + +extension Burrito: Copyable & Edible & P {} // expected-error {{redundant conformance of 'Burrito' to protocol 'Copyable'}} + +struct Blah: ~Copyable {} +extension Blah: P, Q, Copyable, R {} // expected-error {{generic struct 'Blah' required to be 'Copyable' but is marked with '~Copyable'}} +// expected-error@-1 {{conformance to 'Copyable' must be declared in a separate extension}} + +enum Hello: ~Copyable {} +extension Hello: Copyable & Edible & P {} // expected-error {{conformance to 'Copyable' must be declared in a separate extension}} diff --git a/test/SILGen/async_builtins.swift b/test/SILGen/async_builtins.swift index bc8ab85d6a621..97105e2b8f4e4 100644 --- a/test/SILGen/async_builtins.swift +++ b/test/SILGen/async_builtins.swift @@ -21,10 +21,11 @@ public struct X { // CHECK: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none // CHECK: [[GROUP:%.*]] = enum $Optional, #Optional.none // CHECK: [[TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.none + // CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE_FN:%.*]] = function_ref @$s4test1XV12launchFutureyyxlFxyYaYbKcfU_ : // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]({{.*}}) : $@convention(thin) @Sendable @async <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error any Error) // CHECK: [[CONVERTED_CLOSURE:%.*]] = convert_function [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> (@out T, @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for - // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) func launchFuture(_ value: T) { _ = Builtin.createAsyncTask(0) { () async throws -> T in return value @@ -36,10 +37,11 @@ public struct X { // CHECK: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none // CHECK: [[GROUP:%.*]] = enum $Optional, #Optional.some!enumelt, %1 : $Builtin.RawPointer // CHECK: [[TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.none + // CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE_FN:%.*]] = function_ref @$s4test1XV16launchGroupChild_5groupyx_BptlFxyYaYbKcfU_ : // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]({{.*}}) : $@convention(thin) @Sendable @async <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error any Error) // CHECK: [[CONVERTED_CLOSURE:%.*]] = convert_function [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> (@out T, @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for - // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) func launchGroupChild(_ value: T, group: Builtin.RawPointer) { _ = Builtin.createAsyncTaskInGroup(0, group) { () async throws -> T in return value @@ -51,9 +53,10 @@ public struct X { // CHECK: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none // CHECK: [[GROUP:%.*]] = enum $Optional, #Optional.some!enumelt, %0 : $Builtin.RawPointer // CHECK: [[TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.none + // CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE_FN:%.*]] = function_ref @$s4test1XV26launchDiscardingGroupChild5groupyBp_tFyyYaYbKcfU_ : // CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE_FN]] - // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> @error any Error) : $(Builtin.NativeObject, Builtin.RawPointer) + // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> @error any Error) : $(Builtin.NativeObject, Builtin.RawPointer) func launchDiscardingGroupChild(group: Builtin.RawPointer) { _ = Builtin.createAsyncDiscardingTaskInGroup(0, group) { () async throws in return @@ -69,10 +72,11 @@ public struct X { // CHECK: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none // CHECK: [[GROUP:%.*]] = enum $Optional, #Optional.none // CHECK: [[TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.some!enumelt, %1 : $Builtin.Executor + // CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE_FN:%.*]] = function_ref @$s4test1XV24launchFutureWithExecutor_8executoryx_BetlFxyYaYbKcfU_ : // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]({{.*}}) : $@convention(thin) @Sendable @async <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error any Error) // CHECK: [[CONVERTED_CLOSURE:%.*]] = convert_function [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> (@out T, @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for - // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) + // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) func launchFutureWithExecutor(_ value: T, executor: Builtin.Executor) { _ = Builtin.createAsyncTaskWithExecutor(0, executor) { () async throws -> T in return value @@ -84,9 +88,10 @@ public struct X { // CHECK: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none // CHECK: [[GROUP:%.*]] = enum $Optional, #Optional.some!enumelt, %0 : $Builtin.RawPointer // CHECK: [[TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.some!enumelt, %1 : $Builtin.Executor + // CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE_FN:%.*]] = function_ref @$s4test1XV34launchDiscardingFutureWithExecutor5group8executoryBp_BetFyyYaYbKcfU_ : // CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE_FN]] - // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> @error any Error) : $(Builtin.NativeObject, Builtin.RawPointer) + // CHECK: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[GROUP]] : $Optional, [[TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> @error any Error) : $(Builtin.NativeObject, Builtin.RawPointer) func launchDiscardingFutureWithExecutor(group: Builtin.RawPointer, executor: Builtin.Executor) { _ = Builtin.createAsyncDiscardingTaskInGroupWithExecutor(0, group, executor) { () async throws in return @@ -99,9 +104,10 @@ public struct X { // CHECK-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none // CHECK-NEXT: [[OPT_GROUP:%.*]] = enum $Optional, #Optional.none // CHECK-NEXT: [[OPT_TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.none +// CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE:%.*]] = partial_apply // CHECK-NEXT: [[CONVERTED_CLOSURE:%.*]] = convert_function [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> (@out T, @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for -// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) func testCreateTask(value: T) { _ = Builtin.createTask(flags: 0) { value @@ -113,9 +119,10 @@ func testCreateTask(value: T) { // CHECK-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK-NEXT: [[OPT_GROUP:%.*]] = enum $Optional, #Optional.some!enumelt, %0 : $Builtin.RawPointer // CHECK-NEXT: [[OPT_TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.none +// CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE:%.*]] = partial_apply // CHECK-NEXT: [[CONVERTED_CLOSURE:%.*]] = convert_function [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> (@out T, @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for -// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) func testCreateTask(group: Builtin.RawPointer, value: T) { _ = Builtin.createTask(flags: 0, taskGroup: group) { value @@ -127,9 +134,10 @@ func testCreateTask(group: Builtin.RawPointer, value: T) { // CHECK-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK-NEXT: [[OPT_GROUP:%.*]] = enum $Optional, #Optional.none // CHECK-NEXT: [[OPT_TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.some!enumelt, %0 : $Builtin.Executor +// CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE:%.*]] = partial_apply // CHECK-NEXT: [[CONVERTED_CLOSURE:%.*]] = convert_function [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> (@out T, @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for -// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) func testCreateTask(taskExecutor: Builtin.Executor, value: T) { _ = Builtin.createTask(flags: 0, initialTaskExecutor: taskExecutor) { value @@ -141,9 +149,10 @@ func testCreateTask(taskExecutor: Builtin.Executor, value: T) { // CHECK-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.some!enumelt, %0 : $Builtin.Executor // CHECK-NEXT: [[OPT_GROUP:%.*]] = enum $Optional, #Optional.none // CHECK-NEXT: [[OPT_TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.none +// CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE:%.*]] = partial_apply // CHECK-NEXT: [[CONVERTED_CLOSURE:%.*]] = convert_function [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> (@out T, @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for -// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) func testCreateTask(serialExecutor: Builtin.Executor, value: T) { _ = Builtin.createTask(flags: 0, initialSerialExecutor: serialExecutor) { value @@ -154,9 +163,10 @@ func testCreateTask(serialExecutor: Builtin.Executor, value: T) { // CHECK-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK-NEXT: [[OPT_GROUP:%.*]] = enum $Optional, #Optional.some!enumelt, %0 : $Builtin.RawPointer // CHECK-NEXT: [[OPT_TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.some!enumelt, %1 : $Builtin.Executor +// CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE:%.*]] = partial_apply // CHECK-NEXT: [[CONVERTED_CLOSURE:%.*]] = convert_function [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> (@out T, @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for -// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CONVERTED_CLOSURE]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for ) : $(Builtin.NativeObject, Builtin.RawPointer) func testCreateTask(group: Builtin.RawPointer, executor: Builtin.Executor, value: T) { _ = Builtin.createTask(flags: 0, taskGroup: group, initialTaskExecutor: executor) { value @@ -171,8 +181,9 @@ func testCreateTask(group: Builtin.RawPointer, executor: Builtin.Executor, va // CHECK-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK-NEXT: [[OPT_GROUP:%.*]] = enum $Optional, #Optional.none // CHECK-NEXT: [[OPT_TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.none +// CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE:%.*]] = partial_apply -// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> @error any Error) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> @error any Error) : $(Builtin.NativeObject, Builtin.RawPointer) func testCreateDiscardingTask(value: T) { _ = Builtin.createDiscardingTask(flags: 0) { _ = value @@ -187,8 +198,9 @@ func testCreateDiscardingTask(value: T) { // CHECK-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK-NEXT: [[OPT_GROUP:%.*]] = enum $Optional, #Optional.some!enumelt, %0 : $Builtin.RawPointer // CHECK-NEXT: [[OPT_TASK_EXECUTOR:%.*]] = enum $Optional, #Optional.some!enumelt, %1 : $Builtin.Executor +// CHECK: [[TASK_EXECUTOR_OWNED:%.*]] = enum $Optional<[[TASK_EXECUTOR_OWNED_TYPE:.*]]>, #Optional.none // CHECK: [[CLOSURE:%.*]] = partial_apply -// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> @error any Error) : $(Builtin.NativeObject, Builtin.RawPointer) +// CHECK-NEXT: builtin "createAsyncTask"([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional, [[OPT_GROUP]] : $Optional, [[OPT_TASK_EXECUTOR]] : $Optional, [[TASK_EXECUTOR_OWNED]] : $Optional<[[TASK_EXECUTOR_OWNED_TYPE]]>, [[CLOSURE]] : $@Sendable @async @callee_guaranteed () -> @error any Error) : $(Builtin.NativeObject, Builtin.RawPointer) func testCreateDiscardingTask(group: Builtin.RawPointer, executor: Builtin.Executor, value: T) { _ = Builtin.createDiscardingTask(flags: 0, taskGroup: group, initialTaskExecutor: executor) { _ = value diff --git a/test/SILGen/boxed_existentials.swift b/test/SILGen/boxed_existentials.swift index d48adc9bdf251..b2428fb9696ea 100644 --- a/test/SILGen/boxed_existentials.swift +++ b/test/SILGen/boxed_existentials.swift @@ -64,13 +64,10 @@ func test_property(_ x: Error) -> String { // CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials13test_propertyySSs5Error_pF // 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 [init] [[COPY]] : $*[[VALUE_TYPE]] // CHECK: [[METHOD:%.*]] = witness_method $[[VALUE_TYPE]], #Error._domain!getter // -- self parameter of witness is @in_guaranteed; no need to copy since // value in box is immutable and box is guaranteed -// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[COPY]]) +// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[VALUE]]) // CHECK-NOT: destroy_value [[ARG]] // CHECK: return [[RESULT]] @@ -93,10 +90,8 @@ func test_property_of_lvalue(_ x: Error) -> String { // CHECK: [[COPY:%.*]] = alloc_stack $[[VALUE_TYPE]] // CHECK: copy_addr [[VALUE]] to [init] [[COPY]] // CHECK: destroy_value [[VALUE_BOX]] -// CHECK: [[BORROW:%.*]] = alloc_stack $[[VALUE_TYPE]] -// CHECK: copy_addr [[COPY]] to [init] [[BORROW]] // CHECK: [[METHOD:%.*]] = witness_method $[[VALUE_TYPE]], #Error._domain!getter -// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[BORROW]]) +// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[COPY]]) // CHECK: destroy_addr [[COPY]] // CHECK: dealloc_stack [[COPY]] // CHECK: end_borrow [[VAR_LIFETIME]] diff --git a/test/SILGen/copy_expr.swift b/test/SILGen/copy_expr.swift index 4126b7616303a..88cacd5b7964a 100644 --- a/test/SILGen/copy_expr.swift +++ b/test/SILGen/copy_expr.swift @@ -333,10 +333,8 @@ func testCallMethodOnLoadableGlobal() { // Calling computedK. It is borrowed. // CHECK: [[TEMP:%.*]] = alloc_stack $T // CHECK: explicit_copy_addr [[X]] to [init] [[TEMP]] -// CHECK: [[TEMP2:%.*]] = alloc_stack $T -// CHECK: copy_addr [[TEMP]] to [init] [[TEMP2]] // CHECK: [[FUNC:%.*]] = witness_method $T, #P.computedK!getter : (Self) -> () -> Klass : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Klass -// CHECK: apply [[FUNC]]<(T)>([[TEMP2]]) +// CHECK: apply [[FUNC]]<(T)>([[TEMP]]) // // Calling computed consuming getter. // CHECK: [[TEMP:%.*]] = alloc_stack $T @@ -378,10 +376,8 @@ func testCallMethodOnAddressOnlyLetCopy(_ t: T.Type) { // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] // CHECK: [[TEMP:%.*]] = alloc_stack $ // CHECK: explicit_copy_addr [[ACCESS]] to [init] [[TEMP]] -// CHECK: [[TEMP2:%.*]] = alloc_stack $ -// CHECK: copy_addr [[TEMP]] to [init] [[TEMP2]] // CHECK: [[FUNC:%.*]] = witness_method $T, #P.computedK!getter : (Self) -> () -> Klass : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Klass -// CHECK: apply [[FUNC]]<(T)>([[TEMP2]]) +// CHECK: apply [[FUNC]]<(T)>([[TEMP]]) // // Consuming computed getter. // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -423,10 +419,8 @@ func testCallMethodOnAddressOnlyVarCopy(_ t: T.Type) { // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[ARG]] // CHECK: [[TEMP:%.*]] = alloc_stack $ // CHECK: explicit_copy_addr [[ACCESS]] to [init] [[TEMP]] -// CHECK: [[TEMP2:%.*]] = alloc_stack $ -// CHECK: copy_addr [[TEMP]] to [init] [[TEMP2]] // CHECK: [[FUNC:%.*]] = witness_method $T, #P.computedK!getter : (Self) -> () -> Klass : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned Klass -// CHECK: apply [[FUNC]]<(T)>([[TEMP2]]) +// CHECK: apply [[FUNC]]<(T)>([[TEMP]]) // // Consuming computed getter. // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[ARG]] diff --git a/test/SILGen/dynamic_self.swift b/test/SILGen/dynamic_self.swift index d1047a6ef4f01..242ace6264cc8 100644 --- a/test/SILGen/dynamic_self.swift +++ b/test/SILGen/dynamic_self.swift @@ -96,27 +96,19 @@ func testExistentialDispatch(p: 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 [init] [[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: apply [[P_P_GETTER]]<@opened([[N]], any P) Self>([[P_RESULT_ADDR2]], [[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 [[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]] : $*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 [init] [[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: apply [[P_SUBSCRIPT_GETTER]]<@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 [[PCOPY_ADDR_1]] : $*@opened([[N]], any P) Self // CHECK: dealloc_stack [[P_RESULT]] : $*any P _ = p[] } diff --git a/test/SILGen/existential_member_accesses_self_assoctype.swift b/test/SILGen/existential_member_accesses_self_assoctype.swift index 51a949339ff6d..bbf3fbc907695 100644 --- a/test/SILGen/existential_member_accesses_self_assoctype.swift +++ b/test/SILGen/existential_member_accesses_self_assoctype.swift @@ -150,32 +150,25 @@ func testCovariantSelfMethod8(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty11pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] [var_decl] $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]], any P) Self -// CHECK: copy_addr [[OPENED]] to [init] [[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 +// 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 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] [var_decl] $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 [init] [[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: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPTIONAL:%[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 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 : $*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 [init] [[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: [[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 testCovariantSelfProperty3(p: any P) { @@ -184,10 +177,8 @@ func testCovariantSelfProperty3(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty41pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] [var_decl] $(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 [init] [[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: 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: [[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) { @@ -195,10 +186,8 @@ func testCovariantSelfProperty4(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty51pyAA1P_p_tF // 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 [init] [[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:%[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]], 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" @@ -207,10 +196,8 @@ func testCovariantSelfProperty5(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty61pyAA1P_p_tF // 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 [init] [[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:%[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" @@ -219,10 +206,8 @@ func testCovariantSelfProperty6(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty71pyAA1P_p_tF // 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 [init] [[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> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <τ_0_0> +// CHECK: [[RESULT_FN:%[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 @callee_guaranteed @substituted <τ_0_0> (@guaranteed @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> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <@opened([[OPENED_ID]], any P) Self> to $@callee_guaranteed (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <@opened([[OPENED_ID]], any P) Self>) -> () // CHECK: [[THUNK:%[0-9]+]] = function_ref @$sxRi_zRi0_zlyxIsgn_Iegg_42existential_member_accesses_self_assoctype1P_pIgn_Iegg_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed @noescape @callee_guaranteed (@in_guaranteed any P) -> (), @guaranteed @callee_guaranteed (@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> (@guaranteed @noescape @callee_guaranteed (@in_guaranteed any P) -> (), @guaranteed @callee_guaranteed (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> ()) -> () @@ -232,10 +217,8 @@ func testCovariantSelfProperty7(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype26testCovariantSelfProperty81pyAA1P_p_tF // 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 [init] [[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> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>) -> () for <τ_0_0> +// CHECK: [[RESULT_FN:%[0-9]+]] = apply [[WITNESS]]<[[OPENED_TY]]>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed @substituted <τ_0_0> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>) -> () for <τ_0_0> // CHECK: [[STEP1:%[0-9]+]] = convert_function [[RESULT_FN]] : $@callee_guaranteed @substituted <τ_0_0> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>) -> () for <[[OPENED_TY]]> to $@callee_guaranteed (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]]>) -> () // CHECK: [[THUNK:%[0-9]+]] = function_ref @[[THUNK_NAME:\$[0-9a-zA-Z_]+]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed @noescape @callee_guaranteed (@guaranteed Array) -> (), @guaranteed @callee_guaranteed (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>) -> ()) -> () @@ -253,31 +236,25 @@ func testCovariantSelfProperty8(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript11pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] [var_decl] $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 [init] [[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 +// 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 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] [var_decl] $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 [init] [[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: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[OPTIONAL:%[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 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 : $*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 [init] [[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: [[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 testCovariantSelfSubscript3(p: any P) { @@ -286,10 +263,8 @@ func testCovariantSelfSubscript3(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript41pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] [var_decl] $(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 [init] [[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: 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 testCovariantSelfSubscript4(p: any P) { @@ -297,10 +272,8 @@ func testCovariantSelfSubscript4(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript51pyAA1P_p_tF // 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 [init] [[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:%[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]], 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" @@ -309,10 +282,8 @@ func testCovariantSelfSubscript5(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantSelfSubscript61pyAA1P_p_tF // 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 [init] [[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:%[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" @@ -325,10 +296,8 @@ func testCovariantSelfSubscript6(p: 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]], any P) Self -// CHECK: copy_addr [[OPENED]] to [init] [[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> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>, @in_guaranteed τ_0_0) -> () +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[STEP3]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed @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 }] } @@ -338,10 +307,8 @@ func testCovariantSelfSubscript7(p: any P) { // 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> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]]> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $[[OPENED_TY]] -// CHECK: copy_addr [[OPENED]] to [init] [[OPENED_COPY]] : $*[[OPENED_TY]] // CHECK: [[WITNESS:%[0-9]+]] = witness_method $[[OPENED_TY]], #P.subscript!getter : (Self) -> ((Self...) -> ()) -> () -// CHECK: apply [[WITNESS]]<[[OPENED_TY]]>([[STEP3]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>, @in_guaranteed τ_0_0) -> () +// CHECK: apply [[WITNESS]]<[[OPENED_TY]]>([[STEP3]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>, @in_guaranteed τ_0_0) -> () func testCovariantSelfSubscript8(p: any P) { _ = p[covariantSelfSubscript8: { _ in }] } @@ -435,31 +402,25 @@ func testCovariantAssocMethod8(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty11pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] [var_decl] $Any, 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 [init] [[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 +// 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 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] [var_decl] $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 [init] [[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: 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 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 : $*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 [init] [[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: [[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 testCovariantAssocProperty3(p: any P) { @@ -468,10 +429,8 @@ func testCovariantAssocProperty3(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty41pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] [var_decl] $(Any, Any), 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 [init] [[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: 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 testCovariantAssocProperty4(p: any P) { @@ -479,10 +438,8 @@ func testCovariantAssocProperty4(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty51pyAA1P_p_tF // 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 [init] [[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:%[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]], 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" @@ -491,10 +448,8 @@ func testCovariantAssocProperty5(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty61pyAA1P_p_tF // 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 [init] [[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:%[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" @@ -503,10 +458,8 @@ func testCovariantAssocProperty6(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty71pyAA1P_p_tF // 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 [init] [[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> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <τ_0_0.A> +// CHECK: [[RESULT_FN:%[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 @callee_guaranteed @substituted <τ_0_0> (@guaranteed @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> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0>) -> () for <@opened([[OPENED_ID]], any P) Self.A> to $@callee_guaranteed (@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 @$sxRi_zRi0_zly1A42existential_member_accesses_self_assoctype1PPQzIsgn_Iegg_ypIgn_Iegg_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed @noescape @callee_guaranteed (@in_guaranteed Any) -> (), @guaranteed @callee_guaranteed (@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> (@guaranteed @noescape @callee_guaranteed (@in_guaranteed Any) -> (), @guaranteed @callee_guaranteed (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>) -> ()) -> () @@ -516,10 +469,8 @@ func testCovariantAssocProperty7(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype27testCovariantAssocProperty81pyAA1P_p_tF // 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 [init] [[OPENED_COPY]] : $*[[OPENED_TY]] // CHECK: [[WITNESS:%[0-9]+]] = witness_method $[[OPENED_TY]], #P.covariantAssocProperty8!getter : (Self) -> () -> ((Self.A...) -> ()) -> () -// 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> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>) -> () for <τ_0_0.A> +// CHECK: [[RESULT_FN:%[0-9]+]] = apply [[WITNESS]]<[[OPENED_TY]]>([[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed @substituted <τ_0_0> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>) -> () for <τ_0_0.A> // CHECK: [[STEP1:%[0-9]+]] = convert_function [[RESULT_FN]] : $@callee_guaranteed @substituted <τ_0_0> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0>) -> () for <[[OPENED_TY]].A> to $@callee_guaranteed (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]].A>) -> () // CHECK: [[THUNK:%[0-9]+]] = function_ref @[[THUNK_NAME:\$[0-9a-zA-Z_]+]] : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed @noescape @callee_guaranteed (@guaranteed Array) -> (), @guaranteed @callee_guaranteed (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0.A>) -> ()) -> () // CHECK: partial_apply [callee_guaranteed] [[THUNK]]<[[OPENED_TY]]>([[STEP1]]) @@ -536,31 +487,25 @@ func testCovariantAssocProperty8(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript11pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] [var_decl] $Any, 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 [init] [[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 +// 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 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] [var_decl] $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 [init] [[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: 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 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 : $*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 [init] [[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: [[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 testCovariantAssocSubscript3(p: any P) { @@ -569,10 +514,8 @@ func testCovariantAssocSubscript3(p: any P) { // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript41pyAA1P_p_tF // CHECK: [[LET:%[0-9]+]] = alloc_stack [lexical] [var_decl] $(Any, Any), 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 [init] [[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: 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 testCovariantAssocSubscript4(p: any P) { @@ -580,10 +523,8 @@ func testCovariantAssocSubscript4(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript51pyAA1P_p_tF // 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 [init] [[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:%[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]], 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" @@ -592,10 +533,8 @@ func testCovariantAssocSubscript5(p: any P) { } // CHECK-LABEL: sil hidden [ossa] @$s42existential_member_accesses_self_assoctype28testCovariantAssocSubscript61pyAA1P_p_tF // 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 [init] [[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:%[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" @@ -608,10 +547,8 @@ func testCovariantAssocSubscript6(p: 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.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]], any P) Self -// CHECK: copy_addr [[OPENED]] to [init] [[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> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () +// CHECK: apply [[WITNESS]]<@opened([[OPENED_ID]], any P) Self>([[STEP3]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed @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 }] } @@ -621,10 +558,8 @@ func testCovariantAssocSubscript7(p: any P) { // 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> (@guaranteed Array<τ_0_0>) -> () for <[[OPENED_TY]].A> // CHECK: [[STEP3:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[STEP2]] -// CHECK: [[OPENED_COPY:%[0-9]+]] = alloc_stack $[[OPENED_TY]] -// CHECK: copy_addr [[OPENED]] to [init] [[OPENED_COPY]] : $*[[OPENED_TY]] // CHECK: [[WITNESS:%[0-9]+]] = witness_method $[[OPENED_TY]], #P.subscript!getter : (Self) -> ((Self.A...) -> ()) -> () -// CHECK: apply [[WITNESS]]<[[OPENED_TY]]>([[STEP3]], [[OPENED_COPY]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () +// CHECK: apply [[WITNESS]]<[[OPENED_TY]]>([[STEP3]], [[OPENED]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> (@guaranteed Array<τ_0_0>) -> () for <τ_0_0.A>, @in_guaranteed τ_0_0) -> () func testCovariantAssocSubscript8(p: any P) { _ = p[covariantAssocSubscript8: { _ in }] } diff --git a/test/SILGen/generic_property_base_lifetime.swift b/test/SILGen/generic_property_base_lifetime.swift index 4c8325326d98e..61d5643fc0f75 100644 --- a/test/SILGen/generic_property_base_lifetime.swift +++ b/test/SILGen/generic_property_base_lifetime.swift @@ -58,21 +58,13 @@ 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({{".*"}}, any ProtocolB) Self -// CHECK: copy_addr [[PROJECTION]] to [init] [[STACK]] -// CHECK: apply {{%.*}}([[STACK]]) -// CHECK: destroy_addr [[STACK]] -// CHECK: dealloc_stack [[STACK]] +// CHECK: apply {{%.*}}([[PROJECTION]]) func getIntPropExistential(_ a: ProtocolB) -> Int { return a.intProp } // CHECK-LABEL: sil hidden [ossa] @$s30generic_property_base_lifetime17getIntPropGeneric{{[_0-9a-zA-Z]*}}F -// CHECK: [[STACK:%[0-9]+]] = alloc_stack $T -// CHECK: copy_addr %0 to [init] [[STACK]] -// CHECK: apply {{%.*}}([[STACK]]) -// CHECK: destroy_addr [[STACK]] -// CHECK: dealloc_stack [[STACK]] +// CHECK: apply {{%.*}}(%0) func getIntPropGeneric(_ a: T) -> Int { return a.intProp } diff --git a/test/SILGen/init_actor_isolation.swift b/test/SILGen/init_actor_isolation.swift new file mode 100644 index 0000000000000..1ac63a6fb8f81 --- /dev/null +++ b/test/SILGen/init_actor_isolation.swift @@ -0,0 +1,29 @@ +// RUN: %target-swift-frontend -emit-silgen %s -module-name test -swift-version 5 | %FileCheck %s +// REQUIRES: concurrency + +@available(SwiftStdlib 5.1, *) +func f(isolatedTo actor: isolated (any Actor)?) async -> Int { 0 } + +@available(SwiftStdlib 5.1, *) +actor A { + let number: Int + + // CHECK-LABEL: sil hidden{{.*}}[ossa] @$s4test1ACACyYacfc : $@convention(method) @async (@sil_isolated @owned A) -> @owned A + init() async { + // First use of #isolation. + // CHECK: [[ISOLATION_1:%.*]] = builtin "flowSensitiveSelfIsolation" + // CHECK: [[F_1:%.*]] = function_ref @$s4test1f10isolatedToSiScA_pSgYi_tYaF + // CHECK-NEXT: [[F_RESULT:%.*]] = apply [[F_1]]([[ISOLATION_1]]) + + // Assignment to "number" of the result. + // CHECK: [[NUMBER:%.*]] = ref_element_addr {{%.*}} : $A, #A.number + // CHECK: assign [[F_RESULT]] to [[NUMBER]] + self.number = await f(isolatedTo: #isolation) + + // Second use of #isolation. + // CHECK: [[ISOLATION_2:%.*]] = builtin "flowSensitiveSelfIsolation" + // CHECK: [[F_2:%.*]] = function_ref @$s4test1f10isolatedToSiScA_pSgYi_tYaF + // CHECK-NEXT: apply [[F_2]]([[ISOLATION_2]]) + _ = await f(isolatedTo: #isolation) + } +} diff --git a/test/SILGen/local_decl_after_unreachable.swift b/test/SILGen/local_decl_after_unreachable.swift index 61c37ebff7a08..c99521c94ad6c 100644 --- a/test/SILGen/local_decl_after_unreachable.swift +++ b/test/SILGen/local_decl_after_unreachable.swift @@ -13,4 +13,6 @@ func foo() { // CHECK-LABEL: sil {{.*}} @{{.*}}3foo{{.*}}3bar{{.*}}F : {{.*}} { func bar(_: Any) {} + // Check that we don't crash here + lazy var v = 42 } diff --git a/test/SILGen/mangling_inverse_generics.swift b/test/SILGen/mangling_inverse_generics.swift index 1395654d30d16..3533902b0b687 100644 --- a/test/SILGen/mangling_inverse_generics.swift +++ b/test/SILGen/mangling_inverse_generics.swift @@ -145,7 +145,7 @@ public struct A: ~Copyable { // CHECK: sil hidden [ossa] @$s4test1AVAARi_zrlEACyxGycfC : $@convention(method) (@thin A.Type) -> @owned A { } -extension A: Copyable {} +extension A: Copyable where T: Copyable {} // extension A where T: ~Copyable { diff --git a/test/SILGen/moveonly_empty_conditionally_copyable.swift b/test/SILGen/moveonly_empty_conditionally_copyable.swift index 6715a13336f25..baabfca3a62b6 100644 --- a/test/SILGen/moveonly_empty_conditionally_copyable.swift +++ b/test/SILGen/moveonly_empty_conditionally_copyable.swift @@ -2,4 +2,4 @@ struct G: ~Copyable { } -extension G: Copyable {} +extension G: Copyable where T: Copyable {} diff --git a/test/SILGen/objc_generic_class.swift b/test/SILGen/objc_generic_class.swift index 2c9a00e7a0a90..9d0fcd10013e1 100644 --- a/test/SILGen/objc_generic_class.swift +++ b/test/SILGen/objc_generic_class.swift @@ -1,6 +1,7 @@ -// RUN: %target-swift-emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s +// RUN: %target-swift-emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -disable-availability-checking | %FileCheck %s // REQUIRES: objc_interop +// REQUIRES: concurrency import gizmo @@ -11,9 +12,23 @@ import gizmo // CHECK-NOT: sil hidden [ossa] @$sSo7GenericCfd // CHECK-NOT: sil hidden [ossa] @$sSo8NSObjectCfd -class Generic: NSObject { +class Generic: NSObject, ObjCProtocol { var x: Int = 10 + // CHECK-LABEL: sil private [thunk] [ossa] @$s18objc_generic_class7GenericC5evokeyyFTo : $@convention(objc_method) (Generic) -> () { + // CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class7GenericC5evokeyyF + // CHECK-NEXT: apply [[FN]] + func evoke() {} + + // CHECK-LABEL: sil private [thunk] [ossa] @$s18objc_generic_class7GenericC10evokeAsyncyyYaFTo : $@convention(objc_method) (@convention(block) () -> (), Generic) -> () { + // CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class7GenericC10evokeAsyncyyYaFyyYacfU_To + // CHECK-NEXT: partial_apply [callee_guaranteed] [[FN]] + + // CHECK-LABEL: sil shared [thunk] [ossa] @$s18objc_generic_class7GenericC10evokeAsyncyyYaFyyYacfU_To : $@convention(thin) @Sendable @async (@convention(block) () -> (), Generic) -> () + // CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class7GenericC10evokeAsyncyyYaF : $@convention(method) @async <τ_0_0> (@guaranteed Generic<τ_0_0>) -> () + // CHECK-NEXT: apply [[FN]] + func evokeAsync() async {} + // CHECK-LABEL: sil hidden [ossa] @$s18objc_generic_class7GenericCfD : $@convention(method) (@owned Generic) -> () { // CHECK: bb0({{%.*}} : @owned $Generic): // CHECK: } // end sil function '$s18objc_generic_class7GenericCfD' @@ -33,6 +48,11 @@ class Generic: NSObject { // CHECK-NOT: sil hidden [ossa] @$s18objc_generic_class7GenericCfd // CHECK-NOT: sil hidden [ossa] @$sSo8NSObjectCfd +@objc protocol ObjCProtocol { + func evoke() + func evokeAsync() async +} + // CHECK-LABEL: sil hidden [ossa] @$s18objc_generic_class11SubGeneric1CfD : $@convention(method) (@owned SubGeneric1) -> () { // CHECK: bb0([[SELF:%.*]] : @owned $SubGeneric1): // CHECK: [[SUPER_DEALLOC:%.*]] = objc_super_method [[SELF]] : $SubGeneric1, #Generic.deinit!deallocator.foreign : (Generic) -> () -> (), $@convention(objc_method) <τ_0_0> (Generic<τ_0_0>) -> () @@ -51,3 +71,19 @@ public extension GenericStruct where T == String { @objc public func f() -> String { "hello" } } } + +// rdar://129187133 - handle generic @objc thunks properly +actor GenericActor : SendableObjCProtocol { + // CHECK-LABEL: sil private [thunk] [ossa] @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFTo : $@convention(objc_method) (@convention(block) () -> (), @sil_isolated GenericActor) -> () + // CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFyyYacfU_To : $@convention(thin) @Sendable @async <τ_0_0> (@convention(block) () -> (), @sil_isolated GenericActor<τ_0_0>) -> () + // CHECK-NEXT: partial_apply [callee_guaranteed] [[FN]] + func evokeAsync() async {} + + // CHECK-LABEL: sil shared [thunk] [ossa] @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFyyYacfU_To : $@convention(thin) @Sendable @async (@convention(block) () -> (), @sil_isolated GenericActor) -> () + // CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaF : $@convention(method) @async <τ_0_0> (@sil_isolated @guaranteed GenericActor<τ_0_0>) -> () + // CHECK-NEXT: apply [[FN]] +} + +@objc protocol SendableObjCProtocol : Sendable { + func evokeAsync() async +} diff --git a/test/SILGen/package_bypass_resilience.swift b/test/SILGen/package_allow_non_resilient_access.swift similarity index 97% rename from test/SILGen/package_bypass_resilience.swift rename to test/SILGen/package_allow_non_resilient_access.swift index 6c7a0958f3e25..ce15b4b9ec617 100644 --- a/test/SILGen/package_bypass_resilience.swift +++ b/test/SILGen/package_allow_non_resilient_access.swift @@ -17,8 +17,8 @@ /// To bypass resilience at use site, Client needs to be in the same package as its /// loaded module and also opt in with -experimental-package-bypass-resilience. -// RUN: %target-swift-frontend -emit-silgen %t/Client.swift -I %t -module-name Client -package-name mypkg -experimental-package-bypass-resilience | %FileCheck %s --check-prefixes=CHECK,CHECK-BYPASS -// RUN: %target-swift-frontend -emit-silgen %t/Client.swift -I %t -module-name Client -package-name mypkg -experimental-package-bypass-resilience -enable-library-evolution | %FileCheck %s --check-prefixes=CHECK,CHECK-BYPASS +// RUN: %target-swift-frontend -emit-silgen %t/Client.swift -I %t -module-name Client -package-name mypkg -experimental-package-bypass-resilience | %FileCheck %s --check-prefixes=CHECK,CHECK-ACCESS +// RUN: %target-swift-frontend -emit-silgen %t/Client.swift -I %t -module-name Client -package-name mypkg -experimental-package-bypass-resilience -enable-library-evolution | %FileCheck %s --check-prefixes=CHECK,CHECK-ACCESS /// Utils can be built with both -enable-testing and -experimental-allow-non-resilient-access. // RUN: rm -rf %t/Utils.swiftmodule @@ -158,7 +158,7 @@ func foo() { // CHECK: sil hidden [ossa] @$s6Client3fooyyF : $@convention(thin) () -> () { // CHECK-DEFAULT: function_ref @$s5Utils9PkgStructV6pkgVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int // CHECK-DEFAULT: sil package_external @$s5Utils9PkgStructV6pkgVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int -// CHECK-BYPASS: struct_element_addr {{.*}} : $*PkgStruct, #PkgStruct.pkgVar +// CHECK-ACCESS: function_ref @$s5Utils9PkgStructV6pkgVarSivg // CHECK-NONRES: struct_extract {{.*}} : $PkgStruct, #PkgStruct.pkgVar func bar() { @@ -168,5 +168,5 @@ func bar() { // CHECK: sil hidden [ossa] @$s6Client3baryyF : $@convention(thin) () -> () { // CHECK-DEFAULT: function_ref @$s5Utils9PubStructV6pubVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int // CHECK-DEFAULT: sil @$s5Utils9PubStructV6pubVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int -// CHECK-BYPASS: struct_element_addr {{.*}} : $*PubStruct, #PubStruct.pubVar +// CHECK-ACCESS: function_ref @$s5Utils9PubStructV6pubVarSivg // CHECK-NONRES: struct_extract {{.*}} : $PubStruct, #PubStruct.pubVar diff --git a/test/SILGen/package_global_accessor.swift b/test/SILGen/package_global_accessor.swift new file mode 100644 index 0000000000000..99ce73482ef0c --- /dev/null +++ b/test/SILGen/package_global_accessor.swift @@ -0,0 +1,54 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-build-swift -module-name=Lib -package-name Pkg -I%t -emit-silgen %t/Lib.swift -o %t/Lib-nonres.sil +// RUN: %FileCheck %s --check-prefix=CHECK-NONRES < %t/Lib-nonres.sil +// RUN: %target-build-swift -module-name=Lib -package-name Pkg -I%t -emit-silgen -O -wmo %t/Lib.swift | %FileCheck %s --check-prefix=CHECK-NONRES +// RUN: %target-build-swift -module-name=Lib -package-name Pkg -I%t -emit-silgen %t/Lib.swift -enable-library-evolution -o %t/Lib-res.sil +// RUN: %FileCheck %s < %t/Lib-res.sil +// RUN: %target-build-swift -module-name=Lib -package-name Pkg -I%t -emit-silgen %t/Lib.swift -enable-library-evolution -O -wmo | %FileCheck %s +// RUN: %target-build-swift -module-name=Lib -package-name Pkg -I%t -emit-silgen %t/Lib.swift -enable-library-evolution -Xfrontend -experimental-allow-non-resilient-access -Xfrontend -experimental-package-cmo -O -wmo | %FileCheck %s + +// RUN: %target-build-swift -module-name=Lib -package-name Pkg -I%t -emit-module %t/Lib.swift -enable-library-evolution -Xfrontend -experimental-allow-non-resilient-access -Xfrontend -experimental-package-cmo -O -wmo -o %t/Lib.swiftmodule +// RUN: %target-build-swift -module-name=Client -package-name Pkg -I%t -emit-silgen %t/Client.swift -I %t | %FileCheck %s --check-prefix=CHECK-CLIENT + +//--- Client.swift +import Lib +public func client() { + /// Should not be calling S.x.unsafeMutableAddressor when accessing resilient global var; + /// instead, should be calling the opaque getter. + // CHECK-CLIENT-NOT: s3Lib1SV1xSSvau + // CHECK-CLIENT: function_ref @$s3Lib1SV1xSSvgZ + print(S.x) +} + +//--- Lib.swift +public struct S { + public static var x = "hello world" +} + +// one-time initialization token for x +// CHECK-NONRES: sil_global private @$s3Lib1SV1x_Wz : $Builtin.Word +// CHECK: sil_global private @$s3Lib1SV1x_Wz : $Builtin.Word + +// static S.x +// CHECK-NONRES: sil_global @$s3Lib1SV1xSSvpZ : $String +// CHECK: sil_global private @$s3Lib1SV1xSSvpZ : $String + +// one-time initialization function for x +// CHECK-NONRES: sil private [global_init_once_fn] [ossa] @$s3Lib1SV1x_WZ : $@convention(c) (Builtin.RawPointer) -> () { +// CHECK: sil private [global_init_once_fn] [ossa] @$s3Lib1SV1x_WZ : $@convention(c) (Builtin.RawPointer) -> () { + +// S.x.unsafeMutableAddressor +// CHECK-NONRES: sil [global_init] [ossa] @$s3Lib1SV1xSSvau : $@convention(thin) () -> Builtin.RawPointer { +// CHECK: sil hidden [global_init] [ossa] @$s3Lib1SV1xSSvau : $@convention(thin) () -> Builtin.RawPointer { +// CHECK: global_addr @$s3Lib1SV1x_Wz +// CHECK: address_to_pointer +// function_ref one-time initialization function for x +// CHECK: function_ref @$s3Lib1SV1x_WZ +// CHECK: global_addr @$s3Lib1SV1xSSvpZ +// CHECK: address_to_pointer + +// static S.x.getter +// CHECK-NONRES: sil [transparent] [serialized] [ossa] @$s3Lib1SV1xSSvgZ : $@convention(method) (@thin S.Type) -> @owned String { +// CHECK: sil [ossa] @$s3Lib1SV1xSSvgZ : $@convention(method) (@thin S.Type) -> @owned String { diff --git a/test/SILGen/preconcurrency_conformances.swift b/test/SILGen/preconcurrency_conformances.swift index e1c47378ca6aa..11041b5aa28d9 100644 --- a/test/SILGen/preconcurrency_conformances.swift +++ b/test/SILGen/preconcurrency_conformances.swift @@ -276,6 +276,39 @@ extension MyActor : @preconcurrency Q { // CHECK: [[CHECK_EXEC_REF:%.*]] = function_ref @$ss22_checkExpectedExecutor14_filenameStart01_D6Length01_D7IsASCII5_line9_executoryBp_BwBi1_BwBetF // CHECK-NEXT: {{.*}} = apply [[CHECK_EXEC_REF]]({{.*}}, [[EXEC]]) +// https://github.com/apple/swift/issues/74294 +protocol Parent { + func a() +} + +protocol Child : Parent { + func b() +} + +@MainActor +struct PreconcurrencyAppliesToParentToo : @preconcurrency Child { + func a() { + } + + func b() { + } +} + +// protocol witness for Child.b() in conformance PreconcurrencyAppliesToParentToo +// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s27preconcurrency_conformances32PreconcurrencyAppliesToParentTooVAA5ChildA2aDP1byyFTW : $@convention(witness_method: Child) (@in_guaranteed PreconcurrencyAppliesToParentToo) -> () +// CHECK: [[MAIN_ACTOR:%.*]] = begin_borrow {{.*}} : $MainActor +// CHECK-NEXT: [[EXEC:%.*]] = extract_executor [[MAIN_ACTOR]] : $MainActor +// CHECK: [[CHECK_EXEC_REF:%.*]] = function_ref @$ss22_checkExpectedExecutor14_filenameStart01_D6Length01_D7IsASCII5_line9_executoryBp_BwBi1_BwBetF +// CHECK-NEXT: {{.*}} = apply [[CHECK_EXEC_REF]]({{.*}}, [[EXEC]]) + + +// protocol witness for Parent.a() in conformance PreconcurrencyAppliesToParentToo +// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s27preconcurrency_conformances32PreconcurrencyAppliesToParentTooVAA0F0A2aDP1ayyFTW : $@convention(witness_method: Parent) (@in_guaranteed PreconcurrencyAppliesToParentToo) -> () +// CHECK: [[MAIN_ACTOR:%.*]] = begin_borrow {{.*}} : $MainActor +// CHECK-NEXT: [[EXEC:%.*]] = extract_executor [[MAIN_ACTOR]] : $MainActor +// CHECK: [[CHECK_EXEC_REF:%.*]] = function_ref @$ss22_checkExpectedExecutor14_filenameStart01_D6Length01_D7IsASCII5_line9_executoryBp_BwBi1_BwBetF +// CHECK-NEXT: {{.*}} = apply [[CHECK_EXEC_REF]]({{.*}}, [[EXEC]]) + //--- checks_disabled.swift protocol P { associatedtype T @@ -439,3 +472,29 @@ extension MyActor : @preconcurrency Q { // protocol witness for static Q.data.modify in conformance MyActor // CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s27preconcurrency_conformances7MyActorCAA1QA2aDP4dataSaySiGSgvMZTW : $@yield_once @convention(witness_method: Q) @substituted <τ_0_0> (@thick τ_0_0.Type) -> @yields @inout Optional> for // CHECK-NOT: [[CHECK_EXEC_REF:%.*]] = function_ref @$ss22_checkExpectedExecutor14_filenameStart01_D6Length01_D7IsASCII5_line9_executoryBp_BwBi1_BwBetF + +// https://github.com/apple/swift/issues/74294 +protocol Parent { + func a() +} + +protocol Child : Parent { + func b() +} + +@MainActor +struct PreconcurrencyAppliesToParentToo : @preconcurrency Child { + func a() { + } + + func b() { + } +} + +// protocol witness for Child.b() in conformance PreconcurrencyAppliesToParentToo +// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s27preconcurrency_conformances32PreconcurrencyAppliesToParentTooVAA5ChildA2aDP1byyFTW : $@convention(witness_method: Child) (@in_guaranteed PreconcurrencyAppliesToParentToo) -> () +// CHECK-NOT: [[CHECK_EXEC_REF:%.*]] = function_ref @$ss22_checkExpectedExecutor14_filenameStart01_D6Length01_D7IsASCII5_line9_executoryBp_BwBi1_BwBetF + +// protocol witness for Parent.a() in conformance PreconcurrencyAppliesToParentToo +// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s27preconcurrency_conformances32PreconcurrencyAppliesToParentTooVAA0F0A2aDP1ayyFTW : $@convention(witness_method: Parent) (@in_guaranteed PreconcurrencyAppliesToParentToo) -> () +// CHECK-NOT: [[CHECK_EXEC_REF:%.*]] = function_ref @$ss22_checkExpectedExecutor14_filenameStart01_D6Length01_D7IsASCII5_line9_executoryBp_BwBi1_BwBetF diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift index 7b3bd50a011db..ab429d86351cd 100644 --- a/test/SILGen/properties.swift +++ b/test/SILGen/properties.swift @@ -746,13 +746,9 @@ func addressOnlyNonmutatingProperty(_ x: AddressOnlyNonmutatingSet) } // CHECK-LABEL: sil hidden [ossa] @$s10properties30addressOnlyNonmutatingProperty{{[_0-9a-zA-Z]*}}F // CHECK: [[SET:%.*]] = function_ref @$s10properties25AddressOnlyNonmutatingSetV4propSivs -// CHECK: apply [[SET]]({{%.*}}, [[TMP:%[0-9]*]]) -// CHECK: destroy_addr [[TMP]] -// CHECK: dealloc_stack [[TMP]] +// CHECK: apply [[SET]]({{%.*}}, %0) // CHECK: [[GET:%.*]] = function_ref @$s10properties25AddressOnlyNonmutatingSetV4propSivg // CHECK: apply [[GET]]([[TMP:%[0-9]*]]) -// CHECK: destroy_addr [[TMP]] -// CHECK: dealloc_stack [[TMP]] protocol MakeAddressOnly {} struct AddressOnlyReadOnlySubscript { @@ -764,9 +760,8 @@ struct AddressOnlyReadOnlySubscript { // CHECK-LABEL: sil hidden [ossa] @$s10properties015addressOnlyReadC24SubscriptFromMutableBase // CHECK: [[BASE:%.*]] = alloc_box ${ var AddressOnlyReadOnlySubscript } // CHECK: copy_addr [[BASE:%.*]] to [init] [[COPY:%.*]] : -// CHECK: copy_addr [[COPY:%.*]] to [init] [[COPY2:%.*]] : // CHECK: [[GETTER:%.*]] = function_ref @$s10properties015AddressOnlyReadC9SubscriptV{{[_0-9a-zA-Z]*}}ig -// CHECK: apply [[GETTER]]({{%.*}}, [[COPY2]]) +// CHECK: apply [[GETTER]]({{%.*}}, [[COPY]]) func addressOnlyReadOnlySubscriptFromMutableBase(_ x: Int) { var base = AddressOnlyReadOnlySubscript() _ = base[x] @@ -834,13 +829,9 @@ protocol NonmutatingProtocol { // CHECK-NEXT: [[C_FIELD_COPY:%.*]] = alloc_stack $@opened("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: copy_addr [[C_FIELD_PAYLOAD]] to [init] [[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 [init] [[C_FIELD_BORROW]] // 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: [[RESULT_VALUE:%.*]] = apply [[GETTER]]<@opened("{{.*}}", any NonmutatingProtocol) Self>([[C_FIELD_COPY]]) : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int // 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("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: destroy_addr [[C_FIELD_BOX]] : $*any NonmutatingProtocol // CHECK-NEXT: dealloc_stack [[C_FIELD_BOX]] : $*any NonmutatingProtocol diff --git a/test/SILGen/protocol_extensions.swift b/test/SILGen/protocol_extensions.swift index 360f0fd03383d..88cc967033c09 100644 --- a/test/SILGen/protocol_extensions.swift +++ b/test/SILGen/protocol_extensions.swift @@ -507,20 +507,15 @@ func testExistentials1(_ p1: P1, b: Bool, i: Int64) { p1.f1() // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self - // CHECK: copy_addr [[POPENED]] to [init] [[POPENED_COPY:%.*]] : // CHECK: [[GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAEySbs5Int64Vcig - // 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: apply [[GETTER]]<@opened([[UUID]], any P1) Self>([[I]], [[POPENED]]) : $@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]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self - // CHECK: copy_addr [[POPENED]] to [init] [[POPENED_COPY:%.*]] : // CHECK: [[GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE4propSbvg - // CHECK: apply [[GETTER]]<@opened([[UUID]], any 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]]) : $@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 } @@ -541,15 +536,13 @@ func testExistentials2(_ p1: P1) { // CHECK: bb0([[P:%[0-9]+]] : $*any P1): func testExistentialsGetters(_ p1: P1) { // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self - // CHECK: copy_addr [[POPENED]] to [init] [[POPENED_COPY:%.*]] : // CHECK: [[FN:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAE5prop2Sbvg - // 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 + // CHECK: [[B:%[0-9]+]] = apply [[FN]]<@opened([[UUID]], any P1) Self>([[POPENED]]) : $@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]] : $*any P1 to $*@opened([[UUID:".*"]], any P1) Self - // CHECK: copy_addr [[POPENED]] to [init] [[POPENED_COPY:%.*]] : // CHECK: [[GETTER:%[0-9]+]] = function_ref @$s19protocol_extensions2P1PAAEyS2bcig - // 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 + // CHECK: apply [[GETTER]]<@opened([[UUID]], any P1) Self>([[B]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @in_guaranteed τ_0_0) -> Bool let b2: Bool = p1[b] } @@ -597,10 +590,8 @@ func testLogicalExistentialSetters(_ hasAP1: HasAP1, _ b: Bool) { // CHECK-NEXT: copy_addr [[HASP1]] to [init] [[PBHASP1]] : $*HasAP1 // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBHASP1]] // CHECK: [[P1_COPY:%[0-9]+]] = alloc_stack $any P1 - // CHECK-NEXT: [[HASP1_COPY:%[0-9]+]] = alloc_stack $HasAP1 - // CHECK-NEXT: copy_addr [[WRITE]] to [init] [[HASP1_COPY]] : $*HasAP1 // 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: [[RESULT:%[0-9]+]] = apply [[SOMEP1_GETTER]]([[P1_COPY]], [[WRITE]]) : $@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]], any P1) Self>([[B]], [[P1_OPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> () diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift index e21da956db147..4e9a78a57412d 100644 --- a/test/SILGen/protocols.swift +++ b/test/SILGen/protocols.swift @@ -28,13 +28,9 @@ func use_subscript_rvalue_get(_ i : Int) -> Int { // CHECK: [[ALLOCSTACK:%[0-9]+]] = alloc_stack $[[OPENED]] // CHECK: copy_addr [[PROJ]] to [init] [[ALLOCSTACK]] : $*[[OPENED]] // CHECK-NEXT: end_access [[READ]] : $*any SubscriptableGet -// CHECK-NEXT: [[TMP:%.*]] = alloc_stack -// CHECK-NEXT: copy_addr [[ALLOCSTACK]] to [init] [[TMP]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGet.subscript!getter -// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[METH]]<[[OPENED]]>(%0, [[TMP]]) -// CHECK-NEXT: destroy_addr [[TMP]] +// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[METH]]<[[OPENED]]>(%0, [[ALLOCSTACK]]) // CHECK-NEXT: destroy_addr [[ALLOCSTACK]] -// CHECK-NEXT: dealloc_stack [[TMP]] // CHECK-NEXT: dealloc_stack [[ALLOCSTACK]] : $*[[OPENED]] // CHECK-NEXT: return [[RESULT]] @@ -47,13 +43,9 @@ func use_subscript_lvalue_get(_ i : Int) -> Int { // 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 [init] [[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: [[RESULT:%[0-9]+]] = apply [[METH]]<[[OPENED]]>(%0, [[PROJ]]) // CHECK-NEXT: end_access [[READ]] : $*any SubscriptableGetSet -// CHECK-NEXT: dealloc_stack [[ALLOCSTACK]] : $*[[OPENED]] // CHECK-NEXT: return [[RESULT]] func use_subscript_lvalue_set(_ i : Int) { @@ -78,12 +70,8 @@ func use_subscript_archetype_rvalue_get(_ generic : T, idx } // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_subscript_archetype_rvalue_get // CHECK: bb0(%0 : $*T, %1 : $Int): -// CHECK: [[STACK:%[0-9]+]] = alloc_stack $T -// CHECK: copy_addr %0 to [init] [[STACK]] // CHECK: [[METH:%[0-9]+]] = witness_method $T, #SubscriptableGet.subscript!getter -// CHECK-NEXT: apply [[METH]](%1, [[STACK]]) -// CHECK-NEXT: destroy_addr [[STACK]] : $*T -// CHECK-NEXT: dealloc_stack [[STACK]] : $*T +// CHECK-NEXT: apply [[METH]](%1, %0) // CHECK: } // end sil function '${{.*}}use_subscript_archetype_rvalue_get @@ -93,13 +81,9 @@ func use_subscript_archetype_lvalue_get(_ generic: inou // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_subscript_archetype_lvalue_get // CHECK: bb0(%0 : $*T, %1 : $Int): // CHECK: [[READ:%.*]] = begin_access [read] [unknown] %0 : $*T -// CHECK: [[GUARANTEEDSTACK:%[0-9]+]] = alloc_stack $T -// CHECK: copy_addr [[READ]] to [init] [[GUARANTEEDSTACK]] : $*T // CHECK: [[METH:%[0-9]+]] = witness_method $T, #SubscriptableGetSet.subscript!getter -// CHECK-NEXT: [[APPLYRESULT:%[0-9]+]] = apply [[METH]](%1, [[GUARANTEEDSTACK]]) -// CHECK-NEXT: destroy_addr [[GUARANTEEDSTACK]] : $*T +// CHECK-NEXT: [[APPLYRESULT:%[0-9]+]] = apply [[METH]](%1, [[READ]]) // CHECK-NEXT: end_access [[READ]] -// CHECK-NEXT: dealloc_stack [[GUARANTEEDSTACK]] : $*T // CHECK: return [[APPLYRESULT]] @@ -139,10 +123,8 @@ func use_property_rvalue_get() -> Int { // CHECK: [[COPY:%.*]] = alloc_stack $[[OPENED]] // CHECK-NEXT: copy_addr [[PROJ]] to [init] [[COPY]] : $*[[OPENED]] // CHECK-NEXT: end_access [[READ]] : $*any PropertyWithGetter -// CHECK: [[BORROW:%.*]] = alloc_stack $[[OPENED]] -// CHECK-NEXT: copy_addr [[COPY]] to [init] [[BORROW]] : $*[[OPENED]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetter.a!getter -// CHECK-NEXT: apply [[METH]]<[[OPENED]]>([[BORROW]]) +// CHECK-NEXT: apply [[METH]]<[[OPENED]]>([[COPY]]) func use_property_lvalue_get() -> Int { return propertyGetSet.b @@ -151,10 +133,8 @@ func use_property_lvalue_get() -> Int { // 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 [init] [[STACK]] // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetterSetter.b!getter -// CHECK-NEXT: apply [[METH]]<[[OPENED]]>([[STACK]]) +// CHECK: apply [[METH]]<[[OPENED]]>([[PROJ]]) func use_property_lvalue_set(_ x : Int) { propertyGetSet.b = x @@ -178,12 +158,8 @@ func use_property_archetype_rvalue_get(_ generic : T) -> // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_property_archetype_rvalue_get // CHECK: bb0(%0 : $*T): -// CHECK: [[STACK:%[0-9]+]] = alloc_stack $T -// CHECK: copy_addr %0 to [init] [[STACK]] // CHECK: [[METH:%[0-9]+]] = witness_method $T, #PropertyWithGetter.a!getter -// CHECK-NEXT: apply [[METH]]([[STACK]]) -// CHECK-NEXT: destroy_addr [[STACK]] -// CHECK-NEXT: dealloc_stack [[STACK]] +// CHECK-NEXT: apply [[METH]](%0) // CHECK: } // end sil function '{{.*}}use_property_archetype_rvalue_get @@ -193,12 +169,8 @@ func use_property_archetype_lvalue_get(_ generic : // CHECK-LABEL: sil hidden [ossa] @{{.*}}use_property_archetype_lvalue_get // CHECK: bb0(%0 : $*T): -// CHECK: [[STACK:%[0-9]+]] = alloc_stack $T -// CHECK: copy_addr %0 to [init] [[STACK]] : $*T // CHECK: [[METH:%[0-9]+]] = witness_method $T, #PropertyWithGetterSetter.b!getter -// CHECK-NEXT: apply [[METH]]([[STACK]]) -// CHECK-NEXT: destroy_addr [[STACK]] : $*T -// CHECK-NEXT: dealloc_stack [[STACK]] : $*T +// CHECK-NEXT: apply [[METH]](%0) // CHECK: } // end sil function '${{.*}}use_property_archetype_lvalue_get @@ -382,18 +354,12 @@ 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 $any PropertyWithGetterSetter -// CHECK: [[T_TEMP:%.*]] = alloc_stack $T -// CHECK: copy_addr [[READ]] to [init] [[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: apply [[P_GETTER]]([[P_TEMP]], [[READ]]) // 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 [init] [[T0]] // CHECK-NEXT: [[B_GETTER:%.*]] = witness_method $[[P_OPENED]], #PropertyWithGetterSetter.b!getter -// CHECK-NEXT: apply [[B_GETTER]]<[[P_OPENED]]>([[T0]]) +// CHECK-NEXT: apply [[B_GETTER]]<[[P_OPENED]]>([[OPEN]]) // CHECK-NEXT: debug_value -// CHECK-NEXT: destroy_addr [[T0]] // CHECK-NOT: witness_method // CHECK: return @@ -438,10 +404,8 @@ 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("{{.*}}", any SelfReturningSubscript) Self - // CHECK: copy_addr [[OPEN]] to [init] [[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]]) + // CHECK: apply [[WIT_M]]<@opened("{{.*}}", any SelfReturningSubscript) Self>({{%.*}}, {{%.*}}, [[OPEN]]) _ = [String: SelfReturningSubscript]().mapValues { $0[2] } } diff --git a/test/SILGen/struct_resilience.swift b/test/SILGen/struct_resilience.swift index 2dc310e3554af..2587e3bccf4a5 100644 --- a/test/SILGen/struct_resilience.swift +++ b/test/SILGen/struct_resilience.swift @@ -16,17 +16,15 @@ func functionWithResilientTypes(_ s: Size, f: (Size) -> Size) -> Size { // CHECK: copy_addr %1 to [init] [[OTHER_SIZE_BOX:%[0-9]*]] : $*Size var s2 = s -// CHECK: copy_addr %1 to [init] [[SIZE_BOX:%.*]] : $*Size // CHECK: [[GETTER:%.*]] = function_ref @$s16resilient_struct4SizeV1wSivg : $@convention(method) (@in_guaranteed Size) -> Int -// CHECK: [[RESULT:%.*]] = apply [[GETTER]]([[SIZE_BOX]]) +// CHECK: [[RESULT:%.*]] = apply [[GETTER]](%1) // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[OTHER_SIZE_BOX]] : $*Size // CHECK: [[SETTER:%.*]] = function_ref @$s16resilient_struct4SizeV1wSivs : $@convention(method) (Int, @inout Size) -> () // CHECK: apply [[SETTER]]([[RESULT]], [[WRITE]]) s2.w = s.w -// CHECK: copy_addr %1 to [init] [[SIZE_BOX:%.*]] : $*Size // CHECK: [[FN:%.*]] = function_ref @$s16resilient_struct4SizeV1hSivg : $@convention(method) (@in_guaranteed Size) -> Int -// CHECK: [[RESULT:%.*]] = apply [[FN]]([[SIZE_BOX]]) +// CHECK: [[RESULT:%.*]] = apply [[FN]](%1) _ = s.h // CHECK: apply {{.*}}(%0, %1) @@ -162,13 +160,8 @@ public func functionWithMyResilientTypes(_ s: MySize, f: (MySize) -> MySize) -> // Since the body of a public transparent function might be inlined into // other resilience domains, we have to use accessors -// CHECK: [[SELF:%.*]] = alloc_stack $MySize -// CHECK-NEXT: copy_addr %0 to [init] [[SELF]] - // CHECK: [[GETTER:%.*]] = function_ref @$s17struct_resilience6MySizeV1wSivg -// CHECK-NEXT: [[RESULT:%.*]] = apply [[GETTER]]([[SELF]]) -// CHECK-NEXT: destroy_addr [[SELF]] -// CHECK-NEXT: dealloc_stack [[SELF]] +// CHECK-NEXT: [[RESULT:%.*]] = apply [[GETTER]](%0) // CHECK-NEXT: return [[RESULT]] return s.w } @@ -203,13 +196,8 @@ public func functionWithMyResilientTypes(_ s: MySize, f: (MySize) -> MySize) -> // Since the body of a public transparent function might be inlined into // other resilience domains, we have to use accessors -// CHECK: [[SELF:%.*]] = alloc_stack $MySize -// CHECK-NEXT: copy_addr %0 to [init] [[SELF]] - // CHECK: [[GETTER:%.*]] = function_ref @$s17struct_resilience6MySizeV1wSivg -// CHECK-NEXT: [[RESULT:%.*]] = apply [[GETTER]]([[SELF]]) -// CHECK-NEXT: destroy_addr [[SELF]] -// CHECK-NEXT: dealloc_stack [[SELF]] +// CHECK-NEXT: [[RESULT:%.*]] = apply [[GETTER]](%0) // CHECK-NEXT: return [[RESULT]] return s.w diff --git a/test/SILGen/struct_resilience_testable.swift b/test/SILGen/struct_resilience_testable.swift index 4533010d86336..d79f4615afc46 100644 --- a/test/SILGen/struct_resilience_testable.swift +++ b/test/SILGen/struct_resilience_testable.swift @@ -5,12 +5,8 @@ @testable import resilient_struct // CHECK-LABEL: sil [ossa] @$s26struct_resilience_testable37takesResilientStructWithInternalFieldySi010resilient_A00eghI0VF : $@convention(thin) (@in_guaranteed ResilientWithInternalField) -> Int -// CHECK: [[COPY:%.*]] = alloc_stack $ResilientWithInternalField -// CHECK: copy_addr %0 to [init] [[COPY]] : $*ResilientWithInternalField // CHECK: [[FN:%.*]] = function_ref @$s16resilient_struct26ResilientWithInternalFieldV1xSivg : $@convention(method) (@in_guaranteed ResilientWithInternalField) -> Int -// CHECK: [[RESULT:%.*]] = apply [[FN]]([[COPY]]) -// CHECK: destroy_addr [[COPY]] -// CHECK: dealloc_stack [[COPY]] +// CHECK: [[RESULT:%.*]] = apply [[FN]](%0) // CHECK: return [[RESULT]] public func takesResilientStructWithInternalField(_ s: ResilientWithInternalField) -> Int { diff --git a/test/SILGen/synthesized_conformance_enum.swift b/test/SILGen/synthesized_conformance_enum.swift index f1bf4d753777f..c168af1dea93b 100644 --- a/test/SILGen/synthesized_conformance_enum.swift +++ b/test/SILGen/synthesized_conformance_enum.swift @@ -56,6 +56,7 @@ extension Enum: Codable where T: Codable {} extension NoValues: CaseIterable {} // CHECK-LABEL: // static NoValues.allCases.getter +// CHECK-NEXT: // Isolation: nonisolated // CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum8NoValuesO8allCasesSayACGvgZ : $@convention(method) (@thin NoValues.Type) -> @owned Array { extension NoValues: Codable {} diff --git a/test/SILGen/typed_throws_generic.swift b/test/SILGen/typed_throws_generic.swift index 4ddd7eb945309..7bb95b4b53d37 100644 --- a/test/SILGen/typed_throws_generic.swift +++ b/test/SILGen/typed_throws_generic.swift @@ -1,5 +1,7 @@ // RUN: %target-swift-emit-silgen %s -enable-experimental-feature FullTypedThrows | %FileCheck %s +// REQUIRES: asserts + public func genericThrow(e: E) throws(E) { throw e } diff --git a/test/SILGen/typelowering_inverses.swift b/test/SILGen/typelowering_inverses.swift index fc6a4b235d298..cf1b383e7c448 100644 --- a/test/SILGen/typelowering_inverses.swift +++ b/test/SILGen/typelowering_inverses.swift @@ -15,14 +15,14 @@ enum RudeEnum: Copyable { struct CondCopyableStruct: ~Copyable {} -extension CondCopyableStruct: Copyable {} +extension CondCopyableStruct: Copyable where T: Copyable {} enum CondCopyableEnum: ~Copyable { case some(T) case none } -extension CondCopyableEnum: Copyable {} +extension CondCopyableEnum: Copyable where T: Copyable {} protocol NoEscapeP: ~Escapable {} @@ -39,14 +39,14 @@ enum TooRudeEnum: Escapable { struct CondEscapableStruct: ~Escapable {} -extension CondEscapableStruct: Escapable {} +extension CondEscapableStruct: Escapable where T: Escapable {} enum CondEscapableEnum: ~Escapable { case some(T) case none } -extension CondEscapableEnum: Escapable {} +extension CondEscapableEnum: Escapable where T: Escapable {} // MARK: ensure certain conditionally Copyable types are treated as trivial (no ownership in func signature). @@ -142,18 +142,18 @@ struct MyStruct: ~Copyable & ~Escapable { var x: T } -extension MyStruct: Copyable where T: Copyable & ~Escapable {} +extension MyStruct: Copyable where T: Copyable {} -extension MyStruct: Escapable where T: Escapable & ~Copyable {} +extension MyStruct: Escapable where T: Escapable {} enum MyEnum: ~Copyable & ~Escapable { case x(T) case knoll } -extension MyEnum: Copyable where T: Copyable & ~Escapable {} +extension MyEnum: Copyable where T: Copyable {} -extension MyEnum: Escapable where T: Escapable & ~Copyable {} +extension MyEnum: Escapable where T: Escapable {} enum Trivial { case a, b, c diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift index 59e370019bafe..83bb26401df82 100644 --- a/test/SILOptimizer/access_marker_verify.swift +++ b/test/SILOptimizer/access_marker_verify.swift @@ -272,19 +272,15 @@ func testInitLValue(p: HasIntGetter) -> Int { // CHECK: alloc_box ${ var Int }, var, name "x" // CHECK: [[PROJ:%.*]] = project_box // CHECK: [[OPENED:%.*]] = open_existential_addr immutable_access %0 -// CHECK: [[X:%.*]] = alloc_stack $@opened -// CHECK-NOT: begin_access -// CHECK: copy_addr %{{.*}} to [init] [[X]] : $*@opened // CHECK: witness_method $@opened -// CHECK: apply %{{.*}}<@opened("{{.*}}", any HasIntGetter) Self>([[X]]) : $@convention(witness_method: HasIntGetter) <τ_0_0 where τ_0_0 : HasIntGetter> (@in_guaranteed τ_0_0) -> Int +// CHECK: [[VALUE:%.*]] = apply %{{.*}}<@opened("{{.*}}", any HasIntGetter) Self>([[OPENED]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[PROJ]] : $*Int -// CHECK: store %{{.*}} to [trivial] [[ACCESS]] : $*Int -// CHECK: end_access -// CHECK: destroy_addr -// CHECK: dealloc_stack -// CHECK: begin_access [read] [unknown] [[PROJ]] -// CHECK: load [trivial] -// CHECK: end_access +// CHECK: store [[VALUE]] to [trivial] [[ACCESS]] : $*Int +// CHECK: end_access [[ACCESS]] +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJ]] +// CHECK: [[RELOAD:%.*]] = load [trivial] [[ACCESS]] +// CHECK: end_access [[ACCESS]] +// CHECK: return [[RELOAD]] // CHECK-LABEL: } // end sil function '$s20access_marker_verify14testInitLValue1pSiAA12HasIntGetter_p_tF' // --- initialize let. @@ -868,19 +864,11 @@ func testMixedTuple(p: HasClassGetter) -> (BaseClass, Any) { // 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 [init] [[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: [[OUTC:%.*]] = apply %{{.*}}<@opened("{{.*}}", any HasClassGetter) Self>([[P1]]) // 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 [init] [[TEMP2]] : $*@opened -// CHECK-NOT: begin_access -// CHECK: apply {{.*}} $@convention(witness_method: HasClassGetter) <τ_0_0 where τ_0_0 : HasClassGetter> (@in_guaranteed τ_0_0) -> @owned BaseClass +// CHECK: [[R2:%.*]] = apply %{{.*}}<@opened("{{.*}}", any HasClassGetter) Self>([[P2]]) // CHECK: [[OUTANY:%.*]] = init_existential_addr %0 : $*Any, $BaseClass -// CHECK: store %{{.*}} to [init] [[OUTANY]] : $*BaseClass +// CHECK: store [[R2]] to [init] [[OUTANY]] : $*BaseClass // CHECK: return [[OUTC]] : $BaseClass // CHECK-LABEL: } // end sil function '$s20access_marker_verify14testMixedTuple1pAA9BaseClassC_yptAA03HasH6Getter_p_tF' diff --git a/test/SILOptimizer/closure_specialize.sil b/test/SILOptimizer/closure_specialize.sil index b9c1d26e75104..fee8348f653fe 100644 --- a/test/SILOptimizer/closure_specialize.sil +++ b/test/SILOptimizer/closure_specialize.sil @@ -938,3 +938,35 @@ bb0(%0 : $Int): %empty = tuple () return %empty : $() } + +struct NC : ~Copyable { + deinit {} +} + +sil hidden [noinline] @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () { +bb0(%0 : $NC): + %retval = tuple () + return %retval : $() +} + +sil hidden [noinline] @use_noncopyable_arg_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () { +bb0(%0 : $@noescape @callee_guaranteed () -> ()): + %2 = apply %0() : $@noescape @callee_guaranteed () -> () + %3 = tuple () + return %3 : $() +} + +// Ensure that a retain_value of a noncopyable value isn't created. +// CHECK-LABEL: sil @dont_specialize_noncopyable_arg_closure : {{.*}} { +// CHECK-NOT: retain_value {{%.*}} : $NC +// CHECK-LABEL: } // end sil function 'dont_specialize_noncopyable_arg_closure' +sil @dont_specialize_noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () { +bb0(%nc : $NC): + %closure_fn = function_ref @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () + %closure = partial_apply [callee_guaranteed] [on_stack] %closure_fn(%nc) : $@convention(thin) (@guaranteed NC) -> () + %use = function_ref @use_noncopyable_arg_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () + apply %use(%closure) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () + dealloc_stack %closure : $@noescape @callee_guaranteed () -> () + %11 = tuple () + return %11 : $() +} diff --git a/test/SILOptimizer/consume_operator_kills_copyable_addressonly_lets.swift b/test/SILOptimizer/consume_operator_kills_copyable_addressonly_lets.swift index 5509810ed33f5..d1eee7c416328 100644 --- a/test/SILOptimizer/consume_operator_kills_copyable_addressonly_lets.swift +++ b/test/SILOptimizer/consume_operator_kills_copyable_addressonly_lets.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -verify %s -parse-stdlib -emit-sil -o /dev/null +// RUN: %target-swift-frontend -sil-verify-all -verify %s -parse-stdlib -emit-sil -o /dev/null import Swift @@ -146,8 +146,8 @@ public func conditionalBadConsumingUseLoop2(_ x: T) { // Parameters // This is ok, no uses after. -public func simpleMoveOfParameter(_ x: T) -> () { - let _ = consume x +public func simpleMoveOfParameter(_ x: T) -> () { // expected-error {{'x' is borrowed and cannot be consumed}} + let _ = consume x // expected-note {{consumed here}} } public func simpleMoveOfOwnedParameter(_ x: __owned T) -> () { @@ -214,12 +214,12 @@ func consumeOwned(_ k: __owned T) { _ = consume k } -func consumeShared(_ k: __shared T) { - _ = consume k +func consumeShared(_ k: __shared T) { // expected-error {{'k' is borrowed and cannot be consumed}} + _ = consume k // expected-note {{consumed here}} } -func consumeBare(_ k: T) { - _ = consume k +func consumeBare(_ k: T) { // expected-error {{'k' is borrowed and cannot be consumed}} + _ = consume k // expected-note {{consumed here}} } //////////////////////// @@ -384,6 +384,20 @@ public func castTestIfLet2(_ x : __owned EnumWithKlass) { // expected-error {{'x } } +enum rdar125817827 { + case a(A) + case b(B) +} + +extension rdar125817827 { + func foo() { // expected-error {{'self' is borrowed and cannot be consumed}} + switch consume self { // expected-note {{consumed here}} + case let .a(a): print(a) + case let .b(b): print(b) + } + } +} + ///////////////////////// // Partial Apply Tests // ///////////////////////// diff --git a/test/SILOptimizer/definite_init_flow_sensitive_actor_self.swift b/test/SILOptimizer/definite_init_flow_sensitive_actor_self.swift new file mode 100644 index 0000000000000..c3536e291d7f8 --- /dev/null +++ b/test/SILOptimizer/definite_init_flow_sensitive_actor_self.swift @@ -0,0 +1,32 @@ +// RUN: %target-swift-frontend -emit-sil %s -module-name test -swift-version 5 -sil-verify-all | %FileCheck %s +// REQUIRES: concurrency + +@available(SwiftStdlib 5.1, *) +func f(isolatedTo actor: isolated (any Actor)?) async -> Int { 0 } + +@available(SwiftStdlib 5.1, *) +actor A { + let number: Int + + // CHECK-LABEL: sil hidden{{.*}}@$s4test1ACACyYacfc : $@convention(method) @async (@sil_isolated @owned A) -> @owned A + init() async { + // First use of #isolation, which is replaced by 'nil'. + // CHECK: [[ISOLATION_1:%.*]] = enum $Optional, #Optional.none!enumelt + // CHECK: [[F_1:%.*]] = function_ref @$s4test1f10isolatedToSiScA_pSgYi_tYaF + // CHECK-NEXT: [[F_RESULT:%.*]] = apply [[F_1]]([[ISOLATION_1]]) + + // Assignment to "number" of the result. + // CHECK: [[NUMBER:%.*]] = ref_element_addr {{%.*}} : $A, #A.number + // CHECK: store [[F_RESULT]] to [[NUMBER]] + self.number = await f(isolatedTo: #isolation) + + // Second use of #isolation, which uses 'self' injected into (any Actor)?. + // CHECK: [[ACTOR_COPY:%.*]] = end_init_let_ref %0 : $A + // CHECK: strong_retain [[ACTOR_COPY]] : $A + // CHECK: [[ACTOR_EXISTENTIAL:%.*]] = init_existential_ref [[ACTOR_COPY]] : $A : $A, $any Actor + // CHECK: [[ISOLATION_2:%.*]] = enum $Optional, #Optional.some!enumelt, [[ACTOR_EXISTENTIAL]] + // CHECK: [[F_2:%.*]] = function_ref @$s4test1f10isolatedToSiScA_pSgYi_tYaF + // CHECK-NEXT: apply [[F_2]]([[ISOLATION_2]]) + _ = await f(isolatedTo: #isolation) + } +} diff --git a/test/SILOptimizer/definite_init_flow_sensitive_distributed_actor_self.swift b/test/SILOptimizer/definite_init_flow_sensitive_distributed_actor_self.swift new file mode 100644 index 0000000000000..48951bc5ede08 --- /dev/null +++ b/test/SILOptimizer/definite_init_flow_sensitive_distributed_actor_self.swift @@ -0,0 +1,37 @@ +// RUN: %target-swift-frontend -emit-sil %s -module-name test -swift-version 5 -sil-verify-all | %FileCheck %s +// REQUIRES: concurrency, distributed + +import Distributed + +@available(SwiftStdlib 5.1, *) +func f(isolatedTo actor: isolated (any Actor)?) async -> Int { 0 } + +@available(SwiftStdlib 5.7, *) +distributed actor NotCodableDA + where ActorSystem: DistributedActorSystem { + let number: Int + + // CHECK-LABEL: sil hidden{{.*}}@$s4test12NotCodableDAC11actorSystemACyxGx_tYacfc : $@convention(method) @async (@in ActorSystem, @sil_isolated @owned NotCodableDA) -> @owned NotCodableDA { + init(actorSystem: ActorSystem) async { + self.actorSystem = actorSystem + + // First use of #isolation, which is replaced by 'nil'. + // CHECK: [[ISOLATION_1:%.*]] = enum $Optional, #Optional.none!enumelt + // CHECK: [[F_1:%.*]] = function_ref @$s4test1f10isolatedToSiScA_pSgYi_tYaF + // CHECK-NEXT: [[F_RESULT:%.*]] = apply [[F_1]]([[ISOLATION_1]]) + + // Assignment to "number" of the result. + // CHECK: [[NUMBER:%.*]] = ref_element_addr {{%.*}} : $NotCodableDA, #NotCodableDA.number + // CHECK: store [[F_RESULT]] to [[NUMBER]] + self.number = await f(isolatedTo: #isolation) + + // Second use of #isolation, which uses 'self.asLocalActor'' + // CHECK: [[AS_LOCAL_ACTOR_FN:%.*]] = function_ref @$s11Distributed0A5ActorPAAE07asLocalB0ScA_pvg : $@convention(method) <τ_0_0 where τ_0_0 : DistributedActor> (@sil_isolated @guaranteed τ_0_0) -> @owned any Actor + // CHECK-NEXT: [[ACTOR_EXISTENTIAL:%.*]] = apply [[AS_LOCAL_ACTOR_FN]]>(%1) : $@convention(method) <τ_0_0 where τ_0_0 : DistributedActor> (@sil_isolated @guaranteed τ_0_0) -> @owned any Actor + // CHECK: [[ISOLATION_2:%.*]] = enum $Optional, #Optional.some!enumelt, [[ACTOR_EXISTENTIAL]] + // CHECK: [[F_2:%.*]] = function_ref @$s4test1f10isolatedToSiScA_pSgYi_tYaF + // CHECK-NEXT: apply [[F_2]]([[ISOLATION_2]]) + + _ = await f(isolatedTo: #isolation) + } +} diff --git a/test/SILOptimizer/lifetime_dependence.sil b/test/SILOptimizer/lifetime_dependence.sil index 6bbe541698c24..46cdbef3ca8c2 100644 --- a/test/SILOptimizer/lifetime_dependence.sil +++ b/test/SILOptimizer/lifetime_dependence.sil @@ -7,7 +7,7 @@ // REQUIRES: asserts // REQUIRES: swift_in_compiler -// Test the SIL representation for lifetime depenence. +// Test the SIL representation for lifetime dependence. sil_stage raw @@ -18,6 +18,7 @@ class C {} struct Nonescapable: ~Escapable {} sil @c_dependence : $@convention(thin) (@guaranteed C) -> _scope(0) @owned Nonescapable +sil @immortal_dependence : $@convention(thin) () -> _scope(immortal) @owned Nonescapable // Test that SILType.isEscpable does not crash on a generic box when NoncopyableGenerics is enabled. sil shared [serialized] [ossa] @testLocalFunc : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> () { @@ -42,3 +43,12 @@ bb0(%0 : @owned $C): %28 = tuple () return %28 : $() } + +sil [ossa] @test_immortal_dependence : $@convention(thin) () -> () { +bb0: + %f = function_ref @immortal_dependence : $@convention(thin) () -> _scope(immortal) @owned Nonescapable + %c = apply %f() : $@convention(thin) () -> _scope(immortal) @owned Nonescapable + destroy_value %c : $Nonescapable + %t = tuple () + return %t : $() +} diff --git a/test/SILOptimizer/lifetime_dependence_optional.swift b/test/SILOptimizer/lifetime_dependence_optional.swift index f0c7c5cc3ac8b..9b1761110a744 100644 --- a/test/SILOptimizer/lifetime_dependence_optional.swift +++ b/test/SILOptimizer/lifetime_dependence_optional.swift @@ -21,9 +21,9 @@ public enum Nillable: ~Copyable & ~Escapable { case some(Wrapped) } -extension Nillable: Copyable where Wrapped: ~Escapable /* & Copyable */ {} +extension Nillable: Copyable where Wrapped: Copyable {} -extension Nillable: Escapable where Wrapped: ~Copyable /* & Escapable */ {} +extension Nillable: Escapable where Wrapped: Escapable {} extension Nillable: Sendable where Wrapped: ~Copyable & ~Escapable & Sendable { } diff --git a/test/SILOptimizer/moveonly_accessors.swift b/test/SILOptimizer/moveonly_accessors.swift new file mode 100644 index 0000000000000..4ee5df91ce580 --- /dev/null +++ b/test/SILOptimizer/moveonly_accessors.swift @@ -0,0 +1,24 @@ +// RUN: %target-swift-frontend -sil-verify-all -verify -emit-sil %s + +struct AO { + borrowing func borrow2Borrow() -> Int { p1 } + borrowing func borrow2Consume() -> Int { // expected-error{{'self' is borrowed and cannot be consumed}} + p2 // expected-note{{consumed here}} + } + consuming func consume2Borrow() -> Int { p1 } + consuming func consume2Consume() -> Int { p2 } + let t: T + var p1 : Int { borrowing get { 666 } } + var p2: Int { consuming get { 666 } } +} + +// https://github.com/apple/swift/issues/73292 +struct Example { + protocol Proto { + var count: Int { borrowing get } + } + + func takeProto(_ p: borrowing some Proto) -> Int { + p.count + } +} diff --git a/test/SILOptimizer/moveonly_addresschecker.swift b/test/SILOptimizer/moveonly_addresschecker.swift index 35c2c9ce2c336..8752373ccf3f9 100644 --- a/test/SILOptimizer/moveonly_addresschecker.swift +++ b/test/SILOptimizer/moveonly_addresschecker.swift @@ -1,7 +1,5 @@ // RUN: %target-swift-emit-sil -sil-verify-all -verify -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses %s -Xllvm -sil-print-final-ossa-module | %FileCheck %s // RUN: %target-swift-emit-sil -O -sil-verify-all -verify -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses %s -// RUN: %target-swift-emit-sil -sanitize=thread -sil-verify-all -verify -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses %s -Xllvm -sil-print-final-ossa-module | %FileCheck %s -// RUN: %target-swift-emit-sil -sanitize=thread -O -sil-verify-all -verify -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses %s // This file contains tests that used to crash due to verifier errors. It must // be separate from moveonly_addresschecker_diagnostics since when we fail on diff --git a/test/SILOptimizer/moveonly_addresschecker_branch_order.swift b/test/SILOptimizer/moveonly_addresschecker_branch_order.swift new file mode 100644 index 0000000000000..9ef305a81b2f8 --- /dev/null +++ b/test/SILOptimizer/moveonly_addresschecker_branch_order.swift @@ -0,0 +1,26 @@ +//RUN: %target-swift-frontend -emit-sil -verify %s + +@_silgen_name("cond") +func cond() -> Bool + +struct Foo: ~Copyable {} + +func consume(_: consuming Foo) {} + +func test1(_ x: inout Foo, _ y: consuming Foo) { // expected-error{{missing reinitialization}} + consume(x) // expected-note{{consumed here}} + if cond() { + return + } else { + x = y + } +} + +func test2(_ x: inout Foo, _ y: consuming Foo) { // expected-error{{missing reinitialization}} + consume(x) // expected-note{{consumed here}} + if cond() { + x = y + } else { + return + } +} diff --git a/test/SILOptimizer/moveonly_addresschecker_destructure_through_deinit_diagnostics.swift b/test/SILOptimizer/moveonly_addresschecker_destructure_through_deinit_diagnostics.swift index f4982dbcf2e16..bb16dcbe55fb8 100644 --- a/test/SILOptimizer/moveonly_addresschecker_destructure_through_deinit_diagnostics.swift +++ b/test/SILOptimizer/moveonly_addresschecker_destructure_through_deinit_diagnostics.swift @@ -1,5 +1,4 @@ // RUN: %target-swift-emit-sil -sil-verify-all -verify -enable-experimental-feature MoveOnlyClasses -enable-experimental-feature MoveOnlyTuples %s -// RUN: %target-swift-emit-sil -sanitize=thread -sil-verify-all -verify -enable-experimental-feature MoveOnlyClasses -enable-experimental-feature MoveOnlyTuples %s // This test validates that we properly emit errors if we partially invalidate // through a type with a deinit. diff --git a/test/SILOptimizer/moveonly_addresschecker_diagnostics.swift b/test/SILOptimizer/moveonly_addresschecker_diagnostics.swift index b7bdb08ad92f6..d3e49974c1a30 100644 --- a/test/SILOptimizer/moveonly_addresschecker_diagnostics.swift +++ b/test/SILOptimizer/moveonly_addresschecker_diagnostics.swift @@ -1,5 +1,4 @@ // RUN: %target-swift-emit-sil %s -O -sil-verify-all -verify -enable-experimental-feature MoveOnlyPartialReinitialization -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses -// RUN: %target-swift-emit-sil -sanitize=thread %s -O -sil-verify-all -verify -enable-experimental-feature MoveOnlyPartialReinitialization -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses ////////////////// // Declarations // diff --git a/test/SILOptimizer/moveonly_addresschecker_tsan.swift b/test/SILOptimizer/moveonly_addresschecker_tsan.swift new file mode 100644 index 0000000000000..81e20f9f083ad --- /dev/null +++ b/test/SILOptimizer/moveonly_addresschecker_tsan.swift @@ -0,0 +1,38 @@ +// RUN: %target-swift-emit-sil -sanitize=thread -sil-verify-all -verify -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses %s -Xllvm -sil-print-final-ossa-module | %FileCheck %s +// RUN: %target-swift-emit-sil -sanitize=thread -O -sil-verify-all -verify -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses %s +// REQUIRES: OS=macOS + +// This file contains tests that used to crash due to verifier errors. It must +// be separate from moveonly_addresschecker_diagnostics since when we fail on +// the diagnostics in that file, we do not actually run the verifier. + +struct TestTrivialReturnValue : ~Copyable { + var i: Int = 5 + + // We used to error on return buffer. + consuming func drain() -> Int { + let buffer = (consume self).i + self = .init(i: 5) + return buffer + } +} + + +////////////////////// +// MARK: Misc Tests // +////////////////////// + +func testAssertLikeUseDifferentBits() { + struct S : ~Copyable { + var s: [Int] = [] + var currentPosition = 5 + + // CHECK-LABEL: sil private @$s23moveonly_addresschecker30testAssertLikeUseDifferentBitsyyF1SL_V6resume2atySi_tF : $@convention(method) (Int, @inout S) -> () { + // CHECK-NOT: destroy_addr + // CHECK: } // end sil function '$s23moveonly_addresschecker30testAssertLikeUseDifferentBitsyyF1SL_V6resume2atySi_tF' + mutating func resume(at index: Int) { + assert(index >= currentPosition) + currentPosition = index + } + } +} diff --git a/test/SILOptimizer/moveonly_type_eliminator.sil b/test/SILOptimizer/moveonly_type_eliminator.sil index e27dad92be2f0..59a18a9bcba26 100644 --- a/test/SILOptimizer/moveonly_type_eliminator.sil +++ b/test/SILOptimizer/moveonly_type_eliminator.sil @@ -562,3 +562,19 @@ bb3(%result : @owned $@moveOnly FakeOptional): %result2 = moveonlywrapper_to_copyable [owned] %result : $@moveOnly FakeOptional return %result2 : $FakeOptional } + +// CHECK-LABEL: sil [ossa] @debug_value_undef : {{.*}} { +// CHECK: debug_value [moveable_value_debuginfo] undef : $*Klass, var, name "s" +// CHECK-LABEL: } // end sil function 'debug_value_undef' +sil [ossa] @debug_value_undef : $@convention(thin) (@owned Klass) -> () { +bb0(%x : @owned $Klass): + %addr = alloc_stack $@moveOnly Klass + %unwrapped_addr = moveonlywrapper_to_copyable_addr %addr : $*@moveOnly Klass + store %x to [init] %unwrapped_addr : $*Klass + debug_value %addr : $*@moveOnly Klass, var, name "s", argno 1, expr op_deref + destroy_addr %addr : $*@moveOnly Klass + debug_value undef : $*@moveOnly Klass, var, name "s", argno 1, expr op_deref + dealloc_stack %addr : $*@moveOnly Klass + %retval = tuple () + return %retval : $() +} diff --git a/test/SILOptimizer/noimplicitcopy_existentials.swift b/test/SILOptimizer/noimplicitcopy_existentials.swift new file mode 100644 index 0000000000000..ee912af2999ab --- /dev/null +++ b/test/SILOptimizer/noimplicitcopy_existentials.swift @@ -0,0 +1,26 @@ +// RUN: %target-swift-frontend \ +// RUN: -emit-sil -verify \ +// RUN: %s \ +// RUN: -sil-verify-all + +//////////////////////////////////////////////////////////////////////////////// +// https://github.com/apple/swift/issues/73525 {{ +//////////////////////////////////////////////////////////////////////////////// +protocol K { + var a: Int { get } +} + +protocol B { + init(k: any K) +} + +struct A: B { + let a: Int + + init(k: borrowing K) { + self.a = k.a + } +} +//////////////////////////////////////////////////////////////////////////////// +// https://github.com/apple/swift/issues/73525 }} +//////////////////////////////////////////////////////////////////////////////// diff --git a/test/SILOptimizer/package-cmo-inlinable.swift b/test/SILOptimizer/package-cmo-inlinable.swift index 80fa4bdd930db..e8d2952360a55 100644 --- a/test/SILOptimizer/package-cmo-inlinable.swift +++ b/test/SILOptimizer/package-cmo-inlinable.swift @@ -41,7 +41,8 @@ public func inUsePubStruct(_ arg: Int) -> PubStruct { // CHECK-MAIN: sil [ossa] @$s4Main12usePubStructy3Lib0cD0VSiF : $@convention(thin) (Int) -> @out PubStruct { public func usePubStruct(_ arg: Int) -> PubStruct { var p = PubStruct(1) - // CHECK-MAIN: struct_element_addr {{.*}} : $*PubStruct, #PubStruct.pub + // CHECK-MAIN: function_ref @$s3Lib9PubStructVyACSicfC + // CHECK-MAIN: function_ref @$s3Lib9PubStructV3pubSivM p.pub += arg return p } @@ -58,7 +59,8 @@ package func inUseUfiPkgStruct(_ arg: Int) -> UfiPkgStruct { // CHECK-MAIN: sil package [ossa] @$s4Main15useUfiPkgStructy3Lib0cdE0VSiF : $@convention(thin) (Int) -> @out UfiPkgStruct { package func useUfiPkgStruct(_ arg: Int) -> UfiPkgStruct { var p = UfiPkgStruct(1) - // CHECK-MAIN: struct_element_addr {{.*}} : $*UfiPkgStruct, #UfiPkgStruct.ufiPkg + // CHECK-MAIN: function_ref @$s3Lib12UfiPkgStructVyACSicfC + // CHECK-MAIN: function_ref @$s3Lib12UfiPkgStructV03ufiC0SivM p.ufiPkg += arg return p } @@ -66,7 +68,8 @@ package func useUfiPkgStruct(_ arg: Int) -> UfiPkgStruct { // CHECK-MAIN: sil package [ossa] @$s4Main12usePkgStructy3Lib0cD0VSiF : $@convention(thin) (Int) -> @out PkgStruct { package func usePkgStruct(_ arg: Int) -> PkgStruct { var p = PkgStruct(1) - // CHECK-MAIN: struct_element_addr {{.*}} : $*PkgStruct, #PkgStruct.pkg + // CHECK-MAIN: function_ref @$s3Lib9PkgStructVyACSicfC + // CHECK-MAIN: function_ref @$s3Lib9PkgStructV3pkgSivM p.pkg += arg return p } diff --git a/test/SILOptimizer/package-cmo-resilient-mode.swift b/test/SILOptimizer/package-cmo-resilient-mode.swift index d0224967f07b8..20277eda4df87 100644 --- a/test/SILOptimizer/package-cmo-resilient-mode.swift +++ b/test/SILOptimizer/package-cmo-resilient-mode.swift @@ -96,7 +96,7 @@ import Lib // CHECK-MAIN-COMMON: [[FNL_PUB_REF:%.*]] = ref_element_addr [[FNL_PUB_GET]] : $FinalPubKlass, #FinalPubKlass.data // CHECK-MAIN-COMMON-NEXT: [[FNL_PUB_ACCESS:%.*]] = begin_access {{.*}} [[FNL_PUB_REF]] : $*Int // CHECK-MAIN-COMMON-NEXT: [[FNL_PUB_LOAD:%.*]] = load [[FNL_PUB_ACCESS]] : $*Int -// CHECK-MAIN-COMMON-NEXT: store [[FNL_PUB_LOAD]] to {{.*}} : $*Int +// CHECK-MAIN-COMMON: store [[FNL_PUB_LOAD]] to {{.*}} : $*Int // CHECK-MAIN-COMMON: [[FNL_PKG_ALLOC:%.*]] = alloc_ref $FinalPkgKlass // CHECK-MAIN-COMMON-NEXT: [[FNL_PKG_INIT:%.*]] = end_init_let_ref [[FNL_PKG_ALLOC]] : $FinalPkgKlass @@ -108,7 +108,7 @@ import Lib // CHECK-MAIN-COMMON: [[FNL_PKG_REF:%.*]] = ref_element_addr [[FNL_PKG_GET]] : $FinalPkgKlass, #FinalPkgKlass.data // CHECK-MAIN-COMMON-NEXT: [[FNL_PKG_ACCESS:%.*]] = begin_access {{.*}} [[FNL_PKG_REF]] : $*Int // CHECK-MAIN-COMMON-NEXT: [[FNL_PKG_LOAD:%.*]] = load [[FNL_PKG_ACCESS]] : $*Int -// CHECK-MAIN-COMMON-NEXT: store [[FNL_PKG_LOAD]] to {{.*}} : $*Int +// CHECK-MAIN-COMMON: store [[FNL_PKG_LOAD]] to {{.*}} : $*Int // CHECK-MAIN-RES-DAG: sil public_external @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass { // CHECK-MAIN-NONRES-DAG: sil public_external @$s3Lib8PubKlassCyACSicfC : $@convention(method) (Int, @thick PubKlass.Type) -> @owned PubKlass { @@ -176,53 +176,6 @@ public func mainPub() { //--- Lib.swift - -// pcmo TODO: check for Fr public fields serialized kind -// and add silgen of pkg static pts. - -// FIXME: serialize closure pointers? -// static PkgStruct.pkgStaticSimpleFuncPtr -// CHECK-RES-DAG: sil_global package [serialized_for_package] @$s3Lib9PkgStructV22pkgStaticSimpleFuncPtryS2icvpZ -// CHECK-NONRES-DAG: sil_global package [serialized] @$s3Lib9PkgStructV22pkgStaticSimpleFuncPtryS2icvpZ - -// static FrPubStruct.pubStaticClosurePtr -// CHECK-COMMON-DAG: sil_global @$s3Lib11FrPubStructV19pubStaticClosurePtrySiAA0cD0VcvpZ - -// static PkgStruct.pkgStaticClosurePtr -// CHECK-COMMON-DAG: sil_global package @$s3Lib9PkgStructV19pkgStaticClosurePtrySiACcvpZ - -// static PkgStruct.pkgStaticSimpleClosurePtr -// CHECK-COMMON-DAG: sil_global package @$s3Lib9PkgStructV25pkgStaticSimpleClosurePtryS2icvpZ - -// static PkgStruct.pkgStaticFuncPtr -// CHECK-RES-DAG: sil_global package [serialized_for_package] @$s3Lib9PkgStructV16pkgStaticFuncPtrySiACcvpZ -// CHECK-NONRES-DAG: sil_global package [serialized] @$s3Lib9PkgStructV16pkgStaticFuncPtrySiACcvpZ - -// static PubStruct.pubStaticClosurePtr -// CHECK-COMMON-DAG: sil_global @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvpZ - -// static FrPubStruct.pubStaticSimpleFuncPtr -// CHECK-RES-DAG: sil_global [serialized_for_package] @$s3Lib11FrPubStructV22pubStaticSimpleFuncPtryS2icvpZ -// CHECK-NONRES-DAG: sil_global [serialized] @$s3Lib11FrPubStructV22pubStaticSimpleFuncPtryS2icvpZ - -// static FrPubStruct.pubStaticFuncPtr -// CHECK-RES-DAG: sil_global [serialized_for_package] @$s3Lib11FrPubStructV16pubStaticFuncPtrySiAA0cD0VcvpZ -// CHECK-NONRES-DAG: sil_global [serialized] @$s3Lib11FrPubStructV16pubStaticFuncPtrySiAA0cD0VcvpZ - -// static PubStruct.pubStaticSimpleClosurePtr -// CHECK-COMMON-DAG: sil_global @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvpZ - -// static PubStruct.pubStaticSimpleFuncPtr -// CHECK-RES-DAG: sil_global [serialized_for_package] @$s3Lib9PubStructV22pubStaticSimpleFuncPtryS2icvpZ -// CHECK-NONRES-DAG: sil_global [serialized] @$s3Lib9PubStructV22pubStaticSimpleFuncPtryS2icvpZ - -// static PubStruct.pubStaticFuncPtr -// CHECK-RES-DAG: sil_global [serialized_for_package] @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvpZ -// CHECK-NONRES-DAG: sil_global [serialized] @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvpZ - -// static FrPubStruct.pubStaticSimpleClosurePtr -// CHECK-COMMON-DAG: sil_global @$s3Lib11FrPubStructV25pubStaticSimpleClosurePtryS2icvpZ - public struct PubStruct { // PubStruct.foovar.getter // CHECK-RES-DAG: sil [serialized_for_package] [canonical] @$s3Lib9PubStructV6fooVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int { @@ -252,44 +205,32 @@ public struct PubStruct { public static var pubStaticVar: String { "StaticPubVar" } // static PubStruct.pubStaticSimpleFuncPtr.modify - // CHECK-RES-DAG: sil [serialized_for_package] [canonical] @$s3Lib9PubStructV22pubStaticSimpleFuncPtryS2icvMZ : $@yield_once @convention(method) (@thin PubStruct.Type) -> @yields @inout @callee_guaranteed (Int) -> Int { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV22pubStaticSimpleFuncPtryS2icvMZ : $@yield_once @convention(method) (@thin PubStruct.Type) -> @yields @inout @callee_guaranteed (Int) -> Int { public static var pubStaticSimpleFuncPtr: (Int) -> (Int) = runPubSimple // static PubStruct.pubStaticFuncPtr.modify - // CHECK-RES-DAG: sil [serialized_for_package] [canonical] @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvsZ : $@convention(method) (@owned @callee_guaranteed (@in_guaranteed PubStruct) -> Int, @thin PubStruct.Type) -> () { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvsZ : $@convention(method) (@owned @callee_guaranteed (PubStruct) -> Int, @thin PubStruct.Type) -> () { - // CHECK-RES-DAG: global_addr @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvpZ : $*@callee_guaranteed (@in_guaranteed PubStruct) -> Int // CHECK-NONRES-DAG: function_ref @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvau : $@convention(thin) () -> Builtin.RawPointer // PubStruct.pubStaticFuncPtr.unsafeMutableAddressor - // CHECK-RES-DAG: sil [serialized_for_package] [global_init] [canonical] @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvau : $@convention(thin) () -> Builtin.RawPointer - // CHECK-RES-DAG: global_addr @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvpZ : $*@callee_guaranteed (@in_guaranteed PubStruct) -> Int // CHECK-NONRES-DAG: sil [serialized] [global_init] [canonical] @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvau : $@convention(thin) () -> Builtin.RawPointer // CHECK-NONRES-DAG: global_addr @$s3Lib9PubStructV16pubStaticFuncPtrySiACcvpZ : $*@callee_guaranteed (PubStruct) -> Int public static var pubStaticFuncPtr: (PubStruct) -> (Int) = runPub // static PubStruct.pubStaticSimpleClosurePtr.setter - // CHECK-RES-DAG: sil [serialized_for_package] [canonical] @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvsZ : $@convention(method) (@owned @callee_guaranteed (Int) -> Int, @thin PubStruct.Type) -> () { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvsZ : $@convention(method) (@owned @callee_guaranteed (Int) -> Int, @thin PubStruct.Type) -> () { - // CHECK-RES-DAG: global_addr @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvpZ // CHECK-NONRES-DAG: function_ref @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvau : $@convention(thin) () -> Builtin.RawPointer // PubStruct.pubStaticSimpleClosurePtr.unsafeMutableAddressor - // CHECK-RES-DAG: sil [serialized_for_package] [global_init] [canonical] @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvau : $@convention(thin) () -> Builtin.RawPointer { // CHECK-NONRES-DAG: sil [serialized] [global_init] [canonical] @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvau : $@convention(thin) () -> Builtin.RawPointer { - // CHECK-COMMON-DAG: global_addr @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvpZ : $*@callee_guaranteed (Int) -> Int + // CHECK-NONRES-DAG: global_addr @$s3Lib9PubStructV25pubStaticSimpleClosurePtryS2icvpZ : $*@callee_guaranteed (Int) -> Int public static var pubStaticSimpleClosurePtr: (Int) -> (Int) = { return $0 } // static PubStruct.pubStaticClosurePtr.setter - // CHECK-RES-DAG: sil [serialized_for_package] [canonical] @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvsZ : $@convention(method) (@owned @callee_guaranteed (@in_guaranteed PubStruct) -> Int, @thin PubStruct.Type) -> () { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvsZ : $@convention(method) (@owned @callee_guaranteed (PubStruct) -> Int, @thin PubStruct.Type) -> () { - // CHECK-RES-DAG: global_addr @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvpZ // CHECK-NONRES-DAG: function_ref @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvau : $@convention(thin) () -> Builtin.RawPointer // PubStruct.pubStaticClosurePtr.unsafeMutableAddressor - // CHECK-RES-DAG: sil [serialized_for_package] [global_init] [canonical] @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvau : $@convention(thin) () -> Builtin.RawPointer { - // CHECK-RES-DAG: global_addr @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvpZ : $*@callee_guaranteed (@in_guaranteed PubStruct) -> Int // CHECK-NONRES-DAG: sil [serialized] [global_init] [canonical] @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvau : $@convention(thin) () -> Builtin.RawPointer { // CHECK-NONRES-DAG: global_addr @$s3Lib9PubStructV19pubStaticClosurePtrySiACcvpZ : $*@callee_guaranteed (PubStruct) -> Int public static var pubStaticClosurePtr: (PubStruct) -> (Int) = { return $0.fooVar } @@ -345,12 +286,10 @@ public struct FrPubStruct { public static var pubStaticSimpleFuncPtr: (Int) -> (Int) = runPubSimple public static var pubStaticFuncPtr: (PubStruct) -> (Int) = runPub // static FrPubStruct.pubStaticSimpleClosurePtr.setter - // CHECK-RES-DAG: sil [serialized_for_package] [canonical] @$s3Lib11FrPubStructV25pubStaticSimpleClosurePtryS2icvsZ : $@convention(method) (@owned @callee_guaranteed (Int) -> Int, @thin FrPubStruct.Type) -> () { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib11FrPubStructV25pubStaticSimpleClosurePtryS2icvsZ : $@convention(method) (@owned @callee_guaranteed (Int) -> Int, @thin FrPubStruct.Type) -> () { public static var pubStaticSimpleClosurePtr: (Int) -> (Int) = { return $0 } // static FrPubStruct.pubStaticClosurePtr.setter - // CHECK-RES-DAG: sil [serialized_for_package] [canonical] @$s3Lib11FrPubStructV19pubStaticClosurePtrySiAA0cD0VcvsZ : $@convention(method) (@owned @callee_guaranteed (@in_guaranteed PubStruct) -> Int, @thin FrPubStruct.Type) -> () { // CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib11FrPubStructV19pubStaticClosurePtrySiAA0cD0VcvsZ : $@convention(method) (@owned @callee_guaranteed (PubStruct) -> Int, @thin FrPubStruct.Type) -> () { public static var pubStaticClosurePtr: (PubStruct) -> (Int) = { return $0.fooVar } diff --git a/test/SILOptimizer/package-cmo-serialize-tables.swift b/test/SILOptimizer/package-cmo-serialize-tables.swift index 2eaeae70082d8..d8127ca78bae7 100644 --- a/test/SILOptimizer/package-cmo-serialize-tables.swift +++ b/test/SILOptimizer/package-cmo-serialize-tables.swift @@ -268,8 +268,10 @@ public class PubKlassZ: PubProto { } public struct PubStruct: PubProto { + // protocol witness for static PubProto.root.getter in conformance PubStruct // CHECK-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib9PubStructVAA0B5ProtoA2aDP4roots6UInt16VvgZTW : $@convention(witness_method: PubProto) (@thick PubStruct.Type) -> UInt16 { - // CHECK-DAG: sil [serialized_for_package] [canonical] [ossa] @$s3Lib9PubStructV4roots6UInt16VvgZ : $@convention(method) (@thin PubStruct.Type) -> UInt16 { + // CHECK-DAG: function_ref @$s3Lib9PubStructV4roots6UInt16VvgZ : $@convention(method) (@thin PubStruct.Type) -> UInt16 + // CHECK-DAG: sil [canonical] @$s3Lib9PubStructV4roots6UInt16VvgZ : $@convention(method) (@thin PubStruct.Type) -> UInt16 public static let root: UInt16 = 1 << 0 // CHECK-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib9PubStructVAA0B5ProtoA2aDP3envs6UInt16VvgTW : $@convention(witness_method: PubProto) (@in_guaranteed PubStruct) -> UInt16 { @@ -356,8 +358,10 @@ package protocol PkgProto { /// NOTE: witness thunks get `shared` linkage package class PkgKlassZ: PkgProto { + // protocol witness for static PkgProto.root.getter in conformance PkgKlassZ // CHECK-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib9PkgKlassZCAA0B5ProtoA2aDP4roots6UInt16VvgZTW : $@convention(witness_method: PkgProto) (@thick PkgKlassZ.Type) -> UInt16 { - // CHECK-DAG: sil package [serialized_for_package] [canonical] [ossa] @$s3Lib9PkgKlassZC4roots6UInt16VvgZ + // CHECK-DAG: function_ref @$s3Lib9PkgKlassZC4roots6UInt16VvgZ : $@convention(method) (@thick PkgKlassZ.Type) -> UInt16 + // CHECK-DAG: sil package_external [canonical] @$s3Lib9PkgKlassZC4roots6UInt16VvgZ : $@convention(method) (@thick PkgKlassZ.Type) -> UInt16 package static let root: UInt16 = 1 << 0 // CHECK-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib9PkgKlassZCAA0B5ProtoA2aDP3envs6UInt16VvgTW : $@convention(witness_method: PkgProto) (@in_guaranteed PkgKlassZ) -> UInt16 { @@ -384,9 +388,11 @@ package class PkgKlassZ: PkgProto { } package struct PkgStruct: PkgProto { /// NOTE: witness thunks get `shared` linkage + // protocol witness for static PkgProto.root.getter in conformance PkgStruct // CHECK-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib9PkgStructVAA0B5ProtoA2aDP4roots6UInt16VvgZTW : $@convention(witness_method: PkgProto) (@thick PkgStruct.Type) -> UInt16 { - // CHECK-DAG: sil package [serialized_for_package] [canonical] [ossa] @$s3Lib9PkgStructV4roots6UInt16VvgZ - // CHECK-DAG: sil package_external [global_init] [canonical] @$s3Lib9PkgStructV4roots6UInt16Vvau : $@convention(thin) () -> Builtin.RawPointer + // CHECK-DAG: function_ref @$s3Lib9PkgStructV4roots6UInt16VvgZ : $@convention(method) (@thin PkgStruct.Type) + // static PkgStruct.root.getter + // CHECK-DAG: sil package_external [canonical] @$s3Lib9PkgStructV4roots6UInt16VvgZ : $@convention(method) (@thin PkgStruct.Type) -> UInt16 package static let root: UInt16 = 1 << 0 // CHECK-DAG: sil shared [transparent] [serialized] [thunk] [canonical] [ossa] @$s3Lib9PkgStructVAA0B5ProtoA2aDP3envs6UInt16VvsTW : $@convention(witness_method: PkgProto) (UInt16, @inout PkgStruct) -> () { diff --git a/test/SILOptimizer/performance-annotations-noassert-stdlib.swift b/test/SILOptimizer/performance-annotations-noassert-stdlib.swift new file mode 100644 index 0000000000000..afab1348fb0af --- /dev/null +++ b/test/SILOptimizer/performance-annotations-noassert-stdlib.swift @@ -0,0 +1,9 @@ +// RUN: %target-swift-frontend -parse-as-library -disable-availability-checking -import-objc-header %S/Inputs/perf-annotations.h -emit-sil %s -o /dev/null -verify + +// REQUIRES: swift_in_compiler +// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib + +@_noAllocation +func createEmptyArray() { + _ = [Int]() // expected-error {{ending the lifetime of a value of type}} +} \ No newline at end of file diff --git a/test/SILOptimizer/performance-annotations.swift b/test/SILOptimizer/performance-annotations.swift index 24dd54b2b90b3..9df98be9d8a8f 100644 --- a/test/SILOptimizer/performance-annotations.swift +++ b/test/SILOptimizer/performance-annotations.swift @@ -1,6 +1,7 @@ -// RUN: %target-swift-frontend -parse-as-library -disable-availability-checking -import-objc-header %S/Inputs/perf-annotations.h -emit-sil %s -o /dev/null -verify -// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib +// RUN: %target-swift-frontend -parse-as-library -disable-availability-checking -enable-experimental-feature RawLayout -import-objc-header %S/Inputs/perf-annotations.h -emit-sil %s -o /dev/null -verify + // REQUIRES: swift_in_compiler +// REQUIRES: optimized_stdlib protocol P { func protoMethod(_ a: Int) -> Int @@ -233,11 +234,6 @@ func closueWhichModifiesLocalVar() -> Int { return x } -@_noAllocation -func createEmptyArray() { - _ = [Int]() // expected-error {{ending the lifetime of a value of type}} -} - struct Buffer { var p: UnsafeMutableRawBufferPointer @@ -514,3 +510,48 @@ func testNonCopyable() { let t = NonCopyableStruct() t.foo() } + +public struct RawLayoutWrapper: ~Copyable { + private let x = RawLayout() + + @_noLocks func testit() { + x.test() + } +} + +@_rawLayout(like: T) +public struct RawLayout: ~Copyable { + public func test() {} +} + +func takesClosure(_: () -> ()) {} + +@_noLocks +func testClosureExpression(_ t: T) { + takesClosure { + // expected-error@-1 {{generic closures or local functions can cause metadata allocation or locks}} + _ = T.self + } +} + +@_noLocks +func testLocalFunction(_ t: T) { + func localFunc() { + _ = T.self + } + + takesClosure(localFunc) + // expected-error@-1 {{generic closures or local functions can cause metadata allocation or locks}} +} + +func takesGInt(_ x: G) {} + +struct G {} + +extension G where T == Int { + @_noAllocation func method() { + takesClosure { + takesGInt(self) // OK + } + } +} diff --git a/test/SILOptimizer/sil_combine_protocol_conf.swift b/test/SILOptimizer/sil_combine_protocol_conf.swift index 289965e5e6d31..54adf1370f34d 100644 --- a/test/SILOptimizer/sil_combine_protocol_conf.swift +++ b/test/SILOptimizer/sil_combine_protocol_conf.swift @@ -247,10 +247,10 @@ public class OtherClass { // 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]] : $*any GenericPropProtocol to $*@opened("{{.*}}", any GenericPropProtocol) Self -// CHECK: copy_addr [[O2]] to [init] [[T1:%[0-9]*]] +// CHECK: copy_addr [[ACC2]] to [init] [[T1:%[0-9]*]] +// CHECK: [[O2:%.*]] = open_existential_addr immutable_access [[T1]] : $*any GenericPropProtocol to $*@opened("{{.*}}", any GenericPropProtocol) Self // 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: apply [[W2]]<@opened("{{.*}}", any GenericPropProtocol) Self>([[O2]]) : $@convention(witness_method: GenericPropProtocol) <τ_0_0 where τ_0_0 : GenericPropProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK: struct_extract // CHECK: integer_literal // CHECK: builtin diff --git a/test/SILOptimizer/simplify_cfg_crash.swift b/test/SILOptimizer/simplify_cfg_crash.swift index 8deab7259639e..5410b986f620d 100644 --- a/test/SILOptimizer/simplify_cfg_crash.swift +++ b/test/SILOptimizer/simplify_cfg_crash.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -O %s -emit-sil -o /dev/null +// RUN: %target-swift-frontend -O %s -enable-ossa-modules -emit-sil -o /dev/null public class X {} diff --git a/test/SILOptimizer/simplify_cfg_ossa.sil b/test/SILOptimizer/simplify_cfg_ossa.sil index 06a1759e8c1a9..4c9cec76579e5 100644 --- a/test/SILOptimizer/simplify_cfg_ossa.sil +++ b/test/SILOptimizer/simplify_cfg_ossa.sil @@ -25,6 +25,7 @@ class Klass { var a: Int deinit init() + func foo() -> Int? } class B {} @@ -38,6 +39,10 @@ struct KlassWrapper { var k: Klass } +struct OptionalKlassWrapper { + @_hasStorage var k: Optional +} + internal enum CompareResult { case equal case less @@ -1843,3 +1848,42 @@ bb10(%7 : $()): bb11: unreachable } + +// CHECK-LABEL: sil [ossa] @jump_threading_creates_phi : +// CHECK: = borrowed %{{[0-9]+}} : $Klass from (%1 : $OptionalKlassWrapper) +// CHECK: } // end sil function 'jump_threading_creates_phi' +sil [ossa] @jump_threading_creates_phi: $@convention(thin) (Optional, @guaranteed OptionalKlassWrapper) -> () { +bb0(%0 : $Optional, %1 : @guaranteed $OptionalKlassWrapper): + %2 = alloc_stack [lexical] $Optional + store %0 to [trivial] %2 : $*Optional + switch_enum_addr %2 : $*Optional, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2 + +bb1: + %5 = unchecked_take_enum_data_addr %2 : $*Optional, #Optional.some!enumelt + %6 = load [trivial] %5 : $*A + br bb3(%6 : $A) + +bb2: + %8 = enum $A, #A.B!enumelt + br bb3(%8 : $A) + +bb3(%10 : $A): + dealloc_stack %2 : $*Optional + %12 = enum $Optional, #Optional.some!enumelt, %10 : $A + %13 = struct_extract %1 : $OptionalKlassWrapper, #OptionalKlassWrapper.k + switch_enum %13 : $Optional, case #Optional.some!enumelt: bb4, case #Optional.none!enumelt: bb5 + +bb4(%15 : @guaranteed $Klass): + %16 = class_method %15 : $Klass, #Klass.foo : (Klass) -> () -> Int?, $@convention(method) (@guaranteed Klass) -> Optional + %17 = apply %16(%15) : $@convention(method) (@guaranteed Klass) -> Optional + br bb6(%17 : $Optional) + +bb5: + %19 = enum $Optional, #Optional.none!enumelt + br bb6(%19 : $Optional) + +bb6(%21 : $Optional): + %22 = tuple () + return %22 : $() +} + diff --git a/test/SPI/implementation_only_spi_import_exposability.swift b/test/SPI/implementation_only_spi_import_exposability.swift index 3e6c5cd185ebd..de3354d7303da 100644 --- a/test/SPI/implementation_only_spi_import_exposability.swift +++ b/test/SPI/implementation_only_spi_import_exposability.swift @@ -32,8 +32,8 @@ public protocol IOIProtocol {} @_spi(B) public func leakSPIStruct(_ a: SPIStruct) -> SPIStruct { fatalError() } // expected-warning 2 {{cannot use struct 'SPIStruct' here; 'Lib' has been imported as implementation-only}} @_spi(B) public func leakIOIStruct(_ a: IOIStruct) -> IOIStruct { fatalError() } // expected-warning 2 {{cannot use struct 'IOIStruct' here; 'Lib' has been imported as implementation-only}} -public struct PublicStruct : IOIProtocol, SPIProtocol { // expected-error {{cannot use protocol 'IOIProtocol' here; 'Lib' has been imported as implementation-only}} -// expected-error @-1 {{cannot use protocol 'SPIProtocol' here; 'Lib' has been imported as implementation-only}} +public struct PublicStruct : IOIProtocol, SPIProtocol { // expected-error {{cannot use protocol 'IOIProtocol' in a public or '@usableFromInline' conformance; 'Lib' has been imported as implementation-only}} +// expected-error @-1 {{cannot use protocol 'SPIProtocol' in a public or '@usableFromInline' conformance; 'Lib' has been imported as implementation-only}} public var spiStruct = SPIStruct() // expected-error {{cannot use struct 'SPIStruct' here; 'Lib' has been imported as implementation-only}} public var ioiStruct = IOIStruct() // expected-error {{cannot use struct 'IOIStruct' here; 'Lib' has been imported as implementation-only}} @@ -49,8 +49,8 @@ public struct PublicStruct : IOIProtocol, SPIProtocol { // expected-error {{cann } @_spi(B) -public struct LocalSPIStruct : IOIProtocol, SPIProtocol { // expected-warning {{cannot use protocol 'IOIProtocol' here; 'Lib' has been imported as implementation-only}} -// expected-warning @-1 {{cannot use protocol 'SPIProtocol' here; 'Lib' has been imported as implementation-only}} +public struct LocalSPIStruct : IOIProtocol, SPIProtocol { // expected-warning {{cannot use protocol 'IOIProtocol' in a public or '@usableFromInline' conformance; 'Lib' has been imported as implementation-only}} +// expected-warning @-1 {{cannot use protocol 'SPIProtocol' in a public or '@usableFromInline' conformance; 'Lib' has been imported as implementation-only}} } #endif diff --git a/test/SPI/local_spi_decls.swift b/test/SPI/local_spi_decls.swift index 64af46c496e80..02adf40c636e6 100644 --- a/test/SPI/local_spi_decls.swift +++ b/test/SPI/local_spi_decls.swift @@ -70,7 +70,7 @@ private protocol PrivateProtocol {} // expected-note {{type declared here}} @_spi(S) public class BadSubclass : InternalClass {} // expected-error{{class cannot be declared public because its superclass is internal}} @_spi(S) public class OkSPISubclass : SPIClass {} // OK -public class BadPublicClass : SPIClass {} // expected-error {{cannot use class 'SPIClass' here; it is SPI}} +public class BadPublicClass : SPIClass {} // expected-error {{cannot use class 'SPIClass' in a public or '@usableFromInline' conformance; it is SPI}} @_spi(S) public class BadSPIClass : PrivateClass {} // expected-error {{class cannot be declared public because its superclass is private}} @_spi(s) public func genFunc(_ t: T) {} // expected-error {{global function cannot be declared public because its generic parameter uses a private type}} diff --git a/test/ScanDependencies/module_deps_link_libs.swift b/test/ScanDependencies/module_deps_link_libs.swift index 6b27388bc54cd..2792e9dbd3a22 100644 --- a/test/ScanDependencies/module_deps_link_libs.swift +++ b/test/ScanDependencies/module_deps_link_libs.swift @@ -17,18 +17,6 @@ import SubE // CHECK-NEXT: "isFramework": false, // CHECK-NEXT: "shouldForceLoad": false -// CHECK-DAG: "linkName": "swiftCompatibilityConcurrency", -// CHECK-NEXT: "isFramework": false, -// CHECK-NEXT: "shouldForceLoad": true - -// CHECK-DAG: "linkName": "swiftCompatibility56", -// CHECK-NEXT: "isFramework": false, -// CHECK-NEXT: "shouldForceLoad": true - -// CHECK-DAG: "linkName": "swiftCompatibilityPacks", -// CHECK-NEXT: "isFramework": false, -// CHECK-NEXT: "shouldForceLoad": false - // CHECK-DAG: "linkName": "swiftyLibE", // CHECK-NEXT: "isFramework": false, // CHECK-NEXT: "shouldForceLoad": true diff --git a/test/Sema/access-level-import-classic-exportability.swift b/test/Sema/access-level-import-classic-exportability.swift index 47857813a423c..b08b900cb0e03 100644 --- a/test/Sema/access-level-import-classic-exportability.swift +++ b/test/Sema/access-level-import-classic-exportability.swift @@ -52,9 +52,9 @@ public struct PrivateImportType { //--- Client.swift public import PublicLib package import PackageLib // expected-note 2 {{struct 'PackageImportType' imported as 'package' from 'PackageLib' here}} -internal import InternalLib // expected-note 4 {{struct 'InternalImportType' imported as 'internal' from 'InternalLib' here}} -fileprivate import FileprivateLib // expected-note 4 {{struct 'FileprivateImportType' imported as 'fileprivate' from 'FileprivateLib' here}} -private import PrivateLib // expected-note 4 {{struct 'PrivateImportType' imported as 'private' from 'PrivateLib' here}} +internal import InternalLib // expected-note 2 {{struct 'InternalImportType' imported as 'internal' from 'InternalLib' here}} +fileprivate import FileprivateLib // expected-note 2 {{struct 'FileprivateImportType' imported as 'fileprivate' from 'FileprivateLib' here}} +private import PrivateLib // expected-note 2 {{struct 'PrivateImportType' imported as 'private' from 'PrivateLib' here}} public protocol PublicConstrainedExtensionProto {} extension Array: PublicConstrainedExtensionProto where Element == PublicImportType {} @@ -87,8 +87,8 @@ extension PublicImportType { } public protocol PackageConstrainedExtensionProto {} -extension Array: PackageConstrainedExtensionProto where Element == PackageImportType {} // expected-error {{cannot use struct 'PackageImportType' in an extension with conditional conformances; 'PackageLib' was imported as package}} -extension PackageImportType { // expected-error {{cannot use struct 'PackageImportType' in an extension with public or '@usableFromInline' members; 'PackageLib' was imported as package}} +extension Array: PackageConstrainedExtensionProto where Element == PackageImportType {} // expected-error {{cannot use struct 'PackageImportType' in an extension with conditional conformances; 'PackageLib' was not imported publicly}} +extension PackageImportType { // expected-error {{cannot use struct 'PackageImportType' in an extension with public or '@usableFromInline' members; 'PackageLib' was not imported publicly}} public func publicMethod() {} } @@ -123,8 +123,8 @@ extension InternalImportType { // expected-error {{cannot use struct 'InternalIm } package protocol InternalConstrainedExtensionProtoInPackage {} -extension Array: InternalConstrainedExtensionProtoInPackage where Element == InternalImportType {} // expected-error {{cannot use struct 'InternalImportType' in an extension with conditional conformances; 'InternalLib' was not imported publicly or as package}} -extension InternalImportType { // expected-error {{cannot use struct 'InternalImportType' in an extension with public, package, or '@usableFromInline' members; 'InternalLib' was not imported publicly or as package}} +extension Array: InternalConstrainedExtensionProtoInPackage where Element == InternalImportType {} +extension InternalImportType { package func packageMethod() {} } @@ -153,8 +153,8 @@ extension FileprivateImportType { // expected-error {{cannot use struct 'Filepri } package protocol FileprivateConstrainedExtensionProtoInPackage {} -extension Array: FileprivateConstrainedExtensionProtoInPackage where Element == FileprivateImportType {} // expected-error {{cannot use struct 'FileprivateImportType' in an extension with conditional conformances; 'FileprivateLib' was not imported publicly or as package}} -extension FileprivateImportType { // expected-error {{cannot use struct 'FileprivateImportType' in an extension with public, package, or '@usableFromInline' members; 'FileprivateLib' was not imported publicly or as package}} +extension Array: FileprivateConstrainedExtensionProtoInPackage where Element == FileprivateImportType {} +extension FileprivateImportType { package func packageMethod() {} } @@ -183,8 +183,8 @@ extension PrivateImportType { // expected-error {{cannot use struct 'PrivateImpo } package protocol PrivateConstrainedExtensionProtoInPackage {} -extension Array: PrivateConstrainedExtensionProtoInPackage where Element == PrivateImportType {} // expected-error {{cannot use struct 'PrivateImportType' in an extension with conditional conformances; 'PrivateLib' was not imported publicly or as package}} -extension PrivateImportType { // expected-error {{cannot use struct 'PrivateImportType' in an extension with public, package, or '@usableFromInline' members; 'PrivateLib' was not imported publicly or as package}} +extension Array: PrivateConstrainedExtensionProtoInPackage where Element == PrivateImportType {} +extension PrivateImportType { package func packageMethod() {} } diff --git a/test/Sema/access-level-import-conformances.swift b/test/Sema/access-level-import-conformances.swift index b2d974885d534..59026f41608db 100644 --- a/test/Sema/access-level-import-conformances.swift +++ b/test/Sema/access-level-import-conformances.swift @@ -2,82 +2,29 @@ // RUN: split-file --leading-lines %s %t /// Build the libraries. -// RUN: %target-swift-frontend -emit-module %t/ConformanceBaseTypes.swift -o %t -package-name pkg -// RUN: %target-swift-frontend -emit-module %t/ConformanceDefinition1.swift -o %t -I %t -package-name pkg -// RUN: %target-swift-frontend -emit-module %t/ConformanceDefinition2.swift -o %t -I %t -package-name pkg +// RUN: %target-swift-frontend -emit-module %t/ConformanceBaseTypes.swift -o %t +// RUN: %target-swift-frontend -emit-module %t/ConformanceDefinition.swift -o %t -I %t /// Check diagnostics. -// RUN: %target-swift-frontend -typecheck -verify %t/ClientA.swift -I %t -package-name pkg -// RUN: %target-swift-frontend -typecheck -verify %t/ClientB.swift -I %t -package-name pkg +// RUN: %target-swift-frontend -typecheck -verify %t/Client.swift -I %t //--- ConformanceBaseTypes.swift public protocol Proto {} public struct ConformingType { - public init () {} + public init () {} } -package protocol PkgProto {} // expected-note 2 {{protocol 'PkgProto' is not '@usableFromInline' or public}} -package struct PkgConformingType { // expected-note 4 {{struct 'PkgConformingType' is not '@usableFromInline' or public}} - package init () {} // expected-note 4 {{initializer 'init()' is not '@usableFromInline' or public}} -} - -//--- ConformanceDefinition1.swift +//--- ConformanceDefinition.swift import ConformanceBaseTypes extension ConformingType : Proto {} -//--- ConformanceDefinition2.swift -import ConformanceBaseTypes -extension PkgConformingType : PkgProto {} - -//--- ClientA.swift +//--- Client.swift public import ConformanceBaseTypes -internal import ConformanceDefinition1 // expected-note 2 {{extension of struct 'ConformingType' imported as 'internal' from 'ConformanceDefinition1' here}} -internal import ConformanceDefinition2 // expected-note 3 {{extension of struct 'PkgConformingType' imported as 'internal' from 'ConformanceDefinition2' here}} +internal import ConformanceDefinition // expected-note 2 {{extension of struct 'ConformingType' imported as 'internal' from 'ConformanceDefinition' here}} -public func useInAPI(a: any Proto = ConformingType()) { // expected-error {{cannot use conformance of 'ConformingType' to 'Proto' here; 'ConformanceDefinition1' was not imported publicly}} -} -public func useInAPI(b: any PkgProto = PkgConformingType()) { - // expected-error@-1 {{cannot use conformance of 'PkgConformingType' to 'PkgProto' here; 'ConformanceDefinition2' was not imported publicly}} - // expected-error@-2 {{function cannot be declared public because its parameter uses a package type}} - // expected-error@-3 {{struct 'PkgConformingType' is package and cannot be referenced from a default argument value}} - // expected-error@-4 {{initializer 'init()' is package and cannot be referenced from a default argument value}} -} -package func useInPkgAPI(a: any PkgProto = PkgConformingType()) { - // expected-error@-1 {{cannot use conformance of 'PkgConformingType' to 'PkgProto' here; 'ConformanceDefinition2' was not imported publicly}} +public func useInAPI(a: any Proto = ConformingType()) { // expected-error {{cannot use conformance of 'ConformingType' to 'Proto' here; 'ConformanceDefinition' was not imported publicly}} } @inlinable public func inlinableFunc() { - let _: any Proto = ConformingType() // expected-error {{cannot use conformance of 'ConformingType' to 'Proto' here; 'ConformanceDefinition1' was not imported publicly}} - - let _: any PkgProto = PkgConformingType() - // expected-error@-1 {{cannot use conformance of 'PkgConformingType' to 'PkgProto' here; 'ConformanceDefinition2' was not imported publicly}} - // expected-error@-2 {{protocol 'PkgProto' is package and cannot be referenced from an '@inlinable' function}} - // expected-error@-3 {{struct 'PkgConformingType' is package and cannot be referenced from an '@inlinable' function}} - // expected-error@-4 {{initializer 'init()' is package and cannot be referenced from an '@inlinable' function}} -} - -//--- ClientB.swift -public import ConformanceBaseTypes -package import ConformanceDefinition1 // expected-note 2 {{extension of struct 'ConformingType' imported as 'package' from 'ConformanceDefinition1' here}} -package import ConformanceDefinition2 // expected-note 2 {{extension of struct 'PkgConformingType' imported as 'package' from 'ConformanceDefinition2' here}} - -public func useInAPI(a: any Proto = ConformingType()) { // expected-error {{cannot use conformance of 'ConformingType' to 'Proto' here; 'ConformanceDefinition1' was imported as package}} -} -public func useInAPI(b: any PkgProto = PkgConformingType()) { - // expected-error@-1 {{cannot use conformance of 'PkgConformingType' to 'PkgProto' here; 'ConformanceDefinition2' was imported as package}} - // expected-error@-2 {{function cannot be declared public because its parameter uses a package type}} - // expected-error@-3 {{struct 'PkgConformingType' is package and cannot be referenced from a default argument value}} - // expected-error@-4 {{initializer 'init()' is package and cannot be referenced from a default argument value}} -} -package func useInPkgAPI(a: any PkgProto = PkgConformingType()) { // no-error -} - -@inlinable public func inlinableFunc() { - let _: any Proto = ConformingType() // expected-error {{cannot use conformance of 'ConformingType' to 'Proto' here; 'ConformanceDefinition1' was imported as package}} - - let _: any PkgProto = PkgConformingType() - // expected-error@-1 {{cannot use conformance of 'PkgConformingType' to 'PkgProto' here; 'ConformanceDefinition2' was imported as package}} - // expected-error@-2 {{protocol 'PkgProto' is package and cannot be referenced from an '@inlinable' function}} - // expected-error@-3 {{struct 'PkgConformingType' is package and cannot be referenced from an '@inlinable' function}} - // expected-error@-4 {{initializer 'init()' is package and cannot be referenced from an '@inlinable' function}} + let _: any Proto = ConformingType() // expected-error {{cannot use conformance of 'ConformingType' to 'Proto' here; 'ConformanceDefinition' was not imported publicly}} } diff --git a/test/Sema/access-level-import-conforming-types.swift b/test/Sema/access-level-import-conforming-types.swift new file mode 100644 index 0000000000000..ca417cc06426e --- /dev/null +++ b/test/Sema/access-level-import-conforming-types.swift @@ -0,0 +1,70 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -emit-module -o %t/NormalLibrary.swiftmodule \ +// RUN: %S/Inputs/implementation-only-import-in-decls-public-helper.swift \ +// RUN: -enable-library-evolution -swift-version 5 + +// RUN: %target-swift-frontend -emit-module -o %t/BADLibrary.swiftmodule \ +// RUN: %S/Inputs/implementation-only-import-in-decls-helper.swift -I %t \ +// RUN: -enable-library-evolution -swift-version 5 + +// RUN: %target-typecheck-verify-swift -I %t \ +// RUN: -swift-version 5 -package-name pkg -enable-library-evolution +// RUN: %target-typecheck-verify-swift -I %t \ +// RUN: -swift-version 5 -package-name pkg + +internal import BADLibrary // expected-note 9 {{protocol 'BadProto' imported as 'internal' from 'BADLibrary' here}} +// expected-note @-1 2 {{struct 'IntLike' imported as 'internal' from 'BADLibrary' here}} +// expected-note @-2 2 {{class 'BadClass' imported as 'internal' from 'BADLibrary' here}} + +public protocol LocalProto {} + +public struct TestConformance: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} +public struct TestConformanceComposition: LocalProto & BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +@usableFromInline struct TestConformanceUFI: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +public class TestConformanceClass: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} +public enum TestConformanceEnum: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +public struct TestExtensionStruct {} +extension TestExtensionStruct: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +package struct TestConformancePackage: BadProto {} // FIXME-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} +package struct TestConformanceCompositionPackage: LocalProto & BadProto {} // FIXME-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +@usableFromInline struct TestConformanceUFIPackage: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +package class TestConformanceClassPackage: BadProto {} // FIXME-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} +package enum TestConformanceEnumPackage: BADLibrary.BadProto {} // FIXME-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +package struct TestExtensionStructPackage {} +extension TestExtensionStructPackage: BadProto {} // FIXME-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +/// Other inheritance types are covered by the classic access-level check. + +public class TestSubclass: BadClass { // expected-error {{class cannot be declared public because its superclass is internal}} +// expected-note @-1 {{class 'BadClass' is imported by this file as 'internal' from 'BADLibrary'}} +} + +public enum TestRawType: IntLike { // expected-error {{enum cannot be declared public because its raw type uses an internal type}} +// expected-note @-1 {{struct 'IntLike' is imported by this file as 'internal' from 'BADLibrary'}} + case x = 1 +} + +public protocol TestRefinedProto: BadProto { // expected-error {{public protocol cannot refine an internal protocol}} +// expected-note @-1 {{protocol 'BadProto' is imported by this file as 'internal' from 'BADLibrary'}} +} + +package class TestSubclassPackage: BadClass { // expected-error {{class cannot be declared package because its superclass is internal}} +// expected-note @-1 {{class 'BadClass' is imported by this file as 'internal' from 'BADLibrary'}} +} + +package enum TestRawTypePackage: IntLike { // expected-error {{enum cannot be declared package because its raw type uses an internal type}} +// expected-note @-1 {{struct 'IntLike' is imported by this file as 'internal' from 'BADLibrary'}} + case x = 1 +} + +package protocol TestRefinedProtoPackage: BadProto { // expected-error {{package protocol cannot refine an internal protocol}} +// expected-note @-1 {{protocol 'BadProto' is imported by this file as 'internal' from 'BADLibrary'}} +} diff --git a/test/Sema/access-level-import-inlinable.swift b/test/Sema/access-level-import-inlinable.swift index 22d7ddfa22c05..5ce02e71e90ac 100644 --- a/test/Sema/access-level-import-inlinable.swift +++ b/test/Sema/access-level-import-inlinable.swift @@ -43,20 +43,6 @@ public struct PackageImportType { public init() {} } -public protocol PackageImportProto { - associatedtype T -} - -public func PackageFunc() {} - -@propertyWrapper -public struct PackageImportWrapper { - public var wrappedValue: T - public init(wrappedValue: T) { - self.wrappedValue = wrappedValue - } -} - //--- InternalLib.swift public protocol InternalImportProto { associatedtype T @@ -90,12 +76,7 @@ public struct PrivateImportType { public import PublicLib package import PackageLib -// expected-note@-1 9 {{struct 'PackageImportType' imported as 'package' from 'PackageLib' here}} -// expected-note@-2 2 {{global function 'PackageFunc()' imported as 'package' from 'PackageLib' here}} -// expected-note@-3 2 {{protocol 'PackageImportProto' imported as 'package' from 'PackageLib' here}} -// expected-note@-4 2 {{initializer 'init()' imported as 'package' from 'PackageLib' here}} -// expected-note@-5 2 {{generic struct 'PackageImportWrapper' imported as 'package' from 'PackageLib' here}} -// expected-note@-6 2 {{initializer 'init(wrappedValue:)' imported as 'package' from 'PackageLib' here}} +// expected-note@-1 4 {{struct 'PackageImportType' imported as 'package' from 'PackageLib' here}} internal import InternalLib // expected-note@-1 9 {{struct 'InternalImportType' imported as 'internal' from 'InternalLib' here}} @@ -109,29 +90,24 @@ fileprivate import FileprivateLib // expected-note@-3 2 {{protocol 'FileprivateImportProto' imported as 'fileprivate' from 'FileprivateLib' here}} private import PrivateLib -// expected-note@-1 12 {{struct 'PrivateImportType' imported as 'private' from 'PrivateLib' here}} -// expected-note@-2 2 {{initializer 'init()' imported as 'private' from 'PrivateLib' here}} +// expected-note@-1 10 {{struct 'PrivateImportType' imported as 'private' from 'PrivateLib' here}} + // expected-note@-2 2 {{initializer 'init()' imported as 'private' from 'PrivateLib' here}} public struct GenericType {} @inlinable public func inlinable() { PublicFunc() - PackageFunc() // expected-error {{global function 'PackageFunc()' is package and cannot be referenced from an '@inlinable' function}} InternalFunc() // expected-error {{global function 'InternalFunc()' is internal and cannot be referenced from an '@inlinable' function}} let _: PublicImportType - let _: PackageImportType // expected-error {{struct 'PackageImportType' is package and cannot be referenced from an '@inlinable' function}} let _: InternalImportType // expected-error {{struct 'InternalImportType' is internal and cannot be referenced from an '@inlinable' function}} let _ = PublicImportType() - let _ = PackageImportType() // expected-error {{struct 'PackageImportType' is package and cannot be referenced from an '@inlinable' function}} - // expected-error @-1 {{initializer 'init()' is package and cannot be referenced from an '@inlinable' function}} let _ = PrivateImportType() // expected-error {{struct 'PrivateImportType' is private and cannot be referenced from an '@inlinable' function}} // expected-error @-1 {{initializer 'init()' is private and cannot be referenced from an '@inlinable' function}} let _: any PublicImportProto - let _: any PackageImportProto // expected-error {{protocol 'PackageImportProto' is package and cannot be referenced from an '@inlinable' function}} let _: any InternalImportProto // expected-error {{protocol 'InternalImportProto' is internal and cannot be referenced from an '@inlinable' function}} let _: any FileprivateImportProto & InternalImportProto // expected-error {{protocol 'FileprivateImportProto' is fileprivate and cannot be referenced from an '@inlinable' function}} @@ -150,10 +126,6 @@ public struct GenericType {} @PublicImportWrapper var wrappedPublic: PublicImportType - @PackageImportWrapper // expected-error {{initializer 'init(wrappedValue:)' is package and cannot be referenced from an '@inlinable' function}} - // expected-error @-1 {{generic struct 'PackageImportWrapper' is package and cannot be referenced from an '@inlinable' function}} - var wrappedPackage: PublicImportType - @FileprivateImportWrapper // expected-error {{initializer 'init(wrappedValue:)' is fileprivate and cannot be referenced from an '@inlinable' function}} // expected-error @-1 {{generic struct 'FileprivateImportWrapper' is fileprivate and cannot be referenced from an '@inlinable' function}} var wrappedFileprivate: PublicImportType @@ -166,21 +138,16 @@ public struct GenericType {} @_alwaysEmitIntoClient public func alwaysEmitIntoClient() { PublicFunc() - PackageFunc() // expected-error {{global function 'PackageFunc()' is package and cannot be referenced from an '@_alwaysEmitIntoClient' function}} InternalFunc() // expected-error {{global function 'InternalFunc()' is internal and cannot be referenced from an '@_alwaysEmitIntoClient' function}} let _: PublicImportType - let _: PackageImportType // expected-error {{struct 'PackageImportType' is package and cannot be referenced from an '@_alwaysEmitIntoClient' function}} let _: InternalImportType // expected-error {{struct 'InternalImportType' is internal and cannot be referenced from an '@_alwaysEmitIntoClient' function}} let _ = PublicImportType() - let _ = PackageImportType() // expected-error {{struct 'PackageImportType' is package and cannot be referenced from an '@_alwaysEmitIntoClient' function}} - // expected-error @-1 {{initializer 'init()' is package and cannot be referenced from an '@_alwaysEmitIntoClient' function}} let _ = PrivateImportType() // expected-error {{struct 'PrivateImportType' is private and cannot be referenced from an '@_alwaysEmitIntoClient' function}} // expected-error @-1 {{initializer 'init()' is private and cannot be referenced from an '@_alwaysEmitIntoClient' function}} let _: any PublicImportProto - let _: any PackageImportProto // expected-error {{protocol 'PackageImportProto' is package and cannot be referenced from an '@_alwaysEmitIntoClient' function}} let _: any InternalImportProto // expected-error {{protocol 'InternalImportProto' is internal and cannot be referenced from an '@_alwaysEmitIntoClient' function}} let _: any FileprivateImportProto & InternalImportProto // expected-error {{protocol 'FileprivateImportProto' is fileprivate and cannot be referenced from an '@_alwaysEmitIntoClient' function}} @@ -199,10 +166,6 @@ public struct GenericType {} @PublicImportWrapper var wrappedPublic: PublicImportType - @PackageImportWrapper // expected-error {{initializer 'init(wrappedValue:)' is package and cannot be referenced from an '@_alwaysEmitIntoClient' function}} - // expected-error @-1 {{generic struct 'PackageImportWrapper' is package and cannot be referenced from an '@_alwaysEmitIntoClient' function}} - var wrappedPackage: PublicImportType - @FileprivateImportWrapper // expected-error {{initializer 'init(wrappedValue:)' is fileprivate and cannot be referenced from an '@_alwaysEmitIntoClient' function}} // expected-error @-1 {{generic struct 'FileprivateImportWrapper' is fileprivate and cannot be referenced from an '@_alwaysEmitIntoClient' function}} var wrappedFileprivate: PublicImportType @@ -217,23 +180,12 @@ public struct GenericType {} // expected-note @-1 {{struct 'PrivateImportType' is imported by this file as 'private' from 'PrivateLib'}} } -@frozen package struct PkgBadFields1 { - private var field: PrivateImportType // expected-error {{type referenced from a stored property in a '@frozen package' struct must be '@usableFromInline', public, or package}} - // expected-note @-1 {{struct 'PrivateImportType' is imported by this file as 'private' from 'PrivateLib'}} -} - @_fixed_layout public struct FixedBadFields1 { // expected-warning@-1 {{'@frozen' attribute is now used for fixed-layout structs}} private var field: PrivateImportType // expected-error {{type referenced from a stored property in a '@frozen' struct must be '@usableFromInline' or public}} // expected-note @-1 {{struct 'PrivateImportType' is imported by this file as 'private' from 'PrivateLib'}} } -@_fixed_layout package struct PkgFixedBadFields1 { - // expected-warning@-1 {{'@frozen' attribute is now used for fixed-layout structs}} - private var field: PrivateImportType // expected-error {{type referenced from a stored property in a '@frozen package' struct must be '@usableFromInline', public, or package}} - // expected-note @-1 {{struct 'PrivateImportType' is imported by this file as 'private' from 'PrivateLib'}} -} - @frozen public struct BadFields2 { private var field: PrivateImportType? // expected-error {{type referenced from a stored property in a '@frozen' struct must be '@usableFromInline' or public}} // expected-note @-1 {{struct 'PrivateImportType' is imported by this file as 'private' from 'PrivateLib'}} @@ -297,17 +249,6 @@ public struct GenericType {} } } -// expected-error@+1 {{the result of a '@usableFromInline' function must be '@usableFromInline' or public}} -@usableFromInline func notReallyUsableFromInlinePkg() -> PackageImportType? { return nil } -// expected-note @-1 {{struct 'PackageImportType' is imported by this file as 'package' from 'PackageLib'}} -@frozen public struct BadFieldsPkg7 { - private var field = notReallyUsableFromInlinePkg() // expected-error {{type referenced from a stored property with inferred type 'PackageImportType?' in a '@frozen' struct must be '@usableFromInline' or public}} -} -@_fixed_layout public struct FrozenBadFieldsPkg7 { - // expected-warning@-1 {{'@frozen' attribute is now used for fixed-layout structs}} - private var field = notReallyUsableFromInlinePkg() // expected-error {{type referenced from a stored property with inferred type 'PackageImportType?' in a '@frozen' struct must be '@usableFromInline' or public}} -} - // expected-error@+1 {{the result of a '@usableFromInline' function must be '@usableFromInline' or public}} @usableFromInline func notReallyUsableFromInline() -> InternalImportType? { return nil } // expected-note @-1 {{struct 'InternalImportType' is imported by this file as 'internal' from 'InternalLib'}} @@ -320,36 +261,13 @@ public struct GenericType {} private var field = notReallyUsableFromInline() // expected-error {{type referenced from a stored property with inferred type 'InternalImportType?' in a '@frozen' struct must be '@usableFromInline' or public}} } -@frozen package struct PkgBadFields7 { - private var field = notReallyUsableFromInline() // expected-error {{type referenced from a stored property with inferred type 'InternalImportType?' in a '@frozen package' struct must be '@usableFromInline', public, or package}} -} -@_fixed_layout package struct PkgFrozenBadFields7 { - // expected-warning@-1 {{'@frozen' attribute is now used for fixed-layout structs}} - private var field = notReallyUsableFromInline() // expected-error {{type referenced from a stored property with inferred type 'InternalImportType?' in a '@frozen package' struct must be '@usableFromInline', public, or package}} -} - @frozen public struct OKFields { - public var field: PublicImportType internal static var staticProp: InternalImportType? private var computed: PrivateImportType? { return nil } } @_fixed_layout public struct FixedOKFields { // expected-warning@-1 {{'@frozen' attribute is now used for fixed-layout structs}} - public var field: PublicImportType - internal static var staticProp: InternalImportType? - private var computed: PrivateImportType? { return nil } -} - -@frozen package struct PkgOKFields { - package var field: PackageImportType - internal static var staticProp: InternalImportType? - private var computed: PrivateImportType? { return nil } -} - -@_fixed_layout package struct PkgFixedOKFields { - // expected-warning@-1 {{'@frozen' attribute is now used for fixed-layout structs}} - package var field: PackageImportType internal static var staticProp: InternalImportType? private var computed: PrivateImportType? { return nil } } diff --git a/test/Sema/access-level-import-package-exportability.swift b/test/Sema/access-level-import-package-exportability.swift deleted file mode 100644 index 48d5e6a4b10cd..0000000000000 --- a/test/Sema/access-level-import-package-exportability.swift +++ /dev/null @@ -1,108 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: split-file %s %t - -// RUN: %target-swift-frontend -emit-module %t/Lib.swift \ -// RUN: -module-name Lib -swift-version 6 -I %t \ -// RUN: -package-name mypkg \ -// RUN: -enable-library-evolution \ -// RUN: -emit-module -emit-module-path %t/Lib.swiftmodule - -// RUN: %target-swift-frontend -typecheck %t/ClientA.swift -I %t -swift-version 6 -package-name mypkg -enable-library-evolution -verify -// RUN: %target-swift-frontend -typecheck %t/ClientB.swift -I %t -swift-version 6 -package-name mypkg -enable-library-evolution -verify -// RUN: %target-swift-frontend -typecheck %t/ClientC.swift -I %t -swift-version 6 -package-name mypkg -enable-library-evolution -verify -// RUN: %target-swift-frontend -typecheck %t/ClientD.swift -I %t -swift-version 6 -package-name mypkg -enable-library-evolution -verify -// RUN: %target-swift-frontend -typecheck %t/ClientE.swift -I %t -swift-version 6 -package-name mypkg -enable-library-evolution -verify -// RUN: %target-swift-frontend -typecheck %t/ClientF.swift -I %t -swift-version 6 -package-name mypkg -enable-library-evolution -verify - -//--- ClientA.swift - -@_implementationOnly import Lib // expected-warning {{'@_implementationOnly' is deprecated, use 'internal import' instead}} - -public func f() -> PubProto? { // expected-error {{cannot use protocol 'PubProto' here; 'Lib' has been imported as implementation-only}} - return nil -} -package func g() -> PkgProto? { // expected-error {{cannot use protocol 'PkgProto' here; 'Lib' has been imported as implementation-only}} - return nil -} - -//--- ClientB.swift -package import Lib // no-warning - -extension PkgStruct { - package static var v: Self { - fatalError() - } -} - -//--- ClientC.swift -package import Lib // no-warning - -extension PkgStruct { - package func f() {} -} - -//--- ClientD.swift -package import Lib // no-warning - -package extension PubStruct { - func f() {} -} - -//--- ClientE.swift -package import Lib - -package enum FeatureFlag: PubProto { // no-warning - case myFeatureFlag - - package var domain: StaticString { "MyDomain" } - package var feature: StaticString { "MyFeature" } - - package var someVar: String { "" } -} - -package struct MyStruct: PubProto { // no-warning - package var someVar: String { "" } -} - -//--- ClientF.swift -package struct PkgStruct {} -public protocol PubProto { - associatedtype CodeUnit -} - -extension PkgStruct { - @frozen - package enum ASCII {} -} - -extension PkgStruct.ASCII: PubProto { - package typealias CodeUnit = UInt8 -} - -//--- Lib.swift - -// expected-note@+1 1{{type declared here}} -public protocol PubProto { - var someVar: String { get } -} - -// expected-note@+1 1{{type declared here}} -package protocol PkgProto { - var someVar: String { get } -} - -public struct PubStruct { - public init() {} -} - -package struct PkgStruct { - package init() {} -} - -public class PubKlass { - public init() {} -} - -package class PkgKlass { - package init() {} -} diff --git a/test/Sema/access-level-import-typealias.swift b/test/Sema/access-level-import-typealias.swift index ec7e72eb441ce..c5934439a1d87 100644 --- a/test/Sema/access-level-import-typealias.swift +++ b/test/Sema/access-level-import-typealias.swift @@ -13,22 +13,6 @@ // RUN: -swift-version 5 -enable-library-evolution \ // RUN: -enable-upcoming-feature InternalImportsByDefault -// RUN: %target-swift-frontend -emit-module %t/Original.swift -o %t \ -// RUN: -swift-version 6 -enable-library-evolution -package-name pkg - -// RUN: %target-swift-frontend -emit-module %t/AliasesPkg.swift -o %t \ -// RUN: -swift-version 6 -enable-library-evolution -I %t -package-name pkg - -// RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesPkg1.swift -I %t \ -// RUN: -swift-version 5 -enable-library-evolution -package-name pkg -// RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesPkg1.swift -I %t \ -// RUN: -swift-version 6 -enable-library-evolution -package-name pkg - -// RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesPkg2.swift -I %t \ -// RUN: -swift-version 5 -enable-library-evolution -package-name pkg -// RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesPkg2.swift -I %t \ -// RUN: -swift-version 6 -enable-library-evolution -package-name pkg - //--- Original.swift open class Clazz {} @@ -40,54 +24,10 @@ public typealias ClazzAlias = Clazz public import Aliases internal import Original // expected-note 2 {{class 'Clazz' imported as 'internal' from 'Original' here}} -// expected-error@+1 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used here because 'Original' was not imported publicly}} +// expected-error@+1 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used in a public or '@usableFromInline' conformance because 'Original' was not imported publicly}} public class InheritsFromClazzAlias: ClazzAlias {} @inlinable public func inlinableFunc() { // expected-error@+1 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used in an '@inlinable' function because 'Original' was not imported publicly}} _ = ClazzAlias.self } - - -//--- AliasesPkg.swift -public import Original // expected-warning {{public import of 'Original' was not used in public declarations or inlinable code}} -package typealias PkgClazzAlias = Clazz // expected-note 2 {{type alias 'PkgClazzAlias' is not '@usableFromInline' or public}} - -//--- UsesAliasesPkg1.swift -public import AliasesPkg // expected-warning {{public import of 'AliasesPkg' was not used in public declarations or inlinable code}} -internal import Original // expected-note 1 {{class 'Clazz' imported as 'internal' from 'Original' here}} - -// expected-error@+1 {{'PkgClazzAlias' aliases 'Original.Clazz' and cannot be used here because 'Original' was not imported publicly}} -package class InheritsFromPkgClazzAlias: PkgClazzAlias {} - -@inlinable public func inlinableFunc() { - // expected-error@+1 {{type alias 'PkgClazzAlias' is package and cannot be referenced from an '@inlinable' function}} - _ = PkgClazzAlias.self -} - -@inlinable package func inlinableFuncPkg() { - // expected-error@+1 {{type alias 'PkgClazzAlias' is package and cannot be referenced from an '@inlinable' function}} - _ = PkgClazzAlias.self -} - - -//--- UsesAliasesPkg2.swift -public import AliasesPkg // expected-warning {{public import of 'AliasesPkg' was not used in public declarations or inlinable code}} -package import Original - -package class InheritsFromPkgClazzAlias: PkgClazzAlias {} // no-error - -package func usePkgClazzAlias() { - _ = PkgClazzAlias.self // no-error -} - -@inlinable public func inlinableFunc() { - // expected-error@+1 {{type alias 'PkgClazzAlias' is package and cannot be referenced from an '@inlinable' function}} - _ = PkgClazzAlias.self -} - -@inlinable package func inlinableFuncPkg() { - // expected-error@+1 {{type alias 'PkgClazzAlias' is package and cannot be referenced from an '@inlinable' function}} - _ = PkgClazzAlias.self -} - diff --git a/test/Sema/conditionally_copyable.swift b/test/Sema/conditionally_copyable.swift index 73ccd71c228a7..2e49e06243a13 100644 --- a/test/Sema/conditionally_copyable.swift +++ b/test/Sema/conditionally_copyable.swift @@ -2,7 +2,7 @@ struct G: ~Copyable {} -extension G: Copyable {} +extension G: Copyable where T: Copyable {} protocol Base {} protocol Derived: Base {} diff --git a/test/Sema/explicit_lifetime_dependence_specifiers1.swift b/test/Sema/explicit_lifetime_dependence_specifiers1.swift index 66f24dff50aa0..1885846631520 100644 --- a/test/Sema/explicit_lifetime_dependence_specifiers1.swift +++ b/test/Sema/explicit_lifetime_dependence_specifiers1.swift @@ -231,3 +231,8 @@ extension RawBufferView { return BufferView(ptr) } } + +func immortalConflict(immortal: UnsafeRawBufferPointer ) -> dependsOn(immortal) BufferView { // expected-error{{conflict between the parameter name and immortal keyword}} + return BufferView(immortal) +} + diff --git a/test/Sema/immutability.swift b/test/Sema/immutability.swift index 00026f169983a..7669a9275b74d 100644 --- a/test/Sema/immutability.swift +++ b/test/Sema/immutability.swift @@ -762,3 +762,16 @@ struct S2 { // expected-note@-1 {{add explicit 'S2.' to refer to mutable static property of 'S2'}} {{5-5=S2.}} } } + +// SR-3680, https://github.com/apple/swift/issues/46265 +protocol HasFoo { + var foo: String { get } +} +protocol CanSetFoo { + var foo: String { get set } +} +extension HasFoo where Self: CanSetFoo { + func bar() { // expected-note {{mark method 'mutating' to make 'self' mutable}}{{3-3=mutating }} + self.foo = "bar" // expected-error {{cannot assign to property: 'self' is immutable}} + } +} diff --git a/test/Sema/implementation-only-import-in-decls.swift b/test/Sema/implementation-only-import-in-decls.swift index c452a6c3b56fd..07f20d4c3d9f2 100644 --- a/test/Sema/implementation-only-import-in-decls.swift +++ b/test/Sema/implementation-only-import-in-decls.swift @@ -11,15 +11,14 @@ import NormalLibrary @_implementationOnly import BADLibrary // expected-warning @-1 {{'@_implementationOnly' is deprecated, use 'internal import' instead}} -public struct TestConformance: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; 'BADLibrary' has been imported as implementation-only}} +public struct TestConformance: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' has been imported as implementation-only}} -@usableFromInline struct TestConformanceUFI: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; 'BADLibrary' has been imported as implementation-only}} +@usableFromInline struct TestConformanceUFI: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' has been imported as implementation-only}} struct TestConformanceOkay: BadProto {} // ok -public class TestConformanceClass: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; 'BADLibrary' has been imported as implementation-only}} -public enum TestConformanceEnum: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; 'BADLibrary' has been imported as implementation-only}} - +public class TestConformanceClass: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' has been imported as implementation-only}} +public enum TestConformanceEnum: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' has been imported as implementation-only}} public struct TestGenericParams {} // expected-error {{cannot use protocol 'BadProto' here; 'BADLibrary' has been imported as implementation-only}} @@ -75,11 +74,11 @@ public protocol TestAssocTypeWhereClause { associatedtype Assoc: Collection where Assoc.Element: BadProto // expected-error {{cannot use protocol 'BadProto' here; 'BADLibrary' has been imported as implementation-only}} } -public enum TestRawType: IntLike { // expected-error {{cannot use struct 'IntLike' here; 'BADLibrary' has been imported as implementation-only}} +public enum TestRawType: IntLike { // expected-error {{cannot use struct 'IntLike' in a public or '@usableFromInline' conformance; 'BADLibrary' has been imported as implementation-only}} case x = 1 } -public class TestSubclass: BadClass { // expected-error {{cannot use class 'BadClass' here; 'BADLibrary' has been imported as implementation-only}} +public class TestSubclass: BadClass { // expected-error {{cannot use class 'BadClass' in a public or '@usableFromInline' conformance; 'BADLibrary' has been imported as implementation-only}} } public typealias TestUnderlying = BadStruct // expected-error {{cannot use struct 'BadStruct' here; 'BADLibrary' has been imported as implementation-only}} @@ -121,7 +120,7 @@ extension Array where Element == BadStruct { subscript(okay _: Int) -> Int { 0 } // okay } -extension Int: @retroactive BadProto {} // expected-error {{cannot use protocol 'BadProto' here; 'BADLibrary' has been imported as implementation-only}} +extension Int: @retroactive BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' has been imported as implementation-only}} struct TestExtensionConformanceOkay {} extension TestExtensionConformanceOkay: BadProto {} // okay diff --git a/test/Sema/missing-import-typealias-swift6.swift b/test/Sema/missing-import-typealias-swift6.swift index 24d021d13b958..5061d2f106300 100644 --- a/test/Sema/missing-import-typealias-swift6.swift +++ b/test/Sema/missing-import-typealias-swift6.swift @@ -28,6 +28,6 @@ public typealias ClazzAlias = Clazz public import Aliases -// expected-error@+1 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used here because 'Original' was not imported by this file}} +// expected-error@+1 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used in a public or '@usableFromInline' conformance because 'Original' was not imported by this file}} public class InheritsFromClazzAlias: ClazzAlias {} diff --git a/test/Sema/missing-import-typealias.swift b/test/Sema/missing-import-typealias.swift index 71862195a55ae..72c560899b3b7 100644 --- a/test/Sema/missing-import-typealias.swift +++ b/test/Sema/missing-import-typealias.swift @@ -7,23 +7,22 @@ // RUN: %target-swift-emit-module-interface(%t/Aliases.swiftinterface) %t/Aliases.swift -I %t // RUN: %target-swift-typecheck-module-from-interface(%t/Aliases.swiftinterface) -I %t -// RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesNoImport.swift -enable-library-evolution -I %t -package-name pkg +// RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesNoImport.swift -enable-library-evolution -I %t // RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesImplementationOnlyImport.swift -enable-library-evolution -I %t // RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesSPIOnlyImport.swift -enable-library-evolution -I %t -experimental-spi-only-imports // RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesWithImport.swift -enable-library-evolution -I %t /// With library evolution disabled UsesAliasesNoImport.swift should compile without diagnostics. -// RUN: %target-swift-frontend -typecheck %t/UsesAliasesNoImport.swift -I %t -package-name pkg | %FileCheck %t/UsesAliasesNoImport.swift --check-prefix=CHECK-NON-RESILIENT --allow-empty +// RUN: %target-swift-frontend -typecheck %t/UsesAliasesNoImport.swift -I %t | %FileCheck %t/UsesAliasesNoImport.swift --check-prefix=CHECK-NON-RESILIENT --allow-empty /// 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 -package-name pkg \ +// 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 -package-name pkg -emit-package-module-interface-path %t/UsesAliasesNoImportFixed.package.swiftinterface +// 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 -// RUN: %target-swift-typecheck-module-from-interface(%t/UsesAliasesNoImportFixed.package.swiftinterface) -I %t -module-name UsesAliasesNoImportFixed /// 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 \ @@ -67,14 +66,10 @@ import Aliases // CHECK-NON-RESILIENT-NOT: was not imported by this file -// 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 the Swift 6 language mode}} +// expected-warning@+2 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used in a public or '@usableFromInline' conformance because 'Original' was not imported by this file; this is an error in the Swift 6 language mode}} // expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} public class InheritsFromClazzAlias: ClazzAlias {} -// 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 the Swift 6 language mode}} -// expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} -package class InheritsFromClazzAliasPackage: ClazzAlias {} - @inlinable public func inlinableFunc() { // 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 the Swift 6 language mode}} // expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} @@ -85,10 +80,6 @@ package class InheritsFromClazzAliasPackage: ClazzAlias {} // expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} public func takesGeneric(_ t: T) {} -// 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 the Swift 6 language mode}} -// expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} -package func takesGenericPackage(_ t: T) {} - public struct HasMembers { // 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 the Swift 6 language mode}} // expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} @@ -101,11 +92,6 @@ extension StructAlias { public func someFunc() {} } -// expected-warning@+2 {{'StructAlias' aliases 'Original.Struct' and cannot be used in an extension with public, package, or '@usableFromInline' members because 'Original' was not imported by this file; this is an error in the Swift 6 language mode}} -// expected-note@+1 {{The missing import of module 'Original' will be added implicitly}} -extension StructAlias { - package func someFuncPackage() {} -} //--- UsesAliasesImplementationOnlyImport.swift diff --git a/test/Sema/package-import-conforming-types.swift b/test/Sema/package-import-conforming-types.swift new file mode 100644 index 0000000000000..9ae7fd2879c30 --- /dev/null +++ b/test/Sema/package-import-conforming-types.swift @@ -0,0 +1,67 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -emit-module -o %t/NormalLibrary.swiftmodule \ +// RUN: %S/Inputs/implementation-only-import-in-decls-public-helper.swift \ +// RUN: -enable-library-evolution -swift-version 5 + +// RUN: %target-swift-frontend -emit-module -o %t/BADLibrary.swiftmodule \ +// RUN: %S/Inputs/implementation-only-import-in-decls-helper.swift -I %t \ +// RUN: -enable-library-evolution -swift-version 5 + +// RUN: %target-typecheck-verify-swift -I %t \ +// RUN: -swift-version 5 -package-name pkg -enable-library-evolution +// RUN: %target-typecheck-verify-swift -I %t \ +// RUN: -swift-version 5 -package-name pkg + +package import BADLibrary // expected-note 8 {{protocol 'BadProto' imported as 'package' from 'BADLibrary' here}} +// expected-note @-1 {{struct 'IntLike' imported as 'package' from 'BADLibrary' here}} +// expected-note @-2 {{class 'BadClass' imported as 'package' from 'BADLibrary' here}} + +public protocol LocalProto {} + +public struct TestConformance: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} +public struct TestConformanceComposition: LocalProto & BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +@usableFromInline struct TestConformanceUFI: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +public class TestConformanceClass: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} +public enum TestConformanceEnum: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +public struct TestExtensionStruct {} +extension TestExtensionStruct: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +package struct TestConformancePackage: BadProto {} +package struct TestConformanceCompositionPackage: LocalProto & BadProto {} + +@usableFromInline struct TestConformanceUFIPackage: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +package class TestConformanceClassPackage: BadProto {} +package enum TestConformanceEnumPackage: BADLibrary.BadProto {} + +package struct TestExtensionStructPackage {} +extension TestExtensionStructPackage: BadProto {} // FIXME-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; 'BADLibrary' was not imported publicly}} + +/// Other inheritance types are covered by the classic access-level check. + +public class TestSubclass: BadClass { // expected-error {{class cannot be declared public because its superclass is package}} +// expected-note @-1 {{class 'BadClass' is imported by this file as 'package' from 'BADLibrary'}} +} + +public enum TestRawType: IntLike { // expected-error {{enum cannot be declared public because its raw type uses a package type}} +// expected-note @-1 {{struct 'IntLike' is imported by this file as 'package' from 'BADLibrary'}} + case x = 1 +} + +public protocol TestRefinedProto: BadProto { // expected-error {{public protocol cannot refine a package protocol}} +// expected-note @-1 {{protocol 'BadProto' is imported by this file as 'package' from 'BADLibrary'}} +} + +package class TestSubclassPackage: BadClass { +} + +package enum TestRawTypePackage: IntLike { + case x = 1 +} + +package protocol TestRefinedProtoPackage: BadProto { +} diff --git a/test/Sema/spi-available-local.swift b/test/Sema/spi-available-local.swift index fff3cfe6c1902..495e37ebfe92b 100644 --- a/test/Sema/spi-available-local.swift +++ b/test/Sema/spi-available-local.swift @@ -10,7 +10,7 @@ public class MacOSSPIClass {} // expected-note {{type declared here}} public class iOSSPIClass {} @available(macOS 10.10, iOS 8.0, *) -public class MacOSDerived: MacOSSPIClass {} // expected-error {{cannot use class 'MacOSSPIClass' here; it is SPI}} +public class MacOSDerived: MacOSSPIClass {} // expected-error {{cannot use class 'MacOSSPIClass' in a public or '@usableFromInline' conformance; it is SPI}} @available(macOS 10.10, iOS 8.0, *) public class iOSDerived: iOSSPIClass {} diff --git a/test/Sema/spi-in-decls.swift b/test/Sema/spi-in-decls.swift index a6a3a5f8f29c1..59e5818cb8857 100644 --- a/test/Sema/spi-in-decls.swift +++ b/test/Sema/spi-in-decls.swift @@ -46,14 +46,14 @@ public struct BadWrapper { // expected-note {{type declared here}} //@_spi(X) //precedencegroup BadPrecedence {} -public struct TestConformance: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; it is SPI}} +public struct TestConformance: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; it is SPI}} -@usableFromInline struct TestConformanceUFI: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; it is SPI}} +@usableFromInline struct TestConformanceUFI: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; it is SPI}} struct TestConformanceOkay: BadProto {} // ok -public class TestConformanceClass: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; it is SPI}} -public enum TestConformanceEnum: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; it is SPI}} +public class TestConformanceClass: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; it is SPI}} +public enum TestConformanceEnum: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; it is SPI}} public struct TestGenericParams {} // expected-error {{cannot use protocol 'BadProto' here; it is SPI}} @@ -105,11 +105,11 @@ public protocol TestAssocTypeWhereClause { associatedtype Assoc: Collection where Assoc.Element: BadProto // expected-error {{cannot use protocol 'BadProto' here; it is SPI}} } -public enum TestRawType: IntLike { // expected-error {{cannot use struct 'IntLike' here; it is SPI}} +public enum TestRawType: IntLike { // expected-error {{cannot use struct 'IntLike' in a public or '@usableFromInline' conformance; it is SPI}} case x = 1 } -public class TestSubclass: BadClass { // expected-error {{cannot use class 'BadClass' here; it is SPI}} +public class TestSubclass: BadClass { // expected-error {{cannot use class 'BadClass' in a public or '@usableFromInline' conformance; it is SPI}} } public typealias TestUnderlying = BadStruct // expected-error {{cannot use struct 'BadStruct' here; it is SPI}} @@ -150,7 +150,7 @@ extension Array where Element == BadStruct { subscript(okay _: Int) -> Int { 0 } // okay } -extension Int: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; it is SPI}} +extension Int: BadProto {} // expected-error {{cannot use protocol 'BadProto' in a public or '@usableFromInline' conformance; it is SPI}} struct TestExtensionConformanceOkay {} extension TestExtensionConformanceOkay: BadProto {} // okay diff --git a/test/Sema/superfluously-public-imports.swift b/test/Sema/superfluously-public-imports.swift index e65eef4d93fc4..b6e7f137c475d 100644 --- a/test/Sema/superfluously-public-imports.swift +++ b/test/Sema/superfluously-public-imports.swift @@ -235,9 +235,7 @@ internal func internalFunc(a: NotAnAPIType = notAnAPIFunc()) {} func implicitlyInternalFunc(a: NotAnAPIType = notAnAPIFunc()) {} // For package decls we only remark on types used in signatures, not for inlinable code. -package func packageFunc(a: PackageType = packageFunc()) {} -// expected-remark@-1 {{struct 'PackageType' is imported via 'ImportUsedInPackage'}} -// expected-remark@-2 {{global function 'packageFunc()' is imported via 'ImportUsedInPackage'}} +package func packageFunc(a: PackageType = packageFunc()) {} // expected-remark {{struct 'PackageType' is imported via 'ImportUsedInPackage'}} @_spi(X) public func spiFunc(a: ToUseFromSPI) {} // expected-remark {{struct 'ToUseFromSPI' is imported via 'SPIOnlyUsedInSPI'}} @@ -249,7 +247,7 @@ public protocol Countable { extension Extended: Countable { // expected-remark {{struct 'Extended' is imported via 'RetroactiveConformance'}} } -extension ExtendedPackageType { // expected-remark 2 {{struct 'ExtendedPackageType' is imported via 'ExtendedPackageTypeImport'}} +extension ExtendedPackageType { // expected-remark {{struct 'ExtendedPackageType' is imported via 'ExtendedPackageTypeImport'}} package func useExtendedPackageType() { } } diff --git a/test/Serialization/Inputs/def_explicit_lifetime_dependence.swift b/test/Serialization/Inputs/def_explicit_lifetime_dependence.swift index cdbd57b8e4e54..a8eb2ac7ee4ab 100644 --- a/test/Serialization/Inputs/def_explicit_lifetime_dependence.swift +++ b/test/Serialization/Inputs/def_explicit_lifetime_dependence.swift @@ -68,3 +68,16 @@ public struct Wrapper : ~Escapable { } } } + +public enum FakeOptional: ~Escapable { + case none, some(Wrapped) +} + +extension FakeOptional: Escapable where Wrapped: Escapable {} + +extension FakeOptional where Wrapped: ~Escapable { + public init(_ nilLiteral: ()) -> dependsOn(immortal) Self { + self = .none + } +} + diff --git a/test/Serialization/Inputs/ncgenerics.swift b/test/Serialization/Inputs/ncgenerics.swift index 7ea772ebb9a90..c657e5ea8bf00 100644 --- a/test/Serialization/Inputs/ncgenerics.swift +++ b/test/Serialization/Inputs/ncgenerics.swift @@ -25,7 +25,7 @@ public enum Maybe: ~Copyable { case none } -extension Maybe: Copyable {} +extension Maybe: Copyable where Wrapped: Copyable {} public func ncIdentity(_ t: consuming T) -> T { return t } diff --git a/test/Serialization/explicit_lifetime_dependence.swift b/test/Serialization/explicit_lifetime_dependence.swift index 1285c006525ba..f450b2ccf6a64 100644 --- a/test/Serialization/explicit_lifetime_dependence.swift +++ b/test/Serialization/explicit_lifetime_dependence.swift @@ -44,6 +44,10 @@ func testReadAccessor() { } } +func testFakeOptional() { + _ = FakeOptional(()) +} + // CHECK: sil @$s32def_explicit_lifetime_dependence6deriveyAA10BufferViewVADYlsF : $@convention(thin) (@guaranteed BufferView) -> _scope(0) @owned BufferView // CHECK: sil @$s32def_explicit_lifetime_dependence16consumeAndCreateyAA10BufferViewVADnYliF : $@convention(thin) (@owned BufferView) -> _inherit(0) @owned BufferView // CHECK: sil @$s32def_explicit_lifetime_dependence15borrowAndCreateyAA10BufferViewVADYlsF : $@convention(thin) (@guaranteed BufferView) -> _scope(0) @owned BufferView diff --git a/test/Serialization/noncopyable_generics.swift b/test/Serialization/noncopyable_generics.swift index 2e2271aa528d8..4b6cada929dad 100644 --- a/test/Serialization/noncopyable_generics.swift +++ b/test/Serialization/noncopyable_generics.swift @@ -18,7 +18,7 @@ // CHECK-PRINT-DAG: protocol Generator { // CHECK-PRINT-DAG: enum Maybe : ~Copyable where Wrapped : ~Copyable { -// CHECK-PRINT-DAG: extension Maybe : Copyable { +// CHECK-PRINT-DAG: extension Maybe : Copyable where Wrapped : Copyable { // CHECK-PRINT-DAG: func ncIdentity(_ t: consuming T) -> T where T : ~Copyable // CHECK-PRINT-DAG: protocol Either : ~Copyable { // CHECK-PRINT-DAG: associatedtype Left : ~Copyable diff --git a/test/SourceKit/Indexing/index_effective_access_level.swift.response b/test/SourceKit/Indexing/index_effective_access_level.swift.response index af824d5ff6344..69cf39a48c6b9 100644 --- a/test/SourceKit/Indexing/index_effective_access_level.swift.response +++ b/test/SourceKit/Indexing/index_effective_access_level.swift.response @@ -1302,14 +1302,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVXeip", + key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVyXeXecip", key.line: 93, key.column: 5, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVXeig", + key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVyXeXecig", key.line: 93, key.column: 46 }, @@ -1333,14 +1333,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVXeip", + key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVyXeXecip", key.line: 94, key.column: 17, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVXeig", + key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVyXeXecig", key.line: 94, key.column: 61 }, @@ -1369,14 +1369,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVXeip", + key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVyXeXecip", key.line: 95, key.column: 13, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVXeig", + key.usr: "s:28index_effective_access_level18ScopeReducerStruct33_2295DDF1454D6A6D9229E8222CD85214LLVyXeXecig", key.line: 95, key.column: 53 }, @@ -2077,14 +2077,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level17ScopeKeeperStructVXeip", + key.usr: "s:28index_effective_access_level17ScopeKeeperStructVyXeXecip", key.line: 121, key.column: 5, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level17ScopeKeeperStructVXeig", + key.usr: "s:28index_effective_access_level17ScopeKeeperStructVyXeXecig", key.line: 121, key.column: 46 }, @@ -2108,14 +2108,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level17ScopeKeeperStructVXe33_2295DDF1454D6A6D9229E8222CD85214Llip", + key.usr: "s:28index_effective_access_level17ScopeKeeperStructVyXeXec33_2295DDF1454D6A6D9229E8222CD85214Llip", key.line: 122, key.column: 17, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level17ScopeKeeperStructVXe33_2295DDF1454D6A6D9229E8222CD85214Llig", + key.usr: "s:28index_effective_access_level17ScopeKeeperStructVyXeXec33_2295DDF1454D6A6D9229E8222CD85214Llig", key.line: 122, key.column: 61 }, @@ -2144,14 +2144,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level17ScopeKeeperStructVXe33_2295DDF1454D6A6D9229E8222CD85214Llip", + key.usr: "s:28index_effective_access_level17ScopeKeeperStructVyXeXec33_2295DDF1454D6A6D9229E8222CD85214Llip", key.line: 123, key.column: 13, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level17ScopeKeeperStructVXe33_2295DDF1454D6A6D9229E8222CD85214Llig", + key.usr: "s:28index_effective_access_level17ScopeKeeperStructVyXeXec33_2295DDF1454D6A6D9229E8222CD85214Llig", key.line: 123, key.column: 53 }, @@ -2852,14 +2852,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVXeip", + key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVyXeXecip", key.line: 149, key.column: 5, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVXeig", + key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVyXeXecig", key.line: 149, key.column: 46 }, @@ -2883,14 +2883,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVXe33_2295DDF1454D6A6D9229E8222CD85214Llip", + key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVyXeXec33_2295DDF1454D6A6D9229E8222CD85214Llip", key.line: 150, key.column: 17, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVXe33_2295DDF1454D6A6D9229E8222CD85214Llig", + key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVyXeXec33_2295DDF1454D6A6D9229E8222CD85214Llig", key.line: 150, key.column: 61 }, @@ -2919,14 +2919,14 @@ { key.kind: source.lang.swift.decl.function.subscript, key.name: "subscript(_:)", - key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVXe33_2295DDF1454D6A6D9229E8222CD85214Llip", + key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVyXeXec33_2295DDF1454D6A6D9229E8222CD85214Llip", key.line: 151, key.column: 13, key.entities: [ { key.kind: source.lang.swift.decl.function.accessor.getter, key.name: "getter:subscript(_:)", - key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVXe33_2295DDF1454D6A6D9229E8222CD85214Llig", + key.usr: "s:28index_effective_access_level25PartialScopeReducerStructVyXeXec33_2295DDF1454D6A6D9229E8222CD85214Llig", key.line: 151, key.column: 53 }, diff --git a/test/SourceKit/Macros/diags.swift.response b/test/SourceKit/Macros/diags.swift.response index e76b8d8667fd1..3327a46dd2599 100644 --- a/test/SourceKit/Macros/diags.swift.response +++ b/test/SourceKit/Macros/diags.swift.response @@ -5,9 +5,9 @@ key.original_location: { key.offset: 1, key.length: 17, - key.buffer_name: "@__swiftmacro_9MacroUser3fooyyF9stringifyfMf_.swift" + key.buffer_name: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX12_10_9stringifyfMf_.swift" }, - key.buffer_name: "@__swiftmacro_9MacroUser3fooyyF9stringifyfMf_11coerceToIntfMf_.swift" + key.buffer_name: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX12_10_9stringifyfMf_11coerceToIntfMf_.swift" }, { key.buffer_text: "(#coerceToInt(\"c\"), #\"#coerceToInt(\"c\")\"#)", @@ -16,7 +16,7 @@ key.length: 29, key.buffer_name: diags.swift }, - key.buffer_name: "@__swiftmacro_9MacroUser3fooyyF9stringifyfMf_.swift" + key.buffer_name: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX12_10_9stringifyfMf_.swift" }, { key.buffer_text: "\"b\" as Int", @@ -25,7 +25,7 @@ key.length: 17, key.buffer_name: diags.swift }, - key.buffer_name: "@__swiftmacro_9MacroUser3fooyyF11coerceToIntfMf0_.swift" + key.buffer_name: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX11_10_11coerceToIntfMf0_.swift" }, { key.buffer_text: "\"a\" as Int", @@ -34,7 +34,7 @@ key.length: 17, key.buffer_name: diags.swift }, - key.buffer_name: "@__swiftmacro_9MacroUser3fooyyF11coerceToIntfMf_.swift" + key.buffer_name: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX10_10_11coerceToIntfMf_.swift" }, { key.buffer_text: "import Swift\n\nprecedencegroup MyPrecedence {\n}\n\n@attached(member) macro myMacro()\n\nextension Int {\n}\n\n@main\nstruct MyMain {\n static func main() {\n }\n}\n\ntypealias Array = Void\n\ntypealias Dictionary = Void\n\ntypealias BooleanLiteralType = Void\n\ntypealias ExtendedGraphemeClusterType = Void\n\ntypealias FloatLiteralType = Void\n\ntypealias IntegerLiteralType = Void\n\ntypealias StringLiteralType = Void\n\ntypealias UnicodeScalarType = Void\n\ntypealias _ColorLiteralType = Void\n\ntypealias _ImageLiteralType = Void\n\ntypealias _FileReferenceLiteralType = Void", @@ -59,7 +59,7 @@ { key.line: 1, key.column: 1, - key.filepath: "@__swiftmacro_9MacroUser3fooyyF9stringifyfMf_11coerceToIntfMf_.swift", + key.filepath: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX12_10_9stringifyfMf_11coerceToIntfMf_.swift", key.severity: source.diagnostic.severity.error, key.id: "cannot_convert_coerce", key.description: "cannot convert value of type 'String' to type 'Int' in coercion", @@ -73,7 +73,7 @@ { key.line: 1, key.column: 2, - key.filepath: "@__swiftmacro_9MacroUser3fooyyF9stringifyfMf_.swift", + key.filepath: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX12_10_9stringifyfMf_.swift", key.severity: source.diagnostic.severity.note, key.id: "in_macro_expansion", key.description: "in expansion of macro 'coerceToInt' here", @@ -103,7 +103,7 @@ { key.line: 1, key.column: 1, - key.filepath: "@__swiftmacro_9MacroUser3fooyyF11coerceToIntfMf0_.swift", + key.filepath: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX11_10_11coerceToIntfMf0_.swift", key.severity: source.diagnostic.severity.error, key.id: "cannot_convert_coerce", key.description: "cannot convert value of type 'String' to type 'Int' in coercion", @@ -133,7 +133,7 @@ { key.line: 1, key.column: 1, - key.filepath: "@__swiftmacro_9MacroUser3fooyyF11coerceToIntfMf_.swift", + key.filepath: "@__swiftmacro_9MacroUser0016diagsswift_eCJAcfMX10_10_11coerceToIntfMf_.swift", key.severity: source.diagnostic.severity.error, key.id: "cannot_convert_coerce", key.description: "cannot convert value of type 'String' to type 'Int' in coercion", diff --git a/test/SourceKit/Macros/macro_basic.swift b/test/SourceKit/Macros/macro_basic.swift index 78990f822d38d..d90a4fd78020d 100644 --- a/test/SourceKit/Macros/macro_basic.swift +++ b/test/SourceKit/Macros/macro_basic.swift @@ -168,7 +168,7 @@ func remoteCall(function: String, arguments: [String // RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=4:7 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=EXPAND %s // RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=4:8 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=EXPAND %s // EXPAND: source.edit.kind.active: -// EXPAND-NEXT: 4:7-4:24 (@__swiftmacro_9MacroUser13testStringify1a1bySi_SitF9stringifyfMf_.swift) "(a + b, "a + b")" +// EXPAND-NEXT: 4:7-4:24 (@__swiftmacro_9MacroUser0022macro_basicswift_tiAIefMX3_6_9stringifyfMf_.swift) "(a + b, "a + b")" //##-- cursor-info on macro declaration // RUN: %sourcekitd-test -req=cursor -pos=57:1 -cursor-action -req-opts=retrieve_symbol_graph=1 %s -- ${COMPILER_ARGS[@]} -parse-as-library | %FileCheck -check-prefix=CURSOR_MACRO_DECL %s @@ -193,7 +193,7 @@ func remoteCall(function: String, arguments: [String // RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=57:1 %s -- ${COMPILER_ARGS[@]} -parse-as-library | %FileCheck -check-prefix=EXPAND_MACRO_DECL %s // RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=57:2 %s -- ${COMPILER_ARGS[@]} -parse-as-library | %FileCheck -check-prefix=EXPAND_MACRO_DECL %s // EXPAND_MACRO_DECL: source.edit.kind.active: -// EXPAND_MACRO_DECL-NEXT: 57:1-57:28 (@__swiftmacro_9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_.swift) "class $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu_ { +// EXPAND_MACRO_DECL-NEXT: 57:1-57:28 (@__swiftmacro_9MacroUser0022macro_basicswift_tiAIefMX56_0_33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_.swift) "class $s9MacroUser0022macro_basicswift_tiAIefMX56_0_33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu_ { // EXPAND_MACRO_DECL-NEXT: func hello() -> String { // EXPAND_MACRO_DECL-NEXT: "hello" // EXPAND_MACRO_DECL-NEXT: } @@ -202,7 +202,7 @@ func remoteCall(function: String, arguments: [String // EXPAND_MACRO_DECL-NEXT: return Self.self // EXPAND_MACRO_DECL-NEXT: } // EXPAND_MACRO_DECL-NEXT: } -// EXPAND_MACRO_DECL-NEXT: enum $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu0_ { +// EXPAND_MACRO_DECL-NEXT: enum $s9MacroUser0022macro_basicswift_tiAIefMX56_0_33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu0_ { // EXPAND_MACRO_DECL-NEXT: case apple // EXPAND_MACRO_DECL-NEXT: case banana // EXPAND_MACRO_DECL-EMPTY: @@ -210,7 +210,7 @@ func remoteCall(function: String, arguments: [String // EXPAND_MACRO_DECL-NEXT: "hello" // EXPAND_MACRO_DECL-NEXT: } // EXPAND_MACRO_DECL-NEXT: } -// EXPAND_MACRO_DECL-NEXT: struct $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu1_: Equatable { +// EXPAND_MACRO_DECL-NEXT: struct $s9MacroUser0022macro_basicswift_tiAIefMX56_0_33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu1_: Equatable { // EXPAND_MACRO_DECL-NEXT: static func == (lhs: Self, rhs: Self) -> Bool { // EXPAND_MACRO_DECL-NEXT: false // EXPAND_MACRO_DECL-NEXT: } diff --git a/test/SourceKit/Macros/macro_semantic_token.swift b/test/SourceKit/Macros/macro_semantic_token.swift index e2f3fa8c50517..9ed010bc17c8c 100644 --- a/test/SourceKit/Macros/macro_semantic_token.swift +++ b/test/SourceKit/Macros/macro_semantic_token.swift @@ -11,8 +11,11 @@ macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition" //##-- Prepare the macro plugin. // RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/../../Macros/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath +// This command just dumps the SILGen in case the buffer name changes and you need to find it. It will always pass. +// RUN: %target-swift-frontend -primary-file %s -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -emit-silgen + // Check the output of the `#anonymousTypes` macro -// RUN: %sourcekitd-test -req=semantic-tokens @__swiftmacro_9MacroUser33_8C2BB8A10AE555140C0EDFDEB4A9572DLl14anonymousTypesfMf_.swift -primary-file %s -- -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser %s | %FileCheck %s --check-prefix IN_BUFFER +// RUN: %sourcekitd-test -req=semantic-tokens @__swiftmacro_9MacroUser0031macro_semantic_tokenswift_yFFIifMX4_0_33_8C2BB8A10AE555140C0EDFDEB4A9572DLl14anonymousTypesfMf_.swift -primary-file %s -- -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser %s | %FileCheck %s --check-prefix IN_BUFFER // Check that we get some semantic tokens. Checking exact offsets is brittle. // IN_BUFFER: source.lang.swift.ref.struct diff --git a/test/SourceKit/Refactoring/find_rename_ranges_enum_case_with_label.swift b/test/SourceKit/Refactoring/find_rename_ranges_enum_case_with_label.swift new file mode 100644 index 0000000000000..4657564a87733 --- /dev/null +++ b/test/SourceKit/Refactoring/find_rename_ranges_enum_case_with_label.swift @@ -0,0 +1,46 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t +// RUN: %sourcekitd-test -req=find-rename-ranges -rename-spec %t/rename-spec.json %t/input.swift | %FileCheck %s + +// CHECK: source.edit.kind.active: +// CHECK-NEXT: 2:8-2:14 source.refactoring.range.kind.basename +// CHECK-NEXT: 2:15-2:20 source.refactoring.range.kind.decl-argument-label arg-index=0 +// CHECK-NEXT: 2:20-2:20 source.refactoring.range.kind.parameter-and-whitespace arg-index=0 +// CHECK-NEXT: source.edit.kind.active: +// CHECK-NEXT: 6:14-6:20 source.refactoring.range.kind.basename +// CHECK-NEXT: 6:21-6:26 source.refactoring.range.kind.call-argument-label arg-index=0 +// CHECK-NEXT: 6:26-6:28 source.refactoring.range.kind.call-argument-colon arg-index=0 + +//--- input.swift +enum MyEnum { + case myCase(label: String) +} + +func test() { + _ = MyEnum.myCase(label: "abc") +} + +//--- rename-spec.json + +[ + { + "key.name": "myCase(label:)", + "key.locations": [ + { + "key.line": 2, + "key.column": 8, + "key.nametype": source.syntacticrename.definition + } + ] + }, + { + "key.name": "myCase(label:)", + "key.locations": [ + { + "key.line": 6, + "key.column": 14, + "key.nametype": source.syntacticrename.call + } + ] + } +] diff --git a/test/SourceKit/Refactoring/find_rename_ranges_enum_case_without_label.swift b/test/SourceKit/Refactoring/find_rename_ranges_enum_case_without_label.swift new file mode 100644 index 0000000000000..60bc091b856c8 --- /dev/null +++ b/test/SourceKit/Refactoring/find_rename_ranges_enum_case_without_label.swift @@ -0,0 +1,44 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t +// RUN: %sourcekitd-test -req=find-rename-ranges -rename-spec %t/rename-spec.json %t/input.swift | %FileCheck %s + +// CHECK: source.edit.kind.active: +// CHECK-NEXT: 2:8-2:14 source.refactoring.range.kind.basename +// CHECK-NEXT: 2:15-2:15 source.refactoring.range.kind.call-argument-combined arg-index=0 +// CHECK-NEXT: source.edit.kind.active: +// CHECK-NEXT: 6:14-6:20 source.refactoring.range.kind.basename +// CHECK-NEXT: 6:21-6:21 source.refactoring.range.kind.call-argument-combined arg-index=0 + +//--- input.swift +enum MyEnum { + case myCase(String) +} + +func test() { + _ = MyEnum.myCase("abc") +} + +//--- rename-spec.json + +[ + { + "key.name": "myCase(_:)", + "key.locations": [ + { + "key.line": 2, + "key.column": 8, + "key.nametype": source.syntacticrename.definition + } + ] + }, + { + "key.name": "myCase(_:)", + "key.locations": [ + { + "key.line": 6, + "key.column": 14, + "key.nametype": source.syntacticrename.call + } + ] + } +] diff --git a/test/SourceKit/Refactoring/find_rename_ranges_enum_case_without_underscore_as_first_name_label.swift b/test/SourceKit/Refactoring/find_rename_ranges_enum_case_without_underscore_as_first_name_label.swift new file mode 100644 index 0000000000000..8dbe54c425191 --- /dev/null +++ b/test/SourceKit/Refactoring/find_rename_ranges_enum_case_without_underscore_as_first_name_label.swift @@ -0,0 +1,45 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t +// RUN: %sourcekitd-test -req=find-rename-ranges -rename-spec %t/rename-spec.json %t/input.swift | %FileCheck %s + +// CHECK: source.edit.kind.active: +// CHECK-NEXT: 2:8-2:14 source.refactoring.range.kind.basename +// CHECK-NEXT: 2:15-2:16 source.refactoring.range.kind.decl-argument-label arg-index=0 +// CHECK-NEXT: 2:16-2:22 source.refactoring.range.kind.parameter-and-whitespace arg-index=0 +// CHECK-NEXT: source.edit.kind.active: +// CHECK-NEXT: 6:14-6:20 source.refactoring.range.kind.basename +// CHECK-NEXT: 6:21-6:21 source.refactoring.range.kind.call-argument-combined arg-index=0 + +//--- input.swift +enum MyEnum { + case myCase(_ label: String) +} + +func test() { + _ = MyEnum.myCase("abc") +} + +//--- rename-spec.json + +[ + { + "key.name": "myCase(:)", + "key.locations": [ + { + "key.line": 2, + "key.column": 8, + "key.nametype": source.syntacticrename.definition + } + ] + }, + { + "key.name": "myCase(:)", + "key.locations": [ + { + "key.line": 6, + "key.column": 14, + "key.nametype": source.syntacticrename.call + } + ] + } +] diff --git a/test/TypeDecoder/constrained_existentials.swift b/test/TypeDecoder/constrained_existentials.swift index b5f5691d3129b..e84ac363d043a 100644 --- a/test/TypeDecoder/constrained_existentials.swift +++ b/test/TypeDecoder/constrained_existentials.swift @@ -5,6 +5,7 @@ // RUN: %lldb-moduleimport-test %t/constrained_existentials -type-from-mangled=%t/input | %FileCheck %s --match-full-lines func blackHole(_: Any...) {} +func blackHole_noncopyable(_: consuming any ~Copyable) {} protocol BaseProto { associatedtype A @@ -43,3 +44,16 @@ do { blackHole(e0, e1, e2) } + +protocol NCProto: ~Copyable {} +struct NC: ~Copyable {} +struct GenNC: ~Copyable, NCProto {} + +do { + let e0: any NCProto & ~Copyable = GenNC() + let e1: any NCProto & ~Copyable = GenNC() + + // FIXME: breaks the MoveChecker (rdar://129885532) +// blackHole_noncopyable(consume e0) +// blackHole_noncopyable(consume e1) +} diff --git a/test/abi/macOS/arm64/concurrency.swift b/test/abi/macOS/arm64/concurrency.swift index 82bf595634742..103d632e582a1 100644 --- a/test/abi/macOS/arm64/concurrency.swift +++ b/test/abi/macOS/arm64/concurrency.swift @@ -66,6 +66,10 @@ Added: _$sScS8IteratorV4next9isolationxSgScA_pSgYi_tYaF // async function pointer to Swift.AsyncStream.Iterator.next(isolation: isolated Swift.Actor?) async -> A? Added: _$sScS8IteratorV4next9isolationxSgScA_pSgYi_tYaFTu +// Swift.TaskGroup.Iterator.next(isolation: isolated Swift.Actor?) async -> A? +Added: _$sScG8IteratorV4next9isolationxSgScA_pSgYi_tYaF +Added: _$sScG8IteratorV4next9isolationxSgScA_pSgYi_tYaFTu + // Swift.ThrowingTaskGroup.Iterator.next(isolation: isolated Swift.Actor?) async throws(B) -> A? Added: _$sScg8IteratorV4next9isolationxSgScA_pSgYi_tYaq_YKF @@ -319,4 +323,3 @@ Added: _$ss9TaskLocalC13withValueImpl_9operation9isolation4file4lineqd__xn_qd__y // Swift.TaskLocal.withValue(_: A, operation: () async throws -> A1, isolation: isolated Swift.Actor?, file: Swift.String, line: Swift.UInt) async throws -> A1 Added: _$ss9TaskLocalC9withValue_9operation9isolation4file4lineqd__x_qd__yYaKXEScA_pSgYiSSSutYaKlF Added: _$ss9TaskLocalC9withValue_9operation9isolation4file4lineqd__x_qd__yYaKXEScA_pSgYiSSSutYaKlFTu - diff --git a/test/abi/macOS/arm64/distributed.swift b/test/abi/macOS/arm64/distributed.swift index bf11ee0bdac88..35d02d2d5ad8e 100644 --- a/test/abi/macOS/arm64/distributed.swift +++ b/test/abi/macOS/arm64/distributed.swift @@ -102,11 +102,5 @@ Added: _$s11Distributed0A5ActorPAAE07asLocalB0ScA_pvpMV // property descriptor for (extension in Distributed):Distributed.DistributedActor.__actorUnownedExecutor : Swift.UnownedSerialExecutor Added: _$s11Distributed0A5ActorPAAE22__actorUnownedExecutorScevpMV -// (extension in Distributed):Distributed.DistributedActor.whenLocal(@Sendable (isolated A) async throws(B1) -> A1) async throws(B1) -> A1? -Added: _$s11Distributed0A5ActorPAAE9whenLocalyqd__Sgqd__xYiYaYbqd_0_YKXEYaqd_0_YKs8SendableRd__s5ErrorRd_0_r0_lF - -// async function pointer to (extension in Distributed):Distributed.DistributedActor.whenLocal(@Sendable (isolated A) async throws(B1) -> A1) async throws(B1) -> A1? -Added: _$s11Distributed0A5ActorPAAE9whenLocalyqd__Sgqd__xYiYaYbqd_0_YKXEYaqd_0_YKs8SendableRd__s5ErrorRd_0_r0_lFTu - // Distributed._distributedStubFatalError(function: Swift.String) -> Swift.Never Added: _$s11Distributed26_distributedStubFatalError8functions5NeverOSS_tF diff --git a/test/abi/macOS/x86_64/concurrency.swift b/test/abi/macOS/x86_64/concurrency.swift index ad40572037ff7..c3a2785c3beb3 100644 --- a/test/abi/macOS/x86_64/concurrency.swift +++ b/test/abi/macOS/x86_64/concurrency.swift @@ -66,6 +66,10 @@ Added: _$sScS8IteratorV4next9isolationxSgScA_pSgYi_tYaF // async function pointer to Swift.AsyncStream.Iterator.next(isolation: isolated Swift.Actor?) async -> A? Added: _$sScS8IteratorV4next9isolationxSgScA_pSgYi_tYaFTu +// Swift.TaskGroup.Iterator.next(isolation: isolated Swift.Actor?) async -> A? +Added: _$sScG8IteratorV4next9isolationxSgScA_pSgYi_tYaF +Added: _$sScG8IteratorV4next9isolationxSgScA_pSgYi_tYaFTu + // Swift.ThrowingTaskGroup.Iterator.next(isolation: isolated Swift.Actor?) async throws(B) -> A? Added: _$sScg8IteratorV4next9isolationxSgScA_pSgYi_tYaq_YKF @@ -318,4 +322,4 @@ Added: _$ss9TaskLocalC13withValueImpl_9operation9isolation4file4lineqd__xn_qd__y Added: _$ss9TaskLocalC13withValueImpl_9operation9isolation4file4lineqd__xn_qd__yYaKXEScA_pSgYiSSSutYaKlFTu // Swift.TaskLocal.withValue(_: A, operation: () async throws -> A1, isolation: isolated Swift.Actor?, file: Swift.String, line: Swift.UInt) async throws -> A1 Added: _$ss9TaskLocalC9withValue_9operation9isolation4file4lineqd__x_qd__yYaKXEScA_pSgYiSSSutYaKlF -Added: _$ss9TaskLocalC9withValue_9operation9isolation4file4lineqd__x_qd__yYaKXEScA_pSgYiSSSutYaKlFTu \ No newline at end of file +Added: _$ss9TaskLocalC9withValue_9operation9isolation4file4lineqd__x_qd__yYaKXEScA_pSgYiSSSutYaKlFTu diff --git a/test/abi/macOS/x86_64/distributed.swift b/test/abi/macOS/x86_64/distributed.swift index 5b6071c90b132..82ed7c9d54400 100644 --- a/test/abi/macOS/x86_64/distributed.swift +++ b/test/abi/macOS/x86_64/distributed.swift @@ -102,11 +102,5 @@ Added: _$s11Distributed0A5ActorPAAE07asLocalB0ScA_pvpMV // property descriptor for (extension in Distributed):Distributed.DistributedActor.__actorUnownedExecutor : Swift.UnownedSerialExecutor Added: _$s11Distributed0A5ActorPAAE22__actorUnownedExecutorScevpMV -// (extension in Distributed):Distributed.DistributedActor.whenLocal(@Sendable (isolated A) async throws(B1) -> A1) async throws(B1) -> A1? -Added: _$s11Distributed0A5ActorPAAE9whenLocalyqd__Sgqd__xYiYaYbqd_0_YKXEYaqd_0_YKs8SendableRd__s5ErrorRd_0_r0_lF - -// async function pointer to (extension in Distributed):Distributed.DistributedActor.whenLocal(@Sendable (isolated A) async throws(B1) -> A1) async throws(B1) -> A1? -Added: _$s11Distributed0A5ActorPAAE9whenLocalyqd__Sgqd__xYiYaYbqd_0_YKXEYaqd_0_YKs8SendableRd__s5ErrorRd_0_r0_lFTu - // Distributed._distributedStubFatalError(function: Swift.String) -> Swift.Never Added: _$s11Distributed26_distributedStubFatalError8functions5NeverOSS_tF diff --git a/test/attr/attr_fixed_layout_property_wrapper.swift b/test/attr/attr_fixed_layout_property_wrapper.swift index f3cf1ae60bfce..643e207837e4e 100644 --- a/test/attr/attr_fixed_layout_property_wrapper.swift +++ b/test/attr/attr_fixed_layout_property_wrapper.swift @@ -1,9 +1,8 @@ // RUN: %target-typecheck-verify-swift -swift-version 5 -package-name myPkg -private class PrivateType {} -// expected-note@-1 2 {{class 'PrivateType' is not '@usableFromInline' or public}} -// expected-note@-2 2 {{initializer 'init()' is not '@usableFromInline' or public}} -// expected-note@-3 2 {{type declared here}} +private class PrivateType {} // expected-note {{class 'PrivateType' is not '@usableFromInline' or public}} +// expected-note@-1 {{initializer 'init()' is not '@usableFromInline' or public}} +// expected-note@-2 {{type declared here}} package class PackageType { // expected-note@-1 {{class 'PackageType' is not '@usableFromInline' or public}} @@ -45,20 +44,3 @@ public struct Wrapper { @Wrapper private var z1: PackageTypeForInline @Wrapper private var z2 = PackageTypeForInline() } - - -@frozen package struct FrozenPackageStruct { - @Wrapper private var p1: PrivateType - // expected-error@-1 {{type referenced from a stored property in a '@frozen package' struct must be '@usableFromInline', public, or package}} - - @Wrapper private var p2 = PrivateType() - // expected-error@-1 {{class 'PrivateType' is private and cannot be referenced from a property initializer in a '@frozen' type}} - // expected-error@-2 {{initializer 'init()' is private and cannot be referenced from a property initializer in a '@frozen' type}} - // expected-error@-3 {{type referenced from a stored property with inferred type 'PrivateType' in a '@frozen package' struct must be '@usableFromInline', public, or package}} - - // no-errors below - @Wrapper private var q1: PackageType - @Wrapper private var q2 = PackageType() - @Wrapper private var r1: PackageTypeForInline - @Wrapper private var r2 = PackageTypeForInline() -} diff --git a/test/attr/attr_noescape.swift b/test/attr/attr_noescape.swift index c14f74b0d4450..8bd3e5e227e42 100644 --- a/test/attr/attr_noescape.swift +++ b/test/attr/attr_noescape.swift @@ -89,29 +89,29 @@ class SomeClass { takesNoEscapeClosure { foo(); return 0 } } - let _: () -> Void = { // expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{26-26= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{26-26= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{26-26= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{26-26= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} + let _: () -> Void = { // expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{26-26= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{26-26= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{26-26= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{26-26= [self] in}} func inner() { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} - let inner2 = { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} + let inner2 = { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{21-21= [self] in}} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} let _ = inner2 func multi() -> Int { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} - let multi2: () -> Int = { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{33-33=self.}} + let multi2: () -> Int = { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{32-32= [self] in}} expected-note{{reference 'self.' explicitly}} {{33-33=self.}} let _ = multi2 - doesEscape { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{20-20=self.}} + doesEscape { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{19-19= [self] in}} expected-note{{reference 'self.' explicitly}} {{20-20=self.}} takesNoEscapeClosure { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{30-30=self.}} - doesEscape { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{20-20=self.}} + doesEscape { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{19-19= [self] in}} expected-note{{reference 'self.' explicitly}} {{20-20=self.}} takesNoEscapeClosure { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{30-30=self.}} } - doesEscape { // expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{17-17= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{17-17= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{17-17= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{17-17= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} - func inner() { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} - let inner2 = { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} + doesEscape { //expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{17-17= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{17-17= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{17-17= [self] in}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{17-17= [self] in}} + func inner() { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} + let inner2 = { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{21-21= [self] in}} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} _ = inner2 - func multi() -> Int { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} - let multi2: () -> Int = { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{33-33=self.}} + func multi() -> Int { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} + let multi2: () -> Int = { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{32-32= [self] in}} expected-note{{reference 'self.' explicitly}} {{33-33=self.}} _ = multi2 - doesEscape { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{20-20=self.}} + doesEscape { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{19-19= [self] in}} expected-note{{reference 'self.' explicitly}} {{20-20=self.}} takesNoEscapeClosure { foo() } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{30-30=self.}} - doesEscape { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{20-20=self.}} + doesEscape { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{19-19= [self] in}} expected-note{{reference 'self.' explicitly}} {{20-20=self.}} takesNoEscapeClosure { foo(); return 0 } // expected-error {{call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{30-30=self.}} return 0 } diff --git a/test/attr/escaping_inout_arugment.swift b/test/attr/escaping_inout_arugment.swift new file mode 100644 index 0000000000000..8f72298352de9 --- /dev/null +++ b/test/attr/escaping_inout_arugment.swift @@ -0,0 +1,7 @@ +// RUN: %target-typecheck-verify-swift + +let _: (_ v: inout @escaping () -> Void) -> () +// expected-error@-1 {{inout expression is implicitly escaping}}{{20-30=}} + +func m(v: inout @escaping () -> Void) {} +// expected-error@-1 {{inout expression is implicitly escaping}}{{17-27=}} diff --git a/test/decl/protocol/req/deprecated.swift b/test/decl/protocol/req/deprecated.swift new file mode 100644 index 0000000000000..dfbf524f65928 --- /dev/null +++ b/test/decl/protocol/req/deprecated.swift @@ -0,0 +1,60 @@ +// RUN: %target-typecheck-verify-swift + +protocol DeprecatedRequirement { + @available(*, deprecated) + func f() +} + +extension DeprecatedRequirement { + @available(*, deprecated) + func f() {} +} + +// No warning if both the requirement and the default implementation are deprecated +struct S1: DeprecatedRequirement {} + +protocol DeprecatedDefault { + func f() // expected-note {{requirement 'f()' declared here}} +} + +extension DeprecatedDefault { + @available(*, deprecated) + func f() {} // expected-note {{'f()' declared here}} +} + +// expected-warning@+1 {{deprecated default implementation is used to satisfy instance method 'f()' required by protocol 'DeprecatedDefault'}} +struct S2: DeprecatedDefault {} + +// No warning if the conformance itself is deprecated +@available(*, deprecated) +struct S3: DeprecatedDefault { +} + +struct S4: DeprecatedDefault { + func f() {} +} + +struct S5 {} + +// No warning if the conformance itself is deprecated +@available(*, deprecated) +extension S5: DeprecatedDefault {} + +@available(*, deprecated) +enum UnavailableEnum { + struct Nested: DeprecatedDefault {} +} + +// Include message string from @available attribute if provided +protocol DeprecatedDefaultWithMessage { + func f() // expected-note {{requirement 'f()' declared here}} +} + +extension DeprecatedDefaultWithMessage { + @available(*, deprecated, message: "write it yourself") + func f() {} // expected-note {{'f()' declared here}} +} + + +// expected-warning@+1 {{deprecated default implementation is used to satisfy instance method 'f()' required by protocol 'DeprecatedDefaultWithMessage': write it yourself}} +struct S6: DeprecatedDefaultWithMessage {} diff --git a/test/embedded/classes.swift b/test/embedded/classes.swift index 74d94899751d4..4c88dc37e4f66 100644 --- a/test/embedded/classes.swift +++ b/test/embedded/classes.swift @@ -15,9 +15,15 @@ class MyClass { } class MySubClass: MyClass { + var x = 27 + override init() { print("MySubClass.init") } deinit { print("MySubClass.deinit") } override func foo() { print("MySubClass.foo") } + + func printX() { + print(x) + } } class MySubSubClass: MySubClass { @@ -26,6 +32,17 @@ class MySubSubClass: MySubClass { override func foo() { print("MySubSubClass.foo") } } +class OtherSubClass: MyClass {} + +func testCasting(_ title: StaticString, _ c: MyClass) { + print(title, terminator: "") + if let s = c as? MySubClass { + s.printX() + } else { + print("-") + } +} + @main struct Main { static var o: (MyClass?, MyClass?, MyClass?) = (nil, nil, nil) @@ -69,5 +86,14 @@ struct Main { // CHECK: MySubClass.deinit // CHECK: MyClass.deinit print("") + + // CHECK: base: - + testCasting("base: ", MyClass()) + // CHECK: sub: 27 + testCasting("sub: ", MySubClass()) + // CHECK: subsub: 27 + testCasting("subsub: ", MySubSubClass()) + // CHECK: other: - + testCasting("other: ", OtherSubClass()) } } diff --git a/test/embedded/float-abi-hard.swift b/test/embedded/float-abi-hard.swift new file mode 100644 index 0000000000000..b3a955a104450 --- /dev/null +++ b/test/embedded/float-abi-hard.swift @@ -0,0 +1,35 @@ +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s + +// RUN: %target-swift-emit-ir %t/Main.swift -import-bridging-header %t/BridgingHeader.h -parse-as-library -enable-experimental-feature Embedded -wmo \ +// RUN: -target armv7em-none-none-eabi -Xcc -mthumb -Xcc -mcpu=cortex-m7 -Xcc -mfloat-abi=hard -Xcc -mfpu=fpv5-sp-d16 -Xcc -D__FPU_USED=1 -Xcc -falign-functions=16 + +// REQUIRES: swift_in_compiler +// REQUIRES: optimized_stdlib +// REQUIRES: OS=macosx || OS=linux-gnu +// REQUIRES: CODEGENERATOR=ARM + +// BEGIN BridgingHeader.h + +typedef struct +{ + float x; + float y; + float width; + float height; +} Rect; + +typedef void FunctionType(Rect, Rect); +void (* _Nonnull callback)(FunctionType * _Nonnull func); +void c_function(Rect, Rect); + +// BEGIN Main.swift + +@main +struct Main { + static func main() { + callback({ a, b in + c_function(a, b) + }) + } +} diff --git a/test/embedded/mirror.swift b/test/embedded/mirror.swift new file mode 100644 index 0000000000000..c0352c20cf74b --- /dev/null +++ b/test/embedded/mirror.swift @@ -0,0 +1,14 @@ +// RUN: %target-swift-emit-ir -verify %s -enable-experimental-feature Embedded -wmo + +// REQUIRES: swift_in_compiler +// REQUIRES: optimized_stdlib +// REQUIRES: OS=macosx || OS=linux-gnu + +public struct MyStruct { + var a, b, c: Int +} + +public func foo(s: MyStruct) { + let mirror = Mirror(reflecting: s) // expected-error {{'Mirror' is unavailable}} + _ = mirror.children +} \ No newline at end of file diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift index 9b75765bbac00..9a71e1748b680 100644 --- a/test/expr/closure/closures.swift +++ b/test/expr/closure/closures.swift @@ -171,14 +171,14 @@ class ExplicitSelfRequiredTest { doStuff({ [unowned(unsafe) self] in x+1 }) doStuff({ [unowned self = self] in x+1 }) doStuff({ x+1 }) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} expected-note{{reference 'self.' explicitly}} {{15-15=self.}} - doVoidStuff({ doStuff({ x+1 })}) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} + doVoidStuff({ doStuff({ x+1 })}) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{28-28= [self] in}} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} doVoidStuff({ [self] in doStuff({ x+1 })}) // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{38-38= [self] in}} expected-note{{reference 'self.' explicitly}} {{39-39=self.}} doVoidStuff({ x += 1 }) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} expected-note{{reference 'self.' explicitly}} {{19-19=self.}} doVoidStuff({ _ = "\(x)"}) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} expected-note{{reference 'self.' explicitly}} {{26-26=self.}} doVoidStuff({ [y = self] in x += 1 }) // expected-warning {{capture 'y' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{20-20=self, }} expected-note{{reference 'self.' explicitly}} {{33-33=self.}} doStuff({ [y = self] in x+1 }) // expected-warning {{capture 'y' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} - doVoidStuff({ [self = ExplicitSelfRequiredTest()] in x += 1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} - doStuff({ [self = ExplicitSelfRequiredTest()] in x+1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuff({ [self = ExplicitSelfRequiredTest()] in x += 1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-warning {{capture 'self' was never used}} + doStuff({ [self = ExplicitSelfRequiredTest()] in x+1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-warning {{capture 'self' was never used}} // Methods follow the same rules as properties, uses of 'self' without capturing must be marked with "self." doStuff { method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} expected-note{{reference 'self.' explicitly}} {{15-15=self.}} @@ -187,8 +187,8 @@ class ExplicitSelfRequiredTest { doVoidStuff { () -> () in _ = method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self]}} expected-note{{reference 'self.' explicitly}} {{35-35=self.}} doVoidStuff { [y = self] in _ = method() } // expected-warning {{capture 'y' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{20-20=self, }} expected-note{{reference 'self.' explicitly}} {{37-37=self.}} doStuff({ [y = self] in method() }) // expected-warning {{capture 'y' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} - doVoidStuff({ [self = ExplicitSelfRequiredTest()] in _ = method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} - doStuff({ [self = ExplicitSelfRequiredTest()] in method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuff({ [self = ExplicitSelfRequiredTest()] in _ = method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-warning {{capture 'self' was never used}} + doStuff({ [self = ExplicitSelfRequiredTest()] in method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-warning {{capture 'self' was never used}} doVoidStuff { _ = self.method() } doVoidStuff { [self] in _ = method() } doVoidStuff { [self = self] in _ = method() } @@ -790,15 +790,15 @@ public class TestImplicitSelfForWeakSelfCapture { method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } - doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} - doVoidStuff { + doVoidStuff { + doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } } - doVoidStuff { [self] in + doVoidStuff { [self] in // expected-warning {{capture 'self' was never used}} doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} - method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} + method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } } } @@ -839,7 +839,7 @@ public class TestImplicitSelfForWeakSelfCapture { } doVoidStuffNonEscaping { [weak self] in - guard let self = self else { return } + guard let self = self else { return } // expected-warning {{value 'self' was defined but never used; consider replacing with boolean test}} doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } @@ -896,8 +896,8 @@ public class TestImplicitSelfForWeakSelfCapture { method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } - doVoidStuff { [self] in - method() + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} self.method() } @@ -1229,24 +1229,24 @@ class TestGithubIssue70089 { doVoidStuff { [weak self] in guard let self else { return } - doVoidStuff { [self] in - x += 1 + doVoidStuff { [self] in // expected-warning {{capture 'self' was never used}} expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} } doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } - doVoidStuff { [self = TestGithubIssue70089()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + doVoidStuff { [self = TestGithubIssue70089()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} x += 1 // expected-error{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 - doVoidStuff { - x += 1 // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuff { // expected-note {{'self' explicitly to enable implicit 'self' in this closure}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} self.x += 1 } - doVoidStuff { [self] in + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } @@ -1262,8 +1262,8 @@ class TestGithubIssue70089 { self?.method() } - doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} - doVoidStuff { + doVoidStuff { + doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} self.x += 1 } @@ -1271,29 +1271,29 @@ class TestGithubIssue70089 { doVoidStuff { [self] in doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} - x += 1 // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} self.x += 1 } } doVoidStuff { - doVoidStuff { [self] in - x += 1 + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } } doVoidStuff { [weak self] in - doVoidStuff { - x += 1 // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note{{reference 'self?.' explicitly}} + doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} self?.x += 1 } } doVoidStuff { [weak self] in doVoidStuffNonEscaping { - x += 1 // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note{{reference 'self?.' explicitly}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self?.x += 1 } } @@ -1302,27 +1302,27 @@ class TestGithubIssue70089 { // Since this unwrapping is invalid, implicit self is disallowed in all nested closures: guard let self = self ?? TestGithubIssue70089.staticOptional else { return } - doVoidStuff { [self] in + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } doVoidStuffNonEscaping { - x += 1 // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } - doVoidStuff { [self = TestGithubIssue70089()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - doVoidStuff { [self] in + doVoidStuff { [self = TestGithubIssue70089()] in + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } doVoidStuff { [self] in - doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} - doVoidStuff { + doVoidStuff { + doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} x += 1 // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} self.x += 1 } @@ -1348,51 +1348,55 @@ class TestGithubIssue69911 { doVoidStuff { [weak self] in guard let self else { return } + // This stops being an error in Swift 6 mode. doVoidStuffNonEscaping { - x += 1 + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } + // This stops being an error in Swift 6 mode. doVoidStuffNonEscaping { doVoidStuffNonEscaping { - x += 1 + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } - doVoidStuff { [self] in + // This stops being an error in Swift 6 mode. + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} doVoidStuffNonEscaping { - x += 1 + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } + // This stops being an error in Swift 6 mode. doVoidStuffNonEscaping { [self] in doVoidStuffNonEscaping { [self] in - x += 1 + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } doVoidStuffNonEscaping { [weak self] in - doVoidStuffNonEscaping { // expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} + doVoidStuffNonEscaping { guard let self else { return } - x += 1 // expected-error{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} + x += 1 // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } - doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - x += 1 // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 - doVoidStuff { [self] in + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} x += 1 // expected-error{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } doVoidStuffNonEscaping { - x += 1 // expected-warning{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } @@ -1408,33 +1412,33 @@ class TestGithubIssue69911 { guard let self = self ?? TestGithubIssue69911.staticOptional else { return } doVoidStuffNonEscaping { - x += 1 // expected-warning{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } doVoidStuffNonEscaping { doVoidStuffNonEscaping { - x += 1 // expected-warning{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } - doVoidStuff { [self] in + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} doVoidStuffNonEscaping { - x += 1 // expected-warning{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } doVoidStuffNonEscaping { [self] in doVoidStuffNonEscaping { [self] in - x += 1 // expected-warning{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } - doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - x += 1 // expected-warning{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } @@ -1443,9 +1447,9 @@ class TestGithubIssue69911 { self?.x += 1 } - doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in doVoidStuffNonEscaping { [self] in - x += 1 // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + x += 1 // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} self.x += 1 } } @@ -1456,7 +1460,7 @@ class TestGithubIssue69911 { doVoidStuff { [weak self] in self?.x += 1 guard let self else { return } - x += 1 // expected-warning{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + x += 1 // This refers to the 'self' of the function self.x += 1 } } @@ -1477,7 +1481,7 @@ final class AutoclosureTests { withNonEscapingAutoclosure(bar()) withEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} - doVoidStuff { [self] in + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} << This is a false positive withNonEscapingAutoclosure(bar()) withEscapingAutoclosure(bar()) // expected-warning {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} @@ -1493,8 +1497,9 @@ final class AutoclosureTests { withNonEscapingAutoclosure(bar()) } + // NOTE: This is a false positive doVoidStuffNonEscaping { [self] in - withNonEscapingAutoclosure(bar()) + withNonEscapingAutoclosure(bar()) // expected-warning {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} } doVoidStuff { @@ -1510,35 +1515,35 @@ final class AutoclosureTests { } } - doVoidStuff { [weak self] in + doVoidStuff { [weak self] in // expected-warning {{variable 'self' was written to, but never read}} withNonEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} } - doVoidStuff { [weak self] in + doVoidStuff { [weak self] in // expected-warning {{variable 'self' was written to, but never read}} withEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } - doVoidStuff { [weak self] in - doVoidStuff { - withNonEscapingAutoclosure(bar()) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + doVoidStuff { [weak self] in // expected-warning {{variable 'self' was written to, but never read}} + doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} + withNonEscapingAutoclosure(bar()) // expected-error {{all to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } } - doVoidStuff { [weak self] in + doVoidStuff { [weak self] in // expected-warning {{variable 'self' was written to, but never read}} doVoidStuff { - withEscapingAutoclosure(bar()) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + withEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } } doVoidStuff { [weak self] in - doVoidStuff { [self] in - withNonEscapingAutoclosure(bar()) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + doVoidStuff { [self] in // expected-warning {{capture 'self' was never used}} expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + withNonEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} } } doVoidStuff { [weak self] in - doVoidStuff { [self] in - withEscapingAutoclosure(bar()) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + doVoidStuff { [self] in // expected-warning {{capture 'self' was never used}} + withEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } } @@ -1546,18 +1551,18 @@ final class AutoclosureTests { guard let self else { return } withNonEscapingAutoclosure(bar()) - withEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} + withEscapingAutoclosure(bar()) doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} withNonEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } doVoidStuffNonEscaping { - withNonEscapingAutoclosure(bar()) + withNonEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} } - doVoidStuffNonEscaping { [self] in - withNonEscapingAutoclosure(bar()) + doVoidStuffNonEscaping { [self] in // expected-warning {{capture 'self' was never used}} + withNonEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} } doVoidStuff { @@ -1568,14 +1573,14 @@ final class AutoclosureTests { withEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } - doVoidStuffNonEscaping { [self] in - withEscapingAutoclosure(bar()) // expected-warning {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} + doVoidStuffNonEscaping { [self] in // expected-warning {{capture 'self' was never used}} + withEscapingAutoclosure(bar()) // expected-error {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } } doVoidStuff { [weak self] in - doVoidStuff { [self] in - guard let self else { return } + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + guard let self else { return } // expected-warning {{value 'self' was defined but never used; consider replacing with boolean test}} method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} } } @@ -1589,36 +1594,36 @@ final class AutoclosureTests { doVoidStuff { [weak self] in let someOptional: Self? = Self() - var `self` = self ?? someOptional + var `self` = self ?? someOptional // expected-warning {{'self' was never mutated; consider changing to 'let' constant}} guard let self = self else { return } // This is not supposed to be permitted, but has been allowed since Swift 5.8, // so we have to continue allowing it to maintain source compatibility. - method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + method() } - doVoidStuff { + doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} let someOptional: Self? = Self() - guard case let self = someOptional else { return } - method() // expected-error{{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + guard case let self = someOptional else { return } // expected-warning {{immutable value 'self' was never used; consider replacing with '_' or removing it}} + method() // expected-error{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } // This isn't supposed to be accepted, but has been accepted since Swift 5.8 doVoidStuff { [weak self = x] in guard let self else { return } - method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + method() } doVoidStuff { [weak self] in - doVoidStuff { [self] in - guard let self else { return } + doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + guard let self else { return } // expected-warning {{value 'self' was defined but never used; consider replacing with boolean test}} method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} } } doVoidStuff { [weak self] in doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} - guard let self = self else { return } - method() // expected-error{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} + guard let self = self else { return } // expected-warning {{value 'self' was defined but never used; consider replacing with boolean test}} + method() // expected-error{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} } } } @@ -1630,36 +1635,36 @@ class TestInvalidRebindingOutsideOfClosure { func testInvalidRebindingCondition() { guard case let self = TestInvalidRebindingOutsideOfClosure() else { return } // expected-warning {{'guard' condition is always true, body is unreachable}} - doVoidStuff { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + doVoidStuff { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-warning {{capture 'self' was never used}} method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} } // Allowed in Swift 5 mode for source compatibility: - doVoidStuffNonEscaping { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + doVoidStuffNonEscaping { [self] in // expected-warning {{capture 'self' was never used}} + method() } doVoidStuff() { [weak self] in guard let self else { return } - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + method() } doVoidStuffNonEscaping() { [weak self] in guard let self else { return } - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + method() } doVoidStuff { [weak self] in guard let self = self else { return } - doVoidStuff { [self] in + doVoidStuff { [self] in // expected-warning {{capture 'self' was never used}} expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} } } doVoidStuffNonEscaping { [weak self] in guard let self = self else { return } - doVoidStuffNonEscaping { [self] in - method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + doVoidStuffNonEscaping { [self] in // expected-warning {{capture 'self' was never used}} + method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} } } } @@ -1667,46 +1672,46 @@ class TestInvalidRebindingOutsideOfClosure { func testInvalidSelfWithBackticks() { let `self` = TestInvalidRebindingOutsideOfClosure() - doVoidStuff { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + doVoidStuff { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-warning {{capture 'self' was never used}} method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} } // Allowed in Swift 5 mode for source compatibility: - doVoidStuffNonEscaping { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + doVoidStuffNonEscaping { [self] in // expected-warning {{capture 'self' was never used}} + method() } doVoidStuff() { [weak self] in guard let self else { return } - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + method() } doVoidStuffNonEscaping() { [weak self] in guard let self else { return } - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + method() } } func testInvalidSelfWithBackticks2() { let `self` = self - doVoidStuff { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} + doVoidStuff { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-warning {{capture 'self' was never used}} method() // expected-error{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} } // Allowed in Swift 5 mode for source compatibility: - doVoidStuffNonEscaping { [self] in // expected-note{{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuffNonEscaping { [self] in // expected-warning {{capture 'self' was never used}} + method() } doVoidStuff() { [weak self] in guard let self else { return } - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + method() } doVoidStuffNonEscaping() { [weak self] in guard let self else { return } - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + method() } } @@ -1717,18 +1722,18 @@ struct TestInvalidSelfCaptureInStruct { func bar() { // To maintain source compatibility, we continue allowing this in Swift 5 mode: - doVoidStuff { [self = TestInvalidSelfCaptureInStruct()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + doVoidStuff { [self = TestInvalidSelfCaptureInStruct()] in + method() // This refers to the 'self' of the function. self.method() } - doVoidStuffNonEscaping { [self = TestInvalidSelfCaptureInStruct()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + doVoidStuffNonEscaping { [self = TestInvalidSelfCaptureInStruct()] in + method() // This refers to the 'self' of the function. self.method() } - doVoidStuffNonEscaping { [self = TestInvalidSelfCaptureInStruct()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} - method() // expected-warning{{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode}} + doVoidStuffNonEscaping { [self = TestInvalidSelfCaptureInStruct()] in + method() // This refers to the 'self' of the function. self.method() } } @@ -1752,3 +1757,38 @@ struct TestAsyncLetInStruct { } } } + +// rdar://129475277 +class rdar129475277 { + func bar() -> Int { 0 } + func method() {} + + func test1() { + takesEscapingWithAllowedImplicitSelf { [weak self] in // expected-warning {{variable 'self' was written to, but never read}} + takesEscapingWithAllowedImplicitSelf { + method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + } + } + + takesEscapingWithAllowedImplicitSelf { [weak self] in // expected-warning {{variable 'self' was written to, but never read}} + takesEscapingWithAllowedImplicitSelf { + doVoidStuffNonEscaping { + withNonEscapingAutoclosure(bar()) // expected-warning {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} + } + } + } + + takesEscapingWithAllowedImplicitSelf { [weak self] in // expected-warning {{variable 'self' was written to, but never read}} + withNonEscapingAutoclosure(bar()) // expected-warning {{call to method 'bar' in closure requires explicit use of 'self' to make capture semantics explicit}} + } + } + + func test2() { + guard case let self: rdar129475277? = nil else { return } + // expected-warning@-1 {{'guard' condition is always true, body is unreachable}} + // expected-warning@-2 {{immutable value 'self' was never used}} + doVoidStuffNonEscaping { + method() + } + } +} diff --git a/test/expr/closure/closures_swift6.swift b/test/expr/closure/closures_swift6.swift index f8c1f8b8c3700..8d2f43097ba89 100644 --- a/test/expr/closure/closures_swift6.swift +++ b/test/expr/closure/closures_swift6.swift @@ -181,6 +181,11 @@ public final class TestImplicitSelfForWeakSelfCapture: Sendable { method() self.method() } + + doVoidStuff { [self] in + method() + self.method() + } } doVoidStuffNonEscaping { [weak self] in @@ -805,3 +810,37 @@ struct TestInvalidSelfCaptureInStruct { } } } + +// rdar://129475277 +class rdar129475277 { + func bar() -> Int { 0 } + func method() {} + + func test1() { + takesEscapingWithAllowedImplicitSelf { [weak self] in + takesEscapingWithAllowedImplicitSelf { + method() // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + } + } + + takesEscapingWithAllowedImplicitSelf { [weak self] in + takesEscapingWithAllowedImplicitSelf { + doVoidStuffNonEscaping { + withNonEscapingAutoclosure(bar()) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + } + } + } + + takesEscapingWithAllowedImplicitSelf { [weak self] in + withNonEscapingAutoclosure(bar()) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + } + } + + func test2() { + guard case let self: rdar129475277? = nil else { return } + // expected-warning@-1 {{'guard' condition is always true, body is unreachable}} + doVoidStuffNonEscaping { + method() // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}} + } + } +} diff --git a/test/expr/closure/implicit_weak_capture.swift b/test/expr/closure/implicit_weak_capture.swift index 905854f779f14..96b7688a1f20e 100644 --- a/test/expr/closure/implicit_weak_capture.swift +++ b/test/expr/closure/implicit_weak_capture.swift @@ -1,4 +1,4 @@ -// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking) +// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking -swift-version 6) // REQUIRES: concurrency // REQUIRES: executable_test diff --git a/test/refactoring/SyntacticRename/Outputs/types/case-other.swift.expected b/test/refactoring/SyntacticRename/Outputs/types/case-other.swift.expected index 915828f17a671..2a1786116f14d 100644 --- a/test/refactoring/SyntacticRename/Outputs/types/case-other.swift.expected +++ b/test/refactoring/SyntacticRename/Outputs/types/case-other.swift.expected @@ -27,7 +27,7 @@ extension /*class-Animal:def*/Animal { enum /*enum-Barcode:def*/Barcode { case upc(Int, Int, Int, Int) case /*case-qrCode:def*/qrCode(code: String) - case /*case-other:def*/other(Int) + case /*case-other:def*/other(Int) case /*case-another:def*/another } var barCode: /*enum-Barcode*/Barcode = /*enum-Barcode*/Barcode.upc(1, 1, 1, 1) diff --git a/test/stdlib/CaseIterableTests.swift b/test/stdlib/CaseIterableTests.swift index 0e10bbbc21c63..687357938612e 100644 --- a/test/stdlib/CaseIterableTests.swift +++ b/test/stdlib/CaseIterableTests.swift @@ -1,5 +1,6 @@ // RUN: %target-run-simple-swift %t // REQUIRES: executable_test +// REQUIRES: concurrency import StdlibUnittest @@ -16,4 +17,14 @@ CaseIterableTests.test("Simple Enums") { expectEqual(SimpleEnum.allCases, [.bar, .baz, .quux]) } +CaseIterableTests.test("MainActor Isolated Enums") { + @MainActor + enum EnumMainActor: CaseIterable { + case a, b + } + + expectEqual(EnumMainActor.allCases.count, 2) + expectEqual(EnumMainActor.allCases, [.a, .b]) +} + runAllTests() diff --git a/test/stmt/typed_throws.swift b/test/stmt/typed_throws.swift index 0d0878c9144a9..ab1fb7776c9d8 100644 --- a/test/stmt/typed_throws.swift +++ b/test/stmt/typed_throws.swift @@ -1,5 +1,7 @@ // RUN: %target-typecheck-verify-swift -enable-experimental-feature FullTypedThrows +// REQUIRES: asserts + enum MyError: Error { case failed case epicFailed diff --git a/test/type/explicit_existential.swift b/test/type/explicit_existential.swift index 1b9f8632cd97c..d977e4deb1caf 100644 --- a/test/type/explicit_existential.swift +++ b/test/type/explicit_existential.swift @@ -478,6 +478,22 @@ func testAnyFixIt() { let _: (((((~Copyable) & NonCopyableHasAssoc) & NonCopyableHasAssoc).Type.Type)).Type? let _: any (((((~Copyable) & NonCopyableHasAssoc) & NonCopyableHasAssoc).Type.Type)).Type // OK + // Misplaced '!'. + // expected-error@+1 {{force unwrapped 'any' type must be written (any HasAssoc)!}}{{10-23=(any HasAssoc)!}} + let _: any HasAssoc! + + // expected-error@+1 {{using '!' is not allowed here; perhaps '?' was intended}}{{16-29=(any HasAssoc)?}} + let _: (Int, any HasAssoc!) + + // expected-error@+1 {{using '!' is not allowed here; perhaps '?' was intended}}{{12-19=(any PP)?}} + let _: G + + // expected-error@+1 {{using '!' is not allowed here; perhaps '?' was intended}}{{11-18=(any PP)?}} + let _: (any PP!) -> Void + + // expected-error@+1 {{using '!' is not allowed here; perhaps '?' was intended}}{{11-17=(any PP)?}} + let _: (any P!)? + // Misplaced '?'. // expected-error@+1 {{optional 'any' type must be written '(any HasAssoc)?'}}{{10-23=(any HasAssoc)?}} @@ -485,7 +501,7 @@ func testAnyFixIt() { // FIXME: Better recovery // expected-error@+1 {{type '(any Copyable)?' cannot be suppressed}} let _: any ~Copyable? - // expected-error@+1 {{optional 'any' type must be written '(any HasAssoc.Type)?'}}{{10-28=(any HasAssoc.Type)?}} + // expected-error@+1 {{using '!' is not allowed here; perhaps '?' was intended}}{{10-28=(any HasAssoc.Type)?}} let _: any HasAssoc.Type? // FIXME: Better recovery // expected-error@+1 {{type '(any Copyable.Type)?' cannot be suppressed}} diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp index b4b03957db391..fafeb80fa87bd 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp @@ -448,7 +448,7 @@ static bool initDocEntityInfo(const Decl *D, } Info.IsUnavailable = AvailableAttr::isUnavailable(D); - Info.IsDeprecated = D->getAttrs().getDeprecated(D->getASTContext()) != nullptr; + Info.IsDeprecated = D->getAttrs().isDeprecated(D->getASTContext()); Info.IsOptional = D->getAttrs().hasAttribute(); if (auto *AFD = dyn_cast(D)) { Info.IsAsync = AFD->hasAsync(); diff --git a/utils/availability-macros.def b/utils/availability-macros.def index 828314c02ed01..28d1647eb80e7 100644 --- a/utils/availability-macros.def +++ b/utils/availability-macros.def @@ -35,7 +35,8 @@ SwiftStdlib 5.7:macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0 SwiftStdlib 5.8:macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4 SwiftStdlib 5.9:macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0 SwiftStdlib 5.10:macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.1 -SwiftStdlib 6.0:macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999 +SwiftStdlib 6.0:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0 +SwiftStdlib 6.1:macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999 # TODO: Also update ASTContext::getSwift510Availability when needed # TODO: Also update ASTContext::getSwift60Availability when needed diff --git a/utils/build.ps1 b/utils/build.ps1 index 51d9a63c7a13c..09cdbb9a4e93e 100644 --- a/utils/build.ps1 +++ b/utils/build.ps1 @@ -836,11 +836,11 @@ function Build-CMakeProject { } if ($Platform -eq "Android") { - $vsWherePath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" - $vsInstallPath = & $vsWherePath -latest -property installationPath - if (Test-Path "${vsInstallPath}\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin") { - $env:Path = "${vsInstallPath}\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin;${vsInstallPath}\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja;${env:Path}" - TryAdd-KeyValue $Defines CMAKE_MAKE_PROGRAM "${vsInstallPath}\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $VSInstallPath = & $vswhere -nologo -latest -products * -property installationPath + if (Test-Path "${VSInstallPath}\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin") { + $env:Path = "${VSInstallPath}\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin;${VSInstallPath}\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja;${env:Path}" + TryAdd-KeyValue $Defines CMAKE_MAKE_PROGRAM "${VSInstallPath}\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" } else { throw "Missing CMake and Ninja in the visual studio installation that are needed to build Android" } @@ -1068,7 +1068,7 @@ function Build-CMakeProject { } if ($UseBuiltCompilers.Contains("Swift")) { - $env:Path = "$($HostArch.SDKInstallRoot)\usr\bin;$($HostArch.BinaryCache)\cmark-gfm-0.29.0.gfm.13\src;$($HostArch.ToolchainInstallRoot)\usr\bin;${env:Path}" + $env:Path = "$($BuildArch.SDKInstallRoot)\usr\bin;$($BuildArch.BinaryCache)\cmark-gfm-0.29.0.gfm.13\src;$($BuildArch.ToolchainInstallRoot)\usr\bin;${env:Path}" } elseif ($UsePinnedCompilers.Contains("Swift")) { $env:Path = "$(Get-PinnedToolchainRuntime);${env:Path}" } @@ -1629,6 +1629,7 @@ function Build-Dispatch([Platform]$Platform, $Arch, [switch]$Test = $false) { function Build-Foundation([Platform]$Platform, $Arch, [switch]$Test = $false) { $DispatchBinaryCache = Get-TargetProjectBinaryCache $Arch Dispatch + $SwiftSyntaxDir = Get-HostProjectCMakeModules Compilers $FoundationBinaryCache = Get-TargetProjectBinaryCache $Arch Foundation $ShortArch = $Arch.LLVMName @@ -1655,7 +1656,7 @@ function Build-Foundation([Platform]$Platform, $Arch, [switch]$Test = $false) { -InstallTo $InstallPath ` -Arch $Arch ` -Platform $Platform ` - -UseBuiltCompilers ASM,C,Swift ` + -UseBuiltCompilers ASM,C,CXX,Swift ` -BuildTargets $Targets ` -Defines (@{ FOUNDATION_BUILD_TOOLS = if ($Platform -eq "Windows") { "YES" } else { "NO" }; @@ -1695,6 +1696,10 @@ function Build-Foundation([Platform]$Platform, $Arch, [switch]$Test = $false) { }; ZLIB_INCLUDE_DIR = "$LibraryRoot\zlib-1.3.1\usr\include"; dispatch_DIR = "$DispatchBinaryCache\cmake\modules"; + SwiftSyntax_DIR = "$SwiftSyntaxDir"; + _SwiftFoundation_SourceDIR = "$SourceCache\swift-foundation"; + _SwiftFoundationICU_SourceDIR = "$SourceCache\swift-foundation-icu"; + _SwiftCollections_SourceDIR = "$SourceCache\swift-collections" } + $TestingDefines) } } @@ -1772,6 +1777,7 @@ function Install-Platform([Platform]$Platform, $Arch) { Copy-File "$PlatformLibSrc\$($Arch.LLVMName)\*.lib" "$PlatformLibDst\$($Arch.LLVMName)\" } Android { + Copy-File "$PlatformLibSrc\*.a" "$PlatformLibDst\$($Arch.LLVMName)\" Copy-File "$PlatformLibSrc\*.so" "$PlatformLibDst\$($Arch.LLVMName)\" } } diff --git a/utils/swift_build_support/swift_build_support/products/swiftdriver.py b/utils/swift_build_support/swift_build_support/products/swiftdriver.py index 14363fc59f796..ff3e0f02506af 100644 --- a/utils/swift_build_support/swift_build_support/products/swiftdriver.py +++ b/utils/swift_build_support/swift_build_support/products/swiftdriver.py @@ -92,10 +92,6 @@ def run_build_script_helper(action, host_target, product, args): dispatch_build_dir = os.path.join( build_root, '%s-%s' % ('libdispatch', host_target)) - # Pass Foundation directory down if we built it - foundation_build_dir = os.path.join( - build_root, '%s-%s' % ('foundation', host_target)) - # Pass the swift lit tests if we're testing and the Swift tests were built swift_build_dir = os.path.join( build_root, 'swift-{}'.format(host_target)) @@ -118,10 +114,6 @@ def run_build_script_helper(action, host_target, product, args): helper_cmd += [ '--dispatch-build-dir', dispatch_build_dir ] - if os.path.exists(foundation_build_dir): - helper_cmd += [ - '--foundation-build-dir', foundation_build_dir - ] if os.path.exists(lit_test_dir) and action == 'test': helper_cmd += [ '--lit-test-dir', lit_test_dir diff --git a/utils/swift_build_support/swift_build_support/products/swiftpm.py b/utils/swift_build_support/swift_build_support/products/swiftpm.py index 6c698d22b58bd..c9024e64bdaab 100644 --- a/utils/swift_build_support/swift_build_support/products/swiftpm.py +++ b/utils/swift_build_support/swift_build_support/products/swiftpm.py @@ -84,15 +84,6 @@ def run_bootstrap_script(self, action, host_target, additional_params=[]): "--dispatch-build-dir", dispatch_build_dir ] - # Pass Foundation directory down if we built it - foundation_build_dir = os.path.join( - build_root, '%s-%s' % ("foundation", host_target)) - - if os.path.exists(foundation_build_dir): - helper_cmd += [ - "--foundation-build-dir", foundation_build_dir - ] - # Pass Cross compile host info if self.has_cross_compile_hosts(): if self.is_darwin_host(host_target): diff --git a/utils/update_checkout/update-checkout-config.json b/utils/update_checkout/update-checkout-config.json index 5ee039c43c3d2..c93a9e6efc36e 100644 --- a/utils/update_checkout/update-checkout-config.json +++ b/utils/update_checkout/update-checkout-config.json @@ -125,7 +125,7 @@ "swiftpm": "main", "swift-argument-parser": "1.2.3", "swift-atomics": "1.2.0", - "swift-collections": "1.0.5", + "swift-collections": "1.1.1", "swift-crypto": "3.0.0", "swift-certificates": "1.0.1", "swift-asn1": "1.0.0", @@ -178,7 +178,7 @@ "swiftpm": "release/6.0", "swift-argument-parser": "1.2.3", "swift-atomics": "1.2.0", - "swift-collections": "1.0.5", + "swift-collections": "1.1.1", "swift-crypto": "3.0.0", "swift-certificates": "1.0.1", "swift-asn1": "1.0.0", @@ -274,7 +274,7 @@ "swiftpm": "main", "swift-argument-parser": "1.2.3", "swift-atomics": "1.2.0", - "swift-collections": "1.0.5", + "swift-collections": "1.1.1", "swift-crypto": "3.0.0", "swift-certificates": "1.0.1", "swift-asn1": "1.0.0", @@ -657,7 +657,7 @@ "swift-argument-parser": "1.2.3", "swift-async-algorithms": "1.0.0", "swift-atomics": "1.2.0", - "swift-collections": "1.0.5", + "swift-collections": "1.1.1", "swift-crypto": "3.0.0", "swift-certificates": "1.0.1", "swift-asn1": "1.0.0", diff --git a/validation-test/IRGen/issue-72719.swift b/validation-test/IRGen/issue-72719.swift new file mode 100644 index 0000000000000..b839ea796ce03 --- /dev/null +++ b/validation-test/IRGen/issue-72719.swift @@ -0,0 +1,15 @@ +// RUN: %target-swift-frontend -emit-ir -g %s > /dev/null + +// https://github.com/apple/swift/issues/72719 + +protocol D {} +struct U: D, Equatable {} +class Q {} +class R {} +extension R where E == U { + struct S {} + static func a(_: T) -> R { + let x = Q>() + fatalError() + } +} diff --git a/validation-test/ParseableInterface/rdar128577611.swift b/validation-test/ParseableInterface/rdar128577611.swift index 18ca4b791b179..a4086137ad521 100644 --- a/validation-test/ParseableInterface/rdar128577611.swift +++ b/validation-test/ParseableInterface/rdar128577611.swift @@ -7,4 +7,10 @@ struct InternalStruct {} extension [Int: InternalStruct]: Sendable {} // CHECK: @available(*, unavailable) -// CHECK: extension Swift.Dictionary : Swift.Copyable, Swift.Escapable, Swift.Sendable where Key : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {} +// CHECK-NEXT: extension Swift.Dictionary : Swift.Copyable where Key : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {} + +// CHECK: @available(*, unavailable) +// CHECK-NEXT: extension Swift.Dictionary : Swift.Escapable where Key : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {} + +// CHECK: @available(*, unavailable) +// CHECK-NEXT: extension Swift.Dictionary : Swift.Sendable where Key : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {} diff --git a/validation-test/SILOptimizer/consume_checking.swift b/validation-test/SILOptimizer/consume_checking.swift new file mode 100644 index 0000000000000..dcb5c4faceb07 --- /dev/null +++ b/validation-test/SILOptimizer/consume_checking.swift @@ -0,0 +1,42 @@ +// RUN: %target-swift-frontend \ +// RUN: -emit-sil -verify \ +// RUN: %s \ +// RUN: -sil-verify-all + +//////////////////////////////////////////////////////////////////////////////// +// https://github.com/apple/swift/issues/69252 {{ +//////////////////////////////////////////////////////////////////////////////// +public enum LineEnding: String { + /// The default unix `\n` character + case lineFeed = "\n" + /// MacOS line ending `\r` character + case carriageReturn = "\r" + /// Windows line ending sequence `\r\n` + case carriageReturnLineFeed = "\r\n" + + /// Initialize a line ending from a line string. + /// - Parameter line: The line to use + public init?(line: borrowing String) { + guard let lastChar = line.last, + let lineEnding = LineEnding(rawValue: String(lastChar)) else { return nil } + self = lineEnding + } + + + static func makeLineEnding(_ line: borrowing String) -> LineEnding? { + guard let lastChar = line.last, + let lineEnding = LineEnding(rawValue: String(lastChar)) else { return nil } + _ = lineEnding + return nil + } + + func makeLineEnding(_ line: borrowing String) -> LineEnding? { + guard let lastChar = line.last, + let lineEnding = LineEnding(rawValue: String(lastChar)) else { return nil } + _ = lineEnding + return nil + } +} +//////////////////////////////////////////////////////////////////////////////// +// https://github.com/apple/swift/issues/69252 }} +//////////////////////////////////////////////////////////////////////////////// diff --git a/validation-test/SILOptimizer/issue-71495.swift b/validation-test/SILOptimizer/issue-71495.swift new file mode 100644 index 0000000000000..9b74e326ceb64 --- /dev/null +++ b/validation-test/SILOptimizer/issue-71495.swift @@ -0,0 +1,48 @@ +// RUN: %target-run-simple-swift(-Xfrontend -sil-verify-all) +// RUN: %target-run-simple-swift(-O -Xfrontend -sil-verify-all) + +// REQUIRES: executable_test + +/// A unique value represented by a heap memory location. +struct Handle: ~Copyable { + var address: UnsafeMutableRawPointer + + init() { + self.address = .allocate(byteCount: 2, alignment: 2) + } + + consuming func done() { + let address = self.address + discard self + address.deallocate() + print("deallocated handle via done()") + } + + deinit { + address.deallocate() + print("deallocated handle via deinit") + } +} + +func description(of pointer: UnsafeRawPointer) -> String { + let address = UInt(bitPattern: pointer) + return "0x" + String(address, radix: 16) +} + +func borrowHandleAndCrashNoMore(_ handle: borrowing Handle) -> String { + var string = "" + return string.withUTF8 { _ in + description(of: handle.address) + } +} + +let handleDescription: String + +do { + let handle = Handle() + handleDescription = borrowHandleAndCrashNoMore(handle) + handle.done() +} + +// CHECK: result: 0x +print("result: \(handleDescription)") diff --git a/validation-test/SILOptimizer/issue-72615.swift b/validation-test/SILOptimizer/issue-72615.swift new file mode 100644 index 0000000000000..74004d6b39c2b --- /dev/null +++ b/validation-test/SILOptimizer/issue-72615.swift @@ -0,0 +1,29 @@ +// RUN: %target-swift-frontend \ +// RUN: %s \ +// RUN: -emit-sil -verify \ +// RUN: -sil-verify-all + +func doStuffUniquely(with value: consuming [Int]) { + // If we received the last remaining reference to `value`, we'd like + // to be able to efficiently update it without incurring more copies. + var newValue = consume value + newValue.append(42) +} + +func test() { + var x: [Int] = [1,2,3] + + // x is appended to. After this point, we know that x is unique. We want to + // preserve that property. + x.append(5) + + // Pass the current value of x off to another function, that + doStuffUniquely(with: consume x) + + // Reset x to a new value. Since we don't use the old value anymore, + x = [] + doMoreStuff(with: &x) +} + +func doMoreStuff(with value: inout [Int]) { +} diff --git a/validation-test/Sema/issue-46000.swift b/validation-test/Sema/issue-46000.swift new file mode 100644 index 0000000000000..1911a16189997 --- /dev/null +++ b/validation-test/Sema/issue-46000.swift @@ -0,0 +1,24 @@ +// RUN: %target-typecheck-verify-swift +// REQUIRES: OS=macosx + +// https://github.com/apple/swift/issues/46000 + +import Dispatch +import Foundation + +extension DispatchData { + + func asFoundationData(execute: (Data) throws -> T) rethrows -> T { + + //FIXME: SWIFT(SR-3097) - DispatchData.withUnsafeBytes crashes when empty. + guard isEmpty == false else { + return try execute(Data()) + } + + return try withUnsafeBytes { (ptr: UnsafePointer) -> Void in + // expected-error@-1 {{cannot convert return expression of type 'Void' to return type 'T'}} + let foundationData = Data(bytesNoCopy: UnsafeMutableRawPointer(mutating: ptr), count: count, deallocator: .none) + return try execute(foundationData) // expected-error {{cannot convert value of type 'T' to closure result type 'Void'}} + } + } +}