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

Drop old style type tests #9138

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 0 additions & 3 deletions lib/compiler/src/v3_core.erl
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,6 @@ gexpr_test(E0, Bools0, St0) ->
{icall_eq_true(New),
Eps0 ++ [#iset{anno=Anno,var=New,arg=E1}],Bools0,St2};
#icall{anno=Anno,module=#c_literal{val=erlang},name=#c_literal{val=N},args=As} ->
%% Note that erl_expand_records has renamed type
%% tests to the new names; thus, float/1 as a type
%% test will now be named is_float/1.
Ar = length(As),
case erl_internal:new_type_test(N, Ar) orelse
erl_internal:comp_op(N, Ar) orelse
Expand Down
24 changes: 1 addition & 23 deletions lib/stdlib/src/erl_expand_records.erl
Original file line number Diff line number Diff line change
Expand Up @@ -184,32 +184,10 @@ guard_tests1([], St) -> {[],St}.

guard_test(G0, St0) ->
in_guard(fun() ->
{G1,St1} = guard_test1(G0, St0),
{G1,St1} = expr(G0, St0),
strict_record_access(G1, St1)
end).

%% Normalising guard tests ensures that none of the Boolean operands
%% created by strict_record_access/2 calls any of the old guard tests.
guard_test1({call,Anno,{atom,Tanno,Tname},As}, St) ->
Test = {atom,Tanno,normalise_test(Tname, length(As))},
expr({call,Anno,Test,As}, St);
guard_test1(Test, St) ->
expr(Test, St).

normalise_test(atom, 1) -> is_atom;
normalise_test(binary, 1) -> is_binary;
normalise_test(float, 1) -> is_float;
normalise_test(function, 1) -> is_function;
normalise_test(integer, 1) -> is_integer;
normalise_test(list, 1) -> is_list;
normalise_test(number, 1) -> is_number;
normalise_test(pid, 1) -> is_pid;
normalise_test(port, 1) -> is_port;
normalise_test(record, 2) -> is_record;
normalise_test(reference, 1) -> is_reference;
normalise_test(tuple, 1) -> is_tuple;
normalise_test(Name, _) -> Name.

is_in_guard() ->
get(erl_expand_records_in_guard).

Expand Down
22 changes: 2 additions & 20 deletions lib/stdlib/src/erl_internal.erl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ of interest to programmers who manipulate Erlang code.
%%

-export([bif/2,bif/3,guard_bif/2,
type_test/2,new_type_test/2,old_type_test/2,old_bif/2]).
type_test/2,new_type_test/2,old_bif/2]).
-export([arith_op/2,bool_op/2,comp_op/2,list_op/2,send_op/2,op_type/2]).

-export([is_type/2]).
Expand Down Expand Up @@ -107,7 +107,7 @@ guard_bif(Name, A) -> new_type_test(Name, A).
Arity :: arity().

type_test(Name, Arity) ->
new_type_test(Name, Arity) orelse old_type_test(Name, Arity).
new_type_test(Name, Arity).

%% Erlang new-style type tests.
-doc false.
Expand All @@ -133,24 +133,6 @@ new_type_test(is_reference, 1) -> true;
new_type_test(is_tuple, 1) -> true;
new_type_test(Name, A) when is_atom(Name), is_integer(A) -> false.

%% Erlang old-style type tests.
-doc false.
-spec old_type_test(Name::atom(), Arity::arity()) -> boolean().

old_type_test(integer, 1) -> true;
old_type_test(float, 1) -> true;
old_type_test(number, 1) -> true;
old_type_test(atom, 1) -> true;
old_type_test(list, 1) -> true;
old_type_test(tuple, 1) -> true;
old_type_test(pid, 1) -> true;
old_type_test(reference, 1) -> true;
old_type_test(port, 1) -> true;
old_type_test(binary, 1) -> true;
old_type_test(record, 2) -> true;
old_type_test(function, 1) -> true;
old_type_test(Name, A) when is_atom(Name), is_integer(A) -> false.

