Embedded Swift — это подмножество Swift, предназначенное для работы с низким потреблением ресурсов, что позволяет ему работать в ограниченных средах, таких как микроконтроллеры. Используя специальный режим компиляции, Embedded Swift создает значительно меньшие исполняемые файлы по сравнению с обычным Swift. Хотя это и подмножество полного языка, подавляющее большинство возможностей Swift работает в Embedded Swift точно так же. Дополнительная информация описана в документе «Видение Embedded Swift».
Embedded Swift быстро развивается. После наших обновлений об улучшениях Embedded Swift в Swift 6.3 в конце прошлого года, этот пост описывает ряд дополнительных улучшений, сделанных в предстоящем выпуске Swift 6.4. Вы можете опробовать их уже сегодня, используя снапшот разработки Swift.
Улучшения языка
Embedded Swift продолжает расширять свое подмножество языка, включая все больше аспектов «полного» Swift, что упрощает обеспечение совместимости существующих кодовых баз Swift с Embedded Swift. Многие из этих функций имеют динамический аспект, что означает их влияние на производительность во время выполнения (например, из-за косвенных вызовов) и размер кода (из-за необходимости дополнительных метаданных). Однако это влияние проявляется только там, где эти динамические функции языка действительно используются: код, критически важный к размеру и производительности, может избегать их, например, включив предупреждения в группе диагностики PerformanceHints.
Обобщенная поддержка экзистенциальных (any) типов
Ранее Embedded Swift поддерживал только экзистенциальные (any) типы, имеющие ограничение AnyObject, то есть они могли использоваться только с экземплярами классов. Теперь все any-типы доступны в Embedded Swift, включая сам тип Any. Например:
protocol P { func method() } extension Int: P { func method() { print("\(self) здесь") } } let a: any P = 17 a.method() // выводит "17 здесь"
Модель компиляции обобщений в Embedded Swift, которая требует, чтобы все обобщенные функции и типы в конечном итоге были специализированы, накладывает некоторые ограничения на использование any-типов. В частности, обобщенную функцию нельзя вызвать для any-типа:
extension P { func genericMethod<T: P>(_ other: T) { ... } } let a: any P = 17 a.genericMethod(a) // ошибка: невозможно использовать обобщенный метод экземпляра 'genericMethod' для значения типа 'any P' в Embedded Swift
Нетипизированные throws
Ранее Embedded Swift разрешал выбрасывать только конкретные типы ошибок, например:
func parseRecord() throws(ParsingError) -> Record { ... }
«Нетипизированные» throws, которые могут выбрасывать любой экземпляр, соответствующий протоколу Error, ранее были запрещены в Embedded Swift:
func loadImage() throws -> Image { ... } // ранее было запрещено в Embedded Swift
Нетипизированные throws эквивалентны выбрасыванию значения типа any Error. С обобщением any-типов Embedded Swift теперь полностью поддерживает нетипизированные throws. Выбрасывание значения any Error обычно требует выделения памяти в куче, поэтому для кодовых баз, желающих избежать выделений в куче, предпочтение следует отдавать типизированным throws.
Метатипы
Ранее Embedded Swift допускал метатипы (например, Int.self) только в очень узких местах, например, при использовании их для указания типов аргументов в обобщенных функциях:
rawPointer.bindMemory(to: Value.self, capacity: 1)
Swift 6.4 вводит полную поддержку метатипов в Embedded Swift: можно создавать и использовать экземпляры метатипов, включая экзистенциальные типы, такие как any (DefaultInitializable.Type). Например, теперь это разрешено и работает так же, как в полном Swift:
protocol DefaultInitializable { init() } extension Int: DefaultInitializable { } let factory: any (DefaultInitializable.Type) = Int.self let aValue: any DefaultInitializable = factory.init()
Улучшения библиотек
Дополнительные возможности из стандартной библиотеки Swift и связанных с ней библиотек из полного Swift теперь доступны в Embedded Swift.
Разбор чисел с плавающей запятой
Значения чисел с плавающей запятой Swift можно анализировать из строки, например:
let inputText: String = getInputText() if let value = Double(inputText) { // value имеет тип Double }
В рамках перереализации этой функциональности на Swift эти API для разбора чисел с плавающей запятой теперь также доступны в Embedded Swift.
Обработка ошибок в параллелизме
Библиотека параллелизма Embedded Swift теперь поддерживает операции с выбрасыванием ошибок, такие как выбрасывающие задачи и группы задач. Например:
let task = Task { if badThing { throw MyError.badThingHappened } return "ok" } print(try await task.value)
Попробуйте!
Поддержка Embedded Swift доступна в снапшотах разработки Swift. Лучший способ начать работу — через примеры в репозитории Swift Embedded Examples, который содержит ряд примеров проектов для сборки и запуска кода Embedded Swift на различном оборудовании.
Если у вас есть вопросы по описанным здесь улучшениям или вы хотите обсудить свою собственную работу с Embedded Swift, мы приглашаем вас присоединиться к обсуждению на форумах Swift. Вы можете задать вопросы по этому посту в соответствующей теме и поделиться своим опытом в категории Embedded Swift.

