Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate erlang:get_stacktrace/1 #1783

Merged
merged 4 commits into from
Apr 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified erts/preloaded/ebin/erlang.beam
Binary file not shown.
2 changes: 1 addition & 1 deletion erts/preloaded/src/erlang.erl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
dist_ctrl_get_data_notification/1,
dist_get_stat/1]).

-deprecated([now/0]).
-deprecated([get_stacktrace/0,now/0]).

%% Get rid of autoimports of spawn to avoid clashes with ourselves.
-compile({no_auto_import,[spawn_link/1]}).
Expand Down
9 changes: 4 additions & 5 deletions lib/asn1/src/asn1ct.erl
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,7 @@ run_passes_1([{pass,Name,Pass}|Passes], #st{run=Run}=St0)
done ->
ok
catch
Class:Error ->
Stk = erlang:get_stacktrace(),
Class:Error:Stk ->
io:format("Internal error: ~p:~p\n~p\n",
[Class,Error,Stk]),
{error,{internal_error,{Class,Error}}}
Expand Down Expand Up @@ -2390,13 +2389,13 @@ in_process(Fun) ->
receive
{Pid, Result} -> Result;
{Pid, Class, Reason, Stack} ->
ST = try throw(x) catch throw:x -> erlang:get_stacktrace() end,
ST = try throw(x) catch throw:x:Stk -> Stk end,
erlang:raise(Class, Reason, Stack ++ ST)
end.

process(Parent, Fun) ->
try
Parent ! {self(), Fun()}
catch Class:Reason ->
Parent ! {self(), Class, Reason, erlang:get_stacktrace()}
catch Class:Reason:Stack ->
Parent ! {self(), Class, Reason, Stack}
end.
3 changes: 1 addition & 2 deletions lib/asn1/src/asn1ct_gen.erl
Original file line number Diff line number Diff line change
Expand Up @@ -815,8 +815,7 @@ result_line_1(Items) ->

try_catch() ->
[" catch",nl,
" Class:Exception when Class =:= error; Class =:= exit ->",nl,
" Stk = erlang:get_stacktrace(),",nl,
" Class:Exception:Stk when Class =:= error; Class =:= exit ->",nl,
" case Exception of",nl,
" {error,{asn1,Reason}} ->",nl,
" {error,{asn1,{Reason,Stk}}};",nl,
Expand Down
5 changes: 2 additions & 3 deletions lib/asn1/test/asn1_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,9 @@ test(Config, TestF, Rules) ->
try
TestF(C, R, O)
catch
Class:Reason ->
Class:Reason:Stk ->
NewReason = {Reason, [{rule, R}, {options, O}]},
erlang:raise(Class, NewReason,
erlang:get_stacktrace())
erlang:raise(Class, NewReason, Stk)
end
end,
Result = [run_case(Config, Fun, rule(Rule), opts(Rule)) || Rule <- Rules],
Expand Down
3 changes: 1 addition & 2 deletions lib/asn1/test/testUniqueObjectSets.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ seq_roundtrip(I, D0) ->
asn1_test_lib:map_roundtrip(M, 'Seq', Enc),
{ok,{'Seq',I,D}} = M:decode('Seq', Enc),
D
catch C:E ->
Stk = erlang:get_stacktrace(),
catch C:E:Stk ->
io:format("FAILED: ~p ~p\n", [I,D0]),
erlang:raise(C, E, Stk)
end.
Expand Down
8 changes: 0 additions & 8 deletions lib/compiler/doc/src/compile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -649,14 +649,6 @@ module.beam: module.erl \
<p>Turns off warnings for unused record types. Default is to
emit warnings for unused locally defined record types.</p>
</item>

<tag><c>nowarn_get_stacktrace</c></tag>
<item>
<p>Turns off warnings for using <c>get_stacktrace/0</c> in a context
where it will probably not work in a future release. For example,
by default there will be a warning if <c>get_stacktrace/0</c> is
used following a <c>catch</c> expression.</p>
</item>
</taglist>

<p>Another class of warnings is generated by the compiler
Expand Down
16 changes: 8 additions & 8 deletions lib/hipe/main/hipe.erl
Original file line number Diff line number Diff line change
Expand Up @@ -669,8 +669,8 @@ run_compiler_1(Name, DisasmFun, IcodeFun, Options) ->
{Icode, WholeModule} = IcodeFun(Code, Opts),
CompRes = compile_finish(Icode, WholeModule, Opts),
compiler_return(CompRes, Parent)
catch error:Error ->
print_crash_message(Name, Error),
catch error:Error:StackTrace ->
print_crash_message(Name, Error, StackTrace),
exit(Error)
end
end),
Expand Down Expand Up @@ -757,8 +757,8 @@ finalize(OrigList, Mod, Exports, WholeModule, Opts) ->
TargetArch = get(hipe_target_arch),
{ok, {TargetArch,Bin}}
catch
error:Error ->
{error,Error,erlang:get_stacktrace()}
error:Error:StackTrace ->
{error,Error,StackTrace}
end
end.

Expand Down Expand Up @@ -843,16 +843,16 @@ finalize_fun_sequential({MFA, Icode}, Opts, Servers) ->
{llvm_binary, Binary} ->
{MFA, Binary}
catch
error:Error ->
error:Error:StackTrace ->
?when_option(verbose, Opts, ?debug_untagged_msg("\n", [])),
print_crash_message(MFA, Error),
print_crash_message(MFA, Error, StackTrace),
exit(Error)
end.

print_crash_message(What, Error) ->
print_crash_message(What, Error, StackTrace) ->
StackFun = fun(_,_,_) -> false end,
FormatFun = fun (Term, _) -> io_lib:format("~p", [Term]) end,
StackTrace = lib:format_stacktrace(1, erlang:get_stacktrace(),
StackTrace = lib:format_stacktrace(1, StackTrace,
StackFun, FormatFun),
WhatS = case What of
{M,F,A} -> io_lib:format("~w:~w/~w", [M,F,A]);
Expand Down
60 changes: 10 additions & 50 deletions lib/stdlib/src/erl_lint.erl
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,6 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
}).


