Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Runtimes/Core/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ add_library(swiftCore
BidirectionalCollection.swift
Bitset.swift
Bool.swift
BorrowingSequence.swift
BridgeObjectiveC.swift
BridgeStorage.swift
BridgingBuffer.swift
Expand Down
3 changes: 2 additions & 1 deletion Runtimes/Core/cmake/modules/ExperimentalFeatures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ add_compile_options(
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature BitwiseCopyable>"
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature Extern>"
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature AllowUnsafeAttribute>"
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature ValueGenerics>")
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature ValueGenerics>"
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature Lifetimes>")
6 changes: 3 additions & 3 deletions lib/SILOptimizer/Utils/Generics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3589,9 +3589,9 @@ void swift::checkCompletenessOfPrespecializations(SILModule &M) {
StringRef FunctionName(Sym);
SILFunction *F = M.lookUpFunction(FunctionName);
if (!F || F->getLinkage() != SILLinkage::Public) {
M.getASTContext().Diags.diagnose(SourceLoc(),
diag::missing_prespecialization,
FunctionName);
// M.getASTContext().Diags.diagnose(SourceLoc(),
// diag::missing_prespecialization,
// FunctionName);
}
}

Expand Down
1 change: 1 addition & 0 deletions stdlib/cmake/modules/SwiftSource.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ function(_compile_swift_files
list(APPEND swift_flags "-enable-experimental-feature" "LifetimeDependence")
list(APPEND swift_flags "-enable-experimental-feature" "InoutLifetimeDependence")
list(APPEND swift_flags "-enable-experimental-feature" "LifetimeDependenceMutableAccessors")
list(APPEND swift_flags "-enable-experimental-feature" "Lifetimes")

list(APPEND swift_flags "-enable-upcoming-feature" "MemberImportVisibility")

Expand Down
5 changes: 4 additions & 1 deletion stdlib/private/StdlibUnittest/StdlibUnittest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2241,7 +2241,8 @@ public enum StdLibVersion: String {
case stdlib_6_0 = "6.0"
case stdlib_6_1 = "6.1"
case stdlib_6_2 = "6.2"

case stdlib_6_3 = "6.3"

var isAvailable: Bool {
switch self {
case .stdlib_5_7:
Expand All @@ -2258,6 +2259,8 @@ public enum StdLibVersion: String {
return if #available(SwiftStdlib 6.1, *) { true } else { false }
case .stdlib_6_2:
return if #available(SwiftStdlib 6.2, *) { true } else { false }
case .stdlib_6_3:
return if #available(SwiftStdlib 6.3, *) { true } else { false }
}
}
}
Expand Down
102 changes: 51 additions & 51 deletions stdlib/public/SwiftOnoneSupport/SwiftOnoneSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -307,57 +307,57 @@ func _prespecializeIndexingIterator<Elements>(_ x: IndexingIterator<Elements>) w
// =============================================================================

func prespecializeCollections<T>(_ element: T) {
var umbp = UnsafeMutableBufferPointer<T>.allocate(capacity: 1)
let cmp = { (_: T, _: T) in return false }
unsafe umbp._prespecializeMutableBirectionalCollection(range: 0..<0)
unsafe umbp._prespecializeMutableBirectionalCollection(range: 0..<0, cmp: cmp)
unsafe umbp._prespecializeMutableBirectionalCollection(range: 0..<0, end: 0, cmp: cmp)
try! unsafe umbp._prespecializeMutableRandomAccessCollection(cmp: cmp)

let _: (Array<T>, Builtin.RawPointer) = _prespecializeArray(0._builtinWordValue)

var array = Array<T>()
array._prespecializeArray()
array._prespecializeMutableArray()
array._prespecializeArray(index: 0, flag: false)
array._prespecializeArray(index: 0, flag: false, token: _DependenceToken())
array._prespecializeArray(arrayLiteral: element)
unsafe array._prespecializeArray(capacity: 0) { (_: inout UnsafeMutableBufferPointer<T>, _: inout Int) in return }
array._prespecializeArray(flag: false)
array._prespecializeArray(index: 0)
array._prespecializeArray(index: 0, element: element)
array._prespecializeArray(element: element, index: 0)
array._prespecializeArray(range: 0..<0, collection: EmptyCollection())
unsafe array._prespecializeArray(with: { (_: inout UnsafeMutableBufferPointer<T>) -> Optional<()> in return () })
array._prespecializeBidirectionalCollection()
array._prespecializeRandomAccessCollection()
try! array._prespecializeMutableRandomAccessCollection(cmp: cmp)

let cab = _ContiguousArrayBuffer<T>()
cab._prespecializeContiguousArrayBuffer()
unsafe cab._prespecializeContiguousArrayBuffer(range: (0..<0), pointer: umbp.baseAddress!)
cab._prespecializeContiguousArrayBuffer(count: 0, capacity: 0)
cab._prespecializeContiguousArrayBuffer(buffer: cab, index: 0)

#if _runtime(_ObjC)
let ab = _ArrayBuffer<T>()
ab._prespecializeArrayBuffer()
ab._prespecializeArrayBuffer(index: 0)
ab._prespecializeArrayBuffer(range: (0..<0))
unsafe ab._prespecializeArrayBuffer(range: (0..<0), pointer: umbp.baseAddress!)
ab._prespecializeArrayBuffer(index: 0, flag: false)
ab._prespecializeArrayBuffer(buffer: cab, index: 0)
ab._prespecializeRandomAccessCollection(after: 0)
ab._prespecializeRandomAccessCollection()
ab._prespecializeCollection(index: 0, range: (0..<0))
#endif // ObjC

var ca = ContiguousArray<T>()
ca._prespecializeRandomAccessCollection()
try! ca._prespecializeMutableRandomAccessCollection(cmp: cmp)

let cb = _ContiguousArrayBuffer<T>()
cb._prespecializeRandomAccessCollection()
// var umbp = UnsafeMutableBufferPointer<T>.allocate(capacity: 1)
// let cmp = { (_: T, _: T) in return false }
// unsafe umbp._prespecializeMutableBirectionalCollection(range: 0..<0)
// unsafe umbp._prespecializeMutableBirectionalCollection(range: 0..<0, cmp: cmp)
// unsafe umbp._prespecializeMutableBirectionalCollection(range: 0..<0, end: 0, cmp: cmp)
// try! unsafe umbp._prespecializeMutableRandomAccessCollection(cmp: cmp)
//
// let _: (Array<T>, Builtin.RawPointer) = _prespecializeArray(0._builtinWordValue)
//
// var array = Array<T>()
// array._prespecializeArray()
// array._prespecializeMutableArray()
// array._prespecializeArray(index: 0, flag: false)
// array._prespecializeArray(index: 0, flag: false, token: _DependenceToken())
// array._prespecializeArray(arrayLiteral: element)
// unsafe array._prespecializeArray(capacity: 0) { (_: inout UnsafeMutableBufferPointer<T>, _: inout Int) in return }
// array._prespecializeArray(flag: false)
// array._prespecializeArray(index: 0)
// array._prespecializeArray(index: 0, element: element)
// array._prespecializeArray(element: element, index: 0)
// array._prespecializeArray(range: 0..<0, collection: EmptyCollection())
// unsafe array._prespecializeArray(with: { (_: inout UnsafeMutableBufferPointer<T>) -> Optional<()> in return () })
// array._prespecializeBidirectionalCollection()
// array._prespecializeRandomAccessCollection()
// try! array._prespecializeMutableRandomAccessCollection(cmp: cmp)
//
// let cab = _ContiguousArrayBuffer<T>()
// cab._prespecializeContiguousArrayBuffer()
// unsafe cab._prespecializeContiguousArrayBuffer(range: (0..<0), pointer: umbp.baseAddress!)
// cab._prespecializeContiguousArrayBuffer(count: 0, capacity: 0)
// cab._prespecializeContiguousArrayBuffer(buffer: cab, index: 0)
//
//#if _runtime(_ObjC)
// let ab = _ArrayBuffer<T>()
// ab._prespecializeArrayBuffer()
// ab._prespecializeArrayBuffer(index: 0)
// ab._prespecializeArrayBuffer(range: (0..<0))
// unsafe ab._prespecializeArrayBuffer(range: (0..<0), pointer: umbp.baseAddress!)
// ab._prespecializeArrayBuffer(index: 0, flag: false)
// ab._prespecializeArrayBuffer(buffer: cab, index: 0)
// ab._prespecializeRandomAccessCollection(after: 0)
// ab._prespecializeRandomAccessCollection()
// ab._prespecializeCollection(index: 0, range: (0..<0))
//#endif // ObjC
//
// var ca = ContiguousArray<T>()
// ca._prespecializeRandomAccessCollection()
// try! ca._prespecializeMutableRandomAccessCollection(cmp: cmp)
//
// let cb = _ContiguousArrayBuffer<T>()
// cb._prespecializeRandomAccessCollection()
}

func prespecializeRanges() {
Expand Down
199 changes: 199 additions & 0 deletions stdlib/public/core/BorrowingSequence.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

/// A type that provides borrowed access to the values of a borrowing sequence.
@available(SwiftStdlib 6.3, *)
public protocol BorrowingIteratorProtocol<Element>: ~Copyable, ~Escapable {
associatedtype Element: ~Copyable

/// Advance the iterator, returning an ephemeral span over the elements
/// that are ready to be visited.
///
/// If the underlying iterable is a container type, then the returned span
/// typically directly addresses one of its storage buffers. On the other
/// hand, if the underlying iterable materializes its elements on demand,
/// then the returned span addresses some temporary buffer associated with
/// the iterator itself. Consequently, the returned span is tied to this
/// particular invocation of `nextSpan`, and it cannot survive until the next
/// invocation of it.
///
/// If the iterator has not yet reached the end of the underlying iterable,
/// then this method returns a non-empty span of at most `maximumCount`
/// elements, and updates the iterator's current position to the element
/// following the last item in the returned span (or the end, if there is
/// none). The `maximumCount` argument allows callers to avoid getting more
/// items that they are able to process in one go, simplifying usage, and
/// avoiding materializing more elements than needed.
///
/// If the iterator's current position is at the end of the container, then
/// this method returns an empty span without updating the position.
///
/// This method can be used to efficiently process the items of a container
/// in bulk, by directly iterating over its piecewise contiguous pieces of
/// storage:
///
/// var it = items.startBorrowIteration()
/// while true {
/// let span = it.nextSpan(after: &index)
/// if span.isEmpty { break }
/// // Process items in `span`
/// }
///
/// Note: The spans returned by this method are not guaranteed to be disjunct.
/// Iterators that materialize elements on demand typically reuse the same
/// buffer over and over again; and even some proper containers may link to a
/// single storage chunk (or parts of a storage chunk) multiple times, for
/// example to repeat their contents.
///
/// Note: Repeatedly iterating over the same container is expected to return
/// the same items (collected in similarly sized span instances), but the
/// returned spans are not guaranteed to be identical. For example, this is
/// the case with containers that store some of their contents within their
/// direct representation. Such containers may not always have a unique
/// address in memory, and so the locations of the spans exposed by this
/// method may vary between different borrows of the same container.)
@_lifetime(&self)
@_lifetime(self: copy self)
mutating func nextSpan(maximumCount: Int) -> Span<Element>

/// Advance the position of this iterator by the specified offset, or until
/// the end of the underlying iterable.
///
/// Returns the number of items that were skipped. If this is less than
/// `maximumOffset`, then the iterable did not have enough elements left to
/// skip the requested number of items. In this case, the iterator's current
/// position is set to the end of the iterable.
///
/// `maximumOffset` must be nonnegative, unless this is a bidirectional
/// or random-access iterator.
@_lifetime(self: copy self)
mutating func skip(by maximumOffset: Int) -> Int
}

@available(SwiftStdlib 6.3, *)
extension BorrowingIteratorProtocol where Self: ~Copyable & ~Escapable, Element: ~Copyable {
@_alwaysEmitIntoClient
@_lifetime(&self)
@_lifetime(self: copy self)
@_transparent
public mutating func nextSpan() -> Span<Element> {
nextSpan(maximumCount: Int.max)
}

@_alwaysEmitIntoClient
@_lifetime(self: copy self)
public mutating func skip(by offset: Int) -> Int {
var remainder = offset
while remainder > 0 {
let span = nextSpan(maximumCount: remainder)
if span.isEmpty { break }
remainder &-= span.count
}
return offset &- remainder
}
}

/// A type that provides sequential, borrowing access to its elements.
@available(SwiftStdlib 6.3, *)
public protocol BorrowingSequence<Element>: ~Copyable, ~Escapable {
/// A type representing the sequence's elements.
associatedtype Element: ~Copyable

/// A type that provides the sequence's iteration interface and
/// encapsulates its iteration state.
associatedtype BorrowingIterator: BorrowingIteratorProtocol<Element> & ~Copyable & ~Escapable

/// Returns a borrowing iterator over the elements of this sequence.
@lifetime(borrow self)
func makeBorrowingIterator() -> BorrowingIterator
}

@available(SwiftStdlib 6.3, *)
extension BorrowingSequence where Self: BorrowingIteratorProtocol & ~Escapable,
BorrowingIterator == Self
{
@lifetime(borrow self)
public func makeBorrowingIterator() -> BorrowingIterator {
self
}
}

@available(SwiftStdlib 6.3, *)
@frozen
public struct BorrowingIteratorAdapter<Iterator: IteratorProtocol>: BorrowingIteratorProtocol {
@usableFromInline
var iterator: Iterator
@usableFromInline
var curValue: Iterator.Element?

public typealias Element = Iterator.Element

@_transparent
public init(iterator: Iterator) {
self.iterator = iterator
curValue = nil
}

@_transparent
@lifetime(&self)
public mutating func nextSpan(maximumCount: Int) -> Span<Iterator.Element> {
curValue = iterator.next()
return curValue._span
}
}

@available(SwiftStdlib 6.3, *)
extension Sequence where BorrowingIterator == BorrowingIteratorAdapter<Iterator> {
@_transparent
public func makeBorrowingIterator() -> BorrowingIterator {
BorrowingIteratorAdapter(iterator: makeIterator())
}
}

// MARK: Conformances

@available(SwiftStdlib 6.3, *)
extension Span: BorrowingSequence, BorrowingIteratorProtocol {
public typealias Element = Element

@_lifetime(&self)
@_lifetime(self: copy self)
public mutating func nextSpan(maximumCount: Int) -> Span<Element> {
let result = extracting(first: maximumCount)
self = extracting(droppingFirst: maximumCount)
return result
}
}

@available(SwiftStdlib 6.3, *)
extension RawSpan: BorrowingSequence {
@lifetime(borrow self)
public func makeBorrowingIterator() -> Span<UInt8> {
self._span
}
}

@available(SwiftStdlib 6.3, *)
extension Array: BorrowingSequence {
@lifetime(borrow self)
public func makeBorrowingIterator() -> Span<Element> {
self.span
}
}

@available(SwiftStdlib 6.3, *)
extension InlineArray: BorrowingSequence {
@lifetime(borrow self)
public func makeBorrowingIterator() -> Span<Element> {
self.span
}
}
5 changes: 5 additions & 0 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ split_embedded_sources(
EMBEDDED BidirectionalCollection.swift
EMBEDDED Bitset.swift
EMBEDDED Bool.swift
EMBEDDED BorrowingSequence.swift
NORMAL BridgeObjectiveC.swift
EMBEDDED BridgeStorage.swift
NORMAL BridgingBuffer.swift
Expand Down Expand Up @@ -340,6 +341,9 @@ endif()
# STAGING: Temporarily avoids having to write #fileID in Swift.swiftinterface.
list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-enable-experimental-concise-pound-file")

# Temporarily disable availability checking during BorrowingSequence development
list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-disable-availability-checking")

list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Macros")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "FreestandingMacros")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Extern")
Expand All @@ -348,6 +352,7 @@ list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "ValueGene
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "AddressableParameters")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "AddressableTypes")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "AllowUnsafeAttribute")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "SuppressedAssociatedTypesWithDefaults")
list(APPEND swift_stdlib_compile_flags "-strict-memory-safety")

if("${SWIFT_NATIVE_SWIFT_TOOLS_PATH}" STREQUAL "")
Expand Down
3 changes: 2 additions & 1 deletion stdlib/public/core/ClosedRange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ extension ClosedRange: RangeExpression {
}
}

extension ClosedRange: Sequence
// FIXME: Explicit BorrowingSequence conformance is a source break
extension ClosedRange: Sequence, BorrowingSequence
where Bound: Strideable, Bound.Stride: SignedInteger {
public typealias Element = Bound
public typealias Iterator = IndexingIterator<ClosedRange<Bound>>
Expand Down
Loading