← Todos los articulos

Lo que dijo el equipo de Swift de Apple en el lab de la WWDC26

Apple publicó el Swift Group Lab de la WWDC26 como una hora de preguntas y respuestas sin guion con cuatro ingenieros de los equipos de Swift, Foundation y redes de servidor, y luego lo lanzó sin subtítulos.1 Pasamos el video por una transcripción local para leer lo que realmente dijeron. Las sesiones pulidas te explican qué hace una función. El lab es donde Holly admite que se equivocó en una decisión central de concurrencia, donde Corey explica el patrón de limpieza que falla en silencio dentro de código cancelado, y donde el panel repite una y otra vez un consejo que el marketing nunca dará: deja de coleccionar funciones del lenguaje. La versión franca vive aquí.

Una nota sobre las fuentes: Apple no publicó ninguna transcripción oficial del lab. Cada cita que aparece abajo es una paráfrasis de una transcripción local del video publicado, con marcas de tiempo aproximadas. A quienes hablan se les identifica por su nombre de pila y su equipo, tal como los da la transcripción: Holly (equipo del lenguaje Swift, genéricos y concurrencia), Corey (equipo de redes de servidor de Swift), Tony (Foundation y biblioteca estándar) y Doug (equipo del lenguaje Swift).1

TL;DR

  • Holly dijo que, si el equipo diseñara la concurrencia de Swift hoy, las funciones async nonisolated se ejecutarían en el contexto de quien las llama desde el primer día. Sostuvo la creencia opuesta «durante muchísimo tiempo» y cambió de opinión ante la evidencia del mundo real. Swift 6.2 convirtió el contexto del llamador en el comportamiento estándar por defecto.1
  • El consejo repetido: haz que tus tipos sean no-Sendable a propósito. ~Sendable (SE-0518, implementado en Swift 6.4) ofrece una escritura más limpia, y Foundation está reanotando los tipos que había marcado como fuera de límites, con la instancia global de UserDefaults ganando conformidad con Sendable.21
  • El patrón de limpieza asíncrona de Corey: los contextos cancelados saltan en silencio la limpieza asíncrona, así que audita cada async defer en busca de llamadas await que suspendan y envuélvelas en un escudo de cancelación. Tanto SE-0493 (defer async) como SE-0504 (withTaskCancellationShield) llegan en Swift 6.4.34
  • Franqueza sobre la hoja de ruta: el tipo Disconnected es una propuesta activa en los foros, las conformidades de tuplas están «casi listas» pero formalmente han vuelto a revisión, UniqueArray está aceptado en principio, Subprocess 1.0 se está lanzando y SwiftPM se está unificando en torno a Swift Build.5678
  • El tema recurrente del panel: «las funciones del lenguaje no son objetos de colección». Perfila primero, adopta la herramienta concreta que te señale el perfilador y deja el resto en paz.1

La decisión de concurrencia que Apple tomaría de otra manera

Ver: Swift Group Lab (WWDC26)

La retrospectiva de Holly sobre la concurrencia empieza alrededor de las 33:42. El lab completo no tiene subtítulos oficiales; la transcripción de abajo proviene de un ASR local.

Un desarrollador le hizo al panel una pregunta que las sesiones pulidas rara vez invitan: ahora que la concurrencia de Swift 6 lleva en el terreno el tiempo suficiente para observar su adopción, ¿hay algo que el equipo diseñaría de otra manera hoy? Holly respondió sin rodeos. Sí, sin duda.

El arrepentimiento concreto tiene que ver con dónde se ejecuta una función async nonisolated. Dos propuestas de Swift Evolution movieron ese comportamiento en direcciones opuestas. La primera hacía que las funciones async nonisolated saltaran siempre al pool de hilos concurrente global. La posterior, en Swift 6.2, hacía que se quedaran en el contexto que las había llamado, de modo que una función invocada desde el main actor se queda en el main actor.1 Holly rastreó el cambio de rumbo hasta la evidencia de personas que ejecutaban los primeros indicadores de comprobación de concurrencia en apps y bibliotecas reales: pasaban tipos no-Sendable de un lado a otro entre un contexto aislado por un actor y estas funciones async nonisolated, y el comportamiento por defecto del pool global producía errores de carrera de datos, porque el actor original todavía retenía esos valores mientras la función async se ejecutaba en otro sitio.1

