diff options
author | Björn Gustavsson <[email protected]> | 2011-03-15 07:55:44 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2011-03-25 11:02:11 +0100 |
commit | c6b0d6dce5709c61e549e850c2615fd288e27ba9 (patch) | |
tree | d2fda98512c2f42e83b374d6489dd8670a2b852a | |
parent | 40a96ab9a41b780d59da643cce71084e72901a54 (diff) | |
download | otp-c6b0d6dce5709c61e549e850c2615fd288e27ba9.tar.gz otp-c6b0d6dce5709c61e549e850c2615fd288e27ba9.tar.bz2 otp-c6b0d6dce5709c61e549e850c2615fd288e27ba9.zip |
sys_core_fold: Eliminate incorrect warning
The compiler (sys_core_fold) tries to avoid constructing tuples
in case expressions. The following code:
c(A, B) ->
case {A,B} of
{ok,X} -> X;
{_,_} -> error
end.
will be rewritten so that no tuple is built. If a clause
requires a tuple to be built as in this code:
c(A, B) ->
case {A,B} of
{ok,X} -> X;
V -> V %The tuple will be built here
end.
the tuple will be built in the clause(s) in which it is needed.
If the value returned from the case is not used as in this code:
c(A, B) ->
case {A,B} of
V -> V %Warning: a term is constructed, but never used
end,
ok.
there will be an incorrect warning. Basically, what happens is
that the code is reduced to:
c(A, B) ->
{A,B}, %Warning: a term is constructed, but never used
ok.
and the optimizer sees that the {A,B} tuple can't possibly be used.
Eliminate the warning by adding a 'compiler_generated' annotation
to the tuple.
Reported-by: Kostis Sagonas
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 15 | ||||
-rw-r--r-- | lib/compiler/test/warnings_SUITE.erl | 10 |
2 files changed, 22 insertions, 3 deletions
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index c870bb68c8..9360556e00 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -1969,13 +1969,22 @@ case_tuple_pat([#c_tuple{es=Ps}], Arity) when length(Ps) =:= Arity -> case_tuple_pat([#c_literal{val=T}], Arity) when tuple_size(T) =:= Arity -> Ps = [#c_literal{val=E} || E <- tuple_to_list(T)], {ok,Ps,[]}; -case_tuple_pat([#c_var{anno=Anno}=V], Arity) -> - Vars = make_vars(Anno, 1, Arity), +case_tuple_pat([#c_var{anno=Anno0}=V], Arity) -> + Vars = make_vars(Anno0, 1, Arity), + + %% If the entire case statement is evaluated in an effect + %% context (e.g. "case {A,B} of ... end, ok"), there will + %% be a warning that a term is constructed but never used. + %% To avoid that warning, we must annotate the tuple as + %% compiler generated. + + Anno = [compiler_generated|Anno0], {ok,Vars,[{V,#c_tuple{anno=Anno,es=Vars}}]}; case_tuple_pat([#c_alias{var=V,pat=P}], Arity) -> case case_tuple_pat([P], Arity) of {ok,Ps,Avs} -> - Anno = core_lib:get_anno(P), + Anno0 = core_lib:get_anno(P), + Anno = [compiler_generated|Anno0], {ok,Ps,[{V,#c_tuple{anno=Anno,es=unalias_pat_list(Ps)}}|Avs]}; error -> error diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl index 8cc3ca4199..dd18a6e1a3 100644 --- a/lib/compiler/test/warnings_SUITE.erl +++ b/lib/compiler/test/warnings_SUITE.erl @@ -453,6 +453,16 @@ effect(Config) when is_list(Config) -> true -> ok end, ok. + + m8(A, B) -> + case {A,B} of + V -> V + end, + ok. + + m9(Bs) -> + [{B,ok} = {B,foo:bar(B)} || B <- Bs], + ok. ">>, [], {warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}}, |