diff --git a/CHANGELOG.md b/CHANGELOG.md index 4040f144bf239..ad496e0758840 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,88 @@ _**Note:** This is in reverse chronological order, so newer entries are added to ## Swift 5.7 +* References to `optional` methods on a protocol metatype, as well as references to dynamically looked up methods on the `AnyObject` metatype are now supported. These references always have the type of a function that accepts a single argument and returns an optional value of function type: + + ```swift + class Object { + @objc func getTag() -> Int + } + + @objc protocol P { + @objc optional func didUpdateObject(withTag tag: Int) + } + + let getTag: (AnyObject) -> (() -> Int)? = AnyObject.getTag + + let didUpdateObject: (any P) -> ((Int) -> Void)? = P.didUpdateObject + ``` + +* [SE-0349][]: + + Loading data from raw memory represented by `UnsafeRawPointer`, + `UnsafeRawBufferPointer` and their mutable counterparts now supports unaligned + accesses. This previously required a workaround involving an intermediate + copy: + + ```swift + let result = unalignedData.withUnsafeBytes { buffer -> UInt32 in + var storage = UInt32.zero + withUnsafeMutableBytes(of: &storage) { + $0.copyBytes(from: buffer.prefix(MemoryLayout.size)) + } + return storage + } + ``` + Now: + ```swift + let result = unalignedData.withUnsafeBytes { $0.loadUnaligned(as: UInt32.self) } + ``` + Additionally, the counterpart `storeBytes(of:toByteOffset:as:)` had its + alignment restriction lifted, so that storing to arbitrary offsets of raw + memory can now succeed. + +* [SE-0334][]: + + - `UnsafeRawPointer` and `UnsafeMutableRawPointer` have new functionality for + pointer arithmetic, adding functions to obtain a pointer advanced to the next + or previous alignment boundary: + + ```swift + extension UnsafeRawPointer { + public func alignedUp(for: T.type) -> UnsafeRawPointer + public func alignedDown(for: T.type) -> UnsafeRawPointer + public func alignedUp(toMultipleOf alignment: Int) -> UnsafeRawPointer + public func alignedDown(toMultipleOf alignment: Int) -> UnsafeRawPointer + } + ``` + - It is now possible to use a pointer to `struct` to obtain a pointer to one + of its stored properties: + + ```swift + withUnsafeMutablePointer(to: &myStruct) { + let interiorPointer = $0.pointer(to: \.myProperty)! + return myCFunction(interiorPointer) + } + ``` + - Comparisons between pointers have been simplified by being more permissive. + Since pointers are representations of memory locations within a single pool of + underlying memory, Swift now allows comparing pointers without requiring type + conversions with the `==`, `!=`, `<`,`<=`,`>`, and `>=` operators. + +* [SE-0333][]: + + It is now possible to use the `withMemoryRebound()` method on raw memory, + that is `UnsafeRawPointer` , `UnsafeRawBufferPointer` and their mutable + counterparts. Additionally, we clarified the semantics of + `withMemoryRebound()` when used on typed memory (`UnsafePointer`, + `UnsafeBufferPointer` and their mutable counterparts). Whereas + `Pointee` and `T` were previously required to have the same stride, you can + now rebind in cases where `Pointee` is an aggregate of `T` or vice-versa. For + example, given an `UnsafeMutableBufferPointer`, you can now use + `withMemoryRebound` to operate temporarily on a + `UnsafeMutableBufferPointer`, because `CGPoint` is an aggregate of + `CGFloat`. + * [SE-0352][]: It's now possible to call a generic function with a value of protocol type @@ -32,7 +114,7 @@ _**Note:** This is in reverse chronological order, so newer entries are added to It's now possible to use a default value expression with a generic parameter type to default the argument and its type: - ``` + ```swift func compute(_ values: C = [0, 1, 2]) { ... } @@ -107,54 +189,54 @@ _**Note:** This is in reverse chronological order, so newer entries are added to * [SE-0343][]: -Top-level scripts support asynchronous calls. + Top-level scripts support asynchronous calls. -Using an `await` by calling an asynchronous function or accessing an isolated -variable transitions the top-level to an asynchronous context. As an -asynchronous context, top-level variables are `@MainActor`-isolated and the -top-level is run on the `@MainActor`. + Using an `await` by calling an asynchronous function or accessing an isolated + variable transitions the top-level to an asynchronous context. As an + asynchronous context, top-level variables are `@MainActor`-isolated and the + top-level is run on the `@MainActor`. -Note that the transition affects function overload resolution and starts an -implicit run loop to drive the concurrency machinery. + Note that the transition affects function overload resolution and starts an + implicit run loop to drive the concurrency machinery. -Unmodified scripts are not affected by this change unless `-warn-concurrency` is -passed to the compiler invocation. With `-warn-concurrency`, variables in the -top-level are isolated to the main actor and the top-level context is isolated -to the main actor, but is not an asynchronous context. + Unmodified scripts are not affected by this change unless `-warn-concurrency` is + passed to the compiler invocation. With `-warn-concurrency`, variables in the + top-level are isolated to the main actor and the top-level context is isolated + to the main actor, but is not an asynchronous context. * [SE-0336][]: -It is now possible to declare `distributed actor` and `distributed func`s inside of them. - -Distributed actors provide stronger isolation guarantees than "local" actors, and enable additional checks to be made on return types and parameters of distributed methods, e.g. checking if they conform to `Codable`. Distributed methods can be called on "remote" references of distributed actors, turning those invocations into remote procedure calls, by means of pluggable and user extensible distributed actor system implementations. - -Swift does not provide any specific distributed actor system by itself, however, packages in the ecosystem fulfil the role of providing those implementations. + It is now possible to declare `distributed actor` and `distributed func`s inside of them. -```swift -distributed actor Greeter { - var greetingsSent = 0 + Distributed actors provide stronger isolation guarantees than "local" actors, and enable additional checks to be made on return types and parameters of distributed methods, e.g. checking if they conform to `Codable`. Distributed methods can be called on "remote" references of distributed actors, turning those invocations into remote procedure calls, by means of pluggable and user extensible distributed actor system implementations. - distributed func greet(name: String) -> String { - greetingsSent += 1 - return "Hello, \(name)!" + Swift does not provide any specific distributed actor system by itself, however, packages in the ecosystem fulfill the role of providing those implementations. + + ```swift + distributed actor Greeter { + var greetingsSent = 0 + + distributed func greet(name: String) -> String { + greetingsSent += 1 + return "Hello, \(name)!" + } } -} - -func talkTo(greeter: Greeter) async throws { - // isolation of distributed actors is stronger, it is impossible to refer to - // any stored properties of distributed actors from outside of them: - greeter.greetingsSent // distributed actor-isolated property 'name' can not be accessed from a non-isolated context - // remote calls are implicitly throwing and async, - // to account for the potential networking involved: - let greeting = try await greeter.greet(name: "Alice") - print(greeting) // Hello, Alice! -} -``` + func talkTo(greeter: Greeter) async throws { + // isolation of distributed actors is stronger, it is impossible to refer to + // any stored properties of distributed actors from outside of them: + greeter.greetingsSent // distributed actor-isolated property 'name' can not be accessed from a non-isolated context + + // remote calls are implicitly throwing and async, + // to account for the potential networking involved: + let greeting = try await greeter.greet(name: "Alice") + print(greeting) // Hello, Alice! + } + ``` * The compiler now emits a warning when a non-final class conforms to a protocol that imposes a same-type requirement between `Self` and an associated type. This is because such a requirement makes the conformance unsound for subclasses. -For example, Swift 5.6 would allow the following code, which at runtime would construct an instance of `C` and not `SubC` as expected: + For example, Swift 5.6 would allow the following code, which at runtime would construct an instance of `C` and not `SubC` as expected: ```swift protocol P { @@ -257,29 +339,32 @@ For example, Swift 5.6 would allow the following code, which at runtime would co return [ 1: "One", 2: "Two" ] } ``` + Swift 5.6 --------- -* [SE-0327][]: - -In Swift 5 mode, a warning is now emitted if the default-value expression of an -instance-member property requires global-actor isolation. For example: +### 2022-03-14 (Xcode 13.3) -```swift -@MainActor -func partyGenerator() -> [PartyMember] { fatalError("todo") } +* [SE-0327][]: -class Party { - @MainActor var members: [PartyMember] = partyGenerator() - // ^~~~~~~~~~~~~~~~ - // warning: expression requiring global actor 'MainActor' cannot - // appear in default-value expression of property 'members' -} -``` + In Swift 5 mode, a warning is now emitted if the default-value expression of an + instance-member property requires global-actor isolation. For example: -Previously, the isolation granted by the type checker matched the isolation of -the property itself, but at runtime that is not guaranteed. In Swift 6, -such default-value expressions will become an error if they require isolation. + ```swift + @MainActor + func partyGenerator() -> [PartyMember] { fatalError("todo") } + + class Party { + @MainActor var members: [PartyMember] = partyGenerator() + // ^~~~~~~~~~~~~~~~ + // warning: expression requiring global actor 'MainActor' cannot + // appear in default-value expression of property 'members' + } + ``` + + Previously, the isolation granted by the type checker matched the isolation of + the property itself, but at runtime that is not guaranteed. In Swift 6, + such default-value expressions will become an error if they require isolation. * Actor isolation checking now understands that `defer` bodies share the isolation of their enclosing function. @@ -488,8 +573,6 @@ such default-value expressions will become an error if they require isolation. } ``` -**Add new entries to the top of this section, not here!** - Swift 5.5 --------- @@ -908,8 +991,6 @@ Swift 5.5 Asynchronous for loops use asynchronous sequences, defined by the protocol `AsyncSequence` and its corresponding `AsyncIterator`. -**Add new entries to the top of this section, not here!** - Swift 5.4 --------- @@ -1076,8 +1157,6 @@ Swift 5.4 let _: Foo? = .bar.anotherFoo.getFoo().optionalFoo?.optionalFoo![] ``` -**Add new entries to the top of this section, not here!** - Swift 5.3 --------- @@ -9173,20 +9252,23 @@ Swift 1.0 [SE-0316]: [SE-0320]: [SE-0322]: -[SE-0324]: [SE-0323]: +[SE-0324]: +[SE-0326]: [SE-0327]: [SE-0328]: [SE-0331]: -[SE-0337]: +[SE-0333]: +[SE-0334]: [SE-0335]: -[SE-0341]: [SE-0336]: -[SE-0343]: +[SE-0337]: [SE-0340]: +[SE-0341]: +[SE-0343]: [SE-0345]: -[SE-0326]: [SE-0347]: +[SE-0349]: [SE-0352]: [SR-75]: diff --git a/SwiftCompilerSources/CMakeLists.txt b/SwiftCompilerSources/CMakeLists.txt index 9e8bda8489566..4069e71c785fe 100644 --- a/SwiftCompilerSources/CMakeLists.txt +++ b/SwiftCompilerSources/CMakeLists.txt @@ -251,3 +251,23 @@ else() endif() +# Configure 'SwiftCompilerModules' SwiftPM package. The 'Package.swift' will +# be created at '${build_dir}/SwiftCompilerSources/Package.swift' and can be +# built with 'swift-build'. +# Note that this SwiftPM package itself is just for development purposes, and +# is not actually used for the compiler building. +set(swiftcompiler_source_dir_name "_Sources") +configure_file(Package.swift.in + "${CMAKE_CURRENT_BINARY_DIR}/Package.swift" @ONLY) +# SwiftPM requires all sources are inside the directory of 'Package.swift'. +# Create symlinks to the actual source directories. +execute_process(COMMAND + "${CMAKE_COMMAND}" -E create_symlink + "${CMAKE_CURRENT_SOURCE_DIR}/Sources" + "${CMAKE_CURRENT_BINARY_DIR}/${swiftcompiler_source_dir_name}") +if(SWIFT_BUILD_REGEX_PARSER_IN_COMPILER) + execute_process(COMMAND + "${CMAKE_COMMAND}" -E create_symlink + "${EXPERIMENTAL_STRING_PROCESSING_SOURCE_DIR}/Sources/_RegexParser" + "${CMAKE_CURRENT_BINARY_DIR}/_RegexParser_Sources") +endif() diff --git a/SwiftCompilerSources/Package.swift b/SwiftCompilerSources/Package.swift deleted file mode 100644 index a3c90e3ad278b..0000000000000 --- a/SwiftCompilerSources/Package.swift +++ /dev/null @@ -1,51 +0,0 @@ -// swift-tools-version:5.3 - -import PackageDescription - -let package = Package( - name: "SwiftCompilerSources", - platforms: [ - .macOS("10.9"), - ], - products: [ - .library( - name: "Swift", - type: .static, - targets: ["SIL", "Optimizer", "_CompilerRegexParser"]), - ], - dependencies: [ - ], - // Note that all modules must be added to LIBSWIFT_MODULES in the top-level - // CMakeLists.txt file to get debugging working. - targets: [ - .target( - name: "SIL", - dependencies: [], - swiftSettings: [SwiftSetting.unsafeFlags([ - "-I", "../include/swift", - "-cross-module-optimization" - ])]), - .target( - name: "_CompilerRegexParser", - dependencies: [], - path: "_RegexParser", - swiftSettings: [ - .unsafeFlags([ - "-I", "../include/swift", - "-cross-module-optimization", - ]), - // Workaround until `_RegexParser` is imported as implementation-only - // by `_StringProcessing`. - .unsafeFlags([ - "-Xfrontend", - "-disable-implicit-string-processing-module-import" - ])]), - .target( - name: "Optimizer", - dependencies: ["SIL", "_CompilerRegexParser"], - swiftSettings: [SwiftSetting.unsafeFlags([ - "-I", "../include/swift", - "-cross-module-optimization" - ])]), - ] -) diff --git a/SwiftCompilerSources/Package.swift.in b/SwiftCompilerSources/Package.swift.in new file mode 100644 index 0000000000000..bfbe0e9bd6a52 --- /dev/null +++ b/SwiftCompilerSources/Package.swift.in @@ -0,0 +1,92 @@ +// swift-tools-version:5.3 +//===--- Package.swift.in - SwiftCompiler SwiftPM package -----------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2021 - 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// NOTE: This 'Package.swift.in' file is for CMake configure_file(). +// Generated 'Package.swift' can be found in +// '${swift_build_dir}/SwiftCompilerSources/Package.swift'. + +import PackageDescription + +private extension Target { + static let defaultSwiftSettings: [SwiftSetting] = [ + .unsafeFlags([ + "-Xfrontend", "-validate-tbd-against-ir=none", + "-Xfrontend", "-enable-cxx-interop", + // Bridging modules and headers + "-Xcc", "-I", "-Xcc", "@SWIFT_SOURCE_DIR@/include", + // Generated C headers + "-Xcc", "-I", "-Xcc", "@CMAKE_BINARY_DIR@/include", + "-cross-module-optimization" + ]), + ] + + static func compilerModuleTarget( + name: String, + dependencies: [Dependency], + path: String? = nil, + sources: [String]? = nil, + swiftSettings: [SwiftSetting] = []) -> Target { + .target( + name: name, + dependencies: dependencies, + path: path ?? "@swiftcompiler_source_dir_name@/\(name)", + exclude: ["CMakeLists.txt"], + sources: sources, + swiftSettings: defaultSwiftSettings + swiftSettings) + } +} + +let package = Package( + name: "SwiftCompilerSources", + platforms: [ + .macOS("10.9"), + ], + products: [ + .library( + name: "swiftCompilerModules", + type: .static, + targets: ["Basic", "AST", "Parse", "SIL", "Optimizer", "_CompilerRegexParser"]), + ], + dependencies: [ + ], + // Note that targets and their dependencies must align with + // 'SwiftCompilerSources/Sources/CMakeLists.txt' + targets: [ + .compilerModuleTarget( + name: "_CompilerRegexParser", + dependencies: [], + path: "_RegexParser_Sources", + swiftSettings: [ + // Workaround until `_CompilerRegexParser` is imported as implementation-only + // by `_StringProcessing`. + .unsafeFlags([ + "-Xfrontend", + "-disable-implicit-string-processing-module-import" + ])]), + .compilerModuleTarget( + name: "Basic", + dependencies: []), + .compilerModuleTarget( + name: "AST", + dependencies: ["Basic"]), + .compilerModuleTarget( + name: "Parse", + dependencies: ["Basic", "AST", "_CompilerRegexParser"]), + .compilerModuleTarget( + name: "SIL", + dependencies: ["Basic"]), + .compilerModuleTarget( + name: "Optimizer", + dependencies: ["Basic", "SIL", "Parse"]), + ] +) diff --git a/SwiftCompilerSources/Sources/AST/DiagnosticEngine.swift b/SwiftCompilerSources/Sources/AST/DiagnosticEngine.swift index 4ad82aedf90c7..78a56c7e8e798 100644 --- a/SwiftCompilerSources/Sources/AST/DiagnosticEngine.swift +++ b/SwiftCompilerSources/Sources/AST/DiagnosticEngine.swift @@ -67,6 +67,12 @@ public struct DiagnosticEngine { public init(bridged: BridgedDiagnosticEngine) { self.bridged = bridged } + public init?(bridged: BridgedOptionalDiagnosticEngine) { + guard let object = bridged.object else { + return nil + } + self.bridged = BridgedDiagnosticEngine(object: object) + } public func diagnose(_ position: SourceLoc?, _ id: DiagID, diff --git a/SwiftCompilerSources/Sources/Basic/SourceLoc.swift b/SwiftCompilerSources/Sources/Basic/SourceLoc.swift index f5016a6a9f06a..1fa3dc731d64f 100644 --- a/SwiftCompilerSources/Sources/Basic/SourceLoc.swift +++ b/SwiftCompilerSources/Sources/Basic/SourceLoc.swift @@ -33,6 +33,12 @@ public struct SourceLoc { } } +extension SourceLoc { + public func advanced(by n: Int) -> SourceLoc { + SourceLoc(locationInFile: locationInFile.advanced(by: n))! + } +} + extension Optional where Wrapped == SourceLoc { public var bridged: BridgedSourceLoc { self?.bridged ?? .init(pointer: nil) diff --git a/SwiftCompilerSources/Sources/CMakeLists.txt b/SwiftCompilerSources/Sources/CMakeLists.txt index 515c94dc2de5a..af6900ff8d0e9 100644 --- a/SwiftCompilerSources/Sources/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/CMakeLists.txt @@ -8,10 +8,11 @@ # NOTE: Subdirectories must be added in dependency order. -add_subdirectory(Basic) -add_subdirectory(AST) if(SWIFT_BUILD_REGEX_PARSER_IN_COMPILER) add_subdirectory(_RegexParser) endif() +add_subdirectory(Basic) +add_subdirectory(AST) +add_subdirectory(Parse) add_subdirectory(SIL) add_subdirectory(Optimizer) diff --git a/SwiftCompilerSources/Sources/Optimizer/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/CMakeLists.txt index 929e0a54581ab..ed754dd792c94 100644 --- a/SwiftCompilerSources/Sources/Optimizer/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/Optimizer/CMakeLists.txt @@ -7,10 +7,7 @@ # See http://swift.org/CONTRIBUTORS.txt for Swift project authors set(dependencies) -list(APPEND dependencies Basic SIL) -if(SWIFT_BUILD_REGEX_PARSER_IN_COMPILER) - list(APPEND dependencies _CompilerRegexParser) -endif() +list(APPEND dependencies Basic SIL Parse) add_swift_compiler_module(Optimizer DEPENDS ${dependencies}) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift index 1f6c1f6cd9f2b..c21f8809f6f93 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift @@ -12,19 +12,13 @@ import SIL import OptimizerBridging - -#if canImport(_CompilerRegexParser) -import _CompilerRegexParser -#endif +import Parse @_cdecl("initializeSwiftModules") public func initializeSwiftModules() { registerSILClasses() registerSwiftPasses() - - #if canImport(_CompilerRegexParser) registerRegexParser() - #endif } private func registerPass( diff --git a/SwiftCompilerSources/Sources/Parse/CMakeLists.txt b/SwiftCompilerSources/Sources/Parse/CMakeLists.txt new file mode 100644 index 0000000000000..e4c52316ff1df --- /dev/null +++ b/SwiftCompilerSources/Sources/Parse/CMakeLists.txt @@ -0,0 +1,18 @@ +# This source file is part of the Swift.org open source project +# +# Copyright (c) 2022 Apple Inc. and the Swift project authors +# Licensed under Apache License v2.0 with Runtime Library Exception +# +# See http://swift.org/LICENSE.txt for license information +# See http://swift.org/CONTRIBUTORS.txt for Swift project authors + +set(dependencies Basic AST) +if(SWIFT_BUILD_REGEX_PARSER_IN_COMPILER) + list(APPEND dependencies _CompilerRegexParser) +endif() + +add_swift_compiler_module(Parse + DEPENDS + ${dependencies} + SOURCES + Regex.swift) diff --git a/SwiftCompilerSources/Sources/Parse/Regex.swift b/SwiftCompilerSources/Sources/Parse/Regex.swift new file mode 100644 index 0000000000000..22d0c3aa2bcf0 --- /dev/null +++ b/SwiftCompilerSources/Sources/Parse/Regex.swift @@ -0,0 +1,146 @@ +//===--- Regex.swift - SourceLoc bridiging utilities ------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import _RegexParserBridging +import AST +import Basic + +#if canImport(_CompilerRegexParser) +import _CompilerRegexParser + +public func registerRegexParser() { + Parser_registerRegexLiteralParsingFn(_RegexLiteralParsingFn) + Parser_registerRegexLiteralLexingFn(_RegexLiteralLexingFn) +} + +/// Bridging between C++ lexer and _CompilerRegexParser.lexRegex() +/// +/// Attempt to lex a regex literal string. +/// +/// - Parameters: +/// - CurPtrPtr: A pointer to the current pointer of lexer, which should be +/// the start of the literal. This will be advanced to the point +/// at which the lexer should resume, or will remain the same if +/// this is not a regex literal. +/// - BufferEndPtr: A pointer to the end of the buffer, which should not be +/// lexed past. +/// - mustBeRegex: A bool value whether an error during lexing should be +/// considered a regex literal, or some thing else. If true +/// advace the curPtrPtr and emit the diagnostic. If false, +/// curPtrPtr won't be modified. +/// - bridgedDiagnosticEngine: Diagnostic engine to emit diagnostics. +/// +/// - Returns: A bool indicating whether lexing was completely erroneous, and +/// cannot be recovered from, or false if there either was no error, +/// or there was a recoverable error. +private func _RegexLiteralLexingFn( + _ curPtrPtr: UnsafeMutablePointer>, + _ bufferEndPtr: UnsafePointer, + _ mustBeRegex: CBool, + _ bridgedDiagnosticEngine: BridgedOptionalDiagnosticEngine +) -> /*CompletelyErroneous*/ CBool { + let inputPtr = curPtrPtr.pointee + + do { + let (_, _, endPtr) = try lexRegex(start: inputPtr, end: bufferEndPtr) + curPtrPtr.pointee = endPtr.assumingMemoryBound(to: CChar.self) + return false + } catch let error as DelimiterLexError { + if !mustBeRegex { + // This token can be something else. Let the client fallback. + return false; + } + if error.kind == .unknownDelimiter { + // An unknown delimiter should be recovered from, as we may want to try + // lex something else. + return false + } + + if let diagEngine = DiagnosticEngine(bridged: bridgedDiagnosticEngine) { + // Emit diagnostic. + let startLoc = SourceLoc( + locationInFile: UnsafeRawPointer(inputPtr).assumingMemoryBound(to: UInt8.self))! + diagEngine.diagnose(startLoc, .regex_literal_parsing_error, "\(error)") + } + + // Advance the current pointer. + curPtrPtr.pointee = error.resumePtr.assumingMemoryBound(to: CChar.self) + + switch error.kind { + case .unterminated, .multilineClosingNotOnNewline: + // These can be recovered from. + return false + case .unprintableASCII, .invalidUTF8: + // We don't currently have good recovery behavior for these. + return true + case .unknownDelimiter: + fatalError("Already handled") + } + } catch { + fatalError("Should be a DelimiterLexError") + } +} + +/// Bridging between C++ parser and _CompilerRegexParser.parseWithDelimiters() +/// +/// - Parameters: +/// - inputPtr: A null-terminated C string. +/// - errOut: A buffer accepting an error string upon error. +/// - versionOut: A buffer accepting a regex literal format +/// version. +/// - captureStructureOut: A buffer accepting a byte sequence representing the +/// capture structure. +/// - captureStructureSize: The size of the capture structure buffer. Must be +/// greater than or equal to `strlen(inputPtr)`. +/// - bridgedDiagnosticBaseLoc: Source location of the start of the literal +/// - bridgedDiagnosticEngine: Diagnostic engine to emit diagnostics. +public func _RegexLiteralParsingFn( + _ inputPtr: UnsafePointer, + _ versionOut: UnsafeMutablePointer, + _ captureStructureOut: UnsafeMutableRawPointer, + _ captureStructureSize: CUnsignedInt, + _ bridgedDiagnosticBaseLoc: BridgedSourceLoc, + _ bridgedDiagnosticEngine: BridgedDiagnosticEngine +) -> Bool { + versionOut.pointee = currentRegexLiteralFormatVersion + + let str = String(cString: inputPtr) + do { + let ast = try parseWithDelimiters(str) + // Serialize the capture structure for later type inference. + assert(captureStructureSize >= str.utf8.count) + let buffer = UnsafeMutableRawBufferPointer( + start: captureStructureOut, count: Int(captureStructureSize)) + ast.captureStructure.encode(to: buffer) + return false; + } catch { + var diagLoc = SourceLoc(bridged: bridgedDiagnosticBaseLoc) + let diagEngine = DiagnosticEngine(bridged: bridgedDiagnosticEngine) + if let _diagLoc = diagLoc, + let locatedError = error as? LocatedErrorProtocol { + let offset = str.utf8.distance(from: str.startIndex, + to: locatedError.location.start) + diagLoc = _diagLoc.advanced(by: offset) + } + diagEngine.diagnose( + diagLoc, .regex_literal_parsing_error, + "cannot parse regular expression: \(String(describing: error))") + return true + } +} + +#else // canImport(_CompilerRegexParser) + +#warning("Regex parsing is disabled") +public func registerRegexParser() {} + +#endif // canImport(_CompilerRegexParser) diff --git a/SwiftCompilerSources/Sources/_RegexParser/CMakeLists.txt b/SwiftCompilerSources/Sources/_RegexParser/CMakeLists.txt index 32fc6f667c1c9..b1d2ae37978f7 100644 --- a/SwiftCompilerSources/Sources/_RegexParser/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/_RegexParser/CMakeLists.txt @@ -16,5 +16,4 @@ endforeach() message(STATUS "Using Experimental String Processing library for libswift _RegexParser (${EXPERIMENTAL_STRING_PROCESSING_SOURCE_DIR}).") add_swift_compiler_module(_CompilerRegexParser - "${LIBSWIFT_REGEX_PARSER_SOURCES}" - Regex.swift) + "${LIBSWIFT_REGEX_PARSER_SOURCES}") diff --git a/SwiftCompilerSources/Sources/_RegexParser/Regex.swift b/SwiftCompilerSources/Sources/_RegexParser/Regex.swift deleted file mode 100644 index fb484bd793529..0000000000000 --- a/SwiftCompilerSources/Sources/_RegexParser/Regex.swift +++ /dev/null @@ -1,6 +0,0 @@ -import _RegexParserBridging - -public func registerRegexParser() { - Parser_registerRegexLiteralParsingFn(libswiftParseRegexLiteral) - Parser_registerRegexLiteralLexingFn(libswiftLexRegexLiteral) -} diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index 99ca2e68d6c18..daeb249a76497 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -65,6 +65,10 @@ typedef struct { void * _Nonnull object; } BridgedDiagnosticEngine; +typedef struct { + void *_Nullable object; +} BridgedOptionalDiagnosticEngine; + // FIXME: Can we bridge InFlightDiagnostic? void DiagnosticEngine_diagnose(BridgedDiagnosticEngine, BridgedSourceLoc loc, BridgedDiagID diagID, BridgedArrayRef arguments, diff --git a/include/swift/AST/BridgingUtils.h b/include/swift/AST/BridgingUtils.h index 0de9cb21b5831..6f5a0dfbbbe90 100644 --- a/include/swift/AST/BridgingUtils.h +++ b/include/swift/AST/BridgingUtils.h @@ -21,6 +21,10 @@ namespace swift { inline BridgedDiagnosticEngine getBridgedDiagnosticEngine(DiagnosticEngine *D) { return {(void *)D}; } +inline BridgedOptionalDiagnosticEngine +getBridgedOptionalDiagnosticEngine(DiagnosticEngine *D) { + return {(void *)D}; +} } // namespace swift diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index 1bc7c2ae0e733..4c5181ebdde2e 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -491,6 +491,9 @@ void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, namespace namelookup { +/// Add semantic members to \p type before attempting a semantic lookup. +void installSemanticMembersIfNeeded(Type type, DeclNameRef name); + void extractDirectlyReferencedNominalTypes( Type type, SmallVectorImpl &decls); diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 8e38e4be0e4c5..5eeb955fd8f9d 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -223,9 +223,6 @@ namespace swift { /// Emit a remark after loading a module. bool EnableModuleLoadingRemarks = false; - /// Resolve main function as though it were called from an async context - bool EnableAsyncMainResolution = false; - /// /// Support for alternate usage modes /// diff --git a/include/swift/IDE/CompletionLookup.h b/include/swift/IDE/CompletionLookup.h index 0636eb4d41ca8..092dca44f8948 100644 --- a/include/swift/IDE/CompletionLookup.h +++ b/include/swift/IDE/CompletionLookup.h @@ -356,7 +356,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { static bool hasInterestingDefaultValue(const ParamDecl *param); - bool addItemWithoutDefaultArgs(const AbstractFunctionDecl *func); + bool shouldAddItemWithoutDefaultArgs(const AbstractFunctionDecl *func); /// Build argument patterns for calling. Returns \c true if any content was /// added to \p Builder. If \p declParams is non-empty, the size must match diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 770c81c0855a0..36085ad77d86e 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -270,10 +270,6 @@ def pch_output_dir: Separate<["-"], "pch-output-dir">, Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>, HelpText<"Directory to persist automatically created precompiled bridging headers">; -def async_main: Flag<["-"], "async-main">, - Flags<[FrontendOption]>, - HelpText<"Resolve main function as if it were called from an asynchronous context">; - // FIXME: Unhide this once it doesn't depend on an output file map. def incremental : Flag<["-"], "incremental">, Flags<[NoInteractiveOption, HelpHidden, DoesNotAffectIncrementalBuild]>, diff --git a/include/swift/Parse/RegexParserBridging.h b/include/swift/Parse/RegexParserBridging.h index 5fa054cf03689..bc2f97ed2d9cf 100644 --- a/include/swift/Parse/RegexParserBridging.h +++ b/include/swift/Parse/RegexParserBridging.h @@ -14,6 +14,7 @@ #ifndef REGEX_PARSER_BRIDGING #define REGEX_PARSER_BRIDGING +#include "swift/AST/ASTBridging.h" #include #ifdef __cplusplus @@ -28,32 +29,40 @@ extern "C" { /// is not a regex literal. /// - BufferEnd: A pointer to the end of the buffer, which should not be lexed /// past. -/// - ErrorOut: If an error is encountered, this will be set to the error -/// string. +/// - MustBeRegex: whether an error during lexing should be considered a regex +/// literal, or some thing else. +/// - BridgedOptionalDiagnosticEngine: RegexLiteralLexingFn should diagnose the +/// token using this engine. /// /// Returns: A bool indicating whether lexing was completely erroneous, and /// cannot be recovered from, or false if there either was no error, /// or there was a recoverable error. -typedef bool (* RegexLiteralLexingFn)(/*CurPtrPtr*/ const char **, - /*BufferEnd*/ const char *, - /*ErrorOut*/ const char **); -void Parser_registerRegexLiteralLexingFn(RegexLiteralLexingFn fn); +typedef bool (*RegexLiteralLexingFn)( + /*CurPtrPtr*/ const char *_Nonnull *_Nonnull, + /*BufferEnd*/ const char *_Nonnull, + /*MustBeRegex*/ bool, BridgedOptionalDiagnosticEngine); +void Parser_registerRegexLiteralLexingFn(RegexLiteralLexingFn _Nullable fn); /// Parse a regex literal string. Takes the following arguments: /// /// - InputPtr: A null-terminated C string of the regex literal. -/// - ErrorOut: A buffer accepting an error string upon error. /// - VersionOut: A buffer accepting a regex literal format version. /// - CaptureStructureOut: A buffer accepting a byte sequence representing the /// capture structure of the literal. /// - CaptureStructureSize: The size of the capture structure buffer. Must be /// greater than or equal to `strlen(InputPtr) + 3`. -typedef void(* RegexLiteralParsingFn)(/*InputPtr*/ const char *, - /*ErrorOut*/ const char **, - /*VersionOut*/ unsigned *, - /*CaptureStructureOut*/ void *, - /*CaptureStructureSize*/ unsigned); -void Parser_registerRegexLiteralParsingFn(RegexLiteralParsingFn fn); +/// - DiagnosticBaseLoc: Start location of the regex literal. +/// - BridgedDiagnosticEngine: RegexLiteralParsingFn should diagnose the +/// parsing errors using this engine. +/// +/// Returns: A bool value indicating if there was an error while parsing. +typedef bool (*RegexLiteralParsingFn)(/*InputPtr*/ const char *_Nonnull, + /*VersionOut*/ unsigned *_Nonnull, + /*CaptureStructureOut*/ void *_Nonnull, + /*CaptureStructureSize*/ unsigned, + /*DiagnosticBaseLoc*/ BridgedSourceLoc, + BridgedDiagnosticEngine); +void Parser_registerRegexLiteralParsingFn(RegexLiteralParsingFn _Nullable fn); #ifdef __cplusplus } // extern "C" diff --git a/include/swift/Runtime/Atomic.h b/include/swift/Runtime/Atomic.h index 436be6b839f51..a5c6cb84bc682 100644 --- a/include/swift/Runtime/Atomic.h +++ b/include/swift/Runtime/Atomic.h @@ -95,14 +95,6 @@ struct aligned_alloc { free(ptr); #endif } - -#if defined(_WIN32) - // FIXME: why is this even needed? This is not permitted as per the C++ - // standrd new.delete.placement (ยง17.6.3.4). - [[nodiscard]] void *operator new(std::size_t size, void *where) noexcept { - return ::operator new(size, where); - } -#endif }; /// The default implementation for swift::atomic, which just wraps diff --git a/include/swift/Runtime/AtomicWaitQueue.h b/include/swift/Runtime/AtomicWaitQueue.h index cc0d99890d571..0985067828b25 100644 --- a/include/swift/Runtime/AtomicWaitQueue.h +++ b/include/swift/Runtime/AtomicWaitQueue.h @@ -20,6 +20,7 @@ #define SWIFT_RUNTIME_ATOMICWAITQUEUE_H #include "swift/Runtime/Heap.h" +#include "swift/Runtime/HeapObject.h" #include "swift/Runtime/Mutex.h" #include @@ -84,7 +85,7 @@ class AtomicWaitQueue { /// global lock and while *not* holding the wait queue lock. void release_locked() { if (referenceCount == 1) { - delete &asImpl(); + swift_cxx_deleteObject(&asImpl()); } else { referenceCount--; } @@ -211,7 +212,7 @@ class AtomicWaitQueue { // If we created the queue but never published it, destroy it. if (CurrentQueue) { CurrentQueue->WaitQueueLock.unlock(); - delete CurrentQueue; + swift_cxx_deleteObject(CurrentQueue); } } @@ -425,12 +426,7 @@ class AtomicWaitQueue { private: template static Impl *createNewQueue(Args &&...args) { -#if !defined(__cpp_aligned_new) - static_assert(!swift::requires_aligned_alloc::value>::value || - is_aligned_alloc_aware::value, - "type is over-aligned for non-alignment aware operator new"); -#endif - auto queue = new Impl(std::forward(args)...); + auto queue = swift_cxx_newObject(std::forward(args)...); queue->WaitQueueLock.lock(); return queue; } diff --git a/include/swift/Runtime/HeapObject.h b/include/swift/Runtime/HeapObject.h index 4f6ca1c068c54..a0660abcf4e99 100644 --- a/include/swift/Runtime/HeapObject.h +++ b/include/swift/Runtime/HeapObject.h @@ -19,6 +19,8 @@ #include #include +#include +#include #include "swift/Runtime/Config.h" #if SWIFT_OBJC_INTEROP @@ -131,6 +133,49 @@ void *swift_slowAlloc(size_t bytes, size_t alignMask); SWIFT_RUNTIME_EXPORT void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask); +/// Allocate and construct an instance of type \c T. +/// +/// \param args The arguments to pass to the constructor for \c T. +/// +/// \returns A pointer to a new, fully constructed instance of \c T. This +/// function never returns \c nullptr. The caller is responsible for +/// eventually destroying the resulting object by passing it to +/// \c swift_cxx_deleteObject(). +/// +/// This function avoids the use of the global \c operator \c new (which may be +/// overridden by other code in a process) in favor of calling +/// \c swift_slowAlloc() and constructing the new object with placement new. +/// +/// This function is capable of returning well-aligned memory even on platforms +/// that do not implement the C++17 "over-aligned new" feature. +template +static inline T *swift_cxx_newObject(Args &&... args) { + auto result = reinterpret_cast(swift_slowAlloc(sizeof(T), + alignof(T) - 1)); + ::new (result) T(std::forward(args)...); + return result; +} + +/// Destruct and deallocate an instance of type \c T. +/// +/// \param ptr A pointer to an instance of type \c T previously created with a +/// call to \c swift_cxx_newObject(). +/// +/// This function avoids the use of the global \c operator \c delete (which may +/// be overridden by other code in a process) in favor of directly calling the +/// destructor for \a *ptr and then freeing its memory by calling +/// \c swift_slowDealloc(). +/// +/// The effect of passing a pointer to this function that was \em not returned +/// from \c swift_cxx_newObject() is undefined. +template +static inline void swift_cxx_deleteObject(T *ptr) { + if (ptr) { + ptr->~T(); + swift_slowDealloc(ptr, sizeof(T), alignof(T) - 1); + } +} + /// Atomically increments the retain count of an object. /// /// \param object - may be null, in which case this is a no-op diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 3edd230ebb928..cef88f5e37b44 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -194,6 +194,8 @@ class ExpressionTimer { AnchorType getAnchor() const { return Anchor; } + SourceRange getAffectedRange() const; + unsigned getWarnLimit() const { return Context.TypeCheckerOpts.WarnLongExpressionTypeChecking; } @@ -1491,7 +1493,7 @@ enum class ConstraintSystemFlags { /// Note that this flag is automatically applied to all constraint systems, /// when \c DebugConstraintSolver is set in \c TypeCheckerOptions. It can be /// automatically enabled for select constraint solving attempts by setting - /// \c DebugConstraintSolverAttempt. Finally, it can also be automatically + /// \c DebugConstraintSolverAttempt. Finally, it can also be automatically /// enabled for a pre-configured set of expressions on line numbers by setting /// \c DebugConstraintSolverOnLines. DebugConstraints = 0x10, @@ -1516,9 +1518,8 @@ enum class ConstraintSystemFlags { /// `__attribute__((ns_consumed))`. UseClangFunctionTypes = 0x80, - /// When set, nominal typedecl contexts are asynchronous contexts. - /// This is set while searching for the main function - ConsiderNominalTypeContextsAsync = 0x100, + /// When set, ignore async/sync mismatches + IgnoreAsyncSyncMismatch = 0x100, }; /// Options that affect the constraint system as a whole. @@ -5415,9 +5416,17 @@ class ConstraintSystem { /// Determine if we've already explored too many paths in an /// attempt to solve this expression. - bool isExpressionAlreadyTooComplex = false; - bool getExpressionTooComplex(size_t solutionMemory) { - if (isExpressionAlreadyTooComplex) + std::pair isAlreadyTooComplex = {false, SourceRange()}; + + /// If optional is not nil, result is guaranteed to point at a valid + /// location. + Optional getTooComplexRange() const { + auto range = isAlreadyTooComplex.second; + return range.isValid() ? range : Optional(); + } + + bool isTooComplex(size_t solutionMemory) { + if (isAlreadyTooComplex.first) return true; auto CancellationFlag = getASTContext().CancellationFlag; @@ -5428,7 +5437,9 @@ class ConstraintSystem { MaxMemory = std::max(used, MaxMemory); auto threshold = getASTContext().TypeCheckerOpts.SolverMemoryThreshold; if (MaxMemory > threshold) { - return isExpressionAlreadyTooComplex= true; + // No particular location for OoM problems. + isAlreadyTooComplex.first = true; + return true; } if (Timer && Timer->isExpired()) { @@ -5437,24 +5448,29 @@ class ConstraintSystem { // emitting an error. Timer->disableWarning(); - return isExpressionAlreadyTooComplex = true; + isAlreadyTooComplex = {true, Timer->getAffectedRange()}; + return true; } // Bail out once we've looked at a really large number of // choices. if (CountScopes > getASTContext().TypeCheckerOpts.SolverBindingThreshold) { - return isExpressionAlreadyTooComplex = true; + isAlreadyTooComplex.first = true; + return true; } return false; } - bool getExpressionTooComplex(SmallVectorImpl const &solutions) { + bool isTooComplex(SmallVectorImpl const &solutions) { + if (isAlreadyTooComplex.first) + return true; + size_t solutionMemory = 0; for (auto const& s : solutions) { solutionMemory += s.getTotalMemory(); } - return getExpressionTooComplex(solutionMemory); + return isTooComplex(solutionMemory); } // If the given constraint is an applied disjunction, get the argument function diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index 750aa5ef50c3b..c5e53591d007c 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -21,7 +21,6 @@ #include "swift/AST/Identifier.h" #include "swift/Basic/SourceLoc.h" -#include "swift/Basic/OptionSet.h" #include #include @@ -51,8 +50,6 @@ namespace swift { class ConstraintSystem; class Solution; class SolutionApplicationTarget; - enum class ConstraintSystemFlags; - using ConstraintSystemOptions = OptionSet; } /// Typecheck binding initializer at \p bindingIndex. @@ -96,9 +93,8 @@ namespace swift { /// Unlike other member lookup functions, \c swift::resolveValueMember() /// should be used when you want to look up declarations with the same name as /// one you already have. - ResolvedMemberResult - resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name, - constraints::ConstraintSystemOptions Options = {}); + ResolvedMemberResult resolveValueMember(DeclContext &DC, Type BaseTy, + DeclName Name); /// Given a type and an extension to the original type decl of that type, /// decide if the extension has been applied, i.e. if the requirements of the diff --git a/include/swift/Sema/SolutionResult.h b/include/swift/Sema/SolutionResult.h index 04bac3b6dc8dd..99cbb4bf5bc8d 100644 --- a/include/swift/Sema/SolutionResult.h +++ b/include/swift/Sema/SolutionResult.h @@ -64,6 +64,9 @@ class SolutionResult { /// \c numSolutions entries. Solution *solutions = nullptr; + /// A source range that was too complex to solve. + Optional TooComplexAt = None; + /// General constructor for the named constructors. SolutionResult(Kind kind) : kind(kind) { emittedDiagnostic = false; @@ -95,9 +98,7 @@ class SolutionResult { /// Produce a "too complex" failure, which was not yet been /// diagnosed. - static SolutionResult forTooComplex() { - return SolutionResult(TooComplex); - } + static SolutionResult forTooComplex(Optional affected); /// Produce a failure that has already been diagnosed. static SolutionResult forError() { @@ -123,6 +124,10 @@ class SolutionResult { /// Take the set of solutions when there is an ambiguity. MutableArrayRef takeAmbiguousSolutions() &&; + /// Retrieve a range of source that has been determined to be too + /// complex to solve in a reasonable time. + Optional getTooComplexAt() const { return TooComplexAt; } + /// Whether this solution requires the client to produce a diagnostic. bool requiresDiagnostic() const { switch (kind) { diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index c47dd18591f62..29bb70e972c5c 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1051,13 +1051,6 @@ static bool shouldCreateMissingConformances(Type type, ProtocolDecl *proto) { return true; } - // A 'distributed actor' may have to create missing Codable conformances. - if (auto nominal = dyn_cast_or_null(type->getAnyNominal())) { - return nominal->isDistributedActor() && - (proto->isSpecificProtocol(swift::KnownProtocolKind::Decodable) || - proto->isSpecificProtocol(swift::KnownProtocolKind::Encodable)); - } - return false; } diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 1453b00e2f351..4d5a8ddfd9ad3 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -1625,6 +1625,32 @@ void namelookup::pruneLookupResultSet(const DeclContext *dc, NLOptions options, filterForDiscriminator(decls, M->getDebugClient()); } +// An unfortunate hack to kick the decl checker into adding semantic members to +// the current type before we attempt a semantic lookup. The places this method +// looks needs to be in sync with \c extractDirectlyReferencedNominalTypes. +// See the note in \c synthesizeSemanticMembersIfNeeded about a better, more +// just, and peaceful world. +void namelookup::installSemanticMembersIfNeeded(Type type, DeclNameRef name) { + // Look-through class-bound archetypes to ensure we synthesize e.g. + // inherited constructors. + if (auto archetypeTy = type->getAs()) { + if (auto super = archetypeTy->getSuperclass()) { + type = super; + } + } + + if (type->isExistentialType()) { + auto layout = type->getExistentialLayout(); + if (auto super = layout.explicitSuperclass) { + type = super; + } + } + + if (auto *current = type->getAnyNominal()) { + current->synthesizeSemanticMembersIfNeeded(name.getFullName()); + } +} + /// Inspect the given type to determine which nominal type declarations it /// directly references, to facilitate name lookup into those types. void namelookup::extractDirectlyReferencedNominalTypes( diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index 06376d0cbae22..a2aeb6595907e 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -1532,8 +1532,16 @@ IterableDeclContext::getLocalConformances(ConformanceLookupKind lookupKind) // Look for a Sendable conformance globally. If it is synthesized // and matches this declaration context, use it. auto dc = getAsGenericContext(); + + SmallPtrSet known; for (auto conformance : findSynthesizedConformances(dc)) { - result.push_back(conformance); + // Compute the known set of conformances for the first time. + if (known.empty()) { + known.insert(result.begin(), result.end()); + } + + if (known.insert(conformance).second) + result.push_back(conformance); } break; } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index d568a08b8fbf0..9da3a9e5d2d37 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -8787,74 +8787,86 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) { Optional SeenMainActorAttr; PatternBindingInitializer *initContext = nullptr; - // - // __attribute__((swift_attr("attribute"))) - // - for (auto swiftAttr : ClangDecl->specific_attrs()) { - // FIXME: Hard-code @MainActor and @UIActor, because we don't have a - // point at which to do name lookup for imported entities. - if (isMainActorAttr(swiftAttr)) { - if (SeenMainActorAttr) { - // Cannot add main actor annotation twice. We'll keep the first - // one and raise a warning about the duplicate. - HeaderLoc attrLoc(swiftAttr->getLocation()); - diagnose(attrLoc, diag::import_multiple_mainactor_attr, - swiftAttr->getAttribute(), - SeenMainActorAttr.getValue()->getAttribute()); + auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) { + // + // __attribute__((swift_attr("attribute"))) + // + for (auto swiftAttr : ClangDecl->specific_attrs()) { + // FIXME: Hard-code @MainActor and @UIActor, because we don't have a + // point at which to do name lookup for imported entities. + if (isMainActorAttr(swiftAttr)) { + if (SeenMainActorAttr) { + // Cannot add main actor annotation twice. We'll keep the first + // one and raise a warning about the duplicate. + HeaderLoc attrLoc(swiftAttr->getLocation()); + diagnose(attrLoc, diag::import_multiple_mainactor_attr, + swiftAttr->getAttribute(), + SeenMainActorAttr.getValue()->getAttribute()); + continue; + } + + if (Type mainActorType = SwiftContext.getMainActorType()) { + auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext); + auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr); + MappedDecl->getAttrs().add(attr); + SeenMainActorAttr = swiftAttr; + } + continue; } - if (Type mainActorType = SwiftContext.getMainActorType()) { - auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext); - auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr); + // Hard-code @actorIndependent, until Objective-C clients start + // using nonisolated. + if (swiftAttr->getAttribute() == "@actorIndependent") { + auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true); MappedDecl->getAttrs().add(attr); - SeenMainActorAttr = swiftAttr; + continue; } - continue; - } - - // Hard-code @actorIndependent, until Objective-C clients start - // using nonisolated. - if (swiftAttr->getAttribute() == "@actorIndependent") { - auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true); - MappedDecl->getAttrs().add(attr); - continue; - } + // Dig out a buffer with the attribute text. + unsigned bufferID = getClangSwiftAttrSourceBuffer( + swiftAttr->getAttribute()); - // Dig out a buffer with the attribute text. - unsigned bufferID = getClangSwiftAttrSourceBuffer( - swiftAttr->getAttribute()); + // Dig out a source file we can use for parsing. + auto &sourceFile = getClangSwiftAttrSourceFile( + *MappedDecl->getDeclContext()->getParentModule()); - // Dig out a source file we can use for parsing. - auto &sourceFile = getClangSwiftAttrSourceFile( - *MappedDecl->getDeclContext()->getParentModule()); + // Spin up a parser. + swift::Parser parser( + bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr); + // Prime the lexer. + parser.consumeTokenWithoutFeedingReceiver(); - // Spin up a parser. - swift::Parser parser( - bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr); - // Prime the lexer. - parser.consumeTokenWithoutFeedingReceiver(); + bool hadError = false; + SourceLoc atLoc; + if (parser.consumeIf(tok::at_sign, atLoc)) { + hadError = parser.parseDeclAttribute( + MappedDecl->getAttrs(), atLoc, initContext, + /*isFromClangAttribute=*/true).isError(); + } else { + SourceLoc staticLoc; + StaticSpellingKind staticSpelling; + hadError = parser.parseDeclModifierList( + MappedDecl->getAttrs(), staticLoc, staticSpelling, + /*isFromClangAttribute=*/true); + } - bool hadError = false; - SourceLoc atLoc; - if (parser.consumeIf(tok::at_sign, atLoc)) { - hadError = parser.parseDeclAttribute( - MappedDecl->getAttrs(), atLoc, initContext, - /*isFromClangAttribute=*/true).isError(); - } else { - SourceLoc staticLoc; - StaticSpellingKind staticSpelling; - hadError = parser.parseDeclModifierList( - MappedDecl->getAttrs(), staticLoc, staticSpelling, - /*isFromClangAttribute=*/true); - } - - if (hadError) { - // Complain about the unhandled attribute or modifier. - HeaderLoc attrLoc(swiftAttr->getLocation()); - diagnose(attrLoc, diag::clang_swift_attr_unhandled, - swiftAttr->getAttribute()); + if (hadError) { + // Complain about the unhandled attribute or modifier. + HeaderLoc attrLoc(swiftAttr->getLocation()); + diagnose(attrLoc, diag::clang_swift_attr_unhandled, + swiftAttr->getAttribute()); + } + } + }; + importAttrsFromDecl(ClangDecl); + + // If the Clang declaration is from an anonymous tag that was given a + // name via a typedef, look for attributes on the typedef as well. + if (auto tag = dyn_cast(ClangDecl)) { + if (tag->getName().empty()) { + if (auto typedefDecl = tag->getTypedefNameForAnonDecl()) + importAttrsFromDecl(typedefDecl); } } diff --git a/lib/Demangling/OldDemangler.cpp b/lib/Demangling/OldDemangler.cpp index 671265c36ee1b..f8ff94b3294ed 100644 --- a/lib/Demangling/OldDemangler.cpp +++ b/lib/Demangling/OldDemangler.cpp @@ -1044,7 +1044,8 @@ class OldDemangler { // had its generic arguments applied. NodePointer result = Factory.createNode(nominalType->getKind()); result->addChild(parentOrModule, Factory); - result->addChild(nominalType->getChild(1), Factory); + for (unsigned ndx = 1; ndx < nominalType->getNumChildren(); ++ndx) + result->addChild(nominalType->getChild(ndx), Factory); nominalType = result; } diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 5c28fa84ca23a..204871a5faf9d 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -300,7 +300,6 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddLastArg(arguments, options::OPT_access_notes_path); inputArgs.AddLastArg(arguments, options::OPT_library_level); inputArgs.AddLastArg(arguments, options::OPT_enable_bare_slash_regex); - inputArgs.AddLastArg(arguments, options::OPT_async_main); // Pass on any build config options inputArgs.AddAllArgs(arguments, options::OPT_D); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 33c289132f9af..b517d20aa20df 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -489,8 +489,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Diags.diagnose(SourceLoc(), diag::warn_flag_deprecated, "-enable-experimental-async-top-level"); - Opts.EnableAsyncMainResolution = Args.hasArg(OPT_async_main); - Opts.DiagnoseInvalidEphemeralnessAsError |= Args.hasArg(OPT_enable_invalid_ephemeralness_as_error); diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index 9da86b13f561a..3f7d1af508549 100644 --- a/lib/IDE/CompletionLookup.cpp +++ b/lib/IDE/CompletionLookup.cpp @@ -872,6 +872,71 @@ void CompletionLookup::addVarDeclRef(const VarDecl *VD, Builder.addFlair(CodeCompletionFlairBit::ExpressionSpecific); } +/// Return whether \p param has a non-desirable default value for code +/// completion. +/// +/// 'ClangImporter::Implementation::inferDefaultArgument()' automatically adds +/// default values for some parameters; +/// * NS_OPTIONS enum type with the name '...Options'. +/// * NSDictionary and labeled 'options', 'attributes', or 'userInfo'. +/// +/// But sometimes, this behavior isn't really desirable. This function add a +/// heuristic where if a parameter matches all the following condition, we +/// consider the imported default value is _not_ desirable: +/// * it is the first parameter, +/// * it doesn't have an argument label, and +/// * the imported function base name ends with those words +/// For example, ClangImporter imports: +/// +/// -(void)addAttributes:(NSDictionary *)attrs, options:(NSDictionary *)opts; +/// +/// as: +/// +/// func addAttributes(_ attrs: [AnyHashable:Any] = [:], +/// options opts: [AnyHashable:Any] = [:]) +/// +/// In this case, we don't want 'attrs' defaulted because the function name have +/// 'Attribute' in its name so calling 'value.addAttribute()' doesn't make +/// sense, but we _do_ want to keep 'opts' defaulted. +/// +/// Note that: +/// +/// -(void)performWithOptions:(NSDictionary *) opts; +/// +/// This doesn't match the condition because the base name of the function in +/// Swift is 'peform': +/// +/// func perform(options opts: [AnyHashable:Any] = [:]) +/// +bool isNonDesirableImportedDefaultArg(const ParamDecl *param) { + auto kind = param->getDefaultArgumentKind(); + if (kind != DefaultArgumentKind::EmptyArray && + kind != DefaultArgumentKind::EmptyDictionary) + return false; + + if (!param->getArgumentName().empty()) + return false; + + auto *func = dyn_cast(param->getDeclContext()); + if (!func->hasClangNode()) + return false; + if (func->getParameters()->front() != param) + return false; + if (func->getBaseName().isSpecial()) + return false; + + auto baseName = func->getBaseName().getIdentifier().str(); + switch (kind) { + case DefaultArgumentKind::EmptyArray: + return (baseName.endswith("Options")); + case DefaultArgumentKind::EmptyDictionary: + return (baseName.endswith("Options") || baseName.endswith("Attributes") || + baseName.endswith("UserInfo")); + default: + llvm_unreachable("unhandled DefaultArgumentKind"); + } +} + bool CompletionLookup::hasInterestingDefaultValue(const ParamDecl *param) { if (!param) return false; @@ -879,12 +944,16 @@ bool CompletionLookup::hasInterestingDefaultValue(const ParamDecl *param) { switch (param->getDefaultArgumentKind()) { case DefaultArgumentKind::Normal: case DefaultArgumentKind::NilLiteral: - case DefaultArgumentKind::EmptyArray: - case DefaultArgumentKind::EmptyDictionary: case DefaultArgumentKind::StoredProperty: case DefaultArgumentKind::Inherited: return true; + case DefaultArgumentKind::EmptyArray: + case DefaultArgumentKind::EmptyDictionary: + if (isNonDesirableImportedDefaultArg(param)) + return false; + return true; + case DefaultArgumentKind::None: #define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ case DefaultArgumentKind::NAME: @@ -893,7 +962,7 @@ bool CompletionLookup::hasInterestingDefaultValue(const ParamDecl *param) { } } -bool CompletionLookup::addItemWithoutDefaultArgs( +bool CompletionLookup::shouldAddItemWithoutDefaultArgs( const AbstractFunctionDecl *func) { if (!func || !Sink.addCallWithNoDefaultArgs) return false; @@ -923,7 +992,8 @@ bool CompletionLookup::addCallArgumentPatterns( bool hasDefault = false; if (!declParams.empty()) { const ParamDecl *PD = declParams[i]; - hasDefault = PD->isDefaultArgument(); + hasDefault = + PD->isDefaultArgument() && !isNonDesirableImportedDefaultArg(PD); // Skip default arguments if we're either not including them or they // aren't interesting if (hasDefault && @@ -1188,7 +1258,7 @@ void CompletionLookup::addFunctionCallPattern( if (isImplicitlyCurriedInstanceMethod) { addPattern({AFD->getImplicitSelfDecl()}, /*includeDefaultArgs=*/true); } else { - if (addItemWithoutDefaultArgs(AFD)) + if (shouldAddItemWithoutDefaultArgs(AFD)) addPattern(AFD->getParameters()->getArray(), /*includeDefaultArgs=*/false); addPattern(AFD->getParameters()->getArray(), @@ -1384,7 +1454,7 @@ void CompletionLookup::addMethodCall(const FuncDecl *FD, if (trivialTrailingClosure) addMethodImpl(/*includeDefaultArgs=*/false, /*trivialTrailingClosure=*/true); - if (addItemWithoutDefaultArgs(FD)) + if (shouldAddItemWithoutDefaultArgs(FD)) addMethodImpl(/*includeDefaultArgs=*/false); addMethodImpl(/*includeDefaultArgs=*/true); } @@ -1474,7 +1544,7 @@ void CompletionLookup::addConstructorCall(const ConstructorDecl *CD, } }; - if (ConstructorType && addItemWithoutDefaultArgs(CD)) + if (ConstructorType && shouldAddItemWithoutDefaultArgs(CD)) addConstructorImpl(/*includeDefaultArgs=*/false); addConstructorImpl(); } diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 58c96bb5211de..00c982873b02b 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -21,6 +21,7 @@ #include "swift/AST/Initializer.h" #include "swift/AST/LazyResolver.h" #include "swift/AST/Module.h" +#include "swift/AST/NameLookup.h" #include "swift/AST/ParameterList.h" #include "swift/AST/Pattern.h" #include "swift/AST/SourceFile.h" @@ -364,6 +365,9 @@ static void collectPossibleCalleesByQualifiedLookup( if (!baseInstanceTy->mayHaveMembers()) return; + // Make sure we've resolved implicit members. + namelookup::installSemanticMembersIfNeeded(baseInstanceTy, name); + bool isOnMetaType = baseTy->is(); SmallVector decls; diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 83596d793dbf1..f46fe19337e62 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -1883,7 +1883,16 @@ namespace { MetadataResponse visitProtocolType(CanProtocolType type, DynamicMetadataRequest request) { - llvm_unreachable("constraint type should be wrapped in existential type"); + assert(false && "constraint type should be wrapped in existential type"); + + CanExistentialType existential( + ExistentialType::get(type)->castTo()); + + if (auto metatype = tryGetLocal(existential, request)) + return metatype; + + auto metadata = emitExistentialTypeMetadata(existential); + return setLocal(type, MetadataResponse::forComplete(metadata)); } MetadataResponse @@ -1892,7 +1901,16 @@ namespace { if (type->isAny() || type->isAnyObject()) return emitSingletonExistentialTypeMetadata(type); - llvm_unreachable("constraint type should be wrapped in existential type"); + assert(false && "constraint type should be wrapped in existential type"); + + CanExistentialType existential( + ExistentialType::get(type)->castTo()); + + if (auto metatype = tryGetLocal(existential, request)) + return metatype; + + auto metadata = emitExistentialTypeMetadata(existential); + return setLocal(type, MetadataResponse::forComplete(metadata)); } MetadataResponse diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index 4b08f2776efec..47b02a0ed5f11 100644 --- a/lib/Parse/Lexer.cpp +++ b/lib/Parse/Lexer.cpp @@ -14,27 +14,27 @@ // //===----------------------------------------------------------------------===// -#include "swift/Parse/Confusables.h" #include "swift/Parse/Lexer.h" +#include "swift/AST/BridgingUtils.h" #include "swift/AST/DiagnosticsParse.h" #include "swift/AST/Identifier.h" #include "swift/Basic/LangOptions.h" #include "swift/Basic/SourceManager.h" +#include "swift/Parse/Confusables.h" #include "swift/Parse/RegexParserBridging.h" #include "swift/Syntax/Trivia.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryBuffer.h" // FIXME: Figure out if this can be migrated to LLVM. #include "clang/Basic/CharInfo.h" #include // Regex lexing delivered via libSwift. -#include "swift/Parse/RegexParserBridging.h" static RegexLiteralLexingFn regexLiteralLexingFn = nullptr; void Parser_registerRegexLiteralLexingFn(RegexLiteralLexingFn fn) { regexLiteralLexingFn = fn; @@ -2039,25 +2039,18 @@ bool Lexer::tryLexRegexLiteral(const char *TokStart) { // Ask the Swift library to try and lex a regex literal. // - Ptr will not be advanced if this is not for a regex literal. - // - ErrStr will be set if there is any error to emit. // - CompletelyErroneous will be set if there was an error that cannot be // recovered from. auto *Ptr = TokStart; - const char *ErrStr = nullptr; - bool CompletelyErroneous = regexLiteralLexingFn(&Ptr, BufferEnd, &ErrStr); + bool CompletelyErroneous = regexLiteralLexingFn( + &Ptr, BufferEnd, MustBeRegex, + getBridgedOptionalDiagnosticEngine(getTokenDiags())); // If we didn't make any lexing progress, this isn't a regex literal and we // should fallback to lexing as something else. if (Ptr == TokStart) return false; - if (ErrStr) { - if (!MustBeRegex) - return false; - - diagnose(TokStart, diag::regex_literal_parsing_error, ErrStr); - } - // If we're lexing `/.../`, error if we ended on the opening of a comment. // We prefer to lex the comment as it's more likely than not that is what // the user is expecting. @@ -2078,7 +2071,6 @@ bool Lexer::tryLexRegexLiteral(const char *TokStart) { // If the lexing was completely erroneous, form an unknown token. if (CompletelyErroneous) { - assert(ErrStr); formToken(tok::unknown, TokStart); return true; } diff --git a/lib/Parse/ParseRegex.cpp b/lib/Parse/ParseRegex.cpp index c7fa4e95a2917..d0d3e3eae944c 100644 --- a/lib/Parse/ParseRegex.cpp +++ b/lib/Parse/ParseRegex.cpp @@ -14,9 +14,11 @@ // //===----------------------------------------------------------------------===// -#include "swift/Parse/Parser.h" +#include "swift/AST/BridgingUtils.h" #include "swift/AST/DiagnosticsParse.h" +#include "swift/Basic/BridgingUtils.h" #include "swift/Parse/ParsedSyntaxRecorder.h" +#include "swift/Parse/Parser.h" #include "swift/Parse/SyntaxParsingContext.h" #include "swift/Syntax/SyntaxKind.h" @@ -41,19 +43,18 @@ ParserResult Parser::parseExprRegexLiteral() { // Let the Swift library parse the contents, returning an error, or null if // successful. - // TODO: We need to be able to pass back a source location to emit the error - // at. - const char *errorStr = nullptr; unsigned version; auto capturesBuf = Context.AllocateUninitialized( RegexLiteralExpr::getCaptureStructureSerializationAllocationSize( regexText.size())); - regexLiteralParsingFn(regexText.str().c_str(), &errorStr, &version, - /*captureStructureOut*/ capturesBuf.data(), - /*captureStructureSize*/ capturesBuf.size()); + bool hadError = + regexLiteralParsingFn(regexText.str().c_str(), &version, + /*captureStructureOut*/ capturesBuf.data(), + /*captureStructureSize*/ capturesBuf.size(), + /*diagBaseLoc*/ getBridgedSourceLoc(Tok.getLoc()), + getBridgedDiagnosticEngine(&Diags)); auto loc = consumeToken(); - if (errorStr) { - diagnose(loc, diag::regex_literal_parsing_error, errorStr); + if (hadError) { return makeParserResult(new (Context) ErrorExpr(loc)); } return makeParserResult(RegexLiteralExpr::createParsed( diff --git a/lib/SIL/IR/SILInstruction.cpp b/lib/SIL/IR/SILInstruction.cpp index 2a8a4c504d1df..4907aae486930 100644 --- a/lib/SIL/IR/SILInstruction.cpp +++ b/lib/SIL/IR/SILInstruction.cpp @@ -1646,6 +1646,10 @@ bool SILInstruction::maySuspend() const { // await_async_continuation always suspends the current task. if (isa(this)) return true; + + // hop_to_executor also may cause a suspension + if (isa(this)) + return true; // Fully applying an async function may suspend the caller. if (auto applySite = FullApplySite::isa(const_cast(this))) { diff --git a/lib/SILOptimizer/LoopTransforms/LICM.cpp b/lib/SILOptimizer/LoopTransforms/LICM.cpp index 8fa06686347c2..0dcf02745863e 100644 --- a/lib/SILOptimizer/LoopTransforms/LICM.cpp +++ b/lib/SILOptimizer/LoopTransforms/LICM.cpp @@ -1173,7 +1173,8 @@ static SILValue projectLoadValue(SILValue addr, AccessPath accessPath, assert(ProjectionIndex(SEI).Index == elementIdx); SILValue val = projectLoadValue( SEI->getOperand(), - AccessPath(accessPath.getStorage(), pathNode.getParent(), 0), + AccessPath(accessPath.getStorage(), pathNode.getParent(), + accessPath.getOffset()), rootVal, rootAccessPath, beforeInst); SILBuilder B(beforeInst); return B.createStructExtract(beforeInst->getLoc(), val, SEI->getField(), @@ -1183,7 +1184,8 @@ static SILValue projectLoadValue(SILValue addr, AccessPath accessPath, assert(ProjectionIndex(TEI).Index == elementIdx); SILValue val = projectLoadValue( TEI->getOperand(), - AccessPath(accessPath.getStorage(), pathNode.getParent(), 0), + AccessPath(accessPath.getStorage(), pathNode.getParent(), + accessPath.getOffset()), rootVal, rootAccessPath, beforeInst); SILBuilder B(beforeInst); return B.createTupleExtract(beforeInst->getLoc(), val, TEI->getFieldIndex(), diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 90b61949fdb05..0bf11a0ae25d6 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -5433,7 +5433,7 @@ collectExistentialConformances(Type fromType, Type toType, SmallVector conformances; for (auto proto : layout.getProtocols()) { conformances.push_back(TypeChecker::containsProtocol( - fromType, proto, module)); + fromType, proto, module, false, /*allowMissing=*/true)); } return toType->getASTContext().AllocateCopy(conformances); @@ -9145,6 +9145,12 @@ SolutionResult SolutionResult::forAmbiguous( return result; } +SolutionResult SolutionResult::forTooComplex(Optional affected) { + SolutionResult result(Kind::TooComplex); + result.TooComplexAt = affected; + return result; +} + SolutionResult::~SolutionResult() { assert((!requiresDiagnostic() || emittedDiagnostic) && "SolutionResult was destroyed without emitting a diagnostic"); diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index cfd7fc74bb266..baf18816113bf 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -4424,11 +4424,10 @@ getMemberDecls(InterestedMemberKind Kind) { llvm_unreachable("unhandled kind"); } -ResolvedMemberResult -swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name, - ConstraintSystemOptions Options) { +ResolvedMemberResult swift::resolveValueMember(DeclContext &DC, Type BaseTy, + DeclName Name) { ResolvedMemberResult Result; - ConstraintSystem CS(&DC, Options); + ConstraintSystem CS(&DC, None); // Look up all members of BaseTy with the given Name. MemberLookupResult LookupResult = CS.performMemberLookup( diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 360fc136317d7..8d5dc905c51d4 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2672,11 +2672,15 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, } /// Whether to downgrade to a concurrency warning. - auto isConcurrencyWarning = [&] { - if (contextRequiresStrictConcurrencyChecking(DC, GetClosureType{*this}) - && !hasPreconcurrencyCallee(this, locator)) + auto isConcurrencyWarning = [&](bool forSendable) { + // Except for Sendable warnings, don't downgrade to an error in strict + // contexts without a preconcurrency callee. + if (!forSendable && + contextRequiresStrictConcurrencyChecking(DC, GetClosureType{*this}) && + !hasPreconcurrencyCallee(this, locator)) return false; + // We can only handle the downgrade for conversions. switch (kind) { case ConstraintKind::Conversion: case ConstraintKind::ArgumentConversion: @@ -2696,7 +2700,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, auto *fix = AddSendableAttribute::create( *this, func1, func2, getConstraintLocator(locator), - isConcurrencyWarning()); + isConcurrencyWarning(true)); if (recordFix(fix)) return getTypeMatchFailure(locator); } @@ -2731,7 +2735,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, auto *fix = MarkGlobalActorFunction::create( *this, func1, func2, getConstraintLocator(locator), - isConcurrencyWarning()); + isConcurrencyWarning(false)); if (recordFix(fix)) return getTypeMatchFailure(locator); @@ -7108,7 +7112,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( case ConstraintKind::SelfObjectOfProtocol: { auto conformance = TypeChecker::containsProtocol( type, protocol, DC->getParentModule(), - /*skipConditionalRequirements=*/true); + /*skipConditionalRequirements=*/true, + /*allowMissing=*/true); if (conformance) { return recordConformance(conformance); } diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index eb2aadbdbf751..969b860d1a611 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -1298,12 +1298,21 @@ Optional> ConstraintSystem::solve( maybeProduceFallbackDiagnostic(target); return None; - case SolutionResult::TooComplex: - getASTContext().Diags.diagnose( - target.getLoc(), diag::expression_too_complex) - .highlight(target.getSourceRange()); + case SolutionResult::TooComplex: { + auto affectedRange = solution.getTooComplexAt(); + + // If affected range is unknown, let's use whole + // target. + if (!affectedRange) + affectedRange = target.getSourceRange(); + + getASTContext() + .Diags.diagnose(affectedRange->Start, diag::expression_too_complex) + .highlight(*affectedRange); + solution.markAsDiagnosed(); return None; + } case SolutionResult::Ambiguous: // If salvaging produced an ambiguous result, it has already been @@ -1374,8 +1383,8 @@ ConstraintSystem::solveImpl(SolutionApplicationTarget &target, SmallVector solutions; solve(solutions, allowFreeTypeVariables); - if (getExpressionTooComplex(solutions)) - return SolutionResult::forTooComplex(); + if (isTooComplex(solutions)) + return SolutionResult::forTooComplex(getTooComplexRange()); switch (solutions.size()) { case 0: @@ -1415,7 +1424,7 @@ bool ConstraintSystem::solve(SmallVectorImpl &solutions, filterSolutions(solutions); // We fail if there is no solution or the expression was too complex. - return solutions.empty() || getExpressionTooComplex(solutions); + return solutions.empty() || isTooComplex(solutions); } void ConstraintSystem::solveImpl(SmallVectorImpl &solutions) { diff --git a/lib/Sema/CSStep.cpp b/lib/Sema/CSStep.cpp index 5cb3ccd17aacb..1ae3b69fef678 100644 --- a/lib/Sema/CSStep.cpp +++ b/lib/Sema/CSStep.cpp @@ -251,7 +251,7 @@ bool SplitterStep::mergePartialSolutions() const { // Since merging partial solutions can go exponential, make sure we didn't // pass the "too complex" thresholds including allocated memory and time. - if (CS.getExpressionTooComplex(solutionMemory)) + if (CS.isTooComplex(solutionMemory)) return false; } while (nextCombination(counts, indices)); @@ -313,7 +313,7 @@ StepResult ComponentStep::take(bool prevFailed) { // One of the previous components created by "split" // failed, it means that we can't solve this component. if ((prevFailed && DependsOnPartialSolutions.empty()) || - CS.getExpressionTooComplex(Solutions)) + CS.isTooComplex(Solutions)) return done(/*isSuccess=*/false); // Setup active scope, only if previous component didn't fail. diff --git a/lib/Sema/CSStep.h b/lib/Sema/CSStep.h index a02536931e7ed..66d3edb0cb5c8 100644 --- a/lib/Sema/CSStep.h +++ b/lib/Sema/CSStep.h @@ -504,6 +504,11 @@ template class BindingStep : public SolverStep { public: StepResult take(bool prevFailed) override { + // Before attempting the next choice, let's check whether the constraint + // system is too complex already. + if (CS.isTooComplex(Solutions)) + return done(/*isSuccess=*/false); + while (auto choice = Producer()) { if (shouldSkip(*choice)) continue; diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 1701aa154caf1..ad050488bd7c1 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -56,6 +56,22 @@ ExpressionTimer::ExpressionTimer(AnchorType Anchor, ConstraintSystem &CS, PrintDebugTiming(CS.getASTContext().TypeCheckerOpts.DebugTimeExpressions), PrintWarning(true) {} +SourceRange ExpressionTimer::getAffectedRange() const { + ASTNode anchor; + + if (auto *locator = Anchor.dyn_cast()) { + anchor = simplifyLocatorToAnchor(locator); + // If locator couldn't be simplified down to a single AST + // element, let's use its root. + if (!anchor) + anchor = locator->getAnchor(); + } else { + anchor = Anchor.get(); + } + + return anchor.getSourceRange(); +} + ExpressionTimer::~ExpressionTimer() { auto elapsed = getElapsedProcessTimeInFractionalSeconds(); unsigned elapsedMS = static_cast(elapsed * 1000); @@ -81,22 +97,13 @@ ExpressionTimer::~ExpressionTimer() { if (WarnLimit == 0 || elapsedMS < WarnLimit) return; - ASTNode anchor; - if (auto *locator = Anchor.dyn_cast()) { - anchor = simplifyLocatorToAnchor(locator); - // If locator couldn't be simplified down to a single AST - // element, let's warn about its root. - if (!anchor) - anchor = locator->getAnchor(); - } else { - anchor = Anchor.get(); - } + auto sourceRange = getAffectedRange(); - if (anchor.getStartLoc().isValid()) { + if (sourceRange.Start.isValid()) { Context.Diags - .diagnose(anchor.getStartLoc(), diag::debug_long_expression, elapsedMS, + .diagnose(sourceRange.Start, diag::debug_long_expression, elapsedMS, WarnLimit) - .highlight(anchor.getSourceRange()); + .highlight(sourceRange); } } @@ -2900,11 +2907,6 @@ bool ConstraintSystem::isAsynchronousContext(DeclContext *dc) { FunctionType::ExtInfo()).isAsync(); } - if (Options.contains( - ConstraintSystemFlags::ConsiderNominalTypeContextsAsync) && - isa(dc)) - return true; - return false; } @@ -3309,7 +3311,8 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator, // If we're choosing an asynchronous declaration within a synchronous // context, or vice-versa, increase the async/async mismatch score. if (auto func = dyn_cast(decl)) { - if (!func->hasPolymorphicEffect(EffectKind::Async) && + if (!Options.contains(ConstraintSystemFlags::IgnoreAsyncSyncMismatch) && + !func->hasPolymorphicEffect(EffectKind::Async) && func->isAsyncContext() != isAsynchronousContext(useDC)) { increaseScore( func->isAsyncContext() ? SK_AsyncInSyncMismatch : SK_SyncInAsync); @@ -3776,8 +3779,8 @@ SolutionResult ConstraintSystem::salvage() { // Fall through to produce diagnostics. } - if (getExpressionTooComplex(viable)) - return SolutionResult::forTooComplex(); + if (isTooComplex(viable)) + return SolutionResult::forTooComplex(getTooComplexRange()); // Could not produce a specific diagnostic; punt to the client. return SolutionResult::forUndiagnosedError(); @@ -6263,7 +6266,7 @@ void ConstraintSystem::diagnoseFailureFor(SolutionApplicationTarget target) { bool ConstraintSystem::isDeclUnavailable(const Decl *D, ConstraintLocator *locator) const { // First check whether this declaration is universally unavailable. - if (D->getAttrs().isUnavailable(getASTContext())) + if (AvailableAttr::isUnavailable(D)) return true; return TypeChecker::isDeclarationUnavailable(D, DC, [&] { diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 932834ca7df9b..2e50d65452457 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2096,28 +2096,6 @@ synthesizeMainBody(AbstractFunctionDecl *fn, void *arg) { return std::make_pair(body, /*typechecked=*/false); } -static FuncDecl *resolveMainFunctionDecl(DeclContext *declContext, - ResolvedMemberResult &resolution, - ASTContext &ctx) { - // Choose the best overload if it's a main function - if (resolution.hasBestOverload()) { - ValueDecl *best = resolution.getBestOverload(); - if (FuncDecl *func = dyn_cast(best)) { - if (func->isMainTypeMainMethod()) { - return func; - } - } - } - // Look for the most highly-ranked main-function candidate - for (ValueDecl *candidate : resolution.getMemberDecls(Viable)) { - if (FuncDecl *func = dyn_cast(candidate)) { - if (func->isMainTypeMainMethod()) - return func; - } - } - return nullptr; -} - FuncDecl * SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator, Decl *D) const { @@ -2170,17 +2148,91 @@ SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator, // usual type-checking. The alternative would be to directly call // mainType.main() from the entry point, and that would require fully // type-checking the call to mainType.main(). + using namespace constraints; + ConstraintSystem CS(declContext, + ConstraintSystemFlags::IgnoreAsyncSyncMismatch); + ConstraintLocator *locator = + CS.getConstraintLocator({}, ConstraintLocator::Member); + // Allowed main function types + // `() -> Void` + // `() async -> Void` + // `() throws -> Void` + // `() async throws -> Void` + // `@MainActor () -> Void` + // `@MainActor () async -> Void` + // `@MainActor () throws -> Void` + // `@MainActor () async throws -> Void` + { + llvm::SmallVector mainTypes = { + + FunctionType::get(/*params*/ {}, context.TheEmptyTupleType, + ASTExtInfo()), + FunctionType::get( + /*params*/ {}, context.TheEmptyTupleType, + ASTExtInfoBuilder().withAsync().build()), + + FunctionType::get(/*params*/ {}, context.TheEmptyTupleType, + ASTExtInfoBuilder().withThrows().build()), + + FunctionType::get( + /*params*/ {}, context.TheEmptyTupleType, + ASTExtInfoBuilder().withAsync().withThrows().build())}; + + Type mainActor = context.getMainActorType(); + if (mainActor) { + mainTypes.push_back(FunctionType::get( + /*params*/ {}, context.TheEmptyTupleType, + ASTExtInfoBuilder().withGlobalActor(mainActor).build())); + mainTypes.push_back(FunctionType::get( + /*params*/ {}, context.TheEmptyTupleType, + ASTExtInfoBuilder().withAsync().withGlobalActor(mainActor).build())); + mainTypes.push_back(FunctionType::get( + /*params*/ {}, context.TheEmptyTupleType, + ASTExtInfoBuilder().withThrows().withGlobalActor(mainActor).build())); + mainTypes.push_back(FunctionType::get(/*params*/ {}, + context.TheEmptyTupleType, + ASTExtInfoBuilder() + .withAsync() + .withThrows() + .withGlobalActor(mainActor) + .build())); + } + TypeVariableType *mainType = + CS.createTypeVariable(locator, /*options=*/0); + llvm::SmallVector typeEqualityConstraints; + typeEqualityConstraints.reserve(mainTypes.size()); + for (const Type &candidateMainType : mainTypes) { + typeEqualityConstraints.push_back( + Constraint::create(CS, ConstraintKind::Equal, Type(mainType), + candidateMainType, locator)); + } + + CS.addDisjunctionConstraint(typeEqualityConstraints, locator); + CS.addValueMemberConstraint( + nominal->getInterfaceType(), DeclNameRef(context.Id_main), + Type(mainType), declContext, FunctionRefKind::SingleApply, {}, locator); + } + + FuncDecl *mainFunction = nullptr; + llvm::SmallVector candidates; + + if (!CS.solve(candidates, FreeTypeVariableBinding::Disallow)) { + // We can't use CS.diagnoseAmbiguity directly since the locator is empty + // Sticking the main type decl `D` in results in an assert due to a + // unsimplifiable locator anchor since it appears to be looking for an + // expression, which we don't have. + // (locator could not be simplified to anchor) + // TODO: emit notes for each of the ambiguous candidates + if (candidates.size() != 1) { + context.Diags.diagnose(nominal->getLoc(), diag::ambiguous_decl_ref, + DeclNameRef(context.Id_main)); + attr->setInvalid(); + return nullptr; + } + mainFunction = dyn_cast( + candidates[0].overloadChoices[locator].choice.getDecl()); + } - constraints::ConstraintSystemOptions lookupOptions; - if (context.LangOpts.EnableAsyncMainResolution) - lookupOptions |= - constraints::ConstraintSystemFlags::ConsiderNominalTypeContextsAsync; - - auto resolution = resolveValueMember( - *declContext, nominal->getInterfaceType(), context.Id_main, - lookupOptions); - FuncDecl *mainFunction = - resolveMainFunctionDecl(declContext, resolution, context); if (!mainFunction) { const bool hasAsyncSupport = AvailabilityContext::forDeploymentTarget(context).isContainedIn( diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 9ed2bbb135d12..90205c86671ce 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -3914,11 +3914,14 @@ static bool declNeedsExplicitAvailability(const Decl *decl) { decl->isImplicit()) return false; + // Skip unavailable decls. + if (AvailableAttr::isUnavailable(decl)) + return false; + // Warn on decls without an introduction version. auto &ctx = decl->getASTContext(); auto safeRangeUnderApprox = AvailabilityInference::availableRange(decl, ctx); - return !safeRangeUnderApprox.getOSVersion().hasLowerEndpoint() && - !decl->getAttrs().isUnavailable(ctx); + return !safeRangeUnderApprox.getOSVersion().hasLowerEndpoint(); } void swift::checkExplicitAvailability(Decl *decl) { diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index c579a926fd682..810c7c379f063 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -3695,7 +3695,8 @@ getActorIsolationForMainFuncDecl(FuncDecl *fnDecl) { if (!declContext) return {}; const bool isMainDeclContext = - declContext->getAttrs().hasAttribute(); + declContext->getAttrs().hasAttribute( + /*allow invalid*/ true); ASTContext &ctx = fnDecl->getASTContext(); diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 26d0e8ec85a8a..a957da09715e1 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -273,32 +273,6 @@ LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclNameRef name, return result; } -// An unfortunate hack to kick the decl checker into adding semantic members to -// the current type before we attempt a semantic lookup. The places this method -// looks needs to be in sync with \c extractDirectlyReferencedNominalTypes. -// See the note in \c synthesizeSemanticMembersIfNeeded about a better, more -// just, and peaceful world. -static void installSemanticMembersIfNeeded(Type type, DeclNameRef name) { - // Look-through class-bound archetypes to ensure we synthesize e.g. - // inherited constructors. - if (auto archetypeTy = type->getAs()) { - if (auto super = archetypeTy->getSuperclass()) { - type = super; - } - } - - if (type->isExistentialType()) { - auto layout = type->getExistentialLayout(); - if (auto super = layout.explicitSuperclass) { - type = super; - } - } - - if (auto *current = type->getAnyNominal()) { - current->synthesizeSemanticMembersIfNeeded(name.getFullName()); - } -} - LookupResult TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclNameRef name, SourceLoc loc, @@ -346,7 +320,7 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc, subOptions &= ~NL_RemoveNonVisible; // Make sure we've resolved implicit members, if we need them. - installSemanticMembersIfNeeded(type, name); + namelookup::installSemanticMembersIfNeeded(type, name); LookupResultBuilder builder(result, dc, options); SmallVector lookupResults; @@ -438,7 +412,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc, subOptions |= NL_IncludeUsableFromInline; // Make sure we've resolved implicit members, if we need them. - installSemanticMembersIfNeeded(type, name); + namelookup::installSemanticMembersIfNeeded(type, name); if (!dc->lookupQualified(type, name, subOptions, decls)) return result; diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index c5860e5ed7d62..263d5255c1552 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -5672,7 +5672,8 @@ void ConformanceChecker::emitDelayedDiags() { ProtocolConformanceRef TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M, - bool skipConditionalRequirements) { + bool skipConditionalRequirements, + bool allowMissing) { // Existential types don't need to conform, i.e., they only need to // contain the protocol. if (T->isExistentialType()) { @@ -5694,8 +5695,9 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M, if (auto superclass = layout.getSuperclass()) { auto result = (skipConditionalRequirements - ? M->lookupConformance(superclass, Proto) - : TypeChecker::conformsToProtocol(superclass, Proto, M)); + ? M->lookupConformance(superclass, Proto, allowMissing) + : TypeChecker::conformsToProtocol( + superclass, Proto, M, allowMissing)); if (result) { return result; } @@ -5713,13 +5715,22 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M, return ProtocolConformanceRef(Proto); } + // FIXME: Unify with shouldCreateMissingConformances + if (allowMissing && + Proto->isSpecificProtocol(KnownProtocolKind::Sendable)) { + return ProtocolConformanceRef( + M->getASTContext().getBuiltinConformance( + T, Proto, GenericSignature(), { }, + BuiltinConformanceKind::Missing)); + } + return ProtocolConformanceRef::forInvalid(); } // For non-existential types, this is equivalent to checking conformance. return (skipConditionalRequirements - ? M->lookupConformance(T, Proto) - : TypeChecker::conformsToProtocol(T, Proto, M)); + ? M->lookupConformance(T, Proto, allowMissing) + : TypeChecker::conformsToProtocol(T, Proto, M, allowMissing)); } ProtocolConformanceRef diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index bb4011804d512..677bf149bf6f1 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -791,7 +791,8 @@ Expr *addImplicitLoadExpr( /// an empty optional. ProtocolConformanceRef containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M, - bool skipConditionalRequirements=false); + bool skipConditionalRequirements=false, + bool allowMissing=false); /// Determine whether the given type conforms to the given protocol. /// diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift b/stdlib/private/StdlibUnittest/StdlibUnittest.swift index 23180a2f95a0b..f3ac00c80e697 100644 --- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift +++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift @@ -2198,9 +2198,10 @@ func _getSystemVersionPlistProperty(_ propertyName: String) -> String? { func _getSystemVersionPlistProperty(_ propertyName: String) -> String? { var count = 0 sysctlbyname("kern.osproductversion", nil, &count, nil, 0) - var s = [CChar](repeating: 0, count: count) - sysctlbyname("kern.osproductversion", &s, &count, nil, 0) - return String(cString: &s) + return withUnsafeTemporaryAllocation(of: CChar.self, capacity: count) { + sysctlbyname("kern.osproductversion", $0.baseAddress, &count, nil, 0) + return String(cString: $0.baseAddress!) + } } #endif #endif diff --git a/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift b/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift index db1919bb81be5..cb153b8daf618 100644 --- a/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift +++ b/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift @@ -373,25 +373,25 @@ internal func reflect(instanceAddress: UInt, shouldUnwrapClassExistential: Bool = false) { while let command = readLine(strippingNewline: true) { switch command { - case String(validatingUTF8: RequestInstanceKind)!: + case RequestInstanceKind: sendValue(kind.rawValue) - case String(validatingUTF8: RequestShouldUnwrapClassExistential)!: + case RequestShouldUnwrapClassExistential: sendValue(shouldUnwrapClassExistential) - case String(validatingUTF8: RequestInstanceAddress)!: + case RequestInstanceAddress: sendValue(instanceAddress) - case String(validatingUTF8: RequestReflectionInfos)!: + case RequestReflectionInfos: sendReflectionInfos() - case String(validatingUTF8: RequestImages)!: + case RequestImages: sendImages() - case String(validatingUTF8: RequestReadBytes)!: + case RequestReadBytes: sendBytes() - case String(validatingUTF8: RequestSymbolAddress)!: + case RequestSymbolAddress: sendSymbolAddress() - case String(validatingUTF8: RequestStringLength)!: + case RequestStringLength: sendStringLength() - case String(validatingUTF8: RequestPointerSize)!: + case RequestPointerSize: sendPointerSize() - case String(validatingUTF8: RequestDone)!: + case RequestDone: return default: fatalError("Unknown request received: '\(Array(command.utf8))'!") diff --git a/stdlib/public/Concurrency/Actor.cpp b/stdlib/public/Concurrency/Actor.cpp index 97bbd43c27d0c..350d82cf1d9b9 100644 --- a/stdlib/public/Concurrency/Actor.cpp +++ b/stdlib/public/Concurrency/Actor.cpp @@ -17,6 +17,7 @@ #include "swift/Runtime/Concurrency.h" #include +#include #ifdef _WIN32 // On Windows, an include below triggers an indirect include of minwindef.h diff --git a/stdlib/public/Concurrency/AsyncLet.cpp b/stdlib/public/Concurrency/AsyncLet.cpp index e1542cb18df91..6ac84a265caf3 100644 --- a/stdlib/public/Concurrency/AsyncLet.cpp +++ b/stdlib/public/Concurrency/AsyncLet.cpp @@ -31,6 +31,8 @@ #include #endif +#include + using namespace swift; namespace { @@ -139,7 +141,7 @@ static AsyncLetImpl *asImpl(const AsyncLet *alet) { void swift::asyncLet_addImpl(AsyncTask *task, AsyncLet *asyncLet, bool didAllocateInParentTask) { - AsyncLetImpl *impl = new (asyncLet) AsyncLetImpl(task); + AsyncLetImpl *impl = ::new (asyncLet) AsyncLetImpl(task); impl->setDidAllocateFromParentTask(didAllocateInParentTask); auto record = impl->getTaskRecord(); diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index 057322d6baff4..06752c398d077 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -12,7 +12,6 @@ if(NOT swift_concurrency_extra_sources) set(swift_concurrency_extra_sources - Clock.cpp Clock.swift ContinuousClock.swift SuspendingClock.swift @@ -76,6 +75,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I AsyncLet.cpp AsyncLet.swift CheckedContinuation.swift + Clock.cpp GlobalExecutor.cpp Errors.swift Error.cpp diff --git a/stdlib/public/Concurrency/DispatchGlobalExecutor.inc b/stdlib/public/Concurrency/DispatchGlobalExecutor.inc index 8c5337f9e2bfc..858725f35c987 100644 --- a/stdlib/public/Concurrency/DispatchGlobalExecutor.inc +++ b/stdlib/public/Concurrency/DispatchGlobalExecutor.inc @@ -225,44 +225,7 @@ static void swift_task_enqueueGlobalWithDelayImpl(JobDelay delay, dispatch_after_f(when, queue, dispatchContext, dispatchFunction); } -// TODO: The following is cribbed from libdispatch, we should replace it with an official API -typedef enum { - DISPATCH_CLOCK_UPTIME, - DISPATCH_CLOCK_MONOTONIC, - DISPATCH_CLOCK_WALL, -#define DISPATCH_CLOCK_COUNT (DISPATCH_CLOCK_WALL + 1) -} dispatch_clock_t; - #define DISPATCH_UP_OR_MONOTONIC_TIME_MASK (1ULL << 63) -#define DISPATCH_WALLTIME_MASK (1ULL << 62) -#define DISPATCH_TIME_MAX_VALUE (DISPATCH_WALLTIME_MASK - 1) -static inline uint64_t -_dispatch_time_nano2mach(uint64_t value) { -#if HAS_MACH_TIME - struct mach_timebase_info info = calculateTimebase(); - return (value * info.denom) / info.numer; -#else - return value; -#endif -} - -static inline dispatch_time_t -_dispatch_clock_and_value_to_time(dispatch_clock_t clock, uint64_t value) -{ - if (value >= DISPATCH_TIME_MAX_VALUE) { - return DISPATCH_TIME_FOREVER; - } - switch (clock) { - case DISPATCH_CLOCK_WALL: - return -_dispatch_time_nano2mach(value); - case DISPATCH_CLOCK_UPTIME: - return _dispatch_time_nano2mach(value); - case DISPATCH_CLOCK_MONOTONIC: - return _dispatch_time_nano2mach(value) | DISPATCH_UP_OR_MONOTONIC_TIME_MASK; - } - __builtin_unreachable(); -} -// END: REPLACEMENT SWIFT_CC(swift) static void swift_task_enqueueGlobalWithDeadlineImpl(long long sec, @@ -282,18 +245,16 @@ static void swift_task_enqueueGlobalWithDeadlineImpl(long long sec, job->SchedulerPrivate[Job::DispatchQueueIndex] = DISPATCH_QUEUE_GLOBAL_EXECUTOR; - dispatch_time_t when; - switch (clock) { - case swift_clock_id_continuous: { - uint64_t q = sec * NSEC_PER_SEC + nsec; - when = _dispatch_clock_and_value_to_time(DISPATCH_CLOCK_MONOTONIC, q); - break; - } - case swift_clock_id_suspending: { - uint64_t q = sec * NSEC_PER_SEC + nsec; - when = _dispatch_clock_and_value_to_time(DISPATCH_CLOCK_UPTIME, q); - break; - } + long long nowSec; + long long nowNsec; + swift_get_time(&nowSec, &nowNsec, (swift_clock_id)clock); + + uint64_t delta = (sec - nowSec) * NSEC_PER_SEC + nsec - nowNsec; + + dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, delta); + + if (clock == swift_clock_id_continuous) { + when |= DISPATCH_UP_OR_MONOTONIC_TIME_MASK; } // TODO: this should pass the leeway/tolerance along when it is not -1 nanoseconds // either a dispatch_source can be created or a better dispatch_after_f can be made for this diff --git a/stdlib/public/Concurrency/Task.cpp b/stdlib/public/Concurrency/Task.cpp index 1bdbea0bc1b6b..1d232e1ca2245 100644 --- a/stdlib/public/Concurrency/Task.cpp +++ b/stdlib/public/Concurrency/Task.cpp @@ -28,6 +28,7 @@ #include "Debug.h" #include "Error.h" #include +#include #if SWIFT_CONCURRENCY_ENABLE_DISPATCH #include @@ -770,20 +771,20 @@ static AsyncTaskAndContext swift_task_create_commonImpl( // Initialize the child fragment if applicable. if (parent) { auto childFragment = task->childFragment(); - new (childFragment) AsyncTask::ChildFragment(parent); + ::new (childFragment) AsyncTask::ChildFragment(parent); } // Initialize the group child fragment if applicable. if (group) { auto groupChildFragment = task->groupChildFragment(); - new (groupChildFragment) AsyncTask::GroupChildFragment(group); + ::new (groupChildFragment) AsyncTask::GroupChildFragment(group); } // Initialize the future fragment if applicable. if (futureResultType) { assert(task->isFuture()); auto futureFragment = task->futureFragment(); - new (futureFragment) FutureFragment(futureResultType); + ::new (futureFragment) FutureFragment(futureResultType); // Set up the context for the future so there is no error, and a successful // result will be written into the future fragment's storage. @@ -1202,7 +1203,7 @@ swift_task_addCancellationHandlerImpl( void *allocation = swift_task_alloc(sizeof(CancellationNotificationStatusRecord)); auto unsigned_handler = swift_auth_code(handler, 3848); - auto *record = new (allocation) + auto *record = ::new (allocation) CancellationNotificationStatusRecord(unsigned_handler, context); bool fireHandlerNow = false; @@ -1237,7 +1238,7 @@ swift_task_createNullaryContinuationJobImpl( void *allocation = swift_task_alloc(sizeof(NullaryContinuationJob)); auto *job = - new (allocation) NullaryContinuationJob( + ::new (allocation) NullaryContinuationJob( swift_task_getCurrent(), static_cast(priority), continuation); diff --git a/stdlib/public/Concurrency/TaskGroup.cpp b/stdlib/public/Concurrency/TaskGroup.cpp index fa29de226f1e7..60ff5d8670c21 100644 --- a/stdlib/public/Concurrency/TaskGroup.cpp +++ b/stdlib/public/Concurrency/TaskGroup.cpp @@ -33,6 +33,7 @@ #include "string" #include "queue" // TODO: remove and replace with usage of our mpsc queue #include +#include #include #if SWIFT_CONCURRENCY_ENABLE_DISPATCH #include @@ -469,7 +470,7 @@ SWIFT_CC(swift) static void swift_taskGroup_initializeImpl(TaskGroup *group, const Metadata *T) { SWIFT_TASK_DEBUG_LOG("creating task group = %p", group); - TaskGroupImpl *impl = new (group) TaskGroupImpl(T); + TaskGroupImpl *impl = ::new (group) TaskGroupImpl(T); auto record = impl->getTaskRecord(); assert(impl == record && "the group IS the task record"); diff --git a/stdlib/public/Concurrency/TaskLocal.cpp b/stdlib/public/Concurrency/TaskLocal.cpp index 2961403988ce8..dec28b157a012 100644 --- a/stdlib/public/Concurrency/TaskLocal.cpp +++ b/stdlib/public/Concurrency/TaskLocal.cpp @@ -24,6 +24,7 @@ #include "swift/ABI/Metadata.h" #include "llvm/ADT/PointerIntPair.h" #include "TaskPrivate.h" +#include #include #if SWIFT_STDLIB_HAS_ASL @@ -207,7 +208,7 @@ TaskLocal::Item::createLink(AsyncTask *task, size_t amountToAllocate = Item::itemSize(valueType); void *allocation = task ? _swift_task_alloc_specific(task, amountToAllocate) : malloc(amountToAllocate); - Item *item = new (allocation) Item(key, valueType); + Item *item = ::new (allocation) Item(key, valueType); auto next = task ? task->_private().Local.head : FallbackTaskLocalStorage::get()->head; diff --git a/stdlib/public/Concurrency/TaskPrivate.h b/stdlib/public/Concurrency/TaskPrivate.h index ed7daaaf0c81b..f5429db28330b 100644 --- a/stdlib/public/Concurrency/TaskPrivate.h +++ b/stdlib/public/Concurrency/TaskPrivate.h @@ -29,6 +29,7 @@ #include "swift/Runtime/Heap.h" #include "swift/Runtime/HeapObject.h" #include +#include #define SWIFT_FATAL_ERROR swift_Concurrency_fatalError #include "../runtime/StackAllocator.h" @@ -655,11 +656,11 @@ AsyncTask::OpaquePrivateStorage::get() const { return reinterpret_cast(*this); } inline void AsyncTask::OpaquePrivateStorage::initialize(JobPriority basePri) { - new (this) PrivateStorage(basePri); + ::new (this) PrivateStorage(basePri); } inline void AsyncTask::OpaquePrivateStorage::initializeWithSlab( JobPriority basePri, void *slab, size_t slabCapacity) { - new (this) PrivateStorage(basePri, slab, slabCapacity); + ::new (this) PrivateStorage(basePri, slab, slabCapacity); } inline void AsyncTask::OpaquePrivateStorage::complete(AsyncTask *task) { get().complete(task); diff --git a/stdlib/public/Reflection/TypeLowering.cpp b/stdlib/public/Reflection/TypeLowering.cpp index ba6093a0f0b87..742a398300c39 100644 --- a/stdlib/public/Reflection/TypeLowering.cpp +++ b/stdlib/public/Reflection/TypeLowering.cpp @@ -20,6 +20,7 @@ #if SWIFT_ENABLE_REFLECTION +#include "llvm/Support/MathExtras.h" #include "swift/ABI/Enum.h" #include "swift/ABI/MetadataValues.h" #include "swift/Reflection/TypeLowering.h" @@ -645,6 +646,8 @@ class SimpleMultiPayloadEnumTypeInfo: public EnumTypeInfo { // A variable-length bitmap used to track "spare bits" for general multi-payload // enums. class BitMask { + static constexpr unsigned maxSize = 128 * 1024 * 1024; // 128MB + unsigned size; // Size of mask in bytes uint8_t *mask; public: @@ -654,18 +657,72 @@ class BitMask { // Construct a bitmask of the appropriate number of bytes // initialized to all bits set BitMask(unsigned sizeInBytes): size(sizeInBytes) { - assert(sizeInBytes < std::numeric_limits::max()); + // Gracefully fail by constructing an empty mask if we exceed the size + // limit. + if (size > maxSize) { + size = 0; + mask = nullptr; + return; + } + mask = (uint8_t *)malloc(size); + + if (!mask) { + // Malloc might fail if size is large due to some bad data. Assert in + // asserts builds, and fail gracefully in non-asserts builds by + // constructing an empty BitMask. + assert(false && "Failed to allocate BitMask"); + size = 0; + return; + } + memset(mask, 0xff, size); } // Construct a bitmask of the appropriate number of bytes // initialized with bits from the specified buffer - BitMask(unsigned sizeInBytes, const uint8_t *initialValue, unsigned initialValueBytes, unsigned offset) - : size(sizeInBytes) - { - assert(sizeInBytes < std::numeric_limits::max()); - assert(initialValueBytes + offset <= sizeInBytes); + BitMask(unsigned sizeInBytes, const uint8_t *initialValue, + unsigned initialValueBytes, unsigned offset) + : size(sizeInBytes) { + // Gracefully fail by constructing an empty mask if we exceed the size + // limit. + if (size > maxSize) { + size = 0; + mask = nullptr; + return; + } + + // Bad data could cause the initial value location to be off the end of our + // size. If initialValueBytes + offset is beyond sizeInBytes (or overflows), + // assert in asserts builds, and fail gracefully in non-asserts builds by + // constructing an empty BitMask. + bool overflowed = false; + unsigned initialValueEnd = + llvm::SaturatingAdd(initialValueBytes, offset, &overflowed); + if (overflowed) { + assert(false && "initialValueBytes + offset overflowed"); + size = 0; + mask = nullptr; + return; + } + assert(initialValueEnd <= sizeInBytes); + if (initialValueEnd > size) { + assert(false && "initialValueBytes + offset is greater than size"); + size = 0; + mask = nullptr; + return; + } + mask = (uint8_t *)calloc(1, size); + + if (!mask) { + // Malloc might fail if size is large due to some bad data. Assert in + // asserts builds, and fail gracefully in non-asserts builds by + // constructing an empty BitMask. + assert(false && "Failed to allocate BitMask"); + size = 0; + return; + } + memcpy(mask + offset, initialValue, initialValueBytes); } // Move constructor moves ownership and zeros the src @@ -864,10 +921,12 @@ class BitMask { void andNotMask(void *maskData, unsigned len, unsigned offset) { assert(offset < size); - unsigned common = std::min(len, size - offset); - uint8_t *maskBytes = (uint8_t *)maskData; - for (unsigned i = 0; i < common; ++i) { - mask[i + offset] &= ~maskBytes[i]; + if (offset < size) { + unsigned common = std::min(len, size - offset); + uint8_t *maskBytes = (uint8_t *)maskData; + for (unsigned i = 0; i < common; ++i) { + mask[i + offset] &= ~maskBytes[i]; + } } } }; diff --git a/stdlib/public/core/CString.swift b/stdlib/public/core/CString.swift index 930d4cb7b8598..3a430eb287e36 100644 --- a/stdlib/public/core/CString.swift +++ b/stdlib/public/core/CString.swift @@ -42,11 +42,48 @@ extension String { /// } /// // Prints "Caf๏ฟฝ" /// - /// - Parameter cString: A pointer to a null-terminated UTF-8 code sequence. - public init(cString: UnsafePointer) { - let len = UTF8._nullCodeUnitOffset(in: cString) + /// - Parameter nullTerminatedUTF8: A pointer to a null-terminated UTF-8 code sequence. + public init(cString nullTerminatedUTF8: UnsafePointer) { + let len = UTF8._nullCodeUnitOffset(in: nullTerminatedUTF8) + let buffer = UnsafeBufferPointer(start: nullTerminatedUTF8, count: len) + self = buffer.withMemoryRebound(to: UInt8.self) { + String._fromUTF8Repairing($0).0 + } + } + + @inlinable + @_alwaysEmitIntoClient + public init(cString nullTerminatedUTF8: [CChar]) { + self = nullTerminatedUTF8.withUnsafeBufferPointer { + $0.withMemoryRebound(to: UInt8.self, String.init(_checkingCString:)) + } + } + + @_alwaysEmitIntoClient + private init(_checkingCString bytes: UnsafeBufferPointer) { + guard let length = bytes.firstIndex(of: 0) else { + _preconditionFailure( + "input of String.init(cString:) must be null-terminated" + ) + } self = String._fromUTF8Repairing( - UnsafeBufferPointer(start: cString._asUInt8, count: len)).0 + UnsafeBufferPointer( + start: bytes.baseAddress._unsafelyUnwrappedUnchecked, + count: length + ) + ).0 + } + + @inlinable + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)") + public init(cString nullTerminatedUTF8: inout CChar) { + guard nullTerminatedUTF8 == 0 else { + _preconditionFailure( + "input of String.init(cString:) must be null-terminated" + ) + } + self = "" } /// Creates a new string by copying the null-terminated UTF-8 data referenced @@ -54,10 +91,37 @@ extension String { /// /// This is identical to `init(cString: UnsafePointer)` but operates on /// an unsigned sequence of bytes. - public init(cString: UnsafePointer) { - let len = UTF8._nullCodeUnitOffset(in: cString) + public init(cString nullTerminatedUTF8: UnsafePointer) { + let len = UTF8._nullCodeUnitOffset(in: nullTerminatedUTF8) self = String._fromUTF8Repairing( - UnsafeBufferPointer(start: cString, count: len)).0 + UnsafeBufferPointer(start: nullTerminatedUTF8, count: len)).0 + } + + @inlinable + @_alwaysEmitIntoClient + public init(cString nullTerminatedUTF8: [UInt8]) { + self = nullTerminatedUTF8.withUnsafeBufferPointer { + String(_checkingCString: $0) + } + } + + @inlinable + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use a copy of the String argument") + public init(cString nullTerminatedUTF8: String) { + self = nullTerminatedUTF8.withCString(String.init(cString:)) + } + + @inlinable + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)") + public init(cString nullTerminatedUTF8: inout UInt8) { + guard nullTerminatedUTF8 == 0 else { + _preconditionFailure( + "input of String.init(cString:) must be null-terminated" + ) + } + self = "" } /// Creates a new string by copying and validating the null-terminated UTF-8 @@ -88,13 +152,49 @@ extension String { /// - Parameter cString: A pointer to a null-terminated UTF-8 code sequence. public init?(validatingUTF8 cString: UnsafePointer) { let len = UTF8._nullCodeUnitOffset(in: cString) - guard let str = String._tryFromUTF8( - UnsafeBufferPointer(start: cString._asUInt8, count: len)) + guard let str = cString.withMemoryRebound(to: UInt8.self, capacity: len, { + String._tryFromUTF8(UnsafeBufferPointer(start: $0, count: len)) + }) else { return nil } self = str } + @inlinable + @_alwaysEmitIntoClient + public init?(validatingUTF8 cString: [CChar]) { + guard let length = cString.firstIndex(of: 0) else { + _preconditionFailure( + "input of String.init(validatingUTF8:) must be null-terminated" + ) + } + guard let string = cString.prefix(length).withUnsafeBufferPointer({ + $0.withMemoryRebound(to: UInt8.self, String._tryFromUTF8(_:)) + }) + else { return nil } + + self = string + } + + @inlinable + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use a copy of the String argument") + public init?(validatingUTF8 cString: String) { + self = cString.withCString(String.init(cString:)) + } + + @inlinable + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)") + public init?(validatingUTF8 cString: inout CChar) { + guard cString == 0 else { + _preconditionFailure( + "input of String.init(validatingUTF8:) must be null-terminated" + ) + } + self = "" + } + /// Creates a new string by copying the null-terminated data referenced by /// the given pointer using the specified encoding. /// @@ -148,14 +248,18 @@ extension String { guard let cPtr = cString else { return nil } if _fastPath(encoding == Unicode.UTF8.self) { - let ptr = UnsafeRawPointer(cPtr).assumingMemoryBound(to: UInt8.self) - let len = UTF8._nullCodeUnitOffset(in: ptr) - let codeUnits = UnsafeBufferPointer(start: ptr, count: len) - if isRepairing { - return String._fromUTF8Repairing(codeUnits) - } else { - guard let str = String._tryFromUTF8(codeUnits) else { return nil } - return (str, false) + let len = UTF8._nullCodeUnitOffset( + in: UnsafeRawPointer(cPtr).assumingMemoryBound(to: UInt8.self) + ) + let bytes = UnsafeBufferPointer(start: cPtr, count: len) + return bytes.withMemoryRebound(to: UInt8.self) { codeUnits in + if isRepairing { + return String._fromUTF8Repairing(codeUnits) + } + else if let str = String._tryFromUTF8(codeUnits) { + return (str, false) + } + return nil } } @@ -166,6 +270,78 @@ extension String { return String._fromCodeUnits( codeUnits, encoding: encoding, repair: isRepairing) } + + @_specialize(where Encoding == Unicode.UTF8) + @_specialize(where Encoding == Unicode.UTF16) + @inlinable // Fold away specializations + @_alwaysEmitIntoClient + public static func decodeCString( + _ cString: [Encoding.CodeUnit], + as encoding: Encoding.Type, + repairingInvalidCodeUnits isRepairing: Bool = true + ) -> (result: String, repairsMade: Bool)? { + guard let length = cString.firstIndex(of: 0) else { + _preconditionFailure( + "input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated" + ) + } + + if _fastPath(encoding == Unicode.UTF8.self) { + return cString.prefix(length).withUnsafeBufferPointer { + buffer -> (result: String, repairsMade: Bool)? in + return buffer.withMemoryRebound(to: UInt8.self) { codeUnits in + if isRepairing { + return String._fromUTF8Repairing(codeUnits) + } + else if let str = String._tryFromUTF8(codeUnits) { + return (str, false) + } + return nil + } + } + } + + return cString.prefix(length).withUnsafeBufferPointer { + buf -> (result: String, repairsMade: Bool)? in + String._fromCodeUnits(buf, encoding: encoding, repair: isRepairing) + } + } + + @_specialize(where Encoding == Unicode.UTF8) + @_specialize(where Encoding == Unicode.UTF16) + @inlinable + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use a copy of the String argument") + public static func decodeCString( + _ cString: String, + as encoding: Encoding.Type, + repairingInvalidCodeUnits isRepairing: Bool = true + ) -> (result: String, repairsMade: Bool)? { + return cString.withCString(encodedAs: encoding) { + String.decodeCString( + $0, as: encoding, repairingInvalidCodeUnits: isRepairing + ) + } + } + + @_specialize(where Encoding == Unicode.UTF8) + @_specialize(where Encoding == Unicode.UTF16) + @inlinable + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)") + public static func decodeCString( + _ cString: inout Encoding.CodeUnit, + as encoding: Encoding.Type, + repairingInvalidCodeUnits isRepairing: Bool = true + ) -> (result: String, repairsMade: Bool)? { + guard cString == 0 else { + _preconditionFailure( + "input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated" + ) + } + return ("", false) + } + /// Creates a string from the null-terminated sequence of bytes at the given /// pointer. /// @@ -179,10 +355,52 @@ extension String { @_specialize(where Encoding == Unicode.UTF16) @inlinable // Fold away specializations public init( - decodingCString ptr: UnsafePointer, + decodingCString nullTerminatedCodeUnits: UnsafePointer, as sourceEncoding: Encoding.Type ) { - self = String.decodeCString(ptr, as: sourceEncoding)!.0 + self = String.decodeCString(nullTerminatedCodeUnits, as: sourceEncoding)!.0 + } + + @_specialize(where Encoding == Unicode.UTF8) + @_specialize(where Encoding == Unicode.UTF16) + @inlinable // Fold away specializations + @_alwaysEmitIntoClient + public init( + decodingCString nullTerminatedCodeUnits: [Encoding.CodeUnit], + as sourceEncoding: Encoding.Type + ) { + self = String.decodeCString(nullTerminatedCodeUnits, as: sourceEncoding)!.0 + } + + @_specialize(where Encoding == Unicode.UTF8) + @_specialize(where Encoding == Unicode.UTF16) + @inlinable + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use a copy of the String argument") + public init( + decodingCString nullTerminatedCodeUnits: String, + as sourceEncoding: Encoding.Type + ) { + self = nullTerminatedCodeUnits.withCString(encodedAs: sourceEncoding) { + String(decodingCString: $0, as: sourceEncoding.self) + } + } + + @_specialize(where Encoding == Unicode.UTF8) + @_specialize(where Encoding == Unicode.UTF16) + @inlinable // Fold away specializations + @_alwaysEmitIntoClient + @available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)") + public init( + decodingCString nullTerminatedCodeUnits: inout Encoding.CodeUnit, + as sourceEncoding: Encoding.Type + ) { + guard nullTerminatedCodeUnits == 0 else { + _preconditionFailure( + "input of String.init(decodingCString:as:) must be null-terminated" + ) + } + self = "" } } diff --git a/stdlib/public/core/StringGuts.swift b/stdlib/public/core/StringGuts.swift index 5f16b1cec3365..ead304b360505 100644 --- a/stdlib/public/core/StringGuts.swift +++ b/stdlib/public/core/StringGuts.swift @@ -167,8 +167,7 @@ extension _StringGuts { _ f: (UnsafeBufferPointer) throws -> R ) rethrows -> R { return try self.withFastUTF8 { utf8 in - let ptr = utf8.baseAddress._unsafelyUnwrappedUnchecked._asCChar - return try f(UnsafeBufferPointer(start: ptr, count: utf8.count)) + return try utf8.withMemoryRebound(to: CChar.self, f) } } } diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb index d51fe39bc1a95..fce7d0fcd929d 100644 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb @@ -381,6 +381,49 @@ extension Unsafe${Mutable}RawBufferPointer { return baseAddress!.load(fromByteOffset: offset, as: T.self) } + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. + /// + /// This function only supports loading trivial types. + /// A trivial type does not contain any reference-counted property + /// within its in-memory stored representation. + /// The memory at `offset` bytes into the buffer must be laid out + /// identically to the in-memory representation of `T`. + /// + /// You can use this method to create new values from the buffer pointer's + /// underlying bytes. The following example creates two new `Int32` + /// instances from the memory referenced by the buffer pointer `someBytes`. + /// The bytes for `a` are copied from the first four bytes of `someBytes`, + /// and the bytes for `b` are copied from the next four bytes. + /// + /// let a = someBytes.load(as: Int32.self) + /// let b = someBytes.load(fromByteOffset: 4, as: Int32.self) + /// + /// The memory to read for the new instance must not extend beyond the buffer + /// pointer's memory region---that is, `offset + MemoryLayout.size` must + /// be less than or equal to the buffer pointer's `count`. + /// + /// - Parameters: + /// - offset: The offset, in bytes, into the buffer pointer's memory at + /// which to begin reading data for the new instance. The buffer pointer + /// plus `offset` must be properly aligned for accessing an instance of + /// type `T`. The default is zero. + /// - type: The type to use for the newly constructed instance. The memory + /// must be initialized to a value of a type that is layout compatible + /// with `type`. + /// - Returns: A new instance of type `T`, copied from the buffer pointer's + /// memory. + @_alwaysEmitIntoClient + public func loadUnaligned( + fromByteOffset offset: Int = 0, + as type: T.Type + ) -> T { + _debugPrecondition(offset >= 0, "${Self}.load with negative offset") + _debugPrecondition(offset + MemoryLayout.size <= self.count, + "${Self}.load out of bounds") + return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) + } + % if mutable: /// Stores a value's bytes into the buffer pointer's raw memory at the /// specified byte offset. @@ -399,6 +442,16 @@ extension Unsafe${Mutable}RawBufferPointer { /// type `U`. Calling `storeBytes(of:toByteOffset:as:)` does not change the /// bound type of the memory. /// + /// - Note: A trivial type can be copied with just a bit-for-bit copy without + /// any indirection or reference-counting operations. Generally, native + /// Swift types that do not contain strong or weak references or other + /// forms of indirection are trivial, as are imported C structs and enums. + /// + /// If you need to store into memory a copy of a value of a type that isn't + /// trivial, you cannot use the `storeBytes(of:toByteOffset:as:)` method. + /// Instead, you must know either initialize the memory or, + /// if you know the memory was already bound to `type`, assign to the memory. + /// /// - Parameters: /// - value: The value to store as raw bytes. /// - offset: The offset in bytes into the buffer pointer's memory to begin @@ -409,14 +462,34 @@ extension Unsafe${Mutable}RawBufferPointer { /// must be initialized to a value of a type that is layout compatible /// with `type`. @inlinable + @_alwaysEmitIntoClient + @_silgen_name("_swift_se0349_UnsafeMutableRawBufferPointer_storeBytes") public func storeBytes( - of value: T, toByteOffset offset: Int = 0, as: T.Type + of value: T, toByteOffset offset: Int = 0, as type: T.Type + ) { + _debugPrecondition(offset >= 0, "${Self}.storeBytes with negative offset") + _debugPrecondition(offset + MemoryLayout.size <= self.count, + "${Self}.storeBytes out of bounds") + + let pointer = baseAddress._unsafelyUnwrappedUnchecked + pointer.storeBytes(of: value, toByteOffset: offset, as: T.self) + } + + // This unavailable implementation uses the expected mangled name + // of `storeBytes(of:toByteOffset:as:)`, and provides an entry point for + // any binary compiled against the stlib binary for Swift 5.6 and older. + @available(*, unavailable) + @_silgen_name("$sSw10storeBytes2of12toByteOffset2asyx_SixmtlF") + @usableFromInline func _legacy_se0349_storeBytes( + of value: T, toByteOffset offset: Int = 0, as type: T.Type ) { _debugPrecondition(offset >= 0, "${Self}.storeBytes with negative offset") _debugPrecondition(offset + MemoryLayout.size <= self.count, "${Self}.storeBytes out of bounds") - baseAddress!.storeBytes(of: value, toByteOffset: offset, as: T.self) + baseAddress!._legacy_se0349_storeBytes_internal( + of: value, toByteOffset: offset, as: T.self + ) } /// Copies the bytes from the given buffer to this buffer's memory. diff --git a/stdlib/public/core/UnsafeRawPointer.swift b/stdlib/public/core/UnsafeRawPointer.swift index 7c1d424982a68..2ecacf05d1a74 100644 --- a/stdlib/public/core/UnsafeRawPointer.swift +++ b/stdlib/public/core/UnsafeRawPointer.swift @@ -424,7 +424,6 @@ public struct UnsafeRawPointer: _Pointer { let rawPointer = (self + offset)._rawValue #if compiler(>=5.5) && $BuiltinAssumeAlignment - // TODO: to support misaligned raw loads, simply remove this assumption. let alignedPointer = Builtin.assumeAlignment(rawPointer, MemoryLayout.alignment._builtinWordValue) @@ -434,6 +433,36 @@ public struct UnsafeRawPointer: _Pointer { #endif } + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. + /// + /// This function only supports loading trivial types, + /// and will trap if this precondition is not met. + /// A trivial type does not contain any reference-counted property + /// within its in-memory representation. + /// The memory at this pointer plus `offset` must be laid out + /// identically to the in-memory representation of `T`. + /// + /// - Note: A trivial type can be copied with just a bit-for-bit copy without + /// any indirection or reference-counting operations. Generally, native + /// Swift types that do not contain strong or weak references or other + /// forms of indirection are trivial, as are imported C structs and enums. + /// + /// - Parameters: + /// - offset: The offset from this pointer, in bytes. `offset` must be + /// nonnegative. The default is zero. + /// - type: The type of the instance to create. + /// - Returns: A new instance of type `T`, read from the raw bytes at + /// `offset`. The returned instance isn't associated + /// with the value in the range of memory referenced by this pointer. + @_alwaysEmitIntoClient + public func loadUnaligned( + fromByteOffset offset: Int = 0, + as type: T.Type + ) -> T { + _debugPrecondition(_isPOD(T.self)) + return Builtin.loadRaw((self + offset)._rawValue) + } } extension UnsafeRawPointer: Strideable { @@ -1120,7 +1149,6 @@ public struct UnsafeMutableRawPointer: _Pointer { let rawPointer = (self + offset)._rawValue #if compiler(>=5.5) && $BuiltinAssumeAlignment - // TODO: to support misaligned raw loads, simply remove this assumption. let alignedPointer = Builtin.assumeAlignment(rawPointer, MemoryLayout.alignment._builtinWordValue) @@ -1130,11 +1158,41 @@ public struct UnsafeMutableRawPointer: _Pointer { #endif } + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. + /// + /// This function only supports loading trivial types, + /// and will trap if this precondition is not met. + /// A trivial type does not contain any reference-counted property + /// within its in-memory representation. + /// The memory at this pointer plus `offset` must be laid out + /// identically to the in-memory representation of `T`. + /// + /// - Note: A trivial type can be copied with just a bit-for-bit copy without + /// any indirection or reference-counting operations. Generally, native + /// Swift types that do not contain strong or weak references or other + /// forms of indirection are trivial, as are imported C structs and enums. + /// + /// - Parameters: + /// - offset: The offset from this pointer, in bytes. `offset` must be + /// nonnegative. The default is zero. + /// - type: The type of the instance to create. + /// - Returns: A new instance of type `T`, read from the raw bytes at + /// `offset`. The returned instance isn't associated + /// with the value in the range of memory referenced by this pointer. + @_alwaysEmitIntoClient + public func loadUnaligned( + fromByteOffset offset: Int = 0, + as type: T.Type + ) -> T { + _debugPrecondition(_isPOD(T.self)) + return Builtin.loadRaw((self + offset)._rawValue) + } + /// Stores the given value's bytes into raw memory at the specified offset. /// - /// The type `T` to be stored must be a trivial type. The memory at this - /// pointer plus `offset` must be properly aligned for accessing `T`. The - /// memory must also be uninitialized, initialized to `T`, or initialized to + /// The type `T` to be stored must be a trivial type. The memory + /// must also be uninitialized, initialized to `T`, or initialized to /// another trivial type that is layout compatible with `T`. /// /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is @@ -1148,14 +1206,14 @@ public struct UnsafeMutableRawPointer: _Pointer { /// Swift types that do not contain strong or weak references or other /// forms of indirection are trivial, as are imported C structs and enums. /// - /// If you need to store a copy of a nontrivial value into memory, or to - /// store a value into memory that contains a nontrivial value, you cannot - /// use the `storeBytes(of:toByteOffset:as:)` method. Instead, you must know - /// the type of value previously in memory and initialize or assign the - /// memory. For example, to replace a value stored in a raw pointer `p`, + /// If you need to store into memory a copy of a value of a type that isn't + /// trivial, you cannot use the `storeBytes(of:toByteOffset:as:)` method. + /// Instead, you must know either initialize the memory or, + /// if you know the memory was already bound to `type`, assign to the memory. + /// For example, to replace a value stored in a raw pointer `p`, /// where `U` is the current type and `T` is the new type, use a typed /// pointer to access and deinitialize the current value before initializing - /// the memory with a new value. + /// the memory with a new value: /// /// let typedPointer = p.bindMemory(to: U.self, capacity: 1) /// typedPointer.deinitialize(count: 1) @@ -1167,8 +1225,41 @@ public struct UnsafeMutableRawPointer: _Pointer { /// nonnegative. The default is zero. /// - type: The type of `value`. @inlinable + @_alwaysEmitIntoClient + @_silgen_name("_swift_se0349_UnsafeMutableRawPointer_storeBytes") public func storeBytes( of value: T, toByteOffset offset: Int = 0, as type: T.Type + ) { + _debugPrecondition(_isPOD(T.self)) + + withUnsafePointer(to: value) { source in + // FIXME: to be replaced by _memcpy when conversions are implemented. + Builtin.int_memcpy_RawPointer_RawPointer_Int64( + (self + offset)._rawValue, + source._rawValue, + UInt64(MemoryLayout.size)._value, + /*volatile:*/ false._value + ) + } + } + + // This unavailable implementation uses the expected mangled name + // of `storeBytes(of:toByteOffset:as:)`, and provides an entry point for + // any binary compiled against the stlib binary for Swift 5.6 and older. + @available(*, unavailable) + @_silgen_name("sSv10storeBytes2of12toByteOffset2asyx_SixmtlF") + @usableFromInline func _legacy_se0349_storeBytes( + of value: T, toByteOffset offset: Int = 0, as type: T.Type + ) { + _legacy_se0349_storeBytes_internal( + of: value, toByteOffset: offset, as: T.self + ) + } + + // This is the implementation of `storeBytes` from SwiftStdlib 5.6 + @_alwaysEmitIntoClient + internal func _legacy_se0349_storeBytes_internal( + of value: T, toByteOffset offset: Int = 0, as type: T.Type ) { _debugPrecondition(0 == (UInt(bitPattern: self + offset) & (UInt(MemoryLayout.alignment) - 1)), @@ -1183,7 +1274,7 @@ public struct UnsafeMutableRawPointer: _Pointer { /*volatile:*/ false._value) } } - + /// Copies the specified number of bytes from the given raw pointer's memory /// into this pointer's memory. /// diff --git a/stdlib/public/runtime/AccessibleFunction.cpp b/stdlib/public/runtime/AccessibleFunction.cpp index 95e9678323bf6..e71cf09206af8 100644 --- a/stdlib/public/runtime/AccessibleFunction.cpp +++ b/stdlib/public/runtime/AccessibleFunction.cpp @@ -23,6 +23,7 @@ #include "swift/Runtime/Metadata.h" #include +#include using namespace swift; @@ -153,7 +154,7 @@ swift::runtime::swift_findAccessibleFunction(const char *targetNameStart, S.Cache.getOrInsert( name, [&](AccessibleFunctionCacheEntry *entry, bool created) { if (created) - new (entry) AccessibleFunctionCacheEntry{name, record}; + ::new (entry) AccessibleFunctionCacheEntry{name, record}; return true; }); } diff --git a/stdlib/public/runtime/AnyHashableSupport.cpp b/stdlib/public/runtime/AnyHashableSupport.cpp index 65d9e810bdbcf..3002ccca53b9f 100644 --- a/stdlib/public/runtime/AnyHashableSupport.cpp +++ b/stdlib/public/runtime/AnyHashableSupport.cpp @@ -21,6 +21,8 @@ #include "swift/Runtime/Debug.h" #include "swift/Runtime/HeapObject.h" +#include + using namespace swift; using namespace swift::hashable_support; @@ -103,7 +105,7 @@ findHashableBaseTypeImpl(const Metadata *type) { HashableConformances.getOrInsert(key, [&](HashableConformanceEntry *entry, bool created) { if (created) - new (entry) HashableConformanceEntry(key, baseTypeThatConformsToHashable); + ::new (entry) HashableConformanceEntry(key, baseTypeThatConformsToHashable); return true; // Keep the new entry. }); return baseTypeThatConformsToHashable; diff --git a/stdlib/public/runtime/AutoDiffSupport.cpp b/stdlib/public/runtime/AutoDiffSupport.cpp index 467ae2b3e37ce..6e8ec4d1d8190 100644 --- a/stdlib/public/runtime/AutoDiffSupport.cpp +++ b/stdlib/public/runtime/AutoDiffSupport.cpp @@ -14,6 +14,8 @@ #include "swift/ABI/Metadata.h" #include "swift/Runtime/HeapObject.h" +#include + using namespace swift; using namespace llvm; @@ -59,7 +61,7 @@ AutoDiffLinearMapContext *swift::swift_autoDiffCreateLinearMapContext( sizeof(AutoDiffLinearMapContext), alignof(AutoDiffLinearMapContext)) + topLevelLinearMapStructSize; auto *buffer = (AutoDiffLinearMapContext *)malloc(allocationSize); - return new (buffer) AutoDiffLinearMapContext; + return ::new (buffer) AutoDiffLinearMapContext; } void *swift::swift_autoDiffProjectTopLevelSubcontext( diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp index 4ab4b62f5bb34..940e1b08317fe 100644 --- a/stdlib/public/runtime/HeapObject.cpp +++ b/stdlib/public/runtime/HeapObject.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "../SwiftShims/GlobalObjects.h" #include "../SwiftShims/RuntimeShims.h" @@ -124,7 +125,7 @@ static HeapObject *_swift_allocObject_(HeapMetadata const *metadata, // NOTE: this relies on the C++17 guaranteed semantics of no null-pointer // check on the placement new allocator which we have observed on Windows, // Linux, and macOS. - new (object) HeapObject(metadata); + ::new (object) HeapObject(metadata); // If leak tracking is enabled, start tracking this object. SWIFT_LEAKS_START_TRACKING_OBJECT(object); diff --git a/stdlib/public/runtime/KeyPaths.cpp b/stdlib/public/runtime/KeyPaths.cpp index 4afed3e71ee1a..d504b2374b0ff 100644 --- a/stdlib/public/runtime/KeyPaths.cpp +++ b/stdlib/public/runtime/KeyPaths.cpp @@ -14,6 +14,7 @@ #include "swift/Runtime/Metadata.h" #include #include +#include using namespace swift; @@ -98,7 +99,7 @@ namespace { static OpaqueValue *allocateIn(const Metadata *type, YieldOnceBuffer *buffer) { auto *temp = - new (reinterpret_cast(buffer)) YieldOnceTemporary(type); + ::new (reinterpret_cast(buffer)) YieldOnceTemporary(type); return type->allocateBufferIn(&temp->Buffer); } diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 3f220df239358..90b9ce5ccd042 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -2385,7 +2385,7 @@ static ValueWitnessTable *getMutableVWTableForInit(StructMetadata *self, // Otherwise, allocate permanent memory for it and copy the existing table. void *memory = allocateMetadata(sizeof(ValueWitnessTable), alignof(ValueWitnessTable)); - auto newTable = new (memory) ValueWitnessTable(*oldTable); + auto newTable = ::new (memory) ValueWitnessTable(*oldTable); // If we ever need to check layout-completeness asynchronously from // initialization, we'll need this to be a store-release (and rely on @@ -4653,7 +4653,7 @@ static const WitnessTable *_getForeignWitnessTable( ForeignWitnessTables.getOrInsert( key, [&](ForeignWitnessTableCacheEntry *entryPtr, bool created) { if (created) - new (entryPtr) + ::new (entryPtr) ForeignWitnessTableCacheEntry(key, witnessTableCandidate); result = entryPtr->data; return true; diff --git a/stdlib/public/runtime/MetadataImpl.h b/stdlib/public/runtime/MetadataImpl.h index ac455a8cc9938..211d2b93512e8 100644 --- a/stdlib/public/runtime/MetadataImpl.h +++ b/stdlib/public/runtime/MetadataImpl.h @@ -51,6 +51,7 @@ #include "EnumImpl.h" #include +#include #include namespace swift { @@ -99,11 +100,11 @@ struct NativeBox { } static T *initializeWithCopy(T *dest, T *src) { - return new (dest) T(*src); + return ::new (dest) T(*src); } static T *initializeWithTake(T *dest, T *src) { - T *result = new (dest) T(std::move(*src)); + T *result = ::new (dest) T(std::move(*src)); src->T::~T(); return result; } diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index d0815b7e04736..fde4220c496ee 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -38,6 +38,7 @@ #include #include #include +#include using namespace swift; using namespace Demangle; @@ -774,7 +775,7 @@ _findContextDescriptor(Demangle::NodePointer node, *entry, bool created) { if (created) - new (entry) NominalTypeDescriptorCacheEntry{mangledName, foundContext}; + ::new (entry) NominalTypeDescriptorCacheEntry{mangledName, foundContext}; return true; }); @@ -931,7 +932,7 @@ _findProtocolDescriptor(NodePointer node, *entry, bool created) { if (created) - new (entry) ProtocolDescriptorCacheEntry{mangledName, foundProtocol}; + ::new (entry) ProtocolDescriptorCacheEntry{mangledName, foundProtocol}; return true; }); } diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index c3ebd11cbf44b..856132b92452d 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -31,6 +31,7 @@ #include "ImageInspection.h" #include "Private.h" +#include #include #if __has_include() @@ -510,7 +511,7 @@ struct ConformanceState { SectionsToScan.snapshot().count() != sectionsCount) return false; // abandon the new entry - new (entry) ConformanceCacheEntry( + ::new (entry) ConformanceCacheEntry( ConformanceCacheKey(type, proto), witness); return true; // keep the new entry }); diff --git a/stdlib/public/runtime/StackAllocator.h b/stdlib/public/runtime/StackAllocator.h index 2f23ff41cf1c5..9ab0c84030722 100644 --- a/stdlib/public/runtime/StackAllocator.h +++ b/stdlib/public/runtime/StackAllocator.h @@ -25,6 +25,7 @@ #include "swift/Runtime/Debug.h" #include "llvm/Support/Alignment.h" #include +#include // Notes: swift::fatalError is not shared between libswiftCore and libswift_Concurrency // and libswift_Concurrency uses swift_Concurrency_fatalError instead. @@ -170,7 +171,7 @@ class StackAllocator { assert(llvm::isAligned(llvm::Align(alignment), alignedSize)); assert(canAllocate(alignedSize)); void *buffer = getAddr(currentOffset); - auto *allocation = new (buffer) Allocation(lastAllocation, this); + auto *allocation = ::new (buffer) Allocation(lastAllocation, this); currentOffset += Allocation::includingHeader(alignedSize); if (guardAllocations) { uintptr_t *endOfCurrentAllocation = (uintptr_t *)getAddr(currentOffset); @@ -251,7 +252,7 @@ class StackAllocator { size_t capacity = std::max(SlabCapacity, Allocation::includingHeader(size)); void *slabBuffer = malloc(Slab::includingHeader(capacity)); - Slab *newSlab = new (slabBuffer) Slab(capacity); + Slab *newSlab = ::new (slabBuffer) Slab(capacity); if (slab) slab->next = newSlab; else @@ -292,7 +293,7 @@ class StackAllocator { char *end = (char *)firstSlabBuffer + bufferCapacity; assert(start + Slab::headerSize() <= end && "buffer for first slab too small"); - firstSlab = new (start) Slab(end - start - Slab::headerSize()); + firstSlab = ::new (start) Slab(end - start - Slab::headerSize()); firstSlabIsPreallocated = true; numAllocatedSlabs = 0; } diff --git a/stdlib/public/runtime/SwiftRT-COFF.cpp b/stdlib/public/runtime/SwiftRT-COFF.cpp index 61fc81b3c6fc7..5f94fcbe25bb3 100644 --- a/stdlib/public/runtime/SwiftRT-COFF.cpp +++ b/stdlib/public/runtime/SwiftRT-COFF.cpp @@ -65,7 +65,7 @@ static void swift_image_constructor() { { reinterpret_cast(&__start_##name) + sizeof(__start_##name), \ reinterpret_cast(&__stop_##name) - reinterpret_cast(&__start_##name) - sizeof(__start_##name) } - new (§ions) swift::MetadataSections { + ::new (§ions) swift::MetadataSections { swift::CurrentSectionMetadataVersion, { __ImageBase }, diff --git a/stdlib/public/runtime/SwiftRT-ELF.cpp b/stdlib/public/runtime/SwiftRT-ELF.cpp index 577843e449714..0c2253d50f93b 100644 --- a/stdlib/public/runtime/SwiftRT-ELF.cpp +++ b/stdlib/public/runtime/SwiftRT-ELF.cpp @@ -56,7 +56,7 @@ static void swift_image_constructor() { { reinterpret_cast(&__start_##name), \ static_cast(&__stop_##name - &__start_##name) } - new (§ions) swift::MetadataSections { + ::new (§ions) swift::MetadataSections { swift::CurrentSectionMetadataVersion, { __dso_handle }, diff --git a/stdlib/public/runtime/SwiftValue.mm b/stdlib/public/runtime/SwiftValue.mm index b7ea34b864a61..31b8fc3561083 100644 --- a/stdlib/public/runtime/SwiftValue.mm +++ b/stdlib/public/runtime/SwiftValue.mm @@ -34,6 +34,8 @@ #include #include +#include + using namespace swift; using namespace swift::hashable_support; @@ -196,7 +198,7 @@ static size_t getSwiftValuePayloadAlignMask(const Metadata *type) { */ auto header = getSwiftValueHeader(instance); - new (header) SwiftValueHeader(); + ::new (header) SwiftValueHeader(); header->type = srcType; auto payload = getSwiftValuePayload(instance, alignMask); diff --git a/test/ClangImporter/objc_async.swift b/test/ClangImporter/objc_async.swift index 04528006c2675..bc319d6ba32b2 100644 --- a/test/ClangImporter/objc_async.swift +++ b/test/ClangImporter/objc_async.swift @@ -4,6 +4,7 @@ // REQUIRES: concurrency import Foundation import ObjCConcurrency +// expected-remark@-1{{add '@preconcurrency' to suppress 'Sendable'-related warnings from module 'ObjCConcurrency'}} @available(SwiftStdlib 5.5, *) @MainActor func onlyOnMainActor() { } @@ -177,8 +178,16 @@ actor MySubclassCheckingSwiftAttributes : ProtocolWithSwiftAttributes { // Sendable conformance inference for imported types. func acceptCV(_: T) { } -func testCV(r: NSRange) { + +struct MyStruct: Sendable { + var range: NSRange + var inner: SendableStructWithNonSendable +} + +@available(SwiftStdlib 5.5, *) +func testCV(r: NSRange, someStruct: SendableStructWithNonSendable) async { acceptCV(r) + acceptCV(someStruct) } // Global actor (unsafe) isolation. @@ -314,6 +323,7 @@ func check() async { _ = await BazFrame(size: 0) } +@available(SwiftStdlib 5.5, *) func testSender( sender: NXSender, sendableObject: SendableClass, @@ -325,7 +335,7 @@ func testSender( nonSendableGeneric: GenericObject, ptr: UnsafeMutableRawPointer, stringArray: [String] -) { +) async { sender.sendAny(sendableObject) sender.sendAny(nonSendableObject) // expected-warning@-1 {{conformance of 'NonSendableClass' to 'Sendable' is unavailable}} @@ -344,22 +354,22 @@ func testSender( sender.sendProto(sendableProtos) sender.sendProto(nonSendableProtos) - // expected-error@-1 {{argument type 'any LabellyProtocol & ObjCClub' does not conform to expected type 'Sendable'}} - // FIXME(rdar://89992095): Should be a warning because we're in -warn-concurrency + // expected-warning@-1 {{type 'any LabellyProtocol & ObjCClub' does not conform to the 'Sendable' protocol}} sender.sendProtos(sendableProtos) sender.sendProtos(nonSendableProtos) - // expected-error@-1 {{argument type 'any LabellyProtocol & ObjCClub' does not conform to expected type 'Sendable'}} - // FIXME(rdar://89992095): Should be a warning because we're in -warn-concurrency + // expected-warning@-1 {{type 'any LabellyProtocol & ObjCClub' does not conform to the 'Sendable' protocol}} sender.sendAnyArray([sendableObject]) sender.sendAnyArray([nonSendableObject]) // expected-warning@-1 {{conformance of 'NonSendableClass' to 'Sendable' is unavailable}} sender.sendGeneric(sendableGeneric) + // expected-warning@-1{{type 'GenericObject' does not conform to the 'Sendable' protocol}} + // FIXME: Shouldn't warn + sender.sendGeneric(nonSendableGeneric) - // expected-error@-1 {{argument type 'GenericObject' does not conform to expected type 'Sendable'}} - // FIXME(rdar://89992095): Should be a warning because we're in -warn-concurrency + // expected-warning@-1 {{type 'GenericObject' does not conform to the 'Sendable' protocol}} sender.sendPtr(ptr) sender.sendStringArray(stringArray) diff --git a/test/Concurrency/Runtime/clock.swift b/test/Concurrency/Runtime/clock.swift new file mode 100644 index 0000000000000..55f24291d8691 --- /dev/null +++ b/test/Concurrency/Runtime/clock.swift @@ -0,0 +1,71 @@ +// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking -parse-as-library) + +// REQUIRES: concurrency +// REQUIRES: executable_test +// REQUIRES: concurrency_runtime + +import _Concurrency +import StdlibUnittest + +var tests = TestSuite("Time") + +@main struct Main { + static func main() async { + tests.test("ContinuousClock sleep") { + let clock = ContinuousClock() + let elapsed = await clock.measure { + try! await clock.sleep(until: .now + .milliseconds(100)) + } + // give a reasonable range of expected elapsed time + expectTrue(elapsed > .milliseconds(90)) + expectTrue(elapsed < .milliseconds(200)) + } + + tests.test("SuspendingClock sleep") { + let clock = SuspendingClock() + let elapsed = await clock.measure { + try! await clock.sleep(until: .now + .milliseconds(100)) + } + // give a reasonable range of expected elapsed time + expectTrue(elapsed > .milliseconds(90)) + expectTrue(elapsed < .milliseconds(200)) + } + + tests.test("duration addition") { + let d1 = Duration.milliseconds(500) + let d2 = Duration.milliseconds(500) + let d3 = Duration.milliseconds(-500) + let sum = d1 + d2 + expectEqual(sum, .seconds(1)) + let comps = sum.components + expectEqual(comps.seconds, 1) + expectEqual(comps.attoseconds, 0) + let adjusted = sum + d3 + expectEqual(adjusted, .milliseconds(500)) + } + + tests.test("duration subtraction") { + let d1 = Duration.nanoseconds(500) + let d2 = d1 - .nanoseconds(100) + expectEqual(d2, .nanoseconds(400)) + let d3 = d1 - .nanoseconds(500) + expectEqual(d3, .nanoseconds(0)) + let d4 = d1 - .nanoseconds(600) + expectEqual(d4, .nanoseconds(-100)) + } + + tests.test("duration division") { + let d1 = Duration.seconds(1) + let halfSecond = d1 / 2 + expectEqual(halfSecond, .milliseconds(500)) + } + + tests.test("duration multiplication") { + let d1 = Duration.seconds(1) + let twoSeconds = d1 * 2 + expectEqual(twoSeconds, .seconds(2)) + } + + await runAllTestsAsync() + } +} \ No newline at end of file diff --git a/test/Concurrency/async_main_resolution.swift b/test/Concurrency/async_main_resolution.swift index 8fe98e35c5307..51af600be6187 100644 --- a/test/Concurrency/async_main_resolution.swift +++ b/test/Concurrency/async_main_resolution.swift @@ -1,6 +1,11 @@ +// This test aims to show that no preference is given to either the async or +// sync main function. The most specific, valid, main function will be +// selected if one exists. If two main functions could exist, the usage is +// ambiguous. + // async main is nested deeper in protocols than sync, use sync // sync main is nested deeper in protocols than async, use async -// async and sync are same level, use async +// async and sync are same level, error // REQUIRES: concurrency @@ -10,23 +15,17 @@ // BOTH: MainProtocol has both sync and async main // INHERIT_SYNC: main type directly conforms to synchronous main protocol -// | async flag | has async main | has sync main | both | inherits sync | nested async | Result | Run | -// | | | | | | | Error | RUN: not %target-swift-frontend -disable-availability-checking -DNO_ASYNC -DNO_SYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR -// | | x | | | | | Async Main | RUN: %target-swift-frontend -disable-availability-checking -DNO_SYNC -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC -// | x | | x | | | | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -DNO_ASYNC -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC -// | x | x | x | | | | Async Main | RUN: %target-swift-frontend -disable-availability-checking -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC -// | | x | x | | | | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC -// | | x | x | | | x | Async Main | RUN: %target-swift-frontend -disable-availability-checking -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC -// | | x | x | | x | x | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -DINHERIT_SYNC -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC -// | x | x | x | | x | x | Async Main | RUN: %target-swift-frontend -disable-availability-checking -DINHERIT_SYNC -DASYNC_NESTED -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC -// | x | | x | | x | x | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -DNO_ASYNC -DINHERIT_SYNC -DASYNC_NESTED -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC -// | | | x | x | | | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -DBOTH -DNO_ASYNC -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC -// | x | | x | x | | | Async Main | RUN: %target-swift-frontend -disable-availability-checking -DBOTH -DNO_ASYNC -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC - -// tldr; -// If async flag is set, will pick an asynchronous main function if one is available and related. If none exist, will fall back on synchronous main. -// If async flag is not set, will pick a asynchronous main function if one is available and related. If none exist, will fall back on an asynchronous main -// If neither are available; error +// | has async main | has sync main | both | inherits sync | nested async | Result | | Run | +// | | | | | | Error | No main | RUN: not %target-swift-frontend -disable-availability-checking -DNO_SYNC -DNO_ASYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR1 +// | x | x | x | x | | Error | Ambiguous main in MainP | RUN: not %target-swift-frontend -disable-availability-checking -DBOTH -DINHERIT_SYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR2 +// | | x | x | x | | Error | Ambiguous main in MainP | RUN: not %target-swift-frontend -disable-availability-checking -DBOTH -DINHERIT_SYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR2 +// | x | x | x | | | Async | Directly selected | RUN: %target-swift-frontend -disable-availability-checking -DBOTH -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC +// | x | x | | | | Async | Directly selected | RUN: %target-swift-frontend -disable-availability-checking -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC +// | | x | | | | Sync | Indirectly selected | RUN: %target-swift-frontend -disable-availability-checking -DNO_ASYNC -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC +// | x | x | | x | x | Sync | Directly selected | RUN: %target-swift-frontend -disable-availability-checking -DINHERIT_SYNC -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC +// | x | | | x | x | Async | Indirectly selected | RUN: %target-swift-frontend -disable-availability-checking -DNO_SYNC -DINHERIT_SYNC -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC +// | x | | | x | | Error | Unrelated async main | RUN: not %target-swift-frontend -disable-availability-checking -DNO_SYNC -DINHERIT_SYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR1 +// | | x | | | x | Error | Unrelated sync main | RUN: not %target-swift-frontend -disable-availability-checking -DNO_ASYNC -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR1 #if ASYNC_NESTED protocol AsyncMainProtocol { } @@ -71,4 +70,5 @@ extension MainProtocol { // CHECK-IS-ASYNC: (func_decl implicit "$main()" interface type='(MyMain.Type) -> () async -> ()' // CHECK-IS-ASYNC: (declref_expr implicit type='(MyMain.Type) -> () async -> ()' -// CHECK-IS-ERROR: error: 'MyMain' is annotated with @main and must provide a main static function of type {{\(\) -> Void or \(\) throws -> Void|\(\) -> Void, \(\) throws -> Void, \(\) async -> Void, or \(\) async throws -> Void}} +// CHECK-IS-ERROR1: error: 'MyMain' is annotated with @main and must provide a main static function of type {{\(\) -> Void or \(\) throws -> Void|\(\) -> Void, \(\) throws -> Void, \(\) async -> Void, or \(\) async throws -> Void}} +// CHECK-IS-ERROR2: error: ambiguous use of 'main' diff --git a/test/Concurrency/sendable_checking.swift b/test/Concurrency/sendable_checking.swift index 9531e579d0335..269ecd597a212 100644 --- a/test/Concurrency/sendable_checking.swift +++ b/test/Concurrency/sendable_checking.swift @@ -59,7 +59,7 @@ func testCV( acceptCV(ns4) // expected-warning{{type 'NS4' does not conform to the 'Sendable' protocol}} acceptCV(fn) // expected-warning{{type '() -> Void' does not conform to the 'Sendable' protocol}} // expected-note@-1{{a function type must be marked '@Sendable' to conform to 'Sendable'}} - acceptSendableFn(fn) // expected-error{{passing non-sendable parameter 'fn' to function expecting a @Sendable closure}} + acceptSendableFn(fn) // expected-warning{{passing non-sendable parameter 'fn' to function expecting a @Sendable closure}} } // rdar://83942484 - spurious Sendable diagnostics diff --git a/test/Concurrency/sendable_existentials.swift b/test/Concurrency/sendable_existentials.swift new file mode 100644 index 0000000000000..885d4b877e7c9 --- /dev/null +++ b/test/Concurrency/sendable_existentials.swift @@ -0,0 +1,54 @@ +// RUN: %target-typecheck-verify-swift -strict-concurrency=targeted +// REQUIRES: concurrency +// REQUIRES: OS=macosx + +@preconcurrency func send(_: Sendable) { } +func sendOpt(_: Sendable?) { } + +enum E { + case something(Sendable) +} + +@available(SwiftStdlib 5.1, *) +func testE(a: Any, aOpt: Any?) async { + send(a) // expected-warning{{type 'Any' does not conform to the 'Sendable' protocol}} + sendOpt(a) // expected-warning{{type 'Any' does not conform to the 'Sendable' protocol}} + sendOpt(aOpt) // expected-warning{{type 'Any' does not conform to the 'Sendable' protocol}} + + let _: E = .something(a) // expected-warning{{type 'Any' does not conform to the 'Sendable' protocol}} + _ = E.something(a) // expected-warning{{type 'Any' does not conform to the 'Sendable' protocol}} + + var sendable: Sendable + sendable = a // expected-warning{{type 'Any' does not conform to the 'Sendable' protocol}} + + var arrayOfSendable: [Sendable] + arrayOfSendable = [a, a] // expected-warning 2{{type 'Any' does not conform to the 'Sendable' protocol}} + + func localFunc() { } + sendable = localFunc // expected-warning{{type '() -> ()' does not conform to the 'Sendable' protocol}} + // expected-note@-1{{a function type must be marked '@Sendable' to conform to 'Sendable'}} + + _ = sendable + _ = arrayOfSendable +} + +func testESilently(a: Any, aOpt: Any?) { + send(a) + sendOpt(a) + sendOpt(aOpt) + + let _: E = .something(a) + _ = E.something(a) + + var sendable: Sendable + sendable = a + + var arrayOfSendable: [Sendable] + arrayOfSendable = [a, a] + + func localFunc() { } + sendable = localFunc + + _ = sendable + _ = arrayOfSendable +} diff --git a/test/Concurrency/where_clause_main_resolution.swift b/test/Concurrency/where_clause_main_resolution.swift index f650ec6f48257..9f491b974b51f 100644 --- a/test/Concurrency/where_clause_main_resolution.swift +++ b/test/Concurrency/where_clause_main_resolution.swift @@ -1,9 +1,6 @@ // RUN: %target-swift-frontend -disable-availability-checking -D CONFIG1 -dump-ast -parse-as-library %s | %FileCheck %s --check-prefixes=CHECK,CHECK-CONFIG1 -// RUN: %target-swift-frontend -disable-availability-checking -D CONFIG1 -dump-ast -parse-as-library -async-main %s | %FileCheck %s --check-prefixes=CHECK,CHECK-CONFIG1-ASYNC // RUN: %target-swift-frontend -disable-availability-checking -D CONFIG2 -dump-ast -parse-as-library %s | %FileCheck %s --check-prefixes=CHECK,CHECK-CONFIG2 -// RUN: %target-swift-frontend -disable-availability-checking -D CONFIG2 -dump-ast -parse-as-library -async-main %s | %FileCheck %s --check-prefixes=CHECK,CHECK-CONFIG2-ASYNC // RUN: %target-swift-frontend -disable-availability-checking -D CONFIG3 -dump-ast -parse-as-library %s | %FileCheck %s --check-prefixes=CHECK,CHECK-CONFIG3 -// RUN: %target-swift-frontend -disable-availability-checking -D CONFIG3 -dump-ast -parse-as-library -async-main %s | %FileCheck %s --check-prefixes=CHECK,CHECK-CONFIG3-ASYNC // REQUIRES: concurrency @@ -21,40 +18,31 @@ protocol App { // CHECK: (source_file "[[SOURCE_FILE:[^"]+]]" // CHECK: (extension_decl range={{\[}}[[SOURCE_FILE]]:{{[0-9]+}}:{{[0-9]+}} - line:{{[0-9]+}}:{{[0-9]+}}{{\]}} App where // CHECK: (extension_decl range={{\[}}[[SOURCE_FILE]]:{{[0-9]+}}:{{[0-9]+}} - line:{{[0-9]+}}:{{[0-9]+}}{{\]}} App where +// CHECK: (extension_decl range={{\[}}[[SOURCE_FILE]]:{{[0-9]+}}:{{[0-9]+}} - line:{{[0-9]+}}:{{[0-9]+}}{{\]}} App where // CHECK: (extension_decl range={{\[}}[[SOURCE_FILE]]:{{[0-9]+}}:{{[0-9]+}} - line:{{[0-9]+}}:{{[0-9]+}}{{\]}} // CHECK-NOT: where // CHECK-NEXT: (func_decl range={{\[}}[[SOURCE_FILE]]:[[DEFAULT_ASYNCHRONOUS_MAIN_LINE:[0-9]+]]:{{[0-9]+}} - line:{{[0-9]+}}:{{[0-9]+}}{{\]}} "main()" // CHECK-SAME: interface type=' (Self.Type) -> () async -> ()' -// CHECK: (func_decl range={{\[}}[[SOURCE_FILE]]:[[DEFAULT_SYNCHRONOUS_MAIN_LINE:[0-9]+]]:{{[0-9]+}} - line:{{[0-9]+}}:{{[0-9]+}}{{\]}} "main()" -// CHECK-SAME: interface type=' (Self.Type) -> () -> ()' - extension App where Configuration == Config1 { // CHECK-CONFIG1: (func_decl implicit "$main()" interface type='(MainType.Type) -> () -> ()' // CHECK-CONFIG1: [[SOURCE_FILE]]:[[# @LINE+1 ]] static func main() { } - -// CHECK-CONFIG1-ASYNC: (func_decl implicit "$main()" interface type='(MainType.Type) -> () async -> ()' -// CHECK-CONFIG1-ASYNC: [[SOURCE_FILE]]:[[DEFAULT_ASYNCHRONOUS_MAIN_LINE]] } extension App where Configuration == Config2 { -// CHECK-CONFIG2: (func_decl implicit "$main()" interface type='(MainType.Type) -> () -> ()' -// CHECK-CONFIG2: [[SOURCE_FILE]]:[[DEFAULT_SYNCHRONOUS_MAIN_LINE]] - -// CHECK-CONFIG2-ASYNC: (func_decl implicit "$main()" interface type='(MainType.Type) -> () async -> ()' -// CHECK-CONFIG2-ASYNC: [[SOURCE_FILE]]:[[# @LINE+1 ]] +// CHECK-CONFIG2: (func_decl implicit "$main()" interface type='(MainType.Type) -> () async -> ()' +// CHECK-CONFIG2: [[SOURCE_FILE]]:[[# @LINE+1 ]] static func main() async { } } -extension App { +extension App where Configuration == Config3 { // CHECK-CONFIG3-ASYNC: (func_decl implicit "$main()" interface type='(MainType.Type) -> () async -> ()' -// CHECK-CONFIG3-ASYNC: [[SOURCE_FILE]]:[[# @LINE+1 ]] - static func main() async { } +// CHECK-CONFIG3-ASYNC: [[SOURCE_FILE]]:[[DEFAULT_ASYNCHRONOUS_MAIN_LINE]] +} -// CHECK-CONFIG3: (func_decl implicit "$main()" interface type='(MainType.Type) -> () -> ()' -// CHECK-CONFIG3: [[SOURCE_FILE]]:[[# @LINE+1 ]] - static func main() { } +extension App { + static func main() async { } } @main diff --git a/test/Constraints/availability.swift b/test/Constraints/availability.swift index 2fe93b9f20286..3e70211d47089 100644 --- a/test/Constraints/availability.swift +++ b/test/Constraints/availability.swift @@ -43,3 +43,25 @@ func unavailableFunction(_ x: Int) -> Bool { true } // expected-note {{'unavaila func sr13260(_ arr: [Int]) { for x in arr where unavailableFunction(x) {} // expected-error {{'unavailableFunction' is unavailable}} } + +// rdar://92364955 - ambiguity with member declared in unavailable extension +struct WithUnavailableExt { +} + +@available(*, unavailable) +extension WithUnavailableExt { + static var foo: WithUnavailableExt = WithUnavailableExt() +} + +func test_no_ambiguity_with_unavailable_ext() { + struct A { + static var foo: A = A() + } + + struct Test { + init(_: A) {} + init(_: WithUnavailableExt) {} + } + + _ = Test(.foo) // Ok `A.foo` since `foo` from `WithUnavailableExt` is unavailable +} diff --git a/test/Distributed/Runtime/distributed_actor_in_other_module.swift b/test/Distributed/Runtime/distributed_actor_in_other_module.swift index 0d4889fb320b6..ebae97b8589b9 100644 --- a/test/Distributed/Runtime/distributed_actor_in_other_module.swift +++ b/test/Distributed/Runtime/distributed_actor_in_other_module.swift @@ -15,6 +15,8 @@ // FIXME(distributed): Distributed actors currently have some issues on windows, isRemote always returns false. rdar://82593574 // UNSUPPORTED: windows +// REQUIRES: rdar92277324 + import Distributed import EchoActorModule import FakeDistributedActorSystems diff --git a/test/Distributed/distributed_actor_layout.swift b/test/Distributed/distributed_actor_layout.swift index 140189278811a..68f6e9e4ad71d 100644 --- a/test/Distributed/distributed_actor_layout.swift +++ b/test/Distributed/distributed_actor_layout.swift @@ -17,8 +17,18 @@ class MyClass { } // Ensure that the actor layout is (metadata pointer, default actor, id, system, // ) +protocol HasActorSystem { + var actorSystem: FakeActorSystem { get } +} + +extension MyActor: HasActorSystem { } + // CHECK: %T27distributed_actor_accessors7MyActorC = type <{ %swift.refcounted, %swift.defaultactor, %T27FakeDistributedActorSystems0C7AddressV, %T27FakeDistributedActorSystems0aC6SystemV, %T27distributed_actor_accessors7MyClassC* }> @available(SwiftStdlib 5.7, *) public distributed actor MyActor { var field: MyClass = MyClass() + + init(actorSystem: FakeActorSystem) { + self.actorSystem = actorSystem + } } diff --git a/test/IDE/complete_call_arg.swift b/test/IDE/complete_call_arg.swift index e1c065ef09a3b..7ce601fffdefa 100644 --- a/test/IDE/complete_call_arg.swift +++ b/test/IDE/complete_call_arg.swift @@ -1271,6 +1271,7 @@ func testSkippedCallArgInInvalidResultBuilderBody() { Other(action: 2) { MyImage(systemName: "", #^INVALID_RESULTBUILDER_ARG^# struct Invalid + } } // INVALID_RESULTBUILDER_ARG: Begin completions, 1 item @@ -1399,3 +1400,17 @@ func testVarInitializedByCallingClosure() { // VAR_INITIALIZED_BY_CALLING_CLOSURE-DAG: Pattern/Local/Flair[ArgLabels]: {#withExtension: String?#}[#String?#]; // VAR_INITIALIZED_BY_CALLING_CLOSURE: End completions } + +struct Rdar89773376 { + var intVal: Int +} +extension Rdar89773376 { + init(string: String) { self.intVal = 1 } +} +func testRdar89773376(arry: [Int]) { + arry.map { Rdar89773376(#^RDAR89773376^#) } +// RDAR89773376: Begin completions, 2 items +// RDAR89773376-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#string: String#}[')'][#Rdar89773376#]; +// RDAR89773376-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#intVal: Int#}[')'][#Rdar89773376#]; +// RDAR89773376: End completions +} diff --git a/test/IDE/complete_default_arguments_rdar89051832.swift b/test/IDE/complete_default_arguments_rdar89051832.swift new file mode 100644 index 0000000000000..e0e3298ffaa4a --- /dev/null +++ b/test/IDE/complete_default_arguments_rdar89051832.swift @@ -0,0 +1,69 @@ + +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -batch-code-completion -source-filename %t/test.swift -filecheck %raw-FileCheck -completion-output-dir %t/out -code-completion-annotate-results -import-objc-header %t/ObjC.h -enable-objc-interop %t/Lib.swift +// REQUIRES: objc_interop + + +//--- ObjC.h +@import Foundation; + +typedef NS_OPTIONS(NSInteger, MyOptions) { + MyOptOne = 1 << 0, + MyOptTwo = 1 << 1, +}; + +@interface MyObj : NSObject +// 'opt' should not be defaulted. +// FIXME: Currently this is considered defaulted because the base name is 'store'. +- (void)storeOptions:(MyOptions)opts; + +// 'opts' should not be defaulted. +- (void)addOptions:(NSDictionary*)opts; + +// 'attrs' should not be defaulted. +- (void)addAttributes:(NSDictionary *)attrs; + +// 'info' should not be defaulted but 'opts' should be. +- (void)addUserInfo:(NSDictionary *)info options:(MyOptions)opts; + +// 'opts' should be defaulted because the base name is 'run'. +- (void)runWithOptions:(MyOptions)opts; + +// 'attrs' should be defaulted because the base name is 'execute'. +- (void)executeWithAttributes:(NSDictionary *)attrs; +@end + +//--- Lib.swift +extension MyObj { + // 'attrs' should not be defaulted because this is explicitly written in Swift. + func swift_addAttributes(_ attrs : [AnyHashable:Any]! = [:]) {} +} + +//--- test.swift +func test(value: MyObj) { + value.#^COMPLETE^# +// COMPLETE: Begin completions +// COMPLETE-NOT: name=addOptions() +// COMPLETE-NOT: name=addAttributes() + +// FIXME: we don't want to suggest 'store()'. +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: store(); typename=Void; name=store() +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: store(_ opts: MyOptions); typename=Void; name=store(:) +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: addOptions(_ opts: [AnyHashable : Any]!); typename=Void; name=addOptions(:) +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: addAttributes(_ attrs: [AnyHashable : Any]!); typename=Void; name=addAttributes(:) +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: addUserInfo(_ info: [AnyHashable : Any]!); typename=Void; name=addUserInfo(:) +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: addUserInfo(_ info: [AnyHashable : Any]!, options opts: MyOptions); typename=Void; name=addUserInfo(:options:) +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: run(); typename=Void; name=run() +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: run(options opts: MyOptions); typename=Void; name=run(options:) +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: execute(); typename=Void; name=execute() +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: execute(attributes attrs: [AnyHashable : Any]!); typename=Void; name=execute(attributes:) +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: swift_addAttributes(); typename=Void; name=swift_addAttributes() +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal: swift_addAttributes(_ attrs: [AnyHashable : Any]!); typename=Void; name=swift_addAttributes(:) + +// COMPLETE-NOT: name=addOptions() +// COMPLETE-NOT: name=addAttributes() +// COMPLETE: End completions +} + diff --git a/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h b/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h index 10713b46eebc1..ab524142ef336 100644 --- a/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h +++ b/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h @@ -265,6 +265,11 @@ typedef NSString *NonSendableStringEnum NS_STRING_ENUM NONSENDABLE; typedef NSString *SendableStringStruct NS_EXTENSIBLE_STRING_ENUM; typedef NSString *NonSendableStringStruct NS_EXTENSIBLE_STRING_ENUM NONSENDABLE; +SENDABLE +typedef struct { + void *ptr; +} SendableStructWithNonSendable; + ASSUME_NONSENDABLE_END typedef id ObjectTypedef; diff --git a/test/Interpreter/SDK/objc_old_swift.swift b/test/Interpreter/SDK/objc_old_swift.swift index 76c9a8900ff4d..4b9250eb1121a 100644 --- a/test/Interpreter/SDK/objc_old_swift.swift +++ b/test/Interpreter/SDK/objc_old_swift.swift @@ -9,6 +9,11 @@ // REQUIRES: executable_test // REQUIRES: objc_interop +// The bit twiddling done by this test falls afoul of ptrauth on ARM64e. We +// don't support pre-stable Swift ABI code on ARM64e anyway, so just disable the +// test there. +// UNSUPPORTED: CPU=arm64e + // Verify that objects that appear to be from the pre-stable Swift ABI // are correctly ignored by stable Swift's entry points. diff --git a/test/Interpreter/dynamic_lookup.swift b/test/Interpreter/dynamic_lookup.swift index 7a7125f9de822..3aa87bd964dab 100644 --- a/test/Interpreter/dynamic_lookup.swift +++ b/test/Interpreter/dynamic_lookup.swift @@ -5,6 +5,10 @@ import Foundation +@objc protocol P { + @objc optional func e() +} + class X { init() {} @@ -15,11 +19,15 @@ class X { return 17 } } +extension X: P { + @objc func e() { print("X.e()") } +} class Y { init() {} @objc class func g() { print("Y.g()") } } +extension Y: P {} class Z { init() {} @@ -44,7 +52,16 @@ func test_dynamic_lookup_f_unbound(_ obj: AnyObject) { if of != nil { of!() } else { - print("Object does not respond to the selector \"f\".\n", terminator: "") + print("\(type(of: obj)) does not respond to the selector \"f\"") + } +} + +func test_dynamic_lookup_e_unbound(_ obj: AnyObject) { + var oe = AnyObject.e(obj) + if oe != nil { + oe!() + } else { + print("\(type(of: obj)) does not respond to the selector \"e\"") } } @@ -77,11 +94,20 @@ test_dynamic_lookup_f(Z()) print(type(of: AnyObject.f)) // CHECK-NEXT: X.f() test_dynamic_lookup_f_unbound(X()) -// CHECK-NEXT: Object does not respond to the selector "f" +// CHECK-NEXT: Y does not respond to the selector "f" test_dynamic_lookup_f_unbound(Y()) // CHECK-NEXT: Z.f() test_dynamic_lookup_f_unbound(Z()) +// CHECK-NEXT: (AnyObject) -> Optional<() -> ()> +print(type(of: AnyObject.e)) +// CHECK-NEXT: X.e() +test_dynamic_lookup_e_unbound(X()) +// CHECK-NEXT: Y does not respond to the selector "e" +test_dynamic_lookup_e_unbound(Y()) +// CHECK-NEXT: Z does not respond to the selector "e" +test_dynamic_lookup_e_unbound(Z()) + // CHECK: Class does not respond to the selector "g" test_dynamic_lookup_g(X()) // CHECK: Y.g() diff --git a/test/Prototypes/PatternMatching.swift b/test/Prototypes/PatternMatching.swift index 33065d4a3729e..7383ba8466687 100644 --- a/test/Prototypes/PatternMatching.swift +++ b/test/Prototypes/PatternMatching.swift @@ -302,7 +302,9 @@ extension Collection where Iterator.Element == UTF8.CodeUnit { a.reserveCapacity(count + 1) a.append(contentsOf: self) a.append(0) - return String(reflecting: String(cString: a)) + return a.withUnsafeBufferPointer { + String(reflecting: String(cString: $0.baseAddress!)) + } } } diff --git a/test/SIL/verifier-no-nested-suspend.sil b/test/SIL/verifier-no-nested-suspend.sil new file mode 100644 index 0000000000000..bb3af4c21c256 --- /dev/null +++ b/test/SIL/verifier-no-nested-suspend.sil @@ -0,0 +1,26 @@ +// RUN: not --crash %target-sil-opt %s 2>&1 | %FileCheck %s +// REQUIRES: asserts + +// CHECK: cannot suspend async task while unawaited continuation is active + +sil_stage raw + +import Builtin +import Swift +import SwiftShims +import _Concurrency + +// hello(_:) +sil hidden [ossa] @$s4main5helloyS2bYaF : $@convention(thin) @async (Bool) -> Bool { +bb0(%0 : $Bool): + debug_value %0 : $Bool, let, name "b", argno 1 + %2 = enum $Optional, #Optional.none!enumelt + %22 = alloc_stack $Bool + %27 = get_async_continuation_addr Bool, %22 : $*Bool + hop_to_executor %2 : $Optional // <- the bad nested suspension + await_async_continuation %27 : $Builtin.RawUnsafeContinuation, resume bb1 + +bb1: + dealloc_stack %22 : $*Bool + return %0 : $Bool +} diff --git a/test/SILOptimizer/licm.sil b/test/SILOptimizer/licm.sil index ad5b7c2f1d594..8a5729a5bc88a 100644 --- a/test/SILOptimizer/licm.sil +++ b/test/SILOptimizer/licm.sil @@ -8,6 +8,13 @@ sil_stage canonical import Builtin import Swift +class Storage { + init() +} + +// globalArray +sil_global @globalArray : $Storage + // CHECK-LABEL: @memset // CHECK: bb0 @@ -1397,3 +1404,71 @@ bb6: return %15 : $() } +struct UInt64 { + @_hasStorage var _value: Builtin.Int64 { get set } + init(_value: Builtin.Int64) +} + +public struct UInt64Wrapper { + @_hasStorage public var rawValue: UInt64 { get set } + private init(_ rawValue: UInt64) + public init() +} + +// rdar://92191909 (LICM assertion: isSubObjectProjection(), MemAccessUtils.h, line 1069) +// +// projectLoadValue needs to rematerialize a loaded value within the +// loop using projections and the loop-invariant address is an +// index_addr. +// +// The store inside the loop is deleted, and the load is hoisted such +// that it now loads the UInt64Wrapper instead of Builtin.Int64 +// CHECK-LABEL: sil @testTailProjection : $@convention(thin) () -> () { +// CHECK: bb0: +// CHECK: [[A:%.*]] = index_addr %4 : $*UInt64Wrapper, %1 : $Builtin.Word +// CHECK: store %{{.*}} to [[A]] : $*UInt64Wrapper +// CHECK: load %5 : $*UInt64Wrapper +// CHECK: br bb1 +// CHECK: bb1(%{{.*}} : $Builtin.Int64, %{{.*}} : $UInt64Wrapper, [[PHI:%.*]] : $UInt64Wrapper): +// CHECK: cond_br undef, bb3, bb2 +// CHECK: bb2: +// CHECK-NOT: (load|store) +// CHECK: struct_extract [[PHI]] : $UInt64Wrapper, #UInt64Wrapper.rawValue +// CHECK: struct_extract +// CHECK: struct $UInt64 +// CHECK: struct $UInt64Wrapper +// CHECK-NOT: (load|store) +// CHECK: br bb1 +// CHECK: bb3: +// CHECK: store [[PHI]] to [[A]] : $*UInt64Wrapper +// CHECK-LABEL: } // end sil function 'testTailProjection' +sil @testTailProjection : $@convention(thin) () -> () { +bb0: + %0 = integer_literal $Builtin.Int64, 0 + %1 = integer_literal $Builtin.Word, 1 + %2 = integer_literal $Builtin.Word, 2 + %3 = alloc_ref [tail_elems $UInt64Wrapper * %2 : $Builtin.Word] $Storage + %4 = ref_tail_addr %3 : $Storage, $UInt64Wrapper + %5 = index_addr %4 : $*UInt64Wrapper, %1 : $Builtin.Word + %6 = struct $UInt64 (%0 : $Builtin.Int64) + %7 = struct $UInt64Wrapper (%6 : $UInt64) + store %7 to %5 : $*UInt64Wrapper + %9 = load %5 : $*UInt64Wrapper + br bb1(%0 : $Builtin.Int64, %9 : $UInt64Wrapper) + +bb1(%11 : $Builtin.Int64, %12 : $UInt64Wrapper): + cond_br undef, bb3, bb2 + +bb2: + %14 = struct_element_addr %5 : $*UInt64Wrapper, #UInt64Wrapper.rawValue + %15 = struct_element_addr %14 : $*UInt64, #UInt64._value + %16 = load %15 : $*Builtin.Int64 + %17 = struct $UInt64 (%16 : $Builtin.Int64) + %18 = struct $UInt64Wrapper (%17 : $UInt64) + store %18 to %5 : $*UInt64Wrapper + br bb1(%16 : $Builtin.Int64, %18 : $UInt64Wrapper) + +bb3: + %21 = tuple () + return %21 : $() +} diff --git a/test/StringProcessing/Parse/forward-slash-regex.swift b/test/StringProcessing/Parse/forward-slash-regex.swift index e416816c2e5b6..26d0a3040829c 100644 --- a/test/StringProcessing/Parse/forward-slash-regex.swift +++ b/test/StringProcessing/Parse/forward-slash-regex.swift @@ -242,16 +242,19 @@ baz(/,/) // expected-error@-2 {{missing argument for parameter #2 in call}} baz((/), /) +func bazbaz(_ x: (Int, Int) -> Int, _ y: Int) {} +bazbaz(/, 0) + func qux(_ x: (Int, Int) -> Int, _ y: T) -> Int { 0 } do { _ = qux(/, 1) / 2 - // expected-error@-1 {{cannot parse regular expression: closing ')' does not balance any groups openings}} - // expected-error@-2 {{expected ',' separator}} + // expected-error@-1:15 {{cannot parse regular expression: closing ')' does not balance any groups openings}} + // expected-error@-2:19 {{expected ',' separator}} } do { _ = qux(/, "(") / 2 // expected-error@-1 {{cannot convert value of type 'Regex<(Substring, Substring)>' to expected argument type '(Int, Int) -> Int'}} - // expected-error@-2 {{expected ',' separator}} + // expected-error@-2:21 {{expected ',' separator}} } _ = qux(/, 1) // this comment tests to make sure we don't try and end the regex on the starting '/' of '//'. diff --git a/test/StringProcessing/Parse/regex.swift b/test/StringProcessing/Parse/regex.swift index f351e503833c6..797fc2af85eec 100644 --- a/test/StringProcessing/Parse/regex.swift +++ b/test/StringProcessing/Parse/regex.swift @@ -19,5 +19,5 @@ _ = #/#/\/\#\\/# _ = ##/#|\|\#\\/## _ = (#/[*/#, #/+]/#, #/.]/#) -// expected-error@-1 {{cannot parse regular expression: quantifier '+' must appear after expression}} -// expected-error@-2 {{cannot parse regular expression: expected ']'}} +// expected-error@-1:16 {{cannot parse regular expression: quantifier '+' must appear after expression}} +// expected-error@-2:10 {{cannot parse regular expression: expected ']'}} diff --git a/test/StringProcessing/Parse/regex_parse_end_of_buffer.swift b/test/StringProcessing/Parse/regex_parse_end_of_buffer.swift index 53ef39918bd7e..5c62181c0c8c2 100644 --- a/test/StringProcessing/Parse/regex_parse_end_of_buffer.swift +++ b/test/StringProcessing/Parse/regex_parse_end_of_buffer.swift @@ -2,5 +2,6 @@ // REQUIRES: swift_in_compiler // Note there is purposefully no trailing newline here. -// expected-error@+1 {{unterminated regex literal}} -var unterminated = #/xy +// expected-error@+2:20 {{unterminated regex literal}} +// expected-error@+1:25 {{cannot parse regular expression: expected ')'}} +var unterminated = #/(xy \ No newline at end of file diff --git a/test/StringProcessing/Parse/regex_parse_error.swift b/test/StringProcessing/Parse/regex_parse_error.swift index b53500d8aed52..80e428469256d 100644 --- a/test/StringProcessing/Parse/regex_parse_error.swift +++ b/test/StringProcessing/Parse/regex_parse_error.swift @@ -1,28 +1,28 @@ // RUN: %target-typecheck-verify-swift -enable-bare-slash-regex -disable-availability-checking // REQUIRES: swift_in_compiler -_ = /(/ // expected-error {{expected ')'}} -_ = #/(/# // expected-error {{expected ')'}} +_ = /(/ // expected-error@:7 {{expected ')'}} +_ = #/(/# // expected-error@:8 {{expected ')'}} // FIXME: Should be 'group openings' -_ = /)/ // expected-error {{closing ')' does not balance any groups openings}} -_ = #/)/# // expected-error {{closing ')' does not balance any groups openings}} +_ = /)/ // expected-error@:6 {{closing ')' does not balance any groups openings}} +_ = #/)/# // expected-error@:7 {{closing ')' does not balance any groups openings}} -_ = #/\\/''/ // expected-error {{unterminated regex literal}} -_ = #/\| // expected-error {{unterminated regex literal}} -_ = #// // expected-error {{unterminated regex literal}} +_ = #/\\/''/ // expected-error@:5 {{unterminated regex literal}} +_ = #/\| // expected-error@:5 {{unterminated regex literal}} +_ = #// // expected-error@:5 {{unterminated regex literal}} -_ = #/xy // expected-error {{unterminated regex literal}} +_ = #/xy // expected-error@:5 {{unterminated regex literal}} -_ = #/(?/# // expected-error {{expected group specifier}} -_ = #/(?'/# // expected-error {{expected group name}} -_ = #/(?'abc/# // expected-error {{expected '''}} -_ = #/(?'abc /# // expected-error {{expected '''}} +_ = #/(?/# // expected-error@:7 {{expected group specifier}} +_ = #/(?'/# // expected-error@:10 {{expected group name}} +_ = #/(?'abc/# // expected-error@:13 {{expected '''}} +_ = #/(?'abc /# // expected-error@:13 {{expected '''}} do { _ = #/(?'a - // expected-error@-1 {{unterminated regex literal}} - // expected-error@-2 {{cannot parse regular expression: expected '''}} + // expected-error@-1:7 {{unterminated regex literal}} + // expected-error@-2:13 {{cannot parse regular expression: expected '''}} } _ = #/\(?'abc/# @@ -30,21 +30,21 @@ _ = #/\(?'abc/# do { _ = /\ / - // expected-error@-2 {{unterminated regex literal}} - // expected-error@-3 {{expected escape sequence}} -} // expected-error {{expected expression after operator}} + // expected-error@-2:7 {{unterminated regex literal}} + // expected-error@-3:9 {{expected escape sequence}} +} // expected-error@:1 {{expected expression after operator}} do { _ = #/\ /# - // expected-error@-2 {{unterminated regex literal}} - // expected-error@-3 {{expected escape sequence}} - // expected-error@-3 {{unterminated regex literal}} - // expected-warning@-4 {{regular expression literal is unused}} + // expected-error@-2:7 {{unterminated regex literal}} + // expected-error@-3:10 {{expected escape sequence}} + // expected-error@-3:3 {{unterminated regex literal}} + // expected-warning@-4:3 {{regular expression literal is unused}} } func foo(_ x: T, _ y: T) {} -foo(#/(?/#, #/abc/#) // expected-error {{expected group specifier}} -foo(#/(?C/#, #/abc/#) // expected-error {{expected ')'}} +foo(#/(?/#, #/abc/#) // expected-error@:7 {{expected group specifier}} +foo(#/(?C/#, #/abc/#) // expected-error@:10 {{expected ')'}} -foo(#/(?'/#, #/abc/#) // expected-error {{expected group name}} +foo(#/(?'/#, #/abc/#) // expected-error@:10 {{expected group name}} diff --git a/test/api-digester/stability-stdlib-abi-without-asserts.test b/test/api-digester/stability-stdlib-abi-without-asserts.test index 01bdc4fcd4b6f..1407fa3b6ba6b 100644 --- a/test/api-digester/stability-stdlib-abi-without-asserts.test +++ b/test/api-digester/stability-stdlib-abi-without-asserts.test @@ -89,5 +89,7 @@ Func UnsafeBufferPointer.withMemoryRebound(to:_:) has been removed Func UnsafeMutableBufferPointer.withMemoryRebound(to:_:) has been removed Func UnsafeMutablePointer.withMemoryRebound(to:capacity:_:) has been removed Func UnsafePointer.withMemoryRebound(to:capacity:_:) has been removed +Func UnsafeMutableRawBufferPointer.storeBytes(of:toByteOffset:as:) has been removed +Func UnsafeMutableRawPointer.storeBytes(of:toByteOffset:as:) has been removed // *** DO NOT DISABLE OR XFAIL THIS TEST. *** (See comment above.) diff --git a/test/attr/ApplicationMain/attr_main_struct_from_two_protocols_one_missing.swift b/test/attr/ApplicationMain/attr_main_struct_from_two_protocols_one_missing.swift index 561fac3ace780..483a7b90db9b2 100644 --- a/test/attr/ApplicationMain/attr_main_struct_from_two_protocols_one_missing.swift +++ b/test/attr/ApplicationMain/attr_main_struct_from_two_protocols_one_missing.swift @@ -8,14 +8,14 @@ protocol Runnable { protocol OtherThing { } -extension Runnable where Self : OtherThing { // expected-note{{where 'Self' = 'EntryPoint'}} +extension Runnable where Self : OtherThing { static func main() { let it = Self.init() it.run() } } -@main // expected-error{{referencing static method 'main()' on 'Runnable' requires that 'EntryPoint' conform to 'OtherThing'}} +@main //expected-error{{'EntryPoint' is annotated with @main and must provide a main static function}} struct EntryPoint : Runnable { func run() { } diff --git a/test/attr/require_explicit_availability.swift b/test/attr/require_explicit_availability.swift index d45778728d79d..4d8d362791e0b 100644 --- a/test/attr/require_explicit_availability.swift +++ b/test/attr/require_explicit_availability.swift @@ -7,6 +7,11 @@ public struct S { // expected-warning {{public declarations should have an avail public func method() { } } +@available(macOS, unavailable) +public struct UnavailableStruct { + public func okMethod() { } +} + public func foo() { bar() } // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}} @usableFromInline @@ -41,10 +46,25 @@ public func +(lhs: S, rhs: S) -> S { } // expected-warning {{public declarations public enum E { } // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}} +@available(macOS, unavailable) +public enum UnavailableEnum { + case caseOk +} + public class C { } // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}} +@available(macOS, unavailable) +public class UnavailableClass { + public func okMethod() { } +} + public protocol P { } // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}} +@available(macOS, unavailable) +public protocol UnavailableProto { + func requirementOk() +} + private protocol PrivateProto { } extension S { // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}} @@ -56,11 +76,19 @@ extension S { public func okWhenTheExtensionHasAttribute() { } } +@available(macOS, unavailable) +extension S { + public func okWhenTheExtensionIsUnavailable() { } +} + extension S { internal func dontWarnWithoutPublicMembers() { } private func dontWarnWithoutPublicMembers1() { } } +// An empty extension should be ok. +extension S { } + extension S : P { // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}} } @@ -96,6 +124,9 @@ public var publicVar = S() // expected-warning {{public declarations should have @available(macOS 10.10, *) public var publicVarOk = S() +@available(macOS, unavailable) +public var unavailablePublicVarOk = S() + public var (a, b) = (S(), S()) // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}} @available(macOS 10.10, *) @@ -112,6 +143,11 @@ public var implicitGetOk: S { return S() } +@available(macOS, unavailable) +public var unavailableImplicitGetOk: S { + return S() +} + public var computed: S { // expected-warning {{public declarations should have an availability attribute when building with -require-explicit-availability}} {{1-1=@available(macOS 10.10, *)\n}} get { return S() } set { } diff --git a/test/stdlib/StringAPICString.swift b/test/stdlib/StringAPICString.swift index be062847c6455..ede6086c8ed14 100644 --- a/test/stdlib/StringAPICString.swift +++ b/test/stdlib/StringAPICString.swift @@ -7,6 +7,12 @@ import StdlibUnittest +#if arch(wasm32) +let enableCrashTests = false +#else +let enableCrashTests = true +#endif + var CStringTests = TestSuite("CStringTests") func getNullUTF8() -> UnsafeMutablePointer? { @@ -225,5 +231,277 @@ CStringTests.test("Substring.withCString") { } } +CStringTests.test("String.cString.with.Array.UInt8.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + + do { + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + let cstr = UnsafePointer(u8p) + let buffer = UnsafeBufferPointer(start: cstr, count: getUTF8Length(u8p)+1) + let str = String(cString: Array(buffer)) + str.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: buffer.count) { + expectEqualCString(u8p, $0) + } + } + } + guard enableCrashTests else { return } + // no need to test every case; that is covered in other tests + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of String.init(cString:) must be null-terminated" + ) + _ = String(cString: [] as [UInt8]) + expectUnreachable() +} + +CStringTests.test("String.cString.with.Array.CChar.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + do { + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + let buffer = UnsafeBufferPointer(start: u8p, count: getUTF8Length(u8p)+1) + let str = buffer.withMemoryRebound(to: CChar.self) { + String(cString: Array($0)) + } + str.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: buffer.count) { + expectEqualCString(u8p, $0) + } + } + } + guard enableCrashTests else { return } + // no need to test every case; that is covered in other tests + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of String.init(cString:) must be null-terminated" + ) + _ = String(cString: [] as [CChar]) + expectUnreachable() +} + +CStringTests.test("String.cString.with.String.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + var str = String(cString: "ab") + str.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: getUTF8Length(u8p)+1) { + expectEqualCString(u8p, $0) + } + } + str = String(cString: "") + expectTrue(str.isEmpty) +} + +CStringTests.test("String.cString.with.inout.UInt8.conversion") { + guard #available(SwiftStdlib 5.7, *) else { return } + var c = UInt8.zero + var str = String(cString: &c) + expectTrue(str.isEmpty) + c = 100 + guard enableCrashTests else { return } + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of String.init(cString:) must be null-terminated" + ) + str = String(cString: &c) + expectUnreachable() +} + +CStringTests.test("String.cString.with.inout.CChar.conversion") { + guard #available(SwiftStdlib 5.7, *) else { return } + var c = CChar.zero + var str = String(cString: &c) + expectTrue(str.isEmpty) + c = 100 + guard enableCrashTests else { return } + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of String.init(cString:) must be null-terminated" + ) + str = String(cString: &c) + expectUnreachable() +} + +CStringTests.test("String.validatingUTF8.with.Array.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + do { + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + let buffer = UnsafeBufferPointer(start: u8p, count: getUTF8Length(u8p)+1) + let str = buffer.withMemoryRebound(to: CChar.self) { + String(validatingUTF8: Array($0)) + } + expectNotNil(str) + str?.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: buffer.count) { + expectEqualCString(u8p, $0) + } + } + } + guard enableCrashTests else { return } + // no need to test every case; that is covered in other tests + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of String.init(validatingUTF8:) must be null-terminated" + ) + _ = String(validatingUTF8: []) + expectUnreachable() +} + +CStringTests.test("String.validatingUTF8.with.String.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + var str = String(validatingUTF8: "ab") + expectNotNil(str) + str?.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: getUTF8Length(u8p)+1) { + expectEqualCString(u8p, $0) + } + } + str = String(validatingUTF8: "") + expectNotNil(str) + expectEqual(str?.isEmpty, true) +} + +CStringTests.test("String.validatingUTF8.with.inout.conversion") { + guard #available(SwiftStdlib 5.7, *) else { return } + var c = CChar.zero + var str = String(validatingUTF8: &c) + expectNotNil(str) + expectEqual(str?.isEmpty, true) + c = 100 + guard enableCrashTests else { return } + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of String.init(validatingUTF8:) must be null-terminated" + ) + str = String(validatingUTF8: &c) + expectUnreachable() +} + +CStringTests.test("String.decodeCString.with.Array.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + do { + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + let buffer = UnsafeBufferPointer(start: u8p, count: getUTF8Length(u8p)+1) + let result = buffer.withMemoryRebound(to: Unicode.UTF8.CodeUnit.self) { + String.decodeCString(Array($0), as: Unicode.UTF8.self) + } + expectNotNil(result) + expectEqual(result?.repairsMade, false) + result?.result.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: buffer.count) { + expectEqualCString(u8p, $0) + } + } + } + guard enableCrashTests else { return } + // no need to test every case; that is covered in other tests + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated" + ) + _ = String.decodeCString([], as: Unicode.UTF8.self) + expectUnreachable() +} + +CStringTests.test("String.decodeCString.with.String.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + var result = String.decodeCString( + "ab", as: Unicode.UTF8.self, repairingInvalidCodeUnits: true + ) + expectNotNil(result) + expectEqual(result?.repairsMade, false) + result?.result.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: getUTF8Length(u8p)+1) { + expectEqualCString(u8p, $0) + } + } + result = String.decodeCString("", as: Unicode.UTF8.self) + expectNotNil(result) + expectEqual(result?.repairsMade, false) + expectEqual(result?.result.isEmpty, true) +} + +CStringTests.test("String.decodeCString.with.inout.conversion") { + guard #available(SwiftStdlib 5.7, *) else { return } + var c = Unicode.UTF8.CodeUnit.zero + var result = String.decodeCString( + &c, as: Unicode.UTF8.self, repairingInvalidCodeUnits: true + ) + expectNotNil(result) + expectEqual(result?.result.isEmpty, true) + expectEqual(result?.repairsMade, false) + c = 100 + guard enableCrashTests else { return } + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated" + ) + result = String.decodeCString(&c, as: Unicode.UTF8.self) + expectUnreachable() +} + +CStringTests.test("String.init.decodingCString.with.Array.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + do { + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + let buffer = UnsafeBufferPointer(start: u8p, count: getUTF8Length(u8p)+1) + let str = buffer.withMemoryRebound(to: Unicode.UTF8.CodeUnit.self) { + String(decodingCString: Array($0), as: Unicode.UTF8.self) + } + str.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: buffer.count) { + expectEqualCString(u8p, $0) + } + } + } + guard enableCrashTests else { return } + // no need to test every case; that is covered in other tests + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated" + ) + _ = String(decodingCString: [], as: Unicode.UTF8.self) + expectUnreachable() +} + +CStringTests.test("String.init.decodingCString.with.String.input") { + guard #available(SwiftStdlib 5.7, *) else { return } + let (u8p, dealloc) = getASCIIUTF8() + defer { dealloc() } + var str = String(decodingCString: "ab", as: Unicode.UTF8.self) + str.withCString { + $0.withMemoryRebound(to: UInt8.self, capacity: getUTF8Length(u8p)+1) { + expectEqualCString(u8p, $0) + } + } + str = String(decodingCString: "", as: Unicode.UTF8.self) + expectTrue(str.isEmpty) +} + +CStringTests.test("String.init.decodingCString.with.inout.conversion") { + guard #available(SwiftStdlib 5.7, *) else { return } + var c = Unicode.UTF8.CodeUnit.zero + var str = String(decodingCString: &c, as: Unicode.UTF8.self) + expectEqual(str.isEmpty, true) + c = 100 + guard enableCrashTests else { return } + expectCrashLater( + // Workaround for https://bugs.swift.org/browse/SR-16103 (rdar://91365967) + // withMessage: "input of String.init(decodingCString:as:) must be null-terminated" + ) + str = String(decodingCString: &c, as: Unicode.UTF8.self) + expectUnreachable() +} + runAllTests() diff --git a/test/stdlib/StringAPICStringDiagnostics.swift b/test/stdlib/StringAPICStringDiagnostics.swift new file mode 100644 index 0000000000000..434fbab1c4685 --- /dev/null +++ b/test/stdlib/StringAPICStringDiagnostics.swift @@ -0,0 +1,33 @@ +// RUN: %target-typecheck-verify-swift -verify-ignore-unknown + +import StdlibUnittest + +func checkStringOverloadCompilationDiagnostics() { + + _ = String(cString: "string") // expected-warning {{'init(cString:)' is deprecated: Use a copy of the String argument}} + + _ = String(validatingUTF8: "string") // expected-warning {{init(validatingUTF8:)' is deprecated: Use a copy of the String argument}} + + _ = String.decodeCString("string", as: Unicode.UTF8.self) // expected-warning {{'decodeCString(_:as:repairingInvalidCodeUnits:)' is deprecated: Use a copy of the String argument}} + + _ = String(decodingCString: "string", as: Unicode.UTF8.self) // expected-warning {{'init(decodingCString:as:)' is deprecated: Use a copy of the String argument}} +} + +func checkInoutConversionOverloadCompilationDiagnostics() { + + var i = UInt8.zero + + _ = String(cString: &i) // expected-warning {{'init(cString:)' is deprecated: Use String(_ scalar: Unicode.Scalar)}} + + var c = CChar.zero + + _ = String(cString: &c) // expected-warning {{'init(cString:)' is deprecated: Use String(_ scalar: Unicode.Scalar)}} + + _ = String(validatingUTF8: &c) // expected-warning {{init(validatingUTF8:)' is deprecated: Use String(_ scalar: Unicode.Scalar)}} + + var u = Unicode.UTF8.CodeUnit.zero + + _ = String.decodeCString(&u, as: Unicode.UTF8.self) // expected-warning {{'decodeCString(_:as:repairingInvalidCodeUnits:)' is deprecated: Use String(_ scalar: Unicode.Scalar)}} + + _ = String(decodingCString: &u, as: Unicode.UTF8.self) // expected-warning {{'init(decodingCString:as:)' is deprecated: Use String(_ scalar: Unicode.Scalar)}} +} diff --git a/test/stdlib/UnsafeRawBufferPointer.swift b/test/stdlib/UnsafeRawBufferPointer.swift index 47bb466341c61..736634e255222 100644 --- a/test/stdlib/UnsafeRawBufferPointer.swift +++ b/test/stdlib/UnsafeRawBufferPointer.swift @@ -318,7 +318,7 @@ UnsafeRawBufferPointerTestSuite.test("subscript.set.underflow") { let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 2, alignment: MemoryLayout.alignment) defer { buffer.deallocate() } - var bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[1..<2]) + let bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[1..<2]) if _isDebugAssertConfiguration() { expectCrashLater() @@ -331,7 +331,7 @@ UnsafeRawBufferPointerTestSuite.test("subscript.set.overflow") { let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 2, alignment: MemoryLayout.alignment) defer { buffer.deallocate() } - var bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[0..<1]) + let bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[0..<1]) if _isDebugAssertConfiguration() { expectCrashLater() @@ -367,10 +367,10 @@ UnsafeRawBufferPointerTestSuite.test("subscript.range.get.overflow") { } UnsafeRawBufferPointerTestSuite.test("subscript.range.set.underflow") { - var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) + let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) defer { buffer.deallocate() } - var bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[1..<3]) + let bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[1..<3]) if _isDebugAssertConfiguration() { expectCrashLater() @@ -380,10 +380,10 @@ UnsafeRawBufferPointerTestSuite.test("subscript.range.set.underflow") { } UnsafeRawBufferPointerTestSuite.test("subscript.range.set.overflow") { - var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) + let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) defer { buffer.deallocate() } - var bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[0..<2]) + let bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[0..<2]) if _isDebugAssertConfiguration() { expectCrashLater() @@ -394,7 +394,7 @@ UnsafeRawBufferPointerTestSuite.test("subscript.range.set.overflow") { } UnsafeRawBufferPointerTestSuite.test("subscript.range.narrow") { - var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) + let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) defer { buffer.deallocate() } if _isDebugAssertConfiguration() { @@ -405,7 +405,7 @@ UnsafeRawBufferPointerTestSuite.test("subscript.range.narrow") { } UnsafeRawBufferPointerTestSuite.test("subscript.range.wide") { - var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) + let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) defer { buffer.deallocate() } if _isDebugAssertConfiguration() { @@ -431,7 +431,7 @@ UnsafeRawBufferPointerTestSuite.test("_copyContents") { #if !os(WASI) // Trap tests aren't available on WASI. UnsafeRawBufferPointerTestSuite.test("copyMemory.overflow") { - var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) + let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) defer { buffer.deallocate() } let bytes = buffer[0..<2] @@ -461,7 +461,7 @@ UnsafeRawBufferPointerTestSuite.test("copyBytes.withoutContiguouseStorage") { #if !os(WASI) // Trap tests aren't available on WASI. UnsafeRawBufferPointerTestSuite.test("copyBytes.sequence.overflow") { - var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) + let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout.alignment) defer { buffer.deallocate() } let bytes = buffer[0..<2] @@ -498,6 +498,48 @@ UnsafeRawBufferPointerTestSuite.test("load.after") } } +UnsafeRawBufferPointerTestSuite.test("load.aligned") { + var data: [UInt8] = [0, 0, 0, 0, .max, .max, .max, .max] + data.withUnsafeBytes { + let x = $0.load(fromByteOffset: 4, as: UInt32.self) + expectEqual(x, .max) + } + data.withUnsafeMutableBytes { + let x = $0.load(fromByteOffset: 0, as: UInt32.self) + expectEqual(x, 0) + } +} + +UnsafeRawBufferPointerTestSuite.test("load.invalid") +.skip(.custom({ !_isDebugAssertConfiguration() }, // require debugAssert + reason: "This tests a debug precondition..")) +.code { + let data: [UInt8] = [0, 0, 0, .max, .max, .max, .max, 0] + let i = data.firstIndex(of: .max)! + expectCrashLater() + _ = data.withUnsafeBytes { + $0.load(fromByteOffset: i, as: UInt32.self) + } +} + +UnsafeRawBufferPointerTestSuite.test("load.unaligned") +.skip(.custom({ // require SwiftStdlib 5.7 + if #available(SwiftStdlib 5.7, *) { return false } else { return true } +}, reason: "Requires stdlib from Swift 5.7")) +.code { + guard #available(SwiftStdlib 5.7, *) else { return } + var data: [UInt8] = [0, 0, 0, .max, .max, .max, .max, 0] + let i = data.firstIndex(of: .max)! + data.withUnsafeBytes { + let x = $0.loadUnaligned(fromByteOffset: i, as: UInt32.self) + expectEqual(x, .max) + } + data.withUnsafeMutableBytes { + let x = $0.loadUnaligned(fromByteOffset: i-1, as: UInt32.self) + expectEqual(UInt32(littleEndian: x), 0xffffff00) + } +} + UnsafeRawBufferPointerTestSuite.test("store.before") .skip(.custom( { !_isDebugAssertConfiguration() }, @@ -521,6 +563,60 @@ UnsafeRawBufferPointerTestSuite.test("store.after") } } +UnsafeRawBufferPointerTestSuite.test("store.unaligned") +.skip(.custom({ + if #available(SwiftStdlib 5.7, *) { return false } + return true +}, reason: "Requires Swift 5.7's stdlib")) +.code { + let count = MemoryLayout.stride * 2 + let p1 = UnsafeMutableRawBufferPointer.allocate( + byteCount: count, + alignment: MemoryLayout.alignment + ) + defer { p1.deallocate() } + p1.copyBytes(from: repeatElement(UInt8.zero, count: count)) + let value = UInt.max + let offset = 3 + p1.storeBytes(of: value, toByteOffset: offset, as: UInt.self) + expectEqual(p1.load(fromByteOffset: offset-1, as: UInt8.self), + 0) + expectEqual(p1.load(fromByteOffset: offset, as: UInt8.self), + .max) + let storedLength = MemoryLayout.size + expectEqual(p1.load(fromByteOffset: offset-1+storedLength, as: UInt8.self), + .max) + expectEqual(p1.load(fromByteOffset: offset+storedLength, as: UInt8.self), + 0) +} + +UnsafeRawBufferPointerTestSuite.test("store.invalid") +.skip(.custom({ !_isDebugAssertConfiguration() }, // require debugAssert + reason: "This tests a debug precondition..")) +.skip(.custom({ // require SwiftStdlib 5.7 + if #available(SwiftStdlib 5.7, *) { return false } else { return true } +}, reason: "Requires stdlib from Swift 5.7")) +.code { + let t = "Text that is longer than fits in a small String." + let p1 = UnsafeMutableRawPointer.allocate( + byteCount: MemoryLayout.size, + alignment: MemoryLayout.alignment + ) + defer { p1.deallocate() } + expectCrashLater() + p1.storeBytes(of: t, as: String.self) + expectUnreachable() +} + +UnsafeRawBufferPointerTestSuite.test("store.valid") { + let value32 = UInt32.max + var value64 = Int64.zero + withUnsafeMutableBytes(of: &value64) { + $0.storeBytes(of: value32, toByteOffset: MemoryLayout.stride, as: UInt32.self) + } + expectEqual(value64, 0xffffffff << 32) +} + UnsafeRawBufferPointerTestSuite.test("copy.bytes.overflow") .skip(.custom( { !_isDebugAssertConfiguration() }, diff --git a/test/stdlib/UnsafeRawPointer.swift b/test/stdlib/UnsafeRawPointer.swift index c2df7bba40821..5223bc373b369 100644 --- a/test/stdlib/UnsafeRawPointer.swift +++ b/test/stdlib/UnsafeRawPointer.swift @@ -94,6 +94,103 @@ UnsafeMutableRawPointerExtraTestSuite.test("load/store") { expectEqual(6, p1.load(fromByteOffset: 2 * MemoryLayout.stride, as: Int.self)) } +UnsafeMutableRawPointerExtraTestSuite.test("load.unaligned") +.skip(.custom({ + if #available(SwiftStdlib 5.7, *) { return false } + return true +}, reason: "Requires Swift 5.7's stdlib")) +.code { + guard #available(SwiftStdlib 5.7, *) else { return } + var data: [UInt8] = [0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0] + var result: UInt32 + result = data.withUnsafeBytes { + $0.loadUnaligned(fromByteOffset: 3, as: UInt32.self) + } + expectEqual(result, 0xffff_ffff) + result = data.withUnsafeMutableBytes { + $0[0] = 0 + return $0.loadUnaligned(fromByteOffset: 1, as: UInt32.self) + } + expectEqual(result, 0xffff_0000) +} + +#if !os(WASI) +UnsafeMutableRawPointerExtraTestSuite.test("load.invalid") +.skip(.custom({ !_isDebugAssertConfiguration() }, + reason: "This tests a debug precondition..")) +.code { + let data: [UInt8] = [0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0] + expectCrashLater() + _ = data.withUnsafeBytes { + $0.load(fromByteOffset: 3, as: UInt32.self) + } + expectUnreachable() +} + +UnsafeMutableRawPointerExtraTestSuite.test("load.invalid.mutable") +.skip(.custom({ !_isDebugAssertConfiguration() }, + reason: "This tests a debug precondition..")) +.code { + var data: [UInt8] = [0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0] + expectCrashLater() + _ = data.withUnsafeMutableBytes { + $0.load(fromByteOffset: 1, as: UInt32.self) + } + expectUnreachable() +} +#endif + +UnsafeMutableRawPointerExtraTestSuite.test("store.unaligned") +.skip(.custom({ + if #available(SwiftStdlib 5.7, *) { return false } + return true +}, reason: "Requires Swift 5.7's stdlib")) +.code { + let count = MemoryLayout.stride * 2 + let p1 = UnsafeMutableRawPointer.allocate( + byteCount: count, + alignment: MemoryLayout.alignment + ) + defer { p1.deallocate() } + Array(repeating: UInt8.zero, count: count).withUnsafeBufferPointer { + p1.copyBytes(from: UnsafeRawPointer($0.baseAddress!), count: $0.count) + } + let value = UInt.max + let offset = 3 + p1.storeBytes(of: value, toByteOffset: offset, as: UInt.self) + expectEqual(p1.load(fromByteOffset: offset-1, as: UInt8.self), + 0) + expectEqual(p1.load(fromByteOffset: offset, as: UInt8.self), + .max) + let storedLength = MemoryLayout.size + expectEqual(p1.load(fromByteOffset: offset-1+storedLength, as: UInt8.self), + .max) + expectEqual(p1.load(fromByteOffset: offset+storedLength, as: UInt8.self), + 0) +} + +#if !os(WASI) +UnsafeMutableRawPointerExtraTestSuite.test("store.invalid") +.skip(.custom({ !_isDebugAssertConfiguration() }, + reason: "This tests a debug precondition..")) +.skip(.custom({ + if #available(SwiftStdlib 5.7, *) { return false } + return true +}, reason: "Requires Swift 5.7's stdlib")) +.code { + Missile.missilesLaunched = 0 + let m = Missile(0) + let p1 = UnsafeMutableRawPointer.allocate( + byteCount: MemoryLayout.size, + alignment: MemoryLayout.alignment + ) + defer { p1.deallocate() } + expectCrashLater() + p1.storeBytes(of: m, as: Missile.self) + expectUnreachable() +} +#endif + UnsafeMutableRawPointerExtraTestSuite.test("copyMemory") { let sizeInBytes = 4 * MemoryLayout.stride let rawPtr = UnsafeMutableRawPointer.allocate( diff --git a/tools/SourceKit/lib/Support/CMakeLists.txt b/tools/SourceKit/lib/Support/CMakeLists.txt index 3b18cc18e98c9..c4e2cbcd31e03 100644 --- a/tools/SourceKit/lib/Support/CMakeLists.txt +++ b/tools/SourceKit/lib/Support/CMakeLists.txt @@ -7,7 +7,6 @@ add_sourcekit_library(SourceKitSupport UIDRegistry.cpp) target_link_libraries(SourceKitSupport PRIVATE swiftBasic - swiftSyntax clangBasic clangRewrite) if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin) @@ -15,4 +14,3 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin) dispatch BlocksRuntime) endif() - diff --git a/tools/SourceKit/lib/Support/Tracing.cpp b/tools/SourceKit/lib/Support/Tracing.cpp index 00df43a90044c..96eaa99de82a5 100644 --- a/tools/SourceKit/lib/Support/Tracing.cpp +++ b/tools/SourceKit/lib/Support/Tracing.cpp @@ -12,8 +12,6 @@ #include "SourceKit/Support/Tracing.h" -#include "swift/Frontend/Frontend.h" - #include "llvm/Support/Mutex.h" #include "llvm/Support/YAMLTraits.h" diff --git a/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift b/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift index da6e11712f1ee..1b85cdf490590 100644 --- a/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift +++ b/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift @@ -11,12 +11,11 @@ struct rdar19612086 { let x = 1.0 var description : String { - return "\(i)" + Stringly(format: "%.2f", x) + + return "\(i)" + Stringly(format: "%.2f", x) + // expected-error {{reasonable time}} "\(i+1)" + Stringly(format: "%.2f", x) + "\(i+2)" + Stringly(format: "%.2f", x) + "\(i+3)" + Stringly(format: "%.2f", x) + "\(i+4)" + Stringly(format: "%.2f", x) + "\(i+5)" + Stringly(format: "%.2f", x) - // expected-error@-1 {{reasonable time}} } } diff --git a/validation-test/Sema/type_checker_perf/slow/rdar22079400.swift b/validation-test/Sema/type_checker_perf/slow/rdar22079400.swift index 8f22a4ab7a37b..ea8334f5b28fa 100644 --- a/validation-test/Sema/type_checker_perf/slow/rdar22079400.swift +++ b/validation-test/Sema/type_checker_perf/slow/rdar22079400.swift @@ -1,9 +1,8 @@ // RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1 // REQUIRES: tools-release,no_asan -let _ = (0...1).lazy.flatMap { +let _ = (0...1).lazy.flatMap { // expected-error {{reasonable time}} a in (1...2).lazy.map { b in (a, b) } }.filter { - // expected-error@-1 {{reasonable time}} 1 < $0 && $0 < $1 && $0 + $1 < 3 } diff --git a/validation-test/Sema/type_checker_perf/slow/rdar91310777.swift b/validation-test/Sema/type_checker_perf/slow/rdar91310777.swift new file mode 100644 index 0000000000000..eb9dcbee848c8 --- /dev/null +++ b/validation-test/Sema/type_checker_perf/slow/rdar91310777.swift @@ -0,0 +1,16 @@ +// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1 +// REQUIRES: tools-release,no_asan + +func compute(_ cont: () -> Void) {} + +func test() { + compute { + let x = 42 + compute { + print(x) + let v: UInt64 = UInt64((24 / UInt32(1)) + UInt32(0) - UInt32(0) - 24 / 42 - 42) + // expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions}} + print(v) + } + } +}