Skip to content

NSDictionary fix when key is a String rather than NSString. #1438

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
Feb 22, 2018

Conversation

johnno1962
Copy link
Contributor

Hi Apple,

Using a String as a key when setting a value in an NSDictionary causes a crash on Linux. This minor fix brings it into line with Darwin Foundation where this is possible.

Could not cast value of type 'Swift.AnyHashable' (0x1027b3b10) to 'SwiftFoundation.NSObject' (0x101a56668).
2018-02-16 14:30:46.355774+0000 TestFoundation[7306:8715333] Could not cast value of type 'Swift.AnyHashable' (0x1027b3b10) to 'SwiftFoundation.NSObject' (0x101a56668).
(lldb) up
frame #9: 0x000000010165b114 SwiftFoundation`NSMutableDictionary.subscript.setter(newValue=some, key=Swift.AnyHashable @ 0x00007fff5fbfcd88, self=0x000060800e181fe0) at NSDictionary.swift:649
   646 	        }
   647 	        set {
   648 	            if let val = newValue {
-> 649 	                setObject(val, forKey: key)
   650 	            } else {
   651 	                removeObject(forKey: key)
   652 	            }
(lldb) up
frame #10: 0x00000001004c0443 TestFoundation`static Dictionary.twEncode(data=TestFoundation.TwoWayMirror @ 0x00007fff5fbfce00, self=[Key : Value]) at TwoWayMirror.swift:386
   383 	            #if os(Linux)
   384 	            let key = NSString(string: key as! String)
   385 	            #endif
-> 386 	            dict[key] = TwoWayMirror.encode(mirror: &mirror)
   387 	        }
   388 	        return dict
   389 	    }
(lldb)

@spevans
Copy link
Contributor

spevans commented Feb 16, 2018

Can you add a unit test that would crash if this fix wasn't applied to catch it accidentally getting reverted in the future, thanks.

@spevans
Copy link
Contributor

spevans commented Feb 16, 2018

@swift-ci please test

@johnno1962 johnno1962 changed the title NSDictionary fix for when key is a String rather than NSString. NSDictionary fix when key is a String rather than NSString. Feb 16, 2018
@@ -586,7 +586,8 @@ open class NSMutableDictionary : NSDictionary {
guard type(of: self) === NSDictionary.self || type(of: self) === NSMutableDictionary.self else {
NSRequiresConcreteImplementation()
}
_storage[(aKey as! NSObject)] = _SwiftValue.store(anObject)
let aKey = (aKey as? NSObject) ?? NSString(string: aKey as! String)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do not special-case String/NSString here. Can you use _SwiftValue.store(aKey) instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, _SwiftValue.store is the way we are trying to work-around not having bridges and all bridged conversions should be written into the same funnel point

@millenomi
Copy link
Contributor

cc @phausler — any reason why we shouldn't use SwiftValue here that I'm not seeing?

@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

It looks like the test failure is unrelated.

@@ -222,6 +223,12 @@ class TestNSDictionary : XCTestCase {
}
}

func test_settingWithStringKey() {
let dict = NSDictionary()
Copy link
Contributor

@xwu xwu Feb 19, 2018

Choose a reason for hiding this comment

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

Don't you mean NSMutableDictionary()?

On macOS, the test code as given results in a compile-time error: error: cannot assign through subscript: subscript is get-only.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops. Thanks @xwu. Fixed and squashed.

…get the following crash:

Could not cast value of type 'Swift.AnyHashable' (0x1027b3b10) to 'SwiftFoundation.NSObject' (0x101a56668).
2018-02-16 14:30:46.355774+0000 TestFoundation[7306:8715333] Could not cast value of type 'Swift.AnyHashable' (0x1027b3b10) to 'SwiftFoundation.NSObject' (0x101a56668).
(lldb) up
frame swiftlang#9: 0x000000010165b114 SwiftFoundation`NSMutableDictionary.subscript.setter(newValue=some, key=Swift.AnyHashable @ 0x00007fff5fbfcd88, self=0x000060800e181fe0) at NSDictionary.swift:649
   646 	        }
   647 	        set {
   648 	            if let val = newValue {
-> 649 	                �[4ms�[0metObject(val, forKey: key)
   650 	            } else {
   651 	                removeObject(forKey: key)
   652 	            }
(lldb) up
frame swiftlang#10: 0x00000001004c0443 TestFoundation`static Dictionary.twEncode(data=TestFoundation.TwoWayMirror @ 0x00007fff5fbfce00, self=[Key : Value]) at TwoWayMirror.swift:386
   383 	            #if os(Linux)
   384 	            let key = NSString(string: key as! String)
   385 	            #endif
-> 386 	            dict[key] �[4m=�[0m TwoWayMirror.encode(mirror: &mirror)
   387 	        }
   388 	        return dict
   389 	    }
(lldb)
@ianpartridge
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

@swift-ci please test and merge

@ianpartridge
Copy link
Contributor

I think this is a candidate for backporting to the swift-4.1-branch branch. @johnno1962 what do you think?

@johnno1962
Copy link
Contributor Author

Absolutely! Can I leave that to you?

@johnno1962
Copy link
Contributor Author

Never mind, I’ve cherry picked a PR to 4.1-branch.

@millenomi
Copy link
Contributor

Hopefully we can get CI to move on this one.

@millenomi
Copy link
Contributor

@swift-ci please test and merge

@swift-ci swift-ci merged commit 0fd1ce6 into swiftlang:master Feb 22, 2018
@johnno1962
Copy link
Contributor Author

Thanks @millenomi, we got there in the end!

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.

7 participants