Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-3087] No way to arbitrarily initialise an Array's storage #45677

Closed
karwa opened this issue Oct 31, 2016 · 6 comments
Closed

[SR-3087] No way to arbitrarily initialise an Array's storage #45677

karwa opened this issue Oct 31, 2016 · 6 comments
Assignees
Labels
feature A feature request or implementation improvement standard library Area: Standard library umbrella swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented

Comments

@karwa
Copy link
Contributor

karwa commented Oct 31, 2016

Previous ID SR-3087
Radar rdar://problem/21880692
Original Reporter @karwa
Type Improvement
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Standard Library
Labels Improvement, LanguageFeatureRequest
Assignee @natecook1000
Priority Medium

md5: 78d2891e46bb0f408db15202b1a1b736

relates to:

  • SR-3631 Introduce ContiguouslyStored protocol and kill ArraySlice type

Issue Description:

The standard library does not currently expose a way to allocate an Array's storage and (unsafely) initialise its elements, as we can with UnsafeMutablePointer.

An example use-case is to implement a concurrent map. See: https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161024/003769.html

Even though we expose a UMP from Array, it cannot be used to unsafely initialise the Array elements.

The workaround at the moment is to allocate a UMP, initialise its elements unsafely, and then copy the contents in to an Array via the Array(Sequence) constructor, which is less than optimal.

@dabrahams
Copy link
Collaborator

Just a clarification: this is not really about pre-allocated storage, but about being able to tell the array "please allocate the memory and let me (unsafely) initialize the elements"

@karwa
Copy link
Contributor Author

karwa commented Nov 1, 2016

Okay, updated the description.

It would be nice to be able to wrap a contiguously-stored block of elements as a bona-fida Array, though. Ensuring no other mutation-enabling pointers to the memory exist would be an issue, though - is that something which could be achievable with a memory-ownership model?

@karwa
Copy link
Contributor Author

karwa commented Feb 23, 2017

You could imagine a way for a ContigiouslyStored to guarantee its buffer-pointer will have capacity for n elements, and that n elements will be initialised after mutating.

protocol UnsafelyInitialisable: ContiguouslyStored {
     // - The given buffer pointer promises to have capacity for at least `count` elements
     // - The `perform` closure promises that `count` elements will be initialised when it returns
     mutating func withUnsafeMutableBufferPointer<T>(count: Int, perform: (UnsafeMutableBufferPointer<Element>)->T) -> T
}

It fits the requirement that we initialise the type's native buffer in-place, not copying from an existing buffer. Not making it an initialiser means we could also unsafely re-initialise slices of an Array, possibly changing its length.

@atrick
Copy link
Member

atrick commented Mar 24, 2017

This might need a new builtin that produces an indeterminate (undef) of some trivial type. By extension it could produce an indeterminate tuple of trivial types.

@karwa
Copy link
Contributor Author

karwa commented Mar 24, 2017

One extension to the stdlib I could imagine being helpful is a way to "unpack" an UnsafeMutableBufferPointer<T> for the case when T.stride != T.size. For example, it might be cool to initialise an Array directly from a file:

var a = Array<T>()
a.withUnsafeMutableBufferPointer(count: 3) { ptr in
    let r = read(fd, UnsafeRawPointer(ptr.baseAddress), MemoryLayout<T>.size * 3)
    guard r == (MemoryLayout<T>.size * 3) else { throw OhNoError }
    ptr.unpack(count: 3) // Iterates backwards from (MemoryLayout<T>.size * n), moving items to (MemoryLayout<T>.stride * n).
}
// Go walking off in to the sunshine with an Array<T>...

@natecook1000
Copy link
Member

This was approved as a new array initializer in SE-0245 and implemented in #23134

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented label Apr 18, 2023
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A feature request or implementation improvement standard library Area: Standard library umbrella swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented
Projects
None yet
Development

No branches or pull requests

5 participants