Existing issue
Elixir and Erlang/OTP versions
Erlang/OTP 28 [erts-16.1.1] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]
Elixir 1.20.0-rc.5 (383ffc5) (compiled with Erlang/OTP 28)
Operating system
Linux / macOS
Current behavior
On current main (b58e84352), the behaviour of try’s diagnostics changed; once one try alternative sets context.failed, later independent alternatives stop reporting diagnostics:
1. Two rescue bodies with independent bad calls:
defmodule A1R1 do
def f do
try do
raise "oops"
rescue
_ in RuntimeError -> String.length(1)
_ in ArgumentError -> String.length(2)
end
end
end
v1.19.5 (d33fd8e41):
Current main / v1.20 RC (b58e84352):
warning: incompatible types given to String.length/1:
String.length(1)
given types:
-integer()-
but expected one of:
binary()
└─ a1_r1.ex:6:35: A1R1.f/0
2. Failed rescue body followed by undefined exception head:
defmodule A1R2 do
def f do
try do
raise "oops"
rescue
_ in RuntimeError -> String.length(1)
e in UnknownError -> e
end
end
end
v1.19.5 (d33fd8e41):
warning: struct UnknownError is undefined (module UnknownError is not available or is yet to be defined). Make sure the module name is correct and has been specified in full (or that an alias has been defined)
└─ a1_r2.ex:7:9: A1R2.f/0
Current main / v1.20 RC (b58e84352):
warning: incompatible types given to String.length/1:
String.length(1)
given types:
-integer()-
but expected one of:
binary()
└─ a1_r2.ex:6:35: A1R2.f/0
3. Failed rescue body before catch body:
defmodule A1R3 do
def f do
try do
throw(:x)
rescue
_ in RuntimeError -> String.length(1)
catch
:throw, :x -> Integer.to_string(:atom)
end
end
end
v1.19.5 (d33fd8e41):
warning: the call to integer_to_binary/1 will fail with a 'badarg' exception
└─ a1_r3.ex:8:29
warning: incompatible types given to Integer.to_string/1:
Integer.to_string(:atom)
given types:
-:atom-
but expected one of:
integer()
└─ a1_r3.ex:8:29: A1R3.f/0
Current main / v1.20 RC (b58e84352):
warning: incompatible types given to String.length/1:
String.length(1)
given types:
-integer()-
but expected one of:
binary()
└─ a1_r3.ex:6:35: A1R3.f/0
4. else body warning before rescue body:
defmodule A1R4 do
def f(x) do
try do
x
rescue
_ in RuntimeError -> Integer.to_string(:atom)
else
:ok -> String.length(1)
end
end
end
v1.19.5 (d33fd8e41):
warning: incompatible types given to Integer.to_string/1:
Integer.to_string(:atom)
given types:
-:atom-
but expected one of:
integer()
└─ a1_r4.ex:6:36: A1R4.f/1
Current main / v1.20 RC (b58e84352):
warning: incompatible types given to String.length/1:
String.length(1)
given types:
-integer()-
but expected one of:
binary()
└─ a1_r4.ex:8:21: A1R4.f/1
Concern
So, try seems to suppress diagnostics after the 1st failing alternative.
Expected behavior
Equivalent non-try structures still behave as expected (case clauses, multiple catch clauses, or multiple else clauses); they report independent clause warnings.
Speculation
The behaviour appears to come from lib/elixir/lib/module/types/expr.ex:
try handles else first, then reduces rescue/catch blocks sequentially;
- Rescue clauses are checked by an inline nested
Enum.reduce;
of_rescue/9 resets variables after the rescue body with Of.reset_vars/2, but it does not isolate or restore failed;
- Normal clause checking goes through
of_clauses_fun/7, which wraps each clause with reset_failed/2 and set_failed/2, allowing independent diagnostics while preserving the final failed state.
Existing issue
Elixir and Erlang/OTP versions
Erlang/OTP 28 [erts-16.1.1] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]
Elixir 1.20.0-rc.5 (383ffc5) (compiled with Erlang/OTP 28)
Operating system
Linux / macOS
Current behavior
On current
main(b58e84352), the behaviour oftry’s diagnostics changed; once onetryalternative setscontext.failed, later independent alternatives stop reporting diagnostics:1. Two rescue bodies with independent bad calls:
v1.19.5 (
d33fd8e41):Current
main/ v1.20 RC (b58e84352):2. Failed rescue body followed by undefined exception head:
v1.19.5 (
d33fd8e41):Current
main/ v1.20 RC (b58e84352):3. Failed rescue body before catch body:
v1.19.5 (
d33fd8e41):Current
main/ v1.20 RC (b58e84352):4. else body warning before rescue body:
v1.19.5 (
d33fd8e41):Current
main/ v1.20 RC (b58e84352):Concern
So,
tryseems to suppress diagnostics after the 1st failing alternative.Expected behavior
Equivalent non-
trystructures still behave as expected (caseclauses, multiplecatchclauses, or multipleelseclauses); they report independent clause warnings.Speculation
The behaviour appears to come from
lib/elixir/lib/module/types/expr.ex:tryhandleselsefirst, then reducesrescue/catchblocks sequentially;Enum.reduce;of_rescue/9resets variables after the rescue body withOf.reset_vars/2, but it does not isolate or restorefailed;of_clauses_fun/7, which wraps each clause withreset_failed/2andset_failed/2, allowing independent diagnostics while preserving the final failed state.