diff --git a/stdlib/public/core/Span/MutableRawSpan.swift b/stdlib/public/core/Span/MutableRawSpan.swift index 47c4aa7d43308..151d34fad7483 100644 --- a/stdlib/public/core/Span/MutableRawSpan.swift +++ b/stdlib/public/core/Span/MutableRawSpan.swift @@ -27,6 +27,7 @@ public struct MutableRawSpan: ~Copyable & ~Escapable { @usableFromInline internal let _count: Int + @unsafe @_alwaysEmitIntoClient internal func _start() -> UnsafeMutableRawPointer { unsafe _pointer._unsafelyUnwrappedUnchecked @@ -171,8 +172,8 @@ extension RawSpan { @_alwaysEmitIntoClient @lifetime(borrow mutableRawSpan) public init(_mutableRawSpan mutableRawSpan: borrowing MutableRawSpan) { - let (start, count) = (mutableRawSpan._start(), mutableRawSpan._count) - let span = unsafe RawSpan(_unsafeStart: start, byteCount: count) + let (start, count) = unsafe (mutableRawSpan._pointer, mutableRawSpan._count) + let span = unsafe RawSpan(_unchecked: start, byteCount: count) self = unsafe _overrideLifetime(span, borrowing: mutableRawSpan) } } @@ -432,6 +433,10 @@ extension MutableRawSpan { public mutating func update( fromContentsOf source: RawSpan ) -> Int { + _precondition( + source.byteCount <= self.byteCount, + "destination span cannot contain every byte from source." + ) if source.byteCount == 0 { return 0 } unsafe source.withUnsafeBytes { unsafe _start().copyMemory(from: $0.baseAddress!, byteCount: $0.count) @@ -560,7 +565,7 @@ extension MutableRawSpan { @_alwaysEmitIntoClient @lifetime(&self) mutating public func extracting(_: UnboundedRange) -> Self { - let newSpan = unsafe Self(_unchecked: _start(), byteCount: _count) + let newSpan = unsafe Self(_unchecked: _pointer, byteCount: _count) return unsafe _overrideLifetime(newSpan, mutating: &self) } } diff --git a/stdlib/public/core/Span/MutableSpan.swift b/stdlib/public/core/Span/MutableSpan.swift index 7cbbcf439b3cb..c097ef0111d77 100644 --- a/stdlib/public/core/Span/MutableSpan.swift +++ b/stdlib/public/core/Span/MutableSpan.swift @@ -28,6 +28,7 @@ public struct MutableSpan @usableFromInline internal let _count: Int + @unsafe @_alwaysEmitIntoClient internal func _start() -> UnsafeMutableRawPointer { unsafe _pointer._unsafelyUnwrappedUnchecked @@ -447,7 +448,7 @@ extension MutableSpan where Element: BitwiseCopyable { _ body: (_ buffer: UnsafeMutableRawBufferPointer) throws(E) -> Result ) throws(E) -> Result { let bytes = unsafe UnsafeMutableRawBufferPointer( - start: (_count == 0) ? nil : _start(), + start: (_count == 0) ? nil : _pointer, count: _count &* MemoryLayout.stride ) return try unsafe body(bytes) @@ -462,6 +463,7 @@ extension MutableSpan { @_alwaysEmitIntoClient @lifetime(self: copy self) public mutating func update(repeating repeatedValue: consuming Element) { + guard !isEmpty else { return } unsafe _start().withMemoryRebound(to: Element.self, capacity: count) { unsafe $0.update(repeating: repeatedValue, count: count) } @@ -599,7 +601,7 @@ extension MutableSpan where Element: BitwiseCopyable { ) where Element: BitwiseCopyable { guard count > 0 else { return } // rebind _start manually in order to avoid assumptions about alignment. - let rp = _start()._rawValue + let rp = unsafe _start()._rawValue let binding = Builtin.bindMemory(rp, count._builtinWordValue, Element.self) let rebound = unsafe UnsafeMutablePointer(rp) unsafe rebound.update(repeating: repeatedValue, count: count) @@ -796,7 +798,7 @@ extension MutableSpan where Element: ~Copyable { @_alwaysEmitIntoClient @lifetime(&self) mutating public func extracting(_: UnboundedRange) -> Self { - let newSpan = unsafe Self(_unchecked: _start(), count: _count) + let newSpan = unsafe Self(_unchecked: _pointer, count: _count) return unsafe _overrideLifetime(newSpan, mutating: &self) } }