You are helping this community forward in an incredible way. Keep that in mind when problems are hard, or energy is low. There are Elixir devs all around the world having that “hooting and hollering” experience. So thank you for your generous contributions!
I ran tests on my repos against 1.18 and everything looks good. The only thing I’m not quite sure about is what to do about intentionally incorrect code in tests?
Example from ExUnit docs
ExUnit.start()
defmodule MyTest do
use ExUnit.Case, async: true
test "foo" do
assert_raise ArithmeticError, fn ->
1 + "test"
end
end
end
elixir ex_unit.exs
warning: evaluation of operator '+'/2 will fail with a 'badarith' exception
│
9 │ 1 + "test"
│ ~
│
└─ ex_unit.exs:9:9
warning: incompatible types given to Kernel.+/2:
1 + "test"
given types:
integer(), binary()
but expected one of:
#1
integer(), integer()
#2
integer(), float()
#3
float(), integer()
#4
float(), float()
typing violation found at:
│
9 │ 1 + "test"
│ ~
│
└─ ex_unit.exs:9:9: MyTest."test foo"/1
Running ExUnit with seed: 982904, max_cases: 16
.
Finished in 0.03 seconds (0.03s on load, 0.00s async, 0.00s sync)
1 test, 0 failures
Hmm, in this particular case I’m testing a logger handler so it makes sense to intentionally create a problem. But I guess I can always just throw an exception instead. I wonder if there are cases where we have to write code that produces warnings to test something. Curious to see how it plays out!
The trick we are using in Elixir test suite under similar situations (when we need to force the code to crash to test error handlers and similar) is to hide the value under Process.get(:unused_key, value). For example:
Process.get(:unused_key, 1) + "test"
The reason this works for now is because Process.get/2 will always return a dynamic value, so we cannot assume an error will happen. Maybe we will detect these cases in the future too… then you can ping us again. In any case, as the type system becomes smarter, it will be harder to hide compile time errors from it.
Anyone that uses mise (ex-RTX) to manage versions can install Elixir 1.18.0-rc.0? It gets listed but when installing throws a mise ERROR 1.18.0-rc.0 not found in mise tool registry.
I think over time the introduction of a smarter compiler could warrant the introduction of tools to work with it that make their purpose clear. For example:
Kernel.dynamic_value/1
# takes anything, returns it as a dynamic
dynamic_value(1) + "test"
Kernel.unreachable!/1
case something do
:foo -> 10
:bar ->
# somehow tells the type checker not to warn on this clause?
unreachable!("It should not be possible for `something` to be `:bar` at this point.")
end
In this case, you should just remove the a < b from the doctest by removing iex> and have it written as non-executable code. I think using Process.get in the doctest would detract from its main purpose, which is documentation.
That’s the plan in the long term, but something like dynamic_value can also be used to hide actual bugs, so we want to tread carefully.