diff options
author | Björn Gustavsson <[email protected]> | 2016-08-15 15:34:06 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-09-02 14:24:36 +0200 |
commit | 0baa07cdf2754748bbc2d969bf83f08c0976fb78 (patch) | |
tree | b5d649dbe4778d8488ae09a99e68435adc216342 /lib/stdlib/test/qlc_SUITE.erl | |
parent | 8a04dd4dd2d479efe488b0bed118e10559835fb6 (diff) | |
download | otp-0baa07cdf2754748bbc2d969bf83f08c0976fb78.tar.gz otp-0baa07cdf2754748bbc2d969bf83f08c0976fb78.tar.bz2 otp-0baa07cdf2754748bbc2d969bf83f08c0976fb78.zip |
Fix overridden BIFs
The filters in a list comprehension can be guard expressions or
an ordinary expressions.
If a guard expression is used as a filter, an exception will basically
mean the same as 'false':
t() ->
L = [{some_tag,42},an_atom],
[X || X <- L, element(1, X) =:= some_tag]
%% Returns [{some_tag,42}]
On the other hand, if an ordinary expression is used as a filter, there
will be an exception:
my_element(N, T) -> element(N, T).
t() ->
L = [{some_tag,42},an_atom],
[X || X <- L, my_element(1, X) =:= some_tag]
%% Causes a 'badarg' exception when element(1, an_atom) is evaluated
It has been allowed for several releases to override a BIF with
a local function. Thus, if we define a function called element/2,
it will be called instead of the BIF element/2 within the module.
We must use the "erlang:" prefix to call the BIF.
Therefore, the following code is expected to work the same way as in
our second example above:
-compile({no_auto_import,[element/2]}).
element(N, T) ->
erlang:element(N, T).
t() ->
L = [{some_tag,42},an_atom],
[X || X <- L, element(1, X) =:= some_tag].
%% Causes a 'badarg' exception when element(1, an_atom) is evaluated
But the compiler refuses to compile the code with the following
diagnostic:
call to local/imported function element/2 is illegal in guard
Diffstat (limited to 'lib/stdlib/test/qlc_SUITE.erl')
-rw-r--r-- | lib/stdlib/test/qlc_SUITE.erl | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl index 2bd940020c..8c7d5a5fcf 100644 --- a/lib/stdlib/test/qlc_SUITE.erl +++ b/lib/stdlib/test/qlc_SUITE.erl @@ -58,7 +58,7 @@ -export([ badarg/1, nested_qlc/1, unused_var/1, lc/1, fun_clauses/1, filter_var/1, single/1, exported_var/1, generator_vars/1, - nomatch/1, errors/1, pattern/1, + nomatch/1, errors/1, pattern/1, overridden_bif/1, eval/1, cursor/1, fold/1, eval_unique/1, eval_cache/1, append/1, evaluator/1, string_to_handle/1, table/1, process_dies/1, @@ -126,7 +126,7 @@ groups() -> [{parse_transform, [], [badarg, nested_qlc, unused_var, lc, fun_clauses, filter_var, single, exported_var, generator_vars, - nomatch, errors, pattern]}, + nomatch, errors, pattern, overridden_bif]}, {evaluation, [], [eval, cursor, fold, eval_unique, eval_cache, append, evaluator, string_to_handle, table, process_dies, sort, @@ -468,6 +468,23 @@ pattern(Config) when is_list(Config) -> -record(k, {t,v}).\n">>, Ts), ok. +%% Override a guard BIF with an imported or local function. +overridden_bif(Config) -> + Ts = [ + <<"[2] = qlc:e(qlc:q([P || P <- [1,2,3], port(P)])), + [10] = qlc:e(qlc:q([P || P <- [0,9,10,11,12], + (is_reference(P) andalso P > 5)])), + Empty = gb_sets:empty(), Single = gb_sets:singleton(42), + GbSets = [Empty,Single], + [Single] = qlc:e(qlc:q([S || S <- GbSets, size(S) =/= 0])) + ">> + ], + run(Config, "-import(gb_sets, [size/1]). + -compile({no_auto_import, [size/1, is_reference/1]}). + port(N) -> N rem 2 =:= 0. + is_reference(N) -> N rem 10 =:= 0.\n", Ts), + ok. + %% eval/2 eval(Config) when is_list(Config) -> |