From b93b8ea8878090753c6972a1156470e5bbe0a010 Mon Sep 17 00:00:00 2001 From: Stavros Aronis Date: Mon, 21 Mar 2011 18:40:38 +0200 Subject: Add small/param_types_crash --- .../small_SUITE_data/src/param_types_crash.erl | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 lib/dialyzer/test/small_SUITE_data/src/param_types_crash.erl diff --git a/lib/dialyzer/test/small_SUITE_data/src/param_types_crash.erl b/lib/dialyzer/test/small_SUITE_data/src/param_types_crash.erl new file mode 100644 index 0000000000..52d52cc9a9 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/param_types_crash.erl @@ -0,0 +1,77 @@ +%%--------------------------------------------------------------------------- +%% From: Nicolas Tranger +%% Date: 10/11/2110 +%% +%% After adding spec statements to my module, Dialyzer failed on execution +%% though. I've been trying to create a minimal reproducible case and +%% reduced the code to something similar of about 80 LOC. As noted in the +%% comments, commenting out some lines makes Dialyzer parse and analyze +%% the file correctly. The code executes correctly and as expected. +%% +%% I'm not sure what causes the issue. parse_result is polymorphic in its +%% return type, but statically typed based on the type of the 3th argument +%% (well, that's how I see things from a Haskell background). +%%--------------------------------------------------------------------------- +%% This was a bug in erl_types:t_subtract/2 which was not handling the case +%% of free variables in prameterized types. Fixed 15/10/2010. +%%--------------------------------------------------------------------------- +-module(param_types_crash). + +-export([test/0]). + +-type socket_error() :: 'connection_closed' | 'timeout'. +-type app_error() :: 'no_magic' | 'unknown_failure'. + +-type resulthandler_result(T) :: {'ok', T} | socket_error() | app_error(). +-type resulthandler(T) :: fun((binary()) -> resulthandler_result(T)). + +test() -> + Data = <<0:32/little-unsigned, 1:8/little, 1:8/little-unsigned>>, + case parse_result(Data, get_option(fun get_bool/1)) of + %% Removing the next 2 lines makes + %% dialyzer param_types_crash.erl -Wunmatched_returns -Wunderspecs + %% succeed. With these lines, it fails. + {ok, none} -> none; + {ok, {some, Value}} -> Value; + Reply -> {error, Reply} + end. + +-spec parse_result(binary(), resulthandler(T)) -> resulthandler_result(T). +parse_result(<>, ResultHandler) -> + case ResultCode of + 0 -> ResultHandler(Rest); + 1 -> no_magic; + 2 -> unknown_failure + end. + +-spec get_bool(binary()) -> {'ok', boolean()} | socket_error(). +get_bool(Data) -> + case get_data(Data, 1, size(Data)) of + {<>, <<>>} -> {ok, (Value =:= 1)}; + Other -> Other + end. + +-spec get_option(resulthandler(T)) -> resulthandler('none' | {'some', T}). +get_option(Fun) -> + fun(Data) -> + case get_data(Data, 1, size(Data)) of + {<>, Rest} -> + case HasValue of + 0 -> {ok, none}; + 1 -> {ok, Value} = Fun(Rest), + {ok, {some, Value}} + end; + Other -> Other + end + end. + +-spec get_data(binary(), non_neg_integer(), non_neg_integer()) -> + {binary(), binary()} | socket_error(). +get_data(Data, Length, Received) when Length > Received -> + case Data of + <<>> -> connection_closed; + _ -> timeout + end; +get_data(Data, Length, _) -> + <> = Data, + {Bin, Rest}. -- cgit v1.2.3