[dev.boringcrypto.go1.18] all: merge go1.18 into dev.boringcrypto.go1.18

Change-Id: Ib2bfa4940b7b054d54f8ee998c63beb32c6afd51
This commit is contained in:
Heschi Kreinick 2022-03-15 12:16:46 -04:00
commit 0622ea4d90
405 changed files with 8575 additions and 3182 deletions

View File

@ -120,6 +120,7 @@ Alex Kohler <alexjohnkohler@gmail.com>
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 Klauer <Alexander.Klauer@googlemail.com>
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 Polcyn <apolcyn@google.com>
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 @@ Alok Menghrajani <alok.menghrajani@gmail.com>
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 @@ Anatol Pomozov <anatol.pomozov@gmail.com>
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 Gerrand <adg@golang.org>
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 Stormont <astormont@racktopsystems.com>
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 Bibiano <antbbn@gmail.com>
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 @@ Apisak Darakananda <pongad@gmail.com>
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 @@ Arnaud Ysmal <arnaud.ysmal@gmail.com>
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 @@ Balaram Makam <bmakam.qdt@qualcommdatacenter.com>
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 @@ Benny Siegert <bsiegert@gmail.com>
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 Ketelsen <bketelsen@gmail.com>
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 Kenney <charlesc.kenney@gmail.com>
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 @@ Cuong Manh Le <cuong@orijtech.com>
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 Langner <s8572327@gmail.com>
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 Mottl <dmitry.mottl@gmail.com>
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 Herbison <djherbis@gmail.com>
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 @@ Erin Masatsugu <erin.masatsugu@gmail.com>
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 @@ Evgeniy Polyakov <zbr@ioremap.net>
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 @@ Firmansyah Adiputra <frm.adiputra@gmail.com>
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 @@ Geon Kim <geon0250@gmail.com>
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 @fatedier (7346661) <fatedier@gmail.com>
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 @micnncim (21333876) <micnncim@gmail.com>
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 @povsister (11040951) <pov@mahou-shoujo.moe>
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 @unbyte (5772358) <i@shangyes.net>
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 Garnier <guilherme.garnier@gmail.com>
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 @@ Hang Qian <hangqian90@gmail.com>
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 @@ Igor Zhilianin <igor.zhilianin@gmail.com>
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 @@ Jaana Burcu Dogan <jbd@google.com> <jbd@golang.org> <burcujdogan@gmail.com>
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 @@ Jacob Walker <jacobwalker0814@gmail.com>
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 Eady <jmeady@google.com>
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 de Klerk <deklerk@google.com>
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 Johnson <jrjohnson@google.com>
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 @@ Jesús Espino <jespinog@gmail.com>
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 @@ Jingcheng Zhang <diogin@gmail.com>
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 Euphrosine <proppy@google.com>
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 Howard Palevich <jack.palevich@gmail.com>
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 @@ Jordan Rupprecht <rupprecht@google.com>
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 @@ Keyuan Li <keyuanli123@gmail.com>
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 @@ Leonel Quinteros <leonel.quinteros@gmail.com>
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 Adams <mark@markadams.me>
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 Hoefling <martin.hoefling@gmx.de>
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 Denton <mdenton@skyportsystems.com>
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 Bohuslávek <mbohuslavek@gmail.com>
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 Solomon <msolo@gmail.com>
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 @@ Moritz Fain <moritz@fain.io>
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 Miyake <nmiyake@users.noreply.github.com>
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 @@ Noah Santschi-Cooney <noah@santschi-cooney.ch>
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 Tan <otan@cockroachlabs.com>
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 Bernstein <ori@eigenstate.org>
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 Pelletier <pp.pelletier@gmail.com>
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 @@ Paul Wankadia <junyer@google.com>
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 @@ Pavlo Sumkin <ymkins@gmail.com>
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 @@ Rhys Hiltner <rhys@justin.tv>
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 Hudson <rlh@golang.org>
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 Norman <rob.norman@infinitycloud.com>
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 @@ Roger Peppe <rogpeppe@gmail.com>
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 Canty <jrcanty@gmail.com>
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 @@ Sami Pönkänen <sami.ponkanen@gmail.com>
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 @@ Shaba Abhiram <shabarivas.abhiram@gmail.com>
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 Drake <simondrake1990@gmail.com>
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 @@ Suharsh Sivakumar <suharshs@google.com>
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 Symborski <thomas.symborski@gmail.com>
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 @@ Vladimir Varankin <nek.narqo@gmail.com>
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 Guangjing <vcc.163@gmail.com>
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 @@ Yuichi Nishiwaki <yuichi.nishiwaki@gmail.com>
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 Gershman <zachgersh@gmail.com>
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 @@ Zhang Boyang <zhangboyang.id@gmail.com>
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>

View File

@ -165,8 +165,8 @@ pkg reflect, method (Value) FieldByIndexErr([]int) (Value, error)
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

View File

@ -1,2 +1,2 @@
branch: dev.boringcrypto
branch: dev.boringcrypto.go1.18
parent-branch: master

View File

@ -84,7 +84,7 @@ Do not send CLs removing the interior tags from such phrases.
<li>
The new
<a href="/ref/spec#Predeclared_identifiers">predeclared identifier</a>
<code>comparable</code> is an interface the denotes the set of all types which can be
<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>
@ -135,9 +135,19 @@ Do not send CLs removing the interior tags from such phrases.
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
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>
@ -182,7 +192,7 @@ Do not send CLs removing the interior tags from such phrases.
<p><!-- CL 349595 -->
Go 1.18 introduces the new <code>GOAMD64</code> environment variable, which selects at compile time
a mininum target version of the AMD64 architecture. Allowed values are <code>v1</code>,
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 can be found
@ -199,6 +209,12 @@ Do not send CLs removing the interior tags from such phrases.
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 -->
@ -250,6 +266,8 @@ Do not send CLs removing the interior tags from such phrases.
<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
@ -269,9 +287,25 @@ Do not send CLs removing the interior tags from such phrases.
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
@ -281,7 +315,7 @@ Do not send CLs removing the interior tags from such phrases.
</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
@ -303,6 +337,8 @@ Do not send CLs removing the interior tags from such phrases.
<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>
@ -316,6 +352,8 @@ Do not send CLs removing the interior tags from such phrases.
<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.
@ -325,14 +363,9 @@ Do not send CLs removing the interior tags from such phrases.
third-party tools that need to collect package source code.)
</p>
<p><!-- CL 298612 -->
The <code>go</code> <code>build</code> command and related commands
now support an <code>-asan</code> flag that enables interoperation
with C (or C++) code compiled with the address sanitizer (C compiler
option <code>-fsanitize=address</code>).
</p>
<h4 id="go-mod-tidy"><code>go</code> <code>mod</code> <code>tidy</code></h4>
<p><!-- https://golang.org/issue/47738 -->
<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
@ -342,11 +375,13 @@ Do not send CLs removing the interior tags from such phrases.
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>-workfile</code>
flag, it will put the <code>go</code> command into workspace mode.
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>
@ -355,6 +390,17 @@ Do not send CLs removing the interior tags from such phrases.
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
with C (or C++) code compiled with the address sanitizer (C compiler
option <code>-fsanitize=address</code>).
</p>
<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
@ -376,7 +422,28 @@ Do not send CLs removing the interior tags from such phrases.
</ul>
</p>
<h3 id="gofmt"><code>gofmt</code></h3>
<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
@ -384,7 +451,7 @@ Do not send CLs removing the interior tags from such phrases.
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>
@ -472,7 +539,7 @@ Do not send CLs removing the interior tags from such phrases.
</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>
@ -502,10 +569,23 @@ Do not send CLs removing the interior tags from such phrases.
</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="debug/buildinfo">New <code>debug/buildinfo</code> package</h3>
@ -630,8 +710,8 @@ Do not send CLs removing the interior tags from such phrases.
</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>
@ -909,6 +989,19 @@ Do not send CLs removing the interior tags from such phrases.
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>
@ -980,7 +1073,7 @@ Do not send CLs removing the interior tags from such phrases.
<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>
@ -993,7 +1086,7 @@ Do not send CLs removing the interior tags from such phrases.
<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>
@ -1045,7 +1138,7 @@ Do not send CLs removing the interior tags from such phrases.
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>
@ -1078,6 +1171,16 @@ Do not send CLs removing the interior tags from such phrases.
</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 -->
@ -1147,7 +1250,7 @@ Do not send CLs removing the interior tags from such phrases.
</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>
@ -1156,7 +1259,7 @@ Do not send CLs removing the interior tags from such phrases.
<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 -->
@ -1228,7 +1331,7 @@ Do not send CLs removing the interior tags from such phrases.
<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>

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,7 @@ func TestASAN(t *testing.T) {
// 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 occured.
// Check if -asan option can correctly print where the error occurred.
if tc.errorLocation != "" &&
!strings.Contains(out, tc.errorLocation) &&
!strings.Contains(out, noSymbolizer) &&

View File

@ -6,6 +6,7 @@ package reboot_test
import (
"io"
"io/fs"
"os"
"path/filepath"
"strings"
@ -26,10 +27,14 @@ func overlayDir(dstRoot, srcRoot string) error {
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 @@ func overlayDir(dstRoot, srcRoot string) error {
}
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 @@ func overlayDir(dstRoot, srcRoot string) error {
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
}

View File

@ -12,6 +12,7 @@ import (
"path/filepath"
"runtime"
"testing"
"time"
)
func TestRepeatBootstrap(t *testing.T) {
@ -19,16 +20,14 @@ func TestRepeatBootstrap(t *testing.T) {
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)

View File

@ -95,11 +95,11 @@ type rune = int32
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)

View File

@ -372,6 +372,8 @@ func genSplit(s, sep []byte, sepSave, n int) [][]byte {
// 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 @@ func SplitAfterN(s, sep []byte, n int) [][]byte {
// 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

View File

@ -155,7 +155,7 @@ as follows:
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:

View File

@ -62,8 +62,9 @@ func Compiling(pkgs []string) bool {
// 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",

View File

@ -238,6 +238,15 @@ func (e *escape) goDeferStmt(n *ir.GoDeferStmt) {
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 {

View File

@ -10,6 +10,7 @@ import (
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/logopt"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
)
@ -243,6 +244,9 @@ func (b *batch) flowClosure(k hole, clo *ir.ClosureExpr) {
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 {

View File

@ -217,6 +217,10 @@ func dumpGlobalConst(n ir.Node) {
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 @@ func addGCLocals() {
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)
}
}
}

View File

@ -180,6 +180,14 @@ func ImportData(imports map[string]*types2.Package, data, path string) (pkg *typ
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))
@ -191,6 +199,11 @@ func ImportData(imports map[string]*types2.Package, data, path string) (pkg *typ
return localpkg, nil
}
type setConstraintArgs struct {
t *types2.TypeParam
constraint types2.Type
}
type iimporter struct {
exportVersion int64
ipath string
@ -206,6 +219,9 @@ type iimporter struct {
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) {
@ -401,7 +417,11 @@ func (r *importReader) obj(name string) {
}
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()

View File

@ -133,6 +133,10 @@ type Func struct {
// 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 {

View File

@ -20,7 +20,7 @@ func TestSizeof(t *testing.T) {
_32bit uintptr // size on 32bit platforms
_64bit uintptr // size on 64bit platforms
}{
{Func{}, 192, 328},
{Func{}, 196, 336},
{Name{}, 112, 200},
}

View File

@ -362,7 +362,7 @@ func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt {
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

View File

@ -114,7 +114,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
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 @@ func (g *irgen) substType(typ *types.Type, tparams *types.Type, targs []ir.Node)
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) exprs(exprs []syntax.Expr) []ir.Node {
}
func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
if ptr, ok := types2.StructuralType(typ).(*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 {

View File

@ -98,95 +98,6 @@ func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) *ir.BinaryExp
}
}
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)

View File

@ -410,7 +410,8 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
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
@ -640,6 +641,11 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
// 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()
@ -656,11 +662,9 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
s1 := make([]*types.Type, len(shapes))
for i, t := range shapes {
var tparam *types.Type
if tparams[i].Kind() == types.TTYPEPARAM {
// 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, tparam)
} else {
@ -1055,8 +1059,6 @@ func (subst *subster) node(n ir.Node) ir.Node {
// 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
@ -1076,14 +1078,7 @@ func (subst *subster) node(n ir.Node) ir.Node {
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")
}
} else {
// This is the case of a function value that was a
// type parameter (implied to be a function via a
@ -1154,6 +1149,7 @@ func (subst *subster) node(n ir.Node) ir.Node {
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
@ -1183,6 +1179,26 @@ func (subst *subster) node(n ir.Node) ir.Node {
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
}

View File

@ -242,7 +242,7 @@ func transformCompare(n *ir.BinaryExpr) {
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)
}

View File

@ -1338,10 +1338,10 @@ func (w *writer) compLit(lit *syntax.CompositeLit) {
w.typ(tv.Type)
typ := tv.Type
if ptr, ok := types2.StructuralType(typ).(*types2.Pointer); ok {
if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
typ = ptr.Elem()
}
str, isStruct := types2.StructuralType(typ).(*types2.Struct)
str, isStruct := types2.CoreType(typ).(*types2.Struct)
w.len(len(lit.ElemList))
for i, elem := range lit.ElemList {

View File

@ -1457,7 +1457,7 @@ func WriteBasicTypes() {
type typeAndStr struct {
t *types.Type
short string // "short" here means NameString
short string // "short" here means TypeSymName
regular string
}

View File

@ -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)))

View File

@ -906,7 +906,7 @@ func (po *poset) Ordered(n1, n2 *Value) bool {
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).

View File

@ -1124,13 +1124,14 @@ func rewriteValueRISCV64_OpEqPtr(v *Value) bool {
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 @@ func rewriteValueRISCV64_OpNeqPtr(v *Value) bool {
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

View File

@ -6768,6 +6768,34 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
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
@ -6790,6 +6818,8 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
p.To.Sym = openDeferInfo
}
emitWrappedFuncInfo(e, pp)
// Remember where each block starts.
s.bstart = make([]*obj.Prog, f.NumBlocks())
s.pp = pp

View File

@ -6,7 +6,7 @@ package main
import (
"fmt"
"./mysort"
"cmd/compile/internal/test/testdata/mysort"
)
type MyString struct {

View File

@ -1851,7 +1851,10 @@ func (w *exportWriter) expr(n ir.Node) {
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

View File

@ -354,15 +354,18 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name {
// 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 @@ func (r *importReader) node() ir.Node {
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

View File

@ -1424,6 +1424,68 @@ func genericTypeName(sym *types.Sym) string {
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
@ -1432,9 +1494,9 @@ func genericTypeName(sym *types.Sym) string {
// 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. 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.
// 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
@ -1442,6 +1504,30 @@ func genericTypeName(sym *types.Sym) string {
// instantiation.
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()

View File

@ -72,6 +72,7 @@ const (
fmtDebug
fmtTypeID
fmtTypeIDName
fmtTypeIDHash
)
// Sym
@ -144,10 +145,21 @@ func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
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 @@ func pkgqual(pkg *Pkg, verb rune, mode fmtMode) string {
case fmtDebug:
return pkg.Name
case fmtTypeIDName:
case fmtTypeIDName, fmtTypeIDHash:
// dcommontype, typehash
return pkg.Name
@ -331,7 +343,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
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 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
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 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
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 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
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'
}
@ -657,7 +669,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
// Compute tsym, the symbol that would normally be used as
// the field name when embedding f.Type.
// TODO(mdempsky): Check for other occurences of this logic
// TODO(mdempsky): Check for other occurrences of this logic
// and deduplicate.
typ := f.Type
if typ.IsPtr() {
@ -688,7 +700,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
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 {
@ -756,7 +768,7 @@ func FmtConst(v constant.Value, sharp bool) string {
// 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))

View File

@ -204,12 +204,12 @@ type Info struct {
// qualified identifiers are collected in the Uses map.
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.
@ -421,25 +421,45 @@ func (conf *Config) Check(path string, files []*syntax.File, info *Info) (*Packa
}
// 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.

View File

@ -12,6 +12,7 @@ import (
"internal/testenv"
"reflect"
"regexp"
"sort"
"strings"
"testing"
@ -403,69 +404,61 @@ func TestTypesInfo(t *testing.T) {
}
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) }`,
@ -474,97 +467,113 @@ func TestInstanceInfo(t *testing.T) {
// `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) }`,
[]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 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 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 i0; import lib "generic_lib"; func _() { lib.F(42) }`,
`F`,
[]string{`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]`,
`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"; 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`},
},
{`package type4; import lib "generic_lib"; var _ lib.T[int]`,
`T`,
[]string{`int`},
`[]int`,
},
}
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)
}
@ -574,58 +583,70 @@ type T[P any] []P
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))
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)
}
typ = inst.Type
// 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)
}
break
if !Identical(inst.Inst.Type, inst2) {
t.Errorf("%v and %v are not identical", inst.Inst.Type, inst2)
}
}
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) {
@ -1697,7 +1718,7 @@ func F(){
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*/
@ -2313,27 +2334,27 @@ type Bad Bad // invalid type
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},
@ -2364,8 +2385,20 @@ type Bad Bad // invalid type
}
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)
}
}
}

View File

@ -294,15 +294,14 @@ func (check *Checker) typesSummary(list []Type, variadic bool) string {
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)
func measure(x int, unit string) string {
if x != 1 {
s += "s"
unit += "s"
}
return 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]

View File

@ -82,10 +82,24 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
// 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 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
if x.mode == invalid {
return
}
if t := structuralString(x.typ); t != nil && isString(t) {
if t := coreString(x.typ); t != nil && isString(t) {
if check.Types != nil {
sig := makeSig(S, S, x.typ)
sig.variadic = true
@ -331,14 +345,14 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
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)
}
@ -472,13 +486,13 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
}
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)

View File

@ -168,7 +168,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
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
@ -423,7 +423,7 @@ var cgoPrefixes = [...]string{
"_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
@ -525,7 +525,17 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
}
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
}

View File

@ -18,19 +18,6 @@ var nopos syntax.Pos
// 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
@ -139,7 +126,7 @@ type Checker struct {
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)
@ -218,6 +205,16 @@ func (check *Checker) pop() Object {
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 {
@ -260,6 +257,8 @@ func (check *Checker) initFiles(files []*syntax.File) {
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
@ -328,8 +327,8 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) {
print("== processDelayed ==")
check.processDelayed(0) // incl. all functions
print("== expandDefTypes ==")
check.expandDefTypes()
print("== cleanup ==")
check.cleanup()
print("== initOrder ==")
check.initOrder()
@ -357,7 +356,6 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) {
check.recvTParamMap = nil
check.brokenAliases = nil
check.unionTypeSets = nil
check.defTypes = nil
check.ctxt = nil
// TODO(gri) There's more memory we should release at this point.
@ -385,27 +383,13 @@ func (check *Checker) processDelayed(top int) {
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) {

View File

@ -19,12 +19,12 @@ func AsSignature(t Type) *Signature {
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)
}

View File

@ -49,11 +49,14 @@ func (check *Checker) conversion(x *operand, T Type) {
// 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

View File

@ -569,7 +569,6 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel
// Keep track of bounds for later validation.
var bound Type
var bounds []Type
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
@ -584,7 +583,6 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel
check.error(f.Type, "cannot use a type parameter as constraint")
bound = Typ[Invalid]
}
bounds = append(bounds, bound)
}
tparams[i].bound = bound
}

View File

@ -124,6 +124,17 @@ func sprintf(qf Qualifier, debug bool, format string, args ...interface{}) strin
}
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
}

View File

@ -182,9 +182,9 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) {
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
}
@ -899,7 +899,7 @@ func (check *Checker) incomparableCause(typ Type) string {
}
// see if we can extract a more specific error
var cause string
comparable(typ, nil, func(format string, args ...interface{}) {
comparable(typ, true, nil, func(format string, args ...interface{}) {
cause = check.sprintf(format, args...)
})
return cause
@ -1359,7 +1359,11 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case hint != nil:
// no composite literal type present - use hint (element type of enclosing type)
typ = hint
base, _ = deref(structuralType(typ)) // *T implies &T{}
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
}
default:
// TODO(gri) provide better error messages depending on context
@ -1367,7 +1371,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
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.
@ -1552,7 +1556,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
return kind
case *syntax.SelectorExpr:
check.selector(x, e)
check.selector(x, e, nil)
case *syntax.IndexExpr:
if check.indexExpr(x, e) {
@ -1638,6 +1642,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case invalid:
goto Error
case typexpr:
check.validVarType(e.X, x.typ)
x.typ = &Pointer{base: x.typ}
default:
var base Type

View File

@ -182,7 +182,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
}
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 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) {
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

View File

@ -41,6 +41,13 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
}()
}
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)
@ -54,6 +61,64 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
}
// len(targs) < n
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)
}
}
// 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
@ -403,6 +468,13 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool {
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)
@ -416,27 +488,88 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type)
}
}
// 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
// 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(tpar, sbound) {
if !u.unify(tx, core.typ) {
// TODO(gri) improve error message by providing the type arguments
// which we know already
check.errorf(pos, "%s does not match %s", tpar, sbound)
// 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
@ -504,8 +637,8 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type)
}
// 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) {
@ -525,6 +658,42 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type)
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
@ -570,8 +739,6 @@ func (w *cycleFinder) typ(typ Type) {
// 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)
}

View File

@ -15,10 +15,10 @@ import (
// 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
@ -204,7 +204,7 @@ func (check *Checker) implements(V, T Type) error {
// 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() && ((Vi != nil && !Vi.IsComparable()) || (Vi == nil && !Comparable(V))) {
if Ti.IsComparable() && !comparable(V, false, nil, nil) {
pending = errorf("%s does not implement comparable", V)
}

View File

@ -37,7 +37,7 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
}
// 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 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
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
@ -100,6 +109,11 @@ func (t *Interface) String() string { return TypeString(t, nil) }
// ----------------------------------------------------------------------------
// 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)
@ -162,16 +176,10 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
// (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)
}

View File

@ -66,12 +66,13 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false)
// If we didn't find anything and if we have a type parameter with a structural constraint,
// see if there is a matching field (but not a method, those need to be declared explicitly
// in the constraint). If the structural constraint is a named pointer type (see above), we
// are ok here because only fields are accepted as results.
if obj == nil && isTypeParam(T) {
if t := structuralType(T); t != nil {
// 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
@ -425,18 +426,31 @@ func (check *Checker) funcString(f *Func) string {
// 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) {

View File

@ -72,16 +72,36 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar
}
// 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 }
@ -89,7 +109,7 @@ func (t *Named) Origin() *Named { return t.orig }
// 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.
@ -102,7 +122,11 @@ func (t *Named) SetTypeParams(tparams []*TypeParam) {
// 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.
// 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().
@ -360,11 +384,11 @@ func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypePara
// that it wasn't substituted. In this case we need to create a new
// *Interface before modifying receivers.
if iface == n.orig.underlying {
iface = &Interface{
embeddeds: iface.embeddeds,
complete: iface.complete,
implicit: iface.implicit, // should be false but be conservative
}
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

View File

@ -31,7 +31,7 @@ func isBasic(t Type, info BasicInfo) bool {
// 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 @@ func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) }
// 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,11 +102,12 @@ func isGeneric(t Type) bool {
// Comparable reports whether values of type T are comparable.
func Comparable(T Type) bool {
return comparable(T, nil, nil)
return comparable(T, true, nil, nil)
}
// 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, seen map[Type]bool, reportf func(string, ...interface{})) bool {
func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool {
if seen[T] {
return true
}
@ -124,7 +125,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})
return true
case *Struct:
for _, f := range t.fields {
if !comparable(f.typ, seen, nil) {
if !comparable(f.typ, dynamic, seen, nil) {
if reportf != nil {
reportf("struct containing %s cannot be compared", f.typ)
}
@ -133,7 +134,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})
}
return true
case *Array:
if !comparable(t.elem, seen, nil) {
if !comparable(t.elem, dynamic, seen, nil) {
if reportf != nil {
reportf("%s cannot be compared", t)
}
@ -141,7 +142,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})
}
return true
case *Interface:
return !isTypeParam(T) || t.typeSet().IsComparable(seen)
return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen)
}
return false
}

View File

@ -413,7 +413,7 @@ func (check *Checker) collectObjects() {
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})
@ -458,7 +458,7 @@ func (check *Checker) collectObjects() {
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

View File

@ -116,11 +116,10 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
// 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
@ -136,22 +135,23 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
}
}
// 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])
}
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)
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)
}
} 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))
}
}
}
@ -194,9 +194,11 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
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.
// 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."
@ -224,6 +226,8 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
} 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:
@ -250,10 +254,9 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
}
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...)

View File

@ -409,9 +409,9 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
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)
@ -626,14 +626,15 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
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
@ -809,8 +810,6 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu
}
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
@ -835,9 +834,9 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
// 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)
if t, _ := u.(*Chan); t != nil {
if sValue != nil {
check.softErrorf(sValue, "range over %s permits only one iteration variable", &x)
@ -852,7 +851,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
// ok to continue
}
if u == nil {
cause = check.sprintf("%s has no structural type", x.typ)
cause = check.sprintf("%s has no core type", x.typ)
}
}
key, val = rangeKeyVal(u)
@ -866,6 +865,11 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
}
}
// 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)
@ -874,9 +878,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
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 {
@ -913,12 +915,8 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
// 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 {

View File

@ -21,6 +21,17 @@ func makeSubstMap(tpars []*TypeParam, targs []Type) substMap {
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
}
@ -149,7 +160,10 @@ func (subst *subster) typ(typ Type) Type {
methods, mcopied := subst.funcList(t.methods)
embeddeds, ecopied := subst.typeList(t.embeddeds)
if mcopied || ecopied {
iface := &Interface{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.

View File

@ -92,15 +92,6 @@ func (xl termlist) norm() termlist {
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()

View File

@ -106,35 +106,6 @@ func TestTermlistNorm(t *testing.T) {
}
}
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

View File

@ -148,7 +148,7 @@ func _[
_ = 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 @@ func _[
_ = 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 @@ func _[
_ = 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)
}

View File

@ -15,9 +15,9 @@ func append1() {
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 @@ func append3() {
_ = 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() {

View File

@ -8,21 +8,21 @@ import "strconv"
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 @@ func _() {
// 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 @@ func _() {
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 @@ var _ = Double(MySlice{1})
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)

View File

@ -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]
}

View File

@ -134,11 +134,11 @@ func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3
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 @@ func _[
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 @@ func _[
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 @@ func _[
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 @@ func _[
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

View File

@ -78,7 +78,7 @@ func _() {
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 @@ func _() {
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 */ )
}

View File

@ -35,7 +35,7 @@ func (t T1[[ /* ERROR must be an identifier */ ]int]) m2() {}
// 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.

View File

@ -292,7 +292,7 @@ func _[T interface{~int|~float64}]() {
// 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 @@ func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P {
}
// 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 {

View File

@ -35,7 +35,7 @@ func _() int {
return deref(p)
}
func addrOfCopy[V any, P ~*V](v V) P {
func addrOfCopy[V any, P *V](v V) P {
return &v
}

View File

@ -47,7 +47,7 @@ type _ struct{
}
type _ struct{
I3 // ERROR interface is .* comparable
I3 // ERROR interface contains type constraints
}
// General composite types.
@ -59,19 +59,19 @@ type (
_ []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{}

View File

@ -9,7 +9,7 @@ const L = 10
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

View File

@ -12,7 +12,7 @@ type C4 interface{ chan int | chan<- int }
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 C2](ch T) {
}
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) {

View File

@ -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)

View File

@ -12,7 +12,7 @@ type C4 interface{ chan int | chan<- int }
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 C2](ch T) {
}
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) {

View File

@ -8,13 +8,13 @@
package go1_17
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]{}

View File

@ -2,24 +2,19 @@
// 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:
// - the error messages could be better or are incorrect
// - unification fails due to stack overflow that is caught
package p
func f[P any](a, _ 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 P */)
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)
// TODO(gri) these error messages are incorrect because the code is valid
g(&a, & /* ERROR type \*P of &b does not match inferred type \*P for P */ b)
g([]P{}, [ /* ERROR type \[\]P of \[\]P{} does not match inferred type \[\]P for P */ ]P{})
g(&a, &b)
g([]P{}, []P{})
// work-around: provide type argument explicitly
g[*P](&a, &b)

View File

@ -2,14 +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:
// - the error messages are unclear
// - unification fails due to stack overflow that is caught
package p
func f[P *Q, Q any](P, Q) {
// TODO(gri) these error messages are unclear
_ = f[ /* ERROR P does not match \*Q */ P]
_ = f[ /* ERROR cannot infer P */ *P]
_ = f[P]
}
func f2[P /* ERROR instantiation cycle */ *Q, Q any](P, Q) {
_ = f2[*P]
}

View File

@ -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{}

View File

@ -10,9 +10,10 @@ type S[A, B any] struct {
func (S[A, B]) m() {}
// TODO(gri) We should only report one error below. See issue #50588.
// TODO(gri): with type-type inference enabled we should only report one error
// below. See issue #50588.
func _[A any](s S /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [A]) {
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()
@ -21,7 +22,7 @@ func _[A any](s S /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type
// another test case from the issue
func _() {
X(Interface[*F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
X(Interface[*F /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
}
func X[Q Qer](fs Interface[Q]) {

View File

@ -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)
}

View File

@ -2,6 +2,10 @@
// 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 {
@ -9,13 +13,13 @@ type Sf struct {
}
func f0[P Sf](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
}
func f0t[P ~struct{f int}](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
}
var _ = f0[Sf]
@ -25,8 +29,8 @@ var _ = f0[Sm /* ERROR does not implement */ ]
var _ = f0t[Sm /* ERROR does not implement */ ]
func f1[P interface{ Sf; m() }](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
p.m()
}
@ -44,20 +48,20 @@ type Sfm struct {
func (Sfm) m() {}
func f2[P interface{ Sfm; m() }](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
p.m()
}
var _ = f2[Sfm]
// special case: structural type is a named pointer type
// special case: core type is a named pointer type
type PSfm *Sfm
func f3[P interface{ PSfm }](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
p.m /* ERROR type P has no field or method m */ ()
}

View File

@ -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
}

View File

@ -2,6 +2,10 @@
// 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.
@ -18,9 +22,12 @@ type numericAbs[T Numeric] interface {
// 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 {
// TODO: the error below should probably be positioned on the '-'.
d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
return d.Abs()
// 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.

View File

@ -16,7 +16,7 @@ func G[A, B any](F[A, B]) {
func _() {
// TODO(gri) only report one error below (issue #50932)
var x F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int]
var x F /* ERROR got 1 arguments but 2 type parameters */ [int]
G(x /* ERROR does not match */)
}
@ -46,9 +46,9 @@ func NSG[G any](c RSC[G]) {
fmt.Println(c)
}
func MMD[Rc RC /* ERROR cannot infer RG */ /* ERROR got 1 arguments */ [RG], RG any, G any]() M /* ERROR got 2 arguments */ /* ERROR Rc does not match */ [Rc, RG] {
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 */ /* ERROR Rc does not match */ [Rc, RG]
var nFn NFn /* ERROR got 2 arguments */ [Rc, RG]
var empty Rc
switch any(empty).(type) {

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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,
}
}

View File

@ -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()
}

View File

@ -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},
})
}

View File

@ -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 */ }}
}

View File

@ -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() {}

View File

@ -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 */
}

View File

@ -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
}

View File

@ -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("")
}

View File

@ -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
}
}

View File

@ -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]
}

View File

@ -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

View File

@ -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) {}

View File

@ -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
}

View File

@ -7,9 +7,7 @@ package types2
// 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 @@ func under(t Type) Type {
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 @@ func structuralType(t Type) Type {
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

View File

@ -31,11 +31,13 @@ func (t *TypeParam) Obj() *TypeName { return t.obj }
// 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 @@ func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam {
// 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 @@ func (t *TypeParam) Constraint() Type {
// 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 @@ func (t *TypeParam) String() string { return TypeString(t, nil) }
// ----------------------------------------------------------------------------
// 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
@ -136,16 +141,6 @@ func (t *TypeParam) iface() *Interface {
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).

Some files were not shown because too many files have changed in this diff Show More