diff --git a/lib/elixir/lib/module/types/descr.ex b/lib/elixir/lib/module/types/descr.ex index bbef71f22a..9ad6f166c3 100644 --- a/lib/elixir/lib/module/types/descr.ex +++ b/lib/elixir/lib/module/types/descr.ex @@ -5850,8 +5850,14 @@ defmodule Module.Types.Descr do def tuple_insert_at(descr, index, type) when is_integer(index) and index >= 0 do case :maps.take(:dynamic, unfold(type)) do - :error -> tuple_insert_at_checked(descr, index, type) - {dynamic, _static} -> dynamic(tuple_insert_at_checked(descr, index, dynamic)) + :error -> + tuple_insert_at_checked(descr, index, type) + + {dynamic_type, _static} -> + case tuple_insert_at_checked(descr, index, dynamic_type) do + atom when atom in [:badtuple, :badindex] -> atom + result -> dynamic(result) + end end end diff --git a/lib/elixir/test/elixir/module/types/descr_test.exs b/lib/elixir/test/elixir/module/types/descr_test.exs index 53c49536b7..d7e3357d14 100644 --- a/lib/elixir/test/elixir/module/types/descr_test.exs +++ b/lib/elixir/test/elixir/module/types/descr_test.exs @@ -1881,6 +1881,10 @@ defmodule Module.Types.DescrTest do assert dynamic(union(tuple(), integer())) |> tuple_insert_at(1, boolean()) |> equal?(dynamic(open_tuple([term(), boolean()]))) + + # Errors must propagate even when the inserted value is dynamic + assert tuple_insert_at(integer(), 0, dynamic()) == :badtuple + assert tuple_insert_at(tuple([atom([:ok])]), 2, dynamic()) == :badindex end test "tuple_values" do