swift
Annotate Foundation overlay with __shared/__owned
#19143
Merged

Annotate Foundation overlay with __shared/__owned #19143

itaiferber
itaiferber6 years ago (edited 6 years ago)

What's in this pull request?
Annotates portions of the Foundation overlay with the appropriate __shared/__owned annotations following the patterns we use (resolving rdar://problem/34989766). I looked at every declared func and init within our overlay and annotated all methods as appropriate. ~~~A search of all stored vars shows no necessary changes AFAICT as we don't expose reference types from our Swift APIs.~~~ (Since var types cannot be annotated for ownership, there's nothing for us to do in the cases where vars should be __shared.)

Overall the changes mostly revolve around bridging:

  • We often copy() the passed NS type before holding onto it as a reference to preserve value semantics, and in those cases, the parameter should be __shared as we don't hold on to the original. (AFAIK, copy() should help enforce the right refcounting in the case where copy() returns self.)
  • In other cases, we create an NS type out of the Swift type via bridging (which copies as well) and hold on to the NS type

There are a few cases where init parameters go unused (such as in String.init?(contentsOf:)), and some cases around KeyPath where we appear to not store the given KeyPath but it actually ends up stored in a global table.

Annotate Foundation overlay with __shared/__owned
402457bd
itaiferber itaiferber requested a review from phausler phausler 6 years ago
itaiferber itaiferber requested a review from eeckstein eeckstein 6 years ago
itaiferber
itaiferber6 years ago

@swift-ci Please test macOS

itaiferber
itaiferber6 years ago

@swift-ci Please smoke test Linux

itaiferber
itaiferber6 years ago

@eeckstein As far as I'm aware, our actual static bridging functions (_forceBridgeFromObjectiveC, _conditionallyBridgeFromObjectiveC, and _unconditionallyBridgeFromObjectiveC) should not require annotations as:

  1. They're static funcs which have no local storage (or write out to inout-params)
  2. Since they call into the shared reference variants changed above, the default for funcs applies here — the params should not be owned

Is my understanding here correct?

jrose-apple
jrose-apple6 years ago

Sorry, why is this specific to reference types? cc @airspeedswift

itaiferber
itaiferber6 years ago

@jrose-apple Sorry, have I missed something here? Is this not inherently related to values which require reference counting?

jrose-apple
jrose-apple6 years ago

"Values which require reference counting" isn't quite the same as "reference types". String and Array and Data all require reference counting too, right?

itaiferber
itaiferber6 years ago

Ah, therein lies my misunderstanding about what was necessary here. I'll re-audit for those types as well.

itaiferber
itaiferber6 years ago

Closing for now.

itaiferber itaiferber closed this 6 years ago
swift-ci
swift-ci6 years ago

Build failed
Swift Test OS X Platform
Git Sha - 402457b

Apply annotations to further non-trivial types
9f042bc7
itaiferber
itaiferber6 years ago

Made another pass here to add annotations to cover other non-trivial types. Will be doing another pass to confirm there's nothing I missed.

itaiferber itaiferber reopened this 6 years ago
itaiferber
itaiferber6 years ago

@swift-ci Please test macOS

itaiferber
itaiferber6 years ago

@swift-ci Please smoke test Linux

swift-ci
swift-ci6 years ago

Build failed
Swift Test OS X Platform
Git Sha - 402457b

itaiferber
itaiferber6 years ago

@jrose-apple @eeckstein Do the changes here look correct? Does anything stand out as being out of place?

airspeedswift
airspeedswift commented on 2018-09-19
stdlib/public/SDK/Foundation/IndexPath.swift
157157 }
158158
159 mutating func append(contentsOf other: [Int]) {
159
mutating func append(contentsOf other: __owned [Int]) {
airspeedswift6 years ago

this probably isn't necessary since it's just [Int]

eeckstein6 years ago

No, Array of Int is not a trivial type, i.e. involves reference counting of the array buffer.

jrose-apple6 years ago

Right, but IndexPath doesn't gain anything by taking the array owned, since it's not going to be able to use that buffer for storage, and the type isn't generic.

eeckstein6 years ago

You are right, assuming that the case where self is empty and size of other > 2 is not the common case, it's better to pass other as guaranteed.
(I misread airspeedswift's comment: I though he meant that it's not worth annotating because of the parameter type).

jrose-apple
jrose-apple commented on 2018-09-11
jrose-apple6 years ago

Can you explain what the principles are for what is and isn't annotated? Since you're explicitly writing both __shared and __owned, I'd expect it to be

  • every (non-trivial) parameter
  • of all public/@usableFromInline functions and initializers

and perhaps some of the non-public stuff as optimization hints. But I see public functions where that hasn't been done, such as https://github.com/apple/swift/blob/9f042bc7c3452307b7929f5b76db5261b623d79a/stdlib/public/SDK/Foundation/Calendar.swift#L507.

stdlib/public/SDK/Foundation/Calendar.swift
107107 // MARK: Bridging
108108
109 fileprivate init(reference : NSCalendar) {
109
fileprivate init(reference : __shared NSCalendar) {
jrose-apple6 years ago

This one should be owned, no? Since you're immediately going to store it.

jrose-apple6 years ago

Although it's not a public entry point anyway, so it doesn't really matter.

itaiferber6 years ago

_MutableHandle makes a copy of the reference given to it so we never store the original — I've propagated __shared out to every init(reference:) which uses this, per @eeckstein's recommendation.

stdlib/public/SDK/Foundation/JSONEncoder.swift
962962 /// Initializes `self` by referencing the given dictionary container in the given encoder.
963963 fileprivate init(referencing encoder: _JSONEncoder,
964 key: CodingKey, convertedKey: CodingKey, wrapping dictionary: NSMutableDictionary) {
964
key: CodingKey, convertedKey: __shared CodingKey, wrapping dictionary: NSMutableDictionary) {
jrose-apple6 years ago

I don't see why only the one parameter changed here.

itaiferber6 years ago

This parameter is not stored; all others are. Based on your comments, it sounds to me like I've misunderstood something critical here. Let me start an email thread so we can sort this out.

stdlib/public/SDK/Foundation/Data.swift
11791179 /// - parameter options: Options for the read operation. Default value is `[]`.
11801180 /// - throws: An error in the Cocoa domain, if `url` cannot be read.
1181 public init(contentsOf url: URL, options: Data.ReadingOptions = []) throws {
1181
public init(contentsOf url: __shared URL, options: __shared Data.ReadingOptions = []) throws {
jrose-apple6 years ago

Data.ReadingOptions is an ObjC enum, right? So it shouldn't matter what ownership you use.

itaiferber6 years ago

Sure — some of the changes here were mechanical, so I can pull this one out. I'm surprised the compiler didn't produce a warning/error in this case.

jrose-apple6 years ago

We haven't really talked about what form that'll take yet, but yeah, that's a reasonable idea. (You wouldn't necessarily want to do it to everything that's trivial, because a new version of the library might make it non-trivial, but that's not going to happen to an @objc enum.)

itaiferber
itaiferber6 years ago

@jrose-apple Sure — based on the guidelines I was given, I went ahead and annotated every function parameter which deviated from the default rules that I understand are in place (__shared is assumed for all function parameters by default, __owned is assumed for all init parameters by default). Anything not annotated is meant to assume the default.

If it would be more helpful (or even necessary) to annotate all parameters regardless of the default, then I'm willing to go through and do that. Similarly, if I've misunderstood the guidelines (see rdar://problem/34989766 for discussion between between me and @eeckstein), happy to be corrected.

eeckstein
eeckstein approved these changes on 2018-09-19
eeckstein
eeckstein6 years ago

@itaiferber

If it would be more helpful (or even necessary) to annotate all parameters regardless of the default

No, that's not necessary

jrose-apple
jrose-apple6 years ago

I feel silly now. I didn't realize you were just annotating divergences from the default. Sorry for jumping in!

Remove unnecessary __shared annotations
832317c8
itaiferber
itaiferber6 years ago

@swift-ci Please test macOS

itaiferber
itaiferber6 years ago

@swift-ci Please smoke test Linux

swift-ci
swift-ci6 years ago

Build failed
Swift Test OS X Platform
Git Sha - 9f042bc

itaiferber
itaiferber6 years ago

Latest commit removes the unnecessary __shared annotations on Data.ReadingOptions and friends (which are Obj-C enums). If tests are green I'll merge.

itaiferber
itaiferber6 years ago

@jrose-apple No worries at all, BTW — thanks for taking the time to review! Thanks @eeckstein for the help, too.

itaiferber itaiferber merged a28c9d62 into master 6 years ago
itaiferber itaiferber deleted the foundation-overlay-owned-annotations branch 6 years ago

Login to write a write a comment.

Login via GitHub

Assignees
No one assigned
Labels
Milestone