Skip to content

[Foundation] Import shims with @implementationOnly #28918

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

Merged

Conversation

lorentey
Copy link
Member

@lorentey lorentey commented Dec 21, 2019

Update the Foundation overlay to import its shims with the @_implementationOnly attribute, i.e., privately. This removes the shims module (_SwiftFoundationOverlayShims) from the Foundation overlay's swiftinterface.

Unfortunately Foundation’s Data has three instances where it calls _SwiftFoundationOverlayShims._withStackOrHeapBuffer within @inlinable code. These need to be eliminated, since the calls are currently exposed in the public interface. The three instances are in:

  • Data.init<S: Sequence>(_: S)
  • Data.append<S: Sequence>(contentsOf: S)
  • Data.replaceSubrange<C: Collection>(_: Range<Int>, with: C)

Rewrite the first two of these to write sequence contents directly into the target Data instance (saving a memcpy and possibly a memory allocation).

In replaceSubrange, add fast paths for contiguous collection cases, falling back to a Swift version of _withStackOrHeapBuffer with a 32-byte inline buffer.

The expectation is that this will be an overall speedup in most cases, with the possible exception of replaceSubrange invocations with a large non-contiguous collection.

rdar://58132561

We want to enable overlays to import their shims as @_implementationOnly, so that the shims disappear from the public interface.

However, this isn’t possible when a shim is called from an @inlinable func, because then the existence (and definition) of the shim needs to be available to all callers of it.

Unfortunately Foundation’s Data has three instances where it calls  _SwiftFoundationOverlayShims._withStackOrHeapBuffer within @inlinable code:

- Data.init<S: Sequence>(_: S)
- Data.append<S: Sequence>(contentsOf: S)
- Data.replaceSubrange<C: Collection>(_: Range<Int>, with: C)

Rewrite the first two to write sequence contents directly into the target Data instance (saving a memcpy and possibly a memory allocation).

In replaceSubrange, add fast paths for contiguous collection cases, falling back to a Swift version of _withStackOrHeapBuffer with a 32-byte inline buffer.

The expectation is that this will be an overall speedup in most cases, with the possible exception of replaceSubrange invocations with a large non-contiguous collection.

rdar://58132561
@lorentey lorentey requested a review from phausler December 21, 2019 04:46
@lorentey
Copy link
Member Author

@swift-ci test

@lorentey
Copy link
Member Author

@swift-ci benchmark

@swiftlang swiftlang deleted a comment from swift-ci Dec 21, 2019
@swiftlang swiftlang deleted a comment from swift-ci Dec 21, 2019
@lorentey lorentey changed the title [Foundation] Remove inlinable shim calls [Foundation] Imports shims with @implementationOnly Dec 21, 2019
@swift-ci

This comment has been minimized.

@lorentey
Copy link
Member Author

This seems to be a surprisingly big improvement. 😮

(I wonder if the closure calls to the shim allocated a block?)

@lorentey
Copy link
Member Author

Heh, no, it's probably a side effect of me breaking append.

lorentey added a commit to lorentey/swift that referenced this pull request Dec 21, 2019
Data provides a settable `count` property. Its expected behavior is undocumented, but based on the implementation, it is intended to zero-extend (or truncate) the collection to the specified length.

This does not work correctly if we start with an empty Data and we try to increase the count by a small integer:

```
import Foundation

var d = Data()
d.count = 2
print(d.count) // ⟹ 0 ⁉️

d.count = 100
print(d.count) // ⟹ 100 ✓
```

It looks like this bug was introduced with the Data overhaul that shipped in Swift 5.

