Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Incorrect type narrowing of `for` comprehension initial accumulator

Cerrado
#15,980 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
38/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
elixir
Área
compilers

Línea de trabajo

Start by running both scripts from the issue as reduce_repro.exs and reduce_repro_1.exs to reproduce the false-positive type warnings. Trace the type handling for reduce: comprehensions in the compiler/type checker, using the gradual typing reference only to assess the documented alternative. Done means the initializer retains its input type and both examples execute without warnings while preserving their outputs.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Existing issue
  • I have searched existing issues and could not find a duplicate.
Elixir and Erlang/OTP versions

Erlang/OTP 28 [erts-16.4.0.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]

Elixir 1.21.0-dev (7a40579)

Operating system

any

Current behavior

The current implementation types the initializer with the expected type of the comprehension result. An initializer is always evaluated but its value may never reach the final reduction result.

Repro:
save this as reduce_repro.exs and execute

    defmodule ReduceRepro do
      def calculate(initial) do
        (for _ <- [1], reduce: initial do
           _ -> 1
         end) + 1
      end

      def run, do: calculate(:old)
    end

    IO.inspect(ReduceRepro.run())

Result:
the code works fine and prints 2 but emits a false positive warning:

    warning: incompatible types given to calculate/1:

        calculate(:old)

    given types:

        :old

    but expected one of:

        float() or integer()

    type warning found at:
    │
  8 │       def run, do: calculate(:old)
    │                    ~
    │
    └─ reduce_repro.exs:8:20: ReduceRepro.run/0

another example:

defmodule ReduceRepro1 do
    def original(initial) do
      :ok =
        for _ <- [1], reduce: initial do
          _ -> :ok
        end

      case initial do
        :old -> :kept
        _ -> :other
      end
    end
end

IO.inspect(ReduceRepro1.original(:old))

result: code prints kept and warns

    warning: the following clause will never match:

        :old ->

    because it attempts to match on the result of:

        initial

    which has type:

        dynamic(:ok)

    type warning found at:
    │
 17 │         :old -> :kept
    │         ~~~~~~~~~~~~~
    │
    └─ reduce_repro_1.exs:17: ReduceRepro1.original/1

initial is incorrectly narrowed to dynamic(:ok)

I believe this is a separate problem from https://github.com/elixir-lang/elixir/issues/15451 - covers refinements inside conditional code branches

Expected behavior

Initializer type should not be narrowed. Precise typing is probably not possible as the reducer callback is not guaranteed to execute (as in #15451).
Alternatively, if the behaviour is intended it should be documented in https://github.com/elixir-lang/elixir/blob/main/lib/elixir/pages/references/gradual-set-theoretic-types.md#false-positives

Lenguaje dominante
Elixir
Estrellas
26.7k
Forks
3.7k
Merge medio
8 h 8 min
PR fusionados (30 d)
61

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de elixir-lang/elixir

Todos los issues de elixir-lang/elixir

Issues similares

Más issues de Elixir

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.