Luego viene la parte que no aparece en ninguna grabación de sesión. «Mantuve durante muchísimo tiempo la creencia de que ejecutar en el pool de hilos concurrente global era el modelo correcto por sus beneficios a largo plazo —dijo Holly—, pero con el tiempo me convencieron los problemas que surgían en proyectos del mundo real» (paráfrasis del ASR, ~35:50).1 Doug presentó la decisión original como una apuesta defendible a escala de todo el sistema: más concurrencia disponible significa más paralelismo potencial, lo que puede significar mejor rendimiento. El costo solo salió a la luz una vez que la gente usó el modelo de seguridad completo, y empujaba demasiados tipos hacia Sendable, algo que Doug calificó de «no la manera natural de expresar todas estas ideas».1 El contexto del llamador por defecto resulta más accesible porque se comporta como código no concurrente hasta que optas explícitamente por el paralelismo. Si adoptaste Swift 6.2 y te preguntaste por qué la historia de la concurrencia se sentía de pronto más tranquila, la respuesta está en que las personas que la diseñaron admitieron que el primer valor por defecto era el equivocado y entregaron la corrección.

Haz que tus tipos sean no-Sendable a propósito

El consejo más contraintuitivo del lab va en contra de dos años de hábitos de migración. Holly dijo que se encuentra constantemente con desarrolladores que preguntan cómo hacer que sus tipos sean Sendable, cuando a menudo la mejor pregunta es la contraria: ¿debería este tipo ser no-Sendable?1 Para los tipos efímeros que se usan dentro de un único cálculo, marcarlos explícitamente como no-Sendable produce un modelo de datos más limpio y una línea más nítida entre lo que pretendes pasar a través de los límites de aislamiento y lo que no. También ayuda al rendimiento, porque el costo de pasar un tipo de un lado a otro es uno que quieres evitar pagar en valores intermedios que nunca necesitaron viajar.1

Swift 6.4 le da a esa intención una escritura de verdad. ~Sendable (SE-0518) te permite suprimir la conformidad directamente, igual que ~Copyable suprime la copiabilidad, en lugar de escribir una conformidad no disponible.2 Holly trazó la distinción con precisión: una conformidad Sendable no disponible declara que el tipo y cada subclase definitivamente no son sendable y propaga eso por toda la jerarquía, mientras que ~Sendable es simplemente la ausencia de una conformidad, de modo que una subclase que no añade estado mutable aún puede añadir su propia conformidad con Sendable.21

Esa flexibilidad es justo lo que Foundation necesitaba. Tony explicó la tercera categoría que surgió de la auditoría Sendable original de Foundation: clases donde la superclase es segura, pero una subclase podría no serlo. Su ejemplo fue NSString, que es inmutable y sendable, frente a NSMutableString, que es una subclase mutable y no lo es.1 En lugar de apresurar una anotación equivocada, Foundation marcó las clases ambiguas como no-Sendable y esperó. Ahora, dijo Tony en el lab, el equipo está usando la anotación de Swift 6.4 para reanotar esos tipos con precisión, y espera que el UserDefaults global estándar gane una conformidad con Sendable.1 Toma la conformidad de UserDefaults y la reanotación más amplia de Foundation como atribuidas al lab: Tony declaró ambas en las preguntas y respuestas, y no son funciones que yo pueda confirmar de forma independiente a partir de una propuesta publicada. La advertencia permanente del panel también aplica aquí, de parte de Tony: no eches mano de @unchecked Sendable para forzar el modo Swift 6, porque cada anotación unchecked descarta la seguridad que el compilador podría haber demostrado por ti.1

Limpieza asíncrona, hecha de modo que realmente se ejecute

Corey se hace cargo de la corrección más práctica del lab, y es la clase de error que lanzas sin darte cuenta. La victoria emblemática de la concurrencia estructurada es la propagación automática de la cancelación: cancela una tarea y todo lo que se haya generado a su servicio se cancela también, que es lo que quieres cuando se cierra una vista o un cliente se desconecta.1 La trampa está en la limpieza. Podrías tener un archivo escrito a medias que necesita volcarse a un estado correcto conocido, o una transacción de base de datos que revertir, y esa limpieza es asíncrona en sí misma. Como lo planteó Corey, la mayor parte del código Swift se niega a ejecutarse en un contexto cancelado porque asume que debería deshacerse lo más rápido posible, así que la limpieza asíncrona que corre dentro de una tarea cancelada puede dejar de hacer su trabajo sin que se note.1

