diff options
author | Hans Bolinder <[email protected]> | 2018-08-21 13:39:55 +0200 |
---|---|---|
committer | Hans Bolinder <[email protected]> | 2018-08-21 13:39:55 +0200 |
commit | 00401985f1c9227b6e94309ae5526c2ebf341527 (patch) | |
tree | 255a44455312f8c11bf8ac5ac8ad32540947aa38 | |
parent | 374bb679dafbd0739153ab1f5ed474c628788604 (diff) | |
parent | 52ca4ae9db150cc89d44974e516589298b040c17 (diff) | |
download | otp-00401985f1c9227b6e94309ae5526c2ebf341527.tar.gz otp-00401985f1c9227b6e94309ae5526c2ebf341527.tar.bz2 otp-00401985f1c9227b6e94309ae5526c2ebf341527.zip |
Merge branch 'hasse/stdlib/io_lib_errhandling/OTP-15076' into maint
* hasse/stdlib/io_lib_errhandling/OTP-15076:
stdlib: Correct contracts in module io_lib_format
stdlib: Improve error handling in module io_lib
-rw-r--r-- | lib/stdlib/src/io_lib.erl | 49 | ||||
-rw-r--r-- | lib/stdlib/src/io_lib_format.erl | 8 | ||||
-rw-r--r-- | lib/stdlib/test/io_SUITE.erl | 12 |
3 files changed, 49 insertions, 20 deletions
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl index 3a5aba60b4..8223a52873 100644 --- a/lib/stdlib/src/io_lib.erl +++ b/lib/stdlib/src/io_lib.erl @@ -178,11 +178,11 @@ fread(Cont, Chars, Format) -> Data :: [term()]. format(Format, Args) -> - case catch io_lib_format:fwrite(Format, Args) of - {'EXIT',_} -> - erlang:error(badarg, [Format, Args]); - Other -> - Other + try io_lib_format:fwrite(Format, Args) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) end. -spec format(Format, Data, Options) -> chars() when @@ -193,11 +193,11 @@ format(Format, Args) -> CharsLimit :: chars_limit(). format(Format, Args, Options) -> - case catch io_lib_format:fwrite(Format, Args, Options) of - {'EXIT',_} -> - erlang:error(badarg, [Format, Args, Options]); - Other -> - Other + try io_lib_format:fwrite(Format, Args, Options) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) end. -spec scan_format(Format, Data) -> FormatList when @@ -208,7 +208,9 @@ format(Format, Args, Options) -> scan_format(Format, Args) -> try io_lib_format:scan(Format, Args) catch - _:_ -> erlang:error(badarg, [Format, Args]) + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [Format, Args]) end. -spec unscan_format(FormatList) -> {Format, Data} when @@ -223,7 +225,12 @@ unscan_format(FormatList) -> FormatList :: [char() | format_spec()]. build_text(FormatList) -> - io_lib_format:build(FormatList). + try io_lib_format:build(FormatList) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [FormatList]) + end. -spec build_text(FormatList, Options) -> chars() when FormatList :: [char() | format_spec()], @@ -232,7 +239,23 @@ build_text(FormatList) -> CharsLimit :: chars_limit(). build_text(FormatList, Options) -> - io_lib_format:build(FormatList, Options). + try io_lib_format:build(FormatList, Options) + catch + C:R:S -> + test_modules_loaded(C, R, S), + erlang:error(badarg, [FormatList, Options]) + end. + +%% Failure to load a module must not be labeled as badarg. +%% C, R, and S are included so that the original error, which could be +%% a bug in io_lib_format, can be found by tracing on +%% test_modules_loaded/3. +test_modules_loaded(_C, _R, _S) -> + Modules = [io_lib_format, io_lib_pretty, string, unicode], + case code:ensure_modules_loaded(Modules) of + ok -> ok; + Error -> erlang:error(Error) + end. -spec print(Term) -> chars() when Term :: term(). diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl index c814ab50d4..e247b00a04 100644 --- a/lib/stdlib/src/io_lib_format.erl +++ b/lib/stdlib/src/io_lib_format.erl @@ -38,18 +38,16 @@ %% and it also splits the handling of the control characters into two %% parts. --spec fwrite(Format, Data) -> FormatList when +-spec fwrite(Format, Data) -> io_lib:chars() when Format :: io:format(), - Data :: [term()], - FormatList :: [char() | io_lib:format_spec()]. + Data :: [term()]. fwrite(Format, Args) -> build(scan(Format, Args)). --spec fwrite(Format, Data, Options) -> FormatList when +-spec fwrite(Format, Data, Options) -> io_lib:chars() when Format :: io:format(), Data :: [term()], - FormatList :: [char() | io_lib:format_spec()], Options :: [Option], Option :: {'chars_limit', CharsLimit}, CharsLimit :: io_lib:chars_limit(). diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 79cee54335..f097552e8c 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -31,7 +31,7 @@ otp_10836/1, io_lib_width_too_small/1, io_with_huge_message_queue/1, format_string/1, maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1, - otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, + otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1, otp_15159/1]). -export([pretty/2, trf/3]). @@ -64,7 +64,7 @@ all() -> io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836, io_lib_width_too_small, io_with_huge_message_queue, format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175, - otp_14285, limit_term, otp_14983, otp_15103, otp_15159]. + otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159]. %% Error cases for output. error_1(Config) when is_list(Config) -> @@ -2639,3 +2639,11 @@ otp_15159(_Config) -> "[atom]" = lists:flatten(io_lib:format("~p", [[atom]], [{chars_limit,5}])), ok. + +otp_15076(_Config) -> + {'EXIT', {badarg, _}} = (catch io_lib:format("~c", [a])), + L = io_lib:scan_format("~c", [a]), + {"~c", [a]} = io_lib:unscan_format(L), + {'EXIT', {badarg, _}} = (catch io_lib:build_text(L)), + {'EXIT', {badarg, _}} = (catch io_lib:build_text(L, [])), + ok. |