Gradualizer icon indicating copy to clipboard operation
Gradualizer copied to clipboard

throwing a record fails with an error : expected to have type Any

Open berbiche opened this issue 3 years ago • 2 comments

Hi,

Since the last stable release, throwing a record results in an error:

-module(error2).

-compile([export_all, nowarn_export_all]).

-record(my_error_type, { not_important :: atom() }).

%% error2.erl: The record on line 15 at column 11 is expected to have type Any but it has type #my_error_type{}
%%
%% -spec should_pass_throw_record() -> no_return.
%% should_pass_throw_record(_) ->
%%     throw(#my_error_type{not_important = something}).
%%           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-spec should_pass_throw_record() -> no_return().
should_pass_throw_record() ->
    throw(#my_error_type{not_important = something}).
# System Info
OTP: Erlang/OTP 24 [erts-12.0.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit]
System: Ubuntu 20.04.1 LTS x86_64 (VM)

berbiche avatar May 10 '22 21:05 berbiche

It seems that throw has a spec like -spec throw(Any) when Any :: any().. We can probably test it using another function with a type like this, so we don't rely on throw's spec which may differ between OTP versions.

-spec f(A) -> ok when A :: any().
f(_) -> ok.

zuiderkwast avatar May 11 '22 06:05 zuiderkwast

I can reproduce the problem with your example.

The issue can be avoided if the function f above (or throw/1) is called with an assert_type or annotate_type on the parameter: f(?assert_type(#my_error_type{not_important = a}, #my_error_type{})) doesn't produce any error.

berbiche avatar May 12 '22 15:05 berbiche