La solución es un escudo de cancelación, y se empareja directamente con el defer async. SE-0493 permite que un bloque defer contenga llamadas await, y llega en Swift 6.4.3 SE-0504 añade withTaskCancellationShield, también en Swift 6.4, que ejecuta un bloque como si no se hubiera solicitado la cancelación, para que la limpieza que suspende llegue hasta el final.4 La receta de auditoría de Corey es concreta: mira cada bloque async defer y pregúntate si alguno de los await que contiene va a suspender de verdad. Si uno lo hace, envuélvelo en un escudo de cancelación.1 Llamó a los dos «un gran compañero» y «un muy buen uno-dos para dejar tus recursos bien limpios».1 Los tipos no-Sendable refuerzan la misma disciplina, señaló Corey, porque un valor que no puede cruzar dominios de concurrencia obliga a que tu flujo de control asíncrono se mantenga lineal y fácil de razonar.1

El consejo más amplio de Corey sobre la concurrencia estructurada redondea la sección. Apóyate en ella con firmeza, porque son las vías de escape las que causan problemas. Evita las tareas no estructuradas (Task.detached o un Task pelado) «casi a cualquier costo», salvo que estés enviando trabajo a otro sitio de forma deliberada, y nunca en el flujo principal. Haz de los grupos de tareas tu opción por defecto, ajusta los ciclos de vida de los objetos a su ámbito léxico y escribe código asíncrono lineal: una receta de paso A, luego B, luego C, y echa mano del paralelismo dentro de los grupos de tareas solo cuando el trabajo se ramifique de verdad.1

Franqueza sobre la hoja de ruta

El lab es también donde el panel separa las funciones ya lanzadas de las optimistas, y la brecha importa cuando estás decidiendo sobre qué construir.

La cuestión de almacenar un valor no-Sendable transferido tiene una respuesta real en camino. Hoy transfieres con la palabra clave sending y el aislamiento basado en regiones deja que el compilador demuestre que el dueño original liberó el acceso, pero si necesitas almacenar un valor así, solo funcionan las exclusiones inseguras.1 Holly señaló Disconnected, una propuesta activa en los foros para un tipo que preserva la propiedad de transferencia a través del almacenamiento, de modo que puedas guardar un valor y entregarlo más tarde. Se está diseñando y discutiendo ahora mismo, no está implementado.51

Las conformidades de tuplas son el ejemplo más nítido del optimismo de un ingeniero frente al estatus formal. Cuando le preguntaron qué falta antes de que las tuplas se conformen condicionalmente a Equatable, Hashable y Comparable, Holly explicó que es una evolución de los paquetes de parámetros: el lenguaje necesita sintaxis para escribir una extensión sobre una tupla cuyos tipos de elementos sean un paquete de parámetros, con una cláusula where que exija que cada elemento se conforme.1 Dijo que una implementación experimental vive en el repositorio del compilador y está «casi del todo lista».1 El registro formal es más cauto. SE-0283, la propuesta original de conformidades de tuplas, se devolvió a revisión y su implementación de 2020 se revirtió; el enfoque general de paquetes de parámetros existe hoy solo detrás de un indicador experimental del compilador, TupleConformances.10 Lee el «casi lista» de Holly como la lectura honesta de una ingeniera sobre la implementación, no como una función ya lanzada.

Los contenedores de rendimiento están más avanzados. UniqueArray, que mencionó Tony, viene de SE-0527 («RigidArray and UniqueArray»), ahora aceptado en principio, que introduce un nuevo módulo Containers en la biblioteca estándar; ya se incluye en una forma temprana en swift-collections 1.3.7 Tony lo presentó como la mejora para un Array cuyo tráfico de retain/release por copy-on-write aparece en una traza de Instruments.1 Subprocess, la API de procesos multiplataforma y de código abierto que Tony nombró como su favorita, lanza la versión 1.0 este año; el hito 1.0 está anunciado, con la última etiqueta publicada todavía en la 0.5, así que se está lanzando más que lanzado.61 En cuanto a las herramientas, Holly describió el cambio de SwiftPM que los desarrolladores quizá no noten: las compilaciones de paquetes de Xcode y las de la cadena de herramientas de código abierto ahora comparten una sola implementación, Swift Build, que se está convirtiendo en el backend del sistema de compilación por defecto (por defecto en main, apuntando a 6.4).81

