{"$schema": "https://raw.githubusercontent.com/guitaripod/wwdc-sessions/master/schema/transcript.schema.json", "id": "wwdc2026-262", "language": "eng", "source": "https://developer.apple.com/videos/play/wwdc2026/262", "wordCount": 5593, "segments": [{"start": 7.0, "text": "Hi, I'm Becca from the Swift team."}, {"start": 9.0, "text": "My teammate Evan and I are here to tell you about some of the improvements"}, {"start": 12.0, "text": "we've made during the development of Swift 6.3 and 6.4."}, {"start": 16.0, "text": "I'll start by showing you some changes to the language"}, {"start": 18.0, "text": "that'll streamline your day-to-day coding."}, {"start": 21.0, "text": "Then Evan will discuss updates to important libraries"}, {"start": 24.0, "text": "and developments in support beyond Xcode and the Apple platforms."}, {"start": 28.0, "text": "After that, I'll walk you through some specialized features for tuning"}, {"start": 31.0, "text": "performance-sensitive code without compromising on safety."}, {"start": 35.0, "text": "Then Evan will finish up"}, {"start": 36.0, "text": "by talking about how you can follow along or contribute to Swift's development."}, {"start": 40.0, "text": "But let's start with some of the simple improvements that you might use every day."}, {"start": 45.0, "text": "Some of them you might barely notice except as little annoyances going away,"}, {"start": 49.0, "text": "so let's look at some of the smaller changes first."}, {"start": 52.0, "text": "For example, previously if you wanted to use some or any with an optional type,"}, {"start": 56.0, "text": "you had to parenthesize it."}, {"start": 59.0, "text": "This behavior fell out of Swift's operator precedence rules,"}, {"start": 62.0, "text": "but it was a little pedantic."}, {"start": 63.0, "text": "So, in Swift 6.4, you can simply get rid of those parentheses"}, {"start": 67.0, "text": "and the compiler will take that to mean the only thing that really makes sense."}, {"start": 72.0, "text": "You'll now get a warning if you silently ignore an error"}, {"start": 74.0, "text": "thrown from a Swift Concurrency task,"}, {"start": 77.0, "text": "reminding you to either handle the error in the task,"}, {"start": 79.0, "text": "or save the task and check for the error later."}, {"start": 82.0, "text": "And the old restriction on calling async functions from a defer block is now gone."}, {"start": 87.0, "text": "If you have a class that needs to use @unchecked Sendable"}, {"start": 89.0, "text": "because it has a weak var property,"}, {"start": 92.0, "text": "you can now change that property to weak let so it's immutable"}, {"start": 95.0, "text": "and doesn't stop you from using Sendable checking."}, {"start": 98.0, "text": "Or if a type shouldn't be Sendable,"}, {"start": 100.0, "text": "you can state that explicitly with the new tilde Sendable syntax."}, {"start": 103.0, "text": "Which, as an added bonus, doesn't stop subclasses from being Sendable."}, {"start": 108.0, "text": "And a struct with a mix of internal and private properties"}, {"start": 111.0, "text": "will now have a second memberwise initializer"}, {"start": 113.0, "text": "that you can use from other files in your project."}, {"start": 116.0, "text": "But there are also some changes you'll definitely notice."}, {"start": 119.0, "text": "The Apple ecosystem has grown over the last two decades, and as it has,"}, {"start": 123.0, "text": "the availability attributes in your Swift code have grown with it."}, {"start": 128.0, "text": "Last year, Apple began to address this problem"}, {"start": 130.0, "text": "by aligning the version numbers of our OS releases."}, {"start": 133.0, "text": "Now, Swift is taking that even further"}, {"start": 135.0, "text": "by letting you condense all of those platform names into one: \"Any Apple OS\"."}, {"start": 141.0, "text": "So if the availability lines up on all of the platforms you care about,"}, {"start": 145.0, "text": "you can specify all of the OSes at once,"}, {"start": 147.0, "text": "or if there are carve-outs, you can use anyAppleOS to establish the default"}, {"start": 152.0, "text": "and then add more specific attributes for the exceptions."}, {"start": 155.0, "text": "And this also works for #if os conditions"}, {"start": 157.0, "text": "if you want to compile a section of your code out entirely."}, {"start": 161.0, "text": "Another thing that changes over the years is APIs."}, {"start": 164.0, "text": "As they evolve, older APIs are sometimes deprecated"}, {"start": 167.0, "text": "to indicate that you should move to newer versions."}, {"start": 170.0, "text": "But sometimes you can't do that right away,"}, {"start": 172.0, "text": "maybe the new API is very different and you need time to adapt."}, {"start": 176.0, "text": "Wouldn't it be nice to turn off these warnings temporarily"}, {"start": 178.0, "text": "without affecting the rest of your project?"}, {"start": 181.0, "text": "Well, now you can."}, {"start": 182.0, "text": "The @diagnose attribute lets you change the behavior of specific warnings"}, {"start": 186.0, "text": "inside a particular declaration."}, {"start": 188.0, "text": "So you can tell Swift to ignore the warning group deprecated declaration"}, {"start": 191.0, "text": "and make that kind of warning go away in that one place."}, {"start": 195.0, "text": "You can also use it to selectively enable warnings that are off by default."}, {"start": 199.0, "text": "For example, you could turn on strict memory safety"}, {"start": 202.0, "text": "in security-critical functions"}, {"start": 204.0, "text": "to make sure you've audited their uses of unsafe APIs."}, {"start": 208.0, "text": "Or you can treat certain warnings as errors."}, {"start": 210.0, "text": "Here, we've upgraded warnings that will become errors in the future"}, {"start": 213.0, "text": "to errors right now."}, {"start": 215.0, "text": "All that gives you a lot of flexibility."}, {"start": 218.0, "text": "And Swift 6.3 also has a new feature to better handle situations where two modules"}, {"start": 223.0, "text": "have APIs with the same name."}, {"start": 225.0, "text": "For example, the Rocket module might have a type"}, {"start": 228.0, "text": "representing a real, hundred-meter-tall SaturnV rocket,"}, {"start": 232.0, "text": "while the GiftShopToys module"}, {"start": 233.0, "text": "has a type representing a child-size model of a SaturnV rocket."}, {"start": 237.0, "text": "If you've imported both of these modules in the same file,"}, {"start": 240.0, "text": "Swift won't be able to tell which one you wanted to use, so it'll give you an error."}, {"start": 245.0, "text": "When this happens, you've always been able to clarify your code by using"}, {"start": 248.0, "text": "the dot syntax, Rocket.SaturnV will first find the Rocket module,"}, {"start": 253.0, "text": "then look for the type SaturnV inside it,"}, {"start": 255.0, "text": "without ever noticing that there's another SaturnV somewhere else."}, {"start": 259.0, "text": "This usually works, but there are some tricky situations where it breaks down."}, {"start": 264.0, "text": "For example, what happens if the module Rocket also has a type Rocket?"}, {"start": 268.0, "text": "Well, I'll tell you what happens,"}, {"start": 270.0, "text": "Swift prefers type names over module names,"}, {"start": 273.0, "text": "so it decides you must mean the type Rocket"}, {"start": 275.0, "text": "and then looks inside it for a member called SaturnV."}, {"start": 279.0, "text": "When it doesn't find one, it gives you an error."}, {"start": 281.0, "text": "Swift 6.3 has a solution to this problem, just change that dot to a double colon."}, {"start": 287.0, "text": "This new syntax is called a module selector,"}, {"start": 290.0, "text": "and the name on the left is always treated as a module name."}, {"start": 293.0, "text": "So Swift will ignore the type Rocket and go straight to the module Rocket,"}, {"start": 296.0, "text": "and from there, it'll have no trouble finding the type you're looking for."}, {"start": 300.0, "text": "This syntax also works on the name of a method or property,"}, {"start": 303.0, "text": "which is handy if a type gets identically-named methods"}, {"start": 306.0, "text": "from extensions in two different modules."}, {"start": 308.0, "text": "After all, calling the wrong method could really ruin someone's day."}, {"start": 313.0, "text": "Now, module selectors are super useful"}, {"start": 316.0, "text": "when there's a conflict between two modules you don't control."}, {"start": 319.0, "text": "Like, if SwiftUI and the database package you're using both have a type called View,"}, {"start": 324.0, "text": "a module selector can really save you some trouble."}, {"start": 327.0, "text": "It can also be a good idea to use them defensively"}, {"start": 329.0, "text": "in macro expansions and other automatically-generated code,"}, {"start": 333.0, "text": "since you don't know what else might have been imported into the project."}, {"start": 337.0, "text": "But, we don't recommend you intentionally design your APIs to have name conflicts"}, {"start": 341.0, "text": "and then rely on module selectors to distinguish them."}, {"start": 344.0, "text": "Even if your code is unambiguous,"}, {"start": 346.0, "text": "some of the error messages and documentation might still be confusing."}, {"start": 351.0, "text": "So... don't."}, {"start": 354.0, "text": "Now that we've seen what's new in the language,"}, {"start": 355.0, "text": "here's Evan to tell you about updates to important libraries."}, {"start": 359.0, "text": "All of these language improvements share the same goal"}, {"start": 362.0, "text": "of helping you express exactly what you mean without extra noise."}, {"start": 366.0, "text": "That same goal carries into updates to the libraries you use every day."}, {"start": 370.0, "text": "The standard library, Swift testing, Subprocess, and Foundation."}, {"start": 376.0, "text": "Let's start with updates to the standard library,"}, {"start": 378.0, "text": "specifically with new tools for task cancellation,"}, {"start": 382.0, "text": "dictionary transformations, and filepath manipulations."}, {"start": 386.0, "text": "It's important to check the task cancellation status"}, {"start": 388.0, "text": "before starting any expensive work,"}, {"start": 391.0, "text": "but there are times where we actually want to do the work"}, {"start": 394.0, "text": "even after the task was cancelled,"}, {"start": 396.0, "text": "like finishing writing data to disk to avoid corrupting a file."}, {"start": 400.0, "text": "Now you can use the task cancellation shield."}, {"start": 403.0, "text": "Inside of the shield, task cancellation checks always return false."}, {"start": 407.0, "text": "It's important to keep this region short,"}, {"start": 409.0, "text": "focusing on either finishing or rolling back any work that you already started."}, {"start": 413.0, "text": "Mapping values from dictionaries also received an update."}, {"start": 417.0, "text": "mapValues only passes the old value into the mapping closure,"}, {"start": 420.0, "text": "so if you needed the key to compute the new value,"}, {"start": 423.0, "text": "you had to construct a new dictionary by hand."}, {"start": 426.0, "text": "Now, we can call mapKeyedValues,"}, {"start": 428.0, "text": "which passes both the key and the old value"}, {"start": 431.0, "text": "into the mapping closure to compute the new value."}, {"start": 434.0, "text": "Programs often need to manipulate filepaths."}, {"start": 437.0, "text": "There are subtle differences between how different platforms represent filepaths"}, {"start": 441.0, "text": "that can make it tricky to handle them correctly."}, {"start": 443.0, "text": "This year, we added a new filepath type to the standard library,"}, {"start": 447.0, "text": "based on the type from Swift System, making it easier to get right."}, {"start": 451.0, "text": "Testing in Swift 6.4 offers you more control over the behavior of your tests,"}, {"start": 456.0, "text": "allowing you to surface non-fatal issues and dynamically skip tests cases."}, {"start": 461.0, "text": "Now you can set the severity level of issues recorded with Issue.record."}, {"start": 465.0, "text": "Setting it to a warning"}, {"start": 466.0, "text": "means you can surface issues in a test case that are worth investigating,"}, {"start": 470.0, "text": "but not worth blocking CI workflows."}, {"start": 472.0, "text": "You can cancel tests dynamically by calling the Test.cancel API."}, {"start": 477.0, "text": "This is especially powerful with parameterized tests,"}, {"start": 480.0, "text": "where you can cancel individual arguments that shouldn't run,"}, {"start": 483.0, "text": "rather than running them to completion or failing the test."}, {"start": 487.0, "text": "Sometimes you're trying to tackle a flaky test."}, {"start": 490.0, "text": "The swift test command adds new functionality to repeat a test"}, {"start": 493.0, "text": "until it either passes or fails,"}, {"start": 495.0, "text": "while also allowing you to control the maximum number of repetitions."}, {"start": 499.0, "text": "If you specify that you want to repeat until the tests pass,"}, {"start": 503.0, "text": "only failing tests are re-run,"}, {"start": 505.0, "text": "saving time by not re-running tests that are already passing."}, {"start": 509.0, "text": "Many projects have large test suites that have utilities built on XCTest APIs."}, {"start": 514.0, "text": "In Swift 6.4, XCTest assertion failures are now reported as test issues"}, {"start": 519.0, "text": "when called from Swift Testing."}, {"start": 521.0, "text": "This means that you can migrate to Swift Testing"}, {"start": 524.0, "text": "without worrying about accidentally losing test coverage along the way."}, {"start": 528.0, "text": "And the interoperability also works in the other direction too,"}, {"start": 532.0, "text": "Swift Testing APIs, like the #expect macro work when called from an XCTestCase."}, {"start": 537.0, "text": "This means you can build helper APIs with Swift Testing, and they'll have consistent"}, {"start": 541.0, "text": "behavior regardless of whether they're called from XCTest or Swift Testing."}, {"start": 546.0, "text": "If you're working in an existing project,"}, {"start": 548.0, "text": "you might already be calling XCTest assertions from Swift Testing"}, {"start": 552.0, "text": "and vice-versa."}, {"start": 553.0, "text": "To make this transition easier,"}, {"start": 555.0, "text": "these issues are reported as warnings by default."}, {"start": 558.0, "text": "You can opt into promoting them to test failures in the Xcode build settings."}, {"start": 563.0, "text": "To learn more about Swift Testing interoperability and migration strategies,"}, {"start": 567.0, "text": "check out \"Migrate to Swift Testing\"."}, {"start": 569.0, "text": "Last year, we announced the Subprocess package"}, {"start": 572.0, "text": "containing modern APIs for launching subprocesses."}, {"start": 575.0, "text": "This year, we are releasing Subprocess 1.0,"}, {"start": 578.0, "text": "incorporating your feedback from real-world use."}, {"start": 581.0, "text": "The API refinements include a simplified execution type,"}, {"start": 585.0, "text": "improved error handling, and convenience APIs for easily streaming process output."}, {"start": 591.0, "text": "Cross-platform support is also greatly improved,"}, {"start": 593.0, "text": "including platform-specific process file descriptors and termination statuses,"}, {"start": 597.0, "text": "to more accurately reflect the semantics on different platforms."}, {"start": 601.0, "text": "Here is an example of the refined API in Subprocess 1.0."}, {"start": 606.0, "text": "When calling the run method to launch a subprocess,"}, {"start": 609.0, "text": "the standard output and standard error streams"}, {"start": 611.0, "text": "can be included in the execution object as AsyncBufferSequences."}, {"start": 615.0, "text": "This model guarantees that each stream is only created once."}, {"start": 620.0, "text": "The new strings() method on AsyncBufferSequence"}, {"start": 623.0, "text": "makes it easy to read the output of a subprocess line-by-line."}, {"start": 627.0, "text": "This API respects graphene cluster boundaries,"}, {"start": 630.0, "text": "so you don't have to worry about multi-byte characters getting split."}, {"start": 634.0, "text": "Finally, let's talk about improvements to Foundation."}, {"start": 637.0, "text": "ProgressManager is a new type in Foundation for progress reporting."}, {"start": 642.0, "text": "It's designed to work well with async/await style concurrency"}, {"start": 646.0, "text": "it cleanly separates progress composition from progress reporting,"}, {"start": 650.0, "text": "and provides a structured,"}, {"start": 652.0, "text": "type-safe mechanism for attaching additional metadata."}, {"start": 655.0, "text": "We announced Swift-Foundation two years ago,"}, {"start": 658.0, "text": "an effort to migrate Foundation to a safe, consistent,"}, {"start": 660.0, "text": "cross-platform codebase, written in Swift."}, {"start": 664.0, "text": "This year, we continued that effort,"}, {"start": 666.0, "text": "replacing decades of Objective-C with modern Swift."}, {"start": 670.0, "text": "This year, we modernized more parts of Data,"}, {"start": 672.0, "text": "resulting in improvements across the board,"}, {"start": 674.0, "text": "including faster span accesses, equality checks, iteration, and mutation."}, {"start": 680.0, "text": "On Apple platforms, bridging between Data and NSData is also faster."}, {"start": 684.0, "text": "NSURL and CFURL were unified to a single Swift implementation."}, {"start": 689.0, "text": "Leveraging Swift makes these types run faster and use less memory."}, {"start": 693.0, "text": "Migrating a library as large and mature as Foundation"}, {"start": 696.0, "text": "is only possible because of Swift's language interoperability."}, {"start": 700.0, "text": "You can add entirely new APIs in Swift, and you can migrate"}, {"start": 704.0, "text": "the implementation of existing APIs to Swift without changing the API surface."}, {"start": 709.0, "text": "In addition to crossing language boundaries,"}, {"start": 712.0, "text": "many real-world projects extend into services, devices, web components,"}, {"start": 717.0, "text": "cross-platform clients, and more."}, {"start": 719.0, "text": "At Apple, we use Swift in every part of the OS,"}, {"start": 722.0, "text": "in apps like Weather, in services like the realtime phone call spam detection,"}, {"start": 727.0, "text": "in the kernel itself, and all of the way down to the lowest layers of firmware."}, {"start": 732.0, "text": "Swift is designed to be a language that you can reach for"}, {"start": 735.0, "text": "across every layer of your software stack."}, {"start": 739.0, "text": "To make it easier to use in your existing software systems,"}, {"start": 742.0, "text": "Swift 6.4 extends language interoperability,"}, {"start": 746.0, "text": "improves cross-platform IDE support, and makes it easier and safer to bring"}, {"start": 750.0, "text": "your Swift code to other environments like the web and embedded devices."}, {"start": 755.0, "text": "You've always been able to import C into Swift with ease."}, {"start": 759.0, "text": "Swift 6.4 allows you to expose functions written in Swift back to C."}, {"start": 764.0, "text": "You've likely seen or used the @objc attribute"}, {"start": 767.0, "text": "when migrating your apps from Objective-C to Swift."}, {"start": 770.0, "text": "The @C attribute works the same way, but for C."}, {"start": 773.0, "text": "The @C attribute applies to functions that operate on C-compatible types."}, {"start": 777.0, "text": "Any type you can import from C to Swift"}, {"start": 780.0, "text": "can also be used in functions that are exported from Swift to C, like integers"}, {"start": 785.0, "text": "pointers, imported C structs, and enums with raw integer value types."}, {"start": 791.0, "text": "And, the compiler prevents you from accidentally passing types"}, {"start": 794.0, "text": "that are incompatible with C."}, {"start": 796.0, "text": "Let's see the @C attribute in action."}, {"start": 799.0, "text": "I'm working on an app for scheduling rocket launches."}, {"start": 802.0, "text": "We'll focus on the code tracking the launch windows."}, {"start": 804.0, "text": "It's currently written in C,"}, {"start": 806.0, "text": "but we're migrating to Swift for memory safety and improving developer ergonomics."}, {"start": 811.0, "text": "Let's use the new features in Swift 6.4"}, {"start": 813.0, "text": "to rewrite portions of the application from C."}, {"start": 816.0, "text": "There are currently two functions declared in the header,"}, {"start": 819.0, "text": "one to get the length of a launch window,"}, {"start": 821.0, "text": "and another to compute the total time spent in a collection of launch windows,"}, {"start": 825.0, "text": "allowing us to compute launch pad utilization."}, {"start": 828.0, "text": "Let's start by replacing the C implementation"}, {"start": 830.0, "text": "of the function computing the length of a launch window."}, {"start": 834.0, "text": "We can use the @c and @implementation attributes together"}, {"start": 838.0, "text": "to implement a C function without creating a C declaration for it"}, {"start": 842.0, "text": "since it already exists in the original header file."}, {"start": 844.0, "text": "Next, we'll provide an implementation for the function computing"}, {"start": 848.0, "text": "the total time spent in a launch window, across many launch windows."}, {"start": 852.0, "text": "Functions are imported verbatim when you're implementing them in Swift."}, {"start": 856.0, "text": "We can translate the types into native Swift types"}, {"start": 858.0, "text": "allowing us to use the ergonomics of Swift to reimplement our C functions."}, {"start": 862.0, "text": "Safe interop features provide safe wrappers when we call the functions,"}, {"start": 866.0, "text": "so instead of passing the array and count separately, we can pass it a span."}, {"start": 871.0, "text": "It's easier to write, and it's safe!"}, {"start": 873.0, "text": "While we're working on this,"}, {"start": 875.0, "text": "I want to add a new function that gets the average launch window length."}, {"start": 879.0, "text": "We don't use the @implementation attribute here"}, {"start": 881.0, "text": "because the function isn't declared in the original C header."}, {"start": 885.0, "text": "The Swift compiler emits the appropriate function declaration into the generated C"}, {"start": 889.0, "text": "interop header instead, so we can call the new function from our C code."}, {"start": 894.0, "text": "Swift automatically bridges Swift Spans to C."}, {"start": 897.0, "text": "Now, Swift C++ interoperability also supports bridging between Swift and C++ 20 spans."}, {"start": 903.0, "text": "This declaration imports to Swift with a span, so you can pass a span in directly."}, {"start": 908.0, "text": "Interoperability is key"}, {"start": 910.0, "text": "to bringing Swift into existing codebases written in other languages."}, {"start": 914.0, "text": "Swift-Java is the package that enables interoperability between Swift and Java."}, {"start": 919.0, "text": "It now supports calling async and throwing Swift functions from Java."}, {"start": 924.0, "text": "It captures more features of the generics system,"}, {"start": 926.0, "text": "including constrained extensions,"}, {"start": 928.0, "text": "and conforming Java classes to Swift protocols."}, {"start": 932.0, "text": "All of these improvements"}, {"start": 933.0, "text": "make calling Swift code from Java and Kotlin feel natural on Android."}, {"start": 937.0, "text": "And you can now download an official Swift SDK for Android on swift.org."}, {"start": 943.0, "text": "The latest version of the Swift extension for VSCode"}, {"start": 946.0, "text": "adds new integration with Swiftly,"}, {"start": 948.0, "text": "making it easy to install toolchains from swift.org, right from your editor."}, {"start": 952.0, "text": "So now you'll always have the right toolchain for any platform,"}, {"start": 956.0, "text": "right at your fingertips."}, {"start": 958.0, "text": "Last year, we added the Swift extension to the Visual Studio marketplace."}, {"start": 966.0, "text": "This year, we've added it to the OpenVSX marketplace,"}, {"start": 970.0, "text": "making the integrated Swift experience available to new editors including"}, {"start": 974.0, "text": "VSCodium, Cursor, Kiro, and Antigravity."}, {"start": 977.0, "text": "The latest version of the plugin makes it easier to get started with Swift than"}, {"start": 981.0, "text": "ever before with a checklist that guides you through installing Swift,"}, {"start": 984.0, "text": "creating a new project, running your code,"}, {"start": 986.0, "text": "setting up tests, and generating documentation."}, {"start": 990.0, "text": "If you have Swiftly installed, it can help manage your toolchains."}, {"start": 993.0, "text": "I'm installing a nightly toolchain"}, {"start": 995.0, "text": "so that I can play with the new language features targeting Web Assembly"}, {"start": 998.0, "text": "and embedded platforms."}, {"start": 1000.0, "text": "The open source toolchain we just installed can compile to Web Assembly."}, {"start": 1004.0, "text": "Wasm support in Swift"}, {"start": 1005.0, "text": "means that you can use the same language to write your native apps,"}, {"start": 1008.0, "text": "your backend webservers, and your frontend too."}, {"start": 1011.0, "text": "Let's look at some of the improvements in the Javascript interoperability story"}, {"start": 1015.0, "text": "coming out of the open-source project JavascriptKit."}, {"start": 1019.0, "text": "Bridging between Swift and Javascript used to involve a lot of dynamic lookups"}, {"start": 1023.0, "text": "and hoping that types would match up."}, {"start": 1025.0, "text": "The most recent efforts in JavascriptKit"}, {"start": 1028.0, "text": "have made bridging between the languages safer and faster."}, {"start": 1031.0, "text": "The code looks like native Swift code,"}, {"start": 1033.0, "text": "but it's making calls to WebGL through Javascript."}, {"start": 1037.0, "text": "The popular note-taking app, Goodnotes,"}, {"start": 1039.0, "text": "recently implemented a web-based interface in addition to their native iOS app."}, {"start": 1044.0, "text": "The cost of moving their core app to another language,"}, {"start": 1047.0, "text": "working through the bugs, and then maintaining two codebases was too high."}, {"start": 1051.0, "text": "They took their existing, battle-tested, Swift code,"}, {"start": 1054.0, "text": "and compiled it for the web using Wasm."}, {"start": 1057.0, "text": "And with the improvements to JavaScriptKit, their benchmarking found"}, {"start": 1060.0, "text": "the safe bridging to be 35 to 40 times faster than the dynamic bridging."}, {"start": 1066.0, "text": "Wasm support in Swift"}, {"start": 1067.0, "text": "means you can take your Swift code running in your native iOS applications"}, {"start": 1070.0, "text": "and get it running as part of a webapp."}, {"start": 1072.0, "text": "Unlike with a native application though,"}, {"start": 1074.0, "text": "you have to send the compiled code to each device every time they visit your site."}, {"start": 1079.0, "text": "There are CDNs to help,"}, {"start": 1081.0, "text": "but big binaries can quickly eat into yours, and your customer's data."}, {"start": 1085.0, "text": "This means that size is a bigger concern than ever."}, {"start": 1088.0, "text": "With embedded Swift,"}, {"start": 1089.0, "text": "we can take advantage of the ergonomics of Swift in more constrained environments."}, {"start": 1093.0, "text": "We stripped down the language to make it fit,"}, {"start": 1095.0, "text": "and now, as we learn how people are using Swift in these environments,"}, {"start": 1098.0, "text": "we are growing the available subset of the language."}, {"start": 1102.0, "text": "Embedded Swift now has support for existential types."}, {"start": 1105.0, "text": "This means you can work with multiple types conforming to a protocol"}, {"start": 1108.0, "text": "stored in an array or passed to a function."}, {"start": 1112.0, "text": "Typed throws are great when you know the error type,"}, {"start": 1114.0, "text": "but they're limited to a specific error type."}, {"start": 1117.0, "text": "Using the same underlying machinery for handling existential types,"}, {"start": 1121.0, "text": "embedded Swift now supports untyped throws."}, {"start": 1124.0, "text": "The debugger needs extra metadata about type layout to display variables."}, {"start": 1128.0, "text": "To keep binary size down,"}, {"start": 1130.0, "text": "embedded Swift does't include that data in the binary itself."}, {"start": 1134.0, "text": "Furthermore, many embedded systems only leave you with a core dump"}, {"start": 1138.0, "text": "of the memory state when the program crashed,"}, {"start": 1140.0, "text": "so you're not even debugging a live process."}, {"start": 1143.0, "text": "Swift 6.4 saves all of the necessary metadata into the DWARF debug info,"}, {"start": 1148.0, "text": "keeping binary sizes down,"}, {"start": 1150.0, "text": "while greatly improving the experience debugging an embedded Swift coredump."}, {"start": 1154.0, "text": "These are just a few of the improvements we made this year,"}, {"start": 1156.0, "text": "bridging the gap between full and embedded Swift."}, {"start": 1160.0, "text": "While the subset of Swift that works on embedded platforms is growing,"}, {"start": 1163.0, "text": "it is still a subset of the language."}, {"start": 1166.0, "text": "Diagnostics in the EmbeddedRestrictions warning group identify language features"}, {"start": 1170.0, "text": "that aren't available in embedded contexts."}, {"start": 1173.0, "text": "If you're working with a library that supports both embedded and full Swift,"}, {"start": 1177.0, "text": "you may need to expose functions that"}, {"start": 1179.0, "text": "use features that aren't available in embedded contexts."}, {"start": 1182.0, "text": "The @diagnose attribute that Becca showed us earlier"}, {"start": 1185.0, "text": "lets us control these diagnostics."}, {"start": 1187.0, "text": "Embedded code often runs on incredibly constrained hardware environments."}, {"start": 1191.0, "text": "That's why it's critical to get the most out of every clock cycle."}, {"start": 1195.0, "text": "Back to Becca to talk about how to squeeze performance from your Swift code."}, {"start": 1199.0, "text": "Swift is designed to have great performance"}, {"start": 1202.0, "text": "even when you've written the most straightforward,"}, {"start": 1204.0, "text": "expressive implementation of your logic."}, {"start": 1206.0, "text": "But when you're doing a lot of computation,"}, {"start": 1208.0, "text": "or running in constrained environments like embedded systems,"}, {"start": 1212.0, "text": "sometimes it's worth complicating your code"}, {"start": 1214.0, "text": "to squeeze out just a little bit more when it counts."}, {"start": 1218.0, "text": "You usually won't need these advanced performance features,"}, {"start": 1220.0, "text": "but when you do, you'll be glad you have them."}, {"start": 1224.0, "text": "I'm going to focus on two areas we've worked on this year,"}, {"start": 1227.0, "text": "explicitly controlling optimizer decisions,"}, {"start": 1229.0, "text": "and further extending the ownership system to safely prevent unnecessary copying."}, {"start": 1235.0, "text": "The Swift compiler's optimizer"}, {"start": 1236.0, "text": "applies dozens of techniques to make your code faster,"}, {"start": 1239.0, "text": "but some of the most powerful ones"}, {"start": 1241.0, "text": "can be counterproductive when they're applied incorrectly."}, {"start": 1244.0, "text": "These involve duplicating code so it can be customized for a particular situation,"}, {"start": 1248.0, "text": "but if the customization doesn't pay off, you could end up with a program that's"}, {"start": 1252.0, "text": "larger and slower instead of smaller and faster."}, {"start": 1256.0, "text": "For example, one of the most important optimizations the compiler performs is inlining,"}, {"start": 1261.0, "text": "replacing function calls with their implementations,"}, {"start": 1264.0, "text": "and then optimizing those implementations for the specific call site."}, {"start": 1268.0, "text": "When inlining pays off,"}, {"start": 1269.0, "text": "the program does less work to get the same result, but when it doesn't,"}, {"start": 1273.0, "text": "it just makes the binary bigger without making it any faster."}, {"start": 1277.0, "text": "To keep that from happening,"}, {"start": 1278.0, "text": "the optimizer analyzes the function and call site"}, {"start": 1281.0, "text": "to decide whether inlining is likely to pay off,"}, {"start": 1284.0, "text": "but sometimes it makes the wrong decision,"}, {"start": 1286.0, "text": "so you might want a way to force the issue."}, {"start": 1289.0, "text": "Swift has long had an @inline(never) attribute,"}, {"start": 1291.0, "text": "that completely forbids inlining,"}, {"start": 1293.0, "text": "useful when you know that inlining the function will never be a win."}, {"start": 1297.0, "text": "In Swift 6.4, there is now a matching @inline(always) attribute"}, {"start": 1300.0, "text": "which forces the compiler to inline"}, {"start": 1302.0, "text": "even when the optimizer isn't sure it'll be a good idea."}, {"start": 1306.0, "text": "Sometimes it still won't be able to though,"}, {"start": 1308.0, "text": "like when you call an object method that might be overridden,"}, {"start": 1311.0, "text": "so consider using final with @inline(always) for methods of classes."}, {"start": 1315.0, "text": "Another important optimization is specialization"}, {"start": 1318.0, "text": "cloning a generic function for a specific concrete type,"}, {"start": 1322.0, "text": "eliminating generic overhead and often enabling further optimization."}, {"start": 1326.0, "text": "Specializing a function only helps"}, {"start": 1328.0, "text": "if the optimizer knows that you're going to use it with that type,"}, {"start": 1332.0, "text": "but sometimes, especially in libraries,"}, {"start": 1334.0, "text": "the compiler can't see how the function will be used."}, {"start": 1337.0, "text": "Swift 6.3 introduces the @specialized attribute"}, {"start": 1340.0, "text": "to give you direct control over this."}, {"start": 1343.0, "text": "Inside the attribute,"}, {"start": 1344.0, "text": "you write a where clause constraining some or all of the generic parameters"}, {"start": 1348.0, "text": "and Swift will generate a specialized version of the function"}, {"start": 1351.0, "text": "with those constraints."}, {"start": 1353.0, "text": "So if you have some slow generic code"}, {"start": 1355.0, "text": "that gets used a lot with one or two specific types,"}, {"start": 1357.0, "text": "you can let Swift know that it needs to prioritize them."}, {"start": 1360.0, "text": "But the biggest improvements we've made for performance tuning"}, {"start": 1363.0, "text": "are to the ownership system."}, {"start": 1365.0, "text": "To understand what we've done, let's start by reviewing what we already have."}, {"start": 1369.0, "text": "A lot of performance problems in Swift boil down to unnecessarily copying data."}, {"start": 1374.0, "text": "You have a piece of data in one place, you need it in another,"}, {"start": 1378.0, "text": "so you copy the data across to new storage."}, {"start": 1380.0, "text": "Sometimes these components are big,"}, {"start": 1382.0, "text": "like the model and view layers of your app, or sometimes they're small,"}, {"start": 1386.0, "text": "like the two variables on either side of a for loops in keyword,"}, {"start": 1390.0, "text": "but the basic pattern is the same."}, {"start": 1392.0, "text": "The way to solve slow-downs due to copying is to recognize that,"}, {"start": 1396.0, "text": "in certain situations, a copy is unnecessary."}, {"start": 1399.0, "text": "If you know that the storage will stay allocated,"}, {"start": 1402.0, "text": "and that both of the components using it will follow Swift's exclusivity rules"}, {"start": 1405.0, "text": "so they don't mutate data they both have access to,"}, {"start": 1408.0, "text": "then you don't need to copy the data"}, {"start": 1409.0, "text": "you just need to grant access to the existing storage."}, {"start": 1413.0, "text": "The simplest way to avoid copying is to put the data in an object"}, {"start": 1416.0, "text": "and pass that object to the other component."}, {"start": 1419.0, "text": "This is often good enough, but it doesn't entirely eliminate the problem."}, {"start": 1423.0, "text": "After all, objects are reference-counted,"}, {"start": 1425.0, "text": "and passing an object changes its reference count."}, {"start": 1428.0, "text": "Releasing and retaining an object has less overhead than copying a large value,"}, {"start": 1432.0, "text": "but it still might be too slow for the most performance-sensitive code."}, {"start": 1437.0, "text": "When objects aren't an option,"}, {"start": 1438.0, "text": "you've traditionally had to pass an UnsafePointer to the storage instead."}, {"start": 1442.0, "text": "But the problem with doing that is right in its name, UnsafePointers are unsafe."}, {"start": 1448.0, "text": "Sharing storage like this is only safe"}, {"start": 1449.0, "text": "because both components are following certain rules,"}, {"start": 1452.0, "text": "but the compiler has no idea about those rules and can't make sure"}, {"start": 1455.0, "text": "that each side will hold up its end of the bargain."}, {"start": 1458.0, "text": "Component 1 could mutate data that Component 2 expected to remain unchanged."}, {"start": 1463.0, "text": "Or it could deallocate the storage while Component 2 is still using it."}, {"start": 1467.0, "text": "You're back to a world with no memory safety, like the C languages had."}, {"start": 1471.0, "text": "So a few years ago, we started working on a better solution."}, {"start": 1475.0, "text": "We codified the set of guarantees needed to safely share storage as a borrow."}, {"start": 1480.0, "text": "As long as Component 2 is borrowing the storage,"}, {"start": 1482.0, "text": "both Components can only read it, not write it."}, {"start": 1486.0, "text": "Component 2 has to finish using the storage first,"}, {"start": 1488.0, "text": "and when it does, Component 1 regains full control."}, {"start": 1492.0, "text": "Mutation is similar,"}, {"start": 1494.0, "text": "except the other component is completely blocked from accessing the storage."}, {"start": 1497.0, "text": "This ensures that it doesn't read half-updated data or behave differently"}, {"start": 1502.0, "text": "depending on when the other component chooses to write back its changes."}, {"start": 1505.0, "text": "And whether it's borrowing or mutating, Swift can verify at compile time"}, {"start": 1509.0, "text": "that both components are following the rules."}, {"start": 1512.0, "text": "But our goal has always been to support these advanced use cases"}, {"start": 1515.0, "text": "without affecting how you write ordinary Swift code."}, {"start": 1518.0, "text": "That's required careful, incremental design of ownership features."}, {"start": 1522.0, "text": "This has been a multi-year process and it's still not over,"}, {"start": 1525.0, "text": "but this year we've taken a few more steps forward."}, {"start": 1528.0, "text": "For example, the Equatable, Comparable, and Hashable protocols"}, {"start": 1532.0, "text": "can now be used on noncopyable types."}, {"start": 1535.0, "text": "And Equatable and Comparable can also be used with non-escapable types."}, {"start": 1539.0, "text": "This lets types tuned for performance and safety"}, {"start": 1542.0, "text": "take advantage of some of the most universal capabilities"}, {"start": 1544.0, "text": "that ordinary Swift types have."}, {"start": 1546.0, "text": "Associated types can also now be non-copyable or non-escapable."}, {"start": 1550.0, "text": "This opens up powerful new capabilities"}, {"start": 1552.0, "text": "for high-performance protocol-driven development,"}, {"start": 1555.0, "text": "like the Iterable protocol seen here."}, {"start": 1557.0, "text": "Its element type is non-copyable"}, {"start": 1559.0, "text": "and its iterator type is both non-copyable and non-escapable."}, {"start": 1563.0, "text": "Of course, that doesn't mean you can't use a copyable or escapable type for these,"}, {"start": 1567.0, "text": "it just means that the protocol doesn't require it."}, {"start": 1570.0, "text": "Gosh, though, that Iterable type looks really handy."}, {"start": 1574.0, "text": "Don't you wish it were real? Well, good news, it is!"}, {"start": 1578.0, "text": "In Swift 6.4, for loops support a new Iterable protocol."}, {"start": 1582.0, "text": "The Sequence protocol we all know and love"}, {"start": 1584.0, "text": "works by copying the elements out of the sequence,"}, {"start": 1586.0, "text": "the Iterable protocol allows the for loop to borrow them instead."}, {"start": 1590.0, "text": "This means it works with non-copyable elements,"}, {"start": 1593.0, "text": "and also that it doesn't need to perform reference counting"}, {"start": 1595.0, "text": "when it's working with objects or copy-on-write types."}, {"start": 1598.0, "text": "Plus, it can optionally throw an error during the loop,"}, {"start": 1601.0, "text": "just like an ASYNC Sequence can."}, {"start": 1603.0, "text": "However, like any borrow,"}, {"start": 1605.0, "text": "exclusivity checking prohibits you from mutating the Iterable"}, {"start": 1608.0, "text": "while you're looping over it which isn't necessarily a bad thing,"}, {"start": 1611.0, "text": "since this was often a performance trap with Sequences."}, {"start": 1614.0, "text": "Because of this behavior difference,"}, {"start": 1615.0, "text": "the for loop will prefer the Sequence protocol if available,"}, {"start": 1618.0, "text": "and fall back to Iterable otherwise."}, {"start": 1621.0, "text": "Much like a Sequence, an Iterable works by creating an iterator"}, {"start": 1624.0, "text": "for the for loop to retrieve the elements from."}, {"start": 1626.0, "text": "But unlike a sequence, it retrieves elements in batches."}, {"start": 1630.0, "text": "The for loop will ask the iterator for a span of elements"}, {"start": 1633.0, "text": "and go through them one-by-one."}, {"start": 1634.0, "text": "Then ask for another span and visit those, too."}, {"start": 1637.0, "text": "When it runs out of elements, it returns an empty span,"}, {"start": 1640.0, "text": "which terminates the for loop."}, {"start": 1642.0, "text": "This batching design makes the loop a lot more efficient,"}, {"start": 1644.0, "text": "especially for types that can just return everything in one big span."}, {"start": 1648.0, "text": "Swift 6.4 also makes a major improvement to accessors."}, {"start": 1652.0, "text": "To understand why it's important, consider this UniqueBox struct."}, {"start": 1656.0, "text": "It automatically manages a pointer to a large value"}, {"start": 1660.0, "text": "and provides a computed property to access it."}, {"start": 1662.0, "text": "Unfortunately, as it's written right now,"}, {"start": 1665.0, "text": "this property has a serious performance problem."}, {"start": 1667.0, "text": "Let's see why."}, {"start": 1669.0, "text": "Suppose you put an InlineArray of 256 Ints in a UniqueBox."}, {"start": 1674.0, "text": "InlineArrays are, well, inline, so on a 64-bit device,"}, {"start": 1679.0, "text": "that's gonna be a two-kilobyte struct."}, {"start": 1681.0, "text": "Not something you want to be copying around all the time!"}, {"start": 1683.0, "text": "Which is a problem, because get and set work by copying the data."}, {"start": 1688.0, "text": "To change one Int in the array,"}, {"start": 1689.0, "text": "you have to copy the whole thing out and then back again."}, {"start": 1692.0, "text": "That's not going to help your performance very much!"}, {"start": 1696.0, "text": "Fortunately, there's now a better option,"}, {"start": 1698.0, "text": "you can switch from get and set to borrow and mutate."}, {"start": 1702.0, "text": "The new borrow accessor gives you read-only access to shared storage"}, {"start": 1705.0, "text": "without copying it,"}, {"start": 1707.0, "text": "while the mutate accessor gives you exclusive access to modify it in place."}, {"start": 1711.0, "text": "Once you've switched,"}, {"start": 1712.0, "text": "Swift can just mutate the element in the original array without copying anything."}, {"start": 1717.0, "text": "And, as a nice little bonus,"}, {"start": 1718.0, "text": "the new accessors mean UniqueBox can also handle non-copyable values."}, {"start": 1723.0, "text": "The borrow and mutate accessors are a big help for both performance and expressivity,"}, {"start": 1727.0, "text": "and we're excited they're ready for everyone to use."}, {"start": 1729.0, "text": "Gosh, though, that UniqueBox type looks really handy."}, {"start": 1733.0, "text": "Don't you wish it..."}, {"start": 1734.0, "text": "Okay, okay, you know how that ends, I won't do that spiel again."}, {"start": 1737.0, "text": "Yes, UniqueBox is a real type that's now in the standard library."}, {"start": 1742.0, "text": "There are also some other new APIs that save you from writing unsafe code,"}, {"start": 1745.0, "text": "\"Unique Array\" is a lot like an ordinary Swift Array,"}, {"start": 1748.0, "text": "except that it's non-copyable."}, {"start": 1750.0, "text": "That means you can store non-copyable elements"}, {"start": 1752.0, "text": "and avoid reference counting overhead without limiting yourself to a fixed size."}, {"start": 1756.0, "text": "The withTemporaryAllocation function uses an OutputSpan instead of an"}, {"start": 1760.0, "text": "UnsafeMutableBufferPointer to ensure that temporary memory is handled safely."}, {"start": 1765.0, "text": "The Continuation type checks at compile time that you only resume it once,"}, {"start": 1769.0, "text": "making it even safer than a CheckedContinuation"}, {"start": 1771.0, "text": "but just as efficient as an UnsafeContinuation."}, {"start": 1774.0, "text": "And there's also one more pair of types I want to tell you about,"}, {"start": 1777.0, "text": "but they're not improved versions of an existing API,"}, {"start": 1779.0, "text": "they bring new capabilities to the language."}, {"start": 1782.0, "text": "A Ref is a bit like a Span, but for one value instead of many."}, {"start": 1786.0, "text": "It's sort of like a container for a borrow or mutation,"}, {"start": 1789.0, "text": "that can be stored in variables,"}, {"start": 1791.0, "text": "passed and returned from functions, and used in generic types."}, {"start": 1795.0, "text": "You can make an instance of the Ref type from a read access by borrowing storage,"}, {"start": 1798.0, "text": "or an instance of the MutableRef type from a write access"}, {"start": 1801.0, "text": "by using the prefix ampersand."}, {"start": 1803.0, "text": "These types can be used to create new APIs that were impossible to write before,"}, {"start": 1807.0, "text": "like a method that returns a Mutable Ref for one of its properties,"}, {"start": 1811.0, "text": "but they can also be used to address performance issues."}, {"start": 1814.0, "text": "For example, consider this updateCount function."}, {"start": 1817.0, "text": "It looks up a dictionary key every time it needs to increment it,"}, {"start": 1820.0, "text": "even though the key is always the same."}, {"start": 1823.0, "text": "You usually want to hoist repeated work like that out of the loop"}, {"start": 1826.0, "text": "so you only have to do it once, but until now,"}, {"start": 1829.0, "text": "the only way to do a dictionary lookup and just sort of hold it open for a while,"}, {"start": 1833.0, "text": "was by moving the loop into a function and passing the lookup as an inout parameter."}, {"start": 1838.0, "text": "A pretty obscure trick!"}, {"start": 1841.0, "text": "MutableRef gives you a better way."}, {"start": 1843.0, "text": "Now you can make a MutableRef from the dictionary lookup once,"}, {"start": 1846.0, "text": "before the loop starts,"}, {"start": 1848.0, "text": "and then use it when you want to mutate the dictionary entry."}, {"start": 1851.0, "text": "Refs are non-escapable, so Swift knows the access ends"}, {"start": 1854.0, "text": "when the variable goes out of scope."}, {"start": 1856.0, "text": "All these new ownership features combine"}, {"start": 1859.0, "text": "to make speeding up your most performance sensitive code safer and easier than ever."}, {"start": 1864.0, "text": "The ownership system isn't the only work that's still in progress."}, {"start": 1867.0, "text": "Let's hand it back to Evan to tell you about the future of Swift."}, {"start": 1871.0, "text": "The features we covered today"}, {"start": 1873.0, "text": "were developed in open source, improving the overall experience"}, {"start": 1876.0, "text": "across the Apple OS's, Linux, Windows, and beyond."}, {"start": 1880.0, "text": "Here are some more future developments happening in the open source community"}, {"start": 1883.0, "text": "that you can get involved with."}, {"start": 1885.0, "text": "Last year,"}, {"start": 1886.0, "text": "we announced that we were open sourcing Swift Build, the build system in Xcode."}, {"start": 1891.0, "text": "Swift Build is now the default build system backend for Swift Package Manager,"}, {"start": 1895.0, "text": "improving the consistency between Swift Package builds"}, {"start": 1898.0, "text": "and what you see from Xcode."}, {"start": 1900.0, "text": "Joining the growing list of workgroups are the build and packaging workgroup,"}, {"start": 1903.0, "text": "addressing the build and packaging needs of the Swift community."}, {"start": 1907.0, "text": "The networking workgroup,"}, {"start": 1908.0, "text": "designing the next generation of cross-platform networking APIs."}, {"start": 1912.0, "text": "And the Windows workgroup, improving the Swift experience on Windows."}, {"start": 1916.0, "text": "This year,"}, {"start": 1917.0, "text": "the Android work group released the first Swift SDK for Android as part of Swift 6.3."}, {"start": 1923.0, "text": "This means it is now possible to share Swift code between Android and iOS apps."}, {"start": 1928.0, "text": "If you're interested in participating in the development of the Swift ecosystem,"}, {"start": 1932.0, "text": "please join us on the Swift forums at forums.swift.org."}, {"start": 1936.0, "text": "We would love to have your unique feedback."}, {"start": 1939.0, "text": "Thank you for following along with us today to learn more about what's new in Swift."}, {"start": 1943.0, "text": "Whether you've submitted a bug report,"}, {"start": 1945.0, "text": "posted a pull request, joined us at an event, or participated on the forums,"}, {"start": 1950.0, "text": "your contributions help shape the future of Swift"}, {"start": 1952.0, "text": "making programming safer and more approachable for everyone."}, {"start": 1956.0, "text": "Thank you!"}]}