{"id":45953,"date":"2024-11-26T14:16:13","date_gmt":"2024-11-26T19:16:13","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=45953"},"modified":"2024-11-26T14:16:40","modified_gmt":"2024-11-26T19:16:40","slug":"watch-out-for-counterintuitive-implicit-actor-isolation","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2024\/11\/26\/watch-out-for-counterintuitive-implicit-actor-isolation\/","title":{"rendered":"Watch Out for Counterintuitive Implicit Actor-Isolation"},"content":{"rendered":"<p><a href=\"https:\/\/jaredsinclair.com\/2024\/11\/12\/beware-unchecked.html\">Jared Sinclair<\/a>:<\/p>\n<blockquote cite=\"https:\/\/jaredsinclair.com\/2024\/11\/12\/beware-unchecked.html\"><p>I ran into some unexpected runtime crashes recently while testing an app on iOS 18 compiled under Swift 6 language mode, and the root causes ended up being the perils of using <code>@unchecked Sendable<\/code> in combination with some counterintuitive compiler behavior with implicit actor isolation.<\/p><p>[&#8230;]<\/p><p>What occurred to me instead was to find a way to use locking mechanisms to synchronize access to the <code>static var<\/code> mutable property. What happened next led me down a path to some code that (A) compiled without warnings or errors but (B) crashed hard at runtime due to implicit actor isolation assertion failures.<\/p><p>[&#8230;]<\/p><p>It turns out that the implicit Main Actor isolation is getting introduced by <code>MyApp<\/code>[&#8230;] Therefore that <code>init()<\/code> method is isolated to the Main Actor. But our <code>Logging.sink<\/code> member is <em>not<\/em> isolated to the Main Actor. It&rsquo;s implicitly <code>nonisolated<\/code>, so why is the compiler inferring Main Actor isolation for the block we pass to it?<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@mattiem\/113471879178243629\">Matt Massicotte<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@mattiem\/113471879178243629\">\n<p>What&rsquo;s happening here is the compiler is reasoning &ldquo;this closure is not Sendable so it couldn&rsquo;t possibly change isolation from where it was formed and therefore its body must be MainActor too&rdquo; but your unchecked type allows this invariant to be violated. This kind of thing comes up a lot in many forms, and it&rsquo;s hard to debug&#8230;<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/synchronization\/mutex\">Mutex<\/a> is a potential solution but requires iOS 18. He also shows how to protect the sink with a non-global actor.<\/p>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/11\/25\/swift-vision-improving-the-approachability-of-data-race-safety\/\">Swift Vision: Improving the Approachability of Data-Race Safety<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/11\/07\/problematic-swift-concurrency-patterns\/\">Problematic Swift Concurrency Patterns<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/10\/01\/swift-concurrency-and-objective-c\/\">Swift Concurrency and Objective-C<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/09\/20\/unwanted-swift-concurrency-checking\/\">Unwanted Swift Concurrency Checking<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/09\/19\/swift-6\/\">Swift 6<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/04\/30\/swift-proposal-synchronous-mutual-exclusion-lock\/\">Swift Proposal: Synchronous Mutual Exclusion Lock<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/03\/27\/noncopyable-generics-walkthrough\/\">Noncopyable Generics Walkthrough<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/03\/22\/swift-proposal-noncopyable-structs-and-enums\/\">Swift Proposal: Noncopyable Structs and Enums<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Jared Sinclair: I ran into some unexpected runtime crashes recently while testing an app on iOS 18 compiled under Swift 6 language mode, and the root causes ended up being the perils of using @unchecked Sendable in combination with some counterintuitive compiler behavior with implicit actor isolation.[&#8230;]What occurred to me instead was to find a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2024-11-26T19:16:16Z","apple_news_api_id":"0b821913-64f6-46ca-9282-4ae411ea88b2","apple_news_api_modified_at":"2024-11-26T19:16:43Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAA==","apple_news_api_share_url":"https:\/\/apple.news\/AC4IZE2T2RsqSgkrkEeqIsg","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[31,2586,71,2200,901],"class_list":["post-45953","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-ios","tag-ios-18","tag-programming","tag-swift-concurrency","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/45953","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=45953"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/45953\/revisions"}],"predecessor-version":[{"id":45955,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/45953\/revisions\/45955"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=45953"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=45953"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=45953"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}