%% Are we outside or inside a catch or try/catch?
-type catch_scope() :: 'none'
| 'after_old_catch'
| 'after_try'
| 'wrong_part_of_try'
| 'try_catch'.

%% Define the lint state record.
%% 'called' and 'exports' contain {Line, {Function, Arity}},
%% the other function collections contain {Function, Arity}.
Expand Down Expand Up @@ -144,9 +137,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
:: dict:dict(ta(), #typeinfo{}),
exp_types=gb_sets:empty() %Exported types
:: gb_sets:set(ta()),
in_try_head=false :: boolean(), %In a try head.
catch_scope = none %Inside/outside try or catch
:: catch_scope()
in_try_head=false :: boolean() %In a try head.
}).

-type lint_state() :: #lint{}.
Expand Down Expand Up @@ -233,15 +224,6 @@ format_error({redefine_old_bif_import,{F,A}}) ->
format_error({redefine_bif_import,{F,A}}) ->
io_lib:format("import directive overrides auto-imported BIF ~w/~w~n"
" - use \"-compile({no_auto_import,[~w/~w]}).\" to resolve name clash", [F,A,F,A]);
format_error({get_stacktrace,wrong_part_of_try}) ->
"erlang:get_stacktrace/0 used in the wrong part of 'try' expression. "
"(Use it in the block between 'catch' and 'end'.)";
format_error({get_stacktrace,after_old_catch}) ->
"erlang:get_stacktrace/0 used following an old-style 'catch' "
"may stop working in a future release. (Use it inside 'try'.)";
format_error({get_stacktrace,after_try}) ->
"erlang:get_stacktrace/0 used following a 'try' expression "
"may stop working in a future release. (Use it inside 'try'.)";
format_error({deprecated, MFA, ReplacementMFA, Rel}) ->
io_lib:format("~s is deprecated and will be removed in ~s; use ~s",
[format_mfa(MFA), Rel, format_mfa(ReplacementMFA)]);
Expand Down Expand Up @@ -591,10 +573,7 @@ start(File, Opts) ->
false, Opts)},
{missing_spec_all,
bool_option(warn_missing_spec_all, nowarn_missing_spec_all,
false, Opts)},
{get_stacktrace,
bool_option(warn_get_stacktrace, nowarn_get_stacktrace,
true, Opts)}
false, Opts)}
],
Enabled1 = [Category || {Category,true} <- Enabled0],
Enabled = ordsets:from_list(Enabled1),
Expand Down Expand Up @@ -1426,7 +1405,7 @@ call_function(Line, F, A, #lint{usage=Usage0,called=Cd,func=Func,file=File}=St)
%% function(Line, Name, Arity, Clauses, State) -> State.

function(Line, Name, Arity, Cs, St0) ->
St1 = St0#lint{func={Name,Arity},catch_scope=none},
St1 = St0#lint{func={Name,Arity}},
St2 = define_function(Line, Name, Arity, St1),
clauses(Cs, St2).

Expand Down Expand Up @@ -2367,7 +2346,7 @@ expr({call,Line,F,As}, Vt, St0) ->
expr({'try',Line,Es,Scs,Ccs,As}, Vt, St0) ->
%% Currently, we don't allow any exports because later
%% passes cannot handle exports in combination with 'after'.
{Evt0,St1} = exprs(Es, Vt, St0#lint{catch_scope=wrong_part_of_try}),
{Evt0,St1} = exprs(Es, Vt, St0),
TryLine = {'try',Line},
Uvt = vtunsafe(TryLine, Evt0, Vt),
Evt1 = vtupdate(Uvt, Evt0),
Expand All @@ -2379,12 +2358,11 @@ expr({'try',Line,Es,Scs,Ccs,As}, Vt, St0) ->
{Avt0,St} = exprs(As, vtupdate(Evt2, Vt), St2),
Avt1 = vtupdate(vtunsafe(TryLine, Avt0, Vt), Avt0),
Avt = vtmerge(Evt2, Avt1),
{Avt,St#lint{catch_scope=after_try}};
{Avt,St};
expr({'catch',Line,E}, Vt, St0) ->
%% No new variables added, flag new variables as unsafe.
{Evt,St} = expr(E, Vt, St0),
{vtupdate(vtunsafe({'catch',Line}, Evt, Vt), Evt),
St#lint{catch_scope=after_old_catch}};
{vtupdate(vtunsafe({'catch',Line}, Evt, Vt), Evt),St};
expr({match,_Line,P,E}, Vt, St0) ->
{Evt,St1} = expr(E, Vt, St0),
{Pvt,Bvt,St2} = pattern(P, vtupdate(Evt, Vt), St1),
Expand Down Expand Up @@ -3223,7 +3201,7 @@ is_module_dialyzer_option(Option) ->

try_clauses(Scs, Ccs, In, Vt, St0) ->
{Csvt0,St1} = icrt_clauses(Scs, Vt, St0),
St2 = St1#lint{catch_scope=try_catch,in_try_head=true},
St2 = St1#lint{in_try_head=true},
{Csvt1,St3} = icrt_clauses(Ccs, Vt, St2),
Csvt = Csvt0 ++ Csvt1,
UpdVt = icrt_export(Csvt, Vt, In, St3),
Expand All @@ -3243,15 +3221,15 @@ icrt_clauses(Cs, In, Vt, St0) ->
icrt_clauses(Cs, Vt, St) ->
mapfoldl(fun (C, St0) -> icrt_clause(C, Vt, St0) end, St, Cs).

icrt_clause({clause,_Line,H,G,B}, Vt0, #lint{catch_scope=Scope}=St0) ->
icrt_clause({clause,_Line,H,G,B}, Vt0, St0) ->
Vt1 = taint_stack_var(Vt0, H, St0),
{Hvt,Binvt,St1} = head(H, Vt1, St0),
Vt2 = vtupdate(Hvt, Binvt),
Vt3 = taint_stack_var(Vt2, H, St0),
{Gvt,St2} = guard(G, vtupdate(Vt3, Vt0), St1#lint{in_try_head=false}),
Vt4 = vtupdate(Gvt, Vt2),
{Bvt,St3} = exprs(B, vtupdate(Vt4, Vt0), St2),
{vtupdate(Bvt, Vt4),St3#lint{catch_scope=Scope}}.
{vtupdate(Bvt, Vt4),St3}.

taint_stack_var(Vt, Pat, #lint{in_try_head=true}) ->
[{tuple,_,[_,_,{var,_,Stk}]}] = Pat,
Expand Down Expand Up @@ -3736,8 +3714,7 @@ has_wildcard_field([]) -> false.
check_remote_function(Line, M, F, As, St0) ->
St1 = deprecated_function(Line, M, F, As, St0),
St2 = check_qlc_hrl(Line, M, F, As, St1),
St3 = check_get_stacktrace(Line, M, F, As, St2),
format_function(Line, M, F, As, St3).
format_function(Line, M, F, As, St2).

%% check_qlc_hrl(Line, ModName, FuncName, [Arg], State) -> State
%% Add warning if qlc:q/1,2 has been called but qlc.hrl has not
Expand Down Expand Up @@ -3786,23 +3763,6 @@ deprecated_function(Line, M, F, As, St) ->
St
end.

check_get_stacktrace(Line, erlang, get_stacktrace, [], St) ->
case St of
#lint{catch_scope=none} ->
St;
#lint{catch_scope=try_catch} ->
St;
#lint{catch_scope=Scope} ->
case is_warn_enabled(get_stacktrace, St) of
false ->
St;
true ->
add_warning(Line, {get_stacktrace,Scope}, St)
end
end;
check_get_stacktrace(_, _, _, _, St) ->
St.

-dialyzer({no_match, deprecated_type/5}).

deprecated_type(L, M, N, As, St) ->
Expand Down
3 changes: 3 additions & 0 deletions lib/stdlib/src/otp_internal.erl
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,9 @@ obsolete_1(filename, find_src, 1) ->
obsolete_1(filename, find_src, 2) ->
{deprecated, "deprecated; use filelib:find_source/3 instead"};

obsolete_1(erlang, get_stacktrace, 0) ->
{deprecated, "deprecated; use the new try/catch syntax for retrieving the stack backtrace"};

%% Removed in OTP 20.

obsolete_1(erlang, hash, 2) ->
Expand Down
80 changes: 2 additions & 78 deletions lib/stdlib/test/erl_lint_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
otp_11851/1,otp_11879/1,otp_13230/1,
record_errors/1, otp_11879_cont/1,
non_latin1_module/1, otp_14323/1,
get_stacktrace/1, stacktrace_syntax/1,
stacktrace_syntax/1,
otp_14285/1, otp_14378/1]).

suite() ->
Expand All @@ -88,7 +88,7 @@ all() ->
maps, maps_type, maps_parallel_match,
otp_11851, otp_11879, otp_13230,
record_errors, otp_11879_cont, non_latin1_module, otp_14323,
get_stacktrace, stacktrace_syntax, otp_14285, otp_14378].
stacktrace_syntax, otp_14285, otp_14378].

groups() ->
[{unused_vars_warn, [],
Expand Down Expand Up @@ -4055,82 +4055,6 @@ otp_14323(Config) ->
[] = run(Config, Ts),
ok.

get_stacktrace(Config) ->
Ts = [{old_catch,
<<"t1() ->
catch error(foo),
erlang:get_stacktrace().
">>,
[],
{warnings,[{3,erl_lint,{get_stacktrace,after_old_catch}}]}},
{nowarn_get_stacktrace,
<<"t1() ->
catch error(foo),
erlang:get_stacktrace().
">>,
[nowarn_get_stacktrace],
[]},
{try_catch,
<<"t1(X) ->
try abs(X) of
_ ->
erlang:get_stacktrace()
catch
_:_ -> ok
end.

t2() ->
try error(foo)
catch _:_ -> ok
end,
erlang:get_stacktrace().

t3() ->
try error(foo)
catch _:_ ->
try error(bar)
catch _:_ ->
ok
end,
erlang:get_stacktrace()
end.

no_warning(X) ->
try
abs(X)
catch
_:_ ->
erlang:get_stacktrace()
end.
">>,
[],
{warnings,[{4,erl_lint,{get_stacktrace,wrong_part_of_try}},
{13,erl_lint,{get_stacktrace,after_try}},
{22,erl_lint,{get_stacktrace,after_try}}]}},
{multiple_catch_clauses,
<<"maybe_error(Arg) ->
try 5 / Arg
catch
error:badarith ->
_Stacktrace = erlang:get_stacktrace(),
try io:nl()
catch
error:_ -> io:format('internal error')
end;
error:badarg ->
_Stacktrace = erlang:get_stacktrace(),
try io:format(qwe)
catch
error:_ -> io:format('internal error')
end
end.
">>,
[],
[]}],

run(Config, Ts),
ok.

stacktrace_syntax(Config) ->
Ts = [{guard,
<<"t1() ->
Expand Down