(This issue was uncovered by swiftlang#28918.)

rdar://58134026
@lorentey lorentey changed the title [Foundation] Imports shims with @implementationOnly [Foundation] Import shims with @implementationOnly Dec 21, 2019
@lorentey
Copy link
Member Author

The failure turned out to have been caused by a previously shipped regression (see #28919).

I'll merge the fix here to let me rerun the tests & benchmarks.

@lorentey
Copy link
Member Author

@swift-ci benchmark

@lorentey
Copy link
Member Author

@swift-ci test

@swiftlang swiftlang deleted a comment from swift-ci Dec 21, 2019
@swiftlang swiftlang deleted a comment from swift-ci Dec 21, 2019
@swift-ci
Copy link
Contributor

Performance: -O

Regression OLD NEW DELTA RATIO
ArrayAppendGenericStructs 590 1500 +154.2% 0.39x (?)
Dictionary4 156 204 +30.8% 0.76x
FlattenListFlatMap 4603 5967 +29.6% 0.77x (?)
String.data.Empty 20 25 +25.0% 0.80x (?)
String.data.Small 22 27 +22.7% 0.81x
Dictionary4OfObjects 199 237 +19.1% 0.84x (?)
DataCountSmall 13 15 +15.4% 0.87x
DataCountMedium 13 15 +15.4% 0.87x
String.data.LargeUnicode 59 66 +11.9% 0.89x (?)
String.data.Medium 56 61 +8.9% 0.92x (?)
 
Improvement OLD NEW DELTA RATIO
DataReplaceSmallBuffer 5500 2000 -63.6% 2.75x
DataReplaceMediumBuffer 6800 3000 -55.9% 2.27x
DataReplaceLargeBuffer 21 10 -52.4% 2.10x
Data.init.Sequence.64kB.Count.RE.I 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count.I 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count.RE 50 29 -42.0% 1.72x
Data.init.Sequence.513B.Count.I 116 69 -40.5% 1.68x
Data.init.Sequence.511B.Count.I 116 69 -40.5% 1.68x
Data.init.Sequence.809B.Count.I 92 56 -39.1% 1.64x
Data.init.Sequence.809B.Count.RE.I 98 60 -38.8% 1.63x
Data.init.Sequence.809B.Count 91 56 -38.5% 1.62x
Data.init.Sequence.809B.Count.RE 96 60 -37.5% 1.60x
Data.append.Sequence.809B.Count 104 69 -33.7% 1.51x
Data.append.Sequence.809B.Count.I 103 69 -33.0% 1.49x
DataAppendSequence 10700 7300 -31.8% 1.47x
Data.append.Sequence.809B.Count.RE.I 107 73 -31.8% 1.47x
Data.append.Sequence.809B.Count.RE 106 73 -31.1% 1.45x
Data.init.Sequence.2049B.Count.I 75 56 -25.3% 1.34x
Data.init.Sequence.2047B.Count.I 74 56 -24.3% 1.32x
Data.init.Sequence.511B.Count0.I 427 360 -15.7% 1.19x (?)
Data.init.Sequence.513B.Count0.I 427 360 -15.7% 1.19x
Data.init.Sequence.809B.Count0.I 398 351 -11.8% 1.13x
Data.init.Sequence.809B.Count0 398 352 -11.6% 1.13x (?)
Data.init.Sequence.809B.Count0.RE 409 368 -10.0% 1.11x
Data.init.Sequence.809B.Count0.RE.I 409 369 -9.8% 1.11x (?)
Data.append.Sequence.809B.Count0.RE 372 339 -8.9% 1.10x (?)
Data.append.Sequence.809B.Count0 359 330 -8.1% 1.09x (?)
Data.append.Sequence.809B.Count0.I 356 330 -7.3% 1.08x (?)

Code size: -O

Regression OLD NEW DELTA RATIO
ObjectiveCBridging.o 62391 63966 +2.5% 0.98x
 
Improvement OLD NEW DELTA RATIO
DataBenchmarks.o 79553 64984 -18.3% 1.22x

Performance: -Osize

Regression OLD NEW DELTA RATIO
String.data.Empty 20 25 +25.0% 0.80x
String.data.Small 23 27 +17.4% 0.85x
String.data.Medium 56 62 +10.7% 0.90x (?)
String.data.LargeUnicode 60 65 +8.3% 0.92x (?)
 
Improvement OLD NEW DELTA RATIO
DataReplaceSmallBuffer 5800 2000 -65.5% 2.90x
DataReplaceMediumBuffer 6800 3000 -55.9% 2.27x
DataReplaceLargeBuffer 21 10 -52.4% 2.10x
Data.init.Sequence.511B.Count.I 119 69 -42.0% 1.72x
Data.init.Sequence.64kB.Count.RE.I 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count.I 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count.RE 50 29 -42.0% 1.72x
Data.init.Sequence.513B.Count.I 121 71 -41.3% 1.70x
Data.init.Sequence.809B.Count.RE.I 98 60 -38.8% 1.63x
Data.init.Sequence.809B.Count.I 93 57 -38.7% 1.63x
Data.init.Sequence.809B.Count 92 57 -38.0% 1.61x
Data.init.Sequence.809B.Count.RE 96 60 -37.5% 1.60x
DataAppendSequence 10900 7300 -33.0% 1.49x
Data.append.Sequence.809B.Count 104 70 -32.7% 1.49x
Data.append.Sequence.809B.Count.RE.I 108 73 -32.4% 1.48x
Data.append.Sequence.809B.Count.I 103 70 -32.0% 1.47x
Data.append.Sequence.809B.Count.RE 106 73 -31.1% 1.45x
Data.init.Sequence.2047B.Count.I 77 58 -24.7% 1.33x
Data.init.Sequence.2049B.Count.I 77 58 -24.7% 1.33x
Dictionary4 211 166 -21.3% 1.27x
Data.init.Sequence.513B.Count0.I 421 358 -15.0% 1.18x (?)
Data.init.Sequence.511B.Count0.I 420 358 -14.8% 1.17x (?)
ObjectiveCBridgeStubDateAccess 152 130 -14.5% 1.17x
Data.init.Sequence.809B.Count0.RE 421 361 -14.3% 1.17x (?)
Data.init.Sequence.809B.Count0.RE.I 421 361 -14.3% 1.17x (?)
Data.init.Sequence.809B.Count0 401 348 -13.2% 1.15x (?)
Data.init.Sequence.809B.Count0.I 400 348 -13.0% 1.15x (?)
Data.append.Sequence.809B.Count0.RE 377 339 -10.1% 1.11x (?)
Data.append.Sequence.809B.Count0.RE.I 375 338 -9.9% 1.11x (?)
DataCreateEmptyArray 1650 1500 -9.1% 1.10x (?)

Code size: -Osize

Regression OLD NEW DELTA RATIO
ObjectiveCBridging.o 56259 57626 +2.4% 0.98x
 
Improvement OLD NEW DELTA RATIO
DataBenchmarks.o 67073 52823 -21.2% 1.27x

Performance: -Onone

Regression OLD NEW DELTA RATIO
StringToDataEmpty 600 900 +50.0% 0.67x
StringToDataSmall 700 950 +35.7% 0.74x
String.data.Empty 22 27 +22.7% 0.81x
String.data.Small 24 29 +20.8% 0.83x
StringToDataLargeUnicode 2650 2900 +9.4% 0.91x (?)
String.data.Medium 58 63 +8.6% 0.92x (?)
DataCreateEmptyArray 40750 44150 +8.3% 0.92x (?)
StringToDataMedium 2500 2700 +8.0% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
DataReplaceLargeBuffer 22 15 -31.8% 1.47x (?)

Code size: -swiftlibs

How to read the data The tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.

If you see any unexpected regressions, you should consider fixing the
regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false
alarms. Unexpected regressions which are marked with '(?)' are probably noise.
If you see regressions which you cannot explain you can try to run the
benchmarks again. If regressions still show up, please consult with the
performance team (@eeckstein).

Hardware Overview
  Model Name: Mac mini
  Model Identifier: Macmini8,1
  Processor Name: Intel Core i7
  Processor Speed: 3.2 GHz
  Number of Processors: 1
  Total Number of Cores: 6
  L2 Cache (per Core): 256 KB
  L3 Cache: 12 MB
  Memory: 64 GB

@lorentey
Copy link
Member Author

We got some additional (spurious-looking) benchmark regressions, but the results otherwise match the original run. 🎉

@natecook1000
Copy link
Member

🎉 This PR has been a real rollercoaster!

lorentey added a commit to lorentey/swift-corelibs-foundation that referenced this pull request Jan 9, 2020
Data provides a settable `count` property. Its expected behavior is undocumented, but based on the implementation, it is intended to zero-extend (or truncate) the collection to the specified length.

This does not work correctly if we start with an empty Data and we try to increase the count by a small integer:

```
import Foundation

var d = Data()
d.count = 2
print(d.count) // ⟹ 0 ⁉️

d.count = 100
print(d.count) // ⟹ 100 ✓
```

It looks like this bug was introduced with the Data overhaul that shipped in Swift 5.

(This issue was uncovered by swiftlang/swift#28918.)

rdar://58134026
Data.append now calls Data.count’s setter, which used to have a bug in previously shipped versions of the Foundation overlay (swiftlang#28918).

To prevent working code from breaking when recompiled with the current version, avoid calling Data.count’s setter directly. Instead, extract its implementation (conveniently already packaged into a nested function) into a named method, marking it @_alwaysEmitIntoClient.
@lorentey
Copy link
Member Author

lorentey commented Jan 9, 2020

@swift-ci test

@swift-ci

This comment has been minimized.

@swift-ci

This comment has been minimized.

@lorentey
Copy link
Member Author

lorentey commented Jan 9, 2020

@swift-ci please benchmark

@swift-ci
Copy link
Contributor

swift-ci commented Jan 9, 2020

Performance: -O

Regression OLD NEW DELTA RATIO
DataSetCountMedium 410 670 +63.4% 0.61x
String.data.Empty 19 25 +31.6% 0.76x (?)
String.data.Small 21 27 +28.6% 0.78x
DataCountSmall 13 15 +15.4% 0.87x
DataCountMedium 13 15 +15.4% 0.87x
String.data.Medium 54 60 +11.1% 0.90x (?)
String.data.LargeUnicode 61 67 +9.8% 0.91x (?)
 
Improvement OLD NEW DELTA RATIO
DataReplaceSmallBuffer 5500 2000 -63.6% 2.75x
DataReplaceMediumBuffer 6700 3000 -55.2% 2.23x
DataReplaceLargeBuffer 22 10 -54.5% 2.20x
Data.init.Sequence.511B.Count.I 116 66 -43.1% 1.76x
Data.init.Sequence.513B.Count.I 116 67 -42.2% 1.73x
Data.init.Sequence.64kB.Count.RE.I 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count.I 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count.RE 50 29 -42.0% 1.72x
Data.init.Sequence.809B.Count.I 92 55 -40.2% 1.67x
Data.init.Sequence.809B.Count 90 55 -38.9% 1.64x
Data.init.Sequence.809B.Count.RE 98 60 -38.8% 1.63x
Data.init.Sequence.809B.Count.RE.I 96 60 -37.5% 1.60x
DataSetCountSmall 80 52 -35.0% 1.54x
Data.append.Sequence.809B.Count 103 69 -33.0% 1.49x
Data.append.Sequence.809B.Count.I 103 71 -31.1% 1.45x
Data.append.Sequence.809B.Count.RE.I 108 75 -30.6% 1.44x
DataAppendSequence 10900 7700 -29.4% 1.42x
Data.append.Sequence.809B.Count.RE 106 75 -29.2% 1.41x
Data.init.Sequence.2047B.Count.I 75 55 -26.7% 1.36x
Data.init.Sequence.2049B.Count.I 75 55 -26.7% 1.36x
Data.init.Sequence.513B.Count0.I 430 359 -16.5% 1.20x
Data.init.Sequence.511B.Count0.I 430 360 -16.3% 1.19x
Data.init.Sequence.809B.Count0.I 402 351 -12.7% 1.15x
Data.init.Sequence.809B.Count0 401 351 -12.5% 1.14x
Data.append.Sequence.809B.Count0.I 364 320 -12.1% 1.14x
Data.append.Sequence.809B.Count0 363 320 -11.8% 1.13x
Data.init.Sequence.809B.Count0.RE.I 405 372 -8.1% 1.09x (?)
Data.init.Sequence.2047B.Count0.I 443 407 -8.1% 1.09x (?)
Data.append.Sequence.809B.Count0.RE 371 341 -8.1% 1.09x
Data.init.Sequence.809B.Count0.RE 403 371 -7.9% 1.09x (?)
Data.init.Sequence.2049B.Count0.I 442 408 -7.7% 1.08x (?)
Data.append.Sequence.809B.Count0.RE.I 365 341 -6.6% 1.07x (?)

Code size: -O

Regression OLD NEW DELTA RATIO
ObjectiveCBridging.o 62391 63966 +2.5% 0.98x
 
Improvement OLD NEW DELTA RATIO
DataBenchmarks.o 79553 67664 -14.9% 1.18x

Performance: -Osize

Regression OLD NEW DELTA RATIO
DataSetCountMedium 410 660 +61.0% 0.62x
Dictionary4 168 215 +28.0% 0.78x
String.data.Empty 20 25 +25.0% 0.80x
String.data.Small 22 27 +22.7% 0.81x
Set.subtracting.Empty.Box 7 8 +14.3% 0.88x (?)
DropFirstCountableRange 15 17 +13.3% 0.88x (?)
String.data.Medium 56 61 +8.9% 0.92x (?)
DataAccessBytesMedium 52 56 +7.7% 0.93x (?)
 
Improvement OLD NEW DELTA RATIO
DataReplaceSmallBuffer 5600 2000 -64.3% 2.80x
DataReplaceMediumBuffer 6600 3100 -53.0% 2.13x
DataReplaceLargeBuffer 21 10 -52.4% 2.10x
Data.init.Sequence.64kB.Count.RE.I 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count.I 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count 50 29 -42.0% 1.72x
Data.init.Sequence.64kB.Count.RE 50 29 -42.0% 1.72x
Data.init.Sequence.513B.Count.I 116 69 -40.5% 1.68x
Data.init.Sequence.511B.Count.I 115 69 -40.0% 1.67x
Data.init.Sequence.809B.Count 90 56 -37.8% 1.61x
Data.init.Sequence.809B.Count.RE 95 60 -36.8% 1.58x
Data.init.Sequence.809B.Count.RE.I 95 60 -36.8% 1.58x
Data.init.Sequence.809B.Count.I 90 57 -36.7% 1.58x
DataSetCountSmall 80 54 -32.5% 1.48x
Data.append.Sequence.809B.Count 103 70 -32.0% 1.47x
DataAppendSequence 11200 7700 -31.2% 1.45x
Data.append.Sequence.809B.Count.RE.I 107 75 -29.9% 1.43x
Data.append.Sequence.809B.Count.RE 108 76 -29.6% 1.42x
Data.append.Sequence.809B.Count.I 102 72 -29.4% 1.42x
Data.init.Sequence.2047B.Count.I 75 55 -26.7% 1.36x
Data.init.Sequence.2049B.Count.I 75 55 -26.7% 1.36x
Data.init.Sequence.513B.Count0.I 423 357 -15.6% 1.18x (?)
Data.init.Sequence.511B.Count0.I 422 357 -15.4% 1.18x (?)
ObjectiveCBridgeStubDateAccess 152 130 -14.5% 1.17x
Data.init.Sequence.809B.Count0.RE.I 417 360 -13.7% 1.16x (?)
Data.init.Sequence.809B.Count0.RE 416 362 -13.0% 1.15x (?)
DataCreateEmptyArray 1550 1350 -12.9% 1.15x
Data.append.Sequence.809B.Count0.RE.I 385 336 -12.7% 1.15x (?)
Data.init.Sequence.809B.Count0.I 397 347 -12.6% 1.14x
Data.init.Sequence.809B.Count0 396 348 -12.1% 1.14x (?)
Data.append.Sequence.809B.Count0.RE 382 337 -11.8% 1.13x (?)
Data.append.Sequence.809B.Count0.I 359 318 -11.4% 1.13x
Data.append.Sequence.809B.Count0 357 319 -10.6% 1.12x (?)
Data.init.Sequence.2047B.Count0.I 437 404 -7.6% 1.08x (?)
Data.init.Sequence.2049B.Count0.I 436 404 -7.3% 1.08x

Code size: -Osize

Regression OLD NEW DELTA RATIO
ObjectiveCBridging.o 56259 57626 +2.4% 0.98x
 
Improvement OLD NEW DELTA RATIO
DataBenchmarks.o 67073 54391 -18.9% 1.23x

Performance: -Onone

Regression OLD NEW DELTA RATIO
DataSetCountMedium 430 680 +58.1% 0.63x
StringToDataSmall 700 1000 +42.9% 0.70x
StringToDataEmpty 650 900 +38.5% 0.72x
String.data.Empty 21 27 +28.6% 0.78x
String.data.Small 23 29 +26.1% 0.79x
DataCountSmall 47 52 +10.6% 0.90x (?)
StringToDataMedium 2450 2700 +10.2% 0.91x (?)
StringToDataLargeUnicode 2650 2900 +9.4% 0.91x (?)
 
Improvement OLD NEW DELTA RATIO
DataReplaceLargeBuffer 22 15 -31.8% 1.47x (?)
DataSetCountSmall 106 80 -24.5% 1.32x
DataSubscriptMedium 58 54 -6.9% 1.07x (?)

Code size: -swiftlibs

How to read the data The tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.

If you see any unexpected regressions, you should consider fixing the
regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false
alarms. Unexpected regressions which are marked with '(?)' are probably noise.
If you see regressions which you cannot explain you can try to run the
benchmarks again. If regressions still show up, please consult with the
performance team (@eeckstein).

Hardware Overview
  Model Name: Mac mini
  Model Identifier: Macmini8,1
  Processor Name: Intel Core i7
  Processor Speed: 3.2 GHz
  Number of Processors: 1
  Total Number of Cores: 6
  L2 Cache (per Core): 256 KB
  L3 Cache: 12 MB
  Memory: 64 GB

lorentey added a commit to lorentey/swift-corelibs-foundation that referenced this pull request Jan 9, 2020
Data provides a settable `count` property. Its expected behavior is undocumented, but based on the implementation, it is intended to zero-extend (or truncate) the collection to the specified length.

This does not work correctly if we start with an empty Data and we try to increase the count by a small integer:

```
import Foundation

var d = Data()
d.count = 2
print(d.count) // ⟹ 0 ⁉️

d.count = 100
print(d.count) // ⟹ 100 ✓
```

It looks like this bug was introduced with the Data overhaul that shipped in Swift 5.

(This issue was uncovered by swiftlang/swift#28918.)

rdar://58134026
@lorentey lorentey requested a review from parkera January 14, 2020 01:01
@@ -62,6 +62,39 @@ internal func __NSDataIsCompact(_ data: NSData) -> Bool {

#endif

@_alwaysEmitIntoClient
internal func _withStackOrHeapBuffer(capacity: Int, _ body: (UnsafeMutableBufferPointer<UInt8>) -> Void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not mimic the C behavior that has a larger capacity first off and second off it is missing the jumbo capacity for the main thread (which has a larger stack allocation)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the benchmarks, what's the rationale for using a large buffer?

}
// The collection might still be able to provide direct access to typed memory.
// NOTE: It's safe to do this because we're already guarding on ByteCollection's element as `UInt8`. This would not be safe on arbitrary collections.
let replaced: Void? = newElements.withContiguousStorageIfAvailable { buffer in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Void? as a boolean? that seems almost UB territory no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit unusual, but the behavior is well-defined. Void is very much distinct from nil, so there is zero chance of a type system confusion.

I initially had this return a dummy boolean, but I felt it added irrelevant detail that obscured the intent of the code:

        let replaced: Bool? = newElements.withContiguousStorageIfAvailable { buffer in
             _representation.replaceSubrange(subrange, with: buffer.baseAddress, count: buffer.count)
             return true
         }
         guard replaced == nil else { return }

The withContiguousStorageIfAvailable API kind of forces this sort of weird control flow. If we were to design it now, I'd argue it should return a Result-like enum rather than an Optional -- but that's too late now.

@lorentey
Copy link
Member Author

@swift-ci test

@swift-ci

This comment has been minimized.

@swift-ci

This comment has been minimized.

Copy link
Contributor

@parkera parkera left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM pending resolution of the thread around the new alwaysEmitIntoClient code.

@lorentey
Copy link
Member Author

lorentey commented Apr 1, 2020

@swift-ci test and merge

@swift-ci swift-ci merged commit 026c3c9 into swiftlang:master Apr 1, 2020
@lorentey lorentey deleted the foundation-no-inlinable-shim-calls branch April 1, 2020 06:36
lorentey added a commit to lorentey/swift that referenced this pull request Apr 28, 2020
The current version of the Foundation overlay doesn’t use these, but we should still keep them in case a toolchain snapshot build picks up on overlay module from one of the SDKs in Xcode 11.

rdar://62339802
lorentey added a commit to lorentey/swift that referenced this pull request Apr 28, 2020
The current version of the Foundation overlay doesn’t use these, but we should still keep them in case a toolchain snapshot build picks up on overlay module from one of the SDKs in Xcode 11.

rdar://62339802
(cherry picked from commit 057b27b)
millenomi pushed a commit to swiftlang/swift-corelibs-foundation that referenced this pull request Nov 11, 2020
Data provides a settable `count` property. Its expected behavior is undocumented, but based on the implementation, it is intended to zero-extend (or truncate) the collection to the specified length.

This does not work correctly if we start with an empty Data and we try to increase the count by a small integer:

```
import Foundation

var d = Data()
d.count = 2
print(d.count) // ⟹ 0 ⁉️

d.count = 100
print(d.count) // ⟹ 100 ✓
```

It looks like this bug was introduced with the Data overhaul that shipped in Swift 5.

(This issue was uncovered by swiftlang/swift#28918.)

rdar://58134026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants