apple / swift-collections

Commonly used data structures for Swift
Apache License 2.0
3.77k stars 296 forks source link

`OrderedSet.update(_:at:)` naming #171

Closed shadyelmaadawy closed 1 year ago

shadyelmaadawy commented 2 years ago

when calling the update function in an ordered set, the application get crashes.

    // A code work without a problem
    var data = OrderedSet(["id0", "id1"]) 
    data.update("id0", at: 0) // what is the idea to update element with same value? 
    // A code lead to crash
    var data = OrderedSet(["id0", "id1"])
    data.update("bla", at: 0)
Click to expand crash report Full Report ------------------------------------- Translated Report (Full Report Below) ------------------------------------- Incident Identifier: 64E09DB1-54A0-49C2-8CB3-7763DE7603D3 CrashReporter Key: 57D363D4-8EA7-3301-7C86-FBDCC8956CD6 Hardware Model: MacBookPro16,1 Process: asdasdasdasd [3446] Path: /Users/USER/Library/Developer/CoreSimulator/Devices/FECA0831-B583-4273-B0FE-573FB0B2E82C/data/Containers/Bundle/Application/2D524AB7-E62B-4BB9-AD9E-077A2C127C14/asdasdasdasd.app/asdasdasdasd Identifier: test.asdasdasdasd Version: 1.0 (1) Code Type: X86-64 (Native) Role: Foreground Parent Process: launchd_sim [1864] Coalition: com.apple.CoreSimulator.SimDevice.FECA0831-B583-4273-B0FE-573FB0B2E82C [1227] Responsible Process: SimulatorTrampoline [646] Date/Time: 2022-09-02 14:09:39.6781 +0200 Launch Time: 2022-09-02 14:09:36.6389 +0200 OS Version: macOS 12.4 (21F79) Release Type: User Report Version: 104 Exception Type: EXC_BAD_INSTRUCTION (SIGILL) Exception Codes: 0x0000000000000001, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: SIGNAL 4 Illegal instruction: 4 Terminating Process: exc handler [3446] Triggered by Thread: 0 Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 asdasdasdasd 0x10d0415b4 Swift runtime failure: precondition failure + 0 [inlined] 1 asdasdasdasd 0x10d0415b4 $ss14_stringCompare__9expectingSbs11_StringGutsV_ADs01_D16ComparisonResultOtF + 0 [inlined] 2 asdasdasdasd 0x10d0415b4 $sSS2eeoiySbSS_SStFZ + 0 [inlined] 3 asdasdasdasd 0x10d0415b4 $sSSSQsSQ2eeoiySbx_xtFZTW + 0 [inlined] 4 asdasdasdasd 0x10d0415b4 specialized OrderedSet.update(_:at:) + 228 5 asdasdasdasd 0x10d04142a ViewController.removeRandomClicked(_:) + 74 (ViewController.swift:56) 6 asdasdasdasd 0x10d0415fa @objc ViewController.removeRandomClicked(_:) + 58 7 UIKitCore 0x7fff250a49d3 -[UIApplication sendAction:to:from:forEvent:] + 83 8 UIKitCore 0x7fff24933354 -[UIControl sendAction:to:forEvent:] + 110 9 UIKitCore 0x7fff24933758 -[UIControl _sendActionsForEvents:withEvent:] + 345 10 UIKitCore 0x7fff2492fc3b -[UIButton _sendActionsForEvents:withEvent:] + 148 11 UIKitCore 0x7fff24931faf -[UIControl touchesEnded:withEvent:] + 485 12 UIKitCore 0x7fff250e5dd6 -[UIWindow _sendTouchesForEvent:] + 1292 13 UIKitCore 0x7fff250e7e3a -[UIWindow sendEvent:] + 5312 14 UIKitCore 0x7fff250bdeac -[UIApplication sendEvent:] + 820 15 UIKitCore 0x7fff25155f0a __dispatchPreprocessedEventFromEventQueue + 5614 16 UIKitCore 0x7fff2515935d __processEventQueue + 8635 17 UIKitCore 0x7fff2514faf5 __eventFetcherSourceCallback + 232 18 CoreFoundation 0x7fff203724a7 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 19 CoreFoundation 0x7fff2037239f __CFRunLoopDoSource0 + 180 20 CoreFoundation 0x7fff2037186c __CFRunLoopDoSources0 + 242 21 CoreFoundation 0x7fff2036bf68 __CFRunLoopRun + 871 22 CoreFoundation 0x7fff2036b704 CFRunLoopRunSpecific + 562 23 GraphicsServices 0x7fff2cba9c8e GSEventRunModal + 139 24 UIKitCore 0x7fff2509e65a -[UIApplication _run] + 928 25 UIKitCore 0x7fff250a32b5 UIApplicationMain + 101 26 libswiftUIKit.dylib 0x7fff59d55cc2 UIApplicationMain(_:_:_:_:) + 98 27 asdasdasdasd 0x10d041db5 $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ12asdasdasdasd03AppB0C_Tg5 + 80 [inlined] 28 asdasdasdasd 0x10d041db5 $s12asdasdasdasd11AppDelegateC5$mainyyFZ + 97 (:10) [inlined] 29 asdasdasdasd 0x10d041db5 main + 101 30 dyld_sim 0x10d34df21 start_sim + 10 31 dyld 0x1178f251e start + 462 Thread 1: 0 libsystem_pthread.dylib 0x7fff701c6f48 start_wqthread + 0 Thread 2: 0 libsystem_pthread.dylib 0x7fff701c6f48 start_wqthread + 0 Thread 3: 0 libsystem_pthread.dylib 0x7fff701c6f48 start_wqthread + 0 Thread 4:: com.apple.uikit.eventfetch-thread 0 libsystem_kernel.dylib 0x7fff7016c97a mach_msg_trap + 10 1 libsystem_kernel.dylib 0x7fff7016cce8 mach_msg + 56 2 CoreFoundation 0x7fff20371acc __CFRunLoopServiceMachPort + 319 3 CoreFoundation 0x7fff2036c0e2 __CFRunLoopRun + 1249 4 CoreFoundation 0x7fff2036b704 CFRunLoopRunSpecific + 562 5 Foundation 0x7fff20828049 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 213 6 Foundation 0x7fff208282c2 -[NSRunLoop(NSRunLoop) runUntilDate:] + 72 7 UIKitCore 0x7fff25161bda -[UIEventFetcher threadMain] + 491 8 Foundation 0x7fff208511a1 __NSThread__start__ + 1009 9 libsystem_pthread.dylib 0x7fff701cb4e1 _pthread_start + 125 10 libsystem_pthread.dylib 0x7fff701c6f6b thread_start + 15 Thread 5: 0 libsystem_pthread.dylib 0x7fff701c6f48 start_wqthread + 0 Thread 6: 0 libsystem_pthread.dylib 0x7fff701c6f48 start_wqthread + 0 Thread 7: 0 libsystem_pthread.dylib 0x7fff701c6f48 start_wqthread + 0 Thread 0 crashed with X86 Thread State (64-bit): rax: 0x1cffffffffffff00 rbx: 0x00007fa771800000 rcx: 0xe300000000000000 rdx: 0x6964300000000000 rdi: 0x0000000000007831 rsi: 0xe200000000000000 rbp: 0x00007ff7b2ebb750 rsp: 0x00007ff7b2ebb700 r8: 0x0000000000000000 r9: 0x6000000000000000 r10: 0x00007fff867cabe0 r11: 0x00007fff2567402a r12: 0x0000000000000000 r13: 0x0000000000000000 r14: 0xe300000000000000 r15: 0x0000000000007831 rip: 0x000000010d0415b4 rfl: 0x0000000000010246 cr2: 0x00007fff254eb7e3 Logical CPU: 4 Error Code: 0x00000000 Trap Number: 6 Binary Images: 0x10d040000 - 0x10d083fff test.asdasdasdasd (1.0) <750185ab-13f9-3929-9abd-d7f32fd899bb> /Users/USER/Library/Developer/CoreSimulator/Devices/FECA0831-B583-4273-B0FE-573FB0B2E82C/data/Containers/Bundle/Application/2D524AB7-E62B-4BB9-AD9E-077A2C127C14/asdasdasdasd.app/asdasdasdasd 0x7fff243c3000 - 0x7fff25980fff com.apple.UIKitCore (1.0) /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 0x7fff202f0000 - 0x7fff20693fff com.apple.CoreFoundation (6.9) /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation 0x7fff2cba6000 - 0x7fff2cbaefff com.apple.GraphicsServices (1.0) /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices 0x7fff59d34000 - 0x7fff59d94fff libswiftUIKit.dylib (*) <28ff8409-7f90-3a2f-83c0-102b7f12b539> /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/libswiftUIKit.dylib 0x10d34c000 - 0x10d399fff dyld_sim (*) <7276a69b-e3b9-3f23-957f-061350a501b4> /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim 0x1178ed000 - 0x117958fff dyld (*) /usr/lib/dyld 0x7fff701c5000 - 0x7fff701d0fff libsystem_pthread.dylib (*) /usr/lib/system/libsystem_pthread.dylib 0x7fff7016b000 - 0x7fff701a2fff libsystem_kernel.dylib (*) <61711d11-e776-3bc3-b9a2-6f9f37cb8499> /usr/lib/system/libsystem_kernel.dylib 0x7fff20704000 - 0x7fff209bdfff com.apple.Foundation (6.9) <9827fa7d-2500-32d7-aaaf-288e38b126ab> /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation EOF ----------- Full Report ----------- {"app_name":"asdasdasdasd","timestamp":"2022-09-02 14:09:40.00 +0200","app_version":"1.0","slice_uuid":"750185ab-13f9-3929-9abd-d7f32fd899bb","build_version":"1","platform":7,"bundleID":"test.asdasdasdasd","share_with_app_devs":0,"is_first_party":0,"bug_type":"309","os_version":"macOS 12.4 (21F79)","incident_id":"64E09DB1-54A0-49C2-8CB3-7763DE7603D3","name":"asdasdasdasd"} { "uptime" : 6200, "procLaunch" : "2022-09-02 14:09:36.6389 +0200", "procRole" : "Foreground", "version" : 2, "userID" : 501, "deployVersion" : 210, "modelCode" : "MacBookPro16,1", "procStartAbsTime" : 6222601131138, "coalitionID" : 1227, "osVersion" : { "train" : "macOS 12.4", "build" : "21F79", "releaseType" : "User" }, "captureTime" : "2022-09-02 14:09:39.6781 +0200", "incident" : "64E09DB1-54A0-49C2-8CB3-7763DE7603D3", "bug_type" : "309", "pid" : 3446, "procExitAbsTime" : 6225639144792, "cpuType" : "X86-64", "procName" : "asdasdasdasd", "procPath" : "\/Users\/USER\/Library\/Developer\/CoreSimulator\/Devices\/FECA0831-B583-4273-B0FE-573FB0B2E82C\/data\/Containers\/Bundle\/Application\/2D524AB7-E62B-4BB9-AD9E-077A2C127C14\/asdasdasdasd.app\/asdasdasdasd", "bundleInfo" : {"CFBundleShortVersionString":"1.0","CFBundleVersion":"1","CFBundleIdentifier":"test.asdasdasdasd"}, "storeInfo" : {"deviceIdentifierForVendor":"0FE5D930-62CD-5C81-9EA7-D5190C0C7948","thirdParty":true}, "parentProc" : "launchd_sim", "parentPid" : 1864, "coalitionName" : "com.apple.CoreSimulator.SimDevice.FECA0831-B583-4273-B0FE-573FB0B2E82C", "crashReporterKey" : "57D363D4-8EA7-3301-7C86-FBDCC8956CD6", "responsiblePid" : 646, "responsibleProc" : "SimulatorTrampoline", "sip" : "enabled", "isCorpse" : 1, "exception" : {"codes":"0x0000000000000001, 0x0000000000000000","rawCodes":[1,0],"type":"EXC_BAD_INSTRUCTION","signal":"SIGILL"}, "termination" : {"flags":0,"code":4,"namespace":"SIGNAL","indicator":"Illegal instruction: 4","byProc":"exc handler","byPid":3446}, "extMods" : {"caller":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"system":{"thread_create":0,"thread_set_state":0,"task_for_pid":2},"targeted":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"warnings":0}, "faultingThread" : 0, "threads" : [{"triggered":true,"id":94544,"instructionState":{"instructionStream":{"bytes":[132,192,117,11,72,137,223,232,64,23,0,0,72,137,195,76,57,99,16,126,73,78,139,100,43,40,76,139,125,208,76,137,255,232,196,145,3,0,76,137,231,232,182,145,3,0,72,139,69,192,74,137,68,43,32,78,137,124,43,40,72,139,69,184,72,137,88,8,72,139,69,200,76,137,242,72,131,196,40,91,65,92,65,93,65,94,65,95,93,195,15,11,15,11,15,11,15,11,102,46,15,31,132,0,0,0,0,0,85,72,137,229,65,87,65,86,65,85,83,72,131,236,32,72,137,211,73,137,253,255,21,13,57,4,0,73,137,198,72,137,223,232,12,146,3,0,76,141,125,192,76,137,248,72,137,223,232,227,141,3,0,232,230,253,255,255,76,137,255,232,238,25,0,0,76,137,247,255,21,213,56,4,0,72,137,223,232,217,145,3,0,72],"offset":96}},"threadState":{"r13":{"value":0},"rax":{"value":2089670227099909888},"rflags":{"value":66118},"cpu":{"value":4},"r14":{"value":16357073846609641472},"rsi":{"value":16285016252571713536},"r8":{"value":0},"cr2":{"value":140733819303907},"rdx":{"value":7594247648211632128},"r10":{"value":140735449705440,"symbolLocation":0,"symbol":"OBJC_CLASS_$_UIButton"},"r9":{"value":6917529027641081856},"r15":{"value":30769},"rbx":{"value":140357140480000},"trap":{"value":6},"err":{"value":0},"r11":{"value":140733820911658,"symbolLocation":0,"symbol":"-[UIView(UIKitManual) retain]"},"rip":{"value":4513338804,"matchesCrashFrame":1},"rbp":{"value":140701835442000},"rsp":{"value":140701835441920},"r12":{"value":0},"rcx":{"value":16357073846609641472},"flavor":"x86_THREAD_STATE","rdi":{"value":30769}},"queue":"com.apple.main-thread","frames":[{"imageOffset":5556,"sourceFile":"","symbol":"Swift runtime failure: precondition failure","imageIndex":0,"symbolLocation":0,"inline":true},{"imageOffset":5556,"sourceFile":"","symbol":"$ss14_stringCompare__9expectingSbs11_StringGutsV_ADs01_D16ComparisonResultOtF","imageIndex":0,"symbolLocation":0,"inline":true},{"imageOffset":5556,"sourceFile":"","symbol":"$sSS2eeoiySbSS_SStFZ","imageIndex":0,"symbolLocation":0,"inline":true},{"imageOffset":5556,"sourceFile":"","symbol":"$sSSSQsSQ2eeoiySbx_xtFZTW","imageIndex":0,"symbolLocation":0,"inline":true},{"imageOffset":5556,"sourceFile":"","symbol":"specialized OrderedSet.update(_:at:)","symbolLocation":228,"imageIndex":0},{"imageOffset":5162,"sourceLine":56,"sourceFile":"ViewController.swift","symbol":"ViewController.removeRandomClicked(_:)","imageIndex":0,"symbolLocation":74},{"imageOffset":5626,"sourceFile":"","symbol":"@objc ViewController.removeRandomClicked(_:)","symbolLocation":58,"imageIndex":0},{"imageOffset":13507027,"symbol":"-[UIApplication sendAction:to:from:forEvent:]","symbolLocation":83,"imageIndex":1},{"imageOffset":5702484,"symbol":"-[UIControl sendAction:to:forEvent:]","symbolLocation":110,"imageIndex":1},{"imageOffset":5703512,"symbol":"-[UIControl _sendActionsForEvents:withEvent:]","symbolLocation":345,"imageIndex":1},{"imageOffset":5688379,"symbol":"-[UIButton _sendActionsForEvents:withEvent:]","symbolLocation":148,"imageIndex":1},{"imageOffset":5697455,"symbol":"-[UIControl touchesEnded:withEvent:]","symbolLocation":485,"imageIndex":1},{"imageOffset":13774294,"symbol":"-[UIWindow _sendTouchesForEvent:]","symbolLocation":1292,"imageIndex":1},{"imageOffset":13782586,"symbol":"-[UIWindow sendEvent:]","symbolLocation":5312,"imageIndex":1},{"imageOffset":13610668,"symbol":"-[UIApplication sendEvent:]","symbolLocation":820,"imageIndex":1},{"imageOffset":14233354,"symbol":"__dispatchPreprocessedEventFromEventQueue","symbolLocation":5614,"imageIndex":1},{"imageOffset":14246749,"symbol":"__processEventQueue","symbolLocation":8635,"imageIndex":1},{"imageOffset":14207733,"symbol":"__eventFetcherSourceCallback","symbolLocation":232,"imageIndex":1},{"imageOffset":533671,"symbol":"__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__","symbolLocation":17,"imageIndex":2},{"imageOffset":533407,"symbol":"__CFRunLoopDoSource0","symbolLocation":180,"imageIndex":2},{"imageOffset":530540,"symbol":"__CFRunLoopDoSources0","symbolLocation":242,"imageIndex":2},{"imageOffset":507752,"symbol":"__CFRunLoopRun","symbolLocation":871,"imageIndex":2},{"imageOffset":505604,"symbol":"CFRunLoopRunSpecific","symbolLocation":562,"imageIndex":2},{"imageOffset":15502,"symbol":"GSEventRunModal","symbolLocation":139,"imageIndex":3},{"imageOffset":13481562,"symbol":"-[UIApplication _run]","symbolLocation":928,"imageIndex":1},{"imageOffset":13501109,"symbol":"UIApplicationMain","symbolLocation":101,"imageIndex":1},{"imageOffset":138434,"symbol":"UIApplicationMain(_:_:_:_:)","symbolLocation":98,"imageIndex":4},{"imageOffset":7605,"sourceFile":"ViewController.swift","symbol":"$sSo21UIApplicationDelegateP5UIKitE4mainyyFZ12asdasdasdasd03AppB0C_Tg5","imageIndex":0,"symbolLocation":80,"inline":true},{"symbol":"$s12asdasdasdasd11AppDelegateC5$mainyyFZ","inline":true,"imageIndex":0,"imageOffset":7605,"symbolLocation":97,"sourceLine":10,"sourceFile":""},{"imageOffset":7605,"sourceFile":"ViewController.swift","symbol":"main","symbolLocation":101,"imageIndex":0},{"imageOffset":7969,"symbol":"start_sim","symbolLocation":10,"imageIndex":5},{"imageOffset":21790,"symbol":"start","symbolLocation":462,"imageIndex":6}]},{"id":94589,"frames":[{"imageOffset":8008,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":7}]},{"id":94590,"frames":[{"imageOffset":8008,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":7}]},{"id":94591,"frames":[{"imageOffset":8008,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":7}]},{"id":94593,"name":"com.apple.uikit.eventfetch-thread","frames":[{"imageOffset":6522,"symbol":"mach_msg_trap","symbolLocation":10,"imageIndex":8},{"imageOffset":7400,"symbol":"mach_msg","symbolLocation":56,"imageIndex":8},{"imageOffset":531148,"symbol":"__CFRunLoopServiceMachPort","symbolLocation":319,"imageIndex":2},{"imageOffset":508130,"symbol":"__CFRunLoopRun","symbolLocation":1249,"imageIndex":2},{"imageOffset":505604,"symbol":"CFRunLoopRunSpecific","symbolLocation":562,"imageIndex":2},{"imageOffset":1196105,"symbol":"-[NSRunLoop(NSRunLoop) runMode:beforeDate:]","symbolLocation":213,"imageIndex":9},{"imageOffset":1196738,"symbol":"-[NSRunLoop(NSRunLoop) runUntilDate:]","symbolLocation":72,"imageIndex":9},{"imageOffset":14281690,"symbol":"-[UIEventFetcher threadMain]","symbolLocation":491,"imageIndex":1},{"imageOffset":1364385,"symbol":"__NSThread__start__","symbolLocation":1009,"imageIndex":9},{"imageOffset":25825,"symbol":"_pthread_start","symbolLocation":125,"imageIndex":7},{"imageOffset":8043,"symbol":"thread_start","symbolLocation":15,"imageIndex":7}]},{"id":94594,"frames":[{"imageOffset":8008,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":7}]},{"id":94595,"frames":[{"imageOffset":8008,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":7}]},{"id":94596,"frames":[{"imageOffset":8008,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":7}]}], "usedImages" : [ { "source" : "P", "arch" : "x86_64", "base" : 4513333248, "CFBundleShortVersionString" : "1.0", "CFBundleIdentifier" : "test.asdasdasdasd", "size" : 278528, "uuid" : "750185ab-13f9-3929-9abd-d7f32fd899bb", "path" : "\/Users\/USER\/Library\/Developer\/CoreSimulator\/Devices\/FECA0831-B583-4273-B0FE-573FB0B2E82C\/data\/Containers\/Bundle\/Application\/2D524AB7-E62B-4BB9-AD9E-077A2C127C14\/asdasdasdasd.app\/asdasdasdasd", "name" : "asdasdasdasd", "CFBundleVersion" : "1" }, { "source" : "P", "arch" : "x86_64", "base" : 140733801312256, "CFBundleShortVersionString" : "1.0", "CFBundleIdentifier" : "com.apple.UIKitCore", "size" : 22798336, "uuid" : "f710b655-42ee-3939-a3bd-6da0f3758758", "path" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot\/System\/Library\/PrivateFrameworks\/UIKitCore.framework\/UIKitCore", "name" : "UIKitCore", "CFBundleVersion" : "5612" }, { "source" : "P", "arch" : "x86_64", "base" : 140733733339136, "CFBundleShortVersionString" : "6.9", "CFBundleIdentifier" : "com.apple.CoreFoundation", "size" : 3817472, "uuid" : "d7b873d0-2d44-362d-a632-91b54d2dd8c2", "path" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot\/System\/Library\/Frameworks\/CoreFoundation.framework\/CoreFoundation", "name" : "CoreFoundation", "CFBundleVersion" : "1863" }, { "source" : "P", "arch" : "x86_64", "base" : 140733943799808, "CFBundleShortVersionString" : "1.0", "CFBundleIdentifier" : "com.apple.GraphicsServices", "size" : 36864, "uuid" : "d645c3c0-b4f8-31d0-bada-02aea61681d5", "path" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot\/System\/Library\/PrivateFrameworks\/GraphicsServices.framework\/GraphicsServices", "name" : "GraphicsServices", "CFBundleVersion" : "1.0" }, { "source" : "P", "arch" : "x86_64", "base" : 140734700404736, "size" : 397312, "uuid" : "28ff8409-7f90-3a2f-83c0-102b7f12b539", "path" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot\/usr\/lib\/swift\/libswiftUIKit.dylib", "name" : "libswiftUIKit.dylib" }, { "source" : "P", "arch" : "x86_64", "base" : 4516528128, "size" : 319488, "uuid" : "7276a69b-e3b9-3f23-957f-061350a501b4", "path" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot\/usr\/lib\/dyld_sim", "name" : "dyld_sim" }, { "source" : "P", "arch" : "x86_64", "base" : 4690202624, "size" : 442368, "uuid" : "b70ce1ec-b902-3852-8268-05de00bfa8d5", "path" : "\/usr\/lib\/dyld", "name" : "dyld" }, { "source" : "P", "arch" : "x86_64", "base" : 140735074291712, "size" : 49152, "uuid" : "bc574849-1aae-31e7-b350-916dda999d97", "path" : "\/usr\/lib\/system\/libsystem_pthread.dylib", "name" : "libsystem_pthread.dylib" }, { "source" : "P", "arch" : "x86_64", "base" : 140735073923072, "size" : 229376, "uuid" : "61711d11-e776-3bc3-b9a2-6f9f37cb8499", "path" : "\/usr\/lib\/system\/libsystem_kernel.dylib", "name" : "libsystem_kernel.dylib" }, { "source" : "P", "arch" : "x86_64", "base" : 140733737615360, "CFBundleShortVersionString" : "6.9", "CFBundleIdentifier" : "com.apple.Foundation", "size" : 2859008, "uuid" : "9827fa7d-2500-32d7-aaaf-288e38b126ab", "path" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot\/System\/Library\/Frameworks\/Foundation.framework\/Foundation", "name" : "Foundation", "CFBundleVersion" : "1863" } ], "sharedCache" : { "base" : 140733730258944, "size" : 3268706304, "uuid" : "2adedbd1-352c-30c5-aa33-bb7bfa762f74" }, "vmSummary" : "ReadOnly portion of Libraries: Total=854.5M resident=0K(0%) swapped_out_or_unallocated=854.5M(100%)\nWritable regions: Total=615.6M written=0K(0%) resident=0K(0%) swapped_out=0K(0%) unallocated=615.6M(100%)\n\n VIRTUAL REGION \nREGION TYPE SIZE COUNT (non-coalesced) \n=========== ======= ======= \nActivity Tracing 256K 1 \nColorSync 80K 5 \nCoreAnimation 92K 16 \nFoundation 16K 1 \nKernel Alloc Once 8K 1 \nMALLOC 219.7M 46 \nMALLOC guard page 32K 7 \nMALLOC_NANO (reserved) 384.0M 1 reserved VM address space (unallocated)\nSTACK GUARD 56.0M 8 \nStack 11.6M 8 \nVM_ALLOCATE 28K 3 \n__DATA 10.2M 309 \n__DATA_CONST 24.6M 308 \n__DATA_DIRTY 22K 10 \n__FONT_DATA 4K 1 \n__LINKEDIT 522.4M 7 \n__OBJC_RO 63.1M 1 \n__OBJC_RW 3168K 1 \n__TEXT 332.1M 316 \n__UNICODE 592K 1 \ndyld private memory 2048K 2 \nmapped file 157.1M 5 \nshared memory 16K 1 \n=========== ======= ======= \nTOTAL 1.7G 1059 \nTOTAL, minus reserved VM space 1.4G 1059 \n", "legacyInfo" : { "threadTriggered" : { "queue" : "com.apple.main-thread" } }, "trialInfo" : { "rollouts" : [ { "rolloutId" : "5fb4245a1bbfe8005e33a1e1", "factorPackIds" : { }, "deploymentId" : 240000015 }, { "rolloutId" : "5fc94383418129005b4e9ae0", "factorPackIds" : { }, "deploymentId" : 240000452 } ], "experiments" : [ ] } } Model: MacBookPro16,1, BootROM 1731.100.130.0.0, 4 processors, Quad-Core Intel Core i5, 2.4 GHz, 16 GB, SMC Graphics: Intel UHD Graphics 630, Intel UHD Graphics 630, Built-In Display: spdisplays_display, 1920 x 1080 (1080p FHD - Full High Definition), Main, MirrorOff, Online Memory Module: BANK 0/Bottom - Slot 1 (top), 16 GB, DDR4, 2667 MHz, 859B, CB16GS2666.C8ET AirPort: spairport_wireless_card_type_wifi (0x8086, 0x84), itlwm: 2.1.0 fw: 48.1335886879.0 AirPort: AirPort: Bluetooth: Version (null), 0 services, 0 devices, 0 incoming serial ports Network Service: Wi-Fi, AirPort, en1 Serial ATA Device: WDC WDS100T2B0A-00SM50, 1 TB USB Device: USB31Bus USB Device: bluetooth_device USB Device: HP Wide Vision HD Camera USB Device: USB OPTICAL MOUSE Thunderbolt Bus:
lorentey commented 2 years ago

