mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[stdlib] Restore Array value semantics
'nuff said. Swift SVN r18923
This commit is contained in:
@@ -183,6 +183,10 @@ extension ArrayBuffer {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
mutating func isMutableAndUniquelyReferenced() -> Bool {
|
||||
return Swift.isUniquelyReferenced(&storage) && _hasMutableBuffer
|
||||
}
|
||||
|
||||
/// If this buffer is backed by a ContiguousArrayBuffer, return it.
|
||||
/// Otherwise, return nil. Note: the result's elementStorage may
|
||||
|
||||
@@ -47,6 +47,14 @@ protocol ArrayBufferType : MutableCollection {
|
||||
mutating func requestUniqueMutableBuffer(minimumCapacity: Int)
|
||||
-> ContiguousArrayBuffer<Element>?
|
||||
|
||||
/// Returns true iff this buffer is backed by a uniquely-referenced mutable
|
||||
/// ContiguousArrayBuffer.
|
||||
///
|
||||
/// Note: this function must remain mutating; otherwise the buffer
|
||||
/// may acquire spurious extra references, which will cause
|
||||
/// unnecessary reallocation.
|
||||
mutating func isMutableAndUniquelyReferenced() -> Bool
|
||||
|
||||
/// If this buffer is backed by a ContiguousArrayBuffer, return it.
|
||||
/// Otherwise, return nil. Note: the result's elementStorage may
|
||||
/// not match ours, if we are a SliceBuffer.
|
||||
|
||||
@@ -39,7 +39,7 @@ protocol ArrayType
|
||||
/// element. Otherwise, nil.
|
||||
var _elementStorageIfContiguous: UnsafePointer<Element> {get}
|
||||
|
||||
subscript(index: Int) -> Self.GeneratorType.Element {get nonmutating set}
|
||||
subscript(index: Int) -> Self.GeneratorType.Element {get set}
|
||||
|
||||
//===--- basic mutations ------------------------------------------------===//
|
||||
|
||||
|
||||
@@ -42,10 +42,25 @@ struct ${Self}<T> : MutableCollection, Sliceable {
|
||||
_precondition(index >= 0, "Negative ${Self} index is out of range")
|
||||
return _buffer[index]
|
||||
}
|
||||
nonmutating set {
|
||||
set {
|
||||
_precondition(index < count, "${Self} index out of range")
|
||||
_precondition(index >= 0, "Negative array index is out of range")
|
||||
_buffer[index] = newValue
|
||||
if _buffer.isMutableAndUniquelyReferenced() {
|
||||
_buffer[index] = newValue
|
||||
}
|
||||
else {
|
||||
{
|
||||
(inout buffer: _Buffer, e: Element)->() in
|
||||
var newBuffer = ContiguousArrayBuffer<T>(
|
||||
count: buffer.count, minimumCapacity: buffer.count)
|
||||
let target = buffer._uninitializedCopy(
|
||||
0..index, target: newBuffer.elementStorage)
|
||||
target.initialize(e)
|
||||
buffer._uninitializedCopy(
|
||||
(index + 1)..buffer.count, target: target + 1)
|
||||
buffer = _Buffer(newBuffer)
|
||||
}(&_buffer, newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,15 +162,12 @@ extension ${Self} : ArrayType {
|
||||
/// array.
|
||||
/// Complexity: O(N)
|
||||
func copy() -> ${Self} {
|
||||
var result = self
|
||||
result.reserveCapacity(0)
|
||||
return result
|
||||
return self
|
||||
}
|
||||
|
||||
/// Ensure the uniqueness of the array.
|
||||
/// Complexity: O(N)
|
||||
mutating func unshare() {
|
||||
reserveCapacity(0)
|
||||
func unshare() {
|
||||
}
|
||||
|
||||
/// Ensure the array has enough mutable contiguous storage to store
|
||||
|
||||
@@ -123,6 +123,10 @@ struct ContiguousArrayBuffer<T> : ArrayBufferType, LogicValue {
|
||||
return isUniquelyReferenced() && capacity >= minimumCapacity ? self : nil
|
||||
}
|
||||
|
||||
mutating func isMutableAndUniquelyReferenced() -> Bool {
|
||||
return isUniquelyReferenced()
|
||||
}
|
||||
|
||||
/// If this buffer is backed by a ContiguousArrayBuffer, return it.
|
||||
/// Otherwise, return nil. Note: the result's elementStorage may
|
||||
/// not match ours, if we are a SliceBuffer.
|
||||
|
||||
@@ -95,6 +95,10 @@ struct SliceBuffer<T> : ArrayBufferType {
|
||||
return nil
|
||||
}
|
||||
|
||||
mutating func isMutableAndUniquelyReferenced() -> Bool {
|
||||
return _hasNativeBuffer && Swift.isUniquelyReferenced(&owner)
|
||||
}
|
||||
|
||||
/// If this buffer is backed by a ContiguousArrayBuffer, return it.
|
||||
/// Otherwise, return nil. Note: the result's elementStorage may
|
||||
/// not match ours, since we are a SliceBuffer.
|
||||
|
||||
@@ -183,7 +183,7 @@ func testBridgedVerbatim() {
|
||||
println(nsArrayOfBaseConvertedToAnyObjectArray[0] as Base)
|
||||
|
||||
//===--- Up- and Down-casts -----------------------------------------------===//
|
||||
let derived: Derived[] = [Derived(11), Derived(22)]
|
||||
var derived: Derived[] = [Derived(11), Derived(22)]
|
||||
// CHECK-NEXT: [[derived0:\[Derived#[0-9]+\(11\), Derived#[0-9]+\(22\)\]{1}]]
|
||||
println(derived)
|
||||
|
||||
|
||||
@@ -132,18 +132,8 @@ where T.GeneratorType.Element == T._Buffer.Element,
|
||||
|
||||
let y = x
|
||||
x[x.endIndex.pred()] = 17
|
||||
let bufferId3 = checkReallocation(x, bufferId2, false)
|
||||
checkEqual(x, y, true)
|
||||
|
||||
if x !== y {
|
||||
println("unexpectedly, x !== y")
|
||||
}
|
||||
|
||||
x += 42
|
||||
let bufferId3 = checkReallocation(x, bufferId2, true)
|
||||
checkEqual(x, y, false)
|
||||
if x === y {
|
||||
println("unexpectedly, x === y")
|
||||
}
|
||||
|
||||
println("done.")
|
||||
}
|
||||
@@ -223,9 +213,9 @@ func testCocoa() {
|
||||
printSequence(a)
|
||||
// CHECK-NEXT: [foo, garply, baz]
|
||||
|
||||
// Mutating an element in a changes b, too
|
||||
// Mutating an element in a has no effect on b
|
||||
printSequence(b)
|
||||
// CHECK-NEXT: [foo, garply, baz]
|
||||
// CHECK-NEXT: [foo, bar, baz]
|
||||
|
||||
a = nsArrayOfStrings()
|
||||
a.insert("bag", atIndex:2)
|
||||
@@ -259,24 +249,25 @@ func testSlice() {
|
||||
var bSlice = b[3..5]
|
||||
println("<\(bSlice.count)>")
|
||||
// CHECK-NEXT: <2>
|
||||
printSequence(bSlice)
|
||||
// CHECK-NEXT: [3, 4]
|
||||
println("bSlice0: \(bSlice)") // CHECK-NEXT: bSlice0: [3, 4]
|
||||
|
||||
// bSlice += X(11)..X(13)
|
||||
|
||||
// Writing into b changes bSlice
|
||||
// Writing into b does not change bSlice
|
||||
b[4] = 41
|
||||
printSequence(bSlice) // CHECK-NEXT: [3, 41]
|
||||
println("bSlice1: \(bSlice)") // CHECK-NEXT: bSlice1: [3, 4]
|
||||
|
||||
// Writing into bSlice changes b
|
||||
bSlice[1] = 42 // CHECK-NEXT: [3, 42]
|
||||
printSequence(bSlice)
|
||||
printSequence(b) // CHECK-NEXT: [0, 1, 2, 3, 42, 5, 6]
|
||||
// Writing into bSlice does not change b
|
||||
bSlice[1] = 42
|
||||
|
||||
|
||||
println("bSlice2: \(bSlice)") // CHECK-NEXT: bSlice2: [3, 42]
|
||||
printSequence(b) // CHECK-NEXT: [0, 1, 2, 3, 41, 5, 6]
|
||||
|
||||
var c = b
|
||||
b[4..b.count].qsort(<)
|
||||
printSequence(b) // CHECK-NEXT: [0, 1, 2, 3, 5, 6, 42]
|
||||
printSequence(c) // CHECK-NEXT: [0, 1, 2, 3, 5, 6, 42]
|
||||
printSequence(b) // CHECK-NEXT: [0, 1, 2, 3, 5, 6, 41]
|
||||
printSequence(c) // CHECK-NEXT: [0, 1, 2, 3, 41, 5, 6]
|
||||
|
||||
// Now a bridged slice
|
||||
var a = Array<NSString>(
|
||||
@@ -291,8 +282,8 @@ func testSlice() {
|
||||
aSlice[0] = "buzz" // CHECK-NEXT: [buzz, baz]
|
||||
printSequence(aSlice)
|
||||
|
||||
// ...and also changes a with reference semantics
|
||||
printSequence(a) // CHECK-NEXT: [foo, buzz, baz]
|
||||
// ...and doesn't affect a
|
||||
printSequence(a) // CHECK-NEXT: [foo, bar, baz]
|
||||
|
||||
// Appending to aSlice works...
|
||||
aSlice += "fodder"
|
||||
@@ -300,7 +291,7 @@ func testSlice() {
|
||||
printSequence(aSlice) // CHECK-NEXT: [buzz, baz, fodder]
|
||||
|
||||
// And doesn't change a
|
||||
printSequence(a) // CHECK-NEXT: [foo, buzz, baz]
|
||||
printSequence(a) // CHECK-NEXT: [foo, bar, baz]
|
||||
}
|
||||
testSlice()
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
// RUN: %target-run-simple-swift | FileCheck %s
|
||||
|
||||
// Generate all possible permutes.
|
||||
func _permuteInternal(elem: Int, size : Int, perm : Int[], visited : Bool[], verify : (Int[]) -> ()) {
|
||||
func _permuteInternal(
|
||||
elem: Int, size : Int,
|
||||
inout perm : Int[], inout visited : Bool[],
|
||||
verify : (Int[]) -> ()
|
||||
) {
|
||||
if (elem == size) {
|
||||
verify(perm)
|
||||
return
|
||||
@@ -13,20 +17,16 @@ func _permuteInternal(elem: Int, size : Int, perm : Int[], visited : Bool[], ver
|
||||
}
|
||||
visited[i] = true
|
||||
perm[elem] = i
|
||||
_permuteInternal(elem + 1, size, perm, visited, verify)
|
||||
_permuteInternal(elem + 1, size, &perm, &visited, verify)
|
||||
visited[i] = false
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience wrapper for the permute method.
|
||||
func permute(size : Int, verify : (Int[]) -> ()) {
|
||||
var perm : Int[] = []
|
||||
var visited : Bool[] = []
|
||||
for i in 0..size {
|
||||
visited.append(false)
|
||||
perm.append(0)
|
||||
}
|
||||
_permuteInternal(0, size, perm, visited, verify)
|
||||
var perm = Int[](count: size, repeatedValue: 0)
|
||||
var visited = Bool[](count: size, repeatedValue: false)
|
||||
_permuteInternal(0, size, &perm, &visited, verify)
|
||||
}
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ permute(3, printer)
|
||||
let sort_verifier : (Int[]) -> () = {
|
||||
var y = sorted($0)
|
||||
for i in 0..y.count - 1 {
|
||||
if (y[i] > y[i+1]) {
|
||||
print("Error!\n")
|
||||
if (y[i] > y[i+1]) {
|
||||
println("Error: \(y)")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user