Skip to content

NSNumber already preserves whether a value was originally boolean. #4366

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
merged 1 commit into from
Aug 18, 2016

Conversation

jrose-apple
Copy link
Contributor

Use that instead of rolling it up in _SwiftTypePreservingNSNumber so that we get the right behavior when we go to write plists.

https://bugs.swift.org/browse/SR-2381


Before merging this pull request to apple/swift repository:

  • Test pull request on Swift continuous integration.

Triggering Swift CI

The swift-ci is triggered by writing a comment on this PR addressed to the GitHub user @swift-ci. Different tests will run depending on the specific comment that you use. The currently available comments are:

Smoke Testing

Platform Comment
All supported platforms @swift-ci Please smoke test
All supported platforms @swift-ci Please smoke test and merge
OS X platform @swift-ci Please smoke test OS X platform
Linux platform @swift-ci Please smoke test Linux platform

A smoke test on macOS does the following:

  1. Builds the compiler incrementally.
  2. Builds the standard library only for macOS. Simulator standard libraries and
    device standard libraries are not built.
  3. lldb is not built.
  4. The test and validation-test targets are run only for macOS. The optimized
    version of these tests are not run.

A smoke test on Linux does the following:

  1. Builds the compiler incrementally.
  2. Builds the standard library incrementally.
  3. lldb is built incrementally.
  4. The swift test and validation-test targets are run. The optimized version of these
    tests are not run.
  5. lldb is tested.

Validation Testing

Platform Comment
All supported platforms @swift-ci Please test
All supported platforms @swift-ci Please test and merge
OS X platform @swift-ci Please test OS X platform
OS X platform @swift-ci Please benchmark
Linux platform @swift-ci Please test Linux platform

Lint Testing

Language Comment
Python @swift-ci Please Python lint

Note: Only members of the Apple organization can trigger swift-ci.

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test OS X platform

@jrose-apple
Copy link
Contributor Author

I wish @gribozavr were around to review this, but he's not. @DougGregor, what do you think about this instead of #4363?

@jrose-apple
Copy link
Contributor Author

and @phausler probably has good thoughts here as well.

result = ((_SwiftTypePreservingNSNumber *) self_)->tag;
} else if (CFGetTypeID(self_) == CFBooleanGetTypeID()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this probably should be a strcmp of self.objCType and @encode(BOOL)

Copy link
Contributor

Choose a reason for hiding this comment

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

assert(strcmp(@YES.objCType, @encode(BOOL)) == 0);

where as CFGetTypeID of a subclass of NSNumber may not return CFBooleanGetTypeID() unless _cfTypeID is overridden.

@phausler
Copy link
Contributor

a side-concern; doesn't _SwiftTypePreservingNSNumber destroy our optimizations for tagged pointers from Foundation?

@jrose-apple
Copy link
Contributor Author

It does for now. I figure if/when Swift and Foundation are revlocked we may be able to hardcode those as well.

The whole point of this type is to tell whether a particular value was originally a boolean. It's an awful compromise for when you have a Swift dictionary whose key is a particular number type, and then you bridge it to Objective-C and then back into a dictionary whose key is AnyHashable. The value types and NSNumber don't compare the same (is 42 equal to 42.0?) so the best answer we could come up with was to eagerly bridge back if the value originally came from Swift. We really don't want to be treating arbitrary signed chars as booleans, so looking at the objCType isn't good enough.

@phausler
Copy link
Contributor

So basically any subclasser in this case will not get proper behavior unless they override a private method then. (Granted the number of subclassers is likely not very often)

One other consideration (modulo subclasses like _SwiftTypePreservingNSNumber) NSNumber returns singletons even on 32 bit for boolean values.

Overall I think NSNumber expresses something quite different than the numeric primitives and we should consider removing the bridge for it. Per the comparison; is that via - (NSComparisonResult)compare:(NSNumber *)otherNumber;? if so that would be a bug imho.

assert([[NSNumber numberWithDouble:42.0] compare:@42] == NSOrderedSame); // passes

@jrose-apple
Copy link
Contributor Author

Right, we don't want 42 and 42.0 to have to represent the same dictionary key. (They shouldn't have to hash the same or be considered equal.) I think it's acceptable to say that we don't expect custom subclasses to provide custom booleans, since that's what _SwiftTypePreservingNSNumber was doing and it didn't work anyway.

At this point I think it's too late to remove NSNumber bridging for Swift 3, and the reason we've always shied away from that is the very thing that prompted this change: plists. (Which also don't follow objCType when printing, at least not on Apple platforms, because NSNumber isn't using C's boolean type.)

@DougGregor
Copy link
Member

I suggest that you pick up the tests and 'expectedObjCType' test fixes from #4363; otherwise, LGTM with the strcmp of the objcType against @encode(BOOL).

@jrose-apple
Copy link
Contributor Author

I had left that out because the new logic isn't ours; it's CF's. I guess calling CFGetTypeID doesn't guarantee that, though.

Use that instead of rolling it up in _SwiftTypePreservingNSNumber so that we
get the right behavior when we go to write plists.

https://bugs.swift.org/browse/SR-2381
@jrose-apple
Copy link
Contributor Author

@swift-ci Please test OS X platform

@jckarter
Copy link
Contributor

I don't think we'd want to ever remove NSNumber bridging; we get a lot of requests from users to extend it to the other number types beyond just Bool, Int, UInt, and Double.

@DougGregor
Copy link
Member

@swift-ci Please test OSX platform

@DougGregor
Copy link
Member

DougGregor commented Aug 18, 2016

@swift-ci Please test macOS platform

@DougGregor
Copy link
Member

... it's not triggering ...

@swift-ci Please test macOS

@jrose-apple
Copy link
Contributor Author

:-( It was working, just not updating GitHub. Mishal's been investigating that. The actual test is still going; I'll kill your other ones.

@jrose-apple jrose-apple merged commit ba3de9e into swiftlang:master Aug 18, 2016
@jrose-apple jrose-apple deleted the CFBoolean branch August 18, 2016 22:45
jrose-apple added a commit to jrose-apple/swift that referenced this pull request Aug 18, 2016
…wiftlang#4366)

Use that instead of rolling it up in _SwiftTypePreservingNSNumber so that we
get the right behavior when we go to write plists.

https://bugs.swift.org/browse/SR-2381
(cherry picked from commit ba3de9e)
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.

4 participants