As documented, OrderedSet.update(_:at:) requires that the supplied item compare equal to the original one that's already in the set.

  /// Replace the member at the given index with a new value that compares equal
  /// to it.
  ///
  /// This is useful when equal elements can be distinguished by identity
  /// comparison or some other means.
  ///
  /// - Parameter item: The new value that should replace the original element.
  ///     `item` must compare equal to the original value.
  ///
  /// - Parameter index: The index of the element to be replaced.
  ///
  /// - Returns: The original element that was replaced.
  ///
  /// - Complexity: Amortized O(1).

As noted above, this is useful when the Element type has components that it doesn't consider significant for its definition of equality -- it allows the replacement of such items without going through a full hash lookup, as long as the position is already known.

What problem are you trying to solve?

xwu commented 2 years ago

This is a very unusual requirement for a method named update; I think it's reasonable for someone to be confused why doing something that is on its face what the name of the method suggests will be done leads to a runtime trap.

lorentey commented 2 years ago

Xiaodi, what would you expect this method to do?

shadyelmaadawy commented 2 years ago

This is a very unusual requirement for a method named update; I think it's reasonable for someone to be confused why doing something that is on its face what the name of the method suggests will be done leads to a runtime trap.

As documented, OrderedSet.update(_:at:) requires that the supplied item compare equal to the original one that's already in the set.

  /// Replace the member at the given index with a new value that compares equal
  /// to it.
  ///
  /// This is useful when equal elements can be distinguished by identity
  /// comparison or some other means.
  ///
  /// - Parameter item: The new value that should replace the original element.
  ///     `item` must compare equal to the original value.
  ///
  /// - Parameter index: The index of the element to be replaced.
  ///
  /// - Returns: The original element that was replaced.
  ///
  /// - Complexity: Amortized O(1).

As noted above, this is useful when the Element type has components that it doesn't consider significant for its definition of equality -- it allows the replacement of such items without going through a full hash lookup, as long as the position is already known.

What problem are you trying to solve?

it's doesn't about function name or usage, the problem is when trying to update an element that is not the same as the old one, that leads to application crashes, you could simply test the code I wrote above.

lorentey commented 2 years ago

The function is trapping because you’re violating its documented precondition.

Again, what problem are you trying to solve?

xwu commented 2 years ago

@lorentey I would expect a method named update to update the element at the specified index to any value of my choosing, provided that the invariants of the collection are maintained (in this case, that elements are unique).

lorentey commented 2 years ago

I would say that might be a useful operation to add, but replace(at:with:) would be a far more sensible name for it than update(_:at:). The latter doesn't read like a general replacement operation at all.

update(_:at:) is a core low-level operation for set-like collection types, sitting at the same level of importance as insert(_:). It is the primitive operation underlying all mutations that update existing members of the set, including the standard update(with:):

extension SomeSet {
  mutating func update(with item: Element) -> Element? {
    let (inserted, index) = self.insert(item)
    if inserted { return nil }
    return self.update(item, at: index)
  }
}

(Note: this is using the true primitive insert operation that returns an index rather than a member value. Unfortunately, SetAlgebra got this badly wrong -- a very unfortunate bug. (Understandable, given that SetAlgebra doesn't even define an Index type. But nonetheless, it's a crucial design issue.))

The update(_:at:) primitive is not often useful, but when it is, it can be pretty handy. For example, this operation can be used to normalize the members of a set to some canonical form without incurring any hashing at all:

var items: SomeSet<String> = ...
for i in items.indices {
  items.update(items[i].normalizationFormC, at: i)
}

It isn't possible to do this with a regular Set, because it doesn't provide the equivalent operation. (It should!)

I chose the particular name update(_:at:) because it reflects that the operation has a clear subject -- the item we're updating must already exist in the given set.

var items: OrderedSet = ["café", "reëlect", "façade", "jalapeño"]
// Update the set by replacing the existing item "café" with a refined variant.
let old = items.update(with: "caf\u{301}e") 

// Update the existing item "façade" at index 2 with a refined variant.
let old = items.update("fa\u{0327}cade", at: 2)

"Update the item "façade" at index 2" is a precise description of what this operation does, matching exactly what happens.

Passing this method a value that isn't member of the set reads like a nonsensical command:

let old = items.update("peach", at: 1)

This isn't cromulent -- there is no peach at index 1 to update. If this call successfully mutated the set somehow, I would have no idea what its mutated value would be. (If there was already a peach in some other location, would it somehow move the existing item? Leave it in place? Why doesn't it return something indicating this? If peach is a new item, why does this operation have such an awkward name? It isn't sensible to say "update [the value] peach at [index] 1" to mean "replace the member at [index] 1 with [the value] peach" or "insert [the value] "peach" at [index] 1".)

