Skip to content
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

[SR-7284] NSSet/NSDictionary instances aren't always bridgeable to Swift #3726

Open
lorentey opened this issue Mar 27, 2018 · 4 comments
Open

Comments

@lorentey
Copy link
Member

Previous ID SR-7284
Radar rdar://problem/38922580
Original Reporter @lorentey
Type Bug
Environment

Apple Swift version 4.0 (swiftlang-900.0.65 clang-900.0.37)
Apple Swift version 4.1 (swiftlang-902.0.34 clang-902.0.30)
Swift version 4.2-dev (LLVM a481df9074, Clang 051a73f5bc, Swift 599b4bc952)

Additional Detail from JIRA
Votes 1
Component/s Foundation, Standard Library
Labels Bug
Assignee @lorentey
Priority Medium

md5: 3c6a82511a3c7c4552d6181c15f93ce9

Issue Description:

We currently assume that the elements of an NSSet (and the keys of an NSDictionary) are convertible to AnyHashable. Unfortunately, this is not necessarily the case – NSSets may contain elements of Swift types that aren't hashable:

import Foundation

struct NotHashable {
  let value: Int
}

let a = NotHashable(value: 42)
let set = NSSet(object: a as AnyObject)
let s1 = set as? Set<AnyHashable> // crashes
let s2 = set as AnyHashable       // crashes

4.2 stack trace for the Set<AnyHashable> crash:

0  swift                    0x000000010728a418 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1  swift                    0x000000010728ab26 SignalHandler(int) + 694
2  libsystem_platform.dylib 0x00007fff797e1d9a _sigtramp + 26
3  libsystem_platform.dylib 0x000000000000ffff _sigtramp + 2256724607
4  libswiftObjectiveC.dylib 0x000000010eb0bfab $SSo8NSObjectCs8Hashable10ObjectiveCsACP5_hash4intoys7_HasherVz_tFTW + 43
5  libswiftCore.dylib       0x000000010f3e2462 $Ss20_ConcreteHashableBoxV5_hash5_intoys7_HasherVz_tF + 18
6  libswiftCore.dylib       0x000000010f3e2629 $Ss20_ConcreteHashableBoxVyxGs04_AnybC0ssADP5_hash5_intoys7_HasherVz_tFTW + 9
7  libswiftCore.dylib       0x000000010f3e2f87 $Ss11AnyHashableVs0B0ssACP5_hash4intoys7_HasherVz_tFTW + 71
8  libswiftCore.dylib       0x000000010f3c5fcd $Ss17_VariantSetBufferO12nativeInsert_6forKeySb8inserted_x011memberAfterE0tx_xtF + 221
9  libswiftFoundation.dylib 0x000000010fdc09bf $Ss35_setBridgeFromObjectiveCConditionalys3SetVyq_GSgACyxGs8HashableRzsAGR_r0_lFACySo8NSObjectCGAeIRszsAGR_r0_lIetgo_Tp5 + 623
10 libswiftFoundation.dylib 0x000000010fdc02c1 $Ss3SetV10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo5NSSetC_AByxGSgztFZ + 113
11 libswiftFoundation.dylib 0x000000010fdc0e14 $Ss3SetVyxGs21_ObjectiveCBridgeable10FoundationsADP024_conditionallyBridgeFromB1C_6resultSb01_B5CTypeQz_xSgztFZTW + 20
12 libswiftCore.dylib       0x000000010f2b3a01 $Ss45_conditionallyBridgeFromObjectiveC_bridgeableyxSg01_D5CTypeQz_xmts01_D11CBridgeableRzlF + 65
13 libswiftCore.dylib       0x000000010c7c2110 $Ss45_conditionallyBridgeFromObjectiveC_bridgeableyxSg01_D5CTypeQz_xmts01_D11CBridgeableRzlF + 4249937744
14 swift                    0x00000001045ed00d llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) + 461
15 swift                    0x00000001045f0b31 llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 1313
16 swift                    0x0000000103b35367 swift::RunImmediately(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, swift::IRGenOptions&, swift::SILOptions const&) + 3639
17 swift                    0x0000000103af1a8b performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 15179
18 swift                    0x0000000103aecf2e swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3310
19 swift                    0x0000000103aa3a83 main + 2051
20 libdyld.dylib            0x00007fff795f0c91 start + 1

Trace for AnyHashable conversion:

