Skip to content

Commit 184367c

Browse files
committed
[stdlib] Fix Array.append(contentsOf:) for arguments of type NSArray
Due to a couple of unfortunate circumstances, appending an NSArray instance to an Array instance does not actually append any elements. The cause is #29220, which accidentally optimized away the actual loop that appends the elements in this particular case. (And only this particular case, which is why this wasn’t detected by the test suite.) When the argument to `Array.append(contentsOf:)` is of type NSArray, the `newElements is [Element]` expression is compiled into a runtime check that returns true, eliminating the subsequent loop over the remaining items of the iterator. Sadly, NSArray.underestimatedCount` currently returns 0, so the earlier _copyContents call is a noop, so no elements get added to `self` at all. Turning the `is` test into a direct equality check between the metatype instances resolves the issue.
1 parent b385332 commit 184367c

File tree

2 files changed

+10
-1
lines changed

2 files changed

+10
-1
lines changed

stdlib/public/core/Array.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1229,7 +1229,7 @@ extension Array: RangeReplaceableCollection {
12291229
// elements. It reduces code size, because the following code
12301230
// can be removed by the optimizer by constant folding this check in a
12311231
// generic specialization.
1232-
if newElements is [Element] {
1232+
if S.self == [Element].self {
12331233
_internalInvariant(remainder.next() == nil)
12341234
return
12351235
}

validation-test/stdlib/ArrayNew.swift.gyb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,15 @@ ArrayTestSuite.test("BridgedToObjC.Nonverbatim.RoundtripThroughSwiftArray") {
11101110
}
11111111
}
11121112

1113+
ArrayTestSuite.test("append(contentsOf: NSArray)") {
1114+
// A stray runtime `is` test caused this particular operation to fail in 5.3.
1115+
// rdar://70448247
1116+
let nsarray: NSArray = [2, 3, 4]
1117+
var array: [Any] = [1]
1118+
array.append(contentsOf: nsarray)
1119+
expectEqual(array as? [Int], [1, 2, 3, 4])
1120+
}
1121+
11131122
ArrayTestSuite.setUp {
11141123
resetLeaksOfDictionaryKeysValues()
11151124
resetLeaksOfObjCDictionaryKeysValues()

0 commit comments

Comments
 (0)