Contrast with:

let (index, old) = items.replace(at: 1, with: "peach") // or `replaceMember(at:with:)`

I can tell that this operation is supposed to replace whatever was at index 1 with the word "peach". The call site still doesn't explicitly tell me what happens if "peach" was already in the set at a different position, however the fact that the operation returns an index is a strong indication that it leaves it there. (If the method only returned a value, then my expectation would be that it would trap if the new item already existed in the set.)

I'm begging @shadudiix to explain what they're trying to do in order to understand whether to consider this issue a feature request for a new operation, and if so, what precise semantics are they looking for.

(For what it's worth, removing an existing item and replacing it with a brand new one is not a primitive operation -- it is already possible to implement this in O(1) hash+copy operations using append, swapAt, update(_:at:) and removeLast(). However, it may be useful to provide this for convenience.)

lorentey commented 2 years ago

For reference, the primitive operations for a collection type that implements a set construct include:

// Member lookup
func find(_ value: Element) -> Index? // a.k.a. firstIndex(of:)
// Member insertion
mutating func insert(_ value: Element) -> (inserted: Bool, index: Index)
// Member update
mutating func update(_ member: Element, at index: Index) -> Element
// Member removal
mutating func remove(at index: Index) -> Element

Behind the scenes, I usually find more useful to split the insertion primitive into two distinct phases:

mutating func mutatingFind(_ value: Element) -> (found: Bool, index: Index)
mutating func insertNew(_ value: Element, at index: Index)

If the item isn't found, mutatingFind returns an index addressing the position where a newly inserted item belongs. (Depending on the data structure, this may or may not happen to fall onto a valid index -- Set's find operation always returns an invalid index, but in the upcoming SortedSet, it'll be always valid.) This allows higher-level operations to optimize the number of full lookup operations. (For maximum versatility, mutatingFind and insertNew ought to be public API, but the impracticality of validating the index passed to indexNew makes this unlikely to happen.)

xwu commented 2 years ago

I'm not arguing that it doesn't serve a very useful purpose to have this operation, but I think this bug is demonstrating that the update is a poor choice of name.

The very meaning of "update" is that you make some salient change, and the meaning of two things comparing equal is that there is no salient difference (for some blessed definition of salience). The name is setting up users for failure because it is by the dictionary definition of the word telling users to use it for the very thing that trips a precondition.

There is no need for a niche operation to use a tempting common name, even if it is a primitive; it can have a longer name, or it can use different terminology, or both. For instance, one might borrow the term "touch" to indicate a minor and limited modification without changing the salient aspects of the value.

lorentey commented 2 years ago

The name is setting up users for failure because it is by the dictionary definition of the word telling users to use it for the very thing that trips a precondition.

The dictionary definition of the verb "update" is "to bring up to date", not "to replace with something unrelated".

Reasonable people will disagree on naming choices; the world will go on. As much fun it would be endlessly argue on past API naming decisions, the public API of OrderedSet has been stable for a year or so, and I'm not particularly keen to re-litigate minor aspects of its design at this point -- I don't see how renaming this particular entry point could possibly justify the migration costs. As I have explained above, (1) the name we chose perfectly fits the function's purpose, and (2) we would not use this name for a function that implements an unconstrained replacement (if it was possible to implement that).

For what it's worth, the upcoming BitSet will not provide an update(_:at:) method (there is no point in updating an integer value), but I expect PersistentSet and SortedSet will do so. This package does not fall under the scope of the Swift Evolution process, but I expect I will run some sort of a loose API review on the associated forum topic -- that thread might be a good opportunity to revisit this naming decision. Of course, any concrete suggestion for a replacement must be an obviously better choice to overcome the hurdle of breaking precedent.

I'm still interested in learning what exactly @shadudiix is trying to do -- we can certainly add new functionality to cover common use cases!

xwu commented 2 years ago

The dictionary definition of the verb "update" is "to bring up to date", not "to replace with something unrelated".

Yes—to bring up-to-date by changing it. Indeed, to replace with something new (I'm not arguing that the new value must be necessarily unrelated):

verb to make something more modern or suitable for use now by adding new information or changing its design: • an updated version of the software to give someone the most recent information: • We'll update you on this news story throughout the day.

(Source: Cambridge English Dictionary)

This is, in fact, the meaning given to the APIs named update in SE-0370, deprecating (updating!) the original name of assign—there must have been some value initialized originally in order to correctly use the update API, but the meaning of the API is to replace the previous value with a new value.

It's also how the term is used colloquially. If my boss asks me if there's any update about some ongoing work that I haven't made any progress on, I'd tell him that there's "no update." I wouldn't say, "Yes, here's the update!", then rephrase my last report using different words, providing no new information.

Anyway, I too am curious what @shadudiix is trying specifically to do. That will clarify this bug report.

lorentey commented 2 years ago

Ah, good point about SE-0370.