Por último, la ruta de migración con la que Holly empezó: @diagnose, el nuevo atributo de SE-0522 («Source-Level Control Over Compiler Warnings»), aceptado.9 Da control de las advertencias a nivel del código fuente, de modo que puedes suprimir avisos de obsolescencia en una región u optar por advertencias desactivadas por defecto, como la seguridad de memoria estricta o la concurrencia estricta, en las áreas que más importan, lo que lo convierte en una herramienta más fina para una migración por etapas a Swift 6.1

Guía de los ingenieros, recopilada

El valor del lab está en los consejos de profesionales acumulados que nunca caben en la duración de una sesión. Lo más destacado, atribuido:

  • Escribe código asíncrono lineal. Corey: evita las tareas no estructuradas casi a cualquier costo, mantén cada tarea como una receta secuencial e introduce el paralelismo solo dentro de los grupos de tareas cuando el trabajo se ramifique de verdad.1
  • Una receta de migración a MainActor. Holly: empieza por los tipos hoja y avanza hacia afuera, o activa el main-actor-by-default para un módulo que deba estar por completo en el main actor y anota explícitamente las partes descargadas. Marca como nonisolated los métodos que no tocan ningún estado mutable, y convierte en let una static var que en realidad nunca se muta para que pueda seguir siendo nonisolated.1
  • Los costos de conformidad son desiguales. Doug: una conformidad Equatable o Hashable sin usar conserva su código de testigo (witness) en el binario, porque una conversión as? a un existencial en tiempo de ejecución puede descubrirla, así que cuesta tamaño de código; Sendable es una etiqueta puramente de tiempo de compilación sin representación en tiempo de ejecución, de modo que una conformidad Sendable sin usar es gratis.1
  • La combinación de @inlinable con @inline(never). El truco favorito de Corey: @inlinable expone el cuerpo de una función más allá de los límites del módulo y desbloquea la especialización genérica y la propagación de efectos, mientras que @inline(never) evita que una ruta fría y cargada de código (una copia de respaldo byte a byte) se inserte en línea, para que la ruta caliente siga siendo rápida. Ha usado la pareja «tres veces en todo el portafolio de redes de Swift», para problemas inusuales de rendimiento en rutas frías.1
  • Optimiza la ruta más caliente, no el proyecto. Corey: «Hemos tenido un gran éxito introduciendo spans y un par de unique arrays justo a lo largo de la ruta más caliente», lo que entrega casi todas las ganancias de rendimiento con un cambio pequeño y respaldado por el compilador. Mantén los nuevos tipos de rendimiento aislados para que adoptarlos nunca obligue a una refactorización gigantesca.1
  • Deja de coleccionar funciones. La frase recurrente del panel, de un amigo que citó Corey: «las funciones del lenguaje no son objetos de colección». No ganas ningún premio por usarlas todas. Perfila primero, echa mano de la herramienta concreta que te señale el perfilador (tipos no copiables, UniqueArray, Span) y dedica el resto de tus horas a corregir errores y a las funciones.1

Preguntas frecuentes

¿De verdad Apple publicó el lab de Swift de la WWDC26 sin subtítulos?

Sí. Apple subió el Swift Group Lab (sesión 8001) como un video sin transcripción ni subtítulos oficiales en el sitio de desarrolladores.1 Para citarlo con exactitud, pasé la grabación por una transcripción local, así que cada cita de este artículo es una paráfrasis de ese ASR local, con marcas de tiempo aproximadas, atribuida por nombre de pila y por equipo.1

¿Qué dijo el equipo de Swift que cambiaría sobre la concurrencia?

Holly dijo que, si Apple diseñara la concurrencia de Swift hoy, las funciones async nonisolated se ejecutarían en el contexto del llamador desde el principio en lugar de saltar al pool de hilos concurrente global. Sostuvo durante mucho tiempo la creencia del pool global y cambió de opinión ante la evidencia del mundo real, y Swift 6.2 convirtió el comportamiento del contexto del llamador en el predeterminado.1

¿Debería hacer que mis tipos de Swift sean Sendable o no-Sendable?

El consejo del lab es hacer que los tipos de cálculo efímeros sean no-Sendable a propósito. Swift 6.4 añade para ello la escritura ~Sendable (SE-0518), distinta de una conformidad no disponible, porque las subclases aún pueden añadir Sendable cuando no añaden estado mutable.2 Tony dijo que Foundation está reanotando sus clases ambiguas con la nueva función y espera que el UserDefaults global gane una conformidad con Sendable, ambas atribuidas al lab.1

¿Cómo me aseguro de que la limpieza asíncrona se ejecute cuando se cancela una tarea?

