diff options
Diffstat (limited to 'lib/stdlib')
-rw-r--r-- | lib/stdlib/doc/src/array.xml | 3 | ||||
-rw-r--r-- | lib/stdlib/doc/src/dict.xml | 3 | ||||
-rw-r--r-- | lib/stdlib/doc/src/gb_sets.xml | 6 | ||||
-rw-r--r-- | lib/stdlib/doc/src/gb_trees.xml | 6 | ||||
-rw-r--r-- | lib/stdlib/doc/src/queue.xml | 3 | ||||
-rw-r--r-- | lib/stdlib/doc/src/sets.xml | 3 | ||||
-rw-r--r-- | lib/stdlib/doc/src/unicode_usage.xml | 5 | ||||
-rw-r--r-- | lib/stdlib/src/array.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/dict.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/erl_parse.yrl | 64 | ||||
-rw-r--r-- | lib/stdlib/src/erl_pp.erl | 127 | ||||
-rw-r--r-- | lib/stdlib/src/ets.erl | 28 | ||||
-rw-r--r-- | lib/stdlib/src/gb_sets.erl | 5 | ||||
-rw-r--r-- | lib/stdlib/src/gb_trees.erl | 5 | ||||
-rw-r--r-- | lib/stdlib/src/otp_internal.erl | 13 | ||||
-rw-r--r-- | lib/stdlib/src/queue.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/sets.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/supervisor.erl | 27 | ||||
-rw-r--r-- | lib/stdlib/test/erl_pp_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/test/ets_SUITE.erl | 29 | ||||
-rw-r--r-- | lib/stdlib/test/supervisor_SUITE.erl | 29 |
21 files changed, 215 insertions, 151 deletions
diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml index b03a2fa0cc..af23cd95d9 100644 --- a/lib/stdlib/doc/src/array.xml +++ b/lib/stdlib/doc/src/array.xml @@ -93,9 +93,6 @@ the default value cannot be confused with the values of set entries.</p> </datatype> <datatype> <name name="array" n_vars="0"/> - <desc> - <p><c>array()</c> is equivalent to <c>array(term())</c>.</p> - </desc> </datatype> <datatype> <name name="array_indx"/> diff --git a/lib/stdlib/doc/src/dict.xml b/lib/stdlib/doc/src/dict.xml index 0771682a25..b456b97578 100644 --- a/lib/stdlib/doc/src/dict.xml +++ b/lib/stdlib/doc/src/dict.xml @@ -46,9 +46,6 @@ </datatype> <datatype> <name name="dict" n_vars="0"/> - <desc> - <p><c>dict()</c> is equivalent to <c>dict(term(), term())</c>.</p> - </desc> </datatype> </datatypes> <funcs> diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml index 405bae5698..99e92d8680 100644 --- a/lib/stdlib/doc/src/gb_sets.xml +++ b/lib/stdlib/doc/src/gb_sets.xml @@ -120,9 +120,6 @@ </datatype> <datatype> <name name="set" n_vars="0"/> - <desc> - <p><c>set()</c> is equivalent to <c>set(term())</c>.</p> - </desc> </datatype> <datatype> <name name="iter" n_vars="1"/> @@ -130,9 +127,6 @@ </datatype> <datatype> <name name="iter" n_vars="0"/> - <desc> - <p><c>iter()</c> is equivalent to <c>iter(term())</c>.</p> - </desc> </datatype> </datatypes> <funcs> diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml index 82167e1083..99ca2d6a9a 100644 --- a/lib/stdlib/doc/src/gb_trees.xml +++ b/lib/stdlib/doc/src/gb_trees.xml @@ -64,9 +64,6 @@ </datatype> <datatype> <name name="tree" n_vars="0"/> - <desc> - <p><c>tree()</c> is equivalent to <c>tree(term(), term())</c>.</p> - </desc> </datatype> <datatype> <name name="iter" n_vars="2"/> @@ -74,9 +71,6 @@ </datatype> <datatype> <name name="iter" n_vars="0"/> - <desc> - <p><c>iter()</c> is equivalent to <c>iter(term(), term())</c>.</p> - </desc> </datatype> </datatypes> <funcs> diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml index 9c994154d4..f689412988 100644 --- a/lib/stdlib/doc/src/queue.xml +++ b/lib/stdlib/doc/src/queue.xml @@ -95,9 +95,6 @@ </datatype> <datatype> <name name="queue" n_vars="0"/> - <desc> - <p><c>queue()</c> is equivalent to <c>queue(term())</c>.</p> - </desc> </datatype> </datatypes> diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml index 4a31648f8f..eecddb7fd4 100644 --- a/lib/stdlib/doc/src/sets.xml +++ b/lib/stdlib/doc/src/sets.xml @@ -50,9 +50,6 @@ </datatype> <datatype> <name name="set" n_vars="0"/> - <desc> - <p><c>set()</c> is equivalent to <c>set(term())</c>.</p> - </desc> </datatype> </datatypes> <funcs> diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml index 29b8940c62..eb3a556e10 100644 --- a/lib/stdlib/doc/src/unicode_usage.xml +++ b/lib/stdlib/doc/src/unicode_usage.xml @@ -850,8 +850,9 @@ Eshell V5.10.1 (abort with ^G) expected to be in Unicode.</p> <p>If Unicode file names are enabled, the calls to <seealso marker="kernel:os#getenv/0"><c>os:getenv/0</c></seealso>, - <seealso marker="kernel:os#getenv/1"><c>os:getenv/1</c></seealso> and - <seealso marker="kernel:os#putenv/2"><c>os:putenv/2</c></seealso> + <seealso marker="kernel:os#getenv/1"><c>os:getenv/1</c></seealso>, + <seealso marker="kernel:os#putenv/2"><c>os:putenv/2</c></seealso> and + <seealso marker="kernel:os#unsetenv/1"><c>os:unsetenv/1</c></seealso> will handle Unicode strings. On Unix-like platforms, the built-in functions will translate environment variables in UTF-8 to/from Unicode strings, possibly with code points > 255. On Windows the diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl index 10d2ccea45..f98a587c55 100644 --- a/lib/stdlib/src/array.erl +++ b/lib/stdlib/src/array.erl @@ -164,7 +164,7 @@ elements :: elements(_) %% the tuple tree }). --opaque array() :: array(term()). +-type array() :: array(term()). -opaque array(Type) :: #array{default :: Type, elements :: elements(Type)}. diff --git a/lib/stdlib/src/dict.erl b/lib/stdlib/src/dict.erl index 5a9f63c5e2..d2af9554a1 100644 --- a/lib/stdlib/src/dict.erl +++ b/lib/stdlib/src/dict.erl @@ -70,7 +70,7 @@ }). --opaque dict() :: dict(_, _). +-type dict() :: dict(_, _). -opaque dict(Key, Value) :: #dict{segs :: segs(Key, Value)}. diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index e328e065e3..274bb2a782 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -125,22 +125,19 @@ top_type_100 -> type_200 : '$1'. top_type_100 -> type_200 '|' top_type_100 : lift_unions('$1','$3'). type_200 -> type_300 '..' type_300 : {type, ?anno('$1'), range, - [skip_paren('$1'), - skip_paren('$3')]}. + ['$1', '$3']}. type_200 -> type_300 : '$1'. -type_300 -> type_300 add_op type_400 : ?mkop2(skip_paren('$1'), - '$2', skip_paren('$3')). +type_300 -> type_300 add_op type_400 : ?mkop2('$1', '$2', '$3'). type_300 -> type_400 : '$1'. -type_400 -> type_400 mult_op type_500 : ?mkop2(skip_paren('$1'), - '$2', skip_paren('$3')). +type_400 -> type_400 mult_op type_500 : ?mkop2('$1', '$2', '$3'). type_400 -> type_500 : '$1'. -type_500 -> prefix_op type : ?mkop1('$1', skip_paren('$2')). +type_500 -> prefix_op type : ?mkop1('$1', '$2'). type_500 -> type : '$1'. -type -> '(' top_type ')' : {paren_type, ?anno('$2'), ['$2']}. +type -> '(' top_type ')' : '$2'. type -> var : '$1'. type -> atom : '$1'. type -> atom '(' ')' : build_gen_type('$1'). @@ -524,6 +521,7 @@ Erlang code. -export([normalise/1,abstract/1,tokens/1,tokens/2]). -export([abstract/2]). -export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]). +-export([type_inop_prec/1,type_preop_prec/1]). -export([map_anno/2, fold_anno/3, mapfold_anno/3, new_anno/1, anno_to_term/1, anno_from_term/1]). -export([set_line/2,get_attribute/2,get_attributes/1]). @@ -671,11 +669,6 @@ lift_unions(T1, {type, _Aa, union, List}) -> lift_unions(T1, T2) -> {type, ?anno(T1), union, [T1, T2]}. -skip_paren({paren_type,_A,[Type]}) -> - skip_paren(Type); -skip_paren(Type) -> - Type. - build_gen_type({atom, Aa, tuple}) -> {type, Aa, tuple, any}; build_gen_type({atom, Aa, map}) -> @@ -687,7 +680,7 @@ build_gen_type({atom, Aa, Name}) -> build_bin_type([{var, _, '_'}|Left], Int) -> build_bin_type(Left, Int); build_bin_type([], Int) -> - skip_paren(Int); + Int; build_bin_type([{var, Aa, _}|_], _) -> ret_err(Aa, "Bad binary type"). @@ -807,8 +800,7 @@ record_fields([{typed,Expr,TypeInfo}|Fields]) -> {atom, Aa, _} -> case has_undefined(TypeInfo) of false -> - TypeInfo2 = maybe_add_paren(TypeInfo), - lift_unions(abstract2(undefined, Aa), TypeInfo2); + lift_unions(abstract2(undefined, Aa), TypeInfo); true -> TypeInfo end @@ -822,18 +814,11 @@ has_undefined({atom,_,undefined}) -> true; has_undefined({ann_type,_,[_,T]}) -> has_undefined(T); -has_undefined({paren_type,_,[T]}) -> - has_undefined(T); has_undefined({type,_,union,Ts}) -> lists:any(fun has_undefined/1, Ts); has_undefined(_) -> false. -maybe_add_paren({ann_type,A,T}) -> - {paren_type,A,[{ann_type,A,T}]}; -maybe_add_paren(T) -> - T. - term(Expr) -> try normalise(Expr) catch _:_R -> ret_err(?anno(Expr), "bad attribute") @@ -1099,6 +1084,39 @@ func_prec() -> {800,700}. max_prec() -> 900. +-type prec() :: non_neg_integer(). + +-type type_inop() :: '::' | '|' | '..' | '+' | '-' | 'bor' | 'bxor' + | 'bsl' | 'bsr' | '*' | '/' | 'div' | 'rem' | 'band'. + +-type type_preop() :: '+' | '-' | 'bnot' | '#'. + +-spec type_inop_prec(type_inop()) -> {prec(), prec(), prec()}. + +type_inop_prec('=') -> {150,100,100}; +type_inop_prec('::') -> {160,150,150}; +type_inop_prec('|') -> {180,170,170}; +type_inop_prec('..') -> {300,200,300}; +type_inop_prec('+') -> {400,400,500}; +type_inop_prec('-') -> {400,400,500}; +type_inop_prec('bor') -> {400,400,500}; +type_inop_prec('bxor') -> {400,400,500}; +type_inop_prec('bsl') -> {400,400,500}; +type_inop_prec('bsr') -> {400,400,500}; +type_inop_prec('*') -> {500,500,600}; +type_inop_prec('/') -> {500,500,600}; +type_inop_prec('div') -> {500,500,600}; +type_inop_prec('rem') -> {500,500,600}; +type_inop_prec('band') -> {500,500,600}; +type_inop_prec('#') -> {800,700,800}. + +-spec type_preop_prec(type_preop()) -> {prec(), prec()}. + +type_preop_prec('+') -> {600,700}; +type_preop_prec('-') -> {600,700}; +type_preop_prec('bnot') -> {600,700}; +type_preop_prec('#') -> {700,800}. + %%% [Experimental]. The parser just copies the attributes of the %%% scanner tokens to the abstract format. This design decision has %%% been hidden to some extent: use set_line() and get_attribute() to diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index 623a29f923..6da585b72e 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -27,7 +27,8 @@ -import(lists, [append/1,foldr/3,mapfoldl/3,reverse/1,reverse/2]). -import(io_lib, [write/1,format/2]). --import(erl_parse, [inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]). +-import(erl_parse, [inop_prec/1,preop_prec/1,func_prec/0,max_prec/0, + type_inop_prec/1, type_preop_prec/1]). -define(MAXLINE, 72). @@ -271,49 +272,64 @@ typeattr(Tag, {TypeName,Type,Args}, _Opts) -> {first,leaf("-"++atom_to_list(Tag)++" "), typed(call({atom,a0(),TypeName}, Args, 0, options(none)), Type)}. -ltype({ann_type,_Line,[V,T]}) -> - typed(lexpr(V, options(none)), T); -ltype({paren_type,_Line,[T]}) -> - [$(,ltype(T),$)]; -ltype({type,_Line,union,Ts}) -> - {seq,[],[],[' |'],ltypes(Ts)}; -ltype({type,_Line,list,[T]}) -> +ltype(T) -> + ltype(T, 0). + +ltype({ann_type,_Line,[V,T]}, Prec) -> + {_L,P,_R} = type_inop_prec('::'), + E = typed(lexpr(V, options(none)), T), + maybe_paren(P, Prec, E); +ltype({paren_type,_Line,[T]}, P) -> + %% Generated before Erlang/OTP 18. + ltype(T, P); +ltype({type,_Line,union,Ts}, Prec) -> + {_L,P,R} = type_inop_prec('|'), + E = {seq,[],[],[' |'],ltypes(Ts, R)}, + maybe_paren(P, Prec, E); +ltype({type,_Line,list,[T]}, _) -> {seq,$[,$],$,,[ltype(T)]}; -ltype({type,_Line,nonempty_list,[T]}) -> +ltype({type,_Line,nonempty_list,[T]}, _) -> {seq,$[,$],[$,],[ltype(T),leaf("...")]}; -ltype({type,Line,nil,[]}) -> - lexpr({nil,Line}, 0, options(none)); -ltype({type,Line,map,any}) -> +ltype({type,Line,nil,[]}, _) -> + lexpr({nil,Line}, options(none)); +ltype({type,Line,map,any}, _) -> simple_type({atom,Line,map}, []); -ltype({type,_Line,map,Pairs}) -> - map_type(Pairs); -ltype({type,Line,tuple,any}) -> +ltype({type,_Line,map,Pairs}, Prec) -> + {P,_R} = type_preop_prec('#'), + E = map_type(Pairs), + maybe_paren(P, Prec, E); +ltype({type,Line,tuple,any}, _) -> simple_type({atom,Line,tuple}, []); -ltype({type,_Line,tuple,Ts}) -> - tuple_type(Ts, fun ltype/1); -ltype({type,_Line,record,[{atom,_,N}|Fs]}) -> - record_type(N, Fs); -ltype({type,_Line,range,[_I1,_I2]=Es}) -> - expr_list(Es, '..', fun lexpr/2, options(none)); -ltype({type,_Line,binary,[I1,I2]}) -> +ltype({type,_Line,tuple,Ts}, _) -> + tuple_type(Ts, fun ltype/2); +ltype({type,_Line,record,[{atom,_,N}|Fs]}, Prec) -> + {P,_R} = type_preop_prec('#'), + E = record_type(N, Fs), + maybe_paren(P, Prec, E); +ltype({type,_Line,range,[_I1,_I2]=Es}, Prec) -> + {_L,P,R} = type_inop_prec('..'), + F = fun(E, Opts) -> lexpr(E, R, Opts) end, + E = expr_list(Es, '..', F, options(none)), + maybe_paren(P, Prec, E); +ltype({type,_Line,binary,[I1,I2]}, _) -> binary_type(I1, I2); % except binary() -ltype({type,_Line,'fun',[]}) -> +ltype({type,_Line,'fun',[]}, _) -> leaf("fun()"); -ltype({type,_,'fun',[{type,_,any},_]}=FunType) -> +ltype({type,_,'fun',[{type,_,any},_]}=FunType, _) -> [fun_type(['fun',$(], FunType),$)]; -ltype({type,_Line,'fun',[{type,_,product,_},_]}=FunType) -> +ltype({type,_Line,'fun',[{type,_,product,_},_]}=FunType, _) -> [fun_type(['fun',$(], FunType),$)]; -ltype({type,Line,T,Ts}) -> +ltype({type,Line,T,Ts}, _) -> %% Compatibility. Before 18.0. simple_type({atom,Line,T}, Ts); -ltype({user_type,Line,T,Ts}) -> +ltype({user_type,Line,T,Ts}, _) -> simple_type({atom,Line,T}, Ts); -ltype({remote_type,Line,[M,F,Ts]}) -> +ltype({remote_type,Line,[M,F,Ts]}, _) -> simple_type({remote,Line,M,F}, Ts); -ltype({atom,_,T}) -> +ltype({atom,_,T}, _) -> leaf(write(T)); -ltype(E) -> - lexpr(E, 0, options(none)). +ltype(E, P) -> + lexpr(E, P, options(none)). binary_type(I1, I2) -> B = [[] || {integer,_,0} <- [I1]] =:= [], @@ -327,42 +343,37 @@ map_type(Fs) -> {first,[$#],map_pair_types(Fs)}. map_pair_types(Fs) -> - tuple_type(Fs, fun map_pair_type/1). + tuple_type(Fs, fun map_pair_type/2). -map_pair_type({type,_Line,map_field_assoc,[Ktype,Vtype]}) -> - map_assoc_typed(ltype(Ktype), Vtype). +map_pair_type({type,_Line,map_field_assoc,[Ktype,Vtype]}, Prec) -> + map_assoc_typed(ltype(Ktype), Vtype, Prec). -map_assoc_typed(B, {type,_,union,Ts}) -> - {first,[B,$\s],{seq,[],[],[],map_assoc_union_type(Ts)}}; -map_assoc_typed(B, Type) -> - {list,[{cstep,[B," =>"],ltype(Type)}]}. +map_assoc_typed(B, {type,_,union,Ts}, Prec) -> + {first,[B,$\s],{seq,[],[],[],map_assoc_union_type(Ts, Prec)}}; +map_assoc_typed(B, Type, Prec) -> + {list,[{cstep,[B," =>"],ltype(Type, Prec)}]}. -map_assoc_union_type([T|Ts]) -> - [[leaf("=> "),ltype(T)] | ltypes(Ts, fun union_elem/1)]. +map_assoc_union_type([T|Ts], Prec) -> + [[leaf("=> "),ltype(T)] | ltypes(Ts, fun union_elem/2, Prec)]. record_type(Name, Fields) -> {first,[record_name(Name)],field_types(Fields)}. field_types(Fs) -> - tuple_type(Fs, fun field_type/1). + tuple_type(Fs, fun field_type/2). -field_type({type,_Line,field_type,[Name,Type]}) -> +field_type({type,_Line,field_type,[Name,Type]}, _Prec) -> typed(lexpr(Name, options(none)), Type). -typed(B, {type,_,union,Ts}) -> - %% Special layout for :: followed by union. - {first,[B,$\s],{seq,[],[],[],union_type(Ts)}}; typed(B, Type) -> - {list,[{cstep,[B,' ::'],ltype(Type)}]}. + {_L,_P,R} = type_inop_prec('::'), + {list,[{cstep,[B,' ::'],ltype(Type, R)}]}. -union_type([T|Ts]) -> - [[leaf(":: "),ltype(T)] | ltypes(Ts, fun union_elem/1)]. - -union_elem(T) -> - [leaf(" | "),ltype(T)]. +union_elem(T, Prec) -> + [leaf(" | "),ltype(T, Prec)]. tuple_type(Ts, F) -> - {seq,${,$},[$,],ltypes(Ts, F)}. + {seq,${,$},[$,],ltypes(Ts, F, 0)}. specattr(SpecKind, {FuncSpec,TypeSpecs}) -> Func = case FuncSpec of @@ -399,16 +410,16 @@ type_args({type,_line,product,Ts}) -> targs(Ts). simple_type(Tag, Types) -> - {first,lexpr(Tag, 0, options(none)),targs(Types)}. + {first,lexpr(Tag, options(none)),targs(Types)}. targs(Ts) -> - {seq,$(,$),[$,],ltypes(Ts)}. + {seq,$(,$),[$,],ltypes(Ts, 0)}. -ltypes(Ts) -> - ltypes(Ts, fun ltype/1). +ltypes(Ts, Prec) -> + ltypes(Ts, fun ltype/2, Prec). -ltypes(Ts, F) -> - [F(T) || T <- Ts]. +ltypes(Ts, F, Prec) -> + [F(T, Prec) || T <- Ts]. attr(Name, Args) -> call({var,a0(),format("-~s", [Name])}, Args, 0, options(none)). diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl index 0e2d59d0c3..bec64861c3 100644 --- a/lib/stdlib/src/ets.erl +++ b/lib/stdlib/src/ets.erl @@ -1308,18 +1308,30 @@ create_tab(I, TabArg) -> {name, Name} = lists:keyfind(name, 1, I), {type, Type} = lists:keyfind(type, 1, I), {protection, P} = lists:keyfind(protection, 1, I), - {named_table, Val} = lists:keyfind(named_table, 1, I), {keypos, _Kp} = Keypos = lists:keyfind(keypos, 1, I), {size, Sz} = lists:keyfind(size, 1, I), - Comp = case lists:keyfind(compressed, 1, I) of - {compressed, true} -> [compressed]; - {compressed, false} -> []; - false -> [] - end, + L1 = [Type, P, Keypos], + L2 = case lists:keyfind(named_table, 1, I) of + {named_table, true} -> [named_table | L1]; + {named_table, false} -> L1 + end, + L3 = case lists:keyfind(compressed, 1, I) of + {compressed, true} -> [compressed | L2]; + {compressed, false} -> L2; + false -> L2 + end, + L4 = case lists:keyfind(write_concurrency, 1, I) of + {write_concurrency, _}=Wcc -> [Wcc | L3]; + _ -> L3 + end, + L5 = case lists:keyfind(read_concurrency, 1, I) of + {read_concurrency, _}=Rcc -> [Rcc | L4]; + false -> L4 + end, case TabArg of [] -> try - Tab = ets:new(Name, [Type, P, Keypos] ++ named_table(Val) ++ Comp), + Tab = ets:new(Name, L5), {ok, Tab, Sz} catch _:_ -> throw(cannot_create_table) @@ -1328,8 +1340,6 @@ create_tab(I, TabArg) -> {ok, TabArg, Sz} end. -named_table(true) -> [named_table]; -named_table(false) -> []. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% tabfile_info/1 reads the head information in an ets table dumped to diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl index d3fbd542f7..d099737d8f 100644 --- a/lib/stdlib/src/gb_sets.erl +++ b/lib/stdlib/src/gb_sets.erl @@ -203,11 +203,10 @@ -export_type([set/0, set/1, iter/0, iter/1]). -type gb_set_node(Element) :: 'nil' | {Element, _, _}. --type gb_set_node() :: gb_set_node(_). -opaque set(Element) :: {non_neg_integer(), gb_set_node(Element)}. --opaque set() :: set(_). +-type set() :: set(_). -opaque iter(Element) :: [gb_set_node(Element)]. --opaque iter() :: [gb_set_node()]. +-type iter() :: iter(_). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/stdlib/src/gb_trees.erl b/lib/stdlib/src/gb_trees.erl index 259e8f718b..2cbfd8fd2a 100644 --- a/lib/stdlib/src/gb_trees.erl +++ b/lib/stdlib/src/gb_trees.erl @@ -160,11 +160,10 @@ -type gb_tree_node(K, V) :: 'nil' | {K, V, gb_tree_node(K, V), gb_tree_node(K, V)}. --type gb_tree_node() :: gb_tree_node(_, _). -opaque tree(Key, Value) :: {non_neg_integer(), gb_tree_node(Key, Value)}. --opaque tree() :: tree(_, _). +-type tree() :: tree(_, _). -opaque iter(Key, Value) :: [gb_tree_node(Key, Value)]. --opaque iter() :: [gb_tree_node()]. +-type iter() :: iter(_, _). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 0340015c35..62807e2e54 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -634,6 +634,19 @@ obsolete_1(ssl, negotiated_next_protocol, 1) -> obsolete_1(ssl, connection_info, 1) -> {deprecated, "deprecated; use connection_information/[1,2] instead"}; +obsolete_1(httpd_conf, check_enum, 2) -> + {deprecated, "deprecated; use lists:member/2 instead"}; +obsolete_1(httpd_conf, clean, 1) -> + {deprecated, "deprecated; use sting:strip/1 instead or possible the re module"}; +obsolete_1(httpd_conf, custom_clean, 3) -> + {deprecated, "deprecated; use sting:strip/3 instead or possible the re module"}; +obsolete_1(httpd_conf, is_directory, 1) -> + {deprecated, "deprecated; use filelib:is_dir/1 instead"}; +obsolete_1(httpd_conf, is_file, 1) -> + {deprecated, "deprecated; use filelib:is_file/1 instead"}; +obsolete_1(httpd_conf, make_integer, 1) -> + {deprecated, "deprecated; use erlang:list_to_integer/1 instead"}; + obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl index 472d503b99..d2e6848258 100644 --- a/lib/stdlib/src/queue.erl +++ b/lib/stdlib/src/queue.erl @@ -48,7 +48,7 @@ -opaque queue(Item) :: {list(Item), list(Item)}. --opaque queue() :: queue(_). +-type queue() :: queue(_). %% Creation, inspection and conversion diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl index 167a676281..041d281148 100644 --- a/lib/stdlib/src/sets.erl +++ b/lib/stdlib/src/sets.erl @@ -70,7 +70,7 @@ segs :: segs(_) % Segments }). --opaque set() :: set(_). +-type set() :: set(_). -opaque set(Element) :: #set{segs :: segs(Element)}. diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 1d7396adee..ac51bb3b79 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -393,6 +393,15 @@ handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) -> {reply, What, State} end; +handle_call({start_child, ChildSpec}, _From, State) -> + case check_childspec(ChildSpec) of + {ok, Child} -> + {Resp, NState} = handle_start_child(Child, State), + {reply, Resp, NState}; + What -> + {reply, {error, What}, State} + end; + %% terminate_child for simple_one_for_one can only be done with pid handle_call({terminate_child, Name}, _From, State) when not is_pid(Name), ?is_simple(State) -> @@ -411,20 +420,10 @@ handle_call({terminate_child, Name}, _From, State) -> {reply, {error, not_found}, State} end; -%%% The requests delete_child and restart_child are invalid for -%%% simple_one_for_one supervisors. -handle_call({_Req, _Data}, _From, State) when ?is_simple(State) -> +%% restart_child request is invalid for simple_one_for_one supervisors +handle_call({restart_child, _Name}, _From, State) when ?is_simple(State) -> {reply, {error, simple_one_for_one}, State}; -handle_call({start_child, ChildSpec}, _From, State) -> - case check_childspec(ChildSpec) of - {ok, Child} -> - {Resp, NState} = handle_start_child(Child, State), - {reply, Resp, NState}; - What -> - {reply, {error, What}, State} - end; - handle_call({restart_child, Name}, _From, State) -> case get_child(Name, State) of {value, Child} when Child#child.pid =:= undefined -> @@ -446,6 +445,10 @@ handle_call({restart_child, Name}, _From, State) -> {reply, {error, not_found}, State} end; +%% delete_child request is invalid for simple_one_for_one supervisors +handle_call({delete_child, _Name}, _From, State) when ?is_simple(State) -> + {reply, {error, simple_one_for_one}, State}; + handle_call({delete_child, Name}, _From, State) -> case get_child(Name, State) of {value, Child} when Child#child.pid =:= undefined -> diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 1d63c8e17e..afeeb5bfd4 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -1149,7 +1149,7 @@ otp_11100(Config) when is_list(Config) -> {a,{type,A1,range,[{integer,A1,1},{foo,bar}]},[]}}), "-type foo(INVALID-FORM:{foo,bar}:) :: A.\n" = pf({attribute,A1,type,{foo,{var,A1,'A'},[{foo,bar}]}}), - "-type foo() :: (INVALID-FORM:{foo,bar}: :: []).\n" = + "-type foo() :: INVALID-FORM:{foo,bar}: :: [].\n" = pf({attribute,A1,type, {foo,{paren_type,A1, [{ann_type,A1,[{foo,bar},{type,A1,nil,[]}]}]}, diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index fff6b11a38..f47c2c518d 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -117,6 +117,7 @@ init_per_testcase(Case, Config) -> start_spawn_logger(), wait_for_test_procs(), %% Ensure previous case cleaned up Dog=test_server:timetrap(test_server:minutes(20)), + put('__ETS_TEST_CASE__', Case), [{watchdog, Dog}, {test_case, Case} | Config]. end_per_testcase(_Func, Config) -> @@ -216,8 +217,9 @@ memory_check_summary(_Config) -> ets_test_spawn_logger ! {self(), get_failed_memchecks}, receive {get_failed_memchecks, FailedMemchecks} -> ok end, io:format("Failed memchecks: ~p\n",[FailedMemchecks]), - if FailedMemchecks > 3 -> - ct:fail("Too many failed (~p) memchecks", [FailedMemchecks]); + NoFailedMemchecks = length(FailedMemchecks), + if NoFailedMemchecks > 3 -> + ct:fail("Too many failed (~p) memchecks", [NoFailedMemchecks]); true -> ok end @@ -4088,8 +4090,11 @@ tab2file(Config) when is_list(Config) -> tab2file_do(FName, Opts) -> %% Write an empty ets table to a file, read back and check properties. - ?line Tab = ets_new(ets_SUITE_foo_tab, [named_table, set, private, - {keypos, 2}]), + ?line Tab = ets_new(ets_SUITE_foo_tab, [named_table, set, public, + {keypos, 2}, + compressed, + {write_concurrency,true}, + {read_concurrency,true}]), catch file:delete(FName), Res = ets:tab2file(Tab, FName, Opts), true = ets:delete(Tab), @@ -4097,10 +4102,14 @@ tab2file_do(FName, Opts) -> % ?line EtsMem = etsmem(), ?line {ok, Tab2} = ets:file2tab(FName), - ?line private = ets:info(Tab2, protection), + public = ets:info(Tab2, protection), ?line true = ets:info(Tab2, named_table), ?line 2 = ets:info(Tab2, keypos), ?line set = ets:info(Tab2, type), + true = ets:info(Tab2, compressed), + Smp = erlang:system_info(smp_support), + Smp = ets:info(Tab2, read_concurrency), + Smp = ets:info(Tab2, write_concurrency), ?line true = ets:delete(Tab2), ?line verify_etsmem(EtsMem). @@ -4319,7 +4328,7 @@ tabfile_ext4(Config) when is_list(Config) -> {error,Y} = ets:file2tab(FName,[{verify,true}]), ets:tab2file(TL,FName,[{extended_info,[md5sum]}]), {X,Y} - end || N <- lists:seq(400,500) ], + end || N <- lists:seq(500,600) ], io:format("~p~n",[Res]), file:delete(FName), ok. @@ -5921,7 +5930,7 @@ verify_etsmem({MemInfo,AllTabs}) -> io:format("Actual: ~p", [MemInfo2]), io:format("Changed tables before: ~p\n",[AllTabs -- AllTabs2]), io:format("Changed tables after: ~p\n", [AllTabs2 -- AllTabs]), - ets_test_spawn_logger ! failed_memcheck, + ets_test_spawn_logger ! {failed_memcheck, get('__ETS_TEST_CASE__')}, {comment, "Failed memory check"} end. @@ -5972,8 +5981,8 @@ spawn_logger(Procs, FailedMemchecks) -> From ! test_procs_synced, spawn_logger([From], FailedMemchecks); - failed_memcheck -> - spawn_logger(Procs, FailedMemchecks+1); + {failed_memcheck, TestCase} -> + spawn_logger(Procs, [TestCase|FailedMemchecks]); {Pid, get_failed_memchecks} -> Pid ! {get_failed_memchecks, FailedMemchecks}, @@ -5993,7 +6002,7 @@ start_spawn_logger() -> case whereis(ets_test_spawn_logger) of Pid when is_pid(Pid) -> true; _ -> register(ets_test_spawn_logger, - spawn_opt(fun () -> spawn_logger([], 0) end, + spawn_opt(fun () -> spawn_logger([], []) end, [{priority, max}])) end. diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index 015b09f35e..31d4b44f30 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -39,7 +39,8 @@ sup_start_ignore_temporary_child_start_child_simple/1, sup_start_ignore_permanent_child_start_child_simple/1, sup_start_error_return/1, sup_start_fail/1, - sup_start_map/1, sup_start_map_faulty_specs/1, + sup_start_map/1, sup_start_map_simple/1, + sup_start_map_faulty_specs/1, sup_stop_infinity/1, sup_stop_timeout/1, sup_stop_brutal_kill/1, child_adm/1, child_adm_simple/1, child_specs/1, extra_return/1, sup_flags/1]). @@ -103,7 +104,7 @@ groups() -> sup_start_ignore_permanent_child_start_child_simple, sup_start_error_return, sup_start_fail]}, {sup_start_map, [], - [sup_start_map, sup_start_map_faulty_specs]}, + [sup_start_map, sup_start_map_simple, sup_start_map_faulty_specs]}, {sup_stop, [], [sup_stop_infinity, sup_stop_timeout, sup_stop_brutal_kill]}, @@ -323,6 +324,30 @@ sup_start_map(Config) when is_list(Config) -> terminate(Pid, shutdown). %%------------------------------------------------------------------------- +%% Tests that the supervisor process starts correctly with map +%% startspec, and that the full childspec can be read when using +%% simple_one_for_one strategy. +sup_start_map_simple(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SupFlags = #{strategy=>simple_one_for_one}, + ChildSpec = #{id=>undefined, + start=>{supervisor_1, start_child, []}, + restart=>temporary}, + {ok, Pid} = start_link({ok, {SupFlags, [ChildSpec]}}), + + {ok, Child1} = supervisor:start_child(Pid, []), + {ok, Child2} = supervisor:start_child(Pid, []), + {ok, Child3} = supervisor:start_child(Pid, []), + + Spec = ChildSpec#{type=>worker, shutdown=>5000, modules=>[supervisor_1]}, + + {ok, Spec} = supervisor:get_childspec(Pid, Child1), + {ok, Spec} = supervisor:get_childspec(Pid, Child2), + {ok, Spec} = supervisor:get_childspec(Pid, Child3), + {error,not_found} = supervisor:get_childspec(Pid, self()), + terminate(Pid, shutdown). + +%%------------------------------------------------------------------------- %% Tests that the supervisor produces good error messages when start- %% and child specs are faulty. sup_start_map_faulty_specs(Config) when is_list(Config) -> |