-doc "Returns `true` if `OpName/Arity` is an arithmetic operator, otherwise `false`.".
-spec arith_op(OpName, Arity) -> boolean() when
OpName :: atom(),
Expand Down
64 changes: 18 additions & 46 deletions lib/stdlib/src/erl_lint.erl
Original file line number Diff line number Diff line change
Expand Up @@ -396,13 +396,6 @@ format_error_1({removed_type, MNA, String}) ->
{~"the type ~s is removed; ~s", [format_mna(MNA), String]};
format_error_1({removed_callback, MNA, String}) ->
{~"the callback ~s is removed; ~s", [format_mna(MNA), String]};
format_error_1({obsolete_guard, {F, A}}) ->
{~"~p/~p obsolete (use is_~p/~p)", [F, A, F, A]};
format_error_1({obsolete_guard_overridden,Test}) ->
{~"""
obsolete ~s/1 (meaning is_~s/1) is illegal when there is a
local/imported function named is_~p/1
""", [Test,Test,Test]};
format_error_1({too_many_arguments,Arity}) ->
{~"too many arguments (~w) -- maximum allowed is ~w", [Arity,?MAX_ARGUMENTS]};
format_error_1(update_literal) ->
Expand All @@ -416,6 +409,10 @@ format_error_1(illegal_expr) -> ~"illegal expression";
format_error_1({illegal_guard_local_call, {F,A}}) ->
{~"call to local/imported function ~tw/~w is illegal in guard",
[F,A]};
format_error_1({illegal_type_test, {F,A}}) ->
%% last remnant of old style type tests
{~"call to ~tw/~w is not a type test, use is_~tw/~w instead",
[F,A,F,A]};
format_error_1(illegal_guard_expr) -> ~"illegal guard expression";
format_error_1(match_float_zero) ->
~"""
Expand Down Expand Up @@ -830,7 +827,6 @@ bool_options() ->
{deprecated_function,true},
{deprecated_type,true},
{deprecated_callback,true},
{obsolete_guard,true},
{untyped_record,false},
{missing_spec,false},
{missing_spec_documented,false},
Expand Down Expand Up @@ -2351,18 +2347,9 @@ guard_tests([], _Vt, St) -> {[],St}.

%% guard_test(Test, VarTable, State) ->
%% {UsedVarTable,State'}
%% Check one guard test, returns NewVariables. We now allow more
%% expressions in guards including the new is_XXX type tests, but
%% only allow the old type tests at the top level.

guard_test(G, Vt, St0) ->
St1 = obsolete_guard(G, St0),
guard_test2(G, Vt, St1).

%% Specially handle record type test here.
guard_test2({call,Anno,{atom,Ar,record},[E,A]}, Vt, St0) ->
gexpr({call,Anno,{atom,Ar,is_record},[E,A]}, Vt, St0);
guard_test2({call,Anno,{atom,_Aa,F},As}=G, Vt, St0) ->
%% Check one guard test, returns NewVariables.

guard_test({call,Anno,{atom,_Aa,F},As}=G, Vt, St0) ->
{Asvt,St1} = gexpr_list(As, Vt, St0), %Always check this.
A = length(As),
case erl_internal:type_test(F, A) of
Expand All @@ -2371,12 +2358,18 @@ guard_test2({call,Anno,{atom,_Aa,F},As}=G, Vt, St0) ->
false ->
{Asvt,add_error(Anno, {illegal_guard_local_call,{F,A}}, St1)};
true ->
{Asvt,St1}
end;
_ ->
gexpr(G, Vt, St0)
{Asvt,St1}
end;
_ ->
%% check for removed old style type tests whose names coincide with
%% other guard bifs so they do not become silently failing tests
if F =:= float, A =:= 1 ->
{Asvt,add_error(Anno, {illegal_type_test,{F,A}}, St1)};
true ->
gexpr(G, Vt, St0)
end
end;
guard_test2(G, Vt, St) ->
guard_test(G, Vt, St) ->
%% Everything else is a guard expression.
gexpr(G, Vt, St).

Expand Down Expand Up @@ -4675,27 +4668,6 @@ deprecated_type(Anno, M, N, As, St) ->
St
end.

obsolete_guard({call,Anno,{atom,Ar,F},As}, St0) ->
Arity = length(As),
case erl_internal:old_type_test(F, Arity) of
false ->
deprecated_function(Anno, erlang, F, As, St0);
true ->
St = maybe_add_warning(Ar, {obsolete_guard, {F, Arity}}, St0),
test_overriden_by_local(Ar, F, Arity, St)
end;
obsolete_guard(_G, St) ->
St.

test_overriden_by_local(Anno, OldTest, Arity, St) ->
ModernTest = list_to_atom("is_"++atom_to_list(OldTest)),
case is_local_function(St#lint.locals, {ModernTest, Arity}) of
true ->
add_error(Anno, {obsolete_guard_overridden,OldTest}, St);
false ->
St
end.

feature_keywords() ->
Features = erl_features:configurable(),
G = fun(Ftr, Map) ->
Expand Down
24 changes: 0 additions & 24 deletions lib/stdlib/test/erl_eval_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -558,52 +558,28 @@ simple_cases(Config) when is_list(Config) ->
yes),
check(fun() -> if is_integer(3) -> true; true -> false end end,
"if is_integer(3) -> true; true -> false end.", true),
check(fun() -> if integer(3) -> true; true -> false end end,
"if integer(3) -> true; true -> false end.", true),
check(fun() -> if is_float(3) -> true; true -> false end end,
"if is_float(3) -> true; true -> false end.", false),
check(fun() -> if float(3) -> true; true -> false end end,
"if float(3) -> true; true -> false end.", false),
check(fun() -> if is_number(3) -> true; true -> false end end,
"if is_number(3) -> true; true -> false end.", true),
check(fun() -> if number(3) -> true; true -> false end end,
"if number(3) -> true; true -> false end.", true),
check(fun() -> if is_atom(a) -> true; true -> false end end,
"if is_atom(a) -> true; true -> false end.", true),
check(fun() -> if atom(a) -> true; true -> false end end,
"if atom(a) -> true; true -> false end.", true),
check(fun() -> if is_list([]) -> true; true -> false end end,
"if is_list([]) -> true; true -> false end.", true),
check(fun() -> if list([]) -> true; true -> false end end,
"if list([]) -> true; true -> false end.", true),
check(fun() -> if is_tuple({}) -> true; true -> false end end,
"if is_tuple({}) -> true; true -> false end.", true),
check(fun() -> if tuple({}) -> true; true -> false end end,
"if tuple({}) -> true; true -> false end.", true),
check(fun() -> if is_pid(self()) -> true; true -> false end end,
"if is_pid(self()) -> true; true -> false end.", true),
check(fun() -> if pid(self()) -> true; true -> false end end,
"if pid(self()) -> true; true -> false end.", true),
check(fun() -> R = make_ref(), if is_reference(R) -> true;
true -> false end end,
"begin R = make_ref(), if is_reference(R) -> true;"
"true -> false end end.", true),
check(fun() -> R = make_ref(), if reference(R) -> true;
true -> false end end,
"begin R = make_ref(), if reference(R) -> true;"
"true -> false end end.", true),
check(fun() -> if is_port(a) -> true; true -> false end end,
"if is_port(a) -> true; true -> false end.", false),
check(fun() -> if port(a) -> true; true -> false end end,
"if port(a) -> true; true -> false end.", false),
check(fun() -> if is_function(a) -> true; true -> false end end,
"if is_function(a) -> true; true -> false end.", false),
check(fun() -> if function(a) -> true; true -> false end end,
"if function(a) -> true; true -> false end.", false),
check(fun() -> if is_binary(<<>>) -> true; true -> false end end,
"if is_binary(<<>>) -> true; true -> false end.", true),
check(fun() -> if binary(<<>>) -> true; true -> false end end,
"if binary(<<>>) -> true; true -> false end.", true),
check(fun() -> if is_integer(a) == true -> yes;
true -> no end end,
"if is_integer(a) == true -> yes;
Expand Down
28 changes: 12 additions & 16 deletions lib/stdlib/test/erl_expand_records_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ pattern(Config) when is_list(Config) ->
11;
t(L) when is_list(L) ->
12;
t({L}) when list(L) ->
t({L}) when is_list(L) ->
13;
t({a,b}) ->
14;
Expand All @@ -343,21 +343,21 @@ pattern(Config) when is_list(Config) ->
21;
t(#r.a) ->
22;
t(A) when is_record(A, r), record(element(2, A), r) ->
t(A) when is_record(A, r), is_record(element(2, A), r) ->
23;
t(A) when is_record(A, r) ->
1;
t(I) when is_integer(I) ->
3;
t({I}) when integer(I) ->
t({I}) when is_integer(I) ->
4;
t({F}) when float(F) ->
t({F}) when is_float(F) ->
7;
t({A} = B) when A < B ->
19;
t(F) when is_float(F) ->
6;
t(T) when tuple(T) ->
t(T) when is_tuple(T) ->
16.
">>
],
Expand Down Expand Up @@ -485,17 +485,17 @@ otp_5915(Config) when is_list(Config) ->
2 end(2),
3 = fun(A) when (A#r2.a)#r1.a =:= 3 -> 3 end(#r2{a = #r1{a = 3}}),
ok = fun() ->
F = fun(A) when record(A#r.a, r1) -> 4;
(A) when record(A#r1.a, r1) -> 5
F = fun(A) when is_record(A#r.a, r1) -> 4;
(A) when is_record(A#r1.a, r1) -> 5
end,
5 = F(#r1{a = #r1{}}),
4 = F(#r{a = #r1{}}),
ok
end(),
3 = fun(A) when record(A#r1.a, r),
3 = fun(A) when is_record(A#r1.a, r),
(A#r1.a)#r.a > 3 -> 3
end(#r1{a = #r{a = 4}}),
7 = fun(A) when record(A#r3.a, r1) -> 7 end(#r3{}),
7 = fun(A) when is_record(A#r3.a, r1) -> 7 end(#r3{}),
[#r1{a = 2,b = 1}] =
fun() ->
[A || A <- [#r1{a = 1, b = 3},
Expand Down Expand Up @@ -523,7 +523,7 @@ otp_5915(Config) when is_list(Config) ->
end(#r1{a = 2}),

3 = fun(A) when A#r1.a > 3,
record(A, r1) -> 3
is_record(A, r1) -> 3
end(#r1{a = 5}),

ok = fun() ->
Expand Down Expand Up @@ -554,10 +554,6 @@ otp_5915(Config) when is_list(Config) ->
ok
end(),

a = fun(A) when record(A, r),
A#r.a =:= 1,
A#r.b =:= 2 ->a
end(#r{a = 1, b = 2}),
a = fun(A) when erlang:is_record(A, r),
A#r.a =:= 1,
A#r.b =:= 2 -> a
Expand Down Expand Up @@ -719,11 +715,11 @@ otp_5990(Config) when is_list(Config) ->
-record('OrdSet', {orddata = {},
ordtype = {}}).

to_sets(S) when tuple(S#'OrdSet'.ordtype) ->
to_sets(S) when is_tuple(S#'OrdSet'.ordtype) ->
ok.

lc(S) ->
[X || X <- [S], tuple(X#'OrdSet'.ordtype)].
[X || X <- [S], is_tuple(X#'OrdSet'.ordtype)].

t() ->
S = #'OrdSet'{},
Expand Down
Loading
Loading