Los contextos cancelados hacen que la mayor parte del código Swift salte el trabajo que suspende, así que la limpieza asíncrona puede fallar en silencio. El patrón de Corey es auditar cada async defer en busca de llamadas await que suspendan de verdad y envolverlas en un escudo de cancelación. El defer async (SE-0493) y withTaskCancellationShield (SE-0504) llegan ambos en Swift 6.4.341

¿Las conformidades de tuplas se están lanzando en Swift?

Todavía no. SE-0283 se devolvió a revisión y su implementación original se revirtió; el enfoque general de paquetes de parámetros existe solo detrás de un indicador experimental TupleConformances. Holly dijo en el lab que una implementación experimental en el compilador está «casi del todo lista», lo que refleja el optimismo de una ingeniera más que una función ya lanzada.1


El lab es el compañero franco de los anuncios: para las funciones ya lanzadas en contexto, lee las novedades de Swift 2026, y para la mecánica de migración detrás del contexto del llamador por defecto del que habló Holly, mira la concurrencia de Swift 6.2 en la práctica. La filosofía del panel —«perfila primero, adopta la herramienta concreta»— se extiende a las pruebas en Swift Testing frente a XCTest. Toda la cobertura de la WWDC26 vive en la serie Apple Ecosystem.

Referencias


  1. Apple, WWDC 2026 session 8001, Swift Group Lab. Apple published no official transcript or captions for this lab; all quotes attributed to it are paraphrases from a local transcription of the published video, with approximate timestamps. Source for the concurrency retrospective (Holly, ~33:42), the make-types-non-Sendable guidance, the Foundation re-annotation and UserDefaults Sendable conformance (both lab-attributed to Tony), the async-cleanup and cancellation-shield pattern (Corey), the structured-concurrency and MainActor migration advice (Corey and Holly), the conformance-cost explanation (Doug), the @inlinable plus @inline(never) combo and hottest-path performance guidance (Corey), the Disconnected, tuple-conformance, UniqueArray, Subprocess, SwiftPM, and @diagnose remarks, and the “language features aren’t collectibles” theme. 

  2. Apple / Swift Evolution, SE-0518, ~Sendable for explicitly marking non-Sendable types. Status: Implemented (Swift 6.4). Source for suppressing the Sendable conformance and the distinction from an unavailable conformance. 

  3. Apple / Swift Evolution, SE-0493, Support async calls in defer bodies. Status: Implemented (Swift 6.4). Source for await inside defer blocks. 

  4. Apple / Swift Evolution, SE-0504, Task cancellation shields. Status: Implemented (Swift 6.4). Source for withTaskCancellationShield

  5. Swift Forums, Pitch: Disconnected type for modeling disconnected values. Active forums pitch for safely storing transferred non-Sendable values; not implemented. 

  6. Apple / Swift, Subprocess — cross-platform, open-source process API announced in 2025; version 1.0 announced as releasing this year, with the latest published tag at 0.5. Status per the lab and the project’s published releases. 

  7. Apple / Swift Evolution, SE-0527, RigidArray and UniqueArray. Status: Accepted in Principle; introduces a new standard-library Containers module and ships in an early form in swift-collections 1.3. 

  8. Swift Forums, SwiftPM development update: default build system change. Swift Build is becoming the default SwiftPM build-system backend (default on main, targeting 6.4). 

  9. Apple / Swift Evolution, SE-0522, Source-Level Control Over Compiler Warnings. Status: Accepted. Source for the @diagnose attribute and region-scoped warning control. 

  10. Apple / Swift Evolution, SE-0283, Tuples Conform to Equatable, Comparable, and Hashable. Status: Returned for revision; original implementation reverted. Source for the formal status of tuple conformances against the experimental TupleConformances flag. 

Artículos relacionados

What's New in Swift (2026): The WWDC26 Update

Swift 6.3 and 6.4 from WWDC26: anyAppleOS availability, module selectors, borrow/mutate accessors, the Iterable protocol…

19 min de lectura

Lo que dijo el equipo de rendimiento de Apple en el lab de la WWDC26

El equipo de Power & Performance de Apple respondió en vivo a las preguntas de los desarrolladores en la WWDC26. Guía de…

14 min de lectura

Ingeniería de bucles: los bucles ganan donde verificar es barato

La ingeniería de bucles, contrastada con las transcripciones completas de Boris Cherny: cada bucle que menciona tiene un…

18 min de lectura