Incorrect type narrowing of `for` comprehension initial accumulator
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
调研方向
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.
由索引模型根据 Issue 内容生成。
描述
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
- 主要语言
- Elixir
- 星标
- 26.7k
- 派生
- 3.7k
- 平均合并
- 8 小时 7 分钟
- 30 天内合并 PR
- 60
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
elixir-lang/elixir 的其他 Issue
-
Mixed type comprehension target narrows list elements to bitstrings可能重新可做 关联的 PR 已关闭且未合并。 未关闭
难度 4/5 3-5 天 新手友好度 55/100
elixir-lang/elixir#15950 · 2 条评论 ·
维护者通常 1 天内回复
-
map_(get|put|update) ignore atom fields with static term() key可能已有人在做 @lukaszsamson 于 19 天前认领。 未关闭
难度 4/5 3-5 天 新手友好度 45/100
elixir-lang/elixir#15932 ·
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 55/100
elixir-lang/elixir#15909 ·
维护者通常 1 天内回复
-
难度 3/5 1-2 天 新手友好度 64/100
elixir-lang/elixir#15900 ·
维护者通常 1 天内回复
-
Gradual map domain with `none` looses static part when computing lower bound可能已有人在做 @lukaszsamson 于 37 天前认领。 未关闭
难度 4/5 3-5 天 新手友好度 48/100
elixir-lang/elixir#15854 · 2 条评论 ·
维护者通常 1 天内回复
查看 elixir-lang/elixir 的全部 Issue
相似的 Issue
-
github_actions
难度 1/5 1 小时以内 新手友好度 94/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
team-alembic/clarity#146 ·
-
难度 2/5 1-3 小时 新手友好度 68/100
etalab/schema-irve#83 ·
-
难度 2/5 1-3 小时 新手友好度 75/100
ash-project/ash_ai#249 · 1 条评论 ·
维护者通常 1 天内回复
-
marketing v9
难度 2/5 1-3 小时 新手友好度 75/100
revelrylabs/harmonium#715 ·
维护者通常 1 天内回复