summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/stdlib/src/erl_expand_records.erl8
-rw-r--r--lib/stdlib/src/erl_lint.erl37
-rw-r--r--lib/stdlib/test/erl_expand_records_SUITE.erl16
3 files changed, 46 insertions, 15 deletions
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index 83f21670c2..7715f7d458 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -30,6 +30,7 @@
vcount=0, % Variable counter
calltype=#{}, % Call types
records=#{}, % Record definitions
+ raw_records=[],% Raw record forms
strict_ra=[], % strict record accesses
checked_ra=[], % successfully accessed records
dialyzer=false % Cached value of compile flag 'dialyzer'
@@ -70,7 +71,8 @@ init_calltype_imports([], Ctype) -> Ctype.
forms([{attribute,_,record,{Name,Defs}}=Attr | Fs], St0) ->
NDefs = normalise_fields(Defs),
- St = St0#exprec{records=maps:put(Name, NDefs, St0#exprec.records)},
+ St = St0#exprec{records=maps:put(Name, NDefs, St0#exprec.records),
+ raw_records=[Attr | St0#exprec.raw_records]},
{Fs1, St1} = forms(Fs, St),
{[Attr | Fs1], St1};
forms([{function,Anno,N,A,Cs0} | Fs0], St0) ->
@@ -511,7 +513,7 @@ lc_tq(Anno, [{b_generate,AnnoG,P0,G0} | Qs0], St0) ->
{P1,St2} = pattern(P0, St1),
{Qs1,St3} = lc_tq(Anno, Qs0, St2),
{[{b_generate,AnnoG,P1,G1} | Qs1],St3};
-lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype}=St0) ->
+lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype,raw_records=Records}=St0) ->
%% Allow record/2 and expand out as guard test.
IsOverriden = fun(FA) ->
case Calltype of
@@ -520,7 +522,7 @@ lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype}=St0) ->
_ -> false
end
end,
- case erl_lint:is_guard_test(F0, [], IsOverriden) of
+ case erl_lint:is_guard_test(F0, Records, IsOverriden) of
true ->
{F1,St1} = guard_test(F0, St0),
{Qs1,St2} = lc_tq(Anno, Qs0, St1),
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 7400e3c64d..b9b58d6576 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2299,17 +2299,24 @@ is_guard_test(Expression, Forms) ->
IsOverridden :: fun((fa()) -> boolean()).
is_guard_test(Expression, Forms, IsOverridden) ->
- RecordAttributes = [A || A = {attribute, _, record, _D} <- Forms],
- is_guard_test1(set_file(Expression, "nofile"), RecordAttributes, IsOverridden).
-
-is_guard_test1(NoFileExpression, [], IsOverridden) ->
- is_guard_test2(NoFileExpression, {maps:new(),IsOverridden});
-is_guard_test1(NoFileExpression, RecordAttributes, IsOverridden) ->
- St0 = foldl(fun(Attr0, St1) ->
- Attr = set_file(Attr0, "none"),
- attribute_state(Attr, St1)
- end, start(), RecordAttributes),
- is_guard_test2(NoFileExpression, {St0#lint.records,IsOverridden}).
+ NoFileExpression = set_file(Expression, "nofile"),
+
+ %% Unless the expression constructs a record, the record
+ %% definitions are not needed. Therefore, because there can be a
+ %% huge number of record definitions in the forms, delay
+ %% processing the forms until we'll know that the record
+ %% definitions are truly needed.
+ F = fun() ->
+ St = foldl(fun({attribute, _, record, _}=Attr0, St0) ->
+ Attr = set_file(Attr0, "none"),
+ attribute_state(Attr, St0);
+ (_, St0) ->
+ St0
+ end, start(), Forms),
+ St#lint.records
+ end,
+
+ is_guard_test2(NoFileExpression, {F,IsOverridden}).
%% is_guard_test2(Expression, RecordDefs :: dict:dict()) -> boolean().
is_guard_test2({call,Anno,{atom,Ar,record},[E,A]}, Info) ->
@@ -2347,7 +2354,13 @@ is_gexpr({record_index,_A,_Name,Field}, Info) ->
is_gexpr(Field, Info);
is_gexpr({record_field,_A,Rec,_Name,Field}, Info) ->
is_gexpr_list([Rec,Field], Info);
-is_gexpr({record,A,Name,Inits}, Info) ->
+is_gexpr({record,A,Name,Inits}, Info0) ->
+ Info = case Info0 of
+ {#{},_} ->
+ Info0;
+ {F,IsOverridden} when is_function(F, 0) ->
+ {F(),IsOverridden}
+ end,
is_gexpr_fields(Inits, A, Name, Info);
is_gexpr({bin,_A,Fs}, Info) ->
all(fun ({bin_element,_Anno,E,Sz,_Ts}) ->
diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl
index c48a1ac90e..ea5cc4a354 100644
--- a/lib/stdlib/test/erl_expand_records_SUITE.erl
+++ b/lib/stdlib/test/erl_expand_records_SUITE.erl
@@ -148,6 +148,22 @@ expr(Config) when is_list(Config) ->
is_record(_, _, _) ->
error(wrong_is_record).
+ ">>,
+ <<"
+ -record(foo, {bar = [Bar || Bar <- ?MODULE:id([]), size(Bar) > 0]}).
+
+ t() ->
+ {'EXIT',{{bad_filter,{foo,[]}},[_|_]}} = catch gh6501a(whatever),
+ [whatever] = gh6501b(whatever),
+ ok.
+
+ gh6501a(Bar) ->
+ [Bar || #foo{}].
+
+ gh6501b(Bar) ->
+ [Bar || is_tuple(#foo{})].
+
+ id(I) -> I.
">>
],