diff options
author | Hans Bolinder <[email protected]> | 2016-11-29 09:37:21 +0100 |
---|---|---|
committer | Hans Bolinder <[email protected]> | 2016-12-01 16:07:11 +0100 |
commit | 91048957f0681dba853f5720d3618aa1c5d0255e (patch) | |
tree | 6e15b3365bc2ea4b9d7042c1d023f71bb0002f2d /lib/stdlib/test | |
parent | ca29c37928ad36cf4270fb3edffc2cf9752f2ed9 (diff) | |
download | otp-91048957f0681dba853f5720d3618aa1c5d0255e.tar.gz otp-91048957f0681dba853f5720d3618aa1c5d0255e.tar.bz2 otp-91048957f0681dba853f5720d3618aa1c5d0255e.zip |
stdilb: Check for bad type constraints in function types
The parser recognizes the 'is_subtype(V, T)' syntax for constraints,
and of course the new 'V :: T' syntax, but other variants result in an
error message. Up to now, the parser and linter have let badly formed
constraints through, and relied upon Dialyzer to emit warnings.
is_subtype/2 cannot easily be taken out from the parser. Not only
would we need find a way to emit a (linter) warning, but there also
needs to be an option for suppressing the linter warning as
compilation with +warnings_as_errors has to work. (Notice that the
abstract format representation for 'V :: T' is the same as for
'is_subtype(V, T)'.)
This correction was triggered by an email from Robert, and Kostis
created pull request 1214 to provide a fix. However, Kostis' fix
disallowed is_subtype() altogether, which breaks backward
compatibility.
As of Erlang/OTP 19.0 (ticket OTP-11879), the 'is_subtype(V, T)' is no
longer documented.
Diffstat (limited to 'lib/stdlib/test')
-rw-r--r-- | lib/stdlib/test/erl_lint_SUITE.erl | 53 | ||||
-rw-r--r-- | lib/stdlib/test/erl_pp_SUITE.erl | 13 |
2 files changed, 58 insertions, 8 deletions
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 4ee3950882..1dc7c58337 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -64,7 +64,7 @@ predef/1, maps/1,maps_type/1,maps_parallel_match/1, otp_11851/1,otp_11879/1,otp_13230/1, - record_errors/1]). + record_errors/1, otp_xxxxx/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -84,7 +84,7 @@ all() -> too_many_arguments, basic_errors, bin_syntax_errors, predef, maps, maps_type, maps_parallel_match, otp_11851, otp_11879, otp_13230, - record_errors]. + record_errors, otp_xxxxx]. groups() -> [{unused_vars_warn, [], @@ -3869,6 +3869,55 @@ record_errors(Config) when is_list(Config) -> {3,erl_lint,{redefine_field,r,a}}],[]}}], run(Config, Ts). +otp_xxxxx(Config) -> + Ts = [{constraint1, + <<"-export([t/1]). + -spec t(X) -> X when is_subtype(integer()). + t(a) -> foo:bar(). + ">>, + [], + {errors, + [{2,erl_parse,"unsupported constraint " ++ ["is_subtype"]}], + []}}, + {constraint2, + <<"-export([t/1]). + -spec t(X) -> X when bad_atom(X, integer()). + t(a) -> foo:bar(). + ">>, + [], + {errors, + [{2,erl_parse,"unsupported constraint " ++ ["bad_atom"]}], + []}}, + {constraint3, + <<"-export([t/1]). + -spec t(X) -> X when is_subtype(bad_variable, integer()). + t(a) -> foo:bar(). + ">>, + [], + {errors,[{2,erl_parse,"bad type variable"}],[]}}, + {constraint4, + <<"-export([t/1]). + -spec t(X) -> X when is_subtype(atom(), integer()). + t(a) -> foo:bar(). + ">>, + [], + {errors,[{2,erl_parse,"bad type variable"}],[]}}, + {constraint5, + <<"-export([t/1]). + -spec t(X) -> X when is_subtype(X, integer()). + t(a) -> foo:bar(). + ">>, + [], + []}, + {constraint6, + <<"-export([t/1]). + -spec t(X) -> X when X :: integer(). + t(a) -> foo:bar(). + ">>, + [], + []}], + run(Config, Ts). + run(Config, Tests) -> F = fun({N,P,Ws,E}, BadL) -> case catch run_test(Config, P, Ws) of diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 13c5662741..31ea3210a8 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -825,12 +825,13 @@ type_examples() -> %% is_subtype(V, T) syntax, we need a few examples of the syntax. {ex31,<<"-spec t1(FooBar :: t99()) -> t99();" "(t2()) -> t2();" - "('\\'t::4'()) -> '\\'t::4'() when is_subtype('\\'t::4'(), t24);" - "(t23()) -> t23() when is_subtype(t23(), atom())," - " is_subtype(t23(), t14());" - "(t24()) -> t24() when is_subtype(t24(), atom())," - " is_subtype(t24(), t14())," - " is_subtype(t24(), '\\'t::4'()).">>}, + "('\\'t::4'()) -> {'\\'t::4'(), B}" + " when is_subtype(B, '\\'t::4'());" + "(t23()) -> C when is_subtype(C, atom())," + " is_subtype(C, t14());" + "(t24()) -> D when is_subtype(D, atom())," + " is_subtype(D, t14())," + " is_subtype(D, '\\'t::4'()).">>}, {ex32,<<"-spec mod:t2() -> any(). ">>}, {ex33,<<"-opaque attributes_data() :: " "[{'column', column()} | {'line', info_line()} |" |