Futhark admite que el aliasing en su sistema de tipos es más complejo de lo que pensaba
El autor del lenguaje explica por qué una notación ambigua con asteriscos ha destapado problemas de fondo en el seguimiento de alias, y avisa de que arreglarlo rompe código.
Futhark tiene un problema con el aliasing y su responsable lo ha puesto por escrito. El sistema de tipos del lenguaje, orientado a computación paralela de alto rendimiento, hace un seguimiento de qué variables comparten memoria para garantizar que las actualizaciones in situ son seguras. Ese mecanismo, que en principio parecía un detalle fácil de arreglar, ha acabado poniendo en cuestión decisiones de diseño que el lenguaje arrastra desde el principio. El propio autor lo resume sin rodeos: salvo que haya una razón de peso para meterse en esa pelea, mejor no hacerlo, porque la explosión de complejidad no es pequeña.
La característica que lo provoca son las actualizaciones in situ. Futhark permite escribir A with [i] = v y obtener una copia semántica del array con el elemento i sustituido, pero con la garantía de que el coste es proporcional a un elemento y no al array entero. La implementación obvia es escribir de forma destructiva sobre la memoria donde vive A, y para que eso no se note el comprobador de tipos tiene que asegurarse de que el valor antiguo no se usa en ningún camino de ejecución posterior. A eso se le llama consumir A.
El problema es que no basta con vigilar A. Cualquier variable que comparta memoria con ella, sus alias, hay que consumirla también: después de let B = A, B y A son alias. En la práctica cada variable lleva asociado un conjunto de alias que las reglas del lenguaje van construyendo expresión a expresión. Los condicionales son el caso incómodo. Tras let C = if ... then A else B, C se considera alias de A y de B aunque en tiempo de ejecución solo se cumpla una de las dos ramas. Es conservador, pero rechazar un programa al compilar es molesto y dejar pasar un valor ya consumido sería mucho peor.
Funciones y asteriscos
Las funciones añaden otra capa. Para que una función pueda consumir un parámetro hay que avisar en su tipo, con algo parecido a un efecto: *a -> b consume, a -> b observa. Los autores lo llaman la dieta de la función. Como Futhark es currificado, la idea se generaliza sin esfuerzo: a -> *b -> c consume el segundo argumento y no el primero.
Falta decidir qué alias hereda el resultado de aplicar una función. La regla sencilla, que herede los de todos los argumentos no consumidos, propaga los alias demasiado rápido y es más conservadora de lo necesario, porque casi todas las funciones devuelven valores recién construidos. Por eso el tipo de retorno puede marcar si el resultado es fresco o no, y vuelve a usar un asterisco: a -> *b frente a a -> b. El asterisco de un parámetro y el de un retorno significan cosas distintas, lo que no ayuda a leer el código. El análisis remite a dos incidencias abiertas en el repositorio, la 1675 y la 2531.
El texto es continuación del que describía los planes para la versión 1.0, y deja una lección que vale más allá de Futhark: se puede diseñar un sistema donde las reglas de consumo y alias sean locales, sin analizar el programa entero, y aun así acabar con un rompecabezas difícil de sostener. Mantener esa localidad mientras se corrigen los asteriscos es la parte que queda por resolver.