0  swift                    0x000000010bbab418 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1  swift                    0x000000010bbabb26 SignalHandler(int) + 694
2  libsystem_platform.dylib 0x00007fff797e1d9a _sigtramp + 26
3  libsystem_platform.dylib 0x000000000000ffff _sigtramp + 2256724607
4  libswiftObjectiveC.dylib 0x000000011342cfab $SSo8NSObjectCs8Hashable10ObjectiveCsACP5_hash4intoys7_HasherVz_tFTW + 43
5  libswiftCore.dylib       0x0000000113d03462 $Ss20_ConcreteHashableBoxV5_hash5_intoys7_HasherVz_tF + 18
6  libswiftCore.dylib       0x0000000113d03629 $Ss20_ConcreteHashableBoxVyxGs04_AnybC0ssADP5_hash5_intoys7_HasherVz_tFTW + 9
7  libswiftCore.dylib       0x0000000113ed73b7 $Ss15_AnyHashableBoxP5_hash5_intoys7_HasherVz_tFTj + 7
8  libswiftFoundation.dylib 0x00000001147b2e05 $Ss3SetV10FoundationE26_forceBridgeFromObjectiveC_6resultySo5NSSetC_AByxGSgztFZyyp_Spy0F1C8ObjCBoolVGtXEfU0_s11AnyHashableV_Tg5TA + 309
9  libswiftFoundation.dylib 0x00000001146e1152 $SypSpy10ObjectiveC8ObjCBoolVGIgny_yXlADIyByy_TR + 66
10 CoreFoundation           0x00007fff4cc704a3 -[__NSSingleObjectSetI enumerateObjectsWithOptions:usingBlock:] + 99
11 libswiftFoundation.dylib 0x000000011474efc8 $Ss3SetV10FoundationE26_forceBridgeFromObjectiveC_6resultySo5NSSetC_AByxGSgztFZs11AnyHashableV_Tg5Tf4nnd_n + 424
12 libswiftFoundation.dylib 0x00000001146e1e8a $SSo5NSSetC10FoundationE20_toCustomAnyHashables0eF0VSgyF + 58
13 libswiftFoundation.dylib 0x00000001146e20c0 $SSo5NSSetCs35_HasCustomAnyHashableRepresentation10FoundationsACP03_tocdE0s0dE0VSgyFTW + 16
14 libswiftCore.dylib       0x0000000113d03977 $Ss11AnyHashableVyABxcs0B0RzlufC + 231
15 libswiftCore.dylib       0x0000000113d0470e $Ss21_convertToAnyHashableys0cD0Vxs0D0RzlF + 78
16 libswiftCore.dylib       0x00000001110e30fc $Ss21_convertToAnyHashableys0cD0Vxs0D0RzlF + 4248693308
17 swift                    0x0000000108f0e00d llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) + 461
18 swift                    0x0000000108f11b31 llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 1313
19 swift                    0x0000000108456367 swift::RunImmediately(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, swift::IRGenOptions&, swift::SILOptions const&) + 3639
20 swift                    0x0000000108412a8b performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 15179
21 swift                    0x000000010840df2e swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3310
22 swift                    0x00000001083c4a83 main + 2051
23 libdyld.dylib            0x00007fff795f0c91 start + 1
@lorentey
Copy link
Member Author

With the conditional Hashable conformances introduced in SE-0143, this issue also applies to NSArray and the values of an NSDictionary.

apple/swift#15382

@lorentey
Copy link
Member Author

What if we made all _SwiftValues convertible to AnyHashable? (They already are in a way, although only when Foundation is imported, and the resulting AnyHashable is broken.) If the original Swift value isn't Hashable, its AnyHashable representation could still use _SwiftValue identity for hashing – this wouldn't be very useful, but at least it wouldn't crash.

$ swift
Welcome to Apple Swift version 4.1 (swiftlang-902.0.34 clang-902.0.30). Type :help for assistance.
  1> struct NotHashable { let value: Int }
  2> let a = NotHashable(value: 42)
a: NotHashable = {
  value = 42
}
  3> let o = a as AnyObject
o: Swift.AnyObject = {
  instance_type = 0x0000000101700130
}
  4> o as? AnyHashable
$R0: AnyHashable? = nil
  5> import Foundation
  6> o as? AnyHashable
$R1: AnyHashable? = some {
  _box = {
    _baseHashable = {
      value = 42
    }
  }
  _usedCustomRepresentation = false
}
  7> (o as? AnyHashable)?.hashValue
Execution interrupted. Enter code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
Process 31806 stopped
* thread #&#8203;1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x2a)
    frame #&#8203;0: 0x00007fff78635e57 libobjc.A.dylib`objc_msgSend + 23
libobjc.A.dylib`objc_msgSend:
->  0x7fff78635e57 <+23>: andq   (%rdi), %r10
    0x7fff78635e5a <+26>: movq   %rsi, %r11
    0x7fff78635e5d <+29>: andl   0x18(%r10), %r11d
    0x7fff78635e61 <+33>: shlq   $0x4, %r11
Target 0: (repl_swift) stopped.
  8>  

@jckarter
Copy link
Member

Yeah, that's what we should do. If the value isn't the box isn't hashable, we should make a best effort by hashing the boxes.

@lorentey
Copy link
Member Author

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants