Snap for 8414339 from 54b24a8b0acb4627a3e352121f262a92fecdad24 to tm-qpr1-release
Change-Id: I791a3d2ad17ddc1f13fc383c70d5ff5e07df4c33
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index e2e102f..48567ee 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -120,6 +120,7 @@
Alex Myasoedov <msoedov@gmail.com>
Alex Opie <amtopie@gmail.com>
Alex Plugaru <alex@plugaru.org> <alexandru.plugaru@gmail.com>
+Alex Schade <39062967+aschade92@users.noreply.github.com>
Alex Schroeder <alex@gnu.org>
Alex Sergeyev <abc@alexsergeyev.com>
Alex Tokarev <aleksator@gmail.com>
@@ -135,6 +136,7 @@
Alexander Kucherenko <alxkchr@gmail.com>
Alexander Larsson <alexander.larsson@gmail.com>
Alexander Lourier <aml@rulezz.ru>
+Alexander Melentyev <alexander@melentyev.org>
Alexander Menzhinsky <amenzhinsky@gmail.com>
Alexander Morozov <lk4d4math@gmail.com>
Alexander Neumann <alexander@bumpern.de>
@@ -145,6 +147,7 @@
Alexander Rakoczy <alex@golang.org>
Alexander Reece <awreece@gmail.com>
Alexander Surma <surma@surmair.de>
+Alexander Yastrebov <yastrebov.alex@gmail.com>
Alexander Zhavnerchik <alex.vizor@gmail.com>
Alexander Zillion <alex@alexzillion.com>
Alexander Zolotov <goldifit@gmail.com>
@@ -179,6 +182,7 @@
Alwin Doss <alwindoss84@gmail.com>
Aman Gupta <aman@tmm1.net>
Amarjeet Anand <amarjeetanandsingh@gmail.com>
+Amelia Downs <adowns@vmware.com>
Amir Mohammad Saied <amir@gluegadget.com>
Amit Kumar <mittalmailbox@gmail.com>
Amr Mohammed <merodiro@gmail.com>
@@ -191,6 +195,7 @@
Anders Pearson <anders@columbia.edu>
Anderson Queiroz <contato@andersonq.eti.br>
André Carvalho <asantostc@gmail.com>
+Andre Marianiello <andremarianiello@users.noreply.github.com>
André Martins <aanm90@gmail.com>
Andre Nathan <andrenth@gmail.com>
Andrea Nodari <andrea.nodari91@gmail.com>
@@ -221,6 +226,7 @@
Andrew Harding <andrew@spacemonkey.com>
Andrew Jackura <ajackura@google.com>
Andrew Kemm <andrewkemm@gmail.com>
+Andrew LeFevre <capnspacehook@gmail.com>
Andrew Louis <alouis@digitalocean.com>
Andrew Lutomirski <andy@luto.us>
Andrew Medvedev <andrew.y.medvedev@gmail.com>
@@ -234,6 +240,7 @@
Andrew Stribblehill <ads@wompom.org>
Andrew Szeto <andrew@jabagawee.com>
Andrew Todd <andrew.todd@wework.com>
+Andrew Wansink <wansink@uber.com>
Andrew Werner <andrew@upthere.com> <awerner32@gmail.com>
Andrew Wilkins <axwalk@gmail.com>
Andrew Williams <williams.andrew@gmail.com>
@@ -283,6 +290,7 @@
Antonio Garcia <garcia.olais@gmail.com>
Antonio Huete Jimenez <tuxillo@quantumachine.net>
Antonio Murdaca <runcom@redhat.com>
+Antonio Ojea <antonio.ojea.garcia@gmail.com>
Antonio Troina <thoeni@gmail.com>
Anze Kolar <me@akolar.com>
Aofei Sheng <aofei@aofeisheng.com>
@@ -290,6 +298,7 @@
Aram Hăvărneanu <aram@mgk.ro>
Araragi Hokuto <kanseihonbucho@protonmail.com>
Arash Bina <arash@arash.io>
+Archana Ravindar <aravind5@in.ibm.com>
Arda Güçlü <ardaguclu@gmail.com>
Areski Belaid <areski@gmail.com>
Ariel Mashraki <ariel@mashraki.co.il>
@@ -299,6 +308,7 @@
Arne Hormann <arnehormann@gmail.com>
Arnout Engelen <arnout@bzzt.net>
Aron Nopanen <aron.nopanen@gmail.com>
+Arran Walker <arran.walker@fiveturns.org>
Artem Alekseev <artem.alekseev@intel.com>
Artem Khvastunov <artem.khvastunov@jetbrains.com>
Artem Kolin <artemkaxboy@gmail.com>
@@ -337,6 +347,7 @@
Balazs Lecz <leczb@google.com>
Baokun Lee <nototon@gmail.com> <bk@golangcn.org>
Barnaby Keene <accounts@southcla.ws>
+Bartłomiej Klimczak <bartlomiej.klimczak88@gmail.com>
Bartosz Grzybowski <melkorm@gmail.com>
Bartosz Oler <brtsz@google.com>
Bassam Ojeil <bojeil@google.com>
@@ -368,6 +379,7 @@
Benoit Sigoure <tsunanet@gmail.com>
Berengar Lehr <Berengar.Lehr@gmx.de>
Berkant Ipek <41230766+0xbkt@users.noreply.github.com>
+Beth Brown <ecbrown@google.com>
Bharath Kumar Uppala <uppala.bharath@gmail.com>
Bharath Thiruveedula <tbharath91@gmail.com>
Bhavin Gandhi <bhavin7392@gmail.com>
@@ -430,6 +442,7 @@
Brian Slesinsky <skybrian@google.com>
Brian Smith <ohohvi@gmail.com>
Brian Starke <brian.starke@gmail.com>
+Bruce Huang <helbingxxx@gmail.com>
Bryan Alexander <Kozical@msn.com>
Bryan Boreham <bjboreham@gmail.com>
Bryan C. Mills <bcmills@google.com>
@@ -482,17 +495,21 @@
Charles L. Dorian <cldorian@gmail.com>
Charles Lee <zombie.fml@gmail.com>
Charles Weill <weill@google.com>
+Charlie Getzen <charlie@bolt.com>
Charlie Moog <moogcharlie@gmail.com>
Charlotte Brandhorst-Satzkorn <catzkorn@gmail.com>
Chauncy Cullitan <chauncyc@google.com>
Chen Zhidong <njutczd@gmail.com>
Chen Zhihan <energiehund@gmail.com>
+Cheng Wang <wangchengiscool@gmail.com>
Cherry Mui <cherryyz@google.com>
Chew Choon Keat <choonkeat@gmail.com>
+Chia-Chi Hsu <wuchi5457@gmail.com>
Chiawen Chen <golopot@gmail.com>
Chirag Sukhala <cchirag77@gmail.com>
Cholerae Hu <choleraehyq@gmail.com>
Chotepud Teo <AlexRouSg@users.noreply.github.com>
+Chressie Himpel <chressie@google.com>
Chris Ball <chris@printf.net>
Chris Biscardi <chris@christopherbiscardi.com>
Chris Broadfoot <cbro@golang.org>
@@ -570,6 +587,7 @@
Curtis La Graff <curtis@lagraff.me>
Cyrill Schumacher <cyrill@schumacher.fm>
Dai Jie <gzdaijie@gmail.com>
+Dai Wentao <dwt136@gmail.com>
Daisuke Fujita <dtanshi45@gmail.com>
Daisuke Suzuki <daisuzu@gmail.com>
Daker Fernandes Pinheiro <daker.fernandes.pinheiro@intel.com>
@@ -603,6 +621,7 @@
Daniel Lidén <daniel.liden.87@gmail.com>
Daniel Lublin <daniel@lublin.se>
Daniel Mangum <georgedanielmangum@gmail.com>
+Daniel Marshall <daniel.marshall2@ibm.com>
Daniel Martí <mvdan@mvdan.cc>
Daniel McCarney <cpu@letsencrypt.org>
Daniel Morsing <daniel.morsing@gmail.com>
@@ -727,6 +746,7 @@
Dmitry Neverov <dmitry.neverov@gmail.com>
Dmitry Savintsev <dsavints@gmail.com>
Dmitry Yakunin <nonamezeil@gmail.com>
+Dmytro Shynkevych <dm.shynk@gmail.com>
Doga Fincan <doga@icloud.com>
Domas Tamašauskas <puerdomus@gmail.com>
Domen Ipavec <domen@ipavec.net>
@@ -751,6 +771,7 @@
Dustin Long <dustmop@gmail.com>
Dustin Sallings <dsallings@gmail.com>
Dustin Shields-Cloues <dcloues@gmail.com>
+Dustin Spicuzza <dustin.spicuzza@gmail.com>
Dvir Volk <dvir@everything.me> <dvirsky@gmail.com>
Dylan Waits <dylan@waits.io>
Ed Schouten <ed@nuxi.nl>
@@ -810,9 +831,11 @@
Ernest Chiang <ernest_chiang@htc.com>
Erwin Oegema <blablaechthema@hotmail.com>
Esko Luontola <esko.luontola@gmail.com>
+Ethan Anderson <eanderson@atlassian.com>
Ethan Burns <eaburns@google.com>
Ethan Hur <ethan0311@gmail.com>
Ethan Miller <eamiller@us.ibm.com>
+Ethan Reesor <ethan.reesor@gmail.com>
Euan Kemp <euank@euank.com>
Eugene Formanenko <mo4islona@gmail.com>
Eugene Kalinin <e.v.kalinin@gmail.com>
@@ -831,8 +854,10 @@
Ewan Chou <coocood@gmail.com>
Ewan Valentine <ewan.valentine89@gmail.com>
Eyal Posener <posener@gmail.com>
+F. Talha Altınel <talhaaltinel@hotmail.com>
Fabian Wickborn <fabian@wickborn.net>
Fabian Zaremba <fabian@youremail.eu>
+Fabio Falzoi <fabio.falzoi84@gmail.com>
Fabrizio Milo <mistobaan@gmail.com>
Faiyaz Ahmed <ahmedf@vmware.com>
Fan Hongjian <fan.howard@gmail.com>
@@ -861,21 +886,25 @@
Florian Forster <octo@google.com>
Florian Uekermann <florian@uekermann-online.de> <f1@uekermann-online.de>
Florian Weimer <fw@deneb.enyo.de>
+Florin Papa <fpapa@google.com>
Florin Patan <florinpatan@gmail.com>
Folke Behrens <folke@google.com>
Ford Hurley <ford.hurley@gmail.com>
+Forest Johnson <forest.n.johnson@gmail.com>
Francesc Campoy <campoy@golang.org>
Francesco Guardiani <francescoguard@gmail.com>
Francesco Renzi <rentziass@gmail.com>
Francisco Claude <fclaude@recoded.cl>
Francisco Rojas <francisco.rojas.gallegos@gmail.com>
Francisco Souza <franciscossouza@gmail.com>
+Frank Chiarulli Jr <frank@frankchiarulli.com>
Frank Schroeder <frank.schroeder@gmail.com>
Frank Somers <fsomers@arista.com>
Frederic Guillot <frederic.guillot@gmail.com>
Frederick Kelly Mayle III <frederickmayle@gmail.com>
Frederik Ring <frederik.ring@gmail.com>
Frederik Zipp <fzipp@gmx.de>
+Frediano Ziglio <freddy77@gmail.com>
Fredrik Enestad <fredrik.enestad@soundtrackyourbrand.com>
Fredrik Forsmo <fredrik.forsmo@gmail.com>
Fredrik Wallgren <fredrik.wallgren@gmail.com>
@@ -914,6 +943,7 @@
Georg Reinke <guelfey@gmail.com>
George Gkirtsou <ggirtsou@gmail.com>
George Hartzell <hartzell@alerce.com>
+George Looshch <looshch@loosh.ch>
George Shammas <george@shamm.as> <georgyo@gmail.com>
George Tsilias <tsiliasg@gmail.com>
Gerasimos (Makis) Maropoulos <kataras2006@hotmail.com>
@@ -954,19 +984,27 @@
GitHub User @frennkie (6499251) <mail@rhab.de>
GitHub User @geedchin (11672310) <geedchin@gmail.com>
GitHub User @GrigoriyMikhalkin (3637857) <grigoriymikhalkin@gmail.com>
+GitHub User @Gusted (25481501) <williamzijl7@hotmail.com>
GitHub User @hengwu0 (41297446) <41297446+hengwu0@users.noreply.github.com>
GitHub User @hitzhangjie (3725760) <hit.zhangjie@gmail.com>
+GitHub User @hkhere (33268704) <33268704+hkhere@users.noreply.github.com>
+GitHub User @hopehook (7326168) <hopehook.com@gmail.com>
GitHub User @hqpko (13887251) <whaibin01@hotmail.com>
+GitHub User @Illirgway (5428603) <illirgway@gmail.com>
GitHub User @itchyny (375258) <itchyny@hatena.ne.jp>
GitHub User @jinmiaoluo (39730824) <jinmiaoluo@icloud.com>
GitHub User @jopbrown (6345470) <msshane2008@gmail.com>
GitHub User @kazyshr (30496953) <kazyshr0301@gmail.com>
GitHub User @kc1212 (1093806) <kc1212@users.noreply.github.com>
GitHub User @komisan19 (18901496) <komiyama6219@gmail.com>
+GitHub User @korzhao (64203902) <korzhao95@gmail.com>
GitHub User @Kropekk (13366453) <kamilkropiewnicki@gmail.com>
+GitHub User @lgbgbl (65756378) <lgbgbl@qq.com>
GitHub User @lhl2617 (33488131) <l.h.lee2617@gmail.com>
GitHub User @linguohua (3434367) <lghchinaidea@gmail.com>
+GitHub User @lloydchang (1329685) <lloydchang@gmail.com>
GitHub User @LotusFenn (13775899) <fenn.lotus@gmail.com>
+GitHub User @luochuanhang (96416201) <chuanhangluo@gmail.com>
GitHub User @ly303550688 (11519839) <yang.liu636@gmail.com>
GitHub User @madiganz (18340029) <zacharywmadigan@gmail.com>
GitHub User @maltalex (10195391) <code@bit48.net>
@@ -976,6 +1014,7 @@
GitHub User @mkishere (224617) <224617+mkishere@users.noreply.github.com>
GitHub User @nu50218 (40682920) <nu_ll@icloud.com>
GitHub User @OlgaVlPetrova (44112727) <OVPpetrova@gmail.com>
+GitHub User @pierwill (19642016) <pierwill@users.noreply.github.com>
GitHub User @pityonline (438222) <pityonline@gmail.com>
GitHub User @po3rin (29445112) <abctail30@gmail.com>
GitHub User @pokutuna (57545) <popopopopokutuna@gmail.com>
@@ -983,13 +1022,18 @@
GitHub User @pytimer (17105586) <lixin20101023@gmail.com>
GitHub User @qcrao (7698088) <qcrao91@gmail.com>
GitHub User @ramenjuniti (32011829) <ramenjuniti@gmail.com>
+GitHub User @renthraysk (30576707) <renthraysk@gmail.com>
+GitHub User @roudkerk (52280478) <roudkerk@google.com>
GitHub User @saitarunreddy (21041941) <saitarunreddypalla@gmail.com>
GitHub User @SataQiu (9354727) <shidaqiu2018@gmail.com>
+GitHub User @seifchen (23326132) <chenxuefeng1207@gmail.com>
GitHub User @shogo-ma (9860598) <Choroma194@gmail.com>
GitHub User @sivchari (55221074) <shibuuuu5@gmail.com>
GitHub User @skanehira (7888591) <sho19921005@gmail.com>
GitHub User @soolaugust (10558124) <soolaugust@gmail.com>
GitHub User @surechen (7249331) <surechen17@gmail.com>
+GitHub User @syumai (6882878) <syumai@gmail.com>
+GitHub User @tangxi666 (48145175) <tx1275044634@gmail.com>
GitHub User @tatsumack (4510569) <tatsu.mack@gmail.com>
GitHub User @tell-k (26263) <ffk2005@gmail.com>
GitHub User @tennashi (10219626) <tennashio@gmail.com>
@@ -999,6 +1043,7 @@
GitHub User @uropek (39370426) <uropek@gmail.com>
GitHub User @utkarsh-extc (53217283) <utkarsh.extc@gmail.com>
GitHub User @witchard (4994659) <witchard@hotmail.co.uk>
+GitHub User @wmdngngng (22067700) <wangmingdong@gmail.com>
GitHub User @wolf1996 (5901874) <ksgiv37@gmail.com>
GitHub User @yah01 (12216890) <kagaminehuan@gmail.com>
GitHub User @yuanhh (1298735) <yuan415030@gmail.com>
@@ -1029,12 +1074,14 @@
Guilherme Goncalves <guilhermeaugustosg@gmail.com>
Guilherme Rezende <guilhermebr@gmail.com>
Guilherme Souza <32180229+gqgs@users.noreply.github.com>
+Guillaume Blaquiere <guillaume.blaquiere@gmail.com>
Guillaume J. Charmes <guillaume@charmes.net>
Guillaume Sottas <guillaumesottas@gmail.com>
Günther Noack <gnoack@google.com>
Guobiao Mei <meiguobiao@gmail.com>
Guodong Li <guodongli@google.com>
Guoliang Wang <iamwgliang@gmail.com>
+Guoqi Chen <chenguoqi@loongson.cn>
Gustav Paul <gustav.paul@gmail.com>
Gustav Westling <gustav@westling.xyz>
Gustavo Franco <gustavorfranco@gmail.com>
@@ -1050,6 +1097,8 @@
Hanjun Kim <hallazzang@gmail.com>
Hanlin He <hanling.he@gmail.com>
Hanlin Shi <shihanlin9@gmail.com>
+Hans Nielsen <hans@stackallocated.com>
+Hao Mou <mouhao.mu@gmail.com>
Haoran Luo <haoran.luo@chaitin.com>
Haosdent Huang <haosdent@gmail.com>
Harald Nordgren <haraldnordgren@gmail.com>
@@ -1126,6 +1175,7 @@
Ikko Ashimine <eltociear@gmail.com>
Illya Yalovyy <yalovoy@gmail.com>
Ilya Chukov <56119080+Elias506@users.noreply.github.com>
+Ilya Mateyko <me@astrophena.name>
Ilya Sinelnikov <sidhmangh@gmail.com>
Ilya Tocar <ilya.tocar@intel.com>
INADA Naoki <songofacandy@gmail.com>
@@ -1157,6 +1207,7 @@
Jaap Aarts <jaap.aarts1@gmail.com>
Jack Britton <jackxbritton@gmail.com>
Jack Lindamood <jlindamo@justin.tv>
+Jack You <jamesyou@google.com>
Jacob Baskin <jbaskin@google.com>
Jacob Blain Christen <dweomer5@gmail.com>
Jacob H. Haven <jacob@cloudflare.com>
@@ -1165,6 +1216,7 @@
Jaden Teng <long.asyn@gmail.com>
Jae Kwon <jae@tendermint.com>
Jake B <doogie1012@gmail.com>
+Jake Ciolek <jakub@ciolek.dev>
Jakob Borg <jakob@nym.se>
Jakob Weisblat <jakobw@mit.edu>
Jakub Čajka <jcajka@redhat.com>
@@ -1183,6 +1235,7 @@
James Fennell <jpfennell@google.com>
James Fysh <james.fysh@gmail.com>
James Gray <james@james4k.com>
+James Harris <mailjamesharris@gmail.com>
James Hartig <fastest963@gmail.com>
James Kasten <jdkasten@google.com>
James Lawrence <jljatone@gmail.com>
@@ -1246,6 +1299,7 @@
Jean-André Santoni <jean.andre.santoni@gmail.com>
Jean-François Bustarret <jf@bustarret.com>
Jean-Francois Cantin <jfcantin@gmail.com>
+Jean-Hadrien Chabran <jh@chabran.fr>
Jean-Marc Eurin <jmeurin@google.com>
Jean-Nicolas Moal <jn.moal@gmail.com>
Jed Denlea <jed@fastly.com>
@@ -1260,6 +1314,7 @@
Jeff R. Allen <jra@nella.org> <jeff.allen@gmail.com>
Jeff Sickel <jas@corpus-callosum.com>
Jeff Wendling <jeff@spacemonkey.com>
+Jeff Wentworth <j.wentworth@gmail.com>
Jeff Widman <jeff@jeffwidman.com>
Jeffrey H <jeffreyh192@gmail.com>
Jelte Fennema <github-tech@jeltef.nl>
@@ -1282,6 +1337,7 @@
Jia Zhan <jzhan@uber.com>
Jiacai Liu <jiacai2050@gmail.com>
Jiahao Lu <lujjjh@gmail.com>
+Jiahua Wang <wjh180909@gmail.com>
Jianing Yu <jnyu@google.com>
Jianqiao Li <jianqiaoli@google.com>
Jiayu Yi <yijiayu@gmail.com>
@@ -1298,10 +1354,12 @@
Jingguo Yao <yaojingguo@gmail.com>
Jingnan Si <jingnan.si@gmail.com>
Jinkun Zhang <franksnolf@gmail.com>
+Jinwen Wo <wojinwen@huawei.com>
Jiong Du <londevil@gmail.com>
Jirka Daněk <dnk@mail.muni.cz>
Jiulong Wang <jiulongw@gmail.com>
Joakim Sernbrant <serbaut@gmail.com>
+Jochen Weber <jochen.weber80@gmail.com>
Joe Bowbeer <joe.bowbeer@gmail.com>
Joe Cortopassi <joe@joecortopassi.com>
Joe Farrell <joe2farrell@gmail.com>
@@ -1324,6 +1382,7 @@
Johan Jansson <johan.jansson@iki.fi>
Johan Knutzen <johan@senri.se>
Johan Sageryd <j@1616.se>
+Johannes Altmanninger <aclopte@gmail.com>
Johannes Huning <johannes.huning@gmail.com>
John Asmuth <jasmuth@gmail.com>
John Bampton <jbampton@gmail.com>
@@ -1338,10 +1397,12 @@
John Jago <johnjago@protonmail.com>
John Jeffery <jjeffery@sp.com.au>
John Jenkins <twodopeshaggy@gmail.com>
+John Kelly <jkelly@squarespace.com>
John Leidegren <john.leidegren@gmail.com>
John McCabe <john@johnmccabe.net>
John Moore <johnkenneth.moore@gmail.com>
John Newlin <jnewlin@google.com>
+John Olheiser <john.olheiser@gmail.com>
John Papandriopoulos <jpap.code@gmail.com>
John Potocny <johnp@vividcortex.com>
John R. Lenton <jlenton@gmail.com>
@@ -1382,6 +1443,7 @@
Jordi Martin <jordimartin@gmail.com>
Jorge Araya <jorgejavieran@yahoo.com.mx>
Jorge L. Fatta <jorge.fatta@auth0.com>
+Jorge Troncoso <jatron@google.com>
Jos Visser <josv@google.com>
Josa Gesell <josa@gesell.me>
Jose Luis Vázquez González <josvazg@gmail.com>
@@ -1508,6 +1570,7 @@
Kezhu Wang <kezhuw@gmail.com>
Khosrow Moossavi <khos2ow@gmail.com>
Kieran Colford <kieran@kcolford.com>
+Kieran Gorman <kieran.j.gorman@gmail.com>
Kim Shrier <kshrier@racktopsystems.com>
Kim Yongbin <kybinz@gmail.com>
Kir Kolyshkin <kolyshkin@gmail.com>
@@ -1577,6 +1640,7 @@
Lev Shamardin <shamardin@gmail.com>
Lewin Bormann <lewin.bormann@gmail.com>
Lewis Waddicor <nemesismk2@gmail.com>
+Li-Yu Yu <aaronyu@google.com>
Liam Haworth <liam@haworth.id.au>
Lily Chung <lilithkchung@gmail.com>
Lingchao Xin <douglarek@gmail.com>
@@ -1657,7 +1721,9 @@
Mark Bucciarelli <mkbucc@gmail.com>
Mark Dain <mark@markdain.net>
Mark Glines <mark@glines.org>
+Mark Hansen <markhansen@google.com>
Mark Harrison <marhar@google.com>
+Mark Jeffery <dandare100@gmail.com>
Mark Percival <m@mdp.im>
Mark Pulford <mark@kyne.com.au>
Mark Rushakoff <mark.rushakoff@gmail.com>
@@ -1686,7 +1752,7 @@
Martin Kreichgauer <martinkr@google.com>
Martin Kunc <martinkunc@users.noreply.github.com>
Martin Lindhe <martin.j.lindhe@gmail.com>
-Martin Möhrmann <moehrmann@google.com> <martisch@uos.de>
+Martin Möhrmann <martin@golang.org> <moehrmann@google.com> <martisch@uos.de>
Martin Neubauer <m.ne@gmx.net>
Martin Olsen <github.com@martinolsen.net>
Martin Olsson <martin@minimum.se>
@@ -1741,6 +1807,7 @@
Matthew Holt <Matthew.Holt+git@gmail.com>
Matthew Horsnell <matthew.horsnell@gmail.com>
Matthew Waters <mwwaters@gmail.com>
+Matthias Dötsch <matze@mdoetsch.de>
Matthias Frei <matthias.frei@inf.ethz.ch>
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
Matthieu Olivier <olivier.matthieu@gmail.com>
@@ -1814,6 +1881,7 @@
Michal Cierniak <cierniak@google.com>
Michał Derkacz <ziutek@lnet.pl>
Michal Franc <lam.michal.franc@gmail.com>
+Michal Hruby <michal@axiom.co>
Michał Łowicki <mlowicki@gmail.com>
Michal Pristas <michal.pristas@gmail.com>
Michal Rostecki <mrostecki@suse.de>
@@ -1844,6 +1912,7 @@
Mike Strosaker <strosake@us.ibm.com>
Mike Tsao <mike@sowbug.com>
Mike Wiacek <mjwiacek@google.com>
+Mikhail Faraponov <11322032+moredure@users.noreply.github.com>
Mikhail Fesenko <proggga@gmail.com>
Mikhail Gusarov <dottedmag@dottedmag.net>
Mikhail Panchenko <m@mihasya.com>
@@ -1870,6 +1939,7 @@
Moriyoshi Koizumi <mozo@mozo.jp>
Morten Siebuhr <sbhr@sbhr.dk>
Môshe van der Sterre <moshevds@gmail.com>
+Mostafa Solati <mostafa.solati@gmail.com>
Mostyn Bramley-Moore <mostyn@antipode.se>
Mrunal Patel <mrunalp@gmail.com>
Muhammad Falak R Wani <falakreyaz@gmail.com>
@@ -1927,6 +1997,7 @@
Nick Patavalis <nick.patavalis@gmail.com>
Nick Petroni <npetroni@cs.umd.edu>
Nick Robinson <nrobinson13@gmail.com>
+Nick Sherron <nsherron90@gmail.com>
Nick Smolin <nick27surgut@gmail.com>
Nicolas BRULEZ <n.brulez@gmail.com>
Nicolas Kaiser <nikai@nikai.net>
@@ -1956,6 +2027,7 @@
Noble Johnson <noblepoly@gmail.com>
Nodir Turakulov <nodir@google.com>
Noel Georgi <git@frezbo.com>
+Nooras Saba <saba@golang.org>
Norberto Lopes <nlopes.ml@gmail.com>
Norman B. Lancaster <qbradq@gmail.com>
Nuno Cruces <ncruces@users.noreply.github.com>
@@ -1973,6 +2045,7 @@
Oliver Tonnhofer <olt@bogosoft.com>
Olivier Antoine <olivier.antoine@gmail.com>
Olivier Duperray <duperray.olivier@gmail.com>
+Olivier Mengué <olivier.mengue@gmail.com>
Olivier Poitrey <rs@dailymotion.com>
Olivier Saingre <osaingre@gmail.com>
Olivier Wulveryck <olivier.wulveryck@gmail.com>
@@ -1982,6 +2055,7 @@
Ori Rawlings <orirawlings@gmail.com>
Oryan Moshe <iamoryanmoshe@gmail.com>
Osamu TONOMORI <osamingo@gmail.com>
+Oscar Söderlund <oscar.soderlund@einride.tech>
Özgür Kesim <oec-go@kesim.org>
Pablo Caderno <kaderno@gmail.com>
Pablo Lalloni <plalloni@gmail.com>
@@ -2014,6 +2088,7 @@
Patrick Riley <pfr@google.com>
Patrick Smith <pat42smith@gmail.com>
Patrik Lundin <patrik@sigterm.se>
+Patrik Nyblom <pnyb@google.com>
Paul A Querna <paul.querna@gmail.com>
Paul Borman <borman@google.com>
Paul Boyd <boyd.paul2@gmail.com>
@@ -2042,6 +2117,7 @@
Paulo Casaretto <pcasaretto@gmail.com>
Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
Paulo Gomes <paulo.gomes.uk@gmail.com>
+Pavel Kositsyn <kositsyn.pa@phystech.edu>
Pavel Paulau <pavel.paulau@gmail.com>
Pavel Watson <watsonpavel@gmail.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
@@ -2049,6 +2125,7 @@
Pawel Knap <pawelknap88@gmail.com>
Pawel Szczur <filemon@google.com>
Paweł Szulik <pawel.szulik@intel.com>
+Pedro Lopez Mareque <pedro.lopez.mareque@gmail.com>
Pei Xian Chee <luciolas1991@gmail.com>
Pei-Ming Wu <p408865@gmail.com>
Pen Tree <appletree2479@outlook.com>
@@ -2164,6 +2241,7 @@
Ricardo Padilha <ricardospadilha@gmail.com>
Ricardo Pchevuzinske Katz <ricardo.katz@serpro.gov.br>
Ricardo Seriani <ricardo.seriani@gmail.com>
+Rich Hong <hong.rich@gmail.com>
Richard Barnes <rlb@ipv.sx>
Richard Crowley <r@rcrowley.org>
Richard Dingwall <rdingwall@gmail.com>
@@ -2179,6 +2257,7 @@
Rick Sayre <whorfin@gmail.com>
Rijnard van Tonder <rvantonder@gmail.com>
Riku Voipio <riku.voipio@linaro.org>
+Riley Avron <ra.git@posteo.net>
Risto Jaakko Saarelma <rsaarelm@gmail.com>
Rob Earhart <earhart@google.com>
Rob Findley <rfindley@google.com>
@@ -2186,8 +2265,10 @@
Rob Phoenix <rob@robphoenix.com>
Rob Pike <r@golang.org>
Robert Ayrapetyan <robert.ayrapetyan@gmail.com>
+Robert Burke <rebo@google.com>
Robert Daniel Kortschak <dan.kortschak@adelaide.edu.au> <dan@kortschak.io>
Robert Dinu <r@varp.se>
+Robert Engels <rengels@ix.netcom.com>
Robert Figueiredo <robfig@gmail.com>
Robert Griesemer <gri@golang.org>
Robert Hencke <robert.hencke@gmail.com>
@@ -2212,6 +2293,7 @@
Rohan Challa <rohan@golang.org>
Rohan Verma <rohanverma2004@gmail.com>
Rohith Ravi <entombedvirus@gmail.com>
+Roi Martin <jroi.martin@gmail.com>
Roland Illig <roland.illig@gmx.de>
Roland Shoemaker <rolandshoemaker@gmail.com>
Romain Baugue <romain.baugue@elwinar.com>
@@ -2242,6 +2324,7 @@
Ryan Dahl <ry@tinyclouds.org>
Ryan Hitchman <hitchmanr@gmail.com>
Ryan Kohler <ryankohler@google.com>
+Ryan Leung <rleungx@gmail.com>
Ryan Lower <rpjlower@gmail.com>
Ryan Roden-Corrent <ryan@rcorre.net>
Ryan Seys <ryan@ryanseys.com>
@@ -2275,6 +2358,7 @@
Samuel Kelemen <SCKelemen@users.noreply.github.com>
Samuel Tan <samueltan@google.com>
Samuele Pedroni <pedronis@lucediurna.net>
+San Ye <xyesan@gmail.com>
Sander van Harmelen <sander@vanharmelen.nl>
Sanjay Menakuru <balasanjay@gmail.com>
Santhosh Kumar Tekuri <santhosh.tekuri@gmail.com>
@@ -2339,6 +2423,7 @@
Shahar Kohanim <skohanim@gmail.com>
Shailesh Suryawanshi <ss.shailesh28@gmail.com>
Shamil Garatuev <garatuev@gmail.com>
+Shamim Akhtar <shamim.rhce@gmail.com>
Shane Hansen <shanemhansen@gmail.com>
Shang Jian Ding <sding3@ncsu.edu>
Shaozhen Ding <dsz0111@gmail.com>
@@ -2375,6 +2460,7 @@
Simon Ferquel <simon.ferquel@docker.com>
Simon Frei <freisim93@gmail.com>
Simon Jefford <simon.jefford@gmail.com>
+Simon Law <sfllaw@sfllaw.ca>
Simon Rawet <simon@rawet.se>
Simon Rozman <simon@rozman.si>
Simon Ser <contact@emersion.fr>
@@ -2440,6 +2526,7 @@
Sukrit Handa <sukrit.handa@utoronto.ca>
Sunny <me@darkowlzz.space>
Suriyaa Sundararuban <suriyaasundararuban@gmail.com>
+Suvaditya Sur <suvaditya.sur@gmail.com>
Suyash <dextrous93@gmail.com>
Suzy Mueller <suzmue@golang.org>
Sven Almgren <sven@tras.se>
@@ -2502,6 +2589,7 @@
Thomas Wanielista <tomwans@gmail.com>
Thorben Krueger <thorben.krueger@gmail.com>
Thordur Bjornsson <thorduri@secnorth.net>
+Tiago Peczenyj <tpeczenyj@weborama.com>
Tiago Queiroz <contato@tiago.eti.br>
Tianji Wu <the729@gmail.com>
Tianon Gravi <admwiggin@gmail.com>
@@ -2636,6 +2724,7 @@
Vojtech Bocek <vbocek@gmail.com>
Volker Dobler <dr.volker.dobler@gmail.com>
Volodymyr Paprotski <vpaprots@ca.ibm.com>
+Vyacheslav Pachkov <slava.pach@gmail.com>
W. Trevor King <wking@tremily.us>
Wade Simmons <wade@wades.im>
Wagner Riffel <wgrriffel@gmail.com>
@@ -2653,6 +2742,7 @@
Wei Xiao <wei.xiao@arm.com>
Wei Xikai <xykwei@gmail.com>
Weichao Tang <tevic.tt@gmail.com>
+Weilu Jia <optix2000@gmail.com>
Weixie Cui <cuiweixie@gmail.com> <523516579@qq.com>
Wembley G. Leach, Jr <wembley.gl@gmail.com>
Wenlei (Frank) He <wlhe@google.com>
@@ -2722,9 +2812,11 @@
Yuji Yaginuma <yuuji.yaginuma@gmail.com>
Yuki Ito <mrno110y@gmail.com>
Yuki OKUSHI <huyuumi.dev@gmail.com>
+Yuki Osaki <yuki.osaki7@gmail.com>
Yuki Yugui Sonoda <yugui@google.com>
Yukihiro Nishinaka <6elpinal@gmail.com>
YunQiang Su <syq@debian.org>
+Yuntao Wang <ytcoode@gmail.com>
Yury Smolsky <yury@smolsky.by>
Yusuke Kagiwada <block.rxckin.beats@gmail.com>
Yuusei Kuwana <kuwana@kumama.org>
@@ -2736,7 +2828,9 @@
Zach Hoffman <zrhoffman@apache.org>
Zach Jones <zachj1@gmail.com>
Zachary Amsden <zach@thundertoken.com>
+Zachary Burkett <zburkett@splitcubestudios.com>
Zachary Gershman <zgershman@pivotal.io>
+Zaiyang Li <zaiyangli777@gmail.com>
Zak <zrjknill@gmail.com>
Zakatell Kanda <hi@zkanda.io>
Zellyn Hunter <zellyn@squareup.com> <zellyn@gmail.com>
@@ -2745,6 +2839,7 @@
Zheng Dayu <davidzheng23@gmail.com>
Zheng Xu <zheng.xu@arm.com>
Zhengyu He <hzy@google.com>
+Zhi Zheng <zhi.zheng052@gmail.com>
Zhongpeng Lin <zplin@uber.com>
Zhongtao Chen <chenzhongtao@126.com>
Zhongwei Yao <zhongwei.yao@arm.com>
diff --git a/VERSION b/VERSION
index c0e2167..54ba52e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-go1.18beta1
\ No newline at end of file
+go1.18
\ No newline at end of file
diff --git a/api/go1.18.txt b/api/go1.18.txt
index afcb31c..0f3e26d 100644
--- a/api/go1.18.txt
+++ b/api/go1.18.txt
@@ -1,18 +1,14 @@
pkg bufio, method (*Writer) AvailableBuffer() []uint8
pkg bufio, method (ReadWriter) AvailableBuffer() []uint8
pkg bytes, func Cut([]uint8, []uint8) ([]uint8, []uint8, bool)
-pkg constraints, type Complex interface {}
-pkg constraints, type Float interface {}
-pkg constraints, type Integer interface {}
-pkg constraints, type Ordered interface {}
-pkg constraints, type Signed interface {}
-pkg constraints, type Unsigned interface {}
pkg crypto/tls, method (*Conn) NetConn() net.Conn
pkg debug/buildinfo, func Read(io.ReaderAt) (*debug.BuildInfo, error)
pkg debug/buildinfo, func ReadFile(string) (*debug.BuildInfo, error)
pkg debug/buildinfo, type BuildInfo = debug.BuildInfo
pkg debug/elf, const R_PPC64_RELATIVE = 22
pkg debug/elf, const R_PPC64_RELATIVE R_PPC64
+pkg debug/dwarf, type BasicType struct, DataBitOffset int64
+pkg debug/dwarf, type StructField struct, DataBitOffset int64
pkg debug/plan9obj, var ErrNoSymbols error
pkg go/ast, method (*IndexListExpr) End() token.Pos
pkg go/ast, method (*IndexListExpr) Pos() token.Pos
@@ -49,7 +45,6 @@
pkg go/types, method (*Term) Type() Type
pkg go/types, method (*TypeList) At(int) Type
pkg go/types, method (*TypeList) Len() int
-pkg go/types, method (*TypeList) String() string
pkg go/types, method (*TypeParam) Constraint() Type
pkg go/types, method (*TypeParam) Index() int
pkg go/types, method (*TypeParam) Obj() *TypeName
@@ -170,8 +165,8 @@
pkg reflect, method (Value) SetIterKey(*MapIter)
pkg reflect, method (Value) SetIterValue(*MapIter)
pkg reflect, method (Value) UnsafePointer() unsafe.Pointer
-pkg runtime/debug, method (*BuildInfo) MarshalText() ([]uint8, error)
-pkg runtime/debug, method (*BuildInfo) UnmarshalText([]uint8) error
+pkg runtime/debug, func ParseBuildInfo(string) (*BuildInfo, error)
+pkg runtime/debug, method (*BuildInfo) String() string
pkg runtime/debug, type BuildInfo struct, GoVersion string
pkg runtime/debug, type BuildInfo struct, Settings []BuildSetting
pkg runtime/debug, type BuildSetting struct
diff --git a/bin/go b/bin/go
index bca6d2f..e286e0e 100755
--- a/bin/go
+++ b/bin/go
Binary files differ
diff --git a/bin/gofmt b/bin/gofmt
index 4ed6cdc..f5992f3 100755
--- a/bin/gofmt
+++ b/bin/gofmt
Binary files differ
diff --git a/codereview.cfg b/codereview.cfg
index 77a74f1..ff39018 100644
--- a/codereview.cfg
+++ b/codereview.cfg
@@ -1 +1,2 @@
-branch: master
+branch: release-branch.go1.18
+parent-branch: master
diff --git a/doc/go1.18.html b/doc/go1.18.html
index 5ab4028..b320579 100644
--- a/doc/go1.18.html
+++ b/doc/go1.18.html
@@ -32,17 +32,32 @@
<a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md">Type
Parameters Proposal</a>.
This includes major - but fully backward-compatible - changes to the language.
+</p>
+
+<p>
+ These new language changes required a large amount of new code that
+ has not had significant testing in production settings. That will
+ only happen as more people write and use generic code. We believe
+ that this feature is well implemented and high quality. However,
+ unlike most aspects of Go, we can't back up that belief with real
+ world experience. Therefore, while we encourage the use of generics
+ where it makes sense, please use appropriate caution when deploying
+ generic code in production.
+</p>
+
+<p>
The following is a list of the most visible changes. For a more comprehensive overview, see the
<a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md">proposal</a>.
- For details see the <a href="https://golang.org/ref/spec">language spec</a>.
+ For details see the <a href="/ref/spec">language spec</a>.
</p>
+
<ul>
<li>
The syntax for
- <a href="https://golang.org/ref/spec#Function_declarations">Function</a> and
- <a href="https://golang.org/ref/spec#Type_declarations">type declarations</a>
+ <a href="/ref/spec#Function_declarations">function</a> and
+ <a href="/ref/spec#Type_declarations">type declarations</a>
now accepts
- <a href="https://golang.org/ref/spec#Type_parameters">type parameters</a>.
+ <a href="/ref/spec#Type_parameters">type parameters</a>.
</li>
<li>
Parameterized functions and types can be instantiated by following them with a list of
@@ -50,11 +65,11 @@
</li>
<li>
The new token <code>~</code> has been added to the set of
- <a href="https://golang.org/ref/spec#Operators_and_punctuation">operators and punctuation</a>.
+ <a href="/ref/spec#Operators_and_punctuation">operators and punctuation</a>.
</li>
<li>
The syntax for
- <a href="https://golang.org/ref/spec#Interface_types">Interface types</a>
+ <a href="/ref/spec#Interface_types">Interface types</a>
now permits the embedding of arbitrary types (not just type names of interfaces)
as well as union and <code>~T</code> type elements. Such interfaces may only be used
as type constraints.
@@ -62,26 +77,85 @@
</li>
<li>
The new
- <a href="https://golang.org/ref/spec#Predeclared_identifiers">predeclared identifier</a>
+ <a href="/ref/spec#Predeclared_identifiers">predeclared identifier</a>
<code>any</code> is an alias for the empty interface. It may be used instead of
<code>interface{}</code>.
</li>
<li>
The new
- <a href="https://golang.org/ref/spec#Predeclared_identifiers">predeclared identifier</a>
- <code>comparable</code> is an interface the denotes the set of all types which can be
+ <a href="/ref/spec#Predeclared_identifiers">predeclared identifier</a>
+ <code>comparable</code> is an interface that denotes the set of all types which can be
compared using <code>==</code> or <code>!=</code>. It may only be used as (or embedded in)
a type constraint.
</li>
</ul>
<p>
+ There are three experimental packages using generics that may be
+ useful.
+ These packages are in x/exp repository; their API is not covered by
+ the Go 1 guarantee and may change as we gain more experience with
+ generics.
+ <dl>
+ <dt><a href="https://pkg.go.dev/golang.org/x/exp/constraints"><code>golang.org/x/exp/constraints</code></a></dt>
+ <dd>
+ <p>
+ Constraints that are useful for generic code, such as
+ <a href="https://pkg.go.dev/golang.org/x/exp/constraints#Ordered"><code>constraints.Ordered</code></a>.
+ </p>
+ </dd>
+
+ <dt><a href="https://pkg.go.dev/golang.org/x/exp/slices"><code>golang.org/x/exp/slices</code></a></dt>
+ <dd>
+ <p>
+ A collection of generic functions that operate on slices of
+ any element type.
+ </p>
+ </dd>
+
+ <dt><a href="https://pkg.go.dev/golang.org/x/exp/maps"><code>golang.org/x/exp/maps</code></a></dt>
+ <dd>
+ <p>
+ A collection of generic functions that operate on maps of
+ any key or element type.
+ </p>
+ </dd>
+ </dl>
+</p>
+
+<p>
The current generics implementation has the following limitations:
<ul>
<li><!-- https://golang.org/issue/47631 -->
The Go compiler cannot currently handle type declarations inside generic functions
or methods. We hope to provide support for this feature in Go 1.19.
</li>
+ <li><!-- https://golang.org/issue/50937 -->
+ The Go compiler currently does not accept arguments of type parameter type with
+ the predeclared functions <code>real</code>, <code>imag</code>, and <code>complex</code>.
+ We hope to remove this restriction in Go 1.19.
+ </li>
+ <li><!-- https://golang.org/issue/51183 -->
+ The Go compiler currently only supports calling a method <code>m</code> on a value
+ <code>x</code> of type parameter type <code>P</code> if <code>m</code> is explicitly
+ declared by <code>P</code>'s constraint interface.
+ Similarly, method values <code>x.m</code> and method expressions
+ <code>P.m</code> also are only supported if <code>m</code> is explicitly
+ declared by <code>P</code>, even though <code>m</code> might be in the method set
+ of <code>P</code> by virtue of the fact that all types in <code>P</code> implement
+ <code>m</code>. We hope to remove this restriction in Go 1.19.
+ </li>
+ <li><!-- https://golang.org/issue/49030 -->
+ Embedding a type parameter, or a pointer to a type parameter, as
+ an unnamed field in a struct type is not permitted. Similarly,
+ embedding a type parameter in an interface type is not permitted.
+ Whether these will ever be permitted is unclear at present.
+ </li>
+ <li>
+ A union element with more than one term may not contain an
+ interface type with a non-empty method set. Whether this will
+ ever be permitted is unclear at present.
+ </li>
</ul>
</p>
@@ -101,7 +175,7 @@
<p>
The Go 1.18 compiler now reports an overflow when passing a rune constant expression
- such as <code>'1' << 32</code> as an argument to the predeclared functions
+ such as <code>'1' << 32</code> as an argument to the predeclared functions
<code>print</code> and <code>println</code>, consistent with the behavior of
user-defined functions. Before Go 1.18, the compiler did not report an error
in such cases but silently accepted such constant arguments if they fit into an
@@ -117,11 +191,12 @@
<h3 id="amd64">AMD64</h3>
<p><!-- CL 349595 -->
- Go 1.18 introduces the new <code>GOAMD64</code> environment variable which selects
- a version of the AMD64 architecture. Allowed values are <code>v1</code>,
+ Go 1.18 introduces the new <code>GOAMD64</code> environment variable, which selects at compile time
+ a minimum target version of the AMD64 architecture. Allowed values are <code>v1</code>,
<code>v2</code>, <code>v3</code>, or <code>v4</code>. Each higher level requires,
- and takes advantage of, additional processor features. A detailed description of the
- versions is <a href="https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels">here</a>.
+ and takes advantage of, additional processor features. A detailed
+ description can be found
+ <a href="https://golang.org/wiki/MinimumRequirements#amd64">here</a>.
</p>
<p>
The <code>GOAMD64</code> environment variable defaults to <code>v1</code>.
@@ -134,6 +209,12 @@
now supports the <code>c-archive</code> and <code>c-shared</code> build modes.
</p>
+<h3 id="linux">Linux</h3>
+
+<p><!-- golang.org/issue/45964 -->
+ Go 1.18 requires Linux kernel version 2.6.32 or later.
+</p>
+
<h3 id="windows">Windows</h3>
<p><!-- https://golang.org/issue/49759 -->
@@ -185,6 +266,8 @@
<h3 id="go-command">Go command</h3>
+<h4 id="go-get"><code>go</code> <code>get</code></h4>
+
<p><!-- golang.org/issue/43684 -->
<code>go</code> <code>get</code> no longer builds or installs packages in
module-aware mode. <code>go</code> <code>get</code> is now dedicated to
@@ -204,9 +287,25 @@
and installs packages, as before.
</p>
+<h4 id="go-mod-updates">Automatic <code>go.mod</code> and <code>go.sum</code> updates</h4>
+
+<p><!-- https://go.dev/issue/45551 -->
+ The <code>go</code> <code>mod</code> <code>graph</code>,
+ <code>go</code> <code>mod</code> <code>vendor</code>,
+ <code>go</code> <code>mod</code> <code>verify</code>, and
+ <code>go</code> <code>mod</code> <code>why</code> subcommands
+ no longer automatically update the <code>go.mod</code> and
+ <code>go.sum</code> files.
+ (Those files can be updated explicitly using <code>go</code> <code>get</code>,
+ <code>go</code> <code>mod</code> <code>tidy</code>, or
+ <code>go</code> <code>mod</code> <code>download</code>.)
+</p>
+
+<h4 id="go-version"><code>go</code> <code>version</code></h4>
+
<p><!-- golang.org/issue/37475 -->
The <code>go</code> command now embeds version control information in
- binaries including the currently checked-out revision, commit time, and a
+ binaries. It includes the currently checked-out revision, commit time, and a
flag indicating whether edited or untracked files are present. Version
control information is embedded if the <code>go</code> command is invoked in
a directory within a Git, Mercurial, Fossil, or Bazaar repository, and the
@@ -216,19 +315,30 @@
</p>
<p><!-- golang.org/issue/37475 -->
- Additionally, the <code>go</code> command embeds information about the build
+ Additionally, the <code>go</code> command embeds information about the build,
including build and tool tags (set with <code>-tags</code>), compiler,
assembler, and linker flags (like <code>-gcflags</code>), whether cgo was
enabled, and if it was, the values of the cgo environment variables
- (like <code>CGO_CFLAGS</code>). This information may be omitted using the
- flag <code>-buildinfo=false</code>. Both VCS and build information may be
- read together with module information using <code>go</code>
- <code>version</code> <code>-m</code> <code>file</code> or
+ (like <code>CGO_CFLAGS</code>).
+ Both VCS and build information may be read together with module
+ information using
+ <code>go</code> <code>version</code> <code>-m</code> <code>file</code> or
<code>runtime/debug.ReadBuildInfo</code> (for the currently running binary)
or the new <a href="#debug/buildinfo"><code>debug/buildinfo</code></a>
package.
</p>
+<p><!-- CL 369977 -->
+ The underlying data format of the embedded build information can change with
+ new go releases, so an older version of <code>go</code> may not handle the
+ build information produced with a newer version of <code>go</code>.
+ To read the version information from a binary built with <code>go</code> 1.18,
+ use the <code>go</code> <code>version</code> command and the
+ <code>debug/buildinfo</code> package from <code>go</code> 1.18+.
+</p>
+
+<h4 id="go-mod-download"><code>go</code> <code>mod</code> <code>download</code></h4>
+
<p><!-- https://golang.org/issue/44435 -->
If the main module's <code>go.mod</code> file
specifies <a href="/ref/mod#go-mod-file-go"><code>go</code> <code>1.17</code></a>
@@ -242,6 +352,8 @@
<code>go</code> <code>mod</code> <code>download</code> <code>all</code>.
</p>
+<h4 id="go-mod-vendor"><code>go</code> <code>mod</code> <code>vendor</code></h4>
+
<p><!-- https://golang.org/issue/47327 -->
The <code>go</code> <code>mod</code> <code>vendor</code> subcommand now
supports a <code>-o</code> flag to set the output directory.
@@ -251,6 +363,35 @@
third-party tools that need to collect package source code.)
</p>
+<h4 id="go-mod-tidy"><code>go</code> <code>mod</code> <code>tidy</code></h4>
+
+<p><!-- https://golang.org/issue/47738, CL 344572 -->
+ The <code>go</code> <code>mod</code> <code>tidy</code> command now retains
+ additional checksums in the <code>go.sum</code> file for modules whose source
+ code is needed to verify that each imported package is provided by only one
+ module in the <a href="/ref/mod#glos-build-list">build list</a>. Because this
+ condition is rare and failure to apply it results in a build error, this
+ change is <em>not</em> conditioned on the <code>go</code> version in the main
+ module's <code>go.mod</code> file.
+</p>
+
+<h4 id="go-work"><code>go</code> <code>work</code></h4>
+
+<p><!-- https://golang.org/issue/45713 -->
+ The <code>go</code> command now supports a "Workspace" mode. If a
+ <code>go.work</code> file is found in the working directory or a
+ parent directory, or one is specified using the <code>GOWORK</code>
+ environment variable, it will put the <code>go</code> command into workspace mode.
+ In workspace mode, the <code>go.work</code> file will be used to
+ determine the set of main modules used as the roots for module
+ resolution, instead of using the normally-found <code>go.mod</code>
+ file to specify the single main module. For more information see the
+ <a href="/pkg/cmd/go#hdr-Workspace_maintenance"><code>go work</code></a>
+ documentation.
+</p>
+
+<h4 id="go-build-asan"><code>go</code> <code>build</code> <code>-asan</code></h4>
+
<p><!-- CL 298612 -->
The <code>go</code> <code>build</code> command and related commands
now support an <code>-asan</code> flag that enables interoperation
@@ -258,7 +399,51 @@
option <code>-fsanitize=address</code>).
</p>
-<h3 id="gofmt"><code>gofmt</code></h3>
+<h4 id="go-test"><code>go</code> <code>test</code></h4>
+
+<p><!-- CL 251441 -->
+ The <code>go</code> command now supports additional command line
+ options for the new <a href="#fuzzing">fuzzing support described
+ above</a>:
+ <ul>
+ <li>
+ <code>go test</code> supports
+ <code>-fuzz</code>, <code>-fuzztime</code>, and
+ <code>-fuzzminimizetime</code> options.
+ For documentation on these see
+ <a href="/pkg/cmd/go#hdr-Testing_flags"><code>go help testflag</code></a>.
+ </li>
+ <li>
+ <code>go clean</code> supports a <code>-fuzzcache</code>
+ option.
+ For documentation see
+ <a href="/pkg/cmd/go#hdr-Remove_object_files_and_cached_files"><code>go help clean</code></a>.
+ </li>
+ </ul>
+</p>
+
+<h4 id="go-build-lines"><code>//go:build</code> lines</h4>
+
+<p><!-- CL 240611 -->
+Go 1.17 introduced <code>//go:build</code> lines as a more readable way to write build constraints,
+instead of <code>//</code> <code>+build</code> lines.
+As of Go 1.17, <code>gofmt</code> adds <code>//go:build</code> lines
+to match existing <code>+build</code> lines and keeps them in sync,
+while <code>go</code> <code>vet</code> diagnoses when they are out of sync.
+</p>
+
+<p>Since the release of Go 1.18 marks the end of support for Go 1.16,
+all supported versions of Go now understand <code>//go:build</code> lines.
+In Go 1.18, <code>go</code> <code>fix</code> now removes the now-obsolete
+<code>//</code> <code>+build</code> lines in modules declaring
+<code>go</code> <code>1.17</code> or later in their <code>go.mod</code> files.
+</p>
+
+<p>
+For more information, see <a href="https://go.dev/design/draft-gobuild">https://go.dev/design/draft-gobuild</a>.
+</p>
+
+<h3 id="gofmt">Gofmt</h3>
<p><!-- https://golang.org/issue/43566 -->
<code>gofmt</code> now reads and formats input files concurrently, with a
@@ -266,7 +451,7 @@
multiple CPUs, <code>gofmt</code> should now be significantly faster.
</p>
-<h3 id="vet"><code>vet</code></h3>
+<h3 id="vet">Vet</h3>
<h4 id="vet-generics">Updates for Generics</h4>
@@ -354,10 +539,18 @@
</p>
<p><!-- CL 298611 -->
- The new compiler <code>-asan</code> option supports the
+ The new <code>-asan</code> compiler option supports the
new <code>go</code> command <code>-asan</code> option.
</p>
+<p><!-- https://golang.org/issue/50954 -->
+ Because the compiler's type checker was replaced in its entirety to
+ support generics, some error messages now may use different wording
+ than before. In some cases, pre-Go 1.18 error messages provided more
+ detail or were phrased in a more helpful way.
+ We intend to address these cases in Go 1.19.
+</p>
+
<p> <!-- https://github.com/golang/go/issues/49569 -->
Because of changes in the compiler related to supporting generics, the
Go 1.18 compile speed can be roughly 15% slower than the Go 1.17 compile speed.
@@ -367,19 +560,44 @@
<h2 id="linker">Linker</h2>
+<p>
+ The linker emits <a href="https://tailscale.com/blog/go-linker/">far fewer relocations</a>.
+ As a result, most codebases will link faster, require less memory to link,
+ and generate smaller binaries.
+ Tools that process Go binaries should use Go 1.18's <code>debug/gosym</code> package
+ to transparently handle both old and new binaries.
+</p>
+
<p><!-- CL 298610 -->
- The new linker <code>-asan</code> option supports the
+ The new <code>-asan</code> linker option supports the
new <code>go</code> command <code>-asan</code> option.
</p>
+<h2 id="bootstrap">Bootstrap</h2>
+
+<p><!-- CL 369914, CL 370274 -->
+When building a Go release from source and <code>GOROOT_BOOTSTRAP</code>
+is not set, previous versions of Go looked for a Go 1.4 or later bootstrap toolchain
+in the directory <code>$HOME/go1.4</code> (<code>%HOMEDRIVE%%HOMEPATH%\go1.4</code> on Windows).
+Go now looks first for <code>$HOME/go1.17</code> or <code>$HOME/sdk/go1.17</code>
+before falling back to <code>$HOME/go1.4</code>.
+We intend for Go 1.19 to require Go 1.17 or later for bootstrap,
+and this change should make the transition smoother.
+For more details, see <a href="https://go.dev/issue/44505">go.dev/issue/44505</a>.
+</p>
+
<h2 id="library">Core library</h2>
-<h3 id="constraints">New <code>constraints</code> package</h3>
+<h3 id="debug/buildinfo">New <code>debug/buildinfo</code> package</h3>
-<p><!-- CL 349709 -->
- The new <a href="/pkg/constraints/"><code>constraints</code></a> package
- defines a set of useful constraints that can be used with type parameters of
- generic functions.
+<p><!-- golang.org/issue/39301 -->
+ The new <a href="/pkg/debug/buildinfo"><code>debug/buildinfo</code></a> package
+ provides access to module versions, version control information, and build
+ flags embedded in executable files built by the <code>go</code> command.
+ The same information is also available via
+ <a href="/pkg/runtime/debug#ReadBuildInfo"><code>runtime/debug.ReadBuildInfo</code></a>
+ for the currently running binary and via <code>go</code>
+ <code>version</code> <code>-m</code> on the command line.
</p>
<h3 id="netip">New <code>net/netip</code> package</h3>
@@ -400,15 +618,78 @@
a network CIDR prefix.
</p>
<p>
+ The package also defines several functions to create and examine
+ these new types:
+ <a href="/pkg/net/netip#AddrFrom4"><code>AddrFrom4</code></a>,
+ <a href="/pkg/net/netip#AddrFrom16"><code>AddrFrom16</code></a>,
+ <a href="/pkg/net/netip#AddrFromSlice"><code>AddrFromSlice</code></a>,
+ <a href="/pkg/net/netip#AddrPortFrom"><code>AddrPortFrom</code></a>,
+ <a href="/pkg/net/netip#IPv4Unspecified"><code>IPv4Unspecified</code></a>,
+ <a href="/pkg/net/netip#IPv6LinkLocalAllNodes"><code>IPv6LinkLocalAllNodes</code></a>,
+ <a href="/pkg/net/netip#IPv6Unspecified"><code>IPv6Unspecified</code></a>,
+ <a href="/pkg/net/netip#MustParseAddr"><code>MustParseAddr</code></a>,
+ <a href="/pkg/net/netip#MustParseAddrPort"><code>MustParseAddrPort</code></a>,
+ <a href="/pkg/net/netip#MustParsePrefix"><code>MustParsePrefix</code></a>,
+ <a href="/pkg/net/netip#ParseAddr"><code>ParseAddr</code></a>,
+ <a href="/pkg/net/netip#ParseAddrPort"><code>ParseAddrPort</code></a>,
+ <a href="/pkg/net/netip#ParsePrefix"><code>ParsePrefix</code></a>,
+ <a href="/pkg/net/netip#PrefixFrom"><code>PrefixFrom</code></a>.
+</p>
+<p>
The <a href="/pkg/net/"><code>net</code></a> package includes new
methods that parallel existing methods, but
return <code>netip.AddrPort</code> instead of the
heavier-weight <a href="/pkg/net/#IP"><code>net.IP</code></a> or
- <a href="/pkg/net/#UDPAddr"<code>*net.UDPAddr</code></a> types.
+ <a href="/pkg/net/#UDPAddr"><code>*net.UDPAddr</code></a> types:
+ <a href="/pkg/net/#Resolver.LookupNetIP"><code>Resolver.LookupNetIP</code></a>,
+ <a href="/pkg/net/#UDPConn.ReadFromUDPAddrPort"><code>UDPConn.ReadFromUDPAddrPort</code></a>,
+ <a href="/pkg/net/#UDPConn.ReadMsgUDPAddrPort"><code>UDPConn.ReadMsgUDPAddrPort</code></a>,
+ <a href="/pkg/net/#UDPConn.WriteToUDPAddrPort"><code>UDPConn.WriteToUDPAddrPort</code></a>,
+ <a href="/pkg/net/#UDPConn.WriteMsgUDPAddrPort"><code>UDPConn.WriteMsgUDPAddrPort</code></a>.
+ The new <code>UDPConn</code> methods support allocation-free I/O.
+</p>
+<p>
The <code>net</code> package also now includes functions and methods
to convert between the existing
- <a href="/pkg/net/#TCPAddr"><code>TCPAddr</code>/<a href="/pkg/net/#UDPAddr"><code>UDPAddr</code>
- types and <code>netip.AddrPort</code>.
+ <a href="/pkg/net/#TCPAddr"><code>TCPAddr</code></a>/<a href="/pkg/net/#UDPAddr"><code>UDPAddr</code></a>
+ types and <code>netip.AddrPort</code>:
+ <a href="/pkg/net/#TCPAddrFromAddrPort"><code>TCPAddrFromAddrPort</code></a>,
+ <a href="/pkg/net/#UDPAddrFromAddrPort"><code>UDPAddrFromAddrPort</code></a>,
+ <a href="/pkg/net/#TCPAddr.AddrPort"><code>TCPAddr.AddrPort</code></a>,
+ <a href="/pkg/net/#UDPAddr.AddrPort"><code>UDPAddr.AddrPort</code></a>.
+</p>
+
+<h3 id="tls10">TLS 1.0 and 1.1 disabled by default client-side</h3>
+
+<p><!-- CL 359779, golang.org/issue/45428 -->
+ If <a href="/pkg/crypto/tls/#Config.MinVersion"><code>Config.MinVersion</code></a>
+ is not set, it now defaults to TLS 1.2 for client connections. Any safely
+ up-to-date server is expected to support TLS 1.2, and browsers have required
+ it since 2020. TLS 1.0 and 1.1 are still supported by setting
+ <code>Config.MinVersion</code> to <code>VersionTLS10</code>.
+ The server-side default is unchanged at TLS 1.0.
+</p>
+
+<p>
+ The default can be temporarily reverted to TLS 1.0 by setting the
+ <code>GODEBUG=tls10default=1</code> environment variable.
+ This option will be removed in Go 1.19.
+</p>
+
+<h3 id="sha1">Rejecting SHA-1 certificates</h3>
+
+<p><!-- CL 359777, golang.org/issue/41682 -->
+ <code>crypto/x509</code> will now
+ reject certificates signed with the SHA-1 hash function. This doesn't
+ apply to self-signed root certificates. Practical attacks against SHA-1
+ <a href="https://shattered.io/">have been demonstrated since 2017</a> and publicly
+ trusted Certificate Authorities have not issued SHA-1 certificates since 2015.
+</p>
+
+<p>
+ This can be temporarily reverted by setting the
+ <code>GODEBUG=x509sha1=1</code> environment variable.
+ This option will be removed in Go 1.19.
</p>
<h3 id="minor_library_changes">Minor changes to the library</h3>
@@ -425,12 +706,12 @@
The new <a href="/pkg/bufio#Writer.AvailableBuffer"><code>Writer.AvailableBuffer</code></a>
method returns an empty buffer with a possibly non-empty capacity for use
with append-like APIs. After appending, the buffer can be provided to a
- succeeding <code>Write</code> call and possibly avoid any copying.
+ succeeding <code>Write</code> call and possibly avoid any copying.
</p>
<p><!-- CL 345570 -->
- The methods <a href="/pkg/bufio#Reader.Reset"><code>Reader.Reset</code></a> and
- <a href="/pkg/bufio#Writer.Reset"><code>Writer.Reset</code></a>
+ The <a href="/pkg/bufio#Reader.Reset"><code>Reader.Reset</code></a> and
+ <a href="/pkg/bufio#Writer.Reset"><code>Writer.Reset</code></a> methods
now use the default buffer size when called on objects with a
<code>nil</code> buffer.
</p>
@@ -451,7 +732,7 @@
<p><!-- CL 323318, CL 332771 -->
<a href="/pkg/bytes/#Trim"><code>Trim</code></a>, <a href="/pkg/bytes/#TrimLeft"><code>TrimLeft</code></a>,
- and <a href="/pkg/bytes/#TrimRight"><code>TrimRight</code></a> are now allocation free and, especially for
+ and <a href="/pkg/bytes/#TrimRight"><code>TrimRight</code></a> are now allocation free and, especially for
small ASCII cutsets, up to 10 times faster.
</p>
@@ -463,6 +744,35 @@
</dd>
</dl><!-- bytes -->
+<dl id="crypto/elliptic"><dt><a href="/pkg/crypto/elliptic/">crypto/elliptic</a></dt>
+ <dd>
+ <p><!-- CL 320071, CL 320072, CL 320074, CL 361402, CL 360014 -->
+ The <a href="/pkg/crypto/elliptic#P224"><code>P224</code></a>,
+ <a href="/pkg/crypto/elliptic#P384"><code>P384</code></a>, and
+ <a href="/pkg/crypto/elliptic#P521"><code>P521</code></a> curve
+ implementations are now all backed by code generated by the
+ <a href="https://github.com/mmcloughlin/addchain">addchain</a> and
+ <a href="https://github.com/mit-plv/fiat-crypto">fiat-crypto</a>
+ projects, the latter of which is based on a formally-verified model
+ of the arithmetic operations. They now use safer complete formulas
+ and internal APIs. P-224 and P-384 are now approximately four times
+ faster. All specific curve implementations are now constant-time.
+ </p>
+
+ <p>
+ Operating on invalid curve points (those for which the
+ <code>IsOnCurve</code> method returns false, and which are never returned
+ by <a href="/pkg/crypto/elliptic#Unmarshal"><code>Unmarshal</code></a> or
+ a <code>Curve</code> method operating on a valid point) has always been
+ undefined behavior, can lead to key recovery attacks, and is now
+ unsupported by the new backend. If an invalid point is supplied to a
+ <code>P224</code>, <code>P384</code>, or <code>P521</code> method, that
+ method will now return a random point. The behavior might change to an
+ explicit panic in a future release.
+ </p>
+ </dd>
+</dl><!-- crypto/elliptic -->
+
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
<dd>
<p><!-- CL 325250 -->
@@ -473,19 +783,77 @@
</dd>
</dl><!-- crypto/tls -->
-<dl id="debug/buildinfo"><dt><a href="/pkg/debug/buildinfo">debug/buildinfo</a></dt>
+<dl id="crypto/x509"><dt><a href="/pkg/crypto/x509">crypto/x509</a></dt>
<dd>
- <p><!-- golang.org/issue/39301 -->
- This new package provides access to module versions, version control
- information, and build flags embedded in executable files built by
- the <code>go</code> command. The same information is also available via
- <a href="/pkg/runtime/debug#ReadBuildInfo"><code>runtime/debug.ReadBuildInfo</code></a>
- for the currently running binary and via <code>go</code>
- <code>version</code> <code>-m</code> on the command line.
+ <p><!-- CL 353132, CL 353403 -->
+ <a href="/pkg/crypto/x509/#Certificate.Verify"><code>Certificate.Verify</code></a>
+ now uses platform APIs to verify certificate validity on macOS and iOS when it
+ is called with a nil
+ <a href="/pkg/crypto/x509/#VerifyOpts.Roots"><code>VerifyOpts.Roots</code></a>
+ or when using the root pool returned from
+ <a href="/pkg/crypto/x509/#SystemCertPool"><code>SystemCertPool</code></a>.
+ </p>
+
+ <p><!-- CL 353589 -->
+ <a href="/pkg/crypto/x509/#SystemCertPool"><code>SystemCertPool</code></a>
+ is now available on Windows.
+ </p>
+
+ <p>
+ On Windows, macOS, and iOS, when a
+ <a href="/pkg/crypto/x509/#CertPool"><code>CertPool</code></a> returned by
+ <a href="/pkg/crypto/x509/#SystemCertPool"><code>SystemCertPool</code></a>
+ has additional certificates added to it,
+ <a href="/pkg/crypto/x509/#Certificate.Verify"><code>Certificate.Verify</code></a>
+ will do two verifications: one using the platform verifier APIs and the
+ system roots, and one using the Go verifier and the additional roots.
+ Chains returned by the platform verifier APIs will be prioritized.
+ </p>
+
+ <p>
+ <a href="/pkg/crypto/x509/#CertPool.Subjects"><code>CertPool.Subjects</code></a>
+ is deprecated. On Windows, macOS, and iOS the
+ <a href="/pkg/crypto/x509/#CertPool"><code>CertPool</code></a> returned by
+ <a href="/pkg/crypto/x509/#SystemCertPool"><code>SystemCertPool</code></a>
+ will return a pool which does not include system roots in the slice
+ returned by <code>Subjects</code>, as a static list can't appropriately
+ represent the platform policies and might not be available at all from the
+ platform APIs.
</p>
</dd>
</dl>
+<dl id="debug/dwarf"><dt><a href="/pkg/debug/dwarf/">debug/dwarf</a></dt>
+ <dd>
+ <p><!-- CL 380714 -->
+ The <a href="/pkg/debug/dwarf#StructField"><code>StructField</code></a>
+ and <a href="/pkg/debug/dwarf#BasicType"><code>BasicType</code></a>
+ structs both now have a <code>DataBitOffset</code> field, which
+ holds the value of the <code>DW_AT_data_bit_offset</code>
+ attribute if present.
+ </dd>
+</dl>
+
+<dl id="debug/elf"><dt><a href="/pkg/debug/elf/">debug/elf</a></dt>
+ <dd>
+ <p><!-- CL 352829 -->
+ The <a href="/pkg/debug/elf/#R_PPC64_RELATIVE"><code>R_PPC64_RELATIVE</code></a>
+ constant has been added.
+ </p>
+ </dd>
+</dl><!-- debug/elf -->
+
+<dl id="debug/plan9obj"><dt><a href="/pkg/debug/plan9obj/">debug/plan9obj</a></dt>
+ <dd>
+ <p><!-- CL 350229 -->
+ The <a href="/pkg/debug/plan9obj#File.Symbols">File.Symbols</a>
+ method now returns the new exported error
+ value <a href="/pkg/debug/plan9obj#ErrNoSymbols">ErrNoSymbols</a>
+ if the file has no symbol section.
+ </p>
+ </dd>
+</dl><!-- debug/plan9obj -->
+
<dl id="go/ast"><dt><a href="/pkg/go/ast/">go/ast</a></dt>
<dd>
<p><!-- https://golang.org/issue/47781, CL 325689, CL 327149, CL 348375, CL 348609 -->
@@ -533,10 +901,10 @@
<dl id="go/types"><dt><a href="/pkg/go/types/">go/types</a></dt>
<dd>
- <p><!-- https://golang.org/issue/46648 -->
- The new <a href="/pkg/go/types/#Config.GoVersion"><code>Config.GoVersion</code></a>
- field sets the accepted Go language version.
- </p>
+ <p><!-- https://golang.org/issue/46648 -->
+ The new <a href="/pkg/go/types/#Config.GoVersion"><code>Config.GoVersion</code></a>
+ field sets the accepted Go language version.
+ </p>
<p><!-- https://golang.org/issue/47916 -->
Per the proposal
@@ -615,12 +983,47 @@
<li><!-- CL 353089 -->
The new type <a href="/pkg/go/types/#Context"><code>Context</code></a> and factory function
<a href="/pkg/go/types/#NewContext"><code>NewContext</code></a>
- are added to facilitate sharing of identical type instances across type-checked packages.
+ are added to facilitate sharing of identical type instances
+ across type-checked packages, via the new
+ <a href="/pkg/go/types/#Config.Context"><code>Config.Context</code></a>
+ field.
</li>
</ul>
+ <p>
+ The predicates
+ <a href="/pkg/go/types/#AssignableTo"><code>AssignableTo</code></a>,
+ <a href="/pkg/go/types/#ConvertibleTo"><code>ConvertibleTo</code></a>,
+ <a href="/pkg/go/types/#Implements"><code>Implements</code></a>,
+ <a href="/pkg/go/types/#Identical"><code>Identical</code></a>,
+ <a href="/pkg/go/types/#IdenticalIgnoreTags"><code>IdenticalIgnoreTags</code></a>, and
+ <a href="/pkg/go/types/#AssertableTo"><code>AssertableTo</code></a>
+ now also work with arguments that are or contain generalized interfaces, i.e. interfaces
+ that may only be used as type constraints in Go code.
+ Note that the behavior of <code>AssertableTo</code> is undefined if the first argument
+ is a generalized interface.
+ </p>
</dd>
</dl>
+<dl id="html/template"><dt><a href="/pkg/html/template/">html/template</a></dt>
+ <dd>
+ <p><!-- CL 321491 -->
+ Within a <code>range</code> pipeline the new
+ <code>{{break}}</code> command will end the loop early and the
+ new <code>{{continue}}</code> command will immediately start the
+ next loop iteration.
+ </p>
+
+ <p><!-- CL 321490 -->
+ The <code>and</code> function no longer always evaluates all arguments; it
+ stops evaluating arguments after the first argument that evaluates to
+ false. Similarly, the <code>or</code> function now stops evaluating
+ arguments after the first argument that evaluates to true. This makes a
+ difference if any of the arguments is a function call.
+ </p>
+ </dd>
+</dl><!-- html/template -->
+
<dl id="image/draw"><dt><a href="/pkg/image/draw/">image/draw</a></dt>
<dd>
<p><!-- CL 340049 -->
@@ -656,13 +1059,21 @@
<a href="/pkg/net/http#Cookie.Valid"><code>Cookie.Valid</code></a>
method reports whether the cookie is valid.
</p>
+
+ <p><!-- CL 346569 -->
+ The new
+ <a href="/pkg/net/http#MaxBytesHandler"><code>MaxBytesHandler</code></a>
+ function creates a <code>Handler</code> that wraps its
+ <code>ResponseWriter</code> and <code>Request.Body</code> with a
+ <a href="/pkg/net/http#MaxBytesReader"><code>MaxBytesReader</code></a>.
+ </p>
</dd>
</dl><!-- net/http -->
<dl id="os/user"><dt><a href="/pkg/os/user/">os/user</a></dt>
<dd>
<p><!-- CL 330753 -->
- <a href="/pkg/os/user#User.GroupIds"><code>User.GroupIds</code></a>.
+ <a href="/pkg/os/user#User.GroupIds"><code>User.GroupIds</code></a>
now uses a Go native implementation when cgo is not available.
</p>
</dd>
@@ -675,7 +1086,7 @@
<a href="/pkg/reflect/#Value.SetIterKey"><code>Value.SetIterKey</code></a>
and <a href="/pkg/reflect/#Value.SetIterValue"><code>Value.SetIterValue</code></a>
methods set a Value using a map iterator as the source. They are equivalent to
- <code>Value.Set(iter.Key())</code> and <code>Value.Set(iter.Value())</code> but
+ <code>Value.Set(iter.Key())</code> and <code>Value.Set(iter.Value())</code>, but
do fewer allocations.
</p>
@@ -727,7 +1138,7 @@
The old names will continue to work, but will be deprecated in a
future Go release.
</p>
- </dd>
+ </dd><!-- CL 321889 and CL 345486 are optimizations, no need to mention. -->
</dl><!-- reflect -->
<dl id="regexp"><dt><a href="/pkg/regexp/">regexp</a></dt>
@@ -739,6 +1150,37 @@
</dd>
</dl><!-- regexp -->
+<dl id="runtime/debug"><dt><a href="/pkg/runtime/debug/">runtime/debug</a></dt>
+ <dd>
+ <p><!-- CL 354569 -->
+ The <a href="/pkg/runtime/debug#BuildInfo"><code>BuildInfo</code></a>
+ struct has two new fields, containing additional information
+ about how the binary was built:
+ <ul>
+ <li><a href="/pkg/runtime/debug#BuildInfo.GoVersion"><code>GoVersion</code></a>
+ holds the version of Go used to build the binary.
+ </li>
+ <li>
+ <a href="/pkg/runtime/debug#BuildInfo.Settings"><code>Settings</code></a>
+ is a slice of
+ <a href="/pkg/runtime/debug#BuildSettings"><code>BuildSettings</code></a>
+ structs holding key/value pairs describing the build.
+ </li>
+ </ul>
+ </p>
+ </dd>
+</dl><!-- runtime/debug -->
+
+<dl id="runtime/pprof"><dt><a href="/pkg/runtime/pprof/">runtime/pprof</a></dt>
+ <dd>
+ <p><!-- CL 324129 -->
+ The CPU profiler now uses per-thread timers on Linux. This increases the
+ maximum CPU usage that a profile can observe, and reduces some forms of
+ bias.
+ </p>
+ </dd>
+</dl><!-- runtime/pprof -->
+
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
<dd>
<p><!-- CL 343877 -->
@@ -768,7 +1210,7 @@
<p><!-- CL 323318, CL 332771 -->
<a href="/pkg/strings/#Trim"><code>Trim</code></a>, <a href="/pkg/strings/#TrimLeft"><code>TrimLeft</code></a>,
- and <a href="/pkg/strings/#TrimRight"><code>TrimRight</code></a> are now allocation free and, especially for
+ and <a href="/pkg/strings/#TrimRight"><code>TrimRight</code></a> are now allocation free and, especially for
small ASCII cutsets, up to 10 times faster.
</p>
@@ -808,7 +1250,7 @@
</p>
<p><!-- CL 355570 -->
- <a href="/pkg/syscall/?GOOS=freebsd#SysProcAttr.Pdeathsig"><code>SysProcAttr.Pdeathsig</code></a>.
+ <a href="/pkg/syscall/?GOOS=freebsd#SysProcAttr.Pdeathsig"><code>SysProcAttr.Pdeathsig</code></a>
is now supported in FreeBSD.
</p>
</dd>
@@ -817,7 +1259,7 @@
<dl id="syscall/js"><dt><a href="/pkg/syscall/js/">syscall/js</a></dt>
<dd>
<p><!-- CL 356430 -->
- <code>Wrapper</code> interface has been removed.
+ The <code>Wrapper</code> interface has been removed.
</p>
</dd>
</dl><!-- syscall/js -->
@@ -828,7 +1270,7 @@
The precedence of <code>/</code> in the argument for <code>-run</code> and
<code>-bench</code> has been increased. <code>A/B|C/D</code> used to be
treated as <code>A/(B|C)/D</code> and is now treated as
- <code>(A/B)/(C/D)</code>.
+ <code>(A/B)|(C/D)</code>.
</p>
<p><!-- CL 356669 -->
@@ -837,11 +1279,26 @@
existing tests in the unlikely case that a test changes the set of subtests
that are run each time the test function itself is run.
</p>
+
+ <p><!-- CL 251441 -->
+ The new <a href="/pkg/testing#F"><code>testing.F</code></a> type
+ is used by the new <a href="#fuzzing">fuzzing support described
+ above</a>. Tests also now support the command line
+ options <code>-test.fuzz</code>, <code>-test.fuzztime</code>, and
+ <code>-test.fuzzminimizetime</code>.
+ </p>
</dd>
</dl><!-- testing -->
<dl id="text/template"><dt><a href="/pkg/text/template/">text/template</a></dt>
<dd>
+ <p><!-- CL 321491 -->
+ Within a <code>range</code> pipeline the new
+ <code>{{break}}</code> command will end the loop early and the
+ new <code>{{continue}}</code> command will immediately start the
+ next loop iteration.
+ </p>
+
<p><!-- CL 321490 -->
The <code>and</code> function no longer always evaluates all arguments; it
stops evaluating arguments after the first argument that evaluates to
@@ -852,10 +1309,29 @@
</dd>
</dl><!-- text/template -->
+<dl id="text/template/parse"><dt><a href="/pkg/text/template/parse/">text/template/parse</a></dt>
+ <dd>
+ <p><!-- CL 321491 -->
+ The package supports the new
+ <a href="/pkg/text/template/">text/template</a> and
+ <a href="/pkg/html/template/">html/template</a>
+ <code>{{break}}</code> command via the new constant
+ <a href="/pkg/text/template/parse#NodeBreak"><code>NodeBreak</code></a>
+ and the new type
+ <a href="/pkg/text/template/parse#BreakNode"><code>BreakNode</code></a>,
+ and similarly supports the new <code>{{continue}}</code> command
+ via the new constant
+ <a href="/pkg/text/template/parse#NodeContinue"><code>NodeContinue</code></a>
+ and the new type
+ <a href="/pkg/text/template/parse#ContinueNode"><code>ContinueNode</code></a>.
+ </p>
+ </dd>
+</dl><!-- text/template -->
+
<dl id="unicode/utf8"><dt><a href="/pkg/unicode/utf8/">unicode/utf8</a></dt>
<dd>
<p><!-- CL 345571 -->
- The <a href="/pkg/unicode/utf8/#AppendRune"><code>AppendRune</code></a> function appends the UTF-8 new
+ The new <a href="/pkg/unicode/utf8/#AppendRune"><code>AppendRune</code></a> function appends the UTF-8
encoding of a <code>rune</code> to a <code>[]byte</code>.
</p>
</dd>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index cb57aa3..ad12fcf 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,21 +1,16 @@
<!--{
- "Title": "The Go Programming Language Specification - Go 1.18 Draft (incomplete)",
- "Subtitle": "Version of Dec 13, 2021",
+ "Title": "The Go Programming Language Specification",
+ "Subtitle": "Version of March 10, 2022",
"Path": "/ref/spec"
}-->
-<h2>Earlier version</h2>
-
-<p>
-For the pre-Go1.18 specification without generics support see
-<a href="/doc/go1.17_spec.html">The Go Programming Language Specification</a>.
-</p>
-
<h2 id="Introduction">Introduction</h2>
<p>
-This is a reference manual for the Go programming language. For
-more information and other documents, see <a href="/">golang.org</a>.
+This is the reference manual for the Go programming language.
+The pre-Go1.18 version, without generics, can be found
+<a href="/doc/go1.17_spec.html">here</a>.
+For more information and other documents, see <a href="/">golang.org</a>.
</p>
<p>
@@ -679,6 +674,8 @@
operand in an <a href="#Expressions">expression</a>.
It is an error if the constant value
cannot be <a href="#Representability">represented</a> as a value of the respective type.
+If the type is a type parameter, the constant is converted into a non-constant
+value of the type parameter.
</p>
<p>
@@ -759,7 +756,7 @@
<code>new</code> call or composite literal, or the type of
an element of a structured variable.
Variables of interface type also have a distinct <i>dynamic type</i>,
-which is the concrete type of the value assigned to the variable at run time
+which is the (non-interface) type of the value assigned to the variable at run time
(unless the value is the predeclared identifier <code>nil</code>,
which has no type).
The dynamic type may vary during execution but values stored in interface
@@ -788,7 +785,7 @@
<p>
A type determines a set of values together with operations and methods specific
to those values. A type may be denoted by a <i>type name</i>, if it has one, which must be
-followed by <a href="#Instantiations">type arguments</a> if the type is parameterized.
+followed by <a href="#Instantiations">type arguments</a> if the type is generic.
A type may also be specified using a <i>type literal</i>, which composes a type
from existing types.
</p>
@@ -805,7 +802,7 @@
<p>
The language <a href="#Predeclared_identifiers">predeclares</a> certain type names.
Others are introduced with <a href="#Type_declarations">type declarations</a>
-or <a href="#Type_parameter_lists">type parameter lists</a>.
+or <a href="#Type_parameter_declarations">type parameter lists</a>.
<i>Composite types</i>—array, struct, pointer, function,
interface, slice, map, and channel types—may be constructed using
type literals.
@@ -816,79 +813,6 @@
An alias denotes a named type if the type given in the alias declaration is a named type.
</p>
-<h3 id="Underlying_types">Underlying types</h3>
-
-<p>
-Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
-is one of the predeclared boolean, numeric, or string types, or a type literal,
-the corresponding underlying type is <code>T</code> itself.
-Otherwise, <code>T</code>'s underlying type is the underlying type of the
-type to which <code>T</code> refers in its <a href="#Type_declarations">type
-declaration</a>. Accordingly, the underlying type of a type parameter is the
-underlying type of its <a href="#Type_constraints">type constraint</a>, which
-is always an interface.
-</p>
-
-<pre>
-type (
- A1 = string
- A2 = A1
-)
-
-type (
- B1 string
- B2 B1
- B3 []B1
- B4 B3
-)
-
-func f[P any](x P) { … }
-</pre>
-
-<p>
-The underlying type of <code>string</code>, <code>A1</code>, <code>A2</code>, <code>B1</code>,
-and <code>B2</code> is <code>string</code>.
-The underlying type of <code>[]B1</code>, <code>B3</code>, and <code>B4</code> is <code>[]B1</code>.
-The underlying type of <code>P</code> is <code>interface{}</code>.
-</p>
-
-<h3 id="Method_sets">Method sets</h3>
-
-<p>
-The <i>method set</i> of a type determines the methods that can be
-<a href="#Calls">called</a> on an <a href="#Operands">operand</a> of that type.
-Every type has a (possibly empty) method set associated with it:
-</p>
-
-<ul>
-<li>The method set of a <a href="#Type_definitions">defined type</a> <code>T</code> consists of all
-<a href="#Method_declarations">methods</a> declared with receiver type <code>T</code>.
-</li>
-
-<li>
-The method set of a pointer to a defined type <code>T</code>
-(where <code>T</code> is neither a pointer nor an interface)
-is the set of all methods declared with receiver <code>*T</code> or <code>T</code>.
-</li>
-
-<li>The method set of an <a href="#Interface_types">interface type</a> is the intersection
-of the method sets of each type in the interface's <a href="#Interface_types">type set</a>
-(the resulting method set is usually just the set of declared methods in the interface).
-</li>
-</ul>
-
-<p>
-Further rules apply to structs (and pointer to structs) containing embedded fields,
-as described in the section on <a href="#Struct_types">struct types</a>.
-Any other type has an empty method set.
-</p>
-
-<p>
-In a method set, each method must have a
-<a href="#Uniqueness_of_identifiers">unique</a>
-non-<a href="#Blank_identifier">blank</a> <a href="#MethodName">method name</a>.
-</p>
-
<h3 id="Boolean_types">Boolean types</h3>
<p>
@@ -901,7 +825,9 @@
<h3 id="Numeric_types">Numeric types</h3>
<p>
-A <i>numeric type</i> represents sets of integer or floating-point values.
+An <i>integer</i>, <i>floating-point</i>, or <i>complex</i> type
+represents the set of integer, floating-point, or complex values, respectively.
+They are collectively called <i>numeric types</i>.
The predeclared architecture-independent numeric types are:
</p>
@@ -932,7 +858,7 @@
</p>
<p>
-There is also a set of predeclared numeric types with implementation-specific sizes:
+There is also a set of predeclared integer types with implementation-specific sizes:
</p>
<pre class="grammar">
@@ -1051,7 +977,7 @@
</p>
<p>
-A new, initialized slice value for a given element type <code>T</code> is
+A new, initialized slice value for a given element type <code>T</code> may be
made using the built-in function
<a href="#Making_slices_maps_and_channels"><code>make</code></a>,
which takes a slice type
@@ -1274,7 +1200,8 @@
<p>
An interface type defines a <i>type set</i>.
A variable of interface type can store a value of any type that is in the type
-set of the interface. Such a type is said to <i>implement the interface</i>.
+set of the interface. Such a type is said to
+<a href="#Implementing_an_interface">implement the interface</a>.
The value of an uninitialized variable of interface type is <code>nil</code>.
</p>
@@ -1295,11 +1222,15 @@
A type term is either a single type or a single underlying type.
</p>
+<h4 id="Basic_interfaces">Basic interfaces</h4>
+
<p>
In its most basic form an interface specifies a (possibly empty) list of methods.
The type set defined by such an interface is the set of types which implement all of
those methods, and the corresponding <a href="#Method_sets">method set</a> consists
exactly of the methods specified by the interface.
+Interfaces whose type sets can be defined entirely by a list of methods are called
+<i>basic interfaces.</i>
</p>
<pre>
@@ -1384,6 +1315,8 @@
as the <code>File</code> interface.
</p>
+<h4 id="Embedded_interfaces">Embedded interfaces</h4>
+
<p>
In a slightly more general form
an interface <code>T</code> may use a (possibly qualified) interface type
@@ -1428,8 +1361,10 @@
}
</pre>
+<h4 id="General_interfaces">General interfaces</h4>
+
<p>
-Finally, in their most general form, an interface element may also be an arbitrary type term
+In their most general form, an interface element may also be an arbitrary type term
<code>T</code>, or a term of the form <code>~T</code> specifying the underlying type <code>T</code>,
or a union of terms <code>t<sub>1</sub>|t<sub>2</sub>|…|t<sub>n</sub></code>.
Together with method specifications, these elements enable the precise
@@ -1437,7 +1372,7 @@
</p>
<ul>
- <li>The type set of the empty interface is the set of all types.
+ <li>The type set of the empty interface is the set of all non-interface types.
</li>
<li>The type set of a non-empty interface is the intersection of the type sets
@@ -1462,6 +1397,10 @@
</li>
</ul>
+<p>
+By construction, an interface's type set never contains an interface type.
+</p>
+
<pre>
// An interface representing only the type int.
interface {
@@ -1473,7 +1412,7 @@
~int
}
-// An interface representing all types with underlying type int which implement the String method.
+// An interface representing all types with underlying type int that implement the String method.
interface {
~int
String() string
@@ -1506,61 +1445,57 @@
</p>
<pre>
-// The Floats interface represents all floating-point types
+// The Float interface represents all floating-point types
// (including any named types whose underlying types are
// either float32 or float64).
-type Floats interface {
+type Float interface {
~float32 | ~float64
}
</pre>
<p>
-In a union, a term cannot be a type parameter, and the type sets of all
+In a union, a term cannot be a <a href="#Type_parameter_declarations">type parameter</a>, and the type sets of all
non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty).
Given a type parameter <code>P</code>:
</p>
<pre>
interface {
- P // illegal: the term P is a type parameter
- int | P // illegal: the term P is a type parameter
- ~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
- float32 | Floats // overlapping type sets but Floats is an interface
+ P // illegal: P is a type parameter
+ int | P // illegal: P is a type parameter
+ ~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
+ float32 | Float // overlapping type sets but Float is an interface
}
</pre>
<p>
Implementation restriction:
-A union with more than one term cannot contain interface types
-with non-empty <a href="#Method_sets">method sets</a>.
+A union (with more than one term) cannot contain the
+<a href="#Predeclared_identifiers">predeclared identifier</a> <code>comparable</code>
+or interfaces that specify methods, or embed <code>comparable</code> or interfaces
+that specify methods.
</p>
<p>
-Interfaces that contain non-interface types, terms of the form <code>~T</code>,
-or unions may only be used as type constraints, or as elements of other interfaces used
-as constraints. They cannot be the types of values or variables, or components of other,
+Interfaces that are not <a href="#Basic_interfaces">basic</a> may only be used as type
+constraints, or as elements of other interfaces used as constraints.
+They cannot be the types of values or variables, or components of other,
non-interface types.
</p>
<pre>
-var x Floats // illegal: Floats is restricted by float32 and float64
+var x Float // illegal: Float is not a basic interface
-var x interface{} = Floats(nil) // illegal
+var x interface{} = Float(nil) // illegal
type Floatish struct {
- f Floats // illegal
+ f Float // illegal
}
</pre>
-<!-- TODO The rule below needs to be generalized to interface elements.
- It should be factored out and generalized to other types
- such as arrays and structs which are currently missing such a
- rule. See also #5069.
--->
-
<p>
-An interface type <code>T</code> may not embed itself
-or any interface type that embeds <code>T</code>, recursively.
+An interface type <code>T</code> may not embed any type element
+that is, contains, or embeds <code>T</code>, recursively.
</p>
<pre>
@@ -1576,8 +1511,34 @@
type Bad2 interface {
Bad1
}
+
+// illegal: Bad3 cannot embed a union containing Bad3
+type Bad3 interface {
+ ~int | ~string | Bad3
+}
</pre>
+<h4 id="Implementing_an_interface">Implementing an interface</h4>
+
+<p>
+A type <code>T</code> implements an interface <code>I</code> if
+</p>
+
+<ul>
+<li>
+ <code>T</code> is not an interface and is an element of the type set of <code>I</code>; or
+</li>
+<li>
+ <code>T</code> is an interface and the type set of <code>T</code> is a subset of the
+ type set of <code>I</code>.
+</li>
+</ul>
+
+<p>
+A value of type <code>T</code> implements an interface if <code>T</code>
+implements the interface.
+</p>
+
<h3 id="Map_types">Map types</h3>
<p>
@@ -1600,7 +1561,6 @@
If the key type is an interface type, these
comparison operators must be defined for the dynamic key values;
failure will cause a <a href="#Run_time_panics">run-time panic</a>.
-
</p>
<pre>
@@ -1722,27 +1682,118 @@
received in the order sent.
</p>
-<h3 id="Type_parameters">Type parameters</h3>
-
-<p>
-A <i>type parameter</i> is an (unqualified) type name declared in the
-<a href="#Type_parameter_lists">type parameter list</a> of a
-<a href="#Function_declarations">function declaration</a> or
-<a href="#Type_definitions">type definition</a>; or in the receiver specification
-of a <a href="#Method_declarations">method declaration</a> that is associated
-with a parameterized type.
-A type parameter acts as a place holder for an (as of yet) unknown type in the declaration;
-the type parameter is replaced with a <i>type argument</i> upon
-<a href="#Instantiations">instantiation</a> of the parameterized function or type.
-</p>
-
-<p>
-The properties of a type parameter are determined by its
-<a href="#Type_constraints">type constraint</a>.
-</p>
-
<h2 id="Properties_of_types_and_values">Properties of types and values</h2>
+<h3 id="Underlying_types">Underlying types</h3>
+
+<p>
+Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
+is one of the predeclared boolean, numeric, or string types, or a type literal,
+the corresponding underlying type is <code>T</code> itself.
+Otherwise, <code>T</code>'s underlying type is the underlying type of the
+type to which <code>T</code> refers in its declaration.
+For a type parameter that is the underlying type of its
+<a href="#Type_constraints">type constraint</a>, which is always an interface.
+</p>
+
+<pre>
+type (
+ A1 = string
+ A2 = A1
+)
+
+type (
+ B1 string
+ B2 B1
+ B3 []B1
+ B4 B3
+)
+
+func f[P any](x P) { … }
+</pre>
+
+<p>
+The underlying type of <code>string</code>, <code>A1</code>, <code>A2</code>, <code>B1</code>,
+and <code>B2</code> is <code>string</code>.
+The underlying type of <code>[]B1</code>, <code>B3</code>, and <code>B4</code> is <code>[]B1</code>.
+The underlying type of <code>P</code> is <code>interface{}</code>.
+</p>
+
+<h3 id="Core_types">Core types</h3>
+
+<p>
+Each non-interface type <code>T</code> has a <i>core type</i>, which is the same as the
+<a href="#Underlying_types">underlying type</a> of <code>T</code>.
+</p>
+
+<p>
+An interface <code>T</code> has a core type if one of the following
+conditions is satisfied:
+</p>
+
+<ol>
+<li>
+There is a single type <code>U</code> which is the <a href="#Underlying_types">underlying type</a>
+of all types in the <a href="#Interface_types">type set</a> of <code>T</code>; or
+</li>
+<li>
+the type set of <code>T</code> contains only <a href="#Channel_types">channel types</a>
+with identical element type <code>E</code>, and all directional channels have the same
+direction.
+</li>
+</ol>
+
+<p>
+No other interfaces have a core type.
+</p>
+
+<p>
+The core type of an interface is, depending on the condition that is satisfied, either:
+</p>
+
+<ol>
+<li>
+the type <code>U</code>; or
+</li>
+<li>
+the type <code>chan E</code> if <code>T</code> contains only bidirectional
+channels, or the type <code>chan<- E</code> or <code><-chan E</code>
+depending on the direction of the directional channels present.
+</li>
+</ol>
+
+<p>
+By definition, a core type is never a <a href="#Type_definitions">defined type</a>,
+<a href="#Type_parameter_declarations">type parameter</a>, or
+<a href="#Interface_types">interface type</a>.
+</p>
+
+<p>
+Examples of interfaces with core types:
+</p>
+
+<pre>
+type Celsius float32
+type Kelvin float32
+
+interface{ int } // int
+interface{ Celsius|Kelvin } // float32
+interface{ ~chan int } // chan int
+interface{ ~chan int|~chan<- int } // chan<- int
+interface{ ~[]*data; String() string } // []*data
+</pre>
+
+<p>
+Examples of interfaces without core types:
+</p>
+
+<pre>
+interface{} // no single underlying type
+interface{ Celsius|float64 } // no single underlying type
+interface{ chan int | chan<- string } // channels have different element types
+interface{ <-chan int | chan<- int } // directional channels have different directions
+</pre>
+
<h3 id="Type_identity">Type identity</h3>
<p>
@@ -1847,27 +1898,27 @@
<h3 id="Assignability">Assignability</h3>
<p>
-A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
+A value <code>x</code> of type <code>V</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
("<code>x</code> is assignable to <code>T</code>") if one of the following conditions applies:
</p>
<ul>
<li>
-<code>x</code>'s type is identical to <code>T</code>.
+<code>V</code> and <code>T</code> are identical.
</li>
<li>
-<code>x</code>'s type <code>V</code> and <code>T</code> have identical
+<code>V</code> and <code>T</code> have identical
<a href="#Underlying_types">underlying types</a> and at least one of <code>V</code>
or <code>T</code> is not a <a href="#Types">named type</a>.
</li>
<li>
-<code>x</code>'s type <code>V</code> and <code>T</code> are channel types with
+<code>V</code> and <code>T</code> are channel types with
identical element types, <code>V</code> is a bidirectional channel,
and at least one of <code>V</code> or <code>T</code> is not a <a href="#Types">named type</a>.
</li>
<li>
<code>T</code> is an interface type, but not a type parameter, and
-<code>x</code> <a href="#Interface_types">implements</a> <code>T</code>.
+<code>x</code> <a href="#Implementing_an_interface">implements</a> <code>T</code>.
</li>
<li>
<code>x</code> is the predeclared identifier <code>nil</code> and <code>T</code>
@@ -1882,25 +1933,24 @@
</ul>
<p>
-Additionally, if <code>x's</code> type <code>V</code> or <code>T</code> are type parameters
-with <a href="#Structure_of_interfaces">specific types</a>, <code>x</code>
+Additionally, if <code>x</code>'s type <code>V</code> or <code>T</code> are type parameters, <code>x</code>
is assignable to a variable of type <code>T</code> if one of the following conditions applies:
</p>
<ul>
<li>
<code>x</code> is the predeclared identifier <code>nil</code>, <code>T</code> is
-a type parameter, and <code>x</code> is assignable to each specific type of
-<code>T</code>.
+a type parameter, and <code>x</code> is assignable to each type in
+<code>T</code>'s type set.
</li>
<li>
<code>V</code> is not a <a href="#Types">named type</a>, <code>T</code> is
-a type parameter, and <code>x</code> is assignable to each specific type of
-<code>T</code>.
+a type parameter, and <code>x</code> is assignable to each type in
+<code>T</code>'s type set.
</li>
<li>
<code>V</code> is a type parameter and <code>T</code> is not a named type,
-and values of each specific type of <code>V</code> are assignable
+and values of each type in <code>V</code>'s type set are assignable
to <code>T</code>.
</li>
</ul>
@@ -1910,7 +1960,7 @@
<p>
A <a href="#Constants">constant</a> <code>x</code> is <i>representable</i>
by a value of type <code>T</code>,
-where <code>T</code> is not a <a href="#Type_parameters">type parameter</a>,
+where <code>T</code> is not a <a href="#Type_parameter_declarations">type parameter</a>,
if one of the following conditions applies:
</p>
@@ -1920,7 +1970,7 @@
</li>
<li>
-<code>T</code> is a floating-point type and <code>x</code> can be rounded to <code>T</code>'s
+<code>T</code> is a <a href="#Numeric_types">floating-point type</a> and <code>x</code> can be rounded to <code>T</code>'s
precision without overflow. Rounding uses IEEE 754 round-to-even rules but with an IEEE
negative zero further simplified to an unsigned zero. Note that constant values never result
in an IEEE negative zero, NaN, or infinity.
@@ -1935,9 +1985,9 @@
</ul>
<p>
-If <code>T</code> is a type parameter with <a href="#Structure_of_interfaces">specific types</a>,
+If <code>T</code> is a type parameter,
<code>x</code> is representable by a value of type <code>T</code> if <code>x</code> is representable
-by a value of each specific type of <code>T</code>.
+by a value of each type in <code>T</code>'s type set.
</p>
<pre>
@@ -1967,118 +2017,43 @@
1e1000 float64 1e1000 overflows to IEEE +Inf after rounding
</pre>
-<h3 id="Structure_of_interfaces">Structure of interfaces</h3>
+<h3 id="Method_sets">Method sets</h3>
<p>
-An interface specification which contains <a href="#Interface_types">type elements</a>
-defines a (possibly empty) set of <i>specific types</i>.
-Loosely speaking, these are the types <code>T</code> that appear in the
-interface definition in terms of the form <code>T</code>, <code>~T</code>,
-or in unions of such terms.
-</p>
-
-<p>
-More precisely, for a given interface, the set 𝑆 of specific types is defined as follows:
+The <i>method set</i> of a type determines the methods that can be
+<a href="#Calls">called</a> on an <a href="#Operands">operand</a> of that type.
+Every type has a (possibly empty) method set associated with it:
</p>
<ul>
- <li>For an interface with no type elements, 𝑆 is the empty set.
- </li>
+<li>The method set of a <a href="#Type_definitions">defined type</a> <code>T</code> consists of all
+<a href="#Method_declarations">methods</a> declared with receiver type <code>T</code>.
+</li>
- <li>For an interface with type elements, 𝑆 is the intersection
- of the specific types of its type elements.
- </li>
+<li>
+The method set of a pointer to a defined type <code>T</code>
+(where <code>T</code> is neither a pointer nor an interface)
+is the set of all methods declared with receiver <code>*T</code> or <code>T</code>.
+</li>
- <li>For a non-interface type term <code>T</code>
- or <code>~T</code>, 𝑆 is the set consisting of the type <code>T</code>.
- </li>
-
- <li>For a <i>union</i> of terms
- <code>t<sub>1</sub>|t<sub>2</sub>|…|t<sub>n</sub></code>,
- 𝑆 is the union of the specific types of the terms.
- </li>
+<li>The method set of an <a href="#Interface_types">interface type</a> is the intersection
+of the method sets of each type in the interface's <a href="#Interface_types">type set</a>
+(the resulting method set is usually just the set of declared methods in the interface).
+</li>
</ul>
<p>
-If 𝑆 is empty, the interface has <i>no specific types</i>.
-An interface may have specific types even if its <a href="#Interface_types">type set</a>
-is empty.
+Further rules apply to structs (and pointer to structs) containing embedded fields,
+as described in the section on <a href="#Struct_types">struct types</a>.
+Any other type has an empty method set.
</p>
<p>
-Examples of interfaces with their specific types:
+In a method set, each method must have a
+<a href="#Uniqueness_of_identifiers">unique</a>
+non-<a href="#Blank_identifier">blank</a> <a href="#MethodName">method name</a>.
</p>
-<pre>
-type Celsius float32
-type Kelvin float32
-
-interface{} // no specific types
-interface{ int } // int
-interface{ ~string } // string
-interface{ int|~string } // int, string
-interface{ Celsius|Kelvin } // Celsius, Kelvin
-interface{ int; m() } // int (but type set is empty because int has no method m)
-interface{ int; any } // no specific types (intersection is empty)
-interface{ int; string } // no specific types (intersection is empty)
-</pre>
-
-<p>
-An interface <code>T</code> is called <i>structural</i> if one of the following
-conditions is satisfied:
-</p>
-
-<ol>
-<li>
-There is a single type <code>U</code> which is the <a href="#Underlying_types">underlying type</a>
-of all types in the <a href="#Interface_types">type set</a> of <code>T</code>; or
-</li>
-<li>
-the type set of <code>T</code> contains only <a href="#Channel_types">channel types</a>
-with identical element type <code>E</code>, and all directional channels have the same
-direction.
-</li>
-</ol>
-
-<p>
-A structural interface has a <i>structural type</i> which is, depending on the
-condition that is satisfied, either:
-</p>
-
-<ol>
-<li>
-the type <code>U</code>; or
-</li>
-<li>
-the type <code>chan E</code> if <code>T</code> contains only bidirectional
-channels, or the type <code>chan<- E</code> or <code><-chan E</code>
-depending on the direction of the directional channels present.
-</li>
-</ol>
-
-<p>
-Examples of structural interfaces with their structural types:
-</p>
-
-<pre>
-interface{ int } // int
-interface{ Celsius|Kelvin } // float32
-interface{ ~chan int } // chan int
-interface{ ~chan int|~chan<- int } // chan<- int
-interface{ ~[]*data; String() string } // []*data
-</pre>
-
-<p>
-Examples of non-structural interfaces:
-</p>
-
-<pre>
-interface{} // no single underlying type
-interface{ Celsius|float64 } // no single underlying type
-interface{ chan int | chan<- string } // channels have different element types
-interface{ <-chan int | chan<- int } // directional channels have different directions
-</pre>
-
<h2 id="Blocks">Blocks</h2>
<p>
@@ -2125,6 +2100,7 @@
A <i>declaration</i> binds a non-<a href="#Blank_identifier">blank</a> identifier to a
<a href="#Constant_declarations">constant</a>,
<a href="#Type_declarations">type</a>,
+<a href="#Type_parameter_declarations">type parameter</a>,
<a href="#Variable_declarations">variable</a>,
<a href="#Function_declarations">function</a>,
<a href="#Labeled_statements">label</a>, or
@@ -2169,13 +2145,13 @@
<li>The scope of an identifier denoting a method receiver, function parameter,
or result variable is the function body.</li>
- <li>The scope of an identifier denoting a type parameter of a type-parameterized function
+ <li>The scope of an identifier denoting a type parameter of a function
or declared by a method receiver is the function body and all parameter lists of the
function.
</li>
- <li>The scope of an identifier denoting a type parameter of a parameterized type
- begins after the name of the parameterized type and ends at the end
+ <li>The scope of an identifier denoting a type parameter of a type
+ begins after the name of the type and ends at the end
of the TypeSpec.</li>
<li>The scope of a constant or variable identifier declared
@@ -2251,7 +2227,6 @@
make new panic print println real recover
</pre>
-
<h3 id="Exported_identifiers">Exported identifiers</h3>
<p>
@@ -2300,7 +2275,8 @@
<p>
If the type is present, all constants take the type specified, and
-the expressions must be <a href="#Assignability">assignable</a> to that type.
+the expressions must be <a href="#Assignability">assignable</a> to that type,
+which must not be a type parameter.
If the type is omitted, the constants take the
individual types of the corresponding expressions.
If the expression values are untyped <a href="#Constants">constants</a>,
@@ -2461,7 +2437,7 @@
type TreeNode struct {
left, right *TreeNode
- value *Comparable
+ value any
}
type Block interface {
@@ -2522,9 +2498,9 @@
</pre>
<p>
-If the type definition specifies <a href="#Type_parameter_lists">type parameters</a>,
-the type name denotes a <i>parameterized type</i>.
-Parameterized types must be <a href="#Instantiations">instantiated</a> when they
+If the type definition specifies <a href="#Type_parameter_declarations">type parameters</a>,
+the type name denotes a <i>generic type</i>.
+Generic types must be <a href="#Instantiations">instantiated</a> when they
are used.
</p>
@@ -2533,15 +2509,10 @@
next *List[T]
value T
}
-
-type Tree[T constraints.Ordered] struct {
- left, right *Tree[T]
- value T
-}
</pre>
<p>
-The given type cannot be a type parameter in a type definition.
+In a type definition the given type cannot be a type parameter.
</p>
<pre>
@@ -2553,9 +2524,9 @@
</pre>
<p>
-A parameterized type may also have methods associated with it. In this case,
-the method receivers must declare the same number of type parameters as
-present in the parameterized type definition.
+A generic type may also have <a href="#Method_declarations">methods</a> associated with it.
+In this case, the method receivers must declare the same number of type parameters as
+present in the generic type definition.
</p>
<pre>
@@ -2563,11 +2534,10 @@
func (l *List[T]) Len() int { … }
</pre>
-<h3 id="Type_parameter_lists">Type parameter lists</h3>
+<h3 id="Type_parameter_declarations">Type parameter declarations</h3>
<p>
-A type parameter list declares the <a href="#Type_parameters">type parameters</a>
-in a type-parameterized function or type declaration.
+A type parameter list declares the <i>type parameters</i> of a generic function or type declaration.
The type parameter list looks like an ordinary <a href="#Function_types">function parameter list</a>
except that the type parameter names must all be present and the list is enclosed
in square brackets rather than parentheses.
@@ -2580,9 +2550,11 @@
</pre>
<p>
-Each identifier declares a type parameter.
All non-blank names in the list must be unique.
-Each type parameter is a new and different <a href="#Types">named type</a>.
+Each name declares a type parameter, which is a new and different <a href="#Types">named type</a>
+that acts as a place holder for an (as of yet) unknown type in the declaration.
+The type parameter is replaced with a <i>type argument</i> upon
+<a href="#Instantiations">instantiation</a> of the generic function or type.
</p>
<pre>
@@ -2600,31 +2572,45 @@
</p>
<p>
-A parsing ambiguity arises when the type parameter list for a parameterized type
-declares a single type parameter with a type constraint of the form <code>*C</code>
-or <code>(C)</code>:
+A parsing ambiguity arises when the type parameter list for a generic type
+declares a single type parameter <code>P</code> with a constraint <code>C</code>
+such that the text <code>P C</code> forms a valid expression:
</p>
<pre>
type T[P *C] …
type T[P (C)] …
+type T[P *C|Q] …
+…
</pre>
<p>
-In these rare cases, the type parameter declaration is indistinguishable from
-the expressions <code>P*C</code> or <code>P(C)</code> and the type declaration
-is parsed as an array type declaration.
-To resolve the ambiguity, embed the constraint in an interface:
+In these rare cases, the type parameter list is indistinguishable from an
+expression and the type declaration is parsed as an array type declaration.
+To resolve the ambiguity, embed the constraint in an
+<a href="#Interface_types">interface</a> or use a trailing comma:
</p>
<pre>
type T[P interface{*C}] …
+type T[P *C,] …
</pre>
+<p>
+Type parameters may also be declared by the receiver specification
+of a <a href="#Method_declarations">method declaration</a> associated
+with a generic type.
+</p>
+
+<!--
+This section needs to explain if and what kind of cycles are permitted
+using type parameters in a type parameter list.
+-->
+
<h4 id="Type_constraints">Type constraints</h4>
<p>
-A type constraint is an <a href="#Interface_types">interface</a> that determines the
+A type constraint is an <a href="#Interface_types">interface</a> that defines the
set of permissible type arguments for the respective type parameter and controls the
operations supported by values of that type parameter.
</p>
@@ -2634,18 +2620,65 @@
</pre>
<p>
-If the constraint is an interface literal containing exactly one embedded type element
-<code>interface{E}</code>, in a type parameter list the enclosing <code>interface{ … }</code>
-may be omitted for convenience:
+If the constraint is an interface literal of the form <code>interface{E}</code> where
+<code>E</code> is an embedded type element (not a method), in a type parameter list
+the enclosing <code>interface{ … }</code> may be omitted for convenience:
</p>
<pre>
-[T *P] // = [T interface{*P}]
-[T ~int] // = [T interface{~int}]
-[T int|string] // = [T interface{int|string}]
-type Constraint ~int // illegal: ~int is not inside a type parameter list
+[T []P] // = [T interface{[]P}]
+[T ~int] // = [T interface{~int}]
+[T int|string] // = [T interface{int|string}]
+type Constraint ~int // illegal: ~int is not inside a type parameter list
</pre>
+<!--
+We should be able to simplify the rules for comparable or delegate some of them
+elsewhere since we have a section that clearly defines how interfaces implement
+other interfaces based on their type sets. But this should get us going for now.
+-->
+
+<p>
+The <a href="#Predeclared_identifiers">predeclared</a>
+<a href="#Interface_types">interface type</a> <code>comparable</code>
+denotes the set of all non-interface types that are
+<a href="#Comparison_operators">comparable</a>. Specifically,
+a type <code>T</code> implements <code>comparable</code> if:
+</p>
+
+<ul>
+<li>
+ <code>T</code> is not an interface type and <code>T</code> supports the operations
+ <code>==</code> and <code>!=</code>; or
+</li>
+<li>
+ <code>T</code> is an interface type and each type in <code>T</code>'s
+ <a href="#Interface_types">type set</a> implements <code>comparable</code>.
+</li>
+</ul>
+
+<p>
+Even though interfaces that are not type parameters can be
+<a href="#Comparison_operators">compared</a>
+(possibly causing a run-time panic) they do not implement
+<code>comparable</code>.
+</p>
+
+<pre>
+int // implements comparable
+[]byte // does not implement comparable (slices cannot be compared)
+interface{} // does not implement comparable (see above)
+interface{ ~int | ~string } // type parameter only: implements comparable
+interface{ comparable } // type parameter only: implements comparable
+interface{ ~int | ~[]byte } // type parameter only: does not implement comparable (not all types in the type set are comparable)
+</pre>
+
+<p>
+The <code>comparable</code> interface and interfaces that (directly or indirectly) embed
+<code>comparable</code> may only be used as type constraints. They cannot be the types of
+values or variables, or components of other, non-interface types.
+</p>
+
<h3 id="Variable_declarations">Variable declarations</h3>
<p>
@@ -2789,14 +2822,14 @@
</pre>
<p>
-If the function declaration specifies <a href="#Type_parameter_lists">type parameters</a>,
-the function name denotes a <i>type-parameterized function</i>.
-Type-parameterized functions must be <a href="#Instantiations">instantiated</a> when they
-are used.
+If the function declaration specifies <a href="#Type_parameter_declarations">type parameters</a>,
+the function name denotes a <i>generic function</i>.
+A generic function must be <a href="#Instantiations">instantiated</a> before it can be
+called or used as a value.
</p>
<pre>
-func min[T constraints.Ordered](x, y T) T {
+func min[T ~int|~float64](x, y T) T {
if x < y {
return x
}
@@ -2855,7 +2888,7 @@
</p>
<p>
-Given defined type <code>Point</code>, the declarations
+Given defined type <code>Point</code> the declarations
</p>
<pre>
@@ -2876,16 +2909,13 @@
</p>
<p>
-If the receiver base type is a <a href="#Type_declarations">parameterized type</a>, the
+If the receiver base type is a <a href="#Type_declarations">generic type</a>, the
receiver specification must declare corresponding type parameters for the method
to use. This makes the receiver type parameters available to the method.
-</p>
-
-<p>
Syntactically, this type parameter declaration looks like an
-<a href="#Instantiations">instantiation</a> of the receiver base type, except that
-the type arguments are the type parameters being declared, one for each type parameter
-of the receiver base type.
+<a href="#Instantiations">instantiation</a> of the receiver base type: the type
+arguments must be identifiers denoting the type parameters being declared, one
+for each type parameter of the receiver base type.
The type parameter names do not need to match their corresponding parameter names in the
receiver base type definition, and all non-blank parameter names must be unique in the
receiver parameter section and the method signature.
@@ -2899,8 +2929,8 @@
b B
}
-func (p Pair[A, B]) Swap() Pair[B, A] { return Pair[B, A]{p.b, p.a} }
-func (p Pair[First, _]) First() First { return p.a }
+func (p Pair[A, B]) Swap() Pair[B, A] { … } // receiver declares A, B
+func (p Pair[First, _]) First() First { … } // receiver declares First, corresponds to A in Pair
</pre>
<h2 id="Expressions">Expressions</h2>
@@ -2922,9 +2952,16 @@
or a parenthesized expression.
</p>
+<pre class="ebnf">
+Operand = Literal | OperandName [ TypeArgs ] | "(" Expression ")" .
+Literal = BasicLit | CompositeLit | FunctionLit .
+BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
+OperandName = identifier | QualifiedIdent .
+</pre>
+
<p>
-An operand name denoting a <a href="#Function_declarations">type-parameterized function</a>
-may be followed by a list of <a href="#Type_arguments">type arguments</a>; the
+An operand name denoting a <a href="#Function_declarations">generic function</a>
+may be followed by a list of <a href="#Instantiations">type arguments</a>; the
resulting operand is an <a href="#Instantiations">instantiated</a> function.
</p>
@@ -2933,12 +2970,13 @@
operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
</p>
-<pre class="ebnf">
-Operand = Literal | OperandName [ TypeArgs ] | "(" Expression ")" .
-Literal = BasicLit | CompositeLit | FunctionLit .
-BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
-OperandName = identifier | QualifiedIdent .
-</pre>
+<p>
+Implementation restriction: A compiler need not report an error if an operand's
+type is a <a href="#Type_parameter_declarations">type parameter</a> with an empty
+<a href="#Interface_types">type set</a>. Functions with such type parameters
+cannot be <a href="#Instantiations">instantiated</a>; any attempt will lead
+to an error at the instantiation site.
+</p>
<h3 id="Qualified_identifiers">Qualified identifiers</h3>
@@ -2966,8 +3004,7 @@
<h3 id="Composite_literals">Composite literals</h3>
<p>
-Composite literals construct values for structs, arrays, slices, and maps
-and create a new value each time they are evaluated.
+Composite literals construct new composite values each time they are evaluated.
They consist of the type of the literal followed by a brace-bound list of elements.
Each element may optionally be preceded by a corresponding key.
</p>
@@ -2985,11 +3022,12 @@
</pre>
<p>
-The LiteralType's underlying type must be a struct, array, slice, or map type
+The LiteralType's <a href="#Core_types">core type</a> <code>T</code>
+must be a struct, array, slice, or map type
(the grammar enforces this constraint except when the type is given
as a TypeName).
The types of the elements and keys must be <a href="#Assignability">assignable</a>
-to the respective field, element, and key types of the literal type;
+to the respective field, element, and key types of type <code>T</code>;
there is no additional conversion.
The key is interpreted as a field name for struct literals,
an index for array and slice literals, and a key for map literals.
@@ -3051,7 +3089,7 @@
key must be a non-negative constant
<a href="#Representability">representable</a> by
a value of type <code>int</code>; and if it is typed
- it must be of integer type.
+ it must be of <a href="#Numeric_types">integer type</a>.
</li>
<li>An element without a key uses the previous element's index plus one.
If the first element has no key, its index is zero.
@@ -3289,8 +3327,7 @@
For a value <code>x</code> of type <code>T</code> or <code>*T</code>
where <code>T</code> is not a pointer or interface type,
<code>x.f</code> denotes the field or method at the shallowest depth
-in <code>T</code> where there
-is such an <code>f</code>.
+in <code>T</code> where there is such an <code>f</code>.
If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a>
with shallowest depth, the selector expression is illegal.
</li>
@@ -3647,10 +3684,11 @@
</p>
<p>
-If <code>a</code> is not a map:
+If <code>a</code> is neither a map nor a type parameter:
</p>
<ul>
- <li>the index <code>x</code> must be of integer type or an untyped constant</li>
+ <li>the index <code>x</code> must be an untyped constant or its
+ <a href="#Core_types">core type</a> must be an <a href="#Numeric_types">integer</a></li>
<li>a constant index must be non-negative and
<a href="#Representability">representable</a> by a value of type <code>int</code></li>
<li>a constant index that is untyped is given type <code>int</code></li>
@@ -3715,23 +3753,22 @@
</ul>
<p>
-For <code>a</code> of <a href="#Type_parameters">type parameter type</a> <code>P</code>:
+For <code>a</code> of <a href="#Type_parameter_declarations">type parameter type</a> <code>P</code>:
</p>
<ul>
- <li><code>P</code> must have <a href="#Structure_of_interfaces">specific types</a>.</li>
<li>The index expression <code>a[x]</code> must be valid for values
- of all specific types of <code>P</code>.</li>
- <li>The element types of all specific types of <code>P</code> must be identical.
+ of all types in <code>P</code>'s type set.</li>
+ <li>The element types of all types in <code>P</code>'s type set must be identical.
In this context, the element type of a string type is <code>byte</code>.</li>
- <li>If there is a map type among the specific types of <code>P</code>,
- all specific types must be map types, and the respective key types
+ <li>If there is a map type in the type set of <code>P</code>,
+ all types in that type set must be map types, and the respective key types
must be all identical.</li>
<li><code>a[x]</code> is the array, slice, or string element at index <code>x</code>,
or the map element with key <code>x</code> of the type argument
that <code>P</code> is instantiated with, and the type of <code>a[x]</code> is
the type of the (identical) element types.</li>
- <li><code>a[x]</code> may not be assigned to if the specific types of <code>P</code>
- include string types.
+ <li><code>a[x]</code> may not be assigned to if <code>P</code>'s type set
+ includes string types.
</ul>
<p>
@@ -3772,7 +3809,7 @@
<h4>Simple slice expressions</h4>
<p>
-For a string, array, pointer to array, or slice <code>a</code>, the primary expression
+The primary expression
</p>
<pre>
@@ -3780,7 +3817,9 @@
</pre>
<p>
-constructs a substring or slice. The <i>indices</i> <code>low</code> and
+constructs a substring or slice. The <a href="#Core_types">core type</a> of
+<code>a</code> must be a string, array, pointer to array, or slice.
+The <i>indices</i> <code>low</code> and
<code>high</code> select which elements of operand <code>a</code> appear
in the result. The result has indices starting at 0 and length equal to
<code>high</code> - <code>low</code>.
@@ -3856,7 +3895,7 @@
<h4>Full slice expressions</h4>
<p>
-For an array, pointer to array, or slice <code>a</code> (but not a string), the primary expression
+The primary expression
</p>
<pre>
@@ -3867,6 +3906,8 @@
constructs a slice of the same type, and with the same length and elements as the simple slice
expression <code>a[low : high]</code>. Additionally, it controls the resulting slice's capacity
by setting it to <code>max - low</code>. Only the first index may be omitted; it defaults to 0.
+The <a href="#Core_types">core type</a> of <code>a</code> must be an array, pointer to array,
+or slice (but not a string).
After slicing the array <code>a</code>
</p>
@@ -3905,7 +3946,7 @@
<p>
For an expression <code>x</code> of <a href="#Interface_types">interface type</a>,
-but not a <a href="#Type_parameters">type parameter</a>, and a type <code>T</code>,
+but not a <a href="#Type_parameter_declarations">type parameter</a>, and a type <code>T</code>,
the primary expression
</p>
@@ -3926,7 +3967,7 @@
otherwise the type assertion is invalid since it is not possible for <code>x</code>
to store a value of type <code>T</code>.
If <code>T</code> is an interface type, <code>x.(T)</code> asserts that the dynamic type
-of <code>x</code> implements the interface <code>T</code>.
+of <code>x</code> <a href="#Implementing_an_interface">implements</a> the interface <code>T</code>.
</p>
<p>
If the type assertion holds, the value of the expression is the value
@@ -3972,8 +4013,8 @@
<h3 id="Calls">Calls</h3>
<p>
-Given an expression <code>f</code> of function type
-<code>F</code>,
+Given an expression <code>f</code> with a <a href="#Core_types">core type</a>
+<code>F</code> of <a href="#Function_types">function type</a>,
</p>
<pre>
@@ -3999,7 +4040,7 @@
</pre>
<p>
-If <code>f</code> denotes a parameterized function, it must be
+If <code>f</code> denotes a generic function, it must be
<a href="#Instantiations">instantiated</a> before it can be called
or used as a function value.
</p>
@@ -4118,14 +4159,14 @@
<h3 id="Instantiations">Instantiations</h3>
<p>
-A parameterized function or type is <i>instantiated</i> by substituting type arguments
+A generic function or type is <i>instantiated</i> by substituting <i>type arguments</i>
for the type parameters.
-Instantiation proceeds in two phases:
+Instantiation proceeds in two steps:
</p>
<ol>
<li>
-Each type argument is substituted for its corresponding type parameter in the parameterized
+Each type argument is substituted for its corresponding type parameter in the generic
declaration.
This substitution happens across the entire function or type declaration,
including the type parameter list itself and any types in that list.
@@ -4133,64 +4174,463 @@
<li>
After substitution, each type argument must <a href="#Interface_types">implement</a>
-the <a href="#Type_parameter_lists">constraint</a> (instantiated, if necessary)
+the <a href="#Type_parameter_declarations">constraint</a> (instantiated, if necessary)
of the corresponding type parameter. Otherwise instantiation fails.
</li>
</ol>
<p>
-Instantiating a type results in a new non-parameterized <a href="#Types">named type</a>;
-instantiating a function produces a new non-parameterized function.
+Instantiating a type results in a new non-generic <a href="#Types">named type</a>;
+instantiating a function produces a new non-generic function.
</p>
<pre>
type parameter list type arguments after substitution
-[P any] int [int any]
-[S ~[]E, E any] []int, int [[]int ~[]int, int any]
-[P io.Writer] string [string io.Writer] // illegal: string doesn't implement io.Writer
+[P any] int int implements any
+[S ~[]E, E any] []int, int []int implements ~[]int, int implements any
+[P io.Writer] string illegal: string doesn't implement io.Writer
</pre>
<p>
-Type arguments may be provided explicitly, or they may be partially or completely
-<a href="#Type_inference">inferred</a>.
-A partially provided type argument list cannot be empty; there must be at least the
-first argument.
-</p>
-
-<pre>
-type T[P1 ~int, P2 ~[]P1] struct{ … }
-
-T[] // illegal: at least the first type argument must be present, even if it could be inferred
-T[int] // argument for P1 explicitly provided, argument for P2 inferred
-T[int, []int] // both arguments explicitly provided
-</pre>
-
-<p>
-A partial type argument list specifies a prefix of the full list of type arguments, leaving
-the remaining arguments to be inferred. Loosely speaking, type arguments may be omitted from
-"right to left".
-</p>
-
-<p>
-Parameterized types, and parameterized functions that are not <a href="#Calls">called</a>,
-require a type argument list for instantiation; if the list is partial, all
+For a generic function, type arguments may be provided explicitly, or they
+may be partially or completely <a href="#Type_inference">inferred</a>.
+A generic function that is is <i>not</i> <a href="#Calls">called</a> requires a
+type argument list for instantiation; if the list is partial, all
remaining type arguments must be inferrable.
-Calls to parameterized functions may provide a (possibly partial) type
+A generic function that is called may provide a (possibly partial) type
argument list, or may omit it entirely if the omitted type arguments are
inferrable from the ordinary (non-type) function arguments.
</p>
<pre>
-func min[T constraints.Ordered](x, y T) T { … }
+func min[T ~int|~float64](x, y T) T { … }
-f := min // illegal: min must be instantiated when used without being called
+f := min // illegal: min must be instantiated with type arguments when used without being called
minInt := min[int] // minInt has type func(x, y int) int
a := minInt(2, 3) // a has value 2 of type int
b := min[float64](2.0, 3) // b has value 2.0 of type float64
c := min(b, -1) // c has value -1.0 of type float64
</pre>
+<p>
+A partial type argument list cannot be empty; at least the first argument must be present.
+The list is a prefix of the full list of type arguments, leaving the remaining arguments
+to be inferred. Loosely speaking, type arguments may be omitted from "right to left".
+</p>
+
+<pre>
+func apply[S ~[]E, E any](s S, f(E) E) S { … }
+
+f0 := apply[] // illegal: type argument list cannot be empty
+f1 := apply[[]int] // type argument for S explicitly provided, type argument for E inferred
+f2 := apply[[]string, string] // both type arguments explicitly provided
+
+var bytes []byte
+r := apply(bytes, func(byte) byte { … }) // both type arguments inferred from the function arguments
+</pre>
+
+<p>
+For a generic type, all type arguments must always be provided explicitly.
+</p>
+
+<h3 id="Type_inference">Type inference</h3>
+
+<p>
+Missing function type arguments may be <i>inferred</i> by a series of steps, described below.
+Each step attempts to use known information to infer additional type arguments.
+Type inference stops as soon as all type arguments are known.
+After type inference is complete, it is still necessary to substitute all type arguments
+for type parameters and verify that each type argument
+<a href="#Implementing_an_interface">implements</a> the relevant constraint;
+it is possible for an inferred type argument to fail to implement a constraint, in which
+case instantiation fails.
+</p>
+
+<p>
+Type inference is based on
+</p>
+
+<ul>
+<li>
+ a <a href="#Type_parameter_declarations">type parameter list</a>
+</li>
+<li>
+ a substitution map <i>M</i> initialized with the known type arguments, if any
+</li>
+<li>
+ a (possibly empty) list of ordinary function arguments (in case of a function call only)
+</li>
+</ul>
+
+<p>
+and then proceeds with the following steps:
+</p>
+
+<ol>
+<li>
+ apply <a href="#Function_argument_type_inference"><i>function argument type inference</i></a>
+ to all <i>typed</i> ordinary function arguments
+</li>
+<li>
+ apply <a href="#Constraint_type_inference"><i>constraint type inference</i></a>
+</li>
+<li>
+ apply function argument type inference to all <i>untyped</i> ordinary function arguments
+ using the default type for each of the untyped function arguments
+</li>
+<li>
+ apply constraint type inference
+</li>
+</ol>
+
+<p>
+If there are no ordinary or untyped function arguments, the respective steps are skipped.
+Constraint type inference is skipped if the previous step didn't infer any new type arguments,
+but it is run at least once if there are missing type arguments.
+</p>
+
+<p>
+The substitution map <i>M</i> is carried through all steps, and each step may add entries to <i>M</i>.
+The process stops as soon as <i>M</i> has a type argument for each type parameter or if an inference step fails.
+If an inference step fails, or if <i>M</i> is still missing type arguments after the last step, type inference fails.
+</p>
+
+<h4 id="Type_unification">Type unification</h4>
+
+<p>
+Type inference is based on <i>type unification</i>. A single unification step
+applies to a <a href="#Type_inference">substitution map</a> and two types, either
+or both of which may be or contain type parameters. The substitution map tracks
+the known (explicitly provided or already inferred) type arguments: the map
+contains an entry <code>P</code> → <code>A</code> for each type
+parameter <code>P</code> and corresponding known type argument <code>A</code>.
+During unification, known type arguments take the place of their corresponding type
+parameters when comparing types. Unification is the process of finding substitution
+map entries that make the two types equivalent.
+</p>
+
+<p>
+For unification, two types that don't contain any type parameters from the current type
+parameter list are <i>equivalent</i>
+if they are identical, or if they are channel types that are identical ignoring channel
+direction, or if their underlying types are equivalent.
+</p>
+
+<p>
+Unification works by comparing the structure of pairs of types: their structure
+disregarding type parameters must be identical, and types other than type parameters
+must be equivalent.
+A type parameter in one type may match any complete subtype in the other type;
+each successful match causes an entry to be added to the substitution map.
+If the structure differs, or types other than type parameters are not equivalent,
+unification fails.
+</p>
+
+<!--
+TODO(gri) Somewhere we need to describe the process of adding an entry to the
+ substitution map: if the entry is already present, the type argument
+ values are themselves unified.
+-->
+
+<p>
+For example, if <code>T1</code> and <code>T2</code> are type parameters,
+<code>[]map[int]bool</code> can be unified with any of the following:
+</p>
+
+<pre>
+[]map[int]bool // types are identical
+T1 // adds T1 → []map[int]bool to substitution map
+[]T1 // adds T1 → map[int]bool to substitution map
+[]map[T1]T2 // adds T1 → int and T2 → bool to substitution map
+</pre>
+
+<p>
+On the other hand, <code>[]map[int]bool</code> cannot be unified with any of
+</p>
+
+<pre>
+int // int is not a slice
+struct{} // a struct is not a slice
+[]struct{} // a struct is not a map
+[]map[T1]string // map element types don't match
+</pre>
+
+<p>
+As an exception to this general rule, because a <a href="#Type_definitions">defined type</a>
+<code>D</code> and a type literal <code>L</code> are never equivalent,
+unification compares the underlying type of <code>D</code> with <code>L</code> instead.
+For example, given the defined type
+</p>
+
+<pre>
+type Vector []float64
+</pre>
+
+<p>
+and the type literal <code>[]E</code>, unification compares <code>[]float64</code> with
+<code>[]E</code> and adds an entry <code>E</code> → <code>float64</code> to
+the substitution map.
+</p>
+
+<h4 id="Function_argument_type_inference">Function argument type inference</h4>
+
+<!-- In this section and the section on constraint type inference we start with examples
+rather than have the examples follow the rules as is customary elsewhere in spec.
+Hopefully this helps building an intuition and makes the rules easier to follow. -->
+
+<p>
+Function argument type inference infers type arguments from function arguments:
+if a function parameter is declared with a type <code>T</code> that uses
+type parameters,
+<a href="#Type_unification">unifying</a> the type of the corresponding
+function argument with <code>T</code> may infer type arguments for the type
+parameters used by <code>T</code>.
+</p>
+
+<p>
+For instance, given the generic function
+</p>
+
+<pre>
+func scale[Number ~int64|~float64|~complex128](v []Number, s Number) []Number
+</pre>
+
+<p>
+and the call
+</p>
+
+<pre>
+var vector []float64
+scaledVector := scale(vector, 42)
+</pre>
+
+<p>
+the type argument for <code>Number</code> can be inferred from the function argument
+<code>vector</code> by unifying the type of <code>vector</code> with the corresponding
+parameter type: <code>[]float64</code> and <code>[]Number</code>
+match in structure and <code>float64</code> matches with <code>Number</code>.
+This adds the entry <code>Number</code> → <code>float64</code> to the
+<a href="#Type_unification">substitution map</a>.
+Untyped arguments, such as the second function argument <code>42</code> here, are ignored
+in the first round of function argument type inference and only considered if there are
+unresolved type parameters left.
+</p>
+
+<p>
+Inference happens in two separate phases; each phase operates on a specific list of
+(parameter, argument) pairs:
+</p>
+
+<ol>
+<li>
+ The list <i>Lt</i> contains all (parameter, argument) pairs where the parameter
+ type uses type parameters and where the function argument is <i>typed</i>.
+</li>
+<li>
+ The list <i>Lu</i> contains all remaining pairs where the parameter type is a single
+ type parameter. In this list, the respective function arguments are untyped.
+</li>
+</ol>
+
+<p>
+Any other (parameter, argument) pair is ignored.
+</p>
+
+<p>
+By construction, the arguments of the pairs in <i>Lu</i> are <i>untyped</i> constants
+(or the untyped boolean result of a comparison). And because <a href="#Constants">default types</a>
+of untyped values are always predeclared non-composite types, they can never match against
+a composite type, so it is sufficient to only consider parameter types that are single type
+parameters.
+</p>
+
+<p>
+Each list is processed in a separate phase:
+</p>
+
+<ol>
+<li>
+ In the first phase, the parameter and argument types of each pair in <i>Lt</i>
+ are unified. If unification succeeds for a pair, it may yield new entries that
+ are added to the substitution map <i>M</i>. If unification fails, type inference
+ fails.
+</li>
+<li>
+ The second phase considers the entries of list <i>Lu</i>. Type parameters for
+ which the type argument has already been determined are ignored in this phase.
+ For each remaining pair, the parameter type (which is a single type parameter) and
+ the <a href="#Constants">default type</a> of the corresponding untyped argument is
+ unified. If unification fails, type inference fails.
+</li>
+</ol>
+
+<p>
+While unification is successful, processing of each list continues until all list elements
+are considered, even if all type arguments are inferred before the last list element has
+been processed.
+</p>
+
+<p>
+Example:
+</p>
+
+<pre>
+func min[T ~int|~float64](x, y T) T
+
+var x int
+min(x, 2.0) // T is int, inferred from typed argument x; 2.0 is assignable to int
+min(1.0, 2.0) // T is float64, inferred from default type for 1.0 and matches default type for 2.0
+min(1.0, 2) // illegal: default type float64 (for 1.0) doesn't match default type int (for 2)
+</pre>
+
+<p>
+In the example <code>min(1.0, 2)</code>, processing the function argument <code>1.0</code>
+yields the substitution map entry <code>T</code> → <code>float64</code>. Because
+processing continues until all untyped arguments are considered, an error is reported. This
+ensures that type inference does not depend on the order of the untyped arguments.
+</p>
+
+<h4 id="Constraint_type_inference">Constraint type inference</h4>
+
+<p>
+Constraint type inference infers type arguments by considering type constraints.
+If a type parameter <code>P</code> has a constraint with a
+<a href="#Core_types">core type</a> <code>C</code>,
+<a href="#Type_unification">unifying</a> <code>P</code> with <code>C</code>
+may infer additional type arguments, either the type argument for <code>P</code>,
+or if that is already known, possibly the type arguments for type parameters
+used in <code>C</code>.
+</p>
+
+<p>
+For instance, consider the type parameter list with type parameters <code>List</code> and
+<code>Elem</code>:
+</p>
+
+<pre>
+[List ~[]Elem, Elem any]
+</pre>
+
+<p>
+Constraint type inference can deduce the type of <code>Elem</code> from the type argument
+for <code>List</code> because <code>Elem</code> is a type parameter in the core type
+<code>[]Elem</code> of <code>List</code>.
+If the type argument is <code>Bytes</code>:
+</p>
+
+<pre>
+type Bytes []byte
+</pre>
+
+<p>
+unifying the underlying type of <code>Bytes</code> with the core type means
+unifying <code>[]byte</code> with <code>[]Elem</code>. That unification succeeds and yields
+the <a href="#Type_unification">substitution map</a> entry
+<code>Elem</code> → <code>byte</code>.
+Thus, in this example, constraint type inference can infer the second type argument from the
+first one.
+</p>
+
+<p>
+Using the core type of a constraint may lose some information: In the (unlikely) case that
+the constraint's type set contains a single <a href="#Type_definitions">defined type</a>
+<code>N</code>, the corresponding core type is <code>N</code>'s underlying type rather than
+<code>N</code> itself. In this case, constraint type inference may succeed but instantiation
+will fail because the inferred type is not in the type set of the constraint.
+Thus, constraint type inference uses the <i>adjusted core type</i> of
+a constraint: if the type set contains a single type, use that type; otherwise use the
+constraint's core type.
+</p>
+
+<p>
+Generally, constraint type inference proceeds in two phases: Starting with a given
+substitution map <i>M</i>
+</p>
+
+<ol>
+<li>
+For all type parameters with an adjusted core type, unify the type parameter with that
+type. If any unification fails, constraint type inference fails.
+</li>
+
+<li>
+At this point, some entries in <i>M</i> may map type parameters to other
+type parameters or to types containing type parameters. For each entry
+<code>P</code> → <code>A</code> in <i>M</i> where <code>A</code> is or
+contains type parameters <code>Q</code> for which there exist entries
+<code>Q</code> → <code>B</code> in <i>M</i>, substitute those
+<code>Q</code> with the respective <code>B</code> in <code>A</code>.
+Stop when no further substitution is possible.
+</li>
+</ol>
+
+<p>
+The result of constraint type inference is the final substitution map <i>M</i> from type
+parameters <code>P</code> to type arguments <code>A</code> where no type parameter <code>P</code>
+appears in any of the <code>A</code>.
+</p>
+
+<p>
+For instance, given the type parameter list
+</p>
+
+<pre>
+[A any, B []C, C *A]
+</pre>
+
+<p>
+and the single provided type argument <code>int</code> for type parameter <code>A</code>,
+the initial substitution map <i>M</i> contains the entry <code>A</code> → <code>int</code>.
+</p>
+
+<p>
+In the first phase, the type parameters <code>B</code> and <code>C</code> are unified
+with the core type of their respective constraints. This adds the entries
+<code>B</code> → <code>[]C</code> and <code>C</code> → <code>*A</code>
+to <i>M</i>.
+
+<p>
+At this point there are two entries in <i>M</i> where the right-hand side
+is or contains type parameters for which there exists other entries in <i>M</i>:
+<code>[]C</code> and <code>*A</code>.
+In the second phase, these type parameters are replaced with their respective
+types. It doesn't matter in which order this happens. Starting with the state
+of <i>M</i> after the first phase:
+</p>
+
+<p>
+<code>A</code> → <code>int</code>,
+<code>B</code> → <code>[]C</code>,
+<code>C</code> → <code>*A</code>
+</p>
+
+<p>
+Replace <code>A</code> on the right-hand side of → with <code>int</code>:
+</p>
+
+<p>
+<code>A</code> → <code>int</code>,
+<code>B</code> → <code>[]C</code>,
+<code>C</code> → <code>*int</code>
+</p>
+
+<p>
+Replace <code>C</code> on the right-hand side of → with <code>*int</code>:
+</p>
+
+<p>
+<code>A</code> → <code>int</code>,
+<code>B</code> → <code>[]*int</code>,
+<code>C</code> → <code>*int</code>
+</p>
+
+<p>
+At this point no further substitution is possible and the map is full.
+Therefore, <code>M</code> represents the final map of type parameters
+to type arguments for the given type parameter list.
+</p>
+
<h3 id="Operators">Operators</h3>
<p>
@@ -4224,7 +4664,7 @@
</p>
<p>
-The right operand in a shift expression must have integer type
+The right operand in a shift expression must have <a href="#Numeric_types">integer type</a>
or be an untyped constant <a href="#Representability">representable</a> by a
value of type <code>uint</code>.
If the left operand of a non-constant shift expression is an untyped constant,
@@ -4247,7 +4687,8 @@
var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift
var u1 = 1.0<<s != 0 // illegal: 1.0 has type float64, cannot shift
var u2 = 1<<s != 1.0 // illegal: 1 has type float64, cannot shift
-var v float32 = 1<<s // illegal: 1 has type float32, cannot shift
+var v1 float32 = 1<<s // illegal: 1 has type float32, cannot shift
+var v2 = string(1<<s) // illegal: 1 is converted to a string, cannot shift
var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression; w == 1<<33
var x = a[1.0<<s] // panics: 1.0 has type int, but 1<<33 overflows array bounds
var b = make([]byte, 1.0<<s) // 1.0 has type int; len(b) == 1<<33
@@ -4303,8 +4744,9 @@
<p>
Arithmetic operators apply to numeric values and yield a result of the same
type as the first operand. The four standard arithmetic operators (<code>+</code>,
-<code>-</code>, <code>*</code>, <code>/</code>) apply to integer,
-floating-point, and complex types; <code>+</code> also applies to strings.
+<code>-</code>, <code>*</code>, <code>/</code>) apply to
+<a href="#Numeric_types">integer</a>, <a href="#Numeric_types">floating-point</a>, and
+<a href="#Numeric_types">complex</a> types; <code>+</code> also applies to <a href="#String_types">strings</a>.
The bitwise logical and shift operators apply to integers only.
</p>
@@ -4324,6 +4766,30 @@
>> right shift integer >> integer >= 0
</pre>
+<p>
+If the operand type is a <a href="#Type_parameter_declarations">type parameter</a>,
+the operator must apply to each type in that type set.
+The operands are represented as values of the type argument that the type parameter
+is <a href="#Instantiations">instantiated</a> with, and the operation is computed
+with the precision of that type argument. For example, given the function:
+</p>
+
+<pre>
+func dotProduct[F ~float32|~float64](v1, v2 []F) F {
+ var s F
+ for i, x := range v1 {
+ y := v2[i]
+ s += x * y
+ }
+ return s
+}
+</pre>
+
+<p>
+the product <code>x * y</code> and the addition <code>s += x * y</code>
+are computed with <code>float32</code> or <code>float64</code> precision,
+respectively, depending on the type argument for <code>F</code>.
+</p>
<h4 id="Integer_operators">Integer operators</h4>
@@ -4410,13 +4876,14 @@
<h4 id="Integer_overflow">Integer overflow</h4>
<p>
-For unsigned integer values, the operations <code>+</code>,
+For <a href="#Numeric_types">unsigned integer</a> values, the operations <code>+</code>,
<code>-</code>, <code>*</code>, and <code><<</code> are
computed modulo 2<sup><i>n</i></sup>, where <i>n</i> is the bit width of
-the <a href="#Numeric_types">unsigned integer</a>'s type.
+the unsigned integer's type.
Loosely speaking, these unsigned integer operations
discard high bits upon overflow, and programs may rely on "wrap around".
</p>
+
<p>
For signed integers, the operations <code>+</code>,
<code>-</code>, <code>*</code>, <code>/</code>, and <code><<</code> may legally
@@ -4427,7 +4894,6 @@
not occur. For instance, it may not assume that <code>x < x + 1</code> is always true.
</p>
-
<h4 id="Floating_point_operators">Floating-point operators</h4>
<p>
@@ -4443,7 +4909,7 @@
An implementation may combine multiple floating-point operations into a single
fused operation, possibly across statements, and produce a result that differs
from the value obtained by executing and rounding the instructions individually.
-An explicit floating-point type <a href="#Conversions">conversion</a> rounds to
+An explicit <a href="#Numeric_types">floating-point type</a> <a href="#Conversions">conversion</a> rounds to
the precision of the target type, preventing fusion that would discard that rounding.
</p>
@@ -4483,7 +4949,6 @@
String addition creates a new string by concatenating the operands.
</p>
-
<h3 id="Comparison_operators">Comparison operators</h3>
<p>
@@ -4562,7 +5027,7 @@
A value <code>x</code> of non-interface type <code>X</code> and
a value <code>t</code> of interface type <code>T</code> are comparable when values
of type <code>X</code> are comparable and
- <code>X</code> implements <code>T</code>.
+ <code>X</code> <a href="#Implementing_an_interface">implements</a> <code>T</code>.
They are equal if <code>t</code>'s dynamic type is identical to <code>X</code>
and <code>t</code>'s dynamic value is equal to <code>x</code>.
</li>
@@ -4664,7 +5129,8 @@
<h3 id="Receive_operator">Receive operator</h3>
<p>
-For an operand <code>ch</code> of <a href="#Channel_types">channel type</a>,
+For an operand <code>ch</code> whose <a href="#Core_types">core type</a> is a
+<a href="#Channel_types">channel</a>,
the value of the receive operation <code><-ch</code> is the value received
from the channel <code>ch</code>. The channel direction must permit receive operations,
and the type of the receive operation is the element type of the channel.
@@ -4750,9 +5216,8 @@
</p>
<p>
-Converting a constant to a type that is not a <a href="#Type_parameters">type parameter</a>
+Converting a constant to a type that is not a <a href="#Type_parameter_declarations">type parameter</a>
yields a typed constant.
-Converting a constant to a type parameter yields a non-constant value of that type.
</p>
<pre>
@@ -4771,6 +5236,29 @@
</pre>
<p>
+Converting a constant to a type parameter yields a <i>non-constant</i> value of that type,
+with the value represented as a value of the type argument that the type parameter
+is <a href="#Instantiations">instantiated</a> with.
+For example, given the function:
+</p>
+
+<pre>
+func f[P ~float32|~float64]() {
+ … P(1.1) …
+}
+</pre>
+
+<p>
+the conversion <code>P(1.1)</code> results in a non-constant value of type <code>P</code>
+and the value <code>1.1</code> is represented as a <code>float32</code> or a <code>float64</code>
+depending on the type argument for <code>f</code>.
+Accordingly, if <code>f</code> is instantiated with a <code>float32</code> type,
+the numeric value of the expression <code>P(1.1) + 1.2</code> will be computed
+with the same precision as the corresponding non-constant <code>float32</code>
+addition.
+</p>
+
+<p>
A non-constant value <code>x</code> can be converted to type <code>T</code>
in any of these cases:
</p>
@@ -4783,7 +5271,7 @@
<li>
ignoring struct tags (see below),
<code>x</code>'s type and <code>T</code> are not
- <a href="#Type_parameters">type parameters</a> but have
+ <a href="#Type_parameter_declarations">type parameters</a> but have
<a href="#Type_identity">identical</a> <a href="#Types">underlying types</a>.
</li>
<li>
@@ -4814,24 +5302,24 @@
</ul>
<p>
-Additionally, if <code>T</code> or </code><code>x's</code> type <code>V</code> are type
-parameters with <a href="#Structure_of_interfaces">specific types</a>, <code>x</code>
+Additionally, if <code>T</code> or <code>x</code>'s type <code>V</code> are type
+parameters, <code>x</code>
can also be converted to type <code>T</code> if one of the following conditions applies:
</p>
<ul>
<li>
Both <code>V</code> and <code>T</code> are type parameters and a value of each
-specific type of <code>V</code> can be converted to each specific type
-of <code>T</code>.
+type in <code>V</code>'s type set can be converted to each type in <code>T</code>'s
+type set.
</li>
<li>
Only <code>V</code> is a type parameter and a value of each
-specific type of <code>V</code> can be converted to <code>T</code>.
+type in <code>V</code>'s type set can be converted to <code>T</code>.
</li>
<li>
Only <code>T</code> is a type parameter and <code>x</code> can be converted to each
-specific type of <code>T</code>.
+type in <code>T</code>'s type set.
</li>
</ul>
@@ -4872,8 +5360,7 @@
<p>
There is no linguistic mechanism to convert between pointers and integers.
The package <a href="#Package_unsafe"><code>unsafe</code></a>
-implements this functionality under
-restricted circumstances.
+implements this functionality under restricted circumstances.
</p>
<h4>Conversions between numeric types</h4>
@@ -4884,19 +5371,19 @@
<ol>
<li>
-When converting between integer types, if the value is a signed integer, it is
+When converting between <a href="#Numeric_types">integer types</a>, if the value is a signed integer, it is
sign extended to implicit infinite precision; otherwise it is zero extended.
It is then truncated to fit in the result type's size.
For example, if <code>v := uint16(0x10F0)</code>, then <code>uint32(int8(v)) == 0xFFFFFFF0</code>.
The conversion always yields a valid value; there is no indication of overflow.
</li>
<li>
-When converting a floating-point number to an integer, the fraction is discarded
+When converting a <a href="#Numeric_types">floating-point number</a> to an integer, the fraction is discarded
(truncation towards zero).
</li>
<li>
When converting an integer or floating-point number to a floating-point type,
-or a complex number to another complex type, the result value is rounded
+or a <a href="#Numeric_types">complex number</a> to another complex type, the result value is rounded
to the precision specified by the destination type.
For instance, the value of a variable <code>x</code> of type <code>float32</code>
may be stored using additional precision beyond that of an IEEE-754 32-bit number,
@@ -5355,7 +5842,8 @@
<p>
A send statement sends a value on a channel.
-The channel expression must be of <a href="#Channel_types">channel type</a>,
+The channel expression's <a href="#Core_types">core type</a>
+must be a <a href="#Channel_types">channel</a>,
the channel direction must permit send operations,
and the type of the value to be sent must be <a href="#Assignability">assignable</a>
to the channel's element type.
@@ -5702,7 +6190,7 @@
Cases then match actual types <code>T</code> against the dynamic type of the
expression <code>x</code>. As with type assertions, <code>x</code> must be of
<a href="#Interface_types">interface type</a>, but not a
-<a href="#Type_parameters">type parameter</a>, and each non-interface type
+<a href="#Type_parameter_declarations">type parameter</a>, and each non-interface type
<code>T</code> listed in a case must implement the type of <code>x</code>.
The types listed in the cases of a type switch must all be
<a href="#Type_identity">different</a>.
@@ -5784,6 +6272,32 @@
</pre>
<p>
+A <a href="#Type_parameter_declarations">type parameter</a> or a <a href="#Type_declarations">generic type</a>
+may be used as a type in a case. If upon <a href="#Instantiations">instantiation</a> that type turns
+out to duplicate another entry in the switch, the first matching case is chosen.
+</p>
+
+<pre>
+func f[P any](x any) int {
+ switch x.(type) {
+ case P:
+ return 0
+ case string:
+ return 1
+ case []P:
+ return 2
+ case []byte:
+ return 3
+ default:
+ return 4
+ }
+}
+
+var v1 = f[string]("foo") // v1 == 0
+var v2 = f[byte]([]byte{}) // v2 == 2
+</pre>
+
+<p>
The type switch guard may be preceded by a simple statement, which
executes before the guard is evaluated.
</p>
@@ -5875,7 +6389,8 @@
<p>
The expression on the right in the "range" clause is called the <i>range expression</i>,
-which may be an array, pointer to an array, slice, string, map, or channel permitting
+its <a href="#Core_types">core type</a> must be
+an array, pointer to an array, slice, string, map, or channel permitting
<a href="#Receive_operator">receive operations</a>.
As with an assignment, if present the operands on the left must be
<a href="#Address_operators">addressable</a> or map index expressions; they
@@ -5921,7 +6436,7 @@
in the string starting at byte index 0. On successive iterations, the index value will be the
index of the first byte of successive UTF-8-encoded code points in the string,
and the second value, of type <code>rune</code>, will be the value of
-the corresponding code point. If the iteration encounters an invalid
+the corresponding code point. If the iteration encounters an invalid
UTF-8 sequence, the second value will be <code>0xFFFD</code>,
the Unicode replacement character, and the next iteration will advance
a single byte in the string.
@@ -6460,9 +6975,10 @@
<h3 id="Close">Close</h3>
<p>
-For a channel <code>c</code>, the built-in function <code>close(c)</code>
+For an argument <code>ch</code> with a <a href="#Core_types">core type</a>
+that is a <a href="#Channel_types">channel</a>, the built-in function <code>close</code>
records that no more values will be sent on the channel.
-It is an error if <code>c</code> is a receive-only channel.
+It is an error if <code>ch</code> is a receive-only channel.
Sending to or closing a closed channel causes a <a href="#Run_time_panics">run-time panic</a>.
Closing the nil channel also causes a <a href="#Run_time_panics">run-time panic</a>.
After calling <code>close</code>, and after any previously
@@ -6472,7 +6988,6 @@
returns a received value along with an indication of whether the channel is closed.
</p>
-
<h3 id="Length_and_capacity">Length and capacity</h3>
<p>
@@ -6489,19 +7004,18 @@
[]T slice length
map[K]T map length (number of defined keys)
chan T number of elements queued in channel buffer
- type parameter see below
+ type parameter see below
cap(s) [n]T, *[n]T array length (== n)
[]T slice capacity
chan T channel buffer capacity
- type parameter see below
+ type parameter see below
</pre>
<p>
-If the argument type is a <a href="#Type_parameters">type parameter</a> <code>P</code>,
-<code>P</code> must have <a href="#Structure of interfaces">specific types</a>, and
+If the argument type is a <a href="#Type_parameter_declarations">type parameter</a> <code>P</code>,
the call <code>len(e)</code> (or <code>cap(e)</code> respectively) must be valid for
-each specific type of <code>P</code>.
+each type in <code>P</code>'s type set.
The result is the length (or capacity, respectively) of the argument whose type
corresponds to the type argument with which <code>P</code> was
<a href="#Instantiations">instantiated</a>.
@@ -6579,30 +7093,32 @@
<p>
The built-in function <code>make</code> takes a type <code>T</code>,
-which must be a slice, map or channel type,
optionally followed by a type-specific list of expressions.
+The <a href="#Core_types">core type</a> of <code>T</code> must
+be a slice, map or channel.
It returns a value of type <code>T</code> (not <code>*T</code>).
The memory is initialized as described in the section on
<a href="#The_zero_value">initial values</a>.
</p>
<pre class="grammar">
-Call Type T Result
+Call Core type Result
-make(T, n) slice slice of type T with length n and capacity n
-make(T, n, m) slice slice of type T with length n and capacity m
+make(T, n) slice slice of type T with length n and capacity n
+make(T, n, m) slice slice of type T with length n and capacity m
-make(T) map map of type T
-make(T, n) map map of type T with initial space for approximately n elements
+make(T) map map of type T
+make(T, n) map map of type T with initial space for approximately n elements
-make(T) channel unbuffered channel of type T
-make(T, n) channel buffered channel of type T, buffer size n
+make(T) channel unbuffered channel of type T
+make(T, n) channel buffered channel of type T, buffer size n
</pre>
<p>
-Each of the size arguments <code>n</code> and <code>m</code> must be of integer type
-or an untyped <a href="#Constants">constant</a>.
+Each of the size arguments <code>n</code> and <code>m</code> must be of <a href="#Numeric_types">integer type</a>,
+have a <a href="#Interface_types">type set</a> containing only integer types,
+or be an untyped <a href="#Constants">constant</a>.
A constant size argument must be non-negative and <a href="#Representability">representable</a>
by a value of type <code>int</code>; if it is an untyped constant it is given type <code>int</code>.
If both <code>n</code> and <code>m</code> are provided and are constant, then
@@ -6638,21 +7154,20 @@
<p>
The <a href="#Function_types">variadic</a> function <code>append</code>
-appends zero or more values <code>x</code>
-to <code>s</code> of type <code>S</code>, which must be a slice type, and
-returns the resulting slice, also of type <code>S</code>.
-The values <code>x</code> are passed to a parameter of type <code>...T</code>
-where <code>T</code> is the <a href="#Slice_types">element type</a> of
-<code>S</code> and the respective
-<a href="#Passing_arguments_to_..._parameters">parameter passing rules</a> apply.
-As a special case, <code>append</code> also accepts a first argument
-assignable to type <code>[]byte</code> with a second argument of
-string type followed by <code>...</code>. This form appends the
-bytes of the string.
+appends zero or more values <code>x</code> to a slice <code>s</code>
+and returns the resulting slice of the same type as <code>s</code>.
+The <a href="#Core_types">core type</a> of <code>s</code> must be a slice
+of type <code>[]E</code>.
+The values <code>x</code> are passed to a parameter of type <code>...E</code>
+and the respective <a href="#Passing_arguments_to_..._parameters">parameter
+passing rules</a> apply.
+As a special case, if the core type of <code>s</code> is <code>[]byte</code>,
+<code>append</code> also accepts a second argument with core type <code>string</code>
+followed by <code>...</code>. This form appends the bytes of the string.
</p>
<pre class="grammar">
-append(s S, x ...T) S // T is the element type of S
+append(s S, x ...E) S // core type of S is []E
</pre>
<p>
@@ -6680,12 +7195,12 @@
The function <code>copy</code> copies slice elements from
a source <code>src</code> to a destination <code>dst</code> and returns the
number of elements copied.
-Both arguments must have <a href="#Type_identity">identical</a> element type <code>T</code> and must be
-<a href="#Assignability">assignable</a> to a slice of type <code>[]T</code>.
+The <a href="#Core_types">core types</a> of both arguments must be slices
+with <a href="#Type_identity">identical</a> element type.
The number of elements copied is the minimum of
<code>len(src)</code> and <code>len(dst)</code>.
-As a special case, <code>copy</code> also accepts a destination argument assignable
-to type <code>[]byte</code> with a source argument of a string type.
+As a special case, if the destination's core type is <code>[]byte</code>,
+<code>copy</code> also accepts a source argument with core type <code>string</code>.
This form copies the bytes from the string into the byte slice.
</p>
@@ -6713,7 +7228,7 @@
<p>
The built-in function <code>delete</code> removes the element with key
<code>k</code> from a <a href="#Map_types">map</a> <code>m</code>. The
-type of <code>k</code> must be <a href="#Assignability">assignable</a>
+value <code>k</code> must be <a href="#Assignability">assignable</a>
to the key type of <code>m</code>.
</p>
@@ -6722,6 +7237,11 @@
</pre>
<p>
+If the type of <code>m</code> is a <a href="#Type_parameter_declarations">type parameter</a>,
+all types in that type set must be maps, and they must all have identical key types.
+</p>
+
+<p>
If the map <code>m</code> is <code>nil</code> or the element <code>m[k]</code>
does not exist, <code>delete</code> is a no-op.
</p>
@@ -6746,7 +7266,8 @@
<p>
The type of the arguments and return value correspond.
For <code>complex</code>, the two arguments must be of the same
-floating-point type and the return type is the complex type
+<a href="#Numeric_types">floating-point type</a> and the return type is the
+<a href="#Numeric_types">complex type</a>
with the corresponding floating-point constituents:
<code>complex64</code> for <code>float32</code> arguments, and
<code>complex128</code> for <code>float64</code> arguments.
@@ -6790,6 +7311,10 @@
_ = imag(3 << s) // illegal: 3 assumes complex type, cannot shift
</pre>
+<p>
+Arguments of type parameter type are not permitted.
+</p>
+
<h3 id="Handling_panics">Handling panics</h3>
<p> Two built-in functions, <code>panic</code> and <code>recover</code>,
@@ -6808,7 +7333,7 @@
terminates the execution of <code>F</code>.
Any functions <a href="#Defer_statements">deferred</a> by <code>F</code>
are then executed as usual.
-Next, any deferred functions run by <code>F's</code> caller are run,
+Next, any deferred functions run by <code>F</code>'s caller are run,
and so on up to any deferred by the top-level function in the executing goroutine.
At that point, the program is terminated and the error
condition is reported, including the value of the argument to <code>panic</code>.
@@ -7398,11 +7923,17 @@
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
</pre>
+<!--
+These conversions also apply to type parameters with suitable core types.
+Determine if we can simply use core type insted of underlying type here,
+of if the general conversion rules take care of this.
+-->
+
<p>
A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
value may not be <a href="#Address_operators">dereferenced</a>.
-Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
-a type of underlying type <code>Pointer</code> and vice versa.
+Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be
+<a href="#Conversions">converted</a> to a type of underlying type <code>Pointer</code> and vice versa.
The effect of converting between <code>Pointer</code> and <code>uintptr</code> is implementation-defined.
</p>
@@ -7449,7 +7980,8 @@
<p>
A (variable of) type <code>T</code> has <i>variable size</i> if <code>T</code>
-is a type parameter, or if it is an array or struct type containing elements
+is a <a href="#Type_parameter_declarations">type parameter</a>, or if it is an
+array or struct type containing elements
or fields of variable size. Otherwise the size is <i>constant</i>.
Calls to <code>Alignof</code>, <code>Offsetof</code>, and <code>Sizeof</code>
are compile-time <a href="#Constant_expressions">constant expressions</a> of
@@ -7461,7 +7993,7 @@
<p>
The function <code>Add</code> adds <code>len</code> to <code>ptr</code>
and returns the updated pointer <code>unsafe.Pointer(uintptr(ptr) + uintptr(len))</code>.
-The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
+The <code>len</code> argument must be of <a href="#Numeric_types">integer type</a> or an untyped <a href="#Constants">constant</a>.
A constant <code>len</code> argument must be <a href="#Representability">representable</a> by a value of type <code>int</code>;
if it is an untyped constant it is given type <code>int</code>.
The rules for <a href="/pkg/unsafe#Pointer">valid uses</a> of <code>Pointer</code> still apply.
@@ -7484,7 +8016,7 @@
</p>
<p>
-The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
+The <code>len</code> argument must be of <a href="#Numeric_types">integer type</a> or an untyped <a href="#Constants">constant</a>.
A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>;
if it is an untyped constant it is given type <code>int</code>.
At run time, if <code>len</code> is negative,
diff --git a/misc/cgo/errors/badsym_test.go b/misc/cgo/errors/badsym_test.go
index fc68756..bc3ba2b 100644
--- a/misc/cgo/errors/badsym_test.go
+++ b/misc/cgo/errors/badsym_test.go
@@ -201,6 +201,10 @@
if !lastSpace {
cc = append(cc, s[start:])
}
+
+ // Force reallocation (and avoid aliasing bugs) for tests that append to cc.
+ cc = cc[:len(cc):len(cc)]
+
return cc
}
diff --git a/misc/cgo/test/test.go b/misc/cgo/test/test.go
index dd81f77..109ef98 100644
--- a/misc/cgo/test/test.go
+++ b/misc/cgo/test/test.go
@@ -367,6 +367,11 @@
// Cgo incorrectly computed the alignment of structs
// with no Go accessible fields as 0, and then panicked on
// modulo-by-zero computations.
+
+// issue 50987
+// disable arm64 GCC warnings
+#cgo CFLAGS: -Wno-psabi -Wno-unknown-warning-option
+
typedef struct {
} foo;
diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go
index a2b43bb..d36b97b 100644
--- a/misc/cgo/testcarchive/carchive_test.go
+++ b/misc/cgo/testcarchive/carchive_test.go
@@ -10,12 +10,14 @@
"debug/elf"
"flag"
"fmt"
+ "io"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
+ "strconv"
"strings"
"syscall"
"testing"
@@ -138,6 +140,9 @@
libgodir = filepath.Join(GOPATH, "pkg", libbase, "testcarchive")
cc = append(cc, "-I", libgodir)
+ // Force reallocation (and avoid aliasing bugs) for parallel tests that append to cc.
+ cc = cc[:len(cc):len(cc)]
+
if GOOS == "windows" {
exeSuffix = ".exe"
}
@@ -263,6 +268,173 @@
}
}
+// checkArchive verifies that the created library looks OK.
+// We just check a couple of things now, we can add more checks as needed.
+func checkArchive(t *testing.T, arname string) {
+ t.Helper()
+
+ switch GOOS {
+ case "aix", "darwin", "ios", "windows":
+ // We don't have any checks for non-ELF libraries yet.
+ if _, err := os.Stat(arname); err != nil {
+ t.Errorf("archive %s does not exist: %v", arname, err)
+ }
+ default:
+ checkELFArchive(t, arname)
+ }
+}
+
+// checkELFArchive checks an ELF archive.
+func checkELFArchive(t *testing.T, arname string) {
+ t.Helper()
+
+ f, err := os.Open(arname)
+ if err != nil {
+ t.Errorf("archive %s does not exist: %v", arname, err)
+ return
+ }
+ defer f.Close()
+
+ // TODO(iant): put these in a shared package? But where?
+ const (
+ magic = "!<arch>\n"
+ fmag = "`\n"
+
+ namelen = 16
+ datelen = 12
+ uidlen = 6
+ gidlen = 6
+ modelen = 8
+ sizelen = 10
+ fmaglen = 2
+ hdrlen = namelen + datelen + uidlen + gidlen + modelen + sizelen + fmaglen
+ )
+
+ type arhdr struct {
+ name string
+ date string
+ uid string
+ gid string
+ mode string
+ size string
+ fmag string
+ }
+
+ var magbuf [len(magic)]byte
+ if _, err := io.ReadFull(f, magbuf[:]); err != nil {
+ t.Errorf("%s: archive too short", arname)
+ return
+ }
+ if string(magbuf[:]) != magic {
+ t.Errorf("%s: incorrect archive magic string %q", arname, magbuf)
+ }
+
+ off := int64(len(magic))
+ for {
+ if off&1 != 0 {
+ var b [1]byte
+ if _, err := f.Read(b[:]); err != nil {
+ if err == io.EOF {
+ break
+ }
+ t.Errorf("%s: error skipping alignment byte at %d: %v", arname, off, err)
+ }
+ off++
+ }
+
+ var hdrbuf [hdrlen]byte
+ if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
+ if err == io.EOF {
+ break
+ }
+ t.Errorf("%s: error reading archive header at %d: %v", arname, off, err)
+ return
+ }
+
+ var hdr arhdr
+ hdrslice := hdrbuf[:]
+ set := func(len int, ps *string) {
+ *ps = string(bytes.TrimSpace(hdrslice[:len]))
+ hdrslice = hdrslice[len:]
+ }
+ set(namelen, &hdr.name)
+ set(datelen, &hdr.date)
+ set(uidlen, &hdr.uid)
+ set(gidlen, &hdr.gid)
+ set(modelen, &hdr.mode)
+ set(sizelen, &hdr.size)
+ hdr.fmag = string(hdrslice[:fmaglen])
+ hdrslice = hdrslice[fmaglen:]
+ if len(hdrslice) != 0 {
+ t.Fatalf("internal error: len(hdrslice) == %d", len(hdrslice))
+ }
+
+ if hdr.fmag != fmag {
+ t.Errorf("%s: invalid fmagic value %q at %d", arname, hdr.fmag, off)
+ return
+ }
+
+ size, err := strconv.ParseInt(hdr.size, 10, 64)
+ if err != nil {
+ t.Errorf("%s: error parsing size %q at %d: %v", arname, hdr.size, off, err)
+ return
+ }
+
+ off += hdrlen
+
+ switch hdr.name {
+ case "__.SYMDEF", "/", "/SYM64/":
+ // The archive symbol map.
+ case "//", "ARFILENAMES/":
+ // The extended name table.
+ default:
+ // This should be an ELF object.
+ checkELFArchiveObject(t, arname, off, io.NewSectionReader(f, off, size))
+ }
+
+ off += size
+ if _, err := f.Seek(off, os.SEEK_SET); err != nil {
+ t.Errorf("%s: failed to seek to %d: %v", arname, off, err)
+ }
+ }
+}
+
+// checkELFArchiveObject checks an object in an ELF archive.
+func checkELFArchiveObject(t *testing.T, arname string, off int64, obj io.ReaderAt) {
+ t.Helper()
+
+ ef, err := elf.NewFile(obj)
+ if err != nil {
+ t.Errorf("%s: failed to open ELF file at %d: %v", arname, off, err)
+ return
+ }
+ defer ef.Close()
+
+ // Verify section types.
+ for _, sec := range ef.Sections {
+ want := elf.SHT_NULL
+ switch sec.Name {
+ case ".text", ".data":
+ want = elf.SHT_PROGBITS
+ case ".bss":
+ want = elf.SHT_NOBITS
+ case ".symtab":
+ want = elf.SHT_SYMTAB
+ case ".strtab":
+ want = elf.SHT_STRTAB
+ case ".init_array":
+ want = elf.SHT_INIT_ARRAY
+ case ".fini_array":
+ want = elf.SHT_FINI_ARRAY
+ case ".preinit_array":
+ want = elf.SHT_PREINIT_ARRAY
+ }
+ if want != elf.SHT_NULL && sec.Type != want {
+ t.Errorf("%s: incorrect section type in elf file at %d for section %q: got %v want %v", arname, off, sec.Name, sec.Type, want)
+ }
+ }
+}
+
func TestInstall(t *testing.T) {
if !testWork {
defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
@@ -310,7 +482,7 @@
defer func() {
os.Remove("libgo2.a")
os.Remove("libgo2.h")
- os.Remove("testp")
+ os.Remove("testp" + exeSuffix)
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
}()
}
@@ -321,6 +493,7 @@
t.Fatal(err)
}
checkLineComments(t, "libgo2.h")
+ checkArchive(t, "libgo2.a")
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a")
if runtime.Compiler == "gccgo" {
@@ -350,7 +523,7 @@
defer func() {
os.Remove("libgo2.a")
os.Remove("libgo2.h")
- os.Remove("testp")
+ os.Remove("testp" + exeSuffix)
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
}()
}
@@ -361,6 +534,7 @@
t.Fatal(err)
}
checkLineComments(t, "libgo2.h")
+ checkArchive(t, "libgo2.a")
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
if runtime.Compiler == "gccgo" {
@@ -374,7 +548,7 @@
cmd = exec.Command(bin[0], append(bin[1:], "1")...)
out, err := cmd.CombinedOutput()
- t.Logf("%s", out)
+ t.Logf("%v\n%s", cmd.Args, out)
expectSignal(t, err, syscall.SIGSEGV)
// SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
@@ -383,7 +557,9 @@
cmd = exec.Command(bin[0], append(bin[1:], "3")...)
out, err = cmd.CombinedOutput()
- t.Logf("%s", out)
+ if len(out) > 0 {
+ t.Logf("%s", out)
+ }
expectSignal(t, err, syscall.SIGPIPE)
}
}
@@ -400,7 +576,7 @@
defer func() {
os.Remove("libgo2.a")
os.Remove("libgo2.h")
- os.Remove("testp")
+ os.Remove("testp" + exeSuffix)
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
}()
}
@@ -411,6 +587,7 @@
t.Fatal(err)
}
checkLineComments(t, "libgo2.h")
+ checkArchive(t, "libgo2.a")
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
if runtime.Compiler == "gccgo" {
@@ -517,7 +694,7 @@
defer func() {
os.Remove("libgo3.a")
os.Remove("libgo3.h")
- os.Remove("testp")
+ os.Remove("testp" + exeSuffix)
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
}()
}
@@ -528,6 +705,7 @@
t.Fatal(err)
}
checkLineComments(t, "libgo3.h")
+ checkArchive(t, "libgo3.a")
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a")
if runtime.Compiler == "gccgo" {
@@ -554,7 +732,7 @@
defer func() {
os.Remove("libgo4.a")
os.Remove("libgo4.h")
- os.Remove("testp")
+ os.Remove("testp" + exeSuffix)
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
}()
}
@@ -565,6 +743,7 @@
t.Fatal(err)
}
checkLineComments(t, "libgo4.h")
+ checkArchive(t, "libgo4.a")
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a")
if runtime.Compiler == "gccgo" {
@@ -747,25 +926,29 @@
}
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "./libgo6")
- if out, err := cmd.CombinedOutput(); err != nil {
- t.Logf("%s", out)
+ out, err := cmd.CombinedOutput()
+ t.Logf("%v\n%s", cmd.Args, out)
+ if err != nil {
t.Fatal(err)
}
checkLineComments(t, "libgo6.h")
+ checkArchive(t, "libgo6.a")
ccArgs := append(cc, "-o", "testp6"+exeSuffix, "main6.c", "libgo6.a")
if runtime.Compiler == "gccgo" {
ccArgs = append(ccArgs, "-lgo")
}
- if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
- t.Logf("%s", out)
+ out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
+ t.Logf("%v\n%s", ccArgs, out)
+ if err != nil {
t.Fatal(err)
}
argv := cmdToRun("./testp6")
cmd = exec.Command(argv[0], argv[1:]...)
- if out, err := cmd.CombinedOutput(); err != nil {
- t.Logf("%s", out)
+ out, err = cmd.CombinedOutput()
+ t.Logf("%v\n%s", argv, out)
+ if err != nil {
t.Fatal(err)
}
}
@@ -788,13 +971,13 @@
}
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "./libgo2")
- t.Log(cmd.Args)
out, err := cmd.CombinedOutput()
- t.Logf("%s", out)
+ t.Logf("%v\n%s", cmd.Args, out)
if err != nil {
t.Fatal(err)
}
checkLineComments(t, "libgo2.h")
+ checkArchive(t, "libgo2.a")
exe := "./testnoshared" + exeSuffix
@@ -804,23 +987,22 @@
if runtime.Compiler == "gccgo" {
ccArgs = append(ccArgs, "-lgo")
}
- t.Log(ccArgs)
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
+ t.Logf("%v\n%s", ccArgs, out)
// If -no-pie unrecognized, try -nopie if this is possibly clang
if err != nil && bytes.Contains(out, []byte("unknown")) && !strings.Contains(cc[0], "gcc") {
ccArgs = append(cc, "-o", exe, "-nopie", "main5.c", "libgo2.a")
- t.Log(ccArgs)
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
+ t.Logf("%v\n%s", ccArgs, out)
}
// Don't use either -no-pie or -nopie
if err != nil && bytes.Contains(out, []byte("unrecognized")) {
- ccArgs := append(cc, "-o", exe, "main5.c", "libgo2.a")
- t.Log(ccArgs)
+ ccArgs = append(cc, "-o", exe, "main5.c", "libgo2.a")
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
+ t.Logf("%v\n%s", ccArgs, out)
}
- t.Logf("%s", out)
if err != nil {
t.Fatal(err)
}
@@ -829,17 +1011,15 @@
}
binArgs := append(cmdToRun(exe), "1")
- t.Log(binArgs)
out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
- t.Logf("%s", out)
+ t.Logf("%v\n%s", binArgs, out)
expectSignal(t, err, syscall.SIGSEGV)
// SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
binArgs := append(cmdToRun(exe), "3")
- t.Log(binArgs)
out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
- t.Logf("%s", out)
+ t.Logf("%v\n%s", binArgs, out)
expectSignal(t, err, syscall.SIGPIPE)
}
}
@@ -894,26 +1074,29 @@
}
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo7.a", "./libgo7")
- if out, err := cmd.CombinedOutput(); err != nil {
- t.Logf("%s", out)
+ out, err := cmd.CombinedOutput()
+ t.Logf("%v\n%s", cmd.Args, out)
+ if err != nil {
t.Fatal(err)
}
checkLineComments(t, "libgo7.h")
+ checkArchive(t, "libgo7.a")
ccArgs := append(cc, "-o", "testp7"+exeSuffix, "main7.c", "libgo7.a")
if runtime.Compiler == "gccgo" {
ccArgs = append(ccArgs, "-lgo")
}
- if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
- t.Logf("%s", out)
+ out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
+ t.Logf("%v\n%s", ccArgs, out)
+ if err != nil {
t.Fatal(err)
}
argv := cmdToRun("./testp7")
cmd = exec.Command(argv[0], argv[1:]...)
- var sb strings.Builder
- cmd.Stdout = &sb
- cmd.Stderr = &sb
+ sb := new(strings.Builder)
+ cmd.Stdout = sb
+ cmd.Stderr = sb
if err := cmd.Start(); err != nil {
t.Fatal(err)
}
@@ -926,8 +1109,9 @@
)
defer timer.Stop()
- if err := cmd.Wait(); err != nil {
- t.Log(sb.String())
+ err = cmd.Wait()
+ t.Logf("%v\n%s", cmd.Args, sb)
+ if err != nil {
t.Error(err)
}
}
@@ -949,23 +1133,26 @@
}
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo8.a", "./libgo8")
- if out, err := cmd.CombinedOutput(); err != nil {
- t.Logf("%s", out)
+ out, err := cmd.CombinedOutput()
+ t.Logf("%v\n%s", cmd.Args, out)
+ if err != nil {
t.Fatal(err)
}
checkLineComments(t, "libgo8.h")
+ checkArchive(t, "libgo8.a")
ccArgs := append(cc, "-o", "testp8"+exeSuffix, "main8.c", "libgo8.a")
- if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
- t.Logf("%s", out)
+ out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
+ t.Logf("%v\n%s", ccArgs, out)
+ if err != nil {
t.Fatal(err)
}
argv := cmdToRun("./testp8")
cmd = exec.Command(argv[0], argv[1:]...)
- var sb strings.Builder
- cmd.Stdout = &sb
- cmd.Stderr = &sb
+ sb := new(strings.Builder)
+ cmd.Stdout = sb
+ cmd.Stderr = sb
if err := cmd.Start(); err != nil {
t.Fatal(err)
}
@@ -978,8 +1165,9 @@
)
defer timer.Stop()
- if err := cmd.Wait(); err != nil {
- t.Log(sb.String())
+ err = cmd.Wait()
+ t.Logf("%v\n%s", cmd.Args, sb)
+ if err != nil {
t.Error(err)
}
}
diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go
index 13ec876..c9e9e5f 100644
--- a/misc/cgo/testcshared/cshared_test.go
+++ b/misc/cgo/testcshared/cshared_test.go
@@ -117,6 +117,9 @@
}
cc = append(cc, "-I", filepath.Join("pkg", libgodir))
+ // Force reallocation (and avoid aliasing bugs) for parallel tests that append to cc.
+ cc = cc[:len(cc):len(cc)]
+
if GOOS == "windows" {
exeSuffix = ".exe"
}
diff --git a/misc/cgo/testplugin/plugin_test.go b/misc/cgo/testplugin/plugin_test.go
index a6accc1..10c5db2 100644
--- a/misc/cgo/testplugin/plugin_test.go
+++ b/misc/cgo/testplugin/plugin_test.go
@@ -289,3 +289,31 @@
goCmd(t, "build", "-o", "issue44956.exe", "./issue44956/main.go")
run(t, "./issue44956.exe")
}
+
+func TestForkExec(t *testing.T) {
+ // Issue 38824: importing the plugin package causes it hang in forkExec on darwin.
+
+ t.Parallel()
+ goCmd(t, "build", "-o", "forkexec.exe", "./forkexec/main.go")
+
+ var cmd *exec.Cmd
+ done := make(chan int, 1)
+
+ go func() {
+ for i := 0; i < 100; i++ {
+ cmd = exec.Command("./forkexec.exe", "1")
+ err := cmd.Run()
+ if err != nil {
+ t.Errorf("running command failed: %v", err)
+ break
+ }
+ }
+ done <- 1
+ }()
+ select {
+ case <-done:
+ case <-time.After(5 * time.Minute):
+ cmd.Process.Kill()
+ t.Fatalf("subprocess hang")
+ }
+}
diff --git a/misc/cgo/testplugin/testdata/forkexec/main.go b/misc/cgo/testplugin/testdata/forkexec/main.go
new file mode 100644
index 0000000..3169ff5
--- /dev/null
+++ b/misc/cgo/testplugin/testdata/forkexec/main.go
@@ -0,0 +1,30 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "os"
+ "os/exec"
+ _ "plugin"
+ "sync"
+)
+
+func main() {
+ if os.Args[1] != "1" {
+ return
+ }
+
+ var wg sync.WaitGroup
+ for i := 0; i < 8; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ // does not matter what we exec, just exec itself
+ cmd := exec.Command("./forkexec.exe", "0")
+ cmd.Run()
+ }()
+ }
+ wg.Wait()
+}
diff --git a/misc/cgo/testsanitizers/asan_test.go b/misc/cgo/testsanitizers/asan_test.go
index dbcce2f..22dcf23 100644
--- a/misc/cgo/testsanitizers/asan_test.go
+++ b/misc/cgo/testsanitizers/asan_test.go
@@ -33,11 +33,13 @@
cases := []struct {
src string
memoryAccessError string
+ errorLocation string
}{
- {src: "asan1_fail.go", memoryAccessError: "heap-use-after-free"},
- {src: "asan2_fail.go", memoryAccessError: "heap-buffer-overflow"},
- {src: "asan3_fail.go", memoryAccessError: "use-after-poison"},
- {src: "asan4_fail.go", memoryAccessError: "use-after-poison"},
+ {src: "asan1_fail.go", memoryAccessError: "heap-use-after-free", errorLocation: "asan1_fail.go:25"},
+ {src: "asan2_fail.go", memoryAccessError: "heap-buffer-overflow", errorLocation: "asan2_fail.go:31"},
+ {src: "asan3_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan3_fail.go:13"},
+ {src: "asan4_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan4_fail.go:13"},
+ {src: "asan5_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan5_fail.go:18"},
{src: "asan_useAfterReturn.go"},
}
for _, tc := range cases {
@@ -54,8 +56,21 @@
cmd := hangProneCmd(outPath)
if tc.memoryAccessError != "" {
- out, err := cmd.CombinedOutput()
- if err != nil && strings.Contains(string(out), tc.memoryAccessError) {
+ outb, err := cmd.CombinedOutput()
+ out := string(outb)
+ if err != nil && strings.Contains(out, tc.memoryAccessError) {
+ // This string is output if the
+ // sanitizer library needs a
+ // symbolizer program and can't find it.
+ const noSymbolizer = "external symbolizer"
+ // Check if -asan option can correctly print where the error occurred.
+ if tc.errorLocation != "" &&
+ !strings.Contains(out, tc.errorLocation) &&
+ !strings.Contains(out, noSymbolizer) &&
+ compilerSupportsLocation() {
+
+ t.Errorf("%#q exited without expected location of the error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.errorLocation, out)
+ }
return
}
t.Fatalf("%#q exited without expected memory access error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.memoryAccessError, out)
diff --git a/misc/cgo/testsanitizers/cc_test.go b/misc/cgo/testsanitizers/cc_test.go
index b776afa..05b7793 100644
--- a/misc/cgo/testsanitizers/cc_test.go
+++ b/misc/cgo/testsanitizers/cc_test.go
@@ -218,6 +218,23 @@
return compiler.version, compiler.err
}
+// compilerSupportsLocation reports whether the compiler should be
+// able to provide file/line information in backtraces.
+func compilerSupportsLocation() bool {
+ compiler, err := compilerVersion()
+ if err != nil {
+ return false
+ }
+ switch compiler.name {
+ case "gcc":
+ return compiler.major >= 10
+ case "clang":
+ return true
+ default:
+ return false
+ }
+}
+
type compilerCheck struct {
once sync.Once
err error
@@ -269,6 +286,8 @@
case "address":
c.goFlags = append(c.goFlags, "-asan")
+ // Set the debug mode to print the C stack trace.
+ c.cFlags = append(c.cFlags, "-g")
default:
panic(fmt.Sprintf("unrecognized sanitizer: %q", sanitizer))
diff --git a/misc/cgo/testsanitizers/testdata/asan1_fail.go b/misc/cgo/testsanitizers/testdata/asan1_fail.go
index e60db76..80289e5 100644
--- a/misc/cgo/testsanitizers/testdata/asan1_fail.go
+++ b/misc/cgo/testsanitizers/testdata/asan1_fail.go
@@ -22,7 +22,7 @@
// C passes Go an invalid pointer.
a := C.test()
// Use after free
- *a = 2
+ *a = 2 // BOOM
// We shouldn't get here; asan should stop us first.
fmt.Println(*a)
}
diff --git a/misc/cgo/testsanitizers/testdata/asan2_fail.go b/misc/cgo/testsanitizers/testdata/asan2_fail.go
index e35670c..3ab0608 100644
--- a/misc/cgo/testsanitizers/testdata/asan2_fail.go
+++ b/misc/cgo/testsanitizers/testdata/asan2_fail.go
@@ -28,7 +28,7 @@
a := C.f()
q5 := (*C.int)(unsafe.Add(unsafe.Pointer(a), 4*5))
// Access to C pointer out of bounds.
- *q5 = 100
+ *q5 = 100 // BOOM
// We shouldn't get here; asan should stop us first.
fmt.Printf("q5: %d, %x\n", *q5, q5)
}
diff --git a/misc/cgo/testsanitizers/testdata/asan5_fail.go b/misc/cgo/testsanitizers/testdata/asan5_fail.go
new file mode 100644
index 0000000..d6853ea
--- /dev/null
+++ b/misc/cgo/testsanitizers/testdata/asan5_fail.go
@@ -0,0 +1,21 @@
+package main
+
+import (
+ "fmt"
+ "runtime"
+ "unsafe"
+)
+
+func main() {
+ p := new([1024 * 1000]int)
+ p[0] = 10
+ r := bar(&p[1024*1000-1])
+ fmt.Printf("r value is %d", r)
+}
+
+func bar(a *int) int {
+ p := unsafe.Add(unsafe.Pointer(a), 2*unsafe.Sizeof(int(1)))
+ runtime.ASanWrite(p, 8) // BOOM
+ *((*int)(p)) = 10
+ return *((*int)(p))
+}
diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go
index d5d018f..b78083b 100644
--- a/misc/cgo/testshared/shared_test.go
+++ b/misc/cgo/testshared/shared_test.go
@@ -56,7 +56,7 @@
// t.Fatalf if the command fails.
func goCmd(t *testing.T, args ...string) string {
newargs := []string{args[0]}
- if *testX {
+ if *testX && args[0] != "env" {
newargs = append(newargs, "-x")
}
newargs = append(newargs, args[1:]...)
@@ -462,7 +462,9 @@
run(t, "trivial executable", "../../bin/trivial")
AssertIsLinkedTo(t, "../../bin/trivial", soname)
AssertHasRPath(t, "../../bin/trivial", gorootInstallDir)
- checkSize(t, "../../bin/trivial", 100000) // it is 19K on linux/amd64, 100K should be enough
+ // It is 19K on linux/amd64, with separate-code in binutils ld and 64k being most common alignment
+ // 4*64k should be enough, but this might need revision eventually.
+ checkSize(t, "../../bin/trivial", 256000)
}
// Build a trivial program in PIE mode that links against the shared runtime and check it runs.
@@ -471,7 +473,9 @@
run(t, "trivial executable", "./trivial.pie")
AssertIsLinkedTo(t, "./trivial.pie", soname)
AssertHasRPath(t, "./trivial.pie", gorootInstallDir)
- checkSize(t, "./trivial.pie", 100000) // it is 19K on linux/amd64, 100K should be enough
+ // It is 19K on linux/amd64, with separate-code in binutils ld and 64k being most common alignment
+ // 4*64k should be enough, but this might need revision eventually.
+ checkSize(t, "./trivial.pie", 256000)
}
// Check that the file size does not exceed a limit.
diff --git a/misc/reboot/overlaydir_test.go b/misc/reboot/overlaydir_test.go
index c446d08..71faf09 100644
--- a/misc/reboot/overlaydir_test.go
+++ b/misc/reboot/overlaydir_test.go
@@ -6,6 +6,7 @@
import (
"io"
+ "io/fs"
"os"
"path/filepath"
"strings"
@@ -26,10 +27,14 @@
return err
}
- return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
+ return filepath.WalkDir(srcRoot, func(srcPath string, entry fs.DirEntry, err error) error {
if err != nil || srcPath == srcRoot {
return err
}
+ if filepath.Base(srcPath) == "testdata" {
+ // We're just building, so no need to copy those.
+ return fs.SkipDir
+ }
suffix := strings.TrimPrefix(srcPath, srcRoot)
for len(suffix) > 0 && suffix[0] == filepath.Separator {
@@ -37,6 +42,7 @@
}
dstPath := filepath.Join(dstRoot, suffix)
+ info, err := entry.Info()
perm := info.Mode() & os.ModePerm
if info.Mode()&os.ModeSymlink != 0 {
info, err = os.Stat(srcPath)
@@ -46,14 +52,15 @@
perm = info.Mode() & os.ModePerm
}
- // Always copy directories (don't symlink them).
+ // Always make copies of directories.
// If we add a file in the overlay, we don't want to add it in the original.
if info.IsDir() {
return os.MkdirAll(dstPath, perm|0200)
}
- // If the OS supports symlinks, use them instead of copying bytes.
- if err := os.Symlink(srcPath, dstPath); err == nil {
+ // If we can use a hard link, do that instead of copying bytes.
+ // Go builds don't like symlinks in some cases, such as go:embed.
+ if err := os.Link(srcPath, dstPath); err == nil {
return nil
}
diff --git a/misc/reboot/reboot_test.go b/misc/reboot/reboot_test.go
index ef164d3..a134aff 100644
--- a/misc/reboot/reboot_test.go
+++ b/misc/reboot/reboot_test.go
@@ -12,6 +12,7 @@
"path/filepath"
"runtime"
"testing"
+ "time"
)
func TestRepeatBootstrap(t *testing.T) {
@@ -19,16 +20,14 @@
t.Skipf("skipping test that rebuilds the entire toolchain")
}
- goroot, err := os.MkdirTemp("", "reboot-goroot")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(goroot)
+ goroot := t.TempDir()
gorootSrc := filepath.Join(goroot, "src")
+ overlayStart := time.Now()
if err := overlayDir(gorootSrc, filepath.Join(runtime.GOROOT(), "src")); err != nil {
t.Fatal(err)
}
+ t.Logf("GOROOT/src overlay set up in %s", time.Since(overlayStart))
if err := os.WriteFile(filepath.Join(goroot, "VERSION"), []byte(runtime.Version()), 0666); err != nil {
t.Fatal(err)
diff --git a/pkg/include/funcdata.h b/pkg/include/funcdata.h
index a454dca..2e2bb30 100644
--- a/pkg/include/funcdata.h
+++ b/pkg/include/funcdata.h
@@ -20,6 +20,7 @@
#define FUNCDATA_OpenCodedDeferInfo 4 /* info for func with open-coded defers */
#define FUNCDATA_ArgInfo 5
#define FUNCDATA_ArgLiveInfo 6
+#define FUNCDATA_WrapInfo 7
// Pseudo-assembly statements.
diff --git a/pkg/linux_amd64/archive/tar.a b/pkg/linux_amd64/archive/tar.a
index 21fca8e..79344af 100644
--- a/pkg/linux_amd64/archive/tar.a
+++ b/pkg/linux_amd64/archive/tar.a
Binary files differ
diff --git a/pkg/linux_amd64/archive/zip.a b/pkg/linux_amd64/archive/zip.a
index eb094c8..18d312f 100644
--- a/pkg/linux_amd64/archive/zip.a
+++ b/pkg/linux_amd64/archive/zip.a
Binary files differ
diff --git a/pkg/linux_amd64/bufio.a b/pkg/linux_amd64/bufio.a
index 6e363ab..c0b1550 100644
--- a/pkg/linux_amd64/bufio.a
+++ b/pkg/linux_amd64/bufio.a
Binary files differ
diff --git a/pkg/linux_amd64/bytes.a b/pkg/linux_amd64/bytes.a
index fcdb91b..db4e6c6 100644
--- a/pkg/linux_amd64/bytes.a
+++ b/pkg/linux_amd64/bytes.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/asm/internal/arch.a b/pkg/linux_amd64/cmd/asm/internal/arch.a
index feac16e..f61c7fc 100644
--- a/pkg/linux_amd64/cmd/asm/internal/arch.a
+++ b/pkg/linux_amd64/cmd/asm/internal/arch.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/asm/internal/asm.a b/pkg/linux_amd64/cmd/asm/internal/asm.a
index d407f7e..0ae26ee 100644
--- a/pkg/linux_amd64/cmd/asm/internal/asm.a
+++ b/pkg/linux_amd64/cmd/asm/internal/asm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/asm/internal/flags.a b/pkg/linux_amd64/cmd/asm/internal/flags.a
index 562e763..6b32a30 100644
--- a/pkg/linux_amd64/cmd/asm/internal/flags.a
+++ b/pkg/linux_amd64/cmd/asm/internal/flags.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/asm/internal/lex.a b/pkg/linux_amd64/cmd/asm/internal/lex.a
index 9aa7dbe..fdb7a40 100644
--- a/pkg/linux_amd64/cmd/asm/internal/lex.a
+++ b/pkg/linux_amd64/cmd/asm/internal/lex.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/abi.a b/pkg/linux_amd64/cmd/compile/internal/abi.a
index b192911..ebd5008 100644
--- a/pkg/linux_amd64/cmd/compile/internal/abi.a
+++ b/pkg/linux_amd64/cmd/compile/internal/abi.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/amd64.a b/pkg/linux_amd64/cmd/compile/internal/amd64.a
index 96e9110..22290e0 100644
--- a/pkg/linux_amd64/cmd/compile/internal/amd64.a
+++ b/pkg/linux_amd64/cmd/compile/internal/amd64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/arm.a b/pkg/linux_amd64/cmd/compile/internal/arm.a
index 83806a1..b488021 100644
--- a/pkg/linux_amd64/cmd/compile/internal/arm.a
+++ b/pkg/linux_amd64/cmd/compile/internal/arm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/arm64.a b/pkg/linux_amd64/cmd/compile/internal/arm64.a
index bd7dc68..e3dc7bd 100644
--- a/pkg/linux_amd64/cmd/compile/internal/arm64.a
+++ b/pkg/linux_amd64/cmd/compile/internal/arm64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/base.a b/pkg/linux_amd64/cmd/compile/internal/base.a
index 045e40c..06dcdd9 100644
--- a/pkg/linux_amd64/cmd/compile/internal/base.a
+++ b/pkg/linux_amd64/cmd/compile/internal/base.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/bitvec.a b/pkg/linux_amd64/cmd/compile/internal/bitvec.a
index 47742ae..e0a51c7 100644
--- a/pkg/linux_amd64/cmd/compile/internal/bitvec.a
+++ b/pkg/linux_amd64/cmd/compile/internal/bitvec.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/deadcode.a b/pkg/linux_amd64/cmd/compile/internal/deadcode.a
index 55eebf2..f2dd31d 100644
--- a/pkg/linux_amd64/cmd/compile/internal/deadcode.a
+++ b/pkg/linux_amd64/cmd/compile/internal/deadcode.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/devirtualize.a b/pkg/linux_amd64/cmd/compile/internal/devirtualize.a
index da62039..ae621db 100644
--- a/pkg/linux_amd64/cmd/compile/internal/devirtualize.a
+++ b/pkg/linux_amd64/cmd/compile/internal/devirtualize.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/dwarfgen.a b/pkg/linux_amd64/cmd/compile/internal/dwarfgen.a
index 01c8634..c13f565 100644
--- a/pkg/linux_amd64/cmd/compile/internal/dwarfgen.a
+++ b/pkg/linux_amd64/cmd/compile/internal/dwarfgen.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/escape.a b/pkg/linux_amd64/cmd/compile/internal/escape.a
index a48a69d..26c8934 100644
--- a/pkg/linux_amd64/cmd/compile/internal/escape.a
+++ b/pkg/linux_amd64/cmd/compile/internal/escape.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/gc.a b/pkg/linux_amd64/cmd/compile/internal/gc.a
index 3ba34ce..f7de97e 100644
--- a/pkg/linux_amd64/cmd/compile/internal/gc.a
+++ b/pkg/linux_amd64/cmd/compile/internal/gc.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/importer.a b/pkg/linux_amd64/cmd/compile/internal/importer.a
index d61fa7a..a1831fc 100644
--- a/pkg/linux_amd64/cmd/compile/internal/importer.a
+++ b/pkg/linux_amd64/cmd/compile/internal/importer.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/inline.a b/pkg/linux_amd64/cmd/compile/internal/inline.a
index 8960e8c..aa77c96 100644
--- a/pkg/linux_amd64/cmd/compile/internal/inline.a
+++ b/pkg/linux_amd64/cmd/compile/internal/inline.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/ir.a b/pkg/linux_amd64/cmd/compile/internal/ir.a
index a1f046f..2611ebb 100644
--- a/pkg/linux_amd64/cmd/compile/internal/ir.a
+++ b/pkg/linux_amd64/cmd/compile/internal/ir.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/liveness.a b/pkg/linux_amd64/cmd/compile/internal/liveness.a
index dbd3343..c7ddf0d 100644
--- a/pkg/linux_amd64/cmd/compile/internal/liveness.a
+++ b/pkg/linux_amd64/cmd/compile/internal/liveness.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/logopt.a b/pkg/linux_amd64/cmd/compile/internal/logopt.a
index b54ef59..7aa7c74 100644
--- a/pkg/linux_amd64/cmd/compile/internal/logopt.a
+++ b/pkg/linux_amd64/cmd/compile/internal/logopt.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/mips.a b/pkg/linux_amd64/cmd/compile/internal/mips.a
index 9930c17..6040473 100644
--- a/pkg/linux_amd64/cmd/compile/internal/mips.a
+++ b/pkg/linux_amd64/cmd/compile/internal/mips.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/mips64.a b/pkg/linux_amd64/cmd/compile/internal/mips64.a
index c068aa3..8073759 100644
--- a/pkg/linux_amd64/cmd/compile/internal/mips64.a
+++ b/pkg/linux_amd64/cmd/compile/internal/mips64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/noder.a b/pkg/linux_amd64/cmd/compile/internal/noder.a
index 8fd6bde..02ce0a5 100644
--- a/pkg/linux_amd64/cmd/compile/internal/noder.a
+++ b/pkg/linux_amd64/cmd/compile/internal/noder.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/objw.a b/pkg/linux_amd64/cmd/compile/internal/objw.a
index 4f0dea1..9fd01a2 100644
--- a/pkg/linux_amd64/cmd/compile/internal/objw.a
+++ b/pkg/linux_amd64/cmd/compile/internal/objw.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/pkginit.a b/pkg/linux_amd64/cmd/compile/internal/pkginit.a
index e63932b..b6c90e4 100644
--- a/pkg/linux_amd64/cmd/compile/internal/pkginit.a
+++ b/pkg/linux_amd64/cmd/compile/internal/pkginit.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/ppc64.a b/pkg/linux_amd64/cmd/compile/internal/ppc64.a
index b06e170..ea88ce6 100644
--- a/pkg/linux_amd64/cmd/compile/internal/ppc64.a
+++ b/pkg/linux_amd64/cmd/compile/internal/ppc64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/reflectdata.a b/pkg/linux_amd64/cmd/compile/internal/reflectdata.a
index a9373b4..02428af 100644
--- a/pkg/linux_amd64/cmd/compile/internal/reflectdata.a
+++ b/pkg/linux_amd64/cmd/compile/internal/reflectdata.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/riscv64.a b/pkg/linux_amd64/cmd/compile/internal/riscv64.a
index ca1ddf6..d1e6596 100644
--- a/pkg/linux_amd64/cmd/compile/internal/riscv64.a
+++ b/pkg/linux_amd64/cmd/compile/internal/riscv64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/s390x.a b/pkg/linux_amd64/cmd/compile/internal/s390x.a
index bb2b090..c844b7f 100644
--- a/pkg/linux_amd64/cmd/compile/internal/s390x.a
+++ b/pkg/linux_amd64/cmd/compile/internal/s390x.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/ssa.a b/pkg/linux_amd64/cmd/compile/internal/ssa.a
index f0ff485..326baff 100644
--- a/pkg/linux_amd64/cmd/compile/internal/ssa.a
+++ b/pkg/linux_amd64/cmd/compile/internal/ssa.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/ssagen.a b/pkg/linux_amd64/cmd/compile/internal/ssagen.a
index 772c734..5725d50 100644
--- a/pkg/linux_amd64/cmd/compile/internal/ssagen.a
+++ b/pkg/linux_amd64/cmd/compile/internal/ssagen.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/staticdata.a b/pkg/linux_amd64/cmd/compile/internal/staticdata.a
index 90f7fcc..f7e806e 100644
--- a/pkg/linux_amd64/cmd/compile/internal/staticdata.a
+++ b/pkg/linux_amd64/cmd/compile/internal/staticdata.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/staticinit.a b/pkg/linux_amd64/cmd/compile/internal/staticinit.a
index 3ce3880..6d9a016 100644
--- a/pkg/linux_amd64/cmd/compile/internal/staticinit.a
+++ b/pkg/linux_amd64/cmd/compile/internal/staticinit.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/syntax.a b/pkg/linux_amd64/cmd/compile/internal/syntax.a
index 2c9abe2..84ecc4d 100644
--- a/pkg/linux_amd64/cmd/compile/internal/syntax.a
+++ b/pkg/linux_amd64/cmd/compile/internal/syntax.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/test.a b/pkg/linux_amd64/cmd/compile/internal/test.a
index 3cdb292..997b0df 100644
--- a/pkg/linux_amd64/cmd/compile/internal/test.a
+++ b/pkg/linux_amd64/cmd/compile/internal/test.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/typebits.a b/pkg/linux_amd64/cmd/compile/internal/typebits.a
index efd9821..d2d6eb2 100644
--- a/pkg/linux_amd64/cmd/compile/internal/typebits.a
+++ b/pkg/linux_amd64/cmd/compile/internal/typebits.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/typecheck.a b/pkg/linux_amd64/cmd/compile/internal/typecheck.a
index fb07393..b6feb97 100644
--- a/pkg/linux_amd64/cmd/compile/internal/typecheck.a
+++ b/pkg/linux_amd64/cmd/compile/internal/typecheck.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/types.a b/pkg/linux_amd64/cmd/compile/internal/types.a
index 642de52..98170e1 100644
--- a/pkg/linux_amd64/cmd/compile/internal/types.a
+++ b/pkg/linux_amd64/cmd/compile/internal/types.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/types2.a b/pkg/linux_amd64/cmd/compile/internal/types2.a
index caf0e47..663ebaf 100644
--- a/pkg/linux_amd64/cmd/compile/internal/types2.a
+++ b/pkg/linux_amd64/cmd/compile/internal/types2.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/walk.a b/pkg/linux_amd64/cmd/compile/internal/walk.a
index af9457c..0b23d2a 100644
--- a/pkg/linux_amd64/cmd/compile/internal/walk.a
+++ b/pkg/linux_amd64/cmd/compile/internal/walk.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/wasm.a b/pkg/linux_amd64/cmd/compile/internal/wasm.a
index 09eca9d..8f86c0b 100644
--- a/pkg/linux_amd64/cmd/compile/internal/wasm.a
+++ b/pkg/linux_amd64/cmd/compile/internal/wasm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/compile/internal/x86.a b/pkg/linux_amd64/cmd/compile/internal/x86.a
index ec873f2..f92142b 100644
--- a/pkg/linux_amd64/cmd/compile/internal/x86.a
+++ b/pkg/linux_amd64/cmd/compile/internal/x86.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/auth.a b/pkg/linux_amd64/cmd/go/internal/auth.a
index 8ef753c..41f479b 100644
--- a/pkg/linux_amd64/cmd/go/internal/auth.a
+++ b/pkg/linux_amd64/cmd/go/internal/auth.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/base.a b/pkg/linux_amd64/cmd/go/internal/base.a
index 33772e1..dfe8da4 100644
--- a/pkg/linux_amd64/cmd/go/internal/base.a
+++ b/pkg/linux_amd64/cmd/go/internal/base.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/bug.a b/pkg/linux_amd64/cmd/go/internal/bug.a
index 2b45af9..79537ef 100644
--- a/pkg/linux_amd64/cmd/go/internal/bug.a
+++ b/pkg/linux_amd64/cmd/go/internal/bug.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/cache.a b/pkg/linux_amd64/cmd/go/internal/cache.a
index 854de86..f9e09da 100644
--- a/pkg/linux_amd64/cmd/go/internal/cache.a
+++ b/pkg/linux_amd64/cmd/go/internal/cache.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/cfg.a b/pkg/linux_amd64/cmd/go/internal/cfg.a
index cee4a96..2d664aa 100644
--- a/pkg/linux_amd64/cmd/go/internal/cfg.a
+++ b/pkg/linux_amd64/cmd/go/internal/cfg.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/clean.a b/pkg/linux_amd64/cmd/go/internal/clean.a
index cd67a74..666ca92 100644
--- a/pkg/linux_amd64/cmd/go/internal/clean.a
+++ b/pkg/linux_amd64/cmd/go/internal/clean.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/cmdflag.a b/pkg/linux_amd64/cmd/go/internal/cmdflag.a
index e14ff60..f39e6c0 100644
--- a/pkg/linux_amd64/cmd/go/internal/cmdflag.a
+++ b/pkg/linux_amd64/cmd/go/internal/cmdflag.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/doc.a b/pkg/linux_amd64/cmd/go/internal/doc.a
index 2f79d80..a6040f0 100644
--- a/pkg/linux_amd64/cmd/go/internal/doc.a
+++ b/pkg/linux_amd64/cmd/go/internal/doc.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/envcmd.a b/pkg/linux_amd64/cmd/go/internal/envcmd.a
index 2b93a7f..e8d59ef 100644
--- a/pkg/linux_amd64/cmd/go/internal/envcmd.a
+++ b/pkg/linux_amd64/cmd/go/internal/envcmd.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/fix.a b/pkg/linux_amd64/cmd/go/internal/fix.a
index 6ef3813..2e9b751 100644
--- a/pkg/linux_amd64/cmd/go/internal/fix.a
+++ b/pkg/linux_amd64/cmd/go/internal/fix.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/fmtcmd.a b/pkg/linux_amd64/cmd/go/internal/fmtcmd.a
index 0d9716d..680612f 100644
--- a/pkg/linux_amd64/cmd/go/internal/fmtcmd.a
+++ b/pkg/linux_amd64/cmd/go/internal/fmtcmd.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/fsys.a b/pkg/linux_amd64/cmd/go/internal/fsys.a
index 7934944..8eeebca 100644
--- a/pkg/linux_amd64/cmd/go/internal/fsys.a
+++ b/pkg/linux_amd64/cmd/go/internal/fsys.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/generate.a b/pkg/linux_amd64/cmd/go/internal/generate.a
index 244515e..0c64210 100644
--- a/pkg/linux_amd64/cmd/go/internal/generate.a
+++ b/pkg/linux_amd64/cmd/go/internal/generate.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/get.a b/pkg/linux_amd64/cmd/go/internal/get.a
index 5d3bd25..a514a34 100644
--- a/pkg/linux_amd64/cmd/go/internal/get.a
+++ b/pkg/linux_amd64/cmd/go/internal/get.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/help.a b/pkg/linux_amd64/cmd/go/internal/help.a
index 1ef7cc1..c6bd88f 100644
--- a/pkg/linux_amd64/cmd/go/internal/help.a
+++ b/pkg/linux_amd64/cmd/go/internal/help.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/imports.a b/pkg/linux_amd64/cmd/go/internal/imports.a
index 82b3ba6..11d6200 100644
--- a/pkg/linux_amd64/cmd/go/internal/imports.a
+++ b/pkg/linux_amd64/cmd/go/internal/imports.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/list.a b/pkg/linux_amd64/cmd/go/internal/list.a
index ffcadd0..a159c63 100644
--- a/pkg/linux_amd64/cmd/go/internal/list.a
+++ b/pkg/linux_amd64/cmd/go/internal/list.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/load.a b/pkg/linux_amd64/cmd/go/internal/load.a
index d5b65e4..2face97 100644
--- a/pkg/linux_amd64/cmd/go/internal/load.a
+++ b/pkg/linux_amd64/cmd/go/internal/load.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/lockedfile.a b/pkg/linux_amd64/cmd/go/internal/lockedfile.a
index 179204a..b765f73 100644
--- a/pkg/linux_amd64/cmd/go/internal/lockedfile.a
+++ b/pkg/linux_amd64/cmd/go/internal/lockedfile.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/lockedfile/internal/filelock.a b/pkg/linux_amd64/cmd/go/internal/lockedfile/internal/filelock.a
index 2aeb5d0..56f5974 100644
--- a/pkg/linux_amd64/cmd/go/internal/lockedfile/internal/filelock.a
+++ b/pkg/linux_amd64/cmd/go/internal/lockedfile/internal/filelock.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/modcmd.a b/pkg/linux_amd64/cmd/go/internal/modcmd.a
index 92b9157..78476aa 100644
--- a/pkg/linux_amd64/cmd/go/internal/modcmd.a
+++ b/pkg/linux_amd64/cmd/go/internal/modcmd.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/modconv.a b/pkg/linux_amd64/cmd/go/internal/modconv.a
index a817bca..33d7934 100644
--- a/pkg/linux_amd64/cmd/go/internal/modconv.a
+++ b/pkg/linux_amd64/cmd/go/internal/modconv.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/modfetch.a b/pkg/linux_amd64/cmd/go/internal/modfetch.a
index 670de6b..2e0b8bf 100644
--- a/pkg/linux_amd64/cmd/go/internal/modfetch.a
+++ b/pkg/linux_amd64/cmd/go/internal/modfetch.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/modfetch/codehost.a b/pkg/linux_amd64/cmd/go/internal/modfetch/codehost.a
index 62ad0ec..99acc00 100644
--- a/pkg/linux_amd64/cmd/go/internal/modfetch/codehost.a
+++ b/pkg/linux_amd64/cmd/go/internal/modfetch/codehost.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/modget.a b/pkg/linux_amd64/cmd/go/internal/modget.a
index 99069cf..6c9049c 100644
--- a/pkg/linux_amd64/cmd/go/internal/modget.a
+++ b/pkg/linux_amd64/cmd/go/internal/modget.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/modinfo.a b/pkg/linux_amd64/cmd/go/internal/modinfo.a
index 13eeac0..7f93ea4 100644
--- a/pkg/linux_amd64/cmd/go/internal/modinfo.a
+++ b/pkg/linux_amd64/cmd/go/internal/modinfo.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/modload.a b/pkg/linux_amd64/cmd/go/internal/modload.a
index d291f83..7262edb 100644
--- a/pkg/linux_amd64/cmd/go/internal/modload.a
+++ b/pkg/linux_amd64/cmd/go/internal/modload.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/mvs.a b/pkg/linux_amd64/cmd/go/internal/mvs.a
index 947dbfe..873ea46 100644
--- a/pkg/linux_amd64/cmd/go/internal/mvs.a
+++ b/pkg/linux_amd64/cmd/go/internal/mvs.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/par.a b/pkg/linux_amd64/cmd/go/internal/par.a
index e9846e6..c459083 100644
--- a/pkg/linux_amd64/cmd/go/internal/par.a
+++ b/pkg/linux_amd64/cmd/go/internal/par.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/robustio.a b/pkg/linux_amd64/cmd/go/internal/robustio.a
index 3cf1b85..546379c 100644
--- a/pkg/linux_amd64/cmd/go/internal/robustio.a
+++ b/pkg/linux_amd64/cmd/go/internal/robustio.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/run.a b/pkg/linux_amd64/cmd/go/internal/run.a
index b41eaf0..eb79d4f 100644
--- a/pkg/linux_amd64/cmd/go/internal/run.a
+++ b/pkg/linux_amd64/cmd/go/internal/run.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/search.a b/pkg/linux_amd64/cmd/go/internal/search.a
index 0caffe8..5fcd9df 100644
--- a/pkg/linux_amd64/cmd/go/internal/search.a
+++ b/pkg/linux_amd64/cmd/go/internal/search.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/str.a b/pkg/linux_amd64/cmd/go/internal/str.a
index 83f8c23..80c6981 100644
--- a/pkg/linux_amd64/cmd/go/internal/str.a
+++ b/pkg/linux_amd64/cmd/go/internal/str.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/test.a b/pkg/linux_amd64/cmd/go/internal/test.a
index c669de2..9e4712f 100644
--- a/pkg/linux_amd64/cmd/go/internal/test.a
+++ b/pkg/linux_amd64/cmd/go/internal/test.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/test/internal/genflags.a b/pkg/linux_amd64/cmd/go/internal/test/internal/genflags.a
index 1a621b9..f9c9484 100644
--- a/pkg/linux_amd64/cmd/go/internal/test/internal/genflags.a
+++ b/pkg/linux_amd64/cmd/go/internal/test/internal/genflags.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/tool.a b/pkg/linux_amd64/cmd/go/internal/tool.a
index 184f0d4..40826e6 100644
--- a/pkg/linux_amd64/cmd/go/internal/tool.a
+++ b/pkg/linux_amd64/cmd/go/internal/tool.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/trace.a b/pkg/linux_amd64/cmd/go/internal/trace.a
index 61ad65d..ab43887 100644
--- a/pkg/linux_amd64/cmd/go/internal/trace.a
+++ b/pkg/linux_amd64/cmd/go/internal/trace.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/vcs.a b/pkg/linux_amd64/cmd/go/internal/vcs.a
index beec346..e6bb5b8 100644
--- a/pkg/linux_amd64/cmd/go/internal/vcs.a
+++ b/pkg/linux_amd64/cmd/go/internal/vcs.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/version.a b/pkg/linux_amd64/cmd/go/internal/version.a
index ab89d63..d8b2c7d 100644
--- a/pkg/linux_amd64/cmd/go/internal/version.a
+++ b/pkg/linux_amd64/cmd/go/internal/version.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/vet.a b/pkg/linux_amd64/cmd/go/internal/vet.a
index af80041..153ccb6 100644
--- a/pkg/linux_amd64/cmd/go/internal/vet.a
+++ b/pkg/linux_amd64/cmd/go/internal/vet.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/web.a b/pkg/linux_amd64/cmd/go/internal/web.a
index a20bab3..d13f680 100644
--- a/pkg/linux_amd64/cmd/go/internal/web.a
+++ b/pkg/linux_amd64/cmd/go/internal/web.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/work.a b/pkg/linux_amd64/cmd/go/internal/work.a
index f69b91c..0fc4dbe 100644
--- a/pkg/linux_amd64/cmd/go/internal/work.a
+++ b/pkg/linux_amd64/cmd/go/internal/work.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/go/internal/workcmd.a b/pkg/linux_amd64/cmd/go/internal/workcmd.a
index 7aa4397..9377149 100644
--- a/pkg/linux_amd64/cmd/go/internal/workcmd.a
+++ b/pkg/linux_amd64/cmd/go/internal/workcmd.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/archive.a b/pkg/linux_amd64/cmd/internal/archive.a
index 0beff0e..88ac643 100644
--- a/pkg/linux_amd64/cmd/internal/archive.a
+++ b/pkg/linux_amd64/cmd/internal/archive.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/bio.a b/pkg/linux_amd64/cmd/internal/bio.a
index 1ec2182..82ea7c3 100644
--- a/pkg/linux_amd64/cmd/internal/bio.a
+++ b/pkg/linux_amd64/cmd/internal/bio.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/browser.a b/pkg/linux_amd64/cmd/internal/browser.a
index 4aad537..c52b4de 100644
--- a/pkg/linux_amd64/cmd/internal/browser.a
+++ b/pkg/linux_amd64/cmd/internal/browser.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/buildid.a b/pkg/linux_amd64/cmd/internal/buildid.a
index 59bbd6b..1399a3a 100644
--- a/pkg/linux_amd64/cmd/internal/buildid.a
+++ b/pkg/linux_amd64/cmd/internal/buildid.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/codesign.a b/pkg/linux_amd64/cmd/internal/codesign.a
index 29edaf8..a097cd8 100644
--- a/pkg/linux_amd64/cmd/internal/codesign.a
+++ b/pkg/linux_amd64/cmd/internal/codesign.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/diff.a b/pkg/linux_amd64/cmd/internal/diff.a
index d7ab131..a94c6dc 100644
--- a/pkg/linux_amd64/cmd/internal/diff.a
+++ b/pkg/linux_amd64/cmd/internal/diff.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/dwarf.a b/pkg/linux_amd64/cmd/internal/dwarf.a
index d5cd60d..921a1b1 100644
--- a/pkg/linux_amd64/cmd/internal/dwarf.a
+++ b/pkg/linux_amd64/cmd/internal/dwarf.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/edit.a b/pkg/linux_amd64/cmd/internal/edit.a
index 558527b..43d8b0b 100644
--- a/pkg/linux_amd64/cmd/internal/edit.a
+++ b/pkg/linux_amd64/cmd/internal/edit.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/gcprog.a b/pkg/linux_amd64/cmd/internal/gcprog.a
index bf8cd0b..1c7be56 100644
--- a/pkg/linux_amd64/cmd/internal/gcprog.a
+++ b/pkg/linux_amd64/cmd/internal/gcprog.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/goobj.a b/pkg/linux_amd64/cmd/internal/goobj.a
index 3d57501..0df7f24 100644
--- a/pkg/linux_amd64/cmd/internal/goobj.a
+++ b/pkg/linux_amd64/cmd/internal/goobj.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj.a b/pkg/linux_amd64/cmd/internal/obj.a
index 2d2496f..a9f6eb4 100644
--- a/pkg/linux_amd64/cmd/internal/obj.a
+++ b/pkg/linux_amd64/cmd/internal/obj.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj/arm.a b/pkg/linux_amd64/cmd/internal/obj/arm.a
index ad6ebdb..6d6de6e 100644
--- a/pkg/linux_amd64/cmd/internal/obj/arm.a
+++ b/pkg/linux_amd64/cmd/internal/obj/arm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj/arm64.a b/pkg/linux_amd64/cmd/internal/obj/arm64.a
index 5f587c0..364a597 100644
--- a/pkg/linux_amd64/cmd/internal/obj/arm64.a
+++ b/pkg/linux_amd64/cmd/internal/obj/arm64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj/mips.a b/pkg/linux_amd64/cmd/internal/obj/mips.a
index ad1aa2f..183dab0 100644
--- a/pkg/linux_amd64/cmd/internal/obj/mips.a
+++ b/pkg/linux_amd64/cmd/internal/obj/mips.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj/ppc64.a b/pkg/linux_amd64/cmd/internal/obj/ppc64.a
index 7d478b0..6ac035d 100644
--- a/pkg/linux_amd64/cmd/internal/obj/ppc64.a
+++ b/pkg/linux_amd64/cmd/internal/obj/ppc64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj/riscv.a b/pkg/linux_amd64/cmd/internal/obj/riscv.a
index 5408ae4..8235a54 100644
--- a/pkg/linux_amd64/cmd/internal/obj/riscv.a
+++ b/pkg/linux_amd64/cmd/internal/obj/riscv.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj/s390x.a b/pkg/linux_amd64/cmd/internal/obj/s390x.a
index e2713ff..15baba3 100644
--- a/pkg/linux_amd64/cmd/internal/obj/s390x.a
+++ b/pkg/linux_amd64/cmd/internal/obj/s390x.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj/wasm.a b/pkg/linux_amd64/cmd/internal/obj/wasm.a
index 10c4391..c26af25 100644
--- a/pkg/linux_amd64/cmd/internal/obj/wasm.a
+++ b/pkg/linux_amd64/cmd/internal/obj/wasm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/obj/x86.a b/pkg/linux_amd64/cmd/internal/obj/x86.a
index 5d8eeda..04047ee 100644
--- a/pkg/linux_amd64/cmd/internal/obj/x86.a
+++ b/pkg/linux_amd64/cmd/internal/obj/x86.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/objabi.a b/pkg/linux_amd64/cmd/internal/objabi.a
index c5e9f67..89e7fa6 100644
--- a/pkg/linux_amd64/cmd/internal/objabi.a
+++ b/pkg/linux_amd64/cmd/internal/objabi.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/objfile.a b/pkg/linux_amd64/cmd/internal/objfile.a
index 346684f..1c6960d 100644
--- a/pkg/linux_amd64/cmd/internal/objfile.a
+++ b/pkg/linux_amd64/cmd/internal/objfile.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/pkgpath.a b/pkg/linux_amd64/cmd/internal/pkgpath.a
index 9529bf3..e558b2c 100644
--- a/pkg/linux_amd64/cmd/internal/pkgpath.a
+++ b/pkg/linux_amd64/cmd/internal/pkgpath.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/quoted.a b/pkg/linux_amd64/cmd/internal/quoted.a
index a070c79..7c5c8c4 100644
--- a/pkg/linux_amd64/cmd/internal/quoted.a
+++ b/pkg/linux_amd64/cmd/internal/quoted.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/src.a b/pkg/linux_amd64/cmd/internal/src.a
index 8b61cc6..97d639b 100644
--- a/pkg/linux_amd64/cmd/internal/src.a
+++ b/pkg/linux_amd64/cmd/internal/src.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/sys.a b/pkg/linux_amd64/cmd/internal/sys.a
index 82455ba..5f1d063 100644
--- a/pkg/linux_amd64/cmd/internal/sys.a
+++ b/pkg/linux_amd64/cmd/internal/sys.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/test2json.a b/pkg/linux_amd64/cmd/internal/test2json.a
index 55aa09c..0df8f54 100644
--- a/pkg/linux_amd64/cmd/internal/test2json.a
+++ b/pkg/linux_amd64/cmd/internal/test2json.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/internal/traceviewer.a b/pkg/linux_amd64/cmd/internal/traceviewer.a
index f218526..b1c6198 100644
--- a/pkg/linux_amd64/cmd/internal/traceviewer.a
+++ b/pkg/linux_amd64/cmd/internal/traceviewer.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/amd64.a b/pkg/linux_amd64/cmd/link/internal/amd64.a
index 41b6e09..a79c370 100644
--- a/pkg/linux_amd64/cmd/link/internal/amd64.a
+++ b/pkg/linux_amd64/cmd/link/internal/amd64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/arm.a b/pkg/linux_amd64/cmd/link/internal/arm.a
index 488b79d..f179679 100644
--- a/pkg/linux_amd64/cmd/link/internal/arm.a
+++ b/pkg/linux_amd64/cmd/link/internal/arm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/arm64.a b/pkg/linux_amd64/cmd/link/internal/arm64.a
index 8843364..b0913bd 100644
--- a/pkg/linux_amd64/cmd/link/internal/arm64.a
+++ b/pkg/linux_amd64/cmd/link/internal/arm64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/benchmark.a b/pkg/linux_amd64/cmd/link/internal/benchmark.a
index b584f00..5e48fd2 100644
--- a/pkg/linux_amd64/cmd/link/internal/benchmark.a
+++ b/pkg/linux_amd64/cmd/link/internal/benchmark.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/dwtest.a b/pkg/linux_amd64/cmd/link/internal/dwtest.a
index 2ad3243..63fb5c5 100644
--- a/pkg/linux_amd64/cmd/link/internal/dwtest.a
+++ b/pkg/linux_amd64/cmd/link/internal/dwtest.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/ld.a b/pkg/linux_amd64/cmd/link/internal/ld.a
index d65c75e..267a202 100644
--- a/pkg/linux_amd64/cmd/link/internal/ld.a
+++ b/pkg/linux_amd64/cmd/link/internal/ld.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/loadelf.a b/pkg/linux_amd64/cmd/link/internal/loadelf.a
index 108e4cc..c2060b0 100644
--- a/pkg/linux_amd64/cmd/link/internal/loadelf.a
+++ b/pkg/linux_amd64/cmd/link/internal/loadelf.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/loader.a b/pkg/linux_amd64/cmd/link/internal/loader.a
index b7e8b78..112cd73 100644
--- a/pkg/linux_amd64/cmd/link/internal/loader.a
+++ b/pkg/linux_amd64/cmd/link/internal/loader.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/loadmacho.a b/pkg/linux_amd64/cmd/link/internal/loadmacho.a
index b23f6b6..e6a1e4d 100644
--- a/pkg/linux_amd64/cmd/link/internal/loadmacho.a
+++ b/pkg/linux_amd64/cmd/link/internal/loadmacho.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/loadpe.a b/pkg/linux_amd64/cmd/link/internal/loadpe.a
index 127ac98..4f74bc1 100644
--- a/pkg/linux_amd64/cmd/link/internal/loadpe.a
+++ b/pkg/linux_amd64/cmd/link/internal/loadpe.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/loadxcoff.a b/pkg/linux_amd64/cmd/link/internal/loadxcoff.a
index b8369fc..81fe599 100644
--- a/pkg/linux_amd64/cmd/link/internal/loadxcoff.a
+++ b/pkg/linux_amd64/cmd/link/internal/loadxcoff.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/mips.a b/pkg/linux_amd64/cmd/link/internal/mips.a
index 5b26f6a..b98b106 100644
--- a/pkg/linux_amd64/cmd/link/internal/mips.a
+++ b/pkg/linux_amd64/cmd/link/internal/mips.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/mips64.a b/pkg/linux_amd64/cmd/link/internal/mips64.a
index 32c9dc0..e137f59 100644
--- a/pkg/linux_amd64/cmd/link/internal/mips64.a
+++ b/pkg/linux_amd64/cmd/link/internal/mips64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/ppc64.a b/pkg/linux_amd64/cmd/link/internal/ppc64.a
index 9793637..58b3989 100644
--- a/pkg/linux_amd64/cmd/link/internal/ppc64.a
+++ b/pkg/linux_amd64/cmd/link/internal/ppc64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/riscv64.a b/pkg/linux_amd64/cmd/link/internal/riscv64.a
index d23bea2..7d720e7 100644
--- a/pkg/linux_amd64/cmd/link/internal/riscv64.a
+++ b/pkg/linux_amd64/cmd/link/internal/riscv64.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/s390x.a b/pkg/linux_amd64/cmd/link/internal/s390x.a
index a511073..347d03e 100644
--- a/pkg/linux_amd64/cmd/link/internal/s390x.a
+++ b/pkg/linux_amd64/cmd/link/internal/s390x.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/sym.a b/pkg/linux_amd64/cmd/link/internal/sym.a
index dfa33ae..ad5e8eb 100644
--- a/pkg/linux_amd64/cmd/link/internal/sym.a
+++ b/pkg/linux_amd64/cmd/link/internal/sym.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/wasm.a b/pkg/linux_amd64/cmd/link/internal/wasm.a
index f37b636..3f983e6 100644
--- a/pkg/linux_amd64/cmd/link/internal/wasm.a
+++ b/pkg/linux_amd64/cmd/link/internal/wasm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/link/internal/x86.a b/pkg/linux_amd64/cmd/link/internal/x86.a
index d60f04d..d256746 100644
--- a/pkg/linux_amd64/cmd/link/internal/x86.a
+++ b/pkg/linux_amd64/cmd/link/internal/x86.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/driver.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/driver.a
index 2d56110..5f79773 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/driver.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/driver.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/binutils.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/binutils.a
index 612253a..06ab2f0 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/binutils.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/binutils.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/driver.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/driver.a
index 3f6ade7..7778e64 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/driver.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/driver.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/elfexec.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/elfexec.a
index 4993f77..943fe81 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/elfexec.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/elfexec.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/graph.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/graph.a
index ada6b9e..aba0ea1 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/graph.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/graph.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/measurement.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/measurement.a
index b3903b8..9709c70 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/measurement.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/measurement.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/plugin.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/plugin.a
index 26736bc..f047b99 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/plugin.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/plugin.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/report.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/report.a
index 2b018fe..16e492c 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/report.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/report.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/symbolizer.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/symbolizer.a
index 90102d0..e2da4c9 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/symbolizer.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/symbolizer.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/symbolz.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/symbolz.a
index 088dba0..d3b5b6f 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/symbolz.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/symbolz.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/transport.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/transport.a
index 0158a50..c3e4233 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/transport.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/internal/transport.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/profile.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/profile.a
index 4e47324..f318af4 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/profile.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/profile.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/d3.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/d3.a
index 73a6a9a..b9847d7 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/d3.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/d3.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph.a
index a34be1d..b56cb24 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/svgpan.a b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/svgpan.a
index e5fc423..f8b450c 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/svgpan.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/google/pprof/third_party/svgpan.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/github.com/ianlancetaylor/demangle.a b/pkg/linux_amd64/cmd/vendor/github.com/ianlancetaylor/demangle.a
index 87bc2e1..ca33151 100644
--- a/pkg/linux_amd64/cmd/vendor/github.com/ianlancetaylor/demangle.a
+++ b/pkg/linux_amd64/cmd/vendor/github.com/ianlancetaylor/demangle.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/arm/armasm.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/arm/armasm.a
index 4328abf..298a313 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/arm/armasm.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/arm/armasm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/arm64/arm64asm.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/arm64/arm64asm.a
index 67fd7e0..f307893 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/arm64/arm64asm.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/arm64/arm64asm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm.a
index f4f665d..347d08b 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/x86/x86asm.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/x86/x86asm.a
index f271bde..0175eb9 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/x86/x86asm.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/arch/x86/x86asm.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ed25519.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ed25519.a
index 4cf7569..d125d2f 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ed25519.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ed25519.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ed25519/internal/edwards25519.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ed25519/internal/edwards25519.a
index 6dba3fb..4976f64 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ed25519/internal/edwards25519.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ed25519/internal/edwards25519.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/internal/lazyregexp.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/internal/lazyregexp.a
index 1295cd6..4371c29 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/internal/lazyregexp.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/internal/lazyregexp.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/modfile.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/modfile.a
index 9fa13f8..b28a6c7 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/modfile.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/modfile.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/module.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/module.a
index d72cef3..c937348 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/module.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/module.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/semver.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/semver.a
index 4e5a122..854fe4b 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/semver.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/semver.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb.a
index 2ad1d70..9bef4d7 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/dirhash.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/dirhash.a
index a335f2a..6642b5d 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/dirhash.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/dirhash.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/note.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/note.a
index b2169e7..df358d5 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/note.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/note.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/tlog.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/tlog.a
index 141903b..827bf00 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/tlog.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/sumdb/tlog.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/zip.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/zip.a
index b7f6553..b810b9b 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/zip.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/mod/zip.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/sync/semaphore.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/sync/semaphore.a
index fc6c117..4812279 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/sync/semaphore.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/sync/semaphore.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/sys/internal/unsafeheader.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/sys/internal/unsafeheader.a
index a8f7fe8..137de4c 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/sys/internal/unsafeheader.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/sys/internal/unsafeheader.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/sys/unix.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/sys/unix.a
index 9e6f5bf..69c7145 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/sys/unix.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/sys/unix.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/term.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/term.a
index 101141d..1d39ef9 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/term.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/term.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/cover.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/cover.a
index f3c0e2e..969f2e8 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/cover.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/cover.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis.a
index d2422a2..f854e10 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags.a
index 3477b9c..1f2d2c1 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts.a
index 81d7065..98c07db 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl.a
index 34d60f1..89f9d9e 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/assign.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/assign.a
index 05e8341..801519b 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/assign.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/assign.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/atomic.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/atomic.a
index d97d6c0..c7fdfad 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/atomic.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/atomic.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/bools.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/bools.a
index 426ecdb..cccdb3b 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/bools.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/bools.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag.a
index 469e203..2a6b26f 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall.a
index e36444c..cef6e70 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite.a
index 165db05..f526023 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock.a
index 2dc94bc..11125b3 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow.a
index f2d328e..267a3dd 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas.a
index c34c338..bdf30d5 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer.a
index de09ce0..741c0b6 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/httpresponse.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/httpresponse.a
index 03c1407..eddaf74 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/httpresponse.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/httpresponse.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert.a
index 55cd0ce..feda148 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/inspect.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/inspect.a
index 41d9cbc..fd62f3c 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/inspect.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/inspect.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil.a
index 7e29d3d..7205819 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/loopclosure.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/loopclosure.a
index 6afaa1b..f72b2bd 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/loopclosure.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/loopclosure.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/lostcancel.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/lostcancel.a
index b5dc34a..913385d 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/lostcancel.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/lostcancel.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc.a
index 5e4f0d4..99a5f65 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf.a
index bbcbeb7..51c76cb 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift.a
index 53cacab..8be0b07 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/sigchanyzer.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/sigchanyzer.a
index e26c32d..4b20058 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/sigchanyzer.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/sigchanyzer.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods.a
index 72ac0fb..4b78fad 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv.a
index 57c9314..3396f18 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/structtag.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/structtag.a
index 31946f1..981bc70 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/structtag.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/structtag.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine.a
index daefce6..12814f7 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests.a
index da4a0c4..b708be9 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal.a
index 2522c33..226f5dc 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable.a
index aec6b21..4e8700c 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unsafeptr.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unsafeptr.a
index 3b338e0..8cbb09b 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unsafeptr.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unsafeptr.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult.a
index 1b5a22f..091e3ae 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker.a
index f5d9e55..f70872b 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/ast/astutil.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/ast/astutil.a
index f17fa69..7e1675d 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/ast/astutil.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/ast/astutil.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/ast/inspector.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/ast/inspector.a
index 09ce898..0c1fdc7 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/ast/inspector.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/ast/inspector.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/cfg.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/cfg.a
index 30bd45a..3e0e96e 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/cfg.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/cfg.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/types/objectpath.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/types/objectpath.a
index 0f15260..4b6f1d9 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/types/objectpath.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/types/objectpath.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/types/typeutil.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/types/typeutil.a
index de1eaae..580c313 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/types/typeutil.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/go/types/typeutil.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/analysisinternal.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/analysisinternal.a
index e561412..bb0b72a 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/analysisinternal.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/analysisinternal.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy.a
index 61b9e94..0b0e04c 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/typeparams.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/typeparams.a
index 7379f8a..c0dcf59 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/typeparams.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/internal/typeparams.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/txtar.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/txtar.a
index 73cc315..44c45fd 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/txtar.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/tools/txtar.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/xerrors.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/xerrors.a
index 0df16aa..1cbf875 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/xerrors.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/xerrors.a
Binary files differ
diff --git a/pkg/linux_amd64/cmd/vendor/golang.org/x/xerrors/internal.a b/pkg/linux_amd64/cmd/vendor/golang.org/x/xerrors/internal.a
index d2a4ee0..c5144e0 100644
--- a/pkg/linux_amd64/cmd/vendor/golang.org/x/xerrors/internal.a
+++ b/pkg/linux_amd64/cmd/vendor/golang.org/x/xerrors/internal.a
Binary files differ
diff --git a/pkg/linux_amd64/compress/bzip2.a b/pkg/linux_amd64/compress/bzip2.a
index 95135ca..c15c095 100644
--- a/pkg/linux_amd64/compress/bzip2.a
+++ b/pkg/linux_amd64/compress/bzip2.a
Binary files differ
diff --git a/pkg/linux_amd64/compress/flate.a b/pkg/linux_amd64/compress/flate.a
index b532065..ae19abf 100644
--- a/pkg/linux_amd64/compress/flate.a
+++ b/pkg/linux_amd64/compress/flate.a
Binary files differ
diff --git a/pkg/linux_amd64/compress/gzip.a b/pkg/linux_amd64/compress/gzip.a
index 31e6fc4..2b4b31d 100644
--- a/pkg/linux_amd64/compress/gzip.a
+++ b/pkg/linux_amd64/compress/gzip.a
Binary files differ
diff --git a/pkg/linux_amd64/compress/lzw.a b/pkg/linux_amd64/compress/lzw.a
index 25c2a67..28e1fd2 100644
--- a/pkg/linux_amd64/compress/lzw.a
+++ b/pkg/linux_amd64/compress/lzw.a
Binary files differ
diff --git a/pkg/linux_amd64/compress/zlib.a b/pkg/linux_amd64/compress/zlib.a
index 5ca50b0..7e7ce45 100644
--- a/pkg/linux_amd64/compress/zlib.a
+++ b/pkg/linux_amd64/compress/zlib.a
Binary files differ
diff --git a/pkg/linux_amd64/constraints.a b/pkg/linux_amd64/constraints.a
deleted file mode 100644
index 13ccf8b..0000000
--- a/pkg/linux_amd64/constraints.a
+++ /dev/null
Binary files differ
diff --git a/pkg/linux_amd64/container/heap.a b/pkg/linux_amd64/container/heap.a
index dc616e6..d0e9ea9 100644
--- a/pkg/linux_amd64/container/heap.a
+++ b/pkg/linux_amd64/container/heap.a
Binary files differ
diff --git a/pkg/linux_amd64/container/list.a b/pkg/linux_amd64/container/list.a
index 779367c..be8e38e 100644
--- a/pkg/linux_amd64/container/list.a
+++ b/pkg/linux_amd64/container/list.a
Binary files differ
diff --git a/pkg/linux_amd64/container/ring.a b/pkg/linux_amd64/container/ring.a
index 9e1eac2..a5ab90f 100644
--- a/pkg/linux_amd64/container/ring.a
+++ b/pkg/linux_amd64/container/ring.a
Binary files differ
diff --git a/pkg/linux_amd64/context.a b/pkg/linux_amd64/context.a
index 714600f..5e95602 100644
--- a/pkg/linux_amd64/context.a
+++ b/pkg/linux_amd64/context.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto.a b/pkg/linux_amd64/crypto.a
index 5065fd3..43234ec 100644
--- a/pkg/linux_amd64/crypto.a
+++ b/pkg/linux_amd64/crypto.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/aes.a b/pkg/linux_amd64/crypto/aes.a
index 60563dd..41a7802 100644
--- a/pkg/linux_amd64/crypto/aes.a
+++ b/pkg/linux_amd64/crypto/aes.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/cipher.a b/pkg/linux_amd64/crypto/cipher.a
index 572c33d..b0aae44 100644
--- a/pkg/linux_amd64/crypto/cipher.a
+++ b/pkg/linux_amd64/crypto/cipher.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/des.a b/pkg/linux_amd64/crypto/des.a
index b9dc3a2..0feb04a 100644
--- a/pkg/linux_amd64/crypto/des.a
+++ b/pkg/linux_amd64/crypto/des.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/dsa.a b/pkg/linux_amd64/crypto/dsa.a
index a7ec3e5..b27cb6c 100644
--- a/pkg/linux_amd64/crypto/dsa.a
+++ b/pkg/linux_amd64/crypto/dsa.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/ecdsa.a b/pkg/linux_amd64/crypto/ecdsa.a
index f248428..db6a76f 100644
--- a/pkg/linux_amd64/crypto/ecdsa.a
+++ b/pkg/linux_amd64/crypto/ecdsa.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/ed25519.a b/pkg/linux_amd64/crypto/ed25519.a
index 1d03d24..dfa0b18 100644
--- a/pkg/linux_amd64/crypto/ed25519.a
+++ b/pkg/linux_amd64/crypto/ed25519.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/ed25519/internal/edwards25519.a b/pkg/linux_amd64/crypto/ed25519/internal/edwards25519.a
index aa6074a..20ba8fe 100644
--- a/pkg/linux_amd64/crypto/ed25519/internal/edwards25519.a
+++ b/pkg/linux_amd64/crypto/ed25519/internal/edwards25519.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/ed25519/internal/edwards25519/field.a b/pkg/linux_amd64/crypto/ed25519/internal/edwards25519/field.a
index 3b7cd2f..7095bd1 100644
--- a/pkg/linux_amd64/crypto/ed25519/internal/edwards25519/field.a
+++ b/pkg/linux_amd64/crypto/ed25519/internal/edwards25519/field.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/elliptic.a b/pkg/linux_amd64/crypto/elliptic.a
index 652903c..96d187c 100644
--- a/pkg/linux_amd64/crypto/elliptic.a
+++ b/pkg/linux_amd64/crypto/elliptic.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/elliptic/internal/fiat.a b/pkg/linux_amd64/crypto/elliptic/internal/fiat.a
index a03b0bf..bcc34ac 100644
--- a/pkg/linux_amd64/crypto/elliptic/internal/fiat.a
+++ b/pkg/linux_amd64/crypto/elliptic/internal/fiat.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/elliptic/internal/nistec.a b/pkg/linux_amd64/crypto/elliptic/internal/nistec.a
index 884dc51..12bf58e 100644
--- a/pkg/linux_amd64/crypto/elliptic/internal/nistec.a
+++ b/pkg/linux_amd64/crypto/elliptic/internal/nistec.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/hmac.a b/pkg/linux_amd64/crypto/hmac.a
index 7c89f1d..9fff00a 100644
--- a/pkg/linux_amd64/crypto/hmac.a
+++ b/pkg/linux_amd64/crypto/hmac.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/internal/randutil.a b/pkg/linux_amd64/crypto/internal/randutil.a
index dd9e0a4..e3435c9 100644
--- a/pkg/linux_amd64/crypto/internal/randutil.a
+++ b/pkg/linux_amd64/crypto/internal/randutil.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/internal/subtle.a b/pkg/linux_amd64/crypto/internal/subtle.a
index b61fdd6..b1edc11 100644
--- a/pkg/linux_amd64/crypto/internal/subtle.a
+++ b/pkg/linux_amd64/crypto/internal/subtle.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/md5.a b/pkg/linux_amd64/crypto/md5.a
index f18d8d6..a0b3655 100644
--- a/pkg/linux_amd64/crypto/md5.a
+++ b/pkg/linux_amd64/crypto/md5.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/rand.a b/pkg/linux_amd64/crypto/rand.a
index ebbb305..248b232 100644
--- a/pkg/linux_amd64/crypto/rand.a
+++ b/pkg/linux_amd64/crypto/rand.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/rc4.a b/pkg/linux_amd64/crypto/rc4.a
index e16ad58..8989727 100644
--- a/pkg/linux_amd64/crypto/rc4.a
+++ b/pkg/linux_amd64/crypto/rc4.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/rsa.a b/pkg/linux_amd64/crypto/rsa.a
index 216da0e..41ef627 100644
--- a/pkg/linux_amd64/crypto/rsa.a
+++ b/pkg/linux_amd64/crypto/rsa.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/sha1.a b/pkg/linux_amd64/crypto/sha1.a
index d82f21f..e0fd9f4 100644
--- a/pkg/linux_amd64/crypto/sha1.a
+++ b/pkg/linux_amd64/crypto/sha1.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/sha256.a b/pkg/linux_amd64/crypto/sha256.a
index cf1b868..e341aaa 100644
--- a/pkg/linux_amd64/crypto/sha256.a
+++ b/pkg/linux_amd64/crypto/sha256.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/sha512.a b/pkg/linux_amd64/crypto/sha512.a
index 5640116..de277e0 100644
--- a/pkg/linux_amd64/crypto/sha512.a
+++ b/pkg/linux_amd64/crypto/sha512.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/subtle.a b/pkg/linux_amd64/crypto/subtle.a
index 157f0f7..8aab382 100644
--- a/pkg/linux_amd64/crypto/subtle.a
+++ b/pkg/linux_amd64/crypto/subtle.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/tls.a b/pkg/linux_amd64/crypto/tls.a
index 8d0800a..576e1b4 100644
--- a/pkg/linux_amd64/crypto/tls.a
+++ b/pkg/linux_amd64/crypto/tls.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/x509.a b/pkg/linux_amd64/crypto/x509.a
index 0f550b3..082ff67 100644
--- a/pkg/linux_amd64/crypto/x509.a
+++ b/pkg/linux_amd64/crypto/x509.a
Binary files differ
diff --git a/pkg/linux_amd64/crypto/x509/pkix.a b/pkg/linux_amd64/crypto/x509/pkix.a
index d4eb583..c6b4a69 100644
--- a/pkg/linux_amd64/crypto/x509/pkix.a
+++ b/pkg/linux_amd64/crypto/x509/pkix.a
Binary files differ
diff --git a/pkg/linux_amd64/database/sql.a b/pkg/linux_amd64/database/sql.a
index e7ac1d1..5870adb 100644
--- a/pkg/linux_amd64/database/sql.a
+++ b/pkg/linux_amd64/database/sql.a
Binary files differ
diff --git a/pkg/linux_amd64/database/sql/driver.a b/pkg/linux_amd64/database/sql/driver.a
index 890af2d..5de5c1b 100644
--- a/pkg/linux_amd64/database/sql/driver.a
+++ b/pkg/linux_amd64/database/sql/driver.a
Binary files differ
diff --git a/pkg/linux_amd64/debug/buildinfo.a b/pkg/linux_amd64/debug/buildinfo.a
index 1cfed69..acfa6d7 100644
--- a/pkg/linux_amd64/debug/buildinfo.a
+++ b/pkg/linux_amd64/debug/buildinfo.a
Binary files differ
diff --git a/pkg/linux_amd64/debug/dwarf.a b/pkg/linux_amd64/debug/dwarf.a
index 3ca5fce..d503057 100644
--- a/pkg/linux_amd64/debug/dwarf.a
+++ b/pkg/linux_amd64/debug/dwarf.a
Binary files differ
diff --git a/pkg/linux_amd64/debug/elf.a b/pkg/linux_amd64/debug/elf.a
index 5f6fb38..4080431 100644
--- a/pkg/linux_amd64/debug/elf.a
+++ b/pkg/linux_amd64/debug/elf.a
Binary files differ
diff --git a/pkg/linux_amd64/debug/gosym.a b/pkg/linux_amd64/debug/gosym.a
index 8a0da0b..39b9542 100644
--- a/pkg/linux_amd64/debug/gosym.a
+++ b/pkg/linux_amd64/debug/gosym.a
Binary files differ
diff --git a/pkg/linux_amd64/debug/macho.a b/pkg/linux_amd64/debug/macho.a
index 879223e..ec0db95 100644
--- a/pkg/linux_amd64/debug/macho.a
+++ b/pkg/linux_amd64/debug/macho.a
Binary files differ
diff --git a/pkg/linux_amd64/debug/pe.a b/pkg/linux_amd64/debug/pe.a
index 14f755c..a0688ff 100644
--- a/pkg/linux_amd64/debug/pe.a
+++ b/pkg/linux_amd64/debug/pe.a
Binary files differ
diff --git a/pkg/linux_amd64/debug/plan9obj.a b/pkg/linux_amd64/debug/plan9obj.a
index 7689527..0b5c566 100644
--- a/pkg/linux_amd64/debug/plan9obj.a
+++ b/pkg/linux_amd64/debug/plan9obj.a
Binary files differ
diff --git a/pkg/linux_amd64/embed.a b/pkg/linux_amd64/embed.a
index e229e75..a6ac888 100644
--- a/pkg/linux_amd64/embed.a
+++ b/pkg/linux_amd64/embed.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding.a b/pkg/linux_amd64/encoding.a
index 9509d39..91852fc 100644
--- a/pkg/linux_amd64/encoding.a
+++ b/pkg/linux_amd64/encoding.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/ascii85.a b/pkg/linux_amd64/encoding/ascii85.a
index bfc7c69..1a3846b 100644
--- a/pkg/linux_amd64/encoding/ascii85.a
+++ b/pkg/linux_amd64/encoding/ascii85.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/asn1.a b/pkg/linux_amd64/encoding/asn1.a
index 3741c8d..353fa4e 100644
--- a/pkg/linux_amd64/encoding/asn1.a
+++ b/pkg/linux_amd64/encoding/asn1.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/base32.a b/pkg/linux_amd64/encoding/base32.a
index 627d4df..99f94f1 100644
--- a/pkg/linux_amd64/encoding/base32.a
+++ b/pkg/linux_amd64/encoding/base32.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/base64.a b/pkg/linux_amd64/encoding/base64.a
index c68bb1b..dcf5173 100644
--- a/pkg/linux_amd64/encoding/base64.a
+++ b/pkg/linux_amd64/encoding/base64.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/binary.a b/pkg/linux_amd64/encoding/binary.a
index ea0eacd..d93c7f6 100644
--- a/pkg/linux_amd64/encoding/binary.a
+++ b/pkg/linux_amd64/encoding/binary.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/csv.a b/pkg/linux_amd64/encoding/csv.a
index 7df011f..9eebc16 100644
--- a/pkg/linux_amd64/encoding/csv.a
+++ b/pkg/linux_amd64/encoding/csv.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/gob.a b/pkg/linux_amd64/encoding/gob.a
index 20cc7b4..25e86ab 100644
--- a/pkg/linux_amd64/encoding/gob.a
+++ b/pkg/linux_amd64/encoding/gob.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/hex.a b/pkg/linux_amd64/encoding/hex.a
index 18ba339..790ed9f 100644
--- a/pkg/linux_amd64/encoding/hex.a
+++ b/pkg/linux_amd64/encoding/hex.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/json.a b/pkg/linux_amd64/encoding/json.a
index 7d103dd..879074a 100644
--- a/pkg/linux_amd64/encoding/json.a
+++ b/pkg/linux_amd64/encoding/json.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/pem.a b/pkg/linux_amd64/encoding/pem.a
index 1c55362..b4ee3b1 100644
--- a/pkg/linux_amd64/encoding/pem.a
+++ b/pkg/linux_amd64/encoding/pem.a
Binary files differ
diff --git a/pkg/linux_amd64/encoding/xml.a b/pkg/linux_amd64/encoding/xml.a
index c4548a5..1169427 100644
--- a/pkg/linux_amd64/encoding/xml.a
+++ b/pkg/linux_amd64/encoding/xml.a
Binary files differ
diff --git a/pkg/linux_amd64/errors.a b/pkg/linux_amd64/errors.a
index 79f0148..b63cb5c 100644
--- a/pkg/linux_amd64/errors.a
+++ b/pkg/linux_amd64/errors.a
Binary files differ
diff --git a/pkg/linux_amd64/expvar.a b/pkg/linux_amd64/expvar.a
index c45b4bc..c6a5b13 100644
--- a/pkg/linux_amd64/expvar.a
+++ b/pkg/linux_amd64/expvar.a
Binary files differ
diff --git a/pkg/linux_amd64/flag.a b/pkg/linux_amd64/flag.a
index 09b2a63..36f12d3 100644
--- a/pkg/linux_amd64/flag.a
+++ b/pkg/linux_amd64/flag.a
Binary files differ
diff --git a/pkg/linux_amd64/fmt.a b/pkg/linux_amd64/fmt.a
index 9ce75ba..00b5e44 100644
--- a/pkg/linux_amd64/fmt.a
+++ b/pkg/linux_amd64/fmt.a
Binary files differ
diff --git a/pkg/linux_amd64/go/ast.a b/pkg/linux_amd64/go/ast.a
index f399df1..645fad8 100644
--- a/pkg/linux_amd64/go/ast.a
+++ b/pkg/linux_amd64/go/ast.a
Binary files differ
diff --git a/pkg/linux_amd64/go/build.a b/pkg/linux_amd64/go/build.a
index a8cd5ad..3214585 100644
--- a/pkg/linux_amd64/go/build.a
+++ b/pkg/linux_amd64/go/build.a
Binary files differ
diff --git a/pkg/linux_amd64/go/build/constraint.a b/pkg/linux_amd64/go/build/constraint.a
index e6c96c5..0baf2a2 100644
--- a/pkg/linux_amd64/go/build/constraint.a
+++ b/pkg/linux_amd64/go/build/constraint.a
Binary files differ
diff --git a/pkg/linux_amd64/go/constant.a b/pkg/linux_amd64/go/constant.a
index a2dc1bc..1d7d257 100644
--- a/pkg/linux_amd64/go/constant.a
+++ b/pkg/linux_amd64/go/constant.a
Binary files differ
diff --git a/pkg/linux_amd64/go/doc.a b/pkg/linux_amd64/go/doc.a
index 0abc897..6523be6 100644
--- a/pkg/linux_amd64/go/doc.a
+++ b/pkg/linux_amd64/go/doc.a
Binary files differ
diff --git a/pkg/linux_amd64/go/format.a b/pkg/linux_amd64/go/format.a
index 1b0f67d..40a8f21 100644
--- a/pkg/linux_amd64/go/format.a
+++ b/pkg/linux_amd64/go/format.a
Binary files differ
diff --git a/pkg/linux_amd64/go/importer.a b/pkg/linux_amd64/go/importer.a
index b7d8a0d..7aef619 100644
--- a/pkg/linux_amd64/go/importer.a
+++ b/pkg/linux_amd64/go/importer.a
Binary files differ
diff --git a/pkg/linux_amd64/go/internal/gccgoimporter.a b/pkg/linux_amd64/go/internal/gccgoimporter.a
index 56be7ae..bc9ca70 100644
--- a/pkg/linux_amd64/go/internal/gccgoimporter.a
+++ b/pkg/linux_amd64/go/internal/gccgoimporter.a
Binary files differ
diff --git a/pkg/linux_amd64/go/internal/gcimporter.a b/pkg/linux_amd64/go/internal/gcimporter.a
index 6813dc2..608015e 100644
--- a/pkg/linux_amd64/go/internal/gcimporter.a
+++ b/pkg/linux_amd64/go/internal/gcimporter.a
Binary files differ
diff --git a/pkg/linux_amd64/go/internal/srcimporter.a b/pkg/linux_amd64/go/internal/srcimporter.a
index a1e427d..4e9a1a5 100644
--- a/pkg/linux_amd64/go/internal/srcimporter.a
+++ b/pkg/linux_amd64/go/internal/srcimporter.a
Binary files differ
diff --git a/pkg/linux_amd64/go/internal/typeparams.a b/pkg/linux_amd64/go/internal/typeparams.a
index badf65e..f2321f1 100644
--- a/pkg/linux_amd64/go/internal/typeparams.a
+++ b/pkg/linux_amd64/go/internal/typeparams.a
Binary files differ
diff --git a/pkg/linux_amd64/go/parser.a b/pkg/linux_amd64/go/parser.a
index ac6f1c8..ade7d8a 100644
--- a/pkg/linux_amd64/go/parser.a
+++ b/pkg/linux_amd64/go/parser.a
Binary files differ
diff --git a/pkg/linux_amd64/go/printer.a b/pkg/linux_amd64/go/printer.a
index 328f995..d0a3067 100644
--- a/pkg/linux_amd64/go/printer.a
+++ b/pkg/linux_amd64/go/printer.a
Binary files differ
diff --git a/pkg/linux_amd64/go/scanner.a b/pkg/linux_amd64/go/scanner.a
index 3727637..7fd6877 100644
--- a/pkg/linux_amd64/go/scanner.a
+++ b/pkg/linux_amd64/go/scanner.a
Binary files differ
diff --git a/pkg/linux_amd64/go/token.a b/pkg/linux_amd64/go/token.a
index 8c33001..6a9579e 100644
--- a/pkg/linux_amd64/go/token.a
+++ b/pkg/linux_amd64/go/token.a
Binary files differ
diff --git a/pkg/linux_amd64/go/types.a b/pkg/linux_amd64/go/types.a
index b818939..f62faf4 100644
--- a/pkg/linux_amd64/go/types.a
+++ b/pkg/linux_amd64/go/types.a
Binary files differ
diff --git a/pkg/linux_amd64/hash.a b/pkg/linux_amd64/hash.a
index 81f103b..4801575 100644
--- a/pkg/linux_amd64/hash.a
+++ b/pkg/linux_amd64/hash.a
Binary files differ
diff --git a/pkg/linux_amd64/hash/adler32.a b/pkg/linux_amd64/hash/adler32.a
index 7f65a55..c584b7a 100644
--- a/pkg/linux_amd64/hash/adler32.a
+++ b/pkg/linux_amd64/hash/adler32.a
Binary files differ
diff --git a/pkg/linux_amd64/hash/crc32.a b/pkg/linux_amd64/hash/crc32.a
index 15b5c52..1641898 100644
--- a/pkg/linux_amd64/hash/crc32.a
+++ b/pkg/linux_amd64/hash/crc32.a
Binary files differ
diff --git a/pkg/linux_amd64/hash/crc64.a b/pkg/linux_amd64/hash/crc64.a
index a849bc8..eb8ebf7 100644
--- a/pkg/linux_amd64/hash/crc64.a
+++ b/pkg/linux_amd64/hash/crc64.a
Binary files differ
diff --git a/pkg/linux_amd64/hash/fnv.a b/pkg/linux_amd64/hash/fnv.a
index bc60f41..7b9762e 100644
--- a/pkg/linux_amd64/hash/fnv.a
+++ b/pkg/linux_amd64/hash/fnv.a
Binary files differ
diff --git a/pkg/linux_amd64/hash/maphash.a b/pkg/linux_amd64/hash/maphash.a
index 88ed89b..946895c 100644
--- a/pkg/linux_amd64/hash/maphash.a
+++ b/pkg/linux_amd64/hash/maphash.a
Binary files differ
diff --git a/pkg/linux_amd64/html.a b/pkg/linux_amd64/html.a
index 3c1ca70..141412c 100644
--- a/pkg/linux_amd64/html.a
+++ b/pkg/linux_amd64/html.a
Binary files differ
diff --git a/pkg/linux_amd64/html/template.a b/pkg/linux_amd64/html/template.a
index fc3778b..4005f2d 100644
--- a/pkg/linux_amd64/html/template.a
+++ b/pkg/linux_amd64/html/template.a
Binary files differ
diff --git a/pkg/linux_amd64/image.a b/pkg/linux_amd64/image.a
index f1ed3e2..abe44a9 100644
--- a/pkg/linux_amd64/image.a
+++ b/pkg/linux_amd64/image.a
Binary files differ
diff --git a/pkg/linux_amd64/image/color.a b/pkg/linux_amd64/image/color.a
index 3aca386..e21bbe1 100644
--- a/pkg/linux_amd64/image/color.a
+++ b/pkg/linux_amd64/image/color.a
Binary files differ
diff --git a/pkg/linux_amd64/image/color/palette.a b/pkg/linux_amd64/image/color/palette.a
index 750a9d5..88b88ff 100644
--- a/pkg/linux_amd64/image/color/palette.a
+++ b/pkg/linux_amd64/image/color/palette.a
Binary files differ
diff --git a/pkg/linux_amd64/image/draw.a b/pkg/linux_amd64/image/draw.a
index 01dc1a4..51a7832 100644
--- a/pkg/linux_amd64/image/draw.a
+++ b/pkg/linux_amd64/image/draw.a
Binary files differ
diff --git a/pkg/linux_amd64/image/gif.a b/pkg/linux_amd64/image/gif.a
index b04913c..0e64601 100644
--- a/pkg/linux_amd64/image/gif.a
+++ b/pkg/linux_amd64/image/gif.a
Binary files differ
diff --git a/pkg/linux_amd64/image/internal/imageutil.a b/pkg/linux_amd64/image/internal/imageutil.a
index e9f916c..e03b3f9 100644
--- a/pkg/linux_amd64/image/internal/imageutil.a
+++ b/pkg/linux_amd64/image/internal/imageutil.a
Binary files differ
diff --git a/pkg/linux_amd64/image/jpeg.a b/pkg/linux_amd64/image/jpeg.a
index 977a6e3..c0e2d77 100644
--- a/pkg/linux_amd64/image/jpeg.a
+++ b/pkg/linux_amd64/image/jpeg.a
Binary files differ
diff --git a/pkg/linux_amd64/image/png.a b/pkg/linux_amd64/image/png.a
index 5290e31..ee99d0e 100644
--- a/pkg/linux_amd64/image/png.a
+++ b/pkg/linux_amd64/image/png.a
Binary files differ
diff --git a/pkg/linux_amd64/index/suffixarray.a b/pkg/linux_amd64/index/suffixarray.a
index a3c2341..4c9e559 100644
--- a/pkg/linux_amd64/index/suffixarray.a
+++ b/pkg/linux_amd64/index/suffixarray.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/abi.a b/pkg/linux_amd64/internal/abi.a
index ae1ce7b..d59bb3f 100644
--- a/pkg/linux_amd64/internal/abi.a
+++ b/pkg/linux_amd64/internal/abi.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/buildcfg.a b/pkg/linux_amd64/internal/buildcfg.a
index 17c37af..88241e1 100644
--- a/pkg/linux_amd64/internal/buildcfg.a
+++ b/pkg/linux_amd64/internal/buildcfg.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/bytealg.a b/pkg/linux_amd64/internal/bytealg.a
index 895f836..2a68417 100644
--- a/pkg/linux_amd64/internal/bytealg.a
+++ b/pkg/linux_amd64/internal/bytealg.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/cfg.a b/pkg/linux_amd64/internal/cfg.a
index ed1f824..1416119 100644
--- a/pkg/linux_amd64/internal/cfg.a
+++ b/pkg/linux_amd64/internal/cfg.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/cpu.a b/pkg/linux_amd64/internal/cpu.a
index ab2809f..9b57040 100644
--- a/pkg/linux_amd64/internal/cpu.a
+++ b/pkg/linux_amd64/internal/cpu.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/execabs.a b/pkg/linux_amd64/internal/execabs.a
index 36a672a..e098b4e 100644
--- a/pkg/linux_amd64/internal/execabs.a
+++ b/pkg/linux_amd64/internal/execabs.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/fmtsort.a b/pkg/linux_amd64/internal/fmtsort.a
index 4736830..b0b6fb3 100644
--- a/pkg/linux_amd64/internal/fmtsort.a
+++ b/pkg/linux_amd64/internal/fmtsort.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/fuzz.a b/pkg/linux_amd64/internal/fuzz.a
index a40378d..3aee493 100644
--- a/pkg/linux_amd64/internal/fuzz.a
+++ b/pkg/linux_amd64/internal/fuzz.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/goarch.a b/pkg/linux_amd64/internal/goarch.a
index f3d7825..0cd3f68 100644
--- a/pkg/linux_amd64/internal/goarch.a
+++ b/pkg/linux_amd64/internal/goarch.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/godebug.a b/pkg/linux_amd64/internal/godebug.a
index 4807115..e5e4b5b 100644
--- a/pkg/linux_amd64/internal/godebug.a
+++ b/pkg/linux_amd64/internal/godebug.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/goexperiment.a b/pkg/linux_amd64/internal/goexperiment.a
index 2204834..c414c1c 100644
--- a/pkg/linux_amd64/internal/goexperiment.a
+++ b/pkg/linux_amd64/internal/goexperiment.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/goos.a b/pkg/linux_amd64/internal/goos.a
index 7ce5282..be1b55c 100644
--- a/pkg/linux_amd64/internal/goos.a
+++ b/pkg/linux_amd64/internal/goos.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/goroot.a b/pkg/linux_amd64/internal/goroot.a
index 99dfeb5..3859571 100644
--- a/pkg/linux_amd64/internal/goroot.a
+++ b/pkg/linux_amd64/internal/goroot.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/goversion.a b/pkg/linux_amd64/internal/goversion.a
index b0b3d87..41bd10b 100644
--- a/pkg/linux_amd64/internal/goversion.a
+++ b/pkg/linux_amd64/internal/goversion.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/intern.a b/pkg/linux_amd64/internal/intern.a
index 7fab969..2bdc358 100644
--- a/pkg/linux_amd64/internal/intern.a
+++ b/pkg/linux_amd64/internal/intern.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/itoa.a b/pkg/linux_amd64/internal/itoa.a
index 57c130b..1bb9a1a 100644
--- a/pkg/linux_amd64/internal/itoa.a
+++ b/pkg/linux_amd64/internal/itoa.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/lazyregexp.a b/pkg/linux_amd64/internal/lazyregexp.a
index 8454afa..7bae78e 100644
--- a/pkg/linux_amd64/internal/lazyregexp.a
+++ b/pkg/linux_amd64/internal/lazyregexp.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/lazytemplate.a b/pkg/linux_amd64/internal/lazytemplate.a
index 65d0bec..f870f3d 100644
--- a/pkg/linux_amd64/internal/lazytemplate.a
+++ b/pkg/linux_amd64/internal/lazytemplate.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/nettrace.a b/pkg/linux_amd64/internal/nettrace.a
index f903b57..4bcf0e9 100644
--- a/pkg/linux_amd64/internal/nettrace.a
+++ b/pkg/linux_amd64/internal/nettrace.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/obscuretestdata.a b/pkg/linux_amd64/internal/obscuretestdata.a
index 3c88324..325024f 100644
--- a/pkg/linux_amd64/internal/obscuretestdata.a
+++ b/pkg/linux_amd64/internal/obscuretestdata.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/oserror.a b/pkg/linux_amd64/internal/oserror.a
index ee1faf4..69985d3 100644
--- a/pkg/linux_amd64/internal/oserror.a
+++ b/pkg/linux_amd64/internal/oserror.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/poll.a b/pkg/linux_amd64/internal/poll.a
index d599f08..7b0f69d 100644
--- a/pkg/linux_amd64/internal/poll.a
+++ b/pkg/linux_amd64/internal/poll.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/profile.a b/pkg/linux_amd64/internal/profile.a
index 4ddd82b..45760e4 100644
--- a/pkg/linux_amd64/internal/profile.a
+++ b/pkg/linux_amd64/internal/profile.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/race.a b/pkg/linux_amd64/internal/race.a
index b54505b..8b0c11a 100644
--- a/pkg/linux_amd64/internal/race.a
+++ b/pkg/linux_amd64/internal/race.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/reflectlite.a b/pkg/linux_amd64/internal/reflectlite.a
index 0dd019c..9a7500c 100644
--- a/pkg/linux_amd64/internal/reflectlite.a
+++ b/pkg/linux_amd64/internal/reflectlite.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/singleflight.a b/pkg/linux_amd64/internal/singleflight.a
index ea12612..6529782 100644
--- a/pkg/linux_amd64/internal/singleflight.a
+++ b/pkg/linux_amd64/internal/singleflight.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/syscall/execenv.a b/pkg/linux_amd64/internal/syscall/execenv.a
index 7c1c3a5..7416594 100644
--- a/pkg/linux_amd64/internal/syscall/execenv.a
+++ b/pkg/linux_amd64/internal/syscall/execenv.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/syscall/unix.a b/pkg/linux_amd64/internal/syscall/unix.a
index 1289237..a4026c8 100644
--- a/pkg/linux_amd64/internal/syscall/unix.a
+++ b/pkg/linux_amd64/internal/syscall/unix.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/sysinfo.a b/pkg/linux_amd64/internal/sysinfo.a
index 8faade5..4cd6e83 100644
--- a/pkg/linux_amd64/internal/sysinfo.a
+++ b/pkg/linux_amd64/internal/sysinfo.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/testenv.a b/pkg/linux_amd64/internal/testenv.a
index 967e97f..bd5a00d 100644
--- a/pkg/linux_amd64/internal/testenv.a
+++ b/pkg/linux_amd64/internal/testenv.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/testlog.a b/pkg/linux_amd64/internal/testlog.a
index 7647fe8..8a7a13a 100644
--- a/pkg/linux_amd64/internal/testlog.a
+++ b/pkg/linux_amd64/internal/testlog.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/trace.a b/pkg/linux_amd64/internal/trace.a
index 9b5ec29..f55fe7b 100644
--- a/pkg/linux_amd64/internal/trace.a
+++ b/pkg/linux_amd64/internal/trace.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/unsafeheader.a b/pkg/linux_amd64/internal/unsafeheader.a
index 6ce774a..6b1a91e 100644
--- a/pkg/linux_amd64/internal/unsafeheader.a
+++ b/pkg/linux_amd64/internal/unsafeheader.a
Binary files differ
diff --git a/pkg/linux_amd64/internal/xcoff.a b/pkg/linux_amd64/internal/xcoff.a
index 2a6089b..8132cc2 100644
--- a/pkg/linux_amd64/internal/xcoff.a
+++ b/pkg/linux_amd64/internal/xcoff.a
Binary files differ
diff --git a/pkg/linux_amd64/io.a b/pkg/linux_amd64/io.a
index fa2464b..d7777c3 100644
--- a/pkg/linux_amd64/io.a
+++ b/pkg/linux_amd64/io.a
Binary files differ
diff --git a/pkg/linux_amd64/io/fs.a b/pkg/linux_amd64/io/fs.a
index b607e24..42ccc60 100644
--- a/pkg/linux_amd64/io/fs.a
+++ b/pkg/linux_amd64/io/fs.a
Binary files differ
diff --git a/pkg/linux_amd64/io/ioutil.a b/pkg/linux_amd64/io/ioutil.a
index d465be5..95b3fff 100644
--- a/pkg/linux_amd64/io/ioutil.a
+++ b/pkg/linux_amd64/io/ioutil.a
Binary files differ
diff --git a/pkg/linux_amd64/log.a b/pkg/linux_amd64/log.a
index 5d42774..bfdedae 100644
--- a/pkg/linux_amd64/log.a
+++ b/pkg/linux_amd64/log.a
Binary files differ
diff --git a/pkg/linux_amd64/log/syslog.a b/pkg/linux_amd64/log/syslog.a
index 0722177..0aed351 100644
--- a/pkg/linux_amd64/log/syslog.a
+++ b/pkg/linux_amd64/log/syslog.a
Binary files differ
diff --git a/pkg/linux_amd64/math.a b/pkg/linux_amd64/math.a
index 1a4d5dd..0411565 100644
--- a/pkg/linux_amd64/math.a
+++ b/pkg/linux_amd64/math.a
Binary files differ
diff --git a/pkg/linux_amd64/math/big.a b/pkg/linux_amd64/math/big.a
index f660871..04dd8cc 100644
--- a/pkg/linux_amd64/math/big.a
+++ b/pkg/linux_amd64/math/big.a
Binary files differ
diff --git a/pkg/linux_amd64/math/bits.a b/pkg/linux_amd64/math/bits.a
index 5866acd..ff28038 100644
--- a/pkg/linux_amd64/math/bits.a
+++ b/pkg/linux_amd64/math/bits.a
Binary files differ
diff --git a/pkg/linux_amd64/math/cmplx.a b/pkg/linux_amd64/math/cmplx.a
index 61fa2ad..3acae9e 100644
--- a/pkg/linux_amd64/math/cmplx.a
+++ b/pkg/linux_amd64/math/cmplx.a
Binary files differ
diff --git a/pkg/linux_amd64/math/rand.a b/pkg/linux_amd64/math/rand.a
index 66b1864..e020dfe 100644
--- a/pkg/linux_amd64/math/rand.a
+++ b/pkg/linux_amd64/math/rand.a
Binary files differ
diff --git a/pkg/linux_amd64/mime.a b/pkg/linux_amd64/mime.a
index adf7457..702cf80 100644
--- a/pkg/linux_amd64/mime.a
+++ b/pkg/linux_amd64/mime.a
Binary files differ
diff --git a/pkg/linux_amd64/mime/multipart.a b/pkg/linux_amd64/mime/multipart.a
index d03d2e3..c38b101 100644
--- a/pkg/linux_amd64/mime/multipart.a
+++ b/pkg/linux_amd64/mime/multipart.a
Binary files differ
diff --git a/pkg/linux_amd64/mime/quotedprintable.a b/pkg/linux_amd64/mime/quotedprintable.a
index 1a09ff8..99ab769 100644
--- a/pkg/linux_amd64/mime/quotedprintable.a
+++ b/pkg/linux_amd64/mime/quotedprintable.a
Binary files differ
diff --git a/pkg/linux_amd64/net.a b/pkg/linux_amd64/net.a
index a958ac1..54ad745 100644
--- a/pkg/linux_amd64/net.a
+++ b/pkg/linux_amd64/net.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http.a b/pkg/linux_amd64/net/http.a
index 8e44401..1ea6078 100644
--- a/pkg/linux_amd64/net/http.a
+++ b/pkg/linux_amd64/net/http.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/cgi.a b/pkg/linux_amd64/net/http/cgi.a
index 0e763c4..db1273e 100644
--- a/pkg/linux_amd64/net/http/cgi.a
+++ b/pkg/linux_amd64/net/http/cgi.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/cookiejar.a b/pkg/linux_amd64/net/http/cookiejar.a
index a0fa355..7721b93 100644
--- a/pkg/linux_amd64/net/http/cookiejar.a
+++ b/pkg/linux_amd64/net/http/cookiejar.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/fcgi.a b/pkg/linux_amd64/net/http/fcgi.a
index b9b7898..6b7569e 100644
--- a/pkg/linux_amd64/net/http/fcgi.a
+++ b/pkg/linux_amd64/net/http/fcgi.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/httptest.a b/pkg/linux_amd64/net/http/httptest.a
index 29bf899..22a5a78 100644
--- a/pkg/linux_amd64/net/http/httptest.a
+++ b/pkg/linux_amd64/net/http/httptest.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/httptrace.a b/pkg/linux_amd64/net/http/httptrace.a
index 2a867ae..5f16e08 100644
--- a/pkg/linux_amd64/net/http/httptrace.a
+++ b/pkg/linux_amd64/net/http/httptrace.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/httputil.a b/pkg/linux_amd64/net/http/httputil.a
index 9e1a6c6..6db3f11 100644
--- a/pkg/linux_amd64/net/http/httputil.a
+++ b/pkg/linux_amd64/net/http/httputil.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/internal.a b/pkg/linux_amd64/net/http/internal.a
index c48cddb..3b4d151 100644
--- a/pkg/linux_amd64/net/http/internal.a
+++ b/pkg/linux_amd64/net/http/internal.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/internal/ascii.a b/pkg/linux_amd64/net/http/internal/ascii.a
index 7383597..f822084 100644
--- a/pkg/linux_amd64/net/http/internal/ascii.a
+++ b/pkg/linux_amd64/net/http/internal/ascii.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/internal/testcert.a b/pkg/linux_amd64/net/http/internal/testcert.a
index 243c080..a4e27c3 100644
--- a/pkg/linux_amd64/net/http/internal/testcert.a
+++ b/pkg/linux_amd64/net/http/internal/testcert.a
Binary files differ
diff --git a/pkg/linux_amd64/net/http/pprof.a b/pkg/linux_amd64/net/http/pprof.a
index ae58482..f20c313 100644
--- a/pkg/linux_amd64/net/http/pprof.a
+++ b/pkg/linux_amd64/net/http/pprof.a
Binary files differ
diff --git a/pkg/linux_amd64/net/internal/socktest.a b/pkg/linux_amd64/net/internal/socktest.a
index 502718f..b9a0e33 100644
--- a/pkg/linux_amd64/net/internal/socktest.a
+++ b/pkg/linux_amd64/net/internal/socktest.a
Binary files differ
diff --git a/pkg/linux_amd64/net/mail.a b/pkg/linux_amd64/net/mail.a
index dbbcbbb..d5097f1 100644
--- a/pkg/linux_amd64/net/mail.a
+++ b/pkg/linux_amd64/net/mail.a
Binary files differ
diff --git a/pkg/linux_amd64/net/netip.a b/pkg/linux_amd64/net/netip.a
index 9685ed7..8882744 100644
--- a/pkg/linux_amd64/net/netip.a
+++ b/pkg/linux_amd64/net/netip.a
Binary files differ
diff --git a/pkg/linux_amd64/net/rpc.a b/pkg/linux_amd64/net/rpc.a
index 0e9c142..b487c5d 100644
--- a/pkg/linux_amd64/net/rpc.a
+++ b/pkg/linux_amd64/net/rpc.a
Binary files differ
diff --git a/pkg/linux_amd64/net/rpc/jsonrpc.a b/pkg/linux_amd64/net/rpc/jsonrpc.a
index 61797b6..263951a 100644
--- a/pkg/linux_amd64/net/rpc/jsonrpc.a
+++ b/pkg/linux_amd64/net/rpc/jsonrpc.a
Binary files differ
diff --git a/pkg/linux_amd64/net/smtp.a b/pkg/linux_amd64/net/smtp.a
index 7b9c432..7f34606 100644
--- a/pkg/linux_amd64/net/smtp.a
+++ b/pkg/linux_amd64/net/smtp.a
Binary files differ
diff --git a/pkg/linux_amd64/net/textproto.a b/pkg/linux_amd64/net/textproto.a
index 542df10..c472709 100644
--- a/pkg/linux_amd64/net/textproto.a
+++ b/pkg/linux_amd64/net/textproto.a
Binary files differ
diff --git a/pkg/linux_amd64/net/url.a b/pkg/linux_amd64/net/url.a
index b481b66..992c4f4 100644
--- a/pkg/linux_amd64/net/url.a
+++ b/pkg/linux_amd64/net/url.a
Binary files differ
diff --git a/pkg/linux_amd64/os.a b/pkg/linux_amd64/os.a
index 9a04c83..4418d2a 100644
--- a/pkg/linux_amd64/os.a
+++ b/pkg/linux_amd64/os.a
Binary files differ
diff --git a/pkg/linux_amd64/os/exec.a b/pkg/linux_amd64/os/exec.a
index 8ccecfe..a772096 100644
--- a/pkg/linux_amd64/os/exec.a
+++ b/pkg/linux_amd64/os/exec.a
Binary files differ
diff --git a/pkg/linux_amd64/os/exec/internal/fdtest.a b/pkg/linux_amd64/os/exec/internal/fdtest.a
index 77995cb..096db5e 100644
--- a/pkg/linux_amd64/os/exec/internal/fdtest.a
+++ b/pkg/linux_amd64/os/exec/internal/fdtest.a
Binary files differ
diff --git a/pkg/linux_amd64/os/signal.a b/pkg/linux_amd64/os/signal.a
index 8a91a57..3b820a6 100644
--- a/pkg/linux_amd64/os/signal.a
+++ b/pkg/linux_amd64/os/signal.a
Binary files differ
diff --git a/pkg/linux_amd64/os/signal/internal/pty.a b/pkg/linux_amd64/os/signal/internal/pty.a
index 0fd7e62..1c78216 100644
--- a/pkg/linux_amd64/os/signal/internal/pty.a
+++ b/pkg/linux_amd64/os/signal/internal/pty.a
Binary files differ
diff --git a/pkg/linux_amd64/os/user.a b/pkg/linux_amd64/os/user.a
index 9b3c0ec..cd0f67e 100644
--- a/pkg/linux_amd64/os/user.a
+++ b/pkg/linux_amd64/os/user.a
Binary files differ
diff --git a/pkg/linux_amd64/path.a b/pkg/linux_amd64/path.a
index d7dc5e2..71ac5cd 100644
--- a/pkg/linux_amd64/path.a
+++ b/pkg/linux_amd64/path.a
Binary files differ
diff --git a/pkg/linux_amd64/path/filepath.a b/pkg/linux_amd64/path/filepath.a
index 42e4903..a908435 100644
--- a/pkg/linux_amd64/path/filepath.a
+++ b/pkg/linux_amd64/path/filepath.a
Binary files differ
diff --git a/pkg/linux_amd64/plugin.a b/pkg/linux_amd64/plugin.a
index 7699321..dcccbdd 100644
--- a/pkg/linux_amd64/plugin.a
+++ b/pkg/linux_amd64/plugin.a
Binary files differ
diff --git a/pkg/linux_amd64/reflect.a b/pkg/linux_amd64/reflect.a
index f235a4c..b5b092c 100644
--- a/pkg/linux_amd64/reflect.a
+++ b/pkg/linux_amd64/reflect.a
Binary files differ
diff --git a/pkg/linux_amd64/reflect/internal/example1.a b/pkg/linux_amd64/reflect/internal/example1.a
index 6b9b387..7e825f9 100644
--- a/pkg/linux_amd64/reflect/internal/example1.a
+++ b/pkg/linux_amd64/reflect/internal/example1.a
Binary files differ
diff --git a/pkg/linux_amd64/reflect/internal/example2.a b/pkg/linux_amd64/reflect/internal/example2.a
index 2bb36c3..49f1ac5 100644
--- a/pkg/linux_amd64/reflect/internal/example2.a
+++ b/pkg/linux_amd64/reflect/internal/example2.a
Binary files differ
diff --git a/pkg/linux_amd64/regexp.a b/pkg/linux_amd64/regexp.a
index 62b2c6c..b609d27 100644
--- a/pkg/linux_amd64/regexp.a
+++ b/pkg/linux_amd64/regexp.a
Binary files differ
diff --git a/pkg/linux_amd64/regexp/syntax.a b/pkg/linux_amd64/regexp/syntax.a
index a689dc7..eb6940c 100644
--- a/pkg/linux_amd64/regexp/syntax.a
+++ b/pkg/linux_amd64/regexp/syntax.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime.a b/pkg/linux_amd64/runtime.a
index f341be0..8c8c312 100644
--- a/pkg/linux_amd64/runtime.a
+++ b/pkg/linux_amd64/runtime.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/cgo.a b/pkg/linux_amd64/runtime/cgo.a
index 8b1d79c..0c35127 100644
--- a/pkg/linux_amd64/runtime/cgo.a
+++ b/pkg/linux_amd64/runtime/cgo.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/debug.a b/pkg/linux_amd64/runtime/debug.a
index 04b09f3..136761b 100644
--- a/pkg/linux_amd64/runtime/debug.a
+++ b/pkg/linux_amd64/runtime/debug.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/internal/atomic.a b/pkg/linux_amd64/runtime/internal/atomic.a
index 7b5376d..df50508 100644
--- a/pkg/linux_amd64/runtime/internal/atomic.a
+++ b/pkg/linux_amd64/runtime/internal/atomic.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/internal/math.a b/pkg/linux_amd64/runtime/internal/math.a
index 5211c41..ad31b99 100644
--- a/pkg/linux_amd64/runtime/internal/math.a
+++ b/pkg/linux_amd64/runtime/internal/math.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/internal/sys.a b/pkg/linux_amd64/runtime/internal/sys.a
index 779cb35..f37fc1d 100644
--- a/pkg/linux_amd64/runtime/internal/sys.a
+++ b/pkg/linux_amd64/runtime/internal/sys.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/internal/syscall.a b/pkg/linux_amd64/runtime/internal/syscall.a
new file mode 100644
index 0000000..ffc4bd8
--- /dev/null
+++ b/pkg/linux_amd64/runtime/internal/syscall.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/metrics.a b/pkg/linux_amd64/runtime/metrics.a
index 40bd5c0..a943a66 100644
--- a/pkg/linux_amd64/runtime/metrics.a
+++ b/pkg/linux_amd64/runtime/metrics.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/pprof.a b/pkg/linux_amd64/runtime/pprof.a
index 17a49d2..831f71a 100644
--- a/pkg/linux_amd64/runtime/pprof.a
+++ b/pkg/linux_amd64/runtime/pprof.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/race.a b/pkg/linux_amd64/runtime/race.a
index 789318b..5963996 100644
--- a/pkg/linux_amd64/runtime/race.a
+++ b/pkg/linux_amd64/runtime/race.a
Binary files differ
diff --git a/pkg/linux_amd64/runtime/trace.a b/pkg/linux_amd64/runtime/trace.a
index f33c34c..b022149 100644
--- a/pkg/linux_amd64/runtime/trace.a
+++ b/pkg/linux_amd64/runtime/trace.a
Binary files differ
diff --git a/pkg/linux_amd64/sort.a b/pkg/linux_amd64/sort.a
index f0c7d30..8d24e89 100644
--- a/pkg/linux_amd64/sort.a
+++ b/pkg/linux_amd64/sort.a
Binary files differ
diff --git a/pkg/linux_amd64/strconv.a b/pkg/linux_amd64/strconv.a
index d8d320d..4ba15bb 100644
--- a/pkg/linux_amd64/strconv.a
+++ b/pkg/linux_amd64/strconv.a
Binary files differ
diff --git a/pkg/linux_amd64/strings.a b/pkg/linux_amd64/strings.a
index e10ef20..1f8752b 100644
--- a/pkg/linux_amd64/strings.a
+++ b/pkg/linux_amd64/strings.a
Binary files differ
diff --git a/pkg/linux_amd64/sync.a b/pkg/linux_amd64/sync.a
index 08a24b5..28a17b3 100644
--- a/pkg/linux_amd64/sync.a
+++ b/pkg/linux_amd64/sync.a
Binary files differ
diff --git a/pkg/linux_amd64/sync/atomic.a b/pkg/linux_amd64/sync/atomic.a
index 62416fc..303ccf0 100644
--- a/pkg/linux_amd64/sync/atomic.a
+++ b/pkg/linux_amd64/sync/atomic.a
Binary files differ
diff --git a/pkg/linux_amd64/syscall.a b/pkg/linux_amd64/syscall.a
index 762a92c..3b5a44b 100644
--- a/pkg/linux_amd64/syscall.a
+++ b/pkg/linux_amd64/syscall.a
Binary files differ
diff --git a/pkg/linux_amd64/testing.a b/pkg/linux_amd64/testing.a
index 83eac1f..a1ccc1d 100644
--- a/pkg/linux_amd64/testing.a
+++ b/pkg/linux_amd64/testing.a
Binary files differ
diff --git a/pkg/linux_amd64/testing/fstest.a b/pkg/linux_amd64/testing/fstest.a
index 128757f..73e7119 100644
--- a/pkg/linux_amd64/testing/fstest.a
+++ b/pkg/linux_amd64/testing/fstest.a
Binary files differ
diff --git a/pkg/linux_amd64/testing/internal/testdeps.a b/pkg/linux_amd64/testing/internal/testdeps.a
index 9105f82..cc5dbc3 100644
--- a/pkg/linux_amd64/testing/internal/testdeps.a
+++ b/pkg/linux_amd64/testing/internal/testdeps.a
Binary files differ
diff --git a/pkg/linux_amd64/testing/iotest.a b/pkg/linux_amd64/testing/iotest.a
index ba4faf1..ab43f70 100644
--- a/pkg/linux_amd64/testing/iotest.a
+++ b/pkg/linux_amd64/testing/iotest.a
Binary files differ
diff --git a/pkg/linux_amd64/testing/quick.a b/pkg/linux_amd64/testing/quick.a
index 77e46d3..ed2a504 100644
--- a/pkg/linux_amd64/testing/quick.a
+++ b/pkg/linux_amd64/testing/quick.a
Binary files differ
diff --git a/pkg/linux_amd64/text/scanner.a b/pkg/linux_amd64/text/scanner.a
index 97479c7..84be55f 100644
--- a/pkg/linux_amd64/text/scanner.a
+++ b/pkg/linux_amd64/text/scanner.a
Binary files differ
diff --git a/pkg/linux_amd64/text/tabwriter.a b/pkg/linux_amd64/text/tabwriter.a
index 92ac305..7c67c49 100644
--- a/pkg/linux_amd64/text/tabwriter.a
+++ b/pkg/linux_amd64/text/tabwriter.a
Binary files differ
diff --git a/pkg/linux_amd64/text/template.a b/pkg/linux_amd64/text/template.a
index 55cc390..51413b3 100644
--- a/pkg/linux_amd64/text/template.a
+++ b/pkg/linux_amd64/text/template.a
Binary files differ
diff --git a/pkg/linux_amd64/text/template/parse.a b/pkg/linux_amd64/text/template/parse.a
index e6e46fd..3cc339f 100644
--- a/pkg/linux_amd64/text/template/parse.a
+++ b/pkg/linux_amd64/text/template/parse.a
Binary files differ
diff --git a/pkg/linux_amd64/time.a b/pkg/linux_amd64/time.a
index 64e7ec6..4cd4728 100644
--- a/pkg/linux_amd64/time.a
+++ b/pkg/linux_amd64/time.a
Binary files differ
diff --git a/pkg/linux_amd64/time/tzdata.a b/pkg/linux_amd64/time/tzdata.a
index ae325a8..1fe40bd 100644
--- a/pkg/linux_amd64/time/tzdata.a
+++ b/pkg/linux_amd64/time/tzdata.a
Binary files differ
diff --git a/pkg/linux_amd64/unicode.a b/pkg/linux_amd64/unicode.a
index f0b0e0d..2fad19f 100644
--- a/pkg/linux_amd64/unicode.a
+++ b/pkg/linux_amd64/unicode.a
Binary files differ
diff --git a/pkg/linux_amd64/unicode/utf16.a b/pkg/linux_amd64/unicode/utf16.a
index 6573eff..8abb23d 100644
--- a/pkg/linux_amd64/unicode/utf16.a
+++ b/pkg/linux_amd64/unicode/utf16.a
Binary files differ
diff --git a/pkg/linux_amd64/unicode/utf8.a b/pkg/linux_amd64/unicode/utf8.a
index bedf4bf..4d9bd6a 100644
--- a/pkg/linux_amd64/unicode/utf8.a
+++ b/pkg/linux_amd64/unicode/utf8.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/chacha20.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/chacha20.a
index 7a7912b..2079190 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/chacha20.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/chacha20.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/chacha20poly1305.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/chacha20poly1305.a
index 163732a..208b5ac 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/chacha20poly1305.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/chacha20poly1305.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/cryptobyte.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/cryptobyte.a
index d6b391f..a23c7f3 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/cryptobyte.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/cryptobyte.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/cryptobyte/asn1.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/cryptobyte/asn1.a
index e60d52e..bd48e8a 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/cryptobyte/asn1.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/cryptobyte/asn1.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/curve25519.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/curve25519.a
index df61cf3..7d480eb 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/curve25519.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/curve25519.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/curve25519/internal/field.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/curve25519/internal/field.a
index bb7fbd6..21571c0 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/curve25519/internal/field.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/curve25519/internal/field.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/hkdf.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/hkdf.a
index a039f67..2173a31 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/hkdf.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/hkdf.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/internal/poly1305.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/internal/poly1305.a
index 8cdefc9..755a855 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/internal/poly1305.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/internal/poly1305.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/crypto/internal/subtle.a b/pkg/linux_amd64/vendor/golang.org/x/crypto/internal/subtle.a
index 1f8c37f..9e8543d 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/crypto/internal/subtle.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/crypto/internal/subtle.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/net/dns/dnsmessage.a b/pkg/linux_amd64/vendor/golang.org/x/net/dns/dnsmessage.a
index 941f01b..97d843f 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/net/dns/dnsmessage.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/net/dns/dnsmessage.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/net/http/httpguts.a b/pkg/linux_amd64/vendor/golang.org/x/net/http/httpguts.a
index 16ebe04..a872862 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/net/http/httpguts.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/net/http/httpguts.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/net/http/httpproxy.a b/pkg/linux_amd64/vendor/golang.org/x/net/http/httpproxy.a
index b06d9b6..7242707 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/net/http/httpproxy.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/net/http/httpproxy.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/net/http2/hpack.a b/pkg/linux_amd64/vendor/golang.org/x/net/http2/hpack.a
index 26afae8..2731283 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/net/http2/hpack.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/net/http2/hpack.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/net/idna.a b/pkg/linux_amd64/vendor/golang.org/x/net/idna.a
index edb3c4e..27808de 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/net/idna.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/net/idna.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/net/nettest.a b/pkg/linux_amd64/vendor/golang.org/x/net/nettest.a
index 6ee26ea..ebb486c 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/net/nettest.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/net/nettest.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/sys/cpu.a b/pkg/linux_amd64/vendor/golang.org/x/sys/cpu.a
index 5b12b17..9278757 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/sys/cpu.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/sys/cpu.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/text/secure/bidirule.a b/pkg/linux_amd64/vendor/golang.org/x/text/secure/bidirule.a
index dc05e34..89ac187 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/text/secure/bidirule.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/text/secure/bidirule.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/text/transform.a b/pkg/linux_amd64/vendor/golang.org/x/text/transform.a
index a96beb6..2be34e7 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/text/transform.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/text/transform.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/text/unicode/bidi.a b/pkg/linux_amd64/vendor/golang.org/x/text/unicode/bidi.a
index 8261cfe..ff31ad1 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/text/unicode/bidi.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/text/unicode/bidi.a
Binary files differ
diff --git a/pkg/linux_amd64/vendor/golang.org/x/text/unicode/norm.a b/pkg/linux_amd64/vendor/golang.org/x/text/unicode/norm.a
index d8dd0d9..b40be09 100644
--- a/pkg/linux_amd64/vendor/golang.org/x/text/unicode/norm.a
+++ b/pkg/linux_amd64/vendor/golang.org/x/text/unicode/norm.a
Binary files differ
diff --git a/pkg/linux_amd64_race/archive/tar.a b/pkg/linux_amd64_race/archive/tar.a
index 381e499..dc63077 100644
--- a/pkg/linux_amd64_race/archive/tar.a
+++ b/pkg/linux_amd64_race/archive/tar.a
Binary files differ
diff --git a/pkg/linux_amd64_race/archive/zip.a b/pkg/linux_amd64_race/archive/zip.a
index 20ca138..44d1151 100644
--- a/pkg/linux_amd64_race/archive/zip.a
+++ b/pkg/linux_amd64_race/archive/zip.a
Binary files differ
diff --git a/pkg/linux_amd64_race/bufio.a b/pkg/linux_amd64_race/bufio.a
index aec7ea3..7663aa3 100644
--- a/pkg/linux_amd64_race/bufio.a
+++ b/pkg/linux_amd64_race/bufio.a
Binary files differ
diff --git a/pkg/linux_amd64_race/bytes.a b/pkg/linux_amd64_race/bytes.a
index 3770b65..17a4674 100644
--- a/pkg/linux_amd64_race/bytes.a
+++ b/pkg/linux_amd64_race/bytes.a
Binary files differ
diff --git a/pkg/linux_amd64_race/compress/bzip2.a b/pkg/linux_amd64_race/compress/bzip2.a
index db4fc80..d773dd2 100644
--- a/pkg/linux_amd64_race/compress/bzip2.a
+++ b/pkg/linux_amd64_race/compress/bzip2.a
Binary files differ
diff --git a/pkg/linux_amd64_race/compress/flate.a b/pkg/linux_amd64_race/compress/flate.a
index e50aacd..b9c5492 100644
--- a/pkg/linux_amd64_race/compress/flate.a
+++ b/pkg/linux_amd64_race/compress/flate.a
Binary files differ
diff --git a/pkg/linux_amd64_race/compress/gzip.a b/pkg/linux_amd64_race/compress/gzip.a
index 93db800..4be5e97 100644
--- a/pkg/linux_amd64_race/compress/gzip.a
+++ b/pkg/linux_amd64_race/compress/gzip.a
Binary files differ
diff --git a/pkg/linux_amd64_race/compress/lzw.a b/pkg/linux_amd64_race/compress/lzw.a
index 45c8725..d119701 100644
--- a/pkg/linux_amd64_race/compress/lzw.a
+++ b/pkg/linux_amd64_race/compress/lzw.a
Binary files differ
diff --git a/pkg/linux_amd64_race/compress/zlib.a b/pkg/linux_amd64_race/compress/zlib.a
index cd9b4ac..a7f7aaf 100644
--- a/pkg/linux_amd64_race/compress/zlib.a
+++ b/pkg/linux_amd64_race/compress/zlib.a
Binary files differ
diff --git a/pkg/linux_amd64_race/constraints.a b/pkg/linux_amd64_race/constraints.a
deleted file mode 100644
index e7dc14a..0000000
--- a/pkg/linux_amd64_race/constraints.a
+++ /dev/null
Binary files differ
diff --git a/pkg/linux_amd64_race/container/heap.a b/pkg/linux_amd64_race/container/heap.a
index 313d7bf..178a7e1 100644
--- a/pkg/linux_amd64_race/container/heap.a
+++ b/pkg/linux_amd64_race/container/heap.a
Binary files differ
diff --git a/pkg/linux_amd64_race/container/list.a b/pkg/linux_amd64_race/container/list.a
index 6bf3e8c..c793378 100644
--- a/pkg/linux_amd64_race/container/list.a
+++ b/pkg/linux_amd64_race/container/list.a
Binary files differ
diff --git a/pkg/linux_amd64_race/container/ring.a b/pkg/linux_amd64_race/container/ring.a
index 21eb0c0..aafae90 100644
--- a/pkg/linux_amd64_race/container/ring.a
+++ b/pkg/linux_amd64_race/container/ring.a
Binary files differ
diff --git a/pkg/linux_amd64_race/context.a b/pkg/linux_amd64_race/context.a
index 9a9ccd6..a321445 100644
--- a/pkg/linux_amd64_race/context.a
+++ b/pkg/linux_amd64_race/context.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto.a b/pkg/linux_amd64_race/crypto.a
index 2e8d84f..b0e7581 100644
--- a/pkg/linux_amd64_race/crypto.a
+++ b/pkg/linux_amd64_race/crypto.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/aes.a b/pkg/linux_amd64_race/crypto/aes.a
index 959aa73..9f2ed6a 100644
--- a/pkg/linux_amd64_race/crypto/aes.a
+++ b/pkg/linux_amd64_race/crypto/aes.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/cipher.a b/pkg/linux_amd64_race/crypto/cipher.a
index a00948d..7fc8ae1 100644
--- a/pkg/linux_amd64_race/crypto/cipher.a
+++ b/pkg/linux_amd64_race/crypto/cipher.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/des.a b/pkg/linux_amd64_race/crypto/des.a
index 51ed354..4a9f9b8 100644
--- a/pkg/linux_amd64_race/crypto/des.a
+++ b/pkg/linux_amd64_race/crypto/des.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/dsa.a b/pkg/linux_amd64_race/crypto/dsa.a
index 98f63ad..b994757 100644
--- a/pkg/linux_amd64_race/crypto/dsa.a
+++ b/pkg/linux_amd64_race/crypto/dsa.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/ecdsa.a b/pkg/linux_amd64_race/crypto/ecdsa.a
index 024e472..1c7eaf3 100644
--- a/pkg/linux_amd64_race/crypto/ecdsa.a
+++ b/pkg/linux_amd64_race/crypto/ecdsa.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/ed25519.a b/pkg/linux_amd64_race/crypto/ed25519.a
index 99ede32..abbc34c 100644
--- a/pkg/linux_amd64_race/crypto/ed25519.a
+++ b/pkg/linux_amd64_race/crypto/ed25519.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/ed25519/internal/edwards25519.a b/pkg/linux_amd64_race/crypto/ed25519/internal/edwards25519.a
index 0c10b22..e07a47c 100644
--- a/pkg/linux_amd64_race/crypto/ed25519/internal/edwards25519.a
+++ b/pkg/linux_amd64_race/crypto/ed25519/internal/edwards25519.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/ed25519/internal/edwards25519/field.a b/pkg/linux_amd64_race/crypto/ed25519/internal/edwards25519/field.a
index f263247..bd6ec9e 100644
--- a/pkg/linux_amd64_race/crypto/ed25519/internal/edwards25519/field.a
+++ b/pkg/linux_amd64_race/crypto/ed25519/internal/edwards25519/field.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/elliptic.a b/pkg/linux_amd64_race/crypto/elliptic.a
index 4936026..0e63f0a 100644
--- a/pkg/linux_amd64_race/crypto/elliptic.a
+++ b/pkg/linux_amd64_race/crypto/elliptic.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/elliptic/internal/fiat.a b/pkg/linux_amd64_race/crypto/elliptic/internal/fiat.a
index 8dd209a..20008c3 100644
--- a/pkg/linux_amd64_race/crypto/elliptic/internal/fiat.a
+++ b/pkg/linux_amd64_race/crypto/elliptic/internal/fiat.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/elliptic/internal/nistec.a b/pkg/linux_amd64_race/crypto/elliptic/internal/nistec.a
index 1df176c..0218eae 100644
--- a/pkg/linux_amd64_race/crypto/elliptic/internal/nistec.a
+++ b/pkg/linux_amd64_race/crypto/elliptic/internal/nistec.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/hmac.a b/pkg/linux_amd64_race/crypto/hmac.a
index fdf4a7a..9ee8548 100644
--- a/pkg/linux_amd64_race/crypto/hmac.a
+++ b/pkg/linux_amd64_race/crypto/hmac.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/internal/randutil.a b/pkg/linux_amd64_race/crypto/internal/randutil.a
index fdc588b..07c17eb 100644
--- a/pkg/linux_amd64_race/crypto/internal/randutil.a
+++ b/pkg/linux_amd64_race/crypto/internal/randutil.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/internal/subtle.a b/pkg/linux_amd64_race/crypto/internal/subtle.a
index f38acef..a021080 100644
--- a/pkg/linux_amd64_race/crypto/internal/subtle.a
+++ b/pkg/linux_amd64_race/crypto/internal/subtle.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/md5.a b/pkg/linux_amd64_race/crypto/md5.a
index fb6ad42..19f11d8 100644
--- a/pkg/linux_amd64_race/crypto/md5.a
+++ b/pkg/linux_amd64_race/crypto/md5.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/rand.a b/pkg/linux_amd64_race/crypto/rand.a
index 25ac964..6b9f391 100644
--- a/pkg/linux_amd64_race/crypto/rand.a
+++ b/pkg/linux_amd64_race/crypto/rand.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/rc4.a b/pkg/linux_amd64_race/crypto/rc4.a
index b3f81bc..a99acec 100644
--- a/pkg/linux_amd64_race/crypto/rc4.a
+++ b/pkg/linux_amd64_race/crypto/rc4.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/rsa.a b/pkg/linux_amd64_race/crypto/rsa.a
index 837a583..089dfe2 100644
--- a/pkg/linux_amd64_race/crypto/rsa.a
+++ b/pkg/linux_amd64_race/crypto/rsa.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/sha1.a b/pkg/linux_amd64_race/crypto/sha1.a
index 2d155ea..bdd78d0 100644
--- a/pkg/linux_amd64_race/crypto/sha1.a
+++ b/pkg/linux_amd64_race/crypto/sha1.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/sha256.a b/pkg/linux_amd64_race/crypto/sha256.a
index af858e3..08c9abb 100644
--- a/pkg/linux_amd64_race/crypto/sha256.a
+++ b/pkg/linux_amd64_race/crypto/sha256.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/sha512.a b/pkg/linux_amd64_race/crypto/sha512.a
index 00c0b01..36baa3a 100644
--- a/pkg/linux_amd64_race/crypto/sha512.a
+++ b/pkg/linux_amd64_race/crypto/sha512.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/subtle.a b/pkg/linux_amd64_race/crypto/subtle.a
index cd618f1..be3dc99 100644
--- a/pkg/linux_amd64_race/crypto/subtle.a
+++ b/pkg/linux_amd64_race/crypto/subtle.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/tls.a b/pkg/linux_amd64_race/crypto/tls.a
index 5c8dc1b..3300444 100644
--- a/pkg/linux_amd64_race/crypto/tls.a
+++ b/pkg/linux_amd64_race/crypto/tls.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/x509.a b/pkg/linux_amd64_race/crypto/x509.a
index fc7e590..0f30c0b 100644
--- a/pkg/linux_amd64_race/crypto/x509.a
+++ b/pkg/linux_amd64_race/crypto/x509.a
Binary files differ
diff --git a/pkg/linux_amd64_race/crypto/x509/pkix.a b/pkg/linux_amd64_race/crypto/x509/pkix.a
index d870e15..98a645a 100644
--- a/pkg/linux_amd64_race/crypto/x509/pkix.a
+++ b/pkg/linux_amd64_race/crypto/x509/pkix.a
Binary files differ
diff --git a/pkg/linux_amd64_race/database/sql.a b/pkg/linux_amd64_race/database/sql.a
index f14fdc6..53e6180 100644
--- a/pkg/linux_amd64_race/database/sql.a
+++ b/pkg/linux_amd64_race/database/sql.a
Binary files differ
diff --git a/pkg/linux_amd64_race/database/sql/driver.a b/pkg/linux_amd64_race/database/sql/driver.a
index 2caea5b..130cd82 100644
--- a/pkg/linux_amd64_race/database/sql/driver.a
+++ b/pkg/linux_amd64_race/database/sql/driver.a
Binary files differ
diff --git a/pkg/linux_amd64_race/debug/buildinfo.a b/pkg/linux_amd64_race/debug/buildinfo.a
index 684abb2..a0d3e70 100644
--- a/pkg/linux_amd64_race/debug/buildinfo.a
+++ b/pkg/linux_amd64_race/debug/buildinfo.a
Binary files differ
diff --git a/pkg/linux_amd64_race/debug/dwarf.a b/pkg/linux_amd64_race/debug/dwarf.a
index 019871b..05a9876 100644
--- a/pkg/linux_amd64_race/debug/dwarf.a
+++ b/pkg/linux_amd64_race/debug/dwarf.a
Binary files differ
diff --git a/pkg/linux_amd64_race/debug/elf.a b/pkg/linux_amd64_race/debug/elf.a
index ec45f04..3cafe55 100644
--- a/pkg/linux_amd64_race/debug/elf.a
+++ b/pkg/linux_amd64_race/debug/elf.a
Binary files differ
diff --git a/pkg/linux_amd64_race/debug/gosym.a b/pkg/linux_amd64_race/debug/gosym.a
index 288cf23..57d3951 100644
--- a/pkg/linux_amd64_race/debug/gosym.a
+++ b/pkg/linux_amd64_race/debug/gosym.a
Binary files differ
diff --git a/pkg/linux_amd64_race/debug/macho.a b/pkg/linux_amd64_race/debug/macho.a
index 02d7a10..9fde81a 100644
--- a/pkg/linux_amd64_race/debug/macho.a
+++ b/pkg/linux_amd64_race/debug/macho.a
Binary files differ
diff --git a/pkg/linux_amd64_race/debug/pe.a b/pkg/linux_amd64_race/debug/pe.a
index 8232448..46a33f9 100644
--- a/pkg/linux_amd64_race/debug/pe.a
+++ b/pkg/linux_amd64_race/debug/pe.a
Binary files differ
diff --git a/pkg/linux_amd64_race/debug/plan9obj.a b/pkg/linux_amd64_race/debug/plan9obj.a
index 689520b..36e4399 100644
--- a/pkg/linux_amd64_race/debug/plan9obj.a
+++ b/pkg/linux_amd64_race/debug/plan9obj.a
Binary files differ
diff --git a/pkg/linux_amd64_race/embed.a b/pkg/linux_amd64_race/embed.a
index 6bac0c7..b653e27 100644
--- a/pkg/linux_amd64_race/embed.a
+++ b/pkg/linux_amd64_race/embed.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding.a b/pkg/linux_amd64_race/encoding.a
index 3f9379e..860ff34 100644
--- a/pkg/linux_amd64_race/encoding.a
+++ b/pkg/linux_amd64_race/encoding.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/ascii85.a b/pkg/linux_amd64_race/encoding/ascii85.a
index a852345..8b19cd5 100644
--- a/pkg/linux_amd64_race/encoding/ascii85.a
+++ b/pkg/linux_amd64_race/encoding/ascii85.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/asn1.a b/pkg/linux_amd64_race/encoding/asn1.a
index 5462eee..cb8e7e8 100644
--- a/pkg/linux_amd64_race/encoding/asn1.a
+++ b/pkg/linux_amd64_race/encoding/asn1.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/base32.a b/pkg/linux_amd64_race/encoding/base32.a
index 9eff828..d46949e 100644
--- a/pkg/linux_amd64_race/encoding/base32.a
+++ b/pkg/linux_amd64_race/encoding/base32.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/base64.a b/pkg/linux_amd64_race/encoding/base64.a
index 906b55c..9bb8187 100644
--- a/pkg/linux_amd64_race/encoding/base64.a
+++ b/pkg/linux_amd64_race/encoding/base64.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/binary.a b/pkg/linux_amd64_race/encoding/binary.a
index 9d7eda6..e854490 100644
--- a/pkg/linux_amd64_race/encoding/binary.a
+++ b/pkg/linux_amd64_race/encoding/binary.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/csv.a b/pkg/linux_amd64_race/encoding/csv.a
index d048538..a3d317a 100644
--- a/pkg/linux_amd64_race/encoding/csv.a
+++ b/pkg/linux_amd64_race/encoding/csv.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/gob.a b/pkg/linux_amd64_race/encoding/gob.a
index 9540dd2..e34c1d4 100644
--- a/pkg/linux_amd64_race/encoding/gob.a
+++ b/pkg/linux_amd64_race/encoding/gob.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/hex.a b/pkg/linux_amd64_race/encoding/hex.a
index dbb56cb..d6221f2 100644
--- a/pkg/linux_amd64_race/encoding/hex.a
+++ b/pkg/linux_amd64_race/encoding/hex.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/json.a b/pkg/linux_amd64_race/encoding/json.a
index dcb2116..98104f4 100644
--- a/pkg/linux_amd64_race/encoding/json.a
+++ b/pkg/linux_amd64_race/encoding/json.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/pem.a b/pkg/linux_amd64_race/encoding/pem.a
index 645b7d9..ea29265 100644
--- a/pkg/linux_amd64_race/encoding/pem.a
+++ b/pkg/linux_amd64_race/encoding/pem.a
Binary files differ
diff --git a/pkg/linux_amd64_race/encoding/xml.a b/pkg/linux_amd64_race/encoding/xml.a
index f2d9625..be031d5 100644
--- a/pkg/linux_amd64_race/encoding/xml.a
+++ b/pkg/linux_amd64_race/encoding/xml.a
Binary files differ
diff --git a/pkg/linux_amd64_race/errors.a b/pkg/linux_amd64_race/errors.a
index f579365..ff97306 100644
--- a/pkg/linux_amd64_race/errors.a
+++ b/pkg/linux_amd64_race/errors.a
Binary files differ
diff --git a/pkg/linux_amd64_race/expvar.a b/pkg/linux_amd64_race/expvar.a
index bd0fd0d..152bb9b 100644
--- a/pkg/linux_amd64_race/expvar.a
+++ b/pkg/linux_amd64_race/expvar.a
Binary files differ
diff --git a/pkg/linux_amd64_race/flag.a b/pkg/linux_amd64_race/flag.a
index a9091cc..69881ad 100644
--- a/pkg/linux_amd64_race/flag.a
+++ b/pkg/linux_amd64_race/flag.a
Binary files differ
diff --git a/pkg/linux_amd64_race/fmt.a b/pkg/linux_amd64_race/fmt.a
index b1132cf..8a96627 100644
--- a/pkg/linux_amd64_race/fmt.a
+++ b/pkg/linux_amd64_race/fmt.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/ast.a b/pkg/linux_amd64_race/go/ast.a
index 0e3b166..579594d 100644
--- a/pkg/linux_amd64_race/go/ast.a
+++ b/pkg/linux_amd64_race/go/ast.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/build.a b/pkg/linux_amd64_race/go/build.a
index 5171a3b..7683e74 100644
--- a/pkg/linux_amd64_race/go/build.a
+++ b/pkg/linux_amd64_race/go/build.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/build/constraint.a b/pkg/linux_amd64_race/go/build/constraint.a
index 625c517..420ac01 100644
--- a/pkg/linux_amd64_race/go/build/constraint.a
+++ b/pkg/linux_amd64_race/go/build/constraint.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/constant.a b/pkg/linux_amd64_race/go/constant.a
index e2e5a84..35d32d8 100644
--- a/pkg/linux_amd64_race/go/constant.a
+++ b/pkg/linux_amd64_race/go/constant.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/doc.a b/pkg/linux_amd64_race/go/doc.a
index 254ed75..e9ecb10 100644
--- a/pkg/linux_amd64_race/go/doc.a
+++ b/pkg/linux_amd64_race/go/doc.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/format.a b/pkg/linux_amd64_race/go/format.a
index b153d65..3b324ea 100644
--- a/pkg/linux_amd64_race/go/format.a
+++ b/pkg/linux_amd64_race/go/format.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/importer.a b/pkg/linux_amd64_race/go/importer.a
index fc8786f..4ff2be6 100644
--- a/pkg/linux_amd64_race/go/importer.a
+++ b/pkg/linux_amd64_race/go/importer.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/internal/gccgoimporter.a b/pkg/linux_amd64_race/go/internal/gccgoimporter.a
index dee157f..376c364 100644
--- a/pkg/linux_amd64_race/go/internal/gccgoimporter.a
+++ b/pkg/linux_amd64_race/go/internal/gccgoimporter.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/internal/gcimporter.a b/pkg/linux_amd64_race/go/internal/gcimporter.a
index fc43a2b..40800db 100644
--- a/pkg/linux_amd64_race/go/internal/gcimporter.a
+++ b/pkg/linux_amd64_race/go/internal/gcimporter.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/internal/srcimporter.a b/pkg/linux_amd64_race/go/internal/srcimporter.a
index 0dd60ff..1621419 100644
--- a/pkg/linux_amd64_race/go/internal/srcimporter.a
+++ b/pkg/linux_amd64_race/go/internal/srcimporter.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/internal/typeparams.a b/pkg/linux_amd64_race/go/internal/typeparams.a
index 69b4699..5623dff 100644
--- a/pkg/linux_amd64_race/go/internal/typeparams.a
+++ b/pkg/linux_amd64_race/go/internal/typeparams.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/parser.a b/pkg/linux_amd64_race/go/parser.a
index 267059b..da00f0e 100644
--- a/pkg/linux_amd64_race/go/parser.a
+++ b/pkg/linux_amd64_race/go/parser.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/printer.a b/pkg/linux_amd64_race/go/printer.a
index 570faa9..86c247f 100644
--- a/pkg/linux_amd64_race/go/printer.a
+++ b/pkg/linux_amd64_race/go/printer.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/scanner.a b/pkg/linux_amd64_race/go/scanner.a
index 5d249f4..db26800 100644
--- a/pkg/linux_amd64_race/go/scanner.a
+++ b/pkg/linux_amd64_race/go/scanner.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/token.a b/pkg/linux_amd64_race/go/token.a
index c5b700c..3cf26e7 100644
--- a/pkg/linux_amd64_race/go/token.a
+++ b/pkg/linux_amd64_race/go/token.a
Binary files differ
diff --git a/pkg/linux_amd64_race/go/types.a b/pkg/linux_amd64_race/go/types.a
index b98c363..cae31ca 100644
--- a/pkg/linux_amd64_race/go/types.a
+++ b/pkg/linux_amd64_race/go/types.a
Binary files differ
diff --git a/pkg/linux_amd64_race/hash.a b/pkg/linux_amd64_race/hash.a
index eff15b5..f1e5ba2 100644
--- a/pkg/linux_amd64_race/hash.a
+++ b/pkg/linux_amd64_race/hash.a
Binary files differ
diff --git a/pkg/linux_amd64_race/hash/adler32.a b/pkg/linux_amd64_race/hash/adler32.a
index 13c0a5c..2e2e16e 100644
--- a/pkg/linux_amd64_race/hash/adler32.a
+++ b/pkg/linux_amd64_race/hash/adler32.a
Binary files differ
diff --git a/pkg/linux_amd64_race/hash/crc32.a b/pkg/linux_amd64_race/hash/crc32.a
index acdd61a..b1f8f09 100644
--- a/pkg/linux_amd64_race/hash/crc32.a
+++ b/pkg/linux_amd64_race/hash/crc32.a
Binary files differ
diff --git a/pkg/linux_amd64_race/hash/crc64.a b/pkg/linux_amd64_race/hash/crc64.a
index 64475d0..920060d 100644
--- a/pkg/linux_amd64_race/hash/crc64.a
+++ b/pkg/linux_amd64_race/hash/crc64.a
Binary files differ
diff --git a/pkg/linux_amd64_race/hash/fnv.a b/pkg/linux_amd64_race/hash/fnv.a
index 82a085f..6ab4552 100644
--- a/pkg/linux_amd64_race/hash/fnv.a
+++ b/pkg/linux_amd64_race/hash/fnv.a
Binary files differ
diff --git a/pkg/linux_amd64_race/hash/maphash.a b/pkg/linux_amd64_race/hash/maphash.a
index 70ca0d8..6b223f6 100644
--- a/pkg/linux_amd64_race/hash/maphash.a
+++ b/pkg/linux_amd64_race/hash/maphash.a
Binary files differ
diff --git a/pkg/linux_amd64_race/html.a b/pkg/linux_amd64_race/html.a
index d4eded3..ac46a04 100644
--- a/pkg/linux_amd64_race/html.a
+++ b/pkg/linux_amd64_race/html.a
Binary files differ
diff --git a/pkg/linux_amd64_race/html/template.a b/pkg/linux_amd64_race/html/template.a
index 239bcaf..b0eb106 100644
--- a/pkg/linux_amd64_race/html/template.a
+++ b/pkg/linux_amd64_race/html/template.a
Binary files differ
diff --git a/pkg/linux_amd64_race/image.a b/pkg/linux_amd64_race/image.a
index 846b20d..b1bfbd1 100644
--- a/pkg/linux_amd64_race/image.a
+++ b/pkg/linux_amd64_race/image.a
Binary files differ
diff --git a/pkg/linux_amd64_race/image/color.a b/pkg/linux_amd64_race/image/color.a
index 8a9d8ad..55b5e67 100644
--- a/pkg/linux_amd64_race/image/color.a
+++ b/pkg/linux_amd64_race/image/color.a
Binary files differ
diff --git a/pkg/linux_amd64_race/image/color/palette.a b/pkg/linux_amd64_race/image/color/palette.a
index 5f55db2..408241c 100644
--- a/pkg/linux_amd64_race/image/color/palette.a
+++ b/pkg/linux_amd64_race/image/color/palette.a
Binary files differ
diff --git a/pkg/linux_amd64_race/image/draw.a b/pkg/linux_amd64_race/image/draw.a
index 2c871fe..653f27e 100644
--- a/pkg/linux_amd64_race/image/draw.a
+++ b/pkg/linux_amd64_race/image/draw.a
Binary files differ
diff --git a/pkg/linux_amd64_race/image/gif.a b/pkg/linux_amd64_race/image/gif.a
index cc341f6..83461a6 100644
--- a/pkg/linux_amd64_race/image/gif.a
+++ b/pkg/linux_amd64_race/image/gif.a
Binary files differ
diff --git a/pkg/linux_amd64_race/image/internal/imageutil.a b/pkg/linux_amd64_race/image/internal/imageutil.a
index fbb7b85..ae1bde8 100644
--- a/pkg/linux_amd64_race/image/internal/imageutil.a
+++ b/pkg/linux_amd64_race/image/internal/imageutil.a
Binary files differ
diff --git a/pkg/linux_amd64_race/image/jpeg.a b/pkg/linux_amd64_race/image/jpeg.a
index e385835..fafffd4 100644
--- a/pkg/linux_amd64_race/image/jpeg.a
+++ b/pkg/linux_amd64_race/image/jpeg.a
Binary files differ
diff --git a/pkg/linux_amd64_race/image/png.a b/pkg/linux_amd64_race/image/png.a
index 55ad2a6..32c6bbc 100644
--- a/pkg/linux_amd64_race/image/png.a
+++ b/pkg/linux_amd64_race/image/png.a
Binary files differ
diff --git a/pkg/linux_amd64_race/index/suffixarray.a b/pkg/linux_amd64_race/index/suffixarray.a
index 911390e..75209ae 100644
--- a/pkg/linux_amd64_race/index/suffixarray.a
+++ b/pkg/linux_amd64_race/index/suffixarray.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/abi.a b/pkg/linux_amd64_race/internal/abi.a
index f3bcd02..bbd4217 100644
--- a/pkg/linux_amd64_race/internal/abi.a
+++ b/pkg/linux_amd64_race/internal/abi.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/buildcfg.a b/pkg/linux_amd64_race/internal/buildcfg.a
index cfc616b..5795b76 100644
--- a/pkg/linux_amd64_race/internal/buildcfg.a
+++ b/pkg/linux_amd64_race/internal/buildcfg.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/bytealg.a b/pkg/linux_amd64_race/internal/bytealg.a
index f73f1b5..4467af3 100644
--- a/pkg/linux_amd64_race/internal/bytealg.a
+++ b/pkg/linux_amd64_race/internal/bytealg.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/cfg.a b/pkg/linux_amd64_race/internal/cfg.a
index eb3ac98..2c2eca3 100644
--- a/pkg/linux_amd64_race/internal/cfg.a
+++ b/pkg/linux_amd64_race/internal/cfg.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/cpu.a b/pkg/linux_amd64_race/internal/cpu.a
index 836b518..8d48f18 100644
--- a/pkg/linux_amd64_race/internal/cpu.a
+++ b/pkg/linux_amd64_race/internal/cpu.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/execabs.a b/pkg/linux_amd64_race/internal/execabs.a
index 74f078e..839cc41 100644
--- a/pkg/linux_amd64_race/internal/execabs.a
+++ b/pkg/linux_amd64_race/internal/execabs.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/fmtsort.a b/pkg/linux_amd64_race/internal/fmtsort.a
index f1acae2..5033142 100644
--- a/pkg/linux_amd64_race/internal/fmtsort.a
+++ b/pkg/linux_amd64_race/internal/fmtsort.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/fuzz.a b/pkg/linux_amd64_race/internal/fuzz.a
index 2313276..1aa7e68 100644
--- a/pkg/linux_amd64_race/internal/fuzz.a
+++ b/pkg/linux_amd64_race/internal/fuzz.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/goarch.a b/pkg/linux_amd64_race/internal/goarch.a
index 74c40df..60e1323 100644
--- a/pkg/linux_amd64_race/internal/goarch.a
+++ b/pkg/linux_amd64_race/internal/goarch.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/godebug.a b/pkg/linux_amd64_race/internal/godebug.a
index 7b1d3b8..cdd3419 100644
--- a/pkg/linux_amd64_race/internal/godebug.a
+++ b/pkg/linux_amd64_race/internal/godebug.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/goexperiment.a b/pkg/linux_amd64_race/internal/goexperiment.a
index 8bd157b..2d8e988 100644
--- a/pkg/linux_amd64_race/internal/goexperiment.a
+++ b/pkg/linux_amd64_race/internal/goexperiment.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/goos.a b/pkg/linux_amd64_race/internal/goos.a
index 4ae6f3a..a84cce5 100644
--- a/pkg/linux_amd64_race/internal/goos.a
+++ b/pkg/linux_amd64_race/internal/goos.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/goroot.a b/pkg/linux_amd64_race/internal/goroot.a
index 4ac6ccf..47f35ba 100644
--- a/pkg/linux_amd64_race/internal/goroot.a
+++ b/pkg/linux_amd64_race/internal/goroot.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/goversion.a b/pkg/linux_amd64_race/internal/goversion.a
index 980a511..2279850 100644
--- a/pkg/linux_amd64_race/internal/goversion.a
+++ b/pkg/linux_amd64_race/internal/goversion.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/intern.a b/pkg/linux_amd64_race/internal/intern.a
index 6150eab..21ee8b9 100644
--- a/pkg/linux_amd64_race/internal/intern.a
+++ b/pkg/linux_amd64_race/internal/intern.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/itoa.a b/pkg/linux_amd64_race/internal/itoa.a
index ed8aabe..a3bcdcf 100644
--- a/pkg/linux_amd64_race/internal/itoa.a
+++ b/pkg/linux_amd64_race/internal/itoa.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/lazyregexp.a b/pkg/linux_amd64_race/internal/lazyregexp.a
index 933621f..55ff416 100644
--- a/pkg/linux_amd64_race/internal/lazyregexp.a
+++ b/pkg/linux_amd64_race/internal/lazyregexp.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/lazytemplate.a b/pkg/linux_amd64_race/internal/lazytemplate.a
index 66d8f56..64bb954 100644
--- a/pkg/linux_amd64_race/internal/lazytemplate.a
+++ b/pkg/linux_amd64_race/internal/lazytemplate.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/nettrace.a b/pkg/linux_amd64_race/internal/nettrace.a
index 0298b85..74aa0ea 100644
--- a/pkg/linux_amd64_race/internal/nettrace.a
+++ b/pkg/linux_amd64_race/internal/nettrace.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/obscuretestdata.a b/pkg/linux_amd64_race/internal/obscuretestdata.a
index 1804172..031a7d0 100644
--- a/pkg/linux_amd64_race/internal/obscuretestdata.a
+++ b/pkg/linux_amd64_race/internal/obscuretestdata.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/oserror.a b/pkg/linux_amd64_race/internal/oserror.a
index ae425d5..a303b57 100644
--- a/pkg/linux_amd64_race/internal/oserror.a
+++ b/pkg/linux_amd64_race/internal/oserror.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/poll.a b/pkg/linux_amd64_race/internal/poll.a
index a8911b5..0521166 100644
--- a/pkg/linux_amd64_race/internal/poll.a
+++ b/pkg/linux_amd64_race/internal/poll.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/profile.a b/pkg/linux_amd64_race/internal/profile.a
index 1fc5e3f..bb048b4 100644
--- a/pkg/linux_amd64_race/internal/profile.a
+++ b/pkg/linux_amd64_race/internal/profile.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/race.a b/pkg/linux_amd64_race/internal/race.a
index 6a2d6e0..16f4b20 100644
--- a/pkg/linux_amd64_race/internal/race.a
+++ b/pkg/linux_amd64_race/internal/race.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/reflectlite.a b/pkg/linux_amd64_race/internal/reflectlite.a
index 70731c7..e0d54f0 100644
--- a/pkg/linux_amd64_race/internal/reflectlite.a
+++ b/pkg/linux_amd64_race/internal/reflectlite.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/singleflight.a b/pkg/linux_amd64_race/internal/singleflight.a
index 86072f4..69cbb47 100644
--- a/pkg/linux_amd64_race/internal/singleflight.a
+++ b/pkg/linux_amd64_race/internal/singleflight.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/syscall/execenv.a b/pkg/linux_amd64_race/internal/syscall/execenv.a
index ebdd3c0..f1b16b2 100644
--- a/pkg/linux_amd64_race/internal/syscall/execenv.a
+++ b/pkg/linux_amd64_race/internal/syscall/execenv.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/syscall/unix.a b/pkg/linux_amd64_race/internal/syscall/unix.a
index 61bb4d3..36ab438 100644
--- a/pkg/linux_amd64_race/internal/syscall/unix.a
+++ b/pkg/linux_amd64_race/internal/syscall/unix.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/sysinfo.a b/pkg/linux_amd64_race/internal/sysinfo.a
index bb15bc8..c221f67 100644
--- a/pkg/linux_amd64_race/internal/sysinfo.a
+++ b/pkg/linux_amd64_race/internal/sysinfo.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/testenv.a b/pkg/linux_amd64_race/internal/testenv.a
index 4fe2fd9..9135562 100644
--- a/pkg/linux_amd64_race/internal/testenv.a
+++ b/pkg/linux_amd64_race/internal/testenv.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/testlog.a b/pkg/linux_amd64_race/internal/testlog.a
index 1f0642d..b7a42c6 100644
--- a/pkg/linux_amd64_race/internal/testlog.a
+++ b/pkg/linux_amd64_race/internal/testlog.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/trace.a b/pkg/linux_amd64_race/internal/trace.a
index b6a8ba2..a38c0e3 100644
--- a/pkg/linux_amd64_race/internal/trace.a
+++ b/pkg/linux_amd64_race/internal/trace.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/unsafeheader.a b/pkg/linux_amd64_race/internal/unsafeheader.a
index 6fa7fa6..9f6562a 100644
--- a/pkg/linux_amd64_race/internal/unsafeheader.a
+++ b/pkg/linux_amd64_race/internal/unsafeheader.a
Binary files differ
diff --git a/pkg/linux_amd64_race/internal/xcoff.a b/pkg/linux_amd64_race/internal/xcoff.a
index bf0d1e7..6229f6f 100644
--- a/pkg/linux_amd64_race/internal/xcoff.a
+++ b/pkg/linux_amd64_race/internal/xcoff.a
Binary files differ
diff --git a/pkg/linux_amd64_race/io.a b/pkg/linux_amd64_race/io.a
index b63f6f2..8d01b8a 100644
--- a/pkg/linux_amd64_race/io.a
+++ b/pkg/linux_amd64_race/io.a
Binary files differ
diff --git a/pkg/linux_amd64_race/io/fs.a b/pkg/linux_amd64_race/io/fs.a
index c89c5c8..1cd97df 100644
--- a/pkg/linux_amd64_race/io/fs.a
+++ b/pkg/linux_amd64_race/io/fs.a
Binary files differ
diff --git a/pkg/linux_amd64_race/io/ioutil.a b/pkg/linux_amd64_race/io/ioutil.a
index 32ed4f3..8d2923a 100644
--- a/pkg/linux_amd64_race/io/ioutil.a
+++ b/pkg/linux_amd64_race/io/ioutil.a
Binary files differ
diff --git a/pkg/linux_amd64_race/log.a b/pkg/linux_amd64_race/log.a
index c0f8dc3..a9fe496 100644
--- a/pkg/linux_amd64_race/log.a
+++ b/pkg/linux_amd64_race/log.a
Binary files differ
diff --git a/pkg/linux_amd64_race/log/syslog.a b/pkg/linux_amd64_race/log/syslog.a
index 8e9866c..f25189b 100644
--- a/pkg/linux_amd64_race/log/syslog.a
+++ b/pkg/linux_amd64_race/log/syslog.a
Binary files differ
diff --git a/pkg/linux_amd64_race/math.a b/pkg/linux_amd64_race/math.a
index 3939b26..e5de3b8 100644
--- a/pkg/linux_amd64_race/math.a
+++ b/pkg/linux_amd64_race/math.a
Binary files differ
diff --git a/pkg/linux_amd64_race/math/big.a b/pkg/linux_amd64_race/math/big.a
index 3d80e42..7659273 100644
--- a/pkg/linux_amd64_race/math/big.a
+++ b/pkg/linux_amd64_race/math/big.a
Binary files differ
diff --git a/pkg/linux_amd64_race/math/bits.a b/pkg/linux_amd64_race/math/bits.a
index 6ab6f6e..23680d8 100644
--- a/pkg/linux_amd64_race/math/bits.a
+++ b/pkg/linux_amd64_race/math/bits.a
Binary files differ
diff --git a/pkg/linux_amd64_race/math/cmplx.a b/pkg/linux_amd64_race/math/cmplx.a
index 3082eab..e34acdc 100644
--- a/pkg/linux_amd64_race/math/cmplx.a
+++ b/pkg/linux_amd64_race/math/cmplx.a
Binary files differ
diff --git a/pkg/linux_amd64_race/math/rand.a b/pkg/linux_amd64_race/math/rand.a
index 9d58b22..c53f475 100644
--- a/pkg/linux_amd64_race/math/rand.a
+++ b/pkg/linux_amd64_race/math/rand.a
Binary files differ
diff --git a/pkg/linux_amd64_race/mime.a b/pkg/linux_amd64_race/mime.a
index 56bba2c..8715488 100644
--- a/pkg/linux_amd64_race/mime.a
+++ b/pkg/linux_amd64_race/mime.a
Binary files differ
diff --git a/pkg/linux_amd64_race/mime/multipart.a b/pkg/linux_amd64_race/mime/multipart.a
index efda00a..46285bd 100644
--- a/pkg/linux_amd64_race/mime/multipart.a
+++ b/pkg/linux_amd64_race/mime/multipart.a
Binary files differ
diff --git a/pkg/linux_amd64_race/mime/quotedprintable.a b/pkg/linux_amd64_race/mime/quotedprintable.a
index 794705b..6b0370d 100644
--- a/pkg/linux_amd64_race/mime/quotedprintable.a
+++ b/pkg/linux_amd64_race/mime/quotedprintable.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net.a b/pkg/linux_amd64_race/net.a
index 2f4ed0d..a9a028b 100644
--- a/pkg/linux_amd64_race/net.a
+++ b/pkg/linux_amd64_race/net.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http.a b/pkg/linux_amd64_race/net/http.a
index c0d8bc2..41dff23 100644
--- a/pkg/linux_amd64_race/net/http.a
+++ b/pkg/linux_amd64_race/net/http.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/cgi.a b/pkg/linux_amd64_race/net/http/cgi.a
index 9c1b151..7dbbf60 100644
--- a/pkg/linux_amd64_race/net/http/cgi.a
+++ b/pkg/linux_amd64_race/net/http/cgi.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/cookiejar.a b/pkg/linux_amd64_race/net/http/cookiejar.a
index 018b58c..c75d878 100644
--- a/pkg/linux_amd64_race/net/http/cookiejar.a
+++ b/pkg/linux_amd64_race/net/http/cookiejar.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/fcgi.a b/pkg/linux_amd64_race/net/http/fcgi.a
index f5f2f22..29aee3f 100644
--- a/pkg/linux_amd64_race/net/http/fcgi.a
+++ b/pkg/linux_amd64_race/net/http/fcgi.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/httptest.a b/pkg/linux_amd64_race/net/http/httptest.a
index b4b2d64..34745c3 100644
--- a/pkg/linux_amd64_race/net/http/httptest.a
+++ b/pkg/linux_amd64_race/net/http/httptest.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/httptrace.a b/pkg/linux_amd64_race/net/http/httptrace.a
index 285ce07..ee6db98 100644
--- a/pkg/linux_amd64_race/net/http/httptrace.a
+++ b/pkg/linux_amd64_race/net/http/httptrace.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/httputil.a b/pkg/linux_amd64_race/net/http/httputil.a
index 6dafcbf..ea08caa 100644
--- a/pkg/linux_amd64_race/net/http/httputil.a
+++ b/pkg/linux_amd64_race/net/http/httputil.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/internal.a b/pkg/linux_amd64_race/net/http/internal.a
index 8182bd7..4160c1a 100644
--- a/pkg/linux_amd64_race/net/http/internal.a
+++ b/pkg/linux_amd64_race/net/http/internal.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/internal/ascii.a b/pkg/linux_amd64_race/net/http/internal/ascii.a
index 5cf6ff9..d6dcad4 100644
--- a/pkg/linux_amd64_race/net/http/internal/ascii.a
+++ b/pkg/linux_amd64_race/net/http/internal/ascii.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/internal/testcert.a b/pkg/linux_amd64_race/net/http/internal/testcert.a
index 103a6aa..875d40e 100644
--- a/pkg/linux_amd64_race/net/http/internal/testcert.a
+++ b/pkg/linux_amd64_race/net/http/internal/testcert.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/http/pprof.a b/pkg/linux_amd64_race/net/http/pprof.a
index 8d13ca6..1ceb721 100644
--- a/pkg/linux_amd64_race/net/http/pprof.a
+++ b/pkg/linux_amd64_race/net/http/pprof.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/internal/socktest.a b/pkg/linux_amd64_race/net/internal/socktest.a
index 83a0e08..cd925d4 100644
--- a/pkg/linux_amd64_race/net/internal/socktest.a
+++ b/pkg/linux_amd64_race/net/internal/socktest.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/mail.a b/pkg/linux_amd64_race/net/mail.a
index a9907bc..495ea12 100644
--- a/pkg/linux_amd64_race/net/mail.a
+++ b/pkg/linux_amd64_race/net/mail.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/netip.a b/pkg/linux_amd64_race/net/netip.a
index cb8f3a8..628b680 100644
--- a/pkg/linux_amd64_race/net/netip.a
+++ b/pkg/linux_amd64_race/net/netip.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/rpc.a b/pkg/linux_amd64_race/net/rpc.a
index 9445572..3d3878e 100644
--- a/pkg/linux_amd64_race/net/rpc.a
+++ b/pkg/linux_amd64_race/net/rpc.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/rpc/jsonrpc.a b/pkg/linux_amd64_race/net/rpc/jsonrpc.a
index afb8b39..970a07e 100644
--- a/pkg/linux_amd64_race/net/rpc/jsonrpc.a
+++ b/pkg/linux_amd64_race/net/rpc/jsonrpc.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/smtp.a b/pkg/linux_amd64_race/net/smtp.a
index 2a6160c..ff54b9f 100644
--- a/pkg/linux_amd64_race/net/smtp.a
+++ b/pkg/linux_amd64_race/net/smtp.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/textproto.a b/pkg/linux_amd64_race/net/textproto.a
index cde5fda..6a5debd 100644
--- a/pkg/linux_amd64_race/net/textproto.a
+++ b/pkg/linux_amd64_race/net/textproto.a
Binary files differ
diff --git a/pkg/linux_amd64_race/net/url.a b/pkg/linux_amd64_race/net/url.a
index 8877bbc..248f85e 100644
--- a/pkg/linux_amd64_race/net/url.a
+++ b/pkg/linux_amd64_race/net/url.a
Binary files differ
diff --git a/pkg/linux_amd64_race/os.a b/pkg/linux_amd64_race/os.a
index 22e7d98..191fa87 100644
--- a/pkg/linux_amd64_race/os.a
+++ b/pkg/linux_amd64_race/os.a
Binary files differ
diff --git a/pkg/linux_amd64_race/os/exec.a b/pkg/linux_amd64_race/os/exec.a
index 27a139b..bb843e4 100644
--- a/pkg/linux_amd64_race/os/exec.a
+++ b/pkg/linux_amd64_race/os/exec.a
Binary files differ
diff --git a/pkg/linux_amd64_race/os/exec/internal/fdtest.a b/pkg/linux_amd64_race/os/exec/internal/fdtest.a
index fe91fb4..a3190ba 100644
--- a/pkg/linux_amd64_race/os/exec/internal/fdtest.a
+++ b/pkg/linux_amd64_race/os/exec/internal/fdtest.a
Binary files differ
diff --git a/pkg/linux_amd64_race/os/signal.a b/pkg/linux_amd64_race/os/signal.a
index 228db17..dfc4069 100644
--- a/pkg/linux_amd64_race/os/signal.a
+++ b/pkg/linux_amd64_race/os/signal.a
Binary files differ
diff --git a/pkg/linux_amd64_race/os/signal/internal/pty.a b/pkg/linux_amd64_race/os/signal/internal/pty.a
index 1ec4b8b..6c8eb6a 100644
--- a/pkg/linux_amd64_race/os/signal/internal/pty.a
+++ b/pkg/linux_amd64_race/os/signal/internal/pty.a
Binary files differ
diff --git a/pkg/linux_amd64_race/os/user.a b/pkg/linux_amd64_race/os/user.a
index 180c21b..3d2f1d7 100644
--- a/pkg/linux_amd64_race/os/user.a
+++ b/pkg/linux_amd64_race/os/user.a
Binary files differ
diff --git a/pkg/linux_amd64_race/path.a b/pkg/linux_amd64_race/path.a
index f1a6a0f..984537f 100644
--- a/pkg/linux_amd64_race/path.a
+++ b/pkg/linux_amd64_race/path.a
Binary files differ
diff --git a/pkg/linux_amd64_race/path/filepath.a b/pkg/linux_amd64_race/path/filepath.a
index d33b050..0b09f2c 100644
--- a/pkg/linux_amd64_race/path/filepath.a
+++ b/pkg/linux_amd64_race/path/filepath.a
Binary files differ
diff --git a/pkg/linux_amd64_race/plugin.a b/pkg/linux_amd64_race/plugin.a
index 3addf93..a2d163f 100644
--- a/pkg/linux_amd64_race/plugin.a
+++ b/pkg/linux_amd64_race/plugin.a
Binary files differ
diff --git a/pkg/linux_amd64_race/reflect.a b/pkg/linux_amd64_race/reflect.a
index fb9e4d9..a2eb9dd 100644
--- a/pkg/linux_amd64_race/reflect.a
+++ b/pkg/linux_amd64_race/reflect.a
Binary files differ
diff --git a/pkg/linux_amd64_race/reflect/internal/example1.a b/pkg/linux_amd64_race/reflect/internal/example1.a
index 049c945..81cc54b 100644
--- a/pkg/linux_amd64_race/reflect/internal/example1.a
+++ b/pkg/linux_amd64_race/reflect/internal/example1.a
Binary files differ
diff --git a/pkg/linux_amd64_race/reflect/internal/example2.a b/pkg/linux_amd64_race/reflect/internal/example2.a
index 7b72ce1..88659c9 100644
--- a/pkg/linux_amd64_race/reflect/internal/example2.a
+++ b/pkg/linux_amd64_race/reflect/internal/example2.a
Binary files differ
diff --git a/pkg/linux_amd64_race/regexp.a b/pkg/linux_amd64_race/regexp.a
index 05b0f70..2d1c9b3 100644
--- a/pkg/linux_amd64_race/regexp.a
+++ b/pkg/linux_amd64_race/regexp.a
Binary files differ
diff --git a/pkg/linux_amd64_race/regexp/syntax.a b/pkg/linux_amd64_race/regexp/syntax.a
index 647c365..87b78db 100644
--- a/pkg/linux_amd64_race/regexp/syntax.a
+++ b/pkg/linux_amd64_race/regexp/syntax.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime.a b/pkg/linux_amd64_race/runtime.a
index cd00aec..d68b8fd 100644
--- a/pkg/linux_amd64_race/runtime.a
+++ b/pkg/linux_amd64_race/runtime.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/cgo.a b/pkg/linux_amd64_race/runtime/cgo.a
index 8ae5910..4976f30 100644
--- a/pkg/linux_amd64_race/runtime/cgo.a
+++ b/pkg/linux_amd64_race/runtime/cgo.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/debug.a b/pkg/linux_amd64_race/runtime/debug.a
index b214409..c45773f 100644
--- a/pkg/linux_amd64_race/runtime/debug.a
+++ b/pkg/linux_amd64_race/runtime/debug.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/internal/atomic.a b/pkg/linux_amd64_race/runtime/internal/atomic.a
index 582dded..e649b4f 100644
--- a/pkg/linux_amd64_race/runtime/internal/atomic.a
+++ b/pkg/linux_amd64_race/runtime/internal/atomic.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/internal/math.a b/pkg/linux_amd64_race/runtime/internal/math.a
index 19fec49..aa2dc9e 100644
--- a/pkg/linux_amd64_race/runtime/internal/math.a
+++ b/pkg/linux_amd64_race/runtime/internal/math.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/internal/sys.a b/pkg/linux_amd64_race/runtime/internal/sys.a
index 2b4a901..8c9f0e8 100644
--- a/pkg/linux_amd64_race/runtime/internal/sys.a
+++ b/pkg/linux_amd64_race/runtime/internal/sys.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/internal/syscall.a b/pkg/linux_amd64_race/runtime/internal/syscall.a
new file mode 100644
index 0000000..86020a5
--- /dev/null
+++ b/pkg/linux_amd64_race/runtime/internal/syscall.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/metrics.a b/pkg/linux_amd64_race/runtime/metrics.a
index 3f33fd1..2058b66 100644
--- a/pkg/linux_amd64_race/runtime/metrics.a
+++ b/pkg/linux_amd64_race/runtime/metrics.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/pprof.a b/pkg/linux_amd64_race/runtime/pprof.a
index 667a439..3bfcbe3 100644
--- a/pkg/linux_amd64_race/runtime/pprof.a
+++ b/pkg/linux_amd64_race/runtime/pprof.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/race.a b/pkg/linux_amd64_race/runtime/race.a
index b206778..3a6af52 100644
--- a/pkg/linux_amd64_race/runtime/race.a
+++ b/pkg/linux_amd64_race/runtime/race.a
Binary files differ
diff --git a/pkg/linux_amd64_race/runtime/trace.a b/pkg/linux_amd64_race/runtime/trace.a
index fd21d83..379ee16 100644
--- a/pkg/linux_amd64_race/runtime/trace.a
+++ b/pkg/linux_amd64_race/runtime/trace.a
Binary files differ
diff --git a/pkg/linux_amd64_race/sort.a b/pkg/linux_amd64_race/sort.a
index b23c735..c0e22e9 100644
--- a/pkg/linux_amd64_race/sort.a
+++ b/pkg/linux_amd64_race/sort.a
Binary files differ
diff --git a/pkg/linux_amd64_race/strconv.a b/pkg/linux_amd64_race/strconv.a
index 71377ff..aa57923 100644
--- a/pkg/linux_amd64_race/strconv.a
+++ b/pkg/linux_amd64_race/strconv.a
Binary files differ
diff --git a/pkg/linux_amd64_race/strings.a b/pkg/linux_amd64_race/strings.a
index 3928d6b..b71255b 100644
--- a/pkg/linux_amd64_race/strings.a
+++ b/pkg/linux_amd64_race/strings.a
Binary files differ
diff --git a/pkg/linux_amd64_race/sync.a b/pkg/linux_amd64_race/sync.a
index 4f2dd02..5ea8a36 100644
--- a/pkg/linux_amd64_race/sync.a
+++ b/pkg/linux_amd64_race/sync.a
Binary files differ
diff --git a/pkg/linux_amd64_race/sync/atomic.a b/pkg/linux_amd64_race/sync/atomic.a
index ea52706..bfd0037 100644
--- a/pkg/linux_amd64_race/sync/atomic.a
+++ b/pkg/linux_amd64_race/sync/atomic.a
Binary files differ
diff --git a/pkg/linux_amd64_race/syscall.a b/pkg/linux_amd64_race/syscall.a
index 5c0cc15..dd8494b 100644
--- a/pkg/linux_amd64_race/syscall.a
+++ b/pkg/linux_amd64_race/syscall.a
Binary files differ
diff --git a/pkg/linux_amd64_race/testing.a b/pkg/linux_amd64_race/testing.a
index 5cbaaea..36fe03b 100644
--- a/pkg/linux_amd64_race/testing.a
+++ b/pkg/linux_amd64_race/testing.a
Binary files differ
diff --git a/pkg/linux_amd64_race/testing/fstest.a b/pkg/linux_amd64_race/testing/fstest.a
index 96025af..eca0ea1 100644
--- a/pkg/linux_amd64_race/testing/fstest.a
+++ b/pkg/linux_amd64_race/testing/fstest.a
Binary files differ
diff --git a/pkg/linux_amd64_race/testing/internal/testdeps.a b/pkg/linux_amd64_race/testing/internal/testdeps.a
index 5f427ff..4b70bf0 100644
--- a/pkg/linux_amd64_race/testing/internal/testdeps.a
+++ b/pkg/linux_amd64_race/testing/internal/testdeps.a
Binary files differ
diff --git a/pkg/linux_amd64_race/testing/iotest.a b/pkg/linux_amd64_race/testing/iotest.a
index 840552e..367fe36 100644
--- a/pkg/linux_amd64_race/testing/iotest.a
+++ b/pkg/linux_amd64_race/testing/iotest.a
Binary files differ
diff --git a/pkg/linux_amd64_race/testing/quick.a b/pkg/linux_amd64_race/testing/quick.a
index bcca91d..7f6fcb4 100644
--- a/pkg/linux_amd64_race/testing/quick.a
+++ b/pkg/linux_amd64_race/testing/quick.a
Binary files differ
diff --git a/pkg/linux_amd64_race/text/scanner.a b/pkg/linux_amd64_race/text/scanner.a
index aec7470..12c1295 100644
--- a/pkg/linux_amd64_race/text/scanner.a
+++ b/pkg/linux_amd64_race/text/scanner.a
Binary files differ
diff --git a/pkg/linux_amd64_race/text/tabwriter.a b/pkg/linux_amd64_race/text/tabwriter.a
index 85aa718..d6f0084 100644
--- a/pkg/linux_amd64_race/text/tabwriter.a
+++ b/pkg/linux_amd64_race/text/tabwriter.a
Binary files differ
diff --git a/pkg/linux_amd64_race/text/template.a b/pkg/linux_amd64_race/text/template.a
index 9f7b810..75d8988 100644
--- a/pkg/linux_amd64_race/text/template.a
+++ b/pkg/linux_amd64_race/text/template.a
Binary files differ
diff --git a/pkg/linux_amd64_race/text/template/parse.a b/pkg/linux_amd64_race/text/template/parse.a
index 68a9977..8f9b9a2 100644
--- a/pkg/linux_amd64_race/text/template/parse.a
+++ b/pkg/linux_amd64_race/text/template/parse.a
Binary files differ
diff --git a/pkg/linux_amd64_race/time.a b/pkg/linux_amd64_race/time.a
index 9bf1b2d..8b27b33 100644
--- a/pkg/linux_amd64_race/time.a
+++ b/pkg/linux_amd64_race/time.a
Binary files differ
diff --git a/pkg/linux_amd64_race/time/tzdata.a b/pkg/linux_amd64_race/time/tzdata.a
index a7e6300..e6850a9 100644
--- a/pkg/linux_amd64_race/time/tzdata.a
+++ b/pkg/linux_amd64_race/time/tzdata.a
Binary files differ
diff --git a/pkg/linux_amd64_race/unicode.a b/pkg/linux_amd64_race/unicode.a
index 5195017..f653d2b 100644
--- a/pkg/linux_amd64_race/unicode.a
+++ b/pkg/linux_amd64_race/unicode.a
Binary files differ
diff --git a/pkg/linux_amd64_race/unicode/utf16.a b/pkg/linux_amd64_race/unicode/utf16.a
index 78620fb..5bf9034 100644
--- a/pkg/linux_amd64_race/unicode/utf16.a
+++ b/pkg/linux_amd64_race/unicode/utf16.a
Binary files differ
diff --git a/pkg/linux_amd64_race/unicode/utf8.a b/pkg/linux_amd64_race/unicode/utf8.a
index a0fa1d8..df5393c 100644
--- a/pkg/linux_amd64_race/unicode/utf8.a
+++ b/pkg/linux_amd64_race/unicode/utf8.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/chacha20.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/chacha20.a
index bc72826..c7f4dd5 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/chacha20.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/chacha20.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/chacha20poly1305.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/chacha20poly1305.a
index 8bafb36..178e872 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/chacha20poly1305.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/chacha20poly1305.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/cryptobyte.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/cryptobyte.a
index 81beed2..b7eb766 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/cryptobyte.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/cryptobyte.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/cryptobyte/asn1.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/cryptobyte/asn1.a
index e20dddb..be77d57 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/cryptobyte/asn1.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/cryptobyte/asn1.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/curve25519.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/curve25519.a
index 275d84d..720bba5 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/curve25519.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/curve25519.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/curve25519/internal/field.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/curve25519/internal/field.a
index 6111baa..efcce9d 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/curve25519/internal/field.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/curve25519/internal/field.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/hkdf.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/hkdf.a
index e7325f8..d64b7c2 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/hkdf.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/hkdf.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/internal/poly1305.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/internal/poly1305.a
index 8261d35..0af1f26 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/internal/poly1305.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/internal/poly1305.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/internal/subtle.a b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/internal/subtle.a
index eba678e..f1c2e7c 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/crypto/internal/subtle.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/crypto/internal/subtle.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/net/dns/dnsmessage.a b/pkg/linux_amd64_race/vendor/golang.org/x/net/dns/dnsmessage.a
index 5818126..1e72414 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/net/dns/dnsmessage.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/net/dns/dnsmessage.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/net/http/httpguts.a b/pkg/linux_amd64_race/vendor/golang.org/x/net/http/httpguts.a
index ad31e62..0e2d94a 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/net/http/httpguts.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/net/http/httpguts.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/net/http/httpproxy.a b/pkg/linux_amd64_race/vendor/golang.org/x/net/http/httpproxy.a
index 839cd1f..f351935 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/net/http/httpproxy.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/net/http/httpproxy.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/net/http2/hpack.a b/pkg/linux_amd64_race/vendor/golang.org/x/net/http2/hpack.a
index 1106169..5e9a4da 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/net/http2/hpack.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/net/http2/hpack.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/net/idna.a b/pkg/linux_amd64_race/vendor/golang.org/x/net/idna.a
index 0cdce01..9d480e2 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/net/idna.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/net/idna.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/net/nettest.a b/pkg/linux_amd64_race/vendor/golang.org/x/net/nettest.a
index 685caa7..d0547d3 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/net/nettest.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/net/nettest.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/sys/cpu.a b/pkg/linux_amd64_race/vendor/golang.org/x/sys/cpu.a
index 676fe90..b2b1bb8 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/sys/cpu.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/sys/cpu.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/text/secure/bidirule.a b/pkg/linux_amd64_race/vendor/golang.org/x/text/secure/bidirule.a
index ced7ca3..a800c71 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/text/secure/bidirule.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/text/secure/bidirule.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/text/transform.a b/pkg/linux_amd64_race/vendor/golang.org/x/text/transform.a
index ebf1e88..082e759 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/text/transform.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/text/transform.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/text/unicode/bidi.a b/pkg/linux_amd64_race/vendor/golang.org/x/text/unicode/bidi.a
index cf02cfe..719c2b6 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/text/unicode/bidi.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/text/unicode/bidi.a
Binary files differ
diff --git a/pkg/linux_amd64_race/vendor/golang.org/x/text/unicode/norm.a b/pkg/linux_amd64_race/vendor/golang.org/x/text/unicode/norm.a
index 95f3b6f..7aefdee 100644
--- a/pkg/linux_amd64_race/vendor/golang.org/x/text/unicode/norm.a
+++ b/pkg/linux_amd64_race/vendor/golang.org/x/text/unicode/norm.a
Binary files differ
diff --git a/pkg/tool/linux_amd64/addr2line b/pkg/tool/linux_amd64/addr2line
index f38a614..992c2b9 100755
--- a/pkg/tool/linux_amd64/addr2line
+++ b/pkg/tool/linux_amd64/addr2line
Binary files differ
diff --git a/pkg/tool/linux_amd64/api b/pkg/tool/linux_amd64/api
index a506635..44ee111 100755
--- a/pkg/tool/linux_amd64/api
+++ b/pkg/tool/linux_amd64/api
Binary files differ
diff --git a/pkg/tool/linux_amd64/asm b/pkg/tool/linux_amd64/asm
index edb320b..fdb66d7 100755
--- a/pkg/tool/linux_amd64/asm
+++ b/pkg/tool/linux_amd64/asm
Binary files differ
diff --git a/pkg/tool/linux_amd64/buildid b/pkg/tool/linux_amd64/buildid
index aa8ebaa..a8f831e 100755
--- a/pkg/tool/linux_amd64/buildid
+++ b/pkg/tool/linux_amd64/buildid
Binary files differ
diff --git a/pkg/tool/linux_amd64/cgo b/pkg/tool/linux_amd64/cgo
index 5013a57..e1576b4 100755
--- a/pkg/tool/linux_amd64/cgo
+++ b/pkg/tool/linux_amd64/cgo
Binary files differ
diff --git a/pkg/tool/linux_amd64/compile b/pkg/tool/linux_amd64/compile
index 2601dcb..3e4321b 100755
--- a/pkg/tool/linux_amd64/compile
+++ b/pkg/tool/linux_amd64/compile
Binary files differ
diff --git a/pkg/tool/linux_amd64/cover b/pkg/tool/linux_amd64/cover
index ac11c0b..6870106 100755
--- a/pkg/tool/linux_amd64/cover
+++ b/pkg/tool/linux_amd64/cover
Binary files differ
diff --git a/pkg/tool/linux_amd64/dist b/pkg/tool/linux_amd64/dist
index 9c09308..84c49b5 100755
--- a/pkg/tool/linux_amd64/dist
+++ b/pkg/tool/linux_amd64/dist
Binary files differ
diff --git a/pkg/tool/linux_amd64/doc b/pkg/tool/linux_amd64/doc
index 667e16d..ed0cd53 100755
--- a/pkg/tool/linux_amd64/doc
+++ b/pkg/tool/linux_amd64/doc
Binary files differ
diff --git a/pkg/tool/linux_amd64/fix b/pkg/tool/linux_amd64/fix
index f17fd99..2b10b5c 100755
--- a/pkg/tool/linux_amd64/fix
+++ b/pkg/tool/linux_amd64/fix
Binary files differ
diff --git a/pkg/tool/linux_amd64/link b/pkg/tool/linux_amd64/link
index dd2af2a..2cfbcba 100755
--- a/pkg/tool/linux_amd64/link
+++ b/pkg/tool/linux_amd64/link
Binary files differ
diff --git a/pkg/tool/linux_amd64/nm b/pkg/tool/linux_amd64/nm
index ed4cb2d..23e28ae 100755
--- a/pkg/tool/linux_amd64/nm
+++ b/pkg/tool/linux_amd64/nm
Binary files differ
diff --git a/pkg/tool/linux_amd64/objdump b/pkg/tool/linux_amd64/objdump
index 108c0bb..bdb72d4 100755
--- a/pkg/tool/linux_amd64/objdump
+++ b/pkg/tool/linux_amd64/objdump
Binary files differ
diff --git a/pkg/tool/linux_amd64/pack b/pkg/tool/linux_amd64/pack
index c75c88b..68f2a94 100755
--- a/pkg/tool/linux_amd64/pack
+++ b/pkg/tool/linux_amd64/pack
Binary files differ
diff --git a/pkg/tool/linux_amd64/pprof b/pkg/tool/linux_amd64/pprof
index 82b86c7..f6ee3d6 100755
--- a/pkg/tool/linux_amd64/pprof
+++ b/pkg/tool/linux_amd64/pprof
Binary files differ
diff --git a/pkg/tool/linux_amd64/test2json b/pkg/tool/linux_amd64/test2json
index 172ed6e..1d274cd 100755
--- a/pkg/tool/linux_amd64/test2json
+++ b/pkg/tool/linux_amd64/test2json
Binary files differ
diff --git a/pkg/tool/linux_amd64/trace b/pkg/tool/linux_amd64/trace
index c739f4e..a0d709d 100755
--- a/pkg/tool/linux_amd64/trace
+++ b/pkg/tool/linux_amd64/trace
Binary files differ
diff --git a/pkg/tool/linux_amd64/vet b/pkg/tool/linux_amd64/vet
index ca5ca9f..cab88dd 100755
--- a/pkg/tool/linux_amd64/vet
+++ b/pkg/tool/linux_amd64/vet
Binary files differ
diff --git a/src/archive/tar/fuzz_test.go b/src/archive/tar/fuzz_test.go
new file mode 100644
index 0000000..e73e0d2
--- /dev/null
+++ b/src/archive/tar/fuzz_test.go
@@ -0,0 +1,80 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tar
+
+import (
+ "bytes"
+ "io"
+ "testing"
+)
+
+func FuzzReader(f *testing.F) {
+ b := bytes.NewBuffer(nil)
+ w := NewWriter(b)
+ inp := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
+ err := w.WriteHeader(&Header{
+ Name: "lorem.txt",
+ Mode: 0600,
+ Size: int64(len(inp)),
+ })
+ if err != nil {
+ f.Fatalf("failed to create writer: %s", err)
+ }
+ _, err = w.Write(inp)
+ if err != nil {
+ f.Fatalf("failed to write file to archive: %s", err)
+ }
+ if err := w.Close(); err != nil {
+ f.Fatalf("failed to write archive: %s", err)
+ }
+ f.Add(b.Bytes())
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ r := NewReader(bytes.NewReader(b))
+ type file struct {
+ header *Header
+ content []byte
+ }
+ files := []file{}
+ for {
+ hdr, err := r.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return
+ }
+ buf := bytes.NewBuffer(nil)
+ if _, err := io.Copy(buf, r); err != nil {
+ continue
+ }
+ files = append(files, file{header: hdr, content: buf.Bytes()})
+ }
+
+ // If we were unable to read anything out of the archive don't
+ // bother trying to roundtrip it.
+ if len(files) == 0 {
+ return
+ }
+
+ out := bytes.NewBuffer(nil)
+ w := NewWriter(out)
+ for _, f := range files {
+ if err := w.WriteHeader(f.header); err != nil {
+ t.Fatalf("unable to write previously parsed header: %s", err)
+ }
+ if _, err := w.Write(f.content); err != nil {
+ t.Fatalf("unable to write previously parsed content: %s", err)
+ }
+ }
+ if err := w.Close(); err != nil {
+ t.Fatalf("Unable to write archive: %s", err)
+ }
+
+ // TODO: We may want to check if the archive roundtrips. This would require
+ // taking into account addition of the two zero trailer blocks that Writer.Close
+ // appends.
+ })
+}
diff --git a/src/archive/zip/fuzz_test.go b/src/archive/zip/fuzz_test.go
new file mode 100644
index 0000000..7dffde6
--- /dev/null
+++ b/src/archive/zip/fuzz_test.go
@@ -0,0 +1,81 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package zip
+
+import (
+ "bytes"
+ "io"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func FuzzReader(f *testing.F) {
+ testdata, err := os.ReadDir("testdata")
+ if err != nil {
+ f.Fatalf("failed to read testdata directory: %s", err)
+ }
+ for _, de := range testdata {
+ if de.IsDir() {
+ continue
+ }
+ b, err := os.ReadFile(filepath.Join("testdata", de.Name()))
+ if err != nil {
+ f.Fatalf("failed to read testdata: %s", err)
+ }
+ f.Add(b)
+ }
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ r, err := NewReader(bytes.NewReader(b), int64(len(b)))
+ if err != nil {
+ return
+ }
+
+ type file struct {
+ header *FileHeader
+ content []byte
+ }
+ files := []file{}
+
+ for _, f := range r.File {
+ fr, err := f.Open()
+ if err != nil {
+ continue
+ }
+ content, err := io.ReadAll(fr)
+ if err != nil {
+ continue
+ }
+ files = append(files, file{header: &f.FileHeader, content: content})
+ if _, err := r.Open(f.Name); err != nil {
+ continue
+ }
+ }
+
+ // If we were unable to read anything out of the archive don't
+ // bother trying to roundtrip it.
+ if len(files) == 0 {
+ return
+ }
+
+ w := NewWriter(io.Discard)
+ for _, f := range files {
+ ww, err := w.CreateHeader(f.header)
+ if err != nil {
+ t.Fatalf("unable to write previously parsed header: %s", err)
+ }
+ if _, err := ww.Write(f.content); err != nil {
+ t.Fatalf("unable to write previously parsed content: %s", err)
+ }
+ }
+
+ if err := w.Close(); err != nil {
+ t.Fatalf("Unable to write archive: %s", err)
+ }
+
+ // TODO: We may want to check if the archive roundtrips.
+ })
+}
diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go
index 4dddfa9..ff3396e 100644
--- a/src/bufio/bufio_test.go
+++ b/src/bufio/bufio_test.go
@@ -657,7 +657,7 @@
}
// While not recommended, it is valid to append to a shifted buffer.
- // This forces Write to copy the the input.
+ // This forces Write to copy the input.
if rn.Intn(8) == 0 && cap(b) > 0 {
b = b[1:1:cap(b)]
}
diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go
index 08ae7ed..5657be4 100644
--- a/src/builtin/builtin.go
+++ b/src/builtin/builtin.go
@@ -95,11 +95,11 @@
type any = interface{}
// comparable is an interface that is implemented by all comparable types
-// (booleans, numbers, strings, pointers, channels, interfaces,
-// arrays of comparable types, structs whose fields are all comparable types).
+// (booleans, numbers, strings, pointers, channels, arrays of comparable types,
+// structs whose fields are all comparable types).
// The comparable interface may only be used as a type parameter constraint,
// not as the type of a variable.
-type comparable comparable
+type comparable interface{ comparable }
// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go
index 6fdaa49..41323ad 100644
--- a/src/bytes/bytes.go
+++ b/src/bytes/bytes.go
@@ -372,6 +372,8 @@
// n > 0: at most n subslices; the last subslice will be the unsplit remainder.
// n == 0: the result is nil (zero subslices)
// n < 0: all subslices
+//
+// To split around the first instance of a separator, see Cut.
func SplitN(s, sep []byte, n int) [][]byte { return genSplit(s, sep, 0, n) }
// SplitAfterN slices s into subslices after each instance of sep and
@@ -389,6 +391,8 @@
// the subslices between those separators.
// If sep is empty, Split splits after each UTF-8 sequence.
// It is equivalent to SplitN with a count of -1.
+//
+// To split around the first instance of a separator, see Cut.
func Split(s, sep []byte) [][]byte { return genSplit(s, sep, 0, -1) }
// SplitAfter slices s into all subslices after each instance of sep and
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 036aefe..5ae059e 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -459,8 +459,11 @@
var listCache sync.Map // map[string]listImports, keyed by contextName
-// listSem is a semaphore restricting concurrent invocations of 'go list'.
-var listSem = make(chan semToken, ((runtime.GOMAXPROCS(0)-1)/2)+1)
+// listSem is a semaphore restricting concurrent invocations of 'go list'. 'go
+// list' has its own internal concurrency, so we use a hard-coded constant (to
+// allow the I/O-intensive phases of 'go list' to overlap) instead of scaling
+// all the way up to GOMAXPROCS.
+var listSem = make(chan semToken, 2)
type semToken struct{}
diff --git a/src/cmd/compile/README.md b/src/cmd/compile/README.md
index babc3f7..25fa818 100644
--- a/src/cmd/compile/README.md
+++ b/src/cmd/compile/README.md
@@ -40,12 +40,12 @@
* `cmd/compile/internal/gc` (create compiler AST, type checking, AST transformations)
-The gc package includes an AST definition carried over from when it was written
-in C. All of its code is written in terms of it, so the first thing that the gc
+The gc package includes its own AST definition carried over from when it was written
+in C. All of its code is written in terms of this AST, so the first thing that the gc
package must do is convert the syntax package's syntax tree to the compiler's
AST representation. This extra step may be refactored away in the future.
-The AST is then type-checked. The first steps are name resolution and type
+The gc AST is then type-checked. The first steps are name resolution and type
inference, which determine which object belongs to which identifier, and what
type each expression has. Type-checking includes certain extra checks, such as
"declared and not used" as well as determining whether or not a function
@@ -79,8 +79,7 @@
Then, a series of machine-independent passes and rules are applied. These do not
concern any single computer architecture, and thus run on all `GOARCH` variants.
-
-Some examples of these generic passes include dead code elimination, removal of
+These passes include dead code elimination, removal of
unneeded nil checks, and removal of unused branches. The generic rewrite rules
mainly concern expressions, such as replacing some expressions with constant
values, and optimizing multiplications and float operations.
diff --git a/src/cmd/compile/abi-internal.md b/src/cmd/compile/abi-internal.md
index 7fe4463..53eaa84 100644
--- a/src/cmd/compile/abi-internal.md
+++ b/src/cmd/compile/abi-internal.md
@@ -155,7 +155,7 @@
1. Remember I and FP.
1. If T has zero size, add T to the stack sequence S and return.
1. Try to register-assign V.
-1. If step 2 failed, reset I and FP to the values from step 1, add T
+1. If step 3 failed, reset I and FP to the values from step 1, add T
to the stack sequence S, and assign V to this field in S.
Register-assignment of a value V of underlying type T works as follows:
diff --git a/src/cmd/compile/internal/base/base.go b/src/cmd/compile/internal/base/base.go
index be6d49f..39ce8e6 100644
--- a/src/cmd/compile/internal/base/base.go
+++ b/src/cmd/compile/internal/base/base.go
@@ -62,8 +62,9 @@
// at best instrumentation would cause infinite recursion.
var NoInstrumentPkgs = []string{
"runtime/internal/atomic",
- "runtime/internal/sys",
"runtime/internal/math",
+ "runtime/internal/sys",
+ "runtime/internal/syscall",
"runtime",
"runtime/race",
"runtime/msan",
diff --git a/src/cmd/compile/internal/base/print.go b/src/cmd/compile/internal/base/print.go
index 4afe2eb..955f9d2 100644
--- a/src/cmd/compile/internal/base/print.go
+++ b/src/cmd/compile/internal/base/print.go
@@ -217,10 +217,10 @@
fmt.Printf("\n")
// If this is a released compiler version, ask for a bug report.
- if strings.HasPrefix(buildcfg.Version, "go") {
+ if Debug.Panic == 0 && strings.HasPrefix(buildcfg.Version, "go") {
fmt.Printf("\n")
fmt.Printf("Please file a bug report including a short program that triggers the error.\n")
- fmt.Printf("https://golang.org/issue/new\n")
+ fmt.Printf("https://go.dev/issue/new\n")
} else {
// Not a release; dump a stack trace, too.
fmt.Println()
diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go
index d1215af..ee76adb 100644
--- a/src/cmd/compile/internal/escape/call.go
+++ b/src/cmd/compile/internal/escape/call.go
@@ -238,6 +238,15 @@
fn.SetWrapper(true)
fn.Nname.SetType(types.NewSignature(types.LocalPkg, nil, nil, nil, nil))
fn.Body = []ir.Node{call}
+ if call, ok := call.(*ir.CallExpr); ok && call.Op() == ir.OCALLFUNC {
+ // If the callee is a named function, link to the original callee.
+ x := call.X
+ if x.Op() == ir.ONAME && x.(*ir.Name).Class == ir.PFUNC {
+ fn.WrappedFunc = call.X.(*ir.Name).Func
+ } else if x.Op() == ir.OMETHEXPR && ir.MethodExprFunc(x).Nname != nil {
+ fn.WrappedFunc = ir.MethodExprName(x).Func
+ }
+ }
clo := fn.OClosure
if n.Op() == ir.OGO {
diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go
index 61e0121..bc6f7c9 100644
--- a/src/cmd/compile/internal/escape/escape.go
+++ b/src/cmd/compile/internal/escape/escape.go
@@ -10,6 +10,7 @@
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/logopt"
+ "cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
)
@@ -243,6 +244,9 @@
n.SetByval(!loc.addrtaken && !loc.reassigned && n.Type().Size() <= 128)
if !n.Byval() {
n.SetAddrtaken(true)
+ if n.Sym().Name == typecheck.LocalDictName {
+ base.FatalfAt(n.Pos(), "dictionary variable not captured by value")
+ }
}
if base.Flag.LowerM > 1 {
@@ -293,6 +297,14 @@
// TODO(mdempsky): Update tests to expect this.
goDeferWrapper := n.Op() == ir.OCLOSURE && n.(*ir.ClosureExpr).Func.Wrapper()
+ if n.Op() == ir.OCONVIDATA && n.(*ir.ConvExpr).NonEscaping {
+ // The allocation for the data word of an interface is known to not escape.
+ // See issue 50182.
+ // (But we do still need to process that allocation, as pointers inside
+ // the data word may escape.)
+ loc.escapes = false
+ }
+
if loc.escapes {
if n.Op() == ir.ONAME {
if base.Flag.CompilingRuntime {
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index eed4387..c9acfc1 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -31,7 +31,7 @@
if t == constant.Float || t == constant.Complex {
break
}
- fmt.Fprintf(b, "#define const_%s %v\n", n.Sym().Name, n.Val())
+ fmt.Fprintf(b, "#define const_%s %v\n", n.Sym().Name, n.Val().ExactString())
case ir.OTYPE:
t := n.Type()
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index ed81ef7..4c4a724 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -35,18 +35,18 @@
"sort"
)
-func hidePanic() {
- if base.Debug.Panic == 0 && base.Errors() > 0 {
- // If we've already complained about things
- // in the program, don't bother complaining
- // about a panic too; let the user clean up
- // the code and try again.
- if err := recover(); err != nil {
- if err == "-h" {
- panic(err)
- }
- base.ErrorExit()
+// handlePanic ensures that we print out an "internal compiler error" for any panic
+// or runtime exception during front-end compiler processing (unless there have
+// already been some compiler errors). It may also be invoked from the explicit panic in
+// hcrash(), in which case, we pass the panic on through.
+func handlePanic() {
+ if err := recover(); err != nil {
+ if err == "-h" {
+ // Force real panic now with -h option (hcrash) - the error
+ // information will have already been printed.
+ panic(err)
}
+ base.Fatalf("panic: %v", err)
}
}
@@ -56,7 +56,7 @@
func Main(archInit func(*ssagen.ArchInfo)) {
base.Timer.Start("fe", "init")
- defer hidePanic()
+ defer handlePanic()
archInit(&ssagen.Arch)
@@ -245,11 +245,6 @@
base.Timer.Start("fe", "inlining")
if base.Flag.LowerL != 0 {
inline.InlinePackage()
- // If any new fully-instantiated types were referenced during
- // inlining, we need to create needed instantiations.
- if len(typecheck.GetInstTypeList()) > 0 {
- noder.BuildInstantiations(false)
- }
}
noder.MakeWrappers(typecheck.Target) // must happen after inlining
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index dcb5404..74e4c0a 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -217,6 +217,10 @@
if ir.ConstOverflow(v, t) {
return
}
+ } else {
+ // If the type of the constant is an instantiated generic, we need to emit
+ // that type so the linker knows about it. See issue 51245.
+ _ = reflectdata.TypeLinksym(t)
}
base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, types.TypeSymName(t), ir.IntVal(t, v))
}
@@ -263,6 +267,10 @@
objw.Global(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
x.Set(obj.AttrStatic, true)
}
+ if x := fn.WrapInfo; x != nil && !x.OnList() {
+ objw.Global(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
+ x.Set(obj.AttrStatic, true)
+ }
}
}
diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go
index 7c51d3b..bed4fbb 100644
--- a/src/cmd/compile/internal/importer/iimport.go
+++ b/src/cmd/compile/internal/importer/iimport.go
@@ -9,6 +9,7 @@
import (
"cmd/compile/internal/syntax"
+ "cmd/compile/internal/typecheck"
"cmd/compile/internal/types2"
"encoding/binary"
"fmt"
@@ -126,7 +127,7 @@
typCache: make(map[uint64]types2.Type),
// Separate map for typeparams, keyed by their package and unique
// name (name with subscript).
- tparamIndex: make(map[ident]types2.Type),
+ tparamIndex: make(map[ident]*types2.TypeParam),
}
for i, pt := range predeclared {
@@ -179,6 +180,14 @@
p.doDecl(localpkg, name)
}
+ // SetConstraint can't be called if the constraint type is not yet complete.
+ // When type params are created in the 'P' case of (*importReader).obj(),
+ // the associated constraint type may not be complete due to recursion.
+ // Therefore, we defer calling SetConstraint there, and call it here instead
+ // after all types are complete.
+ for _, d := range p.later {
+ d.t.SetConstraint(d.constraint)
+ }
// record all referenced packages as imports
list := append(([]*types2.Package)(nil), pkgList[1:]...)
sort.Sort(byPath(list))
@@ -190,6 +199,11 @@
return localpkg, nil
}
+type setConstraintArgs struct {
+ t *types2.TypeParam
+ constraint types2.Type
+}
+
type iimporter struct {
exportVersion int64
ipath string
@@ -202,9 +216,12 @@
declData string
pkgIndex map[*types2.Package]map[string]uint64
typCache map[uint64]types2.Type
- tparamIndex map[ident]types2.Type
+ tparamIndex map[ident]*types2.TypeParam
interfaceList []*types2.Interface
+
+ // Arguments for calls to SetConstraint that are deferred due to recursive types
+ later []setConstraintArgs
}
func (p *iimporter) doDecl(pkg *types2.Package, name string) {
@@ -376,12 +393,12 @@
if r.p.exportVersion < iexportVersionGenerics {
errorf("unexpected type param type")
}
- // Remove the "path" from the type param name that makes it unique
- ix := strings.LastIndex(name, ".")
- if ix < 0 {
- errorf("missing path for type param")
+ name0 := typecheck.TparamName(name)
+ if name0 == "" {
+ errorf("malformed type parameter export name %s: missing prefix", name)
}
- tn := types2.NewTypeName(pos, r.currPkg, name[ix+1:], nil)
+
+ tn := types2.NewTypeName(pos, r.currPkg, name0, nil)
t := types2.NewTypeParam(tn, nil)
// To handle recursive references to the typeparam within its
// bound, save the partial type in tparamIndex before reading the bounds.
@@ -400,7 +417,11 @@
}
iface.MarkImplicit()
}
- t.SetConstraint(constraint)
+ // The constraint type may not be complete, if we
+ // are in the middle of a type recursion involving type
+ // constraints. So, we defer SetConstraint until we have
+ // completely set up all types in ImportData.
+ r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
case 'V':
typ := r.typ()
diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go
index f526d98..68303c0 100644
--- a/src/cmd/compile/internal/ir/expr.go
+++ b/src/cmd/compile/internal/ir/expr.go
@@ -250,7 +250,8 @@
// It may end up being a value or a type.
type ConvExpr struct {
miniExpr
- X Node
+ X Node
+ NonEscaping bool // The allocation needed for the conversion to interface is known not to escape
}
func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr {
diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go
index 41c9607..23d56f7 100644
--- a/src/cmd/compile/internal/ir/func.go
+++ b/src/cmd/compile/internal/ir/func.go
@@ -133,6 +133,10 @@
// function for go:nowritebarrierrec analysis. Only filled in
// if nowritebarrierrecCheck != nil.
NWBRCalls *[]SymAndPos
+
+ // For wrapper functions, WrappedFunc point to the original Func.
+ // Currently only used for go/defer wrappers.
+ WrappedFunc *Func
}
func NewFunc(pos src.XPos) *Func {
diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go
index 4fdee50..5fdccf8 100644
--- a/src/cmd/compile/internal/ir/node.go
+++ b/src/cmd/compile/internal/ir/node.go
@@ -471,7 +471,7 @@
UintptrEscapes // pointers converted to uintptr escape
// Runtime-only func pragmas.
- // See ../../../../runtime/README.md for detailed descriptions.
+ // See ../../../../runtime/HACKING.md for detailed descriptions.
Systemstack // func must run on system stack
Nowritebarrier // emit compiler error instead of write barrier
Nowritebarrierrec // error on write barrier in this or recursive callees
diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go
index a4421fc..72b6320 100644
--- a/src/cmd/compile/internal/ir/sizeof_test.go
+++ b/src/cmd/compile/internal/ir/sizeof_test.go
@@ -20,7 +20,7 @@
_32bit uintptr // size on 32bit platforms
_64bit uintptr // size on 64bit platforms
}{
- {Func{}, 192, 328},
+ {Func{}, 196, 336},
{Name{}, 112, 200},
}
diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go
index e7d0d87..80bd205 100644
--- a/src/cmd/compile/internal/ir/stmt.go
+++ b/src/cmd/compile/internal/ir/stmt.go
@@ -362,7 +362,7 @@
return n
}
-// A SwitchStmt is a switch statement: switch Init; Expr { Cases }.
+// A SwitchStmt is a switch statement: switch Init; Tag { Cases }.
type SwitchStmt struct {
miniStmt
Tag Node
diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go
index 990b978..6e12c6c 100644
--- a/src/cmd/compile/internal/mips64/ssa.go
+++ b/src/cmd/compile/internal/mips64/ssa.go
@@ -320,7 +320,10 @@
for a.Op == ssa.OpCopy || a.Op == ssa.OpMIPS64MOVVreg {
a = a.Args[0]
}
- if a.Op == ssa.OpLoadReg {
+ if a.Op == ssa.OpLoadReg && mips.REG_R0 <= a.Reg() && a.Reg() <= mips.REG_R31 {
+ // LoadReg from a narrower type does an extension, except loading
+ // to a floating point register. So only eliminate the extension
+ // if it is loaded to an integer register.
t := a.Type
switch {
case v.Op == ssa.OpMIPS64MOVBreg && t.Size() == 1 && t.IsSigned(),
diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go
index df1ca1c..a9522d0 100644
--- a/src/cmd/compile/internal/noder/decl.go
+++ b/src/cmd/compile/internal/noder/decl.go
@@ -133,12 +133,20 @@
g.target.Inits = append(g.target.Inits, fn)
}
- haveEmbed := g.haveEmbed
+ saveHaveEmbed := g.haveEmbed
+ saveCurDecl := g.curDecl
g.curDecl = ""
g.later(func() {
- defer func(b bool) { g.haveEmbed = b }(g.haveEmbed)
+ defer func(b bool, s string) {
+ // Revert haveEmbed and curDecl back to what they were before
+ // the "later" function.
+ g.haveEmbed = b
+ g.curDecl = s
+ }(g.haveEmbed, g.curDecl)
- g.haveEmbed = haveEmbed
+ // Set haveEmbed and curDecl to what they were for this funcDecl.
+ g.haveEmbed = saveHaveEmbed
+ g.curDecl = saveCurDecl
if fn.Type().HasTParam() {
g.topFuncIsGeneric = true
}
@@ -162,9 +170,10 @@
func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
// Set the position for any error messages we might print (e.g. too large types).
base.Pos = g.pos(decl)
- assert(g.curDecl == "")
+ assert(ir.CurFunc != nil || g.curDecl == "")
// Set g.curDecl to the type name, as context for the type params declared
// during types2-to-types1 translation if this is a generic type.
+ saveCurDecl := g.curDecl
g.curDecl = decl.Name.Value
if decl.Alias {
name, _ := g.def(decl.Name)
@@ -225,7 +234,7 @@
}
types.ResumeCheckSize()
- g.curDecl = ""
+ g.curDecl = saveCurDecl
if otyp, ok := otyp.(*types2.Named); ok && otyp.NumMethods() != 0 {
methods := make([]*types.Field, otyp.NumMethods())
for i := range methods {
diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go
index 6891d1e..4b5ae70 100644
--- a/src/cmd/compile/internal/noder/expr.go
+++ b/src/cmd/compile/internal/noder/expr.go
@@ -114,7 +114,7 @@
case *syntax.CallExpr:
fun := g.expr(expr.Fun)
- return Call(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots)
+ return g.callExpr(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots)
case *syntax.IndexExpr:
args := unpackListExpr(expr.Index)
@@ -206,6 +206,53 @@
return newt
}
+// callExpr creates a call expression (which might be a type conversion, built-in
+// call, or a regular call) and does standard transforms, unless we are in a generic
+// function.
+func (g *irgen) callExpr(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node {
+ n := ir.NewCallExpr(pos, ir.OCALL, fun, args)
+ n.IsDDD = dots
+ typed(typ, n)
+
+ if fun.Op() == ir.OTYPE {
+ // Actually a type conversion, not a function call.
+ if !g.delayTransform() {
+ return transformConvCall(n)
+ }
+ return n
+ }
+
+ if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 {
+ if !g.delayTransform() {
+ return transformBuiltin(n)
+ }
+ return n
+ }
+
+ // Add information, now that we know that fun is actually being called.
+ switch fun := fun.(type) {
+ case *ir.SelectorExpr:
+ if fun.Op() == ir.OMETHVALUE {
+ op := ir.ODOTMETH
+ if fun.X.Type().IsInterface() {
+ op = ir.ODOTINTER
+ }
+ fun.SetOp(op)
+ // Set the type to include the receiver, since that's what
+ // later parts of the compiler expect
+ fun.SetType(fun.Selection.Type)
+ }
+ }
+
+ // A function instantiation (even if fully concrete) shouldn't be
+ // transformed yet, because we need to add the dictionary during the
+ // transformation.
+ if fun.Op() != ir.OFUNCINST && !g.delayTransform() {
+ transformCall(n)
+ }
+ return n
+}
+
// selectorExpr resolves the choice of ODOT, ODOTPTR, OMETHVALUE (eventually
// ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather
// than in typecheck.go.
@@ -332,13 +379,13 @@
}
func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
- if ptr, ok := typ.Underlying().(*types2.Pointer); ok {
+ if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
n := ir.NewAddrExpr(g.pos(lit), g.compLit(ptr.Elem(), lit))
n.SetOp(ir.OPTRLIT)
return typed(g.typ(typ), n)
}
- _, isStruct := types2.StructuralType(typ).(*types2.Struct)
+ _, isStruct := types2.CoreType(typ).(*types2.Struct)
exprs := make([]ir.Node, len(lit.ElemList))
for i, elem := range lit.ElemList {
diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go
index 5524673..33acd60 100644
--- a/src/cmd/compile/internal/noder/helpers.go
+++ b/src/cmd/compile/internal/noder/helpers.go
@@ -98,95 +98,6 @@
}
}
-func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node {
- n := ir.NewCallExpr(pos, ir.OCALL, fun, args)
- n.IsDDD = dots
-
- if fun.Op() == ir.OTYPE {
- // Actually a type conversion, not a function call.
- if !fun.Type().IsInterface() &&
- (fun.Type().HasTParam() || args[0].Type().HasTParam()) {
- // For type params, we can transform if fun.Type() is known
- // to be an interface (in which case a CONVIFACE node will be
- // inserted). Otherwise, don't typecheck until we actually
- // know the type.
- return typed(typ, n)
- }
- typed(typ, n)
- return transformConvCall(n)
- }
-
- if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 {
- // For most Builtin ops, we delay doing transformBuiltin if any of the
- // args have type params, for a variety of reasons:
- //
- // OMAKE: transformMake can't choose specific ops OMAKESLICE, etc.
- // until arg type is known
- // OREAL/OIMAG: transformRealImag can't determine type float32/float64
- // until arg type known
- // OAPPEND: transformAppend requires that the arg is a slice
- // ODELETE: transformDelete requires that the arg is a map
- // OALIGNOF, OSIZEOF: can be eval'ed to a constant until types known.
- switch fun.BuiltinOp {
- case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
- hasTParam := false
- for _, arg := range args {
- if fun.BuiltinOp == ir.OOFFSETOF {
- // It's the type of left operand of the
- // selection that matters, not the type of
- // the field itself (which is irrelevant for
- // offsetof).
- arg = arg.(*ir.SelectorExpr).X
- }
- if arg.Type().HasTParam() {
- hasTParam = true
- break
- }
- }
- if hasTParam {
- return typed(typ, n)
- }
- }
-
- typed(typ, n)
- return transformBuiltin(n)
- }
-
- // Add information, now that we know that fun is actually being called.
- switch fun := fun.(type) {
- case *ir.SelectorExpr:
- if fun.Op() == ir.OMETHVALUE {
- op := ir.ODOTMETH
- if fun.X.Type().IsInterface() {
- op = ir.ODOTINTER
- }
- fun.SetOp(op)
- // Set the type to include the receiver, since that's what
- // later parts of the compiler expect
- fun.SetType(fun.Selection.Type)
- }
- }
-
- if fun.Type().HasTParam() || fun.Op() == ir.OXDOT || fun.Op() == ir.OFUNCINST {
- // If the fun arg is or has a type param, we can't do all the
- // transformations, since we may not have needed properties yet
- // (e.g. number of return values, etc). The same applies if a fun
- // which is an XDOT could not be transformed yet because of a generic
- // type in the X of the selector expression.
- //
- // A function instantiation (even if fully concrete) shouldn't be
- // transformed yet, because we need to add the dictionary during the
- // transformation.
- return typed(typ, n)
- }
-
- // If no type params, do the normal call transformations. This
- // will convert OCALL to OCALLFUNC.
- typed(typ, n)
- transformCall(n)
- return n
-}
-
func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) *ir.BinaryExpr {
n := ir.NewBinaryExpr(pos, op, x, y)
typed(typ, n)
diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go
index e20939d..52224c4 100644
--- a/src/cmd/compile/internal/noder/irgen.go
+++ b/src/cmd/compile/internal/noder/irgen.go
@@ -96,6 +96,17 @@
}
}
+// Information about sub-dictionary entries in a dictionary
+type subDictInfo struct {
+ // Call or XDOT node that requires a dictionary.
+ callNode ir.Node
+ // Saved CallExpr.X node (*ir.SelectorExpr or *InstExpr node) for a generic
+ // method or function call, since this node will get dropped when the generic
+ // method/function call is transformed to a call on the instantiated shape
+ // function. Nil for other kinds of calls or XDOTs.
+ savedXNode ir.Node
+}
+
// dictInfo is the dictionary format for an instantiation of a generic function with
// particular shapes. shapeParams, derivedTypes, subDictCalls, and itabConvs describe
// the actual dictionary entries in order, and the remaining fields are other info
@@ -108,7 +119,7 @@
// Nodes in the instantiation that requires a subdictionary. Includes
// method and function calls (OCALL), function values (OFUNCINST), method
// values/expressions (OXDOT).
- subDictCalls []ir.Node
+ subDictCalls []subDictInfo
// Nodes in the instantiation that are a conversion from a typeparam/derived
// type to a specific interface.
itabConvs []ir.Node
@@ -317,7 +328,7 @@
// Create any needed instantiations of generic functions and transform
// existing and new functions to use those instantiations.
- BuildInstantiations(true)
+ BuildInstantiations()
// Remove all generic functions from g.target.Decl, since they have been
// used for stenciling, but don't compile. Generic functions will already
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 0bc9135..5d17c53 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -2029,7 +2029,7 @@
// Quirk: If deadcode elimination turned a non-empty function into
// an empty one, we need to set the position for the empty block
- // left behind to the the inlined position for src.NoXPos, so that
+ // left behind to the inlined position for src.NoXPos, so that
// an empty string gets added into the DWARF file name listing at
// the appropriate index.
if quirksMode() && len(body) == 1 {
diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go
index 9396c0c..c028d21 100644
--- a/src/cmd/compile/internal/noder/reader2.go
+++ b/src/cmd/compile/internal/noder/reader2.go
@@ -250,7 +250,7 @@
case typePointer:
return types2.NewPointer(r.typ())
case typeSignature:
- return r.signature(nil)
+ return r.signature(nil, nil, nil)
case typeSlice:
return types2.NewSlice(r.typ())
case typeStruct:
@@ -298,7 +298,7 @@
for i := range methods {
pos := r.pos()
pkg, name := r.selector()
- mtyp := r.signature(nil)
+ mtyp := r.signature(nil, nil, nil)
methods[i] = types2.NewFunc(pos, pkg, name, mtyp)
}
@@ -309,14 +309,14 @@
return types2.NewInterfaceType(methods, embeddeds)
}
-func (r *reader2) signature(recv *types2.Var) *types2.Signature {
+func (r *reader2) signature(recv *types2.Var, rtparams, tparams []*types2.TypeParam) *types2.Signature {
r.sync(syncSignature)
params := r.params()
results := r.params()
variadic := r.bool()
- return types2.NewSignatureType(recv, nil, nil, params, results, variadic)
+ return types2.NewSignatureType(recv, rtparams, tparams, params, results, variadic)
}
func (r *reader2) params() *types2.Tuple {
@@ -393,8 +393,7 @@
case objFunc:
pos := r.pos()
tparams := r.typeParamNames()
- sig := r.signature(nil)
- sig.SetTypeParams(tparams)
+ sig := r.signature(nil, nil, tparams)
return types2.NewFunc(pos, objPkg, objName, sig)
case objType:
@@ -490,9 +489,8 @@
pos := r.pos()
pkg, name := r.selector()
- rparams := r.typeParamNames()
- sig := r.signature(r.param())
- sig.SetRecvTypeParams(rparams)
+ rtparams := r.typeParamNames()
+ sig := r.signature(r.param(), rtparams, nil)
_ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go.
return types2.NewFunc(pos, pkg, name, sig)
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index 62c306b..cd586ca 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -9,7 +9,6 @@
import (
"cmd/compile/internal/base"
- "cmd/compile/internal/inline"
"cmd/compile/internal/ir"
"cmd/compile/internal/objw"
"cmd/compile/internal/reflectdata"
@@ -40,34 +39,29 @@
var geninst genInst
-func BuildInstantiations(preinliningMainScan bool) {
- if geninst.instInfoMap == nil {
- geninst.instInfoMap = make(map[*types.Sym]*instInfo)
- }
- geninst.buildInstantiations(preinliningMainScan)
+func BuildInstantiations() {
+ geninst.instInfoMap = make(map[*types.Sym]*instInfo)
+ geninst.buildInstantiations()
+ geninst.instInfoMap = nil
}
// buildInstantiations scans functions for generic function calls and methods, and
// creates the required instantiations. It also creates instantiated methods for all
// fully-instantiated generic types that have been encountered already or new ones
-// that are encountered during the instantiation process. If preinliningMainScan is
-// true, it scans all declarations in typecheck.Target.Decls first, before scanning
-// any new instantiations created. If preinliningMainScan is false, we do not scan
-// any existing decls - we only scan method instantiations for any new
-// fully-instantiated types that we saw during inlining.
-func (g *genInst) buildInstantiations(preinliningMainScan bool) {
+// that are encountered during the instantiation process. It scans all declarations
+// in typecheck.Target.Decls first, before scanning any new instantiations created.
+func (g *genInst) buildInstantiations() {
// Instantiate the methods of instantiated generic types that we have seen so far.
g.instantiateMethods()
- if preinliningMainScan {
- n := len(typecheck.Target.Decls)
- for i := 0; i < n; i++ {
- g.scanForGenCalls(typecheck.Target.Decls[i])
- }
+ // Scan all currentdecls for call to generic functions/methods.
+ n := len(typecheck.Target.Decls)
+ for i := 0; i < n; i++ {
+ g.scanForGenCalls(typecheck.Target.Decls[i])
}
// Scan all new instantiations created due to g.instantiateMethods() and the
- // scan of current decls (if done). This loop purposely runs until no new
+ // scan of current decls. This loop purposely runs until no new
// instantiations are created.
for i := 0; i < len(g.newInsts); i++ {
g.scanForGenCalls(g.newInsts[i])
@@ -82,10 +76,6 @@
for _, fun := range g.newInsts {
info := g.instInfoMap[fun.Sym()]
g.dictPass(info)
- if !preinliningMainScan {
- // Prepare for the round of inlining below.
- inline.CanInline(fun.(*ir.Func))
- }
if doubleCheck {
ir.Visit(info.fun, func(n ir.Node) {
if n.Op() != ir.OCONVIFACE {
@@ -103,21 +93,6 @@
ir.Dump(fmt.Sprintf("\ndictpass %v", info.fun), info.fun)
}
}
- if !preinliningMainScan {
- // Extra round of inlining for the new instantiations (only if
- // preinliningMainScan is false, which means we have already done the
- // main round of inlining)
- for _, fun := range g.newInsts {
- inline.InlineCalls(fun.(*ir.Func))
- // New instantiations created during inlining should run
- // ComputeAddrTaken directly, since we are past the main pass
- // that did ComputeAddrTaken(). We could instead do this
- // incrementally during stenciling (for all instantiations,
- // including main ones before inlining), since we have the
- // type information.
- typecheck.ComputeAddrtaken(fun.(*ir.Func).Body)
- }
- }
assert(l == len(g.newInsts))
g.newInsts = nil
}
@@ -435,7 +410,8 @@
fn, formalParams, formalResults := startClosure(pos, outer, typ)
// This is the dictionary we want to use.
- // It may be a constant, or it may be a dictionary acquired from the outer function's dictionary.
+ // It may be a constant, it may be the outer functions's dictionary, or it may be
+ // a subdictionary acquired from the outer function's dictionary.
// For the latter, dictVar is a variable in the outer function's scope, set to the subdictionary
// read from the outer function's dictionary.
var dictVar *ir.Name
@@ -609,7 +585,7 @@
if declInfo != nil {
entry := -1
for i, de := range declInfo.dictInfo.subDictCalls {
- if n == de {
+ if n == de.callNode {
entry = declInfo.dictInfo.startSubDict + i
break
}
@@ -659,17 +635,41 @@
checkFetchBody(nameNode)
}
+ var tparams []*types.Type
+ if isMeth {
+ // Get the type params from the method receiver (after skipping
+ // over any pointer)
+ recvType := nameNode.Type().Recv().Type
+ recvType = deref(recvType)
+ if recvType.IsFullyInstantiated() {
+ // Get the type of the base generic type, so we get
+ // its original typeparams.
+ recvType = recvType.OrigSym().Def.(*ir.Name).Type()
+ }
+ tparams = recvType.RParams()
+ } else {
+ fields := nameNode.Type().TParams().Fields().Slice()
+ tparams = make([]*types.Type, len(fields))
+ for i, f := range fields {
+ tparams[i] = f.Type
+ }
+ }
+
// Convert any non-shape type arguments to their shape, so we can reduce the
// number of instantiations we have to generate. You can actually have a mix
// of shape and non-shape arguments, because of inferred or explicitly
// specified concrete type args.
s1 := make([]*types.Type, len(shapes))
for i, t := range shapes {
+ var tparam *types.Type
+ // Shapes are grouped differently for structural types, so we
+ // pass the type param to Shapify(), so we can distinguish.
+ tparam = tparams[i]
if !t.IsShape() {
- s1[i] = typecheck.Shapify(t, i)
+ s1[i] = typecheck.Shapify(t, i, tparam)
} else {
// Already a shape, but make sure it has the correct index.
- s1[i] = typecheck.Shapify(shapes[i].Underlying(), i)
+ s1[i] = typecheck.Shapify(shapes[i].Underlying(), i, tparam)
}
}
shapes = s1
@@ -700,7 +700,7 @@
}
// genericSubst fills in info.dictParam and info.shapeToBound.
- st := g.genericSubst(sym, nameNode, shapes, isMeth, info)
+ st := g.genericSubst(sym, nameNode, tparams, shapes, isMeth, info)
info.fun = st
g.instInfoMap[sym] = info
@@ -738,21 +738,7 @@
// function type where the receiver becomes the first parameter. For either a generic
// method or function, a dictionary parameter is the added as the very first
// parameter. genericSubst fills in info.dictParam and info.shapeToBound.
-func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func {
- var tparams []*types.Type
- if isMethod {
- // Get the type params from the method receiver (after skipping
- // over any pointer)
- recvType := nameNode.Type().Recv().Type
- recvType = deref(recvType)
- tparams = recvType.RParams()
- } else {
- fields := nameNode.Type().TParams().Fields().Slice()
- tparams = make([]*types.Type, len(fields))
- for i, f := range fields {
- tparams[i] = f.Type
- }
- }
+func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, tparams []*types.Type, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func {
gf := nameNode.Func
// Pos of the instantiated function is same as the generic function
newf := ir.NewFunc(gf.Pos())
@@ -1054,13 +1040,13 @@
}
case ir.OXDOT:
- // Finish the transformation of an OXDOT, unless this was a
- // bound call (a direct call on a type param). A bound call
- // will be transformed during the dictPass. Otherwise, m
- // will be transformed to an OMETHVALUE node. It will be
- // transformed to an ODOTMETH or ODOTINTER node if we find in
- // the OCALL case below that the method value is actually
- // called.
+ // Finish the transformation of an OXDOT, unless this is
+ // bound call or field access on a type param. A bound call
+ // or field access on a type param will be transformed during
+ // the dictPass. Otherwise, m will be transformed to an
+ // OMETHVALUE node. It will be transformed to an ODOTMETH or
+ // ODOTINTER node if we find in the OCALL case below that the
+ // method value is actually called.
mse := m.(*ir.SelectorExpr)
if src := mse.X.Type(); !src.IsShape() {
transformDot(mse, false)
@@ -1073,8 +1059,6 @@
// Transform the conversion, now that we know the
// type argument.
m = transformConvCall(call)
- // CONVIFACE transformation was already done in noder2
- assert(m.Op() != ir.OCONVIFACE)
case ir.OMETHVALUE, ir.OMETHEXPR:
// Redo the transformation of OXDOT, now that we
@@ -1094,14 +1078,7 @@
case ir.ONAME:
name := call.X.Name()
if name.BuiltinOp != ir.OXXX {
- switch name.BuiltinOp {
- case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
- // Transform these builtins now that we
- // know the type of the args.
- m = transformBuiltin(call)
- default:
- base.FatalfAt(call.Pos(), "Unexpected builtin op")
- }
+ m = transformBuiltin(call)
} else {
// This is the case of a function value that was a
// type parameter (implied to be a function via a
@@ -1119,10 +1096,11 @@
transformEarlyCall(call)
case ir.OXDOT:
- // This is the case of a bound call on a typeparam,
- // which will be handled in the dictPass.
- // As with OFUNCINST, we must transform the arguments of the call now,
- // so any needed CONVIFACE nodes are exposed.
+ // This is the case of a bound call or a field access
+ // on a typeparam, which will be handled in the
+ // dictPass. As with OFUNCINST, we must transform the
+ // arguments of the call now, so any needed CONVIFACE
+ // nodes are exposed.
transformEarlyCall(call)
case ir.ODOTTYPE, ir.ODOTTYPE2:
@@ -1171,6 +1149,7 @@
newfn.Dcl = append(newfn.Dcl, ldict)
as := ir.NewAssignStmt(x.Pos(), ldict, cdict)
as.SetTypecheck(1)
+ ldict.Defn = as
newfn.Body.Append(as)
// Create inst info for the instantiated closure. The dict
@@ -1200,6 +1179,26 @@
subst.g.newInsts = append(subst.g.newInsts, m.(*ir.ClosureExpr).Func)
m.(*ir.ClosureExpr).SetInit(subst.list(x.Init()))
+ case ir.OSWITCH:
+ m := m.(*ir.SwitchStmt)
+ if m.Tag != nil && m.Tag.Op() == ir.OTYPESW {
+ break // Nothing to do here for type switches.
+ }
+ if m.Tag != nil && !m.Tag.Type().IsInterface() && m.Tag.Type().HasShape() {
+ // To implement a switch on a value that is or has a type parameter, we first convert
+ // that thing we're switching on to an interface{}.
+ m.Tag = assignconvfn(m.Tag, types.Types[types.TINTER])
+ }
+ for _, c := range m.Cases {
+ for i, x := range c.List {
+ // If we have a case that is or has a type parameter, convert that case
+ // to an interface{}.
+ if !x.Type().IsInterface() && x.Type().HasShape() {
+ c.List[i] = assignconvfn(x, types.Types[types.TINTER])
+ }
+ }
+ }
+
}
return m
}
@@ -1233,27 +1232,40 @@
ir.CurFunc = info.fun
case ir.OXDOT:
+ // This is the case of a dot access on a type param. This is
+ // typically a bound call on the type param, but could be a
+ // field access, if the constraint has a single structural type.
mse := m.(*ir.SelectorExpr)
src := mse.X.Type()
assert(src.IsShape())
- // The only dot on a shape type value are methods.
if mse.X.Op() == ir.OTYPE {
// Method expression T.M
m = g.buildClosure2(info, m)
// No need for transformDot - buildClosure2 has already
// transformed to OCALLINTER/ODOTINTER.
} else {
- // Implement x.M as a conversion-to-bound-interface
- // 1) convert x to the bound interface
- // 2) call M on that interface
- dst := info.dictInfo.shapeToBound[m.(*ir.SelectorExpr).X.Type()]
- if src.IsInterface() {
- // If type arg is an interface (unusual case),
- // we do a type assert to the type bound.
- mse.X = assertToBound(info, info.dictParam, m.Pos(), mse.X, dst)
- } else {
- mse.X = convertUsingDictionary(info, info.dictParam, m.Pos(), mse.X, m, dst)
+ // If we can't find the selected method in the
+ // AllMethods of the bound, then this must be an access
+ // to a field of a structural type. If so, we skip the
+ // dictionary lookups - transformDot() will convert to
+ // the desired direct field access.
+ if isBoundMethod(info.dictInfo, mse) {
+ dst := info.dictInfo.shapeToBound[mse.X.Type()]
+ // Implement x.M as a conversion-to-bound-interface
+ // 1) convert x to the bound interface
+ // 2) call M on that interface
+ if src.IsInterface() {
+ // If type arg is an interface (unusual case),
+ // we do a type assert to the type bound.
+ mse.X = assertToBound(info, info.dictParam, m.Pos(), mse.X, dst)
+ } else {
+ mse.X = convertUsingDictionary(info, info.dictParam, m.Pos(), mse.X, m, dst, true)
+ // Note: we set nonEscaping==true, because we can assume the backing store for the
+ // interface conversion doesn't escape. The method call will immediately go to
+ // a wrapper function which copies all the data out of the interface value.
+ // (It only matters for non-pointer-shaped interface conversions. See issue 50182.)
+ }
}
transformDot(mse, false)
}
@@ -1279,7 +1291,7 @@
// Note: x's argument is still typed as a type parameter.
// m's argument now has an instantiated type.
if mce.X.Type().HasShape() || (mce.X.Type().IsInterface() && m.Type().HasShape()) {
- m = convertUsingDictionary(info, info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, m, m.Type())
+ m = convertUsingDictionary(info, info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, m, m.Type(), false)
}
case ir.ODOTTYPE, ir.ODOTTYPE2:
if !m.Type().HasShape() {
@@ -1372,7 +1384,9 @@
// type dst, by returning a new set of nodes that make use of a dictionary entry. in is the
// instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the
// conversion.
-func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node {
+// If nonEscaping is true, the caller guarantees that the backing store needed for the interface data
+// word will not escape.
+func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type, nonEscaping bool) ir.Node {
assert(v.Type().HasShape() || v.Type().IsInterface() && in.Type().HasShape())
assert(dst.IsInterface())
@@ -1442,6 +1456,7 @@
// Figure out what the data field of the interface will be.
data := ir.NewConvExpr(pos, ir.OCONVIDATA, nil, v)
typed(types.Types[types.TUNSAFEPTR], data)
+ data.NonEscaping = nonEscaping
// Build an interface from the type and data parts.
var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data)
@@ -1570,8 +1585,9 @@
markTypeUsed(ts, lsym)
}
// Emit an entry for each subdictionary (after substituting targs)
- for _, n := range info.subDictCalls {
+ for _, subDictInfo := range info.subDictCalls {
var sym *types.Sym
+ n := subDictInfo.callNode
switch n.Op() {
case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH:
call := n.(*ir.CallExpr)
@@ -1618,31 +1634,31 @@
} else {
// This is the case of a normal
// method call on a generic type.
- recvType := deref(call.X.(*ir.SelectorExpr).X.Type())
- genRecvType := recvType.OrigSym().Def.Type()
- nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
- subtargs := recvType.RParams()
- s2targs := make([]*types.Type, len(subtargs))
- for i, t := range subtargs {
- s2targs[i] = subst.Typ(t)
- }
- sym = g.getDictionarySym(nameNode, s2targs, true)
+ assert(subDictInfo.savedXNode == se)
+ sym = g.getSymForMethodCall(se, &subst)
}
} else {
- inst := call.X.(*ir.InstExpr)
- var nameNode *ir.Name
- var meth *ir.SelectorExpr
- var isMeth bool
- if meth, isMeth = inst.X.(*ir.SelectorExpr); isMeth {
- nameNode = meth.Selection.Nname.(*ir.Name)
+ inst, ok := call.X.(*ir.InstExpr)
+ if ok {
+ // Code hasn't been transformed yet
+ assert(subDictInfo.savedXNode == inst)
+ }
+ // If !ok, then the generic method/function call has
+ // already been transformed to a shape instantiation
+ // call. Either way, use the SelectorExpr/InstExpr
+ // node saved in info.
+ cex := subDictInfo.savedXNode
+ if se, ok := cex.(*ir.SelectorExpr); ok {
+ sym = g.getSymForMethodCall(se, &subst)
} else {
- nameNode = inst.X.(*ir.Name)
+ inst := cex.(*ir.InstExpr)
+ nameNode := inst.X.(*ir.Name)
+ subtargs := typecheck.TypesOf(inst.Targs)
+ for i, t := range subtargs {
+ subtargs[i] = subst.Typ(t)
+ }
+ sym = g.getDictionarySym(nameNode, subtargs, false)
}
- subtargs := typecheck.TypesOf(inst.Targs)
- for i, t := range subtargs {
- subtargs[i] = subst.Typ(t)
- }
- sym = g.getDictionarySym(nameNode, subtargs, isMeth)
}
case ir.OFUNCINST:
@@ -1655,16 +1671,7 @@
sym = g.getDictionarySym(nameNode, subtargs, false)
case ir.OXDOT, ir.OMETHEXPR, ir.OMETHVALUE:
- selExpr := n.(*ir.SelectorExpr)
- recvType := deref(selExpr.Selection.Type.Recv().Type)
- genRecvType := recvType.OrigSym().Def.Type()
- subtargs := recvType.RParams()
- s2targs := make([]*types.Type, len(subtargs))
- for i, t := range subtargs {
- s2targs[i] = subst.Typ(t)
- }
- nameNode := typecheck.Lookdot1(selExpr, selExpr.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
- sym = g.getDictionarySym(nameNode, s2targs, true)
+ sym = g.getSymForMethodCall(n.(*ir.SelectorExpr), &subst)
default:
assert(false)
@@ -1692,6 +1699,24 @@
return sym
}
+// getSymForMethodCall gets the dictionary sym for a method call, method value, or method
+// expression that has selector se. subst gives the substitution from shape types to
+// concrete types.
+func (g *genInst) getSymForMethodCall(se *ir.SelectorExpr, subst *typecheck.Tsubster) *types.Sym {
+ // For everything except method expressions, 'recvType = deref(se.X.Type)' would
+ // also give the receiver type. For method expressions with embedded types, we
+ // need to look at the type of the selection to get the final receiver type.
+ recvType := deref(se.Selection.Type.Recv().Type)
+ genRecvType := recvType.OrigSym().Def.Type()
+ nameNode := typecheck.Lookdot1(se, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
+ subtargs := recvType.RParams()
+ s2targs := make([]*types.Type, len(subtargs))
+ for i, t := range subtargs {
+ s2targs[i] = subst.Typ(t)
+ }
+ return g.getDictionarySym(nameNode, s2targs, true)
+}
+
// finalizeSyms finishes up all dictionaries on g.dictSymsToFinalize, by writing out
// any needed LSyms for itabs. The itab lsyms create wrappers which need various
// dictionaries and method instantiations to be complete, so, to avoid recursive
@@ -1839,7 +1864,7 @@
case ir.OFUNCINST:
if !callMap[n] && hasShapeNodes(n.(*ir.InstExpr).Targs) {
infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X)
- info.subDictCalls = append(info.subDictCalls, n)
+ info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
}
case ir.OMETHEXPR, ir.OMETHVALUE:
if !callMap[n] && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) &&
@@ -1850,7 +1875,7 @@
} else {
infoPrint(" Closure&subdictionary required at generic meth value %v\n", n)
}
- info.subDictCalls = append(info.subDictCalls, n)
+ info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
}
case ir.OCALL:
ce := n.(*ir.CallExpr)
@@ -1858,14 +1883,22 @@
callMap[ce.X] = true
if hasShapeNodes(ce.X.(*ir.InstExpr).Targs) {
infoPrint(" Subdictionary at generic function/method call: %v - %v\n", ce.X.(*ir.InstExpr).X, n)
- info.subDictCalls = append(info.subDictCalls, n)
+ // Save the instExpr node for the function call,
+ // since we will lose this information when the
+ // generic function call is transformed to a call
+ // on the shape instantiation.
+ info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: ce.X})
}
}
- if ce.X.Op() == ir.OXDOT &&
- isShapeDeref(ce.X.(*ir.SelectorExpr).X.Type()) {
+ // Note: this XDOT code is not actually needed as long as we
+ // continue to disable type parameters on RHS of type
+ // declarations (#45639).
+ if ce.X.Op() == ir.OXDOT {
callMap[ce.X] = true
- infoPrint(" Optional subdictionary at generic bound call: %v\n", n)
- info.subDictCalls = append(info.subDictCalls, n)
+ if isBoundMethod(info, ce.X.(*ir.SelectorExpr)) {
+ infoPrint(" Optional subdictionary at generic bound call: %v\n", n)
+ info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: nil})
+ }
}
case ir.OCALLMETH:
ce := n.(*ir.CallExpr)
@@ -1874,7 +1907,11 @@
callMap[ce.X] = true
if hasShapeTypes(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) {
infoPrint(" Subdictionary at generic method call: %v\n", n)
- info.subDictCalls = append(info.subDictCalls, n)
+ // Save the selector for the method call, since we
+ // will eventually lose this information when the
+ // generic method call is transformed into a
+ // function call on the method shape instantiation.
+ info.subDictCalls = append(info.subDictCalls, subDictInfo{callNode: n, savedXNode: ce.X})
}
}
case ir.OCONVIFACE:
@@ -1884,7 +1921,8 @@
info.itabConvs = append(info.itabConvs, n)
}
case ir.OXDOT:
- if n.(*ir.SelectorExpr).X.Type().IsShape() {
+ se := n.(*ir.SelectorExpr)
+ if isBoundMethod(info, se) {
infoPrint(" Itab for bound call: %v\n", n)
info.itabConvs = append(info.itabConvs, n)
}
@@ -1940,11 +1978,13 @@
info.dictLen = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs)
}
-// isShapeDeref returns true if t is either a shape or a pointer to a shape. (We
-// can't just use deref(t).IsShape(), since a shape type is a complex type and may
-// have a pointer as part of its shape.)
-func isShapeDeref(t *types.Type) bool {
- return t.IsShape() || t.IsPtr() && t.Elem().IsShape()
+// isBoundMethod returns true if the selection indicated by se is a bound method of
+// se.X. se.X must be a shape type (i.e. substituted directly from a type param). If
+// isBoundMethod returns false, then the selection must be a field access of a
+// structural type.
+func isBoundMethod(info *dictInfo, se *ir.SelectorExpr) bool {
+ bound := info.shapeToBound[se.X.Type()]
+ return typecheck.Lookdot1(se, se.Sel, bound, bound.AllMethods(), 1) != nil
}
// addType adds t to info.derivedTypes if it is parameterized type (which is not
@@ -2154,7 +2194,7 @@
// the type bound.
rcvr = assertToBound(info, dictVar, pos, rcvr, dst)
} else {
- rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, m, dst)
+ rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, m, dst, false)
}
dot := ir.NewSelectorExpr(pos, ir.ODOTINTER, rcvr, m.(*ir.SelectorExpr).Sel)
dot.Selection = typecheck.Lookdot1(dot, dot.Sel, dot.X.Type(), dot.X.Type().AllMethods(), 1)
diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go
index 1e996b9..a349a7e 100644
--- a/src/cmd/compile/internal/noder/stmt.go
+++ b/src/cmd/compile/internal/noder/stmt.go
@@ -13,8 +13,10 @@
"cmd/internal/src"
)
+// stmts creates nodes for a slice of statements that form a scope.
func (g *irgen) stmts(stmts []syntax.Stmt) []ir.Node {
var nodes []ir.Node
+ types.Markdcl()
for _, stmt := range stmts {
switch s := g.stmt(stmt).(type) {
case nil: // EmptyStmt
@@ -24,6 +26,7 @@
nodes = append(nodes, s)
}
}
+ types.Popdcl()
return nodes
}
diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go
index a673484..db28e8d 100644
--- a/src/cmd/compile/internal/noder/transform.go
+++ b/src/cmd/compile/internal/noder/transform.go
@@ -115,6 +115,31 @@
if n.X.Op() == ir.OLITERAL {
return stringtoruneslit(n)
}
+
+ case ir.OBYTES2STR:
+ assert(t.IsSlice())
+ assert(t.Elem().Kind() == types.TUINT8)
+ if t.Elem() != types.ByteType && t.Elem() != types.Types[types.TUINT8] {
+ // If t is a slice of a user-defined byte type B (not uint8
+ // or byte), then add an extra CONVNOP from []B to []byte, so
+ // that the call to slicebytetostring() added in walk will
+ // typecheck correctly.
+ n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.ByteType), n.X)
+ n.X.SetTypecheck(1)
+ }
+
+ case ir.ORUNES2STR:
+ assert(t.IsSlice())
+ assert(t.Elem().Kind() == types.TINT32)
+ if t.Elem() != types.RuneType && t.Elem() != types.Types[types.TINT32] {
+ // If t is a slice of a user-defined rune type B (not uint32
+ // or rune), then add an extra CONVNOP from []B to []rune, so
+ // that the call to slicerunetostring() added in walk will
+ // typecheck correctly.
+ n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.RuneType), n.X)
+ n.X.SetTypecheck(1)
+ }
+
}
return n
}
@@ -217,7 +242,7 @@
aop, _ := typecheck.Assignop(rt, lt)
if aop != ir.OXXX {
types.CalcSize(rt)
- if rt.HasTParam() || rt.IsInterface() == lt.IsInterface() || rt.Size() >= 1<<16 {
+ if rt.HasShape() || rt.IsInterface() == lt.IsInterface() || rt.Size() >= 1<<16 {
r = ir.NewConvExpr(base.Pos, aop, lt, r)
r.SetTypecheck(1)
}
@@ -331,6 +356,37 @@
}
checkLHS(0, r.Type())
checkLHS(1, types.UntypedBool)
+ t := lhs[0].Type()
+ if t != nil && rhs[0].Type().HasShape() && t.IsInterface() && !types.IdenticalStrict(t, rhs[0].Type()) {
+ // This is a multi-value assignment (map, channel, or dot-type)
+ // where the main result is converted to an interface during the
+ // assignment. Normally, the needed CONVIFACE is not created
+ // until (*orderState).as2ok(), because the AS2* ops and their
+ // sub-ops are so tightly intertwined. But we need to create the
+ // CONVIFACE now to enable dictionary lookups. So, assign the
+ // results first to temps, so that we can manifest the CONVIFACE
+ // in assigning the first temp to lhs[0]. If we added the
+ // CONVIFACE into rhs[0] directly, we would break a lot of later
+ // code that depends on the tight coupling between the AS2* ops
+ // and their sub-ops. (Issue #50642).
+ v := typecheck.Temp(rhs[0].Type())
+ ok := typecheck.Temp(types.Types[types.TBOOL])
+ as := ir.NewAssignListStmt(base.Pos, stmt.Op(), []ir.Node{v, ok}, []ir.Node{r})
+ as.Def = true
+ as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, v))
+ as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, ok))
+ as.SetTypecheck(1)
+ // Change stmt to be a normal assignment of the temps to the final
+ // left-hand-sides. We re-create the original multi-value assignment
+ // so that it assigns to the temps and add it as an init of stmt.
+ //
+ // TODO: fix the order of evaluation, so that the lval of lhs[0]
+ // is evaluated before rhs[0] (similar to problem in #50672).
+ stmt.SetOp(ir.OAS2)
+ stmt.PtrInit().Append(as)
+ // assignconvfn inserts the CONVIFACE.
+ stmt.Rhs = []ir.Node{assignconvfn(v, t), ok}
+ }
return
}
diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go
index 4f6d828..e7ce4c1 100644
--- a/src/cmd/compile/internal/noder/types.go
+++ b/src/cmd/compile/internal/noder/types.go
@@ -113,6 +113,15 @@
// based on the names of the type arguments.
instName := g.instTypeName2(typ.Obj().Name(), typ.TypeArgs())
s := g.pkg(typ.Obj().Pkg()).Lookup(instName)
+
+ // Make sure the base generic type exists in type1 (it may
+ // not yet if we are referecing an imported generic type, as
+ // opposed to a generic type declared in this package). Make
+ // sure to do this lookup before checking s.Def, in case
+ // s.Def gets defined while importing base (if an imported
+ // type). (Issue #50486).
+ base := g.obj(typ.Origin().Obj())
+
if s.Def != nil {
// We have already encountered this instantiation.
// Use the type we previously created, since there
@@ -120,10 +129,13 @@
return s.Def.Type()
}
- // Make sure the base generic type exists in type1 (it may
- // not yet if we are referecing an imported generic type, as
- // opposed to a generic type declared in this package).
- _ = g.obj(typ.Origin().Obj())
+ if base.Class == ir.PAUTO {
+ // If the base type is a local type, we want to pop
+ // this instantiated type symbol/definition when we
+ // leave the containing block, so we don't use it
+ // incorrectly later.
+ types.Pushdcl(s)
+ }
// Create a forwarding type first and put it in the g.typs
// map, in order to deal with recursive generic types
@@ -227,10 +239,13 @@
// Save the name of the type parameter in the sym of the type.
// Include the types2 subscript in the sym name
pkg := g.tpkg(typ)
- // Create the unique types1 name for a type param, using its context with a
- // function, type, or method declaration.
+ // Create the unique types1 name for a type param, using its context
+ // with a function, type, or method declaration. Also, map blank type
+ // param names to a unique name based on their type param index. The
+ // unique blank names will be exported, but will be reverted during
+ // types2 and gcimporter import.
assert(g.curDecl != "")
- nm := g.curDecl + "." + typ.Obj().Name()
+ nm := typecheck.TparamExportName(g.curDecl, typ.Obj().Name(), typ.Index())
sym := pkg.Lookup(nm)
if sym.Def != nil {
// Make sure we use the same type param type for the same
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index 2bb0b4d..46e8339 100644
--- a/src/cmd/compile/internal/noder/writer.go
+++ b/src/cmd/compile/internal/noder/writer.go
@@ -1218,6 +1218,7 @@
}
obj := obj.(*types2.Var)
+ assert(!obj.IsField())
assert(targs.Len() == 0)
w.code(exprLocal)
@@ -1337,10 +1338,10 @@
w.typ(tv.Type)
typ := tv.Type
- if ptr, ok := typ.Underlying().(*types2.Pointer); ok {
+ if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
typ = ptr.Elem()
}
- str, isStruct := typ.Underlying().(*types2.Struct)
+ str, isStruct := types2.CoreType(typ).(*types2.Struct)
w.len(len(lit.ElemList))
for i, elem := range lit.ElemList {
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index b1e2902..a4ddb1a 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -1430,7 +1430,7 @@
type typeAndStr struct {
t *types.Type
- short string // "short" here means NameString
+ short string // "short" here means TypeSymName
regular string
}
@@ -1921,18 +1921,25 @@
// Target method uses shaped names.
targs2 := make([]*types.Type, len(targs))
+ origRParams := deref(orig).OrigSym().Def.(*ir.Name).Type().RParams()
for i, t := range targs {
- targs2[i] = typecheck.Shapify(t, i)
+ targs2[i] = typecheck.Shapify(t, i, origRParams[i])
}
targs = targs2
sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true)
if sym.Def == nil {
- // Currently we make sure that we have all the instantiations
- // we need by generating them all in ../noder/stencil.go:instantiateMethods
- // TODO: maybe there's a better, more incremental way to generate
- // only the instantiations we need?
- base.Fatalf("instantiation %s not found", sym.Name)
+ // Currently we make sure that we have all the
+ // instantiations we need by generating them all in
+ // ../noder/stencil.go:instantiateMethods
+ // Extra instantiations because of an inlined function
+ // should have been exported, and so available via
+ // Resolve.
+ in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
+ if in.Op() == ir.ONONAME {
+ base.Fatalf("instantiation %s not found", sym.Name)
+ }
+ sym = in.Sym()
}
target := ir.AsNode(sym.Def)
call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args)
@@ -2058,8 +2065,14 @@
sym := typecheck.MakeDictSym(gf, targs, true)
// Dictionary should already have been generated by instantiateMethods().
+ // Extra dictionaries needed because of an inlined function should have been
+ // exported, and so available via Resolve.
if lsym := sym.Linksym(); len(lsym.P) == 0 {
- base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name)
+ in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
+ if in.Op() == ir.ONONAME {
+ base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name)
+ }
+ sym = in.Sym()
}
// Make (or reuse) a node referencing the dictionary symbol.
diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules
index 2bc58a3..23f1132 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM.rules
@@ -1270,8 +1270,8 @@
(SRLconst (SLLconst x [c]) [d]) && buildcfg.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFXU [(d-c)|(32-d)<<8] x)
// comparison simplification
-((LT|LE|EQ|NE|GE|GT) (CMP x (RSBconst [0] y))) => ((LT|LE|EQ|NE|GE|GT) (CMN x y)) // sense of carry bit not preserved
-((LT|LE|EQ|NE|GE|GT) (CMN x (RSBconst [0] y))) => ((LT|LE|EQ|NE|GE|GT) (CMP x y)) // sense of carry bit not preserved
+((EQ|NE) (CMP x (RSBconst [0] y))) => ((EQ|NE) (CMN x y)) // sense of carry bit not preserved; see also #50854
+((EQ|NE) (CMN x (RSBconst [0] y))) => ((EQ|NE) (CMP x y)) // sense of carry bit not preserved; see also #50864
(EQ (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (EQ (CMP x y) yes no)
(EQ (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (EQ (CMP a (MUL <x.Type> x y)) yes no)
(EQ (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (EQ (CMPconst [c] x) yes no)
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules
index d34e189..be8be4e 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules
@@ -649,19 +649,13 @@
(GT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GTnoov (CMNW x y) yes no)
(GE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GEnoov (CMNW x y) yes no)
+// CMP(x,-y) -> CMN(x,y) is only valid for unordered comparison, if y can be -1<<63
(EQ (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMN x y) yes no)
(NE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMN x y) yes no)
-(LT (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (LT (CMN x y) yes no)
-(LE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (LE (CMN x y) yes no)
-(GT (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (GT (CMN x y) yes no)
-(GE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (GE (CMN x y) yes no)
+// CMPW(x,-y) -> CMNW(x,y) is only valid for unordered comparison, if y can be -1<<31
(EQ (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMNW x y) yes no)
(NE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMNW x y) yes no)
-(LT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (LT (CMNW x y) yes no)
-(LE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (LE (CMNW x y) yes no)
-(GT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (GT (CMNW x y) yes no)
-(GE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (GE (CMNW x y) yes no)
(EQ (CMPconst [0] x) yes no) => (Z x yes no)
(NE (CMPconst [0] x) yes no) => (NZ x yes no)
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
index e052ce0..2d03c44 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
@@ -285,9 +285,9 @@
{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to auxInt
{name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1, 32 bit
{name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt, 32 bit
- {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1
+ {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1, provided arg1 is not 1<<63
{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // arg0 compare to -auxInt
- {name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0 compare to -arg1, 32 bit
+ {name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0 compare to -arg1, 32 bit, provided arg1 is not 1<<31
{name: "CMNWconst", argLength: 1, reg: gp1flags, asm: "CMNW", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt, 32 bit
{name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0
{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int64", typ: "Flags"}, // arg0 & auxInt compare to 0
diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go
index 2f00420..3803f27 100644
--- a/src/cmd/compile/internal/ssa/gen/ARMOps.go
+++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go
@@ -331,7 +331,7 @@
// comparisons
{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt
- {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1
+ {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1, provided arg1 is not 1<<63
{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt
{name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0
{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0
diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules
index 3379e1d..96b24a6 100644
--- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules
+++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules
@@ -256,7 +256,7 @@
(Leq64F ...) => (FLED ...)
(Leq32F ...) => (FLES ...)
-(EqPtr x y) => (SEQZ (SUB <x.Type> x y))
+(EqPtr x y) => (SEQZ (SUB <typ.Uintptr> x y))
(Eq64 x y) => (SEQZ (SUB <x.Type> x y))
(Eq32 x y) => (SEQZ (SUB <x.Type> (ZeroExt32to64 x) (ZeroExt32to64 y)))
(Eq16 x y) => (SEQZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
@@ -264,7 +264,7 @@
(Eq64F ...) => (FEQD ...)
(Eq32F ...) => (FEQS ...)
-(NeqPtr x y) => (SNEZ (SUB <x.Type> x y))
+(NeqPtr x y) => (SNEZ (SUB <typ.Uintptr> x y))
(Neq64 x y) => (SNEZ (SUB <x.Type> x y))
(Neq32 x y) => (SNEZ (SUB <x.Type> (ZeroExt32to64 x) (ZeroExt32to64 y)))
(Neq16 x y) => (SNEZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
diff --git a/src/cmd/compile/internal/ssa/poset.go b/src/cmd/compile/internal/ssa/poset.go
index d2719eb..ee884ca 100644
--- a/src/cmd/compile/internal/ssa/poset.go
+++ b/src/cmd/compile/internal/ssa/poset.go
@@ -906,7 +906,7 @@
return i1 != i2 && po.reaches(i1, i2, true)
}
-// Ordered reports whether n1<=n2. It returns false either when it is
+// OrderedOrEqual reports whether n1<=n2. It returns false either when it is
// certain that n1<=n2 is false, or if there is not enough information
// to tell.
// Complexity is O(n).
diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go
index 496f9b4..1b50bf9 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM.go
@@ -17153,42 +17153,6 @@
b.resetWithControl(BlockARMLE, cmp)
return true
}
- // match: (GE (CMP x (RSBconst [0] y)))
- // result: (GE (CMN x y))
- for b.Controls[0].Op == OpARMCMP {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- v_0_1 := v_0.Args[1]
- if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
- break
- }
- y := v_0_1.Args[0]
- v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
- return true
- }
- // match: (GE (CMN x (RSBconst [0] y)))
- // result: (GE (CMP x y))
- for b.Controls[0].Op == OpARMCMN {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- v_0_0 := v_0.Args[0]
- v_0_1 := v_0.Args[1]
- for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
- x := v_0_0
- if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
- continue
- }
- y := v_0_1.Args[0]
- v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGE, v0)
- return true
- }
- break
- }
// match: (GE (CMPconst [0] l:(SUB x y)) yes no)
// cond: l.Uses==1
// result: (GEnoov (CMP x y) yes no)
@@ -18069,42 +18033,6 @@
b.resetWithControl(BlockARMLT, cmp)
return true
}
- // match: (GT (CMP x (RSBconst [0] y)))
- // result: (GT (CMN x y))
- for b.Controls[0].Op == OpARMCMP {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- v_0_1 := v_0.Args[1]
- if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
- break
- }
- y := v_0_1.Args[0]
- v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
- return true
- }
- // match: (GT (CMN x (RSBconst [0] y)))
- // result: (GT (CMP x y))
- for b.Controls[0].Op == OpARMCMN {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- v_0_0 := v_0.Args[0]
- v_0_1 := v_0.Args[1]
- for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
- x := v_0_0
- if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
- continue
- }
- y := v_0_1.Args[0]
- v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMGT, v0)
- return true
- }
- break
- }
// match: (GT (CMPconst [0] l:(SUB x y)) yes no)
// cond: l.Uses==1
// result: (GTnoov (CMP x y) yes no)
@@ -19076,42 +19004,6 @@
b.resetWithControl(BlockARMGE, cmp)
return true
}
- // match: (LE (CMP x (RSBconst [0] y)))
- // result: (LE (CMN x y))
- for b.Controls[0].Op == OpARMCMP {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- v_0_1 := v_0.Args[1]
- if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
- break
- }
- y := v_0_1.Args[0]
- v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
- return true
- }
- // match: (LE (CMN x (RSBconst [0] y)))
- // result: (LE (CMP x y))
- for b.Controls[0].Op == OpARMCMN {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- v_0_0 := v_0.Args[0]
- v_0_1 := v_0.Args[1]
- for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
- x := v_0_0
- if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
- continue
- }
- y := v_0_1.Args[0]
- v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLE, v0)
- return true
- }
- break
- }
// match: (LE (CMPconst [0] l:(SUB x y)) yes no)
// cond: l.Uses==1
// result: (LEnoov (CMP x y) yes no)
@@ -19992,42 +19884,6 @@
b.resetWithControl(BlockARMGT, cmp)
return true
}
- // match: (LT (CMP x (RSBconst [0] y)))
- // result: (LT (CMN x y))
- for b.Controls[0].Op == OpARMCMP {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- v_0_1 := v_0.Args[1]
- if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
- break
- }
- y := v_0_1.Args[0]
- v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
- return true
- }
- // match: (LT (CMN x (RSBconst [0] y)))
- // result: (LT (CMP x y))
- for b.Controls[0].Op == OpARMCMN {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- v_0_0 := v_0.Args[0]
- v_0_1 := v_0.Args[1]
- for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
- x := v_0_0
- if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
- continue
- }
- y := v_0_1.Args[0]
- v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARMLT, v0)
- return true
- }
- break
- }
// match: (LT (CMPconst [0] l:(SUB x y)) yes no)
// cond: l.Uses==1
// result: (LTnoov (CMP x y) yes no)
diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go
index ad34855..c5f53e5 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM64.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM64.go
@@ -27983,46 +27983,6 @@
}
break
}
- // match: (GE (CMP x z:(NEG y)) yes no)
- // cond: z.Uses == 1
- // result: (GE (CMN x y) yes no)
- for b.Controls[0].Op == OpARM64CMP {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- z := v_0.Args[1]
- if z.Op != OpARM64NEG {
- break
- }
- y := z.Args[0]
- if !(z.Uses == 1) {
- break
- }
- v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARM64GE, v0)
- return true
- }
- // match: (GE (CMPW x z:(NEG y)) yes no)
- // cond: z.Uses == 1
- // result: (GE (CMNW x y) yes no)
- for b.Controls[0].Op == OpARM64CMPW {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- z := v_0.Args[1]
- if z.Op != OpARM64NEG {
- break
- }
- y := z.Args[0]
- if !(z.Uses == 1) {
- break
- }
- v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARM64GE, v0)
- return true
- }
// match: (GE (CMPconst [0] z:(MADD a x y)) yes no)
// cond: z.Uses==1
// result: (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
@@ -28419,46 +28379,6 @@
}
break
}
- // match: (GT (CMP x z:(NEG y)) yes no)
- // cond: z.Uses == 1
- // result: (GT (CMN x y) yes no)
- for b.Controls[0].Op == OpARM64CMP {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- z := v_0.Args[1]
- if z.Op != OpARM64NEG {
- break
- }
- y := z.Args[0]
- if !(z.Uses == 1) {
- break
- }
- v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARM64GT, v0)
- return true
- }
- // match: (GT (CMPW x z:(NEG y)) yes no)
- // cond: z.Uses == 1
- // result: (GT (CMNW x y) yes no)
- for b.Controls[0].Op == OpARM64CMPW {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- z := v_0.Args[1]
- if z.Op != OpARM64NEG {
- break
- }
- y := z.Args[0]
- if !(z.Uses == 1) {
- break
- }
- v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARM64GT, v0)
- return true
- }
// match: (GT (CMPconst [0] z:(MADD a x y)) yes no)
// cond: z.Uses==1
// result: (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
@@ -28951,46 +28871,6 @@
}
break
}
- // match: (LE (CMP x z:(NEG y)) yes no)
- // cond: z.Uses == 1
- // result: (LE (CMN x y) yes no)
- for b.Controls[0].Op == OpARM64CMP {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- z := v_0.Args[1]
- if z.Op != OpARM64NEG {
- break
- }
- y := z.Args[0]
- if !(z.Uses == 1) {
- break
- }
- v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARM64LE, v0)
- return true
- }
- // match: (LE (CMPW x z:(NEG y)) yes no)
- // cond: z.Uses == 1
- // result: (LE (CMNW x y) yes no)
- for b.Controls[0].Op == OpARM64CMPW {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- z := v_0.Args[1]
- if z.Op != OpARM64NEG {
- break
- }
- y := z.Args[0]
- if !(z.Uses == 1) {
- break
- }
- v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARM64LE, v0)
- return true
- }
// match: (LE (CMPconst [0] z:(MADD a x y)) yes no)
// cond: z.Uses==1
// result: (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
@@ -29363,46 +29243,6 @@
}
break
}
- // match: (LT (CMP x z:(NEG y)) yes no)
- // cond: z.Uses == 1
- // result: (LT (CMN x y) yes no)
- for b.Controls[0].Op == OpARM64CMP {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- z := v_0.Args[1]
- if z.Op != OpARM64NEG {
- break
- }
- y := z.Args[0]
- if !(z.Uses == 1) {
- break
- }
- v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARM64LT, v0)
- return true
- }
- // match: (LT (CMPW x z:(NEG y)) yes no)
- // cond: z.Uses == 1
- // result: (LT (CMNW x y) yes no)
- for b.Controls[0].Op == OpARM64CMPW {
- v_0 := b.Controls[0]
- _ = v_0.Args[1]
- x := v_0.Args[0]
- z := v_0.Args[1]
- if z.Op != OpARM64NEG {
- break
- }
- y := z.Args[0]
- if !(z.Uses == 1) {
- break
- }
- v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
- v0.AddArg2(x, y)
- b.resetWithControl(BlockARM64LT, v0)
- return true
- }
// match: (LT (CMPconst [0] z:(MADD a x y)) yes no)
// cond: z.Uses==1
// result: (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go
index 885bbaf..a67d13e 100644
--- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go
+++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go
@@ -1124,13 +1124,14 @@
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
+ typ := &b.Func.Config.Types
// match: (EqPtr x y)
- // result: (SEQZ (SUB <x.Type> x y))
+ // result: (SEQZ (SUB <typ.Uintptr> x y))
for {
x := v_0
y := v_1
v.reset(OpRISCV64SEQZ)
- v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, typ.Uintptr)
v0.AddArg2(x, y)
v.AddArg(v0)
return true
@@ -2673,13 +2674,14 @@
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
+ typ := &b.Func.Config.Types
// match: (NeqPtr x y)
- // result: (SNEZ (SUB <x.Type> x y))
+ // result: (SNEZ (SUB <typ.Uintptr> x y))
for {
x := v_0
y := v_1
v.reset(OpRISCV64SNEZ)
- v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+ v0 := b.NewValue0(v.Pos, OpRISCV64SUB, typ.Uintptr)
v0.AddArg2(x, y)
v.AddArg(v0)
return true
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index 265ef1a..364e0c8 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -2446,6 +2446,38 @@
return s.newValue1(op, tt, v)
}
+ if ft.IsComplex() && tt.IsComplex() {
+ var op ssa.Op
+ if ft.Size() == tt.Size() {
+ switch ft.Size() {
+ case 8:
+ op = ssa.OpRound32F
+ case 16:
+ op = ssa.OpRound64F
+ default:
+ s.Fatalf("weird complex conversion %v -> %v", ft, tt)
+ }
+ } else if ft.Size() == 8 && tt.Size() == 16 {
+ op = ssa.OpCvt32Fto64F
+ } else if ft.Size() == 16 && tt.Size() == 8 {
+ op = ssa.OpCvt64Fto32F
+ } else {
+ s.Fatalf("weird complex conversion %v -> %v", ft, tt)
+ }
+ ftp := types.FloatForComplex(ft)
+ ttp := types.FloatForComplex(tt)
+ return s.newValue2(ssa.OpComplexMake, tt,
+ s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, v)),
+ s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, v)))
+ }
+
+ if tt.IsComplex() { // and ft is not complex
+ // Needed for generics support - can't happen in normal Go code.
+ et := types.FloatForComplex(tt)
+ v = s.conv(n, v, ft, et)
+ return s.newValue2(ssa.OpComplexMake, tt, v, s.zeroVal(et))
+ }
+
if ft.IsFloat() || tt.IsFloat() {
conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]
if s.config.RegSize == 4 && Arch.LinkArch.Family != sys.MIPS && !s.softFloat {
@@ -2519,31 +2551,6 @@
return nil
}
- if ft.IsComplex() && tt.IsComplex() {
- var op ssa.Op
- if ft.Size() == tt.Size() {
- switch ft.Size() {
- case 8:
- op = ssa.OpRound32F
- case 16:
- op = ssa.OpRound64F
- default:
- s.Fatalf("weird complex conversion %v -> %v", ft, tt)
- }
- } else if ft.Size() == 8 && tt.Size() == 16 {
- op = ssa.OpCvt32Fto64F
- } else if ft.Size() == 16 && tt.Size() == 8 {
- op = ssa.OpCvt64Fto32F
- } else {
- s.Fatalf("weird complex conversion %v -> %v", ft, tt)
- }
- ftp := types.FloatForComplex(ft)
- ttp := types.FloatForComplex(tt)
- return s.newValue2(ssa.OpComplexMake, tt,
- s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, v)),
- s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, v)))
- }
-
s.Fatalf("unhandled OCONV %s -> %s", ft.Kind(), tt.Kind())
return nil
}
@@ -6761,6 +6768,34 @@
return x
}
+// for wrapper, emit info of wrapped function.
+func emitWrappedFuncInfo(e *ssafn, pp *objw.Progs) {
+ if base.Ctxt.Flag_linkshared {
+ // Relative reference (SymPtrOff) to another shared object doesn't work.
+ // Unfortunate.
+ return
+ }
+
+ wfn := e.curfn.WrappedFunc
+ if wfn == nil {
+ return
+ }
+
+ wsym := wfn.Linksym()
+ x := base.Ctxt.LookupInit(fmt.Sprintf("%s.wrapinfo", wsym.Name), func(x *obj.LSym) {
+ objw.SymPtrOff(x, 0, wsym)
+ x.Set(obj.AttrContentAddressable, true)
+ })
+ e.curfn.LSym.Func().WrapInfo = x
+
+ // Emit a funcdata pointing at the wrap info data.
+ p := pp.Prog(obj.AFUNCDATA)
+ p.From.SetConst(objabi.FUNCDATA_WrapInfo)
+ p.To.Type = obj.TYPE_MEM
+ p.To.Name = obj.NAME_EXTERN
+ p.To.Sym = x
+}
+
// genssa appends entries to pp for each instruction in f.
func genssa(f *ssa.Func, pp *objw.Progs) {
var s State
@@ -6783,6 +6818,8 @@
p.To.Sym = openDeferInfo
}
+ emitWrappedFuncInfo(e, pp)
+
// Remember where each block starts.
s.bstart = make([]*obj.Prog, f.NumBlocks())
s.pp = pp
diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go
index 770175f..a75a3b1 100644
--- a/src/cmd/compile/internal/syntax/parser.go
+++ b/src/cmd/compile/internal/syntax/parser.go
@@ -588,44 +588,81 @@
d.Name = p.name()
if p.allowGenerics() && p.tok == _Lbrack {
// d.Name "[" ...
- // array/slice or type parameter list
+ // array/slice type or type parameter list
pos := p.pos()
p.next()
switch p.tok {
case _Name:
- // d.Name "[" name ...
- // array or type parameter list
- name := p.name()
- // Index or slice expressions are never constant and thus invalid
- // array length expressions. Thus, if we see a "[" following name
- // we can safely assume that "[" name starts a type parameter list.
- var x Expr // x != nil means x is the array length expression
+ // We may have an array type or a type parameter list.
+ // In either case we expect an expression x (which may
+ // just be a name, or a more complex expression) which
+ // we can analyze further.
+ //
+ // A type parameter list may have a type bound starting
+ // with a "[" as in: P []E. In that case, simply parsing
+ // an expression would lead to an error: P[] is invalid.
+ // But since index or slice expressions are never constant
+ // and thus invalid array length expressions, if we see a
+ // "[" following a name it must be the start of an array
+ // or slice constraint. Only if we don't see a "[" do we
+ // need to parse a full expression.
+ var x Expr = p.name()
if p.tok != _Lbrack {
- // d.Name "[" name ...
- // If we reach here, the next token is not a "[", and we need to
- // parse the expression starting with name. If that expression is
- // just that name, not followed by a "]" (in which case we might
- // have the array length "[" name "]"), we can also safely assume
- // a type parameter list.
+ // To parse the expression starting with name, expand
+ // the call sequence we would get by passing in name
+ // to parser.expr, and pass in name to parser.pexpr.
p.xnest++
- // To parse the expression starting with name, expand the call
- // sequence we would get by passing in name to parser.expr, and
- // pass in name to parser.pexpr.
- x = p.binaryExpr(p.pexpr(name, false), 0)
+ x = p.binaryExpr(p.pexpr(x, false), 0)
p.xnest--
- if x == name && p.tok != _Rbrack {
- x = nil
+ }
+
+ // analyze the cases
+ var pname *Name // pname != nil means pname is the type parameter name
+ var ptype Expr // ptype != nil means ptype is the type parameter type; pname != nil in this case
+ switch t := x.(type) {
+ case *Name:
+ // Unless we see a "]", we are at the start of a type parameter list.
+ if p.tok != _Rbrack {
+ // d.Name "[" name ...
+ pname = t
+ // no ptype
+ }
+ case *Operation:
+ // If we have an expression of the form name*T, and T is a (possibly
+ // parenthesized) type literal or the next token is a comma, we are
+ // at the start of a type parameter list.
+ if name, _ := t.X.(*Name); name != nil {
+ if t.Op == Mul && (isTypeLit(t.Y) || p.tok == _Comma) {
+ // d.Name "[" name "*" t.Y
+ // d.Name "[" name "*" t.Y ","
+ t.X, t.Y = t.Y, nil // convert t into unary *t.Y
+ pname = name
+ ptype = t
+ }
+ }
+ case *CallExpr:
+ // If we have an expression of the form name(T), and T is a (possibly
+ // parenthesized) type literal or the next token is a comma, we are
+ // at the start of a type parameter list.
+ if name, _ := t.Fun.(*Name); name != nil {
+ if len(t.ArgList) == 1 && !t.HasDots && (isTypeLit(t.ArgList[0]) || p.tok == _Comma) {
+ // d.Name "[" name "(" t.ArgList[0] ")"
+ // d.Name "[" name "(" t.ArgList[0] ")" ","
+ pname = name
+ ptype = t.ArgList[0]
+ }
}
}
- if x == nil {
- // d.Name "[" name ...
- // type parameter list
- d.TParamList = p.paramList(name, _Rbrack, true)
+
+ if pname != nil {
+ // d.Name "[" pname ...
+ // d.Name "[" pname ptype ...
+ // d.Name "[" pname ptype "," ...
+ d.TParamList = p.paramList(pname, ptype, _Rbrack, true)
d.Alias = p.gotAssign()
d.Type = p.typeOrNil()
} else {
- // d.Name "[" x "]" ...
- // x is the array length expression
+ // d.Name "[" x ...
d.Type = p.arrayType(pos, x)
}
case _Rbrack:
@@ -650,6 +687,21 @@
return d
}
+// isTypeLit reports whether x is a (possibly parenthesized) type literal.
+func isTypeLit(x Expr) bool {
+ switch x := x.(type) {
+ case *ArrayType, *StructType, *FuncType, *InterfaceType, *SliceType, *MapType, *ChanType:
+ return true
+ case *Operation:
+ // *T may be a pointer dereferenciation.
+ // Only consider *T as type literal if T is a type literal.
+ return x.Op == Mul && x.Y == nil && isTypeLit(x.X)
+ case *ParenExpr:
+ return isTypeLit(x.X)
+ }
+ return false
+}
+
// VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
func (p *parser) varDecl(group *Group) Decl {
if trace {
@@ -689,7 +741,7 @@
f.Pragma = p.takePragma()
if p.got(_Lparen) {
- rcvr := p.paramList(nil, _Rparen, false)
+ rcvr := p.paramList(nil, nil, _Rparen, false)
switch len(rcvr) {
case 0:
p.error("method has no receiver")
@@ -708,7 +760,13 @@
}
f.Name = p.name()
- f.TParamList, f.Type = p.funcType("")
+
+ context := ""
+ if f.Recv != nil && p.mode&AllowMethodTypeParams == 0 {
+ context = "method" // don't permit (method) type parameters in funcType
+ }
+ f.TParamList, f.Type = p.funcType(context)
+
if p.tok == _Lbrace {
f.Body = p.funcBody()
}
@@ -1363,18 +1421,18 @@
if p.allowGenerics() && p.got(_Lbrack) {
if context != "" {
// accept but complain
- p.syntaxErrorAt(typ.pos, context+" cannot have type parameters")
+ p.syntaxErrorAt(typ.pos, context+" must have no type parameters")
}
if p.tok == _Rbrack {
p.syntaxError("empty type parameter list")
p.next()
} else {
- tparamList = p.paramList(nil, _Rbrack, true)
+ tparamList = p.paramList(nil, nil, _Rbrack, true)
}
}
p.want(_Lparen)
- typ.ParamList = p.paramList(nil, _Rparen, false)
+ typ.ParamList = p.paramList(nil, nil, _Rparen, false)
typ.ResultList = p.funcResult()
return tparamList, typ
@@ -1392,6 +1450,13 @@
len = p.expr()
p.xnest--
}
+ if p.tok == _Comma {
+ // Trailing commas are accepted in type parameter
+ // lists but not in array type declarations.
+ // Accept for better error handling but complain.
+ p.syntaxError("unexpected comma; expecting ]")
+ p.next()
+ }
p.want(_Rbrack)
t := new(ArrayType)
t.pos = pos
@@ -1516,7 +1581,7 @@
}
if p.got(_Lparen) {
- return p.paramList(nil, _Rparen, false)
+ return p.paramList(nil, nil, _Rparen, false)
}
pos := p.pos()
@@ -1742,7 +1807,7 @@
// A type argument list looks like a parameter list with only
// types. Parse a parameter list and decide afterwards.
- list := p.paramList(nil, _Rbrack, false)
+ list := p.paramList(nil, nil, _Rbrack, false)
if len(list) == 0 {
// The type parameter list is not [] but we got nothing
// due to other errors (reported by paramList). Treat
@@ -1764,7 +1829,7 @@
// TODO(gri) Record list as type parameter list with f.Type
// if we want to type-check the generic method.
// For now, report an error so this is not a silent event.
- p.errorAt(pos, "interface method cannot have type parameters")
+ p.errorAt(pos, "interface method must have no type parameters")
break
}
@@ -1948,17 +2013,41 @@
// ParameterList = ParameterDecl { "," ParameterDecl } .
// "(" or "[" has already been consumed.
// If name != nil, it is the first name after "(" or "[".
+// If typ != nil, name must be != nil, and (name, typ) is the first field in the list.
// In the result list, either all fields have a name, or no field has a name.
-func (p *parser) paramList(name *Name, close token, requireNames bool) (list []*Field) {
+func (p *parser) paramList(name *Name, typ Expr, close token, requireNames bool) (list []*Field) {
if trace {
defer p.trace("paramList")()
}
+ // p.list won't invoke its function argument if we're at the end of the
+ // parameter list. If we have a complete field, handle this case here.
+ if name != nil && typ != nil && p.tok == close {
+ p.next()
+ par := new(Field)
+ par.pos = name.pos
+ par.Name = name
+ par.Type = typ
+ return []*Field{par}
+ }
+
var named int // number of parameters that have an explicit name and type
var typed int // number of parameters that have an explicit type
end := p.list(_Comma, close, func() bool {
- par := p.paramDeclOrNil(name, close)
+ var par *Field
+ if typ != nil {
+ if debug && name == nil {
+ panic("initial type provided without name")
+ }
+ par = new(Field)
+ par.pos = name.pos
+ par.Name = name
+ par.Type = typ
+ } else {
+ par = p.paramDeclOrNil(name, close)
+ }
name = nil // 1st name was consumed if present
+ typ = nil // 1st type was consumed if present
if par != nil {
if debug && par.Name == nil && par.Type == nil {
panic("parameter without name or type")
diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go
index 68f3c37..e258a17 100644
--- a/src/cmd/compile/internal/syntax/parser_test.go
+++ b/src/cmd/compile/internal/syntax/parser_test.go
@@ -46,7 +46,7 @@
for _, fi := range list {
name := fi.Name()
if !fi.IsDir() && !strings.HasPrefix(name, ".") {
- ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics)
+ ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowMethodTypeParams)
}
}
}
diff --git a/src/cmd/compile/internal/syntax/printer.go b/src/cmd/compile/internal/syntax/printer.go
index c8d3179..0385227 100644
--- a/src/cmd/compile/internal/syntax/printer.go
+++ b/src/cmd/compile/internal/syntax/printer.go
@@ -44,7 +44,7 @@
return
}
-// String is a convenience functions that prints n in ShortForm
+// String is a convenience function that prints n in ShortForm
// and returns the printed string.
func String(n Node) string {
var buf bytes.Buffer
@@ -666,9 +666,7 @@
}
p.print(n.Name)
if n.TParamList != nil {
- p.print(_Lbrack)
- p.printFieldList(n.TParamList, nil, _Comma)
- p.print(_Rbrack)
+ p.printParameterList(n.TParamList, true)
}
p.print(blank)
if n.Alias {
@@ -700,9 +698,7 @@
}
p.print(n.Name)
if n.TParamList != nil {
- p.print(_Lbrack)
- p.printFieldList(n.TParamList, nil, _Comma)
- p.print(_Rbrack)
+ p.printParameterList(n.TParamList, true)
}
p.printSignature(n.Type)
if n.Body != nil {
@@ -887,38 +883,47 @@
}
func (p *printer) printSignature(sig *FuncType) {
- p.printParameterList(sig.ParamList)
+ p.printParameterList(sig.ParamList, false)
if list := sig.ResultList; list != nil {
p.print(blank)
if len(list) == 1 && list[0].Name == nil {
p.printNode(list[0].Type)
} else {
- p.printParameterList(list)
+ p.printParameterList(list, false)
}
}
}
-func (p *printer) printParameterList(list []*Field) {
- p.print(_Lparen)
- if len(list) > 0 {
- for i, f := range list {
- if i > 0 {
- p.print(_Comma, blank)
- }
- if f.Name != nil {
- p.printNode(f.Name)
- if i+1 < len(list) {
- f1 := list[i+1]
- if f1.Name != nil && f1.Type == f.Type {
- continue // no need to print type
- }
+func (p *printer) printParameterList(list []*Field, types bool) {
+ open, close := _Lparen, _Rparen
+ if types {
+ open, close = _Lbrack, _Rbrack
+ }
+ p.print(open)
+ for i, f := range list {
+ if i > 0 {
+ p.print(_Comma, blank)
+ }
+ if f.Name != nil {
+ p.printNode(f.Name)
+ if i+1 < len(list) {
+ f1 := list[i+1]
+ if f1.Name != nil && f1.Type == f.Type {
+ continue // no need to print type
}
- p.print(blank)
}
- p.printNode(f.Type)
+ p.print(blank)
+ }
+ p.printNode(unparen(f.Type)) // no need for (extra) parentheses around parameter types
+ }
+ // A type parameter list [P *T] where T is not a type literal requires a comma as in [P *T,]
+ // so that it's not parsed as [P*T].
+ if types && len(list) == 1 {
+ if t, _ := list[0].Type.(*Operation); t != nil && t.Op == Mul && t.Y == nil && !isTypeLit(t.X) {
+ p.print(_Comma)
}
}
- p.print(_Rparen)
+ p.print(close)
}
func (p *printer) printStmtList(list []Stmt, braces bool) {
diff --git a/src/cmd/compile/internal/syntax/printer_test.go b/src/cmd/compile/internal/syntax/printer_test.go
index 604f1fc..941af0a 100644
--- a/src/cmd/compile/internal/syntax/printer_test.go
+++ b/src/cmd/compile/internal/syntax/printer_test.go
@@ -53,54 +53,77 @@
}
}
-var stringTests = []string{
- "package p",
- "package p; type _ int; type T1 = struct{}; type ( _ *struct{}; T2 = float32 )",
+var stringTests = [][2]string{
+ dup("package p"),
+ dup("package p; type _ int; type T1 = struct{}; type ( _ *struct{}; T2 = float32 )"),
// generic type declarations
- "package p; type _[T any] struct{}",
- "package p; type _[A, B, C interface{m()}] struct{}",
- "package p; type _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}] struct{}",
+ dup("package p; type _[T any] struct{}"),
+ dup("package p; type _[A, B, C interface{m()}] struct{}"),
+ dup("package p; type _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}] struct{}"),
+
+ dup("package p; type _[P *T,] struct{}"),
+ dup("package p; type _[P *T, _ any] struct{}"),
+ {"package p; type _[P (*T),] struct{}", "package p; type _[P *T,] struct{}"},
+ {"package p; type _[P (*T), _ any] struct{}", "package p; type _[P *T, _ any] struct{}"},
+ {"package p; type _[P (T),] struct{}", "package p; type _[P T] struct{}"},
+ {"package p; type _[P (T), _ any] struct{}", "package p; type _[P T, _ any] struct{}"},
+
+ dup("package p; type _[P *struct{}] struct{}"),
+ {"package p; type _[P (*struct{})] struct{}", "package p; type _[P *struct{}] struct{}"},
+ {"package p; type _[P ([]int)] struct{}", "package p; type _[P []int] struct{}"},
+
+ dup("package p; type _ [P(T)]struct{}"),
+ dup("package p; type _ [P((T))]struct{}"),
+ dup("package p; type _ [P * *T]struct{}"),
+ dup("package p; type _ [P * T]struct{}"),
+ dup("package p; type _ [P(*T)]struct{}"),
+ dup("package p; type _ [P(**T)]struct{}"),
+ dup("package p; type _ [P * T - T]struct{}"),
+
+ // array type declarations
+ dup("package p; type _ [P * T]struct{}"),
+ dup("package p; type _ [P * T - T]struct{}"),
// generic function declarations
- "package p; func _[T any]()",
- "package p; func _[A, B, C interface{m()}]()",
- "package p; func _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}]()",
+ dup("package p; func _[T any]()"),
+ dup("package p; func _[A, B, C interface{m()}]()"),
+ dup("package p; func _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}]()"),
// methods with generic receiver types
- "package p; func (R[T]) _()",
- "package p; func (*R[A, B, C]) _()",
- "package p; func (_ *R[A, B, C]) _()",
+ dup("package p; func (R[T]) _()"),
+ dup("package p; func (*R[A, B, C]) _()"),
+ dup("package p; func (_ *R[A, B, C]) _()"),
// type constraint literals with elided interfaces
- "package p; func _[P ~int, Q int | string]() {}",
- "package p; func _[P struct{f int}, Q *P]() {}",
+ dup("package p; func _[P ~int, Q int | string]() {}"),
+ dup("package p; func _[P struct{f int}, Q *P]() {}"),
// channels
- "package p; type _ chan chan int",
- "package p; type _ chan (<-chan int)",
- "package p; type _ chan chan<- int",
+ dup("package p; type _ chan chan int"),
+ dup("package p; type _ chan (<-chan int)"),
+ dup("package p; type _ chan chan<- int"),
- "package p; type _ <-chan chan int",
- "package p; type _ <-chan <-chan int",
- "package p; type _ <-chan chan<- int",
+ dup("package p; type _ <-chan chan int"),
+ dup("package p; type _ <-chan <-chan int"),
+ dup("package p; type _ <-chan chan<- int"),
- "package p; type _ chan<- chan int",
- "package p; type _ chan<- <-chan int",
- "package p; type _ chan<- chan<- int",
+ dup("package p; type _ chan<- chan int"),
+ dup("package p; type _ chan<- <-chan int"),
+ dup("package p; type _ chan<- chan<- int"),
// TODO(gri) expand
}
func TestPrintString(t *testing.T) {
- for _, want := range stringTests {
- ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics)
+ for _, test := range stringTests {
+ ast, err := Parse(nil, strings.NewReader(test[0]), nil, nil, AllowGenerics)
if err != nil {
t.Error(err)
continue
}
- if got := String(ast); got != want {
- t.Errorf("%q: got %q", want, got)
+ if got := String(ast); got != test[1] {
+ t.Errorf("%q: got %q", test[1], got)
}
}
}
diff --git a/src/cmd/compile/internal/syntax/syntax.go b/src/cmd/compile/internal/syntax/syntax.go
index f3d4c09..25c8116 100644
--- a/src/cmd/compile/internal/syntax/syntax.go
+++ b/src/cmd/compile/internal/syntax/syntax.go
@@ -17,6 +17,7 @@
const (
CheckBranches Mode = 1 << iota // check correct use of labels, break, continue, and goto statements
AllowGenerics
+ AllowMethodTypeParams // does not support interface methods yet; ignored if AllowGenerics is not set
)
// Error describes a syntax error. Error implements the error interface.
diff --git a/src/cmd/compile/internal/syntax/testdata/issue48382.go2 b/src/cmd/compile/internal/syntax/testdata/issue48382.go2
index 1e8f4b0..c00fee6 100644
--- a/src/cmd/compile/internal/syntax/testdata/issue48382.go2
+++ b/src/cmd/compile/internal/syntax/testdata/issue48382.go2
@@ -4,12 +4,12 @@
package p
-type _ func /* ERROR function type cannot have type parameters */ [ /* ERROR empty type parameter list */ ]()
-type _ func /* ERROR function type cannot have type parameters */ [ x /* ERROR missing type constraint */ ]()
-type _ func /* ERROR function type cannot have type parameters */ [P any]()
+type _ func /* ERROR function type must have no type parameters */ [ /* ERROR empty type parameter list */ ]()
+type _ func /* ERROR function type must have no type parameters */ [ x /* ERROR missing type constraint */ ]()
+type _ func /* ERROR function type must have no type parameters */ [P any]()
-var _ = func /* ERROR function literal cannot have type parameters */ [P any]() {}
+var _ = func /* ERROR function literal must have no type parameters */ [P any]() {}
type _ interface{
- m /* ERROR interface method cannot have type parameters */ [P any]()
+ m /* ERROR interface method must have no type parameters */ [P any]()
}
diff --git a/src/cmd/compile/internal/syntax/testdata/issue49482.go2 b/src/cmd/compile/internal/syntax/testdata/issue49482.go2
new file mode 100644
index 0000000..1fc303d
--- /dev/null
+++ b/src/cmd/compile/internal/syntax/testdata/issue49482.go2
@@ -0,0 +1,31 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type (
+ // these need a comma to disambiguate
+ _[P *T,] struct{}
+ _[P *T, _ any] struct{}
+ _[P (*T),] struct{}
+ _[P (*T), _ any] struct{}
+ _[P (T),] struct{}
+ _[P (T), _ any] struct{}
+
+ // these parse as name followed by type
+ _[P *struct{}] struct{}
+ _[P (*struct{})] struct{}
+ _[P ([]int)] struct{}
+
+ // array declarations
+ _ [P(T)]struct{}
+ _ [P((T))]struct{}
+ _ [P * *T] struct{} // this could be a name followed by a type but it makes the rules more complicated
+ _ [P * T]struct{}
+ _ [P(*T)]struct{}
+ _ [P(**T)]struct{}
+ _ [P * T - T]struct{}
+ _ [P*T-T /* ERROR unexpected comma */ ,]struct{}
+ _ [10 /* ERROR unexpected comma */ ,]struct{}
+)
diff --git a/src/cmd/compile/internal/syntax/testdata/tparams.go2 b/src/cmd/compile/internal/syntax/testdata/tparams.go2
index 80e155b..a9bd72c 100644
--- a/src/cmd/compile/internal/syntax/testdata/tparams.go2
+++ b/src/cmd/compile/internal/syntax/testdata/tparams.go2
@@ -13,7 +13,7 @@
}
type t interface {
t[a]
- m /* ERROR method cannot have type parameters */ [_ _, /* ERROR mixed */ _]()
+ m /* ERROR method must have no type parameters */ [_ _, /* ERROR mixed */ _]()
t[a, b]
}
diff --git a/src/cmd/compile/internal/test/issue50182_test.go b/src/cmd/compile/internal/test/issue50182_test.go
new file mode 100644
index 0000000..cd277fa
--- /dev/null
+++ b/src/cmd/compile/internal/test/issue50182_test.go
@@ -0,0 +1,62 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package test
+
+import (
+ "fmt"
+ "sort"
+ "testing"
+)
+
+// Test that calling methods on generic types doesn't cause allocations.
+func genericSorted[T sort.Interface](data T) bool {
+ n := data.Len()
+ for i := n - 1; i > 0; i-- {
+ if data.Less(i, i-1) {
+ return false
+ }
+ }
+ return true
+}
+func TestGenericSorted(t *testing.T) {
+ var data = sort.IntSlice{-10, -5, 0, 1, 2, 3, 5, 7, 11, 100, 100, 100, 1000, 10000}
+ f := func() {
+ genericSorted(data)
+ }
+ if n := testing.AllocsPerRun(10, f); n > 0 {
+ t.Errorf("got %f allocs, want 0", n)
+ }
+}
+
+// Test that escape analysis correctly tracks escaping inside of methods
+// called on generic types.
+type fooer interface {
+ foo()
+}
+type P struct {
+ p *int
+ q int
+}
+
+var esc []*int
+
+func (p P) foo() {
+ esc = append(esc, p.p) // foo escapes the pointer from inside of p
+}
+func f[T fooer](t T) {
+ t.foo()
+}
+func TestGenericEscape(t *testing.T) {
+ for i := 0; i < 4; i++ {
+ var x int = 77 + i
+ var p P = P{p: &x}
+ f(p)
+ }
+ for i, p := range esc {
+ if got, want := *p, 77+i; got != want {
+ panic(fmt.Sprintf("entry %d: got %d, want %d", i, got, want))
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/test/testdata/ptrsort.go b/src/cmd/compile/internal/test/testdata/ptrsort.go
index 6cc7ba4..d26ba58 100644
--- a/src/cmd/compile/internal/test/testdata/ptrsort.go
+++ b/src/cmd/compile/internal/test/testdata/ptrsort.go
@@ -6,7 +6,7 @@
import (
"fmt"
- "./mysort"
+ "cmd/compile/internal/test/testdata/mysort"
)
type MyString struct {
diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go
index ae6542d..4394c6e 100644
--- a/src/cmd/compile/internal/typecheck/crawler.go
+++ b/src/cmd/compile/internal/typecheck/crawler.go
@@ -8,19 +8,32 @@
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
+ "cmd/internal/src"
)
// crawlExports crawls the type/object graph rooted at the given list of exported
-// objects. It descends through all parts of types and follows any methods on defined
-// types. Any functions that are found to be potentially callable by importers are
-// marked with ExportInline, so that iexport.go knows to re-export their inline body.
-// Also, any function or global referenced by a function marked by ExportInline() is
-// marked for export (whether its name is exported or not).
+// objects (which are variables, functions, and types). It descends through all parts
+// of types and follows methods on defined types. Any functions that are found to be
+// potentially callable by importers directly or after inlining are marked with
+// ExportInline, so that iexport.go knows to export their inline body.
+//
+// The overall purpose of crawlExports is to AVOID exporting inlineable methods
+// that cannot actually be referenced, thereby reducing the size of the exports
+// significantly.
+//
+// For non-generic defined types reachable from global variables, we only set
+// ExportInline for exported methods. For defined types that are directly named or are
+// embedded recursively in such a type, we set ExportInline for all methods, since
+// these types can be embedded in another local type. For instantiated types that are
+// used anywhere in a inlineable function, we set ExportInline on all methods of the
+// base generic type, since all methods will be needed for creating any instantiated
+// type.
func crawlExports(exports []*ir.Name) {
p := crawler{
- marked: make(map[*types.Type]bool),
- embedded: make(map[*types.Type]bool),
- generic: make(map[*types.Type]bool),
+ marked: make(map[*types.Type]bool),
+ embedded: make(map[*types.Type]bool),
+ generic: make(map[*types.Type]bool),
+ checkFullyInst: make(map[*types.Type]bool),
}
for _, n := range exports {
p.markObject(n)
@@ -28,9 +41,10 @@
}
type crawler struct {
- marked map[*types.Type]bool // types already seen by markType
- embedded map[*types.Type]bool // types already seen by markEmbed
- generic map[*types.Type]bool // types already seen by markGeneric
+ marked map[*types.Type]bool // types already seen by markType
+ embedded map[*types.Type]bool // types already seen by markEmbed
+ generic map[*types.Type]bool // types already seen by markGeneric
+ checkFullyInst map[*types.Type]bool // types already seen by checkForFullyInst
}
// markObject visits a reachable object (function, method, global type, or global variable)
@@ -170,10 +184,12 @@
}
}
-// markGeneric takes an instantiated type or a base generic type t, and
-// marks all the methods of the base generic type of t. If a base generic
-// type is written to export file, even if not explicitly marked for export,
-// all of its methods need to be available for instantiation if needed.
+// markGeneric takes an instantiated type or a base generic type t, and marks all the
+// methods of the base generic type of t. If a base generic type is written out for
+// export, even if not explicitly marked for export, then all of its methods need to
+// be available for instantiation, since we always create all methods of a specified
+// instantiated type. Non-exported methods must generally be instantiated, since they may
+// be called by the exported methods or other generic function in the same package.
func (p *crawler) markGeneric(t *types.Type) {
if t.IsPtr() {
t = t.Elem()
@@ -194,6 +210,94 @@
}
}
+// checkForFullyInst looks for fully-instantiated types in a type (at any nesting
+// level). If it finds a fully-instantiated type, it ensures that the necessary
+// dictionary and shape methods are exported. It updates p.checkFullyInst, so it
+// traverses each particular type only once.
+func (p *crawler) checkForFullyInst(t *types.Type) {
+ if p.checkFullyInst[t] {
+ return
+ }
+ p.checkFullyInst[t] = true
+
+ if t.IsFullyInstantiated() && !t.HasShape() && !t.IsInterface() && t.Methods().Len() > 0 {
+ // For any fully-instantiated type, the relevant
+ // dictionaries and shape instantiations will have
+ // already been created or are in the import data.
+ // Make sure that they are exported, so that any
+ // other package that inlines this function will have
+ // them available for import, and so will not need
+ // another round of method and dictionary
+ // instantiation after inlining.
+ baseType := t.OrigSym().Def.(*ir.Name).Type()
+ shapes := make([]*types.Type, len(t.RParams()))
+ for i, t1 := range t.RParams() {
+ shapes[i] = Shapify(t1, i, baseType.RParams()[i])
+ }
+ for j := range t.Methods().Slice() {
+ baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
+ dictsym := MakeDictSym(baseNname.Sym(), t.RParams(), true)
+ if dictsym.Def == nil {
+ in := Resolve(ir.NewIdent(src.NoXPos, dictsym))
+ dictsym = in.Sym()
+ }
+ Export(dictsym.Def.(*ir.Name))
+ methsym := MakeFuncInstSym(baseNname.Sym(), shapes, false, true)
+ if methsym.Def == nil {
+ in := Resolve(ir.NewIdent(src.NoXPos, methsym))
+ methsym = in.Sym()
+ }
+ methNode := methsym.Def.(*ir.Name)
+ Export(methNode)
+ if HaveInlineBody(methNode.Func) {
+ // Export the body as well if
+ // instantiation is inlineable.
+ ImportedBody(methNode.Func)
+ methNode.Func.SetExportInline(true)
+ }
+ }
+ }
+
+ // Descend into the type. We descend even if it is a fully-instantiated type,
+ // since the instantiated type may have other instantiated types inside of
+ // it (in fields, methods, etc.).
+ switch t.Kind() {
+ case types.TPTR, types.TARRAY, types.TSLICE:
+ p.checkForFullyInst(t.Elem())
+
+ case types.TCHAN:
+ p.checkForFullyInst(t.Elem())
+
+ case types.TMAP:
+ p.checkForFullyInst(t.Key())
+ p.checkForFullyInst(t.Elem())
+
+ case types.TSTRUCT:
+ if t.IsFuncArgStruct() {
+ break
+ }
+ for _, f := range t.FieldSlice() {
+ p.checkForFullyInst(f.Type)
+ }
+
+ case types.TFUNC:
+ if recv := t.Recv(); recv != nil {
+ p.checkForFullyInst(t.Recv().Type)
+ }
+ for _, f := range t.Params().FieldSlice() {
+ p.checkForFullyInst(f.Type)
+ }
+ for _, f := range t.Results().FieldSlice() {
+ p.checkForFullyInst(f.Type)
+ }
+
+ case types.TINTER:
+ for _, f := range t.AllMethods().Slice() {
+ p.checkForFullyInst(f.Type)
+ }
+ }
+}
+
// markInlBody marks n's inline body for export and recursively
// ensures all called functions are marked too.
func (p *crawler) markInlBody(n *ir.Name) {
@@ -222,8 +326,13 @@
doFlood = func(n ir.Node) {
t := n.Type()
if t != nil {
- if t.HasTParam() || t.IsFullyInstantiated() {
+ if t.HasTParam() {
+ // If any generic types are used, then make sure that
+ // the methods of the generic type are exported and
+ // scanned for other possible exports.
p.markGeneric(t)
+ } else {
+ p.checkForFullyInst(t)
}
if base.Debug.Unified == 0 {
// If a method of un-exported type is promoted and accessible by
@@ -256,6 +365,10 @@
switch n.Class {
case ir.PFUNC:
p.markInlBody(n)
+ // Note: this Export() and the one below seem unneeded,
+ // since any function/extern name encountered in an
+ // exported function body will be exported
+ // automatically via qualifiedIdent() in iexport.go.
Export(n)
case ir.PEXTERN:
Export(n)
diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go
index 9b74bf7..eb316d3 100644
--- a/src/cmd/compile/internal/typecheck/expr.go
+++ b/src/cmd/compile/internal/typecheck/expr.go
@@ -466,6 +466,27 @@
if n.X.Op() == ir.OLITERAL {
return stringtoruneslit(n)
}
+
+ case ir.OBYTES2STR:
+ if t.Elem() != types.ByteType && t.Elem() != types.Types[types.TUINT8] {
+ // If t is a slice of a user-defined byte type B (not uint8
+ // or byte), then add an extra CONVNOP from []B to []byte, so
+ // that the call to slicebytetostring() added in walk will
+ // typecheck correctly.
+ n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.ByteType), n.X)
+ n.X.SetTypecheck(1)
+ }
+
+ case ir.ORUNES2STR:
+ if t.Elem() != types.RuneType && t.Elem() != types.Types[types.TINT32] {
+ // If t is a slice of a user-defined rune type B (not uint32
+ // or rune), then add an extra CONVNOP from []B to []rune, so
+ // that the call to slicerunetostring() added in walk will
+ // typecheck correctly.
+ n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.RuneType), n.X)
+ n.X.SetTypecheck(1)
+ }
+
}
return n
}
diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go
index 7ebabe7..b7a251c 100644
--- a/src/cmd/compile/internal/typecheck/iexport.go
+++ b/src/cmd/compile/internal/typecheck/iexport.go
@@ -243,6 +243,7 @@
"io"
"math/big"
"sort"
+ "strconv"
"strings"
"cmd/compile/internal/base"
@@ -730,6 +731,36 @@
w.pkg(s.Pkg)
}
+const blankMarker = "$"
+
+// TparamExportName creates a unique name for type param in a method or a generic
+// type, using the specified unique prefix and the index of the type param. The index
+// is only used if the type param is blank, in which case the blank is replace by
+// "$<index>". A unique name is needed for later substitution in the compiler and
+// export/import that keeps blank type params associated with the correct constraint.
+func TparamExportName(prefix string, name string, index int) string {
+ if name == "_" {
+ name = blankMarker + strconv.Itoa(index)
+ }
+ return prefix + "." + name
+}
+
+// TparamName returns the real name of a type parameter, after stripping its
+// qualifying prefix and reverting blank-name encoding. See TparamExportName
+// for details.
+func TparamName(exportName string) string {
+ // Remove the "path" from the type param name that makes it unique.
+ ix := strings.LastIndex(exportName, ".")
+ if ix < 0 {
+ return ""
+ }
+ name := exportName[ix+1:]
+ if strings.HasPrefix(name, blankMarker) {
+ return "_"
+ }
+ return name
+}
+
func (w *exportWriter) selector(s *types.Sym) {
if w.currPkg == nil {
base.Fatalf("missing currPkg")
@@ -1820,7 +1851,10 @@
n := n.(*ir.ClosureExpr)
w.op(ir.OCLOSURE)
w.pos(n.Pos())
+ old := w.currPkg
+ w.setPkg(n.Type().Pkg(), true)
w.signature(n.Type())
+ w.setPkg(old, true)
// Write out id for the Outer of each conditional variable. The
// conditional variable itself for this closure will be re-created
diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go
index 09f87df..28a5060 100644
--- a/src/cmd/compile/internal/typecheck/iimport.go
+++ b/src/cmd/compile/internal/typecheck/iimport.go
@@ -354,15 +354,18 @@
// declaration before recursing.
n := importtype(pos, sym)
t := n.Type()
+
+ // Because of recursion, we need to defer width calculations and
+ // instantiations on intermediate types until the top-level type is
+ // fully constructed. Note that we can have recursion via type
+ // constraints.
+ types.DeferCheckSize()
+ deferDoInst()
if tag == 'U' {
rparams := r.typeList()
t.SetRParams(rparams)
}
- // We also need to defer width calculations until
- // after the underlying type has been assigned.
- types.DeferCheckSize()
- deferDoInst()
underlying := r.typ()
t.SetUnderlying(underlying)
@@ -1371,7 +1374,9 @@
case ir.OCLOSURE:
//println("Importing CLOSURE")
pos := r.pos()
+ r.setPkg()
typ := r.signature(nil, nil)
+ r.setPkg()
// All the remaining code below is similar to (*noder).funcLit(), but
// with Dcls and ClosureVars lists already set up
@@ -1630,11 +1635,16 @@
return n
case ir.OADDR, ir.OPTRLIT:
- n := NodAddrAt(r.pos(), r.expr())
if go117ExportTypes {
+ pos := r.pos()
+ expr := r.expr()
+ expr.SetTypecheck(1) // we do this for all nodes after importing, but do it now so markAddrOf can see it.
+ n := NodAddrAt(pos, expr)
n.SetOp(op)
n.SetType(r.typ())
+ return n
}
+ n := NodAddrAt(r.pos(), r.expr())
return n
case ir.ODEREF:
diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go
index 5b5b043..5147ebb 100644
--- a/src/cmd/compile/internal/typecheck/subr.go
+++ b/src/cmd/compile/internal/typecheck/subr.go
@@ -80,7 +80,7 @@
if IncrementalAddrtaken {
// We can only do incremental addrtaken computation when it is ok
// to typecheck the argument of the OADDR. That's only safe after the
- // main typecheck has completed.
+ // main typecheck has completed, and not loading the inlined body.
// The argument to OADDR needs to be typechecked because &x[i] takes
// the address of x if x is an array, but not if x is a slice.
// Note: OuterValue doesn't work correctly until n is typechecked.
@@ -173,6 +173,8 @@
return n
}
+// CalcMethods calculates all the methods (including embedding) of a non-interface
+// type t.
func CalcMethods(t *types.Type) {
if t == nil || t.AllMethods().Len() != 0 {
return
@@ -976,7 +978,9 @@
// function that helps implement a method of an instantiated type). For method nodes
// on shape types, we prepend "nofunc.", because method nodes for shape types will
// have no body, and we want to avoid a name conflict with the shape-based function
-// that helps implement the same method for fully-instantiated types.
+// that helps implement the same method for fully-instantiated types. Function names
+// are also created at the end of (*Tsubster).typ1, so we append "nofunc" there as
+// well, as needed.
func MakeFuncInstSym(gf *types.Sym, targs []*types.Type, isMethodNode, hasBrackets bool) *types.Sym {
nm := makeInstName1(gf.Name, targs, hasBrackets)
if targs[0].HasShape() && isMethodNode {
@@ -1273,7 +1277,25 @@
for i, f := range t.Methods().Slice() {
t2 := ts.typ1(f.Type)
oldsym := f.Nname.Sym()
- newsym := MakeFuncInstSym(oldsym, ts.Targs, true, true)
+
+ // Use the name of the substituted receiver to create the
+ // method name, since the receiver name may have many levels
+ // of nesting (brackets) with type names to be substituted.
+ recvType := t2.Recv().Type
+ var nm string
+ if recvType.IsPtr() {
+ recvType = recvType.Elem()
+ nm = "(*" + recvType.Sym().Name + ")." + f.Sym.Name
+ } else {
+ nm = recvType.Sym().Name + "." + f.Sym.Name
+ }
+ if recvType.RParams()[0].HasShape() {
+ // We add "nofunc" to methods of shape type to avoid
+ // conflict with the name of the shape-based helper
+ // function. See header comment of MakeFuncInstSym.
+ nm = "nofunc." + nm
+ }
+ newsym := oldsym.Pkg.Lookup(nm)
var nname *ir.Name
if newsym.Def != nil {
nname = newsym.Def.(*ir.Name)
@@ -1304,9 +1326,9 @@
func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type {
if t.NumFields() == 0 {
if t.HasTParam() || t.HasShape() {
- // For an empty struct, we need to return a new type,
- // since it may now be fully instantiated (HasTParam
- // becomes false).
+ // For an empty struct, we need to return a new type, if
+ // substituting from a generic type or shape type, since it
+ // will change HasTParam/HasShape flags.
return types.NewStruct(t.Pkg(), nil)
}
return t
@@ -1365,10 +1387,10 @@
// tinter substitutes type params in types of the methods of an interface type.
func (ts *Tsubster) tinter(t *types.Type, force bool) *types.Type {
if t.Methods().Len() == 0 {
- if t.HasTParam() {
- // For an empty interface, we need to return a new type,
- // since it may now be fully instantiated (HasTParam
- // becomes false).
+ if t.HasTParam() || t.HasShape() {
+ // For an empty interface, we need to return a new type, if
+ // substituting from a generic type or shape type, since
+ // since it will change HasTParam/HasShape flags.
return types.NewInterface(t.Pkg(), nil, false)
}
return t
@@ -1402,6 +1424,68 @@
return sym.Name[0:strings.Index(sym.Name, "[")]
}
+// getShapes appends the list of the shape types that are used within type t to
+// listp. The type traversal is simplified for two reasons: (1) we can always stop a
+// type traversal when t.HasShape() is false; and (2) shape types can't appear inside
+// a named type, except for the type args of a generic type. So, the traversal will
+// always stop before we have to deal with recursive types.
+func getShapes(t *types.Type, listp *[]*types.Type) {
+ if !t.HasShape() {
+ return
+ }
+ if t.IsShape() {
+ *listp = append(*listp, t)
+ return
+ }
+
+ if t.Sym() != nil {
+ // A named type can't have shapes in it, except for type args of a
+ // generic type. We will have to deal with this differently once we
+ // alloc local types in generic functions (#47631).
+ for _, rparam := range t.RParams() {
+ getShapes(rparam, listp)
+ }
+ return
+ }
+
+ switch t.Kind() {
+ case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN:
+ getShapes(t.Elem(), listp)
+
+ case types.TSTRUCT:
+ for _, f := range t.FieldSlice() {
+ getShapes(f.Type, listp)
+ }
+
+ case types.TFUNC:
+ for _, f := range t.Recvs().FieldSlice() {
+ getShapes(f.Type, listp)
+ }
+ for _, f := range t.Params().FieldSlice() {
+ getShapes(f.Type, listp)
+ }
+ for _, f := range t.Results().FieldSlice() {
+ getShapes(f.Type, listp)
+ }
+ for _, f := range t.TParams().FieldSlice() {
+ getShapes(f.Type, listp)
+ }
+
+ case types.TINTER:
+ for _, f := range t.Methods().Slice() {
+ getShapes(f.Type, listp)
+ }
+
+ case types.TMAP:
+ getShapes(t.Key(), listp)
+ getShapes(t.Elem(), listp)
+
+ default:
+ panic(fmt.Sprintf("Bad type in getShapes: %v", t.Kind()))
+ }
+
+}
+
// Shapify takes a concrete type and a type param index, and returns a GCshape type that can
// be used in place of the input type and still generate identical code.
// No methods are added - all methods calls directly on a shape should
@@ -1410,12 +1494,40 @@
// For now, we only consider two types to have the same shape, if they have exactly
// the same underlying type or they are both pointer types.
//
+// tparam is the associated typeparam - it must be TTYPEPARAM type. If there is a
+// structural type for the associated type param (not common), then a pointer type t
+// is mapped to its underlying type, rather than being merged with other pointers.
+//
// Shape types are also distinguished by the index of the type in a type param/arg
// list. We need to do this so we can distinguish and substitute properly for two
// type params in the same function that have the same shape for a particular
// instantiation.
-func Shapify(t *types.Type, index int) *types.Type {
+func Shapify(t *types.Type, index int, tparam *types.Type) *types.Type {
assert(!t.IsShape())
+ if t.HasShape() {
+ // We are sometimes dealing with types from a shape instantiation
+ // that were constructed from existing shape types, so t may
+ // sometimes have shape types inside it. In that case, we find all
+ // those shape types with getShapes() and replace them with their
+ // underlying type.
+ //
+ // If we don't do this, we may create extra unneeded shape types that
+ // have these other shape types embedded in them. This may lead to
+ // generating extra shape instantiations, and a mismatch between the
+ // instantiations that we used in generating dictionaries and the
+ // instantations that are actually called. (#51303).
+ list := []*types.Type{}
+ getShapes(t, &list)
+ list2 := make([]*types.Type, len(list))
+ for i, shape := range list {
+ list2[i] = shape.Underlying()
+ }
+ ts := Tsubster{
+ Tparams: list,
+ Targs: list2,
+ }
+ t = ts.Typ(t)
+ }
// Map all types with the same underlying type to the same shape.
u := t.Underlying()
@@ -1423,7 +1535,8 @@
// TODO: Make unsafe.Pointer the same shape as normal pointers.
// Note: pointers to arrays are special because of slice-to-array-pointer
// conversions. See issue 49295.
- if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY {
+ if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY &&
+ tparam.Bound().StructuralType() == nil {
u = types.Types[types.TUINT8].PtrTo()
}
@@ -1453,6 +1566,7 @@
s.SetUnderlying(u)
s.SetIsShape(true)
s.SetHasShape(true)
+ types.CalcSize(s)
name.SetType(s)
name.SetTypecheck(1)
submap[u] = s
diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go
index 42970f6..f6be298 100644
--- a/src/cmd/compile/internal/typecheck/typecheck.go
+++ b/src/cmd/compile/internal/typecheck/typecheck.go
@@ -129,7 +129,11 @@
var typecheckdefstack []*ir.Name
-// Resolve ONONAME to definition, if any.
+// Resolve resolves an ONONAME node to a definition, if any. If n is not an ONONAME node,
+// Resolve returns n unchanged. If n is an ONONAME node and not in the same package,
+// then n.Sym() is resolved using import data. Otherwise, Resolve returns
+// n.Sym().Def. An ONONAME node can be created using ir.NewIdent(), so an imported
+// symbol can be resolved via Resolve(ir.NewIdent(src.NoXPos, sym)).
func Resolve(n ir.Node) (res ir.Node) {
if n == nil || n.Op() != ir.ONONAME {
return n
diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go
index 3198a1f..c7d0623 100644
--- a/src/cmd/compile/internal/types/fmt.go
+++ b/src/cmd/compile/internal/types/fmt.go
@@ -72,6 +72,7 @@
fmtDebug
fmtTypeID
fmtTypeIDName
+ fmtTypeIDHash
)
// Sym
@@ -144,10 +145,21 @@
if q := pkgqual(s.Pkg, verb, mode); q != "" {
b.WriteString(q)
b.WriteByte('.')
- if mode == fmtTypeIDName {
+ switch mode {
+ case fmtTypeIDName:
// If name is a generic instantiation, it might have local package placeholders
// in it. Replace those placeholders with the package name. See issue 49547.
name = strings.Replace(name, LocalPkg.Prefix, q, -1)
+ case fmtTypeIDHash:
+ // If name is a generic instantiation, don't hash the instantiating types.
+ // This isn't great, but it is safe. If we hash the instantiating types, then
+ // we need to make sure they have just the package name. At this point, they
+ // either have "", or the whole package path, and it is hard to reconcile
+ // the two without depending on -p (which we might do someday).
+ // See issue 51250.
+ if i := strings.Index(name, "["); i >= 0 {
+ name = name[:i]
+ }
}
}
b.WriteString(name)
@@ -173,7 +185,7 @@
case fmtDebug:
return pkg.Name
- case fmtTypeIDName:
+ case fmtTypeIDName, fmtTypeIDHash:
// dcommontype, typehash
return pkg.Name
@@ -331,7 +343,7 @@
if t == AnyType || t == ByteType || t == RuneType {
// in %-T mode collapse predeclared aliases with their originals.
switch mode {
- case fmtTypeIDName, fmtTypeID:
+ case fmtTypeIDName, fmtTypeIDHash, fmtTypeID:
t = Types[t.Kind()]
default:
sconv2(b, t.Sym(), 'S', mode)
@@ -422,7 +434,7 @@
case TPTR:
b.WriteByte('*')
switch mode {
- case fmtTypeID, fmtTypeIDName:
+ case fmtTypeID, fmtTypeIDName, fmtTypeIDHash:
if verb == 'S' {
tconv2(b, t.Elem(), 'S', mode, visited)
return
@@ -484,7 +496,7 @@
case IsExported(f.Sym.Name):
sconv2(b, f.Sym, 'S', mode)
default:
- if mode != fmtTypeIDName {
+ if mode != fmtTypeIDName && mode != fmtTypeIDHash {
mode = fmtTypeID
}
sconv2(b, f.Sym, 'v', mode)
@@ -554,7 +566,7 @@
b.WriteByte(byte(open))
fieldVerb := 'v'
switch mode {
- case fmtTypeID, fmtTypeIDName, fmtGo:
+ case fmtTypeID, fmtTypeIDName, fmtTypeIDHash, fmtGo:
// no argument names on function signature, and no "noescape"/"nosplit" tags
fieldVerb = 'S'
}
@@ -631,6 +643,7 @@
}
var name string
+ nameSep := " "
if verb != 'S' {
s := f.Sym
@@ -639,7 +652,47 @@
s = OrigSym(s)
}
- if s != nil && f.Embedded == 0 {
+ // Using type aliases and embedded fields, it's possible to
+ // construct types that can't be directly represented as a
+ // type literal. For example, given "type Int = int" (#50190),
+ // it would be incorrect to format "struct{ Int }" as either
+ // "struct{ int }" or "struct{ Int int }", because those each
+ // represent other, distinct types.
+ //
+ // So for the purpose of LinkString (i.e., fmtTypeID), we use
+ // the non-standard syntax "struct{ Int = int }" to represent
+ // embedded fields that have been renamed through the use of
+ // type aliases.
+ if f.Embedded != 0 {
+ if mode == fmtTypeID {
+ nameSep = " = "
+
+ // Compute tsym, the symbol that would normally be used as
+ // the field name when embedding f.Type.
+ // TODO(mdempsky): Check for other occurrences of this logic
+ // and deduplicate.
+ typ := f.Type
+ if typ.IsPtr() {
+ base.Assertf(typ.Sym() == nil, "embedded pointer type has name: %L", typ)
+ typ = typ.Elem()
+ }
+ tsym := typ.Sym()
+
+ // If the field name matches the embedded type's name, then
+ // suppress printing of the field name. For example, format
+ // "struct{ T }" as simply that instead of "struct{ T = T }".
+ if tsym != nil && (s == tsym || IsExported(tsym.Name) && s.Name == tsym.Name) {
+ s = nil
+ }
+ } else {
+ // Suppress the field name for embedded fields for
+ // non-LinkString formats, to match historical behavior.
+ // TODO(mdempsky): Re-evaluate this.
+ s = nil
+ }
+ }
+
+ if s != nil {
if funarg != FunargNone {
name = fmt.Sprint(f.Nname)
} else if verb == 'L' {
@@ -647,7 +700,7 @@
if name == ".F" {
name = "F" // Hack for toolstash -cmp.
}
- if !IsExported(name) && mode != fmtTypeIDName {
+ if !IsExported(name) && mode != fmtTypeIDName && mode != fmtTypeIDHash {
name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg)
}
} else {
@@ -658,7 +711,7 @@
if name != "" {
b.WriteString(name)
- b.WriteString(" ")
+ b.WriteString(nameSep)
}
if f.IsDDD() {
@@ -715,7 +768,7 @@
// TypeHash computes a hash value for type t to use in type switch statements.
func TypeHash(t *Type) uint32 {
- p := t.NameString()
+ p := tconv(t, 0, fmtTypeIDHash)
// Using MD5 is overkill, but reduces accidental collisions.
h := md5.Sum([]byte(p))
diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go
index a164b84..60a0f2e 100644
--- a/src/cmd/compile/internal/types/identity.go
+++ b/src/cmd/compile/internal/types/identity.go
@@ -59,12 +59,13 @@
case TINT32:
return (t1 == Types[TINT32] || t1 == RuneType) && (t2 == Types[TINT32] || t2 == RuneType)
case TINTER:
- // Make sure named any type matches any empty interface
+ // Make sure named any type matches any unnamed empty interface
// (but not a shape type, if identStrict).
+ isUnnamedEface := func(t *Type) bool { return t.IsEmptyInterface() && t.Sym() == nil }
if flags&identStrict != 0 {
- return t1 == AnyType && t2.IsEmptyInterface() && !t2.HasShape() || t2 == AnyType && t1.IsEmptyInterface() && !t1.HasShape()
+ return t1 == AnyType && isUnnamedEface(t2) && !t2.HasShape() || t2 == AnyType && isUnnamedEface(t1) && !t1.HasShape()
}
- return t1 == AnyType && t2.IsEmptyInterface() || t2 == AnyType && t1.IsEmptyInterface()
+ return t1 == AnyType && isUnnamedEface(t2) || t2 == AnyType && isUnnamedEface(t1)
default:
return false
}
diff --git a/src/cmd/compile/internal/types/pkg.go b/src/cmd/compile/internal/types/pkg.go
index 0b822a4..b159eb5 100644
--- a/src/cmd/compile/internal/types/pkg.go
+++ b/src/cmd/compile/internal/types/pkg.go
@@ -9,7 +9,6 @@
"cmd/internal/objabi"
"fmt"
"sort"
- "strings"
"sync"
)
@@ -49,9 +48,11 @@
p := new(Pkg)
p.Path = path
p.Name = name
- if strings.HasPrefix(path, "go.") && !strings.Contains(path, "/") {
- // Special compiler-internal packages don't need to be escaped.
- // This particularly helps with the go.shape package.
+ if path == "go.shape" {
+ // Don't escape "go.shape", since it's not needed (it's a builtin
+ // package), and we don't want escape codes showing up in shape type
+ // names, which also appear in names of function/method
+ // instantiations.
p.Prefix = path
} else {
p.Prefix = objabi.PathToPrefix(path)
diff --git a/src/cmd/compile/internal/types/structuraltype.go b/src/cmd/compile/internal/types/structuraltype.go
new file mode 100644
index 0000000..ee1341b
--- /dev/null
+++ b/src/cmd/compile/internal/types/structuraltype.go
@@ -0,0 +1,191 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+// Implementation of structural type computation for types.
+
+// TODO: we would like to depend only on the types2 computation of structural type,
+// but we can only do that the next time we change the export format and export
+// structural type info along with each constraint type, since the compiler imports
+// types directly into types1 format.
+
+// A term describes elementary type sets:
+//
+// term{false, T} set of type T
+// term{true, T} set of types with underlying type t
+// term{} empty set (we specifically check for typ == nil)
+type term struct {
+ tilde bool
+ typ *Type
+}
+
+// StructuralType returns the structural type of an interface, or nil if it has no
+// structural type.
+func (t *Type) StructuralType() *Type {
+ sts, _ := specificTypes(t)
+ var su *Type
+ for _, st := range sts {
+ u := st.typ.Underlying()
+ if su != nil {
+ u = match(su, u)
+ if u == nil {
+ return nil
+ }
+ }
+ // su == nil || match(su, u) != nil
+ su = u
+ }
+ return su
+}
+
+// If x and y are identical, match returns x.
+// If x and y are identical channels but for their direction
+// and one of them is unrestricted, match returns the channel
+// with the restricted direction.
+// In all other cases, match returns nil.
+// x and y are assumed to be underlying types, hence are not named types.
+func match(x, y *Type) *Type {
+ if IdenticalStrict(x, y) {
+ return x
+ }
+
+ if x.IsChan() && y.IsChan() && IdenticalStrict(x.Elem(), y.Elem()) {
+ // We have channels that differ in direction only.
+ // If there's an unrestricted channel, select the restricted one.
+ // If both have the same direction, return x (either is fine).
+ switch {
+ case x.ChanDir().CanSend() && x.ChanDir().CanRecv():
+ return y
+ case y.ChanDir().CanSend() && y.ChanDir().CanRecv():
+ return x
+ }
+ }
+ return nil
+}
+
+// specificTypes returns the list of specific types of an interface type or nil if
+// there are none. It also returns a flag that indicates, for an empty term list
+// result, whether it represents the empty set, or the infinite set of all types (in
+// both cases, there are no specific types).
+func specificTypes(t *Type) (list []term, inf bool) {
+ t.wantEtype(TINTER)
+
+ // We have infinite term list before processing any type elements
+ // (or if there are no type elements).
+ inf = true
+ for _, m := range t.Methods().Slice() {
+ var r2 []term
+ inf2 := false
+
+ switch {
+ case m.IsMethod():
+ inf2 = true
+
+ case m.Type.IsUnion():
+ nt := m.Type.NumTerms()
+ for i := 0; i < nt; i++ {
+ t, tilde := m.Type.Term(i)
+ if t.IsInterface() {
+ r3, r3inf := specificTypes(t)
+ if r3inf {
+ // Union with an infinite set of types is
+ // infinite, so skip remaining terms.
+ r2 = nil
+ inf2 = true
+ break
+ }
+ // Add the elements of r3 to r2.
+ for _, r3e := range r3 {
+ r2 = insertType(r2, r3e)
+ }
+ } else {
+ r2 = insertType(r2, term{tilde, t})
+ }
+ }
+
+ case m.Type.IsInterface():
+ r2, inf2 = specificTypes(m.Type)
+
+ default:
+ // m.Type is a single non-interface type, so r2 is just a
+ // one-element list, inf2 is false.
+ r2 = []term{{false, m.Type}}
+ }
+
+ if inf2 {
+ // If the current type element has infinite types,
+ // its intersection with r is just r, so skip this type element.
+ continue
+ }
+
+ if inf {
+ // If r is infinite, then the intersection of r and r2 is just r2.
+ list = r2
+ inf = false
+ continue
+ }
+
+ // r and r2 are finite, so intersect r and r2.
+ var r3 []term
+ for _, re := range list {
+ for _, r2e := range r2 {
+ if tm := intersect(re, r2e); tm.typ != nil {
+ r3 = append(r3, tm)
+ }
+ }
+ }
+ list = r3
+ }
+ return
+}
+
+// insertType adds t to the returned list if it is not already in list.
+func insertType(list []term, tm term) []term {
+ for i, elt := range list {
+ if new := union(elt, tm); new.typ != nil {
+ // Replace existing elt with the union of elt and new.
+ list[i] = new
+ return list
+ }
+ }
+ return append(list, tm)
+}
+
+// If x and y are disjoint, return term with nil typ (which means the union should
+// include both types). If x and y are not disjoint, return the single type which is
+// the union of x and y.
+func union(x, y term) term {
+ if disjoint(x, y) {
+ return term{false, nil}
+ }
+ if x.tilde || !y.tilde {
+ return x
+ }
+ return y
+}
+
+// intersect returns the intersection x ∩ y.
+func intersect(x, y term) term {
+ if disjoint(x, y) {
+ return term{false, nil}
+ }
+ if !x.tilde || y.tilde {
+ return x
+ }
+ return y
+}
+
+// disjoint reports whether x ∩ y == ∅.
+func disjoint(x, y term) bool {
+ ux := x.typ
+ if y.tilde {
+ ux = ux.Underlying()
+ }
+ uy := y.typ
+ if x.tilde {
+ uy = uy.Underlying()
+ }
+ return !IdenticalStrict(ux, uy)
+}
diff --git a/src/cmd/compile/internal/types/structuraltype_test.go b/src/cmd/compile/internal/types/structuraltype_test.go
new file mode 100644
index 0000000..fc34458
--- /dev/null
+++ b/src/cmd/compile/internal/types/structuraltype_test.go
@@ -0,0 +1,135 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that StructuralType() calculates the correct value of structural type for
+// unusual cases.
+
+package types
+
+import (
+ "cmd/internal/src"
+ "testing"
+)
+
+type test struct {
+ typ *Type
+ structuralType *Type
+}
+
+func TestStructuralType(t *testing.T) {
+ // These are the few constants that need to be initialized in order to use
+ // the types package without using the typecheck package by calling
+ // typecheck.InitUniverse() (the normal way to initialize the types package).
+ PtrSize = 8
+ RegSize = 8
+ MaxWidth = 1 << 50
+
+ // type intType = int
+ intType := newType(TINT)
+ // type structf = struct { f int }
+ structf := NewStruct(nil, []*Field{
+ NewField(src.NoXPos, LocalPkg.Lookup("f"), intType),
+ })
+
+ // type Sf structf
+ Sf := newType(TFORW)
+ Sf.sym = LocalPkg.Lookup("Sf")
+ Sf.SetUnderlying(structf)
+
+ // type A int
+ A := newType(TFORW)
+ A.sym = LocalPkg.Lookup("A")
+ A.SetUnderlying(intType)
+
+ // type B int
+ B := newType(TFORW)
+ B.sym = LocalPkg.Lookup("B")
+ B.SetUnderlying(intType)
+
+ emptyInterface := NewInterface(BuiltinPkg, []*Field{}, false)
+ any := newType(TFORW)
+ any.sym = LocalPkg.Lookup("any")
+ any.SetUnderlying(emptyInterface)
+
+ // The tests marked NONE have no structural type; all the others have a
+ // structural type of structf - "struct { f int }"
+ tests := []*test{
+ {
+ // interface { struct { f int } }
+ embed(structf),
+ structf,
+ },
+ {
+ // interface { struct { f int }; any }
+ embed(structf, any),
+ structf,
+ },
+ {
+ // interface { Sf }
+ embed(Sf),
+ structf,
+ },
+ {
+ // interface { any | Sf }
+ embed(any, Sf),
+ structf,
+ },
+ {
+ // interface { struct { f int }; Sf } - NONE
+ embed(structf, Sf),
+ nil,
+ },
+ {
+ // interface { struct { f int } | ~struct { f int } }
+ embed(NewUnion([]*Type{structf, structf}, []bool{false, true})),
+ structf,
+ },
+ {
+ // interface { ~struct { f int } ; Sf }
+ embed(NewUnion([]*Type{structf}, []bool{true}), Sf),
+ structf,
+ },
+ {
+ // interface { struct { f int } ; Sf } - NONE
+ embed(NewUnion([]*Type{structf}, []bool{false}), Sf),
+ nil,
+ },
+ {
+ // interface { Sf | A; B | Sf}
+ embed(NewUnion([]*Type{Sf, A}, []bool{false, false}),
+ NewUnion([]*Type{B, Sf}, []bool{false, false})),
+ structf,
+ },
+ {
+ // interface { Sf | A; A | Sf } - NONE
+ embed(NewUnion([]*Type{Sf, A}, []bool{false, false}),
+ NewUnion([]*Type{A, Sf}, []bool{false, false})),
+ nil,
+ },
+ {
+ // interface { Sf | any } - NONE
+ embed(NewUnion([]*Type{Sf, any}, []bool{false, false})),
+ nil,
+ },
+ {
+ // interface { Sf | any; Sf }
+ embed(NewUnion([]*Type{Sf, any}, []bool{false, false}), Sf),
+ structf,
+ },
+ }
+ for _, tst := range tests {
+ if got, want := tst.typ.StructuralType(), tst.structuralType; got != want {
+ t.Errorf("StructuralType(%v) = %v, wanted %v",
+ tst.typ, got, want)
+ }
+ }
+}
+
+func embed(types ...*Type) *Type {
+ fields := make([]*Field, len(types))
+ for i, t := range types {
+ fields[i] = NewField(src.NoXPos, nil, t)
+ }
+ return NewInterface(LocalPkg, fields, false)
+}
diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go
index 7d22e2d..fe352e0 100644
--- a/src/cmd/compile/internal/types/type.go
+++ b/src/cmd/compile/internal/types/type.go
@@ -75,7 +75,7 @@
TNIL
TBLANK
- // pseudo-types for frame layout
+ // pseudo-types used temporarily only during frame layout (CalcSize())
TFUNCARGS
TCHANARGS
@@ -136,6 +136,14 @@
)
// A Type represents a Go type.
+//
+// There may be multiple unnamed types with identical structure. However, there must
+// be a unique Type object for each unique named (defined) type. After noding, a
+// package-level type can be looked up by building its unique symbol sym (sym =
+// package.Lookup(name)) and checking sym.Def. If sym.Def is non-nil, the type
+// already exists at package scope and is available at sym.Def.(*ir.Name).Type().
+// Local types (which may have the same name as a package-level type) are
+// distinguished by the value of vargen.
type Type struct {
// extra contains extra etype-specific fields.
// As an optimization, those etype-specific structs which contain exactly
@@ -154,6 +162,7 @@
// TSLICE: Slice
// TSSA: string
// TTYPEPARAM: *Typeparam
+ // TUNION: *Union
extra interface{}
// width is the width of this Type in bytes.
@@ -230,7 +239,7 @@
// Generic types should never have alg functions.
func (t *Type) SetHasTParam(b bool) { t.flags.set(typeHasTParam, b); t.flags.set(typeNoalg, b) }
-// Should always do SetHasShape(true) when doing SeIsShape(true).
+// Should always do SetHasShape(true) when doing SetIsShape(true).
func (t *Type) SetIsShape(b bool) { t.flags.set(typeIsShape, b) }
func (t *Type) SetHasShape(b bool) { t.flags.set(typeHasShape, b) }
@@ -494,13 +503,17 @@
Embedded uint8 // embedded field
- Pos src.XPos
+ Pos src.XPos
+
+ // Name of field/method/parameter. Can be nil for interface fields embedded
+ // in interfaces and unnamed parameters.
Sym *Sym
Type *Type // field type
Note string // literal string annotation
- // For fields that represent function parameters, Nname points
- // to the associated ONAME Node.
+ // For fields that represent function parameters, Nname points to the
+ // associated ONAME Node. For fields that represent methods, Nname points to
+ // the function name node.
Nname Object
// Offset in bytes of this field or method within its enclosing struct
@@ -1018,7 +1031,9 @@
}
// AllMethods returns a pointer to all the methods (including embedding) for type t.
-// For an interface type, this is the set of methods that are typically iterated over.
+// For an interface type, this is the set of methods that are typically iterated
+// over. For non-interface types, AllMethods() only returns a valid result after
+// CalcMethods() has been called at least once.
func (t *Type) AllMethods() *Fields {
if t.kind == TINTER {
// Calculate the full method set of an interface type on the fly
@@ -1749,8 +1764,9 @@
t.vargen = typeGen
}
-// SetUnderlying sets the underlying type. SetUnderlying automatically updates any
-// types that were waiting for this type to be completed.
+// SetUnderlying sets the underlying type of an incomplete type (i.e. type whose kind
+// is currently TFORW). SetUnderlying automatically updates any types that were waiting
+// for this type to be completed.
func (t *Type) SetUnderlying(underlying *Type) {
if underlying.kind == TFORW {
// This type isn't computed yet; when it is, update n.
@@ -2210,4 +2226,5 @@
var SimType [NTYPE]Kind
+// Fake package for shape types (see typecheck.Shapify()).
var ShapePkg = NewPkg("go.shape", "go.shape")
diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go
index 54b04bd..55ed7bd 100644
--- a/src/cmd/compile/internal/types/universe.go
+++ b/src/cmd/compile/internal/types/universe.go
@@ -152,7 +152,7 @@
return NewInterface(NoPkg, []*Field{method}, false)
}
-// makeComparableInterface makes the the predefined "comparable" interface in the
+// makeComparableInterface makes the predefined "comparable" interface in the
// built-in package. It has a unique name, but no methods.
func makeComparableInterface() *Type {
return NewInterface(NoPkg, nil, false)
diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go
index ed5bced..d864c96 100644
--- a/src/cmd/compile/internal/types2/api.go
+++ b/src/cmd/compile/internal/types2/api.go
@@ -202,20 +202,14 @@
// identifier z in a variable declaration 'var z int' is found
// only in the Defs map, and identifiers denoting packages in
// qualified identifiers are collected in the Uses map.
- //
- // For binary expressions representing unions in constraint
- // position or type elements in interfaces, a union type is
- // recorded for the top-level expression only. For instance,
- // given the constraint a|b|c, the union type for (a|b)|c
- // is recorded, but not the union type for a|b.
Types map[syntax.Expr]TypeAndValue
- // Instances maps identifiers denoting parameterized types or functions to
- // their type arguments and instantiated type.
+ // Instances maps identifiers denoting generic types or functions to their
+ // type arguments and instantiated type.
//
// For example, Instances will map the identifier for 'T' in the type
// instantiation T[int, string] to the type arguments [int, string] and
- // resulting instantiated *Named type. Given a parameterized function
+ // resulting instantiated *Named type. Given a generic function
// func F[A any](A), Instances will map the identifier for 'F' in the call
// expression F(int(1)) to the inferred type arguments [int], and resulting
// instantiated *Signature.
@@ -271,6 +265,7 @@
//
// *syntax.File
// *syntax.FuncType
+ // *syntax.TypeDecl
// *syntax.BlockStmt
// *syntax.IfStmt
// *syntax.SwitchStmt
@@ -426,25 +421,45 @@
}
// AssertableTo reports whether a value of type V can be asserted to have type T.
+//
+// The behavior of AssertableTo is undefined in two cases:
+// - if V is a generalized interface; i.e., an interface that may only be used
+// as a type constraint in Go code
+// - if T is an uninstantiated generic type
func AssertableTo(V *Interface, T Type) bool {
- m, _ := (*Checker)(nil).assertableTo(V, T)
- return m == nil
+ // Checker.newAssertableTo suppresses errors for invalid types, so we need special
+ // handling here.
+ if T.Underlying() == Typ[Invalid] {
+ return false
+ }
+ return (*Checker)(nil).newAssertableTo(V, T) == nil
}
-// AssignableTo reports whether a value of type V is assignable to a variable of type T.
+// AssignableTo reports whether a value of type V is assignable to a variable
+// of type T.
+//
+// The behavior of AssignableTo is undefined if V or T is an uninstantiated
+// generic type.
func AssignableTo(V, T Type) bool {
x := operand{mode: value, typ: V}
ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
return ok
}
-// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
+// ConvertibleTo reports whether a value of type V is convertible to a value of
+// type T.
+//
+// The behavior of ConvertibleTo is undefined if V or T is an uninstantiated
+// generic type.
func ConvertibleTo(V, T Type) bool {
x := operand{mode: value, typ: V}
return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
}
// Implements reports whether type V implements interface T.
+//
+// The behavior of Implements is undefined if V is an uninstantiated generic
+// type.
func Implements(V Type, T *Interface) bool {
if T.Empty() {
// All types (even Typ[Invalid]) implement the empty interface.
@@ -455,7 +470,7 @@
if V.Underlying() == Typ[Invalid] {
return false
}
- return (*Checker)(nil).implements(V, T, nil) == nil
+ return (*Checker)(nil).implements(V, T) == nil
}
// Identical reports whether x and y are identical types.
diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go
index fc8b5cd..5bb5517 100644
--- a/src/cmd/compile/internal/types2/api_test.go
+++ b/src/cmd/compile/internal/types2/api_test.go
@@ -12,6 +12,7 @@
"internal/testenv"
"reflect"
"regexp"
+ "sort"
"strings"
"testing"
@@ -25,7 +26,7 @@
func parseSrc(path, src string) (*syntax.File, error) {
errh := func(error) {} // dummy error handler so that parsing continues in presence of errors
- return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, syntax.AllowGenerics)
+ return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, syntax.AllowGenerics|syntax.AllowMethodTypeParams)
}
func pkgFor(path, source string, info *Info) (*Package, error) {
@@ -109,7 +110,6 @@
{`package c5d; var _ = string(65)`, `65`, `untyped int`, `65`},
{`package c5e; var _ = string('A')`, `'A'`, `untyped rune`, `65`},
{`package c5f; type T string; var _ = T('A')`, `'A'`, `untyped rune`, `65`},
- {`package c5g; var s uint; var _ = string(1 << s)`, `1 << s`, `untyped int`, ``},
{`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
{`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
@@ -348,10 +348,25 @@
{`package u1a; func _[_ interface{~int}]() {}`, `~int`, `~int`},
{`package u2a; func _[_ interface{int|string}]() {}`, `int | string`, `int|string`},
{`package u3a; func _[_ interface{int|string|~bool}]() {}`, `int | string | ~bool`, `int|string|~bool`},
+ {`package u3a; func _[_ interface{int|string|~bool}]() {}`, `int | string`, `int|string`},
+ {`package u3a; func _[_ interface{int|string|~bool}]() {}`, `~bool`, `~bool`},
+ {`package u3a; func _[_ interface{int|string|~float64|~bool}]() {}`, `int | string | ~float64`, `int|string|~float64`},
+
{`package u0b; func _[_ int]() {}`, `int`, `int`},
{`package u1b; func _[_ ~int]() {}`, `~int`, `~int`},
{`package u2b; func _[_ int|string]() {}`, `int | string`, `int|string`},
{`package u3b; func _[_ int|string|~bool]() {}`, `int | string | ~bool`, `int|string|~bool`},
+ {`package u3b; func _[_ int|string|~bool]() {}`, `int | string`, `int|string`},
+ {`package u3b; func _[_ int|string|~bool]() {}`, `~bool`, `~bool`},
+ {`package u3b; func _[_ int|string|~float64|~bool]() {}`, `int | string | ~float64`, `int|string|~float64`},
+
+ {`package u0c; type _ interface{int}`, `int`, `int`},
+ {`package u1c; type _ interface{~int}`, `~int`, `~int`},
+ {`package u2c; type _ interface{int|string}`, `int | string`, `int|string`},
+ {`package u3c; type _ interface{int|string|~bool}`, `int | string | ~bool`, `int|string|~bool`},
+ {`package u3c; type _ interface{int|string|~bool}`, `int | string`, `int|string`},
+ {`package u3c; type _ interface{int|string|~bool}`, `~bool`, `~bool`},
+ {`package u3c; type _ interface{int|string|~float64|~bool}`, `int | string | ~float64`, `int|string|~float64`},
}
for _, test := range tests {
@@ -389,69 +404,61 @@
}
func TestInstanceInfo(t *testing.T) {
- var tests = []struct {
- src string
+ const lib = `package lib
+
+func F[P any](P) {}
+
+type T[P any] []P
+`
+
+ type testInst struct {
name string
targs []string
typ string
+ }
+
+ var tests = []struct {
+ src string
+ instances []testInst // recorded instances in source order
}{
{`package p0; func f[T any](T) {}; func _() { f(42) }`,
- `f`,
- []string{`int`},
- `func(int)`,
+ []testInst{{`f`, []string{`int`}, `func(int)`}},
},
{`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
- `f`,
- []string{`rune`},
- `func(rune) rune`,
+ []testInst{{`f`, []string{`rune`}, `func(rune) rune`}},
},
{`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
- `f`,
- []string{`complex128`},
- `func(...complex128) complex128`,
+ []testInst{{`f`, []string{`complex128`}, `func(...complex128) complex128`}},
},
{`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
- `f`,
- []string{`float64`, `string`, `byte`},
- `func(float64, *string, []byte)`,
+ []testInst{{`f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`}},
},
{`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
- `f`,
- []string{`float64`, `byte`},
- `func(float64, *byte, ...[]byte)`,
+ []testInst{{`f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`}},
},
-
// we don't know how to translate these but we can type-check them
{`package q0; type T struct{}; func (T) m[P any](P) {}; func _(x T) { x.m(42) }`,
- `m`,
- []string{`int`},
- `func(int)`,
+ []testInst{{`m`, []string{`int`}, `func(int)`}},
},
{`package q1; type T struct{}; func (T) m[P any](P) P { panic(0) }; func _(x T) { x.m(42) }`,
- `m`,
- []string{`int`},
- `func(int) int`,
+ []testInst{{`m`, []string{`int`}, `func(int) int`}},
},
{`package q2; type T struct{}; func (T) m[P any](...P) P { panic(0) }; func _(x T) { x.m(42) }`,
- `m`,
- []string{`int`},
- `func(...int) int`,
+ []testInst{{`m`, []string{`int`}, `func(...int) int`}},
},
{`package q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C) {}; func _(x T) { x.m(1.2, new(string), []byte{}) }`,
- `m`,
- []string{`float64`, `string`, `byte`},
- `func(float64, *string, []byte)`,
+ []testInst{{`m`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`}},
},
{`package q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B) {}; func _(x T) { x.m(1.2, new(byte)) }`,
- `m`,
- []string{`float64`, `byte`},
- `func(float64, *byte, ...[]byte)`,
+ []testInst{{`m`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`}},
},
- {`package r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q) {}; func _[P any](x T[P]) { x.m(42) }`,
- `m`,
- []string{`int`},
- `func(int)`,
+ {`package r0; type T[P1 any] struct{}; func (_ T[P2]) m[Q any](Q) {}; func _[P3 any](x T[P3]) { x.m(42) }`,
+ []testInst{
+ {`T`, []string{`P2`}, `struct{}`},
+ {`T`, []string{`P3`}, `struct{}`},
+ {`m`, []string{`int`}, `func(int)`},
+ },
},
// TODO(gri) record method type parameters in syntax.FuncType so we can check this
// {`package r1; type T interface{ m[P any](P) }; func _(x T) { x.m(4.2) }`,
@@ -460,97 +467,113 @@
// `func(float64)`,
// },
- {`package s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`,
- `f`,
- []string{`string`, `*string`},
- `func(x string)`,
+ {`package s1; func f[T any, P interface{*T}](x T) {}; func _(x string) { f(x) }`,
+ []testInst{{`f`, []string{`string`, `*string`}, `func(x string)`}},
},
- {`package s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `*int`},
- `func(x []int)`,
+ {`package s2; func f[T any, P interface{*T}](x []T) {}; func _(x []int) { f(x) }`,
+ []testInst{{`f`, []string{`int`, `*int`}, `func(x []int)`}},
},
- {`package s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `chan<- int`},
- `func(x []int)`,
+ {`package s3; type C[T any] interface{chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
+ []testInst{
+ {`C`, []string{`T`}, `interface{chan<- T}`},
+ {`f`, []string{`int`, `chan<- int`}, `func(x []int)`},
+ },
},
- {`package s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
- `func(x []int)`,
+ {`package s4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
+ []testInst{
+ {`C`, []string{`T`}, `interface{chan<- T}`},
+ {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+ {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`},
+ },
},
- {`package t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`,
- `f`,
- []string{`string`, `*string`},
- `func() string`,
+ {`package t1; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = f[string] }`,
+ []testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
},
- {`package t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
- `f`,
- []string{`string`, `*string`},
- `func() string`,
+ {`package t2; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
+ []testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
},
- {`package t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
- `f`,
- []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
- `func() []int`,
+ {`package t3; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
+ []testInst{
+ {`C`, []string{`T`}, `interface{chan<- T}`},
+ {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+ {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
+ },
},
- {`package t4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
- `f`,
- []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
- `func() []int`,
+ {`package t4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = (f[int]) }`,
+ []testInst{
+ {`C`, []string{`T`}, `interface{chan<- T}`},
+ {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+ {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
+ },
},
- {`package i0; import lib "generic_lib"; func _() { lib.F(42) }`,
- `F`,
- []string{`int`},
- `func(int)`,
+ {`package i0; import "lib"; func _() { lib.F(42) }`,
+ []testInst{{`F`, []string{`int`}, `func(int)`}},
},
+
+ {`package duplfunc0; func f[T any](T) {}; func _() { f(42); f("foo"); f[int](3) }`,
+ []testInst{
+ {`f`, []string{`int`}, `func(int)`},
+ {`f`, []string{`string`}, `func(string)`},
+ {`f`, []string{`int`}, `func(int)`},
+ },
+ },
+ {`package duplfunc1; import "lib"; func _() { lib.F(42); lib.F("foo"); lib.F(3) }`,
+ []testInst{
+ {`F`, []string{`int`}, `func(int)`},
+ {`F`, []string{`string`}, `func(string)`},
+ {`F`, []string{`int`}, `func(int)`},
+ },
+ },
+
{`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`,
- `T`,
- []string{`int`},
- `struct{x int}`,
+ []testInst{{`T`, []string{`int`}, `struct{x int}`}},
},
{`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`,
- `T`,
- []string{`int`},
- `struct{x int}`,
+ []testInst{{`T`, []string{`int`}, `struct{x int}`}},
},
{`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`,
- `T`,
- []string{`int`},
- `struct{x int}`,
+ []testInst{{`T`, []string{`int`}, `struct{x int}`}},
},
{`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`,
- `T`,
- []string{`[]int`, `int`},
- `struct{x []int; y int}`,
+ []testInst{{`T`, []string{`[]int`, `int`}, `struct{x []int; y int}`}},
},
- {`package type4; import lib "generic_lib"; var _ lib.T[int]`,
- `T`,
- []string{`int`},
- `[]int`,
+ {`package type4; import "lib"; var _ lib.T[int]`,
+ []testInst{{`T`, []string{`int`}, `[]int`}},
+ },
+
+ {`package dupltype0; type T[P interface{~int}] struct{ x P }; var x T[int]; var y T[int]`,
+ []testInst{
+ {`T`, []string{`int`}, `struct{x int}`},
+ {`T`, []string{`int`}, `struct{x int}`},
+ },
+ },
+ {`package dupltype1; type T[P ~int] struct{ x P }; func (r *T[Q]) add(z T[Q]) { r.x += z.x }`,
+ []testInst{
+ {`T`, []string{`Q`}, `struct{x Q}`},
+ {`T`, []string{`Q`}, `struct{x Q}`},
+ },
+ },
+ {`package dupltype1; import "lib"; var x lib.T[int]; var y lib.T[int]; var z lib.T[string]`,
+ []testInst{
+ {`T`, []string{`int`}, `[]int`},
+ {`T`, []string{`int`}, `[]int`},
+ {`T`, []string{`string`}, `[]string`},
+ },
},
}
for _, test := range tests {
- const lib = `package generic_lib
-
-func F[P any](P) {}
-
-type T[P any] []P
-`
-
imports := make(testImporter)
conf := Config{Importer: imports}
- instances := make(map[*syntax.Name]Instance)
- uses := make(map[*syntax.Name]Object)
+ instMap := make(map[*syntax.Name]Instance)
+ useMap := make(map[*syntax.Name]Object)
makePkg := func(src string) *Package {
f, err := parseSrc("p.go", src)
if err != nil {
t.Fatal(err)
}
- pkg, err := conf.Check("", []*syntax.File{f}, &Info{Instances: instances, Uses: uses})
+ pkg, err := conf.Check("", []*syntax.File{f}, &Info{Instances: instMap, Uses: useMap})
if err != nil {
t.Fatal(err)
}
@@ -560,60 +583,72 @@
makePkg(lib)
pkg := makePkg(test.src)
- // look for instance information
- var targs []Type
- var typ Type
- for ident, inst := range instances {
- if syntax.String(ident) == test.name {
- for i := 0; i < inst.TypeArgs.Len(); i++ {
- targs = append(targs, inst.TypeArgs.At(i))
- }
- typ = inst.Type
+ t.Run(pkg.Name(), func(t *testing.T) {
+ // Sort instances in source order for stability.
+ instances := sortedInstances(instMap)
+ if got, want := len(instances), len(test.instances); got != want {
+ t.Fatalf("got %d instances, want %d", got, want)
+ }
- // Check that we can find the corresponding parameterized type.
- ptype := uses[ident].Type()
+ // Pairwise compare with the expected instances.
+ for ii, inst := range instances {
+ var targs []Type
+ for i := 0; i < inst.Inst.TypeArgs.Len(); i++ {
+ targs = append(targs, inst.Inst.TypeArgs.At(i))
+ }
+ typ := inst.Inst.Type
+
+ testInst := test.instances[ii]
+ if got := inst.Name.Value; got != testInst.name {
+ t.Fatalf("got name %s, want %s", got, testInst.name)
+ }
+
+ if len(targs) != len(testInst.targs) {
+ t.Fatalf("got %d type arguments; want %d", len(targs), len(testInst.targs))
+ }
+ for i, targ := range targs {
+ if got := targ.String(); got != testInst.targs[i] {
+ t.Errorf("type argument %d: got %s; want %s", i, got, testInst.targs[i])
+ }
+ }
+ if got := typ.Underlying().String(); got != testInst.typ {
+ t.Errorf("package %s: got %s; want %s", pkg.Name(), got, testInst.typ)
+ }
+
+ // Verify the invariant that re-instantiating the corresponding generic
+ // type with TypeArgs results in an identical instance.
+ ptype := useMap[inst.Name].Type()
lister, _ := ptype.(interface{ TypeParams() *TypeParamList })
if lister == nil || lister.TypeParams().Len() == 0 {
- t.Errorf("package %s: info.Types[%v] = %v, want parameterized type", pkg.Name(), ident, ptype)
- continue
+ t.Fatalf("info.Types[%v] = %v, want parameterized type", inst.Name, ptype)
}
-
- // Verify the invariant that re-instantiating the generic type with
- // TypeArgs results in an equivalent type.
inst2, err := Instantiate(nil, ptype, targs, true)
if err != nil {
t.Errorf("Instantiate(%v, %v) failed: %v", ptype, targs, err)
}
- if !Identical(inst.Type, inst2) {
- t.Errorf("%v and %v are not identical", inst.Type, inst2)
+ if !Identical(inst.Inst.Type, inst2) {
+ t.Errorf("%v and %v are not identical", inst.Inst.Type, inst2)
}
- break
}
- }
- if targs == nil {
- t.Errorf("package %s: no instance information found for %s", pkg.Name(), test.name)
- continue
- }
-
- // check that type arguments are correct
- if len(targs) != len(test.targs) {
- t.Errorf("package %s: got %d type arguments; want %d", pkg.Name(), len(targs), len(test.targs))
- continue
- }
- for i, targ := range targs {
- if got := targ.String(); got != test.targs[i] {
- t.Errorf("package %s, %d. type argument: got %s; want %s", pkg.Name(), i, got, test.targs[i])
- continue
- }
- }
-
- // check that the types match
- if got := typ.Underlying().String(); got != test.typ {
- t.Errorf("package %s: got %s; want %s", pkg.Name(), got, test.typ)
- }
+ })
}
}
+type recordedInstance struct {
+ Name *syntax.Name
+ Inst Instance
+}
+
+func sortedInstances(m map[*syntax.Name]Instance) (instances []recordedInstance) {
+ for id, inst := range m {
+ instances = append(instances, recordedInstance{id, inst})
+ }
+ sort.Slice(instances, func(i, j int) bool {
+ return instances[i].Name.Pos().Cmp(instances[j].Name.Pos()) < 0
+ })
+ return instances
+}
+
func TestDefsInfo(t *testing.T) {
var tests = []struct {
src string
@@ -626,6 +661,11 @@
{`package p3; type x int`, `x`, `type p3.x int`},
{`package p4; func f()`, `f`, `func p4.f()`},
{`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`},
+
+ // Tests using generics.
+ {`package g0; type x[T any] int`, `x`, `type g0.x[T any] int`},
+ {`package g1; func f[T any]() {}`, `f`, `func g1.f[T any]()`},
+ {`package g2; type x[T any] int; func (*x[_]) m() {}`, `m`, `func (*g2.x[_]).m()`},
}
for _, test := range tests {
@@ -664,6 +704,33 @@
{`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`},
{`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`},
{`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`},
+
+ // Tests using generics.
+ {`package g0; func _[T any]() { _ = x }; const x = 42`, `x`, `const g0.x untyped int`},
+ {`package g1; func _[T any](x T) { }`, `T`, `type parameter T any`},
+ {`package g2; type N[A any] int; var _ N[int]`, `N`, `type g2.N[A any] int`},
+ {`package g3; type N[A any] int; func (N[_]) m() {}`, `N`, `type g3.N[A any] int`},
+
+ // Uses of fields are instantiated.
+ {`package s1; type N[A any] struct{ a A }; var f = N[int]{}.a`, `a`, `field a int`},
+ {`package s1; type N[A any] struct{ a A }; func (r N[B]) m(b B) { r.a = b }`, `a`, `field a B`},
+
+ // Uses of methods are uses of the instantiated method.
+ {`package m0; type N[A any] int; func (r N[B]) m() { r.n() }; func (N[C]) n() {}`, `n`, `func (m0.N[B]).n()`},
+ {`package m1; type N[A any] int; func (r N[B]) m() { }; var f = N[int].m`, `m`, `func (m1.N[int]).m()`},
+ {`package m2; func _[A any](v interface{ m() A }) { v.m() }`, `m`, `func (interface).m() A`},
+ {`package m3; func f[A any]() interface{ m() A } { return nil }; var _ = f[int]().m()`, `m`, `func (interface).m() int`},
+ {`package m4; type T[A any] func() interface{ m() A }; var x T[int]; var y = x().m`, `m`, `func (interface).m() int`},
+ {`package m5; type T[A any] interface{ m() A }; func _[B any](t T[B]) { t.m() }`, `m`, `func (m5.T[B]).m() B`},
+ {`package m6; type T[A any] interface{ m() }; func _[B any](t T[B]) { t.m() }`, `m`, `func (m6.T[B]).m()`},
+ {`package m7; type T[A any] interface{ m() A }; func _(t T[int]) { t.m() }`, `m`, `func (m7.T[int]).m() int`},
+ {`package m8; type T[A any] interface{ m() }; func _(t T[int]) { t.m() }`, `m`, `func (m8.T[int]).m()`},
+ {`package m9; type T[A any] interface{ m() }; func _(t T[int]) { _ = t.m }`, `m`, `func (m9.T[int]).m()`},
+ {
+ `package m10; type E[A any] interface{ m() }; type T[B any] interface{ E[B]; n() }; func _(t T[int]) { t.m() }`,
+ `m`,
+ `func (m10.E[int]).m()`,
+ },
}
for _, test := range tests {
@@ -676,8 +743,10 @@
var use Object
for id, obj := range info.Uses {
if id.Value == test.obj {
+ if use != nil {
+ panic(fmt.Sprintf("multiple uses of %q", id.Value))
+ }
use = obj
- break
}
}
if use == nil {
@@ -691,6 +760,89 @@
}
}
+func TestGenericMethodInfo(t *testing.T) {
+ src := `package p
+
+type N[A any] int
+
+func (r N[B]) m() { r.m(); r.n() }
+
+func (r *N[C]) n() { }
+`
+ f, err := parseSrc("p.go", src)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info := Info{
+ Defs: make(map[*syntax.Name]Object),
+ Uses: make(map[*syntax.Name]Object),
+ Selections: make(map[*syntax.SelectorExpr]*Selection),
+ }
+ var conf Config
+ pkg, err := conf.Check("p", []*syntax.File{f}, &info)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ N := pkg.Scope().Lookup("N").Type().(*Named)
+
+ // Find the generic methods stored on N.
+ gm, gn := N.Method(0), N.Method(1)
+ if gm.Name() == "n" {
+ gm, gn = gn, gm
+ }
+
+ // Collect objects from info.
+ var dm, dn *Func // the declared methods
+ var dmm, dmn *Func // the methods used in the body of m
+ for _, decl := range f.DeclList {
+ fdecl, ok := decl.(*syntax.FuncDecl)
+ if !ok {
+ continue
+ }
+ def := info.Defs[fdecl.Name].(*Func)
+ switch fdecl.Name.Value {
+ case "m":
+ dm = def
+ syntax.Inspect(fdecl.Body, func(n syntax.Node) bool {
+ if call, ok := n.(*syntax.CallExpr); ok {
+ sel := call.Fun.(*syntax.SelectorExpr)
+ use := info.Uses[sel.Sel].(*Func)
+ selection := info.Selections[sel]
+ if selection.Kind() != MethodVal {
+ t.Errorf("Selection kind = %v, want %v", selection.Kind(), MethodVal)
+ }
+ if selection.Obj() != use {
+ t.Errorf("info.Selections contains %v, want %v", selection.Obj(), use)
+ }
+ switch sel.Sel.Value {
+ case "m":
+ dmm = use
+ case "n":
+ dmn = use
+ }
+ }
+ return true
+ })
+ case "n":
+ dn = def
+ }
+ }
+
+ if gm != dm {
+ t.Errorf(`N.Method(...) returns %v for "m", but Info.Defs has %v`, gm, dm)
+ }
+ if gn != dn {
+ t.Errorf(`N.Method(...) returns %v for "m", but Info.Defs has %v`, gm, dm)
+ }
+ if dmm != dm {
+ t.Errorf(`Inside "m", r.m uses %v, want the defined func %v`, dmm, dm)
+ }
+ if dmn == dn {
+ t.Errorf(`Inside "m", r.n uses %v, want a func distinct from %v`, dmm, dm)
+ }
+}
+
func TestImplicitsInfo(t *testing.T) {
testenv.MustHaveGoBuild(t)
@@ -711,6 +863,17 @@
{`package p8; func f(int) {}`, "field: var int"},
{`package p9; func f() (complex64) { return 0 }`, "field: var complex64"},
{`package p10; type T struct{}; func (*T) f() {}`, "field: var *p10.T"},
+
+ // Tests using generics.
+ {`package f0; func f[T any](x int) {}`, ""}, // no Implicits entry
+ {`package f1; func f[T any](int) {}`, "field: var int"},
+ {`package f2; func f[T any](T) {}`, "field: var T"},
+ {`package f3; func f[T any]() (complex64) { return 0 }`, "field: var complex64"},
+ {`package f4; func f[T any](t T) (T) { return t }`, "field: var T"},
+ {`package t0; type T[A any] struct{}; func (*T[_]) f() {}`, "field: var *t0.T[_]"},
+ {`package t1; type T[A any] struct{}; func _(x interface{}) { switch t := x.(type) { case T[int]: _ = t } }`, "caseClause: var t t1.T[int]"},
+ {`package t2; type T[A any] struct{}; func _[P any](x interface{}) { switch t := x.(type) { case T[P]: _ = t } }`, "caseClause: var t t2.T[P]"},
+ {`package t3; func _[P any](x interface{}) { switch t := x.(type) { case P: _ = t } }`, "caseClause: var t P"},
}
for _, test := range tests {
@@ -1429,6 +1592,18 @@
makePkg("main", mainSrc) // don't crash when type-checking this package
}
+func TestLookupFieldOrMethodOnNil(t *testing.T) {
+ // LookupFieldOrMethod on a nil type is expected to produce a run-time panic.
+ defer func() {
+ const want = "LookupFieldOrMethod on nil type"
+ p := recover()
+ if s, ok := p.(string); !ok || s != want {
+ t.Fatalf("got %v, want %s", p, want)
+ }
+ }()
+ LookupFieldOrMethod(nil, false, nil, "")
+}
+
func TestLookupFieldOrMethod(t *testing.T) {
// Test cases assume a lookup of the form a.f or x.f, where a stands for an
// addressable value, and x for a non-addressable value (even though a variable
@@ -1543,7 +1718,7 @@
var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F
var a []int
- for i, x := range /*i=undef*/ /*x=var:16*/ a /*i=var:20*/ /*x=var:20*/ { _ = i; _ = x }
+ for i, x := range a /*i=undef*/ /*x=var:16*/ { _ = i; _ = x }
var i interface{}
switch y := i.(type) { /*y=undef*/
@@ -2159,27 +2334,27 @@
conf := Config{Error: func(error) {}}
pkg, _ := conf.Check(f.PkgName.Value, []*syntax.File{f}, nil)
- scope := pkg.Scope()
+ lookup := func(tname string) Type { return pkg.Scope().Lookup(tname).Type() }
var (
- EmptyIface = scope.Lookup("EmptyIface").Type().Underlying().(*Interface)
- I = scope.Lookup("I").Type().(*Named)
+ EmptyIface = lookup("EmptyIface").Underlying().(*Interface)
+ I = lookup("I").(*Named)
II = I.Underlying().(*Interface)
- C = scope.Lookup("C").Type().(*Named)
+ C = lookup("C").(*Named)
CI = C.Underlying().(*Interface)
- Integer = scope.Lookup("Integer").Type().Underlying().(*Interface)
- EmptyTypeSet = scope.Lookup("EmptyTypeSet").Type().Underlying().(*Interface)
- N1 = scope.Lookup("N1").Type()
+ Integer = lookup("Integer").Underlying().(*Interface)
+ EmptyTypeSet = lookup("EmptyTypeSet").Underlying().(*Interface)
+ N1 = lookup("N1")
N1p = NewPointer(N1)
- N2 = scope.Lookup("N2").Type()
+ N2 = lookup("N2")
N2p = NewPointer(N2)
- N3 = scope.Lookup("N3").Type()
- N4 = scope.Lookup("N4").Type()
- Bad = scope.Lookup("Bad").Type()
+ N3 = lookup("N3")
+ N4 = lookup("N4")
+ Bad = lookup("Bad")
)
tests := []struct {
- t Type
- i *Interface
+ V Type
+ T *Interface
want bool
}{
{I, II, true},
@@ -2210,8 +2385,78 @@
}
for _, test := range tests {
- if got := Implements(test.t, test.i); got != test.want {
- t.Errorf("Implements(%s, %s) = %t, want %t", test.t, test.i, got, test.want)
+ if got := Implements(test.V, test.T); got != test.want {
+ t.Errorf("Implements(%s, %s) = %t, want %t", test.V, test.T, got, test.want)
+ }
+
+ // The type assertion x.(T) is valid if T is an interface or if T implements the type of x.
+ // The assertion is never valid if T is a bad type.
+ V := test.T
+ T := test.V
+ want := false
+ if _, ok := T.Underlying().(*Interface); (ok || Implements(T, V)) && T != Bad {
+ want = true
+ }
+ if got := AssertableTo(V, T); got != want {
+ t.Errorf("AssertableTo(%s, %s) = %t, want %t", V, T, got, want)
}
}
}
+
+func TestMissingMethodAlternative(t *testing.T) {
+ const src = `
+package p
+type T interface {
+ m()
+}
+
+type V0 struct{}
+func (V0) m() {}
+
+type V1 struct{}
+
+type V2 struct{}
+func (V2) m() int
+
+type V3 struct{}
+func (*V3) m()
+
+type V4 struct{}
+func (V4) M()
+`
+
+ pkg, err := pkgFor("p.go", src, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ T := pkg.Scope().Lookup("T").Type().Underlying().(*Interface)
+ lookup := func(name string) (*Func, bool) {
+ return MissingMethod(pkg.Scope().Lookup(name).Type(), T, true)
+ }
+
+ // V0 has method m with correct signature. Should not report wrongType.
+ method, wrongType := lookup("V0")
+ if method != nil || wrongType {
+ t.Fatalf("V0: got method = %v, wrongType = %v", method, wrongType)
+ }
+
+ checkMissingMethod := func(tname string, reportWrongType bool) {
+ method, wrongType := lookup(tname)
+ if method == nil || method.Name() != "m" || wrongType != reportWrongType {
+ t.Fatalf("%s: got method = %v, wrongType = %v", tname, method, wrongType)
+ }
+ }
+
+ // V1 has no method m. Should not report wrongType.
+ checkMissingMethod("V1", false)
+
+ // V2 has method m with wrong signature type (ignoring receiver). Should report wrongType.
+ checkMissingMethod("V2", true)
+
+ // V3 has no method m but it exists on *V3. Should report wrongType.
+ checkMissingMethod("V3", true)
+
+ // V4 has no method m but has M. Should not report wrongType.
+ checkMissingMethod("V4", false)
+}
diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go
index 0a85d8e..d88b037 100644
--- a/src/cmd/compile/internal/types2/assignments.go
+++ b/src/cmd/compile/internal/types2/assignments.go
@@ -268,7 +268,7 @@
var s string
switch {
case t == nil:
- fallthrough // should not happend but be cautious
+ fallthrough // should not happen but be cautious
case t == Typ[Invalid]:
s = "<T>"
case isUntyped(t):
@@ -294,15 +294,14 @@
return "(" + strings.Join(res, ", ") + ")"
}
-func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) {
- measure := func(x int, unit string) string {
- s := fmt.Sprintf("%d %s", x, unit)
- if x != 1 {
- s += "s"
- }
- return s
+func measure(x int, unit string) string {
+ if x != 1 {
+ unit += "s"
}
+ return fmt.Sprintf("%d %s", x, unit)
+}
+func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) {
vars := measure(nvars, "variable")
vals := measure(nvals, "value")
rhs0 := rhs[0]
@@ -317,7 +316,7 @@
}
// If returnStmt != nil, initVars is called to type-check the assignment
-// of return expressions, and returnStmt is the the return statement.
+// of return expressions, and returnStmt is the return statement.
func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt syntax.Stmt) {
rhs, commaOk := check.exprList(orig_rhs, len(lhs) == 2 && returnStmt == nil)
diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go
index fcf02a6..428897c 100644
--- a/src/cmd/compile/internal/types2/builtins.go
+++ b/src/cmd/compile/internal/types2/builtins.go
@@ -82,10 +82,24 @@
// of S and the respective parameter passing rules apply."
S := x.typ
var T Type
- if s, _ := structuralType(S).(*Slice); s != nil {
+ if s, _ := coreType(S).(*Slice); s != nil {
T = s.elem
} else {
- check.errorf(x, invalidArg+"%s is not a slice", x)
+ var cause string
+ switch {
+ case x.isNil():
+ cause = "have untyped nil"
+ case isTypeParam(S):
+ if u := coreType(S); u != nil {
+ cause = check.sprintf("%s has core type %s", x, u)
+ } else {
+ cause = check.sprintf("%s has no core type", x)
+ }
+ default:
+ cause = check.sprintf("have %s", x)
+ }
+ // don't use invalidArg prefix here as it would repeat "argument" in the error message
+ check.errorf(x, "first argument to append must be a slice; %s", cause)
return
}
@@ -101,7 +115,7 @@
if x.mode == invalid {
return
}
- if allString(x.typ) {
+ if t := coreString(x.typ); t != nil && isString(t) {
if check.Types != nil {
sig := makeSig(S, S, x.typ)
sig.variadic = true
@@ -142,9 +156,8 @@
// cap(x)
// len(x)
mode := invalid
- var typ Type
var val constant.Value
- switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) {
+ switch t := arrayPtrDeref(under(x.typ)).(type) {
case *Basic:
if isString(t) && id == _Len {
if x.mode == constant_ {
@@ -201,17 +214,19 @@
}
}
- if mode == invalid && typ != Typ[Invalid] {
+ if mode == invalid && under(x.typ) != Typ[Invalid] {
check.errorf(x, invalidArg+"%s for %s", x, bin.name)
return
}
+ // record the signature before changing x.typ
+ if check.Types != nil && mode != constant_ {
+ check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ))
+ }
+
x.mode = mode
x.typ = Typ[Int]
x.val = val
- if check.Types != nil && mode != constant_ {
- check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
- }
case _Close:
// close(c)
@@ -309,7 +324,7 @@
}
return nil
}
- resTyp := check.applyTypeFunc(f, x.typ)
+ resTyp := check.applyTypeFunc(f, x, id)
if resTyp == nil {
check.errorf(x, invalidArg+"arguments have type %s, expected floating-point", x.typ)
return
@@ -330,14 +345,14 @@
case _Copy:
// copy(x, y []T) int
- dst, _ := structuralType(x.typ).(*Slice)
+ dst, _ := coreType(x.typ).(*Slice)
var y operand
arg(&y, 1)
if y.mode == invalid {
return
}
- src0 := structuralString(y.typ)
+ src0 := coreString(y.typ)
if src0 != nil && isString(src0) {
src0 = NewSlice(universeByte)
}
@@ -437,7 +452,7 @@
}
return nil
}
- resTyp := check.applyTypeFunc(f, x.typ)
+ resTyp := check.applyTypeFunc(f, x, id)
if resTyp == nil {
check.errorf(x, invalidArg+"argument has type %s, expected complex type", x.typ)
return
@@ -471,13 +486,13 @@
}
var min int // minimum number of arguments
- switch structuralType(T).(type) {
+ switch coreType(T).(type) {
case *Slice:
min = 2
case *Map, *Chan:
min = 1
case nil:
- check.errorf(arg0, invalidArg+"cannot make %s: no structural type", arg0)
+ check.errorf(arg0, invalidArg+"cannot make %s: no core type", arg0)
return
default:
check.errorf(arg0, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0)
@@ -800,8 +815,8 @@
// of x. If any of these applications of f return nil,
// applyTypeFunc returns nil.
// If x is not a type parameter, the result is f(x).
-func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
- if tp, _ := x.(*TypeParam); tp != nil {
+func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId) Type {
+ if tp, _ := x.typ.(*TypeParam); tp != nil {
// Test if t satisfies the requirements for the argument
// type and collect possible result types at the same time.
var terms []*Term
@@ -818,17 +833,23 @@
return nil
}
+ // We can type-check this fine but we're introducing a synthetic
+ // type parameter for the result. It's not clear what the API
+ // implications are here. Report an error for 1.18 but continue
+ // type-checking.
+ check.softErrorf(x, "%s not supported as argument to %s for go1.18 (see issue #50937)", x, predeclaredFuncs[id].name)
+
// Construct a suitable new type parameter for the result type.
// The type parameter is placed in the current package so export/import
// works as expected.
- tpar := NewTypeName(nopos, check.pkg, "<type parameter>", nil)
+ tpar := NewTypeName(nopos, check.pkg, tp.obj.name, nil)
ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect
ptyp.index = tp.index
return ptyp
}
- return f(x)
+ return f(x.typ)
}
// makeSig makes a signature for the given argument and result types.
diff --git a/src/cmd/compile/internal/types2/builtins_test.go b/src/cmd/compile/internal/types2/builtins_test.go
index be5707c..e07a779 100644
--- a/src/cmd/compile/internal/types2/builtins_test.go
+++ b/src/cmd/compile/internal/types2/builtins_test.go
@@ -28,6 +28,8 @@
{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
{"cap", `var s []int64; _ = cap(s)`, `func([]int64) int`},
{"cap", `var c chan<-bool; _ = cap(c)`, `func(chan<- bool) int`},
+ {"cap", `type S []byte; var s S; _ = cap(s)`, `func(p.S) int`},
+ {"cap", `var s P; _ = cap(s)`, `func(P) int`},
{"len", `_ = len("foo")`, `invalid type`}, // constant
{"len", `var s string; _ = len(s)`, `func(string) int`},
@@ -36,6 +38,8 @@
{"len", `var s []int64; _ = len(s)`, `func([]int64) int`},
{"len", `var c chan<-bool; _ = len(c)`, `func(chan<- bool) int`},
{"len", `var m map[string]float32; _ = len(m)`, `func(map[string]float32) int`},
+ {"len", `type S []byte; var s S; _ = len(s)`, `func(p.S) int`},
+ {"len", `var s P; _ = len(s)`, `func(P) int`},
{"close", `var c chan int; close(c)`, `func(chan int)`},
{"close", `var c chan<- chan string; close(c)`, `func(chan<- chan string)`},
@@ -159,7 +163,7 @@
}
func testBuiltinSignature(t *testing.T, name, src0, want string) {
- src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P any]() { %s }`, src0)
+ src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P ~[]byte]() { %s }`, src0)
f, err := parseGenericSrc("", src)
if err != nil {
t.Errorf("%s: %s", src0, err)
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index ed8b67c..6cc30a7 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -74,17 +74,21 @@
inst := check.instance(pos, typ, targs, check.bestContext(nil)).(*Signature)
assert(len(xlist) <= len(targs))
- tparams := typ.TypeParams().list()
- if i, err := check.verify(pos, tparams, targs); err != nil {
- // best position for error reporting
- pos := pos
- if i < len(xlist) {
- pos = syntax.StartPos(xlist[i])
+
+ // verify instantiation lazily (was issue #50450)
+ check.later(func() {
+ tparams := typ.TypeParams().list()
+ if i, err := check.verify(pos, tparams, targs); err != nil {
+ // best position for error reporting
+ pos := pos
+ if i < len(xlist) {
+ pos = syntax.StartPos(xlist[i])
+ }
+ check.softErrorf(pos, "%s", err)
+ } else {
+ check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist)
}
- check.softErrorf(pos, "%s", err)
- } else {
- check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist)
- }
+ })
return inst
}
@@ -164,7 +168,7 @@
cgocall := x.mode == cgofunc
// a type parameter may be "called" if all types have the same signature
- sig, _ := structuralType(x.typ).(*Signature)
+ sig, _ := coreType(x.typ).(*Signature)
if sig == nil {
check.errorf(x, invalidOp+"cannot call non-function %s", x)
x.mode = invalid
@@ -419,7 +423,7 @@
"_Cmacro_", // function to evaluate the expanded expression
}
-func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
+func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named) {
// these must be declared before the "goto Error" statements
var (
obj Object
@@ -521,32 +525,46 @@
}
check.exprOrType(x, e.X, false)
- if x.mode == invalid {
+ switch x.mode {
+ case typexpr:
+ // don't crash for "type T T.x" (was issue #51509)
+ if def != nil && x.typ == def {
+ check.cycleError([]Object{def.obj})
+ goto Error
+ }
+ case builtin:
+ check.errorf(e.Pos(), "cannot select on %s", x)
+ goto Error
+ case invalid:
goto Error
}
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
- switch {
- case index != nil:
+ // Don't report another error if the underlying type was invalid (issue #49541).
+ if under(x.typ) == Typ[Invalid] {
+ goto Error
+ }
+
+ if index != nil {
// TODO(gri) should provide actual type where the conflict happens
check.errorf(e.Sel, "ambiguous selector %s.%s", x.expr, sel)
- case indirect:
- check.errorf(e.Sel, "cannot call pointer method %s on %s", sel, x.typ)
- default:
- var why string
- if tpar, _ := x.typ.(*TypeParam); tpar != nil {
- // Type parameter bounds don't specify fields, so don't mention "field".
- if tname := tpar.iface().obj; tname != nil {
- why = check.sprintf("interface %s has no method %s", tname.name, sel)
- } else {
- why = check.sprintf("type bound for %s has no method %s", x.typ, sel)
- }
- } else {
- why = check.sprintf("type %s has no field or method %s", x.typ, sel)
- }
+ goto Error
+ }
+ if indirect {
+ check.errorf(e.Sel, "cannot call pointer method %s on %s", sel, x.typ)
+ goto Error
+ }
+
+ var why string
+ if isInterfacePtr(x.typ) {
+ why = check.interfacePtrError(x.typ)
+ } else {
+ why = check.sprintf("type %s has no field or method %s", x.typ, sel)
// Check if capitalization of sel matters and provide better error message in that case.
+ // TODO(gri) This code only looks at the first character but LookupFieldOrMethod has an
+ // (internal) mechanism for case-insensitive lookup. Should use that instead.
if len(sel) > 0 {
var changeCase string
if r := rune(sel[0]); unicode.IsUpper(r) {
@@ -558,10 +576,8 @@
why += ", but does have " + changeCase
}
}
-
- check.errorf(e.Sel, "%s.%s undefined (%s)", x.expr, sel, why)
-
}
+ check.errorf(e.Sel, "%s.%s undefined (%s)", x.expr, sel, why)
goto Error
}
diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go
index aacbb25..4ec6a7b 100644
--- a/src/cmd/compile/internal/types2/check.go
+++ b/src/cmd/compile/internal/types2/check.go
@@ -18,19 +18,6 @@
// debugging/development support
const debug = false // leave on during development
-// If forceStrict is set, the type-checker enforces additional
-// rules not specified by the Go 1 spec, but which will
-// catch guaranteed run-time errors if the respective
-// code is executed. In other words, programs passing in
-// strict mode are Go 1 compliant, but not all Go 1 programs
-// will pass in strict mode. The additional rules are:
-//
-// - A type assertion x.(T) where T is an interface type
-// is invalid if any (statically known) method that exists
-// for both x and T have different signatures.
-//
-const forceStrict = false
-
// exprInfo stores information about an untyped expression.
type exprInfo struct {
isLhs bool // expression is lhs operand of a shift with delayed type-check
@@ -111,6 +98,7 @@
nextID uint64 // unique Id for type parameters (first valid Id is 1)
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
+ infoMap map[*Named]typeInfo // maps named types to their associated type info (for cycle detection)
// pkgPathMap maps package names to the set of distinct import paths we've
// seen for that name, anywhere in the import graph. It is used for
@@ -129,6 +117,8 @@
imports []*PkgName // list of imported packages
dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through
recvTParamMap map[*syntax.Name]*TypeParam // maps blank receiver type parameters to their type
+ brokenAliases map[*TypeName]bool // set of aliases with broken (not yet determined) types
+ unionTypeSets map[*Union]*_TypeSet // computed type sets for union types
mono monoGraph // graph for detecting non-monomorphizable instantiation loops
firstErr error // first error encountered
@@ -136,7 +126,7 @@
untyped map[syntax.Expr]exprInfo // map of expressions without final type
delayed []action // stack of delayed action segments; segments are processed in FIFO order
objPath []Object // path of object dependencies during type inference (for cycle reporting)
- defTypes []*Named // defined types created during type checking, for final validation.
+ cleaners []cleaner // list of types that may need a final cleanup at the end of type-checking
// environment within which the current object is type-checked (valid only
// for the duration of type-checking a specific object)
@@ -158,6 +148,27 @@
from.addDep(to)
}
+// brokenAlias records that alias doesn't have a determined type yet.
+// It also sets alias.typ to Typ[Invalid].
+func (check *Checker) brokenAlias(alias *TypeName) {
+ if check.brokenAliases == nil {
+ check.brokenAliases = make(map[*TypeName]bool)
+ }
+ check.brokenAliases[alias] = true
+ alias.typ = Typ[Invalid]
+}
+
+// validAlias records that alias has the valid type typ (possibly Typ[Invalid]).
+func (check *Checker) validAlias(alias *TypeName, typ Type) {
+ delete(check.brokenAliases, alias)
+ alias.typ = typ
+}
+
+// isBrokenAlias reports whether alias doesn't have a determined type yet.
+func (check *Checker) isBrokenAlias(alias *TypeName) bool {
+ return alias.typ == Typ[Invalid] && check.brokenAliases[alias]
+}
+
func (check *Checker) rememberUntyped(e syntax.Expr, lhs bool, mode operandMode, typ *Basic, val constant.Value) {
m := check.untyped
if m == nil {
@@ -194,6 +205,16 @@
return obj
}
+type cleaner interface {
+ cleanup()
+}
+
+// needsCleanup records objects/types that implement the cleanup method
+// which will be called at the end of type-checking.
+func (check *Checker) needsCleanup(c cleaner) {
+ check.cleaners = append(check.cleaners, c)
+}
+
// NewChecker returns a new Checker instance for a given package.
// Package files may be added incrementally via checker.Files.
func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
@@ -220,6 +241,7 @@
version: version,
objMap: make(map[Object]*declInfo),
impMap: make(map[importKey]*Package),
+ infoMap: make(map[*Named]typeInfo),
}
}
@@ -235,6 +257,8 @@
check.methods = nil
check.untyped = nil
check.delayed = nil
+ check.objPath = nil
+ check.cleaners = nil
// determine package name and collect valid files
pkg := check.pkg
@@ -303,8 +327,8 @@
print("== processDelayed ==")
check.processDelayed(0) // incl. all functions
- print("== expandDefTypes ==")
- check.expandDefTypes()
+ print("== cleanup ==")
+ check.cleanup()
print("== initOrder ==")
check.initOrder()
@@ -330,7 +354,8 @@
check.pkgPathMap = nil
check.seenPkgMap = nil
check.recvTParamMap = nil
- check.defTypes = nil
+ check.brokenAliases = nil
+ check.unionTypeSets = nil
check.ctxt = nil
// TODO(gri) There's more memory we should release at this point.
@@ -358,27 +383,13 @@
check.delayed = check.delayed[:top]
}
-func (check *Checker) expandDefTypes() {
- // Ensure that every defined type created in the course of type-checking has
- // either non-*Named underlying, or is unresolved.
- //
- // This guarantees that we don't leak any types whose underlying is *Named,
- // because any unresolved instances will lazily compute their underlying by
- // substituting in the underlying of their origin. The origin must have
- // either been imported or type-checked and expanded here, and in either case
- // its underlying will be fully expanded.
- for i := 0; i < len(check.defTypes); i++ {
- n := check.defTypes[i]
- switch n.underlying.(type) {
- case nil:
- if n.resolver == nil {
- panic("nil underlying")
- }
- case *Named:
- n.under() // n.under may add entries to check.defTypes
- }
- n.check = nil
+// cleanup runs cleanup for all collected cleaners.
+func (check *Checker) cleanup() {
+ // Don't use a range clause since Named.cleanup may add more cleaners.
+ for i := 0; i < len(check.cleaners); i++ {
+ check.cleaners[i].cleanup()
}
+ check.cleaners = nil
}
func (check *Checker) record(x *operand) {
diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go
index f13679d..7efa512 100644
--- a/src/cmd/compile/internal/types2/check_test.go
+++ b/src/cmd/compile/internal/types2/check_test.go
@@ -118,7 +118,7 @@
var mode syntax.Mode
if strings.HasSuffix(filenames[0], ".go2") || manual {
- mode |= syntax.AllowGenerics
+ mode |= syntax.AllowGenerics | syntax.AllowMethodTypeParams
}
// parse files and collect parser errors
files, errlist := parseFiles(t, filenames, mode)
@@ -295,10 +295,13 @@
// TODO(gri) go/types has extra TestLongConstants and TestIndexRepresentability tests
-func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 55, false) } // TODO(gri) narrow column tolerance
-func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", 0, false) }
-func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", 0, false) }
-func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", 0, false) }
+func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 55, false) } // TODO(gri) narrow column tolerance
+func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", 0, false) }
+func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", 0, false) }
+func TestFixedbugs(t *testing.T) {
+ DefPredeclaredTestFuncs()
+ testDirFiles(t, "testdata/fixedbugs", 0, false)
+}
func testDirFiles(t *testing.T, dir string, colDelta uint, manual bool) {
testenv.MustHaveGoBuild(t)
diff --git a/src/cmd/compile/internal/types2/compilersupport.go b/src/cmd/compile/internal/types2/compilersupport.go
index b35e752..33dd8e8 100644
--- a/src/cmd/compile/internal/types2/compilersupport.go
+++ b/src/cmd/compile/internal/types2/compilersupport.go
@@ -19,12 +19,12 @@
return u
}
-// If typ is a type parameter, structuralType returns the single underlying
+// If typ is a type parameter, CoreType returns the single underlying
// type of all types in the corresponding type constraint if it exists, or
// nil otherwise. If the type set contains only unrestricted and restricted
// channel types (with identical element types), the single underlying type
// is the restricted channel type if the restrictions are always the same.
-// If typ is not a type parameter, structuralType returns the underlying type.
-func StructuralType(t Type) Type {
- return structuralType(t)
+// If typ is not a type parameter, CoreType returns the underlying type.
+func CoreType(t Type) Type {
+ return coreType(t)
}
diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go
index 253868c..08b3cbf 100644
--- a/src/cmd/compile/internal/types2/conversions.go
+++ b/src/cmd/compile/internal/types2/conversions.go
@@ -49,11 +49,14 @@
// have specific types, constant x cannot be
// converted.
ok = T.(*TypeParam).underIs(func(u Type) bool {
- // t is nil if there are no specific type terms
+ // u is nil if there are no specific type terms
if u == nil {
cause = check.sprintf("%s does not contain specific types", T)
return false
}
+ if isString(x.typ) && isBytesOrRunes(u) {
+ return true
+ }
if !constConvertibleTo(u, nil) {
cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
return false
@@ -98,13 +101,13 @@
// - For conversions of untyped constants to non-constant types, also
// use the default type (e.g., []byte("foo") should report string
// not []byte as type for the constant "foo").
- // - For integer to string conversions, keep the argument type.
+ // - For constant integer to string conversions, keep the argument type.
// (See also the TODO below.)
if x.typ == Typ[UntypedNil] {
// ok
} else if IsInterface(T) && !isTypeParam(T) || constArg && !isConstType(T) {
final = Default(x.typ)
- } else if isInteger(x.typ) && allString(T) {
+ } else if x.mode == constant_ && isInteger(x.typ) && allString(T) {
final = x.typ
}
check.updateExprType(x.expr, final, true)
diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go
index a4bc396..579fa55 100644
--- a/src/cmd/compile/internal/types2/decl.go
+++ b/src/cmd/compile/internal/types2/decl.go
@@ -66,12 +66,6 @@
}()
}
- // Funcs with m.instRecv set have not yet be completed. Complete them now
- // so that they have a type when objDecl exits.
- if m, _ := obj.(*Func); m != nil && m.instRecv != nil {
- check.completeMethod(nil, m)
- }
-
// Checking the declaration of obj means inferring its type
// (and possibly its value, for constants).
// An object's type (and thus the object) may be in one of
@@ -278,7 +272,9 @@
check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef)
}
defer func() {
- if !valid {
+ if valid {
+ check.trace(obj.Pos(), "=> cycle is valid")
+ } else {
check.trace(obj.Pos(), "=> error: cycle is invalid")
}
}()
@@ -304,96 +300,6 @@
return false
}
-type typeInfo uint
-
-// validType verifies that the given type does not "expand" infinitely
-// producing a cycle in the type graph. Cycles are detected by marking
-// defined types.
-// (Cycles involving alias types, as in "type A = [10]A" are detected
-// earlier, via the objDecl cycle detection mechanism.)
-func (check *Checker) validType(typ Type, path []Object) typeInfo {
- const (
- unknown typeInfo = iota
- marked
- valid
- invalid
- )
-
- switch t := typ.(type) {
- case *Array:
- return check.validType(t.elem, path)
-
- case *Struct:
- for _, f := range t.fields {
- if check.validType(f.typ, path) == invalid {
- return invalid
- }
- }
-
- case *Union:
- for _, t := range t.terms {
- if check.validType(t.typ, path) == invalid {
- return invalid
- }
- }
-
- case *Interface:
- for _, etyp := range t.embeddeds {
- if check.validType(etyp, path) == invalid {
- return invalid
- }
- }
-
- case *Named:
- // If t is parameterized, we should be considering the instantiated (expanded)
- // form of t, but in general we can't with this algorithm: if t is an invalid
- // type it may be so because it infinitely expands through a type parameter.
- // Instantiating such a type would lead to an infinite sequence of instantiations.
- // In general, we need "type flow analysis" to recognize those cases.
- // Example: type A[T any] struct{ x A[*T] } (issue #48951)
- // In this algorithm we always only consider the orginal, uninstantiated type.
- // This won't recognize some invalid cases with parameterized types, but it
- // will terminate.
- t = t.orig
-
- // don't touch the type if it is from a different package or the Universe scope
- // (doing so would lead to a race condition - was issue #35049)
- if t.obj.pkg != check.pkg {
- return valid
- }
-
- // don't report a 2nd error if we already know the type is invalid
- // (e.g., if a cycle was detected earlier, via under).
- if t.underlying == Typ[Invalid] {
- t.info = invalid
- return invalid
- }
-
- switch t.info {
- case unknown:
- t.info = marked
- t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
- case marked:
- // cycle detected
- for i, tn := range path {
- if t.obj.pkg != check.pkg {
- panic("type cycle via package-external type")
- }
- if tn == t.obj {
- check.cycleError(path[i:])
- t.info = invalid
- t.underlying = Typ[Invalid]
- return invalid
- }
- }
- panic("cycle start not found")
- }
- return t.info
- }
-
- return valid
-}
-
// cycleError reports a declaration cycle starting with
// the object in cycle that is "first" in the source.
func (check *Checker) cycleError(cycle []Object) {
@@ -402,8 +308,13 @@
// cycle? That would be more consistent with other error messages.
i := firstInSrc(cycle)
obj := cycle[i]
+ // If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors.
+ tname, _ := obj.(*TypeName)
+ if tname != nil && tname.IsAlias() {
+ check.validAlias(tname, Typ[Invalid])
+ }
var err error_
- if check.conf.CompilerErrorMessages {
+ if tname != nil && check.conf.CompilerErrorMessages {
err.errorf(obj, "invalid recursive type %s", obj.Name())
} else {
err.errorf(obj, "illegal cycle in declaration of %s", obj.Name())
@@ -567,7 +478,9 @@
var rhs Type
check.later(func() {
- check.validType(obj.typ, nil)
+ if t, _ := obj.typ.(*Named); t != nil { // type may be invalid
+ check.validType(t)
+ }
// If typ is local, an error was already reported where typ is specified/defined.
if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) {
check.versionErrorf(tdecl.Type, "go1.18", "using type constraint %s", rhs)
@@ -588,9 +501,9 @@
check.versionErrorf(tdecl, "go1.9", "type aliases")
}
- obj.typ = Typ[Invalid]
+ check.brokenAlias(obj)
rhs = check.varType(tdecl.Type)
- obj.typ = rhs
+ check.validAlias(obj, rhs)
return
}
@@ -656,34 +569,23 @@
// Keep track of bounds for later validation.
var bound Type
- var bounds []Type
- var posers []poser
for i, f := range list {
// Optimization: Re-use the previous type bound if it hasn't changed.
// This also preserves the grouped output of type parameter lists
// when printing type strings.
if i == 0 || f.Type != list[i-1].Type {
bound = check.bound(f.Type)
- bounds = append(bounds, bound)
- posers = append(posers, f.Type)
- }
- tparams[i].bound = bound
- }
-
- check.later(func() {
- for i, bound := range bounds {
if isTypeParam(bound) {
// We may be able to allow this since it is now well-defined what
// the underlying type and thus type set of a type parameter is.
// But we may need some additional form of cycle detection within
// type parameter lists.
- check.error(posers[i], "cannot use a type parameter as constraint")
+ check.error(f.Type, "cannot use a type parameter as constraint")
+ bound = Typ[Invalid]
}
}
- for _, tpar := range tparams {
- tpar.iface() // compute type set
- }
- })
+ tparams[i].bound = bound
+ }
}
func (check *Checker) bound(x syntax.Expr) Type {
@@ -733,6 +635,7 @@
// and field names must be distinct."
base, _ := obj.typ.(*Named) // shouldn't fail but be conservative
if base != nil {
+ assert(base.targs.Len() == 0) // collectMethods should not be called on an instantiated type
u := base.under()
if t, _ := u.(*Struct); t != nil {
for _, fld := range t.fields {
@@ -745,7 +648,8 @@
// Checker.Files may be called multiple times; additional package files
// may add methods to already type-checked types. Add pre-existing methods
// so that we can detect redeclarations.
- for _, m := range base.methods {
+ for i := 0; i < base.methods.Len(); i++ {
+ m := base.methods.At(i, nil)
assert(m.name != "_")
assert(mset.insert(m) == nil)
}
@@ -777,7 +681,7 @@
if base != nil {
base.resolve(nil) // TODO(mdempsky): Probably unnecessary.
- base.methods = append(base.methods, m)
+ base.AddMethod(m)
}
}
}
diff --git a/src/cmd/compile/internal/types2/errors.go b/src/cmd/compile/internal/types2/errors.go
index c39652f..422f520 100644
--- a/src/cmd/compile/internal/types2/errors.go
+++ b/src/cmd/compile/internal/types2/errors.go
@@ -98,10 +98,43 @@
arg = a.String()
case syntax.Expr:
arg = syntax.String(a)
+ case []syntax.Expr:
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(syntax.String(x))
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
case Object:
arg = ObjectString(a, qf)
case Type:
arg = typeString(a, qf, debug)
+ case []Type:
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(typeString(x, qf, debug))
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
+ case []*TypeParam:
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(typeString(x, qf, debug)) // use typeString so we get subscripts when debugging
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
}
args[i] = arg
}
@@ -145,8 +178,13 @@
}
}
+// check may be nil.
func (check *Checker) sprintf(format string, args ...interface{}) string {
- return sprintf(check.qualifier, false, format, args...)
+ var qf Qualifier
+ if check != nil {
+ qf = check.qualifier
+ }
+ return sprintf(qf, false, format, args...)
}
func (check *Checker) report(err *error_) {
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 5961f32..05cf1d0 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -73,11 +73,7 @@
func (check *Checker) op(m opPredicates, x *operand, op syntax.Operator) bool {
if pred := m[op]; pred != nil {
if !pred(x.typ) {
- if check.conf.CompilerErrorMessages {
- check.errorf(x, invalidOp+"operator %s not defined on %s", op, x)
- } else {
- check.errorf(x, invalidOp+"operator %s not defined for %s", op, x)
- }
+ check.errorf(x, invalidOp+"operator %s not defined on %s", op, x)
return false
}
} else {
@@ -186,9 +182,9 @@
return
case syntax.Recv:
- u := structuralType(x.typ)
+ u := coreType(x.typ)
if u == nil {
- check.errorf(x, invalidOp+"cannot receive from %s: no structural type", x)
+ check.errorf(x, invalidOp+"cannot receive from %s: no core type", x)
x.mode = invalid
return
}
@@ -508,8 +504,11 @@
// Also, if x is a constant, it must be representable as a value of typ,
// and if x is the (formerly untyped) lhs operand of a non-constant
// shift, it must be an integer value.
-//
func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) {
+ check.updateExprType0(nil, x, typ, final)
+}
+
+func (check *Checker) updateExprType0(parent, x syntax.Expr, typ Type, final bool) {
old, found := check.untyped[x]
if !found {
return // nothing to do
@@ -552,7 +551,7 @@
// No operands to take care of.
case *syntax.ParenExpr:
- check.updateExprType(x.X, typ, final)
+ check.updateExprType0(x, x.X, typ, final)
// case *syntax.UnaryExpr:
// // If x is a constant, the operands were constants.
@@ -563,7 +562,7 @@
// if old.val != nil {
// break
// }
- // check.updateExprType(x.X, typ, final)
+ // check.updateExprType0(x, x.X, typ, final)
case *syntax.Operation:
if x.Y == nil {
@@ -584,7 +583,7 @@
if old.val != nil {
break
}
- check.updateExprType(x.X, typ, final)
+ check.updateExprType0(x, x.X, typ, final)
break
}
@@ -598,11 +597,11 @@
} else if isShift(x.Op) {
// The result type depends only on lhs operand.
// The rhs type was updated when checking the shift.
- check.updateExprType(x.X, typ, final)
+ check.updateExprType0(x, x.X, typ, final)
} else {
// The operand types match the result type.
- check.updateExprType(x.X, typ, final)
- check.updateExprType(x.Y, typ, final)
+ check.updateExprType0(x, x.X, typ, final)
+ check.updateExprType0(x, x.Y, typ, final)
}
default:
@@ -626,7 +625,11 @@
// We already know from the shift check that it is representable
// as an integer if it is a constant.
if !allInteger(typ) {
- check.errorf(x, invalidOp+"shifted operand %s (type %s) must be integer", x, typ)
+ if check.conf.CompilerErrorMessages {
+ check.errorf(x, invalidOp+"%s (shift of type %s)", parent, typ)
+ } else {
+ check.errorf(x, invalidOp+"shifted operand %s (type %s) must be integer", x, typ)
+ }
return
}
// Even if we have an integer, if the value is a constant we
@@ -767,46 +770,82 @@
return target, nil, 0
}
-func (check *Checker) comparison(x, y *operand, op syntax.Operator) {
+// If switchCase is true, the operator op is ignored.
+func (check *Checker) comparison(x, y *operand, op syntax.Operator, switchCase bool) {
+ if switchCase {
+ op = syntax.Eql
+ }
+
+ errOp := x // operand for which error is reported, if any
+ cause := "" // specific error cause, if any
+
// spec: "In any comparison, the first operand must be assignable
// to the type of the second operand, or vice versa."
- err := ""
- xok, _ := x.assignableTo(check, y.typ, nil)
- yok, _ := y.assignableTo(check, x.typ, nil)
- if xok || yok {
- defined := false
- switch op {
- case syntax.Eql, syntax.Neq:
- // spec: "The equality operators == and != apply to operands that are comparable."
- defined = Comparable(x.typ) && Comparable(y.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ)
- case syntax.Lss, syntax.Leq, syntax.Gtr, syntax.Geq:
- // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered."
- defined = allOrdered(x.typ) && allOrdered(y.typ)
- default:
- unreachable()
+ ok, _ := x.assignableTo(check, y.typ, nil)
+ if !ok {
+ ok, _ = y.assignableTo(check, x.typ, nil)
+ }
+ if !ok {
+ // Report the error on the 2nd operand since we only
+ // know after seeing the 2nd operand whether we have
+ // a type mismatch.
+ errOp = y
+ // For now, if we're not running the compiler, use the
+ // position of x to minimize changes to existing tests.
+ if !check.conf.CompilerErrorMessages {
+ errOp = x
}
- if !defined {
+ cause = check.sprintf("mismatched types %s and %s", x.typ, y.typ)
+ goto Error
+ }
+
+ // check if comparison is defined for operands
+ switch op {
+ case syntax.Eql, syntax.Neq:
+ // spec: "The equality operators == and != apply to operands that are comparable."
+ switch {
+ case x.isNil() || y.isNil():
+ // Comparison against nil requires that the other operand type has nil.
typ := x.typ
if x.isNil() {
typ = y.typ
}
- if check.conf.CompilerErrorMessages {
- err = check.sprintf("operator %s not defined on %s", op, typ)
- } else {
- err = check.sprintf("operator %s not defined for %s", op, typ)
+ if !hasNil(typ) {
+ // This case should only be possible for "nil == nil".
+ // Report the error on the 2nd operand since we only
+ // know after seeing the 2nd operand whether we have
+ // an invalid comparison.
+ errOp = y
+ goto Error
}
+
+ case !Comparable(x.typ):
+ errOp = x
+ cause = check.incomparableCause(x.typ)
+ goto Error
+
+ case !Comparable(y.typ):
+ errOp = y
+ cause = check.incomparableCause(y.typ)
+ goto Error
}
- } else {
- err = check.sprintf("mismatched types %s and %s", x.typ, y.typ)
+
+ case syntax.Lss, syntax.Leq, syntax.Gtr, syntax.Geq:
+ // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered."
+ switch {
+ case !allOrdered(x.typ):
+ errOp = x
+ goto Error
+ case !allOrdered(y.typ):
+ errOp = y
+ goto Error
+ }
+
+ default:
+ unreachable()
}
- if err != "" {
- // TODO(gri) better error message for cases where one can only compare against nil
- check.errorf(x, invalidOp+"cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
- x.mode = invalid
- return
- }
-
+ // comparison is ok
if x.mode == constant_ && y.mode == constant_ {
x.val = constant.MakeBool(constant.Compare(x.val, op2tok[op], y.val))
// The operands are never materialized; no need to update
@@ -824,6 +863,73 @@
// spec: "Comparison operators compare two operands and yield
// an untyped boolean value."
x.typ = Typ[UntypedBool]
+ return
+
+Error:
+ // We have an offending operand errOp and possibly an error cause.
+ if cause == "" {
+ if isTypeParam(x.typ) || isTypeParam(y.typ) {
+ // TODO(gri) should report the specific type causing the problem, if any
+ if !isTypeParam(x.typ) {
+ errOp = y
+ }
+ cause = check.sprintf("type parameter %s is not comparable with %s", errOp.typ, op)
+ } else {
+ cause = check.sprintf("operator %s not defined on %s", op, check.kindString(errOp.typ)) // catch-all
+ }
+ }
+ if switchCase {
+ check.errorf(x, "invalid case %s in switch on %s (%s)", x.expr, y.expr, cause) // error position always at 1st operand
+ } else {
+ if check.conf.CompilerErrorMessages {
+ check.errorf(errOp, invalidOp+"%s %s %s (%s)", x.expr, op, y.expr, cause)
+ } else {
+ check.errorf(errOp, invalidOp+"cannot compare %s %s %s (%s)", x.expr, op, y.expr, cause)
+ }
+ }
+ x.mode = invalid
+}
+
+// incomparableCause returns a more specific cause why typ is not comparable.
+// If there is no more specific cause, the result is "".
+func (check *Checker) incomparableCause(typ Type) string {
+ switch under(typ).(type) {
+ case *Slice, *Signature, *Map:
+ return check.kindString(typ) + " can only be compared to nil"
+ }
+ // see if we can extract a more specific error
+ var cause string
+ comparable(typ, true, nil, func(format string, args ...interface{}) {
+ cause = check.sprintf(format, args...)
+ })
+ return cause
+}
+
+// kindString returns the type kind as a string.
+func (check *Checker) kindString(typ Type) string {
+ switch under(typ).(type) {
+ case *Array:
+ return "array"
+ case *Slice:
+ return "slice"
+ case *Struct:
+ return "struct"
+ case *Pointer:
+ return "pointer"
+ case *Signature:
+ return "func"
+ case *Interface:
+ if isTypeParam(typ) {
+ return check.sprintf("type parameter %s", typ)
+ }
+ return "interface"
+ case *Map:
+ return "map"
+ case *Chan:
+ return "chan"
+ default:
+ return check.sprintf("%s", typ) // catch-all
+ }
}
// If e != nil, it must be the shift expression; it may be nil for non-constant shifts.
@@ -1025,7 +1131,7 @@
}
if isComparison(op) {
- check.comparison(x, &y, op)
+ check.comparison(x, &y, op, false)
return
}
@@ -1253,11 +1359,11 @@
case hint != nil:
// no composite literal type present - use hint (element type of enclosing type)
typ = hint
- base = typ
- if !isTypeParam(typ) {
- base = under(typ)
+ base, _ = deref(coreType(typ)) // *T implies &T{}
+ if base == nil {
+ check.errorf(e, "invalid composite literal element type %s: no core type", typ)
+ goto Error
}
- base, _ = deref(base) // *T implies &T{}
default:
// TODO(gri) provide better error messages depending on context
@@ -1265,7 +1371,7 @@
goto Error
}
- switch utyp := structuralType(base).(type) {
+ switch utyp := coreType(base).(type) {
case *Struct:
// Prevent crash if the struct referred to is not yet set up.
// See analogous comment for *Array.
@@ -1450,7 +1556,7 @@
return kind
case *syntax.SelectorExpr:
- check.selector(x, e)
+ check.selector(x, e, nil)
case *syntax.IndexExpr:
if check.indexExpr(x, e) {
@@ -1476,8 +1582,7 @@
check.errorf(x, invalidOp+"cannot use type assertion on type parameter value %s", x)
goto Error
}
- xtyp, _ := under(x.typ).(*Interface)
- if xtyp == nil {
+ if _, ok := under(x.typ).(*Interface); !ok {
check.errorf(x, invalidOp+"%s is not an interface", x)
goto Error
}
@@ -1490,7 +1595,7 @@
if T == Typ[Invalid] {
goto Error
}
- check.typeAssertion(e, x, xtyp, T, false)
+ check.typeAssertion(e, x, T, false)
x.mode = commaok
x.typ = T
@@ -1537,6 +1642,7 @@
case invalid:
goto Error
case typexpr:
+ check.validVarType(e.X, x.typ)
x.typ = &Pointer{base: x.typ}
default:
var base Type
@@ -1631,28 +1737,21 @@
return x
}
-// typeAssertion checks that x.(T) is legal; xtyp must be the type of x.
-func (check *Checker) typeAssertion(e syntax.Expr, x *operand, xtyp *Interface, T Type, typeSwitch bool) {
- method, wrongType := check.assertableTo(xtyp, T)
+// typeAssertion checks x.(T). The type of x must be an interface.
+func (check *Checker) typeAssertion(e syntax.Expr, x *operand, T Type, typeSwitch bool) {
+ method, alt := check.assertableTo(under(x.typ).(*Interface), T)
if method == nil {
+ return // success
+ }
+
+ cause := check.missingMethodReason(T, x.typ, method, alt)
+
+ if typeSwitch {
+ check.errorf(e, "impossible type switch case: %s\n\t%s cannot have dynamic type %s %s", e, x, T, cause)
return
}
- var err error_
- var msg string
- if typeSwitch {
- err.errorf(e.Pos(), "impossible type switch case: %s", e)
- msg = check.sprintf("%s cannot have dynamic type %s %s", x, T,
- check.missingMethodReason(T, x.typ, method, wrongType))
-
- } else {
- err.errorf(e.Pos(), "impossible type assertion: %s", e)
- msg = check.sprintf("%s does not implement %s %s", T, x.typ,
- check.missingMethodReason(T, x.typ, method, wrongType))
-
- }
- err.errorf(nopos, msg)
- check.report(&err)
+ check.errorf(e, "impossible type assertion: %s\n\t%s does not implement %s %s", e, T, x.typ, cause)
}
// expr typechecks expression e and initializes x with the expression value.
diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go
index 4995d2d..61009c1 100644
--- a/src/cmd/compile/internal/types2/index.go
+++ b/src/cmd/compile/internal/types2/index.go
@@ -182,7 +182,7 @@
}
if !valid {
- check.errorf(x, invalidOp+"cannot index %s", x)
+ check.errorf(e.Pos(), invalidOp+"cannot index %s", x)
x.mode = invalid
return false
}
@@ -213,9 +213,9 @@
valid := false
length := int64(-1) // valid if >= 0
- switch u := structuralString(x.typ).(type) {
+ switch u := coreString(x.typ).(type) {
case nil:
- check.errorf(x, invalidOp+"cannot slice %s: %s has no structural type", x, x.typ)
+ check.errorf(x, invalidOp+"cannot slice %s: %s has no core type", x, x.typ)
x.mode = invalid
return
diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go
index b203985..e131077 100644
--- a/src/cmd/compile/internal/types2/infer.go
+++ b/src/cmd/compile/internal/types2/infer.go
@@ -19,15 +19,17 @@
// function arguments args, if any. There must be at least one type parameter, no more type arguments
// than type parameters, and params and args must match in number (incl. zero).
// If successful, infer returns the complete list of type arguments, one for each type parameter.
-// Otherwise the result is nil and appropriate errors will be reported unless report is set to false.
+// Otherwise the result is nil and appropriate errors will be reported.
//
-// Inference proceeds in 3 steps:
+// Inference proceeds as follows:
//
-// 1) Start with given type arguments.
-// 2) Infer type arguments from typed function arguments.
-// 3) Infer type arguments from untyped function arguments.
+// Starting with given type arguments
+// 1) apply FTI (function type inference) with typed arguments,
+// 2) apply CTI (constraint type inference),
+// 3) apply FTI with untyped function arguments,
+// 4) apply CTI.
//
-// Constraint type inference is used after each step to expand the set of type arguments.
+// The process stops as soon as all type arguments are known or an error occurs.
func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (result []Type) {
if debug {
defer func() {
@@ -39,6 +41,13 @@
}()
}
+ if traceInference {
+ check.dump("-- inferA %s%s ➞ %s", tparams, params, targs)
+ defer func() {
+ check.dump("=> inferA %s ➞ %s", tparams, result)
+ }()
+ }
+
// There must be at least one type parameter, and no more type arguments than type parameters.
n := len(tparams)
assert(n > 0 && len(targs) <= n)
@@ -46,34 +55,127 @@
// Function parameters and arguments must match in number.
assert(params.Len() == len(args))
- // --- 0 ---
// If we already have all type arguments, we're done.
if len(targs) == n {
return targs
}
// len(targs) < n
- // --- 1 ---
- // Explicitly provided type arguments take precedence over any inferred types;
- // and types inferred via constraint type inference take precedence over types
- // inferred from function arguments.
- // If we have type arguments, see how far we get with constraint type inference.
- if len(targs) > 0 && useConstraintTypeInference {
- var index int
- targs, index = check.inferB(pos, tparams, targs)
- if targs == nil || index < 0 {
- return targs
+ const enableTparamRenaming = true
+ if enableTparamRenaming {
+ // For the purpose of type inference we must differentiate type parameters
+ // occurring in explicit type or value function arguments from the type
+ // parameters we are solving for via unification, because they may be the
+ // same in self-recursive calls. For example:
+ //
+ // func f[P *Q, Q any](p P, q Q) {
+ // f(p)
+ // }
+ //
+ // In this example, the fact that the P used in the instantation f[P] has
+ // the same pointer identity as the P we are trying to solve for via
+ // unification is coincidental: there is nothing special about recursive
+ // calls that should cause them to conflate the identity of type arguments
+ // with type parameters. To put it another way: any such self-recursive
+ // call is equivalent to a mutually recursive call, which does not run into
+ // any problems of type parameter identity. For example, the following code
+ // is equivalent to the code above.
+ //
+ // func f[P interface{*Q}, Q any](p P, q Q) {
+ // f2(p)
+ // }
+ //
+ // func f2[P interface{*Q}, Q any](p P, q Q) {
+ // f(p)
+ // }
+ //
+ // We can turn the first example into the second example by renaming type
+ // parameters in the original signature to give them a new identity. As an
+ // optimization, we do this only for self-recursive calls.
+
+ // We can detect if we are in a self-recursive call by comparing the
+ // identity of the first type parameter in the current function with the
+ // first type parameter in tparams. This works because type parameters are
+ // unique to their type parameter list.
+ selfRecursive := check.sig != nil && check.sig.tparams.Len() > 0 && tparams[0] == check.sig.tparams.At(0)
+
+ if selfRecursive {
+ // In self-recursive inference, rename the type parameters with new type
+ // parameters that are the same but for their pointer identity.
+ tparams2 := make([]*TypeParam, len(tparams))
+ for i, tparam := range tparams {
+ tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil)
+ tparams2[i] = NewTypeParam(tname, nil)
+ tparams2[i].index = tparam.index // == i
+ }
+
+ renameMap := makeRenameMap(tparams, tparams2)
+ for i, tparam := range tparams {
+ tparams2[i].bound = check.subst(pos, tparam.bound, renameMap, nil)
+ }
+
+ tparams = tparams2
+ params = check.subst(pos, params, renameMap, nil).(*Tuple)
}
}
- // Continue with the type arguments we have now. Avoid matching generic
+ // If we have more than 2 arguments, we may have arguments with named and unnamed types.
+ // If that is the case, permutate params and args such that the arguments with named
+ // types are first in the list. This doesn't affect type inference if all types are taken
+ // as is. But when we have inexact unification enabled (as is the case for function type
+ // inference), when a named type is unified with an unnamed type, unification proceeds
+ // with the underlying type of the named type because otherwise unification would fail
+ // right away. This leads to an asymmetry in type inference: in cases where arguments of
+ // named and unnamed types are passed to parameters with identical type, different types
+ // (named vs underlying) may be inferred depending on the order of the arguments.
+ // By ensuring that named types are seen first, order dependence is avoided and unification
+ // succeeds where it can.
+ //
+ // This code is disabled for now pending decision whether we want to address cases like
+ // these and make the spec on type inference more complicated (see issue #43056).
+ const enableArgSorting = false
+ if m := len(args); m >= 2 && enableArgSorting {
+ // Determine indices of arguments with named and unnamed types.
+ var named, unnamed []int
+ for i, arg := range args {
+ if hasName(arg.typ) {
+ named = append(named, i)
+ } else {
+ unnamed = append(unnamed, i)
+ }
+ }
+
+ // If we have named and unnamed types, move the arguments with
+ // named types first. Update the parameter list accordingly.
+ // Make copies so as not to clobber the incoming slices.
+ if len(named) != 0 && len(unnamed) != 0 {
+ params2 := make([]*Var, m)
+ args2 := make([]*operand, m)
+ i := 0
+ for _, j := range named {
+ params2[i] = params.At(j)
+ args2[i] = args[j]
+ i++
+ }
+ for _, j := range unnamed {
+ params2[i] = params.At(j)
+ args2[i] = args[j]
+ i++
+ }
+ params = NewTuple(params2...)
+ args = args2
+ }
+ }
+
+ // --- 1 ---
+ // Continue with the type arguments we have. Avoid matching generic
// parameters that already have type arguments against function arguments:
// It may fail because matching uses type identity while parameter passing
// uses assignment rules. Instantiate the parameter list with the type
// arguments we have, and continue with that parameter list.
- // First, make sure we have a "full" list of type arguments, so of which
- // may be nil (unknown).
+ // First, make sure we have a "full" list of type arguments, some of which
+ // may be nil (unknown). Make a copy so as to not clobber the incoming slice.
if len(targs) < n {
targs2 := make([]Type, n)
copy(targs2, targs)
@@ -90,7 +192,6 @@
params = check.subst(nopos, params, smap, nil).(*Tuple)
}
- // --- 2 ---
// Unify parameter and argument types for generic parameters with typed arguments
// and collect the indices of generic parameters with untyped arguments.
// Terminology: generic parameter = function parameter with a type-parameterized type
@@ -143,7 +244,7 @@
if arg.mode == invalid {
// An error was reported earlier. Ignore this targ
// and continue, we may still be able to infer all
- // targs resulting in fewer follon-on errors.
+ // targs resulting in fewer follow-on errors.
continue
}
if targ := arg.typ; isTyped(targ) {
@@ -154,7 +255,12 @@
errorf("type", par.typ, targ, arg)
return nil
}
- } else {
+ } else if _, ok := par.typ.(*TypeParam); ok {
+ // Since default types are all basic (i.e., non-composite) types, an
+ // untyped argument will never match a composite parameter type; the
+ // only parameter type it can possibly match against is a *TypeParam.
+ // Thus, for untyped arguments we only need to look at parameter types
+ // that are single type parameters.
indices = append(indices, i)
}
}
@@ -167,6 +273,7 @@
return targs
}
+ // --- 2 ---
// See how far we get with constraint type inference.
// Note that even if we don't have any type arguments, constraint type inference
// may produce results for constraints that explicitly specify a type.
@@ -182,20 +289,17 @@
// Some generic parameters with untyped arguments may have been given
// a type by now, we can ignore them.
for _, i := range indices {
- par := params.At(i)
- // Since untyped types are all basic (i.e., non-composite) types, an
- // untyped argument will never match a composite parameter type; the
- // only parameter type it can possibly match against is a *TypeParam.
- // Thus, only consider untyped arguments for generic parameters that
- // are not of composite types and which don't have a type inferred yet.
- if tpar, _ := par.typ.(*TypeParam); tpar != nil && targs[tpar.index] == nil {
+ tpar := params.At(i).typ.(*TypeParam) // is type parameter by construction of indices
+ // Only consider untyped arguments for which the corresponding type
+ // parameter doesn't have an inferred type yet.
+ if targs[tpar.index] == nil {
arg := args[i]
targ := Default(arg.typ)
// The default type for an untyped nil is untyped nil. We must not
// infer an untyped nil type as type parameter type. Ignore untyped
// nil by making sure all default argument types are typed.
- if isTyped(targ) && !u.unify(par.typ, targ) {
- errorf("default type", par.typ, targ, arg)
+ if isTyped(targ) && !u.unify(tpar, targ) {
+ errorf("default type", tpar, targ, arg)
return nil
}
}
@@ -207,6 +311,7 @@
return targs
}
+ // --- 4 ---
// Again, follow up with constraint type inference.
if useConstraintTypeInference {
targs, index = check.inferB(pos, tparams, targs)
@@ -363,6 +468,13 @@
func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type) (types []Type, index int) {
assert(len(tparams) >= len(targs) && len(targs) > 0)
+ if traceInference {
+ check.dump("-- inferB %s ➞ %s", tparams, targs)
+ defer func() {
+ check.dump("=> inferB %s ➞ %s", tparams, types)
+ }()
+ }
+
// Setup bidirectional unification between constraints
// and the corresponding type arguments (which may be nil!).
u := newUnifier(false)
@@ -376,27 +488,88 @@
}
}
- // If a constraint has a structural type, unify the corresponding type parameter with it.
- for _, tpar := range tparams {
- sbound := structuralType(tpar)
- if sbound != nil {
- // If the structural type is the underlying type of a single
- // defined type in the constraint, use that defined type instead.
- if named, _ := tpar.singleType().(*Named); named != nil {
- sbound = named
- }
- if !u.unify(tpar, sbound) {
- // TODO(gri) improve error message by providing the type arguments
- // which we know already
- check.errorf(pos, "%s does not match %s", tpar, sbound)
- return nil, 0
+ // Repeatedly apply constraint type inference as long as
+ // there are still unknown type arguments and progress is
+ // being made.
+ //
+ // This is an O(n^2) algorithm where n is the number of
+ // type parameters: if there is progress (and iteration
+ // continues), at least one type argument is inferred
+ // per iteration and we have a doubly nested loop.
+ // In practice this is not a problem because the number
+ // of type parameters tends to be very small (< 5 or so).
+ // (It should be possible for unification to efficiently
+ // signal newly inferred type arguments; then the loops
+ // here could handle the respective type parameters only,
+ // but that will come at a cost of extra complexity which
+ // may not be worth it.)
+ for n := u.x.unknowns(); n > 0; {
+ nn := n
+
+ for i, tpar := range tparams {
+ // If there is a core term (i.e., a core type with tilde information)
+ // unify the type parameter with the core type.
+ if core, single := coreTerm(tpar); core != nil {
+ // A type parameter can be unified with its core type in two cases.
+ tx := u.x.at(i)
+ switch {
+ case tx != nil:
+ // The corresponding type argument tx is known.
+ // In this case, if the core type has a tilde, the type argument's underlying
+ // type must match the core type, otherwise the type argument and the core type
+ // must match.
+ // If tx is an external type parameter, don't consider its underlying type
+ // (which is an interface). Core type unification will attempt to unify against
+ // core.typ.
+ // Note also that even with inexact unification we cannot leave away the under
+ // call here because it's possible that both tx and core.typ are named types,
+ // with under(tx) being a (named) basic type matching core.typ. Such cases do
+ // not match with inexact unification.
+ if core.tilde && !isTypeParam(tx) {
+ tx = under(tx)
+ }
+ if !u.unify(tx, core.typ) {
+ // TODO(gri) improve error message by providing the type arguments
+ // which we know already
+ // Don't use term.String() as it always qualifies types, even if they
+ // are in the current package.
+ tilde := ""
+ if core.tilde {
+ tilde = "~"
+ }
+ check.errorf(pos, "%s does not match %s%s", tpar, tilde, core.typ)
+ return nil, 0
+ }
+
+ case single && !core.tilde:
+ // The corresponding type argument tx is unknown and there's a single
+ // specific type and no tilde.
+ // In this case the type argument must be that single type; set it.
+ u.x.set(i, core.typ)
+
+ default:
+ // Unification is not possible and no progress was made.
+ continue
+ }
+
+ // The number of known type arguments may have changed.
+ nn = u.x.unknowns()
+ if nn == 0 {
+ break // all type arguments are known
+ }
}
}
+
+ assert(nn <= n)
+ if nn == n {
+ break // no progress
+ }
+ n = nn
}
// u.x.types() now contains the incoming type arguments plus any additional type
- // arguments which were inferred from structural types. The newly inferred non-
- // nil entries may still contain references to other type parameters.
+ // arguments which were inferred from core terms. The newly inferred non-nil
+ // entries may still contain references to other type parameters.
// For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int
// was given, unification produced the type list [int, []C, *A]. We eliminate the
// remaining type parameters by substituting the type parameters in this type list
@@ -464,8 +637,8 @@
}
// Once nothing changes anymore, we may still have type parameters left;
- // e.g., a structural constraint *P may match a type parameter Q but we
- // don't have any type arguments to fill in for *P or Q (issue #45548).
+ // e.g., a constraint with core type *P may match a type parameter Q but
+ // we don't have any type arguments to fill in for *P or Q (issue #45548).
// Don't let such inferences escape, instead nil them out.
for i, typ := range types {
if typ != nil && isParameterized(tparams, typ) {
@@ -485,6 +658,42 @@
return
}
+// If the type parameter has a single specific type S, coreTerm returns (S, true).
+// Otherwise, if tpar has a core type T, it returns a term corresponding to that
+// core type and false. In that case, if any term of tpar has a tilde, the core
+// term has a tilde. In all other cases coreTerm returns (nil, false).
+func coreTerm(tpar *TypeParam) (*term, bool) {
+ n := 0
+ var single *term // valid if n == 1
+ var tilde bool
+ tpar.is(func(t *term) bool {
+ if t == nil {
+ assert(n == 0)
+ return false // no terms
+ }
+ n++
+ single = t
+ if t.tilde {
+ tilde = true
+ }
+ return true
+ })
+ if n == 1 {
+ if debug {
+ assert(debug && under(single.typ) == coreType(tpar))
+ }
+ return single, true
+ }
+ if typ := coreType(tpar); typ != nil {
+ // A core type is always an underlying type.
+ // If any term of tpar has a tilde, we don't
+ // have a precise core type and we must return
+ // a tilde as well.
+ return &term{tilde, typ}, false
+ }
+ return nil, false
+}
+
type cycleFinder struct {
tparams []*TypeParam
types []Type
@@ -530,8 +739,6 @@
// in signatures where they are handled explicitly.
case *Signature:
- // There are no "method types" so we should never see a recv.
- assert(t.recv == nil)
if t.params != nil {
w.varList(t.params.vars)
}
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index cda6c7b..9eced48 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -15,10 +15,10 @@
// Instantiate instantiates the type orig with the given type arguments targs.
// orig must be a *Named or a *Signature type. If there is no error, the
-// resulting Type is a new, instantiated (not parameterized) type of the same
-// kind (either a *Named or a *Signature). Methods attached to a *Named type
-// are also instantiated, and associated with a new *Func that has the same
-// position as the original method, but nil function scope.
+// resulting Type is an instantiated type of the same kind (either a *Named or
+// a *Signature). Methods attached to a *Named type are also instantiated, and
+// associated with a new *Func that has the same position as the original
+// method, but nil function scope.
//
// If ctxt is non-nil, it may be used to de-duplicate the instance against
// previous instances with the same identity. As a special case, generic
@@ -78,7 +78,7 @@
tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
named := check.newNamed(tname, orig, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved
named.targs = newTypeList(targs)
- named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) {
+ named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, *methodList) {
return expandNamed(ctxt, n, pos)
}
res = named
@@ -133,22 +133,16 @@
}
func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type) (int, error) {
- // TODO(rfindley): it would be great if users could pass in a qualifier here,
- // rather than falling back to verbose qualification. Maybe this can be part
- // of the shared context.
- var qf Qualifier
- if check != nil {
- qf = check.qualifier
- }
-
smap := makeSubstMap(tparams, targs)
for i, tpar := range tparams {
+ // Ensure that we have a (possibly implicit) interface as type bound (issue #51048).
+ tpar.iface()
// The type parameter bound is parameterized with the same type parameters
// as the instantiated type; before we can use it for bounds checking we
// need to instantiate it with the type arguments with which we instantiated
// the parameterized type.
bound := check.subst(pos, tpar.bound, smap, nil)
- if err := check.implements(targs[i], bound, qf); err != nil {
+ if err := check.implements(targs[i], bound); err != nil {
return i, err
}
}
@@ -156,21 +150,31 @@
}
// implements checks if V implements T and reports an error if it doesn't.
-// If a qualifier is provided, it is used in error formatting.
-func (check *Checker) implements(V, T Type, qf Qualifier) error {
+// The receiver may be nil if implements is called through an exported
+// API call such as AssignableTo.
+func (check *Checker) implements(V, T Type) error {
Vu := under(V)
Tu := under(T)
if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
- return nil
+ return nil // avoid follow-on errors
+ }
+ if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] {
+ return nil // avoid follow-on errors (see issue #49541 for an example)
}
errorf := func(format string, args ...interface{}) error {
- return errors.New(sprintf(qf, false, format, args...))
+ return errors.New(check.sprintf(format, args...))
}
Ti, _ := Tu.(*Interface)
if Ti == nil {
- return errorf("%s is not an interface", T)
+ var cause string
+ if isInterfacePtr(Tu) {
+ cause = check.sprintf("type %s is pointer to interface, not interface", T)
+ } else {
+ cause = check.sprintf("%s is not an interface", T)
+ }
+ return errorf("%s does not implement %s (%s)", V, T, cause)
}
// Every type satisfies the empty interface.
@@ -192,38 +196,22 @@
return errorf("cannot implement %s (empty type set)", T)
}
- // If T is comparable, V must be comparable.
- // TODO(gri) the error messages could be better, here
- if Ti.IsComparable() && !Comparable(V) {
- if Vi != nil && Vi.Empty() {
- return errorf("empty interface %s does not implement %s", V, T)
- }
- return errorf("%s does not implement comparable", V)
+ // V must implement T's methods, if any.
+ if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
+ return errorf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong))
}
- // V must implement T (methods)
- // - check only if we have methods
- if Ti.NumMethods() > 0 {
- if m, wrong := check.missingMethod(V, Ti, true); m != nil {
- // TODO(gri) needs to print updated name to avoid major confusion in error message!
- // (print warning for now)
- // Old warning:
- // check.softErrorf(pos, "%s does not implement %s (warning: name not updated) = %s (missing method %s)", V, T, Ti, m)
- if wrong != nil {
- // TODO(gri) This can still report uninstantiated types which makes the error message
- // more difficult to read then necessary.
- return errorf("%s does not implement %s: wrong method signature\n\tgot %s\n\twant %s",
- V, T, wrong, m,
- )
- }
- return errorf("%s does not implement %s (missing method %s)", V, T, m.name)
- }
+ // If T is comparable, V must be comparable.
+ // Remember as a pending error and report only if we don't have a more specific error.
+ var pending error
+ if Ti.IsComparable() && !comparable(V, false, nil, nil) {
+ pending = errorf("%s does not implement comparable", V)
}
// V must also be in the set of types of T, if any.
// Constraints with empty type sets were already excluded above.
if !Ti.typeSet().hasTerms() {
- return nil // nothing to do
+ return pending // nothing to do
}
// If V is itself an interface, each of its possible types must be in the set
@@ -234,7 +222,7 @@
// TODO(gri) report which type is missing
return errorf("%s does not implement %s", V, T)
}
- return nil
+ return pending
}
// Otherwise, V's type must be included in the iface type set.
@@ -262,5 +250,5 @@
}
}
- return nil
+ return pending
}
diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go
index b048fdd..75597ab 100644
--- a/src/cmd/compile/internal/types2/interface.go
+++ b/src/cmd/compile/internal/types2/interface.go
@@ -37,7 +37,7 @@
}
// set method receivers if necessary
- typ := new(Interface)
+ typ := (*Checker)(nil).newInterface()
for _, m := range methods {
if sig := m.typ.(*Signature); sig.recv == nil {
sig.recv = NewVar(m.pos, m.pkg, "", typ)
@@ -54,6 +54,15 @@
return typ
}
+// check may be nil
+func (check *Checker) newInterface() *Interface {
+ typ := &Interface{check: check}
+ if check != nil {
+ check.needsCleanup(typ)
+ }
+ return typ
+}
+
// MarkImplicit marks the interface t as implicit, meaning this interface
// corresponds to a constraint literal such as ~T or A|B without explicit
// interface embedding. MarkImplicit should be called before any concurrent use
@@ -86,7 +95,7 @@
func (t *Interface) Empty() bool { return t.typeSet().IsAll() }
// IsComparable reports whether each type in interface t's type set is comparable.
-func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() }
+func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable(nil) }
// IsMethodSet reports whether the interface t is fully described by its method set.
func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() }
@@ -100,6 +109,11 @@
// ----------------------------------------------------------------------------
// Implementation
+func (t *Interface) cleanup() {
+ t.check = nil
+ t.embedPos = nil
+}
+
func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) {
addEmbedded := func(pos syntax.Pos, typ Type) {
ityp.embeddeds = append(ityp.embeddeds, typ)
@@ -136,13 +150,6 @@
continue // ignore
}
- // Always type-check method type parameters but complain if they are not enabled.
- // (This extra check is needed here because interface method signatures don't have
- // a receiver specification.)
- if sig.tparams != nil && !acceptMethodTypeParams {
- check.error(f.Type, "methods cannot have type parameters")
- }
-
// use named receiver type if available (for better error messages)
var recvTyp Type = ityp
if def != nil {
@@ -169,16 +176,10 @@
// (don't sort embeddeds: they must correspond to *embedPos entries)
sortMethods(ityp.methods)
- // Compute type set with a non-nil *Checker as soon as possible
- // to report any errors. Subsequent uses of type sets will use
- // this computed type set and won't need to pass in a *Checker.
- //
- // Pin the checker to the interface type in the interim, in case the type set
- // must be used before delayed funcs are processed (see issue #48234).
- // TODO(rfindley): clean up use of *Checker with computeInterfaceTypeSet
- ityp.check = check
+ // Compute type set as soon as possible to report any errors.
+ // Subsequent uses of type sets will use this computed type
+ // set and won't need to pass in a *Checker.
check.later(func() {
computeInterfaceTypeSet(check, iface.Pos(), ityp)
- ityp.check = nil
}).describef(iface, "compute type set for %s", ityp)
}
diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go
index 9890b79..697a735 100644
--- a/src/cmd/compile/internal/types2/issues_test.go
+++ b/src/cmd/compile/internal/types2/issues_test.go
@@ -611,3 +611,29 @@
t.Errorf("type checking error for c does not disambiguate package template: %q", err)
}
}
+
+func TestIssue50646(t *testing.T) {
+ anyType := Universe.Lookup("any").Type()
+ comparableType := Universe.Lookup("comparable").Type()
+
+ if !Comparable(anyType) {
+ t.Errorf("any is not a comparable type")
+ }
+ if !Comparable(comparableType) {
+ t.Errorf("comparable is not a comparable type")
+ }
+
+ if Implements(anyType, comparableType.Underlying().(*Interface)) {
+ t.Errorf("any implements comparable")
+ }
+ if !Implements(comparableType, anyType.(*Interface)) {
+ t.Errorf("comparable does not implement any")
+ }
+
+ if AssignableTo(anyType, comparableType) {
+ t.Errorf("any assignable to comparable")
+ }
+ if !AssignableTo(comparableType, anyType) {
+ t.Errorf("comparable not assignable to any")
+ }
+}
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index ee764c7..0832877 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -7,7 +7,7 @@
package types2
import (
- "fmt"
+ "bytes"
"strings"
)
@@ -20,7 +20,7 @@
// in T and returns the corresponding *Var or *Func, an index sequence, and a
// bool indicating if there were any pointer indirections on the path to the
// field or method. If addressable is set, T is the type of an addressable
-// variable (only matters for method lookups).
+// variable (only matters for method lookups). T must not be nil.
//
// The last index entry is the field or method index in the (possibly embedded)
// type where the entry was found, either:
@@ -43,7 +43,11 @@
// the method's formal receiver base type, nor was the receiver addressable.
//
func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
- // Methods cannot be associated to a named pointer type
+ if T == nil {
+ panic("LookupFieldOrMethod on nil type")
+ }
+
+ // Methods cannot be associated to a named pointer type.
// (spec: "The type denoted by T is called the receiver base type;
// it must not be a pointer or interface type and it must be declared
// in the same package as the method.").
@@ -52,7 +56,7 @@
// not have found it for T (see also issue 8590).
if t, _ := T.(*Named); t != nil {
if p, _ := t.Underlying().(*Pointer); p != nil {
- obj, index, indirect = lookupFieldOrMethod(p, false, false, pkg, name)
+ obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name, false)
if _, ok := obj.(*Func); ok {
return nil, nil, false
}
@@ -60,7 +64,22 @@
}
}
- return lookupFieldOrMethod(T, addressable, false, pkg, name)
+ obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false)
+
+ // If we didn't find anything and if we have a type parameter with a core type,
+ // see if there is a matching field (but not a method, those need to be declared
+ // explicitly in the constraint). If the constraint is a named pointer type (see
+ // above), we are ok here because only fields are accepted as results.
+ const enableTParamFieldLookup = false // see issue #51576
+ if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
+ if t := coreType(T); t != nil {
+ obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
+ if _, ok := obj.(*Var); !ok {
+ obj, index, indirect = nil, nil, false // accept fields (variables) only
+ }
+ }
+ }
+ return
}
// TODO(gri) The named type consolidation and seen maps below must be
@@ -69,11 +88,11 @@
// indirectly via different packages.)
// lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
-// If checkFold is true, the lookup for methods will include looking for any method
+// If foldCase is true, the lookup for methods will include looking for any method
// which case-folds to the same as 'name' (used for giving helpful error messages).
//
// The resulting object may not be fully type-checked.
-func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, foldCase bool) (obj Object, index []int, indirect bool) {
// WARNING: The code in this function is extremely subtle - do not modify casually!
if name == "_" {
@@ -82,7 +101,7 @@
typ, isPtr := deref(T)
- // *typ where typ is an interface has no methods.
+ // *typ where typ is an interface (incl. a type parameter) has no methods.
if isPtr {
if _, ok := under(typ).(*Interface); ok {
return
@@ -106,7 +125,6 @@
var next []embeddedType // embedded types found at current depth
// look for (pkg, name) in all types at current depth
- var tpar *TypeParam // set if obj receiver is a type parameter
for _, e := range current {
typ := e.typ
@@ -128,7 +146,7 @@
// look for a matching attached method
named.resolve(nil)
- if i, m := lookupMethodFold(named.methods, pkg, name, checkFold); m != nil {
+ if i, m := named.lookupMethod(pkg, name, foldCase); m != nil {
// potential match
// caution: method may not have a proper signature yet
index = concat(e.index, i)
@@ -139,13 +157,9 @@
indirect = e.indirect
continue // we can't have a matching field or interface method
}
-
- // continue with underlying type
- typ = named.under()
}
- tpar = nil
- switch t := typ.(type) {
+ switch t := under(typ).(type) {
case *Struct:
// look for a matching field and collect embedded types
for i, f := range t.fields {
@@ -178,8 +192,8 @@
}
case *Interface:
- // look for a matching method
- if i, m := lookupMethodFold(t.typeSet().methods, pkg, name, checkFold); m != nil {
+ // look for a matching method (interface may be a type parameter)
+ if i, m := t.typeSet().LookupMethod(pkg, name, foldCase); m != nil {
assert(m.typ != nil)
index = concat(e.index, i)
if obj != nil || e.multiples {
@@ -188,24 +202,6 @@
obj = m
indirect = e.indirect
}
-
- case *TypeParam:
- if i, m := lookupMethodFold(t.iface().typeSet().methods, pkg, name, checkFold); m != nil {
- assert(m.typ != nil)
- index = concat(e.index, i)
- if obj != nil || e.multiples {
- return nil, index, false // collision
- }
- tpar = t
- obj = m
- indirect = e.indirect
- }
- if obj == nil {
- // At this point we're not (yet) looking into methods
- // that any underlying type of the types in the type list
- // might have.
- // TODO(gri) Do we want to specify the language that way?
- }
}
}
@@ -217,8 +213,7 @@
// is shorthand for (&x).m()".
if f, _ := obj.(*Func); f != nil {
// determine if method has a pointer receiver
- hasPtrRecv := tpar == nil && f.hasPtrRecv()
- if hasPtrRecv && !indirect && !addressable {
+ if f.hasPtrRecv() && !indirect && !addressable {
return nil, nil, true // pointer/addressable receiver required
}
}
@@ -288,56 +283,38 @@
// x is of interface type V).
//
func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) {
- m, typ := (*Checker)(nil).missingMethod(V, T, static)
- return m, typ != nil
+ m, alt := (*Checker)(nil).missingMethod(V, T, static)
+ // Only report a wrong type if the alternative method has the same name as m.
+ return m, alt != nil && alt.name == m.name // alt != nil implies m != nil
}
-// missingMethod is like MissingMethod but accepts a *Checker as
-// receiver and an addressable flag.
-// The receiver may be nil if missingMethod is invoked through
-// an exported API call (such as MissingMethod), i.e., when all
-// methods have been type-checked.
-// If the type has the correctly named method, but with the wrong
-// signature, the existing method is returned as well.
-// To improve error messages, also report the wrong signature
-// when the method exists on *V instead of V.
-func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, wrongType *Func) {
- // fast path for common case
- if T.Empty() {
+// missingMethod is like MissingMethod but accepts a *Checker as receiver.
+// The receiver may be nil if missingMethod is invoked through an exported
+// API call (such as MissingMethod), i.e., when all methods have been type-
+// checked.
+//
+// If a method is missing on T but is found on *T, or if a method is found
+// on T when looked up with case-folding, this alternative method is returned
+// as the second result.
+func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
+ if T.NumMethods() == 0 {
return
}
- if ityp, _ := under(V).(*Interface); ityp != nil {
- // TODO(gri) the methods are sorted - could do this more efficiently
+ // V is an interface
+ if u, _ := under(V).(*Interface); u != nil {
+ tset := u.typeSet()
for _, m := range T.typeSet().methods {
- _, f := ityp.typeSet().LookupMethod(m.pkg, m.name)
+ _, f := tset.LookupMethod(m.pkg, m.name, false)
if f == nil {
if !static {
continue
}
- // We don't do any case-fold check if V is an interface.
- return m, f
+ return m, nil
}
- // both methods must have the same number of type parameters
- ftyp := f.typ.(*Signature)
- mtyp := m.typ.(*Signature)
- if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() {
- return m, f
- }
- if !acceptMethodTypeParams && ftyp.TypeParams().Len() > 0 {
- panic("method with type parameters")
- }
-
- // If the methods have type parameters we don't care whether they
- // are the same or not, as long as they match up. Use unification
- // to see if they can be made to match.
- // TODO(gri) is this always correct? what about type bounds?
- // (Alternative is to rename/subst type parameters and compare.)
- u := newUnifier(true)
- u.x.init(ftyp.TypeParams().list())
- if !u.unify(ftyp, mtyp) {
+ if !Identical(f.typ, m.typ) {
return m, f
}
}
@@ -345,31 +322,22 @@
return
}
- // A concrete type implements T if it implements all methods of T.
+ // V is not an interface
for _, m := range T.typeSet().methods {
// TODO(gri) should this be calling LookupFieldOrMethod instead (and why not)?
- obj, _, _ := lookupFieldOrMethod(V, false, false, m.pkg, m.name)
+ obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name, false)
- // Check if *V implements this method of T.
- if obj == nil {
- ptr := NewPointer(V)
- obj, _, _ = lookupFieldOrMethod(ptr, false, false, m.pkg, m.name)
+ // check if m is on *V, or on V with case-folding
+ found := obj != nil
+ if !found {
+ // TODO(gri) Instead of NewPointer(V) below, can we just set the "addressable" argument?
+ obj, _, _ = lookupFieldOrMethod(NewPointer(V), false, m.pkg, m.name, false)
if obj == nil {
- // If we didn't find the exact method (even with pointer
- // receiver), look to see if there is a method that
- // matches m.name with case-folding.
- obj, _, _ = lookupFieldOrMethod(V, false, true, m.pkg, m.name)
- }
- if obj != nil {
- // methods may not have a fully set up signature yet
- if check != nil {
- check.objDecl(obj, nil)
- }
- return m, obj.(*Func)
+ obj, _, _ = lookupFieldOrMethod(V, false, m.pkg, m.name, true /* fold case */)
}
}
- // we must have a method (not a field of matching function type)
+ // we must have a method (not a struct field)
f, _ := obj.(*Func)
if f == nil {
return m, nil
@@ -380,37 +348,7 @@
check.objDecl(f, nil)
}
- // both methods must have the same number of type parameters
- ftyp := f.typ.(*Signature)
- mtyp := m.typ.(*Signature)
- if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() {
- return m, f
- }
- if !acceptMethodTypeParams && ftyp.TypeParams().Len() > 0 {
- panic("method with type parameters")
- }
-
- // If the methods have type parameters we don't care whether they
- // are the same or not, as long as they match up. Use unification
- // to see if they can be made to match.
- // TODO(gri) is this always correct? what about type bounds?
- // (Alternative is to rename/subst type parameters and compare.)
- u := newUnifier(true)
- if ftyp.TypeParams().Len() > 0 {
- // We reach here only if we accept method type parameters.
- // In this case, unification must consider any receiver
- // and method type parameters as "free" type parameters.
- assert(acceptMethodTypeParams)
- // We don't have a test case for this at the moment since
- // we can't parse method type parameters. Keeping the
- // unimplemented call so that we test this code if we
- // enable method type parameters.
- unimplemented()
- u.x.init(append(ftyp.RecvTypeParams().list(), ftyp.TypeParams().list()...))
- } else {
- u.x.init(ftyp.RecvTypeParams().list())
- }
- if !u.unify(ftyp, mtyp) {
+ if !found || !Identical(f.typ, m.typ) {
return m, f
}
}
@@ -420,55 +358,67 @@
// missingMethodReason returns a string giving the detailed reason for a missing method m,
// where m is missing from V, but required by T. It puts the reason in parentheses,
-// and may include more have/want info after that. If non-nil, wrongType is a relevant
+// and may include more have/want info after that. If non-nil, alt is a relevant
// method that matches in some way. It may have the correct name, but wrong type, or
// it may have a pointer receiver, or it may have the correct name except wrong case.
-func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string {
- var r string
+// check may be nil.
+func (check *Checker) missingMethodReason(V, T Type, m, alt *Func) string {
var mname string
- if check.conf.CompilerErrorMessages {
+ if check != nil && check.conf.CompilerErrorMessages {
mname = m.Name() + " method"
} else {
mname = "method " + m.Name()
}
- if wrongType != nil {
- if Identical(m.typ, wrongType.typ) {
- if m.Name() == wrongType.Name() {
- r = fmt.Sprintf("(%s has pointer receiver)", mname)
- } else {
- r = fmt.Sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
- mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
- }
- } else {
- if check.conf.CompilerErrorMessages {
- r = fmt.Sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
- mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
- } else {
- r = fmt.Sprintf("(wrong type for %s: have %s, want %s)",
- mname, wrongType.typ, m.typ)
- }
+
+ if alt != nil {
+ if m.Name() != alt.Name() {
+ return check.sprintf("(missing %s)\n\t\thave %s\n\t\twant %s",
+ mname, check.funcString(alt), check.funcString(m))
}
- // This is a hack to print the function type without the leading
- // 'func' keyword in the have/want printouts. We could change to have
- // an extra formatting option for types2.Type that doesn't print out
- // 'func'.
- r = strings.Replace(r, "^^func", "", -1)
- } else if IsInterface(T) && !isTypeParam(T) {
- if isInterfacePtr(V) {
- r = fmt.Sprintf("(%s is pointer to interface, not interface)", V)
+
+ if Identical(m.typ, alt.typ) {
+ return check.sprintf("(%s has pointer receiver)", mname)
}
- } else if isInterfacePtr(T) && !isTypeParam(T) {
- r = fmt.Sprintf("(%s is pointer to interface, not interface)", T)
+
+ return check.sprintf("(wrong type for %s)\n\t\thave %s\n\t\twant %s",
+ mname, check.funcString(alt), check.funcString(m))
}
- if r == "" {
- r = fmt.Sprintf("(missing %s)", mname)
+
+ if isInterfacePtr(V) {
+ return "(" + check.interfacePtrError(V) + ")"
}
- return r
+
+ if isInterfacePtr(T) {
+ return "(" + check.interfacePtrError(T) + ")"
+ }
+
+ return check.sprintf("(missing %s)", mname)
}
func isInterfacePtr(T Type) bool {
p, _ := under(T).(*Pointer)
- return p != nil && IsInterface(p.base) && !isTypeParam(p.base)
+ return p != nil && IsInterface(p.base)
+}
+
+// check may be nil.
+func (check *Checker) interfacePtrError(T Type) string {
+ assert(isInterfacePtr(T))
+ if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
+ return check.sprintf("type %s is pointer to type parameter, not type parameter", T)
+ }
+ return check.sprintf("type %s is pointer to interface, not interface", T)
+}
+
+// funcString returns a string of the form name + signature for f.
+// check may be nil.
+func (check *Checker) funcString(f *Func) string {
+ buf := bytes.NewBufferString(f.name)
+ var qf Qualifier
+ if check != nil {
+ qf = check.qualifier
+ }
+ WriteSignature(buf, f.typ.(*Signature), qf)
+ return buf.String()
}
// assertableTo reports whether a value of type V can be asserted to have type T.
@@ -476,18 +426,31 @@
// method required by V and whether it is missing or just has the wrong type.
// The receiver may be nil if assertableTo is invoked through an exported API call
// (such as AssertableTo), i.e., when all methods have been type-checked.
-// If the global constant forceStrict is set, assertions that are known to fail
-// are not permitted.
+// TODO(gri) replace calls to this function with calls to newAssertableTo.
func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Func) {
// no static check is required if T is an interface
// spec: "If T is an interface type, x.(T) asserts that the
// dynamic type of x implements the interface T."
- if IsInterface(T) && !forceStrict {
+ if IsInterface(T) {
return
}
+ // TODO(gri) fix this for generalized interfaces
return check.missingMethod(T, V, false)
}
+// newAssertableTo reports whether a value of type V can be asserted to have type T.
+// It also implements behavior for interfaces that currently are only permitted
+// in constraint position (we have not yet defined that behavior in the spec).
+func (check *Checker) newAssertableTo(V *Interface, T Type) error {
+ // no static check is required if T is an interface
+ // spec: "If T is an interface type, x.(T) asserts that the
+ // dynamic type of x implements the interface T."
+ if IsInterface(T) {
+ return nil
+ }
+ return check.implements(T, V)
+}
+
// deref dereferences typ if it is a *Pointer and returns its base and true.
// Otherwise it returns (typ, false).
func deref(typ Type) (Type, bool) {
@@ -536,28 +499,11 @@
}
// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
-func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
+// If foldCase is true, method names are considered equal if they are equal with case folding.
+func lookupMethod(methods []*Func, pkg *Package, name string, foldCase bool) (int, *Func) {
if name != "_" {
for i, m := range methods {
- if m.sameId(pkg, name) {
- return i, m
- }
- }
- }
- return -1, nil
-}
-
-// lookupMethodFold is like lookupMethod, but if checkFold is true, it matches a method
-// name if the names are equal with case folding.
-func lookupMethodFold(methods []*Func, pkg *Package, name string, checkFold bool) (int, *Func) {
- if name != "_" {
- for i, m := range methods {
- if m.name != name && !(checkFold && strings.EqualFold(m.name, name)) {
- continue
- }
- // Use m.name, since we've already checked that m.name and
- // name are equal with folding.
- if m.sameId(pkg, m.name) {
+ if (m.name == name || foldCase && strings.EqualFold(m.name, name)) && m.sameId(pkg, m.name) {
return i, m
}
}
diff --git a/src/cmd/compile/internal/types2/methodlist.go b/src/cmd/compile/internal/types2/methodlist.go
new file mode 100644
index 0000000..cd6c06c
--- /dev/null
+++ b/src/cmd/compile/internal/types2/methodlist.go
@@ -0,0 +1,79 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types2
+
+import "sync"
+
+// methodList holds a list of methods that may be lazily resolved by a provided
+// resolution method.
+type methodList struct {
+ methods []*Func
+
+ // guards synchronizes the instantiation of lazy methods. For lazy method
+ // lists, guards is non-nil and of the length passed to newLazyMethodList.
+ // For non-lazy method lists, guards is nil.
+ guards *[]sync.Once
+}
+
+// newMethodList creates a non-lazy method list holding the given methods.
+func newMethodList(methods []*Func) *methodList {
+ return &methodList{methods: methods}
+}
+
+// newLazyMethodList creates a lazy method list of the given length. Methods
+// may be resolved lazily for a given index by providing a resolver function.
+func newLazyMethodList(length int) *methodList {
+ guards := make([]sync.Once, length)
+ return &methodList{
+ methods: make([]*Func, length),
+ guards: &guards,
+ }
+}
+
+// isLazy reports whether the receiver is a lazy method list.
+func (l *methodList) isLazy() bool {
+ return l != nil && l.guards != nil
+}
+
+// Add appends a method to the method list if not not already present. Add
+// panics if the receiver is lazy.
+func (l *methodList) Add(m *Func) {
+ assert(!l.isLazy())
+ if i, _ := lookupMethod(l.methods, m.pkg, m.name, false); i < 0 {
+ l.methods = append(l.methods, m)
+ }
+}
+
+// Lookup looks up the method identified by pkg and name in the receiver.
+// Lookup panics if the receiver is lazy. If foldCase is true, method names
+// are considered equal if they are equal with case folding.
+func (l *methodList) Lookup(pkg *Package, name string, foldCase bool) (int, *Func) {
+ assert(!l.isLazy())
+ if l == nil {
+ return -1, nil
+ }
+ return lookupMethod(l.methods, pkg, name, foldCase)
+}
+
+// Len returns the length of the method list.
+func (l *methodList) Len() int {
+ if l == nil {
+ return 0
+ }
+ return len(l.methods)
+}
+
+// At returns the i'th method of the method list. At panics if i is out of
+// bounds, or if the receiver is lazy and resolve is nil.
+func (l *methodList) At(i int, resolve func() *Func) *Func {
+ if !l.isLazy() {
+ return l.methods[i]
+ }
+ assert(resolve != nil)
+ (*l.guards)[i].Do(func() {
+ l.methods[i] = resolve()
+ })
+ return l.methods[i]
+}
diff --git a/src/cmd/compile/internal/types2/methodlist_test.go b/src/cmd/compile/internal/types2/methodlist_test.go
new file mode 100644
index 0000000..7a183ac
--- /dev/null
+++ b/src/cmd/compile/internal/types2/methodlist_test.go
@@ -0,0 +1,40 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types2
+
+import (
+ "testing"
+)
+
+func TestLazyMethodList(t *testing.T) {
+ l := newLazyMethodList(2)
+
+ if got := l.Len(); got != 2 {
+ t.Fatalf("Len() = %d, want 2", got)
+ }
+
+ f0 := NewFunc(nopos, nil, "f0", nil)
+ f1 := NewFunc(nopos, nil, "f1", nil)
+
+ // Verify that methodList.At is idempotent, by calling it repeatedly with a
+ // resolve func that returns different pointer values (f0 or f1).
+ steps := []struct {
+ index int
+ resolve *Func // the *Func returned by the resolver
+ want *Func // the actual *Func returned by methodList.At
+ }{
+ {0, f0, f0},
+ {0, f1, f0},
+ {1, f1, f1},
+ {1, f0, f1},
+ }
+
+ for i, step := range steps {
+ got := l.At(step.index, func() *Func { return step.resolve })
+ if got != step.want {
+ t.Errorf("step %d: At(%d, ...) = %s, want %s", i, step.index, got.Name(), step.want.Name())
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go
index 51ea27a..daf8fdc 100644
--- a/src/cmd/compile/internal/types2/named.go
+++ b/src/cmd/compile/internal/types2/named.go
@@ -12,17 +12,22 @@
// A Named represents a named (defined) type.
type Named struct {
check *Checker
- info typeInfo // for cycle detection
obj *TypeName // corresponding declared object for declared types; placeholder for instantiated types
orig *Named // original, uninstantiated type
fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting)
underlying Type // possibly a *Named during setup; never a *Named once set up completely
tparams *TypeParamList // type parameters, or nil
targs *TypeList // type arguments (after instantiation), or nil
- methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily
+
+ // methods declared for this type (not the method set of this type).
+ // Signatures are type-checked lazily.
+ // For non-instantiated types, this is a fully populated list of methods. For
+ // instantiated types, this is a 'lazy' list, and methods are instantiated
+ // when they are first accessed.
+ methods *methodList
// resolver may be provided to lazily resolve type parameters, underlying, and methods.
- resolver func(*Context, *Named) (tparams *TypeParamList, underlying Type, methods []*Func)
+ resolver func(*Context, *Named) (tparams *TypeParamList, underlying Type, methods *methodList)
once sync.Once // ensures that tparams, underlying, and methods are resolved before accessing
}
@@ -33,7 +38,7 @@
if _, ok := underlying.(*Named); ok {
panic("underlying type must not be *Named")
}
- return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods)
+ return (*Checker)(nil).newNamed(obj, nil, underlying, nil, newMethodList(methods))
}
func (t *Named) resolve(ctxt *Context) *Named {
@@ -57,7 +62,7 @@
}
// newNamed is like NewNamed but with a *Checker receiver and additional orig argument.
-func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParamList, methods []*Func) *Named {
+func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParamList, methods *methodList) *Named {
typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods}
if typ.orig == nil {
typ.orig = typ
@@ -67,16 +72,36 @@
}
// Ensure that typ is always expanded and sanity-checked.
if check != nil {
- check.defTypes = append(check.defTypes, typ)
+ check.needsCleanup(typ)
}
return typ
}
+func (t *Named) cleanup() {
+ // Ensure that every defined type created in the course of type-checking has
+ // either non-*Named underlying, or is unresolved.
+ //
+ // This guarantees that we don't leak any types whose underlying is *Named,
+ // because any unresolved instances will lazily compute their underlying by
+ // substituting in the underlying of their origin. The origin must have
+ // either been imported or type-checked and expanded here, and in either case
+ // its underlying will be fully expanded.
+ switch t.underlying.(type) {
+ case nil:
+ if t.resolver == nil {
+ panic("nil underlying")
+ }
+ case *Named:
+ t.under() // t.under may add entries to check.cleaners
+ }
+ t.check = nil
+}
+
// Obj returns the type name for the declaration defining the named type t. For
-// instantiated types, this is the type name of the base type.
+// instantiated types, this is same as the type name of the origin type.
func (t *Named) Obj() *TypeName { return t.orig.obj } // for non-instances this is the same as t.obj
-// Origin returns the parameterized type from which the named type t is
+// Origin returns the generic type from which the named type t is
// instantiated. If t is not an instantiated type, the result is t.
func (t *Named) Origin() *Named { return t.orig }
@@ -84,23 +109,95 @@
// between parameterized instantiated and non-instantiated types.
// TypeParams returns the type parameters of the named type t, or nil.
-// The result is non-nil for an (originally) parameterized type even if it is instantiated.
+// The result is non-nil for an (originally) generic type even if it is instantiated.
func (t *Named) TypeParams() *TypeParamList { return t.resolve(nil).tparams }
// SetTypeParams sets the type parameters of the named type t.
-func (t *Named) SetTypeParams(tparams []*TypeParam) { t.resolve(nil).tparams = bindTParams(tparams) }
+// t must not have type arguments.
+func (t *Named) SetTypeParams(tparams []*TypeParam) {
+ assert(t.targs.Len() == 0)
+ t.resolve(nil).tparams = bindTParams(tparams)
+}
// TypeArgs returns the type arguments used to instantiate the named type t.
func (t *Named) TypeArgs() *TypeList { return t.targs }
-// NumMethods returns the number of explicit methods whose receiver is named type t.
-func (t *Named) NumMethods() int { return len(t.resolve(nil).methods) }
+// NumMethods returns the number of explicit methods defined for t.
+//
+// For an ordinary or instantiated type t, the receiver base type of these
+// methods will be the named type t. For an uninstantiated generic type t, each
+// method receiver will be instantiated with its receiver type parameters.
+func (t *Named) NumMethods() int { return t.resolve(nil).methods.Len() }
// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
-func (t *Named) Method(i int) *Func { return t.resolve(nil).methods[i] }
+func (t *Named) Method(i int) *Func {
+ t.resolve(nil)
+ return t.methods.At(i, func() *Func {
+ return t.instantiateMethod(i)
+ })
+}
+
+// instiateMethod instantiates the i'th method for an instantiated receiver.
+func (t *Named) instantiateMethod(i int) *Func {
+ assert(t.TypeArgs().Len() > 0) // t must be an instance
+
+ // t.orig.methods is not lazy. origm is the method instantiated with its
+ // receiver type parameters (the "origin" method).
+ origm := t.orig.Method(i)
+ assert(origm != nil)
+
+ check := t.check
+ // Ensure that the original method is type-checked.
+ if check != nil {
+ check.objDecl(origm, nil)
+ }
+
+ origSig := origm.typ.(*Signature)
+ rbase, _ := deref(origSig.Recv().Type())
+
+ // If rbase is t, then origm is already the instantiated method we're looking
+ // for. In this case, we return origm to preserve the invariant that
+ // traversing Method->Receiver Type->Method should get back to the same
+ // method.
+ //
+ // This occurs if t is instantiated with the receiver type parameters, as in
+ // the use of m in func (r T[_]) m() { r.m() }.
+ if rbase == t {
+ return origm
+ }
+
+ sig := origSig
+ // We can only substitute if we have a correspondence between type arguments
+ // and type parameters. This check is necessary in the presence of invalid
+ // code.
+ if origSig.RecvTypeParams().Len() == t.targs.Len() {
+ ctxt := check.bestContext(nil)
+ smap := makeSubstMap(origSig.RecvTypeParams().list(), t.targs.list())
+ sig = check.subst(origm.pos, origSig, smap, ctxt).(*Signature)
+ }
+
+ if sig == origSig {
+ // No substitution occurred, but we still need to create a new signature to
+ // hold the instantiated receiver.
+ copy := *origSig
+ sig = ©
+ }
+
+ var rtyp Type
+ if origm.hasPtrRecv() {
+ rtyp = NewPointer(t)
+ } else {
+ rtyp = t
+ }
+
+ sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp)
+ return NewFunc(origm.pos, origm.pkg, origm.name, sig)
+}
// SetUnderlying sets the underlying type and marks t as complete.
+// t must not have type arguments.
func (t *Named) SetUnderlying(underlying Type) {
+ assert(t.targs.Len() == 0)
if underlying == nil {
panic("underlying type must not be nil")
}
@@ -108,14 +205,20 @@
panic("underlying type must not be *Named")
}
t.resolve(nil).underlying = underlying
+ if t.fromRHS == nil {
+ t.fromRHS = underlying // for cycle detection
+ }
}
// AddMethod adds method m unless it is already in the method list.
+// t must not have type arguments.
func (t *Named) AddMethod(m *Func) {
+ assert(t.targs.Len() == 0)
t.resolve(nil)
- if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
- t.methods = append(t.methods, m)
+ if t.methods == nil {
+ t.methods = newMethodList(nil)
}
+ t.methods.Add(m)
}
func (t *Named) Underlying() Type { return t.resolve(nil).underlying }
@@ -218,6 +321,19 @@
}
}
+func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
+ n.resolve(nil)
+ // If n is an instance, we may not have yet instantiated all of its methods.
+ // Look up the method index in orig, and only instantiate method at the
+ // matching index (if any).
+ i, _ := n.orig.methods.Lookup(pkg, name, foldCase)
+ if i < 0 {
+ return -1, nil
+ }
+ // For instances, m.Method(i) will be different from the orig method.
+ return i, n.Method(i)
+}
+
// bestContext returns the best available context. In order of preference:
// - the given ctxt, if non-nil
// - check.ctxt, if check is non-nil
@@ -237,7 +353,7 @@
// expandNamed ensures that the underlying type of n is instantiated.
// The underlying type will be Typ[Invalid] if there was an error.
-func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) {
+func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypeParamList, underlying Type, methods *methodList) {
n.orig.resolve(ctxt)
assert(n.orig.underlying != nil)
@@ -259,80 +375,30 @@
smap := makeSubstMap(n.orig.tparams.list(), n.targs.list())
underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt)
-
- for i := 0; i < n.orig.NumMethods(); i++ {
- origm := n.orig.Method(i)
-
- // During type checking origm may not have a fully set up type, so defer
- // instantiation of its signature until later.
- m := NewFunc(origm.pos, origm.pkg, origm.name, nil)
- m.hasPtrRecv_ = origm.hasPtrRecv()
- // Setting instRecv here allows us to complete later (we need the
- // instRecv to get targs and the original method).
- m.instRecv = n
-
- methods = append(methods, m)
+ // If the underlying of n is an interface, we need to set the receiver of
+ // its methods accurately -- we set the receiver of interface methods on
+ // the RHS of a type declaration to the defined type.
+ if iface, _ := underlying.(*Interface); iface != nil {
+ if methods, copied := replaceRecvType(iface.methods, n.orig, n); copied {
+ // If the underlying doesn't actually use type parameters, it's possible
+ // that it wasn't substituted. In this case we need to create a new
+ // *Interface before modifying receivers.
+ if iface == n.orig.underlying {
+ old := iface
+ iface = check.newInterface()
+ iface.embeddeds = old.embeddeds
+ iface.complete = old.complete
+ iface.implicit = old.implicit // should be false but be conservative
+ underlying = iface
+ }
+ iface.methods = methods
+ }
}
} else {
underlying = Typ[Invalid]
}
- // Methods should not escape the type checker API without being completed. If
- // we're in the context of a type checking pass, we need to defer this until
- // later (not all methods may have types).
- completeMethods := func() {
- for _, m := range methods {
- if m.instRecv != nil {
- check.completeMethod(ctxt, m)
- }
- }
- }
- if check != nil {
- check.later(completeMethods)
- } else {
- completeMethods()
- }
-
- return n.orig.tparams, underlying, methods
-}
-
-func (check *Checker) completeMethod(ctxt *Context, m *Func) {
- assert(m.instRecv != nil)
- rbase := m.instRecv
- m.instRecv = nil
- m.setColor(black)
-
- assert(rbase.TypeArgs().Len() > 0)
-
- // Look up the original method.
- _, orig := lookupMethod(rbase.orig.methods, rbase.obj.pkg, m.name)
- assert(orig != nil)
- if check != nil {
- check.objDecl(orig, nil)
- }
- origSig := orig.typ.(*Signature)
- if origSig.RecvTypeParams().Len() != rbase.targs.Len() {
- m.typ = origSig // or new(Signature), but we can't use Typ[Invalid]: Funcs must have Signature type
- return // error reported elsewhere
- }
-
- smap := makeSubstMap(origSig.RecvTypeParams().list(), rbase.targs.list())
- sig := check.subst(orig.pos, origSig, smap, ctxt).(*Signature)
- if sig == origSig {
- // No substitution occurred, but we still need to create a new signature to
- // hold the instantiated receiver.
- copy := *origSig
- sig = ©
- }
- var rtyp Type
- if m.hasPtrRecv() {
- rtyp = NewPointer(rbase)
- } else {
- rtyp = rbase
- }
- sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp)
-
- m.typ = sig
+ return n.orig.tparams, underlying, newLazyMethodList(n.orig.methods.Len())
}
// safeUnderlying returns the underlying of typ without expanding instances, to
diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go
index c7c64ca..08d37cb 100644
--- a/src/cmd/compile/internal/types2/object.go
+++ b/src/cmd/compile/internal/types2/object.go
@@ -281,7 +281,7 @@
func NewTypeNameLazy(pos syntax.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName {
obj := NewTypeName(pos, pkg, name, nil)
- resolve := func(_ *Context, t *Named) (*TypeParamList, Type, []*Func) {
+ resolve := func(_ *Context, t *Named) (*TypeParamList, Type, *methodList) {
tparams, underlying, methods := load(t)
switch underlying.(type) {
@@ -289,7 +289,7 @@
panic(fmt.Sprintf("invalid underlying type %T", t.underlying))
}
- return bindTParams(tparams), underlying, methods
+ return bindTParams(tparams), underlying, newMethodList(methods)
}
NewNamed(obj, nil, nil).resolver = resolve
@@ -365,8 +365,7 @@
// An abstract method may belong to many interfaces due to embedding.
type Func struct {
object
- instRecv *Named // if non-nil, the receiver type for an incomplete instance method
- hasPtrRecv_ bool // only valid for methods that don't have a type yet; use hasPtrRecv() to read
+ hasPtrRecv_ bool // only valid for methods that don't have a type yet; use hasPtrRecv() to read
}
// NewFunc returns a new function with the given signature, representing
@@ -377,7 +376,7 @@
if sig != nil {
typ = sig
}
- return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, nil, false}
+ return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, false}
}
// FullName returns the package- or receiver-type-qualified name of
diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go
index f6bd029..fce9a11 100644
--- a/src/cmd/compile/internal/types2/operand.go
+++ b/src/cmd/compile/internal/types2/operand.go
@@ -288,47 +288,26 @@
return true, 0
}
- // T is an interface type and x implements T and T is not a type parameter
- if Ti, ok := Tu.(*Interface); ok && Tp == nil {
- if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
+ // T is an interface type and x implements T and T is not a type parameter.
+ // Also handle the case where T is a pointer to an interface.
+ if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
+ if err := check.implements(V, T); err != nil {
if reason != nil {
- if check.conf.CompilerErrorMessages {
- *reason = check.sprintf("%s does not implement %s %s", x.typ, T,
- check.missingMethodReason(x.typ, T, m, wrongType))
- } else {
- if wrongType != nil {
- if Identical(m.typ, wrongType.typ) {
- *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name)
- } else {
- *reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ)
- }
- } else {
- *reason = "missing method " + m.Name()
- }
- }
+ *reason = err.Error()
}
return false, _InvalidIfaceAssign
}
return true, 0
}
- // Provide extra detail in compiler error messages in some cases when T is
- // not an interface.
- if check != nil && check.conf.CompilerErrorMessages {
- if isInterfacePtr(Tu) {
+ // If V is an interface, check if a missing type assertion is the problem.
+ if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
+ if check.implements(T, V) == nil {
+ // T implements V, so give hint about type assertion.
if reason != nil {
- *reason = check.sprintf("%s does not implement %s (%s is pointer to interface, not interface)", x.typ, T, T)
+ *reason = "need type assertion"
}
- return false, _InvalidIfaceAssign
- }
- if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
- if m, _ := check.missingMethod(T, Vi, true); m == nil {
- // T implements Vi, so give hint about type assertion.
- if reason != nil {
- *reason = check.sprintf("need type assertion")
- }
- return false, _IncompatibleAssign
- }
+ return false, _IncompatibleAssign
}
}
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go
index cf2993f..ba25934 100644
--- a/src/cmd/compile/internal/types2/predicates.go
+++ b/src/cmd/compile/internal/types2/predicates.go
@@ -31,7 +31,7 @@
// The allX predicates below report whether t is an X.
// If t is a type parameter the result is true if isX is true
// for all specified types of the type parameter's type set.
-// allX is an optimized version of isX(structuralType(t)) (which
+// allX is an optimized version of isX(coreType(t)) (which
// is the same as underIs(t, isX)).
func allBoolean(t Type) bool { return allBasic(t, IsBoolean) }
@@ -45,7 +45,7 @@
// allBasic reports whether under(t) is a basic type with the specified info.
// If t is a type parameter, the result is true if isBasic(t, info) is true
// for all specific types of the type parameter's type set.
-// allBasic(t, info) is an optimized version of isBasic(structuralType(t), info).
+// allBasic(t, info) is an optimized version of isBasic(coreType(t), info).
func allBasic(t Type, info BasicInfo) bool {
if tpar, _ := t.(*TypeParam); tpar != nil {
return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })
@@ -102,10 +102,12 @@
// Comparable reports whether values of type T are comparable.
func Comparable(T Type) bool {
- return comparable(T, nil)
+ return comparable(T, true, nil, nil)
}
-func comparable(T Type, seen map[Type]bool) bool {
+// If dynamic is set, non-type parameter interfaces are always comparable.
+// If reportf != nil, it may be used to report why T is not comparable.
+func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool {
if seen[T] {
return true
}
@@ -123,15 +125,24 @@
return true
case *Struct:
for _, f := range t.fields {
- if !comparable(f.typ, seen) {
+ if !comparable(f.typ, dynamic, seen, nil) {
+ if reportf != nil {
+ reportf("struct containing %s cannot be compared", f.typ)
+ }
return false
}
}
return true
case *Array:
- return comparable(t.elem, seen)
+ if !comparable(t.elem, dynamic, seen, nil) {
+ if reportf != nil {
+ reportf("%s cannot be compared", t)
+ }
+ return false
+ }
+ return true
case *Interface:
- return !isTypeParam(T) || t.IsComparable()
+ return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen)
}
return false
}
@@ -287,8 +298,11 @@
case *Union:
if y, _ := y.(*Union); y != nil {
- xset := computeUnionTypeSet(nil, nopos, x)
- yset := computeUnionTypeSet(nil, nopos, y)
+ // TODO(rfindley): can this be reached during type checking? If so,
+ // consider passing a type set map.
+ unionSets := make(map[*Union]*_TypeSet)
+ xset := computeUnionTypeSet(nil, unionSets, nopos, x)
+ yset := computeUnionTypeSet(nil, unionSets, nopos, y)
return xset.terms.equal(yset.terms)
}
@@ -303,6 +317,9 @@
if y, ok := y.(*Interface); ok {
xset := x.typeSet()
yset := y.typeSet()
+ if xset.comparable != yset.comparable {
+ return false
+ }
if !xset.terms.equal(yset.terms) {
return false
}
diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go
index a8cb244..61963cb 100644
--- a/src/cmd/compile/internal/types2/resolver.go
+++ b/src/cmd/compile/internal/types2/resolver.go
@@ -413,7 +413,7 @@
case *syntax.TypeDecl:
if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) {
- check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
+ check.versionErrorf(s.TParamList[0], "go1.18", "type parameter")
}
obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil)
check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, tdecl: s})
@@ -448,22 +448,17 @@
} else {
// method
// d.Recv != nil
- if !acceptMethodTypeParams && len(s.TParamList) != 0 {
- //check.error(d.TParamList.Pos(), invalidAST + "method must have no type parameters")
- check.error(s.TParamList[0], invalidAST+"method must have no type parameters")
- hasTParamError = true
- }
ptr, recv, _ := check.unpackRecv(s.Recv.Type, false)
- // (Methods with invalid receiver cannot be associated to a type, and
+ // Methods with invalid receiver cannot be associated to a type, and
// methods with blank _ names are never found; no need to collect any
- // of them. They will still be type-checked with all the other functions.)
+ // of them. They will still be type-checked with all the other functions.
if recv != nil && name != "_" {
methods = append(methods, methodInfo{obj, ptr, recv})
}
check.recordDef(s.Name, obj)
}
if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError {
- check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
+ check.versionErrorf(s.TParamList[0], "go1.18", "type parameter")
}
info := &declInfo{file: fileScope, fdecl: s}
// Methods are not package-level objects but we still track them in the
@@ -661,25 +656,31 @@
}
}
- // We process non-alias declarations first, in order to avoid situations where
- // the type of an alias declaration is needed before it is available. In general
- // this is still not enough, as it is possible to create sufficiently convoluted
- // recursive type definitions that will cause a type alias to be needed before it
- // is available (see issue #25838 for examples).
- // As an aside, the cmd/compiler suffers from the same problem (#25838).
+ // We process non-alias type declarations first, followed by alias declarations,
+ // and then everything else. This appears to avoid most situations where the type
+ // of an alias is needed before it is available.
+ // There may still be cases where this is not good enough (see also issue #25838).
+ // In those cases Checker.ident will report an error ("invalid use of type alias").
var aliasList []*TypeName
- // phase 1
+ var othersList []Object // everything that's not a type
+ // phase 1: non-alias type declarations
for _, obj := range objList {
- // If we have a type alias, collect it for the 2nd phase.
- if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Alias {
- aliasList = append(aliasList, tname)
- continue
+ if tname, _ := obj.(*TypeName); tname != nil {
+ if check.objMap[tname].tdecl.Alias {
+ aliasList = append(aliasList, tname)
+ } else {
+ check.objDecl(obj, nil)
+ }
+ } else {
+ othersList = append(othersList, obj)
}
-
+ }
+ // phase 2: alias type declarations
+ for _, obj := range aliasList {
check.objDecl(obj, nil)
}
- // phase 2
- for _, obj := range aliasList {
+ // phase 3: all other declarations
+ for _, obj := range othersList {
check.objDecl(obj, nil)
}
diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go
index 06dcd91..c98024f 100644
--- a/src/cmd/compile/internal/types2/signature.go
+++ b/src/cmd/compile/internal/types2/signature.go
@@ -73,9 +73,6 @@
// RecvTypeParams returns the receiver type parameters of signature s, or nil.
func (s *Signature) RecvTypeParams() *TypeParamList { return s.rparams }
-// SetRecvTypeParams sets the receiver type params of signature s.
-func (s *Signature) SetRecvTypeParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) }
-
// Params returns the parameters of signature s, or nil.
func (s *Signature) Params() *Tuple { return s.params }
@@ -91,9 +88,6 @@
// ----------------------------------------------------------------------------
// Implementation
-// Disabled by default, but enabled when running tests (via types_test.go).
-var acceptMethodTypeParams bool
-
// funcType type-checks a function or method type.
func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []*syntax.Field, ftyp *syntax.FuncType) {
check.openScope(ftyp, "function")
@@ -122,11 +116,10 @@
// lookup in the scope.
for i, p := range rparams {
if p.Value == "_" {
- tpar := sig.rparams.At(i)
if check.recvTParamMap == nil {
check.recvTParamMap = make(map[*syntax.Name]*TypeParam)
}
- check.recvTParamMap[p] = tpar
+ check.recvTParamMap[p] = tparams[i]
}
}
// determine receiver type to get its type parameters
@@ -142,34 +135,30 @@
}
}
// provide type parameter bounds
- // - only do this if we have the right number (otherwise an error is reported elsewhere)
- if sig.RecvTypeParams().Len() == len(recvTParams) {
- // We have a list of *TypeNames but we need a list of Types.
- list := make([]Type, sig.RecvTypeParams().Len())
- for i, t := range sig.RecvTypeParams().list() {
- list[i] = t
- check.mono.recordCanon(t, recvTParams[i])
+ if len(tparams) == len(recvTParams) {
+ smap := makeRenameMap(recvTParams, tparams)
+ for i, tpar := range tparams {
+ recvTPar := recvTParams[i]
+ check.mono.recordCanon(tpar, recvTPar)
+ // recvTPar.bound is (possibly) parameterized in the context of the
+ // receiver type declaration. Substitute parameters for the current
+ // context.
+ tpar.bound = check.subst(tpar.obj.pos, recvTPar.bound, smap, nil)
}
- smap := makeSubstMap(recvTParams, list)
- for i, tpar := range sig.RecvTypeParams().list() {
- bound := recvTParams[i].bound
- // bound is (possibly) parameterized in the context of the
- // receiver type declaration. Substitute parameters for the
- // current context.
- tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil)
- }
+ } else if len(tparams) < len(recvTParams) {
+ // Reporting an error here is a stop-gap measure to avoid crashes in the
+ // compiler when a type parameter/argument cannot be inferred later. It
+ // may lead to follow-on errors (see issues #51339, #51343).
+ // TODO(gri) find a better solution
+ got := measure(len(tparams), "type parameter")
+ check.errorf(recvPar, "got %s, but receiver base type declares %d", got, len(recvTParams))
}
}
}
if tparams != nil {
+ // The parser will complain about invalid type parameters for methods.
check.collectTypeParams(&sig.tparams, tparams)
- // Always type-check method type parameters but complain if they are not enabled.
- // (A separate check is needed when type-checking interface method signatures because
- // they don't have a receiver specification.)
- if recvPar != nil && !acceptMethodTypeParams {
- check.error(ftyp, "methods cannot have type parameters")
- }
}
// Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their
@@ -205,66 +194,69 @@
case 1:
recv = recvList[0]
}
+ sig.recv = recv
- // TODO(gri) We should delay rtyp expansion to when we actually need the
- // receiver; thus all checks here should be delayed to later.
- rtyp, _ := deref(recv.typ)
+ // Delay validation of receiver type as it may cause premature expansion
+ // of types the receiver type is dependent on (see issues #51232, #51233).
+ check.later(func() {
+ rtyp, _ := deref(recv.typ)
- // spec: "The receiver type must be of the form T or *T where T is a type name."
- // (ignore invalid types - error was reported before)
- if rtyp != Typ[Invalid] {
- var err string
- switch T := rtyp.(type) {
- case *Named:
- T.resolve(check.bestContext(nil))
- // The receiver type may be an instantiated type referred to
- // by an alias (which cannot have receiver parameters for now).
- if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
- check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ)
- break
- }
- // spec: "The type denoted by T is called the receiver base type; it must not
- // be a pointer or interface type and it must be declared in the same package
- // as the method."
- if T.obj.pkg != check.pkg {
- err = "type not defined in this package"
+ // spec: "The receiver type must be of the form T or *T where T is a type name."
+ // (ignore invalid types - error was reported before)
+ if rtyp != Typ[Invalid] {
+ var err string
+ switch T := rtyp.(type) {
+ case *Named:
+ T.resolve(check.bestContext(nil))
+ // The receiver type may be an instantiated type referred to
+ // by an alias (which cannot have receiver parameters for now).
+ if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
+ check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ)
+ break
+ }
+ // spec: "The type denoted by T is called the receiver base type; it must not
+ // be a pointer or interface type and it must be declared in the same package
+ // as the method."
+ if T.obj.pkg != check.pkg {
+ err = "type not defined in this package"
+ if check.conf.CompilerErrorMessages {
+ check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
+ err = ""
+ }
+ } else {
+ // The underlying type of a receiver base type can be a type parameter;
+ // e.g. for methods with a generic receiver T[P] with type T[P any] P.
+ // TODO(gri) Such declarations are currently disallowed.
+ // Revisit the need for underIs.
+ underIs(T, func(u Type) bool {
+ switch u := u.(type) {
+ case *Basic:
+ // unsafe.Pointer is treated like a regular pointer
+ if u.kind == UnsafePointer {
+ err = "unsafe.Pointer"
+ return false
+ }
+ case *Pointer, *Interface:
+ err = "pointer or interface type"
+ return false
+ }
+ return true
+ })
+ }
+ case *Basic:
+ err = "basic or unnamed type"
if check.conf.CompilerErrorMessages {
check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
err = ""
}
- } else {
- // The underlying type of a receiver base type can be a type parameter;
- // e.g. for methods with a generic receiver T[P] with type T[P any] P.
- underIs(T, func(u Type) bool {
- switch u := u.(type) {
- case *Basic:
- // unsafe.Pointer is treated like a regular pointer
- if u.kind == UnsafePointer {
- err = "unsafe.Pointer"
- return false
- }
- case *Pointer, *Interface:
- err = "pointer or interface type"
- return false
- }
- return true
- })
+ default:
+ check.errorf(recv.pos, "invalid receiver type %s", recv.typ)
}
- case *Basic:
- err = "basic or unnamed type"
- if check.conf.CompilerErrorMessages {
- check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
- err = ""
+ if err != "" {
+ check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err)
}
- default:
- check.errorf(recv.pos, "invalid receiver type %s", recv.typ)
}
- if err != "" {
- check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err)
- // ok to continue
- }
- }
- sig.recv = recv
+ }).describef(recv, "validate receiver %s", recv)
}
sig.params = NewTuple(params...)
diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go
index 99b846b..1402005 100644
--- a/src/cmd/compile/internal/types2/sizeof_test.go
+++ b/src/cmd/compile/internal/types2/sizeof_test.go
@@ -27,11 +27,11 @@
{Pointer{}, 8, 16},
{Tuple{}, 12, 24},
{Signature{}, 28, 56},
- {Union{}, 16, 32},
+ {Union{}, 12, 24},
{Interface{}, 44, 88},
{Map{}, 16, 32},
{Chan{}, 12, 24},
- {Named{}, 68, 128},
+ {Named{}, 56, 104},
{TypeParam{}, 28, 48},
{term{}, 12, 24},
@@ -40,7 +40,7 @@
{Const{}, 64, 104},
{TypeName{}, 56, 88},
{Var{}, 60, 96},
- {Func{}, 64, 104},
+ {Func{}, 60, 96},
{Label{}, 60, 96},
{Builtin{}, 60, 96},
{Nil{}, 56, 88},
diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go
index ab64882..4c8eac7 100644
--- a/src/cmd/compile/internal/types2/stmt.go
+++ b/src/cmd/compile/internal/types2/stmt.go
@@ -239,7 +239,7 @@
}
// Order matters: By comparing v against x, error positions are at the case values.
res := v // keep original v unchanged
- check.comparison(&res, x, syntax.Eql)
+ check.comparison(&res, x, syntax.Eql, true)
if res.mode == invalid {
continue L
}
@@ -274,7 +274,8 @@
return false
}
-func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) {
+// If the type switch expression is invalid, x is nil.
+func (check *Checker) caseTypes(x *operand, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) {
var dummy operand
L:
for _, e := range types {
@@ -305,8 +306,8 @@
}
}
seen[T] = e
- if T != nil {
- check.typeAssertion(e, x, xtyp, T, true)
+ if x != nil && T != nil {
+ check.typeAssertion(e, x, T, true)
}
}
return
@@ -408,9 +409,9 @@
if ch.mode == invalid || val.mode == invalid {
return
}
- u := structuralType(ch.typ)
+ u := coreType(ch.typ)
if u == nil {
- check.errorf(s, invalidOp+"cannot send to %s: no structural type", &ch)
+ check.errorf(s, invalidOp+"cannot send to %s: no core type", &ch)
return
}
uch, _ := u.(*Chan)
@@ -474,30 +475,28 @@
case *syntax.ReturnStmt:
res := check.sig.results
+ // Return with implicit results allowed for function with named results.
+ // (If one is named, all are named.)
results := unpackExpr(s.Results)
- if res.Len() > 0 {
- // function returns results
- // (if one, say the first, result parameter is named, all of them are named)
- if len(results) == 0 && res.vars[0].name != "" {
- // spec: "Implementation restriction: A compiler may disallow an empty expression
- // list in a "return" statement if a different entity (constant, type, or variable)
- // with the same name as a result parameter is in scope at the place of the return."
- for _, obj := range res.vars {
- if alt := check.lookup(obj.name); alt != nil && alt != obj {
- var err error_
- err.errorf(s, "result parameter %s not in scope at return", obj.name)
- err.errorf(alt, "inner declaration of %s", obj)
- check.report(&err)
- // ok to continue
- }
+ if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
+ // spec: "Implementation restriction: A compiler may disallow an empty expression
+ // list in a "return" statement if a different entity (constant, type, or variable)
+ // with the same name as a result parameter is in scope at the place of the return."
+ for _, obj := range res.vars {
+ if alt := check.lookup(obj.name); alt != nil && alt != obj {
+ var err error_
+ err.errorf(s, "result parameter %s not in scope at return", obj.name)
+ err.errorf(alt, "inner declaration of %s", obj)
+ check.report(&err)
+ // ok to continue
}
- } else {
- // return has results or result parameters are unnamed
- check.initVars(res.vars, results, s)
}
- } else if len(results) > 0 {
- check.error(results[0], "no result values expected")
- check.use(results...)
+ } else {
+ var lhs []*Var
+ if res.Len() > 0 {
+ lhs = res.vars
+ }
+ check.initVars(lhs, results, s)
}
case *syntax.BranchStmt:
@@ -627,14 +626,15 @@
case *syntax.ForStmt:
inner |= breakOk | continueOk
- check.openScope(s, "for")
- defer check.closeScope()
if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
check.rangeStmt(inner, s, rclause)
break
}
+ check.openScope(s, "for")
+ defer check.closeScope()
+
check.simpleStmt(s.Init)
if s.Cond != nil {
var x operand
@@ -733,15 +733,17 @@
if x.mode == invalid {
return
}
+
// TODO(gri) we may want to permit type switches on type parameter values at some point
+ var sx *operand // switch expression against which cases are compared against; nil if invalid
if isTypeParam(x.typ) {
check.errorf(&x, "cannot use type switch on type parameter value %s", &x)
- return
- }
- xtyp, _ := under(x.typ).(*Interface)
- if xtyp == nil {
- check.errorf(&x, "%s is not an interface", &x)
- return
+ } else {
+ if _, ok := under(x.typ).(*Interface); ok {
+ sx = &x
+ } else {
+ check.errorf(&x, "%s is not an interface", &x)
+ }
}
check.multipleSwitchDefaults(s.Body)
@@ -759,7 +761,7 @@
}
// Check each type in this type switch case.
cases := unpackExpr(clause.Cases)
- T := check.caseTypes(&x, xtyp, cases, seen)
+ T := check.caseTypes(sx, cases, seen)
check.openScopeUntil(clause, end, "case")
// If lhs exists, declare a corresponding variable in the case-local scope.
if lhs != nil {
@@ -808,34 +810,34 @@
}
func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *syntax.RangeClause) {
- // scope already opened
+ // determine lhs, if any
+ sKey := rclause.Lhs // possibly nil
+ var sValue, sExtra syntax.Expr
+ if p, _ := sKey.(*syntax.ListExpr); p != nil {
+ if len(p.ElemList) < 2 {
+ check.error(s, invalidAST+"invalid lhs in range clause")
+ return
+ }
+ // len(p.ElemList) >= 2
+ sKey = p.ElemList[0]
+ sValue = p.ElemList[1]
+ if len(p.ElemList) > 2 {
+ // delay error reporting until we know more
+ sExtra = p.ElemList[2]
+ }
+ }
// check expression to iterate over
var x operand
check.expr(&x, rclause.X)
- // determine lhs, if any
- sKey := rclause.Lhs // possibly nil
- var sValue syntax.Expr
- if p, _ := sKey.(*syntax.ListExpr); p != nil {
- if len(p.ElemList) != 2 {
- check.error(s, invalidAST+"invalid lhs in range clause")
- return
- }
- sKey = p.ElemList[0]
- sValue = p.ElemList[1]
- }
-
// determine key/value types
var key, val Type
if x.mode != invalid {
- // Ranging over a type parameter is permitted if it has a structural type.
+ // Ranging over a type parameter is permitted if it has a core type.
var cause string
- u := structuralType(x.typ)
- switch t := u.(type) {
- case nil:
- cause = check.sprintf("%s has no structural type", x.typ)
- case *Chan:
+ u := coreType(x.typ)
+ if t, _ := u.(*Chan); t != nil {
if sValue != nil {
check.softErrorf(sValue, "range over %s permits only one iteration variable", &x)
// ok to continue
@@ -843,6 +845,14 @@
if t.dir == SendOnly {
cause = "receive from send-only channel"
}
+ } else {
+ if sExtra != nil {
+ check.softErrorf(sExtra, "range clause permits at most two iteration variables")
+ // ok to continue
+ }
+ if u == nil {
+ cause = check.sprintf("%s has no core type", x.typ)
+ }
}
key, val = rangeKeyVal(u)
if key == nil || cause != "" {
@@ -855,6 +865,11 @@
}
}
+ // Open the for-statement block scope now, after the range clause.
+ // Iteration variables declared with := need to go in this scope (was issue #51437).
+ check.openScope(s, "range")
+ defer check.closeScope()
+
// check assignment to/declaration of iteration variables
// (irregular assignment, cannot easily map to existing assignment checks)
@@ -863,9 +878,7 @@
rhs := [2]Type{key, val} // key, val may be nil
if rclause.Def {
- // short variable declaration; variable scope starts after the range clause
- // (the for loop opens a new scope, so variables on the lhs never redeclare
- // previously declared variables)
+ // short variable declaration
var vars []*Var
for i, lhs := range lhs {
if lhs == nil {
@@ -902,12 +915,8 @@
// declare variables
if len(vars) > 0 {
- scopePos := syntax.EndPos(rclause.X) // TODO(gri) should this just be s.Body.Pos (spec clarification)?
+ scopePos := s.Body.Pos()
for _, obj := range vars {
- // spec: "The scope of a constant or variable identifier declared inside
- // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
- // for short variable declarations) and ends at the end of the innermost
- // containing block."
check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
}
} else {
diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go
index 516f248..037f047 100644
--- a/src/cmd/compile/internal/types2/subst.go
+++ b/src/cmd/compile/internal/types2/subst.go
@@ -21,6 +21,17 @@
return proj
}
+// makeRenameMap is like makeSubstMap, but creates a map used to rename type
+// parameters in from with the type parameters in to.
+func makeRenameMap(from, to []*TypeParam) substMap {
+ assert(len(from) == len(to))
+ proj := make(substMap, len(from))
+ for i, tpar := range from {
+ proj[tpar] = to[i]
+ }
+ return proj
+}
+
func (m substMap) empty() bool {
return len(m) == 0
}
@@ -106,12 +117,24 @@
return subst.tuple(t)
case *Signature:
- // TODO(gri) rethink the recv situation with respect to methods on parameterized types
- // recv := subst.var_(t.recv) // TODO(gri) this causes a stack overflow - explain
+ // Preserve the receiver: it is handled during *Interface and *Named type
+ // substitution.
+ //
+ // Naively doing the substitution here can lead to an infinite recursion in
+ // the case where the receiver is an interface. For example, consider the
+ // following declaration:
+ //
+ // type T[A any] struct { f interface{ m() } }
+ //
+ // In this case, the type of f is an interface that is itself the receiver
+ // type of all of its methods. Because we have no type name to break
+ // cycles, substituting in the recv results in an infinite loop of
+ // recv->interface->recv->interface->...
recv := t.recv
+
params := subst.tuple(t.params)
results := subst.tuple(t.results)
- if recv != t.recv || params != t.params || results != t.results {
+ if params != t.params || results != t.results {
return &Signature{
rparams: t.rparams,
// TODO(gri) why can't we nil out tparams here, rather than in instantiate?
@@ -130,14 +153,31 @@
// term list substitution may introduce duplicate terms (unlikely but possible).
// This is ok; lazy type set computation will determine the actual type set
// in normal form.
- return &Union{terms, nil}
+ return &Union{terms}
}
case *Interface:
methods, mcopied := subst.funcList(t.methods)
embeddeds, ecopied := subst.typeList(t.embeddeds)
if mcopied || ecopied {
- iface := &Interface{methods: methods, embeddeds: embeddeds, implicit: t.implicit, complete: t.complete}
+ iface := subst.check.newInterface()
+ iface.embeddeds = embeddeds
+ iface.implicit = t.implicit
+ iface.complete = t.complete
+ // If we've changed the interface type, we may need to replace its
+ // receiver if the receiver type is the original interface. Receivers of
+ // *Named type are replaced during named type expansion.
+ //
+ // Notably, it's possible to reach here and not create a new *Interface,
+ // even though the receiver type may be parameterized. For example:
+ //
+ // type T[P any] interface{ m() }
+ //
+ // In this case the interface will not be substituted here, because its
+ // method signatures do not depend on the type parameter P, but we still
+ // need to create new interface methods to hold the instantiated
+ // receiver. This is handled by expandNamed.
+ iface.methods, _ = replaceRecvType(methods, t, iface)
return iface
}
@@ -349,3 +389,31 @@
}
return
}
+
+// replaceRecvType updates any function receivers that have type old to have
+// type new. It does not modify the input slice; if modifications are required,
+// the input slice and any affected signatures will be copied before mutating.
+//
+// The resulting out slice contains the updated functions, and copied reports
+// if anything was modified.
+func replaceRecvType(in []*Func, old, new Type) (out []*Func, copied bool) {
+ out = in
+ for i, method := range in {
+ sig := method.Type().(*Signature)
+ if sig.recv != nil && sig.recv.Type() == old {
+ if !copied {
+ // Allocate a new methods slice before mutating for the first time.
+ // This is defensive, as we may share methods across instantiations of
+ // a given interface type if they do not get substituted.
+ out = make([]*Func, len(in))
+ copy(out, in)
+ copied = true
+ }
+ newsig := *sig
+ sig = &newsig
+ sig.recv = NewVar(sig.recv.pos, sig.recv.pkg, "", new)
+ out[i] = NewFunc(method.pos, method.pkg, method.name, sig)
+ }
+ }
+ return
+}
diff --git a/src/cmd/compile/internal/types2/termlist.go b/src/cmd/compile/internal/types2/termlist.go
index 844e39e..a0108c4 100644
--- a/src/cmd/compile/internal/types2/termlist.go
+++ b/src/cmd/compile/internal/types2/termlist.go
@@ -92,15 +92,6 @@
return rl
}
-// If the type set represented by xl is specified by a single (non-𝓤) term,
-// singleType returns that type. Otherwise it returns nil.
-func (xl termlist) singleType() Type {
- if nl := xl.norm(); len(nl) == 1 {
- return nl[0].typ // if nl.isAll() then typ is nil, which is ok
- }
- return nil
-}
-
// union returns the union xl ∪ yl.
func (xl termlist) union(yl termlist) termlist {
return append(xl, yl...).norm()
diff --git a/src/cmd/compile/internal/types2/termlist_test.go b/src/cmd/compile/internal/types2/termlist_test.go
index 1bdf9e1..d1e3bdf 100644
--- a/src/cmd/compile/internal/types2/termlist_test.go
+++ b/src/cmd/compile/internal/types2/termlist_test.go
@@ -106,35 +106,6 @@
}
}
-func TestTermlistSingleType(t *testing.T) {
- // helper to deal with nil types
- tstring := func(typ Type) string {
- if typ == nil {
- return "nil"
- }
- return typ.String()
- }
-
- for test, want := range map[string]string{
- "∅": "nil",
- "𝓤": "nil",
- "int": "int",
- "myInt": "myInt",
- "~int": "int",
- "~int ∪ string": "nil",
- "~int ∪ myInt": "int",
- "∅ ∪ int": "int",
- "∅ ∪ ~int": "int",
- "∅ ∪ ~int ∪ string": "nil",
- } {
- xl := maketl(test)
- got := tstring(xl.singleType())
- if got != want {
- t.Errorf("(%v).singleType() == %v; want %v", test, got, want)
- }
- }
-}
-
func TestTermlistUnion(t *testing.T) {
for _, test := range []struct {
xl, yl, want string
diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2
index 48a3989..7c3f0c9 100644
--- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2
@@ -148,7 +148,7 @@
_ = make /* ERROR expects 2 or 3 arguments */ (S1)
_ = make(S1, 10, 20)
_ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30)
- _ = make(S2 /* ERROR cannot make S2: no structural type */ , 10)
+ _ = make(S2 /* ERROR cannot make S2: no core type */ , 10)
type M0 map[string]int
_ = make(map[string]int)
@@ -156,7 +156,7 @@
_ = make(M1)
_ = make(M1, 10)
_ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20)
- _ = make(M2 /* ERROR cannot make M2: no structural type */ )
+ _ = make(M2 /* ERROR cannot make M2: no core type */ )
type C0 chan int
_ = make(chan int)
@@ -164,7 +164,7 @@
_ = make(C1)
_ = make(C1, 10)
_ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20)
- _ = make(C2 /* ERROR cannot make C2: no structural type */ )
+ _ = make(C2 /* ERROR cannot make C2: no core type */ )
_ = make(C3)
}
diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.src b/src/cmd/compile/internal/types2/testdata/check/builtins.src
index de27f5c..358e9c5 100644
--- a/src/cmd/compile/internal/types2/testdata/check/builtins.src
+++ b/src/cmd/compile/internal/types2/testdata/check/builtins.src
@@ -15,9 +15,9 @@
var x int
var s []byte
_ = append() // ERROR not enough arguments
- _ = append("foo" /* ERROR not a slice */ )
- _ = append(nil /* ERROR not a slice */ , s)
- _ = append(x /* ERROR not a slice */ , s)
+ _ = append("foo" /* ERROR must be a slice */ )
+ _ = append(nil /* ERROR must be a slice */ , s)
+ _ = append(x /* ERROR must be a slice */ , s)
_ = append(s)
_ = append(s, nil...)
append /* ERROR not used */ (s)
@@ -77,7 +77,7 @@
_ = append(f2())
_ = append(f3())
_ = append(f5())
- _ = append(ff /* ERROR not a slice */ ()) // TODO(gri) better error message
+ _ = append(ff /* ERROR must be a slice */ ()) // TODO(gri) better error message
}
func cap1() {
diff --git a/src/cmd/compile/internal/types2/testdata/check/cycles5.src b/src/cmd/compile/internal/types2/testdata/check/cycles5.src
index 397adcc..c932ef9 100644
--- a/src/cmd/compile/internal/types2/testdata/check/cycles5.src
+++ b/src/cmd/compile/internal/types2/testdata/check/cycles5.src
@@ -135,7 +135,7 @@
type (
a struct{ *b }
b = c
- c struct{ *b }
+ c struct{ *b /* ERROR invalid use of type alias */ }
)
// issue #24939
@@ -145,7 +145,7 @@
}
M interface {
- F() P
+ F() P // ERROR invalid use of type alias
}
P = interface {
diff --git a/src/cmd/compile/internal/types2/testdata/check/expr2.src b/src/cmd/compile/internal/types2/testdata/check/expr2.src
index 8e58623..88781f1 100644
--- a/src/cmd/compile/internal/types2/testdata/check/expr2.src
+++ b/src/cmd/compile/internal/types2/testdata/check/expr2.src
@@ -9,8 +9,8 @@
func _bool() {
const t = true == true
const f = true == false
- _ = t /* ERROR "cannot compare" */ < f
- _ = 0 /* ERROR "mismatched types untyped int and untyped bool" */ == t
+ _ = t /* ERROR cannot compare */ < f
+ _ = 0 /* ERROR mismatched types untyped int and untyped bool */ == t
var b bool
var x, y float32
b = x < y
@@ -20,7 +20,7 @@
// corner cases
var (
- v0 = nil /* ERROR "cannot compare" */ == nil
+ v0 = nil == nil // ERROR operator == not defined on untyped nil
)
func arrays() {
@@ -40,7 +40,7 @@
_ = c /* ERROR mismatched types */ == d
var e [10]func() int
- _ = e /* ERROR == not defined */ == e
+ _ = e /* ERROR \[10\]func\(\) int cannot be compared */ == e
}
func structs() {
@@ -79,8 +79,8 @@
func pointers() {
// nil
- _ = nil /* ERROR == not defined */ == nil
- _ = nil /* ERROR != not defined */ != nil
+ _ = nil == nil // ERROR operator == not defined on untyped nil
+ _ = nil != nil // ERROR operator != not defined on untyped nil
_ = nil /* ERROR < not defined */ < nil
_ = nil /* ERROR <= not defined */ <= nil
_ = nil /* ERROR > not defined */ > nil
@@ -211,16 +211,16 @@
// issue #28164
// testcase from issue
- _ = interface /* ERROR cannot compare */ {}(nil) == []int(nil)
+ _ = interface{}(nil) == [ /* ERROR slice can only be compared to nil */ ]int(nil)
// related cases
var e interface{}
var s []int
var x int
- _ = e /* ERROR cannot compare */ == s
- _ = s /* ERROR cannot compare */ == e
- _ = e /* ERROR cannot compare */ < x
- _ = x /* ERROR cannot compare */ < e
+ _ = e == s // ERROR slice can only be compared to nil
+ _ = s /* ERROR slice can only be compared to nil */ == e
+ _ = e /* ERROR operator < not defined on interface */ < x
+ _ = x < e // ERROR operator < not defined on interface
}
func slices() {
@@ -231,7 +231,7 @@
_ = s /* ERROR < not defined */ < nil
// slices are not otherwise comparable
- _ = s /* ERROR == not defined */ == s
+ _ = s /* ERROR slice can only be compared to nil */ == s
_ = s /* ERROR < not defined */ < s
}
@@ -243,7 +243,7 @@
_ = m /* ERROR < not defined */ < nil
// maps are not otherwise comparable
- _ = m /* ERROR == not defined */ == m
+ _ = m /* ERROR map can only be compared to nil */ == m
_ = m /* ERROR < not defined */ < m
}
@@ -255,6 +255,6 @@
_ = f /* ERROR < not defined */ < nil
// funcs are not otherwise comparable
- _ = f /* ERROR == not defined */ == f
+ _ = f /* ERROR func can only be compared to nil */ == f
_ = f /* ERROR < not defined */ < f
}
diff --git a/src/cmd/compile/internal/types2/testdata/check/funcinference.go2 b/src/cmd/compile/internal/types2/testdata/check/funcinference.go2
index 7160e18..45d0781 100644
--- a/src/cmd/compile/internal/types2/testdata/check/funcinference.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/funcinference.go2
@@ -8,21 +8,21 @@
type any interface{}
-func f0[A any, B interface{~*C}, C interface{~*D}, D interface{~*A}](A, B, C, D) {}
+func f0[A any, B interface{*C}, C interface{*D}, D interface{*A}](A, B, C, D) {}
func _() {
f := f0[string]
f("a", nil, nil, nil)
f0("a", nil, nil, nil)
}
-func f1[A any, B interface{~*A}](A, B) {}
+func f1[A any, B interface{*A}](A, B) {}
func _() {
f := f1[int]
f(int(0), new(int))
f1(int(0), new(int))
}
-func f2[A any, B interface{~[]A}](A, B) {}
+func f2[A any, B interface{[]A}](A, B) {}
func _() {
f := f2[byte]
f(byte(0), []byte{})
@@ -38,7 +38,7 @@
// f3(x, &x, &x)
// }
-func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) {}
+func f4[A any, B interface{[]C}, C interface{*A}](A, B, C) {}
func _() {
f := f4[int]
var x int
@@ -46,7 +46,7 @@
f4(x, []*int{}, &x)
}
-func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A { panic(0) }
+func f5[A interface{struct{b B; c C}}, B any, C interface{*B}](x B) A { panic(0) }
func _() {
x := f5(1.2)
var _ float64 = x.b
@@ -79,14 +79,14 @@
type Setter[B any] interface {
Set(string)
- ~*B
+ *B
}
func FromStrings[T interface{}, PT Setter[T]](s []string) []T {
result := make([]T, len(s))
for i, v := range s {
// The type of &result[i] is *T which is in the type list
- // of Setter2, so we can convert it to PT.
+ // of Setter, so we can convert it to PT.
p := PT(&result[i])
// PT has a Set method.
p.Set(v)
diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2
index 76f9cc5..1763550 100644
--- a/src/cmd/compile/internal/types2/testdata/check/issues.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2
@@ -9,19 +9,18 @@
import "io"
import "context"
-// Interfaces are always comparable (though the comparison may panic at runtime).
func eql[T comparable](x, y T) bool {
return x == y
}
-func _() {
- var x interface{}
- var y interface{ m() }
+func _[X comparable, Y interface{comparable; m()}]() {
+ var x X
+ var y Y
eql(x, y /* ERROR does not match */ ) // interfaces of different types
eql(x, x)
eql(y, y)
- eql(y, nil)
- eql[io.Reader](nil, nil)
+ eql(y, nil /* ERROR cannot use nil as Y value in argument to eql */ )
+ eql[io /* ERROR does not implement comparable */ .Reader](nil, nil)
}
// If we have a receiver of pointer to type parameter type (below: *T)
@@ -47,7 +46,7 @@
func (*T) m2()
func _() {
- f2[T /* ERROR wrong method signature */ ]()
+ f2[T /* ERROR m2 has pointer receiver */ ]()
f2[*T]()
}
@@ -58,7 +57,7 @@
type T1[P interface{~uint}] struct{}
func _[P any]() {
- _ = T1[P /* ERROR empty interface P does not implement interface{~uint} */ ]{}
+ _ = T1[P /* ERROR P does not implement interface{~uint} */ ]{}
}
// This is the original (simplified) program causing the same issue.
@@ -74,8 +73,8 @@
return u.s + 1
}
-func NewT2[U any]() T2[U /* ERROR empty interface U does not implement Unsigned */ ] {
- return T2[U /* ERROR empty interface U does not implement Unsigned */ ]{}
+func NewT2[U any]() T2[U /* ERROR U does not implement Unsigned */ ] {
+ return T2[U /* ERROR U does not implement Unsigned */ ]{}
}
func _() {
@@ -145,8 +144,8 @@
}
// Infinite generic type declarations must lead to an error.
-type inf1 /* ERROR illegal cycle */ [T any] struct{ _ inf1[T] }
-type inf2 /* ERROR illegal cycle */ [T any] struct{ inf2[T] }
+type inf1[T any] struct{ _ inf1 /* ERROR illegal cycle */ [T] }
+type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] }
// The implementation of conversions T(x) between integers and floating-point
// numbers checks that both T and x have either integer or floating-point
diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src
index f4b6199..42c5bc8 100644
--- a/src/cmd/compile/internal/types2/testdata/check/issues.src
+++ b/src/cmd/compile/internal/types2/testdata/check/issues.src
@@ -131,42 +131,42 @@
)
var x I1
- x = T1 /* ERROR cannot use .*: missing method foo \(foo has pointer receiver\) */ {}
- _ = x. /* ERROR impossible type assertion: x.\(T1\)\n\tT1 does not implement I1 \(method foo has pointer receiver\) */ (T1)
+ x = T1 /* ERROR cannot use T1{} .* as I1 value in assignment: T1 does not implement I1 \(method foo has pointer receiver\) */ {}
+ _ = x /* ERROR impossible type assertion: x\.\(T1\)\n\tT1 does not implement I1 \(method foo has pointer receiver\) */ .(T1)
T1{}.foo /* ERROR cannot call pointer method foo on T1 */ ()
x.Foo /* ERROR "x.Foo undefined \(type I1 has no field or method Foo, but does have foo\)" */ ()
- _ = i2. /* ERROR impossible type assertion: i2.\(\*T1\)\n\t\*T1 does not implement I2 \(wrong type for method foo: have func\(\), want func\(x int\)\) */ (*T1)
+ _ = i2 /* ERROR impossible type assertion: i2\.\(\*T1\)\n\t\*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ .(*T1)
- i1 = i0 /* ERROR cannot use .* missing method foo */
- i1 = t0 /* ERROR cannot use .* missing method foo */
- i1 = i2 /* ERROR cannot use .* wrong type for method foo */
- i1 = t2 /* ERROR cannot use .* wrong type for method foo */
- i2 = i1 /* ERROR cannot use .* wrong type for method foo */
- i2 = t1 /* ERROR cannot use .* wrong type for method foo */
+ i1 = i0 /* ERROR cannot use i0 .* as I1 value in assignment: I0 does not implement I1 \(missing method foo\) */
+ i1 = t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing method foo\) */
+ i1 = i2 /* ERROR .* i2 .* as I1 .*: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */
+ i1 = t2 /* ERROR .* t2 .* as I1 .*: \*T2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */
+ i2 = i1 /* ERROR .* i1 .* as I2 .*: I1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */
+ i2 = t1 /* ERROR .* t1 .* as I2 .*: \*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */
- _ = func() I1 { return i0 /* ERROR cannot use .* missing method foo */ }
- _ = func() I1 { return t0 /* ERROR cannot use .* missing method foo */ }
- _ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I2 { return t1 /* ERROR cannot use .* wrong type for method foo */ }
+ _ = func() I1 { return i0 /* ERROR cannot use i0 .* as I1 value in return statement: I0 does not implement I1 \(missing method foo\) */ }
+ _ = func() I1 { return t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing method foo\) */ }
+ _ = func() I1 { return i2 /* ERROR .* i2 .* as I1 .*: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
+ _ = func() I1 { return t2 /* ERROR .* t2 .* as I1 .*: \*T2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
+ _ = func() I2 { return i1 /* ERROR .* i1 .* as I2 .*: I1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ }
+ _ = func() I2 { return t1 /* ERROR .* t1 .* as I2 .*: \*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ }
// a few more - less exhaustive now
f := func(I1, I2){}
- f(i0 /* ERROR cannot use .* missing method foo */ , i1 /* ERROR cannot use .* wrong type for method foo \(have func\(\), want func\(x int\)\) */ )
+ f(i0 /* ERROR missing method foo */ , i1 /* ERROR wrong type for method foo */ )
- _ = [...]I1{i0 /* ERROR cannot use .* missing method foo */ }
- _ = [...]I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = []I1{i0 /* ERROR cannot use .* missing method foo */ }
- _ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
- _ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ }
+ _ = [...]I1{i0 /* ERROR cannot use i0 .* as I1 value in array or slice literal: I0 does not implement I1 \(missing method foo\) */ }
+ _ = [...]I1{i2 /* ERROR cannot use i2 .* as I1 value in array or slice literal: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
+ _ = []I1{i0 /* ERROR missing method foo */ }
+ _ = []I1{i2 /* ERROR wrong type for method foo */ }
+ _ = map[int]I1{0: i0 /* ERROR missing method foo */ }
+ _ = map[int]I1{0: i2 /* ERROR wrong type for method foo */ }
- make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */
- make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */
+ make(chan I1) <- i0 /* ERROR missing method foo */
+ make(chan I1) <- i2 /* ERROR wrong type for method foo */
}
// Check that constants representable as integers are in integer form
diff --git a/src/cmd/compile/internal/types2/testdata/check/methodsets.src b/src/cmd/compile/internal/types2/testdata/check/methodsets.src
index 9fb10de..b0eb14c 100644
--- a/src/cmd/compile/internal/types2/testdata/check/methodsets.src
+++ b/src/cmd/compile/internal/types2/testdata/check/methodsets.src
@@ -196,9 +196,9 @@
_ func(error) string = error.Error
perr = &err
- _ = perr.Error /* ERROR "no field or method" */ ()
- _ func() string = perr.Error /* ERROR "no field or method" */
- _ func(*error) string = (*error).Error /* ERROR "no field or method" */
+ _ = perr.Error /* ERROR "type \*error is pointer to interface, not interface" */ ()
+ _ func() string = perr.Error /* ERROR "type \*error is pointer to interface, not interface" */
+ _ func(*error) string = (*error).Error /* ERROR "type \*error is pointer to interface, not interface" */
)
type T *interface{ m() int }
@@ -207,8 +207,8 @@
_ = (*x).m()
_ = (*x).m
- _ = x.m /* ERROR "no field or method" */ ()
- _ = x.m /* ERROR "no field or method" */
- _ = T.m /* ERROR "no field or method" */
+ _ = x.m /* ERROR "type T is pointer to interface, not interface" */ ()
+ _ = x.m /* ERROR "type T is pointer to interface, not interface" */
+ _ = T.m /* ERROR "type T is pointer to interface, not interface" */
)
}
diff --git a/src/cmd/compile/internal/types2/testdata/check/shifts.src b/src/cmd/compile/internal/types2/testdata/check/shifts.src
index 60db731..37bc84c 100644
--- a/src/cmd/compile/internal/types2/testdata/check/shifts.src
+++ b/src/cmd/compile/internal/types2/testdata/check/shifts.src
@@ -381,7 +381,7 @@
var a = make([]int, 1<<s + 1.2 /* ERROR "truncated to int" */ )
var _ = a[1<<s - 2.3 /* ERROR "truncated to int" */ ]
var _ int = 1<<s + 3.4 /* ERROR "truncated to int" */
- var _ = string(1 << s)
+ var _ = string(1 /* ERROR shifted operand 1 .* must be integer */ << s)
var _ = string(1.0 /* ERROR "cannot convert" */ << s)
}
diff --git a/src/cmd/compile/internal/types2/testdata/check/stmt0.src b/src/cmd/compile/internal/types2/testdata/check/stmt0.src
index 8b18d67..90ef095 100644
--- a/src/cmd/compile/internal/types2/testdata/check/stmt0.src
+++ b/src/cmd/compile/internal/types2/testdata/check/stmt0.src
@@ -375,7 +375,7 @@
func returns0() {
return
- return 0 /* ERROR no result values expected */
+ return 0 /* ERROR too many return values */
}
func returns1(x float64) (int, *float64) {
@@ -429,7 +429,7 @@
switch int32(x) {
case 1, 2:
- case x /* ERROR "cannot compare" */ :
+ case x /* ERROR "invalid case x in switch on int32\(x\) \(mismatched types int and int32\)" */ :
}
switch x {
@@ -695,7 +695,7 @@
_ = y
}
- switch x := i /* ERROR "not an interface" */ .(type) {}
+ switch /* ERROR "x declared but not used" */ x := i /* ERROR "not an interface" */ .(type) {}
switch t := x.(type) {
case nil:
@@ -719,6 +719,18 @@
case T2 /* ERROR "wrong type for method m" */ :
case I2 /* STRICT "wrong type for method m" */ : // only an error in strict mode (issue 8561)
}
+
+
+ {
+ x := 1
+ v := 2
+ switch v /* ERROR "v [(]variable of type int[)] is not an interface" */ .(type) {
+ case int:
+ println(x)
+ println(x / /* ERROR "invalid operation: division by zero" */ 0)
+ case /* ERROR "1 is not a type" */ 1:
+ }
+ }
}
// Test that each case clause uses the correct type of the variable
diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinference.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinference.go2
index 8876cca..28f3e28 100644
--- a/src/cmd/compile/internal/types2/testdata/check/typeinference.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/typeinference.go2
@@ -4,44 +4,46 @@
package typeInference
+// As of issue #51527, type-type inference has been disabled.
+
// basic inference
type Tb[P ~*Q, Q any] int
func _() {
- var x Tb[*int]
+ var x Tb /* ERROR got 1 arguments */ [*int]
var y Tb[*int, int]
- x = y
+ x = y /* ERROR cannot use y .* in assignment */
_ = x
}
// recursive inference
-type Tr[A any, B ~*C, C ~*D, D ~*A] int
+type Tr[A any, B *C, C *D, D *A] int
func _() {
- var x Tr[string]
+ var x Tr /* ERROR got 1 arguments */ [string]
var y Tr[string, ***string, **string, *string]
var z Tr[int, ***int, **int, *int]
- x = y
+ x = y /* ERROR cannot use y .* in assignment */
x = z // ERROR cannot use z .* as Tr
_ = x
}
// other patterns of inference
-type To0[A any, B ~[]A] int
-type To1[A any, B ~struct{a A}] int
-type To2[A any, B ~[][]A] int
-type To3[A any, B ~[3]*A] int
-type To4[A any, B any, C ~struct{a A; b B}] int
+type To0[A any, B []A] int
+type To1[A any, B struct{a A}] int
+type To2[A any, B [][]A] int
+type To3[A any, B [3]*A] int
+type To4[A any, B any, C struct{a A; b B}] int
func _() {
- var _ To0[int]
- var _ To1[int]
- var _ To2[int]
- var _ To3[int]
- var _ To4[int, string]
+ var _ To0 /* ERROR got 1 arguments */ [int]
+ var _ To1 /* ERROR got 1 arguments */ [int]
+ var _ To2 /* ERROR got 1 arguments */ [int]
+ var _ To3 /* ERROR got 1 arguments */ [int]
+ var _ To4 /* ERROR got 2 arguments */ [int, string]
}
// failed inference
type Tf0[A, B any] int
type Tf1[A any, B ~struct{a A; c C}, C any] int
func _() {
- var _ Tf0 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int]
- var _ Tf1 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 3 type parameters */ [int]
+ var _ Tf0 /* ERROR got 1 arguments but 2 type parameters */ [int]
+ var _ Tf1 /* ERROR got 1 arguments but 3 type parameters */ [int]
}
diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst.go2
index a3d1b5e..0e6dc0a 100644
--- a/src/cmd/compile/internal/types2/testdata/check/typeinst.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/typeinst.go2
@@ -58,5 +58,5 @@
// Self-recursive generic types are not permitted
-type self1 /* ERROR illegal cycle */ [P any] self1[P]
+type self1[P any] self1 /* ERROR illegal cycle */ [P]
type self2[P any] *self2[P] // this is ok
diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
index 007157e..68b1f0f 100644
--- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
@@ -134,11 +134,11 @@
type myByte1 []byte
type myByte2 []byte
func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] }
-func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j:k] }
+func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no core type */ i:j:k] }
func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] }
func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] }
-func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j] }
+func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x[ /* ERROR no core type */ i:j] }
// len/cap built-ins
@@ -230,7 +230,7 @@
for _, _ = range s1 {}
var s2 S2
- for range s2 /* ERROR cannot range over s2.*no structural type */ {}
+ for range s2 /* ERROR cannot range over s2.*no core type */ {}
var a0 []int
for range a0 {}
@@ -243,7 +243,7 @@
for _, _ = range a1 {}
var a2 A2
- for range a2 /* ERROR cannot range over a2.*no structural type */ {}
+ for range a2 /* ERROR cannot range over a2.*no core type */ {}
var p0 *[10]int
for range p0 {}
@@ -256,7 +256,7 @@
for _, _ = range p1 {}
var p2 P2
- for range p2 /* ERROR cannot range over p2.*no structural type */ {}
+ for range p2 /* ERROR cannot range over p2.*no core type */ {}
var m0 map[string]int
for range m0 {}
@@ -269,7 +269,7 @@
for _, _ = range m1 {}
var m2 M2
- for range m2 /* ERROR cannot range over m2.*no structural type */ {}
+ for range m2 /* ERROR cannot range over m2.*no core type */ {}
}
// type inference checks
@@ -519,13 +519,13 @@
type I interface {}
func _[P I] (x P) {
- x.m /* ERROR interface I has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
func _[P interface{}] (x P) {
- x.m /* ERROR type bound for P has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
func _[P any] (x P) {
- x.m /* ERROR type bound for P has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
diff --git a/src/cmd/compile/internal/types2/testdata/check/vardecl.src b/src/cmd/compile/internal/types2/testdata/check/vardecl.src
index 827b9b9..c3fe61c 100644
--- a/src/cmd/compile/internal/types2/testdata/check/vardecl.src
+++ b/src/cmd/compile/internal/types2/testdata/check/vardecl.src
@@ -177,8 +177,8 @@
func _() {
var x int
- return x /* ERROR no result values expected */
- return math /* ERROR no result values expected */ .Sin(0)
+ return x /* ERROR too many return values */
+ return math /* ERROR too many return values */ .Sin(0)
}
func _() int {
diff --git a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 b/src/cmd/compile/internal/types2/testdata/examples/inference.go2
index 0732f06..e3d6bfb 100644
--- a/src/cmd/compile/internal/types2/testdata/examples/inference.go2
+++ b/src/cmd/compile/internal/types2/testdata/examples/inference.go2
@@ -78,7 +78,7 @@
related1(si, "foo" /* ERROR cannot use "foo" */ )
}
-func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) {}
+func related2[Elem any, Slice interface{[]Elem}](e Elem, s Slice) {}
func _() {
// related2 can be called with explicit instantiation.
@@ -109,16 +109,8 @@
related3[int, []int]()
related3[byte, List[byte]]()
- // Alternatively, the 2nd type argument can be inferred
- // from the first one through constraint type inference.
- related3[int]()
-
- // The inferred type is the structural type of the Slice
- // type parameter.
- var _ []int = related3[int]()
-
- // It is not the defined parameterized type List.
- type anotherList []float32
- var _ anotherList = related3[float32]() // valid
- var _ anotherList = related3 /* ERROR cannot use .* \(value of type List\[float32\]\) as anotherList */ [float32, List[float32]]()
+ // The 2nd type argument cannot be inferred from the first
+ // one because there's two possible choices: []Elem and
+ // List[Elem].
+ related3[int]( /* ERROR cannot infer Slice */ )
}
diff --git a/src/cmd/compile/internal/types2/testdata/examples/methods.go2 b/src/cmd/compile/internal/types2/testdata/examples/methods.go2
index 1d76d55..a46f789 100644
--- a/src/cmd/compile/internal/types2/testdata/examples/methods.go2
+++ b/src/cmd/compile/internal/types2/testdata/examples/methods.go2
@@ -35,7 +35,7 @@
// style. In m3 below, int is the name of the local receiver type parameter
// and it shadows the predeclared identifier int which then cannot be used
// anymore as expected.
-// This is no different from locally redelaring a predeclared identifier
+// This is no different from locally re-declaring a predeclared identifier
// and usually should be avoided. There are some notable exceptions; e.g.,
// sometimes it makes sense to use the identifier "copy" which happens to
// also be the name of a predeclared built-in function.
diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2
index 077fcfd..ae9c015 100644
--- a/src/cmd/compile/internal/types2/testdata/examples/types.go2
+++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2
@@ -292,7 +292,7 @@
// It is possible to create composite literals of type parameter
// type as long as it's possible to create a composite literal
-// of the structural type of the type parameter's constraint.
+// of the core type of the type parameter's constraint.
func _[P interface{ ~[]int }]() P {
return P{}
return P{1, 2, 3}
@@ -307,7 +307,7 @@
}
// This is a degenerate case with a singleton type set, but we can create
-// composite literals even if the structural type is a defined type.
+// composite literals even if the core type is a defined type.
type MyInts []int
func _[P MyInts]() P {
diff --git a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2
index e19dcf8..55ef022 100644
--- a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2
+++ b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2
@@ -35,7 +35,7 @@
return deref(p)
}
-func addrOfCopy[V any, P ~*V](v V) P {
+func addrOfCopy[V any, P *V](v V) P {
return &v
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue25838.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue25838.go
new file mode 100644
index 0000000..adbd138
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue25838.go
@@ -0,0 +1,26 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// examples from the issue
+
+type (
+ e = f
+ f = g
+ g = []h
+ h i
+ i = j
+ j = e
+)
+
+type (
+ e1 = []h1
+ h1 e1
+)
+
+type (
+ P = *T
+ T P
+)
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2
index 9a98f7f..b408dd7 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2
@@ -37,7 +37,7 @@
// func main8() {}
// crash 9
-type foo9 /* ERROR illegal cycle */ [A any] interface { foo9[A] }
+type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] }
func _() { var _ = new(foo9[int]) }
// crash 12
@@ -85,7 +85,7 @@
var x T25 /* ERROR without instantiation */ .m1
// crash 26
-type T26 = interface{ F26[ /* ERROR cannot have type parameters */ Z any]() }
+type T26 = interface{ F26[ /* ERROR interface method must have no type parameters */ Z any]() }
func F26[Z any]() T26 { return F26 /* ERROR without instantiation */ [] /* ERROR operand */ }
// crash 27
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2
index 1146467..6bc9284 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2
@@ -2,22 +2,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Check "infinite expansion" cycle errors across instantiated types.
-// We can't detect these errors anymore at the moment. See #48962 for
-// details.
-
package p
+// All but E2 and E5 provide an "indirection" and break infinite expansion of a type.
type E0[P any] []P
type E1[P any] *P
type E2[P any] struct{ _ P }
type E3[P any] struct{ _ *P }
+type E5[P any] struct{ _ [10]P }
-type T0 /* illegal cycle */ struct {
+type T0 struct {
_ E0[T0]
}
-type T0_ /* illegal cycle */ struct {
+type T0_ struct {
E0[T0_]
}
@@ -25,7 +23,7 @@
_ E1[T1]
}
-type T2 /* illegal cycle */ struct {
+type T2 /* ERROR illegal cycle */ struct {
_ E2[T2]
}
@@ -33,20 +31,24 @@
_ E3[T3]
}
-// some more complex cases
-
-type T4 /* illegal cycle */ struct {
- _ E0[E2[T4]]
-}
+type T4 /* ERROR illegal cycle */ [10]E5[T4]
type T5 struct {
- _ E0[E2[E0[E1[E2[[10]T5]]]]]
+ _ E0[E2[T5]]
}
-type T6 /* illegal cycle */ struct {
- _ E0[[10]E2[E0[E2[E2[T6]]]]]
+type T6 struct {
+ _ E0[E2[E0[E1[E2[[10]T6]]]]]
}
type T7 struct {
- _ E0[[]E2[E0[E2[E2[T6]]]]]
+ _ E0[[10]E2[E0[E2[E2[T7]]]]]
}
+
+type T8 struct {
+ _ E0[[]E2[E0[E2[E2[T8]]]]]
+}
+
+type T9 /* ERROR illegal cycle */ [10]E2[E5[E2[T9]]]
+
+type T10 [10]E2[E5[E2[func(T10)]]]
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2
index 7f55ba8..4550dd7 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2
@@ -47,7 +47,7 @@
}
type _ struct{
- I3 // ERROR interface is .* comparable
+ I3 // ERROR interface contains type constraints
}
// General composite types.
@@ -59,19 +59,19 @@
_ []I1 // ERROR interface is .* comparable
_ []I2 // ERROR interface contains type constraints
- _ *I3 // ERROR interface is .* comparable
+ _ *I3 // ERROR interface contains type constraints
_ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints
- _ chan I3 // ERROR interface is .* comparable
+ _ chan I3 // ERROR interface contains type constraints
_ func(I1 /* ERROR interface is .* comparable */ )
_ func() I2 // ERROR interface contains type constraints
)
// Other cases.
-var _ = [...]I3 /* ERROR interface is .* comparable */ {}
+var _ = [...]I3 /* ERROR interface contains type constraints */ {}
func _(x interface{}) {
- _ = x.(I3 /* ERROR interface is .* comparable */ )
+ _ = x.(I3 /* ERROR interface contains type constraints */ )
}
type T1[_ any] struct{}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go2
new file mode 100644
index 0000000..35c7ef5
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go2
@@ -0,0 +1,31 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// simplified example
+func f[T ~func(T)](a, b T) {}
+
+type F func(F)
+
+func _() {
+ var i F
+ var j func(F)
+
+ f(i, j)
+ // f(j, i) // disabled for now
+}
+
+// example from issue
+func g[T interface{ Equal(T) bool }](a, b T) {}
+
+type I interface{ Equal(I) bool }
+
+func _() {
+ var i I
+ var j interface{ Equal(I) bool }
+
+ g(i, j)
+ // g(j, i) // disabled for now
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43110.src b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43110.src
index 4a46945..8d5c983 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43110.src
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43110.src
@@ -30,7 +30,7 @@
}
switch (func())(nil) {
- case f /* ERROR cannot compare */ :
+ case f /* ERROR invalid case f in switch on .* \(func can only be compared to nil\) */ :
}
switch nil /* ERROR use of untyped nil in switch expression */ {
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2
index e4bcee5..2955c26 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2
@@ -9,7 +9,7 @@
type (
_ [L]struct{}
_ [A /* ERROR undeclared name A for array length */ ]struct{}
- _ [B /* ERROR not an expression */ ]struct{}
+ _ [B /* ERROR invalid array length B */ ]struct{}
_[A any] struct{}
B int
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2
index 46ac51e..3c78f85 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2
@@ -12,7 +12,7 @@
type C5[T any] interface{ ~chan T | <-chan T }
func _[T any](ch T) {
- <-ch // ERROR cannot receive from ch .* no structural type
+ <-ch // ERROR cannot receive from ch .* no core type
}
func _[T C0](ch T) {
@@ -28,7 +28,7 @@
}
func _[T C3](ch T) {
- <-ch // ERROR cannot receive from ch .* no structural type
+ <-ch // ERROR cannot receive from ch .* no core type
}
func _[T C4](ch T) {
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45114.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45114.go
new file mode 100644
index 0000000..0093660
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45114.go
@@ -0,0 +1,8 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var s uint
+var _ = string(1 /* ERROR shifted operand 1 .* must be integer */ << s)
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2
index b8ba0ad..01c9672 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2
@@ -4,7 +4,7 @@
package p
-func f[F interface{~*Q}, G interface{~*R}, Q, R any](q Q, r R) {}
+func f[F interface{*Q}, G interface{*R}, Q, R any](q Q, r R) {}
func _() {
f[*float64, *int](1, 2)
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2
index 83a8f3a..5c1fa80 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2
@@ -12,7 +12,7 @@
type C5[T any] interface{ ~chan T | chan<- T }
func _[T any](ch T) {
- ch /* ERROR cannot send to ch .* no structural type */ <- 0
+ ch /* ERROR cannot send to ch .* no core type */ <- 0
}
func _[T C0](ch T) {
@@ -28,7 +28,7 @@
}
func _[T C3](ch T) {
- ch /* ERROR cannot send to ch .* no structural type */ <- 0
+ ch /* ERROR cannot send to ch .* no core type */ <- 0
}
func _[T C4](ch T) {
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2
index ce5db0a..3f405ba 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2
@@ -16,11 +16,11 @@
_ = f[P]
_ = f[Q]
_ = f[func( /* ERROR does not implement comparable */ )]
- _ = f[R /* ERROR empty interface R does not implement comparable */ ]
+ _ = f[R /* ERROR R does not implement comparable */ ]
_ = g[int]
_ = g[P /* ERROR P does not implement interface{interface{comparable; ~int\|~string} */ ]
_ = g[Q]
- _ = g[func( /* ERROR does not implement comparable */ )]
- _ = g[R /* ERROR empty interface R does not implement interface{interface{comparable; ~int\|~string} */ ]
+ _ = g[func( /* ERROR func\(\) does not implement interface{interface{comparable; ~int\|~string}} */ )]
+ _ = g[R /* ERROR R does not implement interface{interface{comparable; ~int\|~string} */ ]
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2
index 6a2e787..6f09fc2 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2
@@ -20,7 +20,7 @@
x.m()
// (&x).m doesn't exist because &x is of type *P
// and pointers to type parameters don't have methods
- (&x).m /* ERROR \*P has no field or method m */ ()
+ (&x).m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
}
@@ -29,7 +29,7 @@
func _(x *T2) {
// x.m doesn't exists because x is of type *T2
// and pointers to interfaces don't have methods
- x.m /* ERROR \*T2 has no field or method m */()
+ x.m /* ERROR type \*T2 is pointer to interface, not interface */()
}
// Test case 1 from issue
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
index 2631118..6069f1f 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
@@ -8,15 +8,13 @@
package go1_17
-import "constraints"
-
-type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
+type T[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
// for init (and main, but we're not in package main) we should only get one error
func init[P /* ERROR func init must have no type parameters */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
-func main[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
+func main[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
-func f[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) {
+func f[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) {
var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int]
var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int])
_ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{}
@@ -57,5 +55,3 @@
_ = C1
_ = C2
)
-
-type Ordered constraints /* ERROR using type constraint constraints\.Ordered requires go1\.18 or later */ .Ordered
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48312.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48312.go2
new file mode 100644
index 0000000..2fdb7ca
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48312.go2
@@ -0,0 +1,20 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T interface{ m() }
+type P *T
+
+func _(p *T) {
+ p.m /* ERROR type \*T is pointer to interface, not interface */ ()
+}
+
+func _(p P) {
+ p.m /* ERROR type P is pointer to interface, not interface */ ()
+}
+
+func _[P T](p *P) {
+ p.m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2
index 870bacd..72eea1e 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2
@@ -2,23 +2,21 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This issue has been re-opened.
-
package p
func f[P any](a, _ P) {
- // var x int
- // f(a, x /* ERROR type int of x does not match P */)
- // f(x, a /* ERROR type P of a does not match inferred type int for P */)
+ var x int
+ // TODO(gri) these error messages, while correct, could be better
+ f(a, x /* ERROR type int of x does not match inferred type P for P */)
+ f(x, a /* ERROR type P of a does not match inferred type int for P */)
}
func g[P any](a, b P) {
- // g(a, b)
- // g(&a, &b)
- // g([]P{}, []P{})
-}
+ g(a, b)
+ g(&a, &b)
+ g([]P{}, []P{})
-func h[P any](a, b P) {
- // h(&a, &b)
- // h([]P{a}, []P{b})
+ // work-around: provide type argument explicitly
+ g[*P](&a, &b)
+ g[[]P]([]P{}, []P{})
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2
index 652f8ce..0f60f47 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This issue is still open.
-
package p
-func f[P *Q, Q any](p P, q Q) {
- // _ = f[P]
- // _ = f[/* ERROR cannot infer P */ *P]
+func f[P *Q, Q any](P, Q) {
+ _ = f[P]
+}
+
+func f2[P /* ERROR instantiation cycle */ *Q, Q any](P, Q) {
+ _ = f2[*P]
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go2
new file mode 100644
index 0000000..ab39756
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go2
@@ -0,0 +1,41 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[P comparable](x, y P) {
+ _ = x == x
+ _ = x == y
+ _ = y == x
+ _ = y == y
+
+ _ = x /* ERROR type parameter P is not comparable with < */ < y
+}
+
+func _[P comparable](x P, y any) {
+ _ = x == x
+ _ = x == y
+ _ = y == x
+ _ = y == y
+
+ _ = x /* ERROR type parameter P is not comparable with < */ < y
+}
+
+func _[P any](x, y P) {
+ _ = x /* ERROR type parameter P is not comparable with == */ == x
+ _ = x /* ERROR type parameter P is not comparable with == */ == y
+ _ = y /* ERROR type parameter P is not comparable with == */ == x
+ _ = y /* ERROR type parameter P is not comparable with == */ == y
+
+ _ = x /* ERROR type parameter P is not comparable with < */ < y
+}
+
+func _[P any](x P, y any) {
+ _ = x /* ERROR type parameter P is not comparable with == */ == x
+ _ = x /* ERROR type parameter P is not comparable with == */ == y
+ _ = y == x // ERROR type parameter P is not comparable with ==
+ _ = y == y
+
+ _ = x /* ERROR type parameter P is not comparable with < */ < y
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2
index cf02cc1..a936528 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2
@@ -5,17 +5,17 @@
package p
type (
- A1 /* ERROR illegal cycle */ [P any] [10]A1[P]
- A2 /* ERROR illegal cycle */ [P any] [10]A2[*P]
+ A1[P any] [10]A1 /* ERROR illegal cycle */ [P]
+ A2[P any] [10]A2 /* ERROR illegal cycle */ [*P]
A3[P any] [10]*A3[P]
L1[P any] []L1[P]
- S1 /* ERROR illegal cycle */ [P any] struct{ f S1[P] }
- S2 /* ERROR illegal cycle */ [P any] struct{ f S2[*P] } // like example in issue
+ S1[P any] struct{ f S1 /* ERROR illegal cycle */ [P] }
+ S2[P any] struct{ f S2 /* ERROR illegal cycle */ [*P] } // like example in issue
S3[P any] struct{ f *S3[P] }
- I1 /* ERROR illegal cycle */ [P any] interface{ I1[P] }
- I2 /* ERROR illegal cycle */ [P any] interface{ I2[*P] }
+ I1[P any] interface{ I1 /* ERROR illegal cycle */ [P] }
+ I2[P any] interface{ I2 /* ERROR illegal cycle */ [*P] }
I3[P any] interface{ *I3 /* ERROR interface contains type constraints */ [P] }
)
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48962.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48962.go2
new file mode 100644
index 0000000..4270da1
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48962.go2
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T0[P any] struct {
+ f P
+}
+
+type T1 /* ERROR illegal cycle */ struct {
+ _ T0[T1]
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go
index f152e7f..7083dc9 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file is tested when running "go test -run Manual"
-// without source arguments. Use for one-off debugging.
-
package p
type T1 interface{ M() }
@@ -23,7 +20,7 @@
func F2() T2
-var _ = F2(). /* ERROR impossible type assertion: F2\(\).\(\*X2\)\n\t\*X2 does not implement T2 \(missing method M\) */ (*X2)
+var _ = F2 /* ERROR impossible type assertion: F2\(\)\.\(\*X2\)\n\t\*X2 does not implement T2 \(missing method M\) */ ().(*X2)
type X2 struct{}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49043.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49043.go2
index c37b0f1..a360457 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49043.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49043.go2
@@ -6,13 +6,13 @@
// The example from the issue.
type (
- N /* ERROR illegal cycle */ [P any] M[P]
- M[P any] N[P]
+ N[P any] M /* ERROR illegal cycle */ [P]
+ M[P any] N /* ERROR illegal cycle */ [P]
)
// A slightly more complicated case.
type (
- A /* ERROR illegal cycle */ [P any] B[P]
+ A[P any] B /* ERROR illegal cycle */ [P]
B[P any] C[P]
C[P any] A[P]
)
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49112.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49112.go2
new file mode 100644
index 0000000..0efc906
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49112.go2
@@ -0,0 +1,15 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f[P int](P) {}
+
+func _() {
+ _ = f[int]
+ _ = f[[ /* ERROR \[\]int does not implement int */ ]int]
+
+ f(0)
+ f( /* ERROR \[\]int does not implement int */ []int{})
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49482.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49482.go2
new file mode 100644
index 0000000..f289d2e
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49482.go2
@@ -0,0 +1,25 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+// The following is OK, per the special handling for type literals discussed in issue #49482.
+type _[P *struct{}] struct{}
+type _[P *int,] int
+type _[P (*int),] int
+
+const P = 2 // declare P to avoid noisy 'undeclared name' errors below.
+
+// The following parse as invalid array types.
+type _[P *int /* ERROR "int \(type\) is not an expression" */ ] int
+type _[P /* ERROR non-function P */ (*int)] int
+
+// The following should be parsed as a generic type, but is instead parsed as an array type.
+type _[P *struct /* ERROR "not an expression" */ {}| int /* ERROR "not an expression" */ ] struct{}
+
+// The following fails to parse, due to the '~'
+type _[P *struct /* ERROR "not an expression" */ {}|~ /* ERROR "unexpected ~" */ int] struct{}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49541.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49541.go2
new file mode 100644
index 0000000..c8499c1
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49541.go2
@@ -0,0 +1,45 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type S[A, B any] struct {
+ f int
+}
+
+func (S[A, B]) m() {}
+
+// TODO(gri): with type-type inference enabled we should only report one error
+// below. See issue #50588.
+
+func _[A any](s S /* ERROR got 1 arguments but 2 type parameters */ [A]) {
+ // we should see no follow-on errors below
+ s.f = 1
+ s.m()
+}
+
+// another test case from the issue
+
+func _() {
+ X(Interface[*F /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
+}
+
+func X[Q Qer](fs Interface[Q]) {
+}
+
+type Impl struct{}
+
+func (Impl) M() {}
+
+type Interface[Q Qer] interface {
+ M()
+}
+
+type Qer interface {
+ Q()
+}
+
+type F[A, B any] struct{}
+
+func (f *F[A, B]) Q() {}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2
index 9e20ae5..ee2d94a 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2
@@ -9,7 +9,7 @@
}
func G[F any]() I[any] {
- return g /* ERROR "missing method Q \(Q has pointer receiver\)" */ [F]{}
+ return g /* ERROR cannot use g\[F\]{} .* as I\[any\] value in return statement: g\[F\] does not implement I\[any\] \(method Q has pointer receiver\) */ [F]{}
}
type g[F any] struct{}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49602.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49602.go2
new file mode 100644
index 0000000..9edbf14
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49602.go2
@@ -0,0 +1,19 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type M interface {
+ m()
+}
+
+type C interface {
+ comparable
+}
+
+type _ interface{
+ int | M // ERROR cannot use p\.M in union \(p\.M contains methods\)
+ int | comparable // ERROR cannot use comparable in union
+ int | C // ERROR cannot use p\.C in union \(p\.C embeds comparable\)
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2
index 2b991b8..5b5fba2 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2
@@ -4,8 +4,11 @@
package p
-import "constraints"
+type Integer interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
+}
-func shl[I constraints.Integer](n int) I {
+func shl[I Integer](n int) I {
return 1 << n
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49735.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49735.go2
new file mode 100644
index 0000000..5087022
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49735.go2
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[P1 any, P2 ~byte](s1 P1, s2 P2) {
+ _ = append(nil /* ERROR first argument to append must be a slice; have untyped nil */ , 0)
+ _ = append(s1 /* ERROR s1 .* has no core type */ , 0)
+ _ = append(s2 /* ERROR s2 .* has core type byte */ , 0)
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50259.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50259.go2
new file mode 100644
index 0000000..6df8c64
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50259.go2
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var x T[B]
+
+type T[_ any] struct{}
+type A T[B]
+type B = T[A]
+
+// test case from issue
+
+var v Box[Step]
+type Box[T any] struct{}
+type Step = Box[StepBox]
+type StepBox Box[Step]
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50276.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50276.go2
new file mode 100644
index 0000000..97e477e
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50276.go2
@@ -0,0 +1,39 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// simplified test case
+
+type transform[T any] struct{}
+type pair[S any] struct {}
+
+var _ transform[step]
+
+type box transform[step]
+type step = pair[box]
+
+// test case from issue
+
+type Transform[T any] struct{ hold T }
+type Pair[S, T any] struct {
+ First S
+ Second T
+}
+
+var first Transform[Step]
+
+// This line doesn't use the Step alias, and it compiles fine if you uncomment it.
+var second Transform[Pair[Box, interface{}]]
+
+type Box *Transform[Step]
+
+// This line is the same as the `first` line, but it comes after the Box declaration and
+// does not break the compile.
+var third Transform[Step]
+
+type Step = Pair[Box, interface{}]
+
+// This line also does not break the compile
+var fourth Transform[Step]
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50281.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50281.go2
new file mode 100644
index 0000000..f333e81
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50281.go2
@@ -0,0 +1,26 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[S string | []byte](s S) {
+ var buf []byte
+ _ = append(buf, s...)
+}
+
+func _[S ~string | ~[]byte](s S) {
+ var buf []byte
+ _ = append(buf, s...)
+}
+
+// test case from issue
+
+type byteseq interface {
+ string | []byte
+}
+
+// This should allow to eliminate the two functions above.
+func AppendByteString[source byteseq](buf []byte, s source) []byte {
+ return append(buf, s[1:6]...)
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50321.go2
similarity index 65%
copy from src/cmd/compile/internal/types2/types_test.go
copy to src/cmd/compile/internal/types2/testdata/fixedbugs/issue50321.go2
index 11dca0b..199e66e 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50321.go2
@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
+package p
-func init() {
- acceptMethodTypeParams = true
+func Ln[A A /* ERROR cannot use a type parameter as constraint */ ](p A) {
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50372.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50372.go
new file mode 100644
index 0000000..0f15dc0
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50372.go
@@ -0,0 +1,27 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _(s []int) {
+ var i, j, k, l int
+ _, _, _, _ = i, j, k, l
+
+ for range s {}
+ for i = range s {}
+ for i, j = range s {}
+ for i, j, k /* ERROR range clause permits at most two iteration variables */ = range s {}
+ for i, j, k /* ERROR range clause permits at most two iteration variables */, l = range s {}
+}
+
+func _(s chan int) {
+ var i, j, k, l int
+ _, _, _, _ = i, j, k, l
+
+ for range s {}
+ for i = range s {}
+ for i, j /* ERROR range over .* permits only one iteration variable */ = range s {}
+ for i, j /* ERROR range over .* permits only one iteration variable */, k = range s {}
+ for i, j /* ERROR range over .* permits only one iteration variable */, k, l = range s {}
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2
new file mode 100644
index 0000000..2caef1b
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2
@@ -0,0 +1,68 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
+package p
+
+type Sf struct {
+ f int
+}
+
+func f0[P Sf](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+}
+
+func f0t[P ~struct{f int}](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+}
+
+var _ = f0[Sf]
+var _ = f0t[Sf]
+
+var _ = f0[Sm /* ERROR does not implement */ ]
+var _ = f0t[Sm /* ERROR does not implement */ ]
+
+func f1[P interface{ Sf; m() }](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+ p.m()
+}
+
+var _ = f1[Sf /* ERROR missing method m */ ]
+var _ = f1[Sm /* ERROR does not implement */ ]
+
+type Sm struct {}
+
+func (Sm) m() {}
+
+type Sfm struct {
+ f int
+}
+
+func (Sfm) m() {}
+
+func f2[P interface{ Sfm; m() }](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+ p.m()
+}
+
+var _ = f2[Sfm]
+
+// special case: core type is a named pointer type
+
+type PSfm *Sfm
+
+func f3[P interface{ PSfm }](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+ p.m /* ERROR type P has no field or method m */ ()
+}
+
+var _ = f3[PSfm]
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50426.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50426.go2
new file mode 100644
index 0000000..17ec0ce
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50426.go2
@@ -0,0 +1,44 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type A1 [2]uint64
+type A2 [2]uint64
+
+func (a A1) m() A1 { return a }
+func (a A2) m() A2 { return a }
+
+func f[B any, T interface {
+ A1 | A2
+ m() T
+}](v T) {
+}
+
+func _() {
+ var v A2
+ // Use function type inference to infer type A2 for T.
+ // Don't use constraint type inference before function
+ // type inference for typed arguments, otherwise it would
+ // infer type [2]uint64 for T which doesn't have method m
+ // (was the bug).
+ f[int](v)
+}
+
+// Keep using constraint type inference before function type
+// inference for untyped arguments so we infer type float64
+// for E below, and not int (which would not work).
+func g[S ~[]E, E any](S, E) {}
+
+func _() {
+ var s []float64
+ g[[]float64](s, 0)
+}
+
+// Keep using constraint type inference after function
+// type inference for untyped arguments so we infer
+// missing type arguments for which we only have the
+// untyped arguments as starting point.
+func h[E any, R []E](v E) R { return R{v} }
+func _() []int { return h(0) }
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50450.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50450.go2
new file mode 100644
index 0000000..bae3111
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50450.go2
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type S struct{}
+
+func f[P S]() {}
+
+var _ = f[S]
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50516.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50516.go2
new file mode 100644
index 0000000..f73015e
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50516.go2
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[P struct{ f int }](x P) {
+ _ = x.g // ERROR type P has no field or method g
+}
+
+func _[P struct{ f int } | struct{ g int }](x P) {
+ _ = x.g // ERROR type P has no field or method g
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50646.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50646.go2
new file mode 100644
index 0000000..3bdba11
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50646.go2
@@ -0,0 +1,26 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f1[_ comparable]() {}
+func f2[_ interface{ comparable }]() {}
+
+type T interface{ m() }
+
+func _[P comparable, Q ~int, R any]() {
+ _ = f1[int]
+ _ = f1[T /* ERROR T does not implement comparable */ ]
+ _ = f1[any /* ERROR any does not implement comparable */ ]
+ _ = f1[P]
+ _ = f1[Q]
+ _ = f1[R /* ERROR R does not implement comparable */]
+
+ _ = f2[int]
+ _ = f2[T /* ERROR T does not implement comparable */ ]
+ _ = f2[any /* ERROR any does not implement comparable */ ]
+ _ = f2[P]
+ _ = f2[Q]
+ _ = f2[R /* ERROR R does not implement comparable */]
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50755.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50755.go2
new file mode 100644
index 0000000..afc7b24
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50755.go2
@@ -0,0 +1,47 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// The core type of M2 unifies with the type of m1
+// during function argument type inference.
+// M2's constraint is unnamed.
+func f1[K1 comparable, E1 any](m1 map[K1]E1) {}
+
+func f2[M2 map[string]int](m2 M2) {
+ f1(m2)
+}
+
+// The core type of M3 unifies with the type of m1
+// during function argument type inference.
+// M3's constraint is named.
+type Map3 map[string]int
+
+func f3[M3 Map3](m3 M3) {
+ f1(m3)
+}
+
+// The core type of M5 unifies with the core type of M4
+// during constraint type inference.
+func f4[M4 map[K4]int, K4 comparable](m4 M4) {}
+
+func f5[M5 map[K5]int, K5 comparable](m5 M5) {
+ f4(m5)
+}
+
+// test case from issue
+
+func Copy[MC ~map[KC]VC, KC comparable, VC any](dst, src MC) {
+ for k, v := range src {
+ dst[k] = v
+ }
+}
+
+func Merge[MM ~map[KM]VM, KM comparable, VM any](ms ...MM) MM {
+ result := MM{}
+ for _, m := range ms {
+ Copy(result, m)
+ }
+ return result
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50779.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50779.go2
new file mode 100644
index 0000000..fe68c28
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50779.go2
@@ -0,0 +1,23 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type AC interface {
+ C
+}
+
+type ST []int
+
+type R[S any, P any] struct{}
+
+type SR = R[SS, ST]
+
+type SS interface {
+ NSR(any) *SR // ERROR invalid use of type alias SR in recursive type
+}
+
+type C interface {
+ NSR(any) *SR
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50782.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50782.go2
new file mode 100644
index 0000000..fd1ab11
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50782.go2
@@ -0,0 +1,47 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
+package p
+
+// The first example from the issue.
+type Numeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64
+}
+
+// numericAbs matches numeric types with an Abs method.
+type numericAbs[T Numeric] interface {
+ ~struct{ Value T }
+ Abs() T
+}
+
+// AbsDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
+ // Field accesses are not permitted for now. Keep an error so
+ // we can find and fix this code once the situation changes.
+ return a.Value // ERROR a\.Value undefined
+ // TODO: The error below should probably be positioned on the '-'.
+ // d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
+ // return d.Abs()
+}
+
+// The second example from the issue.
+type T[P int] struct{ f P }
+
+func _[P T[P /* ERROR "P does not implement int" */ ]]() {}
+
+// Additional tests
+func _[P T[T /* ERROR "T\[P\] does not implement int" */ [P /* ERROR "P does not implement int" */ ]]]() {}
+func _[P T[Q /* ERROR "Q does not implement int" */ ], Q T[P /* ERROR "P does not implement int" */ ]]() {}
+func _[P T[Q], Q int]() {}
+
+type C[P comparable] struct{ f P }
+func _[P C[C[P]]]() {}
+func _[P C[C /* ERROR "C\[Q\] does not implement comparable" */ [Q /* ERROR "Q does not implement comparable" */]], Q func()]() {}
+func _[P [10]C[P]]() {}
+func _[P struct{ f C[C[P]]}]() {}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50816.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50816.go2
new file mode 100644
index 0000000..e7e31d9
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50816.go2
@@ -0,0 +1,23 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkg
+
+type I interface {
+ Foo()
+}
+
+type T1 struct{}
+
+func (T1) foo() {}
+
+type T2 struct{}
+
+func (T2) foo() string { return "" }
+
+func _() {
+ var i I
+ _ = i /* ERROR impossible type assertion: i\.\(T1\)\n\tT1 does not implement I \(missing method Foo\)\n\t\thave foo\(\)\n\t\twant Foo\(\) */ .(T1)
+ _ = i /* ERROR impossible type assertion: i\.\(T2\)\n\tT2 does not implement I \(missing method Foo\)\n\t\thave foo\(\) string\n\t\twant Foo\(\) */ .(T2)
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50833.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50833.go2
new file mode 100644
index 0000000..e912e4d
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50833.go2
@@ -0,0 +1,16 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type (
+ S struct{ f int }
+ PS *S
+)
+
+func a() []*S { return []*S{{f: 1}} }
+func b() []PS { return []PS{{f: 1}} }
+
+func c[P *S]() []P { return []P{{f: 1}} }
+func d[P PS]() []P { return []P{{f: 1}} }
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50912.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50912.go2
new file mode 100644
index 0000000..f161925
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50912.go2
@@ -0,0 +1,19 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func Real[P ~complex128](x P) {
+ _ = real(x /* ERROR not supported */ )
+}
+
+func Imag[P ~complex128](x P) {
+ _ = imag(x /* ERROR not supported */ )
+}
+
+func Complex[P ~float64](x P) {
+ _ = complex(x /* ERROR not supported */ , 0)
+ _ = complex(0 /* ERROR not supported */ , x)
+ _ = complex(x /* ERROR not supported */ , x)
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50918.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50918.go
new file mode 100644
index 0000000..41604b8
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50918.go
@@ -0,0 +1,21 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type thing1 struct {
+ things []string
+}
+
+type thing2 struct {
+ things []thing1
+}
+
+func _() {
+ var a1, b1 thing1
+ _ = a1 /* ERROR struct containing \[\]string cannot be compared */ == b1
+
+ var a2, b2 thing2
+ _ = a2 /* ERROR struct containing \[\]thing1 cannot be compared */ == b2
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50929.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50929.go2
new file mode 100644
index 0000000..3629ecf
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50929.go2
@@ -0,0 +1,68 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+import "fmt"
+
+type F[A, B any] int
+
+func G[A, B any](F[A, B]) {
+}
+
+func _() {
+ // TODO(gri) only report one error below (issue #50932)
+ var x F /* ERROR got 1 arguments but 2 type parameters */ [int]
+ G(x /* ERROR does not match */)
+}
+
+// test case from issue
+// (lots of errors but doesn't crash anymore)
+
+type RC[G any, RG any] interface {
+ ~[]RG
+}
+
+type RG[G any] struct{}
+
+type RSC[G any] []*RG[G]
+
+type M[Rc RC[G, RG], G any, RG any] struct {
+ Fn func(Rc)
+}
+
+type NFn[Rc RC[G, RG], G any, RG any] func(Rc)
+
+func NC[Rc RC[G, RG], G any, RG any](nFn NFn[Rc, G, RG]) {
+ var empty Rc
+ nFn(empty)
+}
+
+func NSG[G any](c RSC[G]) {
+ fmt.Println(c)
+}
+
+func MMD[Rc RC /* ERROR got 1 arguments */ [RG], RG any, G any]() M /* ERROR got 2 arguments */ [Rc, RG] {
+
+ var nFn NFn /* ERROR got 2 arguments */ [Rc, RG]
+
+ var empty Rc
+ switch any(empty).(type) {
+ case BC /* ERROR undeclared name: BC */ :
+
+ case RSC[G]:
+ nFn = NSG /* ERROR cannot use NSG\[G\] */ [G]
+ }
+
+ return M /* ERROR got 2 arguments */ [Rc, RG]{
+ Fn: func(rc Rc) {
+ NC(nFn /* ERROR does not match */ )
+ },
+ }
+
+ return M /* ERROR got 2 arguments */ [Rc, RG]{}
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50965.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50965.go
new file mode 100644
index 0000000..bf2dcc9
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50965.go
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _(x int, c string) {
+ switch x {
+ case c /* ERROR invalid case c in switch on x \(mismatched types string and int\) */ :
+ }
+}
+
+func _(x, c []int) {
+ switch x {
+ case c /* ERROR invalid case c in switch on x \(slice can only be compared to nil\) */ :
+ }
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51048.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51048.go2
new file mode 100644
index 0000000..5830837
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51048.go2
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[P int]() {
+ _ = f[P]
+}
+
+func f[T int]() {}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51145.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51145.go
new file mode 100644
index 0000000..b84391d
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51145.go
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "fmt"
+
+type (
+ _ [fmt /* ERROR invalid array length fmt */ ]int
+ _ [float64 /* ERROR invalid array length float64 */ ]int
+ _ [f /* ERROR invalid array length f */ ]int
+ _ [nil /* ERROR invalid array length nil */ ]int
+)
+
+func f()
+
+var _ fmt.Stringer // use fmt
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51158.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51158.go2
new file mode 100644
index 0000000..3edc505
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51158.go2
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Type checking the following code should not cause an infinite recursion.
+func f[M map[K]int, K comparable](m M) {
+ f(m)
+}
+
+// Equivalent code using mutual recursion.
+func f1[M map[K]int, K comparable](m M) {
+ f2(m)
+}
+func f2[M map[K]int, K comparable](m M) {
+ f1(m)
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51229.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51229.go2
new file mode 100644
index 0000000..ef873e6
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51229.go2
@@ -0,0 +1,164 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Constraint type inference should be independent of the
+// ordering of the type parameter declarations. Try all
+// permutations in the test case below.
+// Permutations produced by https://go.dev/play/p/PHcZNGJTEBZ.
+
+func f00[S1 ~[]E1, S2 ~[]E2, E1 ~byte, E2 ~byte](S1, S2) {}
+func f01[S2 ~[]E2, S1 ~[]E1, E1 ~byte, E2 ~byte](S1, S2) {}
+func f02[E1 ~byte, S1 ~[]E1, S2 ~[]E2, E2 ~byte](S1, S2) {}
+func f03[S1 ~[]E1, E1 ~byte, S2 ~[]E2, E2 ~byte](S1, S2) {}
+func f04[S2 ~[]E2, E1 ~byte, S1 ~[]E1, E2 ~byte](S1, S2) {}
+func f05[E1 ~byte, S2 ~[]E2, S1 ~[]E1, E2 ~byte](S1, S2) {}
+func f06[E2 ~byte, S2 ~[]E2, S1 ~[]E1, E1 ~byte](S1, S2) {}
+func f07[S2 ~[]E2, E2 ~byte, S1 ~[]E1, E1 ~byte](S1, S2) {}
+func f08[S1 ~[]E1, E2 ~byte, S2 ~[]E2, E1 ~byte](S1, S2) {}
+func f09[E2 ~byte, S1 ~[]E1, S2 ~[]E2, E1 ~byte](S1, S2) {}
+func f10[S2 ~[]E2, S1 ~[]E1, E2 ~byte, E1 ~byte](S1, S2) {}
+func f11[S1 ~[]E1, S2 ~[]E2, E2 ~byte, E1 ~byte](S1, S2) {}
+func f12[S1 ~[]E1, E1 ~byte, E2 ~byte, S2 ~[]E2](S1, S2) {}
+func f13[E1 ~byte, S1 ~[]E1, E2 ~byte, S2 ~[]E2](S1, S2) {}
+func f14[E2 ~byte, S1 ~[]E1, E1 ~byte, S2 ~[]E2](S1, S2) {}
+func f15[S1 ~[]E1, E2 ~byte, E1 ~byte, S2 ~[]E2](S1, S2) {}
+func f16[E1 ~byte, E2 ~byte, S1 ~[]E1, S2 ~[]E2](S1, S2) {}
+func f17[E2 ~byte, E1 ~byte, S1 ~[]E1, S2 ~[]E2](S1, S2) {}
+func f18[E2 ~byte, E1 ~byte, S2 ~[]E2, S1 ~[]E1](S1, S2) {}
+func f19[E1 ~byte, E2 ~byte, S2 ~[]E2, S1 ~[]E1](S1, S2) {}
+func f20[S2 ~[]E2, E2 ~byte, E1 ~byte, S1 ~[]E1](S1, S2) {}
+func f21[E2 ~byte, S2 ~[]E2, E1 ~byte, S1 ~[]E1](S1, S2) {}
+func f22[E1 ~byte, S2 ~[]E2, E2 ~byte, S1 ~[]E1](S1, S2) {}
+func f23[S2 ~[]E2, E1 ~byte, E2 ~byte, S1 ~[]E1](S1, S2) {}
+
+type myByte byte
+
+func _(a []byte, b []myByte) {
+ f00(a, b)
+ f01(a, b)
+ f02(a, b)
+ f03(a, b)
+ f04(a, b)
+ f05(a, b)
+ f06(a, b)
+ f07(a, b)
+ f08(a, b)
+ f09(a, b)
+ f10(a, b)
+ f11(a, b)
+ f12(a, b)
+ f13(a, b)
+ f14(a, b)
+ f15(a, b)
+ f16(a, b)
+ f17(a, b)
+ f18(a, b)
+ f19(a, b)
+ f20(a, b)
+ f21(a, b)
+ f22(a, b)
+ f23(a, b)
+}
+
+// Constraint type inference may have to iterate.
+// Again, the order of the type parameters shouldn't matter.
+
+func g0[S ~[]E, M ~map[string]S, E any](m M) {}
+func g1[M ~map[string]S, S ~[]E, E any](m M) {}
+func g2[E any, S ~[]E, M ~map[string]S](m M) {}
+func g3[S ~[]E, E any, M ~map[string]S](m M) {}
+func g4[M ~map[string]S, E any, S ~[]E](m M) {}
+func g5[E any, M ~map[string]S, S ~[]E](m M) {}
+
+func _(m map[string][]byte) {
+ g0(m)
+ g1(m)
+ g2(m)
+ g3(m)
+ g4(m)
+ g5(m)
+}
+
+// Worst-case scenario.
+// There are 10 unknown type parameters. In each iteration of
+// constraint type inference we infer one more, from right to left.
+// Each iteration looks repeatedly at all 11 type parameters,
+// requiring a total of 10*11 = 110 iterations with the current
+// implementation. Pathological case.
+
+func h[K any, J ~*K, I ~*J, H ~*I, G ~*H, F ~*G, E ~*F, D ~*E, C ~*D, B ~*C, A ~*B](x A) {}
+
+func _(x **********int) {
+ h(x)
+}
+
+// Examples with channel constraints and tilde.
+
+func ch1[P chan<- int]() (_ P) { return } // core(P) == chan<- int (single type, no tilde)
+func ch2[P ~chan int]() { return } // core(P) == ~chan<- int (tilde)
+func ch3[P chan E, E any](E) { return } // core(P) == chan<- E (single type, no tilde)
+func ch4[P chan E | ~chan<- E, E any](E) { return } // core(P) == ~chan<- E (tilde)
+func ch5[P chan int | chan<- int]() { return } // core(P) == chan<- int (not a single type)
+
+func _() {
+ // P can be inferred as there's a single specific type and no tilde.
+ var _ chan int = ch1 /* ERROR cannot use ch1.*value of type chan<- int */ ()
+ var _ chan<- int = ch1()
+
+ // P cannot be inferred as there's a tilde.
+ ch2( /* ERROR cannot infer P */ )
+ type myChan chan int
+ ch2[myChan]()
+
+ // P can be inferred as there's a single specific type and no tilde.
+ var e int
+ ch3(e)
+
+ // P cannot be inferred as there's more than one specific type and a tilde.
+ ch4( /* ERROR cannot infer P */ e)
+ _ = ch4[chan int]
+
+ // P cannot be inferred as there's more than one specific type.
+ ch5( /* ERROR cannot infer P */ )
+ ch5[chan<- int]()
+}
+
+// test case from issue
+
+func equal[M1 ~map[K1]V1, M2 ~map[K2]V2, K1, K2 ~uint32, V1, V2 ~string](m1 M1, m2 M2) bool {
+ if len(m1) != len(m2) {
+ return false
+ }
+ for k, v1 := range m1 {
+ if v2, ok := m2[K2(k)]; !ok || V2(v1) != v2 {
+ return false
+ }
+ }
+ return true
+}
+
+func equalFixed[K1, K2 ~uint32, V1, V2 ~string](m1 map[K1]V1, m2 map[K2]V2) bool {
+ if len(m1) != len(m2) {
+ return false
+ }
+ for k, v1 := range m1 {
+ if v2, ok := m2[K2(k)]; !ok || v1 != V1(v2) {
+ return false
+ }
+ }
+ return true
+}
+
+type (
+ someNumericID uint32
+ someStringID string
+)
+
+func _() {
+ foo := map[uint32]string{10: "bar"}
+ bar := map[someNumericID]someStringID{10: "bar"}
+ equal(foo, bar)
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51232.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51232.go2
new file mode 100644
index 0000000..3fa6a05
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51232.go2
@@ -0,0 +1,30 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type RC[RG any] interface {
+ ~[]RG
+}
+
+type Fn[RCT RC[RG], RG any] func(RCT)
+
+type F[RCT RC[RG], RG any] interface {
+ Fn() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+type concreteF[RCT RC[RG], RG any] struct {
+ makeFn func() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR got 1 arguments */ [RCT] {
+ return c.makeFn()
+}
+
+func NewConcrete[RCT RC[RG], RG any](Rc RCT) F /* ERROR got 1 arguments */ [RCT] {
+ // TODO(rfindley): eliminate the duplicate error below.
+ return & /* ERROR cannot use .* as F\[RCT\] */ concreteF /* ERROR got 1 arguments */ [RCT]{
+ makeFn: nil,
+ }
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51233.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51233.go2
new file mode 100644
index 0000000..9c15028
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51233.go2
@@ -0,0 +1,27 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// As of issue #51527, type-type inference has been disabled.
+
+type RC[RG any] interface {
+ ~[]RG
+}
+
+type Fn[RCT RC[RG], RG any] func(RCT)
+
+type FFn[RCT RC[RG], RG any] func() Fn /* ERROR got 1 arguments */ [RCT]
+
+type F[RCT RC[RG], RG any] interface {
+ Fn() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+type concreteF[RCT RC[RG], RG any] struct {
+ makeFn FFn /* ERROR got 1 arguments */ [RCT]
+}
+
+func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR got 1 arguments */ [RCT] {
+ return c.makeFn()
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51257.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51257.go2
new file mode 100644
index 0000000..bc4208e
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51257.go2
@@ -0,0 +1,46 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f[_ comparable]() {}
+
+type S1 struct{ x int }
+type S2 struct{ x any }
+type S3 struct{ x [10]interface{ m() } }
+
+func _[P1 comparable, P2 S2]() {
+ _ = f[S1]
+ _ = f[S2 /* ERROR S2 does not implement comparable */ ]
+ _ = f[S3 /* ERROR S3 does not implement comparable */ ]
+
+ type L1 struct { x P1 }
+ type L2 struct { x P2 }
+ _ = f[L1]
+ _ = f[L2 /* ERROR L2 does not implement comparable */ ]
+}
+
+
+// example from issue
+
+type Set[T comparable] map[T]struct{}
+
+func NewSetFromSlice[T comparable](items []T) *Set[T] {
+ s := Set[T]{}
+
+ for _, item := range items {
+ s[item] = struct{}{}
+ }
+
+ return &s
+}
+
+type T struct{ x any }
+
+func main() {
+ NewSetFromSlice( /* ERROR T does not implement comparable */ []T{
+ {"foo"},
+ {5},
+ })
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51335.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51335.go2
new file mode 100644
index 0000000..0b5a1af
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51335.go2
@@ -0,0 +1,16 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type S1 struct{}
+type S2 struct{}
+
+func _[P *S1|*S2]() {
+ _= []P{{ /* ERROR invalid composite literal element type P: no core type */ }}
+}
+
+func _[P *S1|S1]() {
+ _= []P{{ /* ERROR invalid composite literal element type P: no core type */ }}
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51339.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51339.go2
new file mode 100644
index 0000000..84e551d
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51339.go2
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+type T[P any, B *P] struct{}
+
+func (T /* ERROR cannot use generic type */ ) m0() {}
+
+// TODO(rfindley): eliminate the duplicate errors here.
+func (T /* ERROR got 1 type parameter, but receiver base type declares 2 */ /* ERROR got 1 arguments but 2 type parameters */ [_]) m1() {}
+func (T[_, _]) m2() {}
+// TODO(gri) this error is unfortunate (issue #51343)
+func (T /* ERROR got 3 arguments but 2 type parameters */ [_, _, _]) m3() {}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51360.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51360.go
new file mode 100644
index 0000000..447ce03
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51360.go
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _() {
+ len. /* ERROR cannot select on len */ Println
+ len. /* ERROR cannot select on len */ Println()
+ _ = len. /* ERROR cannot select on len */ Println
+ _ = len[ /* ERROR cannot index len */ 0]
+ _ = *len /* ERROR cannot indirect len */
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51376.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51376.go2
new file mode 100644
index 0000000..4eba071
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51376.go2
@@ -0,0 +1,24 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type Map map[string]int
+
+func f[M ~map[K]V, K comparable, V any](M) {}
+func g[M map[K]V, K comparable, V any](M) {}
+
+func _[M1 ~map[K]V, M2 map[K]V, K comparable, V any]() {
+ var m1 M1
+ f(m1)
+ g( /* ERROR M1 does not implement map\[K\]V */ m1) // M1 has tilde
+
+ var m2 M2
+ f(m2)
+ g(m2) // M1 does not have tilde
+
+ var m3 Map
+ f(m3)
+ g( /* ERROR Map does not implement map\[string\]int */ m3) // M in g does not have tilde
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2
new file mode 100644
index 0000000..ef62239
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type myString string
+
+func _[P ~string | ~[]byte | ~[]rune]() {
+ _ = P("")
+ const s myString = ""
+ _ = P(s)
+}
+
+func _[P myString]() {
+ _ = P("")
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51437.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51437.go
new file mode 100644
index 0000000..3762615
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51437.go
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct{}
+
+func (T) m() []int { return nil }
+
+func f(x T) {
+ for _, x := range func() []int {
+ return x.m() // x declared in parameter list of f
+ }() {
+ _ = x // x declared by range clause
+ }
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51472.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51472.go2
new file mode 100644
index 0000000..f19d906
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51472.go2
@@ -0,0 +1,54 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[T comparable](x T) {
+ _ = x == x
+}
+
+func _[T interface{interface{comparable}}](x T) {
+ _ = x == x
+}
+
+func _[T interface{comparable; interface{comparable}}](x T) {
+ _ = x == x
+}
+
+func _[T interface{comparable; ~int}](x T) {
+ _ = x == x
+}
+
+func _[T interface{comparable; ~[]byte}](x T) {
+ _ = x /* ERROR cannot compare */ == x
+}
+
+// TODO(gri) The error message here should be better. See issue #51525.
+func _[T interface{comparable; ~int; ~string}](x T) {
+ _ = x /* ERROR cannot compare */ == x
+}
+
+// TODO(gri) The error message here should be better. See issue #51525.
+func _[T interface{~int; ~string}](x T) {
+ _ = x /* ERROR cannot compare */ == x
+}
+
+func _[T interface{comparable; interface{~int}; interface{int|float64}}](x T) {
+ _ = x == x
+}
+
+func _[T interface{interface{comparable; ~int}; interface{~float64; comparable; m()}}](x T) {
+ _ = x /* ERROR cannot compare */ == x
+}
+
+// test case from issue
+
+func f[T interface{comparable; []byte|string}](x T) {
+ _ = x == x
+}
+
+func _(s []byte) {
+ f( /* ERROR \[\]byte does not implement interface{comparable; \[\]byte\|string} */ s)
+ _ = f[[ /* ERROR does not implement */ ]byte]
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51509.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51509.go
new file mode 100644
index 0000000..5ae4717
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51509.go
@@ -0,0 +1,7 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T /* ERROR illegal cycle */ T.x
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51578.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51578.go2
new file mode 100644
index 0000000..5c204ba
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51578.go2
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = (*interface /* ERROR interface contains type constraints */ {int})(nil)
+
+// abbreviated test case from issue
+
+type TypeSet interface{ int | string }
+
+func _() {
+ f((*TypeSet /* ERROR interface contains type constraints */)(nil))
+}
+
+func f(any) {}
\ No newline at end of file
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51593.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51593.go2
new file mode 100644
index 0000000..d323618
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51593.go2
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f[P interface{ m(R) }, R any]() {}
+
+type T = interface { m(int) }
+
+func _() {
+ _ = f[ /* ERROR cannot infer R */ T] // don't crash in type inference
+}
diff --git a/src/cmd/compile/internal/types2/testdata/manual.go2 b/src/cmd/compile/internal/types2/testdata/manual.go2
index efe13cf..96d4ba6 100644
--- a/src/cmd/compile/internal/types2/testdata/manual.go2
+++ b/src/cmd/compile/internal/types2/testdata/manual.go2
@@ -1,4 +1,4 @@
-// Copyright 2021 The Go Authors. All rights reserved.
+// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/src/cmd/compile/internal/types2/testdata/spec/comparisons.go2 b/src/cmd/compile/internal/types2/testdata/spec/comparisons.go2
new file mode 100644
index 0000000..62c95d4
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/spec/comparisons.go2
@@ -0,0 +1,120 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package comparisons
+
+type (
+ B int // basic type representative
+ A [10]func()
+ L []byte
+ S struct{ f []byte }
+ P *S
+ F func()
+ I interface{}
+ M map[string]int
+ C chan int
+)
+
+var (
+ b B
+ a A
+ l L
+ s S
+ p P
+ f F
+ i I
+ m M
+ c C
+)
+
+func _() {
+ _ = nil == nil // ERROR operator == not defined on untyped nil
+ _ = b == b
+ _ = a /* ERROR \[10\]func\(\) cannot be compared */ == a
+ _ = l /* ERROR slice can only be compared to nil */ == l
+ _ = s /* ERROR struct containing \[\]byte cannot be compared */ == s
+ _ = p == p
+ _ = f /* ERROR func can only be compared to nil */ == f
+ _ = i == i
+ _ = m /* ERROR map can only be compared to nil */ == m
+ _ = c == c
+
+ _ = b /* ERROR mismatched types */ == nil
+ _ = a /* ERROR mismatched types */ == nil
+ _ = l == nil
+ _ = s /* ERROR mismatched types */ == nil
+ _ = p == nil
+ _ = f == nil
+ _ = i == nil
+ _ = m == nil
+ _ = c == nil
+
+ _ = nil /* ERROR operator < not defined on untyped nil */ < nil
+ _ = b < b
+ _ = a /* ERROR operator < not defined on array */ < a
+ _ = l /* ERROR operator < not defined on slice */ < l
+ _ = s /* ERROR operator < not defined on struct */ < s
+ _ = p /* ERROR operator < not defined on pointer */ < p
+ _ = f /* ERROR operator < not defined on func */ < f
+ _ = i /* ERROR operator < not defined on interface */ < i
+ _ = m /* ERROR operator < not defined on map */ < m
+ _ = c /* ERROR operator < not defined on chan */ < c
+}
+
+func _[
+ B int,
+ A [10]func(),
+ L []byte,
+ S struct{ f []byte },
+ P *S,
+ F func(),
+ I interface{},
+ J comparable,
+ M map[string]int,
+ C chan int,
+] (
+ b B,
+ a A,
+ l L,
+ s S,
+ p P,
+ f F,
+ i I,
+ j J,
+ m M,
+ c C,
+) {
+ _ = b == b
+ _ = a /* ERROR type parameter A is not comparable with == */ == a
+ _ = l /* ERROR type parameter L is not comparable with == */ == l
+ _ = s /* ERROR type parameter S is not comparable with == */ == s
+ _ = p == p
+ _ = f /* ERROR type parameter F is not comparable with == */ == f
+ _ = i /* ERROR type parameter I is not comparable with == */ == i
+ _ = j == j
+ _ = m /* ERROR type parameter M is not comparable with == */ == m
+ _ = c == c
+
+ _ = b /* ERROR mismatched types */ == nil
+ _ = a /* ERROR mismatched types */ == nil
+ _ = l == nil
+ _ = s /* ERROR mismatched types */ == nil
+ _ = p == nil
+ _ = f == nil
+ _ = i /* ERROR mismatched types */ == nil
+ _ = j /* ERROR mismatched types */ == nil
+ _ = m == nil
+ _ = c == nil
+
+ _ = b < b
+ _ = a /* ERROR type parameter A is not comparable with < */ < a
+ _ = l /* ERROR type parameter L is not comparable with < */ < l
+ _ = s /* ERROR type parameter S is not comparable with < */ < s
+ _ = p /* ERROR type parameter P is not comparable with < */ < p
+ _ = f /* ERROR type parameter F is not comparable with < */ < f
+ _ = i /* ERROR type parameter I is not comparable with < */ < i
+ _ = j /* ERROR type parameter J is not comparable with < */ < j
+ _ = m /* ERROR type parameter M is not comparable with < */ < m
+ _ = c /* ERROR type parameter C is not comparable with < */ < c
+}
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index 9487ac5..0fe39db 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -7,9 +7,7 @@
// A Type represents a type of Go.
// All types implement the Type interface.
type Type interface {
- // Underlying returns the underlying type of a type
- // w/o following forwarding chains. Only used by
- // client packages.
+ // Underlying returns the underlying type of a type.
Underlying() Type
// String returns a string representation of a type.
@@ -27,13 +25,13 @@
return t.Underlying()
}
-// If t is not a type parameter, structuralType returns the underlying type.
-// If t is a type parameter, structuralType returns the single underlying
+// If t is not a type parameter, coreType returns the underlying type.
+// If t is a type parameter, coreType returns the single underlying
// type of all types in its type set if it exists, or nil otherwise. If the
// type set contains only unrestricted and restricted channel types (with
// identical element types), the single underlying type is the restricted
// channel type if the restrictions are always the same, or nil otherwise.
-func structuralType(t Type) Type {
+func coreType(t Type) Type {
tpar, _ := t.(*TypeParam)
if tpar == nil {
return under(t)
@@ -59,10 +57,10 @@
return nil
}
-// structuralString is like structuralType but also considers []byte
+// coreString is like coreType but also considers []byte
// and strings as identical. In this case, if successful and we saw
// a string, the result is of type (possibly untyped) string.
-func structuralString(t Type) Type {
+func coreString(t Type) Type {
tpar, _ := t.(*TypeParam)
if tpar == nil {
return under(t) // string or untyped string
diff --git a/src/cmd/compile/internal/types2/typelists.go b/src/cmd/compile/internal/types2/typelists.go
index 0b77edb..a2aba4a 100644
--- a/src/cmd/compile/internal/types2/typelists.go
+++ b/src/cmd/compile/internal/types2/typelists.go
@@ -4,8 +4,6 @@
package types2
-import "bytes"
-
// TypeParamList holds a list of type parameters.
type TypeParamList struct{ tparams []*TypeParam }
@@ -54,15 +52,6 @@
return l.types
}
-func (l *TypeList) String() string {
- if l == nil || len(l.types) == 0 {
- return "[]"
- }
- var buf bytes.Buffer
- newTypeWriter(&buf, nil).typeList(l.types)
- return buf.String()
-}
-
// ----------------------------------------------------------------------------
// Implementation
diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go
index e32063a..2e9a2ad 100644
--- a/src/cmd/compile/internal/types2/typeparam.go
+++ b/src/cmd/compile/internal/types2/typeparam.go
@@ -31,11 +31,13 @@
// or Signature type by calling SetTypeParams. Setting a type parameter on more
// than one type will result in a panic.
//
-// The constraint argument can be nil, and set later via SetConstraint.
+// The constraint argument can be nil, and set later via SetConstraint. If the
+// constraint is non-nil, it must be fully defined.
func NewTypeParam(obj *TypeName, constraint Type) *TypeParam {
return (*Checker)(nil).newTypeParam(obj, constraint)
}
+// check may be nil
func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam {
// Always increment lastID, even if it is not used.
id := nextID()
@@ -50,9 +52,7 @@
// iface may mutate typ.bound, so we must ensure that iface() is called
// at least once before the resulting TypeParam escapes.
if check != nil {
- check.later(func() {
- typ.iface()
- })
+ check.needsCleanup(typ)
} else if constraint != nil {
typ.iface()
}
@@ -72,8 +72,10 @@
// SetConstraint sets the type constraint for t.
//
-// SetConstraint should not be called concurrently, but once SetConstraint
-// returns the receiver t is safe for concurrent use.
+// It must be called by users of NewTypeParam after the bound's underlying is
+// fully defined, and before using the type parameter in any way other than to
+// form other types. Once SetConstraint returns the receiver, t is safe for
+// concurrent use.
func (t *TypeParam) SetConstraint(bound Type) {
if bound == nil {
panic("nil constraint")
@@ -93,9 +95,12 @@
// ----------------------------------------------------------------------------
// Implementation
+func (t *TypeParam) cleanup() {
+ t.iface()
+ t.check = nil
+}
+
// iface returns the constraint interface of t.
-// TODO(gri) If we make tparamIsIface the default, this should be renamed to under
-// (similar to Named.under).
func (t *TypeParam) iface() *Interface {
bound := t.bound
@@ -124,8 +129,9 @@
// compute type set if necessary
if ityp.tset == nil {
- // use the (original) type bound position if we have one
- pos := nopos
+ // pos is used for tracing output; start with the type parameter position.
+ pos := t.obj.pos
+ // use the (original or possibly instantiated) type bound position if we have one
if n, _ := bound.(*Named); n != nil {
pos = n.obj.pos
}
@@ -135,16 +141,6 @@
return ityp
}
-// singleType returns the single type of the type parameter constraint; or nil.
-func (t *TypeParam) singleType() Type {
- return t.iface().typeSet().singleType()
-}
-
-// hasTerms reports whether the type parameter constraint has specific type terms.
-func (t *TypeParam) hasTerms() bool {
- return t.iface().typeSet().hasTerms()
-}
-
// is calls f with the specific type terms of t's constraint and reports whether
// all calls to f returned true. If there are no specific terms, is
// returns the result of f(nil).
diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go
index eaf614d..8df8949 100644
--- a/src/cmd/compile/internal/types2/typeset.go
+++ b/src/cmd/compile/internal/types2/typeset.go
@@ -15,41 +15,39 @@
// API
// A _TypeSet represents the type set of an interface.
+// Because of existing language restrictions, methods can be "factored out"
+// from the terms. The actual type set is the intersection of the type set
+// implied by the methods and the type set described by the terms and the
+// comparable bit. To test whether a type is included in a type set
+// ("implements" relation), the type must implement all methods _and_ be
+// an element of the type set described by the terms and the comparable bit.
+// If the term list describes the set of all types and comparable is true,
+// only comparable types are meant; in all other cases comparable is false.
type _TypeSet struct {
- comparable bool // if set, the interface is or embeds comparable
- // TODO(gri) consider using a set for the methods for faster lookup
- methods []*Func // all methods of the interface; sorted by unique ID
- terms termlist // type terms of the type set
+ methods []*Func // all methods of the interface; sorted by unique ID
+ terms termlist // type terms of the type set
+ comparable bool // invariant: !comparable || terms.isAll()
}
// IsEmpty reports whether type set s is the empty set.
func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() }
// IsAll reports whether type set s is the set of all types (corresponding to the empty interface).
-func (s *_TypeSet) IsAll() bool {
- return !s.comparable && len(s.methods) == 0 && s.terms.isAll()
-}
+func (s *_TypeSet) IsAll() bool { return s.IsMethodSet() && len(s.methods) == 0 }
// IsMethodSet reports whether the interface t is fully described by its method set.
func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() }
// IsComparable reports whether each type in the set is comparable.
-func (s *_TypeSet) IsComparable() bool {
+func (s *_TypeSet) IsComparable(seen map[Type]bool) bool {
if s.terms.isAll() {
return s.comparable
}
return s.is(func(t *term) bool {
- return t != nil && Comparable(t.typ)
+ return t != nil && comparable(t.typ, false, seen, nil)
})
}
-// TODO(gri) IsTypeSet is not a great name for this predicate. Find a better one.
-
-// IsTypeSet reports whether the type set s is represented by a finite set of underlying types.
-func (s *_TypeSet) IsTypeSet() bool {
- return !s.comparable && len(s.methods) == 0
-}
-
// NumMethods returns the number of methods available.
func (s *_TypeSet) NumMethods() int { return len(s.methods) }
@@ -58,9 +56,8 @@
func (s *_TypeSet) Method(i int) *Func { return s.methods[i] }
// LookupMethod returns the index of and method with matching package and name, or (-1, nil).
-func (s *_TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) {
- // TODO(gri) s.methods is sorted - consider binary search
- return lookupMethod(s.methods, pkg, name)
+func (s *_TypeSet) LookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
+ return lookupMethod(s.methods, pkg, name, foldCase)
}
func (s *_TypeSet) String() string {
@@ -104,14 +101,6 @@
// hasTerms reports whether the type set has specific type terms.
func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
-// singleType returns the single type in s if there is exactly one; otherwise the result is nil.
-func (s *_TypeSet) singleType() Type { return s.terms.singleType() }
-
-// includes reports whether t ∈ s.
-// TODO(gri) This function is not used anywhere anymore. Remove once we
-// are clear that we don't need it elsewhere in the future.
-func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) }
-
// subsetOf reports whether s1 ⊆ s2.
func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }
@@ -135,7 +124,7 @@
// underIs calls f with the underlying types of the specific type terms
// of s and reports whether all calls to f returned true. If there are
-// no specific terms, is returns the result of f(nil).
+// no specific terms, underIs returns the result of f(nil).
func (s *_TypeSet) underIs(f func(Type) bool) bool {
if !s.hasTerms() {
return f(nil)
@@ -167,7 +156,7 @@
}
// If the interface is not fully set up yet, the type set will
- // not be complete, which may lead to errors when using the the
+ // not be complete, which may lead to errors when using the
// type set (e.g. missing method). Don't compute a partial type
// set (and don't store it!), so that we still compute the full
// type set eventually. Instead, return the top type set and
@@ -199,6 +188,16 @@
// reason.
ityp.tset = &_TypeSet{terms: allTermlist} // TODO(gri) is this sufficient?
+ var unionSets map[*Union]*_TypeSet
+ if check != nil {
+ if check.unionTypeSets == nil {
+ check.unionTypeSets = make(map[*Union]*_TypeSet)
+ }
+ unionSets = check.unionTypeSets
+ } else {
+ unionSets = make(map[*Union]*_TypeSet)
+ }
+
// Methods of embedded interfaces are collected unchanged; i.e., the identity
// of a method I.m's Func Object of an interface I is the same as that of
// the method m in an interface that embeds interface I. On the other hand,
@@ -214,12 +213,12 @@
var todo []*Func
var seen objset
- var methods []*Func
+ var allMethods []*Func
mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages
addMethod := func(pos syntax.Pos, m *Func, explicit bool) {
switch other := seen.insert(m); {
case other == nil:
- methods = append(methods, m)
+ allMethods = append(allMethods, m)
mpos[m] = pos
case explicit:
if check == nil {
@@ -258,7 +257,8 @@
}
// collect embedded elements
- var allTerms = allTermlist
+ allTerms := allTermlist
+ allComparable := false
for i, typ := range ityp.embeddeds {
// The embedding position is nil for imported interfaces
// and also for interface copies after substitution (but
@@ -267,6 +267,7 @@
if ityp.embedPos != nil {
pos = (*ityp.embedPos)[i]
}
+ var comparable bool
var terms termlist
switch u := under(typ).(type) {
case *Interface:
@@ -278,9 +279,7 @@
check.versionErrorf(pos, "go1.18", "embedding constraint interface %s", typ)
continue
}
- if tset.comparable {
- ityp.tset.comparable = true
- }
+ comparable = tset.comparable
for _, m := range tset.methods {
addMethod(pos, m, false) // use embedding position pos rather than m.pos
}
@@ -290,10 +289,12 @@
check.versionErrorf(pos, "go1.18", "embedding interface element %s", u)
continue
}
- tset := computeUnionTypeSet(check, pos, u)
+ tset := computeUnionTypeSet(check, unionSets, pos, u)
if tset == &invalidTypeSet {
continue // ignore invalid unions
}
+ assert(!tset.comparable)
+ assert(len(tset.methods) == 0)
terms = tset.terms
default:
if u == Typ[Invalid] {
@@ -305,11 +306,11 @@
}
terms = termlist{{false, typ}}
}
- // The type set of an interface is the intersection
- // of the type sets of all its elements.
- // Intersection cannot produce longer termlists and
- // thus cannot overflow.
- allTerms = allTerms.intersect(terms)
+
+ // The type set of an interface is the intersection of the type sets of all its elements.
+ // Due to language restrictions, only embedded interfaces can add methods, they are handled
+ // separately. Here we only need to intersect the term lists and comparable bits.
+ allTerms, allComparable = intersectTermLists(allTerms, allComparable, terms, comparable)
}
ityp.embedPos = nil // not needed anymore (errors have been reported)
@@ -322,15 +323,46 @@
}
}
- if methods != nil {
- sortMethods(methods)
- ityp.tset.methods = methods
+ ityp.tset.comparable = allComparable
+ if len(allMethods) != 0 {
+ sortMethods(allMethods)
+ ityp.tset.methods = allMethods
}
ityp.tset.terms = allTerms
return ityp.tset
}
+// TODO(gri) The intersectTermLists function belongs to the termlist implementation.
+// The comparable type set may also be best represented as a term (using
+// a special type).
+
+// intersectTermLists computes the intersection of two term lists and respective comparable bits.
+// xcomp, ycomp are valid only if xterms.isAll() and yterms.isAll() respectively.
+func intersectTermLists(xterms termlist, xcomp bool, yterms termlist, ycomp bool) (termlist, bool) {
+ terms := xterms.intersect(yterms)
+ // If one of xterms or yterms is marked as comparable,
+ // the result must only include comparable types.
+ comp := xcomp || ycomp
+ if comp && !terms.isAll() {
+ // only keep comparable terms
+ i := 0
+ for _, t := range terms {
+ assert(t.typ != nil)
+ if Comparable(t.typ) {
+ terms[i] = t
+ i++
+ }
+ }
+ terms = terms[:i]
+ if !terms.isAll() {
+ comp = false
+ }
+ }
+ assert(!comp || terms.isAll()) // comparable invariant
+ return terms, comp
+}
+
func sortMethods(list []*Func) {
sort.Sort(byUniqueMethodName(list))
}
@@ -358,13 +390,13 @@
// computeUnionTypeSet may be called with check == nil.
// The result is &invalidTypeSet if the union overflows.
-func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet {
- if utyp.tset != nil {
- return utyp.tset
+func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos syntax.Pos, utyp *Union) *_TypeSet {
+ if tset, _ := unionSets[utyp]; tset != nil {
+ return tset
}
// avoid infinite recursion (see also computeInterfaceTypeSet)
- utyp.tset = new(_TypeSet)
+ unionSets[utyp] = new(_TypeSet)
var allTerms termlist
for _, t := range utyp.terms {
@@ -391,11 +423,11 @@
if check != nil {
check.errorf(pos, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
}
- utyp.tset = &invalidTypeSet
- return utyp.tset
+ unionSets[utyp] = &invalidTypeSet
+ return unionSets[utyp]
}
}
- utyp.tset.terms = allTerms
+ unionSets[utyp].terms = allTerms
- return utyp.tset
+ return unionSets[utyp]
}
diff --git a/src/cmd/compile/internal/types2/typeset_test.go b/src/cmd/compile/internal/types2/typeset_test.go
index 7f7cc06..68e5d8a 100644
--- a/src/cmd/compile/internal/types2/typeset_test.go
+++ b/src/cmd/compile/internal/types2/typeset_test.go
@@ -25,9 +25,9 @@
"{int; string}": "∅",
"{comparable}": "{comparable}",
- "{comparable; int}": "{comparable; int}",
- "{~int; comparable}": "{comparable; ~int}",
- "{int|string; comparable}": "{comparable; int ∪ string}",
+ "{comparable; int}": "{int}",
+ "{~int; comparable}": "{~int}",
+ "{int|string; comparable}": "{int ∪ string}",
"{comparable; int; string}": "∅",
"{m()}": "{func (p.T).m()}",
@@ -37,8 +37,8 @@
"{m1(); comparable; m2() int }": "{comparable; func (p.T).m1(); func (p.T).m2() int}",
"{comparable; error}": "{comparable; func (error).Error() string}",
- "{m(); comparable; int|float32|string}": "{comparable; func (p.T).m(); int ∪ float32 ∪ string}",
- "{m1(); int; m2(); comparable }": "{comparable; func (p.T).m1(); func (p.T).m2(); int}",
+ "{m(); comparable; int|float32|string}": "{func (p.T).m(); int ∪ float32 ∪ string}",
+ "{m1(); int; m2(); comparable }": "{func (p.T).m1(); func (p.T).m2(); int}",
"{E}; type E interface{}": "𝓤",
"{E}; type E interface{int;string}": "∅",
diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go
index 4d03eba..ada0529 100644
--- a/src/cmd/compile/internal/types2/typestring.go
+++ b/src/cmd/compile/internal/types2/typestring.go
@@ -201,12 +201,18 @@
}
case *Interface:
- if t == universeAny.Type() && w.ctxt == nil {
- // When not hashing, we can try to improve type strings by writing "any"
- // for a type that is pointer-identical to universeAny. This logic should
- // be deprecated by more robust handling for aliases.
- w.string("any")
- break
+ if w.ctxt == nil {
+ if t == universeAny.Type() {
+ // When not hashing, we can try to improve type strings by writing "any"
+ // for a type that is pointer-identical to universeAny. This logic should
+ // be deprecated by more robust handling for aliases.
+ w.string("any")
+ break
+ }
+ if t == universeComparable.Type().(*Named).underlying {
+ w.string("interface{comparable}")
+ break
+ }
}
if t.implicit {
if len(t.methods) == 0 && len(t.embeddeds) == 1 {
diff --git a/src/cmd/compile/internal/types2/typestring_test.go b/src/cmd/compile/internal/types2/typestring_test.go
index eda6835..c0689e8 100644
--- a/src/cmd/compile/internal/types2/typestring_test.go
+++ b/src/cmd/compile/internal/types2/typestring_test.go
@@ -93,6 +93,10 @@
dup(`interface{String() string; m(int) float32}`),
dup("interface{int|float32|complex128}"),
dup("interface{int|~float32|~complex128}"),
+ dup("any"),
+ dup("interface{comparable}"),
+ {"comparable", "interface{comparable}"},
+ {"error", "interface{Error() string}"},
// maps
dup("map[string]int"),
diff --git a/src/cmd/compile/internal/types2/typeterm_test.go b/src/cmd/compile/internal/types2/typeterm_test.go
index 5a5c1fa..6d9c8db 100644
--- a/src/cmd/compile/internal/types2/typeterm_test.go
+++ b/src/cmd/compile/internal/types2/typeterm_test.go
@@ -99,7 +99,7 @@
"~int ~string ~int ~string",
"~int myInt ~int ∅",
- // union is symmetric, but the result order isn't - repeat symmetric cases explictly
+ // union is symmetric, but the result order isn't - repeat symmetric cases explicitly
"𝓤 ∅ 𝓤 ∅",
"int ∅ int ∅",
"~int ∅ ~int ∅",
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index 9121c2c..7e30562 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -99,6 +99,10 @@
x.mode = constant_
case *TypeName:
+ if check.isBrokenAlias(obj) {
+ check.errorf(e, "invalid use of type alias %s in recursive type (see issue #50729)", obj.name)
+ return
+ }
x.mode = typexpr
case *Var:
@@ -143,10 +147,16 @@
// constraint interface.
func (check *Checker) varType(e syntax.Expr) Type {
typ := check.definedType(e, nil)
+ check.validVarType(e, typ)
+ return typ
+}
+// validVarType reports an error if typ is a constraint interface.
+// The expression e is used for error reporting, if any.
+func (check *Checker) validVarType(e syntax.Expr, typ Type) {
// If we have a type parameter there's nothing to do.
if isTypeParam(typ) {
- return typ
+ return
}
// We don't want to call under() or complete interfaces while we are in
@@ -165,8 +175,6 @@
}
}
})
-
- return typ
}
// definedType is like typ but also accepts a type name def.
@@ -211,7 +219,7 @@
//
func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
if check.conf.Trace {
- check.trace(e0.Pos(), "type %s", e0)
+ check.trace(e0.Pos(), "-- type %s", e0)
check.indent++
defer func() {
check.indent--
@@ -252,7 +260,7 @@
case *syntax.SelectorExpr:
var x operand
- check.selector(&x, e)
+ check.selector(&x, e, def)
switch x.mode {
case typexpr:
@@ -338,7 +346,7 @@
return typ
case *syntax.InterfaceType:
- typ := new(Interface)
+ typ := check.newInterface()
def.setUnderlying(typ)
if def != nil {
typ.obj = def.obj
@@ -426,10 +434,14 @@
// evaluate arguments
targs := check.typeList(xlist)
if targs == nil {
- def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
+ def.setUnderlying(Typ[Invalid]) // avoid errors later due to lazy instantiation
return Typ[Invalid]
}
+ // enableTypeTypeInference controls whether to infer missing type arguments
+ // using constraint type inference. See issue #51527.
+ const enableTypeTypeInference = false
+
// create the instance
ctxt := check.bestContext(nil)
h := ctxt.instanceHash(orig, targs)
@@ -440,27 +452,27 @@
// validation below. Ensure that the validation (and resulting errors) runs
// for each instantiated type in the source.
if inst == nil {
- tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil)
+ // x may be a selector for an imported type; use its start pos rather than x.Pos().
+ tname := NewTypeName(syntax.StartPos(x), orig.obj.pkg, orig.obj.name, nil)
inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved
inst.targs = newTypeList(targs)
inst = ctxt.update(h, orig, targs, inst).(*Named)
}
def.setUnderlying(inst)
- inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) {
- tparams := orig.TypeParams().list()
+ inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, *methodList) {
+ tparams := n.orig.TypeParams().list()
- inferred := targs
- if len(targs) < len(tparams) {
+ targs := n.targs.list()
+ if enableTypeTypeInference && len(targs) < len(tparams) {
// If inference fails, len(inferred) will be 0, and inst.underlying will
// be set to Typ[Invalid] in expandNamed.
- inferred = check.infer(x.Pos(), tparams, targs, nil, nil)
+ inferred := check.infer(x.Pos(), tparams, targs, nil, nil)
if len(inferred) > len(targs) {
- inst.targs = newTypeList(inferred)
+ n.targs = newTypeList(inferred)
}
}
- check.recordInstance(x, inferred, inst)
return expandNamed(ctxt, n, x.Pos())
}
@@ -473,6 +485,7 @@
// Since check is non-nil, we can still mutate inst. Unpinning the resolver
// frees some memory.
inst.resolver = nil
+ check.recordInstance(x, inst.TypeArgs().list(), inst)
if check.validateTArgLen(x.Pos(), inst.tparams.Len(), inst.targs.Len()) {
if i, err := check.verify(x.Pos(), inst.tparams.list(), inst.targs.list()); err != nil {
@@ -487,7 +500,7 @@
}
}
- check.validType(inst, nil)
+ check.validType(inst)
})
return inst
@@ -497,12 +510,20 @@
// and returns the constant length >= 0, or a value < 0
// to indicate an error (and thus an unknown length).
func (check *Checker) arrayLength(e syntax.Expr) int64 {
- // If e is an undeclared identifier, the array declaration might be an
- // attempt at a parameterized type declaration with missing constraint.
- // Provide a better error message than just "undeclared name: X".
- if name, _ := e.(*syntax.Name); name != nil && check.lookup(name.Value) == nil {
- check.errorf(name, "undeclared name %s for array length", name.Value)
- return -1
+ // If e is an identifier, the array declaration might be an
+ // attempt at a parameterized type declaration with missing
+ // constraint. Provide an error message that mentions array
+ // length.
+ if name, _ := e.(*syntax.Name); name != nil {
+ obj := check.lookup(name.Value)
+ if obj == nil {
+ check.errorf(name, "undeclared name %s for array length", name.Value)
+ return -1
+ }
+ if _, ok := obj.(*Const); !ok {
+ check.errorf(name, "invalid array length %s", name.Value)
+ return -1
+ }
}
var x operand
diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go
index f663bee..97d327c 100644
--- a/src/cmd/compile/internal/types2/unify.go
+++ b/src/cmd/compile/internal/types2/unify.go
@@ -9,6 +9,7 @@
import (
"bytes"
"fmt"
+ "strings"
)
// The unifier maintains two separate sets of type parameters x and y
@@ -26,13 +27,36 @@
// parameter P ("x" side), but the argument type P must be left alone so
// that unification resolves the type parameter P to P.
//
-// For bidirection unification, both sets are provided. This enables
+// For bidirectional unification, both sets are provided. This enables
// unification to go from argument to parameter type and vice versa.
// For constraint type inference, we use bidirectional unification
// where both the x and y type parameters are identical. This is done
// by setting up one of them (using init) and then assigning its value
// to the other.
+const (
+ // Upper limit for recursion depth. Used to catch infinite recursions
+ // due to implementation issues (e.g., see issues #48619, #48656).
+ unificationDepthLimit = 50
+
+ // Whether to panic when unificationDepthLimit is reached. Turn on when
+ // investigating infinite recursion.
+ panicAtUnificationDepthLimit = false
+
+ // If enableCoreTypeUnification is set, unification will consider
+ // the core types, if any, of non-local (unbound) type parameters.
+ enableCoreTypeUnification = true
+
+ // If traceInference is set, unification will print a trace of its operation.
+ // Interpretation of trace:
+ // x ≡ y attempt to unify types x and y
+ // p ➞ y type parameter p is set to type y (p is inferred to be y)
+ // p ⇄ q type parameters p and q match (p is inferred to be q and vice versa)
+ // x ≢ y types x and y cannot be unified
+ // [p, q, ...] ➞ [x, y, ...] mapping from type parameters to types
+ traceInference = false
+)
+
// A unifier maintains the current type parameters for x and y
// and the respective types inferred for each type parameter.
// A unifier is created by calling newUnifier.
@@ -40,6 +64,7 @@
exact bool
x, y tparamsList // x and y must initialized via tparamsList.init
types []Type // inferred types, shared by x and y
+ depth int // recursion depth during unification
}
// newUnifier returns a new unifier.
@@ -47,6 +72,7 @@
// exactly. If exact is not set, a named type's underlying type
// is considered if unification would fail otherwise, and the
// direction of channels is ignored.
+// TODO(gri) exact is not set anymore by a caller. Consider removing it.
func newUnifier(exact bool) *unifier {
u := &unifier{exact: exact}
u.x.unifier = u
@@ -59,6 +85,10 @@
return u.nify(x, y, nil)
}
+func (u *unifier) tracef(format string, args ...interface{}) {
+ fmt.Println(strings.Repeat(". ", u.depth) + sprintf(nil, true, format, args...))
+}
+
// A tparamsList describes a list of type parameters and the types inferred for them.
type tparamsList struct {
unifier *unifier
@@ -110,6 +140,9 @@
// If both type parameters already have a type associated with them and they are
// not joined, join fails and returns false.
func (u *unifier) join(i, j int) bool {
+ if traceInference {
+ u.tracef("%s ⇄ %s", u.x.tparams[i], u.y.tparams[j])
+ }
ti := u.x.indices[i]
tj := u.y.indices[j]
switch {
@@ -199,6 +232,9 @@
func (d *tparamsList) set(i int, typ Type) {
assert(typ != nil)
u := d.unifier
+ if traceInference {
+ u.tracef("%s ➞ %s", d.tparams[i], typ)
+ }
switch ti := d.indices[i]; {
case ti < 0:
u.types[-ti-1] = typ
@@ -211,6 +247,17 @@
}
}
+// unknowns returns the number of type parameters for which no type has been set yet.
+func (d *tparamsList) unknowns() int {
+ n := 0
+ for _, ti := range d.indices {
+ if ti <= 0 {
+ n++
+ }
+ }
+ return n
+}
+
// types returns the list of inferred types (via unification) for the type parameters
// described by d, and an index. If all types were inferred, the returned index is < 0.
// Otherwise, it is the index of the first type parameter which couldn't be inferred;
@@ -236,7 +283,29 @@
// adapted version of Checker.identical. For changes to that
// code the corresponding changes should be made here.
// Must not be called directly from outside the unifier.
-func (u *unifier) nify(x, y Type, p *ifacePair) bool {
+func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
+ if traceInference {
+ u.tracef("%s ≡ %s", x, y)
+ }
+
+ // Stop gap for cases where unification fails.
+ if u.depth >= unificationDepthLimit {
+ if traceInference {
+ u.tracef("depth %d >= %d", u.depth, unificationDepthLimit)
+ }
+ if panicAtUnificationDepthLimit {
+ panic("unification reached recursion depth limit")
+ }
+ return false
+ }
+ u.depth++
+ defer func() {
+ u.depth--
+ if traceInference && !result {
+ u.tracef("%s ≢ %s", x, y)
+ }
+ }()
+
if !u.exact {
// If exact unification is known to fail because we attempt to
// match a type name against an unnamed type literal, consider
@@ -244,8 +313,14 @@
// (We use !hasName to exclude any type with a name, including
// basic types and type parameters; the rest are unamed types.)
if nx, _ := x.(*Named); nx != nil && !hasName(y) {
+ if traceInference {
+ u.tracef("under %s ≡ %s", nx, y)
+ }
return u.nify(nx.under(), y, p)
} else if ny, _ := y.(*Named); ny != nil && !hasName(x) {
+ if traceInference {
+ u.tracef("%s ≡ under %s", x, ny)
+ }
return u.nify(x, ny.under(), p)
}
}
@@ -279,6 +354,39 @@
return true
}
+ // If we get here and x or y is a type parameter, they are type parameters
+ // from outside our declaration list. Try to unify their core types, if any
+ // (see issue #50755 for a test case).
+ if enableCoreTypeUnification && !u.exact {
+ if isTypeParam(x) && !hasName(y) {
+ // When considering the type parameter for unification
+ // we look at the adjusted core term (adjusted core type
+ // with tilde information).
+ // If the adjusted core type is a named type N; the
+ // corresponding core type is under(N). Since !u.exact
+ // and y doesn't have a name, unification will end up
+ // comparing under(N) to y, so we can just use the core
+ // type instead. And we can ignore the tilde because we
+ // already look at the underlying types on both sides
+ // and we have known types on both sides.
+ // Optimization.
+ if cx := coreType(x); cx != nil {
+ if traceInference {
+ u.tracef("core %s ≡ %s", x, y)
+ }
+ return u.nify(cx, y, p)
+ }
+ } else if isTypeParam(y) && !hasName(x) {
+ // see comment above
+ if cy := coreType(y); cy != nil {
+ if traceInference {
+ u.tracef("%s ≡ core %s", x, y)
+ }
+ return u.nify(x, cy, p)
+ }
+ }
+ }
+
// For type unification, do not shortcut (x == y) for identical
// types. Instead keep comparing them element-wise to unify the
// matching (and equal type parameter types). A simple test case
@@ -370,6 +478,9 @@
if y, ok := y.(*Interface); ok {
xset := x.typeSet()
yset := y.typeSet()
+ if xset.comparable != yset.comparable {
+ return false
+ }
if !xset.terms.equal(yset.terms) {
return false
}
@@ -437,11 +548,14 @@
xargs := x.targs.list()
yargs := y.targs.list()
+ if len(xargs) != len(yargs) {
+ return false
+ }
+
// TODO(gri) This is not always correct: two types may have the same names
// in the same package if one of them is nested in a function.
// Extremely unlikely but we need an always correct solution.
if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
- assert(len(xargs) == len(yargs))
for i, x := range xargs {
if !u.nify(x, yargs[i], p) {
return false
@@ -461,7 +575,7 @@
// avoid a crash in case of nil type
default:
- panic(fmt.Sprintf("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams))
+ panic(sprintf(nil, true, "u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams))
}
return false
diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go
index 97581fe..e317b9c 100644
--- a/src/cmd/compile/internal/types2/union.go
+++ b/src/cmd/compile/internal/types2/union.go
@@ -11,8 +11,7 @@
// A Union represents a union of terms embedded in an interface.
type Union struct {
- terms []*Term // list of syntactical terms (not a canonicalized termlist)
- tset *_TypeSet // type set described by this union, computed lazily
+ terms []*Term // list of syntactical terms (not a canonicalized termlist)
}
// NewUnion returns a new Union type with the given terms.
@@ -21,7 +20,7 @@
if len(terms) == 0 {
panic("empty union")
}
- return &Union{terms, nil}
+ return &Union{terms}
}
func (u *Union) Len() int { return len(u.terms) }
@@ -49,23 +48,37 @@
// parseUnion parses uexpr as a union of expressions.
// The result is a Union type, or Typ[Invalid] for some errors.
func parseUnion(check *Checker, uexpr syntax.Expr) Type {
- tlist := flattenUnion(nil, uexpr)
+ blist, tlist := flattenUnion(nil, uexpr)
+ assert(len(blist) == len(tlist)-1)
var terms []*Term
- for _, x := range tlist {
- tilde, typ := parseTilde(check, x)
- if len(tlist) == 1 && !tilde {
+
+ var u Type
+ for i, x := range tlist {
+ term := parseTilde(check, x)
+ if len(tlist) == 1 && !term.tilde {
// Single type. Ok to return early because all relevant
// checks have been performed in parseTilde (no need to
// run through term validity check below).
- return typ // typ already recorded through check.typ in parseTilde
+ return term.typ // typ already recorded through check.typ in parseTilde
}
if len(terms) >= maxTermCount {
- check.errorf(x, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
- check.recordTypeAndValue(uexpr, typexpr, Typ[Invalid], nil)
- return Typ[Invalid]
+ if u != Typ[Invalid] {
+ check.errorf(x, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
+ u = Typ[Invalid]
+ }
+ } else {
+ terms = append(terms, term)
+ u = &Union{terms}
}
- terms = append(terms, NewTerm(tilde, typ))
+
+ if i > 0 {
+ check.recordTypeAndValue(blist[i-1], typexpr, u, nil)
+ }
+ }
+
+ if u == Typ[Invalid] {
+ return u
}
// Check validity of terms.
@@ -87,16 +100,27 @@
if !Identical(u, t.typ) {
check.errorf(tlist[i], "invalid use of ~ (underlying type of %s is %s)", t.typ, u)
- continue // don't report another error for t
+ continue
}
}
// Stand-alone embedded interfaces are ok and are handled by the single-type case
// in the beginning. Embedded interfaces with tilde are excluded above. If we reach
- // here, we must have at least two terms in the union.
- if f != nil && !f.typeSet().IsTypeSet() {
- check.errorf(tlist[i], "cannot use %s in union (interface contains methods)", t)
- continue // don't report another error for t
+ // here, we must have at least two terms in the syntactic term list (but not necessarily
+ // in the term list of the union's type set).
+ if f != nil {
+ tset := f.typeSet()
+ switch {
+ case tset.NumMethods() != 0:
+ check.errorf(tlist[i], "cannot use %s in union (%s contains methods)", t, t)
+ continue
+ case t.typ == universeComparable.Type():
+ check.error(tlist[i], "cannot use comparable in union")
+ continue
+ case tset.comparable:
+ check.errorf(tlist[i], "cannot use %s in union (%s embeds comparable)", t, t)
+ continue
+ }
}
// Report overlapping (non-disjoint) terms such as
@@ -107,17 +131,17 @@
}
})
- u := &Union{terms, nil}
- check.recordTypeAndValue(uexpr, typexpr, u, nil)
return u
}
-func parseTilde(check *Checker, x syntax.Expr) (tilde bool, typ Type) {
+func parseTilde(check *Checker, tx syntax.Expr) *Term {
+ x := tx
+ var tilde bool
if op, _ := x.(*syntax.Operation); op != nil && op.Op == syntax.Tilde {
x = op.X
tilde = true
}
- typ = check.typ(x)
+ typ := check.typ(x)
// Embedding stand-alone type parameters is not permitted (issue #47127).
// We don't need this restriction anymore if we make the underlying type of a type
// parameter its constraint interface: if we embed a lone type parameter, we will
@@ -127,7 +151,11 @@
check.error(x, "cannot embed a type parameter")
typ = Typ[Invalid]
}
- return
+ term := NewTerm(tilde, typ)
+ if tilde {
+ check.recordTypeAndValue(tx, typexpr, &Union{[]*Term{term}}, nil)
+ }
+ return term
}
// overlappingTerm reports the index of the term x in terms which is
@@ -148,10 +176,13 @@
return -1
}
-func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr {
+// flattenUnion walks a union type expression of the form A | B | C | ...,
+// extracting both the binary exprs (blist) and leaf types (tlist).
+func flattenUnion(list []syntax.Expr, x syntax.Expr) (blist, tlist []syntax.Expr) {
if o, _ := x.(*syntax.Operation); o != nil && o.Op == syntax.Or {
- list = flattenUnion(list, o.X)
+ blist, tlist = flattenUnion(list, o.X)
+ blist = append(blist, o)
x = o.Y
}
- return append(list, x)
+ return blist, append(tlist, x)
}
diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go
index c16ae3f..11c8186 100644
--- a/src/cmd/compile/internal/types2/universe.go
+++ b/src/cmd/compile/internal/types2/universe.go
@@ -88,22 +88,32 @@
{
obj := NewTypeName(nopos, nil, "error", nil)
obj.setColor(black)
+ typ := NewNamed(obj, nil, nil)
+
+ // error.Error() string
+ recv := NewVar(nopos, nil, "", typ)
res := NewVar(nopos, nil, "", Typ[String])
- sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false)
+ sig := NewSignatureType(recv, nil, nil, nil, NewTuple(res), false)
err := NewFunc(nopos, nil, "Error", sig)
- ityp := &Interface{nil, obj, []*Func{err}, nil, nil, false, true, nil}
+
+ // interface{ Error() string }
+ ityp := &Interface{obj: obj, methods: []*Func{err}, complete: true}
computeInterfaceTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset
- typ := NewNamed(obj, ityp, nil)
- sig.recv = NewVar(nopos, nil, "", typ)
+
+ typ.SetUnderlying(ityp)
def(obj)
}
- // type comparable interface{ /* type set marked comparable */ }
+ // type comparable interface{} // marked as comparable
{
obj := NewTypeName(nopos, nil, "comparable", nil)
obj.setColor(black)
- ityp := &Interface{nil, obj, nil, nil, nil, false, true, &_TypeSet{true, nil, allTermlist}}
- NewNamed(obj, ityp, nil)
+ typ := NewNamed(obj, nil, nil)
+
+ // interface{} // marked as comparable
+ ityp := &Interface{obj: obj, complete: true, tset: &_TypeSet{nil, allTermlist, true}}
+
+ typ.SetUnderlying(ityp)
def(obj)
}
}
diff --git a/src/cmd/compile/internal/types2/validtype.go b/src/cmd/compile/internal/types2/validtype.go
new file mode 100644
index 0000000..f365ad1
--- /dev/null
+++ b/src/cmd/compile/internal/types2/validtype.go
@@ -0,0 +1,147 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types2
+
+// validType verifies that the given type does not "expand" indefinitely
+// producing a cycle in the type graph. Cycles are detected by marking
+// defined types.
+// (Cycles involving alias types, as in "type A = [10]A" are detected
+// earlier, via the objDecl cycle detection mechanism.)
+func (check *Checker) validType(typ *Named) {
+ check.validType0(typ, nil, nil)
+}
+
+type typeInfo uint
+
+// validType0 checks if the given type is valid. If typ is a type parameter
+// its value is looked up in the provided environment. The environment is
+// nil if typ is not part of (the RHS of) an instantiated type, in that case
+// any type parameter encountered must be from an enclosing function and can
+// be ignored. The path is the list of type names that lead to the current typ.
+func (check *Checker) validType0(typ Type, env *tparamEnv, path []Object) typeInfo {
+ const (
+ unknown typeInfo = iota
+ marked
+ valid
+ invalid
+ )
+
+ switch t := typ.(type) {
+ case nil:
+ // We should never see a nil type but be conservative and panic
+ // only in debug mode.
+ if debug {
+ panic("validType0(nil)")
+ }
+
+ case *Array:
+ return check.validType0(t.elem, env, path)
+
+ case *Struct:
+ for _, f := range t.fields {
+ if check.validType0(f.typ, env, path) == invalid {
+ return invalid
+ }
+ }
+
+ case *Union:
+ for _, t := range t.terms {
+ if check.validType0(t.typ, env, path) == invalid {
+ return invalid
+ }
+ }
+
+ case *Interface:
+ for _, etyp := range t.embeddeds {
+ if check.validType0(etyp, env, path) == invalid {
+ return invalid
+ }
+ }
+
+ case *Named:
+ // Don't report a 2nd error if we already know the type is invalid
+ // (e.g., if a cycle was detected earlier, via under).
+ if t.underlying == Typ[Invalid] {
+ check.infoMap[t] = invalid
+ return invalid
+ }
+
+ switch check.infoMap[t] {
+ case unknown:
+ check.infoMap[t] = marked
+ check.infoMap[t] = check.validType0(t.orig.fromRHS, env.push(t), append(path, t.obj))
+ case marked:
+ // We have seen type t before and thus must have a cycle.
+ check.infoMap[t] = invalid
+ // t cannot be in an imported package otherwise that package
+ // would have reported a type cycle and couldn't have been
+ // imported in the first place.
+ assert(t.obj.pkg == check.pkg)
+ t.underlying = Typ[Invalid] // t is in the current package (no race possibility)
+ // Find the starting point of the cycle and report it.
+ for i, tn := range path {
+ if tn == t.obj {
+ check.cycleError(path[i:])
+ return invalid
+ }
+ }
+ panic("cycle start not found")
+ }
+ return check.infoMap[t]
+
+ case *TypeParam:
+ // A type parameter stands for the type (argument) it was instantiated with.
+ // Check the corresponding type argument for validity if we have one.
+ if env != nil {
+ if targ := env.tmap[t]; targ != nil {
+ // Type arguments found in targ must be looked
+ // up in the enclosing environment env.link.
+ return check.validType0(targ, env.link, path)
+ }
+ }
+ }
+
+ return valid
+}
+
+// A tparamEnv provides the environment for looking up the type arguments
+// with which type parameters for a given instance were instantiated.
+// If we don't have an instance, the corresponding tparamEnv is nil.
+type tparamEnv struct {
+ tmap substMap
+ link *tparamEnv
+}
+
+func (env *tparamEnv) push(typ *Named) *tparamEnv {
+ // If typ is not an instantiated type there are no typ-specific
+ // type parameters to look up and we don't need an environment.
+ targs := typ.TypeArgs()
+ if targs == nil {
+ return nil // no instance => nil environment
+ }
+
+ // Populate tmap: remember the type argument for each type parameter.
+ // We cannot use makeSubstMap because the number of type parameters
+ // and arguments may not match due to errors in the source (too many
+ // or too few type arguments). Populate tmap "manually".
+ tparams := typ.TypeParams()
+ n, m := targs.Len(), tparams.Len()
+ if n > m {
+ n = m // too many targs
+ }
+ tmap := make(substMap, n)
+ for i := 0; i < n; i++ {
+ tmap[tparams.At(i)] = targs.At(i)
+ }
+
+ return &tparamEnv{tmap: tmap, link: env}
+}
+
+// TODO(gri) Alternative implementation:
+// We may not need to build a stack of environments to
+// look up the type arguments for type parameters. The
+// same information should be available via the path:
+// We should be able to just walk the path backwards
+// and find the type arguments in the instance objects.
diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go
index 4d1c562..cd922c9 100644
--- a/src/cmd/compile/internal/walk/closure.go
+++ b/src/cmd/compile/internal/walk/closure.go
@@ -235,15 +235,7 @@
saveLineNo := base.Pos
ir.CurFunc = nil
- // Set line number equal to the line number where the method is declared.
- if pos := dot.Selection.Pos; pos.IsKnown() {
- base.Pos = pos
- }
- // Note: !dot.Selection.Pos.IsKnown() happens for method expressions where
- // the method is implicitly declared. The Error method of the
- // built-in error type is one such method. We leave the line
- // number at the use of the method expression in this
- // case. See issue 29389.
+ base.Pos = base.AutogeneratedPos
tfn := ir.NewFuncType(base.Pos, nil,
typecheck.NewFuncParams(t0.Params(), true),
diff --git a/src/cmd/dist/main.go b/src/cmd/dist/main.go
index 37de1ac..212d5cb 100644
--- a/src/cmd/dist/main.go
+++ b/src/cmd/dist/main.go
@@ -94,7 +94,15 @@
if gohostarch == "" {
// Default Unix system.
out := run("", CheckExit, "uname", "-m")
+ outAll := run("", CheckExit, "uname", "-a")
switch {
+ case strings.Contains(outAll, "RELEASE_ARM64"):
+ // MacOS prints
+ // Darwin p1.local 21.1.0 Darwin Kernel Version 21.1.0: Wed Oct 13 17:33:01 PDT 2021; root:xnu-8019.41.5~1/RELEASE_ARM64_T6000 x86_64
+ // on ARM64 laptops when there is an x86 parent in the
+ // process tree. Look for the RELEASE_ARM64 to avoid being
+ // confused into building an x86 toolchain.
+ gohostarch = "arm64"
case strings.Contains(out, "x86_64"), strings.Contains(out, "amd64"):
gohostarch = "amd64"
case strings.Contains(out, "86"):
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index 50a2e59..d9eb9c3 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -1117,9 +1117,9 @@
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=auto")
- // Skip internal linking cases on linux/arm64 to support GCC-9.4 and above.
+ // Skip internal linking cases on arm64 to support GCC-9.4 and above.
// See issue #39466.
- skipInternalLink := goarch == "arm64" && goos == "linux"
+ skipInternalLink := goarch == "arm64" && goos != "darwin"
if t.internalLink() && !skipInternalLink {
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal")
diff --git a/src/cmd/doc/doc_test.go b/src/cmd/doc/doc_test.go
index af77931..0ff9edc 100644
--- a/src/cmd/doc/doc_test.go
+++ b/src/cmd/doc/doc_test.go
@@ -7,6 +7,7 @@
import (
"bytes"
"flag"
+ "log"
"os"
"path/filepath"
"regexp"
@@ -125,6 +126,9 @@
`func MultiLineFunc\(x interface{ ... }\) \(r struct{ ... }\)`, // Multi line function.
`var LongLine = newLongLine\(("someArgument[1-4]", ){4}...\)`, // Long list of arguments.
`type T1 = T2`, // Type alias
+ `type SimpleConstraint interface{ ... }`,
+ `type TildeConstraint interface{ ... }`,
+ `type StructConstraint interface{ ... }`,
},
[]string{
`const internalConstant = 2`, // No internal constants.
@@ -199,6 +203,9 @@
`Comment about exported method`,
`type T1 = T2`,
`type T2 int`,
+ `type SimpleConstraint interface {`,
+ `type TildeConstraint interface {`,
+ `type StructConstraint interface {`,
},
[]string{
`constThree`,
@@ -822,13 +829,19 @@
func TestDoc(t *testing.T) {
maybeSkip(t)
+ defer log.SetOutput(log.Writer())
for _, test := range tests {
var b bytes.Buffer
var flagSet flag.FlagSet
+ var logbuf bytes.Buffer
+ log.SetOutput(&logbuf)
err := do(&b, &flagSet, test.args)
if err != nil {
t.Fatalf("%s %v: %s\n", test.name, test.args, err)
}
+ if logbuf.Len() > 0 {
+ t.Errorf("%s %v: unexpected log messages:\n%s", test.name, test.args, logbuf.Bytes())
+ }
output := b.Bytes()
failed := false
for j, yes := range test.yes {
diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go
index f51efe0..0266600 100644
--- a/src/cmd/doc/pkg.go
+++ b/src/cmd/doc/pkg.go
@@ -865,6 +865,7 @@
if len(names) == 0 {
// Embedded type. Use the name of the type. It must be of the form ident or
// pkg.ident (for structs and interfaces), or *ident or *pkg.ident (structs only).
+ // Or a type embedded in a constraint.
// Nothing else is allowed.
ty := field.Type
if se, ok := field.Type.(*ast.StarExpr); !isInterface && ok {
@@ -872,6 +873,7 @@
// embedded types in structs.
ty = se.X
}
+ constraint := false
switch ident := ty.(type) {
case *ast.Ident:
if isInterface && ident.Name == "error" && ident.Obj == nil {
@@ -885,8 +887,12 @@
case *ast.SelectorExpr:
// An embedded type may refer to a type in another package.
names = []*ast.Ident{ident.Sel}
+ default:
+ // An approximation or union or type
+ // literal in an interface.
+ constraint = true
}
- if names == nil {
+ if names == nil && !constraint {
// Can only happen if AST is incorrect. Safe to continue with a nil list.
log.Print("invalid program: unexpected type for embedded field")
}
diff --git a/src/cmd/doc/testdata/pkg.go b/src/cmd/doc/testdata/pkg.go
index 5ece832..a693c74 100644
--- a/src/cmd/doc/testdata/pkg.go
+++ b/src/cmd/doc/testdata/pkg.go
@@ -238,3 +238,15 @@
// Text after pre-formatted block.
ExportedField int
}
+
+type SimpleConstraint interface {
+ ~int | ~float64
+}
+
+type TildeConstraint interface {
+ ~int
+}
+
+type StructConstraint interface {
+ struct { F int }
+}
diff --git a/src/cmd/go.mod b/src/cmd/go.mod
index f46c770..48fc888 100644
--- a/src/cmd/go.mod
+++ b/src/cmd/go.mod
@@ -8,12 +8,12 @@
golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
- golang.org/x/tools v0.1.9-0.20211207220608-fd2bfb79a16a
+ golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646
)
require (
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d // indirect
- golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect
+ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
diff --git a/src/cmd/go.sum b/src/cmd/go.sum
index 941011f..4a5479f 100644
--- a/src/cmd/go.sum
+++ b/src/cmd/go.sum
@@ -7,8 +7,8 @@
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020 h1:HjtpZuJcnSa+yHlL4Y5aypjDvbHkJne5FS8JRmKI2+I=
golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
@@ -18,7 +18,7 @@
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/tools v0.1.9-0.20211207220608-fd2bfb79a16a h1:G+TZ7v63o8mn+LBWOdnHaiypIhcgFZ6BDDnyX+RXDYg=
-golang.org/x/tools v0.1.9-0.20211207220608-fd2bfb79a16a/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
+golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646 h1:f8aekWvlQQ8ZhD8SL7lOu18dtWslZYl029PN2F0VnS4=
+golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 6703792..420529b 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -135,11 +135,6 @@
//
// -asmflags '[pattern=]arg list'
// arguments to pass on each go tool asm invocation.
-// -buildinfo
-// Whether to stamp binaries with build flags. By default, the compiler name
-// (gc or gccgo), toolchain flags (like -gcflags), and environment variables
-// containing flags (like CGO_CFLAGS) are stamped into binaries. Use
-// -buildinfo=false to omit build information. See also -buildvcs.
// -buildmode mode
// build mode to use. See 'go help buildmode' for more.
// -buildvcs
@@ -147,7 +142,7 @@
// version control information is stamped into a binary if the main package
// and the main module containing it are in the repository containing the
// current directory (if there is a repository). Use -buildvcs=false to
-// omit version control information. See also -buildinfo.
+// omit version control information.
// -compiler name
// name of compiler to use, as in runtime.Compiler (gccgo or gc).
// -gccgoflags '[pattern=]arg list'
@@ -182,14 +177,6 @@
// directory, but it is not accessed. When -modfile is specified, an
// alternate go.sum file is also used: its path is derived from the
// -modfile flag by trimming the ".mod" extension and appending ".sum".
-// -workfile file
-// in module aware mode, use the given go.work file as a workspace file.
-// By default or when -workfile is "auto", the go command searches for a
-// file named go.work in the current directory and then containing directories
-// until one is found. If a valid go.work file is found, the modules
-// specified will collectively be used as the main modules. If -workfile
-// is "off", or a go.work file is not found in "auto" mode, workspace
-// mode is disabled.
// -overlay file
// read a JSON config file that provides an overlay for build operations.
// The file is a JSON struct with a single field, named 'Replace', that
@@ -214,9 +201,8 @@
// -trimpath
// remove all file system paths from the resulting executable.
// Instead of absolute file system paths, the recorded file names
-// will begin with either "go" (for the standard library),
-// or a module path@version (when using modules),
-// or a plain import path (when using GOPATH).
+// will begin either a module path@version (when using modules),
+// or a plain import path (when using the standard library, or GOPATH).
// -toolexec 'cmd args'
// a program to use to invoke toolchain programs like vet and asm.
// For example, instead of running asm, the go command will run
@@ -1370,23 +1356,61 @@
//
// Workspace maintenance
//
-// Go workspace provides access to operations on workspaces.
+// Work provides access to operations on workspaces.
//
-// Note that support for workspaces is built into many other commands,
-// not just 'go work'.
+// Note that support for workspaces is built into many other commands, not
+// just 'go work'.
//
-// See 'go help modules' for information about Go's module system of
-// which workspaces are a part.
+// See 'go help modules' for information about Go's module system of which
+// workspaces are a part.
+//
+// See https://go.dev/ref/mod#workspaces for an in-depth reference on
+// workspaces.
+//
+// See https://go.dev/doc/tutorial/workspaces for an introductory
+// tutorial on workspaces.
//
// A workspace is specified by a go.work file that specifies a set of
-// module directories with the "use" directive. These modules are used
-// as root modules by the go command for builds and related operations.
-// A workspace that does not specify modules to be used cannot be used
-// to do builds from local modules.
+// module directories with the "use" directive. These modules are used as
+// root modules by the go command for builds and related operations. A
+// workspace that does not specify modules to be used cannot be used to do
+// builds from local modules.
//
-// To determine whether the go command is operating in workspace mode,
-// use the "go env GOWORK" command. This will specify the workspace
-// file being used.
+// go.work files are line-oriented. Each line holds a single directive,
+// made up of a keyword followed by arguments. For example:
+//
+// go 1.18
+//
+// use ../foo/bar
+// use ./baz
+//
+// replace example.com/foo v1.2.3 => example.com/bar v1.4.5
+//
+// The leading keyword can be factored out of adjacent lines to create a block,
+// like in Go imports.
+//
+// use (
+// ../foo/bar
+// ./baz
+// )
+//
+// The use directive specifies a module to be included in the workspace's
+// set of main modules. The argument to the use directive is the directory
+// containing the module's go.mod file.
+//
+// The go directive specifies the version of Go the file was written at. It
+// is possible there may be future changes in the semantics of workspaces
+// that could be controlled by this version, but for now the version
+// specified has no effect.
+//
+// The replace directive has the same syntax as the replace directive in a
+// go.mod file and takes precedence over replaces in go.mod files. It is
+// primarily intended to override conflicting replaces in different workspace
+// modules.
+//
+// To determine whether the go command is operating in workspace mode, use
+// the "go env GOWORK" command. This will specify the workspace file being
+// used.
//
// Usage:
//
@@ -1446,19 +1470,14 @@
// The -json flag prints the final go.work file in JSON format instead of
// writing it back to go.mod. The JSON output corresponds to these Go types:
//
-// type Module struct {
-// Path string
-// Version string
-// }
-//
// type GoWork struct {
-// Go string
-// Directory []Directory
-// Replace []Replace
+// Go string
+// Use []Use
+// Replace []Replace
// }
//
// type Use struct {
-// Path string
+// DiskPath string
// ModulePath string
// }
//
@@ -1467,9 +1486,13 @@
// New Module
// }
//
-// See the workspaces design proposal at
-// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for
-// more information.
+// type Module struct {
+// Path string
+// Version string
+// }
+//
+// See the workspaces reference at https://go.dev/ref/mod#workspaces
+// for more information.
//
//
// Initialize workspace file
@@ -1478,36 +1501,67 @@
//
// go work init [moddirs]
//
-// Init initializes and writes a new go.work file in the current
-// directory, in effect creating a new workspace at the current directory.
+// Init initializes and writes a new go.work file in the
+// current directory, in effect creating a new workspace at the current
+// directory.
//
-// go work init optionally accepts paths to the workspace modules as arguments.
-// If the argument is omitted, an empty workspace with no modules will be created.
+// go work init optionally accepts paths to the workspace modules as
+// arguments. If the argument is omitted, an empty workspace with no
+// modules will be created.
//
-// See the workspaces design proposal at
-// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for
-// more information.
+// Each argument path is added to a use directive in the go.work file. The
+// current go version will also be listed in the go.work file.
+//
+// See the workspaces reference at https://go.dev/ref/mod#workspaces
+// for more information.
//
//
// Sync workspace build list to modules
//
// Usage:
//
-// go work sync [moddirs]
+// go work sync
//
-// go work sync
+// Sync syncs the workspace's build list back to the
+// workspace's modules
+//
+// The workspace's build list is the set of versions of all the
+// (transitive) dependency modules used to do builds in the workspace. go
+// work sync generates that build list using the Minimal Version Selection
+// algorithm, and then syncs those versions back to each of modules
+// specified in the workspace (with use directives).
+//
+// The syncing is done by sequentially upgrading each of the dependency
+// modules specified in a workspace module to the version in the build list
+// if the dependency module's version is not already the same as the build
+// list's version. Note that Minimal Version Selection guarantees that the
+// build list's version of each module is always the same or higher than
+// that in each workspace module.
+//
+// See the workspaces reference at https://go.dev/ref/mod#workspaces
+// for more information.
//
//
// Add modules to workspace file
//
// Usage:
//
-// go work use [-r] [moddirs]
+// go work use [-r] moddirs
//
-// Use provides a command-line interface for adding directories,
-// optionally recursively, to a go.work file.
+// Use provides a command-line interface for adding
+// directories, optionally recursively, to a go.work file.
//
-// The -r flag searches recursively for modules in the argument directories.
+// A use directive will be added to the go.work file for each argument
+// directory listed on the command line go.work file, if it exists on disk,
+// or removed from the go.work file if it does not exist on disk.
+//
+// The -r flag searches recursively for modules in the argument
+// directories, and the use command operates as if each of the directories
+// were specified as arguments: namely, use directives will be added for
+// directories that exist, and removed for directories that do not exist.
+//
+// See the workspaces reference at https://go.dev/ref/mod#workspaces
+// for more information.
//
//
// Compile and run Go program
@@ -1988,6 +2042,8 @@
// GOENV
// The location of the Go environment configuration file.
// Cannot be set using 'go env -w'.
+// Setting GOENV=off in the environment disables the use of the
+// default configuration file.
// GOFLAGS
// A space-separated list of -flag=value settings to apply
// to go commands by default, when the given flag is known by
@@ -2025,6 +2081,14 @@
// GOVCS
// Lists version control commands that may be used with matching servers.
// See 'go help vcs'.
+// GOWORK
+// In module aware mode, use the given go.work file as a workspace file.
+// By default or when GOWORK is "auto", the go command searches for a
+// file named go.work in the current directory and then containing directories
+// until one is found. If a valid go.work file is found, the modules
+// specified will collectively be used as the main modules. If GOWORK
+// is "off", or a go.work file is not found in "auto" mode, workspace
+// mode is disabled.
//
// Environment variables for use with cgo:
//
@@ -2077,7 +2141,7 @@
// GOAMD64
// For GOARCH=amd64, the microarchitecture level for which to compile.
// Valid values are v1 (default), v2, v3, v4.
-// See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels.
+// See https://golang.org/wiki/MinimumRequirements#amd64
// GOMIPS
// For GOARCH=mips{,le}, whether to use floating point instructions.
// Valid values are hardfloat (default), softfloat.
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 170c882..1ea347c 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -133,7 +133,7 @@
}
gotool, err := testenv.GoTool()
if err != nil {
- fmt.Fprintln(os.Stderr, err)
+ fmt.Fprintln(os.Stderr, "locating go tool: ", err)
os.Exit(2)
}
@@ -1387,7 +1387,7 @@
for buf.Len() < sys.ExecArgLengthLimit+1 {
buf.WriteString(testStr)
}
- tg.run("run", "-buildinfo=false", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
+ tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
if tg.stderr.String() != buf.String() {
t.Errorf("strings differ")
}
diff --git a/src/cmd/go/internal/base/flag.go b/src/cmd/go/internal/base/flag.go
index 2c72c7e..120420a 100644
--- a/src/cmd/go/internal/base/flag.go
+++ b/src/cmd/go/internal/base/flag.go
@@ -62,13 +62,6 @@
flags.Var(explicitStringFlag{value: &cfg.BuildMod, explicit: &cfg.BuildModExplicit}, "mod", "")
}
-// AddWorkfileFlag adds the workfile flag to the flag set. It enables workspace
-// mode for commands that support it by resetting the cfg.WorkFile variable
-// to "" (equivalent to auto) rather than off.
-func AddWorkfileFlag(flags *flag.FlagSet) {
- flags.Var(explicitStringFlag{value: &cfg.WorkFile, explicit: &cfg.WorkFileExplicit}, "workfile", "")
-}
-
// AddModCommonFlags adds the module-related flags common to build commands
// and 'go mod' subcommands.
func AddModCommonFlags(flags *flag.FlagSet) {
diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go
index 5b84d8b..deab3dd 100644
--- a/src/cmd/go/internal/cfg/cfg.go
+++ b/src/cmd/go/internal/cfg/cfg.go
@@ -25,7 +25,6 @@
// These are general "build flags" used by build and other commands.
var (
BuildA bool // -a flag
- BuildBuildinfo bool // -buildinfo flag
BuildBuildmode string // -buildmode flag
BuildBuildvcs bool // -buildvcs flag
BuildContext = defaultContext()
@@ -50,10 +49,8 @@
BuildWork bool // -work flag
BuildX bool // -x flag
- ModCacheRW bool // -modcacherw flag
- ModFile string // -modfile flag
- WorkFile string // -workfile flag
- WorkFileExplicit bool // whether -workfile was set explicitly
+ ModCacheRW bool // -modcacherw flag
+ ModFile string // -modfile flag
CmdName string // "build", "install", "list", "mod tidy", etc.
diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go
index e56dd82..c1adf8c 100644
--- a/src/cmd/go/internal/envcmd/env.go
+++ b/src/cmd/go/internal/envcmd/env.go
@@ -154,6 +154,10 @@
}
modload.InitWorkfile()
gowork := modload.WorkFilePath()
+ // As a special case, if a user set off explicitly, report that in GOWORK.
+ if cfg.Getenv("GOWORK") == "off" {
+ gowork = "off"
+ }
return []cfg.EnvVar{
{Name: "GOMOD", Value: gomod},
{Name: "GOWORK", Value: gowork},
diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go
index 035235f..28ddaac 100644
--- a/src/cmd/go/internal/help/helpdoc.go
+++ b/src/cmd/go/internal/help/helpdoc.go
@@ -506,6 +506,8 @@
GOENV
The location of the Go environment configuration file.
Cannot be set using 'go env -w'.
+ Setting GOENV=off in the environment disables the use of the
+ default configuration file.
GOFLAGS
A space-separated list of -flag=value settings to apply
to go commands by default, when the given flag is known by
@@ -543,6 +545,14 @@
GOVCS
Lists version control commands that may be used with matching servers.
See 'go help vcs'.
+ GOWORK
+ In module aware mode, use the given go.work file as a workspace file.
+ By default or when GOWORK is "auto", the go command searches for a
+ file named go.work in the current directory and then containing directories
+ until one is found. If a valid go.work file is found, the modules
+ specified will collectively be used as the main modules. If GOWORK
+ is "off", or a go.work file is not found in "auto" mode, workspace
+ mode is disabled.
Environment variables for use with cgo:
@@ -595,7 +605,7 @@
GOAMD64
For GOARCH=amd64, the microarchitecture level for which to compile.
Valid values are v1 (default), v2, v3, v4.
- See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels.
+ See https://golang.org/wiki/MinimumRequirements#amd64
GOMIPS
For GOARCH=mips{,le}, whether to use floating point instructions.
Valid values are hardfloat (default), softfloat.
diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go
index d9a7078..8be9211 100644
--- a/src/cmd/go/internal/list/list.go
+++ b/src/cmd/go/internal/list/list.go
@@ -316,7 +316,6 @@
func init() {
CmdList.Run = runList // break init cycle
work.AddBuildFlags(CmdList, work.DefaultBuildFlags)
- base.AddWorkfileFlag(&CmdList.Flag)
}
var (
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index a891d60..d68f43a 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -819,11 +819,11 @@
}
r := resolvedImportCache.Do(importKey, func() any {
var r resolvedImport
- if build.IsLocalImport(path) {
+ if cfg.ModulesEnabled {
+ r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
+ } else if build.IsLocalImport(path) {
r.dir = filepath.Join(parentDir, path)
r.path = dirToImportPath(r.dir)
- } else if cfg.ModulesEnabled {
- r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
} else if mode&ResolveImport != 0 {
// We do our own path resolution, because we want to
// find out the key to use in packageCache without the
@@ -1113,6 +1113,7 @@
}
if !str.HasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || path != "command-line-arguments" && !build.IsLocalImport(path) && filepath.Join(root, path) != dir {
+ debug.PrintStack()
base.Fatalf("unexpected directory layout:\n"+
" import path: %s\n"+
" root: %s\n"+
@@ -2229,13 +2230,17 @@
var debugModFromModinfo func(*modinfo.ModulePublic) *debug.Module
debugModFromModinfo = func(mi *modinfo.ModulePublic) *debug.Module {
+ version := mi.Version
+ if version == "" {
+ version = "(devel)"
+ }
dm := &debug.Module{
Path: mi.Path,
- Version: mi.Version,
+ Version: version,
}
if mi.Replace != nil {
dm.Replace = debugModFromModinfo(mi.Replace)
- } else {
+ } else if mi.Version != "" {
dm.Sum = modfetch.Sum(module.Version{Path: mi.Path, Version: mi.Version})
}
return dm
@@ -2292,7 +2297,7 @@
// Add command-line flags relevant to the build.
// This is informational, not an exhaustive list.
// Please keep the list sorted.
- if cfg.BuildBuildinfo && !p.Standard {
+ if !p.Standard {
if cfg.BuildASan {
appendSetting("-asan", "true")
}
@@ -2418,12 +2423,7 @@
appendSetting("vcs.modified", strconv.FormatBool(st.Uncommitted))
}
- text, err := info.MarshalText()
- if err != nil {
- setPkgErrorf("error formatting build info: %v", err)
- return
- }
- p.Internal.BuildInfo = string(text)
+ p.Internal.BuildInfo = info.String()
}
// SafeArg reports whether arg is a "safe" command-line argument,
diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go
index 6b8a010..5bc6cbc 100644
--- a/src/cmd/go/internal/modcmd/download.go
+++ b/src/cmd/go/internal/modcmd/download.go
@@ -70,7 +70,6 @@
// TODO(jayconrod): https://golang.org/issue/35849 Apply -x to other 'go mod' commands.
cmdDownload.Flag.BoolVar(&cfg.BuildX, "x", false, "")
base.AddModCommonFlags(&cmdDownload.Flag)
- base.AddWorkfileFlag(&cmdDownload.Flag)
}
type moduleJSON struct {
diff --git a/src/cmd/go/internal/modcmd/graph.go b/src/cmd/go/internal/modcmd/graph.go
index 9b6aa1f..9568c65 100644
--- a/src/cmd/go/internal/modcmd/graph.go
+++ b/src/cmd/go/internal/modcmd/graph.go
@@ -42,7 +42,6 @@
func init() {
cmdGraph.Flag.Var(&graphGo, "go", "")
base.AddModCommonFlags(&cmdGraph.Flag)
- base.AddWorkfileFlag(&cmdGraph.Flag)
}
func runGraph(ctx context.Context, cmd *base.Command, args []string) {
diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go
index 3f0c005..459bf5d 100644
--- a/src/cmd/go/internal/modcmd/verify.go
+++ b/src/cmd/go/internal/modcmd/verify.go
@@ -39,7 +39,6 @@
func init() {
base.AddModCommonFlags(&cmdVerify.Flag)
- base.AddWorkfileFlag(&cmdVerify.Flag)
}
func runVerify(ctx context.Context, cmd *base.Command, args []string) {
diff --git a/src/cmd/go/internal/modcmd/why.go b/src/cmd/go/internal/modcmd/why.go
index d8355cc..2d3f1eb 100644
--- a/src/cmd/go/internal/modcmd/why.go
+++ b/src/cmd/go/internal/modcmd/why.go
@@ -59,7 +59,6 @@
func init() {
cmdWhy.Run = runWhy // break init cycle
base.AddModCommonFlags(&cmdWhy.Flag)
- base.AddWorkfileFlag(&cmdWhy.Flag)
}
func runWhy(ctx context.Context, cmd *base.Command, args []string) {
diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go
index c682447..b0dae1c 100644
--- a/src/cmd/go/internal/modfetch/cache.go
+++ b/src/cmd/go/internal/modfetch/cache.go
@@ -642,7 +642,7 @@
// Lock listfile when writing to it to try to avoid corruption to the file.
// Under rare circumstances, for instance, if the system loses power in the
// middle of a write it is possible for corrupt data to be written. This is
- // not a problem for the go command itself, but may be an issue if the the
+ // not a problem for the go command itself, but may be an issue if the
// cache is being served by a GOPROXY HTTP server. This will be corrected
// the next time a new version of the module is fetched and the file is rewritten.
// TODO(matloob): golang.org/issue/43313 covers adding a go mod verify
diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go
index 79da010..dfaf16d 100644
--- a/src/cmd/go/internal/modfetch/coderepo.go
+++ b/src/cmd/go/internal/modfetch/coderepo.go
@@ -298,42 +298,61 @@
// If statVers is a valid module version, it is used for the Version field.
// Otherwise, the Version is derived from the passed-in info and recent tags.
func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, error) {
- info2 := &RevInfo{
- Name: info.Name,
- Short: info.Short,
- Time: info.Time,
- }
-
// If this is a plain tag (no dir/ prefix)
// and the module path is unversioned,
// and if the underlying file tree has no go.mod,
// then allow using the tag with a +incompatible suffix.
- var canUseIncompatible func() bool
- canUseIncompatible = func() bool {
- var ok bool
- if r.codeDir == "" && r.pathMajor == "" {
+ //
+ // (If the version is +incompatible, then the go.mod file must not exist:
+ // +incompatible is not an ongoing opt-out from semantic import versioning.)
+ incompatibleOk := map[string]bool{}
+ canUseIncompatible := func(v string) bool {
+ if r.codeDir != "" || r.pathMajor != "" {
+ // A non-empty codeDir indicates a module within a subdirectory,
+ // which necessarily has a go.mod file indicating the module boundary.
+ // A non-empty pathMajor indicates a module path with a major-version
+ // suffix, which must match.
+ return false
+ }
+
+ ok, seen := incompatibleOk[""]
+ if !seen {
_, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod)
- if errGoMod != nil {
- ok = true
+ ok = (errGoMod != nil)
+ incompatibleOk[""] = ok
+ }
+ if !ok {
+ // A go.mod file exists at the repo root.
+ return false
+ }
+
+ // Per https://go.dev/issue/51324, previous versions of the 'go' command
+ // didn't always check for go.mod files in subdirectories, so if the user
+ // requests a +incompatible version explicitly, we should continue to allow
+ // it. Otherwise, if vN/go.mod exists, expect that release tags for that
+ // major version are intended for the vN module.
+ if v != "" && !strings.HasSuffix(statVers, "+incompatible") {
+ major := semver.Major(v)
+ ok, seen = incompatibleOk[major]
+ if !seen {
+ _, errGoModSub := r.code.ReadFile(info.Name, path.Join(major, "go.mod"), codehost.MaxGoMod)
+ ok = (errGoModSub != nil)
+ incompatibleOk[major] = ok
+ }
+ if !ok {
+ return false
}
}
- canUseIncompatible = func() bool { return ok }
- return ok
+
+ return true
}
- invalidf := func(format string, args ...any) error {
- return &module.ModuleError{
- Path: r.modPath,
- Err: &module.InvalidVersionError{
- Version: info2.Version,
- Err: fmt.Errorf(format, args...),
- },
- }
- }
-
- // checkGoMod verifies that the go.mod file for the module exists or does not
- // exist as required by info2.Version and the module path represented by r.
- checkGoMod := func() (*RevInfo, error) {
+ // checkCanonical verifies that the canonical version v is compatible with the
+ // module path represented by r, adding a "+incompatible" suffix if needed.
+ //
+ // If statVers is also canonical, checkCanonical also verifies that v is
+ // either statVers or statVers with the added "+incompatible" suffix.
+ checkCanonical := func(v string) (*RevInfo, error) {
// If r.codeDir is non-empty, then the go.mod file must exist: the module
// author — not the module consumer, — gets to decide how to carve up the repo
// into modules.
@@ -344,73 +363,91 @@
// r.findDir verifies both of these conditions. Execute it now so that
// r.Stat will correctly return a notExistError if the go.mod location or
// declared module path doesn't match.
- _, _, _, err := r.findDir(info2.Version)
+ _, _, _, err := r.findDir(v)
if err != nil {
// TODO: It would be nice to return an error like "not a module".
// Right now we return "missing go.mod", which is a little confusing.
return nil, &module.ModuleError{
Path: r.modPath,
Err: &module.InvalidVersionError{
- Version: info2.Version,
+ Version: v,
Err: notExistError{err: err},
},
}
}
- // If the version is +incompatible, then the go.mod file must not exist:
- // +incompatible is not an ongoing opt-out from semantic import versioning.
- if strings.HasSuffix(info2.Version, "+incompatible") {
- if !canUseIncompatible() {
- if r.pathMajor != "" {
- return nil, invalidf("+incompatible suffix not allowed: module path includes a major version suffix, so major version must match")
- } else {
- return nil, invalidf("+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required")
- }
- }
-
- if err := module.CheckPathMajor(strings.TrimSuffix(info2.Version, "+incompatible"), r.pathMajor); err == nil {
- return nil, invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(info2.Version))
+ invalidf := func(format string, args ...any) error {
+ return &module.ModuleError{
+ Path: r.modPath,
+ Err: &module.InvalidVersionError{
+ Version: v,
+ Err: fmt.Errorf(format, args...),
+ },
}
}
- return info2, nil
+ // Add the +incompatible suffix if needed or requested explicitly, and
+ // verify that its presence or absence is appropriate for this version
+ // (which depends on whether it has an explicit go.mod file).
+
+ if v == strings.TrimSuffix(statVers, "+incompatible") {
+ v = statVers
+ }
+ base := strings.TrimSuffix(v, "+incompatible")
+ var errIncompatible error
+ if !module.MatchPathMajor(base, r.pathMajor) {
+ if canUseIncompatible(base) {
+ v = base + "+incompatible"
+ } else {
+ if r.pathMajor != "" {
+ errIncompatible = invalidf("module path includes a major version suffix, so major version must match")
+ } else {
+ errIncompatible = invalidf("module contains a go.mod file, so module path must match major version (%q)", path.Join(r.pathPrefix, semver.Major(v)))
+ }
+ }
+ } else if strings.HasSuffix(v, "+incompatible") {
+ errIncompatible = invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(v))
+ }
+
+ if statVers != "" && statVers == module.CanonicalVersion(statVers) {
+ // Since the caller-requested version is canonical, it would be very
+ // confusing to resolve it to anything but itself, possibly with a
+ // "+incompatible" suffix. Error out explicitly.
+ if statBase := strings.TrimSuffix(statVers, "+incompatible"); statBase != base {
+ return nil, &module.ModuleError{
+ Path: r.modPath,
+ Err: &module.InvalidVersionError{
+ Version: statVers,
+ Err: fmt.Errorf("resolves to version %v (%s is not a tag)", v, statBase),
+ },
+ }
+ }
+ }
+
+ if errIncompatible != nil {
+ return nil, errIncompatible
+ }
+
+ return &RevInfo{
+ Name: info.Name,
+ Short: info.Short,
+ Time: info.Time,
+ Version: v,
+ }, nil
}
// Determine version.
- //
- // If statVers is canonical, then the original call was repo.Stat(statVers).
- // Since the version is canonical, we must not resolve it to anything but
- // itself, possibly with a '+incompatible' annotation: we do not need to do
- // the work required to look for an arbitrary pseudo-version.
- if statVers != "" && statVers == module.CanonicalVersion(statVers) {
- info2.Version = statVers
- if module.IsPseudoVersion(info2.Version) {
- if err := r.validatePseudoVersion(info, info2.Version); err != nil {
- return nil, err
- }
- return checkGoMod()
+ if module.IsPseudoVersion(statVers) {
+ if err := r.validatePseudoVersion(info, statVers); err != nil {
+ return nil, err
}
-
- if err := module.CheckPathMajor(info2.Version, r.pathMajor); err != nil {
- if canUseIncompatible() {
- info2.Version += "+incompatible"
- return checkGoMod()
- } else {
- if vErr, ok := err.(*module.InvalidVersionError); ok {
- // We're going to describe why the version is invalid in more detail,
- // so strip out the existing “invalid version” wrapper.
- err = vErr.Err
- }
- return nil, invalidf("module contains a go.mod file, so major version must be compatible: %v", err)
- }
- }
-
- return checkGoMod()
+ return checkCanonical(statVers)
}
- // statVers is empty or non-canonical, so we need to resolve it to a canonical
- // version or pseudo-version.
+ // statVers is not a pseudo-version, so we need to either resolve it to a
+ // canonical version or verify that it is already a canonical tag
+ // (not a branch).
// Derive or verify a version from a code repo tag.
// Tag must have a prefix matching codeDir.
@@ -441,71 +478,62 @@
if v == "" || !strings.HasPrefix(trimmed, v) {
return "", false // Invalid or incomplete version (just vX or vX.Y).
}
- if isRetracted(v) {
- return "", false
- }
if v == trimmed {
tagIsCanonical = true
}
-
- if err := module.CheckPathMajor(v, r.pathMajor); err != nil {
- if canUseIncompatible() {
- return v + "+incompatible", tagIsCanonical
- }
- return "", false
- }
-
return v, tagIsCanonical
}
// If the VCS gave us a valid version, use that.
if v, tagIsCanonical := tagToVersion(info.Version); tagIsCanonical {
- info2.Version = v
- return checkGoMod()
+ if info, err := checkCanonical(v); err == nil {
+ return info, err
+ }
}
// Look through the tags on the revision for either a usable canonical version
// or an appropriate base for a pseudo-version.
- var pseudoBase string
+ var (
+ highestCanonical string
+ pseudoBase string
+ )
for _, pathTag := range info.Tags {
v, tagIsCanonical := tagToVersion(pathTag)
- if tagIsCanonical {
- if statVers != "" && semver.Compare(v, statVers) == 0 {
- // The user requested a non-canonical version, but the tag for the
- // canonical equivalent refers to the same revision. Use it.
- info2.Version = v
- return checkGoMod()
+ if statVers != "" && semver.Compare(v, statVers) == 0 {
+ // The tag is equivalent to the version requested by the user.
+ if tagIsCanonical {
+ // This tag is the canonical form of the requested version,
+ // not some other form with extra build metadata.
+ // Use this tag so that the resolved version will match exactly.
+ // (If it isn't actually allowed, we'll error out in checkCanonical.)
+ return checkCanonical(v)
} else {
- // Save the highest canonical tag for the revision. If we don't find a
- // better match, we'll use it as the canonical version.
+ // The user explicitly requested something equivalent to this tag. We
+ // can't use the version from the tag directly: since the tag is not
+ // canonical, it could be ambiguous. For example, tags v0.0.1+a and
+ // v0.0.1+b might both exist and refer to different revisions.
//
- // NOTE: Do not replace this with semver.Max. Despite the name,
- // semver.Max *also* canonicalizes its arguments, which uses
- // semver.Canonical instead of module.CanonicalVersion and thereby
- // strips our "+incompatible" suffix.
- if semver.Compare(info2.Version, v) < 0 {
- info2.Version = v
- }
+ // The tag is otherwise valid for the module, so we can at least use it as
+ // the base of an unambiguous pseudo-version.
+ //
+ // If multiple tags match, tagToVersion will canonicalize them to the same
+ // base version.
+ pseudoBase = v
}
- } else if v != "" && semver.Compare(v, statVers) == 0 {
- // The user explicitly requested something equivalent to this tag. We
- // can't use the version from the tag directly: since the tag is not
- // canonical, it could be ambiguous. For example, tags v0.0.1+a and
- // v0.0.1+b might both exist and refer to different revisions.
- //
- // The tag is otherwise valid for the module, so we can at least use it as
- // the base of an unambiguous pseudo-version.
- //
- // If multiple tags match, tagToVersion will canonicalize them to the same
- // base version.
- pseudoBase = v
+ }
+ // Save the highest non-retracted canonical tag for the revision.
+ // If we don't find a better match, we'll use it as the canonical version.
+ if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) {
+ if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible(v) {
+ highestCanonical = v
+ }
}
}
- // If we found any canonical tag for the revision, return it.
+ // If we found a valid canonical tag for the revision, return it.
// Even if we found a good pseudo-version base, a canonical version is better.
- if info2.Version != "" {
- return checkGoMod()
+ if highestCanonical != "" {
+ return checkCanonical(highestCanonical)
}
// Find the highest tagged version in the revision's history, subject to
@@ -514,12 +542,12 @@
// retracted versions.
allowedMajor := func(major string) func(v string) bool {
return func(v string) bool {
- return (major == "" || semver.Major(v) == major) && !isRetracted(v)
+ return ((major == "" && canUseIncompatible(v)) || semver.Major(v) == major) && !isRetracted(v)
}
}
if pseudoBase == "" {
var tag string
- if r.pseudoMajor != "" || canUseIncompatible() {
+ if r.pseudoMajor != "" || canUseIncompatible("") {
tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor(r.pseudoMajor))
} else {
// Allow either v1 or v0, but not incompatible higher versions.
@@ -528,11 +556,10 @@
tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor("v0"))
}
}
- pseudoBase, _ = tagToVersion(tag) // empty if the tag is invalid
+ pseudoBase, _ = tagToVersion(tag)
}
- info2.Version = module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short)
- return checkGoMod()
+ return checkCanonical(module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short))
}
// validatePseudoVersion checks that version has a major version compatible with
@@ -556,10 +583,6 @@
}
}()
- if err := module.CheckPathMajor(version, r.pathMajor); err != nil {
- return err
- }
-
rev, err := module.PseudoVersionRev(version)
if err != nil {
return err
diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go
index 02e399f..bb9268a 100644
--- a/src/cmd/go/internal/modfetch/coderepo_test.go
+++ b/src/cmd/go/internal/modfetch/coderepo_test.go
@@ -418,171 +418,252 @@
zipSum: "h1:JItBZ+gwA5WvtZEGEbuDL4lUttGtLrs53lmdurq3bOg=",
zipFileHash: "9ea9ae1673cffcc44b7fdd3cc89953d68c102449b46c982dbf085e4f2e394da5",
},
+ {
+ // Git branch with a semver name, +incompatible version, and no go.mod file.
+ vcs: "git",
+ path: "vcs-test.golang.org/go/mod/gitrepo1",
+ rev: "v2.3.4+incompatible",
+ err: `resolves to version v2.0.1+incompatible (v2.3.4 is not a tag)`,
+ },
+ {
+ // Git branch with a semver name, matching go.mod file, and compatible version.
+ vcs: "git",
+ path: "vcs-test.golang.org/git/semver-branch.git",
+ rev: "v1.0.0",
+ err: `resolves to version v0.1.1-0.20220202191944-09c4d8f6938c (v1.0.0 is not a tag)`,
+ },
+ {
+ // Git branch with a semver name, matching go.mod file, and disallowed +incompatible version.
+ // The version/tag mismatch takes precedence over the +incompatible mismatched.
+ vcs: "git",
+ path: "vcs-test.golang.org/git/semver-branch.git",
+ rev: "v2.0.0+incompatible",
+ err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`,
+ },
+ {
+ // Git branch with a semver name, matching go.mod file, and mismatched version.
+ // The version/tag mismatch takes precedence over the +incompatible mismatched.
+ vcs: "git",
+ path: "vcs-test.golang.org/git/semver-branch.git",
+ rev: "v2.0.0",
+ err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`,
+ },
+ {
+ // v3.0.0-devel is the same as tag v4.0.0-beta.1, but v4.0.0-beta.1 would
+ // not be allowed because it is incompatible and a go.mod file exists.
+ // The error message should refer to a valid pseudo-version, not the
+ // unusable semver tag.
+ vcs: "git",
+ path: "vcs-test.golang.org/git/semver-branch.git",
+ rev: "v3.0.0-devel",
+ err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`,
+ },
+
+ // If v2/go.mod exists, then we should prefer to match the "v2"
+ // pseudo-versions to the nested module, and resolve the module in the parent
+ // directory to only compatible versions.
+ //
+ // However (https://go.dev/issue/51324), previous versions of the 'go' command
+ // didn't always do so, so if the user explicitly requests a +incompatible
+ // version (as would be present in an existing go.mod file), we should
+ // continue to allow it.
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "80beb17a1603",
+ version: "v0.0.0-20220222205507-80beb17a1603",
+ name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
+ short: "80beb17a1603",
+ time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "v2.0.0",
+ err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "v2.0.1-0.20220222205507-80beb17a1603",
+ err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "v2.0.0+incompatible",
+ version: "v2.0.0+incompatible",
+ name: "5fcd3eaeeb391d399f562fd45a50dac9fc34ae8b",
+ short: "5fcd3eaeeb39",
+ time: time.Date(2022, 2, 22, 20, 53, 33, 0, time.UTC),
+ },
+ {
+ vcs: "git",
+ path: "vcs-test.golang.org/git/v2sub.git",
+ rev: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
+ version: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
+ name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
+ short: "80beb17a1603",
+ time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
+ },
}
func TestCodeRepo(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
+ tmpdir := t.TempDir()
- tmpdir, err := os.MkdirTemp("", "modfetch-test-")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tmpdir)
+ for _, tt := range codeRepoTests {
+ f := func(tt codeRepoTest) func(t *testing.T) {
+ return func(t *testing.T) {
+ t.Parallel()
+ if tt.vcs != "mod" {
+ testenv.MustHaveExecPath(t, tt.vcs)
+ }
- t.Run("parallel", func(t *testing.T) {
- for _, tt := range codeRepoTests {
- f := func(tt codeRepoTest) func(t *testing.T) {
- return func(t *testing.T) {
- t.Parallel()
- if tt.vcs != "mod" {
- testenv.MustHaveExecPath(t, tt.vcs)
- }
+ repo := Lookup("direct", tt.path)
- repo := Lookup("direct", tt.path)
+ if tt.mpath == "" {
+ tt.mpath = tt.path
+ }
+ if mpath := repo.ModulePath(); mpath != tt.mpath {
+ t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath)
+ }
- if tt.mpath == "" {
- tt.mpath = tt.path
- }
- if mpath := repo.ModulePath(); mpath != tt.mpath {
- t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath)
- }
-
- info, err := repo.Stat(tt.rev)
- if err != nil {
- if tt.err != "" {
- if !strings.Contains(err.Error(), tt.err) {
- t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err)
- }
- return
- }
- t.Fatalf("repo.Stat(%q): %v", tt.rev, err)
- }
+ info, err := repo.Stat(tt.rev)
+ if err != nil {
if tt.err != "" {
- t.Errorf("repo.Stat(%q): success, wanted error", tt.rev)
+ if !strings.Contains(err.Error(), tt.err) {
+ t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err)
+ }
+ return
}
- if info.Version != tt.version {
- t.Errorf("info.Version = %q, want %q", info.Version, tt.version)
- }
- if info.Name != tt.name {
- t.Errorf("info.Name = %q, want %q", info.Name, tt.name)
- }
- if info.Short != tt.short {
- t.Errorf("info.Short = %q, want %q", info.Short, tt.short)
- }
- if !info.Time.Equal(tt.time) {
- t.Errorf("info.Time = %v, want %v", info.Time, tt.time)
- }
+ t.Fatalf("repo.Stat(%q): %v", tt.rev, err)
+ }
+ if tt.err != "" {
+ t.Errorf("repo.Stat(%q): success, wanted error", tt.rev)
+ }
+ if info.Version != tt.version {
+ t.Errorf("info.Version = %q, want %q", info.Version, tt.version)
+ }
+ if info.Name != tt.name {
+ t.Errorf("info.Name = %q, want %q", info.Name, tt.name)
+ }
+ if info.Short != tt.short {
+ t.Errorf("info.Short = %q, want %q", info.Short, tt.short)
+ }
+ if !info.Time.Equal(tt.time) {
+ t.Errorf("info.Time = %v, want %v", info.Time, tt.time)
+ }
- if tt.gomod != "" || tt.gomodErr != "" {
- data, err := repo.GoMod(tt.version)
- if err != nil && tt.gomodErr == "" {
- t.Errorf("repo.GoMod(%q): %v", tt.version, err)
- } else if err != nil && tt.gomodErr != "" {
- if err.Error() != tt.gomodErr {
- t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr)
- }
- } else if tt.gomodErr != "" {
- t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr)
- } else if string(data) != tt.gomod {
- t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod)
+ if tt.gomod != "" || tt.gomodErr != "" {
+ data, err := repo.GoMod(tt.version)
+ if err != nil && tt.gomodErr == "" {
+ t.Errorf("repo.GoMod(%q): %v", tt.version, err)
+ } else if err != nil && tt.gomodErr != "" {
+ if err.Error() != tt.gomodErr {
+ t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr)
}
- }
-
- needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "")
- if tt.zip != nil || tt.zipErr != "" || needHash {
- f, err := os.CreateTemp(tmpdir, tt.version+".zip.")
- if err != nil {
- t.Fatalf("os.CreateTemp: %v", err)
- }
- zipfile := f.Name()
- defer func() {
- f.Close()
- os.Remove(zipfile)
- }()
-
- var w io.Writer
- var h hash.Hash
- if needHash {
- h = sha256.New()
- w = io.MultiWriter(f, h)
- } else {
- w = f
- }
- err = repo.Zip(w, tt.version)
- f.Close()
- if err != nil {
- if tt.zipErr != "" {
- if err.Error() == tt.zipErr {
- return
- }
- t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr)
- }
- t.Fatalf("repo.Zip(%q): %v", tt.version, err)
- }
- if tt.zipErr != "" {
- t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr)
- }
-
- if tt.zip != nil {
- prefix := tt.path + "@" + tt.version + "/"
- z, err := zip.OpenReader(zipfile)
- if err != nil {
- t.Fatalf("open zip %s: %v", zipfile, err)
- }
- var names []string
- for _, file := range z.File {
- if !strings.HasPrefix(file.Name, prefix) {
- t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix)
- continue
- }
- names = append(names, file.Name[len(prefix):])
- }
- z.Close()
- if !reflect.DeepEqual(names, tt.zip) {
- t.Fatalf("zip = %v\nwant %v\n", names, tt.zip)
- }
- }
-
- if needHash {
- sum, err := dirhash.HashZip(zipfile, dirhash.Hash1)
- if err != nil {
- t.Errorf("repo.Zip(%q): %v", tt.version, err)
- } else if sum != tt.zipSum {
- t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum)
- } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash {
- t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash)
- }
- }
+ } else if tt.gomodErr != "" {
+ t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr)
+ } else if string(data) != tt.gomod {
+ t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod)
}
}
- }
- t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
- if strings.HasPrefix(tt.path, vgotest1git) {
- for vcs, alt := range altVgotests {
- altTest := tt
- altTest.vcs = vcs
- altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git)
- if strings.HasPrefix(altTest.mpath, vgotest1git) {
- altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git)
+
+ needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "")
+ if tt.zip != nil || tt.zipErr != "" || needHash {
+ f, err := os.CreateTemp(tmpdir, tt.version+".zip.")
+ if err != nil {
+ t.Fatalf("os.CreateTemp: %v", err)
}
- var m map[string]string
- if alt == vgotest1hg {
- m = hgmap
+ zipfile := f.Name()
+ defer func() {
+ f.Close()
+ os.Remove(zipfile)
+ }()
+
+ var w io.Writer
+ var h hash.Hash
+ if needHash {
+ h = sha256.New()
+ w = io.MultiWriter(f, h)
+ } else {
+ w = f
}
- altTest.version = remap(altTest.version, m)
- altTest.name = remap(altTest.name, m)
- altTest.short = remap(altTest.short, m)
- altTest.rev = remap(altTest.rev, m)
- altTest.err = remap(altTest.err, m)
- altTest.gomodErr = remap(altTest.gomodErr, m)
- altTest.zipErr = remap(altTest.zipErr, m)
- altTest.zipSum = ""
- altTest.zipFileHash = ""
- t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest))
+ err = repo.Zip(w, tt.version)
+ f.Close()
+ if err != nil {
+ if tt.zipErr != "" {
+ if err.Error() == tt.zipErr {
+ return
+ }
+ t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr)
+ }
+ t.Fatalf("repo.Zip(%q): %v", tt.version, err)
+ }
+ if tt.zipErr != "" {
+ t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr)
+ }
+
+ if tt.zip != nil {
+ prefix := tt.path + "@" + tt.version + "/"
+ z, err := zip.OpenReader(zipfile)
+ if err != nil {
+ t.Fatalf("open zip %s: %v", zipfile, err)
+ }
+ var names []string
+ for _, file := range z.File {
+ if !strings.HasPrefix(file.Name, prefix) {
+ t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix)
+ continue
+ }
+ names = append(names, file.Name[len(prefix):])
+ }
+ z.Close()
+ if !reflect.DeepEqual(names, tt.zip) {
+ t.Fatalf("zip = %v\nwant %v\n", names, tt.zip)
+ }
+ }
+
+ if needHash {
+ sum, err := dirhash.HashZip(zipfile, dirhash.Hash1)
+ if err != nil {
+ t.Errorf("repo.Zip(%q): %v", tt.version, err)
+ } else if sum != tt.zipSum {
+ t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum)
+ } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash {
+ t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash)
+ }
+ }
}
}
}
- })
+ t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
+ if strings.HasPrefix(tt.path, vgotest1git) {
+ for vcs, alt := range altVgotests {
+ altTest := tt
+ altTest.vcs = vcs
+ altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git)
+ if strings.HasPrefix(altTest.mpath, vgotest1git) {
+ altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git)
+ }
+ var m map[string]string
+ if alt == vgotest1hg {
+ m = hgmap
+ }
+ altTest.version = remap(altTest.version, m)
+ altTest.name = remap(altTest.name, m)
+ altTest.short = remap(altTest.short, m)
+ altTest.rev = remap(altTest.rev, m)
+ altTest.err = remap(altTest.err, m)
+ altTest.gomodErr = remap(altTest.gomodErr, m)
+ altTest.zipErr = remap(altTest.zipErr, m)
+ altTest.zipSum = ""
+ altTest.zipFileHash = ""
+ t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest))
+ }
+ }
+ }
}
var hgmap = map[string]string{
diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go
index 12b7431..21d5f54 100644
--- a/src/cmd/go/internal/modfetch/fetch.go
+++ b/src/cmd/go/internal/modfetch/fetch.go
@@ -319,7 +319,7 @@
//
// If the hash does not match go.sum (or the sumdb if enabled), hashZip returns
// an error and does not write ziphashfile.
-func hashZip(mod module.Version, zipfile, ziphashfile string) error {
+func hashZip(mod module.Version, zipfile, ziphashfile string) (err error) {
hash, err := dirhash.HashZip(zipfile, dirhash.DefaultHash)
if err != nil {
return err
@@ -331,16 +331,17 @@
if err != nil {
return err
}
+ defer func() {
+ if closeErr := hf.Close(); err == nil && closeErr != nil {
+ err = closeErr
+ }
+ }()
if err := hf.Truncate(int64(len(hash))); err != nil {
return err
}
if _, err := hf.WriteAt([]byte(hash), 0); err != nil {
return err
}
- if err := hf.Close(); err != nil {
- return err
- }
-
return nil
}
@@ -405,6 +406,28 @@
used, dirty bool
}
+// Reset resets globals in the modfetch package, so previous loads don't affect
+// contents of go.sum files
+func Reset() {
+ GoSumFile = ""
+ WorkspaceGoSumFiles = nil
+
+ // Uses of lookupCache and downloadCache both can call checkModSum,
+ // which in turn sets the used bit on goSum.status for modules.
+ // Reset them so used can be computed properly.
+ lookupCache = par.Cache{}
+ downloadCache = par.Cache{}
+
+ // Clear all fields on goSum. It will be initialized later
+ goSum.mu.Lock()
+ goSum.m = nil
+ goSum.w = nil
+ goSum.status = nil
+ goSum.overwrite = false
+ goSum.enabled = false
+ goSum.mu.Unlock()
+}
+
// initGoSum initializes the go.sum data.
// The boolean it returns reports whether the
// use of go.sum is now enabled.
diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go
index 45be51f..6f9072c 100644
--- a/src/cmd/go/internal/modload/buildlist.go
+++ b/src/cmd/go/internal/modload/buildlist.go
@@ -352,7 +352,7 @@
if pruning == unpruned {
if _, dup := loadingUnpruned.LoadOrStore(m, nil); dup {
// m has already been enqueued for loading. Since unpruned loading may
- // follow cycles in the the requirement graph, we need to return early
+ // follow cycles in the requirement graph, we need to return early
// to avoid making the load queue infinitely long.
return
}
@@ -386,6 +386,52 @@
}
<-loadQueue.Idle()
+ // Reload any dependencies of the main modules which are not
+ // at their selected versions at workspace mode, because the
+ // requirements don't accurately reflect the transitive imports.
+ if pruning == workspace {
+ // hasDepsInAll contains the set of modules that need to be loaded
+ // at workspace pruning because any of their dependencies may
+ // provide packages in all.
+ hasDepsInAll := make(map[string]bool)
+ seen := map[module.Version]bool{}
+ for _, m := range roots {
+ hasDepsInAll[m.Path] = true
+ seen[m] = true
+ }
+ // This loop will terminate because it will call enqueue on each version of
+ // each dependency of the modules in hasDepsInAll at most once (and only
+ // calls enqueue on successively increasing versions of each dependency).
+ for {
+ needsEnqueueing := map[module.Version]bool{}
+ for p := range hasDepsInAll {
+ m := module.Version{Path: p, Version: mg.g.Selected(p)}
+ reqs, ok := mg.g.RequiredBy(m)
+ if !ok {
+ needsEnqueueing[m] = true
+ continue
+ }
+ for _, r := range reqs {
+ s := module.Version{Path: r.Path, Version: mg.g.Selected(r.Path)}
+ if cmpVersion(s.Version, r.Version) > 0 && !seen[s] {
+ needsEnqueueing[s] = true
+ }
+ }
+ }
+ // add all needs enqueueing to paths we care about
+ if len(needsEnqueueing) == 0 {
+ break
+ }
+
+ for p := range needsEnqueueing {
+ enqueue(p, workspace)
+ seen[p] = true
+ hasDepsInAll[p.Path] = true
+ }
+ <-loadQueue.Idle()
+ }
+ }
+
if hasError {
return mg, mg.findError()
}
diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go
index 812e48a..4862f62 100644
--- a/src/cmd/go/internal/modload/import.go
+++ b/src/cmd/go/internal/modload/import.go
@@ -248,12 +248,26 @@
// return the module, its root directory, and a list of other modules that
// lexically could have provided the package but did not.
func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph) (m module.Version, dir string, altMods []module.Version, err error) {
+ invalidf := func(format string, args ...interface{}) (module.Version, string, []module.Version, error) {
+ return module.Version{}, "", nil, &invalidImportError{
+ importPath: path,
+ err: fmt.Errorf(format, args...),
+ }
+ }
+
if strings.Contains(path, "@") {
- return module.Version{}, "", nil, fmt.Errorf("import path should not have @version")
+ return invalidf("import path %q should not have @version", path)
}
if build.IsLocalImport(path) {
- return module.Version{}, "", nil, fmt.Errorf("relative import not supported")
+ return invalidf("%q is relative, but relative import paths are not supported in module mode", path)
}
+ if filepath.IsAbs(path) {
+ return invalidf("%q is not a package path; see 'go help packages'", path)
+ }
+ if search.IsMetaPackage(path) {
+ return invalidf("%q is not an importable package; see 'go help packages'", path)
+ }
+
if path == "C" {
// There's no directory for import "C".
return module.Version{}, "", nil, nil
diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go
index df083e7..f960edd 100644
--- a/src/cmd/go/internal/modload/init.go
+++ b/src/cmd/go/internal/modload/init.go
@@ -75,6 +75,7 @@
MainModules = nil // reset MainModules
requirements = nil
workFilePath = "" // Force module mode
+ modfetch.Reset()
modRoots = []string{enterModroot}
LoadModFile(ctx)
@@ -287,20 +288,25 @@
// operate in workspace mode. It should not be called by other commands,
// for example 'go mod tidy', that don't operate in workspace mode.
func InitWorkfile() {
- switch cfg.WorkFile {
+ if RootMode == NoRoot {
+ workFilePath = ""
+ return
+ }
+
+ switch gowork := cfg.Getenv("GOWORK"); gowork {
case "off":
workFilePath = ""
case "", "auto":
workFilePath = findWorkspaceFile(base.Cwd())
default:
- if !filepath.IsAbs(cfg.WorkFile) {
- base.Fatalf("the path provided to -workfile must be an absolute path")
+ if !filepath.IsAbs(gowork) {
+ base.Fatalf("the path provided to GOWORK must be an absolute path")
}
- workFilePath = cfg.WorkFile
+ workFilePath = gowork
}
}
-// WorkFilePath returns the path of the go.work file, or "" if not in
+// WorkFilePath returns the absolute path of the go.work file, or "" if not in
// workspace mode. WorkFilePath must be called after InitWorkfile.
func WorkFilePath() string {
return workFilePath
@@ -609,6 +615,9 @@
missingModulePaths := map[string]string{} // module directory listed in file -> abspath modroot
for _, d := range wf.Use {
+ if d.Path == "" {
+ continue // d is marked for deletion.
+ }
modRoot := d.Path
if d.ModulePath == "" {
missingModulePaths[d.Path] = modRoot
@@ -982,9 +991,16 @@
workFileReplaceMap: toReplaceMap(workFileReplaces),
highestReplaced: map[string]string{},
}
+ mainModulePaths := make(map[string]bool)
+ for _, m := range ms {
+ mainModulePaths[m.Path] = true
+ }
replacedByWorkFile := make(map[string]bool)
replacements := make(map[module.Version]module.Version)
for _, r := range workFileReplaces {
+ if mainModulePaths[r.Old.Path] && r.Old.Version == "" {
+ base.Errorf("go: workspace module %v is replaced at all versions in the go.work file. To fix, remove the replacement from the go.work file or specify the version at which to replace the module.", r.Old.Path)
+ }
replacedByWorkFile[r.Old.Path] = true
v, ok := mainModules.highestReplaced[r.Old.Path]
if !ok || semver.Compare(r.Old.Version, v) > 0 {
@@ -1022,11 +1038,25 @@
for _, r := range modFiles[i].Replace {
if replacedByWorkFile[r.Old.Path] {
continue
- } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] && prev != r.New {
- base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go work edit -replace %v=[override]\" to resolve", r.Old, prev, r.New, r.Old)
+ }
+ var newV module.Version = r.New
+ if WorkFilePath() != "" && newV.Version == "" && !filepath.IsAbs(newV.Path) {
+ // Since we are in a workspace, we may be loading replacements from
+ // multiple go.mod files. Relative paths in those replacement are
+ // relative to the go.mod file, not the workspace, so the same string
+ // may refer to two different paths and different strings may refer to
+ // the same path. Convert them all to be absolute instead.
+ //
+ // (We could do this outside of a workspace too, but it would mean that
+ // replacement paths in error strings needlessly differ from what's in
+ // the go.mod file.)
+ newV.Path = filepath.Join(rootDirs[i], newV.Path)
+ }
+ if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] && prev != newV {
+ base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go work edit -replace %v=[override]\" to resolve", r.Old, prev, newV, r.Old)
}
curModuleReplaces[r.Old] = true
- replacements[r.Old] = r.New
+ replacements[r.Old] = newV
v, ok := mainModules.highestReplaced[r.Old.Path]
if !ok || semver.Compare(r.Old.Version, v) > 0 {
@@ -1084,7 +1114,7 @@
if inWorkspaceMode() && cfg.BuildMod != "readonly" {
base.Fatalf("go: -mod may only be set to readonly when in workspace mode, but it is set to %q"+
"\n\tRemove the -mod flag to use the default readonly value,"+
- "\n\tor set -workfile=off to disable workspace mode.", cfg.BuildMod)
+ "\n\tor set GOWORK=off to disable workspace mode.", cfg.BuildMod)
}
// Don't override an explicit '-mod=' argument.
return
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index 617b634..d4847ef 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -479,7 +479,11 @@
}
if !found && search.InDir(absDir, cfg.GOROOTsrc) == "" && pathInModuleCache(ctx, absDir, rs) == "" {
m.Dirs = []string{}
- m.AddError(fmt.Errorf("directory prefix %s outside available modules", base.ShortPath(absDir)))
+ scope := "main module or its selected dependencies"
+ if inWorkspaceMode() {
+ scope = "modules listed in go.work or their selected dependencies"
+ }
+ m.AddError(fmt.Errorf("directory prefix %s does not contain %s", base.ShortPath(absDir), scope))
return
}
}
@@ -601,7 +605,11 @@
pkg := pathInModuleCache(ctx, absDir, rs)
if pkg == "" {
- return "", fmt.Errorf("directory %s outside available modules", base.ShortPath(absDir))
+ scope := "main module or its selected dependencies"
+ if inWorkspaceMode() {
+ scope = "modules listed in go.work or their selected dependencies"
+ }
+ return "", fmt.Errorf("directory %s outside %s", base.ShortPath(absDir), scope)
}
return pkg, nil
}
@@ -1667,24 +1675,6 @@
// load loads an individual package.
func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
- if strings.Contains(pkg.path, "@") {
- // Leave for error during load.
- return
- }
- if build.IsLocalImport(pkg.path) || filepath.IsAbs(pkg.path) {
- // Leave for error during load.
- // (Module mode does not allow local imports.)
- return
- }
-
- if search.IsMetaPackage(pkg.path) {
- pkg.err = &invalidImportError{
- importPath: pkg.path,
- err: fmt.Errorf("%q is not an importable package; see 'go help packages'", pkg.path),
- }
- return
- }
-
var mg *ModuleGraph
if ld.requirements.pruning == unpruned {
var err error
diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go
index ec3f57a..75c278a 100644
--- a/src/cmd/go/internal/modload/modfile.go
+++ b/src/cmd/go/internal/modload/modfile.go
@@ -340,6 +340,9 @@
foundFrom, found, foundModRoot := "", module.Version{}, ""
if MainModules == nil {
return module.Version{}
+ } else if MainModules.Contains(mod.Path) && mod.Version == "" {
+ // Don't replace the workspace version of the main module.
+ return module.Version{}
}
if _, r, ok := replacement(mod, MainModules.WorkFileReplaceMap()); ok {
return r
@@ -799,7 +802,7 @@
// an absolute path or a relative path starting with a '.' or '..'
// path component.
func ToDirectoryPath(path string) string {
- if modfile.IsDirectoryPath(path) {
+ if path == "." || modfile.IsDirectoryPath(path) {
return path
}
// The path is not a relative path or an absolute path, so make it relative
diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go
index c4b70b6..312b49e 100644
--- a/src/cmd/go/internal/run/run.go
+++ b/src/cmd/go/internal/run/run.go
@@ -65,7 +65,6 @@
CmdRun.Run = runRun // break init loop
work.AddBuildFlags(CmdRun, work.DefaultBuildFlags)
- base.AddWorkfileFlag(&CmdRun.Flag)
CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "")
}
@@ -74,8 +73,6 @@
}
func runRun(ctx context.Context, cmd *base.Command, args []string) {
- modload.InitWorkfile()
-
if shouldUseOutsideModuleMode(args) {
// Set global module flags for 'go run cmd@version'.
// This must be done before modload.Init, but we need to call work.BuildInit
@@ -85,7 +82,10 @@
modload.RootMode = modload.NoRoot
modload.AllowMissingModuleImports()
modload.Init()
+ } else {
+ modload.InitWorkfile()
}
+
work.BuildInit()
var b work.Builder
b.Init()
diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go
index b9d1ec9..c046cac 100644
--- a/src/cmd/go/internal/test/testflag.go
+++ b/src/cmd/go/internal/test/testflag.go
@@ -28,7 +28,6 @@
func init() {
work.AddBuildFlags(CmdTest, work.OmitVFlag)
- base.AddWorkfileFlag(&CmdTest.Flag)
cf := CmdTest.Flag
cf.BoolVar(&testC, "c", false, "")
diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go
index 313dc62..2acabf7 100644
--- a/src/cmd/go/internal/vcs/vcs.go
+++ b/src/cmd/go/internal/vcs/vcs.go
@@ -6,7 +6,6 @@
import (
"bytes"
- "encoding/json"
"errors"
"fmt"
exec "internal/execabs"
@@ -165,7 +164,7 @@
func hgStatus(vcsHg *Cmd, rootDir string) (Status, error) {
// Output changeset ID and seconds since epoch.
- out, err := vcsHg.runOutputVerboseOnly(rootDir, `log -l1 -T {node}:{date(date,"%s")}`)
+ out, err := vcsHg.runOutputVerboseOnly(rootDir, `log -l1 -T {node}:{date|hgdate}`)
if err != nil {
return Status{}, err
}
@@ -174,6 +173,10 @@
var rev string
var commitTime time.Time
if len(out) > 0 {
+ // Strip trailing timezone offset.
+ if i := bytes.IndexByte(out, ' '); i > 0 {
+ out = out[:i]
+ }
rev, commitTime, err = parseRevTime(out)
if err != nil {
return Status{}, err
@@ -309,7 +312,7 @@
// uncommitted files and skip tagging revision / committime.
var rev string
var commitTime time.Time
- out, err = vcsGit.runOutputVerboseOnly(rootDir, "show -s --format=%H:%ct")
+ out, err = vcsGit.runOutputVerboseOnly(rootDir, "-c log.showsignature=false show -s --format=%H:%ct")
if err != nil && !uncommitted {
return Status{}, err
} else if err == nil {
@@ -1437,8 +1440,9 @@
{
pathPrefix: "bitbucket.org",
regexp: lazyregexp.New(`^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),
+ vcs: "git",
repo: "https://{root}",
- check: bitbucketVCS,
+ check: noVCSSuffix,
},
// IBM DevOps Services (JazzHub)
@@ -1510,56 +1514,6 @@
return nil
}
-// bitbucketVCS determines the version control system for a
-// Bitbucket repository, by using the Bitbucket API.
-func bitbucketVCS(match map[string]string) error {
- if err := noVCSSuffix(match); err != nil {
- return err
- }
-
- var resp struct {
- SCM string `json:"scm"`
- }
- url := &urlpkg.URL{
- Scheme: "https",
- Host: "api.bitbucket.org",
- Path: expand(match, "/2.0/repositories/{bitname}"),
- RawQuery: "fields=scm",
- }
- data, err := web.GetBytes(url)
- if err != nil {
- if httpErr, ok := err.(*web.HTTPError); ok && httpErr.StatusCode == 403 {
- // this may be a private repository. If so, attempt to determine which
- // VCS it uses. See issue 5375.
- root := match["root"]
- for _, vcs := range []string{"git", "hg"} {
- if vcsByCmd(vcs).Ping("https", root) == nil {
- resp.SCM = vcs
- break
- }
- }
- }
-
- if resp.SCM == "" {
- return err
- }
- } else {
- if err := json.Unmarshal(data, &resp); err != nil {
- return fmt.Errorf("decoding %s: %v", url, err)
- }
- }
-
- if vcsByCmd(resp.SCM) != nil {
- match["vcs"] = resp.SCM
- if resp.SCM == "git" {
- match["repo"] += ".git"
- }
- return nil
- }
-
- return fmt.Errorf("unable to detect version control system for bitbucket.org/ path")
-}
-
// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case,
// "foo" could be a series name registered in Launchpad with its own branch,
// and it could also be the name of a directory within the main project
diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go
index c4e4f4d..943d520 100644
--- a/src/cmd/go/internal/vcs/vcs_test.go
+++ b/src/cmd/go/internal/vcs/vcs_test.go
@@ -183,6 +183,13 @@
"chiselapp.com/user/kyle/fossilgg",
nil,
},
+ {
+ "bitbucket.org/workspace/pkgname",
+ &RepoRoot{
+ VCS: vcsGit,
+ Repo: "https://bitbucket.org/workspace/pkgname",
+ },
+ },
}
for _, test := range tests {
diff --git a/src/cmd/go/internal/version/version.go b/src/cmd/go/internal/version/version.go
index 52502e9..1c0eb54 100644
--- a/src/cmd/go/internal/version/version.go
+++ b/src/cmd/go/internal/version/version.go
@@ -6,7 +6,6 @@
package version
import (
- "bytes"
"context"
"debug/buildinfo"
"errors"
@@ -156,12 +155,8 @@
fmt.Printf("%s: %s\n", file, bi.GoVersion)
bi.GoVersion = "" // suppress printing go version again
- mod, err := bi.MarshalText()
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s: formatting build info: %v\n", file, err)
- return
- }
+ mod := bi.String()
if *versionM && len(mod) > 0 {
- fmt.Printf("\t%s\n", bytes.ReplaceAll(mod[:len(mod)-1], []byte("\n"), []byte("\n\t")))
+ fmt.Printf("\t%s\n", strings.ReplaceAll(mod[:len(mod)-1], "\n", "\n\t"))
}
}
diff --git a/src/cmd/go/internal/vet/vet.go b/src/cmd/go/internal/vet/vet.go
index 88b3c57..d3e0dd8 100644
--- a/src/cmd/go/internal/vet/vet.go
+++ b/src/cmd/go/internal/vet/vet.go
@@ -13,6 +13,7 @@
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/load"
+ "cmd/go/internal/modload"
"cmd/go/internal/trace"
"cmd/go/internal/work"
)
@@ -54,6 +55,7 @@
func runVet(ctx context.Context, cmd *base.Command, args []string) {
vetFlags, pkgArgs := vetFlags(args)
+ modload.InitWorkfile() // The vet command does custom flag processing; initialize workspaces after that.
if cfg.DebugTrace != "" {
var close func() error
diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go
index 9d0ad27..0b5848a 100644
--- a/src/cmd/go/internal/work/build.go
+++ b/src/cmd/go/internal/work/build.go
@@ -88,11 +88,6 @@
-asmflags '[pattern=]arg list'
arguments to pass on each go tool asm invocation.
- -buildinfo
- Whether to stamp binaries with build flags. By default, the compiler name
- (gc or gccgo), toolchain flags (like -gcflags), and environment variables
- containing flags (like CGO_CFLAGS) are stamped into binaries. Use
- -buildinfo=false to omit build information. See also -buildvcs.
-buildmode mode
build mode to use. See 'go help buildmode' for more.
-buildvcs
@@ -100,7 +95,7 @@
version control information is stamped into a binary if the main package
and the main module containing it are in the repository containing the
current directory (if there is a repository). Use -buildvcs=false to
- omit version control information. See also -buildinfo.
+ omit version control information.
-compiler name
name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags '[pattern=]arg list'
@@ -135,14 +130,6 @@
directory, but it is not accessed. When -modfile is specified, an
alternate go.sum file is also used: its path is derived from the
-modfile flag by trimming the ".mod" extension and appending ".sum".
- -workfile file
- in module aware mode, use the given go.work file as a workspace file.
- By default or when -workfile is "auto", the go command searches for a
- file named go.work in the current directory and then containing directories
- until one is found. If a valid go.work file is found, the modules
- specified will collectively be used as the main modules. If -workfile
- is "off", or a go.work file is not found in "auto" mode, workspace
- mode is disabled.
-overlay file
read a JSON config file that provides an overlay for build operations.
The file is a JSON struct with a single field, named 'Replace', that
@@ -167,9 +154,8 @@
-trimpath
remove all file system paths from the resulting executable.
Instead of absolute file system paths, the recorded file names
- will begin with either "go" (for the standard library),
- or a module path@version (when using modules),
- or a plain import path (when using GOPATH).
+ will begin either a module path@version (when using modules),
+ or a plain import path (when using the standard library, or GOPATH).
-toolexec 'cmd args'
a program to use to invoke toolchain programs like vet and asm.
For example, instead of running asm, the go command will run
@@ -223,7 +209,6 @@
AddBuildFlags(CmdBuild, DefaultBuildFlags)
AddBuildFlags(CmdInstall, DefaultBuildFlags)
- base.AddWorkfileFlag(&CmdBuild.Flag)
}
// Note that flags consulted by other parts of the code
@@ -317,7 +302,6 @@
cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "")
cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
- cmd.Flag.BoolVar(&cfg.BuildBuildinfo, "buildinfo", true, "")
cmd.Flag.BoolVar(&cfg.BuildBuildvcs, "buildvcs", true, "")
// Undocumented, unstable debugging flags.
@@ -617,6 +601,7 @@
}
}
+ modload.InitWorkfile()
BuildInit()
pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
if cfg.ModulesEnabled && !modload.HasModRoot() {
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index ccd5aee..ac80f50 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -236,11 +236,13 @@
}
} else if p.Goroot {
// The Go compiler always hides the exact value of $GOROOT
- // when building things in GOROOT, but the C compiler
- // merely rewrites GOROOT to GOROOT_FINAL.
- if len(p.CFiles) > 0 {
- fmt.Fprintf(h, "goroot %s\n", cfg.GOROOT_FINAL)
- }
+ // when building things in GOROOT.
+ //
+ // The C compiler does not, but for packages in GOROOT we rewrite the path
+ // as though -trimpath were set, so that we don't invalidate the build cache
+ // (and especially any precompiled C archive files) when changing
+ // GOROOT_FINAL. (See https://go.dev/issue/50183.)
+ //
// b.WorkDir is always either trimmed or rewritten to
// the literal string "/tmp/go-build".
} else if !strings.HasPrefix(p.Dir, b.WorkDir) {
@@ -2011,6 +2013,7 @@
if reldir := base.ShortPath(dir); reldir != dir {
suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
+ suffix = strings.ReplaceAll(suffix, "\n\t"+dir, "\n\t"+reldir)
}
suffix = strings.ReplaceAll(suffix, " "+b.WorkDir, " $WORK")
@@ -2337,7 +2340,7 @@
// directives pointing to the source directory. It should not generate those
// when -trimpath is enabled.
if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
- if cfg.BuildTrimpath {
+ if cfg.BuildTrimpath || p.Goroot {
// Keep in sync with Action.trimpath.
// The trimmed paths are a little different, but we need to trim in the
// same situations.
@@ -2359,8 +2362,6 @@
to = filepath.Join("/_", toPath)
}
flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+from+"="+to)
- } else if p.Goroot && cfg.GOROOT_FINAL != cfg.GOROOT {
- flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+cfg.GOROOT+"="+cfg.GOROOT_FINAL)
}
}
diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go
index e9b9f6c..d1e2c67 100644
--- a/src/cmd/go/internal/work/security.go
+++ b/src/cmd/go/internal/work/security.go
@@ -131,6 +131,7 @@
"-D",
"-U",
"-I",
+ "-F",
"-framework",
"-include",
"-isysroot",
diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go
index 8d4be0a..d2aeb54 100644
--- a/src/cmd/go/internal/work/security_test.go
+++ b/src/cmd/go/internal/work/security_test.go
@@ -15,6 +15,7 @@
{"-Ufoo"},
{"-Ufoo1"},
{"-F/Qt"},
+ {"-F", "/Qt"},
{"-I/"},
{"-I/etc/passwd"},
{"-I."},
diff --git a/src/cmd/go/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go
index c420007..1478c19 100644
--- a/src/cmd/go/internal/workcmd/edit.go
+++ b/src/cmd/go/internal/workcmd/edit.go
@@ -63,19 +63,14 @@
The -json flag prints the final go.work file in JSON format instead of
writing it back to go.mod. The JSON output corresponds to these Go types:
- type Module struct {
- Path string
- Version string
- }
-
type GoWork struct {
- Go string
- Directory []Directory
- Replace []Replace
+ Go string
+ Use []Use
+ Replace []Replace
}
type Use struct {
- Path string
+ DiskPath string
ModulePath string
}
@@ -84,9 +79,13 @@
New Module
}
-See the workspaces design proposal at
-https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for
-more information.
+ type Module struct {
+ Path string
+ Version string
+ }
+
+See the workspaces reference at https://go.dev/ref/mod#workspaces
+for more information.
`,
}
@@ -110,22 +109,9 @@
cmdEdit.Flag.Var(flagFunc(flagEditworkDropUse), "dropuse", "")
cmdEdit.Flag.Var(flagFunc(flagEditworkReplace), "replace", "")
cmdEdit.Flag.Var(flagFunc(flagEditworkDropReplace), "dropreplace", "")
-
- base.AddWorkfileFlag(&cmdEdit.Flag)
}
func runEditwork(ctx context.Context, cmd *base.Command, args []string) {
- anyFlags :=
- *editGo != "" ||
- *editJSON ||
- *editPrint ||
- *editFmt ||
- len(workedits) > 0
-
- if !anyFlags {
- base.Fatalf("go: no flags specified (see 'go help work edit').")
- }
-
if *editJSON && *editPrint {
base.Fatalf("go: cannot use both -json and -print")
}
@@ -147,6 +133,21 @@
}
}
+ if gowork == "" {
+ base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
+ }
+
+ anyFlags :=
+ *editGo != "" ||
+ *editJSON ||
+ *editPrint ||
+ *editFmt ||
+ len(workedits) > 0
+
+ if !anyFlags {
+ base.Fatalf("go: no flags specified (see 'go help work edit').")
+ }
+
workFile, err := modload.ReadWorkFile(gowork)
if err != nil {
base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gowork), err)
diff --git a/src/cmd/go/internal/workcmd/init.go b/src/cmd/go/internal/workcmd/init.go
index 2297ac2..c2513ba 100644
--- a/src/cmd/go/internal/workcmd/init.go
+++ b/src/cmd/go/internal/workcmd/init.go
@@ -13,29 +13,28 @@
"path/filepath"
)
-// TODO(#49232) Add more documentation below. Though this is
-// enough for those trying workspaces out, there should be more through
-// documentation before Go 1.18 is released.
-
var cmdInit = &base.Command{
UsageLine: "go work init [moddirs]",
Short: "initialize workspace file",
- Long: `Init initializes and writes a new go.work file in the current
-directory, in effect creating a new workspace at the current directory.
+ Long: `Init initializes and writes a new go.work file in the
+current directory, in effect creating a new workspace at the current
+directory.
-go work init optionally accepts paths to the workspace modules as arguments.
-If the argument is omitted, an empty workspace with no modules will be created.
+go work init optionally accepts paths to the workspace modules as
+arguments. If the argument is omitted, an empty workspace with no
+modules will be created.
-See the workspaces design proposal at
-https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for
-more information.
+Each argument path is added to a use directive in the go.work file. The
+current go version will also be listed in the go.work file.
+
+See the workspaces reference at https://go.dev/ref/mod#workspaces
+for more information.
`,
Run: runInit,
}
func init() {
base.AddModCommonFlags(&cmdInit.Flag)
- base.AddWorkfileFlag(&cmdInit.Flag)
}
func runInit(ctx context.Context, cmd *base.Command, args []string) {
@@ -43,12 +42,10 @@
modload.ForceUseModules = true
- // TODO(matloob): support using the -workfile path
- // To do that properly, we'll have to make the module directories
- // make dirs relative to workFile path before adding the paths to
- // the directory entries
-
- workFile := filepath.Join(base.Cwd(), "go.work")
+ workFile := modload.WorkFilePath()
+ if workFile == "" {
+ workFile = filepath.Join(base.Cwd(), "go.work")
+ }
modload.CreateWorkFile(ctx, workFile, args)
}
diff --git a/src/cmd/go/internal/workcmd/sync.go b/src/cmd/go/internal/workcmd/sync.go
index 5f33e05..7712eb6 100644
--- a/src/cmd/go/internal/workcmd/sync.go
+++ b/src/cmd/go/internal/workcmd/sync.go
@@ -15,26 +15,41 @@
"golang.org/x/mod/module"
)
-// TODO(#49232) Add more documentation below. Though this is
-// enough for those trying workspaces out, there should be more thorough
-// documentation before Go 1.18 is released.
-
var cmdSync = &base.Command{
- UsageLine: "go work sync [moddirs]",
+ UsageLine: "go work sync",
Short: "sync workspace build list to modules",
- Long: `go work sync`,
- Run: runSync,
+ Long: `Sync syncs the workspace's build list back to the
+workspace's modules
+
+The workspace's build list is the set of versions of all the
+(transitive) dependency modules used to do builds in the workspace. go
+work sync generates that build list using the Minimal Version Selection
+algorithm, and then syncs those versions back to each of modules
+specified in the workspace (with use directives).
+
+The syncing is done by sequentially upgrading each of the dependency
+modules specified in a workspace module to the version in the build list
+if the dependency module's version is not already the same as the build
+list's version. Note that Minimal Version Selection guarantees that the
+build list's version of each module is always the same or higher than
+that in each workspace module.
+
+See the workspaces reference at https://go.dev/ref/mod#workspaces
+for more information.
+`,
+ Run: runSync,
}
func init() {
base.AddModCommonFlags(&cmdSync.Flag)
- base.AddWorkfileFlag(&cmdSync.Flag)
}
func runSync(ctx context.Context, cmd *base.Command, args []string) {
- modload.InitWorkfile()
-
modload.ForceUseModules = true
+ modload.InitWorkfile()
+ if modload.WorkFilePath() == "" {
+ base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
+ }
workGraph := modload.LoadModGraph(ctx, "")
_ = workGraph
@@ -97,13 +112,13 @@
modload.LoadPackages(ctx, modload.PackageOpts{
Tags: imports.AnyTags(),
+ Tidy: true,
VendorModulesInGOROOTSrc: true,
ResolveMissingImports: false,
LoadTests: true,
AllowErrors: true,
+ SilenceMissingStdImports: true,
SilencePackageErrors: true,
- Tidy: true,
- SilenceUnmatchedWarnings: true,
}, "all")
modload.WriteGoMod(ctx)
}
diff --git a/src/cmd/go/internal/workcmd/use.go b/src/cmd/go/internal/workcmd/use.go
index 97c4936..e20041f 100644
--- a/src/cmd/go/internal/workcmd/use.go
+++ b/src/cmd/go/internal/workcmd/use.go
@@ -10,23 +10,33 @@
"cmd/go/internal/base"
"cmd/go/internal/fsys"
"cmd/go/internal/modload"
+ "cmd/go/internal/str"
"context"
+ "errors"
+ "fmt"
"io/fs"
"os"
"path/filepath"
)
-// TODO(#49232) Add more documentation below. Though this is
-// enough for those trying workspaces out, there should be more thorough
-// documentation before Go 1.18 is released.
-
var cmdUse = &base.Command{
- UsageLine: "go work use [-r] [moddirs]",
+ UsageLine: "go work use [-r] moddirs",
Short: "add modules to workspace file",
- Long: `Use provides a command-line interface for adding directories,
-optionally recursively, to a go.work file.
+ Long: `Use provides a command-line interface for adding
+directories, optionally recursively, to a go.work file.
-The -r flag searches recursively for modules in the argument directories.`,
+A use directive will be added to the go.work file for each argument
+directory listed on the command line go.work file, if it exists on disk,
+or removed from the go.work file if it does not exist on disk.
+
+The -r flag searches recursively for modules in the argument
+directories, and the use command operates as if each of the directories
+were specified as arguments: namely, use directives will be added for
+directories that exist, and removed for directories that do not exist.
+
+See the workspaces reference at https://go.dev/ref/mod#workspaces
+for more information.
+`,
}
var useR = cmdUse.Flag.Bool("r", false, "")
@@ -35,47 +45,50 @@
cmdUse.Run = runUse // break init cycle
base.AddModCommonFlags(&cmdUse.Flag)
- base.AddWorkfileFlag(&cmdUse.Flag)
}
func runUse(ctx context.Context, cmd *base.Command, args []string) {
- modload.InitWorkfile()
-
modload.ForceUseModules = true
var gowork string
modload.InitWorkfile()
gowork = modload.WorkFilePath()
+ if gowork == "" {
+ base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
+ }
workFile, err := modload.ReadWorkFile(gowork)
if err != nil {
base.Fatalf("go: %v", err)
}
+ workDir := filepath.Dir(gowork) // Absolute, since gowork itself is absolute.
- haveDirs := make(map[string]bool)
- for _, dir := range workFile.Use {
- haveDirs[filepath.Join(filepath.Dir(gowork), filepath.FromSlash(dir.Path))] = true
+ haveDirs := make(map[string][]string) // absolute → original(s)
+ for _, use := range workFile.Use {
+ var abs string
+ if filepath.IsAbs(use.Path) {
+ abs = filepath.Clean(use.Path)
+ } else {
+ abs = filepath.Join(workDir, use.Path)
+ }
+ haveDirs[abs] = append(haveDirs[abs], use.Path)
}
- addDirs := make(map[string]bool)
- removeDirs := make(map[string]bool)
+ // keepDirs maps each absolute path to keep to the literal string to use for
+ // that path (either an absolute or a relative path), or the empty string if
+ // all entries for the absolute path should be removed.
+ keepDirs := make(map[string]string)
+
+ // lookDir updates the entry in keepDirs for the directory dir,
+ // which is either absolute or relative to the current working directory
+ // (not necessarily the directory containing the workfile).
lookDir := func(dir string) {
- absDir := filepath.Join(base.Cwd(), dir)
- // If the path is absolute, keep it absolute. If it's relative,
- // make it relative to the go.work file rather than the working directory.
- if !filepath.IsAbs(dir) {
- rel, err := filepath.Rel(filepath.Dir(gowork), absDir)
- if err == nil {
- dir = rel
- }
- }
- fi, err := os.Stat(filepath.Join(dir, "go.mod"))
+ absDir, dir := pathRel(workDir, dir)
+
+ fi, err := os.Stat(filepath.Join(absDir, "go.mod"))
if err != nil {
if os.IsNotExist(err) {
-
- if haveDirs[absDir] {
- removeDirs[dir] = true
- }
+ keepDirs[absDir] = ""
return
}
base.Errorf("go: %v", err)
@@ -85,31 +98,99 @@
base.Errorf("go: %v is not regular", filepath.Join(dir, "go.mod"))
}
- if !haveDirs[absDir] {
- addDirs[dir] = true
+ if dup := keepDirs[absDir]; dup != "" && dup != dir {
+ base.Errorf(`go: already added "%s" as "%s"`, dir, dup)
}
+ keepDirs[absDir] = dir
}
+ if len(args) == 0 {
+ base.Fatalf("go: 'go work use' requires one or more directory arguments")
+ }
for _, useDir := range args {
- if *useR {
- fsys.Walk(useDir, func(path string, info fs.FileInfo, err error) error {
- if !info.IsDir() {
- return nil
- }
- lookDir(path)
- return nil
- })
+ if !*useR {
+ lookDir(useDir)
continue
}
- lookDir(useDir)
+
+ // Add or remove entries for any subdirectories that still exist.
+ err := fsys.Walk(useDir, func(path string, info fs.FileInfo, err error) error {
+ if !info.IsDir() {
+ if info.Mode()&fs.ModeSymlink != 0 {
+ if target, err := fsys.Stat(path); err == nil && target.IsDir() {
+ fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
+ }
+ }
+ return nil
+ }
+ lookDir(path)
+ return nil
+ })
+ if err != nil && !errors.Is(err, os.ErrNotExist) {
+ base.Errorf("go: %v", err)
+ }
+
+ // Remove entries for subdirectories that no longer exist.
+ // Because they don't exist, they will be skipped by Walk.
+ absArg, _ := pathRel(workDir, useDir)
+ for absDir, _ := range haveDirs {
+ if str.HasFilePathPrefix(absDir, absArg) {
+ if _, ok := keepDirs[absDir]; !ok {
+ keepDirs[absDir] = "" // Mark for deletion.
+ }
+ }
+ }
}
- for dir := range removeDirs {
- workFile.DropUse(filepath.ToSlash(dir))
- }
- for dir := range addDirs {
- workFile.AddUse(filepath.ToSlash(dir), "")
+ base.ExitIfErrors()
+
+ for absDir, keepDir := range keepDirs {
+ nKept := 0
+ for _, dir := range haveDirs[absDir] {
+ if dir == keepDir { // (note that dir is always non-empty)
+ nKept++
+ } else {
+ workFile.DropUse(dir)
+ }
+ }
+ if keepDir != "" && nKept != 1 {
+ // If we kept more than one copy, delete them all.
+ // We'll recreate a unique copy with AddUse.
+ if nKept > 1 {
+ workFile.DropUse(keepDir)
+ }
+ workFile.AddUse(keepDir, "")
+ }
}
modload.UpdateWorkFile(workFile)
modload.WriteWorkFile(gowork, workFile)
}
+
+// pathRel returns the absolute and canonical forms of dir for use in a
+// go.work file located in directory workDir.
+//
+// If dir is relative, it is intepreted relative to base.Cwd()
+// and its canonical form is relative to workDir if possible.
+// If dir is absolute or cannot be made relative to workDir,
+// its canonical form is absolute.
+//
+// Canonical absolute paths are clean.
+// Canonical relative paths are clean and slash-separated.
+func pathRel(workDir, dir string) (abs, canonical string) {
+ if filepath.IsAbs(dir) {
+ abs = filepath.Clean(dir)
+ return abs, abs
+ }
+
+ abs = filepath.Join(base.Cwd(), dir)
+ rel, err := filepath.Rel(workDir, abs)
+ if err != nil {
+ // The path can't be made relative to the go.work file,
+ // so it must be kept absolute instead.
+ return abs, abs
+ }
+
+ // Normalize relative paths to use slashes, so that checked-in go.work
+ // files with relative paths within the repo are platform-independent.
+ return abs, modload.ToDirectoryPath(rel)
+}
diff --git a/src/cmd/go/internal/workcmd/work.go b/src/cmd/go/internal/workcmd/work.go
index 3ddbfbe..39c81e8 100644
--- a/src/cmd/go/internal/workcmd/work.go
+++ b/src/cmd/go/internal/workcmd/work.go
@@ -12,23 +12,61 @@
var CmdWork = &base.Command{
UsageLine: "go work",
Short: "workspace maintenance",
- Long: `Go workspace provides access to operations on workspaces.
+ Long: `Work provides access to operations on workspaces.
-Note that support for workspaces is built into many other commands,
-not just 'go work'.
+Note that support for workspaces is built into many other commands, not
+just 'go work'.
-See 'go help modules' for information about Go's module system of
-which workspaces are a part.
+See 'go help modules' for information about Go's module system of which
+workspaces are a part.
+
+See https://go.dev/ref/mod#workspaces for an in-depth reference on
+workspaces.
+
+See https://go.dev/doc/tutorial/workspaces for an introductory
+tutorial on workspaces.
A workspace is specified by a go.work file that specifies a set of
-module directories with the "use" directive. These modules are used
-as root modules by the go command for builds and related operations.
-A workspace that does not specify modules to be used cannot be used
-to do builds from local modules.
+module directories with the "use" directive. These modules are used as
+root modules by the go command for builds and related operations. A
+workspace that does not specify modules to be used cannot be used to do
+builds from local modules.
-To determine whether the go command is operating in workspace mode,
-use the "go env GOWORK" command. This will specify the workspace
-file being used.
+go.work files are line-oriented. Each line holds a single directive,
+made up of a keyword followed by arguments. For example:
+
+ go 1.18
+
+ use ../foo/bar
+ use ./baz
+
+ replace example.com/foo v1.2.3 => example.com/bar v1.4.5
+
+The leading keyword can be factored out of adjacent lines to create a block,
+like in Go imports.
+
+ use (
+ ../foo/bar
+ ./baz
+ )
+
+The use directive specifies a module to be included in the workspace's
+set of main modules. The argument to the use directive is the directory
+containing the module's go.mod file.
+
+The go directive specifies the version of Go the file was written at. It
+is possible there may be future changes in the semantics of workspaces
+that could be controlled by this version, but for now the version
+specified has no effect.
+
+The replace directive has the same syntax as the replace directive in a
+go.mod file and takes precedence over replaces in go.mod files. It is
+primarily intended to override conflicting replaces in different workspace
+modules.
+
+To determine whether the go command is operating in workspace mode, use
+the "go env GOWORK" command. This will specify the workspace file being
+used.
`,
Commands: []*base.Command{
diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go
index dbfba22..55a88e0 100644
--- a/src/cmd/go/script_test.go
+++ b/src/cmd/go/script_test.go
@@ -142,11 +142,12 @@
"SYSTEMROOT", // must be preserved on Windows to find DLLs; golang.org/issue/25210
"WINDIR", // must be preserved on Windows to be able to run PowerShell command; golang.org/issue/30711
"LD_LIBRARY_PATH", // must be preserved on Unix systems to find shared libraries
+ "LIBRARY_PATH", // allow override of non-standard static library paths
+ "C_INCLUDE_PATH", // allow override non-standard include paths
"CC", // don't lose user settings when invoking cgo
"GO_TESTING_GOTOOLS", // for gccgo testing
"GCCGO", // for gccgo testing
"GCCGOTOOLDIR", // for gccgo testing
- "MallocNanoZone", // Needed to work around an apparent kernel bug in macOS 12; see https://golang.org/issue/49138.
}
// setup sets up the test execution temporary directory and environment.
@@ -492,6 +493,7 @@
"go": (*testScript).cmdGo,
"grep": (*testScript).cmdGrep,
"mkdir": (*testScript).cmdMkdir,
+ "mv": (*testScript).cmdMv,
"rm": (*testScript).cmdRm,
"skip": (*testScript).cmdSkip,
"stale": (*testScript).cmdStale,
@@ -586,10 +588,6 @@
// cmp compares two files.
func (ts *testScript) cmdCmp(want simpleStatus, args []string) {
- if want != success {
- // It would be strange to say "this file can have any content except this precise byte sequence".
- ts.fatalf("unsupported: %v cmp", want)
- }
quiet := false
if len(args) > 0 && args[0] == "-q" {
quiet = true
@@ -598,14 +596,11 @@
if len(args) != 2 {
ts.fatalf("usage: cmp file1 file2")
}
- ts.doCmdCmp(args, false, quiet)
+ ts.doCmdCmp(want, args, false, quiet)
}
// cmpenv compares two files with environment variable substitution.
func (ts *testScript) cmdCmpenv(want simpleStatus, args []string) {
- if want != success {
- ts.fatalf("unsupported: %v cmpenv", want)
- }
quiet := false
if len(args) > 0 && args[0] == "-q" {
quiet = true
@@ -614,17 +609,18 @@
if len(args) != 2 {
ts.fatalf("usage: cmpenv file1 file2")
}
- ts.doCmdCmp(args, true, quiet)
+ ts.doCmdCmp(want, args, true, quiet)
}
-func (ts *testScript) doCmdCmp(args []string, env, quiet bool) {
+func (ts *testScript) doCmdCmp(want simpleStatus, args []string, env, quiet bool) {
name1, name2 := args[0], args[1]
var text1, text2 string
- if name1 == "stdout" {
+ switch name1 {
+ case "stdout":
text1 = ts.stdout
- } else if name1 == "stderr" {
+ case "stderr":
text1 = ts.stderr
- } else {
+ default:
data, err := os.ReadFile(ts.mkabs(name1))
ts.check(err)
text1 = string(data)
@@ -639,14 +635,28 @@
text2 = ts.expand(text2, false)
}
- if text1 == text2 {
- return
- }
-
- if !quiet {
+ eq := text1 == text2
+ if !eq && !quiet && want != failure {
fmt.Fprintf(&ts.log, "[diff -%s +%s]\n%s\n", name1, name2, diff(text1, text2))
}
- ts.fatalf("%s and %s differ", name1, name2)
+ switch want {
+ case failure:
+ if eq {
+ ts.fatalf("%s and %s do not differ", name1, name2)
+ }
+ case success:
+ if !eq {
+ ts.fatalf("%s and %s differ", name1, name2)
+ }
+ case successOrFailure:
+ if eq {
+ fmt.Fprintf(&ts.log, "%s and %s do not differ\n", name1, name2)
+ } else {
+ fmt.Fprintf(&ts.log, "%s and %s differ\n", name1, name2)
+ }
+ default:
+ ts.fatalf("unsupported: %v cmp", want)
+ }
}
// cp copies files, maybe eventually directories.
@@ -841,6 +851,16 @@
}
}
+func (ts *testScript) cmdMv(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v mv", want)
+ }
+ if len(args) != 2 {
+ ts.fatalf("usage: mv old new")
+ }
+ ts.check(os.Rename(ts.mkabs(args[0]), ts.mkabs(args[1])))
+}
+
// rm removes files or directories.
func (ts *testScript) cmdRm(want simpleStatus, args []string) {
if want != success {
@@ -884,7 +904,7 @@
tmpl := "{{if .Error}}{{.ImportPath}}: {{.Error.Err}}{{else}}"
switch want {
case failure:
- tmpl += "{{if .Stale}}{{.ImportPath}} is unexpectedly stale{{end}}"
+ tmpl += "{{if .Stale}}{{.ImportPath}} is unexpectedly stale: {{.StaleReason}}{{end}}"
case success:
tmpl += "{{if not .Stale}}{{.ImportPath}} is unexpectedly NOT stale{{end}}"
default:
diff --git a/src/cmd/go/testdata/script/README b/src/cmd/go/testdata/script/README
index 2b55fa8..b2a7fd1 100644
--- a/src/cmd/go/testdata/script/README
+++ b/src/cmd/go/testdata/script/README
@@ -110,14 +110,15 @@
Change the permissions of the files or directories named by the path arguments
to be equal to perm. Only numerical permissions are supported.
-- cmp file1 file2
- Check that the named files have the same content.
+- [! | ?] cmp file1 file2
+ Check that the named files have (or do not have) the same content.
By convention, file1 is the actual data and file2 the expected data.
File1 can be "stdout" or "stderr" to use the standard output or standard error
from the most recent exec or go command.
- (If the files have differing content, the failure prints a diff.)
+ (If the file contents differ and the command is not negated,
+ the failure prints a diff.)
-- cmpenv file1 file2
+- [! | ?] cmpenv file1 file2
Like cmp, but environment variables are substituted in the file contents
before the comparison. For example, $GOOS is replaced by the target GOOS.
@@ -163,6 +164,10 @@
- mkdir path...
Create the listed directories, if they do not already exists.
+- mv path1 path2
+ Rename path1 to path2. OS-specific restrictions may apply when path1 and path2
+ are in different directories.
+
- rm file...
Remove the listed files or directories.
diff --git a/src/cmd/go/testdata/script/build_internal.txt b/src/cmd/go/testdata/script/build_internal.txt
index 25aa18c..5b786f2 100644
--- a/src/cmd/go/testdata/script/build_internal.txt
+++ b/src/cmd/go/testdata/script/build_internal.txt
@@ -10,8 +10,10 @@
# Test internal packages outside GOROOT are respected
cd ../testinternal2
+env GO111MODULE=off
! go build -v .
stderr 'p\.go:3:8: use of internal package .*internal/w not allowed'
+env GO111MODULE=''
[gccgo] skip # gccgo does not have GOROOT
cd ../testinternal
diff --git a/src/cmd/go/testdata/script/build_issue48319.txt b/src/cmd/go/testdata/script/build_issue48319.txt
index f58a5fa..3979247 100644
--- a/src/cmd/go/testdata/script/build_issue48319.txt
+++ b/src/cmd/go/testdata/script/build_issue48319.txt
@@ -1,50 +1,33 @@
+# Regression test for https://go.dev/issue/48319:
+# cgo builds should not include debug information from a stale GOROOT_FINAL.
+
[short] skip
[!cgo] skip
+[windows] skip # The Go Windows builders have an extremely out-of-date gcc that does not support reproducible builds; see https://go.dev/issue/50824.
-# Set up fresh GOCACHE
+# This test is sensitive to cache invalidation,
+# so use a separate build cache that we can control.
env GOCACHE=$WORK/gocache
mkdir $GOCACHE
-# 1. unset GOROOT_FINAL, Build a simple binary with cgo by origin go.
-# The DW_AT_comp_dir of runtime/cgo should have a prefix with origin goroot.
-env GOROOT_FINAL=
-# If using "go run", it is no debuginfo in binary. So use "go build".
-# And we can check the stderr to judge if the cache of "runtime/cgo"
-# was used or not.
-go build -o binary.exe
-exec ./binary.exe $TESTGO_GOROOT
-stdout 'cgo DW_AT_comp_dir is right in binary'
+# Build a binary using a specific value of GOROOT_FINAL.
+env GOROOT_FINAL=$WORK${/}goroot1
+go build -o main.exe
+mv main.exe main1.exe
+# Now clean the cache and build using a different GOROOT_FINAL.
+# The resulting binaries should differ in their debug metadata.
+go clean -cache
+env GOROOT_FINAL=$WORK${/}goroot2
+go build -o main.exe
+mv main.exe main2.exe
+! cmp main2.exe main1.exe
-# 2. GOROOT_FINAL will be changed, the runtime/cgo will be rebuild.
-env GOROOT_FINAL=$WORK/gorootfinal
-go build -x -o binary.exe
-stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
-exec ./binary.exe $GOROOT_FINAL
-stdout 'cgo DW_AT_comp_dir is right in binary'
-
-
-[!symlink] skip
-
-# Symlink the compiler to another path
-env GOROOT=$WORK/goroot
-symlink $GOROOT -> $TESTGO_GOROOT
-
-# 3. GOROOT_FINAL is same with 2, build with the other go
-# the runtime/cgo will not be rebuild.
-go build -x -o binary.exe
-! stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
-exec ./binary.exe $GOROOT_FINAL
-stdout 'cgo DW_AT_comp_dir is right in binary'
-
-
-# 4. unset GOROOT_FINAL, build with the other go
-# the runtime/cgo will be rebuild.
-env GOROOT_FINAL=
-go build -x -o binary.exe
-stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
-exec ./binary.exe $GOROOT
-stdout 'cgo DW_AT_comp_dir is right in binary'
+# Set GOROOT_FINAL back to the first value.
+# If the build is properly reproducible, the two binaries should match.
+env GOROOT_FINAL=$WORK${/}goroot1
+go build -o main.exe
+cmp -q main.exe main1.exe
-- go.mod --
module main
@@ -54,100 +37,11 @@
package main
import "C"
-import (
- "debug/dwarf"
- "fmt"
- "log"
- "os"
- "path/filepath"
- "strings"
-)
+
+import "runtime"
var _ C.int
func main() {
- dwarfData, err := readDWARF(os.Args[0])
- if err != nil {
- log.Fatal(err)
- }
- goroot := filepath.Join(os.Args[1], "src")
- dwarfReader := dwarfData.Reader()
- cgopackage := filepath.Join("runtime", "cgo")
- var hascgo bool
- for {
- e, err := dwarfReader.Next()
- if err != nil {
- log.Fatal(err)
- }
- if e == nil {
- break
- }
- field := e.AttrField(dwarf.AttrCompDir)
- if field == nil {
- continue
- }
- compdir := field.Val.(string)
- if strings.HasSuffix(compdir, cgopackage) {
- hascgo = true
- if !strings.HasPrefix(compdir, goroot) {
- fmt.Printf("cgo DW_AT_comp_dir %s contains incorrect path in binary.\n", compdir)
- return
- }
- }
- }
- if hascgo {
- fmt.Println("cgo DW_AT_comp_dir is right in binary")
- } else {
- fmt.Println("binary does not contain cgo")
- }
-}
--- read_darwin.go --
-package main
-
-import (
- "debug/dwarf"
- "debug/macho"
-)
-
-func readDWARF(exePath string) (*dwarf.Data, error) {
- machoFile, err := macho.Open(exePath)
- if err != nil {
- return nil, err
- }
- defer machoFile.Close()
- return machoFile.DWARF()
-}
--- read_elf.go --
-// +build android dragonfly freebsd illumos linux netbsd openbsd solaris
-
-package main
-
-import (
- "debug/dwarf"
- "debug/elf"
-)
-
-func readDWARF(exePath string) (*dwarf.Data, error) {
- elfFile, err := elf.Open(exePath)
- if err != nil {
- return nil, err
- }
- defer elfFile.Close()
- return elfFile.DWARF()
-}
--- read_windows.go --
-package main
-
-import (
- "debug/dwarf"
- "debug/pe"
-)
-
-func readDWARF(exePath string) (*dwarf.Data, error) {
- peFile, err := pe.Open(exePath)
- if err != nil {
- return nil, err
- }
- defer peFile.Close()
- return peFile.DWARF()
+ println(runtime.GOROOT())
}
diff --git a/src/cmd/go/testdata/script/cgo_stale_precompiled.txt b/src/cmd/go/testdata/script/cgo_stale_precompiled.txt
new file mode 100644
index 0000000..80ed751
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_stale_precompiled.txt
@@ -0,0 +1,28 @@
+# Regression test for https://go.dev/issue/47215 and https://go.dev/issue/50183:
+# A mismatched $GOROOT_FINAL or missing $CC caused the C dependencies of the net
+# package to appear stale, and it could not be rebuilt due to a missing $CC.
+
+[!cgo] skip
+
+# This test may start with the runtime/cgo package already stale.
+# Explicitly rebuild it to ensure that it is cached.
+# (See https://go.dev/issue/50892.)
+#
+# If running in non-short mode, explicitly vary CGO_CFLAGS
+# as a control case (to ensure that our regexps do catch rebuilds).
+
+[!short] env GOCACHE=$WORK/cache
+[!short] env CGO_CFLAGS=-DTestScript_cgo_stale_precompiled=true
+go build -x runtime/cgo
+[!short] stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
+
+# https://go.dev/issue/47215: a missing $(go env CC) caused the precompiled net to be stale.
+[!plan9] env PATH='' # Guaranteed not to include $(go env CC)!
+[plan9] env path=''
+go build -x runtime/cgo
+! stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
+
+# https://go.dev/issue/50183: a mismatched GOROOT_FINAL caused net to be stale.
+env GOROOT_FINAL=$WORK${/}goroot
+go build -x runtime/cgo
+! stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
diff --git a/src/cmd/go/testdata/script/list_cgo_compiled_importmap.txt b/src/cmd/go/testdata/script/list_cgo_compiled_importmap.txt
index 3d68ef3..30effb1 100644
--- a/src/cmd/go/testdata/script/list_cgo_compiled_importmap.txt
+++ b/src/cmd/go/testdata/script/list_cgo_compiled_importmap.txt
@@ -12,7 +12,7 @@
env GOFLAGS=-tags=netcgo # Force net to use cgo even on Windows.
-# "runtime/cgo [runtime.test]" appears in the the test dependencies of "runtime",
+# "runtime/cgo [runtime.test]" appears in the test dependencies of "runtime",
# because "runtime/cgo" itself depends on "runtime"
go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .Imports}}{{end}}' runtime
diff --git a/src/cmd/go/testdata/script/mod_download_partial.txt b/src/cmd/go/testdata/script/mod_download_partial.txt
index 3a02fcd..617b1fd 100644
--- a/src/cmd/go/testdata/script/mod_download_partial.txt
+++ b/src/cmd/go/testdata/script/mod_download_partial.txt
@@ -15,12 +15,13 @@
go mod verify
# 'go list' should not load packages from the directory.
-# NOTE: the message "directory $dir outside available modules" is reported
-# for directories not in the main module, active modules in the module cache,
-# or local replacements. In this case, the directory is in the right place,
-# but it's incomplete, so 'go list' acts as if it's not an active module.
+# NOTE: the message "directory $dir outside main module or its selected dependencies"
+# is reported for directories not in the main module, active modules in the
+# module cache, or local replacements. In this case, the directory is in the
+# right place, but it's incomplete, so 'go list' acts as if it's not an
+# active module.
! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
-stderr 'outside available modules'
+stderr 'outside main module or its selected dependencies'
# 'go list -m' should not print the directory.
go list -m -f '{{.Dir}}' rsc.io/quote
diff --git a/src/cmd/go/testdata/script/mod_fs_patterns.txt b/src/cmd/go/testdata/script/mod_fs_patterns.txt
index a20fefd..276d04e 100644
--- a/src/cmd/go/testdata/script/mod_fs_patterns.txt
+++ b/src/cmd/go/testdata/script/mod_fs_patterns.txt
@@ -51,11 +51,11 @@
# a package path.
cd ../badat/bad@
! go list .
-stderr 'directory . outside available modules'
+stderr 'directory . outside main module or its selected dependencies'
! go list $PWD
-stderr 'directory . outside available modules'
+stderr 'directory . outside main module or its selected dependencies'
! go list $PWD/...
-stderr 'directory . outside available modules'
+stderr 'directory . outside main module or its selected dependencies'
-- x/go.mod --
module m
diff --git a/src/cmd/go/testdata/script/mod_go_version_missing.txt b/src/cmd/go/testdata/script/mod_go_version_missing.txt
index d704816..2159a1e 100644
--- a/src/cmd/go/testdata/script/mod_go_version_missing.txt
+++ b/src/cmd/go/testdata/script/mod_go_version_missing.txt
@@ -27,7 +27,7 @@
! go list -mod=vendor all
! stderr '^go: inconsistent vendoring'
-stderr 'cannot find package "\." in:\n\t.*[/\\]vendor[/\\]example.com[/\\]badedit$'
+stderr 'cannot find package "vendor/example.com/badedit" in:\n\t.*[/\\]vendor[/\\]example.com[/\\]badedit$'
# When we set -mod=mod, the go version should be updated immediately,
# to the current version, converting the requirements from eager to lazy.
diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt
index 428b8aa..8385b08 100644
--- a/src/cmd/go/testdata/script/mod_invalid_version.txt
+++ b/src/cmd/go/testdata/script/mod_invalid_version.txt
@@ -194,10 +194,10 @@
go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible
cd outside
! go list -m github.com/pierrec/lz4
-stderr 'go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
+stderr '^go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
cd ..
! go list -m github.com/pierrec/lz4
-stderr 'github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
+stderr '^go: github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
# A +incompatible pseudo-version is valid for a revision of the module
# that lacks a go.mod file.
@@ -222,7 +222,7 @@
# not resolve to a pseudo-version with a different major version.
cp go.mod.orig go.mod
! go get github.com/pierrec/lz4@v2.0.8
-stderr 'go: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2'
+stderr 'go: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
# An invalid +incompatible suffix for a canonical version should error out,
# not resolve to a pseudo-version.
@@ -233,10 +233,10 @@
go mod edit -require github.com/pierrec/lz4@v2.0.8+incompatible
cd outside
! go list -m github.com/pierrec/lz4
-stderr 'github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
+stderr '^go: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
cd ..
! go list -m github.com/pierrec/lz4
-stderr 'github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
+stderr '^go: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
-- go.mod.orig --
module example.com
diff --git a/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt b/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt
index b08713d..896bbab 100644
--- a/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt
+++ b/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt
@@ -1,6 +1,7 @@
env GO111MODULE=on
[short] skip
+[!cgo] skip
# Regression test for golang.org/issue/29667:
# spurious 'failed to cache compiled Go files' errors.
diff --git a/src/cmd/go/testdata/script/mod_list_dir.txt b/src/cmd/go/testdata/script/mod_list_dir.txt
index 7ad65ff..157d3b6 100644
--- a/src/cmd/go/testdata/script/mod_list_dir.txt
+++ b/src/cmd/go/testdata/script/mod_list_dir.txt
@@ -24,7 +24,7 @@
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.1
stdout '^rsc.io/sampler$'
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0
-stderr 'outside available modules'
+stderr 'outside main module or its selected dependencies'
-- go.mod --
module x
diff --git a/src/cmd/go/testdata/script/mod_list_replace_dir.txt b/src/cmd/go/testdata/script/mod_list_replace_dir.txt
index eac5ca7..b446543 100644
--- a/src/cmd/go/testdata/script/mod_list_replace_dir.txt
+++ b/src/cmd/go/testdata/script/mod_list_replace_dir.txt
@@ -9,7 +9,7 @@
go mod download rsc.io/quote@v1.5.2
! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
-stderr '^directory ..[/\\]pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2 outside available modules$'
+stderr '^directory ..[/\\]pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2 outside main module or its selected dependencies$'
go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.1
stdout 'rsc.io/quote'
diff --git a/src/cmd/go/testdata/script/run_issue51125.txt b/src/cmd/go/testdata/script/run_issue51125.txt
new file mode 100644
index 0000000..8fa4486
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_issue51125.txt
@@ -0,0 +1,54 @@
+# Regression test for https://go.dev/issue/51125:
+# Relative import paths (a holdover from GOPATH) were accidentally allowed in module mode.
+
+cd $WORK
+
+# Relative imports should not be allowed with a go.mod file.
+
+! go run driver.go
+stderr '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+
+go list -e -f '{{with .Error}}{{.}}{{end}}' -deps driver.go
+stdout '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+! stderr .
+
+
+# Relative imports should not be allowed in module mode even without a go.mod file.
+rm go.mod
+
+! go run driver.go
+stderr '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+
+go list -e -f '{{with .Error}}{{.}}{{end}}' -deps driver.go
+stdout '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
+! stderr .
+
+
+# In GOPATH mode, they're still allowed (but only outside of GOPATH/src).
+env GO111MODULE=off
+
+[!short] go run driver.go
+
+go list -deps driver.go
+
+
+-- $WORK/go.mod --
+module example
+
+go 1.17
+-- $WORK/driver.go --
+package main
+
+import "./mypkg"
+
+func main() {
+ mypkg.MyFunc()
+}
+-- $WORK/mypkg/code.go --
+package mypkg
+
+import "fmt"
+
+func MyFunc() {
+ fmt.Println("Hello, world!")
+}
diff --git a/src/cmd/go/testdata/script/run_work_versioned.txt b/src/cmd/go/testdata/script/run_work_versioned.txt
new file mode 100644
index 0000000..eb0f22d
--- /dev/null
+++ b/src/cmd/go/testdata/script/run_work_versioned.txt
@@ -0,0 +1,16 @@
+[short] skip
+go run example.com/printversion@v0.1.0
+stdout '^main is example.com/printversion v0.1.0$'
+
+-- go.work --
+go 1.18
+
+use (
+ .
+)
+-- go.mod --
+module example
+
+go 1.18
+
+require example.com/printversion v1.0.0
diff --git a/src/cmd/go/testdata/script/test_fuzz_cov.txt b/src/cmd/go/testdata/script/test_fuzz_cov.txt
new file mode 100644
index 0000000..05b6348
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_cov.txt
@@ -0,0 +1,33 @@
+# Test that coverage instrumentation is working. Without the instrumentation
+# it is _extremely_ unlikely that the fuzzer would produce this particular
+# input in any reasonable amount of time.
+
+[short] skip
+[!fuzz-instrumented] skip
+
+! go test -fuzz=FuzzCov
+! stderr 'cov instrumentation working'
+
+-- go.mod --
+module test
+
+-- cov_test.go --
+package cov
+
+import "testing"
+
+func FuzzCov(f *testing.F) {
+ f.Fuzz(func(t *testing.T, b []byte) {
+ if len(b) == 8 &&
+ b[0] == 'h' &&
+ b[1] == 'e' &&
+ b[2] == 'l' &&
+ b[3] == 'l' &&
+ b[4] == 'o' &&
+ b[5] == ' ' &&
+ b[6] == ':' &&
+ b[7] == ')' {
+ panic("cov instrumentation working")
+ }
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_dup_cache.txt b/src/cmd/go/testdata/script/test_fuzz_dup_cache.txt
new file mode 100644
index 0000000..52d44a2
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_dup_cache.txt
@@ -0,0 +1,52 @@
+[!fuzz] skip
+[short] skip
+
+# This test checks that cached corpus loading properly handles duplicate entries (this can
+# happen when a f.Add value has a duplicate entry in the cached corpus.) Duplicate entries
+# should be discarded, and the rest of the cache should be loaded as normal.
+
+env GOCACHE=$WORK/cache
+env GODEBUG=fuzzdebug=1
+
+mkdir -p $GOCACHE/fuzz/fuzztest/FuzzTarget
+go run ./populate $GOCACHE/fuzz/fuzztest/FuzzTarget
+
+go test -fuzz=FuzzTarget -fuzztime=10x .
+stdout 'entries: 5'
+
+-- go.mod --
+module fuzztest
+
+go 1.17
+
+-- fuzz_test.go --
+package fuzz
+
+import "testing"
+
+func FuzzTarget(f *testing.F) {
+ f.Add(int(0))
+ f.Fuzz(func(t *testing.T, _ int) {})
+}
+
+-- populate/main.go --
+package main
+
+import (
+ "path/filepath"
+ "fmt"
+ "os"
+)
+
+func main() {
+ for i := 0; i < 10; i++ {
+ b := byte(0)
+ if i > 5 {
+ b = byte(i)
+ }
+ tmpl := "go test fuzz v1\nint(%d)\n"
+ if err := os.WriteFile(filepath.Join(os.Args[1], fmt.Sprint(i)), []byte(fmt.Sprintf(tmpl, b)), 0777); err != nil {
+ panic(err)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt
new file mode 100644
index 0000000..571bf75
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt
@@ -0,0 +1,84 @@
+# Test that minimization doesn't use dirty coverage snapshots when it
+# is unable to actually minimize the input. We do this by checking that
+# a expected value appears in the cache. If a dirty coverage map is used
+# (i.e. the coverage map generated during the last minimization step,
+# rather than the map provided with the initial input) then this value
+# is unlikely to appear in the cache, since the map generated during
+# the last minimization step should not increase the coverage.
+
+[short] skip
+[!fuzz-instrumented] skip
+
+env GOCACHE=$WORK/gocache
+go test -fuzz=FuzzCovMin -fuzztime=25s -test.fuzzcachedir=$GOCACHE/fuzz
+go run check_file/main.go $GOCACHE/fuzz/FuzzCovMin abcd
+
+-- go.mod --
+module test
+
+-- covmin_test.go --
+package covmin
+
+import "testing"
+
+func FuzzCovMin(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ if len(data) >= 4 && data[0] == 'a' && data[1] == 'b' && data[2] == 'c' && data[3] == 'd' {
+ return
+ }
+ })
+}
+
+-- check_file/main.go --
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strconv"
+)
+
+func checkFile(name, expected string) (bool, error) {
+ data, err := os.ReadFile(name)
+ if err != nil {
+ return false, err
+ }
+ for _, line := range bytes.Split(data, []byte("\n")) {
+ m := valRe.FindSubmatch(line)
+ if m == nil {
+ continue
+ }
+ fmt.Println(strconv.Unquote(string(m[1])))
+ if s, err := strconv.Unquote(string(m[1])); err != nil {
+ return false, err
+ } else if s == expected {
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
+var valRe = regexp.MustCompile(`^\[\]byte\(([^)]+)\)$`)
+
+func main() {
+ dir, expected := os.Args[1], os.Args[2]
+ ents, err := os.ReadDir(dir)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ for _, ent := range ents {
+ name := filepath.Join(dir, ent.Name())
+ if good, err := checkFile(name, expected); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ } else if good {
+ os.Exit(0)
+ }
+ }
+ fmt.Fprintln(os.Stderr, "input over minimized")
+ os.Exit(1)
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
index 5d0de17..a09e85b 100644
--- a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
@@ -127,19 +127,8 @@
if bytes.Equal(buf, seed) {
return
}
- if n := sum(buf); n < 0 {
- t.Error("sum cannot be negative")
- }
})
}
-
-func sum(buf []byte) int {
- n := 0
- for _, b := range buf {
- n += int(b)
- }
- return n
-}
-- check_testdata/check_testdata.go --
//go:build ignore
// +build ignore
diff --git a/src/cmd/go/testdata/script/test_fuzz_parallel.txt b/src/cmd/go/testdata/script/test_fuzz_parallel.txt
index 1795e0b..e632520 100644
--- a/src/cmd/go/testdata/script/test_fuzz_parallel.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_parallel.txt
@@ -13,6 +13,13 @@
! go test -run=FuzzMutate -fuzz=FuzzMutate
exists testdata/fuzz/FuzzMutate
+# Testdata should now contain a corpus entry which will fail FuzzMutate.
+# Run the test without fuzzing, setting -parallel to different values to make
+# sure it fails, and doesn't hang.
+! go test -run=FuzzMutate -parallel=1
+! go test -run=FuzzMutate -parallel=2
+! go test -run=FuzzMutate -parallel=4
+
-- go.mod --
module fuzz_parallel
diff --git a/src/cmd/go/testdata/script/test_fuzz_return.txt b/src/cmd/go/testdata/script/test_fuzz_return.txt
new file mode 100644
index 0000000..63275aa
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_return.txt
@@ -0,0 +1,19 @@
+[short] skip
+
+! go test .
+stdout '^panic: testing: fuzz target must not return a value \[recovered\]$'
+
+-- go.mod --
+module test
+go 1.18
+-- x_test.go --
+package test
+
+import "testing"
+
+func FuzzReturnErr(f *testing.F) {
+ f.Add("hello, validation!")
+ f.Fuzz(func(t *testing.T, in string) string {
+ return in
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_fuzz_test_race.txt b/src/cmd/go/testdata/script/test_fuzz_test_race.txt
new file mode 100644
index 0000000..9d39cd6
--- /dev/null
+++ b/src/cmd/go/testdata/script/test_fuzz_test_race.txt
@@ -0,0 +1,39 @@
+# Test that when both race detection and coverage instrumentation are enabled,
+# and seed values are being executed, the race detector isn't mistakenly
+# triggered.
+
+[short] skip
+[!fuzz] skip
+[!race] skip
+
+# Test with coverage instrumentation enabled (-fuzz) and race instrumentation
+# but without actually fuzzing the target (by using a non-matching pattern)
+go test -fuzz=xxx -race -v
+! stderr 'race detected during execution of test'
+
+# Test with just race instrumentation enabled
+go test -race -v
+! stderr 'race detected during execution of test'
+
+# Test with coverage and race instrumentation enabled, and a matching fuzz
+# pattern
+go test -fuzz=FuzzRace -race -v -fuzztime=200x
+! stderr 'race detected during execution of test'
+
+-- go.mod --
+module test
+
+-- race_test.go --
+package race
+
+import "testing"
+
+func FuzzRace(f *testing.F) {
+ for i := 0; i < 100; i++ {
+ f.Add(i)
+ }
+
+ f.Fuzz(func(t *testing.T, i int) {
+ t.Parallel()
+ })
+}
diff --git a/src/cmd/go/testdata/script/test_relative_cmdline.txt b/src/cmd/go/testdata/script/test_relative_cmdline.txt
index 2f9c80f..96f7b87 100644
--- a/src/cmd/go/testdata/script/test_relative_cmdline.txt
+++ b/src/cmd/go/testdata/script/test_relative_cmdline.txt
@@ -1,5 +1,7 @@
# Relative imports in command line package
+env GO111MODULE=off
+
# Run tests outside GOPATH.
env GOPATH=$WORK/tmp
@@ -47,4 +49,4 @@
if F() != p2.F() {
t.Fatal(F())
}
-}
\ No newline at end of file
+}
diff --git a/src/cmd/go/testdata/script/version_buildvcs_git.txt b/src/cmd/go/testdata/script/version_buildvcs_git.txt
index 86d1de0..4470687 100644
--- a/src/cmd/go/testdata/script/version_buildvcs_git.txt
+++ b/src/cmd/go/testdata/script/version_buildvcs_git.txt
@@ -111,7 +111,7 @@
go list -x ./...
stdout -count=3 '^example.com'
stderr -count=1 '^git status'
-stderr -count=1 '^git show'
+stderr -count=1 '^git -c log.showsignature=false show'
-- $WORK/fakebin/git --
#!/bin/sh
diff --git a/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt b/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt
new file mode 100644
index 0000000..dcf97d7
--- /dev/null
+++ b/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt
@@ -0,0 +1,105 @@
+# This test checks that VCS information is stamped into Go binaries even when
+# the current commit is signed and the use has configured git to display commit
+# signatures.
+
+[!exec:git] skip
+[!exec:gpg] skip
+[short] skip
+env GOBIN=$GOPATH/bin
+env GNUPGHOME=$WORK/.gpupg
+mkdir $GNUPGHOME
+chmod 0700 $GNUPGHOME
+
+# Create GPG key
+exec gpg --batch --passphrase '' --quick-generate-key gopher@golang.org
+exec gpg --list-secret-keys --with-colons gopher@golang.org
+cp stdout keyinfo.txt
+go run extract_key_id.go keyinfo.txt
+cp stdout keyid.txt
+
+# Initialize repo
+cd repo/
+exec git init
+exec git config user.email gopher@golang.org
+exec git config user.name 'J.R. Gopher'
+exec git config --add log.showSignature true
+go run ../configure_signing_key.go ../keyid.txt
+
+# Create signed commit
+cd a
+exec git add -A
+exec git commit -m 'initial commit' --gpg-sign
+exec git log
+
+# Verify commit signature does not interfere with versioning
+go install
+go version -m $GOBIN/a
+stdout '^\tbuild\tvcs\.revision='
+stdout '^\tbuild\tvcs\.time='
+stdout '^\tbuild\tvcs\.modified=false$'
+
+-- repo/README --
+Far out in the uncharted backwaters of the unfashionable end of the western
+spiral arm of the Galaxy lies a small, unregarded yellow sun.
+-- repo/a/go.mod --
+module example.com/a
+
+go 1.18
+-- repo/a/a.go --
+package main
+
+func main() {}
+
+-- extract_key_id.go --
+package main
+
+import "fmt"
+import "io/ioutil"
+import "os"
+import "strings"
+
+func main() {
+ err := run(os.Args[1])
+ if err != nil {
+ panic(err)
+ }
+}
+
+func run(keyInfoFilePath string) error {
+ contents, err := ioutil.ReadFile(keyInfoFilePath)
+ if err != nil {
+ return err
+ }
+ lines := strings.Split(string(contents), "\n")
+ for _, line := range lines {
+ fields := strings.Split(line, ":")
+ if fields[0] == "sec" {
+ fmt.Print(fields[4])
+ return nil
+ }
+ }
+ return fmt.Errorf("key ID not found in: %s", keyInfoFilePath)
+}
+
+-- configure_signing_key.go --
+package main
+
+import "io/ioutil"
+import "os"
+import "os/exec"
+
+func main() {
+ err := run(os.Args[1])
+ if err != nil {
+ panic(err)
+ }
+}
+
+func run(keyIdFilePath string) error {
+ keyId, err := ioutil.ReadFile(keyIdFilePath)
+ if err != nil {
+ return err
+ }
+ gitCmd := exec.Command("git", "config", "user.signingKey", string(keyId))
+ return gitCmd.Run()
+}
diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt
index cbb3746..fa1558f 100644
--- a/src/cmd/go/testdata/script/work.txt
+++ b/src/cmd/go/testdata/script/work.txt
@@ -4,7 +4,7 @@
! stdout .
go work init ./a ./b
-cmp go.work go.work.want
+cmpenv go.work go.work.want
go env GOWORK
stdout '^'$WORK'(\\|/)gopath(\\|/)src(\\|/)go.work$'
@@ -32,7 +32,9 @@
go list -mod=readonly all
! go list -mod=mod all
stderr '^go: -mod may only be set to readonly when in workspace mode'
-go list -mod=mod -workfile=off all
+env GOWORK=off
+go list -mod=mod all
+env GOWORK=
# Test that duplicates in the use list return an error
cp go.work go.work.backup
@@ -53,7 +55,9 @@
# This exercises the code that determines which module command-line-arguments
# belongs to.
go list ./b/main.go
-go build -n -workfile=off -o foo foo.go
+env GOWORK=off
+go build -n -o foo foo.go
+env GOWORK=
go build -n -o foo foo.go
-- go.work.dup --
@@ -65,7 +69,7 @@
../src/a
)
-- go.work.want --
-go 1.18
+go $goversion
use (
./a
diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt
index fd04bbd..278afb7 100644
--- a/src/cmd/go/testdata/script/work_edit.txt
+++ b/src/cmd/go/testdata/script/work_edit.txt
@@ -1,10 +1,10 @@
# Test editing go.work files.
go work init m
-cmp go.work go.work.want_initial
+cmpenv go.work go.work.want_initial
go work edit -use n
-cmp go.work go.work.want_use_n
+cmpenv go.work go.work.want_use_n
go work edit -go 1.18
cmp go.work go.work.want_go_118
@@ -30,7 +30,8 @@
go work edit -json -go 1.19 -use b -dropuse c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0
cmp stdout go.work.want_json
-go work edit -print -fmt -workfile $GOPATH/src/unformatted
+env GOWORK=$GOPATH/src/unformatted
+go work edit -print -fmt
cmp stdout formatted
-- m/go.mod --
@@ -38,11 +39,11 @@
go 1.18
-- go.work.want_initial --
-go 1.18
+go $goversion
use ./m
-- go.work.want_use_n --
-go 1.18
+go $goversion
use (
./m
diff --git a/src/cmd/go/testdata/script/work_env.txt b/src/cmd/go/testdata/script/work_env.txt
index ec3d3be..511bb4e 100644
--- a/src/cmd/go/testdata/script/work_env.txt
+++ b/src/cmd/go/testdata/script/work_env.txt
@@ -13,6 +13,10 @@
go env GOWORK
stdout 'go.work'
+env GOWORK='off'
+go env GOWORK
+stdout 'off'
+
! go env -w GOWORK=off
stderr '^go: GOWORK cannot be modified$'
diff --git a/src/cmd/go/testdata/script/work_gowork.txt b/src/cmd/go/testdata/script/work_gowork.txt
new file mode 100644
index 0000000..1cfbf0c
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_gowork.txt
@@ -0,0 +1,24 @@
+env GOWORK=stop.work
+! go list a # require absolute path
+! stderr panic
+env GOWORK=doesnotexist
+! go list a
+! stderr panic
+
+env GOWORK=$GOPATH/src/stop.work
+go list -n a
+go build -n a
+go test -n a
+
+-- stop.work --
+go 1.18
+
+use ./a
+-- a/a.go --
+package a
+-- a/a_test.go --
+package a
+-- a/go.mod --
+module a
+
+go 1.18
\ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_init_gowork.txt b/src/cmd/go/testdata/script/work_init_gowork.txt
new file mode 100644
index 0000000..55ac99b
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_init_gowork.txt
@@ -0,0 +1,19 @@
+# Test that the GOWORK environment variable flag is used by go work init.
+
+! exists go.work
+go work init
+exists go.work
+
+env GOWORK=$GOPATH/src/foo/foo.work
+! exists foo/foo.work
+go work init
+exists foo/foo.work
+
+env GOWORK=
+cd foo/bar
+! go work init
+stderr 'already exists'
+
+# Create directories to make go.work files in.
+-- foo/dummy.txt --
+-- foo/bar/dummy.txt --
diff --git a/src/cmd/go/testdata/script/work_init_path.txt b/src/cmd/go/testdata/script/work_init_path.txt
new file mode 100644
index 0000000..e397788
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_init_path.txt
@@ -0,0 +1,17 @@
+# Regression test for https://go.dev/issue/51448.
+# 'go work init . foo/bar' should produce a go.work file
+# with the same paths as 'go work init; go work use -r .'.
+
+go work init . foo/bar
+mv go.work go.work.init
+
+go work init
+go work use -r .
+cmp go.work go.work.init
+
+-- go.mod --
+module example
+go 1.18
+-- foo/bar/go.mod --
+module example
+go 1.18
diff --git a/src/cmd/go/testdata/script/work_install_submodule.txt b/src/cmd/go/testdata/script/work_install_submodule.txt
new file mode 100644
index 0000000..3d11717
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_install_submodule.txt
@@ -0,0 +1,36 @@
+# This is a regression test for golang.org/issue/50036
+# Don't check sums for other modules in the workspace.
+
+cd m/sub
+go install -n
+
+-- go.work --
+go 1.18
+
+use (
+ ./m
+ ./m/sub
+)
+-- m/go.mod --
+module example.com/m
+
+go 1.18
+
+-- m/m.go --
+package m
+
+func M() {}
+-- m/sub/go.mod --
+module example.com/m/sub
+
+go 1.18
+
+require example.com/m v1.0.0
+-- m/sub/main.go --
+package main
+
+import "example.com/m"
+
+func main() {
+ m.M()
+}
diff --git a/src/cmd/go/testdata/script/work_issue51204.txt b/src/cmd/go/testdata/script/work_issue51204.txt
new file mode 100644
index 0000000..d483002
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_issue51204.txt
@@ -0,0 +1,57 @@
+go work sync
+
+go list -f '{{.Dir}}' example.com/test
+stdout '^'$PWD${/}test'$'
+
+-- go.work --
+go 1.18
+
+use (
+ ./test2
+ ./test2/sub
+)
+-- test/go.mod --
+module example.com/test
+
+go 1.18
+-- test/file.go --
+package test
+
+func DoSomething() {
+}
+-- test2/go.mod --
+module example.com/test2
+
+go 1.18
+
+replace example.com/test => ../test
+
+require example.com/test v0.0.0-00010101000000-000000000000
+-- test2/file.go --
+package test2
+
+import (
+ "example.com/test"
+)
+
+func DoSomething() {
+ test.DoSomething()
+}
+-- test2/sub/go.mod --
+module example.com/test2/sub
+
+go 1.18
+
+replace example.com/test => ../../test
+
+require example.com/test v0.0.0
+-- test2/sub/file.go --
+package test2
+
+import (
+ "example.com/test"
+)
+
+func DoSomething() {
+ test.DoSomething()
+}
diff --git a/src/cmd/go/testdata/script/work_module_not_in_go_work.txt b/src/cmd/go/testdata/script/work_module_not_in_go_work.txt
new file mode 100644
index 0000000..23d908c
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_module_not_in_go_work.txt
@@ -0,0 +1,25 @@
+# This is a regression test for issue #49632.
+# The Go command should mention go.work if the user
+# tries to load a local package that's in a module
+# that's not in go.work and can't be resolved.
+
+! go list ./...
+stderr 'pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies'
+
+! go list ./a
+stderr 'directory a outside modules listed in go.work'
+
+-- go.work --
+go 1.18
+
+use ./b
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+-- a/a.go --
+package a
+-- b/go.mod --
+module example.com/b
+
+go 1.18
diff --git a/src/cmd/go/testdata/script/work_nowork.txt b/src/cmd/go/testdata/script/work_nowork.txt
new file mode 100644
index 0000000..b4c9b1d
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_nowork.txt
@@ -0,0 +1,20 @@
+! go work use
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+! go work use .
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+! go work edit
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+! go work edit -go=1.18
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+! go work sync
+stderr '^go: no go\.work file found\n\t\(run ''go work init'' first or specify path using GOWORK environment variable\)$'
+
+-- go.mod --
+module example
+go 1.18
+-- README.txt --
+There is no go.work file here.
diff --git a/src/cmd/go/testdata/script/work_prune_all.txt b/src/cmd/go/testdata/script/work_prune_all.txt
new file mode 100644
index 0000000..a7ad9c0
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_prune_all.txt
@@ -0,0 +1,176 @@
+# This test makes sure workspace mode's handling of the module graph
+# is compatible with module pruning. The graph we load from either of
+# the workspace modules should be the same, even if their graphs
+# don't overlap.
+#
+# This is the module graph in the test:
+#
+# example.com/p -> example.com/q v1.0.0
+# example.com/a -> example.com/b v1.0.0 -> example.com/q v1.1.0 -> example.com/w v1.0.0 -> example.com/x v1.0.0 -> example.com/y v1.0.0
+# |-> example.com/z v1.0.0 |-> example.com/z v1.1.0
+# |-> example.com/q v1.0.5 -> example.com/r v1.0.0
+# If we didn't load the whole graph and didn't load the dependencies of b
+# when loading p, we would end up loading q v1.0.0, rather than v1.1.0,
+# which is selected by MVS.
+
+go list -m all
+stdout 'example.com/w v1.0.0'
+stdout 'example.com/q v1.1.0'
+stdout 'example.com/z v1.1.0'
+stdout 'example.com/x v1.0.0'
+! stdout 'example.com/r'
+! stdout 'example.com/y'
+
+-- go.work --
+go 1.18
+
+use (
+ ./a
+ ./p
+)
+
+replace example.com/b v1.0.0 => ./b
+replace example.com/q v1.0.0 => ./q1_0_0
+replace example.com/q v1.0.5 => ./q1_0_5
+replace example.com/q v1.1.0 => ./q1_1_0
+replace example.com/r v1.0.0 => ./r
+replace example.com/w v1.0.0 => ./w
+replace example.com/x v1.0.0 => ./x
+replace example.com/y v1.0.0 => ./y
+replace example.com/z v1.0.0 => ./z1_0_0
+replace example.com/z v1.1.0 => ./z1_1_0
+
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+
+require example.com/b v1.0.0
+require example.com/z v1.0.0
+-- a/foo.go --
+package main
+
+import "example.com/b"
+
+func main() {
+ b.B()
+}
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+
+require example.com/q v1.1.0
+-- b/b.go --
+package b
+
+func B() {
+}
+-- p/go.mod --
+module example.com/p
+
+go 1.18
+
+require example.com/q v1.0.0
+
+replace example.com/q v1.0.0 => ../q1_0_0
+replace example.com/q v1.1.0 => ../q1_1_0
+-- p/main.go --
+package main
+
+import "example.com/q"
+
+func main() {
+ q.PrintVersion()
+}
+-- q1_0_0/go.mod --
+module example.com/q
+
+go 1.18
+-- q1_0_0/q.go --
+package q
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.0.0")
+}
+-- q1_0_5/go.mod --
+module example.com/q
+
+go 1.18
+
+require example.com/r v1.0.0
+-- q1_0_5/q.go --
+package q
+
+import _ "example.com/r"
+-- q1_1_0/go.mod --
+module example.com/q
+
+require example.com/w v1.0.0
+require example.com/z v1.1.0
+
+go 1.18
+-- q1_1_0/q.go --
+package q
+
+import _ "example.com/w"
+import _ "example.com/z"
+
+import "fmt"
+
+func PrintVersion() {
+ fmt.Println("version 1.1.0")
+}
+-- r/go.mod --
+module example.com/r
+
+go 1.18
+
+require example.com/r v1.0.0
+-- r/r.go --
+package r
+-- w/go.mod --
+module example.com/w
+
+go 1.18
+
+require example.com/x v1.0.0
+-- w/w.go --
+package w
+-- w/w_test.go --
+package w
+
+import _ "example.com/x"
+-- x/go.mod --
+module example.com/x
+
+go 1.18
+-- x/x.go --
+package x
+-- x/x_test.go --
+package x
+import _ "example.com/y"
+-- y/go.mod --
+module example.com/y
+
+go 1.18
+-- y/y.go --
+package y
+-- z1_0_0/go.mod --
+module example.com/z
+
+go 1.18
+
+require example.com/q v1.0.5
+-- z1_0_0/z.go --
+package z
+
+import _ "example.com/q"
+-- z1_1_0/go.mod --
+module example.com/z
+
+go 1.18
+-- z1_1_0/z.go --
+package z
diff --git a/src/cmd/go/testdata/script/work_replace_conflict.txt b/src/cmd/go/testdata/script/work_replace_conflict.txt
index 81d1fcb..7b71b0f 100644
--- a/src/cmd/go/testdata/script/work_replace_conflict.txt
+++ b/src/cmd/go/testdata/script/work_replace_conflict.txt
@@ -2,7 +2,7 @@
# overriding it in the go.work file.
! go list -m example.com/dep
-stderr 'go: conflicting replacements for example.com/dep@v1.0.0:\n\t./dep1\n\t./dep2\nuse "go work edit -replace example.com/dep@v1.0.0=\[override\]" to resolve'
+stderr 'go: conflicting replacements for example.com/dep@v1.0.0:\n\t'$PWD${/}'dep1\n\t'$PWD${/}'dep2\nuse "go work edit -replace example.com/dep@v1.0.0=\[override\]" to resolve'
go work edit -replace example.com/dep@v1.0.0=./dep1
go list -m example.com/dep
stdout 'example.com/dep v1.0.0 => ./dep1'
@@ -15,7 +15,7 @@
module example.com/m
require example.com/dep v1.0.0
-replace example.com/dep v1.0.0 => ./dep1
+replace example.com/dep v1.0.0 => ../dep1
-- m/m.go --
package m
@@ -28,7 +28,7 @@
module example.com/n
require example.com/dep v1.0.0
-replace example.com/dep v1.0.0 => ./dep2
+replace example.com/dep v1.0.0 => ../dep2
-- n/n.go --
package n
diff --git a/src/cmd/go/testdata/script/work_replace_main_module.txt b/src/cmd/go/testdata/script/work_replace_main_module.txt
new file mode 100644
index 0000000..b213764
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_replace_main_module.txt
@@ -0,0 +1,45 @@
+# Ensure that replaces of the main module in workspace modules
+# are ignored, and replaces in the go.work file are disallowed.
+# This tests against an issue where requirements of the
+# main module were being ignored because the main module
+# was replaced in a transitive dependency with another
+# version.
+
+go list example.com/dep
+
+cp replace_main_module.go.work go.work
+! go list example.com/dep
+stderr 'go: workspace module example.com/mainmoda is replaced at all versions in the go.work file. To fix, remove the replacement from the go.work file or specify the version at which to replace the module.'
+
+-- replace_main_module.go.work --
+go 1.18
+use (
+ ./mainmoda
+ ./mainmodb
+)
+replace example.com/mainmoda => ../mainmodareplacement
+-- go.work --
+go 1.18
+use (
+ ./mainmoda
+ ./mainmodb
+)
+-- mainmoda/go.mod --
+module example.com/mainmoda
+
+go 1.18
+
+require example.com/dep v1.0.0
+replace example.com/dep => ../dep
+
+-- dep/go.mod --
+module example.com/dep
+-- dep/dep.go --
+package dep
+-- mainmodb/go.mod --
+module example.com/mainmodb
+go 1.18
+replace example.com/mainmoda => ../mainmodareplacement
+-- mainmodareplacement/go.mod --
+module example.com/mainmoda
+go 1.18
\ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_sync_sum.txt b/src/cmd/go/testdata/script/work_sync_sum.txt
new file mode 100644
index 0000000..656fd31
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sync_sum.txt
@@ -0,0 +1,40 @@
+# Test that the sum file data state is properly reset between modules in
+# go work sync so that the sum file that's written is correct.
+# Exercises the fix to #50038.
+
+cp b/go.sum b/go.sum.want
+
+# As a sanity check, verify b/go.sum is tidy.
+cd b
+go mod tidy
+cd ..
+cmp b/go.sum b/go.sum.want
+
+# Run go work sync and verify it doesn't change b/go.sum.
+go work sync
+cmp b/go.sum b/go.sum.want
+
+-- b/go.sum --
+rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
+rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
+-- go.work --
+go 1.18
+use (
+ ./a
+ ./b
+)
+replace example.com/c => ./c
+-- a/go.mod --
+module example.com/a
+go 1.18
+require rsc.io/fortune v1.0.0
+-- a/a.go --
+package a
+import "rsc.io/fortune"
+-- b/go.mod --
+module example.com/b
+go 1.18
+require rsc.io/quote v1.0.0
+-- b/b.go --
+package b
+import _ "rsc.io/quote"
diff --git a/src/cmd/go/testdata/script/work_use.txt b/src/cmd/go/testdata/script/work_use.txt
index f5ea89c..12c8cec 100644
--- a/src/cmd/go/testdata/script/work_use.txt
+++ b/src/cmd/go/testdata/script/work_use.txt
@@ -14,16 +14,16 @@
go 1.18
use (
- foo
- foo/bar/baz
+ ./foo
+ ./foo/bar/baz
)
-- go.want_work_other --
go 1.18
use (
- foo
- foo/bar/baz
- other
+ ./foo
+ ./foo/bar/baz
+ ./other
)
-- foo/go.mod --
module foo
diff --git a/src/cmd/go/testdata/script/work_use_deleted.txt b/src/cmd/go/testdata/script/work_use_deleted.txt
new file mode 100644
index 0000000..b379cbc
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_deleted.txt
@@ -0,0 +1,22 @@
+go work use -r .
+cmp go.work go.work.want
+
+-- go.work --
+go 1.18
+
+use (
+ .
+ ./sub
+ ./sub/dir/deleted
+)
+-- go.work.want --
+go 1.18
+
+use ./sub/dir
+-- sub/README.txt --
+A go.mod file has been deleted from this directory.
+In addition, the entire subdirectory sub/dir/deleted
+has been deleted, along with sub/dir/deleted/go.mod.
+-- sub/dir/go.mod --
+module example/sub/dir
+go 1.18
diff --git a/src/cmd/go/testdata/script/work_use_dot.txt b/src/cmd/go/testdata/script/work_use_dot.txt
new file mode 100644
index 0000000..8f21042
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_dot.txt
@@ -0,0 +1,49 @@
+cp go.work go.work.orig
+
+# If the current directory contains a go.mod file,
+# 'go work use .' should add an entry for it.
+cd bar/baz
+go work use .
+cmp ../../go.work ../../go.work.rel
+
+# If the current directory lacks a go.mod file, 'go work use .'
+# should remove its entry.
+mv go.mod go.mod.bak
+go work use .
+cmp ../../go.work ../../go.work.orig
+
+# If the path is absolute, it should remain absolute.
+mv go.mod.bak go.mod
+go work use $PWD
+grep -count=1 '^use ' ../../go.work
+grep '^use ["]?'$PWD'["]?$' ../../go.work
+
+# An absolute path should replace an entry for the corresponding relative path
+# and vice-versa.
+go work use .
+cmp ../../go.work ../../go.work.rel
+go work use $PWD
+grep -count=1 '^use ' ../../go.work
+grep '^use ["]?'$PWD'["]?$' ../../go.work
+
+# If both the absolute and relative paths are named, 'go work use' should error
+# out: we don't know which one to use, and shouldn't add both because the
+# resulting workspace would contain a duplicate module.
+cp ../../go.work.orig ../../go.work
+! go work use $PWD .
+stderr '^go: already added "\./bar/baz" as "'$PWD'"$'
+cmp ../../go.work ../../go.work.orig
+
+
+-- go.mod --
+module example
+go 1.18
+-- go.work --
+go 1.18
+-- go.work.rel --
+go 1.18
+
+use ./bar/baz
+-- bar/baz/go.mod --
+module example/bar/baz
+go 1.18
diff --git a/src/cmd/go/testdata/script/work_use_issue50958.txt b/src/cmd/go/testdata/script/work_use_issue50958.txt
new file mode 100644
index 0000000..7a25531
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_issue50958.txt
@@ -0,0 +1,17 @@
+go work use -r .
+cmp go.work go.work.want
+
+-- go.mod --
+module example
+go 1.18
+-- go.work --
+go 1.18
+
+use sub
+-- go.work.want --
+go 1.18
+
+use .
+-- sub/README.txt --
+This directory no longer contains a go.mod file.
+
diff --git a/src/cmd/go/testdata/script/work_use_noargs.txt b/src/cmd/go/testdata/script/work_use_noargs.txt
new file mode 100644
index 0000000..ca05434
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use_noargs.txt
@@ -0,0 +1,11 @@
+# For now, 'go work use' requires arguments.
+# (Eventually, we may may it implicitly behave like 'go work use .'.
+
+! go work use
+stderr '^go: ''go work use'' requires one or more directory arguments'
+
+! go work use -r
+stderr '^go: ''go work use'' requires one or more directory arguments'
+
+-- go.work --
+go 1.18
diff --git a/src/cmd/go/testdata/script/work_vet.txt b/src/cmd/go/testdata/script/work_vet.txt
new file mode 100644
index 0000000..e258fc0
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_vet.txt
@@ -0,0 +1,19 @@
+! go vet ./a
+stderr 'fmt.Println call has possible formatting directive'
+
+-- go.work --
+go 1.18
+
+use ./a
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+-- a/a.go --
+package a
+
+import "fmt"
+
+func A() {
+ fmt.Println("%s")
+}
\ No newline at end of file
diff --git a/src/cmd/go/testdata/script/work_workfile.txt b/src/cmd/go/testdata/script/work_workfile.txt
deleted file mode 100644
index b629181..0000000
--- a/src/cmd/go/testdata/script/work_workfile.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-! go list -workfile=stop.work a # require absolute path
-! stderr panic
-! go list -workfile=doesnotexist a
-! stderr panic
-
-go list -n -workfile=$GOPATH/src/stop.work a
-go build -n -workfile=$GOPATH/src/stop.work a
-go test -n -workfile=$GOPATH/src/stop.work a
-
--- stop.work --
-go 1.18
-
-use ./a
--- a/a.go --
-package a
--- a/a_test.go --
-package a
--- a/go.mod --
-module a
-
-go 1.18
\ No newline at end of file
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 51f6e65..4280ed4 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -52,6 +52,16 @@
printerNormalizeNumbers = 1 << 30
)
+// fdSem guards the number of concurrently-open file descriptors.
+//
+// For now, this is arbitrarily set to 200, based on the observation that many
+// platforms default to a kernel limit of 256. Ideally, perhaps we should derive
+// it from rlimit on platforms that support that system call.
+//
+// File descriptors opened from outside of this package are not tracked,
+// so this limit may be approximate.
+var fdSem = make(chan bool, 200)
+
var (
rewrite func(*token.FileSet, *ast.File) *ast.File
parserMode parser.Mode
@@ -213,51 +223,9 @@
// If info == nil, we are formatting stdin instead of a file.
// If in == nil, the source is the contents of the file with the given filename.
func processFile(filename string, info fs.FileInfo, in io.Reader, r *reporter) error {
- if in == nil {
- var err error
- in, err = os.Open(filename)
- if err != nil {
- return err
- }
- }
-
- // Compute the file's size and read its contents with minimal allocations.
- //
- // If the size is unknown (or bogus, or overflows an int), fall back to
- // a size-independent ReadAll.
- var src []byte
- size := -1
- if info != nil && info.Mode().IsRegular() && int64(int(info.Size())) == info.Size() {
- size = int(info.Size())
- }
- if size+1 > 0 {
- // If we have the FileInfo from filepath.WalkDir, use it to make
- // a buffer of the right size and avoid ReadAll's reallocations.
- //
- // We try to read size+1 bytes so that we can detect modifications: if we
- // read more than size bytes, then the file was modified concurrently.
- // (If that happens, we could, say, append to src to finish the read, or
- // proceed with a truncated buffer — but the fact that it changed at all
- // indicates a possible race with someone editing the file, so we prefer to
- // stop to avoid corrupting it.)
- src = make([]byte, size+1)
- n, err := io.ReadFull(in, src)
- if err != nil && err != io.ErrUnexpectedEOF {
- return err
- }
- if n < size {
- return fmt.Errorf("error: size of %s changed during reading (from %d to %d bytes)", filename, size, n)
- } else if n > size {
- return fmt.Errorf("error: size of %s changed during reading (from %d to >=%d bytes)", filename, size, len(src))
- }
- src = src[:n]
- } else {
- // The file is not known to be regular, so we don't have a reliable size for it.
- var err error
- src, err = io.ReadAll(in)
- if err != nil {
- return err
- }
+ src, err := readFile(filename, info, in)
+ if err != nil {
+ return err
}
fileSet := token.NewFileSet()
@@ -306,7 +274,9 @@
if err != nil {
return err
}
+ fdSem <- true
err = os.WriteFile(filename, res, perm)
+ <-fdSem
if err != nil {
os.Rename(bakname, filename)
return err
@@ -333,6 +303,65 @@
return err
}
+// readFile reads the contents of filename, described by info.
+// If in is non-nil, readFile reads directly from it.
+// Otherwise, readFile opens and reads the file itself,
+// with the number of concurrently-open files limited by fdSem.
+func readFile(filename string, info fs.FileInfo, in io.Reader) ([]byte, error) {
+ if in == nil {
+ fdSem <- true
+ var err error
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ in = f
+ defer func() {
+ f.Close()
+ <-fdSem
+ }()
+ }
+
+ // Compute the file's size and read its contents with minimal allocations.
+ //
+ // If we have the FileInfo from filepath.WalkDir, use it to make
+ // a buffer of the right size and avoid ReadAll's reallocations.
+ //
+ // If the size is unknown (or bogus, or overflows an int), fall back to
+ // a size-independent ReadAll.
+ size := -1
+ if info != nil && info.Mode().IsRegular() && int64(int(info.Size())) == info.Size() {
+ size = int(info.Size())
+ }
+ if size+1 <= 0 {
+ // The file is not known to be regular, so we don't have a reliable size for it.
+ var err error
+ src, err := io.ReadAll(in)
+ if err != nil {
+ return nil, err
+ }
+ return src, nil
+ }
+
+ // We try to read size+1 bytes so that we can detect modifications: if we
+ // read more than size bytes, then the file was modified concurrently.
+ // (If that happens, we could, say, append to src to finish the read, or
+ // proceed with a truncated buffer — but the fact that it changed at all
+ // indicates a possible race with someone editing the file, so we prefer to
+ // stop to avoid corrupting it.)
+ src := make([]byte, size+1)
+ n, err := io.ReadFull(in, src)
+ if err != nil && err != io.ErrUnexpectedEOF {
+ return nil, err
+ }
+ if n < size {
+ return nil, fmt.Errorf("error: size of %s changed during reading (from %d to %d bytes)", filename, size, n)
+ } else if n > size {
+ return nil, fmt.Errorf("error: size of %s changed during reading (from %d to >=%d bytes)", filename, size, len(src))
+ }
+ return src[:n], nil
+}
+
func main() {
// Arbitrarily limit in-flight work to 2MiB times the number of threads.
//
@@ -354,12 +383,16 @@
flag.Parse()
if *cpuprofile != "" {
+ fdSem <- true
f, err := os.Create(*cpuprofile)
if err != nil {
s.AddReport(fmt.Errorf("creating cpu profile: %s", err))
return
}
- defer f.Close()
+ defer func() {
+ f.Close()
+ <-fdSem
+ }()
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
@@ -474,6 +507,9 @@
// with <number randomly chosen such that the file name is unique. backupFile returns
// the chosen file name.
func backupFile(filename string, data []byte, perm fs.FileMode) (string, error) {
+ fdSem <- true
+ defer func() { <-fdSem }()
+
// create backup file
f, err := os.CreateTemp(filepath.Dir(filename), filepath.Base(filename))
if err != nil {
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index 68f0921..f4111f4 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -1184,7 +1184,7 @@
q := c.newprog()
q.As = ADWORD
q.To.Type = obj.TYPE_CONST
- q.To.Offset = al.Offset
+ q.To.Offset = al.Offset // q.Pc is lower than t.Pc, so al.Offset is stored in q.
t := c.newprog()
t.As = ADWORD
diff --git a/src/cmd/internal/obj/arm64/doc.go b/src/cmd/internal/obj/arm64/doc.go
index 14f0f4c..1234a3e 100644
--- a/src/cmd/internal/obj/arm64/doc.go
+++ b/src/cmd/internal/obj/arm64/doc.go
@@ -89,12 +89,12 @@
7. Move large constants to vector registers.
Go asm uses VMOVQ/VMOVD/VMOVS to move 128-bit, 64-bit and 32-bit constants into vector registers, respectively.
-And for a 128-bit interger, it take two 64-bit operands, for the high and low parts separately.
+And for a 128-bit interger, it take two 64-bit operands, for the low and high parts separately.
Examples:
VMOVS $0x11223344, V0
VMOVD $0x1122334455667788, V1
- VMOVQ $0x1122334455667788, $8877665544332211, V2 // V2=0x11223344556677888877665544332211
+ VMOVQ $0x1122334455667788, $0x99aabbccddeeff00, V2 // V2=0x99aabbccddeeff001122334455667788
8. Move an optionally-shifted 16-bit immediate value to a register.
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 11af143..e0a3138 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -487,6 +487,7 @@
OpenCodedDeferInfo *LSym
ArgInfo *LSym // argument info for traceback
ArgLiveInfo *LSym // argument liveness info for traceback
+ WrapInfo *LSym // for wrapper, info of wrapped function
FuncInfoSym *LSym
}
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index fa61669..560e8e2 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -417,6 +417,7 @@
strings.HasSuffix(name, ".arginfo0") ||
strings.HasSuffix(name, ".arginfo1") ||
strings.HasSuffix(name, ".argliveinfo") ||
+ strings.HasSuffix(name, ".wrapinfo") ||
strings.HasSuffix(name, ".args_stackmap") ||
strings.HasSuffix(name, ".stkobj") {
return 'F' // go.func.* or go.funcrel.*
diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go
index ee2e596..1de6e76 100644
--- a/src/cmd/internal/obj/ppc64/asm_test.go
+++ b/src/cmd/internal/obj/ppc64/asm_test.go
@@ -300,7 +300,7 @@
t.Fatal(err)
}
if !matched {
- t.Errorf("Failed to detect long foward BC fixup in (%v):%s\n", platenv, out)
+ t.Errorf("Failed to detect long forward BC fixup in (%v):%s\n", platenv, out)
}
matched, err = regexp.MatchString(strings.Join(test.backpattern, "\n\t*"), string(out))
if err != nil {
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 5755b11..9f16de0 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -790,6 +790,12 @@
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_X10
+ // Mark the stack bound check and morestack call async nonpreemptible.
+ // If we get preempted here, when resumed the preemption request is
+ // cleared, but we'll still call morestack, which will double the stack
+ // unnecessarily. See issue #35470.
+ p = ctxt.StartUnsafePoint(p, newprog)
+
var to_done, to_more *obj.Prog
if framesize <= objabi.StackSmall {
@@ -854,7 +860,7 @@
to_done = p
}
- p = ctxt.EmitEntryLiveness(cursym, p, newprog)
+ p = ctxt.EmitEntryStackMap(cursym, p, newprog)
// CALL runtime.morestack(SB)
p = obj.Appendp(p, newprog)
@@ -872,6 +878,8 @@
}
jalToSym(ctxt, p, REG_X5)
+ p = ctxt.EndUnsafePoint(p, newprog, -1)
+
// JMP start
p = obj.Appendp(p, newprog)
p.As = AJAL
diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go
index 68d9589..843398d 100644
--- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go
+++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build riscv64
// +build riscv64
package testbranch
diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s
index cce296f..d7141e3 100644
--- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s
+++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build riscv64
// +build riscv64
#include "textflag.h"
diff --git a/src/cmd/internal/objabi/funcdata.go b/src/cmd/internal/objabi/funcdata.go
index 4d49a8d..05a1d49 100644
--- a/src/cmd/internal/objabi/funcdata.go
+++ b/src/cmd/internal/objabi/funcdata.go
@@ -23,6 +23,7 @@
FUNCDATA_OpenCodedDeferInfo = 4
FUNCDATA_ArgInfo = 5
FUNCDATA_ArgLiveInfo = 6
+ FUNCDATA_WrapInfo = 7
// ArgsSizeUnknown is set in Func.argsize to mark all functions
// whose argument size is unknown (C vararg functions, and
diff --git a/src/cmd/internal/src/pos.go b/src/cmd/internal/src/pos.go
index b6816a5..373a22a 100644
--- a/src/cmd/internal/src/pos.go
+++ b/src/cmd/internal/src/pos.go
@@ -389,9 +389,12 @@
}
func makeLico(line, col uint) lico {
- if line > lineMax {
+ if line >= lineMax {
// cannot represent line, use max. line so we have some information
line = lineMax
+ // Drop column information if line number saturates.
+ // Ensures line+col is monotonic. See issue 51193.
+ col = 0
}
if col > colMax {
// cannot represent column, use max. column so we have some information
diff --git a/src/cmd/internal/src/pos_test.go b/src/cmd/internal/src/pos_test.go
index d4cd0e7..cdf4ab4 100644
--- a/src/cmd/internal/src/pos_test.go
+++ b/src/cmd/internal/src/pos_test.go
@@ -140,8 +140,8 @@
{makeLico(1, 0), ":1", 1, 0},
{makeLico(1, 1), ":1:1", 1, 1},
{makeLico(2, 3), ":2:3", 2, 3},
- {makeLico(lineMax, 1), fmt.Sprintf(":%d:1", lineMax), lineMax, 1},
- {makeLico(lineMax+1, 1), fmt.Sprintf(":%d:1", lineMax), lineMax, 1}, // line too large, stick with max. line
+ {makeLico(lineMax, 1), fmt.Sprintf(":%d", lineMax), lineMax, 1},
+ {makeLico(lineMax+1, 1), fmt.Sprintf(":%d", lineMax), lineMax, 1}, // line too large, stick with max. line
{makeLico(1, colMax), ":1", 1, colMax},
{makeLico(1, colMax+1), ":1", 1, 0}, // column too large
{makeLico(lineMax+1, colMax+1), fmt.Sprintf(":%d", lineMax), lineMax, 0},
@@ -170,8 +170,8 @@
{makeLico(1, 1), ":1:1" + def, 1, 1},
{makeLico(1, 1).withIsStmt(), ":1:1" + is, 1, 1},
{makeLico(1, 1).withNotStmt(), ":1:1" + not, 1, 1},
- {makeLico(lineMax, 1), fmt.Sprintf(":%d:1", lineMax) + def, lineMax, 1},
- {makeLico(lineMax+1, 1), fmt.Sprintf(":%d:1", lineMax) + def, lineMax, 1}, // line too large, stick with max. line
+ {makeLico(lineMax, 1), fmt.Sprintf(":%d", lineMax) + def, lineMax, 1},
+ {makeLico(lineMax+1, 1), fmt.Sprintf(":%d", lineMax) + def, lineMax, 1}, // line too large, stick with max. line
{makeLico(1, colMax), ":1" + def, 1, colMax},
{makeLico(1, colMax+1), ":1" + def, 1, 0}, // column too large
{makeLico(lineMax+1, colMax+1), fmt.Sprintf(":%d", lineMax) + def, lineMax, 0},
@@ -214,9 +214,9 @@
{makeLico(1, 1).withXlogue(PosPrologueEnd), ":1:1" + defs + pro, 1, 1},
{makeLico(1, 1).withXlogue(PosEpilogueBegin), ":1:1" + defs + epi, 1, 1},
- {makeLico(lineMax, 1).withXlogue(PosDefaultLogue), fmt.Sprintf(":%d:1", lineMax) + defs + defp, lineMax, 1},
- {makeLico(lineMax, 1).withXlogue(PosPrologueEnd), fmt.Sprintf(":%d:1", lineMax) + defs + pro, lineMax, 1},
- {makeLico(lineMax, 1).withXlogue(PosEpilogueBegin), fmt.Sprintf(":%d:1", lineMax) + defs + epi, lineMax, 1},
+ {makeLico(lineMax, 1).withXlogue(PosDefaultLogue), fmt.Sprintf(":%d", lineMax) + defs + defp, lineMax, 1},
+ {makeLico(lineMax, 1).withXlogue(PosPrologueEnd), fmt.Sprintf(":%d", lineMax) + defs + pro, lineMax, 1},
+ {makeLico(lineMax, 1).withXlogue(PosEpilogueBegin), fmt.Sprintf(":%d", lineMax) + defs + epi, lineMax, 1},
} {
x := test.x
if got := formatstr("", x.Line(), x.Col(), true) + fmt.Sprintf(":%d:%d", x.IsStmt(), x.Xlogue()); got != test.string {
diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go
index f25aaab..82b6551 100644
--- a/src/cmd/internal/sys/supported.go
+++ b/src/cmd/internal/sys/supported.go
@@ -50,7 +50,7 @@
// ('go test -fuzz=.').
func FuzzSupported(goos, goarch string) bool {
switch goos {
- case "darwin", "linux", "windows":
+ case "darwin", "freebsd", "linux", "windows":
return true
default:
return false
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 4a143df..1bdfb33 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -1080,7 +1080,12 @@
}
if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
- sh.Type = uint32(elf.SHT_PROGBITS)
+ switch sect.Name {
+ case ".init_array":
+ sh.Type = uint32(elf.SHT_INIT_ARRAY)
+ default:
+ sh.Type = uint32(elf.SHT_PROGBITS)
+ }
} else {
sh.Type = uint32(elf.SHT_NOBITS)
}
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 9e13db7..f1a37e9 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1269,7 +1269,10 @@
if ctxt.DynlinkingGo() && buildcfg.GOOS != "ios" {
// -flat_namespace is deprecated on iOS.
// It is useful for supporting plugins. We don't support plugins on iOS.
- argv = append(argv, "-Wl,-flat_namespace")
+ // -flat_namespace may cause the dynamic linker to hang at forkExec when
+ // resolving a lazy binding. See issue 38824.
+ // Force eager resolution to work around.
+ argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load")
}
if !combineDwarf {
argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 720c03a..39066da 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -567,6 +567,7 @@
strings.HasSuffix(name, ".arginfo0"),
strings.HasSuffix(name, ".arginfo1"),
strings.HasSuffix(name, ".argliveinfo"),
+ strings.HasSuffix(name, ".wrapinfo"),
strings.HasSuffix(name, ".args_stackmap"),
strings.HasSuffix(name, ".stkobj"):
ldr.SetAttrNotInSymbolTable(s, true)
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
index fd22853..30130f6 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
@@ -51,6 +51,12 @@
if V == nil || T == nil {
return nil
}
+
+ // Mitigations for interface comparisons and generics.
+ // TODO(https://github.com/golang/go/issues/50658): Support more precise conclusion.
+ if isParameterized(V) || isParameterized(T) {
+ return nil
+ }
if f, wrongType := types.MissingMethod(V, T, false); wrongType {
return f
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/parameterized.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/parameterized.go
new file mode 100644
index 0000000..1285ecf
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/parameterized.go
@@ -0,0 +1,112 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package ifaceassert
+
+import (
+ "go/types"
+
+ "golang.org/x/tools/internal/typeparams"
+)
+
+// isParameterized reports whether typ contains any of the type parameters of tparams.
+//
+// NOTE: Adapted from go/types/infer.go. If that is exported in a future release remove this copy.
+func isParameterized(typ types.Type) bool {
+ w := tpWalker{
+ seen: make(map[types.Type]bool),
+ }
+ return w.isParameterized(typ)
+}
+
+type tpWalker struct {
+ seen map[types.Type]bool
+}
+
+func (w *tpWalker) isParameterized(typ types.Type) (res bool) {
+ // detect cycles
+ if x, ok := w.seen[typ]; ok {
+ return x
+ }
+ w.seen[typ] = false
+ defer func() {
+ w.seen[typ] = res
+ }()
+
+ switch t := typ.(type) {
+ case nil, *types.Basic: // TODO(gri) should nil be handled here?
+ break
+
+ case *types.Array:
+ return w.isParameterized(t.Elem())
+
+ case *types.Slice:
+ return w.isParameterized(t.Elem())
+
+ case *types.Struct:
+ for i, n := 0, t.NumFields(); i < n; i++ {
+ if w.isParameterized(t.Field(i).Type()) {
+ return true
+ }
+ }
+
+ case *types.Pointer:
+ return w.isParameterized(t.Elem())
+
+ case *types.Tuple:
+ n := t.Len()
+ for i := 0; i < n; i++ {
+ if w.isParameterized(t.At(i).Type()) {
+ return true
+ }
+ }
+
+ case *types.Signature:
+ // t.tparams may not be nil if we are looking at a signature
+ // of a generic function type (or an interface method) that is
+ // part of the type we're testing. We don't care about these type
+ // parameters.
+ // Similarly, the receiver of a method may declare (rather then
+ // use) type parameters, we don't care about those either.
+ // Thus, we only need to look at the input and result parameters.
+ return w.isParameterized(t.Params()) || w.isParameterized(t.Results())
+
+ case *types.Interface:
+ for i, n := 0, t.NumMethods(); i < n; i++ {
+ if w.isParameterized(t.Method(i).Type()) {
+ return true
+ }
+ }
+ terms, err := typeparams.InterfaceTermSet(t)
+ if err != nil {
+ panic(err)
+ }
+ for _, term := range terms {
+ if w.isParameterized(term.Type()) {
+ return true
+ }
+ }
+
+ case *types.Map:
+ return w.isParameterized(t.Key()) || w.isParameterized(t.Elem())
+
+ case *types.Chan:
+ return w.isParameterized(t.Elem())
+
+ case *types.Named:
+ list := typeparams.NamedTypeArgs(t)
+ for i, n := 0, list.Len(); i < n; i++ {
+ if w.isParameterized(list.At(i)) {
+ return true
+ }
+ }
+
+ case *typeparams.TypeParam:
+ return true
+
+ default:
+ panic(t) // unreachable
+ }
+
+ return false
+}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go
index 850f6f8..e4c66df 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go
@@ -62,7 +62,8 @@
obj = pass.TypesInfo.Uses[v.Sel]
case *ast.IndexExpr, *typeparams.IndexListExpr:
// Check generic functions such as "f[T1,T2]".
- if id, ok := typeparams.GetIndexExprData(v).X.(*ast.Ident); ok {
+ x, _, _, _ := typeparams.UnpackIndexExpr(v)
+ if id, ok := x.(*ast.Ident); ok {
obj = pass.TypesInfo.Uses[id]
}
default:
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go
index 3d4bd49..7ea8f77 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go
@@ -127,11 +127,8 @@
func goStmtFun(goStmt *ast.GoStmt) ast.Node {
switch fun := goStmt.Call.Fun.(type) {
case *ast.IndexExpr, *typeparams.IndexListExpr:
- ix := typeparams.GetIndexExprData(fun)
- if ix == nil {
- break
- }
- id, _ := ix.X.(*ast.Ident)
+ x, _, _, _ := typeparams.UnpackIndexExpr(fun)
+ id, _ := x.(*ast.Ident)
if id == nil {
break
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
index fd94508..06747ba 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
@@ -71,9 +71,9 @@
return // a conversion, not a call
}
- index := typeparams.GetIndexExprData(fun)
- if index != nil {
- fun = index.X // If this is generic function or method call, skip the instantiation arguments
+ x, _, _, _ := typeparams.UnpackIndexExpr(fun)
+ if x != nil {
+ fun = x // If this is generic function or method call, skip the instantiation arguments
}
selector, ok := fun.(*ast.SelectorExpr)
diff --git a/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go b/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go
index 2b89603..90b3ab0 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go
@@ -27,8 +27,7 @@
// it is a *types.Func and not a *types.Var.
// Example: Don't match a slice m within the expression `m[0]()`.
isInstance = true
- ix := typeparams.GetIndexExprData(fun)
- fun = ix.X
+ fun, _, _, _ = typeparams.UnpackIndexExpr(fun)
}
var obj types.Object
diff --git a/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go
index 062f491..df9fbd5 100644
--- a/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go
+++ b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go
@@ -49,11 +49,6 @@
//
// Currently this matcher only accepts case-insensitive fuzzy patterns.
//
-// TODO(rfindley):
-// - implement smart-casing
-// - implement space-separated groups
-// - implement ', ^, and $ modifiers
-//
// An empty pattern matches no input.
func NewSymbolMatcher(pattern string) *SymbolMatcher {
m := &SymbolMatcher{}
@@ -176,7 +171,12 @@
// 1. 1.0 if the character starts a segment, .8 if the character start a
// mid-segment word, otherwise 0.6. This carries over to immediately
// following characters.
- // 2. 1.0 if the character is part of the last segment, otherwise
+ // 2. For the final character match, the multiplier from (1) is reduced to
+ // .8 if the next character in the input is a mid-segment word, or 0.6 if
+ // the next character in the input is not a word or segment start. This
+ // ensures that we favor whole-word or whole-segment matches over prefix
+ // matches.
+ // 3. 1.0 if the character is part of the last segment, otherwise
// 1.0-.2*<segments from the right>, with a max segment count of 3.
//
// This is a very naive algorithm, but it is fast. There's lots of prior art
@@ -211,8 +211,20 @@
case m.roles[ii]&wordStart != 0 && wordStreak > streakBonus:
streakBonus = wordStreak
}
+ finalChar := pi >= m.patternLen
+ // finalCost := 1.0
+ if finalChar && streakBonus > noStreak {
+ switch {
+ case ii == inputLen-1 || m.roles[ii+1]&segmentStart != 0:
+ // Full segment: no reduction
+ case m.roles[ii+1]&wordStart != 0:
+ streakBonus = wordStreak
+ default:
+ streakBonus = noStreak
+ }
+ }
totScore += streakBonus * (1.0 - float64(m.segments[ii])*perSegment)
- if pi >= m.patternLen {
+ if finalChar {
break
}
} else {
diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go
index 961d036..1222764 100644
--- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go
+++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go
@@ -2,12 +2,25 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package typeparams provides functions to work indirectly with type parameter
-// data stored in go/ast and go/types objects, while these API are guarded by a
-// build constraint.
+// Package typeparams contains common utilities for writing tools that interact
+// with generic Go code, as introduced with Go 1.18.
//
-// This package exists to make it easier for tools to work with generic code,
-// while also compiling against older Go versions.
+// Many of the types and functions in this package are proxies for the new APIs
+// introduced in the standard library with Go 1.18. For example, the
+// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec
+// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go
+// versions older than 1.18 these helpers are implemented as stubs, allowing
+// users of this package to write code that handles generic constructs inline,
+// even if the Go version being used to compile does not support generics.
+//
+// Additionally, this package contains common utilities for working with the
+// new generic constructs, to supplement the standard library APIs. Notably,
+// the StructuralTerms API computes a minimal representation of the structural
+// restrictions on a type parameter. In the future, this API may be available
+// from go/types.
+//
+// See the example/README.md for a more detailed guide on how to update tools
+// to support generics.
package typeparams
import (
@@ -16,13 +29,47 @@
"go/types"
)
-// A IndexExprData holds data from both ast.IndexExpr and the new
-// ast.MultiIndexExpr, which was introduced in Go 1.18.
-type IndexExprData struct {
- X ast.Expr // expression
- Lbrack token.Pos // position of "["
- Indices []ast.Expr // index expressions
- Rbrack token.Pos // position of "]"
+// UnpackIndexExpr extracts data from AST nodes that represent index
+// expressions.
+//
+// For an ast.IndexExpr, the resulting indices slice will contain exactly one
+// index expression. For an ast.IndexListExpr (go1.18+), it may have a variable
+// number of index expressions.
+//
+// For nodes that don't represent index expressions, the first return value of
+// UnpackIndexExpr will be nil.
+func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) {
+ switch e := n.(type) {
+ case *ast.IndexExpr:
+ return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack
+ case *IndexListExpr:
+ return e.X, e.Lbrack, e.Indices, e.Rbrack
+ }
+ return nil, token.NoPos, nil, token.NoPos
+}
+
+// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on
+// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0
+// will panic.
+func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr {
+ switch len(indices) {
+ case 0:
+ panic("empty indices")
+ case 1:
+ return &ast.IndexExpr{
+ X: x,
+ Lbrack: lbrack,
+ Index: indices[0],
+ Rbrack: rbrack,
+ }
+ default:
+ return &IndexListExpr{
+ X: x,
+ Lbrack: lbrack,
+ Indices: indices,
+ Rbrack: rbrack,
+ }
+ }
}
// IsTypeParam reports whether t is a type parameter.
diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
index e509daf..5fd3fc3 100644
--- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
+++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
@@ -17,38 +17,6 @@
panic("type parameters are unsupported at this go version")
}
-// GetIndexExprData extracts data from *ast.IndexExpr nodes.
-// For other nodes, GetIndexExprData returns nil.
-func GetIndexExprData(n ast.Node) *IndexExprData {
- if e, _ := n.(*ast.IndexExpr); e != nil {
- return &IndexExprData{
- X: e.X,
- Lbrack: e.Lbrack,
- Indices: []ast.Expr{e.Index},
- Rbrack: e.Rbrack,
- }
- }
- return nil
-}
-
-// PackIndexExpr returns an *ast.IndexExpr with the given index.
-// Calling PackIndexExpr with len(indices) != 1 will panic.
-func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr {
- switch len(indices) {
- case 0:
- panic("empty indices")
- case 1:
- return &ast.IndexExpr{
- X: x,
- Lbrack: lbrack,
- Index: indices[0],
- Rbrack: rbrack,
- }
- default:
- panic("cannot pack multiple indices at this go version")
- }
-}
-
// IndexListExpr is a placeholder type, as type parameters are not supported at
// this Go version. Its methods panic on use.
type IndexListExpr struct {
diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
index e45896f..7470aed 100644
--- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
+++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
@@ -9,59 +9,9 @@
import (
"go/ast"
- "go/token"
"go/types"
)
-// GetIndexExprData extracts data from AST nodes that represent index
-// expressions.
-//
-// For an ast.IndexExpr, the resulting IndexExprData will have exactly one
-// index expression. For an ast.IndexListExpr (go1.18+), it may have a
-// variable number of index expressions.
-//
-// For nodes that don't represent index expressions, GetIndexExprData returns
-// nil.
-// TODO(rfindley): remove this function in favor of using the alias below.
-func GetIndexExprData(n ast.Node) *IndexExprData {
- switch e := n.(type) {
- case *ast.IndexExpr:
- return &IndexExprData{
- X: e.X,
- Lbrack: e.Lbrack,
- Indices: []ast.Expr{e.Index},
- Rbrack: e.Rbrack,
- }
- case *ast.IndexListExpr:
- return (*IndexExprData)(e)
- }
- return nil
-}
-
-// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on
-// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0
-// will panic.
-func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr {
- switch len(indices) {
- case 0:
- panic("empty indices")
- case 1:
- return &ast.IndexExpr{
- X: x,
- Lbrack: lbrack,
- Index: indices[0],
- Rbrack: rbrack,
- }
- default:
- return &ast.IndexListExpr{
- X: x,
- Lbrack: lbrack,
- Indices: indices,
- Rbrack: rbrack,
- }
- }
-}
-
// IndexListExpr is an alias for ast.IndexListExpr.
type IndexListExpr = ast.IndexListExpr
diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt
index 22dd145..f2cd884 100644
--- a/src/cmd/vendor/modules.txt
+++ b/src/cmd/vendor/modules.txt
@@ -24,7 +24,7 @@
golang.org/x/arch/arm64/arm64asm
golang.org/x/arch/ppc64/ppc64asm
golang.org/x/arch/x86/x86asm
-# golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa
+# golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
## explicit; go 1.17
golang.org/x/crypto/ed25519
golang.org/x/crypto/ed25519/internal/edwards25519
@@ -51,7 +51,7 @@
# golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
## explicit; go 1.17
golang.org/x/term
-# golang.org/x/tools v0.1.9-0.20211207220608-fd2bfb79a16a
+# golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646
## explicit; go 1.17
golang.org/x/tools/cover
golang.org/x/tools/go/analysis
diff --git a/src/compress/gzip/fuzz_test.go b/src/compress/gzip/fuzz_test.go
new file mode 100644
index 0000000..80d803c
--- /dev/null
+++ b/src/compress/gzip/fuzz_test.go
@@ -0,0 +1,92 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gzip
+
+import (
+ "bytes"
+ "encoding/base64"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func FuzzReader(f *testing.F) {
+ inp := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
+ for _, level := range []int{BestSpeed, BestCompression, DefaultCompression, HuffmanOnly} {
+ b := bytes.NewBuffer(nil)
+ w, err := NewWriterLevel(b, level)
+ if err != nil {
+ f.Fatalf("failed to construct writer: %s", err)
+ }
+ _, err = w.Write(inp)
+ if err != nil {
+ f.Fatalf("failed to write: %s", err)
+ }
+ f.Add(b.Bytes())
+ }
+
+ testdata, err := os.ReadDir("testdata")
+ if err != nil {
+ f.Fatalf("failed to read testdata directory: %s", err)
+ }
+ for _, de := range testdata {
+ if de.IsDir() {
+ continue
+ }
+ b, err := os.ReadFile(filepath.Join("testdata", de.Name()))
+ if err != nil {
+ f.Fatalf("failed to read testdata: %s", err)
+ }
+
+ // decode any base64 encoded test files
+ if strings.HasPrefix(de.Name(), ".base64") {
+ b, err = base64.StdEncoding.DecodeString(string(b))
+ if err != nil {
+ f.Fatalf("failed to decode base64 testdata: %s", err)
+ }
+ }
+
+ f.Add(b)
+ }
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ for _, multistream := range []bool{true, false} {
+ r, err := NewReader(bytes.NewBuffer(b))
+ if err != nil {
+ continue
+ }
+
+ r.Multistream(multistream)
+
+ decompressed := bytes.NewBuffer(nil)
+ if _, err := io.Copy(decompressed, r); err != nil {
+ continue
+ }
+
+ if err := r.Close(); err != nil {
+ continue
+ }
+
+ for _, level := range []int{NoCompression, BestSpeed, BestCompression, DefaultCompression, HuffmanOnly} {
+ w, err := NewWriterLevel(io.Discard, level)
+ if err != nil {
+ t.Fatalf("failed to construct writer: %s", err)
+ }
+ _, err = w.Write(decompressed.Bytes())
+ if err != nil {
+ t.Fatalf("failed to write: %s", err)
+ }
+ if err := w.Flush(); err != nil {
+ t.Fatalf("failed to flush: %s", err)
+ }
+ if err := w.Close(); err != nil {
+ t.Fatalf("failed to close: %s", err)
+ }
+ }
+ }
+ })
+}
diff --git a/src/constraints/constraints.go b/src/constraints/constraints.go
deleted file mode 100644
index 2c033df..0000000
--- a/src/constraints/constraints.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package constraints defines a set of useful constraints to be used
-// with type parameters.
-package constraints
-
-// Signed is a constraint that permits any signed integer type.
-// If future releases of Go add new predeclared signed integer types,
-// this constraint will be modified to include them.
-type Signed interface {
- ~int | ~int8 | ~int16 | ~int32 | ~int64
-}
-
-// Unsigned is a constraint that permits any unsigned integer type.
-// If future releases of Go add new predeclared unsigned integer types,
-// this constraint will be modified to include them.
-type Unsigned interface {
- ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
-}
-
-// Integer is a constraint that permits any integer type.
-// If future releases of Go add new predeclared integer types,
-// this constraint will be modified to include them.
-type Integer interface {
- Signed | Unsigned
-}
-
-// Float is a constraint that permits any floating-point type.
-// If future releases of Go add new predeclared floating-point types,
-// this constraint will be modified to include them.
-type Float interface {
- ~float32 | ~float64
-}
-
-// Complex is a constraint that permits any complex numeric type.
-// If future releases of Go add new predeclared complex numeric types,
-// this constraint will be modified to include them.
-type Complex interface {
- ~complex64 | ~complex128
-}
-
-// Ordered is a constraint that permits any ordered type: any type
-// that supports the operators < <= >= >.
-// If future releases of Go add new ordered types,
-// this constraint will be modified to include them.
-type Ordered interface {
- Integer | Float | ~string
-}
diff --git a/src/constraints/constraints_test.go b/src/constraints/constraints_test.go
deleted file mode 100644
index 47d4cba..0000000
--- a/src/constraints/constraints_test.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package constraints
-
-import (
- "bytes"
- "fmt"
- "internal/testenv"
- "os"
- "os/exec"
- "path/filepath"
- "testing"
-)
-
-type (
- testSigned[T Signed] struct{ f T }
- testUnsigned[T Unsigned] struct{ f T }
- testInteger[T Integer] struct{ f T }
- testFloat[T Float] struct{ f T }
- testComplex[T Complex] struct{ f T }
- testOrdered[T Ordered] struct{ f T }
-)
-
-// TestTypes passes if it compiles.
-type TestTypes struct {
- _ testSigned[int]
- _ testSigned[int64]
- _ testUnsigned[uint]
- _ testUnsigned[uintptr]
- _ testInteger[int8]
- _ testInteger[uint8]
- _ testInteger[uintptr]
- _ testFloat[float32]
- _ testComplex[complex64]
- _ testOrdered[int]
- _ testOrdered[float64]
- _ testOrdered[string]
-}
-
-var prolog = []byte(`
-package constrainttest
-
-import "constraints"
-
-type (
- testSigned[T constraints.Signed] struct{ f T }
- testUnsigned[T constraints.Unsigned] struct{ f T }
- testInteger[T constraints.Integer] struct{ f T }
- testFloat[T constraints.Float] struct{ f T }
- testComplex[T constraints.Complex] struct{ f T }
- testOrdered[T constraints.Ordered] struct{ f T }
-)
-`)
-
-func TestFailure(t *testing.T) {
- testenv.MustHaveGoBuild(t)
- gocmd := testenv.GoToolPath(t)
- tmpdir := t.TempDir()
-
- if err := os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module constraintest"), 0666); err != nil {
- t.Fatal(err)
- }
-
- // Test for types that should not satisfy a constraint.
- // For each pair of constraint and type, write a Go file
- // var V constraint[type]
- // For example,
- // var V testSigned[uint]
- // This should not compile, as testSigned (above) uses
- // constraints.Signed, and uint does not satisfy that constraint.
- // Therefore, the build of that code should fail.
- for i, test := range []struct {
- constraint, typ string
- }{
- {"testSigned", "uint"},
- {"testUnsigned", "int"},
- {"testInteger", "float32"},
- {"testFloat", "int8"},
- {"testComplex", "float64"},
- {"testOrdered", "bool"},
- } {
- i := i
- test := test
- t.Run(fmt.Sprintf("%s %d", test.constraint, i), func(t *testing.T) {
- t.Parallel()
- name := fmt.Sprintf("go%d.go", i)
- f, err := os.Create(filepath.Join(tmpdir, name))
- if err != nil {
- t.Fatal(err)
- }
- if _, err := f.Write(prolog); err != nil {
- t.Fatal(err)
- }
- if _, err := fmt.Fprintf(f, "var V %s[%s]\n", test.constraint, test.typ); err != nil {
- t.Fatal(err)
- }
- if err := f.Close(); err != nil {
- t.Fatal(err)
- }
- cmd := exec.Command(gocmd, "build", name)
- cmd.Dir = tmpdir
- if out, err := cmd.CombinedOutput(); err == nil {
- t.Error("build succeeded, but expected to fail")
- } else if len(out) > 0 {
- t.Logf("%s", out)
- const want = "does not implement"
- if !bytes.Contains(out, []byte(want)) {
- t.Errorf("output does not include %q", want)
- }
- } else {
- t.Error("no error output, expected something")
- }
- })
- }
-}
diff --git a/src/crypto/aes/asm_amd64.s b/src/crypto/aes/asm_amd64.s
index ad871ec..ed831bf 100644
--- a/src/crypto/aes/asm_amd64.s
+++ b/src/crypto/aes/asm_amd64.s
@@ -15,7 +15,7 @@
ADDQ $16, AX
PXOR X1, X0
SUBQ $12, CX
- JE Lenc196
+ JE Lenc192
JB Lenc128
Lenc256:
MOVUPS 0(AX), X1
@@ -23,7 +23,7 @@
MOVUPS 16(AX), X1
AESENC X1, X0
ADDQ $32, AX
-Lenc196:
+Lenc192:
MOVUPS 0(AX), X1
AESENC X1, X0
MOVUPS 16(AX), X1
@@ -64,7 +64,7 @@
ADDQ $16, AX
PXOR X1, X0
SUBQ $12, CX
- JE Ldec196
+ JE Ldec192
JB Ldec128
Ldec256:
MOVUPS 0(AX), X1
@@ -72,7 +72,7 @@
MOVUPS 16(AX), X1
AESDEC X1, X0
ADDQ $32, AX
-Ldec196:
+Ldec192:
MOVUPS 0(AX), X1
AESDEC X1, X0
MOVUPS 16(AX), X1
@@ -115,7 +115,7 @@
ADDQ $16, BX
PXOR X4, X4 // _expand_key_* expect X4 to be zero
CMPL CX, $12
- JE Lexp_enc196
+ JE Lexp_enc192
JB Lexp_enc128
Lexp_enc256:
MOVUPS 16(AX), X2
@@ -148,7 +148,7 @@
AESKEYGENASSIST $0x40, X2, X1
CALL _expand_key_256a<>(SB)
JMP Lexp_dec
-Lexp_enc196:
+Lexp_enc192:
MOVQ 16(AX), X2
AESKEYGENASSIST $0x01, X2, X1
CALL _expand_key_192a<>(SB)
diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go
index 282596d..9f9a09a 100644
--- a/src/crypto/ecdsa/ecdsa.go
+++ b/src/crypto/ecdsa/ecdsa.go
@@ -3,28 +3,21 @@
// license that can be found in the LICENSE file.
// Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as
-// defined in FIPS 186-3.
+// defined in FIPS 186-4 and SEC 1, Version 2.0.
//
-// This implementation derives the nonce from an AES-CTR CSPRNG keyed by:
-//
-// SHA2-512(priv.D || entropy || hash)[:32]
-//
-// The CSPRNG key is indifferentiable from a random oracle as shown in
-// [Coron], the AES-CTR stream is indifferentiable from a random oracle
-// under standard cryptographic assumptions (see [Larsson] for examples).
-//
-// References:
-// [Coron]
-// https://cs.nyu.edu/~dodis/ps/merkle.pdf
-// [Larsson]
-// https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf
+// Signatures generated by this package are not deterministic, but entropy is
+// mixed with the private key and the message, achieving the same level of
+// security in case of randomness source failure.
package ecdsa
-// Further references:
-// [NSA]: Suite B implementer's guide to FIPS 186-3
-// https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/suite-b-implementers-guide-to-fips-186-3-ecdsa.cfm
-// [SECG]: SECG, SEC1
-// http://www.secg.org/sec1-v2.pdf
+// [FIPS 186-4] references ANSI X9.62-2005 for the bulk of the ECDSA algorithm.
+// That standard is not freely available, which is a problem in an open source
+// implementation, because not only the implementer, but also any maintainer,
+// contributor, reviewer, auditor, and learner needs access to it. Instead, this
+// package references and follows the equivalent [SEC 1, Version 2.0].
+//
+// [FIPS 186-4]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+// [SEC 1, Version 2.0]: https://www.secg.org/sec1-v2.pdf
import (
"crypto"
@@ -41,15 +34,16 @@
"golang.org/x/crypto/cryptobyte/asn1"
)
-// A invertible implements fast inverse mod Curve.Params().N
+// A invertible implements fast inverse in GF(N).
type invertible interface {
- // Inverse returns the inverse of k in GF(P)
+ // Inverse returns the inverse of k mod Params().N.
Inverse(k *big.Int) *big.Int
}
-// combinedMult implements fast multiplication S1*g + S2*p (g - generator, p - arbitrary point)
+// A combinedMult implements fast combined multiplication for verification.
type combinedMult interface {
- CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
+ // CombinedMult returns [s1]G + [s2]P where G is the generator.
+ CombinedMult(Px, Py *big.Int, s1, s2 []byte) (x, y *big.Int)
}
const (
@@ -111,7 +105,7 @@
//
// This method implements crypto.Signer, which is an interface to support keys
// where the private part is kept in, for example, a hardware module. Common
-// uses should use the Sign function in this package directly.
+// uses can use the SignASN1 function in this package directly.
func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
r, s, err := Sign(rand, priv, digest)
if err != nil {
@@ -128,11 +122,13 @@
var one = new(big.Int).SetInt64(1)
-// randFieldElement returns a random element of the field underlying the given
-// curve using the procedure given in [NSA] A.2.1.
+// randFieldElement returns a random element of the order of the given
+// curve using the procedure given in FIPS 186-4, Appendix B.5.1.
func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
params := c.Params()
- b := make([]byte, params.BitSize/8+8)
+ // Note that for P-521 this will actually be 63 bits more than the order, as
+ // division rounds down, but the extra bit is inconsequential.
+ b := make([]byte, params.BitSize/8+8) // TODO: use params.N.BitLen()
_, err = io.ReadFull(rand, b)
if err != nil {
return
@@ -159,12 +155,9 @@
return priv, nil
}
-// hashToInt converts a hash value to an integer. There is some disagreement
-// about how this is done. [NSA] suggests that this is done in the obvious
-// manner, but [SECG] truncates the hash to the bit-length of the curve order
-// first. We follow [SECG] because that's what OpenSSL does. Additionally,
-// OpenSSL right shifts excess bits from the number if the hash is too large
-// and we mirror that too.
+// hashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4,
+// we use the left-most bits of the hash to match the bit-length of the order of
+// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3.
func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
orderBits := c.Params().N.BitLen()
orderBytes := (orderBits + 7) / 8
@@ -180,10 +173,11 @@
return ret
}
-// fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
-// This has better constant-time properties than Euclid's method (implemented
-// in math/big.Int.ModInverse) although math/big itself isn't strictly
-// constant-time so it's not perfect.
+// fermatInverse calculates the inverse of k in GF(P) using Fermat's method
+// (exponentiation modulo P - 2, per Euler's theorem). This has better
+// constant-time properties than Euclid's method (implemented in
+// math/big.Int.ModInverse and FIPS 186-4, Appendix C.1) although math/big
+// itself isn't strictly constant-time so it's not perfect.
func fermatInverse(k, N *big.Int) *big.Int {
two := big.NewInt(2)
nMinus2 := new(big.Int).Sub(N, two)
@@ -195,11 +189,22 @@
// Sign signs a hash (which should be the result of hashing a larger message)
// using the private key, priv. If the hash is longer than the bit-length of the
// private key's curve order, the hash will be truncated to that length. It
-// returns the signature as a pair of integers. The security of the private key
-// depends on the entropy of rand.
+// returns the signature as a pair of integers. Most applications should use
+// SignASN1 instead of dealing directly with r, s.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
randutil.MaybeReadByte(rand)
+ // This implementation derives the nonce from an AES-CTR CSPRNG keyed by:
+ //
+ // SHA2-512(priv.D || entropy || hash)[:32]
+ //
+ // The CSPRNG key is indifferentiable from a random oracle as shown in
+ // [Coron], the AES-CTR stream is indifferentiable from a random oracle
+ // under standard cryptographic assumptions (see [Larsson] for examples).
+ //
+ // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf
+ // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf
+
// Get 256 bits of entropy from rand.
entropy := make([]byte, 32)
_, err = io.ReadFull(rand, entropy)
@@ -207,7 +212,7 @@
return
}
- // Initialize an SHA-512 hash context; digest ...
+ // Initialize an SHA-512 hash context; digest...
md := sha512.New()
md.Write(priv.D.Bytes()) // the private key,
md.Write(entropy) // the entropy,
@@ -228,12 +233,12 @@
S: cipher.NewCTR(block, []byte(aesIV)),
}
- // See [NSA] 3.4.1
c := priv.PublicKey.Curve
return sign(priv, &csprng, c, hash)
}
func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) {
+ // SEC 1, Version 2.0, Section 4.1.3
N := c.Params().N
if N.Sign() == 0 {
return nil, nil, errZeroParam
@@ -276,16 +281,15 @@
// SignASN1 signs a hash (which should be the result of hashing a larger message)
// using the private key, priv. If the hash is longer than the bit-length of the
// private key's curve order, the hash will be truncated to that length. It
-// returns the ASN.1 encoded signature. The security of the private key
-// depends on the entropy of rand.
+// returns the ASN.1 encoded signature.
func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {
return priv.Sign(rand, hash, nil)
}
// Verify verifies the signature in r, s of hash using the public key, pub. Its
-// return value records whether the signature is valid.
+// return value records whether the signature is valid. Most applications should
+// use VerifyASN1 instead of dealing directly with r, s.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
- // See [NSA] 3.4.2
c := pub.Curve
N := c.Params().N
@@ -299,6 +303,7 @@
}
func verifyGeneric(pub *PublicKey, c elliptic.Curve, hash []byte, r, s *big.Int) bool {
+ // SEC 1, Version 2.0, Section 4.1.4
e := hashToInt(hash, c)
var w *big.Int
N := c.Params().N
diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
index d06a284..7ead09f 100644
--- a/src/crypto/elliptic/elliptic.go
+++ b/src/crypto/elliptic/elliptic.go
@@ -2,17 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package elliptic implements several standard elliptic curves over prime
-// fields.
+// Package elliptic implements the standard NIST P-224, P-256, P-384, and P-521
+// elliptic curves over prime fields.
package elliptic
-// This package operates, internally, on Jacobian coordinates. For a given
-// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
-// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
-// calculation can be performed within the transform (as in ScalarMult and
-// ScalarBaseMult). But even for Add and Double, it's faster to apply and
-// reverse the transform than to operate in affine coordinates.
-
import (
"io"
"math/big"
@@ -21,12 +14,12 @@
// A Curve represents a short-form Weierstrass curve with a=-3.
//
-// The output of Add, Double, and ScalarMult when the input is not a point on
+// The behavior of Add, Double, and ScalarMult when the input is not a point on
// the curve is undefined.
//
// Note that the conventional point at infinity (0, 0) is not considered on the
// curve, although it can be returned by Add, Double, ScalarMult, or
-// ScalarBaseMult (but not Unmarshal or UnmarshalCompressed).
+// ScalarBaseMult (but not the Unmarshal or UnmarshalCompressed functions).
type Curve interface {
// Params returns the parameters for the curve.
Params() *CurveParams
@@ -67,6 +60,13 @@
return curve
}
+// CurveParams operates, internally, on Jacobian coordinates. For a given
+// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
+// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
+// calculation can be performed within the transform (as in ScalarMult and
+// ScalarBaseMult). But even for Add and Double, it's faster to apply and
+// reverse the transform than to operate in affine coordinates.
+
// polynomial returns x³ - 3x + b.
func (curve *CurveParams) polynomial(x *big.Int) *big.Int {
x3 := new(big.Int).Mul(x, x)
@@ -89,6 +89,11 @@
return specific.IsOnCurve(x, y)
}
+ if x.Sign() < 0 || x.Cmp(curve.P) >= 0 ||
+ y.Sign() < 0 || y.Cmp(curve.P) >= 0 {
+ return false
+ }
+
// y² = x³ - 3x + b
y2 := new(big.Int).Mul(y, y)
y2.Mod(y2, curve.P)
@@ -353,7 +358,8 @@
}
// Marshal converts a point on the curve into the uncompressed form specified in
-// section 4.3.6 of ANSI X9.62.
+// SEC 1, Version 2.0, Section 2.3.3. If the point is not on the curve (or is
+// the conventional point at infinity), the behavior is undefined.
func Marshal(curve Curve, x, y *big.Int) []byte {
byteLen := (curve.Params().BitSize + 7) / 8
@@ -367,7 +373,8 @@
}
// MarshalCompressed converts a point on the curve into the compressed form
-// specified in section 4.3.6 of ANSI X9.62.
+// specified in SEC 1, Version 2.0, Section 2.3.3. If the point is not on the
+// curve (or is the conventional point at infinity), the behavior is undefined.
func MarshalCompressed(curve Curve, x, y *big.Int) []byte {
byteLen := (curve.Params().BitSize + 7) / 8
compressed := make([]byte, 1+byteLen)
@@ -376,9 +383,9 @@
return compressed
}
-// Unmarshal converts a point, serialized by Marshal, into an x, y pair.
-// It is an error if the point is not in uncompressed form or is not on the curve.
-// On error, x = nil.
+// Unmarshal converts a point, serialized by Marshal, into an x, y pair. It is
+// an error if the point is not in uncompressed form, is not on the curve, or is
+// the point at infinity. On error, x = nil.
func Unmarshal(curve Curve, data []byte) (x, y *big.Int) {
byteLen := (curve.Params().BitSize + 7) / 8
if len(data) != 1+2*byteLen {
@@ -399,9 +406,9 @@
return
}
-// UnmarshalCompressed converts a point, serialized by MarshalCompressed, into an x, y pair.
-// It is an error if the point is not in compressed form or is not on the curve.
-// On error, x = nil.
+// UnmarshalCompressed converts a point, serialized by MarshalCompressed, into
+// an x, y pair. It is an error if the point is not in compressed form, is not
+// on the curve, or is the point at infinity. On error, x = nil.
func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) {
byteLen := (curve.Params().BitSize + 7) / 8
if len(data) != 1+byteLen {
diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go
index f5b36f7..5481929 100644
--- a/src/crypto/elliptic/elliptic_test.go
+++ b/src/crypto/elliptic/elliptic_test.go
@@ -182,6 +182,61 @@
}
}
+// TestInvalidCoordinates tests big.Int values that are not valid field elements
+// (negative or bigger than P). They are expected to return false from
+// IsOnCurve, all other behavior is undefined.
+func TestInvalidCoordinates(t *testing.T) {
+ testAllCurves(t, testInvalidCoordinates)
+}
+
+func testInvalidCoordinates(t *testing.T, curve Curve) {
+ checkIsOnCurveFalse := func(name string, x, y *big.Int) {
+ if curve.IsOnCurve(x, y) {
+ t.Errorf("IsOnCurve(%s) unexpectedly returned true", name)
+ }
+ }
+
+ p := curve.Params().P
+ _, x, y, _ := GenerateKey(curve, rand.Reader)
+ xx, yy := new(big.Int), new(big.Int)
+
+ // Check if the sign is getting dropped.
+ xx.Neg(x)
+ checkIsOnCurveFalse("-x, y", xx, y)
+ yy.Neg(y)
+ checkIsOnCurveFalse("x, -y", x, yy)
+
+ // Check if negative values are reduced modulo P.
+ xx.Sub(x, p)
+ checkIsOnCurveFalse("x-P, y", xx, y)
+ yy.Sub(y, p)
+ checkIsOnCurveFalse("x, y-P", x, yy)
+
+ // Check if positive values are reduced modulo P.
+ xx.Add(x, p)
+ checkIsOnCurveFalse("x+P, y", xx, y)
+ yy.Add(y, p)
+ checkIsOnCurveFalse("x, y+P", x, yy)
+
+ // Check if the overflow is dropped.
+ xx.Add(x, new(big.Int).Lsh(big.NewInt(1), 535))
+ checkIsOnCurveFalse("x+2⁵³⁵, y", xx, y)
+ yy.Add(y, new(big.Int).Lsh(big.NewInt(1), 535))
+ checkIsOnCurveFalse("x, y+2⁵³⁵", x, yy)
+
+ // Check if P is treated like zero (if possible).
+ // y^2 = x^3 - 3x + B
+ // y = mod_sqrt(x^3 - 3x + B)
+ // y = mod_sqrt(B) if x = 0
+ // If there is no modsqrt, there is no point with x = 0, can't test x = P.
+ if yy := new(big.Int).ModSqrt(curve.Params().B, p); yy != nil {
+ if !curve.IsOnCurve(big.NewInt(0), yy) {
+ t.Fatal("(0, mod_sqrt(B)) is not on the curve?")
+ }
+ checkIsOnCurveFalse("P, y", p, yy)
+ }
+}
+
func TestMarshalCompressed(t *testing.T) {
t.Run("P-256/03", func(t *testing.T) {
data, _ := hex.DecodeString("031e3987d9f9ea9d7dd7155a56a86b2009e1e0ab332f962d10d8beb6406ab1ad79")
diff --git a/src/crypto/elliptic/gen_p256_table.go b/src/crypto/elliptic/gen_p256_table.go
index 367bd4b..0ebbc66 100644
--- a/src/crypto/elliptic/gen_p256_table.go
+++ b/src/crypto/elliptic/gen_p256_table.go
@@ -7,30 +7,13 @@
package main
import (
- "bytes"
"crypto/elliptic"
"encoding/binary"
- "fmt"
- "go/format"
"log"
"os"
)
func main() {
- buf := new(bytes.Buffer)
- fmt.Fprint(buf, `
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Generated by gen_p256_table.go. DO NOT EDIT.
-
-//go:build amd64 || arm64
-
-package elliptic
-
-`[1:])
-
// Generate precomputed p256 tables.
var pre [43][32 * 8]uint64
basePoint := []uint64{
@@ -70,41 +53,21 @@
}
}
- fmt.Fprint(buf, "const p256Precomputed = \"\" +\n\n")
+ var bin []byte
// Dump the precomputed tables, flattened, little-endian.
// These tables are used directly by assembly on little-endian platforms.
- // Putting the data in a const string lets it be stored readonly.
+ // go:embedding the data into a string lets it be stored readonly.
for i := range &pre {
- for j, v := range &pre[i] {
- fmt.Fprintf(buf, "\"")
+ for _, v := range &pre[i] {
var u8 [8]byte
binary.LittleEndian.PutUint64(u8[:], v)
- for _, b := range &u8 {
- fmt.Fprintf(buf, "\\x%02x", b)
- }
- fmt.Fprintf(buf, "\"")
- if i < len(pre)-1 || j < len(pre[i])-1 {
- fmt.Fprint(buf, "+")
- }
- if j%8 == 7 {
- fmt.Fprint(buf, "\n")
- }
+ bin = append(bin, u8[:]...)
}
- fmt.Fprint(buf, "\n")
}
- src := buf.Bytes()
- fmtsrc, fmterr := format.Source(src)
- // If formatting failed, keep the original source for debugging.
- if fmterr == nil {
- src = fmtsrc
- }
- err := os.WriteFile("p256_asm_table.go", src, 0644)
+ err := os.WriteFile("p256_asm_table.bin", bin, 0644)
if err != nil {
log.Fatal(err)
}
- if fmterr != nil {
- log.Fatal(fmterr)
- }
}
diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go
index a8533b8..8a431c4 100644
--- a/src/crypto/elliptic/p224.go
+++ b/src/crypto/elliptic/p224.go
@@ -61,6 +61,9 @@
if x.Sign() == 0 && y.Sign() == 0 {
return nistec.NewP224Point(), true
}
+ if x.Sign() < 0 || y.Sign() < 0 {
+ return nil, false
+ }
if x.BitLen() > 224 || y.BitLen() > 224 {
return nil, false
}
diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go
index 7ff7e33..e1c6ff4 100644
--- a/src/crypto/elliptic/p256.go
+++ b/src/crypto/elliptic/p256.go
@@ -6,11 +6,11 @@
package elliptic
-// This file contains a constant-time, 32-bit implementation of P256.
+// P-256 is implemented by various different backends, including a generic
+// 32-bit constant-time one in this file, which is used when assembly
+// implementations are not available, or not appropriate for the hardware.
-import (
- "math/big"
-)
+import "math/big"
type p256Curve struct {
*CurveParams
diff --git a/src/crypto/elliptic/p256_asm.go b/src/crypto/elliptic/p256_asm.go
index ff0c159..8624e03 100644
--- a/src/crypto/elliptic/p256_asm.go
+++ b/src/crypto/elliptic/p256_asm.go
@@ -15,11 +15,15 @@
package elliptic
import (
+ _ "embed"
"math/big"
)
//go:generate go run -tags=tablegen gen_p256_table.go
+//go:embed p256_asm_table.bin
+var p256Precomputed string
+
type (
p256Curve struct {
*CurveParams
diff --git a/src/crypto/elliptic/p256_asm_table.bin b/src/crypto/elliptic/p256_asm_table.bin
new file mode 100644
index 0000000..20c527e
--- /dev/null
+++ b/src/crypto/elliptic/p256_asm_table.bin
Binary files differ
diff --git a/src/crypto/elliptic/p256_asm_table.go b/src/crypto/elliptic/p256_asm_table.go
deleted file mode 100644
index ad2c6c2..0000000
--- a/src/crypto/elliptic/p256_asm_table.go
+++ /dev/null
@@ -1,1430 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Generated by gen_p256_table.go. DO NOT EDIT.
-
-//go:build amd64 || arm64
-
-package elliptic
-
-const p256Precomputed = "" +
-
- "\x3c\x14\xa9\x18\xd4\x30\xe7\x79" + "\x01\xb6\xed\x5f\xfc\x95\xba\x75" + "\x10\x25\x62\x77\x2b\x73\xfb\x79" + "\xc6\x55\x37\xa5\x76\x5f\x90\x18" + "\x0a\x56\x95\xce\x57\x53\xf2\xdd" + "\x5c\xe4\x19\xba\xe4\xb8\x4a\x8b" + "\x25\xf3\x21\xdd\x88\x86\xe8\xd2" + "\x85\x5d\x88\x25\x18\xff\x71\x85" +
- "\x4d\xd6\xdd\x10\xd4\x46\x00\x85" + "\x7d\x82\x33\xa4\xc1\xe3\x6a\xaa" + "\xd9\x90\x14\x8d\x03\x05\x22\x73" + "\x3b\x3a\xcf\x3d\xe4\x32\xbb\xf6" + "\xa5\xe1\xbe\x61\xd3\x48\x36\x2f" + "\xf8\x6f\x23\xeb\xcb\xd7\x2c\x15" + "\xbe\x2d\x04\x92\x0e\xfb\xa8\x19" + "\x3b\x8a\x5b\x0a\x51\x77\xc5\x78" +
- "\x27\xc1\xeb\x4e\x90\x3f\xac\xff" + "\xfb\x81\x7d\x08\x4a\xf8\x27\xb0" + "\x98\xbc\xcb\x87\xdd\x77\xad\x66" + "\x7e\x74\xff\xb6\x3f\x6a\x93\x26" + "\xeb\xa7\x83\xc9\x1f\x5c\x4c\xb0" + "\x1a\xfe\x61\x08\xad\x47\x3e\x58" + "\x8e\xe9\x2e\x1a\x31\x08\x82\x78" + "\x07\xcc\x87\xe5\x29\x6a\xf0\xd5" +
- "\xcc\x8d\x91\x46\x0d\xb5\xb0\x74" + "\x73\xc1\x23\xc6\xed\xa6\x50\x46" + "\xf2\x0a\x10\xe8\xac\xac\xda\x0c" + "\x6b\x17\xb0\x41\xf5\x62\x73\x57" + "\xa6\xab\xcb\xe4\x4c\xf2\x96\x2d" + "\x47\xf4\xd6\xfa\x71\x84\x62\x17" + "\x2e\xd2\xdd\xe5\xde\x36\x6c\x6b" + "\x63\xb8\x5a\x4c\x39\x4c\xb1\x84" +
- "\xf5\x61\x5c\xc4\xae\x8a\x1b\xbe" + "\x7d\x53\xb9\x94\x9a\x64\xec\x90" + "\x0c\xc2\x76\xd0\xaa\xb5\x1c\x94" + "\xc8\x23\x05\x89\x05\x96\x07\xc9" + "\x10\x4f\xba\xe7\x4a\x9b\x30\xeb" + "\x2b\x88\xeb\xe5\xef\x68\xc5\x73" + "\x68\x1f\x7a\x7e\x87\xa9\x40\x35" + "\x16\xe9\xd1\x2d\xbb\x76\xa0\x73" +
- "\x4a\x66\x77\x3e\x37\x47\x39\x40" + "\x3e\xee\x6c\x34\x4f\x74\xae\x55" + "\xad\xa3\x17\x5b\x1a\x96\x0a\xd5" + "\x73\x36\x21\x54\x59\x4b\x07\x13" + "\x4b\xe4\x77\xd3\x20\x62\xd3\x93" + "\xb5\x14\xff\xad\x53\x2b\x9c\x29" + "\x11\x9f\x63\xef\x4c\xd4\x24\xf4" + "\x5f\xf7\x07\x4a\x6d\x91\xc9\xa4" +
- "\x4f\x3b\x17\xa0\x4e\x35\x46\x07" + "\xf7\x00\x3c\xd2\x13\x02\xd2\x2b" + "\x08\xbb\x23\x0c\xb5\xaa\x3e\xf4" + "\x03\x3e\x12\xc3\x19\x51\xba\x13" + "\x4d\x9d\x5b\x3f\x30\xd0\x47\x28" + "\xdd\x7b\xa6\x5d\xf2\xf2\x42\x67" + "\x95\x41\xc9\x77\xdc\x3b\x93\xef" + "\x67\x08\x24\x6e\x15\xd9\xed\xea" +
- "\x8f\xa7\x99\x94\xd1\x4c\xf1\x27" + "\x55\x34\x9b\x6f\xc5\xb5\x2a\x46" + "\x6b\xfc\x2c\xf0\x2a\xf0\x90\x8f" + "\x0d\x23\x65\xb2\x1e\x89\x63\xb7" + "\x77\x49\x2d\x53\xa9\xa3\x9d\xf5" + "\x15\xba\x9e\xcf\x7d\x32\xe3\x21" + "\xf0\xbb\x60\xbe\x84\x7b\x3c\x12" + "\x76\xdf\x06\x77\xf2\x12\xec\x56" +
- "\xe8\x20\x4e\x26\x8f\x6e\xc9\x75" + "\x41\xa8\xa7\x59\xed\xbf\xe6\xab" + "\x00\xeb\xc8\x44\x04\x9c\xc0\x2c" + "\x6b\xe1\xc4\xf0\x80\x30\x5b\xe0" + "\x14\x33\x5f\xa4\x7a\x77\xb7\x1e" + "\xe3\x45\x5d\xce\xed\x7b\xaf\x56" + "\x1a\x2f\xb1\x88\x9a\x01\x6e\x2b" + "\x9b\x5f\x83\xfd\xcd\x59\x66\x08" +
- "\xc8\x1e\xc2\x9d\xd1\xdb\x18\x2c" + "\x39\x81\xcf\x0f\x8a\x86\xf9\x98" + "\x49\x0b\x25\x48\xd6\x2c\x7d\x73" + "\x8f\x42\xb3\x24\x47\xc9\x61\xcc" + "\x76\x9e\xdd\x80\x78\x40\x2b\x0c" + "\x08\xbe\x3f\x38\x91\x89\x3a\xc4" + "\xd2\xe5\x9b\x77\x65\x2d\x7d\x5f" + "\xb5\x4a\x3b\xeb\x54\x9a\x71\x78" +
- "\x04\xe4\x45\x62\x0a\x26\x7d\xea" + "\xe0\xdf\x7f\x6e\x95\x07\xe4\x9d" + "\xb5\x1a\xac\x8d\x15\xa4\xf3\x1f" + "\x73\x90\x9c\x64\xf1\x90\x70\x3e" + "\x88\x4e\x94\x2b\x61\x85\x76\x1a" + "\xc8\x61\x7f\xe5\x9e\x93\x0f\x25" + "\x3d\x64\xad\x1e\x89\xaa\x0d\x0c" + "\x8e\xb8\x25\xe1\x23\x00\x93\x68" +
- "\x68\x77\x69\xd2\xa7\x1a\xb7\x04" + "\x33\x5a\x34\xca\xf5\xde\xde\xab" + "\x5e\x38\x37\xee\x9d\xd2\x09\x24" + "\x56\xe1\x83\xcb\x77\xdf\xe1\x4e" + "\x43\x5b\xbb\x1c\xd9\x12\xac\x0c" + "\x37\x56\x89\xca\xf6\xd2\x0e\x17" + "\x66\x6d\xde\x8a\xfa\x8c\x22\x28" + "\xca\x8a\x23\x53\x95\x7c\xf5\x7f" +
- "\x09\xd7\x2e\x4b\x63\x25\xc4\xcc" + "\x0d\xd3\x6f\x85\x69\x67\x35\x0e" + "\x11\x98\x9e\x55\x3f\xd4\xbc\xbc" + "\x59\xb7\x95\x53\xac\x77\x84\x73" + "\x7f\xe1\x0e\xc0\x90\x2b\x75\x35" + "\xe3\xd2\x2e\x74\x90\x83\x74\x68" + "\xc1\x5b\x1f\xbd\x22\x64\xd0\x7c" + "\x97\xb7\xe7\xc9\x69\x87\xc0\xfb" +
- "\x4a\x66\xcf\xb0\x5b\xa3\x42\xa2" + "\xe3\x07\x97\x7f\xf7\x48\x6e\x12" + "\x60\x26\x83\xc6\x54\xbf\x17\x17" + "\x2e\xc7\x12\xfd\x32\x73\xae\xfa" + "\x6b\x58\x5d\x99\xb7\x2d\xb5\x27" + "\xc2\x37\x22\x83\x9e\x56\x29\xbe" + "\xdb\xe7\x65\x2a\x3e\x19\xe4\xe8" + "\xbb\x1b\xaa\x2e\xdc\x06\x27\x15" +
- "\x5b\x05\x60\xbc\xb7\xd8\xbc\x72" + "\x4b\x7e\xe2\x56\xee\x23\xcc\x03" + "\x70\x93\x81\xe4\x24\x74\x33\xee" + "\x09\xda\xd3\x0a\x43\x0e\xaa\xe2" + "\x5d\xc4\x83\x63\x4f\x52\xb8\x40" + "\x25\x1b\xa4\x42\x54\x35\x66\xd7" + "\x97\x47\x8a\x77\xde\xa6\xef\x64" + "\xf4\xad\x79\x70\x0a\x17\x42\x20" +
- "\x80\xfb\xc6\x0b\x65\x0b\x8b\x80" + "\x6b\x2e\xfe\x3f\x75\xe0\x82\x58" + "\x49\xf5\x83\x2c\x7c\x2f\xef\xd5" + "\x23\xb7\x03\x91\x80\x3c\xd6\x54" + "\x9b\x3f\xa2\x52\xd6\x1b\xf1\xf2" + "\x87\x65\x0b\x4b\x19\xc3\x70\x36" + "\x9e\x0e\x58\xb1\x3b\x62\xc4\x55" + "\x20\xe2\xef\x01\xb2\xf7\xed\x64" +
- "\x9d\x5c\x3c\xd5\xcb\x1d\x09\x97" + "\x7b\x17\x0a\xac\xb6\x24\x76\xf1" + "\xff\x2d\xfe\x2c\x75\x39\xf1\xb0" + "\x4e\x57\x7a\x6c\x0a\x5c\xa3\xc1" + "\x87\x99\xe7\x93\x46\x31\x7d\x22" + "\x0e\xb8\x9c\xe8\x30\xbf\x75\x05" + "\xbb\x83\x18\x0d\x7f\x24\x4e\x2f" + "\xd0\xc3\x74\x32\x26\x12\xd5\xeb" +
- "\x7a\xa9\xad\x56\xc8\x51\x3e\x5f" + "\x3e\x40\x8b\x8f\x4d\x96\xfc\x4a" + "\x79\x29\x2e\x41\xab\x47\xf2\xa6" + "\xda\xeb\x80\x6f\x1b\xbd\x5a\x67" + "\x1d\x5a\x48\x5e\x72\xbd\xa2\x66" + "\x3c\x0b\x4f\x8f\xaf\x5c\x2a\x4b" + "\xba\x7b\x84\x1b\x7f\x92\x26\x26" + "\x4d\x39\x02\x05\xd9\xc7\x6f\x6c" +
- "\xe8\x9a\x65\xa5\xba\x12\xa9\xfe" + "\x6e\xa1\xe1\x25\xba\x3a\x36\x68" + "\xac\x41\x2c\x75\x77\x22\x84\xb8" + "\xfc\xc3\x97\x28\x28\x5c\x54\xfe" + "\x6b\x69\x4c\xdc\xe7\xe9\x36\x2d" + "\xc5\x77\xa9\xfb\x4a\x24\x06\x58" + "\xc1\x08\x95\xe3\x9b\x5e\x66\x85" + "\x7b\x59\x12\x6d\x25\xee\x20\xf7" +
- "\x31\x7a\x33\xd2\x29\x91\x97\x8a" + "\xdc\x2b\x86\x0f\x8f\x86\x16\x59" + "\xba\x83\xd2\x5d\xd9\x99\x80\x04" + "\x4e\xfb\x5b\xfe\xb6\xee\xd1\xe2" + "\x5d\x00\x84\x78\x41\x1c\xef\x82" + "\xae\xcb\xff\xff\x17\xec\xd4\xa2" + "\x66\x5e\xa9\x8a\x3f\xc5\x61\x91" + "\xd0\xe0\xfe\xc5\xe1\x04\xe1\x5e" +
- "\x08\xb2\x35\xc1\xec\x4c\x2e\x56" + "\x7d\xf4\x83\x47\x65\xb2\xe1\x74" + "\x30\x3b\x3f\x5a\x6c\x50\x2a\x6d" + "\xfc\x62\x67\xc1\xf4\xd9\xea\xec" + "\xb9\xe5\x86\xe2\xb2\xd4\x9d\xf2" + "\x61\x3c\xbb\x83\xc0\xad\x0f\x1b" + "\xa4\x29\xac\x7f\x3e\x02\x75\x7a" + "\xa3\x7f\x47\xc9\xf1\xd5\x86\xc0" +
- "\x76\x30\x6f\x2f\x35\x11\xc6\x0f" + "\x9a\x2a\x91\xe3\x23\xfa\x9f\xc9" + "\x3d\xba\xf8\xd2\x85\x06\x0b\x6a" + "\xa4\x58\x33\xe9\xe8\x77\xc7\xfd" + "\x04\x5f\x41\x35\xbb\x87\xa7\x94" + "\xa4\xfe\x23\x4d\x6a\x2d\x0c\x64" + "\xb5\x35\x3a\x15\xda\x17\xe9\x9d" + "\x74\xd0\x5c\x5d\x07\x8d\x3e\x79" +
- "\x68\x50\xe4\x2d\x53\x76\xf8\xf4" + "\x6e\x1f\x2e\x9e\xe8\xa7\xc7\x37" + "\x69\x40\x58\xa3\xa2\x5f\x82\xd0" + "\x42\xbf\x27\x17\x7c\xea\x2c\xaf" + "\xa9\x85\x47\x9e\xfb\xa4\x60\x03" + "\x4a\x9f\x29\x27\x9c\xa4\xfd\xe5" + "\x71\x2f\xac\x71\x13\x8e\x06\x48" + "\x6f\x66\x77\x90\x7b\x68\xd0\x83" +
- "\x19\x28\xd0\x15\xb2\x83\x38\x6d" + "\x35\x9a\xdd\x40\x50\x75\x0d\x6d" + "\x9f\x46\x2b\x1d\xf9\xcb\xd7\x61" + "\x15\x31\xfc\x2e\x2f\x23\x7b\xf9" + "\xc7\xcb\x4b\xb2\x50\xd7\x51\xa5" + "\x56\xe3\xa1\x88\x49\x49\xea\x11" + "\x01\x75\xcb\x93\x31\xf0\x69\x76" + "\x8a\x7b\x73\xca\x5e\xc5\x5d\x59" +
- "\x9f\x87\x37\xd8\xac\x19\xa3\xa4" + "\xb0\x67\x6b\xed\x9e\xb4\xc1\x6f" + "\xaf\xf3\xf1\x32\x33\x99\x95\xe3" + "\x2e\x2a\x43\x65\xeb\x42\x67\x96" + "\x28\x62\x96\xb4\xfe\xc9\x8d\x4b" + "\x50\x39\xf4\x43\x12\x63\xcc\x96" + "\xee\x31\xb7\xc9\x59\x88\x06\x12" + "\x68\x99\xf7\x56\xc3\x8d\x94\x7b" +
- "\x08\x80\x1f\xed\x32\xad\xe4\x61" + "\x38\x75\xb1\xd8\x7a\x26\xc9\xe6" + "\xfb\xf6\x7f\x85\xeb\xc5\xc7\x1a" + "\x10\xfb\xf2\x55\xa8\xaa\x4b\x99" + "\x18\x80\x24\x1d\xe1\x14\xcf\x84" + "\x08\xc5\x8a\x62\x8b\x89\x39\x5a" + "\xf5\x44\xa9\x5f\x7b\xe9\xfd\x14" + "\xc7\x5a\x2e\xd1\x30\x80\x17\xed" +
- "\xb4\xfe\xe2\x97\xf4\x2a\x2c\x04" + "\x13\x73\xbf\xae\xd7\x42\x6a\xd3" + "\xd7\xfd\x4f\x08\xeb\xc9\xd2\x49" + "\x6a\xc7\xf7\x2e\x4b\xa5\x8a\x9f" + "\x70\x5e\x89\x09\xba\xb7\x00\x92" + "\x58\xfb\xb7\xdd\x6f\xc6\xd0\x3b" + "\xbb\x4c\xeb\x78\x08\xd1\x97\x2d" + "\x31\xde\x4b\xd8\x68\x10\x43\x2d" +
- "\x1f\xcd\x2c\x17\xb7\x3e\x52\x4b" + "\x92\xa8\xa6\x30\x28\xcb\x23\x73" + "\xeb\x53\xe1\xcf\xc0\x2e\x08\x97" + "\x97\xdb\xaa\xf2\x6a\x6b\x7f\xe9" + "\xa1\x3d\xa8\xd1\x3e\x39\x3d\x1d" + "\x68\x2a\x4b\x80\xc7\xf9\xa7\xa6" + "\x1e\xb7\x0c\x2d\x48\x8b\x68\x4a" + "\x78\x52\x58\x40\x5f\xcc\xb4\xa9" +
- "\x32\xe1\x66\xcb\x6a\xb4\x5d\x5e" + "\x80\x58\x92\x0d\x3a\x96\xbe\xf1" + "\xe2\xb9\x17\x03\x27\x70\x4a\x94" + "\x48\x3d\x60\x48\x59\xf9\x66\xe2" + "\x99\x88\x20\x5c\x73\x66\xdb\x98" + "\xa3\x18\xfb\xa2\x47\x24\x47\x90" + "\x9f\x61\x7c\x77\x39\x69\x96\x8a" + "\x1b\xe2\x3b\x2a\x2a\x14\x98\x37" +
- "\x43\xb3\x98\x32\xb1\x1c\x24\xb4" + "\xa1\x65\x4f\xb4\x49\x4e\xa1\xa3" + "\xcd\x7a\xc7\x3a\xcd\xd6\xf4\xc5" + "\x3c\xfc\xb6\x52\xb5\x8c\x28\xd0" + "\xbc\x0a\x04\x1c\x2f\x8c\xcc\xd5" + "\x4a\x9b\xbf\x06\x1e\x51\x75\xb6" + "\x41\xa4\x3a\x9b\x37\xda\x67\xd6" + "\x72\x1f\x60\x51\xce\x45\x0d\x46" +
- "\x89\xff\x55\x67\x69\x3c\xf7\xe2" + "\xe6\x17\x30\x47\xe7\xf7\x3c\xdd" + "\x0d\x60\xf7\x3c\x9d\x68\xf5\x8e" + "\xb4\x87\xfc\xb1\xf8\xc4\x8d\x94" + "\x99\x32\xa5\x4e\x81\xfe\xe9\xd9" + "\x28\x60\xeb\x98\xa2\x1c\x92\x2d" + "\xfc\x03\x98\x0c\xfd\xed\xec\xfa" + "\x45\x47\x7b\x4d\x91\xe8\x8a\xf3" +
- "\xd8\xa3\xe3\xc5\xcf\xfc\xc5\xd8" + "\xbf\xdf\x79\x40\x4c\x90\xfd\xbe" + "\x97\x01\xad\xfe\x58\x6a\x6d\xbc" + "\xa4\x32\x55\x69\x77\x70\x22\x39" + "\xf5\x42\xef\xdb\x6d\x3e\xe2\x09" + "\x08\x99\x0a\x48\x64\x9b\x44\x7e" + "\x40\x2e\x9a\xad\x1a\x9c\x96\x7b" + "\xa4\xc2\x91\x95\x92\xd7\x31\x62" +
-
- "\x80\x8b\x96\x05\xf3\x96\x6d\xdb" + "\xb9\x73\x9f\x08\x13\x09\x0a\x38" + "\x01\x1e\xc6\xc2\x83\x0b\xa7\x7d" + "\xc7\x38\x9b\x56\x94\x83\xfb\x95" + "\x2f\xfe\xed\x80\x12\x65\x3c\x9a" + "\x82\xaf\xae\x8f\xb9\x6b\x72\x8f" + "\xf8\x4b\x42\x78\xa0\xa4\x10\x80" + "\x70\x49\x84\x0e\x44\x20\x67\x29" +
- "\x2a\xd6\x2a\x7a\x81\xcb\xc5\x63" + "\x54\xff\x62\xac\xb9\xb6\xf2\x7e" + "\xb5\x9d\xad\xb3\xa4\xbb\x49\x37" + "\x17\xa6\xd5\x46\x2c\x1f\x31\xad" + "\x6d\x3b\xff\xc2\x87\x80\x7a\xb7" + "\xff\x34\x78\x36\xf3\xea\x6f\xb4" + "\x38\xb1\xd6\x75\x6d\x26\xaa\xf8" + "\x88\x81\x00\xec\x20\xd3\x38\xfa" +
- "\xc6\x16\x69\x4e\xfc\xaf\xf2\xc0" + "\xda\x42\x18\x81\x57\x49\xb9\x6f" + "\x57\xd1\xb4\x24\xb6\xbc\x34\x60" + "\x90\xfb\x2e\x99\xc7\xfd\x2e\xde" + "\x87\x3c\x79\xac\xce\x7e\x6f\xd6" + "\xcd\xfd\xc6\x7d\x26\x26\xf0\x02" + "\x01\xc5\xa1\x9a\x5c\x23\xd3\x90" + "\xf0\x66\x46\x2b\x96\x94\xe4\xf6" +
- "\xfc\x46\x69\x69\xfa\x8f\x6d\x48" + "\x6d\xa5\xcb\xb9\xd8\xc6\xfb\x50" + "\x15\x5a\xf3\x90\x3e\x42\x3d\x7e" + "\x2c\x96\xdd\xc0\x95\xa1\x3d\x7c" + "\x8b\x5d\xfd\x3c\xb0\xfd\x73\xe6" + "\xa5\xfc\x9d\x88\xc2\xb7\x04\x07" + "\xaa\x05\x23\xf5\x1f\x58\xce\xf6" + "\x53\x5e\x4d\x91\xeb\x49\x9d\x39" +
- "\x53\xd4\x92\x7b\x36\x7c\xc9\x24" + "\xc0\x26\x9a\x24\xa2\x71\xc2\xd2" + "\x39\x4a\xd1\x89\x2b\x4b\xeb\x60" + "\x05\x80\x2e\x43\x20\xde\x98\x11" + "\xd9\x80\x9b\x79\x75\xea\xab\x9e" + "\xe5\x6a\x82\x8f\x2b\x0c\x6e\xab" + "\xec\x61\x00\xd1\xed\x4e\x00\xca" + "\xd8\x4f\x9c\xe9\x39\xf4\xa9\x31" +
- "\xcd\x93\xc2\x6e\x6d\x49\x0a\x38" + "\xf5\x51\x70\x8e\xa7\xbd\x3d\x73" + "\x0a\x14\x49\xb8\x8d\x38\x7e\x03" + "\xf6\xdb\x46\x59\xb0\x32\x4b\xee" + "\xd1\x68\xe3\xca\xa9\xfd\xc4\xb1" + "\xf3\xb2\xb0\xfd\xb0\xa7\x01\x50" + "\x6e\xc4\x3a\x2e\x74\x93\xf5\x6d" + "\x56\xe6\xb3\x39\xf2\x75\xf6\x4a" +
- "\xeb\x26\x78\xd6\x44\x7c\x0e\xb2" + "\x37\x96\x37\xac\xcf\xd3\x12\x12" + "\x5d\x3a\xe0\x7d\x87\x67\x4f\x61" + "\x26\xaa\x2b\x80\xfc\xa2\x38\x75" + "\x15\x24\x25\x9d\xa1\x37\x3c\x13" + "\x87\xb5\xb4\x6e\x50\x90\xb3\x7d" + "\xd9\xd1\x49\x4c\x57\xd7\x40\x5d" + "\xba\xc4\x01\xa8\x99\x6b\x12\xf1" +
- "\x96\x92\x94\x39\x10\x81\xe3\x44" + "\xb5\xb1\x1d\x36\x7b\x82\x63\x5b" + "\xf5\xaf\x6e\x20\xed\x23\x53\x3e" + "\x90\x42\x1f\xc2\xd2\x70\x23\x94" + "\xa1\x85\xd9\xe0\x2e\xaf\xca\xf2" + "\x6d\x84\x39\x72\x4b\xc6\x2c\x19" + "\xf8\x12\x63\xae\x47\x8f\x0b\x7c" + "\x08\x01\x62\x96\x91\x1f\xc6\x7d" +
- "\x47\x11\x96\x70\x96\xc9\xff\x40" + "\x8c\x2c\xc2\xc7\x42\x68\xe0\x79" + "\xbd\xbb\x97\x1a\xcc\xab\xf1\x63" + "\x88\x03\x73\xf0\xd0\x74\xea\xe9" + "\x66\xff\xef\xd9\x4d\x50\xc3\xa6" + "\x15\x20\xe0\x57\x38\xee\x54\x53" + "\xfa\x40\x70\x6d\xfe\xd7\xfe\x3b" + "\xac\x82\xca\x99\xcc\x95\x2c\x69" +
- "\xe9\x7d\xda\xc2\x5b\xfb\x30\xb8" + "\xbe\xd3\xf8\x0f\xdf\x43\xe6\xd0" + "\x41\x96\x8a\x18\xba\x77\xee\x31" + "\x02\xd5\xf6\xbc\xaa\xa3\x8a\x4e" + "\x0f\x11\x49\x9a\x32\x65\xfb\xf9" + "\x20\xb2\xd6\x2d\xf6\x17\x83\xd1" + "\x5a\xea\xc3\x52\x41\xed\x3c\x7e" + "\x4a\x9c\x57\x7d\x14\x6a\x29\x0d" +
- "\x58\x6c\x2f\x94\xca\x5a\x8b\x68" + "\x39\x94\x5d\x49\xc5\x89\x27\x6f" + "\x1d\x50\x4c\x50\x0c\xdb\x4d\xd5" + "\xa7\xe3\xac\xbc\x0f\x4d\x6a\xf1" + "\xeb\x41\x6a\x05\x6f\xbc\x6f\xb7" + "\xc5\xd6\x5b\x82\x55\xc2\x88\xe2" + "\xd3\xe2\x42\x0f\x96\x77\x03\x95" + "\x44\x7b\xb5\xde\xe3\x47\x3c\x9a" +
- "\x17\x37\x4c\xed\x3e\xa5\xd6\x35" + "\xa3\xd2\x0e\x3d\xcf\x40\x82\x9f" + "\xa5\x3a\x54\xe5\x05\x4d\x0d\x8c" + "\xb4\xb4\x33\xdd\xfb\xbb\xd5\x45" + "\x8e\xd2\x7f\x13\x73\xcc\x04\xfa" + "\xfd\x3f\x3b\xc7\xef\xc6\x2a\x86" + "\xf2\x1e\xf5\x31\xf5\xf9\x3f\x40" + "\xa2\xf5\x73\xbc\xfc\xe0\xd5\x34" +
- "\xb0\xfa\x59\x95\x21\xef\x9a\x2c" + "\x2d\x2f\x32\x62\xce\x61\x33\x83" + "\xf9\x0d\xba\x72\x2b\x5e\xfd\xd3" + "\x0a\x8c\x2d\x9d\x32\xe7\x85\xfc" + "\xd4\xb8\x5d\xf1\x75\x46\x23\xce" + "\x9a\x3f\x2d\xf5\x2e\xac\xf7\x6a" + "\x92\x65\xbf\x3d\x69\xf1\x55\x2d" + "\x38\x8e\x09\xd7\x6c\xcc\xc9\xb1" +
- "\x4f\x3f\x91\x08\x20\x68\x52\xf2" + "\x95\x3d\xc9\xea\x61\xed\x20\xea" + "\x6c\xb2\xa6\x6c\xb4\x38\xed\x51" + "\xb0\x27\x43\xea\xbc\xdc\x62\x86" + "\xaa\x2a\x5d\x72\x5c\x29\xaf\x6d" + "\xda\xdc\x52\x8e\x2f\x75\xd2\xba" + "\xcc\xda\x17\x0b\x21\xe7\x10\x22" + "\x32\x82\x1e\xd5\x12\x79\x7f\xa3" +
- "\xeb\xca\x40\xd5\x0c\x16\x00\x2a" + "\x88\x27\x1a\xa4\x5e\x14\x66\x6f" + "\xfa\x11\xc8\x51\x33\x1c\xc8\xf9" + "\x03\x54\x6f\x64\x0f\x8e\xe5\xee" + "\xe3\xfa\x18\xfc\xef\x20\xf9\x8d" + "\x6c\xea\x71\x09\x5e\x42\x23\x79" + "\xa7\xae\xa0\xcb\xb2\xdc\xe3\xe0" + "\xfc\x2d\x85\x4a\x5e\xaf\x1d\xbf" +
- "\xdd\x3a\xcc\x44\xe1\x81\x70\x4f" + "\xcf\x82\xbe\x87\xd6\xa1\xff\xd5" + "\x72\x64\xdd\x0e\x6c\x0b\x89\x89" + "\x63\x78\xd1\x3e\x1a\x6e\xa2\xad" + "\xaa\x3c\x48\x63\x15\x27\x6f\x27" + "\xfd\x77\x60\x2f\xd9\x4c\x92\xe6" + "\x3c\x6e\x46\x0a\x98\xfe\xa7\x05" + "\x1f\x2d\x90\xb1\xb0\x94\xc7\xf1" +
- "\x1c\x9c\xf0\xaa\x57\x63\x06\xee" + "\xd2\x76\x27\xab\x8d\x87\x53\x1c" + "\x4a\x32\x4e\xae\x4c\x72\xb5\x2c" + "\x52\x83\xfe\xe0\xad\x7c\x30\x13" + "\x96\x56\x39\x54\x78\xbb\x02\xef" + "\x31\x4d\xb6\xb3\xf3\x2d\x59\x2c" + "\xeb\x6a\x8b\xbc\x1a\x95\x05\xf0" + "\x5e\x27\x91\x6b\x82\xbe\x60\x57" +
- "\x2c\x04\xa8\x82\x88\x36\x21\xe5" + "\x98\x82\x27\xcd\xaf\xcf\x31\xd9" + "\x40\xa7\x97\xf5\xe0\x0a\x9a\x06" + "\x7c\x10\x59\xeb\xf3\xb3\xdb\x0a" + "\xb8\x8e\xaa\x5e\x1e\x95\x3e\x98" + "\x78\x8e\xb4\x11\xb5\xa8\x63\xe6" + "\xc5\xf2\x03\x8a\x0d\xcc\x31\x16" + "\xe2\x71\xe2\x11\x1e\xc1\x77\x75" +
- "\xf6\x8f\xa0\x74\x41\xbf\x5d\x08" + "\x0b\x46\x76\xa5\x40\xce\xba\x80" + "\x49\xba\xc1\x27\xcf\xcb\x04\xd2" + "\x49\x69\x80\xe4\x32\x2f\xd1\x64" + "\xe3\xe8\xdf\x01\x22\x22\xd4\xcd" + "\xd4\x83\x5c\xd0\x6e\x3c\x5b\x3b" + "\xc0\x00\xeb\xfc\xb3\x81\xc0\xb2" + "\x69\xd7\x67\xdd\xec\x3e\xc2\xe2" +
- "\x90\x9a\x36\x08\x5c\x38\xb2\x33" + "\xf8\xb4\x0e\x19\x9b\xc5\x90\x29" + "\x80\xac\x8e\xc6\x45\x61\x9a\x81" + "\x14\xa0\xc4\x2e\x62\x6d\x78\x7a" + "\x8d\x3a\xac\x20\xbe\xad\xfa\x33" + "\x30\x2d\xba\x5a\x81\x17\xa2\x31" + "\x65\xf5\xa4\xdb\x42\x27\x9d\x20" + "\xbb\x0f\xaa\x55\xe3\xe9\x2c\xdb" +
- "\xad\xe1\xcc\x63\xb5\x24\x4f\x6f" + "\x77\x3a\xb4\x9f\x2a\x67\x66\x51" + "\x1f\x9d\xc7\x4f\x78\x40\x78\xbb" + "\xf5\xbb\x74\xf7\x6c\x1a\x82\xb3" + "\x41\xf4\x02\xdf\xce\xd4\x7b\xa2" + "\xdf\x2a\x4e\xb8\xb9\x4e\xfa\xc5" + "\xde\xcd\xb7\xf0\xd7\xcb\x0b\x91" + "\xec\x1e\x5a\x2e\x48\x40\xe6\xb7" +
- "\xdf\x84\x89\x16\x4b\x33\xef\x8c" + "\x38\x96\x87\x33\x17\xce\x1d\xe8" + "\xf0\x20\x37\x26\x9c\x94\xe6\xf6" + "\xec\xcb\x93\xf5\xaf\xfe\x56\x5c" + "\x84\x8c\xe5\xfd\x01\x56\xff\x8b" + "\x14\xb3\xcc\x2e\x17\x41\xe2\x74" + "\x78\x8a\x9a\x4c\x61\x1b\xf0\xbc" + "\x68\x98\x4c\x54\x5e\xe3\x33\xa2" +
- "\xfb\xd8\x65\xc7\xc9\x4b\x93\x54" + "\x1e\x75\x0b\xb3\x71\x65\x96\xc1" + "\x17\xc8\xa7\x91\xcf\x2f\xfd\xc4" + "\x88\xc8\xb1\xdc\x7e\xbc\x6f\x24" + "\xff\x1b\xcc\x59\xfd\x4f\x30\x27" + "\x11\x58\x9c\xe5\x8d\x4d\x5c\xc3" + "\x21\x99\x1f\x40\xb9\xff\x63\xd8" + "\x61\x69\x80\x2e\x2e\x48\x14\x5b" +
- "\xf1\xaf\xd7\x8b\xf3\x6b\x15\xb3" + "\x46\xb1\x81\x1d\xcb\xe4\x5e\x1b" + "\x15\xa9\x28\xd6\x41\xac\xa1\x7b" + "\x9e\x69\x89\xfd\x9c\x8f\x3a\x8f" + "\xe7\x8b\x74\xa0\xc9\xb9\x29\x73" + "\x1f\x62\x2e\xa9\x95\x1c\x39\x1d" + "\x37\xa8\x10\x4d\x21\x6b\x1e\xe5" + "\x35\xb4\x47\x49\x3a\xf5\x55\xd2" +
- "\x2b\x88\x20\x1f\x5a\x04\x37\xc1" + "\x0c\x05\x7a\x9b\xf4\x16\x4b\x92" + "\xaf\x94\x66\xea\xf5\x26\xba\x8a" + "\x3e\x6a\x82\x69\x54\x28\x06\x29" + "\x27\x16\x8c\xb0\xcb\xd1\xf6\x2e" + "\x34\x0c\x8c\xc5\x84\x38\x31\x61" + "\xb4\xf1\xf6\xd8\x99\xc2\xc7\xa5" + "\x87\x9f\x3e\xff\xc0\xae\x5a\xcd" +
- "\xe3\x8e\x78\xf1\x04\x9e\x66\x07" + "\xa2\x38\x69\xa8\xaf\x27\x4f\xc1" + "\xc0\x01\x3a\xe9\x34\xa3\x47\x8b" + "\x08\x68\x36\xd9\x38\x74\x62\xff" + "\x65\x59\x2a\xca\xd8\x85\x09\x7a" + "\xb3\xb9\xe9\xd6\x42\x55\x9a\x3d" + "\xe8\x72\xf9\x4c\x0b\xb8\x3e\xc2" + "\xfd\x72\xdf\x4f\xbb\x33\x1c\x5c" +
- "\x5a\xd4\xb3\x4c\xdd\xbd\xca\x3b" + "\xa1\x67\x7d\x41\x6b\x4d\x38\xa9" + "\x54\xfa\xa8\x6a\xba\x5b\x9f\x65" + "\xcb\xf0\x0e\xcd\x21\x76\x93\x04" + "\x47\x23\x8b\x51\xf5\xb2\x80\xd4" + "\x80\x87\xe3\x1f\x1e\x97\x3c\x15" + "\x38\xb5\x07\xfe\xed\x08\x71\x15" + "\x29\x01\x11\xab\x03\x80\x0d\xca" +
- "\x08\x61\xa8\x74\xd4\x58\x4a\x0c" + "\x90\x5d\x4c\xee\x8f\x8a\x04\xf8" + "\x80\x4c\x6d\xe8\x24\xc9\xc7\xe3" + "\x60\x1e\x6a\x05\xde\x89\xc8\x28" + "\x40\xa0\x14\xb2\x2e\x66\xe2\x57" + "\x47\x03\xe1\x37\x98\x8e\xc4\xe8" + "\x8a\x74\xac\x80\x62\x28\x74\x87" + "\xf2\x06\x6b\x18\x22\x40\xc2\xf1" +
- "\xd7\x51\x4e\x09\x76\x33\xbb\xd0" + "\x7a\x87\xcd\x42\x22\xcc\x10\x51" + "\xc6\x97\xd1\xcf\x29\x57\xd6\x7b" + "\x71\x31\xca\x8a\x05\x94\x29\xf2" + "\xa5\xae\x55\x21\x15\x75\x84\x07" + "\x54\x1a\x82\x9a\x48\x2d\xf1\x84" + "\x5c\xaf\x37\x37\xf9\xc1\x8c\xb1" + "\x45\x58\x48\xba\xe2\x0c\xba\x4f" +
- "\x0a\x04\x74\x5f\xc3\xd4\x2d\xac" + "\x57\xc9\xea\xfc\x71\xeb\x9a\x40" + "\x23\xec\xc4\x55\x82\xd7\xba\x4f" + "\xec\x76\x7b\x8a\x61\xed\x59\xb3" + "\x60\x4a\x6f\xed\x26\x49\x74\x12" + "\xe3\x2d\x91\x4b\x7f\x8d\x1e\xe2" + "\x59\x5a\x70\xfc\x59\x5a\x57\xe2" + "\x0e\xbc\x2d\xed\xde\xd4\xf1\x72" +
- "\xd2\x72\x97\xb9\x5a\xd8\x79\x96" + "\x25\x1c\xcd\xdd\x7c\x71\x69\x82" + "\x77\xc3\xdc\xeb\x45\x20\x97\x50" + "\xdf\xc9\xe2\x6e\x83\xde\x13\xed" + "\x7a\x21\xa7\x50\x04\xf5\x39\x9f" + "\xb6\x07\xe0\xae\x41\xa9\x3b\xd3" + "\x9a\xec\x2b\xfc\x90\x71\x4f\x91" + "\x87\x24\xd9\xb0\x4e\x25\xd2\x70" +
- "\xb8\x26\x79\xeb\xb9\x24\x2b\x3d" + "\x09\x55\xbe\xcd\xb3\x8c\xf8\xbf" + "\x0b\x64\xdd\xe4\xaf\x99\xf3\xd0" + "\x45\xed\x76\x2f\x30\xe1\x5f\x3c" + "\x3d\xfb\x64\x37\xf4\x62\x35\x6f" + "\x2d\xb6\x51\x31\x18\xf3\x5a\x7b" + "\xf3\xe5\x9c\xd7\xc7\x0b\xbd\xd5" + "\x0f\x89\x66\xec\x20\x6b\xaf\xfd" +
-
- "\xa2\x35\x4b\xab\xe5\xb0\x72\x67" + "\xcf\xaa\xee\xf5\x01\x60\x8b\x1d" + "\x80\x95\x5b\x79\xe4\x7c\x8f\x72" + "\xda\x81\xfb\x41\x2a\xed\x20\x4a" + "\xe6\x01\xec\x4f\xd4\x5c\x68\x9f" + "\xad\x50\xff\xa7\xcc\xdd\xd7\x3e" + "\xfd\x97\x2d\x0c\x64\xd2\x0f\x46" + "\xf9\xf4\x82\xeb\x26\x14\x24\x3a" +
- "\xd5\x21\xd7\xd5\x62\x98\x00\x80" + "\x82\xa1\xd3\x5b\xa3\x57\x33\x0c" + "\xa4\xcd\xa2\x7a\x3b\xa8\xf3\x27" + "\x85\x30\xf8\xf6\x4e\xe7\x8a\xb5" + "\x6b\xad\x6d\x2e\x81\x1a\x91\x2a" + "\x5b\x6c\x3d\xf4\x51\x60\x28\xde" + "\xd8\xc4\x96\xf9\x41\xcc\xdc\x4b" + "\x4e\xe2\xe1\x0a\xc0\x2e\x31\xe7" +
- "\x70\xee\xe6\xaa\xfe\x68\xaf\x6f" + "\xc9\xb0\x02\x56\x15\xcc\xf4\x78" + "\x2a\x05\x94\x6e\xa8\x21\x33\x7e" + "\x80\x5d\x4d\x73\xd6\xa0\xb3\x2f" + "\xba\x43\x5a\xb2\x3b\x8f\xb9\xf3" + "\x51\x29\xee\x19\x31\x80\xbf\x30" + "\x2a\x61\xb0\x21\x33\xe4\xfe\x7f" + "\xd0\x21\xb8\x2e\xe4\x75\xf7\x12" +
- "\xb3\x85\x64\x6e\xe7\x12\xd1\xf8" + "\xf8\x52\x1c\x77\xdb\x24\x3e\x4d" + "\x6d\x2f\x4a\x68\x41\xee\xe3\x48" + "\x51\x55\xd9\x21\x7d\x95\x61\x71" + "\x6c\x2a\xb1\xcd\x83\x12\x63\x19" + "\x64\xe1\x50\x2e\x82\xa8\x3f\xbf" + "\x73\xcc\x66\x31\x63\x4b\x25\xf6" + "\x38\xcc\xe8\xae\xae\xa7\xef\x3a" +
- "\xa9\x29\xa9\x37\x80\x00\xf7\x46" + "\xbd\xc6\xfe\x19\x8e\x1a\x60\x65" + "\x62\x8b\xab\x12\xdc\x5e\x7f\x53" + "\xcf\x90\x59\x5e\x95\xcd\x97\xe4" + "\xf9\xb2\xa5\x9a\x7f\x38\xcd\x2f" + "\xe8\x8f\xb7\x67\xff\xa3\xfa\xe5" + "\x30\x5e\x5d\x29\x8d\x53\xcf\x1b" + "\xec\xa7\x13\xa8\x39\x32\x57\x3a" +
- "\x09\x24\x7c\xd1\x6b\x28\xf5\xe9" + "\x9b\x4d\x26\x63\x93\x47\x4e\x2c" + "\x0f\x88\xf6\x17\xb1\x42\x70\x17" + "\x43\xee\xe1\x4c\xc8\xe2\xb7\x39" + "\xa9\xf4\x96\xd0\x22\xe7\xc8\xce" + "\x97\xe6\xd5\xbe\xcb\xae\x61\x68" + "\x11\x19\x23\x6c\xf0\x53\xd1\xc2" + "\x7a\x53\x90\x28\xb8\x42\x2f\xcc" +
- "\xb4\x17\xa9\xd0\x51\xcb\xe2\x33" + "\x31\xf9\x99\x48\xf3\xa3\xcf\xc2" + "\xb6\xf6\xa2\xe9\x4b\x4f\xc9\xb2" + "\xb7\x62\xa1\x7c\x81\xb1\x07\x97" + "\x0d\xb1\xf8\xd5\x72\xa1\x02\xb6" + "\x2a\x54\xd4\x4f\x35\x78\x30\xfd" + "\x92\x69\x99\xdd\xdd\x26\xf2\xee" + "\xe1\x15\x0a\xeb\x89\xa9\x1f\x22" +
- "\xfd\xf9\x36\x3b\x62\xfe\xb0\x79" + "\xc0\x9f\xe1\xfd\x23\x3b\x54\x26" + "\xef\x82\x84\x95\xa0\x64\x6e\x13" + "\x25\x58\x09\x9b\x71\x37\xf6\x23" + "\x2e\x14\xa1\xb6\x96\xd5\xcf\x14" + "\x0b\xac\x5a\x33\xc6\xaa\xa6\x5e" + "\xd5\x1d\x08\xf3\xbd\xe8\xa0\x86" + "\x2a\xc1\x3d\x00\x79\x9d\xb8\x5f" +
- "\xa3\x32\x11\xde\x77\x86\x62\x73" + "\x47\x88\xa8\x2f\x64\x7e\x12\x75" + "\x60\xe6\x49\x5b\x30\x7a\x2f\x19" + "\xa9\x6a\x43\x11\xfe\x3c\x06\x1a" + "\x89\x01\x71\x4b\x57\x14\x00\x72" + "\x8d\x37\x57\x2a\xde\x46\xa9\xfa" + "\x66\x30\x1c\x19\x63\x5c\x49\x5c" + "\xdb\xb4\x7d\x6b\x65\x7e\x4b\x2b" +
- "\x13\x04\x63\xd0\x7a\xd2\xe3\xa4" + "\xeb\x56\xfa\x19\x82\xe3\x70\x57" + "\x66\x06\x4c\x75\x7a\xcf\x65\x44" + "\xf3\xc5\x69\x61\xd2\x61\x91\xfe" + "\x48\xe3\x0e\xdc\x22\x27\xf6\x5d" + "\x54\x04\x89\x29\x6a\x59\xc6\x9c" + "\x2a\x32\x5d\x9f\x18\xd6\x43\xf0" + "\xe9\xe3\x1e\x18\x7a\x95\xce\xb4" +
- "\xed\x62\x5c\xfe\x49\x0a\x19\x08" + "\x3d\x18\x91\x36\x3d\x54\x57\x2c" + "\x23\x48\x04\xa9\x8b\x31\xee\x75" + "\x58\x8f\xf2\xae\x9e\xe0\x0c\xd2" + "\x66\x4a\x8a\x84\x50\x3d\x61\x10" + "\xfb\x2e\xcf\x9f\xa8\xa1\x98\x4b" + "\x27\x64\xfc\x98\xd9\x1e\x5f\x41" + "\x50\x2b\x85\xe3\x56\xbb\x6a\x08" +
- "\xd4\x34\x2e\xf7\x3a\xc3\x15\xf6" + "\x35\xec\x0e\x11\x40\xea\xd9\x0b" + "\x4e\xa3\xde\xc1\x5b\xbc\x12\x1c" + "\x99\x46\xae\x49\xc9\x84\x65\x68" + "\x42\xb9\x97\x8c\xd3\x95\xad\x13" + "\x62\x75\x5c\x4e\x1a\x56\x09\x46" + "\x89\x7f\x73\xf2\xae\xa4\x94\x9e" + "\xb6\x78\x1c\x37\xc6\x94\x75\xf5" +
- "\xde\xa9\xed\x19\xd9\x8c\x76\x5a" + "\xd2\x51\x2a\x8e\xf4\x06\x32\x6e" + "\xef\xa3\x78\x86\xc0\xe8\x56\xd3" + "\xc9\x91\x3f\x54\x6d\xd3\xf8\x93" + "\x43\x67\x08\xa4\xf4\x31\xf2\xfe" + "\xc9\xc6\x48\x91\x11\x9a\x37\x4d" + "\xce\x32\x82\xdc\x1d\x58\xb5\x00" + "\x4b\x21\x02\xd7\xef\x72\x7a\xa6" +
- "\x92\xe8\xb4\x17\xf6\xa9\x45\x61" + "\xf1\x9f\x22\x5f\x27\x02\x64\xfe" + "\xa3\x6b\x04\xdc\xa8\x3e\xb0\x6d" + "\xcc\xda\x51\x03\xd6\x73\xc8\x71" + "\x5b\x7b\x94\xc2\x37\xe3\xae\x4b" + "\x80\x43\x8b\xb0\xc7\x85\x08\x90" + "\xb9\x79\x45\xc8\x61\xa6\x1e\x1f" + "\x18\x78\x01\xa5\x93\xbb\xdd\xcc" +
- "\x80\xb4\x9f\xcf\x3d\x88\x4d\x55" + "\x4d\x9a\xfb\x0d\xc5\x71\xca\x76" + "\xea\x40\x42\xe0\x2b\x14\x51\xc2" + "\x99\xfc\x7a\xfa\x3d\xa6\x9b\x89" + "\xa3\xcd\xbb\x9f\x12\x5b\x94\xed" + "\xcc\xa4\x99\xa2\x28\xd5\x4d\x3c" + "\x92\xc0\x63\x8a\x09\xb6\xe8\x68" + "\x1b\x62\x40\x3f\x6c\x0a\xf5\xec" +
- "\xe3\x9e\x77\xe3\xfc\x65\x01\x0f" + "\x9e\x5d\x49\xbd\x9d\x7f\x0e\xe0" + "\x7a\x4e\x28\x20\xa2\xef\xa4\x1f" + "\x19\x62\xac\x47\xde\xba\x64\x45" + "\x8e\x8e\x70\xc4\x2a\x31\xe6\x90" + "\xdf\x9a\x1e\xa7\xfb\x25\x57\x4f" + "\x9f\x4b\x68\x3d\xae\x55\x5f\xe9" + "\x15\xb4\x94\x1e\xb1\xcc\xf7\x47" +
- "\x01\xc2\xad\xa8\xbe\x48\xfd\x50" + "\xa8\x06\xdf\x40\x00\x18\x18\xce" + "\x22\xce\x82\xde\x42\xca\x07\x6c" + "\x1a\x76\x24\x5a\x51\x6c\x64\x23" + "\x2f\x39\x68\xb2\xf8\x91\xcf\x46" + "\x86\x14\x81\x81\xff\x57\xb7\xe4" + "\xa0\x02\x61\xd2\x0b\x57\xdd\x94" + "\x80\xdf\x65\x3e\x2d\x4d\xc3\x2d" +
- "\xd3\x56\xde\x56\x44\xaf\xfe\x18" + "\x22\x79\x02\x61\xe8\x68\x95\xb3" + "\xdc\x58\xa4\x28\x5c\x68\xb8\xa2" + "\x17\xa8\x95\x62\x6c\xbf\xa8\x41" + "\xdc\xd1\x98\xca\x74\x40\x29\x7b" + "\xbe\x13\xe0\xb3\x59\x82\xc4\x94" + "\x56\x52\x4f\x2c\x24\xd5\x2e\xb4" + "\xec\x9f\x7c\xda\x50\x89\x8e\x30" +
- "\x1d\x54\x6c\x31\x83\x70\x02\x46" + "\xcc\xab\x9e\xd3\x6b\xbc\x05\x7f" + "\xdc\x0c\xc2\x60\xa1\xfa\x37\xb8" + "\x06\x9d\xd3\xac\x1a\xf3\x8b\x4f" + "\x51\x20\x51\x00\x95\xdc\x31\x83" + "\xac\xa2\x2a\xaf\x62\xf4\x74\x53" + "\xa3\xb1\x2a\xf3\xb4\xd9\x73\x76" + "\xfc\x49\x4f\xd6\xac\x51\xe1\xa6" +
- "\x81\x65\x94\x8d\x1b\x85\x22\x73" + "\x12\xa0\xf4\xbd\x33\x31\xd1\xf0" + "\xe0\xda\x84\x65\x69\x0f\x51\xa3" + "\x6d\x6c\x9f\x3c\x71\xc1\xa7\x03" + "\x1a\x38\x75\xe4\x38\x7f\xe9\x5b" + "\x34\x33\x82\x85\x22\xa4\x1b\xca" + "\xda\x7d\xe1\x0b\xc7\xc5\x3c\xf8" + "\x0f\x8c\x91\x0b\x94\x14\x8b\x15" +
- "\x05\xf7\xa5\xdb\x88\x8a\x18\xb7" + "\x8b\xd8\xfa\xa1\xa6\xfc\xfe\x5c" + "\x95\x85\x8e\x33\x04\x88\x2d\xed" + "\x81\x09\xb4\x7e\xf8\x0b\x23\xc0" + "\xc7\xf7\x87\x4b\x78\xf1\xd1\x3e" + "\x2a\xd0\x9e\x7f\x76\x60\x1d\x9d" + "\x5b\x8d\x3f\xf2\x8b\x26\x90\x22" + "\xb9\x68\xd3\x86\x35\x4c\x90\xad" +
- "\x82\xd6\xfb\x2a\x05\x96\x64\xdc" + "\xb1\xb0\x37\x16\x13\xfb\x08\xac" + "\x9d\xf3\x84\xa1\x88\xd4\x9f\xdf" + "\xb2\x25\xe3\xac\x23\xbc\xc2\x1f" + "\x84\x9a\x6c\xbd\x36\x3b\x87\x29" + "\x9d\x52\xf8\x3c\x15\x11\x2c\x46" + "\x2d\x21\x55\xc5\x0d\x37\xe0\xb3" + "\xc6\xec\xaa\x89\x75\x3f\xf8\x31" +
- "\x99\x5a\xde\xb7\x31\x74\xdf\xb1" + "\x3c\x87\x95\xf2\xe6\x8e\x52\xfb" + "\x95\x3c\x30\xcc\x0f\x50\xa1\xec" + "\x60\xb7\x33\xce\x97\x05\x39\xdb" + "\x36\x97\x76\xe4\x86\x14\x96\xd6" + "\xa2\x9d\x33\xc3\x28\xe4\x45\xd2" + "\xce\x6c\x10\xfa\x41\x7f\xca\xf5" + "\xdd\xac\x80\x70\x32\xb1\xed\x37" +
- "\x69\x6b\x2e\x52\xe5\x77\x3a\xda" + "\x18\x6c\xcd\xbb\xc3\x08\xc9\x69" + "\x56\xfd\x24\xd9\x48\x9e\x1b\x1f" + "\xf7\xb3\x4b\xaa\x36\x4e\xc6\x37" + "\x7d\x8d\x47\xee\xdf\xdb\x4f\x5a" + "\xa0\xf7\x93\x01\xbc\xc8\x75\xba" + "\xdf\x16\xcd\x56\x84\x1e\xbc\x84" + "\x51\xd1\xfa\x46\x08\x8f\xb0\x1f" +
- "\x36\xbb\x6b\xb2\xef\x01\x33\x29" + "\xfa\x4d\x64\xa9\xf8\xca\x68\x45" + "\x0c\x3c\x0c\x3e\x05\xae\xac\x0d" + "\xa8\x51\xa6\xec\x02\xd5\xa6\x2b" + "\x0b\x61\x04\x60\x68\x59\xbd\xe3" + "\x45\x72\x2b\x28\xf6\x6a\x07\xc2" + "\xa4\xe9\x94\x1e\x4a\xf2\x61\xae" + "\x63\xf1\x76\x15\x5c\x99\x15\x03" +
- "\x47\x15\x57\x74\x3d\xff\xf8\x2a" + "\x19\x9b\xe1\x2c\x07\xea\xb3\x7e" + "\x85\x99\x09\x9b\x88\x62\x1b\xb8" + "\xc5\x09\xa3\xea\xd6\x22\xec\xdf" + "\x19\x34\xc3\xcf\xe2\xa0\xb5\xf9" + "\xa0\xb3\x65\xdb\x9c\xb6\xbf\x70" + "\x95\x4d\x52\x3f\x56\x15\xec\x75" + "\x30\x2f\x80\xe0\x37\x97\xed\xe5" +
- "\xe0\x53\xc7\x04\x2b\xf4\xe7\x6a" + "\x6c\xd4\x06\xe6\x00\x42\x09\x26" + "\xa4\xdc\x80\xf6\x39\x2f\xb0\x3a" + "\xda\x37\x3b\x73\xa9\x53\x88\x9b" + "\x6a\x38\x5d\x85\xae\x34\x11\x2e" + "\x61\x9b\xed\x88\xe1\xbe\xa8\xd8" + "\x59\xd4\xed\x83\xc0\x8b\xa0\x2f" + "\x68\xe1\x0f\x2d\x51\x21\x4d\x94" +
- "\x30\x9f\x2e\x84\xf9\xab\x7c\x8a" + "\xaf\x83\xab\x5e\xbf\xd4\x31\xa3" + "\x6a\x2a\x7f\x01\xba\xcf\x72\xd2" + "\xe3\xa0\xab\x83\xbc\x0a\x56\x27" + "\x75\x6b\x3a\x0e\x87\x33\xb8\x94" + "\xf5\x50\x9f\x6b\xa2\xae\xc6\x25" + "\xd0\xf6\xfd\xb5\x1d\x69\x3d\x80" + "\x14\x35\x33\xe6\x09\x75\xb7\x03" +
- "\x6f\xcf\x14\xbd\x34\xe2\x5e\x74" + "\xbb\x24\xc0\x49\x84\x50\x8b\xde" + "\xb4\xd7\x35\xef\xdd\x4f\x33\x9c" + "\xb4\xb2\x64\xb7\x28\x77\x64\xff" + "\x31\xe0\x21\xcc\xd7\xee\x4d\xf9" + "\x85\x28\xd8\xa0\xb8\x40\x47\xe3" + "\xfb\xd2\x85\xc7\xc4\x17\x03\xa7" + "\xae\x8c\xa5\xf8\xc5\x6a\x05\xdc" +
- "\x5f\x04\x78\x88\x8e\x4e\x27\xc4" + "\xe0\x25\xc3\xeb\xeb\x98\x66\x21" + "\x56\x6c\x39\x09\xcf\xbb\xef\x0f" + "\x5e\x80\x91\x04\x15\x19\x19\xdc" + "\xa2\x80\x54\x5c\x87\x4e\x4c\xa7" + "\x0a\xce\xc8\x72\xb3\xd1\xa8\xde" + "\xc1\xfa\x77\x7f\x1d\x70\x9f\x67" + "\x70\xb5\x6a\x6d\xb5\x00\xba\x3e" +
- "\xce\x50\x23\xf2\x20\x4e\x00\x08" + "\x4e\x1c\x60\x8d\x19\x45\x45\x6b" + "\xd5\x77\xe1\xd5\x5a\xdc\x09\xea" + "\xd9\xba\x34\x75\xaa\x19\x3e\x92" + "\x46\xc0\x80\x31\xa6\x05\x29\xa4" + "\xaa\x64\xc8\xd3\xd0\x9e\x27\x0c" + "\x51\x5a\x90\xff\xb6\x41\xf3\x49" + "\x32\x6b\x96\xa7\x88\x09\xe2\x2b" +
- "\xc1\x41\xa3\x61\x03\x89\x17\x36" + "\x42\x61\xfd\x0c\x60\xdc\x04\x36" + "\x6c\x31\x33\x85\xeb\x95\x22\x02" + "\x22\x29\xaf\x44\xac\xe4\xbd\x3d" + "\x69\xef\x7e\x1c\x5d\xfc\x8a\x89" + "\xa1\x4f\x4f\xd1\x05\x68\x89\x58" + "\xca\x21\x3c\x20\x60\x21\x00\x05" + "\x0b\x73\xef\x40\x30\x1f\x0d\x6f" +
-
- "\x5a\x19\xf7\x77\x09\x77\xbf\xfa" + "\x8f\x83\xeb\xad\x67\x61\xc8\x8e" + "\x2d\x01\x4f\xbb\xa8\x85\x12\xea" + "\x3f\xab\x3e\x9a\x03\x35\x88\xd6" + "\xc2\x04\x90\x30\xf8\x24\x5d\xee" + "\x5e\xe9\xff\x13\x76\x4b\x6e\xa9" + "\xa4\x3e\x22\xbd\x12\xfe\xdf\x0c" + "\x53\x9a\x73\xb6\xe5\x2e\x5c\x8f" +
- "\x02\x38\x76\xbd\xa9\x6a\x40\xed" + "\xa1\x3d\x30\x65\xa0\x86\x14\xc2" + "\xc4\x2e\xe6\xc7\x1e\x29\xae\x61" + "\x3e\x33\x99\xdf\x92\x04\x2a\x62" + "\xe0\x8e\x7a\xbb\x9d\x0c\xd8\x7f" + "\xdb\xae\x01\x6c\xbc\xd3\x2e\xdc" + "\xec\x74\xbe\x08\x12\x5a\xc3\x35" + "\x1f\x67\x9f\x46\x1a\xcb\x40\xd5" +
- "\x5b\x6f\x77\xbf\x5a\x3c\xe5\x2c" + "\x05\x7b\x35\x60\x71\x40\x72\x6f" + "\x7a\x3f\xbf\x71\x17\x37\x59\xb2" + "\x9f\x4a\x0c\x44\x1c\x50\xd2\x87" + "\x40\x53\xb0\x87\xe1\x52\x05\x44" + "\x32\x4c\x62\x21\xc8\x7c\xbf\xb7" + "\xdb\xcd\xfa\x22\xce\xa6\x55\x41" + "\xef\x37\x98\x88\xcb\x28\x42\x5a" +
- "\x20\x5e\x4c\x58\x6a\x74\xa8\xa7" + "\x35\x70\xdc\xb9\xa1\x4e\x7e\x26" + "\x9b\x8c\x54\xb9\xcf\x15\x3a\x59" + "\xf3\x12\xd0\x4b\x35\x21\x6e\x5e" + "\x6e\x93\x8f\x8c\x6a\xcc\x31\xdf" + "\xdc\x41\xc2\xb5\x04\x4d\xf8\x8a" + "\x86\xfb\x5e\x34\x6f\x0a\x99\x63" + "\xcb\x62\xb9\xb9\x61\x4e\xef\x6f" +
- "\x8d\xe4\xa2\xe1\x46\x82\xc4\x23" + "\x5c\xce\x3d\x54\xd1\xe6\x15\xf0" + "\xe9\x1d\x6d\x28\x52\xdb\x9e\xd1" + "\x56\x6f\x82\xdf\xf6\x87\x07\xd6" + "\xe3\x59\x14\x1c\xfe\x5d\x1d\x6e" + "\xdc\x6c\xb0\x9e\xa4\x99\xe8\x26" + "\xdb\xfb\xa1\x14\xc9\x60\x95\x02" + "\xf5\xb4\xd3\xb3\x2f\x84\x78\x8b" +
- "\xcb\xec\xbe\x22\x9c\xfa\x6d\xc5" + "\xc0\xd7\x88\xa1\x4a\xa9\x41\x9c" + "\x29\x47\x32\x70\xa1\x83\xc2\x36" + "\x11\x65\x3f\xb6\x50\xe2\xa0\x2d" + "\xa0\x24\x5e\x7b\xd2\x9f\x4d\x83" + "\x42\xdd\x34\x6c\x1b\xb7\x26\xac" + "\xd9\x36\x93\x32\x97\xb4\xf1\xe5" + "\x9d\x4a\xe9\x39\xcf\x1a\x68\xdc" +
- "\x30\x7b\xd7\x6c\xef\xcc\x80\x5c" + "\xd0\xb6\x99\xec\x99\x82\x97\x49" + "\x35\xd3\x39\xb9\x5e\x48\xf4\x6b" + "\x47\xc1\xd7\x86\xab\x61\x3e\xc5" + "\xdd\x1d\x60\xfb\x52\x80\x94\xdd" + "\x48\xdd\x11\x35\x39\xeb\xc5\x34" + "\x1c\xf6\xe6\x00\x76\xc6\xf5\x91" + "\x34\x1f\xe7\xb1\x25\xb5\xf1\x33" +
- "\x08\x26\x72\x25\x09\x8f\x36\xf6" + "\xc6\xf5\x1c\x13\xdb\x60\x12\x13" + "\xac\xf7\xb4\xfa\x3b\x35\xeb\x40" + "\x29\xe8\xee\x37\x80\x88\xc7\x85" + "\x4e\xf2\xbd\xc3\xff\x81\x15\x4c" + "\xa8\xc5\xc3\xf5\xcb\x75\xff\x5b" + "\x40\x6f\x4e\xa1\x3f\xc8\xe8\x35" + "\xca\xe0\x95\x02\x0f\x1c\x1d\xb8" +
- "\x1d\xdd\xd9\xee\xf8\x53\x71\xde" + "\x2e\xcb\xeb\x52\x11\xad\x09\xba" + "\xb6\x3f\x84\xe1\x15\xb0\x41\xaa" + "\xf0\xe6\x4c\xdd\xab\xa2\x33\xf9" + "\x3f\xb8\xf6\x13\x43\x83\x7f\x77" + "\x75\x3a\x11\xdb\xa4\x7d\xdf\x28" + "\x43\xd1\xa5\x72\x3c\x1b\x7d\x6d" + "\xdf\x6d\x6c\x96\x98\x96\x78\x6f" +
- "\x54\xa0\x2b\xa7\x33\x9a\x43\xed" + "\xba\x65\xd2\xea\x15\x0a\x17\xa3" + "\x8e\xa5\x99\xfe\x03\xb9\x7e\xcf" + "\x26\x0c\xd8\x33\xc6\xb0\x6d\xcf" + "\x1a\xe7\x13\xf6\x5e\x25\x31\xd0" + "\x5c\x25\xca\x18\x57\xbe\xcc\x12" + "\x0d\xc4\x08\x78\x53\xd0\x21\xdd" + "\x6b\xbe\xf2\x3a\xbc\x8e\x48\xf5" +
- "\xc5\xf9\xe3\x1b\x7c\x0d\x11\x47" + "\xdd\xb4\xad\x5e\x48\xe4\xb9\x12" + "\x41\x3d\x71\x0b\x87\x09\x8c\x6e" + "\xae\x56\x3d\x73\x56\x03\xe2\xe1" + "\x27\xa7\x5e\x44\xab\x6b\x8d\xe6" + "\xa4\xa1\x34\xc9\xea\xf6\xf4\x9e" + "\xc3\xf1\xce\xf8\x47\x55\x15\xe0" + "\xbf\xdc\x9b\x15\x09\x39\x5c\xdb" +
- "\xd1\x8a\x2a\x44\x3d\xe2\xef\xf2" + "\x64\xc1\xb9\x06\x7d\x6a\x81\xc3" + "\xe5\xa5\x0a\xdc\x8b\x2d\xdf\xa9" + "\x65\x8e\x0a\x12\x6f\xe4\x1a\x19" + "\x5b\x1c\x61\x00\x87\x7f\x66\x83" + "\x48\x99\x10\xff\xd7\x1e\x17\x83" + "\x52\x59\x69\xca\xf8\xec\xa2\x33" + "\x13\x1a\x8d\xf4\xee\x73\x4a\xfa" +
- "\x7d\x00\x04\x66\x84\xcf\xca\x97" + "\xf1\xa9\x47\x2d\xb2\xb4\x92\x1e" + "\x65\xd1\x4e\x37\xd6\xe0\x8a\x85" + "\xb8\xef\x7a\x30\x6f\x3e\x97\x4c" + "\x72\xeb\x10\x8a\x23\x4a\x52\x6f" + "\xd6\x49\x28\xeb\xa9\x92\x4a\x7b" + "\xdd\x1e\xe9\x2f\xa4\xbd\x78\x36" + "\x5c\xc3\x0f\x7c\xcd\x2a\x09\x56" +
- "\x17\xe5\x10\x0b\xf1\xe9\x13\x35" + "\xd4\xc1\x81\x69\x44\x25\x7d\x40" + "\xc1\xab\xd9\x60\x48\xa8\x53\x49" + "\xd0\xd5\x4f\x8c\xe4\xbd\x8d\xe3" + "\xb1\x5a\xbb\x81\xc5\x16\x52\x7e" + "\xa1\xe0\xc5\x06\x6b\x04\x8a\x32" + "\xa6\x5e\x16\x91\x44\xf6\x34\x52" + "\x36\x0d\xac\xcf\x0f\x8b\xe6\xb6" +
- "\x40\x3b\x09\x1a\x63\x5b\x1d\x09" + "\x4a\xf2\x62\x58\x07\x1c\x5c\xb8" + "\xbf\x85\x8f\x3e\xb5\x4e\xd7\xc5" + "\x56\x24\xb2\xca\x46\x77\x1c\xf5" + "\x89\xda\x61\xe7\xd9\xb8\x5c\xc2" + "\xb5\x28\xf0\xc0\x2f\xec\x70\x26" + "\x5c\xaf\xb9\x2d\x0d\xd3\x3f\x87" + "\x5e\x56\x62\x82\xa1\x1e\x0f\x3d" +
- "\x0f\x73\x3a\xf4\xc8\x7c\xde\xfc" + "\x0e\x59\xab\x33\x3c\x6f\x9b\xe8" + "\x0b\x24\x03\xad\x29\xf5\x23\xc8" + "\xdb\xa5\xbe\x98\xfe\x9a\xb7\x82" + "\xde\xe5\x2f\x96\x56\x28\x8f\x56" + "\xf3\x91\xc5\x60\xdb\x0a\x59\x0c" + "\x58\xa8\x28\x4a\x14\x4a\xc7\x1f" + "\x4c\x3f\x20\xb3\x98\x24\x66\x3b" +
- "\x4f\x8c\xce\x88\xe2\x30\x5c\x75" + "\x3d\x3c\x63\x21\xc8\x8f\x63\x56" + "\x2d\x7c\x5a\xa0\xff\x00\x60\x88" + "\xc6\x18\x02\x01\x31\xe5\x92\x8f" + "\xa3\x64\x17\xb8\x03\x79\xee\x09" + "\x91\x47\x63\x3c\x97\x36\xc2\x95" + "\x13\x2f\x8e\x4e\x22\xf5\xec\x3c" + "\xf8\x4f\xc3\x23\x6c\xd6\x1e\x5d" +
- "\xbf\xb3\x30\x19\x22\xfb\xae\x9e" + "\x73\x9c\xa1\x22\x08\x6b\xc0\x25" + "\x98\xa4\xd3\x4b\x2a\x57\xa8\xd0" + "\x51\x63\xd7\x0c\x2f\x85\xbc\x20" + "\xda\x25\x89\xb3\x6d\x38\x01\x83" + "\x85\xf2\xec\x64\x6a\xe6\xfb\x85" + "\x7f\x61\xc9\xc0\x84\x7e\x74\x53" + "\x72\x17\xbe\x1d\x26\x1d\xd6\xb0" +
- "\x8a\xff\x0d\x8d\x95\xc2\x84\xe5" + "\x05\x63\x24\xef\x8b\xf4\x2b\x55" + "\x3e\xdb\x45\x4f\xa5\x21\x9c\xc0" + "\x8f\xbb\xee\x3c\xec\x83\x30\xca" + "\xe2\xc6\x6d\x40\x7c\xd0\x4d\xbf" + "\x01\x30\xf6\xa7\x6d\x62\x96\x0e" + "\xd3\xcb\x16\xaa\xfe\xfb\xa9\x81" + "\x00\x13\x3a\x67\x5c\xca\x7e\xfe" +
- "\x6a\x1b\xdd\x82\xd0\x4e\xfc\x48" + "\xaf\x03\xb7\x67\x38\xa1\x83\x57" + "\xaa\x6a\x5d\x00\x9a\xcb\x63\x24" + "\x43\xcd\x6e\x70\x5c\xc5\x1e\xd3" + "\x41\x76\x9a\x8e\x3f\xd3\x8e\x9f" + "\x7a\x9e\x8d\x09\xed\x53\x54\x62" + "\x93\x74\x88\xec\xe4\xad\xbe\xa3" + "\x66\x55\x79\x5a\x50\x80\x2b\x44" +
- "\x17\x50\x96\x0c\x31\x62\x0c\x98" + "\x4f\x7a\x0d\x40\xb3\xc0\x8c\xaf" + "\x97\xcf\xf4\x48\xe2\x12\x58\xee" + "\x5e\xd9\x90\xbb\xb8\x7e\x58\xe4" + "\x5e\x04\x52\x81\x7f\xa5\x42\x1b" + "\x2e\x7c\x1c\x64\x06\xb9\x92\xd7" + "\xda\x87\x1c\xa7\x93\xf5\xfc\x9d" + "\xb9\x00\x04\x1b\x77\x7d\xab\xc7" +
- "\xe2\x70\x5a\xd8\x34\x2d\x95\x16" + "\x52\x1a\x2e\xc3\x97\xff\x09\x7d" + "\xbf\x8a\x2d\xa6\x3e\xe4\xd6\xca" + "\xbb\xfe\xaa\x25\xda\x46\x76\x74" + "\xbd\x24\x4e\xe5\x96\xc4\x65\x03" + "\xe3\x50\xe8\x24\x16\xa4\x99\x14" + "\x2b\xd2\x81\x67\xf7\xdd\xf6\x24" + "\x81\x59\xc3\xbf\xf1\x55\xe5\x42" +
- "\x38\x33\xcd\xfa\xc2\x19\x23\x5b" + "\xd1\x3e\x88\x6f\x47\x50\x96\xed" + "\x19\x16\x83\x16\xc3\x96\x07\x37" + "\xaa\x61\x6b\x20\x69\x34\xb7\x8d" + "\xe8\x08\xa9\x1f\x17\x5d\x0e\x0a" + "\xfa\x40\x54\xb4\xe3\x71\x72\xe8" + "\x98\xdb\x2b\x07\x3e\xe0\x6a\x7f" + "\x8a\xb9\xc3\x28\x55\xf7\x87\x06" +
- "\x5a\x76\x39\x6c\x0d\xcf\xe3\x91" + "\x0b\xca\x3c\xac\xcd\x3a\xdb\xa2" + "\x50\x3b\x95\xcb\x08\x2f\x8f\x28" + "\x1a\xcf\x43\xcf\x2c\x58\x14\x24" + "\xa8\xe9\xee\x60\xbc\x8b\xec\x8d" + "\x42\xa0\x9a\x72\x02\x9f\xc7\x54" + "\xd5\xf5\x32\x65\xec\xd5\x1c\xd8" + "\x5f\xe1\x82\xcf\x3a\x30\x72\xa6" +
- "\xff\xf5\x73\xc3\xe2\x03\xbd\xb3" + "\x41\x63\xfc\xe7\xb4\xa8\xa8\x80" + "\xdf\x7b\x08\xa0\xd6\x52\x29\xb7" + "\x8e\xa3\x48\xc0\x9d\xbb\x3c\x80" + "\x00\xb0\xf8\xcc\x7e\x65\x0a\xcf" + "\x09\xeb\xe1\x67\x18\xc0\x54\x8c" + "\xfc\x46\xb6\xf0\x26\x10\xf9\x88" + "\xd8\x4b\xff\x7d\x53\xf2\x0d\x9d" +
- "\x42\xd5\xc6\x48\x80\xc9\xfb\x4e" + "\x2e\xf4\x25\xc9\x00\xc2\x9c\x26" + "\x3e\xfe\xf6\xbc\x6a\x44\x5a\xb5" + "\xc5\xe5\x67\xac\xd5\xdb\x02\xb0" + "\xd8\x8e\xda\xee\x64\xee\xec\x91" + "\xd2\x71\xe0\xba\x2d\xf9\x89\x89" + "\x53\xbf\x7e\xaf\xe0\xdb\x45\x92" + "\x81\xa7\xef\x9e\xe7\xe6\x41\xd1" +
- "\x9f\x7e\xeb\x2d\x0b\x49\x28\x97" + "\x6b\x25\xc7\x02\xc6\xc3\x77\x88" + "\x73\xaf\x32\x22\x1d\xaa\x9d\xd2" + "\xe8\x49\xb0\x1a\x21\x90\x4b\xc9" + "\x94\xbf\xe4\xe6\x53\xdf\xe4\xdb" + "\x06\x10\x7b\x4d\xe7\x24\x73\x4a" + "\xdf\x8b\x6a\x0a\x56\xd4\x46\x04" + "\x89\x55\xa3\x5c\x8b\xf9\xf2\xab" +
- "\x39\xb8\xfa\x3b\x2d\x58\xdf\x46" + "\xde\xda\x8a\x2f\x04\x4e\x47\x92" + "\xc3\x1b\x7a\x14\x6a\x76\xa7\x36" + "\x79\xf9\xc0\x0d\x54\x0f\x94\xb6" + "\x25\x9f\x75\xf2\xf2\x8e\x73\x44" + "\xc6\xf4\x19\xa7\x89\x57\xd9\x9d" + "\x45\xc3\x50\x07\xf4\xb7\x59\x28" + "\xd5\x80\x21\xb2\xf2\x8b\x78\x5e" +
- "\x7e\xb4\x71\x66\x01\x5f\x21\x4b" + "\x2a\xae\x8d\x4a\xca\x33\x76\xb6" + "\xdb\x3c\xfd\x79\x0f\x12\x15\x29" + "\xde\xe6\x64\xb0\x6f\xa0\xf8\xc1" + "\x20\x74\xd5\xc1\x8c\x36\xd5\xf4" + "\x75\xe4\x8d\xe1\xa8\x51\xda\x6a" + "\xb0\xd4\x49\xc7\x7c\xd4\xf0\xa0" + "\xa5\x6a\x52\x74\x00\x2c\xfa\xab" +
- "\x3c\x17\x59\xfc\x73\xb7\xf2\x3f" + "\x9c\x91\xa0\xa2\xa5\x12\x86\xf6" + "\x15\x7b\x4c\x23\x28\xae\xa8\x9c" + "\xdc\xe7\xbe\xed\xaf\x58\xf6\xfd" + "\x5f\x96\x18\xab\xad\xd9\x55\x2c" + "\x44\xde\x00\x5c\x12\x1f\x90\xb9" + "\x51\x0b\x36\xee\xf1\xaa\x70\x8b" + "\xe0\x4f\x60\x05\xd5\xa9\x4b\x3e" +
- "\x2b\x77\xd2\xf0\x82\xe4\xb8\xbe" + "\x99\x06\xe6\x2d\x65\xab\x16\xc5" + "\xf9\xf7\xd4\xc6\x34\x1e\x4f\x1e" + "\xee\xe4\xec\x5c\xbf\x88\x98\x23" + "\x38\xd2\x03\xbc\xfe\x86\xc5\x7a" + "\x6f\x3a\x35\x7d\x15\xc7\xd3\x8c" + "\x65\xfd\xf1\xb3\xde\xaa\x96\x02" + "\x5f\x53\x1e\x3a\xd4\xed\xb8\xe3" +
- "\x63\x05\x9c\x71\xa8\xaf\x6a\x37" + "\x9f\xc7\x5f\xbc\xdc\xd2\x8a\xcd" + "\xd3\x0c\x75\xcb\x9f\xdb\x3f\x30" + "\x8e\xb0\x18\x44\x2f\x05\xff\x14" + "\x20\x65\x2d\x3e\xcf\x84\x50\xf7" + "\x09\xd5\x4e\x14\xf8\xf0\xbd\x7e" + "\x98\x5b\xf2\xd3\xf2\xf0\x3b\xf4" + "\x37\xd8\x54\xa3\xcf\x71\xad\x86" +
-
- "\x5d\xf7\x8a\x86\xc4\xc8\xd0\xd9" + "\xea\xc7\xc8\x45\xff\x5c\x32\xd7" + "\xb0\xec\x81\xcc\x96\x19\x47\xab" + "\xed\x24\x18\x61\xf3\x55\x5d\xff" + "\xee\xa0\x77\x19\x41\x45\x31\xbe" + "\xc6\x38\x20\x72\xc5\xc4\x85\x50" + "\x95\xb4\x4b\xf9\xbf\x35\x53\x2d" + "\x82\xa0\xe2\xc8\xa6\xd8\x4a\x89" +
- "\x37\xbb\x11\x2c\xb2\x34\x02\x54" + "\xa3\x74\x4c\xed\xdd\x66\x03\x2d" + "\x5d\xf2\xc5\xee\xda\x68\xa9\xf9" + "\x42\x31\xb6\x67\x68\x10\x60\x36" + "\xd4\xb6\xd7\x68\x2c\x6d\xcd\x07" + "\x42\x29\x84\x0c\x09\x4f\xf7\xa8" + "\xee\xb1\x68\x77\x04\x14\x75\xe2" + "\xe4\xae\x62\xfe\x89\x7e\x5f\x4b" +
- "\x20\xef\x94\x19\xb2\x59\xe0\xd1" + "\x18\xe3\x8a\x63\x69\x3b\x65\x2a" + "\x10\x90\x69\x2f\x58\xeb\xd5\x70" + "\x4a\xf8\xf5\x09\xf7\x39\x97\x27" + "\x36\x93\x79\x8b\x3c\x66\xa4\x5d" + "\xeb\x37\x3c\x20\x4d\xf1\xfd\xfd" + "\x2d\xfb\xdb\xa1\xdc\xa9\xd8\x32" + "\x9b\x8f\xd4\x77\xf0\xcf\x40\xab" +
- "\xed\xbb\x9f\x87\x0b\x9f\x36\xf2" + "\x69\x18\x9d\xda\x86\xae\xf0\x0f" + "\x45\x6f\x76\x56\x59\xd7\x51\x52" + "\xfc\xd0\xe8\x2b\xc0\xd8\x84\x49" + "\xf0\x08\x10\xd2\xa6\x95\xcc\x7e" + "\x49\x1c\x1a\x3a\xa0\x54\xbd\x29" + "\xf3\x50\x6c\xd2\xc5\x28\x98\xab" + "\x51\xd2\xd0\x51\x7c\x08\xc0\x32" +
- "\xa5\x50\xaf\xfb\xab\x90\x17\xf6" + "\x50\x07\x4e\x68\x6b\xe7\x55\xdf" + "\x05\xb0\x76\xf1\xa7\x6d\x51\xec" + "\xc7\xdd\x2d\x7a\xbb\x53\x55\x57" + "\x73\xfa\x3a\x55\xa3\x7c\xc8\x37" + "\x51\xc2\x55\x4d\xfc\x3f\x5f\x31" + "\x35\x5d\x3e\xaf\x2a\x44\x46\xe8" + "\x28\xff\x95\x64\x49\x11\xb9\x61" +
- "\xaf\xf3\xb5\x62\x66\xeb\xfe\x47" + "\x34\x37\xbb\x0a\x61\xb5\xfa\xce" + "\xb1\x5c\xf3\x19\x0e\xe6\x9d\x44" + "\xb9\x0e\x7f\x15\x14\xdb\xf8\x39" + "\xd6\xbf\x61\x3c\x5b\xcc\xae\xff" + "\x03\x67\x21\x41\x1d\xd4\xa4\xa5" + "\xc2\x1c\x4e\x22\xed\xab\x8f\x7f" + "\x53\xd9\x1a\x87\x86\x81\x5a\x0d" +
- "\x23\x08\xf9\x56\x49\x3a\xdf\x4b" + "\x7b\x77\x1d\x74\x80\x50\x0f\xba" + "\x60\xf7\x8b\xf3\xc3\x71\x1d\x09" + "\x02\x5b\x62\x9b\x0f\xd5\x33\x96" + "\x61\xde\xc9\xb8\x43\xb7\xec\x03" + "\x20\x47\xe7\x5d\x54\x12\x75\xb4" + "\xb2\x1c\xce\x74\xc9\xef\x9d\x9f" + "\xef\x32\xbd\x00\x6a\x4f\x4a\x77" +
- "\x52\x9a\x79\x01\xa6\x8e\x0d\x19" + "\x52\x29\x6d\xb8\x41\xec\x0c\xa2" + "\x7c\x2a\xff\x7f\xb2\xff\x62\x30" + "\x37\x9d\xf1\x79\xe5\x32\x1b\x74" + "\x47\x7d\xb5\x4e\x81\x81\x0d\xf8" + "\x6b\xf0\xae\x16\xd4\x0e\x2d\x7a" + "\x88\xb5\xec\x1c\xb0\x5f\x73\x09" + "\x5b\x1f\x06\xc6\xaa\xca\x41\x16" +
- "\x5b\x1e\x13\xb0\x02\xc0\x7b\x32" + "\xd9\x14\x25\xcb\xd5\xe6\x39\x17" + "\x43\x15\xa8\x55\xfe\xda\xcb\xc8" + "\x43\x72\x13\xe1\x6c\xa3\xb1\x5b" + "\x27\x53\x32\x17\xc5\xa3\x5d\x20" + "\x7e\x05\x5a\x51\x36\x1a\x5c\xc3" + "\x9b\x5f\x92\x42\xc9\x64\x0f\xf0" + "\x7a\x9f\xd5\xb7\x3c\x63\x14\xbd" +
- "\x3a\x8c\x6e\x65\x71\xd1\x2a\xae" + "\x05\x07\xcd\x1a\x63\xa4\xe2\xc0" + "\x5c\x05\xb6\xa0\x8a\x6a\x6f\x00" + "\x6e\xa2\x65\x2b\xd7\x13\x45\xaf" + "\xbc\xd5\x16\xd6\x14\x9e\x54\x3f" + "\x1f\x3b\x25\x71\x55\x39\xee\x64" + "\x3a\x24\xce\xb8\xc1\x0b\xb1\xe8" + "\x77\x4e\x3a\x91\xe5\xac\xbe\xbc" +
- "\xbd\x7d\xf3\x41\x43\x00\xc1\x47" + "\xf6\xec\x68\x61\xe3\xca\xec\x96" + "\xa3\x6a\xa4\x1c\x9d\xe5\xbd\x65" + "\xfa\x8f\x69\xb8\x7a\x02\xa7\x38" + "\x37\x44\xc3\x6d\xc8\x9d\xb8\xa2" + "\x3f\x15\xa4\x43\x8d\x11\x0a\x5a" + "\xd8\x2f\xe2\x1c\x86\x0a\x33\x9e" + "\xbc\xd3\xbb\xb3\xf6\x2a\x38\x28" +
- "\xa7\xd6\x79\xf7\x56\x22\xd3\x68" + "\x4e\x28\xe7\x19\x4d\x3b\x42\x20" + "\x53\xb1\xf3\x38\x1b\xaa\x19\xde" + "\x03\xf7\x44\x84\xc2\xb6\xd0\x73" + "\xa3\xe6\x64\x9c\x48\x61\x61\x66" + "\x24\x62\x25\x37\x37\x7c\x58\x99" + "\x63\x15\x33\x61\xfe\x77\x52\x6f" + "\x2e\x50\x56\xa6\x4a\xad\x74\x71" +
- "\x71\x02\x1e\xd8\xc0\x27\x2e\x0b" + "\x7c\x31\x7a\x11\x96\x75\x7a\xa6" + "\x99\x3d\x72\xa6\x28\x89\xf0\x17" + "\xa3\x10\x53\x48\x81\x56\xa7\x71" + "\xa9\x6c\xb6\xaf\x62\x54\x46\x90" + "\x9d\x22\xbe\xfb\xcc\x97\x5e\x18" + "\xc2\x8f\xad\xdd\x6a\x60\x1a\x6a" + "\xcf\x97\xc7\xb3\x16\xf3\x31\x24" +
- "\x8d\x91\x33\x01\x92\xfc\x1f\xec" + "\x97\xef\xc9\xb2\x5e\xbf\xd9\x15" + "\x9a\xbb\x6c\xfc\x42\xb5\x85\x78" + "\x5d\xcf\x20\x57\x53\x64\xbe\x8a" + "\xab\x68\xec\xd4\xce\x5d\x71\x4e" + "\xa3\x24\x9c\x27\x14\x76\xa6\x57" + "\xcf\x61\xbb\x31\x2a\xd5\x8e\x78" + "\x03\xa0\x37\xf4\x44\x24\xa8\xab" +
- "\x32\x94\x52\x93\x11\x40\x03\x47" + "\x62\x34\x74\x30\xdd\x6b\x10\x1f" + "\xca\xd8\x66\xcd\x64\x99\xfb\xab" + "\xd5\xad\xbd\xe9\x5a\x9d\x4d\x93" + "\x22\x3d\x8e\x90\x15\xd8\x76\x59" + "\xbd\x57\xe0\x28\x2f\x36\x4a\x34" + "\xb3\xdf\x43\x54\xdc\xda\x2c\xf9" + "\x3b\x60\x89\xf0\xad\x97\x12\x00" +
- "\x27\x14\x15\x20\x4f\x82\x99\x7f" + "\x06\x02\x43\x92\xb6\x28\x68\x20" + "\x57\x23\x11\xe1\xd7\x97\x90\xaa" + "\xec\x14\xe4\x09\xf2\xa2\xf9\xac" + "\x56\x53\x91\x27\xda\xc9\xda\xdb" + "\xe3\xfe\x1e\x00\xb7\x34\x07\x7e" + "\xe2\x88\xb2\xd2\xbb\xb5\xfa\x54" + "\x9c\xd0\x2d\xf6\xc4\x0f\x63\x4c" +
- "\x6b\x06\x44\x50\x60\xce\x2f\x4a" + "\xf4\x47\x3a\xfa\x9c\x01\x4a\x90" + "\x60\x0a\x5c\x0c\x9c\xea\x81\xba" + "\xbd\x98\xc0\x96\x0d\xea\xe4\xd7" + "\x02\x0a\xd5\x9c\x41\x00\xe7\xef" + "\x8c\x04\x7f\x2d\xd4\x39\xc8\xc0" + "\x1f\x56\x9b\xe0\x64\xf2\xda\xe2" + "\x8b\xb1\x34\x50\x18\x13\xbc\x0c" +
- "\xe1\xa5\x70\xbd\x66\x3e\x88\x6d" + "\x13\xe7\x5d\xd0\xc1\x84\xd8\x9b" + "\x7d\x48\xd8\xd4\x45\xd4\xd9\x48" + "\x05\xe4\xea\x0e\x8b\xcd\x40\x84" + "\x3e\xf8\x26\x3d\x29\x0f\xcd\xa3" + "\xe4\xc5\xa3\x22\x30\x45\xd9\x3f" + "\xa7\x2c\xfa\x3f\x66\x78\xa0\x63" + "\x97\xa0\xd4\x00\x29\xdd\xea\xbf" +
- "\x7a\x3f\x32\x88\xe3\xf2\xe5\x11" + "\xcd\x84\x75\x92\xc2\x74\x7a\xe0" + "\x2d\x3d\x61\x95\x34\x4b\x77\x1e" + "\x88\x74\x78\x2c\xc5\x52\x9b\x9c" + "\x08\x1f\x42\xbe\x3e\x3c\xdd\x3c" + "\x5f\x3d\x3e\x22\x9e\x81\xf7\x5f" + "\xb9\x09\xda\xc1\xb2\x39\x87\xba" + "\x1b\x49\x8b\x4e\x16\x63\x72\x6b" +
- "\xba\x32\x84\xd6\x59\xa5\xae\x13" + "\xdb\x15\x39\xd3\xfb\x43\x00\x94" + "\x08\xda\xe8\xe2\x94\x7c\x6c\x47" + "\xbb\x65\x30\x44\xc4\x30\x16\x6b" + "\x75\x6c\xf0\x19\x6d\x54\xd8\xd6" + "\xbd\x5a\xb3\x2e\xc2\x98\x1e\x7e" + "\x8e\x7d\x15\xf0\x10\x93\x1c\x75" + "\x75\x60\xfa\xf6\x27\x43\xf8\xde" +
- "\xef\x3b\x94\xa0\x3c\xd1\xaf\xb5" + "\xcc\xb1\xab\x57\x29\x77\x51\xd6" + "\xbc\xb5\x61\x9b\xdc\x52\x5a\x9d" + "\xcd\x31\x6e\x80\xa6\xfa\xce\x85" + "\xea\x1d\x0a\x72\x7a\x25\x84\xab" + "\x35\x0d\xd7\xce\x1b\x26\x60\x6a" + "\x61\xda\xd6\xb9\x4d\xf9\x23\xc0" + "\x0e\xae\xa0\x54\xec\x7e\x7f\x94" +
- "\x0e\x4e\x7a\x3a\x3c\x99\x5b\x76" + "\x14\xd3\x79\x9d\xef\x4a\x8f\xfb" + "\x24\xeb\x19\x2a\x0e\xc5\xa2\x5e" + "\x8c\xbc\x91\xb8\xe5\x16\x50\x92" + "\xe7\xec\xd1\x3a\xdc\xaf\x70\x8f" + "\xe2\xab\x8f\xf0\x4c\xa8\xbb\x0a" + "\x2b\x13\xf6\x15\xc8\x22\x99\x0a" + "\x77\x6d\x07\x5d\x73\x13\x02\x6c" +
- "\x87\xb7\x83\x9f\x56\x87\xb7\xc3" + "\xd7\xdd\x94\x36\x26\x49\xd2\xd6" + "\x2e\xa0\x70\x5d\x94\x48\xd2\x58" + "\x6a\x8c\x27\x8c\x0e\x67\x16\xac" + "\xe6\xb6\x70\xe3\x58\x4d\xa9\x71" + "\x05\xdb\x53\x02\x84\x63\xd7\xe4" + "\xfe\x2c\xb3\x14\x88\xc9\xb1\x99" + "\x95\xcc\x78\xcc\x70\xd8\x6b\x4e" +
- "\x61\x39\x45\xa4\x15\x26\xaf\x00" + "\x2c\x11\x3d\x99\x4b\x49\x05\x17" + "\x52\xd6\xcd\xa1\x2a\xe1\x32\x00" + "\xb3\x9c\x6d\x04\x12\xa6\xbf\x0e" + "\x8c\x72\x63\x1b\xf3\xa9\x03\x9f" + "\x05\x2b\x02\xde\xa2\x18\x36\x8f" + "\xc9\xc5\x77\x3e\x90\x4d\xb2\xd5" + "\x7c\xb7\xac\x72\xa3\x38\x78\x83" +
- "\x14\x36\xb6\xc8\x79\xca\xf7\xf5" + "\x3c\x90\xf4\x8a\x15\xb2\xbf\xf3" + "\xd3\x7b\xd4\x96\x54\x9f\xdb\x2b" + "\xba\x63\x8a\x0e\x30\x15\xe7\xd6" + "\xc4\xbe\x93\x7a\x49\x0a\xe9\x67" + "\xee\x63\x1e\x8c\x8b\x47\x13\x86" + "\x61\xe5\xdd\xf2\xc8\xd9\x6b\xe3" + "\x89\x86\x76\x8a\x51\x86\x14\x68" +
- "\x47\xb0\xce\x8f\xd9\xcb\x65\xfe" + "\xa1\x11\x8b\x3f\xf5\x2e\x87\xde" + "\x2f\x80\xec\x8f\x3d\x0d\xba\x9a" + "\x1d\x38\x9f\x9a\x32\x1d\x9f\x13" + "\x8d\x95\x87\xc5\xd9\xae\x21\x07" + "\xda\xa7\xf6\xb9\x5c\x01\x6a\x06" + "\x06\x9d\x5d\xed\xe3\xc4\x9e\x05" + "\x1f\xca\xba\x6c\x71\x85\x42\x14" +
- "\x1c\x53\xaa\x94\x94\x7a\x61\xef" + "\x87\xad\xf4\xd6\x2f\x5e\xc3\x9a" + "\xfb\x68\x24\x12\x47\xa0\xd2\xbc" + "\xa6\x5c\x7c\xef\x3f\x42\x7a\xbd" + "\x40\x80\x4c\x06\x52\xcb\x58\xab" + "\x16\x47\x64\x4a\xd5\x4e\xef\x93" + "\x8d\xd4\x2c\xc3\x97\x70\xd1\xf7" + "\x42\xcf\x7f\xd1\x73\xa1\x49\xb2" +
- "\xf5\xcd\x98\xe2\xff\x0f\xfe\x66" + "\xb6\x51\x2e\x7b\xa4\xbe\x61\x3f" + "\xa4\xaf\xd3\xba\x17\x21\x37\x7d" + "\x2f\x6e\x65\xef\x9c\xa0\x21\x65" + "\xe7\x8f\xa5\xe8\x66\xc9\xb8\xb3" + "\xc7\xeb\x47\x5a\x11\x3a\x20\x25" + "\x73\xe5\x4b\x5c\x8d\x58\x81\xfe" + "\x3c\xa0\x49\x1f\xf3\xe2\x32\x61" +
- "\xc4\xec\xa7\xb7\x08\xc1\xe5\xbb" + "\x4c\x2e\xd2\xbf\x8e\xa7\xa5\x62" + "\xd2\x8b\x18\xdf\x33\x40\x97\xb7" + "\xae\xd1\xf7\x4d\xea\xde\x11\xcf" + "\xea\xe3\xac\x53\x4a\x77\xcc\x99" + "\xf6\xc1\x5c\x10\x71\x3a\x37\xe0" + "\x20\x7a\x3d\x13\x7f\x98\x51\xd7" + "\x71\x58\x21\xae\x04\xee\x86\xab" +
- "\x99\x2c\x8c\x0f\x13\xb0\x1a\xec" + "\xc2\x25\x77\xf1\x8f\x96\xe8\x60" + "\x0b\x98\x0a\x94\x93\xa5\xa4\xe1" + "\xb1\xcc\xe9\x20\xb0\x15\xed\x15" + "\xec\x0b\xa0\x64\xcc\x54\xd7\x77" + "\x82\x73\x68\x41\x33\x9c\xd0\x90" + "\x51\xb6\x1f\xc3\x2d\xe0\x4f\x29" + "\x53\xae\x94\x1c\x1a\xcd\x72\x83" +
- "\xe6\x10\xcd\x80\xa2\xf9\x94\x20" + "\xa7\x0d\x8a\x7b\xaa\x32\x52\x04" + "\x4e\x24\x03\x9c\xb6\x81\x9a\x96" + "\x55\xd9\x98\x7e\xca\xb4\x93\x12" + "\xb0\x3a\x8f\xd6\x1d\x42\x31\x16" + "\x82\x8c\x73\xc3\x22\x64\x10\xa0" + "\xf9\x4f\x2c\xf8\x45\x38\xf4\xc5" + "\x8f\xf5\xa0\x1a\xbe\xac\x79\xb4" +
- "\x3b\x70\xc2\x1a\x7a\x10\x37\x85" + "\xb5\x57\xc8\x6b\xd8\x58\x92\xb4" + "\xd1\xcc\xda\xbc\xde\x14\xdf\x57" + "\x29\x85\xae\xc4\xd7\x68\xab\x24" + "\xd0\x59\x4e\x73\xd4\xb5\xd8\x7e" + "\x80\xcc\x95\xc4\xc8\x40\x87\x5f" + "\xb3\xb9\x1d\x29\x5a\xdd\xae\x84" + "\xbe\x95\xb9\x4f\xf8\x60\xb3\x80" +
-
- "\xfa\x76\x1a\xa6\x8d\xc6\xd5\x55" + "\xdc\x54\x15\xca\x1d\x44\x8b\x59" + "\x9c\x27\x3b\x77\xb9\x23\x99\xd3" + "\xfc\x9e\xbf\x36\x3c\x1d\x33\x33" + "\x99\xe3\x8d\x29\x8e\x84\x4c\x2d" + "\x56\x7f\xa2\xa1\x77\x8e\xdb\xcf" + "\x70\xab\xb8\x57\xea\x55\xc8\x94" + "\xba\x79\x78\x6f\xae\x9d\xdb\xdc" +
- "\x38\x6a\x63\x7f\x36\x07\x4f\x4c" + "\xcb\xd5\x76\x0e\xb7\x3f\x94\x9f" + "\x8b\x8b\xb6\xa8\xba\x10\x35\xb0" + "\x1f\x7a\xd0\x9e\x0a\x78\x46\xc2" + "\xc2\x9f\x54\x6d\x15\x14\x05\x3c" + "\xca\x81\x77\x60\x31\x3f\x95\xc2" + "\x13\x54\xd9\xd8\x69\x2c\x5e\x95" + "\xe3\x82\xd2\x7b\xdc\xfa\x00\xb3" +
- "\xb4\x01\x79\xc2\x63\x11\x4b\xa1" + "\xf3\x8b\x9b\x89\xe0\x36\x92\xfd" + "\x0a\xda\xc6\xcb\xec\x91\xb0\x42" + "\x97\xd2\xd1\x5a\x6f\xac\x1d\xbb" + "\x6e\xf7\x1c\xa9\x53\x1d\xe6\x80" + "\xe7\x1e\x1f\xd3\x12\xa4\x10\x41" + "\x77\xcf\xef\x13\xba\xc3\x87\x2d" + "\x76\x0d\x45\xdf\xb4\x4b\x37\x1f" +
- "\x9a\x51\x47\x41\x02\x86\x28\x20" + "\xf0\x72\xb3\x26\xac\x1e\x98\xd0" + "\xc8\xeb\x85\xa7\xca\xa7\xd4\xa9" + "\xe9\x58\xdf\xdb\x0d\xc5\x53\xd9" + "\x8f\x0f\x59\xfd\xcc\x61\x63\x9d" + "\x17\xc9\xe6\x44\x6b\x62\xe9\x72" + "\xcf\x64\xeb\x22\x10\x61\xd9\x7f" + "\xf3\x88\xb2\x9e\x7e\xbb\x3e\x86" +
- "\x03\x44\x7e\x09\x0a\x0a\xe1\x15" + "\x65\x46\x85\x19\x86\x0a\x3d\xcb" + "\x26\x48\x7d\xd6\x11\xe2\xd8\x88" + "\x39\x28\x9d\x0b\x6e\xf6\x9a\xb3" + "\xa8\x5c\x47\xbd\x88\x45\xf9\xa5" + "\x0b\xb8\x77\xc0\x66\x79\x6b\xe0" + "\x6c\xc2\x27\xda\x85\x14\xdb\xfe" + "\xe0\xd5\x0f\xfe\x3a\xd3\x90\xd2" +
- "\x3d\x58\x06\x13\xf3\x02\x62\x68" + "\x2e\x62\x7c\x43\xa0\x0d\xb1\x05" + "\xc8\x7b\x6a\x07\x0f\xaa\x9a\xbf" + "\x43\x4e\x8f\x8f\xfb\x4e\xe9\x25" + "\x6d\xc2\x3d\xfa\xb7\xc9\x35\x8a" + "\xc5\x03\xff\x96\x93\xfb\xe5\xe0" + "\xce\x94\xc3\xeb\x43\x38\x7e\xa7" + "\x60\xde\x61\x83\x95\x65\xde\xce" +
- "\x40\xb5\x22\x0c\x09\x75\x90\xbf" + "\xd4\x67\xc2\xb7\xaa\x42\xde\x2c" + "\x93\xd6\xb0\x5a\xed\xf9\x18\xba" + "\xd9\x60\x46\x6e\xa6\x2a\xa6\x3b" + "\x6a\xa9\x9e\xab\x7b\xf9\x4b\xb2" + "\x32\x0e\xb6\xe3\x42\x96\x03\x5d" + "\xd5\x9b\x4d\x7c\x06\x45\x6a\x4e" + "\xa4\xa6\xd4\x7e\x9e\x5b\x6c\x66" +
- "\xb0\x31\x8a\x67\xf5\x7c\x7b\x87" + "\x20\xb6\x98\x39\xae\x01\x03\xd5" + "\x96\xb3\x0f\xc0\xc5\x57\x42\x73" + "\xa6\x72\xe6\x04\xa0\x18\xfb\xf9" + "\x51\x88\x75\xe8\xeb\xd8\x8b\xff" + "\x44\xba\x99\x5d\xc6\xe4\x64\x1e" + "\xb7\x93\xfd\x7d\xdf\xae\x8e\x4b" + "\x8c\x6b\xe7\x04\x98\x2a\x2f\xba" +
- "\xbd\xdd\x56\x9b\xf0\xa2\x02\xae" + "\xf3\x1c\x2f\x8a\xac\xb5\x39\x13" + "\x0d\xff\x9d\x83\xc7\x69\xb5\xf2" + "\x3d\xa4\xe9\xfe\x64\xe8\xb9\xb0" + "\x4e\x06\xbb\x77\x41\xca\xf8\x4f" + "\x63\x9f\x24\xfd\x12\x28\x5a\x14" + "\x9a\x68\x6f\xf8\xac\xbe\xb7\x3a" + "\x5e\x5f\xd3\x01\x27\xec\xaf\x9b" +
- "\xb7\xc7\x57\xae\xdd\x3f\xa2\xbb" + "\x22\x25\x93\x1b\xf2\x42\x53\x34" + "\xa3\x4a\x6d\x55\xfe\x80\x9c\xfd" + "\x61\xbb\x25\x65\xba\x07\x39\xa0" + "\x33\x89\x21\xff\xe1\x10\xb0\x38" + "\x7b\x11\x52\xaa\x54\xb6\x66\xc0" + "\xea\xe6\xf2\x94\x20\x19\x14\x8e" + "\xb2\xf2\x32\x0d\xca\x7d\xa2\x66" +
- "\x92\xbe\xab\xfb\x21\xb1\xe6\xb2" + "\x76\x00\x33\xe1\xfb\x50\x18\x28" + "\x15\x00\x89\x97\xec\x81\x35\x09" + "\xf5\x77\xff\x75\xed\xdd\xb1\x69" + "\x05\x51\x10\xab\x8f\xb1\xf0\x7c" + "\xef\xcf\x9c\xa8\x31\xed\x3c\x95" + "\x09\x40\x91\xeb\x5f\xf8\x51\x31" + "\xad\x48\xed\x88\x87\x1b\x9f\x3c" +
- "\x1e\xb2\x0f\xe9\xe0\x07\x8f\xa1" + "\xa1\xfc\xa7\xbb\x80\x2b\xfd\x00" + "\xb5\x67\xcd\x95\x27\x7f\x38\x20" + "\xf7\x07\x97\xd3\xe7\xa4\x89\x5b" + "\xce\x07\x44\x89\x3f\xad\x83\x8f" + "\x32\x61\x22\x6c\x94\x5b\x02\xa0" + "\x3b\xc1\x06\xf9\xc7\x63\x95\xc7" + "\x25\xb0\x7b\x4e\x31\x8f\x54\x5f" +
- "\x1f\x0c\xde\x4f\x49\x89\x75\xff" + "\x20\xec\xb6\xe5\xbe\x1a\x8a\xbf" + "\x6c\xdb\xe1\x87\xfb\x78\x22\x70" + "\x8f\x65\xed\x35\x7a\xad\x47\xc4" + "\xf2\xcc\xd0\x03\x38\xaa\xd4\x48" + "\x03\x7c\x9a\x81\x38\xb3\xac\x80" + "\xcc\xce\x17\x6e\x9e\xc8\xc7\x9b" + "\x82\x1d\xbe\x03\x8b\x6b\x73\x46" +
- "\xaa\x5e\x3b\xd4\x42\xf7\x26\x21" + "\x85\x9b\xa5\xdf\x66\x07\x4a\x05" + "\x45\xfd\x6b\x12\x36\x5e\x0d\x9d" + "\x8f\x8a\x4f\x38\xd7\xfb\xf8\xa1" + "\xcc\xfc\x63\xd5\xf5\x80\x76\x31" + "\x28\xa9\x80\xf2\x55\x50\xca\x48" + "\xcf\x78\xb5\x27\xb2\x81\x0b\xe0" + "\x14\xa5\x94\x29\x18\xd9\xaa\x10" +
- "\xc0\xcd\x8b\x35\x1f\x30\x3f\xe6" + "\xf8\x47\x9d\x0a\x99\x9e\x68\x07" + "\x3a\xd4\x43\x4f\x2f\x9e\x68\x1f" + "\x04\x09\x92\x90\x16\x2a\x54\x4d" + "\x07\xa7\xa0\x9c\xd5\x93\xa2\xae" + "\x65\x80\xc6\x8a\x45\xfe\x61\xd0" + "\x8c\x00\x90\x00\x1b\xbf\x33\x10" + "\xb6\x6d\x8a\xc0\x58\x95\x74\x29" +
- "\x94\x87\x5d\xc3\xa7\xd3\xe6\x0e" + "\xe5\xba\x56\x03\x58\x65\x2e\x04" + "\xfd\x22\x33\x64\x8d\x69\x59\x9f" + "\x67\x19\xa6\x50\x15\xae\x79\x93" + "\x1e\x98\xc9\xfc\x62\xae\xb9\x64" + "\xc6\x34\x29\x6d\x31\xd6\xd3\xae" + "\xeb\x65\x4e\x5e\x02\xb3\x54\x24" + "\x28\x04\x95\xf9\x47\xf6\x09\xab" +
- "\xcd\x71\x6e\xa6\x50\x9e\xc9\x34" + "\xe9\x13\xb7\x75\x15\xf9\x94\x17" + "\xb9\x57\x45\xe0\x90\xde\x40\x1e" + "\x18\x56\x7d\x26\x8b\x8c\x17\x3c" + "\xad\x32\x79\xc9\x7d\x10\x62\x90" + "\xd3\x1b\x31\x81\x52\x1d\x20\xa2" + "\x9e\xb7\x5b\xbc\xeb\x5e\xd6\x35" + "\xd0\xf4\x5c\xb7\xa6\x0f\x61\xef" +
- "\x30\xca\xe0\x99\x61\x2a\x70\xc1" + "\xe8\x0a\x56\x99\x6b\x6a\xd4\xbf" + "\x0c\xc3\x1c\x61\xe6\xd5\x6b\xb7" + "\x6a\x98\x5b\x75\x8b\xb7\x0e\x1e" + "\xbd\x4b\x91\x34\x77\x9f\xf3\x7e" + "\xea\x56\x95\xa1\xff\x4c\xc0\xe2" + "\x57\x31\xd5\x69\xce\x8e\x8b\xf7" + "\x65\x04\xe1\xa6\x78\x26\xe5\xd4" +
- "\x7b\xa3\x14\xf6\xec\xe5\x40\x3e" + "\xc2\x74\xfa\x06\x04\x9d\xf2\x74" + "\x86\x0d\x28\x61\xd8\x95\xfc\x6a" + "\x9f\x08\xf1\xae\x02\xc7\xea\xba" + "\xab\xb4\x66\x34\x2b\x7d\x2a\xe4" + "\x95\xd5\x5d\xc8\xd4\x19\xf3\x20" + "\x54\xc2\xf5\xd4\x1e\x49\x48\xba" + "\x8a\x43\x31\x33\xdb\xdd\xc1\xed" +
- "\x09\x5f\xb8\x31\xd3\xd3\xb3\xc1" + "\x4a\xe6\x8a\xa8\x4a\x35\x45\x0f" + "\xfd\x50\xec\x2f\xd3\x26\xb6\xa8" + "\x4f\x83\x28\xe8\xd4\xfb\xdc\x1b" + "\x39\x25\x52\xcd\x66\x28\x5a\xe4" + "\xb3\x7a\x0f\x81\x32\x47\x9d\xfa" + "\x93\xf2\x05\xc9\xb4\xd6\xc1\xd8" + "\x97\xb5\x61\x34\x47\x80\xac\x10" +
- "\x05\x6a\x43\xc2\x36\x92\xef\x11" + "\x3d\x30\x4b\xe5\xb6\x3e\x63\x97" + "\xf1\x0c\x9e\xfd\x94\x49\x17\xd2" + "\x8d\xeb\xd5\x98\x44\xc1\x11\x95" + "\x6c\x2e\x8c\xe7\xc1\xfd\x77\xe5" + "\x77\x65\x4f\xbe\x01\x74\xf3\x8d" + "\xa7\x56\x81\xd3\xa5\x82\x12\x3b" + "\x53\xbe\x16\x07\xeb\x96\x7f\xe0" +
- "\x91\x25\x1f\x74\x37\x38\xcd\x29" + "\xe2\x6e\x39\x64\x9d\xc4\xdb\x4b" + "\x8f\x26\x9d\x26\x02\x71\x59\xe6" + "\x05\x63\x9a\xce\xc6\x39\x6b\x89" + "\x45\x02\xb3\x10\x71\x24\x5e\xc0" + "\x72\x00\x13\xa9\xa8\x19\x52\x84" + "\xc2\x9f\x2a\x0e\xb1\x8c\x15\x88" + "\xc6\x91\xf1\x39\x41\xf6\xc6\xcb" +
- "\x56\x82\xb6\xd3\x78\x46\xa3\x7e" + "\x31\x08\xd9\x94\xf5\x4a\xfd\x01" + "\x92\x95\x2f\x6f\x2f\x4f\x91\x7c" + "\x08\x55\xb3\xf5\x23\xd6\x09\xba" + "\x1a\x7c\x95\xc1\x74\xdd\xbb\x27" + "\x7c\xd5\x16\xd7\x17\x55\x2a\xab" + "\x52\x85\x3f\x8f\x2d\x29\xa4\xd3" + "\x50\x7c\x04\xc6\xb2\x9c\x97\x46" +
- "\x2c\xcd\x91\x6d\x36\x15\xc8\xe2" + "\xe4\xf0\xa3\xda\xea\xbe\xa2\x40" + "\x83\xe0\x41\x24\x59\x7a\x16\xfb" + "\x47\x03\x24\xe9\xe9\x75\x46\x00" + "\x6e\x44\x0e\x84\xff\xaa\x48\x78" + "\x72\x8f\x30\xea\x8f\x25\x9f\x9f" + "\xd9\xfa\x9b\x63\x99\x28\xf1\x50" + "\xf6\x0a\x5c\x20\x63\xae\x39\x09" +
- "\x38\x79\x6d\x48\x3e\xde\xcd\xbc" + "\x45\x8f\xea\x81\xea\xc0\xb4\xaf" + "\xda\x52\xb5\xb2\x5c\x2a\xf1\x3e" + "\xe2\xea\x78\x38\x78\xa3\xe6\x6f" + "\x55\x8f\x54\x8d\x98\x53\xb8\x3f" + "\xaf\x33\x3c\x79\xc5\xa3\xaa\x47" + "\x29\xab\x5a\x11\x21\x2d\x4e\x49" + "\xde\xac\xbe\x50\xba\xce\xad\xd2" +
- "\xe5\xaf\x95\xf1\x36\x12\x5d\x46" + "\x13\x44\xcd\x2d\x12\x3c\xdb\x03" + "\x5d\xb1\xf7\xc8\x35\x3b\xcf\xf1" + "\x7f\xc1\x4f\xb5\xe2\x30\x8d\xbc" + "\xae\x72\xe6\x40\xb9\xa3\x3a\xe7" + "\x75\x8f\xf3\x02\x8d\x84\x32\xa0" + "\x05\x0a\xb1\x3b\x21\xdb\xa0\x1c" + "\x2a\x90\x8d\x68\x2f\xa7\xe9\xc5" +
- "\xbc\xdd\xe4\xe7\x5d\xdb\x67\xf5" + "\x63\x3b\x61\xe7\x28\x9b\x83\xbe" + "\x0d\x04\xa6\x7d\xc6\x77\xcc\x81" + "\x26\x10\x4d\x23\xfb\x88\x2b\x69" + "\x82\x35\x59\xd0\xfa\x35\x9d\x6e" + "\x98\x1b\x05\x56\xfe\x3c\x41\xc7" + "\x52\x23\x6b\xf4\x5e\xed\xce\x3c" + "\x85\x52\xa4\x3a\x21\x16\x6f\xb7" +
- "\xe2\x27\xc6\x6f\x14\x75\xb1\xbb" + "\x51\x3a\x57\x91\xc5\x9b\x56\xa0" + "\xd5\x43\x82\x35\x9e\x6d\x01\xa7" + "\x92\x66\x1d\xac\x56\x0c\xac\x0d" + "\x5f\x0d\x59\xda\xb5\x33\x38\x99" + "\x91\x74\x81\xde\x03\x78\x06\xa8" + "\xd0\x75\xbf\x4d\x12\xf2\xb4\x65" + "\xfb\x0c\xf8\xcc\x32\x02\x96\xcc" +
- "\x5e\x3c\xcc\xbe\xf7\xf5\xdd\x87" + "\xb9\xf8\x35\x6d\xa7\xaf\xfe\x21" + "\xcf\x77\x1d\x75\x51\x9c\x27\x41" + "\x50\x2b\xc9\x6f\xeb\x26\xc7\x47" + "\xf4\x54\xfb\x4c\xc8\xb7\x18\x4b" + "\xee\xcf\x18\xa6\xab\x8d\xf8\xb0" + "\xc8\xe0\x95\x5c\x00\x9a\x46\x3f" + "\xdf\x39\x18\xd1\xf3\x28\x12\xcf" +
- "\x98\x7d\x05\xbd\x54\xcb\x32\x1f" + "\x87\x57\xc4\xe1\x02\x1a\x05\x79" + "\xcb\x32\x76\x7d\x20\x94\x85\xac" + "\x21\x94\x03\xfe\x5b\x26\x8b\xce" + "\x48\x68\x7e\x59\x3e\x0d\x9e\x1f" + "\x18\x09\x64\xe2\x14\xf4\x01\xd0" + "\xc9\x0d\x35\x8a\xcd\x48\x37\xe8" + "\x44\x04\x4f\x7b\x1e\xc8\xdd\x0e" +
- "\xd0\xa9\xc6\x45\x8e\x94\x08\x7a" + "\xb7\xd8\x20\x0c\xe5\x3c\x29\xb7" + "\x71\x03\x67\x74\x29\x57\x5a\x71" + "\x40\x45\x72\xae\x98\xe7\xa9\x6a" + "\x42\xb6\x71\xf9\xec\xeb\xd5\x79" + "\xf3\x98\xd4\xaa\xbb\xb2\xd7\x6f" + "\x6b\xd4\x69\x39\xf9\xb6\x46\xff" + "\x55\xe1\xd2\x29\xe3\x9a\x38\xd7" +
- "\xcc\x8a\x24\x22\x12\x3a\x08\xb2" + "\x66\xe3\x64\x32\xef\xc0\x6e\x1f" + "\x28\xee\xfd\x5a\x04\xb7\x59\x56" + "\xb5\x0b\x43\xe6\x40\x3a\x82\x7a" + "\x79\x0a\x90\xe1\x04\x2a\x59\x24" + "\x76\x65\xee\xc9\x4a\x9d\xe0\xcd" + "\x4a\xa5\x5e\x4b\x3f\x46\xb6\x52" + "\xa7\x65\xca\xd3\xd3\x9e\xfe\x1e" +
-
- "\xdd\x06\x54\x30\xbe\x6d\x7a\xe2" + "\x57\x19\x5d\xdd\x7f\xdc\xb7\x8e" + "\x8f\x4d\x7d\x38\x76\x68\x4a\xf5" + "\xe4\x2d\x76\xc7\x09\x94\x47\x9c" + "\x78\x07\xb3\x99\x5d\x5b\x4d\xbe" + "\x82\x36\x79\x6e\x56\x0c\x38\x25" + "\xe3\x40\xc7\xda\xf3\x37\x2d\x60" + "\xae\xe4\x66\x15\xbe\xea\x0d\x14" +
- "\x1e\x86\x9a\xc4\x26\x61\xee\xea" + "\x06\x0d\x4f\xe1\x65\x3b\x4f\x02" + "\x17\xfc\x9b\xc6\xe8\xf1\xa3\x51" + "\x81\x63\x68\xa7\xe9\xa8\xc3\xc3" + "\xc8\xd4\x03\xb1\x2c\x75\x00\x34" + "\x6b\xb3\x18\x92\x13\x46\xbc\x02" + "\x4a\x50\x51\x76\xeb\x75\x7f\xc6" + "\xfa\xeb\x2a\xd0\x56\x8b\x84\xd6" +
- "\x9b\x26\x82\x17\xdb\x81\x83\x95" + "\x50\xe5\x97\x25\x79\xbf\x34\xae" + "\x53\x51\x38\x5f\x64\x60\x5c\xbb" + "\x48\x80\x08\xe3\xaf\x96\x0e\x6f" + "\x56\x44\x88\x77\x15\x02\x6a\xbf" + "\xa7\x0e\x31\x69\x8c\x68\xb5\xb3" + "\xde\xd2\xfa\x04\x95\x42\xc9\x17" + "\x4d\x6d\x89\x17\xe5\xf0\x20\xe0" +
- "\xa9\xa1\xe5\xbb\x8d\x42\xa4\xcc" + "\x67\xbd\x26\x31\x5f\xfd\x87\x81" + "\x26\x58\x10\x48\x3a\x97\x36\x00" + "\xa0\x61\xbd\xb8\x63\x66\x9b\xa3" + "\x08\xa8\x65\x2d\xef\xde\x42\x6d" + "\x19\x6b\x63\x94\x4f\x04\x69\x49" + "\x4c\x56\x5d\xdd\x47\xee\x11\xf6" + "\x77\x30\x87\xd2\x49\x3a\x2f\x7b" +
- "\x14\xb2\x82\x0f\xdd\xd8\xb0\x03" + "\xc6\xcb\x03\xf1\xf9\x34\x0c\x46" + "\x19\x9e\xd7\x18\x03\x5c\x2e\xf3" + "\xf8\x17\x41\xa8\xba\x88\x88\x8b" + "\x77\x26\x72\xc0\xdc\x37\x3c\x8f" + "\x27\x0f\x1c\x1c\xe9\x1b\xd2\x10" + "\xc6\xa0\xf7\xe0\x68\x84\x7c\xd4" + "\xe0\xc0\xec\xad\x13\x22\xf0\x9b" +
- "\x6e\x7b\xfe\xb7\x60\x41\x55\x97" + "\xb2\x3f\x0a\x40\x9a\x18\x16\x7d" + "\x1e\xca\x28\xe3\xea\x9b\x3e\xd7" + "\xcc\xd8\x93\xe7\x97\x4b\xd0\x0d" + "\xcc\xb8\x6d\x50\x9b\x3c\xc8\xa9" + "\x4c\x81\x38\xcf\xae\x7a\xd4\x5c" + "\xe6\x45\x4b\xb6\x0d\x43\xfc\x26" + "\x84\xea\x18\xd8\x99\x54\x9b\x07" +
- "\x41\x29\xac\xe0\x1a\xd2\xb5\x03" + "\x37\x19\xd3\xc2\x54\x02\x9b\x27" + "\xd0\x92\xc9\xca\x52\xc0\x07\x33" + "\xf3\xb1\xa8\xef\x92\xcb\xa7\x6a" + "\xa5\xc7\x37\x0d\x80\x25\x18\x5a" + "\x22\x54\x2d\x34\x37\x0c\x38\x13" + "\x92\xef\xd2\xd5\x66\x2d\xac\x92" + "\xc6\x63\x0c\x03\xc9\x70\x5a\x03" +
- "\x61\x18\xba\x71\x85\xb7\x09\x51" + "\x3d\xf9\xc8\xd0\x5c\x2d\xb2\x48" + "\x93\xbb\x33\x86\xa7\x84\xfa\xe8" + "\x08\xbd\xeb\x5a\xba\xa6\xfb\x53" + "\xd8\xa7\xee\xe5\xf3\x7d\xf2\x7f" + "\x58\x71\xca\x68\x96\x87\x1c\x52" + "\x05\x1a\x6f\xce\x3b\x13\xd5\xb9" + "\xe4\xbe\x0e\xfd\x53\xcd\x50\x2d" +
- "\x17\xff\x4c\xf7\x33\xa1\xeb\x14" + "\xf2\x13\xb8\xec\x03\xaa\x0a\x24" + "\xee\x5b\x66\x6f\x40\x65\xbb\xcf" + "\x73\xad\x25\xa4\xe4\x1f\x4b\x08" + "\xa6\xf6\x81\xd0\x16\x5d\x9d\x00" + "\x90\x2c\xf8\xee\xe8\x4f\x30\x35" + "\x22\xaa\x9e\xaa\xd5\x46\x03\xf2" + "\xe3\x91\x1c\xac\x07\x9f\xda\x0a" +
- "\xcf\xf1\x0d\xb4\x23\x3e\x9b\x7d" + "\xb4\x71\xe9\x94\x73\x73\x33\x59" + "\x21\xf9\x9c\x66\x14\xbd\x57\xbf" + "\x64\x10\x1a\x0c\xdf\xae\x5d\x86" + "\x25\x91\x27\x83\xd3\x0b\xb7\x3e" + "\xab\xda\xec\x34\x9f\x5b\x3d\xbc" + "\xaf\x5c\x75\x5f\x7e\xed\xe3\x91" + "\x02\x6f\x1e\xd4\x54\x9f\x69\x49" +
- "\x34\x48\x3e\x0f\x58\x77\x41\x30" + "\xcb\xaf\xa9\x17\xc2\x21\xbb\xfd" + "\xb3\x67\x9a\x2f\x7f\xa1\x6f\x75" + "\xa8\xc1\x45\xa2\x21\x24\x6b\x2a" + "\x91\x22\xf0\x4a\x94\x27\xbe\x64" + "\xfe\x04\x58\x2a\xc6\x65\xe4\xad" + "\xd7\x8f\xf0\xa6\x39\xbd\xff\x8d" + "\x3b\x40\x14\xaa\x4c\xa8\xef\xc4" +
- "\x27\x84\x71\x47\x46\x80\xb4\xda" + "\x8b\x0f\x83\x6e\x9b\xff\x17\xdf" + "\x47\x13\x9a\xe4\xe8\x7e\x8d\x40" + "\xae\xd4\xc1\x91\x23\x1e\xc7\x6a" + "\x3c\xd7\xef\x1d\xfd\xb9\xcb\xc8" + "\xc5\xfe\xbb\xbb\x57\x06\x84\x19" + "\xea\xf8\x7e\x9e\xb5\x1c\xdb\x39" + "\x30\x5f\x10\x64\x96\x82\xaa\x78" +
- "\x4a\xef\x5f\x06\xc2\xf1\xbe\xcd" + "\xe3\x92\x5b\xfd\x7d\x0f\xe6\x77" + "\x50\x83\x70\x26\xf0\x49\xc5\xd7" + "\xbf\x21\xf1\x34\xd0\x3a\x1b\x20" + "\x14\xfc\x34\x03\xa1\xc2\xca\x5f" + "\xf6\x52\x45\x34\x09\x9e\x9a\x8a" + "\x82\x30\x65\x97\xd3\xa1\xd8\x7d" + "\x89\xf2\xd4\x79\x8f\x73\xc0\x5f" +
- "\xba\x02\x35\xbd\x71\x8e\x60\x67" + "\xa0\x75\xde\xb4\x24\x1f\xf4\x4e" + "\xe5\x25\x61\xfd\x5e\xde\x8d\xb0" + "\x3f\x54\x09\xa4\x25\x48\x48\xde" + "\x95\x22\xcc\x65\x98\x8d\x19\x1f" + "\xa2\xdf\x0e\x6e\x71\x37\x8a\x42" + "\xc7\x5f\xf3\xad\xa2\x97\x96\x4f" + "\xc7\xc3\xca\xf7\x79\x3c\xa4\x01" +
- "\x0c\x44\xae\x7c\x5b\x8d\x25\xc1" + "\x31\x75\x2b\x40\x41\x8b\xc0\x21" + "\x21\x23\x93\xde\x55\x89\x1a\xf6" + "\xaf\x08\x14\x2d\xf8\xfa\x68\x35" + "\x5b\x96\xcf\x9e\x99\x5e\xb1\x71" + "\x6f\x27\x17\xe9\x48\xd2\x4e\xf1" + "\xe2\xf9\x0c\x82\xa1\xca\xf4\xc6" + "\x7e\x3c\xd8\x18\xb2\x20\x1b\x68" +
- "\x17\xf2\x3e\x53\x65\x6d\x9f\x88" + "\x87\x2e\xca\xc3\xe4\xc7\x58\x71" + "\x67\x41\x2b\xdc\xfb\x0d\x67\xfb" + "\x7f\x25\x4c\x84\x01\x0a\x91\x75" + "\x7d\x57\x88\xcf\x07\xbf\x36\xf3" + "\xce\x2a\x5e\xe4\x50\x52\x24\x22" + "\x85\x3d\xa2\x7c\x8d\x2e\xd9\x2e" + "\x58\x2f\x81\x2b\x4c\xbe\xf8\x29" +
- "\x92\xba\x67\x34\x97\xf1\x5b\xd6" + "\xb0\x54\x09\xf7\xdb\x46\x9b\x8c" + "\x5d\xf1\x78\x0e\xf3\xa0\xc8\x97" + "\x61\xc9\xa4\x85\x9a\xa6\xf3\xa8" + "\x9b\xce\xe4\x61\x0f\x66\x42\x42" + "\x0c\x79\xa6\x6e\xb3\xaa\x06\xbf" + "\x16\x64\x98\xec\x8e\x6f\x70\xc6" + "\x25\xc2\x9f\x9a\xc1\xde\x56\x9e" +
- "\xf1\x03\x51\x9a\x71\x32\xee\x4b" + "\x06\xac\x0e\xf5\xc6\xef\x43\x52" + "\x19\xc1\xdc\x6a\xcb\x22\xe1\xb8" + "\x08\x0a\xb8\xc0\x84\xaa\x7f\x1b" + "\x8c\xd0\xfc\x6d\xbd\xd1\xc3\x32" + "\xde\x27\xe4\x0b\x4e\xec\x9d\x12" + "\x83\x3c\x26\x1d\x9c\x67\xab\x98" + "\xff\x4e\xf6\xce\xb7\x3c\xc8\xaf" +
- "\x51\x5a\xdf\x3f\x7d\xe4\x87\x1d" + "\xb0\xca\xc9\x55\x93\x5f\xfb\x7a" + "\x6e\x58\xe0\x89\x8f\xf5\xbb\x91" + "\x09\x37\x84\x0d\x18\xc0\x72\x7c" + "\xdc\xc3\xb5\x99\xfb\xaa\xa5\xa9" + "\xb0\xae\x44\x38\x1d\x0f\x8a\xa4" + "\x82\xe4\x67\xb6\xdd\xb7\x78\x71" + "\x9a\xa5\x23\x6e\xe9\x85\x39\x45" +
- "\xa5\xb8\xf4\xea\xe0\x4d\x6a\xaa" + "\x32\x0e\xc6\x4b\xca\xd9\xcf\x68" + "\x70\x5e\xd1\x7f\x01\x4b\x8a\x66" + "\x9d\xc0\x7d\xf2\x4a\x69\xf0\xd9" + "\xcd\x8b\x70\xba\xd5\xca\xc3\xf6" + "\x2a\x5c\xb9\x5b\x69\xba\xd2\x5c" + "\x8f\xa5\xc0\x33\xd3\xc1\x28\xaa" + "\x70\x78\xc7\xab\xe3\x74\xe2\x23" +
- "\x4b\x88\xc1\x1c\x2d\xc8\xcf\xec" + "\xb4\x53\x47\x5d\x01\xc2\x5a\xc8" + "\x9f\x09\x8e\x65\xac\xca\xa6\xc7" + "\x90\x73\xb2\x04\x9e\x36\x46\xcf" + "\xea\x67\x64\x50\x49\xd0\xe7\xe2" + "\xcc\xec\xcd\x37\xa2\x63\x1b\x48" + "\x3a\x14\x80\xed\xd8\xab\x29\x40" + "\x88\x0b\xb0\xbc\xc7\xe3\xbf\x28" +
- "\x0b\x4a\xe2\x33\x2f\xf8\x57\xff" + "\x79\x50\x56\xf2\x3f\xe2\xbe\x9c" + "\x25\x58\x5f\xeb\x27\x34\x35\x16" + "\x62\xd6\x48\xe9\xc4\xee\x6f\x27" + "\x2b\x03\x10\xda\xc6\x2b\xb6\xd1" + "\x53\x2a\xe7\xf0\xdd\x51\x83\x71" + "\xba\xe7\x20\x24\x76\x20\x45\x93" + "\x8d\x11\x00\x3a\xff\x8f\x36\x96" +
- "\x6b\x4c\x7c\x9c\x15\x53\x97\xd8" + "\xf7\x9a\x40\xd7\xc0\xa3\x3a\x60" + "\xfb\x32\x71\x00\x0c\x3d\xd5\xb8" + "\x38\x92\x84\xa6\xf7\x2a\xd1\x68" + "\x79\x92\x5d\xbf\xe7\x07\x06\xbe" + "\xce\x74\xda\xaa\x55\x00\xa5\x9a" + "\xcb\x8c\x7e\xba\xcb\x79\x10\xe8" + "\x5e\xff\xf4\xa5\xd1\x71\x0c\x61" +
- "\x61\xa6\xb6\xe3\xbf\x81\x47\x18" + "\xf7\x79\xd2\xe6\x1d\xcb\x51\x77" + "\x62\xb6\x9e\xc5\xd6\x95\xff\xf8" + "\xa7\xde\xd3\x58\xb7\x90\x6d\x18" + "\x54\xf7\xb4\xdf\xc1\xb6\x4b\x0e" + "\xdc\x01\x28\x2b\x6b\xf5\x5c\x5c" + "\x4d\x56\x54\x1f\x52\xe4\x61\xc5" + "\x13\x7f\xdd\xf0\x60\x8c\xfb\xb4" +
- "\xb3\x81\xfc\x29\x0b\x20\x4c\xac" + "\xc1\x87\x1d\x17\x9f\xe0\xc3\xeb" + "\x9e\xaa\x81\x14\x30\x95\x79\x91" + "\xfa\x14\xe1\x92\xe1\x92\x1b\x05" + "\x7f\x53\xb5\xec\xe9\x92\x8f\xdf" + "\x83\x74\x0c\x29\xcc\xb2\xb1\x44" + "\x16\xb0\xde\x2a\x5a\x45\x11\xa7" + "\x2c\x0c\xa1\x81\x56\x68\x4b\x96" +
- "\x7a\x56\x88\x40\x08\x59\xf4\x73" + "\x61\x4a\x21\x1f\x0e\x28\x6b\xeb" + "\x3d\xc1\xf0\xca\x34\xdc\x9a\x8c" + "\x80\xfb\x61\xf5\x38\x29\xd1\x39" + "\xb4\xdf\x6e\xbc\x5e\x3a\xdc\xb2" + "\x0e\x21\x4d\xfe\xb1\xb1\x85\x74" + "\x72\xae\x86\xe1\x00\x04\x2e\x06" + "\x88\x3b\xeb\x6e\x5c\x2d\xe3\x91" +
- "\xfa\xde\x34\xb1\x85\xae\xe9\xc7" + "\x75\xd4\xb2\x1b\xd0\xb1\x73\x60" + "\x0d\xc0\x63\x28\x5e\x61\xad\xb9" + "\xc4\x4a\x5f\x52\x3d\x49\x29\x9e" + "\x4f\xcf\x9a\x4e\xea\x1d\x2b\xc3" + "\x8d\xb8\x0d\xa5\xc8\x01\x1f\x3e" + "\x6c\x91\xda\x04\xea\x70\x5d\xb0" + "\x3e\x80\x65\xd8\x0a\x0d\x4b\x71" +
- "\xee\xaf\x79\xe0\x0c\x92\x45\x59" + "\x1f\x83\x89\x67\xa0\x17\x6e\x68" + "\xe5\x5a\x4a\xb7\xe8\xbe\x66\x59" + "\x46\x8d\x25\x1e\xa2\x73\xa6\x38" + "\x95\x1c\x14\x83\xf2\xc1\x1c\xbd" + "\x86\xe4\x96\x0e\x4f\xcf\x2e\x3b" + "\x78\xfc\xe5\x74\x96\xa8\x3a\xcd" + "\x7a\xfa\x82\x24\x0c\xc1\x5e\x41" +
- "\x10\xf5\xc3\x6e\x31\x5a\x20\x85" + "\x75\x04\x98\xd2\x14\x4a\x7e\x2c" + "\xfd\xeb\x30\x6f\xc0\x19\x3c\xde" + "\x44\xe6\xb7\xd4\x38\x1f\x1c\xdb" + "\x4a\x36\xce\x5d\x75\x1a\x29\xfe" + "\xe3\x5b\x8f\x05\x3c\x2a\xb2\xb7" + "\x8c\xa3\xfe\x37\x02\xc3\xd2\x2c" + "\x17\xbe\x17\x2e\x7a\x96\x30\x29" +
- "\x44\x0a\x5b\xa1\x5e\x79\x0f\x02" + "\x58\xa9\x58\x89\xd7\xc8\x37\x8f" + "\xb5\x75\xb6\xa4\x9b\xe8\xb7\x63" + "\xea\x1a\xc3\x0f\x0c\x0c\xfb\xb4" + "\x2e\x1f\xff\xa7\x39\xe6\x95\xed" + "\xfb\x14\x96\x61\xa3\xf5\x80\x98" + "\xab\x51\x71\x94\x02\xff\xb6\xde" + "\xdb\xdc\x68\xa8\x8c\x11\xc5\x5b" +
- "\xed\x7a\x9f\x34\x91\xcb\x97\xf1" + "\x20\x84\xca\x8f\x00\x5a\x2b\x3b" + "\xd8\xf6\xaa\x23\xe8\x5e\x17\x7c" + "\xb6\x32\xaf\x35\x21\xf4\xdc\x54" + "\x1e\x56\xd6\x27\x07\x43\xa1\x0b" + "\xe2\xb1\x75\xd1\xe4\x5e\x9d\x87" + "\xb5\x7d\x80\x99\x73\x36\xc4\xc7" + "\xcd\x5b\xd5\x9c\x55\x44\xa5\x77" +
- "\xd9\xff\x33\x21\x45\xb2\xb9\xfb" + "\x20\x1a\x0f\x83\xf1\xb2\xa8\x39" + "\x2a\xf5\xa1\xd5\x7d\xc9\x4b\x48" + "\xf8\xdd\x0e\xa4\x56\xbf\xae\xd6" + "\xc6\xda\xcc\x76\xcb\x7a\x25\x32" + "\x27\xff\x86\x15\xec\x36\x4d\xaf" + "\xd1\x7d\xde\xf8\x63\x88\xaa\x8e" + "\x16\x7c\x64\x88\xcf\xd5\x45\x00" +
-
- "\x9d\x97\x05\xc0\x74\xd5\xf3\xa6" + "\x50\xe3\x40\x6a\x42\x2b\x07\xc2" + "\xf9\xec\xe2\x8d\x56\xc1\xa5\xfc" + "\x4e\x34\x15\xa5\x5b\xbf\xc8\xa8" + "\x4a\xf1\x4d\x11\x55\xe5\xae\x97" + "\x6b\xec\xc5\xfd\x4d\x4a\x37\xd4" + "\x18\x54\xa8\x2c\x8f\xc2\x4c\x75" + "\x78\x1f\xc4\xd3\x27\x9e\xcb\x71" +
- "\x39\x5c\x60\x03\x79\x50\x10\x89" + "\x6c\xc9\x42\xa1\x9e\x3d\x84\xf0" + "\x84\x36\x92\x16\x34\x49\x74\xf3" + "\x93\x28\x0a\xfa\x2f\xaa\x2c\x73" + "\x70\x01\x16\x61\x70\xc2\xe8\xb2" + "\xa3\xba\x7f\x43\xcc\x88\x27\xc3" + "\xac\xa3\xed\xa6\x8e\x81\xcd\x39" + "\x07\x2e\x2b\x9e\x39\x42\xe9\xe2" +
- "\x2a\xe5\x60\x02\x9b\xd3\x67\x69" + "\x25\x33\x65\x90\xcc\x85\x25\xd4" + "\x54\x79\xca\x21\x05\xd6\x9b\x0d" + "\xb3\x57\xed\x81\x77\x08\xa2\x4f" + "\xbe\x0b\x4a\xe3\xf8\xef\xc1\x60" + "\x64\xef\xf6\x84\x0c\x04\xb0\x56" + "\x83\x84\xaf\xb1\x24\x2b\xbe\x28" + "\x14\x16\x53\xf5\x63\x81\x27\xb2" +
- "\x1c\xac\x22\x59\x45\x75\xf2\x8d" + "\x63\x3f\x2b\xa5\x5c\xef\xb3\xa7" + "\xc4\x57\xde\x71\x14\xb2\x77\x8e" + "\x8b\x00\x4c\x83\x10\x2c\x68\x31" + "\x31\x5d\xd5\x4b\xf0\x24\x68\xc7" + "\x71\x1c\xb6\x17\x86\xc0\xd1\xb6" + "\x9d\x08\xa5\xc2\x03\x09\xdb\x31" + "\x3f\x5d\x4e\x18\x72\x21\x09\x9c" +
- "\x38\xc6\x0c\xc0\x5b\xed\x7c\xdd" + "\xc2\x8f\x27\x61\xeb\x15\x20\x1a" + "\xd6\xf8\x37\x6a\x88\x52\x8e\x2e" + "\xad\x33\x99\xe7\x6f\x78\x57\xc4" + "\x1a\x21\x51\x2c\xce\x4c\xfe\xb3" + "\x98\x04\xc2\x24\xb2\x10\x9b\xad" + "\xe5\xb5\x8d\xd2\x4f\x7a\xd8\x90" + "\xc3\x2f\xca\x3a\x05\xd1\x8c\x69" +
- "\x6d\x53\x1b\xe9\x07\x2d\x11\x4f" + "\xd6\x09\xba\x9e\xf2\x82\xb9\xce" + "\x6f\x39\x7c\x19\x2c\x7b\x15\x3c" + "\x24\xeb\x66\x7b\x41\x2d\x3c\xe2" + "\x37\x0d\x33\x3f\xd9\x57\x0c\x48" + "\xeb\x8d\x10\x79\xa1\xc8\xa4\xb3" + "\xe5\x9c\x19\xcb\xde\x88\x23\x70" + "\xd4\xa8\x44\xb9\x11\x92\x01\x0b" +
- "\x36\xb3\x0b\x84\x92\xa6\xf2\x24" + "\x7b\xfa\x69\xa6\xdc\x3b\x35\x7c" + "\x00\xc3\xc9\xde\xfc\xd6\x20\xda" + "\x17\x4f\x3a\xa1\x2f\xbe\x5f\x62" + "\x28\x73\xc1\xdb\x1a\xb6\xb1\xa2" + "\x21\x56\x51\xa9\xbf\x65\x89\x00" + "\x46\xff\x20\xc6\x39\x09\x69\x49" + "\x1c\xe9\x17\x87\x7d\xd2\x2d\x18" +
- "\x97\x39\x6c\xea\x35\x50\xce\x5a" + "\xef\x0b\x61\xc2\xaa\x9a\x25\x54" + "\x39\xdd\x80\x3c\x3f\xbb\x18\xef" + "\x39\xfa\xc3\x5f\x5b\xb9\x10\x69" + "\xee\x9a\xe0\x43\x10\xf5\xe2\xfc" + "\x65\x56\x67\xa7\x9f\x6c\xd5\xce" + "\x61\xdb\x72\xd8\xac\x65\xe2\x10" + "\x69\xce\x9f\xae\x2e\x81\x82\x69" +
- "\x98\x09\x80\xce\xc6\x11\xbe\x29" + "\xd9\x60\x03\xb9\x52\x17\xbb\x72" + "\x90\xd5\x4a\x5a\x97\x31\x19\x2c" + "\xc0\xdb\xc1\x9f\x48\xf5\xa2\x2b" + "\xe0\xeb\x90\xe4\xbb\xee\xe4\x7f" + "\xc0\x11\xae\x7f\xcd\xa4\xa0\x12" + "\x37\xba\x03\xe9\x81\xcf\x97\x71" + "\xd8\x6d\x1c\xde\xa8\x4a\x7d\xcf" +
- "\x4c\x68\xd5\x3f\xf4\x6b\xaf\x92" + "\xa1\x0a\x36\x80\xcf\xee\x26\x2b" + "\x82\x6a\x54\x00\x30\x0f\x96\xbd" + "\xfe\xd8\x9a\xf5\x43\x3c\x7b\x40" + "\xba\x82\x9c\x24\xfe\xe5\xca\x86" + "\x4c\x74\x63\x24\xc7\xae\x0f\x9e" + "\x72\x62\x91\x94\xe8\x51\xf5\x87" + "\x15\x06\xeb\x6c\x44\x93\x3f\x03" +
- "\x84\x2e\xe8\x8b\xd1\xb0\x5e\x1e" + "\xef\x2f\x58\x7a\x0e\x7f\x96\x89" + "\xfa\x21\xe9\xa6\xd5\x87\xf6\xbc" + "\xba\x09\x7a\xd3\xf3\x4c\xee\xdf" + "\x65\xc4\x93\xb4\x65\x69\xf0\x94" + "\x30\xc0\x35\x76\x1c\x9a\x8b\x63" + "\x9f\x5e\xf0\x66\x64\x78\x66\x76" + "\x25\xa7\x4d\xc0\x08\x68\xaf\xcc" +
- "\xfc\xcc\x8f\x76\x90\xb6\x2e\xca" + "\x62\xb3\x35\xb8\x7d\xd3\x02\xf4" + "\xce\xfc\xfd\xe2\xd0\xc0\xfa\x0e" + "\x90\xd9\x38\xb6\xef\xcd\xc9\xef" + "\x8b\x9a\x66\xd1\x72\x2b\xf1\x2a" + "\xbd\xcc\x74\x57\xbc\x36\xc5\x33" + "\x0e\x87\x34\xfb\x09\x19\xb2\x30" + "\xca\x5a\xf2\x7d\xf7\xa2\x8f\xc3" +
- "\xf5\xf3\x81\xbf\x2b\xf0\xc5\x74" + "\x81\x45\x7e\xaf\xae\xa5\x25\x05" + "\xae\x54\x3c\x43\xba\xaa\xd2\x88" + "\xc5\x56\x6a\x80\xdb\x75\x97\xed" + "\x7d\xb3\xed\xc0\x8a\x73\x20\xd3" + "\x51\x1f\xcc\x66\xee\xb6\xfd\x25" + "\x76\x0d\x60\x10\x17\x1d\x66\xac" + "\x76\xed\xd1\xbd\xf3\xc1\x1e\x93" +
- "\xf1\x43\xee\x19\x62\x1d\xc1\x65" + "\x97\x9d\x82\x60\x3e\x7c\xd5\x5c" + "\xe8\xe6\x4b\x98\xa3\x91\x6c\xd2" + "\xbd\x53\x0c\x8b\x09\x93\x8d\xf0" + "\xea\xe4\x16\xc0\x5b\x9e\xbc\x94" + "\x2b\x3d\xd4\x11\x39\x68\x91\xd3" + "\x55\x11\x70\x73\xd7\x5a\x6c\x88" + "\x15\x07\xb0\x20\x26\x76\x37\xe0" +
- "\x59\xba\x80\xaa\xec\xc9\x01\x7f" + "\x51\x8e\x53\x68\x1a\x41\x83\x30" + "\xaf\x28\x81\xe8\xf1\x70\x03\x97" + "\x4b\xc1\xde\x91\xdb\xc3\x5c\x62" + "\x07\x31\xac\x01\x6c\x66\xf9\xfe" + "\xc3\x7a\x05\xd5\x77\xd5\xa8\xb2" + "\xf7\x5d\xbe\x92\x99\x62\xf2\xb0" + "\x24\x39\x35\x00\xe5\xc8\x79\xf5" +
- "\x7a\xed\x41\x13\x93\x3d\xfa\xb8" + "\x49\x9d\xb5\xa7\x2c\x27\x23\x42" + "\xa4\xc4\xb8\x83\x47\x19\xcb\x3d" + "\xe4\x02\x13\xed\x01\x3c\x41\x4e" + "\xce\x44\x7e\xe1\x27\x91\x99\x6d" + "\xfb\xad\xb3\x33\x75\xbf\x86\xee" + "\xca\x96\xaa\x25\xe6\x2f\x90\xf6" + "\x7d\xe4\xaa\xe5\xe4\x40\x35\xb7" +
- "\x8c\x15\x4a\x1b\x7b\x1d\x80\x32" + "\x69\xa3\xe2\x27\x9e\xc9\x71\xe5" + "\x97\xf1\xd9\x10\xc0\x76\xcb\x40" + "\xae\xc0\x67\x31\x89\xc2\x08\xc3" + "\xf2\x58\x79\xeb\xd3\x9d\xef\xa6" + "\xb1\x79\x08\x30\xfc\x6d\x22\xa7" + "\x36\x06\xdf\x7e\x62\xb3\xd0\x6c" + "\xed\x7e\xc3\x7b\x6c\xce\xfb\x4e" +
- "\x21\x90\x69\x8d\x05\x2a\xf9\x75" + "\xe3\x66\x25\x77\x79\x4c\x6d\x58" + "\x3a\xd2\x1a\x76\xf1\xa5\x8c\x37" + "\xac\xa8\x65\x14\xfc\x86\x0d\x65" + "\x51\xa2\x2b\x84\x57\xd4\x4e\x7a" + "\x33\x49\x23\x42\xe6\xe3\x65\x6b" + "\x57\xd6\xaa\x31\xb7\x43\x15\xaf" + "\x69\xc3\xfe\xcb\x98\xfe\xce\xa4" +
- "\xfb\xbe\x47\x9f\x90\xda\x87\xb5" + "\x13\x2d\x31\x41\xfb\xe9\x62\x65" + "\xfe\xce\xf1\xef\x59\xea\x91\xa6" + "\xf6\x4c\xfc\x05\x7a\x47\x30\xcc" + "\x3d\xfd\x0f\x0b\x61\x24\x63\xa1" + "\x56\x59\x35\x5b\x3b\x6f\xf1\xa1" + "\x24\xec\x24\x42\x53\x8d\x14\x5b" + "\x2a\x01\x77\xf9\x7b\x4e\x83\xdc" +
- "\xbc\x9d\xc6\xb2\x75\x5e\xfc\x7b" + "\x6c\xda\xc3\x03\x29\x7a\xa7\x3a" + "\x71\x02\x91\xca\x3c\xf0\x0d\xde" + "\x55\xdc\x06\x78\x4a\xca\xd5\xcb" + "\xcb\x76\xb4\x6d\x07\x58\xca\xe1" + "\x1e\xa3\x37\x5f\x62\x5d\xe1\xfd" + "\x16\xf4\x1a\xf4\x20\xf5\x9a\xf4" + "\xb5\x2d\x34\x7d\xb1\xc5\xc5\x96" +
- "\x9b\xeb\x4c\xeb\xb7\x43\x5c\x15" + "\x1a\x37\x77\x4e\x10\x30\x99\x2e" + "\xaf\x43\x5d\x67\xda\x87\x29\x1d" + "\x72\xfd\x99\x85\xc0\xc1\x2b\xef" + "\xb2\xf6\x42\x93\x7b\x4b\x89\x96" + "\xf0\x71\x8e\x7c\xf2\xad\x1e\x20" + "\xfc\x3e\x1f\x4a\x9f\x9d\x47\xf3" + "\x04\x97\x2a\x70\x42\xa7\xf8\xe0" +
- "\x0c\xa4\xeb\xb3\xb6\x44\xfd\xea" + "\xd0\xe0\xc1\xc1\x29\x9f\x73\xf9" + "\x5e\x50\x9d\x61\x1a\x47\x91\x00" + "\x3e\x26\x7c\x9d\x96\x9c\x5f\xc1" + "\x33\xbe\xaf\x83\x85\x72\xe4\x5b" + "\x92\xe0\xf1\x04\xaf\xd6\xb6\xa3" + "\x11\x9d\x1a\x75\xb9\x26\x65\xe7" + "\xd2\xe4\x4a\x9a\x6d\xb2\xc5\x2e" +
- "\x8d\xfb\xf6\x02\xd9\xf4\x66\xeb" + "\x64\x21\x91\x96\x61\xc5\x63\x40" + "\x00\x30\xef\x80\xc1\x50\x70\xeb" + "\xf0\xb3\xa5\xea\x33\x1c\x8d\x28" + "\xd8\x6f\x80\x07\xd6\x68\x7c\xe8" + "\x0f\xf5\xbb\x4b\xd5\xf9\xf7\xb2" + "\x27\x66\x8d\xac\x3a\x2f\x97\x25" + "\x3b\xc1\xe8\x10\x74\x77\x54\xf8" +
- "\x60\x4a\x2b\x87\x6c\xef\x50\xcc" + "\x1b\x52\x13\x46\xa4\x34\x2a\xab" + "\xd1\x15\x3e\x98\x90\xc1\xc5\x39" + "\x12\x55\x90\x59\xdf\xe5\xdd\x61" + "\xf3\x75\x22\x9f\x21\xf6\x17\xe4" + "\x4b\x89\x1d\x45\xb6\xc8\x50\x07" + "\xaa\xbd\xb0\x78\xb9\x4a\xb0\x75" + "\xbd\x89\x85\x45\xd4\x9f\xfd\x3b" +
- "\xb6\x20\x91\xee\x30\x3e\x01\xf1" + "\x3e\x74\xa4\x23\x93\xaf\x51\x2b" + "\x9e\x4d\xd1\x48\xae\xff\x96\xea" + "\x32\x1d\x8a\x69\xbe\x0d\xdc\x71" + "\xa4\xcc\x80\x01\xd2\x62\x49\x91" + "\x63\x89\x56\xc3\x77\x06\xe6\x1a" + "\x44\xc4\x7b\x43\xb1\x27\xf2\x8c" + "\x7a\x2c\x96\xc9\x3b\xc8\x50\xc6" +
- "\xc4\xcf\x7c\xfe\xdd\xc7\xc2\x23" + "\x48\x9d\x92\x1b\x9d\xc8\x25\xf9" + "\x33\x3c\x78\x06\x4b\xf7\x60\x44" + "\x5a\x47\x90\xa5\x49\x8d\x2c\xac" + "\xa0\xbb\x07\xb8\x07\xb4\x40\xfb" + "\x3a\x8f\xff\x69\x2d\x36\x1e\x9d" + "\xa4\x64\xef\xcb\x81\x96\x3e\xa3" + "\xb2\xb4\x2f\x33\xfa\xe5\xec\x67" +
- "\xe3\x10\x9f\x73\x9b\xa9\x00\x69" + "\x25\x59\x52\xff\xa9\x1c\x34\xc3" + "\x41\xd0\xe2\xa9\x26\xa6\x18\xee" + "\xdd\x0d\x58\x29\x85\x36\xa8\xa5" + "\xcd\xe3\x7d\x9d\x81\x0c\x47\xf3" + "\x9c\xcf\x62\x20\x86\x25\xf0\xed" + "\xb0\xed\x10\xc0\xfa\x22\x35\xf4" + "\xae\xb1\xa4\x13\x35\x41\x31\x30" +
- "\x4b\xb9\x22\xdb\x2a\xe0\x92\xc7" + "\x5b\xa4\xea\xa1\xe9\x8a\x3d\x99" + "\x63\x1c\x1e\xcd\xd3\x6c\xad\x8a" + "\x8a\x68\xce\xc5\xa7\x9c\x52\x89" + "\x53\xa2\x72\xe5\xaa\xe3\xce\x2c" + "\xfb\x1e\xa2\x02\x38\x64\x2b\xe0" + "\x58\x03\x43\xc9\x6e\x1b\x09\xa7" + "\x04\xb5\x7d\x9d\xfa\xb1\xd1\x06" +
- "\x33\x47\x74\xc4\x32\x6d\x84\x58" + "\x34\x9e\x9f\x37\x71\x7c\x51\x40" + "\xca\xf6\x0e\x13\x5f\x65\x65\x2f" + "\x3f\x50\xf3\xf1\x88\x44\x6e\x52" + "\x76\xa9\xe4\x7e\x17\xbd\x67\x84" + "\xd1\x63\x13\x92\x13\xc9\x9d\x1d" + "\x41\xe0\x69\xb0\x33\x4c\xd2\xd8" + "\x51\x7f\xdf\x2c\x0a\xda\xb5\x5e" +
- "\x4f\x99\x7b\x19\xb1\x3c\x0f\x1c" + "\xe9\xea\x43\x28\xc5\xa6\x95\x3c" + "\xa5\x7e\x09\xa6\xc9\xff\x66\x77" + "\x67\xb8\x23\xd7\x93\x40\xea\x7b" + "\xf9\x78\xb3\x4d\x73\x1f\x8e\xb4" + "\xac\x77\x7b\xe3\x00\x5b\x02\x70" + "\x46\xad\x24\xaf\xe7\xc8\x3d\x94" + "\x85\x0a\xd0\x16\xac\x15\x8a\xb9" +
- "\x04\xb0\x43\x27\xba\x38\xdc\x3a" + "\xee\x15\x44\x33\xf7\xf4\xc7\xb1" + "\x5a\xd0\x62\x1e\x8f\xdf\x43\xea" + "\xb6\xa3\x76\x9d\x05\x89\x61\x32" + "\x46\x0f\x3a\xa2\xb5\x0b\xbd\x2f" + "\x8c\x91\x01\x6a\xdb\x71\xc9\x5b" + "\x94\x3f\x74\xb4\x4a\xd9\x01\x78" + "\x2b\xe2\x6a\x67\x5e\xf6\x4d\xb9" +
- "\x4c\x89\x95\xaf\xab\xbf\xfc\xaa" + "\x41\x22\x6b\x27\x07\xdc\x9b\x7b" + "\x8b\xa4\xdd\x5b\x62\x83\xf9\xea" + "\xdf\xb4\xfc\xa3\xf2\xfa\x77\x59" + "\x5b\x4b\x2c\x05\xef\x42\xd0\xbe" + "\xf0\x91\x75\x06\x71\x7f\xe8\x9f" + "\xc7\x4e\xf2\x22\xca\x73\x9c\xc8" + "\x1b\x9f\x4a\xe6\x9e\xfa\x37\x7d" +
-
- "\x0f\x0c\x75\x0a\x88\x64\x7a\xcc" + "\x83\x8e\x54\x4e\xe3\xcf\xba\x39" + "\x05\x0f\x11\x0c\x76\x8c\x41\x3d" + "\x88\x15\xf1\xb1\x4c\xaa\x4d\x3e" + "\xff\x69\xfc\x5f\xb5\xe7\x33\x27" + "\x27\x31\x05\x92\xbc\x47\xf1\x46" + "\x94\xdf\x22\xd7\x34\x24\x5b\x88" + "\x7c\x6b\xfc\xe6\x65\x4f\x44\x6a" +
- "\xa8\x6e\xf1\xc3\x5a\x46\x1a\x7a" + "\x1c\xd1\xf1\xb2\x1d\x46\x5a\x11" + "\x72\xa1\x68\x6c\x95\xdd\x67\x47" + "\x98\x46\x3a\xd1\xeb\xf2\x92\x33" + "\xc7\xcd\x26\xe5\xcd\x9c\xa9\xc7" + "\x81\x2b\x29\x22\xdc\x7f\x53\x8e" + "\x98\x91\xd3\xa6\x69\xcf\xd8\x76" + "\x2d\x85\x46\x24\x43\xff\xc5\xff" +
- "\xbd\xdf\xae\xbd\xf4\x16\x0b\x6d" + "\xed\x6c\x74\x86\x60\x32\xfd\x23" + "\x17\x3e\x4b\xff\x2f\x1d\xfb\x8b" + "\xc8\x14\x9c\x01\x2d\xec\xf2\xc7" + "\x0d\x4b\x10\x45\xf2\x32\x08\x3e" + "\x7e\x2b\xea\xad\xfb\xda\x00\x5f" + "\x0f\xfb\xfb\x99\x66\xcf\xe5\x29" + "\xda\x7c\x82\x61\x23\x97\x4f\x26" +
- "\xe6\x67\x05\xa9\x7e\x4f\xb1\x97" + "\xb7\x5c\xae\xb6\xb7\x57\x32\x51" + "\x3d\x90\x10\x9f\x3c\x4a\x45\x85" + "\x24\x37\xbc\x69\xad\xc9\xd2\xd8" + "\x44\xcb\x29\x6b\x24\x93\xda\x38" + "\xac\xcb\xc8\x77\x1d\xa2\x40\xb5" + "\x42\x8e\x91\x01\x35\xe4\xbf\x9b" + "\x4e\x61\xc3\x56\x7a\x70\xfa\xff" +
- "\x7f\xc2\x0b\xe3\xf3\xa2\xb1\x6e" + "\x11\x65\x83\xb0\x5a\xc0\xf0\xe5" + "\x0e\xab\x65\x49\xbf\x1b\x74\x4d" + "\xbd\x4b\x46\x83\xca\x41\xec\xfe" + "\x9f\xb0\xd0\x99\x5f\x70\xca\x1a" + "\xfa\xa5\x2d\xf4\x56\xcc\xd6\xc5" + "\x31\xb9\x52\xcc\xdd\x4e\x96\x49" + "\xd8\xd8\x84\xc8\x15\x96\xe5\x8a" +
- "\xb7\x53\xe3\xd4\xf1\xe3\xe4\x0c" + "\xa0\xb0\x46\xef\x14\x8a\x2d\x06" + "\xfd\x73\x4b\x57\xab\xd5\x08\x64" + "\xfd\x3f\x27\xd3\xc9\xd1\x41\xbc" + "\x00\x78\xe7\x6b\xe7\xe1\x38\x35" + "\x31\x50\x65\xc5\x37\x8b\xfe\x71" + "\x1a\x33\x9b\x6b\x21\x16\xd9\x1c" + "\x73\x8f\x38\xbb\x0b\x5d\x82\xad" +
- "\x8a\x86\xf8\x39\x7b\xb5\x34\xf6" + "\xaf\x69\xcc\x75\xd4\x4f\x7f\xe2" + "\x6e\x49\xd5\xd0\xcb\x58\x7e\xa4" + "\x7f\xe0\x23\xd3\x3f\x79\x26\x8a" + "\x49\xf3\x30\xfa\x72\x9b\x1a\xc6" + "\x34\xd1\x96\xb6\xc9\xd9\xc9\x94" + "\xd1\xa6\x80\x58\xa8\xec\x2b\x79" + "\x95\x99\x03\xaf\x45\x46\xcc\xbd" +
- "\x19\x62\xb7\x1c\x5b\xe0\xc2\x56" + "\x7e\x7e\x56\x71\x91\xbf\xc0\x0e" + "\x10\xc9\xc4\x61\x86\x6f\x07\xe7" + "\xd9\x04\xbc\xba\x5b\x08\x7b\xd6" + "\x6a\xa9\x93\x5e\x59\x04\xb9\x9f" + "\x9a\x24\xdc\xfb\xea\xc1\x26\x75" + "\xb7\x0b\xdd\xec\x67\xd3\x44\x0d" + "\x95\xd6\xc0\x9d\x17\x99\x39\x95" +
- "\x3c\x6c\x79\x8c\xe5\xf8\x7e\xce" + "\x7a\xe5\x66\xdd\x84\xae\xda\x9a" + "\x33\x7f\x22\x45\x3e\xe1\x4a\x78" + "\x57\xe7\x85\x2a\xb8\xc5\x46\xb0" + "\x1f\x63\x37\xec\xae\x50\xaa\xb7" + "\x58\x07\x30\x3b\xca\x4f\xdc\xbe" + "\x0b\x70\xc9\x0a\x7e\x56\x82\x0f" + "\xd2\xf8\xf5\x4f\xd4\xd9\x71\x10" +
- "\x18\x0d\x24\x9e\xe9\x0e\x36\x61" + "\x66\x44\xb9\xb4\xac\xdc\x7c\x05" + "\x5c\x32\xe5\x2f\xd1\x7c\x66\xe7" + "\x3b\x4e\x97\x21\xb5\x97\xa2\x1f" + "\x76\x3d\x08\xdb\xe7\x81\x40\xfa" + "\x15\xbd\x06\xf2\xe6\x3b\x99\x31" + "\x8c\x9f\xc1\x14\x9b\x26\x49\x89" + "\x57\x23\xd9\xa9\x72\x8d\x46\x21" +
- "\x11\x28\x1a\xe5\xc4\xf6\x9e\xd0" + "\xb9\x66\xfb\xb8\x2b\x86\xf6\x39" + "\x99\xaa\xdf\x22\x8d\x7f\xe7\x64" + "\xac\x8a\xb0\x61\x44\x50\x10\x7b" + "\x32\xf3\x7d\x4a\x4c\x4e\x70\x71" + "\x5b\x01\xfe\x2f\x34\x34\x97\xd0" + "\x0e\x02\xd3\x08\x44\xaf\x0e\xab" + "\x7a\xb9\x63\xed\x9e\x90\xb1\x28" +
- "\xec\x06\xc5\xa4\x83\xc5\xcb\x2c" + "\x97\xfe\xac\xd1\x88\xd1\x7e\x95" + "\xa2\xae\xf1\x12\x33\xd8\xae\x8b" + "\x2d\x36\x25\x83\xb4\x6c\x2a\xef" + "\x43\x5c\x19\x8e\x42\xde\x0d\x13" + "\xc6\x50\x60\x0e\x5a\x02\x42\xc8" + "\x5d\x6a\x68\x08\xa7\x72\xa9\x2d" + "\xa8\xb4\x08\xe5\xa1\x99\x29\xb5" +
- "\x4f\xcd\xad\xcd\x82\xa8\x3f\x2f" + "\x95\x19\x63\x5f\x59\x68\xef\xa4" + "\x6f\x76\x31\xe5\xf9\xa2\x2c\xe5" + "\xd3\xc1\xe2\x57\x30\x5c\xaf\x20" + "\xb8\x94\x1e\xe5\xf6\x28\x48\x1e" + "\x4f\x5d\x2f\x1a\x75\xa1\x00\xf9" + "\xa0\x58\x2c\x39\xb3\xad\x31\xe8" + "\x66\x58\x6e\x1b\xca\x90\x5a\x4c" +
- "\xbd\xa8\xa5\x10\xb9\x90\xf0\xd9" + "\xda\x64\x68\x09\x49\xd2\x91\xca" + "\xc1\xdb\x67\x3f\xbe\x93\x6a\x8e" + "\x4c\x76\xf4\xf5\xba\x6f\xae\xac" + "\xa0\x11\x14\xd2\xe0\xc6\x63\x15" + "\xd8\x4a\x0a\xda\x7f\x78\xfa\x28" + "\x30\x80\x8c\x90\x1c\x49\x24\xd5" + "\x07\x5f\x79\x4c\x0e\xba\x57\x12" +
- "\x7c\x82\x82\x61\xa8\xcb\x3d\x5f" + "\x52\x72\x7e\xbd\xdd\x48\xa4\xd1" + "\x15\xb8\x93\xf4\xfc\x96\x8f\x2d" + "\x5f\xa9\x0a\x3b\x26\x4c\x0a\xba" + "\x7f\x00\xa0\x63\x40\x51\xa1\x88" + "\x46\x58\x9c\x6a\x5e\xc2\x64\x95" + "\xca\xcb\x0f\xdc\x0f\x7b\x4d\x5a" + "\x0e\x74\x8a\x3f\xa3\xda\x75\x22" +
- "\x54\x97\xca\xce\x67\x91\xf4\x83" + "\xa0\x39\x79\x4b\xf6\x2c\x6d\x42" + "\xbf\xd0\x3f\x72\x55\xe3\x55\x25" + "\xe2\x44\xf1\xc4\x06\x6d\x6e\xa9" + "\x61\x0e\x88\x87\xdd\xa8\x68\x47" + "\xd5\xe4\x08\xe5\x15\x38\x54\x15" + "\x15\x5e\xb6\xb1\x72\xe7\xd7\x09" + "\xa0\x2f\x30\xac\xd6\x9d\x43\x63" +
- "\x6b\x08\x61\x04\xcc\x91\x95\x15" + "\x51\x6e\xe6\x95\x94\xaa\x95\xb6" + "\x31\xd5\xde\x79\x67\x94\x4c\x2d" + "\x79\xbe\xc2\x89\xba\x82\x24\xbd" + "\x19\xbf\x0b\xa2\x8a\x65\xe2\x8e" + "\x17\x79\x24\x32\x8a\x52\x00\xc0" + "\x45\xe8\xea\xff\x4a\xbe\x24\xd9" + "\x8b\x2c\x99\xed\xeb\x2b\x31\x51" +
- "\xc2\x35\x4e\xc1\x2f\x80\x3f\xb9" + "\x3c\x33\x41\x43\x7c\x5b\x73\x71" + "\x62\xf3\xd4\x16\x04\x51\xa2\x03" + "\x8e\x3c\x43\xbf\x9b\x06\x4d\x3f" + "\x7c\x5a\x8f\xf7\x01\xae\x83\x0d" + "\x07\xed\x4e\x7c\xbe\xff\xa8\x50" + "\x83\x0f\xe1\x76\x06\x89\x4f\xc7" + "\xe1\xf8\xda\x9d\x66\x09\x08\x7d" +
- "\xd9\x2b\x75\xdc\x58\xb9\x01\x3a" + "\x45\x5d\x21\x0c\xc2\xdb\xab\x2b" + "\xc1\x41\x16\x13\x9a\xd7\x89\xe6" + "\xd4\x5e\xe0\x80\xda\xf0\xe8\x48" + "\xc4\x70\xbb\x77\xeb\x5f\x50\x4b" + "\xf7\x7e\x05\xb6\x2b\x3e\xbd\xef" + "\xa5\x3c\x60\xce\x2d\xe2\x83\x75" + "\xc7\x70\x5c\x2c\xf2\xb1\xe3\xfb" +
- "\xcc\x04\x8e\x69\xe1\xf8\x1d\xb1" + "\xc8\x05\x90\x16\x03\xe2\x7b\x87" + "\x79\x61\x3c\x4f\x8c\x9e\x74\x32" + "\x05\xfc\x53\x78\x0a\x9d\xbc\x2d" + "\x37\xd9\x54\x94\x93\x4f\x7d\x18" + "\x1b\x0e\x80\xb4\x9d\xce\x82\xe6" + "\xe8\x68\x5e\x16\xd8\x9a\x12\xa9" + "\x5b\x78\x7f\xbe\x35\x97\xe2\x0f" +
- "\x5a\xe3\xe5\x29\xf0\xec\xc1\x8e" + "\xb3\xc2\x45\x86\xe5\x68\x31\x2f" + "\xb2\x4c\xf9\xc7\x62\x73\x29\xe9" + "\x39\x0b\xc9\xd1\x66\x14\xbf\x4f" + "\x2a\xae\x0b\x92\x56\x76\x4f\x3e" + "\x72\xb1\xbe\xf1\xb9\x04\x5d\x80" + "\xb4\xd4\xdb\xdb\x08\x72\x9a\x72" + "\x53\xca\xae\x87\x56\xe4\xad\x1a" +
- "\xb7\x02\x9e\x5b\x0c\xf4\x03\x53" + "\xe8\x04\xee\x35\x92\x96\x7c\xa3" + "\x2b\x63\xd6\x34\x20\xcc\x46\x5f" + "\x5b\x54\xac\x96\xb2\x72\xef\x55" + "\x62\xb0\x91\x7b\x1f\x5c\xec\xab" + "\x21\xe8\x33\xbb\xc7\xe1\x79\x0a" + "\x17\x41\x9f\x3a\x28\xb4\x04\xbb" + "\x5a\x47\x2a\xfd\x8f\xf2\xe1\x0d" +
- "\x08\xa5\x34\x19\x54\x1f\xff\xb0" + "\x1a\xf3\xbb\x04\x76\x39\xe1\x19" + "\xb4\xa6\x17\x37\x03\xe6\xa8\xb2" + "\xb9\x2c\xf1\x0e\x5d\xe4\x01\xd6" + "\x8e\xe9\x15\xb5\xf5\x0a\x3f\x56" + "\x9b\x4f\x98\x33\xb6\x9d\x12\x9b" + "\x65\x4a\x7e\xa4\x2f\xba\x4a\xe3" + "\x82\x9d\x3f\x9e\xd1\x82\x6f\xb5" +
- "\xb4\x34\x44\x3a\xcf\x9c\x01\x31" + "\xdc\x54\x79\x1a\x11\x81\x45\xa3" + "\xa7\x72\x49\xe3\x0d\xc8\xda\xa9" + "\xdd\xb8\xf6\x74\x54\xd0\x43\xb0" + "\x1a\x7b\x13\x11\x9e\x31\x1c\x02" + "\x3f\xc0\x5c\xed\xce\x54\xa7\x00" + "\xd4\x5a\xea\xcb\x94\xc7\xa2\x0a" + "\xb6\x15\xc0\x70\xf4\x67\x3e\x09" +
- "\x86\x9b\x20\xb1\xfd\xef\x03\x02" + "\xbf\x6c\x9d\xb1\xed\x63\xf0\x21" + "\x5b\x27\x0f\x98\x76\x34\xf5\x59" + "\x80\x5e\xac\xb7\xd7\x56\x24\x20" + "\xc9\xed\x00\x49\x5f\xc0\xa8\xe5" + "\x86\x1e\xf0\x70\xb4\x8e\xc0\x04" + "\xce\x98\xcd\x1d\x24\xc2\x4a\xf7" + "\xdb\x30\xe8\xe2\x0c\xcc\x77\x7e" +
- "\x6b\x3f\x7e\xc9\xe9\xfe\xcd\x72" + "\x61\x74\xda\xb6\xb4\xca\x0b\xc1" + "\xb9\x06\x98\xb5\xfc\xd2\x02\x3b" + "\x47\x6f\xde\xa1\x89\x5e\x18\x85" + "\xd4\xc4\xb6\x0e\x1f\x93\xe6\x39" + "\x04\x5b\xfa\xd4\xbd\x40\x44\x4d" + "\xb8\x7e\xbe\x34\x6e\x78\x18\x54" + "\xbc\x59\x72\x9d\x21\xe5\x80\x63" +
- "\xde\x7e\x74\xa9\x34\x72\xe3\x74" + "\x13\x10\x1b\x36\xb1\xfb\xc9\x4f" + "\xef\x57\xf3\x3c\x73\x33\xb5\xe7" + "\x93\x41\x1c\x99\x2c\xdd\xa2\x6a" + "\x7a\x91\x70\xa7\xd2\xe4\x87\x78" + "\xcb\x24\x0d\xc2\xb4\x09\x18\xdd" + "\x3e\x2d\x9c\x8e\xc3\xd7\x4c\x00" + "\xbe\x0a\x97\xa9\xab\x5b\x7c\xc7" +
- "\x10\xd7\x98\xd5\x51\x03\xac\x20" + "\xa4\x4d\x3a\xcb\x66\x41\x2c\x27" + "\x1f\xde\x71\xca\x1a\xfe\x82\xdb" + "\x0f\x4b\xf5\xd8\xf2\x79\x6e\x74" + "\x9b\x3e\x57\x4b\x36\xc7\x7f\x6e" + "\x40\x50\x4b\xfd\x46\x3f\xd0\x75" + "\x7b\xd8\x98\x0b\x6d\xc3\x1c\x5c" + "\xa1\x2d\x47\x1f\xf1\xa3\x3b\x51" +
- "\x7f\x23\xaf\xc3\xaa\x7e\x92\x52" + "\x67\x87\x39\xd7\x65\x60\xa0\xfa" + "\x0b\xce\xc6\x97\xb4\x72\x2e\x04" + "\x61\x23\x9f\x0a\xc4\x0c\xed\xda" + "\x4a\xbb\xc1\x2f\x1c\xe1\xc2\xdd" + "\xf8\x9e\x1a\x0c\x77\xa5\x1d\x63" + "\xbf\x72\x02\x68\x44\xfe\x4c\x8a" + "\xc3\x5c\xfb\x62\x72\x9f\x6b\xc7" +
- "\xdd\x77\xb1\xab\x26\xaf\xd0\x79" + "\x64\xd5\x91\x78\x68\xb5\x2a\xf8" + "\x73\x21\x23\x72\xa9\x68\x67\x2b" + "\x19\x66\x1f\x8c\xb0\x3b\xbb\xef" + "\x58\x83\xd1\xa6\xdb\x11\x9c\xb2" + "\x3a\x6d\x91\xb0\x97\x27\x9e\x51" + "\x90\xe2\x88\x91\xf0\x18\xdc\xd4" + "\x7f\xca\xb0\x98\xe3\x86\x8e\x64" +
- "\xe3\xaa\xb3\x38\x45\x81\x8f\x24" + "\x34\x43\x20\xbc\x64\x58\x34\xb5" + "\x24\x75\x12\x1d\xbc\xb5\xd6\x66" + "\xd3\x72\xf5\x14\x0d\x08\x12\xe3" + "\xeb\xaf\xab\x16\xa7\x15\xed\x13" + "\xbe\x67\xa9\xdb\x27\xce\x18\x6f" + "\x2d\x55\x08\xef\x26\xe8\xc9\x96" + "\xe0\x63\x2b\xbe\x06\x1b\x19\x2c" +
- "\xb5\x38\x3c\x98\x45\x31\x9d\x85" + "\x8b\xbc\x7a\x63\x6c\x17\x4f\xb1" + "\xe6\x7b\xff\xca\x9d\xfb\x93\x27" + "\x5a\x6a\xa6\x35\x5f\xa5\xe5\xeb" + "\x59\xdc\x87\x9f\xcd\x1d\xec\x7c" + "\x60\xf5\xdb\xfb\xd3\x5c\x59\x7c" + "\x57\x32\xeb\x26\x22\x3b\x54\x5b" + "\xfd\x35\xc9\xc4\x46\x06\x08\x69" +
-
- "\x96\x16\x53\x1d\x38\x52\x34\xb9" + "\x69\xde\xcd\x88\x00\x1c\x20\x57" + "\xc7\xaf\x86\x9a\x51\x22\xe9\xdd" + "\xa8\xce\x35\xbd\x95\x38\x04\xe3" + "\x0d\x97\x55\x85\xe1\xc1\x08\x76" + "\x5e\x93\x35\x25\xa9\xdf\x67\x82" + "\x8b\xa3\x2e\x32\x57\x0a\xc6\xd4" + "\xb5\xf8\x4e\x80\x77\x79\xbf\xe0" +
- "\xb5\xdb\x94\xc0\x68\xea\x33\x62" + "\x10\xd4\x68\xd9\x2e\x06\x7d\xb7" + "\x2d\x00\xb3\x58\xbc\x9b\x71\x3e" + "\x58\x9d\xc4\x3d\x3d\xdd\xe7\x68" + "\x58\x5e\x3a\x01\x40\x57\x82\x8d" + "\x1b\x3c\x9e\x3c\x47\x17\x31\x21" + "\xab\xb6\x99\x7c\xa7\xa2\xb0\x0c" + "\xf2\x88\xf8\xc2\xb3\xa3\x48\x5c" +
- "\xca\xd4\x27\x29\xe1\x4b\x5c\x4c" + "\x8e\x84\x8f\x51\x16\x3f\xf2\xb0" + "\xcb\x7b\x75\x0c\x22\x89\xf7\x84" + "\x96\xeb\x5d\x32\xbb\x1c\xbd\x35" + "\x0a\xe1\x0d\x7d\xfb\x86\xb1\xbd" + "\x85\x96\x2c\xb2\xe3\x50\x73\xd0" + "\x41\xc6\x45\xef\x3e\x39\x95\x3f" + "\x44\x6d\x7b\xd0\xf1\x0f\x87\xb8" +
- "\xf3\x24\x17\x99\x91\x3e\x91\xc7" + "\x86\xd6\xcb\x39\x9c\x79\xda\x5e" + "\x1e\xfc\xd4\x63\xc7\x95\xb5\xdd" + "\x54\xed\x4f\xac\x0b\xb8\x63\x6b" + "\x16\xb5\x5f\x7e\x69\xfc\xa0\x6e" + "\x64\xc9\xf1\xd0\xba\x08\x77\x73" + "\xa5\x2c\xa9\x11\x5f\x74\x28\x96" + "\x7a\x96\x86\x9a\x58\x79\xf3\x61" +
- "\x9f\x65\xa2\x47\x65\x0a\xcf\x64" + "\xcb\x0b\x38\x33\x30\xf4\x18\x12" + "\x74\x8a\xd9\x0f\xe4\xe4\x1d\xfc" + "\xb8\xed\x9e\xf0\x8f\xec\xc4\xae" + "\x83\x60\xc5\x95\xe1\xb5\x6d\xde" + "\xa1\x16\xdc\x07\x56\xb0\x07\x33" + "\x97\x70\xd4\xc0\x86\xc1\x82\x14" + "\x66\x3a\x4c\x51\xac\x19\x83\xa0" +
- "\xb3\xe6\x79\x09\x61\xfd\x20\x53" + "\x23\x07\xd4\x93\xe5\xd3\x0b\x1d" + "\xcc\xba\x80\xaa\xfc\x06\xc0\x0a" + "\x15\x25\x00\xd2\x0e\xc6\xd9\xb1" + "\x92\x0b\x78\xaf\xd0\x7e\x0e\x61" + "\x31\xce\xa9\x80\x6e\x44\xbf\xf5" + "\x4b\xb5\x20\x3c\x1d\x01\x1c\x44" + "\xc3\x96\x15\x19\xa1\x6d\xf7\x77" +
- "\xb4\x94\x40\x4d\x2b\x5b\x2e\x97" + "\x5f\xde\x96\x5e\x4f\x95\x49\x4b" + "\x59\x0d\x87\x4f\x0a\xe4\xa8\x6c" + "\xef\x8d\xa6\x45\x6f\x88\xe2\x9e" + "\x13\x9a\x43\xc4\xec\x60\x02\xae" + "\x1f\xb7\xcf\xb4\x3e\xcd\xae\x45" + "\x20\x76\x32\x4e\xb6\xd9\xc5\x50" + "\xf3\x2c\x18\x86\xdb\xda\x0a\x47" +
- "\x72\x50\x66\xaa\x2c\x9b\xf3\x9a" + "\xef\x24\xd3\xef\xa4\x2f\x32\x78" + "\x31\xbd\x27\xc3\x94\x33\x15\x3d" + "\xb0\xda\x29\x31\x71\xf2\xd5\x81" + "\xf5\x27\x80\xf4\x42\x0c\x2e\xc7" + "\x17\xe7\x36\x85\xbc\xcd\x40\xaa" + "\x0f\x9d\x36\x2d\x7a\x65\x5a\xf4" + "\xe6\x74\x7f\xea\xc4\xbf\x3b\xb0" +
- "\xf0\x69\x7c\xf3\x89\x07\xb7\x4a" + "\x2d\x80\xc5\x01\x78\xd8\x26\x32" + "\x97\xf4\x0d\x36\x4c\x42\xe7\x4f" + "\x50\x0d\x89\x5f\xe5\xd4\xae\x9e" + "\xc6\x29\x37\xdd\x5c\x99\x8e\x20" + "\xf3\xea\x0d\xd0\x5c\xbd\x43\xf7" + "\x7d\x84\x61\xf1\x10\x13\x5a\xfe" + "\x25\x3f\x1a\x94\xa2\x75\xe7\x34" +
- "\xea\x42\x6a\x9b\x42\xd5\x04\x7a" + "\xb9\x41\xaf\x3d\x85\x7e\x59\xfa" + "\x89\x0b\x6b\x72\x27\xec\x58\x4c" + "\xde\x43\x0d\x03\x6a\xb1\x8e\xed" + "\x57\xcf\x9d\xec\xe1\xe5\xe1\x65" + "\x81\xff\x7c\x69\xc1\x70\xa7\xb7" + "\x22\x2b\x6e\x9f\x8f\x91\x6d\x1e" + "\xb7\x82\x4e\xc6\x9a\x7a\x27\x7c" +
- "\xcf\x35\x1f\x7b\xc8\x69\xc8\xe5" + "\x37\xd2\xd1\x55\x37\x69\xfa\x29" + "\x44\x9c\x57\xde\xee\x74\xc5\x05" + "\x0c\x59\x6d\x33\x2b\x91\xbb\x45" + "\xeb\x4d\x7d\x77\x85\x2d\x17\x5d" + "\x67\x65\x6c\x7b\xa9\xcc\x37\x1a" + "\x8a\x3a\x37\x25\x3a\x43\xa1\x1c" + "\x3a\x35\x77\x1c\xa8\x94\x3c\xd2" +
- "\xed\x8d\x73\x0d\x18\xc4\xa8\x46" + "\x29\x57\xde\xe0\xb0\x5b\x1a\x6f" + "\x75\x16\xa8\x8b\xb9\x30\x02\xf1" + "\xd4\x33\x2b\x11\x0c\xf3\xc6\x32" + "\x62\xfb\xff\xd8\x9d\x12\x59\x75" + "\x05\xbf\x59\xb4\x47\x1b\x28\x6a" + "\x76\x67\x3b\xfa\x3a\xbd\xc1\x77" + "\x3a\x97\x29\x78\x80\xb3\x09\x07" +
- "\x61\xa3\x35\xc9\x7c\x22\x89\x79" + "\x7e\x0a\x9a\xe3\xaa\xf8\x17\xfd" + "\xba\x63\x91\x26\x86\x5e\x5c\x2e" + "\xf4\xea\x63\xc6\x78\x8e\xc9\x07" + "\x6e\xa3\x2e\x42\x9a\x20\xe8\x64" + "\x82\x08\x6a\x4c\x91\xb3\xe8\x1b" + "\x5e\xa5\x4f\xec\x03\x45\xac\x4b" + "\xdf\x68\x78\xad\xca\xa7\xee\xba" +
- "\x47\xcb\x36\xda\xc1\xe0\x75\x08" + "\xf0\x10\x02\x1e\xcb\xb7\xf5\xfd" + "\xc8\x87\x37\x3a\x4d\x7e\x0c\x7e" + "\x1f\x74\x1c\x2b\x26\xf5\x43\xf0" + "\x2d\xd7\x74\x6d\x00\x1b\xdf\x76" + "\xa9\x5b\xb4\x38\x73\xdf\x14\x05" + "\x7a\x79\x6b\x0a\x3e\x7c\xcf\xae" + "\x39\xac\xea\xdd\x85\xb2\x30\x5e" +
- "\xdb\xe3\x69\xac\x9c\x33\x69\xff" + "\xbd\xd6\xe9\x59\x3c\xc8\xec\x74" + "\x82\x84\x0a\x82\x37\x7b\x23\x67" + "\x23\xfa\x2d\x07\x35\x30\x3a\x94" + "\xb8\xbd\x48\x8f\xd2\x10\x42\x6e" + "\xf4\xc7\xec\x2e\x16\x75\x51\x88" + "\x7f\x18\x2a\x63\xf4\xc5\x05\x0b" + "\x4c\x1d\x7d\xd9\x5e\xfb\xfd\xca" +
- "\x05\x65\x32\xa3\x32\xb2\x26\x8c" + "\xbf\x41\x1d\xee\x72\x92\xd6\x38" + "\xfa\x2a\xe3\xff\x3e\x45\x59\x04" + "\x87\xea\xb3\x7c\xad\x43\x81\xce" + "\x66\xb6\x6a\x7e\xfa\xc1\x2e\x93" + "\x64\x62\x28\x22\x30\xd2\xd2\x6c" + "\xed\xf8\x36\x67\xfe\x46\x9a\x45" + "\xbb\x85\xca\x9e\x00\x0d\xbf\x50" +
- "\xb4\xeb\xa2\x3d\xba\x6b\xc1\x06" + "\x3e\x7c\x55\x32\xbb\x21\x5b\xf3" + "\x11\x67\x07\x30\x12\x23\xb1\x95" + "\xf0\x11\x76\x1b\x76\xa0\x3a\x87" + "\x61\x6d\x3a\xea\x26\x90\xf6\x31" + "\x4c\xbe\xa6\x42\x6b\xb8\xc9\x7a" + "\x02\x28\x6c\x4b\xc7\xd7\xb5\xd3" + "\xe0\x1d\x28\xab\xac\x94\x48\xcd" +
- "\xa5\x38\x52\x60\x7d\x8f\xc7\x15" + "\xab\x96\x84\x44\x42\x78\xd8\xe9" + "\xc1\xac\x10\xd2\xd0\x75\xcf\xcf" + "\xe2\x14\x8c\x5c\x29\xf2\x48\x29" + "\xcb\xf0\xda\xe8\x6d\xd7\x1f\xe8" + "\x00\xe8\x3b\xa0\xe4\x11\x2d\xd0" + "\x0c\xd3\x78\x87\x51\xf3\x4d\x0c" + "\xcb\x39\x51\x96\x96\xbc\x82\x34" +
- "\x68\x1d\x81\x49\x01\xd7\xa0\xef" + "\x4e\xa0\xa1\x1e\xe5\xc8\xf6\xe4" + "\x40\x76\x23\x82\xfd\xe1\x90\x59" + "\x96\xdb\x80\x1d\xf9\x25\xa2\xef" + "\xda\xcc\x96\x3a\x95\x1c\x43\x17" + "\x92\xa1\x3f\xfc\xc1\xaa\x1b\x46" + "\xb4\x84\xc1\xbb\x07\xf4\xe2\x3b" + "\x9c\xd3\x05\x0d\x1d\xde\x76\xd7" +
- "\xec\x21\x7a\x87\x52\x58\x82\x0b" + "\x94\x7a\x53\x0f\xa7\x14\x04\x30" + "\xa2\xa6\xa9\x21\x40\xba\x1c\x3f" + "\x00\x3c\x94\x76\xee\x4e\x82\x50" + "\x5d\xba\x3c\xf8\xec\xfc\xdb\xa0" + "\xc0\xf3\xb4\x93\x48\x81\x53\xf9" + "\xd7\x4d\xf2\x48\x62\x41\x74\x61" + "\xdd\x09\xfb\xe4\x4d\xd6\x22\x53" +
- "\x05\xa7\x73\xdc\xd2\x9e\xb0\xf1" + "\x6e\x1a\xa1\x01\xc8\x00\x2b\x14" + "\xc9\x32\xa1\x98\xb0\x84\x64\x72" + "\x7a\x56\xe1\x26\x63\xef\xb5\xf3" + "\x03\xfc\x4b\x57\xd0\xd2\xbe\x43" + "\x2f\x72\x8f\x76\x38\x1e\x79\x74" + "\xd8\x7e\xe9\x4c\xb3\x9f\x18\x7a" + "\x43\x5f\x8a\x16\x96\x2c\x9b\x2b" +
- "\xbc\x8b\x44\x8a\x27\xcf\xb6\x56" + "\xda\x51\x52\xc8\xdf\x98\xa8\x0c" + "\x24\x9b\xe7\x36\xd8\xca\x82\x90" + "\xa7\x51\x8e\x1a\xd3\x9e\x7b\x2e" + "\x02\xc8\xe1\x43\x8a\x31\x7d\xdc" + "\x9d\x68\xf8\xcb\x23\xe5\x50\x47" + "\x1a\x1b\x07\xf0\x72\xa0\x87\x98" + "\xc1\xfd\x4b\x81\x87\x0f\x09\x52" +
- "\xb9\x6e\x73\x8d\x2e\x85\x21\x48" + "\x6b\x1e\x4c\x54\xd3\x28\xa9\x29" + "\x86\x05\x80\x77\xae\x11\xa4\x1a" + "\x93\x57\x0a\x1b\x7b\x06\x4d\xe9" + "\xad\x46\x5e\xa6\x4b\x8b\x9d\xb5" + "\x04\x18\x94\xcd\x87\xba\x62\x3c" + "\x1b\xe6\x20\x99\x78\x4b\xb5\xfd" + "\xac\x1a\x18\x0a\x84\xf2\x23\xe9" +
- "\xf3\x25\x93\x3d\x84\x73\x44\x57" + "\x84\xcb\x71\xf3\xd0\xf2\xbe\xa9" + "\xc5\x36\x1e\xa6\x8b\x18\xd2\x77" + "\x72\xdf\x02\xc6\xd7\xa7\xd6\xbb" + "\x0b\xbc\x61\x8f\x02\xa9\x3a\xba" + "\xa1\xb6\xd0\x6e\xed\x85\x90\xf4" + "\x98\x82\x6e\xae\xd6\x25\xc6\x8b" + "\x1d\xc0\xe9\xa2\x1d\x0b\x2b\x83" +
- "\xa0\xca\xd1\x70\x82\x5c\xb4\xc2" + "\x57\xb5\x4a\x72\xd0\x41\xce\x44" + "\xfd\x71\x82\x13\xac\x4b\x98\x57" + "\xc8\x08\x36\xcb\x34\xc9\xe0\x67" + "\x03\xf7\x55\x54\x45\xfa\x88\xc8" + "\xb0\x02\x7b\x72\xb4\xb8\xc5\xe9" + "\xa4\x30\x71\x7c\xf0\xf0\x3e\xdc" + "\x0c\x27\x09\x4b\xa3\xbe\xe4\xd9" +
- "\x6e\xbc\x96\x61\x19\xf2\xeb\x5b" + "\xfd\x7e\x09\xef\x6b\x73\x66\x0e" + "\x3a\x29\x87\xea\xb8\xf3\x28\x11" + "\xde\xfc\xdd\x6a\x05\xe4\x98\x29" + "\x61\xc9\x16\x5d\xb8\x31\xcc\x55" + "\x56\xf0\x18\x24\xe1\x34\xa4\x87" + "\x19\xe8\x9f\xdc\xcc\xaa\x94\x2e" + "\xc6\x90\x64\xa5\xc1\x86\xa4\x94" +
- "\xb3\x2b\x8d\xcb\xd4\x83\x4d\x8a" + "\xfd\xb1\xd2\xff\xa8\x6a\x79\xea" + "\xf6\x79\xca\x04\x51\xab\x75\x65" + "\xcf\x86\x6b\xc4\x36\xd5\xf0\xf4" + "\x58\x6b\x0e\x67\xd9\xc5\x1e\x46" + "\x08\xd1\xae\x0e\xf8\x53\x50\x70" + "\xf7\x16\xdd\x14\xce\x5b\xf4\xda" + "\x65\xcf\xb2\xc4\x49\x2d\x6f\x40" +
- "\xd1\xce\xf0\xf1\x47\xc4\x37\xa3" + "\x2b\xdd\x92\x94\x93\xc7\x0c\x80" + "\xfa\x8e\xa0\xbe\x1d\x15\x93\x4b" + "\x1e\x74\x0a\xde\xf8\xf3\x0c\x82" + "\x13\x7d\x0f\x1c\xdc\x82\x19\xff" + "\xca\xe6\xdd\x84\x60\x19\x92\xef" + "\xe3\x6e\xf9\x45\x72\xd9\xd7\x1a" + "\xc7\xa0\xde\x29\xbe\x8d\x9c\x31" +
- "\xf8\xf5\x2e\xe8\x80\xdc\x1c\x6d" + "\xb3\x7f\x1c\x2f\xf0\xf9\x5d\x09" + "\x88\xd8\xcf\xa3\xb9\x34\x7f\xc8" + "\xe1\x08\x02\x34\x95\x70\xd7\xd5" + "\xcb\x51\x88\x91\xe4\xec\x1a\x4a" + "\x42\x71\x2b\x60\xc1\xf5\xb1\xd7" + "\x82\x4f\x52\xc6\x13\x98\xd3\xf0" + "\xb5\x1d\xb0\x6b\xae\x6e\xd9\xf6" +
- "\xc8\x9e\x25\xde\x5b\x38\xf2\x1f" + "\x0d\x7b\xf6\x30\x6a\x83\xb0\xf6" + "\xff\x1c\x66\x06\xb0\x65\xcc\x04" + "\x5c\x0f\x23\xd4\x58\x63\x7e\x46" + "\xd3\xd3\xbe\x2d\x80\x8c\x46\xce" + "\xa6\x0d\x92\xf1\x62\x42\x98\x7b" + "\x9f\x47\x37\x15\x42\x57\xd2\x34" + "\xe1\x8d\xbb\x87\x8c\xa8\x8a\x5c" +
- "\x6a\xa5\xaf\x54\xa1\x68\xf7\x32" + "\xe5\x84\xf1\xfa\xa3\xec\x1e\xa5" + "\x68\x74\x8c\x61\x44\xcb\xce\x20" + "\xc0\x2c\x86\x87\x5f\xd1\x34\x34" + "\xf6\x5d\xf5\xae\x11\x38\x3c\x71" + "\xf0\xf8\xe3\x81\x49\xc0\xd7\x2c" + "\xbe\x99\x2f\xff\x39\xd4\x68\xee" + "\xa6\xa6\x5d\x2b\xe7\x4e\xb6\x79" +
- "\x9b\xb9\x82\x7b\x71\x38\xea\xd3" + "\x24\xb6\x0e\x47\x4d\x2d\x92\x75" + "\x66\xd4\x95\x3b\x54\xec\x66\x8f" + "\x46\xe3\xe1\xbe\xcc\x73\xe6\x66" + "\x9a\xb8\xf2\xb5\xc4\x67\xfe\x6a" + "\xd3\x5c\x0e\x29\xe6\xc1\xe9\x3d" + "\xda\x2a\x0a\x31\xb6\x8b\x27\x8c" + "\x3b\x32\xdb\x0b\x84\xa3\x0f\x42" +
-
- "\x9b\xc4\x24\x64\x79\x96\x6f\x64" + "\xc9\x41\xc2\x67\xe8\xdf\x88\xf8" + "\x49\x8b\xf6\x24\x93\x4b\x2d\xe1" + "\x20\xdf\x71\xa5\xd8\x62\x6b\x9a" + "\xcb\x83\x94\x17\x6d\xb2\xb4\x81" + "\xe2\xfa\x11\x95\x32\x96\x6f\x66" + "\x1f\xa5\x3a\xd5\xe4\xb3\x81\xd2" + "\x16\xbd\x3d\x7f\x65\xa7\x96\x7f" +
- "\x2b\xf6\x1a\x05\x7c\xd3\x53\x85" + "\x96\x44\xf9\x0b\xeb\x98\xa9\xe9" + "\xa1\x9a\xd5\xb0\x9f\x4f\x84\xe0" + "\x13\xb8\xaf\xe6\x58\xd5\x3f\x98" + "\x04\x98\xd6\x65\xca\xc0\x70\x96" + "\x2d\xff\xa5\x6e\xde\x22\x2b\x73" + "\x3b\x62\xd8\x5f\xa9\x0b\x64\xd7" + "\x82\x17\x35\xa6\x63\x91\x61\x9f" +
- "\x4f\xdd\xef\xbd\xe0\xb4\x67\xf1" + "\x01\xe4\x66\xf3\x65\x84\x95\x69" + "\xc0\xbe\x3b\xa7\xab\x68\xa3\x5a" + "\x21\x0c\x24\x7b\x09\x87\x14\x12" + "\x06\x90\x96\x18\x33\x32\x8c\x37" + "\xd1\x53\xfe\xe1\xce\x73\x4d\xcb" + "\x61\x43\x0c\x13\x0e\xa8\x50\x5f" + "\x2b\x21\xf5\x7e\x51\x59\x7f\xd6" +
- "\xc0\x38\xad\x8c\x08\x81\x2f\x33" + "\xe2\x8a\xd6\x6b\x90\x7e\x1b\x47" + "\xa3\x27\x8e\x0d\xb2\x3f\xac\x56" + "\x0d\x4b\x6b\x13\xdb\x60\x46\xb5" + "\xe4\x8d\xfd\xa6\x11\x1e\x3a\x12" + "\xef\x99\x77\xa3\xea\xff\xdb\x44" + "\x7c\xc1\x6a\xce\x77\xb9\x40\x45" + "\xef\xac\x60\xaf\xa8\x73\x51\x49" +
- "\xb0\xea\x73\x45\x43\x37\x44\xeb" + "\x31\x60\xac\xd1\xfb\x0d\x57\x11" + "\xfd\x9a\xdd\x44\x5b\xb4\xd9\xf7" + "\x31\x72\x06\x22\xdd\x6a\x06\xb8" + "\xb4\xf0\xa3\xf8\xd8\x2a\xf9\x15" + "\xa2\xe2\xac\xe0\x99\x48\x0e\x9e" + "\x80\x8b\xb3\xfa\xad\x0a\xcd\xbd" + "\x52\x00\x02\x17\xe9\x6a\x50\x46" +
- "\x9d\x39\xca\x8f\xf7\x69\x9a\x42" + "\x63\xbb\x07\x02\xd2\x27\x9e\xfe" + "\x82\xf5\x88\x87\xd6\x5e\x65\xec" + "\x6e\x5f\xb7\xad\x48\xd7\x26\xa4" + "\x6d\xc6\x81\xca\x02\x5c\x69\x18" + "\x25\xd4\x31\xa5\x27\x8d\xfb\x84" + "\xba\x48\xff\xde\x56\x89\x3a\x3a" + "\x47\x22\x6d\x76\x56\x0d\x1d\xaf" +
- "\x5c\x4b\x2c\x35\x65\x95\x05\x5a" + "\xe2\xc3\x0b\x59\x31\x15\x26\x49" + "\x5f\x9f\x6f\xf6\x21\x75\x9f\x80" + "\x9b\x4a\x0a\xc7\xbf\xf6\xae\x2b" + "\x61\x35\xed\x09\x65\xfa\xe6\xe7" + "\x0c\x23\x4b\x98\x33\x02\x37\x11" + "\x69\xdc\x4c\xd0\x9b\x65\x51\x21" + "\x16\xd4\x07\xf0\x63\x3c\xb8\xbd" +
- "\x82\x2a\x1c\x39\x4d\x28\xbb\x9e" + "\xe8\x08\x83\x15\x63\x48\xdd\xbc" + "\xca\xed\xf1\x83\xec\x16\x6f\x00" + "\xc8\xc6\x5d\x69\x37\x2c\x3e\xa1" + "\x87\x7a\x05\x4a\xf0\x56\xb7\x2a" + "\x98\x8f\xb4\xa6\x00\x55\x76\xa8" + "\x44\x1c\x65\x68\xce\xfa\x52\x42" + "\x02\x5e\x76\xe1\x0b\x54\x2b\xa5" +
- "\xf0\x7f\xa3\x5c\xa8\xa1\x35\xcb" + "\x8f\x1c\x2f\xcd\x1c\x4f\xa0\xe1" + "\x12\x61\xa2\x15\xce\x16\x88\x23" + "\x7e\x17\x5b\x09\x11\xa1\x06\xe2" + "\x49\x41\x42\x8a\x04\xb6\x10\x3c" + "\xfb\x2c\x75\x74\x67\xf5\xa3\xc6" + "\xb8\xdb\xf1\x47\x7a\xa3\x16\xbf" + "\xfb\x3d\x1a\xd3\x9a\x2f\x37\x7c" +
- "\x2a\x4d\x0b\xc2\xb5\x05\x2d\x12" + "\x67\x2a\x66\x0c\xf5\x9c\x65\xff" + "\xe9\xc9\xff\xe8\x28\xc1\x57\xed" + "\x83\x76\x98\x9e\x85\x15\xbb\x0f" + "\x2b\x9a\x31\x47\xf2\x0d\xd7\xad" + "\x70\xe4\x4b\x37\xba\xba\x98\x4b" + "\x07\xb3\xa7\x56\x73\x74\x3d\xf0" + "\x30\xbf\xfe\x3e\x6e\x69\x2e\x34" +
- "\x37\xc5\x4a\x86\xf7\x48\x4b\xf8" + "\x3d\x0d\x94\xa6\x09\x34\x71\x04" + "\xae\xc7\x74\x61\x2d\xb2\x4d\x01" + "\x34\x30\x21\x8c\x43\x1c\x3a\xc7" + "\xec\x93\xdd\xff\xa5\x4e\xac\x18" + "\x3e\x78\x02\x61\x57\xc7\x4f\x72" + "\x3f\xe8\xc3\x91\xcc\x3f\xe1\x9f" + "\xf5\x0b\x8f\xf0\xc8\xc2\xa8\x92" +
- "\xde\xf6\x67\x8f\xfd\x22\x2e\x7f" + "\x77\x31\x69\xd8\x33\x88\x01\xab" + "\x95\xca\x3e\x86\xb6\x1d\x6d\x26" + "\x2b\xef\xb5\x31\x2b\x73\xb7\x6b" + "\xce\x80\x5f\x91\xc6\x27\xa9\x4f" + "\xd8\xef\x90\x5f\xd2\xd6\xa1\x6f" + "\xad\x48\x6b\x45\xe8\x5d\xd7\x7b" + "\x29\x64\x5b\x84\x7a\x50\xcb\xd2" +
- "\xec\xd7\x55\xe2\x2a\xf8\x2c\xa7" + "\x04\xe2\x60\xa4\x23\x5c\x02\x52" + "\x44\x0a\x5b\x7d\x2d\x54\xae\x10" + "\xda\xae\x05\x93\x10\x43\x51\xa8" + "\xe8\xbf\x4b\xa1\xf5\x15\x83\x95" + "\xfe\x65\x53\x38\x26\x18\x36\x3f" + "\x40\x50\xd9\x66\x6b\xa3\xb3\xc2" + "\xa2\xed\xf4\x7c\x34\xb3\xc7\x12" +
- "\x9d\x11\x44\xe7\xd1\xb4\x45\xa5" + "\xe7\x71\x9a\x82\x69\xb1\x93\x4c" + "\xbf\xfc\x17\x61\x8c\x90\xbb\x2d" + "\x85\x3d\x5a\xb3\x20\x73\xc9\x4d" + "\x05\x81\xf8\x6b\x85\x4f\xc0\x94" + "\x1f\xbc\x51\x1b\xce\x1b\x2e\x45" + "\xf3\x3a\x01\xb3\x50\xff\x41\x0c" + "\x24\x7e\x4d\x22\x45\xf4\x7a\xf0" +
- "\x6a\x4f\xd2\xa3\x7c\xe5\xb9\xbd" + "\x63\xa7\x45\xf3\xd7\x46\x82\x8a" + "\x5f\xbb\xcf\x98\x6d\x2a\xbd\x73" + "\xdb\x04\xed\x86\x5e\xe8\xd8\x1d" + "\x0b\x42\x1f\xc0\x42\xda\xf2\x76" + "\xc7\x7b\x40\x64\x73\x54\xf0\x7e" + "\xf5\x48\xf5\xaf\x7f\xba\x98\x7e" + "\x4a\xb6\x30\xfd\xee\xfb\x7a\x6b" +
- "\xbb\xd2\xa0\x16\xc5\x2f\x92\x4f" + "\x99\x34\x62\x1a\x6c\xc1\x5c\x0d" + "\x8b\x2c\xc6\x57\x3a\xcf\x41\x92" + "\x7f\x66\x1b\xfd\x61\x69\x5e\x2f" + "\x97\x17\xa0\xf5\x0b\xc7\x15\x5c" + "\x92\x61\x95\x60\x4d\xb4\x20\x3d" + "\x52\xdb\x1f\x07\x37\x1b\x91\x04" + "\x7b\x0f\x6f\x8d\x16\xf9\x48\xf6" +
- "\xf8\x72\x25\xeb\xea\x39\x76\x06" + "\xce\x53\x08\xd7\x32\xf6\xce\xb0" + "\x04\x90\x98\xe9\x31\x1f\x7f\xd8" + "\xc0\x82\x65\xa2\x36\x72\xaa\x94" + "\x56\xc6\xc2\xb0\xe5\xb8\x11\x42" + "\x4e\x41\x57\xa2\x9b\xa7\xaa\x05" + "\xb0\x9a\xf0\xe0\x41\xf8\x72\x06" + "\x65\x1c\xc8\x3e\xbf\xf9\xc5\xa3" +
- "\xfa\xf0\x03\xe0\x9a\x37\xf6\x4c" + "\xb0\xc8\x75\x1e\x87\xe0\x17\x79" + "\x9f\x3c\x38\xa1\xfc\x59\xc0\x1d" + "\x67\x09\x48\x64\xa6\x4e\x61\xa8" + "\xd1\x5d\x62\x79\x01\x0d\x4d\xc3" + "\x88\xe7\x00\x42\xe1\xa1\x47\x7d" + "\x9d\xa5\x54\xa7\x1e\x9d\xf9\xae" + "\x78\x41\xb1\x49\x00\x2d\x81\x1c" +
- "\xa7\xb3\x77\x08\xb6\x1b\xa1\xa4" + "\xa9\x21\xd5\x2c\xa6\x11\x4d\x24" + "\x2c\xc6\xf5\xbf\xb7\x19\x4b\x46" + "\x7c\x65\x76\x90\xa7\xeb\xf3\x27" + "\xa9\x81\x75\x0c\x97\xbf\x3a\x48" + "\xf3\x22\x0b\xae\xe0\x08\xf1\x2e" + "\xd5\xbc\x64\x50\x66\xf3\x03\xd6" + "\x5e\x02\xf5\x5b\xa7\x75\x48\xcf" +
- "\x2c\xd2\xd5\xd0\xe5\x02\x93\xab" + "\x30\x40\x12\x30\xb0\xe6\xa7\xd0" + "\xf4\xa1\x0a\x4f\x7b\xc5\x62\xe2" + "\x2e\x20\xba\x0b\xa5\x58\x7a\x49" + "\xac\xcc\xcf\xe6\x1e\xd2\x9f\x10" + "\xec\x27\x19\x8a\xe6\xcc\x96\xb5" + "\x5a\xe8\x02\x3b\xe8\xf7\xb9\x48" + "\x34\x11\x59\x08\x3c\xf8\x7e\xbf" +
- "\x62\xc5\xed\x62\xb1\x91\x5e\xe0" + "\x85\xd1\xbc\x62\x72\xfe\xe1\xb5" + "\x19\x5b\x10\xb8\x08\x69\x52\x1d" + "\x22\xbb\x6b\x89\x7e\x44\x11\x0d" + "\xf0\x13\x22\x2c\x49\xaa\x7a\x64" + "\x4b\xc1\x2f\x2e\xc6\xf8\xc9\xf6" + "\xc6\x68\x41\xbc\x9a\x25\xca\x90" + "\x61\x34\x8e\xdd\x62\x27\xb9\x3b" +
- "\x9a\x18\x20\x5b\x94\xc0\x7f\x15" + "\xab\xc8\xf5\x0b\x2d\xc6\x72\x6e" + "\xb7\x50\x77\x35\xe1\x89\xf4\xf7" + "\xc5\x31\x7d\xf8\xb2\x1a\x51\x18" + "\xc5\x35\x5f\x00\x27\x78\x26\xa4" + "\x6d\xed\x80\x94\x54\xa0\x8c\xa2" + "\xb2\x7d\x24\x77\x7c\xde\xef\x20" + "\x60\x9d\x14\xa4\x39\x04\x16\x5e" +
- "\x70\xae\xde\xf3\x48\xb1\x10\x5c" + "\x33\xc4\xab\x6e\x53\x4b\x04\x02" + "\x8e\xf1\x63\xfe\x0c\x79\x82\x1e" + "\xf1\x5f\x69\xaa\x5a\xb6\x86\x28" + "\xed\xa4\x27\x46\x93\xdf\x4f\x99" + "\xb9\xb0\x2e\x87\xc0\xde\xb4\xe9" + "\x8f\xa2\xf7\x58\x8d\xec\x0b\x4c" + "\xfe\xc5\xf9\xea\xed\x4d\x0c\xc3" +
- "\xf7\x7c\x0b\xe6\xaf\xac\xc1\x6d" + "\x69\xd8\xa9\x84\x50\x0a\x86\x25" + "\xc4\x8a\xba\xe7\x09\x6f\xfc\x56" + "\x9e\xd2\x48\x61\xd0\x5b\x8c\x82" + "\x5f\xae\x55\xdc\x5e\x43\x6b\xac" + "\x11\x74\x11\xc0\x6c\xf5\x27\xa5" + "\x2c\x34\x24\xfd\x5e\x04\xd5\x94" + "\x0d\x7c\xb6\x70\x35\x0a\x4c\x2c" +
- "\xcd\x79\x55\xb6\x38\x35\xf6\x69" + "\xa1\x33\xf9\xad\x5c\x60\x70\xd0" + "\x6c\x9f\xbe\x83\x05\x87\x7e\x01" + "\xa1\xb8\x47\xb2\xaa\x2f\x44\xe9" + "\x68\x3d\x0d\x54\x9e\xff\xee\x54" + "\x19\xbe\xe3\xca\xab\xde\x3e\x1f" + "\x1b\x31\x35\x70\xb0\x28\xc5\x95" + "\xa7\xc0\xbc\x96\xb7\x3a\x5d\xb3" +
- "\xb5\x98\xd3\x5e\xfa\x3c\xca\x9b" + "\xd7\xdd\x53\x13\x65\xb4\x60\x6a" + "\xd1\x51\x1c\x1a\xbb\x17\x5c\x90" + "\x1b\xf9\x5c\x7f\x81\x04\xa3\x27" + "\x0a\xbf\xd6\x9e\xf3\x0c\x66\xc4" + "\x56\x1d\x9e\xf7\xb1\x3f\xb0\xb0" + "\x54\x13\x00\x36\xf1\x3b\xa1\xe3" + "\x2a\x2b\x2b\x1f\x54\x50\x72\x9a" +
- "\x6d\xe1\x06\x21\x05\x7d\x89\xb4" + "\x8c\x7f\xa0\x50\x9b\xdf\xbb\x85" + "\xd7\xff\x49\x6c\x3d\x2a\x63\x42" + "\xb8\x20\x07\x60\x7c\x5e\x88\xb7" + "\xac\x94\xb6\xde\xdc\x7f\xa4\x6f" + "\x79\xd1\xe0\x8a\xf5\x14\x46\x38" + "\xb3\x4a\x12\xbd\x29\xba\xfc\x78" + "\xea\x12\x8f\x74\x9e\x3d\x11\xbb" +
- "\x18\x30\xcd\xa7\x99\xef\x23\x3c" + "\x8f\xfd\xde\x83\x06\xc5\x3f\x2c" + "\x9b\x49\x88\x2b\xff\x45\x7a\xf9" + "\x6a\x7f\x6e\x34\x21\x32\xaa\xae" + "\x30\x27\xf3\x50\x84\x34\x47\xe7" + "\x41\xca\xd6\x0f\xbb\xb8\xc0\xc2" + "\x14\xc1\x17\xaf\x79\x20\x88\xa9" + "\x04\x72\xde\x1b\xa6\xf7\x35\x06" +
- "\xfe\x93\x84\xf3\xd0\x13\xb0\xc3" + "\x18\xf7\xba\x07\x96\xae\x2c\xa3" + "\xba\xb3\x95\x20\xc2\xa6\x1d\x37" + "\x9e\x90\x41\xb0\xbd\x0a\x1c\x03" + "\x60\x9e\x1a\x43\xbe\x6d\xcc\x11" + "\x6e\x8f\xf3\x5b\x76\x94\x91\x7e" + "\x33\x4a\x2a\x46\x76\xf0\x47\xbe" + "\x30\xb8\x41\x30\xdf\xc9\xb3\x33" +
- "\x85\xbd\x63\x7b\x4e\x4d\xd7\xa7" + "\xa6\x3d\xe2\x43\x55\xc6\x36\xea" + "\x29\x96\xa7\xe5\x7f\x7d\x7b\xcd" + "\x1d\xc0\xca\x13\x47\xf7\xb1\x1f" + "\xd3\xde\x28\x90\x45\xe1\x0f\xaa" + "\x97\x20\x57\x19\x3b\xca\x23\xb1" + "\x77\x86\x83\x74\x6d\x74\xa8\x21" + "\xc6\xcc\xab\x63\xcb\x7a\xfc\x1c" +
- "\x70\x3d\x05\xe5\x02\x33\x65\x02" + "\xc9\xbf\xc6\xb8\x5b\xe3\x33\x3c" + "\xe9\x1e\x02\x9a\x40\x4b\x2c\xa7" + "\xe4\x27\x65\x3f\x0d\x80\x1b\xe1" + "\xb5\x37\xdc\xb6\x4a\xd4\xc1\x8f" + "\x74\xe4\x80\xf5\xb5\x06\x86\x5d" + "\xfa\xb0\xb5\x87\x4a\x75\x25\xdf" + "\x5e\x2a\x69\xbb\xe8\x0c\xf5\xba" +
- "\x9a\x1d\xc6\xfa\xb8\xc8\x7c\x02" + "\x8a\xfe\xc6\xe3\x62\xe0\x25\x7d" + "\x03\xf5\xbf\xe5\xbf\x05\x88\xe0" + "\xf7\x32\xf6\x6f\x6c\x1e\x27\x13" + "\xa5\x76\x2f\x23\xc0\xa6\xdc\x55" + "\x26\xf4\x1e\x70\x2d\xc3\x57\x89" + "\x78\x51\x0a\xa1\xcb\x8b\x72\xee" + "\x73\x51\x2c\xb6\x11\x04\xa6\x5e" +
-
- "\x50\xbc\xd8\xb4\x2b\x46\xd5\x9a" + "\x70\x57\x19\xa9\x16\x0b\x1c\x18" + "\x68\x2a\x41\x78\x1c\xfe\xd4\xeb" + "\x8c\xf4\xdf\xc0\xbc\x41\x03\xae" + "\x66\xe8\x03\x70\xcf\x45\xbc\xb6" + "\x1b\xa4\x24\x8a\xea\x6d\x1a\xf1" + "\xc2\x24\x4c\xd0\x1a\x15\x07\x54" + "\x68\x7b\x5b\xda\x7d\xd2\xc9\x62" +
- "\xf6\x8b\x3b\x52\x2e\xb1\x50\x0a" + "\x1b\x0c\x91\x8f\x5b\xeb\x09\x80" + "\x88\x75\x16\x4a\x82\xaf\x35\xf5" + "\xbd\x2a\x2a\xfb\x9c\x5f\x83\x0f" + "\x62\xeb\xfc\x2a\x31\x29\x9b\xf5" + "\x3f\x38\x9d\x16\x2a\xdf\x97\xc7" + "\xb0\x02\xac\x66\xb0\x5f\x3f\xeb" + "\xca\xd0\xa2\xda\x6f\x4c\x9d\x02" +
- "\x42\xe5\x7c\x2b\x05\x26\x22\xb8" + "\xe1\xbd\x72\x74\x99\xce\xd4\xe6" + "\xda\xf4\xd2\x09\xbe\x6e\xe1\x53" + "\x2e\x2b\xb9\x53\x2e\xf4\x0f\x18" + "\xc6\xa1\x34\x2c\x02\xcc\x9b\xc5" + "\xc2\x46\x2c\x42\xf9\xd6\x03\x38" + "\xa2\xa8\x14\x5c\x4f\xf7\xaf\x18" + "\x28\x8b\xa0\x10\x80\xbf\xae\x55" +
- "\xbc\x43\xb3\xf5\x10\x20\xaf\x58" + "\xfe\x42\xf1\xf2\x0a\x40\x2e\x0f" + "\xdf\x4b\x5f\xa8\xde\xbf\x83\x34" + "\xa9\xea\xbf\x03\x93\xd0\xb1\xf0" + "\x03\x16\x08\xc7\x95\x1b\xa0\x2e" + "\x97\x10\xba\x3d\xc9\xe4\x43\xe9" + "\xa6\xf3\x38\xb4\xad\x92\xbe\x47" + "\x36\x66\xbf\xe5\x42\x77\xbb\x00" +
- "\x61\x2a\xdf\x86\xb4\x4f\x7a\x13" + "\xa2\xb4\xf7\xec\x07\x9c\xed\xa1" + "\xff\x42\xd0\x7b\xe2\x60\xe4\xb2" + "\xec\xf5\x62\x5f\xfa\xe2\xf5\xb7" + "\xb7\x23\x24\xcc\x6b\xec\xa6\x7a" + "\xa7\xee\x63\xba\x7f\x0a\xce\x75" + "\xe1\xa6\x50\xf2\xb1\x5f\xa4\x67" + "\x9f\xdc\x3c\xe5\x9c\x91\xbc\x93" +
- "\x45\x33\xce\xdd\xaa\xcc\x2f\xec" + "\x50\x43\x2a\x01\xb7\x11\x68\x2a" + "\xdc\x8b\x59\xac\xf1\x0f\x76\x96" + "\x28\x41\xbf\xd1\x2a\x65\x4d\x05" + "\x05\x10\xa2\x92\xd4\x51\x11\x0a" + "\xdf\x0f\x11\x33\x71\x39\x7f\xad" + "\x0f\x10\x60\x19\x8c\x92\x95\x8c" + "\x62\x33\xf0\x7b\x25\xc8\x91\x6c" +
- "\xec\x1d\x3f\xec\x5d\x12\xe6\x19" + "\xda\x78\x11\x91\x40\xf0\xb1\x07" + "\x38\x67\x4a\x90\xda\xde\x3e\xd9" + "\xcd\xed\xeb\x0b\x5a\x7a\x18\x55" + "\x41\x9d\x32\xeb\x22\x47\xd0\xf7" + "\x91\xb3\x70\xf1\x9e\x09\x49\xf4" + "\x28\xf8\x99\xca\x69\x7a\x31\xfd" + "\x6d\x97\xa4\x34\x2b\xdb\xc3\x50" +
- "\x78\x71\xfe\x7b\x1b\x48\x74\xb6" + "\x68\x58\x40\x65\xae\xeb\x1d\x4e" + "\x7d\x86\x8c\xc4\x21\x28\x1b\x06" + "\xea\x30\x3b\x51\x35\x5b\xc1\x69" + "\x88\x10\x87\x36\x66\x16\x4a\x3b" + "\xff\xb1\x20\x12\x5d\x9f\xe2\xe5" + "\x4d\x9f\x3d\x23\x35\xbb\x82\x4b" + "\x75\xc6\xcd\x18\x33\x63\x07\x4e" +
- "\x73\x44\x56\xcb\xdf\xe8\xd2\x78" + "\x1a\x62\xd5\x57\x73\xa9\x49\x43" + "\x24\x8b\x8f\x21\x89\x5d\x83\x9d" + "\xe2\x6e\x9b\x07\xc5\x7b\xfe\x01" + "\xce\x5d\x3b\x5b\x2b\x2a\x7f\xe5" + "\x65\x55\xe5\x5f\xb7\x37\x86\x5a" + "\xe7\xba\x1d\xa4\xae\x34\xff\x83" + "\x8f\x7a\x0a\x95\x9c\x19\xe1\xfc" +
- "\x06\x77\x70\x3e\x1f\x54\x4f\x37" + "\xcf\xd0\x31\xa8\x38\x36\x4d\x9a" + "\x04\xca\x18\x15\x83\xf4\xb4\x4a" + "\x18\xc3\x38\xfe\x5d\xee\xe3\x54" + "\x9b\x81\xc8\x03\x64\xe3\x3a\x38" + "\x4c\x86\x17\x2e\xa1\xda\xd1\xa9" + "\x5b\xaa\xee\x50\xb3\x97\x5a\x24" + "\x83\x4e\xbf\x99\x09\xd0\x62\x53" +
- "\x80\x39\xd4\x9b\xc2\x13\x03\xfc" + "\x29\xdb\x72\xf1\x70\x4b\x95\x9c" + "\x1a\xa2\x54\xf9\xb7\xdc\x9b\x67" + "\xfc\xe4\xe2\x54\x09\x17\x48\x6b" + "\xd0\xf1\xba\x30\xf5\xf5\x8a\x31" + "\x60\x20\xf9\xcb\x3c\x8a\xea\x26" + "\x58\xe2\x5a\xcd\x7c\x9d\xc6\xc3" + "\xc9\x07\xad\x0e\x47\xa0\x3b\xa7" +
- "\x69\x5e\x81\x31\x97\xc3\x63\x3a" + "\x02\x28\xdd\xdc\xd6\xcb\xf9\x6d" + "\xaf\xf6\xb4\x15\x4a\xed\x47\x4c" + "\x78\xf9\xc0\x6a\x82\x9d\x00\x62" + "\xc7\x8f\x89\x8b\xd2\x80\x4d\x66" + "\x1f\xc9\x17\x2c\xda\xee\xf1\x72" + "\x09\x66\xae\x7a\xbc\xd3\x84\x9e" + "\x95\x68\x37\x28\x95\xc1\xc7\x58" +
- "\x07\x4f\x29\xd9\x30\x76\xff\xdc" + "\xd0\x8f\xba\x8d\xd6\x65\xb7\x89" + "\xcd\xac\xbc\x8d\xde\x55\x3e\x55" + "\xf8\x2b\x70\xed\x9e\x00\x4a\x9b" + "\x0d\xca\xb8\x27\xdd\x34\xe5\xf6" + "\x52\xfd\x77\x61\x34\x6b\x49\xc4" + "\xb7\xb7\x7b\xc8\xf6\xe6\x8c\x37" + "\xf0\x19\xcc\x44\x48\x3d\x63\x68" +
- "\x63\x20\x42\x5e\x91\xb9\xde\x73" + "\xc0\x1b\x75\x4a\x27\x64\xd2\x7a" + "\x4f\x34\x14\x44\x22\xe2\xdc\xe6" + "\x28\x1f\x81\x85\xf7\xef\x01\xad" + "\x2b\xb7\x68\xba\x90\x65\x48\x25" + "\xaf\x35\x36\x20\x4a\x26\x93\xdb" + "\x0a\x66\x22\x28\x8a\x1f\xb0\x1e" + "\x64\x8c\x59\xee\xe8\xce\x2d\xae" +
- "\x74\x78\xc1\x7d\xb6\xe7\x59\x35" + "\x2a\xcc\x95\x81\xef\xf0\xca\xd0" + "\xd9\x4d\xd2\x0c\x88\x67\xc0\x07" + "\x41\x7c\x85\x02\xa0\x9e\xa9\x01" + "\x63\x2f\xf8\x90\xe4\x79\x65\xd8" + "\x37\x92\x1c\xe4\x8a\x65\xe0\xb1" + "\x79\x1e\xfd\x93\xfd\xfa\x5f\x07" + "\x8f\x0b\xf6\x47\x35\x40\x70\x6e" +
- "\xed\xfc\xe6\xa3\xc7\xf5\x53\x0d" + "\xeb\xbd\x5f\xf4\xd5\xbd\xcb\xe8" + "\x70\x9a\x33\x13\xdf\x01\x5c\xf8" + "\x81\xeb\x2c\x14\x80\x18\xf7\x0f" + "\x7a\x43\x70\xbd\x74\x87\x4e\x4c" + "\x6a\xda\x0b\xba\x91\x28\xb3\x5f" + "\x6e\xd2\x8b\xf1\xd2\xeb\xdb\x1c" + "\x22\xd5\xa9\x03\xf1\x26\x95\x2f" +
- "\xa6\xb0\x51\xbe\xda\x86\x51\x76" + "\x88\x90\xce\x73\xf4\xe9\x76\x53" + "\x5a\xd8\x5b\x5b\x0b\x80\xed\xe3" + "\x04\xe6\xc1\x4d\x52\x95\x28\x24" + "\x5e\xd3\x27\xef\x47\xcc\x6d\xe7" + "\x7d\xa6\x00\x90\xd6\xee\x96\x43" + "\xc1\x92\xde\x84\xa0\x3b\xb3\x73" + "\xfe\x01\x76\x37\xae\x53\x64\x22" +
- "\xc2\xe9\xf7\xc1\x75\x60\xfc\xec" + "\x34\xec\x5a\xbe\x20\x76\x21\x6a" + "\xa8\x3b\xa3\x9e\x54\xd0\x81\x37" + "\xd4\x85\x6b\xd8\xab\x35\xef\x84" + "\x83\xee\x1f\x46\x3c\xa3\x4a\x91" + "\x6c\x7d\x5f\xb2\xc9\xe5\x11\xf3" + "\x5c\x49\x3d\xc3\xaa\x0d\x11\xc6" + "\xb9\x54\x85\x81\x83\xe5\x7e\x8a" +
- "\x0e\xec\xf4\xa7\x2a\x73\x12\x36" + "\x8f\x34\x71\x9d\xd0\x88\x3e\xee" + "\xdb\xcf\x99\x75\xe4\x07\xa1\xb7" + "\xc6\x51\x1b\x61\xe8\xe7\x5d\x1f" + "\xaa\xaa\x51\x10\x59\x1d\xa1\xd6" + "\x86\xc3\xf0\x55\xf0\x31\xe5\x3d" + "\x66\x0e\xf2\x09\x73\x5c\xf9\x09" + "\x79\x4b\x41\x9e\x1a\xaa\x21\x64" +
- "\x7e\x1d\x27\xa8\x05\xc9\x52\xa7" + "\x0b\x81\xe5\x58\xa5\xdf\x35\x47" + "\xeb\x5a\x92\x5d\xee\x44\x8a\xe1" + "\x53\xa8\xc8\x13\x7f\x69\x08\x97" + "\x0b\x9a\xcc\xbf\x40\xd5\x77\x83" + "\x03\xd4\x74\xe5\x1c\xe0\x27\x7b" + "\xa6\xa8\x60\xcf\x0c\x18\x3d\x3d" + "\xbf\x98\xc2\xf1\x52\xf1\x8e\xe4" +
- "\x60\xb0\x29\xb8\xb1\x60\xb6\xb8" + "\x9b\xc6\x55\x5f\xf1\x3e\xa7\x9f" + "\x88\x78\x20\xef\xec\x19\x5f\xc7" + "\x9e\x12\x2b\x28\x60\x2b\x9b\xb1" + "\xc7\x30\x47\xbf\xee\x27\xf3\xb2" + "\xbe\xc0\x73\xc9\x59\xf6\x9d\xeb" + "\x98\xdb\xc1\x65\xc1\x13\x49\xd1" + "\x9c\x1a\x9d\xf7\xd4\x7d\xf5\x80" +
- "\x21\x28\x39\x66\x6f\x02\x04\x11" + "\x49\x84\x79\xe1\xf7\xbe\x3d\x25" + "\x18\x56\x3e\x3f\x37\x34\x4b\x3c" + "\x41\xe0\x64\x2c\xd6\x46\x55\x5b" + "\x2b\x76\xc5\x57\x79\x32\xb5\xad" + "\xf3\x8d\x95\x92\xf0\xd0\xcb\x5d" + "\xbe\xbd\x4f\xf6\x44\x74\x45\x2c" + "\x75\x81\x40\x1d\x82\xc3\xab\xb4" +
- "\x79\xd7\x19\xe9\x9b\xe7\x2d\x0c" + "\xbd\x78\x2e\x24\x4a\x69\x84\x15" + "\xc9\x76\x13\xf6\x94\x6d\x75\xa4" + "\x98\x27\xdc\x34\xbc\xa7\xcc\xfb" + "\xa1\xf0\x8d\x10\x19\x53\x87\x5e" + "\x9d\x89\x3e\x29\xae\x01\xec\xe2" + "\x91\x70\x35\x92\xef\xa4\x28\xc9" + "\x65\xd0\x2e\xf6\x87\x89\xa2\xd5" +
- "\xc0\xa3\xea\x0a\x8c\x2e\x3a\x31" + "\x0a\x5b\xe8\xab\x9e\x6d\xf4\x89" + "\x3a\x7d\xa9\x2d\xbd\x9e\x88\xd2" + "\xba\x8c\x3f\x10\x6a\x02\x84\x94" + "\x5f\x3b\xd8\x87\x8a\x9f\x15\x52" + "\x95\x02\xef\xb1\xd6\x20\x22\xdb" + "\xcf\x1a\xc0\x03\x6e\x74\xa0\xbd" + "\xe3\x9f\x41\x14\xa7\xb2\x97\x4f" +
- "\x9f\x20\x55\x25\xf7\x36\x04\xac" + "\xec\x73\x27\x16\xa2\x66\x34\x20" + "\xfe\x59\x8e\xb4\x39\x87\x3f\xc5" + "\x60\x56\x84\x88\x2b\xda\x4c\xb2" + "\x9a\x39\x5e\xfa\xf9\xb5\x74\x8d" + "\x5e\x25\x92\x6f\x0b\xed\x3d\xff" + "\x0a\x9e\x5c\x04\xfe\x31\x6c\xc7" + "\x62\x46\x2b\x6d\x44\xa0\xba\x85" +
- "\x51\x5d\xf0\xed\xbe\x8b\xaf\xb8" + "\xb8\x8d\x8f\x71\xa6\xc7\x53\x86" + "\xdd\xff\x00\xcf\x8b\xb4\xfe\x14" + "\x40\xe1\xa9\x5c\xdb\xf7\xbc\xfc" + "\xb7\xfd\xd8\xd9\xe8\xec\xb4\x73" + "\x21\x99\x38\x2f\x68\xd3\x69\xdc" + "\x19\xc2\x8b\xc8\xe4\x2e\xd3\x10" + "\x96\x2d\x1c\x92\x27\x2c\x4d\xc0" +
- "\xfd\x73\x10\x3d\xb8\xfd\x81\x69" + "\x0e\x20\x78\x6c\x0d\xf7\x2a\x25" + "\x7e\x57\xef\xa9\x67\xe8\xd0\x60" + "\x67\xe0\x13\xa4\xe8\x3f\xe6\x66" + "\x3a\x15\x14\xb9\x73\xb1\xdc\xbb" + "\xa8\xa0\xb4\xcc\x23\xe6\x9a\xb5" + "\xa0\xb8\x35\x3c\x20\x30\x05\x34" + "\xff\xf2\xda\x30\x6f\x81\xb8\x19" +
- "\xca\xe5\x80\xc8\xc2\x7a\xbf\xcc" + "\x50\xc4\x11\x8d\xee\xdb\x99\x82" + "\xbf\xa6\x77\x0f\x1b\xd1\x27\xbb" + "\x93\xe7\xdc\x5e\x0b\x63\x01\xc6" + "\xea\xf8\xe7\x79\xfb\xb9\x73\xdb" + "\x88\x72\x36\xf4\xa7\xbb\x48\xe4" + "\x1b\x57\x35\xb0\x6f\x41\xb6\xf5" + "\xa2\x91\x88\xa4\x5d\x8f\x1b\x98" +
- "\xa0\xfa\xfb\xb4\xff\x90\x96\x00" + "\xdb\xc6\x19\x36\xb7\xda\xbb\x8b" + "\xe8\x56\x83\x72\x73\x42\xd4\xc6" + "\x35\xec\x53\xe4\xd8\xf0\x76\xfd" + "\x29\x8a\xc2\xaa\x54\x25\x5c\x77" + "\xf0\xe4\x55\x5c\x9d\xaf\xf7\x28" + "\x4d\xad\xe8\x88\xa6\x54\xcf\xba" + "\xdf\x6d\xa7\x0a\xe8\x18\xb0\x85" +
- "\x93\x7a\xc3\x09\xb9\xb3\xc8\x8f" + "\x2c\xb0\x99\xa1\xcb\xeb\x8f\x75" + "\x8c\x20\x3b\x8f\x38\x45\x9b\x5c" + "\xf0\x90\xba\xf2\xde\x84\x85\x7c" + "\xe3\xcc\x95\xb3\x1c\x1a\x75\x52" + "\x50\x5f\xd4\xc1\xeb\xe4\x59\xbb" + "\xac\x5d\x63\xb0\x11\xb9\xcd\xf7" + "\x94\x36\x24\xd3\x71\xd3\x24\xe9" +
- "\xd6\xa8\x53\x65\xfd\xc0\x32\x65" + "\x6d\x5a\x16\x45\xa5\xcb\xb8\x42" + "\x92\x2d\xf1\x3c\xea\x88\x6d\x9c" + "\xc5\xb0\x6d\x90\x30\x35\xc9\x0e" + "\xdf\x6c\xcc\xec\xf8\x06\x46\x49" + "\x99\x78\x38\xc6\xfc\x66\xed\xa7" + "\x4c\xae\x35\x8a\x17\x2e\x02\x91" + "\xc3\xbe\xa7\xec\xe6\xca\xdb\x28" +
- "\x84\xd6\xc4\x92\x51\x30\xce\x40" + "\xcd\xef\x12\x76\x25\xd7\x04\x8b" + "\x20\xae\x9c\x6f\x36\xda\xdc\xb9" + "\x6c\x85\x58\xf0\x24\x4d\xdc\x0e" + "\x00\x79\x42\x85\xbf\xe6\xf2\x64" + "\xea\xdf\x09\xdc\x95\x12\xe8\x3d" + "\x6c\xf2\x9b\x37\x87\x44\x1b\xd4" + "\xa9\x35\xf1\x6d\x6d\x2c\xb6\x50" +
-
- "\x2a\x83\x05\xd0\x5e\xfb\xb2\x0d" + "\x4f\x2e\x04\x91\x3b\xfd\x5e\x5f" + "\xca\xf8\x70\xed\xc6\xfd\x4f\x8c" + "\xcc\xa9\x2d\xb5\x0b\x5d\x64\xe4" + "\x1f\x1d\x00\xc9\x8b\xf5\x96\x95" + "\x05\x72\x11\x4e\xbc\xf0\xc8\x52" + "\x84\xa0\x98\xe3\xd2\xa0\x4a\xfd" + "\xde\x49\x4f\x10\x3a\xfe\x5b\x81" +
- "\x7b\xb3\x48\xe5\xcc\x3a\xeb\x54" + "\x49\x05\xd4\x84\x42\x75\x8e\xb3" + "\x4f\x1b\x34\x7b\x51\xaa\x3d\x8c" + "\xfa\xf7\x0b\x69\xec\x28\x69\x2f" + "\x41\x6c\xce\x86\x23\xb3\x96\x04" + "\xcd\xad\xad\x10\x55\x1c\xbe\x01" + "\xf9\xfa\xb5\x4b\xe7\x67\x4e\xc0" + "\x85\x99\x5c\xe1\x78\xf6\xba\x3c" +
- "\x2d\x9a\xab\xd7\x6a\x22\x4d\x52" + "\x58\xe9\xfa\x7d\x0d\x09\x00\x9c" + "\xc2\xd8\x51\x87\x39\xf5\xa5\x0b" + "\x2d\x26\xb8\x3a\xdd\xbc\xfc\x8a" + "\x3b\x04\x9d\xe9\x29\x27\x39\x57" + "\x3a\x94\xbc\xae\x3b\x26\x51\xef" + "\x35\x29\x86\x20\x93\xce\xea\x9f" + "\x7b\x81\x6c\xb0\x03\xfc\x9e\x63" +
- "\xdc\x81\x1d\x34\x7d\xbe\x39\xe8" + "\x79\x83\x14\x32\x89\x68\xdb\xcd" + "\xad\x6e\x02\xf7\xa1\x11\x62\xda" + "\x5e\xcc\xd1\xf4\x5f\x57\xb2\xf3" + "\xe6\x3a\xa7\xa7\xf6\xc8\xcf\x40" + "\x83\xb4\xd5\x61\x5e\x9a\x87\x83" + "\xbc\x0e\xa5\x41\xed\xb1\xac\xc5" + "\xfa\xd8\x07\x3c\xc8\x0c\xa6\x59" +
- "\x90\x19\xb8\xc3\x4a\x8d\xc9\xde" + "\xfe\xc8\x0c\x9e\x22\x37\xb8\x1c" + "\xb9\x27\xb4\xd2\x91\x04\x0b\xfe" + "\x6c\xa6\x83\xe9\xac\x86\x23\x0f" + "\x13\x12\x29\xb3\x1e\x4d\x0c\x93" + "\xe4\x2a\xa6\x59\x2e\x2b\xf8\xa2" + "\xe3\x89\x3e\xf9\x53\x38\x23\x77" + "\x7f\x7c\x77\x11\xac\x63\x80\x7f" +
- "\x00\x10\x37\x59\x7c\xc9\x4a\x60" + "\x18\x9c\x75\x7f\x70\x8c\xc4\xe1" + "\x65\x6b\xdb\xa5\xc5\xec\x62\x3f" + "\x95\x14\xa2\x38\x73\xb1\x78\x0a" + "\x94\xad\xc8\xbc\x9d\x81\xe1\x6b" + "\x00\x34\x9c\xd8\xf6\x04\xdc\x70" + "\x0a\x84\xb4\xa6\xb4\x57\x25\x46" + "\xc0\x21\xbd\x60\xde\x6a\x4c\x54" +
- "\x72\x60\xff\x02\xcf\x07\xe6\x36" + "\xdc\x8c\xd9\x8a\xa9\x2c\x7d\xa4" + "\x09\x66\xf5\xf5\x1e\x1d\x47\xbf" + "\xa0\xad\x64\xf2\x23\x66\xf8\xbc" + "\xb6\x5c\x9e\xaa\x87\x06\x0c\xb7" + "\x6c\x1c\x40\x17\xf2\x24\x81\xc9" + "\x35\x14\xa6\xd4\x5f\x63\x89\x81" + "\xa6\x8e\xd9\xa9\xaf\xb8\x8f\xd2" +
- "\x2d\x32\xc7\x65\xb6\x30\x95\x43" + "\xfb\xb3\xc1\xb3\x01\xcc\x12\xcf" + "\x85\xf6\x72\x01\x86\x01\x0b\xc7" + "\x1d\x39\x58\x1b\x22\xee\x15\xb9" + "\x24\xdb\x17\xa3\x3b\xf0\xfd\x9a" + "\xc4\xff\xb8\x17\x59\xc6\xde\x87" + "\x50\xd0\xd3\xe4\x7b\x59\x46\x7f" + "\xe7\x00\x65\x00\xed\xc1\xa1\x80" +
- "\xf3\x25\x70\x01\xc3\xa8\x4d\x3d" + "\xb4\x79\x95\xfb\x8c\x62\xcf\xef" + "\xec\x16\x37\x1f\x16\x00\x4d\x5c" + "\x6e\x11\x01\x68\xc4\xeb\x27\x9c" + "\x7e\x76\xa1\x1d\xa1\x0e\xba\x5e" + "\x57\x4c\x00\x47\x52\x14\x15\xfe" + "\xb7\x73\x23\x8c\xf6\x6d\xce\x3a" + "\xac\x37\xbc\x5d\xfe\xdf\xc3\x75" +
- "\x49\x07\x8a\xa2\xdb\x47\xa1\xa2" + "\x65\x91\x51\xee\xd6\x20\x6c\x24" + "\x15\x07\x81\xd3\xb1\xd1\x68\x50" + "\xb9\x60\x81\x74\x8c\x01\xe7\xb1" + "\x62\xff\x80\xf3\xfa\xb1\xf5\x03" + "\x1e\x2c\xcb\xf3\xdd\xb1\x7f\xef" + "\xda\xa7\x91\xfc\xa8\x39\xb5\xea" + "\x61\xb5\xf9\xf3\x07\xb7\xdd\x83" +
- "\x98\x1b\x10\x80\xd9\x76\x72\xb5" + "\x66\x0f\x2f\xb8\xfd\x83\x08\x76" + "\xf3\xef\xc3\x4b\x75\xde\xd7\x89" + "\x40\xab\xc2\x5d\x43\x06\xb6\x03" + "\xac\xee\x5b\xe0\xdf\x53\x6e\xcd" + "\xcd\x25\x33\xbc\x62\xe8\xf1\xf2" + "\xc3\x03\x4f\x77\x21\x79\x0f\xdd" + "\x1b\xcc\x52\x45\x21\x72\xca\x97" +
- "\xea\x46\xec\x9c\xf0\x4a\x9a\xe7" + "\xc7\x9b\x8b\x65\xa1\x47\x53\xb1" + "\x75\x2f\xaf\x35\x6f\x79\xd2\x6b" + "\x35\xc4\x51\x40\x90\x79\x95\xac" + "\x5d\x65\x3a\xc3\xa3\xdd\x69\x26" + "\xa3\x4a\x51\x88\x2e\x3c\x50\x5d" + "\x41\xdd\x53\x37\x37\x13\xa1\xdf" + "\x78\x4f\x75\x0b\x73\x46\x05\x3f" +
- "\xd7\xc5\x24\xe2\xb5\xb3\x0c\x76" + "\x19\x69\x61\x68\x8c\xaf\x3b\xfa" + "\x52\x25\x14\x8d\x13\xa1\xbc\x9f" + "\xf5\xeb\x69\x76\xf1\x8b\xb1\x1a" + "\xdd\x25\xdf\x9b\x3e\xf5\xe6\x55" + "\x54\xd1\x6c\xcb\xf3\x0b\xcc\x04" + "\x80\x90\xe8\x95\x49\xef\x5b\x59" + "\xc1\x9a\x4a\x10\xa8\x59\x94\xfe" +
- "\xf0\x3e\x12\xa8\x16\x63\xd6\x49" + "\x38\x54\xf9\xe7\xb4\x2d\xc3\x73" + "\x54\x78\x9e\x0d\x09\xd2\x2e\x2e" + "\x07\x05\x9f\x9d\x29\x93\x8a\xf9" + "\x0a\xa2\x6a\x0c\xf6\x3c\xd3\xc5" + "\xb2\x9b\x27\x75\x14\xba\x32\x9a" + "\x07\x73\x4a\x77\xcb\x02\x32\x7e" + "\xbd\x2d\xc4\xe8\xc4\x4b\xed\x64" +
- "\xe8\x20\xb0\xab\xc5\x64\x4b\x69" + "\xc7\xee\xc4\x19\x84\xc1\x18\x3d" + "\xe5\x93\x47\x1c\xef\x73\x46\x9c" + "\xe6\x92\x60\x05\xb5\xae\xb8\xc7" + "\x6b\xc1\xf8\xf0\x43\xca\xa1\x3a" + "\xf6\xb2\x79\xd6\xec\xd5\x4e\x22" + "\xc9\x05\xa2\x55\xaf\xee\x56\x0d" + "\x8b\x02\x8e\x4b\xba\x15\xe1\xbf" +
- "\xec\xf4\xac\x97\xb3\xa7\x22\x3e" + "\x40\xb6\xa8\x5e\x00\xc4\x26\x04" + "\x85\x92\x96\x4e\xa6\x95\x32\x5e" + "\x70\x56\xa4\xa6\x59\xbc\xaa\x22" + "\xbc\x42\x59\x5f\x4c\x71\x29\xb9" + "\xed\x82\x31\xfa\xbd\x68\x61\x9a" + "\xba\x52\x41\x10\x65\xa6\x16\x22" + "\x68\x63\x92\xb6\x03\x8d\x90\x46" +
- "\x50\xa8\xcb\x7f\x24\xe0\x8b\x9b" + "\x1e\x18\x0a\x82\x97\x57\xeb\x81" + "\x11\x12\xa0\x30\x22\x81\xf2\xa0" + "\x21\x88\x7b\xae\x3c\xdc\x9c\x7e" + "\xe7\x15\xce\x72\xcc\x32\x23\x20" + "\xd7\x38\x82\xcb\xbb\xb2\x3c\xcd" + "\x43\x2c\xe8\xc6\xdf\x63\xab\xe4" + "\x17\xd7\x83\x31\x28\x00\xbd\x58" +
- "\xab\x42\x29\xf3\xe8\x46\x8d\xd1" + "\x18\x24\x88\x10\xf6\x6e\x76\x6c" + "\x6b\xcd\xc6\x0c\x1a\xcb\xff\x8e" + "\x60\x59\xd8\x68\x5c\xa0\x1d\x5a" + "\x1c\x6e\x29\x32\xa5\xf4\xa5\xc7" + "\xc8\x2e\x0d\xc9\x43\x1e\x0f\x3d" + "\xd9\x29\x97\x89\x22\x3a\x94\x29" + "\x17\x53\x0e\x36\x26\x8a\x7a\x87" +
- "\xb5\xd7\x7e\x71\x7e\x7b\xd5\x02" + "\xa2\xe1\xbc\x4d\x24\x5b\x2e\xd2" + "\xf5\xdc\x4c\x2a\x71\xd7\x4b\x17" + "\xbb\x05\x82\x40\x01\xb8\xfd\xa6" + "\xe9\x87\x13\x5e\x69\xb0\xb4\x67" + "\x42\xa4\x91\x05\xa1\x19\x2b\x33" + "\x66\xf3\xac\xcc\x16\xd9\xed\x24" + "\x50\x8a\x95\x34\x45\xcc\x34\xbe" +
- "\x4b\x18\x1c\x06\x99\x76\x59\x81" + "\x52\x89\x89\x63\x5c\x10\x3d\x65" + "\xad\xfc\x5e\x7b\xde\x06\x91\xda" + "\x52\x14\xa6\x8a\xa6\x5a\x33\xa0" + "\x04\xba\xfa\x4f\x89\x7c\x7d\x33" + "\xf6\x90\xa9\x8e\xfe\xd4\xce\x9d" + "\x28\x57\x8c\x26\xb6\xb3\x28\x36" + "\xec\x21\xaa\xc2\x89\x70\x93\xf9" +
- "\x91\xd3\x66\x3e\x1e\x6e\xf4\xa3" + "\xb2\x69\x63\x7d\xcd\x32\xa7\xb4" + "\x22\x10\x2c\x40\x5d\xb8\xc3\x99" + "\x2e\x93\x54\x2b\xbe\xfc\xcc\x7d" + "\xe2\xdf\xb1\x56\x7b\xaa\xdd\xa6" + "\xc9\x82\x4a\xe3\xa5\x78\xdc\x31" + "\x41\x39\x4f\x70\xda\xb3\xbe\x8a" + "\x98\xfa\x55\xca\x6c\xa3\x11\xdf" +
- "\x66\x19\x86\x89\x34\x8e\x3b\xd5" + "\x6b\x99\xea\xa0\xa1\x20\xfb\x79" + "\x43\x7f\xd3\x5a\xd9\x47\x06\x30" + "\xcd\xe3\xa7\x53\xa8\xb4\x4d\xb4" + "\xfb\x59\x66\x2e\xb9\xe1\xe3\x9e" + "\x20\x72\x68\x5f\x72\x63\x32\x4b" + "\x43\x01\xa1\xb1\x25\x68\xc2\x6e" + "\x0b\x6f\x7d\x86\x2b\x76\xb6\xb4" +
- "\x1b\x0c\xe0\x16\x7a\xf7\x01\x6c" + "\xac\xaa\x9e\x83\x90\x54\x51\x82" + "\x34\xd3\x70\x34\xef\xa4\xf3\x62" + "\x6c\xcd\x1d\x1c\x49\xa6\x29\x5a" + "\x25\x7a\x99\xce\x2e\x78\xb6\x46" + "\x53\x99\x57\xd3\x35\xfb\x78\x99" + "\xce\xe0\x60\x09\xdf\xa9\xf5\x98" + "\x4c\x7a\x52\x1f\x39\xc8\x7d\x54" +
- "\xc1\xbc\xba\xc2\xc6\x8a\xcb\x52" + "\x8d\xae\x81\xfe\x48\xd4\x48\x47" + "\x11\xa7\xf1\x80\x3f\xf0\x44\x58" + "\xc4\x4a\xdf\xf8\xb2\x84\xb7\x3d" + "\x36\xfe\xf1\x2d\x12\x8f\x91\xad" + "\xc0\xc7\x3c\xf3\xb9\x25\x0f\xe4" + "\x55\x55\x5e\x3b\xe7\xd0\x00\x47" + "\xf9\x26\x33\xb0\x08\xfa\x28\x5c" +
- "\x4f\xc2\x9d\x5d\x83\x15\x5b\x39" + "\x80\xe6\x3a\xc7\x32\x69\x25\xa4" + "\xe9\xc8\xa2\xfa\x0e\x96\x42\x05" + "\x6a\x8c\x06\x71\xee\xad\xb3\x2b" + "\x54\x45\x0b\x57\x9b\x09\x06\xa7" + "\xd6\x78\xe2\xf4\xb5\x2b\xd1\x85" + "\x43\x68\x29\x64\xf6\xf6\x8a\xd7" + "\x33\xc6\x28\x84\x88\xb3\xd3\xc7" +
- "\x58\x97\x3f\xdb\x09\x67\x3b\x4c" + "\x1a\x8c\x1d\x34\x4e\xda\x9e\x16" + "\xd2\xa6\x13\x96\x18\x2f\x4f\xbd" + "\x36\xa5\xcd\xd7\x4e\x2b\x00\x9a" + "\xb9\x03\x61\x77\xd1\xf8\xbd\x97" + "\xba\x45\x79\xb3\x34\x0d\x67\x9c" + "\xbf\x5b\x8c\xd7\x84\xe3\x83\x9b" + "\xb2\x14\x8d\x51\xcf\x3b\x2d\x6e" +
- "\x97\xe5\xb7\x43\x93\x4f\xd4\x34" + "\x42\x0f\x53\xc2\xa7\x40\xe4\xdd" + "\xb9\xbd\x56\x78\x81\xa0\x70\x72" + "\x2f\x03\x53\x53\xeb\x45\xa9\x86" + "\x10\x98\xd3\x66\x99\x8e\x2f\x6c" + "\x6b\x4b\x8b\x9b\x1b\xa3\x42\x06" + "\x82\x9d\x50\xd1\x62\x9e\x67\x51" + "\x16\xff\xf8\x90\x1c\x00\x20\x01" +
- "\x4a\xe3\x36\x2e\x06\xc1\xa1\x50" + "\x1a\xed\x24\xe0\x8c\xf5\xe8\x74" + "\x26\xd7\x00\x13\xfa\x1d\x0f\x3f" + "\x18\x2d\x4a\x7b\x26\xdf\x80\x66" + "\xb7\xb3\x35\x82\x9d\x97\xb5\x12" + "\x93\x14\x61\x8a\xcb\xaf\x2f\x1d" + "\xe5\xec\x48\x88\x96\xda\xeb\x73" + "\x99\xe3\x13\xa4\x75\xc2\x96\xe9" +
- "\x00\xf0\x5f\x49\xc7\xd7\xb7\x46" + "\xd1\x95\xed\xba\x97\xd0\x0e\xe6" + "\xc0\xf9\x38\x6e\xac\x04\x88\xaa" + "\xbb\xf9\xc6\x45\x06\x0c\x99\x92" + "\x51\x98\x91\xc0\x39\xa4\xe6\xca" + "\xf2\xe1\xf5\x1b\x15\xff\x3d\x71" + "\xdb\x8c\xb3\x2e\x30\x2c\x26\x5d" + "\xdf\x31\xdf\x90\x51\x50\x3d\xb7" +
- "\xe5\x2f\x5b\xe5\xc2\x32\xc8\x85" + "\xfc\xde\x19\x91\x65\x21\x51\xf2" + "\xe4\x0f\xb0\x99\xbc\xe3\xfd\xfc" + "\x17\x8b\x90\xd1\xe3\xf5\x67\x80" + "\x42\xae\x43\x14\xb3\xf6\x21\xe9" + "\x3b\x59\xea\x64\x92\xed\xcf\xa2" + "\x35\x7a\xe0\x59\x62\xb9\x89\x15" + "\xdd\x62\xa7\x0d\x0a\x39\xbb\xc6" +
- "\x8c\x26\xd9\x32\x1c\x7b\x1e\x92" + "\xd4\xfa\x76\x42\x96\x2b\xdb\x34" + "\x30\xe7\x44\xcc\x34\x6d\xc5\x0e" + "\xb7\x45\x65\x09\x46\x3a\xbe\x59" + "\x6a\x3a\xcf\x66\x97\xbc\xfd\xe9" + "\x53\x9b\x4e\xd0\xed\x83\x2f\x7b" + "\xe7\xe3\xba\x8f\xcc\xb3\x99\x6d" + "\x40\x3a\xda\x7a\x6c\x64\xb5\x8e" +
- "\xfb\x51\x12\x5a\x74\xd8\xf5\xa9" + "\xc7\x25\x27\xc7\xa8\x47\x77\x96" + "\x9e\xe8\xff\x31\xe5\x33\x5c\x19" + "\x5e\x93\x64\xe9\x0f\x21\x9d\x60" + "\x27\x22\xe1\x2f\xa8\x6c\xfd\xca" + "\x9d\x46\x26\x04\x96\x5b\x9b\xaf" + "\x3c\x18\x93\x56\x4c\xe0\x9e\x2e" + "\xef\x6f\x14\xc8\x33\xa3\x84\x10" +
-
- "\xf7\xd1\xd1\xae\x33\x99\x64\x96" + "\x90\x30\x56\x50\xf3\xaf\x6e\x56" + "\xcf\x39\x2e\xad\xf0\x57\x50\x34" + "\x24\x21\x83\x1f\x5b\xf6\x8f\x14" + "\x0d\xcf\x94\xcf\xd4\x89\x2e\x04" + "\xb3\x58\x0c\x52\x84\xec\x9b\x31" + "\x0d\xaa\x61\x53\x26\x76\x26\x2a" + "\xad\x87\xbc\x8f\x02\xa3\x6f\xc8" +
- "\x6f\x69\xc1\xad\xe1\xd7\x66\x6b" + "\xd0\x72\xcd\x0a\x93\xe5\xeb\x98" + "\x35\x74\x1b\xcc\x50\x45\xf2\x65" + "\xec\xa5\xb9\xb4\x93\x13\x23\xce" + "\xf9\x7d\x06\xdb\xd4\x22\x4a\x23" + "\x00\x9b\xff\xca\x95\xa0\xdd\x98" + "\xc1\xc9\x00\x61\xa0\x75\xbc\x1b" + "\x95\xf6\x9c\x93\xc8\xa9\x60\x15" +
- "\x74\xbf\x51\xfe\x5e\x32\x50\x08" + "\x94\x00\x46\x5e\x9e\x57\x4f\x9c" + "\x25\x2f\xda\x76\x2a\xb9\x87\x5c" + "\x33\xef\xeb\x6f\xe0\xe4\x9d\x88" + "\xce\x83\x60\x64\x06\xec\x00\x69" + "\x73\x27\xe1\xbf\x35\x03\x2a\xbe" + "\x10\x41\x34\xc5\x35\xda\xd1\xad" + "\x20\xcd\x02\xb8\xb7\x68\x75\x75" +
- "\xca\x67\xc3\xf1\x1c\x0f\x05\xe4" + "\x7d\xbc\x0f\xc9\x9b\x5a\xc8\x9b" + "\x32\x10\xa1\xe1\xa2\xc4\x73\xa3" + "\xa9\x93\x03\xad\xb7\x32\x42\xb6" + "\x29\xad\x7d\x16\xb0\x7e\x57\xf5" + "\xb2\x8a\xb7\x94\x01\xf3\x04\x16" + "\x8b\x34\x29\xe8\xaf\x94\xaa\x0b" + "\x42\x43\x65\x41\xdd\xd8\xfb\x77" +
- "\x2e\xcd\xa7\x94\xb4\x51\xf6\x6f" + "\x6c\x33\x99\x06\xd1\xff\x71\x56" + "\x6a\x89\x9a\x97\xcc\xd2\x5f\x6f" + "\xef\x8c\x14\xd8\xa8\x93\xe8\x11" + "\x10\x7b\xcf\x65\xa1\x06\x89\x98" + "\x85\x84\x0d\xc5\x78\x71\xb6\x81" + "\xde\xb3\x35\x8a\x35\xeb\x0d\x7c" + "\x99\x97\xd2\xc1\x55\xc8\x3a\x42" +
- "\x08\x87\x61\x09\xe1\x69\x9f\x71" + "\xb1\xf9\x83\xc1\x64\x83\x9e\xcc" + "\xaf\x21\x6a\x36\x95\x3a\x20\xec" + "\x1f\x14\x8b\x06\x6d\x5d\xec\x6a" + "\xe9\x04\x4f\x99\x8a\xf7\x2d\xee" + "\xb0\x45\x12\x27\xe8\xca\x9c\xb3" + "\x4f\x3f\xe4\x97\xa9\xa4\x75\xb8" + "\x98\xea\x2c\xdb\x11\xfe\x7d\x50" +
- "\x3d\x12\x32\x52\xea\x7a\x4b\x31" + "\xdb\x86\xae\x65\x8c\x7c\x30\x08" + "\xed\x68\x46\xaa\x5c\x16\xe7\x06" + "\x39\xec\xd3\xb4\x8b\x45\x70\xb1" + "\x86\xb9\x9b\xc1\xc6\x3e\x2e\x4d" + "\xed\x04\x03\xae\x46\x48\xf3\xc5" + "\x22\x97\x9f\x6c\xa0\x95\x76\x91" + "\x0a\x1c\xab\x4c\x17\x73\x7f\x6c" +
- "\xfd\xa7\xf0\xfc\x02\x48\xf1\x31" + "\x1e\xb0\x88\x54\x89\x07\xfd\x42" + "\x98\xb4\x52\x99\x6d\x8d\xd7\x71" + "\x01\x52\xac\x07\xd9\x72\xb5\x8e" + "\x88\x4a\x19\x4d\x4c\xa4\xa2\xe0" + "\x66\x7e\x01\xba\xd9\x3f\xb6\xd2" + "\xfc\xae\x88\xf8\xc8\xc6\xef\x78" + "\x11\x1a\x88\x4a\xda\x6b\x6f\xb7" +
- "\x38\x72\xa6\xb2\x01\xe1\x0b\xbf" + "\xf2\x14\x9c\xaf\x67\xd3\x56\x35" + "\x75\x20\x66\xa5\x31\x78\x4b\x10" + "\x0a\xe6\xd9\x79\xbb\x59\xca\x58" + "\x3b\xa7\x69\xa5\x92\x53\xc4\x4b" + "\xc9\xf6\x98\x56\xe8\x52\x7a\x51" + "\x55\xd7\xad\xae\xa5\x3d\x64\x85" + "\x84\x1b\x58\x2a\xd5\x0c\xed\x1a" +
- "\x67\xe9\xf9\x19\xbc\x26\xf7\xa0" + "\x4e\xbf\xfb\xe8\x52\x31\xd0\xd9" + "\x40\x7d\x70\xb7\x1d\xf5\xd6\xcf" + "\xe0\xe6\xf6\x63\xd9\x84\x30\x63" + "\xaf\x7e\x66\x55\xdc\x9c\xcd\xed" + "\x6f\xd5\x44\x2e\x2b\xf9\xb7\x73" + "\x14\x2b\x96\x4e\xb6\x39\x2e\xfb" + "\xbf\xfc\x71\xf6\x6e\x8f\x40\x7d" +
- "\x8a\xcf\xdf\xf8\x75\x30\xea\x9e" + "\x25\x98\x66\x95\xaa\xf0\x84\xa2" + "\xd8\x3f\x7d\x86\x50\xa2\xfc\xb3" + "\x1e\x69\x9d\x26\x5f\x7b\x75\x20" + "\xde\xa5\xb8\x93\x20\x40\xc2\xf2" + "\xa6\x6d\xc0\xeb\x59\x33\xf9\xd3" + "\x33\x9c\x73\xb2\x3e\x29\x78\x11" + "\xe5\x86\xd6\xbc\x70\xe7\xa3\xd2" +
- "\xee\x43\xaf\x68\x2c\x93\xf7\xa2" + "\xbd\x00\x3d\x70\x8e\x46\x02\x55" + "\xf5\x61\xb0\x2f\x8f\x97\xdc\xe5" + "\xad\x15\xc8\x28\x4a\x90\xa1\xc9" + "\xa4\x56\x0c\x47\x8d\x53\xaf\xd3" + "\xed\x8c\x3d\x19\x5f\xbc\x9a\x15" + "\xf3\x8e\x10\x20\x5f\x24\x37\x2a" + "\x78\x71\x3f\x22\x1e\x08\x17\xfa" +
- "\x3a\xa7\xf2\xec\x8d\x6e\x20\x2a" + "\x94\x19\x55\x8e\x97\x63\x6a\x06" + "\xa2\x53\x8d\xb9\x8a\x08\x6a\x3a" + "\xaa\x24\x11\x2d\x7c\xc6\xe7\x0c" + "\x3c\x11\x9a\x75\x71\xc6\xce\x48" + "\xfa\x67\x6f\x4f\xd3\x73\xb3\xe3" + "\x7b\x72\x36\xfd\x79\xd4\x55\x54" + "\x81\x0d\x3c\xa1\xee\x28\xa4\xe5" +
- "\x5e\xbd\xb1\x16\x5f\xea\xfe\x6b" + "\xd3\x0a\xe3\x4d\x20\xe4\x57\xf9" + "\x9e\x3b\x35\x6a\x4e\x66\xaf\xcb" + "\xeb\x4f\xd1\x26\x12\x33\x87\x5c" + "\xcb\x57\x5f\xb6\x8c\xf9\x87\x4e" + "\x41\xdd\x0c\x5e\x21\xa6\x60\xdb" + "\x40\x14\x88\xa6\x65\x68\xc1\x67" + "\xaa\x52\xab\x46\x1a\xef\x93\x10" +
- "\x64\xec\x2e\xbb\xba\xcb\xbc\x93" + "\xbe\xad\x03\xda\x64\x3b\xc2\xa0" + "\xc4\x6a\xe8\xe0\x0a\xa0\x7a\x5f" + "\xe6\x01\x14\xfc\x1e\x94\x0b\x47" + "\x74\x35\xf4\x9d\x79\xd6\xd8\x5a" + "\x10\xd8\x65\x0f\xa9\xb8\xcf\x4c" + "\x81\xbd\x7f\xaa\xe3\x80\xce\x1b" + "\x0a\xd2\x08\x95\xad\x91\x32\x27" +
- "\x7c\xb6\xb4\xb4\xb2\xa9\xe2\x1f" + "\x04\x06\x02\xe8\xf0\x0d\xd1\xc1" + "\xd8\x58\x80\xbc\xfc\xab\x64\x9d" + "\xbb\x0f\x2a\x71\xb2\xb9\x43\x89" + "\x04\xef\x3d\x3b\x14\xd9\xee\x90" + "\xff\x75\xe7\x4c\xa2\x3a\xab\x85" + "\x40\x90\xbc\x7b\xca\xd4\x5f\x60" + "\xfb\x5d\xc7\xe2\x64\xa5\x34\x8b" +
- "\x0f\x36\x82\xe3\x7c\x9f\x75\x25" + "\x57\x58\xbf\x88\xc9\x05\xdb\xb6" + "\x6c\xd4\x58\x6c\x1d\xd6\x17\x29" + "\x7a\xcb\x20\xfd\x91\xe4\xf8\x14" + "\x40\x03\xc2\x11\x7a\x72\x8a\xb6" + "\xb6\xcb\x7c\xaf\x6f\xf8\x86\x03" + "\x20\x9a\xe0\xfe\xcc\xc6\x8b\x5c" + "\x35\xea\x7e\xbb\x4a\xff\x76\x7d" +
- "\x88\x52\x8a\xaa\xaa\xca\xab\x4d" + "\xc9\xa1\x23\xaf\x8a\x0c\xcc\x91" + "\x0c\x0e\x22\x3f\x6a\x2c\xc7\x34" + "\x4a\x14\x32\x12\xdf\x0b\xc2\xbc" + "\x1b\xde\x0e\xa2\xda\x42\x2f\x6e" + "\x15\x05\xa0\x74\x0c\xf0\x41\xc4" + "\x4b\x8c\x4b\x73\xb6\xa5\x46\xbf" + "\xa4\xc9\x56\x7b\x03\x95\x40\x57" +
- "\x1b\x57\xf3\x3f\xa5\x36\x68\xb4" + "\xc1\x27\x79\x83\x78\x8b\xf9\x24" + "\x16\xc7\x33\x45\x6a\x25\x54\x62" + "\x96\xe1\x7e\xd0\x0b\xbb\x7a\xf2" + "\xfd\x5b\x6d\x5c\xfc\x64\xcf\xd7" + "\x77\x7a\xcd\xf0\x51\xc7\x15\x69" + "\x34\xf5\x98\x87\x12\x90\xf5\xd9" + "\x5f\x8b\x1d\xf8\xa8\x0d\x2b\x77" +
- "\x90\x7d\x2f\x8e\xf8\xac\x18\x5c" + "\xcd\x32\xbe\x77\xd7\x33\xbf\xfd" + "\xe9\x5e\xeb\xd2\xd7\x5c\x08\x0a" + "\x15\x11\x20\xb3\xfb\x2c\x70\x2d" + "\xe8\x8c\xc8\x85\xdb\xeb\xe0\xb6" + "\x17\xd6\x01\x1e\x3c\xce\xa3\x23" + "\xac\x33\x73\x56\x8e\x61\x41\x30" + "\x6b\xdb\x7e\x15\x8f\xfd\xd0\x9d" +
- "\xb0\xd1\x07\xce\x73\xda\x6b\x38" + "\x78\x41\xad\x58\xc2\x10\x29\xd8" + "\xf4\x17\x26\xcd\xcf\x82\x4f\x12" + "\x70\x17\x69\xef\x8d\x5e\x2f\xcc" + "\xcc\x0c\xc3\xb8\x50\x25\x70\x82" + "\x5a\x57\x8e\x1a\xea\x6a\x85\x7b" + "\x59\x94\xab\xb1\xef\x2f\x82\xbb" + "\x8e\xe3\x24\xec\xbc\x28\x59\x08" +
- "\x71\x88\xb9\x8f\x11\x3d\x46\x80" + "\xff\x6a\xc7\xbb\xc3\xf5\x26\xcb" + "\x14\x36\xe0\xfb\xdd\x8e\xab\xd4" + "\xee\x2d\xcf\xc0\x9b\x57\xeb\xc8" + "\x41\xae\x3b\xc9\x15\x4c\x00\xcc" + "\xb2\xa3\xec\x3a\x5d\xae\xfb\x46" + "\xb1\x9a\x1e\x0f\xcf\x35\x12\x67" + "\xc1\x85\xc2\x9e\x34\xa9\xfb\xad" +
- "\x77\x64\x7c\xb5\x6b\x93\x6c\xa3" + "\xc6\xbc\x4d\xe9\x64\x8b\x1f\x87" + "\x7b\xa6\x91\xa5\x62\xfb\xd0\x28" + "\xf5\x26\xd9\xc1\x81\xe0\x40\x9d" + "\x5a\x4b\xd8\xf2\xf6\xea\x11\x31" + "\x44\xb6\x65\xa5\xf9\x93\x89\x22" + "\x8b\x18\x83\x2c\x92\xf5\xcb\x0c" + "\x97\xe1\xf3\x3d\xab\x30\x7b\xf8" +
- "\xaa\x7a\xfa\x98\x07\x61\xb2\xb2" + "\x4e\xaa\x73\xf0\xe4\x9e\x20\x41" + "\x9b\xb1\xd6\xf2\x59\x03\x57\xf1" + "\xaf\x7c\x57\xfc\x8c\x86\xe6\xcb" + "\xd3\x4d\xc0\x32\xdc\x4b\x6c\x18" + "\x97\xe3\xee\xcf\xae\x5f\xc3\xa6" + "\xcf\xc0\x86\xf0\x12\xb3\xa1\xb4" + "\xe2\x1f\x46\xd9\xc6\xcc\xa5\xe0" +
- "\xd3\xe5\xaa\xa7\x79\x26\x4e\xd2" + "\xc4\xc1\xe5\x0d\x3d\x01\x76\x70" + "\x29\xb6\x05\xbb\xba\xf8\x50\x2d" + "\xbb\xef\x66\x6e\xe2\xab\xc1\x73" + "\xf7\x8a\x48\xf2\x22\xb4\xd4\xef" + "\x75\xa5\x3b\x66\x02\x5d\x10\xe4" + "\x57\x94\xa6\x53\x8b\x0a\xb6\x7e" + "\x3b\x97\x45\xc9\x08\x00\x21\x62" +
- "\xfb\xab\x66\x4b\x86\x32\x8e\x1d" + "\x00\x09\x03\x59\xe5\x52\x6f\xd2" + "\x1a\x94\x84\x55\x43\xf6\xe3\x1e" + "\x58\x59\x9f\x56\x30\x37\x3b\x6d" + "\xa5\xdb\x89\x47\x2f\xa6\xf2\x9f" + "\xb7\xc9\xb5\x72\x15\xb8\xfc\x91" + "\x0e\x9a\x8f\x6c\x7d\xcb\x46\xf4" + "\xb5\xec\xb7\x39\xc1\x25\xf6\x48" +
- "\x12\x81\x44\x30\x77\x14\x7c\x7b" + "\x56\x86\xa3\xe4\xf1\x1a\xb5\x82" + "\x10\x50\x31\x2f\x8a\x02\xf2\x2b" + "\xd4\x8c\xa8\x6e\x1f\xa0\xa4\xc9" + "\x18\x58\x7e\x25\xd8\x95\x3e\xf6" + "\x16\x9b\x51\xb4\x10\xfa\x8e\xdd" + "\xbf\x10\xa9\x0d\xe0\x73\x89\xed" + "\xa9\xe4\x0f\x5c\x77\xd0\x49\xed" +
- "\x0c\x11\xa6\x6f\xa3\xf3\x6f\x51" + "\x1f\x56\x93\xfb\xb1\x1e\xfb\x74" + "\x2b\x52\x57\x84\x47\x90\x0c\x6c" + "\xc6\xbd\xb8\x6b\x04\x21\xd3\xcf" + "\x57\xad\x80\xcc\xa2\x84\x68\x2d" + "\x37\xb6\xa9\x86\x35\xfc\x27\x7c" + "\xcd\xe8\xf4\xad\xed\xba\x61\x34" + "\xf0\x42\x72\x61\x1a\x25\x56\x1d" +
- "\x94\xe0\x95\xa9\xd1\x46\x99\x71" + "\xd8\x04\x1e\xe5\xf6\x48\xe8\x65" + "\x13\x31\x1e\x6a\x00\x33\x2f\xe6" + "\x03\xe5\x1d\x50\xc1\xc7\x41\x15" + "\xde\xfa\xac\xf4\xfa\xc9\xaa\x4d" + "\x71\x0b\xcd\x44\x97\x58\x58\x0e" + "\x77\xcd\x51\x0a\x69\xd8\x4f\x54" + "\x6d\x01\x31\x00\xed\x20\xfc\x60" +
- "\x44\x44\xdb\x64\xaf\x12\xe7\x3f" + "\x80\xd4\xcd\xbe\x34\xd6\xe9\x19" + "\x8a\x97\x30\xa9\x47\xc0\x8b\xe0" + "\x33\x07\x28\xa1\xec\x24\xbf\x2d" + "\xb2\x06\xd7\x2c\x8c\xe3\x0a\x3c" + "\xb9\x17\x90\x35\x5b\x2a\x01\x5b" + "\xae\xf5\xe0\x72\x8c\xc3\x43\x39" + "\xa3\x6f\x17\x57\xea\x67\x61\x78" +
- "\xb1\x49\xea\xab\xb7\x9f\x97\xfa" + "\xc5\xc6\xe2\x10\x7d\xd2\xb1\xb4" + "\x7a\xde\xaf\x23\xc4\xc2\x61\xbd" + "\x58\xd3\x86\x97\xf8\x14\x66\xeb" + "\x59\x74\x6f\x7f\x6b\x81\x5d\x4a" + "\x7b\x0e\x36\x09\x4f\xa4\x31\xe4" + "\x4c\x91\x09\xc3\x32\xa0\x27\x8c" + "\xd8\xe3\xed\xca\x8a\xd6\xa5\xce" +
- "\x0e\xd8\x1d\x43\xa9\x11\x40\xb8" + "\xd9\x6c\x30\x73\xca\x7c\x7c\xeb" + "\x30\xb7\xb3\xd1\x29\xdd\xfa\x20" + "\xd3\xb3\x37\xfe\x5b\x8b\x85\x83" + "\x5c\x1d\x25\xb6\x93\xd1\x4c\xbf" + "\x52\xd9\x52\x13\xd3\x1f\xca\x1c" + "\x51\xc0\xfb\x90\xa4\x57\x61\xc6" + "\x36\x86\xb9\x89\x38\xa6\x90\x79" +
-
- "\xe1\xc0\xde\x87\x2a\x69\xaa\xe5" + "\x00\x9d\xb3\xf7\x8d\xed\x0d\x01" + "\xb5\xa0\xcf\x54\xc8\x80\x1b\x7b" + "\x28\xea\xf8\xa0\x76\xb8\xbe\x66" + "\x0e\xcd\x76\x34\x31\xf5\xd7\x50" + "\x49\x39\x8d\xb0\x65\x0e\x3d\xa6" + "\xc6\x9f\x47\x53\xa9\xee\x09\x1a" + "\x42\xe7\x99\xf4\x91\x98\xae\x82" +
- "\x66\xd8\xa7\x5c\x10\xb9\x58\xab" + "\x34\x3b\xdb\x3a\xe2\x67\x29\x58" + "\xbc\xc0\xea\xcc\x47\x44\xae\x89" + "\xf5\x6a\xf5\x7b\x7c\x66\x9c\x91" + "\xd7\xdc\xf5\x60\xb1\x17\xec\x9a" + "\xbc\xad\xca\xdd\x9f\x7b\x69\xec" + "\xf5\x67\x34\x46\x41\xf3\x98\x0b" + "\x2f\x13\x67\xa9\xf7\xf1\x87\xb1" +
- "\x18\xeb\x4a\x21\x1d\x7a\xfe\x90" + "\xf7\x32\x14\x74\x3c\xaf\x06\x15" + "\xc4\xa0\x91\xe5\xf9\x65\x55\xbb" + "\xc3\x1b\x4f\xb4\x77\x1a\xd4\x10" + "\x96\xde\x4b\xa8\xe4\x65\x9d\xa0" + "\x1c\x6a\x0a\xf2\xd8\x60\xf0\x42" + "\xe7\x9c\x7f\xf2\xfd\x3b\x2a\x65" + "\x9f\x73\x3d\x3b\x5c\xb6\xbd\xb6" +
- "\x9f\xae\x7f\xec\xb6\xdc\x5d\xeb" + "\x5a\x6e\xb6\xef\x14\x27\x5f\x99" + "\x52\x5d\x44\x69\x8e\x5d\xe9\xde" + "\x20\x76\xe2\x09\x46\x2d\x6c\x1b" + "\x16\xd7\x29\x81\x31\x1c\x62\x32" + "\xaa\xc1\x58\x09\xf1\x09\x39\xb0" + "\x63\xaf\xf4\x1a\xf9\x8e\x46\x8c" + "\xf6\xcd\xa5\xfb\x9f\x42\x2c\x16" +
- "\x71\x93\x3b\x75\x43\x23\x68\x2f" + "\xd7\x9c\x1f\x5f\x5a\xb4\xca\x29" + "\x96\xdb\x45\xb2\xab\x23\x16\x57" + "\x99\x99\xd7\x3f\x09\xdb\x07\xc5" + "\x32\x6c\x03\xaf\x52\xf6\x2e\x4e" + "\x5c\x8e\x01\x05\x78\xcc\xf0\x86" + "\x50\xe3\x8b\xab\xd4\x73\x0a\xc1" + "\x27\x63\x82\x7e\x97\xb3\x19\x65" +
- "\xf7\x3d\x05\x9c\xef\x5e\xcb\xe8" + "\x6f\xea\x00\xb3\x37\x5b\xe2\x8d" + "\xfb\xcf\x49\xc8\x92\xfa\x03\xdb" + "\xbb\x69\x41\xe8\xa7\x43\x2e\x24" + "\x8e\x95\x6f\xdd\xf4\x51\xfa\xe4" + "\x8d\x5a\x44\xf4\x7f\xa7\x25\x69" + "\x49\x89\x0d\xe9\x50\x2a\xe7\xe6" + "\x90\x63\x1f\x2b\xe3\x48\x66\xc6" +
- "\x0c\x46\x3e\x17\x57\x19\xab\xb2" + "\x90\x45\x70\x30\x75\xce\xbb\x1b" + "\x62\x71\x1c\xdb\xbd\x0d\xa9\xc0" + "\x5d\xd6\xcd\x15\x9e\x39\x5e\x50" + "\xb7\x7a\x79\x57\xcb\x4d\x43\x68" + "\xe8\xa8\x2c\x6a\xba\x35\xad\x60" + "\xc1\x36\x33\xde\xe0\xb1\xfd\x4b" + "\x15\x90\xb3\xd8\xeb\x99\xef\xbb" +
- "\xec\xeb\x11\x17\xf3\x96\x3b\x6c" + "\xc4\xfd\x98\xce\x1f\x0f\xa4\x2d" + "\x1f\x41\xb4\x57\xd3\x74\x97\xb9" + "\xb6\x5b\xb6\x15\xf4\xbd\xc8\x87" + "\x2d\xf1\xee\xc2\xe3\x89\x3a\xda" + "\xf3\x71\x74\x3c\x9b\xbb\x95\xde" + "\x94\xc5\x12\xd8\x5b\x22\x0f\x60" + "\x6b\xa5\x75\x2b\x5d\x7c\x90\x54" +
- "\x35\x0e\xb6\x8d\xf0\xc5\x3c\xa9" + "\x19\x33\x83\xfa\xd6\x3c\x3e\x74" + "\xc9\x83\x16\xf8\x41\x5c\xad\x7d" + "\x7e\x10\x34\x9c\xd9\xe7\xc1\x70" + "\x07\x09\xbe\xa6\x39\x4a\xdc\x0e" + "\xd3\xb7\xd0\x86\x35\x70\xd4\x36" + "\x60\xfa\x2b\x27\x03\xda\x76\x8c" + "\x14\xa4\x08\x0f\xea\x07\x4a\x0b" +
- "\x53\xdd\xc1\x45\x29\x4d\x9e\x69" + "\xb5\xeb\x1d\x23\x98\x58\xdc\xca" + "\xe0\x00\x7f\xa7\xc7\xfc\x49\xdf" + "\x0e\x5a\x3e\xa7\xbf\x7b\x05\x93" + "\xd1\x4c\x7a\x02\xcd\x7e\x8b\x2f" + "\x1a\x01\x14\xc6\xb3\x34\x47\x11" + "\x68\x7c\x67\x67\xb7\x1d\xa0\xe7" + "\x4f\x3f\x27\x7e\x5e\xbe\xd9\x89" +
- "\xef\x08\x98\x08\x2e\xcb\x25\xd2" + "\x07\x41\x9e\xd5\x7d\xa2\xf7\xf1" + "\xc9\xb9\x11\x82\x61\xc7\xaf\x53" + "\x59\x91\x81\xe6\x67\xbc\x61\x03" + "\x26\x14\x07\x7f\x0b\x5d\x86\x2a" + "\x67\x25\x07\xe7\x10\x18\x3c\x6a" + "\xbd\xca\x6b\x0d\x1e\xca\x3b\x3e" + "\xbc\x91\x85\x40\xc1\x2b\xb0\xa1" +
- "\x39\xa2\xfb\x31\x59\xee\xde\xe0" + "\xd1\x91\xbd\x98\xd3\x24\x74\xf4" + "\x1d\x3c\x1a\x07\xf4\x86\x88\x0f" + "\x3b\x23\x19\xa8\xe8\x41\x7d\x3f" + "\x98\xb9\x6e\xcf\xc2\x23\x86\x70" + "\x7f\x28\x9a\x60\xaf\x49\xbb\x86" + "\x62\x07\xc9\x63\x49\xb2\x2b\x94" + "\x4b\x65\xa9\x55\xa5\xee\xf6\x0e" +
- "\xfe\xde\xf5\x36\x72\x2d\x6d\x5f" + "\x76\x91\xf9\x56\xdc\x22\x99\xfa" + "\xc7\xe0\x8c\xf7\xce\x5e\x8c\x6c" + "\x5e\xb5\x09\xbe\x9d\x58\x44\x7b" + "\x70\x37\xa8\x9e\xca\x3b\x1b\xe1" + "\x47\x15\xb7\x2a\x7f\x2c\xfa\xd7" + "\xc0\xdc\x1d\x2a\xfa\xd6\x3d\x2a" + "\x07\x77\x7b\x5a\x30\xb4\xac\x09" +
- "\x57\x4e\x9d\x64\x2e\x4a\xdd\x4a" + "\x6e\x52\x17\x19\xb0\xa2\x53\xcd" + "\xc4\x4a\xb4\x20\x30\x23\x26\xc5" + "\x1d\xc3\xa2\xba\x6a\x74\x28\x40" + "\x4c\x1d\x29\x64\x90\x83\x31\x51" + "\x09\xd9\x5a\xee\x51\xf1\x48\xbf" + "\x81\x56\x18\x7b\x59\x7f\xe5\xcc" + "\x42\xd4\x54\x48\xb0\xc1\x3a\x7c" +
- "\x71\xc1\x93\xc0\xc3\x7d\x58\x65" + "\x65\x2b\xf4\x24\x24\xcb\x7a\xae" + "\xcb\x96\x59\x95\xdb\x8a\x33\x5a" + "\x1b\xf9\x51\x60\x75\x56\xe6\xc8" + "\xb1\xd0\xb8\x28\xba\x1f\x71\x66" + "\x90\x0a\xc1\xb6\x37\x41\xd7\x15" + "\x80\x2a\x23\x3a\xeb\xd7\xcd\x70" + "\x24\xed\x91\x61\x7f\xf0\xe2\xc9" +
- "\xc0\x88\x95\xf7\xb6\x1d\x0d\xa8" + "\xcc\x68\x57\xb5\x69\xfc\x52\xfa" + "\x8a\x43\x54\x7f\xae\xf1\x4d\x0b" + "\x4f\x6a\xb4\xf9\xa7\xd1\xad\x0c" + "\x6f\xdd\x03\x18\xb3\xa6\x0e\xb4" + "\x35\xae\xea\x55\xa5\x4f\x8e\x48" + "\x16\x4e\x2e\x38\x55\x7d\x04\x9f" + "\x98\x0c\x6e\x2f\xe0\xb7\xb5\xc9" +
- "\x49\x26\x76\x95\xd3\xd2\x1b\x6b" + "\xf6\xa3\xae\xc7\xe7\x4e\x60\xa9" + "\x96\xf8\xc6\x6d\x27\xff\x46\x36" + "\xd1\xba\x60\x28\xf5\xe7\xf0\x9b" + "\x92\x4b\xb4\x7c\x21\xc8\x92\x2d" + "\x82\xc1\xa9\xae\x63\xce\xf5\xa2" + "\xfd\xa5\x54\x91\xb1\xaf\xa2\xd0" + "\xa6\x1d\x80\x95\x4c\x47\x2e\x48" +
- "\x4b\xc2\x11\xb6\xd0\x72\x99\xc1" + "\x51\xf3\xa8\x60\x65\x8e\x46\x1d" + "\x21\x64\xcf\x7b\x69\x80\x75\xeb" + "\x91\xc4\xfb\x88\xee\xd0\x9d\xec" + "\x32\x2e\x6c\x95\xbf\xd2\x59\x5b" + "\x4e\xf9\xdd\xdc\x64\x68\xdc\x73" + "\x65\x76\xee\xbc\x21\x23\x5e\xfd" + "\xc4\x06\x9a\x5e\xef\xf8\xb4\xa7" +
- "\x55\xf8\x80\x72\xdd\x18\xa9\xfb" + "\x88\xc6\xae\x8b\x60\xc2\xaa\xbb" + "\x42\x0f\x40\x33\x0f\xf0\xb3\xa3" + "\xe4\xe6\xf2\x66\x29\xba\x2d\x3d" + "\x75\x93\x50\x98\x94\x1a\xf7\xb6" + "\xcc\x23\xa4\xce\x1f\x03\x33\x8f" + "\xfb\xe6\x07\x48\xd0\x8d\x9b\x00" + "\x4c\x95\xdb\x5c\xe5\xcf\x63\x51" +
- "\xe8\xc6\x41\xcf\x17\x8f\xcc\x03" + "\x5c\x92\x7b\x03\x2a\x3c\xf0\xf1" + "\x7c\x42\xd2\x66\xcc\x19\x9c\xc3" + "\xe4\x18\x6c\x7b\xba\x24\x3d\x82" + "\x4f\x0b\x1f\x90\x13\x90\xef\x32" + "\x2e\x1c\x94\xf8\xf1\x60\x43\x68" + "\x2e\x09\x28\x2c\x52\xff\xba\x0e" + "\x2f\x93\x6c\x25\xe3\xe4\x91\x78" +
- "\x3d\x5e\x44\xac\x19\x43\x26\x51" + "\x81\x43\xa7\x8e\xe7\x32\x34\x55" + "\x0a\xc5\xe9\x67\x69\xaa\xee\xe6" + "\xc7\x28\xe6\x62\x84\xd2\xce\x27" + "\x57\xfa\x4a\x7a\x75\xd3\x96\x3f" + "\x50\xc1\x84\xe4\xc3\x14\x0a\xde" + "\x23\x99\xbd\x38\xeb\x24\x4a\x36" + "\x22\x74\x17\xe5\xa0\x8d\xf1\x1d" +
- "\x9b\x8a\xd3\xd8\x82\x8f\x4e\x17" + "\x91\x13\xde\xe7\x00\xc6\x97\x2e" + "\xdd\x75\xc1\xa1\x50\x98\x70\xc5" + "\x35\x50\xae\x32\xa0\x41\x90\x96" + "\x6b\x08\xa2\x76\x3b\x53\xfd\xcb" + "\xfe\xe8\xc2\xd7\x1b\xa7\xbb\xd6" + "\x67\xfb\x9d\x09\xe6\x8e\xd5\xb2" + "\xd9\x85\x4a\x06\x2d\x34\x8b\x3a" +
- "\xe3\x9b\x2f\x52\x49\x76\xc0\x3b" + "\xa8\x49\x1f\xdf\x5b\x07\x0c\x69" + "\x42\xec\x54\x38\xe8\xae\xe1\x80" + "\xc7\x9d\x68\x17\x44\xbf\x7d\x2a" + "\x78\x40\xaf\x3f\x0e\xfc\x04\xc0" + "\x2c\x86\x11\xdf\x9e\x2e\xf0\xb2" + "\xb3\xb7\xa1\xa0\x0f\x5e\x0a\xf1" + "\x80\xec\x36\x89\x23\xa6\xac\x30" +
- "\x9a\x0d\xf4\x02\x05\xbf\x3c\xf8" + "\x4d\x8a\x31\x2c\x68\xc4\x81\x46" + "\x74\x26\x9c\x0e\x18\x56\x57\x98" + "\x2e\x09\x47\x18\x46\xd0\x79\xbe" + "\xe0\x01\xbd\x78\x0a\x48\x1e\xaf" + "\xb9\x1d\xa5\x72\xe4\x59\xd3\x6d" + "\xb6\xba\xaf\xe3\x21\x38\xce\x62" + "\x99\x31\x73\x17\xb6\xe5\xce\xc5" +
- "\xbb\x9f\xfd\x6f\xd4\x30\x8b\xe0" + "\xb7\x10\xc6\x36\x99\xc6\x5b\x6e" + "\xcf\x62\xe2\x9c\xf2\xcf\x43\xf3" + "\xc1\x14\xb9\x68\x35\x4e\x2e\xca" + "\xc5\x36\xde\x16\xc0\x64\x1d\x01" + "\x29\xb8\xe2\x42\xdd\x0f\xb1\xe0" + "\xf8\xaa\x85\x66\x81\x29\x94\x78" + "\x97\xde\x0e\x23\x08\x17\x51\xe7" +
- "\xf8\x2b\x92\x3b\xfc\xd8\x1e\x67" + "\x33\xb1\x29\x4c\xa0\xc0\xd8\xe4" + "\xc4\x99\x6e\x3b\x39\x12\xeb\x87" + "\xba\xbe\x93\x87\x4c\x97\xf3\xaf" + "\x9b\xdf\x18\x2c\x05\x94\x74\x03" + "\x39\x71\x00\x91\x93\xa2\xc3\xc5" + "\x95\x0b\x7a\xe3\x4f\x23\x77\x6a" + "\x6b\xc9\x61\xb6\x21\x9a\xc2\x02" +
- "\x61\xcf\x1e\x14\xd6\xf1\xaa\xc3" + "\x53\x2f\xb2\x3b\x9e\x50\x95\x91" + "\x57\x13\xd5\x22\x04\x74\x59\x29" + "\x60\xed\x7b\x53\x22\x38\x08\x1b" + "\xf0\x89\x72\xe0\x35\x6e\x7d\xcd" + "\xff\x6e\xd8\x6d\x8c\xc4\x94\x1f" + "\xfa\x9c\x0f\xeb\x82\x1f\xbb\xc8" + "\x7d\xb9\x2e\x1b\xe6\xb7\xe0\x9e" +
- "\x31\x4e\xd7\x34\x2e\xfe\x52\x5a" + "\xb6\x9a\xf7\x3b\x10\xc3\x52\xa3" + "\x8f\xeb\xfe\xab\x5a\x6c\xff\x97" + "\x05\x73\xc9\xf5\xef\x8f\xbe\xbf" + "\x08\x46\x90\xa7\xe6\x1c\x08\xd6" + "\x49\xa2\xfc\xc4\x3a\x2f\x81\x1f" + "\x00\xe2\xe5\xb9\x9a\xbc\x24\x9b" + "\xe8\x2e\x01\x38\x67\x2c\x02\x91" +
- "\xa1\x13\xa7\x30\x5d\x9c\x3d\xe8" + "\x93\x0f\xef\x84\xf0\xe3\x76\x48" + "\x28\xf9\xfb\xc1\x29\x70\x77\xc9" + "\xa4\xd2\xe7\xbc\xb3\x6b\x7a\xef" + "\x59\xa6\xa2\xdf\x28\x72\x06\xb8" + "\x8f\xa4\x77\xd8\x98\x33\xcd\xd5" + "\x3f\x0f\x5d\x02\x8f\xfd\xa4\xbe" + "\x2b\x7c\xae\x2e\x35\x2e\x7d\xd6" +
- "\x94\x43\x5f\xcc\xd7\xe7\x4d\x18" + "\x42\xe1\x36\x45\x5c\x1b\x55\xb5" + "\x0a\xa6\x4a\xd3\x12\xb2\x89\x2e" + "\xd5\x51\x00\xf5\xea\x6f\xa9\x14" + "\x0b\xbb\x12\x0d\x74\xef\x21\x4e" + "\x7e\x67\xb9\x60\x20\xf0\x22\xc5" + "\x1d\x73\xf7\x2d\x67\xe4\x12\x8b" + "\x31\x6d\x32\x7b\x82\x03\xf8\x39" +
- "\x94\x4a\x02\x39\x0c\x63\xb8\xdf" + "\x52\x94\x31\x97\xa8\x96\xcb\xaa" + "\x7c\x86\xa3\xed\x61\x39\x8a\xd6" + "\xca\xff\xc4\x77\xb0\xe2\x58\x0c" + "\xfa\x19\xa9\x4d\x63\x5d\x54\x3d" + "\x89\x22\x5e\xf1\x9a\xb6\x79\xef" + "\x10\xab\x8b\x80\x3d\x3d\xbc\x54" + "\x37\x2c\xf8\x45\x07\x30\xab\xc8" +
- "\x8a\x65\x4a\x7c\xb6\x38\x27\xc1" + "\x82\x21\xe7\x40\x39\x76\xc4\xb3" + "\x4f\xe4\x98\x87\x46\xbe\x77\x3b" + "\x5f\xf8\xa7\x17\xf2\x7d\x04\xdc" + "\x2d\xd9\x59\x5e\xc5\xd4\x39\x24" + "\x8d\x4d\xe6\xe8\x75\xa4\xdc\xce" + "\x16\x9b\xca\x87\x0d\xcd\x24\xa7" + "\xfe\x0d\x54\xa5\x59\xfd\xe4\x35" +
-
- "\x7a\x46\x29\x3a\x4f\x34\x94\x98" + "\x6d\xba\x1e\xc5\x49\xe9\x81\xde" + "\xf2\xc2\xe5\xa5\x6b\x06\xea\xda" + "\xb3\xc7\xc8\x08\x14\xa6\xc8\x3f" + "\x9f\xde\xd0\x06\x8f\xf8\xdf\x7a" + "\x0a\xce\x75\x3b\xf5\x1c\xc1\xbb" + "\xd5\x87\xbc\xfb\xcc\x7a\xbb\x9f" + "\xe2\xfd\xad\x7b\x26\x8e\x45\xa1" +
- "\x56\xc2\x39\xe0\x68\x36\xb4\x1c" + "\x5d\xfd\x17\x7c\x8b\xfb\x26\x5f" + "\x2b\x06\xaa\x79\xaf\x26\xe4\xee" + "\x04\xbf\x8f\xd7\xd0\x02\x20\x07" + "\xe3\xb7\x4f\xe8\x37\xa2\x9c\x4c" + "\x3d\x13\x82\x0c\xa1\xd8\x01\xb4" + "\x81\x41\x7e\x6d\x92\x25\xa5\xaa" + "\x52\xb1\xdb\x73\x33\x08\x43\xe9" +
- "\x83\xc9\xe7\x6e\x1e\xad\x5f\x2f" + "\xf5\x28\x13\xb4\x7c\x9d\x0f\xeb" + "\xf7\xd5\x78\x1d\x44\x8b\xa6\x9b" + "\x6f\x72\xbc\x35\x9e\x3b\x6b\xa0" + "\xf1\x1f\x3e\x59\x55\x02\x55\xa2" + "\x15\xc1\xbe\xdf\x3d\xd4\x2d\x55" + "\x46\xf0\xa8\xbb\xab\xa7\x48\x2c" + "\x33\xf1\x0b\xad\xa3\x56\xfc\xd4" +
- "\x9a\x31\x24\xbe\x31\xda\x2d\xf9" + "\xe7\xa8\x95\xe0\x8b\xd2\xf7\x03" + "\x85\x21\x78\x98\x40\xe8\x2f\xa5" + "\xbc\x4d\xc2\x29\xfe\xda\x6d\x27" + "\xeb\x64\x7a\x1d\x96\x54\xcd\x80" + "\x42\xbe\x1d\x7f\x89\x08\x36\xe4" + "\xd5\xd2\x38\x84\x77\xa8\x81\x2f" + "\x36\x90\x16\x85\xa8\x52\x4d\x7e" +
- "\xd1\xb5\x04\xba\xef\x1c\xf2\x62" + "\x52\x73\x4c\x22\x07\x27\x44\x9a" + "\x1f\x17\xc6\x33\x6c\x96\x07\xbf" + "\xb0\x16\x08\x1e\x91\xa8\x7b\xdb" + "\xa9\x45\x37\x03\x59\xea\x6f\x30" + "\x67\x8f\xa7\xc0\xe0\xf7\xac\x2a" + "\xf9\x1b\x25\xad\x83\x38\xaa\xb5" + "\x86\x70\xbd\x26\xe9\xed\x5a\x34" +
- "\x5d\x71\x59\x1d\xb1\xd5\xe3\x19" + "\x3e\x98\x88\xd7\x62\xa7\xea\xc7" + "\x48\xf2\xf1\xab\xb0\x30\xa7\xe5" + "\x83\xfd\xe3\xfa\x84\x80\xab\xfb" + "\x2f\x5b\x76\x53\x21\x0d\xe5\x65" + "\x3d\x7f\x12\xfa\x83\xe0\xd4\xbd" + "\x10\x1b\x7b\x39\x74\xc0\xf3\x9c" + "\xd3\x9f\xb5\xb1\x0c\x09\xf8\x59" +
- "\x10\x9f\x11\x98\x7d\xe1\x1d\xdc" + "\xa6\x36\x8c\x48\x5d\x3c\x35\x74" + "\xdf\x23\x8e\x3d\x3a\xf3\xaa\x14" + "\x93\xf5\xba\x78\xc0\x75\xe0\x31" + "\x3c\xca\xd1\x46\x3a\xa0\x7c\x0f" + "\xc7\x60\xb6\x47\xac\xe3\xc5\x99" + "\x59\x2e\xfe\x88\x13\x24\xd0\x70" + "\x05\xc0\x7e\x2a\xe1\x6b\x9a\x2e" +
- "\x8f\xaa\x5f\x61\x9d\xfd\x15\x7b" + "\xed\x54\x85\x96\x40\xeb\xa1\x8f" + "\x82\x48\xa4\x7a\x7e\x44\xb4\x7b" + "\x32\xff\x9f\x02\xd1\xd0\xb2\x2b" + "\x2f\x6d\xaa\x6c\x64\x2a\x5e\x07" + "\x1b\x35\xe7\x22\xde\x79\xb8\x8e" + "\x62\x6c\x50\x9a\x4e\x62\xd5\xbc" + "\xdc\x24\x7e\xa8\xf0\xae\x8e\x21" +
- "\x6f\xbd\x1f\x24\x95\x96\x44\xac" + "\x23\x12\x1c\x08\x70\xb1\xc9\x67" + "\x6f\xac\x6a\xb5\x21\x8f\x86\x16" + "\x21\xb7\xbc\xf8\xa3\x8f\xbd\x34" + "\x76\x1c\x69\xb6\x33\xbd\xb6\x06" + "\x73\x79\x1a\x38\x66\x47\x92\x6c" + "\xdb\x78\x40\xa5\x4c\x44\x12\x6a" + "\xcc\x51\x10\x6d\xa9\x91\x2e\xd0" +
- "\x35\xfa\xdd\x44\x47\x68\xe5\x37" + "\x47\xf7\xb3\xda\xc5\xc5\xcf\x9c" + "\xf4\x6c\xe9\x1e\x3f\xdf\xc1\x9a" + "\x8f\x0b\x48\x3b\xa1\x71\x05\x0c" + "\x3c\x7b\x3a\x4b\xd5\xb3\xbe\x2f" + "\x99\xbb\xcd\x5d\x69\x36\xc0\x35" + "\x3a\x5b\x41\xb2\xdc\xf5\xa0\x52" + "\x9a\xed\x13\x44\xb4\x59\x77\xd5" +
- "\xf8\xd3\x33\x0b\xc0\x79\x73\x07" + "\x09\xe4\x64\x70\xc6\x83\x18\x42" + "\xf6\xc8\x29\x6c\xd7\x73\x08\x2d" + "\xc8\xc0\x74\xd2\xa3\x33\xa4\xbf" + "\x1e\x89\xa5\x23\x8f\x77\xdc\x56" + "\x04\xde\xe2\x35\x65\xbf\x63\xd6" + "\xce\x17\xb5\x5d\x48\xdb\x8f\x48" + "\xc2\x26\xb2\x19\x5e\xa5\xbb\x00" +
- "\xc5\xa2\x30\x3d\xd8\x47\xe6\x1f" + "\xdc\x81\x8a\xf7\x7e\xf7\x57\x08" + "\x9b\x4a\x1a\x13\x34\xa3\xd5\x11" + "\xf5\x93\xd3\x29\xf9\x4a\xa9\xc0" + "\x1a\xec\xa6\xda\x0b\x5c\x3a\xbc" + "\xed\xd7\xd2\x88\x93\xe4\x9f\xba" + "\x97\x47\x61\xbb\xb4\x35\x43\xbb" + "\x33\x35\xf8\x72\x68\x4d\x1c\x99" +
- "\xb6\x8f\x05\x8a\xe7\xee\xbb\xed" + "\x1a\x12\x09\xfb\xdc\x9d\xd1\xb9" + "\xce\xdd\x4d\xd3\x5b\xb4\x1b\xa4" + "\xc4\x4b\x96\x00\xb9\x80\xbc\x2d" + "\x54\xb6\x6c\x1d\x7d\x13\xd9\x4e" + "\xc5\x01\x3d\x48\xdb\x16\x90\x1b" + "\x2e\xe2\x28\x65\xbc\x01\xc5\x5f" + "\x6b\x64\xad\x6c\x81\xf8\xd2\xb2" +
- "\xb3\x1c\xf0\xd2\x28\x8c\x25\x53" + "\xb1\xb0\x5d\xd7\xa3\xea\xd6\x93" + "\xb4\x0d\x7d\xe8\x0d\x2b\x9a\x41" + "\x93\x84\xfe\xd8\x03\x8f\xe4\xa1" + "\x3a\xb2\x08\xc5\xf6\xfa\x47\xf7" + "\x49\x35\xd5\x35\x1a\x57\x37\xf1" + "\x38\xb8\xf9\xfc\xe2\x58\x5e\x9f" + "\xf5\x3c\xfd\xa7\xee\x6c\x18\xc7" +
- "\x39\xad\x6b\x28\x2f\xfb\x76\x5e" + "\xe2\xd1\xca\x9d\xe3\xef\xd9\xba" + "\x04\xe9\xc7\xed\x90\x51\xe7\x60" + "\xa5\xb5\xec\x0f\x3e\x06\x6f\x6a" + "\xc3\xac\xd8\xae\x85\xed\x50\x51" + "\x6c\xaf\x20\x6d\xbc\xcf\x6c\xb5" + "\xfa\xdb\x69\x2c\x98\x1e\x0d\x7e" + "\xa9\x10\x7e\x7c\x8a\x62\xf5\xab" +
- "\xd3\xa1\x78\xe9\xce\x68\xb8\x77" + "\x04\x2d\xb9\x7a\x33\x8b\xa6\xe3" + "\x62\xb8\xa5\x87\x94\x97\x02\x51" + "\x1d\xd4\x61\x3a\xc3\x06\x06\x5f" + "\xf1\x26\x93\x6f\x27\xbe\x14\x28" + "\x2e\x3c\xfe\xc6\x14\x1c\x52\x2f" + "\x51\x73\xdf\xac\x7d\x4d\x46\x17" + "\x44\x7e\x7f\x77\xd3\xf9\xf5\x10" +
- "\xab\xa2\x08\x74\x19\x64\x21\x1d" + "\x6a\x91\x28\x59\x18\xd5\x55\xae" + "\xea\x5e\x16\xf3\x4a\x68\x75\xdf" + "\x59\xef\x4e\xd8\xd5\x64\x83\x53" + "\x1a\x3b\x56\x70\x15\x20\x4e\xb5" + "\xff\xef\x4c\x6b\xa7\xbb\xd9\x74" + "\xdc\x82\x06\x7a\xd8\xcb\xbe\xfc" + "\x6c\x11\x93\xf1\x02\xa4\x00\x0e" +
- "\x7d\xb3\x9f\x26\x6b\x61\x8e\xce" + "\xe5\x2d\xe6\x7d\x04\x38\xf7\xaa" + "\x53\x41\xdd\x4f\x75\x11\xa1\xab" + "\x9b\xb4\x70\x37\xba\x59\x57\x51" + "\x61\x3a\x42\xaa\xf8\xeb\x09\x8b" + "\x92\xfb\x41\xcd\xa1\x45\x22\x59" + "\x36\x89\x4c\x9b\xc1\x8e\xba\x1c" + "\x0e\x71\x36\xaf\xe3\x91\x7e\xa8" +
- "\x16\xc4\x9f\x84\x85\x89\xf6\x65" + "\x3c\xa7\xba\xcd\x34\xa9\x03\x3c" + "\x47\x66\xcb\xbf\x1b\x31\x2f\x11" + "\xcd\x93\x4e\xde\x40\x13\xc1\x69" + "\x7b\x53\xdb\x66\xb9\x58\x24\xbd" + "\xe7\x07\x5b\x88\x18\xb0\x74\xf9" + "\x32\xd3\xc8\x70\xa5\x45\xb1\x5d" + "\x7b\x83\x9b\x54\xd1\xd0\xfd\x30" +
- "\xe3\xa2\x34\x3d\xe4\x4c\xd8\x1f" + "\x61\x5d\x3b\xb4\xce\x59\x37\xee" + "\xc7\x86\x91\x61\x8c\xc7\x5b\x89" + "\x5a\x72\xb9\xcb\x09\x38\x9c\xf1" + "\x1f\x4b\x74\xde\xaa\x21\xbe\xc0" + "\x6b\x05\xf8\x60\xb0\x22\xd2\xa7" + "\x11\xfe\x3e\xb2\x57\x61\xbe\x74" + "\x53\x82\xd6\x0c\x4f\x2b\xab\x6f" +
- "\xb4\x58\x23\x51\x73\x1d\x5c\x3e" + "\xc9\x99\xbb\x30\xb2\x42\x57\xcb" + "\x1a\x03\x2d\x3c\xa8\x2f\x2e\x4a" + "\xb8\x78\x98\xfb\x2b\xc9\x1b\x37" + "\x6c\x65\x75\x82\x9c\x1f\xa7\x1e" + "\xa1\x00\x03\x1c\xa2\x94\xf7\x14" + "\xe5\x54\xea\x26\x98\xe7\xea\x08" + "\xc6\x54\x1a\x17\xe5\x54\x58\xcf" +
- "\x25\xd7\xf1\x4b\x5f\xea\x33\xad" + "\x0f\x95\x6c\x4f\xe2\x8e\x1d\x9c" + "\x06\xaf\x77\xa3\x8a\xe7\x4e\x54" + "\xe1\x13\xa1\x94\xbb\x89\xf4\x54" + "\xe8\xb7\x2f\x99\x34\xd6\x11\x8f" + "\x47\x43\xa4\xa2\xaa\xa7\x69\x01" + "\x00\x0e\x02\x95\xaf\xd4\x49\x1d" + "\x0b\x12\x8e\xe0\x22\x57\x94\x95" +
- "\x86\x38\xba\xb7\xb3\xfb\x0a\x28" + "\xa8\x34\x89\x36\x3e\x3a\x80\x08" + "\xab\x71\xf6\x31\x65\xdf\x80\xf9" + "\x91\x47\x72\x1a\xea\x4a\x89\x90" + "\x50\xa3\x1d\x8d\xa9\x66\x5b\x54" + "\xa5\x53\x13\x41\xbf\xfb\xf4\x9d" + "\x8a\x08\x98\xa3\x3c\x74\x52\x15" + "\x17\x57\x2d\xb8\xde\x4c\xc1\xd1" +
- "\x82\x22\xd3\xa4\x78\x38\xe3\xb6" + "\xe7\x0a\x02\x48\x9d\x02\x6e\xe3" + "\x50\xb7\xa9\x37\xfb\x47\x58\xe0" + "\x19\x38\x9e\xb2\x2c\x81\x76\xf8" + "\xf0\x17\x3a\xd2\x8e\x13\xad\x84" + "\x0e\x95\xb3\xf0\x80\x44\x7b\x6d" + "\xe0\x7a\xd6\x2f\xf4\xae\xa8\xdf" + "\xf6\x3a\x33\x52\x24\xea\x3e\x8d" +
- "\x83\xec\xc5\xf5\xfd\x3a\x8d\xb2" + "\xad\x9f\x04\x91\xc1\xf6\x6a\x8d" + "\x1a\x1e\xbe\xff\xff\x64\x79\x41" + "\x0a\x79\x1c\xf5\xea\x9e\xce\xba" + "\x79\x29\x0f\xb2\x36\x22\x02\x42" + "\x01\x38\x5d\x76\x29\xb7\x05\x6b" + "\xe7\xe3\x6d\x6d\x00\xe2\x0e\xbe" + "\x3a\xaf\x01\x1e\x01\xd5\x6e\xb9" +
- "\xcc\x5a\x5d\xb1\x75\x20\x05\x0d" + "\xc4\x5b\x81\xbd\x9f\xc7\xd9\xc6" + "\xf2\x6c\xa3\xdf\x88\xfd\xca\x8d" + "\x70\x90\xaa\x38\xe2\xcb\x8c\x90" + "\xce\xaf\x35\xba\xc4\x22\x87\x63" + "\x0b\xbf\x6a\xfd\xb0\xa8\x3d\x5a" + "\xc1\x35\xc3\xc9\x2c\x25\xce\x2d" + "\x9b\x79\xaa\x65\xde\xf0\xe7\x84" +
- "\x62\xbc\xed\xe0\xec\x62\x87\xef" + "\xfb\x73\x27\x85\x28\x98\x44\x33" + "\x85\x38\xae\xc3\xf3\x90\x9b\x2c" + "\xb2\x56\x1e\x73\x12\x18\x19\xd8" + "\xf0\x31\x68\x73\x95\x7e\x5d\x20" + "\x5d\xc1\x41\xd6\x48\x8d\x81\xc3" + "\x7c\x15\x3e\xf4\x39\x38\xb6\xc6" + "\xf0\x51\xad\x36\x47\x04\x16\x55" +
- "\xcb\x72\x9a\xb9\x22\xa5\x01\x21" + "\x16\x80\x61\x87\x67\x6e\xde\x06" + "\x3e\x65\xf3\xe6\xcd\xc7\xf8\x5f" + "\x4a\x75\xa6\xc7\xb5\x1a\x82\x0a" + "\xa2\xb5\xb0\x7c\x2b\xa5\x3f\x7e" + "\x90\x87\x04\xc9\x1c\x12\xfb\xa7" + "\x3a\x05\xce\x06\x20\x50\x72\x1a" + "\xb0\x29\xe9\x04\x1f\xa3\x90\xb4" +
- "\x6e\x7e\x40\xbc\x19\x77\xbb\x70" + "\x41\xeb\x4c\xd8\xef\x28\x13\x23" + "\x20\xbb\x04\xc1\x1f\x6a\xca\x8b" + "\x71\x90\x0b\x28\x25\xe4\xf4\xd6" + "\x82\x6a\x89\x92\xa2\x95\x1b\xb4" + "\x67\xdf\x34\xfa\x35\xf4\x5c\x73" + "\x69\xd7\xd6\xd9\x08\x1a\x33\xbc" + "\x7e\x74\x82\x26\x05\x86\x97\x57" +
- "\xad\x61\xdd\x62\x7d\xe4\x7b\xe1" + "\x71\x13\xe0\x6b\x1c\x96\x1a\x78" + "\xba\xcb\xe3\xda\xd3\xbf\x63\x10" + "\xba\xc9\x73\x7f\x06\x74\x64\x35" + "\x29\xa1\x36\x27\x7b\x95\x0e\xf5" + "\x56\xf2\x13\xed\x02\x37\x31\xa6" + "\xc5\xfc\x19\x3a\x65\xee\x36\x94" + "\xb6\xc8\xa4\xe7\x29\xdb\x2b\xcf" +
- "\xbe\xb8\xf3\x87\x42\xf7\x8a\x69" + "\x1d\x59\xa1\xd1\x1a\x9d\x5d\x4f" + "\xe1\xac\xe4\x0f\x3c\xac\x0f\x54" + "\x7d\x4a\x89\xc6\x24\x9b\xa6\x83" + "\x46\xeb\x6f\xad\xee\x07\x5c\x93" + "\xfa\x25\xf3\x7f\x88\xbd\x2c\xe0" + "\x0b\x38\xc6\xbc\x9d\x8c\xf0\xe8" + "\xce\x45\xe0\xa6\x0f\xf4\x7f\x9c" +
- "\xd8\x5c\xf9\xc5\x44\x12\x6b\xb0" + "\xf4\x95\xab\xf4\xf0\x8a\x8c\xda" + "\x6d\x83\xe5\xb9\xc2\x59\xae\x1b" + "\xfc\xff\xcf\x3a\x7e\x1e\xd5\x07" + "\xda\xbc\xcc\xc2\x6a\x5e\xe1\x01" + "\xe0\xc3\x28\x85\x3f\x92\xc1\x3b" + "\xd4\xea\x9f\xa4\x77\x45\x32\x43" + "\x11\xa7\xa7\x2a\x84\xb8\xa1\x61" +
-
- "\x34\x3d\xe6\xb0\x31\xee\xe7\x4f" + "\xab\x4f\xe5\xa9\x72\x05\x60\xf4" + "\xa4\xb5\xe7\xd5\x34\x33\x49\xc0" + "\x31\x48\xd5\x06\x92\xfb\x89\x85" + "\x3a\x55\x83\x65\xcc\xf5\x70\xaa" + "\xe5\x49\x56\xe2\x4a\x09\x79\x08" + "\x52\x46\x04\x10\x07\x45\x90\xcc" + "\x4f\x1c\x54\x02\x6d\x69\xb0\xeb" +
- "\xa6\xe7\xde\xa2\x3e\x1a\x8c\x75" + "\x84\x22\x4b\x73\x3c\x2f\xde\xdc" + "\xad\xa6\xab\x4e\xd2\x45\xa4\xab" + "\xa7\xe0\xce\x76\x68\xf6\xaa\x35" + "\x9a\x04\xaa\xe5\xa9\x04\x0b\x7e" + "\x84\x3e\x10\x91\xad\x83\x40\xe7" + "\xc3\xec\xaf\x40\xce\x83\xb1\xbe" + "\x7a\x3f\x04\xea\x9f\xde\x89\x6b" +
- "\x35\x52\x37\x99\x03\x0e\x9f\xb9" + "\x70\x79\x91\xb9\x47\xc8\x14\x76" + "\x67\xc0\x4e\x52\xe9\x3c\xc9\xfe" + "\x20\x25\x12\x9b\xf8\x7b\x0e\xe4" + "\x74\x47\x4c\xee\x31\x06\x67\xb5" + "\x4c\x91\x04\x3b\x7a\x84\x03\x6f" + "\x26\xd2\x9d\xdc\x29\x94\x6e\xc9" + "\xf8\xc1\x57\x8c\x6c\x9b\x48\x43" +
- "\x66\xba\x67\xfe\x23\x9d\x29\x0e" + "\x34\x2f\xcf\x93\x60\x07\x45\x91" + "\x13\xf9\xfc\x97\xa9\x5e\x5b\xf4" + "\xda\xdd\xd7\x8b\x43\x08\xe0\x5b" + "\x4d\xf0\x3f\xd5\x05\x3e\x8c\x35" + "\xf7\x1e\xe9\x5d\xc3\xcd\x7c\xbf" + "\xa0\xc1\x9e\xb6\xbf\x4d\x68\xad" + "\x97\xd9\x1f\x80\xf2\x7c\x7e\x36" +
- "\xfb\x38\x23\xcc\x27\xd2\xff\x46" + "\x53\x61\xe2\x90\xa9\x6f\xff\x89" + "\x76\x00\x1a\x33\x79\x07\x57\xbe" + "\xaf\xf3\xe1\x06\xc5\x41\xd2\x43" + "\xa3\x62\x9b\xde\x7d\xb9\xcd\xfd" + "\xea\x30\xae\xa0\x84\xe9\x06\x6a" + "\x7d\xdf\xbd\x4f\x80\x16\xbf\xc9" + "\xc4\x63\x61\xd3\xa2\x71\x04\x17" +
- "\x5e\x65\x13\x31\xae\xa8\x5b\xff" + "\x80\x31\xb8\x57\x2b\x6e\x2c\xfa" + "\xbe\xea\xe0\x77\x19\x27\x48\x1c" + "\x97\xea\x7f\x33\x55\xc5\xf3\xf9" + "\xcb\x81\x25\xa4\x22\x70\x0f\x34" + "\xe3\x10\xf7\x18\xc2\x0b\xde\xe1" + "\xa8\x5a\x2e\xf6\xde\x0a\x64\xee" + "\x40\x89\x42\x49\x91\x38\xb2\x16" +
- "\xc3\x0c\x95\x55\xe4\x19\x16\x36" + "\xb8\x6b\xb6\x56\x5c\x66\x1d\xc7" + "\x84\x6d\xac\xaf\x34\x4b\x03\xea" + "\xe3\xc7\xe4\xe5\x32\xf8\x87\xa9" + "\xa7\xa6\x79\x7a\x72\x27\x74\xa0" + "\x23\x6c\x6d\xe2\x17\xd0\xe5\x56" + "\x10\x7e\x16\x38\x76\xb9\x50\x7e" + "\x4e\xa8\x8a\xe8\xef\x81\x6c\xaa" +
- "\x95\x85\xdc\xb0\xb7\xf3\xa1\x0c" + "\x2e\x9f\x1d\x9f\x08\x46\xde\x27" + "\xa7\x82\xdd\xba\x39\xbf\xf3\x1a" + "\x48\x24\x86\x65\x79\x6a\x35\x79" + "\x52\xa0\xf9\xf5\x45\x23\x60\xc0" + "\xf9\x42\x9a\x13\x89\x0f\x8b\x1a" + "\xfc\x40\x4d\x84\x42\xee\x3e\xb5" + "\x68\x63\x5b\x4e\xe5\xbf\xb0\x93" +
- "\xbf\x5b\x32\x4d\xd7\x59\x39\x47" + "\xb9\x14\x61\x8d\xec\xbe\x61\x2a" + "\xee\xe2\x4b\x92\x94\x2a\x67\x25" + "\x0c\x3d\xc2\xf2\xdb\x95\x85\xa4" + "\x38\x18\x22\x6a\x8b\x84\x76\xe4" + "\x73\xb6\xc1\x35\x9a\xe6\x43\xe7" + "\x03\x85\x46\xd8\x99\x24\xb4\x2a" + "\xa7\x0b\xe9\xe9\x54\x00\xaa\x62" +
- "\x11\x29\x48\xbc\xf1\x13\x8d\x35" + "\x26\x7f\xfa\xb7\x71\x19\x5d\x68" + "\xe4\xae\xe1\x2b\x1d\xa5\x67\x3e" + "\xa9\x14\xd1\x98\x09\x85\x41\xe0" + "\x61\x25\x05\x4e\x60\x9f\x63\x59" + "\x18\x08\x5d\x15\x49\x5c\x07\x32" + "\x1c\x4b\xb6\x67\x3b\x34\xa2\x2a" + "\x6a\x3e\xf5\x67\x29\x5e\x44\x1b" +
- "\xe0\x04\xa9\x73\x17\x27\xfb\xbd" + "\x73\x8d\x88\x28\x0b\xe4\xe1\x7c" + "\x1b\x7d\xa9\xea\xf6\x35\x7e\x2e" + "\x97\xa0\xaf\xa9\x2a\x77\x61\xd0" + "\x59\x7c\x1f\x7a\xc4\xc7\x4a\x43" + "\x9a\x7b\x9b\xe7\x4a\x12\x21\x6e" + "\xc7\xec\x22\xbb\xf3\xcf\x5a\x05" + "\xd3\x58\xc8\x84\xc9\x7a\xfd\x8b" +
- "\x9c\x78\x24\xc0\x02\xdd\x34\x54" + "\xfc\x7b\xb5\x41\xea\xa9\xdc\x90" + "\xdf\x98\x33\x24\xe2\x98\xa8\x8a" + "\xbb\x94\x4a\x89\x34\xc8\x07\xf6" + "\x76\x9b\xc9\xc2\x97\xbe\x07\xbb" + "\x02\x93\xc2\x18\x67\xba\x76\x65" + "\x8c\xa8\x03\xe7\xcc\xef\x79\x3d" + "\x06\xd1\xa0\xb6\xd7\xce\x59\xf2" +
- "\xad\x68\x1f\x9f\xf5\x7d\xd5\x2f" + "\xc8\x70\x64\xb0\xdb\xc6\xdc\x5d" + "\x07\x73\xb4\xa9\x51\x64\x1b\x80" + "\xf4\x1b\x55\x76\xe3\xc8\x51\x6b" + "\xa9\x1d\x4e\xd4\xf7\xd1\x0b\xef" + "\x0c\x60\x4e\x4d\x1d\xcb\x4b\x71" + "\xc7\x40\x65\x0c\xe4\xb9\x7b\xc5" + "\x44\xc6\x7c\x32\xc2\x1e\xbd\x71" +
- "\x0a\x4f\xd8\xcf\xb5\x33\xcd\x00" + "\xdd\x0d\x6b\x4e\xf7\x68\xa5\xcf" + "\xf4\x48\x0f\x2d\xdb\x4e\x69\x1c" + "\xd8\x7d\xff\xfe\xcc\xc7\x47\x27" + "\xb2\x24\x8c\xac\xad\xec\xda\xce" + "\xe5\xa5\x42\x07\x3f\xde\x29\xdb" + "\x6d\x29\x90\x30\xbb\x8f\x5d\xe3" + "\x4a\xb5\x1f\xb1\xf7\xab\x8c\x78" +
- "\x1f\xd8\x4d\x7f\x7e\xcf\x52\x9a" + "\x5e\xc0\x69\x5e\xe1\x2b\x13\xa0" + "\x72\x4d\x0f\x2a\x47\xb7\xda\x90" + "\x06\x67\x2d\x31\x11\xf9\x42\xc1" + "\x8b\x99\x61\x82\x1f\x63\xd3\xe8" + "\x94\x1c\x5c\x61\xae\x2f\xf4\xf0" + "\x5d\xfa\xc3\xae\x8c\x94\x4e\x2f" + "\x1e\x10\x74\xa3\xa8\xe7\x2a\x24" +
- "\x0b\x61\xde\xc8\x5d\x3a\x89\x0f" + "\xce\x23\xe2\x67\xfb\x15\xc5\xe8" + "\xc5\x6d\xad\x4e\xa6\xbf\x74\x77" + "\x8f\x72\x5c\x92\x95\x0f\xd2\x89" + "\xce\x83\x85\x09\x66\x09\x1e\x7a" + "\xd7\xa7\xf2\x93\x94\xdb\xee\xa2" + "\x4a\x4d\x30\x4c\x97\x20\x28\x1b" + "\x2d\x28\x77\xc0\xda\xe3\x42\x08" +
- "\x52\xbe\x88\xd0\xca\x78\xa8\x1f" + "\x56\xe6\xe1\xa9\x07\xcb\xc2\x89" + "\xdb\x62\x9d\x21\xc3\xc5\x5b\x38" + "\x52\x27\xda\x5f\x6b\x67\x2b\xd8" + "\xfc\xea\x04\xe3\x9e\xdc\x49\x24" + "\xa2\x4e\x2f\x63\x91\x79\x9e\x1e" + "\xb9\xe0\xd5\xcd\x61\xe0\x36\x30" + "\xbc\x25\x08\x83\xff\xf6\xa6\x75" +
- "\x9b\x5e\xf6\x81\x04\x26\x5b\x2e" + "\x37\xf8\x01\x49\xc0\x56\x01\x48" + "\x33\xb7\x57\xb8\xab\x86\x7f\x55" + "\x11\x44\x5b\x73\x0e\xed\xe3\x88" + "\x2e\x73\x33\x2a\x0d\x68\x37\xc3" + "\x1f\xc1\xc9\x31\xcb\xbf\x99\xa5" + "\xc4\x01\x52\xa9\x51\xf8\x82\xb2" + "\x95\xdf\x4d\x85\x8a\xda\x42\xd3" +
- "\xb4\xed\x9d\x44\xdc\xcd\x0f\xb1" + "\xcf\x4a\x24\xd1\x42\x00\x89\x2c" + "\x17\x70\xfc\xc7\xca\x72\x30\x9b" + "\x3f\x06\xe8\x9c\x85\xa6\xcd\x1a" + "\xf5\xe2\x51\x7f\x3c\x31\x43\xd2" + "\x78\x95\x3d\xd7\xa4\xf1\xa3\x52" + "\x6e\xce\xf0\x64\x7a\x5b\x78\xda" + "\x2d\x4c\x2a\x44\x15\x63\x76\x2e" +
- "\x7b\x2d\x9e\x3b\xa3\x72\xd9\xe4" + "\xff\x18\x82\xc4\x27\x0b\xc6\x7c" + "\x91\x9d\x14\x84\x38\x08\xc7\x8f" + "\xcc\x1e\x46\x2f\x6f\x34\x04\x5c" + "\xa9\x50\x46\x61\xf2\xfd\xe9\xeb" + "\xac\x66\xf6\xc1\x37\xb5\x35\x5e" + "\x83\xbc\xba\x88\xd1\x13\x56\x64" + "\x3e\xc9\xe1\xc5\x3a\xce\xca\x88" +
- "\x1a\x11\x1f\x15\x04\xb0\xf9\x94" + "\xfa\xc5\xdb\x07\x5b\x03\xa5\xc7" + "\xd7\x49\x9e\x60\xa7\x8e\x95\x53" + "\xc0\xf4\x13\x90\xd7\xb4\x26\x05" + "\xbd\x2f\x3e\x59\xbb\x5e\xde\x66" + "\x37\x0c\x2e\x4c\xb4\xf8\x7c\x6e" + "\x78\x3e\x98\x8c\x8b\xfc\x72\x6f" + "\xd7\xf9\x48\x23\x63\x9b\xab\x6f" +
- "\x59\xac\x70\xeb\x81\x2e\xd0\x58" + "\xf7\xd8\x17\x44\x9b\x76\x22\xf5" + "\xff\x74\x72\x07\xd5\x63\x30\x9f" + "\xac\xe8\x0f\x34\x4f\x6f\xac\xf5" + "\xba\x14\x09\xb5\xd1\xd9\x72\xce" + "\x5c\x25\xbc\xb7\x84\x59\x83\xb3" + "\x8f\x03\xa5\x7c\xa7\x3f\x5d\x14" + "\x13\xab\x8f\xad\xc6\xa3\xcd\x7a" +
- "\x68\x84\x3d\x6a\x52\xa3\x48\xc7" + "\x32\x80\xe3\x27\x99\x47\xab\x3f" + "\xe7\x0c\x43\xfa\x29\x36\xad\x91" + "\x44\x4c\x61\x71\x2c\x0b\xaf\xc5" + "\x11\x16\x21\x0c\xa5\x3f\xde\xce" + "\x83\x80\x33\x02\xba\x89\x68\x6e" + "\x32\xfe\xf0\x77\x59\x19\x0a\xee" + "\x5a\xbc\x4b\x0f\x5d\x90\xea\x01" +
- "\x23\x2e\xe9\x3d\x75\xa3\x9c\x20" + "\xe3\xb6\xbb\x5f\xc8\x3c\xb0\xcc" + "\x7e\x48\xb1\xd7\x03\x0f\xb9\xcc" + "\x1f\x94\x10\xc7\x38\x2a\x9c\xfa" + "\xed\xce\x24\x67\x23\x38\x6c\x75" + "\x23\x03\x2d\x19\x58\x22\x90\x3a" + "\x8e\x03\x5e\xea\x19\xe5\x50\xb1" + "\x91\x75\x42\xc7\x65\x28\xba\xdc" +
- "\x48\xdb\x93\x81\x5e\xb2\xcf\x12" + "\x8c\x70\xea\x3b\x63\xae\xb4\xdd" + "\x21\xf8\x81\xf1\x2e\x10\xae\xda" + "\xd9\x89\xa0\x24\x30\x92\x9d\x9d" + "\xea\x6a\x87\xa0\x2d\x12\xc4\x71" + "\x09\x9c\xe1\xbb\x3b\xea\x63\x1a" + "\x0c\x8d\x6f\x01\x76\x80\x89\x3b" + "\x13\xb7\xa6\xae\x5d\xcc\xcc\xa5" +
- "\x7d\xe9\xf6\x06\xe3\x8e\x0e\x51" + "\x8c\xaa\x0e\xb0\xc5\x8f\x4a\x68" + "\x33\xbf\x3f\xb9\x79\x35\x31\x15" + "\x23\x17\x6b\xf6\xa6\x5f\x7f\xe6" + "\x8c\x74\x86\xce\xf6\x81\x58\x81" + "\x10\x8b\xd5\xea\x18\xd3\xce\xc1" + "\x93\x33\xf3\xf2\x5b\x77\x62\x86" + "\xf2\x6f\x83\x7d\x04\xc9\xc0\x7a" +
- "\x61\x2f\x8e\x4a\xaf\x2b\xf2\xc3" + "\xa6\xa6\x6d\x17\xde\x9e\xd2\x77" + "\x63\xda\x07\x16\x21\x5f\xa5\x40" + "\x91\xe3\x52\x14\x56\x38\x8b\x85" + "\x56\x3c\x1b\xfe\x67\xc2\xd3\x0d" + "\x7a\x22\x55\x7d\xdd\x4b\xc0\x66" + "\x09\x4e\x40\xe6\x55\xfe\xd2\xfb" + "\xbc\xfc\x9c\xea\x49\xcf\x81\x59" +
- "\x32\x07\x89\x78\x7f\x23\x49\xe5" + "\xd9\xb4\xfc\x53\xf9\xbe\x43\xc4" + "\xd6\x80\x34\xeb\xa6\xd8\x84\x98" + "\x86\xb1\x48\x30\xa1\xb6\x35\x8a" + "\x0a\xa9\xe9\x65\x16\x47\xe4\xb4" + "\xc0\x06\x30\x65\x0d\x38\xbf\x45" + "\x3b\xae\xe9\x4f\x0d\x82\x3f\x8f" + "\x71\x3b\x9a\x97\xa0\x35\x4a\x24" +
- "\xaf\x70\xa8\xae\x02\xa9\x46\xae" + "\x99\xdc\xbe\x7c\xf5\xfc\xb9\xa9" + "\x93\xe7\xb7\x79\x3f\xca\xf2\x74" + "\x28\xeb\xbe\x1d\x23\xf2\xb8\xad" + "\x85\xdf\x64\x67\x0e\x06\x02\x63" + "\x54\xd5\xeb\x57\xd2\x20\x33\x36" + "\xe1\x22\x8d\x79\x3e\x57\xfd\xd9" + "\xed\x7d\xb6\xeb\xf5\x85\x5f\x28" +
- "\xc9\x55\xeb\x8a\x13\xd6\xac\x0a" + "\xf0\x85\x68\xd8\xa4\x1d\x79\x79" + "\x23\x5f\xb0\x44\x67\x82\x5e\x16" + "\xed\x48\x45\x28\xe8\xf5\xe5\x9e" + "\xb8\x61\xb6\x85\xcc\x48\xd5\x9f" + "\x89\x86\xc5\x89\xc0\x37\x70\x25" + "\xb2\x0c\x29\xf9\x6f\x30\x47\x9b" + "\xf4\xec\x77\x06\xeb\x2e\xba\x56" +
- "\xb5\xa2\xca\x11\x92\x32\x6b\xd8" + "\xd1\x7b\x33\x39\x8e\x25\x26\x2a" + "\x91\xc2\xc8\x79\xb5\xa9\xc5\x4d" + "\xe6\x42\x19\x74\x87\x3d\x44\x16" + "\x0c\x40\x11\xf8\xf8\xa2\xc9\x6b" + "\x0e\x4e\xeb\x9e\x35\x69\x9c\x81" + "\x4b\x21\x0c\xce\x73\x72\xbe\xe1" + "\x81\x15\xb6\x84\x81\xfb\x9a\x42" +
- "\xff\x06\xcd\x74\x9d\x0e\x01\xa1" + "\xac\xee\xa3\xac\xdf\xc7\x17\x9c" + "\x2b\xaa\x63\x80\xd3\x6c\xc8\x74" + "\xff\x14\x46\x73\xb3\xc4\x95\x85" + "\xcc\x62\x0f\x99\xca\x00\xde\xa3" + "\xe5\x3b\x0c\xca\x13\xd2\xbe\xd9" + "\xf5\xe9\x8c\xdf\x8a\x07\x86\x78" + "\x44\x44\xd4\x5c\xe3\x7c\xb2\xdd" +
-
- "\x82\x83\xee\x26\x1d\x58\x7c\x9c" + "\x8e\x63\x9d\x35\xc5\xdc\x17\xcf" + "\x3d\xae\x28\xb7\xab\x73\x82\xee" + "\x47\xf0\x21\xf8\x26\x29\x11\x1d" + "\x74\x1a\x49\x50\x77\x84\x49\x11" + "\xb9\xdf\xe0\xfd\x61\xa7\x7f\x68" + "\xab\x35\xa4\x7e\x22\x80\x25\x2c" + "\x3f\x7e\xce\x91\x94\xdb\x8b\x6b" +
- "\x56\x2b\xfb\x53\xa5\x03\x3a\xb2" + "\x78\x7f\x05\x4e\xe7\x41\xe1\x6c" + "\xd9\x90\xe4\x89\xc3\x25\x65\x79" + "\x75\x7e\x1a\xa3\x25\x57\xc9\x0b" + "\x06\xfd\x20\x12\x91\x67\xc5\x1e" + "\xd6\x0b\x8b\x40\x3c\x3a\x6e\x71" + "\xa9\xeb\xeb\xe8\xf7\x6b\xcd\x31" + "\x70\xb6\xe6\xbe\xa6\x6c\x32\xa7" +
- "\xd7\x41\xf2\x99\x56\x35\x95\x60" + "\x9d\x34\x1a\x00\xd7\xdb\x4a\xee" + "\x91\xe4\x89\xaa\x6a\xbf\x35\x0b" + "\x46\x75\x6f\x13\xf4\x76\x00\x7f" + "\x3d\xda\x64\x92\xba\x18\x9a\xd1" + "\x8b\xa2\xa7\x62\xcd\xd2\xb2\x6e" + "\x71\xc9\x61\x87\x1f\x94\xba\xcd" + "\x5d\x4a\xbe\xa3\x8b\x51\x50\x15" +
- "\xd2\x62\x7d\xcf\x82\xc9\xd3\x20" + "\x50\x81\xba\x23\x9d\xe2\x36\x1f" + "\x9e\x3f\x76\x92\xf0\x0b\xae\x48" + "\x07\x70\x3a\x1d\x6b\x7e\x52\x7a" + "\xe3\x85\x1a\x58\x97\x90\xa8\xb4" + "\xe5\x8b\x15\xdc\x0f\x52\x1a\x1f" + "\x6e\x72\x7d\x16\x7d\xb3\x8d\xf9" + "\x62\xe8\x13\x11\x6e\x78\x02\x88" +
- "\x18\xfc\xce\x6b\x96\x98\xc3\xc3" + "\x00\x6e\x63\x18\x43\xb3\x54\xb7" + "\x91\x19\x3b\xf5\x68\xa1\xb6\x6f" + "\xe5\x2f\x4c\xb8\x55\x1b\x18\x87" + "\x8c\xbc\x21\x27\x10\xc9\x86\x16" + "\x2a\x0e\x03\x95\x60\x06\x49\xc6" + "\xda\x55\xdf\x97\x2f\xeb\xfd\x18" + "\x31\xd2\x27\x7c\xfc\x2c\xd5\x10" +
- "\xb9\x31\x87\x11\x9c\xe0\x01\x2a" + "\xd8\x3c\x39\xcd\x82\x61\xc4\xb6" + "\x28\xe3\x08\x75\x65\xdd\xd7\x5e" + "\xfa\xa8\x1d\x68\x1b\xca\x02\x64" + "\x2d\x27\x9f\xce\x86\xbe\x3a\x60" + "\x9c\x7c\x16\x29\x5c\x43\x63\x93" + "\x42\x2a\x5a\xc4\xc1\xf7\x14\x48" + "\xcd\xca\x22\x9a\x22\x62\x65\x14" +
- "\x0c\x47\x3b\x32\x31\x64\x52\xb4" + "\x18\xe4\x36\xd5\x1a\x4e\xcd\x40" + "\xc0\x3b\x93\x01\x3d\xdd\x0f\x43" + "\x23\x90\x64\x07\xde\x6d\x3e\x3d" + "\xb1\x23\x95\x2e\xef\x64\x05\x4b" + "\x4f\xbc\x79\x90\x05\x31\x0d\x8c" + "\x58\x3d\x7d\x83\x67\x69\x6c\x49" + "\x5f\x3b\x12\x89\x60\xf6\x79\x3a" +
- "\xb0\x9a\xf0\x36\x9e\x14\xb2\xef" + "\x5b\xbb\x10\x4a\xca\x63\xf1\x03" + "\x98\x09\xe2\x06\x45\x70\x29\xd0" + "\xab\x3b\x5a\x1b\x00\xaf\xf0\x56" + "\x0d\x0e\x88\x70\xec\xcf\xf4\x7a" + "\x3f\x91\x3d\xbe\x6f\xa6\x32\x73" + "\xbd\xb4\xce\x7e\x4a\xc8\xe6\x32" + "\x55\x8f\x22\x9c\x9a\xa7\xc4\xed" +
- "\x9a\x69\x2f\xa3\x9e\x14\x99\x29" + "\x70\x61\x18\x72\x11\x8e\x6c\x6d" + "\x52\x6e\x54\x45\x4f\x49\x74\xad" + "\xfe\xe7\xef\x89\x39\xb5\x3c\x2b" + "\x31\xb0\x2f\xe4\x0e\xe6\xa2\xb9" + "\x23\x48\x0e\x67\x0d\xfd\x58\xf8" + "\x6d\x63\x2c\x49\x7e\xab\xca\xeb" + "\x70\x46\x2c\xd3\xfc\x72\xe0\x40" +
- "\x1d\x4e\x34\xb2\x66\x6a\x7a\x45" + "\xfe\xdc\x37\x8f\x2a\x1f\xc8\xde" + "\xd5\xf9\x40\xab\x3e\xf8\xd5\x61" + "\x3c\x04\xdf\xf1\x76\x27\xa8\x5c" + "\x7c\x67\x46\xf8\x1e\x68\x74\x21" + "\x28\x16\x6d\x51\x4f\x1f\x24\x7c" + "\x4f\x37\x01\x1f\xc3\x94\x49\xf5" + "\x0c\x21\x0f\xdf\x67\x83\x3c\x25" +
- "\x20\x18\xe9\x20\xeb\xbe\x4d\xc9" + "\xe7\x41\xb6\x62\x04\xc2\xaa\x19" + "\x50\xcf\x49\x8b\xf0\x34\x28\xc2" + "\x6d\x5a\x5d\x8e\x4b\xc7\xe8\x47" + "\x6a\xcb\x2a\xf4\xdc\x0c\x16\x78" + "\xb9\x68\x35\x3a\x75\x64\x53\x7a" + "\x71\xeb\xd1\x6c\x47\xd5\x28\x4a" + "\x11\xbc\x8f\x8c\x3f\xbc\x60\x03" +
- "\xec\xb6\xc6\xf4\xd1\x94\xe8\xf6" + "\x9b\xcd\xb3\x18\x27\x08\x6b\x52" + "\xbf\x7f\x11\x12\xa8\x52\xf9\x73" + "\xf5\x5b\x94\x11\xb0\x64\xe8\x2b" + "\x64\x9b\x09\x42\xa5\x8e\xf1\x86" + "\xe2\x8c\x54\x07\x8a\xb2\x70\x27" + "\x9c\x1c\x5c\x29\x28\x0f\x39\x97" + "\xc3\x06\x52\xcb\x43\x6a\x2e\x67" +
- "\xf8\xda\xba\x8e\x73\x2b\x50\x66" + "\x07\x4c\xa0\xf9\x8e\xfe\xba\x27" + "\x04\xae\xf6\x1b\x2f\x43\xda\x74" + "\x3b\x40\x8d\x27\x68\x82\x1d\x27" + "\x57\x1b\x47\x93\xac\x91\x8b\x01" + "\x1f\xc5\x76\xb2\x69\x68\x09\x01" + "\xd2\x7d\xc5\x6d\x01\xc1\x79\x5b" + "\xa5\x80\x6c\x80\x5e\x34\x23\xb6" +
- "\x88\x20\xd7\xe9\x49\x43\xd2\x89" + "\xe0\xf6\x9c\x3e\x03\x7a\x31\xd5" + "\xea\xf8\xc8\x73\x9d\x1a\xc6\x5b" + "\x3d\x5a\x0f\xf1\xc8\xc2\xf9\x48" + "\x07\x95\x6b\x08\xdf\x14\x24\x47" + "\x92\x9b\x54\xae\xdf\x8c\x81\x79" + "\xbf\x15\xa4\x62\x7a\xa7\x24\x3d" + "\x76\x29\xb2\xd3\x9f\xf5\x2d\xb9" +
- "\x44\xcf\x1f\xe7\x8e\x0f\x45\x80" + "\x86\x99\x0a\xdb\xfd\xdd\x63\x27" + "\xf2\xbc\x68\x96\x7a\x8c\x28\x8c" + "\xf6\xe2\x92\x03\x35\x9b\xd0\xd7" + "\x7a\xdd\x06\x65\x82\x54\x3d\x0a" + "\x4f\x9d\xce\xcd\xc1\xda\x43\x9b" + "\xb8\x63\x8b\x45\x61\x4f\x15\x8d" + "\x3b\x97\x9c\x12\xd0\xa4\xbd\x77" +
- "\x96\x44\x5c\xc5\xd0\x7d\x7c\xc3" + "\xd2\xab\xbb\x25\x57\x63\xa9\xa6" + "\x63\xf3\xd7\xad\xf2\x63\x7e\x5b" + "\xdf\xf1\x73\x2e\x82\x37\xce\x9d" + "\x71\x1f\xb9\xb2\x6a\xa1\xe5\xe1" + "\x3c\x16\xa0\x5b\x23\x98\x48\xe4" + "\xad\x15\xe5\xf6\x32\x9c\x75\xf2" + "\xcf\xee\x15\x86\xf8\xf1\xe2\xa5" +
- "\xce\xab\xa6\xeb\x19\x0d\x6c\x0b" + "\xe4\xee\x9e\x64\x45\xc4\xaa\x6c" + "\x0e\xe1\x65\xb4\x83\xf2\xb4\x59" + "\x2d\x21\x29\xf7\xf2\x04\x67\xd7" + "\x92\xee\xd1\x70\x83\x73\x4e\x8d" + "\xb5\x1e\x6c\xea\x8b\xc2\xca\xfb" + "\x05\x8e\xf2\x4e\x8b\x21\x84\x2c" + "\x0d\x6e\x6c\x7e\xd0\xf7\x52\x2c" +
- "\x16\x96\xe0\x0f\xf0\x4c\x13\xd8" + "\xc3\x8c\x8c\xe4\x9a\xe5\x31\x4a" + "\x82\x7b\xb8\x5f\x66\xe5\x0a\x5c" + "\xa7\x26\xbd\xb2\x5a\xf1\x2e\xdc" + "\x65\x17\x78\x5b\xf5\xae\xeb\x63" + "\x5e\x58\x39\x53\x3c\xc8\x6c\x4f" + "\xe4\x78\xfc\xab\x01\xe2\x8a\xd0" + "\x56\x2a\xbe\x1f\x9a\xee\xe7\x98" +
- "\xa2\x89\x14\x0e\xdd\x97\x48\x0a" + "\x7f\x98\x3d\xe9\x36\x87\x9f\xc0" + "\x37\xa4\x79\xea\xb8\x00\x7a\x42" + "\xfa\xe9\x89\xaf\xe4\x39\x2b\x3e" + "\xf1\x38\x81\x7e\x2f\x2d\x1c\x45" + "\xb0\x8b\x14\x37\x11\xe4\xcd\x08" + "\x41\xe5\x50\x0d\xc7\x68\x69\x01" + "\x91\x12\x47\xdd\xe1\xee\xdc\x2b" +
- "\x67\x43\xc6\x47\xc8\xe2\xcc\xca" + "\xc0\x4e\xaf\x45\x9f\x6b\x49\x6a" + "\x2c\x04\x34\x60\xf3\x36\x08\x2a" + "\xea\x62\x6c\x0b\x90\xf3\xa1\x14" + "\x40\xf5\xf1\x3e\x63\x93\xfa\xe7" + "\x93\x6d\xa7\x72\x0a\xb3\x23\xd3" + "\x51\xe4\xea\x0f\xb5\xc8\xee\xff" + "\x87\xef\x04\xbd\x72\xc1\xaf\x4e" +
- "\x07\x40\x48\x6c\x1b\x1e\xdb\x3b" + "\x02\x02\xbe\xe6\xa1\xd5\x10\xe1" + "\xae\x5a\x66\x15\xae\xe1\x24\x1c" + "\x27\x9d\x9c\x7c\x89\xf6\x0e\xfa" + "\x07\xb6\x22\x9d\x2a\x66\xa0\x01" + "\x47\xf1\x22\x67\xce\x64\xc3\x18" + "\x4c\xf7\x21\x75\x6d\x14\x46\x04" + "\xb8\xab\xa8\x9f\x4e\x7a\x77\x39" +
- "\x27\xe4\xea\x8d\x0c\xb3\xa7\x36" + "\x3e\x58\x2e\xb6\x5a\x5f\xac\xb4" + "\xa9\x39\x0a\xdf\xa2\x9f\xef\xac" + "\x39\x90\x65\x5d\x04\xa6\x29\xc9" + "\x7e\x2f\x26\xfc\x6e\x9d\x4d\xe1" + "\x9d\x8d\x53\x05\x2d\xd6\xe6\x15" + "\xe0\xf9\x88\xc4\x7e\xa7\x42\xee" + "\x42\x8a\x2c\x89\x65\x63\x83\xae" +
- "\xfd\x33\xf5\x1a\x1b\xdd\xab\x90" + "\xcb\x0a\x0f\x75\x76\x25\x3d\x7c" + "\xc8\xc9\x6c\xc7\x5a\xc5\x0a\xfa" + "\x05\xaa\x75\x52\x2e\x30\xb4\xc3" + "\x9e\xc1\x2d\xef\x1d\xb3\xcb\xe2" + "\x7b\x35\x06\x38\x51\xb7\x3d\x5f" + "\x8e\xf9\x09\xf5\x00\xdf\x74\x64" + "\x89\xbd\xeb\x28\x1e\x5f\xa7\x9b" +
- "\x51\xd5\xde\xab\xe7\x9b\x51\x74" + "\x10\x44\xb7\xc8\xb8\x58\xd3\x03" + "\xa9\xd9\x10\x0e\x0b\xb1\x00\x4d" + "\xb7\x52\xda\x28\xb1\xb0\x92\x63" + "\x04\xc9\x75\x0b\x98\xa2\x44\x67" + "\x6c\xf9\xf7\xa8\xae\xb0\x05\xc3" + "\x32\xf9\x2c\x18\x1d\x42\x2e\x04" + "\xca\x36\x46\x9e\x50\x5d\xfc\xf6" +
- "\xdf\x76\xd6\x5f\xe0\x1f\xcb\x47" + "\x0b\x96\xa8\x9b\x91\x42\xc6\x69" + "\x6d\xde\x65\x01\x06\x23\xd0\x40" + "\x9a\xb2\xb8\xd6\x4e\xf4\x3b\x78" + "\xbd\x98\xd0\x6e\xfb\x19\x4e\xc8" + "\x23\x61\xbe\xff\xf7\x09\x1f\x60" + "\x3a\x4a\xe2\xa0\xc5\x89\xae\x87" + "\x2a\xac\x05\x5e\x9c\x4e\x86\x07" +
- "\x00\x5e\x2c\x39\xfd\x9e\x0f\x85" + "\xde\x1b\x51\xe2\x7f\x66\x9f\xc2" + "\x8f\x29\x31\x84\x6d\x40\xcf\xf5" + "\x5d\xd0\xc0\x79\xc8\x10\x0b\xf9" + "\x12\xf0\x38\x00\x1d\x9b\x3e\xfb" + "\x99\x97\x8c\x0a\x7a\x4e\xc0\x84" + "\x86\xe9\xc8\x96\xd4\x02\x61\xb7" + "\x75\xa6\x6d\x17\x13\x3b\xa6\xde" +
- "\x69\x53\xf5\xdd\xef\xc2\xaf\x2f" + "\xb9\x63\xac\x24\x6f\xf0\xbf\x70" + "\xdd\x6a\x92\x6e\x42\x37\x1a\x1e" + "\xcf\x18\xfa\xfd\xad\x37\x35\x77" + "\x52\xb5\x84\x59\x63\xea\x11\xd2" + "\x24\xed\x1a\x8c\x4d\xed\x7e\xb1" + "\x67\x8b\x0b\x14\x74\xde\xe9\x5d" + "\x57\xff\x8b\x76\xc8\x01\x25\x74" +
- "\x89\x9b\xe5\xb3\x51\x5a\x43\xe4" + "\xc9\xa1\x33\x41\x55\x39\x61\x13" + "\x59\xee\x0b\x44\x73\x69\xf4\x87" + "\xe4\x01\xc4\x00\xf8\x10\x47\x71" + "\xc9\x46\xc4\xd6\xce\x4b\xcf\xc0" + "\x68\x53\x4d\x6c\xd6\x7f\xaa\xe0" + "\x37\xfc\x68\xfc\x1a\x81\x5d\xde" + "\x57\xa0\xc2\xb7\x72\xbd\xfe\x61" +
- "\xe8\x25\x47\xbe\x91\x2b\xff\x90" + "\x1e\x00\x81\x5e\xf6\xbf\x0a\x71" + "\xf3\x04\xef\xc5\x76\x34\xeb\x15" + "\xb7\xa2\x0d\x3c\x1b\xb5\xda\xcc" + "\x2b\x65\xc0\x2c\xa5\x40\x38\x88" + "\x56\xa8\xe4\xf5\x9d\x7d\xfc\xd1" + "\x88\xfc\x0f\x07\x53\x39\xbc\xeb" + "\xc1\xed\xef\x91\x7d\x94\x0f\x34" +
- "\xcf\x11\xbd\x6d\xbb\xbe\xdd\x1e" + "\x03\xe2\x19\xc6\x45\xaa\x97\x82" + "\xa6\xd2\x2b\x96\x6f\x82\x54\x63" + "\xc7\xed\x12\xfa\x67\x3f\x3f\xba" + "\x8d\xd8\x7a\xfc\x1d\x0f\x22\x25" + "\x01\xc8\x83\x86\x81\x9f\x05\x5d" + "\x64\x57\x38\x2d\x6e\xf2\x77\x05" + "\x0d\xe8\x53\xa4\x46\xc6\x74\xa5" +
- "\x0c\xe3\xf4\xb8\x71\x6c\xd1\x89" + "\x29\xfa\x3d\xc6\xfb\xab\x2d\x9e" + "\xeb\x5c\xde\xdf\x5e\x06\x33\x60" + "\xc6\x45\x3c\x0f\x1f\x1d\x2b\x07" + "\xec\x29\xd4\xb8\x2a\xbc\xd0\x0c" + "\x89\x1f\x47\xc2\x8c\x43\x47\xe7" + "\x9e\x67\x9d\x31\x56\xe8\x1c\x13" + "\xba\x4e\xb2\x87\x28\xa2\x20\x75" +
- "\x8c\xc7\x4c\xd6\xc9\x47\x58\x79" + "\x7b\xb2\x6c\x9b\x1b\x62\x50\x6c" + "\xab\x22\x80\xdf\xf8\x9b\x09\x07" + "\x1d\xda\x4e\xc0\xeb\x62\xf8\x48" + "\x16\x3c\x60\xe1\xed\x32\x27\xd1" + "\x50\x94\x9a\x5c\x0f\x0e\xa8\x19" + "\xfc\xb4\x29\xb4\x54\x7f\x25\xe2" + "\x15\x05\x46\x45\xc6\xb2\xd3\x66" +
-
- "\xd6\xad\x3c\x45\xbc\xb7\xe2\x8d" + "\xf8\xc1\x0b\xbc\xa7\x00\x39\x20" + "\xaf\xd3\xab\xa6\x47\x6e\xd8\xbc" + "\xfb\xef\x02\x85\x12\xac\x1c\x91" + "\x69\x54\x96\xec\x42\x02\x55\x2d" + "\x7e\x01\xe0\x29\x92\x76\x9f\x0e" + "\x85\x98\x97\x65\x8f\x07\x3f\x63" + "\xef\x51\xf7\x4c\x49\xd4\x87\xfb" +
- "\x10\xee\x51\xd5\xa2\xe2\x66\x60" + "\xa6\x09\x7e\x72\xd8\xf1\xa8\x87" + "\x8d\x14\x01\x2c\xab\x8b\xd0\x00" + "\xfe\x33\x4f\x42\xf1\xe4\xa8\x6d" + "\x71\x4e\x9a\xcf\xf0\x17\x6d\x46" + "\x19\xcb\xf5\x3b\x10\x20\x50\xff" + "\xc0\xec\x62\xd0\xd8\x97\xcf\xdc" + "\xc4\x0a\xd8\x81\xaf\xd9\xc0\x80" +
- "\xab\xad\x7a\x1d\xff\x45\x04\x1a" + "\x7c\xa6\xf6\xd5\x60\x82\xd3\x65" + "\x6f\xb2\xcf\x91\x08\xfb\x62\x6e" + "\xd6\x91\x7d\x5c\xa5\x0f\x1e\xef" + "\xcd\x72\xdb\x33\xba\xc7\xe7\x47" + "\xb2\x74\x7c\xfa\x09\xbc\x7c\x01" + "\x3c\x50\x0a\xf5\x90\x15\x93\x3c" + "\x42\xaa\x6b\x61\x60\x4f\xc5\xca" +
- "\x1c\x58\xf4\x1b\xeb\x7c\x85\x98" + "\x66\xb1\xa7\xac\x86\xe1\x35\xe6" + "\xac\x22\x97\x65\x22\xdd\x8d\x27" + "\x07\x80\xb6\x1d\x4c\x3c\x90\xa0" + "\x02\x14\xf2\x48\x89\x45\x6e\x36" + "\xa2\xbd\x6a\xb9\x14\x9c\xb4\x31" + "\x90\x31\x40\xe0\x09\x4b\x9c\x32" + "\xfe\x43\x9f\xd2\xa3\x7c\x19\x97" +
- "\xb1\xe2\x07\x4b\x5d\xdd\x73\x71" + "\x21\xa2\x9e\x8d\xcb\xc4\x44\xd1" + "\x14\xab\x05\x11\xa4\x4e\xb0\xe8" + "\xf1\xd8\x80\xfe\x42\xa5\xdd\x92" + "\xe6\xdc\x03\xcf\xa8\x2f\x98\xe9" + "\xfc\xcf\x22\x1a\x65\xa9\x5e\x8b" + "\xc4\x88\xad\x3f\x7f\xea\xf4\xf7" + "\x5c\xa9\x5b\x6a\x3e\x77\xdb\x62" +
- "\xc7\x57\x03\x82\xb4\x3f\xbd\x18" + "\xad\x58\x14\x6f\xae\x39\x20\x99" + "\xa1\x4a\xb4\x25\xc5\xf3\x1d\x9a" + "\x81\x52\x3d\xed\x57\x03\x78\x2d" + "\xd4\xd4\x7a\xc7\x4d\x7e\xcf\x58" + "\xc4\x4f\xdf\xf9\x98\x79\x9a\xd4" + "\x5e\x20\x71\x1d\xb5\xa8\x65\x44" + "\xaa\x54\x92\x64\xa6\x0e\xee\xa0" +
- "\x35\xb2\x92\x9c\xe8\xe6\xaa\x4b" + "\xa1\x93\x39\x6b\x0e\xbd\x3b\xa7" + "\x31\xd0\x3d\x69\xec\x60\x6d\xd0" + "\x1c\x88\x56\x71\x1b\xb9\xca\x03" + "\x4b\x57\xb3\x1d\x2f\x86\x15\xd6" + "\x1a\x06\xbb\x64\x85\x01\x5b\x48" + "\x06\x1e\x18\xa0\x88\x49\x43\x27" + "\x57\xc7\xc0\xc1\xd4\x1a\xd6\x2c" +
- "\x4a\x0d\x48\xf3\x1c\xde\xe2\x03" + "\x1a\xcf\x8a\xbc\xc7\xed\xd8\xf0" + "\x9c\x5a\x29\x68\x03\x33\x3e\xf2" + "\x7d\xa9\x46\xc5\x68\x5f\xdd\xfa" + "\xb1\xac\xf8\x96\xad\x97\x55\x89" + "\xe2\xda\x1b\x67\xd5\x49\xdd\xbd" + "\xf4\x43\xdd\x21\x28\xd5\xfc\x16" + "\x1a\x14\x19\x66\x12\x54\xa4\xa5" +
- "\xa0\x86\x0d\x03\xd3\x34\x5c\xc8" + "\x5e\xe9\x3c\x21\x80\x2e\x4b\xf1" + "\x7f\x6d\x7e\xf0\x9b\xed\x3e\xce" + "\x79\xec\xa3\xa3\x21\x3e\x6c\x47" + "\xd3\xa5\xde\xca\xf2\x11\xec\xb4" + "\xaa\x36\xa9\xcc\x12\x5f\xad\xd1" + "\x7d\x1c\xe6\x34\x9e\x60\x24\x17" + "\xa2\x7b\xd6\x2f\xf3\x0d\x52\xcc" +
- "\x2a\x7f\xa1\xa9\xa8\xe2\xfb\x6b" + "\x17\x50\xd9\x03\x60\x2f\xac\x1c" + "\x8c\xb4\xa2\x8e\x57\x62\xc0\x38" + "\x8a\xc3\x3c\xcc\x5c\x4d\xca\x21" + "\x91\x20\x45\x67\x54\x7a\x06\xff" + "\x2c\x46\x9d\x13\x5d\xdf\xbf\x63" + "\x6f\x00\x50\x14\xa1\x76\x13\x22" + "\xec\x9a\x2a\x33\x5e\xfe\x1a\xc8" +
- "\x41\xa1\xfe\xba\x99\x9a\xa0\x11" + "\x40\x16\xd4\x19\x4b\x41\xe0\x7f" + "\xd1\x09\xb6\xf3\x2a\x07\x6b\xd6" + "\xd2\x54\x55\xbc\x34\xde\xf7\x27" + "\x45\x7b\x51\xbc\xaf\x29\x65\xd6" + "\x9f\x8d\xd1\x12\x21\x35\xe4\x8b" + "\xd7\xef\x0d\x4e\xe1\x92\x21\x94" + "\x1e\xaf\xc0\x90\x1f\x87\x65\xb4" +
- "\xcf\x29\x9f\x43\x9f\xc7\x32\xfa" + "\x3b\x2a\xd8\x4d\xc0\x21\xf3\x7b" + "\xb1\xc1\xa2\xea\x54\x7f\x12\xff" + "\x18\x96\x5e\xf3\x2d\x5f\x36\xa8" + "\xdd\xf8\x0e\x4d\x02\x29\x2d\x85" + "\x4a\x8c\x22\x59\xc1\xe2\x5c\x39" + "\xd3\xfe\x5a\x21\xe8\x44\x9f\xb6" + "\xe3\x58\x74\xb2\x98\xf8\xc1\x16" +
- "\xbc\x25\x3f\xf3\xe0\x87\x0f\x17" + "\x98\xc0\x39\xc3\x67\xb6\xdc\x24" + "\xae\x3e\x07\xab\xa4\x02\x17\xbf" + "\x44\xfb\x8c\x23\x9c\x91\xa6\xad" + "\x75\x63\xee\xdd\x11\x85\x00\x53" + "\xad\x60\xdb\xb8\x85\xfa\x92\xdb" + "\x0e\x21\x21\xa4\x66\xa3\xb6\x50" + "\x8f\x55\x37\x4c\xeb\xf8\x7b\xdc" +
- "\x7e\x25\x4f\x2e\x08\xa1\x7b\xe4" + "\x7c\x9d\x68\x35\xdf\xe2\x0e\xcf" + "\xd0\xa0\x1b\x32\x8e\xc3\x8f\x8b" + "\x8b\x5e\x74\x0f\x4c\xc6\x70\x94" + "\x2f\xa2\x5f\xd6\xf5\x87\x38\xa7" + "\xbe\xef\xa7\xc2\x9b\xf8\x81\xa5" + "\x8a\xc9\xe4\xee\xa6\x0b\x5a\x83" + "\x71\x1a\x29\xa3\xe9\x83\xe1\x86" +
- "\x3b\x04\xe4\x89\xb0\x87\x54\xfb" + "\xd2\x9b\x79\x09\xef\x9d\xe4\x4d" + "\xbe\x60\xe7\xb3\xc0\x70\xa8\x9d" + "\x39\x15\xee\x89\xd3\x1d\x4e\x5e" + "\xdb\x05\x57\x91\xfa\x49\x38\x1b" + "\x81\x0e\xac\x5e\x94\xe1\xe5\x7c" + "\x5c\x3f\x0d\xb0\xa0\x72\x17\x7c" + "\xa1\xb5\x00\x6c\x76\x26\x79\x54" +
- "\x5a\xe2\x60\xc3\xbf\xb6\xe9\x8c" + "\x78\x1a\x5a\x07\x95\x51\x42\xe6" + "\xf4\x32\x17\x48\xa8\x56\xc7\x9d" + "\x7a\xb5\x32\x54\x0f\x44\xc0\x83" + "\x1f\x28\x20\xd7\xf1\xb3\x70\xc6" + "\x51\xe0\x35\xd1\x0e\x91\x05\x22" + "\xe7\x2b\x05\xdb\x0e\x4b\xd1\xde" + "\x39\xea\x68\xc5\x27\x3d\x7b\x69" +
- "\x4b\x71\xf6\x1a\xf1\x6c\x3a\x2e" + "\x6f\xb9\x13\x3c\xa6\x8e\x0f\x77" + "\x95\xff\x8c\x4c\xfb\x42\xc2\x98" + "\x91\xbe\xa0\x95\x0c\x9a\xec\x67" + "\xcf\xe7\x8e\xeb\x5a\x33\xf0\xee" + "\x24\xc4\x71\x33\xe7\x4c\xf3\x63" + "\x05\xe5\xed\x31\x95\x39\x0b\x98" + "\x19\x36\x3f\x9b\xfe\x3a\xe8\x7c" +
- "\x1c\x4a\x5e\x79\x2e\xbd\xf1\xb3" + "\x89\xca\xcd\xa1\x7e\x18\xd3\x85" + "\x3d\x68\x41\x35\x3c\x4e\xe4\x15" + "\x67\x40\xed\x80\x9c\x23\x8c\x2a" + "\xed\x08\xc5\xbf\x5a\x02\xe6\xbd" + "\xed\xc5\xf2\x3b\x31\x1e\x63\xb1" + "\x12\xa1\xd9\xe7\x3b\x3b\xcb\xb2" + "\xcc\x38\x78\x7c\x4f\xc1\x54\x05" +
- "\xbf\xe0\x88\xaa\x27\xb7\xe6\x1b" + "\x07\x35\xe8\x64\xba\xc2\x64\xd7" + "\x86\xeb\xd7\xba\x97\xf3\xbc\x4a" + "\x4f\xb7\x20\x79\xbf\x1c\xfd\xb2" + "\x2b\x03\x3d\xf1\x5b\x91\xe8\x65" + "\x22\xd6\xfb\x19\xbb\x4a\x26\x9d" + "\xb4\xa2\x48\x2f\x79\xaf\x62\x2f" + "\xec\xba\x19\x86\x5f\xb0\xa9\x22" +
- "\x33\x32\x45\xdc\x05\x90\xf2\xde" + "\xcf\x4b\xac\x2f\x7a\xc4\x08\xc2" + "\xac\x55\x3d\xac\xfe\xa3\x57\x60" + "\x07\x12\x2c\x90\x5d\x72\x23\x17" + "\xec\x0f\xeb\x33\x27\xc6\x31\x9c" + "\xbb\x63\x3c\xbb\xdb\xcc\x13\x49" + "\x38\x58\x30\x07\x2b\x54\x3e\x11" + "\x97\x2d\x0c\x31\x2a\xe7\x48\x9d" +
- "\x58\x6b\x31\xb8\x54\x27\xd5\xc1" + "\x60\xab\x1f\x81\x42\xa3\x35\x94" + "\x35\xc9\x02\x61\x76\xc3\x26\xe1" + "\x2e\x29\x25\x3e\x95\x15\x4f\x7a" + "\x59\xad\x2c\x03\xc3\xe7\xc3\x1b" + "\xb6\x1c\x2a\xfe\x81\x7a\x2d\x4b" + "\xcb\xa6\x8b\xe0\xe2\xf4\x0b\xa8" + "\x68\x02\xf9\x8c\xb2\xc9\xfc\xb7" +
- "\x96\x82\x28\x51\xa7\xd1\xe2\xa2" + "\xb0\xdb\x6d\xf6\x7b\x52\xca\xba" + "\xd4\x3c\x31\x80\x8f\x41\x9b\x40" + "\x8b\x6a\x3c\x87\xe8\x1a\x4b\x2b" + "\x5f\x29\x93\x2a\xc7\x5e\xe9\xb8" + "\x5f\x79\x5a\x2e\x90\x50\xf6\x0e" + "\xfa\x6a\x87\x2f\x88\xc8\x5a\x16" + "\x03\xe2\xc1\x25\xd9\x87\xca\x90" +
- "\x36\x79\xce\x93\xa7\x8d\x12\xbc" + "\xf9\x9d\xbe\x39\xd6\x9a\xc6\x3c" + "\x7c\xd3\xb6\xec\x1f\x99\x65\x69" + "\xa3\xff\xb5\xb8\xbf\x01\xe0\x64" + "\x0d\x01\x34\x93\xbf\x0a\x61\x5d" + "\x0c\x3f\xda\xdf\xb0\xee\x8f\x71" + "\xd7\x40\x05\x03\xa8\x1e\x2b\x5b" + "\x37\xd3\xb4\xf4\x73\x2f\xf2\x59" +
- "\x3d\xeb\xbb\xd9\xc4\x4e\x42\x54" + "\x1c\x92\xb2\xd7\xe3\xaf\xce\x34" + "\xc5\x37\x6d\x29\x2e\x02\x68\x5e" + "\xb0\x16\x9f\x35\x2b\x0a\x8e\xa2" + "\x73\x9d\x3f\xbc\xd9\x2d\xd8\xfd" + "\xff\xe1\xf3\xba\xf9\xa8\x39\x69" + "\xc4\x6d\x73\x31\x5c\xf4\xcf\x55" + "\xe7\xe8\x92\x78\x42\x56\x0f\x91" +
- "\x2c\x04\xd0\xaa\x05\xbf\x35\xdf" + "\xcc\x6a\xda\x28\x70\xec\x25\x29" + "\x5c\x3f\xaa\xe1\x04\xa8\x2a\x82" + "\x63\x8e\x34\x3d\x7d\xec\xed\xb5" + "\xcf\xb2\xf6\xb4\x30\x28\x36\x03" + "\x2a\xba\x6b\x09\x0d\xcb\xbf\x08" + "\x04\x3f\xec\x9f\x64\xe4\xfd\x8a" + "\x17\x4e\x43\x1c\x4f\x2e\x40\xfb" +
- "\x26\xc3\xce\x8a\x9d\x6c\xc4\xb6" + "\xc0\xb8\x6c\x29\x3d\x58\xf5\xac" + "\x08\x72\x07\xcf\xc6\xca\x52\x25" + "\xd6\x3d\xa0\x0d\x83\xef\x61\x52" + "\xb4\x46\x00\x5d\x30\xee\xa7\xf6" + "\x85\x3e\x0a\xcb\x96\x5c\x86\x24" + "\x89\x7a\xdf\x8b\x44\x91\x59\x71" + "\x83\x23\xe4\xf8\xdb\x5c\x1d\x22" +
- "\x09\xdc\x47\x35\xf4\xaa\x1d\x95" + "\xd4\xac\xae\xd4\x0b\xd5\x82\xb9" + "\x56\x11\x9f\x45\x2b\x94\xc9\xdc" + "\x72\xb2\x45\xfa\xe2\xb1\x67\x80" + "\xb7\xfb\xa3\xd6\x0c\xd0\xfb\xe2" + "\x37\x2d\x74\xca\xdd\x24\xfc\x46" + "\xdd\xfb\x26\x7b\x76\x44\x45\x66" + "\x7c\xf6\xd8\x2f\x61\xa3\xa6\x3f" +
- "\x60\x92\xe3\xdf\x49\xb3\x09\xde" + "\x93\x90\x54\x73\xf7\x12\x46\x98" + "\x02\x3b\x85\x67\x81\xe2\xed\x7c" + "\x03\x77\xd1\x29\xb4\x9b\x80\x7d" + "\xf0\xc4\x56\x27\xfb\x6b\x0b\x45" + "\x80\x2b\xf0\x93\xba\xf9\x9f\xc5" + "\x61\x95\xad\x20\x57\x54\x69\x3e" + "\xc7\xe2\x31\x33\xbe\xf0\x7c\x0c" +
- "\x03\x48\x9c\xca\x9b\x7c\x72\x42" + "\x5e\xda\xdc\x29\x46\x03\x14\x7c" + "\x17\xf6\x21\xba\x39\xab\xec\x00" + "\xc1\xef\xba\xf0\x96\xb1\x2b\xb5" + "\x74\x1c\xac\x73\xde\x03\xd5\x56" + "\x2c\x9d\x9c\x53\x0f\xce\x2d\x08" + "\x87\x95\x3c\xfa\x8a\x0a\x77\xf7" + "\x7d\x7e\x5c\x59\x7a\x5a\x89\x96" +
- "\x47\xfb\xfa\x6e\xd2\x69\xdb\x29" + "\x29\x74\x5e\xee\xf2\xe9\xb9\x04" + "\x03\x02\xe9\x88\x38\x1d\xf2\x91" + "\x15\xa6\xdf\x7a\x79\x8e\x3f\xcf" + "\x37\xe7\xeb\x61\x1c\x12\xf9\x89" + "\xbd\x03\xba\x06\x06\x69\x59\x87" + "\xb7\xfe\x78\x97\x72\x7a\xc2\x1a" + "\x18\x60\x72\x34\x3c\x72\x18\xe0" +
- "\x7e\x93\x70\xfc\x86\xcf\x42\x7c" + "\x05\x8f\x11\xa1\x75\x33\xf8\x5b" + "\x98\xbf\xe9\x39\x13\x54\xc0\x11" + "\xf9\x08\xfa\xac\x04\xf3\xa2\x4a" + "\xb3\x6f\x8b\xda\x1a\x4d\x61\xd6" + "\x0b\xad\x05\x5b\x77\x3b\x73\x92" + "\x66\xdd\x15\x30\xf1\xd5\x8e\xcf" + "\x32\x0a\x15\xd8\x18\xef\xad\x1b" +
- "\xed\xf9\x3f\xfb\x9a\x9b\x59\x2e" + "\x5c\x51\xf6\x17\xab\xe0\xc2\x28" + "\x49\xa4\x4d\x47\xfd\xe4\xbe\x1c" + "\x52\x44\x36\x4f\xa4\x79\x12\x07" + "\x55\xe8\xfb\x01\x66\xff\xab\x97" + "\xc4\x51\xda\x5f\xe8\x94\xe3\x3e" + "\x0b\x7c\x59\x67\xf6\x85\x03\x19" + "\x4b\xe3\x7e\xa2\xc6\xcc\x9f\x6e" +
-
- "\xf8\x92\xa4\xdd\xde\x7a\xc7\x3b" + "\x05\x72\x29\x78\xea\x3a\x1a\xc1" + "\x4c\x1b\x93\x34\xe7\xa3\x89\x5e" + "\xbb\x94\x56\x9f\x2e\x2e\x51\x17" + "\xb6\xf8\x7b\x17\xf3\x49\xc3\x5d" + "\x3e\xff\xc7\x08\xba\xa4\x2e\x23" + "\x5d\x14\x11\xf5\x16\x9d\x4f\x9c" + "\xc3\x79\xb3\x33\xa3\x09\xf1\xcc" +
- "\xa9\x24\xeb\x80\x70\x85\xe2\x60" + "\xfd\x0c\x8e\x48\x4d\xfb\xed\x7b" + "\xb8\xcd\x59\xc2\xd7\xbb\x1e\x72" + "\xa9\x90\x63\xbc\x55\xa8\x0d\x0b" + "\x70\x4c\x31\xde\xdb\x04\x4d\x2b" + "\x46\xe8\x32\x6c\xbc\x1f\xbf\xcd" + "\x9e\xfc\x62\xb1\xab\x3e\x83\x33" + "\xb7\x3a\xdd\xb0\x8b\xb4\x39\x99" +
- "\xb9\xdf\xc3\x97\xb1\x8a\x2b\xc4" + "\x54\x81\x16\xcf\xb0\x49\xa5\x55" + "\x92\x06\xb5\xc1\xe7\x48\x67\xad" + "\xcb\xcb\xc5\x6f\x0f\x78\x75\x27" + "\xc8\xd7\xc9\xe1\xb8\x80\xab\x4e" + "\x56\xcd\xdb\x3f\xe1\xda\x69\x8c" + "\xce\xea\x69\x99\xfb\xb4\xe6\x47" + "\x5a\xcb\x05\xa7\x85\x10\x2f\x00" +
- "\xb9\x0e\x1b\x71\x1f\x2c\x89\x96" + "\x54\xb9\x0a\x78\xc8\xf2\x05\xb9" + "\xdb\x92\x07\xa2\x09\x63\xe2\xac" + "\x26\xe1\x84\x06\xb3\xc9\x8a\xec" + "\x47\x24\x0a\xb4\xb6\xd8\x6a\x48" + "\x24\xfb\xe3\x9f\xc1\x1f\x12\x60" + "\x3f\x3b\x8e\x1a\xcf\xfc\x26\x56" + "\x94\xf3\xd1\x6a\x22\x86\x56\x4e" +
- "\x52\xbf\x37\x30\x18\x43\xfb\x2b" + "\xd7\x25\xc7\x78\xb5\x6d\x1e\xb6" + "\xd7\xe5\xb3\xbb\x60\x40\xfd\x8e" + "\x8e\x48\xac\xdb\x01\x47\x01\x2e" + "\x49\xa4\x0a\x36\x9a\xcf\x75\xac" + "\x08\x4d\x63\x79\x05\xfd\x0c\xb7" + "\xef\x15\xfb\xff\x6d\x53\x91\xa5" + "\x6c\x10\x7c\xd0\x82\x75\xc3\xb2" +
- "\x98\x4a\x6f\x23\x22\xbb\xfb\x5c" + "\xbb\x00\x68\x06\xe9\x59\x0c\x0b" + "\x74\x77\x9a\x5a\x8f\x9a\xc6\x4a" + "\x48\xc9\xbe\xd6\x04\xf8\x33\x2b" + "\x66\xc4\xe6\x32\x95\x92\x72\xb3" + "\x73\x9c\x59\x4e\x0f\x6d\x95\x68" + "\xcc\x31\x5c\x15\x9f\x24\x7a\xa4" + "\x4e\x28\xce\xe1\x0d\x0f\xd8\x24" +
- "\x88\xd1\x57\x64\x0d\xa7\x47\xf3" + "\x8b\x38\x7a\x8b\x6b\xa8\xed\x86" + "\x13\x60\xcd\x0c\x06\xff\xcd\xb7" + "\xb2\x3f\x05\xd0\xc7\xb6\xb1\xbe" + "\x9f\x0a\x24\x99\x87\x23\x02\x0b" + "\xb2\x89\x61\x77\x4f\x38\xbb\x1b" + "\x3a\x19\x66\x90\x1e\xe7\x95\x86" + "\x7e\xac\xff\x06\x97\x00\xb5\x2e" +
- "\x62\x3d\x8a\x4a\xc6\x46\x4b\x5a" + "\xd2\x43\x77\x24\xd0\xc4\x69\x84" + "\x33\xe4\xf7\x88\x3d\xa1\xb3\x2b" + "\x49\x58\xbe\x01\x10\x3a\xb2\x62" + "\x4c\x1a\x3d\xa6\xb4\x96\x35\xe8" + "\x3e\x3f\x18\x7d\xea\x7f\x4e\x45" + "\x1c\xb0\xaf\x17\x61\xce\x3f\x64" + "\x38\x36\x4c\x1c\xe6\xe5\x65\x4e" +
- "\x5f\xcd\x5f\xa3\x8d\x50\x65\x40" + "\xeb\xca\x5c\x49\x8c\xdf\x65\x89" + "\x62\xa9\xe1\x12\x50\xa8\x2d\x0f" + "\xc4\x1c\xcf\xc1\x94\x1b\x47\xee" + "\x75\xfb\x08\x0a\xc8\x9b\xf1\xce" + "\x91\x35\xde\x81\xf5\x58\x49\x70" + "\x88\x4f\xef\x3a\xb2\xf8\x67\x28" + "\x5f\x9a\x9f\xea\x84\x93\x74\x8d" +
- "\x8b\x50\x09\xdc\xe3\x30\xe8\xb7" + "\x55\x76\x31\x74\xcf\xd2\xf6\xfa" + "\x55\x03\x69\xdf\xeb\x6c\x60\x72" + "\xd6\xde\xc3\xd0\xb3\x92\xbb\x48" + "\x92\xf8\x7c\x5c\x84\x54\xb7\x65" + "\x1f\xf0\xd5\xd5\xc9\x7a\xcd\xf6" + "\x69\x1d\x40\x96\x59\x0a\xc3\xc2" + "\x78\x18\x92\xed\x50\x86\x26\x91" +
- "\xd5\x68\x26\x8d\xf9\x5f\x8b\xe3" + "\x65\x19\xd8\x7a\x1a\x28\x15\x07" + "\x11\xce\xc6\x03\x7c\xfc\xc8\x1b" + "\x36\x04\x65\x8b\xe2\xe6\xbe\xcb" + "\x08\x98\xdb\x0c\xe8\x0f\xb0\x06" + "\x15\xd3\x3e\xfe\x66\xe0\xd6\x17" + "\x18\x50\x0b\x4d\xc6\x38\x9d\x2e" + "\xef\xca\x4d\x84\x56\xfd\x8b\xab" +
- "\x45\x85\xdd\x6a\x17\x77\xdb\xe5" + "\x66\x9b\xc4\x72\x66\xcb\x71\x1b" + "\x77\x1d\x42\x68\x39\x07\x56\xd8" + "\xea\xaf\xe3\x83\xe8\x0f\x84\x03" + "\x77\x99\xc6\x1e\xd5\xda\x91\xb3" + "\x26\x67\x7f\x30\xb9\x3f\x24\xae" + "\x0c\x16\xca\xe8\x7b\xc8\x8a\xc8" + "\xf4\x55\xe3\x4c\xed\xcc\x74\x51" +
- "\x66\xf5\xa4\x53\x7d\x49\xf9\xd4" + "\x10\x68\xb5\x97\x64\x46\x73\x89" + "\x21\xa6\x94\x04\x74\xda\xe1\xf8" + "\x68\x1c\x01\x8d\x93\x6a\x54\x82" + "\x62\xc1\x1a\xc6\x19\xcb\x3a\x1f" + "\x3e\x0d\xad\xab\x9c\xfa\xf8\x52" + "\x43\xea\xb7\xb4\x23\x65\x35\x15" + "\x25\x81\x60\xae\x61\xad\x16\x5a" +
- "\x8e\x57\x81\xff\xf8\x67\x20\x75" + "\x7d\x44\x45\x90\x50\x21\x62\x78" + "\x6f\xaa\x05\x05\xcf\x2f\xc2\xc0" + "\x77\x1c\xed\x6b\xa6\xf0\x30\x10" + "\x39\xd7\x0b\x1f\x15\x9f\xf2\x31" + "\x85\xbe\xde\xe6\xc7\x89\x79\x2d" + "\x98\x7e\x67\x8e\x72\x0e\x07\x5c" + "\xd5\x1f\xe8\x06\xd3\x7b\x81\x0a" +
- "\x99\x22\xe0\x7f\x72\x6a\x81\x0f" + "\x19\x33\x4f\x29\xc2\xcc\x35\x63" + "\xbe\xc5\x45\x47\x9f\x17\x20\x38" + "\x6e\x06\x2f\x92\x82\xb7\x47\xe6" + "\x8a\xfb\xca\x02\xde\x49\x2e\xc2" + "\xcc\xec\xc2\xfc\xff\xc2\x9b\x29" + "\x82\x82\x0e\x6e\xa2\xee\x8f\x9a" + "\x05\x32\x89\xfe\x8b\x27\x27\xa6" +
- "\xe5\x13\xc6\xcb\xb6\x7e\xe1\xc1" + "\x1c\xa6\x7e\x49\x55\x1d\x13\x33" + "\xd5\xde\x7e\xaf\x9e\xd3\x69\x2f" + "\x1b\xf1\x6a\xde\x34\xf4\xc2\x73" + "\xfa\x75\xa3\xa4\x93\x24\xa5\x4c" + "\xc2\xc5\x33\xb8\x7c\x78\x06\x5f" + "\xcf\x71\x6e\x3e\x1f\x09\x4e\x81" + "\x66\x66\x74\x8b\x57\x1f\x45\x76" +
- "\x2a\xe9\x33\xb5\x8c\xc1\x57\x6e" + "\xde\xb5\xbf\x55\xfe\xca\x9b\x33" + "\xeb\xa2\xee\x01\x9c\x8b\xea\xa1" + "\xd6\xa7\xf8\xf4\xf5\xb4\x23\x60" + "\x42\x4e\xb5\x52\xae\xe4\x52\x5e" + "\xdc\x70\xbf\x84\xe0\x55\xba\x1c" + "\x8d\xa4\x06\x3f\xba\x7a\x09\x22" + "\xa9\xbf\x0b\xe9\x3f\x63\x13\x55" +
- "\x88\x93\x53\xe1\x82\xe0\xc7\x01" + "\x6b\x9c\x9a\x75\x30\x6f\x28\xfd" + "\xfb\xac\x6b\x17\x41\x10\x58\x94" + "\x53\xde\xc3\x3b\x7c\xf0\x80\xe5" + "\x2f\x77\x4d\x88\x75\x6f\xdb\xdc" + "\x4f\x9d\xbb\x40\xb8\x3b\x5c\xd7" + "\x11\x30\x08\xdb\x4e\x2e\x6c\xdc" + "\x8d\x29\x9c\xcd\xa2\x89\x87\xe1" +
- "\x82\xce\xa0\xff\x1c\x10\xf2\xa5" + "\x40\x34\x34\x4b\xe5\x36\x6d\x7c" + "\x03\xa3\x74\x0c\x29\x8d\x52\x82" + "\x17\xab\xd4\x04\xc2\xa8\x83\xd0" + "\x0d\x1e\x00\x76\xdd\x4e\xf1\xcf" + "\xc7\x2e\x66\xc9\x02\xc2\x11\xc9" + "\xc6\x78\x02\x81\x98\xfb\x34\xdb" + "\x68\xe3\xe4\x5e\x0e\x25\xb4\xa1" +
- "\x47\x13\xfe\x95\x84\xab\xe6\x5e" + "\x3c\x50\x24\x6f\x39\x6c\x0f\xab" + "\x6b\xdd\x86\x44\xfb\x3f\x7e\x80" + "\xf5\xfe\x02\x80\x74\x6c\x0b\xf0" + "\x99\x29\x86\xa7\xa6\xf9\xbf\x48" + "\x26\x9e\xd8\xbe\x6c\xa0\xe5\x85" + "\xeb\x19\x84\x3d\xaf\x11\xd3\x86" + "\x16\x3f\x73\x34\x78\xad\xf3\x24" +
- "\xaa\xa2\x6f\x5a\x5e\xee\xac\x9c" + "\x23\xe6\xd4\x75\x83\xd7\x86\x06" + "\x5d\x18\x28\x0b\x0a\x8d\x72\x3f" + "\x6f\xed\x3c\xdd\x60\xb0\x12\x79" + "\x5a\xcc\x14\xf0\xfa\x29\x31\x8d" + "\xea\x5a\x39\xd7\x5c\xde\x1d\x32" + "\xab\xba\x0f\x6b\xd6\xb2\x07\x96" + "\x99\xbd\xaf\x07\xae\x11\x59\xbc" +
- "\x44\x0d\x82\x11\x13\x55\x20\x5e" + "\x3a\x47\xc4\x86\xcc\x1b\x65\x0c" + "\xef\x0e\xd8\x9b\x2b\x0c\x23\x1d" + "\xe5\x5b\x51\x07\x12\x4a\x2c\x04" + "\x84\xe2\xe9\xbf\xa0\x7c\x51\x42" + "\x7a\x82\x69\x23\x78\x05\xf6\xe8" + "\x9d\x69\x38\x16\xf0\x04\x4f\x18" + "\x05\x6d\xbc\xf2\xed\x18\x46\x17" +
- "\x77\xf1\x1c\x65\xd5\x78\x37\x7c" + "\x0f\xbd\x52\xd8\x55\x55\x68\x1b" + "\xf8\x1f\x46\xf3\x82\xf6\x03\x4a" + "\x7b\xca\x12\x9b\x35\x8c\x09\xc1" + "\x01\x34\x98\x5d\xd2\x53\x05\x6a" + "\xb0\x87\xc6\x3d\x8f\x76\xc0\xe0" + "\x2e\x73\x4b\x34\x3e\xa3\x44\x7c" + "\x02\x0a\xb7\x64\xc3\x71\xb1\x5e" +
- "\x87\xd6\x68\x6c\xfc\x03\x3e\x5e" + "\xc7\x52\xf0\x1f\x3d\x2c\x73\x3e" + "\x7a\x6e\xd1\x6e\xa6\xef\xd0\xf2" + "\x46\xb7\x5b\xb6\x26\x2b\xd9\x63" + "\x7c\x86\x44\xdd\xba\x82\xcd\xff" + "\xb8\x81\xc0\xf8\x9e\x4a\x1b\xa7" + "\x85\x87\x6c\x73\xa7\x76\x16\x6c" + "\xd0\x32\x89\x9d\x16\x06\x2c\xbe" +
- "\xf2\x39\x09\xb5\x49\x88\x63\xd1" + "\x8e\x85\x90\xba\x2c\x69\x33\xfc" + "\x8e\x00\xa6\x2f\x91\x0a\x4a\x2b" + "\x40\x39\xa3\x97\xc7\x90\x01\xc0" + "\x10\x3c\x2d\xd6\xfd\x14\xff\x8a" + "\xc1\x89\x19\x57\x09\x4d\xc6\x98" + "\xba\xfe\xe5\x00\x28\xea\x24\x82" + "\xc1\xc5\xa9\xf9\x0c\xb9\x3c\x91" +
- "\x9f\x1c\xca\x9e\x4b\x1a\xfa\x7b" + "\x35\xe5\xe5\x8c\xdc\xc1\x0b\x96" + "\x0a\xc3\xee\x17\xf3\xd9\x67\xe2" + "\x38\x7d\x25\x6c\xef\x89\xfb\x06" + "\x6d\xa2\x64\xd3\x9a\x99\x28\x23" + "\x58\xab\xea\x26\xcb\x94\xb7\x69" + "\x96\xa5\x5b\xb8\x1f\xab\x28\xad" + "\x94\xaa\xd0\x56\xf3\xbf\xdc\x05" +
- "\x02\xa6\xa1\xa3\x80\x9e\xd7\x14" + "\xaf\xd6\xc3\x22\x5e\x18\x4f\xfc" + "\xc8\x67\xf6\xb7\x6b\xa5\x2f\x23" + "\xf8\xea\x3e\x8f\x91\xbc\xd0\x49" + "\x48\xe2\x70\x58\xb9\x51\x91\xe8" + "\xab\x09\x44\x3d\x70\x0e\xab\x70" + "\xe8\x83\x07\x80\x10\xe9\xd8\x22" + "\x62\x77\xac\xa2\xb2\x7b\x2c\x9b" +
- "\xc4\xfb\xcf\x2b\x28\x6d\x37\x53" + "\x7a\xdb\xea\x06\xa7\x17\x88\x70" + "\x69\xae\x35\xcd\x05\x0e\xf5\x6f" + "\xde\x7f\xbc\x74\x75\xfb\xb5\x63" + "\xc4\x08\xfe\xe7\x53\xe9\xc9\x71" + "\x18\xca\x83\xf5\xd4\xbf\xd8\xb4" + "\x5c\x1c\xe8\x45\x82\x78\x8d\xde" + "\x38\x41\x47\xe0\x3c\xe9\xf5\xa5" +
- "\x32\x19\x83\xf0\x4b\x5f\xd7\xd4" + "\xc9\x8c\xfe\x77\xc4\x0a\x77\x5e" + "\xa2\x72\x2e\x86\x48\xe7\xb5\x52" + "\xfe\x35\x1d\x50\x82\x54\xa4\xe9" + "\x87\xb1\x9a\x4a\x42\xe7\x93\x8a" + "\x17\xa0\x8c\xe8\x6d\x50\x72\x5a" + "\xef\x2d\xeb\x01\xb2\xdc\x80\xe6" + "\x9d\x20\x68\xba\xe6\xa4\x5a\xdc" +
- "\x31\x9f\x3c\x29\x0f\x16\x6c\x42" + "\xa7\xd7\x64\xe8\x33\x63\xb5\x8e" + "\x30\xba\xbb\x3e\x02\x64\x11\xbe" + "\x02\xa3\xd5\x2f\xe3\xba\xc2\x64" + "\x7b\xff\x5a\x26\xe1\x01\x06\x80" + "\x14\x4b\xfd\x66\x80\xa8\xd8\x52" + "\x9c\x5a\x07\x46\xe7\x20\xba\x5a" + "\xc6\x34\x12\x7e\xf8\x2b\xa3\xda" +
- "\xc8\x2f\x56\xc4\xa5\x97\x74\x45" + "\xf8\xbf\xe2\xf3\x8a\x8e\xfd\x44" + "\x59\x7d\xc9\x49\x35\x49\x23\x19" + "\xe4\xbb\x36\x40\x56\x07\xe3\xda" + "\xed\xa0\xad\x49\x51\x78\x37\xf1" + "\xaa\x87\xef\x80\xc5\x62\xd3\xc6" + "\x6a\x5c\xa5\x30\x12\x43\x97\xc5" + "\x37\x5a\xec\x15\xe5\x07\x84\x56" +
- "\xe0\xb7\x4d\x69\xef\xbd\xf9\x80" + "\xc6\xdd\xfc\xb9\x87\x87\xca\xed" + "\xe1\xdc\xb8\x03\x34\x1c\x98\x51" + "\xa1\x0b\xe1\x70\xf1\xdc\x74\x42" + "\x1a\x6d\xef\x6d\xb8\x43\x27\xf7" + "\x66\x18\xdb\xeb\x70\x16\x5b\xd2" + "\x58\x6f\x0c\x05\x8c\x1e\x49\xc4" + "\xf5\xd7\xfb\x87\xab\xb2\xe2\x2b" +
-
- "\xec\xf8\x11\xd1\x9d\x5c\x0e\x3e" + "\x60\xe7\xc4\xb7\x8d\x3f\xc3\xbc" + "\x51\x2a\x39\xbd\x91\x9a\x2f\x70" + "\x2d\xe9\x32\xc1\x95\xa7\xa4\x7d" + "\x1b\x15\xb1\x0b\xe3\x0a\x0b\x1a" + "\x51\x22\xe3\x02\xc8\xba\xfe\x54" + "\x78\x9e\x4e\x69\x82\x50\x3a\xea" + "\xb8\x40\xfe\xe4\xc1\xfe\x8f\xe5" +
- "\x0b\x12\xc4\x29\x9d\x34\xb8\xfb" + "\x15\xd9\xd0\xc0\x1f\x39\x94\x9f" + "\x51\xba\x10\x54\xa7\x4f\x07\xc4" + "\x11\x59\x0a\x15\xf6\xdb\x6a\xa6" + "\x38\xca\xbf\x34\x3c\x54\x64\xc1" + "\xfc\xcc\xe1\xb9\x60\x75\xf2\xe0" + "\x9c\x21\x20\xe8\x53\x0f\xda\x99" + "\x7a\x99\xb4\xc6\x98\x44\x23\xe8" +
- "\xe4\x19\x6e\x51\x13\xc5\x23\x7b" + "\x93\xd5\xc4\xc5\x47\xe8\xe2\x56" + "\xf6\x1e\xe7\x5c\x73\x7d\x72\x9f" + "\xc5\x44\x9a\xf7\xa6\x04\x63\x5b" + "\x33\xe4\xb7\x3a\x36\xa7\x38\x66" + "\x83\x2f\x74\xfe\x70\xa4\xde\x1a" + "\x9f\xc1\x7f\x5b\x54\xb8\x54\xe0" + "\x98\x06\x1d\xba\x1a\x38\x35\xf9" +
- "\x36\x49\x8e\x91\x9d\x4f\x50\xb5" + "\x82\x39\x51\xb2\xf6\x5e\x03\x65" + "\xb9\x9c\x4d\x6f\xc2\xa0\x53\x05" + "\x09\x55\xa8\xbe\x56\x0d\xb1\x6c" + "\x11\xda\x42\xa2\xb7\x57\xd9\x48" + "\x68\x72\x2b\x67\xdd\xd3\xa4\x16" + "\x6b\xa9\x02\x85\x7c\x63\x7e\x3d" + "\x3b\x46\x0d\x73\x2b\x03\xc7\x27" +
- "\x6f\x42\x46\x58\x7d\x6b\x36\x55" + "\x1d\x44\x7d\x24\x89\x9e\xd0\xe7" + "\x48\xbf\x6f\x73\x4d\x40\x0b\x51" + "\x7d\xbd\x84\xe7\xd0\x03\xa0\x7f" + "\x96\x95\xfd\x17\x4f\x61\xf7\x25" + "\xdb\x98\xcb\x35\xa1\xe0\xe0\x49" + "\x6a\xa7\x83\x2e\x7b\x95\x65\x2c" + "\xf8\xe0\xdb\xcd\x8d\xda\x40\x5d" +
- "\x9d\x93\x95\xa5\xb4\x8b\xf6\x37" + "\x17\x02\x74\x28\x79\x64\x55\x03" + "\x12\x76\xad\x84\x7c\x0e\x74\x8e" + "\x5f\x69\x44\x90\x43\xc8\x9b\xd8" + "\x4d\x18\xa9\x85\x5d\xda\xf3\xf7" + "\x74\xb0\xc0\x9f\xbb\x63\x25\x56" + "\x8e\x88\x8a\xf8\xaa\xe6\xd2\x06" + "\x7c\xbe\x1f\x16\x43\x86\x2d\x61" +
- "\xb2\x0b\x53\x54\xa3\xbb\xb3\x9f" + "\xea\x69\x08\xcb\x77\xef\xe3\xbd" + "\x63\x11\x43\x0b\x46\x90\xbc\x89" + "\x35\x9a\x81\xe4\xd2\xd7\x03\x4d" + "\x82\xa7\xb6\x43\x9e\x4f\xae\x33" + "\x86\xa6\x88\x9c\x07\xb3\x6d\x21" + "\xd9\xed\xff\x00\xe0\x88\xdd\x91" + "\x40\x48\xbd\x12\x9f\xda\x80\xb2" +
- "\xd7\x8c\x53\x3e\x91\x86\x8f\x45" + "\x53\xad\x08\x8e\x6c\x1f\x00\xa7" + "\xff\x15\x5d\xbf\xe6\xc6\xb8\x52" + "\xdd\x15\x12\x01\xa4\x34\x82\x54" + "\x45\x40\x5b\x3d\x2d\x9d\x5a\xff" + "\x90\x41\x90\x4a\xb6\xee\xff\xb0" + "\x8b\x7f\x60\x48\xa4\xac\xa3\x55" + "\x2a\x67\xa0\x30\x5c\x66\xbd\x8c" +
- "\x37\x59\x7f\xf3\x73\x35\x7f\xa3" + "\xa5\xfc\xe4\xd1\x7d\x6c\x0f\xeb" + "\xfc\xb0\x8a\xac\x54\xa5\x65\x29" + "\xac\x76\x46\x27\x6c\xf5\xfb\x17" + "\x20\xd7\xf7\xac\xd9\x6b\x2f\x2e" + "\x66\x47\x22\x10\x88\x8f\xfc\x41" + "\xef\x3b\xd5\x85\xb3\x14\x7a\x51" + "\xd1\xa7\x76\x7d\xa5\x27\xe3\xda" +
- "\xdc\x82\x5f\x1f\x89\x5c\x5d\x51" + "\x9e\x07\x61\x63\xd7\x67\x7f\x9a" + "\x30\x53\xa3\x11\xe3\x81\xda\xa8" + "\x1b\xbe\x18\x4b\xc4\x90\x49\xe4" + "\x59\x3e\x10\xaf\x95\xed\xd5\xc7" + "\x61\x92\xac\x8d\xa7\xab\xe8\xec" + "\xd3\xb8\x94\x93\x99\xb0\x82\xbe" + "\x83\xfe\xad\x16\x9a\xf0\x30\x68" +
- "\xb1\xd9\xd7\x94\xc1\x1a\xc4\x43" + "\x17\x7f\x2e\xc8\x82\xdd\xaf\x5b" + "\xca\x0f\xda\x5f\xc1\x14\x06\xdf" + "\xad\x37\xae\xa8\xa7\x43\xb0\x74" + "\x4c\x73\x71\x9e\xa1\xaf\xa6\x3b" + "\x2e\x0f\x45\x9c\x7e\x43\xd5\x15" + "\xb1\x42\xe2\x67\xfe\x83\x58\x4a" + "\xc2\x53\x19\x2c\xc2\xbd\x43\x51" +
- "\xf9\xf5\x53\x6b\x7c\xce\xa9\xa2" + "\x99\x6d\x17\x1b\x95\x65\x24\x64" + "\x1b\x08\x5c\xb9\x36\x8d\x29\xb1" + "\xe6\x9e\x9a\x1d\xb8\x5b\x50\x53" + "\xb0\x70\xba\xf2\x61\x9e\x6f\x3f" + "\x53\xd4\xfa\x8a\xc9\x16\x7e\xd0" + "\x6a\x4a\xeb\xe7\xbb\x94\x16\x9f" + "\x8e\xbc\xb0\x3c\xd9\xce\xeb\xdf" +
- "\x0b\x39\xf3\xb1\xf2\xd7\x76\xc6" + "\x72\x12\xb6\xa5\x8c\x1b\x7a\x9f" + "\xa9\x27\xe1\xc2\xc9\xbf\xbe\x4e" + "\xbf\x97\xd9\x5d\x0c\x50\x02\x46" + "\x0f\x23\x11\x47\x1c\x77\x09\x7f" + "\xc1\x09\x0f\x02\x7c\xb3\x8e\x05" + "\x8b\xe3\xe5\xfe\x4b\x3d\x69\xab" + "\xc0\xcb\x53\x46\x1f\xeb\x89\x92" +
- "\xa7\xf5\x70\x17\x39\x2b\x4d\xa4" + "\x82\xeb\x44\x0e\x91\xd7\xd4\xe4" + "\x2a\x71\x69\x3f\x1e\x9d\xe6\x42" + "\x0e\x82\x6a\xac\xd6\xc4\x11\xbf" + "\x4c\x22\xc4\x42\xe5\xf3\xe7\xb5" + "\x1c\x94\x9d\x44\x1c\xe8\xb4\xd6" + "\x78\xe8\x50\x54\x16\xbd\x72\x5d" + "\x54\xac\x25\xee\x8a\xe2\x61\x6a" +
- "\x78\x25\x95\xab\xc7\x9d\xda\x54" + "\x0b\x4d\xe8\x26\xf2\x3d\x42\xb5" + "\x42\x20\x87\x9b\xeb\x4e\xb6\xa8" + "\xdf\xf6\x90\x59\x82\x57\x20\xac" + "\x7a\xc7\xf4\x21\xeb\x96\xf6\x4f" + "\xaf\x73\xb2\xaa\xe4\xc3\x79\x1a" + "\xf1\xb3\x36\x94\x2e\x92\xbc\x29" + "\x7a\xa2\xd9\xd6\xf8\x7e\x80\xff" +
- "\x6c\x74\xf6\x33\xf8\xa8\xf3\xc7" + "\xca\x90\xa9\xfe\x65\x6f\xe4\x21" + "\xa9\xb0\xdd\xca\xc5\xd5\x5f\x91" + "\x55\x45\x61\x78\x16\xf0\x41\xbd" + "\x58\xfb\x6f\x42\x34\x44\x6f\x34" + "\x04\xc2\xdb\x14\x36\x94\x55\x80" + "\x7f\x9b\x96\x5a\xfe\x20\xdd\xf3" + "\x9a\xa3\x99\xe8\x56\xe9\x59\x9d" +
- "\xc0\x56\x6f\xd0\x8f\x68\xca\xe4" + "\x72\x79\x02\xdf\x0d\xf7\x8a\xa4" + "\x9d\x60\x9a\x5e\x04\x0f\x1f\x69" + "\x0e\x27\x61\xee\xcd\x82\xdd\xa9" + "\xd3\x18\xef\xa0\x63\xca\x03\x89" + "\xbd\xa3\x6c\x3d\x35\xee\xb7\x9f" + "\x03\x7d\xf4\xab\x9c\xa0\xb4\xa7" + "\x8e\xde\x67\x1c\x01\xda\xda\x4c" +
- "\x92\x15\x92\x74\x37\x56\xa0\xf9" + "\x31\x9d\xbb\xb9\x1d\x26\xf1\xb4" + "\x59\x54\x9c\x4e\xb7\x29\x14\x55" + "\x53\x1f\xa7\x6e\x6f\x2e\x18\xbe" + "\x73\x05\xc5\xdf\x7c\xb0\xa3\xd3" + "\x44\x8d\xbe\x62\xda\xaf\xa1\x9b" + "\xd3\x65\xab\x52\xcb\xd2\xcf\x9b" + "\x02\x18\x57\xa9\x47\xd5\x11\xdf" +
- "\x75\xa6\x38\xe0\xc1\x7d\x12\xac" + "\x20\x63\x5c\x8c\xf3\xef\x9d\x72" + "\x53\x2c\x0d\xa9\xd4\x8f\xdf\xb7" + "\xd3\x7c\x1e\x68\xec\xb0\x74\x9b" + "\xe5\x07\xb4\xda\x23\xa6\xb5\x5c" + "\xc6\x40\xb3\x76\x15\x36\xbd\xcd" + "\x2c\x39\x28\x7d\x5a\x41\x84\xa1" + "\x30\x78\x6f\xe9\xd8\xc1\x84\xc1" +
- "\x61\xfc\x43\x5e\x84\xb6\x89\xb1" + "\x57\xab\xd3\xe0\x75\x23\x28\xf3" + "\xa8\x1d\x18\xb1\x67\x4b\xa3\x4f" + "\xb8\x52\xee\x99\xb2\xd0\x1e\x62" + "\x76\x06\x99\xad\xe1\x8d\x17\x9b" + "\x65\x40\xd5\x56\x7b\xe6\x1d\xd5" + "\x01\xc2\x38\x75\xc4\x27\x2c\x2a" + "\x5c\x0f\xa4\x38\xc8\x6e\x85\x33" +
- "\xc3\x85\x7e\x2f\x3b\x30\xa9\x86" + "\x9b\x8f\x98\x71\x21\x46\xce\x5f" + "\xb5\xac\x38\xc1\xf6\x5b\x93\x5b" + "\x12\x12\x66\x25\x67\x7d\xea\x30" + "\xa2\xb9\x1a\xe5\xf4\xb5\x1e\xef" + "\x78\x7c\x06\xae\x8a\xc9\x87\x05" + "\xa6\x9c\xca\x77\x3c\x1b\xce\xb3" + "\x57\xf0\xb5\x54\x4d\x3d\x55\x2a" +
- "\x3d\xab\x21\xcd\xb2\x68\xe4\x89" + "\x92\xd3\x93\xc3\x22\xf0\x04\xe5" + "\xf9\x3a\x01\xa5\xd4\xe1\x21\xab" + "\xcb\x8a\xc2\xc2\x78\x3f\x28\xe3" + "\x9f\xf9\x6b\x22\xf6\x35\x8b\xf3" + "\x69\x1e\x29\x0e\x74\x42\x35\xe8" + "\x2d\x16\x0c\xb2\x15\x3a\x67\x61" + "\xbe\xbd\x4f\xb0\x75\xdc\x01\xc1" +
- "\xa0\x94\x18\x0b\xe1\x56\x71\x2c" + "\xc0\x68\x1c\xd8\x01\x40\x03\x92" + "\xb5\x15\xb1\xc8\x00\x5d\x22\xed" + "\xf2\x07\xb9\x83\x22\x9c\x7f\x23" + "\xc0\xe2\x70\x44\x2f\xf3\xa2\x0e" + "\x95\x4e\xbe\x58\xc1\xf7\x25\xb7" + "\x63\x54\xae\xb1\xfa\xca\x1d\x0f" + "\x04\xfc\xa2\x1b\x87\x51\xed\x59" +
- "\x57\xd6\xdd\x06\xe2\xbe\xdb\x35" + "\x6d\xa9\xf3\x2f\x11\xdd\xcb\xe7" + "\x58\xe7\x6b\x07\x68\x19\x38\x88" + "\x5d\x1f\xc9\x08\x72\x7e\x73\x2d" + "\x76\x37\xec\x86\x62\xab\x83\x5f" + "\xa1\xa7\x5f\x94\x9d\x64\xaa\x98" + "\x33\x09\xef\x72\x37\xec\x77\xf4" + "\xb1\x17\x8c\x09\x1e\x2b\xf5\x66" +
- "\x11\x07\x52\xc9\xde\xcc\xb0\xd1" + "\xbf\x84\x8b\x3c\xed\xe4\xa9\x55" + "\x14\xf3\xfe\xa1\x39\xbd\x26\x94" + "\x2b\x3f\xb9\x6e\x8e\x63\x5f\x4f" + "\x1b\x34\xf9\x2b\xd3\x1e\x2a\xba" + "\xa9\xd5\x42\x4d\x21\x13\x3c\xd6" + "\xc5\xc7\x6d\x31\x89\x4a\x96\xd2" + "\x51\x18\x51\xca\x06\x96\x75\xd1" +
- "\xbd\x7b\xe5\xcf\x0e\xc1\x2e\xb1" + "\xb5\xc2\xa0\x35\x56\xb6\xc7\x82" + "\xbd\x67\x1c\x16\xcd\xd5\xc7\xdd" + "\xcc\x32\x3a\xae\x85\x89\x2e\xe3" + "\x29\x55\x1a\xd1\x44\x94\xba\x7a" + "\x1a\xfa\x27\x24\x02\xed\x64\xe9" + "\x0a\x77\xa1\x24\x2d\x39\x28\x15" + "\xcd\x2f\xc7\x12\x2c\xce\x52\xa1" +
- "\x87\x11\xc5\xf8\xea\x9f\xf6\xed" + "\xa7\x4d\x1e\x74\xec\x67\xbb\x05" + "\x45\x43\x11\x08\x32\x0f\xdf\x47" + "\xb1\x92\x97\xbb\x07\xcb\xfa\x56" + "\xe4\x29\x62\x8f\xe9\x07\xe0\xf3" + "\x0f\xba\x6f\x52\xf4\x03\xd1\x62" + "\x79\x9d\x33\xb0\xf7\xbe\x33\x4f" + "\xc1\xfe\x9b\xb5\x7b\x35\x41\x98" +
- "\xba\xf5\x8e\xe2\x67\x0b\x1e\xae" + "\x69\xe1\x18\xcb\x99\x46\x9a\x2c" + "\x20\xbd\x6b\x1e\x33\x0e\xcd\x0e" + "\xd2\x81\x5e\xaf\x0e\x36\x1b\x57" + "\x45\x1d\x1c\x10\x58\xea\x9f\xcd" + "\x52\x04\x88\x18\x8e\x78\x51\x66" + "\x46\xd4\x8d\x1f\x35\x26\x97\xa9" + "\xd0\x81\x72\xe3\x22\xd0\xbe\x44" +
- "\x1f\xac\xdb\x60\xea\x6e\x0e\x83" + "\xf7\xa2\x06\xda\x84\xc4\xd8\x23" + "\x5b\x53\xca\x50\xb0\x14\x67\x89" + "\x9b\x7a\xd9\xeb\x44\x36\x8d\xdc" + "\xb4\x77\x21\xb1\xfa\xf9\x6e\x10" + "\x9c\x5d\x4d\x53\x64\xf4\x9b\xf7" + "\x0b\x36\xab\xa6\x49\xa3\x37\x25" + "\x4f\x74\x0c\xa0\x53\x42\xc5\xc7" +
- "\xd4\x69\xcf\xfa\xe5\x2d\xf8\xf0" + "\x4c\x34\x75\x47\x76\x7e\x3b\x36" + "\x04\x6d\xe3\xb2\x12\xf3\x94\x68" + "\xa5\xc9\xd1\x11\xfe\xb4\x6c\x3c" + "\xf2\xe1\x08\x40\x39\xc3\xd9\x85" + "\x6c\x32\x9f\x24\xea\x85\x9a\x5e" + "\x06\x5e\x8c\x67\x0a\xc6\x35\xdc" + "\xa9\xfb\x86\x9f\x4f\x94\x8b\xc0" +
- "\xb0\x4a\x75\x68\xd1\x61\xd6\x24" + "\x76\x9a\x42\x6f\x1d\xce\x1f\x80" + "\x69\xe7\x8c\xa5\x5f\xa8\x68\xc0" + "\x2b\xca\x5e\x5d\x54\x5c\xc3\xed" + "\xd1\x60\xf6\xa3\x6f\x27\x31\xea" + "\x67\x71\xfc\xb8\xbe\x4e\x18\xa0" + "\xae\xb0\x8d\x1d\x1a\xf2\x20\x0f" + "\x12\x5e\xc3\x56\x5f\x09\x6d\xd9" +
- "\x5f\xaa\x33\xb7\xa9\x0b\x2f\x3c" + "\x35\xf2\x5a\xf0\xcb\x47\xce\xde" + "\xa5\x82\xac\xa2\x15\xf7\xe3\xf8" + "\x8a\xf1\x03\x22\x41\xa6\x7b\xc9" + "\x60\x10\xc1\x09\x04\x55\xaf\xc3" + "\x2d\x51\xaf\x46\x05\x2c\xea\x56" + "\x46\x81\xf2\xf3\xaf\x8d\xc2\xfa" + "\x94\xf4\x9e\x95\x3a\xb4\xfa\x87" +
-
- "\x5f\x10\xc5\xd4\x41\x16\x89\x09" + "\x65\xbd\x7f\x6d\x8e\x0f\xe8\x1a" + "\xb0\xbd\xe6\xbe\x5f\x22\x67\x9d" + "\x60\xd8\xc4\x7f\x59\x3b\x43\x3b" + "\x38\x56\xe8\x93\xb6\x6d\xe6\x44" + "\x2f\x86\xe9\xe3\x52\x92\xb5\xf7" + "\xec\x32\x5c\x66\x57\x51\x78\xdb" + "\x50\x2f\x36\xae\xd7\xef\x2f\x70" +
- "\xc3\xb0\xef\x0f\x5d\x47\x54\x37" + "\x5d\xc3\xd7\x46\x6b\xb5\x8f\xd4" + "\xa4\x98\x37\x36\x33\xb6\x70\xa0" + "\xe6\x98\xdb\x8f\xd2\xf3\x89\xae" + "\x4c\xd1\x63\x63\xc8\x89\x0b\x97" + "\x7d\xd2\xab\x67\x21\x75\x81\x89" + "\x21\xa0\xd5\x44\x74\xd4\xf7\x9b" + "\xee\x2a\xc7\xca\xaf\x3b\x08\xb3" +
- "\x44\x9a\x94\xbe\xde\x41\x97\x38" + "\xa5\x4f\x6a\x54\x88\x93\x8e\x63" + "\xdc\x7b\x04\xa0\x9c\x41\xe6\x3f" + "\xca\x57\xea\xaa\x48\xf6\x47\x70" + "\x17\xab\xfb\x41\x90\x8a\xe4\x54" + "\xa2\xdb\x6b\x57\x28\x0b\x8e\xda" + "\xdc\xfd\x2a\xc7\xbc\xee\x07\xe8" + "\xbf\x77\x25\xf4\x6d\x33\xd3\x07" +
- "\x25\x09\xe2\xbf\x44\xc2\xa8\x62" + "\x67\xe8\xdc\x8f\xc3\x9a\xc1\x91" + "\x63\x70\x38\xdd\xd5\xa5\x96\x5a" + "\xf6\x24\xd3\x21\xd4\x87\xd5\x61" + "\xea\x73\x71\xa3\xa2\x73\x76\xe8" + "\x65\x8b\x77\x53\x08\x80\x84\x23" + "\x3e\xb4\xba\x05\x1e\x44\xf8\x10" + "\xbe\xef\x21\x46\x12\xfe\x11\xfa" +
- "\x7b\x5d\x68\x81\x2e\x77\x7b\x04" + "\x76\xa9\x34\xbf\x81\x7d\xf2\x23" + "\xef\x48\x5f\x91\xe2\x08\x76\xc2" + "\xc3\xd5\x21\xa5\xfa\x43\x0b\x3b" + "\x84\x72\xca\x63\x26\xfb\x13\x76" + "\x37\xb8\x4d\x1d\xb4\x29\x57\x7f" + "\x6b\x52\x3b\x58\x98\x48\xb1\x87" + "\xd1\xd3\xad\xbb\xa6\x32\xb7\x00" +
- "\x96\xe3\x48\x20\x26\xf4\x02\x8e" + "\xe4\x9d\x3d\x38\xb6\x50\x6b\x43" + "\xad\x85\x1e\x47\x81\x34\x8d\xf7" + "\xd6\xc8\x05\xd0\x6a\xea\x01\x8b" + "\x07\x5c\x01\x97\xee\xaf\xc7\xd3" + "\xae\xa2\x3b\x4e\xa9\xf1\xcd\x46" + "\xd2\xa1\xd3\x83\x01\xe5\x42\x7a" + "\xf4\xdf\x41\xb5\x68\x52\x4b\xd5" +
- "\xbc\xe9\x23\x4e\x30\xcf\x24\x3f" + "\x24\x36\x6e\x12\x16\xf8\x87\x43" + "\x61\x6d\x0b\x3b\x03\x6a\xa4\x26" + "\x7c\x77\x2d\x8b\x45\xc8\x1b\xaf" + "\x9c\xe7\x7d\x52\xba\x01\xc4\x25" + "\xb6\xbb\x61\x42\xd4\x46\x13\x0e" + "\xc7\x4b\x7b\x28\x4b\xc4\x96\x4b" + "\x2f\x56\x54\x52\xc7\x93\x84\x65" +
- "\x20\x4a\xa2\xb8\xfe\x49\xf9\x23" + "\x3f\xa5\x2c\xf5\xd1\xfe\xeb\x17" + "\x53\x48\xfb\xbc\xbe\x1b\x69\x9b" + "\x5d\xa0\x78\x62\x6b\xff\x17\x56" + "\xbd\x9e\xc9\xe3\xc5\x34\x1b\x24" + "\x6a\x15\x84\x17\x2e\x24\x64\xfc" + "\xdf\x67\x5d\x69\x2f\x48\x06\x42" + "\x11\xc0\x27\xee\x0e\xce\x67\xb9" +
- "\x5d\x0b\xc8\x21\x51\x37\xdb\x65" + "\xa0\xcc\x1e\xa3\x3c\x56\x7a\x2e" + "\x7e\xa0\x38\x52\x4e\xfc\x6f\xe5" + "\x54\xd8\xce\x32\x66\x29\x6c\x3d" + "\x85\xb8\x70\xaf\x1a\x7d\x9d\xe9" + "\x59\x64\x68\x2d\xd9\xba\xc3\xaf" + "\x5b\xba\xc8\x0c\x46\xbf\x78\x9c" + "\xa3\x5a\x95\x18\x19\x95\x43\x5a" +
- "\x14\xe3\xe4\x5f\xa8\x17\xb5\xf8" + "\x6f\x90\xb8\xfc\xd0\x34\x02\xe6" + "\x23\x1b\x06\xf2\xac\x42\xe5\xff" + "\x9c\xb5\x4c\x6b\x1f\x19\x7e\x28" + "\xd8\x77\xd8\x09\xdc\x7d\x85\x21" + "\x41\x89\x67\x14\x8c\x47\x23\x1c" + "\xa4\x5e\xe0\xb6\x56\xc0\xf0\xbb" + "\xfe\x94\x15\xb0\x53\x4b\xda\x82" +
- "\x08\x86\xdb\xfa\x91\x67\x52\xf7" + "\xf6\xcd\x74\x7b\x2d\x83\x9e\x04" + "\x34\x0a\xb9\xc2\xcc\x81\x35\xa4" + "\x0c\xb1\x60\x93\xb8\x9e\x63\x73" + "\x1b\xa7\xe4\xe1\x1f\x33\xba\x4f" + "\x19\xf9\x72\x80\x93\x6b\xfd\x6f" + "\x32\x90\x67\x65\x1c\x27\x53\x6e" + "\xce\x72\x42\xf1\x44\x64\x20\x67" +
- "\x34\x58\x33\xb2\xa3\x34\xf7\xc0" + "\x60\x68\xef\x90\x5a\x20\x26\x95" + "\x0d\xbb\xe2\x04\x17\xe7\x8b\xcb" + "\xfa\x83\xf3\x02\x1e\x87\x18\x24" + "\x57\xc1\x82\x40\x81\x76\x17\xd7" + "\x73\x00\xc2\x29\xd0\x4a\x91\xcc" + "\x28\xe7\x87\xe5\xeb\xc1\x86\xf1" + "\xfd\xd5\xbc\x61\x22\x3c\xdb\x6f" +
- "\xe9\xf8\xf9\xf2\xa6\x14\xd0\x30" + "\xd2\x49\xec\x4f\x23\xce\x3e\x96" + "\xd9\xa8\x05\x96\xc5\x25\x20\x86" + "\x9a\x92\xf8\x19\x45\x44\x87\x39" + "\x6a\x47\xbf\x12\x65\xff\xb6\x01" + "\x91\x7d\xcf\x09\xd8\x64\x8a\x59" + "\xca\x56\xbe\x93\x49\x77\xec\xd7" + "\x15\x36\xb3\xcb\x85\x97\x89\x10" +
- "\xad\xe3\xee\x02\xfd\x92\xa0\xb8" + "\x70\x52\x14\x30\x35\x3d\x6b\xa8" + "\x75\xb6\x12\x85\xc6\x98\x3d\x32" + "\x0f\xb4\xeb\x62\x85\xc7\x8b\x4b" + "\xde\x9c\x3f\x41\x54\x1f\x30\x7d" + "\x64\x56\xab\x2b\x4f\xfb\xe4\xa5" + "\x23\xec\xbf\x1c\x2d\x25\x2b\x1d" + "\x0d\x12\x77\xe1\xbb\x76\xd5\xfc" +
- "\x34\x1a\x73\x83\x3e\x7d\x42\x04" + "\x8e\x6e\x83\xed\x8e\x02\xb9\x2b" + "\x7c\xca\x12\xb6\xf8\xcf\x6a\xb3" + "\x3a\xc7\xd9\xd3\xef\xe5\x8f\xb8" + "\xb3\x4e\xea\xed\xc6\x6b\x2a\xbe" + "\x77\xec\x8e\x48\x33\x31\xb9\x43" + "\xe1\x06\x71\xb1\x66\xf5\x1f\xf4" + "\x32\xfa\x4e\x65\x72\x91\x9e\x46" +
- "\xa3\x3f\xc2\x41\x04\x0f\x48\xb4" + "\x2e\x9a\x98\xc1\xb0\x2e\x71\xb4" + "\xa7\x9c\xa2\x93\x0f\xba\xcb\x3c" + "\x8c\x42\x19\xd6\x14\x5c\x20\x6e" + "\x86\x16\x64\xb3\x57\x79\xdb\x90" + "\x4e\x8b\xac\x45\x1d\x69\x32\x04" + "\x50\x03\x4e\xf6\xac\x59\xa7\x07" + "\x17\x25\x97\x9c\x9c\xd8\x14\x05" +
- "\xc3\x7f\xe6\xa8\x7f\x14\x01\x17" + "\xbe\x85\x20\xab\x8b\x0b\x2e\x9e" + "\x57\x4e\x28\xac\x24\x18\x65\xd5" + "\x64\x36\x89\x74\x25\x43\x0d\x89" + "\xa3\x68\x5e\xc5\x6e\x5e\x7c\x8a" + "\x5a\xc8\x39\x43\x0b\xe9\x12\xbf" + "\x55\xb6\x22\xf9\x85\x6b\x84\x31" + "\x00\xd7\xf4\x0b\x4d\xce\x54\x9a" +
- "\x95\x42\xa1\xf1\x3a\xe8\xf4\xd7" + "\xf9\xd4\x85\xb2\x5c\x95\x6f\x91" + "\xba\xda\xff\x99\xe0\xb0\x7b\xe5" + "\x52\xd1\xb0\xea\x34\x30\xa4\x28" + "\xf8\xce\xa9\xb8\xa2\xff\x36\x0a" + "\x1a\x05\xec\xb9\x7e\x40\x17\x55" + "\x72\xe6\x68\xea\x96\x60\x79\x9c" + "\xfb\x77\x3c\xfb\xfb\xb5\x3d\x85" +
- "\x1a\xa5\x64\xe8\xa9\x4b\x47\x21" + "\x8b\x1b\x8a\x6e\x99\x76\x26\x6c" + "\x28\x0a\x12\x94\x26\x36\x82\x7c" + "\xdb\xa5\x83\x83\x48\x9a\x1e\xe6" + "\x6d\x21\x84\x9f\x03\x50\xd7\x7d" + "\x85\xcd\x43\xad\x07\x0d\x02\xab" + "\x59\xc6\x12\xda\x48\xae\x37\x94" + "\xad\x52\x54\xe6\xeb\xc2\x49\x64" +
- "\xc1\xd7\xf9\x2c\x1c\x4c\x7c\xcc" + "\xab\xe5\x95\xee\x6a\x88\x20\x13" + "\x0c\x17\xae\xbe\x56\x90\x7b\xbb" + "\x62\xd6\xc0\xdb\x50\xb2\xa5\xc8" + "\x03\x23\x1d\xc1\x32\x14\xd8\x4e" + "\x9f\x76\x03\x1f\x12\x69\xa6\x7d" + "\x28\x98\x53\x84\xfd\xa5\xc7\x3a" + "\x02\xdd\xcc\x3b\x94\xda\xda\x14" +
- "\xd1\xb0\xf6\x7e\x21\xc3\x84\x8b" + "\x22\x3f\x93\x7c\x7a\x47\xa9\x52" + "\x82\x0b\x44\xfd\x8a\x72\xf6\x5e" + "\x5e\xbd\xe4\x6c\x59\xd8\x3b\x5c" + "\x3e\x2d\x2c\xf2\xf5\x80\x8b\x91" + "\xc5\x6c\xbb\xb7\x40\x50\x8d\x36" + "\x1c\xa1\x95\x26\xa1\x42\x61\xb6" + "\x70\xea\x19\xeb\x3a\x58\xac\x60" +
- "\x37\x24\xab\x0e\x98\xbb\x7c\x31" + "\xc8\x54\x26\x5e\x55\x8c\xc0\x8c" + "\x7f\x30\xd8\xe6\x20\x65\x2d\xfe" + "\x93\x89\x42\x57\xf3\x47\xf1\xe9" + "\xf1\x6c\xfd\xd2\x14\x7d\x9c\x5f" + "\xb0\xcb\x4f\x2d\x64\xd0\xec\xa3" + "\xf7\x41\x73\x8e\xf0\xfe\x83\xad" + "\x5c\x11\x63\x3a\xa0\x23\x3f\x64" +
- "\x43\xb7\x5a\xe6\xab\x78\x8a\xd3" + "\x9c\xc8\xed\x35\xb1\x75\x7c\xbf" + "\x68\xf5\x0d\x53\x2e\x75\xd8\x3d" + "\x82\xc6\x08\xe3\x76\x4a\x5c\xf8" + "\x37\xcf\x8a\xe6\xb2\x55\x99\x4c" + "\x85\xaf\x32\xab\x3d\xdf\x44\xa5" + "\x93\xf4\x5c\xa2\xf5\xc3\x8e\x4b" + "\xeb\x2f\x62\x1a\x64\x27\x8f\x4d" +
- "\x49\xbc\xdc\xf0\xaa\xf7\xb4\x7b" + "\x5b\xb4\xbb\x70\xf9\x51\xe5\x7d" + "\xe5\xa2\x2c\x9f\xe4\xf3\xd0\xcf" + "\xef\x76\x5c\x1f\x09\x87\xe5\xec" + "\xae\x79\x7d\x16\xdd\x0e\x92\x32" + "\xc1\x7e\x7d\xfa\xa2\xf8\x9d\x03" + "\x91\xaf\x30\xbb\xc0\x06\x62\xf4" + "\x59\x6b\x67\x22\xf5\xe2\xf5\x1f" +
- "\x66\x1d\xa5\x6e\x39\xa0\xf4\x11" + "\x26\x7a\x7d\x80\x45\x14\x6c\x50" + "\x24\x9b\x5a\x75\x05\x57\xda\x60" + "\x9e\x31\x1a\x1f\x32\xcc\xc8\x8f" + "\x7d\xd6\x33\x94\x4d\x2d\x64\x83" + "\x96\xd2\x7d\x6a\x8f\xcb\xa5\x7f" + "\x07\xde\x7b\x9b\xdb\x91\x65\x57" + "\xfb\x16\x97\x41\x25\x3d\x17\x13" +
- "\xff\x40\xb3\xd5\x9d\x59\x30\xea" + "\xc5\x76\xfe\xb0\x97\x52\x6b\xfc" + "\xdc\x5a\x8f\xab\xc8\x68\x69\x1c" + "\x8d\x92\x1c\x90\xf5\xc7\x23\xf7" + "\x02\xd4\x73\x97\x21\xc3\x03\x42" + "\x47\xdd\x51\x1b\xa3\x6a\x7c\xdf" + "\x3c\xe2\x2b\x55\x7a\xe3\x49\x3d" + "\x87\x6e\x5a\x0b\xe8\xbe\xfe\x57" +
- "\x39\xe7\xd8\x7b\xe4\xbe\xec\xc5" + "\x75\xbf\x63\xae\x94\x49\xd4\x79" + "\x23\x89\xfb\x38\x0f\xd0\x8b\x16" + "\x30\x31\x53\xd0\xe4\x8e\xd4\x75" + "\x33\xdf\x5c\xdb\xaa\x77\x4f\x55" + "\x69\x67\x69\x3c\x96\xe8\x96\x33" + "\x4e\x67\xfd\xd3\xf2\xdb\xdd\x2f" + "\xe5\xe3\xd0\x99\xee\xf6\xb8\xbb" +
- "\x70\x2f\xae\xcb\x51\x06\xb9\x51" + "\xeb\xa8\xaa\x93\x05\xbc\xc4\xef" + "\x99\xf4\x1d\xdd\x89\x86\xcd\x8e" + "\xa5\x67\xf3\x22\xa8\x99\xee\x1a" + "\xc5\x74\x82\xae\xb9\x85\xd4\x95" + "\x9c\xb3\x30\x7d\x45\xd4\x14\x6c" + "\x81\xef\xc1\xbc\x0b\xa9\xfe\xba" + "\xed\xa2\x59\xa4\x7a\x31\x5f\x7c" +
- "\x27\x42\xf4\x4e\x75\x10\x21\x01" + "\x96\xf4\x20\xdc\x6e\xed\x7b\xa1" + "\xcd\x53\x98\x81\x24\xe4\xdf\x0c" + "\xe7\x2c\x1e\xf7\x98\x32\x79\x13" + "\x7b\x30\xbe\xdb\x78\x30\x1f\x3c" + "\x36\x99\xee\x76\x0e\xc2\xd1\x6d" + "\x20\xaa\x3c\x42\x57\x4b\xee\x23" + "\x0e\x84\xfb\x8e\x3b\x79\xc3\x4a" +
- "\xa0\x8c\x1f\xed\xeb\x38\x44\x93" + "\xa2\x25\xbb\x4e\x58\x66\x54\x3e" + "\x6f\x89\x69\xc0\x0e\xaf\x15\xc4" + "\x3d\xa4\x5a\x9a\xb0\xdd\x3e\xc1" + "\xf6\xb8\x9e\xd4\x4f\x20\x04\x7a" + "\x70\x16\x4f\xd7\xfc\xbd\xd5\xd0" + "\x58\x05\xfc\x56\x86\xe2\x97\x36" + "\xde\xba\xce\x01\x71\x73\x20\x10" +
- "\x2b\xa8\x47\x06\x90\xe6\x87\x5f" + "\x4f\x05\x40\x8f\xd4\x0e\x8e\x90" + "\x03\x38\x85\x79\xd4\x33\xf6\xa9" + "\x52\xb2\x28\x4a\x9a\x3c\xd1\x8e" + "\x64\x0f\x46\x1f\x76\xf6\x2e\x3e" + "\x36\x63\xd0\x36\x9b\x0b\x93\x53" + "\x9b\x97\xc4\x8f\xac\x73\x70\x34" + "\x97\x55\xcd\x5e\x0e\x0e\x38\x84" +
- "\x39\x3c\xfe\xc4\x6b\x2c\xb2\xe3" + "\xdf\xeb\x7b\x6c\x53\x81\x4a\xba" + "\x59\x34\x69\x25\xb7\xb6\x3a\xf2" + "\x11\x2b\x92\x14\x70\x37\xbc\x53" + "\xdb\x60\xfc\x5a\xab\xc8\x45\x46" + "\xa3\xf2\xb9\x20\x55\x23\x02\xaa" + "\x07\xc5\x0f\xce\x4c\x95\xa2\x52" + "\xe7\xc2\xe1\x7c\xbb\x31\x27\x8c" +
-
- "\x89\xb8\x8f\xe4\xc2\x91\x70\x6a" + "\x06\x9d\x8a\x7b\x13\x2c\x88\x26" + "\xe2\xa0\x82\x1b\x63\x86\x49\xa2" + "\x2d\x15\x18\x35\x36\xd7\x4e\x84" + "\xc7\x27\x6e\xd8\x6f\x47\x2f\x28" + "\xdc\xef\xaf\x04\xca\xda\x4e\xa0" + "\x4d\xe3\x19\x61\xbc\x6e\x25\x8b" + "\x8b\xd7\x87\x07\xe9\x13\xa4\x56" +
- "\x50\xbe\x74\x5a\x1d\x06\xee\x82" + "\xf5\x6f\xa1\xde\xc4\x81\x17\xe4" + "\xa2\xc8\xbf\x99\x1e\xc8\xb0\xe0" + "\x2d\x7e\x54\x0b\x69\x4d\x4f\x62" + "\xe4\x9a\xcc\xbd\x5d\x54\x83\x3a" + "\x8e\x1e\x9b\x40\xb6\xdb\x73\x25" + "\x39\x35\xc9\xa6\xc4\x60\x29\x48" + "\x98\x87\xe1\x5a\xad\x59\x10\xf0" +
- "\x96\x9d\x55\x4d\x27\x1e\x15\x38" + "\x01\x6c\xdb\xb8\xd3\xc0\x18\x4f" + "\xaf\x21\x99\x6f\x83\xaa\xa3\x49" + "\x29\x60\x04\x8c\x7b\xb2\xea\xdb" + "\x3b\xbf\x40\x70\xaa\x9e\x2b\x24" + "\x91\xb0\x14\x16\xe5\x79\xc4\x39" + "\x5d\xaf\x4b\x0e\x2b\xde\x8e\x33" + "\x45\x39\xa5\xf0\xb7\x92\xb1\x5b" +
- "\x5f\x79\x12\x31\x97\x9f\x5c\x71" + "\xe1\x6e\x4e\x98\x37\x44\x24\xe8" + "\xcd\x6b\xb6\xec\x58\x48\xcb\x55" + "\xee\xfb\xaf\xab\x35\x67\x13\x7c" + "\x8e\xc3\xbe\x5d\x95\x15\x66\x54" + "\x53\xd1\x8a\x38\x2c\x78\xc0\x51" + "\x2f\x95\xe0\xc6\x3a\xc5\xa4\x9b" + "\xa8\xdf\x21\x1b\x2a\x78\xe6\x27" +
- "\x65\x7f\x5d\xec\x51\xc2\x89\x7d" + "\x87\x40\x39\x90\x16\x56\x8f\x0c" + "\xb3\x1a\x69\xf0\xfc\x1c\x9e\x60" + "\x21\x0b\xb2\xe9\xbf\x00\x03\x2a" + "\xf4\xfa\x14\xb1\xad\x2f\x53\xbf" + "\xd1\xf5\x1b\x52\xb9\xc0\x8f\x32" + "\xde\x36\xfc\x3b\x3c\xf9\x51\xbd" + "\x60\x5f\x4e\x7a\x0e\x05\x89\xd9" +
- "\xc2\xdb\xd2\x4e\x3d\x90\x2f\x68" + "\x83\x2d\x3b\x7c\xc8\x59\xba\x0e" + "\x35\x93\x7e\x9c\x4d\xc8\x9d\x8e" + "\xd7\x26\xb2\x0e\xb0\x21\x9b\x5f" + "\xae\x7b\x26\xaf\x94\xd3\x3b\xe3" + "\xae\x15\x2e\xbe\x25\xcc\x86\xaa" + "\x00\xc5\x8e\x6a\x7d\xf6\x0b\x4f" + "\x58\x06\x63\xf9\x44\xaa\x46\x58" +
- "\x78\xc2\xe0\xe7\x38\xba\x86\x67" + "\x6f\x2e\x8b\x58\xce\x87\xbf\x09" + "\x3a\xee\x5f\x46\x22\x70\x3b\x72" + "\x94\x23\x68\x64\x14\x41\xb8\x08" + "\x29\x46\xe6\x29\xe0\x2c\xb5\x0e" + "\x43\x8e\xa7\xcc\x8f\x0e\xb6\xad" + "\x91\xa9\x54\xb6\x62\x70\xdd\x20" + "\xe5\x6f\x9a\xc6\x28\xd4\x81\x42" +
- "\x15\xbf\xc2\xe2\x40\x97\xb0\xfe" + "\x04\x97\xe9\xa9\x05\x22\x7a\x62" + "\x65\xc5\xfb\xc2\xd0\x73\x8d\xec" + "\xe8\x8d\x0c\xc2\x8f\xed\x3e\x22" + "\x49\x3b\x36\xa8\x83\x25\xe3\x1e" + "\xa6\xb0\xc2\xc9\xb9\x6c\x0b\x1a" + "\x5c\xc8\xdb\x90\xd2\xc3\xf7\x49" + "\xac\xc1\xf4\x1e\x97\xbb\xdf\xa8" +
- "\xe1\x2e\x1e\xc0\xa3\x7c\x25\x5c" + "\x61\x69\xc3\x27\x14\x3a\xb4\x1f" + "\x24\xf3\x72\x34\xcb\xa7\x94\xd5" + "\x10\xbe\x0a\x66\x24\xc0\x5e\xc1" + "\xed\x4c\x61\x6b\x49\xd4\x76\xb1" + "\x85\xb8\xdb\x62\x4d\x73\x04\x0b" + "\x87\xb5\xdd\x36\xc6\x53\xb7\x2c" + "\x0c\x34\xcd\x14\xe6\x80\x1c\x9a" +
- "\xab\xc2\xc7\x65\x4c\x4d\xb3\xaf" + "\x84\xea\xc5\xe2\xe7\x10\x46\x1d" + "\xb5\x4a\x3c\x97\x1b\x6d\x3f\x89" + "\xc4\xa5\x5b\x94\xe9\xd7\xcd\xa3" + "\xee\x17\x44\x06\x83\x49\x51\x60" + "\x2b\xdf\x6b\xad\x3c\xb2\x59\x14" + "\xc3\x26\xf7\x5c\x41\xc3\xb2\x23" + "\x4a\x35\xd6\x32\x35\x96\x82\x3a" +
- "\xcd\xe7\x6f\xc0\x96\x56\xf6\xe9" + "\x15\x3a\xfd\x9a\x57\x30\x06\x51" + "\xed\x60\x53\x18\xa6\xac\xcd\x3d" + "\x2f\x3d\x85\xc1\x3d\x70\x41\x27" + "\xa0\xf1\x33\x1a\x4a\xd8\x8a\xbd" + "\x7c\xb0\x5c\xc3\x8c\x69\x6c\x5f" + "\xb9\xe6\x61\x65\x19\xd1\x2b\x21" + "\xd7\x4f\x7b\x61\x7e\xcd\x49\xf1" +
- "\x18\x2c\x19\xab\x1f\x90\x4f\x29" + "\x4f\x16\x30\x70\xfe\xcb\x5f\xec" + "\xa6\x6b\x24\xe2\xb7\xfc\xe2\xe2" + "\x0c\x1a\x1a\x22\xb3\x88\x7c\x1e" + "\xc5\x88\x2d\xc9\x93\xdd\xc7\x72" + "\x59\xfb\x06\x11\x8e\x14\xc2\x41" + "\x14\x0f\xf6\xa0\xf5\xd4\x7d\x54" + "\x31\x0f\x96\x63\xb2\x52\x9b\xed" +
- "\xf8\x2b\xe8\x30\xc5\xc9\xe3\x1c" + "\x2a\x77\xbb\x0d\x42\x25\x66\x4d" + "\x14\x72\xc1\xd9\x60\x5a\xe2\x19" + "\x55\xfa\x22\x77\x4c\xf8\xbc\x13" + "\xa7\xf7\x9e\xf8\x0e\xca\x8a\x22" + "\x55\xd4\x3e\xfd\x2f\x4e\xd6\x03" + "\x04\xc9\xe6\xdd\xf5\x90\xc3\xf1" + "\x8a\xe1\x78\x76\xa6\x52\x14\x73" +
- "\x58\xb3\xa5\xb0\xeb\x49\x83\x6c" + "\xd6\x2e\x7e\x9e\xc2\xc5\x54\xb1" + "\xdb\x62\xa4\xed\xcf\xec\xd5\xca" + "\x69\x6b\xe6\x2d\xe4\xdb\xd6\xf2" + "\xb2\xe5\x65\x86\xf3\xed\x6a\x42" + "\x23\x57\x7f\x7b\x13\x85\x8a\x48" + "\x86\xb3\xcb\x8b\xb3\x43\xcc\x15" + "\x79\xd8\x91\xd7\xf3\x0a\xad\x27" +
- "\xba\x2c\x63\xa0\x61\x6e\x00\x3c" + "\xcd\x5c\xb3\x45\x48\x92\x0d\x92" + "\x65\x7f\x5c\x7c\xfb\x79\x33\x4b" + "\x0b\x05\x5e\xb0\x10\xdf\x6c\x52" + "\xae\xf1\x1b\xd2\x36\xe9\x88\x31" + "\x2f\xbd\x4b\x62\x39\x7b\xe0\xb3" + "\x41\xa5\x67\x13\xf3\xfc\x9b\x7b" + "\x27\x79\x36\x8a\xc8\x8e\x9f\x03" +
- "\x4f\x36\x6e\x84\x6e\x23\x6c\xc1" + "\xa0\x0c\xa5\xde\x7c\x52\x33\x7f" + "\x6d\xb8\x26\x09\x75\x07\x81\xc4" + "\x0c\xe7\x98\x05\x09\x36\x2a\x6c" + "\x24\xe9\x24\xf0\x52\x5e\x75\xa6" + "\xca\xaf\xb4\x9d\xa4\x07\xfa\xe0" + "\x90\x17\x83\x66\x7d\xce\xc3\x15" + "\xd6\xb0\xcb\xa6\x50\xf3\x4e\x5b" +
- "\xf4\x82\x69\x43\xe0\x04\x85\x34" + "\x79\xec\xe3\xd8\xee\x05\x49\xc9" + "\x9e\x17\x09\x35\xcb\xfd\x2c\xb9" + "\x14\xd9\xe6\xf9\xd0\x66\x52\x24" + "\x55\x69\x31\xad\xd0\x50\xaa\x8b" + "\x60\x7f\x22\xca\x79\x5c\x23\x77" + "\xd8\xf9\xe5\x51\xc9\x27\xc9\xf2" + "\x0f\x94\x79\xe6\x30\x8c\xbf\xeb" +
- "\x69\x59\x20\xb6\xc4\xaf\x4a\x2c" + "\x4f\x85\xc7\xf6\x02\x3f\x56\x42" + "\x48\x3b\x98\x1d\xd5\xce\x6a\x01" + "\x55\x97\x94\x99\xd8\x56\xb3\xfe" + "\xd7\x9b\xa3\xd1\x81\x2c\x2a\x8c" + "\xe9\x4a\x93\xe6\x0f\x34\x44\x8f" + "\xda\x04\x79\x44\x1c\xf9\x8c\x14" + "\x26\xa9\x51\x0f\x5f\x18\x40\x73" +
- "\x90\x69\xac\xce\x66\x5f\xe9\xe4" + "\xce\x16\x6c\xbe\x16\x1d\xdc\x17" + "\xbe\x0c\xad\x45\x55\xa0\x67\x29" + "\xb6\x7e\x6f\x71\x97\x2f\x0e\xdd" + "\x91\x3b\xc3\x2d\xf3\x7f\x8b\x33" + "\xde\x76\xe9\x2f\xf5\xae\xf6\xdc" + "\x6e\x3f\x19\x43\x1c\xf7\x1c\xf5" + "\xe3\x77\xc0\xe8\xc4\x44\xe4\x15" +
- "\x46\xab\x09\x74\xfb\x00\x8f\x2f" + "\xb2\x89\xe2\x80\xe6\x78\x7e\x05" + "\xd1\xe5\x88\xa8\x2c\x02\xe5\x03" + "\xe2\xe4\xed\x9d\x1a\x11\x87\x3c" + "\x0b\x46\x09\x78\x1c\x0e\x9b\x5b" + "\xc7\xab\xc9\x71\x52\xc8\x51\xe7" + "\xc9\x1d\xcc\xc7\x28\x4e\x94\x8b" + "\x08\xfa\x3c\x1d\xfa\x1f\x20\x4f" +
- "\x49\xc0\x9f\x0f\x2d\xfe\x78\x60" + "\x1a\xd1\xf6\x40\x50\x97\x9d\xd9" + "\xb7\xc0\x54\x08\x97\x9a\xae\x87" + "\x79\xfb\x02\x93\x9c\xb0\xce\xf4" + "\x3f\xa8\x32\x2c\x68\x01\x2f\x50" + "\x24\x50\x68\xb1\x71\x27\x35\x1e" + "\x19\x2b\x79\x66\xf2\xf6\x0d\x97" + "\xfd\x87\x8d\x9c\xbb\xd0\x07\xf5" +
- "\xce\x21\x67\x3e\x5c\x90\xfc\x02" + "\x4c\x67\xb3\xd0\xda\x70\x2d\xd5" + "\xa4\x0d\x81\x18\xca\xe5\xc2\x5d" + "\x99\xdd\x69\x5c\x73\xb2\x84\xa9" + "\xa4\x5c\xde\x84\x27\x25\xb9\x63" + "\xc4\xde\x52\xc8\x72\x98\x1c\x2f" + "\x09\xde\xe3\xc2\x93\x35\xb0\x18" + "\x2f\xdc\x13\x98\x01\x0b\xd7\x19" +
- "\xb2\x38\x63\x42\xce\x40\x4e\x15" + "\xc9\x88\xaa\x96\x00\xb0\x2c\x7b" + "\x25\xf9\x51\xad\xfc\x01\xc9\xd5" + "\x10\xee\xd0\x7e\x6c\x21\xbd\x5a" + "\x64\xe1\x7d\xf8\x57\xd5\xc3\x73" + "\x6d\x51\x39\xe1\xdc\xd1\x3a\x69" + "\x7a\x54\xbd\x3e\x3a\x7b\x76\xb4" + "\x82\xa9\xf4\x20\x4c\xc2\xb3\xb8" +
- "\x29\x1d\xdc\xa6\x2d\x6b\x80\x42" + "\x44\xe1\x71\xf8\x09\x00\x03\xd3" + "\x76\x92\xf4\xaa\x33\xb3\xfe\xa1" + "\x4b\xc0\x0b\xc7\x9e\x3b\x58\xb5" + "\x20\x5f\x69\x95\x78\xbe\xb0\x1d" + "\xb5\x12\xd0\x89\x11\x18\x84\xfc" + "\x43\x16\xf6\x05\x72\xf2\x09\x64" + "\x28\x31\x88\xd5\x74\x41\xd3\x40" +
- "\x7b\x7c\x56\x08\xcd\xa0\xfb\x64" + "\x54\xfb\xcb\xa2\x0d\x59\xea\xc9" + "\x73\x0d\x6d\x13\x16\x77\x6f\x66" + "\x0d\xa3\xf2\x38\x48\x96\xa0\x2c" + "\xa9\x0c\x4e\x0f\x24\x45\xa5\x7f" + "\x4b\xb8\xbe\xc1\xa8\x01\x33\xef" + "\x2a\xb9\x62\xbc\x0e\x93\xcb\x45" + "\xea\xcb\xb6\x9b\x05\xc7\x4a\x96" +
- "\x33\x98\x41\x67\xf5\x96\x91\xd7" + "\x08\x7b\x3b\x86\x52\xe2\x59\x60" + "\x0c\x70\x56\x1c\x17\x18\xda\x84" + "\xc4\x3e\x8d\xb2\x56\xee\x58\x57" + "\xa6\x0e\x3b\x01\x1d\x77\xa2\x7d" + "\xb9\xe9\xc5\x54\x4b\x52\xdf\xfd" + "\x80\x5d\x30\x24\xf8\xfa\xf4\x7d" + "\x3f\x76\x97\x3a\xbf\xc1\xf5\x58" +
- "\x1f\x26\xf5\x81\xcc\x71\xf6\xea" + "\xef\x83\xfe\xbc\x06\x35\x08\x7d" + "\x6e\x53\x88\x31\x0b\xc5\xcd\x94" + "\xcd\x3e\xdd\x24\x41\x2c\x0b\x41" + "\x0c\x52\x05\x02\xcc\x99\xcb\x57" + "\x6d\x44\x06\x5f\x68\xa2\xf3\x23" + "\x17\x4b\xa0\x49\x43\x7e\xb2\xb2" + "\x12\x5a\x78\x81\xf3\x66\xb2\xab" +
- "\x42\x60\x69\x7c\xf1\x37\xaf\xa5" + "\xde\x38\x25\x4a\x2c\xa2\xcb\xd4" + "\x00\x26\xa4\x9e\x95\xb9\x1c\x21" + "\x89\x98\x06\x7b\x41\x5f\x10\xcd" + "\x74\x1e\xb8\xdd\x19\xcf\xe1\xb1" + "\xca\xb8\x57\x51\x89\x2d\x2f\x47" + "\x85\xb8\x9d\xee\x08\xb0\x6f\x08" + "\x31\xd1\x26\x0f\x70\xd5\x5c\x36" +
- "\x5a\xfe\xb7\x66\x5d\xba\xa7\x00" + "\x56\x5d\xfd\x05\xac\x74\x86\x81" + "\x57\x5a\x14\x04\x3c\xb0\x8f\x68" + "\x2c\x83\xd5\x97\x88\x65\xc1\x76" + "\xa7\xab\x45\x12\xd8\xdc\xf0\xa0" + "\xe9\xf6\x47\x18\xaa\x7c\x07\xdd" + "\xd0\xad\x34\x0d\x14\x53\x03\xf9" + "\xed\x3d\xb7\x48\x11\x7c\xe3\x22" +
- "\x53\x70\xbe\xa2\xbb\x02\x4b\x28" + "\xd6\xa6\xb9\x7a\xc6\xf7\xbb\xdc" + "\x30\xa5\xf7\x20\x9c\x55\x25\x44" + "\xc8\x67\x87\x18\xfa\x2d\x1f\x96" + "\xc4\x80\xdc\x70\x35\x94\xfd\xe2" + "\x20\x41\x78\xf0\x63\x6b\x4d\x10" + "\x22\x71\x56\x53\xc1\x2b\x59\x7f" + "\x77\xad\x88\xf6\x46\x12\xbc\xf6" +
- "\x06\xb0\x0a\xb7\x6b\x43\xfe\xfd" + "\x1d\x1a\x99\x18\x19\xd1\xe7\x57" + "\xb0\xc0\xd4\x34\x28\x42\x54\x3a" + "\x04\x84\xb5\x32\xd4\x1d\x09\x26" + "\x99\xf8\x2a\x27\xfc\x6d\x11\x8b" + "\x77\x87\x11\x34\x87\xdc\xf8\x51" + "\xbc\xf0\xa7\xdf\x40\xa3\xf0\xc0" + "\xdd\x97\xad\x56\xf6\xa5\xc5\x22" +
- "\xe9\xdd\x15\x0f\x05\x4c\x21\x05" + "\x82\x2b\x5f\x0d\xa8\x76\x7a\xa4" + "\x62\x2b\xe8\x62\x30\x4d\x25\xbb" + "\xee\x55\xc9\x3e\xe0\x5f\xa0\x11" + "\x36\x9b\x52\x9d\x6e\xf4\xaf\x7e" + "\xf6\x3d\x9e\x8f\x01\x13\xab\x55" + "\x98\x76\x31\x99\x71\xe3\x63\xc4" + "\xad\x47\xda\xcc\x38\x14\x25\xfd" +
-
- "\x4e\x89\xfb\xdb\xf3\x22\x31\xe1" + "\x18\x4b\x27\xce\xf6\x79\x9b\xbe" + "\xdf\xaa\x58\xca\xe5\x9d\xa4\x85" + "\x51\x73\x48\x11\x58\x77\x95\x24" + "\x99\x90\x93\xbb\x61\xef\x1d\x11" + "\x94\x36\xd1\x26\x4a\x97\x6a\x1d" + "\x3b\x25\xfc\xd3\xce\xb4\x74\x44" + "\x5e\xb1\x5d\x4c\xe6\x85\x14\x3a" +
- "\x18\x6f\xd6\x1e\xec\x86\xde\xeb" + "\x43\xce\x1f\xd6\x6b\x90\x5d\x22" + "\x4d\xd7\xbe\xe8\xd6\x07\xab\x5c" + "\xb7\x5a\x85\x27\x7f\x61\xe4\x16" + "\xdd\xc3\xfb\xb2\xdd\xaa\x68\x65" + "\x5b\xdf\xed\x8a\x4f\x48\xb5\xed" + "\xad\x2f\xcf\x6d\xe8\x20\x8f\x87" + "\x99\x56\x5f\x61\x7c\x49\x16\x35" +
- "\xe2\xac\x7b\x70\xe8\xae\x58\x51" + "\x56\x1c\x6d\xf8\xc6\x14\x8d\x45" + "\xe2\xbe\xb9\xc1\x5c\xf1\xeb\x15" + "\xc0\x9c\x37\x0f\x66\xdf\x15\xa0" + "\x61\xd1\x2e\x20\xa3\xeb\x4c\xb2" + "\xf0\x3d\x4b\x20\x87\xf6\x58\x45" + "\x04\x4c\x26\xbe\xed\x8e\x0e\x89" + "\xb7\x8b\xde\x90\x10\x87\xb7\xb5" +
- "\x69\x1e\x18\xfa\xec\x3f\x0a\xef" + "\x98\x9a\xd6\x30\x81\x2f\xa0\x9e" + "\x5d\xb9\xea\x66\x8e\xcf\xe9\xb2" + "\x21\x00\x72\x24\xeb\x2b\x0f\x52" + "\x61\x43\xf8\x1d\x0a\x54\x1c\x62" + "\x5d\x6d\xfa\x71\x21\x77\x03\x12" + "\xff\xf6\xf5\x0f\x51\x7b\x3c\x6e" + "\xf3\xbe\xb2\xab\x9b\x06\x7a\x81" +
- "\x05\xcd\x81\x97\x11\x2f\x2b\x7e" + "\x2b\xa1\xaf\x7e\xe2\xc2\xa8\x77" + "\x5e\x38\x81\xa3\x3c\xd0\xfd\x78" + "\xad\x85\xab\x15\xbb\x54\x3b\xab" + "\xd4\x8a\x1c\xcf\xaa\x55\xbe\x48" + "\x81\xbc\x8a\x52\x58\x0c\xa6\x57" + "\xb3\x93\x68\x4a\xfe\xb5\xaf\xf8" + "\xcb\xcc\x66\x9a\xcf\x79\xd1\xbd" +
- "\xb1\x09\x6c\x65\x77\x7d\x4f\xf1" + "\x00\xdf\xa9\x29\x95\xac\x40\x4b" + "\x33\x38\x10\x14\x82\x48\xdc\xe9" + "\xc7\x45\x17\x42\x33\x32\x63\x4c" + "\x69\x03\xc2\x75\xc5\xcc\x2f\xd2" + "\x36\x0c\x37\x89\xa5\x42\xf2\x47" + "\xcf\xec\xda\x4e\xae\x16\x8c\x1e" + "\xc4\x78\xcf\x4f\xb0\xab\x8e\xad" +
- "\xcf\x98\xc5\x9e\xba\x05\xe6\x3d" + "\xae\x29\x30\x4d\xae\xd3\x33\x19" + "\x16\x05\x14\x9b\xbd\xfa\xf2\x6b" + "\x1c\xd0\xa7\x59\x55\xfc\x2d\x71" + "\x66\x63\x57\xd2\xe0\xaa\x3e\xff" + "\xf8\x1c\x70\x48\xf9\x07\xe4\x36" + "\xd4\x4b\x1f\xb4\x89\x1d\xe2\xed" + "\xa9\xef\x6e\x66\x5c\x2f\x29\xc5" +
- "\xa6\xcd\x94\xb2\xb6\x2f\x57\x83" + "\x34\x9f\x03\xb9\x75\xbf\xe9\x6c" + "\x21\xbb\x5c\x09\xf0\x12\xe0\x20" + "\xda\xf0\x63\xd0\x1b\xcc\xae\xa0" + "\xe5\x09\x29\xf0\x3a\x1c\xc2\x57" + "\xdc\x9c\xce\x48\xcf\x9e\xd5\xc7" + "\xf8\x36\xe3\x8a\x44\xb8\x32\x27" + "\xf4\x85\x4f\x3f\x23\x37\x6e\x05" +
- "\x52\xa8\x78\xef\x21\x5d\xb7\xf2" + "\x00\xa9\x31\xdd\x34\xcd\x38\xba" + "\x8a\xe1\xff\x58\x86\xa6\xb3\x72" + "\x45\x57\xd9\xbf\x0c\x19\x64\x74" + "\x81\x6e\xed\x77\x21\x53\x6e\x40" + "\xab\x5e\x53\xde\x5b\x97\xf0\x1a" + "\x82\x4c\xc5\x60\xc7\x22\xba\x66" + "\xe0\x2f\x0a\xb0\xce\xb1\xe3\x88" +
- "\x15\x7b\x33\xf0\x77\xf9\xb7\x55" + "\x3a\x97\x94\x0e\xa3\x72\xc8\x3b" + "\xa0\xee\x0d\x77\x83\xd9\x4a\x62" + "\xdb\xef\xa5\x13\x64\x33\xab\xca" + "\x47\x42\x0d\x7a\x02\xd0\x1d\x39" + "\xd5\xae\x12\xf3\x5d\x0d\x59\x39" + "\xac\x65\x13\x35\xc9\x02\x28\x53" + "\x2a\xe2\xa2\x78\x45\x82\x2e\xdd" +
- "\x87\xe6\xbe\x2e\xa5\xa6\xc6\x98" + "\x31\xc7\xc1\x56\xfa\x5b\xf6\xcd" + "\x10\xf2\xde\x72\x27\x13\xe8\x48" + "\xa5\xb5\x83\x80\x41\x19\xa1\x4e" + "\x25\xb5\xeb\xff\x4f\xea\xdc\x3f" + "\x72\xbf\x50\xfb\x19\xea\xaa\x55" + "\x0c\xb4\x85\x2a\x0a\xdc\xbe\x5f" + "\x9f\xf2\x44\xbf\x54\xd9\x6f\x0d" +
- "\xca\x00\xe8\x89\x31\xb5\x10\x8a" + "\xfd\x08\x52\x14\x17\x0c\xfe\x50" + "\x37\xba\x14\xb7\xd3\xc0\x43\x9e" + "\xcc\x9a\x18\x34\x0e\x20\x7d\x42" + "\xc0\xe2\x16\xe6\x4f\xe2\xde\x05" + "\xc1\x54\x18\xee\xc8\xf4\x25\x9c" + "\x73\x2a\x34\x8f\xa5\x22\x32\x4d" + "\x52\xc9\x27\xa0\x4f\x80\x07\x08" +
- "\x6f\x32\x8f\x2e\xf8\xb7\xbf\xba" + "\x19\xa5\x25\x56\x22\xac\x9c\xed" + "\xa9\xe0\xda\x0e\x1a\x9c\x10\xf1" + "\x59\x12\x52\x58\x98\x0a\xf8\x45" + "\x44\x1f\xb7\x5a\x07\x4b\xa4\x37" + "\x1b\x16\x21\x4a\xb6\x9e\x69\x21" + "\xee\x67\xfe\x56\xdf\xfd\x23\xb5" + "\x2e\xf7\xb9\x20\x21\x3a\x5c\x9f" +
- "\x73\x6e\xd2\x50\x33\x4a\x41\xba" + "\x88\x26\xf7\x75\x94\x44\x69\x45" + "\x82\x0f\x55\xb1\xe3\xa6\x82\xd4" + "\x7e\x6d\x16\x43\xe6\xf7\x7f\xde" + "\x2a\x22\x94\x9c\x68\xc6\x97\xad" + "\x40\x98\xfa\x72\x2d\x92\xa5\x90" + "\x5f\xaa\xe6\x32\xbd\x86\x18\x37" + "\x44\x0d\x5e\x7f\x67\x4f\xbd\xf1" +
- "\xc5\x19\xa3\xfb\x76\xb2\x8e\x05" + "\x4a\xa5\x7f\x7f\x12\x91\x3a\xd3" + "\xab\x2d\x2a\x93\xb4\xc1\x60\xf0" + "\xbf\xd9\xc7\x79\x4e\x22\x3a\xce" + "\x23\x28\xa9\x0b\x8c\x38\xb0\x6f" + "\x81\x78\x78\x69\x8a\x73\x31\x8d" + "\xb7\x00\xcd\x03\x02\xeb\x86\x2d" + "\x1b\x91\x69\x2b\x51\x44\x6e\x4e" +
- "\xf3\x56\x0d\x4f\x3a\x65\x22\xc2" + "\x05\xb8\x28\xca\x47\x40\x1e\x96" + "\x4b\x43\x73\x4a\xb0\xf8\x03\x2c" + "\x19\x2a\x71\xab\x87\x67\x96\x4c" + "\x42\xee\x4f\x86\x42\x6c\x19\xcc" + "\x5c\xce\x0e\x5b\xda\x93\xbe\xc1" + "\x59\xc1\x31\xc1\x22\x9f\x7d\xa8" + "\x55\x56\xe4\xdc\x93\xd5\xb6\x2b" +
- "\x42\x40\x89\x4c\xa9\x5a\x95\xec" + "\xed\x92\x2f\xf2\x9a\x17\x32\x9d" + "\x08\x65\x28\xfa\xf0\x0f\x02\x5e" + "\xda\x1c\x9b\x23\x3a\x86\x49\x46" + "\x8f\x45\xf1\x11\x92\x1b\x71\xa5" + "\x6d\x35\x9b\xde\xec\x93\xd4\x7d" + "\x94\x81\xad\x80\x82\x06\xf9\xe4" + "\x73\x97\x30\xfe\xc1\x7a\x86\x81" +
- "\x3c\x91\x78\xad\xfe\x96\xdd\xe9" + "\xb5\xb7\xee\x86\x14\xb5\x5e\x32" + "\x8e\xb0\x93\xa1\x61\x74\x74\x85" + "\x41\x35\xdc\x5a\xaa\x0d\x84\xf5" + "\xda\x9f\x36\xdb\x44\x0c\x1d\xc1" + "\x05\x92\x75\xad\xd9\x4a\xb1\x3a" + "\xa2\xaf\x8f\x03\x3d\x9a\x3f\x53" + "\x04\xf7\xe3\xfd\x53\x65\xdf\xfd" +
- "\xc6\xa4\x15\x29\x90\x69\xaf\xbe" + "\x11\x1c\xc3\x37\x4d\xc0\xdb\xd5" + "\xc8\xcb\x1f\x28\xba\x2a\xa7\xa7" + "\x21\xe6\x4a\x3f\x8d\xf2\x78\xa1" + "\x95\x08\x8d\x9b\x76\xdc\xdd\x23" + "\xd0\x06\xb2\x93\x84\xd7\xae\x88" + "\xe4\xa4\x32\x0e\x09\x1a\xe6\x6e" + "\xf4\x03\x2f\x26\x3b\x2e\x48\x1d" +
- "\xce\xb7\x09\xb8\xc9\x9e\xc4\x22" + "\x2c\x2c\xc7\xe2\x6b\x48\x41\x8a" + "\x36\xbf\xa0\xfe\x20\x94\x3b\x81" + "\x69\xac\x6d\xa6\xe9\x6e\xd3\xb3" + "\x87\xc9\x8c\x32\x8a\xc0\xdd\x6f" + "\x61\x64\x32\x3a\x2c\xcd\x3b\x0a" + "\xba\xdb\x10\xd8\x9d\xc4\x03\x71" + "\xc4\xa4\x78\x4b\x28\x1a\xd8\xf9" +
- "\x99\x0b\x18\xdd\xe8\xd8\xd1\xfe" + "\x49\x39\x3a\xd3\x3f\x33\x8c\xdd" + "\x99\x23\xb7\xb9\x2d\xdf\xdf\xcd" + "\x26\x55\x78\x8c\x3e\xe5\xa6\xad" + "\xb4\xe1\xbd\xc1\xed\xbf\xdf\xa0" + "\x4e\xd5\x77\x24\x81\x6b\x43\xc7" + "\xe8\x45\x32\xe7\x41\xd6\xec\x27" + "\x90\xcc\x97\xe0\xf1\x77\x8f\xb6" +
- "\x66\x5c\x62\x2b\x1e\x62\xa3\x1a" + "\x0f\xe5\xea\xa9\xae\x5d\xdc\x48" + "\x58\xa1\x52\x7d\xc2\xac\x06\x57" + "\x5c\xa2\x91\xa9\xa2\x51\x15\x0a" + "\xeb\xb4\x0d\x97\x6a\x04\x54\x46" + "\x4b\x7e\xff\x35\x4d\x4d\xbe\x2b" + "\xb9\x2f\xa6\x18\xe7\x6a\x85\xd9" + "\x8e\xd3\xa7\x10\x04\x16\xa0\xac" +
- "\x89\xdb\x76\x7a\xeb\xbb\xa0\x6b" + "\xf5\x2a\x35\x13\xbd\xc3\xc5\x1b" + "\x08\xbd\x44\xdd\x18\xfe\x3e\xb8" + "\x49\x24\xd8\x8d\xa7\xbe\xd6\x4b" + "\x0e\xd9\xf9\xda\x24\x31\x97\x4a" + "\x4c\xd8\x32\x33\x0c\x89\xdb\x6e" + "\x1b\x84\xbb\x9b\xe6\x39\x3e\xc2" + "\x6d\x3e\xae\x07\x45\x35\x8f\xc3" +
- "\x41\x59\xd5\xe4\xad\x65\xe8\x3d" + "\x87\x40\x38\x30\x5e\xfa\xda\xde" + "\x9b\x8b\xf1\x4e\xbb\x4a\x41\x6f" + "\x68\x52\xee\xfa\x42\xea\xe9\x9e" + "\x4a\x5a\xa5\x37\x16\xaa\x0f\x26" + "\xb9\x93\x5f\x01\x14\xa5\x19\xeb" + "\x98\x35\x9c\x9e\xd2\xeb\xd7\x51" + "\x8e\x17\x32\x19\x6d\xc5\x3f\x52" +
- "\xc8\xf1\xcf\x9a\x08\xdd\xc6\x9f" + "\x0d\xb6\x25\x9b\x2f\xac\xe8\x20" + "\x4c\x5c\xd9\xd4\xab\x30\x29\x22" + "\x7b\x50\xb2\x15\x4e\xb0\x77\x1e" + "\xeb\xda\x9c\x2d\x19\x88\x6b\x7a" + "\x3a\x79\x97\x31\x18\x4d\x5d\xf1" + "\x92\x4b\xed\x1c\x72\x2a\x70\x38" + "\x34\x93\xea\x37\xb0\x92\x8d\x94" +
- "\x1d\x9d\xf3\x16\xa3\x9f\xf8\xda" + "\x51\x6f\x28\x60\xa3\xec\xdf\x4f" + "\xd2\x3a\x05\x79\xe9\xc5\x37\x1d" + "\x40\xfa\x58\x19\x30\x0e\xa7\xde" + "\x7c\xe6\x1f\x25\xef\x96\x0a\xd0" + "\x74\xbe\x94\xeb\x2b\x1a\xc0\xd8" + "\x75\x4b\xfd\x0c\x38\x44\x2a\x0e" + "\x2c\xf2\xbd\x85\xb2\xc7\x1b\x87" +
- "\xf4\x22\x86\x3c\x28\x94\xff\x9f" + "\x40\x84\x46\x8c\x8f\x32\x6e\xb7" + "\x70\x0f\xae\x31\x97\xe1\xc5\x60" + "\xbc\x9c\x72\xec\x77\xd1\x6d\xf8" + "\xa2\x97\xf4\xf3\x30\x35\x81\x21" + "\xe7\xfe\x20\x59\xc1\x92\x31\x7f" + "\xe5\x1e\xc5\xe1\x31\x0c\x0f\x0e" + "\x10\xdd\xf4\x22\x73\xcd\x36\xf3" +
- "\x84\xe6\x8f\xb9\x0c\x07\x1d\x50" + "\x58\x14\x4a\x12\x9a\xbe\x0f\xd6" + "\x3f\x6b\xbc\x92\xc8\x61\x57\xa4" + "\xcb\x27\x6f\xfe\x58\x48\x38\xf5" + "\x3b\x76\x9e\xb5\xf7\x71\x02\x4b" + "\x5e\x8e\x5a\x5b\xa9\x06\x46\x3d" + "\x92\x82\xa4\x05\x9b\x5d\xda\x1e" + "\x46\xc4\xfe\xe6\xd0\x31\x77\xda" +
- "\x20\xff\x18\xeb\x77\x51\x7b\x27" + "\x62\x6d\xf0\x28\x98\x2e\x00\x48" + "\x8d\x6d\x50\x0e\xc3\xd6\xe8\xec" + "\x63\xf9\x9f\xcd\x58\x0a\xde\x5c" + "\x0e\xaa\x3b\x4e\xb7\xcd\x97\x3b" + "\xf9\x38\x12\x63\x0b\x0c\x56\x50" + "\x3d\x79\x79\xcf\x35\x1b\xc3\xe1" + "\x78\x21\x5e\x35\x14\x2f\xd1\x95" +
- "\x37\x88\x42\x2f\xc3\xb9\x21\x3d" + "\xbf\x02\x34\x0f\x1e\x6b\xc9\x73" + "\x9e\xf3\x4f\x42\xc9\xbf\xf7\x6c" + "\x96\xd6\xd0\xf6\x59\xa4\x2d\xca" + "\x4e\x15\xb8\x3b\x9d\xd6\xf1\x3c" + "\xb4\xed\x30\x54\x16\x9b\x42\xc2" + "\x75\xd3\xd0\x15\x8a\x47\xc6\xd3" + "\x6b\x37\xe4\x7d\x7f\x06\x33\x5e" +
- "\x62\x59\x20\xcb\x5d\x30\x8c\x37" + "\x9a\x59\x04\x3d\x9d\x9f\x40\xe1" + "\xb2\xc1\x57\x80\x27\xba\xec\x84" + "\xb1\x80\xbd\xa2\xe7\xac\x92\xcc" + "\x60\xc7\xc4\x4c\xdb\x11\x53\xcb" + "\xfe\x8e\x6d\x46\x63\xce\xf0\x18" + "\xee\x49\x72\x08\x1b\xeb\xa0\x0d" + "\xf3\xde\xfb\x56\xfb\xe3\x47\x7d" +
- "\x71\x58\xd4\x90\x93\x36\xe3\xa3" + "\x8d\x6d\x16\x06\x40\x40\x76\xe9" + "\x03\x04\xa9\x89\x82\x36\xc3\xb5" + "\x37\xd6\xf1\x72\x83\x79\xd1\x4b" + "\x3a\xc5\xd2\xd5\x9e\x67\x16\xa6" + "\x87\x3b\xcf\xfd\xd8\xbc\xc4\x5e" + "\x4e\x69\x6a\xb6\x13\x76\x6d\xae" + "\xe5\x27\xfc\xe3\x76\xfc\x60\x74" +
-
- "\x62\x49\x3c\xc6\xe1\x1f\x53\x80" + "\x25\xdb\x1f\x98\x89\x1e\x54\x50" + "\x6b\x2b\x4c\xfd\xa1\x91\x12\xdc" + "\xca\x4f\xdf\xa6\x17\x3a\x69\xc0" + "\x03\xf2\x17\x01\x4e\x60\xc4\xb2" + "\xd0\xb8\x99\x0a\x63\x19\x5f\x24" + "\x44\x2c\x21\xc6\xaa\x20\xdc\xae" + "\xa8\x52\x0f\x52\x56\x4e\xed\xb1" +
- "\xcd\x1a\x0a\x70\xb6\x0f\x56\xb5" + "\x81\x96\x99\xfd\x73\xfd\x23\xe8" + "\xba\xe1\xb4\x6c\x1f\x5d\x91\xda" + "\xa3\x00\xbe\x6e\x18\x01\x03\x0d" + "\xcd\xa8\xfc\x89\xc9\xb0\x4f\x74" + "\x0b\x0e\xda\xf9\xdb\x01\x0d\x97" + "\x6f\xd7\x31\x79\x64\xc5\xd8\x0a" + "\x6a\xb9\x59\xf6\xbf\x37\x57\xb1" +
- "\xda\x22\xdf\x6b\x9c\x7a\xf3\x18" + "\xdf\x82\xdc\x90\x2f\x43\xbc\xef" + "\x51\x36\x70\x5d\x8e\xef\x2c\xc5" + "\xa5\x81\x98\xd9\xa0\x7b\x88\x82" + "\x1d\xec\x20\xb9\xda\x9d\xec\x7c" + "\x3b\x8d\x3e\xec\xc3\xe8\xd7\xd0" + "\x47\x87\xa8\x4c\x95\xc3\x5b\x44" + "\x35\x35\xd5\x9f\xe0\xa2\xea\xed" +
- "\xd0\xc2\x53\xce\x4e\x38\x2b\xa1" + "\xda\x06\x46\x5e\x7d\x89\x9d\x77" + "\xb0\x12\xec\x73\xb0\x47\x3e\xa5" + "\xad\xf1\x56\x57\xba\xbb\x2d\x46" + "\xb6\x37\xfe\xca\xf2\x09\xfe\x69" + "\x17\x2e\xce\xec\xbf\x1e\x3d\x27" + "\xfd\x07\xf6\x3c\x38\xd5\xc1\x8a" + "\x25\x0c\xe1\x12\xff\xf7\x35\x80" +
- "\x05\x90\x6c\x29\x0f\xcc\xd4\xb7" + "\xdb\xeb\x0a\x7b\xfa\x94\x90\x4b" + "\xd4\xc8\x0e\xc0\xf1\x10\xbf\xe1" + "\x01\xc1\x67\xd6\xc4\xb1\x07\xd8" + "\x83\x33\x71\xbe\xdf\x2c\x41\xa9" + "\xa1\x2b\x14\x81\x3e\x06\x5e\x43" + "\xdc\x6b\x0a\xaf\xec\x15\x4c\x98" + "\xb9\xda\xa3\x92\x60\x24\x2c\x59" +
- "\x2a\xc2\x93\x20\x5a\x2d\x44\xca" + "\xed\x3a\x70\xd5\x31\xbd\xd0\xeb" + "\xb6\x87\x32\x65\xfd\x2a\x8f\x30" + "\xba\xc8\x1b\x0d\xac\x8b\xb8\x9b" + "\xb2\xe3\xc1\x75\x38\x85\xaf\xfb" + "\x7c\x44\x11\xca\x50\xc9\x2a\xbd" + "\x8d\x4c\x5c\xea\x6c\x81\x6d\x28" + "\x08\x32\xdc\x28\x00\xa8\x3a\xdc" +
- "\x9d\x3e\xe2\x16\x00\x69\x65\x93" + "\xe1\x41\xcc\xa7\x6b\x0c\x22\xcb" + "\x5c\x24\xd6\x69\xc3\x20\x6b\xb3" + "\x6a\x9a\x2e\xb6\x48\xc3\x63\x2d" + "\xb5\xbc\xc0\xcd\x19\x3e\x47\xa3" + "\x98\x1b\x60\x8f\x3f\x8b\xf1\x70" + "\xe4\x46\xe3\xcd\xc7\xa2\xd7\x8a" + "\x64\xaa\x3a\xbd\xc3\x6e\x9f\xae" +
- "\x20\x55\x6c\x7e\xc7\x34\x4d\x85" + "\x58\xea\xb9\xdc\xef\xf9\x7d\xc2" + "\x6d\x66\x86\xd6\x69\x23\x5f\x40" + "\x85\xaa\x17\x04\xbf\xfe\xd1\x29" + "\xfe\x0a\x47\x93\x9e\x81\x46\x98" + "\x9e\x7f\xa2\xe2\x69\x96\x6a\x3e" + "\x04\x65\x1e\xe3\xa2\x08\xd0\x24" + "\x0a\x68\xb7\x9c\xcf\xce\xa7\xdb" +
- "\xe1\xc7\x74\x32\x50\x23\x02\x03" + "\x26\x6c\x4b\x4c\x93\x8c\xee\x61" + "\xce\x89\x93\x19\xe3\x97\x43\x3c" + "\xce\x57\x87\x48\x00\x26\x08\xe0" + "\xfb\xda\xb4\x06\xdf\xa2\xc3\xaa" + "\x6a\x5b\xff\xdd\x00\x07\xaf\x45" + "\xa0\x9f\x1d\x8c\x24\x74\x59\x0a" + "\x8b\xc6\x1f\x39\x7d\x08\x40\x16" +
- "\x3d\xa5\x7f\xd0\x41\x3e\xa4\x26" + "\xc5\x5b\xe3\x74\x8a\xa7\x54\x31" + "\x8c\x2f\xda\xe0\x24\x89\x76\x7b" + "\x9a\x3f\x61\x23\x2b\x4a\x96\xba" + "\xc4\x16\x1d\xba\x35\x8d\x54\x5a" + "\x57\xd0\x54\xfb\xd1\xfe\x1b\x2e" + "\x05\x02\x64\xbc\x36\x21\x99\xff" + "\x29\xdf\x56\x81\x14\xb9\x9c\xf3" +
- "\xbd\x48\x55\x4e\xcf\x3f\x87\xf4" + "\xf0\x57\xce\x03\x3f\xda\x25\x87" + "\x58\x32\x95\xca\x95\x5c\x2f\xd8" + "\x7e\x74\xf0\x7c\x12\x7f\x64\xac" + "\xd5\x0b\x57\x2d\xb0\x38\x20\xff" + "\x3f\xe0\x3a\xa1\x67\xa7\xc2\xb0" + "\x16\x2d\x93\xe9\xcd\x27\xaa\xeb" + "\x01\xe9\x34\x12\xfc\xe3\x86\xa6" +
- "\xad\x44\xb4\x99\x46\xe6\x13\xc9" + "\xc5\x04\x05\xc4\x9d\xe9\xfc\xdd" + "\xdb\x53\x2e\xd4\x99\x2a\x48\x58" + "\x37\xf5\xaf\xd1\x25\x2c\xaf\x9a" + "\x67\xcf\x64\x26\x96\xf7\x90\xee" + "\x2b\x3e\x39\xf1\x99\x5c\xab\x74" + "\xb0\x5b\x22\xe6\xea\xfa\xd0\xfa" + "\x6c\xdd\x63\x2d\x8c\x64\x55\xc3" +
- "\xcc\x1e\x26\x63\x5e\x43\x80\x9f" + "\xc9\xd6\x37\x43\x2e\xa6\x02\x63" + "\xa0\x58\x49\xca\x49\x6a\x91\x91" + "\xd3\xd5\x49\x31\x99\x58\x49\x55" + "\x3c\xde\x91\x9f\x0b\x02\x8d\x37" + "\x70\x51\xd2\x4d\xa3\x39\xb8\x47" + "\x58\xf2\xb7\x38\x41\x85\x25\x28" + "\xec\x7d\x7e\x43\xf7\x14\x5b\xea" +
- "\x9d\xcf\x91\x1d\x27\x1d\xe3\xe4" + "\x0a\xb2\x77\xb3\xfd\xd4\x35\xcb" + "\x27\x13\x5e\x05\x45\x1e\xde\x74" + "\x75\x3e\x70\x28\x1b\xe3\x98\x32" + "\x39\x33\x01\xde\x37\x72\x08\x55" + "\xc6\x01\xd1\x23\x01\xf3\xcb\x32" + "\xdc\xb0\xaa\xe8\x22\xba\x0d\xc7" + "\xb9\x5b\x15\x3d\x3d\x62\x52\x4a" +
- "\x44\x8f\x01\xb0\x36\x87\xf0\x74" + "\xf5\xd0\x46\xb4\x17\x34\xa0\xf4" + "\xb2\xa6\x0c\xa4\x2f\xaa\xa4\x66" + "\xed\x60\xdb\xba\xf0\x79\x56\x21" + "\xef\x4e\x3e\x32\x5a\x19\x71\x38" + "\x16\x2b\x95\x20\xc3\x40\x09\x8f" + "\x7d\x5f\x9d\x87\x62\xac\x8d\xfe" + "\x75\xe8\xa6\xc1\x23\xb6\x9c\x64" +
- "\x43\x6e\x8d\x33\x41\xf5\xaf\xec" + "\xcc\xd5\x41\x45\x73\xdd\xf7\x56" + "\xca\x88\xbc\x96\xde\x26\xd4\xb5" + "\xc3\xa2\xd3\x9e\x6b\x4f\xd9\x48" + "\x9c\x27\xf8\x2e\xbb\xa3\x54\x63" + "\xf2\x67\x18\x0b\x5b\x46\x75\xd5" + "\x51\x51\x22\x95\xff\xb0\x99\xef" + "\xd8\x00\x45\xf9\x88\x9d\xe1\xf3" +
- "\x08\xc1\x3e\x13\x87\x90\x6a\xa2" + "\xc0\xbd\x12\x27\x9f\x69\xc5\x5d" + "\xa9\x24\x42\xd1\x4d\x3f\x90\x96" + "\x80\x7b\xe4\x29\x24\x99\xa5\x3d" + "\x5a\xba\xdb\xf9\x2f\x71\x17\xb7" + "\xc9\x91\x63\x75\x4b\x00\x52\x9e" + "\x9c\x21\x9d\xcc\x1d\xa1\x69\xe6" + "\x7d\xc0\xd6\xd1\x84\x6b\x6e\x3b" +
- "\x57\xcf\x5d\xc8\xac\x35\xf4\xdb" + "\x15\x54\x8f\xc8\x58\x56\x74\x61" + "\x07\x58\xc5\x17\x9a\x7e\x36\x26" + "\x6f\xc5\x90\xca\xa5\x77\xd0\x22" + "\x76\x4e\xe0\xa2\x58\x22\xf7\xfb" + "\x05\xe4\x06\x6e\x3e\x5d\x96\xba" + "\x54\xf9\xe6\xe3\x6f\xd0\x24\x57" + "\x74\x1a\x25\x81\x75\xd4\x47\x3e" +
- "\xdb\xea\x6f\x67\x6a\xc0\xee\x5f" + "\x22\xf3\x69\x9d\xc5\x9b\x44\xfc" + "\x95\x88\xda\x7c\x5e\x7b\x8d\x1d" + "\xa7\x14\x33\x1a\xc1\x4d\xd5\x5e" + "\xc0\x89\xe8\x6d\xae\xd2\x11\x1a" + "\xd9\x2b\xed\x4c\x72\x79\xa9\xb2" + "\xf6\x5e\x6a\x30\x89\x69\xcf\x6e" + "\x49\xa2\xc8\x8c\x7b\xd5\x11\x16" +
- "\xf7\x82\xfb\xe0\x51\x01\xba\xb8" + "\xc2\x8a\x66\xd5\x26\x07\x16\x0d" + "\xb0\x11\xd7\x14\x58\xa2\x2b\x62" + "\xf2\xe2\x3f\x7f\x57\xf5\xdd\x6a" + "\x35\x94\x9c\x6b\x1c\x1e\x83\x2b" + "\xbd\x26\x38\xb7\x0a\x06\x3a\xce" + "\x89\x0f\x24\x1c\xc1\x11\xfa\x93" + "\x3a\x30\x6e\x95\xd8\xc8\x9c\x4f" +
- "\x87\xbf\x7c\x00\xba\x42\x99\x2d" + "\x26\xc9\x3f\xdf\xe6\xbc\x62\x4e" + "\xff\x0a\x56\xe4\xb0\xe5\xee\xe7" + "\xb7\x09\xb0\x7c\xbb\x63\x19\xe5" + "\xdd\x37\x9b\xe2\xce\x18\x51\xaa" + "\x03\x39\x26\x47\x47\x4a\xd8\x5c" + "\xd8\x55\x00\x62\xa6\xca\x50\x30" + "\x3d\x1e\x4b\x6c\xa7\x76\xf5\x7e" +
- "\xc9\x82\x1f\x64\xf6\x31\x93\x4b" + "\x56\xc7\xfe\xdf\x54\x7c\x7c\xd9" + "\xab\x58\x91\x1a\x1f\x6d\xee\xf5" + "\x7f\xda\xc3\x85\xa3\x93\x44\x05" + "\xdf\x96\x7d\xeb\xf5\x05\x7a\xa5" + "\x39\x3a\x47\xe4\x47\xd4\xaf\xa3" + "\x55\x6d\xe1\x88\xc4\xd9\xa4\x42" + "\xae\x76\xf8\xf5\xf5\x44\xe1\x83" +
- "\xf1\x8f\x00\xe6\xdd\xa4\x26\x90" + "\x6c\xd9\x8c\x1c\xad\x95\xe9\x49" + "\x9b\x58\x3e\x50\x73\x2e\x72\x80" + "\x26\xbc\xc2\x84\xe1\xbc\xbc\x05" + "\x2c\x2c\x68\xd4\xbb\x9a\x5f\x25" + "\x56\xd4\x84\xf0\xc2\xcf\x2b\xc4" + "\x67\x07\x1c\x64\xb0\xe9\xea\xa0" + "\x2d\x9a\x4c\x86\x2d\x63\x45\x1b" +
- "\x20\xd6\x2d\xe3\x68\x32\xa8\x92" + "\xa2\x49\x78\x62\x9f\xc9\x3e\x91" + "\x82\x88\x37\x2c\xfa\xfd\xd8\xed" + "\xfe\x8c\x6f\xee\x3e\xf3\x96\xaf" + "\xa5\xa8\x3f\xdc\xe5\x37\x67\xc0" + "\x1d\x3a\xb0\xb0\x31\xb5\x6b\x23" + "\xb0\x37\xf0\x89\x29\x9f\xe5\x33" + "\x53\x2a\xa1\xd9\xa7\xb5\xf9\x13" +
- "\xe0\x24\xe0\x6a\x3b\x79\x25\xcf" + "\xb0\xc4\xb5\x84\xb4\x07\x66\x1b" + "\xc8\x24\x16\x3f\x90\xfa\x79\x95" + "\xe8\x57\xbd\x68\xbe\x65\xfb\x37" + "\x03\xc2\x39\xfc\x5e\xa5\x93\xd6" + "\xe9\x52\x72\xc8\xc4\x7a\x26\x4e" + "\x13\x94\x89\x9f\xb0\x8b\xd7\xb8" + "\x08\x85\x3b\x0b\x07\x14\xc0\xe4" +
- "\xa6\x9a\x02\x59\x95\xae\xd8\x50" + "\xed\xb2\x4d\x5a\x2c\x29\x4e\xd7" + "\x3d\x37\x8f\x84\x55\x33\x9c\x0b" + "\x38\xab\x45\xac\xb6\x8d\x01\xec" + "\xa8\x53\xcc\x69\x02\x69\x44\x1f" + "\x64\x98\x87\x1a\x8d\x62\x4b\x8c" + "\x5e\x47\x13\x4b\x28\x3d\x74\x1c" + "\xf6\x19\xde\x73\x38\x93\x4a\xbf" +
- "\x53\x35\x3f\xbc\xe5\x06\x29\x66" + "\x84\x96\x45\x31\x35\xd5\x38\xde" + "\x0d\x28\xf7\x34\xc6\xa8\x46\x8f" + "\x8e\x19\x24\x3d\x87\x1b\xf9\xaa" + "\x7e\x11\x9b\x5f\x11\xee\xd5\xec" + "\xda\x8d\xae\x50\xbe\xff\x00\xce" + "\xae\xa9\x10\x77\x4e\x3d\x3a\x26" + "\x4f\xa7\x6b\xf2\x21\xf7\xf3\x0f" +
- "\x69\xfa\xce\xf0\x47\x4f\x8a\x4a" + "\x66\x68\x54\xa4\xba\x4c\x8e\xdc" + "\xc1\x03\xf6\x23\x9b\xa6\x9b\x35" + "\xc5\x7a\x7b\x18\x01\xd6\xb4\xda" + "\xd9\xc8\xeb\xc1\x37\x43\xca\xa6" + "\x4b\x07\xb4\x52\x54\x58\xa6\x9f" + "\x33\xb7\x2f\x90\x81\x4f\x4b\x1a" + "\xaa\xde\x25\xa5\x7a\x5d\xbb\xd2" +
- "\x7a\x57\xb3\xe6\xc2\x7a\x28\xcc" + "\x3b\x00\x12\xf6\xa7\x8c\x52\xd7" + "\xb8\x00\x14\x2c\xf1\xb6\xfd\x8a" + "\x8d\xdd\xa2\x46\xd3\x2e\x3a\x10" + "\x39\x13\xe2\x2e\x4d\xc5\xf8\xc8" + "\x20\x2d\x5a\x35\x92\x1b\x01\x8f" + "\xac\xf2\x46\x13\x9f\xfc\xc6\x81" + "\x4b\xd2\xa6\x05\xf0\x42\x60\xdb" +
- "\x67\x95\x1f\xf8\xd5\x92\x2e\xeb" + "\x70\x84\x69\x4d\xea\x95\xcb\x54" + "\xeb\x81\x4c\xe0\x28\xcb\x2a\x5f" + "\x64\xec\xce\xf8\xc4\xbf\x1e\x1c" + "\x23\x74\xe0\x06\xac\x9f\x79\x8f" + "\x85\x0c\xfa\x37\x99\x5f\x22\x72" + "\x44\xdb\xf4\x34\x16\x86\xcd\xb0" + "\x91\x90\x2c\x75\x59\x61\xc3\x5e" +
- "\x96\xf9\xa4\x0d\x63\xe3\x90\xfc" + "\xe4\x6f\x6d\xaa\x9d\xa4\xec\x8c" + "\x9b\x61\xfc\xbd\xfd\xaf\x84\x10" + "\x04\x0b\x14\xc1\x72\xf6\x29\x20" + "\x5e\x3e\x6f\x13\x5f\xc2\x6e\x60" + "\x4a\x4c\x22\x02\x9b\x14\x24\x6d" + "\x4c\xcf\xdf\xcf\x42\xf1\xb0\xab" + "\xed\xa0\xb1\xfa\x19\x04\x0d\xe4" +
- "\x10\xb3\xef\x51\xce\xf6\x0d\x0d" + "\xbe\xf5\x8d\x95\xb4\x2e\x5b\xcb" + "\x59\x8e\x15\x36\x29\x9e\x45\xd6" + "\x36\xe3\x66\x14\xb9\xe2\xaa\x82" + "\x36\xa6\x1a\x41\x39\x8a\x65\xfb" + "\x33\xa9\xc0\xd4\xc5\xec\x52\x71" + "\xb7\x26\xf0\x49\x8a\x75\x0c\xf1" + "\x1f\x31\x09\xcb\x97\x7f\x83\xf4" +
-
- "\xd5\x32\x63\x62\x3a\x52\x4f\x99" + "\x44\xbb\x61\x55\x33\x88\xc3\x7b" + "\xa2\x5e\x84\x3d\xb0\xd4\x5e\x00" + "\x8a\xf0\xa1\xc2\xe1\x3e\x9d\xd3" + "\x0d\x6b\x67\xe7\xd3\xfd\x61\x65" + "\x17\x60\x70\xfb\xff\x35\x0e\x62" + "\xa8\xf9\x64\xf2\x4f\x42\xce\x36" + "\xf7\x81\x26\xda\x9f\x41\xc3\xc4" +
- "\x48\x16\xb8\x9b\x76\x31\xf8\x00" + "\xd0\x20\x31\x65\x85\xb4\x9e\xd6" + "\x62\xbc\xca\x4c\xf4\x75\x7d\xd1" + "\xb1\xfc\x49\xb7\x82\x7f\xa0\x34" + "\x54\x55\xfb\xbb\x87\xf7\x3a\x2c" + "\xf8\x83\xe2\x62\xd0\xd4\x6e\xb0" + "\xa0\x13\x92\xa1\x9f\x88\x22\x57" + "\xb4\xc7\xf3\xdc\x5e\x08\x2b\x16" +
- "\x7a\x0f\x30\xeb\xda\x0d\xd9\x36" + "\x01\xe8\xb5\xed\xfc\x7d\xcf\x9d" + "\x4c\x24\xd5\x74\x68\xb2\x5c\x64" + "\xa2\x3a\x8e\x34\x79\xee\x27\xa1" + "\xbb\x1d\x5f\x57\x53\xcc\x8a\x48" + "\x1e\x16\xe6\x80\x85\x7e\x03\x95" + "\xd0\x50\x26\x29\x83\x92\xe5\x57" + "\x16\x82\x93\x14\x99\x7d\xe6\xab" +
- "\x1f\xe7\x89\x71\x2f\x0d\x67\x32" + "\xe7\x91\xcf\x5e\x48\x87\x43\xc6" + "\x21\x7a\x75\xdb\x57\x8e\x75\x15" + "\xe5\x9c\x0a\x29\xf8\x09\x7d\x42" + "\x7a\x4a\x38\x38\x8f\x30\x6a\x84" + "\x99\x2b\x73\xb0\xb4\xac\xc3\xaa" + "\x19\x58\x84\x17\x09\x10\x94\x9e" + "\x03\x5e\xce\xa7\x11\xa1\xcb\x95" +
- "\x8e\x05\x78\x73\x37\xaa\x81\xeb" + "\x54\x11\x41\x04\xa1\x46\xc7\x41" + "\xc7\x8a\x82\xfb\xbc\x73\x0c\xa1" + "\x29\x2b\x97\x9d\x91\xbe\x39\x64" + "\xad\xfb\xa2\x43\xb0\xb4\xf3\x4b" + "\x40\xe8\xb5\x82\xdf\xda\xe6\x39" + "\x4c\xbd\x97\x63\x08\x64\x71\x4f" + "\xcb\xec\x1e\x7f\x68\xe5\x7d\x0f" +
- "\xc3\xc3\x7e\xf3\x73\x2a\x33\xdb" + "\xa0\xeb\x59\xdd\xbd\x59\x52\xc6" + "\x57\x32\x4d\xdb\x9c\x70\x91\x22" + "\x90\x93\x38\xbd\x25\x3b\x79\x9a" + "\xf0\x56\x37\xe4\x4b\xe3\x9f\xf3" + "\xc9\x56\xfb\x9a\xce\xbd\x76\x2f" + "\x27\x8b\x20\x61\x7a\x86\x37\x9f" + "\xc3\x72\x99\x08\x07\x43\x1d\xea" +
- "\x4f\x9f\x42\x8a\x87\x44\xa7\xd0" + "\x09\x66\x51\xdb\x2b\x71\x49\x06" + "\xdf\xb5\x69\xe7\x57\xba\x26\xb8" + "\xf2\xaa\xc7\x1f\xf2\x5d\x33\x82" + "\x95\xd9\x93\x5c\x67\xf0\x89\x23" + "\xe6\x7b\x67\x68\x7a\x36\xac\x59" + "\x1b\x95\xd9\x21\xff\x85\x79\xa7" + "\xce\x1c\x01\x85\xfb\x56\x89\x03" +
- "\x9b\x5e\xca\xaa\x1a\x85\xb7\x97" + "\x97\x3b\x71\x56\x21\xa5\x8a\x51" + "\xf6\x61\x0a\x15\xc7\xe8\x57\x33" + "\x69\x2b\x2c\xec\xe2\xe7\x42\x78" + "\x48\xa5\x68\x68\x65\xaf\xff\x8d" + "\x81\xfc\x68\xe0\x82\xbd\x63\xd9" + "\x33\x77\x91\x65\x8b\x5c\xda\x64" + "\x28\x73\x24\x7b\xff\x90\x70\x92" +
- "\x97\x0d\x6d\x2f\x94\xdb\xff\xd6" + "\x73\x93\x3b\x44\x41\xee\xc3\x05" + "\xb6\x6d\xd3\xff\xeb\x41\xe5\xb2" + "\x3e\xcc\x1d\xce\x96\x5a\x41\xb7" + "\xf6\xa2\x3a\x16\x2e\x68\x83\xe3" + "\x18\xf2\x3a\x2f\xd4\xbd\xfe\x46" + "\xdb\xba\xfd\xba\x7e\x50\xa0\x90" + "\x1a\xe2\x52\xce\x4d\xab\xa8\x4c" +
- "\x73\xfb\x7c\x1b\x2e\x83\xf0\xa3" + "\xc9\x54\xc3\x3e\x52\xfe\x8a\x7a" + "\xca\xad\x8e\x37\x7e\xc9\x91\xae" + "\xbb\x32\x3b\xac\x99\xc5\x49\x74" + "\x55\x46\x1c\x0b\x71\xc3\x19\xa6" + "\x7e\xa8\x9d\xf7\x6a\x4c\x2e\x69" + "\x6a\xd9\x38\xde\x86\x5d\x3f\xff" + "\xec\xc0\x08\x1c\x42\x0f\x32\xc5" +
- "\xec\x5d\xec\x8f\xbc\xf2\xa6\x92" + "\x6c\x78\xd6\x84\xff\x83\x13\xa7" + "\x84\xa0\xff\xdb\x06\x8c\x58\x87" + "\x15\xe7\x57\x68\xca\xf5\x85\x0d" + "\xd4\x74\xc7\xb6\xb3\x11\x73\xe8" + "\xa8\x21\x35\x4c\xc8\x57\x23\x67" + "\x0f\xfe\x29\x5b\x61\x74\xfe\xe5" + "\xcd\x58\x71\x5b\x10\x51\xbc\x02" +
- "\x8e\xfc\x05\xa1\x48\x1e\xa0\x37" + "\x8c\xa4\x9b\x28\x4a\x75\x9d\x76" + "\x80\x21\x1c\xd5\xe1\x6f\x8c\xc0" + "\x87\x13\xbd\xb7\x33\xdd\x32\xb0" + "\xa6\x0a\x0b\x02\xdb\x26\x38\x95" + "\x3c\xc7\x64\x06\x80\x7e\x13\x05" + "\x5d\xf9\x0c\x66\xc4\x02\x63\xc6" + "\x8a\xf2\xce\xb2\x11\x4e\x00\x99" +
- "\x36\x35\x97\x4f\x28\x5b\x4f\x82" + "\xea\x04\x5b\xd3\x9e\x29\x3e\xb4" + "\x89\x30\xa0\x4d\xf7\x88\x2c\xc7" + "\x2c\xe4\xa2\x45\x7a\xd5\x69\x82" + "\x8e\xb3\x07\x66\xfc\x63\x1e\x7c" + "\x0c\x0b\x39\x29\xaf\x2a\x9e\xe8" + "\x69\x28\xee\x1b\xda\x40\xc7\xc7" + "\x74\xb9\x3f\xaf\xfc\xf6\x56\x85" +
- "\xd1\xbe\xb6\xa4\x95\x39\x0a\x1a" + "\x54\x5c\x09\x97\x95\x57\xab\x2d" + "\xe9\x3c\xa7\x2a\xff\xa1\xc6\x06" + "\xa7\x38\xe4\x4d\x4b\xa5\xd0\xad" + "\xcd\x06\xa9\xfc\x1a\x6b\x0b\x16" + "\xdd\x10\xde\x29\x16\x60\xfc\x25" + "\xa3\x3d\x63\xd3\x99\x9c\x8e\x34" + "\x5a\x4d\x8a\x15\x46\xf7\xe3\x1f" +
- "\x1d\x5c\xe8\x8b\xc8\xed\x53\xc2" + "\xb6\x9c\xa0\x3c\x48\x0e\x3d\xdd" + "\x5a\x05\xe3\x9a\x87\xf6\x97\xb9" + "\xbf\x1d\x43\x07\xd0\x9a\x92\x0c" + "\x42\xdb\xd2\x84\x15\x62\xf1\xce" + "\xcd\x28\x88\x07\xef\xf3\x0d\xb5" + "\x66\x4b\xbd\x6d\x9d\xda\x89\x45" + "\x04\x2b\x9c\xd9\xe3\xd2\x4f\xbc" +
- "\x41\xc2\x98\xd2\xa7\xc9\x4b\x21" + "\xfd\x7c\x80\x56\xba\x97\xb6\xe3" + "\xdb\xea\x64\x45\x02\x78\x1c\xef" + "\xc5\x49\x81\xb4\xcf\xcd\xe8\xdd" + "\x04\x26\x4d\x5a\xa7\xf0\x6b\x94" + "\xaf\x38\x15\x6c\x7f\x4d\x15\x27" + "\xcc\x1f\x5b\xde\x30\x92\xcc\x95" + "\x82\x4f\x86\x66\xe9\x19\x85\xd8" +
- "\x77\xbc\x86\x62\xea\xa9\x01\x99" + "\xb0\x4d\x79\x69\x58\xfe\x9d\x24" + "\x21\xcd\xa6\xbb\xbd\x0b\x37\xc4" + "\x6b\x5e\xfc\x21\x31\x81\x8f\x71" + "\x61\x8b\xc7\x22\xbd\xed\xdf\x9c" + "\x71\x3d\xd4\xd9\xec\x3e\x31\x4b" + "\x22\x1b\xbb\x19\x1f\x03\x44\x41" + "\x58\x31\xa3\x07\xab\x73\x49\x97" +
- "\x26\x65\x36\x06\xf4\xde\xaa\x67" + "\x96\x5d\x53\xae\x19\x30\xd5\xd7" + "\xc6\xeb\xa2\xe3\xa7\xdb\xfa\x72" + "\x16\x9d\x26\x75\xa5\x13\x23\xa3" + "\x2e\x92\x0d\xb5\x69\x1a\xfa\x97" + "\x45\x2b\x20\xca\xcf\x28\x6e\x4c" + "\x91\x0b\x10\x68\x00\x11\xbd\xb7" + "\x5d\x6a\xc9\x73\x8d\x41\x2e\xe0" +
- "\x46\x55\x80\x8e\xdc\x6e\x9e\xfa" + "\x40\x98\x63\x82\x78\xe6\xe0\xc0" + "\x3d\x64\xbe\xb7\xa4\x58\x08\x43" + "\x1e\x5f\xcf\x18\x14\x24\x42\x1d" + "\xaf\x49\xef\x9f\x62\x0c\x99\x05" + "\x32\x1d\xc3\x5e\xcd\xe0\x46\x48" + "\xd4\x85\xbf\xba\xa8\x47\xdb\x46" + "\x7f\x9f\x75\xaa\xf1\xc9\x66\x5f" +
- "\xa1\x6c\xea\x96\xf7\xe4\x13\x10" + "\x71\x28\x79\x1f\x2a\xdc\x7c\x56" + "\x45\x8d\x65\x5c\x70\x28\xb7\xad" + "\x98\x0e\x60\xce\x4a\xff\xc1\xf7" + "\x39\xad\x6c\x4b\x57\x86\xba\xa1" + "\x28\xb4\x20\xba\x34\xd6\x58\x3d" + "\xfb\xfd\xe6\xa2\xde\x1c\x01\xc0" + "\x0d\x96\x18\x7b\x7a\x36\x32\xa8" +
- "\x07\x15\x52\x50\x8f\x2c\x39\xb7" + "\x9d\x2e\xef\xe5\x4b\x91\xb3\xac" + "\x85\x6f\x44\xea\x78\xb1\x70\x9a" + "\xee\xc3\xd8\x98\xa6\x43\x4c\xbd" + "\x77\x01\x4c\x84\xe5\xbb\x73\xa9" + "\xea\xb3\x2a\x06\x4d\x27\x9b\x29" + "\xaf\xda\x6a\x85\x7c\x0e\xba\x26" + "\xb8\xb2\x5c\x76\x94\x91\x9b\x13" +
- "\x87\xd3\x9f\xbd\x9b\xe7\x21\x7b" + "\x71\x0c\x1c\x24\x9a\x76\x8f\xb4" + "\x93\x5a\x72\x8b\x36\x68\xe3\x83" + "\xe1\x96\x5b\x1f\x55\x4f\x9d\xef" + "\xa0\x10\x99\x2a\xa4\x39\x71\xc6" + "\x76\x5e\x09\x4e\xa2\xc8\xe1\x71" + "\xf2\xb8\x19\x27\x36\x7f\x2f\x21" + "\x17\x12\xfa\x00\x3f\xeb\x75\x9f" +
- "\xb6\x6d\x3e\x34\x6e\x8e\x11\x4e" + "\x3f\x99\xb6\x25\x59\x55\xbd\x98" + "\x85\xfa\x2e\xb3\x14\xd5\x0d\xb4" + "\xa1\xe3\x24\x7a\x80\x55\x30\x7e" + "\xc3\x57\x58\x77\x50\x95\xcc\x7d" + "\xb0\xc1\x9b\x2c\x12\x11\x63\x05" + "\xe9\xdc\xa5\x02\xd5\x85\xae\x6e" + "\x72\x41\xeb\x34\xaa\xc9\x3f\xe5" +
- "\xf7\x38\x49\x0e\x9f\x8c\x61\x47" + "\x9e\x71\x83\xdc\x69\x7d\xd4\x58" + "\xcc\x64\x1a\xf4\x23\x1a\x4c\xd7" + "\x66\x9f\x82\xb5\x68\xe0\x28\x5d" + "\xf6\x66\x04\x21\x29\x75\xd3\xd8" + "\xf8\x4e\xa6\xc6\x2f\x15\xf1\x2a" + "\x7a\x6a\xce\x19\x5c\x48\xd4\x55" + "\xd7\xe2\x48\xf6\xf5\xd2\x0b\x6d" +
- "\x21\xb5\x9d\xf8\xb1\x6a\x2d\xf0" + "\xc6\xed\x0c\x65\xfc\x1a\xf4\x46" + "\x71\xdf\x8a\x1c\x96\x73\xbc\xb1" + "\xb9\xb1\xbd\x7e\xcb\x7f\x14\xd2" + "\x63\x03\x08\xc1\xf7\x0e\xaf\xca" + "\xc5\x09\x5c\xd9\xf3\x1a\x0b\xf9" + "\x83\x48\xf4\xf6\xd4\xbf\xaf\x7a" + "\x6d\x9b\x8d\x8a\x87\xe0\x64\x9b" +
- "\xe5\x6a\x35\xbd\xe8\x9c\xfc\xee" + "\xf4\x5a\xd2\x2e\xc0\xa6\x98\x3d" + "\x84\xd8\x19\x63\x64\xf5\x73\x31" + "\x16\x4f\x6c\xca\x64\xed\x2d\x2b" + "\xd0\xfc\x6d\xce\xe5\x19\x7b\xe2" + "\xca\x87\xd8\xa0\x5f\xbc\x69\xa3" + "\x10\x37\x46\x07\x6e\x60\xc2\x59" + "\x4e\xe7\xc6\xf3\x2a\x11\xc1\x15" +
- "\xa0\x13\x7a\x7e\x00\x30\xba\x4a" + "\xf5\xaa\xbb\x89\x47\xbb\x83\xf4" + "\x3f\x27\xfd\x9f\xf6\x50\x0d\x7c" + "\x92\xd6\xa4\xf4\x91\xc1\x63\x7e" + "\xe6\xd6\xf2\x42\x40\x34\xda\x8b" + "\xc6\x72\x8b\x93\xc2\xcd\xcf\xd7" + "\xe9\x54\x6e\x6f\xd2\xfb\x8a\xd2" + "\xe5\x3f\x8b\xc2\xb6\x23\x04\xd4" +
- "\x8d\x44\x16\xf4\x2a\x03\xcc\x1e" + "\x71\xd9\x76\xec\x10\x8c\x7e\x4a" + "\xae\x6e\x0b\xb9\x05\x98\x4f\x85" + "\x94\x05\xed\x4b\x32\x15\x0b\xfd" + "\xa3\x5c\x8b\xd9\x48\x18\xf7\x89" + "\xef\xb3\x39\xf0\xfc\xe5\x1f\xd0" + "\x2e\xda\x7b\x62\x2e\x33\x81\x44" + "\x41\x3e\x07\xa5\xd7\xec\x7c\xe6" +
- "\xcd\xec\x9c\x8a\x46\x16\x69\x2e" + "\xa1\x6d\x3a\x05\xcc\xeb\x92\xcc" + "\x64\x6b\x3a\x78\xb8\x76\x00\xa8" + "\xa2\x2f\x99\xa5\xa0\xe8\xd0\x42" + "\x30\xec\x56\x7c\x53\x1c\xc7\xd9" + "\x69\xc7\x6b\x6b\x96\x6a\x8b\x38" + "\xc7\x9f\xbf\xd3\xab\x33\xc2\xa0" + "\x69\x53\xc4\x2f\xd0\x5b\xf5\xd0" +
- "\xf9\xee\x92\x32\x02\x33\x2c\xa7" + "\x16\x11\x8c\x9f\x36\x40\x5a\x0f" + "\x91\xa7\x96\x3e\xf0\x6e\x9e\x42" + "\x39\x39\x84\xf3\x81\x61\xeb\x60" + "\xd3\x18\x25\x90\x83\xf0\x49\xaf" + "\x0b\x39\xe8\xb9\x13\xc0\x65\xfe" + "\xa4\x34\x4d\xec\xb3\x7c\xb9\x7a" + "\x3d\x85\x4f\x8b\x08\x7a\x42\x72" +
- "\x1f\xad\xfe\x2e\x68\xfc\x83\x38" + "\x68\x8d\x4d\xfc\xa1\x24\x72\xdd" + "\xdd\xaf\x1d\x9f\x4c\x84\x4e\x5c" + "\x7d\x9b\x11\x15\x8e\xd1\x40\x7f" + "\xeb\x68\xc2\xb7\x4c\xd1\xc6\x79" + "\xe1\x89\xae\xc2\x55\xc8\xb4\x65" + "\xa2\xd9\xb0\x7c\x99\xbb\x08\x35" + "\x5b\x4a\xc6\x2e\x5b\x63\x2c\xbc" +
- "\x2c\x28\xb1\x7c\x1a\xdd\x28\xb8" + "\x3a\x97\x46\xbe\x26\x76\x8d\xa0" + "\xb2\xd6\x08\xe7\x40\x8d\xaf\x6b" + "\xf3\xb3\xae\x4d\xa1\x1f\x57\x72" + "\x98\xfd\x2d\xf2\x2f\x73\xb1\x85" + "\x8d\x10\x87\x00\xa7\x01\xab\x87" + "\x7a\x20\x88\x59\xa8\xfe\xaa\xaa" + "\x55\x07\xf0\x69\xf8\x32\xc8\xcc" +
-
- "\x1a\x9d\x8d\xca\x85\x11\x8f\x48" + "\xd2\xde\x87\xd9\x7d\xc7\xf2\xad" + "\x24\x61\xc4\x60\xf0\x39\x30\x5f" + "\xf4\x95\xe0\x71\x75\x0b\xd7\xe5" + "\x0f\xe7\x60\x62\x50\x86\xd5\x82" + "\x05\xd1\x50\xf7\xa7\x5e\xd7\x39" + "\x64\xc3\xba\x75\xb1\xd0\xf3\x8c" + "\x29\x13\xd0\x21\x4d\x56\xa7\xf3" +
- "\xfc\x3e\xcd\x3f\x3e\xa4\x4a\xb2" + "\x9a\x8e\x08\xb8\x34\xc0\x26\xdd" + "\xea\x46\x3d\xbd\xc9\x4d\xef\xa5" + "\x6f\x6a\x4c\x8a\x58\x9d\xf9\xa2" + "\x6c\xa4\x1d\x2f\x55\xd3\xab\xdd" + "\xd1\xcd\xfa\x1a\xce\xf8\xc3\x72" + "\x78\x05\xd4\x92\xee\x4e\x0c\xd9" + "\x94\x3b\x62\xca\x1f\xb4\x8b\xd2" +
- "\xe1\x7c\x41\xe7\xd2\x92\x27\x24" + "\xf5\xe7\x0e\x97\x71\xbc\x42\xff" + "\x1e\xa4\x67\x5c\x6d\xdc\xf4\x1f" + "\x58\x2a\x88\x20\x7b\x9b\x70\x77" + "\x2c\x7f\x21\xbe\x1d\x73\x54\x35" + "\x77\x21\xb7\x5b\xcd\xa8\xf2\x2a" + "\x59\xd0\x1d\x59\x69\xe7\xee\x58" + "\x77\x64\xba\x4b\xc9\x30\x29\xbb" +
- "\xc0\xf2\x76\xf1\xda\xdd\x6a\x1e" + "\x58\x26\x57\xe2\x04\x46\xca\x01" + "\xfb\x2f\x34\x85\xed\x4d\x40\x0a" + "\xd6\x38\x18\x44\x96\x0f\xf6\x8c" + "\x4a\x1c\x07\xc9\x1c\x69\xbc\x9b" + "\x03\x28\x44\x34\x44\x87\x58\xfd" + "\x81\x0d\x9c\x80\x85\x1c\x10\x97" + "\x7f\x6f\x45\x8c\x4c\x75\xfb\xa7" +
- "\x3f\x01\x71\xaf\xd5\xa1\xf7\x6a" + "\x46\xc9\xed\x0b\xe5\x16\x82\xe6" + "\xa0\x70\x73\xd2\x0b\xa3\xcb\xf4" + "\xcc\x21\x04\x87\xbf\xaf\x81\x79" + "\xe1\xf0\x49\x94\x67\x6a\x49\x02" + "\xae\xed\x47\x0a\xbe\xc4\xcf\x86" + "\x22\xca\xfe\xb1\x36\xc9\x73\x30" + "\xfb\xf8\xf8\x03\x12\x46\x69\xf5" +
- "\xf8\x48\xde\x5b\x71\xd6\xad\xbc" + "\x7d\xbc\x89\x21\x73\x38\x70\xc9" + "\x8a\xee\x09\xc7\x9e\x29\x45\x5d" + "\xf8\xaf\x5a\x84\xe2\x7e\x28\xd1" + "\x1f\xbf\x1d\xdb\x74\x88\x1f\x7d" + "\xd6\x88\x0c\x99\x8b\x58\x46\xea" + "\x13\x83\x36\x84\x9a\x64\xba\x60" + "\xae\x43\xd5\x60\xce\xcb\xfd\xd5" +
- "\x2d\x27\x90\x98\x95\xe9\x3d\xcf" + "\x10\x3a\x71\x3e\x2a\x43\xf3\x75" + "\xb8\x27\x82\xe2\x9f\x47\x13\x5e" + "\xc8\xcd\xfa\xfe\xa9\x1e\x56\xb8" + "\xfd\xaa\x32\x83\xa0\x97\xa2\xa6" + "\x62\x9b\x80\x73\xb5\x8b\x0d\x9b" + "\x6f\x03\x63\x0c\xfd\x1c\xfa\xd2" + "\xa8\xbd\x64\xbd\x55\xeb\x16\x7a" +
- "\x27\x3e\xc1\x2a\x8a\x8e\xe4\xf7" + "\xf5\xa9\xb1\x4e\xdf\xf6\x94\x44" + "\x62\x0a\x1f\x98\xeb\x84\xbf\xed" + "\xf0\x38\x64\x53\x32\xdc\xba\x49" + "\x71\x75\x4f\x00\x41\xa5\xbe\x50" + "\xee\x94\x1c\xdf\x10\x7d\xc6\xba" + "\x31\xbc\x27\xb7\xa1\x73\x3d\x25" + "\x28\x6e\x68\x30\xf2\x1c\xd0\xb3" +
- "\x3b\x5a\x6a\x30\x39\xc0\x0b\xa4" + "\x1b\x3a\x78\x96\xfd\x41\x0a\x4e" + "\xd4\xcd\x53\x02\x9a\xd3\xe8\xa1" + "\x38\x86\x38\xc7\x26\xbe\x80\x64" + "\x82\xf3\x85\x22\x1d\x5e\x36\xee" + "\x36\x5c\x0b\xec\x8f\x8d\x8d\x18" + "\x82\x4d\x0f\x1f\x48\x1a\xef\x34" + "\x9a\xd2\x87\xa4\xe1\x43\x8f\x1a" +
- "\xa5\xdd\x02\x39\x7c\x14\xa8\xa5" + "\xb4\x73\x69\xfe\x06\xf7\xd2\x35" + "\x7e\x45\x57\xc2\xcf\xef\xc2\x5a" + "\x1b\x61\x00\x87\xd4\x48\x3f\x93" + "\xb2\xbe\x12\x49\x88\xaf\x65\xc3" + "\x94\xdf\x2e\x16\xe6\x4d\x5a\x7f" + "\x4b\xf3\x32\x0c\x7c\xba\x46\xc6" + "\x74\x10\x09\xb2\xf3\x6a\x2c\x63" +
- "\x5f\x6f\xb2\x9b\x33\xa3\xf6\x10" + "\xb6\x85\x4d\x04\x8e\xdb\x85\x1e" + "\x54\x7e\x19\x94\x08\x7a\x69\xc3" + "\xa8\x4e\xcb\xa7\xc0\x8c\xe1\x65" + "\x6e\xfe\x71\xa4\x50\x4f\x8c\xa3" + "\x9c\x43\x13\x2f\x7a\x74\x31\xf0" + "\x8b\x31\x07\xc0\xba\xa6\xc4\x53" + "\x3d\xcb\xec\x1d\xe5\x3e\xda\xa8" +
- "\x3f\x8f\xa4\x5c\xdf\x1a\xc0\xbf" + "\x84\x9b\x2a\xe2\x06\x2f\x35\x64" + "\x4a\x9e\x09\xc1\xa1\x4d\xe5\xce" + "\xc0\x89\x1b\xfa\xe8\x54\xda\xbb" + "\xfb\x55\x6e\x6f\xf5\x3d\x6a\x16" + "\x88\x6f\x17\x20\x24\x4a\xa4\x1c" + "\xff\xb5\xb7\xdf\x88\xfd\x6a\x93" + "\xa0\xd4\x11\x86\x37\x24\x4c\xe3" +
- "\x92\x48\x55\x3e\x6d\x41\x24\x5f" + "\x45\x2a\x0e\x43\x3d\xb5\x13\x84" + "\xa0\xa2\x32\x90\xee\x6a\xc5\x99" + "\xb1\x67\xc3\xee\xf6\x2b\x43\x09" + "\xc1\xec\xf0\xda\xc6\x50\x28\x55" + "\x48\x20\xc9\x5b\x55\xce\xeb\x49" + "\x07\x13\x81\x54\xa6\x6b\xb6\xdf" + "\x97\x85\x29\x6f\x97\xf7\x84\x1b" +
- "\xa4\xd5\xf8\x70\xeb\xd9\xb5\xd5" + "\x28\xb2\xbb\xd7\xe7\xdd\x5a\x37" + "\x32\x0b\x1c\x0c\x86\x8b\xe8\x31" + "\xaa\xdb\x3e\x17\xc4\x68\xf5\xd1" + "\x02\xdf\x59\x54\x83\xfc\x92\x15" + "\x7e\x9a\xcd\x0f\xfb\xc0\xea\x2b" + "\x0a\x3b\x47\x1b\xb8\xfd\xa6\xb0" + "\x48\xfc\xe8\x0f\x6f\x4c\x22\xe3" +
- "\x89\xe1\x77\x57\x45\xc8\xa5\xa1" + "\x29\x28\x6f\x45\xe0\xbe\x10\xcc" + "\xd5\x2b\x76\xda\x56\x5c\xd9\x8a" + "\xa8\x1d\xd9\xe9\x14\x22\x2e\x15" + "\x74\x3c\xb2\x7c\x72\x0e\x5b\x97" + "\xdf\x66\x0c\xa9\x70\x76\x5d\xfd" + "\x53\xfc\x5f\x22\xad\xb8\xb5\xb5" + "\xae\xd2\xde\xfa\x73\xff\x6d\xab" +
- "\xcf\x49\x35\x6d\x0f\xe5\x33\xd4" + "\x5e\x66\xcd\xfa\x6f\x69\x33\x6f" + "\xb4\xfc\x11\xce\xac\xfd\x5b\x69" + "\x60\x98\x7c\xaf\x52\xe2\x0e\x81" + "\x2c\xbb\x59\x71\xe1\x0f\x45\x65" + "\x7b\x35\x8b\x75\xbe\xbe\xdf\xf7" + "\x72\xea\x9f\xd6\x74\x7e\x05\x2b" + "\x45\x17\x73\x92\x7a\x71\x85\xd4" +
- "\xef\xd7\x76\xb3\x84\x76\x6d\x8d" + "\x81\xda\xd5\x48\xac\x02\xbf\x3d" + "\x9c\x13\x89\x1b\x5a\x38\xa5\xfa" + "\xce\xa7\x20\x68\x85\xcb\x4d\x50" + "\x26\x9d\x1a\xe6\x45\x21\x98\xc0" + "\xaf\x25\x5d\xac\x32\x6c\x5c\xf3" + "\xc2\xb3\x27\x4e\x67\xa2\x3b\xaa" + "\xc5\x7a\x6c\x9f\xa0\xa3\x69\x2e" +
- "\xcf\x86\x0b\xf3\x1d\x5c\x6a\x90" + "\x87\xef\x07\x4d\xfc\x66\x6f\xb1" + "\x61\x22\x01\xd4\xda\xc2\x75\xa9" + "\x1e\x36\xbc\x0f\xe6\x48\x97\xe6" + "\xc7\x00\x99\x2d\x36\x35\xa0\xa2" + "\x0f\xaa\xf6\x7c\xe1\x3c\x2a\x1f" + "\x87\x38\xe3\xa1\x3a\x44\xd5\x80" + "\xdf\xb4\x47\x5b\x8b\x24\xda\x6a" +
- "\x1a\x72\x3c\xdd\x08\xbb\x9f\x1f" + "\x9c\x22\xb2\x46\x7e\xf9\xa1\x93" + "\xfb\x7e\xba\x31\x46\xad\xe5\x4e" + "\xa3\x10\xae\xf3\xa5\x5c\xaa\x6b" + "\x04\x02\x6c\x74\x3e\xfc\x81\x7d" + "\x0b\x06\x9a\x2b\xf0\x90\xcc\x9e" + "\xa7\x8c\x68\x7b\x2f\x16\x58\xdb" + "\xdf\xc1\x54\xf5\x99\x2a\x77\xf4" +
- "\xf4\x4b\xdc\x67\x7c\x4e\xb2\xed" + "\x7b\x82\x4a\xaa\x43\xc7\xe4\xcb" + "\x2b\xf8\xcf\xfa\xf5\x72\x94\x22" + "\x9b\x4a\x2c\xcf\x82\xbb\xef\x2c" + "\xf1\x7f\x36\x59\xb8\x06\x6e\x38" + "\x75\xaf\xcd\xa3\x78\x59\x24\x32" + "\x98\xb1\x07\x98\x6d\xd3\xbd\x2d" + "\xe9\x11\x85\xb7\xe7\x95\x74\x43" +
- "\x27\xa7\xdd\x77\x65\x6e\x16\x34" + "\xcf\xaa\xaa\x3e\xc1\xa3\xa4\xb6" + "\x40\x62\x2c\x9d\xc2\x49\xcd\x9c" + "\x63\xa1\x2b\xa4\x3d\x7f\xe1\xc2" + "\x33\x21\x6d\x7c\x5c\xeb\xf9\x91" + "\x06\x76\xa9\xe6\x2a\xbd\xce\x85" + "\xfb\x0d\xb0\x65\xbd\x35\x6e\x80" + "\x82\x2a\x39\xb9\x06\x79\x9f\x9e" +
- "\x3b\x2b\x0d\x4d\x8a\x29\x9f\x23" + "\xf1\x07\xb2\xdb\xcf\x60\x97\x6c" + "\xeb\x2e\xf9\xd4\x3f\x20\xbf\xc8" + "\x9b\x4e\xa7\x7e\xe4\x2a\x0b\x29" + "\x3d\x7d\x3a\x16\x37\x93\xa6\x1f" + "\x14\xa4\xef\x87\xe8\x5e\x29\xd0" + "\x3f\x27\xf8\xf9\x37\x40\x84\x54" + "\x58\xab\x41\xe3\x62\xa8\x46\x30" +
- "\x0b\xfc\xc6\x38\x53\xe9\x9f\xfb" + "\xc8\x79\x95\xac\xe8\xe2\x94\xe4" + "\x8b\xca\xd7\x69\x6f\xef\x24\xc4" + "\xec\x57\xb8\x4f\x15\x52\x0e\x63" + "\x48\xdf\xe2\x42\x2b\x11\x13\xf0" + "\xbf\x04\x52\x62\x08\xc9\xad\xef" + "\xce\xb0\x63\x11\x6c\xb1\x8b\x7d" + "\x89\x68\x14\xb7\xe3\x47\x51\xdf" +
- "\xad\x75\xbf\xa2\x05\x8b\x37\x5b" + "\x92\x1e\xda\x25\x66\x4b\x37\xfe" + "\x12\x67\x76\xff\x00\x81\x4c\xfb" + "\x60\x46\xc8\xcb\x80\x63\x60\xbc" + "\xe4\xad\x10\x6c\xc9\x6e\x26\x27" + "\xa7\xec\xb6\x7a\xb5\xc2\x6a\xb4" + "\x00\xe8\x28\xbb\xd7\x73\xc6\xfd" + "\xfe\xe3\xc0\x23\x20\x5f\x64\xb5" +
- "\x28\x2b\x56\x30\x5f\x0e\x43\x76" + "\x06\xd8\xea\x36\x10\xca\x41\x67" + "\x93\x12\x7f\x93\x31\x50\x6e\xbf" + "\xf0\x9a\x29\x22\x6e\x09\xc3\x32" + "\x22\xdd\x45\x21\x61\xb1\xa3\xd6" + "\x33\x86\x5e\xd7\x57\x90\x49\x6c" + "\xbd\xc2\xf1\x39\x51\x76\x99\xa5" + "\xf5\xab\x1f\x6b\x6d\x0c\x90\x3b" +
- "\x63\x7c\x43\xe7\x16\x68\x29\xe8" + "\x11\x4c\x16\x76\xd2\xc0\xa7\x38" + "\x0e\x84\x29\x9c\xf9\x95\x10\x1f" + "\x3f\x09\xb9\x57\xb3\xb9\x12\x19" + "\x17\xc8\x39\xf8\x04\xd5\x09\xfe" + "\xdd\x4b\xdd\xbd\x3b\xfb\x64\x1f" + "\x34\x45\x04\xdb\x5b\xed\x42\xef" + "\xc8\x21\xe8\xb4\x95\xdd\x60\x15" +
- "\x4e\x52\xb9\x70\x50\xaf\x39\xde" + "\x68\xc8\xd1\xad\xe9\x95\x69\x79" + "\xc9\x4c\x9a\x32\x28\xb8\x90\x97" + "\x64\xae\x62\x5b\xb7\xa2\xeb\x1e" + "\x2f\xc1\xe3\xd7\xf6\xd3\x7b\x61" + "\x21\x64\x33\xdf\x1c\x71\x7e\xdb" + "\xcf\x07\x89\xd7\x37\x09\xfc\x7d" + "\xd5\x8b\x1a\x84\x99\x7a\x93\x88" +
- "\xba\x41\x0a\x5d\x4d\xc2\xa5\xb9" + "\x1e\x86\x6c\xb6\x02\x84\x29\x58" + "\xfc\xcd\x71\x4c\xf8\x6e\xdb\x99" + "\xd9\x4c\x36\xe6\xaa\xaa\xe2\x69" + "\xd9\xc7\x8b\x64\x18\x94\xf0\x4b" + "\x6f\x3c\x71\xeb\xe9\xc2\xb3\x5a" + "\xc2\x52\x6e\x0c\x58\xd5\x75\x6a" + "\x12\x00\x60\xe5\x24\x8a\x2b\x46" +
- "\x8e\x85\x82\xfe\x08\x42\x54\xca" + "\x90\x1a\xc2\x3e\x4a\xaf\xa3\x51" + "\xd4\x14\x76\xc2\x63\x9e\xc1\x63" + "\x39\xe7\x05\xe0\x95\x8c\x08\x32" + "\x00\x8d\x4a\x94\xf9\x25\x50\x7c" + "\x48\x2a\x94\x9a\x7d\xe3\x98\x8f" + "\xe7\x45\x5c\x53\x51\x73\x35\x53" + "\x80\x1f\x89\x44\x1c\xf1\x41\xfe" +
- "\x90\xc3\xa2\x5d\x9c\xe1\xf9\x20" + "\x8a\x6d\xbd\xda\x2f\xe6\x69\x1f" + "\x65\xbb\xaa\x27\x2e\xb6\x9e\x1b" + "\xb5\xbb\xbb\x3d\x37\x83\x09\xbb" + "\xda\x32\x36\x82\xc9\x88\x3b\x7d" + "\xde\xe7\x59\xa7\xf3\x74\x89\x6c" + "\x6c\x87\x52\x3d\x08\x78\x65\x49" + "\xd8\xcd\x45\xe0\xbc\x73\x64\xb5" +
- "\x47\xe7\x53\x00\x0e\x7e\xe5\x5d" + "\x53\x8a\x1c\x56\x92\x65\xd3\x04" + "\xad\x2e\x7f\xca\x78\xd3\x06\x6a" + "\xdb\x59\xf8\x14\x20\x56\x61\xb3" + "\xf8\xf8\x19\x14\x17\x91\xb1\x4e" + "\x32\x99\x3b\x60\x25\x45\xbf\xd0" + "\x98\x58\xa1\x9d\xcd\x45\x3e\xfc" + "\x14\x8d\x32\x79\x71\x9f\xe8\x5e" +
- "\x0c\x86\x36\xee\xe8\x42\x6c\x89" + "\x2d\xc2\x13\x41\xfd\x4d\xf0\xda" + "\x13\x42\x10\x44\xb7\xb7\xdb\x1a" + "\xea\x94\xd3\x1f\xa1\x5f\xfd\xe5" + "\x51\x05\x4e\x1a\x94\x5d\x23\x68" + "\x51\x01\xd1\x18\xbe\xcf\x72\x67" + "\x23\x45\x98\x09\xe3\x71\x60\x27" + "\x98\xba\x56\x5a\xde\x79\xe8\xe4" +
-
- "\x91\x94\x5b\x28\xb0\xaf\xaf\xaa" + "\x5e\x70\x4c\x1e\x88\xbe\xa0\x01" + "\xab\xca\xd9\x2a\x5d\x4f\x1d\xff" + "\x3f\x23\x7a\xc3\x4a\x9a\x34\x6e" + "\x16\x6a\x1c\x4a\x46\x12\x1c\xcf" + "\x60\x32\x38\x29\x66\x6b\x9e\xd9" + "\x71\x54\x6d\x5f\x66\x43\x3d\xea" + "\x9b\xc8\x8c\xff\x04\x4d\x97\x36" +
- "\x57\x90\x92\x8f\x14\x9e\xf2\x27" + "\xdf\x53\xc8\xc0\x06\xae\x64\x7a" + "\xce\xc5\xe9\x58\x83\xd1\x6c\x25" + "\xa5\x92\xd0\xde\x82\xce\x9c\x9d" + "\xc7\xb7\x93\x6e\x79\x59\x6e\xcc" + "\x27\x9e\xbb\x31\x92\x70\xe4\xe1" + "\xa0\x29\x9e\xaa\x83\x30\x0b\xb7" + "\x44\xe6\x85\x37\x75\x1a\x18\xbf" +
- "\x1e\x3f\x0a\x5c\xc8\xe8\xd6\x8e" + "\x7f\xc3\x87\x7c\x92\x24\xad\xbc" + "\x8d\xb7\xe3\x9e\xbb\x62\xfb\xfd" + "\x46\xba\xce\xcb\x77\xe4\xa8\xeb" + "\x4b\xde\xae\xee\xb0\x8c\xd3\x37" + "\xb6\xde\x76\x79\xe8\x98\xc4\x0b" + "\xfb\x47\x61\x6b\x04\x4c\x94\xb2" + "\x09\x96\x1f\xf7\x35\x3f\x12\x8b" +
- "\xd0\xb9\x02\x14\x3f\xa1\xb3\xd3" + "\x63\xc8\x7b\x2c\xc3\x41\x34\x57" + "\x6e\x3e\x8c\x57\xc4\x1e\x30\x4b" + "\x7e\xf5\xda\x0a\xc4\xc9\x6f\xc2" + "\xa3\xce\x93\x74\xfd\x1b\xe7\x96" + "\x56\x14\xf8\x1a\x3f\x4b\x5d\xd0" + "\x8f\x60\x8c\x6a\x8a\x2a\xca\xda" + "\x76\xb2\x25\x07\xf6\x07\xef\x53" +
- "\x78\x59\x43\xc7\xf0\x23\xe0\xba" + "\x19\x0e\xe3\x20\x88\xc8\x52\xb1" + "\xaf\x6f\xfa\xe3\x45\x16\x24\x9c" + "\x60\x3e\x82\x84\xc1\x95\x5d\x73" + "\x17\x53\x95\x03\x73\x75\x19\x03" + "\x95\x49\x3b\xf0\xa9\x02\x4b\x0b" + "\x00\x46\x27\x70\x59\xf5\x6b\x07" + "\x08\x75\xf5\xaa\x53\xcc\xc5\x32" +
- "\xd2\xc5\xc7\xd5\xfd\xdb\x18\x03" + "\x2d\x34\x2b\x07\xa7\x8d\x8f\xb3" + "\x8a\xe3\x8d\x7b\xdc\xbd\x69\x35" + "\x42\x48\xc9\xa1\x87\x58\x5b\xf2" + "\x60\xad\x46\x29\x84\xb2\xd5\xb2" + "\x7e\x70\xd1\xe9\xad\x29\x4f\x85" + "\x09\x45\x6a\x2c\xdc\x59\x51\xaa" + "\x37\x98\x18\x57\xc0\x94\x9f\x89" +
- "\xe7\x89\xce\x49\xe0\x36\xf5\x27" + "\xb5\x0c\x89\xcc\x39\x85\x90\x18" + "\xa1\x2a\x3c\xd8\xab\x09\x89\x30" + "\xd3\x3b\xb7\x1a\x2b\x14\xd3\xec" + "\x84\xab\xf5\xb3\x59\xbf\x85\x6a" + "\xc6\xa4\xbe\xf2\x68\x0a\x32\x3c" + "\x1f\x54\xa4\x6d\x38\xc5\x8d\xad" + "\x86\x11\xc4\xb7\xb0\x4e\xf3\xea" +
- "\xd2\x49\xac\x46\xd6\xc9\xb5\xa6" + "\xa9\x7a\x13\x83\x0b\x7c\xc7\x42" + "\x38\x5a\x22\x68\xfc\x00\xd0\x24" + "\x07\xe9\xe1\x2f\xc8\xcf\x63\x0f" + "\x95\x1f\x44\xc6\x1b\xb0\xd1\x22" + "\x8f\x44\x8e\xec\x19\xf7\x38\x7d" + "\xba\xb1\x7f\x78\x5f\xfa\x33\x9b" + "\xdf\x58\x01\x19\xa1\xfd\xdc\x94" +
- "\xca\x1a\x0a\x49\x26\x93\xc7\x63" + "\x02\x6b\x52\x41\x9c\xdd\x64\xcb" + "\x58\x92\x97\xa2\x91\x25\x77\xbb" + "\x46\x78\xd9\x48\x70\x29\x58\x3f" + "\xa7\x3b\x21\x7c\xd1\x70\x6b\xd6" + "\xd4\xce\xa0\xe8\xb5\xeb\x8f\xc2" + "\xc1\x38\x03\xc1\x31\x18\x91\x6b" + "\xf3\x26\x01\xbf\x89\xe3\x54\x0d" +
- "\x9b\x68\x83\xb4\xfe\x2e\x24\x40" + "\x62\xc2\x3a\x51\xf6\xd3\x75\x25" + "\x72\xdb\xa6\x0c\xc8\x37\x00\xf3" + "\xe2\x4b\x86\x98\x82\xce\xfc\xc9" + "\x2d\x36\x49\x01\xff\x12\xa1\x84" + "\x71\xe9\x4a\x1c\x82\x75\xe5\x95" + "\x6c\xf8\x5c\x94\xa8\xb1\xa4\x1f" + "\x2f\x4a\x02\x0b\x34\xa7\x25\x45" +
- "\x5f\xd8\x05\xc9\xc2\xd1\xea\xca" + "\x57\xae\x33\x07\x90\xf7\xd7\xe9" + "\x94\xdd\x7c\xf0\x5c\xa6\xc9\x24" + "\x31\x59\xb5\xa4\x9c\x35\x89\x73" + "\xf7\x45\x7e\x36\xb7\x09\x87\xf5" + "\xdc\x7a\x7e\xcb\x67\x30\x20\x1f" + "\x18\x28\xb7\xc7\xff\x4b\x44\x82" + "\x33\x80\xac\xba\x35\x3b\x30\x07" +
- "\xfd\x09\x6f\x52\x45\xed\x7f\x05" + "\x0a\x24\x28\x81\x0c\xf1\xa4\xe8" + "\x8d\xfd\x2b\xff\xc4\xef\x32\x93" + "\x31\xaa\x35\xbd\xa0\x77\x4e\x21" + "\x0e\xa4\xfa\x14\x73\x6d\x89\x32" + "\x86\xf1\xe5\x01\xec\x67\x78\x76" + "\x3e\x81\xa1\x17\xf1\xf8\xad\xc9" + "\x95\x17\x74\x54\x78\xda\x6c\xcb" +
- "\x85\xe1\xda\x01\x01\xd0\xb4\xb7" + "\xbc\x94\x7a\x9b\x0b\x4e\x43\x45" + "\x0b\xcb\xd8\xfb\xaf\x39\x43\xf5" + "\x9e\xf4\x8e\xe9\x9e\x56\xc4\xdc" + "\x99\x12\xa5\x09\x8a\x31\x89\x77" + "\xd8\x25\xb0\xb2\x06\xd2\xb4\x81" + "\x92\x57\xe8\xfa\x18\xa4\x4a\xf6" + "\xf7\xba\xd7\xac\x8f\x25\x50\x3e" +
- "\x68\xd8\x9f\xa1\xd3\xeb\x72\xc0" + "\x3b\xdd\x8d\xdb\x1c\x48\x2e\x61" + "\x52\xd8\x64\x1a\x54\xd7\xe1\xb4" + "\xab\xc4\xc6\xc4\xac\x95\xef\x00" + "\x46\x6c\x0a\xaa\xed\xd2\x36\x15" + "\x90\x47\x77\x43\x86\x40\x29\x61" + "\x10\xda\x3f\x34\xe8\x25\xaf\x54" + "\xf2\xd6\x25\xfd\x8d\xd9\xf9\x9f" +
- "\xa4\xbe\x79\x55\xdf\x96\xd2\x4c" + "\xf1\xda\xee\x5c\xc8\x5a\xe3\x10" + "\xb1\xc5\xbc\xe3\xfd\xc5\xc4\x04" + "\xf9\x2c\x41\x89\x8a\xee\xf9\x95" + "\x0f\xeb\xb6\x82\xee\x59\x94\x2c" + "\xdd\xaa\xc2\x95\x65\x57\x84\x2e" + "\xfe\xfc\x27\xd3\xae\x84\x4a\x77" + "\x76\xd4\x68\x03\x22\x37\xc9\xd8" +
- "\xef\x36\x6c\x29\x10\xde\x1c\x21" + "\x77\xda\xc4\x82\x72\x96\xe8\x7e" + "\xda\x36\x78\xa5\x70\xd2\x17\xb6" + "\x0b\x56\xb7\x9c\x31\x9c\xcd\xf0" + "\x90\xfe\x55\xe4\xf7\xcb\xfd\x01" + "\xf3\x34\x73\x7e\xbb\x3c\xb5\x3f" + "\xec\xe4\x7d\x4e\xa4\x2e\x1e\x78" + "\xd0\x4f\x38\x0b\xad\xb3\xda\x8a" +
- "\xb8\xb3\xba\xbb\xf2\x90\xe6\x60" + "\x6b\x81\x04\x8b\xae\xf8\x51\x48" + "\xd2\xe4\x92\x9c\xab\x46\x20\xc7" + "\x6b\x13\xf3\x7c\xa1\x74\x8c\x51" + "\x4c\x7d\x87\xf9\x0a\xb5\x4e\xff" + "\xbb\xca\x19\xa9\x90\x8d\x57\x14" + "\xb6\xb2\x5e\xac\xc4\xf8\x18\x82" + "\xe4\x16\x20\x54\x47\xc5\xcc\xa3" +
- "\x85\x7b\xea\x1e\x6c\xa7\x3e\xe3" + "\x5e\xf8\xd4\x92\x61\xb4\x52\x23" + "\xbb\x15\xe1\xaf\x34\xd3\x01\xf1" + "\xa3\x75\x91\x88\x94\x12\xbc\xfa" + "\x25\xf9\x33\x52\xc0\xcd\x6b\x7f" + "\x55\xec\x7f\xe7\xdb\x02\xa8\xe0" + "\x59\xb6\x69\x80\x75\x7b\xb4\xbd" + "\x74\xbd\x8f\xf9\xde\x12\x5e\x1c" +
- "\xbb\xdd\xd8\x89\x58\x46\x6c\x65" + "\xe8\x8e\xf3\x70\x6e\xb2\x30\x88" + "\xb0\x12\x12\xde\x5c\xfd\x20\x43" + "\xb2\xed\xa2\xe4\xcf\x30\x4f\xc3" + "\xb8\x64\xab\x56\xa3\x31\xb1\xab" + "\x26\x5d\x9c\xd9\xcc\xf0\x77\x7f" + "\x94\x1d\x98\xbf\x37\x6a\x85\x66" + "\x6e\xd7\x8b\x73\x09\x6d\xe7\x19" +
- "\xc0\x18\xb6\x53\x7d\xd4\x6b\x1c" + "\x23\x79\x22\x6a\x6c\xf4\x24\xc4" + "\x64\xd9\x92\xdd\xde\xff\x03\x73" + "\xf2\xab\xb5\x71\x78\x28\x71\xe9" + "\x1d\x56\x15\xf8\x32\xa6\x48\x8f" + "\xd1\x55\xc0\xd3\xf5\x8f\xf4\x85" + "\x4f\x68\x25\x75\x27\x14\x2a\x22" + "\xc3\x0c\x36\x67\xa0\x41\xd8\xd0" +
- "\x99\x4a\xc3\xf2\xb1\x44\x0c\x86" + "\xac\x55\x58\xbf\xa4\xac\x00\x3b" + "\xbe\x37\xaf\xfa\xa0\xaa\xf6\xab" + "\x08\xec\x53\x2a\x82\x36\xf4\x65" + "\xe1\x12\x1b\xa1\x01\x58\x9a\x1d" + "\x75\xd4\x0e\xe2\x2c\xab\xa7\x78" + "\xd5\xe0\x41\x9a\x7e\x06\xe1\x0d" + "\xea\x23\x50\x30\x5f\x3f\x47\x30" +
- "\xc6\x68\x7f\xf9\x52\xb3\xb7\xdb" + "\x58\xcf\x02\x0b\x50\x3b\x77\x0c" + "\xd9\x96\x1f\x3c\x21\x48\x2e\xea" + "\x15\x18\xe0\xee\xb0\x57\xb3\xff" + "\x39\x80\xf2\xe0\xcd\x24\xc9\xb9" + "\xe4\xfb\xa3\x46\x5a\xc9\x36\x0b" + "\x6c\xdb\x46\x5e\xa4\xae\xaa\x1f" + "\xff\xaa\x28\x19\xc3\x75\xe5\xca" +
- "\x6c\xb9\xcb\x70\x2a\x96\x3c\x26" + "\xa9\x24\xd1\xbc\x2a\x36\x34\xe0" + "\x8d\xe5\x2a\x3c\x28\xdb\x20\xf1" + "\x07\xd5\xf6\xfe\x49\x8d\xa3\xb9" + "\xfd\x40\xf1\x1f\x82\x2a\xfd\xb1" + "\xe0\xe7\xae\x20\x30\x2f\x16\xbd" + "\x49\x19\x25\xcb\xd4\xa5\x17\x4e" + "\x3d\x1c\x7e\x4f\x83\xcb\xeb\x2a" +
- "\xf9\xf0\x9f\x59\x2b\x8a\x77\x01" + "\x6b\xfc\x04\x81\xd7\x23\xa9\x68" + "\xf3\x4f\x69\xda\xdf\x44\xfa\x5b" + "\x12\x7f\x66\xf7\xdb\x99\x71\x4f" + "\x79\x2a\x6f\xe4\xf6\x8f\x6d\xc0" + "\x1d\x13\xf8\xe9\xad\xde\xb5\x08" + "\x7c\xce\xb4\xab\x59\x9a\x51\x02" + "\x3e\xec\x2a\xb4\xbc\x10\xf7\xc4" +
- "\x19\x27\xc2\xc0\xca\xd3\xbf\xd8" + "\x1e\x15\xca\xc9\xe4\x09\x02\xc6" + "\x9c\xa6\xa1\xd9\xb5\x4a\x74\x7a" + "\x8f\x7f\x93\x14\x8b\x04\xe5\x6d" + "\x04\xac\x15\xe1\xd8\x38\x19\x17" + "\xd2\x16\x6b\x1c\x40\x09\xf7\x7d" + "\xe7\x94\x8e\x7f\x63\xb6\xae\xa6" + "\x94\xf0\x2c\x2a\x8e\x38\x30\xc1" +
- "\x7c\x33\x6f\x78\x9d\x71\xb6\xcd" + "\x7d\x39\x04\xe7\xd2\x1c\xc0\xd9" + "\xef\x2f\x5c\x55\x20\x3f\x4a\x0f" + "\x23\xf2\x0a\x7c\x09\x25\x45\x00" + "\x76\x8e\xdb\x84\x47\x80\xa5\x54" + "\x06\xaa\xc8\x93\xaa\xf1\xac\x3b" + "\x22\x94\x91\xf7\x7c\x95\xca\x11" + "\x40\xaa\xcd\x78\x53\x10\x64\x50" +
- "\x75\xa7\x67\x6c\x31\xb7\x6e\x9f" + "\xb1\xd0\xc5\xef\x1a\x47\x10\xcb" + "\xb2\x06\xb8\xe1\x0c\x75\x33\xb4" + "\x7e\xae\xb1\x57\x4d\x71\xc5\x19" + "\x3f\xfd\x03\xed\x7b\x8b\xdc\xc0" + "\x4e\x19\xbc\x31\x4f\x34\x03\xdd" + "\xb5\x20\x63\x8c\xa7\x52\x6c\xa6" + "\x93\xfd\xb6\xd0\xe3\x2c\xc8\x8b" +
- "\x0d\x04\x0b\x0e\x0f\xa9\x28\xb2" + "\x7f\x89\xff\x45\x82\x2d\xf0\xba" + "\x22\x61\xfa\x00\xe6\x79\xac\x2a" + "\x57\xf5\x36\x8e\x17\x88\x82\x24" + "\x56\xc3\x3e\x11\x31\x1d\x52\xb9" + "\xf8\xf1\xef\x15\x1e\x86\x48\x9e" + "\x15\x17\xd4\xe0\x12\xd4\xa1\x2a" + "\xb8\x31\xf1\x53\x03\x62\xf8\x71" +
- "\x1e\xc5\x73\x6f\x3d\x48\x2a\x6d" + "\xdd\xc2\x0d\xea\x12\x24\xcb\xa4" + "\xff\x17\xb9\x1e\x41\x3c\x66\x50" + "\x9e\x29\xde\xea\xcf\x74\x3a\x3d" + "\x02\x92\x7a\x4a\x0f\x99\xb3\x29" + "\x3d\x5c\xb1\xa7\x59\xcf\xbc\xa9" + "\x08\x92\xdf\xa5\xdc\xcc\xa3\x66" + "\x29\xf9\xf2\x43\x14\x7c\x02\x48" +
- "\xb4\xaf\x8c\x09\xbb\xa3\x44\xe0" + "\xaf\x8c\xd4\x60\x10\x23\xed\x27" + "\x4d\xb8\x31\x3a\x75\x56\x2b\x54" + "\xd7\xbe\xdd\xfc\x50\xdd\xf3\xcb" + "\x30\xd8\xb1\x41\x16\x1f\x03\x25" + "\x27\x1e\x0c\xcb\x1d\x85\xec\xa7" + "\xdb\x75\xae\xb5\xe0\x8f\x1c\xac" + "\x20\x21\xc5\x08\x57\x75\x4c\xb2" +
- "\x9e\x03\x07\xd6\x71\x0e\xbb\x1f" + "\x46\x45\x3a\xcd\x15\xe2\x70\x2b" + "\x91\x40\x32\x53\x1d\xf0\xd2\x32" + "\x9b\xb1\x0a\x18\x08\xff\x96\xb7" + "\xaa\xc4\x57\x3c\x86\x7a\xd8\x32" + "\x27\x9a\xc4\xb7\xaf\x9c\xed\x2a" + "\x98\x0d\x63\x31\xac\x5e\xb3\x9f" + "\xa3\x20\x3e\x5c\xdf\x8c\x8e\x33" +
- "\x40\x09\xd8\x4e\x8b\x36\x14\x30" + "\xdd\xce\x6f\x7a\x56\xd0\xe6\x67" + "\x9f\x57\x97\xca\x49\x8c\x20\x7c" + "\xf6\x97\x35\xa2\x81\x7a\x3d\xfe" + "\xe2\x6a\x09\x7e\x02\x32\x20\x5e" + "\x66\x93\xb3\x24\xe7\xe1\xf3\xb1" + "\xfc\xdf\xdc\x2f\xf3\x26\xda\x26" + "\x83\xbe\x97\x60\x1d\x2f\x42\x79" +
-
- "\x81\xb3\xb3\x9d\xfb\x2c\x3a\x26" + "\x4b\x0a\xdf\xd4\xee\x2d\x3a\x9c" + "\x1f\xe6\x04\x7d\xe9\x06\x8d\x72" + "\x25\x93\x44\x42\xbc\xdf\x1a\x8b" + "\x1b\x3a\x05\x7e\x39\xd9\xc1\x6e" + "\x07\xf7\xda\x66\xc7\xe5\x2b\xee" + "\xab\xc7\x0a\x81\x14\x1e\xba\x80" + "\x74\xf1\x30\xf5\x78\xe7\x2a\xdd" +
- "\x8b\x9d\x5b\x20\x7a\xd9\x35\x04" + "\xd4\x56\x67\x05\x64\xf0\xb8\x6e" + "\x0e\x21\xf8\xb6\x8b\x8a\xe8\xd5" + "\xea\xd9\x9f\xec\x2d\xf1\x0e\x07" + "\x6a\x87\xcc\x3b\x05\x95\x84\x4d" + "\xe3\x4c\x40\xa7\x38\x53\xa7\x12" + "\x5e\xdb\xa1\xb8\xe1\x49\x2b\xd2" + "\xad\xa5\xbf\x14\x51\x20\x1f\xec" +
- "\x36\x8f\x82\xb6\x79\xeb\xba\xad" + "\x9e\x5b\xbd\x01\x58\x02\x7a\x9d" + "\x0c\x4b\x84\x1e\x0d\x1e\xa0\xed" + "\xc9\xdf\x7e\x88\x75\x51\x62\x4b" + "\x21\xb6\x69\x96\xdd\x9f\x10\x14" + "\x98\x7b\xf8\xf6\x56\xca\xa2\x88" + "\xbc\xf6\x0d\x17\x88\xb7\x2e\xfe" + "\xf9\x73\xa4\xff\xf4\x06\xea\x0c" +
- "\x33\x3d\xe8\xc4\xb5\x81\xed\x43" + "\x8b\x48\xfd\x5e\x79\x58\xf3\xd9" + "\x0f\x4d\xeb\x9d\x0f\x62\x4a\x16" + "\x94\x73\x6a\xac\xdb\x7b\x92\xc6" + "\x03\x0f\x9e\x9f\xf7\x8d\xc2\x45" + "\xa9\xe1\xd7\xfc\x1e\x66\x68\x28" + "\xf1\x48\xa3\xff\xd0\xe8\xf4\x7c" + "\xe0\x38\x85\x39\x84\xc2\xd4\x6b" +
- "\x19\x86\x9a\x28\x91\xa0\x18\x26" + "\x73\xb1\x71\x66\x60\x6e\x79\xef" + "\x32\xc6\x90\x90\xe5\x46\x4e\x66" + "\xfb\xf8\x66\x1e\xd4\x62\x80\xa3" + "\x4e\x27\x73\x05\x20\x4a\x74\x6c" + "\x94\x13\x27\xa9\xe4\x67\x7b\xd0" + "\x20\x0e\xdc\x6b\xb2\x23\x12\x39" + "\xa7\x05\x0a\xeb\xf1\x93\x2d\xbe" +
- "\x41\xd1\x36\x3f\x53\x2e\x3e\xf2" + "\x42\xa4\xfc\x4d\xd4\xb3\x4b\xe8" + "\x3a\x02\x7c\x6b\x8d\xa4\x04\xb8" + "\x3b\x1c\x43\x76\xfa\xa8\x16\x1e" + "\xe0\x72\xd4\xdd\xad\x52\x54\x1b" + "\x27\xe1\x1e\x0d\xe7\x5e\x40\x7d" + "\x99\x75\xa2\xff\x1d\x6f\xfc\x50" + "\x35\x1b\x39\xbf\x3c\xc5\x1a\x35" +
- "\x6b\x89\x44\x44\xb8\x14\xfa\x7e" + "\xfb\x27\x40\xf9\x2f\x4d\x97\x64" + "\x7d\x48\x84\xde\xe8\xd0\xdc\xef" + "\x9b\x98\x48\x2b\x60\xb2\x45\x8c" + "\x87\x34\x46\xd8\xc2\xbb\xfc\xa8" + "\x6c\x47\xbc\x3f\xf7\xb3\xb2\xd1" + "\xc0\x43\xf4\xc8\xb7\x05\xd0\x21" + "\x9c\x13\xc0\x40\x67\x2e\x8f\x51" +
- "\xc1\x5f\xd7\x06\x8c\x6e\x03\x56" + "\x9f\xa8\x49\x32\xb7\x7b\xcf\x2d" + "\xdd\xe7\x45\xe2\x3d\x1d\xdd\x81" + "\xa7\xe2\xd6\xeb\x4b\xdc\x78\xf5" + "\xa0\xe7\x2c\xdf\x03\x89\x02\x4c" + "\xac\xaf\x39\x9c\x88\x62\xe3\xae" + "\xab\x04\x64\x14\x31\x7c\x84\xdc" + "\x18\x78\xe9\xa4\xd8\xc0\x04\x63" +
- "\x91\x67\x1f\xa9\xa2\xdc\x51\xae" + "\xfc\x9e\xaa\x9b\x90\x41\xbe\x2a" + "\xc1\x7a\x9c\x55\xf4\xe2\xd2\xd9" + "\x3a\x77\x9f\xfc\x51\x4b\x2f\xe8" + "\x1c\xe8\x73\x40\x27\x30\x71\xa7" + "\xfc\x96\xb5\xfb\xac\x6f\x27\xc0" + "\x0c\xf7\x84\xa6\xc9\x9f\x81\x1d" + "\xe0\xb1\xf7\xc9\xdd\x7f\xb4\x29" +
- "\x40\x19\x9b\x45\x03\xe1\x8d\x35" + "\x93\x3e\x01\x5b\x59\x1c\x88\xec" + "\xd3\x2a\x53\x49\x93\x4c\x57\x51" + "\xde\x46\x7b\xb3\x45\xd4\xb1\x2d" + "\xd8\x9f\x23\xdf\x87\x5b\x44\xc6" + "\xee\x24\x1d\x15\x75\xaf\x18\xc7" + "\x59\x62\x3c\xf4\xa4\xc4\xa1\xae" + "\xf7\x02\xbe\x70\xd7\xe5\xc0\x40" +
- "\xf2\x33\x1b\x72\xf4\x90\x45\x6a" + "\xea\x04\xdf\xfe\xfb\xf1\x24\x21" + "\xe7\xef\x45\x97\xde\x3c\xe5\xf8" + "\xd9\x46\xf0\x65\x32\x04\xe1\xe7" + "\xe6\xc7\xd0\xe4\x8e\xa2\xfc\xc3" + "\x1b\x3b\x25\x87\x9a\x33\x7e\x84" + "\x43\xe6\x43\x37\x48\x53\x59\x9b" + "\xc5\x2f\xd1\x4f\x0b\x0a\x6a\xcb" +
- "\xcc\x2d\xd0\x27\xc3\x36\x68\xfb" + "\xc2\xbc\x68\x7a\x82\x09\xd0\x5a" + "\x2d\x91\x5e\x00\x4c\xb4\x24\x1b" + "\xfe\xdc\x1f\x81\x0f\xd2\x83\xcc" + "\x0c\xba\x6f\x66\xc1\x7e\x52\x36" + "\x35\x46\x75\x14\x97\x81\x94\x69" + "\xc2\xa9\x6d\x55\xa8\xb1\xdc\xfc" + "\xb2\x32\xa7\x81\x67\x42\x93\xa5" +
- "\x1d\x18\x14\xa7\xed\x14\x12\xec" + "\x41\xb3\x67\x60\x3b\xc1\x9a\x60" + "\x1f\xdf\x45\xa5\x97\x4c\x4b\xff" + "\x6b\x07\xd2\x34\x01\x05\x24\xa1" + "\x97\xca\x09\x14\x23\x0c\xfa\x6e" + "\x43\x8c\x63\x20\xa8\xc1\x4c\x25" + "\xcd\x46\xfb\xdc\xaf\x63\xe3\xd4" + "\x27\x2a\x94\x03\xc3\xad\xc2\x62" +
- "\x83\x64\xe4\x56\xf0\x9d\x7b\xc6" + "\x56\x63\x73\x63\x20\xbb\x5a\xa5" + "\x52\xbc\x51\xc5\x98\xc0\x93\xab" + "\x4b\xe6\x5f\xb1\xf9\x49\x2b\x38" + "\x47\x8d\xff\x4d\xad\x21\xc2\x9e" + "\xd6\xf4\x7d\x43\x15\xf6\xca\x79" + "\x09\x65\x45\xbb\x64\xdc\x13\x5f" + "\x14\x07\x1f\x19\xd9\x89\xc5\xe4" +
- "\x09\x0e\xd4\x3f\xab\xa8\xb6\x27" + "\xa9\x3e\x31\x77\x2e\x84\x55\xe4" + "\x8b\x98\x55\x1f\xe2\xd1\x51\x8b" + "\xfc\xbb\x2b\x06\x73\xdd\x16\x57" + "\xde\xf3\x8b\x4e\xe5\x11\x3c\x63" + "\x3b\xbe\x85\x1b\xb6\x77\x0e\x9a" + "\xa6\xcc\x11\x09\x29\x07\x51\x56" + "\x0f\x59\xa6\xef\x95\x64\xe7\x27" +
- "\xab\x3a\x0d\x07\x33\x8b\xac\xe4" + "\xe5\xd5\x2c\x9a\x2b\x67\x43\x26" + "\x73\x91\xfc\x1c\x9b\xf7\xef\x52" + "\x3f\xc1\xa7\x90\x9b\xa4\x5c\x66" + "\x98\xb9\xef\xb3\x59\xda\x8d\x5a" + "\x41\x13\x2f\x05\x2d\x92\x5b\x8a" + "\x30\xa5\xf9\x3c\xab\xbb\x9e\xae" + "\xd7\xa4\x6d\xf5\x7b\x6e\x98\x35" +
- "\xcc\x13\x35\xff\x5c\x6b\x63\x3a" + "\xdd\xf7\x98\x31\xba\xf8\x0c\xbb" + "\x86\x6f\xf1\x41\x22\x05\xd4\xb8" + "\xbf\xa7\x13\xde\xd8\x75\x05\x76" + "\x81\xa1\x7a\x9f\x16\x4e\xf7\x36" + "\x1c\xed\x09\xf5\xcf\x3e\x3a\x16" + "\x91\xa4\x40\x3c\x1f\xd6\xea\x6a" + "\xaa\xfc\xe8\xdf\xfc\x95\x8c\x15" +
- "\x6f\xa4\xcd\x13\x6e\x1b\x99\xa3" + "\xd0\xae\x2f\x34\x15\x24\x48\x79" + "\x70\x59\x6b\x66\xde\x5b\xba\xf3" + "\xdd\xb6\x6a\xb2\xbc\xe6\x52\x1d" + "\x3d\xdd\x08\x86\xe7\xa1\x8b\x76" + "\x86\x65\x07\xea\x2a\xdb\x30\x49" + "\xfa\x1a\xdc\xe7\x14\x57\x57\xd9" + "\x17\x88\xc5\xf7\x7d\xbf\xc7\x1f" +
- "\x6c\xe9\xee\xd9\xcd\xac\x47\x6b" + "\x37\xec\x8c\xe5\xfb\x77\xa2\x0c" + "\x2a\xc4\x02\xe7\x13\xe4\x3f\x11" + "\x51\xbe\x7c\xc4\xee\x64\x17\xdd" + "\x39\xd7\x3e\x7b\xde\x7c\x1e\x04" + "\xc0\xe1\xe9\x5c\x59\x74\xcb\x50" + "\x12\xb2\x25\x29\x13\x85\x56\x35" + "\x1c\x08\x1b\x00\xc4\x95\xff\x7c" +
- "\x54\xb4\x88\x80\xbd\x4c\xee\x63" + "\x8a\x0c\x9e\x9a\xf7\x32\x7f\xdb" + "\xcb\x47\x24\x6b\x18\xd4\x77\xb3" + "\x9b\x21\x70\xd3\xaa\x82\xe9\xe3" + "\x93\xa5\xa2\xc2\xe4\xc1\xcc\x06" + "\x4f\xf2\x73\x07\x65\x68\xc3\x72" + "\x23\x94\x85\x95\xa7\x4d\x3b\xa1" + "\x8f\x0c\x04\x75\x33\x1d\xbf\x8b" +
- "\x91\xc9\x50\xda\x73\x09\x6f\x72" + "\xe2\x6e\x2d\x82\x5b\xcd\xaf\x48" + "\x71\x77\xfd\x20\x8b\x71\xfc\xe5" + "\xa1\x07\x08\xfd\x7d\xe7\xe8\xb9" + "\x3d\x70\xa7\x99\x44\x0f\x5e\x7f" + "\xf3\x36\x8e\x61\x0e\x93\x72\x69" + "\xbe\x7b\x80\x23\xb8\x77\x7c\x2b" + "\x50\xff\x27\xcb\x05\x24\xb8\xe5" +
- "\x62\x90\x37\xbd\xe3\x8b\x8b\xba" + "\x92\x4a\xce\x2d\x1d\x7a\x4b\xd6" + "\x37\x2e\x95\xb2\xc5\x73\x0a\x04" + "\xca\xae\x38\xd4\x2e\x25\x9e\x0a" + "\xcb\x3b\x9d\xc3\x6b\x95\x43\xdd" + "\x63\x2d\x2b\xb3\x00\xca\x31\x1a" + "\x18\x7a\x41\x5c\xb8\x33\x71\xd6" + "\xc8\x42\xf4\x2e\x90\x47\x8e\xd0" +
- "\x80\x09\x5c\x25\xe9\x1a\xcb\x98" + "\x9f\x73\x4a\x2b\x81\x63\xd8\x4b" + "\xa1\x45\x4a\x1e\xe1\x31\x5c\x5a" + "\x2f\xdb\xb0\x9c\xfe\x55\x5d\x1e" + "\x29\xcc\xf5\x8f\x06\x1b\x66\x74" + "\xf4\xa4\xb8\x0e\x9f\x38\x6b\x02" + "\x24\x8c\x84\x58\xa4\x21\x6b\x53" + "\xb0\x72\xdc\x81\xec\xf8\x5b\x2e" +
- "\xac\x6a\x88\xad\xd0\x87\xc1\x03" + "\x45\xb6\x71\xb7\x8a\x87\x16\x5c" + "\xab\x45\x40\xc7\x6f\xfc\x7d\xb0" + "\xed\xca\x00\x78\xbf\x60\x63\x2c" + "\xa3\x72\xc9\xb9\xb5\x5b\x29\x24" + "\xba\x6d\x9a\x7c\x8e\xf8\xe6\xc9" + "\xa6\x9a\xa7\x92\x24\xbf\xff\x90" + "\xc2\x6a\xc2\x41\x0a\xd5\x29\xde" +
- "\xe6\xcb\x09\xd3\x83\xf4\x0a\x9f" + "\x4f\xed\xbc\xe0\x8a\x0d\x02\x5b" + "\xe3\x23\x80\xb3\x6d\x98\x6e\x60" + "\x33\x69\xbc\x1a\x9d\x2c\x8f\xad" + "\x93\x0e\x40\xe7\x1d\x2e\x29\x19" + "\x4d\x5e\xbe\x52\xa9\x18\x3e\xfe" + "\xbf\x80\x06\x2e\x1d\x77\xe9\xe8" + "\x63\xb0\x4d\xc5\x98\xec\x5b\x8c" +
- "\x1f\x5d\xa5\x74\x2a\x66\xf9\x2a" + "\xd8\x66\x6f\x04\x8f\xf2\xfb\xe3" + "\x94\x47\xdc\xd4\xb4\x2a\xa7\xa3" + "\xd8\x2d\x7c\x5c\x45\x9f\x77\x09" + "\x8d\x9d\xd1\xc3\xaf\xbd\x93\xd8" + "\xdf\xa6\xd6\x57\x94\x50\xa7\xd5" + "\x55\x62\x2e\x95\xf9\xfe\xf8\x8c" + "\xff\x8a\x9a\xda\xfb\x7c\xa6\x3d" +
- "\xcd\x0d\x16\x2c\x2a\xf6\x23\x4c" + "\xef\xea\x90\x8f\xe3\xc5\xe6\x34" + "\x5a\x5d\xa6\xa9\x19\x55\x86\x35" + "\x3d\x8a\xd3\x8f\xae\x8a\xc4\x07" + "\x27\x85\x06\x50\xda\xae\xe7\xb7" + "\x6a\x93\x90\x1c\x23\xef\x09\x2c" + "\x4c\x32\x79\xe8\xb6\xfe\xec\x31" + "\x38\xc9\x0e\xfb\x6b\x1f\x87\xa0" +
- "\x5d\x83\x4d\xd8\x68\xfb\xf0\xb1" + "\xe6\xc1\x1d\x86\x39\xaf\x0c\xc9" + "\xd7\xf8\x94\x75\x46\xb0\xe5\x12" + "\x92\x2b\x01\x65\xe2\x7a\x89\x26" + "\x5d\x75\xd6\xa4\x08\x8a\xf6\xbc" + "\xda\xfb\x91\x09\x1c\xe4\x3e\x40" + "\xe8\x17\xbf\x3b\x3e\x34\x3e\x73" + "\x65\x3d\x9b\x67\x0d\x98\xc7\xd2" +
- "\x05\x13\xe1\xd2\x32\x62\x05\x33" + "\x6f\x7a\xc0\xf3\x92\xe4\x6b\x96" + "\x9d\x50\x15\xbb\xff\x78\x88\x6a" + "\xa4\x59\x9b\x0a\x01\x11\x22\xff" + "\x29\x01\xe3\xab\x4a\x56\x9f\x6c" + "\xcf\x64\x6e\x33\x40\xc9\xf2\xc6" + "\x22\x80\x0c\x8b\x62\x52\xe7\x0f" + "\x87\xdb\xe8\x6a\xe9\x67\x02\xbe" +
- "\x2b\x04\xbc\x93\xf1\x92\xe1\x22" + "\x58\xc4\x37\xb2\x34\xb5\x85\xf0" + "\x68\x41\x2c\x83\xbd\x92\xd1\xa0" + "\x1d\x27\xf6\xbd\xe3\xe9\x76\x7a" + "\xb5\x11\x89\xb8\xfa\x82\xa8\x52" + "\xb5\x0e\xdb\xb4\xe4\x45\x53\xc8" + "\xff\xc3\xa7\x81\xa6\x02\xbe\xa3" + "\x69\x04\xec\xf0\x8c\x9c\x88\x51" +
- "\xe5\x29\xe8\xa5\x69\x13\x03\x9d" + "\x41\xaa\x07\x16\xfc\xc6\xb4\xcb" + "\xc1\x84\x1d\x24\xa6\x59\xac\x75" + "\xee\xe0\x29\x88\xbf\xf2\x43\xc0" + "\x85\xe1\xa5\x8e\x75\x8f\xa3\x82" + "\x9f\xbd\x7c\xd8\xb9\x40\xda\x8b" + "\x01\xc6\x8f\x2d\x5e\xe7\x65\x9e" + "\xb3\x90\x56\xa3\x74\x5f\x51\x3d" +
- "\xac\xe5\x79\xda\x4f\xcf\x4a\x53" + "\x5f\x21\x30\x86\x3a\x3b\xb8\x68" + "\x6e\x75\x85\xd0\x2e\x8b\x74\x5c" + "\xb2\x7c\xd3\xe5\x58\x72\x31\xb0" + "\xc4\xc2\xcc\xc5\x1a\x84\x35\x67" + "\x69\x50\x9d\x3d\x6b\xc9\x7d\x7d" + "\xbd\x54\x17\xfd\x10\xe4\x47\xa1" + "\xd5\xdd\x99\xd3\x94\x6e\x29\x65" +
-
- "\x3a\xfb\x0c\xb3\xcd\xc4\xe0\xd7" + "\xc8\xb4\x9d\x6c\xc1\xb8\x09\x6d" + "\xdf\xd9\xc8\x07\x42\x1a\xba\x40" + "\x6d\xc6\x52\x1c\xf7\x95\xd4\x6f" + "\xda\x64\x52\x27\x9f\x16\x0e\xfb" + "\x62\x83\x7d\xe5\x46\xb7\xc2\x80" + "\x22\x72\xad\x49\xf7\x87\xd9\xed" + "\x7b\xec\x98\x43\xaf\x29\xc2\xfd" +
- "\x58\x6a\x66\x52\x84\xed\xd1\xb0" + "\xc2\xc3\xa9\xe6\x00\x6e\xcb\x4b" + "\x08\x64\x90\x26\x1c\x41\x57\x3c" + "\x00\x64\x55\x13\x55\x07\xc2\xcf" + "\xa3\xdb\x94\x52\x50\x1c\x8b\xa0" + "\x1e\xd3\x7d\x8b\x86\xa2\x0b\xa3" + "\x74\xca\x1e\x99\x0e\xa9\x0b\xd7" + "\xb9\xc2\x62\xe7\x2c\x14\x4e\x09" +
- "\xef\x13\x7f\xac\x9b\x43\xea\x88" + "\x14\x7d\x9a\x8d\x3f\x14\xaa\x65" + "\x1a\x2f\xcb\x20\x2d\xcf\xe0\xff" + "\xd1\x6a\x1c\x38\xf1\x7b\x7b\x84" + "\x4d\x0b\xc8\x8a\x14\xb8\xf5\x56" + "\xf2\xaf\xce\x35\x18\x44\x1b\x04" + "\xef\xfc\xa5\xcd\xc0\x88\x90\xde" + "\xce\xb8\x83\xe0\x9b\x51\x68\xe6" +
- "\x25\x39\x9f\x97\x3e\x78\x1d\xb8" + "\xa7\x89\x4c\xaf\x0a\x13\xfd\x1e" + "\xfa\xf7\x1b\xfd\x44\x21\x5c\x52" + "\x9e\x5a\x26\x1b\x04\x69\x29\x4b" + "\xb6\x65\xdb\xb9\x34\x96\x8e\xed" + "\x8a\x9d\x59\x03\x32\x2e\xc8\x35" + "\xf3\x63\x35\x40\x4f\xa5\xa7\xda" + "\xab\x38\x2c\x02\xad\x88\xf0\x9d" +
- "\xee\x60\x62\x45\xc1\x5a\x69\x1c" + "\x93\x36\x78\x4d\xdf\xce\x3a\x4e" + "\x8f\x4a\x67\x11\x59\x52\xfd\xda" + "\xf9\x22\x7b\x6c\x40\x6d\x84\x21" + "\x55\x1f\x89\x17\xfc\x1c\x3d\x78" + "\x75\x04\x4d\xd7\x34\x3c\x17\x2a" + "\x20\xfa\x99\xb6\x7f\xbd\xfd\x3a" + "\x62\x9f\x82\xac\xb6\x8f\x24\x79" +
- "\x0a\xd3\x3f\xbb\x66\xb0\xcf\xe5" + "\x4e\x35\xf0\xef\xda\x69\x91\x42" + "\x6c\xe3\x24\x35\x52\xf8\x9c\x80" + "\x1d\xbe\x55\x01\xb3\x4f\x6f\x13" + "\x12\xa7\xbb\x1f\x01\xaf\x26\x48" + "\xa1\xa1\x6b\x50\xb4\xf0\xf0\x6e" + "\x3e\xa7\xae\x77\x31\x8b\x92\xd9" + "\x4e\x24\xaa\x5e\xf2\x6a\xbf\xe2" +
- "\xb2\x1d\xc8\x1a\x3a\x36\x28\x18" + "\x66\x06\x82\x48\xb3\x22\x2a\x75" + "\x6a\xab\x32\x3d\x03\x00\xc0\xcf" + "\xb1\x3c\x6a\xd9\xe1\x77\xd6\x2a" + "\x11\x30\x23\xc8\x72\xe6\xe3\xa7" + "\xb7\x03\x43\x5e\x7e\xe8\x65\x2c" + "\xcb\x04\xdf\xc6\x1b\xf7\x34\x18" + "\x34\xa8\xed\x3c\x2c\x77\xf8\x32" +
- "\x4b\xb6\x37\x42\x12\x4f\x08\x8d" + "\x07\xfd\xec\xe3\x99\xbe\x8e\x68" + "\xd8\x5d\x84\xf6\x0c\xa7\xb8\x57" + "\x25\xa3\xa4\x5d\x9c\xc5\x8f\x80" + "\x62\x58\x58\xa3\x2b\x2b\x03\xa9" + "\x86\x93\xf2\xed\xd5\x25\x68\xb6" + "\x9b\xc2\x1e\x43\xdb\xa8\xa5\xb5" + "\xc8\x8d\x1e\x3a\x98\x3a\x14\xbb" +
- "\xd9\xd1\xe9\xcf\x07\x6a\x35\x5b" + "\xdd\x48\x6f\x30\x3a\x68\xba\xd4" + "\xc1\x37\x64\x2c\xb5\xe7\x6a\x3b" + "\xd4\x4f\xb6\x54\xa1\xc1\xc0\xf9" + "\xd0\x52\x54\xed\xba\x0d\x66\x90" + "\x0f\x53\x50\x28\x95\x3e\x3f\x42" + "\x81\x4d\x27\x47\x06\xa2\x32\x14" + "\x74\x05\xb0\x7d\xf8\xf3\xeb\xcc" +
- "\x1b\x38\xae\x12\xce\x94\xee\x35" + "\x90\xda\xcc\x86\x6c\x17\x7f\x3a" + "\xca\xea\x06\x46\x7e\x65\x3a\xc6" + "\xdf\x04\xcd\x43\x80\xa3\xe5\x9a" + "\x46\x1b\x25\xed\x15\x8d\xec\x9b" + "\x64\x5e\xca\xca\x30\x6d\x5d\x1f" + "\x07\x0f\xf2\x9f\x35\x3b\x7b\x34" + "\x86\xb2\xe4\xf7\x34\xf0\x65\x4d" +
- "\x96\x29\xc8\x06\xf6\x81\x9f\xd8" + "\xfc\x92\xc5\x15\x88\x52\x73\x4f" + "\xc6\xa8\x49\xce\xa1\x03\x0c\x8c" + "\x07\x59\xf2\xb9\xe0\xff\x4d\xe0" + "\x4b\xab\xf7\x4a\x50\x21\x66\x22" + "\x4c\x5c\xa3\xf5\xf6\xff\x21\x9e" + "\x98\x91\x1e\x5a\x84\x44\x1d\x07" + "\x11\xfc\x09\x41\x5c\x95\x11\x08" +
- "\x1e\x66\x11\xf1\x24\xba\x93\x9e" + "\x04\xeb\x05\xb1\x84\xd4\xce\xed" + "\x78\xb5\x24\xf4\xa1\x9b\xdc\x96" + "\x69\x90\x3e\xe8\xb7\x66\x8f\xbf" + "\x16\x82\xed\xd7\xf4\x4d\x2d\x87" + "\xcf\xbe\x2c\x8e\x77\xf3\x07\xbf" + "\x54\x37\xe7\x98\x99\xd8\x81\x42" + "\x08\x87\xab\x8a\xbb\x5f\xc8\xfe" +
- "\x5b\x39\x11\x45\x1d\x41\x28\xd3" + "\xde\xf8\xcd\xe4\x79\xc0\x50\x31" + "\xd0\xbc\x34\x59\xc4\xe7\x4b\x22" + "\xae\xc9\x58\x43\x75\x71\x97\x9d" + "\x4d\xdb\x30\x22\x41\xbb\xb1\xdb" + "\xdc\x31\x8e\x0d\xbd\x84\x8e\x16" + "\xd2\x5f\x11\x1c\x34\x4f\x1b\xa6" + "\x8f\xc2\x88\x58\x15\xfa\x75\xc7" +
- "\x0b\x5b\xba\xa5\xee\x0d\x3c\x9a" + "\x99\x52\xd0\x42\xce\x16\xa1\xe6" + "\x42\x2d\xb0\xe9\xfe\x75\x97\xae" + "\xb6\x5c\x54\xa1\x00\x52\xb0\x72" + "\xea\xb4\xa3\x31\x7d\x6f\x50\xbc" + "\x32\x9b\xbd\x8b\x78\x30\x89\xe5" + "\x97\x2a\xb1\xe4\x37\x5f\xbc\xc8" + "\x71\xb6\x73\x4a\x06\x0c\x00\x6b" +
- "\x8a\x5f\xde\x17\x5c\x92\xc6\xf3" + "\xd5\x91\x49\xf3\x95\x4b\xcb\xa6" + "\x66\x05\xd5\x7d\xf0\x97\xbf\xa8" + "\x9e\xa0\x91\x0b\xe5\x55\x8d\x2c" + "\x20\xe7\xd7\x3a\xed\xc2\xdc\x6a" + "\x5a\xec\x93\x00\x48\x23\x4a\x73" + "\xaf\x36\xcb\x43\xbe\x8f\x1d\xfa" + "\xe4\xa7\xa8\xa4\x1c\xb8\x87\xdc" +
- "\xd0\xa7\x5f\x76\x22\xbf\xb5\x13" + "\x70\x53\x6a\x1d\xf0\x5b\x80\x59" + "\x98\xdb\x80\x42\x9d\xe2\xa5\x67" + "\xe3\x1c\x6b\x77\x6f\x91\x53\x4f" + "\x26\xf6\xdd\x33\x1f\xf6\x4f\x71" + "\x03\xd1\x85\xa0\x8e\x23\x06\x42" + "\xe3\x9e\x80\xe5\xb7\xd4\x50\x1c" + "\x1d\xeb\xf8\x85\x0d\x45\x9f\x99" +
- "\x25\xf3\x39\xa2\xb1\x04\x39\x5f" + "\x90\xad\x58\x1a\xf7\xa6\x26\xd0" + "\xed\x24\xb8\xd6\x36\x27\x54\x43" + "\xb8\x64\x93\x4a\x75\xa7\x41\x08" + "\xe9\x1d\xeb\xcf\x41\xcb\x97\x75" + "\x4f\x0a\x58\xbf\x7a\x2b\x25\x20" + "\x20\x8e\xc4\x17\x81\x92\x72\x37" + "\x71\xa0\xf5\xc6\x28\x1c\xdb\xda" +
- "\x9b\x9e\xc7\xe4\x51\x60\x8a\x65" + "\xea\x9f\x6a\xc6\x73\xcb\x94\x13" + "\x23\x7b\xbe\xc6\xd5\x1e\xf3\x27" + "\xfe\xf8\xa6\x5a\x36\x8f\xc8\xf4" + "\x9e\x49\xaa\x4a\x1f\x72\xb0\x0f" + "\x6b\x2a\xfb\xe3\xd5\xa7\xb3\x68" + "\x1d\x85\x92\x3a\x7d\x09\x88\xa7" + "\x13\x49\x6f\xe9\x8a\x7f\x0e\x06" +
- "\xc1\xfd\xdb\x88\xe2\x0c\xfa\xf1" + "\x08\xdd\xf8\xd2\x80\x74\x39\x3c" + "\xf0\x95\xdb\x4e\x8b\x0a\xf1\x0e" + "\x56\xe5\x47\x32\x75\xbc\x58\x45" + "\xa4\x4f\xc0\x0f\x5f\xef\x5c\x76" + "\x75\x3d\x6d\xd6\xe6\x2c\x9f\x72" + "\x66\xf0\x33\xb4\x5d\x27\x35\x6d" + "\x7e\x59\x4e\x36\x27\x5c\xd9\x31" +
- "\xbc\x93\x3a\x1a\x73\xbe\xee\x82" + "\x1a\xdc\x1a\xa2\x65\xf4\xbb\x42" + "\xfd\x0e\x03\xef\xa4\x6f\x0b\xc1" + "\xbb\x97\xb0\x87\xc7\xa4\x7a\x24" + "\xda\x77\x0c\xf6\x32\xc6\x8d\x8b" + "\x3e\x52\x23\xc2\x6a\xc2\xfb\x6f" + "\xcf\x79\x45\x34\x11\xff\xf6\xa4" + "\xf6\x50\x02\x98\x3c\x65\x25\x58" +
- "\x8b\x39\x1f\xcc\x9a\xef\xea\x88" + "\x95\x7e\x21\xf4\x25\x9a\x18\x85" + "\xef\xfc\x68\xb9\xf5\xf5\x24\x94" + "\x28\x22\x07\xd0\xf9\x8a\x5d\xc0" + "\x2a\xb2\xa1\x49\x8c\xfa\x36\x0b" + "\xce\x5f\x11\xf1\x57\x36\x1c\xe6" + "\x3f\x43\x62\x42\xc0\xf0\xcd\x06" + "\xdc\x20\xc8\x9e\x2d\xc5\x8a\x9d" +
- "\xb9\xa2\x1a\xbc\x7e\x09\xdd\xb2" + "\x3a\x33\xa0\x37\x93\x93\x88\x07" + "\x38\xdb\xa0\x37\x71\x5e\xf5\x1c" + "\x13\x16\x2c\x79\x7f\x48\x48\x26" + "\x61\xf2\xce\x3f\x36\x13\xd0\xda" + "\x29\xf1\xab\x0e\x1d\xc8\x39\x62" + "\xe2\x6b\x27\x9d\xde\x61\xe7\x8e" + "\xd3\x6a\xda\x1e\x34\x7a\x6a\x40" +
- "\x07\x6a\x02\xd5\xac\x10\x73\x01" + "\x1c\x28\x93\xe7\x54\xc9\x26\x35" + "\x51\xac\x00\x76\xc5\x7b\x6b\x41" + "\xa7\x44\x2b\xd4\x52\x89\x67\x09" + "\xb1\x9f\x04\xb6\xb7\x3f\xda\xab" + "\x7b\xef\xad\xdf\x59\xa6\xb0\x3c" + "\x0d\x0c\x8b\x1b\x72\x31\x79\x58" + "\x1b\x61\x9d\x4e\x6e\x47\x73\xfe" +
- "\x31\x3b\x49\x4a\xba\x67\xf3\x4b" + "\x26\xf0\xf7\x9b\x52\x0a\xf2\x54" + "\x4b\x91\x95\x97\x62\xe0\x96\xb6" + "\xac\x36\xf2\x8b\x6d\xb9\xda\xcd" + "\x13\xea\x25\xed\x0a\xc7\xf2\x4f" + "\xe7\xbb\xcb\x81\xeb\x09\x1d\xfa" + "\xc5\x44\x85\x46\x87\x8c\xfc\x88" + "\x17\x33\x6b\x69\x0d\x67\x7a\x84" +
- "\x59\x9a\x51\x45\xe2\xaf\x10\x84" + "\x74\xd7\x30\xbc\xaf\x39\x97\x9a" + "\x88\x4a\xf4\xd8\x03\xde\x33\x66" + "\x37\xdb\x5d\x50\xb3\x9b\x6a\xd5" + "\x14\x5e\x81\x46\x07\x7c\x66\x66" + "\xbb\x93\x44\x88\xed\xf8\x28\x22" + "\x82\x48\xab\x17\x1a\x56\xcc\x23" + "\xce\x1b\x1a\x52\x59\x07\x83\x99" +
- "\x26\xb6\xbc\x64\x1e\x42\x33\xf1" + "\xb5\xe0\xde\x26\xc8\x38\xa6\xae" + "\x6c\x34\x10\xb3\x0b\x68\xe7\xd6" + "\xd3\xce\xd4\xd5\x97\x40\x6f\xe0" + "\x0b\xa3\x12\x75\x52\x14\x96\x09" + "\x9a\xa5\x89\xe5\xfd\x67\xd8\xf3" + "\x80\xc1\xd0\x52\x4f\x25\x73\x2e" + "\xac\x74\x3c\x33\xa3\xd8\x63\x90" +
- "\x7a\x6f\xee\xe2\x44\x27\x14\x12" + "\x3f\x60\x21\x65\x10\x9d\x38\x63" + "\x3a\x81\x9c\x9e\xc7\x82\xcd\xa1" + "\xeb\x42\xe3\x5a\x1c\x64\x09\xc1" + "\xe9\x06\xbb\x04\x30\xfb\x85\x3c" + "\x7f\xf1\x12\xc2\x1c\x44\xed\x1f" + "\x53\x1a\xf6\x82\xac\xdf\x56\x16" + "\x5f\x8f\xd9\xce\x30\x7a\xec\x88" +
- "\xbc\xe7\x14\xd3\x95\xc5\xa6\xed" + "\xed\x99\x78\x46\x4b\x46\xe7\x2e" + "\xd3\xd5\x1e\x0a\x3c\x42\xef\x1c" + "\x13\x76\xcc\x69\xea\x76\x7e\x21" + "\x17\xa9\xcd\xe7\x1f\xce\xcc\x27" + "\x16\x3f\x89\x8a\x6b\x01\xd8\x12" + "\x6b\x4f\xc7\x9f\x84\xde\xd6\xbc" + "\x61\x4e\x14\xf3\xe2\x17\x58\xfa" +
- "\xce\x5e\xc5\x9b\xb5\x39\x89\x0b" + "\xff\x70\xaa\xcb\x3b\xb3\x64\xb1" + "\x91\xb7\x2a\x3f\x0f\x01\x6b\xaf" + "\x37\xcb\x52\x7b\xba\x67\xb7\x98" + "\x41\x65\xf8\xfc\x80\xf3\x0d\xbd" + "\x4a\x01\xa1\x64\x54\xf3\x94\x51" + "\x25\xf6\x35\x4c\x2e\xf2\xc1\x42" + "\x1b\xf5\xbb\xf7\xe2\xf3\x70\x9a" +
- "\x4c\xee\x21\x08\x64\x41\x35\x1f" + "\x92\x19\xc6\x0b\xb4\xea\x83\x15" + "\x9f\x87\x72\x1d\xf6\xca\x90\x74" + "\xb2\xe7\x6a\xf7\xf3\xd9\x8a\x99" + "\xf7\x57\x11\xa4\x50\x19\x18\x1e" + "\x7e\x3a\xda\xe8\xe6\xe1\xd7\xa9" + "\x5f\xb9\x26\x84\xeb\x84\x37\x96" + "\x10\x2a\x2e\x54\x6e\xed\xe4\x0e" +
- "\x83\xfd\x12\x96\xb8\x35\x4d\xbc" + "\xe9\x05\x40\x5c\x50\xca\x77\xf4" + "\xd1\xec\x7e\xa8\x3d\x20\x62\xb7" + "\x86\x25\x08\x38\x22\x9b\xac\x68" + "\x91\x35\x78\xcc\x59\xd6\x96\x66" + "\xb4\x52\x63\xd3\xdd\x43\x46\x25" + "\x69\x1d\xad\x9d\xd9\x70\xe3\xcd" + "\xfa\x5d\x71\x62\x6c\xf2\x7a\x9d" +
- "\x7b\x1e\x75\xac\xc5\x4c\x9d\xb7" + "\xbd\x11\x42\xfd\x72\x64\xf9\x93" + "\xc6\x4f\xde\xc8\xd2\xd3\x72\x8c" + "\x64\xf0\x44\xdf\xf5\xcb\x69\x7b" + "\xe1\x94\xbf\xf4\xa2\x0c\xa9\x3d" + "\xe2\x94\x28\xf1\xf8\x25\x53\x1a" + "\x0b\xd6\x17\x79\x6c\x7f\x43\x0a" + "\x5d\xcb\xc9\x96\x86\x04\xe7\x9b" +
-
- "\x26\x7c\x33\xe1\x76\x99\x9c\x94" + "\xe5\x68\x3d\xd7\xbd\xde\xaa\x6f" + "\xd9\x68\xb7\xf1\x14\x86\x15\x9e" + "\x69\xf0\xc4\x9c\x57\xa5\xdf\x22" + "\xd6\xc6\x93\xbe\x17\xda\xd6\xcc" + "\xb9\xf5\x04\xa5\x61\x6c\x86\x24" + "\xa1\x4d\x69\x8d\x3c\x35\x21\x21" + "\xc6\xb8\x40\x01\x80\xa5\x6c\x1c" +
- "\xb8\x9b\xb7\xd4\x7d\x4a\x60\xf1" + "\xc8\x78\xc8\x52\xfb\x06\xe8\xae" + "\xe8\xb8\x47\x8d\x11\x4f\x14\x34" + "\x54\x90\x9f\x94\x2b\xf5\xed\x72" + "\x5a\x01\x27\x21\x4e\xa8\xfc\xeb" + "\xf3\xce\xb7\x9c\xc0\xd0\x51\x90" + "\xc8\xee\x6d\x29\x58\xfe\xe8\x86" + "\x74\x0d\x01\x41\x88\x81\xb2\x33" +
- "\x40\x9f\xed\x9a\xed\x60\x56\xbd" + "\x99\x8c\x2a\x53\xd1\x6a\xca\x70" + "\xea\x71\xc3\x95\xfb\x8b\x97\xc4" + "\x9d\x10\x03\x70\x0d\x4d\x46\xe5" + "\xef\x35\xe5\xd9\xdf\x2f\xf3\x1a" + "\x5b\x18\xc9\x98\xa7\x7e\xf5\xab" + "\x88\x24\xb4\x12\x17\x74\x7a\xed" + "\xfa\x86\x72\xe9\xa7\x96\x02\x8e" +
- "\x5f\x44\x1b\x17\x83\x93\x07\x01" + "\x4c\xad\x31\x81\xe3\x21\xcf\x9b" + "\xe8\x87\x39\xc9\x05\xe2\xdf\x8c" + "\x8f\x8c\x2e\xc9\x52\x41\x3f\xe6" + "\x3d\xd4\xad\x30\xa9\x62\x94\x72" + "\x5a\xf0\x80\xc9\x43\xb1\xeb\x62" + "\x68\xe9\x06\x3b\xe5\x54\x39\x4f" + "\xb1\xf6\x2c\x24\xad\x75\x1d\xfe" +
- "\x5e\x7d\x01\x1f\x6e\x41\x57\x8b" + "\x9b\xe9\x74\x76\x96\x33\x53\x37" + "\xa0\x88\xf4\xe8\xc0\x94\x6d\x6e" + "\x5e\xf9\x16\xdc\x7a\x78\x3a\xb9" + "\xcc\x9c\xc9\xdc\xa2\x51\xac\xc3" + "\x1d\x7c\xa4\x9a\x13\xb4\x34\xc1" + "\xd5\xd8\xdf\xaf\xaf\xcd\x8f\xf2" + "\xed\x31\xb8\x10\x8e\xbd\x57\x0d" +
- "\x46\xfc\xbc\xf0\xcc\xfb\x76\x92" + "\xe6\xfe\xcf\xb5\xce\x2a\x82\x3a" + "\x5b\x91\x5d\xc7\xfe\xd2\x8e\x32" + "\x6c\x47\x59\xc3\x13\xc1\x45\xa1" + "\xcd\x7b\xe1\x8b\x53\x81\x1a\xf6" + "\x8f\x3d\x6c\xaa\xc3\x67\xe8\x01" + "\x2f\xc8\x16\x65\x5d\xe1\x34\x56" + "\xb0\xb9\x48\x69\xd2\x7b\x43\xc1" +
- "\xc7\xd4\x19\x6c\x00\xd2\xfc\xd2" + "\x76\xe9\xb1\xe1\x37\xc4\xf3\xa0" + "\xe8\x37\xf2\x94\xf6\x5f\x54\xf0" + "\xb1\x8b\xbf\xc0\x3f\xec\x10\xdd" + "\xe1\xd3\x7c\xac\x6c\x69\x89\x4f" + "\xe6\xbf\x24\x5f\xec\x14\x37\xed" + "\x06\x77\xaf\x5f\xd8\xb1\x3e\x36" + "\x32\xcc\x27\xc0\x4d\x60\xbd\xfc" +
- "\xc8\x85\x86\xaf\xc7\xc6\x95\x5f" + "\xaa\x01\x8f\x2f\xce\xc8\xc1\xd4" + "\x2a\x69\x74\x25\x32\xbe\x4b\xc4" + "\x68\xa0\xa4\xd4\x78\x34\x00\xb8" + "\xdb\x3c\xca\x2e\xe5\xc6\x8f\x7c" + "\x99\xd3\x04\xec\x6b\xb1\x1d\xea" + "\xcf\xc5\x2b\x8f\x2e\xc8\x5b\xb0" + "\xd2\x93\x47\xf4\x7f\x51\x3d\x76" +
- "\x3b\x36\x55\xc3\xdd\x8e\xce\x16" + "\x6e\x0d\x82\xf8\x0f\xf7\xf2\x4a" + "\x08\xa5\x61\x76\xd2\xd4\x7e\xcb" + "\x72\x54\x19\xdd\x4e\x44\xd3\x41" + "\x49\x96\xda\x38\xb4\xa2\xfe\x17" + "\x00\xa2\xb4\xae\x56\x93\xf6\x9b" + "\x3d\x9c\xb1\x6a\x91\x5f\x3b\xa1" + "\xa6\x60\x93\xdc\x14\x9c\x51\xc0" +
- "\x71\xe1\x42\x2e\xe9\x1a\x57\xc2" + "\xf9\xcc\x41\xed\x63\xab\x31\xcb" + "\x4f\x85\xc8\xb5\x76\xc5\xf3\x37" + "\xa1\x92\x23\xc6\x1b\x19\xe5\x66" + "\x3b\x68\xd5\x6c\x1c\x5a\x56\x71" + "\x89\xe6\x6f\x60\x83\x02\x4b\x48" + "\xa6\xfd\xe2\x67\x67\x5d\xa2\xf3" + "\xa4\xc0\x65\x8a\xde\x21\xba\x87" +
- "\xd1\x84\x06\xa7\x9c\xe4\x74\xde" + "\x3d\x0c\xe8\x33\x61\x76\xe8\x3a" + "\x4d\xc3\xa5\x16\xa9\xa2\x84\x59" + "\x35\x8c\x29\xb8\xcc\x3e\xa8\x09" + "\xc0\xa4\x4c\xaa\x7c\x86\x19\x9a" + "\xff\xb8\x75\xb3\x10\x56\x08\x02" + "\xdc\x96\x03\xf7\x8b\x32\x96\xf2" + "\x63\xae\x6f\xde\x4c\xdc\x9d\x9c" +
- "\xd0\x98\xbd\x08\xb8\xc1\x51\x44" + "\x40\xf2\x75\x65\xd4\x1c\x4b\x64" + "\x70\xd2\x75\x73\x33\xeb\x07\x69" + "\xbd\x86\x22\xfa\xbd\xbe\xc8\x56" + "\x46\x2b\x63\xc4\xac\xd2\x13\xc7" + "\x42\x02\xd6\xaf\x7a\x42\xda\x17" + "\x46\x75\x5c\xc9\xb7\x65\x30\x31" + "\xde\xa3\x17\xbf\x98\x98\x23\xf8" +
- "\x6e\x3b\x08\x0b\x26\x3d\x68\x94" + "\x4d\xa5\xf6\x06\xeb\x52\x37\x0a" + "\xdd\x74\x20\x75\x23\xdc\xbe\x48" + "\x93\x25\x82\x3e\xfc\x22\x76\x63" + "\x3b\x5d\xe5\x6b\x13\x05\x00\xea" + "\x6d\x00\x4d\x32\xf4\x12\x5e\x9f" + "\x70\x02\xfc\x64\xa9\x86\x94\x52" + "\xe6\x99\x33\x92\x0c\x0d\xba\x09" +
- "\x80\x70\x97\x3a\x47\x58\x38\x36" + "\xb6\x6a\x6a\x0c\xb8\xe1\xf8\x4c" + "\x1e\x26\x82\x04\x6c\x5c\x9a\x91" + "\x06\x48\xce\xe5\xd0\x9a\x7a\x51" + "\xaa\xa7\x6a\x05\x0c\xd4\x92\x27" + "\xb0\x61\x6c\xe5\xda\x6a\x7c\x4c" + "\x0c\x9e\xb1\xa4\x78\xb1\x9c\xf1" + "\x7f\x26\xba\xe4\x4f\x5c\x6d\x04" +
- "\xb3\x50\x15\x12\xab\x26\xe9\xd3" + "\x84\xce\x47\xc1\x4a\x5e\x97\xe4" + "\x2a\x72\xff\x5e\xf9\xe0\x8b\x7a" + "\xa0\xf2\xd4\x6f\x2c\x70\xe4\x71" + "\x80\xb2\xb7\x3c\xcf\x2a\xb9\x13" + "\x73\x2d\x27\x28\x6d\x71\x88\xc5" + "\x5c\xfe\xa9\xda\xf3\x7b\x2c\x86" + "\x42\x9e\xa7\xe2\xf2\x08\xc0\x78" +
- "\x20\x03\x83\x4c\x3f\x96\xb7\xf3" + "\xe3\x03\x32\x90\xa0\x7a\x2c\x84" + "\xfb\x7a\x32\xe7\x0a\xca\x22\xaf" + "\xb6\x09\x76\x96\x92\x30\xe1\x38" + "\xf1\x58\x75\x75\x62\xfb\xb8\x73" + "\xc1\xa8\xec\xf7\x31\xe8\xc3\x3c" + "\x27\x16\x33\xf6\x74\x44\x17\xe4" + "\x34\x02\xc4\xc3\xca\x89\x79\xa7" +
- "\x1f\xfa\x36\xf5\xc5\x32\x58\xed" + "\xa4\x44\x82\x92\x55\x3f\x6f\xe1" + "\x90\xe1\x5b\xbf\x21\x26\x3a\xf4" + "\x2b\x6b\x2b\xca\xc3\x72\xd6\xf7" + "\x83\x5b\x7a\x82\x45\x62\xf8\x64" + "\x72\x7f\xe9\x00\xf5\x09\xa1\xc1" + "\xbb\x27\x73\xa4\x5c\x78\x59\xc2" + "\xb6\x62\x6a\x7f\xe9\x09\xf1\xda" +
- "\x20\x51\x56\x57\x18\xdf\xab\x88" + "\xf1\x2b\x5f\xf2\x72\xbc\x34\xbf" + "\x40\xea\x83\x62\x22\x6a\x21\x0c" + "\xe4\x18\x2e\x07\x46\x20\x3d\x57" + "\x36\x81\xbe\x11\x6a\x0f\x11\x11" + "\x1b\x86\xe4\xd6\x84\x2a\xf3\x10" + "\x31\x75\x29\xee\xe2\xde\xed\x3e" + "\x69\x42\x40\xd3\x99\x7f\xf3\xb3" +
- "\x3a\xd4\xc1\x1c\xe9\xf5\xa3\xce" + "\xf4\x3a\x23\x6a\xdb\xca\x4a\x62" + "\xc2\xe7\xef\xd0\xa9\x18\xdf\xc9" + "\xf3\x79\xba\x79\xe8\x0b\x0d\xfe" + "\xea\xf5\x2f\x52\x56\x5a\x4c\xc7" + "\x4e\x51\x7d\x6c\xf0\x79\xc3\x4a" + "\x9f\xa2\x0e\xd7\x04\x14\x92\x64" + "\x70\xf2\x69\x02\x91\xe5\x3e\x44" +
- "\xe0\x81\xa0\x44\xa1\x17\xfd\xe5" + "\x6a\x29\x0e\xb7\x7d\xfb\x97\xd7" + "\x9c\x71\x1f\x48\x30\x2b\x47\x2b" + "\x52\x8c\x6f\xfe\x98\x2a\x63\x0e" + "\x84\xc2\xf0\xc5\x16\xd1\xcc\x89" + "\x62\x7c\x98\x2d\xaf\x88\x10\xf5" + "\xcf\xe6\x2d\x4c\xda\xcc\x2b\x2a" + "\xf9\xf0\x79\xf6\xfe\x9e\x0f\x81" +
- "\x39\xa5\x1e\xa6\x43\xf4\x74\x38" + "\xdf\xfe\x06\xc2\x11\xa3\xa3\x90" + "\x85\x87\xbd\x0f\x5b\x7b\x2a\x96" + "\x8b\x1c\xc3\x58\x70\xe9\x37\xfc" + "\x48\x10\x1a\x5f\x38\x55\xeb\xcd" + "\x55\x62\xcd\x8c\x22\x51\x20\x5a" + "\x8b\x1b\x4f\x9c\x96\xd4\x62\x97" + "\xde\x05\x2f\xd5\x03\x88\x3d\x21" +
- "\xf6\x73\x4c\xe5\x7b\x37\x64\x7c" + "\xc0\xfb\x4e\x5a\x04\xfe\xbf\x65" + "\x41\x85\xf5\x36\x63\x30\xd2\xd0" + "\xf0\xbd\xcd\x25\x6f\x06\xd6\x54" + "\x5b\x6d\xf8\x5c\x63\x2d\x5f\x68" + "\xe5\xf6\x2e\xf1\xc1\xe9\x51\x8e" + "\x82\x6d\x34\xcb\x2d\x04\xaf\xa6" + "\x6f\x81\x73\x00\x79\x50\x95\x37" +
- "\xf4\xf7\xc5\x13\xa7\xd3\x9c\xc8" + "\xed\x2e\x35\xac\x4e\xb5\x9c\x0d" + "\x88\x47\xb3\x33\xee\x7a\x2e\x46" + "\x9a\x8d\x99\x7c\x43\xf1\x1a\x83" + "\x87\x4f\xe0\x11\xc9\x02\x88\xed" + "\x69\xd9\x38\x19\x0b\xa0\xa1\x1c" + "\x10\x93\xbb\x7b\xb4\x5b\x80\x52" + "\x10\x64\xc1\x31\xe4\xcd\xa3\xca" +
- "\x3e\x4b\xfe\x7f\xb9\x94\xf3\xb0" + "\x21\x5d\xfa\xe5\x21\x1d\x69\x0b" + "\x75\xbc\xfb\x9d\x47\x77\xbd\xb0" + "\x00\x8b\xf7\xfa\xda\x0f\x83\xd2" + "\x57\x4f\x43\x52\x9c\x24\x8c\xf7" + "\xab\x6d\x09\x98\x45\x75\x1f\x4b" + "\xb3\xc0\xf8\x8f\x94\x6f\xbf\x73" + "\x4c\x13\x4e\x45\x3d\xf0\xae\x34" +
- "\x59\xc0\x0b\x39\xd5\x56\xb8\x2e" + "\xdf\x12\x13\x04\x5f\xbd\xea\xc0" + "\x7b\xd6\x36\x86\xdf\x45\xef\x7e" + "\xb5\x7f\xea\xdf\x1f\xe8\x09\x69" + "\x37\x77\xda\x31\x53\x8c\x8e\x62" + "\xbc\x55\x5b\x75\xe3\x8b\x2f\x1b" + "\xd7\x41\x78\x13\x12\x05\xba\x35" + "\x7d\xe5\x7c\x31\x59\x03\x55\x59" +
- "\xc9\x6d\xd1\xf5\x07\xd4\x51\xb2" + "\x1c\xcc\x72\x4c\xaf\xaa\x1f\x54" + "\xcc\x73\x81\xe5\xac\x70\x81\xd2" + "\x5a\x1b\x0c\x7b\xc5\x57\xc0\x1c" + "\x74\x23\x06\x21\xe6\x74\xb2\x04" + "\x79\x8c\xcb\xe2\xa7\xca\xac\xef" + "\x95\x94\xea\x24\xec\xc3\x66\xc4" + "\x15\x7c\xef\x67\xf3\x6e\x51\xc3" +
- "\x1c\x5c\x57\x45\x3b\x00\xef\x34" + "\x0c\xfe\xc2\x49\xa0\xe7\xb3\xde" + "\x63\x9c\x14\xf7\x1d\xc0\x8e\x04" + "\x6c\x98\x9a\xc7\xb9\x69\x38\x20" + "\xef\x80\x1e\x6c\x83\x40\x7c\xcf" + "\x47\x44\x29\x8e\xd5\x17\x0e\x21" + "\x1c\x60\x12\x12\x2e\x7d\x50\x2b" + "\x79\xe2\x17\x5a\xfa\xd3\xed\x98" +
- "\xc5\x7e\xac\xb7\xf4\x51\xd1\xf8" + "\xd5\xa7\x0d\xe5\x5a\xb9\xce\xd6" + "\xb8\x0e\x3a\xdc\xb0\x92\xb4\xa1" + "\x63\x28\xdd\xb3\x69\x7b\x15\x75" + "\x62\x3d\x41\xc5\x4e\xc7\xc4\xe2" + "\xc7\xc4\x5f\xbc\xf7\x9f\x32\xbe" + "\xda\x9d\xfa\x60\xea\x2a\x5a\x83" + "\x87\xcb\x45\x74\xad\xf5\x17\xf1" +
- "\x1d\x69\x1d\xe9\x36\x26\xf4\x9b" + "\xe4\x7b\xc0\x8f\x42\x32\xcc\x0b" + "\x90\xaa\xe9\x69\xae\x5c\x20\x5b" + "\x5e\xf7\x9c\x39\x2b\x72\x69\x6f" + "\x35\x42\x42\x79\xf6\x59\xb0\x3d" + "\x63\x54\x20\xa2\x04\xb4\x98\x6b" + "\x51\xf4\x60\x6f\xe4\xf5\xca\x68" + "\x9e\x93\x08\xad\x66\xfc\xf1\xe8" +
- "\x1f\xb2\x46\x63\xd4\x1b\x66\x36" + "\xf0\x9d\xb6\x3c\x1d\xb0\x6f\xde" + "\x0a\xb4\x84\xa8\xe4\xa0\x05\x7d" + "\xbf\x4a\x3d\xef\xd4\x69\x25\xd9" + "\xf8\x61\xb2\xe6\xe1\xd7\x2b\x1c" + "\xef\xdb\x4d\xc7\xe5\xb0\x03\x05" + "\x37\x4c\x9a\xe0\x39\x1a\x36\x6a" + "\x73\x84\xff\xe7\x08\x75\xd5\x7f" +
- "\xf8\xed\x76\xc7\x67\xfd\x39\x19" + "\x8a\x84\x5c\xcb\x70\x7c\x84\xd0" + "\xd1\x03\xde\x5a\x91\x53\xf5\x4f" + "\x3e\x82\xa9\xcf\x83\x4d\xb5\x8f" + "\x04\x4e\x0d\xf1\x6e\x14\x08\xb3" + "\x36\x2a\xcb\xb6\xb3\x91\xa6\x14" + "\x7f\x65\x20\xc6\x93\x9b\x41\x2f" + "\x7f\xda\xe1\xd3\xa2\xaa\xb7\x4d" +
- "\x7a\x6f\x16\xb0\xf4\x17\x83\xae" + "\xe6\x74\xec\xce\xf7\xe3\xd3\xfb" + "\xfd\x4b\x87\xe0\xac\x16\xb5\xfd" + "\xa3\xf3\x81\xc6\x19\x60\x84\x3d" + "\xb0\x20\x16\x7c\x5c\xee\x12\x0b" + "\x01\xc5\x63\x2b\xdd\xb4\x68\xba" + "\x1e\xc5\x68\x66\x32\xcd\x03\xac" + "\x5b\xcb\x0b\x4e\xf7\x79\x62\x2a" +
-
- "\xa8\xcd\x5f\x8f\x9f\x13\x8e\xfd" + "\xfd\x5b\xee\xbd\xc4\x58\xe5\xf3" + "\x77\x9f\x3f\xe3\xf4\xba\x6c\xd7" + "\x69\x19\x77\x71\xa4\x97\x4c\x3a" + "\xa7\xe6\xdc\xf6\x4b\xe8\x27\xda" + "\xd1\xc2\xe6\x13\x96\x3d\x37\xff" + "\xe9\xa6\x59\xd7\x3c\x19\x15\xf1" + "\x2c\x26\xd2\x63\x25\x70\x9b\x3f" +
- "\xc8\x5c\x33\x1a\x91\x84\x31\x8c" + "\xe4\x13\x59\x6a\xba\x59\x34\x56" + "\x19\x29\xb3\xc7\x61\x0d\x92\x1b" + "\xad\x25\x24\xa0\xb6\xb8\x5a\x80" + "\x86\x60\x00\x8d\xda\x12\xc5\x2a" + "\xfd\xc0\xf5\xbc\x6a\x84\xa4\x6c" + "\xd7\x38\x21\xac\xd8\x51\xea\xaf" + "\x43\xd4\x4c\x34\x45\x75\x64\xcb" +
- "\x85\xca\xed\xcd\x66\x24\x1b\x9f" + "\x8c\x53\x09\x1a\x10\xb7\x0b\x14" + "\x5d\x11\x11\x5e\x51\xe8\x8a\xac" + "\x9e\xf5\x03\x6f\x67\xff\x63\x0d" + "\xfb\x4a\x23\x7d\x51\x55\x5e\x75" + "\xc1\x8f\x20\x7e\x4e\xdb\xc2\x61" + "\x5d\x4b\x8a\xf2\xce\x59\x98\xaa" + "\x0f\x03\xaf\x34\xfc\xd4\xd6\xbd" +
- "\x74\x47\x54\x53\xe4\x53\x10\x51" + "\xbc\xa2\xdb\x3a\xcc\x0e\x4d\x83" + "\xf5\x71\xe3\xba\xf7\xd7\x15\x42" + "\xbc\x63\x86\x6c\xbf\x57\xfd\xfc" + "\x1d\x1b\x90\xd6\x3d\x38\xd2\xde" + "\xc3\x7d\x58\xb5\xb4\xfb\x49\x3b" + "\x62\x5f\x62\x07\x8d\xa0\x44\xfd" + "\x62\xb7\xe9\x9d\x5b\xd6\xe4\x3e" +
- "\xde\x15\x78\x71\x6e\x4b\x99\x5a" + "\xd1\x31\xe1\xa7\xa0\xc7\x95\xd9" + "\xaa\x23\xc0\x26\xf2\x6d\xb4\xc8" + "\xed\xfc\x2a\x70\x4d\x09\xfd\x8c" + "\x86\xa8\xd6\xce\xcd\x43\xc7\x7b" + "\x75\xbe\xca\x1f\xc4\x0e\xd7\xb7" + "\x90\x93\xac\xdd\x47\x9e\x6c\x2a" + "\x90\xaa\x10\x93\x25\x94\x06\x72" +
- "\xeb\xd0\x64\x54\xf5\x80\x7e\xd1" + "\xa7\x13\xa6\x67\xa7\xe1\xd3\x89" + "\xad\x7d\xc9\xc8\x60\x12\x79\x77" + "\xe7\xcb\xf0\xe4\x1f\xf2\x2f\xec" + "\x10\xbc\xe6\xe9\xc2\x4a\x98\xed" + "\x05\xa3\xcb\x77\xe8\x3d\xc5\xe3" + "\xdc\x4f\x62\x83\xb2\xf9\xba\x9b" + "\xec\xc0\x85\x14\xcd\x51\x94\x5e" +
- "\xc8\x1e\x76\xb1\x6d\x75\x13\x1f" + "\x55\x7e\xb9\xa4\x98\x8b\x3c\xe5" + "\x28\xcc\x96\x40\xf8\xe3\xae\xb2" + "\x8d\x1a\x0f\x92\xa0\x61\xc3\x48" + "\x0a\x19\x31\x8c\x2d\x67\x8b\xa9" + "\xd4\x55\x18\x00\xd1\xe7\xc1\x7b" + "\x2a\x4b\x3f\xbf\x07\xfb\x2c\x24" + "\xc4\x8b\xa2\x32\x3f\x4a\xf4\x9b" +
- "\xfa\xd1\x63\x0d\x7d\x13\xe5\x64" + "\x9f\xd8\xa9\x02\x52\xc0\x8f\x65" + "\x09\x63\x43\x50\x74\x48\x89\x48" + "\x61\xda\x98\xd5\xf8\x30\xae\xe9" + "\x91\xaf\x8b\x81\xd1\x10\xd7\x2e" + "\x20\x0c\x6a\x8b\x06\x9e\x7e\xe2" + "\x44\x6b\x1a\x1c\xfb\xdc\x28\x1e" + "\xdc\x57\xac\xd6\x64\xcb\x3a\x88" +
- "\xa5\x76\xe1\x42\xac\xe2\x82\x99" + "\x64\x2b\x78\xe2\x46\xba\x4e\x32" + "\xf5\x50\x83\xe1\xaf\xaa\x8c\x3d" + "\xca\x74\xd6\xf5\xf2\x2a\xd8\xf3" + "\x1e\x0d\x60\x56\xed\x0f\x09\xc2" + "\x07\xde\x50\x59\xef\xe0\x48\x45" + "\xeb\x4f\x5a\x76\x3f\x02\xf0\xb2" + "\x90\x67\xf1\x39\x33\x10\x03\xb3" +
- "\xb3\xc8\xa3\x61\x1d\x78\x92\xa6" + "\x0e\x6d\x87\x32\x54\x38\xbc\x08" + "\x03\x7b\x02\x28\xfb\x05\xcf\xbe" + "\x2f\xe1\xb1\xa4\x7d\x68\x6c\x63" + "\x58\x7c\x21\x07\x3d\x00\xe3\x00" + "\xa3\xb2\x01\x5e\x37\xa9\x3b\x61" + "\x6e\xe1\x1d\x88\x05\x84\x8c\xa5" + "\x8b\xf4\xf8\x14\x30\xc4\x53\xc6" +
- "\xf9\xd0\xa0\xd6\x97\x68\x1c\xbc" + "\x55\x7f\x0d\x3b\x0e\xea\xe0\xd8" + "\xad\x7a\x5b\xb8\x92\xaa\x5b\xb3" + "\xf4\x48\x4e\x67\xb7\xd1\xec\x2b" + "\xc2\x9a\x7a\x6d\x8d\xf7\xd7\xe2" + "\xd0\x95\x9c\xf9\x62\x42\x07\xf5" + "\xe9\x11\xf6\x89\x0a\x47\x52\x48" + "\xec\x9d\x86\x92\x19\x91\xaa\xf7" +
- "\xe2\xaa\x6d\x4e\x77\x2e\x7f\xed" + "\xbc\x19\x0a\x9e\xe3\xe0\x3a\x7b" + "\x7e\x67\xae\x91\x8a\x3f\x29\xd3" + "\x1f\x61\xc8\x45\xcb\xb0\x63\xd3" + "\x3b\xe9\x9a\x30\xcf\x1c\x1d\xbe" + "\xe1\xca\x20\x39\xe7\x0b\xf8\xa3" + "\x01\xdf\x8e\x49\x74\xba\xac\xaa" + "\x90\xac\xf5\xb2\x4a\x2a\x6d\x1e" +
- "\xf1\x50\x35\x23\x3f\xf0\xc5\x60" + "\x2e\xfd\x5a\x92\x11\x94\xd0\xd4" + "\xa6\xe5\x58\xd2\xc3\x65\x5b\xa9" + "\x6a\x2c\x90\x9f\xb5\xcf\x19\x1a" + "\x68\x5c\xad\xf5\x3a\x01\x86\xb4" + "\xf3\x38\x96\x97\x76\x67\x50\xa2" + "\x28\x0b\x8e\xa3\xd0\xb4\x32\x12" + "\x4f\x7b\x6a\xd3\xb8\x84\x47\xa6" +
- "\x96\xa6\x66\x02\x9e\xa1\xcf\x7f" + "\x4b\xfb\xc3\x92\xfd\x64\x1f\x5e" + "\xdf\x19\x6d\x50\x11\x49\x95\x6d" + "\xa1\x3c\x7a\x69\xe1\x9f\x98\x9f" + "\x7d\xa8\x27\x23\x8c\x8d\x48\x7e" + "\x17\xa3\x7d\x03\x28\xce\x43\xa5" + "\x18\x55\x3c\xf9\x76\x1d\x07\xea" + "\x3b\x6d\x0a\x22\x48\xfd\x5f\x58" +
- "\x03\x0e\xd7\xe7\x9d\x17\x55\x56" + "\x70\x45\xa8\x72\x5c\x0c\x78\x3e" + "\x9c\x02\x50\x1d\xcb\xb4\x02\xc1" + "\x39\xe8\x75\xf0\xd5\xbd\x71\x3e" + "\x22\xb8\x98\xb4\xf0\xf4\x60\x64" + "\xa5\x8d\x4b\x6d\x6c\xe0\x82\x26" + "\xd4\x40\xa7\x96\xc9\x53\xae\x4e" + "\x2c\x70\x89\x63\xef\x8b\x9d\xc1" +
- "\x70\xff\xc6\xc2\x8d\x72\x35\x87" + "\x35\x22\xdc\xc5\x2f\x12\xd6\x79" + "\xf9\x77\xe2\x19\x03\xd0\xf5\x23" + "\xc7\x8c\xed\xdd\x25\x4e\xe8\x7e" + "\x0a\x88\xcd\x63\xb0\xaf\xa8\x91" + "\x60\xaf\x74\x35\xc6\xa7\x3e\x3f" + "\x42\x7f\xde\x02\x84\xdc\xfc\x0c" + "\x52\xa1\x1a\xb3\x2f\x79\xd0\x62" +
- "\x55\x16\x3b\xee\xb2\x47\x9a\x95" + "\x5b\x3d\x88\xec\xdd\xb9\x99\xc7" + "\x04\x38\x93\xb7\x80\x9f\xc0\x2d" + "\xb8\x3d\x2d\x3d\x88\xe8\x69\xae" + "\xf4\x0a\xe7\x25\x2f\x5e\x5d\xc1" + "\x85\x00\x04\x05\xce\xd9\x5f\x87" + "\xf2\x38\x5a\x6b\xd0\xe8\x50\x28" + "\xda\xb0\xbe\x9a\x35\x7f\x22\x15" +
- "\xf2\x23\xe5\xe0\x37\x10\x0f\x65" + "\x3b\x01\x83\x95\x43\xab\x38\x44" + "\x5e\x90\xc0\xef\xfb\x68\x42\x03" + "\x6b\x77\x06\x0c\xa2\x4b\x28\x7b" + "\x33\x11\x6c\x1b\xc4\x49\xb9\x02" + "\x4f\xef\x4b\x19\x47\x8d\x3b\x7c" + "\x35\x05\x7e\x0e\x00\x5b\xe1\x5f" + "\xb4\x26\xb1\x28\x74\x66\x26\xc3" +
- "\x44\x11\x92\xe0\x42\x93\xb9\xf8" + "\x2c\x3e\x03\xb5\xf1\xc6\x4f\xf1" + "\x54\xcf\xda\xdc\x60\x37\xfb\x7d" + "\xa5\x7b\x8d\xd8\x31\x0a\x5a\xd2" + "\x77\x49\xf7\x68\xcb\x2f\xed\x4d" + "\x07\x40\x76\x9a\x65\x47\x88\xf1" + "\xc7\xf4\xdc\xf2\x69\xb1\x9d\x87" + "\x6a\xf9\x6d\xd1\xd5\x75\x4d\x74" +
- "\xb5\xef\xcc\xbe\xaa\xf5\xfd\x40" + "\xc7\xd7\x21\x36\xe9\xed\x56\xcf" + "\xc1\x76\xb5\x52\xce\xa9\x32\xb6" + "\x27\x60\x6f\x9a\xe8\x3a\x40\xd3" + "\x64\x5a\x78\xe8\x0d\x05\x0a\x66" + "\x2e\x65\x82\x96\x47\xd6\xf3\x10" + "\x02\xbe\xbc\x4f\xdf\x5e\xb2\x78" + "\x5d\x31\xf9\xb4\xde\x0f\x71\xc9" +
- "\xf9\x35\x02\x1e\x9a\x00\x88\x0f" + "\xa1\xb8\x20\x48\x27\x40\xed\x2f" + "\x40\x11\x08\x86\xac\xb7\x72\xbe" + "\xe3\x63\x11\x60\x72\x26\x16\xd4" + "\xea\x71\x0c\x75\xad\xa3\x1e\xf7" + "\xe3\x8b\xdc\xaf\x40\x71\x34\x02" + "\x6b\xa6\x5a\xc6\x29\x6f\xe6\xa5" + "\xc8\x8f\x39\x07\x64\xec\xc7\xf3" +
- "\xa2\x38\x99\x17\x63\x67\x09\x14" + "\x77\xb8\x1c\x1c\x71\x0e\xba\x4f" + "\xcf\x7c\xcf\x7c\x2f\x2a\x6f\xda" + "\x65\xde\x1b\x09\x4e\x1a\x24\x91" + "\xd8\xfc\x71\x1e\xc3\x56\x28\xcc" + "\xc3\x1c\x44\x12\x7c\x7e\xb8\xc0" + "\xaa\x24\xf2\xe5\x1e\x68\xd1\x3d" + "\xea\x08\x73\xad\xf6\xd6\xae\x30" +
- "\x22\x3e\xb5\x28\x17\xb0\xb8\xd4" + "\x71\x7c\x7b\x0f\x48\xd9\x94\xe3" + "\xdf\xaf\x1c\xb2\x68\x23\x1f\xe2" + "\x33\x78\xcc\x86\xb6\xfa\x11\xc9" + "\xd7\xcc\xd1\x39\xfd\xf6\x61\x0f" + "\xa9\x90\x8d\x24\x8b\xeb\x16\xe2" + "\x0d\xd2\x22\xfc\x44\x8f\x05\xa5" + "\x28\x96\xc6\x57\x92\x96\x26\x91" +
- "\xce\x07\x58\x8a\x43\x4e\x1b\x8e" + "\x7e\x9a\x10\xe4\x93\x38\x28\xad" + "\xda\x9d\xd5\xaf\xcb\xc9\x0c\xc3" + "\x93\x80\x8d\x3d\xc6\x36\x5f\xf6" + "\xb2\x32\x0d\xa6\x9e\x46\x31\xdf" + "\xc8\x91\x81\x3e\x4b\xdf\x93\xee" + "\xb5\xde\x5b\x35\xc5\x17\x10\x9c" + "\x28\xaa\x16\x86\x85\x31\x62\xd2" +
- "\x10\xed\x48\xa4\x64\x4f\xed\x38" + "\x8b\xb7\xef\xc4\xa8\x03\xeb\x81" + "\x52\x3b\x32\x91\x5c\x1b\xd9\xbf" + "\x2e\xff\xbe\xb6\x33\x2b\x88\xed" + "\xa1\xd7\x22\x67\x51\x45\xfb\xd0" + "\xab\xe8\x9f\x94\x1b\x44\x91\x6f" + "\xa6\x81\xc1\x3a\x99\x4a\xa4\x63" + "\x74\x6b\x0b\x95\x5f\x2b\xa6\xf4" +
- "\xcf\xa2\x01\xe8\x46\x44\x61\x22" + "\xdf\x8c\x47\x2e\x27\x20\x3a\xfa" + "\xb3\x50\xc6\x98\x9a\x0c\x2a\x10" + "\x70\xff\x73\x48\x98\x93\x00\xc5" + "\x01\x6d\xa1\xfa\x06\x86\xec\x87" + "\x8b\x4d\xdd\x9e\x94\x27\xc1\x0f" + "\x60\xd4\x6b\x6f\x00\x7a\xa9\xe7" + "\x59\xff\xbe\x5e\x30\xd1\x9c\xf6" +
- "\x28\xa2\xb5\x62\x86\xd1\x09\x62" + "\x26\x8b\x40\xd4\xaa\x7d\x5d\xb8" + "\x00\xb3\xb1\x8e\x0f\x11\x48\x7e" + "\xab\xaa\x64\x04\xd2\x3c\x78\x66" + "\x61\xa0\x8b\x0f\x25\x8b\xf6\x2d" + "\xeb\x8a\xa0\xb2\x61\xc4\xe0\x97" + "\x38\x0d\x64\xbd\x0e\x6f\x8f\x6f" + "\xa6\x5d\x47\x41\xe1\x22\x33\x99" +
- "\x0e\x98\x45\x32\xe7\xad\x55\xd6" + "\x00\x72\x06\x81\x57\x96\xf5\xa6" + "\xe1\x6b\x13\xdb\xbe\x23\xfc\xe4" + "\x79\xd8\x13\xaf\xdc\x6c\x24\x9f" + "\x0e\xac\x61\xf9\x17\x31\xb9\xc2" + "\x1a\x9e\xdb\xeb\xb5\x41\xa7\xc8" + "\xd1\x3b\x69\x6c\x46\xe2\xed\x82" + "\x1e\x70\xd1\x3d\x4f\x6b\xde\xfc" +
- "\x6f\x64\xa4\xca\x00\x4e\x80\x1f" + "\x24\x49\x94\x70\x88\xdc\x43\x86" + "\xe9\x6d\xf8\x73\xa2\x1c\x7f\xa3" + "\x98\x98\x88\x28\x92\x9f\x19\xa3" + "\xdf\x4a\x1e\x0c\x58\xba\x73\xc2" + "\xf0\x82\xbc\x65\xaf\x38\x0d\x0f" + "\x3b\xcd\xa6\xf8\xb5\x8a\xb2\xd8" + "\x8e\x4d\x89\x75\x85\xe0\xa6\xee" +
- "\x15\x32\xc9\x0e\x98\xb9\x42\x46" + "\x9f\x34\x9d\x29\x0a\x17\x19\xb7" + "\xba\xb5\x36\xbc\x2b\x16\x2c\xb3" + "\xa2\x3c\xd2\x4b\x85\x73\x35\x06" + "\x15\x81\xf6\xdf\x92\x62\x41\xff" + "\x99\xdb\xb5\x4b\xe3\x50\xa1\xb7" + "\x55\x3d\xc1\xa3\x28\x20\x7a\xb9" + "\x06\x45\x42\xe5\xc1\x06\xf4\x86" +
- "\xcf\x95\xcd\xb9\xb9\xc1\xb0\xfa" + "\x73\xae\xa9\x11\xb3\xab\x85\x36" + "\xa3\xa9\x96\xa9\xaf\x3e\x97\x02" + "\x1d\x57\x34\x29\xaf\x9b\x6f\xff" + "\xe8\x40\x7c\x25\x21\x81\xab\xe4" + "\xb1\x30\x2d\xd9\xe4\x28\xad\x09" + "\x82\xb5\xe4\x09\x35\xa0\x51\x7c" + "\x0f\x12\x5b\xc3\xf8\x01\xbb\x60" +
- "\x21\x1a\xc3\xde\xf9\x83\x2c\xb0" + "\x73\xd5\xd9\x6a\x23\x8b\x8c\x98" + "\x65\xe3\x7b\xa5\xae\x83\xe9\x53" + "\x4e\x83\x6f\x64\x4d\x73\x68\xe9" + "\x9b\x30\xa6\x5d\x8f\xea\x37\x91" + "\x16\xce\xf1\xc1\x24\xa6\xf3\x10" + "\x21\x09\x44\xca\xa2\x9e\x2a\x78" + "\xb5\xf1\x46\x5b\x9e\x73\x94\xdf" +
-
- "\x6a\xb1\xf8\xf4\x0e\x41\xf8\x56" + "\x6a\x26\x7b\xc4\xfe\x1a\x24\x97" + "\xc1\x87\x9c\x6d\x8e\x6b\x40\x0a" + "\x1b\xab\x42\xcd\x02\x3e\x3f\x80" + "\x69\xec\xdb\x04\xa8\x09\x03\x7f" + "\x5f\xd0\xba\x3b\xf7\x85\x3b\xa8" + "\x7f\x19\x8e\xad\x73\x72\x09\xc6" + "\xc1\xad\x67\x50\x0e\x44\x97\xc0" +
- "\x8c\x89\x11\xb3\xa0\x7f\x74\x3f" + "\x65\xac\x0e\xcd\xe4\x72\xa2\xe2" + "\xbc\xd0\x14\xf9\x51\x58\xba\x4b" + "\xe3\x3e\xa4\xc4\x60\x96\x1a\x7a" + "\xe9\xcd\xc8\xa1\xce\x67\xa3\xe5" + "\xe3\xab\x71\x72\xa9\x8b\x95\x9d" + "\xcd\x15\x16\x3d\xb6\x7e\xff\xf3" + "\xb0\x20\xae\xf5\xce\x0d\x28\xa2" +
- "\xdc\xf8\x94\x37\xa4\x44\x63\x26" + "\x36\x5c\x3c\x48\x3a\x92\xca\xdc" + "\xa0\x10\x9d\x3f\xbf\x6b\x6b\x2d" + "\xf3\xbd\xd9\x81\xca\xc5\x20\xb3" + "\x95\x0a\xb5\x47\xff\x28\x0e\x62" + "\x71\x33\xf0\xce\x01\x3b\x3e\x93" + "\x53\x01\x10\x99\x85\xbf\x81\xf0" + "\xd6\xc8\xa8\xc3\xa0\xe9\x3b\x18" +
- "\x66\xa5\xdc\x41\xc3\x85\xc1\xb6" + "\xa3\x2a\x62\xd8\xda\xfe\xe7\x7d" + "\xfb\x6d\x1b\x90\x92\x4d\xe8\x99" + "\x88\xd2\x4a\x7c\x0e\x2b\xa0\x30" + "\x36\xcf\xd3\x2f\xaa\x1d\xc8\xc7" + "\x9f\xe5\x89\xdf\x47\x95\x31\xd1" + "\x33\x67\x49\xcd\x84\x81\xbe\xb2" + "\x2b\x41\xd3\x93\xeb\x49\xf4\xd5" +
- "\x6b\x11\x85\xe0\xab\x0f\x47\x25" + "\x10\x53\x28\x87\x75\x33\xa4\x04" + "\x2f\xd5\xbf\xe2\x7e\x18\x39\x4e" + "\x74\xbc\x9e\x7d\x44\x6b\x16\x36" + "\x2c\x32\x4b\xfd\x3c\x43\xad\x92" + "\x51\xab\x79\xba\x17\xa8\x6a\x72" + "\xeb\x15\xdb\xc1\xd8\xac\x6e\xf9" + "\x63\xbe\x76\x04\x91\x1e\xf7\xfa" +
- "\x16\x65\x7e\xc9\xda\x9b\x4e\xd7" + "\x9e\xf4\x30\xc2\x60\x93\x77\x88" + "\x49\xea\x74\x1e\xe3\x1d\xec\xa6" + "\xa2\x45\xb6\x3f\xe5\xce\x1d\x58" + "\x14\x3f\x48\x8f\x91\x23\xef\xba" + "\x3b\xd1\x37\xd1\xfc\xdd\x2d\x6d" + "\x42\x3a\x74\xd2\x0e\xe5\xcd\x54" + "\x67\x7e\xd9\xe4\xc5\x4f\xa3\x89" +
- "\x68\xe1\xde\x49\xe9\xd2\xcf\x72" + "\x39\xf2\x2a\x3e\x23\x52\xe0\x1a" + "\x6a\x06\x94\x1d\xbe\x75\x9e\x00" + "\x13\xf4\xab\x38\xc7\x31\xca\x6c" + "\x08\x99\xc4\x9b\x1d\xd6\x0b\xb5" + "\x1e\xbc\xe2\xf5\x8c\x4a\x9b\x4a" + "\xac\x83\x6f\x94\xf7\xc5\x6c\xeb" + "\x28\xab\xff\xeb\xfc\x93\xda\x27" +
- "\x4c\xf6\xd8\x4c\x64\xec\x92\xc4" + "\x51\x7b\x9d\x27\x90\xd7\xa2\x58" + "\x56\x52\xc7\x1f\xc5\x1f\xed\x0c" + "\x17\x30\x43\x8f\xed\x8a\x65\x3e" + "\xeb\x59\xda\x05\x2e\x94\x61\x0b" + "\x22\x37\xdc\x0d\xa3\x60\x3d\xba" + "\x87\x7f\x2e\x74\xd1\x1c\x31\x7c" + "\x6e\x1b\xb0\xf6\xee\xff\x73\x64" +
- "\x51\x7c\x25\x76\xef\x19\xe5\x3c" + "\xe7\x77\xd4\x18\xd3\x18\x58\x6f" + "\xc0\xed\x63\x79\x03\x2e\x02\xab" + "\xf3\xf5\xd1\x8b\x89\x3a\x40\xf0" + "\xca\x33\x60\x49\xa0\x8d\x3b\xe4" + "\x72\xdd\xcf\xa1\x0e\xe1\x94\x09" + "\xe2\xc0\x73\xba\x20\x6d\xec\xb1" + "\xd1\xfa\xbc\xb6\xec\xc9\x29\x03" +
- "\x9d\xbd\x84\x2c\xa1\x42\xff\xf1" + "\x4a\x67\x0c\x39\xc4\x3e\x1f\x75" + "\xca\xe0\xe5\x01\xf7\x36\xbb\x27" + "\x92\x66\xaf\x5c\x51\xff\xdf\x65" + "\x3f\xbd\x7b\xcd\xc4\x79\xf5\x5d" + "\x05\x12\x59\x85\x97\xb2\x8f\xef" + "\x32\xc7\x7a\xe4\x03\x72\xed\x1d" + "\x1a\x33\x1c\xcd\x5c\xc4\x3d\xa9" +
- "\xd4\xd2\x18\x33\x8e\x33\xec\xbd" + "\x63\xe9\x8d\xbe\xbb\xd7\x3d\x73" + "\xbd\x7e\xc4\xa2\xba\xc3\xbc\x61" + "\xde\xcb\xef\x35\x19\xad\x21\xa8" + "\x5c\xdd\x4c\x02\x8c\x66\xac\x91" + "\x49\xfa\xcd\xc1\xe4\x58\xa5\x7b" + "\xda\xb4\x8f\x90\xe0\x4c\x1d\x49" + "\xe8\xbd\x85\xf6\xf9\x69\xa8\x7b" +
- "\x78\x1c\xf4\x81\xcb\x0b\x2a\x7b" + "\xe1\x40\xd2\x1f\x85\x2c\x52\x5c" + "\xf6\xe3\x5c\xdf\x68\x2e\x51\xce" + "\x13\xee\xd5\xb6\x52\xb9\xd4\xa7" + "\xaf\x7e\xad\x31\x8b\x0a\xdc\x8c" + "\x20\x5e\x91\x1b\x75\x86\x5e\x16" + "\xf4\x77\x64\x5d\x9b\x26\x8c\x8e" + "\x91\x1b\x42\x44\xde\x5a\x8d\xd2" +
- "\xba\x64\xf4\x79\xc2\x5e\x1b\xed" + "\x26\x2e\xd7\x47\x2c\xe4\x65\x2d" + "\x26\xf9\x67\x9e\x74\xe5\x98\x81" + "\x44\x7e\x74\x34\x38\x67\x06\x41" + "\x47\x54\x7e\xe3\xc1\xac\x37\x46" + "\x22\x58\xe1\xf3\xec\xc9\xcb\x02" + "\x3c\xa8\x5a\x80\x8e\xe9\xa8\x58" + "\x00\xe8\x95\x55\x6e\xcd\xfa\x73" +
- "\x18\x23\xa9\x32\xb3\xfd\x7c\x19" + "\xb6\x87\xac\x25\x41\xa8\xbe\x9e" + "\x7a\x0c\x51\xa3\xf7\x05\xd8\x4c" + "\x8e\x42\x6e\xe0\x9a\x99\xdf\x24" + "\x9c\x45\x71\x4d\xdc\xd5\x4d\xd5" + "\x3c\xa0\xb8\x20\x4f\x32\x84\x14" + "\x27\xb9\x74\x31\xd9\xf2\x24\x79" + "\x50\xde\x3a\xf9\xbf\xac\xb8\x42" +
- "\x07\x05\x33\x38\x03\xf8\x8f\x46" + "\x3e\xa5\x37\x40\xdf\x4d\xf3\x06" + "\xa4\x93\x69\x8d\x40\x1a\xcd\x70" + "\x22\xc0\xe5\x43\x97\x15\x5a\xf8" + "\x7d\xa6\x25\xc1\xc2\xc9\x6f\x39" + "\xcb\xbf\x64\x10\xbf\xbe\xb7\x03" + "\xcb\x6d\x80\xa9\x92\x45\x44\x7c" + "\x54\xcd\x87\x44\x4b\x61\x02\x1b" +
- "\x42\xc5\x2a\x69\x4f\x60\x03\x83" + "\xd3\x91\x7b\x22\xe1\xff\x79\xf0" + "\xbd\xf9\xaa\x15\x63\x3e\xf6\x19" + "\xfb\x44\xf3\xf1\x65\xe5\x9e\xf9" + "\x99\x91\x21\xd6\x1f\x66\x1d\x8a" + "\x1c\xe4\x8c\xd4\xc6\x3b\x88\x8c" + "\x04\xd9\x74\x3c\x8f\x11\x65\x10" + "\x1b\x8b\xaf\x0f\xee\x89\x38\x71" +
- "\xb6\x1b\xe2\x0d\xf7\x60\x7b\xb4" + "\xca\x36\xd8\xdc\x4f\xae\xac\x64" + "\x63\xce\x44\xc7\x6d\xea\x75\x33" + "\x5b\x95\x47\xb0\x5f\x26\x64\xb7" + "\xc3\xc2\x41\x98\x4c\x5d\x8a\xc6" + "\x60\x4f\x45\xcf\xd7\x8f\xe9\x60" + "\x0c\xea\x6a\x75\xe2\xfb\x01\xc7" + "\x79\x1c\xb2\xaa\x5e\x88\xc8\x09" +
- "\xcf\xbd\xd1\x91\xef\x59\x13\xca" + "\x86\x25\x59\xf3\x57\x21\x08\x6a" + "\x1c\x95\x51\x39\x94\xa5\xae\xd9" + "\x06\xe7\xb7\xa2\x24\xef\xab\x57" + "\xa2\xb1\x2e\x2e\x1e\x72\xa5\x3f" + "\x98\xce\x6a\x51\xac\xee\x68\x3c" + "\xdf\x82\x87\xc2\x47\x9d\xa7\xff" + "\x7b\x57\x16\x4e\x63\x9f\xd6\xbd" +
- "\x6c\xd4\xd2\x69\x08\x81\xbb\x45" + "\x5a\x36\xc8\x68\x39\x8b\x7c\xe4" + "\xbd\x51\x75\x26\x63\x76\xb8\xf3" + "\x7a\x54\x67\x5b\x8f\x76\x90\x15" + "\xff\xd3\x2e\xfb\xb2\x1d\x1c\x37" + "\x40\x94\xa5\x17\x19\x69\x16\xe3" + "\x14\x2c\x24\xdf\x78\xd1\xc0\x03" + "\xc1\x2a\x86\xed\xce\x3f\xc9\x40" +
- "\xaf\x84\xbb\xc5\x60\x79\x2b\x40" + "\x39\xa6\xc8\xbc\xdc\xc7\x29\xcf" + "\x6d\x7c\x8f\x47\xff\x9d\xf1\xfa" + "\x22\xbd\x37\x33\xe4\x6a\x30\x71" + "\x7a\x9b\x59\xbf\x05\x55\x7c\xef" + "\xa8\x91\x46\x9c\x9e\x15\x9e\xe0" + "\x19\xb1\xce\x74\x18\xe8\x03\xd4" + "\x8d\xa9\x11\x52\x02\xe7\x25\x53" +
- "\xd6\x82\xc9\x2b\x69\xda\x86\x12" + "\xe3\xe7\xda\x7b\xf2\x80\x6d\x5f" + "\xfb\x64\xf0\xa6\x47\x56\x9c\x3d" + "\x40\x15\x4c\xd7\xa1\xe6\xc8\xfd" + "\x5a\x13\x8b\xd6\xc6\x48\xda\x97" + "\xff\xbf\x6d\xd6\x79\x79\x09\xc2" + "\x1d\x53\x20\xea\xb9\xad\x96\x02" + "\xf0\xc8\xb2\x4a\x0d\x73\x33\xa3" +
- "\x33\x19\x25\x7a\x2b\x12\x97\xaf" + "\x45\x33\x23\xc1\x9c\x34\xc7\x36" + "\xb0\x00\xf4\x73\x88\xde\x87\x56" + "\xaf\x95\x75\x70\xa3\x47\x28\x92" + "\xc1\xde\xf6\x7f\x58\x18\xe0\xb7" + "\xcb\x91\xc1\x2f\xce\x3e\x28\x6e" + "\x56\xdc\x20\x1c\x8b\xef\xc2\x78" + "\xdc\xd2\x2e\x45\x5e\x53\xe6\x51" +
- "\xed\x7f\x84\x29\x54\x56\xb3\x0e" + "\xd0\x3d\x67\x0a\x86\x42\xc1\xfd" + "\x0b\xdd\x62\x8b\x27\x36\x1b\x72" + "\x71\x57\x1a\x71\x3e\x29\x5a\x10" + "\x27\x19\x76\x7f\xce\x1c\x00\xdf" + "\x7d\x4c\xd0\x11\xb0\x81\xb6\xf7" + "\x96\x19\xac\xa3\x92\xf7\xdf\x16" + "\x30\xae\xc4\x0f\x0b\x12\x0c\x58" +
- "\xc7\xb8\x0e\x96\x97\xf6\x35\xc0" + "\xd3\x04\xde\xe2\x2c\x9f\x59\xf1" + "\x28\x92\xad\xd2\xf8\x50\x24\x89" + "\xab\xc1\x29\xb8\x9b\x12\x48\x7d" + "\xc9\xaf\x50\x3a\xe1\x85\xd7\x24" + "\xe0\x6e\xa9\x63\x27\xba\x45\x27" + "\x7b\x6d\xfb\x3b\x01\x34\x65\x95" + "\x42\x2a\xad\x1b\x67\x02\x62\x53" +
- "\xbc\xd0\xe8\x7e\x4f\x3d\xea\x31" + "\xdc\xc3\x42\x0f\x2a\xf2\x32\x38" + "\xf4\xa2\x87\x1a\x1a\x06\x61\xc6" + "\x6b\x57\x45\x4b\xf6\xc9\x78\x09" + "\xd2\x5f\xfb\x6d\x3c\xac\xab\xb7" + "\x90\x1b\xe0\xb7\x00\x6a\xf3\x27" + "\x36\x9e\x42\xe9\xcd\x33\xf7\x68" + "\xcb\xe8\xbf\xdc\x81\x46\x3a\x95" +
- "\xe3\xc2\x03\x41\x24\xff\x96\xe3" + "\xe7\xad\x06\x1b\x1c\x56\x33\x41" + "\x34\xa7\xd0\x65\xac\xb9\x20\xe1" + "\xd9\x19\x79\x92\x07\x6f\x6f\x57" + "\x5a\x95\x1f\x69\x46\xc8\xcf\xa0" + "\x65\x9d\x44\xa6\xc0\x2b\x2e\x3d" + "\x9b\xed\x67\x97\xb8\x41\xa5\x7b" + "\xc7\x15\x92\xdc\x04\x1b\xb2\xd1" +
- "\xaf\x1e\xfe\x67\x10\xc4\xb7\xbf" + "\x85\xa7\x29\x69\x6a\x3c\x07\xa2" + "\x79\xdb\x5f\xa7\xf4\x36\x25\x6f" + "\x69\xca\x9b\x80\x6d\xd2\x9a\x85" + "\x7b\x7e\x19\x3b\x69\xc0\xf2\x06" + "\x73\xa5\xc0\x8e\xf4\xd9\x6a\x65" + "\x62\x02\x4d\x9a\x1f\x90\xc7\xe7" + "\x2b\x60\x38\xb9\x43\x94\xc2\xbe" +
- "\xa4\x73\x00\x0f\xfc\x97\x03\xd0" + "\x5f\x67\x8d\x6f\xa4\x8f\x66\x5b" + "\x8c\x10\x22\x15\xc9\x4a\x37\x14" + "\x2e\xe4\x83\x02\xd1\xa7\xef\x92" + "\x4a\x02\x6d\x0b\xf9\x6d\x3e\x67" + "\x26\x1f\x58\x57\xd4\x14\xf9\x05" + "\x12\x8c\xdf\x67\x62\x51\xc8\xf5" + "\x62\x24\x6c\xe0\xb4\xf1\x97\x11" +
- "\xc1\x90\x9c\xdd\xb3\x1c\x2d\x6e" + "\x9e\x57\x90\x79\x5a\x2d\xf8\x28" + "\x95\x61\x22\x06\xcd\x89\xe1\x90" + "\x74\xdc\xb0\x19\xdf\x39\x29\xbd" + "\x77\x71\x91\xc0\x05\x85\xb1\x18" + "\xc4\xd9\x17\x31\x0d\x47\xd5\xee" + "\xa0\x3c\x89\x6c\xeb\x92\xef\x39" + "\x40\x19\xa4\x44\x82\xef\x33\x45" +
- "\x95\x75\x2d\x2d\x3c\x85\xac\x62" + "\x54\xad\x8f\x59\xb7\xda\x83\x48" + "\xa4\xd7\x32\x6d\xd1\xf5\xf7\xbb" + "\x81\xd8\x1d\xfd\x2d\x4f\xfb\x95" + "\x80\xc5\x5d\x54\xf2\xae\x39\xe2" + "\xb9\x39\x1e\x4d\x0a\xa7\x09\x46" + "\xb2\xbb\x8e\x33\x3e\xb3\xd3\x61" + "\x61\x54\xbd\x15\xc2\x1d\x05\x06" +
- "\xda\x3d\x94\x34\xec\x9d\xee\xca" + "\x82\x67\x4b\x8b\x8e\xe9\x50\x8e" + "\x1f\x3a\xea\x91\xa5\x8e\x35\x24" + "\x94\xc1\xe1\xa9\x27\xc8\xc4\x71" + "\x94\x7a\xbb\x09\x5d\xaa\x8b\xa3" + "\x9c\x8f\xb5\x57\xc0\xb4\x4a\xfb" + "\x19\xee\xe0\x24\x5e\x06\x01\x4a" + "\xbf\x77\xb8\x07\x51\x80\xcf\xb9" +
- "\xbe\xb3\xa1\x81\x8f\x3f\x2b\x97" + "\xa0\x64\x27\xce\x45\xe1\x3c\x4f" + "\xf7\xf5\xc4\x28\xcc\xf1\xd0\xe2" + "\x5b\x98\xf3\xc7\x0d\x0c\xee\xde" + "\xc3\x25\x9e\xd3\xc0\xad\xf4\x7d" + "\x80\xa0\x67\xc4\x20\x98\x61\x40" + "\x58\x5a\xcf\x61\x93\xbc\x0e\x44" + "\x00\xd6\x2a\x42\xa6\x29\x77\x52" +
-
- "\x49\xf4\x73\x3f\x75\x6a\xb2\xef" + "\x79\xfc\x44\x8d\xf8\x94\x1c\x1d" + "\x4d\xdc\xc0\x3b\xc5\xfb\xf0\x49" + "\xd0\xa0\x98\x36\x0b\xea\x47\xb7" + "\x1e\x29\x8d\x22\xfe\xc3\x18\x52" + "\xd6\x29\xc1\x43\xb5\x04\xb8\x35" + "\x16\xc5\xac\xd1\xb8\x59\xc8\xfa" + "\x68\xe6\xd6\x95\x7d\x69\x10\x6c" +
- "\xdb\x2f\x45\xcb\x1a\x25\x30\x6e" + "\x50\x06\xf3\x50\x65\x69\xee\x31" + "\xd9\x48\x35\x93\x08\xe5\xb3\xb0" + "\x5b\xef\xb0\xf4\x4f\x9a\x94\xb8" + "\xbd\xf3\x88\x3c\x26\x83\x8b\x20" + "\x89\x99\x1d\xdb\x30\x7c\x14\xab" + "\x03\xdf\xd4\x44\xfd\x15\x65\xed" + "\xc5\xb0\x2e\xe7\x75\x2f\xa1\x17" +
- "\x89\xfe\xe3\x28\xe0\xbb\x6c\x7a" + "\xeb\xc0\xaa\xc5\xe4\xfe\xe1\xe7" + "\x40\x51\x7e\x69\xa5\xed\x47\x7f" + "\x1f\x92\x54\xb4\x37\x01\x45\x4f" + "\x85\x81\xcd\x95\x84\x5f\x62\xdb" + "\x83\xe5\xb2\xcd\xa1\x0b\xbe\x74" + "\xe4\x6d\x5e\xdd\x7c\xfd\xe4\xae" + "\x39\x17\x10\xe8\x7d\x43\x51\x42" +
- "\x90\xad\xfd\x81\x78\x4f\x91\x25" + "\xab\xf6\x2c\x0d\x56\x8f\x63\xcf" + "\xe5\x4d\x05\xcc\x3f\xc0\x0b\xb9" + "\x50\x63\xb0\x18\xa7\x11\x28\x93" + "\xff\x11\xbd\x9b\x30\xb3\x00\x2f" + "\x74\x49\x04\xb4\x6f\x8a\x10\x76" + "\x66\xd2\x51\xa8\xe0\xb9\x1b\x80" + "\xc1\x90\x89\xbf\xbe\x99\xd0\x0d" +
- "\x61\x70\x7d\x51\x0a\xb2\x5e\x11" + "\x83\xf6\x2d\x6c\x33\x34\xfe\x77" + "\x67\xfc\xc6\xcd\xc7\xdd\x70\x68" + "\x83\xde\x87\x0b\x88\x05\x61\xb1" + "\xbe\xdd\xc4\xd9\xca\x84\x35\x34" + "\xe2\x4b\x75\x3d\x1c\x4f\x16\xb3" + "\x94\xc8\xe6\xc1\x3a\xed\x31\x07" + "\x4c\x90\x6b\x4f\xec\x7d\x32\x26" +
- "\x55\x38\x1c\xc6\xae\x7b\x26\x29" + "\x3b\xfd\xc1\x58\x9d\x42\xff\xeb" + "\xb8\x93\x0b\x8c\xc0\x86\xd8\x22" + "\x53\x89\xdb\x2d\xb2\x00\x5e\xca" + "\xb7\xd8\xfe\xc3\x17\x01\x33\xcf" + "\xf6\x01\x9c\x81\xfa\xc6\x9a\xd4" + "\x54\xbd\x0f\x3c\xbd\xa6\xda\x6d" + "\xcf\xa2\x49\x80\x68\x30\x74\x91" +
- "\x5a\x76\x72\x76\x3c\x06\x6a\x0a" + "\xbf\xb9\x47\x05\x64\xce\xa3\x37" + "\x33\xa6\xb1\x98\xc8\x99\xc0\x42" + "\x61\x69\xee\x05\x0d\x80\xab\xb5" + "\xd6\xac\xa5\x11\x59\x3f\x96\xf1" + "\x63\x10\x20\x46\x57\x61\xee\xba" + "\x0a\x21\x96\xa5\x49\xa6\xd9\x36" + "\x8c\x13\xa7\x1b\x63\x43\xd0\xae" +
- "\x46\xcd\xd6\x58\x8a\xdd\xc6\x14" + "\xd2\x34\x66\x8e\xb5\x33\xb6\x9c" + "\x28\xc3\x1b\xf8\x47\x50\x30\xc1" + "\xe5\x77\xa1\x26\xe2\xe0\xed\x12" + "\x4f\x6f\x5a\x06\x62\xca\x2c\x33" + "\x7b\x48\xbe\x67\xcd\x7e\xa4\xc3" + "\x1c\xed\x47\x0f\x87\xb1\x1e\x74" + "\x14\x8b\x59\xe7\x58\x6e\xe6\x99" +
- "\x6e\xe7\x1f\xf5\x76\x28\x82\x36" + "\x89\x25\xd6\x11\xcc\x11\x68\x8a" + "\x18\x57\x22\x46\x65\x7e\xfc\xc3" + "\xcd\xdb\x2f\xc8\x9f\x2c\xdf\xb7" + "\x5b\x20\x7b\xdd\x52\x4e\x1d\x3b" + "\x14\xe4\xa2\x47\x78\x94\x95\xb6" + "\x48\x11\xa9\xef\x93\xd7\xe4\x05" + "\x75\x96\x2e\xfd\x46\xd4\x7e\xb4" +
- "\x2f\x23\xf3\xeb\xe2\xd0\x0e\x8f" + "\xdd\x2e\x2a\xc5\x9e\x0f\xf8\xff" + "\xdb\x5f\xb5\x75\x33\xb4\x9a\xad" + "\x11\x0c\x2e\xe4\x20\x78\xca\x73" + "\x46\x1b\x25\xe6\xa0\xe0\xac\x6d" + "\x2d\x93\x0d\x4c\x5c\x6b\xbc\x89" + "\x9a\xa1\x5d\x09\x77\xcd\x38\x34" + "\xfb\xbd\x48\x8d\x39\xa9\x24\x2f" +
- "\x92\xb8\x41\x55\x51\xc4\x5d\x1d" + "\x54\x9e\x9d\xfc\x41\xee\x86\xb1" + "\x0d\x61\xbf\xd5\x5e\x34\x9f\x9d" + "\x9f\xca\xac\xf6\x5d\xa6\x7b\x3e" + "\x86\x94\x36\xa8\x7a\x78\xda\x9d" + "\x53\xba\xb5\x8e\xb7\xda\xf9\x09" + "\xc3\x1b\x48\xd6\x33\x20\xfb\x5a" + "\x04\x21\xa6\xaf\x30\xce\xf4\x76" +
- "\x3d\xc9\x0a\x7b\x77\xa6\xd6\xeb" + "\xd7\xe0\xf5\x78\x0d\x7b\xe3\xa6" + "\x2b\x49\xf5\x76\x96\xc0\x16\x25" + "\x3a\x5f\xc0\x9a\x88\xf8\x4b\x1e" + "\x2b\xba\xf0\x4d\xe0\x2c\xb4\xcd" + "\x1b\x34\x62\x50\xfd\x5c\x5d\x93" + "\x20\xac\xac\x82\x33\x33\x30\x8a" + "\x0e\xb0\x98\x51\xc4\x38\x94\x42" +
- "\x24\x8e\x1f\x5a\x3c\x18\x99\x3f" + "\xf0\x55\xd2\x9d\xfa\x18\xb1\xfd" + "\xa6\x62\x7f\xc2\x90\x8b\xb1\xb9" + "\x91\xc1\x6e\x39\xf7\x32\xf7\xe8" + "\xab\x86\xe7\x0b\x91\x2d\x4a\x52" + "\xf5\xa0\xc5\x0a\xef\xad\x32\x5d" + "\x94\xf6\x25\x97\xd6\xd4\x53\x9b" + "\x89\xba\x10\x05\xc6\x76\x2a\x03" +
- "\x1c\xb1\x58\x57\x59\x5d\x9b\xa4" + "\x40\x4f\x65\xc8\x93\x28\x85\x0b" + "\x47\x94\x37\x52\xf4\xf6\x3e\xb6" + "\x0c\x69\x5e\x10\x29\x7d\x95\xd4" + "\xb0\x59\x65\x64\x63\x43\x48\x7d" + "\x8e\x8a\x78\x49\x3c\x27\xa8\xf4" + "\xa9\x54\xce\x34\xb8\x6c\x40\xee" + "\x9b\xda\x6f\xf8\x0f\x26\x1c\x1e" +
- "\x50\x47\x95\x0e\x74\x79\xbd\x9d" + "\xc6\xd2\xf9\x64\x88\xde\x21\x01" + "\x2e\x23\x85\xd9\x42\x7b\x59\x2e" + "\x77\x17\x45\x53\xc5\xc3\xb6\x55" + "\xfb\xb9\x9c\x51\x47\xe5\x53\xbb" + "\x0d\x60\x28\x84\x9f\x01\x34\xf1" + "\x1a\x79\x81\xe0\x76\x31\x47\x5a" + "\x08\x0c\xfb\x35\x63\x22\x3e\x2f" +
- "\xe0\x73\xe5\x67\xbe\x38\x28\xfb" + "\x4b\xc4\x84\x40\xb9\x1d\x89\x05" + "\xc5\xc2\xc1\x96\x73\x13\x31\x91" + "\x4b\x44\x58\xd9\x3f\xfa\xeb\x6a" + "\xc1\x55\x6e\xe5\xe9\xdc\x9c\xac" + "\xd0\x46\xaa\x2c\xd3\xce\x48\x71" + "\xeb\xe8\x1f\xb6\xef\xc7\x10\x2e" + "\x4d\xcf\x97\xff\xda\x35\xd8\x9f" +
- "\xdd\x99\x1d\x43\x8d\xa1\xed\x9b" + "\xe1\xcc\xd5\xf3\x3d\x0b\x69\xf7" + "\xc9\x6e\x32\xb7\x6d\x65\xfb\x97" + "\x9c\x73\x95\x8c\x44\x71\xb2\xc1" + "\x98\xe2\x21\x9c\x89\xea\xec\x65" + "\x34\x57\x35\x37\x91\x72\xe5\xd0" + "\x3d\xeb\x65\x21\x2b\x7c\xbd\x80" + "\xc0\xf1\xc0\xdc\xe7\x16\x1e\xdf" +
- "\x32\xc8\x07\x0c\xad\x8f\xe5\x97" + "\x9b\x43\xc3\x41\xa4\x50\xee\x73" + "\x20\x0e\x1f\x8e\xa4\x43\x06\x23" + "\xa3\xc6\xeb\xce\x8b\x7f\x3c\x53" + "\xb5\xe1\x63\x71\xb3\x47\xa6\x4d" + "\xfa\x26\x0b\x41\x4c\x0d\x65\x1a" + "\xfb\xfd\xe8\xdd\x64\x3a\xa5\x0d" + "\x73\x0c\xd8\x88\xdf\x86\xe7\x0c" +
- "\xca\x0a\x8f\x23\x27\x92\xcf\x19" + "\xfd\x4c\xac\xab\xd4\xad\x86\x63" + "\x7f\xde\x5c\x5e\xa0\xc4\xb6\x17" + "\x07\x56\xaa\xc9\x58\x57\x2b\x17" + "\x8c\xe7\x01\x5f\xc5\x65\xa2\x0f" + "\x1e\x4d\x12\xdc\xfb\xfd\xb2\x1f" + "\xf8\x23\xf2\x9b\x3c\x8d\x23\xcf" + "\x6b\xbb\x94\x03\x8d\x2c\x5c\x3c" +
- "\x16\x06\x77\xc1\x56\x6f\x62\x6c" + "\x2d\x9a\xda\x09\x9e\x90\x51\x53" + "\x45\x0e\x73\xa3\x25\x68\x8e\xe5" + "\x79\x0a\xef\x03\xc0\x8b\x8c\x9d" + "\xfd\xec\x6b\x05\xb6\x78\x3f\x54" + "\x6d\xb3\x90\xa0\x53\x32\xf1\x33" + "\xf9\x32\x44\x79\x97\x49\xad\x82" + "\x02\xf5\x21\x47\x3c\x49\x86\x13" +
- "\x14\xd7\x9e\xd4\xf1\x13\xc4\xdc" + "\xd8\xb4\xc2\x6a\x27\xd6\xd3\x18" + "\xf8\xbc\x47\x53\x45\x7a\x15\x0f" + "\x44\xc9\x94\x26\x12\xf4\x13\x4a" + "\xdd\x00\x77\x39\x7c\xbf\xab\xe3" + "\x39\xef\x4e\x6c\x91\x8a\xa8\x72" + "\x9c\x47\x06\x46\xdb\xf8\x49\xb1" + "\xb3\xd3\xc2\x54\xab\xb1\x44\xff" +
- "\x09\x3d\x83\x4b\x36\xac\x75\x88" + "\x9b\x5c\xed\xf0\x12\x77\xc9\xca" + "\x0d\x52\x81\x02\x8f\x5d\xf5\x7a" + "\x37\x62\x93\x46\x3b\x47\xf7\x06" + "\xd6\x84\x6f\xfe\x51\xca\x5b\x8a" + "\xa7\x4f\x27\x84\x4b\x6f\x4b\x76" + "\x1d\xc0\x64\xb9\xdc\x91\x30\xfa" + "\x46\xb8\x3a\x0a\xf6\x26\x1f\x6d" +
- "\xf0\xcf\xc0\x8a\x5f\xf5\x0b\x0d" + "\x54\xeb\x50\xc1\x82\x88\x59\xd9" + "\xd0\x93\xc2\x51\x2c\xa7\xa4\x22" + "\x8a\x19\x3c\x64\xf6\x57\x6c\xf8" + "\x10\x57\x39\x20\xb0\x91\xab\x97" + "\xc0\xdb\x70\x19\x6c\x71\xe1\x9a" + "\xf8\x3d\xe5\xcc\xa2\x2b\x7a\x5b" + "\x4c\xd6\x85\xfc\x99\x9a\x79\xb2" +
- "\x2a\xa8\xbe\x5a\xfa\xee\x94\x37" + "\xd4\x62\xfe\x93\xb9\x11\xc6\x8d" + "\x06\xf6\x1e\x28\x37\xaf\xf1\x69" + "\x69\x9e\x83\x39\xc8\x46\xf5\x6a" + "\x23\xec\x77\xc9\xc7\x78\x55\x62" + "\x76\x05\x5c\xbd\x4c\x29\xde\xa8" + "\xc0\xa4\xd1\x7c\x0f\xaf\xdd\xe2" + "\xd4\xf4\x95\x4f\x70\xfc\x43\x82" +
- "\x12\x18\xe7\x50\xda\xab\xc5\x94" + "\x7c\x6a\xbb\x03\x35\x74\x94\x02" + "\x14\xbf\x8f\x79\xab\x53\xa1\x02" + "\x4e\x28\x2f\x7a\xc8\x26\xef\xf8" + "\xdc\x9e\xf9\x05\x5d\x92\x3c\x86" + "\xdd\x35\x9b\x40\xe6\x81\x6d\x97" + "\x70\x91\xe9\xdc\x99\x5a\x3a\xef" + "\xe6\x1d\x13\x53\xec\x80\xbc\xaa" +
- "\x35\xb3\x40\xc9\x64\x7c\x41\x19" + "\xe9\x97\x6e\xaf\xf5\x4e\x45\x51" + "\x9c\x30\x16\xed\xac\x9b\x3c\x76" + "\x04\x48\x46\x81\x4d\x17\x6d\xe2" + "\x97\x74\x19\x35\x86\x42\x5a\xa0" + "\x09\xb1\xed\xad\x71\xfa\x10\xa4" + "\x6e\xf7\x95\xda\xb7\xca\x19\x72" + "\x1f\xd1\x88\xbe\xe7\x23\xc3\x74" +
- "\x3c\x10\xdb\xb2\xd6\x91\xbb\xe1" + "\xe3\xc2\xe2\x92\xb1\x3d\x59\xbe" + "\xc1\x25\x5e\xb4\xca\x49\xf9\x53" + "\x23\x2f\x6e\x0a\x16\xe6\x39\x6a" + "\x0a\xd7\x57\x13\x6e\xe2\x13\x02" + "\x9c\x3e\x62\x8e\x1a\x1c\x74\x73" + "\xb2\x99\x93\x8d\xba\xa9\xdf\x54" + "\x32\x8c\x59\x0c\x40\x0c\x31\x86" +
- "\x3a\x73\x08\xb0\x00\xf4\x66\xe5" + "\x57\x1f\x2e\x51\x7d\x69\xa0\xcb" + "\xd0\x9c\x50\x40\xb2\xc2\x37\x95" + "\x8c\x3d\x35\x57\x69\x9c\x98\x5f" + "\x2f\x2b\x3c\x4c\x72\xc9\xbe\x7d" + "\xa8\x1f\x03\xff\xa8\x2f\xe0\x90" + "\x1f\xd1\xd5\xcf\x53\x5c\xd1\xf4" + "\xfc\x4d\x31\x48\xae\x4f\x40\xb3" +
- "\xef\x5f\xca\xb4\xa3\xbb\xf0\xb6" + "\x08\x90\xd1\x0f\xe2\xfc\x19\x49" + "\xdc\x2a\xd1\x1b\x8d\xd1\xb4\x18" + "\x9c\x8e\x1c\xc8\x88\x3a\x2f\xb2" + "\x49\x29\x7c\xcc\x2c\xb1\xf5\x86" + "\x7f\x98\xde\x05\xd8\x1a\xf6\xa2" + "\x70\x79\x72\xed\x72\x21\x74\x69" + "\xc7\x4e\x43\xd7\x8e\x2c\x9f\x3e" +
- "\xb4\x52\x2c\x21\xf8\x0e\x49\xd1" + "\x7b\x5a\xb7\x00\xea\xfd\x2f\x5b" + "\xa1\x8b\x95\xbf\x3e\xb2\xc7\xf2" + "\xaa\xba\x6c\x69\x39\x20\xb4\x43" + "\x96\x34\xbe\x02\x94\xde\x5b\x1f" + "\xc4\xa5\xef\x39\x6b\x9d\xbe\x3a" + "\x82\x7e\x07\x47\xde\x7f\x20\x2a" + "\x28\x29\x86\x65\xfc\x74\xc3\x3b" +
- "\xc4\x04\x06\x54\x1d\x0e\xd4\x35" + "\xed\x6f\x48\x3a\x3a\xb3\xa4\x16" + "\xa1\xa4\x43\xee\x6c\x49\x70\x91" + "\xaf\x8a\x94\xad\xe1\xdb\x4a\x17" + "\x99\xdf\x51\x54\x0a\xa3\x47\x8a" + "\xa1\x91\x17\x9e\xd1\xbd\xca\x7c" + "\x2a\xf1\xfc\xec\x3a\xb5\x12\x71" + "\xd2\xc6\xb5\xfa\x95\xb3\x1e\x56" +
- "\x87\x93\x1e\x08\x09\xa1\x6d\xa3" + "\x28\x58\x93\x8c\xd7\x80\x97\xfb" + "\x15\xb0\x40\xe5\x32\x03\x94\xd5" + "\xfa\x66\xf4\xe0\x1b\xb5\xd7\xc9" + "\x71\xf6\xd9\xd6\x41\xcd\xad\xfa" + "\x17\xac\xa2\xb1\x28\x1e\x6c\xba" + "\x5f\x1e\x20\xed\x33\x78\x6a\x06" + "\x2b\x46\x0f\xf9\x19\x97\xd9\x19" +
-
- "\x61\x5f\x0b\x06\x62\xf4\x31\xf4" + "\xc2\x57\xd0\x7b\xb4\x46\x6f\xa5" + "\x65\xbf\xe1\x47\x6c\xca\x8d\x34" + "\xff\xf1\xbc\x41\x3e\x78\x38\x9a" + "\x18\x07\x71\xda\xa9\x33\x5d\x7a" + "\xf6\xea\x0a\x2e\x87\x99\x77\x5a" + "\x87\xd1\x29\x2d\x4d\x31\x87\xca" + "\x33\xd7\x87\xc6\x3e\xdc\x0e\xfa" +
- "\xc7\x8a\x19\xcb\x49\x48\x89\x1c" + "\x65\x46\x26\x0f\x3d\xa9\x84\xa8" + "\x78\x06\x20\x9b\xef\x64\xa9\x2d" + "\xe6\x34\x98\x00\x87\x1b\x35\x3c" + "\x4b\xb4\xc4\xe2\x9f\xef\xb2\xaf" + "\x0c\x79\x26\x33\x47\x6c\x0f\x58" + "\x4a\x26\x02\x0b\x21\x05\x48\xb8" + "\xe2\x94\xa1\x42\xe2\xf9\xa6\x8b" +
- "\x0e\x3c\xb0\x5e\xb6\x6a\x9b\x49" + "\xde\x3f\xbc\x72\x54\x79\x9b\xf1" + "\xd2\x80\x3a\x6e\x9c\x5b\x6b\xa8" + "\x9f\x81\x42\x6d\x08\x75\x37\xe4" + "\xa3\xe8\x3e\xbb\x50\x36\x66\xc1" + "\x5f\x07\x32\xb1\xfc\x14\xeb\x75" + "\xf6\x34\xd8\x7a\x06\xc9\xcc\xa8" + "\xfd\x2f\xe9\xe6\x74\x24\x6a\xea" +
- "\xf1\x95\xc0\xd3\xab\x34\xd9\x39" + "\x71\x6d\xb7\xe4\xbe\x61\xb2\x04" + "\x84\x69\x3e\xe7\x70\x69\x2e\x1d" + "\x11\xcb\x5f\x5e\x3b\xb2\x9f\x87" + "\x90\x54\xd7\xdf\x72\x6c\x50\x11" + "\xc1\xf1\xbc\x61\x85\xd0\x97\x3a" + "\x07\x70\x5e\xbf\x82\x1d\x20\x43" + "\xa7\x32\x82\x79\x2f\xc5\x0a\x7f" +
- "\x36\x91\x04\x4b\xee\x20\x4d\xcb" + "\x13\x46\x6a\x35\x12\xbf\x63\x8b" + "\x28\x81\xe0\x70\xf6\xae\x21\x12" + "\x16\x6b\xcb\x4a\x51\x8c\x2d\xe6" + "\x96\x78\x9e\x37\x67\x4a\xf6\x71" + "\xa5\x7f\xfd\xca\xa2\x37\x52\xb2" + "\x6a\xba\x41\x38\x98\xbd\x77\xf0" + "\x7e\x6e\xd1\x3c\x44\x02\xac\xc4" +
- "\x82\x76\x9d\x31\xfb\x01\x51\xb2" + "\xee\x2f\x98\x0a\x29\x31\x29\xb0" + "\x44\xb3\x61\x02\xb9\xc9\xc1\x51" + "\xfa\x71\xd3\xbf\x5b\x8c\x00\x0e" + "\x33\xca\x78\x02\x1c\xdd\x66\xd8" + "\xb1\x53\xaa\xe5\xa6\x76\x6f\x66" + "\xcf\xa2\x13\x60\x79\xb7\xcf\xe5" + "\x36\x18\x52\xa3\xad\x1a\x3a\x1d" +
- "\x9c\x5f\xf7\x50\xff\x04\x56\x3c" + "\x22\x2b\x75\x7e\xf3\xdd\x8e\x1d" + "\x18\x11\x9a\x3c\xdd\x74\xf0\x0e" + "\x7b\x6d\xb8\xcc\x72\xc1\xff\xd0" + "\xf2\x90\x7d\x03\xe3\xec\xd1\xab" + "\x6c\x85\x55\x60\xd6\x07\xf3\xe3" + "\xaf\x6d\x4c\x7e\x28\x93\x2f\x42" + "\xa0\x79\x48\x33\x66\xac\x2a\x90" +
- "\xec\x93\x71\x56\x1a\x13\xb4\x76" + "\x0b\xe7\xf6\xe5\x5a\x30\x3c\xaf" + "\xdd\xeb\x1e\x03\x39\xbd\x87\x95" + "\x31\xe8\xbb\x71\xf8\xde\x09\x57" + "\x69\xb6\xb2\x0e\x83\x99\x05\x57" + "\x29\x70\x5b\x87\x1b\xce\x80\x4d" + "\x16\xac\x64\x03\xa8\x7d\x8a\x83" + "\xab\x83\x1c\xbe\x23\x1d\x43\x2f" +
- "\x1e\xc7\x40\xb9\x4c\x87\x52\x8e" + "\x3a\x4b\x5f\xdb\xa9\x35\x19\x21" + "\xc3\x1d\x1b\x30\x92\x04\x35\x94" + "\x20\x86\x95\x29\x6d\x64\xd2\x33" + "\x04\x14\x91\xef\x4b\xd6\xb0\x16" + "\xf4\x5e\x3c\x9a\xea\x25\x1f\x9d" + "\x78\x2c\x35\x4a\xeb\x00\xf2\x20" + "\x28\xb4\xd0\x4b\x2c\x9f\x92\x43" +
- "\x4e\x5d\x23\x38\x66\x27\x81\xe7" + "\x98\x32\x6e\x49\x67\xbd\x62\x1c" + "\xc8\x5b\x17\x3f\x0c\x66\x78\x83" + "\x4d\xdd\xaf\x17\x89\xe1\x04\x4d" + "\x8c\x06\xa8\x85\x01\x16\xa8\x32" + "\x85\x9a\xb2\x92\xe1\xe4\x58\xdb" + "\x3b\x8a\x0d\xc7\x86\x5b\xa6\xe8" + "\x3b\x40\xa0\x98\x4e\x6f\x0e\x5f" +
- "\x9e\x9f\x2c\xe8\xe6\x36\x46\xd4" + "\x43\x10\x3a\xc3\x7c\xb8\x1d\x71" + "\x05\xec\x8a\xaa\x63\x12\x43\x6f" + "\xaa\xa4\x44\x27\x0d\x12\xff\x43" + "\x9b\x77\x77\xae\x2f\x89\xbd\xd3" + "\x82\x9f\xdc\x8c\xc9\x0c\xfe\xf0" + "\xbc\xb1\xc5\xf1\xe6\x7f\x5f\xca" + "\x72\x9a\x92\x44\x82\xa6\x63\xcc" +
- "\xe0\x4a\x89\x3f\xb7\x92\x24\x2c" + "\xce\x18\x5f\xb7\xe5\xf3\x9d\xf5" + "\xd0\xca\x53\x8f\xd2\x40\xb7\x7c" + "\x94\x12\xf0\xc4\xfb\x85\xb5\x3e" + "\x17\xf7\xc7\x32\x86\x0c\xda\x17" + "\x4c\x3f\x94\xaf\x5b\x79\x8c\xeb" + "\xd2\x51\x7c\xf6\xb5\x3f\xe2\x4e" + "\x49\x99\x88\x68\x75\x75\x18\xef" +
- "\x6f\xff\x8d\xb3\x3e\xda\x34\x28" + "\xe8\x6b\x63\xea\x52\x2c\x01\xbe" + "\xf8\x37\xdd\x61\x8c\x23\x2d\x29" + "\xdb\x42\x81\x8f\x3f\x52\x54\x0e" + "\xd8\x05\x6a\x03\x36\xb4\x1e\xe3" + "\xff\xc0\x93\x1e\xff\xcd\xe3\x83" + "\xdf\x1d\x82\x50\x0f\xfe\xd2\x3f" + "\x3b\xb3\x9e\xff\x0d\x9b\xe1\xc8" +
- "\xd0\xf0\x22\xe8\xa4\x11\xa0\x3e" + "\xf8\x04\x87\x5a\xd1\x7a\x64\xbc" + "\x0f\x82\xc6\x50\x35\x5b\x31\xbb" + "\xec\x6b\xe7\xb7\x3d\xec\x3d\x86" + "\xc7\xbf\x17\xf0\x3a\x5d\xff\x01" + "\x29\x82\x6b\x97\x39\x44\x05\x20" + "\x3b\x0d\xbd\x0b\x37\xca\x7f\x06" + "\x0f\x3d\x5e\x7f\x64\xde\x3d\xf6" +
- "\x95\xa8\x9c\x5e\x52\x90\x7d\x14" + "\xdf\x72\x20\x97\x1e\xd3\x4d\x2f" + "\x5c\x75\xc6\xe6\x8e\xda\x6f\xa1" + "\x58\x65\x19\xcf\xff\x26\x68\xc6" + "\x95\x38\xf4\x0c\xa3\x76\x1a\x1f" + "\x7b\x09\xc3\x83\xe0\x04\xd6\xa9" + "\x0e\x0e\x39\x66\x09\x83\x90\xe1" + "\xff\x5e\xc8\xb3\x53\xf7\x0b\xa5" +
- "\xcf\xcc\xf7\xad\x15\xbc\xd9\x75" + "\xb0\xe1\xa1\xdf\xd6\xe5\xa3\x81" + "\x7e\xc1\x9b\x24\x44\xe4\x39\x8c" + "\x43\xfd\xa7\x8e\xb2\xcc\x7d\xf3" + "\x12\xba\x7f\x90\x73\x48\x65\xda" + "\x04\x29\x37\x4a\xda\xa6\xda\x35" + "\xc5\xa6\x83\x62\xc6\xcf\x64\x05" + "\xbf\x95\x93\x4a\xf6\xa4\x9f\xd0" +
- "\x31\x84\x56\x6f\xa7\xf9\x64\x0d" + "\x8c\x89\xf8\x02\x7c\xc2\x48\xf8" + "\xd5\x5b\x0b\x26\xe1\xad\x18\xf4" + "\xe8\xde\x73\x69\x23\xe3\xf3\xc1" + "\xdd\x85\xc1\x26\x9c\x31\xe9\x46" + "\xc4\x0a\x6f\x54\xd8\xb7\x85\x6d" + "\x57\x9d\x7f\x24\xf2\x65\x79\x42" + "\x48\x5f\x03\xb0\x36\xb6\x19\xb5" +
- "\xff\x9d\xa3\x6a\xb5\xb3\x10\xb5" + "\x8c\x4d\x8e\x9f\xa2\x3d\xb4\x59" + "\x9f\x4b\x4c\x9e\xfd\x31\xce\xa8" + "\x01\x3c\x30\xc1\x26\xbe\x20\x0e" + "\xc9\x47\xee\xe8\x82\x71\x18\x18" + "\x01\x81\xb9\x7d\xdb\x7c\x68\xd9" + "\xf6\x4f\xe1\xa1\x4d\x0e\x52\x7a" + "\x72\xd5\x36\x88\xba\x08\x98\x42" +
- "\xc6\xe5\xa9\xdd\xe5\xc1\x2a\x68" + "\x95\xfc\xa9\xca\x72\x3c\x0d\x4e" + "\x44\xea\x2b\x77\xde\xaa\xfa\x17" + "\xc8\x09\x00\xab\x8c\x42\xf8\x5e" + "\x16\xf0\x0f\x46\x7a\xe4\x4c\xcc" + "\xcb\x81\x52\x72\xbf\x12\x6d\xda" + "\xd2\xaa\x23\x02\x48\x78\xc6\x44" + "\x28\x6e\x25\x36\xfa\x2a\x34\x6e" +
- "\x8e\x76\x16\x6d\x99\x46\x4d\x17" + "\x17\xf2\x8b\x62\x6a\xff\xc4\x9f" + "\x0d\x49\x4e\x15\x94\x5a\x70\x77" + "\x7a\x99\x2d\x8d\x28\xdd\x96\x9d" + "\xc4\x72\x5d\xce\xd8\xd9\xe2\x77" + "\x4f\x71\x1c\xc1\xa4\xc5\x06\x9d" + "\x3e\xa0\xe4\x79\x36\x51\xaa\x02" + "\x8b\xf2\x0f\x03\xc2\xb3\x86\x13" +
- "\xc2\xc9\xce\x8b\xb6\x86\x61\xb8" + "\x06\x9f\x0b\x68\xf9\x4d\xf2\x7c" + "\x81\x92\xd2\xc0\xea\x45\x6b\xc4" + "\x12\x0e\xb1\x07\xc5\x2b\xf4\xff" + "\x27\x94\x28\x4d\x40\x3c\x26\x12" + "\xc4\x8e\x84\xb4\x99\x18\x5f\x3d" + "\x0c\x80\x40\xd0\x10\x70\xf9\x11" + "\x20\xeb\x0f\x30\x29\xf5\xc5\xb4" +
- "\x3a\xdc\x40\xea\x69\x2d\xa4\x26" + "\x8f\x01\xcc\xae\x22\xad\x84\xdc" + "\x4a\xf0\x70\x32\x7b\x6c\xc3\x25" + "\xed\x72\xfa\x50\x47\x6d\xba\x46" + "\x8e\x8a\xe5\x93\xc5\xd1\x37\x6c" + "\x8c\x08\x0c\x12\x31\x47\x39\xa2" + "\xda\x86\x6e\xcb\x63\x42\xbe\xc3" + "\x38\xd0\x26\x71\x36\x7d\x41\x2c" +
- "\xd0\x59\x71\xb0\x6d\x11\x3d\x9d" + "\x10\x62\x89\xc1\x7f\xa6\x07\xae" + "\x79\x15\x96\xbb\x87\x4d\xc8\x8f" + "\xd6\x8d\x1f\x1c\x49\x9e\x00\x30" + "\x19\x28\x13\xe3\x22\xaf\x8c\x8a" + "\xff\xb4\x3a\xf2\x7c\x19\xfa\xcf" + "\x87\xd6\x5d\x20\x44\x3a\x10\x58" + "\xa2\x67\xed\x0d\xc3\x96\xb7\x57" +
- "\x29\x22\x0e\x44\xbb\x23\xa5\xcc" + "\x04\x4d\xef\x73\xa2\x73\x46\x32" + "\x39\xec\x11\x3e\x34\xdf\x3a\xaf" + "\xd3\x68\x59\xdc\xf1\xd7\x36\x61" + "\x27\xa9\x53\xb0\x99\x28\x7b\x7a" + "\xcd\x7e\x06\xae\x61\x26\xaa\x3e" + "\xd9\x9c\x77\x02\xc8\xb9\x49\x85" + "\xea\x85\x33\xc5\x40\x79\x1d\x06" +
- "\xe7\x3c\xe9\xb3\x89\x7a\xd2\xd7" + "\x1b\x2c\x3a\x5d\x75\xa8\xb5\xf7" + "\x8a\x21\x5b\x25\xa0\x68\x9e\xb2" + "\x54\x67\xf7\x8a\x7e\x83\x33\xb5" + "\x2e\xab\x9f\x57\x73\x5a\xb0\xd1" + "\x85\x43\xd7\xec\xa1\x55\x10\xb4" + "\x15\x91\x5e\x44\x74\x92\x36\xb2" + "\x4e\x27\x20\xf5\xc4\xa7\x72\x29" +
- "\x2b\x90\xa2\xaa\xfc\x41\x71\xe0" + "\xd3\x9a\xf6\xe4\x99\xd7\x9a\x53" + "\xfd\x9f\x3f\x81\x94\x3f\x45\xa6" + "\xf7\xc2\x5b\x37\x48\x3c\x8d\xc5" + "\x96\x4e\xc6\x5d\xad\x6f\x32\xb3" + "\x54\xe3\x40\xb2\xa9\xca\xaf\x3a" + "\xa9\xe7\xa1\xac\x03\x09\x1b\x1d" + "\xa0\xb8\x11\x12\x67\x97\xeb\x4c" +
- "\xa0\x10\x17\xc8\x79\x2e\x94\x5e" + "\xd4\xad\xcc\x27\x36\x4a\x7e\x55" + "\x0c\x6d\xcf\x4b\x56\xbc\xa2\x72" + "\x0c\xb8\xd7\x26\x43\x5f\xee\x09" + "\x19\x2f\x29\xd4\xe9\xdb\x70\x6b" + "\x18\x6b\xf1\x63\x26\x4c\xf7\x56" + "\x2a\xb4\xfb\x35\xf7\xb0\x3d\xc2" + "\x40\x00\xe1\x6a\xf6\xbd\x06\xb6" +
- "\x58\x2d\x03\x87\x46\xde\xb4\x1e" + "\xe0\x79\x2c\x5e\x83\x3d\x4f\xc5" + "\x23\xef\x04\x5d\xf4\x8d\x81\x07" + "\xb4\x41\x3d\x67\xc8\xa9\xfa\x55" + "\x55\x53\xb9\x89\x6f\x4f\xd6\xce" + "\x84\x5c\x41\xb7\xea\xd2\x60\x48" + "\xd3\xba\x0e\x05\xd2\x9b\xdb\x5f" + "\xbf\xa5\x85\x66\xcc\xe0\x53\xdb" +
- "\xb3\xa7\x1e\x8b\xa0\xd2\x61\x9a" + "\x85\x14\x8b\xae\x63\xab\x95\xd4" + "\x99\x2f\x05\x87\x84\x0f\x74\x38" + "\xea\x4e\x97\xb2\x5b\xbe\x8e\x17" + "\x7f\xd1\x36\x5b\xca\xbc\x0b\x03" + "\xea\x6e\xf8\xaa\xe3\xcc\xe4\xb5" + "\xe0\xe9\xf8\x68\x20\x02\x1a\xb5" + "\x75\x3e\xeb\x09\x96\x87\x34\xa4" +
- "\xca\xe1\xfa\xab\x5f\xca\x9f\x91" + "\x9b\x45\x21\x1a\xac\xfa\x7a\x93" + "\xd2\xa4\x66\x1f\x1c\xa9\x0c\x9e" + "\x31\x13\xec\x23\xf3\xc7\x4c\x19" + "\x90\x16\xa1\x8a\x3a\x14\x25\xad" + "\x08\x9e\xb5\x09\x8d\xad\x40\xbe" + "\x0a\x86\x50\xe7\x9b\x0d\xd6\x37" + "\x4c\x43\xbf\xc6\x08\xb0\x53\x6c" +
- "\x17\xc5\x3e\x1d\xd0\xa0\x61\xa6" + "\xae\x21\x23\x51\x52\x46\x74\x98" + "\x98\x25\xa9\xec\x91\xa5\x4c\x08" + "\xeb\x3f\xcb\x1d\xc9\x9d\xbb\xa9" + "\x40\xc2\xb4\x78\x55\x43\xc5\x14" + "\xdc\xaf\x0c\x61\x3b\x2a\xd6\x5e" + "\x6b\x84\x38\x1b\x37\x2f\x51\x07" + "\x61\x81\xe3\xb0\x0a\xb7\x1b\x57" +
- "\x2d\x24\x6b\xeb\x80\x70\x2d\x83" + "\x46\xe2\x71\x3b\x23\xd0\x0b\xd3" + "\x9d\x13\x31\xbe\x1b\x99\x27\x70" + "\x53\x4e\x2e\x46\x91\x7e\x79\x68" + "\x5a\x18\x4e\x6b\x0a\xe2\x3f\x42" + "\x07\xb7\xd9\x42\x7e\xc6\xf2\x82" + "\x1b\x81\xf7\x4c\x68\x17\xc8\x25" + "\x5d\xb9\x5b\x04\x5e\x00\x53\xbd" +
-
- "\xfd\x68\x8e\x9d\xbe\x49\xf6\xe5" + "\x20\x43\x04\x1b\x33\x05\x0f\xdb" + "\x98\x33\xc3\xe0\xb3\xe9\xfd\xf6" + "\xae\xcf\xc8\x66\x9b\x20\xf4\x92" + "\x4b\x9d\x73\x1a\xcc\xaf\xd1\xe9" + "\xde\xb8\x8a\xa2\x5f\xa7\xae\x09" + "\xd0\xf1\xc6\xea\xb5\x5f\x37\x14" + "\xa5\x7a\x8f\x70\x60\xb5\x20\x64" +
- "\x41\xdc\x54\x62\x9c\x49\xae\x9e" + "\x7e\x7e\x83\x7a\x24\x39\x29\x7e" + "\xa7\x24\x05\x09\x8c\xc0\xae\x74" + "\xf2\x55\x6f\x8d\x19\x92\x2b\xf8" + "\xc5\xce\x02\x14\x2e\x96\x3c\x49" + "\xe7\x30\x2f\xfa\x17\xca\x17\x9f" + "\xcb\x79\xb8\xe9\xe8\x83\xd7\xbc" + "\x5f\x14\x6f\x5a\x14\x8c\x3d\xea" +
- "\x6e\xee\x0d\x5e\xe7\x15\xde\xde" + "\xa2\x8a\x62\xdc\x72\x48\xf2\x74" + "\x93\xbb\x61\x78\xfe\xc4\xe9\xd3" + "\xe0\xb2\x87\x61\x2a\x82\xd4\x56" + "\xf9\x26\x98\xc5\xcf\x17\x64\xb6" + "\x9e\x16\x08\x24\x69\x09\x26\xca" + "\x85\xf8\x9e\xc7\x06\x9d\xf6\xed" + "\x8f\x13\x7d\xdc\x8a\x1f\x03\x00" +
- "\x26\xf7\xbc\x0e\xe6\x46\x3c\x10" + "\x0e\x47\x31\x62\x31\xb8\x82\x44" + "\x09\x21\x7c\x48\xca\xfa\x6d\x6f" + "\xef\x66\xe6\x62\x97\xce\x0a\x2e" + "\x42\x1f\x8d\x1f\xd3\xa9\x46\x32" + "\xd2\x44\x49\x57\xf1\x83\x1e\x1b" + "\x4b\x33\x7f\xa5\x3a\xa6\xdf\x13" + "\x81\x5d\x02\x9f\xed\xda\xf8\x0c" +
- "\xc1\x11\xee\x00\xa8\x8e\xd7\x30" + "\x75\xdd\xe3\xb5\xd4\x3c\x05\xeb" + "\xc5\x43\x8c\xd5\x3e\xb1\x65\x9b" + "\x63\x16\x15\xbd\xbd\x49\xad\xc3" + "\x90\x79\x42\xb6\x41\x8e\xfd\x99" + "\x1e\xae\x7e\x70\xbd\x15\xcf\x12" + "\x1e\xb7\xab\x1a\x1b\x4f\xad\x29" + "\x0e\x5d\x54\x07\x4d\xe7\x43\x51" +
- "\xe1\xde\x8b\xc8\x36\x63\x26\x30" + "\x7c\x76\x76\x58\x06\x93\xf2\x25" + "\x96\x19\x73\xc6\x71\x85\x07\x9c" + "\x51\x29\x55\xed\xb2\x90\x86\xc8" + "\xb4\x05\x27\x85\x2d\x2c\x4f\x27" + "\x2d\x55\x09\x4e\x44\x8d\xbf\xb0" + "\xd1\x75\x65\x98\xeb\xbe\x28\x76" + "\x51\x46\x86\x7f\x38\xe2\x7b\x40" +
- "\x6b\xfc\x39\xa6\x49\x30\x5e\x0e" + "\x25\x36\x00\x86\xd9\x35\x5c\xe7" + "\x46\x16\xcc\x5d\xd8\x5b\xf3\x0c" + "\x3a\x27\x26\x6c\xd2\xce\xca\x8b" + "\x42\x67\x53\xb5\x1d\xcf\x2e\xe2" + "\x8b\x06\x9e\x1a\x97\xd8\x3d\x01" + "\xc5\x09\x79\x8a\xcb\x11\xf4\x17" + "\x06\xd5\x1d\x86\x98\xac\x57\x57" +
- "\xbb\x5a\x93\x1e\x0d\x1f\xde\x85" + "\x7a\xe3\x4d\x15\xb4\x10\xfd\xde" + "\xb5\xeb\x9c\x36\x92\xe3\xd9\xb8" + "\xbe\x24\x13\x76\x9b\xef\xd5\x54" + "\x26\x7e\xf1\x74\xba\x41\x63\x4d" + "\xe4\xdd\xc1\x78\xc8\xe3\xa0\xc0" + "\xfd\x18\xd9\x87\x81\x75\xd7\xa6" + "\x13\x3a\xca\x02\x15\x60\x87\x66" +
- "\xf0\x58\x66\xf3\x9c\x3e\x31\xc7" + "\x7e\x05\xf8\x71\x1c\xef\x33\xc4" + "\x5a\x83\x6a\x1b\x46\x62\x32\x85" + "\x4c\x39\x86\x7c\x98\x53\xf0\xc8" + "\xa1\xc4\x83\xe9\xdf\x8c\x39\xff" + "\x31\xb9\xb7\x03\x62\x81\x5e\xbf" + "\x5b\x04\xb9\xb7\x46\x3c\x19\x93" + "\x6b\xe4\xa6\xa4\x5d\xbf\x4e\x1e" +
- "\xe7\x4f\xa2\x43\x60\x2a\x94\xf9" + "\x2b\x49\xb3\xff\x1e\x19\xc1\x29" + "\x05\xde\x2f\x90\x49\x24\x66\x9f" + "\x2d\xc3\x13\x67\xac\xa7\x92\xc7" + "\x2c\x98\x37\xb7\xd8\x8a\xd8\x2f" + "\xe3\x60\x1e\xa2\x19\x03\x3a\x7e" + "\x1a\x59\x83\x73\x44\xde\xb0\x09" + "\x56\xa4\x10\x83\xee\x41\xf1\x6d" +
- "\x71\xf4\xd6\xe6\x39\xa0\xc1\xae" + "\x2e\xd1\x98\x11\x0f\xba\xb2\x14" + "\xac\xe5\xee\x3a\x60\xa1\xc1\xeb" + "\xce\x64\xb9\xe0\x36\x48\x1f\x40" + "\x66\x3f\xd0\x4f\x96\x37\xe4\x2e" + "\x12\x3f\x8f\xdd\x49\x4e\xdb\x3f" + "\x18\x0f\x38\x29\xf6\x67\xf2\x6e" + "\x16\x4d\xa6\x8d\x70\x96\x8e\x3e" +
- "\xf1\x74\x76\x20\x0c\x18\x19\xbc" + "\xdb\x8f\xae\x33\xa7\x09\x2e\x11" + "\x1e\xb7\xae\x6a\x54\x75\x66\x99" + "\xc7\xb1\x01\xe1\xf1\x2a\x43\x79" + "\xc6\xde\x2d\xde\x8f\x55\xeb\xd5" + "\x3f\x75\x57\x53\x1f\x2d\x39\x81" + "\x8a\x15\xe1\x3a\x97\x6b\xa7\xa7" + "\x91\x99\x89\x4a\xff\xbb\x6f\x41" +
- "\xcf\x9d\x4a\x0d\xfd\xfd\x65\x9e" + "\x12\xdf\x4d\x94\x48\x9e\xc2\x7b" + "\x66\x68\x85\x3c\xd9\x92\x1a\xbc" + "\xe2\xdf\x98\x6e\x05\x69\x3c\x27" + "\xb8\xa6\xfa\xcd\x18\xe4\xfc\x69" + "\x9f\xc6\x61\x50\x23\xd8\x6b\x60" + "\x27\x5e\xf7\x6a\xa0\x95\xd4\x42" + "\x1f\x3a\x87\x6d\x05\xd5\xd3\x8e" +
- "\x6a\x5b\xb2\x6a\x41\x28\x55\xaf" + "\x23\x45\x1a\x2b\xc7\xff\xc0\xc6" + "\x03\x9e\xc9\x21\x7b\x82\x18\xab" + "\x1b\x69\x34\x90\x48\x86\x0e\x06" + "\x98\xf3\xc7\x93\x0f\xf9\x07\x52" + "\x0b\xd1\xf8\x82\xcb\x96\x4a\x9f" + "\xe3\xf9\xd0\x3a\x79\xcd\x71\xdd" + "\xf5\x54\x3a\xfc\xd2\x35\xf4\x84" +
- "\x7f\x78\x33\x8e\x5b\xc5\x03\x4b" + "\x73\x46\x38\xa6\x75\xf9\x42\xef" + "\xf0\xb9\x51\x50\xf7\x04\x73\xff" + "\xc2\x87\x1c\x74\xdc\xa1\xac\x18" + "\x80\xfe\x4b\x2d\xa7\x20\xf1\x56" + "\x2c\x73\x3e\x05\x3d\x3b\x82\xfd" + "\x16\xca\x37\x75\xe4\xcf\xbc\x11" + "\x6b\x99\x5a\x1b\x74\x9c\x6c\xdf" +
- "\xfa\xc3\x4f\x90\xc7\x32\x73\xee" + "\x6a\x63\xe3\xc7\x45\x3f\xa2\x14" + "\xaa\xd9\x91\xf0\xc3\x59\x86\xc3" + "\x40\x85\x2d\xb1\x5d\x5e\x99\x4a" + "\x8a\x59\xa5\xf3\xec\x3b\xa5\x20" + "\x95\xa9\xea\xb1\x17\x4b\x53\x56" + "\x3c\xe0\x04\xbf\xa4\xdc\xd3\x9e" + "\x68\x62\xd5\xd8\x3a\x56\x6c\x71" +
- "\xe7\x78\x61\x1d\xa4\x77\xba\x27" + "\x8e\xff\xa1\x68\x40\x0c\xc8\xe4" + "\x3d\xf6\x13\x0a\x99\x10\x01\x75" + "\xf3\x46\x1d\xa6\x21\x35\xf3\x7b" + "\xbb\x65\xb3\x10\x8e\x21\xff\x0a" + "\x75\xea\xd7\x0f\x04\x18\x02\x81" + "\x25\xa9\xb3\xa4\x8a\xfd\xa3\x05" + "\xe6\xb4\x3d\x9b\x5f\xe7\x29\xb8" +
- "\xfb\xe5\x53\x4d\xa5\x75\xdc\x6b" + "\xe3\x17\x27\xd5\x02\xdc\xa5\x04" + "\xc2\x2e\xa4\xe9\x2f\x50\xaf\x86" + "\x82\xe3\x30\x26\xfb\xe8\x67\x88" + "\x9b\x88\xc9\xbe\x6e\x5c\x84\xbf" + "\x8d\xc9\x47\xcb\xf2\x91\xf4\x54" + "\x12\x2a\x0c\x79\xba\x1f\x09\xa3" + "\x8b\x70\x0f\xc2\x78\xfd\xf6\xd7" +
- "\x17\x5e\xde\xac\x30\xac\x69\xa5" + "\xd7\xb4\x52\x68\xd0\x96\xf9\xd0" + "\x54\xae\x09\x46\xb5\x4b\x1d\xe5" + "\x61\xd0\xae\x0d\x17\x7d\xa3\x3f" + "\x41\xfb\xb8\x34\x84\x86\xa8\x62" + "\xf1\x64\xfb\x9e\xbd\xac\xa2\x99" + "\xf2\xe1\x48\x64\x5e\x1a\x5c\xb7" + "\x69\xa0\xb5\x42\x1a\x95\x99\xfa" +
- "\xe7\x26\x3b\x2f\x89\x6e\x95\x6d" + "\x47\x52\x87\xda\x60\x98\x70\xf4" + "\xa3\xdd\x82\x24\x79\x51\xd1\x3a" + "\xf0\x82\x7d\x01\xe3\x10\x41\xd6" + "\xe4\x14\xd4\xfa\x2c\x8d\x92\x14" + "\x24\x2b\xd0\x2e\x58\x5f\x15\x2b" + "\xf1\x1b\x82\xcb\x1b\x14\x1a\x48" + "\xda\xf5\x81\x4f\x70\xc7\xe3\x12" +
- "\x81\x83\xff\x9f\xe5\x5d\x9c\xe4" + "\x94\xc8\xbe\x5b\x32\x32\x05\x11" + "\xc4\x88\x4d\x45\xcc\x51\xd0\xa0" + "\x1b\x53\x8e\x1f\x9c\xb8\x6d\x4f" + "\x44\x3a\x56\xca\xd6\x3f\xfe\x34" + "\xb9\x8a\xda\x58\x15\x22\x5c\x7f" + "\xa1\xf0\x74\x94\x6d\x01\x45\x84" + "\x0a\x8a\x7d\xcb\x61\x4d\xd3\x17" +
- "\x19\x40\x47\x1c\x10\x39\x9d\x8e" + "\xfb\xee\x2c\xd5\x29\x26\xff\xca" + "\x2b\x2c\x62\xc1\x32\x3e\xcf\xf9" + "\x05\x1a\x07\xe9\x3c\x5e\xb9\xd4" + "\x8c\x43\x94\x15\x1f\xa6\xbc\xfb" + "\xdf\xde\xaa\x04\xa6\xe6\xb6\x1e" + "\x40\x49\xe1\x68\xf4\x27\x30\x85" + "\x9c\xda\xab\xdf\x2a\x32\x1d\x22" +
- "\x9a\x17\xcb\xb7\xf6\xa9\x8e\xed" + "\xcc\x4d\x93\xb7\x4d\x76\x7b\xdc" + "\x0d\x18\x09\x5e\x40\x39\xb1\xfc" + "\xdd\xc2\x7d\xb4\xbf\xa6\x29\x66" + "\x5e\x91\x5a\x9f\x4e\x5e\xc5\xbf" + "\x1e\x44\x04\x62\x37\x9d\xdb\xb1" + "\x53\x5f\x0c\x93\xcf\x68\x2d\xf8" + "\xb1\x05\xb6\xcb\x42\xa1\xd3\x17" +
- "\xf2\x80\x87\x30\xea\x44\x59\xdd" + "\xe4\xf5\x45\x38\x61\xe7\x8d\xdc" + "\xa3\xd7\x24\x76\x7d\xba\xea\x6b" + "\x1e\xf1\x4d\x30\xfd\x9a\x70\x1e" + "\x56\x04\x17\x02\x76\x43\x36\x95" + "\x64\x4b\xf9\xc8\x3a\x4b\x20\xbf" + "\x68\xca\x80\x56\x7c\xaf\x53\x4e" + "\x74\x75\xc6\xe0\x4a\x07\x26\x05" +
- "\xf6\x2a\xd9\xec\xf8\xce\xd8\x95" + "\x5a\x74\xd1\x6c\x7a\xfa\xb9\xe6" + "\xe4\xc3\x25\xa3\x3d\x6d\x54\x3d" + "\xae\x3a\xe9\x9a\x1d\x69\x57\x1f" + "\x33\x1a\x2e\x9d\xfe\xf3\x91\xe8" + "\x35\x3d\x06\xac\x3f\x09\x30\xd4" + "\x27\xa3\x13\x55\x12\x9b\xa5\xed" + "\x8f\xf1\x36\x55\xf3\x34\x21\xdc" +
- "\x86\x02\x21\x5c\x2c\xfe\x51\xaa" + "\x8c\x65\xab\x1c\xee\xaa\x68\x3f" + "\x92\x72\x35\xf9\x0b\xa0\x23\x5a" + "\xed\xab\xfd\x7e\x39\x6f\x62\x9a" + "\xe3\x78\x9d\x19\xf3\x3b\x2b\xfe" + "\x45\xc3\xbb\x71\x77\xaf\xa2\xb7" + "\x2c\x80\x59\x1e\x7a\x82\x19\x3d" + "\x1c\xa5\x87\xb4\x15\xbc\x3b\x82" +
- "\x22\xa4\xd0\x99\xf2\x39\x61\x85" + "\xfb\xc6\x56\xf4\x65\xdf\xc3\x9a" + "\xd6\x8b\x1f\x70\xc6\x65\xdf\xad" + "\x87\xdf\x58\x37\x1e\x32\x9f\x14" + "\xba\x7e\x1b\x72\x14\xf7\xec\xb1" + "\x2a\x31\xa3\x31\x98\xf0\x7d\xe1" + "\x81\xd5\xc4\xd5\xec\xd6\x2f\xdb" + "\xb3\xa1\xce\x8f\x6f\x99\x02\xfd" +
- "\x4f\xf1\x82\x78\x3e\xa6\x9f\xe2" + "\xdc\xca\xc6\x07\x35\xdc\xf6\xc9" + "\xd0\xbe\x82\xb8\x6f\x2d\xf2\x46" + "\x2c\xe5\x18\xd1\x5b\x75\x45\x1a" + "\xcf\x08\x46\x7c\x27\x7c\x2c\x9f" + "\xc2\x12\x80\x56\x32\xdf\xcb\x7c" + "\x0e\x9b\x72\x61\xdd\xae\xb0\xfc" + "\xbf\x5d\xd7\xf7\x9e\xca\xa2\x7c" +
- "\x62\x0f\x64\x6f\xb1\xec\x8f\xf5" + "\x46\x19\xf5\x39\x2b\xb9\x74\xe2" + "\x44\xaf\x88\x62\x04\xfc\x4d\x7f" + "\xe5\x29\xc3\xea\x2a\xf3\x91\x0a" + "\x31\xba\xaa\xd6\x4b\x27\xad\x43" + "\xf9\x84\x68\x0f\x40\x16\x9a\x71" + "\x20\x1e\xf9\xda\xf6\x29\x5d\x68" + "\x52\x9d\xe4\x27\x33\xcc\xc1\x5e" +
- "\x59\xa0\x54\x3b\x96\xde\xf4\x38" + "\xb3\xfd\xbc\xef\xe5\x15\x00\x0e" + "\xa6\x8d\xbb\x4d\xd9\x23\x7d\x17" + "\xad\x17\xa6\x97\xa2\x4a\x72\x98" + "\x8e\x55\xb6\xfd\x5b\x88\xf0\x30" + "\x96\x9a\x89\xc7\x8a\xa2\xf7\xf9" + "\x12\xc1\x2d\x87\xc8\x8a\xae\xd2" + "\x59\xc4\xc3\x73\xca\x42\x06\xfa" +
- "\xd6\xc8\xdf\xe7\x81\x69\x29\x15" + "\x4a\xb9\xb5\x1f\x50\x44\xcd\x67" + "\x37\xfd\xdd\x0e\xf1\x1c\xc7\x0e" + "\xc7\xdd\x8e\x9a\xb3\xee\xe5\xc7" + "\x28\x50\xd9\x81\x3d\x8e\xac\x02" + "\x5d\xe3\xb0\x70\x72\xf1\x88\x00" + "\xe3\x1f\x88\xe1\xab\x1f\x04\xec" + "\xaa\x7f\x9e\xd9\xb8\x71\xcf\x62" +
- "\xc2\x22\xf2\xe0\xa7\xde\x43\x50" + "\x42\x51\xe6\x72\xac\x42\x9d\x30" + "\x30\xcd\x16\x92\xdd\x9d\xfe\x94" + "\xec\xfe\x87\x0f\x7d\x9c\x53\xd6" + "\xd7\xc7\x2a\x43\x7c\xa5\xc5\x03" + "\x10\xda\x7f\x32\xf0\x2c\x69\x72" + "\xde\x98\x06\x28\x5f\xc8\x28\xec" + "\xb1\x83\xc2\x7e\x46\xfb\x31\x23" +
-
- "\x77\xa4\x57\xe4\xea\x8e\x15\xa0" + "\x05\xdc\x6d\xee\xdb\x57\x98\xd1" + "\x71\x16\xc4\x18\x24\x52\x26\xb3" + "\x58\x0d\x2c\x3c\x7e\xfc\xfd\x3f" + "\xda\x7c\xee\x26\x54\x52\x3a\x3a" + "\xa8\xc3\x02\xdf\x69\x08\x1b\x34" + "\xc8\xbf\x3b\x72\x42\xbf\x23\xa0" + "\x91\x26\x45\x14\x2a\x00\x15\x3d" +
- "\x30\xfa\xed\x85\x4c\x32\xf7\x5e" + "\xda\xf3\xd4\x87\x54\x65\x97\x25" + "\x86\x0c\xb5\xdc\xc0\x5b\x2f\x35" + "\x6c\xa9\x32\x48\xb0\x27\x69\x8f" + "\x4c\xf9\xf2\x55\xba\xe1\x8e\xd0" + "\xfa\x45\x4b\x34\x99\x6f\x99\x6a" + "\x5d\x45\xaa\xa8\x8d\xcb\x33\xe1" + "\xf7\xc1\x8d\x75\xec\x21\x07\x5d" +
- "\x39\x35\x2a\x26\xe9\xe7\xca\xf3" + "\x9e\xd5\x70\x66\x1d\x9d\xa4\x78" + "\xb9\xe1\xc5\xc1\x63\x0f\xde\x37" + "\x1c\x7c\xcb\x69\x0c\xc3\x72\x30" + "\xe6\x50\xc8\x77\x52\x8a\x27\x1d" + "\xe6\x3d\x6a\x1f\x8f\x5f\xf1\x84" + "\xad\xa7\x2c\x59\x45\xbb\xa8\x46" + "\xb8\x24\xd4\xe4\xee\xe3\x12\x19" +
- "\x67\xfb\xe5\x79\x20\xa9\xa7\x6b" + "\x5e\x72\xaa\x70\xeb\x1f\x33\xe1" + "\x37\xd8\xf5\x7d\xf5\xcc\x80\x50" + "\x21\x2e\xf7\x7f\x1d\xe0\xca\xe4" + "\x7d\xa7\x12\x04\xe6\x3e\x24\xd9" + "\x25\x90\x44\xdf\xac\x7c\xff\x06" + "\x31\x5a\xef\x23\xcd\xf7\x75\xbe" + "\xa8\xf7\xde\x0d\x22\x78\x95\xbc" +
- "\x8b\x66\x5e\x36\x86\x80\x98\xdc" + "\xfb\xa5\xbd\xaa\xda\xdc\xa8\xad" + "\xbe\x1f\x5f\x25\x4c\x6b\x14\xbc" + "\xc3\xcf\x34\xcf\x29\xde\xfc\x9c" + "\xe4\xd1\x85\x7e\x3e\x45\xbb\xac" + "\xb5\x58\x23\xf9\x79\x96\xa0\x9c" + "\xff\x23\x08\x24\x96\x2d\xfc\x15" + "\x1e\xd1\x11\x0c\xf7\xad\x65\x8d" +
- "\x55\x1c\xce\xb0\x0c\x23\xf7\x8c" + "\x07\xb6\xbf\x0b\x05\x4d\x53\x5b" + "\x3b\x36\x16\x0e\x13\xf1\x1e\xee" + "\x82\x9e\x99\xb4\x7a\xaa\xe0\x27" + "\x41\x2c\x36\x79\x2d\xac\x1d\xce" + "\xb0\x6c\xbb\x91\x90\x0c\x92\x67" + "\x24\xdf\x23\x22\x63\x8d\x64\x1e" + "\x28\x8f\x2e\xe3\xef\x9e\x7d\x0f" +
- "\xfd\xf4\x96\x02\xf1\x57\x55\x77" + "\x36\xb4\x51\xea\xa3\x76\xca\x1d" + "\x05\x08\x95\xfb\x60\x8f\xe9\xf3" + "\xf1\xf7\x1c\x83\xea\x32\xff\x31" + "\x4b\x71\x2c\x8d\xf1\x7b\x3e\x64" + "\xca\x2a\x9d\x2e\x39\xc3\xb5\x64" + "\x23\x2d\xdc\x6a\xcc\x9c\xfd\xa9" + "\x9b\x1b\x72\xcc\xec\x97\x23\xfc" +
- "\x34\x38\x83\xfa\x9a\xf3\x43\x69" + "\x62\x85\x32\xa6\x22\x17\x95\x22" + "\x10\xfc\x70\x41\xd5\x3d\xd6\x81" + "\x6d\x2e\xcc\xae\x8f\xa5\x5f\x9f" + "\x3b\x9a\x7d\xe7\x25\x87\x6c\xb6" + "\xe0\xeb\x84\x63\xea\x5c\x23\x11" + "\x4a\xe2\x45\x58\x18\xc1\xa8\x06" + "\xb1\x93\xd0\xeb\x86\xb2\x37\x01" +
- "\x7d\xc5\x8e\xb4\x2d\x18\x31\xf0" + "\xb9\x33\xb2\x04\xf8\x32\x5d\x51" + "\x26\xad\x3a\x09\xd4\xb1\xbb\x06" + "\xec\xd1\x83\x0d\xfe\x42\xa1\x88" + "\xf8\x73\x5c\x24\x99\xc0\x95\x3b" + "\x32\xcd\xed\x52\xaf\xd4\x26\xb1" + "\xe6\x52\xcb\x8f\x1e\x2c\x02\xf8" + "\x39\xd3\x06\x01\x4c\xac\x51\x5a" +
- "\x50\xe1\xac\x44\xce\xe1\x89\xc5" + "\x7c\xe9\x81\x43\xd9\xd3\xf8\xe0" + "\xb8\xa4\xc5\x62\x11\x9b\xe9\x59" + "\xf9\xc9\x0e\xfd\xf7\x62\xd2\x90" + "\xc9\x13\x3e\x28\xc9\x54\xc8\xfb" + "\x85\x70\xdc\xae\xe7\xfd\x04\x2d" + "\xcb\xbe\xdc\x47\x65\x77\x7d\x05" + "\x5f\xfa\x76\x9a\x91\xf5\xbd\x8d" +
- "\x54\xa0\x64\x7c\x1a\x0a\xf7\xb7" + "\x79\x3e\xb4\x9d\xdf\xc0\xc1\x0d" + "\xd6\x63\xfe\x51\xe2\x4a\x0a\x6d" + "\xbf\x8a\x0c\x7f\x32\xe3\xd5\xe0" + "\xe8\xce\x7e\x2b\x36\x00\x55\xff" + "\x08\x50\x05\x5d\xf7\xe6\xa0\x3e" + "\x4f\xc8\x4a\xf2\x2f\xb6\xde\x30" + "\xb7\x16\x71\x5d\xfd\x69\x69\x93" +
- "\x78\xe5\xe1\x0d\x95\x06\x15\xd0" + "\xc6\x2b\xf7\xe9\xe7\x63\x14\x2e" + "\xa5\xec\x39\x1b\x41\x84\xa6\xff" + "\x2f\x7f\x03\x7c\x30\x85\x3c\x67" + "\xda\x91\x7f\x74\x00\xa6\xd6\xd0" + "\xe9\x78\xcb\xc9\xe1\x43\x8d\xb0" + "\xf5\xce\xb5\x27\x44\xc6\xc0\x0f" + "\xd6\x2f\x0a\xa6\x0a\x16\x1d\x5c" +
- "\x7f\xcf\x17\x26\x12\x76\xda\x02" + "\x60\x52\xe3\xee\x4e\x5d\xe2\xd6" + "\xe9\x33\x35\xfd\x0a\x5b\xfa\xb2" + "\x88\x6f\x12\xb9\xb0\xb7\x6b\xe7" + "\x66\x68\x85\x88\x99\x6a\x2e\x69" + "\xca\x65\xdb\x49\x4f\x39\xdf\x3f" + "\x06\xd6\xd8\x22\x91\x69\x29\x25" + "\xcf\xc4\xd7\x3d\xbf\xbf\x15\xe8" +
- "\x3b\xe1\xc8\x28\x53\xae\x8c\xf9" + "\xd1\xdc\xed\xb2\xc4\x10\x5f\x37" + "\xad\x06\xce\x5c\x7f\x8b\xeb\xd4" + "\xef\xe1\xa2\x80\x45\x9f\x66\xb4" + "\x99\x86\xbd\x5b\xd0\xf9\x93\xd5" + "\x13\x6d\x97\xe7\xc9\xa4\x28\x55" + "\xd3\x28\x7e\x1c\x95\xe0\x23\x39" + "\x77\xb5\x6b\x3f\x90\x37\x29\xb9" +
- "\x7f\x4e\x84\x4d\xed\x84\xc9\x69" + "\x82\x8a\x2e\x4a\x17\xb2\x54\xd3" + "\x36\x41\x2c\xfb\xdd\x4a\xbd\x25" + "\xe1\x26\x4b\x14\xde\xf4\x2d\xf7" + "\xfd\x1a\x10\xe6\xb0\x9d\xaa\xd0" + "\xb8\xd1\x9b\xe4\xaa\xef\x45\x44" + "\xb2\x93\x15\x33\xee\x4e\xc5\x5d" + "\x0b\xf1\x4b\x09\xb9\xe3\x35\xfa" +
- "\xd2\xd6\x2b\xc4\x6a\x7d\x56\xdb" + "\xae\x96\x1f\xbb\x68\x64\xf8\x6d" + "\x8e\xb2\x43\x48\x1a\x5b\xfe\x0e" + "\x40\xb2\x79\x63\x05\xbb\x1b\x96" + "\x6b\xa2\xa6\x70\xf0\xf5\xca\xb6" + "\x39\x6e\x8e\x32\x0d\x6c\x68\x70" + "\xd3\xc8\x5f\x89\xcf\x06\xda\x80" + "\xc9\xfd\x63\xb3\x10\x88\x4d\x80" +
- "\xc3\x89\xa0\x3e\x89\x0f\x0a\x66" + "\x09\x9b\x00\xc9\xaa\x23\x58\xa2" + "\xe5\xf5\x81\xa6\x7b\x2d\x26\xb2" + "\x3a\x86\x13\x34\x8c\x0c\xc3\x4f" + "\xf7\x59\x20\xc3\xb7\x44\x15\x69" + "\x34\x61\x1c\xb2\x76\xf2\x5c\xf6" + "\xba\xda\x04\x51\x2a\x6b\xa9\xe3" + "\x2f\xe4\x3e\xa4\x09\xd1\x08\xbb" +
- "\x70\x16\x7f\x20\x7b\x87\x22\xbe" + "\x91\x52\x61\x4e\x88\xd1\x0d\x9b" + "\xbf\xc2\xa3\x97\xdc\xe8\x5a\x62" + "\xe8\x86\x9b\x43\xf7\x4e\x58\x08" + "\xff\x98\xd8\xdc\xa5\x90\x71\xde" + "\x3d\xee\x58\x20\x40\x6c\x28\x26" + "\xc1\xb1\x87\x5f\x17\xb2\xb0\x3d" + "\xb5\x6d\x2a\x10\x71\x47\x33\xcc" +
- "\x61\x68\x91\xf9\x69\x2d\xa5\x85" + "\x13\xa8\x4f\xda\xa4\x69\x54\x59" + "\x2f\x50\x38\x33\x6e\x78\xd7\x1d" + "\xc5\x3a\x96\x53\x28\xef\xb8\x34" + "\x25\x1b\x89\x1a\xf8\x19\xf0\xc0" + "\x75\xd7\x4b\x4f\x0c\x97\x19\xb6" + "\x81\xf6\x19\xbe\xf3\x5a\x2a\x8c" + "\x28\x17\xec\x98\x04\xdb\x63\x94" +
- "\xb1\x0f\x77\x2f\x54\xe9\x9d\xd9" + "\x5e\x53\xd7\x4c\x20\xc6\xc1\x97" + "\xfc\xce\x09\x3f\x48\xc4\xb6\xd3" + "\xf8\xb4\x63\x5a\x15\xaf\x25\xd7" + "\xec\x20\x1e\xc0\x4f\xd2\x95\x0c" + "\x1f\x12\xe7\x9a\x94\x74\xd3\xdf" + "\xec\xb7\x77\xec\x72\xdb\x6d\x7d" + "\xae\xa4\x53\x03\x3b\x9d\x07\xfe" +
- "\xab\x9e\xf3\x01\x78\xc2\x62\xeb" + "\xaa\xa4\xb3\x0a\x34\x39\xde\x27" + "\x8d\xca\x82\xa9\x20\x75\xd1\xfb" + "\xed\xc6\xbd\xe4\xc2\x7e\x81\x58" + "\x13\xac\xc6\x31\xde\x78\x2d\x31" + "\xa6\x2e\x20\x09\x76\xbf\x83\x94" + "\xe1\xd8\xc6\x22\xb6\xb8\x4a\xf6" + "\x74\xde\x80\xe5\x9c\x58\xdf\xdd" +
- "\xd2\xc8\x6a\x2e\x0a\xe7\x66\x30" + "\x05\x5c\x6e\x10\x43\x5a\x6b\x9c" + "\x8c\x9b\xe5\xed\xf5\xc6\xd3\x52" + "\xae\xc9\xce\xfc\xc3\xa5\xd6\x30" + "\xef\xa9\xc0\x4f\x22\x7c\xec\xed" + "\xed\x6c\xc1\x95\x83\xf0\x0f\x19" + "\xde\x0f\xde\x94\x8f\xec\x12\xbe" + "\x33\x34\x2d\x85\xb8\x1a\x13\x0d" +
- "\x2a\xa9\x98\xee\x36\x33\xfa\xe0" + "\x45\xd7\xa4\x66\xef\xee\x80\x7d" + "\xd3\x19\x01\xba\x1b\x53\x12\xb6" + "\x15\xfe\x51\xb3\xc1\x70\xe7\x86" + "\x97\xa3\xd5\x82\xf8\xd6\xba\xaf" + "\x10\x01\xbf\x0d\xb8\x1c\x5f\x1e" + "\x3d\x06\x79\x9f\xc0\x8a\x13\x25" + "\x56\xa1\x46\x27\x2f\xd2\x9e\x08" +
- "\x91\x12\x70\x85\x7e\xe0\xac\x42" + "\xa8\x61\x40\x19\xd9\x3e\x79\x94" + "\x85\xa4\xf4\xd7\xd6\x3e\xe8\x30" + "\x4d\xff\xee\xf9\x69\x72\xec\x9e" + "\x05\x80\x9d\x0c\x59\xba\xac\x90" + "\xd1\xb9\x79\x1e\x58\xa4\xec\x5f" + "\x1e\x6a\x50\x1d\x27\x54\xbe\x8f" + "\xa7\xcf\x39\x24\x8e\x2c\x2b\xa3" +
- "\xde\x8d\x8b\x7d\x5d\x1b\x8d\x19" + "\xfb\x37\xab\x8d\x07\x11\x2c\xf3" + "\x74\x38\xb9\x42\x6d\xcb\x5f\xf1" + "\x84\x4f\xf9\x41\x4f\xb7\xdd\x91" + "\xb2\x24\x15\x27\x0a\x54\x64\x6a" + "\x64\x5a\x8b\x75\x12\x0c\x0a\x95" + "\x80\x95\xce\x3d\x93\x37\xf2\xf9" + "\x32\xce\xf8\x2c\xab\xd0\xed\xc8" +
- "\x4e\x0b\xdd\x73\x73\xc1\x71\x16" + "\xc6\x54\xa0\x44\x14\x82\xa2\x37" + "\xf1\x53\x8b\x4e\x1b\x0a\x76\x81" + "\x9e\x3b\xf9\xf9\x24\x42\xc0\xa6" + "\x3c\x1e\x67\xcf\x34\x4b\x78\x18" + "\x94\xb9\xa9\xcd\xd2\xec\xbb\x81" + "\x48\x38\xab\xb2\x79\x19\x83\x38" + "\x2d\x3c\xe0\xf2\xb7\xfe\x54\xef" +
- "\xb7\x46\x10\xae\x7e\x35\xc6\xef" + "\xe4\x32\x29\x61\x29\x49\x70\xe6" + "\x17\x5b\x35\xb1\xd4\x05\x03\xa2" + "\x56\xa1\xb4\x58\x6a\x13\xa9\x88" + "\xec\x75\xd2\xb4\x85\x99\x37\xbc" + "\x8b\x33\xaf\x6e\x31\x91\x8b\x71" + "\x09\xa5\x52\xd1\x7a\x9a\x22\x61" + "\xe9\x7a\x15\x45\xc4\xf7\x09\x11" +
- "\xfa\x88\x80\xfb\xa7\x7c\x19\xcf" + "\xc5\x96\xdc\x4d\x47\x72\x42\x01" + "\x76\x71\x77\x30\x0a\x55\xd2\xa2" + "\x1d\xf7\x0c\x4d\x98\x98\x46\x53" + "\xc6\xaa\x2a\x3a\xb8\x37\xe9\x6c" + "\x9b\x8d\xf3\x5a\xc3\x1d\xf9\xe9" + "\x99\x28\xbf\xc8\x83\xad\x98\x25" + "\x16\x6c\x53\xb5\xc9\x6a\x70\x8e" +
- "\x2c\x5c\xf8\x0d\x14\x42\xde\x2b" + "\x63\x7a\x8a\x05\xf4\x39\xb8\x4f" + "\x31\x12\xf5\x47\x2a\x57\x10\x7c" + "\x4e\x82\x89\x19\x23\x26\x88\x87" + "\x4a\x56\xe1\x16\x20\x3d\x29\xa8" + "\x76\x45\xc0\x18\xf8\xc0\x11\xcb" + "\x31\xc6\x40\x97\x7d\x1e\xb9\x83" + "\xa0\xce\xff\xcb\xd0\x23\xcb\xbd" +
- "\x98\xdc\x88\xf6\x95\x74\xdc\x40" + "\xfc\x4a\x4c\x12\xd7\x0c\x49\x26" + "\x5c\x77\x18\x1f\x84\xec\x51\xe6" + "\x4a\xaf\xfd\xb4\xc3\xa6\x3e\x39" + "\x0d\x8e\x33\x7f\x43\x33\x1f\x1e" + "\xb5\xe7\x53\x60\x2b\x83\xfb\x39" + "\xd5\x14\x9e\x61\xda\x02\xe7\x46" + "\xe0\xf6\xee\xcd\xd1\xac\x9c\x85" +
- "\xc8\xbf\x94\x90\x2a\xfd\xbd\x64" + "\x1e\x4d\xc5\x0f\xc6\xac\x58\x85" + "\x1e\x72\x27\xaf\x8f\x84\x92\x39" + "\x09\xd0\x4c\xa1\xda\xcb\x8f\x7a" + "\xc2\xb9\xa4\x00\x09\x12\xe6\x6d" + "\x28\x8f\xcf\x20\x1b\x2b\x19\xbd" + "\x83\xbe\xd9\x68\x01\xb9\x56\x23" + "\x8a\xa4\x49\x4a\x94\x7a\x1e\xce" +
- "\x7d\x00\x62\x44\xe7\x9c\xb9\x63" + "\xb7\xf5\xb5\x4c\xa5\x48\xab\xb8" + "\xe7\xdd\x5e\xf5\xd2\x73\xc6\x9e" + "\xda\xef\xfa\x8c\x74\x7f\x56\xd1" + "\xec\xbc\x87\x08\x6b\x1b\x38\x46" + "\xc2\xf3\x78\xe1\xce\x97\x44\x69" + "\xcb\x66\x62\x1e\xe3\x25\x65\x5e" + "\x13\x64\x7d\x69\x26\xde\x31\x59" +
-
- "\x7a\x50\x93\x1a\x02\x55\x2b\x14" + "\xcf\x06\x3c\x8d\x87\x11\xcd\xb4" + "\x40\x3f\xec\x91\x6a\xe7\x70\xdf" + "\xc2\x53\x75\x4e\xad\x81\x4e\x48" + "\x6e\x9d\x2e\x27\xb5\x87\x0f\x83" + "\x4a\x51\xff\xc6\xe5\x93\x1c\xea" + "\x8e\x2a\x19\xc4\xdc\x2a\xcc\x67" + "\x5a\x53\xf4\x42\xe2\x27\x7e\xc7" +
- "\x99\x51\xc0\xd0\xf2\x9c\xda\x8c" + "\x54\x84\xe7\xfa\x22\xbc\x2f\x50" + "\x82\xa1\x72\xf5\xdf\xa9\xbd\xc0" + "\x72\xb3\x58\x61\xb8\x71\x9b\x5f" + "\x07\xdd\x82\x2b\x59\x3a\xf3\xe0" + "\x2e\x03\x23\x95\x35\x27\x30\x76" + "\x32\x5a\x50\xc4\x21\xa7\xe1\x7f" + "\x9f\x40\x96\xf7\x82\x3e\x6e\x7b" +
- "\x9e\xba\x37\xea\x56\x63\xc6\xb4" + "\x5d\xf5\xff\x0a\x15\x84\xdc\x1a" + "\x62\xc8\x6c\x59\xf9\x0e\x08\xf0" + "\xb6\x7a\x64\x6d\xb8\x85\x6c\x75" + "\x15\xc2\xb9\x1d\xaa\x94\xdb\xc9" + "\xa5\xb1\x13\x20\xb1\x6d\xd3\x2d" + "\x03\xc9\x86\x42\x1c\xc6\x6a\xde" + "\x84\xf8\x6c\xc7\x88\x2f\xd3\x3f" +
- "\x4a\xb3\xd0\x35\xc0\x7b\x41\xe3" + "\xa7\xc0\x27\x83\x6b\x38\x0b\x44" + "\xd1\x62\x03\xac\x2d\x26\xb7\x8f" + "\x43\xf9\xcd\xe0\x4c\x11\x41\x2c" + "\xb1\xa0\x95\xad\xf1\xce\xa5\x2b" + "\x62\x43\xd5\x67\xa8\x37\x9b\xc0" + "\xc9\x86\xe4\x01\xd2\xcd\xd6\x26" + "\x97\x92\xff\x42\xbf\x7a\x47\x20" +
- "\x8d\x46\xe9\x11\xec\x82\xca\x31" + "\xa0\x5f\xa0\x1c\xb6\x0e\x5d\xcf" + "\x73\x2e\x96\xaa\x05\xa3\xba\x49" + "\x56\xe4\x15\x40\xb9\x61\x2b\xad" + "\x35\x38\x21\x6c\x5f\x8e\x2b\x6d" + "\x63\x47\xf7\x48\x2b\x1c\xf1\x0e" + "\x68\xa7\x8b\xc1\x5e\x7b\xcd\xa8" + "\xec\xcc\x7e\x15\xef\x4d\xc8\x73" +
- "\x7d\x1e\x58\x51\xf6\x6a\x54\x13" + "\x2e\xdb\xc7\x39\x87\x0b\xe2\x0c" + "\x46\x7c\x12\xd9\xed\xe2\xb1\xfa" + "\xa8\xe6\x35\x6f\xc4\x1d\x9a\xba" + "\x7b\x0e\x69\x80\x6f\x66\x69\x1b" + "\xa0\x90\x88\x64\x3d\x0e\x53\xd6" + "\x00\x3e\xc2\x99\xb1\x4c\xbd\x37" + "\x00\x7a\xba\xb7\x2c\x4e\x27\xe7" +
- "\x3a\x24\x57\x67\xb6\x50\xac\x9f" + "\x72\x24\xf3\x23\x61\x79\x41\x8f" + "\xf4\xcb\x72\xb3\x56\x7a\x36\xeb" + "\x03\x92\x79\xb7\x5c\xe1\x37\xbe" + "\xdd\x33\x40\xdc\xdf\x1f\x52\x1b" + "\x7f\x8d\x8d\xae\xed\x10\xf4\x21" + "\x47\x75\xdc\xbd\x4e\xf2\x6a\xbe" + "\x4d\xa7\x18\x6e\x84\xae\x65\x99" +
- "\x87\x92\x2a\x29\xb3\xdc\x04\xa0" + "\xc7\x92\xb0\x77\xf6\x5c\xc1\xdd" + "\x05\x06\x6c\x80\x64\x84\x3a\x08" + "\xb0\x97\xb9\x3d\x70\xdf\x68\x4a" + "\xd0\x7d\xbf\x05\x45\x4e\x13\x9c" + "\x8c\x7f\xcf\x8c\x39\x3d\xe6\xa4" + "\xaf\xf8\xb5\x41\x7f\x51\xe6\xa6" + "\xcc\xc1\x7b\xad\x42\x93\x8b\xaa" +
- "\xc1\x5a\x89\x16\xcd\xb0\xa9\x6a" + "\x37\x4c\x8e\xf2\x53\xd3\xdc\xad" + "\x0a\xae\x90\x6f\xbd\x3a\x47\xff" + "\x8e\x14\x8a\x31\x09\x24\x48\x76" + "\x21\x27\x19\xca\xcc\x5e\xeb\xc5" + "\xae\x22\xd2\xfb\x27\x25\x54\x58" + "\x94\x0d\xb5\x81\xa9\x52\x48\x59" + "\xba\x8c\x6a\xe2\x03\x4e\x1f\xa0" +
- "\x4a\xf9\xe0\xc2\xf5\xc5\x1d\xe1" + "\xc7\x6c\x98\x71\x4e\xfa\xb6\x1f" + "\x02\x8d\xb3\xa5\x96\x19\xfc\x0f" + "\x3f\x40\x85\x93\x8e\x26\x06\x0e" + "\x95\x61\x1a\xd0\x09\x1f\xd1\x93" + "\x17\x65\x46\x5d\x40\x96\xeb\x05" + "\xdf\x5a\xed\x77\xcc\x85\xa8\x63" + "\x72\xea\xa0\x35\x25\xdc\x07\xd5" +
- "\x38\xc3\x4f\xa9\x81\xad\xe7\x68" + "\x9d\x4d\x22\x5a\x4b\x70\x6c\x31" + "\x5f\x59\x26\x4f\x38\xa9\x4f\xe3" + "\x36\x18\x96\x98\xe9\x1f\x17\x86" + "\x6c\x49\x27\x39\xc4\x1b\x99\x98" + "\xd7\x61\x87\xc6\x5a\xdb\x6f\xce" + "\xd6\x96\x9e\xb2\xfc\xfe\x24\x0a" + "\xa3\x66\xac\xe5\xa6\xff\x2d\xc7" +
- "\xd9\x6a\x70\x1e\xb5\x35\x6f\x12" + "\xdf\xeb\xa9\xc3\xb4\xeb\x9c\xb9" + "\x90\x8d\x60\xbf\xaf\x89\x53\xa7" + "\x58\x98\xc8\xc6\x4f\x3c\x11\x76" + "\xaa\xb5\xe2\x97\xb0\x8e\xde\x80" + "\x04\x13\xb9\x63\xcc\x22\x10\x7e" + "\x6c\x06\xcc\x6c\x05\xb6\xda\x3b" + "\x00\xf9\xed\xb2\x44\xb1\xcb\x33" +
- "\x5b\x8a\xe0\x8a\x3a\x14\x83\xb4" + "\xa6\x2b\x0b\xe6\xa1\x8f\x27\x4e" + "\xfb\x42\x78\x31\x25\x1c\xb3\x24" + "\x08\x38\xcd\x90\x7c\xcf\xe4\xd4" + "\x78\xf8\x5e\x69\x86\x4d\xdf\x5c" + "\xe8\x3a\x9a\x59\x50\xab\x2a\x36" + "\xfc\x44\x58\xb3\x76\x00\xe0\x22" + "\x04\x1a\xe7\xc8\xb1\x6e\x87\xa6" +
- "\xd9\x0d\x72\xce\xff\x4b\x34\x73" + "\xa1\xe6\x3b\xfe\xc0\x16\xa6\x62" + "\x2a\x16\xec\x41\xbc\x17\x41\x30" + "\x0d\x67\x13\x3e\xf6\xb1\xbe\x79" + "\x6d\x3a\x90\x68\xc5\x3f\xaa\xcc" + "\xaf\xfe\x31\xf5\xac\x57\x9b\x99" + "\x55\x30\x17\xdf\xd7\x95\x63\xab" + "\x0f\xf8\x72\xfc\x97\x1d\x7f\x7b" +
- "\xe6\x4a\x28\xa6\xd9\x91\x9a\x48" + "\x6b\x86\xad\x69\x31\xd4\xe6\x47" + "\x97\x7f\x17\x39\x33\xe5\xe5\x93" + "\x80\xeb\x59\x2c\x8a\x2c\x5d\x23" + "\x46\xc5\xe9\x94\x77\x69\xde\xed" + "\x83\x43\x93\xd5\xbc\x75\x42\xf9" + "\x53\x46\x82\xec\xbf\x71\x2f\xac" + "\x8a\x3d\xd0\x17\x67\x09\x52\x14" +
- "\xd2\x15\xf7\x7a\x71\x64\x17\xc4" + "\x96\x4a\x13\xd0\x94\xf5\xf7\xe2" + "\x56\xc9\x1e\xa4\xef\x73\x18\x2c" + "\x04\x13\x82\x77\xf6\xb4\xe7\xe4" + "\x4a\x37\xd5\x88\x97\xff\xc8\xe5" + "\x5b\x3d\x82\x80\x63\x5e\x91\x2b" + "\xe2\x8f\xee\xb2\x55\xc7\x6b\xea" + "\x51\x26\x11\xe7\x4c\x62\x57\x66" +
- "\x15\x49\xcb\x8a\xac\xb3\x30\xfd" + "\x60\x4b\x00\xe1\xbf\x18\x22\x8c" + "\xcc\x5d\xc2\x4d\xfe\x4c\xa6\x80" + "\xda\xb9\xd0\x95\x6e\xf2\x06\x05" + "\x37\xef\xc3\x41\xfd\x94\xaa\xab" + "\x26\xef\xbc\x89\x9d\xd2\x66\x23" + "\x63\xea\xe4\x4b\x8f\xe7\xd0\x6b" + "\x1f\x33\x21\x2e\x5f\xf3\x86\x06" +
- "\xce\xd9\x90\x05\xf3\xc7\x0f\xcb" + "\x3b\xd5\x0a\xea\xd9\xc3\x22\xc0" + "\x33\x29\xba\x84\xb3\x29\xc4\xa9" + "\xcf\x92\xb8\x9d\x36\x52\xe6\xfc" + "\x52\x8d\x51\x1f\x62\x28\x70\x48" + "\x32\x31\x38\x10\x1e\x7d\xdf\x25" + "\x5b\x79\x36\xaa\xbd\x0e\x17\x3f" + "\x47\x7e\x95\x34\x4f\x88\x31\xa9" +
- "\x4a\xf1\x33\x58\xea\xfb\x39\xdc" + "\x33\x0f\xd5\x88\xc1\xa3\x10\xb0" + "\x2c\x75\xf5\x76\xbc\x45\x61\xcd" + "\x77\xde\x12\x7e\x21\x25\x3b\x11" + "\xa5\x39\x18\x04\x66\x78\x41\x62" + "\xd7\x09\xf3\x0e\xcb\x58\xca\x95" + "\x49\x22\xd0\xa2\x9d\xcc\x02\x6d" + "\xbb\x3a\xfd\xb8\x4b\xb5\x45\x87" +
- "\xca\x5a\xce\xda\x01\xf1\x7a\x15" + "\x67\xa2\xa6\x11\xf2\xbc\xfd\xc4" + "\x09\x86\x9c\xc4\x40\xf3\xdd\xda" + "\x65\x4a\x60\xe9\x52\x9f\xe4\x97" + "\xd5\x2a\x7e\x93\x90\xe7\xe8\x9b" + "\xf1\x17\x6e\x32\x08\x25\x6e\x84" + "\xdc\xc0\xbb\x0b\x7a\x00\x38\x3f" + "\xd6\x16\x1e\xb1\x3f\x60\x03\xcf" +
- "\xfe\xbc\xd3\x4e\x0a\x15\x89\x05" + "\xb9\x0c\xd8\x6c\x5c\xb6\x62\xf4" + "\x5d\x1c\x53\x29\xa8\xad\x12\x34" + "\x75\xa6\x14\x2f\xe7\x69\xe9\x90" + "\x4c\x5b\xb9\xc7\x06\x89\x6c\x48" + "\x0c\x78\xb4\xbc\x4c\xa9\x67\x5a" + "\x85\xf9\x2d\xd2\x13\x15\x61\xde" + "\x0c\xe0\x1b\x48\x9a\x86\xb4\xba" +
- "\x1f\x8f\xd9\xb8\xc5\xa4\xea\x2f" + "\x50\x02\x05\x41\x9c\x02\x09\x7c" + "\x2f\x13\x56\x1b\x77\x42\xfa\xd4" + "\xe5\x35\x12\xda\xf1\x57\xb2\xec" + "\xaf\xae\x46\x6a\x58\x21\x7e\x61" + "\xae\x3e\x65\xd4\x00\xf3\xef\x65" + "\x01\x2a\x56\x03\xad\x13\x7a\xf6" + "\x27\x70\xc7\x70\x87\xfa\x7f\x95" +
- "\x2f\x1c\xc1\x46\x90\xc4\xf2\x89" + "\x18\x08\xd5\xd7\xd6\x06\xbc\xbd" + "\xe2\x51\xbe\x82\x60\xc1\xdf\x13" + "\x95\x98\x71\xc1\xf6\x3a\x0b\x71" + "\x75\x84\xdd\x61\x43\x46\xd5\x0b" + "\x29\xe0\x44\x45\xd3\x8e\x8a\xa1" + "\x7d\xbb\x3f\xdc\xcf\xd2\x1a\xe1" + "\x8a\x78\xe8\x79\x9b\xd7\x77\xb1" +
- "\xd5\xf1\x42\x74\xe0\x00\xf8\xd6" + "\xab\xe3\xe0\x66\xd1\x07\x56\x47" + "\x47\x40\xc6\xb7\x16\x7f\x80\x82" + "\x3d\x88\x49\xa7\xe3\xe1\x58\x88" + "\x10\xee\x31\x82\x0b\x12\x59\x58" + "\xce\x1e\x8a\x63\xeb\xe7\x80\x1b" + "\xa4\x73\xaa\xc6\x5a\x52\x72\xcb" + "\xac\x23\x44\x84\x3d\xea\xcd\xa7" +
- "\x3e\xed\x80\x6b\xb0\x8d\x3a\x86" + "\x13\xfa\xd3\x75\xe3\x47\xa7\x19" + "\x01\xf7\xc8\x69\x2e\xcf\x35\x5a" + "\xe9\xbb\xe5\xf8\x13\x04\x9f\x76" + "\x6a\xe5\x64\x1d\xc0\x36\x6d\x3b" + "\x96\x98\x6a\x45\x32\x2b\xd9\xb9" + "\xda\x9c\x8e\xcf\x70\xce\x47\x0d" + "\x64\x98\x01\x6c\x5e\x35\xe3\x19" +
- "\xed\x23\x51\x02\xac\x1a\x10\x7f" + "\x06\x06\xad\x93\xef\x93\x6e\xf1" + "\xd1\x85\xcf\x46\x48\x89\xfe\x89" + "\x0e\x91\x8e\xf7\xcb\x0c\x1d\xe3" + "\x78\xf6\x61\xd5\x1c\xab\xab\xbc" + "\x33\x28\xc9\x87\xc8\xe5\x31\x73" + "\x8d\xf6\x72\x0e\x26\xad\x38\x63" + "\xc3\x05\xdb\x35\x3e\x05\x0c\x80" +
- "\x08\x6b\xb0\xa1\x76\xeb\xe2\x81" + "\xc9\x82\x7e\x8d\x78\x55\xae\x81" + "\x96\x8a\xf7\x48\x38\x3e\xec\x03" + "\x01\x9b\xa3\x81\x53\xf7\xb4\x1b" + "\x26\x8a\xee\xeb\x1c\xb0\x4e\x42" + "\x2c\x8f\xae\xd4\xf5\xf7\x11\x13" + "\xf1\x01\x8c\xaf\x76\xb0\x3a\x15" + "\x77\xc1\x02\x5e\x83\x4c\xc9\x2e" +
- "\x38\x7c\xae\xf8\x07\xc0\xd0\x5e" + "\x92\x01\x74\x3d\x5c\x7a\xb0\x6d" + "\xb3\x6d\xe3\x5f\x2a\x9c\x5e\xbe" + "\x46\x50\xe9\x76\x7a\xd5\xb9\xd5" + "\xf2\x20\xba\x8e\xe7\x32\xac\x54" + "\x52\xa3\xb9\x71\x8f\xca\x11\xef" + "\x58\xa6\x98\xff\x3e\x37\x5e\x30" + "\x67\xb6\x3e\x82\x00\xa1\xe5\xff" +
- "\xcf\xee\x8c\xdc\x00\xc8\xb7\x46" + "\xa5\x94\x59\x81\x2d\x9c\xe4\xd6" + "\xea\x56\x62\xbb\xfc\x14\x78\x6b" + "\x22\x10\x6e\x4a\xfc\x51\x8f\x7e" + "\x38\x20\xde\xca\x83\x53\x80\xf9" + "\xea\xfb\x54\x74\x31\x2f\x76\x9f" + "\x68\x80\x38\x65\x29\x0c\xba\x5a" + "\x51\xb2\x1c\x72\xfa\x61\x75\xa2" +
- "\xcf\x32\x5e\x94\x38\x49\x14\x5c" + "\xa6\x91\x82\x5a\x75\x7e\x99\x9e" + "\xd6\x07\x6e\xfc\x46\xe8\x70\x05" + "\x7d\x44\x74\x1e\x64\x13\x68\xe2" + "\xe2\xf2\x1f\x72\xce\x10\x17\xbf" + "\x3d\xe8\x14\xf8\x19\x08\x45\xea" + "\xd2\x7a\x69\xed\x0b\xa7\xf0\x27" + "\x36\x3f\x6b\x08\x99\x98\x36\x90" +
- "\xdb\xcf\x46\xdb\xfc\x40\xff\xe9" + "\xc4\x94\x7e\x5e\x15\x67\x52\x1b" + "\xbf\xb3\x00\x97\xc5\x6b\x98\xb8" + "\x28\x31\x8c\x0c\x59\xaf\x8c\xc9" + "\xeb\xbb\x1b\x30\x5d\x01\xfb\xd1" + "\xa9\xd1\x2f\xba\x28\x4f\xe6\x18" + "\x70\x5b\x36\xc0\x7e\x78\x12\x92" + "\x04\x6c\x38\x98\xd0\x51\x4b\xc6" +
- "\xd2\x32\x17\xe5\x11\x7b\x47\x57" + "\x0e\xfc\x38\x25\x28\xeb\xd6\xdf" + "\xc5\xee\x39\x3b\xcc\xb0\x43\x5c" + "\x57\xcc\x36\xcb\x78\x27\xf1\x6a" + "\xae\x25\xc4\x06\x2d\x85\xb0\x70" + "\x9b\x1b\x22\x5c\x8c\x2f\xf9\x6d" + "\x9c\x6d\x82\xce\x9e\x4f\x8d\x6c" + "\xc3\x59\x93\xb4\x7b\xba\x9a\xf5" +
-
- "\xa4\x3a\x1d\x42\x2e\x2c\x7e\xc3" + "\x40\xa8\x4f\xe8\x7c\x40\x26\xf9" + "\x1c\xe4\x54\x14\x3d\xc0\xab\x18" + "\x44\xf6\x7a\x3f\xcd\x5e\x60\x26" + "\xbf\xea\xa5\xd6\xa6\x41\x23\x24" + "\x8e\x66\x6b\x21\xf4\x84\xdb\x1e" + "\x02\x01\x01\x04\xb8\xed\x36\xd8" + "\x8c\x1d\x5e\x94\xe7\x7c\x33\x5b" +
- "\x82\xdc\x3d\xd2\x86\x6b\x07\x4c" + "\xf0\x43\x01\x7e\x4c\x34\xfd\x03" + "\xc5\xf2\x7a\x31\xff\x62\x53\xa9" + "\x4f\x7a\x8b\xe1\xb7\x3d\xdd\x0a" + "\x1b\xe0\x60\x82\x3f\x3e\x67\x9c" + "\x91\xcc\xa1\x54\xe5\x49\xeb\xfb" + "\x33\xe4\xf2\x92\xf2\x1b\x35\x91" + "\xeb\x41\x11\x85\xec\xe7\x55\xc7" +
- "\x04\x38\x9f\xda\x68\xe3\x9a\x34" + "\x9c\x34\x64\xa1\xfe\x07\x0f\x47" + "\xa5\xba\x62\x85\xc9\x4c\x2f\xd5" + "\xf3\x0d\x29\x2b\x86\x9e\x4a\xc7" + "\x24\x1a\x47\x43\x35\xaa\xa1\xd3" + "\x11\x45\x19\xb8\xbe\x46\x94\x23" + "\x4d\xd4\xdc\x81\x00\xdd\xc2\xbe" + "\x2d\xc8\x2a\xc4\x0f\x7f\x3d\xca" +
- "\xd5\x06\x32\xf2\x47\xdb\xf5\x2b" + "\x52\x01\x26\x1d\x20\x34\x6d\x2f" + "\x9a\xf8\x8f\x3f\x53\x76\xb8\x17" + "\x58\xa4\x8f\x37\x0c\xc3\x57\x51" + "\x36\xb9\x4f\x2d\xc5\xc5\x17\x75" + "\xdc\x8c\x51\xe6\xac\xf7\x22\xef" + "\x64\x7a\x84\xbf\xe6\x83\xb4\xde" + "\x89\xfa\xe0\x92\x58\x45\x08\xf5" +
- "\x60\x31\x58\x9b\xa6\xc2\x18\xb4" + "\x94\x91\xe5\xb4\xd4\xfc\x74\xbe" + "\xff\xe3\x83\x3c\xaa\xee\x78\xf1" + "\x9b\xf2\x96\xe2\x95\xf8\x51\xe0" + "\x4a\xb8\xce\x06\x38\x52\x23\xd0" + "\x6b\xfe\x11\xe1\xce\x48\xce\x5a" + "\x45\x55\x04\x1c\x49\x3a\xe4\x40" + "\x46\x21\x52\xdd\xdd\x86\xfa\xf3" +
- "\xb5\xc5\x8e\x90\xfa\x16\x96\x95" + "\x2d\xb1\x1a\xa0\x1d\x66\x2d\x88" + "\x8a\xae\x82\x43\x82\x60\x9f\xc4" + "\x5e\x3f\x13\x5d\xeb\x92\xdf\x5c" + "\xc1\xc9\xf6\x5e\x42\xcc\xce\x98" + "\xee\x84\x4d\x66\x82\x66\x2d\xb5" + "\xc4\xb8\x25\x6f\xd8\x5e\x28\x9e" + "\x88\xbe\xde\x48\xc7\xcd\x80\xeb" +
- "\xa0\x2b\x22\xec\xc1\x94\x97\x2d" + "\x48\x5d\x3e\x52\x2f\xf4\xdf\xc3" + "\x6b\x84\xe4\x0f\x70\xd5\x7c\x4a" + "\x74\x51\x13\xff\x13\xb1\xc5\xef" + "\x85\x5e\xb0\xc6\x5b\xb2\x30\x26" + "\x77\xd0\x4c\x65\x29\x30\x6d\x0a" + "\x9d\xb8\xd8\x32\x4f\xf5\xf1\xb4" + "\x27\xfc\x27\x16\xf2\xaf\x3b\xde" +
- "\xd4\x04\x73\xdf\xd8\x59\x96\xab" + "\x8e\x0e\x21\xff\x1b\xcf\x1b\xb7" + "\x60\xbd\x3f\xd7\x8b\x43\xa2\xa9" + "\xde\xb4\x11\x5d\x1f\xcd\x95\x45" + "\x9d\x85\x35\x48\x9a\x32\x0d\x9c" + "\x56\x6e\xbb\x7d\x2d\x0d\x0f\x4a" + "\x4e\x8a\x92\xdf\x5e\x8e\x03\xc6" + "\x54\xd1\x5a\x8f\x21\x96\x42\xc9" +
- "\x3e\xdf\xa2\xa4\x3b\xb8\x83\xb8" + "\x63\xa3\xe5\x44\xc2\x7c\x5b\x04" + "\xde\x96\x0d\x4e\x73\xd7\x2b\xa4" + "\x65\xc1\x93\x8d\x47\x75\x25\xb9" + "\x8e\x13\xc8\x73\x26\x01\xf9\xe8" + "\xbf\x84\x7d\x60\x4d\xe7\x8e\x5a" + "\x63\x43\xea\x49\x50\xbb\xec\x1b" + "\x86\x32\xda\x5a\x14\x61\x4b\x1d" +
- "\x15\x3b\x09\xaa\xb5\x78\xb6\xeb" + "\x0c\xb4\xe2\xd3\x44\xdf\xac\x0e" + "\x9f\x19\x89\x20\xc4\x23\x42\xbc" + "\xa4\x06\x0a\x49\xb4\x2b\x25\x0e" + "\xf7\x5d\x2c\xcc\xb5\x79\x64\x1e" + "\x8a\x32\x94\xba\xd2\x22\x69\x8b" + "\x8c\x94\x8b\x21\xe7\xcc\x78\x42" + "\x39\x4f\x06\xe6\x5c\x99\x7e\x94" +
- "\x94\x69\xd9\xf1\x65\x2d\xf3\xcd" + "\x18\x2b\x5b\xb7\xf3\xd8\xb3\x8b" + "\x98\x77\x30\xcb\xa3\xd2\x95\x5a" + "\xb5\xa8\x15\xcb\xcc\x29\x86\xdf" + "\x26\x49\x8c\x54\xbe\xdc\x5b\x37" + "\xa6\xb3\x25\x3c\xc6\x58\xad\x94" + "\x88\x48\xac\x8f\x52\x0d\x4e\xe9" + "\xe3\x5b\xba\x69\x46\x77\xbe\x9c" +
- "\xc4\x6e\x0c\xa7\x40\x38\xa3\x08" + "\x95\x11\x31\xe0\xf7\x19\x88\x9e" + "\x02\xb2\x8a\x70\x96\x9d\x20\xed" + "\x27\x3a\x94\xce\xe7\xc4\xd7\x10" + "\xa1\x49\x9b\xa2\x17\xb3\x2f\x37" + "\x1f\x7d\x62\x46\xb3\x7f\xa6\x57" + "\xec\x39\xdf\x7c\x1e\x56\x12\xf9" + "\x17\x8f\x7c\x6f\xf2\xe6\x3c\xfa" +
- "\xc1\xed\x2f\x78\xe7\x6d\xc1\x04" + "\xc4\xe7\x3a\x09\x1a\xc1\xe2\xfe" + "\xb1\x90\xde\x3d\x85\x7d\x7a\x35" + "\xdc\x23\x69\xce\xf2\x6a\x13\x68" + "\x36\x45\x86\x8e\x44\x9b\xaa\x0a" + "\x2f\x1c\xaa\xfe\x52\x34\xb5\x16" + "\x55\xd9\x46\x59\xd1\x94\xf4\xe8" + "\xe3\x69\x15\x3b\x51\x16\x31\xb5" +
- "\xe7\xe3\x51\xbe\x7d\xfd\xeb\xdd" + "\x31\x68\x02\x7f\x40\xfc\x25\x0b" + "\xd1\x5f\xe4\xac\x3b\xad\x3b\x4f" + "\xa7\x09\x68\x70\xba\x32\xb3\x8c" + "\xca\x3f\xb9\xd6\xb1\x60\xe1\x40" + "\xed\xbd\x28\x8b\xdf\x8e\x36\x85" + "\xfd\xc2\xb4\x90\x8c\x0a\x6f\x26" + "\x4f\xd2\xaa\xff\xf6\x87\xd9\xaa" +
- "\x3b\x62\x1b\x4e\x42\x0d\x31\x9f" + "\xa5\x66\x62\x81\x9b\x74\x45\xf0" + "\x27\x78\xdb\xa0\x51\xd7\x4f\x94" + "\x59\x72\x1d\x68\xa6\x0d\x12\x80" + "\x88\xc5\xa9\x31\x0d\xd2\xcd\x00" + "\xf1\x4b\xae\x97\xd3\xab\xf2\x7b" + "\x6a\xc0\x08\x6b\x90\x22\x5a\xf7" + "\x8b\xdc\x12\x4a\x84\xe5\xa3\x0f" +
- "\x92\x2d\x3f\xf2\x62\x34\x21\x91" + "\x78\x40\xb9\x60\xbd\x71\xab\x6c" + "\x20\xde\x6c\x17\x63\x0a\xdd\x6b" + "\xbc\x54\x4d\xee\x0c\xb2\xc9\x54" + "\x2f\xc0\x2a\x9f\xaa\xd8\xd2\x3c" + "\xb0\xed\x6e\x20\x17\xe6\xf8\x03" + "\x34\x64\x08\x93\x16\x8e\xf6\xc7" + "\xb9\x3d\xdd\x92\xc5\x69\x14\x83" +
- "\x41\x22\xba\x69\xfe\x2c\x5e\xf3" + "\xbd\xd5\xf4\x8c\xe0\x6c\x44\x95" + "\x92\x4f\xdb\xb8\xcd\x1b\xba\xdc" + "\x58\xd9\x70\x59\x8e\xae\x79\x96" + "\x4b\xb9\xd5\x40\x45\xb4\x9c\x95" + "\xd2\x1f\xa3\x33\x14\x78\x56\xad" + "\xc1\x2b\x00\x1b\xd1\xc3\xd4\xc7" + "\xe3\x53\xc8\x8a\xcc\x81\xa2\x59" +
- "\xcd\xb1\x28\xdd\xc0\xae\x75\xfd" + "\xc2\x4d\x37\x7a\x05\x02\x12\xc7" + "\x2f\x62\xf0\x08\xe4\x2b\x6a\xab" + "\x58\x8b\x26\x12\xa1\xd0\x4a\xcb" + "\x94\x3a\x19\xf5\x7c\xed\xf8\x34" + "\x2b\x9c\x45\x1c\x7e\x16\xcd\xba" + "\x74\xe2\xbc\x57\x54\x62\xcc\x24" + "\xec\x60\x40\x2d\xa8\x64\x71\xf4" +
- "\x1b\x75\xac\xe2\x5a\x6e\x5d\x0f" + "\x69\x45\x4d\xd4\xf3\xb3\x09\xc6" + "\x33\x4c\x96\x0b\x80\xac\xc4\x38" + "\x05\xc5\x43\xc1\x1b\x45\xf9\xde" + "\x86\x75\x4d\x39\x95\x92\x1f\x98" + "\xd1\xa6\x58\xd0\x9b\x1e\x0d\x4c" + "\x3d\x80\xe8\x07\x1c\xcf\xa4\x76" + "\xd6\x01\xdd\x4d\x33\x76\x5f\x2b" +
- "\x5f\x3c\x3f\x65\x65\x74\x7d\xfe" + "\xb1\xfe\x40\xf0\x5e\xd4\x3d\x28" + "\xfe\xed\xb7\xf3\x9b\x59\xfe\x91" + "\x11\x93\x37\x80\xad\x39\xf0\x5f" + "\x49\xfa\x96\x4e\x5b\x99\x76\xbf" + "\x94\x50\xe2\xa3\xb2\xb6\x40\x26" + "\x74\x3f\xc8\xc1\x41\x63\x09\x8b" + "\xc3\x0a\x56\xfa\x84\xc8\xbe\xd2" +
- "\x05\x14\xf3\xb9\x6b\x57\x6b\x09" + "\x5e\x2b\xb0\x62\x87\x22\xfc\x40" + "\x18\x61\x2f\xe6\xbb\xbd\xb2\x42" + "\x1a\x49\x03\x73\xf7\x80\x8d\x62" + "\x96\xbe\x33\x8f\xfd\xd8\x7e\x89" + "\x0a\x8d\x49\x48\xca\x69\x56\x4d" + "\xef\x9d\x9c\xe9\x1a\x40\x4c\xf7" + "\x5a\xb8\x44\x65\x5b\xeb\x38\x79" +
- "\x88\x12\xf2\xe7\x12\xd3\x0b\x43" + "\x33\xe3\x94\x87\x25\xa7\x81\x73" + "\xfc\xd2\x53\xb2\x8b\x2f\x5d\x94" + "\x9e\xff\xa3\xbe\x85\x35\x59\x79" + "\x06\x60\xaf\x8d\x7f\xf6\xc3\xb0" + "\x77\xd8\xa6\x19\x85\xd0\x48\x78" + "\x4f\x1b\x21\x62\x1b\x70\x38\x6e" + "\x6d\x39\x06\x05\x6e\xf0\x07\xaf" +
- "\xff\xb8\xfa\x91\x8d\xc8\x9a\xe5" + "\xed\x96\x7c\x3f\x0e\x1c\x5e\x2f" + "\x79\x50\x08\xb4\x16\x8a\xf2\xff" + "\x9f\xc0\xe0\x94\x9e\x5f\x76\x8d" + "\xbe\x37\x03\xa0\xce\x3e\xa5\xd2" + "\x88\xd0\xfa\x4a\xbd\x5d\x21\x98" + "\x20\x89\x23\xa9\xa9\x6f\x2b\xa3" + "\x2a\xed\xd9\x64\x15\x80\x65\xe1" +
- "\x54\x13\x98\x8f\x24\xdf\x21\x85" + "\x59\xa2\x88\x35\xec\x23\x7e\x58" + "\x2c\x99\xa0\xd7\x81\xf2\xed\xcb" + "\x07\x14\x96\x38\x55\x0a\x93\x06" + "\x21\xbe\x5b\xbe\xeb\x0d\x32\x09" + "\x7f\x81\x91\x24\xb5\xa5\xff\xa7" + "\x60\x51\x06\x09\xd9\xb4\xc8\xe6" + "\xa9\xd2\xf6\xff\x92\x39\x4f\xac" +
- "\x76\x9c\x7b\x56\xf5\xc8\x5d\x5c" + "\xc6\x9a\xd1\x96\xbe\xcc\xe0\xaa" + "\x5f\xa2\x26\xcf\xa8\xf8\x71\xd4" + "\x08\x52\x36\x37\x4a\x70\xf9\x1d" + "\x05\xda\x45\xa1\x1b\x54\xbc\xab" + "\xaf\xd8\xb7\xf5\x3d\x32\x43\x9d" + "\xdd\x53\xe2\xf1\x92\xb0\xaf\xa3" + "\xcf\x36\xcb\xdb\x79\xeb\xa7\xc4" +
- "\x23\x91\xaa\xa3\x15\x6f\x4d\x2e" + "\x42\xd3\x4d\x38\x8c\x9c\xff\x33" + "\x0c\x1b\x2d\x8f\x17\x86\x16\xb0" + "\x62\x05\x6d\xbd\x7d\xd8\xae\x66" + "\xe8\x66\xa4\x4e\xac\x76\x31\x40" + "\x7b\xbe\x10\x1e\x0c\x8f\x4d\x15" + "\x4b\xa4\xd1\x58\x76\xf7\x75\x5f" + "\x05\x39\xa5\x33\x10\x98\xb2\xc9" +
- "\x01\xb1\x7f\xa4\xf5\x73\xbd\x56" + "\xfb\x59\xbf\xfb\x84\x86\x25\x36" + "\x2b\x84\x4c\x86\x38\xdd\xc8\x43" + "\x03\x87\x4e\xf5\x92\x65\x46\xf1" + "\xc5\x78\x06\xd1\x92\xc3\x37\x11" + "\x8a\x91\xd5\xf0\xde\x82\xa8\x86" + "\xd0\x33\x10\x2d\x4d\xd2\xe1\x8e" + "\x26\xe9\x76\xe3\x62\xe1\x9c\x64" +
- "\x66\xda\x53\xcc\xa3\xb2\x4e\x2e" + "\x4e\x9b\x7a\xf1\x71\x8a\x70\x04" + "\x2c\x5b\xe0\x0d\xb2\xc7\xfd\xdb" + "\x01\xa2\x07\x49\xee\x9a\xdc\x4c" + "\x66\x55\x47\x6c\xfc\x8d\xcc\xe5" + "\x91\x16\xbe\x47\xfb\xcb\x83\x2b" + "\xfd\xc3\x05\x4c\xa7\x33\x58\x69" + "\xb0\xde\xb0\x43\x72\x8a\x93\xee" +
- "\x0f\x8f\x42\x3f\x77\x25\x86\x07" + "\x1f\xed\x3d\x4c\xa9\xdb\x63\x9b" + "\xbd\x51\x67\x35\x44\xae\x2a\x85" + "\x80\x1c\x2f\x3b\x11\x49\xec\xe2" + "\xfb\x20\xc4\x73\x54\xf3\xb0\xed" + "\xc3\x55\xc2\x0b\xab\xcc\x63\xd6" + "\xa9\x46\xae\xcf\x5d\x01\x3e\x1c" + "\x84\x7d\x18\x1f\x99\x89\x55\x98" +
- "\x1a\x3d\x8b\xb7\x1e\x4f\xd3\x2c" + "\x0e\x4c\xf8\x5f\xc6\xfa\x13\x17" + "\x60\xec\x9c\xc2\xc9\xfa\xe9\xde" + "\x52\xa5\x7a\xb2\xfd\x7b\x91\x53" + "\x9f\x12\x64\xee\x4d\x53\x6f\x89" + "\xe0\x1e\xeb\xdb\xf2\x23\xa5\x76" + "\x27\x11\x59\xd2\x09\x33\xc1\xe1" + "\x6c\xf6\x4c\xad\x57\x1d\x6f\x87" +
- "\xa9\xa3\x76\xb5\x89\xc7\x32\xc6" + "\xc8\xd7\x0d\x69\xf2\x21\xc0\xcf" + "\x6d\xad\x84\xeb\x32\xea\x55\xcf" + "\x66\x95\x05\x72\x2b\xb7\x70\x61" + "\x28\xf2\xa5\xcf\x10\x56\xa0\xfb" + "\x1a\xbf\x4c\x89\x15\xdd\xb3\xc1" + "\x36\xf4\x4f\x31\xf0\x24\xc5\xc6" + "\xdd\xff\xa1\x07\x61\x0c\x7e\xb2" +
- "\xbd\xc1\xe9\x3a\x58\xa1\xa7\x7a" + "\x40\xe2\x7c\xe3\x98\x6d\xaf\xe0" + "\xb4\x38\xab\x28\xd9\x42\x43\xe5" + "\xca\x98\x1c\x0a\x07\x50\xb7\xe8" + "\xf2\x58\x23\xe0\xaf\x86\xce\xef" + "\x28\x12\x92\xea\x56\xb8\xb8\x31" + "\xfc\x67\x1c\x0a\x12\x19\x2a\x05" + "\x59\xad\xae\xe3\xa4\x9e\x06\xb4" +
-
- "\x19\xf0\x8d\x55\x9e\x43\x51\x9f" + "\x27\x2b\x71\xac\xba\xa4\x0d\x23" + "\x24\x5a\x18\x55\xe3\x19\x89\x51" + "\x50\x8f\xb7\x84\xdd\xfc\xce\x4d" + "\x5a\x4c\x7d\xa4\xb2\x0f\xd9\xa7" + "\x9e\x00\x0e\xb3\xbf\x9a\xac\x55" + "\x73\xd2\xee\x74\x59\xc3\x2f\xfd" + "\xaf\x8f\xea\xdb\x4c\x82\x2d\xb7" +
- "\x89\x92\x7d\xef\xb5\xb2\x9d\x54" + "\x5a\x01\x7f\x19\xa8\xd4\x80\x24" + "\xb6\x93\x04\xc4\x0b\x59\xd5\x61" + "\x31\x03\x78\x6f\x2e\xb5\x55\x3a" + "\xb0\xad\x9e\x30\x15\x81\xeb\x40" + "\x25\xc6\xe5\x92\x5a\xde\xa7\xde" + "\x5a\x3d\x6a\xcc\xf0\x31\xd6\x64" + "\x61\xdd\xe8\x93\x7c\x9d\x5e\x9d" +
- "\xdd\x2b\xc8\x04\x8d\x58\x7a\x1b" + "\xfd\x9d\x31\xf8\x34\x55\x00\x68" + "\x80\x95\xeb\xd8\xb5\x55\x8a\xde" + "\x81\xca\x5b\x8d\xda\x86\xa8\x5e" + "\x4d\x0b\x2a\x25\x01\x0a\x53\xe8" + "\xa1\xa0\xea\x35\xfe\xb4\xff\x1b" + "\x63\x95\xe9\xd8\xb1\x28\xd8\x2a" + "\x87\xcd\xf9\x95\xf5\x6e\xe9\x7d" +
- "\xe5\xe0\x84\x1e\x41\x60\x68\x19" + "\x93\x4c\xa3\xae\xd3\x84\xdb\xa5" + "\x32\xa7\x73\x70\x19\xbb\xd5\xf9" + "\xc0\xd7\xcf\x6b\x56\xfe\xd2\xb8" + "\xfa\x82\xeb\xf3\x36\x5f\x77\x45" + "\x58\x8b\xff\xfd\xcc\x0c\xb2\x8c" + "\x10\xc1\x74\x83\x5f\xb6\x59\x16" + "\x9a\x78\x0c\x33\x22\xa4\xb4\xb8" +
- "\xdc\x73\xa9\x7e\xe5\x41\x57\x74" + "\x2e\x8f\x88\x20\x70\xca\x00\x5c" + "\xf1\x9c\xfd\x45\xcf\xe3\xdc\x7c" + "\x72\xf8\x07\x55\xf1\x1e\x74\x8a" + "\xec\x4c\x6b\x19\x2f\x1c\xc5\x47" + "\x18\xa6\x7e\xc9\x43\x8e\xd0\x70" + "\x2b\x8a\xb1\x15\x5c\xa1\x0d\x93" + "\x14\x05\x61\x2f\x78\xc6\xb6\x33" +
- "\x9f\xae\xdb\xae\x87\xff\x25\xc9" + "\x54\x0a\x88\x36\xb9\x0e\xaf\x7d" + "\x71\x0e\x4d\x9c\xf5\xdd\x84\x92" + "\xf5\x8c\x6f\x31\x93\xcf\x81\x15" + "\x52\xf4\xc1\x3a\x87\xa8\xec\x3e" + "\xfe\xef\x6a\xfb\xe9\xfc\x17\xb4" + "\xc3\x8d\xfb\xee\x46\x80\x91\xa5" + "\x00\x94\x20\x02\xac\x18\xd3\x73" +
- "\x8b\x78\x85\x9a\xda\x35\xa5\x6b" + "\xd4\x26\x06\xbd\xae\x03\x1f\xd2" + "\x64\xdc\x73\xe8\x47\x8c\x9f\x09" + "\x7e\xc9\x8e\x01\x4d\x56\xa8\xcd" + "\x8c\xc6\x92\xde\x5c\x7a\x8d\x3e" + "\xc4\x3c\x32\x73\xa1\x35\xe0\x78" + "\x7c\xff\x80\xf8\x75\x62\xf2\x3e" + "\xaa\xed\x3e\x27\xff\x3d\xee\xa4" +
- "\x2f\xbc\x2e\xaf\xa3\xcd\xf4\xc4" + "\x24\xfe\x4e\xcb\x3d\x84\xaf\xa0" + "\xb1\x10\xcd\x9c\xc1\x57\xb8\x53" + "\x04\x3e\x4d\x91\xeb\xd1\xc9\xdd" + "\xeb\x1d\x77\x62\xbb\xc8\xde\x7b" + "\x81\xaa\xc5\x91\xaa\x77\x92\x82" + "\xae\x91\x23\x83\xd6\x8d\xf1\x7a" + "\xca\x84\x1a\xc7\x16\xf3\x40\x17" +
- "\xed\x73\x6d\xa5\x88\x5c\x9e\xba" + "\xd3\x54\xa0\x2c\x71\xf7\x24\x6c" + "\xe1\xea\x3b\x08\x35\xc2\x37\x4a" + "\xfd\xe9\x83\x64\xb2\x83\xa8\x04" + "\x5d\x2c\x7c\xe2\xae\xf3\x63\x0c" + "\xf1\x71\x46\xae\x8d\xa8\x1d\x0e" + "\xdb\xe1\x95\x59\xe2\xe8\x77\xa5" + "\x6a\x06\xd6\x6e\xb1\xb1\xc4\xbf" +
- "\xf8\x31\x2b\xe1\xd8\x12\x4a\xdd" + "\xe6\x36\x77\x17\xbc\x29\x7e\x57" + "\xe8\x35\x89\xa8\x2b\x72\x53\x23" + "\x6d\x28\x5f\x01\x29\x37\x1d\xca" + "\x35\xe0\xa3\x39\xa2\xb6\xc7\x86" + "\x9f\x3a\xb0\xd3\xbf\x50\x52\x6e" + "\x6e\x53\x0d\xfd\x30\x89\xd9\x79" + "\x32\x38\x0c\xfa\xab\xbb\x4c\x8c" +
- "\x39\x23\x3b\xa4\xc9\x38\x9b\x16" + "\xab\xbf\x32\x17\xd9\x08\x43\x88" + "\xdd\x02\xf2\x8f\xa2\x93\xb5\xe4" + "\x6c\x37\x65\x1e\x1f\xd1\x51\xaf" + "\xff\x25\x15\x74\xde\x48\xc6\x6e" + "\x28\xc6\xf4\x9f\x36\xbd\x3c\xf9" + "\x79\x9c\x12\xb1\xef\xf9\x6d\xc7" + "\x94\x72\xa6\xb7\xe2\xf2\xa5\x31" +
- "\x1e\x1f\xb9\xca\x10\x09\x50\x2d" + "\x16\xd2\x1c\x4d\x44\x9e\xdd\xbe" + "\x52\x22\xd0\xed\x4f\xb7\x34\xd6" + "\x7a\x61\x58\x12\xe1\xf8\x60\xbd" + "\x4a\x61\x05\x9e\x7b\x53\xc7\xd8" + "\xc5\x5f\xaf\xe7\x66\xc7\x26\xfd" + "\x26\xd9\x2b\x58\x81\xb5\x60\x06" + "\xc8\x7f\xf0\xac\x44\x92\x01\x87" +
- "\x8e\xfe\xdc\xba\x22\x73\x3b\x2c" + "\x04\x5a\xe2\xc5\xfa\x16\x06\x6e" + "\xa2\xe4\xa6\x3d\x75\x12\x3c\x0a" + "\x01\xca\x7b\x07\x7e\x95\x6c\xe4" + "\x4b\xe6\x4b\xda\xe3\xa4\x6c\xb4" + "\x78\xee\x75\x8e\x66\xda\x9b\xa5" + "\xf2\x98\xde\xa4\x84\x51\x83\x41" + "\x68\xa5\xd6\x4e\x92\x1f\xfb\x6e" +
- "\xb6\xec\x64\xaf\xcf\x6c\xa2\xaf" + "\x75\x27\xd7\x4b\x97\x4f\x05\xe6" + "\x5a\x69\x0f\x14\x5b\xab\xcb\xbb" + "\xde\xef\x48\xe3\xa4\xb4\x71\xbc" + "\x63\xd9\x96\xcc\xbe\x52\x2e\xfc" + "\x18\x90\x5d\x5e\x5f\xbf\x0a\x15" + "\x71\x87\x56\x04\xa6\x2f\x18\xbd" + "\x83\x9f\x33\x70\x61\xc0\xb4\x35" +
- "\x05\x06\x37\x11\xb3\xb9\x41\x47" + "\x55\xb3\x09\x5d\xf7\x72\xfa\x47" + "\x6a\x4c\x14\x7a\xac\x71\x1a\x39" + "\xca\xe3\xb6\x98\xf4\xc0\x08\x08" + "\x00\x39\xe5\x7f\xef\xd9\xae\x7e" + "\xba\x30\xa8\xe5\xa5\xa2\x57\xf1" + "\xfc\x4a\x97\x27\x91\xc0\x3e\xd1" + "\x7d\x99\x87\x0b\xa7\x10\xd7\x78" +
- "\x49\x8c\xaf\xee\x9a\xe9\x28\x89" + "\x28\xd7\x24\x6e\x3d\xa7\x7a\xee" + "\x6c\x15\x2b\xe7\xc2\x07\x50\x4c" + "\x1d\x8a\x40\xed\xc5\x57\xcf\x5f" + "\x04\x76\x05\xb6\x39\x9e\x71\x9f" + "\xbf\x8b\x86\xc2\x01\x3c\x34\x7d" + "\x2d\x3e\x10\x7e\x4b\x25\xca\x2c" + "\xa2\xbe\x31\xf1\xa9\x38\xeb\xe6" +
- "\x11\x19\x20\xcd\xec\xd3\xe1\x27" + "\xeb\xc0\x72\xad\x70\x9a\x11\xb1" + "\xfb\x7f\xb5\x6a\xaf\xe3\xb3\xf8" + "\x2b\xc4\x92\x5b\x5b\x68\xc1\x23" + "\xaf\x7a\x8d\xd0\xb9\xb7\x27\x2c" + "\x1c\x59\x9a\x18\xc3\x0d\x66\x0f" + "\xca\x43\xc8\xad\x02\xa1\xca\x7b" + "\x52\x76\xb2\x1a\xb4\x8b\xd3\xde" +
- "\x52\xff\x40\x5f\x4e\xa0\x24\xc6" + "\x4a\x91\xd2\xfc\xcf\xd7\x11\x36" + "\xd6\xbf\xd3\x1f\x2b\xb4\xe8\xb7" + "\x3a\x06\x85\xfa\xfd\x40\xde\x6c" + "\x5b\x7e\x8b\x17\x49\xc4\x11\x78" + "\x13\xcc\x72\x29\x31\x09\xb6\x4c" + "\x35\x61\xb4\x33\x5e\x12\x79\xf5" + "\x6e\xe5\xa4\x88\xf7\x2e\x10\xca" +
- "\x84\x0b\xef\x5d\x7f\x67\xbd\x96" + "\xb9\x99\xde\x97\x7b\xa8\x6f\xe9" + "\x53\x15\xbe\x4e\xc1\xfe\xd3\x5d" + "\xcd\x75\x42\x7e\xe6\x43\x57\x31" + "\x23\x83\xb4\xb1\x25\x31\xf1\x81" + "\x75\x8e\x49\x4d\xdd\xb1\xaf\xc4" + "\xd9\xda\x15\x3f\x7d\x8e\x56\x84" + "\xb8\x73\xae\xa3\x1b\xa6\xe3\xd8" +
- "\x0d\x1b\x98\x0a\x52\xe3\xa4\x0b" + "\xa4\x41\x1a\xbd\xb3\x4c\x35\x1c" + "\x9c\xab\x9f\xdf\x3a\xaa\xab\x1a" + "\xd5\x18\xc4\x53\xd1\xa7\x01\x07" + "\x21\xb9\xf2\xdc\xef\x7c\x1a\xdd" + "\x61\x80\xf4\xbc\xb3\xf0\xee\x6c" + "\xe6\xcc\x25\xde\x98\xb5\x83\x10" + "\x34\x5e\x0a\xe9\xc7\x54\x0a\x89" +
- "\xf4\xca\x02\x1c\x42\xb4\x2b\xa6" + "\x5a\x7b\x62\xdb\x1d\x48\x74\x6a" + "\x2d\xf5\x6b\x2c\xf6\x25\x56\x1d" + "\xa0\x46\xb2\x73\x4c\xfd\xc5\x1f" + "\x3d\x81\x31\x17\x62\xfc\x6d\x3f" + "\xbe\x54\x88\xe5\x79\xdf\x22\x83" + "\xe4\x2e\x8b\xfa\xb2\x38\x14\xe5" + "\xa0\xcd\x4a\x2d\x48\x78\x73\xbe" +
- "\x07\x18\xac\x40\x66\x95\x35\xc5" + "\x1e\x0b\xda\x84\x66\xe5\xc1\xd4" + "\x21\x24\xb8\xe0\x97\x3f\xb3\xc4" + "\x00\xbe\x41\x7b\x17\x23\xbd\xd0" + "\xe1\x72\x7b\x14\x2e\xb4\xa4\x53" + "\x4c\x10\x77\xf7\x5f\x9f\xd3\xf8" + "\x0d\x53\xfb\xd3\x64\x4e\xe6\x36" + "\xdd\x4f\x07\x56\x67\xba\xa6\xa7" +
- "\x71\x7c\xca\x1e\xe3\x8f\x65\x1b" + "\xb8\xda\xad\xe4\x14\x52\x94\x20" + "\x99\xc2\xf9\x11\x3f\x5d\x4e\x7d" + "\x04\x50\x84\x2f\xe7\x2a\xf6\xd7" + "\x92\x1e\x2a\xe2\x6a\x6d\x7e\x41" + "\x41\x71\x4c\xca\x85\x7f\xb6\x1a" + "\xed\xb5\x9a\x27\xc0\xd9\xb2\x44" + "\x11\xce\x57\xfa\xb8\xf0\x0b\x2d" +
- "\xb1\x01\x6d\x4f\xdb\x18\x57\x40" + "\xa0\xe8\x11\x8f\xc2\x6b\x3c\xe7" + "\x3b\x1a\x59\xa0\x8c\xbb\x11\xac" + "\x31\x45\xcc\x0a\x5a\x9a\xd0\x12" + "\xf4\x13\xde\xe7\xee\x74\xf1\xcb" + "\x82\xd6\x4f\x04\xe6\x2b\x7e\x17" + "\x70\xaf\x48\x1c\xcb\x74\xf5\x65" + "\x7c\xcb\x61\x99\x92\x66\x59\xce" +
- "\xe9\xba\xf6\x10\xfc\x6b\x83\x64" + "\x08\x76\x08\x0a\x6e\x61\xd5\x6b" + "\x07\x78\x0b\x2f\x63\xc4\xd5\xcf" + "\x78\x85\xa0\x61\x12\x27\x68\x05" + "\xcd\x2c\x0f\x63\x77\x37\x30\x30" + "\x40\xab\xe2\xc2\x32\xa7\xfd\x9e" + "\x92\x95\x0f\x6b\xc5\xb1\x95\xca" + "\xd8\xf2\xf2\xd0\x3e\xb2\x8f\xf7" +
- "\x9f\xab\x6f\xbc\x4e\xe8\x9f\x98" + "\x74\x64\x0f\xc8\xb1\xe6\x0c\xe7" + "\xbc\xa1\x02\x3b\x05\xf3\x9f\xbe" + "\xd3\xaf\xc0\x99\x66\x48\xef\x12" + "\x26\x1a\x41\xe3\xf9\x57\xd9\x22" + "\x98\x5b\x48\x7b\x81\xd8\x41\x0b" + "\x19\x01\xe2\x4a\xd0\x56\x0e\x82" + "\xe0\x28\x85\x32\x1f\xd0\xe3\x81" +
- "\x8a\x7c\x82\xbe\x77\xd4\x7d\xd4" + "\x4d\xe4\x10\xec\xe7\x69\x4a\xee" + "\x7c\xd7\x0e\x13\x38\x60\x23\xaf" + "\xf0\x65\x4c\x80\xce\x5c\x04\xf2" + "\xdb\x70\x4b\x2a\x03\x19\x87\xfb" + "\xf5\x9f\x3c\xb3\xcc\xb3\x36\xff" + "\x3d\x78\xd2\x1f\xe6\xf2\x37\x4c" + "\xd6\x71\x00\x91\xde\x7e\x11\xe5" +
- "\xa1\x52\x87\x04\x6c\xed\x9e\xc5" + "\xb4\x41\x13\xa0\x2e\x70\xf2\x41" + "\x92\xb0\xc6\x9d\x3b\x90\x35\x6e" + "\x23\x5b\x5b\x1f\xa8\xab\x91\x42" + "\x1d\xd6\x53\xa6\x70\xaa\x73\x81" + "\x1e\xb5\x2e\x4f\xd4\x48\xb6\xd1" + "\x8f\x3f\xb9\x5a\x06\xce\xb7\x31" + "\xfe\xf4\xe2\x99\xee\x08\x54\xa5" +
- "\x04\x44\xdc\xda\x8b\xfa\xc4\x1b" + "\xe3\x2e\xa1\xda\x34\x95\xdb\x0e" + "\x9c\x28\xf7\xa5\xb6\x81\x44\x08" + "\xd2\xb3\x8f\x9d\x1d\x46\x42\x7f" + "\x70\x3c\x29\x12\x32\x1d\x3f\xf9" + "\xa3\x3e\xb7\x6b\x59\x06\x47\xc1" + "\xad\x9c\x33\xde\xaf\x34\x08\xf8" + "\x53\x29\xf2\x81\x00\xfc\xdc\x99" +
- "\x60\x41\xe3\x85\x09\xed\xa4\x1f" + "\xe2\xcd\x03\x7a\xc3\x7d\x6d\xa2" + "\x2d\xdf\x84\xfa\x48\x08\xac\x1d" + "\x08\x71\x69\x1b\xd6\x28\x9a\x5e" + "\xa1\x0e\xea\x14\xd9\x04\x80\xa8" + "\x20\x55\xfe\x3f\x28\x54\xd1\xa8" + "\x9c\x13\x9b\x63\xae\x2d\x42\x4f" + "\x61\xa8\xb5\xd4\x0d\xcc\xdc\xee" +
- "\xcd\x8e\x74\xd7\x36\x16\x1d\x54" + "\x2e\x5c\x86\x7b\xf0\xab\x5a\x38" + "\x31\xe4\xdc\xe1\xec\xf9\xc2\xd2" + "\x52\xe0\x95\x8b\x25\x03\x16\xff" + "\x7a\x07\x33\x7a\x3f\x4c\xde\x0c" + "\x97\x1f\xe4\x12\x56\xdd\x5b\x67" + "\xf1\xa6\xf5\x71\xae\x81\x51\xc3" + "\xf8\x3e\x75\xae\xc8\x00\x56\xd5" +
- "\xb4\x62\xe7\x8b\x4f\x62\x3e\xb3" + "\x13\x34\x8e\x05\xd1\xe4\x9e\x2a" + "\xfa\x05\xd8\x67\x69\x63\x8e\x96" + "\xd7\xbf\xb8\x7d\x9b\x94\x48\x98" + "\x17\x84\x3a\xd2\xe5\xd7\x08\x53" + "\xa5\x9d\xe2\xf3\x1d\x3b\x2f\x89" + "\x1f\x47\xee\x3d\x9e\x13\x5c\xc9" + "\x89\xe0\x57\xd7\x4d\x59\x31\x86" +
-
- "\x15\x56\x09\x1f\xea\xe2\x83\x10" + "\x33\x8c\xe6\x14\x77\xad\x28\x0a" + "\xbe\x18\x88\x3d\x52\x02\xfc\x6b" + "\xcd\x50\x58\xf3\x3a\x11\x85\xb5" + "\xa1\x8a\xdf\x30\x0b\x5f\x93\x7d" + "\xac\xe3\xb7\x4a\x7c\xa0\xdd\xad" + "\xcb\x00\x2f\x55\x99\x42\xc3\x92" + "\x6c\xdf\x09\x29\xde\xd1\x3e\xc3" +
- "\x3c\x11\x07\x3e\x48\x0d\xc4\x2d" + "\xae\x63\x8b\x7d\x39\x5d\x4a\x6e" + "\x2b\x4c\x68\x79\x4b\xa9\x82\x55" + "\x6c\xa2\x2d\x62\xd4\x33\x2b\x93" + "\x8d\xf0\xbb\x0d\x51\xf6\x34\xf5" + "\x52\x3a\xc2\x64\xc9\x07\x1d\x21" + "\x9b\xdc\x5b\xee\x0f\xce\xee\x0e" + "\x58\x55\x01\xf7\x68\x81\x17\xdf" +
- "\x0e\xd6\xcd\x83\x5a\x90\xe7\xab" + "\x84\x01\x17\xa1\xb5\x2f\x60\x50" + "\x2a\x64\x23\xb0\xcd\x86\x98\x68" + "\x00\xfb\xe1\xa6\x90\xd0\x68\xd5" + "\x7f\x21\x59\x02\xc7\x22\x19\x5b" + "\xe4\x41\x31\xc4\xd9\x1c\x83\x93" + "\x6e\xf8\x95\x0c\x87\x35\xca\xdf" + "\x28\xe8\x8a\x56\x7a\x05\xc2\xde" +
- "\x6d\xc1\x3c\x91\x25\x89\x8f\x56" + "\x5a\x6f\xa2\xe1\x6d\x5b\xbc\x18" + "\xae\x99\xf4\xf5\xbe\x13\xa4\xdf" + "\x84\xae\xf0\xc3\xec\x5d\x83\xf8" + "\xb0\x0a\xa4\x65\xd8\x0b\xe6\xb6" + "\x7e\x37\x4b\x19\x39\x64\x59\x65" + "\x69\x4a\x08\x92\x25\x56\xd8\xbc" + "\xe0\xed\x23\x4f\xb9\x33\xe4\x5c" +
- "\x89\x61\xe0\x42\x3d\x52\x0d\x86" + "\x13\xff\x3a\x4e\x41\x79\x07\xbf" + "\x50\x06\xb2\xc1\xca\x6d\x61\x0b" + "\x0d\x30\x31\x21\xd1\xd6\x6d\xe6" + "\xde\xab\x99\xff\x67\xfd\xa0\xd4" + "\x0d\xc5\xaa\xc7\x50\x35\x90\xc9" + "\xd7\xb2\x46\x7c\x8b\xcf\x2e\x02" + "\xaf\x92\xbf\x3a\xe8\xb1\x33\x33" +
- "\x5d\x36\xd6\x84\xe7\x65\xda\xc0" + "\xb8\x9f\x75\x8f\x3f\x44\xb7\xbc" + "\x30\x19\xe8\x7a\xb1\x12\xc7\x35" + "\xab\x08\x6e\x4c\xff\x8d\x42\x80" + "\x43\xf8\xfa\xa4\xef\xaf\x9d\xf1" + "\x5f\x85\xa9\xff\x8d\x53\xd8\xce" + "\xce\xc7\x3a\xbe\x9c\x40\xac\x20" + "\x1e\xa7\x2d\x88\xb6\x1f\x8c\x35" +
- "\x82\xa5\x42\xbe\xf7\xde\xec\xef" + "\xe6\x6b\x04\x65\x80\x60\xfc\xd3" + "\xa9\xdb\xe8\x09\xc8\x13\xaf\xc9" + "\xff\x91\x14\x64\x47\x98\x6c\x1e" + "\xf7\x31\x0c\xd3\x25\x49\x57\x3b" + "\x22\x21\x2a\xac\xba\x72\xeb\xb7" + "\xe7\x59\x08\xef\xac\x0d\x6a\x77" + "\x42\x09\x90\x21\x14\xc3\xfe\x06" +
- "\x2b\x12\x50\x7e\xb0\x94\x47\x32" + "\xa5\x7c\xf0\x4a\x8b\x4f\x74\xdd" + "\x7b\xc9\x3f\xd6\x08\x2f\xa1\x30" + "\x9d\x6d\x62\x76\x1a\x0f\x65\x39" + "\x77\x84\xa3\x1f\xf7\x47\x1b\x10" + "\x4f\x12\xdc\xd4\x19\x5f\x81\x3d" + "\x8a\xb5\x6e\xb2\x95\xae\x69\x15" + "\x87\x18\xfb\x95\x88\xe1\xcd\xc3" +
- "\x21\x7f\x73\xf4\xbb\x2f\xc6\x7e" + "\xac\xf5\x09\x62\xab\xa5\xdb\xd8" + "\xbe\xad\xf9\xa5\xa9\xd7\xb5\x24" + "\x68\xc7\x1d\xa6\xf7\x28\x7d\x70" + "\xea\x99\xa9\xca\x0b\x46\x11\x77" + "\xcc\xe4\x92\x1c\x4d\x17\x7b\xba" + "\x2d\xbf\xd4\x18\x66\xab\x4b\x3c" + "\x79\xd2\x8b\xeb\x80\xc9\xf0\xb8" +
- "\xbf\x91\x06\x79\x32\x89\x65\x9d" + "\xae\x36\xb7\x06\x89\x05\x61\xed" + "\x6e\x3b\xd6\xc0\x04\x2f\x2c\x71" + "\x8f\x48\x3d\xc6\xd5\x6f\xf0\x5c" + "\x41\x8e\x58\xd9\xac\x3f\x36\x97" + "\x7e\x25\x93\x2b\x62\xf7\x9b\x1f" + "\xce\xca\x7a\x66\xc4\xff\xd1\xa9" + "\xcf\x1e\x06\x0a\xaa\xa1\xf4\x1c" +
- "\x23\x9a\x51\xc0\xb2\x75\xd6\x28" + "\xe3\x52\x69\x4f\xfe\x94\xbf\x9e" + "\x8a\x4a\x29\xa2\x67\xb7\x8b\xf2" + "\xf5\xf3\x0a\xfe\x4d\x2b\x51\x85" + "\x0d\x6a\xb1\x99\xa8\x8b\x95\x18" + "\xa7\x48\x75\xba\x0c\x43\xc2\x95" + "\x15\xe6\x6b\xa1\x10\x1b\x0d\xb3" + "\x4c\xb7\xbf\x85\x97\xbb\xeb\xe3" +
- "\x45\x36\xe6\xb2\x5e\x3f\xb5\x07" + "\x32\x42\xc8\x84\x47\xe5\x57\xbe" + "\xcf\xd5\x14\x72\x16\xc2\x79\xd7" + "\xca\x3a\x9a\x02\xcd\x69\x79\x61" + "\xa0\x17\x70\x8a\xcd\x68\x76\xd1" + "\xe8\x7e\x9b\xbe\x9a\xd1\xb4\x77" + "\x76\x17\x16\x9c\x93\x0e\xfd\x58" + "\x72\x8a\x96\xd5\xef\xf4\xc4\xa8" +
- "\x23\xca\xfd\xd2\x65\xb8\xee\x81" + "\x95\xf8\x8e\xcc\x08\xee\x15\x5a" + "\x14\x56\x90\x01\x0a\xa1\x8f\x76" + "\x9b\xe1\x0e\x88\xef\xb8\xf5\xef" + "\x0e\x8a\x1c\xcb\xbb\xca\xc0\xf0" + "\xf9\x38\xc8\xb8\xcd\xe9\x1e\x2e" + "\xc0\x14\x4a\x8a\xb8\xd8\x87\x05" + "\xe5\x98\xf6\x2f\x96\x78\xf2\xf6" +
- "\x80\xda\x44\xbf\xb3\x34\x9d\x51" + "\x66\x2e\xb3\x5a\xf9\x34\x38\x28" + "\x00\xa0\x78\x62\x97\x87\x60\x6e" + "\xf6\x12\x73\x62\x0e\x96\x62\x1e" + "\x55\x1c\x90\xe6\x7b\xb2\x87\x9b" + "\x1f\xbc\xfd\x24\x38\x85\xe7\x80" + "\x7d\xc2\xac\x2f\x51\x09\xbc\xbb" + "\x5a\x3b\x14\xac\x39\x42\x39\x06" +
- "\x99\xce\x2f\x9e\x6e\x64\x4b\x9c" + "\x7f\x85\x80\x1e\x81\x10\xa2\x68" + "\x2a\xb5\x43\x36\x44\x4e\xd5\x06" + "\x43\xb8\x8e\x0d\x63\x6d\x8d\xde" + "\x0a\x6a\x14\x42\x63\x15\x32\x70" + "\x22\x36\xaa\x5e\xf2\x26\xa8\x8b" + "\x87\x87\x13\x86\xbd\x58\x7a\x22" + "\x37\x1d\x28\x10\x3c\xc0\xb6\x43" +
- "\xff\xde\x41\x2f\x95\x7a\xb3\x02" + "\xb7\x89\x3b\xe6\x9a\xa5\x44\x0e" + "\x51\xf9\x3f\x14\xdc\x57\x32\x67" + "\xf4\xba\x52\xd7\x05\x22\xc0\x19" + "\x92\xd6\xb7\xc4\x69\x30\xc2\x46" + "\xac\x02\x15\xfd\xc3\x92\x63\x2e" + "\x46\x08\x22\x1b\xa2\xb1\x57\x60" + "\x63\x5b\x1b\x0c\x46\xf9\x1f\xe5" +
- "\xf0\xc0\x2f\xf0\x32\x26\xca\x7a" + "\x86\x1c\xf0\xc7\x7d\x33\x2b\xb9" + "\x7d\xdc\xfb\x5a\xbf\xc4\x4b\x62" + "\x5e\x1a\xe2\x4d\xbc\x07\x2b\x81" + "\xcc\x90\x20\x0b\x24\x37\xd1\x29" + "\x32\x21\x1b\x5a\x09\xc5\x03\x04" + "\x15\xe0\x35\x0e\xd5\x34\xca\x1d" + "\x6f\xb6\xbb\x3b\x7d\xed\x85\xf0" +
- "\x35\x57\xae\x2e\x86\x66\xc8\xbe" + "\x3e\xf0\xb6\xf9\xf2\x01\x05\x58" + "\xc2\x74\x0e\x99\x63\x20\xff\x8b" + "\x40\xc8\x40\x9f\x3d\x4e\xdc\xfa" + "\x2a\x6f\xeb\x32\xa0\xd3\x57\x03" + "\x8a\xc9\xf1\x0d\x2e\xb2\x18\xe3" + "\x38\xdd\x2a\x50\x8d\x2d\x9a\xbb" + "\x6a\xce\x84\x4a\x7a\x95\x7e\x6f" +
- "\x65\xe8\x81\xf7\xf9\x98\x7b\xc2" + "\x45\x13\x4e\x99\x92\xf6\xe1\x51" + "\xee\x61\x93\xe1\x16\xd5\x07\x08" + "\xef\x8a\x99\xfb\xef\x5c\x88\x13" + "\x17\x8a\x0f\x2f\xe9\xd5\x23\xd2" + "\x80\x02\xd2\xe8\x10\x20\x67\x48" + "\x98\xac\x7e\x23\x60\xfd\x02\x6f" + "\xe7\x7e\xda\x9a\xad\xbf\x51\xcc" +
- "\x48\x36\x1f\x3d\x67\x8d\xe7\x0b" + "\x44\x26\xf8\x26\xbf\xae\x70\xb1" + "\xf5\xa6\xaa\x11\xaf\xb5\x88\x9d" + "\xb2\x0e\x93\x40\xb2\x4e\x44\x57" + "\x06\x29\xd9\x4a\x76\x4a\x96\xd0" + "\x5f\x7e\xf8\xbf\xe3\x5d\xa0\x4c" + "\x84\x90\x86\x0b\xc8\xa6\x41\x11" + "\x8d\x94\xda\x4a\xa3\xfc\x83\x31" +
- "\x1d\x70\x09\x1e\xdd\xbc\x56\x27" + "\x80\x5c\xd4\x90\xb9\x1d\xe3\x94" + "\x84\xe5\x66\x85\xa9\x56\xe8\xb9" + "\xf3\xe3\x10\xab\xde\xd9\x87\x4f" + "\xb2\x9c\xed\x3d\x37\xcb\x6e\x16" + "\x3e\x3d\x65\x3f\x07\xc7\x14\xfd" + "\x25\xc4\xae\x92\x9b\x04\x5d\x10" + "\x11\x2e\xa4\x09\x49\x7e\x65\x7f" +
- "\xa1\x09\xd6\xa5\x9b\xa3\x80\xc3" + "\xcb\x0e\xc1\x24\x77\x1e\x71\x6c" + "\x70\xd0\x22\xb9\xc6\x3c\xd5\xe8" + "\x84\x7d\xb5\x0a\x81\x7b\xc3\xea" + "\xa7\xca\x70\xa7\x78\xc9\x60\xe2" + "\xb5\xf4\x71\xaa\x29\x61\xf2\xdb" + "\x30\x8e\x9a\x48\xb6\xd9\xee\xe2" + "\xfe\x75\x3f\xeb\x7f\xd2\x8f\x48" +
- "\x94\x95\x15\x6a\x07\x90\x64\xea" + "\x52\xce\x97\x1f\x6b\x4d\x42\x3e" + "\xcb\x8c\x5e\x18\x0a\xf3\x6d\xac" + "\xbf\x47\x77\x51\x80\xec\x56\xad" + "\x93\xfe\x91\x43\xcf\x5c\x93\xf0" + "\x40\x1d\x81\x03\x0f\x26\x6b\x86" + "\xbe\x9a\x7b\x9f\xb9\x47\x20\x79" + "\x84\x2d\xe4\x8e\xc8\x0b\x60\xb1" +
- "\x23\x71\xa3\x7c\x92\x45\x58\xdd" + "\xd5\xbd\x8b\x08\x11\x13\x3f\x90" + "\x2e\x27\xc2\xa2\x65\xcf\xde\xdc" + "\xe0\x6f\x1f\xd6\x26\x6e\x35\x9e" + "\xc0\x0d\x48\x54\x9d\x9f\xad\xee" + "\x5a\xbe\x46\x14\x40\xa1\xca\x91" + "\xd1\x75\xc0\xc4\x8d\xcc\x66\x9c" + "\xb8\xc9\x85\xbc\x62\x9a\x52\x5e" +
- "\x5f\xa8\x68\x77\xdb\xb3\x97\x2d" + "\x38\xe0\x87\x42\x33\xf6\x78\x2b" + "\xb1\x2b\x89\x6f\x67\x47\xc9\x86" + "\x00\xc2\xa9\xc0\x1a\xfb\x0b\x92" + "\xb2\x41\x20\x33\xec\xf6\x92\x42" + "\x54\x9d\x98\xc9\x37\xb9\x0b\xa3" + "\x9e\x87\xd5\xc6\xeb\x41\xf9\x39" + "\x87\xb1\xdb\xdf\xfc\x50\xa4\x76" +
- "\x90\xa8\x29\x9c\xc3\x93\xb7\x5f" + "\xb1\x11\xa8\x87\xfd\x3b\xa0\xb0" + "\xd3\x28\xf1\x12\x49\x9e\x24\xb0" + "\xde\x3e\xed\x5a\x13\x3a\x7b\x10" + "\x32\xd9\x34\x20\x56\x99\xe1\x98" + "\x1c\xd7\xc7\x0d\x71\xc7\xce\xd8" + "\xb2\xe0\x31\xb2\x13\x37\x56\xe7" + "\x02\x8c\x96\xac\x85\xd2\x84\x62" +
- "\xb6\x0d\x43\xee\x89\x60\x25\x31" + "\x56\x6f\x83\xf6\xd8\x9b\xce\xae" + "\x46\xa0\x85\xfb\x4b\xfc\x4c\x48" + "\xb9\xb2\x99\x15\x2c\x3e\x1e\xee" + "\xaf\x2e\x12\x3d\x90\x38\x3c\x7e" + "\x6c\x55\x70\xc7\xe0\x0c\x94\xaa" + "\xe8\xfa\x08\x1b\x63\xd6\x02\x48" + "\xba\xf8\x69\x7f\x80\x85\x8a\xb0" +
- "\xae\x1e\x41\x05\x04\x0a\xed\x70" + "\x66\x4c\x49\x16\x8f\xb0\xde\x60" + "\xbb\x97\x37\x13\xc6\x0f\xf2\x8c" + "\x10\xc3\x6b\x0c\xf5\xf4\x30\x3e" + "\xc7\x46\x9c\x74\x29\x7c\x67\x1a" + "\x1c\x98\x1e\xf1\xf4\x93\x1d\xfe" + "\x8b\x68\x3e\x2e\xd8\x03\x73\x93" + "\x85\x9e\xaa\xa6\xa7\xf5\xae\x01" +
- "\x20\xb9\x59\xb9\x95\xf4\x02\x49" + "\x85\xd8\xa2\xfc\xbd\xfd\xb0\x13" + "\xfa\xf0\xa2\xb6\xe7\xd9\xcb\x41" + "\x87\x0b\x43\x56\x10\xf1\xbd\xf9" + "\xb9\x19\x4d\x95\x23\xa2\x05\xd7" + "\xde\x4f\x2a\x97\x5c\xfc\xd0\x74" + "\xea\x77\x29\x91\xd6\xfe\xcb\xcb" + "\xaf\xa5\x59\xcc\xfd\x11\x06\x87" +
- "\x57\x2f\x30\xbb\xab\x19\x72\xba" + "\x30\x27\xb3\xfa\x59\x00\xce\x28" + "\x22\x43\xf5\xa8\xa0\xdc\x26\xfd" + "\xcf\xbd\x6b\xb2\x6b\x0d\xa9\x69" + "\x8b\x63\x49\x89\xbc\xd3\x5d\xe9" + "\x2d\x6a\x2b\x92\xf1\xa4\xe1\x76" + "\xfd\x2c\x87\xd5\xb1\x3c\xf7\x99" + "\xce\xa3\x32\xdb\x9a\x14\x2b\x75" +
- "\x6a\x23\x89\x40\xd0\x9b\xf1\xf4" + "\x0b\x0e\x3d\x31\x12\x6c\x20\x3b" + "\xb2\xae\xfe\x03\xf3\x0d\xe7\x73" + "\xe0\xef\xd1\x9b\xeb\xa0\xdb\x09" + "\x05\x53\x4e\xfc\x32\xd5\x7f\x4c" + "\x7a\x78\x3d\xe9\xed\xff\x92\xd7" + "\x10\x50\x24\xe4\xe2\xc4\x2d\xc7" + "\xbd\xbb\x66\x04\x7d\xd4\xe0\xe7" +
- "\x43\x5c\x6c\x56\x51\xcb\x85\x6e" + "\x46\xf0\x97\x35\x19\xc9\xf9\xcf" + "\x4a\xd9\x94\x49\x0c\xe9\x54\x93" + "\x7d\x92\x47\x21\x32\x93\xa3\xe0" + "\x2b\xeb\xc1\x0d\xc1\xfa\x27\x84" + "\xfa\x19\xf3\x2f\xc2\xd8\xcf\x88" + "\x74\x52\x96\x01\x84\xe6\xd4\xe2" + "\x46\xa7\xaa\x67\x7d\x06\x2e\xfa" +
-
- "\x11\x9f\x5f\x3e\x7f\x2a\xd9\xb6" + "\x8e\x3b\xcb\xd6\x3a\x15\xfe\x9a" + "\xbd\x00\xf8\xdd\xd7\x6d\x1a\x4d" + "\x19\x7e\xf1\xca\xc0\x3c\xc1\xf6" + "\xee\xc3\x5f\x32\x8e\xc5\xf6\x15" + "\xb2\xc3\x1d\xa3\x00\x54\x09\x71" + "\xe7\xd3\xa3\xaf\x07\x7c\x8e\x16" + "\x2d\xae\xc7\x94\xa1\x17\x84\x3f" +
- "\xc3\x40\x95\x31\x9b\x58\x42\x28" + "\xf8\xd6\x83\xa2\x59\x0f\x49\x18" + "\xcb\x9f\xae\xda\x84\x1f\x73\xa2" + "\xa0\x3b\x68\xc3\x60\xd9\xb6\x3d" + "\x69\x10\x61\x14\xbb\x63\x5c\xc8" + "\x05\xbf\x88\x07\xaf\x36\x94\xb1" + "\xd2\x60\x74\x34\xdf\x59\x54\x90" + "\xb1\x7d\x1a\xe1\x94\xe0\xf6\x73" +
- "\x38\x9c\x1b\xc3\x91\xbb\x85\x7b" + "\xb5\x57\xef\x48\x0b\xa9\x5a\x0c" + "\x6f\xab\x3b\xaf\x69\xb1\xde\xde" + "\x85\x36\x37\x2d\x73\xad\x10\xe6" + "\x15\x8e\xba\x02\xdf\x70\x38\xf1" + "\x71\xf7\xa7\x8c\xb6\xed\x37\x03" + "\x6c\x03\x2c\xb6\x47\xf7\xac\xe4" + "\x81\x4e\xb9\xb6\x76\xd5\x21\xd9" +
- "\xcb\x76\x3c\xee\xc8\xa3\x06\xf3" + "\x6e\x1f\x2a\xd3\x23\x16\xf1\x3c" + "\x56\xe9\x63\x68\x64\xab\xd5\xe6" + "\x26\x5c\x00\x5c\xbe\x4c\x8a\x3b" + "\x27\xbb\xe6\x9c\xa5\x29\xd5\xdc" + "\x6f\xb1\xd4\x04\x52\xaa\xaf\xc4" + "\x8d\x79\x23\x79\x26\x4a\x62\xb0" + "\xab\x7f\x30\x6b\xf6\x6d\xe5\x85" +
- "\x14\xd6\x9d\x85\x34\x53\x3e\x3a" + "\xee\xc8\xd0\x18\x5b\x5b\x47\x9c" + "\xd5\x51\xcd\x07\x1f\x0d\x08\x63" + "\x26\x43\x8b\xb8\xa6\xd0\xc0\xc9" + "\x6f\x29\x34\xc2\x91\x86\xc9\x1a" + "\xb6\x7f\x88\x94\xa4\x83\x0a\x2a" + "\xf2\x9c\xea\x0c\x27\x14\x51\x56" + "\xf5\x02\x48\xa2\xe8\xa6\x30\x52" +
- "\xaf\x13\xe9\xbc\x3d\xc7\x0f\xad" + "\xcb\x07\x8a\x45\x7b\x58\x9e\x90" + "\x8a\x0c\xf0\xd4\x84\xda\x00\x13" + "\xac\x66\x44\xb5\x48\xd0\x5c\x42" + "\xbf\xd8\xe9\x90\xbe\xb9\x9c\xb5" + "\x0e\x1b\x43\x3e\xdb\x16\x16\x99" + "\xff\xec\x1a\x53\x7a\x11\xaa\xd3" + "\x3b\xdc\xf4\x59\xd3\x92\xaf\x91" +
- "\x36\x5c\x44\x20\x07\xe2\x3e\x7a" + "\x74\x71\x87\x59\x82\xac\xd1\x71" + "\xe9\x73\x9f\x94\xf7\x39\xc5\x0f" + "\x81\x30\x2e\x98\xd7\xf3\x5c\xd0" + "\x29\x71\x1c\x7b\x0b\xe2\x58\x87" + "\xf2\x61\x9e\x56\x20\xcc\xad\xff" + "\x2d\x4c\x54\x59\x2f\x3a\x5d\xb0" + "\x53\x5e\xff\x9f\xc1\xf5\x16\xbe" +
- "\x63\xa4\x4c\x4e\xef\x0f\x33\xb2" + "\x63\xcc\x66\x35\x87\x72\xef\xbc" + "\x00\x09\x78\xcf\xca\xd2\x61\xd1" + "\x7d\x82\x54\x5b\x39\xc5\x5d\x13" + "\xc6\x1b\xbf\x27\x2e\x05\x8f\x63" + "\x6c\xa0\xdf\x07\xf0\x24\xa2\x10" + "\xda\x21\x33\x6d\x6d\x58\x73\xe9" + "\x8f\x2c\x15\x26\x38\x57\x0c\x8b" +
- "\x98\x60\x55\xb9\x8b\x17\x43\x70" + "\x86\x38\x1c\x80\xdf\xa1\x90\x40" + "\x12\xb9\x67\x9b\xff\x00\x98\x75" + "\xc8\x20\x26\x23\x04\x03\x5c\x3e" + "\xca\xee\xdc\x70\x4b\x3c\x9d\x4b" + "\x8e\x64\x1f\x18\x15\x3c\x2d\xbb" + "\x5c\x34\x33\x6e\x37\xd8\x81\xf9" + "\x7a\x29\xf2\x0c\x9b\x28\x26\xb6" +
- "\x0f\x5e\xbe\x32\xbd\x4c\xc7\x9d" + "\x75\x13\xa0\x17\xb7\xbc\x75\x74" + "\xb1\x72\xd8\x50\xc9\x77\x84\x43" + "\x3d\xd6\xe1\xff\x79\x78\xc6\xce" + "\x70\x8c\x57\xd8\x14\x60\x00\x9b" + "\x8b\x6b\xbb\x78\xa8\x99\xad\xc9" + "\x06\x38\xfb\x11\x8e\x00\x99\x67" + "\xb3\xca\x44\xcd\x35\x14\xe8\xcf" +
- "\xe4\xd2\xf2\x9e\xc1\xfe\x3f\x11" + "\x7f\xea\xa0\xd5\x7e\x76\xf6\x1b" + "\x0a\x4c\x71\x03\x5e\xf7\xff\x57" + "\xee\xe9\x23\x0a\x2e\x42\x3c\xa2" + "\xaf\x83\x0f\x54\x2d\x6b\x5f\xdd" + "\xa7\x46\xea\x55\x7e\xc2\xc2\xc2" + "\x08\x12\x2a\x67\x46\x42\x6b\xeb" + "\x7a\x4f\x63\xae\xf7\x99\x35\xd1" +
- "\xf7\xaa\x84\x98\x95\x95\x68\x89" + "\xa6\x48\xb3\x07\xe3\x9b\x95\xb1" + "\x87\x7c\x14\x3c\x57\x0e\x25\x96" + "\xf8\x61\x0c\xdd\x3a\xfb\x0e\xae" + "\x5e\x32\x8c\xca\x5e\x74\x00\xed" + "\x70\x3f\xff\xec\x96\x16\x91\x3c" + "\x1d\xd4\x9a\x31\x65\xbc\xac\x73" + "\xef\xc7\xb1\xf0\x20\xa0\x01\x7b" +
- "\x6e\x04\x79\x9d\x0d\x79\x89\xaf" + "\x76\x09\xee\x6c\x2d\x0f\x65\x4d" + "\xca\x1e\x07\x43\x9a\x5d\x93\xa3" + "\xfe\x0b\x3b\x28\xc9\xd2\xfc\x66" + "\xf1\x05\x66\x69\xb5\x5e\x66\x0e" + "\x8d\xd3\x4c\xa5\x07\x5d\x7e\xe7" + "\xcf\x50\xd9\x43\x0a\x05\xee\x90" + "\xb5\x69\x2e\xd3\xda\xeb\xdd\x86" +
- "\xe8\x31\x86\x3a\x9b\xb8\xed\xd2" + "\x46\x37\x21\x7a\xde\x55\xe8\x8d" + "\x11\x5f\x0c\xb0\xb7\x6c\x05\xb2" + "\xe4\x85\x9b\x2c\xd0\xfb\xae\xde" + "\x2d\x89\x50\xd1\x8d\x9a\xf3\x03" + "\x85\x79\x8b\x21\x86\x46\xb8\x37" + "\x1a\x5f\x37\xb7\xd8\x6d\x29\x36" + "\x8e\x89\x8e\xb7\xb1\xd4\x2c\x47" +
- "\x93\xbd\x8f\x30\x53\xae\x45\xeb" + "\xda\x6f\xc3\x02\x2e\x5a\xcd\x46" + "\x85\x83\xa4\xba\x90\x4e\x3d\x6a" + "\x60\x99\xbe\x9d\x2e\xe6\x55\xdd" + "\xe7\xed\x81\x2a\xa0\x6a\x40\xa1" + "\xa7\x4e\x27\xf9\x14\xdd\x60\x68" + "\x86\x4f\x41\x80\xc2\xb0\xdc\xcf" + "\x27\x43\xf9\x22\x10\x0b\x41\xff" +
- "\x96\xd8\xa5\x23\x6b\xba\x10\x99" + "\x4e\x36\xe4\x7f\x35\x9e\xe1\x1f" + "\x77\xc6\x33\x9a\xc3\xa8\x1d\x6e" + "\xd0\x9f\xfd\x29\x8b\x48\xb4\x15" + "\xbf\x22\x1f\x1a\x54\x92\x43\x1f" + "\xe8\x63\x81\xab\x70\x8a\x0a\x92" + "\x8e\x65\xe5\x07\x49\xb2\xd1\x3f" + "\x9b\x83\xec\xb6\x9c\xf7\xc4\xf2" +
- "\x84\x3f\x4a\xb4\xe3\x5d\xd5\x17" + "\x90\xc6\xc6\x17\x44\xf3\xb2\xac" + "\x90\x23\x23\x10\x68\x81\x08\x32" + "\xf7\x3b\x73\x6c\x1f\xa6\xe8\xf2" + "\x52\x76\x2d\x9c\xb6\xaa\x74\xa7" + "\xbc\xc5\x95\xed\xe3\x07\x53\xfb" + "\x10\xf1\x81\x49\xc2\x73\x5c\xa0" + "\xc9\x58\x94\xa3\x1c\xe3\xaa\x1b" +
- "\x8b\x2d\x5d\xc5\xbb\xb2\x1d\xce" + "\x56\xca\xf6\xf4\xb7\x8b\xd5\x41" + "\x14\x76\x87\x8f\x80\xb6\x50\x76" + "\xed\x49\xc3\xf4\xba\x16\x5e\x90" + "\xac\xac\x61\xf6\x40\x51\x41\xed" + "\xaf\x70\x22\xcb\xf0\x84\x87\x3b" + "\xba\x2c\x40\x8a\xac\x80\xc2\x3b" + "\x1a\x92\x37\x09\x46\x71\x3f\xd5" +
- "\x30\x17\x34\x78\x6c\xd8\x1e\x7f" + "\x48\xe2\x25\xb5\xb8\xbe\xf5\x8e" + "\x38\xbf\x4f\xb7\xfd\x89\xc4\xbb" + "\x82\xb3\xa0\x91\x0e\x2a\xa9\x38" + "\xcf\x3c\x43\x22\x3f\xba\x77\x7a" + "\xa9\x05\x9f\xa2\xd6\x62\x83\xde" + "\xfc\x9a\x18\x61\xea\x30\x6a\x7f" + "\x4f\x11\xef\x59\x05\x55\x3b\x69" +
- "\xdc\x08\x4c\x22\xb5\x43\x21\x26" + "\x91\x0c\xb5\x81\xb4\x09\xbb\x2b" + "\x4f\xc8\xa8\xac\x09\xd7\x6e\xc1" + "\xa8\x0c\x85\xb2\x9d\x0d\x21\xa6" + "\xd6\x54\xcb\x09\x7a\xf6\x8d\x6d" + "\xa4\x19\x09\x50\xe0\xf6\xee\x91" + "\x57\x28\x13\x0f\x81\x13\xf6\x90" + "\x8b\x02\xd5\xf8\x47\xde\xce\x9a" +
- "\xb8\x06\xd8\xce\xa8\x2f\x1a\x07" + "\x78\x14\x7f\x69\x34\x61\x2e\x22" + "\xbf\xdb\xfc\xab\x5d\xfd\x16\xdc" + "\xb8\x53\x1b\x12\xbf\x2e\x91\x44" + "\x7c\xc2\x96\x24\x74\x36\x94\xac" + "\xb0\x26\xfc\x1f\x6c\x17\xa3\x8e" + "\x2c\xbf\xde\x13\xac\x24\xe2\xb6" + "\x32\xa8\x72\xf3\x35\xc2\x4c\x52" +
- "\x2f\x96\x67\x35\x7d\x36\x98\x7e" + "\xfb\xbf\x88\x81\x1f\xd6\x9e\x37" + "\xa1\x30\xf1\xfa\x48\xa3\xbb\x73" + "\x34\xd7\x4e\x90\xe1\x75\x1f\x6c" + "\xfc\x79\x4a\x3b\x42\x66\x95\x18" + "\x93\x44\xef\x54\x3d\xc8\x0b\xf2" + "\xa1\xec\x11\x91\x5d\x42\x6d\x83" + "\xcf\x8d\x9a\x00\x18\xc3\xb5\xe5" +
- "\x34\xd5\x85\xda\xbd\xa5\x71\x27" + "\xea\x0e\x98\xff\x1f\x8c\xe7\x53" + "\xe7\x85\x03\x90\x84\xcf\xf1\xad" + "\x62\x7b\x38\xc9\xf6\x14\x3b\x7d" + "\xd2\x2b\x8f\xcb\xb0\x74\x0e\x17" + "\x93\xa9\x7f\x82\x86\xb4\x50\x2d" + "\xab\x2b\xf3\xf6\x9a\x8c\xbe\xcd" + "\xb8\x3a\xb9\xc3\xb0\x06\xe9\x55" +
- "\xa5\xa6\x16\x14\x69\xa0\xce\x84" + "\x1c\x88\xef\x43\x79\x0c\x86\x8f" + "\x5d\x8a\x03\x38\x8a\x1f\x31\x41" + "\x67\x20\x61\xfc\xc0\x2e\x8c\xe7" + "\x81\x35\xd7\x5a\x81\x2e\x4d\x49" + "\x97\x40\x60\x59\x00\x9e\xcc\xb4" + "\xba\x2c\x61\xf3\xec\x8a\x55\xff" + "\x9e\xc3\x36\x9e\x7a\xef\xbe\x35" +
- "\xee\x06\xba\x36\xcc\xc0\x4e\x32" + "\x0c\xcc\xd2\x3d\x15\x31\xce\xfa" + "\x1f\xe9\x33\xf3\xbe\xf3\x64\xb3" + "\xb0\x32\xe8\x28\x73\xff\x8a\xef" + "\x1b\x84\x05\x2d\x04\xad\x9b\x1e" + "\xe2\x21\x6a\x35\xdf\xe3\xf0\x42" + "\x7e\x62\xdd\x4a\xcb\x0b\x27\xa3" + "\x11\xe7\x22\xd3\x58\x81\x9a\xb0" +
- "\x04\x6e\x92\x66\xcd\x8e\x3f\x32" + "\xba\xc1\x10\x81\x8f\xe3\x01\x00" + "\x07\x7f\x6a\xfc\x12\xac\xbc\x8d" + "\x27\x08\xec\x0c\x58\x1d\x5e\xd6" + "\x2d\xca\x76\xbe\x41\x41\xcd\xd2" + "\x3a\xf3\x92\xe8\x5c\xcf\x95\x78" + "\xd2\x39\x71\x36\x0d\x23\x6d\x95" + "\xc1\xc4\x12\xd0\x3e\xbd\x1a\xa9" +
- "\x26\xd4\x95\x62\x9d\x77\xff\x28" + "\x7b\xad\xa3\x3f\xc7\x6a\x4f\x0c" + "\x04\x26\x8e\x8b\x54\xd0\x44\xec" + "\xe1\x50\x00\x8b\x6d\xa6\x32\x9b" + "\xe2\x6c\x47\xf0\x66\x33\x94\x1f" + "\xb4\xc7\x02\xa6\x53\xd9\x54\x75" + "\x09\x28\x4f\x52\xa6\xac\x35\xbe" + "\xea\xdb\x4e\xfd\x29\x12\x88\xb6" +
- "\x29\x36\x67\xde\x46\x14\xe2\x45" + "\x21\x2d\x3c\x70\x1e\xaa\xf7\x57" + "\xc7\x68\xc8\x98\x7f\x9b\xe9\xa0" + "\x76\x16\x64\x8b\x6d\xf6\x42\x4e" + "\x96\x78\x07\x91\xdc\x84\x28\x60" + "\x5b\x88\xc9\xc2\xcf\x90\xd6\xa0" + "\x87\x51\x9a\x3b\x33\xda\xb4\xfe" + "\xee\x87\x3c\x15\x98\x95\x78\x5f" +
- "\x90\x96\xf0\x15\xe7\xdc\x82\xb7" + "\xc9\x0f\xfc\x2d\x12\x9b\x8b\x50" + "\xc6\x9f\xd8\x65\x4b\xab\x15\x90" + "\x0f\xbb\xd5\xd6\xb7\xda\x79\x5e" + "\xa2\x5a\x77\x6c\xf0\x21\xf0\x64" + "\xa1\xec\xc7\x37\xcc\xd8\x09\xdf" + "\x06\xa5\x2f\xef\x67\x13\x76\x9a" + "\xc6\xee\x81\x5b\x76\xa4\x4c\xed" +
- "\x7c\x86\xb0\x67\x19\x71\x83\x3b" + "\x20\x45\x36\x9d\x08\x0d\x5e\x8d" + "\xe3\xf0\x30\xd9\x1e\xcc\xdc\x52" + "\xaf\xbb\x20\xbf\xc7\xce\xbb\xef" + "\x10\xad\x63\x02\xab\xfc\xcf\x99" + "\x8a\x8f\xd1\xfc\x6d\x9e\x19\xd8" + "\x17\x06\xf1\xe9\x3f\x77\xe2\x64" + "\x48\x48\x70\x08\xe1\xe8\x79\x00" +
- "\x2b\x34\x2f\x5c\x4d\xce\x9c\xbb" + "\xae\x7a\x2d\xb5\x7a\x90\x80\xbf" + "\xd0\xbc\x61\x21\xcd\xd3\xf3\x97" + "\x4d\x74\x62\x09\x34\x08\x5b\xb2" + "\xda\x1d\x3a\x6c\xa5\x8e\xb1\xc5" + "\x17\x23\xc9\x06\xeb\xc7\x4e\xfe" + "\xfe\x4a\x1c\xad\x90\xb8\x87\xb7" + "\x1a\x80\xde\x0e\x92\x9a\xcd\xdc" +
- "\xe8\x7e\x49\x76\x9c\x61\x5c\x8b" + "\x0e\x37\x17\xc7\xc6\x0a\x2b\x5d" + "\xe1\x68\xcf\x4f\xb6\x4c\x20\x98" + "\x92\x67\xbc\x62\x11\xc2\xde\x0b" + "\x11\x10\x3b\xa6\xef\xcc\x73\x69" + "\xc5\x1a\xde\xe0\x97\xfa\xe3\xf9" + "\x8b\x0c\x0e\x3d\x3e\x69\xfb\x5e" + "\xb4\xfc\xd4\xd2\xe9\x48\x72\x03" +
-
- "\x9e\x4f\xc3\x1e\xc9\x2d\x80\x80" + "\x03\x06\x81\x33\x35\x2d\x77\xd8" + "\xf3\xb4\x0c\x53\x6c\xd6\x06\x3f" + "\x29\xc1\x75\xc4\x0d\xed\xe5\x7b" + "\x10\x2b\xe8\x31\x19\x3c\x9e\xcb" + "\x4c\x6b\xff\xc9\x57\x28\x3d\xc6" + "\x5e\xb4\xa1\x92\xc6\x18\x21\xb9" + "\xca\xbb\x85\x72\x14\x44\xec\x0a" +
- "\xef\xa3\x29\x1e\xe7\x9a\x18\xfc" + "\x2e\x30\x93\x4c\xf0\x06\xe9\xcb" + "\x0e\xe1\xaa\xce\x14\x79\x10\xd0" + "\xf8\x19\x8e\xb6\x34\x3f\xa2\xb7" + "\x9d\x11\xd2\xef\xc2\x75\xd8\xe9" + "\xc8\xc9\xad\xfc\x6e\x8c\x19\x03" + "\x13\x71\xa1\x4d\xf6\x1b\x59\x65" + "\x38\x30\x44\x3d\xf8\xbb\xf0\x3c" +
- "\x59\x47\x72\x2b\xb7\x5b\x48\xae" + "\x3a\xc6\xd4\xb2\xe1\x53\x53\x94" + "\x2c\x6f\x7d\xde\x07\x9d\x15\x82" + "\x09\xb1\xc5\x4e\xf3\xae\x9c\x38" + "\x14\xef\x65\xdb\x53\xbb\x8e\x4a" + "\x43\xde\x99\xdd\x7e\xcb\xc2\x2d" + "\x5f\x40\xf2\x83\xed\xa3\x6f\x81" + "\xa3\x08\x42\xc1\xb9\x9b\x42\x73" +
- "\x27\x6e\x1e\xb0\x90\xd5\x18\xb6" + "\xdc\xb2\x80\xe1\xcd\x2c\x7e\x04" + "\xa9\xa4\xae\x04\xb5\x99\xb2\xd1" + "\xa4\x03\xa4\x9f\x1e\x9e\x2c\x41" + "\x52\x75\x40\x79\x36\x8a\xd2\x88" + "\xe3\xb8\x32\xf3\x36\x01\xc5\x49" + "\x19\xde\x68\xe6\xcc\x6f\x1b\x3a" + "\x97\x2b\x12\x75\xbc\x51\x88\x17" +
- "\x4c\xfa\x85\xfb\x52\x37\xe1\xb1" + "\xe9\x8c\x3c\x38\xce\x57\x12\xd6" + "\xae\x4d\xf7\xd2\x70\xa6\x3d\xd4" + "\xbb\x6b\x84\xbf\x3f\xa2\x5a\xa3" + "\x83\xfc\x21\x44\x5d\x23\x74\x5e" + "\x3b\x47\x63\xc3\xe0\x8e\xdf\xf6" + "\x58\xa1\x4a\x3c\x2a\xf5\xd7\x34" + "\x2e\xd2\xc6\x9b\xab\x5a\xd0\x50" +
- "\xf4\x85\x47\xa6\x35\xe7\x56\x8c" + "\x07\xcd\x29\x5f\x7b\x63\x56\xbc" + "\x67\x50\xe3\x3e\x80\xbb\xb2\x53" + "\x70\x92\x91\xdc\x0f\x5a\x23\x50" + "\x65\xaa\xc4\xf2\xd8\xb6\x1a\x19" + "\x3b\x02\x96\x83\x31\x58\x47\xc3" + "\xba\x05\xf8\xf0\xa5\x0b\x40\x80" + "\x0f\xf8\xc0\x5e\x5b\x06\x81\x88" +
- "\x83\x5e\x1b\xcc\x22\xe5\x70\xc3" + "\xfb\x8b\x0b\x86\xd1\x4a\x2d\xde" + "\xdf\x56\xb2\x67\xf0\x4d\x36\xad" + "\x97\x89\x13\xe0\x2e\x50\x12\x8f" + "\x0a\x92\x83\x77\xdc\xa0\x3f\x50" + "\x6a\x86\xbc\xc0\xad\x14\x00\xe8" + "\xa6\x4b\x06\xd3\x44\xb7\x89\x3f" + "\xa5\xdb\xa5\xcb\xcd\x1d\x51\x03" +
- "\xa2\xb1\xa7\x95\x6d\xd4\x7d\x19" + "\xfb\x41\x63\x3c\xd6\x7a\x4e\x9c" + "\xce\x2e\x4c\x48\x29\xca\x6e\x42" + "\x8a\x4f\x7f\xde\x89\xe4\x11\x92" + "\xf4\xf1\x8e\xc7\x6e\x7f\x99\x14" + "\x86\x45\x57\x06\x10\x09\x2c\x2b" + "\xe8\xed\x3e\x1c\x6e\x6a\x28\x17" + "\x18\xe0\x60\x0f\x47\x2e\xf9\x25" +
- "\x36\x0a\x89\x31\x46\x56\x5c\x80" + "\x5b\xea\xfe\x57\x00\xf6\x3e\x70" + "\x30\x30\x3c\xaf\x7c\x74\x9f\x38" + "\x39\x37\xdd\x54\xeb\xda\xe5\xe0" + "\x55\xf1\xc9\xc9\xc3\xa4\x24\xfe" + "\x62\x39\x39\xb5\x76\xf1\x4b\x7e" + "\x29\xbf\x20\xaf\xe2\x3d\x18\x37" + "\x3b\x8c\x5a\xf9\xb5\xd7\x1b\x4a" +
- "\x3d\x1d\x19\x46\x99\x96\x3b\xa8" + "\x57\xf2\x87\x7b\xdd\xc8\x1f\x28" + "\x88\x75\x10\x54\x13\x2c\x8e\xb1" + "\xe8\xaf\x2b\x9b\xf7\xde\x72\x63" + "\xca\x72\x89\x0d\x48\xbb\xf4\xda" + "\x3f\x7a\x16\x56\xb7\xd4\x2d\x3f" + "\xf4\x0c\x31\x84\x2d\xe3\xac\x1e" + "\xaa\x00\x27\xe4\xaf\xef\xbc\xe3" +
- "\x3d\xe7\x85\xd7\x1e\x69\xe5\x5f" + "\x67\x04\xa6\x2e\xb6\x5a\xdb\xa5" + "\x4a\x51\xc6\xdf\x41\x3d\xe2\x02" + "\x65\x36\x3c\xe0\x8e\x04\xe8\x35" + "\xf8\xa0\xda\x1a\x8f\x11\x8b\x3f" + "\x5a\x1a\xce\x84\x45\x3b\xec\x28" + "\xb8\x46\x66\x2c\x6e\xcc\xca\xe8" + "\x0f\xe4\xd0\xdb\x85\xd1\x43\x13" +
- "\x8c\x35\xaa\xca\x44\xf8\xd7\xe5" + "\x2a\x18\x24\x99\xe4\xb7\x1d\x1a" + "\x9a\x5d\x87\x9c\x2d\xd4\x4c\xd6" + "\xc8\xee\x2e\x04\x5f\x51\x7b\xb3" + "\xbe\x5f\x16\x7b\x09\xd4\x4d\x4d" + "\xf3\xef\x06\xe2\xd9\x2e\x32\xfc" + "\x7e\xe1\xb7\x59\x02\x41\xee\x7d" + "\x00\xca\x36\x82\xc0\x81\xa4\x55" +
- "\x75\xc9\x3f\xc2\x12\x53\x88\x8c" + "\x7b\x29\xd6\x05\x06\x58\x71\x15" + "\x39\xdd\x8e\xf7\x8e\x86\x78\xa0" + "\x52\x5e\xc4\x03\xe0\x31\x6b\x95" + "\xa6\x33\x7b\xff\xd5\x75\x02\x47" + "\x3f\x67\x7e\x0c\x3a\xdc\xd5\xc8" + "\x98\x25\x2f\x7e\xb4\x27\x92\x41" + "\x75\xa9\x14\x4c\x34\xb6\x37\x8b" +
- "\x8c\x88\x11\x8b\xd6\x7e\x66\xd0" + "\xdc\x25\x3e\x80\x3e\x8c\x0e\x5e" + "\x4a\xa2\x87\xb9\xdc\xd0\xe5\x34" + "\x23\x03\x92\xae\x3b\xac\x40\x9f" + "\x3a\xf6\xe0\x34\x95\xde\x63\x54" + "\xf9\x28\x63\x6b\x92\xbf\x28\xa1" + "\xb7\xf1\x64\xda\x7c\xcd\x1c\x49" + "\x35\xde\x7b\xc4\x27\xec\xf1\x7e" +
- "\x37\x27\x6a\xa3\x0f\x24\x57\xa8" + "\xc1\x1b\x62\x63\x66\x13\xdc\x35" + "\x97\x68\xfb\xd4\x53\x64\x3a\x7a" + "\x9d\x31\x29\xc9\x39\xa4\xf1\x80" + "\xa0\x0b\xcb\xf8\x4b\x27\x18\xfc" + "\xeb\xc5\x78\x80\x66\x37\xb5\xb0" + "\xef\xd0\x01\x1e\x24\x49\x0d\xfb" + "\x9c\xb0\x2a\x37\x7d\xc6\xd7\x50" +
- "\x68\xc9\xea\x3a\xaf\x70\xe3\xb4" + "\x66\x32\xb6\xc4\xe9\xfe\xf7\xe4" + "\x64\x56\xac\xe3\xc2\xd4\xac\xb4" + "\xbf\x8c\xb3\xce\xd2\x0b\x91\xf8" + "\x6e\x72\xc0\xc9\x0c\xe5\x3a\x1c" + "\xbf\x40\x7b\xd9\x69\x95\x30\x15" + "\x1b\x5a\x5a\xfd\x7f\x4b\x88\x70" + "\xcd\x14\x83\xef\x6a\x89\x90\x38" +
- "\x93\x8c\x61\xa5\x5c\x51\xe1\x58" + "\xd1\x42\xd9\x77\x2b\x43\x65\xe6" + "\xa8\x67\xf7\xb6\xbf\x81\x21\xb3" + "\x10\x41\x60\x3a\xe8\x94\x37\x75" + "\xcc\xdb\xc0\xe8\x7c\xeb\xaf\x09" + "\xa3\x73\x86\x59\x13\x26\xe0\x31" + "\x00\xdb\x46\x7d\x57\xe5\x98\x5d" + "\x28\x5b\x98\x9d\x8c\xfb\x21\xfc" +
- "\x0b\x3e\x84\xb0\x16\x01\x04\xc9" + "\x31\x45\xb0\x69\xa8\xb3\xb1\x53" + "\x30\xd8\xd7\x85\xf0\x49\x16\xdd" + "\xe8\x27\x74\xcb\x87\xcc\x3b\xbb" + "\x83\xce\x3d\xc9\x00\x11\x26\x77" + "\x2a\x2a\x92\xa1\x61\xda\x79\x7e" + "\xe8\x9c\x14\xf3\x02\x2b\x7a\x58" + "\x83\xec\x92\xde\x84\x13\x7e\x14" +
- "\x30\x7f\x07\xaf\xd3\x83\x4c\x48" + "\x3a\xb5\x58\x06\x44\xf8\x78\xea" + "\x53\xec\x7a\x02\xc2\x76\x20\x91" + "\x7d\x17\xc8\x93\xe3\x14\x47\xf3" + "\x84\x6c\x37\xc2\x15\x5d\xef\x37" + "\x83\xa7\x1a\x3d\x59\xb6\x15\x83" + "\x90\x2a\x85\xef\x84\xc4\x75\x3a" + "\xd4\x6b\x08\x16\x8a\xc5\xa0\x0b" +
- "\x48\x6d\x9a\x52\x7a\x8d\x68\x29" + "\x03\x92\xf1\xc2\x0d\x25\x7f\x9c" + "\xf9\x2d\x2e\x68\xfb\x42\x30\x12" + "\xbc\x21\x81\xad\xe7\x87\x75\x2b" + "\x65\x2a\x18\xe0\x33\x02\xfc\x30" + "\x8a\x12\xe1\xe3\x87\xcf\x2e\xb8" + "\x8f\x09\xfb\x93\x61\x28\x68\x71" + "\xa7\xe6\xe9\x85\xae\x21\x3e\x04" +
- "\xea\x34\xc8\x66\xd6\x49\x5b\xab" + "\x87\x42\x41\x47\x18\x3e\xe4\x3b" + "\x47\x2a\x9a\x21\x59\xb8\x0f\xf4" + "\x3c\xdf\x58\xcc\xe9\x59\x65\x0e" + "\xb4\x15\x66\x0c\x8e\xfe\x1d\xfe" + "\x70\x9d\x45\x56\xfd\xc8\xab\x14" + "\x86\x03\xde\x05\x8e\xfa\xe0\x7b" + "\x7c\x5c\x03\xe9\x68\xef\x63\x8e" +
- "\x91\x1e\xb3\x53\xb4\x01\x64\x11" + "\xd8\xb4\x36\x44\xd4\x7a\xba\x0c" + "\x66\xfd\x7a\x10\xa0\xf9\x51\x91" + "\xc4\xe4\x0e\x1f\xd0\xa8\xac\xaf" + "\x1c\x76\xe9\x9e\x1d\x5c\xfe\x75" + "\x8f\x58\xc0\xf0\x6b\xa1\x97\x34" + "\x4c\x80\x04\x03\xbd\xbe\xe2\x3e" + "\xb9\x90\xc9\xc2\x60\x9a\xfb\xa8" +
- "\x14\x11\x25\x39\xfe\x32\x4d\xd1" + "\x66\x33\xc7\xca\xbc\x25\xbf\x36" + "\x5c\x49\xa7\xdb\x66\x2c\x56\xc9" + "\x8b\x34\xad\x46\x1b\x30\x4d\x32" + "\x7e\x40\x70\xd6\x0c\x62\x46\x9f" + "\x01\x3a\x73\xe3\xf1\xd4\xa8\x0e" + "\xe0\x24\xc3\xb0\x32\xd5\x96\xd3" + "\xcd\x17\xc3\x03\x0e\x1a\x21\x5b" +
- "\x37\x7b\xfe\x5f\x20\x7d\x0d\x09" + "\xda\xd2\x47\x17\xfb\x3e\x7f\x3b" + "\x19\xc5\x4f\xb5\x5f\x52\xcb\xa2" + "\x1e\x97\x6a\xf6\x32\x09\x22\x6e" + "\x40\xd4\x86\xb4\xdf\x60\xc1\xdd" + "\x65\x34\xe1\x3f\x46\xec\xcf\x7f" + "\x51\xc1\xe4\x76\x4e\x7e\xda\x83" + "\xb5\x02\xd3\xd8\xa1\x48\xfa\xd6" +
- "\x88\xcd\x72\x58\x26\x4f\x30\xc6" + "\xa1\x90\x8b\x27\x3c\x1d\x6c\x80" + "\x1c\xbc\xf0\xca\x25\xe7\x53\x35" + "\x5c\x8d\x9d\xbb\x03\xe6\x59\xff" + "\xdd\x85\x0b\x7a\x32\x0f\x55\xa4" + "\x17\xc2\xec\x93\x0a\x72\xc5\xde" + "\x13\x22\xd6\x69\x41\xb7\x88\x0b" + "\x55\x59\x36\x5b\x45\xf2\x12\x72" +
- "\x87\xe7\xca\xb5\x11\x41\x76\x20" + "\x24\x31\xfd\x1d\x58\x7f\xcb\x13" + "\xfb\xae\x75\x11\xda\x77\xca\x2d" + "\x75\xe7\xaa\xff\x6b\x46\x75\xeb" + "\x32\xff\x6c\xdb\x3b\x6f\xd7\x74" + "\x9a\xda\xfc\x61\x7a\xf3\x40\x74" + "\x8b\x02\x25\xb5\x92\xac\xb3\x1b" + "\x29\x5f\x97\xa1\xf7\xf8\xfb\x20" +
- "\x7f\x09\x83\xdf\xe1\x92\x26\x98" + "\x00\x08\x4b\x55\x6c\x8f\x73\x28" + "\x2f\x2f\xce\xa2\x17\x37\x70\xdc" + "\x94\x41\x81\x40\x3c\xb9\x13\x79" + "\x36\x96\xe8\x1f\x93\x45\x92\x04" + "\xa6\x34\x88\xf7\x3f\x44\x98\x7b" + "\xa1\xa5\x14\x51\x01\xab\xc6\x11" + "\x4c\x5f\xba\xff\x83\xb3\xde\x60" +
- "\xe6\x82\xa9\x01\xc6\x54\xaa\x4c" + "\x26\xcd\x91\x34\x11\x5e\xd3\x1d" + "\x05\x6b\xbd\x7c\x5f\x31\x3c\x97" + "\x24\x47\x49\x52\x75\x07\xb0\xca" + "\x5a\xe1\x65\x65\x1f\x9b\x65\x04" + "\x26\xb0\x8f\x8c\x29\xf5\x30\xbf" + "\x37\xde\xa0\xa8\x1b\x64\x21\xfc" + "\x14\x51\x5e\xfa\x66\xa3\xc7\xe9" +
- "\xd8\x3a\xf0\x52\xa5\x9c\x84\xdb" + "\xc0\x35\x4e\x02\xe9\xdb\xe8\xc7" + "\x89\xc7\xc3\xcf\xac\xbb\xa2\xa1" + "\x62\xf2\x26\x9c\x7d\x3e\x73\xbf" + "\x23\x48\x44\xb8\xf5\xfb\x2f\x88" + "\x3b\x48\xf8\x6b\x88\x4e\x22\xb7" + "\x40\xf6\xbe\x65\x8b\x3b\x02\x53" + "\xcd\xf8\xd5\xd4\x91\xec\xbf\xaa" +
- "\xbd\xa1\x9e\x07\x10\x15\x0e\xa4" + "\x26\x5d\x5d\xd0\xdc\xad\xd9\x1a" + "\x4f\x8d\xe6\x13\xab\x2e\x3f\xdb" + "\x3f\x80\x0f\x64\xe2\x1a\xff\x1c" + "\x17\xe1\xce\xd4\x49\xb7\xe7\xe0" + "\x09\xd9\x36\x40\x5b\x27\x9f\x8e" + "\x38\x4c\x4d\x8f\x1d\xe3\x34\xce" + "\xfc\x30\x51\xd7\x69\x7f\xb3\x22" +
- "\x04\x46\x01\xb4\xfd\xf1\xe0\x83" + "\x78\x50\x41\x89\x19\x99\xce\xa8" + "\xfe\x2e\x79\x41\x75\x5b\x37\x82" + "\x5b\x51\xd4\x97\x5c\xbf\x59\x4f" + "\x7d\x27\x3a\x92\x4f\x32\x4f\xac" + "\x06\x34\x0f\x65\x7d\x9b\xbc\xd9" + "\x51\xbc\x39\x8a\xd1\x87\xfa\xc6" + "\x8f\x10\xcc\x5c\x30\x85\x58\x82" +
- "\x34\xc6\xe4\x82\x9f\x3c\xed\x5c" + "\xf8\x64\x44\x3a\x14\x83\xfb\x8e" + "\x25\xca\x1d\x7a\x1b\x38\x06\xe7" + "\x2b\x41\x2a\x5a\x3c\x5a\xd1\x6c" + "\xb5\x8f\xcd\xbf\xfd\xa8\x47\x93" + "\x22\xcd\x54\x6e\xef\x2e\xdb\x31" + "\x2f\x93\xd8\xf8\x1e\xb1\xae\xc4" + "\xaf\x11\x44\x34\xed\xc1\xe7\x11"
diff --git a/src/crypto/elliptic/p384.go b/src/crypto/elliptic/p384.go
index 0fb7471..33a441d 100644
--- a/src/crypto/elliptic/p384.go
+++ b/src/crypto/elliptic/p384.go
@@ -66,6 +66,9 @@
if x.Sign() == 0 && y.Sign() == 0 {
return nistec.NewP384Point(), true
}
+ if x.Sign() < 0 || y.Sign() < 0 {
+ return nil, false
+ }
if x.BitLen() > 384 || y.BitLen() > 384 {
return nil, false
}
diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go
index 6c9eed3..6a3ade3 100644
--- a/src/crypto/elliptic/p521.go
+++ b/src/crypto/elliptic/p521.go
@@ -71,6 +71,9 @@
if x.Sign() == 0 && y.Sign() == 0 {
return nistec.NewP521Point(), true
}
+ if x.Sign() < 0 || y.Sign() < 0 {
+ return nil, false
+ }
if x.BitLen() > 521 || y.BitLen() > 521 {
return nil, false
}
diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go
index cda1d95..75c2129 100644
--- a/src/crypto/x509/internal/macos/corefoundation.go
+++ b/src/crypto/x509/internal/macos/corefoundation.go
@@ -48,7 +48,7 @@
// TimeToCFDateRef converts a time.Time into an apple CFDateRef
func TimeToCFDateRef(t time.Time) CFRef {
secs := t.Sub(time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC)).Seconds()
- ref := CFDateCreate(int(secs))
+ ref := CFDateCreate(secs)
return ref
}
@@ -170,8 +170,8 @@
//go:cgo_import_dynamic x509_CFDateCreate CFDateCreate "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
-func CFDateCreate(seconds int) CFRef {
- ret := syscall(abi.FuncPCABI0(x509_CFDateCreate_trampoline), kCFAllocatorDefault, uintptr(seconds), 0, 0, 0, 0)
+func CFDateCreate(seconds float64) CFRef {
+ ret := syscall(abi.FuncPCABI0(x509_CFDateCreate_trampoline), kCFAllocatorDefault, 0, 0, 0, 0, seconds)
return CFRef(ret)
}
func x509_CFDateCreate_trampoline()
@@ -193,7 +193,7 @@
func x509_CFStringCreateExternalRepresentation_trampoline()
// syscall is implemented in the runtime package (runtime/sys_darwin.go)
-func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
+func syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) uintptr
// ReleaseCFArray iterates through an array, releasing its contents, and then
// releases the array itself. This is necessary because we cannot, easily, set the
diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go
index 5e6bd54..a32a973 100644
--- a/src/crypto/x509/parser.go
+++ b/src/crypto/x509/parser.go
@@ -51,9 +51,9 @@
}
// parseASN1String parses the ASN.1 string types T61String, PrintableString,
-// UTF8String, BMPString, and IA5String. This is mostly copied from the
-// respective encoding/asn1.parse... methods, rather than just increasing
-// the API surface of that package.
+// UTF8String, BMPString, IA5String, and NumericString. This is mostly copied
+// from the respective encoding/asn1.parse... methods, rather than just
+// increasing the API surface of that package.
func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) {
switch tag {
case cryptobyte_asn1.T61String:
@@ -93,6 +93,13 @@
return "", errors.New("invalid IA5String")
}
return s, nil
+ case cryptobyte_asn1.Tag(asn1.TagNumericString):
+ for _, b := range value {
+ if !('0' <= b && b <= '9' || b == ' ') {
+ return "", errors.New("invalid NumericString")
+ }
+ }
+ return string(value), nil
}
return "", fmt.Errorf("unsupported string type: %v", tag)
}
diff --git a/src/crypto/x509/parser_test.go b/src/crypto/x509/parser_test.go
new file mode 100644
index 0000000..d7cf7ea
--- /dev/null
+++ b/src/crypto/x509/parser_test.go
@@ -0,0 +1,102 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package x509
+
+import (
+ "encoding/asn1"
+ "testing"
+
+ cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
+)
+
+func TestParseASN1String(t *testing.T) {
+ tests := []struct {
+ name string
+ tag cryptobyte_asn1.Tag
+ value []byte
+ expected string
+ expectedErr string
+ }{
+ {
+ name: "T61String",
+ tag: cryptobyte_asn1.T61String,
+ value: []byte{80, 81, 82},
+ expected: string("PQR"),
+ },
+ {
+ name: "PrintableString",
+ tag: cryptobyte_asn1.PrintableString,
+ value: []byte{80, 81, 82},
+ expected: string("PQR"),
+ },
+ {
+ name: "PrintableString (invalid)",
+ tag: cryptobyte_asn1.PrintableString,
+ value: []byte{1, 2, 3},
+ expectedErr: "invalid PrintableString",
+ },
+ {
+ name: "UTF8String",
+ tag: cryptobyte_asn1.UTF8String,
+ value: []byte{80, 81, 82},
+ expected: string("PQR"),
+ },
+ {
+ name: "UTF8String (invalid)",
+ tag: cryptobyte_asn1.UTF8String,
+ value: []byte{255},
+ expectedErr: "invalid UTF-8 string",
+ },
+ {
+ name: "BMPString",
+ tag: cryptobyte_asn1.Tag(asn1.TagBMPString),
+ value: []byte{80, 81},
+ expected: string("偑"),
+ },
+ {
+ name: "BMPString (invalid length)",
+ tag: cryptobyte_asn1.Tag(asn1.TagBMPString),
+ value: []byte{255},
+ expectedErr: "invalid BMPString",
+ },
+ {
+ name: "IA5String",
+ tag: cryptobyte_asn1.IA5String,
+ value: []byte{80, 81},
+ expected: string("PQ"),
+ },
+ {
+ name: "IA5String (invalid)",
+ tag: cryptobyte_asn1.IA5String,
+ value: []byte{255},
+ expectedErr: "invalid IA5String",
+ },
+ {
+ name: "NumericString",
+ tag: cryptobyte_asn1.Tag(asn1.TagNumericString),
+ value: []byte{49, 50},
+ expected: string("12"),
+ },
+ {
+ name: "NumericString (invalid)",
+ tag: cryptobyte_asn1.Tag(asn1.TagNumericString),
+ value: []byte{80},
+ expectedErr: "invalid NumericString",
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ out, err := parseASN1String(tc.tag, tc.value)
+ if err != nil && err.Error() != tc.expectedErr {
+ t.Fatalf("parseASN1String returned unexpected error: got %q, want %q", err, tc.expectedErr)
+ } else if err == nil && tc.expectedErr != "" {
+ t.Fatalf("parseASN1String didn't fail, expected: %s", tc.expectedErr)
+ }
+ if out != tc.expected {
+ t.Fatalf("parseASN1String returned unexpected value: got %q, want %q", out, tc.expected)
+ }
+ })
+ }
+}
diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go
index a42b852..69dcd11 100644
--- a/src/crypto/x509/x509_test.go
+++ b/src/crypto/x509/x509_test.go
@@ -3253,3 +3253,98 @@
t.Fatalf("ParseCertificate to failed to parse certificate with optional authority key identifier fields: %s", err)
}
}
+
+const largeOIDPEM = `
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ da:ba:53:19:1b:09:4b:82:b2:89:26:7d:c7:6f:a0:02
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: O = Acme Co
+ Validity
+ Not Before: Dec 21 16:59:27 2021 GMT
+ Not After : Dec 21 16:59:27 2022 GMT
+ Subject: O = Acme Co
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:17:16:d8:bc:29:9c:16:e5:76:b4:93:15:78:
+ ad:6e:45:c5:4a:63:46:a1:b2:76:71:65:51:9c:14:
+ c4:ea:74:13:e4:34:df:2f:2c:65:11:e8:56:52:69:
+ 11:f9:0e:fc:77:bb:63:a8:7c:1a:c6:a1:7b:6e:6c:
+ e7:18:25:25:c9:e8:fb:06:7f:a2:a9:98:fe:2a:bc:
+ 8a:b3:75:b6:b8:7d:b6:c9:6b:29:08:32:22:10:cb:
+ 8d:d6:60:c8:83:ad:f5:58:91:d6:11:e8:55:56:fb:
+ 8f:a3:a2:9f:48:cb:79:e4:65:4a:8c:a6:52:64:9f:
+ 99:38:35:d4:d5:ac:6f:cf:a0:cb:42:8c:07:eb:21:
+ 17:31:3a:eb:91:7b:62:43:a4:75:5f:ef:a7:2f:94:
+ f8:69:0b:d4:ec:09:e6:00:c0:8c:dd:07:63:0b:e4:
+ 77:aa:60:18:3c:a0:e0:ae:0a:ea:0e:52:3b:b4:fa:
+ 6a:30:1b:50:62:21:73:53:33:01:60:a1:6b:99:58:
+ 00:f3:77:c6:0f:46:19:ca:c2:5d:cd:f5:e2:52:4d:
+ 84:94:23:d3:32:2f:ae:5f:da:43:a1:19:95:d2:17:
+ dd:49:14:b4:d9:48:1c:08:13:93:8e:d5:09:43:21:
+ b6:ce:52:e8:87:bb:d2:60:0d:c6:4e:bf:c5:93:6a:
+ c6:bf
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Alternative Name:
+ DNS:longOID.example
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.311.21.8.1492336001
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 72:77:8b:de:48:fb:6d:9a:94:b1:be:d4:90:7d:4c:e6:d3:79:
+ fa:fb:fc:3e:d5:3d:e9:a0:ce:28:2b:2f:94:77:3f:87:f8:9c:
+ 9f:91:1c:f3:f6:58:91:15:6b:24:b9:ca:ae:9f:ee:ca:c8:31:
+ db:1a:3d:bb:6b:83:6d:bc:81:8b:a1:79:d5:3e:bb:dd:93:fe:
+ 35:3e:b7:99:e0:d6:eb:58:0c:fd:42:73:dc:49:da:e2:b7:ae:
+ 15:ee:e6:cc:aa:ef:91:41:9a:18:46:8d:4a:39:65:a2:85:3c:
+ 7f:0c:41:f8:0b:9c:e8:1f:35:36:60:8d:8c:e0:8e:18:b1:06:
+ 57:d0:4e:c4:c3:cd:8f:6f:e7:76:02:52:da:03:43:61:2b:b3:
+ bf:19:fd:73:0d:6a:0b:b4:b6:cb:a9:6f:70:4e:53:2a:54:07:
+ b3:74:fd:85:49:57:5b:23:8d:8c:6b:53:2b:09:e8:41:a5:80:
+ 3f:69:1b:11:d1:6b:13:35:2e:f9:d6:50:15:d9:91:38:42:43:
+ e9:17:af:67:d9:96:a4:d1:6a:4f:cc:b4:a7:8e:48:1f:00:72:
+ 69:de:4d:f1:73:a4:47:12:67:e9:f9:07:3e:79:75:90:42:b8:
+ d4:b5:fd:d1:7e:35:04:f7:00:04:cf:f1:36:be:0f:27:81:1f:
+ a6:ba:88:6c
+-----BEGIN CERTIFICATE-----
+MIIDHTCCAgWgAwIBAgIRANq6UxkbCUuCsokmfcdvoAIwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0yMTEyMjExNjU5MjdaFw0yMjEyMjExNjU5
+MjdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQC/FxbYvCmcFuV2tJMVeK1uRcVKY0ahsnZxZVGcFMTqdBPkNN8vLGUR
+6FZSaRH5Dvx3u2OofBrGoXtubOcYJSXJ6PsGf6KpmP4qvIqzdba4fbbJaykIMiIQ
+y43WYMiDrfVYkdYR6FVW+4+jop9Iy3nkZUqMplJkn5k4NdTVrG/PoMtCjAfrIRcx
+OuuRe2JDpHVf76cvlPhpC9TsCeYAwIzdB2ML5HeqYBg8oOCuCuoOUju0+mowG1Bi
+IXNTMwFgoWuZWADzd8YPRhnKwl3N9eJSTYSUI9MyL65f2kOhGZXSF91JFLTZSBwI
+E5OO1QlDIbbOUuiHu9JgDcZOv8WTasa/AgMBAAGjbjBsMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGC
+D2xvbmdPSUQuZXhhbXBsZTAbBgNVHSAEFDASMBAGDisGAQQBgjcVCIXHzPsBMA0G
+CSqGSIb3DQEBCwUAA4IBAQByd4veSPttmpSxvtSQfUzm03n6+/w+1T3poM4oKy+U
+dz+H+JyfkRzz9liRFWskucqun+7KyDHbGj27a4NtvIGLoXnVPrvdk/41PreZ4Nbr
+WAz9QnPcSdrit64V7ubMqu+RQZoYRo1KOWWihTx/DEH4C5zoHzU2YI2M4I4YsQZX
+0E7Ew82Pb+d2AlLaA0NhK7O/Gf1zDWoLtLbLqW9wTlMqVAezdP2FSVdbI42Ma1Mr
+CehBpYA/aRsR0WsTNS751lAV2ZE4QkPpF69n2Zak0WpPzLSnjkgfAHJp3k3xc6RH
+Emfp+Qc+eXWQQrjUtf3RfjUE9wAEz/E2vg8ngR+muohs
+-----END CERTIFICATE-----`
+
+func TestLargeOID(t *testing.T) {
+ // See Issue 49678.
+ b, _ := pem.Decode([]byte(largeOIDPEM))
+ if b == nil {
+ t.Fatalf("couldn't decode test certificate")
+ }
+ _, err := ParseCertificate(b.Bytes)
+ if err != nil {
+ t.Fatalf("ParseCertificate to failed to parse certificate with large OID: %s", err)
+ }
+}
diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go
index 8f953f6..d1edcb8 100644
--- a/src/database/sql/fakedb_test.go
+++ b/src/database/sql/fakedb_test.go
@@ -676,6 +676,9 @@
if c.waiter != nil {
c.waiter(ctx)
+ if err := ctx.Err(); err != nil {
+ return nil, err
+ }
}
if stmt.wait > 0 {
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 1bb9afc..a921dd5 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -55,6 +55,10 @@
}
}
+// pollDuration is an arbitrary interval to wait between checks when polling for
+// a condition to occur.
+const pollDuration = 5 * time.Millisecond
+
const fakeDBName = "foo"
var chrisBirthday = time.Unix(123456789, 0)
@@ -173,7 +177,7 @@
}
var numOpen int
- if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
+ if !waitCondition(t, func() bool {
numOpen = db.numOpenConns()
return numOpen == 0
}) {
@@ -197,16 +201,14 @@
}
// Dependencies are closed via a goroutine, so this polls waiting for
-// numDeps to fall to want, waiting up to d.
-func (db *DB) numDepsPollUntil(want int, d time.Duration) int {
- deadline := time.Now().Add(d)
- for {
- n := db.numDeps()
- if n <= want || time.Now().After(deadline) {
- return n
- }
- time.Sleep(50 * time.Millisecond)
- }
+// numDeps to fall to want, waiting up to nearly the test's deadline.
+func (db *DB) numDepsPoll(t *testing.T, want int) int {
+ var n int
+ waitCondition(t, func() bool {
+ n = db.numDeps()
+ return n <= want
+ })
+ return n
}
func (db *DB) numFreeConns() int {
@@ -229,7 +231,7 @@
t.Errorf("free conns = %d; want %d", g, w)
}
- if n := db.numDepsPollUntil(0, time.Second); n > 0 {
+ if n := db.numDepsPoll(t, 0); n > 0 {
t.Errorf("number of dependencies = %d; expected 0", n)
db.dumpDeps(t)
}
@@ -321,7 +323,7 @@
for rows.Next() {
if index == 2 {
cancel()
- waitForRowsClose(t, rows, 5*time.Second)
+ waitForRowsClose(t, rows)
}
var r row
err = rows.Scan(&r.age, &r.name)
@@ -355,29 +357,43 @@
// And verify that the final rows.Next() call, which hit EOF,
// also closed the rows connection.
- waitForRowsClose(t, rows, 5*time.Second)
- waitForFree(t, db, 5*time.Second, 1)
+ waitForRowsClose(t, rows)
+ waitForFree(t, db, 1)
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
t.Errorf("executed %d Prepare statements; want 1", prepares)
}
}
-func waitCondition(waitFor, checkEvery time.Duration, fn func() bool) bool {
- deadline := time.Now().Add(waitFor)
- for time.Now().Before(deadline) {
+func waitCondition(t testing.TB, fn func() bool) bool {
+ timeout := 5 * time.Second
+
+ type deadliner interface {
+ Deadline() (time.Time, bool)
+ }
+ if td, ok := t.(deadliner); ok {
+ if deadline, ok := td.Deadline(); ok {
+ timeout = time.Until(deadline)
+ timeout = timeout * 19 / 20 // Give 5% headroom for cleanup and error-reporting.
+ }
+ }
+
+ deadline := time.Now().Add(timeout)
+ for {
if fn() {
return true
}
- time.Sleep(checkEvery)
+ if time.Until(deadline) < pollDuration {
+ return false
+ }
+ time.Sleep(pollDuration)
}
- return false
}
// waitForFree checks db.numFreeConns until either it equals want or
// the maxWait time elapses.
-func waitForFree(t *testing.T, db *DB, maxWait time.Duration, want int) {
+func waitForFree(t *testing.T, db *DB, want int) {
var numFree int
- if !waitCondition(maxWait, 5*time.Millisecond, func() bool {
+ if !waitCondition(t, func() bool {
numFree = db.numFreeConns()
return numFree == want
}) {
@@ -385,8 +401,8 @@
}
}
-func waitForRowsClose(t *testing.T, rows *Rows, maxWait time.Duration) {
- if !waitCondition(maxWait, 5*time.Millisecond, func() bool {
+func waitForRowsClose(t *testing.T, rows *Rows) {
+ if !waitCondition(t, func() bool {
rows.closemu.RLock()
defer rows.closemu.RUnlock()
return rows.closed
@@ -402,26 +418,31 @@
defer closeDB(t, db)
prepares0 := numPrepares(t, db)
- // TODO(kardianos): convert this from using a timeout to using an explicit
- // cancel when the query signals that it is "executing" the query.
- ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
+ ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// This will trigger the *fakeConn.Prepare method which will take time
// performing the query. The ctxDriverPrepare func will check the context
// after this and close the rows and return an error.
- _, err := db.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
- if err != context.DeadlineExceeded {
+ c, err := db.Conn(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ c.dc.ci.(*fakeConn).waiter = func(c context.Context) {
+ cancel()
+ <-ctx.Done()
+ }
+ _, err = c.QueryContext(ctx, "SELECT|people|age,name|")
+ c.Close()
+ if err != context.Canceled {
t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
}
// Verify closed rows connection after error condition.
- waitForFree(t, db, 5*time.Second, 1)
+ waitForFree(t, db, 1)
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
- // TODO(kardianos): if the context timeouts before the db.QueryContext
- // executes this check may fail. After adjusting how the context
- // is canceled above revert this back to a Fatal error.
- t.Logf("executed %d Prepare statements; want 1", prepares)
+ t.Fatalf("executed %d Prepare statements; want 1", prepares)
}
}
@@ -439,19 +460,19 @@
}
tx.keepConnOnRollback = false
- go func() {
- time.Sleep(15 * time.Millisecond)
+ tx.dc.ci.(*fakeConn).waiter = func(c context.Context) {
cancel()
- }()
+ <-ctx.Done()
+ }
// This will trigger the *fakeConn.Prepare method which will take time
// performing the query. The ctxDriverPrepare func will check the context
// after this and close the rows and return an error.
- _, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
+ _, err = tx.QueryContext(ctx, "SELECT|people|age,name|")
if err != context.Canceled {
t.Fatalf("expected QueryContext to error with context canceled but returned %v", err)
}
- waitForFree(t, db, 5*time.Second, 0)
+ waitForFree(t, db, 0)
}
// TestTxContextWaitNoDiscard is the same as TestTxContextWait, but should not discard
@@ -480,7 +501,7 @@
t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
}
- waitForFree(t, db, 5*time.Second, 1)
+ waitForFree(t, db, 1)
}
// TestUnsupportedOptions checks that the database fails when a driver that
@@ -565,7 +586,7 @@
// And verify that the final rows.Next() call, which hit EOF,
// also closed the rows connection.
- waitForFree(t, db, 5*time.Second, 1)
+ waitForFree(t, db, 1)
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
t.Errorf("executed %d Prepare statements; want 1", prepares)
}
@@ -2083,18 +2104,15 @@
}
}()
}
- // Sleep for twice the expected length of time for the
- // batch of 50 queries above to finish before starting
- // the next round.
- time.Sleep(2 * sleepMillis * time.Millisecond)
+ // Wait for the batch of queries above to finish before starting the next round.
+ wg.Wait()
}
- wg.Wait()
if g, w := db.numFreeConns(), 10; g != w {
t.Errorf("free conns = %d; want %d", g, w)
}
- if n := db.numDepsPollUntil(20, time.Second); n > 20 {
+ if n := db.numDepsPoll(t, 20); n > 20 {
t.Errorf("number of dependencies = %d; expected <= 20", n)
db.dumpDeps(t)
}
@@ -2119,7 +2137,7 @@
t.Errorf("free conns = %d; want %d", g, w)
}
- if n := db.numDepsPollUntil(10, time.Second); n > 10 {
+ if n := db.numDepsPoll(t, 10); n > 10 {
t.Errorf("number of dependencies = %d; expected <= 10", n)
db.dumpDeps(t)
}
@@ -2130,7 +2148,7 @@
t.Errorf("free conns = %d; want %d", g, w)
}
- if n := db.numDepsPollUntil(5, time.Second); n > 5 {
+ if n := db.numDepsPoll(t, 5); n > 5 {
t.Errorf("number of dependencies = %d; expected 0", n)
db.dumpDeps(t)
}
@@ -2141,7 +2159,7 @@
t.Errorf("free conns = %d; want %d", g, w)
}
- if n := db.numDepsPollUntil(5, time.Second); n > 5 {
+ if n := db.numDepsPoll(t, 5); n > 5 {
t.Errorf("number of dependencies = %d; expected 0", n)
db.dumpDeps(t)
}
@@ -2400,13 +2418,14 @@
tx2.Commit()
// Give connectionCleaner chance to run.
- for i := 0; i < 100 && closes != 1; i++ {
- time.Sleep(time.Millisecond)
+ waitCondition(t, func() bool {
driver.mu.Lock()
opens = driver.openCount - opens0
closes = driver.closeCount - closes0
driver.mu.Unlock()
- }
+
+ return closes == 1
+ })
if opens != 3 {
t.Errorf("opens = %d; want 3", opens)
@@ -2466,18 +2485,15 @@
}
}()
}
- // Sleep for twice the expected length of time for the
- // batch of 50 queries above to finish before starting
- // the next round.
- time.Sleep(2 * sleepMillis * time.Millisecond)
+ // Wait for the batch of queries above to finish before starting the next round.
+ wg.Wait()
}
- wg.Wait()
if g, w := db.numFreeConns(), 2; g != w {
t.Errorf("free conns = %d; want %d", g, w)
}
- if n := db.numDepsPollUntil(4, time.Second); n > 4 {
+ if n := db.numDepsPoll(t, 4); n > 4 {
t.Errorf("number of dependencies = %d; expected <= 4", n)
db.dumpDeps(t)
}
@@ -2496,7 +2512,7 @@
db.dumpDeps(t)
}
- if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
+ if !waitCondition(t, func() bool {
return len(stmt.css) <= nquery
}) {
t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery)
@@ -2510,7 +2526,7 @@
t.Errorf("free conns = %d; want %d", g, w)
}
- if n := db.numDepsPollUntil(2, time.Second); n > 2 {
+ if n := db.numDepsPoll(t, 2); n > 2 {
t.Errorf("number of dependencies = %d; expected <= 2", n)
db.dumpDeps(t)
}
@@ -2942,7 +2958,7 @@
if ct > 0 {
return
}
- time.Sleep(10 * time.Millisecond)
+ time.Sleep(pollDuration)
}
}()
@@ -3721,7 +3737,7 @@
// Wait for the context to cancel and tx to rollback.
for tx.isDone() == false {
- time.Sleep(3 * time.Millisecond)
+ time.Sleep(pollDuration)
}
}
defer func() { hookTxGrabConn = nil }()
diff --git a/src/debug/buildinfo/buildinfo.go b/src/debug/buildinfo/buildinfo.go
index 2c0200e..8de03ff 100644
--- a/src/debug/buildinfo/buildinfo.go
+++ b/src/debug/buildinfo/buildinfo.go
@@ -75,8 +75,8 @@
if err != nil {
return nil, err
}
- bi := &BuildInfo{}
- if err := bi.UnmarshalText([]byte(mod)); err != nil {
+ bi, err := debug.ParseBuildInfo(mod)
+ if err != nil {
return nil, err
}
bi.GoVersion = vers
diff --git a/src/debug/buildinfo/buildinfo_test.go b/src/debug/buildinfo/buildinfo_test.go
index 8346be0..ac71626 100644
--- a/src/debug/buildinfo/buildinfo_test.go
+++ b/src/debug/buildinfo/buildinfo_test.go
@@ -212,12 +212,10 @@
} else {
if tc.wantErr != "" {
t.Fatalf("unexpected success; want error containing %q", tc.wantErr)
- } else if got, err := info.MarshalText(); err != nil {
- t.Fatalf("unexpected error marshaling BuildInfo: %v", err)
- } else if got := cleanOutputForComparison(string(got)); got != tc.want {
- if got != tc.want {
- t.Fatalf("got:\n%s\nwant:\n%s", got, tc.want)
- }
+ }
+ got := info.String()
+ if clean := cleanOutputForComparison(string(got)); got != tc.want && clean != tc.want {
+ t.Fatalf("got:\n%s\nwant:\n%s", got, tc.want)
}
}
})
diff --git a/src/debug/dwarf/testdata/bitfields.c b/src/debug/dwarf/testdata/bitfields.c
new file mode 100644
index 0000000..0583333
--- /dev/null
+++ b/src/debug/dwarf/testdata/bitfields.c
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Linux ELF:
+gcc -gdwarf-4 -m64 -c bitfields.c -o bitfields.elf4
+*/
+
+typedef struct another_struct {
+ unsigned short quix;
+ int xyz[0];
+ unsigned x:1;
+ long long array[40];
+} t_another_struct;
+t_another_struct q2;
+
diff --git a/src/debug/dwarf/testdata/bitfields.elf4 b/src/debug/dwarf/testdata/bitfields.elf4
new file mode 100644
index 0000000..2e06e68
--- /dev/null
+++ b/src/debug/dwarf/testdata/bitfields.elf4
Binary files differ
diff --git a/src/debug/dwarf/testdata/typedef.elf5 b/src/debug/dwarf/testdata/typedef.elf5
new file mode 100644
index 0000000..aec48f6
--- /dev/null
+++ b/src/debug/dwarf/testdata/typedef.elf5
Binary files differ
diff --git a/src/debug/dwarf/type.go b/src/debug/dwarf/type.go
index 2e5a605..9c15cfb 100644
--- a/src/debug/dwarf/type.go
+++ b/src/debug/dwarf/type.go
@@ -33,10 +33,14 @@
// Basic types
// A BasicType holds fields common to all basic types.
+//
+// See the documentation for StructField for more info on the interpretation of
+// the BitSize/BitOffset/DataBitOffset fields.
type BasicType struct {
CommonType
- BitSize int64
- BitOffset int64
+ BitSize int64
+ BitOffset int64
+ DataBitOffset int64
}
func (b *BasicType) Basic() *BasicType { return b }
@@ -150,13 +154,87 @@
}
// A StructField represents a field in a struct, union, or C++ class type.
+//
+// Bit Fields
+//
+// The BitSize, BitOffset, and DataBitOffset fields describe the bit
+// size and offset of data members declared as bit fields in C/C++
+// struct/union/class types.
+//
+// BitSize is the number of bits in the bit field.
+//
+// DataBitOffset, if non-zero, is the number of bits from the start of
+// the enclosing entity (e.g. containing struct/class/union) to the
+// start of the bit field. This corresponds to the DW_AT_data_bit_offset
+// DWARF attribute that was introduced in DWARF 4.
+//
+// BitOffset, if non-zero, is the number of bits between the most
+// significant bit of the storage unit holding the bit field to the
+// most significant bit of the bit field. Here "storage unit" is the
+// type name before the bit field (for a field "unsigned x:17", the
+// storage unit is "unsigned"). BitOffset values can vary depending on
+// the endianness of the system. BitOffset corresponds to the
+// DW_AT_bit_offset DWARF attribute that was deprecated in DWARF 4 and
+// removed in DWARF 5.
+//
+// At most one of DataBitOffset and BitOffset will be non-zero;
+// DataBitOffset/BitOffset will only be non-zero if BitSize is
+// non-zero. Whether a C compiler uses one or the other
+// will depend on compiler vintage and command line options.
+//
+// Here is an example of C/C++ bit field use, along with what to
+// expect in terms of DWARF bit offset info. Consider this code:
+//
+// struct S {
+// int q;
+// int j:5;
+// int k:6;
+// int m:5;
+// int n:8;
+// } s;
+//
+// For the code above, one would expect to see the following for
+// DW_AT_bit_offset values (using GCC 8):
+//
+// Little | Big
+// Endian | Endian
+// |
+// "j": 27 | 0
+// "k": 21 | 5
+// "m": 16 | 11
+// "n": 8 | 16
+//
+// Note that in the above the offsets are purely with respect to the
+// containing storage unit for j/k/m/n -- these values won't vary based
+// on the size of prior data members in the containing struct.
+//
+// If the compiler emits DW_AT_data_bit_offset, the expected values
+// would be:
+//
+// "j": 32
+// "k": 37
+// "m": 43
+// "n": 48
+//
+// Here the value 32 for "j" reflects the fact that the bit field is
+// preceded by other data members (recall that DW_AT_data_bit_offset
+// values are relative to the start of the containing struct). Hence
+// DW_AT_data_bit_offset values can be quite large for structs with
+// many fields.
+//
+// DWARF also allow for the possibility of base types that have
+// non-zero bit size and bit offset, so this information is also
+// captured for base types, but it is worth noting that it is not
+// possible to trigger this behavior using mainstream languages.
+//
type StructField struct {
- Name string
- Type Type
- ByteOffset int64
- ByteSize int64 // usually zero; use Type.Size() for normal fields
- BitOffset int64 // within the ByteSize bytes at ByteOffset
- BitSize int64 // zero if not a bit field
+ Name string
+ Type Type
+ ByteOffset int64
+ ByteSize int64 // usually zero; use Type.Size() for normal fields
+ BitOffset int64
+ DataBitOffset int64
+ BitSize int64 // zero if not a bit field
}
func (t *StructType) String() string {
@@ -166,6 +244,13 @@
return t.Defn()
}
+func (f *StructField) bitOffset() int64 {
+ if f.BitOffset != 0 {
+ return f.BitOffset
+ }
+ return f.DataBitOffset
+}
+
func (t *StructType) Defn() string {
s := t.Kind
if t.StructName != "" {
@@ -184,7 +269,7 @@
s += "@" + strconv.FormatInt(f.ByteOffset, 10)
if f.BitSize > 0 {
s += " : " + strconv.FormatInt(f.BitSize, 10)
- s += "@" + strconv.FormatInt(f.BitOffset, 10)
+ s += "@" + strconv.FormatInt(f.bitOffset(), 10)
}
}
s += "}"
@@ -469,8 +554,12 @@
// AttrName: name of base type in programming language of the compilation unit [required]
// AttrEncoding: encoding value for type (encFloat etc) [required]
// AttrByteSize: size of type in bytes [required]
- // AttrBitOffset: for sub-byte types, size in bits
- // AttrBitSize: for sub-byte types, bit offset of high order bit in the AttrByteSize bytes
+ // AttrBitOffset: bit offset of value within containing storage unit
+ // AttrDataBitOffset: bit offset of value within containing storage unit
+ // AttrBitSize: size in bits
+ //
+ // For most languages BitOffset/DataBitOffset/BitSize will not be present
+ // for base types.
name, _ := e.Val(AttrName).(string)
enc, ok := e.Val(AttrEncoding).(int64)
if !ok {
@@ -517,8 +606,12 @@
t.Name = name
t.BitSize, _ = e.Val(AttrBitSize).(int64)
haveBitOffset := false
- if t.BitOffset, haveBitOffset = e.Val(AttrBitOffset).(int64); !haveBitOffset {
- t.BitOffset, _ = e.Val(AttrDataBitOffset).(int64)
+ haveDataBitOffset := false
+ t.BitOffset, haveBitOffset = e.Val(AttrBitOffset).(int64)
+ t.DataBitOffset, haveDataBitOffset = e.Val(AttrDataBitOffset).(int64)
+ if haveBitOffset && haveDataBitOffset {
+ err = DecodeError{name, e.Offset, "duplicate bit offset attributes"}
+ goto Error
}
case TagClassType, TagStructType, TagUnionType:
@@ -533,6 +626,7 @@
// AttrType: type of member [required]
// AttrByteSize: size in bytes
// AttrBitOffset: bit offset within bytes for bit fields
+ // AttrDataBitOffset: field bit offset relative to struct start
// AttrBitSize: bit size for bit fields
// AttrDataMemberLoc: location within struct [required for struct, class]
// There is much more to handle C++, all ignored for now.
@@ -551,7 +645,8 @@
t.Incomplete = e.Val(AttrDeclaration) != nil
t.Field = make([]*StructField, 0, 8)
var lastFieldType *Type
- var lastFieldBitOffset int64
+ var lastFieldBitSize int64
+ var lastFieldByteOffset int64
for kid := next(); kid != nil; kid = next() {
if kid.Tag != TagMember {
continue
@@ -578,30 +673,31 @@
f.ByteOffset = loc
}
- haveBitOffset := false
f.Name, _ = kid.Val(AttrName).(string)
f.ByteSize, _ = kid.Val(AttrByteSize).(int64)
- if f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64); !haveBitOffset {
- f.BitOffset, haveBitOffset = kid.Val(AttrDataBitOffset).(int64)
+ haveBitOffset := false
+ haveDataBitOffset := false
+ f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64)
+ f.DataBitOffset, haveDataBitOffset = kid.Val(AttrDataBitOffset).(int64)
+ if haveBitOffset && haveDataBitOffset {
+ err = DecodeError{name, e.Offset, "duplicate bit offset attributes"}
+ goto Error
}
f.BitSize, _ = kid.Val(AttrBitSize).(int64)
t.Field = append(t.Field, f)
- bito := f.BitOffset
- if !haveBitOffset {
- bito = f.ByteOffset * 8
- }
- if bito == lastFieldBitOffset && t.Kind != "union" {
+ if lastFieldBitSize == 0 && lastFieldByteOffset == f.ByteOffset && t.Kind != "union" {
// Last field was zero width. Fix array length.
// (DWARF writes out 0-length arrays as if they were 1-length arrays.)
fixups.recordArrayType(lastFieldType)
}
lastFieldType = &f.Type
- lastFieldBitOffset = bito
+ lastFieldByteOffset = f.ByteOffset
+ lastFieldBitSize = f.BitSize
}
if t.Kind != "union" {
b, ok := e.Val(AttrByteSize).(int64)
- if ok && b*8 == lastFieldBitOffset {
+ if ok && b == lastFieldByteOffset {
// Final field must be zero width. Fix array length.
fixups.recordArrayType(lastFieldType)
}
diff --git a/src/debug/dwarf/type_test.go b/src/debug/dwarf/type_test.go
index 431d085..0acc606 100644
--- a/src/debug/dwarf/type_test.go
+++ b/src/debug/dwarf/type_test.go
@@ -83,15 +83,19 @@
return d
}
-func TestTypedefsELF(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf"), "elf") }
-
-func TestTypedefsMachO(t *testing.T) {
- testTypedefs(t, machoData(t, "testdata/typedef.macho"), "macho")
+func TestTypedefsELF(t *testing.T) {
+ testTypedefs(t, elfData(t, "testdata/typedef.elf"), "elf", typedefTests)
}
-func TestTypedefsELFDwarf4(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf4"), "elf") }
+func TestTypedefsMachO(t *testing.T) {
+ testTypedefs(t, machoData(t, "testdata/typedef.macho"), "macho", typedefTests)
+}
-func testTypedefs(t *testing.T, d *Data, kind string) {
+func TestTypedefsELFDwarf4(t *testing.T) {
+ testTypedefs(t, elfData(t, "testdata/typedef.elf4"), "elf", typedefTests)
+}
+
+func testTypedefs(t *testing.T, d *Data, kind string, testcases map[string]string) {
r := d.Reader()
seen := make(map[string]bool)
for {
@@ -115,7 +119,7 @@
typstr = t1.Type.String()
}
- if want, ok := typedefTests[t1.Name]; ok {
+ if want, ok := testcases[t1.Name]; ok {
if seen[t1.Name] {
t.Errorf("multiple definitions for %s", t1.Name)
}
@@ -130,7 +134,7 @@
}
}
- for k := range typedefTests {
+ for k := range testcases {
if !seen[k] {
t.Errorf("missing %s", k)
}
@@ -229,21 +233,42 @@
}
}
-func TestBitOffsetsELF(t *testing.T) { testBitOffsets(t, elfData(t, "testdata/typedef.elf")) }
+var expectedBitOffsets1 = map[string]string{
+ "x": "S:1 DBO:32",
+ "y": "S:4 DBO:33",
+}
+
+var expectedBitOffsets2 = map[string]string{
+ "x": "S:1 BO:7",
+ "y": "S:4 BO:27",
+}
+
+func TestBitOffsetsELF(t *testing.T) {
+ f := "testdata/typedef.elf"
+ testBitOffsets(t, elfData(t, f), f, expectedBitOffsets2)
+}
func TestBitOffsetsMachO(t *testing.T) {
- testBitOffsets(t, machoData(t, "testdata/typedef.macho"))
+ f := "testdata/typedef.macho"
+ testBitOffsets(t, machoData(t, f), f, expectedBitOffsets2)
}
func TestBitOffsetsMachO4(t *testing.T) {
- testBitOffsets(t, machoData(t, "testdata/typedef.macho4"))
+ f := "testdata/typedef.macho4"
+ testBitOffsets(t, machoData(t, f), f, expectedBitOffsets1)
}
func TestBitOffsetsELFDwarf4(t *testing.T) {
- testBitOffsets(t, elfData(t, "testdata/typedef.elf4"))
+ f := "testdata/typedef.elf4"
+ testBitOffsets(t, elfData(t, f), f, expectedBitOffsets1)
}
-func testBitOffsets(t *testing.T, d *Data) {
+func TestBitOffsetsELFDwarf5(t *testing.T) {
+ f := "testdata/typedef.elf5"
+ testBitOffsets(t, elfData(t, f), f, expectedBitOffsets1)
+}
+
+func testBitOffsets(t *testing.T, d *Data, tag string, expectedBitOffsets map[string]string) {
r := d.Reader()
for {
e, err := r.Next()
@@ -262,15 +287,26 @@
t1 := typ.(*StructType)
+ bitInfoDump := func(f *StructField) string {
+ res := fmt.Sprintf("S:%d", f.BitSize)
+ if f.BitOffset != 0 {
+ res += fmt.Sprintf(" BO:%d", f.BitOffset)
+ }
+ if f.DataBitOffset != 0 {
+ res += fmt.Sprintf(" DBO:%d", f.DataBitOffset)
+ }
+ return res
+ }
+
for _, field := range t1.Field {
// We're only testing for bitfields
if field.BitSize == 0 {
continue
}
-
- // Ensure BitOffset is not zero
- if field.BitOffset == 0 {
- t.Errorf("bit offset of field %s in %s %s is not set", field.Name, t1.Kind, t1.StructName)
+ got := bitInfoDump(field)
+ want := expectedBitOffsets[field.Name]
+ if got != want {
+ t.Errorf("%s: field %s in %s: got info %q want %q", tag, field.Name, t1.StructName, got, want)
}
}
}
@@ -279,3 +315,22 @@
}
}
}
+
+var bitfieldTests = map[string]string{
+ "t_another_struct": "struct another_struct {quix short unsigned int@0; xyz [0]int@4; x unsigned int@4 : 1@31; array [40]long long int@8}",
+}
+
+// TestBitFieldZeroArrayIssue50685 checks to make sure that the DWARF
+// type reading code doesn't get confused by the presence of a
+// specifically-sized bitfield member immediately following a field
+// whose type is a zero-length array. Prior to the fix for issue
+// 50685, we would get this type for the case in testdata/bitfields.c:
+//
+// another_struct {quix short unsigned int@0; xyz [-1]int@4; x unsigned int@4 : 1@31; array [40]long long int@8}
+//
+// Note the "-1" for the xyz field, which should be zero.
+//
+func TestBitFieldZeroArrayIssue50685(t *testing.T) {
+ f := "testdata/bitfields.elf4"
+ testTypedefs(t, elfData(t, f), "elf", bitfieldTests)
+}
diff --git a/src/debug/elf/elf_test.go b/src/debug/elf/elf_test.go
index a61b491..b8c310d 100644
--- a/src/debug/elf/elf_test.go
+++ b/src/debug/elf/elf_test.go
@@ -47,3 +47,25 @@
}
}
}
+
+func TestNobitsSection(t *testing.T) {
+ const testdata = "testdata/gcc-amd64-linux-exec"
+ f, err := Open(testdata)
+ if err != nil {
+ t.Fatalf("could not read %s: %v", testdata, err)
+ }
+ defer f.Close()
+ bss := f.Section(".bss")
+ bssData, err := bss.Data()
+ if err != nil {
+ t.Fatalf("error reading .bss section: %v", err)
+ }
+ if g, w := uint64(len(bssData)), bss.Size; g != w {
+ t.Errorf(".bss section length mismatch: got %d, want %d", g, w)
+ }
+ for i := range bssData {
+ if bssData[i] != 0 {
+ t.Fatalf("unexpected non-zero byte at offset %d: %#x", i, bssData[i])
+ }
+ }
+}
diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go
index eefcaab..8c84661 100644
--- a/src/debug/elf/file.go
+++ b/src/debug/elf/file.go
@@ -120,6 +120,9 @@
// Even if the section is stored compressed in the ELF file,
// the ReadSeeker reads uncompressed data.
func (s *Section) Open() io.ReadSeeker {
+ if s.Type == SHT_NOBITS {
+ return io.NewSectionReader(&zeroReader{}, 0, int64(s.Size))
+ }
if s.Flags&SHF_COMPRESSED == 0 {
return io.NewSectionReader(s.sr, 0, 1<<63-1)
}
@@ -1453,3 +1456,12 @@
}
return all, nil
}
+
+type zeroReader struct{}
+
+func (*zeroReader) ReadAt(p []byte, off int64) (n int, err error) {
+ for i := range p {
+ p[i] = 0
+ }
+ return len(p), nil
+}
diff --git a/src/encoding/json/fuzz_test.go b/src/encoding/json/fuzz_test.go
new file mode 100644
index 0000000..778664c
--- /dev/null
+++ b/src/encoding/json/fuzz_test.go
@@ -0,0 +1,83 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import (
+ "bytes"
+ "io"
+ "testing"
+)
+
+func FuzzUnmarshalJSON(f *testing.F) {
+ f.Add([]byte(`{
+"object": {
+ "slice": [
+ 1,
+ 2.0,
+ "3",
+ [4],
+ {5: {}}
+ ]
+},
+"slice": [[]],
+"string": ":)",
+"int": 1e5,
+"float": 3e-9"
+}`))
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ for _, typ := range []func() interface{}{
+ func() interface{} { return new(interface{}) },
+ func() interface{} { return new(map[string]interface{}) },
+ func() interface{} { return new([]interface{}) },
+ } {
+ i := typ()
+ if err := Unmarshal(b, i); err != nil {
+ return
+ }
+
+ encoded, err := Marshal(i)
+ if err != nil {
+ t.Fatalf("failed to marshal: %s", err)
+ }
+
+ if err := Unmarshal(encoded, i); err != nil {
+ t.Fatalf("failed to roundtrip: %s", err)
+ }
+ }
+ })
+}
+
+func FuzzDecoderToken(f *testing.F) {
+ f.Add([]byte(`{
+"object": {
+ "slice": [
+ 1,
+ 2.0,
+ "3",
+ [4],
+ {5: {}}
+ ]
+},
+"slice": [[]],
+"string": ":)",
+"int": 1e5,
+"float": 3e-9"
+}`))
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ r := bytes.NewReader(b)
+ d := NewDecoder(r)
+ for {
+ _, err := d.Token()
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return
+ }
+ }
+ })
+}
diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go
index 6859be0..7792ac7 100644
--- a/src/encoding/xml/marshal.go
+++ b/src/encoding/xml/marshal.go
@@ -512,7 +512,7 @@
}
fv := finfo.value(val, dontInitNilPointers)
- if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
+ if finfo.flags&fOmitEmpty != 0 && (!fv.IsValid() || isEmptyValue(fv)) {
continue
}
diff --git a/src/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go
index 5fdbae7..3fe7e2d 100644
--- a/src/encoding/xml/marshal_test.go
+++ b/src/encoding/xml/marshal_test.go
@@ -2495,3 +2495,39 @@
t.Errorf("error %q does not contain %q", err, want)
}
}
+
+// Issue 50164. Crash on zero value XML attribute.
+type LayerOne struct {
+ XMLName Name `xml:"l1"`
+
+ Value *float64 `xml:"value,omitempty"`
+ *LayerTwo `xml:",omitempty"`
+}
+
+type LayerTwo struct {
+ ValueTwo *int `xml:"value_two,attr,omitempty"`
+}
+
+func TestMarshalZeroValue(t *testing.T) {
+ proofXml := `<l1><value>1.2345</value></l1>`
+ var l1 LayerOne
+ err := Unmarshal([]byte(proofXml), &l1)
+ if err != nil {
+ t.Fatalf("unmarshal XML error: %v", err)
+ }
+ want := float64(1.2345)
+ got := *l1.Value
+ if got != want {
+ t.Fatalf("unexpected unmarshal result, want %f but got %f", want, got)
+ }
+
+ // Marshal again (or Encode again)
+ // In issue 50164, here `Marshal(l1)` will panic because of the zero value of xml attribute ValueTwo `value_two`.
+ anotherXML, err := Marshal(l1)
+ if err != nil {
+ t.Fatalf("marshal XML error: %v", err)
+ }
+ if string(anotherXML) != proofXml {
+ t.Fatalf("unexpected unmarshal result, want %q but got %q", proofXml, anotherXML)
+ }
+}
diff --git a/src/go.mod b/src/go.mod
index 07d0acf..bd6308a 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -3,7 +3,7 @@
go 1.18
require (
- golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa
+ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
golang.org/x/net v0.0.0-20211209124913-491a49abca63
)
diff --git a/src/go.sum b/src/go.sum
index cec5bc4..8bf0853 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -1,5 +1,5 @@
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E=
diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go
index bc14047..a74a827 100644
--- a/src/go/ast/ast.go
+++ b/src/go/ast/ast.go
@@ -224,11 +224,12 @@
return token.NoPos
}
-// A FieldList represents a list of Fields, enclosed by parentheses or braces.
+// A FieldList represents a list of Fields, enclosed by parentheses,
+// curly braces, or square brackets.
type FieldList struct {
- Opening token.Pos // position of opening parenthesis/brace, if any
+ Opening token.Pos // position of opening parenthesis/brace/bracket, if any
List []*Field // field list; or nil
- Closing token.Pos // position of closing parenthesis/brace, if any
+ Closing token.Pos // position of closing parenthesis/brace/bracket, if any
}
func (f *FieldList) Pos() token.Pos {
diff --git a/src/go/build/build.go b/src/go/build/build.go
index 6f7260b..dce0304 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -789,7 +789,7 @@
}
// package was not found
- return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir)
+ return p, fmt.Errorf("cannot find package %q in:\n\t%s", p.ImportPath, p.Dir)
}
if mode&FindOnly != 0 {
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 7f25038..7246565 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -88,6 +88,7 @@
< internal/itoa
< internal/unsafeheader
< runtime/internal/sys
+ < runtime/internal/syscall
< runtime/internal/atomic
< runtime/internal/math
< runtime
@@ -418,7 +419,7 @@
CGO, fmt, net !< CRYPTO;
# CRYPTO-MATH is core bignum-based crypto - no cgo, net; fmt now ok.
- CRYPTO, FMT, math/big
+ CRYPTO, FMT, math/big, embed
< crypto/rand
< crypto/internal/randutil
< crypto/ed25519
diff --git a/src/go/doc/doc_test.go b/src/go/doc/doc_test.go
index 3d17036..5a5fbd8 100644
--- a/src/go/doc/doc_test.go
+++ b/src/go/doc/doc_test.go
@@ -100,58 +100,56 @@
// test packages
for _, pkg := range pkgs {
- importPath := dataDir + "/" + pkg.Name
- var files []*ast.File
- for _, f := range pkg.Files {
- files = append(files, f)
- }
- doc, err := NewFromFiles(fset, files, importPath, mode)
- if err != nil {
- t.Error(err)
- continue
- }
-
- // golden files always use / in filenames - canonicalize them
- for i, filename := range doc.Filenames {
- doc.Filenames[i] = filepath.ToSlash(filename)
- }
-
- // print documentation
- var buf bytes.Buffer
- if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
- t.Error(err)
- continue
- }
- got := buf.Bytes()
-
- // update golden file if necessary
- golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
- if *update {
- err := os.WriteFile(golden, got, 0644)
- if err != nil {
- t.Error(err)
+ t.Run(pkg.Name, func(t *testing.T) {
+ importPath := dataDir + "/" + pkg.Name
+ var files []*ast.File
+ for _, f := range pkg.Files {
+ files = append(files, f)
}
- continue
- }
+ doc, err := NewFromFiles(fset, files, importPath, mode)
+ if err != nil {
+ t.Fatal(err)
+ }
- // get golden file
- want, err := os.ReadFile(golden)
- if err != nil {
- t.Error(err)
- continue
- }
+ // golden files always use / in filenames - canonicalize them
+ for i, filename := range doc.Filenames {
+ doc.Filenames[i] = filepath.ToSlash(filename)
+ }
- // compare
- if !bytes.Equal(got, want) {
- t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
- }
+ // print documentation
+ var buf bytes.Buffer
+ if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
+ t.Fatal(err)
+ }
+ got := buf.Bytes()
+
+ // update golden file if necessary
+ golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
+ if *update {
+ err := os.WriteFile(golden, got, 0644)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // get golden file
+ want, err := os.ReadFile(golden)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // compare
+ if !bytes.Equal(got, want) {
+ t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
+ }
+ })
}
}
func Test(t *testing.T) {
- test(t, 0)
- test(t, AllDecls)
- test(t, AllMethods)
+ t.Run("default", func(t *testing.T) { test(t, 0) })
+ t.Run("AllDecls", func(t *testing.T) { test(t, AllDecls) })
+ t.Run("AllMethods", func(t *testing.T) { test(t, AllMethods) })
}
func TestAnchorID(t *testing.T) {
@@ -162,3 +160,142 @@
t.Errorf("anchorID(%q) = %q; want %q", in, got, want)
}
}
+
+func TestFuncs(t *testing.T) {
+ fset := token.NewFileSet()
+ file, err := parser.ParseFile(fset, "funcs.go", strings.NewReader(funcsTestFile), parser.ParseComments)
+ if err != nil {
+ t.Fatal(err)
+ }
+ doc, err := NewFromFiles(fset, []*ast.File{file}, "importPath", Mode(0))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, f := range doc.Funcs {
+ f.Decl = nil
+ }
+ for _, ty := range doc.Types {
+ for _, f := range ty.Funcs {
+ f.Decl = nil
+ }
+ for _, m := range ty.Methods {
+ m.Decl = nil
+ }
+ }
+
+ compareFuncs := func(t *testing.T, msg string, got, want *Func) {
+ // ignore Decl and Examples
+ got.Decl = nil
+ got.Examples = nil
+ if !(got.Doc == want.Doc &&
+ got.Name == want.Name &&
+ got.Recv == want.Recv &&
+ got.Orig == want.Orig &&
+ got.Level == want.Level) {
+ t.Errorf("%s:\ngot %+v\nwant %+v", msg, got, want)
+ }
+ }
+
+ compareSlices(t, "Funcs", doc.Funcs, funcsPackage.Funcs, compareFuncs)
+ compareSlices(t, "Types", doc.Types, funcsPackage.Types, func(t *testing.T, msg string, got, want *Type) {
+ if got.Name != want.Name {
+ t.Errorf("%s.Name: got %q, want %q", msg, got.Name, want.Name)
+ } else {
+ compareSlices(t, got.Name+".Funcs", got.Funcs, want.Funcs, compareFuncs)
+ compareSlices(t, got.Name+".Methods", got.Methods, want.Methods, compareFuncs)
+ }
+ })
+}
+
+func compareSlices[E any](t *testing.T, name string, got, want []E, compareElem func(*testing.T, string, E, E)) {
+ if len(got) != len(want) {
+ t.Errorf("%s: got %d, want %d", name, len(got), len(want))
+ }
+ for i := 0; i < len(got) && i < len(want); i++ {
+ compareElem(t, fmt.Sprintf("%s[%d]", name, i), got[i], want[i])
+ }
+}
+
+const funcsTestFile = `
+package funcs
+
+func F() {}
+
+type S1 struct {
+ S2 // embedded, exported
+ s3 // embedded, unexported
+}
+
+func NewS1() S1 {return S1{} }
+func NewS1p() *S1 { return &S1{} }
+
+func (S1) M1() {}
+func (r S1) M2() {}
+func(S1) m3() {} // unexported not shown
+func (*S1) P1() {} // pointer receiver
+
+type S2 int
+func (S2) M3() {} // shown on S2
+
+type s3 int
+func (s3) M4() {} // shown on S1
+
+type G1[T any] struct {
+ *s3
+}
+
+func NewG1[T any]() G1[T] { return G1[T]{} }
+
+func (G1[T]) MG1() {}
+func (*G1[U]) MG2() {}
+
+type G2[T, U any] struct {}
+
+func NewG2[T, U any]() G2[T, U] { return G2[T, U]{} }
+
+func (G2[T, U]) MG3() {}
+func (*G2[A, B]) MG4() {}
+
+
+`
+
+var funcsPackage = &Package{
+ Funcs: []*Func{{Name: "F"}},
+ Types: []*Type{
+ {
+ Name: "G1",
+ Funcs: []*Func{{Name: "NewG1"}},
+ Methods: []*Func{
+ {Name: "M4", Recv: "G1", // TODO: synthesize a param for G1?
+ Orig: "s3", Level: 1},
+ {Name: "MG1", Recv: "G1[T]", Orig: "G1[T]", Level: 0},
+ {Name: "MG2", Recv: "*G1[U]", Orig: "*G1[U]", Level: 0},
+ },
+ },
+ {
+ Name: "G2",
+ Funcs: []*Func{{Name: "NewG2"}},
+ Methods: []*Func{
+ {Name: "MG3", Recv: "G2[T, U]", Orig: "G2[T, U]", Level: 0},
+ {Name: "MG4", Recv: "*G2[A, B]", Orig: "*G2[A, B]", Level: 0},
+ },
+ },
+ {
+ Name: "S1",
+ Funcs: []*Func{{Name: "NewS1"}, {Name: "NewS1p"}},
+ Methods: []*Func{
+ {Name: "M1", Recv: "S1", Orig: "S1", Level: 0},
+ {Name: "M2", Recv: "S1", Orig: "S1", Level: 0},
+ {Name: "M4", Recv: "S1", Orig: "s3", Level: 1},
+ {Name: "P1", Recv: "*S1", Orig: "*S1", Level: 0},
+ },
+ },
+ {
+ Name: "S2",
+ Methods: []*Func{
+ {Name: "M3", Recv: "S2", Orig: "S2", Level: 0},
+ },
+ },
+ },
+}
diff --git a/src/go/doc/reader.go b/src/go/doc/reader.go
index 7ff868f..d9e721d 100644
--- a/src/go/doc/reader.go
+++ b/src/go/doc/reader.go
@@ -5,11 +5,13 @@
package doc
import (
+ "fmt"
"go/ast"
"go/token"
"internal/lazyregexp"
"sort"
"strconv"
+ "strings"
)
// ----------------------------------------------------------------------------
@@ -22,8 +24,8 @@
//
type methodSet map[string]*Func
-// recvString returns a string representation of recv of the
-// form "T", "*T", or "BADRECV" (if not a proper receiver type).
+// recvString returns a string representation of recv of the form "T", "*T",
+// "T[A, ...]", "*T[A, ...]" or "BADRECV" (if not a proper receiver type).
//
func recvString(recv ast.Expr) string {
switch t := recv.(type) {
@@ -31,10 +33,34 @@
return t.Name
case *ast.StarExpr:
return "*" + recvString(t.X)
+ case *ast.IndexExpr:
+ // Generic type with one parameter.
+ return fmt.Sprintf("%s[%s]", recvString(t.X), recvParam(t.Index))
+ case *ast.IndexListExpr:
+ // Generic type with multiple parameters.
+ if len(t.Indices) > 0 {
+ var b strings.Builder
+ b.WriteString(recvString(t.X))
+ b.WriteByte('[')
+ b.WriteString(recvParam(t.Indices[0]))
+ for _, e := range t.Indices[1:] {
+ b.WriteString(", ")
+ b.WriteString(recvParam(e))
+ }
+ b.WriteByte(']')
+ return b.String()
+ }
}
return "BADRECV"
}
+func recvParam(p ast.Expr) string {
+ if id, ok := p.(*ast.Ident); ok {
+ return id.Name
+ }
+ return "BADPARAM"
+}
+
// set creates the corresponding Func for f and adds it to mset.
// If there are multiple f's with the same name, set keeps the first
// one with documentation; conflicts are ignored. The boolean
@@ -901,6 +927,7 @@
"any": true,
"bool": true,
"byte": true,
+ "comparable": true,
"complex64": true,
"complex128": true,
"error": true,
diff --git a/src/go/doc/testdata/b.0.golden b/src/go/doc/testdata/b.0.golden
index 9d93392..c06246a 100644
--- a/src/go/doc/testdata/b.0.golden
+++ b/src/go/doc/testdata/b.0.golden
@@ -46,6 +46,9 @@
FUNCTIONS
+ // Associated with comparable type if AllDecls is set.
+ func ComparableFactory() comparable
+
//
func F(x int) int
diff --git a/src/go/doc/testdata/b.1.golden b/src/go/doc/testdata/b.1.golden
index 66c47b5..2b62c34 100644
--- a/src/go/doc/testdata/b.1.golden
+++ b/src/go/doc/testdata/b.1.golden
@@ -38,6 +38,12 @@
//
func (x *T) M()
+ // Should only appear if AllDecls is set.
+ type comparable struct{} // overrides a predeclared type comparable
+
+ // Associated with comparable type if AllDecls is set.
+ func ComparableFactory() comparable
+
//
type notExported int
diff --git a/src/go/doc/testdata/b.2.golden b/src/go/doc/testdata/b.2.golden
index 9d93392..c06246a 100644
--- a/src/go/doc/testdata/b.2.golden
+++ b/src/go/doc/testdata/b.2.golden
@@ -46,6 +46,9 @@
FUNCTIONS
+ // Associated with comparable type if AllDecls is set.
+ func ComparableFactory() comparable
+
//
func F(x int) int
diff --git a/src/go/doc/testdata/b.go b/src/go/doc/testdata/b.go
index e50663b..61b512b 100644
--- a/src/go/doc/testdata/b.go
+++ b/src/go/doc/testdata/b.go
@@ -27,9 +27,15 @@
// Associated with uint type if AllDecls is set.
func uintFactory() uint {}
+// Associated with comparable type if AllDecls is set.
+func ComparableFactory() comparable {}
+
// Should only appear if AllDecls is set.
type uint struct{} // overrides a predeclared type uint
+// Should only appear if AllDecls is set.
+type comparable struct{} // overrides a predeclared type comparable
+
// ----------------------------------------------------------------------------
// Exported declarations associated with non-exported types must always be shown.
diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go
index 15a7b17..c9c5946 100644
--- a/src/go/internal/gcimporter/gcimporter_test.go
+++ b/src/go/internal/gcimporter/gcimporter_test.go
@@ -169,8 +169,9 @@
}
skip := map[string]string{
- "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this.
- "nested.go": "fails to compile", // TODO(rfindley): investigate this.
+ "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this.
+ "nested.go": "fails to compile", // TODO(rfindley): investigate this.
+ "issue50417.go": "inconsistent interface member sorting",
}
for _, entry := range list {
diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go
index c5b89aa..bff1c09 100644
--- a/src/go/internal/gcimporter/iimport.go
+++ b/src/go/internal/gcimporter/iimport.go
@@ -127,7 +127,7 @@
typCache: make(map[uint64]types.Type),
// Separate map for typeparams, keyed by their package and unique
// name (name with subscript).
- tparamIndex: make(map[ident]types.Type),
+ tparamIndex: make(map[ident]*types.TypeParam),
fake: fakeFileSet{
fset: fset,
@@ -181,6 +181,15 @@
p.doDecl(localpkg, name)
}
+ // SetConstraint can't be called if the constraint type is not yet complete.
+ // When type params are created in the 'P' case of (*importReader).obj(),
+ // the associated constraint type may not be complete due to recursion.
+ // Therefore, we defer calling SetConstraint there, and call it here instead
+ // after all types are complete.
+ for _, d := range p.later {
+ d.t.SetConstraint(d.constraint)
+ }
+
for _, typ := range p.interfaceList {
typ.Complete()
}
@@ -195,6 +204,11 @@
return localpkg, nil
}
+type setConstraintArgs struct {
+ t *types.TypeParam
+ constraint types.Type
+}
+
type iimporter struct {
exportVersion int64
ipath string
@@ -207,10 +221,13 @@
declData []byte
pkgIndex map[*types.Package]map[string]uint64
typCache map[uint64]types.Type
- tparamIndex map[ident]types.Type
+ tparamIndex map[ident]*types.TypeParam
fake fakeFileSet
interfaceList []*types.Interface
+
+ // Arguments for calls to SetConstraint that are deferred due to recursive types
+ later []setConstraintArgs
}
func (p *iimporter) doDecl(pkg *types.Package, name string) {
@@ -369,12 +386,10 @@
if r.p.exportVersion < iexportVersionGenerics {
errorf("unexpected type param type")
}
- // Remove the "path" from the type param name that makes it unique
- ix := strings.LastIndex(name, ".")
- if ix < 0 {
- errorf("missing path for type param")
- }
- tn := types.NewTypeName(pos, r.currPkg, name[ix+1:], nil)
+ // Remove the "path" from the type param name that makes it unique,
+ // and revert any unique name used for blank typeparams.
+ name0 := tparamName(name)
+ tn := types.NewTypeName(pos, r.currPkg, name0, nil)
t := types.NewTypeParam(tn, nil)
// To handle recursive references to the typeparam within its
// bound, save the partial type in tparamIndex before reading the bounds.
@@ -393,7 +408,11 @@
}
iface.MarkImplicit()
}
- t.SetConstraint(constraint)
+ // The constraint type may not be complete, if we
+ // are in the middle of a type recursion involving type
+ // constraints. So, we defer SetConstraint until we have
+ // completely set up all types in ImportData.
+ r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
case 'V':
typ := r.typ()
@@ -772,3 +791,21 @@
n, _ := typ.(*types.Named)
return n
}
+
+const blankMarker = "$"
+
+// tparamName returns the real name of a type parameter, after stripping its
+// qualifying prefix and reverting blank-name encoding. See tparamExportName
+// for details.
+func tparamName(exportName string) string {
+ // Remove the "path" from the type param name that makes it unique.
+ ix := strings.LastIndex(exportName, ".")
+ if ix < 0 {
+ errorf("malformed type parameter export name %s: missing prefix", exportName)
+ }
+ name := exportName[ix+1:]
+ if strings.HasPrefix(name, blankMarker) {
+ return "_"
+ }
+ return name
+}
diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go
index e456e29..51a3c3e 100644
--- a/src/go/parser/parser.go
+++ b/src/go/parser/parser.go
@@ -543,6 +543,13 @@
}
p.exprLev--
}
+ if p.tok == token.COMMA {
+ // Trailing commas are accepted in type parameter
+ // lists but not in array type declarations.
+ // Accept for better error handling but complain.
+ p.error(p.pos, "unexpected comma; expecting ]")
+ p.next()
+ }
p.expect(token.RBRACK)
elt := p.parseType()
return &ast.ArrayType{Lbrack: lbrack, Len: len, Elt: elt}
@@ -797,7 +804,7 @@
return
}
-func (p *parser) parseParameterList(name0 *ast.Ident, closing token.Token) (params []*ast.Field) {
+func (p *parser) parseParameterList(name0 *ast.Ident, typ0 ast.Expr, closing token.Token) (params []*ast.Field) {
if p.trace {
defer un(trace(p, "ParameterList"))
}
@@ -816,8 +823,17 @@
var named int // number of parameters that have an explicit name and type
for name0 != nil || p.tok != closing && p.tok != token.EOF {
- par := p.parseParamDecl(name0, typeSetsOK)
+ var par field
+ if typ0 != nil {
+ if typeSetsOK {
+ typ0 = p.embeddedElem(typ0)
+ }
+ par = field{name0, typ0}
+ } else {
+ par = p.parseParamDecl(name0, typeSetsOK)
+ }
name0 = nil // 1st name was consumed if present
+ typ0 = nil // 1st typ was consumed if present
if par.name != nil || par.typ != nil {
list = append(list, par)
if par.name != nil && par.typ != nil {
@@ -926,7 +942,7 @@
opening := p.pos
p.next()
// [T any](params) syntax
- list := p.parseParameterList(nil, token.RBRACK)
+ list := p.parseParameterList(nil, nil, token.RBRACK)
rbrack := p.expect(token.RBRACK)
tparams = &ast.FieldList{Opening: opening, List: list, Closing: rbrack}
// Type parameter lists must not be empty.
@@ -940,7 +956,7 @@
var fields []*ast.Field
if p.tok != token.RPAREN {
- fields = p.parseParameterList(nil, token.RPAREN)
+ fields = p.parseParameterList(nil, nil, token.RPAREN)
}
rparen := p.expect(token.RPAREN)
@@ -977,7 +993,7 @@
pos := p.expect(token.FUNC)
tparams, params := p.parseParameters(true)
if tparams != nil {
- p.error(tparams.Pos(), "function type cannot have type parameters")
+ p.error(tparams.Pos(), "function type must have no type parameters")
}
results := p.parseResult()
@@ -1004,18 +1020,21 @@
p.exprLev--
if name0, _ := x.(*ast.Ident); name0 != nil && p.tok != token.COMMA && p.tok != token.RBRACK {
// generic method m[T any]
- list := p.parseParameterList(name0, token.RBRACK)
- rbrack := p.expect(token.RBRACK)
- tparams := &ast.FieldList{Opening: lbrack, List: list, Closing: rbrack}
+ //
+ // Interface methods do not have type parameters. We parse them for a
+ // better error message and improved error recovery.
+ _ = p.parseParameterList(name0, nil, token.RBRACK)
+ _ = p.expect(token.RBRACK)
+ p.error(lbrack, "interface method must have no type parameters")
+
// TODO(rfindley) refactor to share code with parseFuncType.
_, params := p.parseParameters(false)
results := p.parseResult()
idents = []*ast.Ident{ident}
typ = &ast.FuncType{
- Func: token.NoPos,
- TypeParams: tparams,
- Params: params,
- Results: results,
+ Func: token.NoPos,
+ Params: params,
+ Results: results,
}
} else {
// embedded instantiated type
@@ -1781,7 +1800,12 @@
return tok, tok.Precedence()
}
-func (p *parser) parseBinaryExpr(x ast.Expr, prec1 int) ast.Expr {
+// parseBinaryExpr parses a (possibly) binary expression.
+// If x is non-nil, it is used as the left operand.
+// If check is true, operands are checked to be valid expressions.
+//
+// TODO(rfindley): parseBinaryExpr has become overloaded. Consider refactoring.
+func (p *parser) parseBinaryExpr(x ast.Expr, prec1 int, check bool) ast.Expr {
if p.trace {
defer un(trace(p, "BinaryExpr"))
}
@@ -1795,11 +1819,32 @@
return x
}
pos := p.expect(op)
- y := p.parseBinaryExpr(nil, oprec+1)
- x = &ast.BinaryExpr{X: p.checkExpr(x), OpPos: pos, Op: op, Y: p.checkExpr(y)}
+ y := p.parseBinaryExpr(nil, oprec+1, check)
+ if check {
+ x = p.checkExpr(x)
+ y = p.checkExpr(y)
+ }
+ x = &ast.BinaryExpr{X: x, OpPos: pos, Op: op, Y: y}
}
}
+// checkBinaryExpr checks binary expressions that were not already checked by
+// parseBinaryExpr, because the latter was called with check=false.
+func (p *parser) checkBinaryExpr(x ast.Expr) {
+ bx, ok := x.(*ast.BinaryExpr)
+ if !ok {
+ return
+ }
+
+ bx.X = p.checkExpr(bx.X)
+ bx.Y = p.checkExpr(bx.Y)
+
+ // parseBinaryExpr checks x and y for each binary expr in a tree, so we
+ // traverse the tree of binary exprs starting from x.
+ p.checkBinaryExpr(bx.X)
+ p.checkBinaryExpr(bx.Y)
+}
+
// The result may be a type or even a raw type ([...]int). Callers must
// check the result (using checkExpr or checkExprOrType), depending on
// context.
@@ -1808,7 +1853,7 @@
defer un(trace(p, "Expression"))
}
- return p.parseBinaryExpr(nil, token.LowestPrec+1)
+ return p.parseBinaryExpr(nil, token.LowestPrec+1, true)
}
func (p *parser) parseRhs() ast.Expr {
@@ -2531,12 +2576,12 @@
return spec
}
-func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident) {
+func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident, typ0 ast.Expr) {
if p.trace {
defer un(trace(p, "parseGenericType"))
}
- list := p.parseParameterList(name0, token.RBRACK)
+ list := p.parseParameterList(name0, typ0, token.RBRACK)
closePos := p.expect(token.RBRACK)
spec.TypeParams = &ast.FieldList{Opening: openPos, List: list, Closing: closePos}
// Let the type checker decide whether to accept type parameters on aliases:
@@ -2561,31 +2606,85 @@
lbrack := p.pos
p.next()
if p.tok == token.IDENT {
- // array type or generic type: [name0...
- name0 := p.parseIdent()
+ // We may have an array type or a type parameter list.
+ // In either case we expect an expression x (which may
+ // just be a name, or a more complex expression) which
+ // we can analyze further.
+ //
+ // A type parameter list may have a type bound starting
+ // with a "[" as in: P []E. In that case, simply parsing
+ // an expression would lead to an error: P[] is invalid.
+ // But since index or slice expressions are never constant
+ // and thus invalid array length expressions, if we see a
+ // "[" following a name it must be the start of an array
+ // or slice constraint. Only if we don't see a "[" do we
+ // need to parse a full expression.
// Index or slice expressions are never constant and thus invalid
// array length expressions. Thus, if we see a "[" following name
// we can safely assume that "[" name starts a type parameter list.
- var x ast.Expr // x != nil means x is the array length expression
+ var x ast.Expr = p.parseIdent()
if p.tok != token.LBRACK {
- // We may still have either an array type or generic type -- check if
- // name0 is the entire expr.
+ // To parse the expression starting with name, expand
+ // the call sequence we would get by passing in name
+ // to parser.expr, and pass in name to parsePrimaryExpr.
p.exprLev++
- lhs := p.parsePrimaryExpr(name0)
- x = p.parseBinaryExpr(lhs, token.LowestPrec+1)
+ lhs := p.parsePrimaryExpr(x)
+ x = p.parseBinaryExpr(lhs, token.LowestPrec+1, false)
p.exprLev--
- if x == name0 && p.tok != token.RBRACK {
- x = nil
+ }
+
+ // analyze the cases
+ var pname *ast.Ident // pname != nil means pname is the type parameter name
+ var ptype ast.Expr // ptype != nil means ptype is the type parameter type; pname != nil in this case
+
+ switch t := x.(type) {
+ case *ast.Ident:
+ // Unless we see a "]", we are at the start of a type parameter list.
+ if p.tok != token.RBRACK {
+ // d.Name "[" name ...
+ pname = t
+ // no ptype
+ }
+ case *ast.BinaryExpr:
+ // If we have an expression of the form name*T, and T is a (possibly
+ // parenthesized) type literal or the next token is a comma, we are
+ // at the start of a type parameter list.
+ if name, _ := t.X.(*ast.Ident); name != nil {
+ if t.Op == token.MUL && (isTypeLit(t.Y) || p.tok == token.COMMA) {
+ // d.Name "[" name "*" t.Y
+ // d.Name "[" name "*" t.Y ","
+ // convert t into unary *t.Y
+ pname = name
+ ptype = &ast.StarExpr{Star: t.OpPos, X: t.Y}
+ }
+ }
+ if pname == nil {
+ // A normal binary expression. Since we passed check=false, we must
+ // now check its operands.
+ p.checkBinaryExpr(t)
+ }
+ case *ast.CallExpr:
+ // If we have an expression of the form name(T), and T is a (possibly
+ // parenthesized) type literal or the next token is a comma, we are
+ // at the start of a type parameter list.
+ if name, _ := t.Fun.(*ast.Ident); name != nil {
+ if len(t.Args) == 1 && !t.Ellipsis.IsValid() && (isTypeLit(t.Args[0]) || p.tok == token.COMMA) {
+ // d.Name "[" name "(" t.ArgList[0] ")"
+ // d.Name "[" name "(" t.ArgList[0] ")" ","
+ pname = name
+ ptype = t.Args[0]
+ }
}
}
- if x == nil {
- // generic type [T any];
- p.parseGenericType(spec, lbrack, name0)
+ if pname != nil {
+ // d.Name "[" pname ...
+ // d.Name "[" pname ptype ...
+ // d.Name "[" pname ptype "," ...
+ p.parseGenericType(spec, lbrack, pname, ptype)
} else {
- // array type
- // TODO(rfindley) should resolve all identifiers in x.
+ // d.Name "[" x ...
spec.Type = p.parseArrayType(lbrack, x)
}
} else {
@@ -2608,6 +2707,21 @@
return spec
}
+// isTypeLit reports whether x is a (possibly parenthesized) type literal.
+func isTypeLit(x ast.Expr) bool {
+ switch x := x.(type) {
+ case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
+ return true
+ case *ast.StarExpr:
+ // *T may be a pointer dereferenciation.
+ // Only consider *T as type literal if T is a type literal.
+ return isTypeLit(x.X)
+ case *ast.ParenExpr:
+ return isTypeLit(x.X)
+ }
+ return false
+}
+
func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
if p.trace {
defer un(trace(p, "GenDecl("+keyword.String()+")"))
@@ -2655,6 +2769,12 @@
ident := p.parseIdent()
tparams, params := p.parseParameters(true)
+ if recv != nil && tparams != nil {
+ // Method declarations do not have type parameters. We parse them for a
+ // better error message and improved error recovery.
+ p.error(tparams.Opening, "method must have no type parameters")
+ tparams = nil
+ }
results := p.parseResult()
var body *ast.BlockStmt
diff --git a/src/go/parser/resolver.go b/src/go/parser/resolver.go
index 910ca06..d66a194 100644
--- a/src/go/parser/resolver.go
+++ b/src/go/parser/resolver.go
@@ -8,6 +8,7 @@
"fmt"
"go/ast"
"go/token"
+ "strings"
)
const debugResolve = false
@@ -24,6 +25,7 @@
declErr: declErr,
topScope: pkgScope,
pkgScope: pkgScope,
+ depth: 1,
}
for _, decl := range file.Decls {
@@ -45,7 +47,7 @@
i++
} else if debugResolve {
pos := ident.Obj.Decl.(interface{ Pos() token.Pos }).Pos()
- r.dump("resolved %s@%v to package object %v", ident.Name, ident.Pos(), pos)
+ r.trace("resolved %s@%v to package object %v", ident.Name, ident.Pos(), pos)
}
}
file.Scope = r.pkgScope
@@ -60,6 +62,7 @@
pkgScope *ast.Scope // pkgScope.Outer == nil
topScope *ast.Scope // top-most scope; may be pkgScope
unresolved []*ast.Ident // unresolved identifiers
+ depth int // scope depth
// Label scopes
// (maintained by open/close LabelScope)
@@ -67,8 +70,8 @@
targetStack [][]*ast.Ident // stack of unresolved labels
}
-func (r *resolver) dump(format string, args ...any) {
- fmt.Println(">>> " + r.sprintf(format, args...))
+func (r *resolver) trace(format string, args ...any) {
+ fmt.Println(strings.Repeat(". ", r.depth) + r.sprintf(format, args...))
}
func (r *resolver) sprintf(format string, args ...any) string {
@@ -83,14 +86,16 @@
func (r *resolver) openScope(pos token.Pos) {
if debugResolve {
- r.dump("opening scope @%v", pos)
+ r.trace("opening scope @%v", pos)
+ r.depth++
}
r.topScope = ast.NewScope(r.topScope)
}
func (r *resolver) closeScope() {
if debugResolve {
- r.dump("closing scope")
+ r.depth--
+ r.trace("closing scope")
}
r.topScope = r.topScope.Outer
}
@@ -117,21 +122,27 @@
func (r *resolver) declare(decl, data any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
for _, ident := range idents {
- assert(ident.Obj == nil, "identifier already declared or resolved")
+ if ident.Obj != nil {
+ panic(fmt.Sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
+ }
obj := ast.NewObj(kind, ident.Name)
// remember the corresponding declaration for redeclaration
// errors and global variable resolution/typechecking phase
obj.Decl = decl
obj.Data = data
- ident.Obj = obj
+ // Identifiers (for receiver type parameters) are written to the scope, but
+ // never set as the resolved object. See issue #50956.
+ if _, ok := decl.(*ast.Ident); !ok {
+ ident.Obj = obj
+ }
if ident.Name != "_" {
if debugResolve {
- r.dump("declaring %s@%v", ident.Name, ident.Pos())
+ r.trace("declaring %s@%v", ident.Name, ident.Pos())
}
if alt := scope.Insert(obj); alt != nil && r.declErr != nil {
prevDecl := ""
if pos := alt.Pos(); pos.IsValid() {
- prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", r.handle.Position(pos))
+ prevDecl = r.sprintf("\n\tprevious declaration at %v", pos)
}
r.declErr(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
}
@@ -153,7 +164,7 @@
ident.Obj = obj
if ident.Name != "_" {
if debugResolve {
- r.dump("declaring %s@%v", ident.Name, ident.Pos())
+ r.trace("declaring %s@%v", ident.Name, ident.Pos())
}
if alt := r.topScope.Insert(obj); alt != nil {
ident.Obj = alt // redeclaration
@@ -180,7 +191,7 @@
//
func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) {
if ident.Obj != nil {
- panic(fmt.Sprintf("%s: identifier %s already declared or resolved", r.handle.Position(ident.Pos()), ident.Name))
+ panic(r.sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
}
// '_' should never refer to existing declarations, because it has special
// handling in the spec.
@@ -189,8 +200,15 @@
}
for s := r.topScope; s != nil; s = s.Outer {
if obj := s.Lookup(ident.Name); obj != nil {
+ if debugResolve {
+ r.trace("resolved %v:%s to %v", ident.Pos(), ident.Name, obj)
+ }
assert(obj.Name != "", "obj with no name")
- ident.Obj = obj
+ // Identifiers (for receiver type parameters) are written to the scope,
+ // but never set as the resolved object. See issue #50956.
+ if _, ok := obj.Decl.(*ast.Ident); !ok {
+ ident.Obj = obj
+ }
return
}
}
@@ -227,7 +245,7 @@
func (r *resolver) Visit(node ast.Node) ast.Visitor {
if debugResolve && node != nil {
- r.dump("node %T@%v", node, node.Pos())
+ r.trace("node %T@%v", node, node.Pos())
}
switch n := node.(type) {
@@ -461,8 +479,7 @@
r.openScope(n.Pos())
defer r.closeScope()
- // Resolve the receiver first, without declaring.
- r.resolveList(n.Recv)
+ r.walkRecv(n.Recv)
// Type parameters are walked normally: they can reference each other, and
// can be referenced by normal parameters.
@@ -519,6 +536,52 @@
}
}
+func (r *resolver) walkRecv(recv *ast.FieldList) {
+ // If our receiver has receiver type parameters, we must declare them before
+ // trying to resolve the rest of the receiver, and avoid re-resolving the
+ // type parameter identifiers.
+ if recv == nil || len(recv.List) == 0 {
+ return // nothing to do
+ }
+ typ := recv.List[0].Type
+ if ptr, ok := typ.(*ast.StarExpr); ok {
+ typ = ptr.X
+ }
+
+ var declareExprs []ast.Expr // exprs to declare
+ var resolveExprs []ast.Expr // exprs to resolve
+ switch typ := typ.(type) {
+ case *ast.IndexExpr:
+ declareExprs = []ast.Expr{typ.Index}
+ resolveExprs = append(resolveExprs, typ.X)
+ case *ast.IndexListExpr:
+ declareExprs = typ.Indices
+ resolveExprs = append(resolveExprs, typ.X)
+ default:
+ resolveExprs = append(resolveExprs, typ)
+ }
+ for _, expr := range declareExprs {
+ if id, _ := expr.(*ast.Ident); id != nil {
+ r.declare(expr, nil, r.topScope, ast.Typ, id)
+ } else {
+ // The receiver type parameter expression is invalid, but try to resolve
+ // it anyway for consistency.
+ resolveExprs = append(resolveExprs, expr)
+ }
+ }
+ for _, expr := range resolveExprs {
+ if expr != nil {
+ ast.Walk(r, expr)
+ }
+ }
+ // The receiver is invalid, but try to resolve it anyway for consistency.
+ for _, f := range recv.List[1:] {
+ if f.Type != nil {
+ ast.Walk(r, f.Type)
+ }
+ }
+}
+
func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) {
if list == nil {
return
diff --git a/src/go/parser/short_test.go b/src/go/parser/short_test.go
index 90a4ec9..d117f0d 100644
--- a/src/go/parser/short_test.go
+++ b/src/go/parser/short_test.go
@@ -74,7 +74,7 @@
`package p; type T[P any /* ERROR "expected ']', found any" */ ] struct { P }`,
`package p; type T[P comparable /* ERROR "expected ']', found comparable" */ ] struct { P }`,
`package p; type T[P comparable /* ERROR "expected ']', found comparable" */ [P]] struct { P }`,
- `package p; type T[P1, /* ERROR "expected ']', found ','" */ P2 any] struct { P1; f []P2 }`,
+ `package p; type T[P1, /* ERROR "unexpected comma" */ P2 any] struct { P1; f []P2 }`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ T any]()()`,
`package p; func _(T (P))`,
`package p; func f[ /* ERROR "expected '\(', found '\['" */ A, B any](); func _() { _ = f[int, int] }`,
@@ -83,8 +83,8 @@
`package p; func _(p.T[ /* ERROR "missing ',' in parameter list" */ Q])`,
`package p; type _[A interface /* ERROR "expected ']', found 'interface'" */ {},] struct{}`,
`package p; type _[A interface /* ERROR "expected ']', found 'interface'" */ {}] struct{}`,
- `package p; type _[A, /* ERROR "expected ']', found ','" */ B any,] struct{}`,
- `package p; type _[A, /* ERROR "expected ']', found ','" */ B any] struct{}`,
+ `package p; type _[A, /* ERROR "unexpected comma" */ B any,] struct{}`,
+ `package p; type _[A, /* ERROR "unexpected comma" */ B any] struct{}`,
`package p; type _[A any /* ERROR "expected ']', found any" */,] struct{}`,
`package p; type _[A any /* ERROR "expected ']', found any" */ ]struct{}`,
`package p; type _[A any /* ERROR "expected ']', found any" */ ] struct{ A }`,
@@ -94,11 +94,9 @@
`package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`,
- `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`,
- `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`,
- `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`,
- `package p; type _[A, /* ERROR "expected ']', found ','" */ B any] interface { _(a A) B }`,
- `package p; type _[A, /* ERROR "expected ']', found ','" */ B C[A, B]] interface { _(a A) B }`,
+
+ `package p; type _[A, /* ERROR "unexpected comma" */ B any] interface { _(a A) B }`,
+ `package p; type _[A, /* ERROR "unexpected comma" */ B C[A, B]] interface { _(a A) B }`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ T1, T2 interface{}](x T1) T2`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ T1 interface{ m() }, T2, T3 interface{}](x T1, y T3) T2`,
`package p; var _ = [ /* ERROR "expected expression" */ ]T[int]{}`,
@@ -110,10 +108,10 @@
`package p; var _ T[ /* ERROR "expected ';', found '\['" */ chan int]`,
// TODO(rfindley) this error message could be improved.
- `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[P]) _[T any](x T)`,
- `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[ P, Q]) _[T1, T2 any](x T)`,
+ `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[P]) _(x T)`,
+ `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[ P, Q]) _(x T)`,
- `package p; func (R[P] /* ERROR "missing element type" */ ) _[T any]()`,
+ `package p; func (R[P] /* ERROR "missing element type" */ ) _()`,
`package p; func _(T[P] /* ERROR "missing element type" */ )`,
`package p; func _(T[P1, /* ERROR "expected ']', found ','" */ P2, P3 ])`,
`package p; func _(T[P] /* ERROR "missing element type" */ ) T[P]`,
@@ -122,7 +120,7 @@
`package p; type _ interface{int| /* ERROR "expected ';'" */ float32; bool; m(); string;}`,
`package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2 interface{ I1[int] }`,
`package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2[T any] interface{ I1[T] }`,
- `package p; type _ interface { f[ /* ERROR "expected ';', found '\['" */ T any]() }`,
+ `package p; type _ interface { N[ /* ERROR "expected ';', found '\['" */ T] }`,
`package p; type T[P any /* ERROR "expected ']'" */ ] = T0`,
}
@@ -195,7 +193,7 @@
`package p; func f() { go func() { func() { f(x func /* ERROR "missing ','" */ (){}) } } }`,
`package p; func _() (type /* ERROR "found 'type'" */ T)(T)`,
`package p; func (type /* ERROR "found 'type'" */ T)(T) _()`,
- `package p; type _[A+B, /* ERROR "expected ']'" */ ] int`,
+ `package p; type _[A+B, /* ERROR "unexpected comma" */ ] int`,
// TODO(rfindley): this error should be positioned on the ':'
`package p; var a = a[[]int:[ /* ERROR "expected expression" */ ]int];`,
@@ -233,22 +231,34 @@
`package p; type T[P any /* ERROR "expected ']', found any" */ ] = T0`,
`package p; var _ func[ /* ERROR "expected '\(', found '\['" */ T any](T)`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ ]()`,
- `package p; type _[A, /* ERROR "expected ']', found ','" */] struct{ A }`,
+ `package p; type _[A, /* ERROR "unexpected comma" */] struct{ A }`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ type P, *Q interface{}]()`,
+
+ `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`,
+ `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`,
+ `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`,
+
+ `package p; func(*T[ /* ERROR "missing ',' in parameter list" */ e, e]) _()`,
}
// invalidTParamErrs holds invalid source code examples annotated with the
// error messages produced when ParseTypeParams is set.
var invalidTParamErrs = []string{
`package p; type _[_ any] int; var _ = T[] /* ERROR "expected operand" */ {}`,
- `package p; var _ func[ /* ERROR "cannot have type parameters" */ T any](T)`,
+ `package p; var _ func[ /* ERROR "must have no type parameters" */ T any](T)`,
`package p; func _[]/* ERROR "empty type parameter list" */()`,
// TODO(rfindley) a better location would be after the ']'
- `package p; type _[A/* ERROR "all type parameters must be named" */,] struct{ A }`,
+ `package p; type _[A /* ERROR "all type parameters must be named" */ ,] struct{ A }`,
// TODO(rfindley) this error is confusing.
- `package p; func _[type /* ERROR "all type parameters must be named" */P, *Q interface{}]()`,
+ `package p; func _[type /* ERROR "all type parameters must be named" */ P, *Q interface{}]()`,
+
+ `package p; func (T) _[ /* ERROR "must have no type parameters" */ A, B any](a A) B`,
+ `package p; func (T) _[ /* ERROR "must have no type parameters" */ A, B C](a A) B`,
+ `package p; func (T) _[ /* ERROR "must have no type parameters" */ A, B C[A, B]](a A) B`,
+
+ `package p; func(*T[e, e /* ERROR "e redeclared" */ ]) _()`,
}
func TestInvalid(t *testing.T) {
diff --git a/src/go/parser/testdata/issue49482.go2 b/src/go/parser/testdata/issue49482.go2
new file mode 100644
index 0000000..50de651
--- /dev/null
+++ b/src/go/parser/testdata/issue49482.go2
@@ -0,0 +1,35 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type (
+ // these need a comma to disambiguate
+ _[P *T,] struct{}
+ _[P *T, _ any] struct{}
+ _[P (*T),] struct{}
+ _[P (*T), _ any] struct{}
+ _[P (T),] struct{}
+ _[P (T), _ any] struct{}
+
+ // these parse as name followed by type
+ _[P *struct{}] struct{}
+ _[P (*struct{})] struct{}
+ _[P ([]int)] struct{}
+
+ // array declarations
+ _ [P(T)]struct{}
+ _ [P((T))]struct{}
+ _ [P * *T]struct{}
+ _ [P * T]struct{}
+ _ [P(*T)]struct{}
+ _ [P(**T)]struct{}
+ _ [P * T - T]struct{}
+ _ [P*T-T, /* ERROR "unexpected comma" */ ]struct{}
+ _ [10, /* ERROR "unexpected comma" */ ]struct{}
+
+ // These should be parsed as generic type declarations.
+ _[P *struct /* ERROR "expected expression" */ {}|int] struct{}
+ _[P *struct /* ERROR "expected expression" */ {}|int|string] struct{}
+)
diff --git a/src/go/parser/testdata/issue50427.go2 b/src/go/parser/testdata/issue50427.go2
new file mode 100644
index 0000000..1521459
--- /dev/null
+++ b/src/go/parser/testdata/issue50427.go2
@@ -0,0 +1,19 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T interface{ m[ /* ERROR "must have no type parameters" */ P any]() }
+
+func _(t T) {
+ var _ interface{ m[ /* ERROR "must have no type parameters" */ P any](); n() } = t
+}
+
+type S struct{}
+
+func (S) m[ /* ERROR "must have no type parameters" */ P any]() {}
+
+func _(s S) {
+ var _ interface{ m[ /* ERROR "must have no type parameters" */ P any](); n() } = s
+}
diff --git a/src/go/parser/testdata/resolution/typeparams.go2 b/src/go/parser/testdata/resolution/typeparams.go2
index 8c243af..7395ca2 100644
--- a/src/go/parser/testdata/resolution/typeparams.go2
+++ b/src/go/parser/testdata/resolution/typeparams.go2
@@ -25,10 +25,15 @@
type Receiver /* =@Receiver */[P /* =@P */ any] struct {}
+type RP /* =@RP1 */ struct{}
+
// TODO(rFindley): make a decision on how/whether to resolve identifiers that
// refer to receiver type parameters, as is the case for the 'P' result
// parameter below.
-func (r /* =@recv */ Receiver /* @Receiver */ [P]) m() P {}
+//
+// For now, we ensure that types are not incorrectly resolved when receiver
+// type parameters are in scope.
+func (r /* =@recv */ Receiver /* @Receiver */ [RP]) m(RP) RP {}
func f /* =@f */[T1 /* =@T1 */ interface{~[]T2 /* @T2 */}, T2 /* =@T2 */ any](
x /* =@x */ T1 /* @T1 */, T1 /* =@T1_duplicate */ y, // Note that this is a bug:
@@ -41,3 +46,6 @@
T1 /* @T1 */ := 0
var t1var /* =@t1var */ T1 /* @T1 */
}
+
+// From issue #39634
+func(*ph1[e, e])h(d)
diff --git a/src/go/parser/testdata/typeparams.src b/src/go/parser/testdata/typeparams.src
index 1fea23f..479cb96 100644
--- a/src/go/parser/testdata/typeparams.src
+++ b/src/go/parser/testdata/typeparams.src
@@ -9,7 +9,7 @@
type List[E any /* ERROR "expected ']', found any" */ ] []E
-type Pair[L, /* ERROR "expected ']', found ','" */ R any] struct {
+type Pair[L, /* ERROR "unexpected comma" */ R any] struct {
Left L
Right R
}
diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go
index 19d4ab6..9a09d58 100644
--- a/src/go/printer/nodes.go
+++ b/src/go/printer/nodes.go
@@ -319,9 +319,17 @@
}
}
-func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) {
+type paramMode int
+
+const (
+ funcParam paramMode = iota
+ funcTParam
+ typeTParam
+)
+
+func (p *printer) parameters(fields *ast.FieldList, mode paramMode) {
openTok, closeTok := token.LPAREN, token.RPAREN
- if isTypeParam {
+ if mode != funcParam {
openTok, closeTok = token.LBRACK, token.RBRACK
}
p.print(fields.Opening, openTok)
@@ -367,26 +375,54 @@
p.expr(stripParensAlways(par.Type))
prevLine = parLineEnd
}
+
// if the closing ")" is on a separate line from the last parameter,
// print an additional "," and line break
if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
p.print(token.COMMA)
p.linebreak(closing, 0, ignore, true)
+ } else if mode == typeTParam && fields.NumFields() == 1 {
+ // Otherwise, if we are in a type parameter list that could be confused
+ // with the constant array length expression [P*C], print a comma so that
+ // parsing is unambiguous.
+ //
+ // Note that while ParenExprs can also be ambiguous (issue #49482), the
+ // printed type is never parenthesized (stripParensAlways is used above).
+ if t, _ := fields.List[0].Type.(*ast.StarExpr); t != nil && !isTypeLit(t.X) {
+ p.print(token.COMMA)
+ }
}
+
// unindent if we indented
if ws == ignore {
p.print(unindent)
}
}
+
p.print(fields.Closing, closeTok)
}
+// isTypeLit reports whether x is a (possibly parenthesized) type literal.
+func isTypeLit(x ast.Expr) bool {
+ switch x := x.(type) {
+ case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
+ return true
+ case *ast.StarExpr:
+ // *T may be a pointer dereferenciation.
+ // Only consider *T as type literal if T is a type literal.
+ return isTypeLit(x.X)
+ case *ast.ParenExpr:
+ return isTypeLit(x.X)
+ }
+ return false
+}
+
func (p *printer) signature(sig *ast.FuncType) {
if sig.TypeParams != nil {
- p.parameters(sig.TypeParams, true)
+ p.parameters(sig.TypeParams, funcTParam)
}
if sig.Params != nil {
- p.parameters(sig.Params, false)
+ p.parameters(sig.Params, funcParam)
} else {
p.print(token.LPAREN, token.RPAREN)
}
@@ -400,7 +436,7 @@
p.expr(stripParensAlways(res.List[0].Type))
return
}
- p.parameters(res, false)
+ p.parameters(res, funcParam)
}
}
@@ -1611,7 +1647,7 @@
p.setComment(s.Doc)
p.expr(s.Name)
if s.TypeParams != nil {
- p.parameters(s.TypeParams, true)
+ p.parameters(s.TypeParams, typeTParam)
}
if n == 1 {
p.print(blank)
@@ -1801,7 +1837,7 @@
// FUNC is emitted).
startCol := p.out.Column - len("func ")
if d.Recv != nil {
- p.parameters(d.Recv, false) // method: print receiver
+ p.parameters(d.Recv, funcParam) // method: print receiver
p.print(blank)
}
p.expr(d.Name)
diff --git a/src/go/printer/testdata/generics.golden b/src/go/printer/testdata/generics.golden
index 3d95eda..c3a7df8 100644
--- a/src/go/printer/testdata/generics.golden
+++ b/src/go/printer/testdata/generics.golden
@@ -38,3 +38,55 @@
// type constraint literals with elided interfaces
func _[P ~int, Q int | string]() {}
func _[P struct{ f int }, Q *P]() {}
+
+// various potentially ambiguous type parameter lists (issue #49482)
+type _[P *T,] struct{}
+type _[P *T, _ any] struct{}
+type _[P *T,] struct{}
+type _[P *T, _ any] struct{}
+type _[P T] struct{}
+type _[P T, _ any] struct{}
+
+type _[P *struct{}] struct{}
+type _[P *struct{}] struct{}
+type _[P []int] struct{}
+
+// array type declarations
+type _ [P(T)]struct{}
+type _ [P((T))]struct{}
+type _ [P * *T]struct{}
+type _ [P * T]struct{}
+type _ [P(*T)]struct{}
+type _ [P(**T)]struct{}
+type _ [P * T]struct{}
+type _ [P*T - T]struct{}
+
+type _[
+ P *T,
+] struct{}
+
+// equivalent test cases for potentially ambiguous type parameter lists, except
+// for function declarations there is no ambiguity (issue #51548)
+func _[P *T]() {}
+func _[P *T, _ any]() {}
+func _[P *T]() {}
+func _[P *T, _ any]() {}
+func _[P T]() {}
+func _[P T, _ any]() {}
+
+func _[P *struct{}]() {}
+func _[P *struct{}]() {}
+func _[P []int]() {}
+
+func _[P T]() {}
+func _[P T]() {}
+func _[P **T]() {}
+func _[P *T]() {}
+func _[P *T]() {}
+func _[P **T]() {}
+func _[P *T]() {}
+
+func _[
+ P *T,
+]() {
+}
diff --git a/src/go/printer/testdata/generics.input b/src/go/printer/testdata/generics.input
index 746dfdd..66e1554 100644
--- a/src/go/printer/testdata/generics.input
+++ b/src/go/printer/testdata/generics.input
@@ -35,3 +35,54 @@
// type constraint literals with elided interfaces
func _[P ~int, Q int | string]() {}
func _[P struct{f int}, Q *P]() {}
+
+// various potentially ambiguous type parameter lists (issue #49482)
+type _[P *T,] struct{}
+type _[P *T, _ any] struct{}
+type _[P (*T),] struct{}
+type _[P (*T), _ any] struct{}
+type _[P (T),] struct{}
+type _[P (T), _ any] struct{}
+
+type _[P *struct{}] struct{}
+type _[P (*struct{})] struct{}
+type _[P ([]int)] struct{}
+
+// array type declarations
+type _ [P(T)]struct{}
+type _ [P((T))]struct{}
+type _ [P * *T]struct{}
+type _ [P * T]struct{}
+type _ [P(*T)]struct{}
+type _ [P(**T)]struct{}
+type _ [P * T]struct{}
+type _ [P * T - T]struct{}
+
+type _[
+ P *T,
+] struct{}
+
+// equivalent test cases for potentially ambiguous type parameter lists, except
+// for function declarations there is no ambiguity (issue #51548)
+func _[P *T,]() {}
+func _[P *T, _ any]() {}
+func _[P (*T),]() {}
+func _[P (*T), _ any]() {}
+func _[P (T),]() {}
+func _[P (T), _ any]() {}
+
+func _[P *struct{}] () {}
+func _[P (*struct{})] () {}
+func _[P ([]int)] () {}
+
+func _ [P(T)]() {}
+func _ [P((T))]() {}
+func _ [P * *T]() {}
+func _ [P * T]() {}
+func _ [P(*T)]() {}
+func _ [P(**T)]() {}
+func _ [P * T]() {}
+
+func _[
+ P *T,
+]() {}
diff --git a/src/go/types/api.go b/src/go/types/api.go
index c4d81c1..f2dcd10 100644
--- a/src/go/types/api.go
+++ b/src/go/types/api.go
@@ -197,20 +197,14 @@
// identifier z in a variable declaration 'var z int' is found
// only in the Defs map, and identifiers denoting packages in
// qualified identifiers are collected in the Uses map.
- //
- // For binary expressions representing unions in constraint
- // position or type elements in interfaces, a union type is
- // recorded for the top-level expression only. For instance,
- // given the constraint a|b|c, the union type for (a|b)|c
- // is recorded, but not the union type for a|b.
Types map[ast.Expr]TypeAndValue
- // Instances maps identifiers denoting parameterized types or functions to
- // their type arguments and instantiated type.
+ // Instances maps identifiers denoting generic types or functions to their
+ // type arguments and instantiated type.
//
// For example, Instances will map the identifier for 'T' in the type
// instantiation T[int, string] to the type arguments [int, string] and
- // resulting instantiated *Named type. Given a parameterized function
+ // resulting instantiated *Named type. Given a generic function
// func F[A any](A), Instances will map the identifier for 'F' in the call
// expression F(int(1)) to the inferred type arguments [int], and resulting
// instantiated *Signature.
@@ -266,6 +260,7 @@
//
// *ast.File
// *ast.FuncType
+ // *ast.TypeSpec
// *ast.BlockStmt
// *ast.IfStmt
// *ast.SwitchStmt
@@ -422,25 +417,45 @@
}
// AssertableTo reports whether a value of type V can be asserted to have type T.
+//
+// The behavior of AssertableTo is undefined in two cases:
+// - if V is a generalized interface; i.e., an interface that may only be used
+// as a type constraint in Go code
+// - if T is an uninstantiated generic type
func AssertableTo(V *Interface, T Type) bool {
- m, _ := (*Checker)(nil).assertableTo(V, T)
- return m == nil
+ // Checker.newAssertableTo suppresses errors for invalid types, so we need special
+ // handling here.
+ if T.Underlying() == Typ[Invalid] {
+ return false
+ }
+ return (*Checker)(nil).newAssertableTo(V, T) == nil
}
-// AssignableTo reports whether a value of type V is assignable to a variable of type T.
+// AssignableTo reports whether a value of type V is assignable to a variable
+// of type T.
+//
+// The behavior of AssignableTo is undefined if V or T is an uninstantiated
+// generic type.
func AssignableTo(V, T Type) bool {
x := operand{mode: value, typ: V}
ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
return ok
}
-// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
+// ConvertibleTo reports whether a value of type V is convertible to a value of
+// type T.
+//
+// The behavior of ConvertibleTo is undefined if V or T is an uninstantiated
+// generic type.
func ConvertibleTo(V, T Type) bool {
x := operand{mode: value, typ: V}
return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
}
// Implements reports whether type V implements interface T.
+//
+// The behavior of Implements is undefined if V is an uninstantiated generic
+// type.
func Implements(V Type, T *Interface) bool {
if T.Empty() {
// All types (even Typ[Invalid]) implement the empty interface.
@@ -451,7 +466,7 @@
if V.Underlying() == Typ[Invalid] {
return false
}
- return (*Checker)(nil).implements(V, T, nil) == nil
+ return (*Checker)(nil).implements(V, T) == nil
}
// Identical reports whether x and y are identical types.
diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go
index 1ee9806..4014201 100644
--- a/src/go/types/api_test.go
+++ b/src/go/types/api_test.go
@@ -16,6 +16,7 @@
"internal/testenv"
"reflect"
"regexp"
+ "sort"
"strings"
"testing"
@@ -127,7 +128,6 @@
{`package c5d; var _ = string(65)`, `65`, `untyped int`, `65`},
{`package c5e; var _ = string('A')`, `'A'`, `untyped rune`, `65`},
{`package c5f; type T string; var _ = T('A')`, `'A'`, `untyped rune`, `65`},
- {`package c5g; var s uint; var _ = string(1 << s)`, `1 << s`, `untyped int`, ``},
{`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
{`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
@@ -379,10 +379,25 @@
{genericPkg + `u1a; func _[_ interface{~int}]() {}`, `~int`, `~int`},
{genericPkg + `u2a; func _[_ interface{int|string}]() {}`, `int | string`, `int|string`},
{genericPkg + `u3a; func _[_ interface{int|string|~bool}]() {}`, `int | string | ~bool`, `int|string|~bool`},
+ {genericPkg + `u3a; func _[_ interface{int|string|~bool}]() {}`, `int | string`, `int|string`},
+ {genericPkg + `u3a; func _[_ interface{int|string|~bool}]() {}`, `~bool`, `~bool`},
+ {genericPkg + `u3a; func _[_ interface{int|string|~float64|~bool}]() {}`, `int | string | ~float64`, `int|string|~float64`},
+
{genericPkg + `u0b; func _[_ int]() {}`, `int`, `int`},
{genericPkg + `u1b; func _[_ ~int]() {}`, `~int`, `~int`},
{genericPkg + `u2b; func _[_ int|string]() {}`, `int | string`, `int|string`},
{genericPkg + `u3b; func _[_ int|string|~bool]() {}`, `int | string | ~bool`, `int|string|~bool`},
+ {genericPkg + `u3b; func _[_ int|string|~bool]() {}`, `int | string`, `int|string`},
+ {genericPkg + `u3b; func _[_ int|string|~bool]() {}`, `~bool`, `~bool`},
+ {genericPkg + `u3b; func _[_ int|string|~float64|~bool]() {}`, `int | string | ~float64`, `int|string|~float64`},
+
+ {genericPkg + `u0c; type _ interface{int}`, `int`, `int`},
+ {genericPkg + `u1c; type _ interface{~int}`, `~int`, `~int`},
+ {genericPkg + `u2c; type _ interface{int|string}`, `int | string`, `int|string`},
+ {genericPkg + `u3c; type _ interface{int|string|~bool}`, `int | string | ~bool`, `int|string|~bool`},
+ {genericPkg + `u3c; type _ interface{int|string|~bool}`, `int | string`, `int|string`},
+ {genericPkg + `u3c; type _ interface{int|string|~bool}`, `~bool`, `~bool`},
+ {genericPkg + `u3c; type _ interface{int|string|~float64|~bool}`, `int | string | ~float64`, `int|string|~float64`},
}
for _, test := range tests {
@@ -420,129 +435,146 @@
}
func TestInstanceInfo(t *testing.T) {
- var tests = []struct {
- src string
- name string
- targs []string
- typ string
- }{
- {`package p0; func f[T any](T) {}; func _() { f(42) }`,
- `f`,
- []string{`int`},
- `func(int)`,
- },
- {`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
- `f`,
- []string{`rune`},
- `func(rune) rune`,
- },
- {`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
- `f`,
- []string{`complex128`},
- `func(...complex128) complex128`,
- },
- {`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
- `f`,
- []string{`float64`, `string`, `byte`},
- `func(float64, *string, []byte)`,
- },
- {`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
- `f`,
- []string{`float64`, `byte`},
- `func(float64, *byte, ...[]byte)`,
- },
-
- {`package s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`,
- `f`,
- []string{`string`, `*string`},
- `func(x string)`,
- },
- {`package s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `*int`},
- `func(x []int)`,
- },
- {`package s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `chan<- int`},
- `func(x []int)`,
- },
- {`package s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
- `func(x []int)`,
- },
-
- {`package t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`,
- `f`,
- []string{`string`, `*string`},
- `func() string`,
- },
- {`package t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
- `f`,
- []string{`string`, `*string`},
- `func() string`,
- },
- {`package t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`,
- `f`,
- []string{`int`, `chan<- int`},
- `func() []int`,
- },
- {`package t4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
- `f`,
- []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
- `func() []int`,
- },
- {`package i0; import "lib"; func _() { lib.F(42) }`,
- `F`,
- []string{`int`},
- `func(int)`,
- },
- {`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`,
- `T`,
- []string{`int`},
- `struct{x int}`,
- },
- {`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`,
- `T`,
- []string{`int`},
- `struct{x int}`,
- },
- {`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`,
- `T`,
- []string{`int`},
- `struct{x int}`,
- },
- {`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`,
- `T`,
- []string{`[]int`, `int`},
- `struct{x []int; y int}`,
- },
- {`package type4; import "lib"; var _ lib.T[int]`,
- `T`,
- []string{`int`},
- `[]int`,
- },
- }
-
- for _, test := range tests {
- const lib = `package lib
+ const lib = `package lib
func F[P any](P) {}
type T[P any] []P
`
+ type testInst struct {
+ name string
+ targs []string
+ typ string
+ }
+
+ var tests = []struct {
+ src string
+ instances []testInst // recorded instances in source order
+ }{
+ {`package p0; func f[T any](T) {}; func _() { f(42) }`,
+ []testInst{{`f`, []string{`int`}, `func(int)`}},
+ },
+ {`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
+ []testInst{{`f`, []string{`rune`}, `func(rune) rune`}},
+ },
+ {`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
+ []testInst{{`f`, []string{`complex128`}, `func(...complex128) complex128`}},
+ },
+ {`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
+ []testInst{{`f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`}},
+ },
+ {`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
+ []testInst{{`f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`}},
+ },
+
+ {`package s1; func f[T any, P interface{*T}](x T) {}; func _(x string) { f(x) }`,
+ []testInst{{`f`, []string{`string`, `*string`}, `func(x string)`}},
+ },
+ {`package s2; func f[T any, P interface{*T}](x []T) {}; func _(x []int) { f(x) }`,
+ []testInst{{`f`, []string{`int`, `*int`}, `func(x []int)`}},
+ },
+ {`package s3; type C[T any] interface{chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
+ []testInst{
+ {`C`, []string{`T`}, `interface{chan<- T}`},
+ {`f`, []string{`int`, `chan<- int`}, `func(x []int)`},
+ },
+ },
+ {`package s4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
+ []testInst{
+ {`C`, []string{`T`}, `interface{chan<- T}`},
+ {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+ {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`},
+ },
+ },
+
+ {`package t1; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = f[string] }`,
+ []testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
+ },
+ {`package t2; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
+ []testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
+ },
+ {`package t3; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
+ []testInst{
+ {`C`, []string{`T`}, `interface{chan<- T}`},
+ {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+ {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
+ },
+ },
+ {`package t4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = (f[int]) }`,
+ []testInst{
+ {`C`, []string{`T`}, `interface{chan<- T}`},
+ {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+ {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
+ },
+ },
+ {`package i0; import "lib"; func _() { lib.F(42) }`,
+ []testInst{{`F`, []string{`int`}, `func(int)`}},
+ },
+
+ {`package duplfunc0; func f[T any](T) {}; func _() { f(42); f("foo"); f[int](3) }`,
+ []testInst{
+ {`f`, []string{`int`}, `func(int)`},
+ {`f`, []string{`string`}, `func(string)`},
+ {`f`, []string{`int`}, `func(int)`},
+ },
+ },
+ {`package duplfunc1; import "lib"; func _() { lib.F(42); lib.F("foo"); lib.F(3) }`,
+ []testInst{
+ {`F`, []string{`int`}, `func(int)`},
+ {`F`, []string{`string`}, `func(string)`},
+ {`F`, []string{`int`}, `func(int)`},
+ },
+ },
+
+ {`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`,
+ []testInst{{`T`, []string{`int`}, `struct{x int}`}},
+ },
+ {`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`,
+ []testInst{{`T`, []string{`int`}, `struct{x int}`}},
+ },
+ {`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`,
+ []testInst{{`T`, []string{`int`}, `struct{x int}`}},
+ },
+ {`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`,
+ []testInst{{`T`, []string{`[]int`, `int`}, `struct{x []int; y int}`}},
+ },
+ {`package type4; import "lib"; var _ lib.T[int]`,
+ []testInst{{`T`, []string{`int`}, `[]int`}},
+ },
+
+ {`package dupltype0; type T[P interface{~int}] struct{ x P }; var x T[int]; var y T[int]`,
+ []testInst{
+ {`T`, []string{`int`}, `struct{x int}`},
+ {`T`, []string{`int`}, `struct{x int}`},
+ },
+ },
+ {`package dupltype1; type T[P ~int] struct{ x P }; func (r *T[Q]) add(z T[Q]) { r.x += z.x }`,
+ []testInst{
+ {`T`, []string{`Q`}, `struct{x Q}`},
+ {`T`, []string{`Q`}, `struct{x Q}`},
+ },
+ },
+ {`package dupltype1; import "lib"; var x lib.T[int]; var y lib.T[int]; var z lib.T[string]`,
+ []testInst{
+ {`T`, []string{`int`}, `[]int`},
+ {`T`, []string{`int`}, `[]int`},
+ {`T`, []string{`string`}, `[]string`},
+ },
+ },
+ }
+
+ for _, test := range tests {
imports := make(testImporter)
conf := Config{Importer: imports}
- instances := make(map[*ast.Ident]Instance)
- uses := make(map[*ast.Ident]Object)
+ instMap := make(map[*ast.Ident]Instance)
+ useMap := make(map[*ast.Ident]Object)
makePkg := func(src string) *Package {
f, err := parser.ParseFile(fset, "p.go", src, 0)
if err != nil {
t.Fatal(err)
}
- pkg, err := conf.Check("", fset, []*ast.File{f}, &Info{Instances: instances, Uses: uses})
+ pkg, err := conf.Check("", fset, []*ast.File{f}, &Info{Instances: instMap, Uses: useMap})
if err != nil {
t.Fatal(err)
}
@@ -552,60 +584,71 @@
makePkg(lib)
pkg := makePkg(test.src)
- // look for instance information
- var targs []Type
- var typ Type
- for ident, inst := range instances {
- if ExprString(ident) == test.name {
- for i := 0; i < inst.TypeArgs.Len(); i++ {
- targs = append(targs, inst.TypeArgs.At(i))
- }
- typ = inst.Type
+ t.Run(pkg.Name(), func(t *testing.T) {
+ // Sort instances in source order for stability.
+ instances := sortedInstances(instMap)
+ if got, want := len(instances), len(test.instances); got != want {
+ t.Fatalf("got %d instances, want %d", got, want)
+ }
- // Check that we can find the corresponding parameterized type.
- ptype := uses[ident].Type()
+ // Pairwise compare with the expected instances.
+ for ii, inst := range instances {
+ var targs []Type
+ for i := 0; i < inst.Inst.TypeArgs.Len(); i++ {
+ targs = append(targs, inst.Inst.TypeArgs.At(i))
+ }
+ typ := inst.Inst.Type
+
+ testInst := test.instances[ii]
+ if got := inst.Ident.Name; got != testInst.name {
+ t.Fatalf("got name %s, want %s", got, testInst.name)
+ }
+ if len(targs) != len(testInst.targs) {
+ t.Fatalf("got %d type arguments; want %d", len(targs), len(testInst.targs))
+ }
+ for i, targ := range targs {
+ if got := targ.String(); got != testInst.targs[i] {
+ t.Errorf("type argument %d: got %s; want %s", i, got, testInst.targs[i])
+ }
+ }
+ if got := typ.Underlying().String(); got != testInst.typ {
+ t.Errorf("package %s: got %s; want %s", pkg.Name(), got, testInst.typ)
+ }
+
+ // Verify the invariant that re-instantiating the corresponding generic
+ // type with TypeArgs results in an identical instance.
+ ptype := useMap[inst.Ident].Type()
lister, _ := ptype.(interface{ TypeParams() *TypeParamList })
if lister == nil || lister.TypeParams().Len() == 0 {
- t.Errorf("package %s: info.Types[%v] = %v, want parameterized type", pkg.Name(), ident, ptype)
- continue
+ t.Fatalf("info.Types[%v] = %v, want parameterized type", inst.Ident, ptype)
}
-
- // Verify the invariant that re-instantiating the generic type with
- // TypeArgs results in an equivalent type.
inst2, err := Instantiate(nil, ptype, targs, true)
if err != nil {
t.Errorf("Instantiate(%v, %v) failed: %v", ptype, targs, err)
}
- if !Identical(inst.Type, inst2) {
- t.Errorf("%v and %v are not identical", inst.Type, inst2)
+ if !Identical(inst.Inst.Type, inst2) {
+ t.Errorf("%v and %v are not identical", inst.Inst.Type, inst2)
}
- break
}
- }
- if targs == nil {
- t.Errorf("package %s: no instance information found for %s", pkg.Name(), test.name)
- continue
- }
-
- // check that type arguments are correct
- if len(targs) != len(test.targs) {
- t.Errorf("package %s: got %d type arguments; want %d", pkg.Name(), len(targs), len(test.targs))
- continue
- }
- for i, targ := range targs {
- if got := targ.String(); got != test.targs[i] {
- t.Errorf("package %s, %d. type argument: got %s; want %s", pkg.Name(), i, got, test.targs[i])
- continue
- }
- }
-
- // check that the types match
- if got := typ.Underlying().String(); got != test.typ {
- t.Errorf("package %s: got %s; want %s", pkg.Name(), got, test.typ)
- }
+ })
}
}
+type recordedInstance struct {
+ Ident *ast.Ident
+ Inst Instance
+}
+
+func sortedInstances(m map[*ast.Ident]Instance) (instances []recordedInstance) {
+ for id, inst := range m {
+ instances = append(instances, recordedInstance{id, inst})
+ }
+ sort.Slice(instances, func(i, j int) bool {
+ return instances[i].Ident.Pos() < instances[j].Ident.Pos()
+ })
+ return instances
+}
+
func TestDefsInfo(t *testing.T) {
var tests = []struct {
src string
@@ -618,6 +661,11 @@
{`package p3; type x int`, `x`, `type p3.x int`},
{`package p4; func f()`, `f`, `func p4.f()`},
{`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`},
+
+ // Tests using generics.
+ {`package generic_g0; type x[T any] int`, `x`, `type generic_g0.x[T any] int`},
+ {`package generic_g1; func f[T any]() {}`, `f`, `func generic_g1.f[T any]()`},
+ {`package generic_g2; type x[T any] int; func (*x[_]) m() {}`, `m`, `func (*generic_g2.x[_]).m()`},
}
for _, test := range tests {
@@ -656,6 +704,33 @@
{`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`},
{`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`},
{`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`},
+
+ // Tests using generics.
+ {`package generic_g0; func _[T any]() { _ = x }; const x = 42`, `x`, `const generic_g0.x untyped int`},
+ {`package generic_g1; func _[T any](x T) { }`, `T`, `type parameter T any`},
+ {`package generic_g2; type N[A any] int; var _ N[int]`, `N`, `type generic_g2.N[A any] int`},
+ {`package generic_g3; type N[A any] int; func (N[_]) m() {}`, `N`, `type generic_g3.N[A any] int`},
+
+ // Uses of fields are instantiated.
+ {`package generic_s1; type N[A any] struct{ a A }; var f = N[int]{}.a`, `a`, `field a int`},
+ {`package generic_s1; type N[A any] struct{ a A }; func (r N[B]) m(b B) { r.a = b }`, `a`, `field a B`},
+
+ // Uses of methods are uses of the instantiated method.
+ {`package generic_m0; type N[A any] int; func (r N[B]) m() { r.n() }; func (N[C]) n() {}`, `n`, `func (generic_m0.N[B]).n()`},
+ {`package generic_m1; type N[A any] int; func (r N[B]) m() { }; var f = N[int].m`, `m`, `func (generic_m1.N[int]).m()`},
+ {`package generic_m2; func _[A any](v interface{ m() A }) { v.m() }`, `m`, `func (interface).m() A`},
+ {`package generic_m3; func f[A any]() interface{ m() A } { return nil }; var _ = f[int]().m()`, `m`, `func (interface).m() int`},
+ {`package generic_m4; type T[A any] func() interface{ m() A }; var x T[int]; var y = x().m`, `m`, `func (interface).m() int`},
+ {`package generic_m5; type T[A any] interface{ m() A }; func _[B any](t T[B]) { t.m() }`, `m`, `func (generic_m5.T[B]).m() B`},
+ {`package generic_m6; type T[A any] interface{ m() }; func _[B any](t T[B]) { t.m() }`, `m`, `func (generic_m6.T[B]).m()`},
+ {`package generic_m7; type T[A any] interface{ m() A }; func _(t T[int]) { t.m() }`, `m`, `func (generic_m7.T[int]).m() int`},
+ {`package generic_m8; type T[A any] interface{ m() }; func _(t T[int]) { t.m() }`, `m`, `func (generic_m8.T[int]).m()`},
+ {`package generic_m9; type T[A any] interface{ m() }; func _(t T[int]) { _ = t.m }`, `m`, `func (generic_m9.T[int]).m()`},
+ {
+ `package generic_m10; type E[A any] interface{ m() }; type T[B any] interface{ E[B]; n() }; func _(t T[int]) { t.m() }`,
+ `m`,
+ `func (generic_m10.E[int]).m()`,
+ },
}
for _, test := range tests {
@@ -668,8 +743,10 @@
var use Object
for id, obj := range info.Uses {
if id.Name == test.obj {
+ if use != nil {
+ panic(fmt.Sprintf("multiple uses of %q", id.Name))
+ }
use = obj
- break
}
}
if use == nil {
@@ -683,6 +760,90 @@
}
}
+func TestGenericMethodInfo(t *testing.T) {
+ src := `package p
+
+type N[A any] int
+
+func (r N[B]) m() { r.m(); r.n() }
+
+func (r *N[C]) n() { }
+`
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "p.go", src, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info := Info{
+ Defs: make(map[*ast.Ident]Object),
+ Uses: make(map[*ast.Ident]Object),
+ Selections: make(map[*ast.SelectorExpr]*Selection),
+ }
+ var conf Config
+ pkg, err := conf.Check("p", fset, []*ast.File{f}, &info)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ N := pkg.Scope().Lookup("N").Type().(*Named)
+
+ // Find the generic methods stored on N.
+ gm, gn := N.Method(0), N.Method(1)
+ if gm.Name() == "n" {
+ gm, gn = gn, gm
+ }
+
+ // Collect objects from info.
+ var dm, dn *Func // the declared methods
+ var dmm, dmn *Func // the methods used in the body of m
+ for _, decl := range f.Decls {
+ fdecl, ok := decl.(*ast.FuncDecl)
+ if !ok {
+ continue
+ }
+ def := info.Defs[fdecl.Name].(*Func)
+ switch fdecl.Name.Name {
+ case "m":
+ dm = def
+ ast.Inspect(fdecl.Body, func(n ast.Node) bool {
+ if call, ok := n.(*ast.CallExpr); ok {
+ sel := call.Fun.(*ast.SelectorExpr)
+ use := info.Uses[sel.Sel].(*Func)
+ selection := info.Selections[sel]
+ if selection.Kind() != MethodVal {
+ t.Errorf("Selection kind = %v, want %v", selection.Kind(), MethodVal)
+ }
+ if selection.Obj() != use {
+ t.Errorf("info.Selections contains %v, want %v", selection.Obj(), use)
+ }
+ switch sel.Sel.Name {
+ case "m":
+ dmm = use
+ case "n":
+ dmn = use
+ }
+ }
+ return true
+ })
+ case "n":
+ dn = def
+ }
+ }
+
+ if gm != dm {
+ t.Errorf(`N.Method(...) returns %v for "m", but Info.Defs has %v`, gm, dm)
+ }
+ if gn != dn {
+ t.Errorf(`N.Method(...) returns %v for "m", but Info.Defs has %v`, gm, dm)
+ }
+ if dmm != dm {
+ t.Errorf(`Inside "m", r.m uses %v, want the defined func %v`, dmm, dm)
+ }
+ if dmn == dn {
+ t.Errorf(`Inside "m", r.n uses %v, want a func distinct from %v`, dmm, dm)
+ }
+}
+
func TestImplicitsInfo(t *testing.T) {
testenv.MustHaveGoBuild(t)
@@ -703,6 +864,17 @@
{`package p8; func f(int) {}`, "field: var int"},
{`package p9; func f() (complex64) { return 0 }`, "field: var complex64"},
{`package p10; type T struct{}; func (*T) f() {}`, "field: var *p10.T"},
+
+ // Tests using generics.
+ {`package generic_f0; func f[T any](x int) {}`, ""}, // no Implicits entry
+ {`package generic_f1; func f[T any](int) {}`, "field: var int"},
+ {`package generic_f2; func f[T any](T) {}`, "field: var T"},
+ {`package generic_f3; func f[T any]() (complex64) { return 0 }`, "field: var complex64"},
+ {`package generic_f4; func f[T any](t T) (T) { return t }`, "field: var T"},
+ {`package generic_t0; type T[A any] struct{}; func (*T[_]) f() {}`, "field: var *generic_t0.T[_]"},
+ {`package generic_t1; type T[A any] struct{}; func _(x interface{}) { switch t := x.(type) { case T[int]: _ = t } }`, "caseClause: var t generic_t1.T[int]"},
+ {`package generic_t2; type T[A any] struct{}; func _[P any](x interface{}) { switch t := x.(type) { case T[P]: _ = t } }`, "caseClause: var t generic_t2.T[P]"},
+ {`package generic_t3; func _[P any](x interface{}) { switch t := x.(type) { case P: _ = t } }`, "caseClause: var t P"},
}
for _, test := range tests {
@@ -1412,6 +1584,18 @@
makePkg("main", mainSrc) // don't crash when type-checking this package
}
+func TestLookupFieldOrMethodOnNil(t *testing.T) {
+ // LookupFieldOrMethod on a nil type is expected to produce a run-time panic.
+ defer func() {
+ const want = "LookupFieldOrMethod on nil type"
+ p := recover()
+ if s, ok := p.(string); !ok || s != want {
+ t.Fatalf("got %v, want %s", p, want)
+ }
+ }()
+ LookupFieldOrMethod(nil, false, nil, "")
+}
+
func TestLookupFieldOrMethod(t *testing.T) {
// Test cases assume a lookup of the form a.f or x.f, where a stands for an
// addressable value, and x for a non-addressable value (even though a variable
@@ -1533,7 +1717,7 @@
var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F
var a []int
- for i, x := range /*i=undef*/ /*x=var:16*/ a /*i=var:20*/ /*x=var:20*/ { _ = i; _ = x }
+ for i, x := range a /*i=undef*/ /*x=var:16*/ { _ = i; _ = x }
var i interface{}
switch y := i.(type) { /*y=undef*/
@@ -2151,27 +2335,27 @@
conf := Config{Error: func(error) {}}
pkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
- scope := pkg.Scope()
+ lookup := func(tname string) Type { return pkg.Scope().Lookup(tname).Type() }
var (
- EmptyIface = scope.Lookup("EmptyIface").Type().Underlying().(*Interface)
- I = scope.Lookup("I").Type().(*Named)
+ EmptyIface = lookup("EmptyIface").Underlying().(*Interface)
+ I = lookup("I").(*Named)
II = I.Underlying().(*Interface)
- C = scope.Lookup("C").Type().(*Named)
+ C = lookup("C").(*Named)
CI = C.Underlying().(*Interface)
- Integer = scope.Lookup("Integer").Type().Underlying().(*Interface)
- EmptyTypeSet = scope.Lookup("EmptyTypeSet").Type().Underlying().(*Interface)
- N1 = scope.Lookup("N1").Type()
+ Integer = lookup("Integer").Underlying().(*Interface)
+ EmptyTypeSet = lookup("EmptyTypeSet").Underlying().(*Interface)
+ N1 = lookup("N1")
N1p = NewPointer(N1)
- N2 = scope.Lookup("N2").Type()
+ N2 = lookup("N2")
N2p = NewPointer(N2)
- N3 = scope.Lookup("N3").Type()
- N4 = scope.Lookup("N4").Type()
- Bad = scope.Lookup("Bad").Type()
+ N3 = lookup("N3")
+ N4 = lookup("N4")
+ Bad = lookup("Bad")
)
tests := []struct {
- t Type
- i *Interface
+ V Type
+ T *Interface
want bool
}{
{I, II, true},
@@ -2202,8 +2386,78 @@
}
for _, test := range tests {
- if got := Implements(test.t, test.i); got != test.want {
- t.Errorf("Implements(%s, %s) = %t, want %t", test.t, test.i, got, test.want)
+ if got := Implements(test.V, test.T); got != test.want {
+ t.Errorf("Implements(%s, %s) = %t, want %t", test.V, test.T, got, test.want)
+ }
+
+ // The type assertion x.(T) is valid if T is an interface or if T implements the type of x.
+ // The assertion is never valid if T is a bad type.
+ V := test.T
+ T := test.V
+ want := false
+ if _, ok := T.Underlying().(*Interface); (ok || Implements(T, V)) && T != Bad {
+ want = true
+ }
+ if got := AssertableTo(V, T); got != want {
+ t.Errorf("AssertableTo(%s, %s) = %t, want %t", V, T, got, want)
}
}
}
+
+func TestMissingMethodAlternative(t *testing.T) {
+ const src = `
+package p
+type T interface {
+ m()
+}
+
+type V0 struct{}
+func (V0) m() {}
+
+type V1 struct{}
+
+type V2 struct{}
+func (V2) m() int
+
+type V3 struct{}
+func (*V3) m()
+
+type V4 struct{}
+func (V4) M()
+`
+
+ pkg, err := pkgFor("p.go", src, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ T := pkg.Scope().Lookup("T").Type().Underlying().(*Interface)
+ lookup := func(name string) (*Func, bool) {
+ return MissingMethod(pkg.Scope().Lookup(name).Type(), T, true)
+ }
+
+ // V0 has method m with correct signature. Should not report wrongType.
+ method, wrongType := lookup("V0")
+ if method != nil || wrongType {
+ t.Fatalf("V0: got method = %v, wrongType = %v", method, wrongType)
+ }
+
+ checkMissingMethod := func(tname string, reportWrongType bool) {
+ method, wrongType := lookup(tname)
+ if method == nil || method.Name() != "m" || wrongType != reportWrongType {
+ t.Fatalf("%s: got method = %v, wrongType = %v", tname, method, wrongType)
+ }
+ }
+
+ // V1 has no method m. Should not report wrongType.
+ checkMissingMethod("V1", false)
+
+ // V2 has method m with wrong signature type (ignoring receiver). Should report wrongType.
+ checkMissingMethod("V2", true)
+
+ // V3 has no method m but it exists on *V3. Should report wrongType.
+ checkMissingMethod("V3", true)
+
+ // V4 has no method m but has M. Should not report wrongType.
+ checkMissingMethod("V4", false)
+}
diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go
index a556e5e..f5e22c2 100644
--- a/src/go/types/assignments.go
+++ b/src/go/types/assignments.go
@@ -264,7 +264,7 @@
var s string
switch {
case t == nil:
- fallthrough // should not happend but be cautious
+ fallthrough // should not happen but be cautious
case t == Typ[Invalid]:
s = "<T>"
case isUntyped(t):
@@ -290,15 +290,14 @@
return "(" + strings.Join(res, ", ") + ")"
}
-func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
- measure := func(x int, unit string) string {
- s := fmt.Sprintf("%d %s", x, unit)
- if x != 1 {
- s += "s"
- }
- return s
+func measure(x int, unit string) string {
+ if x != 1 {
+ unit += "s"
}
+ return fmt.Sprintf("%d %s", x, unit)
+}
+func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
vars := measure(nvars, "variable")
vals := measure(nvals, "value")
rhs0 := rhs[0]
@@ -313,7 +312,7 @@
}
// If returnStmt != nil, initVars is called to type-check the assignment
-// of return expressions, and returnStmt is the the return statement.
+// of return expressions, and returnStmt is the return statement.
func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnStmt ast.Stmt) {
rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && returnStmt == nil)
diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go
index 828220f..c81e73c 100644
--- a/src/go/types/builtins.go
+++ b/src/go/types/builtins.go
@@ -83,10 +83,24 @@
// of S and the respective parameter passing rules apply."
S := x.typ
var T Type
- if s, _ := structuralType(S).(*Slice); s != nil {
+ if s, _ := coreType(S).(*Slice); s != nil {
T = s.elem
} else {
- check.invalidArg(x, _InvalidAppend, "%s is not a slice", x)
+ var cause string
+ switch {
+ case x.isNil():
+ cause = "have untyped nil"
+ case isTypeParam(S):
+ if u := coreType(S); u != nil {
+ cause = check.sprintf("%s has core type %s", x, u)
+ } else {
+ cause = check.sprintf("%s has no core type", x)
+ }
+ default:
+ cause = check.sprintf("have %s", x)
+ }
+ // don't use Checker.invalidArg here as it would repeat "argument" in the error message
+ check.errorf(x, _InvalidAppend, "first argument to append must be a slice; %s", cause)
return
}
@@ -102,7 +116,7 @@
if x.mode == invalid {
return
}
- if allString(x.typ) {
+ if t := coreString(x.typ); t != nil && isString(t) {
if check.Types != nil {
sig := makeSig(S, S, x.typ)
sig.variadic = true
@@ -143,9 +157,8 @@
// cap(x)
// len(x)
mode := invalid
- var typ Type
var val constant.Value
- switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) {
+ switch t := arrayPtrDeref(under(x.typ)).(type) {
case *Basic:
if isString(t) && id == _Len {
if x.mode == constant_ {
@@ -202,7 +215,7 @@
}
}
- if mode == invalid && typ != Typ[Invalid] {
+ if mode == invalid && under(x.typ) != Typ[Invalid] {
code := _InvalidCap
if id == _Len {
code = _InvalidLen
@@ -211,12 +224,14 @@
return
}
+ // record the signature before changing x.typ
+ if check.Types != nil && mode != constant_ {
+ check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ))
+ }
+
x.mode = mode
x.typ = Typ[Int]
x.val = val
- if check.Types != nil && mode != constant_ {
- check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
- }
case _Close:
// close(c)
@@ -314,7 +329,7 @@
}
return nil
}
- resTyp := check.applyTypeFunc(f, x.typ)
+ resTyp := check.applyTypeFunc(f, x, id)
if resTyp == nil {
check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ)
return
@@ -335,14 +350,14 @@
case _Copy:
// copy(x, y []T) int
- dst, _ := structuralType(x.typ).(*Slice)
+ dst, _ := coreType(x.typ).(*Slice)
var y operand
arg(&y, 1)
if y.mode == invalid {
return
}
- src0 := structuralString(y.typ)
+ src0 := coreString(y.typ)
if src0 != nil && isString(src0) {
src0 = NewSlice(universeByte)
}
@@ -442,7 +457,7 @@
}
return nil
}
- resTyp := check.applyTypeFunc(f, x.typ)
+ resTyp := check.applyTypeFunc(f, x, id)
if resTyp == nil {
code := _InvalidImag
if id == _Real {
@@ -480,13 +495,13 @@
}
var min int // minimum number of arguments
- switch structuralType(T).(type) {
+ switch coreType(T).(type) {
case *Slice:
min = 2
case *Map, *Chan:
min = 1
case nil:
- check.errorf(arg0, _InvalidMake, "cannot make %s: no structural type", arg0)
+ check.errorf(arg0, _InvalidMake, "cannot make %s: no core type", arg0)
return
default:
check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0)
@@ -809,8 +824,8 @@
// of x. If any of these applications of f return nil,
// applyTypeFunc returns nil.
// If x is not a type parameter, the result is f(x).
-func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
- if tp, _ := x.(*TypeParam); tp != nil {
+func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId) Type {
+ if tp, _ := x.typ.(*TypeParam); tp != nil {
// Test if t satisfies the requirements for the argument
// type and collect possible result types at the same time.
var terms []*Term
@@ -827,17 +842,34 @@
return nil
}
+ // We can type-check this fine but we're introducing a synthetic
+ // type parameter for the result. It's not clear what the API
+ // implications are here. Report an error for 1.18 (see #50912),
+ // but continue type-checking.
+ var code errorCode
+ switch id {
+ case _Real:
+ code = _InvalidReal
+ case _Imag:
+ code = _InvalidImag
+ case _Complex:
+ code = _InvalidComplex
+ default:
+ unreachable()
+ }
+ check.softErrorf(x, code, "%s not supported as argument to %s for go1.18 (see issue #50937)", x, predeclaredFuncs[id].name)
+
// Construct a suitable new type parameter for the result type.
// The type parameter is placed in the current package so export/import
// works as expected.
- tpar := NewTypeName(token.NoPos, check.pkg, "<type parameter>", nil)
+ tpar := NewTypeName(token.NoPos, check.pkg, tp.obj.name, nil)
ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect
ptyp.index = tp.index
return ptyp
}
- return f(x)
+ return f(x.typ)
}
// makeSig makes a signature for the given argument and result types.
diff --git a/src/go/types/builtins_test.go b/src/go/types/builtins_test.go
index edcd7e7..7e967a3 100644
--- a/src/go/types/builtins_test.go
+++ b/src/go/types/builtins_test.go
@@ -29,6 +29,8 @@
{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
{"cap", `var s []int64; _ = cap(s)`, `func([]int64) int`},
{"cap", `var c chan<-bool; _ = cap(c)`, `func(chan<- bool) int`},
+ {"cap", `type S []byte; var s S; _ = cap(s)`, `func(p.S) int`},
+ {"cap", `var s P; _ = cap(s)`, `func(P) int`},
{"len", `_ = len("foo")`, `invalid type`}, // constant
{"len", `var s string; _ = len(s)`, `func(string) int`},
@@ -37,6 +39,8 @@
{"len", `var s []int64; _ = len(s)`, `func([]int64) int`},
{"len", `var c chan<-bool; _ = len(c)`, `func(chan<- bool) int`},
{"len", `var m map[string]float32; _ = len(m)`, `func(map[string]float32) int`},
+ {"len", `type S []byte; var s S; _ = len(s)`, `func(p.S) int`},
+ {"len", `var s P; _ = len(s)`, `func(P) int`},
{"close", `var c chan int; close(c)`, `func(chan int)`},
{"close", `var c chan<- chan string; close(c)`, `func(chan<- chan string)`},
@@ -157,7 +161,7 @@
// parseGenericSrc in types2 is not necessary. We can just parse in testBuiltinSignature below.
func testBuiltinSignature(t *testing.T, name, src0, want string) {
- src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P any]() { %s }`, src0)
+ src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P ~[]byte]() { %s }`, src0)
f, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
t.Errorf("%s: %s", src0, err)
diff --git a/src/go/types/call.go b/src/go/types/call.go
index 4156d56..5d1f60d 100644
--- a/src/go/types/call.go
+++ b/src/go/types/call.go
@@ -75,17 +75,21 @@
inst := check.instance(pos, typ, targs, check.bestContext(nil)).(*Signature)
assert(len(xlist) <= len(targs))
- tparams := typ.TypeParams().list()
- if i, err := check.verify(pos, tparams, targs); err != nil {
- // best position for error reporting
- pos := pos
- if i < len(xlist) {
- pos = xlist[i].Pos()
+
+ // verify instantiation lazily (was issue #50450)
+ check.later(func() {
+ tparams := typ.TypeParams().list()
+ if i, err := check.verify(pos, tparams, targs); err != nil {
+ // best position for error reporting
+ pos := pos
+ if i < len(xlist) {
+ pos = xlist[i].Pos()
+ }
+ check.softErrorf(atPos(pos), _InvalidTypeArg, "%s", err)
+ } else {
+ check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist)
}
- check.softErrorf(atPos(pos), _InvalidTypeArg, "%s", err)
- } else {
- check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist)
- }
+ })
return inst
}
@@ -167,7 +171,7 @@
cgocall := x.mode == cgofunc
// a type parameter may be "called" if all types have the same signature
- sig, _ := structuralType(x.typ).(*Signature)
+ sig, _ := coreType(x.typ).(*Signature)
if sig == nil {
check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x)
x.mode = invalid
@@ -425,7 +429,7 @@
"_Cmacro_", // function to evaluate the expanded expression
}
-func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
+func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named) {
// these must be declared before the "goto Error" statements
var (
obj Object
@@ -523,32 +527,48 @@
}
check.exprOrType(x, e.X, false)
- if x.mode == invalid {
+ switch x.mode {
+ case typexpr:
+ // don't crash for "type T T.x" (was issue #51509)
+ if def != nil && x.typ == def {
+ check.cycleError([]Object{def.obj})
+ goto Error
+ }
+ case builtin:
+ // types2 uses the position of '.' for the error
+ check.errorf(e.Sel, _UncalledBuiltin, "cannot select on %s", x)
+ goto Error
+ case invalid:
goto Error
}
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
- switch {
- case index != nil:
+ // Don't report another error if the underlying type was invalid (issue #49541).
+ if under(x.typ) == Typ[Invalid] {
+ goto Error
+ }
+
+ if index != nil {
// TODO(gri) should provide actual type where the conflict happens
check.errorf(e.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel)
- case indirect:
- check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ)
- default:
- var why string
- if tpar, _ := x.typ.(*TypeParam); tpar != nil {
- // Type parameter bounds don't specify fields, so don't mention "field".
- if tname := tpar.iface().obj; tname != nil {
- why = check.sprintf("interface %s has no method %s", tname.name, sel)
- } else {
- why = check.sprintf("type bound for %s has no method %s", x.typ, sel)
- }
- } else {
- why = check.sprintf("type %s has no field or method %s", x.typ, sel)
- }
+ goto Error
+ }
+ if indirect {
+ check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ)
+ goto Error
+ }
+
+ var why string
+ if isInterfacePtr(x.typ) {
+ why = check.interfacePtrError(x.typ)
+ } else {
+ why = check.sprintf("type %s has no field or method %s", x.typ, sel)
// Check if capitalization of sel matters and provide better error message in that case.
+ // TODO(gri) This code only looks at the first character but LookupFieldOrMethod should
+ // have an (internal) mechanism for case-insensitive lookup that we should use
+ // instead (see types2).
if len(sel) > 0 {
var changeCase string
if r := rune(sel[0]); unicode.IsUpper(r) {
@@ -560,9 +580,8 @@
why += ", but does have " + changeCase
}
}
-
- check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why)
}
+ check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why)
goto Error
}
diff --git a/src/go/types/check.go b/src/go/types/check.go
index 2dd38e2..2313637 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -24,19 +24,6 @@
compilerErrorMessages = false // match compiler error messages
)
-// If forceStrict is set, the type-checker enforces additional
-// rules not specified by the Go 1 spec, but which will
-// catch guaranteed run-time errors if the respective
-// code is executed. In other words, programs passing in
-// strict mode are Go 1 compliant, but not all Go 1 programs
-// will pass in strict mode. The additional rules are:
-//
-// - A type assertion x.(T) where T is an interface type
-// is invalid if any (statically known) method that exists
-// for both x and T have different signatures.
-//
-const forceStrict = false
-
// exprInfo stores information about an untyped expression.
type exprInfo struct {
isLhs bool // expression is lhs operand of a shift with delayed type-check
@@ -118,6 +105,7 @@
nextID uint64 // unique Id for type parameters (first valid Id is 1)
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
+ infoMap map[*Named]typeInfo // maps named types to their associated type info (for cycle detection)
// pkgPathMap maps package names to the set of distinct import paths we've
// seen for that name, anywhere in the import graph. It is used for
@@ -136,6 +124,8 @@
imports []*PkgName // list of imported packages
dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through
recvTParamMap map[*ast.Ident]*TypeParam // maps blank receiver type parameters to their type
+ brokenAliases map[*TypeName]bool // set of aliases with broken (not yet determined) types
+ unionTypeSets map[*Union]*_TypeSet // computed type sets for union types
mono monoGraph // graph for detecting non-monomorphizable instantiation loops
firstErr error // first error encountered
@@ -143,7 +133,7 @@
untyped map[ast.Expr]exprInfo // map of expressions without final type
delayed []action // stack of delayed action segments; segments are processed in FIFO order
objPath []Object // path of object dependencies during type inference (for cycle reporting)
- defTypes []*Named // defined types created during type checking, for final validation.
+ cleaners []cleaner // list of types that may need a final cleanup at the end of type-checking
// environment within which the current object is type-checked (valid only
// for the duration of type-checking a specific object)
@@ -165,6 +155,27 @@
from.addDep(to)
}
+// brokenAlias records that alias doesn't have a determined type yet.
+// It also sets alias.typ to Typ[Invalid].
+func (check *Checker) brokenAlias(alias *TypeName) {
+ if check.brokenAliases == nil {
+ check.brokenAliases = make(map[*TypeName]bool)
+ }
+ check.brokenAliases[alias] = true
+ alias.typ = Typ[Invalid]
+}
+
+// validAlias records that alias has the valid type typ (possibly Typ[Invalid]).
+func (check *Checker) validAlias(alias *TypeName, typ Type) {
+ delete(check.brokenAliases, alias)
+ alias.typ = typ
+}
+
+// isBrokenAlias reports whether alias doesn't have a determined type yet.
+func (check *Checker) isBrokenAlias(alias *TypeName) bool {
+ return alias.typ == Typ[Invalid] && check.brokenAliases[alias]
+}
+
func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, typ *Basic, val constant.Value) {
m := check.untyped
if m == nil {
@@ -201,6 +212,16 @@
return obj
}
+type cleaner interface {
+ cleanup()
+}
+
+// needsCleanup records objects/types that implement the cleanup method
+// which will be called at the end of type-checking.
+func (check *Checker) needsCleanup(c cleaner) {
+ check.cleaners = append(check.cleaners, c)
+}
+
// NewChecker returns a new Checker instance for a given package.
// Package files may be added incrementally via checker.Files.
func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker {
@@ -228,6 +249,7 @@
version: version,
objMap: make(map[Object]*declInfo),
impMap: make(map[importKey]*Package),
+ infoMap: make(map[*Named]typeInfo),
}
}
@@ -243,6 +265,8 @@
check.methods = nil
check.untyped = nil
check.delayed = nil
+ check.objPath = nil
+ check.cleaners = nil
// determine package name and collect valid files
pkg := check.pkg
@@ -292,22 +316,37 @@
defer check.handleBailout(&err)
+ print := func(msg string) {
+ if trace {
+ fmt.Println()
+ fmt.Println(msg)
+ }
+ }
+
+ print("== initFiles ==")
check.initFiles(files)
+ print("== collectObjects ==")
check.collectObjects()
+ print("== packageObjects ==")
check.packageObjects()
+ print("== processDelayed ==")
check.processDelayed(0) // incl. all functions
- check.expandDefTypes()
+ print("== cleanup ==")
+ check.cleanup()
+ print("== initOrder ==")
check.initOrder()
if !check.conf.DisableUnusedImportCheck {
+ print("== unusedImports ==")
check.unusedImports()
}
+ print("== recordUntyped ==")
check.recordUntyped()
if check.firstErr == nil {
@@ -323,7 +362,8 @@
check.pkgPathMap = nil
check.seenPkgMap = nil
check.recvTParamMap = nil
- check.defTypes = nil
+ check.brokenAliases = nil
+ check.unionTypeSets = nil
check.ctxt = nil
// TODO(rFindley) There's more memory we should release at this point.
@@ -351,27 +391,13 @@
check.delayed = check.delayed[:top]
}
-func (check *Checker) expandDefTypes() {
- // Ensure that every defined type created in the course of type-checking has
- // either non-*Named underlying, or is unresolved.
- //
- // This guarantees that we don't leak any types whose underlying is *Named,
- // because any unresolved instances will lazily compute their underlying by
- // substituting in the underlying of their origin. The origin must have
- // either been imported or type-checked and expanded here, and in either case
- // its underlying will be fully expanded.
- for i := 0; i < len(check.defTypes); i++ {
- n := check.defTypes[i]
- switch n.underlying.(type) {
- case nil:
- if n.resolver == nil {
- panic("nil underlying")
- }
- case *Named:
- n.under() // n.under may add entries to check.defTypes
- }
- n.check = nil
+// cleanup runs cleanup for all collected cleaners.
+func (check *Checker) cleanup() {
+ // Don't use a range clause since Named.cleanup may add more cleaners.
+ for i := 0; i < len(check.cleaners); i++ {
+ check.cleaners[i].cleanup()
}
+ check.cleaners = nil
}
func (check *Checker) record(x *operand) {
diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go
index e296d13..81ea81c 100644
--- a/src/go/types/check_test.go
+++ b/src/go/types/check_test.go
@@ -376,10 +376,13 @@
testFiles(t, &StdSizes{4, 4}, []string{"p.go"}, [][]byte{[]byte(src)}, false, nil)
}
-func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) }
-func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", false) }
-func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", false) }
-func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", false) }
+func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) }
+func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", false) }
+func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", false) }
+func TestFixedbugs(t *testing.T) {
+ DefPredeclaredTestFuncs()
+ testDirFiles(t, "testdata/fixedbugs", false)
+}
func testDirFiles(t *testing.T, dir string, manual bool) {
testenv.MustHaveGoBuild(t)
diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go
index a5b359e..c5a69cd 100644
--- a/src/go/types/conversions.go
+++ b/src/go/types/conversions.go
@@ -48,11 +48,14 @@
// have specific types, constant x cannot be
// converted.
ok = T.(*TypeParam).underIs(func(u Type) bool {
- // t is nil if there are no specific type terms
+ // u is nil if there are no specific type terms
if u == nil {
cause = check.sprintf("%s does not contain specific types", T)
return false
}
+ if isString(x.typ) && isBytesOrRunes(u) {
+ return true
+ }
if !constConvertibleTo(u, nil) {
cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
return false
@@ -96,11 +99,11 @@
// use the default type (e.g., []byte("foo") should report string
// not []byte as type for the constant "foo").
// - Keep untyped nil for untyped nil arguments.
- // - For integer to string conversions, keep the argument type.
+ // - For constant integer to string conversions, keep the argument type.
// (See also the TODO below.)
if IsInterface(T) && !isTypeParam(T) || constArg && !isConstType(T) || x.isNil() {
final = Default(x.typ) // default type of untyped nil is untyped nil
- } else if isInteger(x.typ) && allString(T) {
+ } else if x.mode == constant_ && isInteger(x.typ) && allString(T) {
final = x.typ
}
check.updateExprType(x.expr, final, true)
diff --git a/src/go/types/decl.go b/src/go/types/decl.go
index 2c51329..93a37d7 100644
--- a/src/go/types/decl.go
+++ b/src/go/types/decl.go
@@ -65,12 +65,6 @@
}()
}
- // Funcs with m.instRecv set have not yet be completed. Complete them now
- // so that they have a type when objDecl exits.
- if m, _ := obj.(*Func); m != nil && m.instRecv != nil {
- check.completeMethod(nil, m)
- }
-
// Checking the declaration of obj means inferring its type
// (and possibly its value, for constants).
// An object's type (and thus the object) may be in one of
@@ -277,7 +271,9 @@
check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef)
}
defer func() {
- if !valid {
+ if valid {
+ check.trace(obj.Pos(), "=> cycle is valid")
+ } else {
check.trace(obj.Pos(), "=> error: cycle is invalid")
}
}()
@@ -303,96 +299,6 @@
return false
}
-type typeInfo uint
-
-// validType verifies that the given type does not "expand" infinitely
-// producing a cycle in the type graph. Cycles are detected by marking
-// defined types.
-// (Cycles involving alias types, as in "type A = [10]A" are detected
-// earlier, via the objDecl cycle detection mechanism.)
-func (check *Checker) validType(typ Type, path []Object) typeInfo {
- const (
- unknown typeInfo = iota
- marked
- valid
- invalid
- )
-
- switch t := typ.(type) {
- case *Array:
- return check.validType(t.elem, path)
-
- case *Struct:
- for _, f := range t.fields {
- if check.validType(f.typ, path) == invalid {
- return invalid
- }
- }
-
- case *Union:
- for _, t := range t.terms {
- if check.validType(t.typ, path) == invalid {
- return invalid
- }
- }
-
- case *Interface:
- for _, etyp := range t.embeddeds {
- if check.validType(etyp, path) == invalid {
- return invalid
- }
- }
-
- case *Named:
- // If t is parameterized, we should be considering the instantiated (expanded)
- // form of t, but in general we can't with this algorithm: if t is an invalid
- // type it may be so because it infinitely expands through a type parameter.
- // Instantiating such a type would lead to an infinite sequence of instantiations.
- // In general, we need "type flow analysis" to recognize those cases.
- // Example: type A[T any] struct{ x A[*T] } (issue #48951)
- // In this algorithm we always only consider the orginal, uninstantiated type.
- // This won't recognize some invalid cases with parameterized types, but it
- // will terminate.
- t = t.orig
-
- // don't touch the type if it is from a different package or the Universe scope
- // (doing so would lead to a race condition - was issue #35049)
- if t.obj.pkg != check.pkg {
- return valid
- }
-
- // don't report a 2nd error if we already know the type is invalid
- // (e.g., if a cycle was detected earlier, via under).
- if t.underlying == Typ[Invalid] {
- t.info = invalid
- return invalid
- }
-
- switch t.info {
- case unknown:
- t.info = marked
- t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
- case marked:
- // cycle detected
- for i, tn := range path {
- if t.obj.pkg != check.pkg {
- panic("type cycle via package-external type")
- }
- if tn == t.obj {
- check.cycleError(path[i:])
- t.info = invalid
- t.underlying = Typ[Invalid]
- return invalid
- }
- }
- panic("cycle start not found")
- }
- return t.info
- }
-
- return valid
-}
-
// cycleError reports a declaration cycle starting with
// the object in cycle that is "first" in the source.
func (check *Checker) cycleError(cycle []Object) {
@@ -401,7 +307,16 @@
// cycle? That would be more consistent with other error messages.
i := firstInSrc(cycle)
obj := cycle[i]
- check.errorf(obj, _InvalidDeclCycle, "illegal cycle in declaration of %s", obj.Name())
+ // If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors.
+ tname, _ := obj.(*TypeName)
+ if tname != nil && tname.IsAlias() {
+ check.validAlias(tname, Typ[Invalid])
+ }
+ if tname != nil && compilerErrorMessages {
+ check.errorf(obj, _InvalidDeclCycle, "invalid recursive type %s", obj.Name())
+ } else {
+ check.errorf(obj, _InvalidDeclCycle, "illegal cycle in declaration of %s", obj.Name())
+ }
for range cycle {
check.errorf(obj, _InvalidDeclCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented
i++
@@ -620,7 +535,9 @@
var rhs Type
check.later(func() {
- check.validType(obj.typ, nil)
+ if t, _ := obj.typ.(*Named); t != nil { // type may be invalid
+ check.validType(t)
+ }
// If typ is local, an error was already reported where typ is specified/defined.
if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) {
check.errorf(tdecl.Type, _UnsupportedFeature, "using type constraint %s requires go1.18 or later", rhs)
@@ -641,9 +558,9 @@
check.errorf(atPos(tdecl.Assign), _BadDecl, "type aliases requires go1.9 or later")
}
- obj.typ = Typ[Invalid]
+ check.brokenAlias(obj)
rhs = check.varType(tdecl.Type)
- obj.typ = rhs
+ check.validAlias(obj, rhs)
return
}
@@ -707,35 +624,28 @@
}()
index := 0
- var bounds []Type
- var posns []positioner // bound positions
for _, f := range list.List {
- // TODO(rfindley) we should be able to rely on f.Type != nil at this point
+ var bound Type
+ // NOTE: we may be able to assert that f.Type != nil here, but this is not
+ // an invariant of the AST, so we are cautious.
if f.Type != nil {
- bound := check.bound(f.Type)
- bounds = append(bounds, bound)
- posns = append(posns, f.Type)
- for i := range f.Names {
- tparams[index+i].bound = bound
- }
- }
- index += len(f.Names)
- }
-
- check.later(func() {
- for i, bound := range bounds {
+ bound = check.bound(f.Type)
if isTypeParam(bound) {
// We may be able to allow this since it is now well-defined what
// the underlying type and thus type set of a type parameter is.
// But we may need some additional form of cycle detection within
// type parameter lists.
- check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint")
+ check.error(f.Type, _MisplacedTypeParam, "cannot use a type parameter as constraint")
+ bound = Typ[Invalid]
}
+ } else {
+ bound = Typ[Invalid]
}
- for _, tpar := range tparams {
- tpar.iface() // compute type set
+ for i := range f.Names {
+ tparams[index+i].bound = bound
}
- })
+ index += len(f.Names)
+ }
}
func (check *Checker) bound(x ast.Expr) Type {
@@ -801,6 +711,7 @@
// and field names must be distinct."
base, _ := obj.typ.(*Named) // shouldn't fail but be conservative
if base != nil {
+ assert(base.targs.Len() == 0) // collectMethods should not be called on an instantiated type
u := base.under()
if t, _ := u.(*Struct); t != nil {
for _, fld := range t.fields {
@@ -813,7 +724,8 @@
// Checker.Files may be called multiple times; additional package files
// may add methods to already type-checked types. Add pre-existing methods
// so that we can detect redeclarations.
- for _, m := range base.methods {
+ for i := 0; i < base.methods.Len(); i++ {
+ m := base.methods.At(i, nil)
assert(m.name != "_")
assert(mset.insert(m) == nil)
}
@@ -839,7 +751,7 @@
if base != nil {
base.resolve(nil) // TODO(mdempsky): Probably unnecessary.
- base.methods = append(base.methods, m)
+ base.AddMethod(m)
}
}
}
diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go
index b3796e8..64cf24c 100644
--- a/src/go/types/errorcodes.go
+++ b/src/go/types/errorcodes.go
@@ -98,13 +98,10 @@
// _InvalidDeclCycle occurs when a declaration cycle is not valid.
//
// Example:
- // import "unsafe"
- //
- // type T struct {
- // a [n]int
+ // type S struct {
+ // S
// }
//
- // var n = unsafe.Sizeof(T{})
_InvalidDeclCycle
// _InvalidTypeCycle occurs when a cycle in type definitions results in a
@@ -1342,11 +1339,6 @@
// func _() {
// f()
// }
- //
- // Example:
- // type N[P, Q any] struct{}
- //
- // var _ N[int]
_CannotInferTypeArgs
// _InvalidTypeArg occurs when a type argument does not satisfy its
@@ -1385,10 +1377,7 @@
// _InvalidMethodTypeParams occurs when methods have type parameters.
//
- // Example:
- // type T int
- //
- // func (T) m[P any]() {}
+ // It cannot be encountered with an AST parsed using go/parser.
_InvalidMethodTypeParams
// _MisplacedTypeParam occurs when a type parameter is used in a place where
diff --git a/src/go/types/errors.go b/src/go/types/errors.go
index 81c62a8..fade863 100644
--- a/src/go/types/errors.go
+++ b/src/go/types/errors.go
@@ -7,6 +7,7 @@
package types
import (
+ "bytes"
"errors"
"fmt"
"go/ast"
@@ -62,8 +63,15 @@
}
}
+// check may be nil.
func (check *Checker) sprintf(format string, args ...any) string {
- return sprintf(check.fset, check.qualifier, false, format, args...)
+ var fset *token.FileSet
+ var qf Qualifier
+ if check != nil {
+ fset = check.fset
+ qf = check.qualifier
+ }
+ return sprintf(fset, qf, false, format, args...)
}
func sprintf(fset *token.FileSet, qf Qualifier, debug bool, format string, args ...any) string {
@@ -81,10 +89,38 @@
}
case ast.Expr:
arg = ExprString(a)
+ case []ast.Expr:
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+ writeExprList(&buf, a)
+ buf.WriteByte(']')
+ arg = buf.String()
case Object:
arg = ObjectString(a, qf)
case Type:
arg = typeString(a, qf, debug)
+ case []Type:
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(typeString(x, qf, debug))
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
+ case []*TypeParam:
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+ for i, x := range a {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(typeString(x, qf, debug)) // use typeString so we get subscripts when debugging
+ }
+ buf.WriteByte(']')
+ arg = buf.String()
}
args[i] = arg
}
diff --git a/src/go/types/eval.go b/src/go/types/eval.go
index c8bb005..5700cbf 100644
--- a/src/go/types/eval.go
+++ b/src/go/types/eval.go
@@ -37,8 +37,8 @@
// CheckExpr type checks the expression expr as if it had appeared at position
// pos of package pkg. Type information about the expression is recorded in
-// info. The expression may be an uninstantiated parameterized function or
-// type.
+// info. The expression may be an identifier denoting an uninstantiated generic
+// function or type.
//
// If pkg == nil, the Universe scope is used and the provided
// position pos is ignored. If pkg != nil, and pos is invalid,
diff --git a/src/go/types/example_test.go b/src/go/types/example_test.go
index 2702567..3c1bdb5 100644
--- a/src/go/types/example_test.go
+++ b/src/go/types/example_test.go
@@ -279,7 +279,7 @@
//
// Types and Values of each expression:
// 4: 8 | string | type : string
- // 6:15 | len | builtin : func(string) int
+ // 6:15 | len | builtin : func(fib.S) int
// 6:15 | len(b) | value : int
// 6:19 | b | var : fib.S
// 6:23 | S | type : fib.S
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 452e9ab..e24bd60 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -74,7 +74,7 @@
func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
if pred := m[op]; pred != nil {
if !pred(x.typ) {
- check.invalidOp(x, _UndefinedOp, "operator %s not defined for %s", op, x)
+ check.invalidOp(x, _UndefinedOp, "operator %s not defined on %s", op, x)
return false
}
} else {
@@ -173,9 +173,9 @@
return
case token.ARROW:
- u := structuralType(x.typ)
+ u := coreType(x.typ)
if u == nil {
- check.invalidOp(x, _InvalidReceive, "cannot receive from %s: no structural type", x)
+ check.invalidOp(x, _InvalidReceive, "cannot receive from %s: no core type", x)
x.mode = invalid
return
}
@@ -472,8 +472,11 @@
// Also, if x is a constant, it must be representable as a value of typ,
// and if x is the (formerly untyped) lhs operand of a non-constant
// shift, it must be an integer value.
-//
func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
+ check.updateExprType0(nil, x, typ, final)
+}
+
+func (check *Checker) updateExprType0(parent, x ast.Expr, typ Type, final bool) {
old, found := check.untyped[x]
if !found {
return // nothing to do
@@ -515,7 +518,7 @@
// No operands to take care of.
case *ast.ParenExpr:
- check.updateExprType(x.X, typ, final)
+ check.updateExprType0(x, x.X, typ, final)
case *ast.UnaryExpr:
// If x is a constant, the operands were constants.
@@ -526,7 +529,7 @@
if old.val != nil {
break
}
- check.updateExprType(x.X, typ, final)
+ check.updateExprType0(x, x.X, typ, final)
case *ast.BinaryExpr:
if old.val != nil {
@@ -538,11 +541,11 @@
} else if isShift(x.Op) {
// The result type depends only on lhs operand.
// The rhs type was updated when checking the shift.
- check.updateExprType(x.X, typ, final)
+ check.updateExprType0(x, x.X, typ, final)
} else {
// The operand types match the result type.
- check.updateExprType(x.X, typ, final)
- check.updateExprType(x.Y, typ, final)
+ check.updateExprType0(x, x.X, typ, final)
+ check.updateExprType0(x, x.Y, typ, final)
}
default:
@@ -566,7 +569,11 @@
// We already know from the shift check that it is representable
// as an integer if it is a constant.
if !allInteger(typ) {
- check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ)
+ if compilerErrorMessages {
+ check.invalidOp(x, _InvalidShiftOperand, "%s (shift of type %s)", parent, typ)
+ } else {
+ check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ)
+ }
return
}
// Even if we have an integer, if the value is a constant we
@@ -721,44 +728,84 @@
return target, nil, 0
}
-func (check *Checker) comparison(x, y *operand, op token.Token) {
+// If switchCase is true, the operator op is ignored.
+func (check *Checker) comparison(x, y *operand, op token.Token, switchCase bool) {
+ if switchCase {
+ op = token.EQL
+ }
+
+ errOp := x // operand for which error is reported, if any
+ cause := "" // specific error cause, if any
+
// spec: "In any comparison, the first operand must be assignable
// to the type of the second operand, or vice versa."
- err := ""
- var code errorCode
- xok, _ := x.assignableTo(check, y.typ, nil)
- yok, _ := y.assignableTo(check, x.typ, nil)
- if xok || yok {
- defined := false
- switch op {
- case token.EQL, token.NEQ:
- // spec: "The equality operators == and != apply to operands that are comparable."
- defined = Comparable(x.typ) && Comparable(y.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ)
- case token.LSS, token.LEQ, token.GTR, token.GEQ:
- // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered."
- defined = allOrdered(x.typ) && allOrdered(y.typ)
- default:
- unreachable()
+ code := _MismatchedTypes
+ ok, _ := x.assignableTo(check, y.typ, nil)
+ if !ok {
+ ok, _ = y.assignableTo(check, x.typ, nil)
+ }
+ if !ok {
+ // Report the error on the 2nd operand since we only
+ // know after seeing the 2nd operand whether we have
+ // a type mismatch.
+ errOp = y
+ // For now, if we're not running the compiler, use the
+ // position of x to minimize changes to existing tests.
+ if !compilerErrorMessages {
+ errOp = x
}
- if !defined {
+ cause = check.sprintf("mismatched types %s and %s", x.typ, y.typ)
+ goto Error
+ }
+
+ // check if comparison is defined for operands
+ code = _UndefinedOp
+ switch op {
+ case token.EQL, token.NEQ:
+ // spec: "The equality operators == and != apply to operands that are comparable."
+ switch {
+ case x.isNil() || y.isNil():
+ // Comparison against nil requires that the other operand type has nil.
typ := x.typ
if x.isNil() {
typ = y.typ
}
- err = check.sprintf("operator %s not defined for %s", op, typ)
- code = _UndefinedOp
+ if !hasNil(typ) {
+ // This case should only be possible for "nil == nil".
+ // Report the error on the 2nd operand since we only
+ // know after seeing the 2nd operand whether we have
+ // an invalid comparison.
+ errOp = y
+ goto Error
+ }
+
+ case !Comparable(x.typ):
+ errOp = x
+ cause = check.incomparableCause(x.typ)
+ goto Error
+
+ case !Comparable(y.typ):
+ errOp = y
+ cause = check.incomparableCause(y.typ)
+ goto Error
}
- } else {
- err = check.sprintf("mismatched types %s and %s", x.typ, y.typ)
- code = _MismatchedTypes
+
+ case token.LSS, token.LEQ, token.GTR, token.GEQ:
+ // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered."
+ switch {
+ case !allOrdered(x.typ):
+ errOp = x
+ goto Error
+ case !allOrdered(y.typ):
+ errOp = y
+ goto Error
+ }
+
+ default:
+ unreachable()
}
- if err != "" {
- check.errorf(x, code, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
- x.mode = invalid
- return
- }
-
+ // comparison is ok
if x.mode == constant_ && y.mode == constant_ {
x.val = constant.MakeBool(constant.Compare(x.val, op, y.val))
// The operands are never materialized; no need to update
@@ -776,6 +823,73 @@
// spec: "Comparison operators compare two operands and yield
// an untyped boolean value."
x.typ = Typ[UntypedBool]
+ return
+
+Error:
+ // We have an offending operand errOp and possibly an error cause.
+ if cause == "" {
+ if isTypeParam(x.typ) || isTypeParam(y.typ) {
+ // TODO(gri) should report the specific type causing the problem, if any
+ if !isTypeParam(x.typ) {
+ errOp = y
+ }
+ cause = check.sprintf("type parameter %s is not comparable with %s", errOp.typ, op)
+ } else {
+ cause = check.sprintf("operator %s not defined on %s", op, check.kindString(errOp.typ)) // catch-all
+ }
+ }
+ if switchCase {
+ check.errorf(x, code, "invalid case %s in switch on %s (%s)", x.expr, y.expr, cause) // error position always at 1st operand
+ } else {
+ if compilerErrorMessages {
+ check.invalidOp(errOp, code, "%s %s %s (%s)", x.expr, op, y.expr, cause)
+ } else {
+ check.invalidOp(errOp, code, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, cause)
+ }
+ }
+ x.mode = invalid
+}
+
+// incomparableCause returns a more specific cause why typ is not comparable.
+// If there is no more specific cause, the result is "".
+func (check *Checker) incomparableCause(typ Type) string {
+ switch under(typ).(type) {
+ case *Slice, *Signature, *Map:
+ return check.kindString(typ) + " can only be compared to nil"
+ }
+ // see if we can extract a more specific error
+ var cause string
+ comparable(typ, true, nil, func(format string, args ...interface{}) {
+ cause = check.sprintf(format, args...)
+ })
+ return cause
+}
+
+// kindString returns the type kind as a string.
+func (check *Checker) kindString(typ Type) string {
+ switch under(typ).(type) {
+ case *Array:
+ return "array"
+ case *Slice:
+ return "slice"
+ case *Struct:
+ return "struct"
+ case *Pointer:
+ return "pointer"
+ case *Signature:
+ return "func"
+ case *Interface:
+ if isTypeParam(typ) {
+ return check.sprintf("type parameter %s", typ)
+ }
+ return "interface"
+ case *Map:
+ return "map"
+ case *Chan:
+ return "chan"
+ default:
+ return check.sprintf("%s", typ) // catch-all
+ }
}
// If e != nil, it must be the shift expression; it may be nil for non-constant shifts.
@@ -997,7 +1111,7 @@
}
if isComparison(op) {
- check.comparison(x, &y, op)
+ check.comparison(x, &y, op, false)
return
}
@@ -1224,11 +1338,11 @@
case hint != nil:
// no composite literal type present - use hint (element type of enclosing type)
typ = hint
- base = typ
- if !isTypeParam(typ) {
- base = under(typ)
+ base, _ = deref(coreType(typ)) // *T implies &T{}
+ if base == nil {
+ check.errorf(e, _InvalidLit, "invalid composite literal element type %s: no core type", typ)
+ goto Error
}
- base, _ = deref(base) // *T implies &T{}
default:
// TODO(gri) provide better error messages depending on context
@@ -1236,7 +1350,7 @@
goto Error
}
- switch utyp := structuralType(base).(type) {
+ switch utyp := coreType(base).(type) {
case *Struct:
// Prevent crash if the struct referred to is not yet set up.
// See analogous comment for *Array.
@@ -1419,7 +1533,7 @@
return kind
case *ast.SelectorExpr:
- check.selector(x, e)
+ check.selector(x, e, nil)
case *ast.IndexExpr, *ast.IndexListExpr:
ix := typeparams.UnpackIndexExpr(e)
@@ -1446,8 +1560,7 @@
check.invalidOp(x, _InvalidAssert, "cannot use type assertion on type parameter value %s", x)
goto Error
}
- xtyp, _ := under(x.typ).(*Interface)
- if xtyp == nil {
+ if _, ok := under(x.typ).(*Interface); !ok {
check.invalidOp(x, _InvalidAssert, "%s is not an interface", x)
goto Error
}
@@ -1462,7 +1575,7 @@
if T == Typ[Invalid] {
goto Error
}
- check.typeAssertion(x, x, xtyp, T)
+ check.typeAssertion(e, x, T, false)
x.mode = commaok
x.typ = T
@@ -1475,6 +1588,7 @@
case invalid:
goto Error
case typexpr:
+ check.validVarType(e.X, x.typ)
x.typ = &Pointer{base: x.typ}
default:
var base Type
@@ -1566,23 +1680,21 @@
return x
}
-// typeAssertion checks that x.(T) is legal; xtyp must be the type of x.
-func (check *Checker) typeAssertion(at positioner, x *operand, xtyp *Interface, T Type) {
- method, wrongType := check.assertableTo(xtyp, T)
+// typeAssertion checks x.(T). The type of x must be an interface.
+func (check *Checker) typeAssertion(e ast.Expr, x *operand, T Type, typeSwitch bool) {
+ method, alt := check.assertableTo(under(x.typ).(*Interface), T)
if method == nil {
+ return // success
+ }
+
+ cause := check.missingMethodReason(T, x.typ, method, alt)
+
+ if typeSwitch {
+ check.errorf(e, _ImpossibleAssert, "impossible type switch case: %s\n\t%s cannot have dynamic type %s %s", e, x, T, cause)
return
}
- var msg string
- if wrongType != nil {
- if Identical(method.typ, wrongType.typ) {
- msg = fmt.Sprintf("missing method %s (%s has pointer receiver)", method.name, method.name)
- } else {
- msg = fmt.Sprintf("wrong type for method %s (have %s, want %s)", method.name, wrongType.typ, method.typ)
- }
- } else {
- msg = "missing method " + method.name
- }
- check.errorf(at, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg)
+
+ check.errorf(e, _ImpossibleAssert, "impossible type assertion: %s\n\t%s does not implement %s %s", e, T, x.typ, cause)
}
// expr typechecks expression e and initializes x with the expression value.
diff --git a/src/go/types/exprstring.go b/src/go/types/exprstring.go
index aa4f403..544cd84 100644
--- a/src/go/types/exprstring.go
+++ b/src/go/types/exprstring.go
@@ -71,12 +71,7 @@
ix := typeparams.UnpackIndexExpr(x)
WriteExpr(buf, ix.X)
buf.WriteByte('[')
- for i, e := range ix.Indices {
- if i > 0 {
- buf.WriteString(", ")
- }
- WriteExpr(buf, e)
- }
+ writeExprList(buf, ix.Indices)
buf.WriteByte(']')
case *ast.SliceExpr:
diff --git a/src/go/types/index.go b/src/go/types/index.go
index db4732c..33075ed 100644
--- a/src/go/types/index.go
+++ b/src/go/types/index.go
@@ -183,6 +183,7 @@
}
if !valid {
+ // types2 uses the position of '[' for the error
check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x)
x.mode = invalid
return false
@@ -214,9 +215,9 @@
valid := false
length := int64(-1) // valid if >= 0
- switch u := structuralString(x.typ).(type) {
+ switch u := coreString(x.typ).(type) {
case nil:
- check.invalidOp(x, _NonSliceableOperand, "cannot slice %s: %s has no structural type", x, x.typ)
+ check.invalidOp(x, _NonSliceableOperand, "cannot slice %s: %s has no core type", x, x.typ)
x.mode = invalid
return
diff --git a/src/go/types/infer.go b/src/go/types/infer.go
index a5088f2..6bed55c 100644
--- a/src/go/types/infer.go
+++ b/src/go/types/infer.go
@@ -18,15 +18,17 @@
// function arguments args, if any. There must be at least one type parameter, no more type arguments
// than type parameters, and params and args must match in number (incl. zero).
// If successful, infer returns the complete list of type arguments, one for each type parameter.
-// Otherwise the result is nil and appropriate errors will be reported unless report is set to false.
+// Otherwise the result is nil and appropriate errors will be reported.
//
-// Inference proceeds in 3 steps:
+// Inference proceeds as follows:
//
-// 1) Start with given type arguments.
-// 2) Infer type arguments from typed function arguments.
-// 3) Infer type arguments from untyped function arguments.
+// Starting with given type arguments
+// 1) apply FTI (function type inference) with typed arguments,
+// 2) apply CTI (constraint type inference),
+// 3) apply FTI with untyped function arguments,
+// 4) apply CTI.
//
-// Constraint type inference is used after each step to expand the set of type arguments.
+// The process stops as soon as all type arguments are known or an error occurs.
func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (result []Type) {
if debug {
defer func() {
@@ -38,6 +40,13 @@
}()
}
+ if traceInference {
+ check.dump("-- inferA %s%s ➞ %s", tparams, params, targs)
+ defer func() {
+ check.dump("=> inferA %s ➞ %s", tparams, result)
+ }()
+ }
+
// There must be at least one type parameter, and no more type arguments than type parameters.
n := len(tparams)
assert(n > 0 && len(targs) <= n)
@@ -45,34 +54,127 @@
// Function parameters and arguments must match in number.
assert(params.Len() == len(args))
- // --- 0 ---
// If we already have all type arguments, we're done.
if len(targs) == n {
return targs
}
// len(targs) < n
- // --- 1 ---
- // Explicitly provided type arguments take precedence over any inferred types;
- // and types inferred via constraint type inference take precedence over types
- // inferred from function arguments.
- // If we have type arguments, see how far we get with constraint type inference.
- if len(targs) > 0 {
- var index int
- targs, index = check.inferB(posn, tparams, targs)
- if targs == nil || index < 0 {
- return targs
+ const enableTparamRenaming = true
+ if enableTparamRenaming {
+ // For the purpose of type inference we must differentiate type parameters
+ // occurring in explicit type or value function arguments from the type
+ // parameters we are solving for via unification, because they may be the
+ // same in self-recursive calls. For example:
+ //
+ // func f[P *Q, Q any](p P, q Q) {
+ // f(p)
+ // }
+ //
+ // In this example, the fact that the P used in the instantation f[P] has
+ // the same pointer identity as the P we are trying to solve for via
+ // unification is coincidental: there is nothing special about recursive
+ // calls that should cause them to conflate the identity of type arguments
+ // with type parameters. To put it another way: any such self-recursive
+ // call is equivalent to a mutually recursive call, which does not run into
+ // any problems of type parameter identity. For example, the following code
+ // is equivalent to the code above.
+ //
+ // func f[P interface{*Q}, Q any](p P, q Q) {
+ // f2(p)
+ // }
+ //
+ // func f2[P interface{*Q}, Q any](p P, q Q) {
+ // f(p)
+ // }
+ //
+ // We can turn the first example into the second example by renaming type
+ // parameters in the original signature to give them a new identity. As an
+ // optimization, we do this only for self-recursive calls.
+
+ // We can detect if we are in a self-recursive call by comparing the
+ // identity of the first type parameter in the current function with the
+ // first type parameter in tparams. This works because type parameters are
+ // unique to their type parameter list.
+ selfRecursive := check.sig != nil && check.sig.tparams.Len() > 0 && tparams[0] == check.sig.tparams.At(0)
+
+ if selfRecursive {
+ // In self-recursive inference, rename the type parameters with new type
+ // parameters that are the same but for their pointer identity.
+ tparams2 := make([]*TypeParam, len(tparams))
+ for i, tparam := range tparams {
+ tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil)
+ tparams2[i] = NewTypeParam(tname, nil)
+ tparams2[i].index = tparam.index // == i
+ }
+
+ renameMap := makeRenameMap(tparams, tparams2)
+ for i, tparam := range tparams {
+ tparams2[i].bound = check.subst(posn.Pos(), tparam.bound, renameMap, nil)
+ }
+
+ tparams = tparams2
+ params = check.subst(posn.Pos(), params, renameMap, nil).(*Tuple)
}
}
- // Continue with the type arguments we have now. Avoid matching generic
+ // If we have more than 2 arguments, we may have arguments with named and unnamed types.
+ // If that is the case, permutate params and args such that the arguments with named
+ // types are first in the list. This doesn't affect type inference if all types are taken
+ // as is. But when we have inexact unification enabled (as is the case for function type
+ // inference), when a named type is unified with an unnamed type, unification proceeds
+ // with the underlying type of the named type because otherwise unification would fail
+ // right away. This leads to an asymmetry in type inference: in cases where arguments of
+ // named and unnamed types are passed to parameters with identical type, different types
+ // (named vs underlying) may be inferred depending on the order of the arguments.
+ // By ensuring that named types are seen first, order dependence is avoided and unification
+ // succeeds where it can.
+ //
+ // This code is disabled for now pending decision whether we want to address cases like
+ // these and make the spec on type inference more complicated (see issue #43056).
+ const enableArgSorting = false
+ if m := len(args); m >= 2 && enableArgSorting {
+ // Determine indices of arguments with named and unnamed types.
+ var named, unnamed []int
+ for i, arg := range args {
+ if hasName(arg.typ) {
+ named = append(named, i)
+ } else {
+ unnamed = append(unnamed, i)
+ }
+ }
+
+ // If we have named and unnamed types, move the arguments with
+ // named types first. Update the parameter list accordingly.
+ // Make copies so as not to clobber the incoming slices.
+ if len(named) != 0 && len(unnamed) != 0 {
+ params2 := make([]*Var, m)
+ args2 := make([]*operand, m)
+ i := 0
+ for _, j := range named {
+ params2[i] = params.At(j)
+ args2[i] = args[j]
+ i++
+ }
+ for _, j := range unnamed {
+ params2[i] = params.At(j)
+ args2[i] = args[j]
+ i++
+ }
+ params = NewTuple(params2...)
+ args = args2
+ }
+ }
+
+ // --- 1 ---
+ // Continue with the type arguments we have. Avoid matching generic
// parameters that already have type arguments against function arguments:
// It may fail because matching uses type identity while parameter passing
// uses assignment rules. Instantiate the parameter list with the type
// arguments we have, and continue with that parameter list.
- // First, make sure we have a "full" list of type arguments, so of which
- // may be nil (unknown).
+ // First, make sure we have a "full" list of type arguments, some of which
+ // may be nil (unknown). Make a copy so as to not clobber the incoming slice.
if len(targs) < n {
targs2 := make([]Type, n)
copy(targs2, targs)
@@ -89,7 +191,6 @@
params = check.subst(token.NoPos, params, smap, nil).(*Tuple)
}
- // --- 2 ---
// Unify parameter and argument types for generic parameters with typed arguments
// and collect the indices of generic parameters with untyped arguments.
// Terminology: generic parameter = function parameter with a type-parameterized type
@@ -147,7 +248,7 @@
if arg.mode == invalid {
// An error was reported earlier. Ignore this targ
// and continue, we may still be able to infer all
- // targs resulting in fewer follon-on errors.
+ // targs resulting in fewer follow-on errors.
continue
}
if targ := arg.typ; isTyped(targ) {
@@ -158,7 +259,12 @@
errorf("type", par.typ, targ, arg)
return nil
}
- } else {
+ } else if _, ok := par.typ.(*TypeParam); ok {
+ // Since default types are all basic (i.e., non-composite) types, an
+ // untyped argument will never match a composite parameter type; the
+ // only parameter type it can possibly match against is a *TypeParam.
+ // Thus, for untyped arguments we only need to look at parameter types
+ // that are single type parameters.
indices = append(indices, i)
}
}
@@ -171,6 +277,7 @@
return targs
}
+ // --- 2 ---
// See how far we get with constraint type inference.
// Note that even if we don't have any type arguments, constraint type inference
// may produce results for constraints that explicitly specify a type.
@@ -184,20 +291,17 @@
// Some generic parameters with untyped arguments may have been given
// a type by now, we can ignore them.
for _, i := range indices {
- par := params.At(i)
- // Since untyped types are all basic (i.e., non-composite) types, an
- // untyped argument will never match a composite parameter type; the
- // only parameter type it can possibly match against is a *TypeParam.
- // Thus, only consider untyped arguments for generic parameters that
- // are not of composite types and which don't have a type inferred yet.
- if tpar, _ := par.typ.(*TypeParam); tpar != nil && targs[tpar.index] == nil {
+ tpar := params.At(i).typ.(*TypeParam) // is type parameter by construction of indices
+ // Only consider untyped arguments for which the corresponding type
+ // parameter doesn't have an inferred type yet.
+ if targs[tpar.index] == nil {
arg := args[i]
targ := Default(arg.typ)
// The default type for an untyped nil is untyped nil. We must not
// infer an untyped nil type as type parameter type. Ignore untyped
// nil by making sure all default argument types are typed.
- if isTyped(targ) && !u.unify(par.typ, targ) {
- errorf("default type", par.typ, targ, arg)
+ if isTyped(targ) && !u.unify(tpar, targ) {
+ errorf("default type", tpar, targ, arg)
return nil
}
}
@@ -209,6 +313,7 @@
return targs
}
+ // --- 4 ---
// Again, follow up with constraint type inference.
targs, index = check.inferB(posn, tparams, targs)
if targs == nil || index < 0 {
@@ -362,6 +467,13 @@
func (check *Checker) inferB(posn positioner, tparams []*TypeParam, targs []Type) (types []Type, index int) {
assert(len(tparams) >= len(targs) && len(targs) > 0)
+ if traceInference {
+ check.dump("-- inferB %s ➞ %s", tparams, targs)
+ defer func() {
+ check.dump("=> inferB %s ➞ %s", tparams, types)
+ }()
+ }
+
// Setup bidirectional unification between constraints
// and the corresponding type arguments (which may be nil!).
u := newUnifier(false)
@@ -375,27 +487,88 @@
}
}
- // If a constraint has a structural type, unify the corresponding type parameter with it.
- for _, tpar := range tparams {
- sbound := structuralType(tpar)
- if sbound != nil {
- // If the structural type is the underlying type of a single
- // defined type in the constraint, use that defined type instead.
- if named, _ := tpar.singleType().(*Named); named != nil {
- sbound = named
- }
- if !u.unify(tpar, sbound) {
- // TODO(gri) improve error message by providing the type arguments
- // which we know already
- check.errorf(posn, _InvalidTypeArg, "%s does not match %s", tpar, sbound)
- return nil, 0
+ // Repeatedly apply constraint type inference as long as
+ // there are still unknown type arguments and progress is
+ // being made.
+ //
+ // This is an O(n^2) algorithm where n is the number of
+ // type parameters: if there is progress (and iteration
+ // continues), at least one type argument is inferred
+ // per iteration and we have a doubly nested loop.
+ // In practice this is not a problem because the number
+ // of type parameters tends to be very small (< 5 or so).
+ // (It should be possible for unification to efficiently
+ // signal newly inferred type arguments; then the loops
+ // here could handle the respective type parameters only,
+ // but that will come at a cost of extra complexity which
+ // may not be worth it.)
+ for n := u.x.unknowns(); n > 0; {
+ nn := n
+
+ for i, tpar := range tparams {
+ // If there is a core term (i.e., a core type with tilde information)
+ // unify the type parameter with the core type.
+ if core, single := coreTerm(tpar); core != nil {
+ // A type parameter can be unified with its core type in two cases.
+ tx := u.x.at(i)
+ switch {
+ case tx != nil:
+ // The corresponding type argument tx is known.
+ // In this case, if the core type has a tilde, the type argument's underlying
+ // type must match the core type, otherwise the type argument and the core type
+ // must match.
+ // If tx is an external type parameter, don't consider its underlying type
+ // (which is an interface). Core type unification will attempt to unify against
+ // core.typ.
+ // Note also that even with inexact unification we cannot leave away the under
+ // call here because it's possible that both tx and core.typ are named types,
+ // with under(tx) being a (named) basic type matching core.typ. Such cases do
+ // not match with inexact unification.
+ if core.tilde && !isTypeParam(tx) {
+ tx = under(tx)
+ }
+ if !u.unify(tx, core.typ) {
+ // TODO(gri) improve error message by providing the type arguments
+ // which we know already
+ // Don't use term.String() as it always qualifies types, even if they
+ // are in the current package.
+ tilde := ""
+ if core.tilde {
+ tilde = "~"
+ }
+ check.errorf(posn, _InvalidTypeArg, "%s does not match %s%s", tpar, tilde, core.typ)
+ return nil, 0
+ }
+
+ case single && !core.tilde:
+ // The corresponding type argument tx is unknown and there's a single
+ // specific type and no tilde.
+ // In this case the type argument must be that single type; set it.
+ u.x.set(i, core.typ)
+
+ default:
+ // Unification is not possible and no progress was made.
+ continue
+ }
+
+ // The number of known type arguments may have changed.
+ nn = u.x.unknowns()
+ if nn == 0 {
+ break // all type arguments are known
+ }
}
}
+
+ assert(nn <= n)
+ if nn == n {
+ break // no progress
+ }
+ n = nn
}
// u.x.types() now contains the incoming type arguments plus any additional type
- // arguments which were inferred from structural types. The newly inferred non-
- // nil entries may still contain references to other type parameters.
+ // arguments which were inferred from core terms. The newly inferred non-nil
+ // entries may still contain references to other type parameters.
// For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int
// was given, unification produced the type list [int, []C, *A]. We eliminate the
// remaining type parameters by substituting the type parameters in this type list
@@ -463,8 +636,8 @@
}
// Once nothing changes anymore, we may still have type parameters left;
- // e.g., a structural constraint *P may match a type parameter Q but we
- // don't have any type arguments to fill in for *P or Q (issue #45548).
+ // e.g., a constraint with core type *P may match a type parameter Q but
+ // we don't have any type arguments to fill in for *P or Q (issue #45548).
// Don't let such inferences escape, instead nil them out.
for i, typ := range types {
if typ != nil && isParameterized(tparams, typ) {
@@ -484,6 +657,42 @@
return
}
+// If the type parameter has a single specific type S, coreTerm returns (S, true).
+// Otherwise, if tpar has a core type T, it returns a term corresponding to that
+// core type and false. In that case, if any term of tpar has a tilde, the core
+// term has a tilde. In all other cases coreTerm returns (nil, false).
+func coreTerm(tpar *TypeParam) (*term, bool) {
+ n := 0
+ var single *term // valid if n == 1
+ var tilde bool
+ tpar.is(func(t *term) bool {
+ if t == nil {
+ assert(n == 0)
+ return false // no terms
+ }
+ n++
+ single = t
+ if t.tilde {
+ tilde = true
+ }
+ return true
+ })
+ if n == 1 {
+ if debug {
+ assert(debug && under(single.typ) == coreType(tpar))
+ }
+ return single, true
+ }
+ if typ := coreType(tpar); typ != nil {
+ // A core type is always an underlying type.
+ // If any term of tpar has a tilde, we don't
+ // have a precise core type and we must return
+ // a tilde as well.
+ return &term{tilde, typ}, false
+ }
+ return nil, false
+}
+
type cycleFinder struct {
tparams []*TypeParam
types []Type
@@ -529,8 +738,6 @@
// in signatures where they are handled explicitly.
case *Signature:
- // There are no "method types" so we should never see a recv.
- assert(t.recv == nil)
if t.params != nil {
w.varList(t.params.vars)
}
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index e874897..a481746 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -15,10 +15,10 @@
// Instantiate instantiates the type orig with the given type arguments targs.
// orig must be a *Named or a *Signature type. If there is no error, the
-// resulting Type is a new, instantiated (not parameterized) type of the same
-// kind (either a *Named or a *Signature). Methods attached to a *Named type
-// are also instantiated, and associated with a new *Func that has the same
-// position as the original method, but nil function scope.
+// resulting Type is an instantiated type of the same kind (either a *Named or
+// a *Signature). Methods attached to a *Named type are also instantiated, and
+// associated with a new *Func that has the same position as the original
+// method, but nil function scope.
//
// If ctxt is non-nil, it may be used to de-duplicate the instance against
// previous instances with the same identity. As a special case, generic
@@ -78,7 +78,7 @@
tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
named := check.newNamed(tname, orig, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved
named.targs = newTypeList(targs)
- named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) {
+ named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, *methodList) {
return expandNamed(ctxt, n, pos)
}
res = named
@@ -133,22 +133,16 @@
}
func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type) (int, error) {
- // TODO(rfindley): it would be great if users could pass in a qualifier here,
- // rather than falling back to verbose qualification. Maybe this can be part
- // of the shared context.
- var qf Qualifier
- if check != nil {
- qf = check.qualifier
- }
-
smap := makeSubstMap(tparams, targs)
for i, tpar := range tparams {
+ // Ensure that we have a (possibly implicit) interface as type bound (issue #51048).
+ tpar.iface()
// The type parameter bound is parameterized with the same type parameters
// as the instantiated type; before we can use it for bounds checking we
// need to instantiate it with the type arguments with which we instantiated
// the parameterized type.
bound := check.subst(pos, tpar.bound, smap, nil)
- if err := check.implements(targs[i], bound, qf); err != nil {
+ if err := check.implements(targs[i], bound); err != nil {
return i, err
}
}
@@ -156,21 +150,31 @@
}
// implements checks if V implements T and reports an error if it doesn't.
-// If a qualifier is provided, it is used in error formatting.
-func (check *Checker) implements(V, T Type, qf Qualifier) error {
+// The receiver may be nil if implements is called through an exported
+// API call such as AssignableTo.
+func (check *Checker) implements(V, T Type) error {
Vu := under(V)
Tu := under(T)
if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
- return nil
+ return nil // avoid follow-on errors
+ }
+ if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] {
+ return nil // avoid follow-on errors (see issue #49541 for an example)
}
errorf := func(format string, args ...any) error {
- return errors.New(sprintf(nil, qf, false, format, args...))
+ return errors.New(check.sprintf(format, args...))
}
Ti, _ := Tu.(*Interface)
if Ti == nil {
- return errorf("%s is not an interface", T)
+ var cause string
+ if isInterfacePtr(Tu) {
+ cause = check.sprintf("type %s is pointer to interface, not interface", T)
+ } else {
+ cause = check.sprintf("%s is not an interface", T)
+ }
+ return errorf("%s does not implement %s (%s)", V, T, cause)
}
// Every type satisfies the empty interface.
@@ -192,39 +196,22 @@
return errorf("cannot implement %s (empty type set)", T)
}
- // If T is comparable, V must be comparable.
- // TODO(gri) the error messages could be better, here
- if Ti.IsComparable() && !Comparable(V) {
- if Vi != nil && Vi.Empty() {
- return errorf("empty interface %s does not implement %s", V, T)
- }
- return errorf("%s does not implement comparable", V)
+ // V must implement T's methods, if any.
+ if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
+ return errorf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong))
}
- // V must implement T (methods)
- // - check only if we have methods
- if Ti.NumMethods() > 0 {
- if m, wrong := check.missingMethod(V, Ti, true); m != nil {
- // TODO(gri) needs to print updated name to avoid major confusion in error message!
- // (print warning for now)
- // Old warning:
- // check.softErrorf(pos, "%s does not implement %s (warning: name not updated) = %s (missing method %s)", V, T, Ti, m)
- if wrong != nil {
- // TODO(gri) This can still report uninstantiated types which makes the error message
- // more difficult to read then necessary.
- // TODO(rFindley) should this use parentheses rather than ':' for qualification?
- return errorf("%s does not implement %s: wrong method signature\n\tgot %s\n\twant %s",
- V, T, wrong, m,
- )
- }
- return errorf("%s does not implement %s (missing method %s)", V, T, m.name)
- }
+ // If T is comparable, V must be comparable.
+ // Remember as a pending error and report only if we don't have a more specific error.
+ var pending error
+ if Ti.IsComparable() && !comparable(V, false, nil, nil) {
+ pending = errorf("%s does not implement comparable", V)
}
// V must also be in the set of types of T, if any.
// Constraints with empty type sets were already excluded above.
if !Ti.typeSet().hasTerms() {
- return nil // nothing to do
+ return pending // nothing to do
}
// If V is itself an interface, each of its possible types must be in the set
@@ -235,7 +222,7 @@
// TODO(gri) report which type is missing
return errorf("%s does not implement %s", V, T)
}
- return nil
+ return pending
}
// Otherwise, V's type must be included in the iface type set.
@@ -263,5 +250,5 @@
}
}
- return nil
+ return pending
}
diff --git a/src/go/types/interface.go b/src/go/types/interface.go
index 1ff9015..3db3580 100644
--- a/src/go/types/interface.go
+++ b/src/go/types/interface.go
@@ -56,7 +56,7 @@
}
// set method receivers if necessary
- typ := new(Interface)
+ typ := (*Checker)(nil).newInterface()
for _, m := range methods {
if sig := m.typ.(*Signature); sig.recv == nil {
sig.recv = NewVar(m.pos, m.pkg, "", typ)
@@ -73,6 +73,15 @@
return typ
}
+// check may be nil
+func (check *Checker) newInterface() *Interface {
+ typ := &Interface{check: check}
+ if check != nil {
+ check.needsCleanup(typ)
+ }
+ return typ
+}
+
// MarkImplicit marks the interface t as implicit, meaning this interface
// corresponds to a constraint literal such as ~T or A|B without explicit
// interface embedding. MarkImplicit should be called before any concurrent use
@@ -111,7 +120,7 @@
func (t *Interface) Empty() bool { return t.typeSet().IsAll() }
// IsComparable reports whether each type in interface t's type set is comparable.
-func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() }
+func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable(nil) }
// IsMethodSet reports whether the interface t is fully described by its method
// set.
@@ -141,6 +150,11 @@
// ----------------------------------------------------------------------------
// Implementation
+func (t *Interface) cleanup() {
+ t.check = nil
+ t.embedPos = nil
+}
+
func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
addEmbedded := func(pos token.Pos, typ Type) {
ityp.embeddeds = append(ityp.embeddeds, typ)
@@ -210,16 +224,10 @@
sortMethods(ityp.methods)
// (don't sort embeddeds: they must correspond to *embedPos entries)
- // Compute type set with a non-nil *Checker as soon as possible
- // to report any errors. Subsequent uses of type sets will use
- // this computed type set and won't need to pass in a *Checker.
- //
- // Pin the checker to the interface type in the interim, in case the type set
- // must be used before delayed funcs are processed (see issue #48234).
- // TODO(rfindley): clean up use of *Checker with computeInterfaceTypeSet
- ityp.check = check
+ // Compute type set as soon as possible to report any errors.
+ // Subsequent uses of type sets will use this computed type
+ // set and won't need to pass in a *Checker.
check.later(func() {
computeInterfaceTypeSet(check, iface.Pos(), ityp)
- ityp.check = nil
}).describef(iface, "compute type set for %s", ityp)
}
diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go
index 51995af..bd98f48 100644
--- a/src/go/types/issues_test.go
+++ b/src/go/types/issues_test.go
@@ -638,3 +638,29 @@
testFiles(t, nil, []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp)
testFiles(t, nil, []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp)
}
+
+func TestIssue50646(t *testing.T) {
+ anyType := Universe.Lookup("any").Type()
+ comparableType := Universe.Lookup("comparable").Type()
+
+ if !Comparable(anyType) {
+ t.Errorf("any is not a comparable type")
+ }
+ if !Comparable(comparableType) {
+ t.Errorf("comparable is not a comparable type")
+ }
+
+ if Implements(anyType, comparableType.Underlying().(*Interface)) {
+ t.Errorf("any implements comparable")
+ }
+ if !Implements(comparableType, anyType.(*Interface)) {
+ t.Errorf("comparable does not implement any")
+ }
+
+ if AssignableTo(anyType, comparableType) {
+ t.Errorf("any assignable to comparable")
+ }
+ if !AssignableTo(comparableType, anyType) {
+ t.Errorf("comparable not assignable to any")
+ }
+}
diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go
index c787601..335fada 100644
--- a/src/go/types/lookup.go
+++ b/src/go/types/lookup.go
@@ -7,7 +7,7 @@
package types
import (
- "fmt"
+ "bytes"
"strings"
)
@@ -20,7 +20,7 @@
// in T and returns the corresponding *Var or *Func, an index sequence, and a
// bool indicating if there were any pointer indirections on the path to the
// field or method. If addressable is set, T is the type of an addressable
-// variable (only matters for method lookups).
+// variable (only matters for method lookups). T must not be nil.
//
// The last index entry is the field or method index in the (possibly embedded)
// type where the entry was found, either:
@@ -43,7 +43,11 @@
// the method's formal receiver base type, nor was the receiver addressable.
//
func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
- // Methods cannot be associated to a named pointer type
+ if T == nil {
+ panic("LookupFieldOrMethod on nil type")
+ }
+
+ // Methods cannot be associated to a named pointer type.
// (spec: "The type denoted by T is called the receiver base type;
// it must not be a pointer or interface type and it must be declared
// in the same package as the method.").
@@ -52,7 +56,7 @@
// not have found it for T (see also issue 8590).
if t, _ := T.(*Named); t != nil {
if p, _ := t.Underlying().(*Pointer); p != nil {
- obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name)
+ obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name, false)
if _, ok := obj.(*Func); ok {
return nil, nil, false
}
@@ -60,7 +64,22 @@
}
}
- return lookupFieldOrMethod(T, addressable, pkg, name)
+ obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false)
+
+ // If we didn't find anything and if we have a type parameter with a core type,
+ // see if there is a matching field (but not a method, those need to be declared
+ // explicitly in the constraint). If the constraint is a named pointer type (see
+ // above), we are ok here because only fields are accepted as results.
+ const enableTParamFieldLookup = false // see issue #51576
+ if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
+ if t := coreType(T); t != nil {
+ obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
+ if _, ok := obj.(*Var); !ok {
+ obj, index, indirect = nil, nil, false // accept fields (variables) only
+ }
+ }
+ }
+ return
}
// TODO(gri) The named type consolidation and seen maps below must be
@@ -69,9 +88,11 @@
// indirectly via different packages.)
// lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
+// If foldCase is true, the lookup for methods will include looking for any method
+// which case-folds to the same as 'name' (used for giving helpful error messages).
//
// The resulting object may not be fully type-checked.
-func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, foldCase bool) (obj Object, index []int, indirect bool) {
// WARNING: The code in this function is extremely subtle - do not modify casually!
if name == "_" {
@@ -80,7 +101,7 @@
typ, isPtr := deref(T)
- // *typ where typ is an interface has no methods.
+ // *typ where typ is an interface (incl. a type parameter) has no methods.
if isPtr {
if _, ok := under(typ).(*Interface); ok {
return
@@ -104,7 +125,6 @@
var next []embeddedType // embedded types found at current depth
// look for (pkg, name) in all types at current depth
- var tpar *TypeParam // set if obj receiver is a type parameter
for _, e := range current {
typ := e.typ
@@ -126,7 +146,7 @@
// look for a matching attached method
named.resolve(nil)
- if i, m := lookupMethod(named.methods, pkg, name); m != nil {
+ if i, m := named.lookupMethod(pkg, name, foldCase); m != nil {
// potential match
// caution: method may not have a proper signature yet
index = concat(e.index, i)
@@ -137,13 +157,9 @@
indirect = e.indirect
continue // we can't have a matching field or interface method
}
-
- // continue with underlying type
- typ = named.under()
}
- tpar = nil
- switch t := typ.(type) {
+ switch t := under(typ).(type) {
case *Struct:
// look for a matching field and collect embedded types
for i, f := range t.fields {
@@ -176,8 +192,8 @@
}
case *Interface:
- // look for a matching method
- if i, m := t.typeSet().LookupMethod(pkg, name); m != nil {
+ // look for a matching method (interface may be a type parameter)
+ if i, m := t.typeSet().LookupMethod(pkg, name, foldCase); m != nil {
assert(m.typ != nil)
index = concat(e.index, i)
if obj != nil || e.multiples {
@@ -186,18 +202,6 @@
obj = m
indirect = e.indirect
}
-
- case *TypeParam:
- if i, m := t.iface().typeSet().LookupMethod(pkg, name); m != nil {
- assert(m.typ != nil)
- index = concat(e.index, i)
- if obj != nil || e.multiples {
- return nil, index, false // collision
- }
- tpar = t
- obj = m
- indirect = e.indirect
- }
}
}
@@ -209,8 +213,7 @@
// is shorthand for (&x).m()".
if f, _ := obj.(*Func); f != nil {
// determine if method has a pointer receiver
- hasPtrRecv := tpar == nil && f.hasPtrRecv()
- if hasPtrRecv && !indirect && !addressable {
+ if f.hasPtrRecv() && !indirect && !addressable {
return nil, nil, true // pointer/addressable receiver required
}
}
@@ -280,55 +283,38 @@
// x is of interface type V).
//
func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) {
- m, typ := (*Checker)(nil).missingMethod(V, T, static)
- return m, typ != nil
+ m, alt := (*Checker)(nil).missingMethod(V, T, static)
+ // Only report a wrong type if the alternative method has the same name as m.
+ return m, alt != nil && alt.name == m.name // alt != nil implies m != nil
}
-// missingMethod is like MissingMethod but accepts a *Checker as
-// receiver and an addressable flag.
-// The receiver may be nil if missingMethod is invoked through
-// an exported API call (such as MissingMethod), i.e., when all
-// methods have been type-checked.
-// If the type has the correctly named method, but with the wrong
-// signature, the existing method is returned as well.
-// To improve error messages, also report the wrong signature
-// when the method exists on *V instead of V.
-func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, wrongType *Func) {
- // fast path for common case
- if T.Empty() {
+// missingMethod is like MissingMethod but accepts a *Checker as receiver.
+// The receiver may be nil if missingMethod is invoked through an exported
+// API call (such as MissingMethod), i.e., when all methods have been type-
+// checked.
+//
+// If a method is missing on T but is found on *T, or if a method is found
+// on T when looked up with case-folding, this alternative method is returned
+// as the second result.
+func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
+ if T.NumMethods() == 0 {
return
}
- if ityp, _ := under(V).(*Interface); ityp != nil {
- // TODO(gri) the methods are sorted - could do this more efficiently
+ // V is an interface
+ if u, _ := under(V).(*Interface); u != nil {
+ tset := u.typeSet()
for _, m := range T.typeSet().methods {
- _, f := ityp.typeSet().LookupMethod(m.pkg, m.name)
+ _, f := tset.LookupMethod(m.pkg, m.name, false)
if f == nil {
if !static {
continue
}
- return m, f
+ return m, nil
}
- // both methods must have the same number of type parameters
- ftyp := f.typ.(*Signature)
- mtyp := m.typ.(*Signature)
- if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() {
- return m, f
- }
- if ftyp.TypeParams().Len() > 0 {
- panic("method with type parameters")
- }
-
- // If the methods have type parameters we don't care whether they
- // are the same or not, as long as they match up. Use unification
- // to see if they can be made to match.
- // TODO(gri) is this always correct? what about type bounds?
- // (Alternative is to rename/subst type parameters and compare.)
- u := newUnifier(true)
- u.x.init(ftyp.TypeParams().list())
- if !u.unify(ftyp, mtyp) {
+ if !Identical(f.typ, m.typ) {
return m, f
}
}
@@ -336,26 +322,22 @@
return
}
- // A concrete type implements T if it implements all methods of T.
+ // V is not an interface
for _, m := range T.typeSet().methods {
- // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)?
- obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name)
+ // TODO(gri) should this be calling LookupFieldOrMethod instead (and why not)?
+ obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name, false)
- // Check if *V implements this method of T.
- if obj == nil {
- ptr := NewPointer(V)
- obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name)
-
- if obj != nil {
- // methods may not have a fully set up signature yet
- if check != nil {
- check.objDecl(obj, nil)
- }
- return m, obj.(*Func)
+ // check if m is on *V, or on V with case-folding
+ found := obj != nil
+ if !found {
+ // TODO(gri) Instead of NewPointer(V) below, can we just set the "addressable" argument?
+ obj, _, _ = lookupFieldOrMethod(NewPointer(V), false, m.pkg, m.name, false)
+ if obj == nil {
+ obj, _, _ = lookupFieldOrMethod(V, false, m.pkg, m.name, true /* fold case */)
}
}
- // we must have a method (not a field of matching function type)
+ // we must have a method (not a struct field)
f, _ := obj.(*Func)
if f == nil {
return m, nil
@@ -366,24 +348,7 @@
check.objDecl(f, nil)
}
- // both methods must have the same number of type parameters
- ftyp := f.typ.(*Signature)
- mtyp := m.typ.(*Signature)
- if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() {
- return m, f
- }
- if ftyp.TypeParams().Len() > 0 {
- panic("method with type parameters")
- }
-
- // If the methods have type parameters we don't care whether they
- // are the same or not, as long as they match up. Use unification
- // to see if they can be made to match.
- // TODO(gri) is this always correct? what about type bounds?
- // (Alternative is to rename/subst type parameters and compare.)
- u := newUnifier(true)
- u.x.init(ftyp.RecvTypeParams().list())
- if !u.unify(ftyp, mtyp) {
+ if !found || !Identical(f.typ, m.typ) {
return m, f
}
}
@@ -393,55 +358,66 @@
// missingMethodReason returns a string giving the detailed reason for a missing method m,
// where m is missing from V, but required by T. It puts the reason in parentheses,
-// and may include more have/want info after that. If non-nil, wrongType is a relevant
+// and may include more have/want info after that. If non-nil, alt is a relevant
// method that matches in some way. It may have the correct name, but wrong type, or
-// it may have a pointer receiver.
-func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string {
- var r string
+// it may have a pointer receiver, or it may have the correct name except wrong case.
+// check may be nil.
+func (check *Checker) missingMethodReason(V, T Type, m, alt *Func) string {
var mname string
- if compilerErrorMessages {
+ if check != nil && compilerErrorMessages {
mname = m.Name() + " method"
} else {
mname = "method " + m.Name()
}
- if wrongType != nil {
- if Identical(m.typ, wrongType.typ) {
- if m.Name() == wrongType.Name() {
- r = fmt.Sprintf("(%s has pointer receiver)", mname)
- } else {
- r = fmt.Sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
- mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
- }
- } else {
- if compilerErrorMessages {
- r = fmt.Sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
- mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
- } else {
- r = fmt.Sprintf("(wrong type for %s: have %s, want %s)",
- mname, wrongType.typ, m.typ)
- }
+
+ if alt != nil {
+ if m.Name() != alt.Name() {
+ return check.sprintf("(missing %s)\n\t\thave %s\n\t\twant %s",
+ mname, check.funcString(alt), check.funcString(m))
}
- // This is a hack to print the function type without the leading
- // 'func' keyword in the have/want printouts. We could change to have
- // an extra formatting option for types2.Type that doesn't print out
- // 'func'.
- r = strings.Replace(r, "^^func", "", -1)
- } else if IsInterface(T) && !isTypeParam(T) {
- if isInterfacePtr(V) {
- r = fmt.Sprintf("(%s is pointer to interface, not interface)", V)
+
+ if Identical(m.typ, alt.typ) {
+ return check.sprintf("(%s has pointer receiver)", mname)
}
- } else if isInterfacePtr(T) && !isTypeParam(T) {
- r = fmt.Sprintf("(%s is pointer to interface, not interface)", T)
+
+ return check.sprintf("(wrong type for %s)\n\t\thave %s\n\t\twant %s",
+ mname, check.funcString(alt), check.funcString(m))
}
- if r == "" {
- r = fmt.Sprintf("(missing %s)", mname)
+
+ if isInterfacePtr(V) {
+ return "(" + check.interfacePtrError(V) + ")"
}
- return r
+
+ if isInterfacePtr(T) {
+ return "(" + check.interfacePtrError(T) + ")"
+ }
+
+ return check.sprintf("(missing %s)", mname)
}
func isInterfacePtr(T Type) bool {
p, _ := under(T).(*Pointer)
- return p != nil && IsInterface(p.base) && !isTypeParam(T)
+ return p != nil && IsInterface(p.base)
+}
+
+// check may be nil.
+func (check *Checker) interfacePtrError(T Type) string {
+ assert(isInterfacePtr(T))
+ if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
+ return check.sprintf("type %s is pointer to type parameter, not type parameter", T)
+ }
+ return check.sprintf("type %s is pointer to interface, not interface", T)
+}
+
+// check may be nil.
+func (check *Checker) funcString(f *Func) string {
+ buf := bytes.NewBufferString(f.name)
+ var qf Qualifier
+ if check != nil {
+ qf = check.qualifier
+ }
+ WriteSignature(buf, f.typ.(*Signature), qf)
+ return buf.String()
}
// assertableTo reports whether a value of type V can be asserted to have type T.
@@ -449,18 +425,31 @@
// method required by V and whether it is missing or just has the wrong type.
// The receiver may be nil if assertableTo is invoked through an exported API call
// (such as AssertableTo), i.e., when all methods have been type-checked.
-// If the global constant forceStrict is set, assertions that are known to fail
-// are not permitted.
+// TODO(gri) replace calls to this function with calls to newAssertableTo.
func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Func) {
// no static check is required if T is an interface
// spec: "If T is an interface type, x.(T) asserts that the
// dynamic type of x implements the interface T."
- if IsInterface(T) && !forceStrict {
+ if IsInterface(T) {
return
}
+ // TODO(gri) fix this for generalized interfaces
return check.missingMethod(T, V, false)
}
+// newAssertableTo reports whether a value of type V can be asserted to have type T.
+// It also implements behavior for interfaces that currently are only permitted
+// in constraint position (we have not yet defined that behavior in the spec).
+func (check *Checker) newAssertableTo(V *Interface, T Type) error {
+ // no static check is required if T is an interface
+ // spec: "If T is an interface type, x.(T) asserts that the
+ // dynamic type of x implements the interface T."
+ if IsInterface(T) {
+ return nil
+ }
+ return check.implements(T, V)
+}
+
// deref dereferences typ if it is a *Pointer and returns its base and true.
// Otherwise it returns (typ, false).
func deref(typ Type) (Type, bool) {
@@ -509,10 +498,11 @@
}
// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
-func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
+// If foldCase is true, method names are considered equal if they are equal with case folding.
+func lookupMethod(methods []*Func, pkg *Package, name string, foldCase bool) (int, *Func) {
if name != "_" {
for i, m := range methods {
- if m.sameId(pkg, name) {
+ if (m.name == name || foldCase && strings.EqualFold(m.name, name)) && m.sameId(pkg, m.name) {
return i, m
}
}
diff --git a/src/go/types/methodlist.go b/src/go/types/methodlist.go
new file mode 100644
index 0000000..afe9190
--- /dev/null
+++ b/src/go/types/methodlist.go
@@ -0,0 +1,79 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import "sync"
+
+// methodList holds a list of methods that may be lazily resolved by a provided
+// resolution method.
+type methodList struct {
+ methods []*Func
+
+ // guards synchronizes the instantiation of lazy methods. For lazy method
+ // lists, guards is non-nil and of the length passed to newLazyMethodList.
+ // For non-lazy method lists, guards is nil.
+ guards *[]sync.Once
+}
+
+// newMethodList creates a non-lazy method list holding the given methods.
+func newMethodList(methods []*Func) *methodList {
+ return &methodList{methods: methods}
+}
+
+// newLazyMethodList creates a lazy method list of the given length. Methods
+// may be resolved lazily for a given index by providing a resolver function.
+func newLazyMethodList(length int) *methodList {
+ guards := make([]sync.Once, length)
+ return &methodList{
+ methods: make([]*Func, length),
+ guards: &guards,
+ }
+}
+
+// isLazy reports whether the receiver is a lazy method list.
+func (l *methodList) isLazy() bool {
+ return l != nil && l.guards != nil
+}
+
+// Add appends a method to the method list if not not already present. Add
+// panics if the receiver is lazy.
+func (l *methodList) Add(m *Func) {
+ assert(!l.isLazy())
+ if i, _ := lookupMethod(l.methods, m.pkg, m.name, false); i < 0 {
+ l.methods = append(l.methods, m)
+ }
+}
+
+// Lookup looks up the method identified by pkg and name in the receiver.
+// Lookup panics if the receiver is lazy. If foldCase is true, method names
+// are considered equal if they are equal with case folding.
+func (l *methodList) Lookup(pkg *Package, name string, foldCase bool) (int, *Func) {
+ assert(!l.isLazy())
+ if l == nil {
+ return -1, nil
+ }
+ return lookupMethod(l.methods, pkg, name, foldCase)
+}
+
+// Len returns the length of the method list.
+func (l *methodList) Len() int {
+ if l == nil {
+ return 0
+ }
+ return len(l.methods)
+}
+
+// At returns the i'th method of the method list. At panics if i is out of
+// bounds, or if the receiver is lazy and resolve is nil.
+func (l *methodList) At(i int, resolve func() *Func) *Func {
+ if !l.isLazy() {
+ return l.methods[i]
+ }
+ assert(resolve != nil)
+ (*l.guards)[i].Do(func() {
+ l.methods[i] = resolve()
+ })
+ return l.methods[i]
+}
diff --git a/src/go/types/methodlist_test.go b/src/go/types/methodlist_test.go
new file mode 100644
index 0000000..e628bce
--- /dev/null
+++ b/src/go/types/methodlist_test.go
@@ -0,0 +1,41 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+ "go/token"
+ "testing"
+)
+
+func TestLazyMethodList(t *testing.T) {
+ l := newLazyMethodList(2)
+
+ if got := l.Len(); got != 2 {
+ t.Fatalf("Len() = %d, want 2", got)
+ }
+
+ f0 := NewFunc(token.NoPos, nil, "f0", nil)
+ f1 := NewFunc(token.NoPos, nil, "f1", nil)
+
+ // Verify that methodList.At is idempotent, by calling it repeatedly with a
+ // resolve func that returns different pointer values (f0 or f1).
+ steps := []struct {
+ index int
+ resolve *Func // the *Func returned by the resolver
+ want *Func // the actual *Func returned by methodList.At
+ }{
+ {0, f0, f0},
+ {0, f1, f0},
+ {1, f1, f1},
+ {1, f0, f1},
+ }
+
+ for i, step := range steps {
+ got := l.At(step.index, func() *Func { return step.resolve })
+ if got != step.want {
+ t.Errorf("step %d: At(%d, ...) = %s, want %s", i, step.index, got.Name(), step.want.Name())
+ }
+ }
+}
diff --git a/src/go/types/methodset.go b/src/go/types/methodset.go
index e17be7c..c1d1e93 100644
--- a/src/go/types/methodset.go
+++ b/src/go/types/methodset.go
@@ -125,17 +125,12 @@
}
seen[named] = true
- mset = mset.add(named.methods, e.index, e.indirect, e.multiples)
-
- // continue with underlying type, but only if it's not a type parameter
- // TODO(rFindley): should this use named.under()? Can there be a difference?
- typ = named.underlying
- if _, ok := typ.(*TypeParam); ok {
- continue
+ for i := 0; i < named.NumMethods(); i++ {
+ mset = mset.addOne(named.Method(i), concat(e.index, i), e.indirect, e.multiples)
}
}
- switch t := typ.(type) {
+ switch t := under(typ).(type) {
case *Struct:
for i, f := range t.fields {
if fset == nil {
@@ -158,9 +153,6 @@
case *Interface:
mset = mset.add(t.typeSet().methods, e.index, true, e.multiples)
-
- case *TypeParam:
- mset = mset.add(t.iface().typeSet().methods, e.index, true, e.multiples)
}
}
@@ -224,23 +216,28 @@
if len(list) == 0 {
return s
}
+ for i, f := range list {
+ s = s.addOne(f, concat(index, i), indirect, multiples)
+ }
+ return s
+}
+
+func (s methodSet) addOne(f *Func, index []int, indirect bool, multiples bool) methodSet {
if s == nil {
s = make(methodSet)
}
- for i, f := range list {
- key := f.Id()
- // if f is not in the set, add it
- if !multiples {
- // TODO(gri) A found method may not be added because it's not in the method set
- // (!indirect && f.hasPtrRecv()). A 2nd method on the same level may be in the method
- // set and may not collide with the first one, thus leading to a false positive.
- // Is that possible? Investigate.
- if _, found := s[key]; !found && (indirect || !f.hasPtrRecv()) {
- s[key] = &Selection{MethodVal, nil, f, concat(index, i), indirect}
- continue
- }
+ key := f.Id()
+ // if f is not in the set, add it
+ if !multiples {
+ // TODO(gri) A found method may not be added because it's not in the method set
+ // (!indirect && f.hasPtrRecv()). A 2nd method on the same level may be in the method
+ // set and may not collide with the first one, thus leading to a false positive.
+ // Is that possible? Investigate.
+ if _, found := s[key]; !found && (indirect || !f.hasPtrRecv()) {
+ s[key] = &Selection{MethodVal, nil, f, index, indirect}
+ return s
}
- s[key] = nil // collision
}
+ s[key] = nil // collision
return s
}
diff --git a/src/go/types/named.go b/src/go/types/named.go
index 82a053d..876f7e8 100644
--- a/src/go/types/named.go
+++ b/src/go/types/named.go
@@ -12,17 +12,22 @@
// A Named represents a named (defined) type.
type Named struct {
check *Checker
- info typeInfo // for cycle detection
obj *TypeName // corresponding declared object for declared types; placeholder for instantiated types
orig *Named // original, uninstantiated type
fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting)
underlying Type // possibly a *Named during setup; never a *Named once set up completely
tparams *TypeParamList // type parameters, or nil
targs *TypeList // type arguments (after instantiation), or nil
- methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily
+
+ // methods declared for this type (not the method set of this type).
+ // Signatures are type-checked lazily.
+ // For non-instantiated types, this is a fully populated list of methods. For
+ // instantiated types, this is a 'lazy' list, and methods are instantiated
+ // when they are first accessed.
+ methods *methodList
// resolver may be provided to lazily resolve type parameters, underlying, and methods.
- resolver func(*Context, *Named) (tparams *TypeParamList, underlying Type, methods []*Func)
+ resolver func(*Context, *Named) (tparams *TypeParamList, underlying Type, methods *methodList)
once sync.Once // ensures that tparams, underlying, and methods are resolved before accessing
}
@@ -33,7 +38,7 @@
if _, ok := underlying.(*Named); ok {
panic("underlying type must not be *Named")
}
- return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods)
+ return (*Checker)(nil).newNamed(obj, nil, underlying, nil, newMethodList(methods))
}
func (t *Named) resolve(ctxt *Context) *Named {
@@ -57,7 +62,7 @@
}
// newNamed is like NewNamed but with a *Checker receiver and additional orig argument.
-func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParamList, methods []*Func) *Named {
+func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParamList, methods *methodList) *Named {
typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods}
if typ.orig == nil {
typ.orig = typ
@@ -67,18 +72,38 @@
}
// Ensure that typ is always expanded and sanity-checked.
if check != nil {
- check.defTypes = append(check.defTypes, typ)
+ check.needsCleanup(typ)
}
return typ
}
+func (t *Named) cleanup() {
+ // Ensure that every defined type created in the course of type-checking has
+ // either non-*Named underlying, or is unresolved.
+ //
+ // This guarantees that we don't leak any types whose underlying is *Named,
+ // because any unresolved instances will lazily compute their underlying by
+ // substituting in the underlying of their origin. The origin must have
+ // either been imported or type-checked and expanded here, and in either case
+ // its underlying will be fully expanded.
+ switch t.underlying.(type) {
+ case nil:
+ if t.resolver == nil {
+ panic("nil underlying")
+ }
+ case *Named:
+ t.under() // t.under may add entries to check.cleaners
+ }
+ t.check = nil
+}
+
// Obj returns the type name for the declaration defining the named type t. For
-// instantiated types, this is the type name of the base type.
+// instantiated types, this is same as the type name of the origin type.
func (t *Named) Obj() *TypeName {
return t.orig.obj // for non-instances this is the same as t.obj
}
-// Origin returns the parameterized type from which the named type t is
+// Origin returns the generic type from which the named type t is
// instantiated. If t is not an instantiated type, the result is t.
func (t *Named) Origin() *Named { return t.orig }
@@ -86,23 +111,95 @@
// between parameterized instantiated and non-instantiated types.
// TypeParams returns the type parameters of the named type t, or nil.
-// The result is non-nil for an (originally) parameterized type even if it is instantiated.
+// The result is non-nil for an (originally) generic type even if it is instantiated.
func (t *Named) TypeParams() *TypeParamList { return t.resolve(nil).tparams }
// SetTypeParams sets the type parameters of the named type t.
-func (t *Named) SetTypeParams(tparams []*TypeParam) { t.resolve(nil).tparams = bindTParams(tparams) }
+// t must not have type arguments.
+func (t *Named) SetTypeParams(tparams []*TypeParam) {
+ assert(t.targs.Len() == 0)
+ t.resolve(nil).tparams = bindTParams(tparams)
+}
// TypeArgs returns the type arguments used to instantiate the named type t.
func (t *Named) TypeArgs() *TypeList { return t.targs }
-// NumMethods returns the number of explicit methods whose receiver is named type t.
-func (t *Named) NumMethods() int { return len(t.resolve(nil).methods) }
+// NumMethods returns the number of explicit methods defined for t.
+//
+// For an ordinary or instantiated type t, the receiver base type of these
+// methods will be the named type t. For an uninstantiated generic type t, each
+// method receiver will be instantiated with its receiver type parameters.
+func (t *Named) NumMethods() int { return t.resolve(nil).methods.Len() }
// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
-func (t *Named) Method(i int) *Func { return t.resolve(nil).methods[i] }
+func (t *Named) Method(i int) *Func {
+ t.resolve(nil)
+ return t.methods.At(i, func() *Func {
+ return t.instantiateMethod(i)
+ })
+}
+
+// instiateMethod instantiates the i'th method for an instantiated receiver.
+func (t *Named) instantiateMethod(i int) *Func {
+ assert(t.TypeArgs().Len() > 0) // t must be an instance
+
+ // t.orig.methods is not lazy. origm is the method instantiated with its
+ // receiver type parameters (the "origin" method).
+ origm := t.orig.Method(i)
+ assert(origm != nil)
+
+ check := t.check
+ // Ensure that the original method is type-checked.
+ if check != nil {
+ check.objDecl(origm, nil)
+ }
+
+ origSig := origm.typ.(*Signature)
+ rbase, _ := deref(origSig.Recv().Type())
+
+ // If rbase is t, then origm is already the instantiated method we're looking
+ // for. In this case, we return origm to preserve the invariant that
+ // traversing Method->Receiver Type->Method should get back to the same
+ // method.
+ //
+ // This occurs if t is instantiated with the receiver type parameters, as in
+ // the use of m in func (r T[_]) m() { r.m() }.
+ if rbase == t {
+ return origm
+ }
+
+ sig := origSig
+ // We can only substitute if we have a correspondence between type arguments
+ // and type parameters. This check is necessary in the presence of invalid
+ // code.
+ if origSig.RecvTypeParams().Len() == t.targs.Len() {
+ ctxt := check.bestContext(nil)
+ smap := makeSubstMap(origSig.RecvTypeParams().list(), t.targs.list())
+ sig = check.subst(origm.pos, origSig, smap, ctxt).(*Signature)
+ }
+
+ if sig == origSig {
+ // No substitution occurred, but we still need to create a new signature to
+ // hold the instantiated receiver.
+ copy := *origSig
+ sig = ©
+ }
+
+ var rtyp Type
+ if origm.hasPtrRecv() {
+ rtyp = NewPointer(t)
+ } else {
+ rtyp = t
+ }
+
+ sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp)
+ return NewFunc(origm.pos, origm.pkg, origm.name, sig)
+}
// SetUnderlying sets the underlying type and marks t as complete.
+// t must not have type arguments.
func (t *Named) SetUnderlying(underlying Type) {
+ assert(t.targs.Len() == 0)
if underlying == nil {
panic("underlying type must not be nil")
}
@@ -110,14 +207,20 @@
panic("underlying type must not be *Named")
}
t.resolve(nil).underlying = underlying
+ if t.fromRHS == nil {
+ t.fromRHS = underlying // for cycle detection
+ }
}
// AddMethod adds method m unless it is already in the method list.
+// t must not have type arguments.
func (t *Named) AddMethod(m *Func) {
+ assert(t.targs.Len() == 0)
t.resolve(nil)
- if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
- t.methods = append(t.methods, m)
+ if t.methods == nil {
+ t.methods = newMethodList(nil)
}
+ t.methods.Add(m)
}
func (t *Named) Underlying() Type { return t.resolve(nil).underlying }
@@ -220,6 +323,19 @@
}
}
+func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
+ n.resolve(nil)
+ // If n is an instance, we may not have yet instantiated all of its methods.
+ // Look up the method index in orig, and only instantiate method at the
+ // matching index (if any).
+ i, _ := n.orig.methods.Lookup(pkg, name, foldCase)
+ if i < 0 {
+ return -1, nil
+ }
+ // For instances, m.Method(i) will be different from the orig method.
+ return i, n.Method(i)
+}
+
// bestContext returns the best available context. In order of preference:
// - the given ctxt, if non-nil
// - check.ctxt, if check is non-nil
@@ -239,7 +355,7 @@
// expandNamed ensures that the underlying type of n is instantiated.
// The underlying type will be Typ[Invalid] if there was an error.
-func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) {
+func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParamList, underlying Type, methods *methodList) {
n.orig.resolve(ctxt)
assert(n.orig.underlying != nil)
@@ -261,80 +377,30 @@
smap := makeSubstMap(n.orig.tparams.list(), n.targs.list())
underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt)
-
- for i := 0; i < n.orig.NumMethods(); i++ {
- origm := n.orig.Method(i)
-
- // During type checking origm may not have a fully set up type, so defer
- // instantiation of its signature until later.
- m := NewFunc(origm.pos, origm.pkg, origm.name, nil)
- m.hasPtrRecv_ = origm.hasPtrRecv()
- // Setting instRecv here allows us to complete later (we need the
- // instRecv to get targs and the original method).
- m.instRecv = n
-
- methods = append(methods, m)
+ // If the underlying of n is an interface, we need to set the receiver of
+ // its methods accurately -- we set the receiver of interface methods on
+ // the RHS of a type declaration to the defined type.
+ if iface, _ := underlying.(*Interface); iface != nil {
+ if methods, copied := replaceRecvType(iface.methods, n.orig, n); copied {
+ // If the underlying doesn't actually use type parameters, it's possible
+ // that it wasn't substituted. In this case we need to create a new
+ // *Interface before modifying receivers.
+ if iface == n.orig.underlying {
+ old := iface
+ iface = check.newInterface()
+ iface.embeddeds = old.embeddeds
+ iface.complete = old.complete
+ iface.implicit = old.implicit // should be false but be conservative
+ underlying = iface
+ }
+ iface.methods = methods
+ }
}
} else {
underlying = Typ[Invalid]
}
- // Methods should not escape the type checker API without being completed. If
- // we're in the context of a type checking pass, we need to defer this until
- // later (not all methods may have types).
- completeMethods := func() {
- for _, m := range methods {
- if m.instRecv != nil {
- check.completeMethod(ctxt, m)
- }
- }
- }
- if check != nil {
- check.later(completeMethods)
- } else {
- completeMethods()
- }
-
- return n.orig.tparams, underlying, methods
-}
-
-func (check *Checker) completeMethod(ctxt *Context, m *Func) {
- assert(m.instRecv != nil)
- rbase := m.instRecv
- m.instRecv = nil
- m.setColor(black)
-
- assert(rbase.TypeArgs().Len() > 0)
-
- // Look up the original method.
- _, orig := lookupMethod(rbase.orig.methods, rbase.obj.pkg, m.name)
- assert(orig != nil)
- if check != nil {
- check.objDecl(orig, nil)
- }
- origSig := orig.typ.(*Signature)
- if origSig.RecvTypeParams().Len() != rbase.targs.Len() {
- m.typ = origSig // or new(Signature), but we can't use Typ[Invalid]: Funcs must have Signature type
- return // error reported elsewhere
- }
-
- smap := makeSubstMap(origSig.RecvTypeParams().list(), rbase.targs.list())
- sig := check.subst(orig.pos, origSig, smap, ctxt).(*Signature)
- if sig == origSig {
- // No substitution occurred, but we still need to create a new signature to
- // hold the instantiated receiver.
- copy := *origSig
- sig = ©
- }
- var rtyp Type
- if m.hasPtrRecv() {
- rtyp = NewPointer(rbase)
- } else {
- rtyp = rbase
- }
- sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp)
-
- m.typ = sig
+ return n.orig.tparams, underlying, newLazyMethodList(n.orig.methods.Len())
}
// safeUnderlying returns the underlying of typ without expanding instances, to
diff --git a/src/go/types/object.go b/src/go/types/object.go
index cf05384..fb37700 100644
--- a/src/go/types/object.go
+++ b/src/go/types/object.go
@@ -235,7 +235,7 @@
func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName {
obj := NewTypeName(pos, pkg, name, nil)
- resolve := func(_ *Context, t *Named) (*TypeParamList, Type, []*Func) {
+ resolve := func(_ *Context, t *Named) (*TypeParamList, Type, *methodList) {
tparams, underlying, methods := load(t)
switch underlying.(type) {
@@ -243,7 +243,7 @@
panic(fmt.Sprintf("invalid underlying type %T", t.underlying))
}
- return bindTParams(tparams), underlying, methods
+ return bindTParams(tparams), underlying, newMethodList(methods)
}
NewNamed(obj, nil, nil).resolver = resolve
@@ -319,8 +319,7 @@
// An abstract method may belong to many interfaces due to embedding.
type Func struct {
object
- instRecv *Named // if non-nil, the receiver type for an incomplete instance method
- hasPtrRecv_ bool // only valid for methods that don't have a type yet; use hasPtrRecv() to read
+ hasPtrRecv_ bool // only valid for methods that don't have a type yet; use hasPtrRecv() to read
}
// NewFunc returns a new function with the given signature, representing
@@ -331,7 +330,7 @@
if sig != nil {
typ = sig
}
- return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, nil, false}
+ return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, false}
}
// FullName returns the package- or receiver-type-qualified name of
diff --git a/src/go/types/operand.go b/src/go/types/operand.go
index 06ecbf1..4d7f1e3 100644
--- a/src/go/types/operand.go
+++ b/src/go/types/operand.go
@@ -8,7 +8,6 @@
import (
"bytes"
- "fmt"
"go/ast"
"go/constant"
"go/token"
@@ -278,48 +277,26 @@
return true, 0
}
- // T is an interface type and x implements T and T is not a type parameter
- if Ti, ok := Tu.(*Interface); ok && Tp == nil {
- if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ {
+ // T is an interface type and x implements T and T is not a type parameter.
+ // Also handle the case where T is a pointer to an interface.
+ if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
+ if err := check.implements(V, T); err != nil {
if reason != nil {
- if compilerErrorMessages {
- *reason = check.sprintf("%s does not implement %s %s", x.typ, T,
- check.missingMethodReason(x.typ, T, m, wrongType))
- } else {
- if wrongType != nil {
- if Identical(m.typ, wrongType.typ) {
- *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name)
- } else {
- *reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ)
- }
-
- } else {
- *reason = "missing method " + m.Name()
- }
- }
+ *reason = err.Error()
}
return false, _InvalidIfaceAssign
}
return true, 0
}
- // Provide extra detail in compiler error messages in some cases when T is
- // not an interface.
- if check != nil && compilerErrorMessages {
- if isInterfacePtr(Tu) {
+ // If V is an interface, check if a missing type assertion is the problem.
+ if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
+ if check.implements(T, V) == nil {
+ // T implements V, so give hint about type assertion.
if reason != nil {
- *reason = check.sprintf("%s does not implement %s (%s is pointer to interface, not interface)", x.typ, T, T)
+ *reason = "need type assertion"
}
- return false, _InvalidIfaceAssign
- }
- if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
- if m, _ := check.missingMethod(T, Vi, true); m == nil {
- // T implements Vi, so give hint about type assertion.
- if reason != nil {
- *reason = check.sprintf("need type assertion")
- }
- return false, _IncompatibleAssign
- }
+ return false, _IncompatibleAssign
}
}
diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go
index 22ccdd7..0360f27 100644
--- a/src/go/types/predicates.go
+++ b/src/go/types/predicates.go
@@ -33,7 +33,7 @@
// The allX predicates below report whether t is an X.
// If t is a type parameter the result is true if isX is true
// for all specified types of the type parameter's type set.
-// allX is an optimized version of isX(structuralType(t)) (which
+// allX is an optimized version of isX(coreType(t)) (which
// is the same as underIs(t, isX)).
func allBoolean(typ Type) bool { return allBasic(typ, IsBoolean) }
@@ -47,7 +47,7 @@
// allBasic reports whether under(t) is a basic type with the specified info.
// If t is a type parameter, the result is true if isBasic(t, info) is true
// for all specific types of the type parameter's type set.
-// allBasic(t, info) is an optimized version of isBasic(structuralType(t), info).
+// allBasic(t, info) is an optimized version of isBasic(coreType(t), info).
func allBasic(t Type, info BasicInfo) bool {
if tpar, _ := t.(*TypeParam); tpar != nil {
return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })
@@ -104,10 +104,12 @@
// Comparable reports whether values of type T are comparable.
func Comparable(T Type) bool {
- return comparable(T, nil)
+ return comparable(T, true, nil, nil)
}
-func comparable(T Type, seen map[Type]bool) bool {
+// If dynamic is set, non-type parameter interfaces are always comparable.
+// If reportf != nil, it may be used to report why T is not comparable.
+func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool {
if seen[T] {
return true
}
@@ -125,15 +127,24 @@
return true
case *Struct:
for _, f := range t.fields {
- if !comparable(f.typ, seen) {
+ if !comparable(f.typ, dynamic, seen, nil) {
+ if reportf != nil {
+ reportf("struct containing %s cannot be compared", f.typ)
+ }
return false
}
}
return true
case *Array:
- return comparable(t.elem, seen)
+ if !comparable(t.elem, dynamic, seen, nil) {
+ if reportf != nil {
+ reportf("%s cannot be compared", t)
+ }
+ return false
+ }
+ return true
case *Interface:
- return !isTypeParam(T) || t.IsComparable()
+ return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen)
}
return false
}
@@ -289,8 +300,11 @@
case *Union:
if y, _ := y.(*Union); y != nil {
- xset := computeUnionTypeSet(nil, token.NoPos, x)
- yset := computeUnionTypeSet(nil, token.NoPos, y)
+ // TODO(rfindley): can this be reached during type checking? If so,
+ // consider passing a type set map.
+ unionSets := make(map[*Union]*_TypeSet)
+ xset := computeUnionTypeSet(nil, unionSets, token.NoPos, x)
+ yset := computeUnionTypeSet(nil, unionSets, token.NoPos, y)
return xset.terms.equal(yset.terms)
}
@@ -305,6 +319,9 @@
if y, ok := y.(*Interface); ok {
xset := x.typeSet()
yset := y.typeSet()
+ if xset.comparable != yset.comparable {
+ return false
+ }
if !xset.terms.equal(yset.terms) {
return false
}
diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go
index 7a2dcbf..9edf41b 100644
--- a/src/go/types/resolver.go
+++ b/src/go/types/resolver.go
@@ -629,25 +629,31 @@
}
}
- // We process non-alias declarations first, in order to avoid situations where
- // the type of an alias declaration is needed before it is available. In general
- // this is still not enough, as it is possible to create sufficiently convoluted
- // recursive type definitions that will cause a type alias to be needed before it
- // is available (see issue #25838 for examples).
- // As an aside, the cmd/compiler suffers from the same problem (#25838).
+ // We process non-alias type declarations first, followed by alias declarations,
+ // and then everything else. This appears to avoid most situations where the type
+ // of an alias is needed before it is available.
+ // There may still be cases where this is not good enough (see also issue #25838).
+ // In those cases Checker.ident will report an error ("invalid use of type alias").
var aliasList []*TypeName
- // phase 1
+ var othersList []Object // everything that's not a type
+ // phase 1: non-alias type declarations
for _, obj := range objList {
- // If we have a type alias, collect it for the 2nd phase.
- if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Assign.IsValid() {
- aliasList = append(aliasList, tname)
- continue
+ if tname, _ := obj.(*TypeName); tname != nil {
+ if check.objMap[tname].tdecl.Assign.IsValid() {
+ aliasList = append(aliasList, tname)
+ } else {
+ check.objDecl(obj, nil)
+ }
+ } else {
+ othersList = append(othersList, obj)
}
-
+ }
+ // phase 2: alias type declarations
+ for _, obj := range aliasList {
check.objDecl(obj, nil)
}
- // phase 2
- for _, obj := range aliasList {
+ // phase 3: all other declarations
+ for _, obj := range othersList {
check.objDecl(obj, nil)
}
diff --git a/src/go/types/signature.go b/src/go/types/signature.go
index 8f89e93..a340ac7 100644
--- a/src/go/types/signature.go
+++ b/src/go/types/signature.go
@@ -112,7 +112,8 @@
// - the receiver specification acts as local declaration for its type parameters, which may be blank
_, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true)
if len(rparams) > 0 {
- sig.rparams = bindTParams(check.declareTypeParams(nil, rparams))
+ tparams := check.declareTypeParams(nil, rparams)
+ sig.rparams = bindTParams(tparams)
// Blank identifiers don't get declared, so naive type-checking of the
// receiver type expression would fail in Checker.collectParams below,
// when Checker.ident cannot resolve the _ to a type.
@@ -122,11 +123,10 @@
// lookup in the scope.
for i, p := range rparams {
if p.Name == "_" {
- tpar := sig.rparams.At(i)
if check.recvTParamMap == nil {
check.recvTParamMap = make(map[*ast.Ident]*TypeParam)
}
- check.recvTParamMap[p] = tpar
+ check.recvTParamMap[p] = tparams[i]
}
}
// determine receiver type to get its type parameters
@@ -142,22 +142,23 @@
}
}
// provide type parameter bounds
- // - only do this if we have the right number (otherwise an error is reported elsewhere)
- if sig.RecvTypeParams().Len() == len(recvTParams) {
- // We have a list of *TypeNames but we need a list of Types.
- list := make([]Type, sig.RecvTypeParams().Len())
- for i, t := range sig.RecvTypeParams().list() {
- list[i] = t
- check.mono.recordCanon(t, recvTParams[i])
+ if len(tparams) == len(recvTParams) {
+ smap := makeRenameMap(recvTParams, tparams)
+ for i, tpar := range tparams {
+ recvTPar := recvTParams[i]
+ check.mono.recordCanon(tpar, recvTPar)
+ // recvTPar.bound is (possibly) parameterized in the context of the
+ // receiver type declaration. Substitute parameters for the current
+ // context.
+ tpar.bound = check.subst(tpar.obj.pos, recvTPar.bound, smap, nil)
}
- smap := makeSubstMap(recvTParams, list)
- for i, tpar := range sig.RecvTypeParams().list() {
- bound := recvTParams[i].bound
- // bound is (possibly) parameterized in the context of the
- // receiver type declaration. Substitute parameters for the
- // current context.
- tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil)
- }
+ } else if len(tparams) < len(recvTParams) {
+ // Reporting an error here is a stop-gap measure to avoid crashes in the
+ // compiler when a type parameter/argument cannot be inferred later. It
+ // may lead to follow-on errors (see issues #51339, #51343).
+ // TODO(gri) find a better solution
+ got := measure(len(tparams), "type parameter")
+ check.errorf(recvPar, _BadRecv, "got %s, but receiver base type declares %d", got, len(recvTParams))
}
}
}
@@ -192,66 +193,77 @@
switch len(recvList) {
case 0:
// error reported by resolver
- recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
+ recv = NewParam(token.NoPos, nil, "", Typ[Invalid]) // ignore recv below
default:
// more than one receiver
- check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver")
+ check.error(recvList[len(recvList)-1], _InvalidRecv, "method must have exactly one receiver")
fallthrough // continue with first receiver
case 1:
recv = recvList[0]
}
+ sig.recv = recv
- // TODO(gri) We should delay rtyp expansion to when we actually need the
- // receiver; thus all checks here should be delayed to later.
- rtyp, _ := deref(recv.typ)
+ // Delay validation of receiver type as it may cause premature expansion
+ // of types the receiver type is dependent on (see issues #51232, #51233).
+ check.later(func() {
+ rtyp, _ := deref(recv.typ)
- // spec: "The receiver type must be of the form T or *T where T is a type name."
- // (ignore invalid types - error was reported before)
- if rtyp != Typ[Invalid] {
- var err string
- switch T := rtyp.(type) {
- case *Named:
- T.resolve(check.bestContext(nil))
- // The receiver type may be an instantiated type referred to
- // by an alias (which cannot have receiver parameters for now).
- if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
- check.errorf(atPos(recv.pos), _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
- break
- }
- // spec: "The type denoted by T is called the receiver base type; it must not
- // be a pointer or interface type and it must be declared in the same package
- // as the method."
- if T.obj.pkg != check.pkg {
- err = "type not defined in this package"
- } else {
- // The underlying type of a receiver base type can be a type parameter;
- // e.g. for methods with a generic receiver T[P] with type T[P any] P.
- underIs(T, func(u Type) bool {
- switch u := u.(type) {
- case *Basic:
- // unsafe.Pointer is treated like a regular pointer
- if u.kind == UnsafePointer {
- err = "unsafe.Pointer"
+ // spec: "The receiver type must be of the form T or *T where T is a type name."
+ // (ignore invalid types - error was reported before)
+ if rtyp != Typ[Invalid] {
+ var err string
+ switch T := rtyp.(type) {
+ case *Named:
+ T.resolve(check.bestContext(nil))
+ // The receiver type may be an instantiated type referred to
+ // by an alias (which cannot have receiver parameters for now).
+ if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
+ check.errorf(recv, _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
+ break
+ }
+ // spec: "The type denoted by T is called the receiver base type; it must not
+ // be a pointer or interface type and it must be declared in the same package
+ // as the method."
+ if T.obj.pkg != check.pkg {
+ err = "type not defined in this package"
+ if compilerErrorMessages {
+ check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
+ err = ""
+ }
+ } else {
+ // The underlying type of a receiver base type can be a type parameter;
+ // e.g. for methods with a generic receiver T[P] with type T[P any] P.
+ // TODO(gri) Such declarations are currently disallowed.
+ // Revisit the need for underIs.
+ underIs(T, func(u Type) bool {
+ switch u := u.(type) {
+ case *Basic:
+ // unsafe.Pointer is treated like a regular pointer
+ if u.kind == UnsafePointer {
+ err = "unsafe.Pointer"
+ return false
+ }
+ case *Pointer, *Interface:
+ err = "pointer or interface type"
return false
}
- case *Pointer, *Interface:
- err = "pointer or interface type"
- return false
- }
- return true
- })
+ return true
+ })
+ }
+ case *Basic:
+ err = "basic or unnamed type"
+ if compilerErrorMessages {
+ check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
+ err = ""
+ }
+ default:
+ check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
}
- case *Basic:
- err = "basic or unnamed type"
- default:
- check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
+ if err != "" {
+ check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
+ }
}
- if err != "" {
- check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
- // ok to continue
- }
- }
- sig.recv = recv
+ }).describef(recv, "validate receiver %s", recv)
}
sig.params = NewTuple(params...)
diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go
index 69571d1..bfd14a8 100644
--- a/src/go/types/sizeof_test.go
+++ b/src/go/types/sizeof_test.go
@@ -26,11 +26,11 @@
{Pointer{}, 8, 16},
{Tuple{}, 12, 24},
{Signature{}, 28, 56},
- {Union{}, 16, 32},
+ {Union{}, 12, 24},
{Interface{}, 44, 88},
{Map{}, 16, 32},
{Chan{}, 12, 24},
- {Named{}, 68, 128},
+ {Named{}, 56, 104},
{TypeParam{}, 28, 48},
{term{}, 12, 24},
@@ -39,7 +39,7 @@
{Const{}, 48, 88},
{TypeName{}, 40, 72},
{Var{}, 44, 80},
- {Func{}, 48, 88},
+ {Func{}, 44, 80},
{Label{}, 44, 80},
{Builtin{}, 44, 80},
{Nil{}, 40, 72},
diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go
index 8621d28..9ebfbb6 100644
--- a/src/go/types/stmt.go
+++ b/src/go/types/stmt.go
@@ -248,7 +248,7 @@
}
// Order matters: By comparing v against x, error positions are at the case values.
res := v // keep original v unchanged
- check.comparison(&res, x, token.EQL)
+ check.comparison(&res, x, token.EQL, true)
if res.mode == invalid {
continue L
}
@@ -281,7 +281,8 @@
return false
}
-func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]ast.Expr) (T Type) {
+// If the type switch expression is invalid, x is nil.
+func (check *Checker) caseTypes(x *operand, types []ast.Expr, seen map[Type]ast.Expr) (T Type) {
var dummy operand
L:
for _, e := range types {
@@ -310,8 +311,8 @@
}
}
seen[T] = e
- if T != nil {
- check.typeAssertion(e, x, xtyp, T)
+ if x != nil && T != nil {
+ check.typeAssertion(e, x, T, true)
}
}
return
@@ -417,9 +418,9 @@
if ch.mode == invalid || val.mode == invalid {
return
}
- u := structuralType(ch.typ)
+ u := coreType(ch.typ)
if u == nil {
- check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to %s: no structural type", &ch)
+ check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to %s: no core type", &ch)
return
}
uch, _ := u.(*Chan)
@@ -503,27 +504,25 @@
case *ast.ReturnStmt:
res := check.sig.results
- if res.Len() > 0 {
- // function returns results
- // (if one, say the first, result parameter is named, all of them are named)
- if len(s.Results) == 0 && res.vars[0].name != "" {
- // spec: "Implementation restriction: A compiler may disallow an empty expression
- // list in a "return" statement if a different entity (constant, type, or variable)
- // with the same name as a result parameter is in scope at the place of the return."
- for _, obj := range res.vars {
- if alt := check.lookup(obj.name); alt != nil && alt != obj {
- check.errorf(s, _OutOfScopeResult, "result parameter %s not in scope at return", obj.name)
- check.errorf(alt, _OutOfScopeResult, "\tinner declaration of %s", obj)
- // ok to continue
- }
+ // Return with implicit results allowed for function with named results.
+ // (If one is named, all are named.)
+ if len(s.Results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
+ // spec: "Implementation restriction: A compiler may disallow an empty expression
+ // list in a "return" statement if a different entity (constant, type, or variable)
+ // with the same name as a result parameter is in scope at the place of the return."
+ for _, obj := range res.vars {
+ if alt := check.lookup(obj.name); alt != nil && alt != obj {
+ check.errorf(s, _OutOfScopeResult, "result parameter %s not in scope at return", obj.name)
+ check.errorf(alt, _OutOfScopeResult, "\tinner declaration of %s", obj)
+ // ok to continue
}
- } else {
- // return has results or result parameters are unnamed
- check.initVars(res.vars, s.Results, s)
}
- } else if len(s.Results) > 0 {
- check.error(s.Results[0], _WrongResultCount, "no result values expected")
- check.use(s.Results...)
+ } else {
+ var lhs []*Var
+ if res.Len() > 0 {
+ lhs = res.vars
+ }
+ check.initVars(lhs, s.Results, s)
}
case *ast.BranchStmt:
@@ -686,14 +685,15 @@
return
}
// TODO(gri) we may want to permit type switches on type parameter values at some point
+ var sx *operand // switch expression against which cases are compared against; nil if invalid
if isTypeParam(x.typ) {
check.errorf(&x, _InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
- return
- }
- xtyp, _ := under(x.typ).(*Interface)
- if xtyp == nil {
- check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x)
- return
+ } else {
+ if _, ok := under(x.typ).(*Interface); ok {
+ sx = &x
+ } else {
+ check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x)
+ }
}
check.multipleDefaults(s.Body.List)
@@ -707,7 +707,7 @@
continue
}
// Check each type in this type switch case.
- T := check.caseTypes(&x, xtyp, clause.List, seen)
+ T := check.caseTypes(sx, clause.List, seen)
check.openScope(clause, "case")
// If lhs exists, declare a corresponding variable in the case-local scope.
if lhs != nil {
@@ -821,8 +821,6 @@
case *ast.RangeStmt:
inner |= breakOk | continueOk
- check.openScope(s, "for")
- defer check.closeScope()
// check expression to iterate over
var x operand
@@ -831,12 +829,12 @@
// determine key/value types
var key, val Type
if x.mode != invalid {
- // Ranging over a type parameter is permitted if it has a structural type.
+ // Ranging over a type parameter is permitted if it has a core type.
var cause string
- u := structuralType(x.typ)
+ u := coreType(x.typ)
switch t := u.(type) {
case nil:
- cause = check.sprintf("%s has no structural type", x.typ)
+ cause = check.sprintf("%s has no core type", x.typ)
case *Chan:
if s.Value != nil {
check.softErrorf(s.Value, _InvalidIterVar, "range over %s permits only one iteration variable", &x)
@@ -857,6 +855,11 @@
}
}
+ // Open the for-statement block scope now, after the range clause.
+ // Iteration variables declared with := need to go in this scope (was issue #51437).
+ check.openScope(s, "range")
+ defer check.closeScope()
+
// check assignment to/declaration of iteration variables
// (irregular assignment, cannot easily map to existing assignment checks)
@@ -865,9 +868,7 @@
rhs := [2]Type{key, val} // key, val may be nil
if s.Tok == token.DEFINE {
- // short variable declaration; variable scope starts after the range clause
- // (the for loop opens a new scope, so variables on the lhs never redeclare
- // previously declared variables)
+ // short variable declaration
var vars []*Var
for i, lhs := range lhs {
if lhs == nil {
@@ -904,12 +905,8 @@
// declare variables
if len(vars) > 0 {
- scopePos := s.X.End()
+ scopePos := s.Body.Pos()
for _, obj := range vars {
- // spec: "The scope of a constant or variable identifier declared inside
- // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
- // for short variable declarations) and ends at the end of the innermost
- // containing block."
check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
}
} else {
diff --git a/src/go/types/subst.go b/src/go/types/subst.go
index 1695403..4b4a0f4 100644
--- a/src/go/types/subst.go
+++ b/src/go/types/subst.go
@@ -21,6 +21,17 @@
return proj
}
+// makeRenameMap is like makeSubstMap, but creates a map used to rename type
+// parameters in from with the type parameters in to.
+func makeRenameMap(from, to []*TypeParam) substMap {
+ assert(len(from) == len(to))
+ proj := make(substMap, len(from))
+ for i, tpar := range from {
+ proj[tpar] = to[i]
+ }
+ return proj
+}
+
func (m substMap) empty() bool {
return len(m) == 0
}
@@ -106,12 +117,24 @@
return subst.tuple(t)
case *Signature:
- // TODO(gri) rethink the recv situation with respect to methods on parameterized types
- // recv := subst.var_(t.recv) // TODO(gri) this causes a stack overflow - explain
+ // Preserve the receiver: it is handled during *Interface and *Named type
+ // substitution.
+ //
+ // Naively doing the substitution here can lead to an infinite recursion in
+ // the case where the receiver is an interface. For example, consider the
+ // following declaration:
+ //
+ // type T[A any] struct { f interface{ m() } }
+ //
+ // In this case, the type of f is an interface that is itself the receiver
+ // type of all of its methods. Because we have no type name to break
+ // cycles, substituting in the recv results in an infinite loop of
+ // recv->interface->recv->interface->...
recv := t.recv
+
params := subst.tuple(t.params)
results := subst.tuple(t.results)
- if recv != t.recv || params != t.params || results != t.results {
+ if params != t.params || results != t.results {
return &Signature{
rparams: t.rparams,
// TODO(rFindley) why can't we nil out tparams here, rather than in instantiate?
@@ -130,14 +153,31 @@
// term list substitution may introduce duplicate terms (unlikely but possible).
// This is ok; lazy type set computation will determine the actual type set
// in normal form.
- return &Union{terms, nil}
+ return &Union{terms}
}
case *Interface:
methods, mcopied := subst.funcList(t.methods)
embeddeds, ecopied := subst.typeList(t.embeddeds)
if mcopied || ecopied {
- iface := &Interface{methods: methods, embeddeds: embeddeds, implicit: t.implicit, complete: t.complete}
+ iface := subst.check.newInterface()
+ iface.embeddeds = embeddeds
+ iface.implicit = t.implicit
+ iface.complete = t.complete
+ // If we've changed the interface type, we may need to replace its
+ // receiver if the receiver type is the original interface. Receivers of
+ // *Named type are replaced during named type expansion.
+ //
+ // Notably, it's possible to reach here and not create a new *Interface,
+ // even though the receiver type may be parameterized. For example:
+ //
+ // type T[P any] interface{ m() }
+ //
+ // In this case the interface will not be substituted here, because its
+ // method signatures do not depend on the type parameter P, but we still
+ // need to create new interface methods to hold the instantiated
+ // receiver. This is handled by expandNamed.
+ iface.methods, _ = replaceRecvType(methods, t, iface)
return iface
}
@@ -349,3 +389,31 @@
}
return
}
+
+// replaceRecvType updates any function receivers that have type old to have
+// type new. It does not modify the input slice; if modifications are required,
+// the input slice and any affected signatures will be copied before mutating.
+//
+// The resulting out slice contains the updated functions, and copied reports
+// if anything was modified.
+func replaceRecvType(in []*Func, old, new Type) (out []*Func, copied bool) {
+ out = in
+ for i, method := range in {
+ sig := method.Type().(*Signature)
+ if sig.recv != nil && sig.recv.Type() == old {
+ if !copied {
+ // Allocate a new methods slice before mutating for the first time.
+ // This is defensive, as we may share methods across instantiations of
+ // a given interface type if they do not get substituted.
+ out = make([]*Func, len(in))
+ copy(out, in)
+ copied = true
+ }
+ newsig := *sig
+ sig = &newsig
+ sig.recv = NewVar(sig.recv.pos, sig.recv.pkg, "", new)
+ out[i] = NewFunc(method.pos, method.pkg, method.name, sig)
+ }
+ }
+ return
+}
diff --git a/src/go/types/termlist.go b/src/go/types/termlist.go
index c4ab0e0..94e49ca 100644
--- a/src/go/types/termlist.go
+++ b/src/go/types/termlist.go
@@ -92,15 +92,6 @@
return rl
}
-// If the type set represented by xl is specified by a single (non-𝓤) term,
-// singleType returns that type. Otherwise it returns nil.
-func (xl termlist) singleType() Type {
- if nl := xl.norm(); len(nl) == 1 {
- return nl[0].typ // if nl.isAll() then typ is nil, which is ok
- }
- return nil
-}
-
// union returns the union xl ∪ yl.
func (xl termlist) union(yl termlist) termlist {
return append(xl, yl...).norm()
diff --git a/src/go/types/termlist_test.go b/src/go/types/termlist_test.go
index dddca7a..f0d58ac 100644
--- a/src/go/types/termlist_test.go
+++ b/src/go/types/termlist_test.go
@@ -106,35 +106,6 @@
}
}
-func TestTermlistSingleType(t *testing.T) {
- // helper to deal with nil types
- tstring := func(typ Type) string {
- if typ == nil {
- return "nil"
- }
- return typ.String()
- }
-
- for test, want := range map[string]string{
- "∅": "nil",
- "𝓤": "nil",
- "int": "int",
- "myInt": "myInt",
- "~int": "int",
- "~int ∪ string": "nil",
- "~int ∪ myInt": "int",
- "∅ ∪ int": "int",
- "∅ ∪ ~int": "int",
- "∅ ∪ ~int ∪ string": "nil",
- } {
- xl := maketl(test)
- got := tstring(xl.singleType())
- if got != want {
- t.Errorf("(%v).singleType() == %v; want %v", test, got, want)
- }
- }
-}
-
func TestTermlistUnion(t *testing.T) {
for _, test := range []struct {
xl, yl, want string
diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2
index c1accff..8615973 100644
--- a/src/go/types/testdata/check/builtins.go2
+++ b/src/go/types/testdata/check/builtins.go2
@@ -148,7 +148,7 @@
_ = make /* ERROR expects 2 or 3 arguments */ (S1)
_ = make(S1, 10, 20)
_ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30)
- _ = make(S2 /* ERROR cannot make S2: no structural type */ , 10)
+ _ = make(S2 /* ERROR cannot make S2: no core type */ , 10)
type M0 map[string]int
_ = make(map[string]int)
@@ -156,7 +156,7 @@
_ = make(M1)
_ = make(M1, 10)
_ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20)
- _ = make(M2 /* ERROR cannot make M2: no structural type */ )
+ _ = make(M2 /* ERROR cannot make M2: no core type */ )
type C0 chan int
_ = make(chan int)
@@ -164,7 +164,7 @@
_ = make(C1)
_ = make(C1, 10)
_ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20)
- _ = make(C2 /* ERROR cannot make C2: no structural type */ )
+ _ = make(C2 /* ERROR cannot make C2: no core type */ )
_ = make(C3)
}
diff --git a/src/go/types/testdata/check/builtins.src b/src/go/types/testdata/check/builtins.src
index 7fd6a4b..8a4c207 100644
--- a/src/go/types/testdata/check/builtins.src
+++ b/src/go/types/testdata/check/builtins.src
@@ -15,9 +15,9 @@
var x int
var s []byte
_ = append() // ERROR not enough arguments
- _ = append("foo" /* ERROR not a slice */ )
- _ = append(nil /* ERROR not a slice */ , s)
- _ = append(x /* ERROR not a slice */ , s)
+ _ = append("foo" /* ERROR must be a slice */ )
+ _ = append(nil /* ERROR must be a slice */ , s)
+ _ = append(x /* ERROR must be a slice */ , s)
_ = append(s)
_ = append(s, nil...)
append /* ERROR not used */ (s)
@@ -77,7 +77,7 @@
_ = append(f2())
_ = append(f3())
_ = append(f5())
- _ = append(ff /* ERROR not a slice */ ()) // TODO(gri) better error message
+ _ = append(ff /* ERROR must be a slice */ ()) // TODO(gri) better error message
}
func cap1() {
diff --git a/src/go/types/testdata/check/cycles5.src b/src/go/types/testdata/check/cycles5.src
index 397adcc..c932ef9 100644
--- a/src/go/types/testdata/check/cycles5.src
+++ b/src/go/types/testdata/check/cycles5.src
@@ -135,7 +135,7 @@
type (
a struct{ *b }
b = c
- c struct{ *b }
+ c struct{ *b /* ERROR invalid use of type alias */ }
)
// issue #24939
@@ -145,7 +145,7 @@
}
M interface {
- F() P
+ F() P // ERROR invalid use of type alias
}
P = interface {
diff --git a/src/go/types/testdata/check/expr2.src b/src/go/types/testdata/check/expr2.src
index 8757fd9..6133dbb 100644
--- a/src/go/types/testdata/check/expr2.src
+++ b/src/go/types/testdata/check/expr2.src
@@ -9,8 +9,8 @@
func _bool() {
const t = true == true
const f = true == false
- _ = t /* ERROR "cannot compare" */ < f
- _ = 0 /* ERROR "mismatched types untyped int and untyped bool" */ == t
+ _ = t /* ERROR cannot compare */ < f
+ _ = 0 /* ERROR mismatched types untyped int and untyped bool */ == t
var b bool
var x, y float32
b = x < y
@@ -20,7 +20,7 @@
// corner cases
var (
- v0 = nil /* ERROR "cannot compare" */ == nil
+ v0 = nil == nil // ERROR operator == not defined on untyped nil
)
func arrays() {
@@ -40,7 +40,7 @@
_ = c /* ERROR mismatched types */ == d
var e [10]func() int
- _ = e /* ERROR == not defined */ == e
+ _ = e /* ERROR \[10\]func\(\) int cannot be compared */ == e
}
func structs() {
@@ -79,8 +79,8 @@
func pointers() {
// nil
- _ = nil /* ERROR == not defined */ == nil
- _ = nil /* ERROR != not defined */ != nil
+ _ = nil == nil // ERROR operator == not defined on untyped nil
+ _ = nil != nil // ERROR operator != not defined on untyped nil
_ = nil /* ERROR < not defined */ < nil
_ = nil /* ERROR <= not defined */ <= nil
_ = nil /* ERROR > not defined */ > nil
@@ -211,16 +211,16 @@
// issue #28164
// testcase from issue
- _ = interface /* ERROR cannot compare */ {}(nil) == []int(nil)
+ _ = interface{}(nil) == [ /* ERROR slice can only be compared to nil */ ]int(nil)
// related cases
var e interface{}
var s []int
var x int
- _ = e /* ERROR cannot compare */ == s
- _ = s /* ERROR cannot compare */ == e
- _ = e /* ERROR cannot compare */ < x
- _ = x /* ERROR cannot compare */ < e
+ _ = e == s // ERROR slice can only be compared to nil
+ _ = s /* ERROR slice can only be compared to nil */ == e
+ _ = e /* ERROR operator < not defined on interface */ < x
+ _ = x < e // ERROR operator < not defined on interface
}
func slices() {
@@ -231,7 +231,7 @@
_ = s /* ERROR < not defined */ < nil
// slices are not otherwise comparable
- _ = s /* ERROR == not defined */ == s
+ _ = s /* ERROR slice can only be compared to nil */ == s
_ = s /* ERROR < not defined */ < s
}
@@ -243,7 +243,7 @@
_ = m /* ERROR < not defined */ < nil
// maps are not otherwise comparable
- _ = m /* ERROR == not defined */ == m
+ _ = m /* ERROR map can only be compared to nil */ == m
_ = m /* ERROR < not defined */ < m
}
@@ -255,6 +255,6 @@
_ = f /* ERROR < not defined */ < nil
// funcs are not otherwise comparable
- _ = f /* ERROR == not defined */ == f
+ _ = f /* ERROR func can only be compared to nil */ == f
_ = f /* ERROR < not defined */ < f
}
diff --git a/src/go/types/testdata/check/funcinference.go2 b/src/go/types/testdata/check/funcinference.go2
index f04b76c..45d0781 100644
--- a/src/go/types/testdata/check/funcinference.go2
+++ b/src/go/types/testdata/check/funcinference.go2
@@ -8,21 +8,21 @@
type any interface{}
-func f0[A any, B interface{~*C}, C interface{~*D}, D interface{~*A}](A, B, C, D) {}
+func f0[A any, B interface{*C}, C interface{*D}, D interface{*A}](A, B, C, D) {}
func _() {
f := f0[string]
f("a", nil, nil, nil)
f0("a", nil, nil, nil)
}
-func f1[A any, B interface{~*A}](A, B) {}
+func f1[A any, B interface{*A}](A, B) {}
func _() {
f := f1[int]
f(int(0), new(int))
f1(int(0), new(int))
}
-func f2[A any, B interface{~[]A}](A, B) {}
+func f2[A any, B interface{[]A}](A, B) {}
func _() {
f := f2[byte]
f(byte(0), []byte{})
@@ -38,7 +38,7 @@
// f3(x, &x, &x)
// }
-func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) {}
+func f4[A any, B interface{[]C}, C interface{*A}](A, B, C) {}
func _() {
f := f4[int]
var x int
@@ -46,7 +46,7 @@
f4(x, []*int{}, &x)
}
-func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A { panic(0) }
+func f5[A interface{struct{b B; c C}}, B any, C interface{*B}](x B) A { panic(0) }
func _() {
x := f5(1.2)
var _ float64 = x.b
@@ -79,7 +79,7 @@
type Setter[B any] interface {
Set(string)
- ~*B
+ *B
}
func FromStrings[T interface{}, PT Setter[T]](s []string) []T {
diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2
index 371856e..8291852 100644
--- a/src/go/types/testdata/check/issues.go2
+++ b/src/go/types/testdata/check/issues.go2
@@ -9,19 +9,18 @@
import "io"
import "context"
-// Interfaces are always comparable (though the comparison may panic at runtime).
func eql[T comparable](x, y T) bool {
return x == y
}
-func _() {
- var x interface{}
- var y interface{ m() }
+func _[X comparable, Y interface{comparable; m()}]() {
+ var x X
+ var y Y
eql(x, y /* ERROR does not match */ ) // interfaces of different types
eql(x, x)
eql(y, y)
- eql(y, nil)
- eql[io.Reader](nil, nil)
+ eql(y, nil /* ERROR cannot use nil as Y value in argument to eql */ )
+ eql[io /* ERROR does not implement comparable */ .Reader](nil, nil)
}
// If we have a receiver of pointer to type parameter type (below: *T)
@@ -47,7 +46,7 @@
func (*T) m2()
func _() {
- f2[T /* ERROR wrong method signature */ ]()
+ f2[T /* ERROR m2 has pointer receiver */ ]()
f2[*T]()
}
@@ -58,7 +57,7 @@
type T1[P interface{~uint}] struct{}
func _[P any]() {
- _ = T1[P /* ERROR empty interface P does not implement interface{~uint} */ ]{}
+ _ = T1[P /* ERROR P does not implement interface{~uint} */ ]{}
}
// This is the original (simplified) program causing the same issue.
@@ -74,8 +73,8 @@
return u.s + 1
}
-func NewT2[U any]() T2[U /* ERROR empty interface U does not implement Unsigned */ ] {
- return T2[U /* ERROR empty interface U does not implement Unsigned */ ]{}
+func NewT2[U any]() T2[U /* ERROR U does not implement Unsigned */ ] {
+ return T2[U /* ERROR U does not implement Unsigned */ ]{}
}
func _() {
@@ -145,8 +144,8 @@
}
// Infinite generic type declarations must lead to an error.
-type inf1 /* ERROR illegal cycle */ [T any] struct{ _ inf1[T] }
-type inf2 /* ERROR illegal cycle */ [T any] struct{ inf2[T] }
+type inf1[T any] struct{ _ inf1 /* ERROR illegal cycle */ [T] }
+type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] }
// The implementation of conversions T(x) between integers and floating-point
// numbers checks that both T and x have either integer or floating-point
diff --git a/src/go/types/testdata/check/issues.src b/src/go/types/testdata/check/issues.src
index 88ce452..8bb4c8c 100644
--- a/src/go/types/testdata/check/issues.src
+++ b/src/go/types/testdata/check/issues.src
@@ -131,42 +131,42 @@
)
var x I1
- x = T1 /* ERROR cannot use .*: missing method foo \(foo has pointer receiver\) */ {}
- _ = x /* ERROR .* cannot have dynamic type T1 \(missing method foo \(foo has pointer receiver\)\) */ .(T1)
+ x = T1 /* ERROR cannot use \(T1 literal\) .* as I1 value in assignment: T1 does not implement I1 \(method foo has pointer receiver\) */ {}
+ _ = x /* ERROR impossible type assertion: x\.\(T1\)\n\tT1 does not implement I1 \(method foo has pointer receiver\) */ .(T1)
T1{}.foo /* ERROR cannot call pointer method foo on T1 */ ()
x.Foo /* ERROR "x.Foo undefined \(type I1 has no field or method Foo, but does have foo\)" */ ()
- _ = i2 /* ERROR i2 .* cannot have dynamic type \*T1 \(wrong type for method foo \(have func\(\), want func\(x int\)\)\) */ .(*T1)
+ _ = i2 /* ERROR impossible type assertion: i2\.\(\*T1\)\n\t\*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ .(*T1)
- i1 = i0 /* ERROR cannot use .* missing method foo */
- i1 = t0 /* ERROR cannot use .* missing method foo */
- i1 = i2 /* ERROR cannot use .* wrong type for method foo */
- i1 = t2 /* ERROR cannot use .* wrong type for method foo */
- i2 = i1 /* ERROR cannot use .* wrong type for method foo */
- i2 = t1 /* ERROR cannot use .* wrong type for method foo */
+ i1 = i0 /* ERROR cannot use i0 .* as I1 value in assignment: I0 does not implement I1 \(missing method foo\) */
+ i1 = t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing method foo\) */
+ i1 = i2 /* ERROR .* i2 .* as I1 .*: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */
+ i1 = t2 /* ERROR .* t2 .* as I1 .*: \*T2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */
+ i2 = i1 /* ERROR .* i1 .* as I2 .*: I1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */
+ i2 = t1 /* ERROR .* t1 .* as I2 .*: \*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */
- _ = func() I1 { return i0 /* ERROR cannot use .* missing method foo */ }
- _ = func() I1 { return t0 /* ERROR cannot use .* missing method foo */ }
- _ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I2 { return t1 /* ERROR cannot use .* wrong type for method foo */ }
+ _ = func() I1 { return i0 /* ERROR cannot use i0 .* as I1 value in return statement: I0 does not implement I1 \(missing method foo\) */ }
+ _ = func() I1 { return t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing method foo\) */ }
+ _ = func() I1 { return i2 /* ERROR .* i2 .* as I1 .*: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
+ _ = func() I1 { return t2 /* ERROR .* t2 .* as I1 .*: \*T2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
+ _ = func() I2 { return i1 /* ERROR .* i1 .* as I2 .*: I1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ }
+ _ = func() I2 { return t1 /* ERROR .* t1 .* as I2 .*: \*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ }
// a few more - less exhaustive now
f := func(I1, I2){}
- f(i0 /* ERROR cannot use .* missing method foo */ , i1 /* ERROR cannot use .* wrong type for method foo \(have func\(\), want func\(x int\)\) */ )
+ f(i0 /* ERROR missing method foo */ , i1 /* ERROR wrong type for method foo */ )
- _ = [...]I1{i0 /* ERROR cannot use .* missing method foo */ }
- _ = [...]I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = []I1{i0 /* ERROR cannot use .* missing method foo */ }
- _ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
- _ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ }
+ _ = [...]I1{i0 /* ERROR cannot use i0 .* as I1 value in array or slice literal: I0 does not implement I1 \(missing method foo\) */ }
+ _ = [...]I1{i2 /* ERROR cannot use i2 .* as I1 value in array or slice literal: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
+ _ = []I1{i0 /* ERROR missing method foo */ }
+ _ = []I1{i2 /* ERROR wrong type for method foo */ }
+ _ = map[int]I1{0: i0 /* ERROR missing method foo */ }
+ _ = map[int]I1{0: i2 /* ERROR wrong type for method foo */ }
- make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */
- make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */
+ make(chan I1) <- i0 /* ERROR missing method foo */
+ make(chan I1) <- i2 /* ERROR wrong type for method foo */
}
// Check that constants representable as integers are in integer form
diff --git a/src/go/types/testdata/check/methodsets.src b/src/go/types/testdata/check/methodsets.src
index 9fb10de..b0eb14c 100644
--- a/src/go/types/testdata/check/methodsets.src
+++ b/src/go/types/testdata/check/methodsets.src
@@ -196,9 +196,9 @@
_ func(error) string = error.Error
perr = &err
- _ = perr.Error /* ERROR "no field or method" */ ()
- _ func() string = perr.Error /* ERROR "no field or method" */
- _ func(*error) string = (*error).Error /* ERROR "no field or method" */
+ _ = perr.Error /* ERROR "type \*error is pointer to interface, not interface" */ ()
+ _ func() string = perr.Error /* ERROR "type \*error is pointer to interface, not interface" */
+ _ func(*error) string = (*error).Error /* ERROR "type \*error is pointer to interface, not interface" */
)
type T *interface{ m() int }
@@ -207,8 +207,8 @@
_ = (*x).m()
_ = (*x).m
- _ = x.m /* ERROR "no field or method" */ ()
- _ = x.m /* ERROR "no field or method" */
- _ = T.m /* ERROR "no field or method" */
+ _ = x.m /* ERROR "type T is pointer to interface, not interface" */ ()
+ _ = x.m /* ERROR "type T is pointer to interface, not interface" */
+ _ = T.m /* ERROR "type T is pointer to interface, not interface" */
)
}
diff --git a/src/go/types/testdata/check/shifts.src b/src/go/types/testdata/check/shifts.src
index 4d3c59a..16a67ae 100644
--- a/src/go/types/testdata/check/shifts.src
+++ b/src/go/types/testdata/check/shifts.src
@@ -380,7 +380,7 @@
var a = make([]int, 1<<s + 1.2 /* ERROR "truncated to int" */ )
var _ = a[1<<s - 2.3 /* ERROR "truncated to int" */ ]
var _ int = 1<<s + 3.4 /* ERROR "truncated to int" */
- var _ = string(1 << s)
+ var _ = string(1 /* ERROR shifted operand 1 .* must be integer */ << s)
var _ = string(1.0 /* ERROR "cannot convert" */ << s)
}
diff --git a/src/go/types/testdata/check/stmt0.src b/src/go/types/testdata/check/stmt0.src
index c7a718d..7795a44 100644
--- a/src/go/types/testdata/check/stmt0.src
+++ b/src/go/types/testdata/check/stmt0.src
@@ -375,7 +375,7 @@
func returns0() {
return
- return 0 /* ERROR no result values expected */
+ return 0 /* ERROR too many return values */
}
func returns1(x float64) (int, *float64) {
@@ -429,7 +429,7 @@
switch int32(x) {
case 1, 2:
- case x /* ERROR "cannot compare" */ :
+ case x /* ERROR "invalid case x in switch on int32\(x\) \(mismatched types int and int32\)" */ :
}
switch x {
@@ -695,7 +695,7 @@
_ = y
}
- switch x := i /* ERROR "not an interface" */ .(type) {}
+ switch x /* ERROR "x declared but not used" */ := i /* ERROR "not an interface" */ .(type) {}
switch t := x.(type) {
case nil:
@@ -719,6 +719,18 @@
case T2 /* ERROR "wrong type for method m" */ :
case I2 /* STRICT "wrong type for method m" */ : // only an error in strict mode (issue 8561)
}
+
+
+ {
+ x := 1
+ v := 2
+ switch v /* ERROR "v [(]variable of type int[)] is not an interface" */ .(type) {
+ case int:
+ println(x)
+ println(x / 0 /* ERROR "invalid operation: division by zero" */)
+ case 1 /* ERROR "expected type, found 1" */:
+ }
+ }
}
// Test that each case clause uses the correct type of the variable
diff --git a/src/go/types/testdata/check/typeinference.go2 b/src/go/types/testdata/check/typeinference.go2
index 8876cca..28f3e28 100644
--- a/src/go/types/testdata/check/typeinference.go2
+++ b/src/go/types/testdata/check/typeinference.go2
@@ -4,44 +4,46 @@
package typeInference
+// As of issue #51527, type-type inference has been disabled.
+
// basic inference
type Tb[P ~*Q, Q any] int
func _() {
- var x Tb[*int]
+ var x Tb /* ERROR got 1 arguments */ [*int]
var y Tb[*int, int]
- x = y
+ x = y /* ERROR cannot use y .* in assignment */
_ = x
}
// recursive inference
-type Tr[A any, B ~*C, C ~*D, D ~*A] int
+type Tr[A any, B *C, C *D, D *A] int
func _() {
- var x Tr[string]
+ var x Tr /* ERROR got 1 arguments */ [string]
var y Tr[string, ***string, **string, *string]
var z Tr[int, ***int, **int, *int]
- x = y
+ x = y /* ERROR cannot use y .* in assignment */
x = z // ERROR cannot use z .* as Tr
_ = x
}
// other patterns of inference
-type To0[A any, B ~[]A] int
-type To1[A any, B ~struct{a A}] int
-type To2[A any, B ~[][]A] int
-type To3[A any, B ~[3]*A] int
-type To4[A any, B any, C ~struct{a A; b B}] int
+type To0[A any, B []A] int
+type To1[A any, B struct{a A}] int
+type To2[A any, B [][]A] int
+type To3[A any, B [3]*A] int
+type To4[A any, B any, C struct{a A; b B}] int
func _() {
- var _ To0[int]
- var _ To1[int]
- var _ To2[int]
- var _ To3[int]
- var _ To4[int, string]
+ var _ To0 /* ERROR got 1 arguments */ [int]
+ var _ To1 /* ERROR got 1 arguments */ [int]
+ var _ To2 /* ERROR got 1 arguments */ [int]
+ var _ To3 /* ERROR got 1 arguments */ [int]
+ var _ To4 /* ERROR got 2 arguments */ [int, string]
}
// failed inference
type Tf0[A, B any] int
type Tf1[A any, B ~struct{a A; c C}, C any] int
func _() {
- var _ Tf0 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int]
- var _ Tf1 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 3 type parameters */ [int]
+ var _ Tf0 /* ERROR got 1 arguments but 2 type parameters */ [int]
+ var _ Tf1 /* ERROR got 1 arguments but 3 type parameters */ [int]
}
diff --git a/src/go/types/testdata/check/typeinst.go2 b/src/go/types/testdata/check/typeinst.go2
index 6548120..6423cb8 100644
--- a/src/go/types/testdata/check/typeinst.go2
+++ b/src/go/types/testdata/check/typeinst.go2
@@ -58,5 +58,5 @@
// Self-recursive generic types are not permitted
-type self1 /* ERROR illegal cycle */ [P any] self1[P]
+type self1[P any] self1 /* ERROR illegal cycle */ [P]
type self2[P any] *self2[P] // this is ok
diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2
index e3aca4c..29a3b16 100644
--- a/src/go/types/testdata/check/typeparams.go2
+++ b/src/go/types/testdata/check/typeparams.go2
@@ -134,11 +134,11 @@
type myByte1 []byte
type myByte2 []byte
func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] }
-func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j:k] }
+func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no core type */ [i:j:k] }
func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] }
func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] }
-func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j] }
+func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x /* ERROR no core type */ [i:j] }
// len/cap built-ins
@@ -230,7 +230,7 @@
for _, _ = range s1 {}
var s2 S2
- for range s2 /* ERROR cannot range over s2.*no structural type */ {}
+ for range s2 /* ERROR cannot range over s2.*no core type */ {}
var a0 []int
for range a0 {}
@@ -243,7 +243,7 @@
for _, _ = range a1 {}
var a2 A2
- for range a2 /* ERROR cannot range over a2.*no structural type */ {}
+ for range a2 /* ERROR cannot range over a2.*no core type */ {}
var p0 *[10]int
for range p0 {}
@@ -256,7 +256,7 @@
for _, _ = range p1 {}
var p2 P2
- for range p2 /* ERROR cannot range over p2.*no structural type */ {}
+ for range p2 /* ERROR cannot range over p2.*no core type */ {}
var m0 map[string]int
for range m0 {}
@@ -269,7 +269,7 @@
for _, _ = range m1 {}
var m2 M2
- for range m2 /* ERROR cannot range over m2.*no structural type */ {}
+ for range m2 /* ERROR cannot range over m2.*no core type */ {}
}
// type inference checks
@@ -329,8 +329,8 @@
type T struct {}
func (T) m1() {}
-func (T) m2[ /* ERROR methods cannot have type parameters */ _ any]() {}
-func (T) m3[ /* ERROR methods cannot have type parameters */ P any]() {}
+func (T) m2[ /* ERROR method must have no type parameters */ _ any]() {}
+func (T) m3[ /* ERROR method must have no type parameters */ P any]() {}
// type inference across parameterized types
@@ -391,25 +391,28 @@
// type parameters in methods (generalization)
-type R0 struct{}
+// Type Parameter lists are not allowed on methods, and are not produced by
+// go/parser. The test cases below are preserved for consistency with types2,
+// which produces an error but stores type parameters.
+// type R0 struct{}
-func (R0) _[ /* ERROR methods cannot have type parameters */ T any](x T) {}
-func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ R0 any]() {} // scope of type parameters starts at "func"
+// func (R0) _[ /* ERROR methods cannot have type parameters */ T any](x T) {}
+// func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ R0 any]() {} // scope of type parameters starts at "func"
-type R1[A, B any] struct{}
+// type R1[A, B any] struct{}
-func (_ R1[A, B]) m0(A, B)
-func (_ R1[A, B]) m1[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T { panic(0) }
-func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
-func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ A /* ERROR redeclared */ any](B) {}
+// func (_ R1[A, B]) m0(A, B)
+// func (_ R1[A, B]) m1[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T { panic(0) }
+// func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
+// func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ A /* ERROR redeclared */ any](B) {}
-func _() {
- var r R1[int, string]
- r.m1[rune](42, "foo", 'a')
- r.m1[rune](42, "foo", 1.2 /* ERROR cannot use .* as rune .* \(truncated\) */)
- r.m1(42, "foo", 1.2) // using type inference
- var _ float64 = r.m1(42, "foo", 1.2)
-}
+// func _() {
+// var r R1[int, string]
+// r.m1[rune](42, "foo", 'a')
+// r.m1[rune](42, "foo", 1.2 /* ERROR cannot use .* as rune .* \(truncated\) */)
+// r.m1(42, "foo", 1.2) // using type inference
+// var _ float64 = r.m1(42, "foo", 1.2)
+// }
type I1[A any] interface {
m1(A)
@@ -518,13 +521,13 @@
type I interface {}
func _[P I] (x P) {
- x.m /* ERROR interface I has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
func _[P interface{}] (x P) {
- x.m /* ERROR type bound for P has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
func _[P any] (x P) {
- x.m /* ERROR type bound for P has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
diff --git a/src/go/types/testdata/check/vardecl.src b/src/go/types/testdata/check/vardecl.src
index 787f787..56abf97 100644
--- a/src/go/types/testdata/check/vardecl.src
+++ b/src/go/types/testdata/check/vardecl.src
@@ -169,8 +169,8 @@
func _() {
var x int
- return x /* ERROR no result values expected */
- return math /* ERROR no result values expected */ .Sin(0)
+ return x /* ERROR too many return values */
+ return math /* ERROR too many return values */ .Sin(0)
}
func _() int {
diff --git a/src/go/types/testdata/examples/inference.go2 b/src/go/types/testdata/examples/inference.go2
index ffa30ee..e59a544 100644
--- a/src/go/types/testdata/examples/inference.go2
+++ b/src/go/types/testdata/examples/inference.go2
@@ -78,7 +78,7 @@
related1(si, "foo" /* ERROR cannot use "foo" */ )
}
-func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) {}
+func related2[Elem any, Slice interface{[]Elem}](e Elem, s Slice) {}
func _() {
// related2 can be called with explicit instantiation.
@@ -109,16 +109,8 @@
related3[int, []int]()
related3[byte, List[byte]]()
- // Alternatively, the 2nd type argument can be inferred
- // from the first one through constraint type inference.
- related3[int]()
-
- // The inferred type is the structural type of the Slice
- // type parameter.
- var _ []int = related3[int]()
-
- // It is not the defined parameterized type List.
- type anotherList []float32
- var _ anotherList = related3[float32]() // valid
- var _ anotherList = related3 /* ERROR cannot use .* \(value of type List\[float32\]\) as anotherList */ [float32, List[float32]]()
+ // The 2nd type argument cannot be inferred from the first
+ // one because there's two possible choices: []Elem and
+ // List[Elem].
+ related3 /* ERROR cannot infer Slice */ [int]()
}
diff --git a/src/go/types/testdata/examples/methods.go2 b/src/go/types/testdata/examples/methods.go2
index 1d76d55..a46f789 100644
--- a/src/go/types/testdata/examples/methods.go2
+++ b/src/go/types/testdata/examples/methods.go2
@@ -35,7 +35,7 @@
// style. In m3 below, int is the name of the local receiver type parameter
// and it shadows the predeclared identifier int which then cannot be used
// anymore as expected.
-// This is no different from locally redelaring a predeclared identifier
+// This is no different from locally re-declaring a predeclared identifier
// and usually should be avoided. There are some notable exceptions; e.g.,
// sometimes it makes sense to use the identifier "copy" which happens to
// also be the name of a predeclared built-in function.
diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2
index 33642fa..1e83f89 100644
--- a/src/go/types/testdata/examples/types.go2
+++ b/src/go/types/testdata/examples/types.go2
@@ -298,7 +298,7 @@
// It is possible to create composite literals of type parameter
// type as long as it's possible to create a composite literal
-// of the structural type of the type parameter's constraint.
+// of the core type of the type parameter's constraint.
func _[P interface{ ~[]int }]() P {
return P{}
return P{1, 2, 3}
@@ -313,7 +313,7 @@
}
// This is a degenerate case with a singleton type set, but we can create
-// composite literals even if the structural type is a defined type.
+// composite literals even if the core type is a defined type.
type MyInts []int
func _[P MyInts]() P {
diff --git a/src/go/types/testdata/examples/typesets.go2 b/src/go/types/testdata/examples/typesets.go2
index cf01072..fcddf1f 100644
--- a/src/go/types/testdata/examples/typesets.go2
+++ b/src/go/types/testdata/examples/typesets.go2
@@ -35,7 +35,7 @@
return deref(p)
}
-func addrOfCopy[V any, P ~*V](v V) P {
+func addrOfCopy[V any, P *V](v V) P {
return &v
}
diff --git a/src/go/types/testdata/fixedbugs/issue25838.go b/src/go/types/testdata/fixedbugs/issue25838.go
new file mode 100644
index 0000000..adbd138
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue25838.go
@@ -0,0 +1,26 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// examples from the issue
+
+type (
+ e = f
+ f = g
+ g = []h
+ h i
+ i = j
+ j = e
+)
+
+type (
+ e1 = []h1
+ h1 e1
+)
+
+type (
+ P = *T
+ T P
+)
diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2
index 2de2f43..8cba2e7 100644
--- a/src/go/types/testdata/fixedbugs/issue39634.go2
+++ b/src/go/types/testdata/fixedbugs/issue39634.go2
@@ -37,7 +37,7 @@
// func main8() {}
// crash 9
-type foo9 /* ERROR illegal cycle */ [A any] interface { foo9[A] }
+type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] }
func _() { var _ = new(foo9[int]) }
// crash 12
@@ -85,7 +85,7 @@
var x T25 /* ERROR without instantiation */ .m1
// crash 26
-type T26 = interface{ F26[ /* ERROR methods cannot have type parameters */ Z any]() }
+type T26 = interface{ F26[ /* ERROR interface method must have no type parameters */ Z any]() }
// The error messages on the line below differ from types2 because for backward
// compatibility go/parser must produce an IndexExpr with BadExpr index for the
// expression F26[].
diff --git a/src/go/types/testdata/fixedbugs/issue39938.go2 b/src/go/types/testdata/fixedbugs/issue39938.go2
index 1146467..6bc9284 100644
--- a/src/go/types/testdata/fixedbugs/issue39938.go2
+++ b/src/go/types/testdata/fixedbugs/issue39938.go2
@@ -2,22 +2,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Check "infinite expansion" cycle errors across instantiated types.
-// We can't detect these errors anymore at the moment. See #48962 for
-// details.
-
package p
+// All but E2 and E5 provide an "indirection" and break infinite expansion of a type.
type E0[P any] []P
type E1[P any] *P
type E2[P any] struct{ _ P }
type E3[P any] struct{ _ *P }
+type E5[P any] struct{ _ [10]P }
-type T0 /* illegal cycle */ struct {
+type T0 struct {
_ E0[T0]
}
-type T0_ /* illegal cycle */ struct {
+type T0_ struct {
E0[T0_]
}
@@ -25,7 +23,7 @@
_ E1[T1]
}
-type T2 /* illegal cycle */ struct {
+type T2 /* ERROR illegal cycle */ struct {
_ E2[T2]
}
@@ -33,20 +31,24 @@
_ E3[T3]
}
-// some more complex cases
-
-type T4 /* illegal cycle */ struct {
- _ E0[E2[T4]]
-}
+type T4 /* ERROR illegal cycle */ [10]E5[T4]
type T5 struct {
- _ E0[E2[E0[E1[E2[[10]T5]]]]]
+ _ E0[E2[T5]]
}
-type T6 /* illegal cycle */ struct {
- _ E0[[10]E2[E0[E2[E2[T6]]]]]
+type T6 struct {
+ _ E0[E2[E0[E1[E2[[10]T6]]]]]
}
type T7 struct {
- _ E0[[]E2[E0[E2[E2[T6]]]]]
+ _ E0[[10]E2[E0[E2[E2[T7]]]]]
}
+
+type T8 struct {
+ _ E0[[]E2[E0[E2[E2[T8]]]]]
+}
+
+type T9 /* ERROR illegal cycle */ [10]E2[E5[E2[T9]]]
+
+type T10 [10]E2[E5[E2[func(T10)]]]
diff --git a/src/go/types/testdata/fixedbugs/issue41124.go2 b/src/go/types/testdata/fixedbugs/issue41124.go2
index 7f55ba8..4550dd7 100644
--- a/src/go/types/testdata/fixedbugs/issue41124.go2
+++ b/src/go/types/testdata/fixedbugs/issue41124.go2
@@ -47,7 +47,7 @@
}
type _ struct{
- I3 // ERROR interface is .* comparable
+ I3 // ERROR interface contains type constraints
}
// General composite types.
@@ -59,19 +59,19 @@
_ []I1 // ERROR interface is .* comparable
_ []I2 // ERROR interface contains type constraints
- _ *I3 // ERROR interface is .* comparable
+ _ *I3 // ERROR interface contains type constraints
_ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints
- _ chan I3 // ERROR interface is .* comparable
+ _ chan I3 // ERROR interface contains type constraints
_ func(I1 /* ERROR interface is .* comparable */ )
_ func() I2 // ERROR interface contains type constraints
)
// Other cases.
-var _ = [...]I3 /* ERROR interface is .* comparable */ {}
+var _ = [...]I3 /* ERROR interface contains type constraints */ {}
func _(x interface{}) {
- _ = x.(I3 /* ERROR interface is .* comparable */ )
+ _ = x.(I3 /* ERROR interface contains type constraints */ )
}
type T1[_ any] struct{}
diff --git a/src/go/types/testdata/fixedbugs/issue43056.go2 b/src/go/types/testdata/fixedbugs/issue43056.go2
new file mode 100644
index 0000000..35c7ef5
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue43056.go2
@@ -0,0 +1,31 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// simplified example
+func f[T ~func(T)](a, b T) {}
+
+type F func(F)
+
+func _() {
+ var i F
+ var j func(F)
+
+ f(i, j)
+ // f(j, i) // disabled for now
+}
+
+// example from issue
+func g[T interface{ Equal(T) bool }](a, b T) {}
+
+type I interface{ Equal(I) bool }
+
+func _() {
+ var i I
+ var j interface{ Equal(I) bool }
+
+ g(i, j)
+ // g(j, i) // disabled for now
+}
diff --git a/src/go/types/testdata/fixedbugs/issue43110.src b/src/go/types/testdata/fixedbugs/issue43110.src
index 4a46945..8d5c983 100644
--- a/src/go/types/testdata/fixedbugs/issue43110.src
+++ b/src/go/types/testdata/fixedbugs/issue43110.src
@@ -30,7 +30,7 @@
}
switch (func())(nil) {
- case f /* ERROR cannot compare */ :
+ case f /* ERROR invalid case f in switch on .* \(func can only be compared to nil\) */ :
}
switch nil /* ERROR use of untyped nil in switch expression */ {
diff --git a/src/go/types/testdata/fixedbugs/issue43527.go2 b/src/go/types/testdata/fixedbugs/issue43527.go2
index e4bcee5..2955c26 100644
--- a/src/go/types/testdata/fixedbugs/issue43527.go2
+++ b/src/go/types/testdata/fixedbugs/issue43527.go2
@@ -9,7 +9,7 @@
type (
_ [L]struct{}
_ [A /* ERROR undeclared name A for array length */ ]struct{}
- _ [B /* ERROR not an expression */ ]struct{}
+ _ [B /* ERROR invalid array length B */ ]struct{}
_[A any] struct{}
B int
diff --git a/src/go/types/testdata/fixedbugs/issue43671.go2 b/src/go/types/testdata/fixedbugs/issue43671.go2
index 46ac51e..3c78f85 100644
--- a/src/go/types/testdata/fixedbugs/issue43671.go2
+++ b/src/go/types/testdata/fixedbugs/issue43671.go2
@@ -12,7 +12,7 @@
type C5[T any] interface{ ~chan T | <-chan T }
func _[T any](ch T) {
- <-ch // ERROR cannot receive from ch .* no structural type
+ <-ch // ERROR cannot receive from ch .* no core type
}
func _[T C0](ch T) {
@@ -28,7 +28,7 @@
}
func _[T C3](ch T) {
- <-ch // ERROR cannot receive from ch .* no structural type
+ <-ch // ERROR cannot receive from ch .* no core type
}
func _[T C4](ch T) {
diff --git a/src/go/types/testdata/fixedbugs/issue45114.go b/src/go/types/testdata/fixedbugs/issue45114.go
new file mode 100644
index 0000000..0093660
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue45114.go
@@ -0,0 +1,8 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var s uint
+var _ = string(1 /* ERROR shifted operand 1 .* must be integer */ << s)
diff --git a/src/go/types/testdata/fixedbugs/issue45548.go2 b/src/go/types/testdata/fixedbugs/issue45548.go2
index b8ba0ad..01c9672 100644
--- a/src/go/types/testdata/fixedbugs/issue45548.go2
+++ b/src/go/types/testdata/fixedbugs/issue45548.go2
@@ -4,7 +4,7 @@
package p
-func f[F interface{~*Q}, G interface{~*R}, Q, R any](q Q, r R) {}
+func f[F interface{*Q}, G interface{*R}, Q, R any](q Q, r R) {}
func _() {
f[*float64, *int](1, 2)
diff --git a/src/go/types/testdata/fixedbugs/issue47115.go2 b/src/go/types/testdata/fixedbugs/issue47115.go2
index f71e06c..a0bfe38 100644
--- a/src/go/types/testdata/fixedbugs/issue47115.go2
+++ b/src/go/types/testdata/fixedbugs/issue47115.go2
@@ -12,7 +12,7 @@
type C5[T any] interface{ ~chan T | chan<- T }
func _[T any](ch T) {
- ch <- /* ERROR cannot send to ch .* no structural type */ 0
+ ch <- /* ERROR cannot send to ch .* no core type */ 0
}
func _[T C0](ch T) {
@@ -28,7 +28,7 @@
}
func _[T C3](ch T) {
- ch <- /* ERROR cannot send to ch .* no structural type */ 0
+ ch <- /* ERROR cannot send to ch .* no core type */ 0
}
func _[T C4](ch T) {
diff --git a/src/go/types/testdata/fixedbugs/issue47411.go2 b/src/go/types/testdata/fixedbugs/issue47411.go2
index d6c34be..db5fb32 100644
--- a/src/go/types/testdata/fixedbugs/issue47411.go2
+++ b/src/go/types/testdata/fixedbugs/issue47411.go2
@@ -16,11 +16,11 @@
_ = f[P]
_ = f[Q]
_ = f[func /* ERROR does not implement comparable */ ()]
- _ = f[R /* ERROR empty interface R does not implement comparable */ ]
+ _ = f[R /* ERROR R does not implement comparable */ ]
_ = g[int]
_ = g[P /* ERROR P does not implement interface{interface{comparable; ~int\|~string} */ ]
_ = g[Q]
- _ = g[func /* ERROR does not implement comparable */ ()]
- _ = g[R /* ERROR empty interface R does not implement interface{interface{comparable; ~int\|~string} */ ]
+ _ = g[func /* ERROR func\(\) does not implement interface{interface{comparable; ~int\|~string}} */ ()]
+ _ = g[R /* ERROR R does not implement interface{interface{comparable; ~int\|~string} */ ]
}
diff --git a/src/go/types/testdata/fixedbugs/issue47747.go2 b/src/go/types/testdata/fixedbugs/issue47747.go2
index 6a2e787..6f09fc2 100644
--- a/src/go/types/testdata/fixedbugs/issue47747.go2
+++ b/src/go/types/testdata/fixedbugs/issue47747.go2
@@ -20,7 +20,7 @@
x.m()
// (&x).m doesn't exist because &x is of type *P
// and pointers to type parameters don't have methods
- (&x).m /* ERROR \*P has no field or method m */ ()
+ (&x).m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
}
@@ -29,7 +29,7 @@
func _(x *T2) {
// x.m doesn't exists because x is of type *T2
// and pointers to interfaces don't have methods
- x.m /* ERROR \*T2 has no field or method m */()
+ x.m /* ERROR type \*T2 is pointer to interface, not interface */()
}
// Test case 1 from issue
diff --git a/src/go/types/testdata/fixedbugs/issue47818.go2 b/src/go/types/testdata/fixedbugs/issue47818.go2
index 2631118..546de1c 100644
--- a/src/go/types/testdata/fixedbugs/issue47818.go2
+++ b/src/go/types/testdata/fixedbugs/issue47818.go2
@@ -8,8 +8,6 @@
package go1_17
-import "constraints"
-
type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
// for init (and main, but we're not in package main) we should only get one error
@@ -57,5 +55,3 @@
_ = C1
_ = C2
)
-
-type Ordered constraints /* ERROR using type constraint constraints\.Ordered requires go1\.18 or later */ .Ordered
diff --git a/src/go/types/testdata/fixedbugs/issue48312.go2 b/src/go/types/testdata/fixedbugs/issue48312.go2
new file mode 100644
index 0000000..2fdb7ca
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue48312.go2
@@ -0,0 +1,20 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T interface{ m() }
+type P *T
+
+func _(p *T) {
+ p.m /* ERROR type \*T is pointer to interface, not interface */ ()
+}
+
+func _(p P) {
+ p.m /* ERROR type P is pointer to interface, not interface */ ()
+}
+
+func _[P T](p *P) {
+ p.m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
+}
diff --git a/src/go/types/testdata/fixedbugs/issue48619.go2 b/src/go/types/testdata/fixedbugs/issue48619.go2
index 870bacd..72eea1e 100644
--- a/src/go/types/testdata/fixedbugs/issue48619.go2
+++ b/src/go/types/testdata/fixedbugs/issue48619.go2
@@ -2,23 +2,21 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This issue has been re-opened.
-
package p
func f[P any](a, _ P) {
- // var x int
- // f(a, x /* ERROR type int of x does not match P */)
- // f(x, a /* ERROR type P of a does not match inferred type int for P */)
+ var x int
+ // TODO(gri) these error messages, while correct, could be better
+ f(a, x /* ERROR type int of x does not match inferred type P for P */)
+ f(x, a /* ERROR type P of a does not match inferred type int for P */)
}
func g[P any](a, b P) {
- // g(a, b)
- // g(&a, &b)
- // g([]P{}, []P{})
-}
+ g(a, b)
+ g(&a, &b)
+ g([]P{}, []P{})
-func h[P any](a, b P) {
- // h(&a, &b)
- // h([]P{a}, []P{b})
+ // work-around: provide type argument explicitly
+ g[*P](&a, &b)
+ g[[]P]([]P{}, []P{})
}
diff --git a/src/go/types/testdata/fixedbugs/issue48656.go2 b/src/go/types/testdata/fixedbugs/issue48656.go2
index 52863d4..0f60f47 100644
--- a/src/go/types/testdata/fixedbugs/issue48656.go2
+++ b/src/go/types/testdata/fixedbugs/issue48656.go2
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This issue is still open.
-
package p
-func f[P interface{*Q}, Q any](p P, q Q) {
- // _ = f[P]
- // _ = f[/* ERROR cannot infer P */ *P]
+func f[P *Q, Q any](P, Q) {
+ _ = f[P]
+}
+
+func f2[P /* ERROR instantiation cycle */ *Q, Q any](P, Q) {
+ _ = f2[*P]
}
diff --git a/src/go/types/testdata/fixedbugs/issue48712.go2 b/src/go/types/testdata/fixedbugs/issue48712.go2
new file mode 100644
index 0000000..ab39756
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue48712.go2
@@ -0,0 +1,41 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[P comparable](x, y P) {
+ _ = x == x
+ _ = x == y
+ _ = y == x
+ _ = y == y
+
+ _ = x /* ERROR type parameter P is not comparable with < */ < y
+}
+
+func _[P comparable](x P, y any) {
+ _ = x == x
+ _ = x == y
+ _ = y == x
+ _ = y == y
+
+ _ = x /* ERROR type parameter P is not comparable with < */ < y
+}
+
+func _[P any](x, y P) {
+ _ = x /* ERROR type parameter P is not comparable with == */ == x
+ _ = x /* ERROR type parameter P is not comparable with == */ == y
+ _ = y /* ERROR type parameter P is not comparable with == */ == x
+ _ = y /* ERROR type parameter P is not comparable with == */ == y
+
+ _ = x /* ERROR type parameter P is not comparable with < */ < y
+}
+
+func _[P any](x P, y any) {
+ _ = x /* ERROR type parameter P is not comparable with == */ == x
+ _ = x /* ERROR type parameter P is not comparable with == */ == y
+ _ = y == x // ERROR type parameter P is not comparable with ==
+ _ = y == y
+
+ _ = x /* ERROR type parameter P is not comparable with < */ < y
+}
diff --git a/src/go/types/testdata/fixedbugs/issue48951.go2 b/src/go/types/testdata/fixedbugs/issue48951.go2
index cf02cc1..a936528 100644
--- a/src/go/types/testdata/fixedbugs/issue48951.go2
+++ b/src/go/types/testdata/fixedbugs/issue48951.go2
@@ -5,17 +5,17 @@
package p
type (
- A1 /* ERROR illegal cycle */ [P any] [10]A1[P]
- A2 /* ERROR illegal cycle */ [P any] [10]A2[*P]
+ A1[P any] [10]A1 /* ERROR illegal cycle */ [P]
+ A2[P any] [10]A2 /* ERROR illegal cycle */ [*P]
A3[P any] [10]*A3[P]
L1[P any] []L1[P]
- S1 /* ERROR illegal cycle */ [P any] struct{ f S1[P] }
- S2 /* ERROR illegal cycle */ [P any] struct{ f S2[*P] } // like example in issue
+ S1[P any] struct{ f S1 /* ERROR illegal cycle */ [P] }
+ S2[P any] struct{ f S2 /* ERROR illegal cycle */ [*P] } // like example in issue
S3[P any] struct{ f *S3[P] }
- I1 /* ERROR illegal cycle */ [P any] interface{ I1[P] }
- I2 /* ERROR illegal cycle */ [P any] interface{ I2[*P] }
+ I1[P any] interface{ I1 /* ERROR illegal cycle */ [P] }
+ I2[P any] interface{ I2 /* ERROR illegal cycle */ [*P] }
I3[P any] interface{ *I3 /* ERROR interface contains type constraints */ [P] }
)
diff --git a/src/go/types/testdata/fixedbugs/issue48962.go2 b/src/go/types/testdata/fixedbugs/issue48962.go2
new file mode 100644
index 0000000..4270da1
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue48962.go2
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T0[P any] struct {
+ f P
+}
+
+type T1 /* ERROR illegal cycle */ struct {
+ _ T0[T1]
+}
diff --git a/src/go/types/testdata/fixedbugs/issue49005.go b/src/go/types/testdata/fixedbugs/issue49005.go
new file mode 100644
index 0000000..7083dc9
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue49005.go
@@ -0,0 +1,31 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T1 interface{ M() }
+
+func F1() T1
+
+var _ = F1().(*X1 /* ERROR undeclared name: X1 */)
+
+func _() {
+ switch F1().(type) {
+ case *X1 /* ERROR undeclared name: X1 */ :
+ }
+}
+
+type T2 interface{ M() }
+
+func F2() T2
+
+var _ = F2 /* ERROR impossible type assertion: F2\(\)\.\(\*X2\)\n\t\*X2 does not implement T2 \(missing method M\) */ ().(*X2)
+
+type X2 struct{}
+
+func _() {
+ switch F2().(type) {
+ case * /* ERROR impossible type switch case: \*X2\n\tF2\(\) \(value of type T2\) cannot have dynamic type \*X2 \(missing method M\) */ X2:
+ }
+}
diff --git a/src/go/types/testdata/fixedbugs/issue49043.go2 b/src/go/types/testdata/fixedbugs/issue49043.go2
index c37b0f1..a360457 100644
--- a/src/go/types/testdata/fixedbugs/issue49043.go2
+++ b/src/go/types/testdata/fixedbugs/issue49043.go2
@@ -6,13 +6,13 @@
// The example from the issue.
type (
- N /* ERROR illegal cycle */ [P any] M[P]
- M[P any] N[P]
+ N[P any] M /* ERROR illegal cycle */ [P]
+ M[P any] N /* ERROR illegal cycle */ [P]
)
// A slightly more complicated case.
type (
- A /* ERROR illegal cycle */ [P any] B[P]
+ A[P any] B /* ERROR illegal cycle */ [P]
B[P any] C[P]
C[P any] A[P]
)
diff --git a/src/go/types/testdata/fixedbugs/issue49112.go2 b/src/go/types/testdata/fixedbugs/issue49112.go2
new file mode 100644
index 0000000..61b757c
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue49112.go2
@@ -0,0 +1,15 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f[P int](P) {}
+
+func _() {
+ _ = f[int]
+ _ = f[[ /* ERROR \[\]int does not implement int */ ]int]
+
+ f(0)
+ f/* ERROR \[\]int does not implement int */ ([]int{})
+}
diff --git a/src/go/types/testdata/fixedbugs/issue49482.go2 b/src/go/types/testdata/fixedbugs/issue49482.go2
new file mode 100644
index 0000000..4c6579e
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue49482.go2
@@ -0,0 +1,28 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+// The following is OK, per the special handling for type literals discussed in issue #49482.
+type _[P *struct{}] struct{}
+type _[P *int,] int
+type _[P (*int),] int
+
+const P = 2 // declare P to avoid noisy 'undeclared name' errors below.
+
+// The following parse as invalid array types.
+type _[P *int /* ERROR "int \(type\) is not an expression" */ ] int
+type _[P /* ERROR non-function P */ (*int)] int
+
+// The following should be parsed as a generic type, but is instead parsed as an array type.
+type _[P *struct /* ERROR "expected expression" */ {}| int /* ERROR "not an expression" */ ] struct{}
+
+// The following fails to parse, due to the '~'
+type _[P *struct /* ERROR "expected expression" */ {}|~ /* ERROR "expected operand" */ int] struct{}
+
+// This is fragile: 'var' synchronizes the parser, and we absorb the rest of the errors.
+var /* ERROR "expected ']'" */ _ /* ERROR "value or type" */
diff --git a/src/go/types/testdata/fixedbugs/issue49541.go2 b/src/go/types/testdata/fixedbugs/issue49541.go2
new file mode 100644
index 0000000..c8499c1
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue49541.go2
@@ -0,0 +1,45 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type S[A, B any] struct {
+ f int
+}
+
+func (S[A, B]) m() {}
+
+// TODO(gri): with type-type inference enabled we should only report one error
+// below. See issue #50588.
+
+func _[A any](s S /* ERROR got 1 arguments but 2 type parameters */ [A]) {
+ // we should see no follow-on errors below
+ s.f = 1
+ s.m()
+}
+
+// another test case from the issue
+
+func _() {
+ X(Interface[*F /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
+}
+
+func X[Q Qer](fs Interface[Q]) {
+}
+
+type Impl struct{}
+
+func (Impl) M() {}
+
+type Interface[Q Qer] interface {
+ M()
+}
+
+type Qer interface {
+ Q()
+}
+
+type F[A, B any] struct{}
+
+func (f *F[A, B]) Q() {}
diff --git a/src/go/types/testdata/fixedbugs/issue49579.go2 b/src/go/types/testdata/fixedbugs/issue49579.go2
index 9e20ae5..07748bd 100644
--- a/src/go/types/testdata/fixedbugs/issue49579.go2
+++ b/src/go/types/testdata/fixedbugs/issue49579.go2
@@ -9,7 +9,7 @@
}
func G[F any]() I[any] {
- return g /* ERROR "missing method Q \(Q has pointer receiver\)" */ [F]{}
+ return g /* ERROR cannot use \(g\[F\] literal\) .* as I\[any\] value in return statement: g\[F\] does not implement I\[any\] \(method Q has pointer receiver\) */ [F]{}
}
type g[F any] struct{}
diff --git a/src/go/types/testdata/fixedbugs/issue49602.go2 b/src/go/types/testdata/fixedbugs/issue49602.go2
new file mode 100644
index 0000000..208501f
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue49602.go2
@@ -0,0 +1,19 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type M interface {
+ m()
+}
+
+type C interface {
+ comparable
+}
+
+type _ interface {
+ int | M // ERROR cannot use p\.M in union \(p\.M contains methods\)
+ int | comparable // ERROR cannot use comparable in union
+ int | C // ERROR cannot use p\.C in union \(p\.C embeds comparable\)
+}
diff --git a/src/go/types/testdata/fixedbugs/issue49705.go2 b/src/go/types/testdata/fixedbugs/issue49705.go2
index 2b991b8..5b5fba2 100644
--- a/src/go/types/testdata/fixedbugs/issue49705.go2
+++ b/src/go/types/testdata/fixedbugs/issue49705.go2
@@ -4,8 +4,11 @@
package p
-import "constraints"
+type Integer interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
+}
-func shl[I constraints.Integer](n int) I {
+func shl[I Integer](n int) I {
return 1 << n
}
diff --git a/src/go/types/testdata/fixedbugs/issue49735.go2 b/src/go/types/testdata/fixedbugs/issue49735.go2
new file mode 100644
index 0000000..5087022
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue49735.go2
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[P1 any, P2 ~byte](s1 P1, s2 P2) {
+ _ = append(nil /* ERROR first argument to append must be a slice; have untyped nil */ , 0)
+ _ = append(s1 /* ERROR s1 .* has no core type */ , 0)
+ _ = append(s2 /* ERROR s2 .* has core type byte */ , 0)
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50259.go2 b/src/go/types/testdata/fixedbugs/issue50259.go2
new file mode 100644
index 0000000..6df8c64
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50259.go2
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var x T[B]
+
+type T[_ any] struct{}
+type A T[B]
+type B = T[A]
+
+// test case from issue
+
+var v Box[Step]
+type Box[T any] struct{}
+type Step = Box[StepBox]
+type StepBox Box[Step]
diff --git a/src/go/types/testdata/fixedbugs/issue50276.go2 b/src/go/types/testdata/fixedbugs/issue50276.go2
new file mode 100644
index 0000000..97e477e
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50276.go2
@@ -0,0 +1,39 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// simplified test case
+
+type transform[T any] struct{}
+type pair[S any] struct {}
+
+var _ transform[step]
+
+type box transform[step]
+type step = pair[box]
+
+// test case from issue
+
+type Transform[T any] struct{ hold T }
+type Pair[S, T any] struct {
+ First S
+ Second T
+}
+
+var first Transform[Step]
+
+// This line doesn't use the Step alias, and it compiles fine if you uncomment it.
+var second Transform[Pair[Box, interface{}]]
+
+type Box *Transform[Step]
+
+// This line is the same as the `first` line, but it comes after the Box declaration and
+// does not break the compile.
+var third Transform[Step]
+
+type Step = Pair[Box, interface{}]
+
+// This line also does not break the compile
+var fourth Transform[Step]
diff --git a/src/go/types/testdata/fixedbugs/issue50281.go2 b/src/go/types/testdata/fixedbugs/issue50281.go2
new file mode 100644
index 0000000..f333e81
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50281.go2
@@ -0,0 +1,26 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[S string | []byte](s S) {
+ var buf []byte
+ _ = append(buf, s...)
+}
+
+func _[S ~string | ~[]byte](s S) {
+ var buf []byte
+ _ = append(buf, s...)
+}
+
+// test case from issue
+
+type byteseq interface {
+ string | []byte
+}
+
+// This should allow to eliminate the two functions above.
+func AppendByteString[source byteseq](buf []byte, s source) []byte {
+ return append(buf, s[1:6]...)
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/src/go/types/testdata/fixedbugs/issue50321.go2
similarity index 65%
copy from src/cmd/compile/internal/types2/types_test.go
copy to src/go/types/testdata/fixedbugs/issue50321.go2
index 11dca0b..199e66e 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/src/go/types/testdata/fixedbugs/issue50321.go2
@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
+package p
-func init() {
- acceptMethodTypeParams = true
+func Ln[A A /* ERROR cannot use a type parameter as constraint */ ](p A) {
}
diff --git a/src/go/types/testdata/fixedbugs/issue50417.go2 b/src/go/types/testdata/fixedbugs/issue50417.go2
new file mode 100644
index 0000000..2caef1b
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50417.go2
@@ -0,0 +1,68 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
+package p
+
+type Sf struct {
+ f int
+}
+
+func f0[P Sf](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+}
+
+func f0t[P ~struct{f int}](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+}
+
+var _ = f0[Sf]
+var _ = f0t[Sf]
+
+var _ = f0[Sm /* ERROR does not implement */ ]
+var _ = f0t[Sm /* ERROR does not implement */ ]
+
+func f1[P interface{ Sf; m() }](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+ p.m()
+}
+
+var _ = f1[Sf /* ERROR missing method m */ ]
+var _ = f1[Sm /* ERROR does not implement */ ]
+
+type Sm struct {}
+
+func (Sm) m() {}
+
+type Sfm struct {
+ f int
+}
+
+func (Sfm) m() {}
+
+func f2[P interface{ Sfm; m() }](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+ p.m()
+}
+
+var _ = f2[Sfm]
+
+// special case: core type is a named pointer type
+
+type PSfm *Sfm
+
+func f3[P interface{ PSfm }](p P) {
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
+ p.m /* ERROR type P has no field or method m */ ()
+}
+
+var _ = f3[PSfm]
diff --git a/src/go/types/testdata/fixedbugs/issue50426.go2 b/src/go/types/testdata/fixedbugs/issue50426.go2
new file mode 100644
index 0000000..17ec0ce
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50426.go2
@@ -0,0 +1,44 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type A1 [2]uint64
+type A2 [2]uint64
+
+func (a A1) m() A1 { return a }
+func (a A2) m() A2 { return a }
+
+func f[B any, T interface {
+ A1 | A2
+ m() T
+}](v T) {
+}
+
+func _() {
+ var v A2
+ // Use function type inference to infer type A2 for T.
+ // Don't use constraint type inference before function
+ // type inference for typed arguments, otherwise it would
+ // infer type [2]uint64 for T which doesn't have method m
+ // (was the bug).
+ f[int](v)
+}
+
+// Keep using constraint type inference before function type
+// inference for untyped arguments so we infer type float64
+// for E below, and not int (which would not work).
+func g[S ~[]E, E any](S, E) {}
+
+func _() {
+ var s []float64
+ g[[]float64](s, 0)
+}
+
+// Keep using constraint type inference after function
+// type inference for untyped arguments so we infer
+// missing type arguments for which we only have the
+// untyped arguments as starting point.
+func h[E any, R []E](v E) R { return R{v} }
+func _() []int { return h(0) }
diff --git a/src/go/types/testdata/fixedbugs/issue50427.go2 b/src/go/types/testdata/fixedbugs/issue50427.go2
new file mode 100644
index 0000000..d89d63e
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50427.go2
@@ -0,0 +1,23 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// The parser no longer parses type parameters for methods.
+// In the past, type checking the code below led to a crash (#50427).
+
+type T interface{ m[ /* ERROR "must have no type parameters" */ P any]() }
+
+func _(t T) {
+ var _ interface{ m[ /* ERROR "must have no type parameters" */ P any](); n() } = t /* ERROR "does not implement" */
+}
+
+type S struct{}
+
+func (S) m[ /* ERROR "must have no type parameters" */ P any]() {}
+
+func _(s S) {
+ var _ interface{ m[ /* ERROR "must have no type parameters" */ P any](); n() } = s /* ERROR "does not implement" */
+
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50450.go2 b/src/go/types/testdata/fixedbugs/issue50450.go2
new file mode 100644
index 0000000..bae3111
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50450.go2
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type S struct{}
+
+func f[P S]() {}
+
+var _ = f[S]
diff --git a/src/go/types/testdata/fixedbugs/issue50516.go2 b/src/go/types/testdata/fixedbugs/issue50516.go2
new file mode 100644
index 0000000..f73015e
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50516.go2
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[P struct{ f int }](x P) {
+ _ = x.g // ERROR type P has no field or method g
+}
+
+func _[P struct{ f int } | struct{ g int }](x P) {
+ _ = x.g // ERROR type P has no field or method g
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50646.go2 b/src/go/types/testdata/fixedbugs/issue50646.go2
new file mode 100644
index 0000000..3bdba11
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50646.go2
@@ -0,0 +1,26 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f1[_ comparable]() {}
+func f2[_ interface{ comparable }]() {}
+
+type T interface{ m() }
+
+func _[P comparable, Q ~int, R any]() {
+ _ = f1[int]
+ _ = f1[T /* ERROR T does not implement comparable */ ]
+ _ = f1[any /* ERROR any does not implement comparable */ ]
+ _ = f1[P]
+ _ = f1[Q]
+ _ = f1[R /* ERROR R does not implement comparable */]
+
+ _ = f2[int]
+ _ = f2[T /* ERROR T does not implement comparable */ ]
+ _ = f2[any /* ERROR any does not implement comparable */ ]
+ _ = f2[P]
+ _ = f2[Q]
+ _ = f2[R /* ERROR R does not implement comparable */]
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50755.go2 b/src/go/types/testdata/fixedbugs/issue50755.go2
new file mode 100644
index 0000000..afc7b24
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50755.go2
@@ -0,0 +1,47 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// The core type of M2 unifies with the type of m1
+// during function argument type inference.
+// M2's constraint is unnamed.
+func f1[K1 comparable, E1 any](m1 map[K1]E1) {}
+
+func f2[M2 map[string]int](m2 M2) {
+ f1(m2)
+}
+
+// The core type of M3 unifies with the type of m1
+// during function argument type inference.
+// M3's constraint is named.
+type Map3 map[string]int
+
+func f3[M3 Map3](m3 M3) {
+ f1(m3)
+}
+
+// The core type of M5 unifies with the core type of M4
+// during constraint type inference.
+func f4[M4 map[K4]int, K4 comparable](m4 M4) {}
+
+func f5[M5 map[K5]int, K5 comparable](m5 M5) {
+ f4(m5)
+}
+
+// test case from issue
+
+func Copy[MC ~map[KC]VC, KC comparable, VC any](dst, src MC) {
+ for k, v := range src {
+ dst[k] = v
+ }
+}
+
+func Merge[MM ~map[KM]VM, KM comparable, VM any](ms ...MM) MM {
+ result := MM{}
+ for _, m := range ms {
+ Copy(result, m)
+ }
+ return result
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50779.go2 b/src/go/types/testdata/fixedbugs/issue50779.go2
new file mode 100644
index 0000000..fe68c28
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50779.go2
@@ -0,0 +1,23 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type AC interface {
+ C
+}
+
+type ST []int
+
+type R[S any, P any] struct{}
+
+type SR = R[SS, ST]
+
+type SS interface {
+ NSR(any) *SR // ERROR invalid use of type alias SR in recursive type
+}
+
+type C interface {
+ NSR(any) *SR
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50782.go2 b/src/go/types/testdata/fixedbugs/issue50782.go2
new file mode 100644
index 0000000..fd1ab11
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50782.go2
@@ -0,0 +1,47 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
+package p
+
+// The first example from the issue.
+type Numeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64
+}
+
+// numericAbs matches numeric types with an Abs method.
+type numericAbs[T Numeric] interface {
+ ~struct{ Value T }
+ Abs() T
+}
+
+// AbsDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
+ // Field accesses are not permitted for now. Keep an error so
+ // we can find and fix this code once the situation changes.
+ return a.Value // ERROR a\.Value undefined
+ // TODO: The error below should probably be positioned on the '-'.
+ // d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
+ // return d.Abs()
+}
+
+// The second example from the issue.
+type T[P int] struct{ f P }
+
+func _[P T[P /* ERROR "P does not implement int" */ ]]() {}
+
+// Additional tests
+func _[P T[T /* ERROR "T\[P\] does not implement int" */ [P /* ERROR "P does not implement int" */ ]]]() {}
+func _[P T[Q /* ERROR "Q does not implement int" */ ], Q T[P /* ERROR "P does not implement int" */ ]]() {}
+func _[P T[Q], Q int]() {}
+
+type C[P comparable] struct{ f P }
+func _[P C[C[P]]]() {}
+func _[P C[C /* ERROR "C\[Q\] does not implement comparable" */ [Q /* ERROR "Q does not implement comparable" */]], Q func()]() {}
+func _[P [10]C[P]]() {}
+func _[P struct{ f C[C[P]]}]() {}
diff --git a/src/go/types/testdata/fixedbugs/issue50816.go2 b/src/go/types/testdata/fixedbugs/issue50816.go2
new file mode 100644
index 0000000..e7e31d9
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50816.go2
@@ -0,0 +1,23 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkg
+
+type I interface {
+ Foo()
+}
+
+type T1 struct{}
+
+func (T1) foo() {}
+
+type T2 struct{}
+
+func (T2) foo() string { return "" }
+
+func _() {
+ var i I
+ _ = i /* ERROR impossible type assertion: i\.\(T1\)\n\tT1 does not implement I \(missing method Foo\)\n\t\thave foo\(\)\n\t\twant Foo\(\) */ .(T1)
+ _ = i /* ERROR impossible type assertion: i\.\(T2\)\n\tT2 does not implement I \(missing method Foo\)\n\t\thave foo\(\) string\n\t\twant Foo\(\) */ .(T2)
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50833.go2 b/src/go/types/testdata/fixedbugs/issue50833.go2
new file mode 100644
index 0000000..e912e4d
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50833.go2
@@ -0,0 +1,16 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type (
+ S struct{ f int }
+ PS *S
+)
+
+func a() []*S { return []*S{{f: 1}} }
+func b() []PS { return []PS{{f: 1}} }
+
+func c[P *S]() []P { return []P{{f: 1}} }
+func d[P PS]() []P { return []P{{f: 1}} }
diff --git a/src/go/types/testdata/fixedbugs/issue50912.go2 b/src/go/types/testdata/fixedbugs/issue50912.go2
new file mode 100644
index 0000000..f161925
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50912.go2
@@ -0,0 +1,19 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func Real[P ~complex128](x P) {
+ _ = real(x /* ERROR not supported */ )
+}
+
+func Imag[P ~complex128](x P) {
+ _ = imag(x /* ERROR not supported */ )
+}
+
+func Complex[P ~float64](x P) {
+ _ = complex(x /* ERROR not supported */ , 0)
+ _ = complex(0 /* ERROR not supported */ , x)
+ _ = complex(x /* ERROR not supported */ , x)
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50918.go b/src/go/types/testdata/fixedbugs/issue50918.go
new file mode 100644
index 0000000..41604b8
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50918.go
@@ -0,0 +1,21 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type thing1 struct {
+ things []string
+}
+
+type thing2 struct {
+ things []thing1
+}
+
+func _() {
+ var a1, b1 thing1
+ _ = a1 /* ERROR struct containing \[\]string cannot be compared */ == b1
+
+ var a2, b2 thing2
+ _ = a2 /* ERROR struct containing \[\]thing1 cannot be compared */ == b2
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50929.go2 b/src/go/types/testdata/fixedbugs/issue50929.go2
new file mode 100644
index 0000000..3629ecf
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50929.go2
@@ -0,0 +1,68 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+import "fmt"
+
+type F[A, B any] int
+
+func G[A, B any](F[A, B]) {
+}
+
+func _() {
+ // TODO(gri) only report one error below (issue #50932)
+ var x F /* ERROR got 1 arguments but 2 type parameters */ [int]
+ G(x /* ERROR does not match */)
+}
+
+// test case from issue
+// (lots of errors but doesn't crash anymore)
+
+type RC[G any, RG any] interface {
+ ~[]RG
+}
+
+type RG[G any] struct{}
+
+type RSC[G any] []*RG[G]
+
+type M[Rc RC[G, RG], G any, RG any] struct {
+ Fn func(Rc)
+}
+
+type NFn[Rc RC[G, RG], G any, RG any] func(Rc)
+
+func NC[Rc RC[G, RG], G any, RG any](nFn NFn[Rc, G, RG]) {
+ var empty Rc
+ nFn(empty)
+}
+
+func NSG[G any](c RSC[G]) {
+ fmt.Println(c)
+}
+
+func MMD[Rc RC /* ERROR got 1 arguments */ [RG], RG any, G any]() M /* ERROR got 2 arguments */ [Rc, RG] {
+
+ var nFn NFn /* ERROR got 2 arguments */ [Rc, RG]
+
+ var empty Rc
+ switch any(empty).(type) {
+ case BC /* ERROR undeclared name: BC */ :
+
+ case RSC[G]:
+ nFn = NSG /* ERROR cannot use NSG\[G\] */ [G]
+ }
+
+ return M /* ERROR got 2 arguments */ [Rc, RG]{
+ Fn: func(rc Rc) {
+ NC(nFn /* ERROR does not match */ )
+ },
+ }
+
+ return M /* ERROR got 2 arguments */ [Rc, RG]{}
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50965.go b/src/go/types/testdata/fixedbugs/issue50965.go
new file mode 100644
index 0000000..bf2dcc9
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue50965.go
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _(x int, c string) {
+ switch x {
+ case c /* ERROR invalid case c in switch on x \(mismatched types string and int\) */ :
+ }
+}
+
+func _(x, c []int) {
+ switch x {
+ case c /* ERROR invalid case c in switch on x \(slice can only be compared to nil\) */ :
+ }
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51048.go2 b/src/go/types/testdata/fixedbugs/issue51048.go2
new file mode 100644
index 0000000..5830837
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51048.go2
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[P int]() {
+ _ = f[P]
+}
+
+func f[T int]() {}
diff --git a/src/go/types/testdata/fixedbugs/issue51145.go b/src/go/types/testdata/fixedbugs/issue51145.go
new file mode 100644
index 0000000..b84391d
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51145.go
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "fmt"
+
+type (
+ _ [fmt /* ERROR invalid array length fmt */ ]int
+ _ [float64 /* ERROR invalid array length float64 */ ]int
+ _ [f /* ERROR invalid array length f */ ]int
+ _ [nil /* ERROR invalid array length nil */ ]int
+)
+
+func f()
+
+var _ fmt.Stringer // use fmt
diff --git a/src/go/types/testdata/fixedbugs/issue51158.go2 b/src/go/types/testdata/fixedbugs/issue51158.go2
new file mode 100644
index 0000000..3edc505
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51158.go2
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Type checking the following code should not cause an infinite recursion.
+func f[M map[K]int, K comparable](m M) {
+ f(m)
+}
+
+// Equivalent code using mutual recursion.
+func f1[M map[K]int, K comparable](m M) {
+ f2(m)
+}
+func f2[M map[K]int, K comparable](m M) {
+ f1(m)
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51229.go2 b/src/go/types/testdata/fixedbugs/issue51229.go2
new file mode 100644
index 0000000..808b647
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51229.go2
@@ -0,0 +1,164 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Constraint type inference should be independent of the
+// ordering of the type parameter declarations. Try all
+// permutations in the test case below.
+// Permutations produced by https://go.dev/play/p/PHcZNGJTEBZ.
+
+func f00[S1 ~[]E1, S2 ~[]E2, E1 ~byte, E2 ~byte](S1, S2) {}
+func f01[S2 ~[]E2, S1 ~[]E1, E1 ~byte, E2 ~byte](S1, S2) {}
+func f02[E1 ~byte, S1 ~[]E1, S2 ~[]E2, E2 ~byte](S1, S2) {}
+func f03[S1 ~[]E1, E1 ~byte, S2 ~[]E2, E2 ~byte](S1, S2) {}
+func f04[S2 ~[]E2, E1 ~byte, S1 ~[]E1, E2 ~byte](S1, S2) {}
+func f05[E1 ~byte, S2 ~[]E2, S1 ~[]E1, E2 ~byte](S1, S2) {}
+func f06[E2 ~byte, S2 ~[]E2, S1 ~[]E1, E1 ~byte](S1, S2) {}
+func f07[S2 ~[]E2, E2 ~byte, S1 ~[]E1, E1 ~byte](S1, S2) {}
+func f08[S1 ~[]E1, E2 ~byte, S2 ~[]E2, E1 ~byte](S1, S2) {}
+func f09[E2 ~byte, S1 ~[]E1, S2 ~[]E2, E1 ~byte](S1, S2) {}
+func f10[S2 ~[]E2, S1 ~[]E1, E2 ~byte, E1 ~byte](S1, S2) {}
+func f11[S1 ~[]E1, S2 ~[]E2, E2 ~byte, E1 ~byte](S1, S2) {}
+func f12[S1 ~[]E1, E1 ~byte, E2 ~byte, S2 ~[]E2](S1, S2) {}
+func f13[E1 ~byte, S1 ~[]E1, E2 ~byte, S2 ~[]E2](S1, S2) {}
+func f14[E2 ~byte, S1 ~[]E1, E1 ~byte, S2 ~[]E2](S1, S2) {}
+func f15[S1 ~[]E1, E2 ~byte, E1 ~byte, S2 ~[]E2](S1, S2) {}
+func f16[E1 ~byte, E2 ~byte, S1 ~[]E1, S2 ~[]E2](S1, S2) {}
+func f17[E2 ~byte, E1 ~byte, S1 ~[]E1, S2 ~[]E2](S1, S2) {}
+func f18[E2 ~byte, E1 ~byte, S2 ~[]E2, S1 ~[]E1](S1, S2) {}
+func f19[E1 ~byte, E2 ~byte, S2 ~[]E2, S1 ~[]E1](S1, S2) {}
+func f20[S2 ~[]E2, E2 ~byte, E1 ~byte, S1 ~[]E1](S1, S2) {}
+func f21[E2 ~byte, S2 ~[]E2, E1 ~byte, S1 ~[]E1](S1, S2) {}
+func f22[E1 ~byte, S2 ~[]E2, E2 ~byte, S1 ~[]E1](S1, S2) {}
+func f23[S2 ~[]E2, E1 ~byte, E2 ~byte, S1 ~[]E1](S1, S2) {}
+
+type myByte byte
+
+func _(a []byte, b []myByte) {
+ f00(a, b)
+ f01(a, b)
+ f02(a, b)
+ f03(a, b)
+ f04(a, b)
+ f05(a, b)
+ f06(a, b)
+ f07(a, b)
+ f08(a, b)
+ f09(a, b)
+ f10(a, b)
+ f11(a, b)
+ f12(a, b)
+ f13(a, b)
+ f14(a, b)
+ f15(a, b)
+ f16(a, b)
+ f17(a, b)
+ f18(a, b)
+ f19(a, b)
+ f20(a, b)
+ f21(a, b)
+ f22(a, b)
+ f23(a, b)
+}
+
+// Constraint type inference may have to iterate.
+// Again, the order of the type parameters shouldn't matter.
+
+func g0[S ~[]E, M ~map[string]S, E any](m M) {}
+func g1[M ~map[string]S, S ~[]E, E any](m M) {}
+func g2[E any, S ~[]E, M ~map[string]S](m M) {}
+func g3[S ~[]E, E any, M ~map[string]S](m M) {}
+func g4[M ~map[string]S, E any, S ~[]E](m M) {}
+func g5[E any, M ~map[string]S, S ~[]E](m M) {}
+
+func _(m map[string][]byte) {
+ g0(m)
+ g1(m)
+ g2(m)
+ g3(m)
+ g4(m)
+ g5(m)
+}
+
+// Worst-case scenario.
+// There are 10 unknown type parameters. In each iteration of
+// constraint type inference we infer one more, from right to left.
+// Each iteration looks repeatedly at all 11 type parameters,
+// requiring a total of 10*11 = 110 iterations with the current
+// implementation. Pathological case.
+
+func h[K any, J ~*K, I ~*J, H ~*I, G ~*H, F ~*G, E ~*F, D ~*E, C ~*D, B ~*C, A ~*B](x A) {}
+
+func _(x **********int) {
+ h(x)
+}
+
+// Examples with channel constraints and tilde.
+
+func ch1[P chan<- int]() (_ P) { return } // core(P) == chan<- int (single type, no tilde)
+func ch2[P ~chan int]() { return } // core(P) == ~chan<- int (tilde)
+func ch3[P chan E, E any](E) { return } // core(P) == chan<- E (single type, no tilde)
+func ch4[P chan E | ~chan<- E, E any](E) { return } // core(P) == ~chan<- E (tilde)
+func ch5[P chan int | chan<- int]() { return } // core(P) == chan<- int (not a single type)
+
+func _() {
+ // P can be inferred as there's a single specific type and no tilde.
+ var _ chan int = ch1 /* ERROR cannot use ch1.*value of type chan<- int */ ()
+ var _ chan<- int = ch1()
+
+ // P cannot be inferred as there's a tilde.
+ ch2 /* ERROR cannot infer P */ ()
+ type myChan chan int
+ ch2[myChan]()
+
+ // P can be inferred as there's a single specific type and no tilde.
+ var e int
+ ch3(e)
+
+ // P cannot be inferred as there's more than one specific type and a tilde.
+ ch4 /* ERROR cannot infer P */ (e)
+ _ = ch4[chan int]
+
+ // P cannot be inferred as there's more than one specific type.
+ ch5 /* ERROR cannot infer P */ ()
+ ch5[chan<- int]()
+}
+
+// test case from issue
+
+func equal[M1 ~map[K1]V1, M2 ~map[K2]V2, K1, K2 ~uint32, V1, V2 ~string](m1 M1, m2 M2) bool {
+ if len(m1) != len(m2) {
+ return false
+ }
+ for k, v1 := range m1 {
+ if v2, ok := m2[K2(k)]; !ok || V2(v1) != v2 {
+ return false
+ }
+ }
+ return true
+}
+
+func equalFixed[K1, K2 ~uint32, V1, V2 ~string](m1 map[K1]V1, m2 map[K2]V2) bool {
+ if len(m1) != len(m2) {
+ return false
+ }
+ for k, v1 := range m1 {
+ if v2, ok := m2[K2(k)]; !ok || v1 != V1(v2) {
+ return false
+ }
+ }
+ return true
+}
+
+type (
+ someNumericID uint32
+ someStringID string
+)
+
+func _() {
+ foo := map[uint32]string{10: "bar"}
+ bar := map[someNumericID]someStringID{10: "bar"}
+ equal(foo, bar)
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51232.go2 b/src/go/types/testdata/fixedbugs/issue51232.go2
new file mode 100644
index 0000000..3fa6a05
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51232.go2
@@ -0,0 +1,30 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type RC[RG any] interface {
+ ~[]RG
+}
+
+type Fn[RCT RC[RG], RG any] func(RCT)
+
+type F[RCT RC[RG], RG any] interface {
+ Fn() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+type concreteF[RCT RC[RG], RG any] struct {
+ makeFn func() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR got 1 arguments */ [RCT] {
+ return c.makeFn()
+}
+
+func NewConcrete[RCT RC[RG], RG any](Rc RCT) F /* ERROR got 1 arguments */ [RCT] {
+ // TODO(rfindley): eliminate the duplicate error below.
+ return & /* ERROR cannot use .* as F\[RCT\] */ concreteF /* ERROR got 1 arguments */ [RCT]{
+ makeFn: nil,
+ }
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51233.go2 b/src/go/types/testdata/fixedbugs/issue51233.go2
new file mode 100644
index 0000000..9c15028
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51233.go2
@@ -0,0 +1,27 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// As of issue #51527, type-type inference has been disabled.
+
+type RC[RG any] interface {
+ ~[]RG
+}
+
+type Fn[RCT RC[RG], RG any] func(RCT)
+
+type FFn[RCT RC[RG], RG any] func() Fn /* ERROR got 1 arguments */ [RCT]
+
+type F[RCT RC[RG], RG any] interface {
+ Fn() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+type concreteF[RCT RC[RG], RG any] struct {
+ makeFn FFn /* ERROR got 1 arguments */ [RCT]
+}
+
+func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR got 1 arguments */ [RCT] {
+ return c.makeFn()
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51257.go2 b/src/go/types/testdata/fixedbugs/issue51257.go2
new file mode 100644
index 0000000..8a3eb32
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51257.go2
@@ -0,0 +1,46 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f[_ comparable]() {}
+
+type S1 struct{ x int }
+type S2 struct{ x any }
+type S3 struct{ x [10]interface{ m() } }
+
+func _[P1 comparable, P2 S2]() {
+ _ = f[S1]
+ _ = f[S2 /* ERROR S2 does not implement comparable */ ]
+ _ = f[S3 /* ERROR S3 does not implement comparable */ ]
+
+ type L1 struct { x P1 }
+ type L2 struct { x P2 }
+ _ = f[L1]
+ _ = f[L2 /* ERROR L2 does not implement comparable */ ]
+}
+
+
+// example from issue
+
+type Set[T comparable] map[T]struct{}
+
+func NewSetFromSlice[T comparable](items []T) *Set[T] {
+ s := Set[T]{}
+
+ for _, item := range items {
+ s[item] = struct{}{}
+ }
+
+ return &s
+}
+
+type T struct{ x any }
+
+func main() {
+ NewSetFromSlice /* ERROR T does not implement comparable */ ([]T{
+ {"foo"},
+ {5},
+ })
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51335.go2 b/src/go/types/testdata/fixedbugs/issue51335.go2
new file mode 100644
index 0000000..0b5a1af
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51335.go2
@@ -0,0 +1,16 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type S1 struct{}
+type S2 struct{}
+
+func _[P *S1|*S2]() {
+ _= []P{{ /* ERROR invalid composite literal element type P: no core type */ }}
+}
+
+func _[P *S1|S1]() {
+ _= []P{{ /* ERROR invalid composite literal element type P: no core type */ }}
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51339.go2 b/src/go/types/testdata/fixedbugs/issue51339.go2
new file mode 100644
index 0000000..38f8610
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51339.go2
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+type T[P any, B *P] struct{}
+
+func (T /* ERROR cannot use generic type */ ) m0() {}
+
+// TODO(rfindley): eliminate the duplicate errors here.
+func (/* ERROR got 1 type parameter, but receiver base type declares 2 */ T /* ERROR got 1 arguments but 2 type parameters */ [_]) m1() {}
+func (T[_, _]) m2() {}
+// TODO(gri) this error is unfortunate (issue #51343)
+func (T /* ERROR got 3 arguments but 2 type parameters */ [_, _, _]) m3() {}
diff --git a/src/go/types/testdata/fixedbugs/issue51360.go b/src/go/types/testdata/fixedbugs/issue51360.go
new file mode 100644
index 0000000..fe3de04
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51360.go
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _() {
+ len.Println /* ERROR cannot select on len */
+ len.Println /* ERROR cannot select on len */ ()
+ _ = len.Println /* ERROR cannot select on len */
+ _ = len /* ERROR cannot index len */ [0]
+ _ = *len /* ERROR cannot indirect len */
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51376.go2 b/src/go/types/testdata/fixedbugs/issue51376.go2
new file mode 100644
index 0000000..d51607b
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51376.go2
@@ -0,0 +1,24 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type Map map[string]int
+
+func f[M ~map[K]V, K comparable, V any](M) {}
+func g[M map[K]V, K comparable, V any](M) {}
+
+func _[M1 ~map[K]V, M2 map[K]V, K comparable, V any]() {
+ var m1 M1
+ f(m1)
+ g /* ERROR M1 does not implement map\[K\]V */ (m1) // M1 has tilde
+
+ var m2 M2
+ f(m2)
+ g(m2) // M1 does not have tilde
+
+ var m3 Map
+ f(m3)
+ g /* ERROR Map does not implement map\[string\]int */ (m3) // M in g does not have tilde
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51386.go2 b/src/go/types/testdata/fixedbugs/issue51386.go2
new file mode 100644
index 0000000..ef62239
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51386.go2
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type myString string
+
+func _[P ~string | ~[]byte | ~[]rune]() {
+ _ = P("")
+ const s myString = ""
+ _ = P(s)
+}
+
+func _[P myString]() {
+ _ = P("")
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51437.go b/src/go/types/testdata/fixedbugs/issue51437.go
new file mode 100644
index 0000000..3762615
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51437.go
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct{}
+
+func (T) m() []int { return nil }
+
+func f(x T) {
+ for _, x := range func() []int {
+ return x.m() // x declared in parameter list of f
+ }() {
+ _ = x // x declared by range clause
+ }
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51472.go2 b/src/go/types/testdata/fixedbugs/issue51472.go2
new file mode 100644
index 0000000..3126770
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51472.go2
@@ -0,0 +1,54 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[T comparable](x T) {
+ _ = x == x
+}
+
+func _[T interface{interface{comparable}}](x T) {
+ _ = x == x
+}
+
+func _[T interface{comparable; interface{comparable}}](x T) {
+ _ = x == x
+}
+
+func _[T interface{comparable; ~int}](x T) {
+ _ = x == x
+}
+
+func _[T interface{comparable; ~[]byte}](x T) {
+ _ = x /* ERROR cannot compare */ == x
+}
+
+// TODO(gri) The error message here should be better. See issue #51525.
+func _[T interface{comparable; ~int; ~string}](x T) {
+ _ = x /* ERROR cannot compare */ == x
+}
+
+// TODO(gri) The error message here should be better. See issue #51525.
+func _[T interface{~int; ~string}](x T) {
+ _ = x /* ERROR cannot compare */ == x
+}
+
+func _[T interface{comparable; interface{~int}; interface{int|float64}}](x T) {
+ _ = x == x
+}
+
+func _[T interface{interface{comparable; ~int}; interface{~float64; comparable; m()}}](x T) {
+ _ = x /* ERROR cannot compare */ == x
+}
+
+// test case from issue
+
+func f[T interface{comparable; []byte|string}](x T) {
+ _ = x == x
+}
+
+func _(s []byte) {
+ f /* ERROR \[\]byte does not implement interface{comparable; \[\]byte\|string} */ (s)
+ _ = f[[ /* ERROR does not implement */ ]byte]
+}
diff --git a/src/go/types/testdata/fixedbugs/issue51509.go b/src/go/types/testdata/fixedbugs/issue51509.go
new file mode 100644
index 0000000..5ae4717
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51509.go
@@ -0,0 +1,7 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T /* ERROR illegal cycle */ T.x
diff --git a/src/go/types/testdata/fixedbugs/issue51578.go2 b/src/go/types/testdata/fixedbugs/issue51578.go2
new file mode 100644
index 0000000..5c204ba
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51578.go2
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = (*interface /* ERROR interface contains type constraints */ {int})(nil)
+
+// abbreviated test case from issue
+
+type TypeSet interface{ int | string }
+
+func _() {
+ f((*TypeSet /* ERROR interface contains type constraints */)(nil))
+}
+
+func f(any) {}
\ No newline at end of file
diff --git a/src/go/types/testdata/fixedbugs/issue51593.go2 b/src/go/types/testdata/fixedbugs/issue51593.go2
new file mode 100644
index 0000000..e06c39f
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51593.go2
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f[P interface{ m(R) }, R any]() {}
+
+type T = interface { m(int) }
+
+func _() {
+ _ = f /* ERROR cannot infer R */ [T] // don't crash in type inference
+}
diff --git a/src/go/types/testdata/manual.go2 b/src/go/types/testdata/manual.go2
index 25e6f22..a7caee9 100644
--- a/src/go/types/testdata/manual.go2
+++ b/src/go/types/testdata/manual.go2
@@ -1,4 +1,4 @@
-// Copyright 2021 The Go Authors. All rights reserved.
+// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/src/go/types/testdata/spec/comparisons.go2 b/src/go/types/testdata/spec/comparisons.go2
new file mode 100644
index 0000000..62c95d4
--- /dev/null
+++ b/src/go/types/testdata/spec/comparisons.go2
@@ -0,0 +1,120 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package comparisons
+
+type (
+ B int // basic type representative
+ A [10]func()
+ L []byte
+ S struct{ f []byte }
+ P *S
+ F func()
+ I interface{}
+ M map[string]int
+ C chan int
+)
+
+var (
+ b B
+ a A
+ l L
+ s S
+ p P
+ f F
+ i I
+ m M
+ c C
+)
+
+func _() {
+ _ = nil == nil // ERROR operator == not defined on untyped nil
+ _ = b == b
+ _ = a /* ERROR \[10\]func\(\) cannot be compared */ == a
+ _ = l /* ERROR slice can only be compared to nil */ == l
+ _ = s /* ERROR struct containing \[\]byte cannot be compared */ == s
+ _ = p == p
+ _ = f /* ERROR func can only be compared to nil */ == f
+ _ = i == i
+ _ = m /* ERROR map can only be compared to nil */ == m
+ _ = c == c
+
+ _ = b /* ERROR mismatched types */ == nil
+ _ = a /* ERROR mismatched types */ == nil
+ _ = l == nil
+ _ = s /* ERROR mismatched types */ == nil
+ _ = p == nil
+ _ = f == nil
+ _ = i == nil
+ _ = m == nil
+ _ = c == nil
+
+ _ = nil /* ERROR operator < not defined on untyped nil */ < nil
+ _ = b < b
+ _ = a /* ERROR operator < not defined on array */ < a
+ _ = l /* ERROR operator < not defined on slice */ < l
+ _ = s /* ERROR operator < not defined on struct */ < s
+ _ = p /* ERROR operator < not defined on pointer */ < p
+ _ = f /* ERROR operator < not defined on func */ < f
+ _ = i /* ERROR operator < not defined on interface */ < i
+ _ = m /* ERROR operator < not defined on map */ < m
+ _ = c /* ERROR operator < not defined on chan */ < c
+}
+
+func _[
+ B int,
+ A [10]func(),
+ L []byte,
+ S struct{ f []byte },
+ P *S,
+ F func(),
+ I interface{},
+ J comparable,
+ M map[string]int,
+ C chan int,
+] (
+ b B,
+ a A,
+ l L,
+ s S,
+ p P,
+ f F,
+ i I,
+ j J,
+ m M,
+ c C,
+) {
+ _ = b == b
+ _ = a /* ERROR type parameter A is not comparable with == */ == a
+ _ = l /* ERROR type parameter L is not comparable with == */ == l
+ _ = s /* ERROR type parameter S is not comparable with == */ == s
+ _ = p == p
+ _ = f /* ERROR type parameter F is not comparable with == */ == f
+ _ = i /* ERROR type parameter I is not comparable with == */ == i
+ _ = j == j
+ _ = m /* ERROR type parameter M is not comparable with == */ == m
+ _ = c == c
+
+ _ = b /* ERROR mismatched types */ == nil
+ _ = a /* ERROR mismatched types */ == nil
+ _ = l == nil
+ _ = s /* ERROR mismatched types */ == nil
+ _ = p == nil
+ _ = f == nil
+ _ = i /* ERROR mismatched types */ == nil
+ _ = j /* ERROR mismatched types */ == nil
+ _ = m == nil
+ _ = c == nil
+
+ _ = b < b
+ _ = a /* ERROR type parameter A is not comparable with < */ < a
+ _ = l /* ERROR type parameter L is not comparable with < */ < l
+ _ = s /* ERROR type parameter S is not comparable with < */ < s
+ _ = p /* ERROR type parameter P is not comparable with < */ < p
+ _ = f /* ERROR type parameter F is not comparable with < */ < f
+ _ = i /* ERROR type parameter I is not comparable with < */ < i
+ _ = j /* ERROR type parameter J is not comparable with < */ < j
+ _ = m /* ERROR type parameter M is not comparable with < */ < m
+ _ = c /* ERROR type parameter C is not comparable with < */ < c
+}
diff --git a/src/go/types/type.go b/src/go/types/type.go
index 3acb19c..1306375 100644
--- a/src/go/types/type.go
+++ b/src/go/types/type.go
@@ -7,9 +7,7 @@
// A Type represents a type of Go.
// All types implement the Type interface.
type Type interface {
- // Underlying returns the underlying type of a type
- // w/o following forwarding chains. Only used by
- // client packages.
+ // Underlying returns the underlying type of a type.
Underlying() Type
// String returns a string representation of a type.
@@ -27,13 +25,13 @@
return t.Underlying()
}
-// If t is not a type parameter, structuralType returns the underlying type.
-// If t is a type parameter, structuralType returns the single underlying
+// If t is not a type parameter, coreType returns the underlying type.
+// If t is a type parameter, coreType returns the single underlying
// type of all types in its type set if it exists, or nil otherwise. If the
// type set contains only unrestricted and restricted channel types (with
// identical element types), the single underlying type is the restricted
// channel type if the restrictions are always the same, or nil otherwise.
-func structuralType(t Type) Type {
+func coreType(t Type) Type {
tpar, _ := t.(*TypeParam)
if tpar == nil {
return under(t)
@@ -59,10 +57,10 @@
return nil
}
-// structuralString is like structuralType but also considers []byte
+// coreString is like coreType but also considers []byte
// and strings as identical. In this case, if successful and we saw
// a string, the result is of type (possibly untyped) string.
-func structuralString(t Type) Type {
+func coreString(t Type) Type {
tpar, _ := t.(*TypeParam)
if tpar == nil {
return under(t) // string or untyped string
diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go
index aea19e9..0f24135 100644
--- a/src/go/types/typelists.go
+++ b/src/go/types/typelists.go
@@ -4,8 +4,6 @@
package types
-import "bytes"
-
// TypeParamList holds a list of type parameters.
type TypeParamList struct{ tparams []*TypeParam }
@@ -54,15 +52,6 @@
return l.types
}
-func (l *TypeList) String() string {
- if l == nil || len(l.types) == 0 {
- return "[]"
- }
- var buf bytes.Buffer
- newTypeWriter(&buf, nil).typeList(l.types)
- return buf.String()
-}
-
// ----------------------------------------------------------------------------
// Implementation
diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go
index 03ba9be..40d96ac 100644
--- a/src/go/types/typeparam.go
+++ b/src/go/types/typeparam.go
@@ -5,7 +5,6 @@
package types
import (
- "go/token"
"sync/atomic"
)
@@ -31,11 +30,13 @@
// or Signature type by calling SetTypeParams. Setting a type parameter on more
// than one type will result in a panic.
//
-// The constraint argument can be nil, and set later via SetConstraint.
+// The constraint argument can be nil, and set later via SetConstraint. If the
+// constraint is non-nil, it must be fully defined.
func NewTypeParam(obj *TypeName, constraint Type) *TypeParam {
return (*Checker)(nil).newTypeParam(obj, constraint)
}
+// check may be nil
func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam {
// Always increment lastID, even if it is not used.
id := nextID()
@@ -50,9 +51,7 @@
// iface may mutate typ.bound, so we must ensure that iface() is called
// at least once before the resulting TypeParam escapes.
if check != nil {
- check.later(func() {
- typ.iface()
- })
+ check.needsCleanup(typ)
} else if constraint != nil {
typ.iface()
}
@@ -75,8 +74,10 @@
// SetConstraint sets the type constraint for t.
//
-// SetConstraint should not be called concurrently, but once SetConstraint
-// returns the receiver t is safe for concurrent use.
+// It must be called by users of NewTypeParam after the bound's underlying is
+// fully defined, and before using the type parameter in any way other than to
+// form other types. Once SetConstraint returns the receiver, t is safe for
+// concurrent use.
func (t *TypeParam) SetConstraint(bound Type) {
if bound == nil {
panic("nil constraint")
@@ -96,9 +97,12 @@
// ----------------------------------------------------------------------------
// Implementation
+func (t *TypeParam) cleanup() {
+ t.iface()
+ t.check = nil
+}
+
// iface returns the constraint interface of t.
-// TODO(gri) If we make tparamIsIface the default, this should be renamed to under
-// (similar to Named.under).
func (t *TypeParam) iface() *Interface {
bound := t.bound
@@ -127,8 +131,9 @@
// compute type set if necessary
if ityp.tset == nil {
- // use the (original) type bound position if we have one
- pos := token.NoPos
+ // pos is used for tracing output; start with the type parameter position.
+ pos := t.obj.pos
+ // use the (original or possibly instantiated) type bound position if we have one
if n, _ := bound.(*Named); n != nil {
pos = n.obj.pos
}
@@ -138,16 +143,6 @@
return ityp
}
-// singleType returns the single type of the type parameter constraint; or nil.
-func (t *TypeParam) singleType() Type {
- return t.iface().typeSet().singleType()
-}
-
-// hasTerms reports whether the type parameter constraint has specific type terms.
-func (t *TypeParam) hasTerms() bool {
- return t.iface().typeSet().hasTerms()
-}
-
// is calls f with the specific type terms of t's constraint and reports whether
// all calls to f returned true. If there are no specific terms, is
// returns the result of f(nil).
diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go
index d39483f..6603383 100644
--- a/src/go/types/typeset.go
+++ b/src/go/types/typeset.go
@@ -15,39 +15,39 @@
// API
// A _TypeSet represents the type set of an interface.
+// Because of existing language restrictions, methods can be "factored out"
+// from the terms. The actual type set is the intersection of the type set
+// implied by the methods and the type set described by the terms and the
+// comparable bit. To test whether a type is included in a type set
+// ("implements" relation), the type must implement all methods _and_ be
+// an element of the type set described by the terms and the comparable bit.
+// If the term list describes the set of all types and comparable is true,
+// only comparable types are meant; in all other cases comparable is false.
type _TypeSet struct {
- comparable bool // if set, the interface is or embeds comparable
- // TODO(gri) consider using a set for the methods for faster lookup
- methods []*Func // all methods of the interface; sorted by unique ID
- terms termlist // type terms of the type set
+ methods []*Func // all methods of the interface; sorted by unique ID
+ terms termlist // type terms of the type set
+ comparable bool // invariant: !comparable || terms.isAll()
}
// IsEmpty reports whether type set s is the empty set.
func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() }
// IsAll reports whether type set s is the set of all types (corresponding to the empty interface).
-func (s *_TypeSet) IsAll() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isAll() }
+func (s *_TypeSet) IsAll() bool { return s.IsMethodSet() && len(s.methods) == 0 }
// IsMethodSet reports whether the interface t is fully described by its method set.
func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() }
// IsComparable reports whether each type in the set is comparable.
-func (s *_TypeSet) IsComparable() bool {
+func (s *_TypeSet) IsComparable(seen map[Type]bool) bool {
if s.terms.isAll() {
return s.comparable
}
return s.is(func(t *term) bool {
- return t != nil && Comparable(t.typ)
+ return t != nil && comparable(t.typ, false, seen, nil)
})
}
-// TODO(gri) IsTypeSet is not a great name for this predicate. Find a better one.
-
-// IsTypeSet reports whether the type set s is represented by a finite set of underlying types.
-func (s *_TypeSet) IsTypeSet() bool {
- return !s.comparable && len(s.methods) == 0
-}
-
// NumMethods returns the number of methods available.
func (s *_TypeSet) NumMethods() int { return len(s.methods) }
@@ -56,9 +56,8 @@
func (s *_TypeSet) Method(i int) *Func { return s.methods[i] }
// LookupMethod returns the index of and method with matching package and name, or (-1, nil).
-func (s *_TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) {
- // TODO(gri) s.methods is sorted - consider binary search
- return lookupMethod(s.methods, pkg, name)
+func (s *_TypeSet) LookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
+ return lookupMethod(s.methods, pkg, name, foldCase)
}
func (s *_TypeSet) String() string {
@@ -102,14 +101,6 @@
// hasTerms reports whether the type set has specific type terms.
func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
-// singleType returns the single type in s if there is exactly one; otherwise the result is nil.
-func (s *_TypeSet) singleType() Type { return s.terms.singleType() }
-
-// includes reports whether t ∈ s.
-// TODO(gri) This function is not used anywhere anymore. Remove once we
-// are clear that we don't need it elsewhere in the future.
-func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) }
-
// subsetOf reports whether s1 ⊆ s2.
func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }
@@ -133,7 +124,7 @@
// underIs calls f with the underlying types of the specific type terms
// of s and reports whether all calls to f returned true. If there are
-// no specific terms, is returns the result of f(nil).
+// no specific terms, underIs returns the result of f(nil).
func (s *_TypeSet) underIs(f func(Type) bool) bool {
if !s.hasTerms() {
return f(nil)
@@ -165,7 +156,7 @@
}
// If the interface is not fully set up yet, the type set will
- // not be complete, which may lead to errors when using the the
+ // not be complete, which may lead to errors when using the
// type set (e.g. missing method). Don't compute a partial type
// set (and don't store it!), so that we still compute the full
// type set eventually. Instead, return the top type set and
@@ -201,6 +192,16 @@
// reason.
ityp.tset = &_TypeSet{terms: allTermlist} // TODO(gri) is this sufficient?
+ var unionSets map[*Union]*_TypeSet
+ if check != nil {
+ if check.unionTypeSets == nil {
+ check.unionTypeSets = make(map[*Union]*_TypeSet)
+ }
+ unionSets = check.unionTypeSets
+ } else {
+ unionSets = make(map[*Union]*_TypeSet)
+ }
+
// Methods of embedded interfaces are collected unchanged; i.e., the identity
// of a method I.m's Func Object of an interface I is the same as that of
// the method m in an interface that embeds interface I. On the other hand,
@@ -216,12 +217,12 @@
var todo []*Func
var seen objset
- var methods []*Func
+ var allMethods []*Func
mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages
addMethod := func(pos token.Pos, m *Func, explicit bool) {
switch other := seen.insert(m); {
case other == nil:
- methods = append(methods, m)
+ allMethods = append(allMethods, m)
mpos[m] = pos
case explicit:
if check == nil {
@@ -256,7 +257,8 @@
}
// collect embedded elements
- var allTerms = allTermlist
+ allTerms := allTermlist
+ allComparable := false
for i, typ := range ityp.embeddeds {
// The embedding position is nil for imported interfaces
// and also for interface copies after substitution (but
@@ -265,6 +267,7 @@
if ityp.embedPos != nil {
pos = (*ityp.embedPos)[i]
}
+ var comparable bool
var terms termlist
switch u := under(typ).(type) {
case *Interface:
@@ -276,9 +279,7 @@
check.errorf(atPos(pos), _UnsupportedFeature, "embedding constraint interface %s requires go1.18 or later", typ)
continue
}
- if tset.comparable {
- ityp.tset.comparable = true
- }
+ comparable = tset.comparable
for _, m := range tset.methods {
addMethod(pos, m, false) // use embedding position pos rather than m.pos
}
@@ -288,10 +289,12 @@
check.errorf(atPos(pos), _InvalidIfaceEmbed, "embedding interface element %s requires go1.18 or later", u)
continue
}
- tset := computeUnionTypeSet(check, pos, u)
+ tset := computeUnionTypeSet(check, unionSets, pos, u)
if tset == &invalidTypeSet {
continue // ignore invalid unions
}
+ assert(!tset.comparable)
+ assert(len(tset.methods) == 0)
terms = tset.terms
default:
if u == Typ[Invalid] {
@@ -303,11 +306,11 @@
}
terms = termlist{{false, typ}}
}
- // The type set of an interface is the intersection
- // of the type sets of all its elements.
- // Intersection cannot produce longer termlists and
- // thus cannot overflow.
- allTerms = allTerms.intersect(terms)
+
+ // The type set of an interface is the intersection of the type sets of all its elements.
+ // Due to language restrictions, only embedded interfaces can add methods, they are handled
+ // separately. Here we only need to intersect the term lists and comparable bits.
+ allTerms, allComparable = intersectTermLists(allTerms, allComparable, terms, comparable)
}
ityp.embedPos = nil // not needed anymore (errors have been reported)
@@ -320,15 +323,46 @@
}
}
- if methods != nil {
- sort.Sort(byUniqueMethodName(methods))
- ityp.tset.methods = methods
+ ityp.tset.comparable = allComparable
+ if len(allMethods) != 0 {
+ sortMethods(allMethods)
+ ityp.tset.methods = allMethods
}
ityp.tset.terms = allTerms
return ityp.tset
}
+// TODO(gri) The intersectTermLists function belongs to the termlist implementation.
+// The comparable type set may also be best represented as a term (using
+// a special type).
+
+// intersectTermLists computes the intersection of two term lists and respective comparable bits.
+// xcomp, ycomp are valid only if xterms.isAll() and yterms.isAll() respectively.
+func intersectTermLists(xterms termlist, xcomp bool, yterms termlist, ycomp bool) (termlist, bool) {
+ terms := xterms.intersect(yterms)
+ // If one of xterms or yterms is marked as comparable,
+ // the result must only include comparable types.
+ comp := xcomp || ycomp
+ if comp && !terms.isAll() {
+ // only keep comparable terms
+ i := 0
+ for _, t := range terms {
+ assert(t.typ != nil)
+ if Comparable(t.typ) {
+ terms[i] = t
+ i++
+ }
+ }
+ terms = terms[:i]
+ if !terms.isAll() {
+ comp = false
+ }
+ }
+ assert(!comp || terms.isAll()) // comparable invariant
+ return terms, comp
+}
+
func sortMethods(list []*Func) {
sort.Sort(byUniqueMethodName(list))
}
@@ -356,13 +390,13 @@
// computeUnionTypeSet may be called with check == nil.
// The result is &invalidTypeSet if the union overflows.
-func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet {
- if utyp.tset != nil {
- return utyp.tset
+func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos token.Pos, utyp *Union) *_TypeSet {
+ if tset, _ := unionSets[utyp]; tset != nil {
+ return tset
}
// avoid infinite recursion (see also computeInterfaceTypeSet)
- utyp.tset = new(_TypeSet)
+ unionSets[utyp] = new(_TypeSet)
var allTerms termlist
for _, t := range utyp.terms {
@@ -389,11 +423,11 @@
if check != nil {
check.errorf(atPos(pos), _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
}
- utyp.tset = &invalidTypeSet
- return utyp.tset
+ unionSets[utyp] = &invalidTypeSet
+ return unionSets[utyp]
}
}
- utyp.tset.terms = allTerms
+ unionSets[utyp].terms = allTerms
- return utyp.tset
+ return unionSets[utyp]
}
diff --git a/src/go/types/typeset_test.go b/src/go/types/typeset_test.go
index 1c0eece..2bbe611 100644
--- a/src/go/types/typeset_test.go
+++ b/src/go/types/typeset_test.go
@@ -26,9 +26,9 @@
"{int; string}": "∅",
"{comparable}": "{comparable}",
- "{comparable; int}": "{comparable; int}",
- "{~int; comparable}": "{comparable; ~int}",
- "{int|string; comparable}": "{comparable; int ∪ string}",
+ "{comparable; int}": "{int}",
+ "{~int; comparable}": "{~int}",
+ "{int|string; comparable}": "{int ∪ string}",
"{comparable; int; string}": "∅",
"{m()}": "{func (p.T).m()}",
@@ -38,8 +38,8 @@
"{m1(); comparable; m2() int }": "{comparable; func (p.T).m1(); func (p.T).m2() int}",
"{comparable; error}": "{comparable; func (error).Error() string}",
- "{m(); comparable; int|float32|string}": "{comparable; func (p.T).m(); int ∪ float32 ∪ string}",
- "{m1(); int; m2(); comparable }": "{comparable; func (p.T).m1(); func (p.T).m2(); int}",
+ "{m(); comparable; int|float32|string}": "{func (p.T).m(); int ∪ float32 ∪ string}",
+ "{m1(); int; m2(); comparable }": "{func (p.T).m1(); func (p.T).m2(); int}",
"{E}; type E interface{}": "𝓤",
"{E}; type E interface{int;string}": "∅",
diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go
index cf86f9f..80210a2 100644
--- a/src/go/types/typestring.go
+++ b/src/go/types/typestring.go
@@ -202,12 +202,18 @@
}
case *Interface:
- if t == universeAny.Type() && w.ctxt == nil {
- // When not hashing, we can try to improve type strings by writing "any"
- // for a type that is pointer-identical to universeAny. This logic should
- // be deprecated by more robust handling for aliases.
- w.string("any")
- break
+ if w.ctxt == nil {
+ if t == universeAny.Type() {
+ // When not hashing, we can try to improve type strings by writing "any"
+ // for a type that is pointer-identical to universeAny. This logic should
+ // be deprecated by more robust handling for aliases.
+ w.string("any")
+ break
+ }
+ if t == universeComparable.Type().(*Named).underlying {
+ w.string("interface{comparable}")
+ break
+ }
}
if t.implicit {
if len(t.methods) == 0 && len(t.embeddeds) == 1 {
diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go
index 14ab9b6..b7b8435 100644
--- a/src/go/types/typestring_test.go
+++ b/src/go/types/typestring_test.go
@@ -97,6 +97,11 @@
dup(`interface{String() string; m(int) float32}`),
dup("interface{int|float32|complex128}"),
dup("interface{int|~float32|~complex128}"),
+ dup("any"),
+ dup("interface{comparable}"),
+ // TODO(gri) adjust test for EvalCompositeTest
+ // {"comparable", "interface{comparable}"},
+ // {"error", "interface{Error() string}"},
// maps
dup("map[string]int"),
diff --git a/src/go/types/typeterm_test.go b/src/go/types/typeterm_test.go
index 27f132a..24a1410 100644
--- a/src/go/types/typeterm_test.go
+++ b/src/go/types/typeterm_test.go
@@ -100,7 +100,7 @@
"~int ~string ~int ~string",
"~int myInt ~int ∅",
- // union is symmetric, but the result order isn't - repeat symmetric cases explictly
+ // union is symmetric, but the result order isn't - repeat symmetric cases explicitly
"𝓤 ∅ 𝓤 ∅",
"int ∅ int ∅",
"~int ∅ ~int ∅",
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index b961f7c..5bb2d8f 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -96,6 +96,10 @@
x.mode = constant_
case *TypeName:
+ if check.isBrokenAlias(obj) {
+ check.errorf(e, _InvalidDeclCycle, "invalid use of type alias %s in recursive type (see issue #50729)", obj.name)
+ return
+ }
x.mode = typexpr
case *Var:
@@ -140,10 +144,16 @@
// constraint interface.
func (check *Checker) varType(e ast.Expr) Type {
typ := check.definedType(e, nil)
+ check.validVarType(e, typ)
+ return typ
+}
+// validVarType reports an error if typ is a constraint interface.
+// The expression e is used for error reporting, if any.
+func (check *Checker) validVarType(e ast.Expr, typ Type) {
// If we have a type parameter there's nothing to do.
if isTypeParam(typ) {
- return typ
+ return
}
// We don't want to call under() or complete interfaces while we are in
@@ -161,8 +171,6 @@
}
}
})
-
- return typ
}
// definedType is like typ but also accepts a type name def.
@@ -209,7 +217,7 @@
//
func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
if trace {
- check.trace(e0.Pos(), "type %s", e0)
+ check.trace(e0.Pos(), "-- type %s", e0)
check.indent++
defer func() {
check.indent--
@@ -250,7 +258,7 @@
case *ast.SelectorExpr:
var x operand
- check.selector(&x, e)
+ check.selector(&x, e, def)
switch x.mode {
case typexpr:
@@ -319,7 +327,7 @@
return typ
case *ast.InterfaceType:
- typ := new(Interface)
+ typ := check.newInterface()
def.setUnderlying(typ)
if def != nil {
typ.obj = def.obj
@@ -411,10 +419,14 @@
// evaluate arguments
targs := check.typeList(ix.Indices)
if targs == nil {
- def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
+ def.setUnderlying(Typ[Invalid]) // avoid errors later due to lazy instantiation
return Typ[Invalid]
}
+ // enableTypeTypeInference controls whether to infer missing type arguments
+ // using constraint type inference. See issue #51527.
+ const enableTypeTypeInference = false
+
// create the instance
ctxt := check.bestContext(nil)
h := ctxt.instanceHash(orig, targs)
@@ -425,27 +437,27 @@
// validation below. Ensure that the validation (and resulting errors) runs
// for each instantiated type in the source.
if inst == nil {
- tname := NewTypeName(ix.X.Pos(), orig.obj.pkg, orig.obj.name, nil)
+ // x may be a selector for an imported type; use its start pos rather than x.Pos().
+ tname := NewTypeName(ix.Pos(), orig.obj.pkg, orig.obj.name, nil)
inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved
inst.targs = newTypeList(targs)
inst = ctxt.update(h, orig, targs, inst).(*Named)
}
def.setUnderlying(inst)
- inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) {
- tparams := orig.TypeParams().list()
+ inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, *methodList) {
+ tparams := n.orig.TypeParams().list()
- inferred := targs
- if len(targs) < len(tparams) {
+ targs := n.targs.list()
+ if enableTypeTypeInference && len(targs) < len(tparams) {
// If inference fails, len(inferred) will be 0, and inst.underlying will
// be set to Typ[Invalid] in expandNamed.
- inferred = check.infer(ix.Orig, tparams, targs, nil, nil)
+ inferred := check.infer(ix.Orig, tparams, targs, nil, nil)
if len(inferred) > len(targs) {
- inst.targs = newTypeList(inferred)
+ n.targs = newTypeList(inferred)
}
}
- check.recordInstance(ix.Orig, inferred, inst)
return expandNamed(ctxt, n, pos)
}
@@ -458,6 +470,7 @@
// Since check is non-nil, we can still mutate inst. Unpinning the resolver
// frees some memory.
inst.resolver = nil
+ check.recordInstance(ix.Orig, inst.TypeArgs().list(), inst)
if check.validateTArgLen(pos, inst.tparams.Len(), inst.targs.Len()) {
if i, err := check.verify(pos, inst.tparams.list(), inst.targs.list()); err != nil {
@@ -472,7 +485,7 @@
}
}
- check.validType(inst, nil)
+ check.validType(inst)
})
return inst
@@ -482,12 +495,20 @@
// and returns the constant length >= 0, or a value < 0
// to indicate an error (and thus an unknown length).
func (check *Checker) arrayLength(e ast.Expr) int64 {
- // If e is an undeclared identifier, the array declaration might be an
- // attempt at a parameterized type declaration with missing constraint.
- // Provide a better error message than just "undeclared name: X".
- if name, _ := e.(*ast.Ident); name != nil && check.lookup(name.Name) == nil {
- check.errorf(name, _InvalidArrayLen, "undeclared name %s for array length", name.Name)
- return -1
+ // If e is an identifier, the array declaration might be an
+ // attempt at a parameterized type declaration with missing
+ // constraint. Provide an error message that mentions array
+ // length.
+ if name, _ := e.(*ast.Ident); name != nil {
+ obj := check.lookup(name.Name)
+ if obj == nil {
+ check.errorf(name, _InvalidArrayLen, "undeclared name %s for array length", name.Name)
+ return -1
+ }
+ if _, ok := obj.(*Const); !ok {
+ check.errorf(name, _InvalidArrayLen, "invalid array length %s", name.Name)
+ return -1
+ }
}
var x operand
diff --git a/src/go/types/unify.go b/src/go/types/unify.go
index 5dcb35f..7b9aeee 100644
--- a/src/go/types/unify.go
+++ b/src/go/types/unify.go
@@ -9,6 +9,7 @@
import (
"bytes"
"fmt"
+ "strings"
)
// The unifier maintains two separate sets of type parameters x and y
@@ -26,13 +27,36 @@
// parameter P ("x" side), but the argument type P must be left alone so
// that unification resolves the type parameter P to P.
//
-// For bidirection unification, both sets are provided. This enables
+// For bidirectional unification, both sets are provided. This enables
// unification to go from argument to parameter type and vice versa.
// For constraint type inference, we use bidirectional unification
// where both the x and y type parameters are identical. This is done
// by setting up one of them (using init) and then assigning its value
// to the other.
+const (
+ // Upper limit for recursion depth. Used to catch infinite recursions
+ // due to implementation issues (e.g., see issues #48619, #48656).
+ unificationDepthLimit = 50
+
+ // Whether to panic when unificationDepthLimit is reached. Turn on when
+ // investigating infinite recursion.
+ panicAtUnificationDepthLimit = false
+
+ // If enableCoreTypeUnification is set, unification will consider
+ // the core types, if any, of non-local (unbound) type parameters.
+ enableCoreTypeUnification = true
+
+ // If traceInference is set, unification will print a trace of its operation.
+ // Interpretation of trace:
+ // x ≡ y attempt to unify types x and y
+ // p ➞ y type parameter p is set to type y (p is inferred to be y)
+ // p ⇄ q type parameters p and q match (p is inferred to be q and vice versa)
+ // x ≢ y types x and y cannot be unified
+ // [p, q, ...] ➞ [x, y, ...] mapping from type parameters to types
+ traceInference = false
+)
+
// A unifier maintains the current type parameters for x and y
// and the respective types inferred for each type parameter.
// A unifier is created by calling newUnifier.
@@ -40,6 +64,7 @@
exact bool
x, y tparamsList // x and y must initialized via tparamsList.init
types []Type // inferred types, shared by x and y
+ depth int // recursion depth during unification
}
// newUnifier returns a new unifier.
@@ -47,6 +72,7 @@
// exactly. If exact is not set, a named type's underlying type
// is considered if unification would fail otherwise, and the
// direction of channels is ignored.
+// TODO(gri) exact is not set anymore by a caller. Consider removing it.
func newUnifier(exact bool) *unifier {
u := &unifier{exact: exact}
u.x.unifier = u
@@ -59,6 +85,10 @@
return u.nify(x, y, nil)
}
+func (u *unifier) tracef(format string, args ...interface{}) {
+ fmt.Println(strings.Repeat(". ", u.depth) + sprintf(nil, nil, true, format, args...))
+}
+
// A tparamsList describes a list of type parameters and the types inferred for them.
type tparamsList struct {
unifier *unifier
@@ -110,6 +140,9 @@
// If both type parameters already have a type associated with them and they are
// not joined, join fails and returns false.
func (u *unifier) join(i, j int) bool {
+ if traceInference {
+ u.tracef("%s ⇄ %s", u.x.tparams[i], u.y.tparams[j])
+ }
ti := u.x.indices[i]
tj := u.y.indices[j]
switch {
@@ -159,7 +192,7 @@
}
// If tpar is a type parameter in list, tparamIndex returns the type parameter index.
-// Otherwise, the result is < 0. tpar must not be nil.j
+// Otherwise, the result is < 0. tpar must not be nil.
func tparamIndex(list []*TypeParam, tpar *TypeParam) int {
// Once a type parameter is bound its index is >= 0. However, there are some
// code paths (namely tracing and type hashing) by which it is possible to
@@ -199,6 +232,9 @@
func (d *tparamsList) set(i int, typ Type) {
assert(typ != nil)
u := d.unifier
+ if traceInference {
+ u.tracef("%s ➞ %s", d.tparams[i], typ)
+ }
switch ti := d.indices[i]; {
case ti < 0:
u.types[-ti-1] = typ
@@ -211,6 +247,17 @@
}
}
+// unknowns returns the number of type parameters for which no type has been set yet.
+func (d *tparamsList) unknowns() int {
+ n := 0
+ for _, ti := range d.indices {
+ if ti <= 0 {
+ n++
+ }
+ }
+ return n
+}
+
// types returns the list of inferred types (via unification) for the type parameters
// described by d, and an index. If all types were inferred, the returned index is < 0.
// Otherwise, it is the index of the first type parameter which couldn't be inferred;
@@ -236,7 +283,29 @@
// adapted version of Checker.identical. For changes to that
// code the corresponding changes should be made here.
// Must not be called directly from outside the unifier.
-func (u *unifier) nify(x, y Type, p *ifacePair) bool {
+func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
+ if traceInference {
+ u.tracef("%s ≡ %s", x, y)
+ }
+
+ // Stop gap for cases where unification fails.
+ if u.depth >= unificationDepthLimit {
+ if traceInference {
+ u.tracef("depth %d >= %d", u.depth, unificationDepthLimit)
+ }
+ if panicAtUnificationDepthLimit {
+ panic("unification reached recursion depth limit")
+ }
+ return false
+ }
+ u.depth++
+ defer func() {
+ u.depth--
+ if traceInference && !result {
+ u.tracef("%s ≢ %s", x, y)
+ }
+ }()
+
if !u.exact {
// If exact unification is known to fail because we attempt to
// match a type name against an unnamed type literal, consider
@@ -244,8 +313,14 @@
// (We use !hasName to exclude any type with a name, including
// basic types and type parameters; the rest are unamed types.)
if nx, _ := x.(*Named); nx != nil && !hasName(y) {
+ if traceInference {
+ u.tracef("under %s ≡ %s", nx, y)
+ }
return u.nify(nx.under(), y, p)
} else if ny, _ := y.(*Named); ny != nil && !hasName(x) {
+ if traceInference {
+ u.tracef("%s ≡ under %s", x, ny)
+ }
return u.nify(x, ny.under(), p)
}
}
@@ -279,6 +354,39 @@
return true
}
+ // If we get here and x or y is a type parameter, they are type parameters
+ // from outside our declaration list. Try to unify their core types, if any
+ // (see issue #50755 for a test case).
+ if enableCoreTypeUnification && !u.exact {
+ if isTypeParam(x) && !hasName(y) {
+ // When considering the type parameter for unification
+ // we look at the adjusted core term (adjusted core type
+ // with tilde information).
+ // If the adjusted core type is a named type N; the
+ // corresponding core type is under(N). Since !u.exact
+ // and y doesn't have a name, unification will end up
+ // comparing under(N) to y, so we can just use the core
+ // type instead. And we can ignore the tilde because we
+ // already look at the underlying types on both sides
+ // and we have known types on both sides.
+ // Optimization.
+ if cx := coreType(x); cx != nil {
+ if traceInference {
+ u.tracef("core %s ≡ %s", x, y)
+ }
+ return u.nify(cx, y, p)
+ }
+ } else if isTypeParam(y) && !hasName(x) {
+ // see comment above
+ if cy := coreType(y); cy != nil {
+ if traceInference {
+ u.tracef("%s ≡ core %s", x, y)
+ }
+ return u.nify(x, cy, p)
+ }
+ }
+ }
+
// For type unification, do not shortcut (x == y) for identical
// types. Instead keep comparing them element-wise to unify the
// matching (and equal type parameter types). A simple test case
@@ -370,6 +478,9 @@
if y, ok := y.(*Interface); ok {
xset := x.typeSet()
yset := y.typeSet()
+ if xset.comparable != yset.comparable {
+ return false
+ }
if !xset.terms.equal(yset.terms) {
return false
}
@@ -437,11 +548,14 @@
xargs := x.targs.list()
yargs := y.targs.list()
+ if len(xargs) != len(yargs) {
+ return false
+ }
+
// TODO(gri) This is not always correct: two types may have the same names
// in the same package if one of them is nested in a function.
// Extremely unlikely but we need an always correct solution.
if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
- assert(len(xargs) == len(yargs))
for i, x := range xargs {
if !u.nify(x, yargs[i], p) {
return false
@@ -461,7 +575,7 @@
// avoid a crash in case of nil type
default:
- panic(fmt.Sprintf("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams))
+ panic(sprintf(nil, nil, true, "u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams))
}
return false
diff --git a/src/go/types/union.go b/src/go/types/union.go
index 1437bd4..8397d65 100644
--- a/src/go/types/union.go
+++ b/src/go/types/union.go
@@ -14,8 +14,7 @@
// A Union represents a union of terms embedded in an interface.
type Union struct {
- terms []*Term // list of syntactical terms (not a canonicalized termlist)
- tset *_TypeSet // type set described by this union, computed lazily
+ terms []*Term // list of syntactical terms (not a canonicalized termlist)
}
// NewUnion returns a new Union type with the given terms.
@@ -24,7 +23,7 @@
if len(terms) == 0 {
panic("empty union")
}
- return &Union{terms, nil}
+ return &Union{terms}
}
func (u *Union) Len() int { return len(u.terms) }
@@ -52,23 +51,37 @@
// parseUnion parses uexpr as a union of expressions.
// The result is a Union type, or Typ[Invalid] for some errors.
func parseUnion(check *Checker, uexpr ast.Expr) Type {
- tlist := flattenUnion(nil, uexpr)
+ blist, tlist := flattenUnion(nil, uexpr)
+ assert(len(blist) == len(tlist)-1)
var terms []*Term
- for _, x := range tlist {
- tilde, typ := parseTilde(check, x)
- if len(tlist) == 1 && !tilde {
+
+ var u Type
+ for i, x := range tlist {
+ term := parseTilde(check, x)
+ if len(tlist) == 1 && !term.tilde {
// Single type. Ok to return early because all relevant
// checks have been performed in parseTilde (no need to
// run through term validity check below).
- return typ // typ already recorded through check.typ in parseTilde
+ return term.typ // typ already recorded through check.typ in parseTilde
}
if len(terms) >= maxTermCount {
- check.errorf(x, _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
- check.recordTypeAndValue(uexpr, typexpr, Typ[Invalid], nil)
- return Typ[Invalid]
+ if u != Typ[Invalid] {
+ check.errorf(x, _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
+ u = Typ[Invalid]
+ }
+ } else {
+ terms = append(terms, term)
+ u = &Union{terms}
}
- terms = append(terms, NewTerm(tilde, typ))
+
+ if i > 0 {
+ check.recordTypeAndValue(blist[i-1], typexpr, u, nil)
+ }
+ }
+
+ if u == Typ[Invalid] {
+ return u
}
// Check validity of terms.
@@ -90,16 +103,27 @@
if !Identical(u, t.typ) {
check.errorf(tlist[i], _InvalidUnion, "invalid use of ~ (underlying type of %s is %s)", t.typ, u)
- continue // don't report another error for t
+ continue
}
}
// Stand-alone embedded interfaces are ok and are handled by the single-type case
// in the beginning. Embedded interfaces with tilde are excluded above. If we reach
- // here, we must have at least two terms in the union.
- if f != nil && !f.typeSet().IsTypeSet() {
- check.errorf(tlist[i], _InvalidUnion, "cannot use %s in union (interface contains methods)", t)
- continue // don't report another error for t
+ // here, we must have at least two terms in the syntactic term list (but not necessarily
+ // in the term list of the union's type set).
+ if f != nil {
+ tset := f.typeSet()
+ switch {
+ case tset.NumMethods() != 0:
+ check.errorf(tlist[i], _InvalidUnion, "cannot use %s in union (%s contains methods)", t, t)
+ continue
+ case t.typ == universeComparable.Type():
+ check.error(tlist[i], _InvalidUnion, "cannot use comparable in union")
+ continue
+ case tset.comparable:
+ check.errorf(tlist[i], _InvalidUnion, "cannot use %s in union (%s embeds comparable)", t, t)
+ continue
+ }
}
// Report overlapping (non-disjoint) terms such as
@@ -110,17 +134,17 @@
}
})
- u := &Union{terms, nil}
- check.recordTypeAndValue(uexpr, typexpr, u, nil)
return u
}
-func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) {
+func parseTilde(check *Checker, tx ast.Expr) *Term {
+ x := tx
+ var tilde bool
if op, _ := x.(*ast.UnaryExpr); op != nil && op.Op == token.TILDE {
x = op.X
tilde = true
}
- typ = check.typ(x)
+ typ := check.typ(x)
// Embedding stand-alone type parameters is not permitted (issue #47127).
// We don't need this restriction anymore if we make the underlying type of a type
// parameter its constraint interface: if we embed a lone type parameter, we will
@@ -130,7 +154,11 @@
check.error(x, _MisplacedTypeParam, "cannot embed a type parameter")
typ = Typ[Invalid]
}
- return
+ term := NewTerm(tilde, typ)
+ if tilde {
+ check.recordTypeAndValue(tx, typexpr, &Union{[]*Term{term}}, nil)
+ }
+ return term
}
// overlappingTerm reports the index of the term x in terms which is
@@ -151,10 +179,13 @@
return -1
}
-func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr {
+// flattenUnion walks a union type expression of the form A | B | C | ...,
+// extracting both the binary exprs (blist) and leaf types (tlist).
+func flattenUnion(list []ast.Expr, x ast.Expr) (blist, tlist []ast.Expr) {
if o, _ := x.(*ast.BinaryExpr); o != nil && o.Op == token.OR {
- list = flattenUnion(list, o.X)
+ blist, tlist = flattenUnion(list, o.X)
+ blist = append(blist, o)
x = o.Y
}
- return append(list, x)
+ return blist, append(tlist, x)
}
diff --git a/src/go/types/universe.go b/src/go/types/universe.go
index edda56f..303ada4 100644
--- a/src/go/types/universe.go
+++ b/src/go/types/universe.go
@@ -89,22 +89,32 @@
{
obj := NewTypeName(token.NoPos, nil, "error", nil)
obj.setColor(black)
+ typ := NewNamed(obj, nil, nil)
+
+ // error.Error() string
+ recv := NewVar(token.NoPos, nil, "", typ)
res := NewVar(token.NoPos, nil, "", Typ[String])
- sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false)
+ sig := NewSignatureType(recv, nil, nil, nil, NewTuple(res), false)
err := NewFunc(token.NoPos, nil, "Error", sig)
- ityp := &Interface{nil, obj, []*Func{err}, nil, nil, false, true, nil}
+
+ // interface{ Error() string }
+ ityp := &Interface{obj: obj, methods: []*Func{err}, complete: true}
computeInterfaceTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset
- typ := NewNamed(obj, ityp, nil)
- sig.recv = NewVar(token.NoPos, nil, "", typ)
+
+ typ.SetUnderlying(ityp)
def(obj)
}
- // type comparable interface{ /* type set marked comparable */ }
+ // type comparable interface{} // marked as comparable
{
obj := NewTypeName(token.NoPos, nil, "comparable", nil)
obj.setColor(black)
- ityp := &Interface{nil, obj, nil, nil, nil, false, true, &_TypeSet{true, nil, allTermlist}}
- NewNamed(obj, ityp, nil)
+ typ := NewNamed(obj, nil, nil)
+
+ // interface{} // marked as comparable
+ ityp := &Interface{obj: obj, complete: true, tset: &_TypeSet{nil, allTermlist, true}}
+
+ typ.SetUnderlying(ityp)
def(obj)
}
}
diff --git a/src/go/types/validtype.go b/src/go/types/validtype.go
new file mode 100644
index 0000000..7d7029b
--- /dev/null
+++ b/src/go/types/validtype.go
@@ -0,0 +1,147 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+// validType verifies that the given type does not "expand" indefinitely
+// producing a cycle in the type graph. Cycles are detected by marking
+// defined types.
+// (Cycles involving alias types, as in "type A = [10]A" are detected
+// earlier, via the objDecl cycle detection mechanism.)
+func (check *Checker) validType(typ *Named) {
+ check.validType0(typ, nil, nil)
+}
+
+type typeInfo uint
+
+// validType0 checks if the given type is valid. If typ is a type parameter
+// its value is looked up in the provided environment. The environment is
+// nil if typ is not part of (the RHS of) an instantiated type, in that case
+// any type parameter encountered must be from an enclosing function and can
+// be ignored. The path is the list of type names that lead to the current typ.
+func (check *Checker) validType0(typ Type, env *tparamEnv, path []Object) typeInfo {
+ const (
+ unknown typeInfo = iota
+ marked
+ valid
+ invalid
+ )
+
+ switch t := typ.(type) {
+ case nil:
+ // We should never see a nil type but be conservative and panic
+ // only in debug mode.
+ if debug {
+ panic("validType0(nil)")
+ }
+
+ case *Array:
+ return check.validType0(t.elem, env, path)
+
+ case *Struct:
+ for _, f := range t.fields {
+ if check.validType0(f.typ, env, path) == invalid {
+ return invalid
+ }
+ }
+
+ case *Union:
+ for _, t := range t.terms {
+ if check.validType0(t.typ, env, path) == invalid {
+ return invalid
+ }
+ }
+
+ case *Interface:
+ for _, etyp := range t.embeddeds {
+ if check.validType0(etyp, env, path) == invalid {
+ return invalid
+ }
+ }
+
+ case *Named:
+ // Don't report a 2nd error if we already know the type is invalid
+ // (e.g., if a cycle was detected earlier, via under).
+ if t.underlying == Typ[Invalid] {
+ check.infoMap[t] = invalid
+ return invalid
+ }
+
+ switch check.infoMap[t] {
+ case unknown:
+ check.infoMap[t] = marked
+ check.infoMap[t] = check.validType0(t.orig.fromRHS, env.push(t), append(path, t.obj))
+ case marked:
+ // We have seen type t before and thus must have a cycle.
+ check.infoMap[t] = invalid
+ // t cannot be in an imported package otherwise that package
+ // would have reported a type cycle and couldn't have been
+ // imported in the first place.
+ assert(t.obj.pkg == check.pkg)
+ t.underlying = Typ[Invalid] // t is in the current package (no race possibility)
+ // Find the starting point of the cycle and report it.
+ for i, tn := range path {
+ if tn == t.obj {
+ check.cycleError(path[i:])
+ return invalid
+ }
+ }
+ panic("cycle start not found")
+ }
+ return check.infoMap[t]
+
+ case *TypeParam:
+ // A type parameter stands for the type (argument) it was instantiated with.
+ // Check the corresponding type argument for validity if we have one.
+ if env != nil {
+ if targ := env.tmap[t]; targ != nil {
+ // Type arguments found in targ must be looked
+ // up in the enclosing environment env.link.
+ return check.validType0(targ, env.link, path)
+ }
+ }
+ }
+
+ return valid
+}
+
+// A tparamEnv provides the environment for looking up the type arguments
+// with which type parameters for a given instance were instantiated.
+// If we don't have an instance, the corresponding tparamEnv is nil.
+type tparamEnv struct {
+ tmap substMap
+ link *tparamEnv
+}
+
+func (env *tparamEnv) push(typ *Named) *tparamEnv {
+ // If typ is not an instantiated type there are no typ-specific
+ // type parameters to look up and we don't need an environment.
+ targs := typ.TypeArgs()
+ if targs == nil {
+ return nil // no instance => nil environment
+ }
+
+ // Populate tmap: remember the type argument for each type parameter.
+ // We cannot use makeSubstMap because the number of type parameters
+ // and arguments may not match due to errors in the source (too many
+ // or too few type arguments). Populate tmap "manually".
+ tparams := typ.TypeParams()
+ n, m := targs.Len(), tparams.Len()
+ if n > m {
+ n = m // too many targs
+ }
+ tmap := make(substMap, n)
+ for i := 0; i < n; i++ {
+ tmap[tparams.At(i)] = targs.At(i)
+ }
+
+ return &tparamEnv{tmap: tmap, link: env}
+}
+
+// TODO(gri) Alternative implementation:
+// We may not need to build a stack of environments to
+// look up the type arguments for type parameters. The
+// same information should be available via the path:
+// We should be able to just walk the path backwards
+// and find the type arguments in the instance objects.
diff --git a/src/image/gif/fuzz_test.go b/src/image/gif/fuzz_test.go
new file mode 100644
index 0000000..3ddf15d
--- /dev/null
+++ b/src/image/gif/fuzz_test.go
@@ -0,0 +1,61 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gif
+
+import (
+ "bytes"
+ "image"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func FuzzDecode(f *testing.F) {
+ testdata, err := os.ReadDir("../testdata")
+ if err != nil {
+ f.Fatalf("failed to read testdata directory: %s", err)
+ }
+ for _, de := range testdata {
+ if de.IsDir() || !strings.HasSuffix(de.Name(), ".gif") {
+ continue
+ }
+ b, err := os.ReadFile(filepath.Join("../testdata", de.Name()))
+ if err != nil {
+ f.Fatalf("failed to read testdata: %s", err)
+ }
+ f.Add(b)
+ }
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ cfg, _, err := image.DecodeConfig(bytes.NewReader(b))
+ if err != nil {
+ return
+ }
+ if cfg.Width*cfg.Height > 1e6 {
+ return
+ }
+ img, typ, err := image.Decode(bytes.NewReader(b))
+ if err != nil || typ != "gif" {
+ return
+ }
+ for q := 1; q <= 256; q++ {
+ var w bytes.Buffer
+ err := Encode(&w, img, &Options{NumColors: q})
+ if err != nil {
+ t.Fatalf("failed to encode valid image: %s", err)
+ }
+ img1, err := Decode(&w)
+ if err != nil {
+ t.Fatalf("failed to decode roundtripped image: %s", err)
+ }
+ got := img1.Bounds()
+ want := img.Bounds()
+ if !got.Eq(want) {
+ t.Fatalf("roundtripped image bounds have changed, got: %v, want: %v", got, want)
+ }
+ }
+ })
+}
diff --git a/src/image/jpeg/fuzz_test.go b/src/image/jpeg/fuzz_test.go
new file mode 100644
index 0000000..716f06f
--- /dev/null
+++ b/src/image/jpeg/fuzz_test.go
@@ -0,0 +1,61 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jpeg
+
+import (
+ "bytes"
+ "image"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func FuzzDecode(f *testing.F) {
+ testdata, err := os.ReadDir("../testdata")
+ if err != nil {
+ f.Fatalf("failed to read testdata directory: %s", err)
+ }
+ for _, de := range testdata {
+ if de.IsDir() || !strings.HasSuffix(de.Name(), ".jpeg") {
+ continue
+ }
+ b, err := os.ReadFile(filepath.Join("../testdata", de.Name()))
+ if err != nil {
+ f.Fatalf("failed to read testdata: %s", err)
+ }
+ f.Add(b)
+ }
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ cfg, _, err := image.DecodeConfig(bytes.NewReader(b))
+ if err != nil {
+ return
+ }
+ if cfg.Width*cfg.Height > 1e6 {
+ return
+ }
+ img, typ, err := image.Decode(bytes.NewReader(b))
+ if err != nil || typ != "jpeg" {
+ return
+ }
+ for q := 1; q <= 100; q++ {
+ var w bytes.Buffer
+ err := Encode(&w, img, &Options{Quality: q})
+ if err != nil {
+ t.Fatalf("failed to encode valid image: %s", err)
+ }
+ img1, err := Decode(&w)
+ if err != nil {
+ t.Fatalf("failed to decode roundtripped image: %s", err)
+ }
+ got := img1.Bounds()
+ want := img.Bounds()
+ if !got.Eq(want) {
+ t.Fatalf("roundtripped image bounds have changed, got: %s, want: %s", got, want)
+ }
+ }
+ })
+}
diff --git a/src/image/png/fuzz_test.go b/src/image/png/fuzz_test.go
new file mode 100644
index 0000000..22b3ef0
--- /dev/null
+++ b/src/image/png/fuzz_test.go
@@ -0,0 +1,68 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package png
+
+import (
+ "bytes"
+ "image"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func FuzzDecode(f *testing.F) {
+ testdata, err := os.ReadDir("../testdata")
+ if err != nil {
+ f.Fatalf("failed to read testdata directory: %s", err)
+ }
+ for _, de := range testdata {
+ if de.IsDir() || !strings.HasSuffix(de.Name(), ".png") {
+ continue
+ }
+ b, err := os.ReadFile(filepath.Join("../testdata", de.Name()))
+ if err != nil {
+ f.Fatalf("failed to read testdata: %s", err)
+ }
+ f.Add(b)
+ }
+
+ f.Fuzz(func(t *testing.T, b []byte) {
+ cfg, _, err := image.DecodeConfig(bytes.NewReader(b))
+ if err != nil {
+ return
+ }
+ if cfg.Width*cfg.Height > 1e6 {
+ return
+ }
+ img, typ, err := image.Decode(bytes.NewReader(b))
+ if err != nil || typ != "png" {
+ return
+ }
+ levels := []CompressionLevel{
+ DefaultCompression,
+ NoCompression,
+ BestSpeed,
+ BestCompression,
+ }
+ for _, l := range levels {
+ var w bytes.Buffer
+ e := &Encoder{CompressionLevel: l}
+ err = e.Encode(&w, img)
+ if err != nil {
+ t.Fatalf("failed to encode valid image: %s", err)
+ }
+ img1, err := Decode(&w)
+ if err != nil {
+ t.Fatalf("failed to decode roundtripped image: %s", err)
+ }
+ got := img1.Bounds()
+ want := img.Bounds()
+ if !got.Eq(want) {
+ t.Fatalf("roundtripped image bounds have changed, got: %s, want: %s", got, want)
+ }
+ }
+ })
+}
diff --git a/src/internal/buildcfg/zbootstrap.go b/src/internal/buildcfg/zbootstrap.go
index 1e164e8..d710914 100644
--- a/src/internal/buildcfg/zbootstrap.go
+++ b/src/internal/buildcfg/zbootstrap.go
@@ -13,6 +13,6 @@
const defaultGOEXPERIMENT = ``
const defaultGO_EXTLINK_ENABLED = ``
const defaultGO_LDSO = `/lib64/ld-linux-x86-64.so.2`
-const version = `go1.18beta1`
+const version = `go1.18`
const defaultGOOS = runtime.GOOS
const defaultGOARCH = runtime.GOARCH
diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go
index 4cb3fbd..78664d7 100644
--- a/src/internal/cfg/cfg.go
+++ b/src/internal/cfg/cfg.go
@@ -62,6 +62,7 @@
GOTOOLDIR
GOVCS
GOWASM
+ GOWORK
GO_EXTLINK_ENABLED
PKG_CONFIG
`
diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go
index 3dee73b..88f98a1 100644
--- a/src/internal/fuzz/coverage.go
+++ b/src/internal/fuzz/coverage.go
@@ -66,6 +66,17 @@
return n
}
+// isCoverageSubset returns true if all the base coverage bits are set in
+// snapshot
+func isCoverageSubset(base, snapshot []byte) bool {
+ for i, v := range base {
+ if v&snapshot[i] != v {
+ return false
+ }
+ }
+ return true
+}
+
// hasCoverageBit returns true if snapshot has at least one bit set that is
// also set in base.
func hasCoverageBit(base, snapshot []byte) bool {
diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go
index 2bfa02b..c95d9e0 100644
--- a/src/internal/fuzz/encoding.go
+++ b/src/internal/fuzz/encoding.go
@@ -10,7 +10,9 @@
"go/ast"
"go/parser"
"go/token"
+ "math"
"strconv"
+ "unicode/utf8"
)
// encVersion1 will be the first line of a file with version 1 encoding.
@@ -27,13 +29,64 @@
// instead of changing to byte and rune respectively.
for _, val := range vals {
switch t := val.(type) {
- case int, int8, int16, int64, uint, uint16, uint32, uint64, float32, float64, bool:
+ case int, int8, int16, int64, uint, uint16, uint32, uint64, bool:
fmt.Fprintf(b, "%T(%v)\n", t, t)
+ case float32:
+ if math.IsNaN(float64(t)) && math.Float32bits(t) != math.Float32bits(float32(math.NaN())) {
+ // We encode unusual NaNs as hex values, because that is how users are
+ // likely to encounter them in literature about floating-point encoding.
+ // This allows us to reproduce fuzz failures that depend on the specific
+ // NaN representation (for float32 there are about 2^24 possibilities!),
+ // not just the fact that the value is *a* NaN.
+ //
+ // Note that the specific value of float32(math.NaN()) can vary based on
+ // whether the architecture represents signaling NaNs using a low bit
+ // (as is common) or a high bit (as commonly implemented on MIPS
+ // hardware before around 2012). We believe that the increase in clarity
+ // from identifying "NaN" with math.NaN() is worth the slight ambiguity
+ // from a platform-dependent value.
+ fmt.Fprintf(b, "math.Float32frombits(0x%x)\n", math.Float32bits(t))
+ } else {
+ // We encode all other values — including the NaN value that is
+ // bitwise-identical to float32(math.Nan()) — using the default
+ // formatting, which is equivalent to strconv.FormatFloat with format
+ // 'g' and can be parsed by strconv.ParseFloat.
+ //
+ // For an ordinary floating-point number this format includes
+ // sufficiently many digits to reconstruct the exact value. For positive
+ // or negative infinity it is the string "+Inf" or "-Inf". For positive
+ // or negative zero it is "0" or "-0". For NaN, it is the string "NaN".
+ fmt.Fprintf(b, "%T(%v)\n", t, t)
+ }
+ case float64:
+ if math.IsNaN(t) && math.Float64bits(t) != math.Float64bits(math.NaN()) {
+ fmt.Fprintf(b, "math.Float64frombits(0x%x)\n", math.Float64bits(t))
+ } else {
+ fmt.Fprintf(b, "%T(%v)\n", t, t)
+ }
case string:
fmt.Fprintf(b, "string(%q)\n", t)
case rune: // int32
- fmt.Fprintf(b, "rune(%q)\n", t)
+ // Although rune and int32 are represented by the same type, only a subset
+ // of valid int32 values can be expressed as rune literals. Notably,
+ // negative numbers, surrogate halves, and values above unicode.MaxRune
+ // have no quoted representation.
+ //
+ // fmt with "%q" (and the corresponding functions in the strconv package)
+ // would quote out-of-range values to the Unicode replacement character
+ // instead of the original value (see https://go.dev/issue/51526), so
+ // they must be treated as int32 instead.
+ //
+ // We arbitrarily draw the line at UTF-8 validity, which biases toward the
+ // "rune" interpretation. (However, we accept either format as input.)
+ if utf8.ValidRune(t) {
+ fmt.Fprintf(b, "rune(%q)\n", t)
+ } else {
+ fmt.Fprintf(b, "int32(%v)\n", t)
+ }
case byte: // uint8
+ // For bytes, we arbitrarily prefer the character interpretation.
+ // (Every byte has a valid character encoding.)
fmt.Fprintf(b, "byte(%q)\n", t)
case []byte: // []uint8
fmt.Fprintf(b, "[]byte(%q)\n", t)
@@ -105,44 +158,78 @@
return []byte(s), nil
}
- idType, ok := call.Fun.(*ast.Ident)
- if !ok {
- return nil, fmt.Errorf("expected []byte or primitive type")
- }
- if idType.Name == "bool" {
- id, ok := arg.(*ast.Ident)
+ var idType *ast.Ident
+ if selector, ok := call.Fun.(*ast.SelectorExpr); ok {
+ xIdent, ok := selector.X.(*ast.Ident)
+ if !ok || xIdent.Name != "math" {
+ return nil, fmt.Errorf("invalid selector type")
+ }
+ switch selector.Sel.Name {
+ case "Float64frombits":
+ idType = &ast.Ident{Name: "float64-bits"}
+ case "Float32frombits":
+ idType = &ast.Ident{Name: "float32-bits"}
+ default:
+ return nil, fmt.Errorf("invalid selector type")
+ }
+ } else {
+ idType, ok = call.Fun.(*ast.Ident)
if !ok {
- return nil, fmt.Errorf("malformed bool")
+ return nil, fmt.Errorf("expected []byte or primitive type")
}
- if id.Name == "true" {
- return true, nil
- } else if id.Name == "false" {
- return false, nil
- } else {
- return nil, fmt.Errorf("true or false required for type bool")
+ if idType.Name == "bool" {
+ id, ok := arg.(*ast.Ident)
+ if !ok {
+ return nil, fmt.Errorf("malformed bool")
+ }
+ if id.Name == "true" {
+ return true, nil
+ } else if id.Name == "false" {
+ return false, nil
+ } else {
+ return nil, fmt.Errorf("true or false required for type bool")
+ }
}
}
+
var (
val string
kind token.Token
)
if op, ok := arg.(*ast.UnaryExpr); ok {
- // Special case for negative numbers.
- lit, ok := op.X.(*ast.BasicLit)
- if !ok || (lit.Kind != token.INT && lit.Kind != token.FLOAT) {
+ switch lit := op.X.(type) {
+ case *ast.BasicLit:
+ if op.Op != token.SUB {
+ return nil, fmt.Errorf("unsupported operation on int/float: %v", op.Op)
+ }
+ // Special case for negative numbers.
+ val = op.Op.String() + lit.Value // e.g. "-" + "124"
+ kind = lit.Kind
+ case *ast.Ident:
+ if lit.Name != "Inf" {
+ return nil, fmt.Errorf("expected operation on int or float type")
+ }
+ if op.Op == token.SUB {
+ val = "-Inf"
+ } else {
+ val = "+Inf"
+ }
+ kind = token.FLOAT
+ default:
return nil, fmt.Errorf("expected operation on int or float type")
}
- if op.Op != token.SUB {
- return nil, fmt.Errorf("unsupported operation on int: %v", op.Op)
- }
- val = op.Op.String() + lit.Value // e.g. "-" + "124"
- kind = lit.Kind
} else {
- lit, ok := arg.(*ast.BasicLit)
- if !ok {
+ switch lit := arg.(type) {
+ case *ast.BasicLit:
+ val, kind = lit.Value, lit.Kind
+ case *ast.Ident:
+ if lit.Name != "NaN" {
+ return nil, fmt.Errorf("literal value required for primitive type")
+ }
+ val, kind = "NaN", token.FLOAT
+ default:
return nil, fmt.Errorf("literal value required for primitive type")
}
- val, kind = lit.Value, lit.Kind
}
switch typ := idType.Name; typ {
@@ -152,6 +239,14 @@
}
return strconv.Unquote(val)
case "byte", "rune":
+ if kind == token.INT {
+ switch typ {
+ case "rune":
+ return parseInt(val, typ)
+ case "byte":
+ return parseUint(val, typ)
+ }
+ }
if kind != token.CHAR {
return nil, fmt.Errorf("character literal required for byte/rune types")
}
@@ -191,6 +286,24 @@
return nil, fmt.Errorf("float or integer literal required for float64 type")
}
return strconv.ParseFloat(val, 64)
+ case "float32-bits":
+ if kind != token.INT {
+ return nil, fmt.Errorf("integer literal required for math.Float32frombits type")
+ }
+ bits, err := parseUint(val, "uint32")
+ if err != nil {
+ return nil, err
+ }
+ return math.Float32frombits(bits.(uint32)), nil
+ case "float64-bits":
+ if kind != token.FLOAT && kind != token.INT {
+ return nil, fmt.Errorf("integer literal required for math.Float64frombits type")
+ }
+ bits, err := parseUint(val, "uint64")
+ if err != nil {
+ return nil, err
+ }
+ return math.Float64frombits(bits.(uint64)), nil
default:
return nil, fmt.Errorf("expected []byte or primitive type")
}
@@ -200,18 +313,24 @@
func parseInt(val, typ string) (any, error) {
switch typ {
case "int":
- return strconv.Atoi(val)
+ // The int type may be either 32 or 64 bits. If 32, the fuzz tests in the
+ // corpus may include 64-bit values produced by fuzzing runs on 64-bit
+ // architectures. When running those tests, we implicitly wrap the values to
+ // fit in a regular int. (The test case is still “interesting”, even if the
+ // specific values of its inputs are platform-dependent.)
+ i, err := strconv.ParseInt(val, 0, 64)
+ return int(i), err
case "int8":
- i, err := strconv.ParseInt(val, 10, 8)
+ i, err := strconv.ParseInt(val, 0, 8)
return int8(i), err
case "int16":
- i, err := strconv.ParseInt(val, 10, 16)
+ i, err := strconv.ParseInt(val, 0, 16)
return int16(i), err
- case "int32":
- i, err := strconv.ParseInt(val, 10, 32)
+ case "int32", "rune":
+ i, err := strconv.ParseInt(val, 0, 32)
return int32(i), err
case "int64":
- return strconv.ParseInt(val, 10, 64)
+ return strconv.ParseInt(val, 0, 64)
default:
panic("unreachable")
}
@@ -221,19 +340,19 @@
func parseUint(val, typ string) (any, error) {
switch typ {
case "uint":
- i, err := strconv.ParseUint(val, 10, 0)
+ i, err := strconv.ParseUint(val, 0, 64)
return uint(i), err
- case "uint8":
- i, err := strconv.ParseUint(val, 10, 8)
+ case "uint8", "byte":
+ i, err := strconv.ParseUint(val, 0, 8)
return uint8(i), err
case "uint16":
- i, err := strconv.ParseUint(val, 10, 16)
+ i, err := strconv.ParseUint(val, 0, 16)
return uint16(i), err
case "uint32":
- i, err := strconv.ParseUint(val, 10, 32)
+ i, err := strconv.ParseUint(val, 0, 32)
return uint32(i), err
case "uint64":
- return strconv.ParseUint(val, 10, 64)
+ return strconv.ParseUint(val, 0, 64)
default:
panic("unreachable")
}
diff --git a/src/internal/fuzz/encoding_test.go b/src/internal/fuzz/encoding_test.go
index b429d42..8e3800e 100644
--- a/src/internal/fuzz/encoding_test.go
+++ b/src/internal/fuzz/encoding_test.go
@@ -5,85 +5,104 @@
package fuzz
import (
+ "math"
"strconv"
- "strings"
"testing"
+ "unicode"
)
func TestUnmarshalMarshal(t *testing.T) {
var tests = []struct {
- in string
- ok bool
+ desc string
+ in string
+ reject bool
+ want string // if different from in
}{
{
- in: "int(1234)",
- ok: false, // missing version
+ desc: "missing version",
+ in: "int(1234)",
+ reject: true,
},
{
+ desc: "malformed string",
in: `go test fuzz v1
string("a"bcad")`,
- ok: false, // malformed
+ reject: true,
},
{
+ desc: "empty value",
in: `go test fuzz v1
int()`,
- ok: false, // empty value
+ reject: true,
},
{
+ desc: "negative uint",
in: `go test fuzz v1
uint(-32)`,
- ok: false, // invalid negative uint
+ reject: true,
},
{
+ desc: "int8 too large",
in: `go test fuzz v1
int8(1234456)`,
- ok: false, // int8 too large
+ reject: true,
},
{
+ desc: "multiplication in int value",
in: `go test fuzz v1
int(20*5)`,
- ok: false, // expression in int value
+ reject: true,
},
{
+ desc: "double negation",
in: `go test fuzz v1
int(--5)`,
- ok: false, // expression in int value
+ reject: true,
},
{
+ desc: "malformed bool",
in: `go test fuzz v1
bool(0)`,
- ok: false, // malformed bool
+ reject: true,
},
{
+ desc: "malformed byte",
in: `go test fuzz v1
byte('aa)`,
- ok: false, // malformed byte
+ reject: true,
},
{
+ desc: "byte out of range",
in: `go test fuzz v1
byte('☃')`,
- ok: false, // byte out of range
+ reject: true,
},
{
+ desc: "extra newline",
in: `go test fuzz v1
-string("has final newline")
+string("has extra newline")
`,
- ok: true, // has final newline
+ want: `go test fuzz v1
+string("has extra newline")`,
},
{
+ desc: "trailing spaces",
in: `go test fuzz v1
string("extra")
[]byte("spacing")
`,
- ok: true, // extra spaces in the final newline
+ want: `go test fuzz v1
+string("extra")
+[]byte("spacing")`,
},
{
+ desc: "float types",
in: `go test fuzz v1
float64(0)
float32(0)`,
- ok: true, // will be an integer literal since there is no decimal
},
{
+ desc: "various types",
in: `go test fuzz v1
int(-23)
int8(-2)
@@ -101,19 +120,112 @@
string("hello\\xbd\\xb2=\\xbc ⌘")
float64(-12.5)
float32(2.5)`,
- ok: true,
+ },
+ {
+ desc: "float edge cases",
+ // The two IEEE 754 bit patterns used for the math.Float{64,32}frombits
+ // encodings are non-math.NAN quiet-NaN values. Since they are not equal
+ // to math.NaN(), they should be re-encoded to their bit patterns. They
+ // are, respectively:
+ // * math.Float64bits(math.NaN())+1
+ // * math.Float32bits(float32(math.NaN()))+1
+ in: `go test fuzz v1
+float32(-0)
+float64(-0)
+float32(+Inf)
+float32(-Inf)
+float32(NaN)
+float64(+Inf)
+float64(-Inf)
+float64(NaN)
+math.Float64frombits(0x7ff8000000000002)
+math.Float32frombits(0x7fc00001)`,
+ },
+ {
+ desc: "int variations",
+ // Although we arbitrarily choose default integer bases (0 or 16), we may
+ // want to change those arbitrary choices in the future and should not
+ // break the parser. Verify that integers in the opposite bases still
+ // parse correctly.
+ in: `go test fuzz v1
+int(0x0)
+int32(0x41)
+int64(0xfffffffff)
+uint32(0xcafef00d)
+uint64(0xffffffffffffffff)
+uint8(0b0000000)
+byte(0x0)
+byte('\000')
+byte('\u0000')
+byte('\'')
+math.Float64frombits(9221120237041090562)
+math.Float32frombits(2143289345)`,
+ want: `go test fuzz v1
+int(0)
+rune('A')
+int64(68719476735)
+uint32(3405705229)
+uint64(18446744073709551615)
+byte('\x00')
+byte('\x00')
+byte('\x00')
+byte('\x00')
+byte('\'')
+math.Float64frombits(0x7ff8000000000002)
+math.Float32frombits(0x7fc00001)`,
+ },
+ {
+ desc: "rune validation",
+ in: `go test fuzz v1
+rune(0)
+rune(0x41)
+rune(-1)
+rune(0xfffd)
+rune(0xd800)
+rune(0x10ffff)
+rune(0x110000)
+`,
+ want: `go test fuzz v1
+rune('\x00')
+rune('A')
+int32(-1)
+rune('�')
+int32(55296)
+rune('\U0010ffff')
+int32(1114112)`,
+ },
+ {
+ desc: "int overflow",
+ in: `go test fuzz v1
+int(0x7fffffffffffffff)
+uint(0xffffffffffffffff)`,
+ want: func() string {
+ switch strconv.IntSize {
+ case 32:
+ return `go test fuzz v1
+int(-1)
+uint(4294967295)`
+ case 64:
+ return `go test fuzz v1
+int(9223372036854775807)
+uint(18446744073709551615)`
+ default:
+ panic("unreachable")
+ }
+ }(),
},
}
for _, test := range tests {
- t.Run(test.in, func(t *testing.T) {
+ t.Run(test.desc, func(t *testing.T) {
vals, err := unmarshalCorpusFile([]byte(test.in))
- if test.ok && err != nil {
- t.Fatalf("unmarshal unexpected error: %v", err)
- } else if !test.ok && err == nil {
- t.Fatalf("unmarshal unexpected success")
+ if test.reject {
+ if err == nil {
+ t.Fatalf("unmarshal unexpected success")
+ }
+ return
}
- if !test.ok {
- return // skip the rest of the test
+ if err != nil {
+ t.Fatalf("unmarshal unexpected error: %v", err)
}
newB := marshalCorpusFile(vals...)
if err != nil {
@@ -122,9 +234,15 @@
if newB[len(newB)-1] != '\n' {
t.Error("didn't write final newline to corpus file")
}
- before, after := strings.TrimSpace(test.in), strings.TrimSpace(string(newB))
- if before != after {
- t.Errorf("values changed after unmarshal then marshal\nbefore: %q\nafter: %q", before, after)
+
+ want := test.want
+ if want == "" {
+ want = test.in
+ }
+ want += "\n"
+ got := string(newB)
+ if got != want {
+ t.Errorf("unexpected marshaled value\ngot:\n%s\nwant:\n%s", got, want)
}
})
}
@@ -170,3 +288,117 @@
})
}
}
+
+func TestByteRoundTrip(t *testing.T) {
+ for x := 0; x < 256; x++ {
+ b1 := byte(x)
+ buf := marshalCorpusFile(b1)
+ vs, err := unmarshalCorpusFile(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ b2 := vs[0].(byte)
+ if b2 != b1 {
+ t.Fatalf("unmarshaled %v, want %v:\n%s", b2, b1, buf)
+ }
+ }
+}
+
+func TestInt8RoundTrip(t *testing.T) {
+ for x := -128; x < 128; x++ {
+ i1 := int8(x)
+ buf := marshalCorpusFile(i1)
+ vs, err := unmarshalCorpusFile(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ i2 := vs[0].(int8)
+ if i2 != i1 {
+ t.Fatalf("unmarshaled %v, want %v:\n%s", i2, i1, buf)
+ }
+ }
+}
+
+func FuzzFloat64RoundTrip(f *testing.F) {
+ f.Add(math.Float64bits(0))
+ f.Add(math.Float64bits(math.Copysign(0, -1)))
+ f.Add(math.Float64bits(math.MaxFloat64))
+ f.Add(math.Float64bits(math.SmallestNonzeroFloat64))
+ f.Add(math.Float64bits(math.NaN()))
+ f.Add(uint64(0x7FF0000000000001)) // signaling NaN
+ f.Add(math.Float64bits(math.Inf(1)))
+ f.Add(math.Float64bits(math.Inf(-1)))
+
+ f.Fuzz(func(t *testing.T, u1 uint64) {
+ x1 := math.Float64frombits(u1)
+
+ b := marshalCorpusFile(x1)
+ t.Logf("marshaled math.Float64frombits(0x%x):\n%s", u1, b)
+
+ xs, err := unmarshalCorpusFile(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(xs) != 1 {
+ t.Fatalf("unmarshaled %d values", len(xs))
+ }
+ x2 := xs[0].(float64)
+ u2 := math.Float64bits(x2)
+ if u2 != u1 {
+ t.Errorf("unmarshaled %v (bits 0x%x)", x2, u2)
+ }
+ })
+}
+
+func FuzzRuneRoundTrip(f *testing.F) {
+ f.Add(rune(-1))
+ f.Add(rune(0xd800))
+ f.Add(rune(0xdfff))
+ f.Add(rune(unicode.ReplacementChar))
+ f.Add(rune(unicode.MaxASCII))
+ f.Add(rune(unicode.MaxLatin1))
+ f.Add(rune(unicode.MaxRune))
+ f.Add(rune(unicode.MaxRune + 1))
+ f.Add(rune(-0x80000000))
+ f.Add(rune(0x7fffffff))
+
+ f.Fuzz(func(t *testing.T, r1 rune) {
+ b := marshalCorpusFile(r1)
+ t.Logf("marshaled rune(0x%x):\n%s", r1, b)
+
+ rs, err := unmarshalCorpusFile(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(rs) != 1 {
+ t.Fatalf("unmarshaled %d values", len(rs))
+ }
+ r2 := rs[0].(rune)
+ if r2 != r1 {
+ t.Errorf("unmarshaled rune(0x%x)", r2)
+ }
+ })
+}
+
+func FuzzStringRoundTrip(f *testing.F) {
+ f.Add("")
+ f.Add("\x00")
+ f.Add(string([]rune{unicode.ReplacementChar}))
+
+ f.Fuzz(func(t *testing.T, s1 string) {
+ b := marshalCorpusFile(s1)
+ t.Logf("marshaled %q:\n%s", s1, b)
+
+ rs, err := unmarshalCorpusFile(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(rs) != 1 {
+ t.Fatalf("unmarshaled %d values", len(rs))
+ }
+ s2 := rs[0].(string)
+ if s2 != s1 {
+ t.Errorf("unmarshaled %q", s2)
+ }
+ })
+}
diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go
index b3f1381..3ccf747 100644
--- a/src/internal/fuzz/fuzz.go
+++ b/src/internal/fuzz/fuzz.go
@@ -316,32 +316,15 @@
} else {
// Update the coordinator's coverage mask and save the value.
inputSize := len(result.entry.Data)
- if opts.CacheDir != "" {
- // It is possible that the input that was discovered is already
- // present in the corpus, but the worker produced a coverage map
- // that still expanded our total coverage (this may happen due to
- // flakiness in the coverage counters). In order to prevent adding
- // duplicate entries to the corpus (and re-writing the file on
- // disk), skip it if the on disk file already exists.
- // TOOD(roland): this check is limited in that it will only be
- // applied if we are using the CacheDir. Another option would be
- // to iterate through the corpus and check if it is already present,
- // which would catch cases where we are not caching entries.
- // A slightly faster approach would be to keep some kind of map of
- // entry hashes, which would allow us to avoid iterating through
- // all entries.
- _, err = os.Stat(result.entry.Path)
- if err == nil {
- continue
- }
- err := writeToCorpus(&result.entry, opts.CacheDir)
- if err != nil {
- stop(err)
- }
- result.entry.Data = nil
+ entryNew, err := c.addCorpusEntries(true, result.entry)
+ if err != nil {
+ stop(err)
+ break
+ }
+ if !entryNew {
+ continue
}
c.updateCoverage(keepCoverage)
- c.corpus.entries = append(c.corpus.entries, result.entry)
c.inputQueue.enqueue(result.entry)
c.interestingCount++
if shouldPrintDebugInfo() {
@@ -433,6 +416,38 @@
type corpus struct {
entries []CorpusEntry
+ hashes map[[sha256.Size]byte]bool
+}
+
+// addCorpusEntries adds entries to the corpus, and optionally writes the entries
+// to the cache directory. If an entry is already in the corpus it is skipped. If
+// all of the entries are unique, addCorpusEntries returns true and a nil error,
+// if at least one of the entries was a duplicate, it returns false and a nil error.
+func (c *coordinator) addCorpusEntries(addToCache bool, entries ...CorpusEntry) (bool, error) {
+ noDupes := true
+ for _, e := range entries {
+ data, err := corpusEntryData(e)
+ if err != nil {
+ return false, err
+ }
+ h := sha256.Sum256(data)
+ if c.corpus.hashes[h] {
+ noDupes = false
+ continue
+ }
+ if addToCache {
+ if err := writeToCorpus(&e, c.opts.CacheDir); err != nil {
+ return false, err
+ }
+ // For entries written to disk, we don't hold onto the bytes,
+ // since the corpus would consume a significant amount of
+ // memory.
+ e.Data = nil
+ }
+ c.corpus.hashes[h] = true
+ c.corpus.entries = append(c.corpus.entries, e)
+ }
+ return noDupes, nil
}
// CorpusEntry represents an individual input for fuzzing.
@@ -463,9 +478,9 @@
IsSeed bool
}
-// Data returns the raw input bytes, either from the data struct field,
-// or from disk.
-func CorpusEntryData(ce CorpusEntry) ([]byte, error) {
+// corpusEntryData returns the raw input bytes, either from the data struct
+// field, or from disk.
+func corpusEntryData(ce CorpusEntry) ([]byte, error) {
if ce.Data != nil {
return ce.Data, nil
}
@@ -582,7 +597,7 @@
// interestingCount is the number of unique interesting values which have
// been found this execution.
- interestingCount int64
+ interestingCount int
// warmupInputCount is the count of all entries in the corpus which will
// need to be received from workers to run once during warmup, but not fuzz.
@@ -640,18 +655,17 @@
opts.Seed[i].Data = marshalCorpusFile(opts.Seed[i].Values...)
}
}
- corpus, err := readCache(opts.Seed, opts.Types, opts.CacheDir)
- if err != nil {
- return nil, err
- }
c := &coordinator{
opts: opts,
startTime: time.Now(),
inputC: make(chan fuzzInput),
minimizeC: make(chan fuzzMinimizeInput),
resultC: make(chan fuzzResult),
- corpus: corpus,
timeLastLog: time.Now(),
+ corpus: corpus{hashes: make(map[[sha256.Size]byte]bool)},
+ }
+ if err := c.readCache(); err != nil {
+ return nil, err
}
if opts.MinimizeLimit > 0 || opts.MinimizeTimeout > 0 {
for _, t := range opts.Types {
@@ -691,7 +705,7 @@
data := marshalCorpusFile(vals...)
h := sha256.Sum256(data)
name := fmt.Sprintf("%x", h[:4])
- c.corpus.entries = append(c.corpus.entries, CorpusEntry{Path: name, Data: data})
+ c.addCorpusEntries(false, CorpusEntry{Path: name, Data: data})
}
return c, nil
@@ -717,8 +731,8 @@
} else {
rate := float64(c.count-c.countLastLog) / now.Sub(c.timeLastLog).Seconds()
if coverageEnabled {
- interestingTotalCount := int64(c.warmupInputCount-len(c.opts.Seed)) + c.interestingCount
- fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), new interesting: %d (total: %d)\n", c.elapsed(), c.count, rate, c.interestingCount, interestingTotalCount)
+ total := c.warmupInputCount + c.interestingCount
+ fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), new interesting: %d (total: %d)\n", c.elapsed(), c.count, rate, c.interestingCount, total)
} else {
fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec)\n", c.elapsed(), c.count, rate)
}
@@ -908,22 +922,25 @@
//
// TODO(fuzzing): need a mechanism that can remove values that
// aren't useful anymore, for example, because they have the wrong type.
-func readCache(seed []CorpusEntry, types []reflect.Type, cacheDir string) (corpus, error) {
- var c corpus
- c.entries = append(c.entries, seed...)
- entries, err := ReadCorpus(cacheDir, types)
+func (c *coordinator) readCache() error {
+ if _, err := c.addCorpusEntries(false, c.opts.Seed...); err != nil {
+ return err
+ }
+ entries, err := ReadCorpus(c.opts.CacheDir, c.opts.Types)
if err != nil {
if _, ok := err.(*MalformedCorpusError); !ok {
// It's okay if some files in the cache directory are malformed and
// are not included in the corpus, but fail if it's an I/O error.
- return corpus{}, err
+ return err
}
// TODO(jayconrod,katiehockman): consider printing some kind of warning
// indicating the number of files which were skipped because they are
// malformed.
}
- c.entries = append(c.entries, entries...)
- return c, nil
+ if _, err := c.addCorpusEntries(false, entries...); err != nil {
+ return err
+ }
+ return nil
}
// MalformedCorpusError is an error found while reading the corpus from the
diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go
index 6e5f318..2db2633 100644
--- a/src/internal/fuzz/minimize_test.go
+++ b/src/internal/fuzz/minimize_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build darwin || linux || windows
+//go:build darwin || freebsd || linux || windows
package fuzz
diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go
index 89c86c1..fec6054 100644
--- a/src/internal/fuzz/sys_posix.go
+++ b/src/internal/fuzz/sys_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build darwin || linux
+//go:build darwin || freebsd || linux
package fuzz
diff --git a/src/internal/fuzz/sys_unimplemented.go b/src/internal/fuzz/sys_unimplemented.go
index 123a325..f84dae6 100644
--- a/src/internal/fuzz/sys_unimplemented.go
+++ b/src/internal/fuzz/sys_unimplemented.go
@@ -4,7 +4,7 @@
// If you update this constraint, also update cmd/internal/sys.FuzzSupported.
//
-//go:build !darwin && !linux && !windows
+//go:build !darwin && !freebsd && !linux && !windows
package fuzz
diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go
index c2d5532..6e4c4e2 100644
--- a/src/internal/fuzz/worker.go
+++ b/src/internal/fuzz/worker.go
@@ -800,6 +800,7 @@
if err != nil {
panic(err)
}
+ inpHash := sha256.Sum256(mem.valueCopy())
if args.Timeout != 0 {
var cancel func()
ctx, cancel = context.WithTimeout(ctx, args.Timeout)
@@ -811,12 +812,22 @@
success, err := ws.minimizeInput(ctx, vals, mem, args)
if success {
writeToMem(vals, mem)
+ outHash := sha256.Sum256(mem.valueCopy())
mem.header().rawInMem = false
resp.WroteToMem = true
if err != nil {
resp.Err = err.Error()
} else {
- resp.CoverageData = coverageSnapshot
+ // If the values didn't change during minimization then coverageSnapshot is likely
+ // a dirty snapshot which represents the very last step of minimization, not the
+ // coverage for the initial input. In that case just return the coverage we were
+ // given initially, since it more accurately represents the coverage map for the
+ // input we are returning.
+ if outHash != inpHash {
+ resp.CoverageData = coverageSnapshot
+ } else {
+ resp.CoverageData = args.KeepCoverage
+ }
}
}
return resp
@@ -883,7 +894,8 @@
}
return true
}
- if keepCoverage != nil && hasCoverageBit(keepCoverage, coverageSnapshot) {
+ // Minimization should preserve coverage bits.
+ if keepCoverage != nil && isCoverageSubset(keepCoverage, coverageSnapshot) {
return true
}
vals[args.Index] = prev
@@ -973,7 +985,7 @@
return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed
}
mem.header().count = 0
- inp, err := CorpusEntryData(entryIn)
+ inp, err := corpusEntryData(entryIn)
if err != nil {
return CorpusEntry{}, minimizeResponse{}, err
}
@@ -1059,7 +1071,7 @@
return CorpusEntry{}, fuzzResponse{}, true, errSharedMemClosed
}
mem.header().count = 0
- inp, err := CorpusEntryData(entryIn)
+ inp, err := corpusEntryData(entryIn)
if err != nil {
return CorpusEntry{}, fuzzResponse{}, true, err
}
diff --git a/src/internal/nettrace/nettrace.go b/src/internal/nettrace/nettrace.go
index 94f38a7..6e0dbe7 100644
--- a/src/internal/nettrace/nettrace.go
+++ b/src/internal/nettrace/nettrace.go
@@ -27,7 +27,7 @@
DNSStart func(name string)
// DNSDone is called after a DNS lookup completes (or fails).
- // The coalesced parameter is whether singleflight de-dupped
+ // The coalesced parameter is whether singleflight de-duped
// the call. The addrs are of type net.IPAddr but can't
// actually be for circular dependency reasons.
DNSDone func(netIPs []any, coalesced bool, err error)
diff --git a/src/math/big/rat.go b/src/math/big/rat.go
index d35cd4c..731a979 100644
--- a/src/math/big/rat.go
+++ b/src/math/big/rat.go
@@ -418,7 +418,7 @@
// If the result is a reference to x's denominator it
// may change if a new value is assigned to x, and vice versa.
func (x *Rat) Denom() *Int {
- x.b.neg = false // the result is always >= 0
+ // Note that x.b.neg is guaranteed false.
if len(x.b.abs) == 0 {
// Note: If this proves problematic, we could
// panic instead and require the Rat to
diff --git a/src/math/big/rat_test.go b/src/math/big/rat_test.go
index 02569c1..d98c89b 100644
--- a/src/math/big/rat_test.go
+++ b/src/math/big/rat_test.go
@@ -726,3 +726,21 @@
}
}
}
+
+func TestDenomRace(t *testing.T) {
+ x := NewRat(1, 2)
+ const N = 3
+ c := make(chan bool, N)
+ for i := 0; i < N; i++ {
+ go func() {
+ // Denom (also used by Float.SetRat) used to mutate x unnecessarily,
+ // provoking race reports when run in the race detector.
+ x.Denom()
+ new(Float).SetRat(x)
+ c <- true
+ }()
+ }
+ for i := 0; i < N; i++ {
+ <-c
+ }
+}
diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go
index ac3c8bd..90053a9 100644
--- a/src/math/big/ratconv.go
+++ b/src/math/big/ratconv.go
@@ -169,6 +169,11 @@
n := exp5
if n < 0 {
n = -n
+ if n < 0 {
+ // This can occur if -n overflows. -(-1 << 63) would become
+ // -1 << 63, which is still negative.
+ return nil, false
+ }
}
if n > 1e6 {
return nil, false // avoid excessively large exponents
diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go
index 15d206c..e55e655 100644
--- a/src/math/big/ratconv_test.go
+++ b/src/math/big/ratconv_test.go
@@ -104,6 +104,7 @@
{in: "4/3/"},
{in: "4/3."},
{in: "4/"},
+ {in: "13e-9223372036854775808"}, // CVE-2022-23772
// valid
{"0", "0", true},
diff --git a/src/net/conn_test.go b/src/net/conn_test.go
index 3403edd..d168dda 100644
--- a/src/net/conn_test.go
+++ b/src/net/conn_test.go
@@ -17,7 +17,7 @@
// someTimeout is used just to test that net.Conn implementations
// don't explode when their SetFooDeadline methods are called.
// It isn't actually used for testing timeouts.
-const someTimeout = 10 * time.Second
+const someTimeout = 1 * time.Hour
func TestConnAndListener(t *testing.T) {
for i, network := range []string{"tcp", "unix", "unixpacket"} {
diff --git a/src/net/dial_test.go b/src/net/dial_test.go
index e0c9cdc..b9aead0 100644
--- a/src/net/dial_test.go
+++ b/src/net/dial_test.go
@@ -429,14 +429,15 @@
readDeadline = time.Now().Add(5 * time.Second)
}
- var wg sync.WaitGroup
- wg.Add(2)
+ var closed sync.WaitGroup
+ closed.Add(2)
handler := func(dss *dualStackServer, ln Listener) {
// Accept one connection per address.
c, err := ln.Accept()
if err != nil {
t.Fatal(err)
}
+
// The client should close itself, without sending data.
c.SetReadDeadline(readDeadline)
var b [1]byte
@@ -444,7 +445,7 @@
t.Errorf("got %v; want %v", err, io.EOF)
}
c.Close()
- wg.Done()
+ closed.Done()
}
dss, err := newDualStackServer()
if err != nil {
@@ -457,12 +458,16 @@
const fallbackDelay = 100 * time.Millisecond
+ var dialing sync.WaitGroup
+ dialing.Add(2)
origTestHookDialTCP := testHookDialTCP
defer func() { testHookDialTCP = origTestHookDialTCP }()
testHookDialTCP = func(ctx context.Context, net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
- // Sleep long enough for Happy Eyeballs to kick in, and inhibit cancellation.
+ // Wait until Happy Eyeballs kicks in and both connections are dialing,
+ // and inhibit cancellation.
// This forces dialParallel to juggle two successful connections.
- time.Sleep(fallbackDelay * 2)
+ dialing.Done()
+ dialing.Wait()
// Now ignore the provided context (which will be canceled) and use a
// different one to make sure this completes with a valid connection,
@@ -496,7 +501,7 @@
c.Close()
// The server should've seen both connections.
- wg.Wait()
+ closed.Wait()
}
func TestDialerPartialDeadline(t *testing.T) {
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index 21aa91f..9a4a6ee 100644
--- a/src/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.go
@@ -30,6 +30,10 @@
// to be used as a useTCP parameter to exchange
useTCPOnly = true
useUDPOrTCP = false
+
+ // Maximum DNS packet size.
+ // Value taken from https://dnsflagday.net/2020/.
+ maxDNSPacketSize = 1232
)
var (
@@ -82,7 +86,7 @@
return dnsmessage.Parser{}, dnsmessage.Header{}, err
}
- b = make([]byte, 512) // see RFC 1035
+ b = make([]byte, maxDNSPacketSize)
for {
n, err := c.Read(b)
if err != nil {
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 14366ec..e46deca 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -881,7 +881,7 @@
func TestIgnoreDNSForgeries(t *testing.T) {
c, s := Pipe()
go func() {
- b := make([]byte, 512)
+ b := make([]byte, maxDNSPacketSize)
n, err := s.Read(b)
if err != nil {
t.Error(err)
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
index c2ea6f4..e91d526 100644
--- a/src/net/http/client_test.go
+++ b/src/net/http/client_test.go
@@ -13,6 +13,7 @@
"encoding/base64"
"errors"
"fmt"
+ "internal/testenv"
"io"
"log"
"net"
@@ -21,6 +22,7 @@
"net/http/httptest"
"net/url"
"reflect"
+ "runtime"
"strconv"
"strings"
"sync"
@@ -1289,6 +1291,9 @@
t.Errorf("net.Error.Timeout = false; want true")
}
if got := ne.Error(); !strings.Contains(got, "(Client.Timeout") {
+ if runtime.GOOS == "windows" && strings.HasPrefix(runtime.GOARCH, "arm") {
+ testenv.SkipFlaky(t, 43120)
+ }
t.Errorf("error string = %q; missing timeout substring", got)
}
@@ -1334,6 +1339,9 @@
t.Error("net.Error.Timeout = false; want true")
}
if got := ne.Error(); !strings.Contains(got, "Client.Timeout exceeded") {
+ if runtime.GOOS == "windows" && strings.HasPrefix(runtime.GOARCH, "arm") {
+ testenv.SkipFlaky(t, 43120)
+ }
t.Errorf("error string = %q; missing timeout substring", got)
}
}
diff --git a/src/net/http/fs.go b/src/net/http/fs.go
index 19b2894..6caee9e 100644
--- a/src/net/http/fs.go
+++ b/src/net/http/fs.go
@@ -42,20 +42,20 @@
// An empty Dir is treated as ".".
type Dir string
-// mapDirOpenError maps the provided non-nil error from opening name
+// mapOpenError maps the provided non-nil error from opening name
// to a possibly better non-nil error. In particular, it turns OS-specific errors
-// about opening files in non-directories into fs.ErrNotExist. See Issue 18984.
-func mapDirOpenError(originalErr error, name string) error {
+// about opening files in non-directories into fs.ErrNotExist. See Issues 18984 and 49552.
+func mapOpenError(originalErr error, name string, sep rune, stat func(string) (fs.FileInfo, error)) error {
if errors.Is(originalErr, fs.ErrNotExist) || errors.Is(originalErr, fs.ErrPermission) {
return originalErr
}
- parts := strings.Split(name, string(filepath.Separator))
+ parts := strings.Split(name, string(sep))
for i := range parts {
if parts[i] == "" {
continue
}
- fi, err := os.Stat(strings.Join(parts[:i+1], string(filepath.Separator)))
+ fi, err := stat(strings.Join(parts[:i+1], string(sep)))
if err != nil {
return originalErr
}
@@ -79,7 +79,7 @@
fullName := filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))
f, err := os.Open(fullName)
if err != nil {
- return nil, mapDirOpenError(err, fullName)
+ return nil, mapOpenError(err, fullName, filepath.Separator, os.Stat)
}
return f, nil
}
@@ -759,7 +759,9 @@
}
file, err := f.fsys.Open(name)
if err != nil {
- return nil, err
+ return nil, mapOpenError(err, name, '/', func(path string) (fs.FileInfo, error) {
+ return fs.Stat(f.fsys, path)
+ })
}
return ioFile{file}, nil
}
diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go
index 4b01cce..d627dfd 100644
--- a/src/net/http/fs_test.go
+++ b/src/net/http/fs_test.go
@@ -1244,10 +1244,19 @@
}
}
-// Issue 18984: tests that requests for paths beyond files return not-found errors
+// Issues 18984, 49552: tests that requests for paths beyond files return not-found errors
func TestFileServerNotDirError(t *testing.T) {
defer afterTest(t)
- ts := httptest.NewServer(FileServer(Dir("testdata")))
+ t.Run("Dir", func(t *testing.T) {
+ testFileServerNotDirError(t, func(path string) FileSystem { return Dir(path) })
+ })
+ t.Run("FS", func(t *testing.T) {
+ testFileServerNotDirError(t, func(path string) FileSystem { return FS(os.DirFS(path)) })
+ })
+}
+
+func testFileServerNotDirError(t *testing.T, newfs func(string) FileSystem) {
+ ts := httptest.NewServer(FileServer(newfs("testdata")))
defer ts.Close()
res, err := Get(ts.URL + "/index.html/not-a-file")
@@ -1259,9 +1268,9 @@
t.Errorf("StatusCode = %v; want 404", res.StatusCode)
}
- test := func(name string, dir Dir) {
+ test := func(name string, fsys FileSystem) {
t.Run(name, func(t *testing.T) {
- _, err = dir.Open("/index.html/not-a-file")
+ _, err = fsys.Open("/index.html/not-a-file")
if err == nil {
t.Fatal("err == nil; want != nil")
}
@@ -1270,7 +1279,7 @@
errors.Is(err, fs.ErrNotExist))
}
- _, err = dir.Open("/index.html/not-a-dir/not-a-file")
+ _, err = fsys.Open("/index.html/not-a-dir/not-a-file")
if err == nil {
t.Fatal("err == nil; want != nil")
}
@@ -1286,8 +1295,8 @@
t.Fatal("get abs path:", err)
}
- test("RelativePath", Dir("testdata"))
- test("AbsolutePath", Dir(absPath))
+ test("RelativePath", newfs("testdata"))
+ test("AbsolutePath", newfs(absPath))
}
func TestFileServerCleanPath(t *testing.T) {
diff --git a/src/net/http/internal/testcert/testcert.go b/src/net/http/internal/testcert/testcert.go
index 5f94704..d510e79 100644
--- a/src/net/http/internal/testcert/testcert.go
+++ b/src/net/http/internal/testcert/testcert.go
@@ -10,37 +10,56 @@
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
// generated from src/crypto/tls:
-// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
+// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
-MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
+MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
-MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
-iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
-rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
-BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
-AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
-AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
-tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
-h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
-fblo6RBxUQ==
+MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r
+bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U
+aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P
+YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk
+POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu
+h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE
+AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv
+bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI
+5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv
+cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2
++tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B
+grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK
+5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/
+WkBKOclmOV2xlTVuPw==
-----END CERTIFICATE-----`)
// LocalhostKey is the private key for LocalhostCert.
var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY-----
-MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
-SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
-l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
-AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
-3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
-uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
-qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
-jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
-fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
-fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
-y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
-qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
-f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDoZtrm0dXV0Aqi
+4Bpc7f95sNRTiu/AJSD8I1onY9PnEsPg3VVxvytsVJbYdcqr4w99V3AgpH/UNzMS
+gAZ/8lZBNbsSDOVesJ3euVqMRfYPvd9pYl6QPRRpSDPm+2tNdn3QFAvta9EgJ3sW
+URnoU85w+W6aLI2bNSq3AaE771p3VbkGolpEjo9h+i42TBHo1rhPNKPkGupR8/QX
+AOLMpInRdeaHyDwb2a3DE5I3dG7VAVzrVfJ6W6Q84YoFX+rpEE2SVM17SAjy6xQy
+VjKgLvK2mk0xbtfa+h0B6VK7bmODHZqeP18NVm6HsBcXn7iclLgAC3SfWU1jucZK
+x1lqzw9tAgMBAAECggEABWzxS1Y2wckblnXY57Z+sl6YdmLV+gxj2r8Qib7g4ZIk
+lIlWR1OJNfw7kU4eryib4fc6nOh6O4AWZyYqAK6tqNQSS/eVG0LQTLTTEldHyVJL
+dvBe+MsUQOj4nTndZW+QvFzbcm2D8lY5n2nBSxU5ypVoKZ1EqQzytFcLZpTN7d89
+EPj0qDyrV4NZlWAwL1AygCwnlwhMQjXEalVF1ylXwU3QzyZ/6MgvF6d3SSUlh+sq
+XefuyigXw484cQQgbzopv6niMOmGP3of+yV4JQqUSb3IDmmT68XjGd2Dkxl4iPki
+6ZwXf3CCi+c+i/zVEcufgZ3SLf8D99kUGE7v7fZ6AQKBgQD1ZX3RAla9hIhxCf+O
+3D+I1j2LMrdjAh0ZKKqwMR4JnHX3mjQI6LwqIctPWTU8wYFECSh9klEclSdCa64s
+uI/GNpcqPXejd0cAAdqHEEeG5sHMDt0oFSurL4lyud0GtZvwlzLuwEweuDtvT9cJ
+Wfvl86uyO36IW8JdvUprYDctrQKBgQDycZ697qutBieZlGkHpnYWUAeImVA878sJ
+w44NuXHvMxBPz+lbJGAg8Cn8fcxNAPqHIraK+kx3po8cZGQywKHUWsxi23ozHoxo
++bGqeQb9U661TnfdDspIXia+xilZt3mm5BPzOUuRqlh4Y9SOBpSWRmEhyw76w4ZP
+OPxjWYAgwQKBgA/FehSYxeJgRjSdo+MWnK66tjHgDJE8bYpUZsP0JC4R9DL5oiaA
+brd2fI6Y+SbyeNBallObt8LSgzdtnEAbjIH8uDJqyOmknNePRvAvR6mP4xyuR+Bv
+m+Lgp0DMWTw5J9CKpydZDItc49T/mJ5tPhdFVd+am0NAQnmr1MCZ6nHxAoGABS3Y
+LkaC9FdFUUqSU8+Chkd/YbOkuyiENdkvl6t2e52jo5DVc1T7mLiIrRQi4SI8N9bN
+/3oJWCT+uaSLX2ouCtNFunblzWHBrhxnZzTeqVq4SLc8aESAnbslKL4i8/+vYZlN
+s8xtiNcSvL+lMsOBORSXzpj/4Ot8WwTkn1qyGgECgYBKNTypzAHeLE6yVadFp3nQ
+Ckq9yzvP/ib05rvgbvrne00YeOxqJ9gtTrzgh7koqJyX1L4NwdkEza4ilDWpucn0
+xiUZS4SoaJq6ZvcBYS62Yr1t8n09iG47YL8ibgtmH3L+svaotvpVxVK+d7BLevA/
+ZboOWVe3icTy64BT3OQhmg==
-----END RSA TESTING KEY-----`))
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
diff --git a/src/net/http/pprof/pprof_test.go b/src/net/http/pprof/pprof_test.go
index 84757e4..1a4d653 100644
--- a/src/net/http/pprof/pprof_test.go
+++ b/src/net/http/pprof/pprof_test.go
@@ -8,6 +8,7 @@
"bytes"
"fmt"
"internal/profile"
+ "internal/testenv"
"io"
"net/http"
"net/http/httptest"
@@ -152,6 +153,10 @@
}
func TestDeltaProfile(t *testing.T) {
+ if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
+ testenv.SkipFlaky(t, 50218)
+ }
+
rate := runtime.SetMutexProfileFraction(1)
defer func() {
runtime.SetMutexProfileFraction(rate)
diff --git a/src/net/http/server.go b/src/net/http/server.go
index ddc799b..ffb742b 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -494,8 +494,8 @@
// prior to the headers being written. If the set of trailers is fixed
// or known before the header is written, the normal Go trailers mechanism
// is preferred:
-// https://golang.org/pkg/net/http/#ResponseWriter
-// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
+// https://pkg.go.dev/net/http#ResponseWriter
+// https://pkg.go.dev/net/http#example-ResponseWriter-Trailers
const TrailerPrefix = "Trailer:"
// finalTrailers is called after the Handler exits and returns a non-nil
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 5fe3e6e..e41b20a 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -606,6 +606,9 @@
} else if !pconn.shouldRetryRequest(req, err) {
// Issue 16465: return underlying net.Conn.Read error from peek,
// as we've historically done.
+ if e, ok := err.(nothingWrittenError); ok {
+ err = e.error
+ }
if e, ok := err.(transportReadFromServerError); ok {
err = e.err
}
@@ -2032,6 +2035,9 @@
}
if _, ok := err.(transportReadFromServerError); ok {
+ if pc.nwrite == startBytesWritten {
+ return nothingWrittenError{err}
+ }
// Don't decorate
return err
}
diff --git a/src/net/http/transport_internal_test.go b/src/net/http/transport_internal_test.go
index 1cce272..2ed637e 100644
--- a/src/net/http/transport_internal_test.go
+++ b/src/net/http/transport_internal_test.go
@@ -52,8 +52,8 @@
conn.Close() // simulate the server hanging up on the client
_, err = pc.roundTrip(treq)
- if !isTransportReadFromServerError(err) && err != errServerClosedIdle {
- t.Errorf("roundTrip = %#v, %v; want errServerClosedIdle or transportReadFromServerError", err, err)
+ if !isNothingWrittenError(err) && !isTransportReadFromServerError(err) && err != errServerClosedIdle {
+ t.Errorf("roundTrip = %#v, %v; want errServerClosedIdle, transportReadFromServerError, or nothingWrittenError", err, err)
}
<-pc.closech
@@ -63,6 +63,11 @@
}
}
+func isNothingWrittenError(err error) bool {
+ _, ok := err.(nothingWrittenError)
+ return ok
+}
+
func isTransportReadFromServerError(err error) bool {
_, ok := err.(transportReadFromServerError)
return ok
diff --git a/src/net/ip.go b/src/net/ip.go
index b016bef..54c5288 100644
--- a/src/net/ip.go
+++ b/src/net/ip.go
@@ -545,6 +545,9 @@
// character and a mask expressed as hexadecimal form with no
// punctuation like "198.51.100.0/c000ff00".
func (n *IPNet) String() string {
+ if n == nil {
+ return "<nil>"
+ }
nn, m := networkNumberAndMask(n)
if nn == nil || m == nil {
return "<nil>"
diff --git a/src/net/ip_test.go b/src/net/ip_test.go
index 777461a..8f1590c 100644
--- a/src/net/ip_test.go
+++ b/src/net/ip_test.go
@@ -407,6 +407,7 @@
{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
{&IPNet{IP: ParseIP("2001:db8::"), Mask: CIDRMask(55, 128)}, "2001:db8::/55"},
{&IPNet{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
+ {nil, "<nil>"},
}
func TestIPNetString(t *testing.T) {
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index d71a18c..3a31f56 100644
--- a/src/net/lookup_test.go
+++ b/src/net/lookup_test.go
@@ -352,6 +352,7 @@
func TestLookupCNAME(t *testing.T) {
mustHaveExternalNetwork(t)
+ testenv.SkipFlakyNet(t)
if !supportsIPv4() || !*testIPv4 {
t.Skip("IPv4 is required")
@@ -390,6 +391,7 @@
func TestLookupGoogleHost(t *testing.T) {
mustHaveExternalNetwork(t)
+ testenv.SkipFlakyNet(t)
if !supportsIPv4() || !*testIPv4 {
t.Skip("IPv4 is required")
@@ -442,6 +444,7 @@
func TestLookupGoogleIP(t *testing.T) {
mustHaveExternalNetwork(t)
+ testenv.SkipFlakyNet(t)
if !supportsIPv4() || !*testIPv4 {
t.Skip("IPv4 is required")
@@ -632,6 +635,7 @@
testenv.SkipFlaky(t, 27992)
}
mustHaveExternalNetwork(t)
+ testenv.SkipFlakyNet(t)
if !supportsIPv4() || !*testIPv4 {
t.Skip("IPv4 is required")
@@ -656,7 +660,6 @@
func testDots(t *testing.T, mode string) {
names, err := LookupAddr("8.8.8.8") // Google dns server
if err != nil {
- testenv.SkipFlakyNet(t)
t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
} else {
for _, name := range names {
@@ -669,7 +672,6 @@
cname, err := LookupCNAME("www.mit.edu")
if err != nil {
- testenv.SkipFlakyNet(t)
t.Errorf("LookupCNAME(www.mit.edu, mode=%v): %v", mode, err)
} else if !strings.HasSuffix(cname, ".") {
t.Errorf("LookupCNAME(www.mit.edu) = %v, want cname ending in . with trailing dot (mode=%v)", cname, mode)
@@ -677,7 +679,6 @@
mxs, err := LookupMX("google.com")
if err != nil {
- testenv.SkipFlakyNet(t)
t.Errorf("LookupMX(google.com): %v (mode=%v)", err, mode)
} else {
for _, mx := range mxs {
@@ -690,7 +691,6 @@
nss, err := LookupNS("google.com")
if err != nil {
- testenv.SkipFlakyNet(t)
t.Errorf("LookupNS(google.com): %v (mode=%v)", err, mode)
} else {
for _, ns := range nss {
@@ -703,7 +703,6 @@
cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com")
if err != nil {
- testenv.SkipFlakyNet(t)
t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode)
} else {
if !hasSuffixFold(cname, ".google.com.") {
@@ -884,21 +883,66 @@
func TestLookupContextCancel(t *testing.T) {
mustHaveExternalNetwork(t)
- defer dnsWaitGroup.Wait()
+ testenv.SkipFlakyNet(t)
- ctx, ctxCancel := context.WithCancel(context.Background())
- ctxCancel()
- _, err := DefaultResolver.LookupIPAddr(ctx, "google.com")
- if err.(*DNSError).Err != errCanceled.Error() {
- testenv.SkipFlakyNet(t)
- t.Fatal(err)
+ origTestHookLookupIP := testHookLookupIP
+ defer func() {
+ dnsWaitGroup.Wait()
+ testHookLookupIP = origTestHookLookupIP
+ }()
+
+ lookupCtx, cancelLookup := context.WithCancel(context.Background())
+ unblockLookup := make(chan struct{})
+
+ // Set testHookLookupIP to start a new, concurrent call to LookupIPAddr
+ // and cancel the original one, then block until the canceled call has returned
+ // (ensuring that it has performed any synchronous cleanup).
+ testHookLookupIP = func(
+ ctx context.Context,
+ fn func(context.Context, string, string) ([]IPAddr, error),
+ network string,
+ host string,
+ ) ([]IPAddr, error) {
+ select {
+ case <-unblockLookup:
+ default:
+ // Start a concurrent LookupIPAddr for the same host while the caller is
+ // still blocked, and sleep a little to give it time to be deduplicated
+ // before we cancel (and unblock) the caller.
+ // (If the timing doesn't quite work out, we'll end up testing sequential
+ // calls instead of concurrent ones, but the test should still pass.)
+ t.Logf("starting concurrent LookupIPAddr")
+ dnsWaitGroup.Add(1)
+ go func() {
+ defer dnsWaitGroup.Done()
+ _, err := DefaultResolver.LookupIPAddr(context.Background(), host)
+ if err != nil {
+ t.Error(err)
+ }
+ }()
+ time.Sleep(1 * time.Millisecond)
+ }
+
+ cancelLookup()
+ <-unblockLookup
+ // If the concurrent lookup above is deduplicated to this one
+ // (as we expect to happen most of the time), it is important
+ // that the original call does not cancel the shared Context.
+ // (See https://go.dev/issue/22724.) Explicitly check for
+ // cancellation now, just in case fn itself doesn't notice it.
+ if err := ctx.Err(); err != nil {
+ t.Logf("testHookLookupIP canceled")
+ return nil, err
+ }
+ t.Logf("testHookLookupIP performing lookup")
+ return fn(ctx, network, host)
}
- ctx = context.Background()
- _, err = DefaultResolver.LookupIPAddr(ctx, "google.com")
- if err != nil {
- testenv.SkipFlakyNet(t)
- t.Fatal(err)
+
+ _, err := DefaultResolver.LookupIPAddr(lookupCtx, "google.com")
+ if dnsErr, ok := err.(*DNSError); !ok || dnsErr.Err != errCanceled.Error() {
+ t.Errorf("unexpected error from canceled, blocked LookupIPAddr: %v", err)
}
+ close(unblockLookup)
}
// Issue 24330: treat the nil *Resolver like a zero value. Verify nothing
@@ -925,6 +969,7 @@
// canceled lookups (see golang.org/issue/24178 for details).
func TestLookupHostCancel(t *testing.T) {
mustHaveExternalNetwork(t)
+ testenv.SkipFlakyNet(t)
t.Parallel() // Executes 600ms worth of sequential sleeps.
const (
diff --git a/src/net/net.go b/src/net/net.go
index 77e54a9..d91e743 100644
--- a/src/net/net.go
+++ b/src/net/net.go
@@ -703,6 +703,12 @@
_ io.Reader = (*Buffers)(nil)
)
+// WriteTo writes contents of the buffers to w.
+//
+// WriteTo implements io.WriterTo for Buffers.
+//
+// WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v),
+// but does not modify v[i][j] for any i, j.
func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
if wv, ok := w.(buffersWriter); ok {
return wv.writeBuffers(v)
@@ -719,6 +725,12 @@
return n, nil
}
+// Read from the buffers.
+//
+// Read implements io.Reader for Buffers.
+//
+// Read modifies the slice v as well as v[i] for 0 <= i < len(v),
+// but does not modify v[i][j] for any i, j.
func (v *Buffers) Read(p []byte) (n int, err error) {
for len(p) > 0 && len(*v) > 0 {
n0 := copy(p, (*v)[0])
diff --git a/src/net/net_test.go b/src/net/net_test.go
index 7b16991..76a9c8b 100644
--- a/src/net/net_test.go
+++ b/src/net/net_test.go
@@ -9,7 +9,6 @@
import (
"errors"
"fmt"
- "internal/testenv"
"io"
"net/internal/socktest"
"os"
@@ -515,35 +514,50 @@
// Issue 24808: verify that ECONNRESET is not temporary for read.
func TestNotTemporaryRead(t *testing.T) {
- if runtime.GOOS == "freebsd" {
- testenv.SkipFlaky(t, 25289)
- }
- if runtime.GOOS == "aix" {
- testenv.SkipFlaky(t, 29685)
- }
t.Parallel()
- server := func(cs *TCPConn) error {
- cs.SetLinger(0)
- // Give the client time to get stuck in a Read.
- time.Sleep(50 * time.Millisecond)
- cs.Close()
- return nil
- }
- client := func(ss *TCPConn) error {
- _, err := ss.Read([]byte{0})
- if err == nil {
- return errors.New("Read succeeded unexpectedly")
- } else if err == io.EOF {
- // This happens on Plan 9.
- return nil
- } else if ne, ok := err.(Error); !ok {
- return fmt.Errorf("unexpected error %v", err)
- } else if ne.Temporary() {
- return fmt.Errorf("unexpected temporary error %v", err)
+
+ ln := newLocalListener(t, "tcp")
+ serverDone := make(chan struct{})
+ dialed := make(chan struct{})
+ go func() {
+ defer close(serverDone)
+
+ cs, err := ln.Accept()
+ if err != nil {
+ return
}
- return nil
+ <-dialed
+ cs.(*TCPConn).SetLinger(0)
+ cs.Close()
+
+ ln.Close()
+ }()
+ defer func() { <-serverDone }()
+
+ ss, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
}
- withTCPConnPair(t, client, server)
+ defer ss.Close()
+ close(dialed)
+ _, err = ss.Read([]byte{0})
+ if err == nil {
+ t.Fatal("Read succeeded unexpectedly")
+ } else if err == io.EOF {
+ // This happens on Plan 9, but for some reason (prior to CL 385314) it was
+ // accepted everywhere else too.
+ if runtime.GOOS == "plan9" {
+ return
+ }
+ // TODO: during an open development cycle, try making this a failure
+ // and see whether it causes the test to become flaky anywhere else.
+ return
+ }
+ if ne, ok := err.(Error); !ok {
+ t.Errorf("Read error does not implement net.Error: %v", err)
+ } else if ne.Temporary() {
+ t.Errorf("Read error is unexpectedly temporary: %v", err)
+ }
}
// The various errors should implement the Error interface.
diff --git a/src/net/netip/fuzz_test.go b/src/net/netip/fuzz_test.go
new file mode 100644
index 0000000..c9fc6c9
--- /dev/null
+++ b/src/net/netip/fuzz_test.go
@@ -0,0 +1,351 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package netip_test
+
+import (
+ "bytes"
+ "encoding"
+ "fmt"
+ "net"
+ . "net/netip"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+var corpus = []string{
+ // Basic zero IPv4 address.
+ "0.0.0.0",
+ // Basic non-zero IPv4 address.
+ "192.168.140.255",
+ // IPv4 address in windows-style "print all the digits" form.
+ "010.000.015.001",
+ // IPv4 address with a silly amount of leading zeros.
+ "000001.00000002.00000003.000000004",
+ // 4-in-6 with octet with leading zero
+ "::ffff:1.2.03.4",
+ // Basic zero IPv6 address.
+ "::",
+ // Localhost IPv6.
+ "::1",
+ // Fully expanded IPv6 address.
+ "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b",
+ // IPv6 with elided fields in the middle.
+ "fd7a:115c::626b:430b",
+ // IPv6 with elided fields at the end.
+ "fd7a:115c:a1e0:ab12:4843:cd96::",
+ // IPv6 with single elided field at the end.
+ "fd7a:115c:a1e0:ab12:4843:cd96:626b::",
+ "fd7a:115c:a1e0:ab12:4843:cd96:626b:0",
+ // IPv6 with single elided field in the middle.
+ "fd7a:115c:a1e0::4843:cd96:626b:430b",
+ "fd7a:115c:a1e0:0:4843:cd96:626b:430b",
+ // IPv6 with the trailing 32 bits written as IPv4 dotted decimal. (4in6)
+ "::ffff:192.168.140.255",
+ "::ffff:192.168.140.255",
+ // IPv6 with a zone specifier.
+ "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b%eth0",
+ // IPv6 with dotted decimal and zone specifier.
+ "1:2::ffff:192.168.140.255%eth1",
+ "1:2::ffff:c0a8:8cff%eth1",
+ // IPv6 with capital letters.
+ "FD9E:1A04:F01D::1",
+ "fd9e:1a04:f01d::1",
+ // Empty string.
+ "",
+ // Garbage non-IP.
+ "bad",
+ // Single number. Some parsers accept this as an IPv4 address in
+ // big-endian uint32 form, but we don't.
+ "1234",
+ // IPv4 with a zone specifier.
+ "1.2.3.4%eth0",
+ // IPv4 field must have at least one digit.
+ ".1.2.3",
+ "1.2.3.",
+ "1..2.3",
+ // IPv4 address too long.
+ "1.2.3.4.5",
+ // IPv4 in dotted octal form.
+ "0300.0250.0214.0377",
+ // IPv4 in dotted hex form.
+ "0xc0.0xa8.0x8c.0xff",
+ // IPv4 in class B form.
+ "192.168.12345",
+ // IPv4 in class B form, with a small enough number to be
+ // parseable as a regular dotted decimal field.
+ "127.0.1",
+ // IPv4 in class A form.
+ "192.1234567",
+ // IPv4 in class A form, with a small enough number to be
+ // parseable as a regular dotted decimal field.
+ "127.1",
+ // IPv4 field has value >255.
+ "192.168.300.1",
+ // IPv4 with too many fields.
+ "192.168.0.1.5.6",
+ // IPv6 with not enough fields.
+ "1:2:3:4:5:6:7",
+ // IPv6 with too many fields.
+ "1:2:3:4:5:6:7:8:9",
+ // IPv6 with 8 fields and a :: expander.
+ "1:2:3:4::5:6:7:8",
+ // IPv6 with a field bigger than 2b.
+ "fe801::1",
+ // IPv6 with non-hex values in field.
+ "fe80:tail:scal:e::",
+ // IPv6 with a zone delimiter but no zone.
+ "fe80::1%",
+ // IPv6 with a zone specifier of zero.
+ "::ffff:0:0%0",
+ // IPv6 (without ellipsis) with too many fields for trailing embedded IPv4.
+ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:192.168.140.255",
+ // IPv6 (with ellipsis) with too many fields for trailing embedded IPv4.
+ "ffff::ffff:ffff:ffff:ffff:ffff:ffff:192.168.140.255",
+ // IPv6 with invalid embedded IPv4.
+ "::ffff:192.168.140.bad",
+ // IPv6 with multiple ellipsis ::.
+ "fe80::1::1",
+ // IPv6 with invalid non hex/colon character.
+ "fe80:1?:1",
+ // IPv6 with truncated bytes after single colon.
+ "fe80:",
+ // AddrPort strings.
+ "1.2.3.4:51820",
+ "[fd7a:115c:a1e0:ab12:4843:cd96:626b:430b]:80",
+ "[::ffff:c000:0280]:65535",
+ "[::ffff:c000:0280%eth0]:1",
+ // Prefix strings.
+ "1.2.3.4/24",
+ "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118",
+ "::ffff:c000:0280/96",
+ "::ffff:c000:0280%eth0/37",
+}
+
+func FuzzParse(f *testing.F) {
+ for _, seed := range corpus {
+ f.Add(seed)
+ }
+
+ f.Fuzz(func(t *testing.T, s string) {
+ ip, _ := ParseAddr(s)
+ checkStringParseRoundTrip(t, ip, ParseAddr)
+ checkEncoding(t, ip)
+
+ // Check that we match the net's IP parser, modulo zones.
+ if !strings.Contains(s, "%") {
+ stdip := net.ParseIP(s)
+ if !ip.IsValid() != (stdip == nil) {
+ t.Errorf("ParseAddr zero != net.ParseIP nil: ip=%q stdip=%q", ip, stdip)
+ }
+
+ if ip.IsValid() && !ip.Is4In6() {
+ buf, err := ip.MarshalText()
+ if err != nil {
+ t.Fatal(err)
+ }
+ buf2, err := stdip.MarshalText()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(buf, buf2) {
+ t.Errorf("Addr.MarshalText() != net.IP.MarshalText(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.String() != stdip.String() {
+ t.Errorf("Addr.String() != net.IP.String(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.IsGlobalUnicast() != stdip.IsGlobalUnicast() {
+ t.Errorf("Addr.IsGlobalUnicast() != net.IP.IsGlobalUnicast(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.IsInterfaceLocalMulticast() != stdip.IsInterfaceLocalMulticast() {
+ t.Errorf("Addr.IsInterfaceLocalMulticast() != net.IP.IsInterfaceLocalMulticast(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.IsLinkLocalMulticast() != stdip.IsLinkLocalMulticast() {
+ t.Errorf("Addr.IsLinkLocalMulticast() != net.IP.IsLinkLocalMulticast(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.IsLinkLocalUnicast() != stdip.IsLinkLocalUnicast() {
+ t.Errorf("Addr.IsLinkLocalUnicast() != net.IP.IsLinkLocalUnicast(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.IsLoopback() != stdip.IsLoopback() {
+ t.Errorf("Addr.IsLoopback() != net.IP.IsLoopback(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.IsMulticast() != stdip.IsMulticast() {
+ t.Errorf("Addr.IsMulticast() != net.IP.IsMulticast(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.IsPrivate() != stdip.IsPrivate() {
+ t.Errorf("Addr.IsPrivate() != net.IP.IsPrivate(): ip=%q stdip=%q", ip, stdip)
+ }
+ if ip.IsUnspecified() != stdip.IsUnspecified() {
+ t.Errorf("Addr.IsUnspecified() != net.IP.IsUnspecified(): ip=%q stdip=%q", ip, stdip)
+ }
+ }
+ }
+
+ // Check that .Next().Prev() and .Prev().Next() preserve the IP.
+ if ip.IsValid() && ip.Next().IsValid() && ip.Next().Prev() != ip {
+ t.Errorf(".Next.Prev did not round trip: ip=%q .next=%q .next.prev=%q", ip, ip.Next(), ip.Next().Prev())
+ }
+ if ip.IsValid() && ip.Prev().IsValid() && ip.Prev().Next() != ip {
+ t.Errorf(".Prev.Next did not round trip: ip=%q .prev=%q .prev.next=%q", ip, ip.Prev(), ip.Prev().Next())
+ }
+
+ port, err := ParseAddrPort(s)
+ if err == nil {
+ checkStringParseRoundTrip(t, port, ParseAddrPort)
+ checkEncoding(t, port)
+ }
+ port = AddrPortFrom(ip, 80)
+ checkStringParseRoundTrip(t, port, ParseAddrPort)
+ checkEncoding(t, port)
+
+ ipp, err := ParsePrefix(s)
+ if err == nil {
+ checkStringParseRoundTrip(t, ipp, ParsePrefix)
+ checkEncoding(t, ipp)
+ }
+ ipp = PrefixFrom(ip, 8)
+ checkStringParseRoundTrip(t, ipp, ParsePrefix)
+ checkEncoding(t, ipp)
+ })
+}
+
+// checkTextMarshaler checks that x's MarshalText and UnmarshalText functions round trip correctly.
+func checkTextMarshaler(t *testing.T, x encoding.TextMarshaler) {
+ buf, err := x.MarshalText()
+ if err != nil {
+ t.Fatal(err)
+ }
+ y := reflect.New(reflect.TypeOf(x)).Interface().(encoding.TextUnmarshaler)
+ err = y.UnmarshalText(buf)
+ if err != nil {
+ t.Logf("(%v).MarshalText() = %q", x, buf)
+ t.Fatalf("(%T).UnmarshalText(%q) = %v", y, buf, err)
+ }
+ e := reflect.ValueOf(y).Elem().Interface()
+ if !reflect.DeepEqual(x, e) {
+ t.Logf("(%v).MarshalText() = %q", x, buf)
+ t.Logf("(%T).UnmarshalText(%q) = %v", y, buf, y)
+ t.Fatalf("MarshalText/UnmarshalText failed to round trip: %#v != %#v", x, e)
+ }
+ buf2, err := y.(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ t.Logf("(%v).MarshalText() = %q", x, buf)
+ t.Logf("(%T).UnmarshalText(%q) = %v", y, buf, y)
+ t.Fatalf("failed to MarshalText a second time: %v", err)
+ }
+ if !bytes.Equal(buf, buf2) {
+ t.Logf("(%v).MarshalText() = %q", x, buf)
+ t.Logf("(%T).UnmarshalText(%q) = %v", y, buf, y)
+ t.Logf("(%v).MarshalText() = %q", y, buf2)
+ t.Fatalf("second MarshalText differs from first: %q != %q", buf, buf2)
+ }
+}
+
+// checkBinaryMarshaler checks that x's MarshalText and UnmarshalText functions round trip correctly.
+func checkBinaryMarshaler(t *testing.T, x encoding.BinaryMarshaler) {
+ buf, err := x.MarshalBinary()
+ if err != nil {
+ t.Fatal(err)
+ }
+ y := reflect.New(reflect.TypeOf(x)).Interface().(encoding.BinaryUnmarshaler)
+ err = y.UnmarshalBinary(buf)
+ if err != nil {
+ t.Logf("(%v).MarshalBinary() = %q", x, buf)
+ t.Fatalf("(%T).UnmarshalBinary(%q) = %v", y, buf, err)
+ }
+ e := reflect.ValueOf(y).Elem().Interface()
+ if !reflect.DeepEqual(x, e) {
+ t.Logf("(%v).MarshalBinary() = %q", x, buf)
+ t.Logf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
+ t.Fatalf("MarshalBinary/UnmarshalBinary failed to round trip: %#v != %#v", x, e)
+ }
+ buf2, err := y.(encoding.BinaryMarshaler).MarshalBinary()
+ if err != nil {
+ t.Logf("(%v).MarshalBinary() = %q", x, buf)
+ t.Logf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
+ t.Fatalf("failed to MarshalBinary a second time: %v", err)
+ }
+ if !bytes.Equal(buf, buf2) {
+ t.Logf("(%v).MarshalBinary() = %q", x, buf)
+ t.Logf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
+ t.Logf("(%v).MarshalBinary() = %q", y, buf2)
+ t.Fatalf("second MarshalBinary differs from first: %q != %q", buf, buf2)
+ }
+}
+
+func checkTextMarshalMatchesString(t *testing.T, x netipType) {
+ buf, err := x.MarshalText()
+ if err != nil {
+ t.Fatal(err)
+ }
+ str := x.String()
+ if string(buf) != str {
+ t.Fatalf("%v: MarshalText = %q, String = %q", x, buf, str)
+ }
+}
+
+type appendMarshaler interface {
+ encoding.TextMarshaler
+ AppendTo([]byte) []byte
+}
+
+// checkTextMarshalMatchesAppendTo checks that x's MarshalText matches x's AppendTo.
+func checkTextMarshalMatchesAppendTo(t *testing.T, x appendMarshaler) {
+ buf, err := x.MarshalText()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ buf2 := make([]byte, 0, len(buf))
+ buf2 = x.AppendTo(buf2)
+ if !bytes.Equal(buf, buf2) {
+ t.Fatalf("%v: MarshalText = %q, AppendTo = %q", x, buf, buf2)
+ }
+}
+
+type netipType interface {
+ encoding.BinaryMarshaler
+ encoding.TextMarshaler
+ fmt.Stringer
+ IsValid() bool
+}
+
+type netipTypeCmp interface {
+ comparable
+ netipType
+}
+
+// checkStringParseRoundTrip checks that x's String method and the provided parse function can round trip correctly.
+func checkStringParseRoundTrip[P netipTypeCmp](t *testing.T, x P, parse func(string) (P, error)) {
+ if !x.IsValid() {
+ // Ignore invalid values.
+ return
+ }
+
+ s := x.String()
+ y, err := parse(s)
+ if err != nil {
+ t.Fatalf("s=%q err=%v", s, err)
+ }
+ if x != y {
+ t.Fatalf("%T round trip identity failure: s=%q x=%#v y=%#v", x, s, x, y)
+ }
+ s2 := y.String()
+ if s != s2 {
+ t.Fatalf("%T String round trip identity failure: s=%#v s2=%#v", x, s, s2)
+ }
+}
+
+func checkEncoding(t *testing.T, x netipType) {
+ if x.IsValid() {
+ checkTextMarshaler(t, x)
+ checkBinaryMarshaler(t, x)
+ checkTextMarshalMatchesString(t, x)
+ }
+
+ if am, ok := x.(appendMarshaler); ok {
+ checkTextMarshalMatchesAppendTo(t, am)
+ }
+}
diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go
index 591d38a..f27984a 100644
--- a/src/net/netip/netip.go
+++ b/src/net/netip/netip.go
@@ -1288,7 +1288,7 @@
func (p Prefix) IsSingleIP() bool { return p.bits != 0 && int(p.bits) == p.ip.BitLen() }
// ParsePrefix parses s as an IP address prefix.
-// The string can be in the form "192.168.1.0/24" or "2001::db8::/32",
+// The string can be in the form "192.168.1.0/24" or "2001:db8::/32",
// the CIDR notation defined in RFC 4632 and RFC 4291.
//
// Note that masked address bits are not zeroed. Use Masked for that.
diff --git a/src/net/smtp/auth.go b/src/net/smtp/auth.go
index fd1a472..7a32ef6 100644
--- a/src/net/smtp/auth.go
+++ b/src/net/smtp/auth.go
@@ -16,8 +16,7 @@
// Start begins an authentication with a server.
// It returns the name of the authentication protocol
// and optionally data to include in the initial AUTH message
- // sent to the server. It can return proto == "" to indicate
- // that the authentication should be skipped.
+ // sent to the server.
// If it returns a non-nil error, the SMTP client aborts
// the authentication attempt and closes the connection.
Start(server *ServerInfo) (proto string, toServer []byte, err error)
diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go
index 032770d..d1cfbf8 100644
--- a/src/net/timeout_test.go
+++ b/src/net/timeout_test.go
@@ -644,10 +644,20 @@
// timeoutUpperBound returns the maximum time that we expect a timeout of
// duration d to take to return the caller.
func timeoutUpperBound(d time.Duration) time.Duration {
- // In https://storage.googleapis.com/go-build-log/1e637cd3/openbsd-amd64-68_3585d3e7.log,
- // we observed that an openbsd-amd64-68 builder took 636ms for a 512ms timeout
- // (24.2% overhead).
- return d * 4 / 3
+ switch runtime.GOOS {
+ case "openbsd", "netbsd":
+ // NetBSD and OpenBSD seem to be unable to reliably hit deadlines even when
+ // the absolute durations are long.
+ // In https://build.golang.org/log/c34f8685d020b98377dd4988cd38f0c5bd72267e,
+ // we observed that an openbsd-amd64-68 builder took 4.090948779s for a
+ // 2.983020682s timeout (37.1% overhead).
+ // (See https://go.dev/issue/50189 for further detail.)
+ // Give them lots of slop to compensate.
+ return d * 3 / 2
+ }
+ // Other platforms seem to hit their deadlines more reliably,
+ // at least when they are long enough to cover scheduling jitter.
+ return d * 11 / 10
}
// nextTimeout returns the next timeout to try after an operation took the given
@@ -947,35 +957,23 @@
name := fmt.Sprintf("%v %d/%d", timeout, run, numRuns)
t.Log(name)
- tooSlow := time.NewTimer(5 * time.Second)
- defer tooSlow.Stop()
-
c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
if err != nil {
t.Fatal(err)
}
- ch := make(chan result, 1)
- go func() {
- t0 := time.Now()
- if err := c.SetDeadline(t0.Add(timeout)); err != nil {
- t.Error(err)
- }
- n, err := io.Copy(io.Discard, c)
- dt := time.Since(t0)
- c.Close()
- ch <- result{n, err, dt}
- }()
+ t0 := time.Now()
+ if err := c.SetDeadline(t0.Add(timeout)); err != nil {
+ t.Error(err)
+ }
+ n, err := io.Copy(io.Discard, c)
+ dt := time.Since(t0)
+ c.Close()
- select {
- case res := <-ch:
- if nerr, ok := res.err.(Error); ok && nerr.Timeout() {
- t.Logf("%v: good timeout after %v; %d bytes", name, res.d, res.n)
- } else {
- t.Fatalf("%v: Copy = %d, %v; want timeout", name, res.n, res.err)
- }
- case <-tooSlow.C:
- t.Fatalf("%v: client stuck in Dial+Copy", name)
+ if nerr, ok := err.(Error); ok && nerr.Timeout() {
+ t.Logf("%v: good timeout after %v; %d bytes", name, dt, n)
+ } else {
+ t.Fatalf("%v: Copy = %d, %v; want timeout", name, n, err)
}
}
}
diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go
index 6f82554..f8acf6a 100644
--- a/src/net/udpsock_test.go
+++ b/src/net/udpsock_test.go
@@ -415,19 +415,14 @@
if n != len(b1) {
t.Errorf("got %d; want %d", n, len(b1))
}
- c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
b2 := make([]byte, len(b1)-1)
if genericRead {
n, err = c1.(Conn).Read(b2)
} else {
n, _, err = c1.ReadFrom(b2)
}
- switch err {
- case nil: // ReadFrom succeeds
- default: // Read may timeout, it depends on the platform
- if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE
- t.Fatal(err)
- }
+ if err != nil && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE
+ t.Fatal(err)
}
if n != len(b1)-1 {
t.Fatalf("got %d; want %d", n, len(b1)-1)
diff --git a/src/os/example_test.go b/src/os/example_test.go
index e8554b0..53e3c52 100644
--- a/src/os/example_test.go
+++ b/src/os/example_test.go
@@ -241,3 +241,25 @@
log.Fatal(err)
}
}
+
+func ExampleMkdir() {
+ err := os.Mkdir("testdir", 0750)
+ if err != nil && !os.IsExist(err) {
+ log.Fatal(err)
+ }
+ err = os.WriteFile("testdir/testfile.txt", []byte("Hello, Gophers!"), 0660)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func ExampleMkdirAll() {
+ err := os.MkdirAll("test/subdir", 0750)
+ if err != nil && !os.IsExist(err) {
+ log.Fatal(err)
+ }
+ err = os.WriteFile("test/subdir/testfile.txt", []byte("Hello, Gophers!"), 0660)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 92992a6..73aa35f 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -954,6 +954,10 @@
}
func TestContextCancel(t *testing.T) {
+ if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" {
+ testenv.SkipFlaky(t, 42061)
+ }
+
// To reduce noise in the final goroutine dump,
// let other parallel tests complete if possible.
t.Parallel()
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 717330e..63427de 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -28,6 +28,16 @@
"time"
)
+func TestMain(m *testing.M) {
+ if Getenv("GO_OS_TEST_DRAIN_STDIN") == "1" {
+ os.Stdout.Close()
+ io.Copy(io.Discard, os.Stdin)
+ Exit(0)
+ }
+
+ Exit(m.Run())
+}
+
var dot = []string{
"dir_unix.go",
"env.go",
@@ -54,34 +64,31 @@
"libpowermanager.so",
},
}
- case "darwin", "ios":
- switch runtime.GOARCH {
- case "arm64":
- wd, err := syscall.Getwd()
- if err != nil {
- wd = err.Error()
- }
- sd := &sysDir{
- filepath.Join(wd, "..", ".."),
- []string{
- "ResourceRules.plist",
- "Info.plist",
- },
- }
- found := true
- for _, f := range sd.files {
- path := filepath.Join(sd.name, f)
- if _, err := Stat(path); err != nil {
- found = false
- break
- }
- }
- if found {
- return sd
- }
- // In a self-hosted iOS build the above files might
- // not exist. Look for system files instead below.
+ case "ios":
+ wd, err := syscall.Getwd()
+ if err != nil {
+ wd = err.Error()
}
+ sd := &sysDir{
+ filepath.Join(wd, "..", ".."),
+ []string{
+ "ResourceRules.plist",
+ "Info.plist",
+ },
+ }
+ found := true
+ for _, f := range sd.files {
+ path := filepath.Join(sd.name, f)
+ if _, err := Stat(path); err != nil {
+ found = false
+ break
+ }
+ }
+ if found {
+ return sd
+ }
+ // In a self-hosted iOS build the above files might
+ // not exist. Look for system files instead below.
case "windows":
return &sysDir{
Getenv("SystemRoot") + "\\system32\\drivers\\etc",
@@ -140,13 +147,8 @@
// localTmp returns a local temporary directory not on NFS.
func localTmp() string {
switch runtime.GOOS {
- case "android", "windows":
+ case "android", "ios", "windows":
return TempDir()
- case "darwin", "ios":
- switch runtime.GOARCH {
- case "arm64":
- return TempDir()
- }
}
return "/tmp"
}
@@ -570,15 +572,12 @@
switch runtime.GOOS {
case "android":
dir = "/system/bin"
- case "darwin", "ios":
- switch runtime.GOARCH {
- case "arm64":
- wd, err := Getwd()
- if err != nil {
- t.Fatal(err)
- }
- dir = wd
+ case "ios":
+ wd, err := Getwd()
+ if err != nil {
+ t.Fatal(err)
}
+ dir = wd
case "plan9":
dir = "/bin"
case "windows":
@@ -1399,22 +1398,19 @@
dirs = []string{"/system/bin"}
case "plan9":
dirs = []string{"/", "/usr"}
- case "darwin", "ios":
- switch runtime.GOARCH {
- case "arm64":
- dirs = nil
- for _, d := range []string{"d1", "d2"} {
- dir, err := os.MkdirTemp("", d)
- if err != nil {
- t.Fatalf("TempDir: %v", err)
- }
- // Expand symlinks so path equality tests work.
- dir, err = filepath.EvalSymlinks(dir)
- if err != nil {
- t.Fatalf("EvalSymlinks: %v", err)
- }
- dirs = append(dirs, dir)
+ case "ios":
+ dirs = nil
+ for _, d := range []string{"d1", "d2"} {
+ dir, err := os.MkdirTemp("", d)
+ if err != nil {
+ t.Fatalf("TempDir: %v", err)
}
+ // Expand symlinks so path equality tests work.
+ dir, err = filepath.EvalSymlinks(dir)
+ if err != nil {
+ t.Fatalf("EvalSymlinks: %v", err)
+ }
+ dirs = append(dirs, dir)
}
}
oldwd := Getenv("PWD")
@@ -2273,9 +2269,18 @@
testenv.MustHaveExec(t)
t.Parallel()
- // Re-exec the test binary itself to emulate "sleep 1".
- cmd := osexec.Command(Args[0], "-test.run", "TestSleep")
- err := cmd.Start()
+ // Re-exec the test binary to start a process that hangs until stdin is closed.
+ cmd := osexec.Command(Args[0])
+ cmd.Env = append(os.Environ(), "GO_OS_TEST_DRAIN_STDIN=1")
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = cmd.Start()
if err != nil {
t.Fatalf("Failed to start test process: %v", err)
}
@@ -2284,19 +2289,14 @@
if err := cmd.Wait(); err == nil {
t.Errorf("Test process succeeded, but expected to fail")
}
+ stdin.Close() // Keep stdin alive until the process has finished dying.
}()
- time.Sleep(100 * time.Millisecond)
- processKiller(cmd.Process)
-}
+ // Wait for the process to be started.
+ // (It will close its stdout when it reaches TestMain.)
+ io.Copy(io.Discard, stdout)
-// TestSleep emulates "sleep 1". It is a helper for testKillProcess, so we
-// don't have to rely on an external "sleep" command being available.
-func TestSleep(t *testing.T) {
- if testing.Short() {
- t.Skip("Skipping in short mode")
- }
- time.Sleep(time.Second)
+ processKiller(cmd.Process)
}
func TestKillStartProcess(t *testing.T) {
@@ -2434,8 +2434,6 @@
// Test that reading from a pipe doesn't use up a thread.
func TestPipeThreads(t *testing.T) {
switch runtime.GOOS {
- case "freebsd":
- t.Skip("skipping on FreeBSD; issue 19093")
case "illumos", "solaris":
t.Skip("skipping on Solaris and illumos; issue 19111")
case "windows":
diff --git a/src/os/path_test.go b/src/os/path_test.go
index 4535abb..59f7283 100644
--- a/src/os/path_test.go
+++ b/src/os/path_test.go
@@ -96,13 +96,8 @@
func TestMkdirAllAtSlash(t *testing.T) {
switch runtime.GOOS {
- case "android", "plan9", "windows":
+ case "android", "ios", "plan9", "windows":
t.Skipf("skipping on %s", runtime.GOOS)
- case "darwin", "ios":
- switch runtime.GOARCH {
- case "arm64":
- t.Skipf("skipping on darwin/arm64, mkdir returns EPERM")
- }
}
RemoveAll("/_go_os_test")
const dir = "/_go_os_test/dir"
diff --git a/src/os/pipe_test.go b/src/os/pipe_test.go
index ab6d1ce..20716bc 100644
--- a/src/os/pipe_test.go
+++ b/src/os/pipe_test.go
@@ -150,11 +150,6 @@
}
func testClosedPipeRace(t *testing.T, read bool) {
- switch runtime.GOOS {
- case "freebsd":
- t.Skip("FreeBSD does not use the poller; issue 19093")
- }
-
limit := 1
if !read {
// Get the amount we have to write to overload a pipe
diff --git a/src/os/tempfile.go b/src/os/tempfile.go
index 5b681fc..3be3d13 100644
--- a/src/os/tempfile.go
+++ b/src/os/tempfile.go
@@ -46,7 +46,7 @@
if try++; try < 10000 {
continue
}
- return nil, &PathError{Op: "createtemp", Path: dir + string(PathSeparator) + prefix + "*" + suffix, Err: ErrExist}
+ return nil, &PathError{Op: "createtemp", Path: prefix + "*" + suffix, Err: ErrExist}
}
return f, err
}
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 9c8434c..866f38e 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -7768,3 +7768,17 @@
t.Errorf("methodValueCall code pointer mismatched, want: %v, got: %v", want, got)
}
}
+
+type A struct{}
+type B[T any] struct{}
+
+func TestIssue50208(t *testing.T) {
+ want1 := "B[reflect_test.A]"
+ if got := TypeOf(new(B[A])).Elem().Name(); got != want1 {
+ t.Errorf("name of type parameter mismatched, want:%s, got:%s", want1, got)
+ }
+ want2 := "B[reflect_test.B[reflect_test.A]]"
+ if got := TypeOf(new(B[B[A]])).Elem().Name(); got != want2 {
+ t.Errorf("name of type parameter mismatched, want:%s, got:%s", want2, got)
+ }
+}
diff --git a/src/reflect/asm_arm64.s b/src/reflect/asm_arm64.s
index 5b9b357..812b8a0 100644
--- a/src/reflect/asm_arm64.s
+++ b/src/reflect/asm_arm64.s
@@ -33,9 +33,14 @@
ADD $LOCAL_REGARGS, RSP, R20
CALL runtime·spillArgs(SB)
MOVD R26, 32(RSP) // outside of moveMakeFuncArgPtrs's arg area
+#ifdef GOEXPERIMENT_regabiargs
+ MOVD R26, R0
+ MOVD R20, R1
+#else
MOVD R26, 8(RSP)
MOVD R20, 16(RSP)
- CALL ·moveMakeFuncArgPtrs(SB)
+#endif
+ CALL ·moveMakeFuncArgPtrs<ABIInternal>(SB)
MOVD 32(RSP), R26
MOVD R26, 8(RSP)
MOVD $argframe+0(FP), R3
@@ -61,9 +66,14 @@
ADD $LOCAL_REGARGS, RSP, R20
CALL runtime·spillArgs(SB)
MOVD R26, 32(RSP) // outside of moveMakeFuncArgPtrs's arg area
+#ifdef GOEXPERIMENT_regabiargs
+ MOVD R26, R0
+ MOVD R20, R1
+#else
MOVD R26, 8(RSP)
MOVD R20, 16(RSP)
- CALL ·moveMakeFuncArgPtrs(SB)
+#endif
+ CALL ·moveMakeFuncArgPtrs<ABIInternal>(SB)
MOVD 32(RSP), R26
MOVD R26, 8(RSP)
MOVD $argframe+0(FP), R3
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 6217291..8ba63bc 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -229,7 +229,7 @@
// See https://golang.org/issue/4876 for more details.
/*
- * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
+ * These data structures are known to the compiler (../cmd/compile/internal/reflectdata/reflect.go).
* A few are known to ../runtime/type.go to convey to debuggers.
* They are also known to ../runtime/type.go.
*/
@@ -915,7 +915,14 @@
}
s := t.String()
i := len(s) - 1
- for i >= 0 && s[i] != '.' {
+ sqBrackets := 0
+ for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
+ switch s[i] {
+ case ']':
+ sqBrackets++
+ case '[':
+ sqBrackets--
+ }
i--
}
return s[i+1:]
diff --git a/src/regexp/regexp.go b/src/regexp/regexp.go
index af7259c..f975bb3 100644
--- a/src/regexp/regexp.go
+++ b/src/regexp/regexp.go
@@ -42,7 +42,7 @@
// successive submatches of the expression. Submatches are matches of
// parenthesized subexpressions (also known as capturing groups) within the
// regular expression, numbered from left to right in order of opening
-// parenthesis. Submatch 0 is the match of the entire expression, submatch 1
+// parenthesis. Submatch 0 is the match of the entire expression, submatch 1 is
// the match of the first parenthesized subexpression, and so on.
//
// If 'Index' is present, matches and submatches are identified by byte index
diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go
index 06a92fb..0f6587a 100644
--- a/src/regexp/syntax/parse.go
+++ b/src/regexp/syntax/parse.go
@@ -76,13 +76,29 @@
opVerticalBar
)
+// maxHeight is the maximum height of a regexp parse tree.
+// It is somewhat arbitrarily chosen, but the idea is to be large enough
+// that no one will actually hit in real use but at the same time small enough
+// that recursion on the Regexp tree will not hit the 1GB Go stack limit.
+// The maximum amount of stack for a single recursive frame is probably
+// closer to 1kB, so this could potentially be raised, but it seems unlikely
+// that people have regexps nested even this deeply.
+// We ran a test on Google's C++ code base and turned up only
+// a single use case with depth > 100; it had depth 128.
+// Using depth 1000 should be plenty of margin.
+// As an optimization, we don't even bother calculating heights
+// until we've allocated at least maxHeight Regexp structures.
+const maxHeight = 1000
+
type parser struct {
flags Flags // parse mode flags
stack []*Regexp // stack of parsed expressions
free *Regexp
numCap int // number of capturing groups seen
wholeRegexp string
- tmpClass []rune // temporary char class work space
+ tmpClass []rune // temporary char class work space
+ numRegexp int // number of regexps allocated
+ height map[*Regexp]int // regexp height for height limit check
}
func (p *parser) newRegexp(op Op) *Regexp {
@@ -92,16 +108,52 @@
*re = Regexp{}
} else {
re = new(Regexp)
+ p.numRegexp++
}
re.Op = op
return re
}
func (p *parser) reuse(re *Regexp) {
+ if p.height != nil {
+ delete(p.height, re)
+ }
re.Sub0[0] = p.free
p.free = re
}
+func (p *parser) checkHeight(re *Regexp) {
+ if p.numRegexp < maxHeight {
+ return
+ }
+ if p.height == nil {
+ p.height = make(map[*Regexp]int)
+ for _, re := range p.stack {
+ p.checkHeight(re)
+ }
+ }
+ if p.calcHeight(re, true) > maxHeight {
+ panic(ErrInternalError)
+ }
+}
+
+func (p *parser) calcHeight(re *Regexp, force bool) int {
+ if !force {
+ if h, ok := p.height[re]; ok {
+ return h
+ }
+ }
+ h := 1
+ for _, sub := range re.Sub {
+ hsub := p.calcHeight(sub, false)
+ if h < 1+hsub {
+ h = 1 + hsub
+ }
+ }
+ p.height[re] = h
+ return h
+}
+
// Parse stack manipulation.
// push pushes the regexp re onto the parse stack and returns the regexp.
@@ -137,6 +189,7 @@
}
p.stack = append(p.stack, re)
+ p.checkHeight(re)
return re
}
@@ -246,6 +299,7 @@
re.Sub = re.Sub0[:1]
re.Sub[0] = sub
p.stack[n-1] = re
+ p.checkHeight(re)
if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
@@ -693,6 +747,21 @@
// Flags, and returns a regular expression parse tree. The syntax is
// described in the top-level comment.
func Parse(s string, flags Flags) (*Regexp, error) {
+ return parse(s, flags)
+}
+
+func parse(s string, flags Flags) (_ *Regexp, err error) {
+ defer func() {
+ switch r := recover(); r {
+ default:
+ panic(r)
+ case nil:
+ // ok
+ case ErrInternalError:
+ err = &Error{Code: ErrInternalError, Expr: s}
+ }
+ }()
+
if flags&Literal != 0 {
// Trivial parser for literal string.
if err := checkUTF8(s); err != nil {
@@ -704,7 +773,6 @@
// Otherwise, must do real work.
var (
p parser
- err error
c rune
op Op
lastRepeat string
diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go
index 5581ba1..1ef6d8a 100644
--- a/src/regexp/syntax/parse_test.go
+++ b/src/regexp/syntax/parse_test.go
@@ -207,6 +207,11 @@
// Valid repetitions.
{`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``},
{`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``},
+
+ // Valid nesting.
+ {strings.Repeat("(", 999) + strings.Repeat(")", 999), ``},
+ {strings.Repeat("(?:", 999) + strings.Repeat(")*", 999), ``},
+ {"(" + strings.Repeat("|", 12345) + ")", ``}, // not nested at all
}
const testFlags = MatchNL | PerlX | UnicodeGroups
@@ -482,6 +487,8 @@
`a{100000}`,
`a{100000,}`,
"((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
+ strings.Repeat("(", 1000) + strings.Repeat(")", 1000),
+ strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000),
`\Q\E*`,
}
diff --git a/src/runtime/asan.go b/src/runtime/asan.go
index a22b56b..5f1e637 100644
--- a/src/runtime/asan.go
+++ b/src/runtime/asan.go
@@ -11,23 +11,43 @@
)
// Public address sanitizer API.
-
func ASanRead(addr unsafe.Pointer, len int) {
- asanread(addr, uintptr(len))
+ sp := getcallersp()
+ pc := getcallerpc()
+ doasanread(addr, uintptr(len), sp, pc)
}
func ASanWrite(addr unsafe.Pointer, len int) {
- asanwrite(addr, uintptr(len))
+ sp := getcallersp()
+ pc := getcallerpc()
+ doasanwrite(addr, uintptr(len), sp, pc)
}
// Private interface for the runtime.
const asanenabled = true
-//go:noescape
-func asanread(addr unsafe.Pointer, sz uintptr)
+// asan{read,write} are nosplit because they may be called between
+// fork and exec, when the stack must not grow. See issue #50391.
+
+//go:nosplit
+func asanread(addr unsafe.Pointer, sz uintptr) {
+ sp := getcallersp()
+ pc := getcallerpc()
+ doasanread(addr, sz, sp, pc)
+}
+
+//go:nosplit
+func asanwrite(addr unsafe.Pointer, sz uintptr) {
+ sp := getcallersp()
+ pc := getcallerpc()
+ doasanwrite(addr, sz, sp, pc)
+}
//go:noescape
-func asanwrite(addr unsafe.Pointer, sz uintptr)
+func doasanread(addr unsafe.Pointer, sz, sp, pc uintptr)
+
+//go:noescape
+func doasanwrite(addr unsafe.Pointer, sz, sp, pc uintptr)
//go:noescape
func asanunpoison(addr unsafe.Pointer, sz uintptr)
diff --git a/src/runtime/asan/asan.go b/src/runtime/asan/asan.go
index eb66b3a..bab2362 100644
--- a/src/runtime/asan/asan.go
+++ b/src/runtime/asan/asan.go
@@ -14,38 +14,15 @@
#include <stdint.h>
#include <sanitizer/asan_interface.h>
-extern void __asan_report_load1(void*);
-extern void __asan_report_load2(void*);
-extern void __asan_report_load4(void*);
-extern void __asan_report_load8(void*);
-extern void __asan_report_load_n(void*, uintptr_t);
-extern void __asan_report_store1(void*);
-extern void __asan_report_store2(void*);
-extern void __asan_report_store4(void*);
-extern void __asan_report_store8(void*);
-extern void __asan_report_store_n(void*, uintptr_t);
-
-void __asan_read_go(void *addr, uintptr_t sz) {
+void __asan_read_go(void *addr, uintptr_t sz, void *sp, void *pc) {
if (__asan_region_is_poisoned(addr, sz)) {
- switch (sz) {
- case 1: __asan_report_load1(addr); break;
- case 2: __asan_report_load2(addr); break;
- case 4: __asan_report_load4(addr); break;
- case 8: __asan_report_load8(addr); break;
- default: __asan_report_load_n(addr, sz); break;
- }
+ __asan_report_error(pc, 0, sp, addr, false, sz);
}
}
-void __asan_write_go(void *addr, uintptr_t sz) {
+void __asan_write_go(void *addr, uintptr_t sz, void *sp, void *pc) {
if (__asan_region_is_poisoned(addr, sz)) {
- switch (sz) {
- case 1: __asan_report_store1(addr); break;
- case 2: __asan_report_store2(addr); break;
- case 4: __asan_report_store4(addr); break;
- case 8: __asan_report_store8(addr); break;
- default: __asan_report_store_n(addr, sz); break;
- }
+ __asan_report_error(pc, 0, sp, addr, true, sz);
}
}
diff --git a/src/runtime/asan_amd64.s b/src/runtime/asan_amd64.s
index e8de803..3857350 100644
--- a/src/runtime/asan_amd64.s
+++ b/src/runtime/asan_amd64.s
@@ -15,25 +15,33 @@
#ifdef GOOS_windows
#define RARG0 CX
#define RARG1 DX
+#define RARG2 R8
+#define RARG3 R9
#else
#define RARG0 DI
#define RARG1 SI
+#define RARG2 DX
+#define RARG3 CX
#endif
// Called from intrumented code.
-// func runtime·asanread(addr unsafe.Pointer, sz uintptr)
-TEXT runtime·asanread(SB), NOSPLIT, $0-16
+// func runtime·doasanread(addr unsafe.Pointer, sz, sp, pc uintptr)
+TEXT runtime·doasanread(SB), NOSPLIT, $0-32
MOVQ addr+0(FP), RARG0
MOVQ size+8(FP), RARG1
- // void __asan_read_go(void *addr, uintptr_t sz);
+ MOVQ sp+16(FP), RARG2
+ MOVQ pc+24(FP), RARG3
+ // void __asan_read_go(void *addr, uintptr_t sz, void *sp, void *pc);
MOVQ $__asan_read_go(SB), AX
JMP asancall<>(SB)
-// func runtime·asanwrite(addr unsafe.Pointer, sz uintptr)
-TEXT runtime·asanwrite(SB), NOSPLIT, $0-16
+// func runtime·doasanwrite(addr unsafe.Pointer, sz, sp, pc uintptr)
+TEXT runtime·doasanwrite(SB), NOSPLIT, $0-32
MOVQ addr+0(FP), RARG0
MOVQ size+8(FP), RARG1
- // void __asan_write_go(void *addr, uintptr_t sz);
+ MOVQ sp+16(FP), RARG2
+ MOVQ pc+24(FP), RARG3
+ // void __asan_write_go(void *addr, uintptr_t sz, void *sp, void *pc);
MOVQ $__asan_write_go(SB), AX
JMP asancall<>(SB)
diff --git a/src/runtime/asan_arm64.s b/src/runtime/asan_arm64.s
index acae200..5ed03c9 100644
--- a/src/runtime/asan_arm64.s
+++ b/src/runtime/asan_arm64.s
@@ -9,22 +9,28 @@
#define RARG0 R0
#define RARG1 R1
-#define FARG R3
+#define RARG2 R2
+#define RARG3 R3
+#define FARG R4
// Called from instrumented code.
-// func runtime·asanread(addr unsafe.Pointer, sz uintptr)
-TEXT runtime·asanread(SB), NOSPLIT, $0-16
+// func runtime·doasanread(addr unsafe.Pointer, sz, sp, pc uintptr)
+TEXT runtime·doasanread(SB), NOSPLIT, $0-32
MOVD addr+0(FP), RARG0
MOVD size+8(FP), RARG1
- // void __asan_read_go(void *addr, uintptr_t sz);
+ MOVD sp+16(FP), RARG2
+ MOVD pc+24(FP), RARG3
+ // void __asan_read_go(void *addr, uintptr_t sz, void *sp, void *pc);
MOVD $__asan_read_go(SB), FARG
JMP asancall<>(SB)
-// func runtime·asanwrite(addr unsafe.Pointer, sz uintptr)
-TEXT runtime·asanwrite(SB), NOSPLIT, $0-16
+// func runtime·doasanwrite(addr unsafe.Pointer, sz, sp, pc uintptr)
+TEXT runtime·doasanwrite(SB), NOSPLIT, $0-32
MOVD addr+0(FP), RARG0
MOVD size+8(FP), RARG1
- // void __asan_write_go(void *addr, uintptr_t sz);
+ MOVD sp+16(FP), RARG2
+ MOVD pc+24(FP), RARG3
+ // void __asan_write_go(void *addr, uintptr_t sz, void *sp, void *pc);
MOVD $__asan_write_go(SB), FARG
JMP asancall<>(SB)
@@ -53,8 +59,8 @@
CMP R11, g
BEQ g0stack
- MOVD (g_sched+gobuf_sp)(R11), R4
- MOVD R4, RSP
+ MOVD (g_sched+gobuf_sp)(R11), R5
+ MOVD R5, RSP
g0stack:
BL (FARG)
diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s
index 594cd5e..e16880c 100644
--- a/src/runtime/asm_386.s
+++ b/src/runtime/asm_386.s
@@ -937,8 +937,9 @@
PAND masks<>(SB)(BX*8), X1
final1:
- AESENC X0, X1 // scramble input, xor in seed
- AESENC X1, X1 // scramble combo 2 times
+ PXOR X0, X1 // xor data with seed
+ AESENC X1, X1 // scramble combo 3 times
+ AESENC X1, X1
AESENC X1, X1
MOVL X1, (DX)
RET
@@ -971,9 +972,13 @@
MOVOU (AX), X2
MOVOU -16(AX)(BX*1), X3
+ // xor with seed
+ PXOR X0, X2
+ PXOR X1, X3
+
// scramble 3 times
- AESENC X0, X2
- AESENC X1, X3
+ AESENC X2, X2
+ AESENC X3, X3
AESENC X2, X2
AESENC X3, X3
AESENC X2, X2
@@ -1000,10 +1005,15 @@
MOVOU -32(AX)(BX*1), X6
MOVOU -16(AX)(BX*1), X7
- AESENC X0, X4
- AESENC X1, X5
- AESENC X2, X6
- AESENC X3, X7
+ PXOR X0, X4
+ PXOR X1, X5
+ PXOR X2, X6
+ PXOR X3, X7
+
+ AESENC X4, X4
+ AESENC X5, X5
+ AESENC X6, X6
+ AESENC X7, X7
AESENC X4, X4
AESENC X5, X5
@@ -1069,7 +1079,12 @@
DECL BX
JNE aesloop
- // 2 more scrambles to finish
+ // 3 more scrambles to finish
+ AESENC X4, X4
+ AESENC X5, X5
+ AESENC X6, X6
+ AESENC X7, X7
+
AESENC X4, X4
AESENC X5, X5
AESENC X6, X6
diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s
index 0e81318..2a4837b 100644
--- a/src/runtime/asm_riscv64.s
+++ b/src/runtime/asm_riscv64.s
@@ -81,7 +81,10 @@
// func cputicks() int64
TEXT runtime·cputicks(SB),NOSPLIT,$0-8
- RDCYCLE A0
+ // RDTIME to emulate cpu ticks
+ // RDCYCLE reads counter that is per HART(core) based
+ // according to the riscv manual, see issue 46737
+ RDTIME A0
MOV A0, ret+0(FP)
RET
diff --git a/src/runtime/cgo/gcc_amd64.S b/src/runtime/cgo/gcc_amd64.S
index d75f864..46699d1 100644
--- a/src/runtime/cgo/gcc_amd64.S
+++ b/src/runtime/cgo/gcc_amd64.S
@@ -12,7 +12,7 @@
#endif
/*
- * void crosscall_amd64(void (*fn)(void))
+ * void crosscall_amd64(void (*fn)(void), void (*setg_gcc)(void*), void *g)
*
* Calling into the 6c tool chain, where all registers are caller save.
* Called from standard x86-64 ABI, where %rbx, %rbp, %r12-%r15
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 058eae1..c9c9406 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -7,7 +7,6 @@
package runtime_test
import (
- "bytes"
"fmt"
"internal/testenv"
"os"
@@ -95,17 +94,8 @@
t.Skipf("no pthreads on %s", runtime.GOOS)
}
- exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
- if err != nil {
- t.Fatal(err)
- }
-
- got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
- if err != nil {
- t.Fatalf("exit status: %v\n%s", err, got)
- }
-
- if want := "OK\n"; string(got) != want {
+ got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF", "GO_START_SIGPROF_THREAD=1")
+ if want := "OK\n"; got != want {
t.Fatalf("expected %q, but got:\n%s", want, got)
}
}
@@ -118,18 +108,8 @@
t.Skipf("no pthreads on %s", runtime.GOOS)
}
- exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
- if err != nil {
- t.Fatal(err)
- }
-
- got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSignal")).CombinedOutput()
- if err != nil {
- t.Fatalf("exit status: %v\n%s", err, got)
- }
-
- want := []byte("OK\n")
- if !bytes.Equal(got, want) {
+ got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
+ if want := "OK\n"; got != want {
t.Fatalf("expected %q, but got:\n%s", want, got)
}
}
@@ -236,6 +216,19 @@
}
}
+func TestCgoPprofCallback(t *testing.T) {
+ t.Parallel()
+ switch runtime.GOOS {
+ case "windows", "plan9":
+ t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS)
+ }
+ got := runTestProg(t, "testprogcgo", "CgoPprofCallback")
+ want := "OK\n"
+ if got != want {
+ t.Errorf("expected %q got %v", want, got)
+ }
+}
+
func TestCgoCrashTraceback(t *testing.T) {
t.Parallel()
switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
@@ -616,21 +609,32 @@
t.Log(got)
want := "SIGSEGV"
if !strings.Contains(got, want) {
+ if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" && strings.Contains(got, "fatal: morestack on g0") {
+ testenv.SkipFlaky(t, 39457)
+ }
t.Errorf("did not see %q in output", want)
}
// No runtime errors like "runtime: unknown pc".
switch runtime.GOOS {
case "darwin", "illumos", "solaris":
- // TODO(golang.org/issue/49182): Skip, runtime
- // throws while attempting to generate
- // traceback.
- default:
- nowant := "runtime: "
- if strings.Contains(got, nowant) {
- t.Errorf("unexpectedly saw %q in output", nowant)
+ // Runtime sometimes throws when generating the traceback.
+ testenv.SkipFlaky(t, 49182)
+ case "linux":
+ if runtime.GOARCH == "386" {
+ // Runtime throws when generating a traceback from
+ // a VDSO call via asmcgocall.
+ testenv.SkipFlaky(t, 50504)
}
}
+ if test == "SegvInCgo" && strings.Contains(got, "runtime: unknown pc") {
+ testenv.SkipFlaky(t, 50979)
+ }
+
+ nowant := "runtime: "
+ if strings.Contains(got, nowant) {
+ t.Errorf("unexpectedly saw %q in output", nowant)
+ }
})
}
}
diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go
index 1eb10f9..a218205 100644
--- a/src/runtime/crash_unix_test.go
+++ b/src/runtime/crash_unix_test.go
@@ -132,7 +132,7 @@
out := outbuf.Bytes()
n := bytes.Count(out, []byte("main.crashDumpsAllThreadsLoop("))
if n != 4 {
- t.Errorf("found %d instances of main.loop; expected 4", n)
+ t.Errorf("found %d instances of main.crashDumpsAllThreadsLoop; expected 4", n)
t.Logf("%s", out)
}
}
diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go
index 14a496a..688e258 100644
--- a/src/runtime/debug/mod.go
+++ b/src/runtime/debug/mod.go
@@ -5,9 +5,9 @@
package debug
import (
- "bytes"
"fmt"
"runtime"
+ "strconv"
"strings"
)
@@ -23,8 +23,8 @@
return nil, false
}
data = data[16 : len(data)-16]
- bi := &BuildInfo{}
- if err := bi.UnmarshalText([]byte(data)); err != nil {
+ bi, err := ParseBuildInfo(data)
+ if err != nil {
return nil, false
}
@@ -63,8 +63,18 @@
Key, Value string
}
-func (bi *BuildInfo) MarshalText() ([]byte, error) {
- buf := &bytes.Buffer{}
+// quoteKey reports whether key is required to be quoted.
+func quoteKey(key string) bool {
+ return len(key) == 0 || strings.ContainsAny(key, "= \t\r\n\"`")
+}
+
+// quoteValue reports whether value is required to be quoted.
+func quoteValue(value string) bool {
+ return strings.ContainsAny(value, " \t\r\n\"`")
+}
+
+func (bi *BuildInfo) String() string {
+ buf := new(strings.Builder)
if bi.GoVersion != "" {
fmt.Fprintf(buf, "go\t%s\n", bi.GoVersion)
}
@@ -76,12 +86,8 @@
buf.WriteString(word)
buf.WriteByte('\t')
buf.WriteString(m.Path)
- mv := m.Version
- if mv == "" {
- mv = "(devel)"
- }
buf.WriteByte('\t')
- buf.WriteString(mv)
+ buf.WriteString(m.Version)
if m.Replace == nil {
buf.WriteByte('\t')
buf.WriteString(m.Sum)
@@ -91,27 +97,28 @@
}
buf.WriteByte('\n')
}
- if bi.Main.Path != "" {
+ if bi.Main != (Module{}) {
formatMod("mod", bi.Main)
}
for _, dep := range bi.Deps {
formatMod("dep", *dep)
}
for _, s := range bi.Settings {
- if strings.ContainsAny(s.Key, "= \t\n") {
- return nil, fmt.Errorf("invalid build setting key %q", s.Key)
+ key := s.Key
+ if quoteKey(key) {
+ key = strconv.Quote(key)
}
- if strings.Contains(s.Value, "\n") {
- return nil, fmt.Errorf("invalid build setting value for key %q: contains newline", s.Value)
+ value := s.Value
+ if quoteValue(value) {
+ value = strconv.Quote(value)
}
- fmt.Fprintf(buf, "build\t%s=%s\n", s.Key, s.Value)
+ fmt.Fprintf(buf, "build\t%s=%s\n", key, value)
}
- return buf.Bytes(), nil
+ return buf.String()
}
-func (bi *BuildInfo) UnmarshalText(data []byte) (err error) {
- *bi = BuildInfo{}
+func ParseBuildInfo(data string) (bi *BuildInfo, err error) {
lineNum := 1
defer func() {
if err != nil {
@@ -120,67 +127,69 @@
}()
var (
- pathLine = []byte("path\t")
- modLine = []byte("mod\t")
- depLine = []byte("dep\t")
- repLine = []byte("=>\t")
- buildLine = []byte("build\t")
- newline = []byte("\n")
- tab = []byte("\t")
+ pathLine = "path\t"
+ modLine = "mod\t"
+ depLine = "dep\t"
+ repLine = "=>\t"
+ buildLine = "build\t"
+ newline = "\n"
+ tab = "\t"
)
- readModuleLine := func(elem [][]byte) (Module, error) {
+ readModuleLine := func(elem []string) (Module, error) {
if len(elem) != 2 && len(elem) != 3 {
return Module{}, fmt.Errorf("expected 2 or 3 columns; got %d", len(elem))
}
+ version := elem[1]
sum := ""
if len(elem) == 3 {
- sum = string(elem[2])
+ sum = elem[2]
}
return Module{
- Path: string(elem[0]),
- Version: string(elem[1]),
+ Path: elem[0],
+ Version: version,
Sum: sum,
}, nil
}
+ bi = new(BuildInfo)
var (
last *Module
- line []byte
+ line string
ok bool
)
// Reverse of BuildInfo.String(), except for go version.
for len(data) > 0 {
- line, data, ok = bytes.Cut(data, newline)
+ line, data, ok = strings.Cut(data, newline)
if !ok {
break
}
switch {
- case bytes.HasPrefix(line, pathLine):
+ case strings.HasPrefix(line, pathLine):
elem := line[len(pathLine):]
bi.Path = string(elem)
- case bytes.HasPrefix(line, modLine):
- elem := bytes.Split(line[len(modLine):], tab)
+ case strings.HasPrefix(line, modLine):
+ elem := strings.Split(line[len(modLine):], tab)
last = &bi.Main
*last, err = readModuleLine(elem)
if err != nil {
- return err
+ return nil, err
}
- case bytes.HasPrefix(line, depLine):
- elem := bytes.Split(line[len(depLine):], tab)
+ case strings.HasPrefix(line, depLine):
+ elem := strings.Split(line[len(depLine):], tab)
last = new(Module)
bi.Deps = append(bi.Deps, last)
*last, err = readModuleLine(elem)
if err != nil {
- return err
+ return nil, err
}
- case bytes.HasPrefix(line, repLine):
- elem := bytes.Split(line[len(repLine):], tab)
+ case strings.HasPrefix(line, repLine):
+ elem := strings.Split(line[len(repLine):], tab)
if len(elem) != 3 {
- return fmt.Errorf("expected 3 columns for replacement; got %d", len(elem))
+ return nil, fmt.Errorf("expected 3 columns for replacement; got %d", len(elem))
}
if last == nil {
- return fmt.Errorf("replacement with no module on previous line")
+ return nil, fmt.Errorf("replacement with no module on previous line")
}
last.Replace = &Module{
Path: string(elem[0]),
@@ -188,17 +197,63 @@
Sum: string(elem[2]),
}
last = nil
- case bytes.HasPrefix(line, buildLine):
- key, val, ok := strings.Cut(string(line[len(buildLine):]), "=")
- if !ok {
- return fmt.Errorf("invalid build line")
+ case strings.HasPrefix(line, buildLine):
+ kv := line[len(buildLine):]
+ if len(kv) < 1 {
+ return nil, fmt.Errorf("build line missing '='")
}
- if key == "" {
- return fmt.Errorf("empty key")
+
+ var key, rawValue string
+ switch kv[0] {
+ case '=':
+ return nil, fmt.Errorf("build line with missing key")
+
+ case '`', '"':
+ rawKey, err := strconv.QuotedPrefix(kv)
+ if err != nil {
+ return nil, fmt.Errorf("invalid quoted key in build line")
+ }
+ if len(kv) == len(rawKey) {
+ return nil, fmt.Errorf("build line missing '=' after quoted key")
+ }
+ if c := kv[len(rawKey)]; c != '=' {
+ return nil, fmt.Errorf("unexpected character after quoted key: %q", c)
+ }
+ key, _ = strconv.Unquote(rawKey)
+ rawValue = kv[len(rawKey)+1:]
+
+ default:
+ var ok bool
+ key, rawValue, ok = strings.Cut(kv, "=")
+ if !ok {
+ return nil, fmt.Errorf("build line missing '=' after key")
+ }
+ if quoteKey(key) {
+ return nil, fmt.Errorf("unquoted key %q must be quoted", key)
+ }
}
- bi.Settings = append(bi.Settings, BuildSetting{Key: key, Value: val})
+
+ var value string
+ if len(rawValue) > 0 {
+ switch rawValue[0] {
+ case '`', '"':
+ var err error
+ value, err = strconv.Unquote(rawValue)
+ if err != nil {
+ return nil, fmt.Errorf("invalid quoted value in build line")
+ }
+
+ default:
+ value = rawValue
+ if quoteValue(value) {
+ return nil, fmt.Errorf("unquoted value %q must be quoted", value)
+ }
+ }
+ }
+
+ bi.Settings = append(bi.Settings, BuildSetting{Key: key, Value: value})
}
lineNum++
}
- return nil
+ return bi, nil
}
diff --git a/src/runtime/debug/mod_test.go b/src/runtime/debug/mod_test.go
new file mode 100644
index 0000000..b291769
--- /dev/null
+++ b/src/runtime/debug/mod_test.go
@@ -0,0 +1,75 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package debug_test
+
+import (
+ "reflect"
+ "runtime/debug"
+ "strings"
+ "testing"
+)
+
+// strip removes two leading tabs after each newline of s.
+func strip(s string) string {
+ replaced := strings.ReplaceAll(s, "\n\t\t", "\n")
+ if len(replaced) > 0 && replaced[0] == '\n' {
+ replaced = replaced[1:]
+ }
+ return replaced
+}
+
+func FuzzParseBuildInfoRoundTrip(f *testing.F) {
+ // Package built from outside a module, missing some fields..
+ f.Add(strip(`
+ path rsc.io/fortune
+ mod rsc.io/fortune v1.0.0
+ `))
+
+ // Package built from the standard library, missing some fields..
+ f.Add(`path cmd/test2json`)
+
+ // Package built from inside a module.
+ f.Add(strip(`
+ go 1.18
+ path example.com/m
+ mod example.com/m (devel)
+ build -compiler=gc
+ `))
+
+ // Package built in GOPATH mode.
+ f.Add(strip(`
+ go 1.18
+ path example.com/m
+ build -compiler=gc
+ `))
+
+ // Escaped build info.
+ f.Add(strip(`
+ go 1.18
+ path example.com/m
+ build CRAZY_ENV="requires\nescaping"
+ `))
+
+ f.Fuzz(func(t *testing.T, s string) {
+ bi, err := debug.ParseBuildInfo(s)
+ if err != nil {
+ // Not a round-trippable BuildInfo string.
+ t.Log(err)
+ return
+ }
+
+ // s2 could have different escaping from s.
+ // However, it should parse to exactly the same contents.
+ s2 := bi.String()
+ bi2, err := debug.ParseBuildInfo(s2)
+ if err != nil {
+ t.Fatalf("%v:\n%s", err, s2)
+ }
+
+ if !reflect.DeepEqual(bi2, bi) {
+ t.Fatalf("Parsed representation differs.\ninput:\n%s\noutput:\n%s", s, s2)
+ }
+ })
+}
diff --git a/src/runtime/defs_linux.go b/src/runtime/defs_linux.go
index fa94e38..95f807b 100644
--- a/src/runtime/defs_linux.go
+++ b/src/runtime/defs_linux.go
@@ -91,6 +91,8 @@
SIGPWR = C.SIGPWR
SIGSYS = C.SIGSYS
+ SIGRTMIN = C.SIGRTMIN
+
FPE_INTDIV = C.FPE_INTDIV
FPE_INTOVF = C.FPE_INTOVF
FPE_FLTDIV = C.FPE_FLTDIV
diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go
index 24fb58b..d24d00f 100644
--- a/src/runtime/defs_linux_386.go
+++ b/src/runtime/defs_linux_386.go
@@ -64,6 +64,8 @@
_SIGPWR = 0x1e
_SIGSYS = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go
index 36da22f..47fb468 100644
--- a/src/runtime/defs_linux_amd64.go
+++ b/src/runtime/defs_linux_amd64.go
@@ -64,6 +64,8 @@
_SIGPWR = 0x1e
_SIGSYS = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go
index 13d0696..ed387e6 100644
--- a/src/runtime/defs_linux_arm.go
+++ b/src/runtime/defs_linux_arm.go
@@ -63,6 +63,7 @@
_SIGIO = 0x1d
_SIGPWR = 0x1e
_SIGSYS = 0x1f
+ _SIGRTMIN = 0x20
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_arm64.go b/src/runtime/defs_linux_arm64.go
index f9ee9cb..97b3a96 100644
--- a/src/runtime/defs_linux_arm64.go
+++ b/src/runtime/defs_linux_arm64.go
@@ -64,6 +64,8 @@
_SIGPWR = 0x1e
_SIGSYS = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go
index 2601082..67f28dd 100644
--- a/src/runtime/defs_linux_mips64x.go
+++ b/src/runtime/defs_linux_mips64x.go
@@ -66,6 +66,8 @@
_SIGXCPU = 0x1e
_SIGXFSZ = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go
index 37651ef..b5c0d7f 100644
--- a/src/runtime/defs_linux_mipsx.go
+++ b/src/runtime/defs_linux_mipsx.go
@@ -66,6 +66,8 @@
_SIGXCPU = 0x1e
_SIGXFSZ = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_ppc64.go b/src/runtime/defs_linux_ppc64.go
index c7aa723..c077868 100644
--- a/src/runtime/defs_linux_ppc64.go
+++ b/src/runtime/defs_linux_ppc64.go
@@ -63,6 +63,8 @@
_SIGPWR = 0x1e
_SIGSYS = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_ppc64le.go b/src/runtime/defs_linux_ppc64le.go
index c7aa723..c077868 100644
--- a/src/runtime/defs_linux_ppc64le.go
+++ b/src/runtime/defs_linux_ppc64le.go
@@ -63,6 +63,8 @@
_SIGPWR = 0x1e
_SIGSYS = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_riscv64.go b/src/runtime/defs_linux_riscv64.go
index 747e26b..30bf177 100644
--- a/src/runtime/defs_linux_riscv64.go
+++ b/src/runtime/defs_linux_riscv64.go
@@ -65,6 +65,8 @@
_SIGPWR = 0x1e
_SIGSYS = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/defs_linux_s390x.go b/src/runtime/defs_linux_s390x.go
index 740d810..224136a 100644
--- a/src/runtime/defs_linux_s390x.go
+++ b/src/runtime/defs_linux_s390x.go
@@ -64,6 +64,8 @@
_SIGPWR = 0x1e
_SIGSYS = 0x1f
+ _SIGRTMIN = 0x20
+
_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
diff --git a/src/runtime/export_futex_test.go b/src/runtime/export_futex_test.go
deleted file mode 100644
index 03157d8..0000000
--- a/src/runtime/export_futex_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build dragonfly || freebsd || linux
-
-package runtime
-
-var Futexwakeup = futexwakeup
-
-//go:nosplit
-func Futexsleep(addr *uint32, val uint32, ns int64) {
- // Temporarily disable preemption so that a preemption signal
- // doesn't interrupt the system call.
- poff := debug.asyncpreemptoff
- debug.asyncpreemptoff = 1
- futexsleep(addr, val, ns)
- debug.asyncpreemptoff = poff
-}
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 3c8f9eb..0ac15ce 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -1199,6 +1199,8 @@
(*timeHistogram)(th).record(duration)
}
+var TimeHistogramMetricsBuckets = timeHistogramMetricsBuckets
+
func SetIntArgRegs(a int) int {
lock(&finlock)
old := intArgRegs
@@ -1328,3 +1330,23 @@
func Releasem() {
releasem(getg().m)
}
+
+var Timediv = timediv
+
+type PIController struct {
+ piController
+}
+
+func NewPIController(kp, ti, tt, min, max float64) *PIController {
+ return &PIController{piController{
+ kp: kp,
+ ti: ti,
+ tt: tt,
+ min: min,
+ max: max,
+ }}
+}
+
+func (c *PIController) Next(input, setpoint, period float64) (float64, bool) {
+ return c.piController.next(input, setpoint, period)
+}
diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h
index a454dca..2e2bb30 100644
--- a/src/runtime/funcdata.h
+++ b/src/runtime/funcdata.h
@@ -20,6 +20,7 @@
#define FUNCDATA_OpenCodedDeferInfo 4 /* info for func with open-coded defers */
#define FUNCDATA_ArgInfo 5
#define FUNCDATA_ArgLiveInfo 6
+#define FUNCDATA_WrapInfo 7
// Pseudo-assembly statements.
diff --git a/src/runtime/futex_test.go b/src/runtime/futex_test.go
deleted file mode 100644
index 188d0c6..0000000
--- a/src/runtime/futex_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Futex is only available on DragonFly BSD, FreeBSD and Linux.
-// The race detector emits calls to split stack functions so it breaks
-// the test.
-
-//go:build (dragonfly || freebsd || linux) && !race
-
-package runtime_test
-
-import (
- "runtime"
- "sync"
- "sync/atomic"
- "testing"
- "time"
-)
-
-type futexsleepTest struct {
- mtx uint32
- ns int64
- msg string
- ch chan *futexsleepTest
-}
-
-var futexsleepTests = []futexsleepTest{
- beforeY2038: {mtx: 0, ns: 86400 * 1e9, msg: "before the year 2038"},
- afterY2038: {mtx: 0, ns: (1<<31 + 100) * 1e9, msg: "after the year 2038"},
-}
-
-const (
- beforeY2038 = iota
- afterY2038
-)
-
-func TestFutexsleep(t *testing.T) {
- if runtime.GOMAXPROCS(0) > 1 {
- // futexsleep doesn't handle EINTR or other signals,
- // so spurious wakeups may happen.
- t.Skip("skipping; GOMAXPROCS>1")
- }
-
- start := time.Now()
- var wg sync.WaitGroup
- for i := range futexsleepTests {
- tt := &futexsleepTests[i]
- tt.mtx = 0
- tt.ch = make(chan *futexsleepTest, 1)
- wg.Add(1)
- go func(tt *futexsleepTest) {
- runtime.Entersyscall()
- runtime.Futexsleep(&tt.mtx, 0, tt.ns)
- runtime.Exitsyscall()
- tt.ch <- tt
- wg.Done()
- }(tt)
- }
-loop:
- for {
- select {
- case tt := <-futexsleepTests[beforeY2038].ch:
- t.Errorf("futexsleep test %q finished early after %s", tt.msg, time.Since(start))
- break loop
- case tt := <-futexsleepTests[afterY2038].ch:
- // Looks like FreeBSD 10 kernel has changed
- // the semantics of timedwait on userspace
- // mutex to make broken stuff look broken.
- switch {
- case runtime.GOOS == "freebsd" && runtime.GOARCH == "386":
- t.Log("freebsd/386 may not work correctly after the year 2038, see golang.org/issue/7194")
- default:
- t.Errorf("futexsleep test %q finished early after %s", tt.msg, time.Since(start))
- break loop
- }
- case <-time.After(time.Second):
- break loop
- }
- }
- for i := range futexsleepTests {
- tt := &futexsleepTests[i]
- atomic.StoreUint32(&tt.mtx, 1)
- runtime.Futexwakeup(&tt.mtx, 1)
- }
- wg.Wait()
-}
diff --git a/src/runtime/histogram.go b/src/runtime/histogram.go
index 0cccbcc..cd7e29a 100644
--- a/src/runtime/histogram.go
+++ b/src/runtime/histogram.go
@@ -47,7 +47,7 @@
// │ └---- Next 4 bits -> sub-bucket 1
// └------- Bit 5 set -> super-bucket 2
//
- // Following this pattern, bucket 45 will have the bit 48 set. We don't
+ // Following this pattern, super-bucket 44 will have the bit 47 set. We don't
// have any buckets for higher values, so the highest sub-bucket will
// contain values of 2^48-1 nanoseconds or approx. 3 days. This range is
// more than enough to handle durations produced by the runtime.
@@ -139,36 +139,30 @@
func timeHistogramMetricsBuckets() []float64 {
b := make([]float64, timeHistTotalBuckets+1)
b[0] = float64NegInf()
- for i := 0; i < timeHistNumSuperBuckets; i++ {
- superBucketMin := uint64(0)
- // The (inclusive) minimum for the first non-negative bucket is 0.
- if i > 0 {
- // The minimum for the second bucket will be
- // 1 << timeHistSubBucketBits, indicating that all
- // sub-buckets are represented by the next timeHistSubBucketBits
- // bits.
- // Thereafter, we shift up by 1 each time, so we can represent
- // this pattern as (i-1)+timeHistSubBucketBits.
- superBucketMin = uint64(1) << uint(i-1+timeHistSubBucketBits)
- }
- // subBucketShift is the amount that we need to shift the sub-bucket
- // index to combine it with the bucketMin.
- subBucketShift := uint(0)
- if i > 1 {
- // The first two super buckets are exact with respect to integers,
- // so we'll never have to shift the sub-bucket index. Thereafter,
- // we shift up by 1 with each subsequent bucket.
- subBucketShift = uint(i - 2)
- }
+ // Super-bucket 0 has no bits above timeHistSubBucketBits
+ // set, so just iterate over each bucket and assign the
+ // incrementing bucket.
+ for i := 0; i < timeHistNumSubBuckets; i++ {
+ bucketNanos := uint64(i)
+ b[i+1] = float64(bucketNanos) / 1e9
+ }
+ // Generate the rest of the super-buckets. It's easier to reason
+ // about if we cut out the 0'th bucket, so subtract one since
+ // we just handled that bucket.
+ for i := 0; i < timeHistNumSuperBuckets-1; i++ {
for j := 0; j < timeHistNumSubBuckets; j++ {
- // j is the sub-bucket index. By shifting the index into position to
- // combine with the bucket minimum, we obtain the minimum value for that
- // sub-bucket.
- subBucketMin := superBucketMin + (uint64(j) << subBucketShift)
-
- // Convert the subBucketMin which is in nanoseconds to a float64 seconds value.
+ // Set the super-bucket bit.
+ bucketNanos := uint64(1) << (i + timeHistSubBucketBits)
+ // Set the sub-bucket bits.
+ bucketNanos |= uint64(j) << i
+ // The index for this bucket is going to be the (i+1)'th super bucket
+ // (note that we're starting from zero, but handled the first super-bucket
+ // earlier, so we need to compensate), and the j'th sub bucket.
+ // Add 1 because we left space for -Inf.
+ bucketIndex := (i+1)*timeHistNumSubBuckets + j + 1
+ // Convert nanoseconds to seconds via a division.
// These values will all be exactly representable by a float64.
- b[i*timeHistNumSubBuckets+j+1] = float64(subBucketMin) / 1e9
+ b[bucketIndex] = float64(bucketNanos) / 1e9
}
}
b[len(b)-1] = float64Inf()
diff --git a/src/runtime/histogram_test.go b/src/runtime/histogram_test.go
index dbc64fa..b12b65a 100644
--- a/src/runtime/histogram_test.go
+++ b/src/runtime/histogram_test.go
@@ -68,3 +68,43 @@
dummyTimeHistogram = TimeHistogram{}
}
+
+func TestTimeHistogramMetricsBuckets(t *testing.T) {
+ buckets := TimeHistogramMetricsBuckets()
+
+ nonInfBucketsLen := TimeHistNumSubBuckets * TimeHistNumSuperBuckets
+ expBucketsLen := nonInfBucketsLen + 2 // Count -Inf and +Inf.
+ if len(buckets) != expBucketsLen {
+ t.Fatalf("unexpected length of buckets: got %d, want %d", len(buckets), expBucketsLen)
+ }
+ // Check the first non-Inf 2*TimeHistNumSubBuckets buckets in order, skipping the
+ // first bucket which should be -Inf (checked later).
+ //
+ // Because of the way this scheme works, the bottom TimeHistNumSubBuckets
+ // buckets are fully populated, and then the next TimeHistNumSubBuckets
+ // have the TimeHistSubBucketBits'th bit set, while the bottom are once
+ // again fully populated.
+ for i := 1; i <= 2*TimeHistNumSubBuckets+1; i++ {
+ if got, want := buckets[i], float64(i-1)/1e9; got != want {
+ t.Errorf("expected bucket %d to have value %e, got %e", i, want, got)
+ }
+ }
+ // Check some values.
+ idxToBucket := map[int]float64{
+ 0: math.Inf(-1),
+ 33: float64(0x10<<1) / 1e9,
+ 34: float64(0x11<<1) / 1e9,
+ 49: float64(0x10<<2) / 1e9,
+ 58: float64(0x19<<2) / 1e9,
+ 65: float64(0x10<<3) / 1e9,
+ 513: float64(0x10<<31) / 1e9,
+ 519: float64(0x16<<31) / 1e9,
+ expBucketsLen - 2: float64(0x1f<<43) / 1e9,
+ expBucketsLen - 1: math.Inf(1),
+ }
+ for idx, bucket := range idxToBucket {
+ if got, want := buckets[idx], bucket; got != want {
+ t.Errorf("expected bucket %d to have value %e, got %e", idx, want, got)
+ }
+ }
+}
diff --git a/src/runtime/internal/atomic/atomic_arm.s b/src/runtime/internal/atomic/atomic_arm.s
index be3fd3a..92cbe8a 100644
--- a/src/runtime/internal/atomic/atomic_arm.s
+++ b/src/runtime/internal/atomic/atomic_arm.s
@@ -229,16 +229,22 @@
// functions tail-call into the appropriate implementation, which
// means they must not open a frame. Hence, when they go down the
// panic path, at that point they push the LR to create a real frame
-// (they don't need to pop it because panic won't return).
+// (they don't need to pop it because panic won't return; however, we
+// do need to set the SP delta back).
+
+// Check if R1 is 8-byte aligned, panic if not.
+// Clobbers R2.
+#define CHECK_ALIGN \
+ AND.S $7, R1, R2 \
+ BEQ 4(PC) \
+ MOVW.W R14, -4(R13) /* prepare a real frame */ \
+ BL ·panicUnaligned(SB) \
+ ADD $4, R13 /* compensate SP delta */
TEXT ·Cas64(SB),NOSPLIT,$-4-21
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
- // make unaligned atomic access panic
- AND.S $7, R1, R2
- BEQ 3(PC)
- MOVW.W R14, -4(R13) // prepare a real frame
- BL ·panicUnaligned(SB)
+ CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
@@ -249,11 +255,7 @@
TEXT ·Xadd64(SB),NOSPLIT,$-4-20
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
- // make unaligned atomic access panic
- AND.S $7, R1, R2
- BEQ 3(PC)
- MOVW.W R14, -4(R13) // prepare a real frame
- BL ·panicUnaligned(SB)
+ CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
@@ -264,11 +266,7 @@
TEXT ·Xchg64(SB),NOSPLIT,$-4-20
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
- // make unaligned atomic access panic
- AND.S $7, R1, R2
- BEQ 3(PC)
- MOVW.W R14, -4(R13) // prepare a real frame
- BL ·panicUnaligned(SB)
+ CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
@@ -279,11 +277,7 @@
TEXT ·Load64(SB),NOSPLIT,$-4-12
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
- // make unaligned atomic access panic
- AND.S $7, R1, R2
- BEQ 3(PC)
- MOVW.W R14, -4(R13) // prepare a real frame
- BL ·panicUnaligned(SB)
+ CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
@@ -294,11 +288,7 @@
TEXT ·Store64(SB),NOSPLIT,$-4-12
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
- // make unaligned atomic access panic
- AND.S $7, R1, R2
- BEQ 3(PC)
- MOVW.W R14, -4(R13) // prepare a real frame
- BL ·panicUnaligned(SB)
+ CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
diff --git a/src/runtime/internal/syscall/asm_linux_386.s b/src/runtime/internal/syscall/asm_linux_386.s
new file mode 100644
index 0000000..15aae4d
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_386.s
@@ -0,0 +1,34 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// See ../sys_linux_386.s for the reason why we always use int 0x80
+// instead of the glibc-specific "CALL 0x10(GS)".
+#define INVOKE_SYSCALL INT $0x80
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+//
+// Syscall # in AX, args in BX CX DX SI DI BP, return in AX
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ MOVL num+0(FP), AX // syscall entry
+ MOVL a1+4(FP), BX
+ MOVL a2+8(FP), CX
+ MOVL a3+12(FP), DX
+ MOVL a4+16(FP), SI
+ MOVL a5+20(FP), DI
+ MOVL a6+24(FP), BP
+ INVOKE_SYSCALL
+ CMPL AX, $0xfffff001
+ JLS ok
+ MOVL $-1, r1+28(FP)
+ MOVL $0, r2+32(FP)
+ NEGL AX
+ MOVL AX, errno+36(FP)
+ RET
+ok:
+ MOVL AX, r1+28(FP)
+ MOVL DX, r2+32(FP)
+ MOVL $0, errno+36(FP)
+ RET
diff --git a/src/runtime/internal/syscall/asm_linux_amd64.s b/src/runtime/internal/syscall/asm_linux_amd64.s
new file mode 100644
index 0000000..961d9bd
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_amd64.s
@@ -0,0 +1,33 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+//
+// Syscall # in AX, args in DI SI DX R10 R8 R9, return in AX DX.
+//
+// Note that this differs from "standard" ABI convention, which would pass 4th
+// arg in CX, not R10.
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ MOVQ num+0(FP), AX // syscall entry
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
+ MOVQ a4+32(FP), R10
+ MOVQ a5+40(FP), R8
+ MOVQ a6+48(FP), R9
+ SYSCALL
+ CMPQ AX, $0xfffffffffffff001
+ JLS ok
+ MOVQ $-1, r1+56(FP)
+ MOVQ $0, r2+64(FP)
+ NEGQ AX
+ MOVQ AX, errno+72(FP)
+ RET
+ok:
+ MOVQ AX, r1+56(FP)
+ MOVQ DX, r2+64(FP)
+ MOVQ $0, errno+72(FP)
+ RET
diff --git a/src/runtime/internal/syscall/asm_linux_arm.s b/src/runtime/internal/syscall/asm_linux_arm.s
new file mode 100644
index 0000000..dbf1826
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_arm.s
@@ -0,0 +1,32 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ MOVW num+0(FP), R7 // syscall entry
+ MOVW a1+4(FP), R0
+ MOVW a2+8(FP), R1
+ MOVW a3+12(FP), R2
+ MOVW a4+16(FP), R3
+ MOVW a5+20(FP), R4
+ MOVW a6+24(FP), R5
+ SWI $0
+ MOVW $0xfffff001, R6
+ CMP R6, R0
+ BLS ok
+ MOVW $-1, R1
+ MOVW R1, r1+28(FP)
+ MOVW $0, R2
+ MOVW R2, r2+32(FP)
+ RSB $0, R0, R0
+ MOVW R0, errno+36(FP)
+ RET
+ok:
+ MOVW R0, r1+28(FP)
+ MOVW R1, r2+32(FP)
+ MOVW $0, R0
+ MOVW R0, errno+36(FP)
+ RET
diff --git a/src/runtime/internal/syscall/asm_linux_arm64.s b/src/runtime/internal/syscall/asm_linux_arm64.s
new file mode 100644
index 0000000..83e862f
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_arm64.s
@@ -0,0 +1,29 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ MOVD num+0(FP), R8 // syscall entry
+ MOVD a1+8(FP), R0
+ MOVD a2+16(FP), R1
+ MOVD a3+24(FP), R2
+ MOVD a4+32(FP), R3
+ MOVD a5+40(FP), R4
+ MOVD a6+48(FP), R5
+ SVC
+ CMN $4095, R0
+ BCC ok
+ MOVD $-1, R4
+ MOVD R4, r1+56(FP)
+ MOVD ZR, r2+64(FP)
+ NEG R0, R0
+ MOVD R0, errno+72(FP)
+ RET
+ok:
+ MOVD R0, r1+56(FP)
+ MOVD R1, r2+64(FP)
+ MOVD ZR, errno+72(FP)
+ RET
diff --git a/src/runtime/internal/syscall/asm_linux_mips64x.s b/src/runtime/internal/syscall/asm_linux_mips64x.s
new file mode 100644
index 0000000..0e88a2d
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_mips64x.s
@@ -0,0 +1,29 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build linux && (mips64 || mips64le)
+
+#include "textflag.h"
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ MOVV num+0(FP), R2 // syscall entry
+ MOVV a1+8(FP), R4
+ MOVV a2+16(FP), R5
+ MOVV a3+24(FP), R6
+ MOVV a4+32(FP), R7
+ MOVV a5+40(FP), R8
+ MOVV a6+48(FP), R9
+ SYSCALL
+ BEQ R7, ok
+ MOVV $-1, R1
+ MOVV R1, r1+56(FP)
+ MOVV R0, r2+64(FP)
+ MOVV R2, errno+72(FP)
+ RET
+ok:
+ MOVV R2, r1+56(FP)
+ MOVV R3, r2+64(FP)
+ MOVV R0, errno+72(FP)
+ RET
diff --git a/src/runtime/internal/syscall/asm_linux_mipsx.s b/src/runtime/internal/syscall/asm_linux_mipsx.s
new file mode 100644
index 0000000..050029e
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_mipsx.s
@@ -0,0 +1,34 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build linux && (mips || mipsle)
+
+#include "textflag.h"
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+//
+// The 5th and 6th arg go at sp+16, sp+20.
+// Note that frame size of 20 means that 24 bytes gets reserved on stack.
+TEXT ·Syscall6(SB),NOSPLIT,$20-40
+ MOVW num+0(FP), R2 // syscall entry
+ MOVW a1+4(FP), R4
+ MOVW a2+8(FP), R5
+ MOVW a3+12(FP), R6
+ MOVW a4+16(FP), R7
+ MOVW a5+20(FP), R8
+ MOVW a6+24(FP), R9
+ MOVW R8, 16(R29)
+ MOVW R9, 20(R29)
+ SYSCALL
+ BEQ R7, ok
+ MOVW $-1, R1
+ MOVW R1, r1+28(FP)
+ MOVW R0, r2+32(FP)
+ MOVW R2, errno+36(FP)
+ RET
+ok:
+ MOVW R2, r1+28(FP)
+ MOVW R3, r2+32(FP)
+ MOVW R0, errno+36(FP)
+ RET
diff --git a/src/runtime/internal/syscall/asm_linux_ppc64x.s b/src/runtime/internal/syscall/asm_linux_ppc64x.s
new file mode 100644
index 0000000..8e84638
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_ppc64x.s
@@ -0,0 +1,29 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build linux && (ppc64 || ppc64le)
+
+#include "textflag.h"
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ MOVD num+0(FP), R9 // syscall entry
+ MOVD a1+8(FP), R3
+ MOVD a2+16(FP), R4
+ MOVD a3+24(FP), R5
+ MOVD a4+32(FP), R6
+ MOVD a5+40(FP), R7
+ MOVD a6+48(FP), R8
+ SYSCALL R9
+ BVC ok
+ MOVD $-1, R4
+ MOVD R4, r1+56(FP)
+ MOVD R0, r2+64(FP)
+ MOVD R3, errno+72(FP)
+ RET
+ok:
+ MOVD R3, r1+56(FP)
+ MOVD R4, r2+64(FP)
+ MOVD R0, errno+72(FP)
+ RET
diff --git a/src/runtime/internal/syscall/asm_linux_riscv64.s b/src/runtime/internal/syscall/asm_linux_riscv64.s
new file mode 100644
index 0000000..a8652fd
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_riscv64.s
@@ -0,0 +1,29 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ MOV num+0(FP), A7 // syscall entry
+ MOV a1+8(FP), A0
+ MOV a2+16(FP), A1
+ MOV a3+24(FP), A2
+ MOV a4+32(FP), A3
+ MOV a5+40(FP), A4
+ MOV a6+48(FP), A5
+ ECALL
+ MOV $-4096, T0
+ BLTU T0, A0, err
+ MOV A0, r1+56(FP)
+ MOV A1, r2+64(FP)
+ MOV ZERO, errno+72(FP)
+ RET
+err:
+ MOV $-1, T0
+ MOV T0, r1+56(FP)
+ MOV ZERO, r2+64(FP)
+ SUB A0, ZERO, A0
+ MOV A0, errno+72(FP)
+ RET
diff --git a/src/runtime/internal/syscall/asm_linux_s390x.s b/src/runtime/internal/syscall/asm_linux_s390x.s
new file mode 100644
index 0000000..1b27f29
--- /dev/null
+++ b/src/runtime/internal/syscall/asm_linux_s390x.s
@@ -0,0 +1,28 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ MOVD num+0(FP), R1 // syscall entry
+ MOVD a1+8(FP), R2
+ MOVD a2+16(FP), R3
+ MOVD a3+24(FP), R4
+ MOVD a4+32(FP), R5
+ MOVD a5+40(FP), R6
+ MOVD a6+48(FP), R7
+ SYSCALL
+ MOVD $0xfffffffffffff001, R8
+ CMPUBLT R2, R8, ok
+ MOVD $-1, r1+56(FP)
+ MOVD $0, r2+64(FP)
+ NEG R2, R2
+ MOVD R2, errno+72(FP)
+ RET
+ok:
+ MOVD R2, r1+56(FP)
+ MOVD R3, r2+64(FP)
+ MOVD $0, errno+72(FP)
+ RET
diff --git a/src/runtime/internal/syscall/syscall_linux.go b/src/runtime/internal/syscall/syscall_linux.go
new file mode 100644
index 0000000..06d5f21
--- /dev/null
+++ b/src/runtime/internal/syscall/syscall_linux.go
@@ -0,0 +1,12 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package syscall provides the syscall primitives required for the runtime.
+package syscall
+
+// TODO(https://go.dev/issue/51087): This package is incomplete and currently
+// only contains very minimal support for Linux.
+
+// Syscall6 calls system call number 'num' with arguments a1-6.
+func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go
index 0f8b2af..465c21f 100644
--- a/src/runtime/mbarrier.go
+++ b/src/runtime/mbarrier.go
@@ -198,7 +198,7 @@
// typedmemmovepartial is like typedmemmove but assumes that
// dst and src point off bytes into the value and only copies size bytes.
-// off must be a multiple of sys.PtrSize.
+// off must be a multiple of goarch.PtrSize.
//go:linkname reflect_typedmemmovepartial reflect.typedmemmovepartial
func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
if writeBarrier.needed && typ.ptrdata > off && size >= goarch.PtrSize {
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index 1c6f3f9..9379688 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -843,7 +843,7 @@
// size is sizeof(_defer{}) (at least 6 words) and dataSize may be
// arbitrarily larger.
//
- // The checks for size == sys.PtrSize and size == 2*sys.PtrSize can therefore
+ // The checks for size == goarch.PtrSize and size == 2*goarch.PtrSize can therefore
// assume that dataSize == size without checking it explicitly.
if goarch.PtrSize == 8 && size == goarch.PtrSize {
@@ -893,7 +893,7 @@
}
return
}
- // Otherwise typ.size must be 2*sys.PtrSize,
+ // Otherwise typ.size must be 2*goarch.PtrSize,
// and typ.kind&kindGCProg == 0.
if doubleCheck {
if typ.size != 2*goarch.PtrSize || typ.kind&kindGCProg != 0 {
@@ -1095,8 +1095,8 @@
// Replicate ptrmask to fill entire pbits uintptr.
// Doubling and truncating is fewer steps than
// iterating by nb each time. (nb could be 1.)
- // Since we loaded typ.ptrdata/sys.PtrSize bits
- // but are pretending to have typ.size/sys.PtrSize,
+ // Since we loaded typ.ptrdata/goarch.PtrSize bits
+ // but are pretending to have typ.size/goarch.PtrSize,
// there might be no replication necessary/possible.
pbits = b
endnb = nb
@@ -1564,7 +1564,7 @@
// progToPointerMask returns the 1-bit pointer mask output by the GC program prog.
// size the size of the region described by prog, in bytes.
-// The resulting bitvector will have no more than size/sys.PtrSize bits.
+// The resulting bitvector will have no more than size/goarch.PtrSize bits.
func progToPointerMask(prog *byte, size uintptr) bitvector {
n := (size/goarch.PtrSize + 7) / 8
x := (*[1 << 30]byte)(persistentalloc(n+1, 1, &memstats.buckhash_sys))[:n+1]
@@ -1697,7 +1697,7 @@
// into a register and use that register for the entire loop
// instead of repeatedly reading from memory.
// Handling fewer than 8 bits here makes the general loop simpler.
- // The cutoff is sys.PtrSize*8 - 7 to guarantee that when we add
+ // The cutoff is goarch.PtrSize*8 - 7 to guarantee that when we add
// the pattern to a bit buffer holding at most 7 bits (a partial byte)
// it will not overflow.
src := dst
diff --git a/src/runtime/mem_aix.go b/src/runtime/mem_aix.go
index 957aa4d..489d792 100644
--- a/src/runtime/mem_aix.go
+++ b/src/runtime/mem_aix.go
@@ -72,6 +72,7 @@
throw("runtime: out of memory")
}
if err != 0 {
+ print("runtime: mprotect(", v, ", ", n, ") returned ", err, "\n")
throw("runtime: cannot map pages in arena address space")
}
}
diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go
index b152571..49337ea 100644
--- a/src/runtime/mem_bsd.go
+++ b/src/runtime/mem_bsd.go
@@ -73,6 +73,7 @@
throw("runtime: out of memory")
}
if p != v || err != 0 {
+ print("runtime: mmap(", v, ", ", n, ") returned ", p, ", ", err, "\n")
throw("runtime: cannot map pages in arena address space")
}
}
diff --git a/src/runtime/mem_darwin.go b/src/runtime/mem_darwin.go
index 7fccd2b..9f836c0 100644
--- a/src/runtime/mem_darwin.go
+++ b/src/runtime/mem_darwin.go
@@ -66,6 +66,7 @@
throw("runtime: out of memory")
}
if p != v || err != 0 {
+ print("runtime: mmap(", v, ", ", n, ") returned ", p, ", ", err, "\n")
throw("runtime: cannot map pages in arena address space")
}
}
diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go
index f8f9c53..f833301 100644
--- a/src/runtime/mem_linux.go
+++ b/src/runtime/mem_linux.go
@@ -189,6 +189,7 @@
throw("runtime: out of memory")
}
if p != v || err != 0 {
+ print("runtime: mmap(", v, ", ", n, ") returned ", p, ", ", err, "\n")
throw("runtime: cannot map pages in arena address space")
}
}
diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go
index e2ac5d4..10623e4 100644
--- a/src/runtime/mfinal.go
+++ b/src/runtime/mfinal.go
@@ -187,21 +187,15 @@
f := &fb.fin[i-1]
var regs abi.RegArgs
- var framesz uintptr
- if argRegs > 0 {
- // The args can always be passed in registers if they're
- // available, because platforms we support always have no
- // argument registers available, or more than 2.
- //
- // But unfortunately because we can have an arbitrary
- // amount of returns and it would be complex to try and
- // figure out how many of those can get passed in registers,
- // just conservatively assume none of them do.
- framesz = f.nret
- } else {
- // Need to pass arguments on the stack too.
- framesz = unsafe.Sizeof((any)(nil)) + f.nret
- }
+ // The args may be passed in registers or on stack. Even for
+ // the register case, we still need the spill slots.
+ // TODO: revisit if we remove spill slots.
+ //
+ // Unfortunately because we can have an arbitrary
+ // amount of returns and it would be complex to try and
+ // figure out how many of those can get passed in registers,
+ // just conservatively assume none of them do.
+ framesz := unsafe.Sizeof((any)(nil)) + f.nret
if framecap < framesz {
// The frame does not contain pointers interesting for GC,
// all not yet finalized objects are stored in finq.
diff --git a/src/runtime/mfinal_test.go b/src/runtime/mfinal_test.go
index 04ba7a6..902ccc5 100644
--- a/src/runtime/mfinal_test.go
+++ b/src/runtime/mfinal_test.go
@@ -42,6 +42,15 @@
{func(x *int) any { return Tintptr(x) }, func(v *int) { finalize(v) }},
{func(x *int) any { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }},
{func(x *int) any { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }},
+ // Test case for argument spill slot.
+ // If the spill slot was not counted for the frame size, it will (incorrectly) choose
+ // call32 as the result has (exactly) 32 bytes. When the argument actually spills,
+ // it clobbers the caller's frame (likely the return PC).
+ {func(x *int) any { return x }, func(v any) [4]int64 {
+ print() // force spill
+ finalize(v.(*int))
+ return [4]int64{}
+ }},
}
for i, tt := range finalizerTests {
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 8c8f7d9..44b9615 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -1323,7 +1323,7 @@
// point, signal the main GC goroutine.
if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
// We don't need the P-local buffers here, allow
- // preemption becuse we may schedule like a regular
+ // preemption because we may schedule like a regular
// goroutine in gcMarkDone (block on locks, etc).
releasem(node.m.ptr())
node.m.set(nil)
diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go
index a15c62c..0bf044e 100644
--- a/src/runtime/mgcmark.go
+++ b/src/runtime/mgcmark.go
@@ -401,7 +401,7 @@
}
// gcAssistAlloc performs GC work to make gp's assist debt positive.
-// gp must be the calling user gorountine.
+// gp must be the calling user goroutine.
//
// This must be called with preemption enabled.
func gcAssistAlloc(gp *g) {
@@ -1561,7 +1561,7 @@
if !goexperiment.PacerRedesign {
// The old pacer counts newly allocated memory toward
// heapScanWork because heapScan is continuously updated
- // throughout the GC cyle with newly allocated memory. However,
+ // throughout the GC cycle with newly allocated memory. However,
// these objects are never actually scanned, so we need
// to account for them in heapScanWork here, "faking" their work.
// Otherwise the pacer will think it's always behind, potentially
diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go
index 6df8af4..d54dbc2 100644
--- a/src/runtime/mgcpacer.go
+++ b/src/runtime/mgcpacer.go
@@ -154,6 +154,8 @@
// For goexperiment.PacerRedesign.
consMarkController piController
+ _ uint32 // Padding for atomics on 32-bit platforms.
+
// heapGoal is the goal heapLive for when next GC ends.
// Set to ^uint64(0) if disabled.
//
@@ -670,16 +672,41 @@
currentConsMark := (float64(c.heapLive-c.trigger) * (utilization + idleUtilization)) /
(float64(scanWork) * (1 - utilization))
- // Update cons/mark controller.
- // Period for this is 1 GC cycle.
+ // Update cons/mark controller. The time period for this is 1 GC cycle.
+ //
+ // This use of a PI controller might seem strange. So, here's an explanation:
+ //
+ // currentConsMark represents the consMark we *should've* had to be perfectly
+ // on-target for this cycle. Given that we assume the next GC will be like this
+ // one in the steady-state, it stands to reason that we should just pick that
+ // as our next consMark. In practice, however, currentConsMark is too noisy:
+ // we're going to be wildly off-target in each GC cycle if we do that.
+ //
+ // What we do instead is make a long-term assumption: there is some steady-state
+ // consMark value, but it's obscured by noise. By constantly shooting for this
+ // noisy-but-perfect consMark value, the controller will bounce around a bit,
+ // but its average behavior, in aggregate, should be less noisy and closer to
+ // the true long-term consMark value, provided its tuned to be slightly overdamped.
+ var ok bool
oldConsMark := c.consMark
- c.consMark = c.consMarkController.next(c.consMark, currentConsMark, 1.0)
+ c.consMark, ok = c.consMarkController.next(c.consMark, currentConsMark, 1.0)
+ if !ok {
+ // The error spiraled out of control. This is incredibly unlikely seeing
+ // as this controller is essentially just a smoothing function, but it might
+ // mean that something went very wrong with how currentConsMark was calculated.
+ // Just reset consMark and keep going.
+ c.consMark = 0
+ }
if debug.gcpacertrace > 0 {
printlock()
- print("pacer: ", int(utilization*100), "% CPU (", int(gcGoalUtilization*100), " exp.) for ")
+ goal := gcGoalUtilization * 100
+ print("pacer: ", int(utilization*100), "% CPU (", int(goal), " exp.) for ")
print(c.heapScanWork.Load(), "+", c.stackScanWork.Load(), "+", c.globalsScanWork.Load(), " B work (", c.lastHeapScan+c.stackScan+c.globalsScan, " B exp.) ")
print("in ", c.trigger, " B -> ", c.heapLive, " B (∆goal ", int64(c.heapLive)-int64(c.heapGoal), ", cons/mark ", oldConsMark, ")")
+ if !ok {
+ print("[controller reset]")
+ }
println()
printunlock()
}
@@ -1262,15 +1289,38 @@
// PI controller state.
errIntegral float64 // Integral of the error from t=0 to now.
+
+ // Error flags.
+ errOverflow bool // Set if errIntegral ever overflowed.
+ inputOverflow bool // Set if an operation with the input overflowed.
}
-func (c *piController) next(input, setpoint, period float64) float64 {
+// next provides a new sample to the controller.
+//
+// input is the sample, setpoint is the desired point, and period is how much
+// time (in whatever unit makes the most sense) has passed since the last sample.
+//
+// Returns a new value for the variable it's controlling, and whether the operation
+// completed successfully. One reason this might fail is if error has been growing
+// in an unbounded manner, to the point of overflow.
+//
+// In the specific case of an error overflow occurs, the errOverflow field will be
+// set and the rest of the controller's internal state will be fully reset.
+func (c *piController) next(input, setpoint, period float64) (float64, bool) {
// Compute the raw output value.
prop := c.kp * (setpoint - input)
rawOutput := prop + c.errIntegral
// Clamp rawOutput into output.
output := rawOutput
+ if isInf(output) || isNaN(output) {
+ // The input had a large enough magnitude that either it was already
+ // overflowed, or some operation with it overflowed.
+ // Set a flag and reset. That's the safest thing to do.
+ c.reset()
+ c.inputOverflow = true
+ return c.min, false
+ }
if output < c.min {
output = c.min
} else if output > c.max {
@@ -1280,6 +1330,19 @@
// Update the controller's state.
if c.ti != 0 && c.tt != 0 {
c.errIntegral += (c.kp*period/c.ti)*(setpoint-input) + (period/c.tt)*(output-rawOutput)
+ if isInf(c.errIntegral) || isNaN(c.errIntegral) {
+ // So much error has accumulated that we managed to overflow.
+ // The assumptions around the controller have likely broken down.
+ // Set a flag and reset. That's the safest thing to do.
+ c.reset()
+ c.errOverflow = true
+ return c.min, false
+ }
}
- return output
+ return output, true
+}
+
+// reset resets the controller state, except for controller error flags.
+func (c *piController) reset() {
+ c.errIntegral = 0
}
diff --git a/src/runtime/mgcpacer_test.go b/src/runtime/mgcpacer_test.go
index 9ec0e51..10a8ca2 100644
--- a/src/runtime/mgcpacer_test.go
+++ b/src/runtime/mgcpacer_test.go
@@ -715,3 +715,48 @@
return v
}
}
+
+func FuzzPIController(f *testing.F) {
+ isNormal := func(x float64) bool {
+ return !math.IsInf(x, 0) && !math.IsNaN(x)
+ }
+ isPositive := func(x float64) bool {
+ return isNormal(x) && x > 0
+ }
+ // Seed with constants from controllers in the runtime.
+ // It's not critical that we keep these in sync, they're just
+ // reasonable seed inputs.
+ f.Add(0.3375, 3.2e6, 1e9, 0.001, 1000.0, 0.01)
+ f.Add(0.9, 4.0, 1000.0, -1000.0, 1000.0, 0.84)
+ f.Fuzz(func(t *testing.T, kp, ti, tt, min, max, setPoint float64) {
+ // Ignore uninteresting invalid parameters. These parameters
+ // are constant, so in practice surprising values will be documented
+ // or will be other otherwise immediately visible.
+ //
+ // We just want to make sure that given a non-Inf, non-NaN input,
+ // we always get a non-Inf, non-NaN output.
+ if !isPositive(kp) || !isPositive(ti) || !isPositive(tt) {
+ return
+ }
+ if !isNormal(min) || !isNormal(max) || min > max {
+ return
+ }
+ // Use a random source, but make it deterministic.
+ rs := rand.New(rand.NewSource(800))
+ randFloat64 := func() float64 {
+ return math.Float64frombits(rs.Uint64())
+ }
+ p := NewPIController(kp, ti, tt, min, max)
+ state := float64(0)
+ for i := 0; i < 100; i++ {
+ input := randFloat64()
+ // Ignore the "ok" parameter. We're just trying to break it.
+ // state is intentionally completely uncorrelated with the input.
+ var ok bool
+ state, ok = p.Next(input, setPoint, 1.0)
+ if !isNormal(state) {
+ t.Fatalf("got NaN or Inf result from controller: %f %v", state, ok)
+ }
+ }
+ })
+}
diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go
index c27e189..5f50378 100644
--- a/src/runtime/mgcscavenge.go
+++ b/src/runtime/mgcscavenge.go
@@ -165,11 +165,12 @@
// Sleep/wait state of the background scavenger.
var scavenge struct {
- lock mutex
- g *g
- parked bool
- timer *timer
- sysmonWake uint32 // Set atomically.
+ lock mutex
+ g *g
+ parked bool
+ timer *timer
+ sysmonWake uint32 // Set atomically.
+ printControllerReset bool // Whether the scavenger is in cooldown.
}
// readyForScavenger signals sysmon to wake the scavenger because
@@ -295,8 +296,14 @@
max: 1000.0, // 1000:1
}
// It doesn't really matter what value we start at, but we can't be zero, because
- // that'll cause divide-by-zero issues.
- critSleepRatio := 0.001
+ // that'll cause divide-by-zero issues. Pick something conservative which we'll
+ // also use as a fallback.
+ const startingCritSleepRatio = 0.001
+ critSleepRatio := startingCritSleepRatio
+ // Duration left in nanoseconds during which we avoid using the controller and
+ // we hold critSleepRatio at a conservative value. Used if the controller's
+ // assumptions fail to hold.
+ controllerCooldown := int64(0)
for {
released := uintptr(0)
crit := float64(0)
@@ -383,9 +390,22 @@
// because of the additional overheads of using scavenged memory.
crit *= 1 + scavengeCostRatio
- // Go to sleep for our current sleepNS.
+ // Go to sleep based on how much time we spent doing work.
slept := scavengeSleep(int64(crit / critSleepRatio))
+ // Stop here if we're cooling down from the controller.
+ if controllerCooldown > 0 {
+ // crit and slept aren't exact measures of time, but it's OK to be a bit
+ // sloppy here. We're just hoping we're avoiding some transient bad behavior.
+ t := slept + int64(crit)
+ if t > controllerCooldown {
+ controllerCooldown = 0
+ } else {
+ controllerCooldown -= t
+ }
+ continue
+ }
+
// Calculate the CPU time spent.
//
// This may be slightly inaccurate with respect to GOMAXPROCS, but we're
@@ -395,7 +415,20 @@
cpuFraction := float64(crit) / ((float64(slept) + crit) * float64(gomaxprocs))
// Update the critSleepRatio, adjusting until we reach our ideal fraction.
- critSleepRatio = critSleepController.next(cpuFraction, idealFraction, float64(slept)+crit)
+ var ok bool
+ critSleepRatio, ok = critSleepController.next(cpuFraction, idealFraction, float64(slept)+crit)
+ if !ok {
+ // The core assumption of the controller, that we can get a proportional
+ // response, broke down. This may be transient, so temporarily switch to
+ // sleeping a fixed, conservative amount.
+ critSleepRatio = startingCritSleepRatio
+ controllerCooldown = 5e9 // 5 seconds.
+
+ // Signal the scav trace printer to output this.
+ lock(&scavenge.lock)
+ scavenge.printControllerReset = true
+ unlock(&scavenge.lock)
+ }
}
}
@@ -434,7 +467,11 @@
// released should be the amount of memory released since the last time this
// was called, and forced indicates whether the scavenge was forced by the
// application.
+//
+// scavenge.lock must be held.
func printScavTrace(gen uint32, released uintptr, forced bool) {
+ assertLockHeld(&scavenge.lock)
+
printlock()
print("scav ", gen, " ",
released>>10, " KiB work, ",
@@ -443,6 +480,9 @@
)
if forced {
print(" (forced)")
+ } else if scavenge.printControllerReset {
+ print(" [controller reset]")
+ scavenge.printControllerReset = false
}
println()
printunlock()
diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go
index fdbec30..a46f4ec 100644
--- a/src/runtime/mgcsweep.go
+++ b/src/runtime/mgcsweep.go
@@ -393,7 +393,7 @@
// The scavenger is signaled by the last sweeper because once
// sweeping is done, we will definitely have useful work for
// the scavenger to do, since the scavenger only runs over the
- // heap once per GC cyle. This update is not done during sweep
+ // heap once per GC cycle. This update is not done during sweep
// termination because in some cases there may be a long delay
// between sweep done and sweep termination (e.g. not enough
// allocations to trigger a GC) which would be nice to fill in
diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go
index 322a6f3..bb3dd35 100644
--- a/src/runtime/netpoll.go
+++ b/src/runtime/netpoll.go
@@ -71,31 +71,99 @@
//go:notinheap
type pollDesc struct {
link *pollDesc // in pollcache, protected by pollcache.lock
+ fd uintptr // constant for pollDesc usage lifetime
- // The lock protects pollOpen, pollSetDeadline, pollUnblock and deadlineimpl operations.
- // This fully covers seq, rt and wt variables. fd is constant throughout the PollDesc lifetime.
- // pollReset, pollWait, pollWaitCanceled and runtime·netpollready (IO readiness notification)
- // proceed w/o taking the lock. So closing, everr, rg, rd, wg and wd are manipulated
- // in a lock-free way by all operations.
- // TODO(golang.org/issue/49008): audit these lock-free fields for continued correctness.
- // NOTE(dvyukov): the following code uses uintptr to store *g (rg/wg),
- // that will blow up when GC starts moving objects.
+ // atomicInfo holds bits from closing, rd, and wd,
+ // which are only ever written while holding the lock,
+ // summarized for use by netpollcheckerr,
+ // which cannot acquire the lock.
+ // After writing these fields under lock in a way that
+ // might change the summary, code must call publishInfo
+ // before releasing the lock.
+ // Code that changes fields and then calls netpollunblock
+ // (while still holding the lock) must call publishInfo
+ // before calling netpollunblock, because publishInfo is what
+ // stops netpollblock from blocking anew
+ // (by changing the result of netpollcheckerr).
+ // atomicInfo also holds the eventErr bit,
+ // recording whether a poll event on the fd got an error;
+ // atomicInfo is the only source of truth for that bit.
+ atomicInfo atomic.Uint32 // atomic pollInfo
+
+ // rg, wg are accessed atomically and hold g pointers.
+ // (Using atomic.Uintptr here is similar to using guintptr elsewhere.)
+ rg atomic.Uintptr // pdReady, pdWait, G waiting for read or nil
+ wg atomic.Uintptr // pdReady, pdWait, G waiting for write or nil
+
lock mutex // protects the following fields
- fd uintptr
closing bool
- everr bool // marks event scanning error happened
user uint32 // user settable cookie
rseq uintptr // protects from stale read timers
- rg uintptr // pdReady, pdWait, G waiting for read or nil. Accessed atomically.
rt timer // read deadline timer (set if rt.f != nil)
- rd int64 // read deadline
+ rd int64 // read deadline (a nanotime in the future, -1 when expired)
wseq uintptr // protects from stale write timers
- wg uintptr // pdReady, pdWait, G waiting for write or nil. Accessed atomically.
wt timer // write deadline timer
- wd int64 // write deadline
+ wd int64 // write deadline (a nanotime in the future, -1 when expired)
self *pollDesc // storage for indirect interface. See (*pollDesc).makeArg.
}
+// pollInfo is the bits needed by netpollcheckerr, stored atomically,
+// mostly duplicating state that is manipulated under lock in pollDesc.
+// The one exception is the pollEventErr bit, which is maintained only
+// in the pollInfo.
+type pollInfo uint32
+
+const (
+ pollClosing = 1 << iota
+ pollEventErr
+ pollExpiredReadDeadline
+ pollExpiredWriteDeadline
+)
+
+func (i pollInfo) closing() bool { return i&pollClosing != 0 }
+func (i pollInfo) eventErr() bool { return i&pollEventErr != 0 }
+func (i pollInfo) expiredReadDeadline() bool { return i&pollExpiredReadDeadline != 0 }
+func (i pollInfo) expiredWriteDeadline() bool { return i&pollExpiredWriteDeadline != 0 }
+
+// info returns the pollInfo corresponding to pd.
+func (pd *pollDesc) info() pollInfo {
+ return pollInfo(pd.atomicInfo.Load())
+}
+
+// publishInfo updates pd.atomicInfo (returned by pd.info)
+// using the other values in pd.
+// It must be called while holding pd.lock,
+// and it must be called after changing anything
+// that might affect the info bits.
+// In practice this means after changing closing
+// or changing rd or wd from < 0 to >= 0.
+func (pd *pollDesc) publishInfo() {
+ var info uint32
+ if pd.closing {
+ info |= pollClosing
+ }
+ if pd.rd < 0 {
+ info |= pollExpiredReadDeadline
+ }
+ if pd.wd < 0 {
+ info |= pollExpiredWriteDeadline
+ }
+
+ // Set all of x except the pollEventErr bit.
+ x := pd.atomicInfo.Load()
+ for !pd.atomicInfo.CompareAndSwap(x, (x&pollEventErr)|info) {
+ x = pd.atomicInfo.Load()
+ }
+}
+
+// setEventErr sets the result of pd.info().eventErr() to b.
+func (pd *pollDesc) setEventErr(b bool) {
+ x := pd.atomicInfo.Load()
+ for (x&pollEventErr != 0) != b && !pd.atomicInfo.CompareAndSwap(x, x^pollEventErr) {
+ x = pd.atomicInfo.Load()
+ }
+}
+
type pollCache struct {
lock mutex
first *pollDesc
@@ -147,24 +215,25 @@
func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) {
pd := pollcache.alloc()
lock(&pd.lock)
- wg := atomic.Loaduintptr(&pd.wg)
+ wg := pd.wg.Load()
if wg != 0 && wg != pdReady {
throw("runtime: blocked write on free polldesc")
}
- rg := atomic.Loaduintptr(&pd.rg)
+ rg := pd.rg.Load()
if rg != 0 && rg != pdReady {
throw("runtime: blocked read on free polldesc")
}
pd.fd = fd
pd.closing = false
- pd.everr = false
+ pd.setEventErr(false)
pd.rseq++
- atomic.Storeuintptr(&pd.rg, 0)
+ pd.rg.Store(0)
pd.rd = 0
pd.wseq++
- atomic.Storeuintptr(&pd.wg, 0)
+ pd.wg.Store(0)
pd.wd = 0
pd.self = pd
+ pd.publishInfo()
unlock(&pd.lock)
errno := netpollopen(fd, pd)
@@ -180,11 +249,11 @@
if !pd.closing {
throw("runtime: close polldesc w/o unblock")
}
- wg := atomic.Loaduintptr(&pd.wg)
+ wg := pd.wg.Load()
if wg != 0 && wg != pdReady {
throw("runtime: blocked write on closing polldesc")
}
- rg := atomic.Loaduintptr(&pd.rg)
+ rg := pd.rg.Load()
if rg != 0 && rg != pdReady {
throw("runtime: blocked read on closing polldesc")
}
@@ -209,9 +278,9 @@
return errcode
}
if mode == 'r' {
- atomic.Storeuintptr(&pd.rg, 0)
+ pd.rg.Store(0)
} else if mode == 'w' {
- atomic.Storeuintptr(&pd.wg, 0)
+ pd.wg.Store(0)
}
return pollNoError
}
@@ -273,6 +342,7 @@
if mode == 'w' || mode == 'r'+'w' {
pd.wd = d
}
+ pd.publishInfo()
combo := pd.rd > 0 && pd.rd == pd.wd
rtf := netpollReadDeadline
if combo {
@@ -314,15 +384,13 @@
}
}
// If we set the new deadline in the past, unblock currently pending IO if any.
+ // Note that pd.publishInfo has already been called, above, immediately after modifying rd and wd.
var rg, wg *g
- if pd.rd < 0 || pd.wd < 0 {
- atomic.StorepNoWB(noescape(unsafe.Pointer(&wg)), nil) // full memory barrier between stores to rd/wd and load of rg/wg in netpollunblock
- if pd.rd < 0 {
- rg = netpollunblock(pd, 'r', false)
- }
- if pd.wd < 0 {
- wg = netpollunblock(pd, 'w', false)
- }
+ if pd.rd < 0 {
+ rg = netpollunblock(pd, 'r', false)
+ }
+ if pd.wd < 0 {
+ wg = netpollunblock(pd, 'w', false)
}
unlock(&pd.lock)
if rg != nil {
@@ -343,7 +411,7 @@
pd.rseq++
pd.wseq++
var rg, wg *g
- atomic.StorepNoWB(noescape(unsafe.Pointer(&rg)), nil) // full memory barrier between store to closing and read of rg/wg in netpollunblock
+ pd.publishInfo()
rg = netpollunblock(pd, 'r', false)
wg = netpollunblock(pd, 'w', false)
if pd.rt.f != nil {
@@ -388,16 +456,17 @@
}
func netpollcheckerr(pd *pollDesc, mode int32) int {
- if pd.closing {
+ info := pd.info()
+ if info.closing() {
return pollErrClosing
}
- if (mode == 'r' && pd.rd < 0) || (mode == 'w' && pd.wd < 0) {
+ if (mode == 'r' && info.expiredReadDeadline()) || (mode == 'w' && info.expiredWriteDeadline()) {
return pollErrTimeout
}
// Report an event scanning error only on a read event.
// An error on a write event will be captured in a subsequent
// write call that is able to report a more specific error.
- if mode == 'r' && pd.everr {
+ if mode == 'r' && info.eventErr() {
return pollErrNotPollable
}
return pollNoError
@@ -432,28 +501,28 @@
// set the gpp semaphore to pdWait
for {
// Consume notification if already ready.
- if atomic.Casuintptr(gpp, pdReady, 0) {
+ if gpp.CompareAndSwap(pdReady, 0) {
return true
}
- if atomic.Casuintptr(gpp, 0, pdWait) {
+ if gpp.CompareAndSwap(0, pdWait) {
break
}
// Double check that this isn't corrupt; otherwise we'd loop
// forever.
- if v := atomic.Loaduintptr(gpp); v != pdReady && v != 0 {
+ if v := gpp.Load(); v != pdReady && v != 0 {
throw("runtime: double wait")
}
}
// need to recheck error states after setting gpp to pdWait
// this is necessary because runtime_pollUnblock/runtime_pollSetDeadline/deadlineimpl
- // do the opposite: store to closing/rd/wd, membarrier, load of rg/wg
+ // do the opposite: store to closing/rd/wd, publishInfo, load of rg/wg
if waitio || netpollcheckerr(pd, mode) == pollNoError {
gopark(netpollblockcommit, unsafe.Pointer(gpp), waitReasonIOWait, traceEvGoBlockNet, 5)
}
// be careful to not lose concurrent pdReady notification
- old := atomic.Xchguintptr(gpp, 0)
+ old := gpp.Swap(0)
if old > pdWait {
throw("runtime: corrupted polldesc")
}
@@ -467,7 +536,7 @@
}
for {
- old := atomic.Loaduintptr(gpp)
+ old := gpp.Load()
if old == pdReady {
return nil
}
@@ -480,7 +549,7 @@
if ioready {
new = pdReady
}
- if atomic.Casuintptr(gpp, old, new) {
+ if gpp.CompareAndSwap(old, new) {
if old == pdWait {
old = 0
}
@@ -508,7 +577,7 @@
throw("runtime: inconsistent read deadline")
}
pd.rd = -1
- atomic.StorepNoWB(unsafe.Pointer(&pd.rt.f), nil) // full memory barrier between store to rd and load of rg in netpollunblock
+ pd.publishInfo()
rg = netpollunblock(pd, 'r', false)
}
var wg *g
@@ -517,7 +586,7 @@
throw("runtime: inconsistent write deadline")
}
pd.wd = -1
- atomic.StorepNoWB(unsafe.Pointer(&pd.wt.f), nil) // full memory barrier between store to wd and load of wg in netpollunblock
+ pd.publishInfo()
wg = netpollunblock(pd, 'w', false)
}
unlock(&pd.lock)
diff --git a/src/runtime/netpoll_aix.go b/src/runtime/netpoll_aix.go
index 4590ed8..90950af 100644
--- a/src/runtime/netpoll_aix.go
+++ b/src/runtime/netpoll_aix.go
@@ -212,10 +212,7 @@
pfd.events &= ^_POLLOUT
}
if mode != 0 {
- pds[i].everr = false
- if pfd.revents == _POLLERR {
- pds[i].everr = true
- }
+ pds[i].setEventErr(pfd.revents == _POLLERR)
netpollready(&toRun, pds[i], mode)
n--
}
diff --git a/src/runtime/netpoll_epoll.go b/src/runtime/netpoll_epoll.go
index e0fb877..b7d6199 100644
--- a/src/runtime/netpoll_epoll.go
+++ b/src/runtime/netpoll_epoll.go
@@ -168,10 +168,7 @@
}
if mode != 0 {
pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
- pd.everr = false
- if ev.events == _EPOLLERR {
- pd.everr = true
- }
+ pd.setEventErr(ev.events == _EPOLLERR)
netpollready(&toRun, pd, mode)
}
}
diff --git a/src/runtime/netpoll_kqueue.go b/src/runtime/netpoll_kqueue.go
index 2f7f284..1694753 100644
--- a/src/runtime/netpoll_kqueue.go
+++ b/src/runtime/netpoll_kqueue.go
@@ -179,10 +179,7 @@
}
if mode != 0 {
pd := (*pollDesc)(unsafe.Pointer(ev.udata))
- pd.everr = false
- if ev.flags == _EV_ERROR {
- pd.everr = true
- }
+ pd.setEventErr(ev.flags == _EV_ERROR)
netpollready(&toRun, pd, mode)
}
}
diff --git a/src/runtime/netpoll_solaris.go b/src/runtime/netpoll_solaris.go
index d217d5b..6e545b3 100644
--- a/src/runtime/netpoll_solaris.go
+++ b/src/runtime/netpoll_solaris.go
@@ -158,7 +158,7 @@
// this call, port_getn will return one and only one event for that
// particular descriptor, so this function needs to be called again.
func netpollupdate(pd *pollDesc, set, clear uint32) {
- if pd.closing {
+ if pd.info().closing() {
return
}
diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go
index 2e94665..4aba0ff 100644
--- a/src/runtime/os3_solaris.go
+++ b/src/runtime/os3_solaris.go
@@ -634,3 +634,12 @@
}
}
}
+
+// sigPerThreadSyscall is only used on linux, so we assign a bogus signal
+// number.
+const sigPerThreadSyscall = 1 << 31
+
+//go:nosplit
+func runPerThreadSyscall() {
+ throw("runPerThreadSyscall only valid on linux")
+}
diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go
index aeff593..292ff94 100644
--- a/src/runtime/os_aix.go
+++ b/src/runtime/os_aix.go
@@ -373,3 +373,12 @@
flags := fcntl(fd, _F_GETFL, 0)
fcntl(fd, _F_SETFL, flags|_O_NONBLOCK)
}
+
+// sigPerThreadSyscall is only used on linux, so we assign a bogus signal
+// number.
+const sigPerThreadSyscall = 1 << 31
+
+//go:nosplit
+func runPerThreadSyscall() {
+ throw("runPerThreadSyscall only valid on linux")
+}
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
index 0f0eb6c..9065b76 100644
--- a/src/runtime/os_darwin.go
+++ b/src/runtime/os_darwin.go
@@ -459,3 +459,12 @@
func signalM(mp *m, sig int) {
pthread_kill(pthread(mp.procid), uint32(sig))
}
+
+// sigPerThreadSyscall is only used on linux, so we assign a bogus signal
+// number.
+const sigPerThreadSyscall = 1 << 31
+
+//go:nosplit
+func runPerThreadSyscall() {
+ throw("runPerThreadSyscall only valid on linux")
+}
diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go
index cba2e42..152d94c 100644
--- a/src/runtime/os_dragonfly.go
+++ b/src/runtime/os_dragonfly.go
@@ -324,3 +324,12 @@
func signalM(mp *m, sig int) {
lwp_kill(-1, int32(mp.procid), sig)
}
+
+// sigPerThreadSyscall is only used on linux, so we assign a bogus signal
+// number.
+const sigPerThreadSyscall = 1 << 31
+
+//go:nosplit
+func runPerThreadSyscall() {
+ throw("runPerThreadSyscall only valid on linux")
+}
diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go
index c63b0e3..d908a80 100644
--- a/src/runtime/os_freebsd.go
+++ b/src/runtime/os_freebsd.go
@@ -460,3 +460,12 @@
func signalM(mp *m, sig int) {
thr_kill(thread(mp.procid), sig)
}
+
+// sigPerThreadSyscall is only used on linux, so we assign a bogus signal
+// number.
+const sigPerThreadSyscall = 1 << 31
+
+//go:nosplit
+func runPerThreadSyscall() {
+ throw("runPerThreadSyscall only valid on linux")
+}
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
index 32a1e1b..eb8aa07 100644
--- a/src/runtime/os_linux.go
+++ b/src/runtime/os_linux.go
@@ -8,9 +8,15 @@
"internal/abi"
"internal/goarch"
"runtime/internal/atomic"
+ "runtime/internal/syscall"
"unsafe"
)
+// sigPerThreadSyscall is the same signal (SIGSETXID) used by glibc for
+// per-thread syscalls on Linux. We use it for the same purpose in non-cgo
+// binaries.
+const sigPerThreadSyscall = _SIGRTMIN + 1
+
type mOS struct {
// profileTimer holds the ID of the POSIX interval timer for profiling CPU
// usage on this thread.
@@ -21,6 +27,10 @@
// are in signal handling code, access to that field uses atomic operations.
profileTimer int32
profileTimerValid uint32
+
+ // needPerThreadSyscall indicates that a per-thread syscall is required
+ // for doAllThreadsSyscall.
+ needPerThreadSyscall atomic.Uint8
}
//go:noescape
@@ -664,3 +674,205 @@
mp.profileTimer = timerid
atomic.Store(&mp.profileTimerValid, 1)
}
+
+// perThreadSyscallArgs contains the system call number, arguments, and
+// expected return values for a system call to be executed on all threads.
+type perThreadSyscallArgs struct {
+ trap uintptr
+ a1 uintptr
+ a2 uintptr
+ a3 uintptr
+ a4 uintptr
+ a5 uintptr
+ a6 uintptr
+ r1 uintptr
+ r2 uintptr
+}
+
+// perThreadSyscall is the system call to execute for the ongoing
+// doAllThreadsSyscall.
+//
+// perThreadSyscall may only be written while mp.needPerThreadSyscall == 0 on
+// all Ms.
+var perThreadSyscall perThreadSyscallArgs
+
+// syscall_runtime_doAllThreadsSyscall and executes a specified system call on
+// all Ms.
+//
+// The system call is expected to succeed and return the same value on every
+// thread. If any threads do not match, the runtime throws.
+//
+//go:linkname syscall_runtime_doAllThreadsSyscall syscall.runtime_doAllThreadsSyscall
+//go:uintptrescapes
+func syscall_runtime_doAllThreadsSyscall(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ if iscgo {
+ // In cgo, we are not aware of threads created in C, so this approach will not work.
+ panic("doAllThreadsSyscall not supported with cgo enabled")
+ }
+
+ // STW to guarantee that user goroutines see an atomic change to thread
+ // state. Without STW, goroutines could migrate Ms while change is in
+ // progress and e.g., see state old -> new -> old -> new.
+ //
+ // N.B. Internally, this function does not depend on STW to
+ // successfully change every thread. It is only needed for user
+ // expectations, per above.
+ stopTheWorld("doAllThreadsSyscall")
+
+ // This function depends on several properties:
+ //
+ // 1. All OS threads that already exist are associated with an M in
+ // allm. i.e., we won't miss any pre-existing threads.
+ // 2. All Ms listed in allm will eventually have an OS thread exist.
+ // i.e., they will set procid and be able to receive signals.
+ // 3. OS threads created after we read allm will clone from a thread
+ // that has executed the system call. i.e., they inherit the
+ // modified state.
+ //
+ // We achieve these through different mechanisms:
+ //
+ // 1. Addition of new Ms to allm in allocm happens before clone of its
+ // OS thread later in newm.
+ // 2. newm does acquirem to avoid being preempted, ensuring that new Ms
+ // created in allocm will eventually reach OS thread clone later in
+ // newm.
+ // 3. We take allocmLock for write here to prevent allocation of new Ms
+ // while this function runs. Per (1), this prevents clone of OS
+ // threads that are not yet in allm.
+ allocmLock.lock()
+
+ // Disable preemption, preventing us from changing Ms, as we handle
+ // this M specially.
+ //
+ // N.B. STW and lock() above do this as well, this is added for extra
+ // clarity.
+ acquirem()
+
+ // N.B. allocmLock also prevents concurrent execution of this function,
+ // serializing use of perThreadSyscall, mp.needPerThreadSyscall, and
+ // ensuring all threads execute system calls from multiple calls in the
+ // same order.
+
+ r1, r2, errno := syscall.Syscall6(trap, a1, a2, a3, a4, a5, a6)
+ if GOARCH == "ppc64" || GOARCH == "ppc64le" {
+ // TODO(https://go.dev/issue/51192 ): ppc64 doesn't use r2.
+ r2 = 0
+ }
+ if errno != 0 {
+ releasem(getg().m)
+ allocmLock.unlock()
+ startTheWorld()
+ return r1, r2, errno
+ }
+
+ perThreadSyscall = perThreadSyscallArgs{
+ trap: trap,
+ a1: a1,
+ a2: a2,
+ a3: a3,
+ a4: a4,
+ a5: a5,
+ a6: a6,
+ r1: r1,
+ r2: r2,
+ }
+
+ // Wait for all threads to start.
+ //
+ // As described above, some Ms have been added to allm prior to
+ // allocmLock, but not yet completed OS clone and set procid.
+ //
+ // At minimum we must wait for a thread to set procid before we can
+ // send it a signal.
+ //
+ // We take this one step further and wait for all threads to start
+ // before sending any signals. This prevents system calls from getting
+ // applied twice: once in the parent and once in the child, like so:
+ //
+ // A B C
+ // add C to allm
+ // doAllThreadsSyscall
+ // allocmLock.lock()
+ // signal B
+ // <receive signal>
+ // execute syscall
+ // <signal return>
+ // clone C
+ // <thread start>
+ // set procid
+ // signal C
+ // <receive signal>
+ // execute syscall
+ // <signal return>
+ //
+ // In this case, thread C inherited the syscall-modified state from
+ // thread B and did not need to execute the syscall, but did anyway
+ // because doAllThreadsSyscall could not be sure whether it was
+ // required.
+ //
+ // Some system calls may not be idempotent, so we ensure each thread
+ // executes the system call exactly once.
+ for mp := allm; mp != nil; mp = mp.alllink {
+ for atomic.Load64(&mp.procid) == 0 {
+ // Thread is starting.
+ osyield()
+ }
+ }
+
+ // Signal every other thread, where they will execute perThreadSyscall
+ // from the signal handler.
+ gp := getg()
+ tid := gp.m.procid
+ for mp := allm; mp != nil; mp = mp.alllink {
+ if atomic.Load64(&mp.procid) == tid {
+ // Our thread already performed the syscall.
+ continue
+ }
+ mp.needPerThreadSyscall.Store(1)
+ signalM(mp, sigPerThreadSyscall)
+ }
+
+ // Wait for all threads to complete.
+ for mp := allm; mp != nil; mp = mp.alllink {
+ if mp.procid == tid {
+ continue
+ }
+ for mp.needPerThreadSyscall.Load() != 0 {
+ osyield()
+ }
+ }
+
+ perThreadSyscall = perThreadSyscallArgs{}
+
+ releasem(getg().m)
+ allocmLock.unlock()
+ startTheWorld()
+
+ return r1, r2, errno
+}
+
+// runPerThreadSyscall runs perThreadSyscall for this M if required.
+//
+// This function throws if the system call returns with anything other than the
+// expected values.
+//go:nosplit
+func runPerThreadSyscall() {
+ gp := getg()
+ if gp.m.needPerThreadSyscall.Load() == 0 {
+ return
+ }
+
+ args := perThreadSyscall
+ r1, r2, errno := syscall.Syscall6(args.trap, args.a1, args.a2, args.a3, args.a4, args.a5, args.a6)
+ if GOARCH == "ppc64" || GOARCH == "ppc64le" {
+ // TODO(https://go.dev/issue/51192 ): ppc64 doesn't use r2.
+ r2 = 0
+ }
+ if errno != 0 || r1 != args.r1 || r2 != args.r2 {
+ print("trap:", args.trap, ", a123456=[", args.a1, ",", args.a2, ",", args.a3, ",", args.a4, ",", args.a5, ",", args.a6, "]\n")
+ print("results: got {r1=", r1, ",r2=", r2, ",errno=", errno, "}, want {r1=", args.r1, ",r2=", args.r2, ",errno=0\n")
+ throw("AllThreadsSyscall6 results differ between threads; runtime corrupted")
+ }
+
+ gp.m.needPerThreadSyscall.Store(0)
+}
diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go
index cd9508c..c4e69fb 100644
--- a/src/runtime/os_netbsd.go
+++ b/src/runtime/os_netbsd.go
@@ -428,3 +428,12 @@
func signalM(mp *m, sig int) {
lwp_kill(int32(mp.procid), sig)
}
+
+// sigPerThreadSyscall is only used on linux, so we assign a bogus signal
+// number.
+const sigPerThreadSyscall = 1 << 31
+
+//go:nosplit
+func runPerThreadSyscall() {
+ throw("runPerThreadSyscall only valid on linux")
+}
diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go
index 2d0e71d..1a00b89 100644
--- a/src/runtime/os_openbsd.go
+++ b/src/runtime/os_openbsd.go
@@ -286,3 +286,12 @@
func signalM(mp *m, sig int) {
thrkill(int32(mp.procid), sig)
}
+
+// sigPerThreadSyscall is only used on linux, so we assign a bogus signal
+// number.
+const sigPerThreadSyscall = 1 << 31
+
+//go:nosplit
+func runPerThreadSyscall() {
+ throw("runPerThreadSyscall only valid on linux")
+}
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index d320463..322579c 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -79,10 +79,6 @@
return foo
}
-func cpuHog3(x int) int {
- return cpuHog0(x, 1e5)
-}
-
// Return a list of functions that we don't want to ever appear in CPU
// profiles. For gccgo, that list includes the sigprof handler itself.
func avoidFunctions() []string {
@@ -158,79 +154,81 @@
maxDiff = 0.40
}
- parallelism := runtime.GOMAXPROCS(0)
+ compare := func(a, b time.Duration, maxDiff float64) error {
+ if a <= 0 || b <= 0 {
+ return fmt.Errorf("Expected both time reports to be positive")
+ }
- // This test compares the process's total CPU time against the CPU
- // profiler's view of time spent in direct execution of user code.
- // Background work, especially from the garbage collector, adds noise to
- // that measurement. Disable automatic triggering of the GC, and then
- // request a complete GC cycle (up through sweep termination).
- defer debug.SetGCPercent(debug.SetGCPercent(-1))
- runtime.GC()
+ if a < b {
+ a, b = b, a
+ }
- var cpuTime1, cpuTimeN time.Duration
- matches := matchAndAvoidStacks(stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog3"}, avoidFunctions())
- p := testCPUProfile(t, matches, func(dur time.Duration) {
- cpuTime1 = diffCPUTime(t, func() {
- // Consume CPU in one goroutine
- cpuHogger(cpuHog1, &salt1, dur)
+ diff := float64(a-b) / float64(a)
+ if diff > maxDiff {
+ return fmt.Errorf("CPU usage reports are too different (limit -%.1f%%, got -%.1f%%)", maxDiff*100, diff*100)
+ }
+
+ return nil
+ }
+
+ for _, tc := range []struct {
+ name string
+ workers int
+ }{
+ {
+ name: "serial",
+ workers: 1,
+ },
+ {
+ name: "parallel",
+ workers: runtime.GOMAXPROCS(0),
+ },
+ } {
+ // check that the OS's perspective matches what the Go runtime measures.
+ t.Run(tc.name, func(t *testing.T) {
+ t.Logf("Running with %d workers", tc.workers)
+
+ var cpuTime time.Duration
+ matches := matchAndAvoidStacks(stackContains, []string{"runtime/pprof.cpuHog1"}, avoidFunctions())
+ p := testCPUProfile(t, matches, func(dur time.Duration) {
+ cpuTime = diffCPUTime(t, func() {
+ var wg sync.WaitGroup
+ var once sync.Once
+ for i := 0; i < tc.workers; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ var salt = 0
+ cpuHogger(cpuHog1, &salt, dur)
+ once.Do(func() { salt1 = salt })
+ }()
+ }
+ wg.Wait()
+ })
+ })
+
+ for i, unit := range []string{"count", "nanoseconds"} {
+ if have, want := p.SampleType[i].Unit, unit; have != want {
+ t.Errorf("pN SampleType[%d]; %q != %q", i, have, want)
+ }
+ }
+
+ // cpuHog1 called above is the primary source of CPU
+ // load, but there may be some background work by the
+ // runtime. Since the OS rusage measurement will
+ // include all work done by the process, also compare
+ // against all samples in our profile.
+ var value time.Duration
+ for _, sample := range p.Sample {
+ value += time.Duration(sample.Value[1]) * time.Nanosecond
+ }
+
+ t.Logf("compare %s vs %s", cpuTime, value)
+ if err := compare(cpuTime, value, maxDiff); err != nil {
+ t.Errorf("compare got %v want nil", err)
+ }
})
-
- cpuTimeN = diffCPUTime(t, func() {
- // Next, consume CPU in several goroutines
- var wg sync.WaitGroup
- var once sync.Once
- for i := 0; i < parallelism; i++ {
- wg.Add(1)
- go func() {
- defer wg.Done()
- var salt = 0
- cpuHogger(cpuHog3, &salt, dur)
- once.Do(func() { salt1 = salt })
- }()
- }
- wg.Wait()
- })
- })
-
- for i, unit := range []string{"count", "nanoseconds"} {
- if have, want := p.SampleType[i].Unit, unit; have != want {
- t.Errorf("pN SampleType[%d]; %q != %q", i, have, want)
- }
}
-
- var value1, valueN time.Duration
- for _, sample := range p.Sample {
- if stackContains("runtime/pprof.cpuHog1", uintptr(sample.Value[0]), sample.Location, sample.Label) {
- value1 += time.Duration(sample.Value[1]) * time.Nanosecond
- }
- if stackContains("runtime/pprof.cpuHog3", uintptr(sample.Value[0]), sample.Location, sample.Label) {
- valueN += time.Duration(sample.Value[1]) * time.Nanosecond
- }
- }
-
- compare := func(a, b time.Duration, maxDiff float64) func(*testing.T) {
- return func(t *testing.T) {
- t.Logf("compare %s vs %s", a, b)
- if a <= 0 || b <= 0 {
- t.Errorf("Expected both time reports to be positive")
- return
- }
-
- if a < b {
- a, b = b, a
- }
-
- diff := float64(a-b) / float64(a)
- if diff > maxDiff {
- t.Errorf("CPU usage reports are too different (limit -%.1f%%, got -%.1f%%)", maxDiff*100, diff*100)
- }
- }
- }
-
- // check that the OS's perspective matches what the Go runtime measures
- t.Run("serial execution OS vs pprof", compare(cpuTime1, value1, maxDiff))
- t.Run("parallel execution OS vs pprof", compare(cpuTimeN, valueN, maxDiff))
}
// containsInlinedCall reports whether the function body for the function f is
@@ -796,7 +794,7 @@
func TestBlockProfile(t *testing.T) {
type TestCase struct {
name string
- f func()
+ f func(*testing.T)
stk []string
re string
}
@@ -905,7 +903,7 @@
runtime.SetBlockProfileRate(1)
defer runtime.SetBlockProfileRate(0)
for _, test := range tests {
- test.f()
+ test.f(t)
}
t.Run("debug=1", func(t *testing.T) {
@@ -981,42 +979,73 @@
return false
}
-const blockDelay = 10 * time.Millisecond
+// awaitBlockedGoroutine spins on runtime.Gosched until a runtime stack dump
+// shows a goroutine in the given state with a stack frame in
+// runtime/pprof.<fName>.
+func awaitBlockedGoroutine(t *testing.T, state, fName string) {
+ re := fmt.Sprintf(`(?m)^goroutine \d+ \[%s\]:\n(?:.+\n\t.+\n)*runtime/pprof\.%s`, regexp.QuoteMeta(state), fName)
+ r := regexp.MustCompile(re)
-func blockChanRecv() {
+ if deadline, ok := t.Deadline(); ok {
+ if d := time.Until(deadline); d > 1*time.Second {
+ timer := time.AfterFunc(d-1*time.Second, func() {
+ debug.SetTraceback("all")
+ panic(fmt.Sprintf("timed out waiting for %#q", re))
+ })
+ defer timer.Stop()
+ }
+ }
+
+ buf := make([]byte, 64<<10)
+ for {
+ runtime.Gosched()
+ n := runtime.Stack(buf, true)
+ if n == len(buf) {
+ // Buffer wasn't large enough for a full goroutine dump.
+ // Resize it and try again.
+ buf = make([]byte, 2*len(buf))
+ continue
+ }
+ if r.Match(buf[:n]) {
+ return
+ }
+ }
+}
+
+func blockChanRecv(t *testing.T) {
c := make(chan bool)
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "chan receive", "blockChanRecv")
c <- true
}()
<-c
}
-func blockChanSend() {
+func blockChanSend(t *testing.T) {
c := make(chan bool)
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "chan send", "blockChanSend")
<-c
}()
c <- true
}
-func blockChanClose() {
+func blockChanClose(t *testing.T) {
c := make(chan bool)
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "chan receive", "blockChanClose")
close(c)
}()
<-c
}
-func blockSelectRecvAsync() {
+func blockSelectRecvAsync(t *testing.T) {
const numTries = 3
c := make(chan bool, 1)
c2 := make(chan bool, 1)
go func() {
for i := 0; i < numTries; i++ {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "select", "blockSelectRecvAsync")
c <- true
}
}()
@@ -1028,11 +1057,11 @@
}
}
-func blockSelectSendSync() {
+func blockSelectSendSync(t *testing.T) {
c := make(chan bool)
c2 := make(chan bool)
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "select", "blockSelectSendSync")
<-c
}()
select {
@@ -1041,11 +1070,11 @@
}
}
-func blockMutex() {
+func blockMutex(t *testing.T) {
var mu sync.Mutex
mu.Lock()
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "semacquire", "blockMutex")
mu.Unlock()
}()
// Note: Unlock releases mu before recording the mutex event,
@@ -1055,12 +1084,12 @@
mu.Lock()
}
-func blockCond() {
+func blockCond(t *testing.T) {
var mu sync.Mutex
c := sync.NewCond(&mu)
mu.Lock()
go func() {
- time.Sleep(blockDelay)
+ awaitBlockedGoroutine(t, "sync.Cond.Wait", "blockCond")
mu.Lock()
c.Signal()
mu.Unlock()
@@ -1146,7 +1175,7 @@
t.Fatalf("need MutexProfileRate 0, got %d", old)
}
- blockMutex()
+ blockMutex(t)
t.Run("debug=1", func(t *testing.T) {
var w bytes.Buffer
@@ -1432,47 +1461,89 @@
matches := matchAndAvoidStacks(stackContainsLabeled, []string{"runtime.systemstack;key=value"}, avoidFunctions())
p := testCPUProfile(t, matches, func(dur time.Duration) {
- Do(context.Background(), Labels("key", "value"), func(context.Context) {
- var wg sync.WaitGroup
- stop := make(chan struct{})
- for i := 0; i < runtime.GOMAXPROCS(0); i++ {
- wg.Add(1)
- go func() {
- defer wg.Done()
- labelHog(stop, gogc)
- }()
- }
-
- time.Sleep(dur)
- close(stop)
- wg.Wait()
+ Do(context.Background(), Labels("key", "value"), func(ctx context.Context) {
+ parallelLabelHog(ctx, dur, gogc)
})
})
- // labelHog should always be labeled.
+ // Two conditions to check:
+ // * labelHog should always be labeled.
+ // * The label should _only_ appear on labelHog and the Do call above.
for _, s := range p.Sample {
+ isLabeled := s.Label != nil && contains(s.Label["key"], "value")
+ var (
+ mayBeLabeled bool
+ mustBeLabeled bool
+ mustNotBeLabeled bool
+ )
for _, loc := range s.Location {
for _, l := range loc.Line {
- if l.Function.Name != "runtime/pprof.labelHog" {
- continue
+ switch l.Function.Name {
+ case "runtime/pprof.labelHog", "runtime/pprof.parallelLabelHog", "runtime/pprof.parallelLabelHog.func1":
+ mustBeLabeled = true
+ case "runtime/pprof.Do":
+ // Do sets the labels, so samples may
+ // or may not be labeled depending on
+ // which part of the function they are
+ // at.
+ mayBeLabeled = true
+ case "runtime.bgsweep", "runtime.bgscavenge", "runtime.forcegchelper", "runtime.gcBgMarkWorker", "runtime.runfinq", "runtime.sysmon":
+ // Runtime system goroutines or threads
+ // (such as those identified by
+ // runtime.isSystemGoroutine). These
+ // should never be labeled.
+ mustNotBeLabeled = true
+ case "gogo", "gosave_systemstack_switch", "racecall":
+ // These are context switch/race
+ // critical that we can't do a full
+ // traceback from. Typically this would
+ // be covered by the runtime check
+ // below, but these symbols don't have
+ // the package name.
+ mayBeLabeled = true
}
- if s.Label == nil {
- t.Errorf("labelHog sample labels got nil want key=value")
- continue
- }
- if !contains(s.Label["key"], "value") {
- t.Errorf("labelHog sample labels got %+v want contains key=value", s.Label)
- continue
+ if strings.HasPrefix(l.Function.Name, "runtime.") {
+ // There are many places in the runtime
+ // where we can't do a full traceback.
+ // Ideally we'd list them all, but
+ // barring that allow anything in the
+ // runtime, unless explicitly excluded
+ // above.
+ mayBeLabeled = true
}
}
}
+ if mustNotBeLabeled {
+ // If this must not be labeled, then mayBeLabeled hints
+ // are not relevant.
+ mayBeLabeled = false
+ }
+ if mustBeLabeled && !isLabeled {
+ var buf bytes.Buffer
+ fprintStack(&buf, s.Location)
+ t.Errorf("Sample labeled got false want true: %s", buf.String())
+ }
+ if mustNotBeLabeled && isLabeled {
+ var buf bytes.Buffer
+ fprintStack(&buf, s.Location)
+ t.Errorf("Sample labeled got true want false: %s", buf.String())
+ }
+ if isLabeled && !(mayBeLabeled || mustBeLabeled) {
+ var buf bytes.Buffer
+ fprintStack(&buf, s.Location)
+ t.Errorf("Sample labeled got true want false: %s", buf.String())
+ }
}
}
// labelHog is designed to burn CPU time in a way that a high number of CPU
// samples end up running on systemstack.
func labelHog(stop chan struct{}, gogc int) {
+ // Regression test for issue 50032. We must give GC an opportunity to
+ // be initially triggered by a labelled goroutine.
+ runtime.GC()
+
for i := 0; ; i++ {
select {
case <-stop:
@@ -1483,6 +1554,23 @@
}
}
+// parallelLabelHog runs GOMAXPROCS goroutines running labelHog.
+func parallelLabelHog(ctx context.Context, dur time.Duration, gogc int) {
+ var wg sync.WaitGroup
+ stop := make(chan struct{})
+ for i := 0; i < runtime.GOMAXPROCS(0); i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ labelHog(stop, gogc)
+ }()
+ }
+
+ time.Sleep(dur)
+ close(stop)
+ wg.Wait()
+}
+
// Check that there is no deadlock when the program receives SIGPROF while in
// 64bit atomics' critical section. Used to happen on mips{,le}. See #20146.
func TestAtomicLoadStore64(t *testing.T) {
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 7509f76..b997a46 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -167,10 +167,6 @@
mainStarted = true
if GOARCH != "wasm" { // no threads on wasm yet, so no sysmon
- // For runtime_syscall_doAllThreadsSyscall, we
- // register sysmon is not ready for the world to be
- // stopped.
- atomic.Store(&sched.sysmonStarting, 1)
systemstack(func() {
newm(sysmon, nil, -1)
})
@@ -187,7 +183,6 @@
if g.m != &m0 {
throw("runtime.main not on m0")
}
- m0.doesPark = true
// Record when the world started.
// Must be before doInit for tracing init.
@@ -802,8 +797,18 @@
mp.id = mReserveID()
}
- // cputicks is not very random in startup virtual machine
- mp.fastrand = uint64(int64Hash(uint64(mp.id), fastrandseed^uintptr(cputicks())))
+ lo := uint32(int64Hash(uint64(mp.id), fastrandseed))
+ hi := uint32(int64Hash(uint64(cputicks()), ^fastrandseed))
+ if lo|hi == 0 {
+ hi = 1
+ }
+ // Same behavior as for 1.17.
+ // TODO: Simplify ths.
+ if goarch.BigEndian {
+ mp.fastrand = uint64(lo)<<32 | uint64(hi)
+ } else {
+ mp.fastrand = uint64(hi)<<32 | uint64(lo)
+ }
mpreinit(mp)
if mp.gsignal != nil {
@@ -1437,22 +1442,12 @@
initsig(false)
}
-// mPark causes a thread to park itself - temporarily waking for
-// fixups but otherwise waiting to be fully woken. This is the
-// only way that m's should park themselves.
+// mPark causes a thread to park itself, returning once woken.
//go:nosplit
func mPark() {
- g := getg()
- for {
- notesleep(&g.m.park)
- // Note, because of signal handling by this parked m,
- // a preemptive mDoFixup() may actually occur via
- // mDoFixupAndOSYield(). (See golang.org/issue/44193)
- noteclear(&g.m.park)
- if !mDoFixup() {
- return
- }
- }
+ gp := getg()
+ notesleep(&gp.m.park)
+ noteclear(&gp.m.park)
}
// mexit tears down and exits the current thread.
@@ -1659,145 +1654,6 @@
releasem(mp)
}
-// syscall_runtime_doAllThreadsSyscall serializes Go execution and
-// executes a specified fn() call on all m's.
-//
-// The boolean argument to fn() indicates whether the function's
-// return value will be consulted or not. That is, fn(true) should
-// return true if fn() succeeds, and fn(true) should return false if
-// it failed. When fn(false) is called, its return status will be
-// ignored.
-//
-// syscall_runtime_doAllThreadsSyscall first invokes fn(true) on a
-// single, coordinating, m, and only if it returns true does it go on
-// to invoke fn(false) on all of the other m's known to the process.
-//
-//go:linkname syscall_runtime_doAllThreadsSyscall syscall.runtime_doAllThreadsSyscall
-func syscall_runtime_doAllThreadsSyscall(fn func(bool) bool) {
- if iscgo {
- panic("doAllThreadsSyscall not supported with cgo enabled")
- }
- if fn == nil {
- return
- }
- for atomic.Load(&sched.sysmonStarting) != 0 {
- osyield()
- }
-
- // We don't want this thread to handle signals for the
- // duration of this critical section. The underlying issue
- // being that this locked coordinating m is the one monitoring
- // for fn() execution by all the other m's of the runtime,
- // while no regular go code execution is permitted (the world
- // is stopped). If this present m were to get distracted to
- // run signal handling code, and find itself waiting for a
- // second thread to execute go code before being able to
- // return from that signal handling, a deadlock will result.
- // (See golang.org/issue/44193.)
- lockOSThread()
- var sigmask sigset
- sigsave(&sigmask)
- sigblock(false)
-
- stopTheWorldGC("doAllThreadsSyscall")
- if atomic.Load(&newmHandoff.haveTemplateThread) != 0 {
- // Ensure that there are no in-flight thread
- // creations: don't want to race with allm.
- lock(&newmHandoff.lock)
- for !newmHandoff.waiting {
- unlock(&newmHandoff.lock)
- osyield()
- lock(&newmHandoff.lock)
- }
- unlock(&newmHandoff.lock)
- }
- if netpollinited() {
- netpollBreak()
- }
- sigRecvPrepareForFixup()
- _g_ := getg()
- if raceenabled {
- // For m's running without racectx, we loan out the
- // racectx of this call.
- lock(&mFixupRace.lock)
- mFixupRace.ctx = _g_.racectx
- unlock(&mFixupRace.lock)
- }
- if ok := fn(true); ok {
- tid := _g_.m.procid
- for mp := allm; mp != nil; mp = mp.alllink {
- if mp.procid == tid {
- // This m has already completed fn()
- // call.
- continue
- }
- // Be wary of mp's without procid values if
- // they are known not to park. If they are
- // marked as parking with a zero procid, then
- // they will be racing with this code to be
- // allocated a procid and we will annotate
- // them with the need to execute the fn when
- // they acquire a procid to run it.
- if mp.procid == 0 && !mp.doesPark {
- // Reaching here, we are either
- // running Windows, or cgo linked
- // code. Neither of which are
- // currently supported by this API.
- throw("unsupported runtime environment")
- }
- // stopTheWorldGC() doesn't guarantee stopping
- // all the threads, so we lock here to avoid
- // the possibility of racing with mp.
- lock(&mp.mFixup.lock)
- mp.mFixup.fn = fn
- atomic.Store(&mp.mFixup.used, 1)
- if mp.doesPark {
- // For non-service threads this will
- // cause the wakeup to be short lived
- // (once the mutex is unlocked). The
- // next real wakeup will occur after
- // startTheWorldGC() is called.
- notewakeup(&mp.park)
- }
- unlock(&mp.mFixup.lock)
- }
- for {
- done := true
- for mp := allm; done && mp != nil; mp = mp.alllink {
- if mp.procid == tid {
- continue
- }
- done = atomic.Load(&mp.mFixup.used) == 0
- }
- if done {
- break
- }
- // if needed force sysmon and/or newmHandoff to wakeup.
- lock(&sched.lock)
- if atomic.Load(&sched.sysmonwait) != 0 {
- atomic.Store(&sched.sysmonwait, 0)
- notewakeup(&sched.sysmonnote)
- }
- unlock(&sched.lock)
- lock(&newmHandoff.lock)
- if newmHandoff.waiting {
- newmHandoff.waiting = false
- notewakeup(&newmHandoff.wake)
- }
- unlock(&newmHandoff.lock)
- osyield()
- }
- }
- if raceenabled {
- lock(&mFixupRace.lock)
- mFixupRace.ctx = 0
- unlock(&mFixupRace.lock)
- }
- startTheWorldGC()
- msigrestore(sigmask)
- unlockOSThread()
-}
-
// runSafePointFn runs the safe point function, if any, for this P.
// This should be called like
//
@@ -1847,8 +1703,14 @@
//
//go:yeswritebarrierrec
func allocm(_p_ *p, fn func(), id int64) *m {
+ allocmLock.rlock()
+
+ // The caller owns _p_, but we may borrow (i.e., acquirep) it. We must
+ // disable preemption to ensure it is not stolen, which would make the
+ // caller lose ownership.
+ acquirem()
+
_g_ := getg()
- acquirem() // disable GC because it can be called from sysmon
if _g_.m.p == 0 {
acquirep(_p_) // temporarily borrow p for mallocs in this function
}
@@ -1894,8 +1756,9 @@
if _p_ == _g_.m.p.ptr() {
releasep()
}
- releasem(_g_.m)
+ releasem(_g_.m)
+ allocmLock.runlock()
return mp
}
@@ -2172,9 +2035,17 @@
atomic.Storeuintptr(&extram, uintptr(unsafe.Pointer(mp)))
}
-// execLock serializes exec and clone to avoid bugs or unspecified behaviour
-// around exec'ing while creating/destroying threads. See issue #19546.
-var execLock rwmutex
+var (
+ // allocmLock is locked for read when creating new Ms in allocm and their
+ // addition to allm. Thus acquiring this lock for write blocks the
+ // creation of new Ms.
+ allocmLock rwmutex
+
+ // execLock serializes exec and clone to avoid bugs or unspecified
+ // behaviour around exec'ing while creating/destroying threads. See
+ // issue #19546.
+ execLock rwmutex
+)
// newmHandoff contains a list of m structures that need new OS threads.
// This is used by newm in situations where newm itself can't safely
@@ -2204,8 +2075,19 @@
// id is optional pre-allocated m ID. Omit by passing -1.
//go:nowritebarrierrec
func newm(fn func(), _p_ *p, id int64) {
+ // allocm adds a new M to allm, but they do not start until created by
+ // the OS in newm1 or the template thread.
+ //
+ // doAllThreadsSyscall requires that every M in allm will eventually
+ // start and be signal-able, even with a STW.
+ //
+ // Disable preemption here until we start the thread to ensure that
+ // newm is not preempted between allocm and starting the new thread,
+ // ensuring that anything added to allm is guaranteed to eventually
+ // start.
+ acquirem()
+
mp := allocm(_p_, fn, id)
- mp.doesPark = (_p_ != nil)
mp.nextp.set(_p_)
mp.sigmask = initSigmask
if gp := getg(); gp != nil && gp.m != nil && (gp.m.lockedExt != 0 || gp.m.incgo) && GOOS != "plan9" {
@@ -2231,9 +2113,14 @@
notewakeup(&newmHandoff.wake)
}
unlock(&newmHandoff.lock)
+ // The M has not started yet, but the template thread does not
+ // participate in STW, so it will always process queued Ms and
+ // it is safe to releasem.
+ releasem(getg().m)
return
}
newm1(mp)
+ releasem(getg().m)
}
func newm1(mp *m) {
@@ -2281,81 +2168,6 @@
releasem(mp)
}
-// mFixupRace is used to temporarily borrow the race context from the
-// coordinating m during a syscall_runtime_doAllThreadsSyscall and
-// loan it out to each of the m's of the runtime so they can execute a
-// mFixup.fn in that context.
-var mFixupRace struct {
- lock mutex
- ctx uintptr
-}
-
-// mDoFixup runs any outstanding fixup function for the running m.
-// Returns true if a fixup was outstanding and actually executed.
-//
-// Note: to avoid deadlocks, and the need for the fixup function
-// itself to be async safe, signals are blocked for the working m
-// while it holds the mFixup lock. (See golang.org/issue/44193)
-//
-//go:nosplit
-func mDoFixup() bool {
- _g_ := getg()
- if used := atomic.Load(&_g_.m.mFixup.used); used == 0 {
- return false
- }
-
- // slow path - if fixup fn is used, block signals and lock.
- var sigmask sigset
- sigsave(&sigmask)
- sigblock(false)
- lock(&_g_.m.mFixup.lock)
- fn := _g_.m.mFixup.fn
- if fn != nil {
- if gcphase != _GCoff {
- // We can't have a write barrier in this
- // context since we may not have a P, but we
- // clear fn to signal that we've executed the
- // fixup. As long as fn is kept alive
- // elsewhere, technically we should have no
- // issues with the GC, but fn is likely
- // generated in a different package altogether
- // that may change independently. Just assert
- // the GC is off so this lack of write barrier
- // is more obviously safe.
- throw("GC must be disabled to protect validity of fn value")
- }
- if _g_.racectx != 0 || !raceenabled {
- fn(false)
- } else {
- // temporarily acquire the context of the
- // originator of the
- // syscall_runtime_doAllThreadsSyscall and
- // block others from using it for the duration
- // of the fixup call.
- lock(&mFixupRace.lock)
- _g_.racectx = mFixupRace.ctx
- fn(false)
- _g_.racectx = 0
- unlock(&mFixupRace.lock)
- }
- *(*uintptr)(unsafe.Pointer(&_g_.m.mFixup.fn)) = 0
- atomic.Store(&_g_.m.mFixup.used, 0)
- }
- unlock(&_g_.m.mFixup.lock)
- msigrestore(sigmask)
- return fn != nil
-}
-
-// mDoFixupAndOSYield is called when an m is unable to send a signal
-// because the allThreadsSyscall mechanism is in progress. That is, an
-// mPark() has been interrupted with this signal handler so we need to
-// ensure the fixup is executed from this context.
-//go:nosplit
-func mDoFixupAndOSYield() {
- mDoFixup()
- osyield()
-}
-
// templateThread is a thread in a known-good state that exists solely
// to start new threads in known-good states when the calling thread
// may not be in a good state.
@@ -2392,7 +2204,6 @@
noteclear(&newmHandoff.wake)
unlock(&newmHandoff.lock)
notesleep(&newmHandoff.wake)
- mDoFixup()
}
}
@@ -4300,11 +4111,13 @@
newg.gopc = callerpc
newg.ancestors = saveAncestors(callergp)
newg.startpc = fn.fn
- if _g_.m.curg != nil {
- newg.labels = _g_.m.curg.labels
- }
if isSystemGoroutine(newg, false) {
atomic.Xadd(&sched.ngsys, +1)
+ } else {
+ // Only user goroutines inherit pprof labels.
+ if _g_.m.curg != nil {
+ newg.labels = _g_.m.curg.labels
+ }
}
// Track initial transition?
newg.trackingSeq = uint8(fastrand())
@@ -4669,7 +4482,6 @@
getg().m.mallocing++
var stk [maxCPUProfStack]uintptr
- flags := uint(_TraceJumpStack)
n := 0
if mp.ncgo > 0 && mp.curg != nil && mp.curg.syscallpc != 0 && mp.curg.syscallsp != 0 {
cgoOff := 0
@@ -4687,12 +4499,12 @@
}
// Collect Go stack that leads to the cgo call.
- n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[cgoOff], len(stk)-cgoOff, nil, nil, flags)
+ n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[cgoOff], len(stk)-cgoOff, nil, nil, 0)
if n > 0 {
n += cgoOff
}
} else {
- n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|flags)
+ n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|_TraceJumpStack)
}
if n <= 0 {
@@ -4702,10 +4514,10 @@
if usesLibcall() && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 {
// Libcall, i.e. runtime syscall on windows.
// Collect Go stack that leads to the call.
- n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, flags)
+ n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, 0)
}
if n == 0 && mp != nil && mp.vdsoSP != 0 {
- n = gentraceback(mp.vdsoPC, mp.vdsoSP, 0, gp, 0, &stk[0], len(stk), nil, nil, flags)
+ n = gentraceback(mp.vdsoPC, mp.vdsoSP, 0, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|_TraceJumpStack)
}
if n == 0 {
// If all of the above has failed, account it against abstract "System" or "GC".
@@ -5238,10 +5050,6 @@
checkdead()
unlock(&sched.lock)
- // For syscall_runtime_doAllThreadsSyscall, sysmon is
- // sufficiently up to participate in fixups.
- atomic.Store(&sched.sysmonStarting, 0)
-
lasttrace := int64(0)
idle := 0 // how many cycles in succession we had not wokeup somebody
delay := uint32(0)
@@ -5256,7 +5064,6 @@
delay = 10 * 1000
}
usleep(delay)
- mDoFixup()
// sysmon should not enter deep sleep if schedtrace is enabled so that
// it can print that information at the right time.
@@ -5293,7 +5100,6 @@
osRelax(true)
}
syscallWake = notetsleep(&sched.sysmonnote, sleep)
- mDoFixup()
if shouldRelax {
osRelax(false)
}
@@ -5336,7 +5142,6 @@
incidlelocked(1)
}
}
- mDoFixup()
if GOOS == "netbsd" && needSysmonWorkaround {
// netpoll is responsible for waiting for timer
// expiration, so we typically don't have to worry
diff --git a/src/runtime/proc_test.go b/src/runtime/proc_test.go
index cc899a2..719d0d1 100644
--- a/src/runtime/proc_test.go
+++ b/src/runtime/proc_test.go
@@ -1044,7 +1044,7 @@
interations = 1
}
const (
- maxDuration = 3 * time.Second
+ maxDuration = 5 * time.Second
nroutines = 8
)
@@ -1080,6 +1080,10 @@
}
func TestPreemptionAfterSyscall(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ testenv.SkipFlaky(t, 41015)
+ }
+
for _, i := range []time.Duration{10, 100, 1000} {
d := i * time.Microsecond
t.Run(fmt.Sprint(d), func(t *testing.T) {
diff --git a/src/runtime/race/output_test.go b/src/runtime/race/output_test.go
index 46cdfcd..0dcdabe 100644
--- a/src/runtime/race/output_test.go
+++ b/src/runtime/race/output_test.go
@@ -207,7 +207,7 @@
}
`, []string{`
==================
---- FAIL: TestFail \(0...s\)
+--- FAIL: TestFail \([0-9.]+s\)
.*main_test.go:14: true
.*testing.go:.*: race detected during execution of test
FAIL`}},
@@ -363,7 +363,7 @@
}
`, []string{`
==================
---- FAIL: TestFail \(0...s\)
+--- FAIL: TestFail \([0-9.]+s\)
.*testing.go:.*: race detected during execution of test
FAIL`}},
{"mutex", "run", "", "atexit_sleep_ms=0", `
diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s
index 798e232..95fec0b 100644
--- a/src/runtime/race_arm64.s
+++ b/src/runtime/race_arm64.s
@@ -188,8 +188,12 @@
// func runtime·racefuncenter(pc uintptr)
// Called from instrumented code.
-TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8
+TEXT runtime·racefuncenter<ABIInternal>(SB), NOSPLIT, $0-8
+#ifdef GOEXPERIMENT_regabiargs
+ MOVD R0, R9 // callpc
+#else
MOVD callpc+0(FP), R9
+#endif
JMP racefuncenter<>(SB)
// Common code for racefuncenter
@@ -205,7 +209,7 @@
// func runtime·racefuncexit()
// Called from instrumented code.
-TEXT runtime·racefuncexit(SB), NOSPLIT, $0-0
+TEXT runtime·racefuncexit<ABIInternal>(SB), NOSPLIT, $0-0
load_g
MOVD g_racectx(g), R0 // race context
// void __tsan_func_exit(ThreadState *thr);
@@ -392,12 +396,12 @@
// Addr is outside the good range.
// Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
// An attempt to synchronize on the address would cause crash.
- MOVD R9, R20 // remember the original function
+ MOVD R9, R21 // remember the original function
MOVD $__tsan_go_ignore_sync_begin(SB), R9
load_g
MOVD g_racectx(g), R0 // goroutine context
BL racecall<>(SB)
- MOVD R20, R9 // restore the original function
+ MOVD R21, R9 // restore the original function
// Call the atomic function.
// racecall will call LLVM race code which might clobber R28 (g)
load_g
@@ -424,10 +428,12 @@
JMP racecall<>(SB)
// Switches SP to g0 stack and calls (R9). Arguments already set.
-TEXT racecall<>(SB), NOSPLIT, $0-0
+// Clobbers R19, R20.
+TEXT racecall<>(SB), NOSPLIT|NOFRAME, $0-0
MOVD g_m(g), R10
// Switch to g0 stack.
MOVD RSP, R19 // callee-saved, preserved across the CALL
+ MOVD R30, R20 // callee-saved, preserved across the CALL
MOVD m_g0(R10), R11
CMP R11, g
BEQ call // already on g0
@@ -436,7 +442,7 @@
call:
BL R9
MOVD R19, RSP
- RET
+ JMP (R20)
// C->Go callback thunk that allows to call runtime·racesymbolize from C code.
// Direct Go->C race call has only switched SP, finish g->g0 switch by setting correct g.
diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go
index 63d3160..ee8c6c2 100644
--- a/src/runtime/runtime-gdb_test.go
+++ b/src/runtime/runtime-gdb_test.go
@@ -153,8 +153,8 @@
}
func TestGdbPythonCgo(t *testing.T) {
- if runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" || runtime.GOARCH == "mips64" {
- testenv.SkipFlaky(t, 18784)
+ if strings.HasPrefix(runtime.GOARCH, "mips") {
+ testenv.SkipFlaky(t, 37794)
}
testGdbPython(t, true)
}
@@ -427,6 +427,14 @@
got, err := testenv.RunWithTimeout(t, exec.Command("gdb", args...))
t.Logf("gdb output:\n%s", got)
if err != nil {
+ if bytes.Contains(got, []byte("internal-error: wait returned unexpected status 0x0")) {
+ // GDB bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28551
+ testenv.SkipFlaky(t, 43068)
+ }
+ if bytes.Contains(got, []byte("Couldn't get registers: No such process.")) {
+ // GDB bug: https://sourceware.org/bugzilla/show_bug.cgi?id=9086
+ testenv.SkipFlaky(t, 50838)
+ }
t.Fatalf("gdb exited with error: %v", err)
}
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index ec34e7a..3d01ac5 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -255,6 +255,8 @@
// so I can't see them ever moving. If we did want to start moving data
// in the GC, we'd need to allocate the goroutine structs from an
// alternate arena. Using guintptr doesn't make that problem any worse.
+// Note that pollDesc.rg, pollDesc.wg also store g in uintptr form,
+// so they would need to be updated too if g's start moving.
type guintptr uintptr
//go:nosplit
@@ -545,7 +547,6 @@
ncgo int32 // number of cgo calls currently in progress
cgoCallersUse uint32 // if non-zero, cgoCallers in use temporarily
cgoCallers *cgoCallers // cgo traceback if crashing in cgo call
- doesPark bool // non-P running threads: sysmon and newmHandoff never use .park
park note
alllink *m // on allm
schedlink muintptr
@@ -562,16 +563,6 @@
syscalltick uint32
freelink *m // on sched.freem
- // mFixup is used to synchronize OS related m state
- // (credentials etc) use mutex to access. To avoid deadlocks
- // an atomic.Load() of used being zero in mDoFixupFn()
- // guarantees fn is nil.
- mFixup struct {
- lock mutex
- used uint32
- fn func(bool) bool
- }
-
// these are here because they are too large to be on the stack
// of low-level NOSPLIT functions.
libcall libcall
@@ -815,10 +806,6 @@
sysmonwait uint32
sysmonnote note
- // While true, sysmon not ready for mFixup calls.
- // Accessed atomically.
- sysmonStarting uint32
-
// safepointFn should be called on each P at the next GC
// safepoint if p.runSafePointFn is set.
safePointFn func(*p)
@@ -836,8 +823,6 @@
// with the rest of the runtime.
sysmonlock mutex
- _ uint32 // ensure timeToRun has 8-byte alignment
-
// timeToRun is a distribution of scheduling latencies, defined
// as the sum of time a G spends in the _Grunnable state before
// it transitions to _Grunning.
@@ -854,7 +839,7 @@
_SigPanic // if the signal is from the kernel, panic
_SigDefault // if the signal isn't explicitly requested, don't monitor it
_SigGoExit // cause all runtime procs to exit (only used on Plan 9).
- _SigSetStack // add SA_ONSTACK to libc handler
+ _SigSetStack // Don't explicitly install handler, but add SA_ONSTACK to existing libc handler
_SigUnblock // always unblock; see blockableSig
_SigIgn // _SIG_DFL action is to ignore the signal
)
@@ -939,7 +924,7 @@
}
// A _defer holds an entry on the list of deferred calls.
-// If you add a field here, add code to clear it in freedefer and deferProcStack
+// If you add a field here, add code to clear it in deferProcStack.
// This struct must match the code in cmd/compile/internal/ssagen/ssa.go:deferstruct
// and cmd/compile/internal/ssagen/ssa.go:(*state).call.
// Some defers will be allocated on the stack and some on the heap.
diff --git a/src/runtime/runtime_test.go b/src/runtime/runtime_test.go
index 1ca1fa2..12f261b 100644
--- a/src/runtime/runtime_test.go
+++ b/src/runtime/runtime_test.go
@@ -6,6 +6,7 @@
import (
"flag"
+ "fmt"
"io"
. "runtime"
"runtime/debug"
@@ -362,3 +363,78 @@
t.Fatalf("cr/nl in version: %q", vers)
}
}
+
+func TestTimediv(t *testing.T) {
+ for _, tc := range []struct {
+ num int64
+ div int32
+ ret int32
+ rem int32
+ }{
+ {
+ num: 8,
+ div: 2,
+ ret: 4,
+ rem: 0,
+ },
+ {
+ num: 9,
+ div: 2,
+ ret: 4,
+ rem: 1,
+ },
+ {
+ // Used by runtime.check.
+ num: 12345*1000000000 + 54321,
+ div: 1000000000,
+ ret: 12345,
+ rem: 54321,
+ },
+ {
+ num: 1<<32 - 1,
+ div: 2,
+ ret: 1<<31 - 1, // no overflow.
+ rem: 1,
+ },
+ {
+ num: 1 << 32,
+ div: 2,
+ ret: 1<<31 - 1, // overflow.
+ rem: 0,
+ },
+ {
+ num: 1 << 40,
+ div: 2,
+ ret: 1<<31 - 1, // overflow.
+ rem: 0,
+ },
+ {
+ num: 1<<40 + 1,
+ div: 1 << 10,
+ ret: 1 << 30,
+ rem: 1,
+ },
+ } {
+ name := fmt.Sprintf("%d div %d", tc.num, tc.div)
+ t.Run(name, func(t *testing.T) {
+ // Double check that the inputs make sense using
+ // standard 64-bit division.
+ ret64 := tc.num / int64(tc.div)
+ rem64 := tc.num % int64(tc.div)
+ if ret64 != int64(int32(ret64)) {
+ // Simulate timediv overflow value.
+ ret64 = 1<<31 - 1
+ rem64 = 0
+ }
+ if ret64 != int64(tc.ret) {
+ t.Errorf("%d / %d got ret %d rem %d want ret %d rem %d", tc.num, tc.div, ret64, rem64, tc.ret, tc.rem)
+ }
+
+ var rem int32
+ ret := Timediv(tc.num, tc.div, &rem)
+ if ret != tc.ret || rem != tc.rem {
+ t.Errorf("timediv %d / %d got ret %d rem %d want ret %d rem %d", tc.num, tc.div, ret, rem, tc.ret, tc.rem)
+ }
+ })
+ }
+}
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index dbcbfc6..2dd4cc5 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -161,6 +161,13 @@
}
}
+ if (GOOS == "linux" || GOOS == "android") && !iscgo && sig == sigPerThreadSyscall {
+ // sigPerThreadSyscall is the same signal used by glibc for
+ // per-thread syscalls on Linux. We use it for the same purpose
+ // in non-cgo binaries.
+ return true
+ }
+
t := &sigtable[sig]
if t.flags&_SigSetStack != 0 {
return false
@@ -271,7 +278,24 @@
if hz != 0 {
// Enable the Go signal handler if not enabled.
if atomic.Cas(&handlingSig[_SIGPROF], 0, 1) {
- atomic.Storeuintptr(&fwdSig[_SIGPROF], getsig(_SIGPROF))
+ h := getsig(_SIGPROF)
+ // If no signal handler was installed before, then we record
+ // _SIG_IGN here. When we turn off profiling (below) we'll start
+ // ignoring SIGPROF signals. We do this, rather than change
+ // to SIG_DFL, because there may be a pending SIGPROF
+ // signal that has not yet been delivered to some other thread.
+ // If we change to SIG_DFL when turning off profiling, the
+ // program will crash when that SIGPROF is delivered. We assume
+ // that programs that use profiling don't want to crash on a
+ // stray SIGPROF. See issue 19320.
+ // We do the change here instead of when turning off profiling,
+ // because there we may race with a signal handler running
+ // concurrently, in particular, sigfwdgo may observe _SIG_DFL and
+ // die. See issue 43828.
+ if h == _SIG_DFL {
+ h = _SIG_IGN
+ }
+ atomic.Storeuintptr(&fwdSig[_SIGPROF], h)
setsig(_SIGPROF, abi.FuncPCABIInternal(sighandler))
}
@@ -288,21 +312,9 @@
// when we enabled profiling. We don't try to handle the case
// of a program that changes the SIGPROF handler while Go
// profiling is enabled.
- //
- // If no signal handler was installed before, then start
- // ignoring SIGPROF signals. We do this, rather than change
- // to SIG_DFL, because there may be a pending SIGPROF
- // signal that has not yet been delivered to some other thread.
- // If we change to SIG_DFL here, the program will crash
- // when that SIGPROF is delivered. We assume that programs
- // that use profiling don't want to crash on a stray SIGPROF.
- // See issue 19320.
if !sigInstallGoHandler(_SIGPROF) {
if atomic.Cas(&handlingSig[_SIGPROF], 1, 0) {
h := atomic.Loaduintptr(&fwdSig[_SIGPROF])
- if h == _SIG_DFL {
- h = _SIG_IGN
- }
setsig(_SIGPROF, h)
}
}
@@ -611,6 +623,15 @@
return
}
+ if (GOOS == "linux" || GOOS == "android") && sig == sigPerThreadSyscall {
+ // sigPerThreadSyscall is the same signal used by glibc for
+ // per-thread syscalls on Linux. We use it for the same purpose
+ // in non-cgo binaries. Since this signal is not _SigNotify,
+ // there is nothing more to do once we run the syscall.
+ runPerThreadSyscall()
+ return
+ }
+
if sig == sigPreempt && debug.asyncpreemptoff == 0 {
// Might be a preemption signal.
doSigPreempt(gp, c)
diff --git a/src/runtime/sigqueue.go b/src/runtime/sigqueue.go
index 7b84a0e..fdf99d9 100644
--- a/src/runtime/sigqueue.go
+++ b/src/runtime/sigqueue.go
@@ -11,18 +11,18 @@
//
// sigsend is called by the signal handler to queue a new signal.
// signal_recv is called by the Go program to receive a newly queued signal.
+//
// Synchronization between sigsend and signal_recv is based on the sig.state
-// variable. It can be in 4 states: sigIdle, sigReceiving, sigSending and sigFixup.
-// sigReceiving means that signal_recv is blocked on sig.Note and there are no
-// new pending signals.
-// sigSending means that sig.mask *may* contain new pending signals,
-// signal_recv can't be blocked in this state.
-// sigIdle means that there are no new pending signals and signal_recv is not blocked.
-// sigFixup is a transient state that can only exist as a short
-// transition from sigReceiving and then on to sigIdle: it is
-// used to ensure the AllThreadsSyscall()'s mDoFixup() operation
-// occurs on the sleeping m, waiting to receive a signal.
+// variable. It can be in three states:
+// * sigReceiving means that signal_recv is blocked on sig.Note and there are
+// no new pending signals.
+// * sigSending means that sig.mask *may* contain new pending signals,
+// signal_recv can't be blocked in this state.
+// * sigIdle means that there are no new pending signals and signal_recv is not
+// blocked.
+//
// Transitions between states are done atomically with CAS.
+//
// When signal_recv is unblocked, it resets sig.Note and rechecks sig.mask.
// If several sigsends and signal_recv execute concurrently, it can lead to
// unnecessary rechecks of sig.mask, but it cannot lead to missed signals
@@ -63,7 +63,6 @@
sigIdle = iota
sigReceiving
sigSending
- sigFixup
)
// sigsend delivers a signal from sighandler to the internal signal delivery queue.
@@ -117,9 +116,6 @@
notewakeup(&sig.note)
break Send
}
- case sigFixup:
- // nothing to do - we need to wait for sigIdle.
- mDoFixupAndOSYield()
}
}
@@ -127,19 +123,6 @@
return true
}
-// sigRecvPrepareForFixup is used to temporarily wake up the
-// signal_recv() running thread while it is blocked waiting for the
-// arrival of a signal. If it causes the thread to wake up, the
-// sig.state travels through this sequence: sigReceiving -> sigFixup
-// -> sigIdle -> sigReceiving and resumes. (This is only called while
-// GC is disabled.)
-//go:nosplit
-func sigRecvPrepareForFixup() {
- if atomic.Cas(&sig.state, sigReceiving, sigFixup) {
- notewakeup(&sig.note)
- }
-}
-
// Called to receive the next queued signal.
// Must only be called from a single goroutine at a time.
//go:linkname signal_recv os/signal.signal_recv
@@ -167,16 +150,7 @@
}
notetsleepg(&sig.note, -1)
noteclear(&sig.note)
- if !atomic.Cas(&sig.state, sigFixup, sigIdle) {
- break Receive
- }
- // Getting here, the code will
- // loop around again to sleep
- // in state sigReceiving. This
- // path is taken when
- // sigRecvPrepareForFixup()
- // has been called by another
- // thread.
+ break Receive
}
case sigSending:
if atomic.Cas(&sig.state, sigSending, sigIdle) {
diff --git a/src/runtime/sigqueue_plan9.go b/src/runtime/sigqueue_plan9.go
index aebd206..d5fe8f8 100644
--- a/src/runtime/sigqueue_plan9.go
+++ b/src/runtime/sigqueue_plan9.go
@@ -92,13 +92,6 @@
return true
}
-// sigRecvPrepareForFixup is a no-op on plan9. (This would only be
-// called while GC is disabled.)
-//
-//go:nosplit
-func sigRecvPrepareForFixup() {
-}
-
// Called to receive the next queued signal.
// Must only be called from a single goroutine at a time.
//go:linkname signal_recv os/signal.signal_recv
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index ac0b7d5..e0aeba6 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -214,7 +214,7 @@
var lenmem, newlenmem, capmem uintptr
// Specialize for common values of et.size.
// For 1 we don't need any division/multiplication.
- // For sys.PtrSize, compiler will optimize division/multiplication into a shift by a constant.
+ // For goarch.PtrSize, compiler will optimize division/multiplication into a shift by a constant.
// For powers of 2, use a variable shift.
switch {
case et.size == 1:
diff --git a/src/runtime/stack_test.go b/src/runtime/stack_test.go
index 4c2671b..1a59086 100644
--- a/src/runtime/stack_test.go
+++ b/src/runtime/stack_test.go
@@ -7,11 +7,9 @@
import (
"bytes"
"fmt"
- "os"
"reflect"
"regexp"
. "runtime"
- "strconv"
"strings"
"sync"
"sync/atomic"
@@ -83,12 +81,7 @@
t.Skip("-quick")
}
- if GOARCH == "wasm" {
- t.Skip("fails on wasm (too slow?)")
- }
-
- // Don't make this test parallel as this makes the 20 second
- // timeout unreliable on slow builders. (See issue #19381.)
+ t.Parallel()
var wg sync.WaitGroup
@@ -102,6 +95,7 @@
growDuration = time.Since(start)
}()
wg.Wait()
+ t.Log("first growStack took", growDuration)
// in locked goroutine
wg.Add(1)
@@ -114,48 +108,38 @@
wg.Wait()
// in finalizer
+ var finalizerStart time.Time
+ var started, progress uint32
wg.Add(1)
- go func() {
+ s := new(string) // Must be of a type that avoids the tiny allocator, or else the finalizer might not run.
+ SetFinalizer(s, func(ss *string) {
defer wg.Done()
- done := make(chan bool)
- var startTime time.Time
- var started, progress uint32
- go func() {
- s := new(string)
- SetFinalizer(s, func(ss *string) {
- startTime = time.Now()
- atomic.StoreUint32(&started, 1)
- growStack(&progress)
- done <- true
- })
- s = nil
- done <- true
- }()
- <-done
- GC()
+ finalizerStart = time.Now()
+ atomic.StoreUint32(&started, 1)
+ growStack(&progress)
+ })
+ setFinalizerTime := time.Now()
+ s = nil
- timeout := 20 * time.Second
- if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
- scale, err := strconv.Atoi(s)
- if err == nil {
- timeout *= time.Duration(scale)
- }
- }
-
- select {
- case <-done:
- case <-time.After(timeout):
+ if d, ok := t.Deadline(); ok {
+ // Pad the timeout by an arbitrary 5% to give the AfterFunc time to run.
+ timeout := time.Until(d) * 19 / 20
+ timer := time.AfterFunc(timeout, func() {
+ // Panic — instead of calling t.Error and returning from the test — so
+ // that we get a useful goroutine dump if the test times out, especially
+ // if GOTRACEBACK=system or GOTRACEBACK=crash is set.
if atomic.LoadUint32(&started) == 0 {
- t.Log("finalizer did not start")
+ panic("finalizer did not start")
} else {
- t.Logf("finalizer started %s ago and finished %d iterations", time.Since(startTime), atomic.LoadUint32(&progress))
+ panic(fmt.Sprintf("finalizer started %s ago (%s after registration) and ran %d iterations, but did not return", time.Since(finalizerStart), finalizerStart.Sub(setFinalizerTime), atomic.LoadUint32(&progress)))
}
- t.Log("first growStack took", growDuration)
- t.Error("finalizer did not run")
- return
- }
- }()
+ })
+ defer timer.Stop()
+ }
+
+ GC()
wg.Wait()
+ t.Logf("finalizer started after %s and ran %d iterations in %v", finalizerStart.Sub(setFinalizerTime), atomic.LoadUint32(&progress), time.Since(finalizerStart))
}
// ... and in init
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index 21dd95a..ee4db47 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -310,6 +310,7 @@
_FUNCDATA_OpenCodedDeferInfo = 4
_FUNCDATA_ArgInfo = 5
_FUNCDATA_ArgLiveInfo = 6
+ _FUNCDATA_WrapInfo = 7
_ArgsSizeUnknown = -0x80000000
)
@@ -863,7 +864,7 @@
// pcvalueCacheKey returns the outermost index in a pcvalueCache to use for targetpc.
// It must be very cheap to calculate.
-// For now, align to sys.PtrSize and reduce mod the number of entries.
+// For now, align to goarch.PtrSize and reduce mod the number of entries.
// In practice, this appears to be fairly randomly and evenly distributed.
func pcvalueCacheKey(targetpc uintptr) uintptr {
return (targetpc / goarch.PtrSize) % uintptr(len(pcvalueCache{}.entries))
diff --git a/src/runtime/sys_aix_ppc64.s b/src/runtime/sys_aix_ppc64.s
index c171c19..217ebb8 100644
--- a/src/runtime/sys_aix_ppc64.s
+++ b/src/runtime/sys_aix_ppc64.s
@@ -25,7 +25,12 @@
// stored in libcall_fn and store the results in libcall struture
// Up to 6 arguments can be passed to this C function
// Called by runtime.asmcgocall
-// It reserves a stack of 288 bytes for the C function.
+// It reserves a stack of 288 bytes for the C function. It must
+// follow AIX convention, thus the first local variable must
+// be stored at the offset 112, after the linker area (48 bytes)
+// and the argument area (64).
+// The AIX convention is described here:
+// https://www.ibm.com/docs/en/aix/7.2?topic=overview-runtime-process-stack
// NOT USING GO CALLING CONVENTION
// runtime.asmsyscall6 is a function descriptor to the real asmsyscall6.
DATA runtime·asmsyscall6+0(SB)/8, $asmsyscall6<>(SB)
@@ -34,7 +39,8 @@
GLOBL runtime·asmsyscall6(SB), NOPTR, $24
TEXT asmsyscall6<>(SB),NOSPLIT,$256
- MOVD R3, 48(R1) // Save libcall for later
+ // Save libcall for later
+ MOVD R3, 112(R1)
MOVD libcall_fn(R3), R12
MOVD libcall_args(R3), R9
MOVD 0(R9), R3
@@ -50,7 +56,7 @@
MOVD 40(R1), R2
// Store result in libcall
- MOVD 48(R1), R5
+ MOVD 112(R1), R5
MOVD R3, (libcall_r1)(R5)
MOVD $-1, R6
CMP R6, R3
diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go
index 80dd1a0..58b3a91 100644
--- a/src/runtime/sys_darwin.go
+++ b/src/runtime/sys_darwin.go
@@ -17,87 +17,91 @@
//go:linkname syscall_syscall syscall.syscall
//go:nosplit
-//go:cgo_unsafe_args
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
- libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn))
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
exitsyscall()
- return
+ return args.r1, args.r2, args.err
}
func syscall()
//go:linkname syscall_syscallX syscall.syscallX
//go:nosplit
-//go:cgo_unsafe_args
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
- libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&fn))
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&args))
exitsyscall()
- return
+ return args.r1, args.r2, args.err
}
func syscallX()
//go:linkname syscall_syscall6 syscall.syscall6
//go:nosplit
-//go:cgo_unsafe_args
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
entersyscall()
- libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn))
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
exitsyscall()
- return
+ return args.r1, args.r2, args.err
}
func syscall6()
//go:linkname syscall_syscall6X syscall.syscall6X
//go:nosplit
-//go:cgo_unsafe_args
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
entersyscall()
- libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&fn))
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&args))
exitsyscall()
- return
+ return args.r1, args.r2, args.err
}
func syscall6X()
//go:linkname syscall_syscallPtr syscall.syscallPtr
//go:nosplit
-//go:cgo_unsafe_args
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
- libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&fn))
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&args))
exitsyscall()
- return
+ return args.r1, args.r2, args.err
}
func syscallPtr()
//go:linkname syscall_rawSyscall syscall.rawSyscall
//go:nosplit
-//go:cgo_unsafe_args
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
- libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn))
- return
+ args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
+ return args.r1, args.r2, args.err
}
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:nosplit
-//go:cgo_unsafe_args
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
- libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn))
- return
+ args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
+ return args.r1, args.r2, args.err
}
// syscallNoErr is used in crypto/x509 to call into Security.framework and CF.
//go:linkname crypto_x509_syscall crypto/x509/internal/macos.syscall
//go:nosplit
-//go:cgo_unsafe_args
-func crypto_x509_syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1 uintptr) {
+func crypto_x509_syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) (r1 uintptr) {
+ args := struct {
+ fn, a1, a2, a3, a4, a5 uintptr
+ f1 float64
+ r1 uintptr
+ }{fn, a1, a2, a3, a4, a5, f1, r1}
entersyscall()
- libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallNoErr)), unsafe.Pointer(&fn))
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_x509)), unsafe.Pointer(&args))
exitsyscall()
- return
+ return args.r1
}
-func syscallNoErr()
+func syscall_x509()
// The *_trampoline functions convert from the Go calling convention to the C calling convention
// and then call the underlying libc function. They are defined in sys_darwin_$ARCH.s.
diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s
index 5d89cda..db4715d 100644
--- a/src/runtime/sys_darwin_amd64.s
+++ b/src/runtime/sys_darwin_amd64.s
@@ -831,9 +831,10 @@
POPQ BP
RET
-// syscallNoErr is like syscall6 but does not check for errors, and
-// only returns one value, for use with standard C ABI library functions.
-TEXT runtime·syscallNoErr(SB),NOSPLIT,$0
+// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
+// takes 5 uintptrs and 1 float64, and only returns one value,
+// for use with standard C ABI functions.
+TEXT runtime·syscall_x509(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
SUBQ $16, SP
@@ -842,7 +843,7 @@
MOVQ (3*8)(DI), DX // a3
MOVQ (4*8)(DI), CX // a4
MOVQ (5*8)(DI), R8 // a5
- MOVQ (6*8)(DI), R9 // a6
+ MOVQ (6*8)(DI), X0 // f1
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s
index 96d2ed1..e57ac53 100644
--- a/src/runtime/sys_darwin_arm64.s
+++ b/src/runtime/sys_darwin_arm64.s
@@ -736,9 +736,10 @@
ok:
RET
-// syscallNoErr is like syscall6 but does not check for errors, and
-// only returns one value, for use with standard C ABI library functions.
-TEXT runtime·syscallNoErr(SB),NOSPLIT,$0
+// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
+// takes 5 uintptrs and 1 float64, and only returns one value,
+// for use with standard C ABI functions.
+TEXT runtime·syscall_x509(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
MOVD R0, (RSP)
@@ -747,7 +748,7 @@
MOVD 24(R0), R2 // a3
MOVD 32(R0), R3 // a4
MOVD 40(R0), R4 // a5
- MOVD 48(R0), R5 // a6
+ FMOVD 48(R0), F0 // f1
MOVD 8(R0), R0 // a1
BL (R12)
diff --git a/src/runtime/sys_netbsd_arm64.s b/src/runtime/sys_netbsd_arm64.s
index 2d0b894..8a0496e 100644
--- a/src/runtime/sys_netbsd_arm64.s
+++ b/src/runtime/sys_netbsd_arm64.s
@@ -279,8 +279,8 @@
TEXT sigreturn_tramp<>(SB),NOSPLIT,$-8
MOVD g, R0
SVC $SYS_setcontext
- MOVD $0x4242, R0 // Something failed, return magic number
- SVC $SYS_exit
+ MOVD $0, R0
+ MOVD R0, (R0) // crash
TEXT runtime·sigaction(SB),NOSPLIT,$-8
MOVW sig+0(FP), R0 // arg 1 - signum
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index e76b403..9c38fac 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -152,7 +152,7 @@
// tryRegAssignArg tries to register-assign a value of type t.
// If this type is nested in an aggregate type, then offset is the
// offset of this type within its parent type.
-// Assumes t.size <= sys.PtrSize and t.size != 0.
+// Assumes t.size <= goarch.PtrSize and t.size != 0.
//
// Returns whether the assignment succeeded.
func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
index 101e941..034a1d8 100644
--- a/src/runtime/syscall_windows_test.go
+++ b/src/runtime/syscall_windows_test.go
@@ -628,6 +628,9 @@
}
func TestRaiseException(t *testing.T) {
+ if testenv.Builder() == "windows-amd64-2012" {
+ testenv.SkipFlaky(t, 49681)
+ }
o := runTestProg(t, "testprog", "RaiseException")
if strings.Contains(o, "RaiseException should not return") {
t.Fatalf("RaiseException did not crash program: %v", o)
@@ -770,6 +773,7 @@
for arglen := 0; arglen <= runtime.MaxArgs; arglen++ {
arglen := arglen
t.Run(fmt.Sprintf("arg-%d", arglen), func(t *testing.T) {
+ t.Parallel()
args := make([]string, arglen)
rets := make([]string, arglen+1)
params := make([]uintptr, arglen)
diff --git a/src/runtime/testdata/testprogcgo/aprof.go b/src/runtime/testdata/testprogcgo/aprof.go
index 44a15b0..1687014 100644
--- a/src/runtime/testdata/testprogcgo/aprof.go
+++ b/src/runtime/testdata/testprogcgo/aprof.go
@@ -7,8 +7,11 @@
// Test that SIGPROF received in C code does not crash the process
// looking for the C code's func pointer.
-// The test fails when the function is the first C function.
-// The exported functions are the first C functions, so we use that.
+// This is a regression test for issue 14599, where profiling fails when the
+// function is the first C function. Exported functions are the first C
+// functions, so we use an exported function. Exported functions are created in
+// lexicographical order of source files, so this file is named aprof.go to
+// ensure its function is first.
// extern void CallGoNop();
import "C"
diff --git a/src/runtime/testdata/testprogcgo/callback.go b/src/runtime/testdata/testprogcgo/callback.go
index a2d8a49..25f0715 100644
--- a/src/runtime/testdata/testprogcgo/callback.go
+++ b/src/runtime/testdata/testprogcgo/callback.go
@@ -66,7 +66,7 @@
func CgoCallbackGC() {
P := 100
- if os.Getenv("RUNTIME_TESTING_SHORT") != "" {
+ if os.Getenv("RUNTIME_TEST_SHORT") != "" {
P = 10
}
done := make(chan bool)
diff --git a/src/runtime/testdata/testprogcgo/pprof_callback.go b/src/runtime/testdata/testprogcgo/pprof_callback.go
new file mode 100644
index 0000000..e345643
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/pprof_callback.go
@@ -0,0 +1,89 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !plan9 && !windows
+
+package main
+
+// Make many C-to-Go callback while collecting a CPU profile.
+//
+// This is a regression test for issue 50936.
+
+/*
+#include <unistd.h>
+
+void goCallbackPprof();
+
+static void callGo() {
+ // Spent >20us in C so this thread is eligible for sysmon to retake its
+ // P.
+ usleep(50);
+ goCallbackPprof();
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "runtime/pprof"
+ "runtime"
+ "time"
+)
+
+func init() {
+ register("CgoPprofCallback", CgoPprofCallback)
+}
+
+//export goCallbackPprof
+func goCallbackPprof() {
+ // No-op. We want to stress the cgocall and cgocallback internals,
+ // landing as many pprof signals there as possible.
+}
+
+func CgoPprofCallback() {
+ // Issue 50936 was a crash in the SIGPROF handler when the signal
+ // arrived during the exitsyscall following a cgocall(back) in dropg or
+ // execute, when updating mp.curg.
+ //
+ // These are reachable only when exitsyscall finds no P available. Thus
+ // we make C calls from significantly more Gs than there are available
+ // Ps. Lots of runnable work combined with >20us spent in callGo makes
+ // it possible for sysmon to retake Ps, forcing C calls to go down the
+ // desired exitsyscall path.
+ //
+ // High GOMAXPROCS is used to increase opportunities for failure on
+ // high CPU machines.
+ const (
+ P = 16
+ G = 64
+ )
+ runtime.GOMAXPROCS(P)
+
+ f, err := os.CreateTemp("", "prof")
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(2)
+ }
+ defer f.Close()
+
+ if err := pprof.StartCPUProfile(f); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(2)
+ }
+
+ for i := 0; i < G; i++ {
+ go func() {
+ for {
+ C.callGo()
+ }
+ }()
+ }
+
+ time.Sleep(time.Second)
+
+ pprof.StopCPUProfile()
+
+ fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/threadprof.go b/src/runtime/testdata/testprogcgo/threadprof.go
index 8081173..d62d4b4 100644
--- a/src/runtime/testdata/testprogcgo/threadprof.go
+++ b/src/runtime/testdata/testprogcgo/threadprof.go
@@ -2,21 +2,22 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// We only build this file with the tag "threadprof", since it starts
-// a thread running a busy loop at constructor time.
-
-//go:build !plan9 && !windows && threadprof
-// +build !plan9,!windows,threadprof
+//go:build !plan9 && !windows
+// +build !plan9,!windows
package main
/*
#include <stdint.h>
+#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
volatile int32_t spinlock;
+// Note that this thread is only started if GO_START_SIGPROF_THREAD
+// is set in the environment, which is only done when running the
+// CgoExternalThreadSIGPROF test.
static void *thread1(void *p) {
(void)p;
while (spinlock == 0)
@@ -26,9 +27,13 @@
return NULL;
}
+// This constructor function is run when the program starts.
+// It is used for the CgoExternalThreadSIGPROF test.
__attribute__((constructor)) void issue9456() {
- pthread_t tid;
- pthread_create(&tid, 0, thread1, NULL);
+ if (getenv("GO_START_SIGPROF_THREAD") != NULL) {
+ pthread_t tid;
+ pthread_create(&tid, 0, thread1, NULL);
+ }
}
void **nullptr;
diff --git a/src/runtime/testdata/testwinlib/main.c b/src/runtime/testdata/testwinlib/main.c
index e84a32f..c3fe3cb 100644
--- a/src/runtime/testdata/testwinlib/main.c
+++ b/src/runtime/testdata/testwinlib/main.c
@@ -41,17 +41,20 @@
if (NULL == exceptionHandlerHandle)
{
printf("cannot add vectored exception handler\n");
+ fflush(stdout);
return 2;
}
void *continueHandlerHandle = AddVectoredContinueHandler(0, customContinueHandlder);
if (NULL == continueHandlerHandle)
{
printf("cannot add vectored continue handler\n");
+ fflush(stdout);
return 2;
}
CallMeBack(throwFromC);
RemoveVectoredContinueHandler(continueHandlerHandle);
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
printf("exceptionCount: %d\ncontinueCount: %d\n", exceptionCount, continueCount);
+ fflush(stdout);
return 0;
-}
\ No newline at end of file
+}
diff --git a/src/runtime/trace.go b/src/runtime/trace.go
index 5b14a5f..8f60de2 100644
--- a/src/runtime/trace.go
+++ b/src/runtime/trace.go
@@ -229,7 +229,7 @@
gp.traceseq = 0
gp.tracelastp = getg().m.p
// +PCQuantum because traceFrameForPC expects return PCs and subtracts PCQuantum.
- id := trace.stackTab.put([]uintptr{gp.startpc + sys.PCQuantum})
+ id := trace.stackTab.put([]uintptr{startPCforTrace(gp.startpc) + sys.PCQuantum})
traceEvent(traceEvGoCreate, -1, uint64(gp.goid), uint64(id), stackID)
}
if status == _Gwaiting {
@@ -426,6 +426,9 @@
trace.footerWritten = true
// Use float64 because (trace.ticksEnd - trace.ticksStart) * 1e9 can overflow int64.
freq := float64(trace.ticksEnd-trace.ticksStart) * 1e9 / float64(trace.timeEnd-trace.timeStart) / traceTickDiv
+ if freq <= 0 {
+ throw("trace: ReadTrace got invalid frequency")
+ }
trace.lockOwner = nil
unlock(&trace.lock)
var data []byte
@@ -1068,7 +1071,7 @@
newg.traceseq = 0
newg.tracelastp = getg().m.p
// +PCQuantum because traceFrameForPC expects return PCs and subtracts PCQuantum.
- id := trace.stackTab.put([]uintptr{pc + sys.PCQuantum})
+ id := trace.stackTab.put([]uintptr{startPCforTrace(pc) + sys.PCQuantum})
traceEvent(traceEvGoCreate, 2, uint64(newg.goid), uint64(id))
}
@@ -1241,3 +1244,17 @@
traceReleaseBuffer(pid)
}
+
+// the start PC of a goroutine for tracing purposes. If pc is a wrapper,
+// it returns the PC of the wrapped function. Otherwise it returns pc.
+func startPCforTrace(pc uintptr) uintptr {
+ f := findfunc(pc)
+ if !f.valid() {
+ return pc // should not happen, but don't care
+ }
+ w := funcdata(f, _FUNCDATA_WrapInfo)
+ if w == nil {
+ return pc // not a wrapper
+ }
+ return f.datap.textAddr(*(*uint32)(w))
+}
diff --git a/src/strings/builder.go b/src/strings/builder.go
index 547e52e..ba4df61 100644
--- a/src/strings/builder.go
+++ b/src/strings/builder.go
@@ -17,10 +17,9 @@
buf []byte
}
-// noescape hides a pointer from escape analysis. noescape is
-// the identity function but escape analysis doesn't think the
-// output depends on the input. noescape is inlined and currently
-// compiles down to zero instructions.
+// noescape hides a pointer from escape analysis. It is the identity function
+// but escape analysis doesn't think the output depends on the input.
+// noescape is inlined and currently compiles down to zero instructions.
// USE CAREFULLY!
// This was copied from the runtime; see issues 23382 and 7921.
//go:nosplit
diff --git a/src/strings/strings.go b/src/strings/strings.go
index c5a29e9..5793d9e 100644
--- a/src/strings/strings.go
+++ b/src/strings/strings.go
@@ -270,6 +270,8 @@
//
// Edge cases for s and sep (for example, empty strings) are handled
// as described in the documentation for Split.
+//
+// To split around the first instance of a separator, see Cut.
func SplitN(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
// SplitAfterN slices s into substrings after each instance of sep and
@@ -296,6 +298,8 @@
// and sep are empty, Split returns an empty slice.
//
// It is equivalent to SplitN with a count of -1.
+//
+// To split around the first instance of a separator, see Cut.
func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) }
// SplitAfter slices s into all substrings after each instance of sep and
diff --git a/src/syscall/dirent_test.go b/src/syscall/dirent_test.go
index 6570bf9..aeb40e5 100644
--- a/src/syscall/dirent_test.go
+++ b/src/syscall/dirent_test.go
@@ -22,7 +22,7 @@
func TestDirent(t *testing.T) {
const (
- direntBufSize = 2048
+ direntBufSize = 2048 // arbitrary? See https://go.dev/issue/37323.
filenameMinSize = 11
)
@@ -37,23 +37,38 @@
}
}
- buf := bytes.Repeat([]byte("DEADBEAF"), direntBufSize/8)
+ names := make([]string, 0, 10)
+
fd, err := syscall.Open(d, syscall.O_RDONLY, 0)
if err != nil {
t.Fatalf("syscall.open: %v", err)
}
defer syscall.Close(fd)
- n, err := syscall.ReadDirent(fd, buf)
- if err != nil {
- t.Fatalf("syscall.readdir: %v", err)
- }
- buf = buf[:n]
- names := make([]string, 0, 10)
- for len(buf) > 0 {
- var bc int
- bc, _, names = syscall.ParseDirent(buf, -1, names)
- buf = buf[bc:]
+ buf := bytes.Repeat([]byte{0xCD}, direntBufSize)
+ for {
+ n, err := syscall.ReadDirent(fd, buf)
+ if err == syscall.EINVAL {
+ // On linux, 'man getdents64' says that EINVAL indicates “result buffer is too small”.
+ // Try a bigger buffer.
+ t.Logf("ReadDirent: %v; retrying with larger buffer", err)
+ buf = bytes.Repeat([]byte{0xCD}, len(buf)*2)
+ continue
+ }
+ if err != nil {
+ t.Fatalf("syscall.readdir: %v", err)
+ }
+ t.Logf("ReadDirent: read %d bytes", n)
+ if n == 0 {
+ break
+ }
+
+ var consumed, count int
+ consumed, count, names = syscall.ParseDirent(buf[:n], -1, names)
+ t.Logf("ParseDirent: %d new name(s)", count)
+ if consumed != n {
+ t.Fatalf("ParseDirent: consumed %d bytes; expected %d", consumed, n)
+ }
}
sort.Strings(names)
diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go
index abcf1d5..e3891b0 100644
--- a/src/syscall/syscall_linux.go
+++ b/src/syscall/syscall_linux.go
@@ -958,62 +958,11 @@
//sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tv *Timeval) (err error)
-// allThreadsCaller holds the input and output state for performing a
-// allThreadsSyscall that needs to synchronize all OS thread state. Linux
-// generally does not always support this natively, so we have to
-// manipulate the runtime to fix things up.
-type allThreadsCaller struct {
- // arguments
- trap, a1, a2, a3, a4, a5, a6 uintptr
-
- // return values (only set by 0th invocation)
- r1, r2 uintptr
-
- // err is the error code
- err Errno
-}
-
-// doSyscall is a callback for executing a syscall on the current m
-// (OS thread).
-//go:nosplit
-//go:norace
-func (pc *allThreadsCaller) doSyscall(initial bool) bool {
- r1, r2, err := RawSyscall(pc.trap, pc.a1, pc.a2, pc.a3)
- if initial {
- pc.r1 = r1
- pc.r2 = r2
- pc.err = err
- } else if pc.r1 != r1 || (archHonorsR2 && pc.r2 != r2) || pc.err != err {
- print("trap:", pc.trap, ", a123=[", pc.a1, ",", pc.a2, ",", pc.a3, "]\n")
- print("results: got {r1=", r1, ",r2=", r2, ",err=", err, "}, want {r1=", pc.r1, ",r2=", pc.r2, ",r3=", pc.err, "}\n")
- panic("AllThreadsSyscall results differ between threads; runtime corrupted")
- }
- return err == 0
-}
-
-// doSyscall6 is a callback for executing a syscall6 on the current m
-// (OS thread).
-//go:nosplit
-//go:norace
-func (pc *allThreadsCaller) doSyscall6(initial bool) bool {
- r1, r2, err := RawSyscall6(pc.trap, pc.a1, pc.a2, pc.a3, pc.a4, pc.a5, pc.a6)
- if initial {
- pc.r1 = r1
- pc.r2 = r2
- pc.err = err
- } else if pc.r1 != r1 || (archHonorsR2 && pc.r2 != r2) || pc.err != err {
- print("trap:", pc.trap, ", a123456=[", pc.a1, ",", pc.a2, ",", pc.a3, ",", pc.a4, ",", pc.a5, ",", pc.a6, "]\n")
- print("results: got {r1=", r1, ",r2=", r2, ",err=", err, "}, want {r1=", pc.r1, ",r2=", pc.r2, ",r3=", pc.err, "}\n")
- panic("AllThreadsSyscall6 results differ between threads; runtime corrupted")
- }
- return err == 0
-}
-
-// Provided by runtime.syscall_runtime_doAllThreadsSyscall which
-// serializes the world and invokes the fn on each OS thread (what the
-// runtime refers to as m's). Once this function returns, all threads
-// are in sync.
-func runtime_doAllThreadsSyscall(fn func(bool) bool)
+// Provided by runtime.syscall_runtime_doAllThreadsSyscall which stops the
+// world and invokes the syscall on each OS thread. Once this function returns,
+// all threads are in sync.
+//go:uintptrescapes
+func runtime_doAllThreadsSyscall(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
// AllThreadsSyscall performs a syscall on each OS thread of the Go
// runtime. It first invokes the syscall on one thread. Should that
@@ -1035,17 +984,8 @@
if cgo_libc_setegid != nil {
return minus1, minus1, ENOTSUP
}
- pc := &allThreadsCaller{
- trap: trap,
- a1: a1,
- a2: a2,
- a3: a3,
- }
- runtime_doAllThreadsSyscall(pc.doSyscall)
- r1 = pc.r1
- r2 = pc.r2
- err = pc.err
- return
+ r1, r2, errno := runtime_doAllThreadsSyscall(trap, a1, a2, a3, 0, 0, 0)
+ return r1, r2, Errno(errno)
}
// AllThreadsSyscall6 is like AllThreadsSyscall, but extended to six
@@ -1055,20 +995,8 @@
if cgo_libc_setegid != nil {
return minus1, minus1, ENOTSUP
}
- pc := &allThreadsCaller{
- trap: trap,
- a1: a1,
- a2: a2,
- a3: a3,
- a4: a4,
- a5: a5,
- a6: a6,
- }
- runtime_doAllThreadsSyscall(pc.doSyscall6)
- r1 = pc.r1
- r2 = pc.r2
- err = pc.err
- return
+ r1, r2, errno := runtime_doAllThreadsSyscall(trap, a1, a2, a3, a4, a5, a6)
+ return r1, r2, Errno(errno)
}
// linked by runtime.cgocall.go
diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go
index 9844205..a3a5870 100644
--- a/src/syscall/syscall_linux_386.go
+++ b/src/syscall/syscall_linux_386.go
@@ -6,12 +6,6 @@
import "unsafe"
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall".
-const archHonorsR2 = true
-
const _SYS_setgroups = SYS_SETGROUPS32
func setTimespec(sec, nsec int64) Timespec {
diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go
index 04acd06..26b40ff 100644
--- a/src/syscall/syscall_linux_amd64.go
+++ b/src/syscall/syscall_linux_amd64.go
@@ -4,12 +4,6 @@
package syscall
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall".
-const archHonorsR2 = true
-
const _SYS_setgroups = SYS_SETGROUPS
//sys Dup2(oldfd int, newfd int) (err error)
diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go
index f2f342e..58f376f 100644
--- a/src/syscall/syscall_linux_arm.go
+++ b/src/syscall/syscall_linux_arm.go
@@ -6,12 +6,6 @@
import "unsafe"
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall". [EABI assumed.]
-const archHonorsR2 = true
-
const _SYS_setgroups = SYS_SETGROUPS32
func setTimespec(sec, nsec int64) Timespec {
diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go
index 990e732..f3c6c48 100644
--- a/src/syscall/syscall_linux_arm64.go
+++ b/src/syscall/syscall_linux_arm64.go
@@ -6,12 +6,6 @@
import "unsafe"
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall".
-const archHonorsR2 = true
-
const _SYS_setgroups = SYS_SETGROUPS
func EpollCreate(size int) (fd int, err error) {
diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go
index 7c9dd80..7be1664 100644
--- a/src/syscall/syscall_linux_mips64x.go
+++ b/src/syscall/syscall_linux_mips64x.go
@@ -6,12 +6,6 @@
package syscall
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall".
-const archHonorsR2 = true
-
const _SYS_setgroups = SYS_SETGROUPS
//sys Dup2(oldfd int, newfd int) (err error)
diff --git a/src/syscall/syscall_linux_mipsx.go b/src/syscall/syscall_linux_mipsx.go
index 741eeb1..97188d3 100644
--- a/src/syscall/syscall_linux_mipsx.go
+++ b/src/syscall/syscall_linux_mipsx.go
@@ -8,12 +8,6 @@
import "unsafe"
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall".
-const archHonorsR2 = true
-
const _SYS_setgroups = SYS_SETGROUPS
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go
index cc1b72e..ac42b20 100644
--- a/src/syscall/syscall_linux_ppc64x.go
+++ b/src/syscall/syscall_linux_ppc64x.go
@@ -6,12 +6,6 @@
package syscall
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall".
-const archHonorsR2 = false
-
const _SYS_setgroups = SYS_SETGROUPS
//sys Dup2(oldfd int, newfd int) (err error)
diff --git a/src/syscall/syscall_linux_riscv64.go b/src/syscall/syscall_linux_riscv64.go
index bcb89c6..4331a19 100644
--- a/src/syscall/syscall_linux_riscv64.go
+++ b/src/syscall/syscall_linux_riscv64.go
@@ -6,12 +6,6 @@
import "unsafe"
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall".
-const archHonorsR2 = true
-
const _SYS_setgroups = SYS_SETGROUPS
func EpollCreate(size int) (fd int, err error) {
diff --git a/src/syscall/syscall_linux_s390x.go b/src/syscall/syscall_linux_s390x.go
index 123664f..ff99024 100644
--- a/src/syscall/syscall_linux_s390x.go
+++ b/src/syscall/syscall_linux_s390x.go
@@ -6,12 +6,6 @@
import "unsafe"
-// archHonorsR2 captures the fact that r2 is honored by the
-// runtime.GOARCH. Syscall conventions are generally r1, r2, err :=
-// syscall(trap, ...). Not all architectures define r2 in their
-// ABI. See "man syscall".
-const archHonorsR2 = true
-
const _SYS_setgroups = SYS_SETGROUPS
//sys Dup2(oldfd int, newfd int) (err error)
diff --git a/src/syscall/syscall_linux_test.go b/src/syscall/syscall_linux_test.go
index 8d828be..0444b64 100644
--- a/src/syscall/syscall_linux_test.go
+++ b/src/syscall/syscall_linux_test.go
@@ -15,6 +15,7 @@
"sort"
"strconv"
"strings"
+ "sync"
"syscall"
"testing"
"unsafe"
@@ -565,3 +566,73 @@
}
}
}
+
+// TestAllThreadsSyscallError verifies that errors are properly returned when
+// the syscall fails on the original thread.
+func TestAllThreadsSyscallError(t *testing.T) {
+ // SYS_CAPGET takes pointers as the first two arguments. Since we pass
+ // 0, we expect to get EFAULT back.
+ r1, r2, err := syscall.AllThreadsSyscall(syscall.SYS_CAPGET, 0, 0, 0)
+ if err == syscall.ENOTSUP {
+ t.Skip("AllThreadsSyscall disabled with cgo")
+ }
+ if err != syscall.EFAULT {
+ t.Errorf("AllThreadSyscall(SYS_CAPGET) got %d, %d, %v, want err %v", r1, r2, err, syscall.EFAULT)
+ }
+}
+
+// TestAllThreadsSyscallBlockedSyscall confirms that AllThreadsSyscall
+// can interrupt threads in long-running system calls. This test will
+// deadlock if this doesn't work correctly.
+func TestAllThreadsSyscallBlockedSyscall(t *testing.T) {
+ if _, _, err := syscall.AllThreadsSyscall(syscall.SYS_PRCTL, PR_SET_KEEPCAPS, 0, 0); err == syscall.ENOTSUP {
+ t.Skip("AllThreadsSyscall disabled with cgo")
+ }
+
+ rd, wr, err := os.Pipe()
+ if err != nil {
+ t.Fatalf("unable to obtain a pipe: %v", err)
+ }
+
+ // Perform a blocking read on the pipe.
+ var wg sync.WaitGroup
+ ready := make(chan bool)
+ wg.Add(1)
+ go func() {
+ data := make([]byte, 1)
+
+ // To narrow the window we have to wait for this
+ // goroutine to block in read, synchronize just before
+ // calling read.
+ ready <- true
+
+ // We use syscall.Read directly to avoid the poller.
+ // This will return when the write side is closed.
+ n, err := syscall.Read(int(rd.Fd()), data)
+ if !(n == 0 && err == nil) {
+ t.Errorf("expected read to return 0, got %d, %s", n, err)
+ }
+
+ // Clean up rd and also ensure rd stays reachable so
+ // it doesn't get closed by GC.
+ rd.Close()
+ wg.Done()
+ }()
+ <-ready
+
+ // Loop here to give the goroutine more time to block in read.
+ // Generally this will trigger on the first iteration anyway.
+ pid := syscall.Getpid()
+ for i := 0; i < 100; i++ {
+ if id, _, e := syscall.AllThreadsSyscall(syscall.SYS_GETPID, 0, 0, 0); e != 0 {
+ t.Errorf("[%d] getpid failed: %v", i, e)
+ } else if int(id) != pid {
+ t.Errorf("[%d] getpid got=%d, want=%d", i, id, pid)
+ }
+ // Provide an explicit opportunity for this goroutine
+ // to change Ms.
+ runtime.Gosched()
+ }
+ wr.Close()
+ wg.Wait()
+}
diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go
index e4af0ba..317c0c1 100644
--- a/src/syscall/syscall_unix_test.go
+++ b/src/syscall/syscall_unix_test.go
@@ -326,46 +326,6 @@
}
}
-func TestRlimit(t *testing.T) {
- var rlimit, zero syscall.Rlimit
- err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit)
- if err != nil {
- t.Fatalf("Getrlimit: save failed: %v", err)
- }
- if zero == rlimit {
- t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit)
- }
- set := rlimit
- set.Cur = set.Max - 1
- if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && set.Cur > 4096 {
- // rlim_min for RLIMIT_NOFILE should be equal to
- // or lower than kern.maxfilesperproc, which on
- // some machines are 4096. See #40564.
- set.Cur = 4096
- }
- err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &set)
- if err != nil {
- t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
- }
- var get syscall.Rlimit
- err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &get)
- if err != nil {
- t.Fatalf("Getrlimit: get failed: %v", err)
- }
- set = rlimit
- set.Cur = set.Max - 1
- if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && set.Cur > 4096 {
- set.Cur = 4096
- }
- if set != get {
- t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
- }
- err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)
- if err != nil {
- t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err)
- }
-}
-
func TestSeekFailure(t *testing.T) {
_, err := syscall.Seek(-1, 0, io.SeekStart)
if err == nil {
diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go
index 4a5def1..b5e1339 100644
--- a/src/testing/fuzz.go
+++ b/src/testing/fuzz.go
@@ -63,7 +63,7 @@
// for an example, and see the F.Fuzz and F.Add method documentation for
// details.
//
-// *F methods can only be called before (*F).Fuzz. Once the the test is
+// *F methods can only be called before (*F).Fuzz. Once the test is
// executing the fuzz target, only (*T) methods can be used. The only *F methods
// that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.
type F struct {
@@ -199,7 +199,7 @@
// the corresponding *T method instead. The only *F methods that are allowed in
// the (*F).Fuzz function are (*F).Failed and (*F).Name.
//
-// This function sould be fast and deterministic, and its behavior should not
+// This function should be fast and deterministic, and its behavior should not
// depend on shared state. No mutatable input arguments, or pointers to them,
// should be retained between executions of the fuzz function, as the memory
// backing them may be mutated during a subsequent invocation. ff must not
@@ -227,6 +227,9 @@
if fnType.NumIn() < 2 || fnType.In(0) != reflect.TypeOf((*T)(nil)) {
panic("testing: fuzz target must receive at least two arguments, where the first argument is a *T")
}
+ if fnType.NumOut() != 0 {
+ panic("testing: fuzz target must not return a value")
+ }
// Save the types of the function to compare against the corpus.
var types []reflect.Type
@@ -323,12 +326,14 @@
for _, v := range e.Values {
args = append(args, reflect.ValueOf(v))
}
- // Before reseting the current coverage, defer the snapshot so that we
- // make sure it is called right before the tRunner function exits,
- // regardless of whether it was executed cleanly, panicked, or if the
- // fuzzFn called t.Fatal.
- defer f.fuzzContext.deps.SnapshotCoverage()
- f.fuzzContext.deps.ResetCoverage()
+ // Before resetting the current coverage, defer the snapshot so that
+ // we make sure it is called right before the tRunner function
+ // exits, regardless of whether it was executed cleanly, panicked,
+ // or if the fuzzFn called t.Fatal.
+ if f.testContext.isFuzzing {
+ defer f.fuzzContext.deps.SnapshotCoverage()
+ f.fuzzContext.deps.ResetCoverage()
+ }
fn.Call(args)
})
<-t.signal
@@ -666,6 +671,7 @@
// This only affects fuzz tests run as normal tests.
// While fuzzing, T.Parallel has no effect, so f.sub is empty, and this
// branch is not taken. f.barrier is nil in that case.
+ f.testContext.release()
close(f.barrier)
// Wait for the subtests to complete.
for _, sub := range f.sub {
diff --git a/src/testing/testing.go b/src/testing/testing.go
index 7bd13a8..df4dfe4 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -202,8 +202,7 @@
// mode, the fuzz test acts much like a regular test, with subtests started
// with F.Fuzz instead of T.Run.
//
-// TODO(#48255): write and link to documentation that will be helpful to users
-// who are unfamiliar with fuzzing.
+// See https://go.dev/doc/fuzz for documentation about fuzzing.
//
// Skipping
//
@@ -1087,7 +1086,7 @@
c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern)
if c.tempDirErr == nil {
c.Cleanup(func() {
- if err := os.RemoveAll(c.tempDir); err != nil {
+ if err := removeAll(c.tempDir); err != nil {
c.Errorf("TempDir RemoveAll cleanup: %v", err)
}
})
@@ -1106,6 +1105,36 @@
return dir
}
+// removeAll is like os.RemoveAll, but retries Windows "Access is denied."
+// errors up to an arbitrary timeout.
+//
+// Those errors have been known to occur spuriously on at least the
+// windows-amd64-2012 builder (https://go.dev/issue/50051), and can only occur
+// legitimately if the test leaves behind a temp file that either is still open
+// or the test otherwise lacks permission to delete. In the case of legitimate
+// failures, a failing test may take a bit longer to fail, but once the test is
+// fixed the extra latency will go away.
+func removeAll(path string) error {
+ const arbitraryTimeout = 2 * time.Second
+ var (
+ start time.Time
+ nextSleep = 1 * time.Millisecond
+ )
+ for {
+ err := os.RemoveAll(path)
+ if !isWindowsAccessDenied(err) {
+ return err
+ }
+ if start.IsZero() {
+ start = time.Now()
+ } else if d := time.Since(start) + nextSleep; d >= arbitraryTimeout {
+ return err
+ }
+ time.Sleep(nextSleep)
+ nextSleep += time.Duration(rand.Int63n(int64(nextSleep)))
+ }
+}
+
// Setenv calls os.Setenv(key, value) and uses Cleanup to
// restore the environment variable to its original value
// after the test.
diff --git a/src/testing/testing_other.go b/src/testing/testing_other.go
new file mode 100644
index 0000000..29496d8
--- /dev/null
+++ b/src/testing/testing_other.go
@@ -0,0 +1,13 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !windows
+
+package testing
+
+// isWindowsAccessDenied reports whether err is ERROR_ACCESS_DENIED,
+// which is defined only on Windows.
+func isWindowsAccessDenied(err error) bool {
+ return false
+}
diff --git a/src/testing/testing_windows.go b/src/testing/testing_windows.go
new file mode 100644
index 0000000..bc76cb8
--- /dev/null
+++ b/src/testing/testing_windows.go
@@ -0,0 +1,18 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build windows
+
+package testing
+
+import (
+ "errors"
+ "syscall"
+)
+
+// isWindowsAccessDenied reports whether err is ERROR_ACCESS_DENIED,
+// which is defined only on Windows.
+func isWindowsAccessDenied(err error) bool {
+ return errors.Is(err, syscall.ERROR_ACCESS_DENIED)
+}
diff --git a/src/time/format.go b/src/time/format.go
index 5fb9cdc..33e6543 100644
--- a/src/time/format.go
+++ b/src/time/format.go
@@ -914,6 +914,7 @@
// field immediately after the seconds field, even if the layout does not
// signify its presence. In that case either a comma or a decimal point
// followed by a maximal series of digits is parsed as a fractional second.
+// Fractional seconds are truncated to nanosecond precision.
//
// Elements omitted from the layout are assumed to be zero or, when
// zero is impossible, one, so parsing "3:04pm" returns the time
diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go
index c48e704..5a949b6 100644
--- a/src/time/sleep_test.go
+++ b/src/time/sleep_test.go
@@ -7,6 +7,7 @@
import (
"errors"
"fmt"
+ "internal/testenv"
"math/rand"
"runtime"
"strings"
@@ -531,6 +532,10 @@
// Test that rapidly moving a timer earlier doesn't cause it to get dropped.
// Issue 47329.
func TestTimerModifiedEarlier(t *testing.T) {
+ if runtime.GOOS == "plan9" && runtime.GOARCH == "arm" {
+ testenv.SkipFlaky(t, 50470)
+ }
+
past := Until(Unix(0, 0))
count := 1000
fail := 0
diff --git a/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go
index 83c776d..3a1674a 100644
--- a/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go
+++ b/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go
@@ -407,7 +407,12 @@
func (s *String) readBase128Int(out *int) bool {
ret := 0
for i := 0; len(*s) > 0; i++ {
- if i == 4 {
+ if i == 5 {
+ return false
+ }
+ // Avoid overflowing int on a 32-bit platform.
+ // We don't want different behavior based on the architecture.
+ if ret >= 1<<(31-7) {
return false
}
ret <<= 7
diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt
index 4130027..3a975cd 100644
--- a/src/vendor/modules.txt
+++ b/src/vendor/modules.txt
@@ -1,4 +1,4 @@
-# golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa
+# golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
## explicit; go 1.17
golang.org/x/crypto/chacha20
golang.org/x/crypto/chacha20poly1305
diff --git a/test/asmhdr.dir/main.go b/test/asmhdr.dir/main.go
index 808b5de..4e1813d 100644
--- a/test/asmhdr.dir/main.go
+++ b/test/asmhdr.dir/main.go
@@ -16,12 +16,15 @@
bigInt = 0xffffffffffffffff
stringVal = "test"
+
+ longStringVal = "this_is_a_string_constant_longer_than_seventy_characters_which_used_to_fail_see_issue_50253"
)
var (
- smallIntAsm int64
- bigIntAsm uint64
- stringAsm [len(stringVal)]byte
+ smallIntAsm int64
+ bigIntAsm uint64
+ stringAsm [len(stringVal)]byte
+ longStringAsm [len(longStringVal)]byte
)
type typ struct {
@@ -46,6 +49,9 @@
if stringVal != string(stringAsm[:]) {
println("stringVal", stringVal, "!=", string(stringAsm[:]))
}
+ if longStringVal != string(longStringAsm[:]) {
+ println("longStringVal", longStringVal, "!=", string(longStringAsm[:]))
+ }
// We also include boolean consts in go_asm.h, but they're
// defined to be "true" or "false", and it's not clear how to
diff --git a/test/asmhdr.dir/main.s b/test/asmhdr.dir/main.s
index 7e2d8e7..bc2aa99 100644
--- a/test/asmhdr.dir/main.s
+++ b/test/asmhdr.dir/main.s
@@ -14,6 +14,9 @@
DATA ·stringAsm(SB)/4, $const_stringVal
GLOBL ·stringAsm(SB),RODATA,$4
+DATA ·longStringAsm(SB)/91, $const_longStringVal
+GLOBL ·longStringAsm(SB),RODATA,$91
+
DATA ·typSize(SB)/8, $typ__size
GLOBL ·typSize(SB),RODATA,$8
diff --git a/test/fixedbugs/bug176.go b/test/fixedbugs/bug176.go
index 7001dd0..61e63c7 100644
--- a/test/fixedbugs/bug176.go
+++ b/test/fixedbugs/bug176.go
@@ -8,7 +8,6 @@
var x int
-var a = []int{ x: 1} // ERROR "constant"
-var b = [...]int{x: 1} // GCCGO_ERROR "constant"
-var c = map[int]int{ x: 1}
-
+var a = []int{x: 1} // ERROR "constant"
+var b = [...]int{x: 1} // ERROR "constant"
+var c = map[int]int{x: 1}
diff --git a/test/fixedbugs/bug193.go b/test/fixedbugs/bug193.go
index 3607322..64e06da 100644
--- a/test/fixedbugs/bug193.go
+++ b/test/fixedbugs/bug193.go
@@ -11,8 +11,6 @@
ss := 1 << s
y1 := float64(ss)
y2 := float64(1 << s) // ERROR "shift"
- // see issues #45114, #45117
- // y3 := string(1 << s) // DISABLED "shift"
- y3 := 0
+ y3 := string(1 << s) // ERROR "shift"
_, _, _, _, _ = s, ss, y1, y2, y3
}
diff --git a/test/fixedbugs/bug195.go b/test/fixedbugs/bug195.go
index 6d8578d..4a3bf0d 100644
--- a/test/fixedbugs/bug195.go
+++ b/test/fixedbugs/bug195.go
@@ -11,14 +11,14 @@
type I3 interface{ int } // ERROR "interface"
-type S struct {
- x interface{ S } // ERROR "interface"
+type S struct { // GC_ERROR "invalid recursive type"
+ x interface{ S } // GCCGO_ERROR "interface"
}
-type I4 interface { // GC_ERROR "invalid recursive type I4\n\tLINE: I4 refers to\n\tLINE: I4$"
+type I4 interface { // GC_ERROR "invalid recursive type I4\n\tLINE:.* I4 refers to\n\tLINE:.* I4$"
I4 // GCCGO_ERROR "interface"
}
-type I5 interface { // GC_ERROR "invalid recursive type I5\n\tLINE: I5 refers to\n\tLINE+4: I6 refers to\n\tLINE: I5$"
+type I5 interface { // GC_ERROR "invalid recursive type I5\n\tLINE:.* I5 refers to\n\tLINE+4:.* I6 refers to\n\tLINE:.* I5$"
I6
}
diff --git a/test/fixedbugs/bug228.go b/test/fixedbugs/bug228.go
index 50e8959..5c0e7e5 100644
--- a/test/fixedbugs/bug228.go
+++ b/test/fixedbugs/bug228.go
@@ -6,14 +6,10 @@
package main
-func f(x int, y ...int) // ok
+func f(x int, y ...int) // ok
func g(x int, y float32) (...) // ERROR "[.][.][.]"
-func h(x, y ...int) // ERROR "[.][.][.]"
-
-func i(x int, y ...int, z float32) // ERROR "[.][.][.]"
-
var x ...int; // ERROR "[.][.][.]|syntax|type"
type T ...int; // ERROR "[.][.][.]|syntax|type"
diff --git a/test/fixedbugs/bug228a.go b/test/fixedbugs/bug228a.go
new file mode 100644
index 0000000..c42b0bf
--- /dev/null
+++ b/test/fixedbugs/bug228a.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func f(x int, y ...int) // ok
+
+func h(x, y ...int) // ERROR "[.][.][.]"
+
+func i(x int, y ...int, z float32) // ERROR "[.][.][.]"
diff --git a/test/fixedbugs/bug231.go b/test/fixedbugs/bug231.go
index f64ddc3..db0d536 100644
--- a/test/fixedbugs/bug231.go
+++ b/test/fixedbugs/bug231.go
@@ -6,17 +6,19 @@
package main
-type I interface { m() }
-type T struct { m func() }
-type M struct {}
+type I interface{ m() }
+type T struct{ m func() }
+type M struct{}
+
func (M) m() {}
func main() {
var t T
var m M
var i I
-
+
i = m
- i = t // ERROR "not a method|has no methods" "does not implement I"
+ // types2 does not give extra error "T.m is a field, not a method"
+ i = t // ERROR "not a method|has no methods|does not implement I"
_ = i
}
diff --git a/test/fixedbugs/bug255.go b/test/fixedbugs/bug255.go
index 458fb97..184ff2d 100644
--- a/test/fixedbugs/bug255.go
+++ b/test/fixedbugs/bug255.go
@@ -6,15 +6,16 @@
package main
-var a [10]int // ok
-var b [1e1]int // ok
-var c [1.5]int // ERROR "truncated"
-var d ["abc"]int // ERROR "invalid array bound|not numeric"
-var e [nil]int // ERROR "use of untyped nil|invalid array bound|not numeric"
-var f [e]int // ok: error already reported for e
-var g [1 << 65]int // ERROR "array bound is too large|overflows"
+var a [10]int // ok
+var b [1e1]int // ok
+var c [1.5]int // ERROR "truncated|must be integer"
+var d ["abc"]int // ERROR "invalid array bound|not numeric|must be integer"
+var e [nil]int // ERROR "use of untyped nil|invalid array (bound|length)|not numeric|must be constant"
+// var f [e]int // ok with Go 1.17 because an error was reported for e; leads to an error for Go 1.18
+var f [ee]int // ERROR "undefined|undeclared"
+var g [1 << 65]int // ERROR "array bound is too large|overflows|must be integer"
var h [len(a)]int // ok
func ff() string
-var i [len([1]string{ff()})]int // ERROR "non-constant array bound|not constant"
+var i [len([1]string{ff()})]int // ERROR "non-constant array bound|not constant|must be constant"
diff --git a/test/fixedbugs/bug388.go b/test/fixedbugs/bug388.go
index 2d50850..a060c9f 100644
--- a/test/fixedbugs/bug388.go
+++ b/test/fixedbugs/bug388.go
@@ -13,16 +13,6 @@
println(i, runtime.UintType) // GCCGO_ERROR "undefined identifier"
}
-func bar(i int) {
- runtime.UintType := i // ERROR "non-name runtime.UintType|non-name on left side|undefined identifier"
- println(runtime.UintType) // GCCGO_ERROR "invalid use of type|undefined identifier"
-}
-
-func baz() {
- main.i := 1 // ERROR "non-name main.i|non-name on left side"
- println(main.i) // GCCGO_ERROR "no fields or methods"
-}
-
func qux() {
var main.i // ERROR "unexpected [.]|expected type"
println(main.i)
diff --git a/test/fixedbugs/bug388a.go b/test/fixedbugs/bug388a.go
new file mode 100644
index 0000000..fca6d9c
--- /dev/null
+++ b/test/fixedbugs/bug388a.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 2231
+
+package main
+import "runtime"
+
+func bar(i int) {
+ runtime.UintType := i // ERROR "non-name runtime.UintType|non-name on left side|undefined"
+ println(runtime.UintType) // ERROR "invalid use of type|undefined"
+}
+
+func baz() {
+ main.i := 1 // ERROR "non-name main.i|non-name on left side|undefined"
+ println(main.i) // ERROR "no fields or methods|undefined"
+}
+
+func main() {
+}
diff --git a/test/fixedbugs/bug412.go b/test/fixedbugs/bug412.go
index 183fb7e..26ac45f 100644
--- a/test/fixedbugs/bug412.go
+++ b/test/fixedbugs/bug412.go
@@ -7,10 +7,10 @@
package p
type t struct {
- x int // GCCGO_ERROR "duplicate field name .x."
- x int // GC_ERROR "duplicate field x"
+ x int // GCCGO_ERROR "duplicate field name .x."
+ x int // GC_ERROR "duplicate field x|x redeclared"
}
func f(t *t) int {
- return t.x // GC_ERROR "ambiguous selector t.x"
+ return t.x
}
diff --git a/test/fixedbugs/bug515.go b/test/fixedbugs/bug515.go
new file mode 100644
index 0000000..186f466
--- /dev/null
+++ b/test/fixedbugs/bug515.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Caused a gofrontend crash.
+
+package p
+
+//go:notinheap
+type S1 struct{}
+
+type S2 struct {
+ r interface { Read([]byte) (int, error) }
+ s1, s2 []byte
+ p *S1
+ n uintptr
+}
+
+var V any = S2{}
diff --git a/test/fixedbugs/issue11590.go b/test/fixedbugs/issue11590.go
index f2a955f..9f89783 100644
--- a/test/fixedbugs/issue11590.go
+++ b/test/fixedbugs/issue11590.go
@@ -6,6 +6,6 @@
package p
-var _ = int8(4) * 300 // ERROR "constant 300 overflows int8" "constant 1200 overflows int8|integer constant overflow"
-var _ = complex64(1) * 1e200 // ERROR "constant 1e\+200 overflows complex64|complex real part overflow"
-var _ = complex128(1) * 1e500 // ERROR "constant 1e\+500 overflows complex128|complex real part overflow"
+var _ = int8(4) * 300 // ERROR "overflows int8"
+var _ = complex64(1) * 1e200 // ERROR "complex real part overflow|overflows complex64"
+var _ = complex128(1) * 1e500 // ERROR "complex real part overflow|overflows complex128"
diff --git a/test/fixedbugs/issue11610.go b/test/fixedbugs/issue11610.go
index 7ebfae6..8d68c98 100644
--- a/test/fixedbugs/issue11610.go
+++ b/test/fixedbugs/issue11610.go
@@ -8,7 +8,6 @@
// following an empty import.
package a
-import"" // ERROR "import path is empty"
var? // ERROR "invalid character U\+003F '\?'|invalid character 0x3f in input file"
var x int // ERROR "unexpected var|expected identifier|expected type"
diff --git a/test/fixedbugs/issue11610a.go b/test/fixedbugs/issue11610a.go
new file mode 100644
index 0000000..bbf60b6
--- /dev/null
+++ b/test/fixedbugs/issue11610a.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test an internal compiler error on ? symbol in declaration
+// following an empty import.
+
+package a
+import"" // ERROR "import path is empty|invalid import path \(empty string\)"
diff --git a/test/fixedbugs/issue11614.go b/test/fixedbugs/issue11614.go
index 6ea463b..e8d6bad 100644
--- a/test/fixedbugs/issue11614.go
+++ b/test/fixedbugs/issue11614.go
@@ -11,15 +11,15 @@
package main
type I interface {
- int // ERROR "interface contains embedded non-interface"
+ int // ERROR "interface contains embedded non-interface|embedding non-interface type int requires"
}
func n() {
- (I)
+ (I) // GC_ERROR "is not an expression"
}
func m() {
- (interface{int}) // ERROR "interface contains embedded non-interface" "type interface { int } is not an expression"
+ (interface{int}) // ERROR "interface contains embedded non-interface|embedding non-interface type int requires" "type interface { int } is not an expression|\(interface{int}\) \(type\) is not an expression"
}
func main() {
diff --git a/test/fixedbugs/issue11656.dir/asm.go b/test/fixedbugs/issue11656.dir/asm.go
new file mode 100644
index 0000000..cdcb064
--- /dev/null
+++ b/test/fixedbugs/issue11656.dir/asm.go
@@ -0,0 +1,10 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build ppc64 || ppc64le
+// +build ppc64 ppc64le
+
+package main
+
+func syncIcache(p uintptr)
diff --git a/test/fixedbugs/issue11656.dir/asm_generic.go b/test/fixedbugs/issue11656.dir/asm_generic.go
new file mode 100644
index 0000000..104d44d
--- /dev/null
+++ b/test/fixedbugs/issue11656.dir/asm_generic.go
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !ppc64 && !ppc64le
+// +build !ppc64,!ppc64le
+
+package main
+
+func syncIcache(p uintptr) {
+}
diff --git a/test/fixedbugs/issue11656.dir/asm_ppc64.s b/test/fixedbugs/issue11656.dir/asm_ppc64.s
new file mode 100644
index 0000000..125a197
--- /dev/null
+++ b/test/fixedbugs/issue11656.dir/asm_ppc64.s
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func syncIcache(p uintptr)
+TEXT main·syncIcache(SB), NOSPLIT|NOFRAME, $0-0
+ SYNC
+ MOVD (R3), R3
+ ICBI (R3)
+ ISYNC
+ RET
diff --git a/test/fixedbugs/issue11656.dir/asm_ppc64le.s b/test/fixedbugs/issue11656.dir/asm_ppc64le.s
new file mode 100644
index 0000000..125a197
--- /dev/null
+++ b/test/fixedbugs/issue11656.dir/asm_ppc64le.s
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func syncIcache(p uintptr)
+TEXT main·syncIcache(SB), NOSPLIT|NOFRAME, $0-0
+ SYNC
+ MOVD (R3), R3
+ ICBI (R3)
+ ISYNC
+ RET
diff --git a/test/fixedbugs/issue11656.dir/issue11656.go b/test/fixedbugs/issue11656.dir/issue11656.go
new file mode 100644
index 0000000..a5a52df
--- /dev/null
+++ b/test/fixedbugs/issue11656.dir/issue11656.go
@@ -0,0 +1,75 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "encoding/binary"
+ "runtime"
+ "runtime/debug"
+ "unsafe"
+)
+
+func main() {
+ debug.SetPanicOnFault(true)
+ defer func() {
+ if err := recover(); err == nil {
+ panic("not panicking")
+ }
+ pc, _, _, _ := runtime.Caller(10)
+ f := runtime.FuncForPC(pc)
+ if f == nil || f.Name() != "main.f" {
+ if f == nil {
+ println("no func for ", unsafe.Pointer(pc))
+ } else {
+ println("found func:", f.Name())
+ }
+ panic("cannot find main.f on stack")
+ }
+ }()
+ f(20)
+}
+
+func f(n int) {
+ if n > 0 {
+ f(n - 1)
+ }
+ var f struct {
+ x uintptr
+ }
+
+ // We want to force a seg fault, to get a crash at a PC value != 0.
+ // Not all systems make the data section non-executable.
+ ill := make([]byte, 64)
+ switch runtime.GOARCH {
+ case "386", "amd64":
+ ill = append(ill[:0], 0x89, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00) // MOVL AX, 0
+ case "arm":
+ binary.LittleEndian.PutUint32(ill[0:4], 0xe3a00000) // MOVW $0, R0
+ binary.LittleEndian.PutUint32(ill[4:8], 0xe5800000) // MOVW R0, (R0)
+ case "arm64":
+ binary.LittleEndian.PutUint32(ill, 0xf90003ff) // MOVD ZR, (ZR)
+ case "ppc64":
+ binary.BigEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0)
+ case "ppc64le":
+ binary.LittleEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0)
+ case "mips", "mips64":
+ binary.BigEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0)
+ case "mipsle", "mips64le":
+ binary.LittleEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0)
+ case "s390x":
+ ill = append(ill[:0], 0xa7, 0x09, 0x00, 0x00) // MOVD $0, R0
+ ill = append(ill, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x24) // MOVD R0, (R0)
+ case "riscv64":
+ binary.LittleEndian.PutUint32(ill, 0x00003023) // MOV X0, (X0)
+ default:
+ // Just leave it as 0 and hope for the best.
+ }
+
+ f.x = uintptr(unsafe.Pointer(&ill[0]))
+ p := &f
+ fn := *(*func())(unsafe.Pointer(&p))
+ syncIcache(f.x)
+ fn()
+}
diff --git a/test/fixedbugs/issue11656.go b/test/fixedbugs/issue11656.go
index 85fe720..dba8e35 100644
--- a/test/fixedbugs/issue11656.go
+++ b/test/fixedbugs/issue11656.go
@@ -1,89 +1,22 @@
-// run
+// runindir
-// Copyright 2015 The Go Authors. All rights reserved.
+// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Issue 11656: runtime: jump to bad PC missing good traceback
+
// windows doesn't work, because Windows exception handling
// delivers signals based on the current PC, and that current PC
// doesn't go into the Go runtime.
-// +build !windows
// wasm does not work, because the linear memory is not executable.
-// +build !wasm
// This test doesn't work on gccgo/GoLLVM, because they will not find
// any unwind information for the artificial function, and will not be
// able to unwind past that point.
-// +build !gccgo
-package main
+//go:build !windows && !wasm && !gccgo
+// +build !windows,!wasm,!gccgo
-import (
- "encoding/binary"
- "runtime"
- "runtime/debug"
- "unsafe"
-)
-
-func main() {
- debug.SetPanicOnFault(true)
- defer func() {
- if err := recover(); err == nil {
- panic("not panicking")
- }
- pc, _, _, _ := runtime.Caller(10)
- f := runtime.FuncForPC(pc)
- if f == nil || f.Name() != "main.f" {
- if f == nil {
- println("no func for ", unsafe.Pointer(pc))
- } else {
- println("found func:", f.Name())
- }
- panic("cannot find main.f on stack")
- }
- }()
- f(20)
-}
-
-func f(n int) {
- if n > 0 {
- f(n - 1)
- }
- var f struct {
- x uintptr
- }
-
- // We want to force a seg fault, to get a crash at a PC value != 0.
- // Not all systems make the data section non-executable.
- ill := make([]byte, 64)
- switch runtime.GOARCH {
- case "386", "amd64":
- ill = append(ill[:0], 0x89, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00) // MOVL AX, 0
- case "arm":
- binary.LittleEndian.PutUint32(ill[0:4], 0xe3a00000) // MOVW $0, R0
- binary.LittleEndian.PutUint32(ill[4:8], 0xe5800000) // MOVW R0, (R0)
- case "arm64":
- binary.LittleEndian.PutUint32(ill, 0xf90003ff) // MOVD ZR, (ZR)
- case "ppc64":
- binary.BigEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0)
- case "ppc64le":
- binary.LittleEndian.PutUint32(ill, 0xf8000000) // MOVD R0, (R0)
- case "mips", "mips64":
- binary.BigEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0)
- case "mipsle", "mips64le":
- binary.LittleEndian.PutUint32(ill, 0xfc000000) // MOVV R0, (R0)
- case "s390x":
- ill = append(ill[:0], 0xa7, 0x09, 0x00, 0x00) // MOVD $0, R0
- ill = append(ill, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x24) // MOVD R0, (R0)
- case "riscv64":
- binary.LittleEndian.PutUint32(ill, 0x00003023) // MOV X0, (X0)
- default:
- // Just leave it as 0 and hope for the best.
- }
-
- f.x = uintptr(unsafe.Pointer(&ill[0]))
- p := &f
- fn := *(*func())(unsafe.Pointer(&p))
- fn()
-}
+package ignored
diff --git a/test/fixedbugs/issue11737.go b/test/fixedbugs/issue11737.go
index eb4bfe8..aa4abbc 100644
--- a/test/fixedbugs/issue11737.go
+++ b/test/fixedbugs/issue11737.go
@@ -12,6 +12,6 @@
func s(x interface{}) {
switch x {
- case f: // ERROR "invalid case f \(type func\(\)\) in switch \(incomparable type\)|cannot compare"
+ case f: // ERROR "invalid case f \(type func\(\)\) in switch \(incomparable type\)|can only be compared to nil"
}
}
diff --git a/test/fixedbugs/issue14520.go b/test/fixedbugs/issue14520.go
index 0b840ff..29cc270 100644
--- a/test/fixedbugs/issue14520.go
+++ b/test/fixedbugs/issue14520.go
@@ -6,9 +6,6 @@
package f
-import /* // ERROR "import path" */ `
-bogus`
-
func f(x int /* // GC_ERROR "unexpected newline"
*/) // GCCGO_ERROR "expected .*\).*|expected declaration"
diff --git a/test/fixedbugs/issue14520a.go b/test/fixedbugs/issue14520a.go
new file mode 100644
index 0000000..bb45d7e
--- /dev/null
+++ b/test/fixedbugs/issue14520a.go
@@ -0,0 +1,10 @@
+// errorcheck
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package f
+
+import /* // ERROR "import path" */ `
+bogus`
diff --git a/test/fixedbugs/issue17038.go b/test/fixedbugs/issue17038.go
index 4d7422c..1b65ffc 100644
--- a/test/fixedbugs/issue17038.go
+++ b/test/fixedbugs/issue17038.go
@@ -6,4 +6,4 @@
package main
-const A = complex(0()) // ERROR "cannot call non-function" "not enough arguments"
+const A = complex(0()) // ERROR "cannot call non-function"
diff --git a/test/fixedbugs/issue19012.go b/test/fixedbugs/issue19012.go
index 158618a..77b2236 100644
--- a/test/fixedbugs/issue19012.go
+++ b/test/fixedbugs/issue19012.go
@@ -13,9 +13,9 @@
func f(x int, y uint) {
if true {
- return "a" > 10 // ERROR "^too many arguments to return$|return with value in function with no return|mismatched types"
+ return "a" > 10 // ERROR "^too many arguments to return$|return with value in function with no return|no result values expected|mismatched types"
}
- return "gopher" == true, 10 // ERROR "^too many arguments to return$|return with value in function with no return|mismatched types"
+ return "gopher" == true, 10 // ERROR "^too many arguments to return$|return with value in function with no return|no result values expected|mismatched types"
}
func main() {
diff --git a/test/fixedbugs/issue21979.go b/test/fixedbugs/issue21979.go
index addf786..c6575a3 100644
--- a/test/fixedbugs/issue21979.go
+++ b/test/fixedbugs/issue21979.go
@@ -7,39 +7,40 @@
package p
func f() {
- _ = bool("") // ERROR "cannot convert .. \(type untyped string\) to type bool|invalid type conversion"
- _ = bool(1) // ERROR "cannot convert 1 \(type untyped int\) to type bool|invalid type conversion"
- _ = bool(1.0) // ERROR "cannot convert 1 \(type untyped float\) to type bool|invalid type conversion"
- _ = bool(-4 + 2i) // ERROR "cannot convert -4 \+ 2i \(type untyped complex\) to type bool|invalid type conversion"
+ _ = bool("") // ERROR "cannot convert .. \(.*untyped string.*\) to type bool|invalid type conversion"
+ _ = bool(1) // ERROR "cannot convert 1 \(.*untyped int.*\) to type bool|invalid type conversion"
+ _ = bool(1.0) // ERROR "cannot convert 1.* \(.*untyped float.*\) to type bool|invalid type conversion"
+ _ = bool(-4 + 2i) // ERROR "cannot convert -4 \+ 2i \(.*untyped complex.*\) to type bool|invalid type conversion"
- _ = string(true) // ERROR "cannot convert true \(type untyped bool\) to type string|invalid type conversion"
+ _ = string(true) // ERROR "cannot convert true \(.*untyped bool.*\) to type string|invalid type conversion"
_ = string(-1)
- _ = string(1.0) // ERROR "cannot convert 1 \(type untyped float\) to type string|invalid type conversion"
- _ = string(-4 + 2i) // ERROR "cannot convert -4 \+ 2i \(type untyped complex\) to type string|invalid type conversion"
+ _ = string(1.0) // ERROR "cannot convert 1.* \(.*untyped float.*\) to type string|invalid type conversion"
+ _ = string(-4 + 2i) // ERROR "cannot convert -4 \+ 2i \(.*untyped complex.*\) to type string|invalid type conversion"
- _ = int("") // ERROR "cannot convert .. \(type untyped string\) to type int|invalid type conversion"
- _ = int(true) // ERROR "cannot convert true \(type untyped bool\) to type int|invalid type conversion"
+ _ = int("") // ERROR "cannot convert .. \(.*untyped string.*\) to type int|invalid type conversion"
+ _ = int(true) // ERROR "cannot convert true \(.*untyped bool.*\) to type int|invalid type conversion"
_ = int(-1)
_ = int(1)
_ = int(1.0)
- _ = int(-4 + 2i) // ERROR "truncated to integer"
+ _ = int(-4 + 2i) // ERROR "truncated to integer|cannot convert -4 \+ 2i \(.*untyped complex.*\) to type int"
- _ = uint("") // ERROR "cannot convert .. \(type untyped string\) to type uint|invalid type conversion"
- _ = uint(true) // ERROR "cannot convert true \(type untyped bool\) to type uint|invalid type conversion"
- _ = uint(-1) // ERROR "constant -1 overflows uint|integer constant overflow"
+ _ = uint("") // ERROR "cannot convert .. \(.*untyped string.*\) to type uint|invalid type conversion"
+ _ = uint(true) // ERROR "cannot convert true \(.*untyped bool.*\) to type uint|invalid type conversion"
+ _ = uint(-1) // ERROR "constant -1 overflows uint|integer constant overflow|cannot convert -1 \(untyped int constant\) to type uint"
_ = uint(1)
_ = uint(1.0)
- _ = uint(-4 + 2i) // ERROR "constant -4 overflows uint" "truncated to integer"
+ // types1 reports extra error "truncated to integer"
+ _ = uint(-4 + 2i) // ERROR "constant -4 overflows uint|truncated to integer|cannot convert -4 \+ 2i \(untyped complex constant.*\) to type uint"
- _ = float64("") // ERROR "cannot convert .. \(type untyped string\) to type float64|invalid type conversion"
- _ = float64(true) // ERROR "cannot convert true \(type untyped bool\) to type float64|invalid type conversion"
+ _ = float64("") // ERROR "cannot convert .. \(.*untyped string.*\) to type float64|invalid type conversion"
+ _ = float64(true) // ERROR "cannot convert true \(.*untyped bool.*\) to type float64|invalid type conversion"
_ = float64(-1)
_ = float64(1)
_ = float64(1.0)
- _ = float64(-4 + 2i) // ERROR "truncated to"
+ _ = float64(-4 + 2i) // ERROR "truncated to|cannot convert -4 \+ 2i \(.*untyped complex.*\) to type float64"
- _ = complex128("") // ERROR "cannot convert .. \(type untyped string\) to type complex128|invalid type conversion"
- _ = complex128(true) // ERROR "cannot convert true \(type untyped bool\) to type complex128|invalid type conversion"
+ _ = complex128("") // ERROR "cannot convert .. \(.*untyped string.*\) to type complex128|invalid type conversion"
+ _ = complex128(true) // ERROR "cannot convert true \(.*untyped bool.*\) to type complex128|invalid type conversion"
_ = complex128(-1)
_ = complex128(1)
_ = complex128(1.0)
diff --git a/test/fixedbugs/issue23536.go b/test/fixedbugs/issue23536.go
new file mode 100644
index 0000000..07b5033
--- /dev/null
+++ b/test/fixedbugs/issue23536.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case where a slice of a user-defined byte type (not uint8 or byte) is
+// converted to a string. Same for slice of runes.
+
+package main
+
+type MyByte byte
+
+type MyRune rune
+
+func main() {
+ var y []MyByte
+ _ = string(y)
+
+ var z []MyRune
+ _ = string(z)
+}
diff --git a/test/fixedbugs/issue23732.go b/test/fixedbugs/issue23732.go
index db2d182..79b60e2 100644
--- a/test/fixedbugs/issue23732.go
+++ b/test/fixedbugs/issue23732.go
@@ -24,19 +24,19 @@
_ = Foo{ // GCCGO_ERROR "too few expressions"
1,
2,
- 3, // GC_ERROR "too few values in Foo{...}"
- }
+ 3,
+ } // GC_ERROR "too few values in"
_ = Foo{
1,
2,
3,
- Bar{"A", "B"}, // ERROR "too many values in Bar{...}|too many expressions"
+ Bar{"A", "B"}, // ERROR "too many values in|too many expressions"
}
_ = Foo{ // GCCGO_ERROR "too few expressions"
1,
2,
- Bar{"A", "B"}, // ERROR "too many values in Bar{...}|too many expressions" "too few values in Foo{...}"
- }
+ Bar{"A", "B"}, // ERROR "too many values in|too many expressions"
+ } // GC_ERROR "too few values in"
}
diff --git a/test/fixedbugs/issue25958.go b/test/fixedbugs/issue25958.go
index 90fcee1..91358f8 100644
--- a/test/fixedbugs/issue25958.go
+++ b/test/fixedbugs/issue25958.go
@@ -11,7 +11,7 @@
func f(done chan struct{}) {
select {
- case done: // ERROR "must be receive|expected .*<-.* or .*=" "not used"
- case (chan struct{})(done): // ERROR "must be receive|expected .*<-.* or .*="
+ case done: // ERROR "must be receive|expected .*<-.* or .*=|must be send or receive|not used"
+ case (chan struct{})(done): // ERROR "must be receive|expected .*<-.* or .*=|must be send or receive"
}
}
diff --git a/test/fixedbugs/issue28079b.go b/test/fixedbugs/issue28079b.go
index 54c9db9..69d1a2f 100644
--- a/test/fixedbugs/issue28079b.go
+++ b/test/fixedbugs/issue28079b.go
@@ -10,8 +10,8 @@
import "unsafe"
-type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound|array bound is not constant"
+type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound|array bound is not constant|must be constant"
func f() {
- _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "shift of type float64|non-integer type for left operand of shift"
+ _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "shift of type float64|non-integer type for left operand of shift|must be integer"
}
diff --git a/test/fixedbugs/issue28079c.go b/test/fixedbugs/issue28079c.go
index f6954ed..dfac8d0 100644
--- a/test/fixedbugs/issue28079c.go
+++ b/test/fixedbugs/issue28079c.go
@@ -11,5 +11,5 @@
import "unsafe"
func f() {
- _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "invalid operation: .*shift of type float64.*|non-integer type for left operand of shift|shifted operand .* must be integer"
+ _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "invalid operation: .*shift of type float64.*|non-integer type for left operand of shift"
}
diff --git a/test/fixedbugs/issue28268.go b/test/fixedbugs/issue28268.go
index 59a4c57..263b2d1 100644
--- a/test/fixedbugs/issue28268.go
+++ b/test/fixedbugs/issue28268.go
@@ -16,8 +16,8 @@
type E struct{}
-func (T) b() {} // ERROR "field and method named b|redeclares struct field name"
-func (*T) E() {} // ERROR "field and method named E|redeclares struct field name"
+func (T) b() {} // ERROR "field and method named b|redeclares struct field name|field and method with the same name b"
+func (*T) E() {} // ERROR "field and method named E|redeclares struct field name|field and method with the same name E"
func _() {
var x T
diff --git a/test/fixedbugs/issue33460.go b/test/fixedbugs/issue33460.go
index d90b0a4..dff468a 100644
--- a/test/fixedbugs/issue33460.go
+++ b/test/fixedbugs/issue33460.go
@@ -18,11 +18,11 @@
func f(v int) {
switch v {
case zero, one:
- case two, one: // ERROR "previous case at LINE-1|duplicate case in switch"
+ case two, one: // ERROR "previous case at LINE-1|duplicate case .*in.* switch"
case three:
- case 3: // ERROR "previous case at LINE-1|duplicate case in switch"
- case iii: // ERROR "previous case at LINE-2|duplicate case in switch"
+ case 3: // ERROR "previous case at LINE-1|duplicate case .*in.* switch"
+ case iii: // ERROR "previous case at LINE-2|duplicate case .*in.* switch"
}
}
@@ -31,7 +31,7 @@
var _ = map[string]int{
"a": 0,
b: 1,
- "a": 2, // ERROR "previous key at LINE-2|duplicate key in map literal"
- "b": 3, // GC_ERROR "previous key at LINE-2"
- "b": 4, // GC_ERROR "previous key at LINE-3"
+ "a": 2, // ERROR "previous key at LINE-2|duplicate key.*in map literal"
+ "b": 3, // GC_ERROR "previous key at LINE-2|duplicate key.*in map literal"
+ "b": 4, // GC_ERROR "previous key at LINE-3|duplicate key.*in map literal"
}
diff --git a/test/fixedbugs/issue4215.go b/test/fixedbugs/issue4215.go
index b6ece4b..9f32f5b 100644
--- a/test/fixedbugs/issue4215.go
+++ b/test/fixedbugs/issue4215.go
@@ -11,7 +11,7 @@
}
func foo2() {
- return int(2), 2 // ERROR "too many arguments to return\n\thave \(int, number\)\n\twant \(\)|return with value in function with no return type|no result values expected"
+ return int(2), 2 // ERROR "too many (arguments to return|return values)\n\thave \(int, number\)\n\twant \(\)|return with value in function with no return type"
}
func foo3(v int) (a, b, c, d int) {
diff --git a/test/fixedbugs/issue4232.go b/test/fixedbugs/issue4232.go
index 30d1326..f49c615 100644
--- a/test/fixedbugs/issue4232.go
+++ b/test/fixedbugs/issue4232.go
@@ -11,46 +11,46 @@
func f() {
var a [10]int
- _ = a[-1] // ERROR "invalid array index -1|index out of bounds"
- _ = a[-1:] // ERROR "invalid slice index -1|index out of bounds"
- _ = a[:-1] // ERROR "invalid slice index -1|index out of bounds"
- _ = a[10] // ERROR "invalid array index 10|index out of bounds"
+ _ = a[-1] // ERROR "invalid array index -1|index out of bounds|must not be negative"
+ _ = a[-1:] // ERROR "invalid slice index -1|index out of bounds|must not be negative"
+ _ = a[:-1] // ERROR "invalid slice index -1|index out of bounds|must not be negative"
+ _ = a[10] // ERROR "invalid array index 10|index .*out of bounds"
_ = a[9:10]
_ = a[10:10]
- _ = a[9:12] // ERROR "invalid slice index 12|index out of bounds"
- _ = a[11:12] // ERROR "invalid slice index 11|index out of bounds"
- _ = a[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds"
+ _ = a[9:12] // ERROR "invalid slice index 12|index .*out of bounds"
+ _ = a[11:12] // ERROR "invalid slice index 11|index .*out of bounds"
+ _ = a[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow|invalid slice index 1 << 100|index out of bounds"
var s []int
- _ = s[-1] // ERROR "invalid slice index -1|index out of bounds"
- _ = s[-1:] // ERROR "invalid slice index -1|index out of bounds"
- _ = s[:-1] // ERROR "invalid slice index -1|index out of bounds"
+ _ = s[-1] // ERROR "invalid slice index -1|index .*out of bounds|must not be negative"
+ _ = s[-1:] // ERROR "invalid slice index -1|index .*out of bounds|must not be negative"
+ _ = s[:-1] // ERROR "invalid slice index -1|index .*out of bounds|must not be negative"
_ = s[10]
_ = s[9:10]
_ = s[10:10]
_ = s[9:12]
_ = s[11:12]
- _ = s[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds"
+ _ = s[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow|invalid slice index 1 << 100|index out of bounds"
const c = "foofoofoof"
- _ = c[-1] // ERROR "invalid string index -1|index out of bounds"
- _ = c[-1:] // ERROR "invalid slice index -1|index out of bounds"
- _ = c[:-1] // ERROR "invalid slice index -1|index out of bounds"
- _ = c[10] // ERROR "invalid string index 10|index out of bounds"
+ _ = c[-1] // ERROR "invalid string index -1|index out of bounds|must not be negative"
+ _ = c[-1:] // ERROR "invalid slice index -1|index out of bounds|must not be negative"
+ _ = c[:-1] // ERROR "invalid slice index -1|index out of bounds|must not be negative"
+ _ = c[10] // ERROR "invalid string index 10|index .*out of bounds"
_ = c[9:10]
_ = c[10:10]
- _ = c[9:12] // ERROR "invalid slice index 12|index out of bounds"
- _ = c[11:12] // ERROR "invalid slice index 11|index out of bounds"
- _ = c[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds"
+ _ = c[9:12] // ERROR "invalid slice index 12|index .*out of bounds"
+ _ = c[11:12] // ERROR "invalid slice index 11|index .*out of bounds"
+ _ = c[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow|invalid slice index 1 << 100|index out of bounds"
var t string
- _ = t[-1] // ERROR "invalid string index -1|index out of bounds"
- _ = t[-1:] // ERROR "invalid slice index -1|index out of bounds"
- _ = t[:-1] // ERROR "invalid slice index -1|index out of bounds"
+ _ = t[-1] // ERROR "invalid string index -1|index out of bounds|must not be negative"
+ _ = t[-1:] // ERROR "invalid slice index -1|index out of bounds|must not be negative"
+ _ = t[:-1] // ERROR "invalid slice index -1|index out of bounds|must not be negative"
_ = t[10]
_ = t[9:10]
_ = t[10:10]
_ = t[9:12]
_ = t[11:12]
- _ = t[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds"
+ _ = t[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow|invalid slice index 1 << 100|index out of bounds"
}
diff --git a/test/fixedbugs/issue4452.go b/test/fixedbugs/issue4452.go
index f91bd2c..c3d9b61 100644
--- a/test/fixedbugs/issue4452.go
+++ b/test/fixedbugs/issue4452.go
@@ -9,5 +9,5 @@
package main
func main() {
- _ = [...]int(4) // ERROR "\[\.\.\.\].*outside of array literal"
+ _ = [...]int(4) // ERROR "\[\.\.\.\].*outside of array literal|invalid use of \[\.\.\.\] array"
}
diff --git a/test/fixedbugs/issue4510.dir/f1.go b/test/fixedbugs/issue4510.dir/f1.go
index 7e2cffa..1217106 100644
--- a/test/fixedbugs/issue4510.dir/f1.go
+++ b/test/fixedbugs/issue4510.dir/f1.go
@@ -4,6 +4,6 @@
package p
-import "fmt" // ERROR "fmt redeclared|imported"
+import "fmt" // GCCGO_ERROR "fmt redeclared|imported"
var _ = fmt.Printf
diff --git a/test/fixedbugs/issue4510.dir/f2.go b/test/fixedbugs/issue4510.dir/f2.go
index 895fc34..1a67153 100644
--- a/test/fixedbugs/issue4510.dir/f2.go
+++ b/test/fixedbugs/issue4510.dir/f2.go
@@ -4,4 +4,4 @@
package p
-func fmt() {}
+func fmt() {} // GC_ERROR "fmt already declared through import of package"
diff --git a/test/fixedbugs/issue46234.go b/test/fixedbugs/issue46234.go
index 8e7eb8b..ed1c05c 100644
--- a/test/fixedbugs/issue46234.go
+++ b/test/fixedbugs/issue46234.go
@@ -1,5 +1,6 @@
-// buildrun -t 30
+// buildrun -t 45
+//go:build !js
// +build !js
// Copyright 2021 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue48471.go b/test/fixedbugs/issue48471.go
index 88caeed..eaf8a94 100644
--- a/test/fixedbugs/issue48471.go
+++ b/test/fixedbugs/issue48471.go
@@ -22,19 +22,34 @@
func (*T4) M(int)
+type T5 struct{}
+
+func (T5) m(int) {}
+
+type T6 struct{}
+
+func (T6) m(int) string { return "" }
+
func f(I)
func g() {
f(new(T)) // ERROR "cannot use new\(T\) \(.*type \*T\) as type I in argument to f:\n\t\*T does not implement I \(missing M method\)"
+
var i I
i = new(T) // ERROR "cannot use new\(T\) \(.*type \*T\) as type I in assignment:\n\t\*T does not implement I \(missing M method\)"
i = I(new(T)) // ERROR "cannot convert new\(T\) \(.*type \*T\) to type I:\n\t\*T does not implement I \(missing M method\)"
i = new(T2) // ERROR "cannot use new\(T2\) \(.*type \*T2\) as type I in assignment:\n\t\*T2 does not implement I \(missing M method\)\n\t\thave m\(int\)\n\t\twant M\(int\)"
- i = new(T3) // ERROR "cannot use new\(T3\) \(.*type \*T3\) as type I in assignment:\n\t\*T3 does not implement I \(wrong type for M method\)\n\t\thave M\(string\)\n\t\twant M\(int\)"
- i = T4{} // ERROR "cannot use T4\{\} \(.*type T4\) as type I in assignment:\n\tT4 does not implement I \(M method has pointer receiver\)"
- i = new(I) // ERROR "cannot use new\(I\) \(.*type \*I\) as type I in assignment:\n\t\*I does not implement I \(\*I is pointer to interface, not interface\)"
- _ = i.(*T2) // ERROR "impossible type assertion: i.\(\*T2\)\n\t\*T2 does not implement I \(missing M method\)\n\t\thave m\(int\)\n\t\twant M\(int\)"
- _ = i.(*T3) // ERROR "impossible type assertion: i.\(\*T3\)\n\t\*T3 does not implement I \(wrong type for M method\)\n\t\thave M\(string\)\n\t\twant M\(int\)"
+
+ i = new(T3) // ERROR "cannot use new\(T3\) \(.*type \*T3\) as type I in assignment:\n\t\*T3 does not implement I \(wrong type for M method\)\n\t\thave M\(string\)\n\t\twant M\(int\)"
+
+ i = T4{} // ERROR "cannot use T4\{\} \(.*type T4\) as type I in assignment:\n\tT4 does not implement I \(M method has pointer receiver\)"
+ i = new(I) // ERROR "cannot use new\(I\) \(.*type \*I\) as type I in assignment:\n\t\*I does not implement I \(type \*I is pointer to interface, not interface\)"
+
+ _ = i.(*T2) // ERROR "impossible type assertion: i.\(\*T2\)\n\t\*T2 does not implement I \(missing M method\)\n\t\thave m\(int\)\n\t\twant M\(int\)"
+ _ = i.(*T3) // ERROR "impossible type assertion: i.\(\*T3\)\n\t\*T3 does not implement I \(wrong type for M method\)\n\t\thave M\(string\)\n\t\twant M\(int\)"
+ _ = i.(T5) // ERROR ""impossible type assertion: i.\(T5\)\n\tT5 does not implement I \(missing M method\)\n\t\thave m\(int\)\n\t\twant M\(int\)"
+ _ = i.(T6) // ERROR "impossible type assertion: i.\(T6\)\n\tT6 does not implement I \(missing M method\)\n\t\thave m\(int\) string\n\t\twant M\(int\)"
+
var t *T4
t = i // ERROR "cannot use i \(variable of type I\) as type \*T4 in assignment:\n\tneed type assertion"
_ = i
diff --git a/test/fixedbugs/issue48834.go b/test/fixedbugs/issue48834.go
index cf97d13..584dfa5 100644
--- a/test/fixedbugs/issue48834.go
+++ b/test/fixedbugs/issue48834.go
@@ -20,5 +20,5 @@
}
func _() {
- return 1 // ERROR "too many arguments to return\n\thave \(number\)\n\twant \(\)|no result values expected"
+ return 1 // ERROR "too many (arguments to return|return values)\n\thave \(number\)\n\twant \(\)"
}
diff --git a/test/fixedbugs/issue50169.go b/test/fixedbugs/issue50169.go
new file mode 100644
index 0000000..30d2713
--- /dev/null
+++ b/test/fixedbugs/issue50169.go
@@ -0,0 +1,24 @@
+// compile
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ var x Value
+ NewScanner().Scan(x)
+}
+
+type Value any
+
+type Scanner interface{ Scan(any) error }
+
+func NewScanner() Scanner {
+ return &t{}
+}
+
+type t struct{}
+
+func (*t) Scan(interface{}) error { return nil }
diff --git a/test/fixedbugs/issue50190.go b/test/fixedbugs/issue50190.go
new file mode 100644
index 0000000..a5ee646
--- /dev/null
+++ b/test/fixedbugs/issue50190.go
@@ -0,0 +1,31 @@
+// run
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type Int = int
+
+type A = struct{ int }
+type B = struct{ Int }
+
+func main() {
+ var x, y interface{} = A{}, B{}
+ if x == y {
+ panic("FAIL")
+ }
+
+ {
+ type C = int32
+ x = struct{ C }{}
+ }
+ {
+ type C = uint32
+ y = struct{ C }{}
+ }
+ if x == y {
+ panic("FAIL")
+ }
+}
diff --git a/test/fixedbugs/issue50372.go b/test/fixedbugs/issue50372.go
new file mode 100644
index 0000000..30a171d
--- /dev/null
+++ b/test/fixedbugs/issue50372.go
@@ -0,0 +1,29 @@
+// errorcheck -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _(s []int) {
+ var i, j, k, l int
+ _, _, _, _ = i, j, k, l
+
+ for range s {}
+ for i = range s {}
+ for i, j = range s {}
+ for i, j, k = range s {} // ERROR "range clause permits at most two iteration variables"
+ for i, j, k, l = range s {} // ERROR "range clause permits at most two iteration variables"
+}
+
+func _(s chan int) {
+ var i, j, k, l int
+ _, _, _, _ = i, j, k, l
+
+ for range s {}
+ for i = range s {}
+ for i, j = range s {} // ERROR "range over .* permits only one iteration variable"
+ for i, j, k = range s {} // ERROR "range over .* permits only one iteration variable"
+ for i, j, k, l = range s {} // ERROR "range over .* permits only one iteration variable"
+}
diff --git a/test/fixedbugs/issue50439.go b/test/fixedbugs/issue50439.go
new file mode 100644
index 0000000..63629a5
--- /dev/null
+++ b/test/fixedbugs/issue50439.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var data []struct {
+ F string `tag`
+}
+
+var V = ([]struct{ F string })(data)
diff --git a/test/fixedbugs/issue50671.go b/test/fixedbugs/issue50671.go
new file mode 100644
index 0000000..9f4742b
--- /dev/null
+++ b/test/fixedbugs/issue50671.go
@@ -0,0 +1,35 @@
+// run
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 50671: sign extension eliminated incorrectly on MIPS64.
+
+package main
+
+//go:noinline
+func F(x int32) (float64, int64) {
+ a := float64(x)
+ b := int64(x)
+ return a, b
+}
+
+var a, b, c float64
+
+// Poison some floating point registers with non-zero high bits.
+//
+//go:noinline
+func poison(x float64) {
+ a = x - 123.45
+ b = a * 1.2
+ c = b + 3.4
+}
+
+func main() {
+ poison(333.3)
+ _, b := F(123)
+ if b != 123 {
+ panic("FAIL")
+ }
+}
diff --git a/test/fixedbugs/issue50854.go b/test/fixedbugs/issue50854.go
new file mode 100644
index 0000000..a5be919
--- /dev/null
+++ b/test/fixedbugs/issue50854.go
@@ -0,0 +1,38 @@
+// run
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// This checks for incorrect application of CMP(-x,y) -> CMN(x,y) in arm and arm64
+
+//go:noinline
+func f(p int64, x, y int64) bool { return -x <= p && p <= y }
+
+//go:noinline
+func g(p int32, x, y int32) bool { return -x <= p && p <= y }
+
+// There are some more complicated patterns involving compares and shifts, try to trigger those.
+
+//go:noinline
+func h(p int64, x, y int64) bool { return -(x<<1) <= p && p <= y }
+
+//go:noinline
+func k(p int32, x, y int32) bool { return -(1<<x) <= p && p <= y }
+
+//go:noinline
+func check(b bool) {
+ if b {
+ return
+ }
+ panic("FAILURE")
+}
+
+func main() {
+ check(f(1, -1<<63, 1<<63-1))
+ check(g(1, -1<<31, 1<<31-1))
+ check(h(1, -1<<62, 1<<63-1))
+ check(k(1, 31, 1<<31-1))
+}
diff --git a/test/fixedbugs/issue51101.go b/test/fixedbugs/issue51101.go
new file mode 100644
index 0000000..a390e50
--- /dev/null
+++ b/test/fixedbugs/issue51101.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 51101: on RISCV64, difference of two pointers
+// was marked as pointer and crashes GC.
+
+package main
+
+var a, b int
+
+func main() {
+ F(&b, &a)
+}
+
+//go:noinline
+func F(a, b *int) bool {
+ x := a == b
+ G(x)
+ y := a != b
+ return y
+}
+
+//go:noinline
+func G(bool) {
+ grow([1000]int{20})
+}
+
+func grow(x [1000]int) {
+ if x[0] != 0 {
+ x[0]--
+ grow(x)
+ }
+}
diff --git a/test/fixedbugs/issue51401.go b/test/fixedbugs/issue51401.go
new file mode 100644
index 0000000..1e8e0d0
--- /dev/null
+++ b/test/fixedbugs/issue51401.go
@@ -0,0 +1,44 @@
+// run
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 51401: bad inline info in generated interface method wrapper
+// causes infinite loop in stack unwinding.
+
+package main
+
+import "runtime"
+
+type Outer interface{ Inner }
+
+type impl struct{}
+
+func New() Outer { return &impl{} }
+
+type Inner interface {
+ DoStuff() error
+}
+
+func (a *impl) DoStuff() error {
+ return newError()
+}
+
+func newError() error {
+ stack := make([]uintptr, 50)
+ runtime.Callers(2, stack[:])
+
+ return nil
+}
+
+func main() {
+ funcs := listFuncs(New())
+ for _, f := range funcs {
+ f()
+ }
+}
+
+func listFuncs(outer Outer) []func() error {
+ return []func() error{outer.DoStuff}
+}
diff --git a/test/fixedbugs/issue51437.go b/test/fixedbugs/issue51437.go
new file mode 100644
index 0000000..3d1b9ee
--- /dev/null
+++ b/test/fixedbugs/issue51437.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T struct{}
+
+func (T) m() []T { return nil }
+
+func f(x T) {
+ for _, x := range func() []T {
+ return x.m()
+ }() {
+ _ = x
+ }
+}
diff --git a/test/fixedbugs/issue51531.go b/test/fixedbugs/issue51531.go
new file mode 100644
index 0000000..9a6a438
--- /dev/null
+++ b/test/fixedbugs/issue51531.go
@@ -0,0 +1,13 @@
+// errorcheck -G=3 -lang=go1.17
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type empty interface{}
+
+type Foo[T empty] int // ERROR "type parameter requires go1\.18 or later \(-lang was set to go1\.17; check go.mod\)"
+
+func Bar[T empty]() {} // ERROR "type parameter requires go1\.18 or later \(-lang was set to go1\.17; check go.mod\)"
diff --git a/test/fixedbugs/issue7525.go b/test/fixedbugs/issue7525.go
index fcfab72..b292d66 100644
--- a/test/fixedbugs/issue7525.go
+++ b/test/fixedbugs/issue7525.go
@@ -10,6 +10,6 @@
import "unsafe"
-var x struct {
- a [unsafe.Sizeof(x.a)]int // ERROR "array bound|typechecking loop|invalid expression"
+var x struct { // GC_ERROR "initialization loop for x"
+ a [unsafe.Sizeof(x.a)]int // GCCGO_ERROR "array bound|typechecking loop|invalid expression"
}
diff --git a/test/fixedbugs/issue7525b.go b/test/fixedbugs/issue7525b.go
index 20a62ee..139408e 100644
--- a/test/fixedbugs/issue7525b.go
+++ b/test/fixedbugs/issue7525b.go
@@ -8,6 +8,6 @@
package main
-var y struct {
- d [len(y.d)]int // ERROR "array bound|typechecking loop|invalid array"
+var y struct { // GC_ERROR "initialization loop for y"
+ d [len(y.d)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array"
}
diff --git a/test/fixedbugs/issue7525c.go b/test/fixedbugs/issue7525c.go
index f633b1c..9448159 100644
--- a/test/fixedbugs/issue7525c.go
+++ b/test/fixedbugs/issue7525c.go
@@ -8,6 +8,6 @@
package main
-var z struct {
- e [cap(z.e)]int // ERROR "array bound|typechecking loop|invalid array"
+var z struct { // GC_ERROR "initialization loop for z"
+ e [cap(z.e)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array"
}
diff --git a/test/fixedbugs/issue7525d.go b/test/fixedbugs/issue7525d.go
index 141d675..62d4659 100644
--- a/test/fixedbugs/issue7525d.go
+++ b/test/fixedbugs/issue7525d.go
@@ -10,6 +10,6 @@
import "unsafe"
-var x struct {
- b [unsafe.Offsetof(x.b)]int // ERROR "array bound|typechecking loop|invalid array"
+var x struct { // GC_ERROR "initialization loop for x"
+ b [unsafe.Offsetof(x.b)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array"
}
diff --git a/test/fixedbugs/issue7525e.go b/test/fixedbugs/issue7525e.go
index c13194c..150df07 100644
--- a/test/fixedbugs/issue7525e.go
+++ b/test/fixedbugs/issue7525e.go
@@ -10,6 +10,6 @@
import "unsafe"
-var x struct {
- c [unsafe.Alignof(x.c)]int // ERROR "array bound|typechecking loop|invalid array"
+var x struct { // GC_ERROR "initialization loop for x"
+ c [unsafe.Alignof(x.c)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array"
}
diff --git a/test/import1.go b/test/import1.go
index 2433b5f..294ef3a 100644
--- a/test/import1.go
+++ b/test/import1.go
@@ -9,11 +9,11 @@
package main
-import "bufio" // GCCGO_ERROR "previous|not used"
+import "bufio" // ERROR "previous|not used"
import bufio "os" // ERROR "redeclared|redefinition|incompatible" "imported and not used"
import (
- "fmt" // GCCGO_ERROR "previous|not used"
+ "fmt" // ERROR "previous|not used"
fmt "math" // ERROR "redeclared|redefinition|incompatible" "imported and not used: \x22math\x22 as fmt"
. "math" // GC_ERROR "imported and not used: \x22math\x22$"
)
diff --git a/test/import6.go b/test/import6.go
index c19280f..17c7dd4 100644
--- a/test/import6.go
+++ b/test/import6.go
@@ -34,5 +34,6 @@
import `\xFFFD` // ERROR "import path"
// Invalid local imports.
-import "/foo" // ERROR "import path cannot be absolute path"
-import "c:/foo" // ERROR "import path contains invalid character"
+// types2 adds extra "not used" error.
+import "/foo" // ERROR "import path cannot be absolute path|not used"
+import "c:/foo" // ERROR "import path contains invalid character|invalid character"
diff --git a/test/initializerr.go b/test/initializerr.go
index 5e2e9a9..aae740d 100644
--- a/test/initializerr.go
+++ b/test/initializerr.go
@@ -18,24 +18,24 @@
}
var x = 1
-var a1 = S { 0, X: 1 } // ERROR "mixture|undefined"
-var a2 = S { Y: 3, Z: 2, Y: 3 } // ERROR "duplicate"
-var a3 = T { S{}, 2, 3, 4, 5, 6 } // ERROR "convert|too many"
-var a4 = [5]byte{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } // ERROR "index|too many"
-var a5 = []byte { x: 2 } // ERROR "index"
-var a6 = []byte{1: 1, 2: 2, 1: 3} // ERROR "duplicate"
+var a1 = S{0, X: 1} // ERROR "mixture|undefined" "too few values"
+var a2 = S{Y: 3, Z: 2, Y: 3} // ERROR "duplicate"
+var a3 = T{S{}, 2, 3, 4, 5, 6} // ERROR "convert|too many"
+var a4 = [5]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // ERROR "index|too many"
+var a5 = []byte{x: 2} // ERROR "index"
+var a6 = []byte{1: 1, 2: 2, 1: 3} // ERROR "duplicate"
-var ok1 = S { } // should be ok
-var ok2 = T { S: ok1 } // should be ok
+var ok1 = S{} // should be ok
+var ok2 = T{S: ok1} // should be ok
// These keys can be computed at compile time but they are
// not constants as defined by the spec, so they do not trigger
// compile-time errors about duplicate key values.
// See issue 4555.
-type Key struct {X, Y int}
+type Key struct{ X, Y int }
var _ = map[Key]string{
- Key{1,2}: "hello",
- Key{1,2}: "world",
+ Key{1, 2}: "hello",
+ Key{1, 2}: "world",
}
diff --git a/test/method2.go b/test/method2.go
index 2a92136..0a497b4 100644
--- a/test/method2.go
+++ b/test/method2.go
@@ -28,7 +28,7 @@
val() int
}
-var _ = (*Val).val // ERROR "method"
+var _ = (*Val).val // ERROR "method|type \*Val is pointer to interface, not interface"
var v Val
var pv = &v
diff --git a/test/run.go b/test/run.go
index 37be958..ae5afc7 100644
--- a/test/run.go
+++ b/test/run.go
@@ -350,25 +350,25 @@
return
}
+ var failureSets []map[string]bool
+
if t.glevel == 0 && !hasGFlag && !unifiedEnabled {
- // tests should always pass when run w/o types2 (i.e., using the
- // legacy typechecker, option -G=0).
- return
- }
-
- failureSets := []map[string]bool{types2Failures}
-
- // Note: gccgo supports more 32-bit architectures than this, but
- // hopefully the 32-bit failures are fixed before this matters.
- switch goarch {
- case "386", "arm", "mips", "mipsle":
- failureSets = append(failureSets, types2Failures32Bit)
- }
-
- if unifiedEnabled {
- failureSets = append(failureSets, unifiedFailures)
+ failureSets = append(failureSets, g0Failures)
} else {
- failureSets = append(failureSets, g3Failures)
+ failureSets = append(failureSets, types2Failures)
+
+ // Note: gccgo supports more 32-bit architectures than this, but
+ // hopefully the 32-bit failures are fixed before this matters.
+ switch goarch {
+ case "386", "arm", "mips", "mipsle":
+ failureSets = append(failureSets, types2Failures32Bit)
+ }
+
+ if unifiedEnabled {
+ failureSets = append(failureSets, unifiedFailures)
+ } else {
+ failureSets = append(failureSets, g3Failures)
+ }
}
filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows
@@ -710,6 +710,13 @@
if err != nil {
t.err = fmt.Errorf("need number of seconds for -t timeout, got %s instead", args[0])
}
+ if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
+ timeoutScale, err := strconv.Atoi(s)
+ if err != nil {
+ log.Fatalf("failed to parse $GO_TEST_TIMEOUT_SCALE = %q as integer: %v", s, err)
+ }
+ tim *= timeoutScale
+ }
case "-goexperiment": // set GOEXPERIMENT environment
args = args[1:]
if goexp != "" {
@@ -834,6 +841,13 @@
if tim != 0 {
err = cmd.Start()
// This command-timeout code adapted from cmd/go/test.go
+ // Note: the Go command uses a more sophisticated timeout
+ // strategy, first sending SIGQUIT (if appropriate for the
+ // OS in question) to try to trigger a stack trace, then
+ // finally much later SIGKILL. If timeouts prove to be a
+ // common problem here, it would be worth porting over
+ // that code as well. See https://do.dev/issue/50973
+ // for more discussion.
if err == nil {
tick := time.NewTimer(time.Duration(tim) * time.Second)
done := make(chan error)
@@ -2115,47 +2129,15 @@
// List of files that the compiler cannot errorcheck with the new typechecker (compiler -G option).
// Temporary scaffolding until we pass all the tests at which point this map can be removed.
var types2Failures = setOf(
- "import1.go", // types2 reports extra errors
- "import6.go", // issue #43109
- "initializerr.go", // types2 reports extra errors
- "notinheap.go", // types2 doesn't report errors about conversions that are invalid due to //go:notinheap
- "shift1.go", // mostly just different wording, but reports two new errors.
- "typecheck.go", // invalid function is not causing errors when called
-
- "fixedbugs/bug176.go", // types2 reports all errors (pref: types2)
- "fixedbugs/bug195.go", // types2 reports slightly different (but correct) bugs
- "fixedbugs/bug228.go", // types2 doesn't run when there are syntax errors
- "fixedbugs/bug231.go", // types2 bug? (same error reported twice)
- "fixedbugs/bug255.go", // types2 reports extra errors
- "fixedbugs/bug388.go", // types2 not run due to syntax errors
- "fixedbugs/bug412.go", // types2 produces a follow-on error
-
- "fixedbugs/issue10700.go", // types2 reports ok hint, but does not match regexp
- "fixedbugs/issue11590.go", // types2 doesn't report a follow-on error (pref: types2)
- "fixedbugs/issue11610.go", // types2 not run after syntax errors
- "fixedbugs/issue11614.go", // types2 reports an extra error
- "fixedbugs/issue14520.go", // missing import path error by types2
- "fixedbugs/issue17038.go", // types2 doesn't report a follow-on error (pref: types2)
- "fixedbugs/issue18331.go", // missing error about misuse of //go:noescape (irgen needs code from noder)
- "fixedbugs/issue18419.go", // types2 reports no field or method member, but should say unexported
- "fixedbugs/issue19012.go", // multiple errors on same line
- "fixedbugs/issue20233.go", // types2 reports two instead of one error (pref: compiler)
- "fixedbugs/issue20245.go", // types2 reports two instead of one error (pref: compiler)
- "fixedbugs/issue21979.go", // types2 doesn't report a follow-on error (pref: types2)
- "fixedbugs/issue23732.go", // types2 reports different (but ok) line numbers
- "fixedbugs/issue25958.go", // types2 doesn't report a follow-on error (pref: types2)
- "fixedbugs/issue28079b.go", // types2 reports follow-on errors
- "fixedbugs/issue28268.go", // types2 reports follow-on errors
- "fixedbugs/issue31053.go", // types2 reports "unknown field" instead of "cannot refer to unexported field"
- "fixedbugs/issue33460.go", // types2 reports alternative positions in separate error
- "fixedbugs/issue4232.go", // types2 reports (correct) extra errors
- "fixedbugs/issue4452.go", // types2 reports (correct) extra errors
- "fixedbugs/issue4510.go", // types2 reports different (but ok) line numbers
- "fixedbugs/issue7525b.go", // types2 reports init cycle error on different line - ok otherwise
- "fixedbugs/issue7525c.go", // types2 reports init cycle error on different line - ok otherwise
- "fixedbugs/issue7525d.go", // types2 reports init cycle error on different line - ok otherwise
- "fixedbugs/issue7525e.go", // types2 reports init cycle error on different line - ok otherwise
- "fixedbugs/issue7525.go", // types2 reports init cycle error on different line - ok otherwise
+ "notinheap.go", // types2 doesn't report errors about conversions that are invalid due to //go:notinheap
+ "shift1.go", // types2 reports two new errors which are probably not right
+ "fixedbugs/issue10700.go", // types2 should give hint about ptr to interface
+ "fixedbugs/issue18331.go", // missing error about misuse of //go:noescape (irgen needs code from noder)
+ "fixedbugs/issue18419.go", // types2 reports no field or method member, but should say unexported
+ "fixedbugs/issue20233.go", // types2 reports two instead of one error (pref: -G=0)
+ "fixedbugs/issue20245.go", // types2 reports two instead of one error (pref: -G=0)
+ "fixedbugs/issue28268.go", // types2 reports follow-on errors (pref: -G=0)
+ "fixedbugs/issue31053.go", // types2 reports "unknown field" instead of "cannot refer to unexported field"
)
var types2Failures32Bit = setOf(
@@ -2168,6 +2150,29 @@
"typeparam/nested.go", // -G=3 doesn't support function-local types with generics
)
+// In all of these cases, -G=0 reports reasonable errors, but either -G=0 or types2
+// report extra errors, so we can't match correctly on both. We now set the patterns
+// to match correctly on all the types2 errors.
+var g0Failures = setOf(
+ "import1.go", // types2 reports extra errors
+ "initializerr.go", // types2 reports extra error
+ "typecheck.go", // types2 reports extra error at function call
+
+ "fixedbugs/bug176.go", // types2 reports all errors (pref: types2)
+ "fixedbugs/bug195.go", // types2 reports slight different errors, and an extra error
+ "fixedbugs/bug412.go", // types2 produces a follow-on error
+
+ "fixedbugs/issue11614.go", // types2 reports an extra error
+ "fixedbugs/issue17038.go", // types2 doesn't report a follow-on error (pref: types2)
+ "fixedbugs/issue23732.go", // types2 reports different (but ok) line numbers
+ "fixedbugs/issue4510.go", // types2 reports different (but ok) line numbers
+ "fixedbugs/issue7525b.go", // types2 reports init cycle error on different line - ok otherwise
+ "fixedbugs/issue7525c.go", // types2 reports init cycle error on different line - ok otherwise
+ "fixedbugs/issue7525d.go", // types2 reports init cycle error on different line - ok otherwise
+ "fixedbugs/issue7525e.go", // types2 reports init cycle error on different line - ok otherwise
+ "fixedbugs/issue7525.go", // types2 reports init cycle error on different line - ok otherwise
+)
+
var unifiedFailures = setOf(
"closure3.go", // unified IR numbers closures differently than -d=inlfuncswithclosures
"escape4.go", // unified IR can inline f5 and f6; test doesn't expect this
@@ -2176,7 +2181,6 @@
"fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape"
"fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap"
- "typeparam/issue48538.go", // assertion failure, interprets struct key as closure variable
"typeparam/issue47631.go", // unified IR can handle local type declarations
"fixedbugs/issue42058a.go", // unified IR doesn't report channel element too large
"fixedbugs/issue42058b.go", // unified IR doesn't report channel element too large
@@ -2187,6 +2191,7 @@
"typeparam/typeswitch2.go", // duplicate case failure due to stenciling
"typeparam/typeswitch3.go", // duplicate case failure due to stenciling
"typeparam/typeswitch4.go", // duplicate case failure due to stenciling
+ "typeparam/issue50552.go", // gives missing method for instantiated type
)
func setOf(keys ...string) map[string]bool {
diff --git a/test/typecheck.go b/test/typecheck.go
index 4c55d2e..f822ae9 100644
--- a/test/typecheck.go
+++ b/test/typecheck.go
@@ -17,6 +17,6 @@
}
func main() {
- mine() // GCCGO_ERROR "not enough arguments"
+ mine() // ERROR "not enough arguments"
c = mine() // ERROR "undefined.*c|not enough arguments"
}
diff --git a/test/typeparam/absdiff2.go b/test/typeparam/absdiff2.go
new file mode 100644
index 0000000..443388e
--- /dev/null
+++ b/test/typeparam/absdiff2.go
@@ -0,0 +1,135 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// absdiff example in which an Abs method is attached to a generic type, which is a
+// structure with a single field that may be a list of possible basic types.
+
+package main
+
+import (
+ "fmt"
+ "math"
+)
+
+type Numeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
+ ~float32 | ~float64 |
+ ~complex64 | ~complex128
+}
+
+// numericAbs matches a struct containing a numeric type that has an Abs method.
+type numericAbs[T Numeric] interface {
+ ~struct{ Value_ T }
+ Abs() T
+ Value() T
+}
+
+// absDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
+ d := a.Value() - b.Value()
+ dt := U{Value_: d}
+ return dt.Abs()
+}
+
+// orderedNumeric matches numeric types that support the < operator.
+type orderedNumeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
+ ~float32 | ~float64
+}
+
+// Complex matches the two complex types, which do not have a < operator.
+type Complex interface {
+ ~complex64 | ~complex128
+}
+
+// orderedAbs is a helper type that defines an Abs method for
+// a struct containing an ordered numeric type.
+type orderedAbs[T orderedNumeric] struct {
+ Value_ T
+}
+
+func (a orderedAbs[T]) Abs() T {
+ if a.Value_ < 0 {
+ return -a.Value_
+ }
+ return a.Value_
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (a orderedAbs[T]) Value() T {
+ return a.Value_
+}
+
+// complexAbs is a helper type that defines an Abs method for
+// a struct containing a complex type.
+type complexAbs[T Complex] struct {
+ Value_ T
+}
+
+func realimag(x any) (re, im float64) {
+ switch z := x.(type) {
+ case complex64:
+ re = float64(real(z))
+ im = float64(imag(z))
+ case complex128:
+ re = real(z)
+ im = imag(z)
+ default:
+ panic("unknown complex type")
+ }
+ return
+}
+
+func (a complexAbs[T]) Abs() T {
+ // TODO use direct conversion instead of realimag once #50937 is fixed
+ r, i := realimag(a.Value_)
+ // r := float64(real(a.Value))
+ // i := float64(imag(a.Value))
+ d := math.Sqrt(r*r + i*i)
+ return T(complex(d, 0))
+}
+
+func (a complexAbs[T]) Value() T {
+ return a.Value_
+}
+
+// OrderedAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of an ordered type.
+func OrderedAbsDifference[T orderedNumeric](a, b T) T {
+ return absDifference(orderedAbs[T]{a}, orderedAbs[T]{b})
+}
+
+// ComplexAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of a complex type.
+func ComplexAbsDifference[T Complex](a, b T) T {
+ return absDifference(complexAbs[T]{a}, complexAbs[T]{b})
+}
+
+func main() {
+ if got, want := OrderedAbsDifference(1.0, -2.0), 3.0; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := OrderedAbsDifference(-1.0, 2.0), 3.0; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := OrderedAbsDifference(-20, 15), 35; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+
+ if got, want := ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+}
diff --git a/test/typeparam/absdiff3.go b/test/typeparam/absdiff3.go
new file mode 100644
index 0000000..99fa6f1
--- /dev/null
+++ b/test/typeparam/absdiff3.go
@@ -0,0 +1,98 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// absdiff example using a function argument rather than attaching an
+// Abs method to a structure containing base types.
+
+package main
+
+import (
+ "fmt"
+ "math"
+)
+
+type Numeric interface {
+ OrderedNumeric | Complex
+}
+
+// absDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the abs function.
+func absDifference[T Numeric](a, b T, abs func(a T) T) T {
+ return abs(a - b)
+}
+
+// OrderedNumeric matches numeric types that support the < operator.
+type OrderedNumeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
+ ~float32 | ~float64
+}
+
+func Abs[T OrderedNumeric](a T) T {
+ if a < 0 {
+ return -a
+ }
+ return a
+}
+
+// Complex matches the two complex types, which do not have a < operator.
+type Complex interface {
+ ~complex64 | ~complex128
+}
+
+func realimag(x any) (re, im float64) {
+ switch z := x.(type) {
+ case complex64:
+ re = float64(real(z))
+ im = float64(imag(z))
+ case complex128:
+ re = real(z)
+ im = imag(z)
+ default:
+ panic("unknown complex type")
+ }
+ return
+}
+
+func ComplexAbs[T Complex](a T) T {
+ // TODO use direct conversion instead of realimag once #50937 is fixed
+ r, i := realimag(a)
+ // r := float64(real(a))
+ // i := float64(imag(a))
+ d := math.Sqrt(r*r + i*i)
+ return T(complex(d, 0))
+}
+
+// OrderedAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of an ordered type.
+func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
+ return absDifference(a, b, Abs[T])
+}
+
+// ComplexAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of a complex type.
+func ComplexAbsDifference[T Complex](a, b T) T {
+ return absDifference(a, b, ComplexAbs[T])
+}
+
+func main() {
+ if got, want := OrderedAbsDifference(1.0, -2.0), 3.0; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := OrderedAbsDifference(-1.0, 2.0), 3.0; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := OrderedAbsDifference(-20, 15), 35; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+
+ if got, want := ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+}
diff --git a/test/typeparam/absdiffimp2.dir/a.go b/test/typeparam/absdiffimp2.dir/a.go
new file mode 100644
index 0000000..dc64f2d
--- /dev/null
+++ b/test/typeparam/absdiffimp2.dir/a.go
@@ -0,0 +1,110 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import (
+ "math"
+)
+
+type Numeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
+ ~float32 | ~float64 |
+ ~complex64 | ~complex128
+}
+
+// numericAbs matches a struct containing a numeric type that has an Abs method.
+type numericAbs[T Numeric] interface {
+ ~struct{ Value_ T }
+ Abs() T
+ Value() T
+}
+
+// absDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
+ d := a.Value() - b.Value()
+ dt := U{Value_: d}
+ return dt.Abs()
+}
+
+// orderedNumeric matches numeric types that support the < operator.
+type orderedNumeric interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
+ ~float32 | ~float64
+}
+
+// Complex matches the two complex types, which do not have a < operator.
+type Complex interface {
+ ~complex64 | ~complex128
+}
+
+// orderedAbs is a helper type that defines an Abs method for
+// a struct containing an ordered numeric type.
+type orderedAbs[T orderedNumeric] struct {
+ Value_ T
+}
+
+func (a orderedAbs[T]) Abs() T {
+ if a.Value_ < 0 {
+ return -a.Value_
+ }
+ return a.Value_
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (a orderedAbs[T]) Value() T {
+ return a.Value_
+}
+
+// complexAbs is a helper type that defines an Abs method for
+// a struct containing a complex type.
+type complexAbs[T Complex] struct {
+ Value_ T
+}
+
+func realimag(x any) (re, im float64) {
+ switch z := x.(type) {
+ case complex64:
+ re = float64(real(z))
+ im = float64(imag(z))
+ case complex128:
+ re = real(z)
+ im = imag(z)
+ default:
+ panic("unknown complex type")
+ }
+ return
+}
+
+func (a complexAbs[T]) Abs() T {
+ // TODO use direct conversion instead of realimag once #50937 is fixed
+ r, i := realimag(a.Value_)
+ // r := float64(real(a.Value))
+ // i := float64(imag(a.Value))
+ d := math.Sqrt(r*r + i*i)
+ return T(complex(d, 0))
+}
+
+func (a complexAbs[T]) Value() T {
+ return a.Value_
+}
+
+// OrderedAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of an ordered type.
+func OrderedAbsDifference[T orderedNumeric](a, b T) T {
+ return absDifference(orderedAbs[T]{a}, orderedAbs[T]{b})
+}
+
+// ComplexAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of a complex type.
+func ComplexAbsDifference[T Complex](a, b T) T {
+ return absDifference(complexAbs[T]{a}, complexAbs[T]{b})
+}
diff --git a/test/typeparam/absdiffimp2.dir/main.go b/test/typeparam/absdiffimp2.dir/main.go
new file mode 100644
index 0000000..8eefdbd
--- /dev/null
+++ b/test/typeparam/absdiffimp2.dir/main.go
@@ -0,0 +1,29 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "a"
+ "fmt"
+)
+
+func main() {
+ if got, want := a.OrderedAbsDifference(1.0, -2.0), 3.0; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := a.OrderedAbsDifference(-1.0, 2.0), 3.0; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := a.OrderedAbsDifference(-20, 15), 35; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+
+ if got, want := a.ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := a.ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/absdiffimp2.go
similarity index 71%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/absdiffimp2.go
index 11dca0b..76930e5 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/absdiffimp2.go
@@ -1,9 +1,7 @@
+// rundir -G=3
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
-
-func init() {
- acceptMethodTypeParams = true
-}
+package ignored
diff --git a/test/typeparam/gencrawler.dir/a.go b/test/typeparam/gencrawler.dir/a.go
new file mode 100644
index 0000000..50d6b4a
--- /dev/null
+++ b/test/typeparam/gencrawler.dir/a.go
@@ -0,0 +1,27 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var V val[int]
+
+type val[T any] struct {
+ valx T
+}
+
+func (v *val[T]) Print() {
+ v.print1()
+}
+
+func (v *val[T]) print1() {
+ println(v.valx)
+}
+
+func (v *val[T]) fnprint1() {
+ println(v.valx)
+}
+
+func FnPrint[T any](v *val[T]) {
+ v.fnprint1()
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/gencrawler.dir/main.go
similarity index 69%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/gencrawler.dir/main.go
index 11dca0b..063de7f 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/gencrawler.dir/main.go
@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
+package main
-func init() {
- acceptMethodTypeParams = true
+import "a"
+
+func main() {
+ a.V.Print()
+ a.FnPrint(&a.V)
}
diff --git a/test/typeparam/gencrawler.go b/test/typeparam/gencrawler.go
new file mode 100644
index 0000000..7c268ae
--- /dev/null
+++ b/test/typeparam/gencrawler.go
@@ -0,0 +1,10 @@
+// rundir -G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Testing that all methods of a private generic type are exported, if a variable
+// with that type is exported.
+
+package ignored
diff --git a/test/typeparam/gencrawler.out b/test/typeparam/gencrawler.out
new file mode 100644
index 0000000..aa47d0d
--- /dev/null
+++ b/test/typeparam/gencrawler.out
@@ -0,0 +1,2 @@
+0
+0
diff --git a/test/typeparam/issue23536.go b/test/typeparam/issue23536.go
new file mode 100644
index 0000000..a4f0618
--- /dev/null
+++ b/test/typeparam/issue23536.go
@@ -0,0 +1,32 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case where a slice of a user-defined byte type (not uint8 or byte) is
+// converted to a string. Same for slice of runes.
+
+package main
+
+type MyByte byte
+
+type MyRune rune
+
+func f[T []MyByte](x T) string {
+ return string(x)
+}
+
+func g[T []MyRune](x T) string {
+ return string(x)
+}
+
+func main() {
+ var y []MyByte
+ _ = f(y)
+ _ = string(y)
+
+ var z []MyRune
+ _ = g(z)
+ _ = string(z)
+}
diff --git a/test/typeparam/issue376214.go b/test/typeparam/issue376214.go
new file mode 100644
index 0000000..8f94f41
--- /dev/null
+++ b/test/typeparam/issue376214.go
@@ -0,0 +1,20 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func add[S ~string | ~[]byte](buf *[]byte, s S) {
+ *buf = append(*buf, s...)
+}
+
+func main() {
+ var buf []byte
+ add(&buf, "foo")
+ add(&buf, []byte("bar"))
+ if string(buf) != "foobar" {
+ panic("got " + string(buf))
+ }
+}
diff --git a/test/typeparam/issue48276a.go b/test/typeparam/issue48276a.go
index 060ac3e..25e939f 100644
--- a/test/typeparam/issue48276a.go
+++ b/test/typeparam/issue48276a.go
@@ -9,7 +9,7 @@
import "fmt"
func main() {
- IsZero[interface{}]("")
+ IsZero[int](0)
}
func IsZero[T comparable](val T) bool {
diff --git a/test/typeparam/issue48276a.out b/test/typeparam/issue48276a.out
index 7e8a8a9..8f38db9 100644
--- a/test/typeparam/issue48276a.out
+++ b/test/typeparam/issue48276a.out
@@ -1 +1 @@
-<nil>:
+0:0
diff --git a/test/typeparam/issue48424.go b/test/typeparam/issue48424.go
index 3253e64..8d80911 100644
--- a/test/typeparam/issue48424.go
+++ b/test/typeparam/issue48424.go
@@ -13,14 +13,14 @@
return x
}
-func min[T int|string](x, y T) T {
+func min[T int | string](x, y T) T {
if x < y {
return x
}
return y
}
-func max[T ~float64](x, y T) T {
+func max[T ~int | ~float64](x, y T) T {
if x > y {
return x
}
@@ -48,7 +48,7 @@
// Some random type parameter lists with elided interfaces.
type (
- _ [T struct{}] struct{}
- _ [M map[K]V, K comparable, V any] struct{}
- _ [_ interface{}|int] struct{}
+ _[T struct{}] struct{}
+ _[M map[K]V, K comparable, V any] struct{}
+ _[_ interface{} | int] struct{}
)
diff --git a/test/typeparam/issue48962.dir/a.go b/test/typeparam/issue48962.dir/a.go
new file mode 100644
index 0000000..a6d2734
--- /dev/null
+++ b/test/typeparam/issue48962.dir/a.go
@@ -0,0 +1,12 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type (
+ A[P any] [10]P
+ S[P any] struct{ f P }
+ P[P any] *P
+ M[K comparable, V any] map[K]V
+)
diff --git a/test/typeparam/issue48962.dir/b.go b/test/typeparam/issue48962.dir/b.go
new file mode 100644
index 0000000..a49f55d
--- /dev/null
+++ b/test/typeparam/issue48962.dir/b.go
@@ -0,0 +1,51 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+type (
+ lA[P any] [10]P
+ lS[P any] struct{ f P }
+ lP[P any] *P
+ lM[K comparable, V any] map[K]V
+)
+
+// local cycles
+type (
+ A lA[A] // ERROR "invalid recursive type"
+ S lS[S] // ERROR "invalid recursive type"
+ P lP[P] // ok (indirection through lP)
+ M1 lM[int, M1] // ok (indirection through lM)
+ M2 lM[lA[byte], M2] // ok (indirection through lM)
+
+ A2 lA[lS[lP[A2]]] // ok (indirection through lP)
+ A3 lA[lS[lS[A3]]] // ERROR "invalid recursive type"
+)
+
+// cycles through imported types
+type (
+ Ai a.A[Ai] // ERROR "invalid recursive type"
+ Si a.S[Si] // ERROR "invalid recursive type"
+ Pi a.P[Pi] // ok (indirection through a.P)
+ M1i a.M[int, M1i] // ok (indirection through a.M)
+ M2i a.M[a.A[byte], M2i] // ok (indirection through a.M)
+
+ A2i a.A[a.S[a.P[A2i]]] // ok (indirection through a.P)
+ A3i a.A[a.S[a.S[A3i]]] // ERROR "invalid recursive type"
+
+ T2 a.S[T0[T2]] // ERROR "invalid recursive type"
+ T3 T0[Ai] // no follow-on error here
+)
+
+// test case from issue
+
+type T0[P any] struct {
+ f P
+}
+
+type T1 struct { // ERROR "invalid recursive type"
+ _ T0[T1]
+}
diff --git a/test/typeparam/issue48962.go b/test/typeparam/issue48962.go
index de9a23c..326d67b 100644
--- a/test/typeparam/issue48962.go
+++ b/test/typeparam/issue48962.go
@@ -1,15 +1,7 @@
-// errorcheck -G=3
+// errorcheckdir -G=3
-// Copyright 2021 The Go Authors. All rights reserved.
+// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package p
-
-type T0[P any] struct { // ERROR "invalid recursive type"
- f P
-}
-
-type T1 struct {
- _ T0[T1]
-}
+package ignored
diff --git a/test/typeparam/issue50109b.go b/test/typeparam/issue50109b.go
new file mode 100644
index 0000000..1d89efc
--- /dev/null
+++ b/test/typeparam/issue50109b.go
@@ -0,0 +1,29 @@
+// run -gcflags=-G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ F[any]()
+}
+
+func F[T any]() I[T] {
+ return (*S1[T])(nil)
+}
+
+type I[T any] interface{}
+
+type S1[T any] struct {
+ *S2[T]
+}
+
+type S2[T any] struct {
+ S3 *S3[T]
+}
+
+type S3[T any] struct {
+ x int
+}
diff --git a/test/typeparam/issue50121.dir/a.go b/test/typeparam/issue50121.dir/a.go
index 9918fa3..ca11b6b 100644
--- a/test/typeparam/issue50121.dir/a.go
+++ b/test/typeparam/issue50121.dir/a.go
@@ -5,11 +5,15 @@
package a
import (
- "constraints"
"math/rand"
)
-type Builder[T constraints.Integer] struct{}
+type Integer interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
+}
+
+type Builder[T Integer] struct{}
func (r Builder[T]) New() T {
return T(rand.Int())
diff --git a/test/typeparam/issue50121b.dir/a.go b/test/typeparam/issue50121b.dir/a.go
new file mode 100644
index 0000000..4ddbb6e
--- /dev/null
+++ b/test/typeparam/issue50121b.dir/a.go
@@ -0,0 +1,16 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Integer interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
+}
+
+type Builder[T Integer] struct{}
+
+func (r Builder[T]) New() T {
+ return T(42)
+}
diff --git a/test/typeparam/issue50121b.dir/b.go b/test/typeparam/issue50121b.dir/b.go
new file mode 100644
index 0000000..20f9b38
--- /dev/null
+++ b/test/typeparam/issue50121b.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import (
+ "a"
+)
+
+var IntBuilder = a.Builder[int]{}
diff --git a/test/typeparam/issue50121b.dir/c.go b/test/typeparam/issue50121b.dir/c.go
new file mode 100644
index 0000000..ee9ff9f
--- /dev/null
+++ b/test/typeparam/issue50121b.dir/c.go
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import (
+ "b"
+)
+
+func BuildInt() int {
+ return b.IntBuilder.New()
+}
diff --git a/test/typeparam/issue50121b.dir/d.go b/test/typeparam/issue50121b.dir/d.go
new file mode 100644
index 0000000..3020381
--- /dev/null
+++ b/test/typeparam/issue50121b.dir/d.go
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package d
+
+import (
+ "c"
+)
+
+func BuildInt() int {
+ return c.BuildInt()
+}
diff --git a/test/typeparam/issue50121b.dir/main.go b/test/typeparam/issue50121b.dir/main.go
new file mode 100644
index 0000000..4b6ae41
--- /dev/null
+++ b/test/typeparam/issue50121b.dir/main.go
@@ -0,0 +1,12 @@
+package main
+
+import (
+ "d"
+ "fmt"
+)
+
+func main() {
+ if got, want := d.BuildInt(), 42; got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/issue50121b.go
similarity index 71%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/issue50121b.go
index 11dca0b..76930e5 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/issue50121b.go
@@ -1,9 +1,7 @@
+// rundir -G=3
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
-
-func init() {
- acceptMethodTypeParams = true
-}
+package ignored
diff --git a/test/typeparam/issue50177.go b/test/typeparam/issue50177.go
new file mode 100644
index 0000000..5fd62ad
--- /dev/null
+++ b/test/typeparam/issue50177.go
@@ -0,0 +1,101 @@
+// compile -G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+type Fn[T any] func(T)
+type FnErr[T any] func(T) error
+
+// Test that local generic types across functions don't conflict, and they also don't
+// conflict with local non-generic types and local variables.
+func caller0() {
+ type X[T any] struct {
+ fn Fn[int]
+ }
+
+ x := X[int]{func(v int) { fmt.Println(v) }}
+ x.fn(0)
+}
+
+func caller1(val int) {
+ type X[T any] struct {
+ fn FnErr[int]
+ }
+
+ x := X[int]{func(v int) error { fmt.Println(v); return nil }}
+ x.fn(0)
+}
+
+func caller1a(val int) {
+ type X struct {
+ fn func(float64) error
+ }
+
+ x := X{func(v float64) error { fmt.Println(v); return nil }}
+ x.fn(float64(3.2))
+}
+
+func caller1b(val int) {
+ type Y struct {
+ fn func(float64) error
+ }
+
+ X := Y{func(v float64) error { fmt.Println(v); return nil }}
+ X.fn(float64(3.2))
+}
+
+// Test that local generic types within different if clauses don't conflict.
+func caller2(val int) {
+ if val > 2 {
+ type X[T any] struct {
+ fn func(v int) float64
+ }
+
+ x := X[int]{func(v int) float64 { fmt.Println(v); return 1.5 }}
+ x.fn(0)
+ } else {
+ type X[T any] struct {
+ fn func(v int) int
+ }
+ x := X[int]{func(v int) int { fmt.Println(v); return 5 }}
+ x.fn(0)
+ }
+}
+
+// Test that local generic types within different cases don't conflict with each
+// other or with local non-generic types or local variables.
+func caller3(val int) {
+ switch val {
+ case 0:
+ type X[T any] struct {
+ fn func(v int) float64
+ }
+
+ x := X[int]{func(v int) float64 { fmt.Println(v); return 1.5 }}
+ x.fn(0)
+ case 1:
+ type X[T any] struct {
+ fn func(v int) int
+ }
+ x := X[int]{func(v int) int { fmt.Println(v); return 5 }}
+ x.fn(0)
+ case 2:
+ type X struct {
+ fn func(v int) bool
+ }
+ x := X{func(v int) bool { fmt.Println(v); return false }}
+ x.fn(0)
+ case 3:
+ type Y struct {
+ fn func(v int) bool
+ }
+ X := Y{func(v int) bool { fmt.Println(v); return false }}
+ X.fn(0)
+
+ }
+}
diff --git a/test/typeparam/issue50193.go b/test/typeparam/issue50193.go
new file mode 100644
index 0000000..76de588
--- /dev/null
+++ b/test/typeparam/issue50193.go
@@ -0,0 +1,35 @@
+// run -gcflags=-G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+type Complex interface {
+ ~complex64 | ~complex128
+}
+
+func zero[T Complex]() T {
+ return T(0)
+}
+func pi[T Complex]() T {
+ return T(3.14)
+}
+func sqrtN1[T Complex]() T {
+ return T(-1i)
+}
+
+func main() {
+ fmt.Println(zero[complex128]())
+ fmt.Println(pi[complex128]())
+ fmt.Println(sqrtN1[complex128]())
+ fmt.Println(zero[complex64]())
+ fmt.Println(pi[complex64]())
+ fmt.Println(sqrtN1[complex64]())
+}
+
diff --git a/test/typeparam/issue50193.out b/test/typeparam/issue50193.out
new file mode 100644
index 0000000..6818622
--- /dev/null
+++ b/test/typeparam/issue50193.out
@@ -0,0 +1,6 @@
+(0+0i)
+(3.14+0i)
+(0-1i)
+(0+0i)
+(3.14+0i)
+(0-1i)
diff --git a/test/typeparam/issue50259.go b/test/typeparam/issue50259.go
new file mode 100644
index 0000000..59611ef
--- /dev/null
+++ b/test/typeparam/issue50259.go
@@ -0,0 +1,13 @@
+// compile -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var x T[B]
+
+type T[_ any] struct{}
+type A T[B]
+type B = T[A]
diff --git a/test/typeparam/issue50264.go b/test/typeparam/issue50264.go
new file mode 100644
index 0000000..ee3eedc
--- /dev/null
+++ b/test/typeparam/issue50264.go
@@ -0,0 +1,45 @@
+// run -gcflags=-G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type hello struct{}
+
+func main() {
+ _ = Some(hello{})
+ res := Applicative2(func(a int, b int) int {
+ return 0
+ })
+ _ = res
+}
+
+type NoneType[T any] struct{}
+
+func (r NoneType[T]) Recover() any {
+ return nil
+}
+
+type Func2[A1, A2, R any] func(a1 A1, a2 A2) R
+
+func Some[T any](v T) any {
+ _ = Some2[T](v)
+ return NoneType[T]{}.Recover()
+}
+
+//go:noinline
+func Some2[T any](v T) any {
+ return v
+}
+
+type Nil struct{}
+
+type ApplicativeFunctor2[H, HT, A1, A2, R any] struct {
+ h any
+}
+
+func Applicative2[A1, A2, R any](fn Func2[A1, A2, R]) ApplicativeFunctor2[Nil, Nil, A1, A2, R] {
+ return ApplicativeFunctor2[Nil, Nil, A1, A2, R]{Some(Nil{})}
+}
diff --git a/test/typeparam/issue50317.go b/test/typeparam/issue50317.go
new file mode 100644
index 0000000..df879c1
--- /dev/null
+++ b/test/typeparam/issue50317.go
@@ -0,0 +1,15 @@
+// errorcheck -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type S struct{}
+
+func (S) _[_ any]() {} // ERROR "method must have no type parameters"
+
+type _ interface {
+ m[_ any]() // ERROR "method must have no type parameters"
+}
diff --git a/test/typeparam/issue50417.go b/test/typeparam/issue50417.go
new file mode 100644
index 0000000..e93583f
--- /dev/null
+++ b/test/typeparam/issue50417.go
@@ -0,0 +1,146 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
+/*
+type Sf struct {
+ f int
+}
+
+func f0[P Sf](p P) {
+ _ = p.f
+ p.f = 0
+}
+
+func f0t[P ~struct{ f int }](p P) {
+ _ = p.f
+ p.f = 0
+}
+
+var _ = f0[Sf]
+var _ = f0t[Sf]
+
+func f1[P interface {
+ ~struct{ f int }
+ m()
+}](p P) {
+ _ = p.f
+ p.f = 0
+ p.m()
+}
+
+var _ = f1[Sfm]
+
+type Sm struct{}
+
+func (Sm) m() {}
+
+type Sfm struct {
+ f int
+}
+
+func (Sfm) m() {}
+
+func f2[P interface {
+ Sfm
+ m()
+}](p P) {
+ _ = p.f
+ p.f = 0
+ p.m()
+}
+
+var _ = f2[Sfm]
+
+// special case: core type is a named pointer type
+
+type PSfm *Sfm
+
+func f3[P interface{ PSfm }](p P) {
+ _ = p.f
+ p.f = 0
+}
+
+var _ = f3[PSfm]
+
+// special case: core type is an unnamed pointer type
+
+func f4[P interface{ *Sfm }](p P) {
+ _ = p.f
+ p.f = 0
+}
+
+var _ = f4[*Sfm]
+
+type A int
+type B int
+type C float64
+
+type Int interface {
+ *Sf | A
+ *Sf | B
+}
+
+func f5[P Int](p P) {
+ _ = p.f
+ p.f = 0
+}
+
+var _ = f5[*Sf]
+
+type Int2 interface {
+ *Sf | A
+ any
+ *Sf | C
+}
+
+func f6[P Int2](p P) {
+ _ = p.f
+ p.f = 0
+}
+
+var _ = f6[*Sf]
+
+type Int3 interface {
+ Sf
+ ~struct{ f int }
+}
+
+func f7[P Int3](p P) {
+ _ = p.f
+ p.f = 0
+}
+
+var _ = f7[Sf]
+
+type Em1 interface {
+ *Sf | A
+}
+
+type Em2 interface {
+ *Sf | B
+}
+
+type Int4 interface {
+ Em1
+ Em2
+ any
+}
+
+func f8[P Int4](p P) {
+ _ = p.f
+ p.f = 0
+}
+
+var _ = f8[*Sf]
+*/
diff --git a/test/typeparam/issue50417b.go b/test/typeparam/issue50417b.go
new file mode 100644
index 0000000..86e1f8a
--- /dev/null
+++ b/test/typeparam/issue50417b.go
@@ -0,0 +1,58 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
+/*
+import "fmt"
+
+type MyStruct struct {
+ b1, b2 string
+ E
+}
+
+type E struct {
+ val int
+}
+
+type C interface {
+ ~struct {
+ b1, b2 string
+ E
+ }
+}
+
+func f[T C]() T {
+ var x T = T{
+ b1: "a",
+ b2: "b",
+ }
+
+ if got, want := x.b2, "b"; got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+ x.b1 = "y"
+ x.val = 5
+
+ return x
+}
+
+func main() {
+ x := f[MyStruct]()
+ if got, want := x.b1, "y"; got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+ if got, want := x.val, 5; got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+}
+*/
diff --git a/test/typeparam/issue50419.go b/test/typeparam/issue50419.go
new file mode 100644
index 0000000..ff9d08d
--- /dev/null
+++ b/test/typeparam/issue50419.go
@@ -0,0 +1,33 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that type substitution works correctly even for a method of a generic type
+// that has multiple blank type params.
+
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ foo := &Foo[string, int]{
+ valueA: "i am a string",
+ valueB: 123,
+ }
+ if got, want := fmt.Sprintln(foo), "i am a string 123\n"; got != want {
+ panic(fmt.Sprintf("got %s, want %s", got, want))
+ }
+}
+
+type Foo[T1 any, T2 any] struct {
+ valueA T1
+ valueB T2
+}
+
+func (f *Foo[_, _]) String() string {
+ return fmt.Sprintf("%v %v", f.valueA, f.valueB)
+}
diff --git a/test/typeparam/issue50437.dir/a.go b/test/typeparam/issue50437.dir/a.go
new file mode 100644
index 0000000..4a136b5
--- /dev/null
+++ b/test/typeparam/issue50437.dir/a.go
@@ -0,0 +1,43 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type MarshalOptions struct {
+ *typedArshalers[MarshalOptions]
+}
+
+func Marshal(in interface{}) (out []byte, err error) {
+ return MarshalOptions{}.Marshal(in)
+}
+
+func (mo MarshalOptions) Marshal(in interface{}) (out []byte, err error) {
+ err = mo.MarshalNext(in)
+ return nil, err
+}
+
+func (mo MarshalOptions) MarshalNext(in interface{}) error {
+ a := new(arshaler)
+ a.marshal = func(MarshalOptions) error { return nil }
+ return a.marshal(mo)
+}
+
+type arshaler struct {
+ marshal func(MarshalOptions) error
+}
+
+type typedArshalers[Options any] struct {
+ m M
+}
+
+func (a *typedArshalers[Options]) lookup(fnc func(Options) error) (func(Options) error, bool) {
+ a.m.Load(nil)
+ return fnc, false
+}
+
+type M struct {}
+
+func (m *M) Load(key any) (value any, ok bool) {
+ return
+}
diff --git a/test/typeparam/issue50437.dir/b.go b/test/typeparam/issue50437.dir/b.go
new file mode 100644
index 0000000..afddc3f
--- /dev/null
+++ b/test/typeparam/issue50437.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func f() {
+ a.Marshal(map[int]int{})
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/issue50437.go
similarity index 71%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/issue50437.go
index 11dca0b..87b4ff4 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/issue50437.go
@@ -1,9 +1,7 @@
+// compiledir -G=3
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
-
-func init() {
- acceptMethodTypeParams = true
-}
+package ignored
diff --git a/test/typeparam/issue50481b.dir/b.go b/test/typeparam/issue50481b.dir/b.go
new file mode 100644
index 0000000..d458357
--- /dev/null
+++ b/test/typeparam/issue50481b.dir/b.go
@@ -0,0 +1,16 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "fmt"
+
+type Foo[T1 ~string, T2 ~int] struct {
+ ValueA T1
+ ValueB T2
+}
+
+func (f *Foo[_, _]) String() string {
+ return fmt.Sprintf("%v %v", f.ValueA, f.ValueB)
+}
diff --git a/test/typeparam/issue50481b.dir/main.go b/test/typeparam/issue50481b.dir/main.go
new file mode 100644
index 0000000..909d6e4
--- /dev/null
+++ b/test/typeparam/issue50481b.dir/main.go
@@ -0,0 +1,23 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that type substitution and export/import works correctly even for a method of
+// a generic type that has multiple blank type params.
+
+package main
+
+import (
+ "b"
+ "fmt"
+)
+
+func main() {
+ foo := &b.Foo[string, int]{
+ ValueA: "i am a string",
+ ValueB: 123,
+ }
+ if got, want := fmt.Sprintln(foo), "i am a string 123\n"; got != want {
+ panic(fmt.Sprintf("got %s, want %s", got, want))
+ }
+}
diff --git a/test/typeparam/issue50481b.go b/test/typeparam/issue50481b.go
new file mode 100644
index 0000000..642f4bf
--- /dev/null
+++ b/test/typeparam/issue50481b.go
@@ -0,0 +1,7 @@
+// rundir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue50481c.dir/a.go b/test/typeparam/issue50481c.dir/a.go
new file mode 100644
index 0000000..384ba23
--- /dev/null
+++ b/test/typeparam/issue50481c.dir/a.go
@@ -0,0 +1,30 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type A interface {
+ int | int64
+}
+
+type B interface {
+ string
+}
+
+type C interface {
+ String() string
+}
+
+type Myint int
+
+func (i Myint) String() string {
+ return "aa"
+}
+
+type T[P A, _ C, _ B] int
+
+func (v T[P, Q, R]) test() {
+ var r Q
+ r.String()
+}
diff --git a/test/typeparam/issue50481c.dir/main.go b/test/typeparam/issue50481c.dir/main.go
new file mode 100644
index 0000000..4661976
--- /dev/null
+++ b/test/typeparam/issue50481c.dir/main.go
@@ -0,0 +1,18 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that type substitution works and export/import works correctly even for a
+// generic type that has multiple blank type params.
+
+package main
+
+import (
+ "a"
+ "fmt"
+)
+
+func main() {
+ var x a.T[int, a.Myint, string]
+ fmt.Printf("%v\n", x)
+}
diff --git a/test/typeparam/issue50481c.go b/test/typeparam/issue50481c.go
new file mode 100644
index 0000000..642f4bf
--- /dev/null
+++ b/test/typeparam/issue50481c.go
@@ -0,0 +1,7 @@
+// rundir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue50481c.out b/test/typeparam/issue50481c.out
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/test/typeparam/issue50481c.out
@@ -0,0 +1 @@
+0
diff --git a/test/typeparam/issue50485.dir/a.go b/test/typeparam/issue50485.dir/a.go
new file mode 100644
index 0000000..3a7c71a
--- /dev/null
+++ b/test/typeparam/issue50485.dir/a.go
@@ -0,0 +1,239 @@
+package a
+
+import "fmt"
+
+type ImplicitOrd interface {
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
+ ~float32 | ~float64 |
+ ~string
+}
+
+func LessGiven[T ImplicitOrd]() Ord[T] {
+ return LessFunc[T](func(a, b T) bool {
+ return a < b
+ })
+}
+
+type Eq[T any] interface {
+ Eqv(a T, b T) bool
+}
+
+type Ord[T any] interface {
+ Eq[T]
+ Less(a T, b T) bool
+}
+
+type LessFunc[T any] func(a, b T) bool
+
+func (r LessFunc[T]) Eqv(a, b T) bool {
+ return r(a, b) == false && r(b, a) == false
+}
+
+func (r LessFunc[T]) Less(a, b T) bool {
+ return r(a, b)
+}
+
+type Option[T any] struct {
+ v *T
+}
+
+func (r Option[T]) IsDefined() bool {
+ return r.v != nil
+}
+
+func (r Option[T]) IsEmpty() bool {
+ return !r.IsDefined()
+}
+
+func (r Option[T]) Get() T {
+ return *r.v
+}
+
+func (r Option[T]) String() string {
+ if r.IsDefined() {
+ return fmt.Sprintf("Some(%v)", r.v)
+ } else {
+ return "None"
+ }
+}
+
+func (r Option[T]) OrElse(t T) T {
+ if r.IsDefined() {
+ return *r.v
+ }
+ return t
+}
+
+func (r Option[T]) Recover(f func() T) Option[T] {
+ if r.IsDefined() {
+ return r
+ }
+ t := f()
+ return Option[T]{&t}
+}
+
+type Func1[A1, R any] func(a1 A1) R
+
+type Func2[A1, A2, R any] func(a1 A1, a2 A2) R
+
+func (r Func2[A1, A2, R]) Curried() Func1[A1, Func1[A2, R]] {
+ return func(a1 A1) Func1[A2, R] {
+ return Func1[A2, R](func(a2 A2) R {
+ return r(a1, a2)
+ })
+ }
+}
+
+type HList interface {
+ sealed()
+}
+
+// Header is constrains interface type, enforce Head type of Cons is HT
+type Header[HT any] interface {
+ HList
+ Head() HT
+}
+
+// Cons means H :: T
+// zero value of Cons[H,T] is not allowed.
+// so Cons defined as interface type
+type Cons[H any, T HList] interface {
+ HList
+ Head() H
+ Tail() T
+}
+
+type Nil struct {
+}
+
+func (r Nil) Head() Nil {
+ return r
+}
+
+func (r Nil) Tail() Nil {
+ return r
+}
+
+func (r Nil) String() string {
+ return "Nil"
+}
+
+func (r Nil) sealed() {
+
+}
+
+type hlistImpl[H any, T HList] struct {
+ head H
+ tail T
+}
+
+func (r hlistImpl[H, T]) Head() H {
+ return r.head
+}
+
+func (r hlistImpl[H, T]) Tail() T {
+ return r.tail
+}
+
+func (r hlistImpl[H, T]) String() string {
+ return fmt.Sprintf("%v :: %v", r.head, r.tail)
+}
+
+func (r hlistImpl[H, T]) sealed() {
+
+}
+
+func hlist[H any, T HList](h H, t T) Cons[H, T] {
+ return hlistImpl[H, T]{h, t}
+}
+
+func Concat[H any, T HList](h H, t T) Cons[H, T] {
+ return hlist(h, t)
+}
+
+func Empty() Nil {
+ return Nil{}
+}
+func Some[T any](v T) Option[T] {
+ return Option[T]{}.Recover(func() T {
+ return v
+ })
+}
+
+func None[T any]() Option[T] {
+ return Option[T]{}
+}
+
+func Ap[T, U any](t Option[Func1[T, U]], a Option[T]) Option[U] {
+ return FlatMap(t, func(f Func1[T, U]) Option[U] {
+ return Map(a, f)
+ })
+}
+
+func Map[T, U any](opt Option[T], f func(v T) U) Option[U] {
+ return FlatMap(opt, func(v T) Option[U] {
+ return Some(f(v))
+ })
+}
+
+func FlatMap[T, U any](opt Option[T], fn func(v T) Option[U]) Option[U] {
+ if opt.IsDefined() {
+ return fn(opt.Get())
+ }
+ return None[U]()
+}
+
+type ApplicativeFunctor1[H Header[HT], HT, A, R any] struct {
+ h Option[H]
+ fn Option[Func1[A, R]]
+}
+
+func (r ApplicativeFunctor1[H, HT, A, R]) ApOption(a Option[A]) Option[R] {
+ return Ap(r.fn, a)
+}
+
+func (r ApplicativeFunctor1[H, HT, A, R]) Ap(a A) Option[R] {
+ return r.ApOption(Some(a))
+}
+
+func Applicative1[A, R any](fn Func1[A, R]) ApplicativeFunctor1[Nil, Nil, A, R] {
+ return ApplicativeFunctor1[Nil, Nil, A, R]{Some(Empty()), Some(fn)}
+}
+
+type ApplicativeFunctor2[H Header[HT], HT, A1, A2, R any] struct {
+ h Option[H]
+ fn Option[Func1[A1, Func1[A2, R]]]
+}
+
+func (r ApplicativeFunctor2[H, HT, A1, A2, R]) ApOption(a Option[A1]) ApplicativeFunctor1[Cons[A1, H], A1, A2, R] {
+
+ nh := FlatMap(r.h, func(hv H) Option[Cons[A1, H]] {
+ return Map(a, func(av A1) Cons[A1, H] {
+ return Concat(av, hv)
+ })
+ })
+
+ return ApplicativeFunctor1[Cons[A1, H], A1, A2, R]{nh, Ap(r.fn, a)}
+}
+func (r ApplicativeFunctor2[H, HT, A1, A2, R]) Ap(a A1) ApplicativeFunctor1[Cons[A1, H], A1, A2, R] {
+
+ return r.ApOption(Some(a))
+
+}
+
+func Applicative2[A1, A2, R any](fn Func2[A1, A2, R]) ApplicativeFunctor2[Nil, Nil, A1, A2, R] {
+ return ApplicativeFunctor2[Nil, Nil, A1, A2, R]{Some(Empty()), Some(fn.Curried())}
+}
+func OrdOption[T any](m Ord[T]) Ord[Option[T]] {
+ return LessFunc[Option[T]](func(t1 Option[T], t2 Option[T]) bool {
+ if !t1.IsDefined() && !t2.IsDefined() {
+ return false
+ }
+ return Applicative2(m.Less).ApOption(t1).ApOption(t2).OrElse(!t1.IsDefined())
+ })
+}
+
+func Given[T ImplicitOrd]() Ord[T] {
+ return LessGiven[T]()
+}
diff --git a/test/typeparam/issue50485.dir/main.go b/test/typeparam/issue50485.dir/main.go
new file mode 100644
index 0000000..88a765b
--- /dev/null
+++ b/test/typeparam/issue50485.dir/main.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+ "a"
+)
+
+func main() {
+ _ = a.OrdOption(a.Given[int]())
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/issue50485.go
similarity index 71%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/issue50485.go
index 11dca0b..87b4ff4 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/issue50485.go
@@ -1,9 +1,7 @@
+// compiledir -G=3
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
-
-func init() {
- acceptMethodTypeParams = true
-}
+package ignored
diff --git a/test/typeparam/issue50486.dir/goerror_fp.go b/test/typeparam/issue50486.dir/goerror_fp.go
new file mode 100644
index 0000000..fec9095
--- /dev/null
+++ b/test/typeparam/issue50486.dir/goerror_fp.go
@@ -0,0 +1,75 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goerror_fp
+
+type Seq[T any] []T
+
+func (r Seq[T]) Size() int {
+ return len(r)
+}
+
+func (r Seq[T]) Append(items ...T) Seq[T] {
+ tail := Seq[T](items)
+ ret := make(Seq[T], r.Size()+tail.Size())
+
+ for i := range r {
+ ret[i] = r[i]
+ }
+
+ for i := range tail {
+ ret[i+r.Size()] = tail[i]
+ }
+
+ return ret
+}
+
+func (r Seq[T]) Iterator() Iterator[T] {
+ idx := 0
+
+ return Iterator[T]{
+ IsHasNext: func() bool {
+ return idx < r.Size()
+ },
+ GetNext: func() T {
+ ret := r[idx]
+ idx++
+ return ret
+ },
+ }
+}
+
+type Iterator[T any] struct {
+ IsHasNext func() bool
+ GetNext func() T
+}
+
+func (r Iterator[T]) ToSeq() Seq[T] {
+ ret := Seq[T]{}
+ for r.HasNext() {
+ ret = append(ret, r.Next())
+ }
+ return ret
+}
+
+func (r Iterator[T]) Map(f func(T) any) Iterator[any] {
+ return MakeIterator(r.HasNext, func() any {
+ return f(r.Next())
+ })
+}
+
+func (r Iterator[T]) HasNext() bool {
+ return r.IsHasNext()
+}
+
+func (r Iterator[T]) Next() T {
+ return r.GetNext()
+}
+
+func MakeIterator[T any](has func() bool, next func() T) Iterator[T] {
+ return Iterator[T]{
+ IsHasNext: has,
+ GetNext: next,
+ }
+}
diff --git a/test/typeparam/issue50486.dir/main.go b/test/typeparam/issue50486.dir/main.go
new file mode 100644
index 0000000..db5f1c3
--- /dev/null
+++ b/test/typeparam/issue50486.dir/main.go
@@ -0,0 +1,16 @@
+package main
+
+import fp "goerror_fp"
+
+func Fold[A, B any](zero B, a A, f func(B, A) B) B {
+ return f(zero, a)
+}
+
+func main() {
+
+ var v any = "hello"
+ Fold(fp.Seq[any]{}, v, func(seq fp.Seq[any], v any) fp.Seq[any] {
+ return seq.Append(v)
+ })
+
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/issue50486.go
similarity index 71%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/issue50486.go
index 11dca0b..87b4ff4 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/issue50486.go
@@ -1,9 +1,7 @@
+// compiledir -G=3
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
-
-func init() {
- acceptMethodTypeParams = true
-}
+package ignored
diff --git a/test/typeparam/issue50552.dir/a.go b/test/typeparam/issue50552.dir/a.go
new file mode 100644
index 0000000..89b9bcb
--- /dev/null
+++ b/test/typeparam/issue50552.dir/a.go
@@ -0,0 +1,16 @@
+package a
+
+type Builder[T any] struct{}
+
+func (r Builder[T]) New() T {
+ var v T
+ return v
+}
+
+func (r Builder[T]) New2() T {
+ return r.New()
+}
+
+func BuildInt() int {
+ return Builder[int]{}.New()
+}
diff --git a/test/typeparam/issue50552.dir/main.go b/test/typeparam/issue50552.dir/main.go
new file mode 100644
index 0000000..047c27e
--- /dev/null
+++ b/test/typeparam/issue50552.dir/main.go
@@ -0,0 +1,20 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "a"
+ "fmt"
+)
+
+func BuildInt() int {
+ return a.BuildInt()
+}
+
+func main() {
+ if got, want := BuildInt(), 0; got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/issue50552.go
similarity index 71%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/issue50552.go
index 11dca0b..87b4ff4 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/issue50552.go
@@ -1,9 +1,7 @@
+// compiledir -G=3
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
-
-func init() {
- acceptMethodTypeParams = true
-}
+package ignored
diff --git a/test/typeparam/issue50561.dir/diameter.go b/test/typeparam/issue50561.dir/diameter.go
new file mode 100644
index 0000000..2bfe924
--- /dev/null
+++ b/test/typeparam/issue50561.dir/diameter.go
@@ -0,0 +1,86 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package diameter
+
+type Runnable interface {
+ Run()
+}
+
+// RunnableFunc is converter which converts function to Runnable interface
+type RunnableFunc func()
+
+// Run is Runnable.Run
+func (r RunnableFunc) Run() {
+ r()
+}
+
+type Executor interface {
+ ExecuteUnsafe(runnable Runnable)
+}
+
+type Promise[T any] interface {
+ Future() Future[T]
+ Success(value T) bool
+ Failure(err error) bool
+ IsCompleted() bool
+ Complete(result Try[T]) bool
+}
+
+type Future[T any] interface {
+ OnFailure(cb func(err error), ctx ...Executor)
+ OnSuccess(cb func(success T), ctx ...Executor)
+ Foreach(f func(v T), ctx ...Executor)
+ OnComplete(cb func(try Try[T]), ctx ...Executor)
+ IsCompleted() bool
+ // Value() Option[Try[T]]
+ Failed() Future[error]
+ Recover(f func(err error) T, ctx ...Executor) Future[T]
+ RecoverWith(f func(err error) Future[T], ctx ...Executor) Future[T]
+}
+
+type Try[T any] struct {
+ v *T
+ err error
+}
+
+func (r Try[T]) IsSuccess() bool {
+ return r.v != nil
+}
+
+type ByteBuffer struct {
+ pos int
+ buf []byte
+ underflow error
+}
+
+// InboundHandler is extends of uclient.NetInboundHandler
+type InboundHandler interface {
+ OriginHost() string
+ OriginRealm() string
+}
+
+type transactionID struct {
+ hopID uint32
+ endID uint32
+}
+
+type roundTripper struct {
+ promise map[transactionID]Promise[*ByteBuffer]
+ host string
+ realm string
+}
+
+func (r *roundTripper) OriginHost() string {
+ return r.host
+}
+func (r *roundTripper) OriginRealm() string {
+ return r.realm
+}
+
+func NewInboundHandler(host string, realm string, productName string) InboundHandler {
+ ret := &roundTripper{promise: make(map[transactionID]Promise[*ByteBuffer]), host: host, realm: realm}
+
+ return ret
+}
diff --git a/test/typeparam/issue50561.dir/main.go b/test/typeparam/issue50561.dir/main.go
new file mode 100644
index 0000000..bad7b6a
--- /dev/null
+++ b/test/typeparam/issue50561.dir/main.go
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "diameter"
+)
+
+func main() {
+ diameter.NewInboundHandler("hello", "world", "hi")
+}
diff --git a/test/typeparam/issue50561.go b/test/typeparam/issue50561.go
new file mode 100644
index 0000000..060a121
--- /dev/null
+++ b/test/typeparam/issue50561.go
@@ -0,0 +1,7 @@
+// compiledir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue50598.dir/a0.go b/test/typeparam/issue50598.dir/a0.go
new file mode 100644
index 0000000..61d353e
--- /dev/null
+++ b/test/typeparam/issue50598.dir/a0.go
@@ -0,0 +1,23 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a0
+
+type Builder[T any] struct{}
+
+func (r Builder[T]) New1() T {
+ var v T
+ return v
+}
+
+func (r Builder[T]) New2() T {
+ var v T
+ return v
+}
+
+type IntBuilder struct{}
+
+func (b IntBuilder) New() int {
+ return Builder[int]{}.New2()
+}
diff --git a/test/typeparam/issue50598.dir/a1.go b/test/typeparam/issue50598.dir/a1.go
new file mode 100644
index 0000000..0e63fac
--- /dev/null
+++ b/test/typeparam/issue50598.dir/a1.go
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a1
+
+import "a0"
+
+func New() int {
+ return a0.IntBuilder{}.New()
+}
diff --git a/test/typeparam/issue50598.dir/a2.go b/test/typeparam/issue50598.dir/a2.go
new file mode 100644
index 0000000..3eb5200
--- /dev/null
+++ b/test/typeparam/issue50598.dir/a2.go
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a2
+
+import "a0"
+
+func New() int {
+ return a0.Builder[int]{}.New1()
+}
diff --git a/test/typeparam/issue50598.dir/main.go b/test/typeparam/issue50598.dir/main.go
new file mode 100644
index 0000000..0fab8b6
--- /dev/null
+++ b/test/typeparam/issue50598.dir/main.go
@@ -0,0 +1,22 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+
+ "a1"
+ "a2"
+)
+
+func New() int {
+ return a1.New() + a2.New()
+}
+
+func main() {
+ if got, want := New(), 0; got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+}
diff --git a/test/typeparam/issue50598.go b/test/typeparam/issue50598.go
new file mode 100644
index 0000000..642f4bf
--- /dev/null
+++ b/test/typeparam/issue50598.go
@@ -0,0 +1,7 @@
+// rundir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue50642.go b/test/typeparam/issue50642.go
new file mode 100644
index 0000000..0cdbc36
--- /dev/null
+++ b/test/typeparam/issue50642.go
@@ -0,0 +1,63 @@
+// run -gcflags=-G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+type Temp[T any] struct {
+}
+
+var temp, temp1 any
+var ch any
+
+func (it Temp[T]) HasNext() bool {
+ var ok bool
+ temp1 = <-ch.(chan T)
+ // test conversion of T to interface{} during an OAS2RECV
+ temp, ok = <-ch.(chan T)
+ return ok
+}
+
+type MyInt int
+
+func (i MyInt) String() string {
+ return "a"
+}
+
+type Stringer interface {
+ String() string
+}
+
+type Temp2[T Stringer] struct {
+}
+
+var temp2 Stringer
+
+func (it Temp2[T]) HasNext() string {
+ var x map[int]T
+
+ var ok bool
+ // test conversion of T to Stringer during an OAS2MAPR
+ temp2, ok = x[43]
+ _ = ok
+ return temp2.String()
+}
+
+func main() {
+ ch1 := make(chan int, 2)
+ ch1 <- 5
+ ch1 <- 6
+ ch = ch1
+ iter := Temp[int]{}
+ iter.HasNext()
+
+ iter2 := Temp2[MyInt]{}
+ if got, want := iter2.HasNext(), "a"; got != want {
+ panic(fmt.Sprintf("got %v, want %v", got, want))
+ }
+
+}
diff --git a/test/typeparam/issue50690a.go b/test/typeparam/issue50690a.go
new file mode 100644
index 0000000..0f5f5e9
--- /dev/null
+++ b/test/typeparam/issue50690a.go
@@ -0,0 +1,75 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+// Numeric expresses a type constraint satisfied by any numeric type.
+type Numeric interface {
+ ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
+ ~int | ~int8 | ~int16 | ~int32 | ~int64 |
+ ~float32 | ~float64 |
+ ~complex64 | ~complex128
+}
+
+// Sum returns the sum of the provided arguments.
+func Sum[T Numeric](args ...T) T {
+ var sum T
+ for i := 0; i < len(args); i++ {
+ sum += args[i]
+ }
+ return sum
+}
+
+// Ledger is an identifiable, financial record.
+type Ledger[T ~string, K Numeric] struct {
+ // ID identifies the ledger.
+ ID_ T
+
+ // Amounts is a list of monies associated with this ledger.
+ Amounts_ []K
+
+ // SumFn is a function that can be used to sum the amounts
+ // in this ledger.
+ SumFn_ func(...K) K
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor methods instead.
+
+func (l Ledger[T, _]) ID() T { return l.ID_ }
+func (l Ledger[_, K]) Amounts() []K { return l.Amounts_ }
+func (l Ledger[_, K]) SumFn() func(...K) K { return l.SumFn_ }
+
+func PrintLedger[
+ T ~string,
+ K Numeric,
+ L interface {
+ ~struct {
+ ID_ T
+ Amounts_ []K
+ SumFn_ func(...K) K
+ }
+ ID() T
+ Amounts() []K
+ SumFn() func(...K) K
+ },
+](l L) {
+ fmt.Printf("%s has a sum of %v\n", l.ID(), l.SumFn()(l.Amounts()...))
+}
+
+func main() {
+ PrintLedger(Ledger[string, int]{
+ ID_: "fake",
+ Amounts_: []int{1, 2, 3},
+ SumFn_: Sum[int],
+ })
+}
diff --git a/test/typeparam/issue50690a.out b/test/typeparam/issue50690a.out
new file mode 100644
index 0000000..2932767
--- /dev/null
+++ b/test/typeparam/issue50690a.out
@@ -0,0 +1 @@
+fake has a sum of 6
diff --git a/test/typeparam/issue50690b.go b/test/typeparam/issue50690b.go
new file mode 100644
index 0000000..572d8eb
--- /dev/null
+++ b/test/typeparam/issue50690b.go
@@ -0,0 +1,51 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+type Printer[T ~string] struct {
+ PrintFn func(T)
+}
+
+func Print[T ~string](s T) {
+ fmt.Println(s)
+}
+
+func PrintWithPrinter[T ~string, S interface {
+ ~struct {
+ ID T
+ PrintFn_ func(T)
+ }
+ PrintFn() func(T)
+}](message T, obj S) {
+ obj.PrintFn()(message)
+}
+
+type PrintShop[T ~string] struct {
+ ID T
+ PrintFn_ func(T)
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (s PrintShop[T]) PrintFn() func(T) { return s.PrintFn_ }
+
+func main() {
+ PrintWithPrinter(
+ "Hello, world.",
+ PrintShop[string]{
+ ID: "fake",
+ PrintFn_: Print[string],
+ },
+ )
+}
diff --git a/test/typeparam/issue50690b.out b/test/typeparam/issue50690b.out
new file mode 100644
index 0000000..f75ba05
--- /dev/null
+++ b/test/typeparam/issue50690b.out
@@ -0,0 +1 @@
+Hello, world.
diff --git a/test/typeparam/issue50690c.go b/test/typeparam/issue50690c.go
new file mode 100644
index 0000000..8b87c2f
--- /dev/null
+++ b/test/typeparam/issue50690c.go
@@ -0,0 +1,50 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+type Printer[T ~string] struct {
+ PrintFn func(T)
+}
+
+func Print[T ~string](s T) {
+ fmt.Println(s)
+}
+
+func PrintWithPrinter[T ~string, S interface {
+ ~struct {
+ ID T
+ PrintFn_ func(T)
+ }
+ PrintFn() func(T)
+}](message T, obj S) {
+ obj.PrintFn()(message)
+}
+
+func main() {
+ PrintWithPrinter(
+ "Hello, world.",
+ StructWithPrinter{ID: "fake", PrintFn_: Print[string]},
+ )
+}
+
+type StructWithPrinter struct {
+ ID string
+ PrintFn_ func(string)
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (s StructWithPrinter) PrintFn() func(string) {
+ return s.PrintFn_
+}
diff --git a/test/typeparam/issue50690c.out b/test/typeparam/issue50690c.out
new file mode 100644
index 0000000..f75ba05
--- /dev/null
+++ b/test/typeparam/issue50690c.out
@@ -0,0 +1 @@
+Hello, world.
diff --git a/test/typeparam/issue50833.go b/test/typeparam/issue50833.go
new file mode 100644
index 0000000..07c1a86
--- /dev/null
+++ b/test/typeparam/issue50833.go
@@ -0,0 +1,23 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type (
+ S struct{ f int }
+ PS *S
+)
+
+func a() []*S { return []*S{{f: 1}} }
+func b() []PS { return []PS{{f: 1}} }
+
+func c[P *S]() []P { return []P{{f: 1}} }
+func d[P PS]() []P { return []P{{f: 1}} }
+
+func main() {
+ c[*S]()
+ d[PS]()
+}
diff --git a/test/typeparam/issue50841.dir/a.go b/test/typeparam/issue50841.dir/a.go
new file mode 100644
index 0000000..37e0233
--- /dev/null
+++ b/test/typeparam/issue50841.dir/a.go
@@ -0,0 +1,22 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func Marshal[foobar any]() {
+ _ = NewEncoder[foobar]()
+}
+
+func NewEncoder[foobar any]() *Encoder[foobar] {
+ return nil
+}
+
+type Encoder[foobar any] struct {
+}
+
+func (e *Encoder[foobar]) EncodeToken(t Token[foobar]) {
+
+}
+
+type Token[foobar any] any
diff --git a/test/typeparam/issue50841.dir/b.go b/test/typeparam/issue50841.dir/b.go
new file mode 100644
index 0000000..f2f7022
--- /dev/null
+++ b/test/typeparam/issue50841.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+func F() {
+ a.Marshal[int]()
+}
diff --git a/test/typeparam/issue50841.go b/test/typeparam/issue50841.go
new file mode 100644
index 0000000..060a121
--- /dev/null
+++ b/test/typeparam/issue50841.go
@@ -0,0 +1,7 @@
+// compiledir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue50993.go b/test/typeparam/issue50993.go
new file mode 100644
index 0000000..39bdba0
--- /dev/null
+++ b/test/typeparam/issue50993.go
@@ -0,0 +1,35 @@
+// compile -G=3 -d=checkptr
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "sync/atomic"
+ "unsafe"
+)
+
+type Node[T any] struct {
+ Next *Node[T]
+ // Prev *Node[T]
+}
+
+func LoadPointer[T any](addr **T) (val *T) {
+ return (*T)(
+ atomic.LoadPointer(
+ (*unsafe.Pointer)(unsafe.Pointer(addr)),
+ ))
+}
+
+func (q *Node[T]) Pop() {
+ var tail, head *Node[T]
+ if head == LoadPointer(&tail) {
+ }
+}
+
+func main() {
+ ch := Node[uint64]{}
+ ch.Pop()
+}
diff --git a/test/typeparam/issue51219.dir/a.go b/test/typeparam/issue51219.dir/a.go
new file mode 100644
index 0000000..29670df
--- /dev/null
+++ b/test/typeparam/issue51219.dir/a.go
@@ -0,0 +1,20 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+// Type I is the first basic test for the issue, which relates to a type that is recursive
+// via a type constraint. (In this test, I -> IConstraint -> MyStruct -> I.)
+type JsonRaw []byte
+
+type MyStruct struct {
+ x *I[JsonRaw]
+}
+
+type IConstraint interface {
+ JsonRaw | MyStruct
+}
+
+type I[T IConstraint] struct {
+}
diff --git a/test/typeparam/issue51219.dir/main.go b/test/typeparam/issue51219.dir/main.go
new file mode 100644
index 0000000..999b4a9
--- /dev/null
+++ b/test/typeparam/issue51219.dir/main.go
@@ -0,0 +1,16 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "a"
+ "fmt"
+)
+
+func main() {
+ var x a.I[a.JsonRaw]
+
+ fmt.Printf("%v\n", x)
+}
diff --git a/test/typeparam/issue51219.go b/test/typeparam/issue51219.go
new file mode 100644
index 0000000..642f4bf
--- /dev/null
+++ b/test/typeparam/issue51219.go
@@ -0,0 +1,7 @@
+// rundir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue51219.out b/test/typeparam/issue51219.out
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/test/typeparam/issue51219.out
@@ -0,0 +1 @@
+{}
diff --git a/test/typeparam/issue51219b.dir/a.go b/test/typeparam/issue51219b.dir/a.go
new file mode 100644
index 0000000..1904940
--- /dev/null
+++ b/test/typeparam/issue51219b.dir/a.go
@@ -0,0 +1,37 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Interaction[DataT InteractionDataConstraint] struct {
+}
+
+type InteractionDataConstraint interface {
+ []byte |
+ UserCommandInteractionData
+}
+
+type UserCommandInteractionData struct {
+ resolvedInteractionWithOptions
+}
+
+type resolvedInteractionWithOptions struct {
+ Resolved Resolved `json:"resolved,omitempty"`
+}
+
+type Resolved struct {
+ Users ResolvedData[User] `json:"users,omitempty"`
+}
+
+type ResolvedData[T ResolvedDataConstraint] map[uint64]T
+
+type ResolvedDataConstraint interface {
+ User | Message
+}
+
+type User struct{}
+
+type Message struct {
+ Interaction *Interaction[[]byte] `json:"interaction,omitempty"`
+}
diff --git a/test/typeparam/issue51219b.dir/b.go b/test/typeparam/issue51219b.dir/b.go
new file mode 100644
index 0000000..8413d66
--- /dev/null
+++ b/test/typeparam/issue51219b.dir/b.go
@@ -0,0 +1,14 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import (
+ "./a"
+)
+
+// InteractionRequest is an incoming request Interaction
+type InteractionRequest[T a.InteractionDataConstraint] struct {
+ a.Interaction[T]
+}
diff --git a/test/typeparam/issue51219b.dir/p.go b/test/typeparam/issue51219b.dir/p.go
new file mode 100644
index 0000000..9f8b840
--- /dev/null
+++ b/test/typeparam/issue51219b.dir/p.go
@@ -0,0 +1,14 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import (
+ "./b"
+)
+
+// ResponseWriterMock mocks corde's ResponseWriter interface
+type ResponseWriterMock struct {
+ x b.InteractionRequest[[]byte]
+}
diff --git a/test/typeparam/issue51219b.go b/test/typeparam/issue51219b.go
new file mode 100644
index 0000000..060a121
--- /dev/null
+++ b/test/typeparam/issue51219b.go
@@ -0,0 +1,7 @@
+// compiledir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue51232.go b/test/typeparam/issue51232.go
new file mode 100644
index 0000000..4e9d68c
--- /dev/null
+++ b/test/typeparam/issue51232.go
@@ -0,0 +1,31 @@
+// errorcheck -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type RC[RG any] interface {
+ ~[]RG
+}
+
+type Fn[RCT RC[RG], RG any] func(RCT)
+
+type F[RCT RC[RG], RG any] interface {
+ Fn() Fn[RCT] // ERROR "got 1 arguments"
+}
+
+type concreteF[RCT RC[RG], RG any] struct {
+ makeFn func() Fn[RCT] // ERROR "got 1 arguments"
+}
+
+func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { // ERROR "got 1 arguments"
+ return c.makeFn()
+}
+
+func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] { // ERROR "got 1 arguments"
+ return &concreteF[RCT]{ // ERROR "cannot use" "got 1 arguments"
+ makeFn: nil,
+ }
+}
diff --git a/test/typeparam/issue51233.go b/test/typeparam/issue51233.go
new file mode 100644
index 0000000..e6aabf3
--- /dev/null
+++ b/test/typeparam/issue51233.go
@@ -0,0 +1,28 @@
+// errorcheck -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package p
+
+// As of issue #51527, type-type inference has been disabled.
+
+type RC[RG any] interface {
+ ~[]RG
+}
+
+type Fn[RCT RC[RG], RG any] func(RCT)
+
+type FFn[RCT RC[RG], RG any] func() Fn[RCT] // ERROR "got 1 arguments"
+
+type F[RCT RC[RG], RG any] interface {
+ Fn() Fn[RCT] // ERROR "got 1 arguments"
+}
+
+type concreteF[RCT RC[RG], RG any] struct {
+ makeFn FFn[RCT] // ERROR "got 1 arguments"
+}
+
+func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { // ERROR "got 1 arguments"
+ return c.makeFn()
+}
diff --git a/test/typeparam/issue51236.go b/test/typeparam/issue51236.go
new file mode 100644
index 0000000..779c74e
--- /dev/null
+++ b/test/typeparam/issue51236.go
@@ -0,0 +1,22 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type I interface {
+ []byte
+}
+
+func F[T I]() {
+ var t T
+ explodes(t)
+}
+
+func explodes(b []byte) {}
+
+func main() {
+
+}
diff --git a/test/typeparam/issue51245.go b/test/typeparam/issue51245.go
new file mode 100644
index 0000000..bd4f7c5
--- /dev/null
+++ b/test/typeparam/issue51245.go
@@ -0,0 +1,16 @@
+// build -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T[P any] int
+const C T[int] = 3
+
+type T2 int
+const C2 T2 = 9
+
+func main() {
+}
diff --git a/test/typeparam/issue51250a.dir/a.go b/test/typeparam/issue51250a.dir/a.go
new file mode 100644
index 0000000..12dd60a
--- /dev/null
+++ b/test/typeparam/issue51250a.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type G[T any] struct {
+ x T
+}
diff --git a/test/typeparam/issue51250a.dir/b.go b/test/typeparam/issue51250a.dir/b.go
new file mode 100644
index 0000000..114c9f8
--- /dev/null
+++ b/test/typeparam/issue51250a.dir/b.go
@@ -0,0 +1,24 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+type T struct { a int }
+
+var I interface{} = a.G[T]{}
+
+//go:noinline
+func F(x interface{}) {
+ switch x.(type) {
+ case a.G[T]:
+ case int:
+ panic("bad")
+ case float64:
+ panic("bad")
+ default:
+ panic("bad")
+ }
+}
diff --git a/test/typeparam/issue51250a.dir/main.go b/test/typeparam/issue51250a.dir/main.go
new file mode 100644
index 0000000..45288be
--- /dev/null
+++ b/test/typeparam/issue51250a.dir/main.go
@@ -0,0 +1,24 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "./a"
+ "./b"
+)
+
+func main() {
+ switch b.I.(type) {
+ case a.G[b.T]:
+ case int:
+ panic("bad")
+ case float64:
+ panic("bad")
+ default:
+ panic("bad")
+ }
+
+ b.F(a.G[b.T]{})
+}
diff --git a/test/typeparam/issue51250a.go b/test/typeparam/issue51250a.go
new file mode 100644
index 0000000..aefbe67
--- /dev/null
+++ b/test/typeparam/issue51250a.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue51303.go b/test/typeparam/issue51303.go
new file mode 100644
index 0000000..5f4bdc0
--- /dev/null
+++ b/test/typeparam/issue51303.go
@@ -0,0 +1,65 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ x := [][]int{{1}}
+ y := [][]int{{2, 3}}
+ IntersectSS(x, y)
+}
+
+type list[E any] interface {
+ ~[]E
+ Equal(x, y E) bool
+}
+
+// ss is a set of sets
+type ss[E comparable, T []E] []T
+
+func (ss[E, T]) Equal(a, b T) bool {
+ return SetEq(a, b)
+}
+
+func IntersectSS[E comparable](x, y [][]E) [][]E {
+ return IntersectT[[]E, ss[E, []E]](ss[E, []E](x), ss[E, []E](y))
+}
+
+func IntersectT[E any, L list[E]](x, y L) L {
+ var z L
+outer:
+ for _, xe := range x {
+ fmt.Println("xe", xe)
+ for _, ye := range y {
+ fmt.Println("ye", ye)
+ fmt.Println("x", x)
+ if x.Equal(xe, ye) {
+ fmt.Println("appending")
+ z = append(z, xe)
+ continue outer
+ }
+ }
+ }
+ return z
+}
+
+func SetEq[S []E, E comparable](x, y S) bool {
+ fmt.Println("SetEq", x, y)
+outer:
+ for _, xe := range x {
+ for _, ye := range y {
+ if xe == ye {
+ continue outer
+ }
+ }
+ return false // xs wasn't found in y
+ }
+ return true
+}
diff --git a/test/typeparam/issue51303.out b/test/typeparam/issue51303.out
new file mode 100644
index 0000000..34b3be3
--- /dev/null
+++ b/test/typeparam/issue51303.out
@@ -0,0 +1,4 @@
+xe [1]
+ye [2 3]
+x [[1]]
+SetEq [1] [2 3]
diff --git a/test/typeparam/issue51355.go b/test/typeparam/issue51355.go
new file mode 100644
index 0000000..15ffa4b
--- /dev/null
+++ b/test/typeparam/issue51355.go
@@ -0,0 +1,31 @@
+// compile -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type Cache[E comparable] struct {
+ adder func(...E)
+}
+
+func New[E comparable]() *Cache[E] {
+ c := &Cache[E]{}
+
+ c.adder = func(elements ...E) {
+ for _, value := range elements {
+ value := value
+ go func() {
+ println(value)
+ }()
+ }
+ }
+
+ return c
+}
+
+func main() {
+ c := New[string]()
+ c.adder("test")
+}
diff --git a/test/typeparam/issue51367.dir/a.go b/test/typeparam/issue51367.dir/a.go
new file mode 100644
index 0000000..be0c3b0
--- /dev/null
+++ b/test/typeparam/issue51367.dir/a.go
@@ -0,0 +1,14 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type A[T any] struct{}
+
+func (_ A[T]) Method() {}
+
+func DoSomething[P any]() {
+ a := A[*byte]{}
+ a.Method()
+}
diff --git a/test/typeparam/issue51367.dir/main.go b/test/typeparam/issue51367.dir/main.go
new file mode 100644
index 0000000..64273d3
--- /dev/null
+++ b/test/typeparam/issue51367.dir/main.go
@@ -0,0 +1,13 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "a"
+)
+
+func main() {
+ a.DoSomething[byte]()
+}
diff --git a/test/typeparam/issue51367.go b/test/typeparam/issue51367.go
new file mode 100644
index 0000000..642f4bf
--- /dev/null
+++ b/test/typeparam/issue51367.go
@@ -0,0 +1,7 @@
+// rundir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue51423.dir/a.go b/test/typeparam/issue51423.dir/a.go
new file mode 100644
index 0000000..e824d0e
--- /dev/null
+++ b/test/typeparam/issue51423.dir/a.go
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Comparator[T any] func(v1, v2 T) int
+
+func CompareInt[T ~int](a, b T) int {
+ if a < b {
+ return -1
+ }
+ if a == b {
+ return 0
+ }
+ return 1
+}
diff --git a/test/typeparam/issue51423.dir/b.go b/test/typeparam/issue51423.dir/b.go
new file mode 100644
index 0000000..2bad19f
--- /dev/null
+++ b/test/typeparam/issue51423.dir/b.go
@@ -0,0 +1,11 @@
+package b
+
+import "./a"
+
+func C() a.Comparator[int] {
+ return a.CompareInt[int]
+}
+
+func main() {
+ _ = C()(1, 2)
+}
diff --git a/test/typeparam/issue51423.go b/test/typeparam/issue51423.go
new file mode 100644
index 0000000..060a121
--- /dev/null
+++ b/test/typeparam/issue51423.go
@@ -0,0 +1,7 @@
+// compiledir -G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/typeparam/issue51522a.go b/test/typeparam/issue51522a.go
new file mode 100644
index 0000000..31ce4bf
--- /dev/null
+++ b/test/typeparam/issue51522a.go
@@ -0,0 +1,42 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package main
+
+
+func f[T comparable](i any) {
+ var t T
+
+ if i != t {
+ println("FAIL: if i != t")
+ }
+}
+
+type myint int
+
+func (m myint) foo() {
+}
+
+type fooer interface {
+ foo()
+}
+
+type comparableFoo interface {
+ comparable
+ foo()
+}
+
+func g[T comparableFoo](i fooer) {
+ var t T
+
+ if i != t {
+ println("FAIL: if i != t")
+ }
+}
+
+func main() {
+ f[int](int(0))
+ g[myint](myint(0))
+}
diff --git a/test/typeparam/issue51522b.go b/test/typeparam/issue51522b.go
new file mode 100644
index 0000000..47de578
--- /dev/null
+++ b/test/typeparam/issue51522b.go
@@ -0,0 +1,62 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func f[T comparable](i any) {
+ var t T
+
+ switch i {
+ case t:
+ // ok
+ default:
+ println("FAIL: switch i")
+ }
+
+ switch t {
+ case i:
+ // ok
+ default:
+ println("FAIL: switch t")
+ }
+}
+
+type myint int
+
+func (m myint) foo() {
+}
+
+type fooer interface {
+ foo()
+}
+
+type comparableFoo interface {
+ comparable
+ foo()
+}
+
+func g[T comparableFoo](i fooer) {
+ var t T
+
+ switch i {
+ case t:
+ // ok
+ default:
+ println("FAIL: switch i")
+ }
+
+ switch t {
+ case i:
+ // ok
+ default:
+ println("FAIL: switch t")
+ }
+}
+
+func main() {
+ f[int](0)
+ g[myint](myint(0))
+}
diff --git a/test/typeparam/settable.go b/test/typeparam/settable.go
index 412023b..6179ae0 100644
--- a/test/typeparam/settable.go
+++ b/test/typeparam/settable.go
@@ -15,7 +15,7 @@
type Setter[B any] interface {
Set(string)
- ~*B
+ *B
}
// Takes two type parameters where PT = *T
diff --git a/test/typeparam/structinit.dir/a.go b/test/typeparam/structinit.dir/a.go
new file mode 100644
index 0000000..c76d155
--- /dev/null
+++ b/test/typeparam/structinit.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type S[T any] struct {
+}
+
+func (b *S[T]) build() *X[T] {
+ return &X[T]{f:0}
+}
+type X[T any] struct {
+ f int
+}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/structinit.dir/b.go
similarity index 72%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/structinit.dir/b.go
index 11dca0b..40a929b 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/structinit.dir/b.go
@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
+package b
-func init() {
- acceptMethodTypeParams = true
+import "./a"
+
+func B() {
+ var x a.S[int]
+ _ = x
}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/structinit.dir/main.go
similarity index 72%
rename from src/cmd/compile/internal/types2/types_test.go
rename to test/typeparam/structinit.dir/main.go
index 11dca0b..c564171 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/structinit.dir/main.go
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
+package main
-func init() {
- acceptMethodTypeParams = true
+import "./b"
+
+func main() {
+ b.B()
}
diff --git a/src/cmd/compile/internal/types2/types_test.go b/test/typeparam/structinit.go
similarity index 71%
copy from src/cmd/compile/internal/types2/types_test.go
copy to test/typeparam/structinit.go
index 11dca0b..76930e5 100644
--- a/src/cmd/compile/internal/types2/types_test.go
+++ b/test/typeparam/structinit.go
@@ -1,9 +1,7 @@
+// rundir -G=3
+
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package types2
-
-func init() {
- acceptMethodTypeParams = true
-}
+package ignored
diff --git a/test/typeparam/typelist.go b/test/typeparam/typelist.go
index 34ea4b8..c82cb5f 100644
--- a/test/typeparam/typelist.go
+++ b/test/typeparam/typelist.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file tests type lists & structural constraints.
+// This file tests type lists & constraints with core types.
// Note: This test has been adjusted to use the new
// type set notation rather than type lists.
@@ -30,28 +30,28 @@
var _ T = 42
var _ T = T(myint(42))
}
+
// TODO: put this type declaration back inside the above function when issue 47631 is fixed.
type myint int
-// Indexing a generic type which has a structural contraints to be an array.
+// Indexing a generic type which has a an array as core type.
func _[T interface{ ~[10]int }](x T) {
_ = x[9] // ok
}
-// Dereference of a generic type which has a structural contraint to be a pointer.
+// Dereference of a generic type which has a pointer as core type.
func _[T interface{ ~*int }](p T) int {
return *p
}
-// Channel send and receive on a generic type which has a structural constraint to
-// be a channel.
+// Channel send and receive on a generic type which has a channel as core type.
func _[T interface{ ~chan int }](ch T) int {
// This would deadlock if executed (but ok for a compile test)
ch <- 0
return <-ch
}
-// Calling of a generic type which has a structural constraint to be a function.
+// Calling of a generic type which has a function as core type.
func _[T interface{ ~func() }](f T) {
f()
go f()
@@ -62,7 +62,7 @@
return f("hello")
}
-// Map access of a generic type which has a structural constraint to be a map.
+// Map access of a generic type which has a map as core type.
func _[V any, T interface{ ~map[string]V }](p T) V {
return p["test"]
}
@@ -89,7 +89,7 @@
}
*/
-func f2[A any, B interface{ ~[]A }](_ A, _ B) {}
+func f2[A any, B interface{ []A }](_ A, _ B) {}
func f2x() {
f := f2[byte]
f(byte(0), []byte{})
@@ -109,7 +109,7 @@
}
*/
-func f4[A any, B interface{ ~[]C }, C interface{ ~*A }](_ A, _ B, c C) {}
+func f4[A any, B interface{ []C }, C interface{ *A }](_ A, _ B, c C) {}
func f4x() {
f := f4[int]
var x int
@@ -118,11 +118,13 @@
}
func f5[A interface {
- ~struct {
+ struct {
b B
c C
}
-}, B any, C interface{ ~*B }](x B) A { panic(0) }
+}, B any, C interface{ *B }](x B) A {
+ panic(0)
+}
func f5x() {
x := f5(1.2)
var _ float64 = x.b