From a8fc95bf9cb6809b49686842eb17100449b224be Mon Sep 17 00:00:00 2001 From: Kobe Date: Wed, 15 Nov 2023 19:54:36 +0900 Subject: [PATCH 01/35] [stdlib]Catch the reasonable mistake 'UnsafeRawMutableBufferPointer' issue: [SR-6360] tag: #48910 --- test/stdlib/UnsafePointerDiagnostics.swift | 27 ++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/test/stdlib/UnsafePointerDiagnostics.swift b/test/stdlib/UnsafePointerDiagnostics.swift index 068642bdc95fa..ef7902b81524b 100644 --- a/test/stdlib/UnsafePointerDiagnostics.swift +++ b/test/stdlib/UnsafePointerDiagnostics.swift @@ -2,6 +2,9 @@ // Test availability attributes on UnsafePointer initializers. // Assume the original source contains no UnsafeRawPointer types. +@available(*, unavailable, renamed: "UnsafeMutableRawBufferPointer") +typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer + func unsafePointerConversionAvailability( mrp: UnsafeMutableRawPointer, rp: UnsafeRawPointer, @@ -99,7 +102,7 @@ func unsafePointerConversionAvailability( func unsafeRawBufferPointerConversions( mrp: UnsafeMutableRawPointer, rp: UnsafeRawPointer, - mrbp: UnsafeMutableRawBufferPointer, + mrbp: UnsafeRawMutableBufferPointer, rbp: UnsafeRawBufferPointer, mbpi: UnsafeMutableBufferPointer, bpi: UnsafeBufferPointer) { @@ -107,21 +110,21 @@ func unsafeRawBufferPointerConversions( let omrp: UnsafeMutableRawPointer? = mrp let orp: UnsafeRawPointer? = rp - _ = UnsafeMutableRawBufferPointer(start: mrp, count: 1) + _ = UnsafeRawMutableBufferPointer(start: mrp, count: 1) _ = UnsafeRawBufferPointer(start: mrp, count: 1) - _ = UnsafeMutableRawBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} + _ = UnsafeRawMutableBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} _ = UnsafeRawBufferPointer(start: rp, count: 1) - _ = UnsafeMutableRawBufferPointer(mrbp) + _ = UnsafeRawMutableBufferPointer(mrbp) _ = UnsafeRawBufferPointer(mrbp) - _ = UnsafeMutableRawBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} + _ = UnsafeRawMutableBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} _ = UnsafeRawBufferPointer(rbp) - _ = UnsafeMutableRawBufferPointer(mbpi) + _ = UnsafeRawMutableBufferPointer(mbpi) _ = UnsafeRawBufferPointer(mbpi) - _ = UnsafeMutableRawBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawBufferPointer'}} + _ = UnsafeRawMutableBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeRawMutableBufferPointer'}} _ = UnsafeRawBufferPointer(bpi) - _ = UnsafeMutableRawBufferPointer(start: omrp, count: 1) + _ = UnsafeRawMutableBufferPointer(start: omrp, count: 1) _ = UnsafeRawBufferPointer(start: omrp, count: 1) - _ = UnsafeMutableRawBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} + _ = UnsafeRawMutableBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} _ = UnsafeRawBufferPointer(start: orp, count: 1) } @@ -327,11 +330,11 @@ func unsafePointerInitEphemeralConversions() { // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - _ = UnsafeMutableRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} + _ = UnsafeRawMutableBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeRawMutableBufferPointer' results in a dangling buffer pointer}} // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - _ = UnsafeMutableRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} + _ = UnsafeRawMutableBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeRawMutableBufferPointer' results in a dangling buffer pointer}} // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} @@ -363,7 +366,7 @@ func unsafePointerInitNonEphemeralConversions() { _ = UnsafeBufferPointer(start: &global, count: 0) _ = UnsafeMutableBufferPointer(start: &global, count: 0) _ = UnsafeRawBufferPointer(start: &global, count: 0) - _ = UnsafeMutableRawBufferPointer(start: &global, count: 0) + _ = UnsafeRawMutableBufferPointer(start: &global, count: 0) // FIXME: This is currently ambiguous. _ = OpaquePointer(&global) // expected-error {{ambiguous use of 'init(_:)'}} From 86a501094cff8a638d3b2d881084fe5d240aef78 Mon Sep 17 00:00:00 2001 From: Kobe Date: Thu, 16 Nov 2023 07:36:07 +0900 Subject: [PATCH 02/35] [stdlidt]Restore Original File Code. I restored the code to its original state in 'test/stdlib/UnsafePointerDiagnostics.swift --- test/stdlib/UnsafePointerDiagnostics.swift | 26 ++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/test/stdlib/UnsafePointerDiagnostics.swift b/test/stdlib/UnsafePointerDiagnostics.swift index ef7902b81524b..a8d2e1e912617 100644 --- a/test/stdlib/UnsafePointerDiagnostics.swift +++ b/test/stdlib/UnsafePointerDiagnostics.swift @@ -2,8 +2,6 @@ // Test availability attributes on UnsafePointer initializers. // Assume the original source contains no UnsafeRawPointer types. -@available(*, unavailable, renamed: "UnsafeMutableRawBufferPointer") -typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer func unsafePointerConversionAvailability( mrp: UnsafeMutableRawPointer, @@ -102,7 +100,7 @@ func unsafePointerConversionAvailability( func unsafeRawBufferPointerConversions( mrp: UnsafeMutableRawPointer, rp: UnsafeRawPointer, - mrbp: UnsafeRawMutableBufferPointer, + mrbp: UnsafeMutableRawBufferPointer, rbp: UnsafeRawBufferPointer, mbpi: UnsafeMutableBufferPointer, bpi: UnsafeBufferPointer) { @@ -110,21 +108,21 @@ func unsafeRawBufferPointerConversions( let omrp: UnsafeMutableRawPointer? = mrp let orp: UnsafeRawPointer? = rp - _ = UnsafeRawMutableBufferPointer(start: mrp, count: 1) + _ = UnsafeMutableRawBufferPointer(start: mrp, count: 1) _ = UnsafeRawBufferPointer(start: mrp, count: 1) - _ = UnsafeRawMutableBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} + _ = UnsafeMutableRawBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} _ = UnsafeRawBufferPointer(start: rp, count: 1) - _ = UnsafeRawMutableBufferPointer(mrbp) + _ = UnsafeMutableRawBufferPointer(mrbp) _ = UnsafeRawBufferPointer(mrbp) - _ = UnsafeRawMutableBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} + _ = UnsafeMutableRawBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} _ = UnsafeRawBufferPointer(rbp) - _ = UnsafeRawMutableBufferPointer(mbpi) + _ = UnsafeMutableRawBufferPointer(mbpi) _ = UnsafeRawBufferPointer(mbpi) - _ = UnsafeRawMutableBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeRawMutableBufferPointer'}} + _ = UnsafeMutableRawBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawBufferPointer'}} _ = UnsafeRawBufferPointer(bpi) - _ = UnsafeRawMutableBufferPointer(start: omrp, count: 1) + _ = UnsafeMutableRawBufferPointer(start: omrp, count: 1) _ = UnsafeRawBufferPointer(start: omrp, count: 1) - _ = UnsafeRawMutableBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} + _ = UnsafeMutableRawBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} _ = UnsafeRawBufferPointer(start: orp, count: 1) } @@ -330,11 +328,11 @@ func unsafePointerInitEphemeralConversions() { // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - _ = UnsafeRawMutableBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeRawMutableBufferPointer' results in a dangling buffer pointer}} + _ = UnsafeMutableRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - _ = UnsafeRawMutableBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeRawMutableBufferPointer' results in a dangling buffer pointer}} + _ = UnsafeMutableRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} @@ -366,7 +364,7 @@ func unsafePointerInitNonEphemeralConversions() { _ = UnsafeBufferPointer(start: &global, count: 0) _ = UnsafeMutableBufferPointer(start: &global, count: 0) _ = UnsafeRawBufferPointer(start: &global, count: 0) - _ = UnsafeRawMutableBufferPointer(start: &global, count: 0) + _ = UnsafeMutableRawBufferPointer(start: &global, count: 0) // FIXME: This is currently ambiguous. _ = OpaquePointer(&global) // expected-error {{ambiguous use of 'init(_:)'}} From 2ca5c32bd59fa3ac731ce9f01b426460d10580be Mon Sep 17 00:00:00 2001 From: Kobe Date: Thu, 16 Nov 2023 17:54:38 +0900 Subject: [PATCH 03/35] [stdlib]Catch the reasonable mistake 'UnsafeRawMutableBufferPointer' Issue: [SR-6360] Tag: #48910 We could make things easier on people by adding an unavailable typealias with a renamed field. Resolve: #48910, fix: #69881 cc: @glessard --- .../core/UnsafeRawBufferPointer.swift.gyb | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb index 98231bdebbd75..0b4bc6387e900 100644 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb @@ -13,8 +13,12 @@ %import gyb % for mutable in (True, False): -% Self = 'UnsafeMutableRawBufferPointer' if mutable else 'UnsafeRawBufferPointer' % Mutable = 'Mutable' if mutable else '' +% Self = 'UnsafeMutableRawBufferPointer' if mutable else 'UnsafeRawBufferPointer' +% if mutable: +@available(*, unavailable, renamed: "UnsafeMutableRawBufferPointer") +typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer +%end /// A ${Mutable.lower()} nonowning collection interface to the bytes in a /// region of memory. @@ -95,7 +99,7 @@ /// destBytes[0.. /// Returns an iterator over the bytes of this sequence. @@ -202,7 +206,7 @@ extension Unsafe${Mutable}RawBufferPointer: Sequence { } } -extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection { +extension UnsafeRaw${Mutable}BufferPointer: ${Mutable}Collection { // TODO: Specialize `index` and `formIndex` and // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. public typealias Element = UInt8 @@ -218,7 +222,7 @@ extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection { /// The "past the end" position---that is, the position one greater than the /// last valid subscript argument. /// - /// The `endIndex` property of an `Unsafe${Mutable}RawBufferPointer` + /// The `endIndex` property of an `UnsafeRaw${Mutable}BufferPointer` /// instance is always identical to `count`. @inlinable public var endIndex: Index { @@ -318,9 +322,9 @@ extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection { } } -extension Unsafe${Mutable}RawBufferPointer: RandomAccessCollection { } +extension UnsafeRaw${Mutable}BufferPointer: RandomAccessCollection { } -extension Unsafe${Mutable}RawBufferPointer { +extension UnsafeRaw${Mutable}BufferPointer { % if mutable: /// Allocates uninitialized memory with the specified size and alignment. /// @@ -1144,7 +1148,7 @@ extension Unsafe${Mutable}RawBufferPointer { } @_unavailableInEmbedded -extension Unsafe${Mutable}RawBufferPointer: CustomDebugStringConvertible { +extension UnsafeRaw${Mutable}BufferPointer: CustomDebugStringConvertible { /// A textual representation of the buffer, suitable for debugging. public var debugDescription: String { return "${Self}" @@ -1153,8 +1157,8 @@ extension Unsafe${Mutable}RawBufferPointer: CustomDebugStringConvertible { } extension ${Self} { - @available(*, unavailable, - message: "use 'Unsafe${Mutable}RawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") + @available(*, unavailable, + message: "use 'UnsafeRaw${Mutable}BufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") public subscript(bounds: Range) -> ${Self} { get { return ${Self}(start: nil, count: 0) } % if mutable: From 243984db7095f5c0ca27d336688e8aebbf03a4b1 Mon Sep 17 00:00:00 2001 From: Kobe Date: Fri, 17 Nov 2023 08:27:24 +0900 Subject: [PATCH 04/35] [stdlib]fix typealias for written code to guide developers. Issue:[SR-6360] Tag: #48910 Modified: stdlib/public/core/UnsafeRawBufferPointer.swift.gyb Resolve: #48910, fix: #69909 --- .../core/UnsafeRawBufferPointer.swift.gyb | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb index 0b4bc6387e900..6f28588ad0589 100644 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb @@ -11,14 +11,11 @@ //===----------------------------------------------------------------------===// %import gyb - -% for mutable in (True, False): -% Mutable = 'Mutable' if mutable else '' -% Self = 'UnsafeMutableRawBufferPointer' if mutable else 'UnsafeRawBufferPointer' -% if mutable: @available(*, unavailable, renamed: "UnsafeMutableRawBufferPointer") typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer -%end +% for mutable in (True, False): +% Self = 'UnsafeMutableRawBufferPointer' if mutable else 'UnsafeRawBufferPointer' +% Mutable = 'Mutable' if mutable else '' /// A ${Mutable.lower()} nonowning collection interface to the bytes in a /// region of memory. @@ -99,7 +96,7 @@ typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer /// destBytes[0.. /// Returns an iterator over the bytes of this sequence. @@ -206,7 +203,7 @@ extension UnsafeRaw${Mutable}BufferPointer: Sequence { } } -extension UnsafeRaw${Mutable}BufferPointer: ${Mutable}Collection { +extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection { // TODO: Specialize `index` and `formIndex` and // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. public typealias Element = UInt8 @@ -222,7 +219,7 @@ extension UnsafeRaw${Mutable}BufferPointer: ${Mutable}Collection { /// The "past the end" position---that is, the position one greater than the /// last valid subscript argument. /// - /// The `endIndex` property of an `UnsafeRaw${Mutable}BufferPointer` + /// The `endIndex` property of an `Unsafe${Mutable}RawBufferPointer` /// instance is always identical to `count`. @inlinable public var endIndex: Index { @@ -322,9 +319,9 @@ extension UnsafeRaw${Mutable}BufferPointer: ${Mutable}Collection { } } -extension UnsafeRaw${Mutable}BufferPointer: RandomAccessCollection { } +extension Unsafe${Mutable}RawBufferPointer: RandomAccessCollection { } -extension UnsafeRaw${Mutable}BufferPointer { +extension Unsafe${Mutable}RawBufferPointer { % if mutable: /// Allocates uninitialized memory with the specified size and alignment. /// @@ -519,7 +516,7 @@ extension UnsafeRaw${Mutable}BufferPointer { /// must be properly aligned for accessing `T`, and `source.count` must be a /// multiple of `MemoryLayout.stride`. /// - /// The memory referenced by `source` may overlap with the memory referenced + /// The memory referenced by `source` may overlap with the memory referenced /// by this buffer. /// /// After calling `copyMemory(from:)`, the first `source.count` bytes of @@ -713,7 +710,7 @@ extension UnsafeRaw${Mutable}BufferPointer { /// initialized to a trivial type, and must be properly aligned for /// accessing `T`. /// - /// After calling this method on a raw buffer with non-nil `baseAddress` `b`, + /// After calling this method on a raw buffer with non-nil `baseAddress` `b`, /// the region starting at `b` and continuing up to /// `b + self.count - self.count % MemoryLayout.stride` is bound /// to type `T` and is initialized. If `T` is a nontrivial type, you must @@ -724,8 +721,8 @@ extension UnsafeRaw${Mutable}BufferPointer { /// - Parameters: /// - type: The type to bind this buffer’s memory to. /// - repeatedValue: The instance to copy into memory. - /// - Returns: A typed buffer of the memory referenced by this raw buffer. - /// The typed buffer contains `self.count / MemoryLayout.stride` + /// - Returns: A typed buffer of the memory referenced by this raw buffer. + /// The typed buffer contains `self.count / MemoryLayout.stride` /// instances of `T`. @inlinable @discardableResult @@ -779,10 +776,10 @@ extension UnsafeRaw${Mutable}BufferPointer { "insufficient space to accommodate source.underestimatedCount elements") guard let base = baseAddress else { // this can be a precondition since only an invalid argument should be costly - _precondition(source.underestimatedCount == 0, + _precondition(source.underestimatedCount == 0, "no memory available to initialize from source") return (it, UnsafeMutableBufferPointer(start: nil, count: 0)) - } + } _debugPrecondition( Int(bitPattern: base) % MemoryLayout.stride == 0, @@ -790,9 +787,9 @@ extension UnsafeRaw${Mutable}BufferPointer { ) _internalInvariant(_end != nil) - for p in stride(from: base, + for p in stride(from: base, // only advance to as far as the last element that will fit - to: _end._unsafelyUnwrappedUnchecked - elementStride + 1, + to: _end._unsafelyUnwrappedUnchecked - elementStride + 1, by: elementStride ) { // underflow is permitted -- e.g. a sequence into @@ -803,7 +800,7 @@ extension UnsafeRaw${Mutable}BufferPointer { } return (it, UnsafeMutableBufferPointer( - start: base.assumingMemoryBound(to: S.Element.self), + start: base.assumingMemoryBound(to: S.Element.self), count: idx / elementStride)) } @@ -987,7 +984,7 @@ extension UnsafeRaw${Mutable}BufferPointer { % end # mutable - /// Binds this buffer’s memory to the specified type and returns a typed buffer + /// Binds this buffer’s memory to the specified type and returns a typed buffer /// of the bound memory. /// /// Use the `bindMemory(to:)` method to bind the memory referenced @@ -1148,7 +1145,7 @@ extension UnsafeRaw${Mutable}BufferPointer { } @_unavailableInEmbedded -extension UnsafeRaw${Mutable}BufferPointer: CustomDebugStringConvertible { +extension Unsafe${Mutable}RawBufferPointer: CustomDebugStringConvertible { /// A textual representation of the buffer, suitable for debugging. public var debugDescription: String { return "${Self}" @@ -1158,7 +1155,7 @@ extension UnsafeRaw${Mutable}BufferPointer: CustomDebugStringConvertible { extension ${Self} { @available(*, unavailable, - message: "use 'UnsafeRaw${Mutable}BufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") + message: "use 'Unsafe${Mutable}RawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") public subscript(bounds: Range) -> ${Self} { get { return ${Self}(start: nil, count: 0) } % if mutable: @@ -1167,7 +1164,7 @@ extension ${Self} { } % if mutable: - @available(*, unavailable, + @available(*, unavailable, message: "use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") public subscript(bounds: Range) -> UnsafeRawBufferPointer { get { return UnsafeRawBufferPointer(start: nil, count: 0) } From d1212f507d9d72b79add37730bd5918790d9260f Mon Sep 17 00:00:00 2001 From: Kobe Date: Fri, 17 Nov 2023 08:37:15 +0900 Subject: [PATCH 05/35] [stdlib]Catch the reasonable mistake 'UnsafeRawMutableBufferPointer' Issue: [SR-6360] Tag: #48910 Modified: stdlib/public/core/UnsafeRawBufferPointer.swift Resolve: #48910, fix: #69909 --- .../public/core/UnsafeRawBufferPointer.swift | 1821 +++++++++++++++++ 1 file changed, 1821 insertions(+) create mode 100644 stdlib/public/core/UnsafeRawBufferPointer.swift diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift b/stdlib/public/core/UnsafeRawBufferPointer.swift new file mode 100644 index 0000000000000..ff4d216b85ca2 --- /dev/null +++ b/stdlib/public/core/UnsafeRawBufferPointer.swift @@ -0,0 +1,1821 @@ +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1) +//===--- UnsafeRawBufferPointer.swift.gyb ---------------------*- swift -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 14) +@available(*, unavailable, renamed: "UnsafeMutableRawBufferPointer") +typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 19) + +/// A mutable nonowning collection interface to the bytes in a +/// region of memory. +/// +/// You can use an `UnsafeMutableRawBufferPointer` instance in low-level operations to eliminate +/// uniqueness checks and release mode bounds checks. Bounds checks are always +/// performed in debug mode. +/// +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 28) +/// An `UnsafeMutableRawBufferPointer` instance is a view of the raw bytes in a region of memory. +/// Each byte in memory is viewed as a `UInt8` value independent of the type +/// of values held in that memory. Reading from and writing to memory through +/// a raw buffer are untyped operations. Accessing this collection's bytes +/// does not bind the underlying memory to `UInt8`. +/// +/// In addition to its collection interface, an `UnsafeMutableRawBufferPointer` +/// instance also supports the following methods provided by +/// `UnsafeMutableRawPointer`, including bounds checks in debug mode: +/// +/// - `load(fromByteOffset:as:)` +/// - `loadUnaligned(fromByteOffset:as:)` +/// - `storeBytes(of:toByteOffset:as:)` +/// - `copyMemory(from:)` +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 53) +/// +/// To access the underlying memory through typed operations, the memory must +/// be bound to a trivial type. +/// +/// - Note: A *trivial type* can be copied bit for bit with no 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. Copying memory that +/// contains values of nontrivial types can only be done safely with a typed +/// pointer. Copying bytes directly from nontrivial, in-memory values does +/// not produce valid copies and can only be done by calling a C API, such as +/// `memmove()`. +/// +/// UnsafeMutableRawBufferPointer Semantics +/// ================= +/// +/// An `UnsafeMutableRawBufferPointer` instance is a view into memory and does not own the memory +/// that it references. Copying a variable or constant of type `UnsafeMutableRawBufferPointer` does +/// not copy the underlying memory. However, initializing another collection +/// with an `UnsafeMutableRawBufferPointer` instance copies bytes out of the referenced memory and +/// into the new collection. +/// +/// The following example uses `someBytes`, an `UnsafeMutableRawBufferPointer` instance, to +/// demonstrate the difference between assigning a buffer pointer and using a +/// buffer pointer as the source for another collection's elements. Here, the +/// assignment to `destBytes` creates a new, nonowning buffer pointer +/// covering the first `n` bytes of the memory that `someBytes` +/// references---nothing is copied: +/// +/// var destBytes = someBytes[0..= 0, "UnsafeMutableRawBufferPointer with negative count") + _debugPrecondition(count == 0 || start != nil, + "UnsafeMutableRawBufferPointer has a nil start and nonzero count") + _position = start + _end = start.map { $0 + _assumeNonNegative(count) } + } +} + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 171) +extension UnsafeMutableRawBufferPointer { + public typealias Iterator = UnsafeRawBufferPointer.Iterator +} +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 175) + +extension UnsafeMutableRawBufferPointer: Sequence { + public typealias SubSequence = Slice + + /// Returns an iterator over the bytes of this sequence. + @inlinable + public func makeIterator() -> Iterator { + return Iterator(_position: _position, _end: _end) + } + + /// Copies the elements of `self` to the memory at `destination.baseAddress`, + /// stopping when either `self` or `destination` is exhausted. + /// + /// - Returns: an iterator over any remaining elements of `self` and the + /// number of elements copied. + @inlinable // unsafe-performance + @_alwaysEmitIntoClient + public func _copyContents( + initializing destination: UnsafeMutableBufferPointer + ) -> (Iterator, UnsafeMutableBufferPointer.Index) { + guard let s = _position, let e = _end, e > s, !destination.isEmpty else { + return (makeIterator(), 0) + } + let destinationAddress = destination.baseAddress._unsafelyUnwrappedUnchecked + let d = UnsafeMutableRawPointer(destinationAddress) + let n = Swift.min(destination.count, s.distance(to: e)) + d.copyMemory(from: s, byteCount: n) + return (Iterator(_position: s.advanced(by: n), _end: e), n) + } +} + +extension UnsafeMutableRawBufferPointer: MutableCollection { + // TODO: Specialize `index` and `formIndex` and + // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. + public typealias Element = UInt8 + public typealias Index = Int + public typealias Indices = Range + + /// Always zero, which is the index of the first byte in a nonempty buffer. + @inlinable + public var startIndex: Index { + return 0 + } + + /// The "past the end" position---that is, the position one greater than the + /// last valid subscript argument. + /// + /// The `endIndex` property of an `UnsafeMutableRawBufferPointer` + /// instance is always identical to `count`. + @inlinable + public var endIndex: Index { + return count + } + + @inlinable + public var indices: Indices { + // Not checked because init forbids negative count. + return Indices(uncheckedBounds: (startIndex, endIndex)) + } + + /// Accesses the byte at the given offset in the memory region as a `UInt8` + /// value. + /// + /// - Parameter i: The offset of the byte to access. `i` must be in the range + /// `0.. Element { + get { + _debugPrecondition(i >= 0) + _debugPrecondition(i < endIndex) + return _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 248) + nonmutating set { + _debugPrecondition(i >= 0) + _debugPrecondition(i < endIndex) + _position._unsafelyUnwrappedUnchecked.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 254) + } + + /// Accesses the bytes in the specified memory region. + /// + /// - Parameter bounds: The range of byte offsets to access. The upper and + /// lower bounds of the range must be in the range `0...count`. + @inlinable + public subscript(bounds: Range) -> SubSequence { + get { + _debugPrecondition(bounds.lowerBound >= startIndex) + _debugPrecondition(bounds.upperBound <= endIndex) + return Slice(base: self, bounds: bounds) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 268) + nonmutating set { + _debugPrecondition(bounds.lowerBound >= startIndex) + _debugPrecondition(bounds.upperBound <= endIndex) + _debugPrecondition(bounds.count == newValue.count) + + if !newValue.isEmpty { + (baseAddress! + bounds.lowerBound).copyMemory( + from: newValue.base.baseAddress! + newValue.startIndex, + byteCount: newValue.count) + } + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 280) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 283) + /// Exchanges the byte values at the specified indices + /// in this buffer's memory. + /// + /// Both parameters must be valid indices of the buffer, and not + /// equal to `endIndex`. Passing the same index as both `i` and `j` has no + /// effect. + /// + /// - Parameters: + /// - i: The index of the first byte to swap. + /// - j: The index of the second byte to swap. + @inlinable + public func swapAt(_ i: Int, _ j: Int) { + guard i != j else { return } + _debugPrecondition(i >= 0 && j >= 0) + _debugPrecondition(i < endIndex && j < endIndex) + let pi = (_position! + i) + let pj = (_position! + j) + let tmp = pi.load(fromByteOffset: 0, as: UInt8.self) + pi.copyMemory(from: pj, byteCount: MemoryLayout.size) + pj.storeBytes(of: tmp, toByteOffset: 0, as: UInt8.self) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 306) + /// The number of bytes in the buffer. + /// + /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, + /// a buffer can have a `count` of zero even with a non-`nil` base address. + @inlinable + public var count: Int { + if let pos = _position { + // Unsafely unwrapped because init forbids end being nil if _position + // isn't. + _internalInvariant(_end != nil) + return _assumeNonNegative(_end._unsafelyUnwrappedUnchecked - pos) + } + return 0 + } +} + +extension UnsafeMutableRawBufferPointer: RandomAccessCollection { } + +extension UnsafeMutableRawBufferPointer { +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 326) + /// Allocates uninitialized memory with the specified size and alignment. + /// + /// You are in charge of managing the allocated memory. Be sure to deallocate + /// any memory that you manually allocate. + /// + /// The allocated memory is not bound to any specific type and must be bound + /// before performing any typed operations. If you are using the memory for + /// a specific type, allocate memory using the + /// `UnsafeMutablePointerBuffer.allocate(capacity:)` static method instead. + /// + /// - Parameters: + /// - byteCount: The number of bytes to allocate. `byteCount` must not be + /// negative. + /// - alignment: The alignment of the new region of allocated memory, in + /// bytes. `alignment` must be a whole power of 2. + /// - Returns: A buffer pointer to a newly allocated region of memory aligned + /// to `alignment`. + @inlinable + public static func allocate( + byteCount: Int, alignment: Int + ) -> UnsafeMutableRawBufferPointer { + let base = UnsafeMutableRawPointer.allocate( + byteCount: byteCount, alignment: alignment) + return UnsafeMutableRawBufferPointer(start: base, count: byteCount) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 352) + + /// Deallocates the memory block previously allocated at this buffer pointer’s + /// base address. + /// + /// This buffer pointer's `baseAddress` must be `nil` or a pointer to a memory + /// block previously returned by a Swift allocation method. If `baseAddress` is + /// `nil`, this function does nothing. Otherwise, the memory must not be initialized + /// or `Pointee` must be a trivial type. This buffer pointer's byte `count` must + /// be equal to the originally allocated size of the memory block. + @inlinable + public func deallocate() { + _position?.deallocate() + } + + /// Returns a new instance of the given type, read from the buffer pointer's + /// raw memory at the specified byte offset. + /// + /// The memory at `offset` bytes from this buffer pointer's `baseAddress` + /// must be properly aligned for accessing `T` and initialized to `T` or + /// another type that is layout compatible with `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. + @inlinable + public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { + _debugPrecondition(offset >= 0, "UnsafeMutableRawBufferPointer.load with negative offset") + _debugPrecondition(offset + MemoryLayout.size <= self.count, + "UnsafeMutableRawBufferPointer.load out of bounds") + 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 fourth through seventh bytes. + /// + /// let a = someBytes.loadUnaligned(as: Int32.self) + /// let b = someBytes.loadUnaligned(fromByteOffset: 3, 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 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, "UnsafeMutableRawBufferPointer.load with negative offset") + _debugPrecondition(offset + MemoryLayout.size <= self.count, + "UnsafeMutableRawBufferPointer.load out of bounds") + return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 446) + /// Stores a value's bytes into the buffer pointer's raw memory at the + /// specified byte offset. + /// + /// 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`. + /// + /// The memory written to 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`. + /// + /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is + /// initialized to the raw bytes of `value`. If the memory is bound to a + /// type `U` that is layout compatible with `T`, then it contains a value of + /// 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 + /// writing bytes from the value. 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`. + @inlinable + @_alwaysEmitIntoClient + // This custom silgen name is chosen to not interfere with the old ABI + @_silgen_name("_swift_se0349_UnsafeMutableRawBufferPointer_storeBytes") + public func storeBytes( + of value: T, toByteOffset offset: Int = 0, as type: T.Type + ) { + _debugPrecondition(offset >= 0, "UnsafeMutableRawBufferPointer.storeBytes with negative offset") + _debugPrecondition(offset + MemoryLayout.size <= self.count, + "UnsafeMutableRawBufferPointer.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 linked against the stdlib 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, "UnsafeMutableRawBufferPointer.storeBytes with negative offset") + _debugPrecondition(offset + MemoryLayout.size <= self.count, + "UnsafeMutableRawBufferPointer.storeBytes out of bounds") + + baseAddress!._legacy_se0349_storeBytes_internal( + of: value, toByteOffset: offset, as: T.self + ) + } + + /// Copies the bytes from the given buffer to this buffer's memory. + /// + /// If the `source.count` bytes of memory referenced by this buffer are bound + /// to a type `T`, then `T` must be a trivial type, the underlying pointer + /// must be properly aligned for accessing `T`, and `source.count` must be a + /// multiple of `MemoryLayout.stride`. + /// + /// The memory referenced by `source` may overlap with the memory referenced + /// by this buffer. + /// + /// After calling `copyMemory(from:)`, the first `source.count` bytes of + /// memory referenced by this buffer are initialized to raw bytes. If the + /// memory is bound to type `T`, then it contains values of type `T`. + /// + /// - Parameter source: A buffer of raw bytes. `source.count` must + /// be less than or equal to this buffer's `count`. + @inlinable + public func copyMemory(from source: UnsafeRawBufferPointer) { + _debugPrecondition(source.count <= self.count, + "UnsafeMutableRawBufferPointer.copyMemory source has too many elements") + if let baseAddress = baseAddress, let sourceAddress = source.baseAddress { + baseAddress.copyMemory(from: sourceAddress, byteCount: source.count) + } + } + + /// Copies from a collection of `UInt8` into this buffer's memory. + /// + /// If the first `source.count` bytes of memory referenced by this buffer + /// are bound to a type `T`, then `T` must be a trivial type, + /// the underlying pointer must be properly aligned for accessing `T`, + /// and `source.count` must be a multiple of `MemoryLayout.stride`. + /// + /// After calling `copyBytes(from:)`, the first `source.count` bytes of memory + /// referenced by this buffer are initialized to raw bytes. If the memory is + /// bound to type `T`, then it contains values of type `T`. + /// + /// - Parameter source: A collection of `UInt8` elements. `source.count` must + /// be less than or equal to this buffer's `count`. + @inlinable + public func copyBytes( + from source: C + ) where C.Element == UInt8 { + guard let position = _position else { + return + } + + if source.withContiguousStorageIfAvailable({ + (buffer: UnsafeBufferPointer) -> Void in + _debugPrecondition(source.count <= self.count, + "UnsafeMutableRawBufferPointer.copyBytes source has too many elements") + if let base = buffer.baseAddress { + position.copyMemory(from: base, byteCount: buffer.count) + } + }) != nil { + return + } + + for (index, byteValue) in source.enumerated() { + _debugPrecondition(index < self.count, + "UnsafeMutableRawBufferPointer.copyBytes source has too many elements") + position.storeBytes( + of: byteValue, toByteOffset: index, as: UInt8.self) + } + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 577) + + /// Creates a new buffer over the same memory as the given buffer. + /// + /// - Parameter bytes: The buffer to convert. + @inlinable + public init(_ bytes: UnsafeMutableRawBufferPointer) { + self.init(start: bytes.baseAddress, count: bytes.count) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 587) + /// Creates a new mutable buffer over the same memory as the given buffer. + /// + /// - Parameter bytes: The buffer to convert. + @inlinable + public init(mutating bytes: UnsafeRawBufferPointer) { + self.init(start: UnsafeMutableRawPointer(mutating: bytes.baseAddress), + count: bytes.count) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 604) + + /// Creates a raw buffer over the contiguous bytes in the given typed buffer. + /// + /// - Parameter buffer: The typed buffer to convert to a raw buffer. The + /// buffer's type `T` must be a trivial type. + @inlinable + public init(_ buffer: UnsafeMutableBufferPointer) { + self.init(start: buffer.baseAddress, + count: buffer.count * MemoryLayout.stride) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 626) + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 666) + + /// Creates a raw buffer over the same memory as the given raw buffer slice, + /// with the indices rebased to zero. + /// + /// The new buffer represents the same region of memory as the slice, but its + /// indices start at zero instead of at the beginning of the slice in the + /// original buffer. The following code creates `slice`, a slice covering + /// part of an existing buffer instance, then rebases it into a new `rebased` + /// buffer. + /// + /// let slice = buffer[n...] + /// let rebased = UnsafeRawBufferPointer(rebasing: slice) + /// + /// After this code has executed, the following are true: + /// + /// - `rebased.startIndex == 0` + /// - `rebased[0] == slice[n]` + /// - `rebased[0] == buffer[n]` + /// - `rebased.count == slice.count` + /// + /// - Parameter slice: The raw buffer slice to rebase. + @inlinable + public init(rebasing slice: Slice) { + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + let count = slice.endIndex &- slice.startIndex + self.init(start: base, count: count) + } + + /// A pointer to the first byte of the buffer. + /// + /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, + /// a buffer can have a `count` of zero even with a non-`nil` base address. + @inlinable + public var baseAddress: UnsafeMutableRawPointer? { + return _position + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 704) + + /// Initializes the memory referenced by this buffer with the given value, + /// binds the memory to the value's type, and returns a typed buffer of the + /// initialized memory. + /// + /// The memory referenced by this buffer must be uninitialized or + /// initialized to a trivial type, and must be properly aligned for + /// accessing `T`. + /// + /// After calling this method on a raw buffer with non-nil `baseAddress` `b`, + /// the region starting at `b` and continuing up to + /// `b + self.count - self.count % MemoryLayout.stride` is bound + /// to type `T` and is initialized. If `T` is a nontrivial type, you must + /// eventually deinitialize or move the values in this region to avoid leaks. + /// If `baseAddress` is `nil`, this function does nothing + /// and returns an empty buffer pointer. + /// + /// - Parameters: + /// - type: The type to bind this buffer’s memory to. + /// - repeatedValue: The instance to copy into memory. + /// - Returns: A typed buffer of the memory referenced by this raw buffer. + /// The typed buffer contains `self.count / MemoryLayout.stride` + /// instances of `T`. + @inlinable + @discardableResult + public func initializeMemory(as type: T.Type, repeating repeatedValue: T) + -> UnsafeMutableBufferPointer { + guard let base = _position else { + return .init(start: nil, count: 0) + } + + let count = (_end._unsafelyUnwrappedUnchecked-base) / MemoryLayout.stride + let initialized = base.initializeMemory( + as: type, repeating: repeatedValue, count: count + ) + return .init(start: initialized, count: count) + } + + /// Initializes the buffer's memory with the given elements, binding the + /// initialized memory to the elements' type. + /// + /// When calling the `initializeMemory(as:from:)` method on a buffer `b`, + /// the memory referenced by `b` must be uninitialized or initialized to a + /// trivial type, and must be properly aligned for accessing `S.Element`. + /// The buffer must contain sufficient memory to accommodate + /// `source.underestimatedCount`. + /// + /// This method initializes the buffer with elements from `source` until + /// `source` is exhausted or, if `source` is a sequence but not a collection, + /// the buffer has no more room for source's elements. After calling + /// `initializeMemory(as:from:)`, the memory referenced by the returned + /// `UnsafeMutableBufferPointer` instance is bound and initialized to type + /// `S.Element`. This method does not change + /// the binding state of the unused portion of `b`, if any. + /// + /// - Parameters: + /// - type: The type of element to which this buffer's memory will be bound. + /// - source: A sequence of elements with which to initialize the buffer. + /// - Returns: An iterator to any elements of `source` that didn't fit in the + /// buffer, and a typed buffer of the written elements. The returned + /// buffer references memory starting at the same base address as this + /// buffer. + @inlinable + public func initializeMemory( + as type: S.Element.Type, from source: S + ) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer) { + var it = source.makeIterator() + var idx = startIndex + let elementStride = MemoryLayout.stride + + // This has to be a debug precondition due to the cost of walking over some collections. + _debugPrecondition(source.underestimatedCount <= (count / elementStride), + "insufficient space to accommodate source.underestimatedCount elements") + guard let base = baseAddress else { + // this can be a precondition since only an invalid argument should be costly + _precondition(source.underestimatedCount == 0, + "no memory available to initialize from source") + return (it, UnsafeMutableBufferPointer(start: nil, count: 0)) + } + + _debugPrecondition( + Int(bitPattern: base) % MemoryLayout.stride == 0, + "buffer base address must be properly aligned to access S.Element" + ) + + _internalInvariant(_end != nil) + for p in stride(from: base, + // only advance to as far as the last element that will fit + to: _end._unsafelyUnwrappedUnchecked - elementStride + 1, + by: elementStride + ) { + // underflow is permitted -- e.g. a sequence into + // the spare capacity of an Array buffer + guard let x = it.next() else { break } + p.initializeMemory(as: S.Element.self, repeating: x, count: 1) + formIndex(&idx, offsetBy: elementStride) + } + + return (it, UnsafeMutableBufferPointer( + start: base.assumingMemoryBound(to: S.Element.self), + count: idx / elementStride)) + } + + /// Initializes the buffer's memory with every element of the source, + /// binding the initialized memory to the elements' type. + /// + /// When calling the `initializeMemory(as:fromContentsOf:)` method, + /// the memory referenced by the buffer must be uninitialized, or initialized + /// to a trivial type. The buffer must reference enough memory to store + /// `source.count` elements, and its `baseAddress` must be properly aligned + /// for accessing `C.Element`. + /// + /// This method initializes the buffer with the contents of `source` + /// until `source` is exhausted. + /// After calling `initializeMemory(as:fromContentsOf:)`, the memory + /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound + /// to the type `C.Element` and is initialized. This method does not change + /// the binding state of the unused portion of the buffer, if any. + /// + /// - Note: The memory regions referenced by `source` and this buffer + /// must not overlap. + /// + /// - Parameters: + /// - type: The type of element to which this buffer's memory will be bound. + /// - source: A collection of elements to be used to + /// initialize the buffer's storage. + /// - Returns: A typed buffer referencing the initialized elements. + /// The returned buffer references memory starting at the same + /// base address as this buffer, and its count is equal to `source.count` + @inlinable + @_alwaysEmitIntoClient + public func initializeMemory( + as type: C.Element.Type, + fromContentsOf source: C + ) -> UnsafeMutableBufferPointer { + let buffer: UnsafeMutableBufferPointer? + buffer = source.withContiguousStorageIfAvailable { + guard let sourceAddress = $0.baseAddress, !$0.isEmpty else { + return .init(start: nil, count: 0) + } + _debugPrecondition( + Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, + "buffer base address must be properly aligned to access C.Element" + ) + _precondition( + $0.count * MemoryLayout.stride <= self.count, + "buffer cannot contain every element from source collection." + ) + let start = baseAddress?.initializeMemory( + as: C.Element.self, from: sourceAddress, count: $0.count + ) + return .init(start: start, count: $0.count) + } + if let buffer { + return buffer + } + + guard let base = baseAddress else { + _precondition( + source.isEmpty, + "buffer cannot contain every element from source collection." + ) + return .init(start: nil, count: 0) + } + _internalInvariant(_end != nil) + _debugPrecondition( + Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, + "buffer base address must be properly aligned to access C.Element" + ) + var iterator = source.makeIterator() + var element = base + var initialized = 0 + let end = _end._unsafelyUnwrappedUnchecked - MemoryLayout.stride + while element <= end { + guard let value = iterator.next() else { + return .init(start: .init(base._rawValue), count: initialized) + } + element.initializeMemory(as: C.Element.self, to: value) + element = element.advanced(by: MemoryLayout.stride) + initialized += 1 + } + _precondition( + iterator.next() == nil, + "buffer cannot contain every element from source collection." + ) + return .init(start: .init(base._rawValue), count: initialized) + } + + /// Moves every element of an initialized source buffer into the + /// uninitialized memory referenced by this buffer, leaving the source memory + /// uninitialized and this buffer's memory initialized. + /// + /// When calling the `moveInitializeMemory(as:fromContentsOf:)` method, + /// the memory referenced by the buffer must be uninitialized, or initialized + /// to a trivial type. The buffer must reference enough memory to store + /// `source.count` elements, and its `baseAddress` must be properly aligned + /// for accessing `C.Element`. After the method returns, + /// the memory referenced by the returned buffer is initialized and the + /// memory region underlying `source` is uninitialized. + /// + /// This method initializes the buffer with the contents of `source` + /// until `source` is exhausted. + /// After calling `initializeMemory(as:fromContentsOf:)`, the memory + /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound + /// to the type `T` and is initialized. This method does not change + /// the binding state of the unused portion of the buffer, if any. + /// + /// - Note: The memory regions referenced by `source` and this buffer + /// may overlap. + /// + /// - Parameters: + /// - type: The type of element to which this buffer's memory will be bound. + /// - source: A buffer referencing the values to copy. + /// The memory region underlying `source` must be initialized. + /// - Returns: A typed buffer referencing the initialized elements. + /// The returned buffer references memory starting at the same + /// base address as this buffer, and its count is equal to `source.count`. + @discardableResult + @inlinable + @_alwaysEmitIntoClient + public func moveInitializeMemory( + as type: T.Type, + fromContentsOf source: UnsafeMutableBufferPointer + ) -> UnsafeMutableBufferPointer { + guard let sourceAddress = source.baseAddress, !source.isEmpty else { + return .init(start: nil, count: 0) + } + _debugPrecondition( + Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, + "buffer base address must be properly aligned to access T" + ) + _precondition( + source.count * MemoryLayout.stride <= self.count, + "buffer cannot contain every element from source." + ) + let initialized = baseAddress?.moveInitializeMemory( + as: T.self, from: sourceAddress, count: source.count + ) + return .init(start: initialized, count: source.count) + } + + /// Moves every element of an initialized source buffer slice into the + /// uninitialized memory referenced by this buffer, leaving the source memory + /// uninitialized and this buffer's memory initialized. + /// + /// When calling the `moveInitializeMemory(as:fromContentsOf:)` method, + /// the memory referenced by the buffer must be uninitialized, or initialized + /// to a trivial type. The buffer must reference enough memory to store + /// `source.count` elements, and its `baseAddress` must be properly aligned + /// for accessing `C.Element`. After the method returns, + /// the memory referenced by the returned buffer is initialized and the + /// memory region underlying `source` is uninitialized. + /// + /// This method initializes the buffer with the contents of `source` + /// until `source` is exhausted. + /// After calling `initializeMemory(as:fromContentsOf:)`, the memory + /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound + /// to the type `T` and is initialized. This method does not change + /// the binding state of the unused portion of the buffer, if any. + /// + /// - Note: The memory regions referenced by `source` and this buffer + /// may overlap. + /// + /// - Parameters: + /// - type: The type of element to which this buffer's memory will be bound. + /// - source: A buffer referencing the values to copy. + /// The memory region underlying `source` must be initialized. + /// - Returns: A typed buffer referencing the initialized elements. + /// The returned buffer references memory starting at the same + /// base address as this buffer, and its count is equal to `source.count`. + @discardableResult + @inlinable + @_alwaysEmitIntoClient + public func moveInitializeMemory( + as type: T.Type, + fromContentsOf source: Slice> + ) -> UnsafeMutableBufferPointer { + let rebased = UnsafeMutableBufferPointer(rebasing: source) + return moveInitializeMemory(as: T.self, fromContentsOf: rebased) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 986) + + /// Binds this buffer’s memory to the specified type and returns a typed buffer + /// of the bound memory. + /// + /// Use the `bindMemory(to:)` method to bind the memory referenced + /// by this buffer to the type `T`. The memory must be uninitialized or + /// initialized to a type that is layout compatible with `T`. If the memory + /// is uninitialized, it is still uninitialized after being bound to `T`. + /// + /// - Warning: A memory location may only be bound to one type at a time. The + /// behavior of accessing memory as a type unrelated to its bound type is + /// undefined. + /// + /// - Parameters: + /// - type: The type `T` to bind the memory to. + /// - Returns: A typed buffer of the newly bound memory. The memory in this + /// region is bound to `T`, but has not been modified in any other way. + /// The typed buffer references `self.count / MemoryLayout.stride` + /// instances of `T`. + @_transparent + @discardableResult + public func bindMemory( + to type: T.Type + ) -> UnsafeMutableBufferPointer { + guard let base = _position else { + return UnsafeMutableBufferPointer(start: nil, count: 0) + } + + let capacity = count / MemoryLayout.stride + Builtin.bindMemory(base._rawValue, capacity._builtinWordValue, type) + return UnsafeMutableBufferPointer( + start: UnsafeMutablePointer(base._rawValue), count: capacity) + } + + /// Executes the given closure while temporarily binding the buffer to + /// instances of type `T`. + /// + /// Use this method when you have a buffer to raw memory and you need + /// to access that memory as instances of a given type `T`. Accessing + /// memory as a type `T` requires that the memory be bound to that type. + /// A memory location may only be bound to one type at a time, so accessing + /// the same memory as an unrelated type without first rebinding the memory + /// is undefined. + /// + /// Any instance of `T` within the re-bound region may be initialized or + /// uninitialized. The memory underlying any individual instance of `T` + /// must have the same initialization state (i.e. initialized or + /// uninitialized.) Accessing a `T` whose underlying memory + /// is in a mixed initialization state shall be undefined behaviour. + /// + /// If the byte count of the original buffer is not a multiple of + /// the stride of `T`, then the re-bound buffer is shorter + /// than the original buffer. + /// + /// After executing `body`, this method rebinds memory back to its original + /// binding state. This can be unbound memory, or bound to a different type. + /// + /// - Note: The buffer's base address must match the + /// alignment of `T` (as reported by `MemoryLayout.alignment`). + /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` + /// must equal zero. + /// + /// - Note: A raw buffer may represent memory that has been bound to a type. + /// If that is the case, then `T` must be layout compatible with the + /// type to which the memory has been bound. This requirement does not + /// apply if the raw buffer represents memory that has not been bound + /// to any type. + /// + /// - Parameters: + /// - type: The type to temporarily bind the memory referenced by this + /// buffer. + /// - body: A closure that takes a typed pointer to the + /// same memory as this pointer, only bound to type `T`. The closure's + /// pointer argument is valid only for the duration of the closure's + /// execution. If `body` has a return value, that value is also used as + /// the return value for the `withMemoryRebound(to:capacity:_:)` method. + /// - buffer: The buffer temporarily bound to instances of `T`. + /// - Returns: The return value, if any, of the `body` closure parameter. + @inlinable + @_alwaysEmitIntoClient + public func withMemoryRebound( + to type: T.Type, + _ body: (_ buffer: UnsafeMutableBufferPointer) throws -> Result + ) rethrows -> Result { + guard let s = _position else { + return try body(.init(start: nil, count: 0)) + } + _debugPrecondition( + Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0, + "baseAddress must be a properly aligned pointer for type T" + ) + // initializer ensures _end is nil only when _position is nil. + _internalInvariant(_end != nil) + let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) + let n = c / MemoryLayout.stride + let binding = Builtin.bindMemory(s._rawValue, n._builtinWordValue, T.self) + defer { Builtin.rebindMemory(s._rawValue, binding) } + return try body(.init(start: .init(s._rawValue), count: n)) + } + + /// Returns a typed buffer to the memory referenced by this buffer, + /// assuming that the memory is already bound to the specified type. + /// + /// Use this method when you have a raw buffer to memory that has already + /// been bound to the specified type. The memory starting at this pointer + /// must be bound to the type `T`. Accessing memory through the returned + /// pointer is undefined if the memory has not been bound to `T`. To bind + /// memory to `T`, use `bindMemory(to:capacity:)` instead of this method. + /// + /// - Note: The buffer's base address must match the + /// alignment of `T` (as reported by `MemoryLayout.alignment`). + /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` + /// must equal zero. + /// + /// - Parameter to: The type `T` that the memory has already been bound to. + /// - Returns: A typed pointer to the same memory as this raw pointer. + @inlinable + @_alwaysEmitIntoClient + public func assumingMemoryBound( + to: T.Type + ) -> UnsafeMutableBufferPointer { + guard let s = _position else { + return .init(start: nil, count: 0) + } + // initializer ensures _end is nil only when _position is nil. + _internalInvariant(_end != nil) + let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) + let n = c / MemoryLayout.stride + return .init(start: .init(s._rawValue), count: n) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1118) + @inlinable + @_alwaysEmitIntoClient + public func withContiguousMutableStorageIfAvailable( + _ body: (inout UnsafeMutableBufferPointer) throws -> R + ) rethrows -> R? { + try withMemoryRebound(to: Element.self) { b in + var buffer = b + defer { + _debugPrecondition( + (b.baseAddress, b.count) == (buffer.baseAddress, buffer.count), + "UnsafeMutableRawBufferPointer.withContiguousMutableStorageIfAvailable: replacing the buffer is not allowed" + ) + } + return try body(&buffer) + } + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1136) + @inlinable + @_alwaysEmitIntoClient + public func withContiguousStorageIfAvailable( + _ body: (UnsafeBufferPointer) throws -> R + ) rethrows -> R? { + try withMemoryRebound(to: Element.self) { + try body(UnsafeBufferPointer($0)) + } + } +} + +@_unavailableInEmbedded +extension UnsafeMutableRawBufferPointer: CustomDebugStringConvertible { + /// A textual representation of the buffer, suitable for debugging. + public var debugDescription: String { + return "UnsafeMutableRawBufferPointer" + + "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))" + } +} + +extension UnsafeMutableRawBufferPointer { + @available(*, unavailable, + message: "use 'UnsafeMutableRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") + public subscript(bounds: Range) -> UnsafeMutableRawBufferPointer { + get { return UnsafeMutableRawBufferPointer(start: nil, count: 0) } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1162) + nonmutating set {} +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1164) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1167) + @available(*, unavailable, + message: "use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") + public subscript(bounds: Range) -> UnsafeRawBufferPointer { + get { return UnsafeRawBufferPointer(start: nil, count: 0) } + nonmutating set {} + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1174) +} + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 19) + +/// A nonowning collection interface to the bytes in a +/// region of memory. +/// +/// You can use an `UnsafeRawBufferPointer` instance in low-level operations to eliminate +/// uniqueness checks and release mode bounds checks. Bounds checks are always +/// performed in debug mode. +/// +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 43) +/// An `UnsafeRawBufferPointer` instance is a view of the raw bytes in a region of memory. +/// Each byte in memory is viewed as a `UInt8` value independent of the type +/// of values held in that memory. Reading from memory through a raw buffer is +/// an untyped operation. +/// +/// In addition to its collection interface, an `UnsafeRawBufferPointer` +/// instance also supports the `load(fromByteOffset:as:)` +/// and `loadUnaligned(fromByteOffset:as:)` methods provided by +/// `UnsafeRawPointer`, including bounds checks in debug mode. +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 53) +/// +/// To access the underlying memory through typed operations, the memory must +/// be bound to a trivial type. +/// +/// - Note: A *trivial type* can be copied bit for bit with no 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. Copying memory that +/// contains values of nontrivial types can only be done safely with a typed +/// pointer. Copying bytes directly from nontrivial, in-memory values does +/// not produce valid copies and can only be done by calling a C API, such as +/// `memmove()`. +/// +/// UnsafeRawBufferPointer Semantics +/// ================= +/// +/// An `UnsafeRawBufferPointer` instance is a view into memory and does not own the memory +/// that it references. Copying a variable or constant of type `UnsafeRawBufferPointer` does +/// not copy the underlying memory. However, initializing another collection +/// with an `UnsafeRawBufferPointer` instance copies bytes out of the referenced memory and +/// into the new collection. +/// +/// The following example uses `someBytes`, an `UnsafeRawBufferPointer` instance, to +/// demonstrate the difference between assigning a buffer pointer and using a +/// buffer pointer as the source for another collection's elements. Here, the +/// assignment to `destBytes` creates a new, nonowning buffer pointer +/// covering the first `n` bytes of the memory that `someBytes` +/// references---nothing is copied: +/// +/// var destBytes = someBytes[0..= 0, "UnsafeRawBufferPointer with negative count") + _debugPrecondition(count == 0 || start != nil, + "UnsafeRawBufferPointer has a nil start and nonzero count") + _position = start + _end = start.map { $0 + _assumeNonNegative(count) } + } +} + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 125) +extension UnsafeRawBufferPointer { + /// An iterator over the bytes viewed by a raw buffer pointer. + @frozen + public struct Iterator { + @usableFromInline + internal var _position, _end: UnsafeRawPointer? + + @inlinable + internal init(_position: UnsafeRawPointer?, _end: UnsafeRawPointer?) { + self._position = _position + self._end = _end + } + } +} + +extension UnsafeRawBufferPointer.Iterator: IteratorProtocol, Sequence { + /// Advances to the next byte and returns it, or `nil` if no next byte + /// exists. + /// + /// Once `nil` has been returned, all subsequent calls return `nil`. + /// + /// - Returns: The next sequential byte in the raw buffer if another byte + /// exists; otherwise, `nil`. + @inlinable + public mutating func next() -> UInt8? { + if _position == _end { return nil } + + // We can do an unchecked unwrap here by borrowing invariants from the pointer. + // For a validly constructed buffer pointer, the only way _position can be nil is + // if _end is also nil. We checked that case above. Thus, we can safely do an + // unchecked unwrap here. + // + // Additionally, validly constructed buffer pointers also have an _end that is + // strictly greater than or equal to _position, and so we do not need to do checked + // arithmetic here as we cannot possibly overflow. + // + // We check these invariants in debug builds to defend against invalidly constructed + // pointers. + _debugPrecondition(_position! < _end!) + let position = _position._unsafelyUnwrappedUnchecked + let result = position.load(as: UInt8.self) + _position = position + 1 + return result + } +} +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 175) + +extension UnsafeRawBufferPointer: Sequence { + public typealias SubSequence = Slice + + /// Returns an iterator over the bytes of this sequence. + @inlinable + public func makeIterator() -> Iterator { + return Iterator(_position: _position, _end: _end) + } + + /// Copies the elements of `self` to the memory at `destination.baseAddress`, + /// stopping when either `self` or `destination` is exhausted. + /// + /// - Returns: an iterator over any remaining elements of `self` and the + /// number of elements copied. + @inlinable // unsafe-performance + @_alwaysEmitIntoClient + public func _copyContents( + initializing destination: UnsafeMutableBufferPointer + ) -> (Iterator, UnsafeMutableBufferPointer.Index) { + guard let s = _position, let e = _end, e > s, !destination.isEmpty else { + return (makeIterator(), 0) + } + let destinationAddress = destination.baseAddress._unsafelyUnwrappedUnchecked + let d = UnsafeMutableRawPointer(destinationAddress) + let n = Swift.min(destination.count, s.distance(to: e)) + d.copyMemory(from: s, byteCount: n) + return (Iterator(_position: s.advanced(by: n), _end: e), n) + } +} + +extension UnsafeRawBufferPointer: Collection { + // TODO: Specialize `index` and `formIndex` and + // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. + public typealias Element = UInt8 + public typealias Index = Int + public typealias Indices = Range + + /// Always zero, which is the index of the first byte in a nonempty buffer. + @inlinable + public var startIndex: Index { + return 0 + } + + /// The "past the end" position---that is, the position one greater than the + /// last valid subscript argument. + /// + /// The `endIndex` property of an `UnsafeRawBufferPointer` + /// instance is always identical to `count`. + @inlinable + public var endIndex: Index { + return count + } + + @inlinable + public var indices: Indices { + // Not checked because init forbids negative count. + return Indices(uncheckedBounds: (startIndex, endIndex)) + } + + /// Accesses the byte at the given offset in the memory region as a `UInt8` + /// value. + /// + /// - Parameter i: The offset of the byte to access. `i` must be in the range + /// `0.. Element { + get { + _debugPrecondition(i >= 0) + _debugPrecondition(i < endIndex) + return _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 254) + } + + /// Accesses the bytes in the specified memory region. + /// + /// - Parameter bounds: The range of byte offsets to access. The upper and + /// lower bounds of the range must be in the range `0...count`. + @inlinable + public subscript(bounds: Range) -> SubSequence { + get { + _debugPrecondition(bounds.lowerBound >= startIndex) + _debugPrecondition(bounds.upperBound <= endIndex) + return Slice(base: self, bounds: bounds) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 280) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 306) + /// The number of bytes in the buffer. + /// + /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, + /// a buffer can have a `count` of zero even with a non-`nil` base address. + @inlinable + public var count: Int { + if let pos = _position { + // Unsafely unwrapped because init forbids end being nil if _position + // isn't. + _internalInvariant(_end != nil) + return _assumeNonNegative(_end._unsafelyUnwrappedUnchecked - pos) + } + return 0 + } +} + +extension UnsafeRawBufferPointer: RandomAccessCollection { } + +extension UnsafeRawBufferPointer { +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 352) + + /// Deallocates the memory block previously allocated at this buffer pointer’s + /// base address. + /// + /// This buffer pointer's `baseAddress` must be `nil` or a pointer to a memory + /// block previously returned by a Swift allocation method. If `baseAddress` is + /// `nil`, this function does nothing. Otherwise, the memory must not be initialized + /// or `Pointee` must be a trivial type. This buffer pointer's byte `count` must + /// be equal to the originally allocated size of the memory block. + @inlinable + public func deallocate() { + _position?.deallocate() + } + + /// Returns a new instance of the given type, read from the buffer pointer's + /// raw memory at the specified byte offset. + /// + /// The memory at `offset` bytes from this buffer pointer's `baseAddress` + /// must be properly aligned for accessing `T` and initialized to `T` or + /// another type that is layout compatible with `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. + @inlinable + public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { + _debugPrecondition(offset >= 0, "UnsafeRawBufferPointer.load with negative offset") + _debugPrecondition(offset + MemoryLayout.size <= self.count, + "UnsafeRawBufferPointer.load out of bounds") + 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 fourth through seventh bytes. + /// + /// let a = someBytes.loadUnaligned(as: Int32.self) + /// let b = someBytes.loadUnaligned(fromByteOffset: 3, 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 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, "UnsafeRawBufferPointer.load with negative offset") + _debugPrecondition(offset + MemoryLayout.size <= self.count, + "UnsafeRawBufferPointer.load out of bounds") + return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 577) + + /// Creates a new buffer over the same memory as the given buffer. + /// + /// - Parameter bytes: The buffer to convert. + @inlinable + public init(_ bytes: UnsafeMutableRawBufferPointer) { + self.init(start: bytes.baseAddress, count: bytes.count) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 596) + /// Creates a new buffer over the same memory as the given buffer. + /// + /// - Parameter bytes: The buffer to convert. + @inlinable + public init(_ bytes: UnsafeRawBufferPointer) { + self.init(start: bytes.baseAddress, count: bytes.count) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 604) + + /// Creates a raw buffer over the contiguous bytes in the given typed buffer. + /// + /// - Parameter buffer: The typed buffer to convert to a raw buffer. The + /// buffer's type `T` must be a trivial type. + @inlinable + public init(_ buffer: UnsafeMutableBufferPointer) { + self.init(start: buffer.baseAddress, + count: buffer.count * MemoryLayout.stride) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 616) + /// Creates a raw buffer over the contiguous bytes in the given typed buffer. + /// + /// - Parameter buffer: The typed buffer to convert to a raw buffer. The + /// buffer's type `T` must be a trivial type. + @inlinable + public init(_ buffer: UnsafeBufferPointer) { + self.init(start: buffer.baseAddress, + count: buffer.count * MemoryLayout.stride) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 626) + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 628) + /// Creates a raw buffer over the same memory as the given raw buffer slice, + /// with the indices rebased to zero. + /// + /// The new buffer represents the same region of memory as the slice, but its + /// indices start at zero instead of at the beginning of the slice in the + /// original buffer. The following code creates `slice`, a slice covering + /// part of an existing buffer instance, then rebases it into a new `rebased` + /// buffer. + /// + /// let slice = buffer[n...] + /// let rebased = UnsafeRawBufferPointer(rebasing: slice) + /// + /// After this code has executed, the following are true: + /// + /// - `rebased.startIndex == 0` + /// - `rebased[0] == slice[n]` + /// - `rebased[0] == buffer[n]` + /// - `rebased.count == slice.count` + /// + /// - Parameter slice: The raw buffer slice to rebase. + @inlinable + public init(rebasing slice: Slice) { + // NOTE: `Slice` does not guarantee that its start/end indices are valid + // in `base` -- it merely ensures that `startIndex <= endIndex`. + // We need manually check that we aren't given an invalid slice, + // or the resulting collection would allow access that was + // out-of-bounds with respect to the original base buffer. + // We only do this in debug builds to prevent a measurable performance + // degradation wrt passing around pointers not wrapped in a BufferPointer + // construct. + _debugPrecondition( + slice.startIndex >= 0 && slice.endIndex <= slice.base.count, + "Invalid slice") + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + let count = slice.endIndex &- slice.startIndex + self.init(start: base, count: count) + } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 666) + + /// Creates a raw buffer over the same memory as the given raw buffer slice, + /// with the indices rebased to zero. + /// + /// The new buffer represents the same region of memory as the slice, but its + /// indices start at zero instead of at the beginning of the slice in the + /// original buffer. The following code creates `slice`, a slice covering + /// part of an existing buffer instance, then rebases it into a new `rebased` + /// buffer. + /// + /// let slice = buffer[n...] + /// let rebased = UnsafeRawBufferPointer(rebasing: slice) + /// + /// After this code has executed, the following are true: + /// + /// - `rebased.startIndex == 0` + /// - `rebased[0] == slice[n]` + /// - `rebased[0] == buffer[n]` + /// - `rebased.count == slice.count` + /// + /// - Parameter slice: The raw buffer slice to rebase. + @inlinable + public init(rebasing slice: Slice) { + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + let count = slice.endIndex &- slice.startIndex + self.init(start: base, count: count) + } + + /// A pointer to the first byte of the buffer. + /// + /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, + /// a buffer can have a `count` of zero even with a non-`nil` base address. + @inlinable + public var baseAddress: UnsafeRawPointer? { + return _position + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 986) + + /// Binds this buffer’s memory to the specified type and returns a typed buffer + /// of the bound memory. + /// + /// Use the `bindMemory(to:)` method to bind the memory referenced + /// by this buffer to the type `T`. The memory must be uninitialized or + /// initialized to a type that is layout compatible with `T`. If the memory + /// is uninitialized, it is still uninitialized after being bound to `T`. + /// + /// - Warning: A memory location may only be bound to one type at a time. The + /// behavior of accessing memory as a type unrelated to its bound type is + /// undefined. + /// + /// - Parameters: + /// - type: The type `T` to bind the memory to. + /// - Returns: A typed buffer of the newly bound memory. The memory in this + /// region is bound to `T`, but has not been modified in any other way. + /// The typed buffer references `self.count / MemoryLayout.stride` + /// instances of `T`. + @_transparent + @discardableResult + public func bindMemory( + to type: T.Type + ) -> UnsafeBufferPointer { + guard let base = _position else { + return UnsafeBufferPointer(start: nil, count: 0) + } + + let capacity = count / MemoryLayout.stride + Builtin.bindMemory(base._rawValue, capacity._builtinWordValue, type) + return UnsafeBufferPointer( + start: UnsafePointer(base._rawValue), count: capacity) + } + + /// Executes the given closure while temporarily binding the buffer to + /// instances of type `T`. + /// + /// Use this method when you have a buffer to raw memory and you need + /// to access that memory as instances of a given type `T`. Accessing + /// memory as a type `T` requires that the memory be bound to that type. + /// A memory location may only be bound to one type at a time, so accessing + /// the same memory as an unrelated type without first rebinding the memory + /// is undefined. + /// + /// Any instance of `T` within the re-bound region may be initialized or + /// uninitialized. The memory underlying any individual instance of `T` + /// must have the same initialization state (i.e. initialized or + /// uninitialized.) Accessing a `T` whose underlying memory + /// is in a mixed initialization state shall be undefined behaviour. + /// + /// If the byte count of the original buffer is not a multiple of + /// the stride of `T`, then the re-bound buffer is shorter + /// than the original buffer. + /// + /// After executing `body`, this method rebinds memory back to its original + /// binding state. This can be unbound memory, or bound to a different type. + /// + /// - Note: The buffer's base address must match the + /// alignment of `T` (as reported by `MemoryLayout.alignment`). + /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` + /// must equal zero. + /// + /// - Note: A raw buffer may represent memory that has been bound to a type. + /// If that is the case, then `T` must be layout compatible with the + /// type to which the memory has been bound. This requirement does not + /// apply if the raw buffer represents memory that has not been bound + /// to any type. + /// + /// - Parameters: + /// - type: The type to temporarily bind the memory referenced by this + /// buffer. + /// - body: A closure that takes a typed pointer to the + /// same memory as this pointer, only bound to type `T`. The closure's + /// pointer argument is valid only for the duration of the closure's + /// execution. If `body` has a return value, that value is also used as + /// the return value for the `withMemoryRebound(to:capacity:_:)` method. + /// - buffer: The buffer temporarily bound to instances of `T`. + /// - Returns: The return value, if any, of the `body` closure parameter. + @inlinable + @_alwaysEmitIntoClient + public func withMemoryRebound( + to type: T.Type, + _ body: (_ buffer: UnsafeBufferPointer) throws -> Result + ) rethrows -> Result { + guard let s = _position else { + return try body(.init(start: nil, count: 0)) + } + _debugPrecondition( + Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0, + "baseAddress must be a properly aligned pointer for type T" + ) + // initializer ensures _end is nil only when _position is nil. + _internalInvariant(_end != nil) + let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) + let n = c / MemoryLayout.stride + let binding = Builtin.bindMemory(s._rawValue, n._builtinWordValue, T.self) + defer { Builtin.rebindMemory(s._rawValue, binding) } + return try body(.init(start: .init(s._rawValue), count: n)) + } + + /// Returns a typed buffer to the memory referenced by this buffer, + /// assuming that the memory is already bound to the specified type. + /// + /// Use this method when you have a raw buffer to memory that has already + /// been bound to the specified type. The memory starting at this pointer + /// must be bound to the type `T`. Accessing memory through the returned + /// pointer is undefined if the memory has not been bound to `T`. To bind + /// memory to `T`, use `bindMemory(to:capacity:)` instead of this method. + /// + /// - Note: The buffer's base address must match the + /// alignment of `T` (as reported by `MemoryLayout.alignment`). + /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` + /// must equal zero. + /// + /// - Parameter to: The type `T` that the memory has already been bound to. + /// - Returns: A typed pointer to the same memory as this raw pointer. + @inlinable + @_alwaysEmitIntoClient + public func assumingMemoryBound( + to: T.Type + ) -> UnsafeBufferPointer { + guard let s = _position else { + return .init(start: nil, count: 0) + } + // initializer ensures _end is nil only when _position is nil. + _internalInvariant(_end != nil) + let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) + let n = c / MemoryLayout.stride + return .init(start: .init(s._rawValue), count: n) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1136) + @inlinable + @_alwaysEmitIntoClient + public func withContiguousStorageIfAvailable( + _ body: (UnsafeBufferPointer) throws -> R + ) rethrows -> R? { + try withMemoryRebound(to: Element.self) { + try body($0) + } + } +} + +@_unavailableInEmbedded +extension UnsafeRawBufferPointer: CustomDebugStringConvertible { + /// A textual representation of the buffer, suitable for debugging. + public var debugDescription: String { + return "UnsafeRawBufferPointer" + + "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))" + } +} + +extension UnsafeRawBufferPointer { + @available(*, unavailable, + message: "use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") + public subscript(bounds: Range) -> UnsafeRawBufferPointer { + get { return UnsafeRawBufferPointer(start: nil, count: 0) } +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1164) + } + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1174) +} + +// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1177) + +/// Invokes the given closure with a mutable buffer pointer covering the raw +/// bytes of the given argument. +/// +/// The buffer pointer argument to the `body` closure provides a collection +/// interface to the raw bytes of `value`. The buffer is the size of the +/// instance passed as `value` and does not include any remote storage. +/// +/// - Parameters: +/// - value: An instance to temporarily access through a mutable raw buffer +/// pointer. +/// Note that the `inout` exclusivity rules mean that, like any other +/// `inout` argument, `value` cannot be directly accessed by other code +/// for the duration of `body`. Access must only occur through the pointer +/// argument to `body` until `body` returns. +/// - body: A closure that takes a raw buffer pointer to the bytes of `value` +/// as its sole argument. If the closure has a return value, that value is +/// also used as the return value of the `withUnsafeMutableBytes(of:_:)` +/// function. The buffer pointer argument is valid only for the duration +/// of the closure's execution. +/// - Returns: The return value, if any, of the `body` closure. +@inlinable +public func withUnsafeMutableBytes( + of value: inout T, + _ body: (UnsafeMutableRawBufferPointer) throws -> Result +) rethrows -> Result +{ + return try withUnsafeMutablePointer(to: &value) { + return try body(UnsafeMutableRawBufferPointer( + start: $0, count: MemoryLayout.size)) + } +} + +/// Invokes the given closure with a buffer pointer covering the raw bytes of +/// the given argument. +/// +/// The buffer pointer argument to the `body` closure provides a collection +/// interface to the raw bytes of `value`. The buffer is the size of the +/// instance passed as `value` and does not include any remote storage. +/// +/// - Parameters: +/// - value: An instance to temporarily access through a raw buffer pointer. +/// Note that the `inout` exclusivity rules mean that, like any other +/// `inout` argument, `value` cannot be directly accessed by other code +/// for the duration of `body`. Access must only occur through the pointer +/// argument to `body` until `body` returns. +/// - body: A closure that takes a raw buffer pointer to the bytes of `value` +/// as its sole argument. If the closure has a return value, that value is +/// also used as the return value of the `withUnsafeBytes(of:_:)` +/// function. The buffer pointer argument is valid only for the duration +/// of the closure's execution. It is undefined behavior to attempt to +/// mutate through the pointer by conversion to +/// `UnsafeMutableRawBufferPointer` or any other mutable pointer type. +/// If you want to mutate a value by writing through a pointer, use +/// `withUnsafeMutableBytes(of:_:)` instead. +/// - Returns: The return value, if any, of the `body` closure. +@inlinable +public func withUnsafeBytes( + of value: inout T, + _ body: (UnsafeRawBufferPointer) throws -> Result +) rethrows -> Result +{ + return try withUnsafePointer(to: &value) { + try body(UnsafeRawBufferPointer(start: $0, count: MemoryLayout.size)) + } +} + +/// Invokes the given closure with a buffer pointer covering the raw bytes of +/// the given argument. +/// +/// This function is similar to `withUnsafeBytes`, except that it +/// doesn't trigger stack protection for the pointer. +@_alwaysEmitIntoClient +public func _withUnprotectedUnsafeBytes( + of value: inout T, + _ body: (UnsafeRawBufferPointer) throws -> Result +) rethrows -> Result +{ + return try _withUnprotectedUnsafePointer(to: &value) { + try body(UnsafeRawBufferPointer(start: $0, count: MemoryLayout.size)) + } +} + +/// Invokes the given closure with a buffer pointer covering the raw bytes of +/// the given argument. +/// +/// The buffer pointer argument to the `body` closure provides a collection +/// interface to the raw bytes of `value`. The buffer is the size of the +/// instance passed as `value` and does not include any remote storage. +/// +/// - Parameters: +/// - value: An instance to temporarily access through a raw buffer pointer. +/// - body: A closure that takes a raw buffer pointer to the bytes of `value` +/// as its sole argument. If the closure has a return value, that value is +/// also used as the return value of the `withUnsafeBytes(of:_:)` +/// function. The buffer pointer argument is valid only for the duration +/// of the closure's execution. It is undefined behavior to attempt to +/// mutate through the pointer by conversion to +/// `UnsafeMutableRawBufferPointer` or any other mutable pointer type. +/// If you want to mutate a value by writing through a pointer, use +/// `withUnsafeMutableBytes(of:_:)` instead. +/// - Returns: The return value, if any, of the `body` closure. +@inlinable +public func withUnsafeBytes( + of value: T, + _ body: (UnsafeRawBufferPointer) throws -> Result +) rethrows -> Result { + let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) + let buffer = UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) + return try body(buffer) +} + +/// Invokes the given closure with a buffer pointer covering the raw bytes of +/// the given argument. +/// +/// This function is similar to `withUnsafeBytes`, except that it +/// doesn't trigger stack protection for the pointer. +@_alwaysEmitIntoClient +public func _withUnprotectedUnsafeBytes( + of value: T, + _ body: (UnsafeRawBufferPointer) throws -> Result +) rethrows -> Result { +#if $BuiltinUnprotectedAddressOf + let addr = UnsafeRawPointer(Builtin.unprotectedAddressOfBorrow(value)) +#else + let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) +#endif + let buffer = UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) + return try body(buffer) +} + +@available(*, unavailable) +extension UnsafeRawBufferPointer: Sendable { } +@available(*, unavailable) +extension UnsafeRawBufferPointer.Iterator: Sendable { } +@available(*, unavailable) +extension UnsafeMutableRawBufferPointer: Sendable { } + + +// Local Variables: +// eval: (read-only-mode 1) +// End: From 7f816c7e59d123bbb3bbe51117c4fd4bff25a556 Mon Sep 17 00:00:00 2001 From: Kobe Date: Fri, 17 Nov 2023 11:18:12 +0900 Subject: [PATCH 06/35] [stdlib]Delete unnecessary file. - Modified: stdlib/public/core/UnsafeRawBufferPointer.swift --- .../public/core/UnsafeRawBufferPointer.swift | 1821 ----------------- 1 file changed, 1821 deletions(-) delete mode 100644 stdlib/public/core/UnsafeRawBufferPointer.swift diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift b/stdlib/public/core/UnsafeRawBufferPointer.swift deleted file mode 100644 index ff4d216b85ca2..0000000000000 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift +++ /dev/null @@ -1,1821 +0,0 @@ -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1) -//===--- UnsafeRawBufferPointer.swift.gyb ---------------------*- swift -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 14) -@available(*, unavailable, renamed: "UnsafeMutableRawBufferPointer") -typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 19) - -/// A mutable nonowning collection interface to the bytes in a -/// region of memory. -/// -/// You can use an `UnsafeMutableRawBufferPointer` instance in low-level operations to eliminate -/// uniqueness checks and release mode bounds checks. Bounds checks are always -/// performed in debug mode. -/// -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 28) -/// An `UnsafeMutableRawBufferPointer` instance is a view of the raw bytes in a region of memory. -/// Each byte in memory is viewed as a `UInt8` value independent of the type -/// of values held in that memory. Reading from and writing to memory through -/// a raw buffer are untyped operations. Accessing this collection's bytes -/// does not bind the underlying memory to `UInt8`. -/// -/// In addition to its collection interface, an `UnsafeMutableRawBufferPointer` -/// instance also supports the following methods provided by -/// `UnsafeMutableRawPointer`, including bounds checks in debug mode: -/// -/// - `load(fromByteOffset:as:)` -/// - `loadUnaligned(fromByteOffset:as:)` -/// - `storeBytes(of:toByteOffset:as:)` -/// - `copyMemory(from:)` -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 53) -/// -/// To access the underlying memory through typed operations, the memory must -/// be bound to a trivial type. -/// -/// - Note: A *trivial type* can be copied bit for bit with no 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. Copying memory that -/// contains values of nontrivial types can only be done safely with a typed -/// pointer. Copying bytes directly from nontrivial, in-memory values does -/// not produce valid copies and can only be done by calling a C API, such as -/// `memmove()`. -/// -/// UnsafeMutableRawBufferPointer Semantics -/// ================= -/// -/// An `UnsafeMutableRawBufferPointer` instance is a view into memory and does not own the memory -/// that it references. Copying a variable or constant of type `UnsafeMutableRawBufferPointer` does -/// not copy the underlying memory. However, initializing another collection -/// with an `UnsafeMutableRawBufferPointer` instance copies bytes out of the referenced memory and -/// into the new collection. -/// -/// The following example uses `someBytes`, an `UnsafeMutableRawBufferPointer` instance, to -/// demonstrate the difference between assigning a buffer pointer and using a -/// buffer pointer as the source for another collection's elements. Here, the -/// assignment to `destBytes` creates a new, nonowning buffer pointer -/// covering the first `n` bytes of the memory that `someBytes` -/// references---nothing is copied: -/// -/// var destBytes = someBytes[0..= 0, "UnsafeMutableRawBufferPointer with negative count") - _debugPrecondition(count == 0 || start != nil, - "UnsafeMutableRawBufferPointer has a nil start and nonzero count") - _position = start - _end = start.map { $0 + _assumeNonNegative(count) } - } -} - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 171) -extension UnsafeMutableRawBufferPointer { - public typealias Iterator = UnsafeRawBufferPointer.Iterator -} -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 175) - -extension UnsafeMutableRawBufferPointer: Sequence { - public typealias SubSequence = Slice - - /// Returns an iterator over the bytes of this sequence. - @inlinable - public func makeIterator() -> Iterator { - return Iterator(_position: _position, _end: _end) - } - - /// Copies the elements of `self` to the memory at `destination.baseAddress`, - /// stopping when either `self` or `destination` is exhausted. - /// - /// - Returns: an iterator over any remaining elements of `self` and the - /// number of elements copied. - @inlinable // unsafe-performance - @_alwaysEmitIntoClient - public func _copyContents( - initializing destination: UnsafeMutableBufferPointer - ) -> (Iterator, UnsafeMutableBufferPointer.Index) { - guard let s = _position, let e = _end, e > s, !destination.isEmpty else { - return (makeIterator(), 0) - } - let destinationAddress = destination.baseAddress._unsafelyUnwrappedUnchecked - let d = UnsafeMutableRawPointer(destinationAddress) - let n = Swift.min(destination.count, s.distance(to: e)) - d.copyMemory(from: s, byteCount: n) - return (Iterator(_position: s.advanced(by: n), _end: e), n) - } -} - -extension UnsafeMutableRawBufferPointer: MutableCollection { - // TODO: Specialize `index` and `formIndex` and - // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. - public typealias Element = UInt8 - public typealias Index = Int - public typealias Indices = Range - - /// Always zero, which is the index of the first byte in a nonempty buffer. - @inlinable - public var startIndex: Index { - return 0 - } - - /// The "past the end" position---that is, the position one greater than the - /// last valid subscript argument. - /// - /// The `endIndex` property of an `UnsafeMutableRawBufferPointer` - /// instance is always identical to `count`. - @inlinable - public var endIndex: Index { - return count - } - - @inlinable - public var indices: Indices { - // Not checked because init forbids negative count. - return Indices(uncheckedBounds: (startIndex, endIndex)) - } - - /// Accesses the byte at the given offset in the memory region as a `UInt8` - /// value. - /// - /// - Parameter i: The offset of the byte to access. `i` must be in the range - /// `0.. Element { - get { - _debugPrecondition(i >= 0) - _debugPrecondition(i < endIndex) - return _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 248) - nonmutating set { - _debugPrecondition(i >= 0) - _debugPrecondition(i < endIndex) - _position._unsafelyUnwrappedUnchecked.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 254) - } - - /// Accesses the bytes in the specified memory region. - /// - /// - Parameter bounds: The range of byte offsets to access. The upper and - /// lower bounds of the range must be in the range `0...count`. - @inlinable - public subscript(bounds: Range) -> SubSequence { - get { - _debugPrecondition(bounds.lowerBound >= startIndex) - _debugPrecondition(bounds.upperBound <= endIndex) - return Slice(base: self, bounds: bounds) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 268) - nonmutating set { - _debugPrecondition(bounds.lowerBound >= startIndex) - _debugPrecondition(bounds.upperBound <= endIndex) - _debugPrecondition(bounds.count == newValue.count) - - if !newValue.isEmpty { - (baseAddress! + bounds.lowerBound).copyMemory( - from: newValue.base.baseAddress! + newValue.startIndex, - byteCount: newValue.count) - } - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 280) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 283) - /// Exchanges the byte values at the specified indices - /// in this buffer's memory. - /// - /// Both parameters must be valid indices of the buffer, and not - /// equal to `endIndex`. Passing the same index as both `i` and `j` has no - /// effect. - /// - /// - Parameters: - /// - i: The index of the first byte to swap. - /// - j: The index of the second byte to swap. - @inlinable - public func swapAt(_ i: Int, _ j: Int) { - guard i != j else { return } - _debugPrecondition(i >= 0 && j >= 0) - _debugPrecondition(i < endIndex && j < endIndex) - let pi = (_position! + i) - let pj = (_position! + j) - let tmp = pi.load(fromByteOffset: 0, as: UInt8.self) - pi.copyMemory(from: pj, byteCount: MemoryLayout.size) - pj.storeBytes(of: tmp, toByteOffset: 0, as: UInt8.self) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 306) - /// The number of bytes in the buffer. - /// - /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, - /// a buffer can have a `count` of zero even with a non-`nil` base address. - @inlinable - public var count: Int { - if let pos = _position { - // Unsafely unwrapped because init forbids end being nil if _position - // isn't. - _internalInvariant(_end != nil) - return _assumeNonNegative(_end._unsafelyUnwrappedUnchecked - pos) - } - return 0 - } -} - -extension UnsafeMutableRawBufferPointer: RandomAccessCollection { } - -extension UnsafeMutableRawBufferPointer { -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 326) - /// Allocates uninitialized memory with the specified size and alignment. - /// - /// You are in charge of managing the allocated memory. Be sure to deallocate - /// any memory that you manually allocate. - /// - /// The allocated memory is not bound to any specific type and must be bound - /// before performing any typed operations. If you are using the memory for - /// a specific type, allocate memory using the - /// `UnsafeMutablePointerBuffer.allocate(capacity:)` static method instead. - /// - /// - Parameters: - /// - byteCount: The number of bytes to allocate. `byteCount` must not be - /// negative. - /// - alignment: The alignment of the new region of allocated memory, in - /// bytes. `alignment` must be a whole power of 2. - /// - Returns: A buffer pointer to a newly allocated region of memory aligned - /// to `alignment`. - @inlinable - public static func allocate( - byteCount: Int, alignment: Int - ) -> UnsafeMutableRawBufferPointer { - let base = UnsafeMutableRawPointer.allocate( - byteCount: byteCount, alignment: alignment) - return UnsafeMutableRawBufferPointer(start: base, count: byteCount) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 352) - - /// Deallocates the memory block previously allocated at this buffer pointer’s - /// base address. - /// - /// This buffer pointer's `baseAddress` must be `nil` or a pointer to a memory - /// block previously returned by a Swift allocation method. If `baseAddress` is - /// `nil`, this function does nothing. Otherwise, the memory must not be initialized - /// or `Pointee` must be a trivial type. This buffer pointer's byte `count` must - /// be equal to the originally allocated size of the memory block. - @inlinable - public func deallocate() { - _position?.deallocate() - } - - /// Returns a new instance of the given type, read from the buffer pointer's - /// raw memory at the specified byte offset. - /// - /// The memory at `offset` bytes from this buffer pointer's `baseAddress` - /// must be properly aligned for accessing `T` and initialized to `T` or - /// another type that is layout compatible with `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. - @inlinable - public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { - _debugPrecondition(offset >= 0, "UnsafeMutableRawBufferPointer.load with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeMutableRawBufferPointer.load out of bounds") - 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 fourth through seventh bytes. - /// - /// let a = someBytes.loadUnaligned(as: Int32.self) - /// let b = someBytes.loadUnaligned(fromByteOffset: 3, 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 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, "UnsafeMutableRawBufferPointer.load with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeMutableRawBufferPointer.load out of bounds") - return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 446) - /// Stores a value's bytes into the buffer pointer's raw memory at the - /// specified byte offset. - /// - /// 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`. - /// - /// The memory written to 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`. - /// - /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is - /// initialized to the raw bytes of `value`. If the memory is bound to a - /// type `U` that is layout compatible with `T`, then it contains a value of - /// 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 - /// writing bytes from the value. 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`. - @inlinable - @_alwaysEmitIntoClient - // This custom silgen name is chosen to not interfere with the old ABI - @_silgen_name("_swift_se0349_UnsafeMutableRawBufferPointer_storeBytes") - public func storeBytes( - of value: T, toByteOffset offset: Int = 0, as type: T.Type - ) { - _debugPrecondition(offset >= 0, "UnsafeMutableRawBufferPointer.storeBytes with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeMutableRawBufferPointer.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 linked against the stdlib 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, "UnsafeMutableRawBufferPointer.storeBytes with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeMutableRawBufferPointer.storeBytes out of bounds") - - baseAddress!._legacy_se0349_storeBytes_internal( - of: value, toByteOffset: offset, as: T.self - ) - } - - /// Copies the bytes from the given buffer to this buffer's memory. - /// - /// If the `source.count` bytes of memory referenced by this buffer are bound - /// to a type `T`, then `T` must be a trivial type, the underlying pointer - /// must be properly aligned for accessing `T`, and `source.count` must be a - /// multiple of `MemoryLayout.stride`. - /// - /// The memory referenced by `source` may overlap with the memory referenced - /// by this buffer. - /// - /// After calling `copyMemory(from:)`, the first `source.count` bytes of - /// memory referenced by this buffer are initialized to raw bytes. If the - /// memory is bound to type `T`, then it contains values of type `T`. - /// - /// - Parameter source: A buffer of raw bytes. `source.count` must - /// be less than or equal to this buffer's `count`. - @inlinable - public func copyMemory(from source: UnsafeRawBufferPointer) { - _debugPrecondition(source.count <= self.count, - "UnsafeMutableRawBufferPointer.copyMemory source has too many elements") - if let baseAddress = baseAddress, let sourceAddress = source.baseAddress { - baseAddress.copyMemory(from: sourceAddress, byteCount: source.count) - } - } - - /// Copies from a collection of `UInt8` into this buffer's memory. - /// - /// If the first `source.count` bytes of memory referenced by this buffer - /// are bound to a type `T`, then `T` must be a trivial type, - /// the underlying pointer must be properly aligned for accessing `T`, - /// and `source.count` must be a multiple of `MemoryLayout.stride`. - /// - /// After calling `copyBytes(from:)`, the first `source.count` bytes of memory - /// referenced by this buffer are initialized to raw bytes. If the memory is - /// bound to type `T`, then it contains values of type `T`. - /// - /// - Parameter source: A collection of `UInt8` elements. `source.count` must - /// be less than or equal to this buffer's `count`. - @inlinable - public func copyBytes( - from source: C - ) where C.Element == UInt8 { - guard let position = _position else { - return - } - - if source.withContiguousStorageIfAvailable({ - (buffer: UnsafeBufferPointer) -> Void in - _debugPrecondition(source.count <= self.count, - "UnsafeMutableRawBufferPointer.copyBytes source has too many elements") - if let base = buffer.baseAddress { - position.copyMemory(from: base, byteCount: buffer.count) - } - }) != nil { - return - } - - for (index, byteValue) in source.enumerated() { - _debugPrecondition(index < self.count, - "UnsafeMutableRawBufferPointer.copyBytes source has too many elements") - position.storeBytes( - of: byteValue, toByteOffset: index, as: UInt8.self) - } - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 577) - - /// Creates a new buffer over the same memory as the given buffer. - /// - /// - Parameter bytes: The buffer to convert. - @inlinable - public init(_ bytes: UnsafeMutableRawBufferPointer) { - self.init(start: bytes.baseAddress, count: bytes.count) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 587) - /// Creates a new mutable buffer over the same memory as the given buffer. - /// - /// - Parameter bytes: The buffer to convert. - @inlinable - public init(mutating bytes: UnsafeRawBufferPointer) { - self.init(start: UnsafeMutableRawPointer(mutating: bytes.baseAddress), - count: bytes.count) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 604) - - /// Creates a raw buffer over the contiguous bytes in the given typed buffer. - /// - /// - Parameter buffer: The typed buffer to convert to a raw buffer. The - /// buffer's type `T` must be a trivial type. - @inlinable - public init(_ buffer: UnsafeMutableBufferPointer) { - self.init(start: buffer.baseAddress, - count: buffer.count * MemoryLayout.stride) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 626) - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 666) - - /// Creates a raw buffer over the same memory as the given raw buffer slice, - /// with the indices rebased to zero. - /// - /// The new buffer represents the same region of memory as the slice, but its - /// indices start at zero instead of at the beginning of the slice in the - /// original buffer. The following code creates `slice`, a slice covering - /// part of an existing buffer instance, then rebases it into a new `rebased` - /// buffer. - /// - /// let slice = buffer[n...] - /// let rebased = UnsafeRawBufferPointer(rebasing: slice) - /// - /// After this code has executed, the following are true: - /// - /// - `rebased.startIndex == 0` - /// - `rebased[0] == slice[n]` - /// - `rebased[0] == buffer[n]` - /// - `rebased.count == slice.count` - /// - /// - Parameter slice: The raw buffer slice to rebase. - @inlinable - public init(rebasing slice: Slice) { - let base = slice.base.baseAddress?.advanced(by: slice.startIndex) - let count = slice.endIndex &- slice.startIndex - self.init(start: base, count: count) - } - - /// A pointer to the first byte of the buffer. - /// - /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, - /// a buffer can have a `count` of zero even with a non-`nil` base address. - @inlinable - public var baseAddress: UnsafeMutableRawPointer? { - return _position - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 704) - - /// Initializes the memory referenced by this buffer with the given value, - /// binds the memory to the value's type, and returns a typed buffer of the - /// initialized memory. - /// - /// The memory referenced by this buffer must be uninitialized or - /// initialized to a trivial type, and must be properly aligned for - /// accessing `T`. - /// - /// After calling this method on a raw buffer with non-nil `baseAddress` `b`, - /// the region starting at `b` and continuing up to - /// `b + self.count - self.count % MemoryLayout.stride` is bound - /// to type `T` and is initialized. If `T` is a nontrivial type, you must - /// eventually deinitialize or move the values in this region to avoid leaks. - /// If `baseAddress` is `nil`, this function does nothing - /// and returns an empty buffer pointer. - /// - /// - Parameters: - /// - type: The type to bind this buffer’s memory to. - /// - repeatedValue: The instance to copy into memory. - /// - Returns: A typed buffer of the memory referenced by this raw buffer. - /// The typed buffer contains `self.count / MemoryLayout.stride` - /// instances of `T`. - @inlinable - @discardableResult - public func initializeMemory(as type: T.Type, repeating repeatedValue: T) - -> UnsafeMutableBufferPointer { - guard let base = _position else { - return .init(start: nil, count: 0) - } - - let count = (_end._unsafelyUnwrappedUnchecked-base) / MemoryLayout.stride - let initialized = base.initializeMemory( - as: type, repeating: repeatedValue, count: count - ) - return .init(start: initialized, count: count) - } - - /// Initializes the buffer's memory with the given elements, binding the - /// initialized memory to the elements' type. - /// - /// When calling the `initializeMemory(as:from:)` method on a buffer `b`, - /// the memory referenced by `b` must be uninitialized or initialized to a - /// trivial type, and must be properly aligned for accessing `S.Element`. - /// The buffer must contain sufficient memory to accommodate - /// `source.underestimatedCount`. - /// - /// This method initializes the buffer with elements from `source` until - /// `source` is exhausted or, if `source` is a sequence but not a collection, - /// the buffer has no more room for source's elements. After calling - /// `initializeMemory(as:from:)`, the memory referenced by the returned - /// `UnsafeMutableBufferPointer` instance is bound and initialized to type - /// `S.Element`. This method does not change - /// the binding state of the unused portion of `b`, if any. - /// - /// - Parameters: - /// - type: The type of element to which this buffer's memory will be bound. - /// - source: A sequence of elements with which to initialize the buffer. - /// - Returns: An iterator to any elements of `source` that didn't fit in the - /// buffer, and a typed buffer of the written elements. The returned - /// buffer references memory starting at the same base address as this - /// buffer. - @inlinable - public func initializeMemory( - as type: S.Element.Type, from source: S - ) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer) { - var it = source.makeIterator() - var idx = startIndex - let elementStride = MemoryLayout.stride - - // This has to be a debug precondition due to the cost of walking over some collections. - _debugPrecondition(source.underestimatedCount <= (count / elementStride), - "insufficient space to accommodate source.underestimatedCount elements") - guard let base = baseAddress else { - // this can be a precondition since only an invalid argument should be costly - _precondition(source.underestimatedCount == 0, - "no memory available to initialize from source") - return (it, UnsafeMutableBufferPointer(start: nil, count: 0)) - } - - _debugPrecondition( - Int(bitPattern: base) % MemoryLayout.stride == 0, - "buffer base address must be properly aligned to access S.Element" - ) - - _internalInvariant(_end != nil) - for p in stride(from: base, - // only advance to as far as the last element that will fit - to: _end._unsafelyUnwrappedUnchecked - elementStride + 1, - by: elementStride - ) { - // underflow is permitted -- e.g. a sequence into - // the spare capacity of an Array buffer - guard let x = it.next() else { break } - p.initializeMemory(as: S.Element.self, repeating: x, count: 1) - formIndex(&idx, offsetBy: elementStride) - } - - return (it, UnsafeMutableBufferPointer( - start: base.assumingMemoryBound(to: S.Element.self), - count: idx / elementStride)) - } - - /// Initializes the buffer's memory with every element of the source, - /// binding the initialized memory to the elements' type. - /// - /// When calling the `initializeMemory(as:fromContentsOf:)` method, - /// the memory referenced by the buffer must be uninitialized, or initialized - /// to a trivial type. The buffer must reference enough memory to store - /// `source.count` elements, and its `baseAddress` must be properly aligned - /// for accessing `C.Element`. - /// - /// This method initializes the buffer with the contents of `source` - /// until `source` is exhausted. - /// After calling `initializeMemory(as:fromContentsOf:)`, the memory - /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound - /// to the type `C.Element` and is initialized. This method does not change - /// the binding state of the unused portion of the buffer, if any. - /// - /// - Note: The memory regions referenced by `source` and this buffer - /// must not overlap. - /// - /// - Parameters: - /// - type: The type of element to which this buffer's memory will be bound. - /// - source: A collection of elements to be used to - /// initialize the buffer's storage. - /// - Returns: A typed buffer referencing the initialized elements. - /// The returned buffer references memory starting at the same - /// base address as this buffer, and its count is equal to `source.count` - @inlinable - @_alwaysEmitIntoClient - public func initializeMemory( - as type: C.Element.Type, - fromContentsOf source: C - ) -> UnsafeMutableBufferPointer { - let buffer: UnsafeMutableBufferPointer? - buffer = source.withContiguousStorageIfAvailable { - guard let sourceAddress = $0.baseAddress, !$0.isEmpty else { - return .init(start: nil, count: 0) - } - _debugPrecondition( - Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, - "buffer base address must be properly aligned to access C.Element" - ) - _precondition( - $0.count * MemoryLayout.stride <= self.count, - "buffer cannot contain every element from source collection." - ) - let start = baseAddress?.initializeMemory( - as: C.Element.self, from: sourceAddress, count: $0.count - ) - return .init(start: start, count: $0.count) - } - if let buffer { - return buffer - } - - guard let base = baseAddress else { - _precondition( - source.isEmpty, - "buffer cannot contain every element from source collection." - ) - return .init(start: nil, count: 0) - } - _internalInvariant(_end != nil) - _debugPrecondition( - Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, - "buffer base address must be properly aligned to access C.Element" - ) - var iterator = source.makeIterator() - var element = base - var initialized = 0 - let end = _end._unsafelyUnwrappedUnchecked - MemoryLayout.stride - while element <= end { - guard let value = iterator.next() else { - return .init(start: .init(base._rawValue), count: initialized) - } - element.initializeMemory(as: C.Element.self, to: value) - element = element.advanced(by: MemoryLayout.stride) - initialized += 1 - } - _precondition( - iterator.next() == nil, - "buffer cannot contain every element from source collection." - ) - return .init(start: .init(base._rawValue), count: initialized) - } - - /// Moves every element of an initialized source buffer into the - /// uninitialized memory referenced by this buffer, leaving the source memory - /// uninitialized and this buffer's memory initialized. - /// - /// When calling the `moveInitializeMemory(as:fromContentsOf:)` method, - /// the memory referenced by the buffer must be uninitialized, or initialized - /// to a trivial type. The buffer must reference enough memory to store - /// `source.count` elements, and its `baseAddress` must be properly aligned - /// for accessing `C.Element`. After the method returns, - /// the memory referenced by the returned buffer is initialized and the - /// memory region underlying `source` is uninitialized. - /// - /// This method initializes the buffer with the contents of `source` - /// until `source` is exhausted. - /// After calling `initializeMemory(as:fromContentsOf:)`, the memory - /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound - /// to the type `T` and is initialized. This method does not change - /// the binding state of the unused portion of the buffer, if any. - /// - /// - Note: The memory regions referenced by `source` and this buffer - /// may overlap. - /// - /// - Parameters: - /// - type: The type of element to which this buffer's memory will be bound. - /// - source: A buffer referencing the values to copy. - /// The memory region underlying `source` must be initialized. - /// - Returns: A typed buffer referencing the initialized elements. - /// The returned buffer references memory starting at the same - /// base address as this buffer, and its count is equal to `source.count`. - @discardableResult - @inlinable - @_alwaysEmitIntoClient - public func moveInitializeMemory( - as type: T.Type, - fromContentsOf source: UnsafeMutableBufferPointer - ) -> UnsafeMutableBufferPointer { - guard let sourceAddress = source.baseAddress, !source.isEmpty else { - return .init(start: nil, count: 0) - } - _debugPrecondition( - Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, - "buffer base address must be properly aligned to access T" - ) - _precondition( - source.count * MemoryLayout.stride <= self.count, - "buffer cannot contain every element from source." - ) - let initialized = baseAddress?.moveInitializeMemory( - as: T.self, from: sourceAddress, count: source.count - ) - return .init(start: initialized, count: source.count) - } - - /// Moves every element of an initialized source buffer slice into the - /// uninitialized memory referenced by this buffer, leaving the source memory - /// uninitialized and this buffer's memory initialized. - /// - /// When calling the `moveInitializeMemory(as:fromContentsOf:)` method, - /// the memory referenced by the buffer must be uninitialized, or initialized - /// to a trivial type. The buffer must reference enough memory to store - /// `source.count` elements, and its `baseAddress` must be properly aligned - /// for accessing `C.Element`. After the method returns, - /// the memory referenced by the returned buffer is initialized and the - /// memory region underlying `source` is uninitialized. - /// - /// This method initializes the buffer with the contents of `source` - /// until `source` is exhausted. - /// After calling `initializeMemory(as:fromContentsOf:)`, the memory - /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound - /// to the type `T` and is initialized. This method does not change - /// the binding state of the unused portion of the buffer, if any. - /// - /// - Note: The memory regions referenced by `source` and this buffer - /// may overlap. - /// - /// - Parameters: - /// - type: The type of element to which this buffer's memory will be bound. - /// - source: A buffer referencing the values to copy. - /// The memory region underlying `source` must be initialized. - /// - Returns: A typed buffer referencing the initialized elements. - /// The returned buffer references memory starting at the same - /// base address as this buffer, and its count is equal to `source.count`. - @discardableResult - @inlinable - @_alwaysEmitIntoClient - public func moveInitializeMemory( - as type: T.Type, - fromContentsOf source: Slice> - ) -> UnsafeMutableBufferPointer { - let rebased = UnsafeMutableBufferPointer(rebasing: source) - return moveInitializeMemory(as: T.self, fromContentsOf: rebased) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 986) - - /// Binds this buffer’s memory to the specified type and returns a typed buffer - /// of the bound memory. - /// - /// Use the `bindMemory(to:)` method to bind the memory referenced - /// by this buffer to the type `T`. The memory must be uninitialized or - /// initialized to a type that is layout compatible with `T`. If the memory - /// is uninitialized, it is still uninitialized after being bound to `T`. - /// - /// - Warning: A memory location may only be bound to one type at a time. The - /// behavior of accessing memory as a type unrelated to its bound type is - /// undefined. - /// - /// - Parameters: - /// - type: The type `T` to bind the memory to. - /// - Returns: A typed buffer of the newly bound memory. The memory in this - /// region is bound to `T`, but has not been modified in any other way. - /// The typed buffer references `self.count / MemoryLayout.stride` - /// instances of `T`. - @_transparent - @discardableResult - public func bindMemory( - to type: T.Type - ) -> UnsafeMutableBufferPointer { - guard let base = _position else { - return UnsafeMutableBufferPointer(start: nil, count: 0) - } - - let capacity = count / MemoryLayout.stride - Builtin.bindMemory(base._rawValue, capacity._builtinWordValue, type) - return UnsafeMutableBufferPointer( - start: UnsafeMutablePointer(base._rawValue), count: capacity) - } - - /// Executes the given closure while temporarily binding the buffer to - /// instances of type `T`. - /// - /// Use this method when you have a buffer to raw memory and you need - /// to access that memory as instances of a given type `T`. Accessing - /// memory as a type `T` requires that the memory be bound to that type. - /// A memory location may only be bound to one type at a time, so accessing - /// the same memory as an unrelated type without first rebinding the memory - /// is undefined. - /// - /// Any instance of `T` within the re-bound region may be initialized or - /// uninitialized. The memory underlying any individual instance of `T` - /// must have the same initialization state (i.e. initialized or - /// uninitialized.) Accessing a `T` whose underlying memory - /// is in a mixed initialization state shall be undefined behaviour. - /// - /// If the byte count of the original buffer is not a multiple of - /// the stride of `T`, then the re-bound buffer is shorter - /// than the original buffer. - /// - /// After executing `body`, this method rebinds memory back to its original - /// binding state. This can be unbound memory, or bound to a different type. - /// - /// - Note: The buffer's base address must match the - /// alignment of `T` (as reported by `MemoryLayout.alignment`). - /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` - /// must equal zero. - /// - /// - Note: A raw buffer may represent memory that has been bound to a type. - /// If that is the case, then `T` must be layout compatible with the - /// type to which the memory has been bound. This requirement does not - /// apply if the raw buffer represents memory that has not been bound - /// to any type. - /// - /// - Parameters: - /// - type: The type to temporarily bind the memory referenced by this - /// buffer. - /// - body: A closure that takes a typed pointer to the - /// same memory as this pointer, only bound to type `T`. The closure's - /// pointer argument is valid only for the duration of the closure's - /// execution. If `body` has a return value, that value is also used as - /// the return value for the `withMemoryRebound(to:capacity:_:)` method. - /// - buffer: The buffer temporarily bound to instances of `T`. - /// - Returns: The return value, if any, of the `body` closure parameter. - @inlinable - @_alwaysEmitIntoClient - public func withMemoryRebound( - to type: T.Type, - _ body: (_ buffer: UnsafeMutableBufferPointer) throws -> Result - ) rethrows -> Result { - guard let s = _position else { - return try body(.init(start: nil, count: 0)) - } - _debugPrecondition( - Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0, - "baseAddress must be a properly aligned pointer for type T" - ) - // initializer ensures _end is nil only when _position is nil. - _internalInvariant(_end != nil) - let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) - let n = c / MemoryLayout.stride - let binding = Builtin.bindMemory(s._rawValue, n._builtinWordValue, T.self) - defer { Builtin.rebindMemory(s._rawValue, binding) } - return try body(.init(start: .init(s._rawValue), count: n)) - } - - /// Returns a typed buffer to the memory referenced by this buffer, - /// assuming that the memory is already bound to the specified type. - /// - /// Use this method when you have a raw buffer to memory that has already - /// been bound to the specified type. The memory starting at this pointer - /// must be bound to the type `T`. Accessing memory through the returned - /// pointer is undefined if the memory has not been bound to `T`. To bind - /// memory to `T`, use `bindMemory(to:capacity:)` instead of this method. - /// - /// - Note: The buffer's base address must match the - /// alignment of `T` (as reported by `MemoryLayout.alignment`). - /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` - /// must equal zero. - /// - /// - Parameter to: The type `T` that the memory has already been bound to. - /// - Returns: A typed pointer to the same memory as this raw pointer. - @inlinable - @_alwaysEmitIntoClient - public func assumingMemoryBound( - to: T.Type - ) -> UnsafeMutableBufferPointer { - guard let s = _position else { - return .init(start: nil, count: 0) - } - // initializer ensures _end is nil only when _position is nil. - _internalInvariant(_end != nil) - let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) - let n = c / MemoryLayout.stride - return .init(start: .init(s._rawValue), count: n) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1118) - @inlinable - @_alwaysEmitIntoClient - public func withContiguousMutableStorageIfAvailable( - _ body: (inout UnsafeMutableBufferPointer) throws -> R - ) rethrows -> R? { - try withMemoryRebound(to: Element.self) { b in - var buffer = b - defer { - _debugPrecondition( - (b.baseAddress, b.count) == (buffer.baseAddress, buffer.count), - "UnsafeMutableRawBufferPointer.withContiguousMutableStorageIfAvailable: replacing the buffer is not allowed" - ) - } - return try body(&buffer) - } - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1136) - @inlinable - @_alwaysEmitIntoClient - public func withContiguousStorageIfAvailable( - _ body: (UnsafeBufferPointer) throws -> R - ) rethrows -> R? { - try withMemoryRebound(to: Element.self) { - try body(UnsafeBufferPointer($0)) - } - } -} - -@_unavailableInEmbedded -extension UnsafeMutableRawBufferPointer: CustomDebugStringConvertible { - /// A textual representation of the buffer, suitable for debugging. - public var debugDescription: String { - return "UnsafeMutableRawBufferPointer" - + "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))" - } -} - -extension UnsafeMutableRawBufferPointer { - @available(*, unavailable, - message: "use 'UnsafeMutableRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") - public subscript(bounds: Range) -> UnsafeMutableRawBufferPointer { - get { return UnsafeMutableRawBufferPointer(start: nil, count: 0) } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1162) - nonmutating set {} -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1164) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1167) - @available(*, unavailable, - message: "use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") - public subscript(bounds: Range) -> UnsafeRawBufferPointer { - get { return UnsafeRawBufferPointer(start: nil, count: 0) } - nonmutating set {} - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1174) -} - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 19) - -/// A nonowning collection interface to the bytes in a -/// region of memory. -/// -/// You can use an `UnsafeRawBufferPointer` instance in low-level operations to eliminate -/// uniqueness checks and release mode bounds checks. Bounds checks are always -/// performed in debug mode. -/// -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 43) -/// An `UnsafeRawBufferPointer` instance is a view of the raw bytes in a region of memory. -/// Each byte in memory is viewed as a `UInt8` value independent of the type -/// of values held in that memory. Reading from memory through a raw buffer is -/// an untyped operation. -/// -/// In addition to its collection interface, an `UnsafeRawBufferPointer` -/// instance also supports the `load(fromByteOffset:as:)` -/// and `loadUnaligned(fromByteOffset:as:)` methods provided by -/// `UnsafeRawPointer`, including bounds checks in debug mode. -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 53) -/// -/// To access the underlying memory through typed operations, the memory must -/// be bound to a trivial type. -/// -/// - Note: A *trivial type* can be copied bit for bit with no 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. Copying memory that -/// contains values of nontrivial types can only be done safely with a typed -/// pointer. Copying bytes directly from nontrivial, in-memory values does -/// not produce valid copies and can only be done by calling a C API, such as -/// `memmove()`. -/// -/// UnsafeRawBufferPointer Semantics -/// ================= -/// -/// An `UnsafeRawBufferPointer` instance is a view into memory and does not own the memory -/// that it references. Copying a variable or constant of type `UnsafeRawBufferPointer` does -/// not copy the underlying memory. However, initializing another collection -/// with an `UnsafeRawBufferPointer` instance copies bytes out of the referenced memory and -/// into the new collection. -/// -/// The following example uses `someBytes`, an `UnsafeRawBufferPointer` instance, to -/// demonstrate the difference between assigning a buffer pointer and using a -/// buffer pointer as the source for another collection's elements. Here, the -/// assignment to `destBytes` creates a new, nonowning buffer pointer -/// covering the first `n` bytes of the memory that `someBytes` -/// references---nothing is copied: -/// -/// var destBytes = someBytes[0..= 0, "UnsafeRawBufferPointer with negative count") - _debugPrecondition(count == 0 || start != nil, - "UnsafeRawBufferPointer has a nil start and nonzero count") - _position = start - _end = start.map { $0 + _assumeNonNegative(count) } - } -} - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 125) -extension UnsafeRawBufferPointer { - /// An iterator over the bytes viewed by a raw buffer pointer. - @frozen - public struct Iterator { - @usableFromInline - internal var _position, _end: UnsafeRawPointer? - - @inlinable - internal init(_position: UnsafeRawPointer?, _end: UnsafeRawPointer?) { - self._position = _position - self._end = _end - } - } -} - -extension UnsafeRawBufferPointer.Iterator: IteratorProtocol, Sequence { - /// Advances to the next byte and returns it, or `nil` if no next byte - /// exists. - /// - /// Once `nil` has been returned, all subsequent calls return `nil`. - /// - /// - Returns: The next sequential byte in the raw buffer if another byte - /// exists; otherwise, `nil`. - @inlinable - public mutating func next() -> UInt8? { - if _position == _end { return nil } - - // We can do an unchecked unwrap here by borrowing invariants from the pointer. - // For a validly constructed buffer pointer, the only way _position can be nil is - // if _end is also nil. We checked that case above. Thus, we can safely do an - // unchecked unwrap here. - // - // Additionally, validly constructed buffer pointers also have an _end that is - // strictly greater than or equal to _position, and so we do not need to do checked - // arithmetic here as we cannot possibly overflow. - // - // We check these invariants in debug builds to defend against invalidly constructed - // pointers. - _debugPrecondition(_position! < _end!) - let position = _position._unsafelyUnwrappedUnchecked - let result = position.load(as: UInt8.self) - _position = position + 1 - return result - } -} -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 175) - -extension UnsafeRawBufferPointer: Sequence { - public typealias SubSequence = Slice - - /// Returns an iterator over the bytes of this sequence. - @inlinable - public func makeIterator() -> Iterator { - return Iterator(_position: _position, _end: _end) - } - - /// Copies the elements of `self` to the memory at `destination.baseAddress`, - /// stopping when either `self` or `destination` is exhausted. - /// - /// - Returns: an iterator over any remaining elements of `self` and the - /// number of elements copied. - @inlinable // unsafe-performance - @_alwaysEmitIntoClient - public func _copyContents( - initializing destination: UnsafeMutableBufferPointer - ) -> (Iterator, UnsafeMutableBufferPointer.Index) { - guard let s = _position, let e = _end, e > s, !destination.isEmpty else { - return (makeIterator(), 0) - } - let destinationAddress = destination.baseAddress._unsafelyUnwrappedUnchecked - let d = UnsafeMutableRawPointer(destinationAddress) - let n = Swift.min(destination.count, s.distance(to: e)) - d.copyMemory(from: s, byteCount: n) - return (Iterator(_position: s.advanced(by: n), _end: e), n) - } -} - -extension UnsafeRawBufferPointer: Collection { - // TODO: Specialize `index` and `formIndex` and - // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. - public typealias Element = UInt8 - public typealias Index = Int - public typealias Indices = Range - - /// Always zero, which is the index of the first byte in a nonempty buffer. - @inlinable - public var startIndex: Index { - return 0 - } - - /// The "past the end" position---that is, the position one greater than the - /// last valid subscript argument. - /// - /// The `endIndex` property of an `UnsafeRawBufferPointer` - /// instance is always identical to `count`. - @inlinable - public var endIndex: Index { - return count - } - - @inlinable - public var indices: Indices { - // Not checked because init forbids negative count. - return Indices(uncheckedBounds: (startIndex, endIndex)) - } - - /// Accesses the byte at the given offset in the memory region as a `UInt8` - /// value. - /// - /// - Parameter i: The offset of the byte to access. `i` must be in the range - /// `0.. Element { - get { - _debugPrecondition(i >= 0) - _debugPrecondition(i < endIndex) - return _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 254) - } - - /// Accesses the bytes in the specified memory region. - /// - /// - Parameter bounds: The range of byte offsets to access. The upper and - /// lower bounds of the range must be in the range `0...count`. - @inlinable - public subscript(bounds: Range) -> SubSequence { - get { - _debugPrecondition(bounds.lowerBound >= startIndex) - _debugPrecondition(bounds.upperBound <= endIndex) - return Slice(base: self, bounds: bounds) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 280) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 306) - /// The number of bytes in the buffer. - /// - /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, - /// a buffer can have a `count` of zero even with a non-`nil` base address. - @inlinable - public var count: Int { - if let pos = _position { - // Unsafely unwrapped because init forbids end being nil if _position - // isn't. - _internalInvariant(_end != nil) - return _assumeNonNegative(_end._unsafelyUnwrappedUnchecked - pos) - } - return 0 - } -} - -extension UnsafeRawBufferPointer: RandomAccessCollection { } - -extension UnsafeRawBufferPointer { -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 352) - - /// Deallocates the memory block previously allocated at this buffer pointer’s - /// base address. - /// - /// This buffer pointer's `baseAddress` must be `nil` or a pointer to a memory - /// block previously returned by a Swift allocation method. If `baseAddress` is - /// `nil`, this function does nothing. Otherwise, the memory must not be initialized - /// or `Pointee` must be a trivial type. This buffer pointer's byte `count` must - /// be equal to the originally allocated size of the memory block. - @inlinable - public func deallocate() { - _position?.deallocate() - } - - /// Returns a new instance of the given type, read from the buffer pointer's - /// raw memory at the specified byte offset. - /// - /// The memory at `offset` bytes from this buffer pointer's `baseAddress` - /// must be properly aligned for accessing `T` and initialized to `T` or - /// another type that is layout compatible with `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. - @inlinable - public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { - _debugPrecondition(offset >= 0, "UnsafeRawBufferPointer.load with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeRawBufferPointer.load out of bounds") - 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 fourth through seventh bytes. - /// - /// let a = someBytes.loadUnaligned(as: Int32.self) - /// let b = someBytes.loadUnaligned(fromByteOffset: 3, 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 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, "UnsafeRawBufferPointer.load with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeRawBufferPointer.load out of bounds") - return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 577) - - /// Creates a new buffer over the same memory as the given buffer. - /// - /// - Parameter bytes: The buffer to convert. - @inlinable - public init(_ bytes: UnsafeMutableRawBufferPointer) { - self.init(start: bytes.baseAddress, count: bytes.count) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 596) - /// Creates a new buffer over the same memory as the given buffer. - /// - /// - Parameter bytes: The buffer to convert. - @inlinable - public init(_ bytes: UnsafeRawBufferPointer) { - self.init(start: bytes.baseAddress, count: bytes.count) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 604) - - /// Creates a raw buffer over the contiguous bytes in the given typed buffer. - /// - /// - Parameter buffer: The typed buffer to convert to a raw buffer. The - /// buffer's type `T` must be a trivial type. - @inlinable - public init(_ buffer: UnsafeMutableBufferPointer) { - self.init(start: buffer.baseAddress, - count: buffer.count * MemoryLayout.stride) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 616) - /// Creates a raw buffer over the contiguous bytes in the given typed buffer. - /// - /// - Parameter buffer: The typed buffer to convert to a raw buffer. The - /// buffer's type `T` must be a trivial type. - @inlinable - public init(_ buffer: UnsafeBufferPointer) { - self.init(start: buffer.baseAddress, - count: buffer.count * MemoryLayout.stride) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 626) - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 628) - /// Creates a raw buffer over the same memory as the given raw buffer slice, - /// with the indices rebased to zero. - /// - /// The new buffer represents the same region of memory as the slice, but its - /// indices start at zero instead of at the beginning of the slice in the - /// original buffer. The following code creates `slice`, a slice covering - /// part of an existing buffer instance, then rebases it into a new `rebased` - /// buffer. - /// - /// let slice = buffer[n...] - /// let rebased = UnsafeRawBufferPointer(rebasing: slice) - /// - /// After this code has executed, the following are true: - /// - /// - `rebased.startIndex == 0` - /// - `rebased[0] == slice[n]` - /// - `rebased[0] == buffer[n]` - /// - `rebased.count == slice.count` - /// - /// - Parameter slice: The raw buffer slice to rebase. - @inlinable - public init(rebasing slice: Slice) { - // NOTE: `Slice` does not guarantee that its start/end indices are valid - // in `base` -- it merely ensures that `startIndex <= endIndex`. - // We need manually check that we aren't given an invalid slice, - // or the resulting collection would allow access that was - // out-of-bounds with respect to the original base buffer. - // We only do this in debug builds to prevent a measurable performance - // degradation wrt passing around pointers not wrapped in a BufferPointer - // construct. - _debugPrecondition( - slice.startIndex >= 0 && slice.endIndex <= slice.base.count, - "Invalid slice") - let base = slice.base.baseAddress?.advanced(by: slice.startIndex) - let count = slice.endIndex &- slice.startIndex - self.init(start: base, count: count) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 666) - - /// Creates a raw buffer over the same memory as the given raw buffer slice, - /// with the indices rebased to zero. - /// - /// The new buffer represents the same region of memory as the slice, but its - /// indices start at zero instead of at the beginning of the slice in the - /// original buffer. The following code creates `slice`, a slice covering - /// part of an existing buffer instance, then rebases it into a new `rebased` - /// buffer. - /// - /// let slice = buffer[n...] - /// let rebased = UnsafeRawBufferPointer(rebasing: slice) - /// - /// After this code has executed, the following are true: - /// - /// - `rebased.startIndex == 0` - /// - `rebased[0] == slice[n]` - /// - `rebased[0] == buffer[n]` - /// - `rebased.count == slice.count` - /// - /// - Parameter slice: The raw buffer slice to rebase. - @inlinable - public init(rebasing slice: Slice) { - let base = slice.base.baseAddress?.advanced(by: slice.startIndex) - let count = slice.endIndex &- slice.startIndex - self.init(start: base, count: count) - } - - /// A pointer to the first byte of the buffer. - /// - /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, - /// a buffer can have a `count` of zero even with a non-`nil` base address. - @inlinable - public var baseAddress: UnsafeRawPointer? { - return _position - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 986) - - /// Binds this buffer’s memory to the specified type and returns a typed buffer - /// of the bound memory. - /// - /// Use the `bindMemory(to:)` method to bind the memory referenced - /// by this buffer to the type `T`. The memory must be uninitialized or - /// initialized to a type that is layout compatible with `T`. If the memory - /// is uninitialized, it is still uninitialized after being bound to `T`. - /// - /// - Warning: A memory location may only be bound to one type at a time. The - /// behavior of accessing memory as a type unrelated to its bound type is - /// undefined. - /// - /// - Parameters: - /// - type: The type `T` to bind the memory to. - /// - Returns: A typed buffer of the newly bound memory. The memory in this - /// region is bound to `T`, but has not been modified in any other way. - /// The typed buffer references `self.count / MemoryLayout.stride` - /// instances of `T`. - @_transparent - @discardableResult - public func bindMemory( - to type: T.Type - ) -> UnsafeBufferPointer { - guard let base = _position else { - return UnsafeBufferPointer(start: nil, count: 0) - } - - let capacity = count / MemoryLayout.stride - Builtin.bindMemory(base._rawValue, capacity._builtinWordValue, type) - return UnsafeBufferPointer( - start: UnsafePointer(base._rawValue), count: capacity) - } - - /// Executes the given closure while temporarily binding the buffer to - /// instances of type `T`. - /// - /// Use this method when you have a buffer to raw memory and you need - /// to access that memory as instances of a given type `T`. Accessing - /// memory as a type `T` requires that the memory be bound to that type. - /// A memory location may only be bound to one type at a time, so accessing - /// the same memory as an unrelated type without first rebinding the memory - /// is undefined. - /// - /// Any instance of `T` within the re-bound region may be initialized or - /// uninitialized. The memory underlying any individual instance of `T` - /// must have the same initialization state (i.e. initialized or - /// uninitialized.) Accessing a `T` whose underlying memory - /// is in a mixed initialization state shall be undefined behaviour. - /// - /// If the byte count of the original buffer is not a multiple of - /// the stride of `T`, then the re-bound buffer is shorter - /// than the original buffer. - /// - /// After executing `body`, this method rebinds memory back to its original - /// binding state. This can be unbound memory, or bound to a different type. - /// - /// - Note: The buffer's base address must match the - /// alignment of `T` (as reported by `MemoryLayout.alignment`). - /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` - /// must equal zero. - /// - /// - Note: A raw buffer may represent memory that has been bound to a type. - /// If that is the case, then `T` must be layout compatible with the - /// type to which the memory has been bound. This requirement does not - /// apply if the raw buffer represents memory that has not been bound - /// to any type. - /// - /// - Parameters: - /// - type: The type to temporarily bind the memory referenced by this - /// buffer. - /// - body: A closure that takes a typed pointer to the - /// same memory as this pointer, only bound to type `T`. The closure's - /// pointer argument is valid only for the duration of the closure's - /// execution. If `body` has a return value, that value is also used as - /// the return value for the `withMemoryRebound(to:capacity:_:)` method. - /// - buffer: The buffer temporarily bound to instances of `T`. - /// - Returns: The return value, if any, of the `body` closure parameter. - @inlinable - @_alwaysEmitIntoClient - public func withMemoryRebound( - to type: T.Type, - _ body: (_ buffer: UnsafeBufferPointer) throws -> Result - ) rethrows -> Result { - guard let s = _position else { - return try body(.init(start: nil, count: 0)) - } - _debugPrecondition( - Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0, - "baseAddress must be a properly aligned pointer for type T" - ) - // initializer ensures _end is nil only when _position is nil. - _internalInvariant(_end != nil) - let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) - let n = c / MemoryLayout.stride - let binding = Builtin.bindMemory(s._rawValue, n._builtinWordValue, T.self) - defer { Builtin.rebindMemory(s._rawValue, binding) } - return try body(.init(start: .init(s._rawValue), count: n)) - } - - /// Returns a typed buffer to the memory referenced by this buffer, - /// assuming that the memory is already bound to the specified type. - /// - /// Use this method when you have a raw buffer to memory that has already - /// been bound to the specified type. The memory starting at this pointer - /// must be bound to the type `T`. Accessing memory through the returned - /// pointer is undefined if the memory has not been bound to `T`. To bind - /// memory to `T`, use `bindMemory(to:capacity:)` instead of this method. - /// - /// - Note: The buffer's base address must match the - /// alignment of `T` (as reported by `MemoryLayout.alignment`). - /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` - /// must equal zero. - /// - /// - Parameter to: The type `T` that the memory has already been bound to. - /// - Returns: A typed pointer to the same memory as this raw pointer. - @inlinable - @_alwaysEmitIntoClient - public func assumingMemoryBound( - to: T.Type - ) -> UnsafeBufferPointer { - guard let s = _position else { - return .init(start: nil, count: 0) - } - // initializer ensures _end is nil only when _position is nil. - _internalInvariant(_end != nil) - let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) - let n = c / MemoryLayout.stride - return .init(start: .init(s._rawValue), count: n) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1136) - @inlinable - @_alwaysEmitIntoClient - public func withContiguousStorageIfAvailable( - _ body: (UnsafeBufferPointer) throws -> R - ) rethrows -> R? { - try withMemoryRebound(to: Element.self) { - try body($0) - } - } -} - -@_unavailableInEmbedded -extension UnsafeRawBufferPointer: CustomDebugStringConvertible { - /// A textual representation of the buffer, suitable for debugging. - public var debugDescription: String { - return "UnsafeRawBufferPointer" - + "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))" - } -} - -extension UnsafeRawBufferPointer { - @available(*, unavailable, - message: "use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") - public subscript(bounds: Range) -> UnsafeRawBufferPointer { - get { return UnsafeRawBufferPointer(start: nil, count: 0) } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1164) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1174) -} - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1177) - -/// Invokes the given closure with a mutable buffer pointer covering the raw -/// bytes of the given argument. -/// -/// The buffer pointer argument to the `body` closure provides a collection -/// interface to the raw bytes of `value`. The buffer is the size of the -/// instance passed as `value` and does not include any remote storage. -/// -/// - Parameters: -/// - value: An instance to temporarily access through a mutable raw buffer -/// pointer. -/// Note that the `inout` exclusivity rules mean that, like any other -/// `inout` argument, `value` cannot be directly accessed by other code -/// for the duration of `body`. Access must only occur through the pointer -/// argument to `body` until `body` returns. -/// - body: A closure that takes a raw buffer pointer to the bytes of `value` -/// as its sole argument. If the closure has a return value, that value is -/// also used as the return value of the `withUnsafeMutableBytes(of:_:)` -/// function. The buffer pointer argument is valid only for the duration -/// of the closure's execution. -/// - Returns: The return value, if any, of the `body` closure. -@inlinable -public func withUnsafeMutableBytes( - of value: inout T, - _ body: (UnsafeMutableRawBufferPointer) throws -> Result -) rethrows -> Result -{ - return try withUnsafeMutablePointer(to: &value) { - return try body(UnsafeMutableRawBufferPointer( - start: $0, count: MemoryLayout.size)) - } -} - -/// Invokes the given closure with a buffer pointer covering the raw bytes of -/// the given argument. -/// -/// The buffer pointer argument to the `body` closure provides a collection -/// interface to the raw bytes of `value`. The buffer is the size of the -/// instance passed as `value` and does not include any remote storage. -/// -/// - Parameters: -/// - value: An instance to temporarily access through a raw buffer pointer. -/// Note that the `inout` exclusivity rules mean that, like any other -/// `inout` argument, `value` cannot be directly accessed by other code -/// for the duration of `body`. Access must only occur through the pointer -/// argument to `body` until `body` returns. -/// - body: A closure that takes a raw buffer pointer to the bytes of `value` -/// as its sole argument. If the closure has a return value, that value is -/// also used as the return value of the `withUnsafeBytes(of:_:)` -/// function. The buffer pointer argument is valid only for the duration -/// of the closure's execution. It is undefined behavior to attempt to -/// mutate through the pointer by conversion to -/// `UnsafeMutableRawBufferPointer` or any other mutable pointer type. -/// If you want to mutate a value by writing through a pointer, use -/// `withUnsafeMutableBytes(of:_:)` instead. -/// - Returns: The return value, if any, of the `body` closure. -@inlinable -public func withUnsafeBytes( - of value: inout T, - _ body: (UnsafeRawBufferPointer) throws -> Result -) rethrows -> Result -{ - return try withUnsafePointer(to: &value) { - try body(UnsafeRawBufferPointer(start: $0, count: MemoryLayout.size)) - } -} - -/// Invokes the given closure with a buffer pointer covering the raw bytes of -/// the given argument. -/// -/// This function is similar to `withUnsafeBytes`, except that it -/// doesn't trigger stack protection for the pointer. -@_alwaysEmitIntoClient -public func _withUnprotectedUnsafeBytes( - of value: inout T, - _ body: (UnsafeRawBufferPointer) throws -> Result -) rethrows -> Result -{ - return try _withUnprotectedUnsafePointer(to: &value) { - try body(UnsafeRawBufferPointer(start: $0, count: MemoryLayout.size)) - } -} - -/// Invokes the given closure with a buffer pointer covering the raw bytes of -/// the given argument. -/// -/// The buffer pointer argument to the `body` closure provides a collection -/// interface to the raw bytes of `value`. The buffer is the size of the -/// instance passed as `value` and does not include any remote storage. -/// -/// - Parameters: -/// - value: An instance to temporarily access through a raw buffer pointer. -/// - body: A closure that takes a raw buffer pointer to the bytes of `value` -/// as its sole argument. If the closure has a return value, that value is -/// also used as the return value of the `withUnsafeBytes(of:_:)` -/// function. The buffer pointer argument is valid only for the duration -/// of the closure's execution. It is undefined behavior to attempt to -/// mutate through the pointer by conversion to -/// `UnsafeMutableRawBufferPointer` or any other mutable pointer type. -/// If you want to mutate a value by writing through a pointer, use -/// `withUnsafeMutableBytes(of:_:)` instead. -/// - Returns: The return value, if any, of the `body` closure. -@inlinable -public func withUnsafeBytes( - of value: T, - _ body: (UnsafeRawBufferPointer) throws -> Result -) rethrows -> Result { - let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) - let buffer = UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) - return try body(buffer) -} - -/// Invokes the given closure with a buffer pointer covering the raw bytes of -/// the given argument. -/// -/// This function is similar to `withUnsafeBytes`, except that it -/// doesn't trigger stack protection for the pointer. -@_alwaysEmitIntoClient -public func _withUnprotectedUnsafeBytes( - of value: T, - _ body: (UnsafeRawBufferPointer) throws -> Result -) rethrows -> Result { -#if $BuiltinUnprotectedAddressOf - let addr = UnsafeRawPointer(Builtin.unprotectedAddressOfBorrow(value)) -#else - let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) -#endif - let buffer = UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) - return try body(buffer) -} - -@available(*, unavailable) -extension UnsafeRawBufferPointer: Sendable { } -@available(*, unavailable) -extension UnsafeRawBufferPointer.Iterator: Sendable { } -@available(*, unavailable) -extension UnsafeMutableRawBufferPointer: Sendable { } - - -// Local Variables: -// eval: (read-only-mode 1) -// End: From 2573c4d7c37da0c422eb4041d95149019c36cc22 Mon Sep 17 00:00:00 2001 From: Kobe Date: Fri, 17 Nov 2023 11:46:39 +0900 Subject: [PATCH 07/35] [stdlib]Restore the whitespace changes in the file to their original state. - Modified: swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb --- stdlib/public/core/UnsafeRawBufferPointer.swift.gyb | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb index 6f28588ad0589..645f866f3a513 100644 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// %import gyb + @available(*, unavailable, renamed: "UnsafeMutableRawBufferPointer") typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer % for mutable in (True, False): From 0a7c7efcb47309d5732372d4f21b183faa024359 Mon Sep 17 00:00:00 2001 From: Kobe Date: Fri, 17 Nov 2023 13:02:32 +0900 Subject: [PATCH 08/35] [stdlib]Add test case code. - Modified: swift/test/stdlib/UnsafePointerDiagnostics.swift --- test/stdlib/UnsafePointerDiagnostics.swift | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/stdlib/UnsafePointerDiagnostics.swift b/test/stdlib/UnsafePointerDiagnostics.swift index a8d2e1e912617..6a5ff8f74b69c 100644 --- a/test/stdlib/UnsafePointerDiagnostics.swift +++ b/test/stdlib/UnsafePointerDiagnostics.swift @@ -103,26 +103,35 @@ func unsafeRawBufferPointerConversions( mrbp: UnsafeMutableRawBufferPointer, rbp: UnsafeRawBufferPointer, mbpi: UnsafeMutableBufferPointer, - bpi: UnsafeBufferPointer) { + bpi: UnsafeBufferPointer, + rmbp: UnsafeRawMutableBufferPointer) { let omrp: UnsafeMutableRawPointer? = mrp let orp: UnsafeRawPointer? = rp _ = UnsafeMutableRawBufferPointer(start: mrp, count: 1) + _ = UnsafeRawMutableBufferPointer(start: mrp, count: 1) _ = UnsafeRawBufferPointer(start: mrp, count: 1) _ = UnsafeMutableRawBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} + _ = UnsafeRawMutableBufferPointer(start: rp, count: 1) _ = UnsafeRawBufferPointer(start: rp, count: 1) _ = UnsafeMutableRawBufferPointer(mrbp) + _ = UnsafeRawMutableBufferPointer(mrbp) _ = UnsafeRawBufferPointer(mrbp) _ = UnsafeMutableRawBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} + _ = UnsafeRawMutableBufferPointer(rbp) _ = UnsafeRawBufferPointer(rbp) _ = UnsafeMutableRawBufferPointer(mbpi) + _ = UnsafeRawMutableBufferPointer(mbpi) _ = UnsafeRawBufferPointer(mbpi) _ = UnsafeMutableRawBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawBufferPointer'}} + _ = UnsafeRawMutableBufferPointer(bpi) _ = UnsafeRawBufferPointer(bpi) _ = UnsafeMutableRawBufferPointer(start: omrp, count: 1) + _ = UnsafeRawMutableBufferPointer(start: omrp, count: 1) _ = UnsafeRawBufferPointer(start: omrp, count: 1) _ = UnsafeMutableRawBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} + - = UnsafeRawMutableBufferPointer(start: orp, count: 1) _ = UnsafeRawBufferPointer(start: orp, count: 1) } @@ -331,10 +340,14 @@ func unsafePointerInitEphemeralConversions() { _ = UnsafeMutableRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawMutableBufferPointer(start: &foo, count: 0) _ = UnsafeMutableRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawMutableBufferPointer(start: &arr, count: 0) // FIXME: This is currently ambiguous. @@ -365,6 +378,7 @@ func unsafePointerInitNonEphemeralConversions() { _ = UnsafeMutableBufferPointer(start: &global, count: 0) _ = UnsafeRawBufferPointer(start: &global, count: 0) _ = UnsafeMutableRawBufferPointer(start: &global, count: 0) + _ = UnsafeRawMutableBufferPointer(start: &global, count: 0) // FIXME: This is currently ambiguous. _ = OpaquePointer(&global) // expected-error {{ambiguous use of 'init(_:)'}} From 169973f4cad0ab69b010128280e8a85cacabf0c0 Mon Sep 17 00:00:00 2001 From: Kobe Date: Sat, 18 Nov 2023 10:14:20 +0900 Subject: [PATCH 09/35] [stdlib]Delete unnecessary file. - Modified: stdlib/public/core/UnsafeRawBufferPointer.swift --- .../public/core/UnsafeRawBufferPointer.swift | 1821 ----------------- 1 file changed, 1821 deletions(-) delete mode 100644 stdlib/public/core/UnsafeRawBufferPointer.swift diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift b/stdlib/public/core/UnsafeRawBufferPointer.swift deleted file mode 100644 index ff4d216b85ca2..0000000000000 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift +++ /dev/null @@ -1,1821 +0,0 @@ -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1) -//===--- UnsafeRawBufferPointer.swift.gyb ---------------------*- swift -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 14) -@available(*, unavailable, renamed: "UnsafeMutableRawBufferPointer") -typealias UnsafeRawMutableBufferPointer = UnsafeMutableRawBufferPointer -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 19) - -/// A mutable nonowning collection interface to the bytes in a -/// region of memory. -/// -/// You can use an `UnsafeMutableRawBufferPointer` instance in low-level operations to eliminate -/// uniqueness checks and release mode bounds checks. Bounds checks are always -/// performed in debug mode. -/// -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 28) -/// An `UnsafeMutableRawBufferPointer` instance is a view of the raw bytes in a region of memory. -/// Each byte in memory is viewed as a `UInt8` value independent of the type -/// of values held in that memory. Reading from and writing to memory through -/// a raw buffer are untyped operations. Accessing this collection's bytes -/// does not bind the underlying memory to `UInt8`. -/// -/// In addition to its collection interface, an `UnsafeMutableRawBufferPointer` -/// instance also supports the following methods provided by -/// `UnsafeMutableRawPointer`, including bounds checks in debug mode: -/// -/// - `load(fromByteOffset:as:)` -/// - `loadUnaligned(fromByteOffset:as:)` -/// - `storeBytes(of:toByteOffset:as:)` -/// - `copyMemory(from:)` -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 53) -/// -/// To access the underlying memory through typed operations, the memory must -/// be bound to a trivial type. -/// -/// - Note: A *trivial type* can be copied bit for bit with no 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. Copying memory that -/// contains values of nontrivial types can only be done safely with a typed -/// pointer. Copying bytes directly from nontrivial, in-memory values does -/// not produce valid copies and can only be done by calling a C API, such as -/// `memmove()`. -/// -/// UnsafeMutableRawBufferPointer Semantics -/// ================= -/// -/// An `UnsafeMutableRawBufferPointer` instance is a view into memory and does not own the memory -/// that it references. Copying a variable or constant of type `UnsafeMutableRawBufferPointer` does -/// not copy the underlying memory. However, initializing another collection -/// with an `UnsafeMutableRawBufferPointer` instance copies bytes out of the referenced memory and -/// into the new collection. -/// -/// The following example uses `someBytes`, an `UnsafeMutableRawBufferPointer` instance, to -/// demonstrate the difference between assigning a buffer pointer and using a -/// buffer pointer as the source for another collection's elements. Here, the -/// assignment to `destBytes` creates a new, nonowning buffer pointer -/// covering the first `n` bytes of the memory that `someBytes` -/// references---nothing is copied: -/// -/// var destBytes = someBytes[0..= 0, "UnsafeMutableRawBufferPointer with negative count") - _debugPrecondition(count == 0 || start != nil, - "UnsafeMutableRawBufferPointer has a nil start and nonzero count") - _position = start - _end = start.map { $0 + _assumeNonNegative(count) } - } -} - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 171) -extension UnsafeMutableRawBufferPointer { - public typealias Iterator = UnsafeRawBufferPointer.Iterator -} -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 175) - -extension UnsafeMutableRawBufferPointer: Sequence { - public typealias SubSequence = Slice - - /// Returns an iterator over the bytes of this sequence. - @inlinable - public func makeIterator() -> Iterator { - return Iterator(_position: _position, _end: _end) - } - - /// Copies the elements of `self` to the memory at `destination.baseAddress`, - /// stopping when either `self` or `destination` is exhausted. - /// - /// - Returns: an iterator over any remaining elements of `self` and the - /// number of elements copied. - @inlinable // unsafe-performance - @_alwaysEmitIntoClient - public func _copyContents( - initializing destination: UnsafeMutableBufferPointer - ) -> (Iterator, UnsafeMutableBufferPointer.Index) { - guard let s = _position, let e = _end, e > s, !destination.isEmpty else { - return (makeIterator(), 0) - } - let destinationAddress = destination.baseAddress._unsafelyUnwrappedUnchecked - let d = UnsafeMutableRawPointer(destinationAddress) - let n = Swift.min(destination.count, s.distance(to: e)) - d.copyMemory(from: s, byteCount: n) - return (Iterator(_position: s.advanced(by: n), _end: e), n) - } -} - -extension UnsafeMutableRawBufferPointer: MutableCollection { - // TODO: Specialize `index` and `formIndex` and - // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. - public typealias Element = UInt8 - public typealias Index = Int - public typealias Indices = Range - - /// Always zero, which is the index of the first byte in a nonempty buffer. - @inlinable - public var startIndex: Index { - return 0 - } - - /// The "past the end" position---that is, the position one greater than the - /// last valid subscript argument. - /// - /// The `endIndex` property of an `UnsafeMutableRawBufferPointer` - /// instance is always identical to `count`. - @inlinable - public var endIndex: Index { - return count - } - - @inlinable - public var indices: Indices { - // Not checked because init forbids negative count. - return Indices(uncheckedBounds: (startIndex, endIndex)) - } - - /// Accesses the byte at the given offset in the memory region as a `UInt8` - /// value. - /// - /// - Parameter i: The offset of the byte to access. `i` must be in the range - /// `0.. Element { - get { - _debugPrecondition(i >= 0) - _debugPrecondition(i < endIndex) - return _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 248) - nonmutating set { - _debugPrecondition(i >= 0) - _debugPrecondition(i < endIndex) - _position._unsafelyUnwrappedUnchecked.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 254) - } - - /// Accesses the bytes in the specified memory region. - /// - /// - Parameter bounds: The range of byte offsets to access. The upper and - /// lower bounds of the range must be in the range `0...count`. - @inlinable - public subscript(bounds: Range) -> SubSequence { - get { - _debugPrecondition(bounds.lowerBound >= startIndex) - _debugPrecondition(bounds.upperBound <= endIndex) - return Slice(base: self, bounds: bounds) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 268) - nonmutating set { - _debugPrecondition(bounds.lowerBound >= startIndex) - _debugPrecondition(bounds.upperBound <= endIndex) - _debugPrecondition(bounds.count == newValue.count) - - if !newValue.isEmpty { - (baseAddress! + bounds.lowerBound).copyMemory( - from: newValue.base.baseAddress! + newValue.startIndex, - byteCount: newValue.count) - } - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 280) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 283) - /// Exchanges the byte values at the specified indices - /// in this buffer's memory. - /// - /// Both parameters must be valid indices of the buffer, and not - /// equal to `endIndex`. Passing the same index as both `i` and `j` has no - /// effect. - /// - /// - Parameters: - /// - i: The index of the first byte to swap. - /// - j: The index of the second byte to swap. - @inlinable - public func swapAt(_ i: Int, _ j: Int) { - guard i != j else { return } - _debugPrecondition(i >= 0 && j >= 0) - _debugPrecondition(i < endIndex && j < endIndex) - let pi = (_position! + i) - let pj = (_position! + j) - let tmp = pi.load(fromByteOffset: 0, as: UInt8.self) - pi.copyMemory(from: pj, byteCount: MemoryLayout.size) - pj.storeBytes(of: tmp, toByteOffset: 0, as: UInt8.self) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 306) - /// The number of bytes in the buffer. - /// - /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, - /// a buffer can have a `count` of zero even with a non-`nil` base address. - @inlinable - public var count: Int { - if let pos = _position { - // Unsafely unwrapped because init forbids end being nil if _position - // isn't. - _internalInvariant(_end != nil) - return _assumeNonNegative(_end._unsafelyUnwrappedUnchecked - pos) - } - return 0 - } -} - -extension UnsafeMutableRawBufferPointer: RandomAccessCollection { } - -extension UnsafeMutableRawBufferPointer { -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 326) - /// Allocates uninitialized memory with the specified size and alignment. - /// - /// You are in charge of managing the allocated memory. Be sure to deallocate - /// any memory that you manually allocate. - /// - /// The allocated memory is not bound to any specific type and must be bound - /// before performing any typed operations. If you are using the memory for - /// a specific type, allocate memory using the - /// `UnsafeMutablePointerBuffer.allocate(capacity:)` static method instead. - /// - /// - Parameters: - /// - byteCount: The number of bytes to allocate. `byteCount` must not be - /// negative. - /// - alignment: The alignment of the new region of allocated memory, in - /// bytes. `alignment` must be a whole power of 2. - /// - Returns: A buffer pointer to a newly allocated region of memory aligned - /// to `alignment`. - @inlinable - public static func allocate( - byteCount: Int, alignment: Int - ) -> UnsafeMutableRawBufferPointer { - let base = UnsafeMutableRawPointer.allocate( - byteCount: byteCount, alignment: alignment) - return UnsafeMutableRawBufferPointer(start: base, count: byteCount) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 352) - - /// Deallocates the memory block previously allocated at this buffer pointer’s - /// base address. - /// - /// This buffer pointer's `baseAddress` must be `nil` or a pointer to a memory - /// block previously returned by a Swift allocation method. If `baseAddress` is - /// `nil`, this function does nothing. Otherwise, the memory must not be initialized - /// or `Pointee` must be a trivial type. This buffer pointer's byte `count` must - /// be equal to the originally allocated size of the memory block. - @inlinable - public func deallocate() { - _position?.deallocate() - } - - /// Returns a new instance of the given type, read from the buffer pointer's - /// raw memory at the specified byte offset. - /// - /// The memory at `offset` bytes from this buffer pointer's `baseAddress` - /// must be properly aligned for accessing `T` and initialized to `T` or - /// another type that is layout compatible with `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. - @inlinable - public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { - _debugPrecondition(offset >= 0, "UnsafeMutableRawBufferPointer.load with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeMutableRawBufferPointer.load out of bounds") - 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 fourth through seventh bytes. - /// - /// let a = someBytes.loadUnaligned(as: Int32.self) - /// let b = someBytes.loadUnaligned(fromByteOffset: 3, 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 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, "UnsafeMutableRawBufferPointer.load with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeMutableRawBufferPointer.load out of bounds") - return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 446) - /// Stores a value's bytes into the buffer pointer's raw memory at the - /// specified byte offset. - /// - /// 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`. - /// - /// The memory written to 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`. - /// - /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is - /// initialized to the raw bytes of `value`. If the memory is bound to a - /// type `U` that is layout compatible with `T`, then it contains a value of - /// 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 - /// writing bytes from the value. 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`. - @inlinable - @_alwaysEmitIntoClient - // This custom silgen name is chosen to not interfere with the old ABI - @_silgen_name("_swift_se0349_UnsafeMutableRawBufferPointer_storeBytes") - public func storeBytes( - of value: T, toByteOffset offset: Int = 0, as type: T.Type - ) { - _debugPrecondition(offset >= 0, "UnsafeMutableRawBufferPointer.storeBytes with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeMutableRawBufferPointer.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 linked against the stdlib 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, "UnsafeMutableRawBufferPointer.storeBytes with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeMutableRawBufferPointer.storeBytes out of bounds") - - baseAddress!._legacy_se0349_storeBytes_internal( - of: value, toByteOffset: offset, as: T.self - ) - } - - /// Copies the bytes from the given buffer to this buffer's memory. - /// - /// If the `source.count` bytes of memory referenced by this buffer are bound - /// to a type `T`, then `T` must be a trivial type, the underlying pointer - /// must be properly aligned for accessing `T`, and `source.count` must be a - /// multiple of `MemoryLayout.stride`. - /// - /// The memory referenced by `source` may overlap with the memory referenced - /// by this buffer. - /// - /// After calling `copyMemory(from:)`, the first `source.count` bytes of - /// memory referenced by this buffer are initialized to raw bytes. If the - /// memory is bound to type `T`, then it contains values of type `T`. - /// - /// - Parameter source: A buffer of raw bytes. `source.count` must - /// be less than or equal to this buffer's `count`. - @inlinable - public func copyMemory(from source: UnsafeRawBufferPointer) { - _debugPrecondition(source.count <= self.count, - "UnsafeMutableRawBufferPointer.copyMemory source has too many elements") - if let baseAddress = baseAddress, let sourceAddress = source.baseAddress { - baseAddress.copyMemory(from: sourceAddress, byteCount: source.count) - } - } - - /// Copies from a collection of `UInt8` into this buffer's memory. - /// - /// If the first `source.count` bytes of memory referenced by this buffer - /// are bound to a type `T`, then `T` must be a trivial type, - /// the underlying pointer must be properly aligned for accessing `T`, - /// and `source.count` must be a multiple of `MemoryLayout.stride`. - /// - /// After calling `copyBytes(from:)`, the first `source.count` bytes of memory - /// referenced by this buffer are initialized to raw bytes. If the memory is - /// bound to type `T`, then it contains values of type `T`. - /// - /// - Parameter source: A collection of `UInt8` elements. `source.count` must - /// be less than or equal to this buffer's `count`. - @inlinable - public func copyBytes( - from source: C - ) where C.Element == UInt8 { - guard let position = _position else { - return - } - - if source.withContiguousStorageIfAvailable({ - (buffer: UnsafeBufferPointer) -> Void in - _debugPrecondition(source.count <= self.count, - "UnsafeMutableRawBufferPointer.copyBytes source has too many elements") - if let base = buffer.baseAddress { - position.copyMemory(from: base, byteCount: buffer.count) - } - }) != nil { - return - } - - for (index, byteValue) in source.enumerated() { - _debugPrecondition(index < self.count, - "UnsafeMutableRawBufferPointer.copyBytes source has too many elements") - position.storeBytes( - of: byteValue, toByteOffset: index, as: UInt8.self) - } - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 577) - - /// Creates a new buffer over the same memory as the given buffer. - /// - /// - Parameter bytes: The buffer to convert. - @inlinable - public init(_ bytes: UnsafeMutableRawBufferPointer) { - self.init(start: bytes.baseAddress, count: bytes.count) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 587) - /// Creates a new mutable buffer over the same memory as the given buffer. - /// - /// - Parameter bytes: The buffer to convert. - @inlinable - public init(mutating bytes: UnsafeRawBufferPointer) { - self.init(start: UnsafeMutableRawPointer(mutating: bytes.baseAddress), - count: bytes.count) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 604) - - /// Creates a raw buffer over the contiguous bytes in the given typed buffer. - /// - /// - Parameter buffer: The typed buffer to convert to a raw buffer. The - /// buffer's type `T` must be a trivial type. - @inlinable - public init(_ buffer: UnsafeMutableBufferPointer) { - self.init(start: buffer.baseAddress, - count: buffer.count * MemoryLayout.stride) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 626) - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 666) - - /// Creates a raw buffer over the same memory as the given raw buffer slice, - /// with the indices rebased to zero. - /// - /// The new buffer represents the same region of memory as the slice, but its - /// indices start at zero instead of at the beginning of the slice in the - /// original buffer. The following code creates `slice`, a slice covering - /// part of an existing buffer instance, then rebases it into a new `rebased` - /// buffer. - /// - /// let slice = buffer[n...] - /// let rebased = UnsafeRawBufferPointer(rebasing: slice) - /// - /// After this code has executed, the following are true: - /// - /// - `rebased.startIndex == 0` - /// - `rebased[0] == slice[n]` - /// - `rebased[0] == buffer[n]` - /// - `rebased.count == slice.count` - /// - /// - Parameter slice: The raw buffer slice to rebase. - @inlinable - public init(rebasing slice: Slice) { - let base = slice.base.baseAddress?.advanced(by: slice.startIndex) - let count = slice.endIndex &- slice.startIndex - self.init(start: base, count: count) - } - - /// A pointer to the first byte of the buffer. - /// - /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, - /// a buffer can have a `count` of zero even with a non-`nil` base address. - @inlinable - public var baseAddress: UnsafeMutableRawPointer? { - return _position - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 704) - - /// Initializes the memory referenced by this buffer with the given value, - /// binds the memory to the value's type, and returns a typed buffer of the - /// initialized memory. - /// - /// The memory referenced by this buffer must be uninitialized or - /// initialized to a trivial type, and must be properly aligned for - /// accessing `T`. - /// - /// After calling this method on a raw buffer with non-nil `baseAddress` `b`, - /// the region starting at `b` and continuing up to - /// `b + self.count - self.count % MemoryLayout.stride` is bound - /// to type `T` and is initialized. If `T` is a nontrivial type, you must - /// eventually deinitialize or move the values in this region to avoid leaks. - /// If `baseAddress` is `nil`, this function does nothing - /// and returns an empty buffer pointer. - /// - /// - Parameters: - /// - type: The type to bind this buffer’s memory to. - /// - repeatedValue: The instance to copy into memory. - /// - Returns: A typed buffer of the memory referenced by this raw buffer. - /// The typed buffer contains `self.count / MemoryLayout.stride` - /// instances of `T`. - @inlinable - @discardableResult - public func initializeMemory(as type: T.Type, repeating repeatedValue: T) - -> UnsafeMutableBufferPointer { - guard let base = _position else { - return .init(start: nil, count: 0) - } - - let count = (_end._unsafelyUnwrappedUnchecked-base) / MemoryLayout.stride - let initialized = base.initializeMemory( - as: type, repeating: repeatedValue, count: count - ) - return .init(start: initialized, count: count) - } - - /// Initializes the buffer's memory with the given elements, binding the - /// initialized memory to the elements' type. - /// - /// When calling the `initializeMemory(as:from:)` method on a buffer `b`, - /// the memory referenced by `b` must be uninitialized or initialized to a - /// trivial type, and must be properly aligned for accessing `S.Element`. - /// The buffer must contain sufficient memory to accommodate - /// `source.underestimatedCount`. - /// - /// This method initializes the buffer with elements from `source` until - /// `source` is exhausted or, if `source` is a sequence but not a collection, - /// the buffer has no more room for source's elements. After calling - /// `initializeMemory(as:from:)`, the memory referenced by the returned - /// `UnsafeMutableBufferPointer` instance is bound and initialized to type - /// `S.Element`. This method does not change - /// the binding state of the unused portion of `b`, if any. - /// - /// - Parameters: - /// - type: The type of element to which this buffer's memory will be bound. - /// - source: A sequence of elements with which to initialize the buffer. - /// - Returns: An iterator to any elements of `source` that didn't fit in the - /// buffer, and a typed buffer of the written elements. The returned - /// buffer references memory starting at the same base address as this - /// buffer. - @inlinable - public func initializeMemory( - as type: S.Element.Type, from source: S - ) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer) { - var it = source.makeIterator() - var idx = startIndex - let elementStride = MemoryLayout.stride - - // This has to be a debug precondition due to the cost of walking over some collections. - _debugPrecondition(source.underestimatedCount <= (count / elementStride), - "insufficient space to accommodate source.underestimatedCount elements") - guard let base = baseAddress else { - // this can be a precondition since only an invalid argument should be costly - _precondition(source.underestimatedCount == 0, - "no memory available to initialize from source") - return (it, UnsafeMutableBufferPointer(start: nil, count: 0)) - } - - _debugPrecondition( - Int(bitPattern: base) % MemoryLayout.stride == 0, - "buffer base address must be properly aligned to access S.Element" - ) - - _internalInvariant(_end != nil) - for p in stride(from: base, - // only advance to as far as the last element that will fit - to: _end._unsafelyUnwrappedUnchecked - elementStride + 1, - by: elementStride - ) { - // underflow is permitted -- e.g. a sequence into - // the spare capacity of an Array buffer - guard let x = it.next() else { break } - p.initializeMemory(as: S.Element.self, repeating: x, count: 1) - formIndex(&idx, offsetBy: elementStride) - } - - return (it, UnsafeMutableBufferPointer( - start: base.assumingMemoryBound(to: S.Element.self), - count: idx / elementStride)) - } - - /// Initializes the buffer's memory with every element of the source, - /// binding the initialized memory to the elements' type. - /// - /// When calling the `initializeMemory(as:fromContentsOf:)` method, - /// the memory referenced by the buffer must be uninitialized, or initialized - /// to a trivial type. The buffer must reference enough memory to store - /// `source.count` elements, and its `baseAddress` must be properly aligned - /// for accessing `C.Element`. - /// - /// This method initializes the buffer with the contents of `source` - /// until `source` is exhausted. - /// After calling `initializeMemory(as:fromContentsOf:)`, the memory - /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound - /// to the type `C.Element` and is initialized. This method does not change - /// the binding state of the unused portion of the buffer, if any. - /// - /// - Note: The memory regions referenced by `source` and this buffer - /// must not overlap. - /// - /// - Parameters: - /// - type: The type of element to which this buffer's memory will be bound. - /// - source: A collection of elements to be used to - /// initialize the buffer's storage. - /// - Returns: A typed buffer referencing the initialized elements. - /// The returned buffer references memory starting at the same - /// base address as this buffer, and its count is equal to `source.count` - @inlinable - @_alwaysEmitIntoClient - public func initializeMemory( - as type: C.Element.Type, - fromContentsOf source: C - ) -> UnsafeMutableBufferPointer { - let buffer: UnsafeMutableBufferPointer? - buffer = source.withContiguousStorageIfAvailable { - guard let sourceAddress = $0.baseAddress, !$0.isEmpty else { - return .init(start: nil, count: 0) - } - _debugPrecondition( - Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, - "buffer base address must be properly aligned to access C.Element" - ) - _precondition( - $0.count * MemoryLayout.stride <= self.count, - "buffer cannot contain every element from source collection." - ) - let start = baseAddress?.initializeMemory( - as: C.Element.self, from: sourceAddress, count: $0.count - ) - return .init(start: start, count: $0.count) - } - if let buffer { - return buffer - } - - guard let base = baseAddress else { - _precondition( - source.isEmpty, - "buffer cannot contain every element from source collection." - ) - return .init(start: nil, count: 0) - } - _internalInvariant(_end != nil) - _debugPrecondition( - Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, - "buffer base address must be properly aligned to access C.Element" - ) - var iterator = source.makeIterator() - var element = base - var initialized = 0 - let end = _end._unsafelyUnwrappedUnchecked - MemoryLayout.stride - while element <= end { - guard let value = iterator.next() else { - return .init(start: .init(base._rawValue), count: initialized) - } - element.initializeMemory(as: C.Element.self, to: value) - element = element.advanced(by: MemoryLayout.stride) - initialized += 1 - } - _precondition( - iterator.next() == nil, - "buffer cannot contain every element from source collection." - ) - return .init(start: .init(base._rawValue), count: initialized) - } - - /// Moves every element of an initialized source buffer into the - /// uninitialized memory referenced by this buffer, leaving the source memory - /// uninitialized and this buffer's memory initialized. - /// - /// When calling the `moveInitializeMemory(as:fromContentsOf:)` method, - /// the memory referenced by the buffer must be uninitialized, or initialized - /// to a trivial type. The buffer must reference enough memory to store - /// `source.count` elements, and its `baseAddress` must be properly aligned - /// for accessing `C.Element`. After the method returns, - /// the memory referenced by the returned buffer is initialized and the - /// memory region underlying `source` is uninitialized. - /// - /// This method initializes the buffer with the contents of `source` - /// until `source` is exhausted. - /// After calling `initializeMemory(as:fromContentsOf:)`, the memory - /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound - /// to the type `T` and is initialized. This method does not change - /// the binding state of the unused portion of the buffer, if any. - /// - /// - Note: The memory regions referenced by `source` and this buffer - /// may overlap. - /// - /// - Parameters: - /// - type: The type of element to which this buffer's memory will be bound. - /// - source: A buffer referencing the values to copy. - /// The memory region underlying `source` must be initialized. - /// - Returns: A typed buffer referencing the initialized elements. - /// The returned buffer references memory starting at the same - /// base address as this buffer, and its count is equal to `source.count`. - @discardableResult - @inlinable - @_alwaysEmitIntoClient - public func moveInitializeMemory( - as type: T.Type, - fromContentsOf source: UnsafeMutableBufferPointer - ) -> UnsafeMutableBufferPointer { - guard let sourceAddress = source.baseAddress, !source.isEmpty else { - return .init(start: nil, count: 0) - } - _debugPrecondition( - Int(bitPattern: baseAddress) % MemoryLayout.stride == 0, - "buffer base address must be properly aligned to access T" - ) - _precondition( - source.count * MemoryLayout.stride <= self.count, - "buffer cannot contain every element from source." - ) - let initialized = baseAddress?.moveInitializeMemory( - as: T.self, from: sourceAddress, count: source.count - ) - return .init(start: initialized, count: source.count) - } - - /// Moves every element of an initialized source buffer slice into the - /// uninitialized memory referenced by this buffer, leaving the source memory - /// uninitialized and this buffer's memory initialized. - /// - /// When calling the `moveInitializeMemory(as:fromContentsOf:)` method, - /// the memory referenced by the buffer must be uninitialized, or initialized - /// to a trivial type. The buffer must reference enough memory to store - /// `source.count` elements, and its `baseAddress` must be properly aligned - /// for accessing `C.Element`. After the method returns, - /// the memory referenced by the returned buffer is initialized and the - /// memory region underlying `source` is uninitialized. - /// - /// This method initializes the buffer with the contents of `source` - /// until `source` is exhausted. - /// After calling `initializeMemory(as:fromContentsOf:)`, the memory - /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound - /// to the type `T` and is initialized. This method does not change - /// the binding state of the unused portion of the buffer, if any. - /// - /// - Note: The memory regions referenced by `source` and this buffer - /// may overlap. - /// - /// - Parameters: - /// - type: The type of element to which this buffer's memory will be bound. - /// - source: A buffer referencing the values to copy. - /// The memory region underlying `source` must be initialized. - /// - Returns: A typed buffer referencing the initialized elements. - /// The returned buffer references memory starting at the same - /// base address as this buffer, and its count is equal to `source.count`. - @discardableResult - @inlinable - @_alwaysEmitIntoClient - public func moveInitializeMemory( - as type: T.Type, - fromContentsOf source: Slice> - ) -> UnsafeMutableBufferPointer { - let rebased = UnsafeMutableBufferPointer(rebasing: source) - return moveInitializeMemory(as: T.self, fromContentsOf: rebased) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 986) - - /// Binds this buffer’s memory to the specified type and returns a typed buffer - /// of the bound memory. - /// - /// Use the `bindMemory(to:)` method to bind the memory referenced - /// by this buffer to the type `T`. The memory must be uninitialized or - /// initialized to a type that is layout compatible with `T`. If the memory - /// is uninitialized, it is still uninitialized after being bound to `T`. - /// - /// - Warning: A memory location may only be bound to one type at a time. The - /// behavior of accessing memory as a type unrelated to its bound type is - /// undefined. - /// - /// - Parameters: - /// - type: The type `T` to bind the memory to. - /// - Returns: A typed buffer of the newly bound memory. The memory in this - /// region is bound to `T`, but has not been modified in any other way. - /// The typed buffer references `self.count / MemoryLayout.stride` - /// instances of `T`. - @_transparent - @discardableResult - public func bindMemory( - to type: T.Type - ) -> UnsafeMutableBufferPointer { - guard let base = _position else { - return UnsafeMutableBufferPointer(start: nil, count: 0) - } - - let capacity = count / MemoryLayout.stride - Builtin.bindMemory(base._rawValue, capacity._builtinWordValue, type) - return UnsafeMutableBufferPointer( - start: UnsafeMutablePointer(base._rawValue), count: capacity) - } - - /// Executes the given closure while temporarily binding the buffer to - /// instances of type `T`. - /// - /// Use this method when you have a buffer to raw memory and you need - /// to access that memory as instances of a given type `T`. Accessing - /// memory as a type `T` requires that the memory be bound to that type. - /// A memory location may only be bound to one type at a time, so accessing - /// the same memory as an unrelated type without first rebinding the memory - /// is undefined. - /// - /// Any instance of `T` within the re-bound region may be initialized or - /// uninitialized. The memory underlying any individual instance of `T` - /// must have the same initialization state (i.e. initialized or - /// uninitialized.) Accessing a `T` whose underlying memory - /// is in a mixed initialization state shall be undefined behaviour. - /// - /// If the byte count of the original buffer is not a multiple of - /// the stride of `T`, then the re-bound buffer is shorter - /// than the original buffer. - /// - /// After executing `body`, this method rebinds memory back to its original - /// binding state. This can be unbound memory, or bound to a different type. - /// - /// - Note: The buffer's base address must match the - /// alignment of `T` (as reported by `MemoryLayout.alignment`). - /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` - /// must equal zero. - /// - /// - Note: A raw buffer may represent memory that has been bound to a type. - /// If that is the case, then `T` must be layout compatible with the - /// type to which the memory has been bound. This requirement does not - /// apply if the raw buffer represents memory that has not been bound - /// to any type. - /// - /// - Parameters: - /// - type: The type to temporarily bind the memory referenced by this - /// buffer. - /// - body: A closure that takes a typed pointer to the - /// same memory as this pointer, only bound to type `T`. The closure's - /// pointer argument is valid only for the duration of the closure's - /// execution. If `body` has a return value, that value is also used as - /// the return value for the `withMemoryRebound(to:capacity:_:)` method. - /// - buffer: The buffer temporarily bound to instances of `T`. - /// - Returns: The return value, if any, of the `body` closure parameter. - @inlinable - @_alwaysEmitIntoClient - public func withMemoryRebound( - to type: T.Type, - _ body: (_ buffer: UnsafeMutableBufferPointer) throws -> Result - ) rethrows -> Result { - guard let s = _position else { - return try body(.init(start: nil, count: 0)) - } - _debugPrecondition( - Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0, - "baseAddress must be a properly aligned pointer for type T" - ) - // initializer ensures _end is nil only when _position is nil. - _internalInvariant(_end != nil) - let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) - let n = c / MemoryLayout.stride - let binding = Builtin.bindMemory(s._rawValue, n._builtinWordValue, T.self) - defer { Builtin.rebindMemory(s._rawValue, binding) } - return try body(.init(start: .init(s._rawValue), count: n)) - } - - /// Returns a typed buffer to the memory referenced by this buffer, - /// assuming that the memory is already bound to the specified type. - /// - /// Use this method when you have a raw buffer to memory that has already - /// been bound to the specified type. The memory starting at this pointer - /// must be bound to the type `T`. Accessing memory through the returned - /// pointer is undefined if the memory has not been bound to `T`. To bind - /// memory to `T`, use `bindMemory(to:capacity:)` instead of this method. - /// - /// - Note: The buffer's base address must match the - /// alignment of `T` (as reported by `MemoryLayout.alignment`). - /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` - /// must equal zero. - /// - /// - Parameter to: The type `T` that the memory has already been bound to. - /// - Returns: A typed pointer to the same memory as this raw pointer. - @inlinable - @_alwaysEmitIntoClient - public func assumingMemoryBound( - to: T.Type - ) -> UnsafeMutableBufferPointer { - guard let s = _position else { - return .init(start: nil, count: 0) - } - // initializer ensures _end is nil only when _position is nil. - _internalInvariant(_end != nil) - let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) - let n = c / MemoryLayout.stride - return .init(start: .init(s._rawValue), count: n) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1118) - @inlinable - @_alwaysEmitIntoClient - public func withContiguousMutableStorageIfAvailable( - _ body: (inout UnsafeMutableBufferPointer) throws -> R - ) rethrows -> R? { - try withMemoryRebound(to: Element.self) { b in - var buffer = b - defer { - _debugPrecondition( - (b.baseAddress, b.count) == (buffer.baseAddress, buffer.count), - "UnsafeMutableRawBufferPointer.withContiguousMutableStorageIfAvailable: replacing the buffer is not allowed" - ) - } - return try body(&buffer) - } - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1136) - @inlinable - @_alwaysEmitIntoClient - public func withContiguousStorageIfAvailable( - _ body: (UnsafeBufferPointer) throws -> R - ) rethrows -> R? { - try withMemoryRebound(to: Element.self) { - try body(UnsafeBufferPointer($0)) - } - } -} - -@_unavailableInEmbedded -extension UnsafeMutableRawBufferPointer: CustomDebugStringConvertible { - /// A textual representation of the buffer, suitable for debugging. - public var debugDescription: String { - return "UnsafeMutableRawBufferPointer" - + "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))" - } -} - -extension UnsafeMutableRawBufferPointer { - @available(*, unavailable, - message: "use 'UnsafeMutableRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") - public subscript(bounds: Range) -> UnsafeMutableRawBufferPointer { - get { return UnsafeMutableRawBufferPointer(start: nil, count: 0) } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1162) - nonmutating set {} -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1164) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1167) - @available(*, unavailable, - message: "use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") - public subscript(bounds: Range) -> UnsafeRawBufferPointer { - get { return UnsafeRawBufferPointer(start: nil, count: 0) } - nonmutating set {} - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1174) -} - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 19) - -/// A nonowning collection interface to the bytes in a -/// region of memory. -/// -/// You can use an `UnsafeRawBufferPointer` instance in low-level operations to eliminate -/// uniqueness checks and release mode bounds checks. Bounds checks are always -/// performed in debug mode. -/// -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 43) -/// An `UnsafeRawBufferPointer` instance is a view of the raw bytes in a region of memory. -/// Each byte in memory is viewed as a `UInt8` value independent of the type -/// of values held in that memory. Reading from memory through a raw buffer is -/// an untyped operation. -/// -/// In addition to its collection interface, an `UnsafeRawBufferPointer` -/// instance also supports the `load(fromByteOffset:as:)` -/// and `loadUnaligned(fromByteOffset:as:)` methods provided by -/// `UnsafeRawPointer`, including bounds checks in debug mode. -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 53) -/// -/// To access the underlying memory through typed operations, the memory must -/// be bound to a trivial type. -/// -/// - Note: A *trivial type* can be copied bit for bit with no 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. Copying memory that -/// contains values of nontrivial types can only be done safely with a typed -/// pointer. Copying bytes directly from nontrivial, in-memory values does -/// not produce valid copies and can only be done by calling a C API, such as -/// `memmove()`. -/// -/// UnsafeRawBufferPointer Semantics -/// ================= -/// -/// An `UnsafeRawBufferPointer` instance is a view into memory and does not own the memory -/// that it references. Copying a variable or constant of type `UnsafeRawBufferPointer` does -/// not copy the underlying memory. However, initializing another collection -/// with an `UnsafeRawBufferPointer` instance copies bytes out of the referenced memory and -/// into the new collection. -/// -/// The following example uses `someBytes`, an `UnsafeRawBufferPointer` instance, to -/// demonstrate the difference between assigning a buffer pointer and using a -/// buffer pointer as the source for another collection's elements. Here, the -/// assignment to `destBytes` creates a new, nonowning buffer pointer -/// covering the first `n` bytes of the memory that `someBytes` -/// references---nothing is copied: -/// -/// var destBytes = someBytes[0..= 0, "UnsafeRawBufferPointer with negative count") - _debugPrecondition(count == 0 || start != nil, - "UnsafeRawBufferPointer has a nil start and nonzero count") - _position = start - _end = start.map { $0 + _assumeNonNegative(count) } - } -} - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 125) -extension UnsafeRawBufferPointer { - /// An iterator over the bytes viewed by a raw buffer pointer. - @frozen - public struct Iterator { - @usableFromInline - internal var _position, _end: UnsafeRawPointer? - - @inlinable - internal init(_position: UnsafeRawPointer?, _end: UnsafeRawPointer?) { - self._position = _position - self._end = _end - } - } -} - -extension UnsafeRawBufferPointer.Iterator: IteratorProtocol, Sequence { - /// Advances to the next byte and returns it, or `nil` if no next byte - /// exists. - /// - /// Once `nil` has been returned, all subsequent calls return `nil`. - /// - /// - Returns: The next sequential byte in the raw buffer if another byte - /// exists; otherwise, `nil`. - @inlinable - public mutating func next() -> UInt8? { - if _position == _end { return nil } - - // We can do an unchecked unwrap here by borrowing invariants from the pointer. - // For a validly constructed buffer pointer, the only way _position can be nil is - // if _end is also nil. We checked that case above. Thus, we can safely do an - // unchecked unwrap here. - // - // Additionally, validly constructed buffer pointers also have an _end that is - // strictly greater than or equal to _position, and so we do not need to do checked - // arithmetic here as we cannot possibly overflow. - // - // We check these invariants in debug builds to defend against invalidly constructed - // pointers. - _debugPrecondition(_position! < _end!) - let position = _position._unsafelyUnwrappedUnchecked - let result = position.load(as: UInt8.self) - _position = position + 1 - return result - } -} -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 175) - -extension UnsafeRawBufferPointer: Sequence { - public typealias SubSequence = Slice - - /// Returns an iterator over the bytes of this sequence. - @inlinable - public func makeIterator() -> Iterator { - return Iterator(_position: _position, _end: _end) - } - - /// Copies the elements of `self` to the memory at `destination.baseAddress`, - /// stopping when either `self` or `destination` is exhausted. - /// - /// - Returns: an iterator over any remaining elements of `self` and the - /// number of elements copied. - @inlinable // unsafe-performance - @_alwaysEmitIntoClient - public func _copyContents( - initializing destination: UnsafeMutableBufferPointer - ) -> (Iterator, UnsafeMutableBufferPointer.Index) { - guard let s = _position, let e = _end, e > s, !destination.isEmpty else { - return (makeIterator(), 0) - } - let destinationAddress = destination.baseAddress._unsafelyUnwrappedUnchecked - let d = UnsafeMutableRawPointer(destinationAddress) - let n = Swift.min(destination.count, s.distance(to: e)) - d.copyMemory(from: s, byteCount: n) - return (Iterator(_position: s.advanced(by: n), _end: e), n) - } -} - -extension UnsafeRawBufferPointer: Collection { - // TODO: Specialize `index` and `formIndex` and - // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. - public typealias Element = UInt8 - public typealias Index = Int - public typealias Indices = Range - - /// Always zero, which is the index of the first byte in a nonempty buffer. - @inlinable - public var startIndex: Index { - return 0 - } - - /// The "past the end" position---that is, the position one greater than the - /// last valid subscript argument. - /// - /// The `endIndex` property of an `UnsafeRawBufferPointer` - /// instance is always identical to `count`. - @inlinable - public var endIndex: Index { - return count - } - - @inlinable - public var indices: Indices { - // Not checked because init forbids negative count. - return Indices(uncheckedBounds: (startIndex, endIndex)) - } - - /// Accesses the byte at the given offset in the memory region as a `UInt8` - /// value. - /// - /// - Parameter i: The offset of the byte to access. `i` must be in the range - /// `0.. Element { - get { - _debugPrecondition(i >= 0) - _debugPrecondition(i < endIndex) - return _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 254) - } - - /// Accesses the bytes in the specified memory region. - /// - /// - Parameter bounds: The range of byte offsets to access. The upper and - /// lower bounds of the range must be in the range `0...count`. - @inlinable - public subscript(bounds: Range) -> SubSequence { - get { - _debugPrecondition(bounds.lowerBound >= startIndex) - _debugPrecondition(bounds.upperBound <= endIndex) - return Slice(base: self, bounds: bounds) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 280) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 306) - /// The number of bytes in the buffer. - /// - /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, - /// a buffer can have a `count` of zero even with a non-`nil` base address. - @inlinable - public var count: Int { - if let pos = _position { - // Unsafely unwrapped because init forbids end being nil if _position - // isn't. - _internalInvariant(_end != nil) - return _assumeNonNegative(_end._unsafelyUnwrappedUnchecked - pos) - } - return 0 - } -} - -extension UnsafeRawBufferPointer: RandomAccessCollection { } - -extension UnsafeRawBufferPointer { -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 352) - - /// Deallocates the memory block previously allocated at this buffer pointer’s - /// base address. - /// - /// This buffer pointer's `baseAddress` must be `nil` or a pointer to a memory - /// block previously returned by a Swift allocation method. If `baseAddress` is - /// `nil`, this function does nothing. Otherwise, the memory must not be initialized - /// or `Pointee` must be a trivial type. This buffer pointer's byte `count` must - /// be equal to the originally allocated size of the memory block. - @inlinable - public func deallocate() { - _position?.deallocate() - } - - /// Returns a new instance of the given type, read from the buffer pointer's - /// raw memory at the specified byte offset. - /// - /// The memory at `offset` bytes from this buffer pointer's `baseAddress` - /// must be properly aligned for accessing `T` and initialized to `T` or - /// another type that is layout compatible with `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. - @inlinable - public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { - _debugPrecondition(offset >= 0, "UnsafeRawBufferPointer.load with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeRawBufferPointer.load out of bounds") - 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 fourth through seventh bytes. - /// - /// let a = someBytes.loadUnaligned(as: Int32.self) - /// let b = someBytes.loadUnaligned(fromByteOffset: 3, 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 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, "UnsafeRawBufferPointer.load with negative offset") - _debugPrecondition(offset + MemoryLayout.size <= self.count, - "UnsafeRawBufferPointer.load out of bounds") - return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 577) - - /// Creates a new buffer over the same memory as the given buffer. - /// - /// - Parameter bytes: The buffer to convert. - @inlinable - public init(_ bytes: UnsafeMutableRawBufferPointer) { - self.init(start: bytes.baseAddress, count: bytes.count) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 596) - /// Creates a new buffer over the same memory as the given buffer. - /// - /// - Parameter bytes: The buffer to convert. - @inlinable - public init(_ bytes: UnsafeRawBufferPointer) { - self.init(start: bytes.baseAddress, count: bytes.count) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 604) - - /// Creates a raw buffer over the contiguous bytes in the given typed buffer. - /// - /// - Parameter buffer: The typed buffer to convert to a raw buffer. The - /// buffer's type `T` must be a trivial type. - @inlinable - public init(_ buffer: UnsafeMutableBufferPointer) { - self.init(start: buffer.baseAddress, - count: buffer.count * MemoryLayout.stride) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 616) - /// Creates a raw buffer over the contiguous bytes in the given typed buffer. - /// - /// - Parameter buffer: The typed buffer to convert to a raw buffer. The - /// buffer's type `T` must be a trivial type. - @inlinable - public init(_ buffer: UnsafeBufferPointer) { - self.init(start: buffer.baseAddress, - count: buffer.count * MemoryLayout.stride) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 626) - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 628) - /// Creates a raw buffer over the same memory as the given raw buffer slice, - /// with the indices rebased to zero. - /// - /// The new buffer represents the same region of memory as the slice, but its - /// indices start at zero instead of at the beginning of the slice in the - /// original buffer. The following code creates `slice`, a slice covering - /// part of an existing buffer instance, then rebases it into a new `rebased` - /// buffer. - /// - /// let slice = buffer[n...] - /// let rebased = UnsafeRawBufferPointer(rebasing: slice) - /// - /// After this code has executed, the following are true: - /// - /// - `rebased.startIndex == 0` - /// - `rebased[0] == slice[n]` - /// - `rebased[0] == buffer[n]` - /// - `rebased.count == slice.count` - /// - /// - Parameter slice: The raw buffer slice to rebase. - @inlinable - public init(rebasing slice: Slice) { - // NOTE: `Slice` does not guarantee that its start/end indices are valid - // in `base` -- it merely ensures that `startIndex <= endIndex`. - // We need manually check that we aren't given an invalid slice, - // or the resulting collection would allow access that was - // out-of-bounds with respect to the original base buffer. - // We only do this in debug builds to prevent a measurable performance - // degradation wrt passing around pointers not wrapped in a BufferPointer - // construct. - _debugPrecondition( - slice.startIndex >= 0 && slice.endIndex <= slice.base.count, - "Invalid slice") - let base = slice.base.baseAddress?.advanced(by: slice.startIndex) - let count = slice.endIndex &- slice.startIndex - self.init(start: base, count: count) - } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 666) - - /// Creates a raw buffer over the same memory as the given raw buffer slice, - /// with the indices rebased to zero. - /// - /// The new buffer represents the same region of memory as the slice, but its - /// indices start at zero instead of at the beginning of the slice in the - /// original buffer. The following code creates `slice`, a slice covering - /// part of an existing buffer instance, then rebases it into a new `rebased` - /// buffer. - /// - /// let slice = buffer[n...] - /// let rebased = UnsafeRawBufferPointer(rebasing: slice) - /// - /// After this code has executed, the following are true: - /// - /// - `rebased.startIndex == 0` - /// - `rebased[0] == slice[n]` - /// - `rebased[0] == buffer[n]` - /// - `rebased.count == slice.count` - /// - /// - Parameter slice: The raw buffer slice to rebase. - @inlinable - public init(rebasing slice: Slice) { - let base = slice.base.baseAddress?.advanced(by: slice.startIndex) - let count = slice.endIndex &- slice.startIndex - self.init(start: base, count: count) - } - - /// A pointer to the first byte of the buffer. - /// - /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, - /// a buffer can have a `count` of zero even with a non-`nil` base address. - @inlinable - public var baseAddress: UnsafeRawPointer? { - return _position - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 986) - - /// Binds this buffer’s memory to the specified type and returns a typed buffer - /// of the bound memory. - /// - /// Use the `bindMemory(to:)` method to bind the memory referenced - /// by this buffer to the type `T`. The memory must be uninitialized or - /// initialized to a type that is layout compatible with `T`. If the memory - /// is uninitialized, it is still uninitialized after being bound to `T`. - /// - /// - Warning: A memory location may only be bound to one type at a time. The - /// behavior of accessing memory as a type unrelated to its bound type is - /// undefined. - /// - /// - Parameters: - /// - type: The type `T` to bind the memory to. - /// - Returns: A typed buffer of the newly bound memory. The memory in this - /// region is bound to `T`, but has not been modified in any other way. - /// The typed buffer references `self.count / MemoryLayout.stride` - /// instances of `T`. - @_transparent - @discardableResult - public func bindMemory( - to type: T.Type - ) -> UnsafeBufferPointer { - guard let base = _position else { - return UnsafeBufferPointer(start: nil, count: 0) - } - - let capacity = count / MemoryLayout.stride - Builtin.bindMemory(base._rawValue, capacity._builtinWordValue, type) - return UnsafeBufferPointer( - start: UnsafePointer(base._rawValue), count: capacity) - } - - /// Executes the given closure while temporarily binding the buffer to - /// instances of type `T`. - /// - /// Use this method when you have a buffer to raw memory and you need - /// to access that memory as instances of a given type `T`. Accessing - /// memory as a type `T` requires that the memory be bound to that type. - /// A memory location may only be bound to one type at a time, so accessing - /// the same memory as an unrelated type without first rebinding the memory - /// is undefined. - /// - /// Any instance of `T` within the re-bound region may be initialized or - /// uninitialized. The memory underlying any individual instance of `T` - /// must have the same initialization state (i.e. initialized or - /// uninitialized.) Accessing a `T` whose underlying memory - /// is in a mixed initialization state shall be undefined behaviour. - /// - /// If the byte count of the original buffer is not a multiple of - /// the stride of `T`, then the re-bound buffer is shorter - /// than the original buffer. - /// - /// After executing `body`, this method rebinds memory back to its original - /// binding state. This can be unbound memory, or bound to a different type. - /// - /// - Note: The buffer's base address must match the - /// alignment of `T` (as reported by `MemoryLayout.alignment`). - /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` - /// must equal zero. - /// - /// - Note: A raw buffer may represent memory that has been bound to a type. - /// If that is the case, then `T` must be layout compatible with the - /// type to which the memory has been bound. This requirement does not - /// apply if the raw buffer represents memory that has not been bound - /// to any type. - /// - /// - Parameters: - /// - type: The type to temporarily bind the memory referenced by this - /// buffer. - /// - body: A closure that takes a typed pointer to the - /// same memory as this pointer, only bound to type `T`. The closure's - /// pointer argument is valid only for the duration of the closure's - /// execution. If `body` has a return value, that value is also used as - /// the return value for the `withMemoryRebound(to:capacity:_:)` method. - /// - buffer: The buffer temporarily bound to instances of `T`. - /// - Returns: The return value, if any, of the `body` closure parameter. - @inlinable - @_alwaysEmitIntoClient - public func withMemoryRebound( - to type: T.Type, - _ body: (_ buffer: UnsafeBufferPointer) throws -> Result - ) rethrows -> Result { - guard let s = _position else { - return try body(.init(start: nil, count: 0)) - } - _debugPrecondition( - Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0, - "baseAddress must be a properly aligned pointer for type T" - ) - // initializer ensures _end is nil only when _position is nil. - _internalInvariant(_end != nil) - let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) - let n = c / MemoryLayout.stride - let binding = Builtin.bindMemory(s._rawValue, n._builtinWordValue, T.self) - defer { Builtin.rebindMemory(s._rawValue, binding) } - return try body(.init(start: .init(s._rawValue), count: n)) - } - - /// Returns a typed buffer to the memory referenced by this buffer, - /// assuming that the memory is already bound to the specified type. - /// - /// Use this method when you have a raw buffer to memory that has already - /// been bound to the specified type. The memory starting at this pointer - /// must be bound to the type `T`. Accessing memory through the returned - /// pointer is undefined if the memory has not been bound to `T`. To bind - /// memory to `T`, use `bindMemory(to:capacity:)` instead of this method. - /// - /// - Note: The buffer's base address must match the - /// alignment of `T` (as reported by `MemoryLayout.alignment`). - /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` - /// must equal zero. - /// - /// - Parameter to: The type `T` that the memory has already been bound to. - /// - Returns: A typed pointer to the same memory as this raw pointer. - @inlinable - @_alwaysEmitIntoClient - public func assumingMemoryBound( - to: T.Type - ) -> UnsafeBufferPointer { - guard let s = _position else { - return .init(start: nil, count: 0) - } - // initializer ensures _end is nil only when _position is nil. - _internalInvariant(_end != nil) - let c = _assumeNonNegative(s.distance(to: _end._unsafelyUnwrappedUnchecked)) - let n = c / MemoryLayout.stride - return .init(start: .init(s._rawValue), count: n) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1136) - @inlinable - @_alwaysEmitIntoClient - public func withContiguousStorageIfAvailable( - _ body: (UnsafeBufferPointer) throws -> R - ) rethrows -> R? { - try withMemoryRebound(to: Element.self) { - try body($0) - } - } -} - -@_unavailableInEmbedded -extension UnsafeRawBufferPointer: CustomDebugStringConvertible { - /// A textual representation of the buffer, suitable for debugging. - public var debugDescription: String { - return "UnsafeRawBufferPointer" - + "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))" - } -} - -extension UnsafeRawBufferPointer { - @available(*, unavailable, - message: "use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") - public subscript(bounds: Range) -> UnsafeRawBufferPointer { - get { return UnsafeRawBufferPointer(start: nil, count: 0) } -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1164) - } - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1174) -} - -// ###sourceLocation(file: "/Users/kobe/Desktop/swift-project/swift/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb", line: 1177) - -/// Invokes the given closure with a mutable buffer pointer covering the raw -/// bytes of the given argument. -/// -/// The buffer pointer argument to the `body` closure provides a collection -/// interface to the raw bytes of `value`. The buffer is the size of the -/// instance passed as `value` and does not include any remote storage. -/// -/// - Parameters: -/// - value: An instance to temporarily access through a mutable raw buffer -/// pointer. -/// Note that the `inout` exclusivity rules mean that, like any other -/// `inout` argument, `value` cannot be directly accessed by other code -/// for the duration of `body`. Access must only occur through the pointer -/// argument to `body` until `body` returns. -/// - body: A closure that takes a raw buffer pointer to the bytes of `value` -/// as its sole argument. If the closure has a return value, that value is -/// also used as the return value of the `withUnsafeMutableBytes(of:_:)` -/// function. The buffer pointer argument is valid only for the duration -/// of the closure's execution. -/// - Returns: The return value, if any, of the `body` closure. -@inlinable -public func withUnsafeMutableBytes( - of value: inout T, - _ body: (UnsafeMutableRawBufferPointer) throws -> Result -) rethrows -> Result -{ - return try withUnsafeMutablePointer(to: &value) { - return try body(UnsafeMutableRawBufferPointer( - start: $0, count: MemoryLayout.size)) - } -} - -/// Invokes the given closure with a buffer pointer covering the raw bytes of -/// the given argument. -/// -/// The buffer pointer argument to the `body` closure provides a collection -/// interface to the raw bytes of `value`. The buffer is the size of the -/// instance passed as `value` and does not include any remote storage. -/// -/// - Parameters: -/// - value: An instance to temporarily access through a raw buffer pointer. -/// Note that the `inout` exclusivity rules mean that, like any other -/// `inout` argument, `value` cannot be directly accessed by other code -/// for the duration of `body`. Access must only occur through the pointer -/// argument to `body` until `body` returns. -/// - body: A closure that takes a raw buffer pointer to the bytes of `value` -/// as its sole argument. If the closure has a return value, that value is -/// also used as the return value of the `withUnsafeBytes(of:_:)` -/// function. The buffer pointer argument is valid only for the duration -/// of the closure's execution. It is undefined behavior to attempt to -/// mutate through the pointer by conversion to -/// `UnsafeMutableRawBufferPointer` or any other mutable pointer type. -/// If you want to mutate a value by writing through a pointer, use -/// `withUnsafeMutableBytes(of:_:)` instead. -/// - Returns: The return value, if any, of the `body` closure. -@inlinable -public func withUnsafeBytes( - of value: inout T, - _ body: (UnsafeRawBufferPointer) throws -> Result -) rethrows -> Result -{ - return try withUnsafePointer(to: &value) { - try body(UnsafeRawBufferPointer(start: $0, count: MemoryLayout.size)) - } -} - -/// Invokes the given closure with a buffer pointer covering the raw bytes of -/// the given argument. -/// -/// This function is similar to `withUnsafeBytes`, except that it -/// doesn't trigger stack protection for the pointer. -@_alwaysEmitIntoClient -public func _withUnprotectedUnsafeBytes( - of value: inout T, - _ body: (UnsafeRawBufferPointer) throws -> Result -) rethrows -> Result -{ - return try _withUnprotectedUnsafePointer(to: &value) { - try body(UnsafeRawBufferPointer(start: $0, count: MemoryLayout.size)) - } -} - -/// Invokes the given closure with a buffer pointer covering the raw bytes of -/// the given argument. -/// -/// The buffer pointer argument to the `body` closure provides a collection -/// interface to the raw bytes of `value`. The buffer is the size of the -/// instance passed as `value` and does not include any remote storage. -/// -/// - Parameters: -/// - value: An instance to temporarily access through a raw buffer pointer. -/// - body: A closure that takes a raw buffer pointer to the bytes of `value` -/// as its sole argument. If the closure has a return value, that value is -/// also used as the return value of the `withUnsafeBytes(of:_:)` -/// function. The buffer pointer argument is valid only for the duration -/// of the closure's execution. It is undefined behavior to attempt to -/// mutate through the pointer by conversion to -/// `UnsafeMutableRawBufferPointer` or any other mutable pointer type. -/// If you want to mutate a value by writing through a pointer, use -/// `withUnsafeMutableBytes(of:_:)` instead. -/// - Returns: The return value, if any, of the `body` closure. -@inlinable -public func withUnsafeBytes( - of value: T, - _ body: (UnsafeRawBufferPointer) throws -> Result -) rethrows -> Result { - let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) - let buffer = UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) - return try body(buffer) -} - -/// Invokes the given closure with a buffer pointer covering the raw bytes of -/// the given argument. -/// -/// This function is similar to `withUnsafeBytes`, except that it -/// doesn't trigger stack protection for the pointer. -@_alwaysEmitIntoClient -public func _withUnprotectedUnsafeBytes( - of value: T, - _ body: (UnsafeRawBufferPointer) throws -> Result -) rethrows -> Result { -#if $BuiltinUnprotectedAddressOf - let addr = UnsafeRawPointer(Builtin.unprotectedAddressOfBorrow(value)) -#else - let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) -#endif - let buffer = UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) - return try body(buffer) -} - -@available(*, unavailable) -extension UnsafeRawBufferPointer: Sendable { } -@available(*, unavailable) -extension UnsafeRawBufferPointer.Iterator: Sendable { } -@available(*, unavailable) -extension UnsafeMutableRawBufferPointer: Sendable { } - - -// Local Variables: -// eval: (read-only-mode 1) -// End: From 15e7298b151dd55b8897d4d47d23964eacda3f80 Mon Sep 17 00:00:00 2001 From: Kobe Date: Sat, 18 Nov 2023 10:45:29 +0900 Subject: [PATCH 10/35] [stdlib]Add test case code. - Modified: swift/test/stdlib/UnsafePointerDiagnostics.swift --- test/stdlib/UnsafePointerDiagnostics.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/stdlib/UnsafePointerDiagnostics.swift b/test/stdlib/UnsafePointerDiagnostics.swift index 6a5ff8f74b69c..a70c9b1dc4356 100644 --- a/test/stdlib/UnsafePointerDiagnostics.swift +++ b/test/stdlib/UnsafePointerDiagnostics.swift @@ -101,10 +101,10 @@ func unsafeRawBufferPointerConversions( mrp: UnsafeMutableRawPointer, rp: UnsafeRawPointer, mrbp: UnsafeMutableRawBufferPointer, + rmbp: UnsafeRawMutableBufferPointer, rbp: UnsafeRawBufferPointer, mbpi: UnsafeMutableBufferPointer, - bpi: UnsafeBufferPointer, - rmbp: UnsafeRawMutableBufferPointer) { + bpi: UnsafeBufferPointer) { let omrp: UnsafeMutableRawPointer? = mrp let orp: UnsafeRawPointer? = rp From dcd46c647620a7bbeb48f46d98de8228d23d1dce Mon Sep 17 00:00:00 2001 From: Kobe Date: Sat, 18 Nov 2023 11:03:10 +0900 Subject: [PATCH 11/35] [stdlib]Code indentation and line alignment adjustment. - Modified: swift/test/stdlib/UnsafePointerDiagnostics.swift --- test/stdlib/UnsafePointerDiagnostics.swift | 714 ++++++++++----------- 1 file changed, 357 insertions(+), 357 deletions(-) diff --git a/test/stdlib/UnsafePointerDiagnostics.swift b/test/stdlib/UnsafePointerDiagnostics.swift index a70c9b1dc4356..0741faec5d126 100644 --- a/test/stdlib/UnsafePointerDiagnostics.swift +++ b/test/stdlib/UnsafePointerDiagnostics.swift @@ -4,382 +4,382 @@ // Assume the original source contains no UnsafeRawPointer types. func unsafePointerConversionAvailability( - mrp: UnsafeMutableRawPointer, - rp: UnsafeRawPointer, - umpv: UnsafeMutablePointer, // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - upv: UnsafePointer, // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - umpi: UnsafeMutablePointer, - upi: UnsafePointer, - umps: UnsafeMutablePointer, - ups: UnsafePointer) { - - let omrp: UnsafeMutableRawPointer? = mrp - let orp: UnsafeRawPointer? = rp - let oumpv: UnsafeMutablePointer = umpv // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - let oupv: UnsafePointer? = upv // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - let oumpi: UnsafeMutablePointer? = umpi - let oupi: UnsafePointer? = upi - let oumps: UnsafeMutablePointer? = umps - let oups: UnsafePointer? = ups - - _ = UnsafeMutableRawPointer(mrp) - _ = UnsafeMutableRawPointer(rp) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(umpv) - _ = UnsafeMutableRawPointer(upv) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(umpi) - _ = UnsafeMutableRawPointer(upi) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(umps) - _ = UnsafeMutableRawPointer(ups) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(omrp) - _ = UnsafeMutableRawPointer(orp) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(oumpv) - _ = UnsafeMutableRawPointer(oupv) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(oumpi) - _ = UnsafeMutableRawPointer(oupi) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(oumps) - _ = UnsafeMutableRawPointer(oups) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - - // These all correctly pass with no error. - _ = UnsafeRawPointer(mrp) - _ = UnsafeRawPointer(rp) - _ = UnsafeRawPointer(umpv) - _ = UnsafeRawPointer(upv) - _ = UnsafeRawPointer(umpi) - _ = UnsafeRawPointer(upi) - _ = UnsafeRawPointer(umps) - _ = UnsafeRawPointer(ups) - _ = UnsafeRawPointer(omrp) - _ = UnsafeRawPointer(orp) - _ = UnsafeRawPointer(oumpv) - _ = UnsafeRawPointer(oupv) - _ = UnsafeRawPointer(oumpi) - _ = UnsafeRawPointer(oupi) - _ = UnsafeRawPointer(oumps) - _ = UnsafeRawPointer(oups) - _ = UnsafePointer(upi) - _ = UnsafePointer(oumpi) - _ = UnsafePointer(oupi) - _ = UnsafeMutablePointer(umpi) - _ = UnsafeMutablePointer(oumpi) - - _ = UnsafeMutablePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer'}} expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - _ = UnsafeMutablePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - _ = UnsafeMutablePointer(umpv) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - _ = UnsafeMutablePointer(umpi) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - _ = UnsafeMutablePointer(umps) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - - _ = UnsafePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(umpv) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(upv) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(umpi) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(upi) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(umps) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(ups) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - - _ = UnsafeMutablePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer'}} - _ = UnsafeMutablePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} - _ = UnsafeMutablePointer(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutablePointer'}} - _ = UnsafeMutablePointer(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} - - _ = UnsafePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} - _ = UnsafePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} - _ = UnsafePointer(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} - _ = UnsafePointer(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} - - _ = UnsafePointer(ups) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafePointer'}} - // expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}} - _ = UnsafeMutablePointer(umps) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} - // expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}} - _ = UnsafePointer(upi) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafePointer'}} - // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'String') are expected to be equal}} - _ = UnsafeMutablePointer(umpi) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} - // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'String') are expected to be equal}} -} + mrp: UnsafeMutableRawPointer, + rp: UnsafeRawPointer, + umpv: UnsafeMutablePointer, // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + upv: UnsafePointer, // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + umpi: UnsafeMutablePointer, + upi: UnsafePointer, + umps: UnsafeMutablePointer, + ups: UnsafePointer) { + + let omrp: UnsafeMutableRawPointer? = mrp + let orp: UnsafeRawPointer? = rp + let oumpv: UnsafeMutablePointer = umpv // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + let oupv: UnsafePointer? = upv // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + let oumpi: UnsafeMutablePointer? = umpi + let oupi: UnsafePointer? = upi + let oumps: UnsafeMutablePointer? = umps + let oups: UnsafePointer? = ups + + _ = UnsafeMutableRawPointer(mrp) + _ = UnsafeMutableRawPointer(rp) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(umpv) + _ = UnsafeMutableRawPointer(upv) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(umpi) + _ = UnsafeMutableRawPointer(upi) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(umps) + _ = UnsafeMutableRawPointer(ups) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(omrp) + _ = UnsafeMutableRawPointer(orp) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(oumpv) + _ = UnsafeMutableRawPointer(oupv) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(oumpi) + _ = UnsafeMutableRawPointer(oupi) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(oumps) + _ = UnsafeMutableRawPointer(oups) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + + // These all correctly pass with no error. + _ = UnsafeRawPointer(mrp) + _ = UnsafeRawPointer(rp) + _ = UnsafeRawPointer(umpv) + _ = UnsafeRawPointer(upv) + _ = UnsafeRawPointer(umpi) + _ = UnsafeRawPointer(upi) + _ = UnsafeRawPointer(umps) + _ = UnsafeRawPointer(ups) + _ = UnsafeRawPointer(omrp) + _ = UnsafeRawPointer(orp) + _ = UnsafeRawPointer(oumpv) + _ = UnsafeRawPointer(oupv) + _ = UnsafeRawPointer(oumpi) + _ = UnsafeRawPointer(oupi) + _ = UnsafeRawPointer(oumps) + _ = UnsafeRawPointer(oups) + _ = UnsafePointer(upi) + _ = UnsafePointer(oumpi) + _ = UnsafePointer(oupi) + _ = UnsafeMutablePointer(umpi) + _ = UnsafeMutablePointer(oumpi) + + _ = UnsafeMutablePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer'}} expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + _ = UnsafeMutablePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + _ = UnsafeMutablePointer(umpv) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + _ = UnsafeMutablePointer(umpi) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + _ = UnsafeMutablePointer(umps) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + + _ = UnsafePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(umpv) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(upv) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(umpi) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(upi) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(umps) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(ups) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + + _ = UnsafeMutablePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer'}} + _ = UnsafeMutablePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} + _ = UnsafeMutablePointer(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutablePointer'}} + _ = UnsafeMutablePointer(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} + + _ = UnsafePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} + _ = UnsafePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} + _ = UnsafePointer(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} + _ = UnsafePointer(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} + + _ = UnsafePointer(ups) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafePointer'}} + // expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}} + _ = UnsafeMutablePointer(umps) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} + // expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}} + _ = UnsafePointer(upi) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafePointer'}} + // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'String') are expected to be equal}} + _ = UnsafeMutablePointer(umpi) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} + // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'String') are expected to be equal}} + } func unsafeRawBufferPointerConversions( - mrp: UnsafeMutableRawPointer, - rp: UnsafeRawPointer, - mrbp: UnsafeMutableRawBufferPointer, + mrp: UnsafeMutableRawPointer, + rp: UnsafeRawPointer, + mrbp: UnsafeMutableRawBufferPointer, rmbp: UnsafeRawMutableBufferPointer, - rbp: UnsafeRawBufferPointer, - mbpi: UnsafeMutableBufferPointer, - bpi: UnsafeBufferPointer) { - - let omrp: UnsafeMutableRawPointer? = mrp - let orp: UnsafeRawPointer? = rp - - _ = UnsafeMutableRawBufferPointer(start: mrp, count: 1) - _ = UnsafeRawMutableBufferPointer(start: mrp, count: 1) - _ = UnsafeRawBufferPointer(start: mrp, count: 1) - _ = UnsafeMutableRawBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} - _ = UnsafeRawMutableBufferPointer(start: rp, count: 1) - _ = UnsafeRawBufferPointer(start: rp, count: 1) - _ = UnsafeMutableRawBufferPointer(mrbp) - _ = UnsafeRawMutableBufferPointer(mrbp) - _ = UnsafeRawBufferPointer(mrbp) - _ = UnsafeMutableRawBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} - _ = UnsafeRawMutableBufferPointer(rbp) - _ = UnsafeRawBufferPointer(rbp) - _ = UnsafeMutableRawBufferPointer(mbpi) - _ = UnsafeRawMutableBufferPointer(mbpi) - _ = UnsafeRawBufferPointer(mbpi) - _ = UnsafeMutableRawBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawBufferPointer'}} - _ = UnsafeRawMutableBufferPointer(bpi) - _ = UnsafeRawBufferPointer(bpi) - _ = UnsafeMutableRawBufferPointer(start: omrp, count: 1) - _ = UnsafeRawMutableBufferPointer(start: omrp, count: 1) - _ = UnsafeRawBufferPointer(start: omrp, count: 1) - _ = UnsafeMutableRawBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} - - = UnsafeRawMutableBufferPointer(start: orp, count: 1) - _ = UnsafeRawBufferPointer(start: orp, count: 1) -} + rbp: UnsafeRawBufferPointer, + mbpi: UnsafeMutableBufferPointer, + bpi: UnsafeBufferPointer) { + + let omrp: UnsafeMutableRawPointer? = mrp + let orp: UnsafeRawPointer? = rp + + _ = UnsafeMutableRawBufferPointer(start: mrp, count: 1) + _ = UnsafeRawMutableBufferPointer(start: mrp, count: 1) + _ = UnsafeRawBufferPointer(start: mrp, count: 1) + _ = UnsafeMutableRawBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} + _ = UnsafeRawMutableBufferPointer(start: rp, count: 1) + _ = UnsafeRawBufferPointer(start: rp, count: 1) + _ = UnsafeMutableRawBufferPointer(mrbp) + _ = UnsafeRawMutableBufferPointer(mrbp) + _ = UnsafeRawBufferPointer(mrbp) + _ = UnsafeMutableRawBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} + _ = UnsafeRawMutableBufferPointer(rbp) + _ = UnsafeRawBufferPointer(rbp) + _ = UnsafeMutableRawBufferPointer(mbpi) + _ = UnsafeRawMutableBufferPointer(mbpi) + _ = UnsafeRawBufferPointer(mbpi) + _ = UnsafeMutableRawBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawBufferPointer'}} + _ = UnsafeRawMutableBufferPointer(bpi) + _ = UnsafeRawBufferPointer(bpi) + _ = UnsafeMutableRawBufferPointer(start: omrp, count: 1) + _ = UnsafeRawMutableBufferPointer(start: omrp, count: 1) + _ = UnsafeRawBufferPointer(start: omrp, count: 1) + _ = UnsafeMutableRawBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} + - = UnsafeRawMutableBufferPointer(start: orp, count: 1) + _ = UnsafeRawBufferPointer(start: orp, count: 1) + } // https://github.com/apple/swift/issues/52224 struct S_52224 { - func foo(_: UnsafePointer) {} - func foo(_: UnsafePointer) {} - - func ambiguityTest(buf: UnsafeMutablePointer) { - foo(UnsafePointer(buf)) // this call should be unambiguous - } + func foo(_: UnsafePointer) {} + func foo(_: UnsafePointer) {} + + func ambiguityTest(buf: UnsafeMutablePointer) { + foo(UnsafePointer(buf)) // this call should be unambiguous + } } // Test that we get a custom diagnostic for an ephemeral conversion to non-ephemeral param for an Unsafe[Mutable][Raw][Buffer]Pointer init. func unsafePointerInitEphemeralConversions() { - class C {} - var foo = 0 - var str = "" - var arr = [0] - var optionalArr: [Int]? = [0] - var c: C? - - _ = UnsafePointer(&foo) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer(&foo + 1) // expected-error {{cannot use inout expression here; argument #1 must be a pointer that outlives the call to '+'}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to '+'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer.init(&foo) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer("") // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer.init("") // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer(str) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer([0]) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafePointer(arr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafePointer(&arr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafePointer(optionalArr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(_:)'}} - - - _ = UnsafeMutablePointer(&foo) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(&arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(&arr + 2) // expected-error {{cannot use inout expression here; argument #1 must be a pointer that outlives the call to '+'}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to '+'}} - // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: &foo) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: "") // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: str) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: [0]) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: &arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: optionalArr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - - - _ = UnsafeRawPointer(&foo) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawPointer(str) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeRawPointer(arr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawPointer(&arr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawPointer(optionalArr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(_:)'}} - - - _ = UnsafeMutableRawPointer(&foo) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(&arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: &foo) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use 'withUnsafeBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: str) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: &arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: optionalArr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - - _ = UnsafeBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeBufferPointer.init(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeBufferPointer(start: str, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeBufferPointer.init(start: str, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeBufferPointer(start: arr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeBufferPointer(start: optionalArr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - - _ = UnsafeMutableBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutablePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutableBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - - _ = UnsafeRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafeBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawBufferPointer(start: str, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeRawBufferPointer(start: arr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawBufferPointer(start: optionalArr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - - - _ = UnsafeMutableRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + class C {} + var foo = 0 + var str = "" + var arr = [0] + var optionalArr: [Int]? = [0] + var c: C? + + _ = UnsafePointer(&foo) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer(&foo + 1) // expected-error {{cannot use inout expression here; argument #1 must be a pointer that outlives the call to '+'}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to '+'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer.init(&foo) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer("") // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer.init("") // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer(str) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer([0]) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafePointer(arr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafePointer(&arr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafePointer(optionalArr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(_:)'}} + + + _ = UnsafeMutablePointer(&foo) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(&arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(&arr + 2) // expected-error {{cannot use inout expression here; argument #1 must be a pointer that outlives the call to '+'}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to '+'}} + // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: &foo) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: "") // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: str) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: [0]) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: &arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: optionalArr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + + + _ = UnsafeRawPointer(&foo) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawPointer(str) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeRawPointer(arr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawPointer(&arr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawPointer(optionalArr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(_:)'}} + + + _ = UnsafeMutableRawPointer(&foo) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(&arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: &foo) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use 'withUnsafeBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: str) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: &arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: optionalArr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + + _ = UnsafeBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeBufferPointer.init(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeBufferPointer(start: str, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeBufferPointer.init(start: str, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeBufferPointer(start: arr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeBufferPointer(start: optionalArr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + + _ = UnsafeMutableBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutablePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutableBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + + _ = UnsafeRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafeBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawBufferPointer(start: str, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeRawBufferPointer(start: arr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawBufferPointer(start: optionalArr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + + + _ = UnsafeMutableRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} _ = UnsafeRawMutableBufferPointer(start: &foo, count: 0) - - _ = UnsafeMutableRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} _ = UnsafeRawMutableBufferPointer(start: &arr, count: 0) - - - // FIXME: This is currently ambiguous. - _ = OpaquePointer(&foo) // expected-error {{no exact matches in call to initializer}} - - - // FIXME: This is currently ambiguous. - _ = OpaquePointer(&arr) // expected-error {{no exact matches in call to initializer}} - - _ = OpaquePointer(arr) // expected-error {{initialization of 'OpaquePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = OpaquePointer(str) // expected-error {{initialization of 'OpaquePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + + // FIXME: This is currently ambiguous. + _ = OpaquePointer(&foo) // expected-error {{no exact matches in call to initializer}} + + + // FIXME: This is currently ambiguous. + _ = OpaquePointer(&arr) // expected-error {{no exact matches in call to initializer}} + + _ = OpaquePointer(arr) // expected-error {{initialization of 'OpaquePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = OpaquePointer(str) // expected-error {{initialization of 'OpaquePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} } var global = 0 // Test that we allow non-ephemeral conversions, such as inout-to-pointer for globals. func unsafePointerInitNonEphemeralConversions() { - _ = UnsafePointer(&global) - _ = UnsafeMutablePointer(&global) - _ = UnsafeRawPointer(&global) - _ = UnsafeMutableRawPointer(&global) - _ = UnsafeBufferPointer(start: &global, count: 0) - _ = UnsafeMutableBufferPointer(start: &global, count: 0) - _ = UnsafeRawBufferPointer(start: &global, count: 0) - _ = UnsafeMutableRawBufferPointer(start: &global, count: 0) + _ = UnsafePointer(&global) + _ = UnsafeMutablePointer(&global) + _ = UnsafeRawPointer(&global) + _ = UnsafeMutableRawPointer(&global) + _ = UnsafeBufferPointer(start: &global, count: 0) + _ = UnsafeMutableBufferPointer(start: &global, count: 0) + _ = UnsafeRawBufferPointer(start: &global, count: 0) + _ = UnsafeMutableRawBufferPointer(start: &global, count: 0) _ = UnsafeRawMutableBufferPointer(start: &global, count: 0) - - // FIXME: This is currently ambiguous. - _ = OpaquePointer(&global) // expected-error {{ambiguous use of 'init(_:)'}} + + // FIXME: This is currently ambiguous. + _ = OpaquePointer(&global) // expected-error {{ambiguous use of 'init(_:)'}} } From 46bd22a122ea1877a7aebde09c344746f927edfb Mon Sep 17 00:00:00 2001 From: Kobe Date: Sat, 18 Nov 2023 11:10:44 +0900 Subject: [PATCH 12/35] [stdlib]Code indentation and line alignment adjustment. - Modified: swift/test/stdlib/UnsafePointerDiagnostics.swift --- test/stdlib/UnsafePointerDiagnostics.swift | 726 ++++++++++----------- 1 file changed, 363 insertions(+), 363 deletions(-) diff --git a/test/stdlib/UnsafePointerDiagnostics.swift b/test/stdlib/UnsafePointerDiagnostics.swift index 0741faec5d126..6b70b83bcf3e0 100644 --- a/test/stdlib/UnsafePointerDiagnostics.swift +++ b/test/stdlib/UnsafePointerDiagnostics.swift @@ -4,382 +4,382 @@ // Assume the original source contains no UnsafeRawPointer types. func unsafePointerConversionAvailability( - mrp: UnsafeMutableRawPointer, - rp: UnsafeRawPointer, - umpv: UnsafeMutablePointer, // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - upv: UnsafePointer, // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - umpi: UnsafeMutablePointer, - upi: UnsafePointer, - umps: UnsafeMutablePointer, - ups: UnsafePointer) { - - let omrp: UnsafeMutableRawPointer? = mrp - let orp: UnsafeRawPointer? = rp - let oumpv: UnsafeMutablePointer = umpv // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - let oupv: UnsafePointer? = upv // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - let oumpi: UnsafeMutablePointer? = umpi - let oupi: UnsafePointer? = upi - let oumps: UnsafeMutablePointer? = umps - let oups: UnsafePointer? = ups - - _ = UnsafeMutableRawPointer(mrp) - _ = UnsafeMutableRawPointer(rp) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(umpv) - _ = UnsafeMutableRawPointer(upv) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(umpi) - _ = UnsafeMutableRawPointer(upi) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(umps) - _ = UnsafeMutableRawPointer(ups) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(omrp) - _ = UnsafeMutableRawPointer(orp) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(oumpv) - _ = UnsafeMutableRawPointer(oupv) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(oumpi) - _ = UnsafeMutableRawPointer(oupi) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - _ = UnsafeMutableRawPointer(oumps) - _ = UnsafeMutableRawPointer(oups) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} - - // These all correctly pass with no error. - _ = UnsafeRawPointer(mrp) - _ = UnsafeRawPointer(rp) - _ = UnsafeRawPointer(umpv) - _ = UnsafeRawPointer(upv) - _ = UnsafeRawPointer(umpi) - _ = UnsafeRawPointer(upi) - _ = UnsafeRawPointer(umps) - _ = UnsafeRawPointer(ups) - _ = UnsafeRawPointer(omrp) - _ = UnsafeRawPointer(orp) - _ = UnsafeRawPointer(oumpv) - _ = UnsafeRawPointer(oupv) - _ = UnsafeRawPointer(oumpi) - _ = UnsafeRawPointer(oupi) - _ = UnsafeRawPointer(oumps) - _ = UnsafeRawPointer(oups) - _ = UnsafePointer(upi) - _ = UnsafePointer(oumpi) - _ = UnsafePointer(oupi) - _ = UnsafeMutablePointer(umpi) - _ = UnsafeMutablePointer(oumpi) - - _ = UnsafeMutablePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer'}} expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - _ = UnsafeMutablePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - _ = UnsafeMutablePointer(umpv) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - _ = UnsafeMutablePointer(umpi) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - _ = UnsafeMutablePointer(umps) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} - - _ = UnsafePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(umpv) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(upv) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(umpi) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(upi) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(umps) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - _ = UnsafePointer(ups) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} - - _ = UnsafeMutablePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer'}} - _ = UnsafeMutablePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} - _ = UnsafeMutablePointer(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutablePointer'}} - _ = UnsafeMutablePointer(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} - - _ = UnsafePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} - _ = UnsafePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} - _ = UnsafePointer(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} - _ = UnsafePointer(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} - - _ = UnsafePointer(ups) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafePointer'}} - // expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}} - _ = UnsafeMutablePointer(umps) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} - // expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}} - _ = UnsafePointer(upi) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafePointer'}} - // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'String') are expected to be equal}} - _ = UnsafeMutablePointer(umpi) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} - // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'String') are expected to be equal}} - } + mrp: UnsafeMutableRawPointer, + rp: UnsafeRawPointer, + umpv: UnsafeMutablePointer, // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + upv: UnsafePointer, // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + umpi: UnsafeMutablePointer, + upi: UnsafePointer, + umps: UnsafeMutablePointer, + ups: UnsafePointer) { + + let omrp: UnsafeMutableRawPointer? = mrp + let orp: UnsafeRawPointer? = rp + let oumpv: UnsafeMutablePointer = umpv // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + let oupv: UnsafePointer? = upv // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + let oumpi: UnsafeMutablePointer? = umpi + let oupi: UnsafePointer? = upi + let oumps: UnsafeMutablePointer? = umps + let oups: UnsafePointer? = ups + + _ = UnsafeMutableRawPointer(mrp) + _ = UnsafeMutableRawPointer(rp) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(umpv) + _ = UnsafeMutableRawPointer(upv) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(umpi) + _ = UnsafeMutableRawPointer(upi) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(umps) + _ = UnsafeMutableRawPointer(ups) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(omrp) + _ = UnsafeMutableRawPointer(orp) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(oumpv) + _ = UnsafeMutableRawPointer(oupv) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(oumpi) + _ = UnsafeMutableRawPointer(oupi) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + _ = UnsafeMutableRawPointer(oumps) + _ = UnsafeMutableRawPointer(oups) // expected-error {{'init(_:)' has been renamed to 'init(mutating:)'}} + + // These all correctly pass with no error. + _ = UnsafeRawPointer(mrp) + _ = UnsafeRawPointer(rp) + _ = UnsafeRawPointer(umpv) + _ = UnsafeRawPointer(upv) + _ = UnsafeRawPointer(umpi) + _ = UnsafeRawPointer(upi) + _ = UnsafeRawPointer(umps) + _ = UnsafeRawPointer(ups) + _ = UnsafeRawPointer(omrp) + _ = UnsafeRawPointer(orp) + _ = UnsafeRawPointer(oumpv) + _ = UnsafeRawPointer(oupv) + _ = UnsafeRawPointer(oumpi) + _ = UnsafeRawPointer(oupi) + _ = UnsafeRawPointer(oumps) + _ = UnsafeRawPointer(oups) + _ = UnsafePointer(upi) + _ = UnsafePointer(oumpi) + _ = UnsafePointer(oupi) + _ = UnsafeMutablePointer(umpi) + _ = UnsafeMutablePointer(oumpi) + + _ = UnsafeMutablePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer'}} expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + _ = UnsafeMutablePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + _ = UnsafeMutablePointer(umpv) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + _ = UnsafeMutablePointer(umpi) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + _ = UnsafeMutablePointer(umps) // expected-warning {{UnsafeMutablePointer has been replaced by UnsafeMutableRawPointer}} + + _ = UnsafePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(umpv) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(upv) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(umpi) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(upi) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(umps) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + _ = UnsafePointer(ups) // expected-warning {{UnsafePointer has been replaced by UnsafeRawPointer}} + + _ = UnsafeMutablePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer'}} + _ = UnsafeMutablePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} + _ = UnsafeMutablePointer(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutablePointer'}} + _ = UnsafeMutablePointer(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer'}} + + _ = UnsafePointer(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} + _ = UnsafePointer(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} + _ = UnsafePointer(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer'}} + _ = UnsafePointer(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer'}} + + _ = UnsafePointer(ups) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafePointer'}} + // expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}} + _ = UnsafeMutablePointer(umps) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} + // expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}} + _ = UnsafePointer(upi) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafePointer'}} + // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'String') are expected to be equal}} + _ = UnsafeMutablePointer(umpi) // expected-error {{cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'}} + // expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'String') are expected to be equal}} + } func unsafeRawBufferPointerConversions( - mrp: UnsafeMutableRawPointer, - rp: UnsafeRawPointer, - mrbp: UnsafeMutableRawBufferPointer, - rmbp: UnsafeRawMutableBufferPointer, - rbp: UnsafeRawBufferPointer, - mbpi: UnsafeMutableBufferPointer, - bpi: UnsafeBufferPointer) { - - let omrp: UnsafeMutableRawPointer? = mrp - let orp: UnsafeRawPointer? = rp - - _ = UnsafeMutableRawBufferPointer(start: mrp, count: 1) - _ = UnsafeRawMutableBufferPointer(start: mrp, count: 1) - _ = UnsafeRawBufferPointer(start: mrp, count: 1) - _ = UnsafeMutableRawBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} - _ = UnsafeRawMutableBufferPointer(start: rp, count: 1) - _ = UnsafeRawBufferPointer(start: rp, count: 1) - _ = UnsafeMutableRawBufferPointer(mrbp) - _ = UnsafeRawMutableBufferPointer(mrbp) - _ = UnsafeRawBufferPointer(mrbp) - _ = UnsafeMutableRawBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} - _ = UnsafeRawMutableBufferPointer(rbp) - _ = UnsafeRawBufferPointer(rbp) - _ = UnsafeMutableRawBufferPointer(mbpi) - _ = UnsafeRawMutableBufferPointer(mbpi) - _ = UnsafeRawBufferPointer(mbpi) - _ = UnsafeMutableRawBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawBufferPointer'}} - _ = UnsafeRawMutableBufferPointer(bpi) - _ = UnsafeRawBufferPointer(bpi) - _ = UnsafeMutableRawBufferPointer(start: omrp, count: 1) - _ = UnsafeRawMutableBufferPointer(start: omrp, count: 1) - _ = UnsafeRawBufferPointer(start: omrp, count: 1) - _ = UnsafeMutableRawBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} - - = UnsafeRawMutableBufferPointer(start: orp, count: 1) - _ = UnsafeRawBufferPointer(start: orp, count: 1) - } + mrp: UnsafeMutableRawPointer, + rp: UnsafeRawPointer, + mrbp: UnsafeMutableRawBufferPointer, + rmbp: UnsafeRawMutableBufferPointer, + rbp: UnsafeRawBufferPointer, + mbpi: UnsafeMutableBufferPointer, + bpi: UnsafeBufferPointer) { + + let omrp: UnsafeMutableRawPointer? = mrp + let orp: UnsafeRawPointer? = rp + + _ = UnsafeMutableRawBufferPointer(start: mrp, count: 1) + _ = UnsafeRawMutableBufferPointer(start: mrp, count: 1) + _ = UnsafeRawBufferPointer(start: mrp, count: 1) + _ = UnsafeMutableRawBufferPointer(start: rp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer?'}} + _ = UnsafeRawMutableBufferPointer(start: rp, count: 1) + _ = UnsafeRawBufferPointer(start: rp, count: 1) + _ = UnsafeMutableRawBufferPointer(mrbp) + _ = UnsafeRawMutableBufferPointer(mrbp) + _ = UnsafeRawBufferPointer(mrbp) + _ = UnsafeMutableRawBufferPointer(rbp) // expected-error {{missing argument label 'mutating:' in call}} + _ = UnsafeRawMutableBufferPointer(rbp) + _ = UnsafeRawBufferPointer(rbp) + _ = UnsafeMutableRawBufferPointer(mbpi) + _ = UnsafeRawMutableBufferPointer(mbpi) + _ = UnsafeRawBufferPointer(mbpi) + _ = UnsafeMutableRawBufferPointer(bpi) // expected-error {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawBufferPointer'}} + _ = UnsafeRawMutableBufferPointer(bpi) + _ = UnsafeRawBufferPointer(bpi) + _ = UnsafeMutableRawBufferPointer(start: omrp, count: 1) + _ = UnsafeRawMutableBufferPointer(start: omrp, count: 1) + _ = UnsafeRawBufferPointer(start: omrp, count: 1) + _ = UnsafeMutableRawBufferPointer(start: orp, count: 1) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutableRawPointer?'}} + - = UnsafeRawMutableBufferPointer(start: orp, count: 1) + _ = UnsafeRawBufferPointer(start: orp, count: 1) + } // https://github.com/apple/swift/issues/52224 struct S_52224 { - func foo(_: UnsafePointer) {} - func foo(_: UnsafePointer) {} - - func ambiguityTest(buf: UnsafeMutablePointer) { - foo(UnsafePointer(buf)) // this call should be unambiguous - } + func foo(_: UnsafePointer) {} + func foo(_: UnsafePointer) {} + + func ambiguityTest(buf: UnsafeMutablePointer) { + foo(UnsafePointer(buf)) // this call should be unambiguous + } } // Test that we get a custom diagnostic for an ephemeral conversion to non-ephemeral param for an Unsafe[Mutable][Raw][Buffer]Pointer init. func unsafePointerInitEphemeralConversions() { - class C {} - var foo = 0 - var str = "" - var arr = [0] - var optionalArr: [Int]? = [0] - var c: C? - - _ = UnsafePointer(&foo) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer(&foo + 1) // expected-error {{cannot use inout expression here; argument #1 must be a pointer that outlives the call to '+'}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to '+'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer.init(&foo) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer("") // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer.init("") // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer(str) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafePointer([0]) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafePointer(arr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafePointer(&arr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafePointer(optionalArr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(_:)'}} - - - _ = UnsafeMutablePointer(&foo) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(&arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(&arr + 2) // expected-error {{cannot use inout expression here; argument #1 must be a pointer that outlives the call to '+'}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to '+'}} - // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: &foo) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: "") // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: str) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: [0]) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: &arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutablePointer(mutating: optionalArr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - - - _ = UnsafeRawPointer(&foo) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawPointer(str) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeRawPointer(arr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawPointer(&arr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawPointer(optionalArr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(_:)'}} - - - _ = UnsafeMutableRawPointer(&foo) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(&arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: &foo) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use 'withUnsafeBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: str) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: &arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeMutableRawPointer(mutating: optionalArr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(mutating:)}} - - _ = UnsafeBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeBufferPointer.init(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeBufferPointer(start: str, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeBufferPointer.init(start: str, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeBufferPointer(start: arr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeBufferPointer(start: optionalArr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - - _ = UnsafeMutableBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutablePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeMutableBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - - _ = UnsafeRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafeBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawBufferPointer(start: str, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} - - _ = UnsafeRawBufferPointer(start: arr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawBufferPointer(start: optionalArr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - - - _ = UnsafeMutableRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawMutableBufferPointer(start: &foo, count: 0) - - _ = UnsafeMutableRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} - // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = UnsafeRawMutableBufferPointer(start: &arr, count: 0) - - - // FIXME: This is currently ambiguous. - _ = OpaquePointer(&foo) // expected-error {{no exact matches in call to initializer}} - - - // FIXME: This is currently ambiguous. - _ = OpaquePointer(&arr) // expected-error {{no exact matches in call to initializer}} - - _ = OpaquePointer(arr) // expected-error {{initialization of 'OpaquePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} - - _ = OpaquePointer(str) // expected-error {{initialization of 'OpaquePointer' results in a dangling pointer}} - // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} - // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + class C {} + var foo = 0 + var str = "" + var arr = [0] + var optionalArr: [Int]? = [0] + var c: C? + + _ = UnsafePointer(&foo) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer(&foo + 1) // expected-error {{cannot use inout expression here; argument #1 must be a pointer that outlives the call to '+'}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to '+'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer.init(&foo) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer("") // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer.init("") // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer(str) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafePointer([0]) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafePointer(arr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafePointer(&arr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafePointer(optionalArr) // expected-error {{initialization of 'UnsafePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(_:)'}} + + + _ = UnsafeMutablePointer(&foo) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(&arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(&arr + 2) // expected-error {{cannot use inout expression here; argument #1 must be a pointer that outlives the call to '+'}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer' produces a pointer valid only for the duration of the call to '+'}} + // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: &foo) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: "") // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: str) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: [0]) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: &arr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutablePointer(mutating: optionalArr) // expected-error {{initialization of 'UnsafeMutablePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + + + _ = UnsafeRawPointer(&foo) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawPointer(str) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeRawPointer(arr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawPointer(&arr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawPointer(optionalArr) // expected-error {{initialization of 'UnsafeRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(_:)'}} + + + _ = UnsafeMutableRawPointer(&foo) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(&arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: &foo) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use 'withUnsafeBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: str) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: &arr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeMutableRawPointer(mutating: optionalArr) // expected-error {{initialization of 'UnsafeMutableRawPointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(mutating:)}} + + _ = UnsafeBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeBufferPointer.init(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeBufferPointer(start: str, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeBufferPointer.init(start: str, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeBufferPointer(start: arr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeBufferPointer(start: optionalArr, count: 0) // expected-error {{initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + + _ = UnsafeMutableBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutablePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeMutableBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutablePointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + + _ = UnsafeRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafeBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawBufferPointer(start: str, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} + + _ = UnsafeRawBufferPointer(start: arr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawBufferPointer(start: optionalArr, count: 0) // expected-error {{initialization of 'UnsafeRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]?' to 'UnsafeRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + + + _ = UnsafeMutableRawBufferPointer(start: &foo, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from 'Int' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use 'withUnsafeMutableBytes' in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawMutableBufferPointer(start: &foo, count: 0) + + _ = UnsafeMutableRawBufferPointer(start: &arr, count: 0) // expected-error {{initialization of 'UnsafeMutableRawBufferPointer' results in a dangling buffer pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeMutableRawPointer?' produces a pointer valid only for the duration of the call to 'init(start:count:)'}} + // expected-note@-2 {{use the 'withUnsafeMutableBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = UnsafeRawMutableBufferPointer(start: &arr, count: 0) + + + // FIXME: This is currently ambiguous. + _ = OpaquePointer(&foo) // expected-error {{no exact matches in call to initializer}} + + + // FIXME: This is currently ambiguous. + _ = OpaquePointer(&arr) // expected-error {{no exact matches in call to initializer}} + + _ = OpaquePointer(arr) // expected-error {{initialization of 'OpaquePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from '[Int]' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withUnsafeBytes' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}} + + _ = OpaquePointer(str) // expected-error {{initialization of 'OpaquePointer' results in a dangling pointer}} + // expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafeRawPointer' produces a pointer valid only for the duration of the call to 'init(_:)'}} + // expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}} } var global = 0 // Test that we allow non-ephemeral conversions, such as inout-to-pointer for globals. func unsafePointerInitNonEphemeralConversions() { - _ = UnsafePointer(&global) - _ = UnsafeMutablePointer(&global) - _ = UnsafeRawPointer(&global) - _ = UnsafeMutableRawPointer(&global) - _ = UnsafeBufferPointer(start: &global, count: 0) - _ = UnsafeMutableBufferPointer(start: &global, count: 0) - _ = UnsafeRawBufferPointer(start: &global, count: 0) - _ = UnsafeMutableRawBufferPointer(start: &global, count: 0) - _ = UnsafeRawMutableBufferPointer(start: &global, count: 0) - - // FIXME: This is currently ambiguous. - _ = OpaquePointer(&global) // expected-error {{ambiguous use of 'init(_:)'}} + _ = UnsafePointer(&global) + _ = UnsafeMutablePointer(&global) + _ = UnsafeRawPointer(&global) + _ = UnsafeMutableRawPointer(&global) + _ = UnsafeBufferPointer(start: &global, count: 0) + _ = UnsafeMutableBufferPointer(start: &global, count: 0) + _ = UnsafeRawBufferPointer(start: &global, count: 0) + _ = UnsafeMutableRawBufferPointer(start: &global, count: 0) + _ = UnsafeRawMutableBufferPointer(start: &global, count: 0) + + // FIXME: This is currently ambiguous. + _ = OpaquePointer(&global) // expected-error {{ambiguous use of 'init(_:)'}} } From 253a8cf538fd2dd14d435d8c8356bad75e78f7f0 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Tue, 21 Nov 2023 15:02:56 +0000 Subject: [PATCH 13/35] [Profiler] Fix ternary error handling coverage Previously the branches of a ternary would cut off the coverage after a throwing expression, since they have their own region, and we pop child regions when leaving. Update the logic to use the existing counter adjustment logic when we leave the scope, ensuring that we push a new counter to reflect the exit count of the scope. --- lib/SIL/IR/SILProfiler.cpp | 122 +++++++++++++---------- test/Profiler/coverage_errors.swift | 89 +++++++++++++++++ test/Profiler/coverage_errors_exec.swift | 28 ++++++ 3 files changed, 184 insertions(+), 55 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index d2d15933f781a..f3632367e8f9c 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -876,22 +876,28 @@ struct CoverageMapping : public ASTWalker { /// Adjust the count for control flow when exiting a scope. void adjustForNonLocalExits(ASTNode Scope, llvm::Optional ControlFlowAdjust) { - if (Parent.getAsDecl()) + // If there are no regions left, there's nothing to adjust. + if (RegionStack.empty()) return; + // If the region is for a brace, check to see if we have a parent labeled + // statement, in which case the exit count needs to account for any direct + // jumps to it though e.g break statements. llvm::Optional JumpsToLabel; - if (auto *ParentStmt = Parent.getAsStmt()) { - if (auto *DCS = dyn_cast(ParentStmt)) { - // We need to handle the brace of a DoCatchStmt here specially, - // applying the same logic we apply to the catch clauses (handled by - // the CaseStmt logic), we add on the exit count of the branch to the - // statement's exit count. - addToCounter(DCS, getExitCounter()); - return; - } + if (Scope.isStmt(StmtKind::Brace)) { + if (auto *ParentStmt = Parent.getAsStmt()) { + if (auto *DCS = dyn_cast(ParentStmt)) { + // We need to handle the brace of a DoCatchStmt here specially, + // applying the same logic we apply to the catch clauses (handled by + // the CaseStmt logic), we add on the exit count of the branch to the + // statement's exit count. + addToCounter(DCS, getExitCounter()); + return; + } - if (auto *LS = dyn_cast(ParentStmt)) - JumpsToLabel = getCounter(LS); + if (auto *LS = dyn_cast(ParentStmt)) + JumpsToLabel = getCounter(LS); + } } if (!ControlFlowAdjust && !JumpsToLabel) @@ -942,46 +948,55 @@ struct CoverageMapping : public ASTWalker { return Lexer::getLocForEndOfToken(SM, Node.getEndLoc()); } + /// Record a popped region in the resulting list of regions. + void takePoppedRegion(SourceMappingRegion &&Region, SourceLoc ParentEndLoc) { + LLVM_DEBUG({ + llvm::dbgs() << "Popped region: "; + Region.print(llvm::dbgs(), SM); + llvm::dbgs() << "\n"; + }); + + // Don't record incomplete regions. + if (!Region.hasStartLoc()) + return; + + // Set the region end location to the end location of the parent. + if (!Region.hasEndLoc()) + Region.setEndLoc(ParentEndLoc); + + // If the range ended up being empty, ignore it (this can happen when we + // replace the counter, and don't extend the region any further). + if (!Region.hasNonEmptyRange()) + return; + + SourceRegions.push_back(std::move(Region)); + } + /// Pop regions from the stack into the function's list of regions. /// /// Adds all regions from \c ParentNode to the top of the stack to the /// function's \c SourceRegions. void popRegions(ASTNode ParentNode) { - auto I = RegionStack.begin(), E = RegionStack.end(); - while (I != E && - I->getNode().getOpaqueValue() != ParentNode.getOpaqueValue()) - ++I; + auto I = llvm::find_if(RegionStack, [&](const SourceMappingRegion &Region) { + return Region.getNode().getOpaqueValue() == ParentNode.getOpaqueValue(); + }); + auto E = RegionStack.end(); assert(I != E && "parent not in stack"); - auto ParentIt = I; - SourceLoc EndLoc = ParentIt->getEndLoc(); - assert(ParentIt->hasNonEmptyRange() && "Pushed node with empty range?"); - - unsigned FirstPoppedIndex = SourceRegions.size(); - (void)FirstPoppedIndex; - SourceRegions.push_back(std::move(*I++)); - for (; I != E; ++I) { - if (!I->hasStartLoc()) - continue; - if (!I->hasEndLoc()) - I->setEndLoc(EndLoc); - - // If the range ended up being empty, ignore it (this can happen when we - // replace the counter, and don't extend the region any further). - if (!I->hasNonEmptyRange()) - continue; - - SourceRegions.push_back(std::move(*I)); - } + assert(I->hasNonEmptyRange() && "Pushed node with empty range?"); - LLVM_DEBUG({ - for (unsigned Idx = FirstPoppedIndex; Idx < SourceRegions.size(); ++Idx) { - llvm::dbgs() << "Popped region: "; - SourceRegions[Idx].print(llvm::dbgs(), SM); - llvm::dbgs() << "\n"; - } - }); + auto EndLoc = I->getEndLoc(); + for (auto &Region : llvm::make_range(I, E)) + takePoppedRegion(std::move(Region), EndLoc); - RegionStack.erase(ParentIt, E); + RegionStack.erase(I, E); + } + + /// Exit the given region, popping it and its children from the region stack, + /// and adjusting the following counter if needed. + void exitRegion(ASTNode Node) { + auto Adjust = setExitCount(Node); + popRegions(Node); + adjustForNonLocalExits(Node, Adjust); } /// Return the currently active region. @@ -1217,11 +1232,8 @@ struct CoverageMapping : public ASTWalker { return Action::Continue(S); if (isa(S)) { - if (hasCounter(S)) { - auto Adjust = setExitCount(S); - popRegions(S); - adjustForNonLocalExits(S, Adjust); - } + if (hasCounter(S)) + exitRegion(S); } else if (auto *WS = dyn_cast(S)) { // Update the condition with the backedge count. @@ -1339,18 +1351,18 @@ struct CoverageMapping : public ASTWalker { if (shouldSkipExpr(E)) return Action::Continue(E); - if (hasCounter(E)) - popRegions(E); - - // The region following the expression gets current counter minus the - // error branch counter, i.e the number of times we didn't throw an error. - if (!RegionStack.empty() && mayExpressionThrow(E)) { + // The region following the expression gets current counter minus the error + // branch counter, i.e the number of times we didn't throw an error. + if (mayExpressionThrow(E)) { auto ThrowCount = assignKnownCounter(ProfileCounterRef::errorBranchOf(E)); replaceCount( CounterExpr::Sub(getCurrentCounter(), ThrowCount, CounterBuilder), Lexer::getLocForEndOfToken(SM, E->getEndLoc())); } + if (hasCounter(E)) + exitRegion(E); + return Action::Continue(E); } }; diff --git a/test/Profiler/coverage_errors.swift b/test/Profiler/coverage_errors.swift index 90bdbb56d2d2a..1af1518598231 100644 --- a/test/Profiler/coverage_errors.swift +++ b/test/Profiler/coverage_errors.swift @@ -150,6 +150,33 @@ enum SomeErr : Error { // CHECK: [[BB_ERR]] // CHECK-NEXT: increment_profiler_counter 1 +// func test28() throws -> Int { +// let x = try .random() +// ? throwingFn() +// : throwingFn() +// return x +// } +// CHECK-LABEL: sil hidden @$s15coverage_errors6test28SiyKF : $@convention(thin) () -> (Int, @error any Error) +// CHECK: bb0: +// CHECK: increment_profiler_counter 0 +// CHECK: function_ref @$sSb6randomSbyFZ +// CHECK: cond_br {{%[0-9]+}}, [[BB_TRUE:bb[0-9]+]], [[BB_FALSE:bb[0-9]+]] +// +// CHECK: [[BB_FALSE]] +// CHECK: [[THROW_FN:%[0-9]+]] = function_ref @$s15coverage_errors10throwingFnSiyKF +// CHECK: try_apply [[THROW_FN]]() : $@convention(thin) () -> (Int, @error any Error), normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERR:bb[0-9]+]] +// +// CHECK: [[BB_ERR]] +// CHECK: increment_profiler_counter 3 +// +// CHECK: [[BB_TRUE]] +// CHECK: increment_profiler_counter 1 +// CHECK: [[THROW_FN:%[0-9]+]] = function_ref @$s15coverage_errors10throwingFnSiyKF +// CHECK: try_apply [[THROW_FN]]() : $@convention(thin) () -> (Int, @error any Error), normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERR:bb[0-9]+]] +// +// CHECK: [[BB_ERR]] +// CHECK: increment_profiler_counter 2 + // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors5test1SiyF" func test1() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+7]]:2 : 0 do { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE+3]]:4 : 0 @@ -402,6 +429,68 @@ func test23() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+11]]:2 : 0 return 2 } // CHECK-NEXT: } +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test24SiyKF" +func test24() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+4]]:2 : 0 + let x = .random() ? try throwingFn() : 0 // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE]]:39 : 1 + return x // CHECK-NEXT: [[@LINE-1]]:39 -> [[@LINE]]:11 : (0 - 2) + // CHECK-NEXT: [[@LINE-2]]:42 -> [[@LINE-2]]:43 : (0 - 1) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test25SiyKF" +func test25() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+4]]:2 : 0 + let x = .random() ? 0 : try throwingFn() // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE]]:24 : 1 + return x // CHECK-NEXT: [[@LINE-1]]:27 -> [[@LINE-1]]:43 : (0 - 1) + // CHECK-NEXT: [[@LINE-2]]:43 -> [[@LINE-1]]:11 : (0 - 2) +} // CHECK-NEXT: } + +// Note in this case the throws region of the first branch overlaps the +// second branch, which isn't ideal, but it matches what we already do +// for e.g if statements and returns, and doesn't impact the resulting +// coverage since we always take the counter for the smallest subrange, +// which in this case is the region for the second branch. +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test26SiyKF" +func test26() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+5]]:2 : 0 + let x = .random() ? try throwingFn() : try throwingFn() // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE]]:39 : 1 + return x // CHECK-NEXT: [[@LINE-1]]:39 -> [[@LINE]]:11 : (0 - 2) + // CHECK-NEXT: [[@LINE-2]]:42 -> [[@LINE-2]]:58 : (0 - 1) + // CHECK-NEXT: [[@LINE-3]]:58 -> [[@LINE-2]]:11 : ((0 - 2) - 3) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test27SiyKF" +func test27() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+5]]:2 : 0 + let x = try .random() ? throwingFn() : throwingFn() // CHECK-NEXT: [[@LINE]]:27 -> [[@LINE]]:39 : 1 + return x // CHECK-NEXT: [[@LINE-1]]:39 -> [[@LINE]]:11 : (0 - 2) + // CHECK-NEXT: [[@LINE-2]]:42 -> [[@LINE-2]]:54 : (0 - 1) + // CHECK-NEXT: [[@LINE-3]]:54 -> [[@LINE-2]]:11 : ((0 - 2) - 3) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test28SiyKF" +func test28() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+5]]:2 : 0 + let x = try .random() // CHECK-NEXT: [[@LINE+1]]:7 -> [[@LINE+1]]:19 : 1 + ? throwingFn() // CHECK-NEXT: [[@LINE]]:19 -> [[@LINE+2]]:11 : (0 - 2) + : throwingFn() // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:19 : (0 - 1) + return x // CHECK-NEXT: [[@LINE-1]]:19 -> [[@LINE]]:11 : ((0 - 2) - 3) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test29Si_SityKF" +func test29() throws -> (Int, Int) { // CHECK-NEXT: [[@LINE]]:36 -> [[@LINE+7]]:2 : 0 + let x = try .random() // CHECK-NEXT: [[@LINE+1]]:7 -> [[@LINE+1]]:24 : 1 + ? (throwingFn(), 0) // CHECK-NEXT: [[@LINE]]:20 -> [[@LINE]]:24 : (1 - 2) + : (0, throwingFn()) // CHECK-NEXT: [[@LINE-1]]:24 -> [[@LINE+1]]:11 : (0 - 2) + return x // CHECK-NEXT: [[@LINE-1]]:7 -> [[@LINE-1]]:24 : (0 - 1) + // CHECK-NEXT: [[@LINE-2]]:23 -> [[@LINE-2]]:24 : ((0 - 1) - 3) + // CHECK-NEXT: [[@LINE-3]]:24 -> [[@LINE-2]]:11 : ((0 - 2) - 3) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test30Si_SityKF" +func test30() throws -> (Int, Int) { // CHECK-NEXT: [[@LINE]]:36 -> [[@LINE+6]]:2 : 0 + let x = try .random() // CHECK-NEXT: [[@LINE+1]]:7 -> [[@LINE+1]]:35 : 1 + ? (throwingFn(), throwingFn()) // CHECK-NEXT: [[@LINE]]:20 -> [[@LINE]]:35 : (1 - 2) + : (0, 0) // CHECK-NEXT: [[@LINE-1]]:34 -> [[@LINE-1]]:35 : ((1 - 2) - 3) + return x // CHECK-NEXT: [[@LINE-2]]:35 -> [[@LINE]]:11 : ((0 - 2) - 3) + // CHECK-NEXT: [[@LINE-2]]:7 -> [[@LINE-2]]:13 : (0 - 1) +} // CHECK-NEXT: } + struct TestInit { // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_errors.TestInit.init() -> coverage_errors.TestInit init() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+5]]:4 : 0 diff --git a/test/Profiler/coverage_errors_exec.swift b/test/Profiler/coverage_errors_exec.swift index 346272af3ad22..ea2f12eaf526d 100644 --- a/test/Profiler/coverage_errors_exec.swift +++ b/test/Profiler/coverage_errors_exec.swift @@ -178,3 +178,31 @@ func test15() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 return 2 // CHECK: {{ *}}[[@LINE]]|{{ *}}1 } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 _ = try? test15() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test16() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + let x = try true // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + ? throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + : throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test16() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +// FIXME: The line execution count is misleading here as it includes the +// trailing edge of the thrown error from the first branch (rdar://118654503). +func test17() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + let x = try false // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + ? throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + : throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test17() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +// FIXME: The line execution count is misleading here as it includes the +// trailing edge of the thrown error from the first branch (rdar://118654503). +func test18() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + let x = try true // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + ? noThrowingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + : noThrowingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test18() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 From c311f6cde243d54ef05ac5960e30f00886929e2d Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Tue, 21 Nov 2023 15:02:56 +0000 Subject: [PATCH 14/35] [Profiler] Correctly handle `try?` expressions Ensure that `try?` expressions appropriately scope the regions generated by child error-throwing expressions, such that the non-error branch does not extend beyond the region of the `try?`. --- lib/SIL/IR/SILProfiler.cpp | 108 +++++++++++--- test/Profiler/coverage_errors.swift | 172 +++++++++++++++++++++++ test/Profiler/coverage_errors_exec.swift | 61 ++++++-- 3 files changed, 310 insertions(+), 31 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index f3632367e8f9c..d1f0edefae926 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -433,6 +433,23 @@ class CounterExpr { /// A region of source code that can be mapped to a counter. class SourceMappingRegion { +public: + enum class Kind { + /// A region that is associated with an ASTNode, and defines a scope under + /// which the region is active. + Node, + + /// A node region that is only present for scoping of child regions, and + /// doesn't need to be included in the resulting set of regions. + ScopingOnly, + + /// A region that refines the counter of a node region. This doesn't have + /// an ASTNode of its own. + Refined, + }; + +private: + Kind RegionKind; ASTNode Node; /// The counter for an incomplete region. Note we do not store counters @@ -445,21 +462,54 @@ class SourceMappingRegion { /// The region's ending location. llvm::Optional EndLoc; -public: - SourceMappingRegion(ASTNode Node, llvm::Optional Counter, - llvm::Optional StartLoc, - llvm::Optional EndLoc) - : Node(Node), Counter(std::move(Counter)), StartLoc(StartLoc), - EndLoc(EndLoc) { + SourceMappingRegion(Kind RegionKind, llvm::Optional Counter, + llvm::Optional StartLoc) + : RegionKind(RegionKind), Counter(Counter), StartLoc(StartLoc) { assert((!StartLoc || StartLoc->isValid()) && "Expected start location to be valid"); - assert((!EndLoc || EndLoc->isValid()) && - "Expected end location to be valid"); + } + + SourceMappingRegion(Kind RegionKind, ASTNode Node, SourceRange Range, + const SourceManager &SM) + : RegionKind(RegionKind), Node(Node) { + assert(Range.isValid()); + StartLoc = Range.Start; + EndLoc = Lexer::getLocForEndOfToken(SM, Range.End); + } + +public: + /// Create a regular source region for an ASTNode. + static SourceMappingRegion forNode(ASTNode Node, const SourceManager &SM, + SourceRange Range = SourceRange()) { + if (Range.isInvalid()) + Range = Node.getSourceRange(); + + // Note we don't store counters for nodes, as we need to be able to fix them + // up later. + return SourceMappingRegion(Kind::Node, Node, Range, SM); + } + + /// Create a source region for an ASTNode that is only present for scoping of + /// child regions, and doesn't need to be included in the resulting set of + /// regions. + static SourceMappingRegion scopingOnly(ASTNode Node, + const SourceManager &SM) { + return SourceMappingRegion(Kind::ScopingOnly, Node, Node.getSourceRange(), + SM); + } + + /// Create a refined region for a given counter. + static SourceMappingRegion refined(CounterExpr Counter, + llvm::Optional StartLoc) { + return SourceMappingRegion(Kind::Refined, Counter, StartLoc); } SourceMappingRegion(SourceMappingRegion &&Region) = default; SourceMappingRegion &operator=(SourceMappingRegion &&RHS) = default; + /// Whether this region is for scoping only. + bool isForScopingOnly() const { return RegionKind == Kind::ScopingOnly; } + ASTNode getNode() const { return Node; } CounterExpr getCounter(const llvm::DenseMap @@ -867,6 +917,13 @@ struct CoverageMapping : public ASTWalker { /// Returns the delta of the count on entering \c Node and exiting, or null if /// there was no change. llvm::Optional setExitCount(ASTNode Node) { + // A `try?` absorbs child error branches, so we can assume the exit count is + // the same as the entry count in that case. + // NOTE: This assumes there is no other kind of control flow that can happen + // in a nested expression, which is true today, but may not always be. + if (Node.isExpr(ExprKind::OptionalTry)) + return llvm::None; + ExitCounter = getCurrentCounter(); if (hasCounter(Node) && getRegion().getNode() != Node) return CounterExpr::Sub(getCounter(Node), *ExitCounter, CounterBuilder); @@ -914,20 +971,14 @@ struct CoverageMapping : public ASTWalker { replaceCount(Count, getEndLoc(Scope)); } - /// Push a region covering \c Node onto the stack. - void pushRegion(ASTNode Node, SourceRange Range = SourceRange()) { - if (Range.isInvalid()) - Range = Node.getSourceRange(); - - // Note we don't store counters for nodes, as we need to be able to fix - // them up later. - RegionStack.emplace_back(Node, /*Counter*/ llvm::None, Range.Start, - Lexer::getLocForEndOfToken(SM, Range.End)); + /// Push a region onto the stack. + void pushRegion(SourceMappingRegion Region) { LLVM_DEBUG({ llvm::dbgs() << "Pushed region: "; - RegionStack.back().print(llvm::dbgs(), SM); + Region.print(llvm::dbgs(), SM); llvm::dbgs() << "\n"; }); + RegionStack.push_back(std::move(Region)); } /// Replace the current region at \p Start with a new counter. If \p Start is @@ -940,7 +991,7 @@ struct CoverageMapping : public ASTWalker { if (Start && Counter.isZero()) Start = llvm::None; - RegionStack.emplace_back(ASTNode(), Counter, Start, llvm::None); + pushRegion(SourceMappingRegion::refined(Counter, Start)); } /// Get the location for the end of the last token in \c Node. @@ -956,6 +1007,10 @@ struct CoverageMapping : public ASTWalker { llvm::dbgs() << "\n"; }); + // Don't bother recording regions that are only present for scoping. + if (Region.isForScopingOnly()) + return; + // Don't record incomplete regions. if (!Region.hasStartLoc()) return; @@ -1128,7 +1183,7 @@ struct CoverageMapping : public ASTWalker { if (auto *BS = dyn_cast(S)) { if (hasCounter(BS)) - pushRegion(BS); + pushRegion(SourceMappingRegion::forNode(BS, SM)); } else if (auto *IS = dyn_cast(S)) { if (auto *Cond = getConditionNode(IS->getCond())) @@ -1222,7 +1277,7 @@ struct CoverageMapping : public ASTWalker { Range = CS->getSourceRange(); break; } - pushRegion(CS, Range); + pushRegion(SourceMappingRegion::forNode(CS, SM, Range)); } return Action::Continue(S); } @@ -1326,8 +1381,15 @@ struct CoverageMapping : public ASTWalker { if (isa(E)) assignKnownCounter(E); - if (hasCounter(E)) - pushRegion(E); + if (hasCounter(E)) { + pushRegion(SourceMappingRegion::forNode(E, SM)); + } else if (isa(E)) { + // If we have a `try?`, that doesn't already have a counter, record it + // as a scoping-only region. We need it to scope child error branches, + // but don't need it in the resulting set of regions. + assignCounter(E, getCurrentCounter()); + pushRegion(SourceMappingRegion::scopingOnly(E, SM)); + } assert(!RegionStack.empty() && "Must be within a region"); diff --git a/test/Profiler/coverage_errors.swift b/test/Profiler/coverage_errors.swift index 1af1518598231..39ae21d0813de 100644 --- a/test/Profiler/coverage_errors.swift +++ b/test/Profiler/coverage_errors.swift @@ -177,6 +177,26 @@ enum SomeErr : Error { // CHECK: [[BB_ERR]] // CHECK: increment_profiler_counter 2 +// func test43() -> Int? { +// let x = try? throwingS.throwingMethod() +// return x +// } +// CHECK-LABEL: sil hidden @$s15coverage_errors6test43SiSgyF : $@convention(thin) () -> Optional +// CHECK: bb0: +// CHECK: increment_profiler_counter 0 +// CHECK: [[GETTER:%[0-9]+]] = function_ref @$s15coverage_errors9throwingSAA1SVvg : $@convention(thin) () -> (S, @error any Error) +// CHECK: try_apply [[GETTER]]() : $@convention(thin) () -> (S, @error any Error), normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERR:bb[0-9]+]] +// +// CHECK: [[BB_ERR]] +// CHECK: increment_profiler_counter 1 +// +// CHECK: [[BB_NORMAL]] +// CHECK: [[METHOD:%[0-9]+]] = function_ref @$s15coverage_errors1SV14throwingMethodSiyKF : $@convention(method) (S) -> (Int, @error any Error) // user: %5 +// CHECK: try_apply [[METHOD]]({{%[0-9]+}}) : $@convention(method) (S) -> (Int, @error any Error), normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERR:bb[0-9]+]] +// +// CHECK: [[BB_ERR]] +// CHECK: increment_profiler_counter 2 + // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors5test1SiyF" func test1() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+7]]:2 : 0 do { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE+3]]:4 : 0 @@ -491,6 +511,129 @@ func test30() throws -> (Int, Int) { // CHECK-NEXT: [[@LINE]]:36 -> [[@LINE+6] // CHECK-NEXT: [[@LINE-2]]:7 -> [[@LINE-2]]:13 : (0 - 1) } // CHECK-NEXT: } +@discardableResult +func takesOptInts(_ x: Int?, _ y: Int?) -> Int { 0 } + +// `throwingFn` is within a `try?`, so the non-error branch is empty. +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test31yyF" +func test31() { // CHECK-NEXT: [[@LINE]]:15 -> [[@LINE+2]]:2 : 0 + takesOptInts(try? throwingFn(), 0) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test32yyF" +func test32() { // CHECK-NEXT: [[@LINE]]:15 -> [[@LINE+5]]:2 : 0 + takesOptInts( + try? throwingFn(), + try? throwingFn() + ) +} // CHECK-NEXT: } + +// Here the throws region extends into the second arg. +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test33SiSgyF" +func test33() -> Int? { // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE+2]]:2 : 0 + try? takesOptInts(throwingFn(), 0) // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE]]:37 : (0 - 1) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test34SiSgyF" +func test34() -> Int? { // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE+3]]:2 : 0 + try? takesOptInts(throwingFn(), throwingFn()) // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE]]:48 : (0 - 1) + // CHECK-NEXT: [[@LINE-1]]:47 -> [[@LINE-1]]:48 : ((0 - 1) - 2) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test35SiSgyF" +func test35() -> Int? { // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE+5]]:2 : 0 + try? takesOptInts( + throwingFn(), // CHECK-NEXT: [[@LINE]]:17 -> [[@LINE+2]]:4 : (0 - 1) + throwingFn() // CHECK-NEXT: [[@LINE]]:17 -> [[@LINE+1]]:4 : ((0 - 1) - 2) + ) +} // CHECK-NEXT: } + +// The 'try's here are redundant. +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test36SiSgyF" +func test36() -> Int? { // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE+5]]:2 : 0 + try? takesOptInts( + try throwingFn(), // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+2]]:4 : (0 - 1) + try throwingFn() // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+1]]:4 : ((0 - 1) - 2) + ) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test37SiSgyF" +func test37() -> Int? { // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE+5]]:2 : 0 + try? takesOptInts( + try throwingFn(), // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+2]]:4 : (0 - 1) + try? S[] + ) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test38SiSgyF" +func test38() -> Int? { // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE+5]]:2 : 0 + try? takesOptInts( + try? throwingFn(), + try S[] // CHECK-NEXT: [[@LINE]]:12 -> [[@LINE+1]]:4 : (0 - 2) + ) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test39Si_SitSgyF" +func test39( +) -> (Int, Int)? { // CHECK-NEXT: [[@LINE]]:18 -> [[@LINE+5]]:2 : 0 + try? (takesOptInts( + throwingFn(), // CHECK-NEXT: [[@LINE]]:17 -> [[@LINE+2]]:8 : (0 - 1) + try? throwingProp + ), 0) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test40SiyKF" +func test40( +) throws -> Int { // CHECK-NEXT: [[@LINE]]:17 -> [[@LINE+5]]:2 : 0 + try takesOptInts( + try? throwingFn(), + throwingProp // CHECK-NEXT: [[@LINE]]:17 -> [[@LINE+2]]:2 : (0 - 2) + ) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test41SiyKF" +func test41( +) throws -> Int { // CHECK-NEXT: [[@LINE]]:17 -> [[@LINE+5]]:2 : 0 + try takesOptInts( + throwingFn(), // CHECK-NEXT: [[@LINE]]:17 -> [[@LINE+3]]:2 : (0 - 1) + try? throwingFn() + ) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test42SiSgyF" +func test42() -> Int? { // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE+5]]:2 : 0 + guard let x = try? throwingFn() else { // CHECK-NEXT: [[@LINE]]:40 -> [[@LINE+2]]:4 : 1 + return nil + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (0 - 1) + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test43SiSgyF" +func test43() -> Int? { // CHECK-NEXT: [[@LINE]]:23 -> [[@LINE+3]]:2 : 0 + let x = try? throwingS.throwingMethod() // CHECK-NEXT: [[@LINE]]:25 -> [[@LINE]]:42 : (0 - 1) + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test44SiSgyKF" +func test44() throws -> Int? { // CHECK-NEXT: [[@LINE]]:30 -> [[@LINE+3]]:2 : 0 + let x = try (try? throwingS)?.throwingMethod() // CHECK-NEXT: [[@LINE]]:49 -> [[@LINE+1]]:11 : (0 - 2) + return x +} + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test45yyF" +func test45() { // CHECK-NEXT: [[@LINE]]:15 -> [[@LINE+2]]:2 : 0 + _ = try? { throw SomeErr.Err1 }() +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test45yyFyyKXEfU_" +// CHECK-NEXT: [[@LINE-4]]:12 -> [[@LINE-4]]:34 : 0 +// CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test46Si_SitSgyF" +func test46() -> (Int, Int)? { // CHECK-NEXT: [[@LINE]]:30 -> [[@LINE+2]]:2 : 0 + try? ({ throw SomeErr.Err1 }(), 0) // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE]]:37 : (0 - 1) +} // CHECK-NEXT: } + struct TestInit { // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_errors.TestInit.init() -> coverage_errors.TestInit init() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+5]]:4 : 0 @@ -500,3 +643,32 @@ struct TestInit { } // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE+1]]:4 : 1 } // CHECK-NEXT: } } + +struct TestProp { + let a = try? throwingFn() + // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors8TestPropV1aSiSgvpfi" + // CHECK-NEXT: [[@LINE-2]]:11 -> [[@LINE-2]]:28 : 0 + // CHECK-NEXT: } + + let b = try? (throwingFn(), 0) + // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors8TestPropV1bSi_SitSgvpfi" + // CHECK-NEXT: [[@LINE-2]]:11 -> [[@LINE-2]]:33 : 0 + // CHECK-NEXT: [[@LINE-3]]:29 -> [[@LINE-3]]:33 : (0 - 1) + // CHECK-NEXT: } + + let c = try? (throwingFn(), .random() ? 0 : 1) + // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors8TestPropV1cSi_SitSgvpfi" + // CHECK-NEXT: [[@LINE-2]]:11 -> [[@LINE-2]]:49 : 0 + // CHECK-NEXT: [[@LINE-3]]:29 -> [[@LINE-3]]:49 : (0 - 1) + // CHECK-NEXT: [[@LINE-4]]:43 -> [[@LINE-4]]:44 : 2 + // CHECK-NEXT: [[@LINE-5]]:47 -> [[@LINE-5]]:48 : ((0 - 1) - 2) + // CHECK-NEXT: } + + let d = (try? (throwingFn(), .random() ? 0 : 1), 0) + // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors8TestPropV1dSi_SitSg_Sitvpfi" + // CHECK-NEXT: [[@LINE-2]]:11 -> [[@LINE-2]]:54 : 0 + // CHECK-NEXT: [[@LINE-3]]:30 -> [[@LINE-3]]:50 : (0 - 1) + // CHECK-NEXT: [[@LINE-4]]:44 -> [[@LINE-4]]:45 : 2 + // CHECK-NEXT: [[@LINE-5]]:48 -> [[@LINE-5]]:49 : ((0 - 1) - 2) + // CHECK-NEXT: } +} diff --git a/test/Profiler/coverage_errors_exec.swift b/test/Profiler/coverage_errors_exec.swift index ea2f12eaf526d..7e5526c04457b 100644 --- a/test/Profiler/coverage_errors_exec.swift +++ b/test/Profiler/coverage_errors_exec.swift @@ -121,14 +121,6 @@ func test11() throws { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 try? test11() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 -func test21() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 - try { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 - throw Err() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 - }() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 - return 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 -} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 -_ = try? test21() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 - // rdar://100470244 - Make sure we don't underflow the counter here. func test12() -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 do { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 @@ -206,3 +198,56 @@ func test18() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 return x // CHECK: {{ *}}[[@LINE]]|{{ *}}1 } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 _ = try? test18() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +@discardableResult +func takesOptInts(_ x: Int?, _ y: Int?) -> Int { 0 } + +func test19() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + takesOptInts( // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try? throwingFn(), // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try? throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + ) // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +test19() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test20( +) throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try takesOptInts( // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + throwingFn(), // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try? throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + ) // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test20() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test21() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + throw Err() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + }() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test21() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test22( +) throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try takesOptInts( // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + noThrowingFn(), // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try? throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + ) // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test22() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test23() -> Int? { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + guard let x = try? throwingFn() else { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return nil // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = test23() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test24() -> Int? { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + guard let x = try? noThrowingFn() else { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return nil // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = test24() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 From b7d02442db56b5c8eea82091357756c9fbebb0ff Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Tue, 21 Nov 2023 15:02:56 +0000 Subject: [PATCH 15/35] [Profiler] Fix throwing expressions in if conditions Previously we would ignore the effect that an if statement or ternary's condition exit counter might have on its branches, as we assumed a condition can't do any control flow. However, in the case where the condition throws an error, we need to account for the error branch. --- lib/SIL/IR/SILProfiler.cpp | 90 +++++++++-- test/Profiler/coverage_errors.swift | 183 +++++++++++++++++++++ test/Profiler/coverage_errors_exec.swift | 192 +++++++++++++++++++++++ 3 files changed, 450 insertions(+), 15 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index d1f0edefae926..3cd1fbba76676 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -1172,6 +1172,20 @@ struct CoverageMapping : public ASTWalker { return Action::Continue(); } + class SetParentRAII final { + ASTWalker &Walker; + decltype(ASTWalker::Parent) PriorParent; + + public: + template + SetParentRAII(ASTWalker &walker, T *newParent) + : Walker(walker), PriorParent(walker.Parent) { + walker.Parent = newParent; + } + + ~SetParentRAII() { Walker.Parent = PriorParent; } + }; + PreWalkResult walkToStmtPre(Stmt *S) override { if (S->isImplicit() && S != ImplicitTopLevelBody) return Action::Continue(S); @@ -1186,21 +1200,42 @@ struct CoverageMapping : public ASTWalker { pushRegion(SourceMappingRegion::forNode(BS, SM)); } else if (auto *IS = dyn_cast(S)) { - if (auto *Cond = getConditionNode(IS->getCond())) - assignCounter(Cond, getCurrentCounter()); - // The counter for the if statement itself tracks the number of jumps to // it by break statements. assignCounter(IS, CounterExpr::Zero()); - // We emit a counter for the then block, and define the else block in - // terms of it. - auto ThenCounter = assignKnownCounter(IS->getThenStmt()); - if (IS->getElseStmt()) { - auto ElseCounter = - CounterExpr::Sub(getCurrentCounter(), ThenCounter, CounterBuilder); - assignCounter(IS->getElseStmt(), ElseCounter); + // FIXME: This is a redundant region. + if (auto *Cond = getConditionNode(IS->getCond())) + assignCounter(Cond, getCurrentCounter()); + + // Visit the children. + // FIXME: This is a hack. + { + SetParentRAII R(*this, S); + for (auto Cond : IS->getCond()) + Cond.walk(*this); + + // The parent counter is taken after the condition in case e.g + // it threw an error. + auto ParentCounter = getCurrentCounter(); + + // We emit a counter for the then block, and define the else block in + // terms of it. + auto ThenCounter = assignKnownCounter(IS->getThenStmt()); + IS->getThenStmt()->walk(*this); + + if (auto *Else = IS->getElseStmt()) { + auto ElseCounter = CounterExpr::Sub(ParentCounter, ThenCounter, + CounterBuilder); + assignCounter(Else, ElseCounter); + Else->walk(*this); + } } + // Already visited the children. + // FIXME: The ASTWalker should do a post-walk for SkipChildren. + walkToStmtPost(S); + return Action::SkipChildren(S); + } else if (auto *GS = dyn_cast(S)) { assignCounter(GS, CounterExpr::Zero()); assignKnownCounter(GS->getBody()); @@ -1235,6 +1270,7 @@ struct CoverageMapping : public ASTWalker { // cases. assignCounter(SS, CounterExpr::Zero()); + // FIXME: This is a redundant region. assignCounter(SS->getSubjectExpr(), getCurrentCounter()); // Assign counters for cases so they're available for fallthrough. @@ -1393,11 +1429,35 @@ struct CoverageMapping : public ASTWalker { assert(!RegionStack.empty() && "Must be within a region"); - if (auto *IE = dyn_cast(E)) { - auto ThenCounter = assignKnownCounter(IE->getThenExpr()); - auto ElseCounter = - CounterExpr::Sub(getCurrentCounter(), ThenCounter, CounterBuilder); - assignCounter(IE->getElseExpr(), ElseCounter); + if (auto *TE = dyn_cast(E)) { + assert(shouldWalkIntoExpr(TE, Parent, Constant).Action.Action == + PreWalkAction::Continue && + "Currently this only returns false for closures"); + + // Visit the children. + // FIXME: This is a hack. + { + SetParentRAII R(*this, TE); + TE->getCondExpr()->walk(*this); + + // The parent counter is taken after the condition in case e.g + // it threw an error. + auto ParentCounter = getCurrentCounter(); + + auto *Then = TE->getThenExpr(); + auto ThenCounter = assignKnownCounter(Then); + Then->walk(*this); + + auto *Else = TE->getElseExpr(); + auto ElseCounter = + CounterExpr::Sub(ParentCounter, ThenCounter, CounterBuilder); + assignCounter(Else, ElseCounter); + Else->walk(*this); + } + // Already visited the children. + // FIXME: The ASTWalker should do a post-walk for SkipChildren. + walkToExprPost(TE); + return Action::SkipChildren(TE); } auto WalkResult = shouldWalkIntoExpr(E, Parent, Constant); if (WalkResult.Action.Action == PreWalkAction::SkipChildren) { diff --git a/test/Profiler/coverage_errors.swift b/test/Profiler/coverage_errors.swift index 39ae21d0813de..d60089583cc8d 100644 --- a/test/Profiler/coverage_errors.swift +++ b/test/Profiler/coverage_errors.swift @@ -11,8 +11,11 @@ struct S { func throwingMethod() throws -> Int { 0 } } +@discardableResult func throwingFn() throws -> Int { 0 } +func throwingBool() throws -> Bool { true } + var throwingProp: Int { get throws { 5 } } @@ -634,6 +637,186 @@ func test46() -> (Int, Int)? { // CHECK-NEXT: [[@LINE]]:30 -> [[@LINE+2]]: try? ({ throw SomeErr.Err1 }(), 0) // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE]]:37 : (0 - 1) } // CHECK-NEXT: } +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test47yyKF" +func test47() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+2]]:2 : 0 + try throwingFn() // CHECK-NEXT: [[@LINE]]:19 -> [[@LINE+1]]:2 : (0 - 1) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test48SiyKF" +func test48() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+5]]:2 : 0 + try throwingBool() // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+4]]:2 : (0 - 2) + ? try throwingFn() // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:23 : 1 + : 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+2]]:2 : ((0 - 2) - 3) + // CHECK-NEXT: [[@LINE-1]]:7 -> [[@LINE-1]]:8 : ((0 - 1) - 2) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test49SiyKF" +func test49() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+6]]:2 : 0 + try throwingBool() // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+5]]:2 : (0 - 2) + ? try throwingFn() // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:23 : 1 + : try throwingFn() // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+3]]:2 : ((0 - 2) - 3) + // CHECK-NEXT: [[@LINE-1]]:7 -> [[@LINE-1]]:23 : ((0 - 1) - 2) + // CHECK-NEXT: [[@LINE-2]]:23 -> [[@LINE+1]]:2 : (((0 - 2) - 3) - 4) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test50SiyKF" +func test50() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+8]]:2 : 0 + let x = if try throwingBool() { // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0 + try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : (0 - 2) + } else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1 + 1 // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 3) + } // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : ((0 - 2) - 3) + return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : ((0 - 1) - 2) + // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE-1]]:11 : ((0 - 2) - 3) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test51SiyKF" +func test51() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+9]]:2 : 0 + let x = if try throwingBool() { // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0 + try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : (0 - 2) + } else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1 + try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 3) + } // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : ((0 - 2) - 3) + return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : ((0 - 1) - 2) + // CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : (((0 - 1) - 2) - 4) + // CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE-2]]:11 : (((0 - 2) - 3) - 4) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test52SiyKF" +func test52() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+10]]:2 : 0 + let x = if try throwingBool(), // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0 + try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+5]]:11 : (0 - 2) + try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : ((0 - 2) - 3) + } else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1 + try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 4) + } // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : (((0 - 2) - 3) - 4) + return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : (((0 - 1) - 2) - 3) + // CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : ((((0 - 1) - 2) - 3) - 5) + // CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE-2]]:11 : ((((0 - 2) - 3) - 4) - 5) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test53yyKF" +func test53() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+10]]:2 : 0 + if try throwingBool(), // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:24 : 0 + try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:24 -> [[@LINE+8]]:2 : (0 - 2) + try throwingFn() // CHECK-NEXT: [[@LINE-1]]:25 -> [[@LINE+7]]:2 : ((0 - 2) - 3) + } else { // CHECK-NEXT: [[@LINE-2]]:26 -> [[@LINE]]:4 : 1 + try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 4) + } // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+4]]:2 : (((0 - 2) - 3) - 4) + // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : (((0 - 1) - 2) - 3) + // CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : ((((0 - 1) - 2) - 3) - 5) + // CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE+1]]:2 : ((((0 - 2) - 3) - 4) - 5) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test54SiSgyF" +func test54()-> Int? { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+7]]:2 : 0 + if let x = try? throwingFn(), + let y = try? throwingFn() { // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE+2]]:4 : 1 + x + y // FIXME: This region is redundant, and not really accurate since we have implicit returns (rdar://118653218) + } else { // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+3]]:2 : 0 + try? throwingFn() // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : (0 - 1) + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : 0 +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test55yyKF" +func test55() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+5]]:2 : 0 + while try throwingBool() { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:27 : (0 + 1) + // CHECK-NEXT: [[@LINE-1]]:27 -> [[@LINE+3]]:2 : (0 - 2) + // CHECK-NEXT: [[@LINE-2]]:28 -> [[@LINE+1]]:4 : 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : (0 - 2) +} // CHECK-NEXT: } + +// FIXME: The second condition ought to get a region too (rdar://118649481) +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test56yyKF" +func test56() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+6]]:2 : 0 + while try throwingBool(), // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:27 : (0 + 1) + try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:27 -> [[@LINE+4]]:2 : (0 - 2) + // CHECK-NEXT: [[@LINE-1]]:27 -> [[@LINE+3]]:2 : ((0 - 2) - 3) + // CHECK-NEXT: [[@LINE-2]]:28 -> [[@LINE+1]]:4 : 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : ((0 - 2) - 3) +} // CHECK-NEXT: } + +// FIXME: We ought to be giving both conditions a region here... +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test57yyF" +func test57() { // CHECK-NEXT: [[@LINE]]:15 -> [[@LINE+4]]:2 : 0 + while let _ = try? throwingFn(), + let _ = try? throwingFn() { // CHECK-NEXT: [[@LINE]]:35 -> [[@LINE+1]]:4 : 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : 0 +} // CHECK-NEXT: } + +// We generate the same regions for `try!` as `try`. We could handle it +// specially, but the error branches are effectively unreachable, so it +// doesn't make a difference. +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test58SiyF" +func test58() -> Int { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+3]]:2 : 0 + let x = try! throwingFn() // CHECK-NEXT: [[@LINE]]:28 -> [[@LINE+1]]:11 : (0 - 1) + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test59SiyKF" +func test59() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+5]]:2 : 0 + guard try throwingBool() else { // CHECK-NEXT: [[@LINE]]:27 -> [[@LINE+3]]:11 : (0 - 2) + return 1 // CHECK-NEXT: [[@LINE-1]]:33 -> [[@LINE+1]]:4 : 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : ((0 - 1) - 2) + return 0 +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test60SiyKF" +func test60() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+7]]:2 : 0 + switch try throwingBool() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:28 : 0 + case true: // CHECK-NEXT: [[@LINE-1]]:28 -> [[@LINE+5]]:2 : (0 - 1) + return 0 // CHECK-NEXT: [[@LINE-1]]:3 -> [[@LINE]]:13 : 2 + case false: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:13 : 3 + return 1 + } +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test61SiyKF" +func test61() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+7]]:2 : 0 + switch try throwingBool() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:28 : 0 + case true: // CHECK-NEXT: [[@LINE-1]]:28 -> [[@LINE+5]]:2 : (0 - 1) + 0 // CHECK-NEXT: [[@LINE-1]]:3 -> [[@LINE]]:6 : 2 + case false: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:6 : 3 + 1 // FIXME: This next region shouldn't be needed, we should know it's unrechabale (rdar://118653218). + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : (2 + 3) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test62SiyKF" +func test62() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+8]]:2 : 0 + let x = switch try throwingBool() { // CHECK-NEXT: [[@LINE]]:18 -> [[@LINE]]:36 : 0 + case true: // CHECK-NEXT: [[@LINE-1]]:36 -> [[@LINE+5]]:11 : (0 - 1) + 0 // CHECK-NEXT: [[@LINE-1]]:3 -> [[@LINE]]:6 : 2 + case false: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:6 : 3 + 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (2 + 3) + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test63yyKF" +func test63() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+4]]:2 : 0 + for _ in [try throwingFn()] { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+3]]:2 : (0 - 2) + // CHECK-NEXT: [[@LINE-1]]:31 -> [[@LINE+1]]:4 : 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : (0 - 2) +} // CHECK-NEXT: } + +// FIXME: We don't currently assign a separate region for the where clause, but +// we ought to (rdar://118653191). +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test64yyKF" +func test64() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+5]]:2 : 0 + for _ in [0] + where try throwingBool() { // CHECK-NEXT: [[@LINE]]:27 -> [[@LINE+3]]:2 : (0 - 2) + // CHECK-NEXT: [[@LINE-1]]:28 -> [[@LINE+1]]:4 : 1 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : (0 - 2) +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test65yyKF" +func test65() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+5]]:2 : 0 + repeat { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : 1 + // CHECK-NEXT: [[@LINE+1]]:4 -> [[@LINE+3]]:2 : 0 + } while try throwingBool() // CHECK-NEXT: [[@LINE]]:11 -> [[@LINE]]:29 : 1 + // CHECK-NEXT: [[@LINE-1]]:29 -> [[@LINE+1]]:2 : (0 - 2) +} // CHECK-NEXT: } + struct TestInit { // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_errors.TestInit.init() -> coverage_errors.TestInit init() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+5]]:4 : 0 diff --git a/test/Profiler/coverage_errors_exec.swift b/test/Profiler/coverage_errors_exec.swift index 7e5526c04457b..0af491b7ae39c 100644 --- a/test/Profiler/coverage_errors_exec.swift +++ b/test/Profiler/coverage_errors_exec.swift @@ -27,6 +27,9 @@ func noThrowingFn() throws -> Int { 0 } @discardableResult func throwingFn() throws -> Int { throw Err() } +func throwingBool() throws -> Bool { throw Err() } +func noThrowingBool() throws -> Bool { true } + var throwingProp: Int { get throws { throw Err() } } @@ -251,3 +254,192 @@ func test24() -> Int? { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 return x // CHECK: {{ *}}[[@LINE]]|{{ *}}1 } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 _ = test24() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test25() -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + let x = try! noThrowingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = test25() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test26() throws -> Int { + let x = if try throwingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } else { // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test26() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test27() throws -> Int { + let x = if try noThrowingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + } else { // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test27() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test28() throws -> Int { + let x = if try !noThrowingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } else { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test28() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test29() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingBool() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + ? try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + : try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test29() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test30() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try noThrowingBool() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + ? try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + : try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test30() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +// FIXME: The line execution count is misleading here (rdar://118654503). +func test31() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try !noThrowingBool() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + ? try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + : try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test31() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test32() throws { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + if try throwingBool(), // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } else { // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test32() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test33() throws { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + if try noThrowingBool(), // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } else { // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test33() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test34() throws { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + if try noThrowingBool(), // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try noThrowingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + } else { // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test34() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test35() throws { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + if try !noThrowingBool(), // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try noThrowingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } else { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + try throwingFn() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test35() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test36() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + guard try throwingBool() else { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + return 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test36() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test37() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + guard try noThrowingBool() else { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test37() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test38() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + guard try !noThrowingBool() else { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test38() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test39() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + switch try throwingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + case true: // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + return 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + case false: // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + return 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +_ = try? test39() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +// FIXME: The line coverage for the second case isn't great (rdar://118654503). +func test40() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + switch try noThrowingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + case true: // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + case false: // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test40() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +// FIXME: The line coverage for the first case isn't great (rdar://118654503). +func test41() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + switch try !noThrowingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + case true: // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + case false: // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test41() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +func test42() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + let x = switch try throwingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + case true: // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + case false: // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}0 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test42() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +// FIXME: The line coverage for the second case isn't great (rdar://118654503). +func test43() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + let x = switch try noThrowingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + case true: // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + case false: // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test43() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + +// FIXME: The line coverage for the first case isn't great (rdar://118654503). +func test44() throws -> Int { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + let x = switch try !noThrowingBool() { // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + case true: // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + 0 // CHECK: {{ *}}[[@LINE]]|{{ *}}0 + case false: // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + 1 // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + } // CHECK: {{ *}}[[@LINE]]|{{ *}}1 + return x // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +} // CHECK: {{ *}}[[@LINE]]|{{ *}}1 +_ = try? test44() // CHECK: {{ *}}[[@LINE]]|{{ *}}1 From 66dd9b2971b09747cec37e7ce7b053796c27a9c1 Mon Sep 17 00:00:00 2001 From: Nuri Amari Date: Fri, 17 Nov 2023 14:36:00 -0800 Subject: [PATCH 16/35] [swift-ide-test] Add support for -enable-upcoming-feature --- tools/swift-ide-test/swift-ide-test.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 8c2b7886cb157..b8f55911fac77 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -870,6 +870,11 @@ static llvm::cl::list llvm::cl::desc("Enable an experimental feature"), llvm::cl::cat(Category)); +static llvm::cl::list + EnableUpcomingFeatures("enable-upcoming-feature", + llvm::cl::desc("Enable a feature that will be introduced in an upcoming language version"), + llvm::cl::cat(Category)); + static llvm::cl::list AccessNotesPath("access-notes-path", llvm::cl::desc("Path to access notes file"), llvm::cl::cat(Category)); @@ -4435,6 +4440,12 @@ int main(int argc, char *argv[]) { } } + for (const auto &featureArg : options::EnableUpcomingFeatures) { + if (auto feature = getUpcomingFeature(featureArg)) { + InitInvok.getLangOptions().Features.insert(*feature); + } + } + if (!options::Triple.empty()) InitInvok.setTargetTriple(options::Triple); if (!options::SwiftVersion.empty()) { From 504c3243095c38fd4d1d23e9f39d2fa3e417ab70 Mon Sep 17 00:00:00 2001 From: Nuri Amari Date: Fri, 17 Nov 2023 14:38:35 -0800 Subject: [PATCH 17/35] [swift-ide-test] Tie ClangImporter fwd-decl option to chosen lang feature Prviously swift-ide-test enabled importing of ObjC forward declarations with the -enable-objc-forward-declarations option. The compiler enables the same behavior via -enable-upcoming-feature. Now that swift-ide-test also supports upcoming-features, make enabling the ImportObjcForwardDeclarations language feature have the expected effect in swift-ide-test. The old flag is also removed. --- ...incomplete_objc_types_swift_ide_test.swift | 35 +++++++++++++++++++ .../objc_forward_declarations.swift | 2 +- test/IDE/print_clang_ObjectiveC.swift | 2 +- tools/swift-ide-test/swift-ide-test.cpp | 13 ++++--- 4 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 test/ClangImporter/incomplete_objc_types_swift_ide_test.swift diff --git a/test/ClangImporter/incomplete_objc_types_swift_ide_test.swift b/test/ClangImporter/incomplete_objc_types_swift_ide_test.swift new file mode 100644 index 0000000000000..6a7c2c3ff0d77 --- /dev/null +++ b/test/ClangImporter/incomplete_objc_types_swift_ide_test.swift @@ -0,0 +1,35 @@ +// This test checks that swift-ide-test output under either -swift-version 6 or +// -enable-upcoming-feature ImportObjCForwardDeclarations the output matches the +// import capabilities of the compiler. + +// (1) Print the interface with -enable-upcoming-feature ImportObjCForwardDeclarations +// RUN: %target-swift-ide-test -print-module -module-to-print IncompleteTypeLibrary1 -I %S/Inputs/custom-modules/IncompleteTypes \ +// RUN: -enable-objc-interop -enable-upcoming-feature ImportObjcForwardDeclarations -source-filename x | %FileCheck %s + +// (2) Print the interface with -swift-version 6 +// RUN: %target-swift-ide-test -print-module -module-to-print IncompleteTypeLibrary1 -I %S/Inputs/custom-modules/IncompleteTypes \ +// RUN: -enable-objc-interop -swift-version 6 -source-filename x | %FileCheck %s + +// REQUIRES: objc_interop +// REQUIRES: asserts + +// CHECK: import Foundation +// CHECK: @available(*, unavailable, message: "This Objective-C class has only been forward-declared; import its owning module to use it") +// CHECK: class ForwardDeclaredInterface { +// CHECK: } +// CHECK: @available(*, unavailable, message: "This Objective-C protocol has only been forward-declared; import its owning module to use it") +// CHECK: protocol ForwardDeclaredProtocol { +// CHECK: } +// CHECK: class IncompleteTypeConsumer1 : NSObject { +// CHECK: var propertyUsingAForwardDeclaredProtocol1: (any ForwardDeclaredProtocol)! +// CHECK: var propertyUsingAForwardDeclaredInterface1: ForwardDeclaredInterface! +// CHECK: init!() +// CHECK: func methodReturningForwardDeclaredProtocol1() -> (any ForwardDeclaredProtocol & NSObjectProtocol)! +// CHECK: func methodReturningForwardDeclaredInterface1() -> ForwardDeclaredInterface! +// CHECK: func methodTakingAForwardDeclaredProtocol1(_ param: (any ForwardDeclaredProtocol)!) +// CHECK: func methodTakingAForwardDeclaredInterface1(_ param: ForwardDeclaredInterface!) +// CHECK: } +// CHECK: func CFunctionReturningAForwardDeclaredInterface1() -> ForwardDeclaredInterface! +// CHECK: func CFunctionTakingAForwardDeclaredInterface1(_ param: ForwardDeclaredInterface!) +// CHECK: func CFunctionReturningAForwardDeclaredProtocol1() -> (any ForwardDeclaredProtocol & NSObjectProtocol)! +// CHECK: func CFunctionTakingAForwardDeclaredProtocol1(_ param: (any ForwardDeclaredProtocol)!) diff --git a/test/ClangImporter/objc_forward_declarations.swift b/test/ClangImporter/objc_forward_declarations.swift index 045cfb46c34d0..3144b1bfad7ed 100644 --- a/test/ClangImporter/objc_forward_declarations.swift +++ b/test/ClangImporter/objc_forward_declarations.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -emit-module -o %t -I %S/Inputs/custom-modules -enable-objc-interop %s -// RUN: %target-swift-ide-test -print-module -module-to-print objc_forward_declarations -I %t -I %S/Inputs/custom-modules -enable-objc-interop -enable-objc-forward-declarations -source-filename x | %FileCheck %s +// RUN: %target-swift-ide-test -print-module -module-to-print objc_forward_declarations -I %t -I %S/Inputs/custom-modules -enable-objc-interop -enable-upcoming-feature ImportObjcForwardDeclarations -source-filename x | %FileCheck %s // CHECK: class Innocuous : Confusing { diff --git a/test/IDE/print_clang_ObjectiveC.swift b/test/IDE/print_clang_ObjectiveC.swift index aa7a2eb15a9a7..ac36997675305 100644 --- a/test/IDE/print_clang_ObjectiveC.swift +++ b/test/IDE/print_clang_ObjectiveC.swift @@ -4,7 +4,7 @@ // RUN: %FileCheck -input-file %t/ObjectiveC.NSObject.printed.txt %s // RUN: %FileCheck -input-file %t/ObjectiveC.NSObject.printed.txt -check-prefix=NEGATIVE -check-prefix=NEGATIVE-WITHOUT-FORWARD-DECLS %s -// RUN: %target-swift-ide-test -print-module -source-filename %s -module-to-print=ObjectiveC.NSObject -function-definitions=false -enable-objc-forward-declarations > %t/ObjectiveC.NSObject.forward-decls.txt +// RUN: %target-swift-ide-test -print-module -source-filename %s -module-to-print=ObjectiveC.NSObject -function-definitions=false -enable-upcoming-feature ImportObjcForwardDeclarations > %t/ObjectiveC.NSObject.forward-decls.txt // RUN: %FileCheck -input-file %t/ObjectiveC.NSObject.forward-decls.txt -check-prefix=CHECK -check-prefix=CHECK-WITH-FORWARD-DECLS %s // RUN: %FileCheck -input-file %t/ObjectiveC.NSObject.forward-decls.txt -check-prefix=NEGATIVE %s diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index b8f55911fac77..52f270de245d1 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -413,12 +413,6 @@ static llvm::cl::opt CodeCompleteCallPatternHeuristics( "Use heuristics to guess whether we want call pattern completions"), llvm::cl::cat(Category)); -static llvm::cl::opt -ObjCForwardDeclarations("enable-objc-forward-declarations", - llvm::cl::desc("Import Objective-C forward declarations when possible"), - llvm::cl::cat(Category), - llvm::cl::init(false)); - static llvm::cl::opt EnableSwift3ObjCInference("enable-swift3-objc-inference", llvm::cl::desc("Enable Swift 3's @objc inference rules"), @@ -4500,8 +4494,13 @@ int main(int argc, char *argv[]) { options::EnableDeserializationSafety; InitInvok.getLangOptions().EnableSwift3ObjCInference = options::EnableSwift3ObjCInference; + // The manner in which swift-ide-test constructs its CompilerInvocation does + // not hit the codepath in arg parsing that would normally construct + // ClangImporter options based on enabled language features etc. Explicitly + // enable them here. InitInvok.getClangImporterOptions().ImportForwardDeclarations |= - options::ObjCForwardDeclarations; + InitInvok.getLangOptions().hasFeature( + Feature::ImportObjcForwardDeclarations); if (!options::ResourceDir.empty()) { InitInvok.setRuntimeResourcePath(options::ResourceDir); } From c2caa84373f9fcce177d4df4e9617ce16fea1c6b Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Thu, 16 Nov 2023 23:56:08 -0500 Subject: [PATCH 18/35] [Concurrency] Diagnose default values whose isolation differs from the corresponding stored property. --- include/swift/AST/DiagnosticsSema.def | 2 +- lib/AST/Decl.cpp | 8 +++ lib/Sema/TypeCheckConcurrency.cpp | 70 +++++++++++++------ lib/Sema/TypeCheckConcurrency.h | 8 ++- lib/Sema/TypeCheckDeclPrimary.cpp | 10 +-- .../isolated_default_arguments.swift | 11 ++- .../isolated_default_property_inits.swift | 12 ++-- 7 files changed, 80 insertions(+), 41 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index e45f317063cc4..3878bdc6d8fa9 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5353,7 +5353,7 @@ ERROR(distributed_actor_isolated_non_self_reference,none, "non-isolated context", (const ValueDecl *)) ERROR(isolated_default_argument_context,none, - "%0 default argument in a %1 context", + "%0 default value in a %1 context", (ActorIsolation, ActorIsolation)) ERROR(conflicting_default_argument_isolation,none, "default argument cannot be both %0 and %1", diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 65b9c729b34d9..89e22c5683492 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -10637,6 +10637,7 @@ ActorIsolation swift::getActorIsolationOfContext( DeclContext *dc, llvm::function_ref getClosureActorIsolation) { + auto &ctx = dc->getASTContext(); auto dcToUse = dc; // Defer bodies share actor isolation of their enclosing context. if (auto FD = dyn_cast(dcToUse)) { @@ -10657,6 +10658,13 @@ ActorIsolation swift::getActorIsolationOfContext( // actor isolation as the field itself. That default expression may only // be used from inits that meet the required isolation. if (auto *var = dcToUse->getNonLocalVarDecl()) { + // If IsolatedDefaultValues are enabled, treat this context as having + // unspecified isolation. We'll compute the required isolation for + // the initializer and validate that it matches the isolation of the + // var itself in the DefaultInitializerIsolation request. + if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues)) + return ActorIsolation::forUnspecified(); + return getActorIsolation(var); } diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index abd8f848fe238..14762ba5d2154 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -3143,7 +3143,10 @@ namespace { if (!unsatisfiedIsolation) return false; - if (refineRequiredIsolation(*unsatisfiedIsolation)) + bool onlyArgsCrossIsolation = callOptions.contains( + ActorReferenceResult::Flags::OnlyArgsCrossIsolation); + if (!onlyArgsCrossIsolation && + refineRequiredIsolation(*unsatisfiedIsolation)) return false; // At this point, we know a jump is made to the callee that yields @@ -4757,6 +4760,7 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator, Initializer *dc = nullptr; Expr *initExpr = nullptr; + ActorIsolation enclosingIsolation; if (auto *pbd = var->getParentPatternBinding()) { if (!var->isParentInitialized()) @@ -4765,6 +4769,7 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator, auto i = pbd->getPatternEntryIndexForVarDecl(var); dc = cast(pbd->getInitContext(i)); initExpr = var->getParentInitializer(); + enclosingIsolation = getActorIsolation(var); } else if (auto *param = dyn_cast(var)) { // If this parameter corresponds to a stored property for a // memberwise initializer, the default argument is the default @@ -4782,13 +4787,27 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator, dc = param->getDefaultArgumentInitContext(); initExpr = param->getTypeCheckedDefaultExpr(); + enclosingIsolation = + getActorIsolationOfContext(param->getDeclContext()); } if (!dc || !initExpr) return ActorIsolation::forUnspecified(); + // If the default argument has isolation, it must match the + // isolation of the decl context. ActorIsolationChecker checker(dc); - return checker.computeRequiredIsolation(initExpr); + auto requiredIsolation = checker.computeRequiredIsolation(initExpr); + if (requiredIsolation.isActorIsolated()) { + if (enclosingIsolation != requiredIsolation) { + var->diagnose( + diag::isolated_default_argument_context, + requiredIsolation, enclosingIsolation); + return ActorIsolation::forUnspecified(); + } + } + + return requiredIsolation; } void swift::checkOverrideActorIsolation(ValueDecl *value) { @@ -5859,8 +5878,8 @@ bool swift::isAccessibleAcrossActors( } ActorReferenceResult ActorReferenceResult::forSameConcurrencyDomain( - ActorIsolation isolation) { - return ActorReferenceResult{SameConcurrencyDomain, llvm::None, isolation}; + ActorIsolation isolation, Options options) { + return ActorReferenceResult{SameConcurrencyDomain, options, isolation}; } ActorReferenceResult ActorReferenceResult::forEntersActor( @@ -5869,8 +5888,8 @@ ActorReferenceResult ActorReferenceResult::forEntersActor( } ActorReferenceResult ActorReferenceResult::forExitsActorToNonisolated( - ActorIsolation isolation) { - return ActorReferenceResult{ExitsActorToNonisolated, llvm::None, isolation}; + ActorIsolation isolation, Options options) { + return ActorReferenceResult{ExitsActorToNonisolated, options, isolation}; } // Determine if two actor isolation contexts are considered to be equivalent. @@ -5906,10 +5925,24 @@ ActorReferenceResult ActorReferenceResult::forReference( declIsolation = declIsolation.subst(declRef.getSubstitutions()); } + // Determine what adjustments we need to perform for cross-actor + // references. + Options options = llvm::None; + + // FIXME: Actor constructors are modeled as isolated to the actor + // so that Sendable checking is applied to their arguments, but the + // call itself does not hop to another executor. + if (auto ctor = dyn_cast(declRef.getDecl())) { + if (auto nominal = ctor->getDeclContext()->getSelfNominalTypeDecl()) { + if (nominal->isAnyActor()) + options |= Flags::OnlyArgsCrossIsolation; + } + } + // If the entity we are referencing is not a value, we're in the same // concurrency domain. if (isNonValueReference(declRef.getDecl())) - return forSameConcurrencyDomain(declIsolation); + return forSameConcurrencyDomain(declIsolation, options); // Compute the isolation of the context, if not provided. ActorIsolation contextIsolation = ActorIsolation::forUnspecified(); @@ -5928,11 +5961,11 @@ ActorReferenceResult ActorReferenceResult::forReference( if (isAsyncDecl(declRef) && contextIsolation.isActorIsolated() && !declRef.getDecl()->getAttrs() .hasAttribute()) - return forExitsActorToNonisolated(contextIsolation); + return forExitsActorToNonisolated(contextIsolation, options); // Otherwise, we stay in the same concurrency domain, whether on an actor // or in a task. - return forSameConcurrencyDomain(declIsolation); + return forSameConcurrencyDomain(declIsolation, options); } // The declaration we are accessing is actor-isolated. First, check whether @@ -5941,11 +5974,11 @@ ActorReferenceResult ActorReferenceResult::forReference( declIsolation.getActorInstanceParameter() == 0) { // If this instance is isolated, we're in the same concurrency domain. if (actorInstance->isIsolated()) - return forSameConcurrencyDomain(declIsolation); + return forSameConcurrencyDomain(declIsolation, options); } else if (equivalentIsolationContexts(declIsolation, contextIsolation)) { // The context isolation matches, so we are in the same concurrency // domain. - return forSameConcurrencyDomain(declIsolation); + return forSameConcurrencyDomain(declIsolation, options); } // Initializing an actor isolated stored property with a value effectively @@ -5965,7 +5998,8 @@ ActorReferenceResult ActorReferenceResult::forReference( // Treat the decl isolation as 'preconcurrency' to downgrade violations // to warnings, because violating Sendable here is accepted by the // Swift 5.9 compiler. - return forEntersActor(declIsolation, Flags::Preconcurrency); + options |= Flags::Preconcurrency; + return forEntersActor(declIsolation, options); } } } @@ -5975,7 +6009,7 @@ ActorReferenceResult ActorReferenceResult::forReference( if (actorInstance && checkedByFlowIsolation( fromDC, *actorInstance, declRef.getDecl(), declRefLoc, useKind)) - return forSameConcurrencyDomain(declIsolation); + return forSameConcurrencyDomain(declIsolation, options); // If we are delegating to another initializer, treat them as being in the // same concurrency domain. @@ -5984,7 +6018,7 @@ ActorReferenceResult ActorReferenceResult::forReference( if (actorInstance && actorInstance->isSelf() && isa(declRef.getDecl()) && isa(fromDC)) - return forSameConcurrencyDomain(declIsolation); + return forSameConcurrencyDomain(declIsolation, options); // If there is an instance that corresponds to 'self', // we are in a constructor or destructor, and we have a stored property of @@ -5994,18 +6028,14 @@ ActorReferenceResult ActorReferenceResult::forReference( isNonInheritedStorage(declRef.getDecl(), fromDC) && declIsolation.isGlobalActor() && (isa(fromDC) || isa(fromDC))) - return forSameConcurrencyDomain(declIsolation); - - // Determine what adjustments we need to perform for cross-actor - // references. - Options options = llvm::None; + return forSameConcurrencyDomain(declIsolation, options); // At this point, we are accessing the target from outside the actor. // First, check whether it is something that can be accessed directly, // without any kind of promotion. if (isAccessibleAcrossActors( declRef.getDecl(), declIsolation, fromDC, options, actorInstance)) - return forEntersActor(declIsolation, llvm::None); + return forEntersActor(declIsolation, options); // This is a cross-actor reference. diff --git a/lib/Sema/TypeCheckConcurrency.h b/lib/Sema/TypeCheckConcurrency.h index 0bc1fbaa2ba44..0dfb7fbad5234 100644 --- a/lib/Sema/TypeCheckConcurrency.h +++ b/lib/Sema/TypeCheckConcurrency.h @@ -202,6 +202,10 @@ struct ActorReferenceResult { /// The declaration is being accessed from a @preconcurrency context. Preconcurrency = 1 << 3, + + /// Only arguments cross an isolation boundary, e.g. because they + /// escape into an actor in a nonisolated actor initializer. + OnlyArgsCrossIsolation = 1 << 4, }; using Options = OptionSet; @@ -212,13 +216,13 @@ struct ActorReferenceResult { private: static ActorReferenceResult forSameConcurrencyDomain( - ActorIsolation isolation); + ActorIsolation isolation, Options options = llvm::None); static ActorReferenceResult forEntersActor( ActorIsolation isolation, Options options); static ActorReferenceResult forExitsActorToNonisolated( - ActorIsolation isolation); + ActorIsolation isolation, Options options = llvm::None); public: /// Determine what happens when referencing the given declaration from the diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index df9cfc49aeac2..72860119cb777 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1055,15 +1055,7 @@ static void checkDefaultArguments(ParameterList *params) { // If the default argument has isolation, it must match the // isolation of the decl context. - auto defaultArgIsolation = param->getInitializerIsolation(); - if (defaultArgIsolation.isActorIsolated()) { - auto *dc = param->getDeclContext(); - auto enclosingIsolation = getActorIsolationOfContext(dc); - if (enclosingIsolation != defaultArgIsolation) { - param->diagnose(diag::isolated_default_argument_context, - defaultArgIsolation, enclosingIsolation); - } - } + (void)param->getInitializerIsolation(); if (!ifacety->hasPlaceholder()) { continue; diff --git a/test/Concurrency/isolated_default_arguments.swift b/test/Concurrency/isolated_default_arguments.swift index 59c6f81e96fc4..0e93722829cab 100644 --- a/test/Concurrency/isolated_default_arguments.swift +++ b/test/Concurrency/isolated_default_arguments.swift @@ -20,11 +20,11 @@ func requiresMainActor() -> Int { 0 } @SomeGlobalActor func requiresSomeGlobalActor() -> Int { 0 } -// expected-error@+1 {{main actor-isolated default argument in a nonisolated context}} +// expected-error@+1 {{main actor-isolated default value in a nonisolated context}} func mainActorDefaultArgInvalid(value: Int = requiresMainActor()) {} func mainActorClosureInvalid( - closure: () -> Int = { // expected-error {{main actor-isolated default argument in a nonisolated context}} + closure: () -> Int = { // expected-error {{main actor-isolated default value in a nonisolated context}} requiresMainActor() } ) {} @@ -41,7 +41,7 @@ func mainActorDefaultArg(value: Int = requiresMainActor()) {} ) {} func mainActorClosureCall( - closure: Int = { // expected-error {{main actor-isolated default argument in a nonisolated context}} + closure: Int = { // expected-error {{main actor-isolated default value in a nonisolated context}} requiresMainActor() }() ) {} @@ -155,6 +155,11 @@ struct S3 { var (x, y, z) = (requiresMainActor(), requiresSomeGlobalActor(), 10) } +struct S4 { + // expected-error@+1 {{main actor-isolated default value in a nonisolated context}} + var x: Int = requiresMainActor() +} + @MainActor func initializeFromMainActor() { _ = S1(required: 10) diff --git a/test/Concurrency/isolated_default_property_inits.swift b/test/Concurrency/isolated_default_property_inits.swift index 0c5fa39107df4..7d7487cbedd95 100644 --- a/test/Concurrency/isolated_default_property_inits.swift +++ b/test/Concurrency/isolated_default_property_inits.swift @@ -19,11 +19,11 @@ func requiresMainActor() -> Int { 0 } @SomeGlobalActor func requiresSomeGlobalActor() -> Int { 0 } -struct S1 { +class C1 { // expected-note@+1 2 {{'self.x' not initialized}} - var x = requiresMainActor() + @MainActor var x = requiresMainActor() // expected-note@+1 2 {{'self.y' not initialized}} - var y = requiresSomeGlobalActor() + @SomeGlobalActor var y = requiresSomeGlobalActor() var z = 10 // expected-error@+1 {{return from initializer without initializing all stored properties}} @@ -36,9 +36,9 @@ struct S1 { @SomeGlobalActor init(c: Int) {} } -struct S2 { - var x = requiresMainActor() - var y = requiresSomeGlobalActor() +class C2 { + @MainActor var x = requiresMainActor() + @SomeGlobalActor var y = requiresSomeGlobalActor() var z = 10 nonisolated init(x: Int, y: Int) { From fb36bb5980a5b322a2ddd5cfb6bb6df0f8c0deac Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 17 Nov 2023 16:19:14 -0500 Subject: [PATCH 19/35] [Concurrency] When isolated default values are enabled, synthesized initializers should be nonisolated if all initialized properties are Sendable with nonisolated default values. --- include/swift/AST/DiagnosticsSema.def | 6 ++ lib/Sema/CodeSynthesis.cpp | 59 +++++++++++++++++-- lib/Sema/TypeCheckConcurrency.cpp | 5 +- .../isolated_default_arguments.swift | 34 +++++++++++ 4 files changed, 99 insertions(+), 5 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 3878bdc6d8fa9..c78b991ae329b 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5352,6 +5352,12 @@ ERROR(distributed_actor_isolated_non_self_reference,none, "distributed actor-isolated %kind0 can not be accessed from a " "non-isolated context", (const ValueDecl *)) +ERROR(conflicting_stored_property_isolation,none, + "%select{default|memberwise}0 initializer for %1 cannot be both %2 and %3", + (bool, Type, ActorIsolation, ActorIsolation)) +NOTE(property_requires_actor,none, + "initializer for %0 %1 is %2", + (DescriptiveDeclKind, Identifier, ActorIsolation)) ERROR(isolated_default_argument_context,none, "%0 default value in a %1 context", (ActorIsolation, ActorIsolation)) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index a3970376700e5..63d8112ff066e 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -337,13 +337,64 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl, ctor->setSynthesized(); ctor->setAccess(accessLevel); + if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues)) { + // If any of the type's actor-isolated properties: + // 1. Have non-Sendable type, or + // 2. Have an isolated initial value + // then the initializer must also be actor-isolated. If all + // isolated properties have Sendable type and a nonisolated + // default value, then the initializer can be nonisolated. + // + // These rules only apply for global actor isolation, because actor + // initializers apply Sendable checking to arguments at the call-site, + // and actor initializers do not run on the actor, so initial values + // cannot be actor-instance-isolated. + bool shouldAddNonisolated = true; + llvm::Optional existingIsolation = llvm::None; + VarDecl *previousVar = nullptr; + + // The memberwise init properties are also effectively what the + // default init uses, e.g. default initializers initialize via + // properties wrapped and init accessors. + for (auto var : decl->getMemberwiseInitProperties()) { + auto type = var->getTypeInContext(); + auto isolation = getActorIsolation(var); + if (isolation.isGlobalActor()) { + if (!isSendableType(decl->getModuleContext(), type) || + var->getInitializerIsolation().isGlobalActor()) { + // If different isolated stored properties require different + // global actors, it is impossible to initialize this type. + if (existingIsolation && + *existingIsolation != isolation) { + ctx.Diags.diagnose(decl->getLoc(), + diag::conflicting_stored_property_isolation, + ICK == ImplicitConstructorKind::Memberwise, + decl->getDeclaredType(), *existingIsolation, isolation); + previousVar->diagnose( + diag::property_requires_actor, + previousVar->getDescriptiveKind(), + previousVar->getName(), *existingIsolation); + var->diagnose( + diag::property_requires_actor, + var->getDescriptiveKind(), + var->getName(), isolation); + } + + existingIsolation = isolation; + previousVar = var; + shouldAddNonisolated = false; + } + } + } + + if (shouldAddNonisolated) { + addNonIsolatedToSynthesized(decl, ctor); + } + } + if (ICK == ImplicitConstructorKind::Memberwise) { ctor->setIsMemberwiseInitializer(); - // FIXME: If 'IsolatedDefaultValues' is enabled, the memberwise init - // should be 'nonisolated' if none of the memberwise-initialized properties - // are global actor isolated and have non-Sendable type, and none of the - // initial values require global actor isolation. if (!ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues)) { addNonIsolatedToSynthesized(decl, ctor); } diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 14762ba5d2154..fd05feb4c1fd4 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -4767,8 +4767,11 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator, return ActorIsolation::forUnspecified(); auto i = pbd->getPatternEntryIndexForVarDecl(var); + if (!pbd->isInitializerChecked(i)) + TypeChecker::typeCheckPatternBinding(pbd, i); + dc = cast(pbd->getInitContext(i)); - initExpr = var->getParentInitializer(); + initExpr = pbd->getInit(i); enclosingIsolation = getActorIsolation(var); } else if (auto *param = dyn_cast(var)) { // If this parameter corresponds to a stored property for a diff --git a/test/Concurrency/isolated_default_arguments.swift b/test/Concurrency/isolated_default_arguments.swift index 0e93722829cab..3cc69daa8b261 100644 --- a/test/Concurrency/isolated_default_arguments.swift +++ b/test/Concurrency/isolated_default_arguments.swift @@ -195,3 +195,37 @@ extension A { _ = S2(required: 10) } } + +// expected-error@+1 {{default initializer for 'C1' cannot be both main actor-isolated and global actor 'SomeGlobalActor'-isolated}} +class C1 { + // expected-note@+1 {{initializer for property 'x' is main actor-isolated}} + @MainActor var x = requiresMainActor() + // expected-note@+1 {{initializer for property 'y' is global actor 'SomeGlobalActor'-isolated}} + @SomeGlobalActor var y = requiresSomeGlobalActor() +} + +class NonSendable {} + +// expected-error@+1 {{default initializer for 'C2' cannot be both main actor-isolated and global actor 'SomeGlobalActor'-isolated}} +class C2 { + // expected-note@+1 {{initializer for property 'x' is main actor-isolated}} + @MainActor var x = NonSendable() + // expected-note@+1 {{initializer for property 'y' is global actor 'SomeGlobalActor'-isolated}} + @SomeGlobalActor var y = NonSendable() +} + +class C3 { + @MainActor var x = 1 + @SomeGlobalActor var y = 2 +} + +@MainActor struct NonIsolatedInit { + var x = 0 + var y = 0 +} + +func callDefaultInit() async { + _ = C2() + _ = NonIsolatedInit() + _ = NonIsolatedInit(x: 10) +} From 7217641c3f3e24a90ebf6b8fe04e881196b353d5 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 16 Nov 2023 09:01:57 -0800 Subject: [PATCH 20/35] [SIL] Addr-only enums have non-none ownership. Values produced by address-only `enum` instructions have non-none ownership. And because `enum` is representation-changing, they have `owned` ownership. This corresponds at the opaque values SIL stage to the fact that at the address-lowered SIL stage the storage location has non-trivial initialization which must be `destroy_addr`d, regardless of whether an empty case was stored to it. --- lib/SIL/IR/ValueOwnership.cpp | 20 +++++++++++- lib/SILGen/SILGenBuilder.cpp | 2 +- lib/SILGen/SILGenExpr.cpp | 4 +-- .../opaque_values_silgen_resilient.swift | 14 ++++++++ ...aque_values_silgen_imports_resilient.swift | 32 +++++++++++++++++++ 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 test/SILGen/Inputs/opaque_values_silgen_resilient.swift create mode 100644 test/SILGen/opaque_values_silgen_imports_resilient.swift diff --git a/lib/SIL/IR/ValueOwnership.cpp b/lib/SIL/IR/ValueOwnership.cpp index 88b993cb666ed..e775a6556d510 100644 --- a/lib/SIL/IR/ValueOwnership.cpp +++ b/lib/SIL/IR/ValueOwnership.cpp @@ -275,7 +275,6 @@ FORWARDING_OWNERSHIP_INST(UnconditionalCheckedCast) FORWARDING_OWNERSHIP_INST(Upcast) FORWARDING_OWNERSHIP_INST(UncheckedValueCast) FORWARDING_OWNERSHIP_INST(UncheckedEnumData) -FORWARDING_OWNERSHIP_INST(Enum) FORWARDING_OWNERSHIP_INST(MarkDependence) // NOTE: init_existential_ref from a reference counting perspective is not // considered to be "owned" since it doesn't affect reference counts. That being @@ -296,6 +295,25 @@ FORWARDING_OWNERSHIP_INST(CopyableToMoveOnlyWrapperValue) FORWARDING_OWNERSHIP_INST(MoveOnlyWrapperToCopyableBox) #undef FORWARDING_OWNERSHIP_INST +ValueOwnershipKind +ValueOwnershipKindClassifier::visitEnumInst(EnumInst *I) { + if (!I->getModule().useLoweredAddresses() && I->getType().isAddressOnly(*I->getFunction())) { + // During address lowering, an address-only enum instruction will eventually + // be lowered to inject_enum_addr/init_enum_data_addr, initializing a + // non-trivial storage location. So prior to AddressLowering (in opaque + // values mode) such an enum instruction produces a non-trivial value, + // without regard to whether it is in a trivial case. Otherwise, non-trivial + // storage would fail to be destroy_addr'd. + assert(!I->getType().isTrivial(*I->getFunction())); + // An enum instruction is representation changing, so its address-only + // operand must be owned. + return OwnershipKind::Owned; + } + return I->getType().isTrivial(*I->getFunction()) + ? ValueOwnershipKind(OwnershipKind::None) + : I->getForwardingOwnershipKind(); +} + ValueOwnershipKind ValueOwnershipKindClassifier::visitUncheckedOwnershipConversionInst( UncheckedOwnershipConversionInst *I) { diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp index 905b8f86eff2f..3a6a1a43b222a 100644 --- a/lib/SILGen/SILGenBuilder.cpp +++ b/lib/SILGen/SILGenBuilder.cpp @@ -681,7 +681,7 @@ ManagedValue SILGenBuilder::createManagedOptionalNone(SILLocation loc, if (!type.isAddressOnly(getFunction()) || !SGF.silConv.useLoweredAddresses()) { SILValue noneValue = createOptionalNone(loc, type); - return ManagedValue::forObjectRValueWithoutOwnership(noneValue); + return SGF.emitManagedRValueWithCleanup(noneValue); } SILValue tempResult = SGF.emitTemporaryAllocation(loc, type); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 168f63574689d..30eec0ec04c4a 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -1028,8 +1028,8 @@ RValue RValueEmitter::visitNilLiteralExpr(NilLiteralExpr *E, SGFContext C) { ManagedValue noneValue; if (enumTy.isLoadable(SGF.F) || !SGF.silConv.useLoweredAddresses()) { - noneValue = ManagedValue::forObjectRValueWithoutOwnership( - SGF.B.createEnum(E, SILValue(), noneDecl, enumTy)); + auto *e = SGF.B.createEnum(E, SILValue(), noneDecl, enumTy); + noneValue = SGF.emitManagedRValueWithCleanup(e); } else { noneValue = SGF.B.bufferForExpr(E, enumTy, SGF.getTypeLowering(enumTy), C, diff --git a/test/SILGen/Inputs/opaque_values_silgen_resilient.swift b/test/SILGen/Inputs/opaque_values_silgen_resilient.swift new file mode 100644 index 0000000000000..428d596931e08 --- /dev/null +++ b/test/SILGen/Inputs/opaque_values_silgen_resilient.swift @@ -0,0 +1,14 @@ +public class ClassEquatable : Equatable { + public static func ==(lhs: ClassEquatable, rhs: ClassEquatable) -> Bool { lhs === rhs } +} + +public enum EnumNontrivialWithEmptyCases : Equatable { + case empty + case other + case loaded(ClassEquatable) +} + +public enum EnumTrivial : Equatable { + case empty + case other +} diff --git a/test/SILGen/opaque_values_silgen_imports_resilient.swift b/test/SILGen/opaque_values_silgen_imports_resilient.swift new file mode 100644 index 0000000000000..579258d2eb440 --- /dev/null +++ b/test/SILGen/opaque_values_silgen_imports_resilient.swift @@ -0,0 +1,32 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -disable-availability-checking -o %t -enable-library-evolution -module-name ResilientLibrary %S/Inputs/opaque_values_silgen_resilient.swift +// RUN: %target-swift-frontend -enable-sil-opaque-values -emit-silgen -disable-availability-checking -I %t %s | %FileCheck %s + +import ResilientLibrary + +// Verify that an enum instruction producing a trivial is _still_ destroyed if +// (1) the enum instruction's type is non-trivial +// (2) the enum is address-only +// Necessary because such an enum will be lowered to +// init_enum_data_addr/inject_enum_addr and there isn't generally enough +// information to determine whether a destroy_addr is required so it is always +// required. +// CHECK-LABEL: sil [ossa] @produceSomeEmptyNontrivialAddronlyEnumInstance : {{.*}} { +// CHECK: [[EMPTY_CASE:%[^,]+]] = enum $EnumNontrivialWithEmptyCases, #EnumNontrivialWithEmptyCases.empty!enumelt +// CHECK: [[SOME_EMPTY_CASE:%[^,]+]] = enum $Optional, #Optional.some!enumelt, [[EMPTY_CASE]] +// CHECK: destroy_value [[SOME_EMPTY_CASE]] +// CHECK-LABEL: } // end sil function 'produceSomeEmptyNontrivialAddronlyEnumInstance' +@_silgen_name("produceSomeEmptyNontrivialAddronlyEnumInstance") +public func produceSomeEmptyNontrivialAddronlyEnumInstance(_ one: EnumNontrivialWithEmptyCases?) { + if one != .empty { + } +} + +// CHECK-LABEL: sil [ossa] @produceNoneEmptyAddronlyEnumInstance : {{.*}} { +// CHECK: [[NONE:%[^,]+]] = enum $Optional, #Optional.none!enumelt +// CHECK: return [[NONE]] : $Optional +// CHECK-LABEL: } // end sil function 'produceNoneEmptyAddronlyEnumInstance' +@_silgen_name("produceNoneEmptyAddronlyEnumInstance") +public func produceNoneEmptyAddronlyEnumInstance() -> EnumNontrivialWithEmptyCases? { + return .none +} From 7ff6780580a1ae5d0c92ce2d926c5d1b7e0509b3 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 16 Nov 2023 15:46:51 -0800 Subject: [PATCH 21/35] [ConstraintSystem] Key path literals with completion tokens should be marked as invalid Capability couldn't be determined for expressions like that which means that inference should be delayed until root becomes available. Resolves: https://github.com/apple/swift/issues/69936 --- lib/Sema/CSBindings.cpp | 3 ++- lib/Sema/ConstraintSystem.cpp | 3 +-- test/IDE/complete_issue-69936.swift | 13 +++++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 test/IDE/complete_issue-69936.swift diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index f223e8951a872..3dd8e53b1f8bf 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -641,6 +641,7 @@ void BindingSet::finalize( updatedBindings.insert( {keyPathTy, AllowedBindingKind::Exact, keyPathLoc}); } else if (CS.shouldAttemptFixes()) { + auto fixedRootTy = CS.getFixedType(rootTy); // If key path is structurally correct and has a resolved root // type, let's promote the fallback type into a binding because // root would have been inferred from explicit type already and @@ -648,7 +649,7 @@ void BindingSet::finalize( // type to key path literal to propagate root/value to the context. if (!keyPath->hasSingleInvalidComponent() && (keyPath->getParsedRoot() || - !CS.getFixedType(rootTy)->isTypeVariableOrMember())) { + (fixedRootTy && !fixedRootTy->isTypeVariableOrMember()))) { auto fallback = llvm::find_if(Defaults, [](const auto &entry) { return entry.second->getKind() == ConstraintKind::FallbackType; }); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 6c79f35ddfec1..a892988af8747 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -7470,8 +7470,7 @@ ConstraintSystem::inferKeyPathLiteralCapability(KeyPathExpr *keyPath) { break; case KeyPathExpr::Component::Kind::CodeCompletion: { - capability = KeyPathCapability::ReadOnly; - break; + return fail(); } case KeyPathExpr::Component::Kind::Property: case KeyPathExpr::Component::Kind::Subscript: diff --git a/test/IDE/complete_issue-69936.swift b/test/IDE/complete_issue-69936.swift new file mode 100644 index 0000000000000..5e3fef7af81e5 --- /dev/null +++ b/test/IDE/complete_issue-69936.swift @@ -0,0 +1,13 @@ +// RUN: %batch-code-completion + +struct Test { + var currentHeight: Int + + func subscribeToKeyboardEvents() { + objectAndKeyPath(object: self, keyPath: \.#^COMPLETE^#) + } +} + +func objectAndKeyPath(object: Root, keyPath: WritableKeyPath) {} + +// COMPLETE: Decl[InstanceVar]/CurrNominal: currentHeight[#Int#]; name=currentHeight From 7267cba8e3321422af718413a7ec5b78619abb58 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 14 Nov 2023 17:19:10 -0800 Subject: [PATCH 22/35] [AST] Teach `InheritedProtocolsRequest` about synthesized protocol attributes ClangImporter converts NS_SWIFT_SENDABLE into `SynthesizedProtocolAttr` which needs to be recognized by the request that collects all of the protocols that the given protocol inherits. --- lib/AST/NameLookup.cpp | 18 ++++++--- .../sendable_objc_protocol_attr.swift | 40 +++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 test/Concurrency/sendable_objc_protocol_attr.swift diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 9f561346b75d8..6e82e3bff32ac 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -3186,18 +3186,24 @@ SuperclassDeclRequest::evaluate(Evaluator &evaluator, ArrayRef InheritedProtocolsRequest::evaluate(Evaluator &evaluator, ProtocolDecl *PD) const { - llvm::SmallVector result; - SmallPtrSet known; - known.insert(PD); + llvm::SmallSetVector inherited; + auto addInherited = [&inherited, &PD](ProtocolDecl *P) { + if (PD != P) + inherited.insert(P); + }; + + for (auto attr : PD->getAttrs().getAttributes()) { + addInherited(attr->getProtocol()); + } + bool anyObject = false; for (const auto &found : getDirectlyInheritedNominalTypeDecls(PD, anyObject)) { if (auto proto = dyn_cast(found.Item)) { - if (known.insert(proto).second) - result.push_back(proto); + addInherited(proto); } } - return PD->getASTContext().AllocateCopy(result); + return PD->getASTContext().AllocateCopy(inherited.getArrayRef()); } ArrayRef diff --git a/test/Concurrency/sendable_objc_protocol_attr.swift b/test/Concurrency/sendable_objc_protocol_attr.swift new file mode 100644 index 0000000000000..f79e3e0402b51 --- /dev/null +++ b/test/Concurrency/sendable_objc_protocol_attr.swift @@ -0,0 +1,40 @@ +// RUN: %empty-directory(%t/src) +// RUN: %empty-directory(%t/sdk) +// RUN: split-file %s %t/src + +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %t/src/main.swift \ +// RUN: -import-objc-header %t/src/Test.h \ +// RUN: -strict-concurrency=complete \ +// RUN: -module-name main -I %t -verify + +// REQUIRES: objc_interop +// REQUIRES: concurrency + +//--- Test.h +#define NS_SWIFT_SENDABLE __attribute__((__swift_attr__("@Sendable"))) + +#pragma clang assume_nonnull begin + +@import Foundation; + +NS_SWIFT_SENDABLE +@protocol MyObjCProtocol +@property (readonly, nonatomic) NSString *test; +@end + +#pragma clang assume_nonnull end + +//--- main.swift +struct MyStruct: Sendable { + let value: any MyObjCProtocol // Ok +} + +extension Sendable { + func compute() {} +} + +extension MyObjCProtocol { + func test() { + compute() // Ok + } +} From 1422e8a3ab73b6dcd6dca5d1c81df523707e9fc2 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 14 Nov 2023 17:32:47 -0800 Subject: [PATCH 23/35] [RequirementMachine] Inherited requirements collection should account for synthesized protocols ClangImporter adds `SynthesizedProtocolAttr` to model inheritance from `Sendable` on protocols imported from Objective-C. --- lib/AST/RequirementMachine/RequirementLowering.cpp | 13 ++++++++++++- test/IDE/print_objc_concurrency_interface.swift | 3 +++ .../usr/include/ObjCConcurrency.h | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/AST/RequirementMachine/RequirementLowering.cpp b/lib/AST/RequirementMachine/RequirementLowering.cpp index 7859dc9ec38e7..dcad9e3f9acae 100644 --- a/lib/AST/RequirementMachine/RequirementLowering.cpp +++ b/lib/AST/RequirementMachine/RequirementLowering.cpp @@ -858,7 +858,7 @@ void swift::rewriting::expandDefaultRequirements(ASTContext &ctx, } /// Collect structural requirements written in the inheritance clause of an -/// AssociatedTypeDecl or GenericTypeParamDecl. +/// AssociatedTypeDecl, GenericTypeParamDecl, or ProtocolDecl. void swift::rewriting::realizeInheritedRequirements( TypeDecl *decl, Type type, bool shouldInferRequirements, SmallVectorImpl &result, @@ -891,6 +891,17 @@ void swift::rewriting::realizeInheritedRequirements( realizeTypeRequirement(dc, type, inheritedType, loc, result, errors); } + + // Also check for `SynthesizedProtocolAttr`s with additional constraints added + // by ClangImporter. This is how imported protocols are marked `Sendable` + // without changing their inheritance lists. + auto attrs = decl->getAttrs().getAttributes(); + for (auto attr : attrs) { + auto inheritedType = attr->getProtocol()->getDeclaredType(); + auto loc = attr->getLocation(); + + realizeTypeRequirement(dc, type, inheritedType, loc, result, errors); + } } /// StructuralRequirementsRequest realizes all the user-written requirements diff --git a/test/IDE/print_objc_concurrency_interface.swift b/test/IDE/print_objc_concurrency_interface.swift index fe60e16137afe..ee15af0452804 100644 --- a/test/IDE/print_objc_concurrency_interface.swift +++ b/test/IDE/print_objc_concurrency_interface.swift @@ -43,6 +43,9 @@ import _Concurrency // CHECK: @available(*, unavailable) // CHECK-NEXT: extension AuditedBoth : @unchecked Sendable { +// CHECK-LABEL: public protocol SendableProtocol +// CHECK-SAME: : Sendable + // CHECK-LABEL: enum SendableEnum : // CHECK-SAME: @unchecked Sendable diff --git a/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h b/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h index 759f356f0706e..5eb83031ba70c 100644 --- a/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h +++ b/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h @@ -225,6 +225,9 @@ SENDABLE @interface AuditedSendable : NSObject @end @interface AuditedNonSendable : NSObject @end NONSENDABLE SENDABLE @interface AuditedBoth : NSObject @end +SENDABLE @protocol SendableProtocol @end +@protocol SendableProtocolRefined @end + typedef NS_ENUM(unsigned, SendableEnum) { SendableEnumFoo, SendableEnumBar }; From e87a36545c56cbb613ec202bfa73b0ee6126aa40 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 15 Nov 2023 09:52:26 -0800 Subject: [PATCH 24/35] [NameLookup] Lift synthesized protocol check into `getDirectlyInheritedNominalTypeDecls` Some places use `getDirectlyInheritedNominalTypeDecls` directly instead of fetching it through a request, so lift the check there instead (direct use of `getDirectlyInheritedNominalTypeDecls` could be refactored separately). --- lib/AST/NameLookup.cpp | 28 +++++++++-------- .../sendable_objc_protocol_attr.swift | 30 +++++++++++++++++++ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 6e82e3bff32ac..7885ae80442da 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -3187,20 +3187,12 @@ ArrayRef InheritedProtocolsRequest::evaluate(Evaluator &evaluator, ProtocolDecl *PD) const { llvm::SmallSetVector inherited; - auto addInherited = [&inherited, &PD](ProtocolDecl *P) { - if (PD != P) - inherited.insert(P); - }; - - for (auto attr : PD->getAttrs().getAttributes()) { - addInherited(attr->getProtocol()); - } - bool anyObject = false; - for (const auto &found : getDirectlyInheritedNominalTypeDecls(PD, anyObject)) { - if (auto proto = dyn_cast(found.Item)) { - addInherited(proto); - } + for (const auto &found : + getDirectlyInheritedNominalTypeDecls(PD, anyObject)) { + auto proto = dyn_cast(found.Item); + if (proto && proto != PD) + inherited.insert(proto); } return PD->getASTContext().AllocateCopy(inherited.getArrayRef()); @@ -3718,6 +3710,16 @@ swift::getDirectlyInheritedNominalTypeDecls( return result; } + // Check for SynthesizedProtocolAttrs on the protocol. ClangImporter uses + // these to add `Sendable` conformances to protocols without modifying the + // inherited type list. + for (auto attr : + protoDecl->getAttrs().getAttributes()) { + auto loc = attr->getLocation(); + result.push_back( + {attr->getProtocol(), loc, attr->isUnchecked() ? loc : SourceLoc()}); + } + // Else we have access to this information on the where clause. auto selfBounds = getSelfBoundsFromWhereClause(decl); anyObject |= selfBounds.anyObject; diff --git a/test/Concurrency/sendable_objc_protocol_attr.swift b/test/Concurrency/sendable_objc_protocol_attr.swift index f79e3e0402b51..fc20ebebfecb4 100644 --- a/test/Concurrency/sendable_objc_protocol_attr.swift +++ b/test/Concurrency/sendable_objc_protocol_attr.swift @@ -22,6 +22,9 @@ NS_SWIFT_SENDABLE @property (readonly, nonatomic) NSString *test; @end +@protocol MyRefinedObjCProtocol +@end + #pragma clang assume_nonnull end //--- main.swift @@ -38,3 +41,30 @@ extension MyObjCProtocol { compute() // Ok } } + +class K : NSObject, MyObjCProtocol { + // expected-warning@-1 {{non-final class 'K' cannot conform to 'Sendable'; use '@unchecked Sendable'}} + let test: String = "k" +} + +class UncheckedK : NSObject, MyObjCProtocol, @unchecked Sendable { // ok + let test: String = "unchecked" +} + +class KRefined : NSObject, MyRefinedObjCProtocol { + // expected-warning@-1 {{non-final class 'KRefined' cannot conform to 'Sendable'; use '@unchecked Sendable'}} + let test: String = "refined" +} + +class KUncheckedRefined : NSObject, MyRefinedObjCProtocol, @unchecked Sendable { // Ok + let test: String = "refined unchecked" +} + +do { + func testSendable(_: T) {} + + testSendable(K()) // Ok + testSendable(UncheckedK()) // Ok + testSendable(KRefined()) // Ok + testSendable(KUncheckedRefined()) // Ok +} From f3cd1cfccc8a75fa6b773759ebcc6f8d696dc535 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 16 Nov 2023 13:40:41 -0800 Subject: [PATCH 25/35] [Concurrency] Downgrade error about inherited Sendable classes inheriting from non-NSObject to warning --- lib/Sema/TypeCheckConcurrency.cpp | 13 ++++--- .../sendable_objc_protocol_attr.swift | 36 +++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index fd05feb4c1fd4..41fcb22b7b8bb 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -5132,11 +5132,14 @@ bool swift::checkSendableConformance( // we allow `NSObject` for Objective-C interoperability. if (auto superclassDecl = classDecl->getSuperclassDecl()) { if (!superclassDecl->isNSObject()) { - classDecl->diagnose( - diag::concurrent_value_inherit, - nominal->getASTContext().LangOpts.EnableObjCInterop, - classDecl->getName()); - return true; + classDecl + ->diagnose(diag::concurrent_value_inherit, + nominal->getASTContext().LangOpts.EnableObjCInterop, + classDecl->getName()) + .limitBehavior(behavior); + + if (behavior == DiagnosticBehavior::Unspecified) + return true; } } } diff --git a/test/Concurrency/sendable_objc_protocol_attr.swift b/test/Concurrency/sendable_objc_protocol_attr.swift index fc20ebebfecb4..90999f745ce3e 100644 --- a/test/Concurrency/sendable_objc_protocol_attr.swift +++ b/test/Concurrency/sendable_objc_protocol_attr.swift @@ -60,6 +60,42 @@ class KUncheckedRefined : NSObject, MyRefinedObjCProtocol, @unchecked Sendable { let test: String = "refined unchecked" } +@preconcurrency +protocol P : Sendable { +} + +protocol Q : Sendable { +} + +do { + class A : NSObject {} + + final class B : A, P { + // expected-warning@-1 {{'Sendable' class 'B' cannot inherit from another class other than 'NSObject'}} + } + + final class UncheckedB : A, P, @unchecked Sendable { // Ok + } + + class C : A, MyObjCProtocol { + // expected-warning@-1 {{non-final class 'C' cannot conform to 'Sendable'; use '@unchecked Sendable'}} + // expected-warning@-2 {{'Sendable' class 'C' cannot inherit from another class other than 'NSObject'}} + let test: String = "c" + } + + class UncheckedC : A, MyObjCProtocol, @unchecked Sendable { // Ok + let test: String = "c" + } + + // A warning until `-swift-version 6` + final class D : A, Q { + // expected-warning@-1 {{'Sendable' class 'D' cannot inherit from another class other than 'NSObject'}} + } + + final class UncheckedD : A, Q, @unchecked Sendable { // Ok + } +} + do { func testSendable(_: T) {} From 0c1ba5d07ba51063e419c99a8d7477bd0c0a96e8 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Fri, 17 Nov 2023 21:30:12 -0800 Subject: [PATCH 26/35] [embedded] Start building embedded support on Linux/ELF, expand archs of the embedded stdlib to cover common embedded targets --- cmake/modules/SwiftSetIfArchBitness.cmake | 2 ++ stdlib/public/CMakeLists.txt | 32 ++++++++++++++++--- stdlib/public/Concurrency/CMakeLists.txt | 11 +++++-- test/embedded/array-builtins-exec.swift | 3 +- test/embedded/array-to-pointer.swift | 3 +- test/embedded/array-zero-size-struct.swift | 3 +- test/embedded/arrays.swift | 3 +- test/embedded/class-func.swift | 3 +- test/embedded/classes-arrays.swift | 3 +- test/embedded/classes-stack-promotion.swift | 3 +- test/embedded/classes.swift | 3 +- test/embedded/closures-heap.swift | 3 +- test/embedded/collection.swift | 3 +- test/embedded/concurrency-actors.swift | 3 +- test/embedded/concurrency-async-let.swift | 3 +- test/embedded/concurrency-builtins.swift | 3 +- test/embedded/concurrency-simple.swift | 3 +- test/embedded/custom-print.swift | 3 +- test/embedded/debuginfo.swift | 3 +- test/embedded/deserialize-vtables.swift | 3 +- test/embedded/dynamic-self.swift | 3 +- test/embedded/fno-builtin.swift | 3 +- test/embedded/generic-classes-debuginfo.swift | 3 +- test/embedded/generic-classes.swift | 3 +- test/embedded/lto.swift | 3 +- test/embedded/metatypes.swift | 3 +- test/embedded/modules-classes.swift | 3 +- test/embedded/modules-globals-exec.swift | 3 +- test/embedded/modules-globals-many.swift | 3 +- test/embedded/modules-globals.swift | 3 +- test/embedded/modules-print-exec.swift | 3 +- test/embedded/no-autolink.swift | 3 +- test/embedded/once-dependent.swift | 3 +- test/embedded/once-multithreaded.swift | 3 +- test/embedded/once.swift | 3 +- test/embedded/osize-genericspecializer.swift | 3 +- test/embedded/osize-releasedevirt.swift | 3 +- test/embedded/ouroboros-bug.swift | 1 - test/embedded/ptrauth-fieldptr1.swift | 3 +- test/embedded/ptrauth-fieldptr2.swift | 3 +- test/embedded/runtime-release.swift | 3 +- test/embedded/runtime.swift | 3 +- test/embedded/shared-linkage.swift | 3 +- test/embedded/static-object.swift | 3 +- .../static-string-interpolation.swift | 3 +- test/embedded/stdlib-basic.swift | 1 - test/embedded/stdlib-types.swift | 1 - test/embedded/throw-trap-stdlib.swift | 3 +- test/embedded/throw-trap.swift | 3 +- test/embedded/throw-typed.swift | 3 +- test/embedded/typeof.swift | 3 +- 51 files changed, 83 insertions(+), 100 deletions(-) diff --git a/cmake/modules/SwiftSetIfArchBitness.cmake b/cmake/modules/SwiftSetIfArchBitness.cmake index 0f9027e9f28ed..0aceb632f39e3 100644 --- a/cmake/modules/SwiftSetIfArchBitness.cmake +++ b/cmake/modules/SwiftSetIfArchBitness.cmake @@ -11,12 +11,14 @@ function(set_if_arch_bitness var_name) "${SIA_ARCH}" STREQUAL "x86" OR "${SIA_ARCH}" STREQUAL "armv5" OR "${SIA_ARCH}" STREQUAL "armv6" OR + "${SIA_ARCH}" STREQUAL "armv6m" OR "${SIA_ARCH}" STREQUAL "armv7" OR "${SIA_ARCH}" STREQUAL "armv7k" OR "${SIA_ARCH}" STREQUAL "arm64_32" OR "${SIA_ARCH}" STREQUAL "armv7m" OR "${SIA_ARCH}" STREQUAL "armv7em" OR "${SIA_ARCH}" STREQUAL "armv7s" OR + "${SIA_ARCH}" STREQUAL "riscv32" OR "${SIA_ARCH}" STREQUAL "wasm32" OR "${SIA_ARCH}" STREQUAL "powerpc") set("${var_name}" "${SIA_CASE_32_BIT}" PARENT_SCOPE) diff --git a/stdlib/public/CMakeLists.txt b/stdlib/public/CMakeLists.txt index 86115cbf8ea75..0efa50f99f32e 100644 --- a/stdlib/public/CMakeLists.txt +++ b/stdlib/public/CMakeLists.txt @@ -138,7 +138,7 @@ option(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB "Enable build of the embedded Swift standard library and runtime" TRUE) -if(NOT SWIFT_HOST_VARIANT STREQUAL "macosx") +if((NOT SWIFT_HOST_VARIANT STREQUAL "macosx") AND (NOT SWIFT_HOST_VARIANT STREQUAL "linux")) set(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB FALSE) elseif(NOT SWIFT_INCLUDE_TOOLS) # Temporarily, only build embedded stdlib when building the compiler, to @@ -151,12 +151,36 @@ endif() if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB) set(EMBEDDED_STDLIB_TARGET_TRIPLES # arch module_name target triple + "armv6 armv6-apple-none-macho armv6-apple-none-macho" + "armv6m armv6m-apple-none-macho armv6m-apple-none-macho" "armv7 armv7-apple-none-macho armv7-apple-none-macho" + "armv7em armv7em-apple-none-macho armv7em-apple-none-macho" "arm64 arm64-apple-none-macho arm64-apple-none-macho" - "x86_64 x86_64-apple-macos x86_64-apple-macos10.13" - "arm64 arm64-apple-macos arm64-apple-macos10.13" - "arm64e arm64e-apple-macos arm64e-apple-macos10.13" + + # the following are all ELF targets + "armv6 armv6-none-none-eabi armv6-none-none-eabi" + "armv6m armv6m-none-none-eabi armv6-none-none-eabi" + "armv7 armv7-none-none-eabi armv7-none-none-eabi" + "armv7em armv7em-none-none-eabi armv7em-none-none-eabi" + "aarch64 aarch64-none-none-elf aarch64-none-none-elf" + "riscv32 riscv32-none-none-eabi riscv32-none-none-eabi" + "riscv64 riscv64-none-none-eabi riscv64-none-none-eabi" ) + + if (SWIFT_HOST_VARIANT STREQUAL "linux") + set(EMBEDDED_STDLIB_TARGET_TRIPLES ${EMBEDDED_STDLIB_TARGET_TRIPLES} + "${SWIFT_HOST_VARIANT_ARCH} ${SWIFT_HOST_VARIANT_ARCH}-unknown-linux-gnu ${SWIFT_HOST_VARIANT_ARCH}-unknown-linux-gnu" + # In practice this expands to either: + # "x86_64 x86_64-unknown-linux-gnu x86_64-unknown-linux-gnu" + # "aarch64 aarch64-unknown-linux-gnu aarch64-unknown-linux-gnu" + ) + elseif (SWIFT_HOST_VARIANT STREQUAL "macosx") + set(EMBEDDED_STDLIB_TARGET_TRIPLES ${EMBEDDED_STDLIB_TARGET_TRIPLES} + "x86_64 x86_64-apple-macos x86_64-apple-macos10.13" + "arm64 arm64-apple-macos arm64-apple-macos10.13" + "arm64e arm64e-apple-macos arm64e-apple-macos10.13" + ) + endif() endif() if(SWIFT_BUILD_STDLIB) diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index d705d0e16de37..770cd863e9a5e 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -198,9 +198,14 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC list(GET list 1 mod) list(GET list 2 triple) - # TODO: Only build embedded Swift Concurrency for macOS, for now. - if(NOT "${mod}" MATCHES "-macos$") - continue() + if (SWIFT_HOST_VARIANT STREQUAL "linux") + if(NOT "${mod}" MATCHES "-linux-gnu$") + continue() + endif() + elseif (SWIFT_HOST_VARIANT STREQUAL "macosx") + if(NOT "${mod}" MATCHES "-macos$") + continue() + endif() endif() set(SWIFT_SDK_embedded_ARCH_${mod}_MODULE "${mod}") diff --git a/test/embedded/array-builtins-exec.swift b/test/embedded/array-builtins-exec.swift index 0c8b22ccf3c78..f901d682da95d 100644 --- a/test/embedded/array-builtins-exec.swift +++ b/test/embedded/array-builtins-exec.swift @@ -6,8 +6,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu import Builtin diff --git a/test/embedded/array-to-pointer.swift b/test/embedded/array-to-pointer.swift index 03cdb314cefff..fdcc7dcdb80b6 100644 --- a/test/embedded/array-to-pointer.swift +++ b/test/embedded/array-to-pointer.swift @@ -7,8 +7,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu @_silgen_name("putchar") func putchar(_: UInt8) diff --git a/test/embedded/array-zero-size-struct.swift b/test/embedded/array-zero-size-struct.swift index fbec4d08c4431..74a2f1daf938b 100644 --- a/test/embedded/array-zero-size-struct.swift +++ b/test/embedded/array-zero-size-struct.swift @@ -2,8 +2,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public struct MyStruct { } diff --git a/test/embedded/arrays.swift b/test/embedded/arrays.swift index 3ba3339566959..62afa33b33809 100644 --- a/test/embedded/arrays.swift +++ b/test/embedded/arrays.swift @@ -7,8 +7,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu @_silgen_name("putchar") func putchar(_: UInt8) diff --git a/test/embedded/class-func.swift b/test/embedded/class-func.swift index 2baeeaaf2d278..7526435f85c19 100644 --- a/test/embedded/class-func.swift +++ b/test/embedded/class-func.swift @@ -3,8 +3,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu @main struct Main { diff --git a/test/embedded/classes-arrays.swift b/test/embedded/classes-arrays.swift index ee48d09424937..c7a8a6bad00b0 100644 --- a/test/embedded/classes-arrays.swift +++ b/test/embedded/classes-arrays.swift @@ -6,8 +6,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu class MyClass { init() { print("MyClass.init") } diff --git a/test/embedded/classes-stack-promotion.swift b/test/embedded/classes-stack-promotion.swift index 6fed60c86bd6d..21273c71fbcf3 100644 --- a/test/embedded/classes-stack-promotion.swift +++ b/test/embedded/classes-stack-promotion.swift @@ -7,8 +7,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public class MyClass { public init() { print("MyClass.init") } diff --git a/test/embedded/classes.swift b/test/embedded/classes.swift index 0e92b07e4d0a6..d066a3000c9aa 100644 --- a/test/embedded/classes.swift +++ b/test/embedded/classes.swift @@ -6,8 +6,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu class MyClass { init() { print("MyClass.init") } diff --git a/test/embedded/closures-heap.swift b/test/embedded/closures-heap.swift index d596c0e4ef9e4..49e379b5b7fa7 100644 --- a/test/embedded/closures-heap.swift +++ b/test/embedded/closures-heap.swift @@ -6,8 +6,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public class MyClass { var handler: (()->())? = nil diff --git a/test/embedded/collection.swift b/test/embedded/collection.swift index b89c29af73da0..2dc4075656cb7 100644 --- a/test/embedded/collection.swift +++ b/test/embedded/collection.swift @@ -7,8 +7,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu @_silgen_name("putchar") func putchar(_: UInt8) diff --git a/test/embedded/concurrency-actors.swift b/test/embedded/concurrency-actors.swift index fa43b5d43d1ce..d8ae6c50d3775 100644 --- a/test/embedded/concurrency-actors.swift +++ b/test/embedded/concurrency-actors.swift @@ -7,8 +7,7 @@ // REQUIRES: executable_test // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu import _Concurrency diff --git a/test/embedded/concurrency-async-let.swift b/test/embedded/concurrency-async-let.swift index 737e1be271ae5..2c26ceac83721 100644 --- a/test/embedded/concurrency-async-let.swift +++ b/test/embedded/concurrency-async-let.swift @@ -7,8 +7,7 @@ // REQUIRES: executable_test // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu import _Concurrency diff --git a/test/embedded/concurrency-builtins.swift b/test/embedded/concurrency-builtins.swift index 24cac48b22828..dc577f86030f4 100644 --- a/test/embedded/concurrency-builtins.swift +++ b/test/embedded/concurrency-builtins.swift @@ -2,8 +2,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu import Builtin diff --git a/test/embedded/concurrency-simple.swift b/test/embedded/concurrency-simple.swift index 1df0d2d68f3e7..618db48fb18e6 100644 --- a/test/embedded/concurrency-simple.swift +++ b/test/embedded/concurrency-simple.swift @@ -7,8 +7,7 @@ // REQUIRES: executable_test // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu import _Concurrency diff --git a/test/embedded/custom-print.swift b/test/embedded/custom-print.swift index 3f75ad206ee83..9111bd89cbe9a 100644 --- a/test/embedded/custom-print.swift +++ b/test/embedded/custom-print.swift @@ -5,8 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu @_silgen_name("putchar") func putchar(_: UInt8) diff --git a/test/embedded/debuginfo.swift b/test/embedded/debuginfo.swift index e679003e4c37d..726fbf7affbe0 100644 --- a/test/embedded/debuginfo.swift +++ b/test/embedded/debuginfo.swift @@ -7,8 +7,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func foo(_ array: inout [T]) { array.withUnsafeMutableBytes { diff --git a/test/embedded/deserialize-vtables.swift b/test/embedded/deserialize-vtables.swift index ece26b8c2f773..c2e2fda964d3e 100644 --- a/test/embedded/deserialize-vtables.swift +++ b/test/embedded/deserialize-vtables.swift @@ -5,8 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu @main struct Main { diff --git a/test/embedded/dynamic-self.swift b/test/embedded/dynamic-self.swift index a2dbfa2efe4aa..8e8d3acb05183 100644 --- a/test/embedded/dynamic-self.swift +++ b/test/embedded/dynamic-self.swift @@ -1,8 +1,7 @@ // RUN: %target-swift-emit-ir %s -enable-experimental-feature Embedded -parse-as-library -module-name main | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu class MyClass { init() { diff --git a/test/embedded/fno-builtin.swift b/test/embedded/fno-builtin.swift index 69affa62566ef..a02b6c48ccd6d 100644 --- a/test/embedded/fno-builtin.swift +++ b/test/embedded/fno-builtin.swift @@ -3,8 +3,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func foo() -> [Int] { var a = [1, 2, 3] diff --git a/test/embedded/generic-classes-debuginfo.swift b/test/embedded/generic-classes-debuginfo.swift index b7c0fb5d35491..e8d8db88ecc7a 100644 --- a/test/embedded/generic-classes-debuginfo.swift +++ b/test/embedded/generic-classes-debuginfo.swift @@ -3,8 +3,7 @@ // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu struct User { let o: BaseClass diff --git a/test/embedded/generic-classes.swift b/test/embedded/generic-classes.swift index 57fb883b6b142..38f80cd5ecafb 100644 --- a/test/embedded/generic-classes.swift +++ b/test/embedded/generic-classes.swift @@ -4,8 +4,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu protocol Fooable { func foo() diff --git a/test/embedded/lto.swift b/test/embedded/lto.swift index c2bd79422a832..7d96ba676b40b 100644 --- a/test/embedded/lto.swift +++ b/test/embedded/lto.swift @@ -5,8 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // For LTO, the linker dlopen()'s the libLTO library, which is a scenario that // ASan cannot work in ("Interceptors are not working, AddressSanitizer is diff --git a/test/embedded/metatypes.swift b/test/embedded/metatypes.swift index b6f24a59287d5..cf6ed3009136b 100644 --- a/test/embedded/metatypes.swift +++ b/test/embedded/metatypes.swift @@ -2,8 +2,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func sink(t: T) {} diff --git a/test/embedded/modules-classes.swift b/test/embedded/modules-classes.swift index ad1ee631478fd..d11aff527cc70 100644 --- a/test/embedded/modules-classes.swift +++ b/test/embedded/modules-classes.swift @@ -9,8 +9,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // BEGIN MyModule.swift diff --git a/test/embedded/modules-globals-exec.swift b/test/embedded/modules-globals-exec.swift index 4ac31c7da49b1..5cf4a9668fde5 100644 --- a/test/embedded/modules-globals-exec.swift +++ b/test/embedded/modules-globals-exec.swift @@ -9,8 +9,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // BEGIN MyModule.swift diff --git a/test/embedded/modules-globals-many.swift b/test/embedded/modules-globals-many.swift index d003cbe220e0c..17542491ac909 100644 --- a/test/embedded/modules-globals-many.swift +++ b/test/embedded/modules-globals-many.swift @@ -7,8 +7,7 @@ // RUN: %target-swift-frontend -emit-ir -I %t %t/Main.swift -enable-experimental-feature Embedded -parse-as-library | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // Dependencies look like this: // diff --git a/test/embedded/modules-globals.swift b/test/embedded/modules-globals.swift index f081e33ccfe0d..13a15ab081193 100644 --- a/test/embedded/modules-globals.swift +++ b/test/embedded/modules-globals.swift @@ -5,8 +5,7 @@ // RUN: %target-swift-frontend -emit-ir -I %t %t/Main.swift -enable-experimental-feature Embedded -parse-as-library | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // BEGIN MyModule.swift diff --git a/test/embedded/modules-print-exec.swift b/test/embedded/modules-print-exec.swift index 18b21c2f99922..74e18c8484702 100644 --- a/test/embedded/modules-print-exec.swift +++ b/test/embedded/modules-print-exec.swift @@ -9,8 +9,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // BEGIN MyModule.swift diff --git a/test/embedded/no-autolink.swift b/test/embedded/no-autolink.swift index c8d026f3cb387..c5fb171145630 100644 --- a/test/embedded/no-autolink.swift +++ b/test/embedded/no-autolink.swift @@ -1,8 +1,7 @@ // RUN: %target-swift-frontend -emit-ir %s -enable-experimental-feature Embedded | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func staticstring() -> StaticString { return "hello" diff --git a/test/embedded/once-dependent.swift b/test/embedded/once-dependent.swift index bad01330b06a0..57d44b8e82cae 100644 --- a/test/embedded/once-dependent.swift +++ b/test/embedded/once-dependent.swift @@ -5,8 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public struct MyStructA { static var singleton = MyStructA() diff --git a/test/embedded/once-multithreaded.swift b/test/embedded/once-multithreaded.swift index 7f7c98ed13071..1e6937b292019 100644 --- a/test/embedded/once-multithreaded.swift +++ b/test/embedded/once-multithreaded.swift @@ -8,8 +8,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // BEGIN BridgingHeader.h diff --git a/test/embedded/once.swift b/test/embedded/once.swift index c13dab3a64e57..e80fff7d6f266 100644 --- a/test/embedded/once.swift +++ b/test/embedded/once.swift @@ -5,8 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // For LTO, the linker dlopen()'s the libLTO library, which is a scenario that // ASan cannot work in ("Interceptors are not working, AddressSanitizer is diff --git a/test/embedded/osize-genericspecializer.swift b/test/embedded/osize-genericspecializer.swift index e8413ed6cfe93..e33eb79f3c1e7 100644 --- a/test/embedded/osize-genericspecializer.swift +++ b/test/embedded/osize-genericspecializer.swift @@ -1,8 +1,7 @@ // RUN: %target-swift-emit-ir -Osize %s -enable-experimental-feature Embedded | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func foo(n: T) { bar(n: 42) diff --git a/test/embedded/osize-releasedevirt.swift b/test/embedded/osize-releasedevirt.swift index dac2b71ff831e..5403671eeb69d 100644 --- a/test/embedded/osize-releasedevirt.swift +++ b/test/embedded/osize-releasedevirt.swift @@ -2,8 +2,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func foo() { bar([42]) diff --git a/test/embedded/ouroboros-bug.swift b/test/embedded/ouroboros-bug.swift index 3e526ce6a6b09..1e44bb9a5c489 100644 --- a/test/embedded/ouroboros-bug.swift +++ b/test/embedded/ouroboros-bug.swift @@ -7,7 +7,6 @@ // RUN: %target-swift-frontend -target arm64-apple-none-macho -assert-config Debug -Osize -Xcc -D__MACH__ -Xcc -D__arm64__ -Xcc -D__APPLE__ -emit-ir %s -enable-experimental-feature Embedded | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple // REQUIRES: optimized_stdlib public func test() {} diff --git a/test/embedded/ptrauth-fieldptr1.swift b/test/embedded/ptrauth-fieldptr1.swift index f8413da20743f..cd3f82122622c 100644 --- a/test/embedded/ptrauth-fieldptr1.swift +++ b/test/embedded/ptrauth-fieldptr1.swift @@ -4,8 +4,7 @@ // RUN: %target-swift-frontend -enable-import-ptrauth-field-function-pointers -O -emit-ir %t/Main.swift -enable-experimental-feature Embedded -import-objc-header %t/header.h | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // REQUIRES: CPU=arm64e // BEGIN header.h diff --git a/test/embedded/ptrauth-fieldptr2.swift b/test/embedded/ptrauth-fieldptr2.swift index 6c9a11931da72..62cd1ce706f2e 100644 --- a/test/embedded/ptrauth-fieldptr2.swift +++ b/test/embedded/ptrauth-fieldptr2.swift @@ -6,8 +6,7 @@ // RUN: %target-swift-frontend -enable-import-ptrauth-field-function-pointers -O -emit-ir %t/Main.swift -I%t -enable-experimental-feature Embedded -import-objc-header %t/header.h // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // REQUIRES: CPU=arm64e // BEGIN header.h diff --git a/test/embedded/runtime-release.swift b/test/embedded/runtime-release.swift index dc879b58d0fa6..0237c98be675a 100644 --- a/test/embedded/runtime-release.swift +++ b/test/embedded/runtime-release.swift @@ -5,8 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu @main struct Main { diff --git a/test/embedded/runtime.swift b/test/embedded/runtime.swift index 752f4421d182c..522689ab76f98 100644 --- a/test/embedded/runtime.swift +++ b/test/embedded/runtime.swift @@ -5,8 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu @_silgen_name("putchar") func putchar(_: UInt8) diff --git a/test/embedded/shared-linkage.swift b/test/embedded/shared-linkage.swift index eabbd5f6927ff..b7de4bed17aa7 100644 --- a/test/embedded/shared-linkage.swift +++ b/test/embedded/shared-linkage.swift @@ -11,8 +11,7 @@ // RUN: %target-swift-frontend -Osize -emit-ir %t/Main.swift -I%t -enable-experimental-feature Embedded // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu // BEGIN Module.swift diff --git a/test/embedded/static-object.swift b/test/embedded/static-object.swift index a4366adab5ecf..1f59c0f309fd5 100644 --- a/test/embedded/static-object.swift +++ b/test/embedded/static-object.swift @@ -4,8 +4,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func stringArray() -> [StaticString] { return ["a", "b", "c", "d"] diff --git a/test/embedded/static-string-interpolation.swift b/test/embedded/static-string-interpolation.swift index ac554e1bb24dc..37311b9baae52 100644 --- a/test/embedded/static-string-interpolation.swift +++ b/test/embedded/static-string-interpolation.swift @@ -3,8 +3,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public struct MyInterpolation : StringInterpolationProtocol { public typealias StringLiteralType = StaticString diff --git a/test/embedded/stdlib-basic.swift b/test/embedded/stdlib-basic.swift index c59d09bdb155f..9bdf6f59adcc2 100644 --- a/test/embedded/stdlib-basic.swift +++ b/test/embedded/stdlib-basic.swift @@ -2,7 +2,6 @@ // RUN: %target-swift-frontend -target arm64-apple-none-macho -Xcc -D__MACH__ -Xcc -D__arm64__ -Xcc -D__APPLE__ -emit-ir %s -enable-experimental-feature Embedded | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple public func bool() -> Bool { return true diff --git a/test/embedded/stdlib-types.swift b/test/embedded/stdlib-types.swift index c3c036a1053a4..b284829c634d0 100644 --- a/test/embedded/stdlib-types.swift +++ b/test/embedded/stdlib-types.swift @@ -2,7 +2,6 @@ // RUN: %target-swift-frontend -target arm64-apple-none-macho -Xcc -D__MACH__ -Xcc -D__arm64__ -Xcc -D__APPLE__ -emit-ir %s -enable-experimental-feature Embedded | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple // REQUIRES: optimized_stdlib class MyClass {} diff --git a/test/embedded/throw-trap-stdlib.swift b/test/embedded/throw-trap-stdlib.swift index eb6f576d4ef20..4f9584da71a72 100644 --- a/test/embedded/throw-trap-stdlib.swift +++ b/test/embedded/throw-trap-stdlib.swift @@ -1,8 +1,7 @@ // RUN: %target-swift-frontend -emit-ir %s -enable-experimental-feature Embedded -throws-as-traps | %FileCheck %s // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func test() { withUnsafeTemporaryAllocation(byteCount: MemoryLayout.size, alignment: MemoryLayout.alignment) { p in diff --git a/test/embedded/throw-trap.swift b/test/embedded/throw-trap.swift index c33465aa18655..f4135b5fb8ead 100644 --- a/test/embedded/throw-trap.swift +++ b/test/embedded/throw-trap.swift @@ -3,8 +3,7 @@ // RUN: %target-swift-frontend -emit-ir %s -enable-experimental-feature Embedded -throws-as-traps | %FileCheck %s --check-prefix CHECK-TRAPS-IR // REQUIRES: swift_in_compiler -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu enum MyError : Error { case a diff --git a/test/embedded/throw-typed.swift b/test/embedded/throw-typed.swift index 89171974b0e33..416f529054b75 100644 --- a/test/embedded/throw-typed.swift +++ b/test/embedded/throw-typed.swift @@ -5,8 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public enum MyError : Error, Equatable { case a diff --git a/test/embedded/typeof.swift b/test/embedded/typeof.swift index 7d369e535a75a..8b7650ddc25db 100644 --- a/test/embedded/typeof.swift +++ b/test/embedded/typeof.swift @@ -2,8 +2,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=linux-gnu public func unsafeWriteArray(_ elementType: R.Type, array: inout T, index n: Int, value: R) { precondition(_isPOD(elementType)) From 403d9b70e603db13aaefe5b988f99ffdeb68baaf Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Fri, 17 Nov 2023 21:35:59 -0800 Subject: [PATCH 27/35] [embedded] Avoid passing -D__APPLE__ on Linux builds --- stdlib/public/Concurrency/CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index 770cd863e9a5e..80c926a346c8d 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -202,10 +202,14 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC if(NOT "${mod}" MATCHES "-linux-gnu$") continue() endif() + set(extra_c_compile_flags) + set(extra_swift_compile_flags) elseif (SWIFT_HOST_VARIANT STREQUAL "macosx") if(NOT "${mod}" MATCHES "-macos$") continue() endif() + set(extra_c_compile_flags -D__MACH__ -D__APPLE__ -ffreestanding) + set(extra_swift_compile_flags -Xcc -D__MACH__ -Xcc -D__APPLE__ -Xcc -ffreestanding) endif() set(SWIFT_SDK_embedded_ARCH_${mod}_MODULE "${mod}") @@ -247,12 +251,11 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC TaskCancellation.swift SWIFT_COMPILE_FLAGS - -Xcc -D__MACH__ -Xcc -D__APPLE__ -Xcc -ffreestanding -enable-experimental-feature Embedded + ${extra_swift_compile_flags} -enable-experimental-feature Embedded -parse-stdlib -DSWIFT_CONCURRENCY_EMBEDDED ${SWIFT_RUNTIME_CONCURRENCY_SWIFT_FLAGS} C_COMPILE_FLAGS - -D__MACH__ -D__APPLE__ -ffreestanding - ${SWIFT_RUNTIME_CONCURRENCY_C_FLAGS} -DSWIFT_CONCURRENCY_EMBEDDED=1 + ${extra_c_compile_flags} ${SWIFT_RUNTIME_CONCURRENCY_C_FLAGS} -DSWIFT_CONCURRENCY_EMBEDDED=1 MODULE_DIR "${CMAKE_BINARY_DIR}/lib/swift/embedded" SDK "embedded" ARCHITECTURE "${mod}" From eb43d0edaced40c72942a3e48afd6a9603fef863 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Fri, 17 Nov 2023 21:48:31 -0800 Subject: [PATCH 28/35] [embedded] Fix modules test expectations on Linux, skip LTO and Concurrency tests on Linux --- test/embedded/concurrency-actors.swift | 2 +- test/embedded/concurrency-async-let.swift | 2 +- test/embedded/concurrency-builtins.swift | 2 +- test/embedded/concurrency-simple.swift | 2 +- test/embedded/lto.swift | 2 +- test/embedded/modules-globals-many.swift | 2 +- test/embedded/modules-globals.swift | 8 ++++---- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/embedded/concurrency-actors.swift b/test/embedded/concurrency-actors.swift index d8ae6c50d3775..d65f0c3b1ebc5 100644 --- a/test/embedded/concurrency-actors.swift +++ b/test/embedded/concurrency-actors.swift @@ -7,7 +7,7 @@ // REQUIRES: executable_test // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: OS=macosx || OS=linux-gnu +// REQUIRES: OS=macosx import _Concurrency diff --git a/test/embedded/concurrency-async-let.swift b/test/embedded/concurrency-async-let.swift index 2c26ceac83721..900a8c4cd34f1 100644 --- a/test/embedded/concurrency-async-let.swift +++ b/test/embedded/concurrency-async-let.swift @@ -7,7 +7,7 @@ // REQUIRES: executable_test // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: OS=macosx || OS=linux-gnu +// REQUIRES: OS=macosx import _Concurrency diff --git a/test/embedded/concurrency-builtins.swift b/test/embedded/concurrency-builtins.swift index dc577f86030f4..a65ede31f8288 100644 --- a/test/embedded/concurrency-builtins.swift +++ b/test/embedded/concurrency-builtins.swift @@ -2,7 +2,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: OS=macosx || OS=linux-gnu +// REQUIRES: OS=macosx import Builtin diff --git a/test/embedded/concurrency-simple.swift b/test/embedded/concurrency-simple.swift index 618db48fb18e6..842b49eddf68e 100644 --- a/test/embedded/concurrency-simple.swift +++ b/test/embedded/concurrency-simple.swift @@ -7,7 +7,7 @@ // REQUIRES: executable_test // REQUIRES: swift_in_compiler // REQUIRES: optimized_stdlib -// REQUIRES: OS=macosx || OS=linux-gnu +// REQUIRES: OS=macosx import _Concurrency diff --git a/test/embedded/lto.swift b/test/embedded/lto.swift index 7d96ba676b40b..3810f14cf0350 100644 --- a/test/embedded/lto.swift +++ b/test/embedded/lto.swift @@ -5,7 +5,7 @@ // REQUIRES: swift_in_compiler // REQUIRES: executable_test -// REQUIRES: OS=macosx || OS=linux-gnu +// REQUIRES: OS=macosx // For LTO, the linker dlopen()'s the libLTO library, which is a scenario that // ASan cannot work in ("Interceptors are not working, AddressSanitizer is diff --git a/test/embedded/modules-globals-many.swift b/test/embedded/modules-globals-many.swift index 17542491ac909..53f3ae5faba38 100644 --- a/test/embedded/modules-globals-many.swift +++ b/test/embedded/modules-globals-many.swift @@ -43,4 +43,4 @@ public func main() { MyModuleC.foo() } -// CHECK: @"$s9MyModuleA6globalSivp" = global %TSi zeroinitializer +// CHECK: @"$s9MyModuleA6globalSivp" = {{.*}}global %TSi zeroinitializer diff --git a/test/embedded/modules-globals.swift b/test/embedded/modules-globals.swift index 13a15ab081193..a7ae29c8f29db 100644 --- a/test/embedded/modules-globals.swift +++ b/test/embedded/modules-globals.swift @@ -30,7 +30,7 @@ public func main() { foo() } -// CHECK: @"$s4Main022global_in_client_used_c1_D0Sivp" = global %TSi zeroinitializer -// CHECK: @"$s4Main024global_in_client_unused_c1_D0Sivp" = global %TSi zeroinitializer -// CHECK: @"$s8MyModule022global_in_module_used_d1_E0Sivp" = global %TSi zeroinitializer -// CHECK: @"$s8MyModule024global_in_module_unused_d1_E0Sivp" = global %TSi zeroinitializer +// CHECK: @"$s4Main022global_in_client_used_c1_D0Sivp" = {{.*}}global %TSi zeroinitializer +// CHECK: @"$s4Main024global_in_client_unused_c1_D0Sivp" = {{.*}}global %TSi zeroinitializer +// CHECK: @"$s8MyModule022global_in_module_used_d1_E0Sivp" = {{.*}}global %TSi zeroinitializer +// CHECK: @"$s8MyModule024global_in_module_unused_d1_E0Sivp" = {{.*}}global %TSi zeroinitializer From 9bac05728714a2a68b3e839797358bc383a936d6 Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Sat, 18 Nov 2023 11:58:00 -0800 Subject: [PATCH 29/35] [embedded] Pass -pthreads in embedded/once-multithreaded.swift to link correctly on Linux --- test/embedded/once-multithreaded.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/embedded/once-multithreaded.swift b/test/embedded/once-multithreaded.swift index 1e6937b292019..5508a74e35f8f 100644 --- a/test/embedded/once-multithreaded.swift +++ b/test/embedded/once-multithreaded.swift @@ -2,7 +2,7 @@ // RUN: %{python} %utils/split_file.py -o %t %s // RUN: %target-swift-frontend %t/Main.swift %S/Inputs/print.swift -import-bridging-header %t/BridgingHeader.h -enable-experimental-feature Embedded -c -o %t/main.o -// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip +// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip -pthreads // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: swift_in_compiler From a045b797e10daaf8dc07d4bbd68c0044bd3190dc Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Fri, 17 Nov 2023 16:53:49 -0800 Subject: [PATCH 30/35] Fix lit test Python/python_lint.swift ./utils/cmpcodesize/cmpcodesize/main.py:20:71: E231 missing whitespace after ',' ./utils/round-trip-syntax-test:20:20: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()` ./utils/round-trip-syntax-test:21:16: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()` I can't find any uses of round-trip-syntax-test, so I don't know if this fix is correct. --- utils/cmpcodesize/cmpcodesize/main.py | 2 +- utils/round-trip-syntax-test | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/cmpcodesize/cmpcodesize/main.py b/utils/cmpcodesize/cmpcodesize/main.py index 56a6fa645588f..fdc980d138fd2 100644 --- a/utils/cmpcodesize/cmpcodesize/main.py +++ b/utils/cmpcodesize/cmpcodesize/main.py @@ -17,7 +17,7 @@ import sys from cmpcodesize.compare import \ - compare_function_sizes, compare_sizes_of_file, list_function_sizes,\ + compare_function_sizes, compare_sizes_of_file, list_function_sizes, \ read_sizes diff --git a/utils/round-trip-syntax-test b/utils/round-trip-syntax-test index 8ad3849bf7b09..99743fd75b118 100755 --- a/utils/round-trip-syntax-test +++ b/utils/round-trip-syntax-test @@ -17,8 +17,8 @@ class RoundTripTask(object): skip_bad_syntax): assert action == '-round-trip-parse' or action == '-round-trip-lex' if sys.version_info[0] < 3: - assert type(input_filename) == str - assert type(swift_syntax_test) == str + assert isinstance(input_filename, str) + assert isinstance(swift_syntax_test, str) assert os.path.isfile(input_filename), \ "Input file {} is not accessible!".format(input_filename) From 3304ab2016a3995ffa7820239dc801dc3dfc2e47 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 23 Nov 2023 11:41:21 -0800 Subject: [PATCH 31/35] [Sema] Remove `LeaveClosureBodiesUnchecked` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This shouldn’t be needed anymore since we migrated code completion to be solver-based. rdar://91403086 --- include/swift/AST/Decl.h | 4 +-- include/swift/AST/TypeCheckRequests.h | 7 ++-- include/swift/AST/TypeCheckerTypeIDZone.def | 2 +- include/swift/Sema/ConstraintSystem.h | 18 ++++------ include/swift/Sema/IDETypeChecking.h | 3 +- lib/AST/Decl.cpp | 10 +++--- lib/IDE/PostfixCompletion.cpp | 3 +- lib/Sema/BuilderTransform.cpp | 3 +- lib/Sema/CSApply.cpp | 7 ++-- lib/Sema/CSSimplify.cpp | 3 +- lib/Sema/CSSyntacticElement.cpp | 6 ++-- lib/Sema/ConstraintSystem.cpp | 3 -- lib/Sema/PreCheckExpr.cpp | 39 ++++++--------------- lib/Sema/TypeCheckCodeCompletion.cpp | 14 ++------ lib/Sema/TypeCheckConstraints.cpp | 6 +--- lib/Sema/TypeCheckDeclPrimary.cpp | 17 +++------ lib/Sema/TypeCheckStmt.cpp | 14 ++------ lib/Sema/TypeCheckStorage.cpp | 11 ++---- lib/Sema/TypeChecker.cpp | 9 ++--- lib/Sema/TypeChecker.h | 11 ++---- 20 files changed, 51 insertions(+), 139 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index fac1c87b49dbc..0bd0a56be85bf 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -2212,9 +2212,7 @@ class PatternBindingDecl final : public Decl, } /// Returns the typechecked binding entry at the given index. - const PatternBindingEntry * - getCheckedPatternBindingEntry(unsigned i, - bool leaveClosureBodiesUnchecked = false) const; + const PatternBindingEntry *getCheckedPatternBindingEntry(unsigned i) const; /// Clean up walking the initializers for the pattern class InitIterator { diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 44e149fcb74bb..1cbf15e66faaf 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -2327,7 +2327,7 @@ class ResultTypeRequest class PatternBindingEntryRequest : public SimpleRequest { public: using SimpleRequest::SimpleRequest; @@ -2336,9 +2336,8 @@ class PatternBindingEntryRequest friend SimpleRequest; // Evaluation. - const PatternBindingEntry *evaluate(Evaluator &evaluator, - PatternBindingDecl *PBD, unsigned i, - bool LeaveClosureBodiesUnchecked) const; + const PatternBindingEntry * + evaluate(Evaluator &evaluator, PatternBindingDecl *PBD, unsigned i) const; public: // Separate caching. diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index b3cc83ef6d0e8..5b50b973b5ead 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -256,7 +256,7 @@ SWIFT_REQUEST(TypeChecker, OverriddenDeclsRequest, llvm::TinyPtrVector(ValueDecl *), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, PatternBindingEntryRequest, - const PatternBindingEntry *(PatternBindingDecl *, unsigned, bool), + const PatternBindingEntry *(PatternBindingDecl *, unsigned), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, PatternBindingCheckedAndContextualizedInitRequest, Expr *(PatternBindingDecl *, unsigned), diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index b6ddbf3eb8db5..19325aa253ad2 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -1806,14 +1806,10 @@ enum class ConstraintSystemFlags { /// \c DebugConstraintSolverOnLines. DebugConstraints = 0x08, - /// Don't try to type check closure bodies, and leave them unchecked. This is - /// used for source tooling functionalities. - LeaveClosureBodyUnchecked = 0x10, - /// If set, we are solving specifically to determine the type of a /// CodeCompletionExpr, and should continue in the presence of errors wherever /// possible. - ForCodeCompletion = 0x20, + ForCodeCompletion = 0x10, /// Include Clang function types when checking equality for function types. /// @@ -1824,13 +1820,13 @@ enum class ConstraintSystemFlags { /// should be treated as semantically different, as they may have different /// calling conventions, say due to Clang attributes such as /// `__attribute__((ns_consumed))`. - UseClangFunctionTypes = 0x40, + UseClangFunctionTypes = 0x20, /// When set, ignore async/sync mismatches - IgnoreAsyncSyncMismatch = 0x80, + IgnoreAsyncSyncMismatch = 0x40, /// Disable macro expansions. - DisableMacroExpansions = 0x100, + DisableMacroExpansions = 0x80, }; /// Options that affect the constraint system as a whole. @@ -5210,8 +5206,7 @@ class ConstraintSystem { /// \param replaceInvalidRefsWithErrors Indicates whether it's allowed /// to replace any discovered invalid member references with `ErrorExpr`. static bool preCheckTarget(SyntacticElementTarget &target, - bool replaceInvalidRefsWithErrors, - bool leaveClosureBodiesUnchecked); + bool replaceInvalidRefsWithErrors); /// Pre-check the expression, validating any types that occur in the /// expression and folding sequence expressions. @@ -5219,8 +5214,7 @@ class ConstraintSystem { /// \param replaceInvalidRefsWithErrors Indicates whether it's allowed /// to replace any discovered invalid member references with `ErrorExpr`. static bool preCheckExpression(Expr *&expr, DeclContext *dc, - bool replaceInvalidRefsWithErrors, - bool leaveClosureBodiesUnchecked); + bool replaceInvalidRefsWithErrors); /// Solve the system of constraints generated from provided target. /// diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index 7fffd10b44530..7e4fca4300101 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -58,8 +58,7 @@ namespace swift { } /// Typecheck binding initializer at \p bindingIndex. - void typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned bindingIndex, - bool leaveClosureBodiesUnchecked); + void typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned bindingIndex); /// Check if T1 is convertible to T2. /// diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 89e22c5683492..df0e2c0df3edd 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2220,12 +2220,11 @@ bool PatternBindingDecl::hasStorage() const { return false; } -const PatternBindingEntry *PatternBindingDecl::getCheckedPatternBindingEntry( - unsigned i, bool leaveClosureBodiesUnchecked) const { +const PatternBindingEntry * +PatternBindingDecl::getCheckedPatternBindingEntry(unsigned i) const { return evaluateOrDefault( getASTContext().evaluator, - PatternBindingEntryRequest{const_cast(this), i, - leaveClosureBodiesUnchecked}, + PatternBindingEntryRequest{const_cast(this), i}, nullptr); } @@ -2428,8 +2427,7 @@ bool PatternBindingDecl::isComputingPatternBindingEntry( const VarDecl *vd) const { unsigned i = getPatternEntryIndexForVarDecl(vd); return getASTContext().evaluator.hasActiveRequest( - PatternBindingEntryRequest{const_cast(this), i, - /*LeaveClosureBodyUnchecked=*/false}); + PatternBindingEntryRequest{const_cast(this), i}); } bool PatternBindingDecl::isExplicitlyInitialized(unsigned i) const { diff --git a/lib/IDE/PostfixCompletion.cpp b/lib/IDE/PostfixCompletion.cpp index f4ee4bf52eb5c..1711d7ca114c5 100644 --- a/lib/IDE/PostfixCompletion.cpp +++ b/lib/IDE/PostfixCompletion.cpp @@ -328,8 +328,7 @@ getOperatorCompletionTypes(DeclContext *DC, Type LHSType, OperatorDecl *Op) { llvm_unreachable("unexpected operator kind"); } - CS.preCheckExpression(OpCallExpr, DC, /*replaceInvalidRefsWithErrors=*/true, - /*leaveClosureBodyUnchecked=*/false); + CS.preCheckExpression(OpCallExpr, DC, /*replaceInvalidRefsWithErrors=*/true); OpCallExpr = CS.generateConstraints(OpCallExpr, DC); CS.assignFixedType(CS.getType(&LHS)->getAs(), LHSType); diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index 1784bb08b4ff8..3979747b668e3 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -1310,8 +1310,7 @@ class PreCheckResultBuilderApplication : public ASTWalker { DiagnosticTransaction transaction(diagEngine); HasError |= ConstraintSystem::preCheckExpression( - E, DC, /*replaceInvalidRefsWithErrors=*/true, - /*leaveClosureBodiesUnchecked=*/false); + E, DC, /*replaceInvalidRefsWithErrors=*/true); HasError |= transaction.hasErrors(); diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 64462ed173ddd..a2c8939a5027a 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -8749,11 +8749,8 @@ namespace { return true; case SolutionApplicationToFunctionResult::Delay: { - if (!Rewriter.cs.Options - .contains(ConstraintSystemFlags::LeaveClosureBodyUnchecked)) { - auto closure = cast(fn.getAbstractClosureExpr()); - ClosuresToTypeCheck.push_back(closure); - } + auto closure = cast(fn.getAbstractClosureExpr()); + ClosuresToTypeCheck.push_back(closure); return false; } } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index f8e22a617f56e..cc604181116af 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -10514,8 +10514,7 @@ static bool inferEnumMemberThroughTildeEqualsOperator( DiagnosticTransaction diagnostics(ctx.Diags); { - if (cs.preCheckTarget(target, /*replaceInvalidRefWithErrors=*/true, - /*leaveClosureBodyUnchecked=*/false)) { + if (cs.preCheckTarget(target, /*replaceInvalidRefWithErrors=*/true)) { // Skip diagnostics if they are disabled, otherwise it would result in // duplicate diagnostics, since this operation is going to be repeated // in diagnostic mode. diff --git a/lib/Sema/CSSyntacticElement.cpp b/lib/Sema/CSSyntacticElement.cpp index f71f2a3910d3d..b33ae0a39ae6a 100644 --- a/lib/Sema/CSSyntacticElement.cpp +++ b/lib/Sema/CSSyntacticElement.cpp @@ -539,8 +539,7 @@ class SyntacticElementConstraintGenerator void visitExprPattern(ExprPattern *EP) { auto target = SyntacticElementTarget::forExprPattern(EP); - if (cs.preCheckTarget(target, /*replaceInvalidRefWithErrors=*/true, - /*leaveClosureBodyUnchecked=*/false)) { + if (cs.preCheckTarget(target, /*replaceInvalidRefWithErrors=*/true)) { hadError = true; return; } @@ -757,8 +756,7 @@ class SyntacticElementConstraintGenerator /*bindPatternVarsOneWay=*/false); if (ConstraintSystem::preCheckTarget( - target, /*replaceInvalidRefsWithErrors=*/true, - /*LeaveCLosureBodyUnchecked=*/false)) + target, /*replaceInvalidRefsWithErrors=*/true)) return llvm::None; return target; diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index a892988af8747..5d0f81f95e56e 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -7407,9 +7407,6 @@ bool ConstraintSystem::participatesInInference(ClosureExpr *closure) const { if (getAppliedResultBuilderTransform(closure)) return true; - if (Options.contains(ConstraintSystemFlags::LeaveClosureBodyUnchecked)) - return false; - if (closure->hasEmptyBody()) return false; diff --git a/lib/Sema/PreCheckExpr.cpp b/lib/Sema/PreCheckExpr.cpp index 9f23b33598c19..f48965fa259f1 100644 --- a/lib/Sema/PreCheckExpr.cpp +++ b/lib/Sema/PreCheckExpr.cpp @@ -939,8 +939,6 @@ namespace { /// implicit `ErrorExpr` in place of invalid references. bool UseErrorExprs; - bool LeaveClosureBodiesUnchecked; - /// A stack of expressions being walked, used to determine where to /// insert RebindSelfInConstructorExpr nodes. llvm::SmallVector ExprStack; @@ -1009,11 +1007,9 @@ namespace { public: PreCheckExpression(DeclContext *dc, Expr *parent, - bool replaceInvalidRefsWithErrors, - bool leaveClosureBodiesUnchecked) - : Ctx(dc->getASTContext()), DC(dc), - ParentExpr(parent), UseErrorExprs(replaceInvalidRefsWithErrors), - LeaveClosureBodiesUnchecked(leaveClosureBodiesUnchecked) {} + bool replaceInvalidRefsWithErrors) + : Ctx(dc->getASTContext()), DC(dc), ParentExpr(parent), + UseErrorExprs(replaceInvalidRefsWithErrors) {} ASTContext &getASTContext() const { return Ctx; } @@ -1394,9 +1390,7 @@ namespace { /// true when we want the body to be considered part of this larger expression. bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) { // If we have a single statement that can become an expression, turn it - // into an expression now. This needs to happen before we check - // LeaveClosureBodiesUnchecked, as the closure may become a single expression - // closure. + // into an expression now. auto *body = closure->getBody(); if (auto *S = body->getSingleActiveStatement()) { if (S->mayProduceSingleValue(Ctx)) { @@ -1408,12 +1402,6 @@ bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) { } } - // If we won't be checking the body of the closure, don't walk into it here. - if (!closure->hasSingleExpressionBody()) { - if (LeaveClosureBodiesUnchecked) - return false; - } - // Update the current DeclContext to be the closure we're about to // recurse into. assert((closure->getParent() == DC || @@ -2310,15 +2298,13 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) { } bool ConstraintSystem::preCheckTarget(SyntacticElementTarget &target, - bool replaceInvalidRefsWithErrors, - bool leaveClosureBodiesUnchecked) { + bool replaceInvalidRefsWithErrors) { auto *DC = target.getDeclContext(); bool hadErrors = false; if (auto *expr = target.getAsExpr()) { - hadErrors |= preCheckExpression(expr, DC, replaceInvalidRefsWithErrors, - leaveClosureBodiesUnchecked); + hadErrors |= preCheckExpression(expr, DC, replaceInvalidRefsWithErrors); // Even if the pre-check fails, expression still has to be re-set. target.setExpr(expr); } @@ -2330,13 +2316,11 @@ bool ConstraintSystem::preCheckTarget(SyntacticElementTarget &target, auto *whereExpr = stmt->getWhere(); hadErrors |= preCheckExpression(sequenceExpr, DC, - /*replaceInvalidRefsWithErrors=*/true, - /*leaveClosureBodiesUnchecked=*/false); + /*replaceInvalidRefsWithErrors=*/true); if (whereExpr) { hadErrors |= preCheckExpression(whereExpr, DC, - /*replaceInvalidRefsWithErrors=*/true, - /*leaveClosureBodiesUnchecked=*/false); + /*replaceInvalidRefsWithErrors=*/true); } // Update sequence and where expressions to pre-checked versions. @@ -2354,14 +2338,11 @@ bool ConstraintSystem::preCheckTarget(SyntacticElementTarget &target, /// Pre-check the expression, validating any types that occur in the /// expression and folding sequence expressions. bool ConstraintSystem::preCheckExpression(Expr *&expr, DeclContext *dc, - bool replaceInvalidRefsWithErrors, - bool leaveClosureBodiesUnchecked) { + bool replaceInvalidRefsWithErrors) { auto &ctx = dc->getASTContext(); FrontendStatsTracer StatsTracer(ctx.Stats, "precheck-expr", expr); - PreCheckExpression preCheck(dc, expr, - replaceInvalidRefsWithErrors, - leaveClosureBodiesUnchecked); + PreCheckExpression preCheck(dc, expr, replaceInvalidRefsWithErrors); // Perform the pre-check. if (auto result = expr->walk(preCheck)) { diff --git a/lib/Sema/TypeCheckCodeCompletion.cpp b/lib/Sema/TypeCheckCodeCompletion.cpp index 0c0f0277be4d5..09264922e7797 100644 --- a/lib/Sema/TypeCheckCodeCompletion.cpp +++ b/lib/Sema/TypeCheckCodeCompletion.cpp @@ -77,9 +77,6 @@ getTypeOfExpressionWithoutApplying(Expr *&expr, DeclContext *dc, ConstraintSystemOptions options; options |= ConstraintSystemFlags::SuppressDiagnostics; - if (!Context.CompletionCallback) { - options |= ConstraintSystemFlags::LeaveClosureBodyUnchecked; - } // Construct a constraint system from this expression. ConstraintSystem cs(dc, options); @@ -223,8 +220,7 @@ bool TypeChecker::typeCheckForCodeCompletion( // expression and folding sequence expressions. auto failedPreCheck = ConstraintSystem::preCheckTarget(target, - /*replaceInvalidRefsWithErrors=*/true, - /*leaveClosureBodiesUnchecked=*/true); + /*replaceInvalidRefsWithErrors=*/true); if (failedPreCheck) return false; @@ -238,10 +234,7 @@ bool TypeChecker::typeCheckForCodeCompletion( options |= ConstraintSystemFlags::AllowFixes; options |= ConstraintSystemFlags::SuppressDiagnostics; options |= ConstraintSystemFlags::ForCodeCompletion; - if (!Context.CompletionCallback) { - options |= ConstraintSystemFlags::LeaveClosureBodyUnchecked; - } - + ConstraintSystem cs(DC, options); llvm::SmallVector solutions; @@ -309,8 +302,7 @@ getTypeOfCompletionContextExpr(DeclContext *DC, CompletionTypeCheckKind kind, ConcreteDeclRef &referencedDecl) { if (constraints::ConstraintSystem::preCheckExpression( parsedExpr, DC, - /*replaceInvalidRefsWithErrors=*/true, - /*leaveClosureBodiesUnchecked=*/true)) + /*replaceInvalidRefsWithErrors=*/true)) return llvm::None; switch (kind) { diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 14b539565b738..8546ba71b51ff 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -448,8 +448,7 @@ TypeChecker::typeCheckTarget(SyntacticElementTarget &target, // First, pre-check the target, validating any types that occur in the // expression and folding sequence expressions. if (ConstraintSystem::preCheckTarget( - target, /*replaceInvalidRefsWithErrors=*/true, - options.contains(TypeCheckExprFlags::LeaveClosureBodyUnchecked))) { + target, /*replaceInvalidRefsWithErrors=*/true)) { return llvm::None; } @@ -468,9 +467,6 @@ TypeChecker::typeCheckTarget(SyntacticElementTarget &target, if (DiagnosticSuppression::isEnabled(Context.Diags)) csOptions |= ConstraintSystemFlags::SuppressDiagnostics; - if (options.contains(TypeCheckExprFlags::LeaveClosureBodyUnchecked)) - csOptions |= ConstraintSystemFlags::LeaveClosureBodyUnchecked; - if (options.contains(TypeCheckExprFlags::DisableMacroExpansions)) csOptions |= ConstraintSystemFlags::DisableMacroExpansions; diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 72860119cb777..5530f2be9d337 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -2048,12 +2048,7 @@ class DeclChecker : public DeclVisitor { ASTContext &Ctx; SourceFile *SF; - bool LeaveClosureBodiesUnchecked; - - explicit DeclChecker(ASTContext &ctx, SourceFile *SF, - bool LeaveClosureBodiesUnchecked = false) - : Ctx(ctx), SF(SF), - LeaveClosureBodiesUnchecked(LeaveClosureBodiesUnchecked) {} + explicit DeclChecker(ASTContext &ctx, SourceFile *SF) : Ctx(ctx), SF(SF) {} ASTContext &getASTContext() const { return Ctx; } void addDelayedFunction(AbstractFunctionDecl *AFD) { @@ -2505,8 +2500,7 @@ class DeclChecker : public DeclVisitor { for (auto i : range(PBD->getNumPatternEntries())) { const auto *entry = PBD->isFullyValidated(i) ? &PBD->getPatternList()[i] - : PBD->getCheckedPatternBindingEntry( - i, LeaveClosureBodiesUnchecked); + : PBD->getCheckedPatternBindingEntry(i); assert(entry && "No pattern binding entry?"); const auto *Pat = PBD->getPattern(i); @@ -2632,9 +2626,6 @@ class DeclChecker : public DeclVisitor { if (!PBD->isInitializerChecked(i)) { TypeCheckExprOptions options; - if (LeaveClosureBodiesUnchecked) - options |= TypeCheckExprFlags::LeaveClosureBodyUnchecked; - TypeChecker::typeCheckPatternBinding(PBD, i, /*patternType=*/Type(), options); } @@ -4045,9 +4036,9 @@ class DeclChecker : public DeclVisitor { }; } // end anonymous namespace -void TypeChecker::typeCheckDecl(Decl *D, bool LeaveClosureBodiesUnchecked) { +void TypeChecker::typeCheckDecl(Decl *D) { auto *SF = D->getDeclContext()->getParentSourceFile(); - DeclChecker(D->getASTContext(), SF, LeaveClosureBodiesUnchecked).visit(D); + DeclChecker(D->getASTContext(), SF).visit(D); } void TypeChecker::checkParameterList(ParameterList *params, diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 576f61550bee4..85139a2a895f9 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1090,12 +1090,6 @@ class StmtChecker : public StmtVisitor { Expr *E = RS->getResult(); TypeCheckExprOptions options = {}; - if (LeaveBraceStmtBodyUnchecked) { - assert(DiagnosticSuppression::isEnabled(getASTContext().Diags) && - "Diagnosing and AllowUnresolvedTypeVariables don't seem to mix"); - options |= TypeCheckExprFlags::LeaveClosureBodyUnchecked; - } - ContextualTypePurpose ctp = CTP_ReturnStmt; if (auto func = dyn_cast_or_null(TheFunc->getAbstractFunctionDecl())) { @@ -2047,9 +2041,6 @@ void StmtChecker::typeCheckASTNode(ASTNode &node) { (!ctx.LangOpts.Playground && !ctx.LangOpts.DebuggerSupport); if (isDiscarded) options |= TypeCheckExprFlags::IsDiscarded; - if (LeaveBraceStmtBodyUnchecked) { - options |= TypeCheckExprFlags::LeaveClosureBodyUnchecked; - } auto resultTy = TypeChecker::typeCheckExpression(E, DC, /*contextualInfo=*/{}, options); @@ -2087,7 +2078,7 @@ void StmtChecker::typeCheckASTNode(ASTNode &node) { // Type check the declaration. if (auto *D = node.dyn_cast()) { - TypeChecker::typeCheckDecl(D, LeaveBraceStmtBodyUnchecked); + TypeChecker::typeCheckDecl(D); return; } @@ -2396,8 +2387,7 @@ bool TypeCheckASTNodeAtLocRequest::evaluate( [](VarDecl *VD) { (void)VD->getInterfaceType(); }); if (auto Init = PBD->getInit(i)) { if (!PBD->isInitializerChecked(i)) { - typeCheckPatternBinding(PBD, i, - /*LeaveClosureBodyUnchecked=*/false); + typeCheckPatternBinding(PBD, i); // Retrieve the accessor's body to trigger RecontextualizeClosures // This is important to get the correct USR of variables defined // in closures initializing lazy variables. diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index e6ff99795edf7..ef364293bf3ff 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -397,8 +397,7 @@ MemberwiseInitPropertiesRequest::evaluate(Evaluator &evaluator, /// Validate the \c entryNumber'th entry in \c binding. const PatternBindingEntry *PatternBindingEntryRequest::evaluate( - Evaluator &eval, PatternBindingDecl *binding, unsigned entryNumber, - bool LeaveClosureBodiesUnchecked) const { + Evaluator &eval, PatternBindingDecl *binding, unsigned entryNumber) const { const auto &pbe = binding->getPatternList()[entryNumber]; auto &Context = binding->getASTContext(); @@ -513,12 +512,8 @@ const PatternBindingEntry *PatternBindingEntryRequest::evaluate( if (patternType->hasUnresolvedType() || patternType->hasPlaceholder() || patternType->hasUnboundGenericType()) { - TypeCheckExprOptions options; - if (LeaveClosureBodiesUnchecked) { - options |= TypeCheckExprFlags::LeaveClosureBodyUnchecked; - } - if (TypeChecker::typeCheckPatternBinding(binding, entryNumber, patternType, - options)) { + if (TypeChecker::typeCheckPatternBinding(binding, entryNumber, + patternType)) { binding->setInvalid(); return &pbe; } diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 03619859cb52c..6e1972b822882 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -518,20 +518,15 @@ swift::handleSILGenericParams(GenericParamList *genericParams, } void swift::typeCheckPatternBinding(PatternBindingDecl *PBD, - unsigned bindingIndex, - bool leaveClosureBodiesUnchecked) { + unsigned bindingIndex) { assert(!PBD->isInitializerChecked(bindingIndex) && PBD->getInit(bindingIndex)); auto &Ctx = PBD->getASTContext(); DiagnosticSuppression suppression(Ctx.Diags); - TypeCheckExprOptions options; - if (leaveClosureBodiesUnchecked) - options |= TypeCheckExprFlags::LeaveClosureBodyUnchecked; - TypeChecker::typeCheckPatternBinding(PBD, bindingIndex, - /*patternType=*/Type(), options); + /*patternType=*/Type()); } bool swift::typeCheckASTNodeAtLoc(TypeCheckASTNodeAtLocContext TypeCheckCtx, diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 5c2883533632d..cafe4ae628aeb 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -131,16 +131,11 @@ enum class TypeCheckExprFlags { /// not affect type checking itself. IsExprStmt = 0x02, - /// Don't try to type check closure expression bodies, and leave them - /// unchecked. This is used by source tooling functionalities such as code - /// completion. - LeaveClosureBodyUnchecked = 0x04, - /// Don't type check expressions for correct availability. - DisableExprAvailabilityChecking = 0x08, + DisableExprAvailabilityChecking = 0x04, /// Don't expand macros. - DisableMacroExpansions = 0x10, + DisableMacroExpansions = 0x08, }; using TypeCheckExprOptions = OptionSet; @@ -474,7 +469,7 @@ Type typeCheckParameterDefault(Expr *&defaultValue, DeclContext *DC, void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD); -void typeCheckDecl(Decl *D, bool LeaveClosureBodiesUnchecked = false); +void typeCheckDecl(Decl *D); void addImplicitDynamicAttribute(Decl *D); void checkDeclAttributes(Decl *D); From 802601cf348f3b52d8f5c9887b7798a4031d9b43 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 23 Nov 2023 10:44:10 -0800 Subject: [PATCH 32/35] [CodeComplete] Prefer function call if both reference and call are possible The real-world use case here is the `Task` initializer in the added test case. In general, we should only prefer to insert an unapplied function reference if it has a better type relation than calling the function because, in most cases, you want to call functions and not get unapplied references to them. rdar://90456105 --- lib/IDE/CompletionLookup.cpp | 7 +++-- ...both_reference_and_call_are_possible.swift | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 test/IDE/complete_prefer_function_call_if_both_reference_and_call_are_possible.swift diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index 82edff684f246..6cb48b2a421c9 100644 --- a/lib/IDE/CompletionLookup.cpp +++ b/lib/IDE/CompletionLookup.cpp @@ -1972,10 +1972,11 @@ bool CompletionLookup::addCompoundFunctionNameIfDesiable( if (!useFunctionReference && funcTy) { // We know that the CodeCompletionResultType is AST-based so we can pass // nullptr for USRTypeContext. - auto maxRel = CodeCompletionResultType(funcTy).calculateTypeRelation( + auto maxFuncTyRel = CodeCompletionResultType(funcTy).calculateTypeRelation( &expectedTypeContext, CurrDeclContext, /*USRTypeContext=*/nullptr); - useFunctionReference = - maxRel >= CodeCompletionResultTypeRelation::Convertible; + auto maxResultTyRel = CodeCompletionResultType(funcTy->getResult()).calculateTypeRelation( + &expectedTypeContext, CurrDeclContext, /*USRTypeContext=*/nullptr); + useFunctionReference = maxFuncTyRel > maxResultTyRel; } if (!useFunctionReference) return false; diff --git a/test/IDE/complete_prefer_function_call_if_both_reference_and_call_are_possible.swift b/test/IDE/complete_prefer_function_call_if_both_reference_and_call_are_possible.swift new file mode 100644 index 0000000000000..c68cbbd1ae090 --- /dev/null +++ b/test/IDE/complete_prefer_function_call_if_both_reference_and_call_are_possible.swift @@ -0,0 +1,30 @@ +// RUN: %batch-code-completion + +struct Route { + func makeDetailView() -> Int { + return 52 + } +} + +@resultBuilder struct ViewBuilder { + static func buildBlock(_ x: Int) -> Int { return x } +} + +func foo(@ViewBuilder destination: () -> Int) {} +func foo(destination: Int) {} + +func test(route: Route?) { + route.map { route in + foo(destination: route.#^COMPLETE^#) + } +} + + +// COMPLETE-DAG: Keyword[self]/CurrNominal: self[#Route#]; +// COMPLETE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: makeDetailView()[#Int#]; + +func testTask(route: Route) { + Task { + route.#^IN_TASK?check=COMPLETE^# + } +} From 784ba20b83019d31c7ede024910090a4a86bc9f8 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 23 Nov 2023 11:05:44 -0800 Subject: [PATCH 33/35] [CodeComplete] Add test case for rdar://88883761 This test was already passing. Probably fixed by migrating to solver-based completions. rdar://88883761 --- ...ll_if_both_reference_and_call_are_possible.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/IDE/complete_prefer_function_call_if_both_reference_and_call_are_possible.swift b/test/IDE/complete_prefer_function_call_if_both_reference_and_call_are_possible.swift index c68cbbd1ae090..f0e6d312816f3 100644 --- a/test/IDE/complete_prefer_function_call_if_both_reference_and_call_are_possible.swift +++ b/test/IDE/complete_prefer_function_call_if_both_reference_and_call_are_possible.swift @@ -28,3 +28,16 @@ func testTask(route: Route) { route.#^IN_TASK?check=COMPLETE^# } } + +protocol Builder { + func recv(_: (T) throws -> Void) +} + +struct S { + func foo(x: Int) throws {} + func test(builder: Builder) { + builder.recv(#^IN_CONTEXT_FOR_UNAPPLIED_REF^#) + } +} +// IN_CONTEXT_FOR_UNAPPLIED_REF-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: foo(x:)[#(Int) throws -> ()#]; name=foo(x:) +// IN_CONTEXT_FOR_UNAPPLIED_REF-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: test(builder:)[#(any Builder) -> ()#]; name=test(builder:) From b96d5ff584b648599784130ee78a6354f0801baa Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 23 Nov 2023 11:13:35 -0800 Subject: [PATCH 34/35] [CodeComplete] Add test case for #57148, #57149 The issue no longer occurs on `main`. Add a test case for it. Fixes #57148 Fixes #57149 --- .../IDE/issues_fixed/issue-57148.swift | 16 ++++++++++ .../IDE/issues_fixed/issue-57149.swift | 30 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 validation-test/IDE/issues_fixed/issue-57148.swift create mode 100644 validation-test/IDE/issues_fixed/issue-57149.swift diff --git a/validation-test/IDE/issues_fixed/issue-57148.swift b/validation-test/IDE/issues_fixed/issue-57148.swift new file mode 100644 index 0000000000000..d55a10d9e4eb0 --- /dev/null +++ b/validation-test/IDE/issues_fixed/issue-57148.swift @@ -0,0 +1,16 @@ +// RUN: %batch-code-completion + +protocol MyProtocol {} +struct MyStruct: MyProtocol { + func aspectRatio(contentMode: Int) -> MyStruct { fatalError() } +} + +func foo(content: (MyStruct) -> I) where I : MyProtocol { fatalError() } + +func bazx() { + foo() { image in + image.aspectRatio(#^COMPLETE^#) + } +} + +// COMPLETE: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]/TypeRelation[Convertible]: ['(']{#contentMode: Int#}[')'][#MyStruct#]; name=contentMode: diff --git a/validation-test/IDE/issues_fixed/issue-57149.swift b/validation-test/IDE/issues_fixed/issue-57149.swift new file mode 100644 index 0000000000000..bcf9d48334743 --- /dev/null +++ b/validation-test/IDE/issues_fixed/issue-57149.swift @@ -0,0 +1,30 @@ +// RUN: %batch-code-completion + +protocol View {} + +extension Never: View {} + +@resultBuilder struct ViewBuilder { + static func buildBlock() -> Never { fatalError() } + static func buildBlock(_ content: Content) -> Content where Content : View { fatalError() } +} + +struct AsyncImage : View where Content : View { + init(@ViewBuilder content: @escaping (Image) -> Content) { fatalError() } +} + +struct Image: View {} + +extension View { + func bspectRatio(foo: Int) -> Never { fatalError() } +} + +struct ContentView: View { + var body: some View { + AsyncImage() { image in + image.bspectRatio(#^COMPLETE^#foo: 1) + } + } +} + +// COMPLETE: Decl[InstanceMethod]/Super/Flair[ArgLabels]/TypeRelation[Convertible]: ['(']{#foo: Int#}[')'][#Never#]; name=foo: From 99d2b91a5fc135ec6c98c7223a20ef347514faab Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Mon, 27 Nov 2023 12:03:47 -0800 Subject: [PATCH 35/35] [embedded] Consider 'skipped' decls when SILGen-ing accessors, fix compiler crash on unavailable accessors --- lib/SILGen/SILGen.cpp | 12 +++++++++++- lib/SILGen/SILGen.h | 5 +++++ lib/SILGen/SILGenDecl.cpp | 2 +- lib/SILGen/SILGenTopLevel.cpp | 4 ++-- lib/SILGen/SILGenType.cpp | 4 ++-- ...le_decl_optimization_complete_struct.swift | 9 +++++++++ test/embedded/accessor-unavailable.swift | 19 +++++++++++++++++++ 7 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 test/embedded/accessor-unavailable.swift diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 1b29af764d13f..592ea82ba5f85 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -1802,7 +1802,7 @@ void SILGenModule::visitVarDecl(VarDecl *vd) { if (vd->hasStorage()) addGlobalVariable(vd); - vd->visitEmittedAccessors([&](AccessorDecl *accessor) { + visitEmittedAccessors(vd, [&](AccessorDecl *accessor) { emitFunction(accessor); }); @@ -1825,6 +1825,16 @@ void SILGenModule::visitMacroExpansionDecl(MacroExpansionDecl *d) { // Expansion already visited as auxiliary decls. } +void SILGenModule::visitEmittedAccessors( + AbstractStorageDecl *D, llvm::function_ref callback) { + D->visitEmittedAccessors([&](AccessorDecl *accessor) { + if (shouldSkipDecl(accessor)) + return; + + callback(accessor); + }); +} + bool SILGenModule::canStorageUseStoredKeyPathComponent(AbstractStorageDecl *decl, ResilienceExpansion expansion) { diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h index 2af88e6091159..1057c241cfa5d 100644 --- a/lib/SILGen/SILGen.h +++ b/lib/SILGen/SILGen.h @@ -301,6 +301,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor { void visitMacroDecl(MacroDecl *d); void visitMacroExpansionDecl(MacroExpansionDecl *d); + // Same as AbstractStorageDecl::visitEmittedAccessors, but skips over skipped + // (unavailable) decls. + void visitEmittedAccessors(AbstractStorageDecl *D, + llvm::function_ref); + void emitEntryPoint(SourceFile *SF); void emitEntryPoint(SourceFile *SF, SILFunction *TopLevel); diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index 914eb499638c6..c23c1ee92286c 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -1628,7 +1628,7 @@ void SILGenFunction::visitVarDecl(VarDecl *D) { }); // Emit the variable's accessors. - D->visitEmittedAccessors([&](AccessorDecl *accessor) { + SGM.visitEmittedAccessors(D, [&](AccessorDecl *accessor) { SGM.emitFunction(accessor); }); } diff --git a/lib/SILGen/SILGenTopLevel.cpp b/lib/SILGen/SILGenTopLevel.cpp index 9317bccdffe23..3c6b0a3c50be7 100644 --- a/lib/SILGen/SILGenTopLevel.cpp +++ b/lib/SILGen/SILGenTopLevel.cpp @@ -257,7 +257,7 @@ void SILGenTopLevel::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) { } void SILGenTopLevel::visitAbstractStorageDecl(AbstractStorageDecl *ASD) { - ASD->visitEmittedAccessors( + SGF.SGM.visitEmittedAccessors(ASD, [this](AccessorDecl *Accessor) { visitAbstractFunctionDecl(Accessor); }); } @@ -338,7 +338,7 @@ void SILGenTopLevel::TypeVisitor::visitAbstractFunctionDecl( void SILGenTopLevel::TypeVisitor::visitAbstractStorageDecl( AbstractStorageDecl *ASD) { - ASD->visitEmittedAccessors( + SGF.SGM.visitEmittedAccessors(ASD, [this](AccessorDecl *Accessor) { visitAbstractFunctionDecl(Accessor); }); } diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index 8238aabcdf95f..5ae67f2aef6ae 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -1242,7 +1242,7 @@ class SILGenType : public TypeMemberVisitor { } void visitAccessors(AbstractStorageDecl *asd) { - asd->visitEmittedAccessors([&](AccessorDecl *accessor) { + SGM.visitEmittedAccessors(asd, [&](AccessorDecl *accessor) { visitFuncDecl(accessor); }); } @@ -1422,7 +1422,7 @@ class SILGenExtension : public TypeMemberVisitor { } void visitAccessors(AbstractStorageDecl *asd) { - asd->visitEmittedAccessors([&](AccessorDecl *accessor) { + SGM.visitEmittedAccessors(asd, [&](AccessorDecl *accessor) { visitFuncDecl(accessor); }); } diff --git a/test/IRGen/unavailable_decl_optimization_complete_struct.swift b/test/IRGen/unavailable_decl_optimization_complete_struct.swift index 26999fe6200b9..9d3cd55743351 100644 --- a/test/IRGen/unavailable_decl_optimization_complete_struct.swift +++ b/test/IRGen/unavailable_decl_optimization_complete_struct.swift @@ -21,6 +21,15 @@ public struct AvailableStruct { _modify { fatalError() } } + // CHECK-NO-STRIP: s4Test15AvailableStructV45availablePropertyWithSomeUnavailableAccessorsxvg + // CHECK-NO-STRIP: s4Test15AvailableStructV45availablePropertyWithSomeUnavailableAccessorsxvs + // CHECK-STRIP-NOT: s4Test15AvailableStructV45availablePropertyWithSomeUnavailableAccessorsxvs + public var availablePropertyWithSomeUnavailableAccessors: T { + get { fatalError() } + @available(*, unavailable) + set { fatalError() } + } + // CHECK-NO-STRIP: s4Test15AvailableStructVyACyxGxcfC // CHECK-STRIP-NOT: s4Test15AvailableStructVyACyxGxcfC @available(*, unavailable) diff --git a/test/embedded/accessor-unavailable.swift b/test/embedded/accessor-unavailable.swift new file mode 100644 index 0000000000000..c8455f5e2ec23 --- /dev/null +++ b/test/embedded/accessor-unavailable.swift @@ -0,0 +1,19 @@ +// RUN: %target-swift-frontend -emit-ir %s -enable-experimental-feature Embedded | %FileCheck %s + +// REQUIRES: swift_in_compiler +// REQUIRES: VENDOR=apple +// REQUIRES: OS=macosx + +struct Foo { + public subscript(x: Int) -> Int { + get { + return 0 + } + + @available(*, unavailable) + set { } + } +} + +// CHECK: $s4main3FooVyS2icig +// CHECK-NOT: $s4main3FooVyS2icis