From 47513757332b35d47e9ef53209af69b8d988f5ac Mon Sep 17 00:00:00 2001 From: lucioleKi Date: Thu, 25 Jan 2024 15:32:57 +0100 Subject: [PATCH] dialyzer: Introduce nominal types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR implements [EEP-69: Nominal Types](https://www.erlang.org/eeps/eep-0069) in Dialyzer. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer. All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparison are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, `meter()` and `foot()` are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer(). -type meter() :: integer(). -type foot() :: integer(). Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax `-nominal` for declaring nominal types. Under nominal typing, `meter()` and `foot()` are no longer compatible. Whenever a function expects type `meter()`, passing in type `foot()` would result in a Dialyzer error. -nominal meter() :: integer(). -nominal foot() :: integer(). More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in `erl_types.erl`. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings. Backwards compatibility for opaque type-checking is **not** preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning `opaque_union` is added, together with a Dialyzer option `no_opaque_union` to turn this kind of warnings off. This PR is likely not bug-free, but not having it in master is blocking other changes to Dialyzer. Once nominal type-checking and the new opaque type-checking are applied to more codebases, we will fix the bugs as they appear. Co-authored-by: John Högberg --- .../lib/compiler/ebin/beam_core_to_ssa.beam | Bin 59604 -> 59652 bytes bootstrap/lib/compiler/ebin/beam_disasm.beam | Bin 26708 -> 26736 bytes bootstrap/lib/compiler/ebin/beam_doc.beam | Bin 20592 -> 20592 bytes bootstrap/lib/compiler/ebin/beam_ssa.beam | Bin 16180 -> 16352 bytes .../lib/compiler/ebin/beam_ssa_alias.beam | Bin 22612 -> 24616 bytes .../lib/compiler/ebin/beam_ssa_bc_size.beam | Bin 9588 -> 9760 bytes .../lib/compiler/ebin/beam_ssa_dead.beam | Bin 16532 -> 16580 bytes bootstrap/lib/compiler/ebin/beam_ssa_opt.beam | Bin 64240 -> 64648 bytes bootstrap/lib/compiler/ebin/beam_ssa_pp.beam | Bin 10956 -> 11000 bytes .../compiler/ebin/beam_ssa_pre_codegen.beam | Bin 46480 -> 46604 bytes .../lib/compiler/ebin/beam_ssa_type.beam | Bin 43396 -> 44260 bytes bootstrap/lib/compiler/ebin/compiler.app | 10 +- bootstrap/lib/compiler/ebin/v3_core.beam | Bin 71552 -> 71552 bytes bootstrap/lib/kernel/ebin/code.beam | Bin 17684 -> 17684 bytes bootstrap/lib/kernel/ebin/group.beam | Bin 21708 -> 21560 bytes bootstrap/lib/kernel/ebin/kernel.app | 12 +- bootstrap/lib/kernel/ebin/prim_tty.beam | Bin 24596 -> 25040 bytes bootstrap/lib/kernel/ebin/user_drv.beam | Bin 20656 -> 21088 bytes bootstrap/lib/stdlib/ebin/beam_lib.beam | Bin 21900 -> 21868 bytes bootstrap/lib/stdlib/ebin/edlin_context.beam | Bin 12288 -> 12304 bytes bootstrap/lib/stdlib/ebin/erl_anno.beam | Bin 3756 -> 3908 bytes bootstrap/lib/stdlib/ebin/erl_lint.beam | Bin 106512 -> 107636 bytes bootstrap/lib/stdlib/ebin/erl_parse.beam | Bin 185452 -> 185628 bytes bootstrap/lib/stdlib/ebin/erl_scan.beam | Bin 39404 -> 39348 bytes bootstrap/lib/stdlib/ebin/qlc_pt.beam | Bin 68424 -> 68516 bytes bootstrap/lib/stdlib/ebin/rand.beam | Bin 35208 -> 35240 bytes bootstrap/lib/stdlib/ebin/stdlib.app | 9 +- bootstrap/lib/stdlib/ebin/supervisor.beam | Bin 27912 -> 28276 bytes lib/common_test/src/ct_ssh.erl | 1 + lib/compiler/src/beam_core_to_ssa.erl | 4 +- lib/compiler/src/beam_disasm.erl | 8 +- lib/compiler/src/beam_doc.erl | 2 +- lib/compiler/src/beam_ssa_dead.erl | 8 +- lib/dialyzer/src/dialyzer.erl | 79 +- lib/dialyzer/src/dialyzer.hrl | 1 + lib/dialyzer/src/dialyzer_contracts.erl | 254 +- lib/dialyzer/src/dialyzer_coordinator.erl | 3 + lib/dialyzer/src/dialyzer_dataflow.erl | 1498 +++++----- lib/dialyzer/src/dialyzer_options.erl | 9 +- lib/dialyzer/src/dialyzer_succ_typings.erl | 63 +- lib/dialyzer/src/dialyzer_typesig.erl | 5 +- lib/dialyzer/src/dialyzer_utils.erl | 6 +- lib/dialyzer/src/dialyzer_worker.erl | 1 + lib/dialyzer/src/erl_bif_types.erl | 1416 +++++----- lib/dialyzer/src/erl_types.erl | 2511 +++++++---------- lib/dialyzer/src/typer_core.erl | 2 +- lib/dialyzer/test/cplt_SUITE.erl | 6 +- lib/dialyzer/test/incremental_SUITE.erl | 3 +- .../test/indent_SUITE_data/results/dict_use | 88 +- .../test/indent_SUITE_data/results/map_galore | 12 + .../test/indent_SUITE_data/results/queue_use | 23 +- .../test/indent_SUITE_data/results/rec | 5 +- .../test/indent_SUITE_data/results/simple | 240 +- .../indent_SUITE_data/src/rec/rec_adt.erl | 5 +- .../indent_SUITE_data/src/rec/rec_use.erl | 7 +- lib/dialyzer/test/map_SUITE_data/results/loop | 9 + .../test/map_SUITE_data/results/map_galore | 1 + .../test/map_SUITE_data/results/opaque_key | 8 +- .../results/warn_function | 4 + .../test/opaque_SUITE_data/results/array | 2 +- .../test/opaque_SUITE_data/results/crash | 6 +- .../test/opaque_SUITE_data/results/dict | 21 +- .../test/opaque_SUITE_data/results/ets | 5 +- .../test/opaque_SUITE_data/results/inf_loop1 | 2 +- .../test/opaque_SUITE_data/results/inf_loop2 | 2 +- .../test/opaque_SUITE_data/results/int | 4 +- .../opaque_SUITE_data/results/mixed_opaque | 4 +- .../test/opaque_SUITE_data/results/my_queue | 4 +- .../test/opaque_SUITE_data/results/opaque | 2 +- .../test/opaque_SUITE_data/results/para | 28 +- .../test/opaque_SUITE_data/results/queue | 6 +- .../test/opaque_SUITE_data/results/rec | 3 +- .../test/opaque_SUITE_data/results/recrec | 31 + .../test/opaque_SUITE_data/results/simple | 106 +- .../test/opaque_SUITE_data/results/timer | 5 +- .../test/opaque_SUITE_data/results/union | 5 +- .../test/opaque_SUITE_data/results/weird | 4 +- .../test/opaque_SUITE_data/results/wings | 21 +- .../src/opaque/opaque_adt.erl | 30 +- .../src/opaque/opaque_bug6.erl | 9 + .../opaque_SUITE_data/src/rec/rec_adt.erl | 5 +- .../opaque_SUITE_data/src/rec/rec_use.erl | 7 +- .../opaque_SUITE_data/src/timer/timer_use.erl | 3 +- .../test/overspecs_SUITE_data/results/opaque | 3 +- lib/dialyzer/test/r9c_SUITE_data/results/asn1 | 2 + .../test/r9c_SUITE_data/results/mnesia | 15 +- .../test/small_SUITE_data/results/bif1 | 1 - .../test/small_SUITE_data/results/maps_sum | 6 +- .../test/underspecs_SUITE_data/results/opaque | 4 +- .../results/lc_warnings | 1 - .../user_SUITE_data/results/gcpFlowControl | 1 + lib/diameter/src/base/diameter_service.erl | 6 +- lib/diameter/src/base/diameter_sup.erl | 3 +- lib/edoc/src/edoc_doclet_markdown.erl | 4 +- lib/edoc/src/edoc_layout_chunks.erl | 2 +- lib/edoc/src/edoc_specs.erl | 2 + lib/eunit/src/eunit_lib.erl | 1 + lib/kernel/src/code.erl | 2 + lib/mnesia/src/mnesia_lib.erl | 2 + lib/mnesia/src/mnesia_loader.erl | 1 + lib/mnesia/src/mnesia_schema.erl | 1 + lib/parsetools/src/leex.erl | 12 +- lib/runtime_tools/src/observer_backend.erl | 14 +- lib/snmp/src/agent/snmpa_mib.erl | 1 + lib/snmp/src/agent/snmpa_vacm.erl | 1 + lib/ssh/src/ssh_client_channel.erl | 2 +- lib/ssl/src/ssl_gen_statem.erl | 7 +- lib/stdlib/src/erl_anno.erl | 4 +- lib/stdlib/src/erl_lint.erl | 19 +- lib/stdlib/src/erl_parse.yrl | 12 +- lib/syntax_tools/src/erl_recomment.erl | 6 - lib/syntax_tools/src/merl_transform.erl | 1 + 112 files changed, 3191 insertions(+), 3573 deletions(-) create mode 100644 lib/dialyzer/test/opaque_SUITE_data/results/recrec create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug6.erl diff --git a/bootstrap/lib/compiler/ebin/beam_core_to_ssa.beam b/bootstrap/lib/compiler/ebin/beam_core_to_ssa.beam index 73722b3f8ac56f93b04966317d807652593c396c..20ff28e73c82f89eba9cb183d22b6873f8073e5e 100644 GIT binary patch delta 13863 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 UoOwyFIWB!U`@mNE!BTjPOOlJ(eV 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 J(?9>{{{TwY*fszF diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam index 7eabf02fe1000ce75085352c14dfeeb05196a7ea..c9669f8140bb1f9836b025aa98c5ab84f0f187eb 100644 GIT binary patch delta 11025 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 delta 10788 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 Mx%+1LvZ0Q@0cR#_x&QzG delta 1670 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�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 diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_alias.beam b/bootstrap/lib/compiler/ebin/beam_ssa_alias.beam index 254ae9d62fe6cd577c0cd18a56ce0475596ee3c0..b783dd1ced4628d92034054a1cdfdfec8dd7df12 100644 GIT binary patch literal 24616 zcmb7s349yH6}QGKCsW~VH(3#Lvtb1+F-w$4fSh2umSiFV0)Y(XwiQW9lsLAKVvQ<;=6^csyNNw5>JSS~(};@qFgvPd@qh&0UM~nH8Poa;7uWUC5M!y~T>P zB2z3|%kyi>JM*PVxwFty$(MRE-D4}VodrB*D!rwhi!!;+CHWrbS69B&o#|PU%9l#L zrNPCe-W8qQg>ofD|CLjVd%JVpsmjt)@2dVvZ*ONVpD*?=FLZa8^Of?B>O<$^zMh@6 zAB(z|Pk4o2sYRXmzrTv@Xt^(&&6mr)rLsj}f<5_FgWZLd`OejRT&l09(AzVX%XfF?yYnmZJ(W?AwxZBO)a|Bm`5Y+6q`leYd}a+$ zUon@d3i&Klcdoz_mA&Pu1pWC^p+?g%qi9d@9J)`)QUtK9>vXwDB0^QC^ zrqIn5{3!GkDxIrJg-T{ocfKDDD>9Yr(p`8cS2CrF^K%D&R`Ou4JFKtJoul{J z&QhiTZBt75>`J^XEzg&T**QLKVoSC=pDA&5VpAz!&X-o^2Sr;Cn6s;tU(pLKcIWLv zhrSj0ovwnTTW=}1!~NwDx+(*yRSGNe(9$m0&!v5N(3$I8nJEn}0?yf1TAYEkTa^-xAU~7O4d#0=9h^x%nCV%gRl2pMxj{fGkV=%hGQ}c zqvH)6RxRGU9I2WHoRB+&0Kh}JzedL&Q!wp9&n~>q<-rc<6ddgC$v@}7lhxh{gk8yH zdU|?+5vD2g12D#IhFZdXRbTOg$KQ;%y8eM5^xt1{|GwT8T^jd|$DFZpZ(k{!@5~kQ zWv(tRlwjhEOPM9)gq_Ai_64;Q{3fOrp_kB{&`+6})km)*Wfd)K#r8FkGcMFtvOn9DC#1F!XTrE_N zA6SD6izglI%=J2?^5e!|^(=)1Dm8=K&weosJ1|1#K`jp(TRm zE<$f3xE zpfUz;mVrqY5eK@u^F2!{OLri>5F}6*GPtCVj1E1Ei+X#zJ9~@8ENI2OAI_t)6c0Ov zmxb^}_#n6l$s`nt7;qS*IF)=6E~^(UyUEh%4cf_f2!4`-5N+f@$n-?SBC9Evg%F6C z2{sIt6LSQ`BFZ>{4`#v86|JdBXtbNjbQXJI zCF1oUus|XPyaecSc4hwz1-g>s=nUY9UH{wB!%xOZ?K%dbg=qkPO;J}!d0zhF5e%FL>85=IvZz((NZ5m z6{S-!T|5@byXm&L&<$l0&WQUbG?dr$RF>u|g={}H(!9Ij0J2alVI449K7Ee{fuzHD zIJ-Sxl1R(>e9z9s@Uyk-u^+#LZy$9$JYvbxu@$|7qr_t;Zy5j04=}4EW{1oSyvv#u zy?tdfX!3*U%{b)QbIk5+;F2KjL9<_ET?kYB2y;)w3gtTaK66Zd_?~bk0RcKQ z%&J1oo+~g30}}w>t38Bv06bt~|8c^?X0T;;%ig2r2)h2;s1QcYYvBhH%&LOVK7Im2 zxSw9ZE@y`)wjNHclikeZVLEl#+s(TqI?Nu#LIutYIsB-|ZACU>Q4HWm((t`Pxsp%+P%CV8$MdDh z6AIB(R~3_lFiLAX$1M4DfPetT!9szilP@g53NIT^suZVRRpBxDEVH({p#{;TmCq!0 zqwk#YzOHQcT3_u++l<-}SM;t__G)+eJI%ye$?ZxC4?0x0X`Hx_$tU)6K~8LPp}FK1 zdT6DQBjXo(xtC&*NG5dB_Ow}eEbwANj{|EzCaF2VKZn6gop`Z&Y_doew zg%LD8o>*@#@9``|Ex@DTqJNKjJav!aekD_ErEdBW8q*rOw1*pmUVp$+!)}QvfO&5h^A_5bph8GV{^?yROD$_}%6CZ0Pn+`UYc9I+Fum#O z)>T%t`|GB^ud)6Hk7f^oz+3H6fV#={aCBya_E_C?pQ5nQ21NnN_71Ni9{?f*A(j-f zyi&dOtis0Zo#;5tVml%~ms+J*dfwwPtwHOu(q1d%kH$PwG^T_se{8EB+N$dIE^q21 zP^N-1-SWF&G`3T*EZ`ng^^nST*}DOAdW!8Hc|)~)YC|yvO1)MrV1>e#9=FtXOUgyn zpx;s@n=4b56rsqcP4#qHfshr~t(kP9FGeUtN^qJR087zrfP$Paa_>k1sRs51H^$-wNc_W z^bkP9L`gkpuo$1-Q0x-SP5Vj1V__>4xAb;P%~^!UK`tIS;$+U|2NNzJJqHZDU<_Kr z0A}+;Xl5xqBCCEP(XaVQ2HqT)FWw&t41lq&G-}>zc9=7tAqQcGFnCSTES0F+ zrg$4YHa{Fkejm9)7s(W;(`c_G`x$X_hhYItS>H!L14~D7%(L-z=0LTF5 zJTxL7rnagfbwoZaM9d2XV@>j5G2bDwR&^wnrF!95wrOxDQZ!_#WJ~-=@+V%%8m1)G zVDih&_H5O(F! z?x${HbnB3UB#4Kh>j9e^qGzl{K7#R?Rv^as5hPWZUOU82;?f{hJuDwC0WuK6m}3@( z89&nIvw+x9K1sNOI9IiCX^2S$(kX6@>T19wXc z48p;5!8Og@uYN4xg@l7@%6BXY3|^gwpdE9g@iBE+Zt5T}63|=ZV;OI6_|RHArKX-P+^6<90z%dZV@j07)Vc2Xq6} zKpe+4ST6d0OQ$d=P!9u>;}HS6!HBRtyF*HmM+rN=4u0$e*!<6g|FPh+^60 zqwPDwL-I-CVL2p}H>bA9P`(h^G~;2A0spbU6S5jL7E*Rw<$@PzSbbU+yx!8`cJ=s-{!me1^nfz-|08+Pq@xG_aihGMr{ zn{(ENid9}`r8io!Emr6;OMk{vUyKew?pfU`hpg?8eyi7#&mv9_$!9!Pi{-gt`HYUo z0JTF6l3)X*y<6ai$W^s(v3V3$b{EV?m|Scsq%E}%$qP3Q%dw7)7?+daSzF{d+@P1X1` zA*uz?c$=SsnQguR#=xhy&s2|=6H{<7H`Q;HNQk~>OWN2XpUQZ`eHE#_ zir^LFr$)DUve7MyWO*^Y2#?RCtruffV2c%RU!NMZdBR(iAJ|ln&?_&J4uxv?+Ritz*md--@r`!D0#AA#nZN6|J_;ZHM zPov*w+WhncJb%jONoYk2Ec&d7ydGK+OOME@7-Ct&SXWKX>53IvXXzU)bqm5|E*c9W zH?-QDmV71SXG7$WXvoshTNgqVws3|wWnN5b z04F1Dgn(P*b&RKxZ^q|K0K-$hR=M97m9O%}aK!ad{KO0vXS39nAzL5%jftO%k91;L|eP1BbZarMCu=J-y#S* z(`%VfxjhIwhx+-Jk}q(&rJ#23r&}WOjqR=NVWgKghBe&#?K4Omq=C})Z%<{T$Fk;L>)4|c)QKd1}zqaa9H_96}gGc)9_&j z&=SIr{8qQN#H_kBsQ0_nw|l$Hg&->$RwT&rb1=kN@uMIDt1+%@Dk)pIfst?zUe?92Pqq4 zu*`9rya+bgu@{1iCm;wPwb9Yvi-BReO2d*GVp`mJeFE0y@=%MsobhEKImGyKit}4A zZ4GV)^L~CW`nn_XEdp*>zQu*NVw{sbjIXd3P`cDJB(FlY(kpTShN%#0doACkn5t;` zN}zI&=@wzSTlbpo(ujPkOUAA0W))Q23Y~&+g`ngUkj;X@ckVU16p;sAWCvYj%j3va z7%w}>RvcveYRIl+yw5>)rR6K{jcjh8$gXmiXTGp1A`FaabuH+`k#3-2O+>!UCFnMX zpxXpNlc>oL#? z_{y52s-kq2qIueK?c+Y~zmDyX$OD4YBl3VG{QUqi9IaH5k?vC|bPm9W_Q_ZKR?1g1 zel@|4*HQj$ZPabP94YvrP4YF8uZMj7BoTG*lhxPk3%mcun1OwD-jfZCuR{W~kun)d zidT^DM^>~2xNj8x|2p{pYZ#Qv>%ImFl@GZJkp;gjZ z(8l#)IfYVNkn#%n2*z))`MC>`{eI5oJ#@d(=Dmq_#&5EDk?uF!{8GB#V)GK+Z?$=u z?#RR{bid8!eRRLw<}2yG!RD*zz7ePsygO{Zn(lYnd=2ubRYAt@YL@SmPQpq~zO&H^ z%0nsn^NfFi0)dVYvr`BuxDd~0Nzahr;6F|VcjMd9W$6!VrKV568N7Hoc} zEVZdgzB?ULQmM9BooE-ug1ePsS6do!GUjv^jYBkBlYD2$cNtV8G$d~h4a@g*geZ@= z9KLIq@p~M1Fgz@eh)RNQE(!vpjE}&5#uy(RlJAc-1W|aPS|C=O!}7f%{|{lMb06dP zTD~iE#_vI;x%6{BoF7V?^E}l9RB!1*=@IgsJ^1);$vPTHjpA$Vrjv zrUxOV%_zN+$b8|D?Kwly7>B$sr&Y`SHosya@cDwx*Mh%S78!paB5woeveYC$Se`Zo z=`!OF4#|(ihUG^DisgYJ`QfxY8XOdBuK~YR4q$z2W#d-5-HPR`P{q>MS?WfiCFNmx zYeyRBL1JF4*IML<7~g91D@COO$UTHbH~^s_2c@`5)K0wQvPpgWp}xq6RLaf0(t4%e z=2wGytSFG$P?O~ktk+P(yasmgMa!Q?xn;c8B4uek4Fb9t-)3d0)bg;+2NtFof5hhN z5}^B0n_mmM`=M7~yhk3>Q9`o$by(XtvVAr;6RNW2D%U7Z=DN?Q;) zwhGu^vibFZbq!#Bd05^q#4b&M5d!G-fN{`d7~5@rLjtmX%;ulN@O6;RrUZ;)@oAW?|@1{KIq0ny~gG3gUFzXd?9$KyAfj6ZGj+s+8`Lm2-~P<{qV_!KJjzR$JD&ocf@7^4_}7P&I0e$M8%W8xbz z@pmb}BgLL#$=_%Edp6%dFD%BtACaF|NsN-eRaLz<--w0sk3`l6+L1Yl0?_w?)$?Kb z2dWh!z&`+(A2I$zo8JL2Hv!C#M&zF$CR{rrzd%a?ECY}p{21Lu;yeX(G5%v`@CzgI zPV~7J?`(c2C^?kzom43J3EA6EZGIPE-hv5#Mq444sKKIMuSeCc&^AkLRMahcqZZP) z>grYrAU=Oa5D2_za~tDs1+70HkzbThDQgG@NjXLNmI9Q`H&LO<3z~GRPF=5|E+W6I z3@WsEL;)v-#9nRGPzy*=cVV28C{?{=^Sc3j5c9kokza-J$I{L6OR;&lG}@yI^(tzH*-eB^AXaGf96#hYiS6~)W*DIRM@598u!NjOlS{;6> zRR%k}Da$dLU)y{$z~2t=ziF1=apKTB6o=kU$-ia%w@zeuCxlwH6huU_V$JgFp%MA5 zj!;nZog57*r15WIA-_R>%~zIx=PSv(7~d6<--@-yLg}#lR=NSD>yQXn*mfYVu?1zu zZ%*Jv9sHh-VhRlEJz(;?|2g>n|2_D%>R{Z{t?8_TL8@qF-N@u@`3XF}08o#M+6rtZ zELN-!2 z{|}SDQJrU>?0rbkFs^EQu=maXIe6Ru9{iS*Ap9xRkaBnGDB3$b9hU##z z<9~o_@-qHMYnp1sP~V2|A4b4C44xVrR;Wau?QEn5T$d{1AC&eHXmpa8;}`sfd->B| zG5_tFZX#>Zpp)-};HSo89BJC4#L-D`-hu0S*XCb@)^CKay>}97iSoOo@qbOpe`fs8 z<9kV{PQ(6nM9aXoF167U4Jb7?HU@JS7AJY5$QDq{`Vd~fRem2upWTe_j>sQ6rJ368 zJ`^T|mQ!+I^DiN}o;oD|#p^~--yKqm{1M}SsjZm2STO;^_X!lOcbeo6)dkq$`EL-v z>_GgW2Jub@;s<*|{185k@sE@)_yo97QM%V8ky-r}^>=XcUBOB0D5_q>2C@DlZf=Jw z`MYA#F!&Iv_#+F_gwOq(%^w3x?*hVqA2Piu%db$I?3`QMEH%c_IA{CmD?*2AUr%AfeIkU#b5P%%}^S@NCH8kcrs*o7iET8Ds{wZ6(oVX@GcZcwPVQ3+qnSYSi2O zTMO}Kip`${^EP47RO~*4qIycV`BO;SLb~3JgBbI01tA(0Z}Daa-e9?cq{+_=j-JT3 zj8ED8+W>O6#tdJRxu4`4BAfwzKWv3LDHP(B&7YT^pmG2yb5u>C-uXOO zsH2niVq<<2($ksubEOx0x2 zJX~Q0HhX_e{Xy-awIt3wm>GxJ`~|$Y4=)anm^v&v6l*pQ3(do&MMIwS{Iq!(C64A1 zzH3b&i=!1Oca=xBw-eTVWRp3Q5?-1Vu7omB^Kf*X38p!cIs!YeQ_#o^J!~F^Y@vr( z5wQ7BF!yH6ePk`42J3D9QzW+*lf7iEvx z`B^h0W{Y69JDsGgKAkJe$7?{2o-8F~8Y7Nt$P#ELI-Gg_9fm zeOt{I-$S^z;d z4x6o_GT0I7Ph)|ocQtCUG&5Rl{>!!X)=o4}3r#`opBd4x`B_Pc(}<-IC>AIN776l z*(>(=cH!;86W${KMJf@d`p)+;V}jHy3^fxLgY!IaM!$oD!%>Qw-hq#&+Wa-(vAv5K z3nS(^s269;&E~1udAPJ_7Dt$}*xWSF8lbh(fU+TIp0=UI1lFg`Hcxk+P9HLp&QtPg z^9<+djHG#{^K@p|JZl3pQc9|y(n;0#xi&SOw#w=hY=AK1tcJls^3Vf*D;u!NVJjWC zV(nHaXXzD7S~qN-E#l+=l*(E6nrDL@N=i6zFMvtd@e5-cAy(b@lj;F@kQrywohl~I)LP|qoa zs465*K9$urgg9E#;+5D|UfEnl8{12G#D-huY5%WSQEOxid^Hqo` zVxA9APrF-GV#4lL5W8E>T3!@DbZNpim)}e2z3_S$hRyTI7A~^+9|8KSAmw6YBa0hH zeP1*4z71x^S2nv4U^{&!^AcuU5-}Hpj95BsE(Rw{x)sARI!4v9DJbYOqmw#p*3-B- z%Mt2_b#^RdWmQ@I#AherU1qLs|HtMa)=4Q*2JhfJv;y z%rPVD&RIrF8EaY9G;^w9=CBt%&E|hvTVKSh5rqLGKOXm~c_{?@HdVz*UHo1V4q?2A*iL=KSZwomuBf+oK#yV3P^%ES>o9aB z)p!?P`bapcA}Cs6E)wh4f+oSQeN4zaKZwuA8 zyYbe*+ZE#NGUx3w=PeZ8i)`XA=yD9YTq?SBJ6)E;Af~6F3f<&H;&39+LYFFN#fnKG z5Dh)!4L0A6u!y$aiEV#&+KLm~-gDY61p_EoDcSseXx$FzczM#QnG&}TQ0JXbgW*AZ zhXe>632Xh3%|C<}{7lq4h$tf1PjMA>L^!*TrdoVfvspous7M-)BPdwEQT1e(Q#~0~ zv4|426X%$ZQ9;qc=(G7>fyTE%!ODo)2Y;AGrqrK4sUwYJ|5z)Tt1WXCGgd{@9=*xz z*L_b%(~5Xn5R9fZ=gGq9NAWbxJ;@h}ft#x_CW|py-*+1NabkeZf~7^+jK!@`yQSwW zsp1%jI9B&JqK$Gq_&0=wct}){{*Kn`LH>w&t%Nf#s7*-Gc+lH~pWbME6txvF>>m&- zC6()hSg(Ru*DzxZPHExYKauIt%10V82dMfqWM1PPHm?y054GdBbPujZg$N)gUGc&-SX$GaQk}8viZN@_k2P= z)C^LP%Q(U4-;hsJvw1b-bM^m|e5yM_zHmn2z;4r;Ae0DICdmjnB1 zn}0%jbB%3y5?*EufWP#69b`aieXVV<1oHUnY@-f(^(@r;`e;at4VgE@hRqv96&_{X zG$m5$2`IuhAi5Y5sA+66*8{_VlRvF@S6^XCoOXgXqxjXR1tBMj5}NrKrntd2yr_vA zpR2mWGNIxtkcdn>I2zkk@gUmVoy2xG6o@Wb(*IBagIHbE!$zq{T~C;7rslX6Nuv)cxaY$r`@OCL9(R^1<A5@ub90KxmGI#7BwwMnw<3UQVsZspeYN1$TJVao(#$kb!OyUT-WgCZL zy2C{~92yn$g0^uOeC}*;(KhJpwa_*pK&(|Q^Wh*fw%LXTa&|&LAC8z`lp0bNEt_;? z{P77D0b{1?yuU1*_akuLk22$tA@fUtVe?UO@X`-j9+kR$KSA|Rs@CC+BLo5z8{-r* zykVe9m0d%}5lI&xv{Q%_F4zdbG9Grx7oPG_w=f^aXn{5K>5E}=3>yt#1@v-^7AJL- zygkf}FWJVC3z3U{**0d9uiI`LbQ=4o5Z7ZP=Hn_wC!E*V&wQK*B^~kbaoyL0&5=D? z8tCLYif#Q6BaUY8s`@oiWg8Ux8ph*JVdE>dVPJ+AF~e60^pN>Ac(1Ps??v(KYs3@M z0Ovsbwm}`GOYD$P;53e*?HA)~wlRx*+1G8O37~$iFyk8|=GVnGjE3DvKlP9LgS5eE z8^=P6zZHck51CJ3PgbSl%f6Sq3jXqjeo3vsuaozV7e+n5WyUIAWDN6haMUSRQa&f$Fp5$ricu;)Ys^DR%q!6CPK zF6+xjkwi!Ev^iVGt=w83C}S8cAf2BZ%0uR}>4wxO<-^%(OxEMW=6A&I^2}I^`3y6@ z1MeDR#xq!ThO7;`RR)qFoSOSS(XkaPIwMT_4pBic;_DO~{DWYGKmx%)qlNu3Ed>Wf zbrRP|gz+9v<3x~`baDm`Q=SG>o>hWfuz$l>a^jF3<-x=`_&_V_XVFWesdqs)vC$>Qcz<;AK9m@k*2VY7CaITcL>gYN$07bMI+!$JbY`p6YQr7OLi2Lw+xa z15-g8meIxnIIv$)#Rkhv+epx_tw?(DIfQX42zXQ3ft*~D+5))3lH+yb!8jSYmyCRj zPHwfs%ya9z6x&!R7~=$X5!qfPtJM*kPuug&FT&V!R;X4`K5Sn&ywTk;XK?hkg9X{c_T1r<`X&%3V(($h?EMZ`;N> z)Db*=Ct|(}e5jcGHib1xPTxk^NX4RAiiSK$uHO@-))4kryQqF9xj_!u5th@y>0IQ= zpHL!?QfC-hPME6Pl;aS>Sk#-l$CEz_gdo+sZ4~QRn1fhEd&BNJ&%nWEP%BoX@P|Ma z9D5gW5X8M_8|TyZ$DeKE0^t4zaNiv=7#}*}Pm3YmA?8^j>|N0IXUcrvcZm5H zX8dLRb2elH#LsPGKp}>8y=~we@}y~ZW7_v40NNTNOQCx<6vmytOb9gweQ&0-L*`%c zZD>){eQW+6p+qM;8a6)=Ov8}`@3H0w-a05HdbVR#U>g^Sv=2&&cji1%`isMt;(4ek_i9m>;8SUd7O_H$$qrER3 zCn&(Z9F_*k1j9?z;ayvZPV`C8orFYyn#_+?-(@0SPQc;hG4mgTEKxs{5H7BR3^KfZSs_rr&>Q#_e!Zo1Al0c!$$#(y&(y7G6^l*|k6BDSgDkO{&5JEGS z;{`z9jfwYfP97-D!=()+4-mDu;p7aV%u=W&*~k(zthx|OG!jejjX84jZ94%-EM0A5 z871?H1FEyqv1>8Gfm5{P11xcnZ7jz;e?gyvx2hP5?+2@6rd&%hKcLRsQS06EGwx&h=P z;CA#-vPm6II-gNu!INxq7J)&0Qk0xU%f;j|zMdpXP6nkV`_=OZj++9;G0r|$Vpf%5 zTOjcjf@4j#(F1>%I2Ma&O!GHPV@8s*_h3QMVZm{Gv%s9lg5zo|Fu{V^0E>ljFTnmC zVCM`aj|cY0J3YVI{&?HCl(0Vm zwF*r0PjLFgNHQWdc$Cc&Hae0g5_;Ipm!^|}MZ(Eug48@&EwQoq0Y?7|qvuDGEw0j^ z1f@S|g3`|isHoR7uJrh(aFWuugp(%|^pht;$L8Yi0R7)!ffY%%VgaGG;!GuN#!cj1 zYd9ID(b37HV>q{f(f`5dcqG|IqoFUz&*vc&Lf7Izx~)060JfBnf^^^kQ3s#?!V|%V z+eQhla=xf}Bu}A}5iob0EW$VdJjMA{t#3XJl;VQO36{N}32-q^=ux7En`>{_Kg8cq zn8g5WVRP~{AaR=5lGR6&r-?)cYFITi83uS7W(1A+*zOSwtAmmxBgr$ta0J)n8I)$? z>s{e)QIHZLBP8L#!`DS&0?9>K6vn7n3x`Z6rQFQc`CN;#l*Ab@=_E^>8BV5Xs#FbS zp)hCR7#3!hfbiLoWCv!};or{H=ix%mjg@xtTtZ_gc@CX66_FEv;sIZ~4=2+?b9Ei~ zwIthF0_n@8UY2MF+s@uA!%m!2)sC8TIv39AY?kN%)w>tSdBK(o zBFPJ3g9sO>KEM-6UOLQ3^-p*paK^7=m&4(~1rxRC!f^5;0*(*8COY1WaZD4C>jC+a zrevoy&5=XrP_hdq+2xvKO;TTGi7wkHlVxRaa1|q`VC16aWEM7&rAjHz$|v)o;bdM! zb18=MuR4^>0T?#f5R9d?9NgVS)rAmAQq=x*`eYjwix?d}wT%iW`Z?*TyM7N)#)hLq zehTI|{_YqT{?r7HO(e45-Tf?)vyDE&DsLMrQHoArhwU<8H&tPYC6Q#owcMq^a_I!i zU9zWAFRjYP4OfM5av5=L*<`LQ$2a4E&Y>*bkz{eQPlR1zizO*G=8`>dTq{^&#UAmY zd!lIE-~rp~1~aQ0WV1d+2T9OS#QdlRufl{r{49+mS4k*W+Qw?yut9bLn_8ozz(q-f zW8-=dM<0@_h3l*UgEC8$X$94i>|==vZH}-+A68{x_8KVZ@*0-7+BPnCKTAklLm95K!DC#3oOm+z1CAxE z1I>@H1omszBB@PWhd-79Tt5w3uWwFX2YtE@`eebml2d}R`(XlJcv9QA(p3cdhI2*o z28dxjORPt-O11684d{cCxIYXeYy%%f?4rd8`7sq|GDOykPa~>}Lr8?ODeT)^Nu0mY z9t9GgQCQ-pNb+VZNfkH(a_wH?2wkXNc$NE64nwHBX>VV6Gl1P<4+02fU$;h*gTmoK zp>(jU`b7g4Ox~{=oe;P`Deh;0-=ZhX^5#Z{yZR1Z|%u+$erbzPc33O}%9d|b;hd{?Y z`=H|+ljzvAZ#ssWFt$nuHfdbX>(Vi7lPdWkfRRY@UPl1QQ6ALQP*ZXgDUY+RhYUt0 zTG1#pa)c%Bg%Iv@+`|3m$Ai%0k(T7cQo2%Vr#~8X>WU)nb-VD` zf=j~X#l>*d?lbi{ z3|Ad4dOqBJrn#CXJmarji9Xam+kK|~A@}(N+)us-MFX^;aPN_sZRx073NwzSNmTzq0iM5o(Cp8UpL|T20T~sx!HZL&PDB?$5o}B zo~v}xI~y0_M)=%=tBTKKc&7J6*Vo#IGxwSL{K9>nfqPYF==oQ;Xe`0~lY1vP@8GJ! zq-TOjJgMpl_4%vYPS5{vpGj9g#zkX4ac)(IgrY zPh6+;^`JkaF`veLI_?-(cNgyTk9pr)1U+DQNB!%rr#5=ww##^={^%p%Rr}K%)LwG# zH8^Bv)V>IJVSg?hqKn!u!JVF~aA+=?cOmXH)}7b$cei~G?o)BO{XHMK?MLHIe5g0Bvqo_F1L;s^1x3g<8M2sj7hPCTij{-+lz z#MirV(Lcg-%0NXtqnCJM8P6&Se_I-jGX|E{t@>2$Z&a_Ek`aGidS7pxKV^?M{yoNc z^Q#LqK@E6yw#I==S9$3#60h1XgTFEA{_*2XohO;EWH7)S=*IsH7%2H3`s>#C>x%dz z>3#Sssp7>d--^tdMfm&UtBa*&%h0v8QX$zMT^lE@Ecb}6J&I@U;lahq-Am8g^yud< z_~^_Z-h&bC_*1v&AH@ZJd*si20zI<0N7L|&{wbbyIG5%8WAul=+-K-=?b!<+D<04P E0Z9a0#@~(h>?i=xL79lQ#6Aw3Ifb^lst*eX}bcN!rivpAXCK z&d$7f_j~hZvP>jJZ5XXmGPC?eD~@?$$85ZDm~fK>Qtdp z>8%W|s`Re!?kQGlsoI)K@5cUGZ*O7WEB5qM3$^N=`a}1szS8)_%gUa0Q$FD> zwXz%k@2_JxTJ6i_3e{?FrD_qFV5zWiu&218(B0cttEOniYPnL_P^eT3V-rw|Re(YF zV0lf^>Z=y=slHONw=|Y7^mG?`3hN7{+9-%xUn~(_`)FJt51KJ`Z*Co*KLMz(oX^$@ zAPf^`OZo1eY_--6fT>lzJ^3Df*hEK6R?|fUszQv74l=*Z1<|-)#YAD!pilQHe4G znu7V_h7?8?tHG7URjE}yz1iBJ5KAFn$d9kAcIPSu;?l}uX%ugTt80~Pt~Q28pxa%` z7JImYmtv_{>)u!?*0L*m3jJtUpRMKA?8QU1maWvB*FAWx6~JV7SYNRxPv3Lv2x!5| zWqW!Cb2PBKP|EKsTwTcZ34mZ_sZe(3&d|hb^84sUY;$EUnrl6LmcXm8+*7E38DEnn ze9B;Xp(oFkVzs-}TPmzC*ERugwYCopwe0HE(2^RB6WZKet8AjyQP@GgSXy1q=KI%Y z*A++>qk_2ZRUm#0DqHV5SSqe^$lX&e6xMaGhiYe67y8S6H8D?_9!OGj7c&i3vKzZA z*k-@PGQ8C(gR$v5;2W-F_^Yn#f2 z>L?iHayzvu3(L1^6&gW)rjQ>jlrSBfNg=p=hgm$1%<70+}69tMbDDgs>Lc z56vOTRjd8gzLk!y;i7*uIjC9%vOX-*7~Z18|e}h6mP%=w2V$R za9FkY?sBAV8gNDK5CQ-{<-UzhKBi#W#nN7U&KJNA=oB36zUi-v;Lj$$34~qAWlN=A zV1#L^{BVqMo1vC)V)aja-sG3bR@Xo9BmVnG?myVKvPSzY>=U^We2{K)0Ezp2xuT{oG_a1@ro+;0Z%6K8H$kjsS_}mG& zuz1qJ?tHI9DnDuRQ)vw(SQDYeLBi>bzMv11B9MHxI}i9!?RHF%D`PxHG7a=2ofj@8C=~*Mu(o|mA$<^-M!^<4z%Ll59d)^gNJe9Wg&bK zJ_s&CG6{tu1{?+{POVUe%j!kTKC(3Wf_Cy9f}i9dL>oB}GCdKo$ZD!pAp|03iVcJ1 z#2i7fh%!##gV}KvqaFUZ5ebbDjc6hjs)vbwJVUh$6$=?oO>1cp8tvvY-Q`|biTFGS zERcu+F9EumTT{sQA$*}{v0AK=*Ch;)zX`M6|GOXyDH8V=t}as^<9K@4G4%IVimSVG z$cYM-KGy*tyX%93_0x^CH&`uPHCTUHRIc@ka5d4gm>&j4B9|)EosBcYXr&LKijpdr zE*^{3eRNw@?13@~XT<$e8mgO0wKauWG1pIxH1F8@UO_04?u7HncRt6gv+v}^W=}3~ zW%%Sp=3?`}_7K_^nf&mn{j+cqo7VUCRn4#&Y&*H_z)_1ZD)?VVg)nMq8=p%s>*73l zi9jRh4D{0{XyM7>DXsk?6+`Ue$I$2L)-`>+P8|;PZZ56PB!kG$VZ%sZM@32}g0Mxd zj~_?F4~PhhP7axqq=UR;584gAh@r#+Fz$c$aj7*93da$?3(f7>@;`c3!K`WM9h{0P zm@wH57|tV@lWD^A35AU6$@Da7jM9?E(MCQSAg0X@O`1(Epa|D|&15d2IQ@t{L=Yxl zU`{0Uv<{e-@K0km`YxL6>&oVU#l`-#&6ybDir$sV0qrh-XPHa%G3a^P@XlpYS zj}=h8TC!kCek&~5!I_E@ULq+$&rYdXtAwdRYrBvIy-G4;duA#@OY&NhYWXGG@@h9* zUY*_oAv6f!cFJqX$44cPKPo9+>Xspp9TOn^4nXUnX2lPnmkFT7xDr%oM#(!nrLxr8 zcuS#6QXXw7s9$k$2?yv)rbky<*)BKCeoaQ-1+nD(KQJzY9fUe#9=Fs^OUg&pAcP><`(|P+5ah~CPl|XL*R4D-i~&Oo3v5v`HlO89 z$r^D-ZPt8qI=43l0$Q`CO3}E6u7D`neD+Kwqi9NpSMqOBQZ`o!o?o}Zsud48@T@?1 zOHc!>SuPFI_C~J?NPblbYQ%a~nysmfD>nCohPf%mXGLT`IFpt};GJ;LenW>befy!Ysl`?5WC!XhcHF*wDk9sw)K!2VW%)`X-xF7+lXL&&-Fm9fy z^%KT%L6a9`Se6bDhtJdoiP-_6W?|w?BWSP~pWRf>2;QdsmK3mJVJj53^iE67TZG44 z7mqw~GH>%E2p5o^7it++(HaIYo6n<}rSOQX`iVrp<|i3=^I*RCek3pe#<~L2>9oRN zC)7O##U?y5jDvl`R(!|Aw>NfDHy8*I1>*rHAi9+q_bb5^aoMMZwm0fh3f*E8j0f8f zv-weA`+SY@IdbsSAX&1eXqHOUJ?QZ^du)C*#Oi87Kq77t{>Sj(Xpr${n`;=aD~yw_ zt1~qD2*&5yd_J`T>Jbrn9)zifmdbN=EvhTA5qWNmbW}-MA#XIMNm1RSL(_Ljs?Cq} z2IZrORxli(0CpZ!4Tv6Ta~&W9nDeNJe6-rGhSU-H=nye46pXdVN5_2gWDOK3M1f_g z@E86E6{%T~q9IEqQ{sV{!BNW#S;LZ~M$7~RkA}bj{}`Je2l&UO7}p}QE;VIRQgq!<{I17TMloqp;TMz=00NP>WS@&{~wg6J7*laFP5J|xNb zu_RTPUZ)@y)&{BSVfh#dkbw}!7%RezA7}Fuf!OgDixtNn+KuaK- z2F;sW&yE=opW^I)07nc%?>YBbQ6tmPcX-1rgjoW;ww=B0~ zNIcpZ3=GRlx+sp&6sIu0#F^rhVfj>nly5QGBaENwv_~*C%&E1@k0HLrkoQu?Tk#F@ zUK*7&??QQ*3Ko%9^;&s|W*Kz!vk(pA%P3-bFq40KV>nI^KwwlwFL2Bs?#$c#w3*u8 z5xLC^i>Pa&7edHbKygfhT57Y)V8Cg0Pa6(Xq}R%fw_)&OnB;Vuw~ed}i<6{psr%145+Sb;*HBhtCo2}S3E40(nAG6fwqE*N_r&~K9>N8*)=M#^INYqW@=2ZBY;IxLU6!;>*jM{ZWgq4ml2>dVmSbI;F)lB` zgS5$U#^JCde#Ya={Bp9{^0mrm`XX`%;~jP0XqfCAXENdTkOV*+(V0Q6KpbuIa>mbe zEXC%rnHrxZgtQ#$ZSy#0ws{9MpU>``ubv<$q%O6*P(G{6ulQQGH*S_Zz{S^UNt@f` zvlvgfpCS{VBKXAkSkd3;jpU}qj8J;$3e zyGR4zOo&}KF`kZwl=w0UKzPd6E`Pumm9O{3aK!H9#LOAxA}-C4)rCz+Pl1r7q;9b4&8kJY=K1hhvuSR_BAzY#1-0C>Svv z#mqsK<>CXCCA&WjmrSE!ExE$!CXmwNj;t>ytRnIUp}$aWs05~Q=h$rXD=^1)F>;j{+3Q9#hdoywD8bbc zc?&>E0J#MTv#y45cciw)r8v|k7a3mzQbUXvDQ-jmrWjr~=KRQXx?oYa3aDZERu|g3 zN&fXPzRp@s`A*M}+=p~yy@>1#6O|ZWZ~3mmL?z2t0e$;VmceAVPM@qdBH!kcaGSbA z1qHW3hhR7%Qs60wX2I6M>0`?g`9m(EA94}BY7)^3<5xL|RvbjD6NuIrM@S|_YnHEi z5JXoVh-ja?s`7?LTY!aR4AD0cZ5|RsI%9(OxxxJuj>`f(~<9-bXWgn z*asr=je@l!@{N*k+&2=3(Mp9A={}Vr;EiyGeew;y4e||)-$0P#4HBgZn{}HPkuEp4 z$o-P9L{59UOx7OA-Ts4Oc2I8Ic+jrXXlMK;iuJ%1nFuXS&xgJYgyj?pSV0QruwKR? zrp^_}GjF!}I=bIt^PWT};~%v7db)41d5P|~+Ps(Ux7oZ*_Yc|pD!Sip^9tSXuz8j4 zciOy0_Yd2=kKhg3d;?OJjYwJUYLy42)37{}2b-;+e0NIz2;(0Cj-jX&j723Yy(~nZ zd{@ice4FI0jBlkPR?KVZeo+b8h|*XPArjRgu?q4#b)Ic4@<-D#C6(%kHHdbx`u?a= z&UB;^nPN_7(Req_)*=sveAj?4p&|L+(6Icmt`J4;YvE5m&iKb1GyV9mY>TD2Z!uQb z+Zngv&|-{lACgC6O+l>WskVk?+^~F)$go3LOAIl7kL9~gXM9Mpf>=&S9TG6m8>kpz z^Q)op%@KK6qyu4j7)wX5gsJ^1Ru&TSN8e(|#!0jqW(Ogidr_q%QTf6l+jFj>F+L11 zv@RI2`KA@XXVm7`fWIHW`rs20`I7)$m0INcs62Pu{tm$-=CI8 zgM(sqGvK$X0W2D=T--``TCuzpauY|P9o1oZM^_r?L1JF4h}vXiqC0GUtyuj7xt&1hVf5YIjUXUZ}a{YX~rM0`Hhqcf6C@Jf$o0j)vkNxPwS}3*n9xX zd!%*k7@@IWF%VUg>*?h~n z8lT7bXOU(SRgc>IRvL<#cQLZge_YJ}1m^!d~-{Mm^7 zoJwMp{OzjhwfSAB#(!PpPoN#qMpRXv1y;|6<*%w%hyZ^TV7|`y*KGa~fVmxDzCI#< z3(ouI5&3yazL9t%Y<~mYMXEXjbTR%7XYlhQ@;A}vW_+{xR#0*jnI(#vsDJBGH4}O;s5UF=PQ6(R>AQ4wmjn_y z{;q`bQ&TWV$|>rh6iICUF{<8pL6dGZs9Q7zq`sgGD&)RV6-jk@0bawJJ4M}vaY~~8 zGj8*b1Na~aeIX*h1mlmTTjlZCQd}C<{afT0rCExW>4>Q+TqxM{0^=`I%^RkX4ouY1 zus;A32PQTO`9z+mcq$KCAPZ$%oy;gs>w>t=w~I0$>H;sLy6|$BIR6+eABEc#nTa&E_MR_=lJn1wgCIPX)kWmp5fOCi4TEV=u+`5rF?;tNgkX zhhC>R^y`%TBgTK^M26QxDE>-8L?kQLD!&>UkzeZy1vTI4Sn-m^zlLS=R{5vCs{9jQ zMgB44KaR++#oA+`bXa~Z-4wJ?fTnPTIzD-gPoQ@9xhcG8fZs#yQH4Rh0Ze}KKL_9U zzX$)cJ{b3OdphS}kSbd_H!`8XNZTre#}0scMAR@~J7KX#+$o@sPKXJi6H4X}i%4Nr|7Ae49KIeU%)*QJX12c`WqGPEueJt2YCH<`S&QY{EqS8MdUv?#gK{HeJBM8EvMwb<_{waW<&Cu zUN?IBJ}R}ze`Ng4iM5OuYZ+kpdjdskkrw$6>T+zE{5Ob?I1t~OfOxk9@vZ$K{sBIX z@jqfqQMgf257#7-S?xnn8=U-&;H22wL2MA~GUDbKT*=$;gct@NLS=MhL7MQnf3o>! z!P1Wb;kSq6cXc?aI`p}Nx)(B0-OXCxv-uZRsLb%#{EJ}T_8>DD>ieOn zp3-gp6wft1=qv8Y07hA}e)p*TGNqm;wuOxke4cuK5{nKs|U6^=6o z2DkY$m}S^v#vzlYCelfpe?=6=C=r3-B0Vw>#R#9xpT&p~5O-+Ae81FWAXva>U zrBlXc^XI@=RMAWYMzr3PeI>Jr8BN%kX*1u)3>lcHPOPL&zOc=|DiSfG?tM<;Op^hp z_lHfN1TyhK0aPrtj9E7S8s;AbDzizMqiPBj#;=2gx~jICs=5>xn5&@m8JMt0Cz3exFlHQX^KawB zefTgpVjcyH4#ir{!$V7PY0;1;y)11WPKl#=r0-_)2xc77q@~GnDZ#% zrAgsRC<8U;g06XBnj@(rv86c!jm$VIY#xqmp+u}W+UDQI+&eJ$F%$VTSa0+1xqR0J z-{*tx0H+C|&mT6A?efw(Olm}~jrLdh_Y@q{|I3bBGSj;DpXpR7(~oRmoexf5*uBB0z4D25!=oLxbY5O$~tVgVrh5~@$f zK?<$rLjO`+TGa1BwbooHShoPIJCPYDItu~E(QW~W^I)89W(zYGz(g^93(Xr42|T7< zSYJ0J*W(Slm@fl~2Y|#$5iOjFFZ7_*(sjFX!zu^dnPt&oU> zA;daJ?E4gZTFga~Z_T}CFigRc#AIRqAhya>4-!EkOrU}!7u%ucNtkreM6bmnH#JXU zMks8WbzwsLUjcrfQkb!%)jUO7YDUD$gSZfB?)U97PxXBo*MqnoGEZg3Dei~Qpy6R$ zkKh`k52w275uq7@RjbW^0LY&O5=$fIX+*g+WVWfp<}y*S>k9R!u|U)_%~~wYjAb_e z;q{HyIGSgLW}w>6jMKtqt0Y!426pa#M7|9>cRvQuM*;K<3wxIC!X{<5GsCj^Pv~2U z8SPD$(Do2TTS~@YWl(dQ{}cj0sl|*sdJm;X(o7!NEB4Y}#n;28d`13?R3c1U%gVMaV+o`(uZf#4 z_1)H?rqfncoq;U}W}MwLI7l9Pz;ERORyAy;<5sNG3ZbxF!-m_id5(ya15hew-D{o$ zb|@*~z`Xz_#nZHl-5Im;A*wBGmKp(gkQwJV8*YMM38HA zL$_a&%Z!*81lj|tj=SEjhx9P+%BV%FL|-LDRUvVdsH%1##L<%08xt!)P$;N^STC^o zuMz=fq;39d%=bBnurp#_2!+Ldl9|SGb#257V{Ec#k`mq7e~wt z$cUxGW+p9)?cfU397XLJsIfES66&x+Pvhn+N2njx*|Ct7Q(-j_(xua3pbowtjLYgB zTFngnP-empWrQEP0)FUnW?W8F>`2FeNvzGhk{MUHb5_w(#adQ1%_~*Iyb^o92#UYC zzOjts7@1i(;8YgeUn?-D^9R5TyAjN|k`~EQ8UatZX;Bz3x+mj4HLrnS-=Ly3sf*tU z{xDudY^OeAWNiN1>l!T{&|_FMOjHQnbr`ymYWxmf`ZzeMwV-IdnMEKfFe6KjnYOpz z#Mk5TwJ5%>biS^vfBikao`A1w#MhkjHCO-o7QPzzx>|hAJ74q8S17y}{`3#%aw58{ z6J1t0T?#M=I+19sA}11u6G6yzse)Flo)!Ypux7Hs=5HY^qOCZ!?e|XG+No`CI&JH~ z0LoQ*Z2m`R-5%)p`f00XO5FCL&g-SY@F2c<0YXQ@T0dm-Kfwzg67>!uiim84;wtKh zaCUFcwD^KnvxF#7k~D?SQm}rb>dClMJsDN8h!V9E=j@D8LeatKwfUcc#xtOx95H+0 z57Wq$u1TNPl@6NMV69|UEb}U6Top}w^cM3P-S?GfS`kmngVD6+JXttSD4u4yN8>^< zaI=CjIgH8qo^9&SkN`x<1&i_+7Ui9mp0}i$V<6(3+B-xW<#_OK2n+F$s3QFZtv7=F z5%UHKr%F(pkfQM*^4=S;9*d8nwgQIz6=J2N@&iJwn;_OIGpacHgl~UCrq_j)k2GRl zPt~U(^E&Uad7Vgjs2%Upy||hcHf+{JIR|CvHnWczHAE9Isc*=ec`Mwx#X^w#JN%wk$cLIi3UV1I82tnCX=ydDg?z64Kgs9niN#!A z?0)q#V-srYVk5T(6|HS4L+t;AJs#=m8BW|PKWOYu$j);kb-HXvs z8qMbaLXbFASaXB;;#f0IKW$L}d)g+H1N&N=|C{vYI-CC|;bq44;4i&@05Tx8zQN}2 zCa_fLxA}X}tFJ=6Z^S8#*pN988#V_-6&_{XG$m5$DJWuML>I#YYLGwP1PlXC{&bVO z`U*?pJQ1`R#jj>92su%d(9DN1#ei)v)WnU=w$XrDzZPW1%~4$o4VfPd4Vxbnr3y6` z)ie5#d5b=5-Xemms*aeq&~Z2_ViJ=K3Bhe4Gj6dBFRimaXd8`*5Hq&e#teY{I*jDj zR&xuM5nEI(s)|H@3p8%6c_;kxZOpjMO>J~HwHYz*2nBuLXfZ#e`zm0AWE(RPjFz;R zcOWdcnYT0JL#V5vnNKz|<95oODS5oZt%-_6$2Jb(7B@leo#Hg3@nPHW0j=lJGDwaZ zBFEuG<4_okK~B$In#s>-%(%-on$Y)~AmJme=3OA+t_c$E5+r;aBy45I))DhA9Z_}2 z{1{lbO|T9d&E`j$u}y3Y86OoZQ$xPKF*UBw5|YFk0Lmt!|A={a$nt%QPTdTdcT2h;}$MD(D4m1E;NV{t{>2jU&Z| zm@W=?i-Wh8c|T0>leR(UpvR$~_eacKQd7#JWs{DKKR%@*U>xl_ZyX{-Lht~b_otZg zz>xW1VA%YWINIn3EuWGyz86salj?PN;~0Se#l|>=3~v~yQf1fBa0pRoe~8*CL<$#d z%!g&%?~*S(<)_@je7ue|^l4Yv{4_QizzXQ)r)hE0K*`(v%y`f?j$MIV^dZ|gnta`7 zY=e$Z@B3QUKHu{EO2TCpRXbY8bs zhs>wbO{r1JhjaCqtjCAVFNxjd`AFfv%#1I=yT+LDWvn_w)>hrB0?8oGsXa?{?81u9 zSVZ~`Q9&@`=N>p}2f+w|1cHHP3;SbQ3J!|uB(9MN<6TVSM39$sat01lo&r;zR)QJw zOTKX0sZ$zzpqw2cokaB%GoA^X*cF{*TIc|#eZ@AyVA_u|%y_mbRgdYS=qI*baGD*M zF98ON;64_+o80a26=|xX;;?8O``qSNVR+Bk#wh^xlQJ{D8Zo~H{#OS^%;&0tkA=MALv{>!ao88&PsO=+amKrIbUrF9SU$$Yk7ba7<*0N9_`vULVe>ioAhA7^ z77FDaq6dTskV8tHn;hJLG^q;HZ|pa}0pz}J8?8X@)qZAtBVv9NCDs0RX+YY!70kOi zMn}1KjN&MFPCSjFaorBvSbBZq*q(t|yOr@hJ9ndP?e31<4ZAziyLa#0(G0cPvDKH_ zJz_qeqkx$U?jACq-#u(T-?bZ7*EKM>dwXNGx~EwS?PkXFN_lMO0KpjO7|`{Ot-5X- z%K#rWnbG+;i$69Vn-x>Ev5p<8Is-T}rzv&->TN5GwJ?Ox`c@z|@43cd}YSiztL6n6ldcUfBE&dGvAHhyjPaz~P06 z`7+@ED}PBRD@Vo{)q}AS^TiOP+G4&K^QFicnP@P~7rR1b{1(T2ff+Bhm@ma(`MMQ~ zm@kFeLoxTB7I*xd$<jzBPK@}zZJY&0ycT4}D?{dwCkrOS<`0~d4Ko5e?)l@ zR-o81H_oO_5U}${Zl;dhm39(-TwnZRRWDBN7(cO%b1>sC(D$bi^JgyWUq!ZwWSzMD zD!BZr%jKUkf|(zyx`Gvn7z8%*YPa%5=M_!4IP2DuXYz7CAuh?u{F{UO)~M7HCX9xW?f>Yf(! zx0LxJr-#649j0LJH>Q&JTjwJdH`pULeg_QRMD7N#zrl3BkC@IT;fVQ`llRgh{4Je1 zdBv0rPbk7$Gmzae;|~DxN83mN$Q!_I-;ntZioNfMVlQP9?>O025GUi!KZ`ucjjhKJmj|CZr z1%Eq`1%I8&g1=3$;ICl8-vRa?wvh(dHv#saL*~1{{@n@e-<^W}e+2gb2KN7A#=l(b zPj#^Ww~PIMrefbIuz%M!E+p*V!y*9Fyrr;&Cz51RlSkPhp@Nw75PH}qlV*EVmSEu| z@gvdTYIy}}p|J$jZZP@}810QDXFwrUsWsWCF2$wQ1%%R$h96RTkfi_`R_uw!IzE3? z1(+G(t^Z!n=eooII39A3A+>6E*}f z`cD`wN0RTO(MX06_##OC8nG1!q~F(?RHUWJSyGU85@8zypCZejOgj;ekF?ivr=~aRmIh3E%?q@i_kk$o~N36IzmnG|Q2L zF_b(}9ZsI;n&gC}9%6|TZKDg8l~{liVHo*OjBII5E`&`iq!I)Up(alX4JS_$r3NX6 zx{5lKGy%+XfTiW&-VCMfLXu)ptr~biG|?ZI+ieP;}XK^B-^+YHJ-%DHs1*B{-v-)Fp^yCTJ9oXxoC>z2KQI$ zMRnP@mb*Bd3=!8t)47JqGo{J@hO#V)BwMHZMA#K-m&ph@uH>n{Qt}j*IAwZ#NG_Qw znp5k}F}VcHjJQ+z{zE&oXlTX!OKsyaO!zKdmyIMX33UM5xST4XQc#CYp%&(Qfi{R8 z8`p!_Q%trC4BCLfX)JLXr6z63(^;a8s*WsiI?^35`wA#2eqF|w4kgdP?*PTo2q)wx z@M|KEvz+jY^ z5;xDB&dufc)iK615SM68CgCfR!dHaw62gmEM#h%KlJvW}waIgQHz&_xiL;OqkzNpn zl0K9?SFQgVRT7IbH9VYLAylq@-ZyzRORTVsZuh)z;%ubMZspX-VC6oY`g0shNP_08 zSmIpU$YN78fnTm216&(GYpOMQ9`xxv=#vHKD$-gNe_TPu4kvyJWvp}+AuYsk0mN`V zOPr4?Cl!qn7oZPnP5v;Du#Fs*I8Z7lKc-@{Q>Zv2t|b2WdM%#txDOwI#^m^32kxRWw#x~)H5)3CX&ofnL2~1v#rUM zm^ycmsUMp*H7%PCGWE(9jIB?d+kfi3tzqh!;8`J(T)Vn&EKw4h zr3(%P!M$zC5=)dFgK0vKtJ;!f34cr^U8{8B<~eJ98TW>7;Bgr)`sBsMa5dtZ;XZTR z4{@KVkI#Lcjl1eT`*A-E7yWC-bvQ19Lw$~PpQ+DLxEgTL^U>}z^*2u?h=Yc8Dw@i7y70-2i?r@*$b5Z-pan<=i&vm-!n~jTbBYf_~RmbNs zJkxjL&y#NZ7jXX~F6vLuPfdCL(v;^fPkDaYeJ1$xaFOik`MD|2B-1+n=eX^J|95c_ zK7_;faMk(zlKV`3e(XLIpX)k9&p*XgAN%Y5p6hUai}w2S@7-t8$+zA9f5!bCx1Df) zkJ>w~CVlo8xCrN8Q5*hy-F>E4Y9qMfIEokK!U;%kO^=GP1Zw)9^^uJ${Vf*v8G17D?1elOkLUjZwe!rX diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_bc_size.beam b/bootstrap/lib/compiler/ebin/beam_ssa_bc_size.beam index 472d92d9b57dfe84c6bb492b75f4796d230959e1..fed57ed0fd1ae0bc007c52170c457d504b0cf6d6 100644 GIT binary patch delta 5141 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 K&*AgU$o~P{*3)SK diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam b/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam index a428abf1591e57e7cfeea5c5e9c0ad81b1ad5dd4..df7f5a3589e8298364c9b6e47c8ff767d35bafb6 100644 GIT binary patch delta 26566 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 F{{yE#b07c! delta 26292 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 delta 1708 zcmZuyYiv|S6u#5hZHJ*JnR1t2=(g-FcUzzv^p?GZg<`xdtOcToeIcu*Er{~4P)bXo z6hVSXm8T4exuQIzAV&OQmLg!mmUnqshNij|OV-OguRpGN8Oge=D2hOHf8A)`#?5qtkU?3M5hZux?`NzgWI$#Pn?-KM ztA}L}(jTwoh3Vu{e5+_6q&NO^);6LARfn}^=q$(f8MdX`9$%+0J*M2M*2!|8syo}gvZnPpVa5GtUGK+ z%2-z%wlgstPSddY3PS z-FzAB;>%$tUm<&PD#`0o_+wcyO4vS!9YwB&jb6b5a)bYg$twk6A0B}H)aDD)afPt` znTl}Ov1Hnh6KRt<4>;_Tv=Mxj{N5iV3na}A&Cx?}2#<9Z_Y-yq&(4b+NcoYYAg~#A z9=1o&xq{^r*7f%st{!pE8K-qNmawCk46!Y8U2c@L%5%9@WUW;5YDk-0o>#DGok`e< z2%My)G)&9F%8cRA&5RjFWeB<}xj)mMXV381)Mpz(TeZr<0{85=M~B%C`)s(Esh;^k zfwviNFU3*}6_@_=l1Jd+F;4IQinA7wB6lX0s=Te*-Lh+TumLf%mPFQaQ&f_*2bSm^2)1XgI z57f@=6*?-y3S1q1!ZZ{4+l)m1^A=oiNiPf`z38xoNV*Y8FGb+8{4S7hT}maoY{3;b z@XCaNDE&?Z?#k-?{5f}0F?TJv=PI~2M8SRM zAjWM$?!gE=p!f>#2?X&z58^F;FclusY4Aw)<`Kmj{+n?&T}&F^y>V}&_2=GGc^};GI#MG0il+Pp D!%l6} diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam b/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam index f74a9aa743de40b5f4235e7c1e6983f41f12cab5..46f1e74c67d947f2c7928f5b1a1995785c2f393b 100644 GIT binary patch delta 26267 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�{u#WzJAcWxWxKpPJAoegG!TR7CxD(JW z1bg6-SWhe`;=1~G;*t8(s*{uP;j@P-?I++)vzPtRiIEkf0Sj@bS#$xqv(mml?!?}% z_B-$h#6gZbiKD85U}L4d33n1-SNpAa#>9ekxRbcM;M{=60wLZR4^lxYfX3r*v{#W* z)9ktitimG@EAQbh6|mA@;BP3K@&@jtuw95RskHwCcd6i&{ukqKf&&XYGZ4ccT?j6! zym$cjQMg!Tz=f4|63yry?dQ`o0NsSUhD*ZP7`^Q!C35#!sYlm+G5<2_^-p$7{IT*2 J@25L1`+sF^5*+{l delta 25876 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 ZPuL~w{(jTjSGCXo>%K|eaT_oD{{Si#*mD2? diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_type.beam b/bootstrap/lib/compiler/ebin/beam_ssa_type.beam index 3f174e0503e7ebacc89dc5c37c5a7bf3e29c7ffe..d8226f3fa1e3cad1759f96cde8e6a3420bebce34 100644 GIT binary patch literal 44260 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 literal 43396 zcmb4s3w#_^^?#^*8DDeNDJF|I|$Im}}w)47k z@44rF&OLW>^66(TtE$?yv2{g@+fqI&UR70l^*ispJ+x<4zN^q#Ds^?1*BA4{{l#); zsoXVCwhLXwlD#&+zBE30uX9-@KhWFNx2A}Poon*tjQ1$n+fyo+B3JYjhgT2u7dq)O zIgnph%4Y`hh5k$PqotlTeO={s1NqX#)M@83y69ZJt}k2e>F+D9>g?^$cJ&V9*i+6A zboJ^z{h8I54d7y5uD^47Tf024Ex!U4qb|6nvUe(h#h^s;u2HJ}gEclkd&#>nU}XyVk79=e$;f#dT#aTEle0U)0D+Lrg+-{=!JYK zGEnT#c&DSKb=hpbRO%ln4SRP$BdOLuoq8zE@oyCe`ios_2&r72_Ho%DA@d>Xf+pzZ z=Tgvrg-|$2T`9;X$Z5x^$XQFOtxRo-GYH2e2&$yL>lvn0$V2-3`up&>)Kh@GtzO@W z$wQ%#0NKzP14Nru{r$c9u09SB)B}WYu+n^(&n}phGz5naofIbc zncqVObHKginsr?Rxk$0QXS@uyDwoOw&`I_>=q;#?oV^PF6n!4jyK|!ef#v}ftph5W zj$ZB^^%#n-KtFzg?!mU8Oumrhj5rKofo52f9~kE-Ue&*@FISR+yu;F342sF*aIdSc ztS@cWo12SxL<%9&ytEnJ0;K*vNySaV5~&RSbl+uQU&sr{?6vOe>9w=@o?a55{(HhB6{OmJW=*e(l14@~&9;**Nx zdM@4L&9&UmN83XHcH)BHO%k)LAE$|=dPY!DL5Tcj6|xp zcN8|or{2V6Jz#2|NA^y?=v-DL;Ranj4)N*4X@e2Cmg!mrjX_MFf$r%VSRa9eNOLNz z*XfV#sf1#-o5V6V44ivs$It72*0D#F${#;wSPx)id;FVG2Dcu)6fVDr^Iy`+xOH^>Tp80KoSl) zjFvmOiJkUN3El#k#`RNg?86O=HQB=?)B1{;k5wA)?IAm#gEHwJUx!!tbw0Oe+Ii

SObr&N5h1T9*wSSycrz-g=%Eh5` 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 Z+kdH^dWqv9X<9>-@24-~ceN@_`yUJ#4d4I( diff --git a/bootstrap/lib/compiler/ebin/compiler.app b/bootstrap/lib/compiler/ebin/compiler.app index 134ea1fda509..ddf47dbb8e25 100644 --- a/bootstrap/lib/compiler/ebin/compiler.app +++ b/bootstrap/lib/compiler/ebin/compiler.app @@ -1,7 +1,7 @@ % This is an -*- erlang -*- file. %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2023. All Rights Reserved. +%% Copyright Ericsson AB 1997-2024. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ {application, compiler, [{description, "ERTS CXC 138 10"}, - {vsn, "8.3.2"}, + {vsn, "8.5.2"}, {modules, [ beam_a, beam_asm, @@ -31,6 +31,7 @@ beam_dict, beam_digraph, beam_disasm, + beam_doc, beam_flatten, beam_jump, beam_listing, @@ -43,11 +44,11 @@ beam_ssa_check, beam_ssa_codegen, beam_ssa_dead, + beam_ssa_destructive_update, beam_ssa_lint, beam_ssa_opt, beam_ssa_pp, beam_ssa_pre_codegen, - beam_ssa_private_append, beam_ssa_recv, beam_ssa_share, beam_ssa_ss, @@ -76,6 +77,7 @@ sys_core_fold_lists, sys_core_inline, sys_core_prepare, + sys_coverage, sys_messages, sys_pre_attributes, v3_core @@ -83,5 +85,5 @@ {registered, []}, {applications, [kernel, stdlib]}, {env, []}, - {runtime_dependencies, ["stdlib-5.0","kernel-8.4","erts-13.0", + {runtime_dependencies, ["stdlib-6.0","kernel-8.4","erts-13.0", "crypto-5.1"]}]}. diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam index 9c6d6888fc3060f9b349b8be90c0d8462f9df1cf..91484696b2d20cfd0e876e169565e86a5fb2395a 100644 GIT binary patch delta 15064 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

!p8W*uM=3#|4Bc2wn?jaJW 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 delta 14928 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 diff --git a/bootstrap/lib/kernel/ebin/code.beam b/bootstrap/lib/kernel/ebin/code.beam index 0e7ba4c53a8e9997ea50e748fe518b5cbddf87b3..cb74d7b0c49c7c146e7ae0d220b56754de404e3e 100644 GIT binary patch delta 203 zcmbQz#Wi zLcvF%5YPlhkV&jyHpqkp2n8>p3Z4ULb|7X1n{WZ4;2BU5Xf)$}APsT{6G*`(hb4@R iJ2o$MG+`2OaMqJK)oXi3WWnNZM=sV0Y<}si%?JS5Iy6%N delta 203 zcmbQz#W|A3)3mM4UjH5r`Q;;*%ZhMPLfPKqMId18HWsf&zqs zk3d1735+0S)3w@UVsL^<$mM;U#v;ZF&BG&ToF{tj!1jMi?`6 diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam index 3154d81551362cec65c41d1e2d940bde2d029a3c..6433f76fda973a062beebedaea9c36c68179d150 100644 GIT binary patch delta 8686 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 Sw)^B2-#pdz1OKwd%>M#7v&EJG delta 8693 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 PnkT$-cl!pm*k=C+L&+HO delta 14476 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 HnC$-m;rNWO diff --git a/bootstrap/lib/kernel/ebin/user_drv.beam b/bootstrap/lib/kernel/ebin/user_drv.beam index e33e3942a439e2eddb026a3d90b648b589c767e9..5fe6cfccd86aaac5532444dc08befd6704746f55 100644 GIT binary patch delta 4295 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 Oal*5!?r}>N_xuluSSR=Z diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam index f0fad6254627072e7a18d1d4f677203c532ea17c..eaab7b5364c89ad04c2021e657fcf250adaac93b 100644 GIT binary patch delta 2139 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 a-(%%t2Xs2nv+UfJiUV)gv_wYsCI11LE7`07 diff --git a/bootstrap/lib/stdlib/ebin/edlin_context.beam b/bootstrap/lib/stdlib/ebin/edlin_context.beam index 78a6f1e86e29a0415e9e6d5b28d1bb9e1cc4f2c5..6d5ac67149a2d984da5f603dcac36feab60db709 100644 GIT binary patch literal 12304 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 literal 12288 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%0DqY|%H_{2kEywYEvNZ2Ma+As{*;cYUt+K<#} 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 OY4{U$KIt))CHcQq>ZMHp diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam index 098b353153d933244f3b20bae4c423466354cd76..0dff2813a5df0634842071076697d4988f102dac 100644 GIT binary patch literal 107636 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

    07P%y(&&+%XuGDVXwM6e^G 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%0DG=%^)eL%~pOXxR*={ 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 literal 106512 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

    {zU3=}0 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∾)F(39CsxiON06*ZNSXJRe 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%0D4EAYBR#~P2j((wS3$C&(r$qP(=>v4~C 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 DLNr&% literal 185452 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 diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam index 319761ffdc77885cae734a46481eac203eb9081b..cfde60d1eb2bd765292e0db54473eaadc105e24e 100644 GIT binary patch delta 18659 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 K@31Y`6#YM16kzfI diff --git a/bootstrap/lib/stdlib/ebin/qlc_pt.beam b/bootstrap/lib/stdlib/ebin/qlc_pt.beam index 5f28202497734c555ea3b7484f68a57652b17f96..c066d199bc6d21504d050285ec9a2425e9baafa3 100644 GIT binary patch delta 18762 zcmZu&349a9_s?|G651k5H&BpkApt^5A&>x@LScJBs2qiYMGh&JV+9K3P(09}sJ|6m zK?lJ>v?!oKSVamy@kUW8YW(2|2q*|1APUG&MMeF8XE!PR)qg*q>CC>Feb>Bs^XBcO zZnbmc8fWVvqsH`hkhFCL#rY%h7mZUKj;zAJ|Ne8*^R3r5t^Ie?b?Jpy=FC_ywQBmp zK9%$4EbP@k=axB@-fR86`sDa?j$Jo(+LW2o=T2WRbJO-n8is$NqT^heJf+ ze>)wHl*zRfS=T0!yxP}$Och9f+Q~2Be_#KDq$l0$?-lTE4hqbrIK^hYRKczChY){o ziZQP$I4wY~)$5dWvD7KYI@0dFUm~sO$==60CZ{F4#BxDQ5;7bTafO&`cv42{0Fk(I zQ^c5~_C%l6MEZ)jikNF6I#ijsic@6sK<)j(Vv_TQ>h^FNMUv_P-DytQe1U`TEEK6u zw=Swy$8>aj&qM z09`Y<7xB}*gGZ2T+Nn5`_E4LXu5_R(H}Bj;bahaj9@Q-+`^}DYwz`aD(zB|P<>tIB z;&c`<*DFBQBCnZFT>q+vy$V&{2Xa@?(fLx6N$8CHo5`=W$MPjYPSyUmpmP#AR-0Ko zfsjvX7YwN)WIsJNbQ0N1^TKV(>-3s%ki1ME2(KW!Xoq2WWG9_8th|k>dZ9;2bqCaG zpe?(nG1uQt)u^HG5A%{o>G@$Fkkxc|$uzREw#!wclF0q^h7r5d?`A%k>%b`*OKJYd zT5@CU&m#k*urgWf-_b*Mm8#f?IyKXsl{$Pgvst75*lLE%qu zKer~QNYV$CNLSAZwrmmfx{C#fr-J<*%=a_i$e>@&$s-bNUp0mdq19C# zy+a`3P{E#rm#m>Li+-*eIW-Tn_q$7Ug=uY-2kzxS)od)P!nrDz@m+Is@PGTD{09*FaFP)x2IEEaDE6Tg9*Hi_&#Uh7NFlwCBDNoIY$IFs|78q&Li#V zgVp7v13gtei*%%8=XWA9y>WgK=|o?iKZ10oO&55GhvqD}l6Yx&LA%jiaxSJmp7Sg5 z{kkOQH@~aIBX!UDtz0@*?m4ISk<=uQngz!d?mW`(x{CNNT7!ni2dRw)dH5i@bHO0u zqyJstCFg0Ig`-G!di}!k^emBtQ))&u5%@H{zi=Tuj=Ja;(u2OdXb#Dtz8ebQt!Ljb zk@TW_Zzv-pXxkfg*GLvtu^2|tEjPA@yV`f7OoH_EjZ@sE4iaw9!i8ahggdZsF*MPS zPF_5~*WXXVozi8$>T#-)Ta^U0g~Y;P7^}+d7w*54fQQj^_u@$8x9ELUQ?CtuZ0fSa=h< z#-KSJ9)^XVg0{zTN7Dz4J?)ZRS3}V=SU8GN<1lI_3vV7Ny2?pdW8r52ET=avAK806 zM$J(P-Z9ZTj)bdN_*wK`1NdC-w8GEX@Odn}4e$x{=jGkW1lsYwXURnR!F|2Rc>33U z?aAcYcJ~`eT=)U(2qHi3liVBz=h(o{NnMVI#1fs4D+Wzll8n9de3&`L~k ztcl+>k@+vZu-n#Pc_LKNN>;*3eA>`!j5vzngaQrNM zh(FTy58g>;(e)4BoIHEPx~w_0!$b4Q9J=zMiDY)|nTG}tQbm2MdXlQz@>RzOnM;+` zjd;0SSXv;6*u(hd3HYCY zPoe6Xme9e~YdVk{=nZS`yJCtRE-=lB?h1OvBNNF~I_r_XWHDX;NEdPwedm#JpxKV~ zEV>z{@qW4}tCEvx=@8?(xTmpQa5%=aW>DO%P}v8e5iubbMJ^B=+*vl8_>gI84HyGfl#{2pzq)eY>TSCs6E3@^G`unk@+)AUeV{ zHwN56m#_7bJLz+4yFzcDt(}1Xy&qjkmeDsK-QVvnpgz-o#1E3~znYWq4?usGgnwjO zXS{tk`p+`WGg5X{lJGgEc>%nK)~yS5_!qikc0?jf8(;S{8=rwButF zOYen%zo}!mSids|z{?#Z{D+z$!04uv@Fg3DL4R`723U5@AmP85)(2zn2mZeSnMpJU z(|Q78(03opClAo{$7QmD<~-h0T*)zoiPn^9*%eNrK_=`T-qCN;FphEZfay?(=_die*l@YQ(Z3Hs@Voc`A{Z6vI7 z79t!tVe~lVDpho4h#RF$f7V8~6Lo3UCbyLJRMu0)Qj%oBpQfRWo_d5uOdAD+Q95Vi z%zEH379IoOW_n`d&0P`-8_BfM06qgnjk3*cG|@_##z$_UcWmkewl{1VT#sZN3m2hl zEB$HH5Mt8MQ$yX)LIo3)s>wpWAPF^9lOS*ly6UMhZ4)%6uy9|z^PEbwikhma*6vH5 z?$~|^(XM0KICO0T`AWD^Xb)bt10c`Syr;+4Q-w~rg0|C5PX|dY{ru_vWCzWN<|E!6 zi~s+otD{l(3qW$4QWXIo9`JEHd|eAVW^?~~EO3o{h3}$l^HB04J-)d&d5KETj0q+f zy^n>{FyLh{dVh+VbC_rb(;pESKq&O2Q2AP=KB+a-k=p*29r1G`Yj8{9x81eP2Qr@ zxB8{GLE{;l#umh382Jv3ZdGsuIKH(dsiVJc?N@L9JD6610sBC2XNo^3Mznu3AKzQv z1(Fw(su$zB*=5Cl*J1xji2gFurefTCbhqgz@6+?98Ax>PVcN7EPNKcVe0&p&VY=T| zs@@Ue`%1nbxSe9on>hK+rXN1roqRz5c(z|X;`f-3Z>ayF`Oj5H5-2}JBoE+zp!&#; z)ZtSG676H00s#N8f@q&8RiA>}%7seRXHxporD~;DT^Ll$iqyifYG9h`S(Goiojgnl z2uzy}_n(Lpu!Cwd@H|*8Dpbb?)J4`=$XlkmBUs#CU9P}E;~>*!VwH8nYFFKrYOqi( z3aDc-a;)kt(@RCQ65*$HBH^b+Cqh(&>Ds5ks?P+Ja!FK^xV3&JR`4A_79{>Z>!Y~q zI{*$K$H$Q4pi=dDT#my+fxt7<(`#@jpyJjjX=y9tUAPL zj+N9Rx_4WL$RTWxSpjU27(NSUvlQ#RQK^nCRHxYzPg9G^RPR{5)NkRO!DSYgawj5t zxeJjccd-PqaQxQ}@wYL&{_UWUjNwa(_Ia@CFa$n~*p`cXI4*9ddU>IG+uLJjn+=ga zEhXAfrRobh;rY>#qYZWU1>XOXX;m2XnM$-{p{nC>%g4D}77MW|$_fO(usKk+SqP+5 zRGlE&@f10RZR9Ja&BZ$hpvx0V)ycRnzn0Rgm#Sr!O%xWXfw8J*nq?3H$&z;-&MT3T z`~>X9)LIrWt;|XxRH&(I1ZPFgZG7sz|2y^W#MEnZp|2AS**_Vq`Wl+}IOWTFc=%fc|4!&im+mJ9p0TPIK5 z$$WD#;)F`{sLik4!vT8$ z*dqrqV%xtv<~JvLddf;8jp)rF5kjZCf$N)dL~pJbEr9ES5HiFIxhQhM1xK1#V~A-Y z=ORs%(^_O3A{Ad~Im=CSG3A^AWG#Y5hM+DJ)Dz2Wv>A;oKu73v4`_Vr${@O1F^N@L&BxqT_LvPJA9aO(_wIq5Q#c0c^wiF7|T8e3{YK$xCJ-g=NMDfe6ijwxO zOrl?z;%aHMA$nV21!i|zi#WA*Oj`~-r(Lay-d-_ej;FOyV{}YwEoXgSkk(pEYaQZG zxkg92{>3|R^6&i8-sT;IK0S;M-lQ6%(^!Z@Z-03L9rLogb$hW?EO5&_z>=Mk?mJU+u$?vXq3g9}b%l7Qq~4}^vh)ZH2^ zYTcIt0MWY#jV!D^J?pZXZ5?OZB+i0F55?$dkq8+%u<0C0wvR;|HBc5f9k#H18RY;!W{efGt-}o7rLW(g^NLP`p@TyXfUh}Hd zB^SG3t})13s}k0#C)*e#xsf8yGX@Yn7jBB^1L%XVc8-KFmDV)cn;xIWfk7jWv!B;k zQ-hecrUY*eX1;;o_7`xgE=d;sf&jNMuUwFO^Vjm3Zvc8PqPL*FH-uj7jYKbGz7TqU zLvN8{6h{)G@-(U~YEeT`i}A`3ragjJepiV;bh9Ub`13zR4>OGc_y^=4mTi zP%p7{3SD2tw6z#<2_uGEA)h{iX^#T(CmuA4;m>}SceIx z+nWdh^ie6u=@PvZjErVJKi>aqJ<-P~#yGscK`7YZs4dtaZm2QFQswob$nY$Ey>s%I zZA34lPrsg(RgTu!l=a3KqK^ZLtC{vVQ2f20=;ewr0VqBO2iJU@Yg|MBczwQHjj%@O zVT|Wr3REwg&XY~#-CT=2+{re^)BAV#X*T&B(Z{RqJ*u}>4bqz3?It6upS<5F2mG28 z)I^^UG$sn_hK1@L%H3M+GMj~om!}kr*!Dk(X^2Bh2wtA77!_dYf?zq#kTE4q%r&Oa zqBmxwTr2dcF{aXOZ>VH4J^w~4axHbe=?_eHiA0|Q2R51L73#;e>IOmGvq3$v$7W+H z(>Co`M0A{Ho&t>|Xs(jZesgR8X_kS`Y-pe}%O!ug7gh`-olf*=mXS_p+Ez>ayQ(Fh zF@uiW(oJ4dZWC7`Ft4B6eMm`jGLfr3G=@g&StSB7f22d9z1yP$ORrp zpog(IKnf($%6IsUTZq0mMT{6X68$D{bu-gyfh!f%Zc&U|aqNKd-1$f?J25uCuHDXh z_k3&6SRz=u;24%9B#cK%`fW_x0d#55*zNTii{Q%#fa&0Osbbv8`SpR}JHYTAHp84f z0KoJe9@%1nr%d6pmeTaM<;WdylS_$yXV6&2HMy)Y)w`IlBM3ADfx8vs9!nw6gQTXe z_E@JuLnrz@c=KOO+lhf!Kw4cfmSbQ*CA|!xDMf z%c>oKKFqXTppyZaS1ZONmdqhz4dh)Dkh$=9D8vI@@y_6Zs~h^wHIQ;O(H{vKjH73b z(XVAb0?ZOHKdKmy(bT=Zp6i6HfEu(uDq3H%9xWyMx_W@>EKg`jj;t`?L+D6Hg$tjrEYbhS1k)VftoIOnY@l z8PT^g*I%HL31cx8V;hKggaVHks4pX_zQ;`0$V!R?W^UJVPZ$9!B#qK1WoZmo}U_Q_B zdvV70>Ikv;XXo=y*?9S%@xm)XnOcWS`!c4H3SVXp6i zP6h{i6=R>pLCC1XO0BcqSLCvLeV^!cU}P`R_XUl2xj^qWM)#hLt`oR>Uom3;%ia6` zR81^sd=TdjXg_F-?mx^GLEfsQGuYd&7$05^hMGNX2SfWCF6s}1#z&m3j~e6on7NJt zjR$BxQ4F3P^6-lS@Bs&i{wd!0jA?r?zze<)C;9qbHpWkDr(5+})!J#9>MyI zuMncPSYmwT@RtW&8F4@-wWJ&3krPD!N-gmrt~fz=#c~Q4s9v~AtPR|i@bJ_b&fUni zxjuwvJSOfIi@ixwu@hf7kdaQ!bW2H|`grmrbaRa8UsK-)JqIBxf?Rn?cL?*XxYCbf zx#{K#rVhsIAi=af;~Q z2MwMN(HrMObmT+c1Ilcm{82H^#ZjIG%CiAE-H)pz)>qGf7t;KQowUH~kP5t_EzME4 zN3vrIKX9J~sUL~%I~O!~=0tCtInjS&u6IDI2WVZWF@B~s|7n-;-};<{)1ARj9RH=U z|Fj+RGm-~IME`}kxUJ@hME_MWezR2uoahs1-bX%ut!3s%J;z3qBof7#&++{v ziuBE4UMJ%nAny(2c+Z9R?9Bw0TnG~{tTCIE7y4CfgxF&dEqVa(fc*lGT$yb)p{G6? z7)kl(fhO7n*NRd|)CH3G5On|~`hW!3PH#ZMj;j!21ZvE*@_6{l}YLT zQtmJcxx;{bsbVz_$)Z%?^mAiTdwV5MeKIwg2EwT%nhwIvnCn##4u~Xrg<>|pykAlA z6Zg#3)?&dSJK7vY#Qh+Q4T8xQikX42vK8av$`GXEXL69_W49zirKosn9N4IXS6kjw_z?G67~l}SBA{? zLN1E6C;z_>e*SR{Js#}Z$V9WLulD6f!-a>A9TiFgrJv+LI!hok`RS;kz*HII!U2TC}TT+6fu!++zAX zxhOcqKuidPlz@mkB1=r4>JJ3ck}F-I@_^hTkZpD=_w3)EZTiXs`}>e+w}i(xyEgD) zQDkk*t|ZzWB(s={pS}h{-`R?pV_9j)>;ZB;8lE_0Gn=0ItXFyum{~T7<^;{20^M@B zm)x__b{Xx(T>KcA2ZVmb>`iYx(3$utJ1~g!<}bAE!(9CAI0*d##q1j=7zDu}?R>B+ zu8=^hX+h8lkZ9ka*^l0OuxDAn#$@{AmK@Lw1{y^%bK|Sa0quyMZf1yhn0E5EWYx8> z+~X2kc(~)mTJqq!32xfi_vJh5*-vY2lFK}xUnEAZUTa6 z0f^=+W}!vYp7R3e1pbEa-ilcuZHP#4Z3PlfLwj)SG4mTvX#vROlV~AG6fqa>la&-g zHN}cK)KX2hImFW^ZVa+n-0;mIP(d+?4#k^c=6Vuu7U9ididljP43R4iy@HdkGycg0 ze)Jos-yCk=yF)Oei=q|2J_!#stRdPG;6s+^8{jMUljv~896?WgUQCA5UWYq(9)aGG z%(Wi9LqKhmVwToZLuf6Vqv*oJ{SiaJWCo9BF64DehL)1(n2o_mL1To7$MhGVP3osp-)^k@EQ5 z3PJv9B03(M+awabhG{%bFM*g7te6eoW}*{uPZYqb0GyfK8QpsY%EiQ=5+$*2U84Au4`<2 zmCUsQT#SJ2O;gP2z;1gj>yx}WlSHROj2ZTzkzjSEVqR~tnqz97xE;#o%=okq<6l6c z8ff9o>x1SjJ2*F|k?5?(lxH*TM^GMBL85bN%z6B_0`8AghRk^|`g!!uFRHI!fcWDR zSU#`ciq|{h^~QL;Dqi0euNTGZX;>)>cz}@J%AekfX+JGVcAy~?q$3xFC7hm#GuWb# zIUlw(pHBR;4Y{HAhA;ajA;Y-k_%USt@Bb>~oJ*orbl+DUn~&l99uFT2ya*lU(qF&o zN2+Ph6EnxnOYz69Cedo9H{(&od{E-`0;Y?+UdZ$okg`lAQ4m`UVvD)qBDG*HF2qA& z+=>^M;h{_|DDy)Di|OeTS9Vy;E&4{kc>{^wfH-?Ywz+siYBl~Zq&4PEwDZYqGM0`! zIrfSh(Tfdku_tvO{?lzI2Spac@WzwqO-#?&K}qyx=DHVLjDro`Qe)oCbK-^K$$iKl~@-pYF2zF6uM zc*xm~L~mz$CJ>YZL8Qi9$`ORj+hMg!>AhbMbHyKSr=Nd4IC2Mb;R{~Lco^ZGig}l1 zgf-?esWi29{qA+AW#E@HJke!vcXyKLT|x71?p5z@Y+v^<{YoIc2KM!@khvUgV7a7* z%==(n%ehN+RARL)98hU4Z^rNCn0nSyQzucKZu+KI_5@tQh6^$fUIu%Z_rlL7Awq|$ z+BxMBhq$#1xMV8?N%UU&_csC8avSk|H22&79qvm}V-ra9ex|nt0~2HtH57BDwQ6e2 z6?Db7?II80RvXU#_;$nZ1&A2Qsl`{3wTK?D`;!62tgXP3GDvh~(0q^!`(R^XA7VPs zBTmFnnqKPPn(0T5ogbe(MNIDmp7$cpP-8wK*!O!|yZP1jAiv=jWO`@x--*FB<{Db? zUBBRJJ^`MPxf(iKEy+Q1wTEv<*{Gekcm`(}cYW3kAg|o{poSKJ! zW0_4KJk>I?G22|v1;IypPNoKA*4s}u8BnQdNacy3i7eYtmz$G%vN5R*OwR_XYef>> zI6yF;%B(1vVs1+9h!QY2k?1BXg&lng33j~xG;?*Ci{TX*9u1jK!(TjYZFIbIGt+yZ zZz>pihL)VpDcEvZ-&?r;kRO|l0oOq+Q!$^j#0r_u!s4Ix_<5o%+k7^VItmd5jvdbi z{3Vt2#nas)+kx;|7???-&jrnGoYc07LIBo1N zGu;pD8f1G#F<*eX% zAJ8^G4$j<<(3|NB_rKP!Oq~3}QORsN@5eS|I=%NtU!>3}Yz*K>CrQNt4?nQt{s!N$ z1gXdh#y)^s9!{eFVS0ZsG#AR=ub9XQ#v@!S=G-4Y(5KG3{9z~hVbJ7x!D!>WVDw|A z<4$SGJfQld#w4H8-e=tdKg9)%ktF&V(+8lh8hr;8^H6+F4?^sNI92&^kAxpYumw3G zKYZjsxRoRHj;3Qcpt>(gV+(p{4!4L3lRIl1~!~!x>G~X5Sg-sYo{~bbJkT?}IPYbpu0j1NIDFCx= zl;1ObFla1NN%V|j{s z_CkD@z2HGuCJO7!^YrNXE^~gm?BwgSe|%Fd;+raj{)y@Q2Nux_z|8CaG95p(C|QiI zpKHutc&sP-dFs=;&J_KHe?vsz=0V^#1h)eALr80tq)H_>(YZg#>Ay04C=lEXQUHxCMaUL*`%L_b*As$`!z7A@;PtGS?%1`m^L#lqKe+lH1HbN^Up*AkjZ~ z{>q}I2E1w^m>x#M7kZORwBLnJ^wA5QkpsNtLML(u=(eWS7n(-?`kx^4Z>A3i;X6fA z=TKrvTwy{@jNs$tl?Yrt*)ift{WcLH#vBbc`iU# zxKCe~s>JNXUv@0bGt|}6x(F6a<-8`@zdx!&;*KLt55^+R>;n@=-mEdwE0~K#G5+1bO7E$$4AIrX zzLrVws}(uuEcVdcpW8&FV2p<{b?(Ltv}CS);QSYK)=G)BwsaPXWlFgy+>^t8c7S_floIJP#8v0Z6n(;-ek5>+{t8rGyI`z+ zTt&d$zA?@Y%!S+cCHF$_9hF#TaA=*Wt&~u{r_d9Mbt=q7@yEYmRA$FIRi;AVPURjk zUA5vAI{KG35gCgP-ye8tCul`|$nNCwpPY)@tQ#!ulI11$#qYq&m#=8m$@W{x7zxdH z!o+qYb)Bt)e4PhBXa#fkLw#N)*40v9LTgr@J=P_VivlMXvGT)Z*|9EVoVzak92<}& zJWD0R;veF93O?qI^W!WrN*+k?(?DNcFbQ5#*A)}cjk)-~w*usSN-R4*ds&#hEIxap zM~P*5@;w14DN6z)S#fV0%PQnNWYJrHZ5!zhz2N(l81q5J-L3Nr&;I~5nDI4SfLWmI zBX!xqSPwq^JuXib(@X6&n8RFs!O=>f>Z!#1)@+4hy*#-nmp6@AfYkMZB72fLe| z&9U{qjLk-clp;sv z8ps|3U;Udoa3@sccS7YYuF-VW#dZ;e>9{jjLeU+vXEv9)dIGWvkO891@0N-J5-20( z3Q{+ax%fHwVf5uGvB7a62SLa|c6QbBk1(w~o^5wKtTPpUo_X2k2SNBeQa3ml!wv#n zsEzr}XZl!>SY1l$3b@BD(M$ijo$?%*$wmh{}8nUU5FAYIVruk+rnsPVeh?qsDz0BiWO3CFdV%*_|tsDEJ&+8CGo z9_l6y;8W2CqU2{#V+!j9s6ZQxCr42?MM>c2GsEE76>NuX-Pv#NLG$E zmw*pVM@fw5w#DH~P&eb?xB%nO;tX+(T*1L{IHugf&jsPy6F8ikQVAX~X~`2%V`}kd zYhox`T;egPTcB7kU}%4|`S>eQW2*3HkMD^V#ykH&4Fjkj-@|GJBJz z{N#7EIexC$jwnfvh(&;0!UKO{IBFRs@dCG6PMEKbPACZizo5n8D(cQC3HVQFaXdlP z9+U*0^Kp0|)ZPa0b47UIs`jJqf|5XV5-kqrs_Kf8Ky(6aE&-;&(GA5i(lvf3aYy2^ ze`P@(PO#zVj*`ImC0c+9f1!p~x8DTfFRZph;5y4jNsK>=7B~=oL(MHH!NC!ehww0JrGY0QoI_54ub&V~g22mYaf$i*$wi4TXtE7$KE4w50F=ad z&Nv@mfqEcHf*})a4j+#?4<+GA$X08RL%16CAe026$I*ht2wd91C<#Q5q0LpzwWgvZ z#;-$*GsLGQA0?r=wQ)GNtAYk_uCWML9XH8BlmsHKGLFcDx`>10#uDFMgqDC5qa+AW ztL+dZ)I(4b-N50jM12)XQ=8EwXpL*gS%rEyN*qrT*8s=Ejd}zMaa7uf%J2Yok{6*Ki4tch zX(HNqA(=}!ssVhS)pjI*g1QtXE?E*E2c}ZE{fth)Uyxnou_W=P9oOW~KK6ZhO6;C~Ihx8Tz delta 18724 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 diff --git a/bootstrap/lib/stdlib/ebin/stdlib.app b/bootstrap/lib/stdlib/ebin/stdlib.app index c947f9b04782..697f8e82814e 100644 --- a/bootstrap/lib/stdlib/ebin/stdlib.app +++ b/bootstrap/lib/stdlib/ebin/stdlib.app @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2023. All Rights Reserved. +%% Copyright Ericsson AB 1996-2024. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ %% {application, stdlib, [{description, "ERTS CXC 138 10"}, - {vsn, "5.0.2"}, + {vsn, "6.1.2"}, {modules, [argparse, array, base64, @@ -37,6 +37,7 @@ digraph, digraph_utils, edlin, + edlin_key, edlin_context, edlin_expand, edlin_type_suggestion, @@ -77,6 +78,7 @@ io_lib_format, io_lib_fread, io_lib_pretty, + json, lists, log_mf_h, maps, @@ -99,6 +101,7 @@ shell, shell_default, shell_docs, + shell_docs_markdown, slave, sofs, string, @@ -115,6 +118,6 @@ dets]}, {applications, [kernel]}, {env, []}, - {runtime_dependencies, ["sasl-3.0","kernel-9.0","erts-13.1","crypto-4.5", + {runtime_dependencies, ["sasl-3.0","kernel-10.0","erts-15.0","crypto-4.5", "compiler-5.0"]} ]}. diff --git a/bootstrap/lib/stdlib/ebin/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam index c2d15cf98c199840f2a1b556ed17a083ef31e413..40c1374af0eaca99b2df1238895009f273f6359d 100644 GIT binary patch literal 28276 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 literal 27912 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 target=KeyOrName}} end. +-dialyzer({no_opaque_union, [handle_msg/2]}). -doc false. handle_msg(sftp_connect, State) -> #state{ssh_ref=SSHRef, target=Target} = State, diff --git a/lib/compiler/src/beam_core_to_ssa.erl b/lib/compiler/src/beam_core_to_ssa.erl index d6beeb7bb440..5b613a3a6cb0 100644 --- a/lib/compiler/src/beam_core_to_ssa.erl +++ b/lib/compiler/src/beam_core_to_ssa.erl @@ -1566,7 +1566,7 @@ partition_intersection([U|_]=Us, [_,_|_]=Cs0, St0) -> case find_key_intersection(Ps) of none -> {Us,Cs0,St0}; - Ks -> + {ok, Ks} -> Cs1 = map(fun(#iclause{pats=[Arg|Args]}=C) -> {Arg1,Arg2} = partition_keys(Arg, Ks), C#iclause{pats=[Arg1,Arg2|Args]} @@ -1601,7 +1601,7 @@ find_key_intersection(Ps) -> %% the keys could only make the code worse. none; false -> - Intersection + {ok, Intersection} end end. diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl index dd63a7e058f3..7859ffe689ba 100644 --- a/lib/compiler/src/beam_disasm.erl +++ b/lib/compiler/src/beam_disasm.erl @@ -41,8 +41,8 @@ %%----------------------------------------------------------------------- -type index() :: non_neg_integer(). --type literals() :: 'none' | gb_trees:tree(index(), term()). --type types() :: 'none' | gb_trees:tree(index(), term()). +-type literals() :: gb_trees:tree(index(), term()). +-type types() :: gb_trees:tree(index(), term()). -type symbolic_tag() :: 'a' | 'f' | 'h' | 'i' | 'u' | 'x' | 'y' | 'z'. -type disasm_tag() :: symbolic_tag() | 'fr' | 'atom' | 'float' | 'literal'. -type disasm_term() :: 'nil' | {disasm_tag(), _}. @@ -254,7 +254,7 @@ disasm_lambdas(<<>>, _, _) -> []. -spec beam_disasm_types('none' | binary()) -> types(). beam_disasm_types(none) -> - none; + gb_trees:empty(); beam_disasm_types(<>) -> case beam_types:convert_ext(Version, Table0) of none -> @@ -265,7 +265,7 @@ beam_disasm_types(<>) -> Res end; beam_disasm_types(<<_/binary>>) -> - none. + gb_trees:empty(). disasm_types(Types0, Index) -> case beam_types:decode_ext(Types0) of diff --git a/lib/compiler/src/beam_doc.erl b/lib/compiler/src/beam_doc.erl index 4f2aecf7753e..db8a2fed871d 100644 --- a/lib/compiler/src/beam_doc.erl +++ b/lib/compiler/src/beam_doc.erl @@ -61,7 +61,7 @@ deprecated = #{} :: map(), docformat = ?DEFAULT_FORMAT :: binary(), - moduledoc = {?DEFAULT_MODULE_DOC_LOC, none} :: {integer() | erl_anno:anno(), none | map() | hidden}, + moduledoc = {erl_anno:new(?DEFAULT_MODULE_DOC_LOC), none} :: {erl_anno:anno(), none | map() | hidden}, moduledoc_meta = none :: none | #{ _ := _ }, behaviours = [] :: list(module()), diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl index 0dd0a9f37d5c..4720b8b6938c 100644 --- a/lib/compiler/src/beam_ssa_dead.erl +++ b/lib/compiler/src/beam_ssa_dead.erl @@ -240,7 +240,7 @@ shortcut_3(L, From, Bs0, UnsetVars0, St) -> %% because it refers to a variable defined %% in this block. shortcut_unsafe_br(Br, L, Bs, UnsetVars0, St); - UnsetVars -> + {safe, UnsetVars} -> %% Continue checking whether this br is %% suitable. shortcut_test_br(Br, L, Bs, UnsetVars, St) @@ -381,16 +381,16 @@ update_unset_vars(L, Is, Br, UnsetVars, #st{skippable=Skippable}) -> %% to the UnsetVars set would not change %% the outcome of the tests in %% is_br_safe/2. - UnsetVars + {safe, UnsetVars} end; #b_br{} -> - UnsetVars + {safe, UnsetVars} end; false -> %% Some variables defined in this block are used by %% successors. We must update the set of unset variables. SetInThisBlock = [V || #b_set{dst=V} <:- Is], - list_set_union(SetInThisBlock, UnsetVars) + {safe, list_set_union(SetInThisBlock, UnsetVars)} end. shortcut_two_way(#b_br{succ=Succ,fail=Fail}, From, Bs0, UnsetVars0, St0) -> diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl index f27d7796e4a0..54bfd786c416 100644 --- a/lib/dialyzer/src/dialyzer.erl +++ b/lib/dialyzer/src/dialyzer.erl @@ -787,9 +787,10 @@ message_to_string({call, [M, F, Args, ArgNs, FailReason, message_to_string({call_to_missing, [M, F, A]}, _I, _E) -> io_lib:format("Call to missing or unexported function ~w:~tw/~w\n", [M, F, A]); -message_to_string({exact_eq, [Type1, Op, Type2]}, I, _E) -> - io_lib:format("The test ~ts ~s ~ts can never evaluate to 'true'\n", - [t(Type1, I), Op, t(Type2, I)]); +message_to_string({exact_compare, [Type1, Op, Type2]}, I, _E) -> + io_lib:format("The test ~ts ~s ~ts can never evaluate to '~w'\n", + [t(Type1, I), Op, t(Type2, I), + (Op =:= '=:=' orelse Op =:= '==')]); message_to_string({fun_app_args, [ArgNs, Args, Type]}, I, _E) -> PositionString = form_position_string(ArgNs), io_lib:format("Fun application with arguments ~ts will fail" @@ -887,7 +888,8 @@ message_to_string({invalid_contract, [M, F, A, InvalidContractDetails, Contract, " The success typing is ~ts\n" " But the spec is ~ts\n" "~ts", - [M, F, A, con(M, F, Sig, I), con(M, F, Contract, I), format_invalid_contract_details(InvalidContractDetails)]); + [M, F, A, con(M, F, Sig, I), con(M, F, Contract, I), + format_invalid_contract_details(InvalidContractDetails)]); message_to_string({contract_with_opaque, [M, F, A, OpaqueType, SigType]}, I, _E) -> io_lib:format("The specification for ~w:~tw/~w" @@ -910,18 +912,25 @@ message_to_string({spec_missing_fun, [M, F, A]}, _I, _E) -> io_lib:format("Contract for function that does not exist: ~w:~tw/~w\n", [M, F, A]); %%----- Warnings for opaque type violations ------------------- -message_to_string({call_with_opaque, [M, F, Args, ArgNs, ExpArgs]}, I, _E) -> +message_to_string({call_with_opaque, + [M, F, Args, Conflicts, ExpectedTypes]}, I, _E) -> + Positions = [N || {N, _T, _TStr} <- Conflicts], io_lib:format("The call ~w:~tw~ts contains ~ts when ~ts\n", - [M, F, a(Args, I), form_positions(ArgNs), - form_expected(ExpArgs, I)]); -message_to_string({call_without_opaque, [M, F, Args, ExpectedTriples]}, I, _E) -> + [M, F, a(Args, I), form_positions(Positions), + form_expected(ExpectedTypes, I)]); +message_to_string({call_without_opaque, + [M, F, Args, Conflicts, _ExpectedTypes]}, I, _E) -> io_lib:format("The call ~w:~tw~ts does not have ~ts\n", - [M, F, a(Args, I), - form_expected_without_opaque(ExpectedTriples, I)]); -message_to_string({opaque_eq, [Type, _Op, OpaqueType]}, I, _E) -> - io_lib:format("Attempt to test for equality between a term of type ~ts" - " and a term of opaque type ~ts\n", - [t(Type, I), t(OpaqueType, I)]); + [M, F, a(Args, I), + form_expected_without_opaque(Conflicts, I)]); +message_to_string({opaque_compare, [Type, Op, OpaqueType]}, I, _E) -> + Kind = if + Op =:= '=:='; Op =:= '==' -> "equality"; + Op =:= '=/='; Op =:= '/=' -> "inequality" + end, + io_lib:format("Attempt to test for ~ts between a term of type ~ts" + " and a term of opaque type ~ts\n", + [Kind, t(Type, I), t(OpaqueType, I)]); message_to_string({opaque_guard, [Arg1, Infix, Arg2, ArgNs]}, I, _E) -> io_lib:format("Guard test ~ts ~s ~ts contains ~s\n", [a(Arg1, I), Infix, a(Arg2, I), form_positions(ArgNs)]); @@ -930,15 +939,21 @@ message_to_string({opaque_guard, [Guard, Args]}, I, _E) -> [Guard, a(Args, I)]); message_to_string({opaque_match, [Pat, OpaqueType, OpaqueTerm]}, I, _E) -> Term = if OpaqueType =:= OpaqueTerm -> "the term"; - true -> t(OpaqueTerm, I) - end, - io_lib:format("The attempt to match a term of type ~ts against the ~ts" - " breaks the opacity of ~ts\n", - [t(OpaqueType, I), ps(Pat, I), Term]); -message_to_string({opaque_neq, [Type, _Op, OpaqueType]}, I, _E) -> - io_lib:format("Attempt to test for inequality between a term of type ~ts" - " and a term of opaque type ~ts\n", - [t(Type, I), t(OpaqueType, I)]); + true -> "a term of type " ++ t(OpaqueTerm, I) + end, + io_lib:format("The attempt to match ~ts against the " + "~ts breaks the opacity of the term\n", + [Term, ps(Pat, I)]); +message_to_string({opaque_union, [IsOpaque, Type]}, I, _E) -> + TypeString = t(Type, I), + case IsOpaque of + true -> + io_lib:format("Body yields the opaque type ~ts whose opacity is " + "broken by the other clauses.\n", [TypeString]); + false -> + io_lib:format("Body yields the type ~ts which violates the " + "opacity of the other clauses.\n", [TypeString]) + end; message_to_string({opaque_type_test, [Fun, Args, Arg, ArgType]}, I, _E) -> io_lib:format("The type test ~ts~ts breaks the opacity of the term ~ts~ts\n", [Fun, a(Args, I), Arg, t(ArgType, I)]); @@ -1004,7 +1019,6 @@ format_invalid_contract_details({InvalidArgIdxs, IsRangeInvalid}) -> false -> "" end, case {ArgDesc, RangeDesc} of - {"", ""} -> ""; {"", [_|_]} -> io_lib:format(" The ~ts\n", [RangeDesc]); {[_|_], ""} -> io_lib:format(" ~ts\n", [ArgDesc]); {[_|_], [_|_]} -> io_lib:format(" ~ts, and the ~ts\n", [ArgDesc, RangeDesc]) @@ -1045,24 +1059,25 @@ form_positions(ArgNs) -> case ArgNs of [_] -> "an opaque term as "; [_,_|_] -> "opaque terms as " - end ++ form_position_string(ArgNs) ++ - case ArgNs of - [_] -> " argument"; - [_,_|_] -> " arguments" - end. + end + ++ form_position_string(ArgNs) + ++ case ArgNs of + [_] -> " argument"; + [_,_|_] -> " arguments" + end. %% We know which positions N are to blame; %% the list of triples will never be empty. form_expected_without_opaque([{N, T, TStr}], I) -> case erl_types:t_is_opaque(T) of - true -> + true -> io_lib:format("an opaque term of type ~ts as ", [t(TStr, I)]); false -> io_lib:format("a term of type ~ts (with opaque subterms) as ", [t(TStr, I)]) end ++ form_position_string([N]) ++ " argument"; -form_expected_without_opaque(ExpectedTriples, _I) -> %% TODO: can do much better here - {ArgNs, _Ts, _TStrs} = lists:unzip3(ExpectedTriples), +form_expected_without_opaque(Conflicts, _I) -> %% TODO: can do much better here + ArgNs = [N || {N, _T, _TStr} <- Conflicts], "opaque terms as " ++ form_position_string(ArgNs) ++ " arguments". form_expected(ExpectedArgs, I) -> diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl index f59d66a73079..2a9eea0fd63d 100644 --- a/lib/dialyzer/src/dialyzer.hrl +++ b/lib/dialyzer/src/dialyzer.hrl @@ -51,6 +51,7 @@ -define(WARN_NON_PROPER_LIST, warn_non_proper_list). -define(WARN_NOT_CALLED, warn_not_called). -define(WARN_OPAQUE, warn_opaque). +-define(WARN_OPAQUE_UNION, warn_opaque_union). -define(WARN_OVERLAPPING_CONTRACT, warn_overlapping_contract). -define(WARN_RETURN_NO_RETURN, warn_return_no_exit). -define(WARN_RETURN_ONLY_EXIT, warn_return_only_exit). diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index 2ae277fec32b..74b7d5876768 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -15,8 +15,8 @@ -module(dialyzer_contracts). -moduledoc false. --export([check_contract/2, - check_contracts/4, +-export([check_contract/3, + check_contracts/3, contracts_without_fun/3, contract_to_string/1, get_invalid_contract_warnings/3, @@ -230,18 +230,17 @@ rcv_ext_types(Self, ExtTypes) -> -type fun_types() :: orddict:orddict(label(), erl_types:erl_type()). -spec check_contracts(orddict:orddict(mfa(), #contract{}), - dialyzer_callgraph:callgraph(), fun_types(), - erl_types:opaques()) -> plt_contracts(). + dialyzer_callgraph:callgraph(), fun_types()) -> + plt_contracts(). -check_contracts(Contracts, Callgraph, FunTypes, ModOpaques) -> +check_contracts(Contracts, Callgraph, FunTypes) -> FoldFun = fun({Label, Type}, NewContracts) -> case dialyzer_callgraph:lookup_name(Label, Callgraph) of {ok, {M,F,A} = MFA} -> case orddict:find(MFA, Contracts) of {ok, Contract} -> - {M, Opaques} = lists:keyfind(M, 1, ModOpaques), - case check_contract(Contract, Type, Opaques) of + case check_contract(Contract, Type, M) of ok -> case erl_bif_types:is_known(M, F, A) of true -> @@ -271,7 +270,7 @@ check_contracts(Contracts, Callgraph, FunTypes, ModOpaques) -> | {'error', 'invalid_contract' | {'invalid_contract', {InvalidArgIdxs :: [pos_integer()], IsReturnTypeInvalid :: boolean()}} - | {'opaque_mismatch', erl_types:erl_type()} + | {opaque_mismatch, erl_types:erl_type()} | {'overlapping_contract', [module() | atom() | byte()]} | string()} | {'range_warnings', @@ -280,37 +279,30 @@ check_contracts(Contracts, Callgraph, FunTypes, ModOpaques) -> erl_types:erl_type()}}]}. %% Checks all components of a contract --spec check_contract(#contract{}, erl_types:erl_type()) -> check_contract_return(). +-spec check_contract(#contract{}, erl_types:erl_type(), module()) -> check_contract_return(). -check_contract(Contract, SuccType) -> - check_contract(Contract, SuccType, 'universe'). - --spec check_contract(#contract{}, erl_types:erl_type(), erl_types:opaques()) -> - check_contract_return(). - -check_contract(#contract{contracts = Contracts}, SuccType, Opaques) -> +check_contract(#contract{contracts = Contracts}, SuccType, Module) -> try Contracts1 = [{Contract, insert_constraints(Constraints)} - || {Contract, Constraints} <- Contracts], + || {Contract, Constraints} <- Contracts], Contracts2 = [erl_types:t_subst(Contract, Map) - || {Contract, Map} <- Contracts1], + || {Contract, Map} <- Contracts1], GenDomains = [erl_types:t_fun_args(C) || C <- Contracts2], case check_domains(GenDomains) of error -> - {error, {overlapping_contract, []}}; + {error, {overlapping_contract, []}}; ok -> - InfList = [{Contract, erl_types:t_inf(Contract, SuccType, Opaques)} - || Contract <- Contracts2], - case check_contract_inf_list(InfList, SuccType, Opaques) of - {error, _} = Invalid -> Invalid; + case check_contract_list(Contracts2, SuccType, Module) of + {error, _}=Res -> + Res; ok -> - case check_extraneous(Contracts2, SuccType, Opaques) of + case check_extraneous(Contracts2, SuccType) of {error, {invalid_contract, _}} = Err -> Err; {error, {extra_range, _, _}} = Err -> - MissingError = check_missing(Contracts2, SuccType, Opaques), + MissingError = check_missing(Contracts2, SuccType), {range_warnings, [Err | MissingError]}; ok -> - case check_missing(Contracts2, SuccType, Opaques) of + case check_missing(Contracts2, SuccType) of [] -> ok; ErrorL -> {range_warnings, ErrorL} end @@ -321,24 +313,28 @@ check_contract(#contract{contracts = Contracts}, SuccType, Opaques) -> throw:{error, _} = Error -> Error end. -locate_invalid_elems(InfList) -> - case InfList of - [{Contract, Inf}] -> - ArgComparisons = lists:zip(erl_types:t_fun_args(Contract), - erl_types:t_fun_args(Inf)), - ProblematicArgs = - [erl_types:t_is_none(Succ) andalso (not erl_types:t_is_none(Cont)) - || {Cont,Succ} <- ArgComparisons], - ProblematicRange = - erl_types:t_is_none(erl_types:t_fun_range(Inf)) - andalso (not erl_types:t_is_none(erl_types:t_fun_range(Contract))), - ProblematicArgIdxs = [Idx || - {Idx, IsProblematic} <- - lists:enumerate(ProblematicArgs), IsProblematic], - {error, {invalid_contract, {ProblematicArgIdxs, ProblematicRange}}}; - _ -> - {error, invalid_contract} - end. +locate_invalid_elems([Contract], SuccType) -> + CArgs = erl_types:t_fun_args(Contract), + SArgs = erl_types:t_fun_args(SuccType), + CRange = erl_types:t_fun_range(Contract), + SRange = erl_types:t_fun_range(SuccType), + + ProblematicArgs = + [erl_types:t_is_none(erl_types:t_inf(Cont, Succ)) andalso + (not erl_types:t_is_none(Cont)) + || {Cont, Succ} <- lists:zip(CArgs, SArgs)], + + ProblematicRange = + erl_types:t_is_impossible(erl_types:t_inf(CRange, SRange)) + =/= erl_types:t_is_impossible(CRange), + + ProblematicArgIdxs = [Idx || {Idx, IsProblematic} <- + lists:enumerate(ProblematicArgs), + IsProblematic], + + {invalid_contract, {ProblematicArgIdxs, ProblematicRange}}; +locate_invalid_elems(_Contracts, _SuccType) -> + invalid_contract. check_domains([_]) -> ok; check_domains([Dom|Doms]) -> @@ -350,61 +346,56 @@ check_domains([Dom|Doms]) -> false -> error end. - %% Allow a contract if one of the overloaded contracts is possible. %% We used to be more strict, e.g., all overloaded contracts had to be %% possible. -check_contract_inf_list(List, SuccType, Opaques) -> - case check_contract_inf_list(List, SuccType, Opaques, []) of - ok -> ok; - {error, []} -> - locate_invalid_elems(List); - {error, [{SigRange, ContrRange}|_]} -> - case erl_types:t_find_opaque_mismatch(SigRange, ContrRange, Opaques) of - error -> - locate_invalid_elems(List); - {ok, _T1, T2} -> {error, {opaque_mismatch, T2}} - end +check_contract_list(List, SuccType, Module) -> + case check_contract_list_1(List, SuccType, Module, false) of + invalid_contract -> {error, locate_invalid_elems(List, SuccType)}; + {opaque_mismatch, _}=Details -> {error, Details}; + ok -> ok end. -check_contract_inf_list([{Contract, FunType}|Left], SuccType, Opaques, OM) -> - FunArgs = erl_types:t_fun_args(FunType), - case lists:any(fun erl_types:t_is_impossible/1, FunArgs) of - true -> check_contract_inf_list(Left, SuccType, Opaques, OM); - false -> - STRange = erl_types:t_fun_range(SuccType), - case erl_types:t_is_impossible(STRange) of - true -> ok; - false -> - Range = erl_types:t_fun_range(FunType), - case erl_types:t_is_none(erl_types:t_inf(STRange, Range)) of - true -> - CR = erl_types:t_fun_range(Contract), - NewOM = [{STRange, CR}|OM], - check_contract_inf_list(Left, SuccType, Opaques, NewOM); - false -> ok - end - end +check_contract_list_1([Contract | Left], SuccType, Module, Valid0) -> + CRange = erl_types:t_fun_range(Contract), + SRange = erl_types:t_fun_range(SuccType), + case erl_types:t_opacity_conflict(SRange, CRange, Module) of + none -> + Valid = case Valid0 of + false -> + Inf = erl_types:t_inf(Contract, SuccType), + (not erl_types:t_is_impossible(Inf)) andalso + (not erl_types:any_none(erl_types:t_fun_args(Inf))) andalso + (erl_types:t_is_impossible(CRange) =:= + erl_types:t_is_impossible(erl_types:t_fun_range(Inf))); + true -> + true + end, + check_contract_list_1(Left, SuccType, Module, Valid); + _ -> + {opaque_mismatch, CRange} end; -check_contract_inf_list([], _SuccType, _Opaques, OM) -> - {error, OM}. +check_contract_list_1([], _SuccType, _Module, false) -> + invalid_contract; +check_contract_list_1([], _SuccType, _Module, true) -> + ok. -check_extraneous([], _SuccType, _Opaques) -> +check_extraneous([], _SuccType) -> ok; -check_extraneous([C|Cs], SuccType, Opaques) -> - case check_extraneous_1(C, SuccType, Opaques) of +check_extraneous([C|Cs], SuccType) -> + case check_extraneous_1(C, SuccType) of {error, _} = Error -> Error; - ok -> check_extraneous(Cs, SuccType, Opaques) + ok -> check_extraneous(Cs, SuccType) end. -check_extraneous_1(Contract, SuccType, Opaques) -> +check_extraneous_1(Contract, SuccType) -> CRng = erl_types:t_fun_range(Contract), - CRngs = erl_types:t_elements(CRng, Opaques), + CRngs = erl_types:t_elements(CRng), STRng = erl_types:t_fun_range(SuccType), ?debug("\nCR = ~ts\nSR = ~ts\n", [erl_types:t_to_string(CRng), erl_types:t_to_string(STRng)]), case [CR || CR <- CRngs, - erl_types:t_is_none(erl_types:t_inf(CR, STRng, Opaques))] of + erl_types:t_is_none(erl_types:t_inf(CR, STRng))] of [] -> case bad_extraneous_list(CRng, STRng) orelse bad_extraneous_map(CRng, STRng) of true -> {error, {invalid_contract, {[],true}}}; @@ -444,13 +435,13 @@ map_part(Type) -> is_empty_map(Type) -> erl_types:t_is_equal(Type, erl_types:t_from_term(#{})). -check_missing(Contracts, SuccType, Opaques) -> +check_missing(Contracts, SuccType) -> CRanges = [erl_types:t_fun_range(C) || C <- Contracts], AllCRange = erl_types:t_sup(CRanges), STRng = erl_types:t_fun_range(SuccType), - STRngs = erl_types:t_elements(STRng, Opaques), + STRngs = erl_types:t_elements(STRng), case [STR || STR <- STRngs, - erl_types:t_is_none(erl_types:t_inf(STR, AllCRange, Opaques))] of + erl_types:t_is_none(erl_types:t_inf(STR, AllCRange))] of [] -> []; STRs -> [{error, {missing_range, erl_types:t_sup(STRs), AllCRange}}] end. @@ -559,9 +550,7 @@ insert_constraints([], Map) -> Map. store_tmp_contract(Module, MFA, FileLocation, {TypeSpec, Xtra}, SpecMap, RecordsDict) -> - %% io:format("contract from form: ~tp\n", [TypeSpec]), TmpContract = contract_from_form(TypeSpec, Module, MFA, RecordsDict, FileLocation), - %% io:format("contract: ~tp\n", [TmpContract]), maps:put(MFA, {FileLocation, TmpContract, Xtra}, SpecMap). contract_from_form(Forms, Module, MFA, RecDict, FileLocation) -> @@ -585,7 +574,7 @@ contract_from_form([{type, _, 'fun', [_, _]} = Form | Left], Module, MFA, throw({error, NewMsg}) end, NewTypeNoVars = erl_types:subst_all_vars_to_any(NewType), - {{NewTypeNoVars, []}, NewCache} + {{NewTypeNoVars, []}, NewCache} end, NewTypeAcc = [TypeFun | TypeAcc], NewFormAcc = [{Form, []} | FormAcc], @@ -818,38 +807,34 @@ get_invalid_contract_warnings_modules([Mod|Mods], CodeServer, Plt, Acc) -> false -> Contracts2 = maps:to_list(Contracts1), Records = dialyzer_codeserver:lookup_mod_records(Mod, CodeServer), - Opaques = erl_types:t_opaque_from_records(Records), - get_invalid_contract_warnings_funs(Contracts2, Plt, Records, - Opaques, Acc) + get_invalid_contract_warnings_funs(Contracts2, Plt, Records, Acc) end, get_invalid_contract_warnings_modules(Mods, CodeServer, Plt, NewAcc); get_invalid_contract_warnings_modules([], _CodeServer, _Plt, Acc) -> Acc. get_invalid_contract_warnings_funs([{MFA, {FileLocation, Contract, _Xtra}}|Left], - Plt, RecDict, Opaques, Acc) -> + Plt, RecDict, Acc) -> case dialyzer_plt:lookup(Plt, MFA) of none -> %% This must be a contract for a non-available function. Just accept it. - get_invalid_contract_warnings_funs(Left, Plt, RecDict, Opaques, Acc); + get_invalid_contract_warnings_funs(Left, Plt, RecDict, Acc); {value, {Ret, Args}} -> Sig = erl_types:t_fun(Args, Ret), {M, _F, _A} = MFA, - %% io:format("MFA ~tp~n", [MFA]), {File, Location} = FileLocation, WarningInfo = {File, Location, MFA}, NewAcc = - case check_contract(Contract, Sig, Opaques) of - {error, invalid_contract} -> - [invalid_contract_warning(MFA, WarningInfo, none, Contract, Sig, RecDict)|Acc]; - {error, {invalid_contract, {_ProblematicArgIdxs, _IsRangeProblematic} = ProblemDetails}} -> - [invalid_contract_warning(MFA, WarningInfo, ProblemDetails, Contract, Sig, RecDict)|Acc]; - {error, {opaque_mismatch, T2}} -> - W = contract_opaque_warning(MFA, WarningInfo, T2, Sig, RecDict), - [W|Acc]; - {error, {overlapping_contract, []}} -> - [overlapping_contract_warning(MFA, WarningInfo)|Acc]; - {range_warnings, Errors} -> + case check_contract(Contract, Sig, M) of + {error, invalid_contract} -> + [invalid_contract_warning(MFA, WarningInfo, none, Contract, Sig, RecDict)|Acc]; + {error, {invalid_contract, {_ProblematicArgIdxs, _IsRangeProblematic} = ProblemDetails}} -> + [invalid_contract_warning(MFA, WarningInfo, ProblemDetails, Contract, Sig, RecDict)|Acc]; + {error, {overlapping_contract, []}} -> + [overlapping_contract_warning(MFA, WarningInfo)|Acc]; + {error, {opaque_mismatch, Offender}} -> + [contract_opaque_warning(MFA, WarningInfo, Offender, Sig, RecDict)|Acc]; + {range_warnings, Errors} -> Fun = fun({error, {extra_range, ExtraRanges, STRange}}, Acc0) -> Warn = @@ -857,7 +842,7 @@ get_invalid_contract_warnings_funs([{MFA, {FileLocation, Contract, _Xtra}}|Left] MFA, File, RecDict) of {ok, NoRemoteType} -> CRet = erl_types:t_fun_range(NoRemoteType), - is_subtype(ExtraRanges, CRet, Opaques); + is_subtype(ExtraRanges, CRet); unsupported -> true end, @@ -879,32 +864,37 @@ get_invalid_contract_warnings_funs([{MFA, {FileLocation, Contract, _Xtra}}|Left] {M, F, A} = MFA, CSig0 = get_contract_signature(Contract), CSig = erl_types:subst_all_vars_to_any(CSig0), - case erl_bif_types:is_known(M, F, A) of + + %% erlang:raise/3 has an inconsistent contract by design, which + %% becomes invalid when testing its defined contract against the + %% one in erl_bif_types. Hence, we explicitly ignore it. + case (MFA =/= {erlang, raise, 3} andalso + erl_bif_types:is_known(M, F, A)) of true -> %% This is strictly for contracts of functions also in %% erl_bif_types BifArgs = erl_bif_types:arg_types(M, F, A), BifRet = erl_bif_types:type(M, F, A), BifSig = erl_types:t_fun(BifArgs, BifRet), - case check_contract(Contract, BifSig, Opaques) of + case check_contract(Contract, BifSig, M) of {error, _} -> [invalid_contract_warning(MFA, WarningInfo, none, Contract, BifSig, RecDict) |Acc]; {range_warnings, _} -> picky_contract_check(CSig, BifSig, MFA, WarningInfo, - Contract, RecDict, Opaques, Acc); + Contract, RecDict, Acc); ok -> picky_contract_check(CSig, BifSig, MFA, WarningInfo, - Contract, RecDict, Opaques, Acc) + Contract, RecDict, Acc) end; false -> picky_contract_check(CSig, Sig, MFA, WarningInfo, Contract, - RecDict, Opaques, Acc) + RecDict, Acc) end end, - get_invalid_contract_warnings_funs(Left, Plt, RecDict, Opaques, NewAcc) + get_invalid_contract_warnings_funs(Left, Plt, RecDict, NewAcc) end; -get_invalid_contract_warnings_funs([], _Plt, _RecDict, _Opaques, Acc) -> +get_invalid_contract_warnings_funs([], _Plt, _RecDict, Acc) -> Acc. invalid_contract_warning({M, F, A}, WarningInfo, ProblemDetails, Contract, SuccType, RecDict) -> @@ -934,7 +924,7 @@ missing_range_warning({M, F, A}, WarningInfo, ExtraRanges, CRange) -> {missing_range, [M, F, A, ERangesStr, CRangeStr]}}. picky_contract_check(CSig0, Sig0, MFA, WarningInfo, Contract, RecDict, - Opaques, Acc) -> + Acc) -> CSig = erl_types:t_abstract_records(CSig0, RecDict), Sig = erl_types:t_abstract_records(Sig0, RecDict), case erl_types:t_is_equal(CSig, Sig) of @@ -945,7 +935,7 @@ picky_contract_check(CSig0, Sig0, MFA, WarningInfo, Contract, RecDict, true -> Acc; false -> case extra_contract_warning(MFA, WarningInfo, Contract, - CSig0, Sig0, RecDict, Opaques) of + CSig0, Sig0, RecDict) of no_warning -> Acc; {warning, Warning} -> [Warning|Acc] end @@ -953,10 +943,10 @@ picky_contract_check(CSig0, Sig0, MFA, WarningInfo, Contract, RecDict, end. extra_contract_warning(MFA, WarningInfo, Contract, CSig, Sig, - RecDict, Opaques) -> + RecDict) -> {File, _, _} = WarningInfo, {IsRemoteTypesRelated, SubtypeRelation} = - is_remote_types_related(Contract, CSig, Sig, MFA, File, RecDict, Opaques), + is_remote_types_related(Contract, CSig, Sig, MFA, File, RecDict), case IsRemoteTypesRelated of true -> no_warning; @@ -979,17 +969,17 @@ extra_contract_warning(MFA, WarningInfo, Contract, CSig, Sig, {warning, {Tag, WarningInfo, Msg}} end. -is_remote_types_related(Contract, CSig, Sig, MFA, File, RecDict, Opaques) -> - case is_subtype(CSig, Sig, Opaques) of +is_remote_types_related(Contract, CSig, Sig, MFA, File, RecDict) -> + case is_subtype(CSig, Sig) of true -> {false, contract_is_subtype}; false -> - case is_subtype(Sig, CSig, Opaques) of + case is_subtype(Sig, CSig) of true -> case t_from_forms_without_remote(Contract#contract.forms, MFA, File, RecDict) of {ok, NoRemoteTypeSig} -> - case blame_remote(CSig, NoRemoteTypeSig, Sig, Opaques) of + case blame_remote(CSig, NoRemoteTypeSig, Sig) of true -> {true, neither}; false -> @@ -1014,36 +1004,36 @@ t_from_forms_without_remote(_Forms, _MFA, _File, _RecDict) -> %% Lots of forms unsupported. -blame_remote(ContractSig, NoRemoteContractSig, Sig, Opaques) -> +blame_remote(ContractSig, NoRemoteContractSig, Sig) -> CArgs = erl_types:t_fun_args(ContractSig), CRange = erl_types:t_fun_range(ContractSig), NRArgs = erl_types:t_fun_args(NoRemoteContractSig), NRRange = erl_types:t_fun_range(NoRemoteContractSig), SArgs = erl_types:t_fun_args(Sig), SRange = erl_types:t_fun_range(Sig), - blame_remote_list([CRange|CArgs], [NRRange|NRArgs], [SRange|SArgs], Opaques). + blame_remote_list([CRange|CArgs], [NRRange|NRArgs], [SRange|SArgs]). -blame_remote_list([], [], [], _Opaques) -> +blame_remote_list([], [], []) -> true; -blame_remote_list([CArg|CArgs], [NRArg|NRArgs], [SArg|SArgs], Opaques) -> +blame_remote_list([CArg|CArgs], [NRArg|NRArgs], [SArg|SArgs]) -> case erl_types:t_is_equal(CArg, NRArg) of true -> case not erl_types:t_is_equal(CArg, SArg) of true -> false; - false -> blame_remote_list(CArgs, NRArgs, SArgs, Opaques) + false -> blame_remote_list(CArgs, NRArgs, SArgs) end; false -> - case is_subtype(SArg, NRArg, Opaques) - andalso not is_subtype(NRArg, SArg, Opaques) of + case is_subtype(SArg, NRArg) + andalso not is_subtype(NRArg, SArg) of true -> false; - false -> blame_remote_list(CArgs, NRArgs, SArgs, Opaques) + false -> blame_remote_list(CArgs, NRArgs, SArgs) end end. %% As erl_types:t_is_subtype/2 but without looking into opaque types that %% aren't known to us. -is_subtype(T1, T2, Opaques) -> - Inf = erl_types:t_inf(T1, T2, Opaques), +is_subtype(T1, T2) -> + Inf = erl_types:t_inf(T1, T2), erl_types:t_is_equal(T1, Inf). -spec constraint_form_to_remote_modules(Constraint :: term()) -> [module()]. diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl index 37a049566ff5..b95751e3450c 100644 --- a/lib/dialyzer/src/dialyzer_coordinator.erl +++ b/lib/dialyzer/src/dialyzer_coordinator.erl @@ -157,6 +157,7 @@ wait_for_success_typings(Labels, {_Collector, _Regulator, JobLabelsToPid}) -> %%-------------------------------------------------------------------- %% Local functions. +-dialyzer({no_opaque_union, [spawn_jobs/4]}). spawn_jobs(Mode, Jobs, InitData, Timing) -> Collector = self(), Regulator = spawn_regulator(), @@ -215,6 +216,7 @@ job_fun(JobLabelsToPid, Mode, InitData, Coordinator) -> ok end. +-dialyzer({no_opaque_union, [collect_result/1]}). collect_result(#state{mode = Mode, active = Active, result = Result, next_label = NextLabel, init_data = InitData, jobs = JobsLeft, job_fun = JobFun, @@ -258,6 +260,7 @@ collect_result(#state{mode = Mode, active = Active, result = Result, end end. +-dialyzer({no_opaque_union, [update_result/5]}). update_result(Mode, InitData, Job, Data, Result) -> if Mode =:= 'compile' -> diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index 91879198b1c8..46bb23ab4d91 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -28,34 +28,33 @@ -include("dialyzer.hrl"). -import(erl_types, - [t_inf/2, t_inf/3, t_inf_lists/2, t_inf_lists/3, - t_is_equal/2, t_is_subtype/2, t_subtract/2, + [t_inf/2, t_inf_lists/2, + t_is_equal/2, t_subtract/2, t_sup/1, t_sup/2]). -import(erl_types, - [any_none/1, t_any/0, t_atom/0, t_atom/1, t_atom_vals/1, t_atom_vals/2, + [any_none/1, t_any/0, t_atom/0, t_atom/1, t_atom_vals/1, t_binary/0, t_boolean/0, t_bitstr/0, t_bitstr/2, t_bitstr_concat/1, t_bitstr_match/2, - t_cons/0, t_cons/2, t_cons_hd/2, t_cons_tl/2, - t_contains_opaque/2, - t_find_opaque_mismatch/3, t_float/0, t_from_range/2, t_from_term/1, - t_fun/0, t_fun/2, t_fun_args/1, t_fun_args/2, t_fun_range/1, - t_fun_range/2, t_integer/0, t_integers/1, - t_is_any/1, t_is_atom/1, t_is_atom/2, t_is_any_atom/3, - t_is_boolean/2, - t_is_integer/2, t_is_list/1, - t_is_nil/2, t_is_none/1, t_is_impossible/1, - t_is_number/2, t_is_reference/2, t_is_pid/2, t_is_port/2, + t_cons/0, t_cons/2, t_cons_hd/1, t_cons_tl/1, + t_float/0, t_from_range/2, t_from_term/1, + t_fun/0, t_fun/2, t_fun_args/1, t_fun_range/1, + t_integer/0, t_integers/1, + t_is_any/1, t_is_atom/1, t_is_any_atom/2, + t_is_boolean/1, + t_is_integer/1, t_is_list/1, + t_is_nil/1, t_is_none/1, t_is_impossible/1, + t_is_number/1, t_is_reference/1, t_is_pid/1, t_is_port/1, t_is_unit/1, - t_limit/2, t_list/0, t_list_elements/2, + t_limit/2, t_list/0, t_list_elements/1, t_maybe_improper_list/0, t_module/0, - t_none/0, t_non_neg_integer/0, t_number/0, t_number_vals/2, + t_none/0, t_non_neg_integer/0, t_number/0, t_number_vals/1, t_pid/0, t_port/0, t_product/1, t_reference/0, t_to_string/2, t_to_tlist/1, - t_tuple/0, t_tuple/1, t_tuple_args/1, t_tuple_args/2, - t_tuple_subtypes/2, - t_unit/0, t_unopaque/2, - t_map/0, t_map/1, t_is_singleton/2 + t_tuple/0, t_tuple/1, t_tuple_args/1, + t_tuple_subtypes/1, + t_unit/0, + t_map/0, t_map/1, t_is_singleton/1 ]). %%-define(DEBUG, true). @@ -87,7 +86,6 @@ fun_homes :: dict:dict(label(), mfa()), reachable_funs :: sets:set(label()), plt :: dialyzer_plt:plt(), - opaques :: [type()], records = dict:new() :: types(), tree_map :: dict:dict(label(), cerl:cerl()), warning_mode = false :: boolean(), @@ -353,8 +351,7 @@ handle_apply(Tree, Map, State) -> Tree, Msg), {State3, Map2, t_none()}; false -> - NewArgs = t_inf_lists(ArgTypes, - t_fun_args(OpType1, 'universe')), + NewArgs = t_inf_lists(ArgTypes, t_fun_args(OpType1)), case any_none(NewArgs) of true -> EnumNewArgs = lists:zip(lists:seq(1, length(NewArgs)), @@ -371,7 +368,7 @@ handle_apply(Tree, Map, State) -> {State3, enter_type(Op, OpType1, Map2), t_none()}; false -> Map3 = enter_type_lists(Args, NewArgs, Map2), - Range0 = t_fun_range(OpType1, 'universe'), + Range0 = t_fun_range(OpType1), Range = case t_is_unit(Range0) of true -> t_none(); @@ -408,12 +405,12 @@ handle_apply_or_call([{local, external}|Left], Args, ArgTypes, Map, Tree, State, none -> one; _ -> many end, - NewWarns = {NewHowMany, []}, + NewWarns = {NewHowMany, []}, handle_apply_or_call(Left, Args, ArgTypes, Map, Tree, State, ArgTypes, t_any(), true, NewWarns); handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left], Args, ArgTypes, Map, Tree, - #state{opaques = Opaques} = State, + State0, AccArgTypes, AccRet, HadExternal, Warns) -> Any = t_any(), AnyArgs = [Any || _ <- Args], @@ -435,7 +432,7 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left], BArgs = erl_bif_types:arg_types(M, F, A), BRange = fun(FunArgs) -> - erl_bif_types:type(M, F, A, FunArgs, Opaques) + erl_bif_types:type(M, F, A, FunArgs) end, {BArgs, BRange}; false -> @@ -450,22 +447,22 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left], end, ?debug("--------------------------------------------------------\n", []), - ?debug("Fun: ~tp\n", [state__lookup_name(Fun, State)]), - ?debug("Module ~p\n", [State#state.module]), + ?debug("Fun: ~tp\n", [state__lookup_name(Fun, State0)]), + ?debug("Module ~p\n", [State0#state.module]), ?debug("CArgs ~ts\n", [erl_types:t_to_string(t_product(CArgs))]), ?debug("ArgTypes ~ts\n", [erl_types:t_to_string(t_product(ArgTypes))]), ?debug("BifArgs ~tp\n", [erl_types:t_to_string(t_product(BifArgs))]), - NewArgsSig = t_inf_lists(SigArgs, ArgTypes, Opaques), + NewArgsSig = t_inf_lists(SigArgs, ArgTypes), ?debug("SigArgs ~ts\n", [erl_types:t_to_string(t_product(SigArgs))]), ?debug("NewArgsSig: ~ts\n", [erl_types:t_to_string(t_product(NewArgsSig))]), - NewArgsContract = t_inf_lists(CArgs, ArgTypes, Opaques), + NewArgsContract = t_inf_lists(CArgs, ArgTypes), ?debug("NewArgsContract: ~ts\n", [erl_types:t_to_string(t_product(NewArgsContract))]), - NewArgsBif = t_inf_lists(BifArgs, ArgTypes, Opaques), + NewArgsBif = t_inf_lists(BifArgs, ArgTypes), ?debug("NewArgsBif: ~ts\n", [erl_types:t_to_string(t_product(NewArgsBif))]), NewArgTypes0 = t_inf_lists(NewArgsSig, NewArgsContract), - NewArgTypes = t_inf_lists(NewArgTypes0, NewArgsBif, Opaques), + NewArgTypes = t_inf_lists(NewArgTypes0, NewArgsBif), ?debug("NewArgTypes ~ts\n", [erl_types:t_to_string(t_product(NewArgTypes))]), ?debug("\n", []), @@ -487,6 +484,10 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left], ?debug("FailedConj: ~p~n", [FailedConj]), ?debug("IsFailBif: ~p~n", [IsFailBif]), ?debug("IsFailSig: ~p~n", [IsFailSig]), + + State = opacity_conflicts(ArgTypes, t_inf_lists(CArgs, SigArgs), + Args, Tree, Fun, State0), + State2 = case FailedConj andalso not (IsFailBif orelse IsFailSig) of true -> @@ -513,26 +514,16 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left], FailReason = apply_fail_reason(FailedSig, FailedBif, FailedContract), Msg = get_apply_fail_msg(Fun, Args, ArgTypes, NewArgTypes, InfSig, - Contr, CArgs, State, FailReason, Opaques), + Contr, CArgs, State, FailReason), WarnType = case Msg of {call, _} -> ?WARN_FAILING_CALL; - {apply, _} -> ?WARN_FAILING_CALL; - {call_with_opaque, _} -> ?WARN_OPAQUE; - {call_without_opaque, _} -> ?WARN_OPAQUE; - {opaque_type_test, _} -> ?WARN_OPAQUE + {apply, _} -> ?WARN_FAILING_CALL end, LocTree = case Msg of {call, [_M, _F, _ASs, ANs | _]} -> select_arg(ANs, Args, Tree); {apply, [_ASs, ANs | _]} -> - select_arg(ANs, Args, Tree); - {call_with_opaque, [_M, _F, _ASs, ANs, _EAs_]} -> - select_arg(ANs, Args, Tree); - {call_without_opaque, - [_M, _F, _ASs, [{N, _T, _TS} | _]]} -> - select_arg([N], Args, Tree); - {opaque_type_test, _} -> - Tree + select_arg(ANs, Args, Tree) end, Frc = {erlang, is_record, 3} =:= state__lookup_name(Fun, State), state__add_warning(State, WarnType, LocTree, Msg, Frc) @@ -591,6 +582,49 @@ handle_apply_or_call([], Args, _ArgTypes, Map, _Tree, State, {had_external, State1} end. +opacity_conflicts([], [], _Args, _Tree, _Fun, State0) -> + State0; +opacity_conflicts(GivenTypes, ExpectedTypes, Args, Tree, Fun, State0) -> + {Reason, Conflicts} = + opacity_conflicts_1(GivenTypes, ExpectedTypes, State0, 1, none, []), + maybe + [{N, _, _} | _] ?= Conflicts, + {Mod, Func, _A} ?= state__lookup_name(Fun, State0), + Description = case Reason of + expected_transparent -> call_with_opaque; + expected_opaque -> call_without_opaque + end, + state__add_warning(State0, + ?WARN_OPAQUE, + select_arg([N], Args, Tree), + {Description, + [Mod, + Func, + format_args(Args, GivenTypes, State0), + Conflicts, + ExpectedTypes]}) + else + _ -> State0 + end. + +opacity_conflicts_1([Given | GivenTypes], + [Expected | ExpectedTypes], + State, N, Reason, Acc0) -> + Conflict = erl_types:t_opacity_conflict(Given, Expected, State#state.module), + Acc = case Conflict of + expected_transparent -> + Acc0 ++ [{N, Given, format_type(Given, State)}]; + expected_opaque -> + Acc0 ++ [{N, Expected, format_type(Expected, State)}]; + none -> + Acc0 + end, + true = expected_opaque < none, %Assertion. + opacity_conflicts_1(GivenTypes, ExpectedTypes, State, + N + 1, min(Reason, Conflict), Acc); +opacity_conflicts_1([], [], _State, _N, Reason, Acc) -> + {Reason, Acc}. + apply_fail_reason(FailedSig, FailedBif, FailedContract) -> if (FailedSig orelse FailedBif) andalso (not FailedContract) -> only_sig; @@ -599,7 +633,7 @@ apply_fail_reason(FailedSig, FailedBif, FailedContract) -> end. get_apply_fail_msg(Fun, Args, ArgTypes, NewArgTypes, - Sig, Contract, ContrArgs, State, FailReason, Opaques) -> + Sig, Contract, _ContrArgs, State, FailReason) -> ArgStrings = format_args(Args, ArgTypes, State), ContractInfo = case Contract of @@ -611,52 +645,12 @@ get_apply_fail_msg(Fun, Args, ArgTypes, NewArgTypes, EnumArgTypes = lists:zip(lists:seq(1, length(NewArgTypes)), NewArgTypes), ArgNs = [Arg || {Arg, Type} <- EnumArgTypes, t_is_none(Type)], case state__lookup_name(Fun, State) of - {M, F, A} -> - case is_opaque_type_test_problem(Fun, Args, NewArgTypes, State) of - {yes, Arg, ArgType} -> - {opaque_type_test, [atom_to_list(F), ArgStrings, - format_arg(Arg), format_type(ArgType, State)]}; - no -> - SigArgs = t_fun_args(Sig), - BadOpaque = - opaque_problems([SigArgs, ContrArgs], ArgTypes, Opaques, ArgNs), - %% In fact *both* 'call_with_opaque' and - %% 'call_without_opaque' are possible. - case lists:keyfind(decl, 1, BadOpaque) of - {decl, BadArgs} -> - %% a structured term is used where an opaque is expected - ExpectedTriples = - case FailReason of - only_sig -> expected_arg_triples(BadArgs, SigArgs, State); - _ -> expected_arg_triples(BadArgs, ContrArgs, State) - end, - {call_without_opaque, [M, F, ArgStrings, ExpectedTriples]}; - false -> - case lists:keyfind(use, 1, BadOpaque) of - {use, BadArgs} -> - %% an opaque term is used where a structured term is expected - ExpectedArgs = - case FailReason of - only_sig -> SigArgs; - _ -> ContrArgs - end, - {call_with_opaque, [M, F, ArgStrings, BadArgs, ExpectedArgs]}; - false -> - case - erl_bif_types:opaque_args(M, F, A, ArgTypes, Opaques) - of - [] -> %% there is a structured term clash in some argument - {call, [M, F, ArgStrings, - ArgNs, FailReason, - format_sig_args(Sig, State), - format_type(t_fun_range(Sig), State), - ContractInfo]}; - Ns -> - {call_with_opaque, [M, F, ArgStrings, Ns, ContrArgs]} - end - end - end - end; + {M, F, _A} -> + {call, [M, F, ArgStrings, + ArgNs, FailReason, + format_sig_args(Sig, State), + format_type(t_fun_range(Sig), State), + ContractInfo]}; Label when is_integer(Label) -> {apply, [ArgStrings, ArgNs, FailReason, @@ -665,106 +659,48 @@ get_apply_fail_msg(Fun, Args, ArgTypes, NewArgTypes, ContractInfo]} end. -%% -> [{ElementI, [ArgN]}] where [ArgN] is a non-empty list of -%% arguments containing unknown opaque types and Element is 1 or 2. -opaque_problems(ContractOrSigList, ArgTypes, Opaques, ArgNs) -> - ArgElementList = find_unknown(ContractOrSigList, ArgTypes, Opaques, ArgNs), - F = fun(1) -> decl; (2) -> use end, - [{F(ElementI), lists:usort([ArgN || {ArgN, EI} <- ArgElementList, - EI =:= ElementI])} || - ElementI <- lists:usort([EI || {_, EI} <- ArgElementList])]. - -%% -> [{ArgN, ElementI}] where ElementI = 1 means there is an unknown -%% opaque type in argument ArgN of the the contract/signature, -%% and ElementI = 2 means that there is an unknown opaque type in -%% argument ArgN of the the (current) argument types. -find_unknown(ContractOrSigList, ArgTypes, Opaques, NoneArgNs) -> - ArgNs = lists:seq(1, length(ArgTypes)), - [{ArgN, ElementI} || - ContractOrSig <- ContractOrSigList, - {E1, E2, ArgN} <- lists:zip3(ContractOrSig, ArgTypes, ArgNs), - lists:member(ArgN, NoneArgNs), - ElementI <- erl_types:t_find_unknown_opaque(E1, E2, Opaques)]. - -is_opaque_type_test_problem(Fun, Args, ArgTypes, State) -> - case Fun of - {erlang, FN, 2} when FN =:= is_function -> - type_test_opaque_arg(Args, ArgTypes, State#state.opaques); - {erlang, FN, 1} -> - case t_is_any(type_test_type(FN, 1)) of - true -> - no; - false -> - type_test_opaque_arg(Args, ArgTypes, State#state.opaques) - end; - _ -> - no - end. - -type_test_opaque_arg([], [], _Opaques) -> - no; -type_test_opaque_arg([Arg|Args], [ArgType|ArgTypes], Opaques) -> - case erl_types:t_has_opaque_subtype(ArgType, Opaques) of - true -> {yes, Arg, ArgType}; - false -> type_test_opaque_arg(Args, ArgTypes, Opaques) - end. - -expected_arg_triples(ArgNs, ArgTypes, State) -> - [begin - Arg = lists:nth(N, ArgTypes), - {N, Arg, format_type(Arg, State)} - end || N <- ArgNs]. -add_bif_warnings({erlang, Op, 2}, [T1, T2] = Ts, Tree, State) +add_bif_warnings({erlang, Op, 2}, [T1, T2], Tree, State) when Op =:= '=:='; Op =:= '==' -> - Opaques = State#state.opaques, - Inf = t_inf(T1, T2, Opaques), - case - t_is_none(Inf) andalso (not any_none(Ts)) - andalso (not is_int_float_eq_comp(T1, Op, T2, Opaques)) - of - true -> - %% Give priority to opaque warning (as usual). - case erl_types:t_find_unknown_opaque(T1, T2, Opaques) of - [] -> - Args = comp_format_args([], T1, Op, T2, State), - state__add_warning(State, ?WARN_MATCHING, Tree, {exact_eq, Args}); - Ns -> - Args = comp_format_args(Ns, T1, Op, T2, State), - state__add_warning(State, ?WARN_OPAQUE, Tree, {opaque_eq, Args}) - end; - false -> - State - end; -add_bif_warnings({erlang, Op, 2}, [T1, T2] = Ts, Tree, State) + add_bif_warnings_1(Op, T1, T2, Tree, State); +add_bif_warnings({erlang, Op, 2}, [T1, T2], Tree, State) when Op =:= '=/='; Op =:= '/=' -> - Opaques = State#state.opaques, - case - (not any_none(Ts)) - andalso (not is_int_float_eq_comp(T1, Op, T2, Opaques)) - of - true -> - case erl_types:t_find_unknown_opaque(T1, T2, Opaques) of - [] -> State; - Ns -> - Args = comp_format_args(Ns, T1, Op, T2, State), - state__add_warning(State, ?WARN_OPAQUE, Tree, {opaque_neq, Args}) - end; - false -> - State - end; + add_bif_warnings_1(Op, T1, T2, Tree, State); add_bif_warnings(_, _, _, State) -> State. -is_int_float_eq_comp(T1, Op, T2, Opaques) -> +add_bif_warnings_1(Op, T1, T2, Tree, State0) -> + State = case {any_none([T1, T2]), + erl_types:t_opacity_conflict(T1, T2, State0#state.module)} of + {false, expected_transparent} -> + state__add_warning(State0, ?WARN_OPAQUE, Tree, + {opaque_compare, + comp_format_args([], T2, Op, T1, State0)}); + {false, expected_opaque} -> + state__add_warning(State0, ?WARN_OPAQUE, Tree, + {opaque_compare, + comp_format_args([], T1, Op, T2, State0)}); + {_, _} -> + State0 + end, + case {t_is_none(t_inf(T1, T2)), not is_int_float_eq_comp(T1, Op, T2)} of + {true, true} -> + state__add_warning(State, ?WARN_MATCHING, Tree, + {exact_compare, + comp_format_args([], T1, Op, T2, State)}); + {_, _} -> + State + end. + +is_int_float_eq_comp(T1, Op, T2) -> (Op =:= '==' orelse Op =:= '/=') andalso - ((erl_types:t_is_float(T1, Opaques) - andalso t_is_integer(T2, Opaques)) orelse - (t_is_integer(T1, Opaques) - andalso erl_types:t_is_float(T2, Opaques))). + ((erl_types:t_is_float(T1) + andalso t_is_integer(T2)) orelse + (t_is_integer(T1) + andalso erl_types:t_is_float(T2))). -comp_format_args([1|_], T1, Op, T2, State) -> - [format_type(T2, State), Op, format_type(T1, State)]; +% comp_format_args([1|_], T1, Op, T2, State) -> +% [format_type(T2, State), Op, format_type(T1, State)]; comp_format_args(_, T1, Op, T2, State) -> [format_type(T1, State), Op, format_type(T2, State)]. @@ -826,28 +762,30 @@ handle_bitstr(Tree, Map, State) -> Offending, Msg), {State3, Map2, t_none()}; false -> - UnitVal = cerl:concrete(cerl:bitstr_unit(Tree)), - Opaques = State2#state.opaques, - NumberVals = t_number_vals(SizeType, Opaques), - {State3, Type} = - case t_contains_opaque(SizeType, Opaques) of - true -> - Msg = {opaque_size, [format_type(SizeType, State2), - format_cerl(Size)]}, - {state__add_warning(State2, ?WARN_OPAQUE, Size, Msg), - t_none()}; - false -> - case NumberVals of - [OneSize] -> {State2, t_bitstr(0, OneSize * UnitVal)}; - unknown -> {State2, t_bitstr()}; - _ -> - MinSize = erl_types:number_min(SizeType, Opaques), - {State2, t_bitstr(UnitVal, UnitVal * MinSize)} - end - end, - Map3 = enter_type_lists([Val, Size, Tree], - [ValType, SizeType, Type], Map2), - {State3, Map3, Type} + UnitVal = cerl:concrete(cerl:bitstr_unit(Tree)), + NumberVals = t_number_vals(SizeType), + State3 = case erl_types:t_opacity_conflict(SizeType, + ValType, + State#state.module) of + none -> + State2; + _ -> + Msg = {opaque_size, [format_type(SizeType, State2), + format_cerl(Size)]}, + state__add_warning(State2, ?WARN_OPAQUE, Size, Msg) + end, + {State4, Type} = case NumberVals of + [OneSize] -> + {State3, t_bitstr(0, OneSize * UnitVal)}; + unknown -> + {State3, t_bitstr()}; + _ -> + MinSize = erl_types:number_min(SizeType), + {State3, t_bitstr(UnitVal, UnitVal * MinSize)} + end, + Map3 = enter_type_lists([Val, Size, Tree], + [ValType, SizeType, Type], Map2), + {State4, Map3, Type} end end. @@ -857,15 +795,14 @@ handle_call(Tree, Map, State) -> M = cerl:call_module(Tree), F = cerl:call_name(Tree), Args = cerl:call_args(Tree), - MFAList = [M, F|Args], - {State1, Map1, [MType0, FType0|As]} = traverse_list(MFAList, Map, State), - Opaques = State#state.opaques, - MType = t_inf(t_module(), MType0, Opaques), - FType = t_inf(t_atom(), FType0, Opaques), + MFAList = [M, F | Args], + {State1, Map1, [MType0, FType0 | As]} = traverse_list(MFAList, Map, State), + MType = t_inf(t_module(), MType0), + FType = t_inf(t_atom(), FType0), Map2 = enter_type_lists([M, F], [MType, FType], Map1), MOpaque = t_is_none(MType) andalso (not t_is_none(MType0)), FOpaque = t_is_none(FType) andalso (not t_is_none(FType0)), - case any_none([MType, FType|As]) of + case any_none([MType, FType | As]) of true -> State2 = if @@ -951,15 +888,14 @@ handle_cons(Tree, Map, State) -> {State1, Map1, HdType} = traverse(Hd, Map, State), {State2, Map2, TlType} = traverse(Tl, Map1, State1), State3 = - case t_is_none(t_inf(TlType, t_list(), State2#state.opaques)) of + case t_is_none(t_inf(TlType, t_list())) of true -> - Msg = {improper_list_constr, [format_type(TlType, State2)]}, - state__add_warning(State2, ?WARN_NON_PROPER_LIST, Tree, Msg); + Msg = {improper_list_constr, [format_type(TlType, State2)]}, + state__add_warning(State2, ?WARN_NON_PROPER_LIST, Tree, Msg); false -> - State2 + State2 end, - Type = t_cons(HdType, TlType), - {State3, Map2, Type}. + {State3, Map2, t_cons(HdType, TlType)}. %%---------------------------------------- @@ -1001,9 +937,8 @@ handle_primop(Tree, Map, State) -> recv_wait_timeout -> [Arg] = cerl:primop_args(Tree), {State1, Map1, TimeoutType} = traverse(Arg, Map, State), - Opaques = State1#state.opaques, - case t_is_atom(TimeoutType, Opaques) andalso - t_atom_vals(TimeoutType, Opaques) =:= ['infinity'] of + case t_is_atom(TimeoutType) andalso + t_atom_vals(TimeoutType) =:= ['infinity'] of true -> {State1, Map1, t_boolean()}; false -> @@ -1036,23 +971,23 @@ handle_try(Tree, Map, State) -> Map2 = mark_as_fresh(Vars, Map1), {SuccState, SuccMap, SuccType} = case bind_pat_vars(Vars, TypeList, Map2, State1) of - {error, _, _, _, _} -> + {error, _, _, _} -> {State1, map__new(), t_none()}; - {SuccMap1, VarTypes} -> + {SuccMap1, VarTypes, State2} -> %% Try to bind the argument. Will only succeed if %% it is a simple structured term. SuccMap2 = case bind_pat_vars_reverse([Arg], [t_product(VarTypes)], - SuccMap1, State1) of - {error, _, _, _, _} -> SuccMap1; - {SM, _} -> SM + SuccMap1, State2) of + {error, _, _, _} -> SuccMap1; + {SM, _, _} -> SM end, - traverse(Body, SuccMap2, State1) + traverse(Body, SuccMap2, State2) end, ExcMap1 = mark_as_fresh(EVars, Map), - {State2, ExcMap2, HandlerType} = traverse(Handler, ExcMap1, SuccState), + {State3, ExcMap2, HandlerType} = traverse(Handler, ExcMap1, SuccState), TryType = t_sup(SuccType, HandlerType), - {State2, join_maps([ExcMap2, SuccMap], Map1), TryType} + {State3, join_maps([ExcMap2, SuccMap], Map1), TryType} end. %%---------------------------------------- @@ -1079,8 +1014,8 @@ handle_map(Tree,Map,State) -> of ResT -> BindT = t_map([{K, t_any()} || K <- ExactKeys]), case bind_pat_vars_reverse([Arg], [BindT], Map2, State2) of - {error, _, _, _, _} -> {State2, Map2, ResT}; - {Map3, _} -> {State2, Map3, ResT} + {error, _, _, _} -> {State2, Map2, ResT}; + {Map3, _, State3} -> {State3, Map3, ResT} end catch {none, MapType, {K,_}, KVTree} -> Msg2 = {map_update, [format_type(MapType, State2), @@ -1099,7 +1034,7 @@ traverse_map_pairs([Pair|Pairs], Map, State, ShadowKeys, PairAcc, KeyAcc) -> {State1, Map1, [K,V]} = traverse_list([Key,Val],Map,State), KeyAcc1 = case cerl:is_literal(Op) andalso cerl:concrete(Op) =:= exact andalso - t_is_singleton(K, State#state.opaques) andalso + t_is_singleton(K) andalso t_is_none(t_inf(ShadowKeys, K)) of true -> [K|KeyAcc]; false -> KeyAcc @@ -1125,7 +1060,7 @@ handle_tuple(Tree, Map, State) -> TagVal = cerl:atom_val(Tag), case state__lookup_record(TagVal, length(Left), State1) of error -> {State1, Map1, TupleType}; - {ok, RecType, FieldNames} -> + {ok, RecType, _FieldNames} -> InfTupleType = t_inf(RecType, TupleType), case t_is_none(InfTupleType) of true -> @@ -1140,7 +1075,7 @@ handle_tuple(Tree, Map, State) -> false -> case bind_pat_vars(Elements, t_tuple_args(RecType), Map1, State1) of - {error, bind, ErrorPat, ErrorType, _} -> + {error, bind, ErrorPat, ErrorType} -> Msg = {record_constr, [TagVal, format_patterns(ErrorPat), format_type(ErrorType, State1)]}, @@ -1148,27 +1083,15 @@ handle_tuple(Tree, Map, State) -> State2 = state__add_warning(State1, ?WARN_MATCHING, LocTree, Msg), {State2, Map1, t_none()}; - {error, opaque, ErrorPat, ErrorType, OpaqueType} -> - OpaqueStr = format_type(OpaqueType, State1), - Name = field_name(Elements, ErrorPat, FieldNames), - Msg = {opaque_match, - ["record field" ++ Name ++ - " declared to be of type " ++ - format_type(ErrorType, State1), - OpaqueStr, OpaqueStr]}, - LocTree = hd(ErrorPat), - State2 = state__add_warning(State1, ?WARN_OPAQUE, - LocTree, Msg), - {State2, Map1, t_none()}; - {error, record, ErrorPat, ErrorType, _} -> + {error, record, ErrorPat, ErrorType} -> Msg = {record_match, [format_patterns(ErrorPat), format_type(ErrorType, State1)]}, State2 = state__add_warning(State1, ?WARN_MATCHING, Tree, Msg), {State2, Map1, t_none()}; - {Map2, ETypes} -> - {State1, Map2, t_tuple(ETypes)} + {Map2, ETypes, State2} -> + {State2, Map2, t_tuple(ETypes)} end end end; @@ -1180,37 +1103,71 @@ handle_tuple(Tree, Map, State) -> end end. -field_name(Elements, ErrorPat, FieldNames) -> - try - [Pat] = ErrorPat, - Take = lists:takewhile(fun(X) -> X =/= Pat end, Elements), - " " ++ format_atom(lists:nth(length(Take), FieldNames)) - catch - _:_ -> "" - end. - %%---------------------------------------- %% Clauses %% -handle_clauses(Cs, Arg, ArgType, Map, State) -> - handle_clauses(Cs, Arg, ArgType, ArgType, Map, State, [], [], []). +handle_clauses(Cs, Arg, ArgType, Map, State0) -> + {MapList, State, Cases, CaseTypes, Warns0} = + handle_clauses(Cs, Arg, ArgType, ArgType, Map, State0, [], [], [], []), + Warns = opaque_clauses(Cases, CaseTypes, State) ++ Warns0, + {MapList, State, t_sup(CaseTypes), Warns}. -handle_clauses([C|Cs], Arg, ArgType, OrigArgType, MapIn, State, - CaseTypes, Acc, WarnAcc0) -> +handle_clauses([C | Cs], Arg, ArgType, OrigArgType, MapIn, State, + Cases0, CaseTypes0, Acc0, WarnAcc0) -> {State1, ClauseMap, BodyType, NewArgType, WarnAcc} = do_clause(C, Arg, ArgType, OrigArgType, MapIn, State, WarnAcc0), - case t_is_none(BodyType) of - true -> - handle_clauses(Cs, Arg, NewArgType, OrigArgType, MapIn, State1, - CaseTypes, Acc, WarnAcc); - false -> - handle_clauses(Cs, Arg, NewArgType, OrigArgType, MapIn, State1, - [BodyType|CaseTypes], [ClauseMap|Acc], WarnAcc) - end; + + {Cases, CaseTypes, Acc} = + case t_is_none(BodyType) of + true -> {Cases0, CaseTypes0, Acc0}; + false -> {[C | Cases0], [BodyType | CaseTypes0], [ClauseMap | Acc0]} + end, + + handle_clauses(Cs, Arg, NewArgType, OrigArgType, MapIn, State1, + Cases, CaseTypes, Acc, WarnAcc); handle_clauses([], _Arg, _ArgType, _OrigArgType, _MapIn, State, - CaseTypes, Acc, WarnAcc) -> - {lists:reverse(Acc), State, t_sup(CaseTypes), WarnAcc}. + Cases, CaseTypes, Acc, WarnAcc) -> + {lists:reverse(Acc), State, Cases, CaseTypes, WarnAcc}. + +opaque_clauses(Clauses, ClauseTypes, #state{module=Module}=State) -> + maybe + %% Only warn if the clause bodies have different return types (to any + %% degree no matter how small). + [_, _ | _] ?= lists:usort(ClauseTypes), + + FlatTypes = lists:flatmap(fun erl_types:t_elements/1, ClauseTypes), + + %% Do any of the clauses return opaques? + {value, Opaque} ?= lists:search(fun(Type) -> + erl_types:t_is_opaque(Type, Module) + end, FlatTypes), + + %% If yes, do all clauses return opaques from the same module? + %% + %% (This is a compromise to cut down on the number of warnings; modules + %% with multiple opaques can tell them apart more often than not, e.g. + %% `sofs:ordset() | sofs:a_set()`.) + OpaqueMod = erl_types:t_nominal_module(Opaque), + false ?= lists:all(fun(Type) -> + erl_types:t_is_any(Type) orelse + erl_types:t_is_impossible(Type) orelse + (erl_types:t_is_opaque(Type, Module) andalso + erl_types:t_nominal_module(Type) =:= OpaqueMod) + end, FlatTypes), + + %% If not, emit a warning that the clauses mix opaques and non-opaques. + [begin + Msg = {opaque_union, + [erl_types:t_is_opaque(Type, Module), + format_type(Type, State)]}, + clause_error_warning(Msg, false, Clause) + end || {Clause, Type} <- lists:zip(Clauses, ClauseTypes), + not erl_types:t_is_impossible(Type), + not erl_types:t_is_any(Type)] + else + _ -> [] + end. %% %% Process one clause. @@ -1230,7 +1187,7 @@ do_clause(C, Arg, ArgType, OrigArgType, Map, State, Warns) -> BindRes = case t_is_none(ArgType) of true -> - {error, maybe_covered, OrigArgType, ignore, ignore}; + {error, maybe_covered, OrigArgType, ignore}; false -> ArgTypes = get_arg_list(ArgType, Pats), bind_pat_vars(Pats, ArgTypes, Map1, State) @@ -1238,7 +1195,7 @@ do_clause(C, Arg, ArgType, OrigArgType, Map, State, Warns) -> %% Test whether the binding succeeded. case BindRes of - {error, _ErrorType, _NewPats, _Type, _OpaqueTerm} -> + {error, _ErrorType, _NewPats, _Type} -> ?debug("Failed binding pattern: ~ts\nto ~ts\n", [cerl_prettypr:format(C), format_type(ArgType, State)]), NewWarns = @@ -1250,14 +1207,14 @@ do_clause(C, Arg, ArgType, OrigArgType, Map, State, Warns) -> [Warn|Warns] end, {State, Map, t_none(), ArgType, NewWarns}; - {Map2, PatTypes} -> + {Map2, PatTypes, State1} -> %% Try to bind the argument. Will only succeed if %% it is a simple structured term. Map3 = case bind_pat_vars_reverse([Arg], [t_product(PatTypes)], - Map2, State) of - {error, _, _, _, _} -> Map2; - {NewMap, _} -> NewMap + Map2, State1) of + {error, _, _, _} -> Map2; + {NewMap, _, _} -> NewMap end, %% Subtract the matched type from the case argument. That will @@ -1268,35 +1225,35 @@ do_clause(C, Arg, ArgType, OrigArgType, Map, State, Warns) -> NewArgType = t_subtract(t_product(t_to_tlist(ArgType)), GenType), %% Now test whether the guard will succeed. - case bind_guard(Guard, Map3, State) of + case bind_guard(Guard, Map3, State1) of {error, Reason} -> - ?debug("Failed guard: ~ts\n", - [cerl_prettypr:format(C, [{hook, cerl_typean:pp_hook()}])]), - Warn = clause_guard_error(State, Reason, C, Pats, ArgType), - {State, Map, t_none(), NewArgType, [Warn|Warns]}; - Map4 -> + ?debug("Failed guard: ~p\n", + [C]), + Warn = clause_guard_error(State1, Reason, C, Pats, ArgType), + {State1, Map, t_none(), NewArgType, [Warn|Warns]}; + {Map4, State2} -> Body = cerl:clause_body(C), - {RetState, RetMap, BodyType} = traverse(Body, Map4, State), + {RetState, RetMap, BodyType} = traverse(Body, Map4, State2), {RetState, RetMap, BodyType, NewArgType, Warns} end end. -clause_error(State, Map, {error, maybe_covered, OrigArgType, _, _}, C, Pats, _) -> +clause_error(State, Map, {error, maybe_covered, OrigArgType, _}, C, Pats, _) -> %% This clause is covered by previous clauses, but it is possible %% that it would never match anyway. Find out by matching the %% original argument types of the case. OrigArgTypes = get_arg_list(OrigArgType, Pats), Msg = case bind_pat_vars(Pats, OrigArgTypes, Map, State) of - {_, _} -> + {_, _, State1} -> %% The pattern would match if it had not been covered. PatString = format_patterns(Pats), - ArgTypeString = format_type(OrigArgType, State), + ArgTypeString = format_type(OrigArgType, State1), {pattern_match_cov, [PatString, ArgTypeString]}; - {error, ErrorType, _, _, OpaqueTerm} -> + {error, ErrorType, _, _} -> %% This pattern can never match. failed_msg(State, ErrorType, Pats, OrigArgType, - Pats, OrigArgType, OpaqueTerm) + Pats, OrigArgType) end, Force = false, clause_error_warning(Msg, Force, C); @@ -1305,19 +1262,19 @@ clause_error(State, _Map, BindRes, C, Pats, ArgType) -> %% unless it is the default clause in a list comprehension %% without any filters. Force = not is_lc_default_clause(C), - {error, ErrorType, NewPats, NewType, OpaqueTerm} = BindRes, - Msg = failed_msg(State, ErrorType, Pats, ArgType, NewPats, NewType, OpaqueTerm), + {error, ErrorType, NewPats, NewType} = BindRes, + Msg = failed_msg(State, ErrorType, Pats, ArgType, NewPats, NewType), clause_error_warning(Msg, Force, C). -failed_msg(State, ErrorType, Pats, Type, NewPats, NewType, OpaqueTerm) -> +failed_msg(State, ErrorType, Pats, Type, NewPats, NewType) -> case ErrorType of bind -> {pattern_match, [format_patterns(Pats), format_type(Type, State)]}; record -> {record_match, [format_patterns(NewPats), format_type(NewType, State)]}; opaque -> - {opaque_match, [format_patterns(NewPats), format_type(NewType, State), - format_type(OpaqueTerm, State)]} + {opaque_match, [format_patterns(NewPats), format_type(Type, State), + format_type(NewType, State)]} end. clause_error_warning(Msg, Force, C) -> @@ -1329,6 +1286,7 @@ warn_type({Tag, _}) -> neg_guard_fail -> ?WARN_MATCHING; opaque_guard -> ?WARN_OPAQUE; opaque_match -> ?WARN_OPAQUE; + opaque_union -> ?WARN_OPAQUE_UNION; pattern_match -> ?WARN_MATCHING; pattern_match_cov -> ?WARN_MATCHING; record_match -> ?WARN_MATCHING @@ -1440,10 +1398,9 @@ bind_pat_vars(Pats, Types, Map, State, Rev) -> Error end. -do_bind_pat_vars([Pat|Pats], [Type|Types], Map, State, Rev, Acc) -> - ?debug("Binding pat: ~tw to ~ts\n", [cerl:type(Pat), format_type(Type, State)]), - Opaques = State#state.opaques, - {NewMap, TypeOut} = +do_bind_pat_vars([Pat|Pats], [Type|Types], Map, State0, Rev, Acc) -> + ?debug("Binding pat: ~tw to ~ts\n", [cerl:type(Pat), format_type(Type, State0)]), + {NewMap, TypeOut, State} = case cerl:type(Pat) of alias -> %% Map patterns are more allowing than the type of their literal. We @@ -1451,59 +1408,59 @@ do_bind_pat_vars([Pat|Pats], [Type|Types], Map, State, Rev, Acc) -> AliasPat = dialyzer_utils:refold_pattern(cerl:alias_pat(Pat)), Var = cerl:alias_var(Pat), Map1 = enter_subst(Var, AliasPat, Map), - {Map2, [PatType]} = do_bind_pat_vars([AliasPat], [Type], - Map1, State, Rev, []), - {enter_type(Var, PatType, Map2), PatType}; + {Map2, [PatType], State1} = do_bind_pat_vars([AliasPat], [Type], + Map1, State0, Rev, []), + {enter_type(Var, PatType, Map2), PatType, State1}; binary -> case Rev of true -> %% Cannot bind the binary if we are in reverse match since %% binary patterns and binary construction are not %% symmetric. - {Map, t_bitstr()}; + {Map, t_bitstr(), State0}; false -> - BinType = bind_checked_inf(Pat, t_bitstr(), Type, Opaques), + {BinType, State1} = bind_checked_inf(Pat, t_bitstr(), Type, State0), Segs = cerl:binary_segments(Pat), - {Map1, SegTypes} = bind_bin_segs(Segs, BinType, Map, State), - {Map1, t_bitstr_concat(SegTypes)} + {Map1, SegTypes, State2} = bind_bin_segs(Segs, BinType, Map, State1), + {Map1, t_bitstr_concat(SegTypes), State2} end; cons -> - Cons = bind_checked_inf(Pat, t_cons(), Type, Opaques), - {Map1, [HdType, TlType]} = + {Cons, State1} = bind_checked_inf(Pat, t_cons(), Type, State0), + {Map1, [HdType, TlType], State2} = do_bind_pat_vars([cerl:cons_hd(Pat), cerl:cons_tl(Pat)], - [t_cons_hd(Cons, Opaques), - t_cons_tl(Cons, Opaques)], - Map, State, Rev, []), - {Map1, t_cons(HdType, TlType)}; + [t_cons_hd(Cons), + t_cons_tl(Cons)], + Map, State1, Rev, []), + {Map1, t_cons(HdType, TlType), State2}; literal -> Pat0 = dialyzer_utils:refold_pattern(Pat), case cerl:is_literal(Pat0) of true -> - LiteralType = bind_checked_inf(Pat, literal_type(Pat), Type, Opaques), - {Map, LiteralType}; + {LiteralType, State1} = bind_checked_inf(Pat, literal_type(Pat), Type, State0), + {Map, LiteralType, State1}; false -> - {Map1, [PatType]} = do_bind_pat_vars([Pat0], [Type], Map, State, Rev, []), - {Map1, PatType} + {Map1, [PatType], State1} = do_bind_pat_vars([Pat0], [Type], Map, State0, Rev, []), + {Map1, PatType, State1} end; map -> - bind_map(Pat, Type, Map, State, Opaques, Rev); + bind_map(Pat, Type, Map, State0, Rev); tuple -> - bind_tuple(Pat, Type, Map, State, Opaques, Rev); + bind_tuple(Pat, Type, Map, State0, Rev); values -> Es = cerl:values_es(Pat), - {Map1, EsTypes} = do_bind_pat_vars(Es, t_to_tlist(Type), - Map, State, Rev, []), - {Map1, t_product(EsTypes)}; + {Map1, EsTypes, State1} = do_bind_pat_vars(Es, t_to_tlist(Type), + Map, State0, Rev, []), + {Map1, t_product(EsTypes), State1}; var -> VarType1 = - case state__lookup_type_for_letrec(Pat, State) of + case state__lookup_type_for_letrec(Pat, State0) of error -> lookup_type(Pat, Map); {ok, RecType} -> RecType end, %% Must do inf when binding args to pats. Vars in pats are fresh. - VarType2 = bind_checked_inf(Pat, VarType1, Type, Opaques), + {VarType2, State1} = bind_checked_inf(Pat, VarType1, Type, State0), Map1 = enter_type(Pat, VarType2, Map), - {Map1, VarType2}; + {Map1, VarType2, State1}; _Other -> %% Catch all is needed when binding args to pats ?debug("Failed match for ~p\n", [_Other]), @@ -1511,25 +1468,25 @@ do_bind_pat_vars([Pat|Pats], [Type|Types], Map, State, Rev, Acc) -> bind_error([Pat], Type, t_none(), bind) end, do_bind_pat_vars(Pats, Types, NewMap, State, Rev, [TypeOut|Acc]); -do_bind_pat_vars([], [], Map, _State, _Rev, Acc) -> - {Map, lists:reverse(Acc)}. +do_bind_pat_vars([], [], Map, State, _Rev, Acc) -> + {Map, lists:reverse(Acc), State}. -bind_map(Pat, Type, Map, State, Opaques, Rev) -> - MapT = bind_checked_inf(Pat, t_map(), Type, Opaques), +bind_map(Pat, Type, Map, State0, Rev) -> + {MapT, State1} = bind_checked_inf(Pat, t_map(), Type, State0), case Rev of %% TODO: Reverse matching (propagating a matched subset back to a value). true -> - {Map, MapT}; + {Map, MapT, State1}; false -> FoldFun = - fun(Pair, {MapAcc, ListAcc}) -> + fun(Pair, {MapAcc, ListAcc, StateAcc0}) -> %% Only exact (:=) can appear in patterns. exact = cerl:concrete(cerl:map_pair_op(Pair)), Key = cerl:map_pair_key(Pair), KeyType = case cerl:type(Key) of var -> - case state__lookup_type_for_letrec(Key, State) of + case state__lookup_type_for_letrec(Key, StateAcc0) of error -> lookup_type(Key, MapAcc); {ok, RecType} -> RecType end; @@ -1537,19 +1494,19 @@ bind_map(Pat, Type, Map, State, Opaques, Rev) -> literal_type(Key) end, Bind = erl_types:t_map_get(KeyType, MapT), - {MapAcc1, [ValType]} = + {MapAcc1, [ValType], StateAcc} = do_bind_pat_vars([cerl:map_pair_val(Pair)], - [Bind], MapAcc, State, Rev, []), - case t_is_singleton(KeyType, Opaques) of - true -> {MapAcc1, [{KeyType, ValType}|ListAcc]}; - false -> {MapAcc1, ListAcc} + [Bind], MapAcc, StateAcc0, Rev, []), + case t_is_singleton(KeyType) of + true -> {MapAcc1, [{KeyType, ValType}|ListAcc], StateAcc}; + false -> {MapAcc1, ListAcc, StateAcc} end end, - {Map1, Pairs} = lists:foldl(FoldFun, {Map, []}, cerl:map_es(Pat)), - {Map1, t_inf(MapT, t_map(Pairs))} + {Map1, Pairs, State2} = lists:foldl(FoldFun, {Map, [], State1}, cerl:map_es(Pat)), + {Map1, t_inf(MapT, t_map(Pairs)), State2} end. -bind_tuple(Pat, Type, Map, State, Opaques, Rev) -> +bind_tuple(Pat, Type, Map, State, Rev) -> Es = cerl:tuple_es(Pat), {IsTypedRecord, Prototype} = case Es of @@ -1572,34 +1529,41 @@ bind_tuple(Pat, Type, Map, State, Opaques, Rev) -> {false, t_tuple(length(Es))} end end, - Tuple = bind_checked_inf(Pat, Prototype, Type, Opaques), - SubTuples = t_tuple_subtypes(Tuple, Opaques), + {Tuple, State1} = bind_checked_inf(Pat, Prototype, Type, State), + SubTuples = t_tuple_subtypes(Tuple), MapJ = join_maps_begin(Map), %% Need to call the top function to get the try-catch wrapper. - Results = [bind_pat_vars(Es, t_tuple_args(SubTuple, Opaques), MapJ, State, Rev) || - SubTuple <- SubTuples], - case lists:keyfind(opaque, 2, Results) of - {error, opaque, _PatList, _Type, Opaque} -> - bind_error([Pat], Tuple, Opaque, opaque); - false -> - case [M || {M, _} <- Results, M =/= error] of - [] -> - case IsTypedRecord of - true -> bind_error([Pat], Tuple, Prototype, record); - false -> bind_error([Pat], Tuple, t_none(), bind) - end; - Maps -> - Map1 = join_maps_end(Maps, MapJ), - TupleType = t_sup([t_tuple(EsTypes) || - {M, EsTypes} <- Results, M =/= error]), - {Map1, TupleType} - end + {Results, State2} = lists:mapfoldl(fun(SubTuple,State0) -> + maybe + {M, P, NewState} ?= bind_pat_vars(Es, + t_tuple_args(SubTuple), + MapJ, + State0, + Rev), + {{M, P}, NewState} + else + Error -> {Error, State0} + end + end, + State1, SubTuples), + %%Results = lists:mapfoldl(fun(S) -> bind_pat_vars(Es, t_tuple_args(S), MapJ, State1, Rev) end, [], SubTuples), + case [M || {M, _} <- Results, M =/= error] of + [] -> + case IsTypedRecord of + true -> bind_error([Pat], Tuple, Prototype, record); + false -> bind_error([Pat], Tuple, t_none(), bind) + end; + Maps -> + Map1 = join_maps_end(Maps, MapJ), + TupleType = t_sup([t_tuple(EsTypes) || + {M, EsTypes} <- Results, M =/= error]), + {Map1, TupleType, State2} end. bind_bin_segs(BinSegs, BinType, Map, State) -> bind_bin_segs(BinSegs, BinType, [], Map, State). -bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) -> +bind_bin_segs([Seg|Segs], BinType, Acc, Map, State0) -> Val = cerl:bitstr_val(Seg), SegType = cerl:concrete(cerl:bitstr_type(Seg)), UnitVal = cerl:concrete(cerl:bitstr_unit(Seg)), @@ -1608,34 +1572,32 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) -> {literal, all} -> binary = SegType, [] = Segs, %Assertion. T = t_inf(t_bitstr(UnitVal, 0), BinType), - {Map1, [Type]} = do_bind_pat_vars([Val], [T], Map, - State, false, []), - Type1 = remove_local_opaque_types(Type, State#state.opaques), - bind_bin_segs(Segs, t_none(), [Type1|Acc], Map1, State); + {Map1, [Type], State1} = do_bind_pat_vars([Val], [T], Map, + State0, false, []), + bind_bin_segs(Segs, + t_bitstr(0, 0), + [erl_types:t_structural(Type) | Acc], + Map1, + State1); SizeType when SegType =:= utf8; SegType =:= utf16; SegType =:= utf32 -> {literal, undefined} = SizeType, %Assertion. - {Map1, [_]} = do_bind_pat_vars([Val], [t_integer()], - Map, State, false, []), + {Map1, [_], State1} = do_bind_pat_vars([Val], [t_integer()], + Map, State0, false, []), Type = t_binary(), bind_bin_segs(Segs, t_bitstr_match(Type, BinType), - [Type | Acc], Map1, State); + [Type | Acc], Map1, State1); {literal, N} when not is_integer(N); N < 0 -> %% Bogus literal size, fails in runtime. bind_error([Seg], BinType, t_none(), bind); _ -> - {Map1, [SizeType]} = do_bind_pat_vars([Size], [t_non_neg_integer()], - Map, State, false, []), - Opaques = State#state.opaques, - NumberVals = t_number_vals(SizeType, Opaques), - case t_contains_opaque(SizeType, Opaques) of - true -> bind_error([Seg], SizeType, t_none(), opaque); - false -> ok - end, + {Map1, [SizeType], State1} = do_bind_pat_vars([Size], [t_non_neg_integer()], + Map, State0, false, []), + NumberVals = t_number_vals(SizeType), Type = case NumberVals of [OneSize] -> t_bitstr(0, UnitVal * OneSize); _ -> % 'unknown' too - MinSize = erl_types:number_min(SizeType, Opaques), + MinSize = erl_types:number_min(SizeType), t_bitstr(UnitVal, UnitVal * MinSize) end, ValConstr = @@ -1663,15 +1625,15 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) -> end end end, - {Map2, [_]} = do_bind_pat_vars([Val], [ValConstr], Map1, State, false, []), + {Map2, [_], State2} = do_bind_pat_vars([Val], [ValConstr], Map1, State1, false, []), NewBinType = t_bitstr_match(Type, BinType), case t_is_none(NewBinType) of true -> bind_error([Seg], BinType, t_none(), bind); - false -> bind_bin_segs(Segs, NewBinType, [Type|Acc], Map2, State) + false -> bind_bin_segs(Segs, NewBinType, [Type|Acc], Map2, State2) end end; -bind_bin_segs([], _BinType, Acc, Map, _State) -> - {Map, lists:reverse(Acc)}. +bind_bin_segs([], _BinType, Acc, Map, State) -> + {Map, lists:reverse(Acc), State}. bitstr_bitsize_type(Size) -> case cerl:is_literal(Size) of @@ -1681,21 +1643,23 @@ bitstr_bitsize_type(Size) -> %% Return the infimum (meet) of ExpectedType and Type if it describes a %% possible value (not 'none' or 'unit'), otherwise raise a bind_error(). -bind_checked_inf(Pat, ExpectedType, Type, Opaques) -> - Inf = t_inf(ExpectedType, Type, Opaques), +bind_checked_inf(Pat, ExpectedType, Type, State0) -> + Inf = t_inf(ExpectedType, Type), + State = case erl_types:t_opacity_conflict(Type, + ExpectedType, + State0#state.module) of + none -> + State0; + _ -> + Msg = failed_msg(State0, opaque, Pat, ExpectedType, [Pat], Inf), + state__add_warning(State0, ?WARN_OPAQUE, Pat, Msg) + end, case t_is_impossible(Inf) of - true -> - case t_find_opaque_mismatch(ExpectedType, Type, Opaques) of - {ok, T1, T2} -> - bind_error([Pat], T1, T2, opaque); - error -> - bind_error([Pat], Type, Inf, bind) - end; - false -> - Inf + true -> {bind_error([Pat], Type, Inf, bind), State}; + false -> {Inf, State} end. -bind_error(Pats, Type, OpaqueType, Error0) -> +bind_error(Pats, Type, _Inf, Error0) -> Error = case {Error0, Pats} of {bind, [Pat]} -> case is_literal_record(Pat) of @@ -1704,38 +1668,38 @@ bind_error(Pats, Type, OpaqueType, Error0) -> end; _ -> Error0 end, - throw({error, Error, Pats, Type, OpaqueType}). + throw({error, Error, Pats, Type}). %%---------------------------------------- %% Guards %% -bind_guard(Guard, Map, State) -> - try bind_guard(Guard, Map, maps:new(), pos, State) of - {Map1, _Type} -> Map1 +bind_guard(Guard, Map, State0) -> + try bind_guard(Guard, Map, maps:new(), pos, State0) of + {Map1, _Type, State} -> {Map1, State} catch throw:{fail, Warning} -> {error, Warning}; throw:{fatal_fail, Warning} -> {error, Warning} end. -bind_guard(Guard, Map, Env, Eval, State) -> +bind_guard(Guard, Map, Env, Eval, State0) -> ?debug("Handling ~tw guard: ~ts\n", [Eval, cerl_prettypr:format(Guard, [{noann, true}])]), case cerl:type(Guard) of binary -> - {Map, t_binary()}; + {Map, t_binary(), State0}; 'case' -> Arg = cerl:case_arg(Guard), Clauses = cerl:case_clauses(Guard), - bind_guard_case_clauses(Arg, Clauses, Map, Env, Eval, State); + bind_guard_case_clauses(Arg, Clauses, Map, Env, Eval, State0); cons -> Hd = cerl:cons_hd(Guard), Tl = cerl:cons_tl(Guard), - {Map1, HdType} = bind_guard(Hd, Map, Env, dont_know, State), - {Map2, TlType} = bind_guard(Tl, Map1, Env, dont_know, State), - {Map2, t_cons(HdType, TlType)}; + {Map1, HdType, State1} = bind_guard(Hd, Map, Env, dont_know, State0), + {Map2, TlType, State2} = bind_guard(Tl, Map1, Env, dont_know, State1), + {Map2, t_cons(HdType, TlType), State2}; literal -> - {Map, literal_type(Guard)}; + {Map, literal_type(Guard), State0}; 'try' -> Arg = cerl:try_arg(Guard), [Var] = cerl:try_vars(Guard), @@ -1744,21 +1708,21 @@ bind_guard(Guard, Map, Env, Eval, State) -> Map1 = join_maps_begin(Map), Map2 = mark_as_fresh(EVars, Map1), %% Visit handler first so we know if it should be ignored - {{HandlerMap, HandlerType}, HandlerE} = - try {bind_guard(cerl:try_handler(Guard), Map2, Env, Eval, State), none} + {{HandlerMap, HandlerType, State1}, HandlerE} = + try {bind_guard(cerl:try_handler(Guard), Map2, Env, Eval, State0), none} catch throw:HE -> - {{Map2, t_none()}, HE} + {{Map2, t_none(), State0}, HE} end, BodyEnv = maps:put(get_label(Var), Arg, Env), case t_is_none(guard_eval_inf(Eval, HandlerType)) of %% Handler won't save us; pretend it does not exist - true -> bind_guard(cerl:try_body(Guard), Map, BodyEnv, Eval, State); + true -> bind_guard(cerl:try_body(Guard), Map, BodyEnv, Eval, State1); false -> - {{BodyMap, BodyType}, BodyE} = + {{BodyMap, BodyType, State2}, BodyE} = try {bind_guard(cerl:try_body(Guard), Map1, BodyEnv, - Eval, State), none} + Eval, State1), none} catch throw:BE -> - {{Map1, t_none()}, BE} + {{Map1, t_none(), State1}, BE} end, Map3 = join_maps_end([BodyMap, HandlerMap], Map1), case t_is_none(Sup = t_sup(BodyType, HandlerType)) of @@ -1777,122 +1741,174 @@ bind_guard(Guard, Map, Env, Eval, State) -> {_, {_,Rsn}} -> Rsn; _ -> none end}); - false -> {Map3, Sup} + false -> {Map3, Sup, State2} end end; tuple -> Es0 = cerl:tuple_es(Guard), - {Map1, Es} = bind_guard_list(Es0, Map, Env, dont_know, State), - {Map1, t_tuple(Es)}; + {Map1, Es, State1} = bind_guard_list(Es0, Map, Env, dont_know, State0), + {Map1, t_tuple(Es), State1}; map -> case Eval of - dont_know -> handle_guard_map(Guard, Map, Env, State); - _PosOrNeg -> {Map, t_none()} %% Map exprs do not produce bools + dont_know -> handle_guard_map(Guard, Map, Env, State0); + _PosOrNeg -> {Map, t_none(), State0} %% Map exprs do not produce bools end; 'let' -> Arg = cerl:let_arg(Guard), [Var] = cerl:let_vars(Guard), %%?debug("Storing: ~w\n", [Var]), NewEnv = maps:put(get_label(Var), Arg, Env), - bind_guard(cerl:let_body(Guard), Map, NewEnv, Eval, State); + bind_guard(cerl:let_body(Guard), Map, NewEnv, Eval, State0); values -> Es = cerl:values_es(Guard), - List = [bind_guard(V, Map, Env, dont_know, State) || V <- Es], - Type = t_product([T || {_, T} <- List]), - {Map, Type}; + {Types, State1} = lists:mapfoldl(fun(V, StateAcc0) -> + {_, Type, StateAcc0} = + bind_guard(V, + Map, + Env, + dont_know, + StateAcc0), + {Type, StateAcc0} + end, State0, Es), + {Map, t_product(Types), State1}; var -> ?debug("Looking for var(~w)...", [cerl_trees:get_label(Guard)]), GuardLabel = get_label(Guard), case Env of #{GuardLabel := Tree} -> ?debug("Found it\n", []), - {Map1, Type} = bind_guard(Tree, Map, Env, Eval, State), - {enter_type(Guard, Type, Map1), Type}; + {Map1, Type, State1} = bind_guard(Tree, Map, Env, Eval, State0), + {enter_type(Guard, Type, Map1), Type, State1}; #{} -> ?debug("Did not find it\n", []), Type = lookup_type(Guard, Map), Inf = guard_eval_inf(Eval, Type), - {enter_type(Guard, Inf, Map), Inf} + {enter_type(Guard, Inf, Map), Inf, State0} end; call -> - handle_guard_call(Guard, Map, Env, Eval, State) + handle_guard_call(Guard, Map, Env, Eval, State0) end. -handle_guard_call(Guard, Map, Env, Eval, State) -> - MFA = {cerl:atom_val(cerl:call_module(Guard)), - cerl:atom_val(cerl:call_name(Guard)), - cerl:call_arity(Guard)}, +handle_guard_call(Guard, Map, Env, Eval, State0) -> + MFA = {erlang = cerl:atom_val(cerl:call_module(Guard)), %Assertion. + cerl:atom_val(cerl:call_name(Guard)), + cerl:call_arity(Guard)}, + Args = cerl:call_args(Guard), + {_, ArgTypes, State1} = bind_guard_list(Args, Map, Env, dont_know, State0), + State2 = handle_opaque_guard_warnings(MFA, Guard, Args, ArgTypes, State1), case MFA of {erlang, is_function, 2} -> - handle_guard_is_function(Guard, Map, Env, Eval, State); + {_,_,_}=handle_guard_is_function(Guard, Map, Env, Eval, State2); {erlang, F, 3} when F =:= internal_is_record; F =:= is_record -> - handle_guard_is_record(Guard, Map, Env, Eval, State); + {_,_,_}=handle_guard_is_record(Guard, Map, Env, Eval, State2); {erlang, '=:=', 2} -> - handle_guard_eqeq(Guard, Map, Env, Eval, State); + {_,_,_}=handle_guard_eqeq(Guard, Map, Env, Eval, State2); {erlang, '==', 2} -> - handle_guard_eq(Guard, Map, Env, Eval, State); + {_,_,_}=handle_guard_eq(Guard, Map, Env, Eval, State2); {erlang, 'and', 2} -> - handle_guard_and(Guard, Map, Env, Eval, State); + {_,_,_}=handle_guard_and(Guard, Map, Env, Eval, State2); {erlang, 'or', 2} -> - handle_guard_or(Guard, Map, Env, Eval, State); + {_,_,_}=handle_guard_or(Guard, Map, Env, Eval, State2); {erlang, 'not', 1} -> - handle_guard_not(Guard, Map, Env, Eval, State); + {_,_,_}=handle_guard_not(Guard, Map, Env, Eval, State2); {erlang, Comp, 2} when Comp =:= '<'; Comp =:= '=<'; Comp =:= '>'; Comp =:= '>=' -> - handle_guard_comp(Guard, Comp, Map, Env, Eval, State); + {_,_,_}=handle_guard_comp(Guard, Comp, Map, Env, Eval, State2); {erlang, F, A} -> TypeTestType = type_test_type(F, A), case t_is_any(TypeTestType) of true -> - handle_guard_gen_fun(MFA, Guard, Map, Env, Eval, State); + {_,_,_}=handle_guard_gen_fun(MFA, Guard, Map, Env, Eval, State2); false -> - handle_guard_type_test(Guard, TypeTestType, Map, Env, Eval, State) + {_,_,_}=handle_guard_type_test(Guard, TypeTestType, Map, Env, Eval, State2) end end. -handle_guard_gen_fun({M, F, A}, Guard, Map, Env, Eval, State) -> +handle_opaque_guard_warnings({erlang, Op, 2}=MFA, + Guard, + [_, _]=Args, + [LHS, RHS]=ArgTypes, + State) when Op =:= '=:='; + Op =:= '=/=' -> + %% To reduce noise, we tolerate equivalence tests between two opaques with + %% the same name (or any() specifically) as it doesn't leak any information + %% about their contents. + case ((erl_types:t_is_any(LHS) orelse erl_types:t_is_any(RHS)) orelse + (erl_types:t_is_opaque(LHS) andalso + erl_types:t_is_opaque(RHS) andalso + erl_types:t_is_same_opaque(LHS, RHS))) of + true -> State; + false -> handle_opaque_guard_warnings_1(MFA, Guard, Args, ArgTypes, State) + end; +handle_opaque_guard_warnings(MFA, Guard, Args, ArgTypes, State) -> + handle_opaque_guard_warnings_1(MFA, Guard, Args, ArgTypes, State). + +handle_opaque_guard_warnings_1(MFA, Guard, Args, ArgTypes, State) -> + Ns = [Arg || {Arg, Type} <- lists:enumerate(ArgTypes), + erl_types:t_is_opaque(Type, State#state.module)], + maybe + [_ | _] ?= Ns, + {erlang, Fname, _A} = MFA, + Msg = case is_infix_op(MFA) of + true -> + [ArgType1, ArgType2] = ArgTypes, + [Arg1, Arg2] = Args, + {opaque_guard, + [format_args_1([Arg1], [ArgType1], State), + atom_to_list(Fname), + format_args_1([Arg2], [ArgType2], State), + Ns]}; + false -> + {opaque_guard, + [Fname, format_args(Args, ArgTypes, State)]} + end, + state__add_warning(State, ?WARN_OPAQUE, Guard, Msg) + else + _ -> State + end. + +handle_guard_gen_fun({M, F, A}, Guard, Map, Env, Eval, State0) -> Args = cerl:call_args(Guard), - {Map1, As} = bind_guard_list(Args, Map, Env, dont_know, State), - Opaques = State#state.opaques, - BifRet = erl_bif_types:type(M, F, A, As, Opaques), + {Map1, As, State1} = bind_guard_list(Args, Map, Env, dont_know, State0), + BifRet = erl_bif_types:type(M, F, A, As), case t_is_none(BifRet) of true -> %% Is this an error-bif? case t_is_none(erl_bif_types:type(M, F, A)) of - true -> signal_guard_fail(Eval, Guard, As, State); - false -> signal_guard_fatal_fail(Eval, Guard, As, State) + true -> signal_guard_fail(Eval, Guard, As, State1); + false -> signal_guard_fatal_fail(Eval, Guard, As, State1) end; false -> BifArgs = bif_args(M, F, A), - Map2 = enter_type_lists(Args, t_inf_lists(BifArgs, As, Opaques), Map1), + Map2 = enter_type_lists(Args, t_inf_lists(BifArgs, As), Map1), Ret = guard_eval_inf(Eval, BifRet), case t_is_none(Ret) of true -> case Eval =:= pos of - true -> signal_guard_fail(Eval, Guard, As, State); + true -> signal_guard_fail(Eval, Guard, As, State1); false -> throw({fail, none}) end; - false -> {Map2, Ret} + false -> {Map2, Ret, State1} end end. -handle_guard_type_test(Guard, TypeTestType, Map, Env, Eval, State) -> +handle_guard_type_test(Guard, TypeTestType, Map, Env, Eval, State0) -> [Arg] = cerl:call_args(Guard), - {Map1, ArgType} = bind_guard(Arg, Map, Env, dont_know, State), - case bind_type_test(Eval, TypeTestType, ArgType, State) of + {Map1, ArgType, State1} = bind_guard(Arg, Map, Env, dont_know, State0), + case bind_type_test(Eval, TypeTestType, ArgType) of error -> - ?debug("Type test: ~w failed\n", [F]), - signal_guard_fail(Eval, Guard, [ArgType], State); + ?debug("Type test: ~w failed\n", [Guard]), + signal_guard_fail(Eval, Guard, [ArgType], State1); {ok, NewArgType, Ret} -> ?debug("Type test: ~w succeeded, NewType: ~ts, Ret: ~ts\n", - [F, t_to_string(NewArgType), t_to_string(Ret)]), - {enter_type(Arg, NewArgType, Map1), Ret} + [Guard, t_to_string(NewArgType), t_to_string(Ret)]), + {enter_type(Arg, NewArgType, Map1), Ret, State1} end. -bind_type_test(Eval, Type, ArgType, State) -> +bind_type_test(Eval, Type, ArgType) -> case Eval of pos -> - Inf = t_inf(Type, ArgType, State#state.opaques), + Inf = t_inf(Type, ArgType), case t_is_none(Inf) of true -> error; false -> {ok, Inf, t_atom(true)} @@ -1928,38 +1944,37 @@ type_test_type(TypeTest, 1) -> type_test_type(_, _) -> t_any(). -handle_guard_comp(Guard, Comp, Map, Env, Eval, State) -> +handle_guard_comp(Guard, Comp, Map, Env, Eval, State0) -> Args = cerl:call_args(Guard), [Arg1, Arg2] = Args, - {Map1, ArgTypes} = bind_guard_list(Args, Map, Env, dont_know, State), - Opaques = State#state.opaques, + {Map1, ArgTypes, State1} = bind_guard_list(Args, Map, Env, dont_know, State0), [Type1, Type2] = ArgTypes, - IsInt1 = t_is_integer(Type1, Opaques), - IsInt2 = t_is_integer(Type2, Opaques), + IsInt1 = t_is_integer(Type1), + IsInt2 = t_is_integer(Type2), case {type(Arg1), type(Arg2)} of {{literal, Lit1}, {literal, Lit2}} -> case erlang:Comp(cerl:concrete(Lit1), cerl:concrete(Lit2)) of - true when Eval =:= pos -> {Map, t_atom(true)}; - true when Eval =:= dont_know -> {Map, t_atom(true)}; - true when Eval =:= neg -> {Map, t_atom(true)}; + true when Eval =:= pos -> {Map, t_atom(true), State1}; + true when Eval =:= dont_know -> {Map, t_atom(true), State1}; + true when Eval =:= neg -> {Map, t_atom(true), State1}; false when Eval =:= pos -> - signal_guard_fail(Eval, Guard, ArgTypes, State); - false when Eval =:= dont_know -> {Map, t_atom(false)}; - false when Eval =:= neg -> {Map, t_atom(false)} + signal_guard_fail(Eval, Guard, ArgTypes, State1); + false when Eval =:= dont_know -> {Map, t_atom(false), State1}; + false when Eval =:= neg -> {Map, t_atom(false), State1} end; {{literal, Lit1}, var} when IsInt1, IsInt2, Eval =:= pos -> - case bind_comp_literal_var(Lit1, Arg2, Type2, Comp, Map1, Opaques) of - error -> signal_guard_fail(Eval, Guard, ArgTypes, State); - {ok, NewMap} -> {NewMap, t_atom(true)} + case bind_comp_literal_var(Lit1, Arg2, Type2, Comp, Map1) of + error -> signal_guard_fail(Eval, Guard, ArgTypes, State1); + {ok, NewMap} -> {NewMap, t_atom(true), State1} end; {var, {literal, Lit2}} when IsInt1, IsInt2, Eval =:= pos -> case bind_comp_literal_var(Lit2, Arg1, Type1, invert_comp(Comp), - Map1, Opaques) of - error -> signal_guard_fail(Eval, Guard, ArgTypes, State); - {ok, NewMap} -> {NewMap, t_atom(true)} + Map1) of + error -> signal_guard_fail(Eval, Guard, ArgTypes, State1); + {ok, NewMap} -> {NewMap, t_atom(true), State1} end; {_, _} -> - handle_guard_gen_fun({erlang, Comp, 2}, Guard, Map, Env, Eval, State) + handle_guard_gen_fun({erlang, Comp, 2}, Guard, Map, Env, Eval, State1) end. invert_comp('=<') -> '>='; @@ -1967,10 +1982,10 @@ invert_comp('<') -> '>'; invert_comp('>=') -> '=<'; invert_comp('>') -> '<'. -bind_comp_literal_var(Lit, Var, VarType, CompOp, Map, Opaques) -> +bind_comp_literal_var(Lit, Var, VarType, CompOp, Map) -> LitVal = cerl:concrete(Lit), NewVarType = - case t_number_vals(VarType, Opaques) of + case t_number_vals(VarType) of unknown -> Range = case CompOp of @@ -1979,7 +1994,7 @@ bind_comp_literal_var(Lit, Var, VarType, CompOp, Map, Opaques) -> '>=' -> t_from_range(neg_inf, LitVal); '>' -> t_from_range(neg_inf, LitVal - 1) end, - t_inf(Range, VarType, Opaques); + t_inf(Range, VarType); NumberVals -> NewNumberVals = [X || X <- NumberVals, erlang:CompOp(LitVal, X)], t_integers(NewNumberVals) @@ -1989,84 +2004,83 @@ bind_comp_literal_var(Lit, Var, VarType, CompOp, Map, Opaques) -> false -> {ok, enter_type(Var, NewVarType, Map)} end. -handle_guard_is_function(Guard, Map, Env, Eval, State) -> +handle_guard_is_function(Guard, Map, Env, Eval, State0) -> Args = cerl:call_args(Guard), - {Map1, ArgTypes0} = bind_guard_list(Args, Map, Env, dont_know, State), + {Map1, ArgTypes0, State1} = bind_guard_list(Args, Map, Env, dont_know, State0), [FunType0, ArityType0] = ArgTypes0, - Opaques = State#state.opaques, - ArityType = t_inf(ArityType0, t_integer(), Opaques), + ArityType = t_inf(ArityType0, t_integer()), case t_is_none(ArityType) of - true -> signal_guard_fail(Eval, Guard, ArgTypes0, State); + true -> signal_guard_fail(Eval, Guard, ArgTypes0, State1); false -> FunTypeConstr = - case t_number_vals(ArityType, State#state.opaques) of + case t_number_vals(ArityType) of unknown -> t_fun(); Vals -> t_sup([t_fun(lists:duplicate(X, t_any()), t_any()) || X <- Vals]) end, - FunType = t_inf(FunType0, FunTypeConstr, Opaques), + FunType = t_inf(FunType0, FunTypeConstr), case t_is_none(FunType) of true -> case Eval of - pos -> signal_guard_fail(Eval, Guard, ArgTypes0, State); - neg -> {Map1, t_atom(false)}; - dont_know -> {Map1, t_atom(false)} + pos -> signal_guard_fail(Eval, Guard, ArgTypes0, State1); + neg -> {Map1, t_atom(false), State1}; + dont_know -> {Map1, t_atom(false), State1} end; false -> case Eval of pos -> {enter_type_lists(Args, [FunType, ArityType], Map1), - t_atom(true)}; - neg -> {Map1, t_atom(false)}; - dont_know -> {Map1, t_boolean()} + t_atom(true), State1}; + neg -> {Map1, t_atom(false), State1}; + dont_know -> {Map1, t_boolean(), State1} end end end. -handle_guard_is_record(Guard, Map, Env, Eval, State) -> +handle_guard_is_record(Guard, Map, Env, Eval, State0) -> Args = cerl:call_args(Guard), [Rec, Tag0, Arity0] = Args, Tag = cerl:atom_val(Tag0), Arity = cerl:int_val(Arity0), - {Map1, RecType} = bind_guard(Rec, Map, Env, dont_know, State), + {Map1, RecType, State1} = bind_guard(Rec, Map, Env, dont_know, State0), ArityMin1 = Arity - 1, - Opaques = State#state.opaques, Tuple = t_tuple([t_atom(Tag)|lists:duplicate(ArityMin1, t_any())]), - case t_is_none(t_inf(Tuple, RecType, Opaques)) of + Inf = t_inf(Tuple, RecType), + State2 = case erl_types:t_opacity_conflict(RecType, + Tuple, + State1#state.module) of + none -> + State1; + _ -> + Msg = failed_msg(State1, opaque, Guard, Tuple, [Guard], Inf), + state__add_warning(State1, ?WARN_OPAQUE, Guard, Msg) + end, + case t_is_none(Inf) of true -> - case erl_types:t_has_opaque_subtype(RecType, Opaques) of - true -> - signal_guard_fail(Eval, Guard, - [RecType, t_from_term(Tag), - t_from_term(Arity)], - State); - false -> - case Eval of - pos -> signal_guard_fail(Eval, Guard, - [RecType, t_from_term(Tag), - t_from_term(Arity)], - State); - neg -> {Map1, t_atom(false)}; - dont_know -> {Map1, t_atom(false)} - end - end; + case Eval of + pos -> signal_guard_fail(Eval, Guard, + [RecType, t_from_term(Tag), + t_from_term(Arity)], + State2); + neg -> {Map1, t_atom(false), State2}; + dont_know -> {Map1, t_atom(false), State2} + end; false -> TupleType = - case state__lookup_record(Tag, ArityMin1, State) of + case state__lookup_record(Tag, ArityMin1, State2) of error -> Tuple; {ok, Prototype, _FieldNames} -> Prototype end, - Type = t_inf(TupleType, RecType, State#state.opaques), + Type = t_inf(TupleType, RecType), case t_is_none(Type) of true -> %% No special handling of opaque errors. - FArgs = "record " ++ format_type(RecType, State), - Msg = {record_matching, [FArgs, Tag]}, - throw({fail, {Guard, Msg}}); + FArgs = "record " ++ format_type(RecType, State2), + throw({fail, {Guard, {record_matching, [FArgs, Tag]}}}); false -> case Eval of - pos -> {enter_type(Rec, Type, Map1), t_atom(true)}; - neg -> {Map1, t_atom(false)}; - dont_know -> {Map1, t_boolean()} + pos -> {enter_type(Rec, Type, Map1), t_atom(true), State2}; + neg -> {Map1, t_atom(false), State2}; + dont_know -> {Map1, t_boolean(), State2} end end end. @@ -2078,17 +2092,17 @@ handle_guard_eq(Guard, Map, Env, Eval, State) -> case cerl:concrete(Lit1) =:= cerl:concrete(Lit2) of true -> if - Eval =:= pos -> {Map, t_atom(true)}; + Eval =:= pos -> {Map, t_atom(true), State}; Eval =:= neg -> ArgTypes = [t_from_term(cerl:concrete(Lit1)), t_from_term(cerl:concrete(Lit2))], signal_guard_fail(Eval, Guard, ArgTypes, State); - Eval =:= dont_know -> {Map, t_atom(true)} + Eval =:= dont_know -> {Map, t_atom(true), State} end; false -> if - Eval =:= neg -> {Map, t_atom(false)}; - Eval =:= dont_know -> {Map, t_atom(false)}; + Eval =:= neg -> {Map, t_atom(false), State}; + Eval =:= dont_know -> {Map, t_atom(false), State}; Eval =:= pos -> ArgTypes = [t_from_term(cerl:concrete(Lit1)), t_from_term(cerl:concrete(Lit2))], @@ -2118,22 +2132,19 @@ handle_guard_eq(Guard, Map, Env, Eval, State) -> end. bind_eq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) -> - {Map1, Type1} = bind_guard(Arg1, Map, Env, dont_know, State), - {Map2, Type2} = bind_guard(Arg2, Map1, Env, dont_know, State), - Opaques = State#state.opaques, + {Map1, Type1, State1} = bind_guard(Arg1, Map, Env, dont_know, State), + {Map2, Type2, State2} = bind_guard(Arg2, Map1, Env, dont_know, State1), case - t_is_nil(Type1, Opaques) orelse t_is_nil(Type2, Opaques) - orelse t_is_atom(Type1, Opaques) orelse t_is_atom(Type2, Opaques) + t_is_nil(Type1) orelse t_is_nil(Type2) + orelse t_is_atom(Type1) orelse t_is_atom(Type2) of - true -> bind_eqeq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State); + true -> bind_eqeq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State2); false -> - %% XXX. Is this test OK? - OpArgs = erl_types:t_find_unknown_opaque(Type1, Type2, Opaques), - case OpArgs =:= [] of - true -> - {Map2, guard_eval_inf(Eval, t_boolean())}; - false -> - signal_guard_fail(Eval, Guard, [Type1, Type2], State) + case erl_types:t_opacity_conflict(Type1, Type2, State2#state.module) of + none -> + {Map2, guard_eval_inf(Eval, t_boolean()), State2}; + _ -> + signal_guard_fail(Eval, Guard, [Type1, Type2], State2) end end. @@ -2148,12 +2159,12 @@ handle_guard_eqeq(Guard, Map, Env, Eval, State) -> ArgTypes = [t_from_term(cerl:concrete(Lit1)), t_from_term(cerl:concrete(Lit2))], signal_guard_fail(Eval, Guard, ArgTypes, State); - Eval =:= pos -> {Map, t_atom(true)}; - Eval =:= dont_know -> {Map, t_atom(true)} + Eval =:= pos -> {Map, t_atom(true), State}; + Eval =:= dont_know -> {Map, t_atom(true), State} end; false -> - if Eval =:= neg -> {Map, t_atom(false)}; - Eval =:= dont_know -> {Map, t_atom(false)}; + if Eval =:= neg -> {Map, t_atom(false), State}; + Eval =:= dont_know -> {Map, t_atom(false), State}; Eval =:= pos -> ArgTypes = [t_from_term(cerl:concrete(Lit1)), t_from_term(cerl:concrete(Lit2))], @@ -2168,25 +2179,18 @@ handle_guard_eqeq(Guard, Map, Env, Eval, State) -> bind_eqeq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) end. -bind_eqeq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) -> - {Map1, Type1} = bind_guard(Arg1, Map, Env, dont_know, State), - {Map2, Type2} = bind_guard(Arg2, Map1, Env, dont_know, State), +bind_eqeq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State0) -> + {Map1, Type1, State1} = bind_guard(Arg1, Map, Env, dont_know, State0), + {Map2, Type2, State2} = bind_guard(Arg2, Map1, Env, dont_know, State1), ?debug("Types are:~ts =:= ~ts\n", [t_to_string(Type1), t_to_string(Type2)]), - Opaques = State#state.opaques, - Inf = t_inf(Type1, Type2, Opaques), + Inf = t_inf(Type1, Type2), case t_is_none(Inf) of true -> - OpArgs = erl_types:t_find_unknown_opaque(Type1, Type2, Opaques), - case OpArgs =:= [] of - true -> - case Eval of - neg -> {Map2, t_atom(false)}; - dont_know -> {Map2, t_atom(false)}; - pos -> signal_guard_fail(Eval, Guard, [Type1, Type2], State) - end; - false -> - signal_guard_fail(Eval, Guard, [Type1, Type2], State) + case Eval of + neg -> {Map2, t_atom(false), State2}; + dont_know -> {Map2, t_atom(false), State2}; + pos -> signal_guard_fail(Eval, Guard, [Type1, Type2], State2) end; false -> case Eval of @@ -2195,92 +2199,90 @@ bind_eqeq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) -> {var, var} -> Map3 = enter_subst(Arg1, Arg2, Map2), Map4 = enter_type(Arg2, Inf, Map3), - {Map4, t_atom(true)}; + {Map4, t_atom(true), State2}; {var, _} -> Map3 = enter_type(Arg1, Inf, Map2), - {Map3, t_atom(true)}; + {Map3, t_atom(true), State2}; {_, var} -> Map3 = enter_type(Arg2, Inf, Map2), - {Map3, t_atom(true)}; + {Map3, t_atom(true), State2}; {_, _} -> - {Map2, t_atom(true)} + {Map2, t_atom(true), State2} end; neg -> - {Map2, t_atom(false)}; + {Map2, t_atom(false), State2}; dont_know -> - {Map2, t_boolean()} + {Map2, t_boolean(), State2} end end. -bind_eqeq_guard_lit_other(Guard, Arg1, Arg2, Map, Env, State) -> +bind_eqeq_guard_lit_other(Guard, Arg1, Arg2, Map, Env, State0) -> Eval = dont_know, - Opaques = State#state.opaques, case cerl:concrete(Arg1) of true -> - {_, Type} = MT = bind_guard(Arg2, Map, Env, pos, State), - case t_is_any_atom(true, Type, Opaques) of + {_, Type, State1} = MT = bind_guard(Arg2, Map, Env, pos, State0), + case t_is_any_atom(true, Type) of true -> MT; false -> - {_, Type0} = bind_guard(Arg2, Map, Env, Eval, State), - signal_guard_fail(Eval, Guard, [Type0, t_atom(true)], State) + {_, Type0, State2} = bind_guard(Arg2, Map, Env, Eval, State1), + signal_guard_fail(Eval, Guard, [Type0, t_atom(true)], State2) end; false -> - {Map1, Type} = bind_guard(Arg2, Map, Env, neg, State), - case t_is_any_atom(false, Type, Opaques) of - true -> {Map1, t_atom(true)}; + {Map1, Type, State1} = bind_guard(Arg2, Map, Env, neg, State0), + case t_is_any_atom(false, Type) of + true -> {Map1, t_atom(true), State1}; false -> - {_, Type0} = bind_guard(Arg2, Map, Env, Eval, State), - signal_guard_fail(Eval, Guard, [Type0, t_atom(false)], State) + {_, Type0, State2} = bind_guard(Arg2, Map, Env, Eval, State1), + signal_guard_fail(Eval, Guard, [Type0, t_atom(false)], State2) end; Term -> LitType = t_from_term(Term), - {Map1, Type} = bind_guard(Arg2, Map, Env, Eval, State), - case t_is_subtype(LitType, Type) of - false -> signal_guard_fail(Eval, Guard, [Type, LitType], State); - true -> - case cerl:is_c_var(Arg2) of - true -> {enter_type(Arg2, LitType, Map1), t_atom(true)}; - false -> {Map1, t_atom(true)} - end + {Map1, Type, State1} = bind_guard(Arg2, Map, Env, Eval, State0), + case t_is_none(t_inf(LitType, Type)) of + true -> signal_guard_fail(Eval, Guard, [Type, LitType], State1); + false -> + case cerl:is_c_var(Arg2) of + true -> {enter_type(Arg2, LitType, Map1), t_atom(true), State1}; + false -> {Map1, t_atom(true), State1} + end end end. -handle_guard_and(Guard, Map, Env, Eval, State) -> +handle_guard_and(Guard, Map, Env, Eval, State0) -> [Arg1, Arg2] = cerl:call_args(Guard), - Opaques = State#state.opaques, case Eval of pos -> - {Map1, Type1} = bind_guard(Arg1, Map, Env, Eval, State), - case t_is_any_atom(true, Type1, Opaques) of - false -> signal_guard_fail(Eval, Guard, [Type1, t_any()], State); + {Map1, Type1, State1} = bind_guard(Arg1, Map, Env, Eval, State0), + case t_is_any_atom(true, Type1) of + false -> signal_guard_fail(Eval, Guard, [Type1, t_any()], State1); true -> - {Map2, Type2} = bind_guard(Arg2, Map1, Env, Eval, State), - case t_is_any_atom(true, Type2, Opaques) of - false -> signal_guard_fail(Eval, Guard, [Type1, Type2], State); - true -> {Map2, t_atom(true)} + {Map2, Type2, State2} = bind_guard(Arg2, Map1, Env, Eval, State1), + case t_is_any_atom(true, Type2) of + false -> signal_guard_fail(Eval, Guard, [Type1, Type2], State2); + true -> {Map2, t_atom(true), State2} end end; neg -> MapJ = join_maps_begin(Map), - {Map1, Type1} = - try bind_guard(Arg1, MapJ, Env, neg, State) - catch throw:{fail, _} -> bind_guard(Arg2, MapJ, Env, pos, State) + {Map1, Type1, State1} = + try bind_guard(Arg1, MapJ, Env, neg, State0) + catch throw:{fail, _} -> bind_guard(Arg2, MapJ, Env, pos, State0) end, - {Map2, Type2} = - try bind_guard(Arg2, MapJ, Env, neg, State) - catch throw:{fail, _} -> bind_guard(Arg1, MapJ, Env, pos, State) + {Map2, Type2, State2} = + try bind_guard(Arg2, MapJ, Env, neg, State1) + catch throw:{fail, _} -> bind_guard(Arg1, MapJ, Env, pos, State1) end, case - t_is_any_atom(false, Type1, Opaques) - orelse t_is_any_atom(false, Type2, Opaques) + t_is_any_atom(false, Type1) + orelse t_is_any_atom(false, Type2) of - true -> {join_maps_end([Map1, Map2], MapJ), t_atom(false)}; - false -> signal_guard_fail(Eval, Guard, [Type1, Type2], State) + true -> {join_maps_end([Map1, Map2], MapJ), t_atom(false), State2}; + false -> signal_guard_fail(Eval, Guard, [Type1, Type2], State2) end; dont_know -> MapJ = join_maps_begin(Map), - {Map1, Type1} = bind_guard(Arg1, MapJ, Env, dont_know, State), - {Map2, Type2} = bind_guard(Arg2, MapJ, Env, dont_know, State), + {Map1, Type1, State1} = bind_guard(Arg1, MapJ, Env, dont_know, State0), + {Map2, Type2, State2} = bind_guard(Arg2, MapJ, Env, dont_know, State1), Bool1 = t_inf(Type1, t_boolean()), Bool2 = t_inf(Type2, t_boolean()), case t_is_none(Bool1) orelse t_is_none(Bool2) of @@ -2288,114 +2290,114 @@ handle_guard_and(Guard, Map, Env, Eval, State) -> false -> NewMap = join_maps_end([Map1, Map2], MapJ), NewType = - case {t_atom_vals(Bool1, Opaques), t_atom_vals(Bool2, Opaques)} of + case {t_atom_vals(Bool1), t_atom_vals(Bool2)} of {['true'] , ['true'] } -> t_atom(true); {['false'], _ } -> t_atom(false); {_ , ['false']} -> t_atom(false); {unknown , _ } -> - signal_guard_fail(Eval, Guard, [Type1, Type2], State); + signal_guard_fail(Eval, Guard, [Type1, Type2], State2); {_ , unknown } -> - signal_guard_fail(Eval, Guard, [Type1, Type2], State); + signal_guard_fail(Eval, Guard, [Type1, Type2], State2); {_ , _ } -> t_boolean() end, - {NewMap, NewType} + {NewMap, NewType, State2} end end. -handle_guard_or(Guard, Map, Env, Eval, State) -> +handle_guard_or(Guard, Map, Env, Eval, State0) -> [Arg1, Arg2] = cerl:call_args(Guard), - Opaques = State#state.opaques, case Eval of pos -> MapJ = join_maps_begin(Map), - {Map1, Bool1} = - try bind_guard(Arg1, MapJ, Env, pos, State) + {Map1, Bool1, State1} = + try bind_guard(Arg1, MapJ, Env, pos, State0) catch - throw:{fail,_} -> bind_guard(Arg1, MapJ, Env, dont_know, State) + throw:{fail,_} -> bind_guard(Arg1, MapJ, Env, dont_know, State0) end, - {Map2, Bool2} = - try bind_guard(Arg2, MapJ, Env, pos, State) + {Map2, Bool2, State2} = + try bind_guard(Arg2, MapJ, Env, pos, State1) catch - throw:{fail,_} -> bind_guard(Arg2, MapJ, Env, dont_know, State) + throw:{fail,_} -> bind_guard(Arg2, MapJ, Env, dont_know, State1) end, case - ((t_is_any_atom(true, Bool1, Opaques) - andalso t_is_boolean(Bool2, Opaques)) + ((t_is_any_atom(true, Bool1) + andalso t_is_boolean(Bool2)) orelse - (t_is_any_atom(true, Bool2, Opaques) - andalso t_is_boolean(Bool1, Opaques))) + (t_is_any_atom(true, Bool2) + andalso t_is_boolean(Bool1))) of - true -> {join_maps_end([Map1, Map2], MapJ), t_atom(true)}; - false -> signal_guard_fail(Eval, Guard, [Bool1, Bool2], State) + true -> {join_maps_end([Map1, Map2], MapJ), t_atom(true), State2}; + false -> signal_guard_fail(Eval, Guard, [Bool1, Bool2], State2) end; neg -> - {Map1, Type1} = bind_guard(Arg1, Map, Env, neg, State), - case t_is_any_atom(false, Type1, Opaques) of - false -> signal_guard_fail(Eval, Guard, [Type1, t_any()], State); + {Map1, Type1, State1} = bind_guard(Arg1, Map, Env, neg, State0), + case t_is_any_atom(false, Type1) of + false -> + signal_guard_fail(Eval, Guard, [Type1, t_any()], State1); true -> - {Map2, Type2} = bind_guard(Arg2, Map1, Env, neg, State), - case t_is_any_atom(false, Type2, Opaques) of - false -> signal_guard_fail(Eval, Guard, [Type1, Type2], State); - true -> {Map2, t_atom(false)} + {Map2, Type2, State2} = bind_guard(Arg2, Map1, Env, neg, State1), + case t_is_any_atom(false, Type2) of + false -> signal_guard_fail(Eval, Guard, [Type1, Type2], State2); + true -> {Map2, t_atom(false), State2} end end; dont_know -> MapJ = join_maps_begin(Map), - {Map1, Type1} = bind_guard(Arg1, MapJ, Env, dont_know, State), - {Map2, Type2} = bind_guard(Arg2, MapJ, Env, dont_know, State), + {Map1, Type1, State1} = bind_guard(Arg1, MapJ, Env, dont_know, State0), + {Map2, Type2, State2} = bind_guard(Arg2, MapJ, Env, dont_know, State1), Bool1 = t_inf(Type1, t_boolean()), Bool2 = t_inf(Type2, t_boolean()), case t_is_none(Bool1) orelse t_is_none(Bool2) of - true -> throw({fatal_fail, none}); + true -> + throw({fatal_fail, none}); false -> NewMap = join_maps_end([Map1, Map2], MapJ), NewType = - case {t_atom_vals(Bool1, Opaques), t_atom_vals(Bool2, Opaques)} of + case {t_atom_vals(Bool1), t_atom_vals(Bool2)} of {['false'], ['false']} -> t_atom(false); {['true'] , _ } -> t_atom(true); {_ , ['true'] } -> t_atom(true); {unknown , _ } -> - signal_guard_fail(Eval, Guard, [Type1, Type2], State); + signal_guard_fail(Eval, Guard, [Type1, Type2], State2); {_ , unknown } -> - signal_guard_fail(Eval, Guard, [Type1, Type2], State); + signal_guard_fail(Eval, Guard, [Type1, Type2], State2); {_ , _ } -> t_boolean() end, - {NewMap, NewType} + {NewMap, NewType, State2} end end. -handle_guard_not(Guard, Map, Env, Eval, State) -> +handle_guard_not(Guard, Map, Env, Eval, State0) -> [Arg] = cerl:call_args(Guard), - Opaques = State#state.opaques, case Eval of neg -> - {Map1, Type} = bind_guard(Arg, Map, Env, pos, State), - case t_is_any_atom(true, Type, Opaques) of - true -> {Map1, t_atom(false)}; + {Map1, Type, State1} = bind_guard(Arg, Map, Env, pos, State0), + case t_is_any_atom(true, Type) of + true -> {Map1, t_atom(false), State1}; false -> - {_, Type0} = bind_guard(Arg, Map, Env, Eval, State), - signal_guard_fail(Eval, Guard, [Type0], State) + {_, Type0, State2} = bind_guard(Arg, Map, Env, Eval, State1), + signal_guard_fail(Eval, Guard, [Type0], State2) end; pos -> - {Map1, Type} = bind_guard(Arg, Map, Env, neg, State), - case t_is_any_atom(false, Type, Opaques) of - true -> {Map1, t_atom(true)}; + {Map1, Type, State1} = bind_guard(Arg, Map, Env, neg, State0), + case t_is_any_atom(false, Type) of + true -> {Map1, t_atom(true), State1}; false -> - {_, Type0} = bind_guard(Arg, Map, Env, Eval, State), - signal_guard_fail(Eval, Guard, [Type0], State) + {_, Type0, State2} = bind_guard(Arg, Map, Env, Eval, State1), + signal_guard_fail(Eval, Guard, [Type0], State2) end; dont_know -> - {Map1, Type} = bind_guard(Arg, Map, Env, dont_know, State), + {Map1, Type, State1} = bind_guard(Arg, Map, Env, dont_know, State0), Bool = t_inf(Type, t_boolean()), case t_is_none(Bool) of true -> throw({fatal_fail, none}); false -> - case t_atom_vals(Bool, Opaques) of - ['true'] -> {Map1, t_atom(false)}; - ['false'] -> {Map1, t_atom(true)}; - [_, _] -> {Map1, Bool}; - unknown -> signal_guard_fail(Eval, Guard, [Type], State) + case t_atom_vals(Bool) of + ['true'] -> {Map1, t_atom(false), State1}; + ['false'] -> {Map1, t_atom(true), State1}; + [_, _] -> {Map1, Bool, State1}; + unknown -> signal_guard_fail(Eval, Guard, [Type], State1) end end end. @@ -2404,33 +2406,33 @@ bind_guard_list(Guards, Map, Env, Eval, State) -> bind_guard_list(Guards, Map, Env, Eval, State, []). bind_guard_list([G|Gs], Map, Env, Eval, State, Acc) -> - {Map1, T} = bind_guard(G, Map, Env, Eval, State), - bind_guard_list(Gs, Map1, Env, Eval, State, [T|Acc]); -bind_guard_list([], Map, _Env, _Eval, _State, Acc) -> - {Map, lists:reverse(Acc)}. + {Map1, T, State1} = bind_guard(G, Map, Env, Eval, State), + bind_guard_list(Gs, Map1, Env, Eval, State1, [T|Acc]); +bind_guard_list([], Map, _Env, _Eval, State, Acc) -> + {Map, lists:reverse(Acc), State}. -handle_guard_map(Guard, Map, Env, State) -> +handle_guard_map(Guard, Map, Env, State0) -> Pairs = cerl:map_es(Guard), Arg = cerl:map_arg(Guard), - {Map1, ArgType0} = bind_guard(Arg, Map, Env, dont_know, State), + {Map1, ArgType0, State1} = bind_guard(Arg, Map, Env, dont_know, State0), ArgType1 = t_inf(t_map(), ArgType0), case t_is_impossible(ArgType1) of - true -> {Map1, t_none()}; + true -> {Map1, t_none(), State1}; false -> - {Map2, TypePairs} = bind_guard_map_pairs(Pairs, Map1, Env, State, []), + {Map2, TypePairs, State2} = bind_guard_map_pairs(Pairs, Map1, Env, State1, []), {Map2, lists:foldl(fun({KV,assoc},Acc) -> erl_types:t_map_put(KV,Acc); ({KV,exact},Acc) -> erl_types:t_map_update(KV,Acc) - end, ArgType1, TypePairs)} + end, ArgType1, TypePairs), State2} end. -bind_guard_map_pairs([], Map, _Env, _State, PairAcc) -> - {Map, lists:reverse(PairAcc)}; -bind_guard_map_pairs([Pair|Pairs], Map, Env, State, PairAcc) -> +bind_guard_map_pairs([], Map, _Env, State, PairAcc) -> + {Map, lists:reverse(PairAcc), State}; +bind_guard_map_pairs([Pair|Pairs], Map, Env, State0, PairAcc) -> Key = cerl:map_pair_key(Pair), Val = cerl:map_pair_val(Pair), Op = cerl:map_pair_op(Pair), - {Map1, [K,V]} = bind_guard_list([Key,Val],Map,Env,dont_know,State), - bind_guard_map_pairs(Pairs, Map1, Env, State, + {Map1, [K,V], State1} = bind_guard_list([Key,Val],Map,Env,dont_know,State0), + bind_guard_map_pairs(Pairs, Map1, Env, State1, [{{K,V},cerl:concrete(Op)}|PairAcc]). -type eval() :: 'pos' | 'neg' | 'dont_know'. @@ -2458,19 +2460,12 @@ signal_guard_fatal_fail(Eval, Guard, ArgTypes, State) -> signal_guard_failure(Eval, Guard, ArgTypes, Tag, State) -> Args = cerl:call_args(Guard), F = cerl:atom_val(cerl:call_name(Guard)), - {M, F, A} = MFA = {cerl:atom_val(cerl:call_module(Guard)), F, length(Args)}, - Opaques = State#state.opaques, - {Kind, XInfo} = - case erl_bif_types:opaque_args(M, F, A, ArgTypes, Opaques) of - [] -> - {case Eval of - neg -> neg_guard_fail; - pos -> guard_fail; - dont_know -> guard_fail - end, - []}; - Ns -> {opaque_guard, [Ns]} - end, + MFA = {cerl:atom_val(cerl:call_module(Guard)), F, length(Args)}, + Kind = case Eval of + neg -> neg_guard_fail; + pos -> guard_fail; + dont_know -> guard_fail + end, FArgs = case is_infix_op(MFA) of true -> @@ -2478,17 +2473,12 @@ signal_guard_failure(Eval, Guard, ArgTypes, Tag, State) -> [Arg1, Arg2] = Args, [format_args_1([Arg1], [ArgType1], State), atom_to_list(F), - format_args_1([Arg2], [ArgType2], State)] ++ XInfo; + format_args_1([Arg2], [ArgType2], State)]; false -> [F, format_args(Args, ArgTypes, State)] end, Msg = {Kind, FArgs}, - LocTree = - case XInfo of - [] -> Guard; - [Ns1] -> select_arg(Ns1, Args, Guard) - end, - throw({Tag, {LocTree, Msg}}). + throw({Tag, {Guard, Msg}}). is_infix_op({erlang, F, 2}) -> erl_internal:comp_op(F, 2); @@ -2501,12 +2491,12 @@ bif_args(M, F, A) -> List -> List end. -bind_guard_case_clauses(Arg, Clauses, Map0, Env, Eval, State) -> +bind_guard_case_clauses(Arg, Clauses, Map0, Env, Eval, State0) -> Clauses1 = filter_fail_clauses(Clauses), Map = join_maps_begin(Map0), - {GenMap, GenArgType} = bind_guard(Arg, Map, Env, dont_know, State), + {GenMap, GenArgType, State1} = bind_guard(Arg, Map, Env, dont_know, State0), bind_guard_case_clauses(GenArgType, GenMap, Arg, Clauses1, Map, Env, Eval, - t_none(), [], [], State). + t_none(), [], [], State1). filter_fail_clauses([Clause|Left]) -> case (cerl:clause_pats(Clause) =:= []) of @@ -2525,41 +2515,41 @@ filter_fail_clauses([]) -> []. bind_guard_case_clauses(GenArgType, GenMap, ArgExpr, [Clause|Left], - Map, Env, Eval, AccType, AccMaps, Throws, State) -> + Map, Env, Eval, AccType, AccMaps, Throws, State0) -> Pats = cerl:clause_pats(Clause), - {NewMap0, ArgType} = + {NewMap0, ArgType, State1} = case Pats of [Pat] -> case cerl:is_literal(Pat) of true -> try case cerl:concrete(Pat) of - true -> bind_guard(ArgExpr, Map, Env, pos, State); - false -> bind_guard(ArgExpr, Map, Env, neg, State); - _ -> {GenMap, GenArgType} + true -> bind_guard(ArgExpr, Map, Env, pos, State0); + false -> bind_guard(ArgExpr, Map, Env, neg, State0); + _ -> {GenMap, GenArgType, State0} end catch - throw:{fail, _} -> {none, GenArgType} + throw:{fail, _} -> {none, GenArgType, State0} end; false -> - {GenMap, GenArgType} + {GenMap, GenArgType, State0} end; - _ -> {GenMap, GenArgType} + _ -> {GenMap, GenArgType, State0} end, - NewMap1 = + {NewMap1, State3} = case Pats =:= [] of - true -> NewMap0; + true -> {NewMap0, State1}; false -> case t_is_none(ArgType) of - true -> none; + true -> {none, State1}; false -> ArgTypes = case t_is_any(ArgType) of true -> Any = t_any(), [Any || _ <- Pats]; false -> t_to_tlist(ArgType) end, - case bind_pat_vars(Pats, ArgTypes, NewMap0, State) of - {error, _, _, _, _} -> none; - {PatMap, _PatTypes} -> PatMap + case bind_pat_vars(Pats, ArgTypes, NewMap0, State1) of + {error, _, _, _} -> {none, State1}; + {PatMap, _PatTypes, State2} -> {PatMap, State2} end end end, @@ -2569,53 +2559,41 @@ bind_guard_case_clauses(GenArgType, GenMap, ArgExpr, [Clause|Left], case (NewMap1 =:= none) orelse t_is_none(GenArgType) of true -> bind_guard_case_clauses(NewGenArgType, GenMap, ArgExpr, Left, Map, Env, - Eval, AccType, AccMaps, Throws, State); + Eval, AccType, AccMaps, Throws, State3); false -> - {NewAccType, NewAccMaps, NewThrows} = - try - {NewMap2, GuardType} = bind_guard(Guard, NewMap1, Env, pos, State), - case t_is_none(t_inf(t_atom(true), GuardType)) of - true -> throw({fail, none}); - false -> ok - end, - {NewMap3, CType} = bind_guard(cerl:clause_body(Clause), NewMap2, - Env, Eval, State), - Opaques = State#state.opaques, - case Eval of - pos -> - case t_is_any_atom(true, CType, Opaques) of - true -> ok; - false -> throw({fail, none}) - end; - neg -> - case t_is_any_atom(false, CType, Opaques) of - true -> ok; - false -> throw({fail, none}) - end; - dont_know -> - ok - end, - {t_sup(AccType, CType), [NewMap3|AccMaps], Throws} - catch - throw:{fail, Reason} -> - Throws1 = case Reason of - none -> Throws; - _ -> Throws ++ [Reason] - end, - {AccType, AccMaps, Throws1} + {NewAccType, NewAccMaps, NewThrows, State6} = + try maybe + {NewMap2, GuardType, State4} = bind_guard(Guard, NewMap1, Env, pos, State3), + true ?= not t_is_none(t_inf(t_atom(true), GuardType)), + {NewMap3, CType, State5} = bind_guard(cerl:clause_body(Clause), NewMap2, + Env, Eval, State4), + true ?= case Eval of + pos -> t_is_any_atom(true, CType); + neg -> t_is_any_atom(false, CType); + dont_know -> true + end, + {t_sup(AccType, CType), [NewMap3|AccMaps], Throws, State5} + else + false -> {AccType, AccMaps, Throws, State3} + end + of + Res -> Res + catch + throw:{fail, Reason} -> + {AccType, AccMaps, Throws ++ [Reason], State3} end, bind_guard_case_clauses(NewGenArgType, GenMap, ArgExpr, Left, Map, Env, - Eval, NewAccType, NewAccMaps, NewThrows, State) + Eval, NewAccType, NewAccMaps, NewThrows, State6) end; bind_guard_case_clauses(_GenArgType, _GenMap, _ArgExpr, [], Map, _Env, _Eval, - AccType, AccMaps, Throws, _State) -> + AccType, AccMaps, Throws, State) -> case t_is_none(AccType) of true -> case Throws of [Throw|_] -> throw({fail, Throw}); [] -> throw({fail, none}) end; - false -> {join_maps_end(AccMaps, Map), AccType} + false -> {join_maps_end(AccMaps, Map), AccType, State} end. %%% =========================================================================== @@ -2837,15 +2815,11 @@ get_label(L) when is_integer(L) -> get_label(T) -> cerl_trees:get_label(T). -t_is_simple(ArgType, State) -> - Opaques = State#state.opaques, - t_is_atom(ArgType, Opaques) orelse t_is_number(ArgType, Opaques) - orelse t_is_port(ArgType, Opaques) - orelse t_is_pid(ArgType, Opaques) orelse t_is_reference(ArgType, Opaques) - orelse t_is_nil(ArgType, Opaques). - -remove_local_opaque_types(Type, Opaques) -> - t_unopaque(Type, Opaques). +t_is_simple(ArgType, _State) -> + t_is_atom(ArgType) orelse t_is_number(ArgType) + orelse t_is_port(ArgType) + orelse t_is_pid(ArgType) orelse t_is_reference(ArgType) + orelse t_is_nil(ArgType). %% t_is_structured(ArgType) -> %% case t_is_nil(ArgType) of @@ -2874,11 +2848,10 @@ is_send(send) -> true; is_send(_) -> false. is_lc_simple_list(Tree, TreeType, State) -> - Opaques = State#state.opaques, Ann = cerl:get_ann(Tree), lists:member(list_comprehension, Ann) andalso t_is_list(TreeType) - andalso t_is_simple(t_list_elements(TreeType, Opaques), State). + andalso t_is_simple(t_list_elements(TreeType), State). %%% =========================================================================== %%% @@ -2887,7 +2860,6 @@ is_lc_simple_list(Tree, TreeType, State) -> %%% =========================================================================== state__new(Callgraph, Codeserver, Tree, Plt, Module, Records) -> - Opaques = erl_types:t_opaque_from_records(Records), {TreeMap, FunHomes} = build_tree_map(Tree, Callgraph), Funs = dict:fetch_keys(TreeMap), FunTab = init_fun_tab(Funs, dict:new(), TreeMap, Callgraph, Plt), @@ -2901,7 +2873,7 @@ state__new(Callgraph, Codeserver, Tree, Plt, Module, Records) -> Env = lists:foldl(fun(Fun, Env) -> dict:store(Fun, map__new(), Env) end, dict:new(), Funs), #state{callgraph = Callgraph, codeserver = Codeserver, - envs = Env, fun_tab = FunTab, fun_homes = FunHomes, opaques = Opaques, + envs = Env, fun_tab = FunTab, fun_homes = FunHomes, plt = Plt, records = Records, warning_mode = false, warnings = [], work = Work, tree_map = TreeMap, module = Module, reachable_funs = sets:new()}. @@ -2933,28 +2905,19 @@ state__add_warning(#state{warning_mode = false} = State, _, _, _, _) -> state__add_warning(#state{warnings = Warnings, warning_mode = true} = State, Tag, Tree, Msg, Force) -> Ann = cerl:get_ann(Tree), - case Force of + case Force orelse (not is_compiler_generated(Ann)) of true -> WarningInfo = {get_file(Ann, State), get_location(Tree), State#state.curr_fun}, Warn = {Tag, WarningInfo, Msg}, - ?debug("MSG ~ts\n", [dialyzer:format_warning(Warn)]), + case Tag of + ?WARN_CONTRACT_RANGE -> ok; + _ -> ?debug("MSG ~ts\n", [dialyzer:format_warning(Warn)]) + end, State#state{warnings = [Warn|Warnings]}; false -> - case is_compiler_generated(Ann) of - true -> State; - false -> - WarningInfo = {get_file(Ann, State), - get_location(Tree), - State#state.curr_fun}, - Warn = {Tag, WarningInfo, Msg}, - case Tag of - ?WARN_CONTRACT_RANGE -> ok; - _ -> ?debug("MSG ~ts\n", [dialyzer:format_warning(Warn)]) - end, - State#state{warnings = [Warn|Warnings]} - end + State end. state__remove_added_warnings(OldState, NewState) -> @@ -3408,8 +3371,8 @@ format_field_diffs(RecConstruction, #state{records = R}) -> -spec format_sig_args(type(), state()) -> string(). -format_sig_args(Type, #state{opaques = Opaques} = State) -> - SigArgs = t_fun_args(Type, Opaques), +format_sig_args(Type, State) -> + SigArgs = t_fun_args(Type), case SigArgs of [] -> "()"; [SArg|SArgs] -> @@ -3462,9 +3425,6 @@ map_pats(Pats) -> fold_literals(TreeList) -> [cerl:fold_literal(Tree) || Tree <- TreeList]. -format_atom(A) -> - format_cerl(cerl:c_atom(A)). - type(Tree) -> Folded = cerl:fold_literal(Tree), case cerl:type(Folded) of diff --git a/lib/dialyzer/src/dialyzer_options.erl b/lib/dialyzer/src/dialyzer_options.erl index 90b156f86576..0e68559785be 100644 --- a/lib/dialyzer/src/dialyzer_options.erl +++ b/lib/dialyzer/src/dialyzer_options.erl @@ -38,6 +38,7 @@ build(Opts) -> ?WARN_FUN_APP, ?WARN_MATCHING, ?WARN_OPAQUE, + ?WARN_OPAQUE_UNION, ?WARN_CALLGRAPH, ?WARN_FAILING_CALL, ?WARN_BIN_CONSTRUCTION, @@ -501,7 +502,9 @@ build_warnings([Opt|Opts], Warnings) -> no_match -> ordsets:del_element(?WARN_MATCHING, Warnings); no_opaque -> - ordsets:del_element(?WARN_OPAQUE, Warnings); + S = ordsets:from_list([?WARN_OPAQUE, + ?WARN_OPAQUE_UNION]), + ordsets:subtract(Warnings, S); no_fail_call -> ordsets:del_element(?WARN_FAILING_CALL, Warnings); no_contracts -> @@ -543,6 +546,10 @@ build_warnings([Opt|Opts], Warnings) -> ordsets:add_element(?WARN_CONTRACT_MISSING_RETURN, Warnings); no_missing_return -> ordsets:del_element(?WARN_CONTRACT_MISSING_RETURN, Warnings); + opaque_union -> + ordsets:add_element(?WARN_OPAQUE_UNION, Warnings); + no_opaque_union -> + ordsets:del_element(?WARN_OPAQUE_UNION, Warnings); unknown -> ordsets:add_element(?WARN_UNKNOWN, Warnings); overlapping_contract -> diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl index 76396a5446a1..f4ebe6560c20 100644 --- a/lib/dialyzer/src/dialyzer_succ_typings.erl +++ b/lib/dialyzer/src/dialyzer_succ_typings.erl @@ -125,27 +125,25 @@ find_succ_types_for_scc(SCC0, {Codeserver, Callgraph, Plt, Solvers}) -> FilteredFunTypes = sofs:to_external(sofs:restriction(BinRel, Set)), FunMFAContracts = get_contracts(FilteredFunTypes, Callgraph, Codeserver), - ModOpaques = get_module_opaques(FunMFAContracts, Codeserver), - DecoratedFunTypes = decorate_succ_typings(FunMFAContracts, ModOpaques), %% Check contracts Contracts = orddict:from_list([{MFA, Contract} || {_, {MFA, Contract}} <- FunMFAContracts]), PltContracts = dialyzer_contracts:check_contracts(Contracts, Callgraph, - DecoratedFunTypes, - ModOpaques), - debug_pp_functions("SCC", FilteredFunTypes, DecoratedFunTypes, Callgraph), + FilteredFunTypes), + NewPltContracts = [MC || {MFA, _C}=MC <- PltContracts, %% Check the non-deleted PLT not dialyzer_plt:is_contract(Plt, MFA)], - _ = insert_into_plt(DecoratedFunTypes, Callgraph, Plt), + + _ = insert_into_plt(FilteredFunTypes, Callgraph, Plt), _ = dialyzer_plt:insert_contract_list(Plt, NewPltContracts), %% Check whether we have reached a fixpoint. case NewPltContracts =:= [] andalso - reached_fixpoint_strict(PropTypes, DecoratedFunTypes) of + reached_fixpoint_strict(PropTypes, FilteredFunTypes) of true -> []; false -> ?debug("Not fixpoint for: ~tw\n", [AllFuns]), @@ -162,12 +160,7 @@ refine_one_module(M, {CodeServer, Callgraph, Plt, _Solvers}) -> NewFunTypes = dialyzer_dataflow:get_fun_types(ModCode, Plt, Callgraph, CodeServer, Records), - FunMFAContracts = get_contracts(NewFunTypes, Callgraph, CodeServer), - ModOpaques = get_module_opaques(FunMFAContracts, CodeServer), - DecoratedFunTypes = decorate_succ_typings(FunMFAContracts, ModOpaques), - debug_pp_functions("Refine", NewFunTypes, DecoratedFunTypes, Callgraph), - - case updated_types(FunTypes, DecoratedFunTypes) of + case updated_types(FunTypes, NewFunTypes) of [] -> []; [_|_]=NotFixpoint -> ?debug("Not fixpoint\n", []), @@ -381,31 +374,6 @@ get_contracts(FunTypes, Callgraph, Codeserver) -> end, lists:foldl(F, [], FunTypes). -get_module_opaques(Contracts, Codeserver) -> - OpaqueModules = ordsets:from_list([M || {_LabelType, {{M, _, _}, _Con}} <- Contracts]), - [{M, lookup_opaques(M, Codeserver)} || M <- OpaqueModules]. - -decorate_succ_typings(FunTypesContracts, ModOpaques) -> - F = fun({{Label, Type}, {{M, _, _}, Contract}}, Acc) -> - case lists:keyfind(M, 1, ModOpaques) of - {M, []} -> - [{Label, Type}|Acc]; - {M, Opaques} -> - Args = dialyzer_contracts:get_contract_args(Contract), - Ret = dialyzer_contracts:get_contract_return(Contract), - C = erl_types:t_fun(Args, Ret), - R = erl_types:t_decorate_with_opaque(Type, C, Opaques), - [{Label, R}|Acc] - end; - ({LabelType, no}, Acc) -> - [LabelType|Acc] - end, - orddict:from_list(lists:foldl(F, [], FunTypesContracts)). - -lookup_opaques(Module, Codeserver) -> - Records = dialyzer_codeserver:lookup_mod_records(Module, Codeserver), - erl_types:t_opaque_from_records(Records). - get_fun_types_from_plt(FunList, Callgraph, Plt) -> get_fun_types_from_plt(FunList, Callgraph, Plt, []). @@ -475,26 +443,7 @@ debug_pp_succ_typings(SuccTypes) -> || {MFA, {contract, RetFun, ArgT}} <- SuccTypes], ?debug("\n", []), ok. - -debug_pp_functions(Header, FTypes, DTypes, Callgraph) -> - ?debug("FunTypes (~s)\n", [Header]), - Fun = fun({{Label, Type},{Label, DecoratedType}}) -> - Name = lookup_name(Label, Callgraph), - ?debug("~tw (~w): ~ts\n", - [Name, Label, erl_types:t_to_string(Type)]), - case erl_types:t_is_equal(Type, DecoratedType) of - true -> ok; - false -> - ?debug(" With opaque types: ~ts\n", - [erl_types:t_to_string(DecoratedType)]) - end - end, - lists:foreach(Fun, lists:zip(FTypes, DTypes)), - ?debug("\n", []). -else. debug_pp_succ_typings(_) -> ok. - -debug_pp_functions(_, _, _, _) -> - ok. -endif. diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 1a4853cb239b..da809051b399 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -2267,8 +2267,7 @@ solve_subtype(Type, Inf, Map) -> %% Similar to enter_type/3 over a list, but refines known types rather than %% replaces them. refine_bindings([{Key, Val} | Tail], Map, U0) -> - ?debug("Unifying ~ts :: ~ts\n", - [format_type(t_var(Key)), format_type(Val)]), + ?debug("Unifying ~p :: ~ts\n", [Key, format_type(Val)]), %% It's important to keep opaque types whose internal structure is any(), %% hence the equality check on t_any() rather than t_is_any/1. case t_is_equal(Val, t_any()) of @@ -3168,7 +3167,7 @@ pp_constrs_scc(SCC, State) -> [pp_constrs(Fun, state__get_cs(Fun, State), State) || Fun <- SCC]. pp_constrs(Fun, Cs, State) -> - io:format("Constraints for fun: ~tw", [debug_lookup_name(Fun)]), + io:format("Constraints for fun: ~tw~n", [debug_lookup_name(Fun)]), MaxDepth = pp_constraints(Cs, State), io:format("Depth: ~w\n", [MaxDepth]). diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl index 3868851b0a75..ed6edeafdb37 100644 --- a/lib/dialyzer/src/dialyzer_utils.erl +++ b/lib/dialyzer/src/dialyzer_utils.erl @@ -176,7 +176,7 @@ get_record_and_type_info([{type, Location, [{{record, Name}, Fields0, []}]} get_record_and_type_info(Left, Module, NewRecDict, File); get_record_and_type_info([{Attr, Location, [{Name, TypeForm}]}|Left], Module, RecDict, File) - when Attr =:= 'type'; Attr =:= 'opaque' -> + when Attr =:= 'type'; Attr =:= 'opaque'; Attr =:= 'nominal' -> FN = {File, Location}, try add_new_type(Attr, Name, TypeForm, [], Module, FN, RecDict) of NewRecDict -> @@ -186,7 +186,7 @@ get_record_and_type_info([{Attr, Location, [{Name, TypeForm}]}|Left], end; get_record_and_type_info([{Attr, Location, [{Name, TypeForm, Args}]}|Left], Module, RecDict, File) - when Attr =:= 'type'; Attr =:= 'opaque' -> + when Attr =:= 'type'; Attr =:= 'opaque'; Attr =:= 'nominal' -> FN = {File, Location}, try add_new_type(Attr, Name, TypeForm, Args, Module, FN, RecDict) of NewRecDict -> @@ -375,6 +375,8 @@ process_opaque_types(AllModules, CServer, TempExpTypes) -> {{Key, {F, Type}}, C3}; {type, _Name, _NArgs} -> {{Key, Value}, C2}; + {nominal, _Name, _NArgs} -> + {{Key, Value}, C2}; {record, _RecName} -> {{Key, Value}, C2} end diff --git a/lib/dialyzer/src/dialyzer_worker.erl b/lib/dialyzer/src/dialyzer_worker.erl index 1fd948336755..a5e925961c06 100644 --- a/lib/dialyzer/src/dialyzer_worker.erl +++ b/lib/dialyzer/src/dialyzer_worker.erl @@ -72,6 +72,7 @@ run(#state{coordinator = Coordinator, job = Job} = State) -> ?debug("~w: Done: ~p\n",[self(), Job]), dialyzer_coordinator:job_done(Job, Result, Coordinator). +-dialyzer({no_opaque_union, [run_job/1]}). run_job(#state{mode = Mode, job = Job, init_data = InitData} = State) -> ?debug("~w: ~p: ~p\n", [self(), Mode, Job]), StartableJob = dialyzer_coordinator:get_job_input(Mode, Job), diff --git a/lib/dialyzer/src/erl_bif_types.erl b/lib/dialyzer/src/erl_bif_types.erl index 37d9dcec8908..7cfd1c014d7d 100644 --- a/lib/dialyzer/src/erl_bif_types.erl +++ b/lib/dialyzer/src/erl_bif_types.erl @@ -23,17 +23,17 @@ -moduledoc false. -define(BITS, 128). %This is only in bsl to convert answer to pos_inf/neg_inf. --export([type/3, type/4, type/5, arg_types/3, - is_known/3, opaque_args/5, infinity_add/2]). +-export([type/3, type/4, arg_types/3, + is_known/3, infinity_add/2]). --import(erl_types, [number_max/2, - number_min/2, +-import(erl_types, [number_max/1, + number_min/1, t_any/0, t_arity/0, t_atom/0, t_atom/1, t_atoms/1, - t_atom_vals/2, + t_atom_vals/1, t_binary/0, t_bitstr/0, t_boolean/0, @@ -49,11 +49,10 @@ t_from_term/1, t_fun/0, t_fun/2, - t_fun_args/2, - t_fun_range/2, + t_fun_args/1, + t_fun_range/1, t_identifier/0, - t_has_opaque_subtype/2, - t_inf/3, + t_inf/2, t_integer/0, t_integer/1, t_non_neg_fixnum/0, @@ -61,28 +60,28 @@ t_pos_integer/0, t_integers/1, t_is_any/1, - t_is_atom/2, - t_is_binary/2, - t_is_bitstr/2, - t_is_boolean/2, - t_is_cons/2, - t_is_float/2, - t_is_fun/2, + t_is_atom/1, + t_is_binary/1, + t_is_bitstr/1, + t_is_boolean/1, + t_is_cons/1, + t_is_float/1, + t_is_fun/1, t_is_impossible/1, - t_is_integer/2, - t_is_nil/1, t_is_nil/2, + t_is_integer/1, + t_is_nil/1, t_is_none/1, - t_is_number/2, - t_is_pid/2, - t_is_port/2, - t_is_maybe_improper_list/2, - t_is_reference/2, + t_is_number/1, + t_is_pid/1, + t_is_port/1, + t_is_maybe_improper_list/1, + t_is_reference/1, t_is_subtype/2, - t_is_tuple/2, + t_is_tuple/1, t_list/0, t_list/1, - t_list_elements/2, - t_list_termination/2, + t_list_elements/1, + t_list_termination/1, t_module/0, t_nil/0, t_node/0, @@ -90,7 +89,7 @@ t_nonempty_list/0, t_nonempty_list/1, t_number/0, - t_number_vals/2, + t_number_vals/1, t_pid/0, t_port/0, t_maybe_improper_list/0, @@ -101,21 +100,22 @@ t_sup/2, t_tuple/0, t_tuple/1, - t_tuple_args/2, - t_tuple_size/2, - t_tuple_subtypes/2, - t_is_map/2, + t_tuple_args/1, + t_tuple_size/1, + t_tuple_subtypes/1, + t_is_map/1, t_map/0, t_map/3, - t_map_def_key/2, - t_map_def_val/2, - t_map_get/3, - t_map_is_key/3, - t_map_entries/2, - t_map_put/3, - t_map_remove/3, - t_map_update/3, - t_map_pairwise_merge/4 + t_map_def_key/1, + t_map_def_val/1, + t_map_get/2, + t_map_is_key/2, + t_map_entries/1, + t_map_put/2, + t_map_remove/2, + t_map_update/2, + t_map_pairwise_merge/3, + t_inf_lists/2 ]). -ifdef(DO_ERL_BIF_TYPES_TEST). @@ -127,62 +127,52 @@ -spec type(atom(), atom(), arity()) -> erl_types:erl_type(). type(M, F, A) -> - type(M, F, A, any_list(A), []). + type(M, F, A, any_list(A)). %% Arguments should be checked for undefinedness, so we do not make %% unnecessary overapproximations. -spec type(atom(), atom(), arity(), [erl_types:erl_type()]) -> erl_types:erl_type(). -type(M, F, A, Xs) -> - type(M, F, A, Xs, 'universe'). - --type opaques() :: erl_types:opaques(). - --type arg_types() :: [erl_types:erl_type()]. - --spec type(atom(), atom(), arity(), arg_types(), opaques()) -> - erl_types:erl_type(). - %%-- erlang ------------------------------------------------------------------- -type(erlang, halt, 0, _, _) -> t_none(); -type(erlang, halt, 1, _, _) -> t_none(); -type(erlang, halt, 2, _, _) -> t_none(); -type(erlang, exit, 1, _, _) -> t_none(); -type(erlang, error, 1, _, _) -> t_none(); -type(erlang, error, 2, _, _) -> t_none(); -type(erlang, error, 3, _, _) -> t_none(); -type(erlang, throw, 1, _, _) -> t_none(); -type(erlang, '==', 2, Xs = [X1, X2], Opaques) -> +type(erlang, halt, 0, _) -> t_none(); +type(erlang, halt, 1, _) -> t_none(); +type(erlang, halt, 2, _) -> t_none(); +type(erlang, exit, 1, _) -> t_none(); +type(erlang, error, 1, _) -> t_none(); +type(erlang, error, 2, _) -> t_none(); +type(erlang, error, 3, _) -> t_none(); +type(erlang, throw, 1, _) -> t_none(); +type(erlang, '==', 2, Xs = [X1, X2]) -> case - t_is_atom(X1, Opaques) andalso t_is_atom(X2, Opaques) + t_is_atom(X1) andalso t_is_atom(X2) of - true -> type(erlang, '=:=', 2, Xs, Opaques); + true -> type(erlang, '=:=', 2, Xs); false -> - case t_is_integer(X1, Opaques) andalso t_is_integer(X2, Opaques) of - true -> type(erlang, '=:=', 2, Xs, Opaques); + case t_is_integer(X1) andalso t_is_integer(X2) of + true -> type(erlang, '=:=', 2, Xs); false -> strict2(Xs, t_boolean()) end end; -type(erlang, '/=', 2, Xs = [X1, X2], Opaques) -> +type(erlang, '/=', 2, Xs = [X1, X2]) -> case - t_is_atom(X1, Opaques) andalso t_is_atom(X2, Opaques) + t_is_atom(X1) andalso t_is_atom(X2) of - true -> type(erlang, '=/=', 2, Xs, Opaques); + true -> type(erlang, '=/=', 2, Xs); false -> - case t_is_integer(X1, Opaques) andalso t_is_integer(X2, Opaques) of - true -> type(erlang, '=/=', 2, Xs, Opaques); + case t_is_integer(X1) andalso t_is_integer(X2) of + true -> type(erlang, '=/=', 2, Xs); false -> strict2(Xs, t_boolean()) end end; -type(erlang, '=:=', 2, Xs = [Lhs, Rhs], Opaques) -> +type(erlang, '=:=', 2, Xs = [Lhs, Rhs]) -> Ans = - case t_is_none(t_inf(Lhs, Rhs, Opaques)) of + case t_is_none(t_inf(Lhs, Rhs)) of true -> t_atom('false'); false -> - case t_is_atom(Lhs, Opaques) andalso t_is_atom(Rhs, Opaques) of + case t_is_atom(Lhs) andalso t_is_atom(Rhs) of true -> - case {t_atom_vals(Lhs, Opaques), t_atom_vals(Rhs, Opaques)} of + case {t_atom_vals(Lhs), t_atom_vals(Rhs)} of {unknown, _} -> t_boolean(); {_, unknown} -> t_boolean(); {[X], [X]} -> t_atom('true'); @@ -195,19 +185,19 @@ type(erlang, '=:=', 2, Xs = [Lhs, Rhs], Opaques) -> end; false -> case - t_is_integer(Lhs, Opaques) andalso t_is_integer(Rhs, Opaques) + t_is_integer(Lhs) andalso t_is_integer(Rhs) of false -> t_boolean(); true -> case - {t_number_vals(Lhs, Opaques), t_number_vals(Rhs, Opaques)} + {t_number_vals(Lhs), t_number_vals(Rhs)} of {[X], [X]} when is_integer(X) -> t_atom('true'); _ -> - LhsMax = number_max(Lhs, Opaques), - LhsMin = number_min(Lhs, Opaques), - RhsMax = number_max(Rhs, Opaques), - RhsMin = number_min(Rhs, Opaques), + LhsMax = number_max(Lhs), + LhsMin = number_min(Lhs), + RhsMax = number_max(Rhs), + RhsMin = number_min(Rhs), Ans1 = (is_integer(LhsMin) andalso is_integer(RhsMax) andalso (LhsMin > RhsMax)), @@ -223,14 +213,14 @@ type(erlang, '=:=', 2, Xs = [Lhs, Rhs], Opaques) -> end end, strict2(Xs, Ans); -type(erlang, '=/=', 2, Xs = [Lhs, Rhs], Opaques) -> +type(erlang, '=/=', 2, Xs = [Lhs, Rhs]) -> Ans = - case t_is_none(t_inf(Lhs, Rhs, Opaques)) of + case t_is_none(t_inf(Lhs, Rhs)) of true -> t_atom('true'); false -> - case t_is_atom(Lhs, Opaques) andalso t_is_atom(Rhs, Opaques) of + case t_is_atom(Lhs) andalso t_is_atom(Rhs) of true -> - case {t_atom_vals(Lhs, Opaques), t_atom_vals(Rhs, Opaques)} of + case {t_atom_vals(Lhs), t_atom_vals(Rhs)} of {unknown, _} -> t_boolean(); {_, unknown} -> t_boolean(); {[Val], [Val]} -> t_atom('false'); @@ -239,14 +229,14 @@ type(erlang, '=/=', 2, Xs = [Lhs, Rhs], Opaques) -> end; false -> case - t_is_integer(Lhs, Opaques) andalso t_is_integer(Rhs, Opaques) + t_is_integer(Lhs) andalso t_is_integer(Rhs) of false -> t_boolean(); true -> - LhsMax = number_max(Lhs, Opaques), - LhsMin = number_min(Lhs, Opaques), - RhsMax = number_max(Rhs, Opaques), - RhsMin = number_min(Rhs, Opaques), + LhsMax = number_max(Lhs), + LhsMin = number_min(Lhs), + RhsMax = number_max(Rhs), + RhsMin = number_min(Rhs), Ans1 = (is_integer(LhsMin) andalso is_integer(RhsMax) andalso (LhsMin > RhsMax)), Ans2 = (is_integer(LhsMax) andalso is_integer(RhsMin) @@ -264,14 +254,14 @@ type(erlang, '=/=', 2, Xs = [Lhs, Rhs], Opaques) -> end end, strict2(Xs, Ans); -type(erlang, '>', 2, Xs = [Lhs, Rhs], Opaques) -> +type(erlang, '>', 2, Xs = [Lhs, Rhs]) -> Ans = - case t_is_integer(Lhs, Opaques) andalso t_is_integer(Rhs, Opaques) of + case t_is_integer(Lhs) andalso t_is_integer(Rhs) of true -> - LhsMax = number_max(Lhs, Opaques), - LhsMin = number_min(Lhs, Opaques), - RhsMax = number_max(Rhs, Opaques), - RhsMin = number_min(Rhs, Opaques), + LhsMax = number_max(Lhs), + LhsMin = number_min(Lhs), + RhsMax = number_max(Rhs), + RhsMin = number_min(Rhs), T = t_atom('true'), F = t_atom('false'), if @@ -279,17 +269,17 @@ type(erlang, '>', 2, Xs = [Lhs, Rhs], Opaques) -> is_integer(LhsMax), is_integer(RhsMin), RhsMin >= LhsMax -> F; true -> t_boolean() end; - false -> compare('>', Lhs, Rhs, Opaques) + false -> compare('>', Lhs, Rhs) end, strict2(Xs, Ans); -type(erlang, '>=', 2, Xs = [Lhs, Rhs], Opaques) -> +type(erlang, '>=', 2, Xs = [Lhs, Rhs]) -> Ans = - case t_is_integer(Lhs, Opaques) andalso t_is_integer(Rhs, Opaques) of + case t_is_integer(Lhs) andalso t_is_integer(Rhs) of true -> - LhsMax = number_max(Lhs, Opaques), - LhsMin = number_min(Lhs, Opaques), - RhsMax = number_max(Rhs, Opaques), - RhsMin = number_min(Rhs, Opaques), + LhsMax = number_max(Lhs), + LhsMin = number_min(Lhs), + RhsMax = number_max(Rhs), + RhsMin = number_min(Rhs), T = t_atom('true'), F = t_atom('false'), if @@ -297,17 +287,17 @@ type(erlang, '>=', 2, Xs = [Lhs, Rhs], Opaques) -> is_integer(LhsMax), is_integer(RhsMin), RhsMin > LhsMax -> F; true -> t_boolean() end; - false -> compare('>=', Lhs, Rhs, Opaques) + false -> compare('>=', Lhs, Rhs) end, strict2(Xs, Ans); -type(erlang, '<', 2, Xs = [Lhs, Rhs], Opaques) -> +type(erlang, '<', 2, Xs = [Lhs, Rhs]) -> Ans = - case t_is_integer(Lhs, Opaques) andalso t_is_integer(Rhs, Opaques) of + case t_is_integer(Lhs) andalso t_is_integer(Rhs) of true -> - LhsMax = number_max(Lhs, Opaques), - LhsMin = number_min(Lhs, Opaques), - RhsMax = number_max(Rhs, Opaques), - RhsMin = number_min(Rhs, Opaques), + LhsMax = number_max(Lhs), + LhsMin = number_min(Lhs), + RhsMax = number_max(Rhs), + RhsMin = number_min(Rhs), T = t_atom('true'), F = t_atom('false'), if @@ -315,17 +305,17 @@ type(erlang, '<', 2, Xs = [Lhs, Rhs], Opaques) -> is_integer(LhsMin), is_integer(RhsMax), RhsMax =< LhsMin -> F; true -> t_boolean() end; - false -> compare('<', Lhs, Rhs, Opaques) + false -> compare('<', Lhs, Rhs) end, strict2(Xs, Ans); -type(erlang, '=<', 2, Xs = [Lhs, Rhs], Opaques) -> +type(erlang, '=<', 2, Xs = [Lhs, Rhs]) -> Ans = - case t_is_integer(Lhs, Opaques) andalso t_is_integer(Rhs, Opaques) of + case t_is_integer(Lhs) andalso t_is_integer(Rhs) of true -> - LhsMax = number_max(Lhs, Opaques), - LhsMin = number_min(Lhs, Opaques), - RhsMax = number_max(Rhs, Opaques), - RhsMin = number_min(Rhs, Opaques), + LhsMax = number_max(Lhs), + LhsMin = number_min(Lhs), + RhsMax = number_max(Rhs), + RhsMin = number_min(Rhs), T = t_atom('true'), F = t_atom('false'), if @@ -333,100 +323,100 @@ type(erlang, '=<', 2, Xs = [Lhs, Rhs], Opaques) -> is_integer(LhsMin), is_integer(RhsMax), RhsMax < LhsMin -> F; true -> t_boolean() end; - false -> compare('=<', Lhs, Rhs, Opaques) + false -> compare('=<', Lhs, Rhs) end, strict2(Xs, Ans); -type(erlang, '+', 1, Xs, Opaques) -> - strict(erlang, '+', 1, Xs, fun ([X]) -> X end, Opaques); -type(erlang, '-', 1, Xs, Opaques) -> +type(erlang, '+', 1, Xs) -> + strict(erlang, '+', 1, Xs, fun ([X]) -> X end); +type(erlang, '-', 1, Xs) -> strict(erlang, '-', 1, Xs, fun ([X]) -> - case t_is_integer(X, Opaques) of + case t_is_integer(X) of true -> type(erlang, '-', 2, [t_integer(0), X]); false -> X end - end, Opaques); -type(erlang, '!', 2, Xs, Opaques) -> - strict(erlang, '!', 2, Xs, fun ([_, X2]) -> X2 end, Opaques); -type(erlang, '+', 2, Xs, Opaques) -> + end); +type(erlang, '!', 2, Xs) -> + strict(erlang, '!', 2, Xs, fun ([_, X2]) -> X2 end); +type(erlang, '+', 2, Xs) -> strict(erlang, '+', 2, Xs, fun ([X1, X2]) -> - case arith('+', X1, X2, Opaques) of + case arith('+', X1, X2) of {ok, T} -> T; error -> case - t_is_float(X1, Opaques) orelse t_is_float(X2, Opaques) + t_is_float(X1) orelse t_is_float(X2) of true -> t_float(); false -> t_number() end end - end, Opaques); -type(erlang, '-', 2, Xs, Opaques) -> + end); +type(erlang, '-', 2, Xs) -> strict(erlang, '-', 2, Xs, fun ([X1, X2]) -> - case arith('-', X1, X2, Opaques) of + case arith('-', X1, X2) of {ok, T} -> T; error -> case - t_is_float(X1, Opaques) orelse t_is_float(X2, Opaques) + t_is_float(X1) orelse t_is_float(X2) of true -> t_float(); false -> t_number() end end - end, Opaques); -type(erlang, '*', 2, Xs, Opaques) -> + end); +type(erlang, '*', 2, Xs) -> strict(erlang, '*', 2, Xs, fun ([X1, X2]) -> - case arith('*', X1, X2, Opaques) of + case arith('*', X1, X2) of {ok, T} -> T; error -> case - t_is_float(X1, Opaques) orelse t_is_float(X2, Opaques) + t_is_float(X1) orelse t_is_float(X2) of true -> t_float(); false -> t_number() end end - end, Opaques); -type(erlang, '/', 2, Xs, Opaques) -> - strict(erlang, '/', 2, Xs, fun (_) -> t_float() end, Opaques); -type(erlang, 'div', 2, Xs, Opaques) -> + end); +type(erlang, '/', 2, Xs) -> + strict(erlang, '/', 2, Xs, fun (_) -> t_float() end); +type(erlang, 'div', 2, Xs) -> strict(erlang, 'div', 2, Xs, fun ([X1, X2]) -> - case arith('div', X1, X2, Opaques) of + case arith('div', X1, X2) of error -> t_integer(); {ok, T} -> T end - end, Opaques); -type(erlang, 'rem', 2, Xs, Opaques) -> + end); +type(erlang, 'rem', 2, Xs) -> strict(erlang, 'rem', 2, Xs, fun ([X1, X2]) -> - case arith('rem', X1, X2, Opaques) of + case arith('rem', X1, X2) of error -> t_non_neg_integer(); {ok, T} -> T end - end, Opaques); -type(erlang, '++', 2, Xs, Opaques) -> + end); +type(erlang, '++', 2, Xs) -> strict(erlang, '++', 2, Xs, fun ([X1, X2]) -> - case t_is_nil(X1, Opaques) of + case t_is_nil(X1) of true -> X2; % even if X2 is not a list false -> - case t_is_nil(X2, Opaques) of + case t_is_nil(X2) of true -> X1; false -> - E1 = t_list_elements(X1, Opaques), - case t_is_cons(X1, Opaques) of + E1 = t_list_elements(X1), + case t_is_cons(X1) of true -> t_cons(E1, X2); false -> t_sup(X2, t_cons(E1, X2)) end end end - end, Opaques); -type(erlang, '--', 2, Xs, Opaques) -> + end); +type(erlang, '--', 2, Xs) -> %% We don't know which elements (if any) in X2 will be found and %% removed from X1, even if they would have the same type. Thus, we %% must assume that X1 can remain unchanged. However, if we succeed, @@ -434,137 +424,137 @@ type(erlang, '--', 2, Xs, Opaques) -> %% possibly be empty even if X1 is nonempty. strict(erlang, '--', 2, Xs, fun ([X1, X2]) -> - case t_is_nil(X1, Opaques) of + case t_is_nil(X1) of true -> t_nil(); false -> - case t_is_nil(X2, Opaques) of + case t_is_nil(X2) of true -> X1; - false -> t_list(t_list_elements(X1, Opaques)) + false -> t_list(t_list_elements(X1)) end end - end, Opaques); -type(erlang, 'and', 2, Xs, Opaques) -> - strict(erlang, 'and', 2, Xs, fun (_) -> t_boolean() end, Opaques); -type(erlang, 'or', 2, Xs, Opaques) -> - strict(erlang, 'or', 2, Xs, fun (_) -> t_boolean() end, Opaques); -type(erlang, 'xor', 2, Xs, Opaques) -> - strict(erlang, 'xor', 2, Xs, fun (_) -> t_boolean() end, Opaques); -type(erlang, 'not', 1, Xs, Opaques) -> - strict(erlang, 'not', 1, Xs, fun (_) -> t_boolean() end, Opaques); -type(erlang, 'band', 2, Xs, Opaques) -> + end); +type(erlang, 'and', 2, Xs) -> + strict(erlang, 'and', 2, Xs, fun (_) -> t_boolean() end); +type(erlang, 'or', 2, Xs) -> + strict(erlang, 'or', 2, Xs, fun (_) -> t_boolean() end); +type(erlang, 'xor', 2, Xs) -> + strict(erlang, 'xor', 2, Xs, fun (_) -> t_boolean() end); +type(erlang, 'not', 1, Xs) -> + strict(erlang, 'not', 1, Xs, fun (_) -> t_boolean() end); +type(erlang, 'band', 2, Xs) -> strict(erlang, 'band', 2, Xs, fun ([X1, X2]) -> - case arith('band', X1, X2, Opaques) of + case arith('band', X1, X2) of error -> t_integer(); {ok, T} -> T end - end, Opaques); + end); %% The result is not wider than the smallest argument. We need to %% kill any value-sets in the result. %% strict(erlang, 'band', 2, Xs, -%% fun ([X1, X2]) -> t_sup(t_inf(X1, X2, Opaques), t_byte()) end, Opaques); -type(erlang, 'bor', 2, Xs, Opaques) -> +%% fun ([X1, X2]) -> t_sup(t_inf(X1, X2), t_byte()) end); +type(erlang, 'bor', 2, Xs) -> strict(erlang, 'bor', 2, Xs, fun ([X1, X2]) -> - case arith('bor', X1, X2, Opaques) of + case arith('bor', X1, X2) of error -> t_integer(); {ok, T} -> T end - end, Opaques); + end); %% The result is not wider than the largest argument. We need to %% kill any value-sets in the result. %% strict(erlang, 'bor', 2, Xs, -%% fun ([X1, X2]) -> t_sup(t_sup(X1, X2), t_byte()) end, Opaques); -type(erlang, 'bxor', 2, Xs, Opaques) -> +%% fun ([X1, X2]) -> t_sup(t_sup(X1, X2), t_byte()) end); +type(erlang, 'bxor', 2, Xs) -> strict(erlang, 'bxor', 2, Xs, fun ([X1, X2]) -> - case arith('bxor', X1, X2, Opaques) of + case arith('bxor', X1, X2) of error -> t_integer(); {ok, T} -> T end - end, Opaques); + end); %% The result is not wider than the largest argument. We need to %% kill any value-sets in the result. %% strict(erlang, 'bxor', 2, Xs, -%% fun ([X1, X2]) -> t_sup(t_sup(X1, X2), t_byte()) end, Opaques); -type(erlang, 'bsr', 2, Xs, Opaques) -> +%% fun ([X1, X2]) -> t_sup(t_sup(X1, X2), t_byte()) end); +type(erlang, 'bsr', 2, Xs) -> strict(erlang, 'bsr', 2, Xs, fun ([X1, X2]) -> - case arith('bsr', X1, X2, Opaques) of + case arith('bsr', X1, X2) of error -> t_integer(); {ok, T} -> T end - end, Opaques); + end); %% If the first argument is unsigned (which is the case for %% characters and bytes), the result is never wider. We need to kill %% any value-sets in the result. %% strict(erlang, 'bsr', 2, Xs, -%% fun ([X, _]) -> t_sup(X, t_byte()) end, Opaques); -type(erlang, 'bsl', 2, Xs, Opaques) -> +%% fun ([X, _]) -> t_sup(X, t_byte()) end); +type(erlang, 'bsl', 2, Xs) -> strict(erlang, 'bsl', 2, Xs, fun ([X1, X2]) -> - case arith('bsl', X1, X2, Opaques) of + case arith('bsl', X1, X2) of error -> t_integer(); {ok, T} -> T end - end, Opaques); + end); %% Not worth doing anything special here. -%% strict(erlang, 'bsl', 2, Xs, fun (_) -> t_integer() end, Opaques); -type(erlang, 'bnot', 1, Xs, Opaques) -> +%% strict(erlang, 'bsl', 2, Xs, fun (_) -> t_integer() end); +type(erlang, 'bnot', 1, Xs) -> strict(erlang, 'bnot', 1, Xs, fun ([X1]) -> - case arith_bnot(X1, Opaques) of + case arith_bnot(X1) of error -> t_integer(); {ok, T} -> T end - end, Opaques); + end); %% Guard bif, needs to be here. -type(erlang, abs, 1, Xs, Opaques) -> +type(erlang, abs, 1, Xs) -> strict(erlang, abs, 1, Xs, - fun ([X1]) -> arith_abs(X1, Opaques) end, Opaques); + fun ([X1]) -> arith_abs(X1) end); %% This returns (-X)-1, so it often gives a negative result. -%% strict(erlang, 'bnot', 1, Xs, fun (_) -> t_integer() end, Opaques); -type(erlang, append, 2, Xs, _Opaques) -> type(erlang, '++', 2, Xs); % alias -type(erlang, apply, 2, Xs, Opaques) -> +%% strict(erlang, 'bnot', 1, Xs, fun (_) -> t_integer() end); +type(erlang, append, 2, Xs) -> type(erlang, '++', 2, Xs); % alias +type(erlang, apply, 2, Xs) -> Fun = fun ([X, _Y]) -> - case t_is_fun(X, Opaques) of + case t_is_fun(X) of true -> - t_fun_range(X, Opaques); + t_fun_range(X); false -> t_any() end end, - strict(erlang, apply, 2, Xs, Fun, Opaques); -type(erlang, apply, 3, Xs, Opaques) -> - strict(erlang, apply, 3, Xs, fun (_) -> t_any() end, Opaques); + strict(erlang, apply, 2, Xs, Fun); +type(erlang, apply, 3, Xs) -> + strict(erlang, apply, 3, Xs, fun (_) -> t_any() end); %% Guard bif, needs to be here. -type(erlang, binary_part, 2, Xs, Opaques) -> - strict(erlang, binary_part, 2, Xs, fun (_) -> t_binary() end, Opaques); +type(erlang, binary_part, 2, Xs) -> + strict(erlang, binary_part, 2, Xs, fun (_) -> t_binary() end); %% Guard bif, needs to be here. -type(erlang, binary_part, 3, Xs, Opaques) -> - strict(erlang, binary_part, 3, Xs, fun (_) -> t_binary() end, Opaques); +type(erlang, binary_part, 3, Xs) -> + strict(erlang, binary_part, 3, Xs, fun (_) -> t_binary() end); %% Guard bif, needs to be here. -type(erlang, bit_size, 1, Xs, Opaques) -> +type(erlang, bit_size, 1, Xs) -> strict(erlang, bit_size, 1, Xs, - fun (_) -> t_non_neg_integer() end, Opaques); + fun (_) -> t_non_neg_integer() end); %% Guard bif, needs to be here. -type(erlang, byte_size, 1, Xs, Opaques) -> +type(erlang, byte_size, 1, Xs) -> strict(erlang, byte_size, 1, Xs, - fun (_) -> t_non_neg_integer() end, Opaques); + fun (_) -> t_non_neg_integer() end); %% Guard bif, needs to be here. -type(erlang, ceil, 1, Xs, Opaques) -> - strict(erlang, ceil, 1, Xs, fun (_) -> t_integer() end, Opaques); +type(erlang, ceil, 1, Xs) -> + strict(erlang, ceil, 1, Xs, fun (_) -> t_integer() end); %% Guard bif, needs to be here. %% Also much more expressive than anything you could write in a spec... -type(erlang, element, 2, Xs, Opaques) -> +type(erlang, element, 2, Xs) -> strict(erlang, element, 2, Xs, fun ([X1, X2]) -> - case t_tuple_subtypes(X2, Opaques) of + case t_tuple_subtypes(X2) of unknown -> t_any(); [_] -> - Sz = t_tuple_size(X2, Opaques), - As = t_tuple_args(X2, Opaques), - case t_number_vals(X1, Opaques) of + Sz = t_tuple_size(X2), + As = t_tuple_args(X2), + case t_number_vals(X1) of unknown -> t_sup(As); Ns when is_list(Ns) -> Fun = fun @@ -578,15 +568,15 @@ type(erlang, element, 2, Xs, Opaques) -> Ts when is_list(Ts) -> t_sup([type(erlang, element, 2, [X1, Y]) || Y <- Ts]) end - end, Opaques); + end); %% Guard bif, needs to be here. -type(erlang, float, 1, Xs, Opaques) -> - strict(erlang, float, 1, Xs, fun (_) -> t_float() end, Opaques); +type(erlang, float, 1, Xs) -> + strict(erlang, float, 1, Xs, fun (_) -> t_float() end); %% Guard bif, needs to be here. -type(erlang, floor, 1, Xs, Opaques) -> - strict(erlang, floor, 1, Xs, fun (_) -> t_integer() end, Opaques); +type(erlang, floor, 1, Xs) -> + strict(erlang, floor, 1, Xs, fun (_) -> t_integer() end); %% Primop, needs to be somewhere. -type(erlang, build_stacktrace, 0, _, _Opaques) -> +type(erlang, build_stacktrace, 0, _) -> t_list(t_tuple([t_module(), t_atom(), t_sup([t_arity(),t_list()]), @@ -594,156 +584,144 @@ type(erlang, build_stacktrace, 0, _, _Opaques) -> t_tuple([t_atom('file'),t_string()]), t_tuple([t_atom('line'),t_pos_integer()])]))])); %% Guard bif, needs to be here. -type(erlang, hd, 1, Xs, Opaques) -> - strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end, Opaques); -type(erlang, info, 1, Xs, _) -> type(erlang, system_info, 1, Xs); % alias +type(erlang, hd, 1, Xs) -> + strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end); +type(erlang, info, 1, Xs) -> type(erlang, system_info, 1, Xs); % alias %% All type tests are guard BIF's and may be implemented in ways that %% cannot be expressed in a type spec, why they are kept in erl_bif_types. -type(erlang, is_atom, 1, Xs, Opaques) -> +type(erlang, is_atom, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_atom(Y, Opaques) end, - t_atom(), Opaques) + check_guard(X, fun (Y) -> t_is_atom(Y) end, + t_atom()) end, - strict(erlang, is_atom, 1, Xs, Fun, Opaques); -type(erlang, is_binary, 1, Xs, Opaques) -> + strict(erlang, is_atom, 1, Xs, Fun); +type(erlang, is_binary, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_binary(Y, Opaques) end, - t_binary(), Opaques) + check_guard(X, fun (Y) -> t_is_binary(Y) end, + t_binary()) end, - strict(erlang, is_binary, 1, Xs, Fun, Opaques); -type(erlang, is_bitstring, 1, Xs, Opaques) -> + strict(erlang, is_binary, 1, Xs, Fun); +type(erlang, is_bitstring, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_bitstr(Y, Opaques) end, - t_bitstr(), Opaques) + check_guard(X, fun (Y) -> t_is_bitstr(Y) end, + t_bitstr()) end, - strict(erlang, is_bitstring, 1, Xs, Fun, Opaques); -type(erlang, is_boolean, 1, Xs, Opaques) -> + strict(erlang, is_bitstring, 1, Xs, Fun); +type(erlang, is_boolean, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_boolean(Y, Opaques) end, - t_boolean(), Opaques) + check_guard(X, fun (Y) -> t_is_boolean(Y) end, + t_boolean()) end, - strict(erlang, is_boolean, 1, Xs, Fun, Opaques); -type(erlang, is_float, 1, Xs, Opaques) -> + strict(erlang, is_boolean, 1, Xs, Fun); +type(erlang, is_float, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_float(Y, Opaques) end, - t_float(), Opaques) + check_guard(X, fun (Y) -> t_is_float(Y) end, + t_float()) end, - strict(erlang, is_float, 1, Xs, Fun, Opaques); -type(erlang, is_function, 1, Xs, Opaques) -> + strict(erlang, is_float, 1, Xs, Fun); +type(erlang, is_function, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_fun(Y, Opaques) end, - t_fun(), Opaques) + check_guard(X, fun (Y) -> t_is_fun(Y) end, + t_fun()) end, - strict(erlang, is_function, 1, Xs, Fun, Opaques); -type(erlang, is_function, 2, Xs, Opaques) -> + strict(erlang, is_function, 1, Xs, Fun); +type(erlang, is_function, 2, Xs) -> Fun = fun ([FunType, ArityType]) -> - case t_number_vals(ArityType, Opaques) of + case t_number_vals(ArityType) of unknown -> t_boolean(); [Val] -> FunConstr = t_fun(any_list(Val), t_any()), Fun2 = fun (X) -> t_is_subtype(X, FunConstr) andalso (not t_is_none(X)) end, - check_guard_single(FunType, Fun2, FunConstr, Opaques); + check_guard_single(FunType, Fun2, FunConstr); IntList when is_list(IntList) -> t_boolean() %% true? end end, - strict(erlang, is_function, 2, Xs, Fun, Opaques); -type(erlang, is_integer, 1, Xs, Opaques) -> + strict(erlang, is_function, 2, Xs, Fun); +type(erlang, is_integer, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_integer(Y, Opaques) end, - t_integer(), Opaques) + check_guard(X, fun (Y) -> t_is_integer(Y) end, + t_integer()) end, - strict(erlang, is_integer, 1, Xs, Fun, Opaques); -type(erlang, is_list, 1, Xs, Opaques) -> + strict(erlang, is_integer, 1, Xs, Fun); +type(erlang, is_list, 1, Xs) -> Fun = fun (X) -> - Fun2 = fun (Y) -> t_is_maybe_improper_list(Y, Opaques) end, - check_guard(X, Fun2, t_maybe_improper_list(), Opaques) + Fun2 = fun (Y) -> t_is_maybe_improper_list(Y) end, + check_guard(X, Fun2, t_maybe_improper_list()) end, - strict(erlang, is_list, 1, Xs, Fun, Opaques); -type(erlang, is_map, 1, Xs, Opaques) -> + strict(erlang, is_list, 1, Xs, Fun); +type(erlang, is_map, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_map(Y, Opaques) end, - t_map(), Opaques) end, - strict(erlang, is_map, 1, Xs, Fun, Opaques); -type(erlang, is_map_key, 2, Xs, Opaques) -> - type(maps, is_key, 2, Xs, Opaques); -type(erlang, is_number, 1, Xs, Opaques) -> + check_guard(X, fun (Y) -> t_is_map(Y) end, + t_map()) end, + strict(erlang, is_map, 1, Xs, Fun); +type(erlang, is_map_key, 2, Xs) -> + type(maps, is_key, 2, Xs); +type(erlang, is_number, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_number(Y, Opaques) end, - t_number(), Opaques) + check_guard(X, fun (Y) -> t_is_number(Y) end, + t_number()) end, - strict(erlang, is_number, 1, Xs, Fun, Opaques); -type(erlang, is_pid, 1, Xs, Opaques) -> + strict(erlang, is_number, 1, Xs, Fun); +type(erlang, is_pid, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_pid(Y, Opaques) end, - t_pid(), Opaques) + check_guard(X, fun (Y) -> t_is_pid(Y) end, + t_pid()) end, - strict(erlang, is_pid, 1, Xs, Fun, Opaques); -type(erlang, is_port, 1, Xs, Opaques) -> + strict(erlang, is_pid, 1, Xs, Fun); +type(erlang, is_port, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_port(Y, Opaques) end, - t_port(), Opaques) + check_guard(X, fun (Y) -> t_is_port(Y) end, + t_port()) end, - strict(erlang, is_port, 1, Xs, Fun, Opaques); -type(erlang, is_record, 2, Xs, Opaques) -> + strict(erlang, is_port, 1, Xs, Fun); +type(erlang, is_record, 2, Xs) -> Fun = fun ([X, Y]) -> - case t_is_tuple(X, Opaques) of + case t_is_tuple(X) of false -> - case t_is_none(t_inf(t_tuple(), X, Opaques)) of - true -> - case t_has_opaque_subtype(X, Opaques) of - true -> t_none(); - false -> t_atom('false') - end; + case t_is_none(t_inf(t_tuple(), X)) of + true -> t_atom('false'); false -> t_boolean() end; true -> - case t_tuple_subtypes(X, Opaques) of + case t_tuple_subtypes(X) of unknown -> t_boolean(); [Tuple] -> - case t_tuple_args(Tuple, Opaques) of + case t_tuple_args(Tuple) of %% any -> t_boolean(); - [Tag|_] -> check_record_tag(Tag, Y, Opaques) + [Tag|_] -> check_record_tag(Tag, Y) end; List when length(List) >= 2 -> t_sup([type(erlang, is_record, 2, [T, Y]) || T <- List]) end end end, - strict(erlang, is_record, 2, Xs, Fun, Opaques); -type(erlang, is_record, 3, Xs, Opaques) -> + strict(erlang, is_record, 2, Xs, Fun); +type(erlang, is_record, 3, Xs) -> Fun = fun ([X, Y, Z]) -> - Arity = t_number_vals(Z, Opaques), - case t_is_tuple(X, Opaques) of + Arity = t_number_vals(Z), + case t_is_tuple(X) of false when length(Arity) =:= 1 -> [RealArity] = Arity, - case t_is_none(t_inf(t_tuple(RealArity), X, Opaques)) of - true -> - case t_has_opaque_subtype(X, Opaques) of - true -> t_none(); - false -> t_atom('false') - end; + case t_is_none(t_inf(t_tuple(RealArity), X)) of + true -> t_atom('false'); false -> t_boolean() end; false -> - case t_is_none(t_inf(t_tuple(), X, Opaques)) of - true -> - case t_has_opaque_subtype(X, Opaques) of - true -> t_none(); - false -> t_atom('false') - end; + case t_is_none(t_inf(t_tuple(), X)) of + true -> t_atom('false'); false -> t_boolean() end; true when length(Arity) =:= 1 -> [RealArity] = Arity, - case t_tuple_subtypes(X, Opaques) of + case t_tuple_subtypes(X) of unknown -> t_boolean(); [Tuple] -> - case t_tuple_args(Tuple, Opaques) of + case t_tuple_args(Tuple) of %% any -> t_boolean(); Args when length(Args) =:= RealArity -> - check_record_tag(hd(Args), Y, Opaques); + check_record_tag(hd(Args), Y); Args when length(Args) =/= RealArity -> t_atom('false') end; @@ -754,36 +732,34 @@ type(erlang, is_record, 3, Xs, Opaques) -> t_boolean() end end, - strict(erlang, is_record, 3, Xs, Fun, Opaques); -type(erlang, is_reference, 1, Xs, Opaques) -> + strict(erlang, is_record, 3, Xs, Fun); +type(erlang, is_reference, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_reference(Y, Opaques) end, - t_reference(), Opaques) + check_guard(X, fun (Y) -> t_is_reference(Y) end, + t_reference()) end, - strict(erlang, is_reference, 1, Xs, Fun, Opaques); -type(erlang, is_tuple, 1, Xs, Opaques) -> + strict(erlang, is_reference, 1, Xs, Fun); +type(erlang, is_tuple, 1, Xs) -> Fun = fun (X) -> - check_guard(X, fun (Y) -> t_is_tuple(Y, Opaques) end, - t_tuple(), Opaques) + check_guard(X, fun (Y) -> t_is_tuple(Y) end, + t_tuple()) end, - strict(erlang, is_tuple, 1, Xs, Fun, Opaques); + strict(erlang, is_tuple, 1, Xs, Fun); %% Guard bif, needs to be here. -type(erlang, length, 1, Xs, Opaques) -> - strict(erlang, length, 1, Xs, fun (_) -> t_non_neg_fixnum() end, Opaques); +type(erlang, length, 1, Xs) -> + strict(erlang, length, 1, Xs, fun (_) -> t_non_neg_fixnum() end); %% Guard bif, needs to be here. -type(erlang, map_size, 1, Xs, Opaques) -> - type(maps, size, 1, Xs, Opaques); -type(erlang, max, 2, Xs, Opaques) -> - strict(erlang, max, 2, Xs, - fun([A, B]) -> t_sup(A, B) end, - Opaques); +type(erlang, map_size, 1, Xs) -> + type(maps, size, 1, Xs); +type(erlang, max, 2, Xs) -> + strict(erlang, max, 2, Xs, fun([A, B]) -> t_sup(A, B) end); %% Guard bif, needs to be here. -type(erlang, map_get, 2, Xs, Opaques) -> - type(maps, get, 2, Xs, Opaques); -type(erlang, make_fun, 3, Xs, Opaques) -> +type(erlang, map_get, 2, Xs) -> + type(maps, get, 2, Xs); +type(erlang, make_fun, 3, Xs) -> strict(erlang, make_fun, 3, Xs, fun ([_, _, Arity]) -> - case t_number_vals(Arity, Opaques) of + case t_number_vals(Arity) of [N] -> case is_integer(N) andalso 0 =< N andalso N =< 255 of true -> t_fun(N, t_any()); @@ -791,58 +767,56 @@ type(erlang, make_fun, 3, Xs, Opaques) -> end; _Other -> t_fun() end - end, Opaques); -type(erlang, make_tuple, 2, Xs, Opaques) -> + end); +type(erlang, make_tuple, 2, Xs) -> strict(erlang, make_tuple, 2, Xs, fun ([Int, _]) -> - case t_number_vals(Int, Opaques) of + case t_number_vals(Int) of [N] when is_integer(N), N >= 0 -> t_tuple(N); _Other -> t_tuple() end - end, Opaques); -type(erlang, make_tuple, 3, Xs, Opaques) -> + end); +type(erlang, make_tuple, 3, Xs) -> strict(erlang, make_tuple, 3, Xs, fun ([Int, _, _]) -> - case t_number_vals(Int, Opaques) of + case t_number_vals(Int) of [N] when is_integer(N), N >= 0 -> t_tuple(N); _Other -> t_tuple() end - end, Opaques); -type(erlang, min, 2, Xs, Opaques) -> - strict(erlang, min, 2, Xs, - fun([A, B]) -> t_sup(A, B) end, - Opaques); -type(erlang, nif_error, 1, Xs, Opaques) -> + end); +type(erlang, min, 2, Xs) -> + strict(erlang, min, 2, Xs, fun([A, B]) -> t_sup(A, B) end); +type(erlang, nif_error, 1, Xs) -> %% this BIF and the next one are stubs for NIFs and never return - strict(erlang, nif_error, 1, Xs, fun (_) -> t_any() end, Opaques); -type(erlang, nif_error, 2, Xs, Opaques) -> - strict(erlang, nif_error, 2, Xs, fun (_) -> t_any() end, Opaques); + strict(erlang, nif_error, 1, Xs, fun (_) -> t_any() end); +type(erlang, nif_error, 2, Xs) -> + strict(erlang, nif_error, 2, Xs, fun (_) -> t_any() end); %% Guard bif, needs to be here. -type(erlang, node, 0, _, _Opaques) -> t_node(); +type(erlang, node, 0, _) -> t_node(); %% Guard bif, needs to be here. -type(erlang, node, 1, Xs, Opaques) -> - strict(erlang, node, 1, Xs, fun (_) -> t_node() end, Opaques); -type(erlang, raise, 3, Xs, Opaques) -> +type(erlang, node, 1, Xs) -> + strict(erlang, node, 1, Xs, fun (_) -> t_node() end); +type(erlang, raise, 3, Xs) -> Ts = arg_types(erlang, raise, 3), - Xs1 = inf_lists(Xs, Ts, Opaques), + Xs1 = t_inf_lists(Xs, Ts), case any_is_none_or_unit(Xs1) of true -> t_atom('badarg'); false -> t_none() end; %% Guard bif, needs to be here. -type(erlang, round, 1, Xs, Opaques) -> - strict(erlang, round, 1, Xs, fun (_) -> t_integer() end, Opaques); +type(erlang, round, 1, Xs) -> + strict(erlang, round, 1, Xs, fun (_) -> t_integer() end); %% Guard bif, needs to be here. -type(erlang, self, 0, _, _Opaques) -> t_pid(); -type(erlang, setelement, 3, Xs, Opaques) -> +type(erlang, self, 0, _) -> t_pid(); +type(erlang, setelement, 3, Xs) -> strict(erlang, setelement, 3, Xs, fun ([X1, X2, X3]) -> - case t_tuple_subtypes(X2, Opaques) of + case t_tuple_subtypes(X2) of unknown -> t_tuple(); [_] -> - Sz = t_tuple_size(X2, Opaques), - As = t_tuple_args(X2, Opaques), - case t_number_vals(X1, Opaques) of + Sz = t_tuple_size(X2), + As = t_tuple_args(X2), + case t_number_vals(X1) of unknown -> t_tuple([t_sup(X, X3) || X <- As]); [N] when is_integer(N), 1 =< N, N =< Sz -> @@ -864,17 +838,17 @@ type(erlang, setelement, 3, Xs, Opaques) -> Ts when is_list(Ts) -> t_sup([type(erlang, setelement, 3, [X1, Y, X3]) || Y <- Ts]) end - end, Opaques); + end); %% Guard bif, needs to be here. -type(erlang, size, 1, Xs, Opaques) -> - strict(erlang, size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques); -type(erlang, subtract, 2, Xs, _Opaques) -> type(erlang, '--', 2, Xs); % alias -type(erlang, system_info, 1, Xs, Opaques) -> +type(erlang, size, 1, Xs) -> + strict(erlang, size, 1, Xs, fun (_) -> t_non_neg_integer() end); +type(erlang, subtract, 2, Xs) -> type(erlang, '--', 2, Xs); % alias +type(erlang, system_info, 1, Xs) -> strict(erlang, system_info, 1, Xs, fun ([Type]) -> - case t_is_atom(Type, Opaques) of + case t_is_atom(Type) of true -> - case t_atom_vals(Type, Opaques) of + case t_atom_vals(Type) of ['allocated_areas'] -> t_list(t_sup([t_tuple([t_atom(),t_non_neg_integer()]), t_tuple([t_atom(), @@ -986,28 +960,28 @@ type(erlang, system_info, 1, Xs, Opaques) -> false -> %% This currently handles only {allocator, Alloc} t_any() %% overapproximation as the return value might change end - end, Opaques); + end); %% Guard bif, needs to be here. -type(erlang, tl, 1, Xs, Opaques) -> - strict(erlang, tl, 1, Xs, fun ([X]) -> t_cons_tl(X) end, Opaques); +type(erlang, tl, 1, Xs) -> + strict(erlang, tl, 1, Xs, fun ([X]) -> t_cons_tl(X) end); %% Guard bif, needs to be here. -type(erlang, trunc, 1, Xs, Opaques) -> - strict(erlang, trunc, 1, Xs, fun (_) -> t_integer() end, Opaques); +type(erlang, trunc, 1, Xs) -> + strict(erlang, trunc, 1, Xs, fun (_) -> t_integer() end); %% Guard bif, needs to be here. -type(erlang, tuple_size, 1, Xs, Opaques) -> +type(erlang, tuple_size, 1, Xs) -> strict(erlang, tuple_size, 1, Xs, - fun (_) -> t_non_neg_integer() end, Opaques); -type(erlang, tuple_to_list, 1, Xs, Opaques) -> + fun (_) -> t_non_neg_integer() end); +type(erlang, tuple_to_list, 1, Xs) -> strict(erlang, tuple_to_list, 1, Xs, fun ([X]) -> - case t_tuple_subtypes(X, Opaques) of + case t_tuple_subtypes(X) of unknown -> t_list(); SubTypes -> - Args = lists:append([t_tuple_args(ST, Opaques) || + Args = lists:append([t_tuple_args(ST) || ST <- SubTypes]), %% Can be nil if the tuple can be {} case lists:any(fun (T) -> - t_tuple_size(T, Opaques) =:= 0 + t_tuple_size(T) =:= 0 end, SubTypes) of true -> %% Be careful here. If we had only {} we need to @@ -1017,105 +991,105 @@ type(erlang, tuple_to_list, 1, Xs, Opaques) -> t_nonempty_list(t_sup(Args)) end end - end, Opaques); + end); %%-- lists -------------------------------------------------------------------- -type(lists, all, 2, Xs, Opaques) -> +type(lists, all, 2, Xs) -> strict(lists, all, 2, Xs, fun ([F, L]) -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> t_atom('true'); false -> - El = t_list_elements(L, Opaques), - case check_fun_application(F, [El], Opaques) of + El = t_list_elements(L), + case check_fun_application(F, [El]) of ok -> - case t_is_cons(L, Opaques) of - true -> t_fun_range(F, Opaques); + case t_is_cons(L) of + true -> t_fun_range(F); false -> %% The list can be empty. - t_sup(t_atom('true'), t_fun_range(F, Opaques)) + t_sup(t_atom('true'), t_fun_range(F)) end; error -> - case t_is_cons(L, Opaques) of + case t_is_cons(L) of true -> t_none(); - false -> t_fun_range(F, Opaques) + false -> t_fun_range(F) end end end - end, Opaques); -type(lists, any, 2, Xs, Opaques) -> + end); +type(lists, any, 2, Xs) -> strict(lists, any, 2, Xs, fun ([F, L]) -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> t_atom('false'); false -> - El = t_list_elements(L, Opaques), - case check_fun_application(F, [El], Opaques) of + El = t_list_elements(L), + case check_fun_application(F, [El]) of ok -> - case t_is_cons(L, Opaques) of - true -> t_fun_range(F, Opaques); + case t_is_cons(L) of + true -> t_fun_range(F); false -> %% The list can be empty - t_sup(t_atom('false'), t_fun_range(F, Opaques)) + t_sup(t_atom('false'), t_fun_range(F)) end; error -> - case t_is_cons(L, Opaques) of + case t_is_cons(L) of true -> t_none(); - false -> t_fun_range(F, Opaques) + false -> t_fun_range(F) end end end - end, Opaques); -type(lists, append, 2, Xs, _Opaques) -> type(erlang, '++', 2, Xs); % alias -type(lists, delete, 2, Xs, Opaques) -> + end); +type(lists, append, 2, Xs) -> type(erlang, '++', 2, Xs); % alias +type(lists, delete, 2, Xs) -> strict(lists, delete, 2, Xs, fun ([_, List]) -> - case t_is_cons(List, Opaques) of + case t_is_cons(List) of true -> t_cons_tl(List); false -> List end - end, Opaques); -type(lists, dropwhile, 2, Xs, Opaques) -> + end); +type(lists, dropwhile, 2, Xs) -> strict(lists, dropwhile, 2, Xs, fun ([F, X]) -> - case t_is_nil(X, Opaques) of + case t_is_nil(X) of true -> t_nil(); false -> - X1 = t_list_elements(X, Opaques), - case check_fun_application(F, [X1], Opaques) of + X1 = t_list_elements(X), + case check_fun_application(F, [X1]) of ok -> - case t_atom_vals(t_fun_range(F, Opaques), Opaques) of + case t_atom_vals(t_fun_range(F)) of ['true'] -> - case t_is_none(t_inf(t_list(), X, Opaques)) of + case t_is_none(t_inf(t_list(), X)) of true -> t_none(); false -> t_nil() end; ['false'] -> - case t_is_none(t_inf(t_list(), X, Opaques)) of + case t_is_none(t_inf(t_list(), X)) of true -> t_none(); false -> X end; _ -> - t_inf(t_cons_tl(t_inf(X, t_cons(), Opaques)), - t_maybe_improper_list(), Opaques) + t_inf(t_cons_tl(t_inf(X, t_cons())), + t_maybe_improper_list()) end; error -> - case t_is_cons(X, Opaques) of + case t_is_cons(X) of true -> t_none(); false -> t_nil() end end end - end, Opaques); -type(lists, filter, 2, Xs, Opaques) -> + end); +type(lists, filter, 2, Xs) -> strict(lists, filter, 2, Xs, fun ([F, L]) -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> t_nil(); false -> - T = t_list_elements(L, Opaques), - case check_fun_application(F, [T], Opaques) of + T = t_list_elements(L), + case check_fun_application(F, [T]) of ok -> - RangeVals = t_atom_vals(t_fun_range(F, Opaques), Opaques), + RangeVals = t_atom_vals(t_fun_range(F)), case RangeVals =:= ['false'] of true -> t_nil(); false -> @@ -1125,47 +1099,46 @@ type(lists, filter, 2, Xs, Opaques) -> end end; error -> - case t_is_cons(L, Opaques) of + case t_is_cons(L) of true -> t_none(); false -> t_nil() end end end - end, Opaques); -type(lists, flatten, 1, Xs, Opaques) -> + end); +type(lists, flatten, 1, Xs) -> strict(lists, flatten, 1, Xs, fun ([L]) -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> L; % (nil has undefined elements) false -> %% Avoiding infinite recursion is tricky - X1 = t_list_elements(L, Opaques), + X1 = t_list_elements(L), case t_is_any(X1) of true -> t_list(); false -> - X2 = type(lists, flatten, 1, [t_inf(X1, t_list(), Opaques)]), + X2 = type(lists, flatten, 1, [t_inf(X1, t_list())]), t_sup(t_list(t_subtract(X1, t_list())), X2) end end - end, Opaques); -type(lists, flatmap, 2, Xs, Opaques) -> + end); +type(lists, flatmap, 2, Xs) -> strict(lists, flatmap, 2, Xs, fun ([F, List]) -> - case t_is_nil(List, Opaques) of + case t_is_nil(List) of true -> t_nil(); false -> case - check_fun_application(F, [t_list_elements(List, Opaques)], - Opaques) + check_fun_application(F, [t_list_elements(List)]) of ok -> - R = t_fun_range(F, Opaques), + R = t_fun_range(F), case t_is_nil(R) of true -> t_nil(); false -> - Elems = t_list_elements(R, Opaques), - case t_is_cons(List, Opaques) of + Elems = t_list_elements(R), + case t_is_cons(List) of true -> case t_is_subtype(t_nil(), R) of true -> t_list(Elems); @@ -1175,21 +1148,20 @@ type(lists, flatmap, 2, Xs, Opaques) -> end end; error -> - case t_is_cons(List, Opaques) of + case t_is_cons(List) of true -> t_none(); false -> t_nil() end end end - end, Opaques); -type(lists, foreach, 2, Xs, Opaques) -> + end); +type(lists, foreach, 2, Xs) -> strict(lists, foreach, 2, Xs, fun ([F, List]) -> - case t_is_cons(List, Opaques) of + case t_is_cons(List) of true -> case - check_fun_application(F, [t_list_elements(List, Opaques)], - Opaques) + check_fun_application(F, [t_list_elements(List)]) of ok -> t_atom('ok'); error -> t_none() @@ -1197,43 +1169,42 @@ type(lists, foreach, 2, Xs, Opaques) -> false -> t_atom('ok') end - end, Opaques); -type(lists, foldl, 3, Xs, Opaques) -> + end); +type(lists, foldl, 3, Xs) -> strict(lists, foldl, 3, Xs, fun ([F, Acc, List]) -> - case t_is_nil(List, Opaques) of + case t_is_nil(List) of true -> Acc; false -> case check_fun_application(F, - [t_list_elements(List, Opaques),Acc], - Opaques) + [t_list_elements(List),Acc]) of ok -> - case t_is_cons(List, Opaques) of - true -> t_fun_range(F, Opaques); - false -> t_sup(t_fun_range(F, Opaques), Acc) + case t_is_cons(List) of + true -> t_fun_range(F); + false -> t_sup(t_fun_range(F), Acc) end; error -> - case t_is_cons(List, Opaques) of + case t_is_cons(List) of true -> t_none(); false -> Acc end end end - end, Opaques); -type(lists, foldr, 3, Xs, _Opaques) -> type(lists, foldl, 3, Xs); % same -type(lists, keydelete, 3, Xs, Opaques) -> + end); +type(lists, foldr, 3, Xs) -> type(lists, foldl, 3, Xs); % same +type(lists, keydelete, 3, Xs) -> strict(lists, keydelete, 3, Xs, fun ([_, _, L]) -> - Term = t_list_termination(L, Opaques), - t_sup(Term, erl_types:lift_list_to_pos_empty(L, Opaques)) - end, Opaques); -type(lists, keyfind, 3, Xs, Opaques) -> + Term = t_list_termination(L), + t_sup(Term, erl_types:lift_list_to_pos_empty(L)) + end); +type(lists, keyfind, 3, Xs) -> strict(lists, keyfind, 3, Xs, fun ([X, Y, Z]) -> - ListEs = t_list_elements(Z, Opaques), - Tuple = t_inf(t_tuple(), ListEs, Opaques), + ListEs = t_list_elements(Z), + Tuple = t_inf(t_tuple(), ListEs), case t_is_none(Tuple) of true -> t_atom('false'); false -> @@ -1243,61 +1214,61 @@ type(lists, keyfind, 3, Xs, Opaques) -> case t_is_any(X) of true -> Ret; false -> - case t_tuple_subtypes(Tuple, Opaques) of + case t_tuple_subtypes(Tuple) of unknown -> Ret; List -> - case key_comparisons_fail(X, Y, List, Opaques) of + case key_comparisons_fail(X, Y, List) of true -> t_atom('false'); false -> Ret end end end end - end, Opaques); -type(lists, keymap, 3, Xs, Opaques) -> + end); +type(lists, keymap, 3, Xs) -> strict(lists, keymap, 3, Xs, fun ([F, _I, L]) -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> L; - false -> t_list(t_sup(t_fun_range(F, Opaques), - t_list_elements(L, Opaques))) + false -> t_list(t_sup(t_fun_range(F), + t_list_elements(L))) end - end, Opaques); -type(lists, keymember, 3, Xs, Opaques) -> + end); +type(lists, keymember, 3, Xs) -> strict(lists, keymember, 3, Xs, fun ([X, Y, Z]) -> - ListEs = t_list_elements(Z, Opaques), - Tuple = t_inf(t_tuple(), ListEs, Opaques), + ListEs = t_list_elements(Z), + Tuple = t_inf(t_tuple(), ListEs), case t_is_none(Tuple) of true -> t_atom('false'); false -> case t_is_any(X) of true -> t_boolean(); false -> - case t_tuple_subtypes(Tuple, Opaques) of + case t_tuple_subtypes(Tuple) of unknown -> t_boolean(); List -> - case key_comparisons_fail(X, Y, List, Opaques) of + case key_comparisons_fail(X, Y, List) of true -> t_atom('false'); false -> t_boolean() end end end end - end, Opaques); -type(lists, keymerge, 3, Xs, Opaques) -> + end); +type(lists, keymerge, 3, Xs) -> strict(lists, keymerge, 3, Xs, - fun ([_I, L1, L2]) -> type(lists, merge, 2, [L1, L2]) end, Opaques); -type(lists, keyreplace, 4, Xs, Opaques) -> + fun ([_I, L1, L2]) -> type(lists, merge, 2, [L1, L2]) end); +type(lists, keyreplace, 4, Xs) -> strict(lists, keyreplace, 4, Xs, fun ([_K, _I, L, T]) -> - t_list(t_sup(t_list_elements(L, Opaques), T)) - end, Opaques); -type(lists, keysearch, 3, Xs, Opaques) -> + t_list(t_sup(t_list_elements(L), T)) + end); +type(lists, keysearch, 3, Xs) -> strict(lists, keysearch, 3, Xs, fun ([X, Y, Z]) -> - ListEs = t_list_elements(Z, Opaques), - Tuple = t_inf(t_tuple(), ListEs, Opaques), + ListEs = t_list_elements(Z), + Tuple = t_inf(t_tuple(), ListEs), case t_is_none(Tuple) of true -> t_atom('false'); false -> @@ -1306,92 +1277,92 @@ type(lists, keysearch, 3, Xs, Opaques) -> case t_is_any(X) of true -> Ret; false -> - case t_tuple_subtypes(Tuple, Opaques) of + case t_tuple_subtypes(Tuple) of unknown -> Ret; List -> - case key_comparisons_fail(X, Y, List, Opaques) of + case key_comparisons_fail(X, Y, List) of true -> t_atom('false'); false -> Ret end end end end - end, Opaques); -type(lists, keysort, 2, Xs, Opaques) -> - strict(lists, keysort, 2, Xs, fun ([_, L]) -> L end, Opaques); -type(lists, last, 1, Xs, Opaques) -> + end); +type(lists, keysort, 2, Xs) -> + strict(lists, keysort, 2, Xs, fun ([_, L]) -> L end); +type(lists, last, 1, Xs) -> strict(lists, last, 1, Xs, - fun ([L]) -> t_list_elements(L, Opaques) end, Opaques); -type(lists, map, 2, Xs, Opaques) -> + fun ([L]) -> t_list_elements(L) end); +type(lists, map, 2, Xs) -> strict(lists, map, 2, Xs, fun ([F, L]) -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> L; false -> - El = t_list_elements(L, Opaques), - case t_is_cons(L, Opaques) of + El = t_list_elements(L), + case t_is_cons(L) of true -> - case check_fun_application(F, [El], Opaques) of - ok -> t_nonempty_list(t_fun_range(F, Opaques)); + case check_fun_application(F, [El]) of + ok -> t_nonempty_list(t_fun_range(F)); error -> t_none() end; false -> - case check_fun_application(F, [El], Opaques) of - ok -> t_list(t_fun_range(F, Opaques)); + case check_fun_application(F, [El]) of + ok -> t_list(t_fun_range(F)); error -> t_nil() end end end - end, Opaques); -type(lists, mapfoldl, 3, Xs, Opaques) -> + end); +type(lists, mapfoldl, 3, Xs) -> strict(lists, mapfoldl, 3, Xs, fun ([F, Acc, List]) -> - case t_is_nil(List, Opaques) of + case t_is_nil(List) of true -> t_tuple([List, Acc]); false -> - El = t_list_elements(List, Opaques), - R = t_fun_range(F, Opaques), - case t_is_cons(List, Opaques) of + El = t_list_elements(List), + R = t_fun_range(F), + case t_is_cons(List) of true -> - case check_fun_application(F, [El, Acc], Opaques) of + case check_fun_application(F, [El, Acc]) of ok -> Fun = fun (RangeTuple) -> - [T1, T2] = t_tuple_args(RangeTuple, Opaques), + [T1, T2] = t_tuple_args(RangeTuple), t_tuple([t_nonempty_list(T1), T2]) end, - t_sup([Fun(ST) || ST <- t_tuple_subtypes(R, Opaques)]); + t_sup([Fun(ST) || ST <- t_tuple_subtypes(R)]); error -> t_none() end; false -> - case check_fun_application(F, [El, Acc], Opaques) of + case check_fun_application(F, [El, Acc]) of ok -> Fun = fun (RangeTuple) -> - [T1, T2] = t_tuple_args(RangeTuple, Opaques), + [T1, T2] = t_tuple_args(RangeTuple), t_tuple([t_list(T1), t_sup(Acc, T2)]) end, - t_sup([Fun(ST) || ST <- t_tuple_subtypes(R, Opaques)]); + t_sup([Fun(ST) || ST <- t_tuple_subtypes(R)]); error -> t_tuple([t_nil(), Acc]) end end end - end, Opaques); -type(lists, mapfoldr, 3, Xs, _Opaques) -> type(lists, mapfoldl, 3, Xs); % same -type(lists, max, 1, Xs, Opaques) -> + end); +type(lists, mapfoldr, 3, Xs) -> type(lists, mapfoldl, 3, Xs); % same +type(lists, max, 1, Xs) -> strict(lists, max, 1, Xs, - fun ([L]) -> t_list_elements(L, Opaques) end, Opaques); -type(lists, member, 2, Xs, Opaques) -> + fun ([L]) -> t_list_elements(L) end); +type(lists, member, 2, Xs) -> strict(lists, member, 2, Xs, fun ([X, Y]) -> - Y1 = t_list_elements(Y, Opaques), - case t_is_none(t_inf(Y1, X, Opaques)) of + Y1 = t_list_elements(Y), + case t_is_none(t_inf(Y1, X)) of true -> t_atom('false'); false -> t_boolean() end - end, Opaques); -%% type(lists, merge, 1, Xs, Opaques) -> -type(lists, merge, 2, Xs, Opaques) -> + end); +%% type(lists, merge, 1, Xs) -> +type(lists, merge, 2, Xs) -> strict(lists, merge, 2, Xs, fun ([L1, L2]) -> case t_is_none(L1) of @@ -1402,31 +1373,31 @@ type(lists, merge, 2, Xs, Opaques) -> false -> t_sup(L1, L2) end end - end, Opaques); -type(lists, min, 1, Xs, Opaques) -> + end); +type(lists, min, 1, Xs) -> strict(lists, min, 1, Xs, - fun ([L]) -> t_list_elements(L, Opaques) end, Opaques); -type(lists, nth, 2, Xs, Opaques) -> + fun ([L]) -> t_list_elements(L) end); +type(lists, nth, 2, Xs) -> strict(lists, nth, 2, Xs, - fun ([_, Y]) -> t_list_elements(Y, Opaques) end, Opaques); -type(lists, nthtail, 2, Xs, Opaques) -> + fun ([_, Y]) -> t_list_elements(Y) end); +type(lists, nthtail, 2, Xs) -> strict(lists, nthtail, 2, Xs, - fun ([_, Y]) -> t_sup(Y, t_list()) end, Opaques); -type(lists, partition, 2, Xs, Opaques) -> + fun ([_, Y]) -> t_sup(Y, t_list()) end); +type(lists, partition, 2, Xs) -> strict(lists, partition, 2, Xs, fun ([F, L]) -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> t_tuple([L,L]); false -> - El = t_list_elements(L, Opaques), - case check_fun_application(F, [El], Opaques) of + El = t_list_elements(L), + case check_fun_application(F, [El]) of error -> - case t_is_cons(L, Opaques) of + case t_is_cons(L) of true -> t_none(); false -> t_tuple([t_nil(), t_nil()]) end; ok -> - case t_atom_vals(t_fun_range(F, Opaques), Opaques) of + case t_atom_vals(t_fun_range(F)) of ['true'] -> t_tuple([L, t_nil()]); ['false'] -> t_tuple([t_nil(), L]); [_, _] -> @@ -1435,206 +1406,204 @@ type(lists, partition, 2, Xs, Opaques) -> end end end - end, Opaques); -type(lists, reverse, 1, Xs, Opaques) -> - strict(lists, reverse, 1, Xs, fun ([X]) -> X end, Opaques); -type(lists, reverse, 2, Xs, _Opaques) -> + end); +type(lists, reverse, 1, Xs) -> + strict(lists, reverse, 1, Xs, fun ([X]) -> X end); +type(lists, reverse, 2, Xs) -> type(erlang, '++', 2, Xs); % reverse-onto is just like append -type(lists, sort, 1, Xs, Opaques) -> - strict(lists, sort, 1, Xs, fun ([X]) -> X end, Opaques); -type(lists, sort, 2, Xs, Opaques) -> +type(lists, sort, 1, Xs) -> + strict(lists, sort, 1, Xs, fun ([X]) -> X end); +type(lists, sort, 2, Xs) -> strict(lists, sort, 2, Xs, fun ([F, L]) -> - R = t_fun_range(F, Opaques), - case t_is_boolean(R, Opaques) of + R = t_fun_range(F), + case t_is_boolean(R) of true -> L; false -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> t_nil(); false -> t_none() end end - end, Opaques); -type(lists, split, 2, Xs, Opaques) -> + end); +type(lists, split, 2, Xs) -> strict(lists, split, 2, Xs, fun ([_, L]) -> - case t_is_nil(L, Opaques) of + case t_is_nil(L) of true -> t_tuple([L, L]); false -> - T = t_list_elements(L, Opaques), + T = t_list_elements(L), t_tuple([t_list(T), t_list(T)]) end - end, Opaques); -type(lists, splitwith, 2, Xs, _Opaques) -> + end); +type(lists, splitwith, 2, Xs) -> T1 = type(lists, takewhile, 2, Xs), T2 = type(lists, dropwhile, 2, Xs), case t_is_none(T1) orelse t_is_none(T2) of true -> t_none(); false -> t_tuple([T1, T2]) end; -type(lists, subtract, 2, Xs, _Opaques) -> type(erlang, '--', 2, Xs); % alias -type(lists, takewhile, 2, Xs, Opaques) -> +type(lists, subtract, 2, Xs) -> type(erlang, '--', 2, Xs); % alias +type(lists, takewhile, 2, Xs) -> strict(lists, takewhile, 2, Xs, fun([F, L]) -> - case t_is_none(t_inf(t_list(), L, Opaques)) of + case t_is_none(t_inf(t_list(), L)) of false -> type(lists, filter, 2, Xs); true -> %% This works for non-proper lists as well. - El = t_list_elements(L, Opaques), + El = t_list_elements(L), type(lists, filter, 2, [F, t_list(El)]) end - end, Opaques); -type(lists, usort, 1, Xs, _Opaques) -> type(lists, sort, 1, Xs); % same -type(lists, usort, 2, Xs, _Opaques) -> type(lists, sort, 2, Xs); % same -type(lists, unzip, 1, Xs, Opaques) -> + end); +type(lists, usort, 1, Xs) -> type(lists, sort, 1, Xs); % same +type(lists, usort, 2, Xs) -> type(lists, sort, 2, Xs); % same +type(lists, unzip, 1, Xs) -> strict(lists, unzip, 1, Xs, fun ([Ps]) -> - case t_is_nil(Ps, Opaques) of + case t_is_nil(Ps) of true -> t_tuple([t_nil(), t_nil()]); false -> % Ps is a proper list of pairs - TupleTypes = t_tuple_subtypes(t_list_elements(Ps, Opaques), - Opaques), + TupleTypes = t_tuple_subtypes(t_list_elements(Ps)), lists:foldl(fun(Tuple, Acc) -> - [A, B] = t_tuple_args(Tuple, Opaques), + [A, B] = t_tuple_args(Tuple), t_sup(t_tuple([t_list(A), t_list(B)]), Acc) end, t_none(), TupleTypes) end - end, Opaques); -type(lists, unzip3, 1, Xs, Opaques) -> + end); +type(lists, unzip3, 1, Xs) -> strict(lists, unzip3, 1, Xs, fun ([Ts]) -> - case t_is_nil(Ts, Opaques) of + case t_is_nil(Ts) of true -> t_tuple([t_nil(), t_nil(), t_nil()]); false -> % Ps is a proper list of triples - TupleTypes = t_tuple_subtypes(t_list_elements(Ts, Opaques), - Opaques), + TupleTypes = t_tuple_subtypes(t_list_elements(Ts)), lists:foldl(fun(T, Acc) -> - [A, B, C] = t_tuple_args(T, Opaques), + [A, B, C] = t_tuple_args(T), t_sup(t_tuple([t_list(A), t_list(B), t_list(C)]), Acc) end, t_none(), TupleTypes) end - end, Opaques); -type(lists, zip, 2, Xs, Opaques) -> + end); +type(lists, zip, 2, Xs) -> strict(lists, zip, 2, Xs, fun ([As, Bs]) -> - case (t_is_nil(As, Opaques) orelse t_is_nil(Bs, Opaques)) of + case (t_is_nil(As) orelse t_is_nil(Bs)) of true -> t_nil(); false -> - A = t_list_elements(As, Opaques), - B = t_list_elements(Bs, Opaques), + A = t_list_elements(As), + B = t_list_elements(Bs), t_list(t_tuple([A, B])) end - end, Opaques); -type(lists, zip3, 3, Xs, Opaques) -> + end); +type(lists, zip3, 3, Xs) -> strict(lists, zip3, 3, Xs, fun ([As, Bs, Cs]) -> case - (t_is_nil(As, Opaques) - orelse t_is_nil(Bs, Opaques) - orelse t_is_nil(Cs, Opaques)) + (t_is_nil(As) + orelse t_is_nil(Bs) + orelse t_is_nil(Cs)) of true -> t_nil(); false -> - A = t_list_elements(As, Opaques), - B = t_list_elements(Bs, Opaques), - C = t_list_elements(Cs, Opaques), + A = t_list_elements(As), + B = t_list_elements(Bs), + C = t_list_elements(Cs), t_list(t_tuple([A, B, C])) end - end, Opaques); -type(lists, zipwith, 3, Xs, Opaques) -> + end); +type(lists, zipwith, 3, Xs) -> strict(lists, zipwith, 3, Xs, - fun ([F, _As, _Bs]) -> t_sup(t_list(t_fun_range(F, Opaques)), - t_nil()) end, Opaques); -type(lists, zipwith3, 4, Xs, Opaques) -> + fun ([F, _As, _Bs]) -> t_sup(t_list(t_fun_range(F)), + t_nil()) end); +type(lists, zipwith3, 4, Xs) -> strict(lists, zipwith3, 4, Xs, - fun ([F,_As,_Bs,_Cs]) -> t_sup(t_list(t_fun_range(F, Opaques)), - t_nil()) end, Opaques); + fun ([F,_As,_Bs,_Cs]) -> t_sup(t_list(t_fun_range(F)), + t_nil()) end); %%-- maps --------------------------------------------------------------------- -type(maps, from_keys, 2, Xs, Opaques) -> +type(maps, from_keys, 2, Xs) -> strict(maps, from_keys, 2, Xs, fun ([List, Value]) -> - case t_is_nil(List, Opaques) of + case t_is_nil(List) of true -> t_from_term(#{}); - false -> t_map([], t_list_elements(List, Opaques), Value) + false -> t_map([], t_list_elements(List), Value) end - end, Opaques); -type(maps, from_list, 1, Xs, Opaques) -> + end); +type(maps, from_list, 1, Xs) -> strict(maps, from_list, 1, Xs, fun ([List]) -> - case t_is_nil(List, Opaques) of + case t_is_nil(List) of true -> t_from_term(#{}); false -> - T = t_list_elements(List, Opaques), - case t_tuple_subtypes(T, Opaques) of + T = t_list_elements(List), + case t_tuple_subtypes(T) of unknown -> t_map(); Stypes when length(Stypes) >= 1 -> t_sup([begin - [K, V] = t_tuple_args(Args, Opaques), + [K, V] = t_tuple_args(Args), t_map([], K, V) end || Args <- Stypes]) end end - end, Opaques); -type(maps, get, 2, Xs, Opaques) -> + end); +type(maps, get, 2, Xs) -> strict(maps, get, 2, Xs, fun ([Key, Map]) -> - t_map_get(Key, Map, Opaques) - end, Opaques); -type(maps, is_key, 2, Xs, Opaques) -> + t_map_get(Key, Map) + end); +type(maps, is_key, 2, Xs) -> strict(maps, is_key, 2, Xs, fun ([Key, Map]) -> - t_map_is_key(Key, Map, Opaques) - end, Opaques); -type(maps, merge, 2, Xs, Opaques) -> + t_map_is_key(Key, Map) + end); +type(maps, merge, 2, Xs) -> strict(maps, merge, 2, Xs, fun ([MapA, MapB]) -> - ADefK = t_map_def_key(MapA, Opaques), - BDefK = t_map_def_key(MapB, Opaques), - ADefV = t_map_def_val(MapA, Opaques), - BDefV = t_map_def_val(MapB, Opaques), + ADefK = t_map_def_key(MapA), + BDefK = t_map_def_key(MapB), + ADefV = t_map_def_val(MapA), + BDefV = t_map_def_val(MapB), t_map(t_map_pairwise_merge( fun(K, _, _, mandatory, V) -> {K, mandatory, V}; (K, MNess, VA, optional, VB) -> {K, MNess, t_sup(VA,VB)} - end, MapA, MapB, Opaques), + end, MapA, MapB), t_sup(ADefK, BDefK), t_sup(ADefV, BDefV)) - end, Opaques); -type(maps, put, 3, Xs, Opaques) -> + end); +type(maps, put, 3, Xs) -> strict(maps, put, 3, Xs, fun ([Key, Value, Map]) -> - t_map_put({Key, Value}, Map, Opaques) - end, Opaques); -type(maps, remove, 2, Xs, Opaques) -> + t_map_put({Key, Value}, Map) + end); +type(maps, remove, 2, Xs) -> strict(maps, remove, 2, Xs, fun ([Key, Map]) -> - t_map_remove(Key, Map, Opaques) - end, Opaques); -type(maps, size, 1, Xs, Opaques) -> + t_map_remove(Key, Map) + end); +type(maps, size, 1, Xs) -> strict(maps, size, 1, Xs, fun ([Map]) -> - Mand = [E || E={_,mandatory,_} <- t_map_entries(Map, Opaques)], + Mand = [E || E={_,mandatory,_} <- t_map_entries(Map)], LowerBound = length(Mand), - case t_is_none(t_map_def_key(Map, Opaques)) of + case t_is_none(t_map_def_key(Map)) of false -> t_from_range(LowerBound, pos_inf); true -> - Opt = [E || E={_,optional,_} <- t_map_entries(Map, Opaques)], + Opt = [E || E={_,optional,_} <- t_map_entries(Map)], UpperBound = LowerBound + length(Opt), t_from_range(LowerBound, UpperBound) end - end, Opaques); -type(maps, update, 3, Xs, Opaques) -> + end); +type(maps, update, 3, Xs) -> strict(maps, update, 3, Xs, fun ([Key, Value, Map]) -> - t_map_update({Key, Value}, Map, Opaques) - end, Opaques); + t_map_update({Key, Value}, Map) + end); %%----------------------------------------------------------------------------- -type(M, F, A, Xs, _O) when is_atom(M), is_atom(F), +type(M, F, A, Xs) when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 -> strict(Xs, t_any()). % safe approximation for all functions. @@ -1643,11 +1612,9 @@ type(M, F, A, Xs, _O) when is_atom(M), is_atom(F), %% Auxiliary functions %%----------------------------------------------------------------------------- -strict(M, F, A, Xs, Fun, Opaques) -> +strict(M, F, A, Xs, Fun) -> Ts = arg_types(M, F, A), - %% io:format("inf lists arg~nXs: ~p~nTs: ~p ~n", [Xs, Ts]), - Xs1 = inf_lists(Xs, Ts, Opaques), - %% io:format("inf lists return ~p ~n", [Xs1]), + Xs1 = t_inf_lists(Xs, Ts), case any_is_none_or_unit(Xs1) of true -> t_none(); false -> Fun(Xs1) @@ -1665,11 +1632,6 @@ strict(Xs, X) -> false -> X end. -inf_lists([X | Xs], [T | Ts], Opaques) -> - [t_inf(X, T, Opaques) | inf_lists(Xs, Ts, Opaques)]; -inf_lists([], [], _Opaques) -> - []. - any_list(N) -> any_list(N, t_any()). any_list(N, A) when N > 0 -> @@ -1685,39 +1647,31 @@ list_replace(1, E, [_X | Xs]) -> any_is_none_or_unit(Ts) -> lists:any(fun erl_types:t_is_impossible/1, Ts). -check_guard([X], Test, Type, Opaques) -> - check_guard_single(X, Test, Type, Opaques). +check_guard([X], Test, Type) -> + check_guard_single(X, Test, Type). -check_guard_single(X, Test, Type, Opaques) -> +check_guard_single(X, Test, Type) -> case Test(X) of true -> t_atom('true'); false -> - case t_is_none(t_inf(Type, X, Opaques)) of - true -> - case t_has_opaque_subtype(X, Opaques) of - true -> t_none(); - false -> t_atom('false') - end; + case t_is_none(t_inf(Type, X)) of + true -> t_atom('false'); false -> t_boolean() end end. -check_record_tag(Tag, Y, Opaques) -> - case t_is_atom(Tag, Opaques) of +check_record_tag(Tag, Y) -> + case t_is_atom(Tag) of false -> - TagAtom = t_inf(Tag, t_atom(), Opaques), + TagAtom = t_inf(Tag, t_atom()), case t_is_none(TagAtom) of - true -> - case t_has_opaque_subtype(Tag, Opaques) of - true -> t_none(); - false -> t_atom('false') - end; + true -> t_atom('false'); false -> t_boolean() end; true -> - case t_atom_vals(Tag, Opaques) of + case t_atom_vals(Tag) of [RealTag] -> - case t_atom_vals(Y, Opaques) of + case t_atom_vals(Y) of [RealTag] -> t_atom('true'); _ -> t_boolean() end; @@ -1877,26 +1831,26 @@ negwidth(X, N) -> false -> negwidth(X, N+1) end. -arith_bnot(X1, Opaques) -> - case t_is_integer(X1, Opaques) of +arith_bnot(X1) -> + case t_is_integer(X1) of false -> error; true -> - Min1 = number_min(X1, Opaques), - Max1 = number_max(X1, Opaques), + Min1 = number_min(X1), + Max1 = number_max(X1), {ok, t_from_range(infinity_add(infinity_inv(Max1), -1), infinity_add(infinity_inv(Min1), -1))} end. -arith_abs(X1, Opaques) -> - case t_is_integer(X1, Opaques) of +arith_abs(X1) -> + case t_is_integer(X1) of false -> - case t_is_float(X1, Opaques) of + case t_is_float(X1) of true -> t_float(); false -> t_number() end; true -> - Min1 = number_min(X1, Opaques), - Max1 = number_max(X1, Opaques), + Min1 = number_min(X1), + Max1 = number_max(X1), {NewMin, NewMax} = case infinity_geq(Min1, 0) of true -> {Min1, Max1}; @@ -1977,13 +1931,13 @@ arith_bor_range_set({Min, Max}, [Int|IntList]) -> IntList), {infinity_bor(Min, SafeAnd), infinity_bor(Max, SafeAnd)}. -arith_band(X1, X2, Opaques) -> - L1 = t_number_vals(X1, Opaques), - L2 = t_number_vals(X2, Opaques), - Min1 = number_min(X1, Opaques), - Max1 = number_max(X1, Opaques), - Min2 = number_min(X2, Opaques), - Max2 = number_max(X2, Opaques), +arith_band(X1, X2) -> + L1 = t_number_vals(X1), + L2 = t_number_vals(X2), + Min1 = number_min(X1), + Max1 = number_max(X1), + Min2 = number_min(X2), + Max2 = number_max(X2), case {L1 =:= unknown, L2 =:= unknown} of {true, false} -> arith_band_range_set(arith_band_ranges(Min1, Max1, Min2, Max2), L2); @@ -1993,13 +1947,13 @@ arith_band(X1, X2, Opaques) -> arith_band_ranges(Min1, Max1, Min2, Max2) end. -arith_bor(X1, X2, Opaques) -> - L1 = t_number_vals(X1, Opaques), - L2 = t_number_vals(X2, Opaques), - Min1 = number_min(X1, Opaques), - Max1 = number_max(X1, Opaques), - Min2 = number_min(X2, Opaques), - Max2 = number_max(X2, Opaques), +arith_bor(X1, X2) -> + L1 = t_number_vals(X1), + L2 = t_number_vals(X2), + Min1 = number_min(X1), + Max1 = number_max(X1), + Min2 = number_min(X2), + Max2 = number_max(X2), case {L1 =:= unknown, L2 =:= unknown} of {true, false} -> arith_bor_range_set(arith_bor_ranges(Min1, Max1, Min2, Max2), L2); @@ -2037,19 +1991,18 @@ arith_bor_ranges(Min1, Max1, Min2, Max2) -> end, {Min, Max}. -arith(Op, X1, X2, Opaques) -> - %% io:format("arith ~p ~p ~p~n", [Op, X1, X2]), - case t_is_integer(X1, Opaques) andalso t_is_integer(X2, Opaques) of +arith(Op, X1, X2) -> + case t_is_integer(X1) andalso t_is_integer(X2) of false -> error; true -> - L1 = t_number_vals(X1, Opaques), - L2 = t_number_vals(X2, Opaques), + L1 = t_number_vals(X1), + L2 = t_number_vals(X2), case (L1 =:= unknown) orelse (L2 =:= unknown) of true -> - Min1 = number_min(X1, Opaques), - Max1 = number_max(X1, Opaques), - Min2 = number_min(X2, Opaques), - Max2 = number_max(X2, Opaques), + Min1 = number_min(X1), + Max1 = number_max(X1), + Min2 = number_min(X2), + Max2 = number_max(X2), {NewMin, NewMax} = case Op of '+' -> {infinity_add(Min1, Min2), infinity_add(Max1, Max2)}; @@ -2062,11 +2015,10 @@ arith(Op, X1, X2, Opaques) -> 'bsr' -> NewMin2 = infinity_inv(Max2), NewMax2 = infinity_inv(Min2), arith_bsl(Min1, Max1, NewMin2, NewMax2); - 'band' -> arith_band(X1, X2, Opaques); - 'bor' -> arith_bor(X1, X2, Opaques); + 'band' -> arith_band(X1, X2); + 'bor' -> arith_bor(X1, X2); 'bxor' -> arith_bor_ranges(Min1, Max1, Min2, Max2) %% overaprox. end, - %% io:format("done arith ~p = ~p~n", [Op, {NewMin, NewMax}]), {ok, t_from_range(NewMin, NewMax)}; false -> %% Some of these arithmetic operations might throw a system_limit @@ -2095,59 +2047,56 @@ arith(Op, X1, X2, Opaques) -> %% Comparison of terms %%============================================================================= -compare(Op, Lhs, Rhs, Opaques) -> - case t_is_none(t_inf(Lhs, Rhs, Opaques)) of - false -> t_boolean(); +compare(Op, Lhs, Rhs) -> + case t_is_none(t_inf(Lhs, Rhs)) of + false -> + t_boolean(); true -> - case opaque_args(erlang, Op, 2, [Lhs, Rhs], Opaques) =:= [] of - true -> - case Op of - '<' -> always_smaller(Lhs, Rhs, Opaques); - '>' -> always_smaller(Rhs, Lhs, Opaques); - '=<' -> always_smaller(Lhs, Rhs, Opaques); - '>=' -> always_smaller(Rhs, Lhs, Opaques) - end; - false -> t_none() + case Op of + '<' -> always_smaller(Lhs, Rhs); + '>' -> always_smaller(Rhs, Lhs); + '=<' -> always_smaller(Lhs, Rhs); + '>=' -> always_smaller(Rhs, Lhs) end end. -always_smaller(Type1, Type2, Opaques) -> - {Min1, Max1} = type_ranks(Type1, Opaques), - {Min2, Max2} = type_ranks(Type2, Opaques), +always_smaller(Type1, Type2) -> + {Min1, Max1} = type_ranks(Type1), + {Min2, Max2} = type_ranks(Type2), if Max1 < Min2 -> t_atom('true'); Min1 > Max2 -> t_atom('false'); true -> t_boolean() end. -type_ranks(Type, Opaques) -> - type_ranks(Type, 1, 0, 0, type_order(), Opaques). +type_ranks(Type) -> + type_ranks(Type, 1, 0, 0, type_order()). -type_ranks(_Type, _I, Min, Max, [], _Opaques) -> {Min, Max}; -type_ranks(Type, I, Min, Max, [TypeClass|Rest], Opaques) -> +type_ranks(_Type, _I, Min, Max, []) -> {Min, Max}; +type_ranks(Type, I, Min, Max, [TypeClass|Rest]) -> {NewMin, NewMax} = - case t_is_none(t_inf(Type, TypeClass, Opaques)) of + case t_is_none(t_inf(Type, TypeClass)) of true -> {Min, Max}; false -> case Min of 0 -> {I, I}; _ -> {Min, I} end end, - type_ranks(Type, I+1, NewMin, NewMax, Rest, Opaques). + type_ranks(Type, I+1, NewMin, NewMax, Rest). type_order() -> [t_number(), t_atom(), t_reference(), t_fun(), t_port(), t_pid(), t_tuple(), t_map(), t_list(), t_bitstr()]. -key_comparisons_fail(X0, KeyPos, TupleList, Opaques) -> +key_comparisons_fail(X0, KeyPos, TupleList) -> X = erl_types:t_widen_to_number(X0), lists:all(fun(Tuple) -> Key = type(erlang, element, 2, [KeyPos, Tuple]), - t_is_none(t_inf(Key, X, Opaques)) + t_is_none(t_inf(Key, X)) end, TupleList). %%============================================================================= --spec arg_types(atom(), atom(), arity()) -> arg_types() | 'unknown'. +-spec arg_types(atom(), atom(), arity()) -> [erl_types:erl_type()] | 'unknown'. %%------- erlang -------------------------------------------------------------- arg_types(erlang, '!', 2) -> @@ -2508,75 +2457,20 @@ arg_types(M, F, A) when is_atom(M), is_atom(F), is_known(M, F, A) -> arg_types(M, F, A) =/= unknown. --spec opaque_args(module(), atom(), arity(), - arg_types(), opaques()) -> [pos_integer()]. - -%% Use this function to find out which argument caused empty type. - -opaque_args(_M, _F, _A, _Xs, 'universe') -> []; -opaque_args(M, F, A, Xs, Opaques) -> - case kind_of_check(M, F, A) of - record -> - [X,Y|_] = Xs, - [1 || - case t_is_tuple(X, Opaques) of - true -> - case t_tuple_subtypes(X, Opaques) of - unknown -> false; - List when length(List) >= 1 -> - (t_is_atom(Y, Opaques) andalso - opaque_recargs(List, Y, Opaques)) - end; - false -> t_has_opaque_subtype(X, Opaques) - end]; - subtype -> - [N || - {N, X} <- lists:zip(lists:seq(1, length(Xs)), Xs), - t_has_opaque_subtype(X, Opaques)]; - find_unknown -> - [L, R] = Xs, - erl_types:t_find_unknown_opaque(L, R, Opaques); - no_check -> [] - end. - -kind_of_check(erlang, is_record, 3) -> - record; -kind_of_check(erlang, is_record, 2) -> - record; -kind_of_check(erlang, F, A) -> - case erl_internal:guard_bif(F, A) orelse erl_internal:bool_op(F, A) of - true -> subtype; - false -> - case erl_internal:comp_op(F, A) of - true -> find_unknown; - false -> no_check - end - end; -kind_of_check(_M, _F, _A) -> no_check. - -opaque_recargs(Tuples, Y, Opaques) -> - Fun = fun(Tuple) -> - case t_tuple_args(Tuple, Opaques) of - [Tag|_] -> t_is_none(check_record_tag(Tag, Y, Opaques)); - _ -> false - end - end, - lists:all(Fun, Tuples). - -check_fun_application(Fun, Args, Opaques) -> - case t_is_fun(Fun, Opaques) of +check_fun_application(Fun, Args) -> + case t_is_fun(Fun) of true -> - case t_fun_args(Fun, Opaques) of + case t_fun_args(Fun) of unknown -> - case t_is_impossible(t_fun_range(Fun, Opaques)) of + case t_is_impossible(t_fun_range(Fun)) of true -> error; false -> ok end; FunDom when length(FunDom) =:= length(Args) -> - case any_is_none_or_unit(inf_lists(FunDom, Args, Opaques)) of + case any_is_none_or_unit(t_inf_lists(FunDom, Args)) of true -> error; false -> - case t_is_impossible(t_fun_range(Fun, Opaques)) of + case t_is_impossible(t_fun_range(Fun)) of true -> error; false -> ok end diff --git a/lib/dialyzer/src/erl_types.erl b/lib/dialyzer/src/erl_types.erl index 0f528f6a45e5..f1608a6b5f71 100644 --- a/lib/dialyzer/src/erl_types.erl +++ b/lib/dialyzer/src/erl_types.erl @@ -35,15 +35,15 @@ lookup_record/3, max/2, min/2, - number_max/1, number_max/2, - number_min/1, number_min/2, + number_max/1, + number_min/1, t_abstract_records/2, t_any/0, t_arity/0, t_atom/0, t_atom/1, t_atoms/1, - t_atom_vals/1, t_atom_vals/2, + t_atom_vals/1, t_binary/0, t_bitstr/0, t_bitstr/2, @@ -59,14 +59,9 @@ t_collect_var_names/1, t_cons/0, t_cons/2, - t_cons_hd/1, t_cons_hd/2, - t_cons_tl/1, t_cons_tl/2, - t_contains_opaque/1, t_contains_opaque/2, - t_decorate_with_opaque/3, + t_cons_hd/1, + t_cons_tl/1, t_elements/1, - t_elements/2, - t_find_opaque_mismatch/3, - t_find_unknown_opaque/3, t_fixnum/0, t_non_neg_fixnum/0, t_pos_fixnum/0, @@ -82,18 +77,15 @@ t_fun/0, t_fun/1, t_fun/2, - t_fun_args/1, t_fun_args/2, - t_fun_arity/1, t_fun_arity/2, - t_fun_range/1, t_fun_range/2, - t_has_opaque_subtype/2, + t_fun_args/1, + t_fun_arity/1, + t_fun_range/1, t_has_var/1, t_identifier/0, %% t_improper_list/2, t_inf/1, t_inf/2, - t_inf/3, t_inf_lists/2, - t_inf_lists/3, t_integer/0, t_integer/1, t_non_neg_integer/0, @@ -102,62 +94,64 @@ t_iodata/0, t_iolist/0, t_is_any/1, - t_is_atom/1, t_is_atom/2, - t_is_any_atom/2, t_is_any_atom/3, - t_is_binary/1, t_is_binary/2, - t_is_bitstr/1, t_is_bitstr/2, - t_is_boolean/1, t_is_boolean/2, + t_is_atom/1, + t_is_any_atom/2, + t_is_binary/1, + t_is_bitstr/1, + t_is_boolean/1, t_is_byte/1, t_is_char/1, - t_is_cons/1, t_is_cons/2, + t_is_cons/1, t_is_equal/2, - t_is_float/1, t_is_float/2, - t_is_fun/1, t_is_fun/2, + t_is_float/1, + t_is_fun/1, t_is_identifier/1, t_is_impossible/1, t_is_instance/2, - t_is_integer/1, t_is_integer/2, + t_is_integer/1, t_is_list/1, t_is_map/1, - t_is_map/2, - t_is_nil/1, t_is_nil/2, + t_is_nil/1, t_is_non_neg_integer/1, t_is_none/1, t_is_none_or_unit/1, - t_is_number/1, t_is_number/2, - t_is_opaque/1, t_is_opaque/2, - t_is_pid/1, t_is_pid/2, - t_is_port/1, t_is_port/2, - t_is_maybe_improper_list/1, t_is_maybe_improper_list/2, - t_is_reference/1, t_is_reference/2, + t_is_number/1, + t_is_opaque/1, + t_is_opaque/2, + t_is_pid/1, + t_is_port/1, + t_is_maybe_improper_list/1, + t_is_reference/1, + t_is_same_opaque/2, t_is_singleton/1, - t_is_singleton/2, t_is_string/1, t_is_subtype/2, - t_is_tuple/1, t_is_tuple/2, + t_is_tuple/1, t_is_unit/1, t_is_var/1, t_limit/2, t_list/0, t_list/1, - t_list_elements/1, t_list_elements/2, - t_list_termination/1, t_list_termination/2, + t_list_elements/1, + t_list_termination/1, t_map/0, t_map/1, t_map/3, - t_map_entries/2, t_map_entries/1, - t_map_def_key/2, t_map_def_key/1, - t_map_def_val/2, t_map_def_val/1, - t_map_get/2, t_map_get/3, - t_map_is_key/2, t_map_is_key/3, - t_map_update/2, t_map_update/3, - t_map_pairwise_merge/4, - t_map_put/2, t_map_put/3, - t_map_remove/3, + t_map_entries/1, + t_map_def_key/1, + t_map_def_val/1, + t_map_get/2, + t_map_is_key/2, + t_map_update/2, + t_map_pairwise_merge/3, + t_map_put/2, + t_map_remove/2, t_mfa/0, t_module/0, t_nil/0, t_node/0, + t_nominal/2, + t_nominal_module/1, t_none/0, t_nonempty_binary/0, t_nonempty_bitstring/0, @@ -166,13 +160,11 @@ t_nonempty_string/0, t_number/0, t_number/1, - t_number_vals/1, t_number_vals/2, - t_opaque_from_records/1, - t_opaque_structure/1, + t_number_vals/1, + t_opacity_conflict/3, t_pid/0, t_port/0, t_maybe_improper_list/0, - %% t_maybe_improper_list/2, t_product/1, t_reference/0, t_string/0, @@ -187,23 +179,20 @@ t_to_tlist/1, t_tuple/0, t_tuple/1, - t_tuple_args/1, t_tuple_args/2, - t_tuple_size/1, t_tuple_size/2, + t_tuple_args/1, + t_tuple_size/1, t_tuple_sizes/1, t_tuple_subtypes/1, - t_tuple_subtypes/2, t_unify_table_only/2, t_unit/0, - t_unopaque/1, t_unopaque/2, + t_structural/1, t_var/1, t_var_name/1, t_widen_to_number/1, - %% t_assign_variables_to_subtype/2, type_is_defined/4, record_field_diffs_to_string/2, subst_all_vars_to_any/1, - lift_list_to_pos_empty/1, lift_list_to_pos_empty/2, - is_opaque_type/2, + lift_list_to_pos_empty/1, is_erl_type/1, atom_to_string/1, var_table__new/0, @@ -214,15 +203,14 @@ -compile({no_auto_import,[min/2,max/2,map_get/2]}). --export_type([erl_type/0, opaques/0, type_table/0, - var_table/0, cache/0]). +-export_type([erl_type/0, type_table/0, var_table/0, cache/0]). %%-define(DEBUG, true). -ifdef(DEBUG). --define(debug(__A), __A). +-define(debug(__A, __B), case __A of true -> ok; false -> error(__B) end). -else. --define(debug(__A), ok). +-define(debug(__A, __B), ok). -endif. %%============================================================================= @@ -257,11 +245,12 @@ -define(binary_tag, binary). -define(function_tag, function). -define(identifier_tag, identifier). +-define(nominal_tag, nominal). +-define(nominal_set_tag,nominal_set). -define(list_tag, list). -define(map_tag, map). -define(nil_tag, nil). -define(number_tag, number). --define(opaque_tag, opaque). -define(product_tag, product). -define(tuple_set_tag, tuple_set). -define(tuple_tag, tuple). @@ -270,7 +259,8 @@ -type tag() :: ?atom_tag | ?binary_tag | ?function_tag | ?identifier_tag | ?list_tag | ?map_tag | ?nil_tag | ?number_tag - | ?opaque_tag | ?product_tag + | ?nominal_tag | ?nominal_set_tag + | ?product_tag | ?tuple_tag | ?tuple_set_tag | ?union_tag | ?var_tag. -define(float_qual, float). @@ -288,15 +278,27 @@ %% The type representation %% --define(any, any). +%% Top type +-define(any, any). + +%% Bottom type -define(none, none). + +%% Special type used to mark infinite loops: functions are assumed to return +%% a supertype of ?unit rather than ?none during analysis, letting us +%% distingish between functions that intentionally never return (like server +%% loops) and functions that never return because of a crash. -define(unit, unit). + +%% Special type used to mark opaque nominals during opacity violation checking. +-define(opaque, opaque). + %% Generic constructor - elements can be many things depending on the tag. --record(c, {tag :: tag(), - elements = [] :: term(), - qualifier = ?unknown_qual :: qual()}). +-record(c, {tag :: tag(), + elements = [] :: term(), + qualifier = ?unknown_qual :: qual()}). --opaque erl_type() :: ?any | ?none | ?unit | #c{}. +-nominal erl_type() :: ?any | ?none | ?unit | ?opaque | #c{}. %%----------------------------------------------------------------------------- %% Auxiliary types and convenient macros @@ -308,30 +310,30 @@ -record(int_set, {set :: [integer()]}). -record(int_rng, {from :: rng_elem(), to :: rng_elem()}). --record(opaque, {mod :: module(), name :: atom(), - arity = 0 :: arity(), struct :: erl_type()}). - -define(atom(Set), #c{tag=?atom_tag, elements=Set}). -define(bitstr(Unit, Base), #c{tag=?binary_tag, elements={Unit,Base}}). -define(float, ?number(?any, ?float_qual)). -define(function(Domain, Range), #c{tag=?function_tag, - elements={Domain,Range}}). + elements={Domain,Range}}). -define(identifier(Types), #c{tag=?identifier_tag, elements=Types}). -define(integer(Types), ?number(Types, ?integer_qual)). -define(int_range(From, To), ?integer(#int_rng{from=From, to=To})). -define(int_set(Set), ?integer(#int_set{set=Set})). +-define(nominal(Name, Types), #c{tag=?nominal_tag, elements={Name,Types}}). +-define(nominal_set(Nominals, + Structurals), #c{tag=?nominal_set_tag, + elements={Nominals, Structurals}}). -define(list(Types, Term, Size), #c{tag=?list_tag, elements={Types,Term}, - qualifier=Size}). + qualifier=Size}). -define(nil, #c{tag=?nil_tag}). -define(nonempty_list(Types, Term),?list(Types, Term, ?nonempty_qual)). -define(number(Set, Qualifier), #c{tag=?number_tag, elements=Set, - qualifier=Qualifier}). + qualifier=Qualifier}). -define(map(Pairs,DefKey,DefVal), #c{tag=?map_tag, elements={Pairs,DefKey,DefVal}}). --define(opaque(Optypes), #c{tag=?opaque_tag, elements=Optypes}). -define(product(Types), #c{tag=?product_tag, elements=Types}). -define(tuple(Types, Arity, Qual), #c{tag=?tuple_tag, elements=Types, - qualifier={Arity, Qual}}). + qualifier={Arity, Qual}}). -define(tuple_set(Tuples), #c{tag=?tuple_set_tag, elements=Tuples}). -define(var(Id), #c{tag=?var_tag, elements=Id}). @@ -341,11 +343,9 @@ -define(integer_non_neg, ?int_range(0, pos_inf)). -define(integer_neg, ?int_range(neg_inf, -1)). --type opaques() :: [erl_type()] | 'universe'. - -type file_line() :: {file:name(), erl_anno:line()}. -type record_key() :: {'record', atom()}. --type type_key() :: {'type' | 'opaque', atom(), arity()}. +-type type_key() :: {'type' | 'opaque' | 'nominal', atom(), arity()}. -type field() :: {atom(), erl_parse:abstract_expr(), erl_type()}. -type record_value() :: {file_line(), [{RecordSize :: non_neg_integer(), [field()]}]}. @@ -363,20 +363,19 @@ %% -define(union(List), #c{tag=?union_tag, elements=List}). --define(untagged_union(A, B, F, I, L, N, T, O, Map), [A,B,F,I,L,N,T,O,Map]). +-define(untagged_union(A, B, F, I, L, N, T, Map), [A,B,F,I,L,N,T,Map]). -define(num_types_in_union, length(?untagged_union(?any, ?any, ?any, ?any, ?any, - ?any, ?any, ?any, ?any))). - --define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none])). --define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none])). --define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none])). --define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none])). --define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none])). --define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none])). --define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none])). --define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none])). --define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T])). + ?any, ?any, ?any))). + +-define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none])). +-define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none])). +-define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none])). +-define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none])). +-define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none])). +-define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none])). +-define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none])). +-define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T])). -define(integer_union(T), ?number_union(T)). -define(float_union(T), ?number_union(T)). -define(nil_union(T), ?list_union(T)). @@ -400,7 +399,7 @@ t_any() -> -spec t_is_any(erl_type()) -> boolean(). t_is_any(Type) -> - do_opaque(Type, 'universe', fun is_any/1). + structural(Type, fun is_any/1). is_any(?any) -> true; is_any(_) -> false. @@ -419,347 +418,86 @@ t_is_none(_) -> false. %% Opaque types %% --spec t_opaque(module(), atom(), [_], erl_type()) -> erl_type(). - -t_opaque(Mod, Name, Args, Struct) -> - O = #opaque{mod = Mod, name = Name, arity = length(Args), struct = Struct}, - ?opaque(set_singleton(O)). - --spec t_is_opaque(erl_type(), [erl_type()]) -> boolean(). - -t_is_opaque(?opaque(_) = Type, Opaques) -> - not is_opaque_type(Type, Opaques); -t_is_opaque(_Type, _Opaques) -> false. - --spec t_is_opaque(erl_type()) -> boolean(). - -t_is_opaque(?opaque(_)) -> true; -t_is_opaque(_) -> false. - --spec t_has_opaque_subtype(erl_type(), opaques()) -> boolean(). - -t_has_opaque_subtype(Type, Opaques) -> - do_opaque(Type, Opaques, fun has_opaque_subtype/1). - -has_opaque_subtype(?union(Ts)) -> - lists:any(fun t_is_opaque/1, Ts); -has_opaque_subtype(T) -> - t_is_opaque(T). - --spec t_opaque_structure(erl_type()) -> erl_type(). - -t_opaque_structure(?opaque(Elements)) -> - t_sup([Struct || #opaque{struct = Struct} <- Elements]). - --spec t_contains_opaque(erl_type()) -> boolean(). - -t_contains_opaque(Type) -> - t_contains_opaque(Type, []). - -%% Returns 'true' iff there is an opaque type that is *not* one of -%% the types of the second argument. - --spec t_contains_opaque(erl_type(), [erl_type()]) -> boolean(). - -t_contains_opaque(?any, _Opaques) -> false; -t_contains_opaque(?none, _Opaques) -> false; -t_contains_opaque(?unit, _Opaques) -> false; -t_contains_opaque(?atom(_Set), _Opaques) -> false; -t_contains_opaque(?bitstr(_Unit, _Base), _Opaques) -> false; -t_contains_opaque(?float, _Opaques) -> false; -t_contains_opaque(?function(Domain, Range), Opaques) -> - t_contains_opaque(Domain, Opaques) - orelse t_contains_opaque(Range, Opaques); -t_contains_opaque(?identifier(_Types), _Opaques) -> false; -t_contains_opaque(?int_range(_From, _To), _Opaques) -> false; -t_contains_opaque(?int_set(_Set), _Opaques) -> false; -t_contains_opaque(?integer(_Types), _Opaques) -> false; -t_contains_opaque(?list(Type, ?nil, _), Opaques) -> - t_contains_opaque(Type, Opaques); -t_contains_opaque(?list(Type, Tail, _), Opaques) -> - t_contains_opaque(Type, Opaques) orelse t_contains_opaque(Tail, Opaques); -t_contains_opaque(?map(_, _, _) = Map, Opaques) -> - list_contains_opaque(map_all_types(Map), Opaques); -t_contains_opaque(?nil, _Opaques) -> false; -t_contains_opaque(?number(_Set, _Tag), _Opaques) -> false; -t_contains_opaque(?opaque(_)=T, Opaques) -> - not is_opaque_type(T, Opaques) - orelse t_contains_opaque(t_opaque_structure(T)); -t_contains_opaque(?product(Types), Opaques) -> - list_contains_opaque(Types, Opaques); -t_contains_opaque(?tuple(?any, _, _), _Opaques) -> false; -t_contains_opaque(?tuple(Types, _, _), Opaques) -> - list_contains_opaque(Types, Opaques); -t_contains_opaque(?tuple_set(_Set) = T, Opaques) -> - list_contains_opaque(t_tuple_subtypes(T), Opaques); -t_contains_opaque(?union(List), Opaques) -> - list_contains_opaque(List, Opaques); -t_contains_opaque(?var(_Id), _Opaques) -> false. - --spec list_contains_opaque([erl_type()], [erl_type()]) -> boolean(). - -list_contains_opaque([H|T], Opaques) -> - t_contains_opaque(H, Opaques) orelse list_contains_opaque(T, Opaques); -list_contains_opaque([], _Opaques) -> false. - -%% t_find_opaque_mismatch/2 of two types should only be used if their -%% t_inf is t_none() due to some opaque type violation. However, -%% 'error' is returned if a structure mismatch is found. -%% -%% The first argument of the function is the pattern and its second -%% argument the type we are matching against the pattern. - --spec t_find_opaque_mismatch(erl_type(), erl_type(), [erl_type()]) -> - 'error' | {'ok', erl_type(), erl_type()}. - -t_find_opaque_mismatch(T1, T2, Opaques) -> - try t_find_opaque_mismatch(T1, T2, T2, Opaques) - catch throw:error -> error - end. - -t_find_opaque_mismatch(?any, _Type, _TopType, _Opaques) -> error; -t_find_opaque_mismatch(?none, _Type, _TopType, _Opaques) -> throw(error); -t_find_opaque_mismatch(?list(T1, Tl1, _), ?list(T2, Tl2, _), TopType, Opaques) -> - t_find_opaque_mismatch_ordlists([T1, Tl1], [T2, Tl2], TopType, Opaques); -t_find_opaque_mismatch(T1, ?opaque(_) = T2, TopType, Opaques) -> - case is_opaque_type(T2, Opaques) of - false -> - case t_is_opaque(T1) andalso compatible_opaque_types(T1, T2) =/= [] of - true -> error; - false -> {ok, TopType, T2} - end; - true -> - t_find_opaque_mismatch(T1, t_opaque_structure(T2), TopType, Opaques) - end; -t_find_opaque_mismatch(?opaque(_) = T1, T2, TopType, Opaques) -> - %% The generated message is somewhat misleading: - case is_opaque_type(T1, Opaques) of - false -> - case t_is_opaque(T2) andalso compatible_opaque_types(T1, T2) =/= [] of - true -> error; - false -> {ok, TopType, T1} - end; - true -> - t_find_opaque_mismatch(t_opaque_structure(T1), T2, TopType, Opaques) - end; -t_find_opaque_mismatch(?product(T1), ?product(T2), TopType, Opaques) -> - t_find_opaque_mismatch_ordlists(T1, T2, TopType, Opaques); -t_find_opaque_mismatch(?tuple(T1, Arity, _), ?tuple(T2, Arity, _), - TopType, Opaques) -> - t_find_opaque_mismatch_ordlists(T1, T2, TopType, Opaques); -t_find_opaque_mismatch(?tuple(_, _, _) = T1, ?tuple_set(_) = T2, - TopType, Opaques) -> - Tuples1 = t_tuple_subtypes(T1), - Tuples2 = t_tuple_subtypes(T2), - t_find_opaque_mismatch_lists(Tuples1, Tuples2, TopType, Opaques); -t_find_opaque_mismatch(T1, ?union(U2), TopType, Opaques) -> - t_find_opaque_mismatch_lists([T1], U2, TopType, Opaques); -t_find_opaque_mismatch(T1, T2, _TopType, Opaques) -> - case t_is_none(t_inf(T1, T2, Opaques)) of - false -> error; - true -> throw(error) - end. - -t_find_opaque_mismatch_ordlists(L1, L2, TopType, Opaques) - when is_list(L1), is_list(L2) -> - List = lists:zipwith(fun(T1, T2) -> - t_find_opaque_mismatch(T1, T2, TopType, Opaques) - end, L1, L2), - t_find_opaque_mismatch_list(List); -t_find_opaque_mismatch_ordlists(_, _, _TopType, _Opaques) -> - error. - -t_find_opaque_mismatch_lists(L1, L2, _TopType, Opaques) - when is_list(L1), is_list(L2) -> - List = [try t_find_opaque_mismatch(T1, T2, T2, Opaques) - catch throw:error -> error - end || T1 <- L1, T2 <- L2], - t_find_opaque_mismatch_list(List); -t_find_opaque_mismatch_lists(_, _, _TopType, _Opaques) -> - error. - -t_find_opaque_mismatch_list([]) -> throw(error); -t_find_opaque_mismatch_list([H|T]) -> - case H of - {ok, _T1, _T2} -> H; - error -> t_find_opaque_mismatch_list(T) - end. - --spec t_find_unknown_opaque(erl_type(), erl_type(), opaques()) -> - [pos_integer()]. - -%% The nice thing about using two types and t_inf() as compared to -%% calling t_contains_opaque/2 is that the traversal stops when -%% there is a mismatch which means that unknown opaque types "below" -%% the mismatch are not found. -t_find_unknown_opaque(_T1, _T2, 'universe') -> []; -t_find_unknown_opaque(T1, T2, Opaques) -> - try t_inf(T1, T2, {match, Opaques}) of - _ -> [] - catch throw:{pos, Ns} -> Ns - end. - --spec t_decorate_with_opaque(erl_type(), erl_type(), [erl_type()]) -> erl_type(). - -%% The first argument can contain opaque types. The second argument -%% is assumed to be taken from the contract. - -t_decorate_with_opaque(T1, T2, Opaques) -> - case - Opaques =:= [] orelse t_is_equal(T1, T2) orelse not t_contains_opaque(T2) - of - true -> T1; - false -> - T = t_inf(T1, T2), - case t_contains_opaque(T) of - false -> T1; - true -> - R = decorate(T1, T, Opaques), - ?debug(case catch - not t_is_equal(t_unopaque(R), t_unopaque(T1)) - orelse - t_is_equal(T1, T) andalso not t_is_equal(T1, R) - of - false -> ok; - _ -> - io:format("T1 = ~p,\n", [T1]), - io:format("T2 = ~p,\n", [T2]), - io:format("O = ~p,\n", [Opaques]), - io:format("erl_types:t_decorate_with_opaque(T1,T2,O).\n"), - throw({error, "Failed to handle opaque types"}) - end), - R - end - end. - -decorate(Type, ?none, _Opaques) -> Type; -decorate(?function(Domain, Range), ?function(D, R), Opaques) -> - ?function(decorate(Domain, D, Opaques), decorate(Range, R, Opaques)); -decorate(?list(Types, Tail, Size), ?list(Ts, Tl, _Sz), Opaques) -> - ?list(decorate(Types, Ts, Opaques), decorate(Tail, Tl, Opaques), Size); -decorate(?product(Types), ?product(Ts), Opaques) -> - ?product(list_decorate(Types, Ts, Opaques)); -decorate(?tuple(_, _, _)=T, ?tuple(?any, _, _), _Opaques) -> T; -decorate(?tuple(?any, _, _)=T, ?tuple(_, _, _), _Opaques) -> T; -decorate(?tuple(Types, Arity, Tag), ?tuple(Ts, Arity, _), Opaques) -> - ?tuple(list_decorate(Types, Ts, Opaques), Arity, Tag); -decorate(?tuple_set(List), ?tuple(_, Arity, _) = T, Opaques) -> - decorate_tuple_sets(List, [{Arity, [T]}], Opaques); -decorate(?tuple_set(List), ?tuple_set(L), Opaques) -> - decorate_tuple_sets(List, L, Opaques); -decorate(?union(List), T, Opaques) when T =/= ?any -> - ?union(L) = force_union(T), - union_decorate(List, L, Opaques); -decorate(T, ?union(L), Opaques) when T =/= ?any -> - ?union(List) = force_union(T), - union_decorate(List, L, Opaques); -decorate(Type, ?opaque(_)=T, Opaques) -> - decorate_with_opaque(Type, T, Opaques); -decorate(Type, _T, _Opaques) -> Type. - -%% Note: it is important that #opaque.struct is a subtype of the -%% opaque type. -decorate_with_opaque(Type, ?opaque(Set2), Opaques) -> - case decoration(Set2, Type, Opaques, [], false) of - {[], false} -> Type; - {List, All} when List =/= [] -> - NewType = sup_opaque(List), - case All of - true -> NewType; - false -> t_sup(NewType, Type) - end - end. - -decoration([#opaque{struct = S} = Opaque|OpaqueTypes], Type, Opaques, - NewOpaqueTypes0, All) -> - IsOpaque = is_opaque_type2(Opaque, Opaques), - I = t_inf(Type, S), - case not IsOpaque orelse t_is_none(I) of - true -> decoration(OpaqueTypes, Type, Opaques, NewOpaqueTypes0, All); - false -> - NewI = decorate(I, S, Opaques), - NewOpaque = combine(NewI, [Opaque]), - NewAll = All orelse t_is_equal(I, Type), - NewOpaqueTypes = NewOpaque ++ NewOpaqueTypes0, - decoration(OpaqueTypes, Type, Opaques, NewOpaqueTypes, NewAll) - end; -decoration([], _Type, _Opaques, NewOpaqueTypes, All) -> - {NewOpaqueTypes, All}. - --spec list_decorate([erl_type()], [erl_type()], opaques()) -> [erl_type()]. - -list_decorate(List, L, Opaques) -> - [decorate(Elem, E, Opaques) || {Elem, E} <- lists:zip(List, L)]. - -union_decorate(U1, U2, Opaques) -> - Union = union_decorate(U1, U2, Opaques, 0, []), - ?untagged_union(A,B,F,I,L,N,T,_,Map) = U1, - ?untagged_union(_,_,_,_,_,_,_,Opaque,_) = U2, - List = [A,B,F,I,L,N,T,Map], - DecList = [Dec || - E <- List, - not t_is_none(E), - not t_is_none(Dec = decorate(E, Opaque, Opaques))], - t_sup([Union|DecList]). - -union_decorate([?none|Left1], [_|Left2], Opaques, N, Acc) -> - union_decorate(Left1, Left2, Opaques, N, [?none|Acc]); -union_decorate([T1|Left1], [?none|Left2], Opaques, N, Acc) -> - union_decorate(Left1, Left2, Opaques, N+1, [T1|Acc]); -union_decorate([T1|Left1], [T2|Left2], Opaques, N, Acc) -> - union_decorate(Left1, Left2, Opaques, N+1, [decorate(T1, T2, Opaques)|Acc]); -union_decorate([], [], _Opaques, N, Acc) -> - if N =:= 0 -> ?none; - N =:= 1 -> - [Type] = [T || T <- Acc, T =/= ?none], - Type; - N >= 2 -> ?union(lists:reverse(Acc)) +%% Returns whether the `Given` type implicitly violates the opacity of opaque +%% nominals of the `Required` type. +-spec t_opacity_conflict(Given :: erl_type(), + Required :: erl_type(), + Module :: module()) -> + none | expected_opaque | expected_transparent. +t_opacity_conflict(Given, Required, Module) -> + %% Opacity violations are detected by selectively blinding the infimum + %% routine to the structure of opaque types that we are not supposed to know + %% anything about. + %% + %% If the infimum of the `Given` and `Required` types is possible, we replace + %% the structural component of opaques with a magic value whose infimum with + %% anything else becomes `none()`, forcing a failure when the original + %% opaques introduce more information. + %% + %% Conversely, if the infimum of the `Given` and `Required` types is + %% impossible, we replace the structural component of opaques with `any()` to + %% force success when the altered opaques introduce more information (note + %% the inversion). + %% + %% From there, we can detect opacity violations by checking whether the + %% infimum of (blinded `Given`) and (blinded `Required`) is equal to the + %% blinded infimum of `Given` and `Required`. + Direction = case t_is_impossible(t_inf(Given, Required)) of + true -> ?any; + false -> ?opaque + end, + + RequiredBlind = oc_mark(Required, Direction, Module), + GivenBlind = oc_mark(Given, Direction, Module), + + %% If the `Required` type does not change when blinded, we know that the call + %% expects a transparent type and not an opaque. Note that this is merely a + %% heuristic, and we can clash in both ways at once should the types be + %% complex enough. + ErrorType = case t_is_equal(RequiredBlind, Required) of + true -> expected_transparent; + false -> expected_opaque + end, + + case {t_is_impossible(t_inf(GivenBlind, RequiredBlind)), Direction} of + {true, ?opaque} -> ErrorType; + {false, ?any} -> ErrorType; + {_, _} -> none end. -decorate_tuple_sets(List, L, Opaques) -> - decorate_tuple_sets(List, L, Opaques, []). - -decorate_tuple_sets([{Arity, Tuples}|List], [{Arity, Ts}|L], Opaques, Acc) -> - DecTs = decorate_tuples_in_sets(Tuples, Ts, Opaques), - decorate_tuple_sets(List, L, Opaques, [{Arity, DecTs}|Acc]); -decorate_tuple_sets([ArTup|List], L, Opaques, Acc) -> - decorate_tuple_sets(List, L, Opaques, [ArTup|Acc]); -decorate_tuple_sets([], _L, _Opaques, Acc) -> - ?tuple_set(lists:reverse(Acc)). - -decorate_tuples_in_sets([?tuple(Elements, _, ?any)], Ts, Opaques) -> - NewList = [list_decorate(Elements, Es, Opaques) || ?tuple(Es, _, _) <- Ts], - case t_sup([t_tuple(Es) || Es <- NewList]) of - ?tuple_set([{_Arity, Tuples}]) -> Tuples; - ?tuple(_, _, _)=Tuple -> [Tuple] - end; -decorate_tuples_in_sets(Tuples, Ts, Opaques) -> - decorate_tuples_in_sets(Tuples, Ts, Opaques, []). - -decorate_tuples_in_sets([?tuple(Elements, Arity, Tag1) = T1|Tuples] = L1, - [?tuple(Es, Arity, Tag2)|Ts] = L2, Opaques, Acc) -> - if - Tag1 < Tag2 -> decorate_tuples_in_sets(Tuples, L2, Opaques, [T1|Acc]); - Tag1 > Tag2 -> decorate_tuples_in_sets(L1, Ts, Opaques, Acc); - Tag1 == Tag2 -> - NewElements = list_decorate(Elements, Es, Opaques), - NewAcc = [?tuple(NewElements, Arity, Tag1)|Acc], - decorate_tuples_in_sets(Tuples, Ts, Opaques, NewAcc) +oc_mark(?nominal({Mod, _Name, _Arity, Opacity}=Name, S0), Direction, Module) -> + case (Opacity =:= transparent) orelse (Mod =:= Module) of + true -> t_nominal(Name, oc_mark(S0, Direction, Module)); + false -> t_nominal(Name, Direction) end; -decorate_tuples_in_sets([T1|Tuples], L2, Opaques, Acc) -> - decorate_tuples_in_sets(Tuples, L2, Opaques, [T1|Acc]); -decorate_tuples_in_sets([], _L, _Opaques, Acc) -> - lists:reverse(Acc). - --spec t_opaque_from_records(type_table()) -> [erl_type()]. - -t_opaque_from_records(RecMap) -> - Any = t_any(), - [begin - Rep = Any, % not used for anything right now - Args = [Any || _ <- ArgNames], - t_opaque(Module, Name, Args, Rep) - end || {opaque, Name, _} := {{Module, _, _, ArgNames}, _} <- RecMap]. +oc_mark(?nominal_set(Ns, Other), Direction, Module) -> + normalize_nominal_set([oc_mark(N, Direction, Module) || N <- Ns], + oc_mark(Other, Direction, Module), + []); +oc_mark(?list(ElemT, Termination, Sz), Direction, Module) -> + ?list(oc_mark(ElemT, Direction, Module), + oc_mark(Termination, Direction, Module), Sz); +oc_mark(?tuple(?any, _, _) = T, _Direction, _Module) -> + T; +oc_mark(?tuple(ArgTs, Sz, Tag), Direction, Module) when is_list(ArgTs) -> + ?tuple([oc_mark(A, Direction, Module) || A <- ArgTs], Sz, Tag); +oc_mark(?tuple_set(Set0), Direction, Module) -> + ?tuple_set([{Sz, [oc_mark(T, Direction, Module) || T <- Tuples]} + || {Sz, Tuples} <- Set0]); +oc_mark(?product(Types), Direction, Module) -> + ?product([oc_mark(T, Direction, Module) || T <- Types]); +oc_mark(?function(Domain, Range), Direction, Module) -> + ?function(oc_mark(Domain, Direction, Module), + oc_mark(Range, Direction, Module)); +oc_mark(?union(U0), Direction, Module) -> + ?union([oc_mark(T, Direction, Module) || T <- U0]); +oc_mark(?map(Pairs, DefK, DefV), Direction, Module) -> + %% K is always a singleton, and thus can't contain any nominals. + t_map([{K, MNess, oc_mark(V, Direction, Module)} || {K, MNess, V} <- Pairs], + oc_mark(DefK, Direction, Module), + oc_mark(DefV, Direction, Module)); +oc_mark(T, _Direction, _Module) -> + T. %%----------------------------------------------------------------------------- %% Unit type. Signals non termination. @@ -807,16 +545,10 @@ t_atoms(List) when is_list(List) -> -spec t_atom_vals(erl_type()) -> 'unknown' | [atom(),...]. t_atom_vals(Type) -> - t_atom_vals(Type, 'universe'). - --spec t_atom_vals(erl_type(), opaques()) -> 'unknown' | [atom(),...]. - -t_atom_vals(Type, Opaques) -> - do_opaque(Type, Opaques, fun atom_vals/1). + structural(Type, fun atom_vals/1). atom_vals(?atom(?any)) -> unknown; atom_vals(?atom(Set)) -> Set; -atom_vals(?opaque(_)) -> unknown; atom_vals(Other) -> ?atom(_) = Atm = t_inf(t_atom(), Other), atom_vals(Atm). @@ -824,12 +556,7 @@ atom_vals(Other) -> -spec t_is_atom(erl_type()) -> boolean(). t_is_atom(Type) -> - t_is_atom(Type, 'universe'). - --spec t_is_atom(erl_type(), opaques()) -> boolean(). - -t_is_atom(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_atom1/1). + structural(Type, fun is_atom1/1). is_atom1(?atom(_)) -> true; is_atom1(_) -> false. @@ -837,12 +564,7 @@ is_atom1(_) -> false. -spec t_is_any_atom(atom(), erl_type()) -> boolean(). t_is_any_atom(Atom, SomeAtomsType) -> - t_is_any_atom(Atom, SomeAtomsType, 'universe'). - --spec t_is_any_atom(atom(), erl_type(), opaques()) -> boolean(). - -t_is_any_atom(Atom, SomeAtomsType, Opaques) -> - do_opaque(SomeAtomsType, Opaques, + structural(SomeAtomsType, fun(AtomsType) -> is_any_atom(Atom, AtomsType) end). is_any_atom(Atom, ?atom(?any)) when is_atom(Atom) -> false; @@ -855,12 +577,7 @@ is_any_atom(Atom, _) when is_atom(Atom) -> false. -spec t_is_boolean(erl_type()) -> boolean(). t_is_boolean(Type) -> - t_is_boolean(Type, 'universe'). - --spec t_is_boolean(erl_type(), opaques()) -> boolean(). - -t_is_boolean(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_boolean/1). + structural(Type, fun is_boolean/1). -spec t_boolean() -> erl_type(). @@ -893,12 +610,7 @@ t_nonempty_binary() -> -spec t_is_binary(erl_type()) -> boolean(). t_is_binary(Type) -> - t_is_binary(Type, 'universe'). - --spec t_is_binary(erl_type(), opaques()) -> boolean(). - -t_is_binary(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_binary/1). + structural(Type, fun is_binary/1). is_binary(?bitstr(U, B)) -> ((U rem 8) =:= 0) andalso ((B rem 8) =:= 0); @@ -954,24 +666,19 @@ t_bitstr_concat_1([], Acc) -> t_bitstr_concat(T1, T2) -> T1p = t_inf(t_bitstr(), T1), T2p = t_inf(t_bitstr(), T2), - bitstr_concat(t_unopaque(T1p), t_unopaque(T2p)). + bitstr_concat(t_structural(T1p), t_structural(T2p)). -spec t_bitstr_match(erl_type(), erl_type()) -> erl_type(). t_bitstr_match(T1, T2) -> T1p = t_inf(t_bitstr(), T1), T2p = t_inf(t_bitstr(), T2), - bitstr_match(t_unopaque(T1p), t_unopaque(T2p)). + bitstr_match(t_structural(T1p), t_structural(T2p)). -spec t_is_bitstr(erl_type()) -> boolean(). t_is_bitstr(Type) -> - t_is_bitstr(Type, 'universe'). - --spec t_is_bitstr(erl_type(), opaques()) -> boolean(). - -t_is_bitstr(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_bitstr/1). + structural(Type, fun is_bitstr/1). is_bitstr(?bitstr(_, _)) -> true; is_bitstr(_) -> false. @@ -1000,12 +707,7 @@ t_fun(Arity, Range) when is_integer(Arity), 0 =< Arity, Arity =< 255 -> -spec t_fun_args(erl_type()) -> 'unknown' | [erl_type()]. t_fun_args(Type) -> - t_fun_args(Type, 'universe'). - --spec t_fun_args(erl_type(), opaques()) -> 'unknown' | [erl_type()]. - -t_fun_args(Type, Opaques) -> - do_opaque(Type, Opaques, fun fun_args/1). + structural(Type, fun fun_args/1). fun_args(?function(?any, _)) -> unknown; @@ -1015,12 +717,7 @@ fun_args(?function(?product(Domain), _)) when is_list(Domain) -> -spec t_fun_arity(erl_type()) -> 'unknown' | non_neg_integer(). t_fun_arity(Type) -> - t_fun_arity(Type, 'universe'). - --spec t_fun_arity(erl_type(), opaques()) -> 'unknown' | non_neg_integer(). - -t_fun_arity(Type, Opaques) -> - do_opaque(Type, Opaques, fun fun_arity/1). + structural(Type, fun fun_arity/1). fun_arity(?function(?any, _)) -> unknown; @@ -1030,12 +727,7 @@ fun_arity(?function(?product(Domain), _)) -> -spec t_fun_range(erl_type()) -> erl_type(). t_fun_range(Type) -> - t_fun_range(Type, 'universe'). - --spec t_fun_range(erl_type(), opaques()) -> erl_type(). - -t_fun_range(Type, Opaques) -> - do_opaque(Type, Opaques, fun fun_range/1). + structural(Type, fun fun_range/1). fun_range(?function(_, Range)) -> Range. @@ -1043,12 +735,7 @@ fun_range(?function(_, Range)) -> -spec t_is_fun(erl_type()) -> boolean(). t_is_fun(Type) -> - t_is_fun(Type, 'universe'). - --spec t_is_fun(erl_type(), opaques()) -> boolean(). - -t_is_fun(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_fun/1). + structural(Type, fun is_fun/1). is_fun(?function(_, _)) -> true; is_fun(_) -> false. @@ -1077,12 +764,7 @@ t_port() -> -spec t_is_port(erl_type()) -> boolean(). t_is_port(Type) -> - t_is_port(Type, 'universe'). - --spec t_is_port(erl_type(), opaques()) -> boolean(). - -t_is_port(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_port1/1). + structural(Type, fun is_port1/1). is_port1(?identifier(?any)) -> false; is_port1(?identifier(Set)) -> set_is_singleton(?port_qual, Set); @@ -1098,12 +780,7 @@ t_pid() -> -spec t_is_pid(erl_type()) -> boolean(). t_is_pid(Type) -> - t_is_pid(Type, 'universe'). - --spec t_is_pid(erl_type(), opaques()) -> boolean(). - -t_is_pid(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_pid1/1). + structural(Type, fun is_pid1/1). is_pid1(?identifier(?any)) -> false; is_pid1(?identifier(Set)) -> set_is_singleton(?pid_qual, Set); @@ -1119,12 +796,7 @@ t_reference() -> -spec t_is_reference(erl_type()) -> boolean(). t_is_reference(Type) -> - t_is_reference(Type, 'universe'). - --spec t_is_reference(erl_type(), opaques()) -> boolean(). - -t_is_reference(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_reference1/1). + structural(Type, fun is_reference1/1). is_reference1(?identifier(?any)) -> false; is_reference1(?identifier(Set)) -> set_is_singleton(?reference_qual, Set); @@ -1147,12 +819,7 @@ t_number(X) when is_integer(X) -> -spec t_is_number(erl_type()) -> boolean(). t_is_number(Type) -> - t_is_number(Type, 'universe'). - --spec t_is_number(erl_type(), opaques()) -> boolean(). - -t_is_number(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_number/1). + structural(Type, fun is_number/1). is_number(?number(_, _)) -> true; is_number(_) -> false. @@ -1164,16 +831,10 @@ is_number(_) -> false. -spec t_number_vals(erl_type()) -> 'unknown' | [integer(),...]. t_number_vals(Type) -> - t_number_vals(Type, 'universe'). - --spec t_number_vals(erl_type(), opaques()) -> 'unknown' | [integer(),...]. - -t_number_vals(Type, Opaques) -> - do_opaque(Type, Opaques, fun number_vals/1). + structural(Type, fun number_vals/1). number_vals(?int_set(Set)) -> Set; number_vals(?number(_, _)) -> unknown; -number_vals(?opaque(_)) -> unknown; number_vals(Other) -> Inf = t_inf(Other, t_number()), false = t_is_none(Inf), % sanity check @@ -1189,12 +850,7 @@ t_float() -> -spec t_is_float(erl_type()) -> boolean(). t_is_float(Type) -> - t_is_float(Type, 'universe'). - --spec t_is_float(erl_type(), opaques()) -> boolean(). - -t_is_float(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_float1/1). + structural(Type, fun is_float1/1). is_float1(?float) -> true; is_float1(_) -> false. @@ -1219,12 +875,7 @@ t_integers(List) when is_list(List) -> -spec t_is_integer(erl_type()) -> boolean(). t_is_integer(Type) -> - t_is_integer(Type, 'universe'). - --spec t_is_integer(erl_type(), opaques()) -> boolean(). - -t_is_integer(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_integer1/1). + structural(Type, fun is_integer1/1). is_integer1(?integer(_)) -> true; is_integer1(_) -> false. @@ -1302,17 +953,12 @@ t_cons(Hd, Tail) -> end. cons_tail(Type) -> - do_opaque(Type, 'universe', fun(T) -> T end). + structural(Type, fun(T) -> T end). -spec t_is_cons(erl_type()) -> boolean(). t_is_cons(Type) -> - t_is_cons(Type, 'universe'). - --spec t_is_cons(erl_type(), opaques()) -> boolean(). - -t_is_cons(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_cons/1). + structural(Type, fun is_cons/1). is_cons(?nonempty_list(_, _)) -> true; is_cons(_) -> false. @@ -1320,24 +966,14 @@ is_cons(_) -> false. -spec t_cons_hd(erl_type()) -> erl_type(). t_cons_hd(Type) -> - t_cons_hd(Type, 'universe'). - --spec t_cons_hd(erl_type(), opaques()) -> erl_type(). - -t_cons_hd(Type, Opaques) -> - do_opaque(Type, Opaques, fun cons_hd/1). + structural(Type, fun cons_hd/1). cons_hd(?nonempty_list(Contents, _Termination)) -> Contents. -spec t_cons_tl(erl_type()) -> erl_type(). t_cons_tl(Type) -> - t_cons_tl(Type, 'universe'). - --spec t_cons_tl(erl_type(), opaques()) -> erl_type(). - -t_cons_tl(Type, Opaques) -> - do_opaque(Type, Opaques, fun cons_tl/1). + structural(Type, fun cons_tl/1). cons_tl(?nonempty_list(_Contents, Termination) = T) -> t_sup(Termination, T). @@ -1350,16 +986,55 @@ t_nil() -> -spec t_is_nil(erl_type()) -> boolean(). t_is_nil(Type) -> - t_is_nil(Type, 'universe'). - --spec t_is_nil(erl_type(), opaques()) -> boolean(). - -t_is_nil(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_nil/1). + structural(Type, fun is_nil/1). is_nil(?nil) -> true; is_nil(_) -> false. +-spec t_nominal(any(), erl_type()) -> erl_type(). + +t_nominal(Name, Type) -> + case not t_is_impossible(Type) of + true -> ?nominal(Name, Type); + false -> ?none + end. + +-spec t_nominal_module(erl_type()) -> term(). + +t_nominal_module(?nominal({Module, _, _, _},_)) -> Module. + +-ifdef(DEBUG). +-spec t_is_nominal(erl_type()) -> boolean(). + +t_is_nominal(?nominal_set(_,?none)) -> true; +t_is_nominal(?nominal(_,_)) -> true; +t_is_nominal(_) -> false. +-endif. + +-spec t_is_opaque(erl_type()) -> boolean(). + +t_is_opaque(?nominal({_,_,_,opaque},_)) -> true; +t_is_opaque(_) -> false. + +-spec t_is_opaque(erl_type(), module()) -> boolean(). + +t_is_opaque(?nominal({ModA,_,_,opaque},_), ModB) -> + ModA =/= ModB; +t_is_opaque(?nominal_set(Ns, ?none), Mod) -> + %% This is a relaxed check to reduce noise; there are many benign violations + %% of opacity throughout OTP and user code where we have a union of an opaque + %% type and a structural one that doesn't overlap. + lists:any(fun(N) -> t_is_opaque(N, Mod) end, Ns); +t_is_opaque(_, _) -> + false. + +-spec t_is_same_opaque(erl_type(), erl_type()) -> boolean(). + +t_is_same_opaque(?nominal({_,_,_,opaque}=Same,_), ?nominal(Same,_)) -> + true; +t_is_same_opaque(?nominal({_,_,_,opaque},_), ?nominal({_,_,_,opaque},_)) -> + false. + -spec t_list() -> erl_type(). t_list() -> @@ -1373,25 +1048,18 @@ t_list(Contents) -> -spec t_list_elements(erl_type()) -> erl_type(). t_list_elements(Type) -> - t_list_elements(Type, 'universe'). - --spec t_list_elements(erl_type(), opaques()) -> erl_type(). - -t_list_elements(Type, Opaques) -> - do_opaque(Type, Opaques, fun list_elements/1). + structural(Type, fun list_elements/1). list_elements(?list(Contents, _, _)) -> Contents; list_elements(?nil) -> ?none. --spec t_list_termination(erl_type(), opaques()) -> erl_type(). - -t_list_termination(Type, Opaques) -> - do_opaque(Type, Opaques, fun t_list_termination/1). - -spec t_list_termination(erl_type()) -> erl_type(). -t_list_termination(?nil) -> ?nil; -t_list_termination(?list(_, Term, _)) -> Term. +t_list_termination(Type) -> + structural(Type, fun list_termination/1). + +list_termination(?nil) -> ?nil; +list_termination(?list(_, Term, _)) -> Term. -spec t_is_list(erl_type()) -> boolean(). @@ -1444,12 +1112,7 @@ t_maybe_improper_list(Content, Termination) -> -spec t_is_maybe_improper_list(erl_type()) -> boolean(). t_is_maybe_improper_list(Type) -> - t_is_maybe_improper_list(Type, 'universe'). - --spec t_is_maybe_improper_list(erl_type(), opaques()) -> boolean(). - -t_is_maybe_improper_list(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_maybe_improper_list/1). + structural(Type, fun is_maybe_improper_list/1). is_maybe_improper_list(?list(_, _, _)) -> true; is_maybe_improper_list(?nil) -> true; @@ -1465,15 +1128,13 @@ is_maybe_improper_list(_) -> false. %% %% false = t_is_subtype(t_nil(), Termination), %% ?list(Content, Termination, ?any). --spec lift_list_to_pos_empty(erl_type(), opaques()) -> erl_type(). - -lift_list_to_pos_empty(Type, Opaques) -> - do_opaque(Type, Opaques, fun lift_list_to_pos_empty/1). - -spec lift_list_to_pos_empty(erl_type()) -> erl_type(). -lift_list_to_pos_empty(?nil) -> ?nil; -lift_list_to_pos_empty(?list(Content, Termination, _)) -> +lift_list_to_pos_empty(Type) -> + structural(Type, fun lift_list_to_pos_empty_1/1). + +lift_list_to_pos_empty_1(?nil) -> ?nil; +lift_list_to_pos_empty_1(?list(Content, Termination, _)) -> ?list(Content, Termination, ?unknown_qual). -spec t_widen_to_number(erl_type()) -> erl_type(). @@ -1501,10 +1162,11 @@ t_widen_to_number(?map(Pairs, DefK, DefV)) -> t_map(L, t_widen_to_number(DefK), t_widen_to_number(DefV)); t_widen_to_number(?nil) -> ?nil; t_widen_to_number(?number(_Set, _Tag)) -> t_number(); -t_widen_to_number(?opaque(Set)) -> - L = [Opaque#opaque{struct = t_widen_to_number(S)} || - #opaque{struct = S} = Opaque <- Set], - ?opaque(ordsets:from_list(L)); +t_widen_to_number(?nominal(N, S)) -> ?nominal(N, t_widen_to_number(S)); +t_widen_to_number(?nominal_set(N, S)) -> + normalize_nominal_set([t_widen_to_number(Nom) || Nom <- N], + t_widen_to_number(S), + []); t_widen_to_number(?product(Types)) -> ?product(list_widen_to_number(Types)); t_widen_to_number(?tuple(?any, _, _) = T) -> T; @@ -1678,12 +1340,7 @@ map_pairs_are_none([_|Ps]) -> map_pairs_are_none(Ps). -spec t_is_map(erl_type()) -> boolean(). t_is_map(Type) -> - t_is_map(Type, 'universe'). - --spec t_is_map(erl_type(), opaques()) -> boolean(). - -t_is_map(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_map1/1). + structural(Type, fun is_map1/1). is_map1(?map(_, _, _)) -> true; is_map1(_) -> false. @@ -1691,12 +1348,7 @@ is_map1(_) -> false. -spec t_map_entries(erl_type()) -> t_map_dict(). t_map_entries(M) -> - t_map_entries(M, 'universe'). - --spec t_map_entries(erl_type(), opaques()) -> t_map_dict(). - -t_map_entries(M, Opaques) -> - do_opaque(M, Opaques, fun map_entries/1). + structural(M, fun map_entries/1). map_entries(?map(Pairs,_,_)) -> Pairs. @@ -1704,12 +1356,7 @@ map_entries(?map(Pairs,_,_)) -> -spec t_map_def_key(erl_type()) -> erl_type(). t_map_def_key(M) -> - t_map_def_key(M, 'universe'). - --spec t_map_def_key(erl_type(), opaques()) -> erl_type(). - -t_map_def_key(M, Opaques) -> - do_opaque(M, Opaques, fun map_def_key/1). + structural(M, fun map_def_key/1). map_def_key(?map(_,DefK,_)) -> DefK. @@ -1717,12 +1364,7 @@ map_def_key(?map(_,DefK,_)) -> -spec t_map_def_val(erl_type()) -> erl_type(). t_map_def_val(M) -> - t_map_def_val(M, 'universe'). - --spec t_map_def_val(erl_type(), opaques()) -> erl_type(). - -t_map_def_val(M, Opaques) -> - do_opaque(M, Opaques, fun map_def_val/1). + structural(M, fun map_def_val/1). map_def_val(?map(_,_,DefV)) -> DefV. @@ -1746,12 +1388,12 @@ mapdict_insert(E={_,_,_}, T) -> [E|T]. t_map_mandatoriness(), erl_type()) -> t_map_pair() | false). --spec t_map_pairwise_merge(map_pairwise_merge_fun(), erl_type(), erl_type(), - opaques()) -> t_map_dict(). -t_map_pairwise_merge(F, MapA, MapB, Opaques) -> - do_opaque(MapA, Opaques, +-spec t_map_pairwise_merge(map_pairwise_merge_fun(), erl_type(), erl_type()) -> + t_map_dict(). +t_map_pairwise_merge(F, MapA, MapB) -> + structural(MapA, fun(UMapA) -> - do_opaque(MapB, Opaques, + structural(MapB, fun(UMapB) -> map_pairwise_merge(F, UMapA, UMapB) end) @@ -1825,17 +1467,12 @@ mapmerge_otherv(K, ODefK, ODefV) -> -spec t_map_put({erl_type(), erl_type()}, erl_type()) -> erl_type(). t_map_put(KV, Map) -> - t_map_put(KV, Map, 'universe'). - --spec t_map_put({erl_type(), erl_type()}, erl_type(), opaques()) -> erl_type(). - -t_map_put(KV, Map, Opaques) -> - do_opaque(Map, Opaques, fun(UM) -> map_put(KV, UM, Opaques) end). + structural(Map, fun(UM) -> map_put(KV, UM) end). %% Key and Value are *not* unopaqued, but the map is -map_put(_, ?none, _) -> ?none; -map_put(_, ?unit, _) -> ?none; -map_put({Key, Value}, ?map(Pairs,DefK,DefV), Opaques) -> +map_put(_, ?none) -> ?none; +map_put(_, ?unit) -> ?none; +map_put({Key, Value}, ?map(Pairs,DefK,DefV)) -> case t_is_impossible(Key) orelse t_is_impossible(Value) of true -> ?none; false -> @@ -1843,7 +1480,7 @@ map_put({Key, Value}, ?map(Pairs,DefK,DefV), Opaques) -> true -> t_map(mapdict_store({Key, ?mand, Value}, Pairs), DefK, DefV); false -> - t_map([{K, MNess, case t_is_none(t_inf(K, Key, Opaques)) of + t_map([{K, MNess, case t_is_none(t_inf(K, Key)) of true -> V; false -> t_sup(V, Value) end} || {K, MNess, V} <- Pairs], @@ -1852,10 +1489,10 @@ map_put({Key, Value}, ?map(Pairs,DefK,DefV), Opaques) -> end end. --spec t_map_remove(erl_type(), erl_type(), opaques()) -> erl_type(). +-spec t_map_remove(erl_type(), erl_type()) -> erl_type(). -t_map_remove(Key, Map, Opaques) -> - do_opaque(Map, Opaques, fun(UM) -> map_remove(Key, UM) end). +t_map_remove(Key, Map) -> + structural(Map, fun(UM) -> map_remove(Key, UM) end). map_remove(_, ?none) -> ?none; map_remove(_, ?unit) -> ?none; @@ -1875,30 +1512,20 @@ map_remove(Key, Map) -> -spec t_map_update({erl_type(), erl_type()}, erl_type()) -> erl_type(). -t_map_update(KV, Map) -> - t_map_update(KV, Map, 'universe'). - --spec t_map_update({erl_type(), erl_type()}, erl_type(), opaques()) -> erl_type(). - -t_map_update(_, ?none, _) -> ?none; -t_map_update(_, ?unit, _) -> ?none; -t_map_update(KV={Key, _}, M, Opaques) -> - case t_is_subtype(t_atom('true'), t_map_is_key(Key, M, Opaques)) of +t_map_update(_, ?none) -> ?none; +t_map_update(_, ?unit) -> ?none; +t_map_update(KV={Key, _}, M) -> + case t_is_subtype(t_atom('true'), t_map_is_key(Key, M)) of false -> ?none; - true -> t_map_put(KV, M, Opaques) + true -> t_map_put(KV, M) end. -spec t_map_get(erl_type(), erl_type()) -> erl_type(). t_map_get(Key, Map) -> - t_map_get(Key, Map, 'universe'). - --spec t_map_get(erl_type(), erl_type(), opaques()) -> erl_type(). - -t_map_get(Key, Map, Opaques) -> - do_opaque(Map, Opaques, + structural(Map, fun(UM) -> - do_opaque(Key, Opaques, fun(UK) -> map_get(UK, UM) end) + structural(Key, fun(UK) -> map_get(UK, UM) end) end). map_get(_, ?none) -> ?none; @@ -1927,14 +1554,9 @@ map_get(Key, ?map(Pairs, DefK, DefV)) -> -spec t_map_is_key(erl_type(), erl_type()) -> erl_type(). t_map_is_key(Key, Map) -> - t_map_is_key(Key, Map, 'universe'). - --spec t_map_is_key(erl_type(), erl_type(), opaques()) -> erl_type(). - -t_map_is_key(Key, Map, Opaques) -> - do_opaque(Map, Opaques, + structural(Map, fun(UM) -> - do_opaque(Key, Opaques, fun(UK) -> map_is_key(UK, UM) end) + structural(Key, fun(UK) -> map_is_key(UK, UM) end) end). map_is_key(_, ?none) -> ?none; @@ -1995,7 +1617,7 @@ t_tuple(List) -> -spec get_tuple_tags([erl_type()]) -> [erl_type(),...]. get_tuple_tags([Tag|_]) -> - do_opaque(Tag, 'universe', fun tuple_tags/1); + structural(Tag, fun tuple_tags/1); get_tuple_tags(_) -> [?any]. tuple_tags(?atom(?any)) -> [?any]; @@ -2010,13 +1632,7 @@ tuple_tags(_) -> [?any]. -spec t_tuple_args(erl_type()) -> [erl_type()]. t_tuple_args(Type) -> - t_tuple_args(Type, 'universe'). - -%% to be used for a tuple with known types for its arguments (not ?any) --spec t_tuple_args(erl_type(), opaques()) -> [erl_type()]. - -t_tuple_args(Type, Opaques) -> - do_opaque(Type, Opaques, fun tuple_args/1). + structural(Type, fun tuple_args/1). tuple_args(?tuple(Args, _, _)) when is_list(Args) -> Args. @@ -2024,61 +1640,32 @@ tuple_args(?tuple(Args, _, _)) when is_list(Args) -> Args. -spec t_tuple_size(erl_type()) -> non_neg_integer(). t_tuple_size(Type) -> - t_tuple_size(Type, 'universe'). - -%% to be used for a tuple with a known size (not ?any) --spec t_tuple_size(erl_type(), opaques()) -> non_neg_integer(). - -t_tuple_size(Type, Opaques) -> - do_opaque(Type, Opaques, fun tuple_size1/1). + structural(Type, fun tuple_size1/1). tuple_size1(?tuple(_, Size, _)) when is_integer(Size) -> Size. -spec t_tuple_sizes(erl_type()) -> 'unknown' | [non_neg_integer(),...]. t_tuple_sizes(Type) -> - do_opaque(Type, 'universe', fun tuple_sizes/1). + structural(Type, fun tuple_sizes/1). tuple_sizes(?tuple(?any, ?any, ?any)) -> unknown; tuple_sizes(?tuple(_, Size, _)) when is_integer(Size) -> [Size]; tuple_sizes(?tuple_set(List)) -> [Size || {Size, _} <- List]. --spec t_tuple_subtypes(erl_type(), opaques()) -> - 'unknown' | [erl_type(),...]. - -t_tuple_subtypes(Type, Opaques) -> - Fun = fun(?tuple_set(List)) -> - t_tuple_subtypes_tuple_list(List, Opaques); - (?opaque(_)) -> unknown; - (T) -> t_tuple_subtypes(T) - end, - do_opaque(Type, Opaques, Fun). - -t_tuple_subtypes_tuple_list(List, Opaques) -> - lists:append([t_tuple_subtypes_list(Tuples, Opaques) || - {_Size, Tuples} <- List]). - -t_tuple_subtypes_list(List, Opaques) -> - ListOfLists = [t_tuple_subtypes(E, Opaques) || E <- List, E =/= ?none], - lists:append([L || L <- ListOfLists, L =/= 'unknown']). - -spec t_tuple_subtypes(erl_type()) -> 'unknown' | [erl_type(),...]. +t_tuple_subtypes(Type) -> + structural(Type, fun tuple_subtypes/1). -%% XXX. Not the same as t_tuple_subtypes(T, 'universe')... -t_tuple_subtypes(?tuple(?any, ?any, ?any)) -> unknown; -t_tuple_subtypes(?tuple(_, _, _) = T) -> [T]; -t_tuple_subtypes(?tuple_set(List)) -> +tuple_subtypes(?tuple(?any, ?any, ?any)) -> unknown; +tuple_subtypes(?tuple(_, _, _) = T) -> [T]; +tuple_subtypes(?tuple_set(List)) -> lists:append([Tuples || {_Size, Tuples} <- List]). -spec t_is_tuple(erl_type()) -> boolean(). t_is_tuple(Type) -> - t_is_tuple(Type, 'universe'). - --spec t_is_tuple(erl_type(), opaques()) -> boolean(). - -t_is_tuple(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_tuple1/1). + structural(Type, fun is_tuple1/1). is_tuple1(?tuple(_, _, _)) -> true; is_tuple1(?tuple_set(_)) -> true; @@ -2216,6 +1803,10 @@ t_has_var(?list(Contents, ?nil, _)) -> t_has_var(Contents); t_has_var(?list(Contents, Termination, _)) -> t_has_var(Contents) orelse t_has_var(Termination); +t_has_var(?nominal(_, S)) -> + t_has_var(S); +t_has_var(?nominal_set(N, S)) -> + t_has_var(S) andalso lists:any(fun t_has_var/1, N); t_has_var(?product(Types)) -> t_has_var_list(Types); t_has_var(?tuple(?any, ?any, ?any)) -> false; t_has_var(?tuple(Elements, _, _)) -> @@ -2225,8 +1816,6 @@ t_has_var(?tuple_set(_) = T) -> t_has_var(?map(_, DefK, _)= Map) -> t_has_var_list(map_all_values(Map)) orelse t_has_var(DefK); -t_has_var(?opaque(Set)) -> - t_has_var_list([O#opaque.struct || O <- Set]); t_has_var(?union(List)) -> t_has_var_list(List); t_has_var(_) -> false. @@ -2264,8 +1853,10 @@ t_collect_var_names(?tuple_set(_) = TS, Acc) -> t_collect_var_names(?map(_, DefK, _) = Map, Acc0) -> Acc = t_collect_vars_list(map_all_values(Map), Acc0), t_collect_var_names(DefK, Acc); -t_collect_var_names(?opaque(Set), Acc) -> - t_collect_vars_list([O#opaque.struct || O <- Set], Acc); +t_collect_var_names(?nominal(_, S), Acc) -> + t_collect_var_names(S, Acc); +t_collect_var_names(?nominal_set(N, S), Acc) -> + t_collect_vars_list(N, t_collect_var_names(S, Acc)); t_collect_var_names(?union(List), Acc) -> t_collect_vars_list(List, Acc); t_collect_var_names(_, Acc) -> @@ -2362,12 +1953,7 @@ t_from_range(pos_inf, neg_inf) -> t_none(). -spec number_min(erl_type()) -> rng_elem(). number_min(Type) -> - number_min(Type, 'universe'). - --spec number_min(erl_type(), opaques()) -> rng_elem(). - -number_min(Type, Opaques) -> - do_opaque(Type, Opaques, fun number_min2/1). + structural(Type, fun number_min2/1). number_min2(?int_range(From, _)) -> From; number_min2(?int_set(Set)) -> set_min(Set); @@ -2376,12 +1962,7 @@ number_min2(?number(?any, _Tag)) -> neg_inf. -spec number_max(erl_type()) -> rng_elem(). number_max(Type) -> - number_max(Type, 'universe'). - --spec number_max(erl_type(), opaques()) -> rng_elem(). - -number_max(Type, Opaques) -> - do_opaque(Type, Opaques, fun number_max2/1). + structural(Type, fun number_max2/1). number_max2(?int_range(_, To)) -> To; number_max2(?int_set(Set)) -> set_max(Set); @@ -2458,36 +2039,39 @@ t_sup1([], Type) -> -spec t_sup(erl_type(), erl_type()) -> erl_type(). -t_sup(?any, _) -> ?any; -t_sup(_, ?any) -> ?any; -t_sup(?none, T) -> T; -t_sup(T, ?none) -> T; -t_sup(?unit, T) -> T; -t_sup(T, ?unit) -> T; -t_sup(T, T) -> do_not_subst_all_vars_to_any(T); -t_sup(?var(_), _) -> ?any; -t_sup(_, ?var(_)) -> ?any; -t_sup(?atom(Set1), ?atom(Set2)) -> +t_sup(T1, T2) -> + Res = t_sup_aux(T1, T2), + %% `Res` must be at least as general as both `T1` and `T2`. + ?debug(t_is_subtype(subst_all_vars_to_any(T1), Res) andalso + t_is_subtype(subst_all_vars_to_any(T2), Res), + {T1, T2, Res}), + Res. + +t_sup_aux(?any, _) -> ?any; +t_sup_aux(_, ?any) -> ?any; +t_sup_aux(?none, T) -> T; +t_sup_aux(T, ?none) -> T; +t_sup_aux(?unit, T) -> T; +t_sup_aux(T, ?unit) -> T; +t_sup_aux(T, T) -> do_not_subst_all_vars_to_any(T); +t_sup_aux(?opaque, T) -> T; +t_sup_aux(T, ?opaque) -> T; +t_sup_aux(?var(_), _) -> ?any; +t_sup_aux(_, ?var(_)) -> ?any; +t_sup_aux(?atom(Set1), ?atom(Set2)) -> ?atom(set_union(Set1, Set2)); -t_sup(?bitstr(U1, B1), ?bitstr(U2, B2)) -> +t_sup_aux(?bitstr(U1, B1), ?bitstr(U2, B2)) -> t_bitstr(gcd(gcd(U1, U2), abs(B1-B2)), lists:min([B1, B2])); -t_sup(?function(Domain1, Range1), ?function(Domain2, Range2)) -> +t_sup_aux(?function(Domain1, Range1), ?function(Domain2, Range2)) -> %% The domain is either a product or any. - ?function(t_sup(Domain1, Domain2), t_sup(Range1, Range2)); -t_sup(?identifier(Set1), ?identifier(Set2)) -> + ?function(t_sup_aux(Domain1, Domain2), t_sup_aux(Range1, Range2)); +t_sup_aux(?identifier(Set1), ?identifier(Set2)) -> ?identifier(set_union(Set1, Set2)); -t_sup(?opaque(Set1), ?opaque(Set2)) -> - sup_opaque(ordsets:union(Set1, Set2)); -%%Disallow unions with opaque types -%%t_sup(T1=?opaque(_,_,_), T2) -> -%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none; -%%t_sup(T1, T2=?opaque(_,_,_)) -> -%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none; -t_sup(?nil, ?list(Contents, Termination, _)) -> - ?list(Contents, t_sup(?nil, Termination), ?unknown_qual); -t_sup(?list(Contents, Termination, _), ?nil) -> - ?list(Contents, t_sup(?nil, Termination), ?unknown_qual); -t_sup(?list(Contents1, Termination1, Size1), +t_sup_aux(?nil, ?list(Contents, Termination, _)) -> + ?list(Contents, t_sup_aux(?nil, Termination), ?unknown_qual); +t_sup_aux(?list(Contents, Termination, _), ?nil) -> + ?list(Contents, t_sup_aux(?nil, Termination), ?unknown_qual); +t_sup_aux(?list(Contents1, Termination1, Size1), ?list(Contents2, Termination2, Size2)) -> NewSize = case {Size1, Size2} of @@ -2496,43 +2080,43 @@ t_sup(?list(Contents1, Termination1, Size1), {?nonempty_qual, ?unknown_qual} -> ?unknown_qual; {?nonempty_qual, ?nonempty_qual} -> ?nonempty_qual end, - NewContents = t_sup(Contents1, Contents2), - NewTermination = t_sup(Termination1, Termination2), + NewContents = t_sup_aux(Contents1, Contents2), + NewTermination = t_sup_aux(Termination1, Termination2), ?list(NewContents, NewTermination, NewSize); -t_sup(?number(_, _), ?number(?any, ?unknown_qual) = T) -> T; -t_sup(?number(?any, ?unknown_qual) = T, ?number(_, _)) -> T; -t_sup(?float, ?integer(_)) -> t_number(); -t_sup(?integer(_), ?float) -> t_number(); -t_sup(?integer(?any) = T, ?integer(_)) -> T; -t_sup(?integer(_), ?integer(?any) = T) -> T; -t_sup(?int_set(Set1), ?int_set(Set2)) -> +t_sup_aux(?number(_, _), ?number(?any, ?unknown_qual) = T) -> T; +t_sup_aux(?number(?any, ?unknown_qual) = T, ?number(_, _)) -> T; +t_sup_aux(?float, ?integer(_)) -> t_number(); +t_sup_aux(?integer(_), ?float) -> t_number(); +t_sup_aux(?integer(?any) = T, ?integer(_)) -> T; +t_sup_aux(?integer(_), ?integer(?any) = T) -> T; +t_sup_aux(?int_set(Set1), ?int_set(Set2)) -> case set_union(Set1, Set2) of ?any -> t_from_range(min(set_min(Set1), set_min(Set2)), max(set_max(Set1), set_max(Set2))); Set -> ?int_set(Set) end; -t_sup(?int_range(From1, To1), ?int_range(From2, To2)) -> +t_sup_aux(?int_range(From1, To1), ?int_range(From2, To2)) -> t_from_range(min(From1, From2), max(To1, To2)); -t_sup(Range = ?int_range(_, _), ?int_set(Set)) -> +t_sup_aux(Range = ?int_range(_, _), ?int_set(Set)) -> expand_range_from_set(Range, Set); -t_sup(?int_set(Set), Range = ?int_range(_, _)) -> +t_sup_aux(?int_set(Set), Range = ?int_range(_, _)) -> expand_range_from_set(Range, Set); -t_sup(?product(Types1), ?product(Types2)) -> +t_sup_aux(?product(Types1), ?product(Types2)) -> L1 = length(Types1), L2 = length(Types2), if L1 =:= L2 -> ?product(t_sup_lists(Types1, Types2)); true -> ?any end; -t_sup(?product(_), _) -> +t_sup_aux(?product(_), _) -> ?any; -t_sup(_, ?product(_)) -> +t_sup_aux(_, ?product(_)) -> ?any; -t_sup(?tuple(?any, ?any, ?any) = T, ?tuple(_, _, _)) -> T; -t_sup(?tuple(_, _, _), ?tuple(?any, ?any, ?any) = T) -> T; -t_sup(?tuple(?any, ?any, ?any) = T, ?tuple_set(_)) -> T; -t_sup(?tuple_set(_), ?tuple(?any, ?any, ?any) = T) -> T; -t_sup(?tuple(Elements1, Arity, Tag1) = T1, +t_sup_aux(?tuple(?any, ?any, ?any) = T, ?tuple(_, _, _)) -> T; +t_sup_aux(?tuple(_, _, _), ?tuple(?any, ?any, ?any) = T) -> T; +t_sup_aux(?tuple(?any, ?any, ?any) = T, ?tuple_set(_)) -> T; +t_sup_aux(?tuple_set(_), ?tuple(?any, ?any, ?any) = T) -> T; +t_sup_aux(?tuple(Elements1, Arity, Tag1) = T1, ?tuple(Elements2, Arity, Tag2) = T2) -> if Tag1 == Tag2 -> t_tuple(t_sup_lists(Elements1, Elements2)); Tag1 == ?any -> t_tuple(t_sup_lists(Elements1, Elements2)); @@ -2540,47 +2124,108 @@ t_sup(?tuple(Elements1, Arity, Tag1) = T1, Tag1 < Tag2 -> ?tuple_set([{Arity, [T1, T2]}]); Tag1 > Tag2 -> ?tuple_set([{Arity, [T2, T1]}]) end; -t_sup(?tuple(_, Arity1, _) = T1, ?tuple(_, Arity2, _) = T2) -> +t_sup_aux(?tuple(_, Arity1, _) = T1, ?tuple(_, Arity2, _) = T2) -> sup_tuple_sets([{Arity1, [T1]}], [{Arity2, [T2]}]); -t_sup(?tuple_set(List1), ?tuple_set(List2)) -> +t_sup_aux(?tuple_set(List1), ?tuple_set(List2)) -> sup_tuple_sets(List1, List2); -t_sup(?tuple_set(List1), T2 = ?tuple(_, Arity, _)) -> +t_sup_aux(?tuple_set(List1), T2 = ?tuple(_, Arity, _)) -> sup_tuple_sets(List1, [{Arity, [T2]}]); -t_sup(?tuple(_, Arity, _) = T1, ?tuple_set(List2)) -> +t_sup_aux(?tuple(_, Arity, _) = T1, ?tuple_set(List2)) -> sup_tuple_sets([{Arity, [T1]}], List2); -t_sup(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) -> +t_sup_aux(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) -> Pairs = map_pairwise_merge( - fun(K, MNess, V1, MNess, V2) -> {K, MNess, t_sup(V1, V2)}; - (K, _, V1, _, V2) -> {K, ?opt, t_sup(V1, V2)} + fun(K, MNess, V1, MNess, V2) -> {K, MNess, t_sup_aux(V1, V2)}; + (K, _, V1, _, V2) -> {K, ?opt, t_sup_aux(V1, V2)} end, A, B), - t_map(Pairs, t_sup(ADefK, BDefK), t_sup(ADefV, BDefV)); -t_sup(T1, T2) -> + t_map(Pairs, t_sup_aux(ADefK, BDefK), t_sup_aux(ADefV, BDefV)); +%% Union of 1 or more nominal types/nominal sets +t_sup_aux(?nominal(Name, S1), ?nominal(Name, S2)) -> + ?nominal(Name, t_sup_aux(S1, S2)); +t_sup_aux(?nominal(LHS_Name, ?nominal(LHS_InnerName, _)=LHS_Inner)=LHS, + ?nominal(RHS_Name, ?nominal(RHS_InnerName, _)=RHS_Inner)=RHS) -> + case t_sup_aux(LHS_Inner, RHS_Inner) of + ?nominal(LHS_InnerName = RHS_Name, _)=Sup -> + ?nominal(RHS_Name, Sup); + ?nominal(RHS_InnerName = LHS_Name, _)=Sup -> + ?nominal(LHS_Name, Sup); + ?nominal_set(_, ?none) when LHS_Name < RHS_Name -> + ?nominal_set([LHS, RHS], ?none); + ?nominal_set(_, ?none) -> + ?nominal_set([RHS, LHS], ?none) + end; +t_sup_aux(?nominal(LHS_Name, ?nominal(_, _)=LHS_Inner), + ?nominal(_, ?nominal_set(_, _))=RHS) -> + t_sup_aux(?nominal(LHS_Name, ?nominal_set([LHS_Inner], ?none)), RHS); +t_sup_aux(?nominal(_, ?nominal_set(_, _))=LHS, + ?nominal(_, ?nominal(_, _))=RHS) -> + t_sup_aux(RHS, LHS); +t_sup_aux(?nominal(LHS_Name, ?nominal(LHS_InnerName, _)=LHS_Inner)=LHS, + ?nominal(RHS_Name, _)=RHS) -> + case t_sup_aux(LHS_Inner, RHS) of + ?nominal_set(_, ?none) when LHS_Name < RHS_Name -> + ?nominal_set([LHS, RHS], ?none); + ?nominal_set(_, ?none) -> + ?nominal_set([RHS, LHS], ?none); + ?nominal(RHS_Name, _)=Sup -> + Sup; + ?nominal(LHS_InnerName, _)=Sup -> + ?nominal(LHS_Name, Sup) + end; +t_sup_aux(?nominal(_, _)=LHS, ?nominal(_, ?nominal(_,_))=RHS) -> + t_sup_aux(RHS, LHS); +t_sup_aux(?nominal(LHS_Name, ?nominal_set(L_Ns, L_S)), + ?nominal(RHS_Name, ?nominal_set(R_Ns, R_S))) -> + Sup0 = t_sup_aux(?nominal(LHS_Name, L_S), + ?nominal(RHS_Name, R_S)), + LHS_Expanded = [?nominal(LHS_Name, N) || N <- L_Ns], + RHS_Expanded = [?nominal(RHS_Name, N) || N <- R_Ns], + Sup = lists:foldl(fun t_sup_aux/2, Sup0, LHS_Expanded), + lists:foldl(fun t_sup_aux/2, Sup, RHS_Expanded); +t_sup_aux(?nominal(LHS_Name, ?nominal_set(L_Ns, L_S)), + ?nominal(_, _)=RHS) -> + LHS_Expanded = [?nominal(LHS_Name, N) || N <- L_Ns], + Sup = nominal_set_absorb(LHS_Expanded, RHS, []), + t_sup_aux(Sup, ?nominal(LHS_Name, L_S)); +t_sup_aux(?nominal(_, _)=LHS, ?nominal(_, ?nominal_set(_,_))=RHS) -> + t_sup_aux(RHS, LHS); +t_sup_aux(?nominal(LHS_Name, _)=LHS, ?nominal(RHS_Name, _)=RHS) -> + case LHS_Name < RHS_Name of + true -> ?nominal_set([LHS, RHS], ?none); + false -> ?nominal_set([RHS, LHS], ?none) + end; +t_sup_aux(?nominal_set(LHS_Ns, LHS_S), ?nominal_set(RHS_Ns, RHS_S)) -> + Sup0 = t_sup_aux(LHS_S, RHS_S), + ?debug(not t_is_nominal(Sup0), {LHS_S, RHS_S}), + Sup = lists:foldl(fun t_sup_aux/2, Sup0, LHS_Ns), + lists:foldl(fun t_sup_aux/2, Sup, RHS_Ns); +t_sup_aux(?nominal_set(LHS_Ns, ?none), ?nominal(_, _)=RHS) -> + nominal_set_absorb(LHS_Ns, RHS, []); +t_sup_aux(?nominal_set(LHS_Ns, Other), ?nominal(_, _)=RHS) -> + t_sup_aux(t_sup_aux(?nominal_set(LHS_Ns, ?none), RHS), Other); +t_sup_aux(?nominal(_, _)=LHS, ?nominal_set(_, _)=RHS) -> + t_sup_aux(RHS, LHS); +t_sup_aux(?nominal(_,LHS_S)=LHS, RHS) -> + ?debug(not t_is_nominal(RHS), RHS), + Inf = t_inf_aux(LHS_S, RHS), + case t_is_impossible(Inf) of + true -> ?nominal_set([LHS], RHS); + false -> t_sup_aux(LHS_S, RHS) + end; +t_sup_aux(LHS, ?nominal(_, _)=RHS) -> + ?debug(not t_is_nominal(LHS), LHS), + t_sup_aux(RHS, LHS); +t_sup_aux(?nominal_set(LHS_Ns, LHS_S), RHS) -> + ?debug(not t_is_nominal(RHS), RHS), + normalize_nominal_set(LHS_Ns, t_sup_aux(LHS_S, RHS), []); +t_sup_aux(LHS, ?nominal_set(_, _)=RHS) -> + ?debug(not t_is_nominal(LHS), LHS), + t_sup_aux(RHS, LHS); +t_sup_aux(T1, T2) -> ?union(U1) = force_union(T1), ?union(U2) = force_union(T2), sup_union(U1, U2). -sup_opaque([]) -> ?none; -sup_opaque(List) -> - L = sup_opaq(List), - ?opaque(ordsets:from_list(L)). - -sup_opaq(L0) -> - L1 = [{{Mod,Name,Arity}, T} || - #opaque{mod = Mod, name = Name, arity = Arity}=T <- L0], - F = dialyzer_utils:family(L1), - [supl(Ts) || {_, Ts} <- F]. - -supl([O]) -> O; -supl(Ts) -> supl(Ts, t_none()). - -supl([#opaque{struct = S}=O|L], S0) -> - S1 = t_sup(S, S0), - case L =:= [] of - true -> O#opaque{struct = S1}; - false -> supl(L, S1) - end. - -spec t_sup_lists([erl_type()], [erl_type()]) -> [erl_type()]. t_sup_lists([T1|Left1], [T2|Left2]) -> @@ -2588,6 +2233,73 @@ t_sup_lists([T1|Left1], [T2|Left2]) -> t_sup_lists([], []) -> []. +%% Adds the new nominal `Sup` into the set of nominals `Ns0`. Note that it does +%% not handle structurals; the caller is expected to normalize the result +%% afterwards. +nominal_set_absorb([?nominal(_, _)=N | Ns0], Sup, Acc) -> + ?debug(t_is_nominal(Sup), Sup), + case t_inf_aux(N, Sup) of + ?nominal(_, _) -> + %% The types overlap, abort and start over with the widened type. + t_sup_aux(?nominal_set(lists:reverse(Acc, Ns0), ?none), + t_sup_aux(N, Sup)); + ?none -> + nominal_set_absorb(Ns0, Sup, [N | Acc]) + end; +nominal_set_absorb([], Sup, Acc) -> + ?debug(t_is_nominal(Sup), Sup), + Ns = nominal_set_absorb_merge(Acc, Sup, []), + ?debug(begin + Names = [Name || ?nominal(Name, _) <- Ns], + Names =:= lists:usort(Names) + end, {Sup, Acc, Ns}), + ?nominal_set(Ns, ?none). + +nominal_set_absorb_merge([?nominal(Same, LHS_S) | Rest], + ?nominal(Same, RHS_S), Acc) -> + lists:reverse([?nominal(Same, t_sup_aux(LHS_S, RHS_S)) | Rest], Acc); +nominal_set_absorb_merge([?nominal(LHS_Name, _)=LHS | Rest], + ?nominal(RHS_Name, _)=RHS, Acc) + when LHS_Name > RHS_Name -> + %% Note that the list is reversed, so '>' puts this in ascending order. + nominal_set_absorb_merge(Rest, RHS, [LHS | Acc]); +nominal_set_absorb_merge(Rest, RHS, Acc) -> + lists:reverse([RHS | Rest], Acc). + +normalize_nominal_set(_, ?any, _) -> + ?any; +normalize_nominal_set([], Other, []) -> + ?debug(not t_is_nominal(Other), Other), + Other; +normalize_nominal_set([], ?none, [?nominal(_, _) = N]) -> + N; +normalize_nominal_set([], Other, Nominals0) -> + %% Names must be unique and in the correct order. + Nominals = lists:reverse(Nominals0), + ?debug(begin + Names = [Name || ?nominal(Name, _) <- Nominals], + Names =:= lists:usort(Names) + end, Nominals), + ?nominal_set(Nominals, Other); +normalize_nominal_set([?nominal(_, _)=Type | Types], ?none, Nominals) -> + normalize_nominal_set(Types, ?none, [Type | Nominals]); +normalize_nominal_set([?none | Types], Other, Nominals) -> + normalize_nominal_set(Types, Other, Nominals); +normalize_nominal_set([Type | Types], Other, Nominals) -> + case t_inf_aux(Type, Other) of + ?none -> + %% The `Other` type does not overlap with the nominal type, include it + %% in the new nominal list. + ?nominal(_, _) = Type, %Assertion. + normalize_nominal_set(Types, Other, [Type | Nominals]); + _ -> + %% `Type` is structural (can happen during limiting) or overlaps with + %% `Other0`, start over since the new `Other` type could overlap with + %% previously-handled nominals. + t_sup_aux(?nominal_set(lists:reverse(Nominals, Types), ?none), + t_sup_aux(Type, Other)) + end. + sup_tuple_sets(L1, L2) -> TotalArities = ordsets:union([Arity || {Arity, _} <- L1], [Arity || {Arity, _} <- L2]), @@ -2651,6 +2363,8 @@ sup_tuples_in_set([], L2, Acc) -> lists:reverse(Acc, L2); sup_tuples_in_set(L1, [], Acc) -> lists:reverse(Acc, L1). sup_union(U1, U2) -> + true = length(U1) =:= length(U2), %Assertion. + true = ?num_types_in_union =:= length(U1), %Assertion sup_union(U1, U2, 0, []). sup_union([?none|Left1], [?none|Left2], N, Acc) -> @@ -2665,7 +2379,10 @@ sup_union([], [], N, Acc) -> [Type] = [T || T <- Acc, T =/= ?none], Type; N =:= ?num_types_in_union -> - ?any; + case Acc == [t_tuple(), t_map(), ?any, t_number(), t_list(), t_identifier(), t_fun(), t_bitstr(), t_atom()] of + true -> ?any; + false -> ?union(lists:reverse(Acc)) + end; true -> ?union(lists:reverse(Acc)) end. @@ -2677,7 +2394,6 @@ force_union(T = ?identifier(_)) -> ?identifier_union(T); force_union(T = ?list(_, _, _)) -> ?list_union(T); force_union(T = ?nil) -> ?list_union(T); force_union(T = ?number(_, _)) -> ?number_union(T); -force_union(T = ?opaque(_)) -> ?opaque_union(T); force_union(T = ?map(_,_,_)) -> ?map_union(T); force_union(T = ?tuple(_, _, _)) -> ?tuple_union(T); force_union(T = ?tuple_set(_)) -> ?tuple_union(T); @@ -2687,25 +2403,23 @@ force_union(T = ?union(_)) -> T. %% An attempt to write the inverse operation of t_sup/1 -- XXX: INCOMPLETE !! %% -spec t_elements(erl_type()) -> [erl_type()]. -t_elements(T) -> - t_elements(T, 'universe'). - --spec t_elements(erl_type(), opaques()) -> [erl_type()]. - -t_elements(?none, _Opaques) -> []; -t_elements(?unit, _Opaques) -> []; -t_elements(?any = T, _Opaques) -> [T]; -t_elements(?nil = T, _Opaques) -> [T]; -t_elements(?atom(?any) = T, _Opaques) -> [T]; -t_elements(?atom(Atoms), _Opaques) -> +t_elements(?none) -> []; +t_elements(?unit) -> []; +t_elements(?any = T) -> [T]; +t_elements(?nil = T) -> [T]; +t_elements(?atom(?any) = T) -> [T]; +t_elements(?atom(Atoms)) -> [t_atom(A) || A <- Atoms]; -t_elements(?bitstr(_, _) = T, _Opaques) -> [T]; -t_elements(?function(_, _) = T, _Opaques) -> [T]; -t_elements(?identifier(?any) = T, _Opaques) -> [T]; -t_elements(?identifier(IDs), _Opaques) -> +t_elements(?bitstr(_, _) = T) -> [T]; +t_elements(?function(_, _) = T) -> [T]; +t_elements(?identifier(?any) = T) -> [T]; +t_elements(?identifier(IDs)) -> [?identifier([T]) || T <- IDs]; -t_elements(?list(_, _, _) = T, _Opaques) -> [T]; -t_elements(?number(_, _) = T, _Opaques) -> +t_elements(?nominal(_, _) = T) -> [T]; +t_elements(?nominal_set(Ns, S)) -> + t_elements(S) ++ Ns; +t_elements(?list(_, _, _) = T) -> [T]; +t_elements(?number(_, _) = T) -> case T of ?number(?any, ?unknown_qual) -> [?float, ?integer(?any)]; @@ -2715,30 +2429,26 @@ t_elements(?number(_, _) = T, _Opaques) -> ?int_set(Set) -> [t_integer(I) || I <- Set] end; -t_elements(?opaque(_) = T, Opaques) -> - do_elements(T, Opaques); -t_elements(?map(_,_,_) = T, _Opaques) -> [T]; -t_elements(?tuple(_, _, _) = T, _Opaques) -> [T]; -t_elements(?tuple_set(_) = TS, _Opaques) -> +t_elements(?map(_,_,_) = T) -> [T]; +t_elements(?product(_) = T) -> [T]; +t_elements(?tuple(_, _, _) = T) -> [T]; +t_elements(?tuple_set(_) = TS) -> case t_tuple_subtypes(TS) of unknown -> []; Elems -> Elems end; -t_elements(?union(_) = T, Opaques) -> - do_elements(T, Opaques); -t_elements(?var(_), _Opaques) -> [?any]. %% yes, vars exist -- what else to do here? +t_elements(?union(_) = T) -> + do_elements(T); +t_elements(?var(_)) -> [?any]. %% yes, vars exist -- what else to do here? %% t_elements(T) -> %% io:format("T_ELEMENTS => ~p\n", [T]). -do_elements(Type0, Opaques) -> - case do_opaque(Type0, Opaques, fun(T) -> T end) of +do_elements(Type0) -> + case structural(Type0, fun(T) -> T end) of ?union(List) -> - lists:append([t_elements(T, Opaques) || T <- List]); - ?opaque(_)=Type -> - %% We lack insight into this opaque type, return it as-is. - [Type]; + lists:append([t_elements(T) || T <- List]); Type -> - t_elements(Type, Opaques) + t_elements(Type) end. %%----------------------------------------------------------------------------- @@ -2758,53 +2468,55 @@ t_inf([]) -> ?none. -spec t_inf(erl_type(), erl_type()) -> erl_type(). t_inf(T1, T2) -> - t_inf(T1, T2, 'universe'). - -%% 'match' should be used from t_find_unknown_opaque() only --type t_inf_opaques() :: opaques() | {'match', [erl_type() | 'universe']}. - --spec t_inf(erl_type(), erl_type(), t_inf_opaques()) -> erl_type(). - -t_inf(?var(_), ?var(_), _Opaques) -> ?any; -t_inf(?var(_), T, _Opaques) -> do_not_subst_all_vars_to_any(T); -t_inf(T, ?var(_), _Opaques) -> do_not_subst_all_vars_to_any(T); -t_inf(?any, T, _Opaques) -> do_not_subst_all_vars_to_any(T); -t_inf(T, ?any, _Opaques) -> do_not_subst_all_vars_to_any(T); -t_inf(?none, _, _Opaques) -> ?none; -t_inf(_, ?none, _Opaques) -> ?none; -t_inf(?unit, _, _Opaques) -> ?unit; % ?unit cases should appear below ?none -t_inf(_, ?unit, _Opaques) -> ?unit; -t_inf(T, T, _Opaques) -> do_not_subst_all_vars_to_any(T); -t_inf(?atom(Set1), ?atom(Set2), _) -> + Res = t_inf_aux(T1, T2), + %% `Res` must be at least as specific as `T1` and `T2` + ?debug(t_is_subtype(subst_all_vars_to_any(Res), + subst_all_vars_to_any(T1)) andalso + t_is_subtype(subst_all_vars_to_any(Res), + subst_all_vars_to_any(T2)), + {T1, T2, Res}), + Res. + +t_inf_aux(?var(_), ?var(_)) -> ?any; +t_inf_aux(?var(_), T) -> do_not_subst_all_vars_to_any(T); +t_inf_aux(T, ?var(_)) -> do_not_subst_all_vars_to_any(T); +t_inf_aux(?any, T) -> do_not_subst_all_vars_to_any(T); +t_inf_aux(T, ?any) -> do_not_subst_all_vars_to_any(T); +t_inf_aux(?none, _) -> ?none; +t_inf_aux(_, ?none) -> ?none; +t_inf_aux(?unit, _) -> ?unit; % ?unit cases should appear below ?none +t_inf_aux(_, ?unit) -> ?unit; +t_inf_aux(T, T) -> do_not_subst_all_vars_to_any(T); +t_inf_aux(?atom(Set1), ?atom(Set2)) -> case set_intersection(Set1, Set2) of ?none -> ?none; NewSet -> ?atom(NewSet) end; -t_inf(?bitstr(U1, B1), ?bitstr(0, B2), _Opaques) -> +t_inf_aux(?bitstr(U1, B1), ?bitstr(0, B2)) -> if B2 >= B1 andalso (B2-B1) rem U1 =:= 0 -> t_bitstr(0, B2); true -> ?none end; -t_inf(?bitstr(0, B1), ?bitstr(U2, B2), _Opaques) -> +t_inf_aux(?bitstr(0, B1), ?bitstr(U2, B2)) -> if B1 >= B2 andalso (B1-B2) rem U2 =:= 0 -> t_bitstr(0, B1); true -> ?none end; -t_inf(?bitstr(U1, B1), ?bitstr(U1, B1), _Opaques) -> +t_inf_aux(?bitstr(U1, B1), ?bitstr(U1, B1)) -> t_bitstr(U1, B1); -t_inf(?bitstr(U1, B1), ?bitstr(U2, B2), _Opaques) when U2 > U1 -> +t_inf_aux(?bitstr(U1, B1), ?bitstr(U2, B2)) when U2 > U1 -> inf_bitstr(U2, B2, U1, B1); -t_inf(?bitstr(U1, B1), ?bitstr(U2, B2), _Opaques) -> +t_inf_aux(?bitstr(U1, B1), ?bitstr(U2, B2)) -> inf_bitstr(U1, B1, U2, B2); -t_inf(?function(Domain1, Range1), ?function(Domain2, Range2), Opaques) -> - case t_inf(Domain1, Domain2, Opaques) of +t_inf_aux(?function(Domain1, Range1), ?function(Domain2, Range2)) -> + case t_inf_aux(Domain1, Domain2) of ?none -> ?none; - Domain -> ?function(Domain, t_inf(Range1, Range2, Opaques)) + Domain -> ?function(Domain, t_inf_aux(Range1, Range2)) end; -t_inf(?identifier(Set1), ?identifier(Set2), _Opaques) -> +t_inf_aux(?identifier(Set1), ?identifier(Set2)) -> case set_intersection(Set1, Set2) of ?none -> ?none; Set -> ?identifier(Set) end; -t_inf(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B, _Opaques) -> +t_inf_aux(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) -> %% Because it simplifies the anonymous function, we allow Pairs to temporarily %% contain mandatory pairs with none values, since all such cases should %% result in a none result. @@ -2812,27 +2524,95 @@ t_inf(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B, _Opaques) -> map_pairwise_merge( %% For optional keys in both maps, when the infimum is none, we have %% essentially concluded that K must not be a key in the map. - fun(K, ?opt, V1, ?opt, V2) -> {K, ?opt, t_inf(V1, V2)}; + fun(K, ?opt, V1, ?opt, V2) -> {K, ?opt, t_inf_aux(V1, V2)}; %% When a key is optional in one map, but mandatory in another, it %% becomes mandatory in the infinumum - (K, _, V1, _, V2) -> {K, ?mand, t_inf(V1, V2)} + (K, _, V1, _, V2) -> {K, ?mand, t_inf_aux(V1, V2)} end, A, B), - t_map(Pairs, t_inf(ADefK, BDefK), t_inf(ADefV, BDefV)); -t_inf(?nil, ?nil, _Opaques) -> ?nil; -t_inf(?nil, ?nonempty_list(_, _), _Opaques) -> + t_map(Pairs, + t_inf_aux(ADefK, BDefK), + t_inf_aux(ADefV, BDefV)); +%% Intersection of 1 or more nominal types +t_inf_aux(?nominal(Same, LHS_S), ?nominal(Same, RHS_S)) -> + t_nominal(Same, t_inf_aux(LHS_S, RHS_S)); +t_inf_aux(?nominal(LHS_Name, ?nominal(LHS_InnerName, _)=LHS_Inner), + ?nominal(RHS_Name, ?nominal(RHS_InnerName, _)=RHS_Inner)) -> + %% FIXME: Explain this in more detail; + %% + %% Because `LHS_Name =/= RHS_Name`, the only way this can work is if + %% `LHS` or `RHS` is a nominal subtype of `RHS_Inner` or `LHS_Inner`, + %% respectively. + case t_inf_aux(LHS_Inner, RHS_Inner) of + ?nominal(LHS_InnerName = RHS_Name, _)=Inf -> ?nominal(LHS_Name, Inf); + ?nominal(RHS_InnerName = LHS_Name, _)=Inf -> ?nominal(RHS_Name, Inf); + _ -> ?none + end; +t_inf_aux(?nominal(LHS_Name, ?nominal_set(L_Ns, L_S)), + ?nominal(RHS_Name, ?nominal_set(R_Ns, R_S))) -> + %% As inf_nominal_sets/2 can handle non-normalized sets, we can simplify + %% crossing the lists by wrapping each nominal in the respective sets with + %% their outer name and letting the regular nested nominal clause handle it. + [_|_] = L_Ns, %Assertion. + LHS_Expanded = + [?nominal(LHS_Name, L_S) | [?nominal(LHS_Name, N) || N <- L_Ns]], + [_|_] = R_Ns, %Assertion. + RHS_Expanded = + [?nominal(RHS_Name, R_S) | [?nominal(RHS_Name, N) || N <- R_Ns]], + case inf_nominal_sets(LHS_Expanded, RHS_Expanded) of + ?nominal(LHS_Name, _)=Inf -> Inf; + ?nominal(RHS_Name, _)=Inf -> Inf; + ?none -> ?none + end; +t_inf_aux(?nominal(LHS_Name, ?nominal(_, _)=LHS_Inner), + ?nominal(_, ?nominal_set(_, _))=RHS) -> + t_inf_aux(?nominal(LHS_Name, ?nominal_set([LHS_Inner], ?none)), RHS); +t_inf_aux(?nominal(_, ?nominal_set(_, _))=LHS, + ?nominal(RHS_Name, ?nominal(_, _)=RHS_Inner)) -> + t_inf_aux(LHS, ?nominal(RHS_Name, ?nominal_set([RHS_Inner], ?none))); +t_inf_aux(?nominal(LHS_Name, ?nominal_set(_, _))=LHS, + ?nominal(_, _)=RHS) -> + t_inf_aux(LHS, ?nominal(LHS_Name, RHS)); +t_inf_aux(?nominal(_, _)=LHS, + ?nominal(_, ?nominal_set(_, _))=RHS) -> + t_inf_aux(RHS, LHS); +t_inf_aux(?nominal(LHS_Name, ?nominal(_, _))=LHS, + ?nominal(_, _)=RHS) -> + t_inf_aux(LHS, ?nominal(LHS_Name, RHS)); +t_inf_aux(?nominal(_, _)=LHS, + ?nominal(_, ?nominal(_, _))=RHS) -> + t_inf_aux(RHS, LHS); +t_inf_aux(?nominal_set(LHS_Ns, LHS_S), + ?nominal_set(RHS_Ns, RHS_S)) -> + inf_nominal_sets([LHS_S | LHS_Ns], [RHS_S | RHS_Ns]); +t_inf_aux(?nominal_set(LHS_Ns, LHS_S), ?nominal(_, _)=RHS) -> + inf_nominal_sets([LHS_S | LHS_Ns], [RHS]); +t_inf_aux(?nominal(_, _)=LHS, ?nominal_set(RHS_Ns, RHS_S)) -> + inf_nominal_sets([LHS], [RHS_S | RHS_Ns]); +t_inf_aux(?nominal_set(LHS_Ns, LHS_S), RHS) -> + inf_nominal_sets([LHS_S | LHS_Ns], [RHS]); +t_inf_aux(LHS, ?nominal_set(_, _)=RHS) -> + t_inf_aux(RHS, LHS); +t_inf_aux(?nominal(_, _), ?nominal(_, _)) -> + ?none; +t_inf_aux(?nominal(LHS_Name, LHS_S), RHS_S) -> + t_nominal(LHS_Name, t_inf_aux(LHS_S, RHS_S)); +t_inf_aux(LHS, ?nominal(_, _)=RHS) -> + t_inf_aux(RHS, LHS); +t_inf_aux(?nil, ?nil) -> ?nil; +t_inf_aux(?nil, ?nonempty_list(_, _)) -> ?none; -t_inf(?nonempty_list(_, _), ?nil, _Opaques) -> +t_inf_aux(?nonempty_list(_, _), ?nil) -> ?none; -t_inf(?nil, ?list(_Contents, Termination, _), Opaques) -> - t_inf(?nil, t_unopaque(Termination), Opaques); -t_inf(?list(_Contents, Termination, _), ?nil, Opaques) -> - t_inf(?nil, t_unopaque(Termination), Opaques); -t_inf(?list(Contents1, Termination1, Size1), - ?list(Contents2, Termination2, Size2), Opaques) -> - case t_inf(Termination1, Termination2, Opaques) of +t_inf_aux(?nil, ?list(_Contents, Termination, _)) -> + t_inf_aux(?nil, t_structural(Termination)); +t_inf_aux(?list(_Contents, Termination, _), ?nil) -> + t_inf_aux(?nil, t_structural(Termination)); +t_inf_aux(?list(Contents1, Termination1, Size1), + ?list(Contents2, Termination2, Size2)) -> + case t_inf_aux(Termination1, Termination2) of ?none -> ?none; Termination -> - case t_inf(Contents1, Contents2, Opaques) of + case t_inf_aux(Contents1, Contents2) of ?none -> %% If none of the lists are nonempty, then the infimum is nil. case (Size1 =:= ?unknown_qual) andalso (Size2 =:= ?unknown_qual) of @@ -2850,7 +2630,7 @@ t_inf(?list(Contents1, Termination1, Size1), ?list(Contents, Termination, Size) end end; -t_inf(?number(_, _) = T1, ?number(_, _) = T2, _Opaques) -> +t_inf_aux(?number(_, _) = T1, ?number(_, _) = T2) -> case {T1, T2} of {T, T} -> T; {_, ?number(?any, ?unknown_qual)} -> T1; @@ -2867,13 +2647,11 @@ t_inf(?number(_, _) = T1, ?number(_, _) = T2, _Opaques) -> {?int_range(From1, To1), ?int_range(From2, To2)} -> t_from_range(max(From1, From2), min(To1, To2)); {Range = ?int_range(_, _), ?int_set(Set)} -> - %% io:format("t_inf range, set args ~p ~p ~n", [T1, T2]), Ans2 = case set_filter(fun(X) -> in_range(X, Range) end, Set) of ?none -> ?none; NewSet -> ?int_set(NewSet) end, - %% io:format("Ans2 ~p ~n", [Ans2]), Ans2; {?int_set(Set), ?int_range(_, _) = Range} -> case set_filter(fun(X) -> in_range(X, Range) end, Set) of @@ -2881,276 +2659,189 @@ t_inf(?number(_, _) = T1, ?number(_, _) = T2, _Opaques) -> NewSet -> ?int_set(NewSet) end end; -t_inf(?product(Types1), ?product(Types2), Opaques) -> - L1 = length(Types1), - L2 = length(Types2), - if L1 =:= L2 -> ?product(t_inf_lists(Types1, Types2, Opaques)); - true -> ?none +t_inf_aux(?product(Types1), ?product(Types2)) -> + case {length(Types1), length(Types2)} of + {Same, Same} -> ?product(t_inf_lists(Types1, Types2)); + _ -> ?none end; -t_inf(?product(_), _, _Opaques) -> +t_inf_aux(?product(_), _) -> ?none; -t_inf(_, ?product(_), _Opaques) -> +t_inf_aux(_, ?product(_)) -> ?none; -t_inf(?tuple(?any, ?any, ?any), ?tuple(_, _, _) = T, _Opaques) -> +t_inf_aux(?tuple(?any, ?any, ?any), ?tuple(_, _, _) = T) -> do_not_subst_all_vars_to_any(T); -t_inf(?tuple(_, _, _) = T, ?tuple(?any, ?any, ?any), _Opaques) -> +t_inf_aux(?tuple(_, _, _) = T, ?tuple(?any, ?any, ?any)) -> do_not_subst_all_vars_to_any(T); -t_inf(?tuple(?any, ?any, ?any), ?tuple_set(_) = T, _Opaques) -> +t_inf_aux(?tuple(?any, ?any, ?any), ?tuple_set(_) = T) -> do_not_subst_all_vars_to_any(T); -t_inf(?tuple_set(_) = T, ?tuple(?any, ?any, ?any), _Opaques) -> +t_inf_aux(?tuple_set(_) = T, ?tuple(?any, ?any, ?any)) -> do_not_subst_all_vars_to_any(T); -t_inf(?tuple(Elements1, Arity, _Tag1), ?tuple(Elements2, Arity, _Tag2), Opaques) -> - case t_inf_lists_strict(Elements1, Elements2, Opaques) of +t_inf_aux(?tuple(Elements1, Arity, _Tag1), ?tuple(Elements2, Arity, _Tag2)) -> + case t_inf_lists_strict(Elements1, Elements2) of bottom -> ?none; NewElements -> t_tuple(NewElements) end; -t_inf(?tuple_set(List1), ?tuple_set(List2), Opaques) -> - inf_tuple_sets(List1, List2, Opaques); -t_inf(?tuple_set(List), ?tuple(_, Arity, _) = T, Opaques) -> - inf_tuple_sets(List, [{Arity, [T]}], Opaques); -t_inf(?tuple(_, Arity, _) = T, ?tuple_set(List), Opaques) -> - inf_tuple_sets(List, [{Arity, [T]}], Opaques); -%% be careful: here and in the next clause T can be ?opaque -t_inf(?union(U1), T, Opaques) -> +t_inf_aux(?tuple_set(List1), ?tuple_set(List2)) -> + inf_tuple_sets(List1, List2); +t_inf_aux(?tuple_set(List), ?tuple(_, Arity, _) = T) -> + inf_tuple_sets(List, [{Arity, [T]}]); +t_inf_aux(?tuple(_, Arity, _) = T, ?tuple_set(List)) -> + inf_tuple_sets(List, [{Arity, [T]}]); +t_inf_aux(?opaque, _) -> + ?none; +t_inf_aux(_, ?opaque) -> + ?none; +t_inf_aux(?union(U1), T) -> ?union(U2) = force_union(T), - inf_union(U1, U2, Opaques); -t_inf(T, ?union(U2), Opaques) -> + inf_union(U1, U2); +t_inf_aux(T, ?union(U2)) -> ?union(U1) = force_union(T), - inf_union(U1, U2, Opaques); -t_inf(?opaque(Set1), ?opaque(Set2), Opaques) -> - inf_opaque(Set1, Set2, Opaques); -t_inf(?opaque(_) = T1, T2, Opaques) -> - inf_opaque1(T2, T1, 1, Opaques); -t_inf(T1, ?opaque(_) = T2, Opaques) -> - inf_opaque1(T1, T2, 2, Opaques); -%% and as a result, the cases for ?opaque should appear *after* ?union -t_inf(#c{}, #c{}, _) -> + inf_union(U1, U2); +t_inf_aux(#c{}, #c{}) -> ?none. -inf_opaque1(T1, ?opaque(Set2)=T2, Pos, Opaques) -> - case Opaques =:= 'universe' orelse inf_is_opaque_type(T2, Pos, Opaques) of - false -> ?none; - true -> - case inf_collect(T1, Set2, Opaques, []) of - [] -> ?none; - OpL -> ?opaque(ordsets:from_list(OpL)) - end - end. - -inf_is_opaque_type(T, Pos, {match, Opaques}) -> - is_opaque_type(T, Opaques) orelse throw({pos, [Pos]}); -inf_is_opaque_type(T, _Pos, Opaques) -> - is_opaque_type(T, Opaques). - -inf_collect(T1, [T2|List2], Opaques, OpL) -> - #opaque{struct = S2} = T2, - case t_inf(T1, S2, Opaques) of - ?none -> inf_collect(T1, List2, Opaques, OpL); - Inf -> - Op = T2#opaque{struct = Inf}, - inf_collect(T1, List2, Opaques, [Op|OpL]) - end; -inf_collect(_T1, [], _Opaques, OpL) -> - OpL. - -combine(S, T1, T2) -> - case is_compat_opaque_names(T1, T2) of - true -> combine(S, [T1]); - false -> combine(S, [T1, T2]) - end. - -combine(?opaque(Set), Ts) -> - [comb2(O, T) || O <- Set, T <- Ts]; -combine(S, Ts) -> - [T#opaque{struct = S} || T <- Ts]. - -comb2(O, T) -> - case is_compat_opaque_names(O, T) of - true -> O; - false -> T#opaque{struct = ?opaque(set_singleton(O))} - end. - -%% Combining two lists this way can be very time consuming... -%% Note: two parameterized opaque types are not the same if their -%% actual parameters differ -inf_opaque(Set1, Set2, Opaques) -> - List1 = inf_look_up(Set1, Opaques), - List2 = inf_look_up(Set2, Opaques), - List0 = [combine(Inf, T1, T2) || - {Is1, T1} <- List1, - {Is2, T2} <- List2, - not t_is_none(Inf = inf_opaque_types(Is1, T1, Is2, T2, Opaques))], - List = lists:append(List0), - sup_opaque(List). - -%% Optimization: do just one lookup. -inf_look_up(Set, Opaques) -> - [{Opaques =:= 'universe' orelse inf_is_opaque_type2(T, Opaques), T} || - T <- Set]. - -inf_is_opaque_type2(T, {match, Opaques}) -> - is_opaque_type2(T, Opaques); -inf_is_opaque_type2(T, Opaques) -> - is_opaque_type2(T, Opaques). - -inf_opaque_types(IsOpaque1, T1, IsOpaque2, T2, Opaques) -> - #opaque{struct = S1}=T1, - #opaque{struct = S2}=T2, - case - Opaques =:= 'universe' orelse is_compat_opaque_names(T1, T2) - of - true -> t_inf(S1, S2, Opaques); - false -> - case {IsOpaque1, IsOpaque2} of - {true, true} -> t_inf(S1, S2, Opaques); - {true, false} -> t_inf(S1, ?opaque(set_singleton(T2)), Opaques); - {false, true} -> t_inf(?opaque(set_singleton(T1)), S2, Opaques); - {false, false} when element(1, Opaques) =:= match -> - throw({pos, [1, 2]}); - {false, false} -> t_none() - end - end. - -compatible_opaque_types(?opaque(Es1), ?opaque(Es2)) -> - [{O1, O2} || O1 <- Es1, O2 <- Es2, is_compat_opaque_names(O1, O2)]. - -is_compat_opaque_names(Opaque1, Opaque2) -> - #opaque{mod = Mod1, name = Name1, arity = Arity1} = Opaque1, - #opaque{mod = Mod2, name = Name2, arity = Arity2} = Opaque2, - case {{Mod1, Name1, Arity1}, {Mod2, Name2, Arity2}} of - {ModNameArity, ModNameArity} -> true; - _ -> false - end. - -spec t_inf_lists([erl_type()], [erl_type()]) -> [erl_type()]. -t_inf_lists(L1, L2) -> - t_inf_lists(L1, L2, 'universe'). - --spec t_inf_lists([erl_type()], [erl_type()], t_inf_opaques()) -> [erl_type()]. - -t_inf_lists(L1, L2, Opaques) -> - t_inf_lists(L1, L2, [], Opaques). - --spec t_inf_lists([erl_type()], [erl_type()], [erl_type()], [erl_type()]) -> [erl_type()]. - -t_inf_lists([T1|Left1], [T2|Left2], Acc, Opaques) -> - t_inf_lists(Left1, Left2, [t_inf(T1, T2, Opaques)|Acc], Opaques); -t_inf_lists([], [], Acc, _Opaques) -> - lists:reverse(Acc). +t_inf_lists([T1 | Left1], [T2 | Left2]) -> + [t_inf(T1, T2) | t_inf_lists(Left1, Left2)]; +t_inf_lists([], []) -> + []. %% Infimum of lists with strictness. %% If any element is the ?none type, the value 'bottom' is returned. --spec t_inf_lists_strict([erl_type()], [erl_type()], [erl_type()]) -> 'bottom' | [erl_type()]. +-spec t_inf_lists_strict([erl_type()], [erl_type()]) -> 'bottom' | [erl_type()]. -t_inf_lists_strict(L1, L2, Opaques) -> - t_inf_lists_strict(L1, L2, [], Opaques). +t_inf_lists_strict(L1, L2) -> + t_inf_lists_strict(L1, L2, []). --spec t_inf_lists_strict([erl_type()], [erl_type()], [erl_type()], [erl_type()]) -> 'bottom' | [erl_type()]. - -t_inf_lists_strict([T1|Left1], [T2|Left2], Acc, Opaques) -> - case t_inf(T1, T2, Opaques) of +t_inf_lists_strict([T1|Left1], [T2|Left2], Acc) -> + case t_inf(T1, T2) of ?none -> bottom; - T -> t_inf_lists_strict(Left1, Left2, [T|Acc], Opaques) + T -> t_inf_lists_strict(Left1, Left2, [T|Acc]) end; -t_inf_lists_strict([], [], Acc, _Opaques) -> +t_inf_lists_strict([], [], Acc) -> lists:reverse(Acc). -inf_tuple_sets(L1, L2, Opaques) -> - case inf_tuple_sets(L1, L2, [], Opaques) of +inf_nominal_sets([_|_]=LHS, [_|_]=RHS) -> + %% Because a nominal in LHS_Ns can be a subtype of another in RHS_Ns or of + %% the structure in RHS_S (and vice versa), we have to t_inf/2 the cartesian + %% product of both sets. + %% + %% This is quadratic but generally fast enough given the small sizes of the + %% sets. + ins_cartesian(LHS, RHS). + +ins_cartesian([A | As], Bs) -> + case ins_cartesian_1(A, Bs) of + ?none -> ins_cartesian(As, Bs); + T -> t_sup_aux(T, ins_cartesian(As, Bs)) + end; +ins_cartesian([], _Bs) -> + ?none. + +ins_cartesian_1(A, [B | Bs]) -> + case t_inf_aux(A, B) of + ?none -> ins_cartesian_1(A, Bs); + T -> t_sup_aux(T, ins_cartesian_1(A, Bs)) + end; +ins_cartesian_1(_A, []) -> + ?none. + +inf_tuple_sets(L1, L2) -> + case inf_tuple_sets(L1, L2, []) of [] -> ?none; [{_Arity, [?tuple(_, _, _) = OneTuple]}] -> OneTuple; List -> ?tuple_set(List) end. -inf_tuple_sets([{Arity, Tuples1}|Ts1], [{Arity, Tuples2}|Ts2], Acc, Opaques) -> - case inf_tuples_in_sets(Tuples1, Tuples2, Opaques) of - [] -> inf_tuple_sets(Ts1, Ts2, Acc, Opaques); +inf_tuple_sets([{Arity, Tuples1}|Ts1], [{Arity, Tuples2}|Ts2], Acc) -> + case inf_tuples_in_sets(Tuples1, Tuples2) of + [] -> inf_tuple_sets(Ts1, Ts2, Acc); [?tuple_set([{Arity, NewTuples}])] -> - inf_tuple_sets(Ts1, Ts2, [{Arity, NewTuples}|Acc], Opaques); - NewTuples -> inf_tuple_sets(Ts1, Ts2, [{Arity, NewTuples}|Acc], Opaques) + inf_tuple_sets(Ts1, Ts2, [{Arity, NewTuples}|Acc]); + NewTuples -> inf_tuple_sets(Ts1, Ts2, [{Arity, NewTuples}|Acc]) end; -inf_tuple_sets([{Arity1, _}|Ts1] = L1, [{Arity2, _}|Ts2] = L2, Acc, Opaques) -> - if Arity1 < Arity2 -> inf_tuple_sets(Ts1, L2, Acc, Opaques); - Arity1 > Arity2 -> inf_tuple_sets(L1, Ts2, Acc, Opaques) +inf_tuple_sets([{Arity1, _}|Ts1] = L1, [{Arity2, _}|Ts2] = L2, Acc) -> + if Arity1 < Arity2 -> inf_tuple_sets(Ts1, L2, Acc); + Arity1 > Arity2 -> inf_tuple_sets(L1, Ts2, Acc) end; -inf_tuple_sets([], _, Acc, _Opaques) -> lists:reverse(Acc); -inf_tuple_sets(_, [], Acc, _Opaques) -> lists:reverse(Acc). +inf_tuple_sets([], _, Acc) -> lists:reverse(Acc); +inf_tuple_sets(_, [], Acc) -> lists:reverse(Acc). -inf_tuples_in_sets([?tuple(Elements1, _, ?any)], L2, Opaques) -> - NewList = [t_inf_lists_strict(Elements1, Elements2, Opaques) +inf_tuples_in_sets([?tuple(Elements1, _, ?any)], L2) -> + NewList = [t_inf_lists_strict(Elements1, Elements2) || ?tuple(Elements2, _, _) <- L2], [t_tuple(Es) || Es <- NewList, Es =/= bottom]; -inf_tuples_in_sets(L1, [?tuple(Elements2, _, ?any)], Opaques) -> - NewList = [t_inf_lists_strict(Elements1, Elements2, Opaques) +inf_tuples_in_sets(L1, [?tuple(Elements2, _, ?any)]) -> + NewList = [t_inf_lists_strict(Elements1, Elements2) || ?tuple(Elements1, _, _) <- L1], [t_tuple(Es) || Es <- NewList, Es =/= bottom]; -inf_tuples_in_sets(L1, L2, Opaques) -> - inf_tuples_in_sets2(L1, L2, [], Opaques). +inf_tuples_in_sets(L1, L2) -> + inf_tuples_in_sets2(L1, L2, []). inf_tuples_in_sets2([?tuple(Elements1, Arity, Tag)|Ts1], - [?tuple(Elements2, Arity, Tag)|Ts2], Acc, Opaques) -> - case t_inf_lists_strict(Elements1, Elements2, Opaques) of - bottom -> inf_tuples_in_sets2(Ts1, Ts2, Acc, Opaques); + [?tuple(Elements2, Arity, Tag)|Ts2], Acc) -> + case t_inf_lists_strict(Elements1, Elements2) of + bottom -> inf_tuples_in_sets2(Ts1, Ts2, Acc); NewElements -> - inf_tuples_in_sets2(Ts1, Ts2, [?tuple(NewElements, Arity, Tag)|Acc], - Opaques) + inf_tuples_in_sets2(Ts1, Ts2, [?tuple(NewElements, Arity, Tag)|Acc]) end; inf_tuples_in_sets2([?tuple(_, _, Tag1)|Ts1] = L1, - [?tuple(_, _, Tag2)|Ts2] = L2, Acc, Opaques) -> - if Tag1 < Tag2 -> inf_tuples_in_sets2(Ts1, L2, Acc, Opaques); - Tag1 > Tag2 -> inf_tuples_in_sets2(L1, Ts2, Acc, Opaques) + [?tuple(_, _, Tag2)|Ts2] = L2, Acc) -> + if Tag1 < Tag2 -> inf_tuples_in_sets2(Ts1, L2, Acc); + Tag1 > Tag2 -> inf_tuples_in_sets2(L1, Ts2, Acc) end; -inf_tuples_in_sets2([], _, Acc, _Opaques) -> lists:reverse(Acc); -inf_tuples_in_sets2(_, [], Acc, _Opaques) -> lists:reverse(Acc). +inf_tuples_in_sets2([], _, Acc) -> lists:reverse(Acc); +inf_tuples_in_sets2(_, [], Acc) -> lists:reverse(Acc). -inf_union(U1, U2, Opaques) -> +inf_union(U1, U2) -> OpaqueFun = fun(Union1, Union2, InfFun) -> - ?untagged_union(_,_,_,_,_,_,_,Opaque,_) = Union1, - ?untagged_union(A,B,F,I,L,N,T,_,Map) = Union2, + ?untagged_union(_,_,_,_,_,_,_,_) = Union1, + ?untagged_union(A,B,F,I,L,N,T,Map) = Union2, List = [A,B,F,I,L,N,T,Map], - inf_union_collect(List, Opaque, InfFun, [], []) + %% FIXME: Faking ?none opaque -- remove argument. + inf_union_collect(List, InfFun, [], []) end, {O1, ThrowList1} = - OpaqueFun(U1, U2, fun(E, Opaque) -> t_inf(Opaque, E, Opaques) end), + OpaqueFun(U1, U2, fun(E, Opaque) -> t_inf(Opaque, E) end), {O2, ThrowList2} = - OpaqueFun(U2, U1, fun(E, Opaque) -> t_inf(E, Opaque, Opaques) end), - {Union, ThrowList3} = inf_union(U1, U2, ?none, [], [], Opaques), + OpaqueFun(U2, U1, fun(E, Opaque) -> t_inf(E, Opaque) end), + {Union, ThrowList3} = inf_union(U1, U2, ?none, [], []), ThrowList = lists:merge3(ThrowList1, ThrowList2, ThrowList3), case t_sup([O1, O2, Union]) of ?none when ThrowList =/= [] -> throw({pos, lists:usort(ThrowList)}); Sup -> Sup end. -inf_union_collect([], _Opaque, _InfFun, InfList, ThrowList) -> +inf_union_collect([], _InfFun, InfList, ThrowList) -> {t_sup(InfList), lists:usort(ThrowList)}; -inf_union_collect([?none|L], Opaque, InfFun, InfList, ThrowList) -> - inf_union_collect(L, Opaque, InfFun, [?none|InfList], ThrowList); -inf_union_collect([E|L], Opaque, InfFun, InfList, ThrowList) -> - try InfFun(E, Opaque)of +inf_union_collect([?none|L], InfFun, InfList, ThrowList) -> + inf_union_collect(L, InfFun, [?none|InfList], ThrowList); +inf_union_collect([E|L], InfFun, InfList, ThrowList) -> + try InfFun(E, ?none)of Inf -> - inf_union_collect(L, Opaque, InfFun, [Inf|InfList], ThrowList) + inf_union_collect(L, InfFun, [Inf|InfList], ThrowList) catch throw:{pos, Ns} -> - inf_union_collect(L, Opaque, InfFun, InfList, Ns ++ ThrowList) + inf_union_collect(L, InfFun, InfList, Ns ++ ThrowList) end. -inf_union([?none|Left1], [?none|Left2], Type, Acc, ThrowList, Opaques) -> - inf_union(Left1, Left2, Type, [?none|Acc], ThrowList, Opaques); -inf_union([T1|Left1], [T2|Left2], Type, Acc, ThrowList, Opaques) -> - try t_inf(T1, T2, Opaques) of +inf_union([?none|Left1], [?none|Left2], Type, Acc, ThrowList) -> + inf_union(Left1, Left2, Type, [?none|Acc], ThrowList); +inf_union([T1|Left1], [T2|Left2], Type, Acc, ThrowList) -> + try t_inf(T1, T2) of ?none -> - inf_union(Left1, Left2, Type, [?none|Acc], ThrowList, Opaques); + inf_union(Left1, Left2, Type, [?none|Acc], ThrowList); T when Type =:= ?none -> - inf_union(Left1, Left2, T, [T|Acc], ThrowList, Opaques); + inf_union(Left1, Left2, T, [T|Acc], ThrowList); T -> - inf_union(Left1, Left2, ?union_tag, [T|Acc], ThrowList, Opaques) + inf_union(Left1, Left2, ?union_tag, [T|Acc], ThrowList) catch throw:{pos, Ns} -> - inf_union(Left1, Left2, Type, [?none|Acc], Ns ++ ThrowList, Opaques) + inf_union(Left1, Left2, Type, [?none|Acc], Ns ++ ThrowList) end; -inf_union([], [], Type, Acc, ThrowList, _Opaques) -> +inf_union([], [], Type, Acc, ThrowList) -> case Type of ?union_tag -> {?union(lists:reverse(Acc)), ThrowList}; @@ -3229,6 +2920,12 @@ t_subst_aux(?list(Contents, Termination, Size), Map) -> end; t_subst_aux(?function(Domain, Range), Map) -> ?function(t_subst_aux(Domain, Map), t_subst_aux(Range, Map)); +t_subst_aux(?nominal(N, S), Map) -> + ?nominal(N, t_subst_aux(S, Map)); +t_subst_aux(?nominal_set(N, S), Map) -> + normalize_nominal_set([t_subst_aux(X, Map) || X <- N], + t_subst_aux(S, Map), + []); t_subst_aux(?product(Types), Map) -> ?product([t_subst_aux(T, Map) || T <- Types]); t_subst_aux(?tuple(?any, ?any, ?any) = T, _Map) -> @@ -3240,10 +2937,6 @@ t_subst_aux(?tuple_set(_) = TS, Map) -> t_subst_aux(?map(Pairs, DefK, DefV), Map) -> t_map([{K, MNess, t_subst_aux(V, Map)} || {K, MNess, V} <- Pairs], t_subst_aux(DefK, Map), t_subst_aux(DefV, Map)); -t_subst_aux(?opaque(Es), Map) -> - List = [Opaque#opaque{struct = t_subst_aux(S, Map)} || - Opaque = #opaque{struct = S} <- Es], - ?opaque(ordsets:from_list(List)); t_subst_aux(?union(List), Map) -> ?union([t_subst_aux(E, Map) || E <- List]); t_subst_aux(T, _Map) -> @@ -3273,7 +2966,7 @@ t_unify_table_only(?var(Id1) = LHS, ?var(Id2) = RHS, VarMap) -> #{ Id2 := Type } -> t_unify_table_only(LHS, Type, VarMap); #{} -> - VarMap#{ Id1 => LHS, Id2 => RHS } + VarMap#{ Id1 => LHS, Id2 => LHS } end; t_unify_table_only(?var(Id), Type, VarMap) -> case VarMap of @@ -3292,6 +2985,39 @@ t_unify_table_only(Type, ?var(Id), VarMap) -> t_unify_table_only(?function(Domain1, Range1), ?function(Domain2, Range2), VarMap) -> VarMap1 = t_unify_table_only(Domain1, Domain2, VarMap), t_unify_table_only(Range1, Range2, VarMap1); +%% Nominals +t_unify_table_only(?nominal(N1, S1)=T1, ?nominal(N2, S2)=T2, VarMap) -> + case N1 =:= N2 of + true -> t_unify_table_only(S1, S2, VarMap); + false -> throw({mismatch, T1, T2}) + end; +%% +t_unify_table_only(?nominal_set([H1], S1), ?nominal_set([H2], S2), VarMap) -> + VarMap1 = t_unify_table_only(H1, H2, VarMap), + t_unify_table_only(S1, S2, VarMap1); +t_unify_table_only(?nominal_set([H1 | T1], Str1), + ?nominal_set([H2 | T2], Str2), VarMap) -> + VarMap1 = t_unify_table_only(H1, H2, VarMap), + t_unify_table_only(?nominal_set(T1, Str1), ?nominal_set(T2, Str2), VarMap1); +%% +t_unify_table_only(?nominal(_, _) = T1, ?nominal_set(_, _) = T2, VarMap) -> + t_unify_table_only(T2, T1, VarMap); +t_unify_table_only(?nominal_set(_, _) = T1, ?nominal(_, _) = T2, VarMap) -> + t_unify_table_only(T1, ?nominal_set(T2, ?none), VarMap); +%% +t_unify_table_only(?nominal_set([?nominal(_, NomS)], Other), T2, VarMap) -> + t_unify_table_only(t_sup(NomS, Other), T2, VarMap); +t_unify_table_only(?nominal_set([?nominal(_, NomS) | T], Other), T2, VarMap) -> + VarMap1 = t_unify_table_only(t_sup(NomS, Other), T2, VarMap), + t_unify_table_only(?nominal_set(T, Other), T2, VarMap1); +t_unify_table_only(T1, ?nominal_set(_, _) = T2, VarMap) -> + t_unify_table_only(T2, T1, VarMap); +%% +t_unify_table_only(?nominal(_, S1), T2, VarMap) -> + t_unify_table_only(S1, T2, VarMap); +t_unify_table_only(T1, ?nominal(_, _)=T2, VarMap) -> + t_unify_table_only(T2, T1, VarMap); +%% t_unify_table_only(?list(Contents1, Termination1, Size), ?list(Contents2, Termination2, Size), VarMap) -> VarMap1 = t_unify_table_only(Contents1, Contents2, VarMap), @@ -3332,21 +3058,8 @@ t_unify_table_only(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B, VarMap0 {Pairs0, VarMap4} end, {[], VarMap2}, A, B), VarMap; -t_unify_table_only(?opaque(_) = T1, ?opaque(_) = T2, VarMap) -> - t_unify_table_only(t_opaque_structure(T1), t_opaque_structure(T2), VarMap); -t_unify_table_only(T1, ?opaque(_) = T2, VarMap) -> - t_unify_table_only(T1, t_opaque_structure(T2), VarMap); -t_unify_table_only(?opaque(_) = T1, T2, VarMap) -> - t_unify_table_only(t_opaque_structure(T1), T2, VarMap); t_unify_table_only(T, T, VarMap) -> VarMap; -t_unify_table_only(?union(_)=T1, ?union(_)=T2, VarMap) -> - {Type1, Type2} = unify_union2(T1, T2), - t_unify_table_only(Type1, Type2, VarMap); -t_unify_table_only(?union(_)=T1, T2, VarMap) -> - t_unify_table_only(unify_union1(T1, T1, T2), T2, VarMap); -t_unify_table_only(T1, ?union(_)=T2, VarMap) -> - t_unify_table_only(T1, unify_union1(T2, T1, T2), VarMap); t_unify_table_only(T1, T2, _) -> throw({mismatch, T1, T2}). @@ -3367,50 +3080,6 @@ unify_lists_table_only([T1|Left1], [T2|Left2], VarMap) -> unify_lists_table_only([], [], VarMap) -> VarMap. -unify_union2(?union(List1)=T1, ?union(List2)=T2) -> - case {unify_union(List1), unify_union(List2)} of - {{yes, Type1}, {yes, Type2}} -> {Type1, Type2}; - {{yes, Type1}, no} -> {Type1, T2}; - {no, {yes, Type2}} -> {T1, Type2}; - {no, no} -> throw({mismatch, T1, T2}) - end. - -unify_union1(?union(List), T1, T2) -> - case unify_union(List) of - {yes, Type} -> Type; - no -> throw({mismatch, T1, T2}) - end. - -unify_union(List) -> - ?untagged_union(A,B,F,I,L,N,T,O,Map) = List, - if O =:= ?none -> no; - true -> - S = t_opaque_structure(O), - {yes, t_sup([A,B,F,I,L,N,T,S,Map])} - end. - --spec is_opaque_type(erl_type(), [erl_type()]) -> boolean(). - -%% An opaque type is a union of types. Returns true iff any of the type -%% names (Module and Name) of the first argument (the opaque type to -%% check) occurs in any of the opaque types of the second argument. -is_opaque_type(?opaque(Elements), Opaques) -> - lists:any(fun(Opaque) -> is_opaque_type2(Opaque, Opaques) end, Elements). - -is_opaque_type2(#opaque{mod = Mod1, name = Name1, arity = Arity1}, Opaques) -> - F1 = fun(?opaque(Es)) -> - F2 = fun(#opaque{mod = Mod, name = Name, arity = Arity}) -> - is_type_name(Mod1, Name1, Arity1, Mod, Name, Arity) - end, - lists:any(F2, Es) - end, - lists:any(F1, Opaques). - -is_type_name(Mod, Name, Arity, Mod, Name, Arity) -> - true; -is_type_name(_Mod1, _Name1, _Arity1, _Mod2, _Name2, _Arity2) -> - false. - %%----------------------------------------------------------------------------- %% Subtraction. %% @@ -3437,49 +3106,53 @@ t_subtract_list(T, []) -> -spec t_subtract(erl_type(), erl_type()) -> erl_type(). -t_subtract(_, ?any) -> ?none; -t_subtract(T, ?var(_)) -> T; -t_subtract(?any, _) -> ?any; -t_subtract(?var(_) = T, _) -> T; -t_subtract(T, ?unit) -> T; -t_subtract(?unit, _) -> ?unit; -t_subtract(?none, _) -> ?none; -t_subtract(T, ?none) -> T; -t_subtract(?atom(Set1), ?atom(Set2)) -> +t_subtract(LHS, RHS) -> + Res = t_subtract_aux(LHS, RHS), + %% `Res` must be at least as specific as `LHS`, and the latter must overlap + %% with `RHS` if the result differs from `LHS`. + ?debug(t_is_subtype(subst_all_vars_to_any(Res), + subst_all_vars_to_any(LHS)) andalso + (Res =:= LHS) orelse (not t_is_impossible(t_inf(LHS, RHS))), + {LHS, RHS, Res}), + Res. + +t_subtract_aux(_, ?any) -> ?none; +t_subtract_aux(T, ?var(_)) -> T; +t_subtract_aux(?any, _) -> ?any; +t_subtract_aux(?var(_) = T, _) -> T; +t_subtract_aux(T, ?unit) -> T; +t_subtract_aux(?unit, _) -> ?unit; +t_subtract_aux(?none, _) -> ?none; +t_subtract_aux(T, ?none) -> T; +t_subtract_aux(?atom(Set1), ?atom(Set2)) -> case set_subtract(Set1, Set2) of ?none -> ?none; Set -> ?atom(Set) end; -t_subtract(?bitstr(U1, B1), ?bitstr(U2, B2)) -> +t_subtract_aux(?bitstr(U1, B1), ?bitstr(U2, B2)) -> subtract_bin(t_bitstr(U1, B1), t_inf(t_bitstr(U1, B1), t_bitstr(U2, B2))); -t_subtract(?function(_, _) = T1, ?function(_, _) = T2) -> +t_subtract_aux(?function(_, _) = T1, ?function(_, _) = T2) -> case t_is_subtype(T1, T2) of true -> ?none; false -> T1 end; -t_subtract(?identifier(Set1), ?identifier(Set2)) -> +t_subtract_aux(?identifier(Set1), ?identifier(Set2)) -> case set_subtract(Set1, Set2) of ?none -> ?none; Set -> ?identifier(Set) end; -t_subtract(?opaque(_)=T1, ?opaque(_)=T2) -> - opaque_subtract(T1, t_opaque_structure(T2)); -t_subtract(?opaque(_)=T1, T2) -> - opaque_subtract(T1, T2); -t_subtract(T1, ?opaque(_)=T2) -> - t_subtract(T1, t_opaque_structure(T2)); -t_subtract(?nil, ?nil) -> +t_subtract_aux(?nil, ?nil) -> ?none; -t_subtract(?nil, ?nonempty_list(_, _)) -> +t_subtract_aux(?nil, ?nonempty_list(_, _)) -> ?nil; -t_subtract(?nil, ?list(_, _, _)) -> +t_subtract_aux(?nil, ?list(_, _, _)) -> ?none; -t_subtract(?list(Contents, Termination, _Size) = T, ?nil) -> +t_subtract_aux(?list(Contents, Termination, _Size) = T, ?nil) -> case Termination =:= ?nil of true -> ?nonempty_list(Contents, Termination); false -> T end; -t_subtract(?list(Contents1, Termination1, Size1) = T, +t_subtract_aux(?list(Contents1, Termination1, Size1) = T, ?list(Contents2, Termination2, Size2)) -> case t_is_subtype(Contents1, Contents2) of true -> @@ -3500,21 +3173,45 @@ t_subtract(?list(Contents1, Termination1, Size1) = T, %% change to the list. T end; -t_subtract(?float, ?float) -> ?none; -t_subtract(?number(_, _) = T1, ?float) -> t_inf(T1, t_integer()); -t_subtract(?float, ?number(_Set, Tag)) -> +t_subtract_aux(?float, ?float) -> ?none; +t_subtract_aux(?number(_, _) = T1, ?float) -> t_inf(T1, t_integer()); +t_subtract_aux(?float, ?number(_Set, Tag)) -> case Tag of ?unknown_qual -> ?none; _ -> ?float end; -t_subtract(?number(_, _), ?number(?any, ?unknown_qual)) -> ?none; -t_subtract(?number(_, _) = T1, ?integer(?any)) -> t_inf(?float, T1); -t_subtract(?int_set(Set1), ?int_set(Set2)) -> +t_subtract_aux(?nominal_set(_, _)=LHS, ?nominal_set(_, _)=RHS) -> + subtract_nominal_sets(LHS, RHS); +t_subtract_aux(?nominal_set(_, _)=LHS, ?nominal(_, _) = RHS) -> + t_subtract_aux(LHS, ?nominal_set([RHS], ?none)); +t_subtract_aux(?nominal_set(LHS_Ns, LHS_S)=LHS, RHS) -> + case t_inf(LHS, RHS) of + ?nominal_set(_, _)=Overlap -> + t_subtract_aux(LHS, Overlap); + ?nominal(_, _)=Overlap -> + t_subtract_aux(LHS, Overlap); + Overlap -> + normalize_nominal_set(LHS_Ns, t_subtract_aux(LHS_S, Overlap), []) + end; +t_subtract_aux(S1, ?nominal_set(_, S2)) -> + t_subtract_aux(S1, S2); +t_subtract_aux(?nominal(Name, LHS_S), ?nominal(Name, RHS_S)) -> + t_nominal(Name, t_subtract_aux(LHS_S, RHS_S)); +t_subtract_aux(?nominal(LHS_Name, _)=LHS, RHS) -> + case t_inf(LHS, RHS) of + ?nominal(LHS_Name, _)=Overlap -> t_subtract_aux(LHS, Overlap); + _ -> LHS + end; +t_subtract_aux(S1, ?nominal(_, _)) -> + S1; +t_subtract_aux(?number(_, _), ?number(?any, ?unknown_qual)) -> ?none; +t_subtract_aux(?number(_, _) = T1, ?integer(?any)) -> t_inf(?float, T1); +t_subtract_aux(?int_set(Set1), ?int_set(Set2)) -> case set_subtract(Set1, Set2) of ?none -> ?none; Set -> ?int_set(Set) end; -t_subtract(?int_range(From1, To1) = T1, ?int_range(_, _) = T2) -> +t_subtract_aux(?int_range(From1, To1) = T1, ?int_range(_, _) = T2) -> case t_inf(T1, T2) of ?none -> T1; ?int_range(From1, To1) -> ?none; @@ -3523,7 +3220,7 @@ t_subtract(?int_range(From1, To1) = T1, ?int_range(_, _) = T2) -> ?int_range(From, To) -> t_sup(t_from_range(From1, From - 1), t_from_range(To + 1, To)) end; -t_subtract(?int_range(From, To) = T1, ?int_set(Set)) -> +t_subtract_aux(?int_range(From, To) = T1, ?int_set(Set)) -> NewFrom = case set_is_element(From, Set) of true -> From + 1; false -> From @@ -3535,17 +3232,17 @@ t_subtract(?int_range(From, To) = T1, ?int_set(Set)) -> if (NewFrom =:= From) and (NewTo =:= To) -> T1; true -> t_from_range(NewFrom, NewTo) end; -t_subtract(?int_set(Set), ?int_range(From, To)) -> +t_subtract_aux(?int_set(Set), ?int_range(From, To)) -> case set_filter(fun(X) -> not ((X =< From) orelse (X >= To)) end, Set) of ?none -> ?none; NewSet -> ?int_set(NewSet) end; -t_subtract(?integer(?any) = T1, ?integer(_)) -> T1; -t_subtract(?number(_, _) = T1, ?number(_, _)) -> T1; -t_subtract(?tuple(_, _, _), ?tuple(?any, ?any, ?any)) -> ?none; -t_subtract(?tuple_set(_), ?tuple(?any, ?any, ?any)) -> ?none; -t_subtract(?tuple(?any, ?any, ?any) = T1, ?tuple_set(_)) -> T1; -t_subtract(?tuple(Elements1, Arity1, _Tag1) = T1, +t_subtract_aux(?integer(?any) = T1, ?integer(_)) -> T1; +t_subtract_aux(?number(_, _) = T1, ?number(_, _)) -> T1; +t_subtract_aux(?tuple(_, _, _), ?tuple(?any, ?any, ?any)) -> ?none; +t_subtract_aux(?tuple_set(_), ?tuple(?any, ?any, ?any)) -> ?none; +t_subtract_aux(?tuple(?any, ?any, ?any) = T1, ?tuple_set(_)) -> T1; +t_subtract_aux(?tuple(Elements1, Arity1, _Tag1) = T1, ?tuple(Elements2, Arity2, _Tag2)) -> if Arity1 =/= Arity2 -> T1; Arity1 =:= Arity2 -> @@ -3556,22 +3253,22 @@ t_subtract(?tuple(Elements1, Arity1, _Tag1) = T1, _ -> T1 end end; -t_subtract(?tuple_set(List1) = T1, ?tuple(_, Arity, _) = T2) -> +t_subtract_aux(?tuple_set(List1) = T1, ?tuple(_, Arity, _) = T2) -> case orddict:find(Arity, List1) of error -> T1; {ok, List2} -> TuplesLeft0 = [Tuple || {_Arity, Tuple} <- orddict:erase(Arity, List1)], TuplesLeft1 = lists:append(TuplesLeft0), - t_sup([t_subtract(L, T2) || L <- List2] ++ TuplesLeft1) + t_sup([t_subtract_aux(L, T2) || L <- List2] ++ TuplesLeft1) end; -t_subtract(?tuple(_, Arity, _) = T1, ?tuple_set(List1)) -> +t_subtract_aux(?tuple(_, Arity, _) = T1, ?tuple_set(List1)) -> case orddict:find(Arity, List1) of error -> T1; - {ok, List2} -> t_inf([t_subtract(T1, L) || L <- List2]) + {ok, List2} -> t_inf([t_subtract_aux(T1, L) || L <- List2]) end; -t_subtract(?tuple_set(_) = T1, ?tuple_set(_) = T2) -> - t_sup([t_subtract(T, T2) || T <- t_tuple_subtypes(T1)]); -t_subtract(?product(Elements1) = T1, ?product(Elements2)) -> +t_subtract_aux(?tuple_set(_) = T1, ?tuple_set(_) = T2) -> + t_sup([t_subtract_aux(T, T2) || T <- t_tuple_subtypes(T1)]); +t_subtract_aux(?product(Elements1) = T1, ?product(Elements2)) -> Arity1 = length(Elements1), Arity2 = length(Elements2), if Arity1 =/= Arity2 -> T1; @@ -3583,7 +3280,7 @@ t_subtract(?product(Elements1) = T1, ?product(Elements2)) -> _ -> T1 end end; -t_subtract(?map(APairs, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) -> +t_subtract_aux(?map(APairs, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) -> case t_is_subtype(ADefK, BDefK) andalso t_is_subtype(ADefV, BDefV) of false -> A; true -> @@ -3609,10 +3306,10 @@ t_subtract(?map(APairs, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) -> map_pairwise_merge( %% If V1 is a subtype of V2, the case that K does not exist in A %% remain. - fun(K, ?opt, V1, ?mand, V2) -> {K, ?opt, t_subtract(V1, V2)}; + fun(K, ?opt, V1, ?mand, V2) -> {K, ?opt, t_subtract_aux(V1, V2)}; (K, _, V1, _, V2) -> %% If we subtract an optional key, that leaves a mandatory key - case t_subtract(V1, V2) of + case t_subtract_aux(V1, V2) of ?none -> false; Partial -> {K, ?mand, Partial} end @@ -3627,28 +3324,17 @@ t_subtract(?map(APairs, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) -> _ -> A end end; -t_subtract(?product(P1), _) -> +t_subtract_aux(?product(P1), _) -> ?product(P1); -t_subtract(T, ?product(_)) -> +t_subtract_aux(T, ?product(_)) -> T; -t_subtract(?union(U1), ?union(U2)) -> +t_subtract_aux(?union(U1), ?union(U2)) -> subtract_union(U1, U2); -t_subtract(T1, T2) -> +t_subtract_aux(T1, T2) -> ?union(U1) = force_union(T1), ?union(U2) = force_union(T2), subtract_union(U1, U2). --spec opaque_subtract(erl_type(), erl_type()) -> erl_type(). - -opaque_subtract(?opaque(Set1), T2) -> - List = [T1#opaque{struct = Sub} || - #opaque{struct = S1}=T1 <- Set1, - not t_is_none(Sub = t_subtract(S1, T2))], - case List of - [] -> ?none; - _ -> ?opaque(ordsets:from_list(List)) - end. - -spec t_subtract_lists([erl_type()], [erl_type()]) -> [erl_type()]. t_subtract_lists(L1, L2) -> @@ -3664,18 +3350,11 @@ t_subtract_lists([], [], Acc) -> -spec subtract_union([erl_type(),...], [erl_type(),...]) -> erl_type(). subtract_union(U1, U2) -> - ?untagged_union(A1,B1,F1,I1,L1,N1,T1,O1,Map1) = U1, - ?untagged_union(A2,B2,F2,I2,L2,N2,T2,O2,Map2) = U2, - List1 = ?untagged_union(A1,B1,F1,I1,L1,N1,T1,?none,Map1), - List2 = ?untagged_union(A2,B2,F2,I2,L2,N2,T2,?none,Map2), - Sub1 = subtract_union(List1, List2, ?none, []), - O = if O1 =:= ?none -> O1; - true -> t_subtract(O1, ?union(U2)) - end, - Sub2 = if O2 =:= ?none -> Sub1; - true -> t_subtract(Sub1, t_opaque_structure(O2)) - end, - t_sup(O, Sub2). + ?untagged_union(A1,B1,F1,I1,L1,N1,T1,Map1) = U1, + ?untagged_union(A2,B2,F2,I2,L2,N2,T2,Map2) = U2, + List1 = ?untagged_union(A1,B1,F1,I1,L1,N1,T1,Map1), + List2 = ?untagged_union(A2,B2,F2,I2,L2,N2,T2,Map2), + subtract_union(List1, List2, ?none, []). subtract_union([T1|Left1], [T2|Left2], Type, Acc) -> case t_subtract(T1, T2) of @@ -3691,6 +3370,24 @@ subtract_union([], [], Type, Acc) -> Type end. +subtract_nominal_sets(?nominal_set(LHS_Ns, LHS_S), + ?nominal_set(RHS_Ns, RHS_S)) -> + %% See inf_nominal_sets/3 + sns_cartesian([LHS_S | LHS_Ns], [RHS_S | RHS_Ns]). + +sns_cartesian([A | As], Bs) -> + case sns_cartesian_1(A, Bs) of + ?none -> sns_cartesian(As, Bs); + T -> t_sup_aux(T, sns_cartesian(As, Bs)) + end; +sns_cartesian([], _Bs) -> + ?none. + +sns_cartesian_1(A, [B | Bs]) -> + sns_cartesian_1(t_subtract(A, B), Bs); +sns_cartesian_1(A, []) -> + A. + %% Helper for tuple and product subtraction. The second list %% should contain a single element that is not none. That element %% will replace the element in the corresponding position in the @@ -3735,74 +3432,54 @@ t_is_equal(_, _) -> false. -spec t_is_subtype(erl_type(), erl_type()) -> boolean(). t_is_subtype(T1, T2) -> - Inf = t_inf(T1, T2), - subtype_is_equal(T1, Inf). - -%% The subtype relation has to behave correctly irrespective of opaque -%% types. -subtype_is_equal(T, T) -> true; -subtype_is_equal(T1, T2) -> - t_is_equal(case t_contains_opaque(T1) of - true -> t_unopaque(T1); - false -> T1 - end, - case t_contains_opaque(T2) of - true -> t_unopaque(T2); - false -> T2 - end). + Inf = t_inf_aux(T1, T2), + t_is_equal(T1, Inf). -spec t_is_instance(erl_type(), erl_type()) -> boolean(). %% XXX. To be removed. t_is_instance(ConcreteType, Type) -> - t_is_subtype(ConcreteType, t_unopaque(Type)). + t_is_subtype(ConcreteType, t_structural(Type)). -spec t_do_overlap(erl_type(), erl_type()) -> boolean(). t_do_overlap(TypeA, TypeB) -> not (t_is_impossible(t_inf(TypeA, TypeB))). --spec t_unopaque(erl_type()) -> erl_type(). - -t_unopaque(T) -> - t_unopaque(T, 'universe'). - --spec t_unopaque(erl_type(), opaques()) -> erl_type(). - -t_unopaque(?opaque(_) = T, Opaques) -> - case Opaques =:= 'universe' orelse is_opaque_type(T, Opaques) of - true -> t_unopaque(t_opaque_structure(T), Opaques); - false -> T - end; -t_unopaque(?list(ElemT, Termination, Sz), Opaques) -> - ?list(t_unopaque(ElemT, Opaques), t_unopaque(Termination, Opaques), Sz); -t_unopaque(?tuple(?any, _, _) = T, _) -> T; -t_unopaque(?tuple(ArgTs, Sz, Tag), Opaques) when is_list(ArgTs) -> - NewArgTs = [t_unopaque(A, Opaques) || A <- ArgTs], +-spec t_structural(erl_type()) -> erl_type(). + +t_structural(?nominal(_, S)) -> + t_structural(S); +t_structural(?nominal_set([], S)) -> + t_structural(S); +t_structural(?nominal_set([?nominal(_, S1)|T], S)) -> + t_structural(?nominal_set(T, t_sup(S, S1))); +t_structural(?list(ElemT, Termination, Sz)) -> + ?list(t_structural(ElemT), t_structural(Termination), Sz); +t_structural(?tuple(?any, _, _) = T) -> T; +t_structural(?tuple(ArgTs, Sz, Tag)) when is_list(ArgTs) -> + NewArgTs = [t_structural(A) || A <- ArgTs], ?tuple(NewArgTs, Sz, Tag); -t_unopaque(?tuple_set(Set), Opaques) -> - NewSet = [{Sz, [t_unopaque(T, Opaques) || T <- Tuples]} +t_structural(?tuple_set(Set)) -> + NewSet = [{Sz, [t_structural(T) || T <- Tuples]} || {Sz, Tuples} <- Set], ?tuple_set(NewSet); -t_unopaque(?product(Types), Opaques) -> - ?product([t_unopaque(T, Opaques) || T <- Types]); -t_unopaque(?function(Domain, Range), Opaques) -> - ?function(t_unopaque(Domain, Opaques), t_unopaque(Range, Opaques)); -t_unopaque(?union(?untagged_union(A,B,F,I,L,N,T,O,Map)), Opaques) -> - UL = t_unopaque(L, Opaques), - UT = t_unopaque(T, Opaques), - UF = t_unopaque(F, Opaques), - UMap = t_unopaque(Map, Opaques), - {OF,UO} = case t_unopaque(O, Opaques) of - ?opaque(_) = O1 -> {O1, []}; - Type -> {?none, [Type]} - end, - t_sup([?union([A,B,UF,I,UL,N,UT,OF,UMap])|UO]); -t_unopaque(?map(Pairs,DefK,DefV), Opaques) -> - t_map([{K, MNess, t_unopaque(V, Opaques)} || {K, MNess, V} <- Pairs], - t_unopaque(DefK, Opaques), - t_unopaque(DefV, Opaques)); -t_unopaque(T, _) -> +t_structural(?product(Types)) -> + ?product([t_structural(T) || T <- Types]); +t_structural(?function(Domain, Range)) -> + ?function(t_structural(Domain), t_structural(Range)); +t_structural(?union(?untagged_union(A,B,F,I,L,N,T,Map))) -> + UL = t_structural(L), + UT = t_structural(T), + UF = t_structural(F), + UMap = t_structural(Map), + t_sup([A,B,UF,I,UL,N,UT,UMap]); +t_structural(?map(Pairs,DefK,DefV)) -> + t_map([{t_structural(K), MNess, t_structural(V)} + || {K, MNess, V} <- Pairs], + t_structural(DefK), + t_structural(DefV)); +t_structural(T) -> T. %%----------------------------------------------------------------------------- @@ -3815,54 +3492,78 @@ t_unopaque(T, _) -> -spec t_limit(erl_type(), integer()) -> erl_type(). t_limit(Term, K) when is_integer(K) -> - case is_limited(Term, K) of - true -> Term; - false -> t_limit_k(Term, K) + IsLimited = is_limited(Term, K), + %% `is_limited/2` must mirror `t_limit_k/2` + ?debug(IsLimited =:= (Term =:= t_limit_k(Term, K)), + {IsLimited, Term, K}), + case IsLimited of + true -> + Term; + false -> + Res = t_limit_k(Term, K), + %% `Res` must be strictly more general than `Term` + ?debug(t_is_subtype(subst_all_vars_to_any(Term), + subst_all_vars_to_any(Res)), + {Term, Res}), + Res end. -is_limited(?any, _) -> true; -is_limited(_, K) when K =< 0 -> false; -is_limited(?tuple(?any, ?any, ?any), _K) -> true; -is_limited(?tuple(Elements, _Arity, _), K) -> - if K =:= 1 -> false; - true -> - are_all_limited(Elements, K - 1) +%% Optimized mirror of t_limit_k/2 that merely checks whether the latter will +%% change the input term in any way. Needless to say this _must_ mirror +%% t_limit_k/2. +is_limited(?any, _) -> + true; +is_limited(_, K) when K =< 0 -> + false; +is_limited(?tuple(?any, ?any, ?any), _K) -> + true; +is_limited(?tuple(Elements, _Arity, Qual), K) -> + ?debug(length(Elements) =:= _Arity, _Arity), + if + K =:= 1 -> t_is_any(Qual) andalso are_all_limited(Elements, K - 1); + true -> are_all_limited(Elements, K - 1) end; is_limited(?tuple_set(_) = T, K) -> are_all_limited(t_tuple_subtypes(T), K); is_limited(?list(Elements, ?nil, _Size), K) -> is_limited(Elements, K - 1); is_limited(?list(Elements, Termination, _Size), K) -> - if K =:= 1 -> is_limited(Termination, K); - true -> is_limited(Termination, K - 1) - end - andalso is_limited(Elements, K - 1); + %% We do not want to lose the termination information, always pass a K of at + %% least 1 for that + is_limited(Elements, K - 1) andalso is_limited(Termination, max(1, K - 1)); is_limited(?function(Domain, Range), K) -> is_limited(Domain, K) andalso is_limited(Range, K-1); is_limited(?product(Elements), K) -> are_all_limited(Elements, K - 1); is_limited(?union(Elements), K) -> are_all_limited(Elements, K); -is_limited(?opaque(Es), K) -> - lists:all(fun(#opaque{struct = S}) -> is_limited(S, K) end, Es); +is_limited(?nominal_set(Elements, S), K) -> + is_limited(S, K) andalso are_all_limited(Elements, K); +is_limited(?nominal(_, S), K) -> + %% To simplify checking opacity violations, nominals aren't counted in the + %% term depth. + is_limited(S, K); is_limited(?map(Pairs, DefK, DefV), K) -> %% Use the fact that t_sup() does not increase the depth. K1 = K - 1, lists:all(fun({Key, _, Value}) -> - is_limited(Key, K1) andalso is_limited(Value, K1) + is_limited(Key, K1) andalso is_limited(Value, K1) end, Pairs) andalso is_limited(DefK, K1) andalso is_limited(DefV, K1); is_limited(_, _K) -> true. -are_all_limited([E|Es], K) -> +are_all_limited([E | Es], K) -> is_limited(E, K) andalso are_all_limited(Es, K); are_all_limited([], _) -> true. -t_limit_k(_, K) when K =< 0 -> ?any; -t_limit_k(?tuple(?any, ?any, ?any) = T, _K) -> T; +t_limit_k(_, K) when K =< 0 -> + ?any; +t_limit_k(?tuple(?any, ?any, ?any) = T, _K) -> + T; t_limit_k(?tuple(Elements, Arity, _), K) -> - if K =:= 1 -> t_tuple(Arity); + if + K =:= 1 -> t_tuple(Arity); true -> t_tuple([t_limit_k(E, K-1) || E <- Elements]) end; t_limit_k(?tuple_set(_) = T, K) -> @@ -3871,14 +3572,11 @@ t_limit_k(?list(Elements, ?nil, Size), K) -> NewElements = t_limit_k(Elements, K - 1), ?list(NewElements, ?nil, Size); t_limit_k(?list(Elements, Termination, Size), K) -> - NewTermination = - if K =:= 1 -> - %% We do not want to lose the termination information. - t_limit_k(Termination, K); - true -> t_limit_k(Termination, K - 1) - end, - NewElements = t_limit_k(Elements, K - 1), - ?list(NewElements, NewTermination, Size); + %% We do not want to lose the termination information, always pass a K of at + %% least 1 for that. + ?list(t_limit_k(Elements, K - 1), + t_limit_k(Termination, max(1, K - 1)), + Size); t_limit_k(?function(Domain, Range), K) -> %% The domain is either a product or any() so we do not decrease the K. ?function(t_limit_k(Domain, K), t_limit_k(Range, K-1)); @@ -3886,23 +3584,26 @@ t_limit_k(?product(Elements), K) -> ?product([t_limit_k(X, K - 1) || X <- Elements]); t_limit_k(?union(Elements), K) -> ?union([t_limit_k(X, K) || X <- Elements]); -t_limit_k(?opaque(Es), K) -> - List = [begin - NewS = t_limit_k(S, K), - Opaque#opaque{struct = NewS} - end || #opaque{struct = S} = Opaque <- Es], - ?opaque(ordsets:from_list(List)); +t_limit_k(?nominal(Name, Inner), K) -> + %% To simplify checking opacity violations, nominals aren't counted in the + %% term depth. + ?nominal(Name, t_limit_k(Inner, K)); +t_limit_k(?nominal_set(Elements, S), K) -> + normalize_nominal_set([t_limit_k(X, K) || X <- Elements], + t_limit_k(S, K), + []); t_limit_k(?map(Pairs0, DefK0, DefV0), K) -> Fun = fun({EK, MNess, EV}, {Exact, DefK1, DefV1}) -> - LV = t_limit_k(EV, K - 1), - case t_limit_k(EK, K - 1) of - EK -> {[{EK,MNess,LV}|Exact], DefK1, DefV1}; - LK -> {Exact, t_sup(LK, DefK1), t_sup(LV, DefV1)} - end - end, + LV = t_limit_k(EV, K - 1), + case t_limit_k(EK, K - 1) of + EK -> {[{EK, MNess, LV}|Exact], DefK1, DefV1}; + LK -> {Exact, t_sup(LK, DefK1), t_sup(LV, DefV1)} + end + end, {Pairs, DefK2, DefV2} = lists:foldr(Fun, {[], DefK0, DefV0}, Pairs0), t_map(Pairs, t_limit_k(DefK2, K - 1), t_limit_k(DefV2, K - 1)); -t_limit_k(T, _K) -> T. +t_limit_k(T, _K) -> + T. %%============================================================================ %% @@ -3930,6 +3631,23 @@ t_abstract_records(?function(Domain, Range), RecDict) -> t_abstract_records(Range, RecDict)); t_abstract_records(?product(Types), RecDict) -> ?product([t_abstract_records(T, RecDict) || T <- Types]); +t_abstract_records(?nominal(N, ?nominal(_, _)=S0), RecDict) -> + case t_abstract_records(S0, RecDict) of + ?nominal(_, _)=S -> ?nominal(N, S); + _ -> ?any + end; +t_abstract_records(?nominal(N, ?nominal_set(_, _)=S0), RecDict) -> + case t_abstract_records(S0, RecDict) of + ?nominal_set(_, _)=S -> ?nominal(N, S); + ?nominal(_, _)=S -> ?nominal(N, S); + _ -> ?any + end; +t_abstract_records(?nominal(N, S), RecDict) -> + ?nominal(N, t_abstract_records(S, RecDict)); +t_abstract_records(?nominal_set(Elements, S), RecDict) -> + normalize_nominal_set([t_abstract_records(X, RecDict) || X <- Elements], + t_abstract_records(S, RecDict), + []); t_abstract_records(?union(Types), RecDict) -> t_sup([t_abstract_records(T, RecDict) || T <- Types]); t_abstract_records(?tuple(?any, ?any, ?any) = T, _RecDict) -> @@ -3944,8 +3662,6 @@ t_abstract_records(?tuple(Elements, _Arity, _Tag), RecDict) -> t_tuple([t_abstract_records(E, RecDict) || E <- Elements]); t_abstract_records(?tuple_set(_) = Tuples, RecDict) -> t_sup([t_abstract_records(T, RecDict) || T <- t_tuple_subtypes(Tuples)]); -t_abstract_records(?opaque(_)=Type, RecDict) -> - t_abstract_records(t_opaque_structure(Type), RecDict); t_abstract_records(T, _RecDict) -> T. @@ -4009,11 +3725,6 @@ t_to_string(?identifier(Set), _RecDict) -> _ -> flat_join([flat_format("~w()", [T]) || T <- Set], " | ") end; -t_to_string(?opaque(Set), RecDict) -> - flat_join([opaque_type(Mod, Name, Arity, S, RecDict) || - #opaque{mod = Mod, name = Name, struct = S, arity = Arity} - <- Set], - " | "); t_to_string(?nil, _RecDict) -> "[]"; t_to_string(?nonempty_list(Contents, Termination), RecDict) -> @@ -4085,6 +3796,20 @@ t_to_string(?int_range(From, To), _RecDict) -> flat_format("~w..~w", [From, To]); t_to_string(?integer(?any), _RecDict) -> "integer()"; t_to_string(?float, _RecDict) -> "float()"; +t_to_string(?nominal({Module, Name, Arity, _}, ?opaque), _RecDict) -> + Modname = flat_format("~w:~tw", [Module, Name]), + Args = lists:join($,, lists:duplicate(Arity, $_)), + flat_format("~ts(~ts)", [Modname, Args]); +t_to_string(?nominal({_Module, _Name, _Arity, opaque}, _) = N, _RecDict) -> + t_to_string(oc_mark(N, ?opaque, "erl_types")); +t_to_string(?nominal({Module, Name, Arity, _}, Structure), RecDict) -> + Modname = flat_format("~w:~tw", [Module, Name]), + Args = lists:join($,, lists:duplicate(Arity, $_)), + Namearity = flat_format("~ts(~ts)", [Modname, Args]), + StructureString = t_to_string(Structure, RecDict), + flat_format("(~ts :: ~ts)", [Namearity, StructureString]); +t_to_string(?nominal_set(T, S), RecDict) -> + union_sequence([N || N <- [S|T], N =/= ?none], RecDict); t_to_string(?number(?any, ?unknown_qual), _RecDict) -> "number()"; t_to_string(?product(List), RecDict) -> "<" ++ comma_sequence(List, RecDict) ++ ">"; @@ -4180,23 +3905,6 @@ union_sequence(Types, RecDict) -> List = [t_to_string(T, RecDict) || T <- Types], flat_join(List, " | "). --ifdef(DEBUG). -opaque_type(Mod, Name, Arity, S, RecDict) -> - String = t_to_string(S, RecDict), - opaque_name(Mod, Name, Arity) ++ "[" ++ String ++ "]". --else. -opaque_type(Mod, Name, Arity, _S, _RecDict) -> - opaque_name(Mod, Name, Arity). --endif. - -opaque_name(Mod, Name, Arity) -> - S = mod_name(Mod, Name), - Args = lists:join($,, lists:duplicate(Arity, $_)), - flat_format("~ts(~ts)", [S, Args]). - -mod_name(Mod, Name) -> - flat_format("~w:~tw", [Mod, Name]). - %%============================================================================= %% %% Build a type from parse forms. @@ -4537,13 +4245,7 @@ from_form({type, _Anno, union, Args}, S, D, L, C) -> {Lst, L1, C1} = list_from_form(Args, S, D, L, C), {t_sup(Lst), L1, C1}; from_form({user_type, _Anno, Name, Args}, S, D, L, C) -> - type_from_form(Name, Args, S, D, L, C); -from_form({type, _Anno, Name, Args}, S, D, L, C) -> - %% Compatibility: modules compiled before Erlang/OTP 18.0. - type_from_form(Name, Args, S, D, L, C); -from_form({opaque, _Anno, Name, {Mod, Args, Rep}}, _S, _D, L, C) -> - %% XXX. To be removed. - {t_opaque(Mod, Name, Args, Rep), L, C}. + type_from_form(Name, Args, S, D, L, C). builtin_type(Name, Type, S, D, L, C) -> #from_form{site = Site, mrecs = MR} = S, @@ -4567,7 +4269,7 @@ type_from_form(Name, Args, S, D, L, C) -> TypeName = {type, {Module, Name, ArgsLen}}, case can_unfold_more(TypeName, TypeNames) of true -> - {R, C1} = lookup_module_types(Module, MR, C), + {R, C1} = case lookup_module_types(Module, MR, C) of error -> error({Name, Args}); KK -> KK end, type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames, Site, S, D, L, C1); false -> @@ -4580,7 +4282,7 @@ type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames, Site, {_, {_, _}} when element(1, Site) =:= check -> {_ArgTypes, L1, C1} = list_from_form(Args, S, D, L, C), {t_any(), L1, C1}; - {Tag, {{Module, {File,_Location}, Form, ArgNames}, Type}} -> + {Tag, {{Module, {File,_Location}, Form, ArgNames}, _Type}} -> NewTypeNames = [TypeName|TypeNames], S1 = S#from_form{tnames = NewTypeNames}, {ArgTypes, L1, C1} = list_from_form(Args, S1, D, L, C), @@ -4597,18 +4299,14 @@ type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames, Site, Fun = fun(DD, LL) -> from_form(Form, S2, DD, LL, C1) end, {NewType, L3, C3} = case Tag of - type -> - recur_limit(Fun, D, L1, TypeName, TypeNames); + nominal -> + {Rep, L2, C2} = recur_limit(Fun, D, L1, TypeName, TypeNames), + {t_nominal({Module, Name, ArgsLen, transparent}, Rep), L2, C2}; opaque -> {Rep, L2, C2} = recur_limit(Fun, D, L1, TypeName, TypeNames), - Rep1 = choose_opaque_type(Rep, Type), - Rep2 = case cannot_have_opaque(Rep1, TypeName, TypeNames) of - true -> Rep; - false -> - ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), - t_opaque(Module, Name, ArgTypes2, Rep1) - end, - {Rep2, L2, C2} + {t_nominal({Module, Name, ArgsLen, opaque}, Rep), L2, C2}; + type -> + recur_limit(Fun, D, L1, TypeName, TypeNames) end, C4 = cache_put(CKey, NewType, L1 - L3, C3), {NewType, L3, C4} @@ -4658,7 +4356,7 @@ remote_from_form1(RemMod, Name, Args, ArgsLen, RemDict, RemType, TypeNames, {_, {_, _}} when element(1, Site) =:= check -> {_ArgTypes, L1, C1} = list_from_form(Args, S, D, L, C), {t_any(), L1, C1}; - {Tag, {{Mod, {File,_Location}, Form, ArgNames}, Type}} -> + {Tag, {{Mod, {File,_Location}, Form, ArgNames}, _Type}} -> NewTypeNames = [RemType|TypeNames], S1 = S#from_form{tnames = NewTypeNames}, {ArgTypes, L1, C1} = list_from_form(Args, S1, D, L, C), @@ -4675,19 +4373,14 @@ remote_from_form1(RemMod, Name, Args, ArgsLen, RemDict, RemType, TypeNames, Fun = fun(DD, LL) -> from_form(Form, S2, DD, LL, C1) end, {NewType, L3, C3} = case Tag of - type -> - recur_limit(Fun, D, L1, RemType, TypeNames); + nominal -> + {NewRep, L2, C2} = recur_limit(Fun, D, L1, RemType, TypeNames), + {t_nominal({Mod, Name, ArgsLen, transparent}, NewRep), L2, C2}; opaque -> {NewRep, L2, C2} = recur_limit(Fun, D, L1, RemType, TypeNames), - NewRep1 = choose_opaque_type(NewRep, Type), - NewRep2 = - case cannot_have_opaque(NewRep1, RemType, TypeNames) of - true -> NewRep; - false -> - ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), - t_opaque(Mod, Name, ArgTypes2, NewRep1) - end, - {NewRep2, L2, C2} + {t_nominal({Mod, Name, ArgsLen, opaque}, NewRep), L2, C2}; + type -> + recur_limit(Fun, D, L1, RemType, TypeNames) end, C4 = cache_put(CKey, NewType, L1 - L3, C3), {NewType, L3, C4} @@ -4698,27 +4391,7 @@ remote_from_form1(RemMod, Name, Args, ArgsLen, RemDict, RemType, TypeNames, throw({error, Msg}) end. -subst_all_vars_to_any_list(Types) -> - [subst_all_vars_to_any(Type) || Type <- Types]. -%% Opaque types (both local and remote) are problematic when it comes -%% to the limits (TypeNames, D, and L). The reason is that if any() is -%% substituted for a more specialized subtype of an opaque type, the -%% property stated along with decorate_with_opaque() (the type has to -%% be a subtype of the declared type) no longer holds. -%% -%% The less than perfect remedy: if the opaque type created from a -%% form is not a subset of the declared type, the declared type is -%% used instead, effectively bypassing the limits, and potentially -%% resulting in huge types. -choose_opaque_type(Type, DeclType) -> - case - t_is_subtype(subst_all_vars_to_any(Type), - subst_all_vars_to_any(DeclType)) - of - true -> Type; - false -> DeclType - end. record_from_form({atom, _, Name}, ModFields, S, D0, L0, C) -> #from_form{site = Site, mrecs = MR, tnames = TypeNames} = S, @@ -4836,7 +4509,8 @@ separate_key(?number(_, _) = T) -> t_elements(T); separate_key(?union(List)) -> lists:append([separate_key(K) || K <- List, not t_is_none(K)]); -separate_key(Key) -> [Key]. +separate_key(Key) -> + [Key]. %% Sorts, combines non-singleton pairs, and applies precedence and %% mandatoriness rules. @@ -5239,25 +4913,25 @@ lookup_record(Tag, Arity, Table) when is_atom(Tag) -> error end. --spec lookup_type(_, _, _) -> {'type' | 'opaque', type_value()} | 'error'. +-spec lookup_type(_, _, _) -> {'type' | 'opaque' | 'nominal', type_value()} | 'error'. lookup_type(Name, Arity, Table) -> case Table of #{{type, Name, Arity} := Found} -> {type, Found}; #{{opaque, Name, Arity} := Found} -> {opaque, Found}; + #{{nominal, Name, Arity} := Found} -> + {nominal, Found}; #{} -> error end. --spec type_is_defined('type' | 'opaque', atom(), arity(), type_table()) -> +-spec type_is_defined('type' | 'opaque' | 'nominal', atom(), arity(), type_table()) -> boolean(). type_is_defined(TypeOrOpaque, Name, Arity, Table) -> maps:is_key({TypeOrOpaque, Name, Arity}, Table). -cannot_have_opaque(Type, TypeName, TypeNames) -> - t_is_none(Type) orelse is_recursive(TypeName, TypeNames). is_recursive(TypeName, TypeNames) -> lists:member(TypeName, TypeNames). @@ -5266,56 +4940,40 @@ can_unfold_more(TypeName, TypeNames) -> Fun = fun(E, Acc) -> case E of TypeName -> Acc + 1; _ -> Acc end end, lists:foldl(Fun, 0, TypeNames) < ?REC_TYPE_LIMIT. --spec do_opaque(erl_type(), opaques(), fun((_) -> T)) -> T. +-spec structural(erl_type(), fun((_) -> T)) -> T. -%% Probably a little faster than calling t_unopaque/2. +%% Probably a little faster than calling t_structural/2. %% Unions that are due to opaque types are unopaqued. -do_opaque(?opaque(_) = Type, Opaques, Pred) -> - case Opaques =:= 'universe' orelse is_opaque_type(Type, Opaques) of - true -> do_opaque(t_opaque_structure(Type), Opaques, Pred); - false -> Pred(Type) - end; -do_opaque(?union(List) = Type, Opaques, Pred) -> - ?untagged_union(A,B,F,I,L,N,T,O,Map) = List, - if O =:= ?none -> Pred(Type); - true -> - case Opaques =:= 'universe' orelse is_opaque_type(O, Opaques) of - true -> - S = t_opaque_structure(O), - do_opaque(t_sup(?untagged_union(A,B,F,I,L,N,T,S,Map)), Opaques, Pred); - false -> Pred(Type) - end - end; -do_opaque(Type, _Opaques, Pred) -> +structural(?nominal_set([], S), Pred) -> + structural(S, Pred); +structural(?nominal_set([?nominal(_, S1) | T], Str), Pred) -> + structural(?nominal_set(T, t_sup(Str, S1)), Pred); +structural(?nominal(_, S), Pred) -> + structural(S, Pred); +structural(Type, Pred) -> Pred(Type). map_all_values(?map(Pairs,_,DefV)) -> - [DefV|[V || {V, _, _} <- Pairs]]. - -map_all_keys(?map(Pairs,DefK,_)) -> - [DefK|[K || {_, _, K} <- Pairs]]. - -map_all_types(M) -> - map_all_keys(M) ++ map_all_values(M). + [DefV | [V || {V, _, _} <- Pairs]]. %% Tests if a type has exactly one possible value. -spec t_is_singleton(erl_type()) -> boolean(). t_is_singleton(Type) -> - t_is_singleton(Type, 'universe'). - --spec t_is_singleton(erl_type(), opaques()) -> boolean(). - -t_is_singleton(Type, Opaques) -> - do_opaque(Type, Opaques, fun is_singleton_type/1). + structural(Type, fun is_singleton_type/1). %% To be in sync with separate_key/1. %% Used to also recognize maps and tuples. -is_singleton_type(?nil) -> true; -is_singleton_type(?atom(?any)) -> false; -is_singleton_type(?atom([_])) -> true; -is_singleton_type(?int_range(V, V)) -> true; % cannot happen -is_singleton_type(?int_set([_])) -> true; +is_singleton_type(?nil) -> + true; +is_singleton_type(?atom(?any)) -> + false; +is_singleton_type(?atom([_])) -> + true; +is_singleton_type(?int_range(V, V)) -> + true; % cannot happen +is_singleton_type(?int_set([_])) -> + true; is_singleton_type(_) -> false. @@ -5479,6 +5137,9 @@ module_type_deps_of_type_defs(TypeTable) -> module_type_deps_of_entry({{'type', _TypeName, _A}, {{_FromM, _FileLine, AbstractType, _ArgNames}, _}}) -> type_form_to_remote_modules(AbstractType); +module_type_deps_of_entry({{'nominal', _TypeName, _A}, {{_FromM, _FileLine, AbstractType, _ArgNames}, _}}) -> + type_form_to_remote_modules(AbstractType); + module_type_deps_of_entry({{'opaque', _TypeName, _A}, {{_FromM, _FileLine, AbstractType, _ArgNames}, _}}) -> type_form_to_remote_modules(AbstractType); @@ -5582,4 +5243,4 @@ list_get_modules_mentioned([], _D, L, Acc) -> {L, Acc}; list_get_modules_mentioned([H|Tail], D, L, Acc) -> {L1, Acc1} = get_modules_mentioned(H, D, L - 1, Acc), - list_get_modules_mentioned(Tail, D, L1, Acc1). + list_get_modules_mentioned(Tail, D, L1, Acc1). \ No newline at end of file diff --git a/lib/dialyzer/src/typer_core.erl b/lib/dialyzer/src/typer_core.erl index 131308b32b0c..a0f97ced7f86 100644 --- a/lib/dialyzer/src/typer_core.erl +++ b/lib/dialyzer/src/typer_core.erl @@ -433,7 +433,7 @@ get_type({{M, F, A} = MFA, Range, Arg}, CodeServer, Records, Analysis) -> {{F, A}, {Range, Arg}}; {ok, {_FileLine, Contract, _Xtra}} -> Sig = erl_types:t_fun(Arg, Range), - case dialyzer_contracts:check_contract(Contract, Sig) of + case dialyzer_contracts:check_contract(Contract, Sig, M) of ok -> {{F, A}, {contract, Contract}}; {range_warnings, _} -> {{F, A}, {contract, Contract}}; diff --git a/lib/dialyzer/test/cplt_SUITE.erl b/lib/dialyzer/test/cplt_SUITE.erl index 725ed455a689..b839f507fd13 100644 --- a/lib/dialyzer/test/cplt_SUITE.erl +++ b/lib/dialyzer/test/cplt_SUITE.erl @@ -288,8 +288,7 @@ local_fun_same_as_callback(Config) when is_list(Config) -> ErlangBeam = case code:where_is_file("erlang.beam") of non_existing -> filename:join([code:root_dir(), - "erts", "preloaded", "ebin", - "erlang.beam"]); + "erts", "ebin", "erlang.beam"]); EBeam -> EBeam end, @@ -900,8 +899,7 @@ erlang_beam() -> case code:where_is_file("erlang.beam") of non_existing -> filename:join([code:root_dir(), - "erts", "preloaded", "ebin", - "erlang.beam"]); + "erts", "ebin", "erlang.beam"]); EBeam -> EBeam end. diff --git a/lib/dialyzer/test/incremental_SUITE.erl b/lib/dialyzer/test/incremental_SUITE.erl index 1bf5731db8fa..b342eb57c31a 100644 --- a/lib/dialyzer/test/incremental_SUITE.erl +++ b/lib/dialyzer/test/incremental_SUITE.erl @@ -64,8 +64,7 @@ erlang_module() -> case code:where_is_file("erlang.beam") of non_existing -> filename:join([code:root_dir(), - "erts", "preloaded", "ebin", - "erlang.beam"]); + "erts", "ebin", "erlang.beam"]); EBeam -> EBeam end. diff --git a/lib/dialyzer/test/indent_SUITE_data/results/dict_use b/lib/dialyzer/test/indent_SUITE_data/results/dict_use index 4039223eec09..bd529077c4a7 100644 --- a/lib/dialyzer/test/indent_SUITE_data/results/dict_use +++ b/lib/dialyzer/test/indent_SUITE_data/results/dict_use @@ -1,42 +1,82 @@ -dict_use.erl:41:3: The attempt to match a term of type - dict:dict(_, _) against the pattern - 'gazonk' breaks the opacity of the term -dict_use.erl:45:5: The attempt to match a term of type - dict:dict(_, _) against the pattern - [] breaks the opacity of the term -dict_use.erl:46:5: The attempt to match a term of type - dict:dict(_, _) against the pattern - 42 breaks the opacity of the term -dict_use.erl:51:5: The attempt to match a term of type - dict:dict(_, _) against the pattern - [] breaks the opacity of the term -dict_use.erl:52:5: The attempt to match a term of type - dict:dict(_, _) against the pattern - 42 breaks the opacity of the term +dict_use.erl:41:3: The pattern + 'gazonk' can never match the type + dict:dict(_, _) +dict_use.erl:45:5: The pattern + [] can never match the type + dict:dict(_, _) +dict_use.erl:46:5: The pattern + 42 can never match the type + dict:dict(_, _) +dict_use.erl:51:5: The pattern + [] can never match the type + dict:dict(_, _) +dict_use.erl:52:5: The pattern + 42 can never match the type + dict:dict(_, _) dict_use.erl:58:3: Attempt to test for equality between a term of type maybe_improper_list() and a term of opaque type dict:dict(_, _) +dict_use.erl:58:3: The test + maybe_improper_list() =:= + dict:dict(_, _) can never evaluate to 'true' dict_use.erl:60:3: Attempt to test for inequality between a term of type atom() and a term of opaque type dict:dict(_, _) -dict_use.erl:64:19: Guard test length - (D :: dict:dict(_, _)) breaks the opacity of its argument -dict_use.erl:65:20: Guard test is_atom - (D :: dict:dict(_, _)) breaks the opacity of its argument -dict_use.erl:66:20: Guard test is_list - (D :: dict:dict(_, _)) breaks the opacity of its argument -dict_use.erl:70:3: The type test is_list - (dict:dict(_, _)) breaks the opacity of the term - dict:dict(_, _) +dict_use.erl:60:3: The test + atom() =/= + dict:dict(_, _) can never evaluate to 'false' +dict_use.erl:64:12: Guard test length + (D :: dict:dict(_, _)) can never succeed +dict_use.erl:65:12: Guard test is_atom + (D :: dict:dict(_, _)) can never succeed +dict_use.erl:66:12: Guard test is_list + (D :: dict:dict(_, _)) can never succeed dict_use.erl:73:19: The call dict:fetch ('foo', [1, 2, 3]) does not have an opaque term of type dict:dict(_, _) as 2nd argument +dict_use.erl:73:19: The call dict:fetch + ('foo', + [1, 2, 3]) will never return since the success typing is + (any(), + {'dict', + non_neg_integer(), + non_neg_integer(), + pos_integer(), + non_neg_integer(), + non_neg_integer(), + non_neg_integer(), + tuple(), + tuple()}) -> + any() and the contract is + (Key, Dict) -> Value when Dict :: dict(Key, Value) dict_use.erl:76:19: The call dict:merge (Fun :: any(), 42, [1, 2]) does not have opaque terms as 2nd and 3rd arguments +dict_use.erl:76:19: The call dict:merge + (Fun :: any(), + 42, + [1, 2]) will never return since the success typing is + (any(), + any(), + {'dict', + non_neg_integer(), + non_neg_integer(), + non_neg_integer(), + non_neg_integer(), + non_neg_integer(), + non_neg_integer(), + tuple(), + tuple()}) -> + any() and the contract is + (Fun, Dict1, Dict2) -> Dict3 + when + Fun :: fun((Key, Value1, Value2) -> Value), + Dict1 :: dict(Key, Value1), + Dict2 :: dict(Key, Value2), + Dict3 :: dict(Key, Value) dict_use.erl:80:7: The call dict:store (42, 'elli', diff --git a/lib/dialyzer/test/indent_SUITE_data/results/map_galore b/lib/dialyzer/test/indent_SUITE_data/results/map_galore index 13a39d80cd48..2e82edd2c862 100644 --- a/lib/dialyzer/test/indent_SUITE_data/results/map_galore +++ b/lib/dialyzer/test/indent_SUITE_data/results/map_galore @@ -705,6 +705,18 @@ map_galore.erl:2281:50: The call maps:from_list map_galore.erl:2282:50: The call maps:from_list (42) will never return since it differs in the 1st argument from the success typing arguments: ([{_, _}]) +map_galore.erl:982:12: The test + #{1 := 'a', + 2 := 'b', + 4 := 'd', + 5 := 'e', + float() => 'c' | 'new'} =/= + #{1 := 'a', + 2 := 'b', + 3 := 'right', + 4 := 'd', + 5 := 'e', + float() => 'c' | 'new'} can never evaluate to 'false' map_galore.erl:997:55: A key of type 'nonexisting' cannot exist in a map of type #{} diff --git a/lib/dialyzer/test/indent_SUITE_data/results/queue_use b/lib/dialyzer/test/indent_SUITE_data/results/queue_use index 77afde07c48c..facc21cb2a93 100644 --- a/lib/dialyzer/test/indent_SUITE_data/results/queue_use +++ b/lib/dialyzer/test/indent_SUITE_data/results/queue_use @@ -18,17 +18,26 @@ queue_use.erl:36:5: The attempt to match a term of type queue_use.erl:40:35: The call queue:out ({"*", []}) does not have an opaque term of type queue:queue(_) as 1st argument -queue_use.erl:51:25: The call queue_use:is_in_queue - (E :: 42, - DB :: #db{p :: [], q :: queue:queue(_)}) contains an opaque term as 2nd argument when terms of different types are expected in these positions -queue_use.erl:56:1: The attempt to match a term of type - #db{p :: [], q :: queue:queue(_)} against the pattern - {'db', _, {L1, L2}} breaks the opacity of - queue:queue(_) +queue_use.erl:52:2: The pattern + 'true' can never match the type + 'false' +queue_use.erl:56:24: The attempt to match a term of type + queue:queue(_) against the pattern + {L1, L2} breaks the opacity of the term queue_use.erl:62:17: The call queue_use:tuple_queue ({42, 'gazonk'}) does not have a term of type {_, queue:queue(_)} (with opaque subterms) as 1st argument +queue_use.erl:62:17: The call queue_use:tuple_queue + ({42, 'gazonk'}) will never return since it differs in the 1st argument from the success typing arguments: + ({_, queue:queue(_)}) queue_use.erl:65:17: The call queue:in (F :: 42, Q :: 'gazonk') does not have an opaque term of type queue:queue(_) as 2nd argument +queue_use.erl:65:17: The call queue:in + (F :: 42, + Q :: 'gazonk') will never return since the success typing is + (any(), + {maybe_improper_list(), maybe_improper_list()}) -> + {nonempty_maybe_improper_list(), maybe_improper_list()} and the contract is + (Item, Q1 :: queue(Item)) -> Q2 :: queue(Item) diff --git a/lib/dialyzer/test/indent_SUITE_data/results/rec b/lib/dialyzer/test/indent_SUITE_data/results/rec index 7bd512073d55..5dbd931eec37 100644 --- a/lib/dialyzer/test/indent_SUITE_data/results/rec +++ b/lib/dialyzer/test/indent_SUITE_data/results/rec @@ -2,7 +2,7 @@ rec_use.erl:17:2: The attempt to match a term of type rec_adt:rec() against the pattern {'rec', _, 42} breaks the opacity of the term -rec_use.erl:18:20: Guard test tuple_size +rec_use.erl:18:9: Guard test tuple_size (R :: rec_adt:rec()) breaks the opacity of its argument rec_use.erl:23:19: The call rec_adt:get_a (R :: tuple()) does not have an opaque term of type @@ -10,6 +10,3 @@ rec_use.erl:23:19: The call rec_adt:get_a rec_use.erl:27:5: Attempt to test for equality between a term of type {'rec', 'gazonk', 42} and a term of opaque type rec_adt:rec() -rec_use.erl:30:16: The call erlang:tuple_size - (rec_adt:rec()) contains an opaque term as 1st argument when a structured term of type - tuple() is expected diff --git a/lib/dialyzer/test/indent_SUITE_data/results/simple b/lib/dialyzer/test/indent_SUITE_data/results/simple index 7fea96c5021c..0c4e50ae36a5 100644 --- a/lib/dialyzer/test/indent_SUITE_data/results/simple +++ b/lib/dialyzer/test/indent_SUITE_data/results/simple @@ -19,124 +19,104 @@ exact_api.erl:55:5: The attempt to match a term of type exact_api.erl:59:39: The call exact_adt:exact_adt_set_type2 (A :: #exact_adt{}) does not have an opaque term of type exact_adt:exact_adt() as 1st argument -is_rec.erl:10:5: The call erlang:is_record - (simple1_adt:d1(), - 'r', - 2) contains an opaque term as 1st argument when terms of different types are expected in these positions -is_rec.erl:15:15: The call erlang:is_record - (A :: simple1_adt:d1(), - 'r', - I :: 1 | 2 | 3) contains an opaque term as 1st argument when terms of different types are expected in these positions -is_rec.erl:19:18: Guard test is_record +is_rec.erl:19:8: Guard test is_record (A :: simple1_adt:d1(), 'r', - 2) breaks the opacity of its argument -is_rec.erl:23:18: Guard test is_record + 2) can never succeed +is_rec.erl:23:8: Guard test is_record ({simple1_adt:d1(), 1}, 'r', - 2) breaks the opacity of its argument -is_rec.erl:41:15: The call erlang:is_record - (A :: simple1_adt:d1(), - R :: 'a') contains an opaque term as 1st argument when terms of different types are expected in these positions -is_rec.erl:45:18: The call erlang:is_record - (A :: simple1_adt:d1(), - A :: simple1_adt:d1(), - 1) contains an opaque term as 2nd argument when terms of different types are expected in these positions -is_rec.erl:49:15: The call erlang:is_record - (A :: simple1_adt:d1(), - any(), - 1) contains an opaque term as 1st argument when terms of different types are expected in these positions -is_rec.erl:53:18: The call erlang:is_record - (A :: simple1_adt:d1(), - A :: simple1_adt:d1(), - any()) contains an opaque term as 2nd argument when terms of different types are expected in these positions -is_rec.erl:57:18: Guard test is_record + 2) can never succeed +is_rec.erl:57:8: Guard test is_record (A :: simple1_adt:d1(), 'r', - 2) breaks the opacity of its argument + 2) can never succeed is_rec.erl:61:8: The record #r{f1 :: simple1_adt:d1()} violates the declared type for #r{} -is_rec.erl:65:5: The call erlang:is_record - ({simple1_adt:d1(), 1}, - 'r', - 2) contains an opaque term as 1st argument when terms of different types are expected in these positions rec_api.erl:104:5: Matching of pattern {'r2', 10} tagged with a record name violates the declared type of #r2{f1 :: 10} -rec_api.erl:113:5: The attempt to match a term of type - #r3{f1 :: queue:queue(_)} against the pattern - {'r3', 'a'} breaks the opacity of - queue:queue(_) +rec_api.erl:113:5: The pattern + {'r3', 'a'} can never match the type + #r3{f1 :: queue:queue(_)} rec_api.erl:118:18: Record construction #r3{f1 :: 10} violates the declared type of field f1 :: queue:queue(_) -rec_api.erl:123:5: The attempt to match a term of type - #r3{f1 :: 10} against the pattern - {'r3', 10} breaks the opacity of - queue:queue(_) +rec_api.erl:123:5: Matching of pattern + {'r3', 10} tagged with a record name violates the declared type of + #r3{f1 :: 10} rec_api.erl:24:18: Record construction #r1{f1 :: 10} violates the declared type of field f1 :: rec_api:a() rec_api.erl:29:5: Matching of pattern {'r1', 10} tagged with a record name violates the declared type of #r1{f1 :: 10} +rec_api.erl:33:10: The attempt to match a term of type + rec_adt:a() against the pattern + 'a' breaks the opacity of the term rec_api.erl:33:5: The attempt to match a term of type rec_adt:r1() against the pattern {'r1', 'a'} breaks the opacity of the term -rec_api.erl:35:2: Invalid type specification for function rec_api:adt_t1/1. - The success typing is rec_api:adt_t1 +rec_api.erl:35:2: The specification for rec_api:adt_t1/1 has an opaque subtype + rec_adt:r1() which is violated by the success typing (#r1{f1 :: 'a'}) -> #r1{f1 :: 'a'} - But the spec is rec_api:adt_t1 - (rec_adt:r1()) -> rec_adt:r1() - They do not overlap in the 1st argument, and the return types do not overlap rec_api.erl:40:2: The specification for rec_api:adt_r1/0 has an opaque subtype rec_adt:r1() which is violated by the success typing - () -> #r1{f1 :: 'a'} -rec_api.erl:85:13: The attempt to match a term of type - rec_adt:f() against the record field 'f' declared to be of type - rec_api:f() breaks the opacity of the term + () -> #r1{f1 :: rec_api:a()} +rec_api.erl:85:13: Record construction + #r{f :: rec_adt:f(), o :: 2} violates the declared type of field f :: + rec_api:f() rec_api.erl:99:18: Record construction #r2{f1 :: 10} violates the declared type of field f1 :: rec_api:a() +simple1_api.erl:102:5: Guard test + simple1_api:o2() =:= + A :: simple1_api:o1() can never succeed +simple1_api.erl:108:5: The test + simple1_api:o1() =:= + simple1_api:o2() can never evaluate to 'true' simple1_api.erl:113:5: The test simple1_api:d1() =:= simple1_api:d2() can never evaluate to 'true' simple1_api.erl:118:5: Guard test simple1_api:d2() =:= A :: simple1_api:d1() can never succeed -simple1_api.erl:142:5: Attempt to test for equality between a term of type - simple1_adt:o2() and a term of opaque type - simple1_adt:o1() +simple1_api.erl:123:5: The test + simple1_api:d1() =/= + simple1_api:d2() can never evaluate to 'false' +simple1_api.erl:128:5: The test + simple1_api:d1() /= + simple1_api:d2() can never evaluate to 'false' +simple1_api.erl:142:5: The test + simple1_adt:o1() =:= + simple1_adt:o2() can never evaluate to 'true' simple1_api.erl:148:5: Guard test simple1_adt:o2() =:= - A :: simple1_adt:o1() contains opaque terms as 1st and 2nd arguments -simple1_api.erl:154:5: Attempt to test for inequality between a term of type - simple1_adt:o2() and a term of opaque type - simple1_adt:o1() -simple1_api.erl:160:5: Attempt to test for inequality between a term of type - simple1_adt:o2() and a term of opaque type - simple1_adt:o1() -simple1_api.erl:165:5: Attempt to test for equality between a term of type - simple1_adt:c2() and a term of opaque type - simple1_adt:c1() + A :: simple1_adt:o1() can never succeed +simple1_api.erl:154:5: The test + simple1_adt:o1() =/= + simple1_adt:o2() can never evaluate to 'false' +simple1_api.erl:160:5: The test + simple1_adt:o1() /= + simple1_adt:o2() can never evaluate to 'false' +simple1_api.erl:165:5: The test + simple1_adt:c1() =:= + simple1_adt:c2() can never evaluate to 'true' simple1_api.erl:181:8: Guard test A :: simple1_adt:d1() =< B :: simple1_adt:d2() contains opaque terms as 1st and 2nd arguments -simple1_api.erl:185:13: Guard test +simple1_api.erl:185:8: Guard test 'a' =< B :: simple1_adt:d2() contains an opaque term as 2nd argument simple1_api.erl:189:8: Guard test A :: simple1_adt:d1() =< 'd' contains an opaque term as 1st argument -simple1_api.erl:197:5: The type test is_integer - (A :: simple1_adt:d1()) breaks the opacity of the term A:: - simple1_adt:d1() simple1_api.erl:221:8: Guard test A :: simple1_api:i1() > 3 can never succeed simple1_api.erl:225:8: Guard test A :: simple1_adt:i1() > - 3 contains an opaque term as 1st argument + 3 can never succeed simple1_api.erl:233:8: Guard test A :: simple1_adt:i1() < 3 contains an opaque term as 1st argument @@ -148,28 +128,14 @@ simple1_api.erl:243:8: Guard test 3 can never succeed simple1_api.erl:257:8: Guard test is_function (T :: simple1_api:o1()) can never succeed -simple1_api.erl:265:20: Guard test is_function - (T :: simple1_adt:o1()) breaks the opacity of its argument -simple1_api.erl:269:5: The type test is_function - (T :: simple1_adt:o1()) breaks the opacity of the term T:: - simple1_adt:o1() +simple1_api.erl:265:8: Guard test is_function + (T :: simple1_adt:o1()) can never succeed simple1_api.erl:274:8: Guard test is_function (T :: simple1_api:o1(), A :: simple1_api:i1()) can never succeed -simple1_api.erl:284:20: Guard test is_function - (T :: simple1_adt:o1(), - A :: simple1_adt:i1()) breaks the opacity of its argument -simple1_api.erl:289:5: The type test is_function +simple1_api.erl:284:8: Guard test is_function (T :: simple1_adt:o1(), - A :: simple1_adt:i1()) breaks the opacity of the term T:: - simple1_adt:o1() -simple1_api.erl:294:20: The call erlang:is_function - (T :: simple1_api:o1(), - A :: simple1_adt:i1()) contains an opaque term as 2nd argument when terms of different types are expected in these positions -simple1_api.erl:300:5: The type test is_function - (T :: simple1_adt:o1(), - A :: simple1_api:i1()) breaks the opacity of the term T:: - simple1_adt:o1() + A :: simple1_adt:i1()) can never succeed simple1_api.erl:306:8: Guard test B :: simple1_api:b2() =:= 'true' can never succeed @@ -179,56 +145,38 @@ simple1_api.erl:315:8: Guard test simple1_api.erl:319:16: Guard test not(and ('true', 'true')) can never succeed +simple1_api.erl:333:2: Invalid type specification for function simple1_api:bool_t7/0. + The success typing is simple1_api:bool_t7 + () -> none() + But the spec is simple1_api:bool_t7 + () -> integer() + The return types do not overlap simple1_api.erl:337:8: Clause guard cannot succeed. simple1_api.erl:342:8: Guard test B :: simple1_adt:b2() =:= - 'true' contains an opaque term as 1st argument -simple1_api.erl:347:8: Guard test - A :: simple1_adt:b1() =:= - 'true' contains an opaque term as 1st argument -simple1_api.erl:355:2: Invalid type specification for function simple1_api:bool_adt_t6/1. - The success typing is simple1_api:bool_adt_t6 - ('true') -> 1 - But the spec is simple1_api:bool_adt_t6 - (simple1_adt:b1()) -> integer() - They do not overlap in the 1st argument + 'true' can never succeed +simple1_api.erl:361:2: Invalid type specification for function simple1_api:bool_t8/0. + The success typing is simple1_api:bool_t8 + () -> none() + But the spec is simple1_api:bool_t8 + () -> integer() + The return types do not overlap simple1_api.erl:365:8: Clause guard cannot succeed. -simple1_api.erl:368:2: Invalid type specification for function simple1_api:bool_adt_t8/2. - The success typing is simple1_api:bool_adt_t8 - (boolean(), boolean()) -> 1 - But the spec is simple1_api:bool_adt_t8 - (simple1_adt:b1(), simple1_adt:b2()) -> integer() - They do not overlap in the 1st and 2nd arguments +simple1_api.erl:374:2: Invalid type specification for function simple1_api:bool_t9/0. + The success typing is simple1_api:bool_t9 + () -> none() + But the spec is simple1_api:bool_t9 + () -> integer() + The return types do not overlap simple1_api.erl:378:8: Clause guard cannot succeed. -simple1_api.erl:381:2: Invalid type specification for function simple1_api:bool_adt_t9/2. - The success typing is simple1_api:bool_adt_t9 - ('false', 'false') -> 1 - But the spec is simple1_api:bool_adt_t9 - (simple1_adt:b1(), simple1_adt:b2()) -> integer() - They do not overlap in the 1st and 2nd arguments simple1_api.erl:407:12: The size simple1_adt:i1() breaks the opacity of A -simple1_api.erl:418:9: The attempt to match a term of type - non_neg_integer() against the variable A breaks the opacity of - simple1_adt:i1() -simple1_api.erl:425:9: The attempt to match a term of type - non_neg_integer() against the variable B breaks the opacity of - simple1_adt:i1() simple1_api.erl:432:9: The pattern <<_:B>> can never match the type any() -simple1_api.erl:448:9: The attempt to match a term of type - non_neg_integer() against the variable Sz breaks the opacity of - simple1_adt:i1() simple1_api.erl:460:9: The attempt to match a term of type simple1_adt:bit1() against the pattern <<_/binary>> breaks the opacity of the term -simple1_api.erl:478:9: The call 'foo':A - (A :: simple1_adt:a()) breaks the opacity of the term A :: - simple1_adt:a() -simple1_api.erl:486:5: The call A:'foo' - (A :: simple1_adt:a()) breaks the opacity of the term A :: - simple1_adt:a() simple1_api.erl:499:9: The call 'foo':A (A :: simple1_api:i()) requires that A is of type atom() not @@ -247,57 +195,51 @@ simple1_api.erl:511:5: The call A:'foo' simple1_adt:i() simple1_api.erl:519:9: Guard test A :: simple1_adt:d2() == - B :: simple1_adt:d1() contains opaque terms as 1st and 2nd arguments + B :: simple1_adt:d1() can never succeed +simple1_api.erl:521:9: Guard test + A :: simple1_adt:d2() == + A :: simple1_adt:d2() contains opaque terms as 1st and 2nd arguments simple1_api.erl:534:9: Guard test A :: simple1_adt:d1() >= 3 contains an opaque term as 1st argument simple1_api.erl:536:9: Guard test A :: simple1_adt:d1() == - 3 contains an opaque term as 1st argument + 3 can never succeed simple1_api.erl:538:9: Guard test A :: simple1_adt:d1() =:= - 3 contains an opaque term as 1st argument -simple1_api.erl:548:5: The call erlang:'<' - (A :: simple1_adt:d1(), - 3) contains an opaque term as 1st argument when terms of different types are expected in these positions -simple1_api.erl:558:5: The call erlang:'=<' - (A :: simple1_adt:d1(), - B :: simple1_adt:d2()) contains opaque terms as 1st and 2nd arguments when terms of different types are expected in these positions -simple1_api.erl:565:17: Guard test - {digraph:graph(), 3} > - {digraph:graph(), atom() | ets:tid()} contains an opaque term as 2nd argument + 3 can never succeed +simple1_api.erl:540:9: Guard test + A :: simple1_adt:d1() == + A :: simple1_adt:d1() contains opaque terms as 1st and 2nd arguments simple1_api.erl:91:2: The specification for simple1_api:tup/0 has an opaque subtype simple1_adt:tuple1() which is violated by the success typing () -> {'a', 'b'} simple2_api.erl:100:19: The call lists:flatten (A :: simple1_adt:tuple1()) contains an opaque term as 1st argument when a structured term of type [any()] is expected +simple2_api.erl:100:19: The call lists:flatten + (A :: simple1_adt:tuple1()) will never return since it differs in the 1st argument from the success typing arguments: + ([any()]) simple2_api.erl:116:19: The call lists:flatten ({simple1_adt:tuple1()}) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) -simple2_api.erl:121:16: Guard test - {simple1_adt:d1(), 3} > - {simple1_adt:d1(), simple1_adt:tuple1()} contains an opaque term as 2nd argument -simple2_api.erl:125:19: The call erlang:tuple_to_list - (B :: simple1_adt:tuple1()) contains an opaque term as 1st argument when a structured term of type - tuple() is expected -simple2_api.erl:31:5: The call erlang:'!' - (A :: simple1_adt:d1(), - 'foo') contains an opaque term as 1st argument when terms of different types are expected in these positions simple2_api.erl:35:17: The call erlang:send (A :: simple1_adt:d1(), 'foo') contains an opaque term as 1st argument when terms of different types are expected in these positions -simple2_api.erl:51:5: The call erlang:'<' - (A :: simple1_adt:d1(), - 3) contains an opaque term as 1st argument when terms of different types are expected in these positions simple2_api.erl:59:24: The call lists:keysearch (1, A :: simple1_adt:d1(), - []) contains an opaque term as 2nd argument when terms of different types are expected in these positions + []) will never return since it differs in the 2nd argument from the success typing arguments: + (any(), + pos_integer(), + maybe_improper_list()) simple2_api.erl:67:29: The call lists:keysearch ('key', 1, - A :: simple1_adt:tuple1()) contains an opaque term as 3rd argument when terms of different types are expected in these positions + A :: simple1_adt:tuple1()) will never return since it differs in the 3rd argument from the success typing arguments: + (any(), + pos_integer(), + maybe_improper_list()) simple2_api.erl:96:37: The call lists:keyreplace ('a', 1, diff --git a/lib/dialyzer/test/indent_SUITE_data/src/rec/rec_adt.erl b/lib/dialyzer/test/indent_SUITE_data/src/rec/rec_adt.erl index f01cc5e51908..ff991a201a4b 100644 --- a/lib/dialyzer/test/indent_SUITE_data/src/rec/rec_adt.erl +++ b/lib/dialyzer/test/indent_SUITE_data/src/rec/rec_adt.erl @@ -1,6 +1,6 @@ -module(rec_adt). --export([new/0, get_a/1, get_b/1, set_a/2, set_b/2]). +-export([new/0, new/1, get_a/1, get_b/1, set_a/2, set_b/2]). -record(rec, {a :: atom(), b = 0 :: integer()}). @@ -9,6 +9,9 @@ -spec new() -> rec(). new() -> #rec{a = gazonk, b = 42}. +-spec new(integer()) -> rec(). +new(B) -> #rec{a = gazonk, b = B}. + -spec get_a(rec()) -> atom(). get_a(#rec{a = A}) -> A. diff --git a/lib/dialyzer/test/indent_SUITE_data/src/rec/rec_use.erl b/lib/dialyzer/test/indent_SUITE_data/src/rec/rec_use.erl index 358e9f918ca4..24597e85d4db 100644 --- a/lib/dialyzer/test/indent_SUITE_data/src/rec/rec_use.erl +++ b/lib/dialyzer/test/indent_SUITE_data/src/rec/rec_use.erl @@ -1,6 +1,6 @@ -module(rec_use). --export([ok1/0, ok2/0, wrong1/0, wrong2/0, wrong3/0, wrong4/0]). +-export([ok1/0, ok2/0, wrong1/0, wrong2/0, wrong3/0]). ok1() -> rec_adt:set_a(rec_adt:new(), foo). @@ -13,7 +13,7 @@ ok2() -> B1 =:= B2. wrong1() -> - case rec_adt:new() of + case rec_adt:new(42) of {rec, _, 42} -> weird1; R when tuple_size(R) =:= 3 -> weird2 end. @@ -25,6 +25,3 @@ wrong2() -> wrong3() -> R = rec_adt:new(), R =:= {rec, gazonk, 42}. - -wrong4() -> - tuple_size(rec_adt:new()). diff --git a/lib/dialyzer/test/map_SUITE_data/results/loop b/lib/dialyzer/test/map_SUITE_data/results/loop index aaa8a676e868..32df0cd49c77 100644 --- a/lib/dialyzer/test/map_SUITE_data/results/loop +++ b/lib/dialyzer/test/map_SUITE_data/results/loop @@ -1,4 +1,13 @@ loop.erl:63:27: The call loop:start_timer(#loop{state::'idle' | 'waiting',queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1':=10, 2:=10}}) does not have a term of type #loop{state::'idle' | 'waiting',timer::timer:tref(),queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1'=>non_neg_integer(), 2=>non_neg_integer()}} (with opaque subterms) as 1st argument +loop.erl:63:27: The call loop:start_timer(#loop{state::'idle' | 'waiting',queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1':=10, 2:=10}}) will never return since it differs in the 1st argument from the success typing arguments: (#loop{state::'idle' | 'waiting',timer::timer:tref(),queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1'=>non_neg_integer(), 2=>non_neg_integer()}}) +loop.erl:66:2: Invalid type specification for function loop:wait/1. + The success typing is loop:wait(_) -> none() + But the spec is loop:wait(#loop{}) -> {'noreply',#loop{}} + The return types do not overlap loop.erl:67:1: Function wait/1 has no local return +loop.erl:80:2: Invalid type specification for function loop:start_timer/1. + The success typing is loop:start_timer(#loop{state::'idle' | 'waiting',timer::timer:tref(),queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1'=>non_neg_integer(), 2=>non_neg_integer()}}) -> no_return() + But the spec is loop:start_timer(MV::#loop{}) -> #loop{} + The return types do not overlap loop.erl:85:24: Record construction #loop{state::'idle' | 'waiting',timer::{'error',_} | {'ok',timer:tref()},queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1'=>non_neg_integer(), 2=>non_neg_integer()}} violates the declared type of field timer::'undefined' | timer:tref() diff --git a/lib/dialyzer/test/map_SUITE_data/results/map_galore b/lib/dialyzer/test/map_SUITE_data/results/map_galore index 25cfe920d8c2..c13ddc97e395 100644 --- a/lib/dialyzer/test/map_SUITE_data/results/map_galore +++ b/lib/dialyzer/test/map_SUITE_data/results/map_galore @@ -24,5 +24,6 @@ map_galore.erl:2280:50: Cons will produce an improper list since its 2nd argumen map_galore.erl:2280:50: The call maps:from_list([{'a', 'b'} | {'b', 'a'}]) will never return since it differs in the 1st argument from the success typing arguments: ([{_,_}]) map_galore.erl:2281:50: The call maps:from_list('a') will never return since it differs in the 1st argument from the success typing arguments: ([{_,_}]) map_galore.erl:2282:50: The call maps:from_list(42) will never return since it differs in the 1st argument from the success typing arguments: ([{_,_}]) +map_galore.erl:982:12: The test #{1:='a', 2:='b', 4:='d', 5:='e', float()=>'c' | 'new'} =/= #{1:='a', 2:='b', 3:='right', 4:='d', 5:='e', float()=>'c' | 'new'} can never evaluate to 'false' map_galore.erl:997:55: A key of type 'nonexisting' cannot exist in a map of type #{} map_galore.erl:998:52: A key of type 'nonexisting' cannot exist in a map of type #{1:='a', 2:='b', 4:='d', 5:='e', float()=>'c'} diff --git a/lib/dialyzer/test/map_SUITE_data/results/opaque_key b/lib/dialyzer/test/map_SUITE_data/results/opaque_key index c3df7a5560fc..965404a4edb0 100644 --- a/lib/dialyzer/test/map_SUITE_data/results/opaque_key +++ b/lib/dialyzer/test/map_SUITE_data/results/opaque_key @@ -20,12 +20,10 @@ opaque_key_adt.erl:59:2: Invalid type specification for function opaque_key_adt: But the spec is opaque_key_adt:smt2() -> smt(1) The return types do not overlap opaque_key_use.erl:13:5: The test opaque_key_use:t() =:= opaque_key_use:t(_) can never evaluate to 'true' -opaque_key_use.erl:24:5: Attempt to test for equality between a term of type opaque_key_adt:t(_) and a term of opaque type opaque_key_adt:t() -opaque_key_use.erl:37:1: Function adt_mm1/0 has no local return +opaque_key_use.erl:24:5: The test opaque_key_adt:t() =:= opaque_key_adt:t(_) can never evaluate to 'true' opaque_key_use.erl:40:5: The attempt to match a term of type opaque_key_adt:m() against the pattern #{A:=R} breaks the opacity of the term -opaque_key_use.erl:48:1: Function adt_mu1/0 has no local return opaque_key_use.erl:51:5: Guard test is_map(M::opaque_key_adt:m()) breaks the opacity of its argument -opaque_key_use.erl:53:1: Function adt_mu2/0 has no local return +opaque_key_use.erl:51:5: The attempt to match the term against the variable M breaks the opacity of the term opaque_key_use.erl:56:5: Guard test is_map(M::opaque_key_adt:m()) breaks the opacity of its argument -opaque_key_use.erl:58:1: Function adt_mu3/0 has no local return +opaque_key_use.erl:56:5: The attempt to match the term against the variable M breaks the opacity of the term opaque_key_use.erl:60:5: Guard test is_map(M::opaque_key_adt:m()) breaks the opacity of its argument diff --git a/lib/dialyzer/test/nowarn_function_SUITE_data/results/warn_function b/lib/dialyzer/test/nowarn_function_SUITE_data/results/warn_function index da14df557648..b2ec5a368fbf 100644 --- a/lib/dialyzer/test/nowarn_function_SUITE_data/results/warn_function +++ b/lib/dialyzer/test/nowarn_function_SUITE_data/results/warn_function @@ -1,5 +1,9 @@ warn_function.erl:12:17: Guard test 1 =:= B::fun((none()) -> no_return()) can never succeed +warn_function.erl:16:2: Invalid type specification for function warn_function:b/1. + The success typing is warn_function:b(_) -> none() + But the spec is warn_function:b(_) -> integer() + The return types do not overlap warn_function.erl:18:1: Function b/1 has no local return warn_function.erl:22:5: Guard test 2 =:= A::fun((none()) -> no_return()) can never succeed warn_function.erl:26:1: Function c/0 has no local return diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/array b/lib/dialyzer/test/opaque_SUITE_data/results/array index d7f41014b212..08bf74c85399 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/array +++ b/lib/dialyzer/test/opaque_SUITE_data/results/array @@ -1,3 +1,3 @@ -array_use.erl:12:8: The type test is_tuple(array:array(_)) breaks the opacity of the term array:array(_) +array_use.erl:14:5: The pattern 'false' can never match the type 'true' array_use.erl:9:3: The attempt to match a term of type array:array(_) against the pattern {'array', _, _, 'undefined', _} breaks the opacity of the term diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/crash b/lib/dialyzer/test/opaque_SUITE_data/results/crash index 90279341d529..0be4282e8c04 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/crash +++ b/lib/dialyzer/test/opaque_SUITE_data/results/crash @@ -1,7 +1,11 @@ +crash_1.erl:42:2: Invalid type specification for function crash_1:empty/0. + The success typing is crash_1:empty() -> none() + But the spec is crash_1:empty() -> targetlist() + The return types do not overlap crash_1.erl:45:24: Record construction #targetlist{list::[]} violates the declared type of field list::crash_1:target() crash_1.erl:48:31: The call crash_1:get_using_branch2(Branch::maybe_improper_list(),L::crash_1:target()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),maybe_improper_list()) crash_1.erl:50:1: The pattern <_Branch, []> can never match the type crash_1.erl:52:1: The pattern can never match the type crash_1.erl:54:1: The pattern can never match the type -crash_2.erl:4:2: The specification for crash_2:crash/0 has an opaque subtype queue:queue(_) which is violated by the success typing () -> {tuple(),queue:queue(_)} +crash_2.erl:4:2: The specification for crash_2:crash/0 has an opaque subtype {tuple(),integer()} which is violated by the success typing () -> {tuple(),queue:queue(_)} diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/dict b/lib/dialyzer/test/opaque_SUITE_data/results/dict index 461b30d3767c..3ba316f95fa7 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/dict +++ b/lib/dialyzer/test/opaque_SUITE_data/results/dict @@ -1,15 +1,18 @@ -dict_use.erl:41:3: The attempt to match a term of type dict:dict(_,_) against the pattern 'gazonk' breaks the opacity of the term -dict_use.erl:45:5: The attempt to match a term of type dict:dict(_,_) against the pattern [] breaks the opacity of the term -dict_use.erl:46:5: The attempt to match a term of type dict:dict(_,_) against the pattern 42 breaks the opacity of the term -dict_use.erl:51:5: The attempt to match a term of type dict:dict(_,_) against the pattern [] breaks the opacity of the term -dict_use.erl:52:5: The attempt to match a term of type dict:dict(_,_) against the pattern 42 breaks the opacity of the term +dict_use.erl:41:3: The pattern 'gazonk' can never match the type dict:dict(_,_) +dict_use.erl:45:5: The pattern [] can never match the type dict:dict(_,_) +dict_use.erl:46:5: The pattern 42 can never match the type dict:dict(_,_) +dict_use.erl:51:5: The pattern [] can never match the type dict:dict(_,_) +dict_use.erl:52:5: The pattern 42 can never match the type dict:dict(_,_) dict_use.erl:58:3: Attempt to test for equality between a term of type maybe_improper_list() and a term of opaque type dict:dict(_,_) +dict_use.erl:58:3: The test maybe_improper_list() =:= dict:dict(_,_) can never evaluate to 'true' dict_use.erl:60:3: Attempt to test for inequality between a term of type atom() and a term of opaque type dict:dict(_,_) -dict_use.erl:64:19: Guard test length(D::dict:dict(_,_)) breaks the opacity of its argument -dict_use.erl:65:20: Guard test is_atom(D::dict:dict(_,_)) breaks the opacity of its argument -dict_use.erl:66:20: Guard test is_list(D::dict:dict(_,_)) breaks the opacity of its argument -dict_use.erl:70:3: The type test is_list(dict:dict(_,_)) breaks the opacity of the term dict:dict(_,_) +dict_use.erl:60:3: The test atom() =/= dict:dict(_,_) can never evaluate to 'false' +dict_use.erl:64:12: Guard test length(D::dict:dict(_,_)) can never succeed +dict_use.erl:65:12: Guard test is_atom(D::dict:dict(_,_)) can never succeed +dict_use.erl:66:12: Guard test is_list(D::dict:dict(_,_)) can never succeed dict_use.erl:73:19: The call dict:fetch('foo',[1, 2, 3]) does not have an opaque term of type dict:dict(_,_) as 2nd argument +dict_use.erl:73:19: The call dict:fetch('foo',[1, 2, 3]) will never return since the success typing is (any(),{'dict',non_neg_integer(),non_neg_integer(),pos_integer(),non_neg_integer(),non_neg_integer(),non_neg_integer(),tuple(),tuple()}) -> any() and the contract is (Key,Dict) -> Value when Dict :: dict(Key,Value) dict_use.erl:76:19: The call dict:merge(Fun::any(),42,[1, 2]) does not have opaque terms as 2nd and 3rd arguments +dict_use.erl:76:19: The call dict:merge(Fun::any(),42,[1, 2]) will never return since the success typing is (any(),any(),{'dict',non_neg_integer(),non_neg_integer(),non_neg_integer(),non_neg_integer(),non_neg_integer(),non_neg_integer(),tuple(),tuple()}) -> any() and the contract is (Fun,Dict1,Dict2) -> Dict3 when Fun :: fun((Key,Value1,Value2) -> Value), Dict1 :: dict(Key,Value1), Dict2 :: dict(Key,Value2), Dict3 :: dict(Key,Value) dict_use.erl:80:7: The call dict:store(42,'elli',{'dict', 0, 16, 16, 8, 80, 48, {[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []}, {{[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []}}}) does not have an opaque term of type dict:dict(_,_) as 3rd argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/ets b/lib/dialyzer/test/opaque_SUITE_data/results/ets index aba95ca9f4f2..f6011e7b63e2 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/ets +++ b/lib/dialyzer/test/opaque_SUITE_data/results/ets @@ -1,4 +1,3 @@ -ets_use.erl:12:20: Guard test is_integer(T::atom() | ets:tid()) breaks the opacity of its argument -ets_use.erl:20:5: The type test is_integer(atom() | ets:tid()) breaks the opacity of the term atom() | ets:tid() -ets_use.erl:7:20: Guard test is_integer(T::ets:tid()) breaks the opacity of its argument +ets_use.erl:12:9: Guard test is_integer(T::atom() | ets:tid()) can never succeed +ets_use.erl:7:9: Guard test is_integer(T::ets:tid()) can never succeed diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 index 26dfbb6923c5..f1ec461f17ce 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 +++ b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 @@ -2,4 +2,4 @@ inf_loop1.erl:119:1: The pattern [{_, LNorms}] can never match the type [] inf_loop1.erl:121:1: The pattern [{LinksA, LNormA}, {LinksB, LNormB}] can never match the type [] inf_loop1.erl:129:15: The pattern [{_, Norm} | _] can never match the type [] -inf_loop1.erl:71:74: The call gb_trees:get(Edge::any(),Etab::array:array(_)) does not have an opaque term of type gb_trees:tree(_,_) as 2nd argument +inf_loop1.erl:71:74: The call gb_trees:get(Edge::any(),Etab::array:array(_)) will never return since the success typing is (any(),{_,{_,_,_,_}}) -> any() and the contract is (Key,Tree) -> Value when Tree :: tree(Key,Value) diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop2 b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop2 index 7b35563d4344..62948906e5ae 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop2 +++ b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop2 @@ -2,4 +2,4 @@ inf_loop2.erl:122:1: The pattern [{_, LNorms}] can never match the type [] inf_loop2.erl:124:1: The pattern [{LinksA, LNormA}, {LinksB, LNormB}] can never match the type [] inf_loop2.erl:132:15: The pattern [{_, Norm} | _] can never match the type [] -inf_loop2.erl:74:74: The call gb_trees:get(Edge::any(),Etab::array:array(_)) does not have an opaque term of type gb_trees:tree(_,_) as 2nd argument +inf_loop2.erl:74:74: The call gb_trees:get(Edge::any(),Etab::array:array(_)) will never return since the success typing is (any(),{_,{_,_,_,_}}) -> any() and the contract is (Key,Tree) -> Value when Tree :: tree(Key,Value) diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/int b/lib/dialyzer/test/opaque_SUITE_data/results/int index 504013883fa9..f4204b17f7be 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/int +++ b/lib/dialyzer/test/opaque_SUITE_data/results/int @@ -1,9 +1,9 @@ int_adt.erl:28:2: Invalid type specification for function int_adt:add_f/2. - The success typing is int_adt:add_f(number() | int_adt:int(),float()) -> number() | int_adt:int() + The success typing is int_adt:add_f(number(),float()) -> number() But the spec is int_adt:add_f(int(),int()) -> int() They do not overlap in the 2nd argument int_adt.erl:32:2: Invalid type specification for function int_adt:div_f/2. - The success typing is int_adt:div_f(number() | int_adt:int(),number() | int_adt:int()) -> float() + The success typing is int_adt:div_f(number(),number()) -> float() But the spec is int_adt:div_f(int(),int()) -> int() The return types do not overlap diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/mixed_opaque b/lib/dialyzer/test/opaque_SUITE_data/results/mixed_opaque index 77f45b1f2009..d708349c545c 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/mixed_opaque +++ b/lib/dialyzer/test/opaque_SUITE_data/results/mixed_opaque @@ -1,2 +1,4 @@ -mixed_opaque_use.erl:31:16: The call mixed_opaque_rec_adt:get_a(Q::mixed_opaque_queue_adt:my_queue()) does not have an opaque term of type mixed_opaque_rec_adt:rec() as 1st argument +mixed_opaque_use.erl:15:2: Body yields the opaque type mixed_opaque_queue_adt:my_queue() whose opacity is broken by the other clauses. +mixed_opaque_use.erl:16:2: Body yields the opaque type mixed_opaque_rec_adt:rec() whose opacity is broken by the other clauses. +mixed_opaque_use.erl:31:16: The call mixed_opaque_rec_adt:get_a(Q::mixed_opaque_queue_adt:my_queue()) will never return since the success typing is ({'rec',atom(),integer()}) -> atom() and the contract is (rec()) -> atom() diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/my_queue b/lib/dialyzer/test/opaque_SUITE_data/results/my_queue index 8364d8e9a502..6b2ed03e7d47 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/my_queue +++ b/lib/dialyzer/test/opaque_SUITE_data/results/my_queue @@ -3,5 +3,5 @@ my_queue_use.erl:15:27: The call my_queue_adt:is_empty([]) does not have an opaq my_queue_use.erl:19:26: The call my_queue_adt:add(42,Q0::[]) does not have an opaque term of type my_queue_adt:my_queue() as 2nd argument my_queue_use.erl:24:5: The attempt to match a term of type my_queue_adt:my_queue() against the pattern [42 | Q2] breaks the opacity of the term my_queue_use.erl:30:5: Attempt to test for equality between a term of type [] and a term of opaque type my_queue_adt:my_queue() -my_queue_use.erl:34:37: Cons will produce an improper list since its 2nd argument is my_queue_adt:my_queue() -my_queue_use.erl:34:37: The call my_queue_adt:dequeue(nonempty_maybe_improper_list(42,my_queue_adt:my_queue())) does not have an opaque term of type my_queue_adt:my_queue() as 1st argument +my_queue_use.erl:30:5: The test my_queue_adt:my_queue() =:= [] can never evaluate to 'true' +my_queue_use.erl:34:37: The call my_queue_adt:dequeue(nonempty_improper_list(42,my_queue_adt:my_queue())) does not have an opaque term of type my_queue_adt:my_queue() as 1st argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/opaque b/lib/dialyzer/test/opaque_SUITE_data/results/opaque index cc793a71c7e0..626a528047c0 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/opaque +++ b/lib/dialyzer/test/opaque_SUITE_data/results/opaque @@ -1,3 +1,3 @@ opaque_bug3.erl:19:1: The pattern 'a' can never match the type #c{} -opaque_bug4.erl:20:1: The attempt to match a term of type opaque_adt:abc() against the pattern 'a' breaks the opacity of the term +opaque_bug4.erl:20:5: The attempt to match a term of type opaque_adt:abc() against the pattern 'a' breaks the opacity of the term diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/para b/lib/dialyzer/test/opaque_SUITE_data/results/para index 77106c6afa6a..222813df68fa 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/para +++ b/lib/dialyzer/test/opaque_SUITE_data/results/para @@ -3,13 +3,15 @@ para1.erl:18:5: The test para1:t(_) =:= para1:t(_) can never evaluate to 'true' para1.erl:23:5: The test para1:t(_) =:= para1:t() can never evaluate to 'true' para1.erl:28:5: The test para1:t() =:= para1:t(_) can never evaluate to 'true' para1.erl:33:5: The test {3,2} =:= {'a','b'} can never evaluate to 'true' +para1.erl:38:5: Attempt to test for equality between a term of type para1_adt:t(_) and a term of opaque type para1_adt:t(_) para1.erl:38:5: The test para1_adt:t(_) =:= para1_adt:t(_) can never evaluate to 'true' -para1.erl:43:5: Attempt to test for equality between a term of type para1_adt:t() and a term of opaque type para1_adt:t(_) -para1.erl:48:5: Attempt to test for equality between a term of type para1_adt:t(_) and a term of opaque type para1_adt:t() +para1.erl:43:5: The test para1_adt:t(_) =:= para1_adt:t() can never evaluate to 'true' +para1.erl:48:5: The test para1_adt:t() =:= para1_adt:t(_) can never evaluate to 'true' para1.erl:53:5: The test {3,2} =:= {'a','b'} can never evaluate to 'true' -para2.erl:103:5: Attempt to test for equality between a term of type para2_adt:circ(_,_) and a term of opaque type para2_adt:circ(_) +para2.erl:103:5: The test para2_adt:circ(_) =:= para2_adt:circ(_,_) can never evaluate to 'true' +para2.erl:26:5: The test para2:c1() =:= para2:c2() can never evaluate to 'true' para2.erl:31:5: The test 'a' =:= 'b' can never evaluate to 'true' -para2.erl:61:5: Attempt to test for equality between a term of type para2_adt:c2() and a term of opaque type para2_adt:c1() +para2.erl:61:5: The test para2_adt:c1() =:= para2_adt:c2() can never evaluate to 'true' para2.erl:66:5: The test 'a' =:= 'b' can never evaluate to 'true' para2.erl:88:5: The test para2:circ(_) =:= para2:circ(_,_) can never evaluate to 'true' para3.erl:28:2: Invalid type specification for function para3:ot2/0. @@ -21,13 +23,23 @@ para3.erl:55:2: Invalid type specification for function para3:t2/0. The success typing is para3:t2() -> 'foo' But the spec is para3:t2() -> t1() The return types do not overlap -para3.erl:65:5: The attempt to match a term of type {{{{{para3_adt:ot1(_,_,_,_,_)}}}}} against the pattern {{{{{17}}}}} breaks the opacity of para3_adt:ot1(_,_,_,_,_) +para3.erl:65:5: The pattern {{{{{17}}}}} can never match the type {{{{{para3_adt:ot1(_,_,_,_,_)}}}}} para3.erl:68:5: The pattern {{{{17}}}} can never match the type {{{{{para3_adt:ot1(_,_,_,_,_)}}}}} para3.erl:74:2: The specification for para3:exp_adt/0 has an opaque subtype para3_adt:exp1(_) which is violated by the success typing () -> 3 +para4.erl:21:2: Invalid type specification for function para4:a/1. + The success typing is para4:a(para4:d_all()) -> [{atom() | integer(),atom() | integer()}] + But the spec is para4:a(d_atom()) -> [{atom(),atom()}] + They do not overlap in the 1st argument +para4.erl:26:2: Invalid type specification for function para4:i/1. + The success typing is para4:i(para4:d_all()) -> [{atom() | integer(),atom() | integer()}] + But the spec is para4:i(d_integer()) -> [{integer(),integer()}] + They do not overlap in the 1st argument para4.erl:31:2: Invalid type specification for function para4:t/1. - The success typing is para4:t(para4:d_all() | para4:d_tuple()) -> [{atom() | integer(),atom() | integer()}] + The success typing is para4:t(para4:d_all()) -> [{atom() | integer(),atom() | integer()}] But the spec is para4:t(d_tuple()) -> [{tuple(),tuple()}] - The return types do not overlap + They do not overlap in the 1st argument +para4.erl:79:5: Attempt to test for equality between a term of type para4_adt:int(_) and a term of opaque type para4_adt:int(_) para4.erl:79:5: The test para4_adt:int(_) =:= para4_adt:int(_) can never evaluate to 'true' -para5.erl:13:5: Attempt to test for inequality between a term of type para5_adt:dd(_) and a term of opaque type para5_adt:d() +para5.erl:13:5: The test para5_adt:d() =/= para5_adt:dd(_) can never evaluate to 'false' +para5.erl:8:5: Attempt to test for equality between a term of type para5_adt:d() and a term of opaque type para5_adt:d() para5.erl:8:5: The test para5_adt:d() =:= para5_adt:d() can never evaluate to 'true' diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/queue b/lib/dialyzer/test/opaque_SUITE_data/results/queue index b66ffcb648ce..81477c9852c0 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/queue +++ b/lib/dialyzer/test/opaque_SUITE_data/results/queue @@ -5,7 +5,9 @@ queue_use.erl:27:5: The attempt to match a term of type queue:queue(_) against t queue_use.erl:33:5: Attempt to test for equality between a term of type {[42,...],[]} and a term of opaque type queue:queue(_) queue_use.erl:36:5: The attempt to match a term of type queue:queue(_) against the pattern {F, _R} breaks the opacity of the term queue_use.erl:40:35: The call queue:out({"*", []}) does not have an opaque term of type queue:queue(_) as 1st argument -queue_use.erl:51:25: The call queue_use:is_in_queue(E::42,DB::#db{p::[],q::queue:queue(_)}) contains an opaque term as 2nd argument when terms of different types are expected in these positions -queue_use.erl:56:1: The attempt to match a term of type #db{p::[],q::queue:queue(_)} against the pattern {'db', _, {L1, L2}} breaks the opacity of queue:queue(_) +queue_use.erl:52:2: The pattern 'true' can never match the type 'false' +queue_use.erl:56:24: The attempt to match a term of type queue:queue(_) against the pattern {L1, L2} breaks the opacity of the term queue_use.erl:62:17: The call queue_use:tuple_queue({42, 'gazonk'}) does not have a term of type {_,queue:queue(_)} (with opaque subterms) as 1st argument +queue_use.erl:62:17: The call queue_use:tuple_queue({42, 'gazonk'}) will never return since it differs in the 1st argument from the success typing arguments: ({_,queue:queue(_)}) queue_use.erl:65:17: The call queue:in(F::42,Q::'gazonk') does not have an opaque term of type queue:queue(_) as 2nd argument +queue_use.erl:65:17: The call queue:in(F::42,Q::'gazonk') will never return since the success typing is (any(),{maybe_improper_list(),maybe_improper_list()}) -> {nonempty_maybe_improper_list(),maybe_improper_list()} and the contract is (Item,Q1::queue(Item)) -> Q2::queue(Item) diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/rec b/lib/dialyzer/test/opaque_SUITE_data/results/rec index 60943ea0ce16..220905aa5e65 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/rec +++ b/lib/dialyzer/test/opaque_SUITE_data/results/rec @@ -1,6 +1,5 @@ rec_use.erl:17:2: The attempt to match a term of type rec_adt:rec() against the pattern {'rec', _, 42} breaks the opacity of the term -rec_use.erl:18:20: Guard test tuple_size(R::rec_adt:rec()) breaks the opacity of its argument +rec_use.erl:18:9: Guard test tuple_size(R::rec_adt:rec()) breaks the opacity of its argument rec_use.erl:23:19: The call rec_adt:get_a(R::tuple()) does not have an opaque term of type rec_adt:rec() as 1st argument rec_use.erl:27:5: Attempt to test for equality between a term of type {'rec','gazonk',42} and a term of opaque type rec_adt:rec() -rec_use.erl:30:16: The call erlang:tuple_size(rec_adt:rec()) contains an opaque term as 1st argument when a structured term of type tuple() is expected diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/recrec b/lib/dialyzer/test/opaque_SUITE_data/results/recrec new file mode 100644 index 000000000000..6889fbc2ccae --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/results/recrec @@ -0,0 +1,31 @@ + +dialyzer_races.erl:1571:5: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:1572:5: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:1973:17: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:1974:17: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2000:17: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2002:21: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2006:25: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2010:25: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2015:21: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2018:21: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2021:21: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2023:17: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2025:21: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2028:21: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2031:21: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2034:21: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2036:17: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2038:21: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2043:21: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2046:21: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2049:21: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2051:17: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2060:17: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2069:17: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2173:5: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2174:5: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2176:9: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. +dialyzer_races.erl:2177:9: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2179:13: Body yields the type 'undefined' | dict:dict(_,_) which violates the opacity of the other clauses. +dialyzer_races.erl:2183:13: Body yields the opaque type dict:dict(_,_) whose opacity is broken by the other clauses. diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/simple b/lib/dialyzer/test/opaque_SUITE_data/results/simple index 4c211a442566..5d62ce628e4d 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/simple +++ b/lib/dialyzer/test/opaque_SUITE_data/results/simple @@ -3,102 +3,82 @@ exact_api.erl:17:14: The call exact_api:set_type(A::#digraph{vtab::'notable',eta exact_api.erl:23:20: The call digraph:delete(G::#digraph{vtab::'notable',etab::'notable',ntab::'notable',cyclic::'true'}) does not have an opaque term of type digraph:graph() as 1st argument exact_api.erl:55:5: The attempt to match a term of type exact_adt:exact_adt() against the pattern {'exact_adt'} breaks the opacity of the term exact_api.erl:59:39: The call exact_adt:exact_adt_set_type2(A::#exact_adt{}) does not have an opaque term of type exact_adt:exact_adt() as 1st argument -is_rec.erl:10:5: The call erlang:is_record(simple1_adt:d1(),'r',2) contains an opaque term as 1st argument when terms of different types are expected in these positions -is_rec.erl:15:15: The call erlang:is_record(A::simple1_adt:d1(),'r',I::1 | 2 | 3) contains an opaque term as 1st argument when terms of different types are expected in these positions -is_rec.erl:19:18: Guard test is_record(A::simple1_adt:d1(),'r',2) breaks the opacity of its argument -is_rec.erl:23:18: Guard test is_record({simple1_adt:d1(),1},'r',2) breaks the opacity of its argument -is_rec.erl:41:15: The call erlang:is_record(A::simple1_adt:d1(),R::'a') contains an opaque term as 1st argument when terms of different types are expected in these positions -is_rec.erl:45:18: The call erlang:is_record(A::simple1_adt:d1(),A::simple1_adt:d1(),1) contains an opaque term as 2nd argument when terms of different types are expected in these positions -is_rec.erl:49:15: The call erlang:is_record(A::simple1_adt:d1(),any(),1) contains an opaque term as 1st argument when terms of different types are expected in these positions -is_rec.erl:53:18: The call erlang:is_record(A::simple1_adt:d1(),A::simple1_adt:d1(),any()) contains an opaque term as 2nd argument when terms of different types are expected in these positions -is_rec.erl:57:18: Guard test is_record(A::simple1_adt:d1(),'r',2) breaks the opacity of its argument +is_rec.erl:19:8: Guard test is_record(A::simple1_adt:d1(),'r',2) can never succeed +is_rec.erl:23:8: Guard test is_record({simple1_adt:d1(),1},'r',2) can never succeed +is_rec.erl:57:8: Guard test is_record(A::simple1_adt:d1(),'r',2) can never succeed is_rec.erl:61:8: The record #r{f1::simple1_adt:d1()} violates the declared type for #r{} -is_rec.erl:65:5: The call erlang:is_record({simple1_adt:d1(),1},'r',2) contains an opaque term as 1st argument when terms of different types are expected in these positions rec_api.erl:104:5: Matching of pattern {'r2', 10} tagged with a record name violates the declared type of #r2{f1::10} -rec_api.erl:113:5: The attempt to match a term of type #r3{f1::queue:queue(_)} against the pattern {'r3', 'a'} breaks the opacity of queue:queue(_) +rec_api.erl:113:5: The pattern {'r3', 'a'} can never match the type #r3{f1::queue:queue(_)} rec_api.erl:118:18: Record construction #r3{f1::10} violates the declared type of field f1::queue:queue(_) -rec_api.erl:123:5: The attempt to match a term of type #r3{f1::10} against the pattern {'r3', 10} breaks the opacity of queue:queue(_) +rec_api.erl:123:5: Matching of pattern {'r3', 10} tagged with a record name violates the declared type of #r3{f1::10} rec_api.erl:24:18: Record construction #r1{f1::10} violates the declared type of field f1::rec_api:a() rec_api.erl:29:5: Matching of pattern {'r1', 10} tagged with a record name violates the declared type of #r1{f1::10} +rec_api.erl:33:10: The attempt to match a term of type rec_adt:a() against the pattern 'a' breaks the opacity of the term rec_api.erl:33:5: The attempt to match a term of type rec_adt:r1() against the pattern {'r1', 'a'} breaks the opacity of the term -rec_api.erl:35:2: Invalid type specification for function rec_api:adt_t1/1. - The success typing is rec_api:adt_t1(#r1{f1::'a'}) -> #r1{f1::'a'} - But the spec is rec_api:adt_t1(rec_adt:r1()) -> rec_adt:r1() - They do not overlap in the 1st argument, and the return types do not overlap -rec_api.erl:40:2: The specification for rec_api:adt_r1/0 has an opaque subtype rec_adt:r1() which is violated by the success typing () -> #r1{f1::'a'} -rec_api.erl:85:13: The attempt to match a term of type rec_adt:f() against the record field 'f' declared to be of type rec_api:f() breaks the opacity of the term +rec_api.erl:35:2: The specification for rec_api:adt_t1/1 has an opaque subtype rec_adt:r1() which is violated by the success typing (#r1{f1::'a'}) -> #r1{f1::'a'} +rec_api.erl:40:2: The specification for rec_api:adt_r1/0 has an opaque subtype rec_adt:r1() which is violated by the success typing () -> #r1{f1::rec_api:a()} +rec_api.erl:85:13: Record construction #r{f::rec_adt:f(),o::2} violates the declared type of field f::rec_api:f() rec_api.erl:99:18: Record construction #r2{f1::10} violates the declared type of field f1::rec_api:a() +simple1_api.erl:102:5: Guard test simple1_api:o2() =:= A::simple1_api:o1() can never succeed +simple1_api.erl:108:5: The test simple1_api:o1() =:= simple1_api:o2() can never evaluate to 'true' simple1_api.erl:113:5: The test simple1_api:d1() =:= simple1_api:d2() can never evaluate to 'true' simple1_api.erl:118:5: Guard test simple1_api:d2() =:= A::simple1_api:d1() can never succeed -simple1_api.erl:142:5: Attempt to test for equality between a term of type simple1_adt:o2() and a term of opaque type simple1_adt:o1() -simple1_api.erl:148:5: Guard test simple1_adt:o2() =:= A::simple1_adt:o1() contains opaque terms as 1st and 2nd arguments -simple1_api.erl:154:5: Attempt to test for inequality between a term of type simple1_adt:o2() and a term of opaque type simple1_adt:o1() -simple1_api.erl:160:5: Attempt to test for inequality between a term of type simple1_adt:o2() and a term of opaque type simple1_adt:o1() -simple1_api.erl:165:5: Attempt to test for equality between a term of type simple1_adt:c2() and a term of opaque type simple1_adt:c1() +simple1_api.erl:123:5: The test simple1_api:d1() =/= simple1_api:d2() can never evaluate to 'false' +simple1_api.erl:128:5: The test simple1_api:d1() /= simple1_api:d2() can never evaluate to 'false' +simple1_api.erl:142:5: The test simple1_adt:o1() =:= simple1_adt:o2() can never evaluate to 'true' +simple1_api.erl:148:5: Guard test simple1_adt:o2() =:= A::simple1_adt:o1() can never succeed +simple1_api.erl:154:5: The test simple1_adt:o1() =/= simple1_adt:o2() can never evaluate to 'false' +simple1_api.erl:160:5: The test simple1_adt:o1() /= simple1_adt:o2() can never evaluate to 'false' +simple1_api.erl:165:5: The test simple1_adt:c1() =:= simple1_adt:c2() can never evaluate to 'true' simple1_api.erl:181:8: Guard test A::simple1_adt:d1() =< B::simple1_adt:d2() contains opaque terms as 1st and 2nd arguments -simple1_api.erl:185:13: Guard test 'a' =< B::simple1_adt:d2() contains an opaque term as 2nd argument +simple1_api.erl:185:8: Guard test 'a' =< B::simple1_adt:d2() contains an opaque term as 2nd argument simple1_api.erl:189:8: Guard test A::simple1_adt:d1() =< 'd' contains an opaque term as 1st argument -simple1_api.erl:197:5: The type test is_integer(A::simple1_adt:d1()) breaks the opacity of the term A::simple1_adt:d1() simple1_api.erl:221:8: Guard test A::simple1_api:i1() > 3 can never succeed -simple1_api.erl:225:8: Guard test A::simple1_adt:i1() > 3 contains an opaque term as 1st argument +simple1_api.erl:225:8: Guard test A::simple1_adt:i1() > 3 can never succeed simple1_api.erl:233:8: Guard test A::simple1_adt:i1() < 3 contains an opaque term as 1st argument simple1_api.erl:239:8: Guard test A::1 > 3 can never succeed simple1_api.erl:243:8: Guard test A::1 > 3 can never succeed simple1_api.erl:257:8: Guard test is_function(T::simple1_api:o1()) can never succeed -simple1_api.erl:265:20: Guard test is_function(T::simple1_adt:o1()) breaks the opacity of its argument -simple1_api.erl:269:5: The type test is_function(T::simple1_adt:o1()) breaks the opacity of the term T::simple1_adt:o1() +simple1_api.erl:265:8: Guard test is_function(T::simple1_adt:o1()) can never succeed simple1_api.erl:274:8: Guard test is_function(T::simple1_api:o1(),A::simple1_api:i1()) can never succeed -simple1_api.erl:284:20: Guard test is_function(T::simple1_adt:o1(),A::simple1_adt:i1()) breaks the opacity of its argument -simple1_api.erl:289:5: The type test is_function(T::simple1_adt:o1(),A::simple1_adt:i1()) breaks the opacity of the term T::simple1_adt:o1() -simple1_api.erl:294:20: The call erlang:is_function(T::simple1_api:o1(),A::simple1_adt:i1()) contains an opaque term as 2nd argument when terms of different types are expected in these positions -simple1_api.erl:300:5: The type test is_function(T::simple1_adt:o1(),A::simple1_api:i1()) breaks the opacity of the term T::simple1_adt:o1() +simple1_api.erl:284:8: Guard test is_function(T::simple1_adt:o1(),A::simple1_adt:i1()) can never succeed simple1_api.erl:306:8: Guard test B::simple1_api:b2() =:= 'true' can never succeed simple1_api.erl:315:8: Guard test A::simple1_api:b1() =:= 'false' can never succeed simple1_api.erl:319:16: Guard test not(and('true','true')) can never succeed +simple1_api.erl:333:2: Invalid type specification for function simple1_api:bool_t7/0. + The success typing is simple1_api:bool_t7() -> none() + But the spec is simple1_api:bool_t7() -> integer() + The return types do not overlap simple1_api.erl:337:8: Clause guard cannot succeed. -simple1_api.erl:342:8: Guard test B::simple1_adt:b2() =:= 'true' contains an opaque term as 1st argument -simple1_api.erl:347:8: Guard test A::simple1_adt:b1() =:= 'true' contains an opaque term as 1st argument -simple1_api.erl:355:2: Invalid type specification for function simple1_api:bool_adt_t6/1. - The success typing is simple1_api:bool_adt_t6('true') -> 1 - But the spec is simple1_api:bool_adt_t6(simple1_adt:b1()) -> integer() - They do not overlap in the 1st argument +simple1_api.erl:342:8: Guard test B::simple1_adt:b2() =:= 'true' can never succeed +simple1_api.erl:361:2: Invalid type specification for function simple1_api:bool_t8/0. + The success typing is simple1_api:bool_t8() -> none() + But the spec is simple1_api:bool_t8() -> integer() + The return types do not overlap simple1_api.erl:365:8: Clause guard cannot succeed. -simple1_api.erl:368:2: Invalid type specification for function simple1_api:bool_adt_t8/2. - The success typing is simple1_api:bool_adt_t8(boolean(),boolean()) -> 1 - But the spec is simple1_api:bool_adt_t8(simple1_adt:b1(),simple1_adt:b2()) -> integer() - They do not overlap in the 1st and 2nd arguments +simple1_api.erl:374:2: Invalid type specification for function simple1_api:bool_t9/0. + The success typing is simple1_api:bool_t9() -> none() + But the spec is simple1_api:bool_t9() -> integer() + The return types do not overlap simple1_api.erl:378:8: Clause guard cannot succeed. -simple1_api.erl:381:2: Invalid type specification for function simple1_api:bool_adt_t9/2. - The success typing is simple1_api:bool_adt_t9('false','false') -> 1 - But the spec is simple1_api:bool_adt_t9(simple1_adt:b1(),simple1_adt:b2()) -> integer() - They do not overlap in the 1st and 2nd arguments simple1_api.erl:407:12: The size simple1_adt:i1() breaks the opacity of A -simple1_api.erl:418:9: The attempt to match a term of type non_neg_integer() against the variable A breaks the opacity of simple1_adt:i1() -simple1_api.erl:425:9: The attempt to match a term of type non_neg_integer() against the variable B breaks the opacity of simple1_adt:i1() simple1_api.erl:432:9: The pattern <<_:B>> can never match the type any() -simple1_api.erl:448:9: The attempt to match a term of type non_neg_integer() against the variable Sz breaks the opacity of simple1_adt:i1() simple1_api.erl:460:9: The attempt to match a term of type simple1_adt:bit1() against the pattern <<_/binary>> breaks the opacity of the term -simple1_api.erl:478:9: The call 'foo':A(A::simple1_adt:a()) breaks the opacity of the term A :: simple1_adt:a() -simple1_api.erl:486:5: The call A:'foo'(A::simple1_adt:a()) breaks the opacity of the term A :: simple1_adt:a() simple1_api.erl:499:9: The call 'foo':A(A::simple1_api:i()) requires that A is of type atom() not simple1_api:i() simple1_api.erl:503:9: The call 'foo':A(A::simple1_adt:i()) requires that A is of type atom() not simple1_adt:i() simple1_api.erl:507:5: The call A:'foo'(A::simple1_api:i()) requires that A is of type atom() not simple1_api:i() simple1_api.erl:511:5: The call A:'foo'(A::simple1_adt:i()) requires that A is of type atom() not simple1_adt:i() -simple1_api.erl:519:9: Guard test A::simple1_adt:d2() == B::simple1_adt:d1() contains opaque terms as 1st and 2nd arguments +simple1_api.erl:519:9: Guard test A::simple1_adt:d2() == B::simple1_adt:d1() can never succeed +simple1_api.erl:521:9: Guard test A::simple1_adt:d2() == A::simple1_adt:d2() contains opaque terms as 1st and 2nd arguments simple1_api.erl:534:9: Guard test A::simple1_adt:d1() >= 3 contains an opaque term as 1st argument -simple1_api.erl:536:9: Guard test A::simple1_adt:d1() == 3 contains an opaque term as 1st argument -simple1_api.erl:538:9: Guard test A::simple1_adt:d1() =:= 3 contains an opaque term as 1st argument -simple1_api.erl:548:5: The call erlang:'<'(A::simple1_adt:d1(),3) contains an opaque term as 1st argument when terms of different types are expected in these positions -simple1_api.erl:558:5: The call erlang:'=<'(A::simple1_adt:d1(),B::simple1_adt:d2()) contains opaque terms as 1st and 2nd arguments when terms of different types are expected in these positions -simple1_api.erl:565:17: Guard test {digraph:graph(),3} > {digraph:graph(),atom() | ets:tid()} contains an opaque term as 2nd argument +simple1_api.erl:536:9: Guard test A::simple1_adt:d1() == 3 can never succeed +simple1_api.erl:538:9: Guard test A::simple1_adt:d1() =:= 3 can never succeed +simple1_api.erl:540:9: Guard test A::simple1_adt:d1() == A::simple1_adt:d1() contains opaque terms as 1st and 2nd arguments simple1_api.erl:91:2: The specification for simple1_api:tup/0 has an opaque subtype simple1_adt:tuple1() which is violated by the success typing () -> {'a','b'} simple2_api.erl:100:19: The call lists:flatten(A::simple1_adt:tuple1()) contains an opaque term as 1st argument when a structured term of type [any()] is expected +simple2_api.erl:100:19: The call lists:flatten(A::simple1_adt:tuple1()) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) simple2_api.erl:116:19: The call lists:flatten({simple1_adt:tuple1()}) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) -simple2_api.erl:121:16: Guard test {simple1_adt:d1(),3} > {simple1_adt:d1(),simple1_adt:tuple1()} contains an opaque term as 2nd argument -simple2_api.erl:125:19: The call erlang:tuple_to_list(B::simple1_adt:tuple1()) contains an opaque term as 1st argument when a structured term of type tuple() is expected -simple2_api.erl:31:5: The call erlang:'!'(A::simple1_adt:d1(),'foo') contains an opaque term as 1st argument when terms of different types are expected in these positions simple2_api.erl:35:17: The call erlang:send(A::simple1_adt:d1(),'foo') contains an opaque term as 1st argument when terms of different types are expected in these positions -simple2_api.erl:51:5: The call erlang:'<'(A::simple1_adt:d1(),3) contains an opaque term as 1st argument when terms of different types are expected in these positions -simple2_api.erl:59:24: The call lists:keysearch(1,A::simple1_adt:d1(),[]) contains an opaque term as 2nd argument when terms of different types are expected in these positions -simple2_api.erl:67:29: The call lists:keysearch('key',1,A::simple1_adt:tuple1()) contains an opaque term as 3rd argument when terms of different types are expected in these positions +simple2_api.erl:59:24: The call lists:keysearch(1,A::simple1_adt:d1(),[]) will never return since it differs in the 2nd argument from the success typing arguments: (any(),pos_integer(),maybe_improper_list()) +simple2_api.erl:67:29: The call lists:keysearch('key',1,A::simple1_adt:tuple1()) will never return since it differs in the 3rd argument from the success typing arguments: (any(),pos_integer(),maybe_improper_list()) simple2_api.erl:96:37: The call lists:keyreplace('a',1,[{1, 2}],A::simple1_adt:tuple1()) contains an opaque term as 4th argument when terms of different types are expected in these positions diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/timer b/lib/dialyzer/test/opaque_SUITE_data/results/timer index d921968bc896..85d59db48375 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/timer +++ b/lib/dialyzer/test/opaque_SUITE_data/results/timer @@ -1,4 +1,5 @@ timer_use.erl:16:5: The pattern 'gazonk' can never match the type {'error',_} | {'ok',timer:tref()} -timer_use.erl:17:5: The attempt to match a term of type {'error',_} | {'ok',timer:tref()} against the pattern {'ok', 42} breaks the opacity of timer:tref() -timer_use.erl:18:5: The attempt to match a term of type {'error',_} | {'ok',timer:tref()} against the pattern {Tag, 'gazonk'} breaks the opacity of timer:tref() +timer_use.erl:17:5: The pattern {'ok', 42} can never match the type {'error',_} | {'ok',timer:tref()} +timer_use.erl:18:10: The attempt to match a term of type timer:tref() against the pattern {_, _} breaks the opacity of the term +timer_use.erl:19:24: Guard test Tag::'error' =/= 'error' can never succeed diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/union b/lib/dialyzer/test/opaque_SUITE_data/results/union index c05e17999eee..c21101ba686d 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/union +++ b/lib/dialyzer/test/opaque_SUITE_data/results/union @@ -1,5 +1,4 @@ union_use.erl:12:3: The attempt to match a term of type union_adt:u() against the pattern 'aaa' breaks the opacity of the term -union_use.erl:16:3: The type test is_tuple(union_adt:u()) breaks the opacity of the term union_adt:u() -union_use.erl:7:20: Guard test is_atom(A::union_adt:u()) breaks the opacity of its argument -union_use.erl:8:21: Guard test is_tuple(T::union_adt:u()) breaks the opacity of its argument +union_use.erl:7:12: Guard test is_atom(A::union_adt:u()) breaks the opacity of its argument +union_use.erl:8:12: Guard test is_tuple(T::union_adt:u()) breaks the opacity of its argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/weird b/lib/dialyzer/test/opaque_SUITE_data/results/weird index 8b9cda85dd0c..76c91b8b5dc2 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/weird +++ b/lib/dialyzer/test/opaque_SUITE_data/results/weird @@ -1,6 +1,6 @@ weird_warning1.erl:15:1: Matching of pattern {'a', Dict} tagged with a record name violates the declared type of #b{q::queue:queue(_)} weird_warning2.erl:13:1: Matching of pattern <{'b', Queue}, Key, Value> tagged with a record name violates the declared type of <#a{d::dict:dict(_,_)},'my_key','my_value'> -weird_warning3.erl:14:17: The call weird_warning3:add_element(#a{d::queue:queue(_)},'my_key','my_value') does not have a term of type #a{d::dict:dict(_,_)} | #b{q::queue:queue(_)} (with opaque subterms) as 1st argument -weird_warning3.erl:16:1: The attempt to match a term of type #a{d::queue:queue(_)} against the pattern {'a', Dict} breaks the opacity of queue:queue(_) +weird_warning3.erl:14:17: The call weird_warning3:add_element(#a{d::queue:queue(_)},'my_key','my_value') will never return since it differs in the 1st argument from the success typing arguments: (#a{d::dict:dict(_,_)} | #b{q::queue:queue(_)},any(),any()) +weird_warning3.erl:16:1: Matching of pattern {'a', Dict} tagged with a record name violates the declared type of #a{d::queue:queue(_)} weird_warning3.erl:18:1: Matching of pattern {'b', Queue} tagged with a record name violates the declared type of #a{d::queue:queue(_)} diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/wings b/lib/dialyzer/test/opaque_SUITE_data/results/wings index f95916e68044..905e4c6c8f58 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/wings +++ b/lib/dialyzer/test/opaque_SUITE_data/results/wings @@ -1,11 +1,12 @@ -wings_dissolve.erl:142:30: Guard test is_list(List::gb_sets:set(_)) breaks the opacity of its argument -wings_dissolve.erl:311:45: Guard test is_list(Faces::gb_sets:set(_)) breaks the opacity of its argument -wings_dissolve.erl:58:21: Guard test is_list(Faces::gb_sets:set(_)) breaks the opacity of its argument -wings_dissolve.erl:70:27: The call gb_sets:is_empty(Faces::[any(),...]) does not have an opaque term of type gb_sets:set(_) as 1st argument -wings_edge.erl:245:1: The pattern can never match the type <_,'soft',_> -wings_edge_cmd.erl:70:31: The call gb_trees:size(P::gb_sets:set(_)) does not have an opaque term of type gb_trees:tree(_,_) as 1st argument -wings_edge_cmd.erl:72:18: The pattern [{_, P} | _] can never match the type [] -wings_edge_cmd.erl:72:6: The pattern [_ | Parts] can never match the type [] -wings_io.erl:70:2: The attempt to match a term of type {'empty',queue:queue(_)} against the pattern {'empty', {In, Out}} breaks the opacity of queue:queue(_) -wings_we.erl:195:37: The call wings_util:gb_trees_largest_key(Etab::gb_trees:tree(_,_)) contains an opaque term as 1st argument when a structured term of type {_,{_,_,_,'nil' | {_,_,_,'nil' | {_,_,_,_}}}} is expected +wings_dissolve.erl:103:22: Guard test is_list(List::gb_sets:set(_)) can never succeed +wings_dissolve.erl:19:13: Guard test is_list(Faces::gb_sets:set(_)) can never succeed +wings_dissolve.erl:272:37: Guard test is_list(Faces::gb_sets:set(_)) can never succeed +wings_dissolve.erl:31:27: The call gb_sets:is_empty(Faces::[any(),...]) breaks the contract (Set) -> boolean() when Set :: set() +wings_dissolve.erl:31:27: The call gb_sets:is_empty(Faces::[any(),...]) does not have an opaque term of type gb_sets:set(_) as 1st argument +wings_edge.erl:205:1: The pattern can never match the type <_,'soft',_> +wings_edge_cmd.erl:30:31: The call gb_trees:size(P::gb_sets:set(_)) breaks the contract (Tree) -> non_neg_integer() when Tree :: tree() +wings_edge_cmd.erl:32:18: The pattern [{_, P} | _] can never match the type [] +wings_edge_cmd.erl:32:6: The pattern [_ | Parts] can never match the type [] +wings_io.erl:30:9: The attempt to match a term of type queue:queue(_) against the pattern {In, Out} breaks the opacity of the term +wings_we.erl:155:37: The call wings_util:gb_trees_largest_key(Etab::gb_trees:tree(_,_)) contains an opaque term as 1st argument when a structured term of type {_,{_,_,_,'nil' | {_,_,_,'nil' | {_,_,_,_}}}} is expected diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_adt.erl index cdcaa5f9e827..577e2f9e9c6b 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_adt.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_adt.erl @@ -1,5 +1,13 @@ -module(opaque_adt). --export([atom_or_list/1]). +-export([atom_or_list/1, line/1, location/1]). + +-export_type([anno/0]). + +-type annotation() :: {'location', location()} | {'text', string()}. +-nominal column() :: pos_integer(). +-nominal line() :: non_neg_integer(). +-nominal location() :: line() | {line(), column()}. +-opaque anno() :: location() | [annotation(), ...]. -opaque abc() :: 'a' | 'b' | 'c'. @@ -9,3 +17,23 @@ atom_or_list(1) -> a; atom_or_list(2) -> b; atom_or_list(3) -> c; atom_or_list(N) -> lists:duplicate(N, a). + +-spec line(Anno) -> line() when + Anno :: anno(). +line(Anno) -> + case location(Anno) of + {Line, _Column} -> + Line; + Line -> + Line + end. + +-spec location(Anno) -> location() when + Anno :: anno(). + +location(Line) when is_integer(Line) -> + Line; +location({Line, Column}=Location) when is_integer(Line), is_integer(Column) -> + Location; +location(Anno) -> + ext:ernal(Anno, location). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug6.erl b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug6.erl new file mode 100644 index 000000000000..f4d407a34d2f --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug6.erl @@ -0,0 +1,9 @@ +-module(opaque_bug6). +-export([record_update/1]). + +record_update(R) -> + Anno = element(2, R), + [ln(Anno), Anno]. + +ln(Anno) -> + opaque_adt:line(Anno). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_adt.erl index f01cc5e51908..ff991a201a4b 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_adt.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_adt.erl @@ -1,6 +1,6 @@ -module(rec_adt). --export([new/0, get_a/1, get_b/1, set_a/2, set_b/2]). +-export([new/0, new/1, get_a/1, get_b/1, set_a/2, set_b/2]). -record(rec, {a :: atom(), b = 0 :: integer()}). @@ -9,6 +9,9 @@ -spec new() -> rec(). new() -> #rec{a = gazonk, b = 42}. +-spec new(integer()) -> rec(). +new(B) -> #rec{a = gazonk, b = B}. + -spec get_a(rec()) -> atom(). get_a(#rec{a = A}) -> A. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_use.erl index 358e9f918ca4..24597e85d4db 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_use.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_use.erl @@ -1,6 +1,6 @@ -module(rec_use). --export([ok1/0, ok2/0, wrong1/0, wrong2/0, wrong3/0, wrong4/0]). +-export([ok1/0, ok2/0, wrong1/0, wrong2/0, wrong3/0]). ok1() -> rec_adt:set_a(rec_adt:new(), foo). @@ -13,7 +13,7 @@ ok2() -> B1 =:= B2. wrong1() -> - case rec_adt:new() of + case rec_adt:new(42) of {rec, _, 42} -> weird1; R when tuple_size(R) =:= 3 -> weird2 end. @@ -25,6 +25,3 @@ wrong2() -> wrong3() -> R = rec_adt:new(), R =:= {rec, gazonk, 42}. - -wrong4() -> - tuple_size(rec_adt:new()). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/timer/timer_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/timer/timer_use.erl index ed6810634f74..5af9ee167263 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/timer/timer_use.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/timer/timer_use.erl @@ -14,7 +14,8 @@ wrong() -> case timer:kill_after(42, self()) of gazonk -> weird; - {ok, 42} -> weirder; + {ok, 42} -> odd; + {ok, {_,_}} -> weirder; {Tag, gazonk} when Tag =/= error -> weirdest; {error, _} -> error end. diff --git a/lib/dialyzer/test/overspecs_SUITE_data/results/opaque b/lib/dialyzer/test/overspecs_SUITE_data/results/opaque index b0b41aba8edc..5f3ebca631bb 100644 --- a/lib/dialyzer/test/overspecs_SUITE_data/results/opaque +++ b/lib/dialyzer/test/overspecs_SUITE_data/results/opaque @@ -1,2 +1,3 @@ -opaque.erl:5:2: The success typing for opaque:accidental_supertype/0 implies that the function might also return gb_sets:set(_) but the specification return is 'other' | {_,_} +opaque.erl:8:9: Body yields the opaque type gb_sets:set(_) whose opacity is broken by the other clauses. +opaque.erl:9:9: Body yields the type 'other' which violates the opacity of the other clauses. diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 b/lib/dialyzer/test/r9c_SUITE_data/results/asn1 index e73698747c1f..6d6c886e6b06 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 +++ b/lib/dialyzer/test/r9c_SUITE_data/results/asn1 @@ -1,4 +1,6 @@ +asn1ct.erl:1224:2: Body yields the type atom() | ets:tid() which violates the opacity of the other clauses. +asn1ct.erl:1227:2: Body yields the type 'ok' which violates the opacity of the other clauses. asn1ct.erl:1500:2: The variable Err can never match since previous clauses completely covered the type #type{} asn1ct.erl:1596:2: The variable _ can never match since previous clauses completely covered the type 'ber_bin_v2' asn1ct.erl:1673:2: The pattern 'all' can never match the type 'asn1_module' | 'exclusive_decode' | 'partial_decode' diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia index ffeb712fc56d..044fc3a954f9 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia +++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia @@ -21,9 +21,21 @@ mnesia_frag_old_hash.erl:105:6: Call to missing or unexported function erlang:ha mnesia_frag_old_hash.erl:23:2: Callback info about the mnesia_frag_hash behaviour is not available mnesia_index.erl:52:45: The call mnesia_lib:other_val(Var::{_,'commit_work' | 'index' | 'setorbag' | 'storage_type' | {'index',_}},_ReASoN_::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any()) mnesia_lib.erl:1028:2: The pattern {'EXIT', Reason} can never match the type [any()] | {'error',_} +mnesia_lib.erl:1110:2: Body yields the type atom() | {'error',_} | ets:tid() which violates the opacity of the other clauses. +mnesia_lib.erl:1114:2: Body yields the type {_,_} which violates the opacity of the other clauses. +mnesia_lib.erl:1118:1: Body yields the type 'loaded' which violates the opacity of the other clauses. +mnesia_lib.erl:1119:1: Body yields the type atom() | {'error',_} | ets:tid() which violates the opacity of the other clauses. mnesia_lib.erl:957:2: The pattern {'ok', {0, _}} can never match the type 'eof' | {'error',atom() | {'no_translation','unicode','latin1'}} | {'ok',binary() | string()} mnesia_lib.erl:959:2: The pattern {'ok', {_, Bin}} can never match the type 'eof' | {'error',atom() | {'no_translation','unicode','latin1'}} | {'ok',binary() | string()} +mnesia_loader.erl:101:5: Body yields the type 'false' which violates the opacity of the other clauses. +mnesia_loader.erl:105:3: Body yields the type 'false' which violates the opacity of the other clauses. mnesia_loader.erl:36:43: The call mnesia_lib:other_val(Var::{_,'access_mode' | 'cstruct' | 'db_nodes' | 'setorbag' | 'snmp' | 'storage_type'},Reason::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any()) +mnesia_loader.erl:85:2: Body yields the type 'ignore' which violates the opacity of the other clauses. +mnesia_loader.erl:87:2: Body yields the type atom() | number() | {_,_} | ets:tid() which violates the opacity of the other clauses. +mnesia_loader.erl:93:3: Body yields the type atom() | number() | {_,_} | ets:tid() which violates the opacity of the other clauses. +mnesia_loader.erl:95:4: Body yields the type number() which violates the opacity of the other clauses. +mnesia_loader.erl:96:4: Body yields the type atom() | {_,_} | ets:tid() which violates the opacity of the other clauses. +mnesia_loader.erl:98:5: Body yields the type atom() | {_,_} | ets:tid() which violates the opacity of the other clauses. mnesia_locker.erl:1017:1: Function system_terminate/4 has no local return mnesia_log.erl:707:23: The test {'error',{[1..255,...],[any(),...]}} | {'ok',_} == atom() can never evaluate to 'true' mnesia_log.erl:727:13: The created fun has no local return @@ -36,6 +48,7 @@ mnesia_schema.erl:1258:2: Guard test FromS::'disc_copies' | 'disc_only_copies' | mnesia_schema.erl:1639:2: The pattern {'false', 'mandatory'} can never match the type {'false','optional'} mnesia_schema.erl:2434:2: The variable Reason can never match since previous clauses completely covered the type {'error',_} | {'ok',_} mnesia_schema.erl:451:36: Guard test UseDirAnyway::'false' == 'true' can never succeed -mnesia_text.erl:180:3: The variable T can never match since previous clauses completely covered the type {'error',{non_neg_integer() | {non_neg_integer(),pos_integer()},atom(),_}} | {'ok',_} +mnesia_schema.erl:496:13: Body yields the type atom() | ets:tid() which violates the opacity of the other clauses. +mnesia_text.erl:180:3: The variable T can never match since previous clauses completely covered the type {'error',{(erl_anno:location() :: {(erl_anno:line() :: non_neg_integer()),pos_integer()} | (erl_anno:line() :: non_neg_integer())),atom(),_}} | {'ok',_} mnesia_tm.erl:1522:1: Function commit_participant/5 has no local return mnesia_tm.erl:2169:1: Function system_terminate/4 has no local return diff --git a/lib/dialyzer/test/small_SUITE_data/results/bif1 b/lib/dialyzer/test/small_SUITE_data/results/bif1 index f35efeab5aa1..b3ef29a2a9f3 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/bif1 +++ b/lib/dialyzer/test/small_SUITE_data/results/bif1 @@ -1,3 +1,2 @@ -bif1.erl:13:1: Function string_chars/0 has no local return bif1.erl:16:25: The call string:chars(S::65,10,L2::bif1_adt:s()) contains an opaque term as 3rd argument when terms of different types are expected in these positions diff --git a/lib/dialyzer/test/small_SUITE_data/results/maps_sum b/lib/dialyzer/test/small_SUITE_data/results/maps_sum index df2a90387b93..b0ed98abdcf1 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/maps_sum +++ b/lib/dialyzer/test/small_SUITE_data/results/maps_sum @@ -1,7 +1,11 @@ maps_sum.erl:15:2: Invalid type specification for function maps_sum:wrong1/1. - The success typing is maps_sum:wrong1(maps:iterator(_,_) | map()) -> any() + The success typing is maps_sum:wrong1(map() | maps:iterator(_,_)) -> any() But the spec is maps_sum:wrong1([{atom(),term()}]) -> integer() They do not overlap in the 1st argument +maps_sum.erl:24:2: Invalid type specification for function maps_sum:wrong2/1. + The success typing is maps_sum:wrong2(_) -> none() + But the spec is maps_sum:wrong2(#{atom()=>term()}) -> integer() + The return types do not overlap maps_sum.erl:26:1: Function wrong2/1 has no local return maps_sum.erl:27:17: The call lists:foldl(fun((_,_,_) -> any()),0,Data::any()) will never return since it differs in the 1st argument from the success typing arguments: (fun((_,_) -> any()),any(),[any()]) diff --git a/lib/dialyzer/test/underspecs_SUITE_data/results/opaque b/lib/dialyzer/test/underspecs_SUITE_data/results/opaque index 80048dea79f0..f18dca9d2943 100644 --- a/lib/dialyzer/test/underspecs_SUITE_data/results/opaque +++ b/lib/dialyzer/test/underspecs_SUITE_data/results/opaque @@ -1,2 +1,4 @@ -opaque.erl:5:2: The specification for opaque:accidental_supertype/0 states that the function might also return {_,_} but the inferred return is 'other' | gb_sets:set(_) +opaque.erl:5:2: Type specification opaque:accidental_supertype() -> {term(),term()} | 'other' is a supertype of the success typing: opaque:accidental_supertype() -> 'other' | gb_sets:set(_) +opaque.erl:8:9: Body yields the opaque type gb_sets:set(_) whose opacity is broken by the other clauses. +opaque.erl:9:9: Body yields the type 'other' which violates the opacity of the other clauses. diff --git a/lib/dialyzer/test/unmatched_returns_SUITE_data/results/lc_warnings b/lib/dialyzer/test/unmatched_returns_SUITE_data/results/lc_warnings index 44913ba8b772..3d92d31b7765 100644 --- a/lib/dialyzer/test/unmatched_returns_SUITE_data/results/lc_warnings +++ b/lib/dialyzer/test/unmatched_returns_SUITE_data/results/lc_warnings @@ -1,5 +1,4 @@ -lc_warnings.erl:32:5: Expression produces a value of type [opaque_atom_adt:opaque_atom()], but this value is unmatched lc_warnings.erl:43:5: Expression produces a value of type [array:array(_)], but this value is unmatched lc_warnings.erl:65:5: Expression produces a value of type [lc_warnings:opaque_tuple()], but this value is unmatched lc_warnings.erl:7:5: Expression produces a value of type ['ok' | {'error',atom()}], but this value is unmatched diff --git a/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl b/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl index 7bf005d8ada7..c929a4bbd9b8 100644 --- a/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl +++ b/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl @@ -1,2 +1,3 @@ +gcpFlowControl.erl:130:1: Body yields the type atom() | ets:tid() which violates the opacity of the other clauses. gcpFlowControl.erl:171:2: The pattern can never match the type <_,'available' | 'bucket' | 'rejectable' | 'rejects' | 'window',0 | 1 | 20> diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 7d54c2b0bf77..04129eea96c8 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -2353,11 +2353,7 @@ map_info(_, T, _) -> bins_sum(L, true = _BinsInfo) -> {0, bins_sum2(L, dict:new())}; bins_sum(L, BinsInfo) when is_integer(BinsInfo) -> - bins_sum3(L, BinsInfo, dict:new()); -bins_sum(_, _) -> - %% We should actually not get here, but just in case - %% we have a logic error somewhere... - dict:new(). + bins_sum3(L, BinsInfo, dict:new()). bins_sum2([], D) -> D; diff --git a/lib/diameter/src/base/diameter_sup.erl b/lib/diameter/src/base/diameter_sup.erl index 3232f1507a31..03546f5b67ff 100644 --- a/lib/diameter/src/base/diameter_sup.erl +++ b/lib/diameter/src/base/diameter_sup.erl @@ -78,7 +78,8 @@ ets_new(List) lists:foreach(fun ets_new/1, List); ets_new({Table, Opts}) -> - ets:new(Table, [named_table, public | Opts]). + ets:new(Table, [named_table, public | Opts]), + ok. %% tree/0 diff --git a/lib/edoc/src/edoc_doclet_markdown.erl b/lib/edoc/src/edoc_doclet_markdown.erl index b8056b2aef5c..796564c70904 100644 --- a/lib/edoc/src/edoc_doclet_markdown.erl +++ b/lib/edoc/src/edoc_doclet_markdown.erl @@ -403,10 +403,10 @@ filter_and_fix_anno(AST, [{{What, F, A}, _Anno, S, D, M} | T], ModuleDoc) end; type -> case lists:search(fun({attribute, _TypeAnno, TO, {FA, _}}) when - is_tuple(FA), TO =:= type orelse TO =:= opaque -> + is_tuple(FA), TO =:= type orelse TO =:= nominal -> {F, A} =:= FA; ({attribute, _TypeAnno, TO, {Type, _, Args}}) when - is_atom(Type), TO =:= type orelse TO =:= opaque -> + is_atom(Type), TO =:= type orelse TO =:= opaque orelse TO =:= nominal-> {F, A} =:= {Type, length(Args)}; (_) -> false diff --git a/lib/edoc/src/edoc_layout_chunks.erl b/lib/edoc/src/edoc_layout_chunks.erl index 548582b51726..b7c77987b8fd 100644 --- a/lib/edoc/src/edoc_layout_chunks.erl +++ b/lib/edoc/src/edoc_layout_chunks.erl @@ -222,7 +222,7 @@ select_tag(#tag{name = type, line = Line, origin = code} = T, TypeAttr = erl_syntax:revert(TypeTree), case TypeAttr of {attribute, _, Type, {Name, _, Args}} - when (type =:= Type orelse opaque =:= Type), + when (type =:= Type orelse opaque =:= Type orelse nominal =:= Type), length(Args) == Arity -> {true, TypeAttr}; _ -> diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index b43e66171f20..76e002e313a0 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -667,6 +667,7 @@ analyze_type_attribute(Form) -> -spec is_tag(Tag :: tag_kind() | term()) -> boolean(). is_tag(callback) -> true; +is_tag(nominal) -> true; is_tag(opaque) -> true; is_tag(spec) -> true; is_tag(type) -> true; @@ -678,6 +679,7 @@ is_tag(_) -> false. -spec tag(Tag :: atom()) -> tag_kind() | unknown. tag(callback) -> callback; +tag(nominal) -> nominal; tag(opaque) -> type; tag(spec) -> spec; tag(type) -> type; diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl index bdda7769b23c..e290817f6fa1 100644 --- a/lib/eunit/src/eunit_lib.erl +++ b/lib/eunit/src/eunit_lib.erl @@ -526,6 +526,7 @@ list_dir(Dir) -> trie_new() -> gb_trees:empty(). +-dialyzer({no_opaque_union, [trie_store/2]}). trie_store([_ | _], []) -> []; trie_store([E | Es], T) -> diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 172f4d5b280a..9b9c6fb61603 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -536,6 +536,7 @@ load_file(Mod) when is_atom(Mod) -> {Mod,Binary,File} -> load_module(Mod, File, Binary, false) end. +-dialyzer({no_opaque_union, [ensure_loaded/1]}). -doc """ Tries to load a module in the same way as `load_file/1`, unless the module is already loaded. @@ -574,6 +575,7 @@ ensure_loaded(Mod) when is_atom(Mod) -> end end. +-dialyzer({no_opaque_union, [ensure_prepare_loading/3]}). ensure_prepare_loading(Mod, missing, File) -> case erl_prim_loader:read_file(File) of {ok, Binary} -> erlang:prepare_loading(Mod, Binary); diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl index f96b64710d91..65386ad6c7ff 100644 --- a/lib/mnesia/src/mnesia_lib.erl +++ b/lib/mnesia/src/mnesia_lib.erl @@ -1305,6 +1305,7 @@ db_erase_tab(disc_only_copies, _Tab) -> ignore; db_erase_tab({ext, _Alias, _Mod}, _Tab) -> ignore. %% assuming that Tab is a valid ets-table +-dialyzer({no_opaque_union, [dets_to_ets/6]}). dets_to_ets(Tabname, Tab, File, Type, Rep, Lock) -> {Open, Close} = mkfuns(Lock), case Open(Tabname, [{file, File}, {type, disk_type(Tab, Type)}, @@ -1317,6 +1318,7 @@ dets_to_ets(Tabname, Tab, File, Type, Rep, Lock) -> Other end. +-dialyzer({no_opaque_union, [trav_ret/2]}). trav_ret(Tabname, Tabname) -> loaded; trav_ret(Other, _Tabname) -> Other. diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl index fc8f19edffc8..b578ddac2309 100644 --- a/lib/mnesia/src/mnesia_loader.erl +++ b/lib/mnesia/src/mnesia_loader.erl @@ -57,6 +57,7 @@ disc_load_table(Tab, Reason, Cs) -> {type, Type}]), do_get_disc_copy2(Tab, Reason, Storage, Type). +-dialyzer({no_opaque_union, [do_get_disc_copy2/4]}). do_get_disc_copy2(Tab, Reason, Storage, _Type) when Storage == unknown -> verbose("Local table copy of ~0tp ~0p has recently been deleted, ignored.~n", [Tab, Reason]), diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl index c73e0f7ed46e..13ee81991a2c 100644 --- a/lib/mnesia/src/mnesia_schema.erl +++ b/lib/mnesia/src/mnesia_schema.erl @@ -559,6 +559,7 @@ read_disc_schema(Keep, IgnoreFallback) -> end end. +-dialyzer({no_opaque_union, [do_read_disc_schema/2]}). do_read_disc_schema(Fname, Keep) -> T = case Keep of diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl index 32b1aaa2b750..27b401f4a01c 100644 --- a/lib/parsetools/src/leex.erl +++ b/lib/parsetools/src/leex.erl @@ -289,7 +289,7 @@ Floats (\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)? Token :: term(), ErrorInfo :: {error, error_info(), erl_anno:location()}, EndLoc :: erl_anno:location(). -string(_String) -> error(undef). +string(_String) -> erlang:nif_error(undef). -doc """ Scans `String` and returns either all the tokens in it or an `error` tuple. @@ -310,7 +310,7 @@ or [`erl_anno:location()`](`t:erl_anno:location/0`), depending on the ErrorInfo :: {error, error_info(), erl_anno:location()}, StartLoc :: erl_anno:location(), EndLoc :: erl_anno:location(). -string(_String, _StartLoc) -> error(undef). +string(_String, _StartLoc) -> erlang:nif_error(undef). -doc #{equiv => token(Cont, Chars, 1)}. -doc(#{title => <<"Generated Scanner Exports">>}). @@ -326,7 +326,7 @@ string(_String, _StartLoc) -> error(undef). ErrorInfo :: {error, error_info(), erl_anno:location()}, Token :: term(), EndLoc :: erl_anno:location(). -token(_Cont, _Chars) -> error(undef). +token(_Cont, _Chars) -> erlang:nif_error(undef). -doc """ This is a re-entrant call to try and scan a single token from `Chars`. @@ -361,7 +361,7 @@ io:request(InFile, {get_until,unicode,Prompt,Module,token,[Loc]}) Token :: term(), StartLoc :: erl_anno:location(), EndLoc :: erl_anno:location(). -token(_Cont, _Chars, _StartLoc) -> error(undef). +token(_Cont, _Chars, _StartLoc) -> erlang:nif_error(undef). -doc #{equiv => tokens(Cont, Chars, 1)}. -doc(#{title => <<"Generated Scanner Exports">>}). @@ -378,7 +378,7 @@ token(_Cont, _Chars, _StartLoc) -> error(undef). Token :: term(), ErrorInfo :: {error, error_info(), erl_anno:location()}, EndLoc :: erl_anno:location(). -tokens(_Cont, _Chars) -> error(undef). +tokens(_Cont, _Chars) -> erlang:nif_error(undef). -doc """ This is a re-entrant call to try and scan tokens from `Chars`. @@ -419,7 +419,7 @@ io:request(InFile, {get_until,unicode,Prompt,Module,tokens,[Loc]}) ErrorInfo :: {error, error_info(), erl_anno:location()}, StartLoc :: erl_anno:location(), EndLoc :: erl_anno:location(). -tokens(_Cont, _Chars, _StartLoc) -> error(undef). +tokens(_Cont, _Chars, _StartLoc) -> erlang:nif_error(undef). %%% %%% Exported functions diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl index 73151e25e07d..4d557cf3ead2 100644 --- a/lib/runtime_tools/src/observer_backend.erl +++ b/lib/runtime_tools/src/observer_backend.erl @@ -416,17 +416,19 @@ sockaddr_to_list(#{family := inet6, addr := Addr, port := Port, " , " ++ erlang:integer_to_list(SID); sockaddr_to_list(Addr) -> f("~p", [Addr]). - + +-dialyzer({no_opaque_union, [get_ets_tab_id/1]}). +get_ets_tab_id(Id) -> + case ets:info(Id, named_table) of + true -> ignore; + false -> Id + end. get_table_list(ets, Opts) -> HideUnread = proplists:get_value(unread_hidden, Opts, true), HideSys = proplists:get_value(sys_hidden, Opts, true), Info = fun(Id, Acc) -> try - TabId = case ets:info(Id, named_table) of - true -> ignore; - false -> Id - end, Name = ets:info(Id, name), Protection = ets:info(Id, protection), ignore(HideUnread andalso Protection == private, unreadable), @@ -442,7 +444,7 @@ get_table_list(ets, Opts) -> andalso is_atom((catch mnesia:table_info(Name, where_to_read))), mnesia_tab), Memory = ets:info(Id, memory) * erlang:system_info(wordsize), Tab = [{name,Name}, - {id,TabId}, + {id,get_ets_tab_id(Id)}, {protection,Protection}, {owner,Owner}, {size,ets:info(Id, size)}, diff --git a/lib/snmp/src/agent/snmpa_mib.erl b/lib/snmp/src/agent/snmpa_mib.erl index 1ff45299a4ec..2232999e360e 100644 --- a/lib/snmp/src/agent/snmpa_mib.erl +++ b/lib/snmp/src/agent/snmpa_mib.erl @@ -946,6 +946,7 @@ do_gc_cache(Cache, [Key|Keys]) -> ets:delete(Cache, Key), do_gc_cache(Cache, Keys). +-dialyzer({no_opaque_union, [maybe_invalidate_cache/1]}). maybe_invalidate_cache(?NO_CACHE) -> ?NO_CACHE; maybe_invalidate_cache(Cache) -> diff --git a/lib/snmp/src/agent/snmpa_vacm.erl b/lib/snmp/src/agent/snmpa_vacm.erl index f159e6bd7aed..2194d178a394 100644 --- a/lib/snmp/src/agent/snmpa_vacm.erl +++ b/lib/snmp/src/agent/snmpa_vacm.erl @@ -188,6 +188,7 @@ loop_mib_view_get(Indexes) -> init(Dir) -> init(Dir, terminate). +-dialyzer({no_opaque_union, [init/2]}). init(Dir, InitError) -> FName = filename:join(Dir, "snmpa_vacm.db"), case file:read_file_info(FName) of diff --git a/lib/ssh/src/ssh_client_channel.erl b/lib/ssh/src/ssh_client_channel.erl index bcc2848b50ef..fd8ba096cb11 100644 --- a/lib/ssh/src/ssh_client_channel.erl +++ b/lib/ssh/src/ssh_client_channel.erl @@ -335,7 +335,7 @@ The user is responsible for any initialization of the process and must call `init/1`. """. -doc(#{since => <<"OTP 21.0">>}). --spec enter_loop(State) -> _ when State :: term(). +-spec enter_loop(State) -> no_return() when State :: term(). enter_loop(State) -> gen_server:enter_loop(?MODULE, [], State). diff --git a/lib/ssl/src/ssl_gen_statem.erl b/lib/ssl/src/ssl_gen_statem.erl index d269db8f588a..475178aaed1e 100644 --- a/lib/ssl/src/ssl_gen_statem.erl +++ b/lib/ssl/src/ssl_gen_statem.erl @@ -1592,7 +1592,12 @@ read_application_dist_data(_DHandle, [] = Front, BufferSize, [] = Rear) -> read_application_dist_data(DHandle, [], BufferSize, Rear) -> [Bin|Front] = lists:reverse(Rear), read_application_dist_data(DHandle, Front, BufferSize, [], Bin). -%% + +%% We suppress opacity warnings because we've violated the opacity of +%% `erlang:dist_handle() :: atom()` previously in the code, mixing it with +%% the magic atom 'undefined' caused the opacity to be removed leading to +%% warnings in calls to erlang:dist_ctrl_put_data/2 +-dialyzer({no_opaque, [read_application_dist_data/5]}). read_application_dist_data(DHandle, Front0, BufferSize, Rear0, Bin0) -> case Bin0 of %% diff --git a/lib/stdlib/src/erl_anno.erl b/lib/stdlib/src/erl_anno.erl index ef47d5a4df33..976c9b41a184 100644 --- a/lib/stdlib/src/erl_anno.erl +++ b/lib/stdlib/src/erl_anno.erl @@ -119,8 +119,8 @@ or a list of key-value pairs. -type column() :: pos_integer(). -type generated() :: boolean(). -type filename() :: file:filename_all(). --type line() :: non_neg_integer(). --type location() :: line() | {line(), column()}. +-nominal line() :: non_neg_integer(). +-nominal location() :: line() | {line(), column()}. -type record() :: boolean(). -type text() :: string(). diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index e05cf24e600e..99853332273b 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -180,8 +180,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> :: #{atom() => {anno(),Fields :: term()}}, locals=gb_sets:empty() %All defined functions (prescanned) :: gb_sets:set(fa()), - no_auto=gb_sets:empty() %Functions explicitly not autoimported - :: gb_sets:set(fa()) | 'all', + no_auto={set, gb_sets:empty()} %Functions explicitly not autoimported + :: 'all' | {set, gb_sets:set(fa())}, defined=gb_sets:empty() %Defined fuctions :: gb_sets:set(fa()), on_load=[] :: [fa()], %On-load function @@ -1069,6 +1069,9 @@ attribute_state({attribute,A,type,{TypeName,TypeDef,Args}}, St) -> attribute_state({attribute,A,opaque,{TypeName,TypeDef,Args}}, St) -> St1 = untrack_doc({type, TypeName, length(Args)}, St), type_def(opaque, A, TypeName, TypeDef, Args, St1); +attribute_state({attribute,A,nominal,{TypeName,TypeDef,Args}}=AST, St) -> + St1 = untrack_doc(AST, St), + type_def(nominal, A, TypeName, TypeDef, Args, St1); attribute_state({attribute,A,spec,{Fun,Types}}, St) -> spec_decl(A, Fun, Types, St); attribute_state({attribute,A,callback,{Fun,Types}}, St) -> @@ -1150,6 +1153,9 @@ function_state({attribute,A,type,{TypeName,TypeDef,Args}}, St) -> function_state({attribute,A,opaque,{TypeName,TypeDef,Args}}, St) -> St1 = untrack_doc({type, TypeName, length(Args)}, St), type_def(opaque, A, TypeName, TypeDef, Args, St1); +function_state({attribute,A,nominal,{TypeName,TypeDef,Args}}=AST, St) -> + St1 = untrack_doc(AST, St), + type_def(nominal, A, TypeName, TypeDef, Args, St1); function_state({attribute,A,spec,{Fun,Types}}, St) -> spec_decl(A, Fun, Types, St); function_state({attribute,_A,doc,_Val}=AST, St) -> @@ -3795,6 +3801,8 @@ check_local_opaque_types(St) -> FoldFun = fun(_Type, #typeinfo{attr = type}, AccSt) -> AccSt; + (_Type, #typeinfo{attr = nominal, anno = _Anno}, AccSt) -> + AccSt; (Type, #typeinfo{attr = opaque, anno = Anno}, AccSt) -> case gb_sets:is_element(Type, ExpTs) of true -> AccSt; @@ -3863,7 +3871,8 @@ is_module_dialyzer_option(Option) -> error_handling,race_conditions,no_missing_calls, specdiffs,overspecs,underspecs,unknown, no_underspecs,extra_return,no_extra_return, - missing_return,no_missing_return,overlapping_contract + missing_return,no_missing_return,overlapping_contract, + opaque_union,no_opaque_union ]). %% try_catch_clauses(Scs, Ccs, In, ImportVarTable, State) -> @@ -5014,12 +5023,12 @@ auto_import_suppressed(CompileFlags) -> false -> L0 = [ X || {no_auto_import,X} <- CompileFlags ], L1 = [ {Y,Z} || {Y,Z} <- lists:flatten(L0), is_atom(Y), is_integer(Z) ], - gb_sets:from_list(L1) + {set, gb_sets:from_list(L1)} end. %% Predicate to find out if autoimport is explicitly suppressed for a function is_autoimport_suppressed(all,{_Func,_Arity}) -> true; -is_autoimport_suppressed(NoAutoSet,{Func,Arity}) -> +is_autoimport_suppressed({set, NoAutoSet},{Func,Arity}) -> gb_sets:is_element({Func,Arity},NoAutoSet). %% Predicate to find out if a function specific bif-clash suppression (old deprecated) is present bif_clash_specifically_disabled(St,{F,A}) -> diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index 7babc9c7bc1d..090f74d7ad29 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -856,7 +856,7 @@ processed (see section [Error Information](#module-error-information)). -type af_type_decl() :: {'attribute', anno(), type_attr(), {type_name(), abstract_type(), [af_variable()]}}. --type type_attr() :: 'opaque' | 'type'. +-type type_attr() :: 'nominal' | 'opaque' | 'type'. -type af_function_spec() :: {'attribute', anno(), spec_attr(), {{function_name(), arity()}, @@ -1375,14 +1375,14 @@ parse_term(Tokens) -> end. -type attributes() :: 'export' | 'file' | 'import' | 'module' - | 'opaque' | 'record' | 'type'. + | 'nominal' | 'opaque' | 'record' | 'type'. build_typed_attribute({atom,Aa,record}, {typed_record, {atom,_An,RecordName}, RecTuple}) -> {attribute,Aa,record,{RecordName,record_tuple(RecTuple)}}; build_typed_attribute({atom,Aa,Attr}, {type_def, {call,_,{atom,_,TypeName},Args}, Type}) - when Attr =:= 'type' ; Attr =:= 'opaque' -> + when Attr =:= 'type' ; Attr =:= 'opaque' ; Attr =:= 'nominal'-> lists:foreach(fun({var, A, '_'}) -> ret_err(A, "bad type variable"); (_) -> ok end, Args), @@ -1395,6 +1395,7 @@ build_typed_attribute({atom,Aa,Attr}=Abstr,_) -> case Attr of record -> error_bad_decl(Abstr, record); type -> error_bad_decl(Abstr, type); + nominal -> error_bad_decl(Abstr, nominal); opaque -> error_bad_decl(Abstr, opaque); _ -> ret_err(Aa, "bad attribute") end. @@ -2246,6 +2247,11 @@ modify_anno1({attribute,A,opaque,{TypeName,TypeDef,Args}}, Ac, Mf) -> {TypeDef1,Ac2} = modify_anno1(TypeDef, Ac1, Mf), {Args1,Ac3} = modify_anno1(Args, Ac2, Mf), {{attribute,A1,opaque,{TypeName,TypeDef1,Args1}},Ac3}; +modify_anno1({attribute,A,nominal,{TypeName,TypeDef,Args}}, Ac, Mf) -> + {A1,Ac1} = Mf(A, Ac), + {TypeDef1,Ac2} = modify_anno1(TypeDef, Ac1, Mf), + {Args1,Ac3} = modify_anno1(Args, Ac2, Mf), + {{attribute,A1,nominal,{TypeName,TypeDef1,Args1}},Ac3}; modify_anno1({attribute,A,Attr,Val}, Ac, Mf) -> {A1,Ac1} = Mf(A, Ac), {{attribute,A1,Attr,Val},Ac1}; diff --git a/lib/syntax_tools/src/erl_recomment.erl b/lib/syntax_tools/src/erl_recomment.erl index a2f3519f923f..0a3e65b9727d 100644 --- a/lib/syntax_tools/src/erl_recomment.erl +++ b/lib/syntax_tools/src/erl_recomment.erl @@ -723,12 +723,6 @@ get_line(Node) -> L; {L, _} when is_integer(L) -> L; - {_, L} when is_integer(L) -> - L; - {L, _, _} when is_integer(L) -> - L; - {_, L, _} when is_integer(L) -> - L; Pos -> try erl_anno:line(Pos) of Line -> diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl index c9841c388e54..49ca53e6fbf7 100644 --- a/lib/syntax_tools/src/merl_transform.erl +++ b/lib/syntax_tools/src/merl_transform.erl @@ -281,6 +281,7 @@ is_erlang_var([C|_]) when C >= $A, C =< $Z ; C >= $À, C =< $Þ, C /= $× -> is_erlang_var(_) -> false. +-dialyzer({no_opaque_union, [get_location/1]}). get_location(T) -> Pos = erl_syntax:get_pos(T), case erl_anno:is_anno(Pos) of