[release-branch.go1.18] all: merge master (acc5f55) into release-branch.go1.18

Merge List:

+ 2022-02-28 acc5f55bac cmd/go: make work and work_edit script tests version-independent
+ 2022-02-28 f04d5c118c cmd/internal/obj/riscv/testdata/testbranch: add //go:build lines
+ 2022-02-28 9fe3676bc7 all: fix typos
+ 2022-02-28 f9285818b6 go/types, types2: fix string to type parameter conversions
+ 2022-02-28 eb8198d2f6 cmd/compile: deal with constructed types that have shapes in them
+ 2022-02-28 b33592dcfd spec: the -'s possessive suffix is English, not code
+ 2022-02-28 57e3809884 runtime: avoid cgo_unsafe_args for syscall.syscall functions on darwin/arm64
+ 2022-02-28 06a43e4ab6 cmd/compile: fix case for structural types where we should be looking at typeparams
+ 2022-02-28 0907d57abf cmd/compile: emit types of constants which are instantiated generic types
+ 2022-02-28 9c4a8620c8 CONTRIBUTORS: update for the Go 1.18 release
+ 2022-02-28 57dda9795d test: add new test case for 51219 that triggers the types2 issue
+ 2022-02-26 a064a4f29a cmd/compile: ensure dictionary assignment statements are defining statements
+ 2022-02-26 286e3e61aa go/types, types2: report an error for x.sel where x is a built-in
+ 2022-02-25 01e522a973 go/types,types2: revert documentation for Type.Underlying
+ 2022-02-25 26999cfd84 runtime/internal/atomic: set SP delta correctly for 64-bit atomic functions on ARM
+ 2022-02-25 7c694fbad1 go/types, types2: delay receiver type validation
+ 2022-02-25 55e5b03cb3 doc/go1.18: note changes to automatic go.mod and go.sum updates
+ 2022-02-25 6d810241eb doc/go1.18: document minimum Linux kernel version
+ 2022-02-25 b8b3196375 doc/go1.18: document method set limitation for method selectors
+ 2022-02-24 c0840a7c72 go/types, types2: method recv type parameter count must match base type parameter count
+ 2022-02-24 c15527f0b0 go/types, types2: implement adjCoreType using TypeParam.is
+ 2022-02-24 5a9fc946b4 cmd/go: avoid +incompatible major versions if a go.mod file exists in a subdirectory for that version
+ 2022-02-24 4edefe9568 cmd/compile: delay all call transforms if in a generic function
+ 2022-02-24 8c5904f149 doc/go1.18: mention runtime/pprof improvements
+ 2022-02-24 b2dfec100a doc/go1.18: fix typo in AMD64 port section
+ 2022-02-24 78e99761fc go/types, types2: don't crash if comp. literal element type has no core type
+ 2022-02-23 e94f7df957 go/types, types2: generalize cleanup phase after type checking
+ 2022-02-23 163da6feb5 go/types, types2: add "dynamic" flag to comparable predicate
+ 2022-02-23 e534907f65 go/types: delete unnecessary slice construction
+ 2022-02-23 d0c3b01162 doc/go1.18: drop misplaced period
+ 2022-02-22 35170365c8 net: document methods of Buffers
+ 2022-02-22 3140625606 doc/go1.18: correct "go build -asan" HTML tag
+ 2022-02-22 d17b65ff54 crypto/x509, runtime: fix occasional spurious “certificate is expired”
+ 2022-02-21 c9fe126c8b doc/go1.18: fix a few small typos, add a few commas
+ 2022-02-20 851ecea4cc encoding/xml: embedded reference to substruct causes XML marshaller to panic on encoding
+ 2022-02-19 0261fa616a testdata: fix typo in comment
+ 2022-02-19 903e7cc699 doc/go1.18: fix grammar error
+ 2022-02-19 e002cf4df7 strings: fix typo in comment
+ 2022-02-18 61b5c866a9 doc/go1.18: document Go 1.17 bootstrap and //go:build fix
+ 2022-02-18 d27248c52f runtime: save some stack space for racecall on ARM64
+ 2022-02-18 d93cc8cb96 runtime: define racefuncenter and racefuncexit as ABIInternal
+ 2022-02-18 20b177268f reflect: call ABIInternal moveMakeFuncArgPtrs on ARM64
+ 2022-02-18 d35ed09486 cmd/compile: fix importers to deal with recursion through type constraints
+ 2022-02-16 eaf040502b os: eliminate arbitrary sleep in Kill tests

Change-Id: I74352b70d97c6fd4a45aee4e222160ea2a7854ae
This commit is contained in:
Dmitri Shuralyov 2022-03-02 18:41:18 -05:00
commit 9f2f0ee6ce
108 changed files with 1726 additions and 634 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

@ -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,12 +363,7 @@ 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, CL 344572 -->
The <code>go</code> <code>mod</code> <code>tidy</code> command now retains
@ -342,6 +375,8 @@ 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
@ -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,11 +422,28 @@ Do not send CLs removing the interior tags from such phrases.
</ul>
</p>
<h4 id="go-build-lines"><code>//go:build</code> lines</h4>
<p><!-- CL 240611 -->
TODO: <a href="https://golang.org/cl/240611">https://golang.org/cl/240611</a>: 240611: cmd/fix: add buildtag fix
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>
<h3 id="gofmt"><code>gofmt</code></h3>
<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
@ -388,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>
@ -476,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>
@ -506,14 +569,21 @@ 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="build">Build</h2>
<h2 id="bootstrap">Bootstrap</h2>
<p><!-- CL 369914, CL 370274 -->
TODO: <a href="https://golang.org/cl/369914">https://golang.org/cl/369914</a>: for default bootstrap, use Go 1.17 if present, falling back to Go 1.4
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>
@ -640,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>
@ -1003,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>
@ -1016,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>
@ -1101,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 -->
@ -1170,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>
@ -1179,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 -->
@ -1251,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>

View File

@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification - Go 1.18 Draft",
"Subtitle": "Version of Feb 14, 2022",
"Subtitle": "Version of Feb 28, 2022",
"Path": "/ref/spec"
}-->
@ -2008,7 +2008,7 @@ by a value of type <code>T</code>.
</ul>
<p>
Additionally, if <code>x's</code> type <code>V</code> or <code>T</code> are type parameters
Additionally, if <code>x</code>'s type <code>V</code> or <code>T</code> are type parameters
with <a href="#Specific_types">specific types</a>, <code>x</code>
is assignable to a variable of type <code>T</code> if one of the following conditions applies:
</p>
@ -7414,7 +7414,7 @@ an explicit call to <code>panic</code> or a <a href="#Run_time_panics">run-time
terminates the execution of <code>F</code>.
Any functions <a href="#Defer_statements">deferred</a> by <code>F</code>
are then executed as usual.
Next, any deferred functions run by <code>F's</code> caller are run,
Next, any deferred functions run by <code>F</code>'s caller are run,
and so on up to any deferred by the top-level function in the executing goroutine.
At that point, the program is terminated and the error
condition is reported, including the value of the argument to <code>panic</code>.

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

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

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

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

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]
}
// 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")
}
m = transformBuiltin(call)
} 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

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)

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

@ -657,7 +657,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() {

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)
if x != 1 {
s += "s"
}
return s
func measure(x int, unit string) string {
if x != 1 {
unit += "s"
}
return fmt.Sprintf("%d %s", x, unit)
}
func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) {
vars := measure(nvars, "variable")
vals := measure(nvals, "value")
rhs0 := rhs[0]

View File

@ -525,7 +525,11 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
}
check.exprOrType(x, e.X, false)
if x.mode == invalid {
switch x.mode {
case builtin:
check.errorf(e.Pos(), "cannot select on %s", x)
goto Error
case invalid:
goto Error
}

View File

@ -126,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)
@ -205,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 {
@ -247,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
@ -315,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()
@ -344,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.
@ -372,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

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

@ -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
@ -1360,6 +1360,10 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
// no composite literal type present - use hint (element type of enclosing type)
typ = hint
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

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
}

View File

@ -591,15 +591,24 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type)
return
}
// adjCoreType returns the core type of tpar unless the
// type parameter embeds a single, possibly named type,
// in which case it returns that single type instead.
// (The core type is always the underlying type of that
// single type.)
func adjCoreType(tpar *TypeParam) Type {
// If the type parameter embeds a single, possibly named
// type, use that one instead of the core type (which is
// always the underlying type of that single type).
if single := tpar.singleType(); single != nil {
if debug {
assert(under(single) == coreType(tpar))
var single *term
if tpar.is(func(t *term) bool {
if single == nil && t != nil {
single = t
return true
}
return single
return false // zero or more than one terms
}) {
if debug {
assert(under(single.typ) == coreType(tpar))
}
return single.typ
}
return coreType(tpar)
}

View File

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

@ -72,11 +72,31 @@ 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.
func (t *Named) Obj() *TypeName { return t.orig.obj } // for non-instances this is the same as t.obj
@ -360,11 +380,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

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

@ -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,66 +194,69 @@ 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.
rtyp, _ := deref(recv.typ)
// Delay validation of receiver type as it may cause premature expansion
// of types the receiver type is dependent on (see issues #51232, #51233).
check.later(func() {
rtyp, _ := deref(recv.typ)
// spec: "The receiver type must be of the form T or *T where T is a type name."
// (ignore invalid types - error was reported before)
if rtyp != Typ[Invalid] {
var err string
switch T := rtyp.(type) {
case *Named:
T.resolve(check.bestContext(nil))
// The receiver type may be an instantiated type referred to
// by an alias (which cannot have receiver parameters for now).
if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ)
break
}
// spec: "The type denoted by T is called the receiver base type; it must not
// be a pointer or interface type and it must be declared in the same package
// as the method."
if T.obj.pkg != check.pkg {
err = "type not defined in this package"
// spec: "The receiver type must be of the form T or *T where T is a type name."
// (ignore invalid types - error was reported before)
if rtyp != Typ[Invalid] {
var err string
switch T := rtyp.(type) {
case *Named:
T.resolve(check.bestContext(nil))
// The receiver type may be an instantiated type referred to
// by an alias (which cannot have receiver parameters for now).
if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ)
break
}
// spec: "The type denoted by T is called the receiver base type; it must not
// be a pointer or interface type and it must be declared in the same package
// as the method."
if T.obj.pkg != check.pkg {
err = "type not defined in this package"
if check.conf.CompilerErrorMessages {
check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
err = ""
}
} else {
// The underlying type of a receiver base type can be a type parameter;
// e.g. for methods with a generic receiver T[P] with type T[P any] P.
// TODO(gri) Such declarations are currently disallowed.
// Revisit the need for underIs.
underIs(T, func(u Type) bool {
switch u := u.(type) {
case *Basic:
// unsafe.Pointer is treated like a regular pointer
if u.kind == UnsafePointer {
err = "unsafe.Pointer"
return false
}
case *Pointer, *Interface:
err = "pointer or interface type"
return false
}
return true
})
}
case *Basic:
err = "basic or unnamed type"
if check.conf.CompilerErrorMessages {
check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
err = ""
}
} else {
// The underlying type of a receiver base type can be a type parameter;
// e.g. for methods with a generic receiver T[P] with type T[P any] P.
underIs(T, func(u Type) bool {
switch u := u.(type) {
case *Basic:
// unsafe.Pointer is treated like a regular pointer
if u.kind == UnsafePointer {
err = "unsafe.Pointer"
return false
}
case *Pointer, *Interface:
err = "pointer or interface type"
return false
}
return true
})
default:
check.errorf(recv.pos, "invalid receiver type %s", recv.typ)
}
case *Basic:
err = "basic or unnamed type"
if check.conf.CompilerErrorMessages {
check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ)
err = ""
if err != "" {
check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err)
}
default:
check.errorf(recv.pos, "invalid receiver type %s", recv.typ)
}
if err != "" {
check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err)
// ok to continue
}
}
sig.recv = recv
}).describef(recv, "validate receiver %s", recv)
}
sig.params = NewTuple(params...)

View File

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

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

@ -0,0 +1,29 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type RC[RG any] interface {
~[]RG
}
type Fn[RCT RC[RG], RG any] func(RCT)
type F[RCT RC[RG], RG any] interface {
Fn() Fn[RCT]
}
type concreteF[RCT RC[RG], RG any] struct {
makeFn func() Fn[RCT]
}
func (c *concreteF[RCT, RG]) Fn() Fn[RCT] {
return c.makeFn()
}
func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] {
return &concreteF[RCT]{
makeFn: nil,
}
}

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.
package p
type RC[RG any] interface {
~[]RG
}
type Fn[RCT RC[RG], RG any] func(RCT)
type FFn[RCT RC[RG], RG any] func() Fn[RCT]
type F[RCT RC[RG], RG any] interface {
Fn() Fn[RCT]
}
type concreteF[RCT RC[RG], RG any] struct {
makeFn FFn[RCT]
}
func (c *concreteF[RCT, RG]) Fn() Fn[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,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.
// 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() {}
func (T /* ERROR got 1 type parameter, but receiver base type declares 2 */ [_]) 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,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

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

View File

@ -36,6 +36,7 @@ func NewTypeParam(obj *TypeName, constraint Type) *TypeParam {
return (*Checker)(nil).newTypeParam(obj, constraint)
}
// check may be nil
func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam {
// Always increment lastID, even if it is not used.
id := nextID()
@ -50,9 +51,7 @@ 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()
}
@ -93,9 +92,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 +138,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).

View File

@ -39,7 +39,7 @@ func (s *_TypeSet) IsComparable(seen map[Type]bool) bool {
return s.comparable
}
return s.is(func(t *term) bool {
return t != nil && comparable(t.typ, seen, nil)
return t != nil && comparable(t.typ, false, seen, nil)
})
}
@ -103,9 +103,6 @@ func (s *_TypeSet) String() string {
// hasTerms reports whether the type set has specific type terms.
func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
// singleType returns the single type in s if there is exactly one; otherwise the result is nil.
func (s *_TypeSet) singleType() Type { return s.terms.singleType() }
// subsetOf reports whether s1 ⊆ s2.
func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }

View File

@ -342,7 +342,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
return typ
case *syntax.InterfaceType:
typ := new(Interface)
typ := check.newInterface()
def.setUnderlying(typ)
if def != nil {
typ.obj = def.obj

View File

@ -79,7 +79,7 @@ func (check *Checker) validType0(typ Type, env *tparamEnv, path []Object) typeIn
// would have reported a type cycle and couldn't have been
// imported in the first place.
assert(t.obj.pkg == check.pkg)
t.underlying = Typ[Invalid] // t is in the current package (no race possibilty)
t.underlying = Typ[Invalid] // t is in the current package (no race possibility)
// Find the starting point of the cycle and report it.
for i, tn := range path {
if tn == t.obj {

View File

@ -305,17 +305,46 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
//
// (If the version is +incompatible, then the go.mod file must not exist:
// +incompatible is not an ongoing opt-out from semantic import versioning.)
var canUseIncompatible func() bool
canUseIncompatible = func() bool {
var ok bool
if r.codeDir == "" && r.pathMajor == "" {
incompatibleOk := map[string]bool{}
canUseIncompatible := func(v string) bool {
if r.codeDir != "" || r.pathMajor != "" {
// A non-empty codeDir indicates a module within a subdirectory,
// which necessarily has a go.mod file indicating the module boundary.
// A non-empty pathMajor indicates a module path with a major-version
// suffix, which must match.
return false
}
ok, seen := incompatibleOk[""]
if !seen {
_, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod)
if errGoMod != nil {
ok = true
ok = (errGoMod != nil)
incompatibleOk[""] = ok
}
if !ok {
// A go.mod file exists at the repo root.
return false
}
// Per https://go.dev/issue/51324, previous versions of the 'go' command
// didn't always check for go.mod files in subdirectories, so if the user
// requests a +incompatible version explicitly, we should continue to allow
// it. Otherwise, if vN/go.mod exists, expect that release tags for that
// major version are intended for the vN module.
if v != "" && !strings.HasSuffix(statVers, "+incompatible") {
major := semver.Major(v)
ok, seen = incompatibleOk[major]
if !seen {
_, errGoModSub := r.code.ReadFile(info.Name, path.Join(major, "go.mod"), codehost.MaxGoMod)
ok = (errGoModSub != nil)
incompatibleOk[major] = ok
}
if !ok {
return false
}
}
canUseIncompatible = func() bool { return ok }
return ok
return true
}
// checkCanonical verifies that the canonical version v is compatible with the
@ -367,7 +396,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
base := strings.TrimSuffix(v, "+incompatible")
var errIncompatible error
if !module.MatchPathMajor(base, r.pathMajor) {
if canUseIncompatible() {
if canUseIncompatible(base) {
v = base + "+incompatible"
} else {
if r.pathMajor != "" {
@ -495,7 +524,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
// Save the highest non-retracted canonical tag for the revision.
// If we don't find a better match, we'll use it as the canonical version.
if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) {
if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible() {
if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible(v) {
highestCanonical = v
}
}
@ -513,12 +542,12 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
// retracted versions.
allowedMajor := func(major string) func(v string) bool {
return func(v string) bool {
return (major == "" || semver.Major(v) == major) && !isRetracted(v)
return ((major == "" && canUseIncompatible(v)) || semver.Major(v) == major) && !isRetracted(v)
}
}
if pseudoBase == "" {
var tag string
if r.pseudoMajor != "" || canUseIncompatible() {
if r.pseudoMajor != "" || canUseIncompatible("") {
tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor(r.pseudoMajor))
} else {
// Allow either v1 or v0, but not incompatible higher versions.

View File

@ -458,6 +458,54 @@ var codeRepoTests = []codeRepoTest{
rev: "v3.0.0-devel",
err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`,
},
// If v2/go.mod exists, then we should prefer to match the "v2"
// pseudo-versions to the nested module, and resolve the module in the parent
// directory to only compatible versions.
//
// However (https://go.dev/issue/51324), previous versions of the 'go' command
// didn't always do so, so if the user explicitly requests a +incompatible
// version (as would be present in an existing go.mod file), we should
// continue to allow it.
{
vcs: "git",
path: "vcs-test.golang.org/git/v2sub.git",
rev: "80beb17a1603",
version: "v0.0.0-20220222205507-80beb17a1603",
name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
short: "80beb17a1603",
time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
},
{
vcs: "git",
path: "vcs-test.golang.org/git/v2sub.git",
rev: "v2.0.0",
err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
},
{
vcs: "git",
path: "vcs-test.golang.org/git/v2sub.git",
rev: "v2.0.1-0.20220222205507-80beb17a1603",
err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
},
{
vcs: "git",
path: "vcs-test.golang.org/git/v2sub.git",
rev: "v2.0.0+incompatible",
version: "v2.0.0+incompatible",
name: "5fcd3eaeeb391d399f562fd45a50dac9fc34ae8b",
short: "5fcd3eaeeb39",
time: time.Date(2022, 2, 22, 20, 53, 33, 0, time.UTC),
},
{
vcs: "git",
path: "vcs-test.golang.org/git/v2sub.git",
rev: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
version: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
short: "80beb17a1603",
time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
},
}
func TestCodeRepo(t *testing.T) {

View File

@ -4,7 +4,7 @@ go env GOWORK
! stdout .
go work init ./a ./b
cmp go.work go.work.want
cmpenv go.work go.work.want
go env GOWORK
stdout '^'$WORK'(\\|/)gopath(\\|/)src(\\|/)go.work$'
@ -69,7 +69,7 @@ use (
../src/a
)
-- go.work.want --
go 1.18
go $goversion
use (
./a

View File

@ -1,10 +1,10 @@
# Test editing go.work files.
go work init m
cmp go.work go.work.want_initial
cmpenv go.work go.work.want_initial
go work edit -use n
cmp go.work go.work.want_use_n
cmpenv go.work go.work.want_use_n
go work edit -go 1.18
cmp go.work go.work.want_go_118
@ -39,11 +39,11 @@ module m
go 1.18
-- go.work.want_initial --
go 1.18
go $goversion
use ./m
-- go.work.want_use_n --
go 1.18
go $goversion
use (
./m

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build riscv64
// +build riscv64
package testbranch

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build riscv64
// +build riscv64
#include "textflag.h"

View File

@ -48,7 +48,7 @@ func CFStringToString(ref CFRef) string {
// TimeToCFDateRef converts a time.Time into an apple CFDateRef
func TimeToCFDateRef(t time.Time) CFRef {
secs := t.Sub(time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC)).Seconds()
ref := CFDateCreate(int(secs))
ref := CFDateCreate(secs)
return ref
}
@ -170,8 +170,8 @@ func x509_CFArrayAppendValue_trampoline()
//go:cgo_import_dynamic x509_CFDateCreate CFDateCreate "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFDateCreate(seconds int) CFRef {
ret := syscall(abi.FuncPCABI0(x509_CFDateCreate_trampoline), kCFAllocatorDefault, uintptr(seconds), 0, 0, 0, 0)
func CFDateCreate(seconds float64) CFRef {
ret := syscall(abi.FuncPCABI0(x509_CFDateCreate_trampoline), kCFAllocatorDefault, 0, 0, 0, 0, seconds)
return CFRef(ret)
}
func x509_CFDateCreate_trampoline()
@ -193,7 +193,7 @@ func CFStringCreateExternalRepresentation(strRef CFRef) CFRef {
func x509_CFStringCreateExternalRepresentation_trampoline()
// syscall is implemented in the runtime package (runtime/sys_darwin.go)
func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
func syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) uintptr
// ReleaseCFArray iterates through an array, releasing its contents, and then
// releases the array itself. This is necessary because we cannot, easily, set the

View File

@ -512,7 +512,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
}
fv := finfo.value(val, dontInitNilPointers)
if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
if finfo.flags&fOmitEmpty != 0 && (!fv.IsValid() || isEmptyValue(fv)) {
continue
}

View File

@ -2495,3 +2495,39 @@ func TestInvalidXMLName(t *testing.T) {
t.Errorf("error %q does not contain %q", err, want)
}
}
// Issue 50164. Crash on zero value XML attribute.
type LayerOne struct {
XMLName Name `xml:"l1"`
Value *float64 `xml:"value,omitempty"`
*LayerTwo `xml:",omitempty"`
}
type LayerTwo struct {
ValueTwo *int `xml:"value_two,attr,omitempty"`
}
func TestMarshalZeroValue(t *testing.T) {
proofXml := `<l1><value>1.2345</value></l1>`
var l1 LayerOne
err := Unmarshal([]byte(proofXml), &l1)
if err != nil {
t.Fatalf("unmarshal XML error: %v", err)
}
want := float64(1.2345)
got := *l1.Value
if got != want {
t.Fatalf("unexpected unmarshal result, want %f but got %f", want, got)
}
// Marshal again (or Encode again)
// In issue 50164, here `Marshal(l1)` will panic because of the zero value of xml attribute ValueTwo `value_two`.
anotherXML, err := Marshal(l1)
if err != nil {
t.Fatalf("marshal XML error: %v", err)
}
if string(anotherXML) != proofXml {
t.Fatalf("unexpected unmarshal result, want %q but got %q", proofXml, anotherXML)
}
}

View File

@ -181,6 +181,15 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea
p.doDecl(localpkg, name)
}
// SetConstraint can't be called if the constraint type is not yet complete.
// When type params are created in the 'P' case of (*importReader).obj(),
// the associated constraint type may not be complete due to recursion.
// Therefore, we defer calling SetConstraint there, and call it here instead
// after all types are complete.
for _, d := range p.later {
d.t.SetConstraint(d.constraint)
}
for _, typ := range p.interfaceList {
typ.Complete()
}
@ -195,6 +204,11 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea
return localpkg, nil
}
type setConstraintArgs struct {
t *types.TypeParam
constraint types.Type
}
type iimporter struct {
exportVersion int64
ipath string
@ -211,6 +225,9 @@ type iimporter struct {
fake fakeFileSet
interfaceList []*types.Interface
// Arguments for calls to SetConstraint that are deferred due to recursive types
later []setConstraintArgs
}
func (p *iimporter) doDecl(pkg *types.Package, name string) {
@ -391,7 +408,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

@ -290,15 +290,14 @@ func (check *Checker) typesSummary(list []Type, variadic bool) string {
return "(" + strings.Join(res, ", ") + ")"
}
func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
measure := func(x int, unit string) string {
s := fmt.Sprintf("%d %s", x, unit)
if x != 1 {
s += "s"
}
return s
func measure(x int, unit string) string {
if x != 1 {
unit += "s"
}
return fmt.Sprintf("%d %s", x, unit)
}
func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
vars := measure(nvars, "variable")
vals := measure(nvals, "value")
rhs0 := rhs[0]

View File

@ -527,7 +527,12 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
}
check.exprOrType(x, e.X, false)
if x.mode == invalid {
switch x.mode {
case builtin:
// types2 uses the position of '.' for the error
check.errorf(e.Sel, _UncalledBuiltin, "cannot select on %s", x)
goto Error
case invalid:
goto Error
}

View File

@ -133,7 +133,7 @@ type Checker struct {
untyped map[ast.Expr]exprInfo // map of expressions without final type
delayed []action // stack of delayed action segments; segments are processed in FIFO order
objPath []Object // path of object dependencies during type inference (for cycle reporting)
defTypes []*Named // defined types created during type checking, for final validation.
cleaners []cleaner // list of types that may need a final cleanup at the end of type-checking
// environment within which the current object is type-checked (valid only
// for the duration of type-checking a specific object)
@ -212,6 +212,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, fset *token.FileSet, pkg *Package, info *Info) *Checker {
@ -255,6 +265,8 @@ func (check *Checker) initFiles(files []*ast.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
@ -304,22 +316,37 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
defer check.handleBailout(&err)
print := func(msg string) {
if trace {
fmt.Println()
fmt.Println(msg)
}
}
print("== initFiles ==")
check.initFiles(files)
print("== collectObjects ==")
check.collectObjects()
print("== packageObjects ==")
check.packageObjects()
print("== processDelayed ==")
check.processDelayed(0) // incl. all functions
check.expandDefTypes()
print("== cleanup ==")
check.cleanup()
print("== initOrder ==")
check.initOrder()
if !check.conf.DisableUnusedImportCheck {
print("== unusedImports ==")
check.unusedImports()
}
print("== recordUntyped ==")
check.recordUntyped()
if check.firstErr == nil {
@ -337,7 +364,6 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
check.recvTParamMap = nil
check.brokenAliases = nil
check.unionTypeSets = nil
check.defTypes = nil
check.ctxt = nil
// TODO(rFindley) There's more memory we should release at this point.
@ -365,27 +391,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

@ -48,11 +48,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

@ -624,7 +624,6 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList
}()
index := 0
var bounds []Type
for _, f := range list.List {
var bound Type
// NOTE: we may be able to assert that f.Type != nil here, but this is not
@ -642,7 +641,6 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList
} else {
bound = Typ[Invalid]
}
bounds = append(bounds, bound)
for i := range f.Names {
tparams[index+i].bound = bound
}

View File

@ -859,7 +859,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
@ -1339,6 +1339,10 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
// no composite literal type present - use hint (element type of enclosing type)
typ = hint
base, _ = deref(coreType(typ)) // *T implies &T{}
if base == nil {
check.errorf(e, _InvalidLit, "invalid composite literal element type %s: no core type", typ)
goto Error
}
default:
// TODO(gri) provide better error messages depending on context

View File

@ -183,6 +183,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst
}
if !valid {
// types2 uses the position of '[' for the error
check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x)
x.mode = invalid
return false

View File

@ -590,15 +590,24 @@ func (check *Checker) inferB(posn positioner, tparams []*TypeParam, targs []Type
return
}
// adjCoreType returns the core type of tpar unless the
// type parameter embeds a single, possibly named type,
// in which case it returns that single type instead.
// (The core type is always the underlying type of that
// single type.)
func adjCoreType(tpar *TypeParam) Type {
// If the type parameter embeds a single, possibly named
// type, use that one instead of the core type (which is
// always the underlying type of that single type).
if single := tpar.singleType(); single != nil {
if debug {
assert(under(single) == coreType(tpar))
var single *term
if tpar.is(func(t *term) bool {
if single == nil && t != nil {
single = t
return true
}
return single
return false // zero or more than one terms
}) {
if debug {
assert(under(single.typ) == coreType(tpar))
}
return single.typ
}
return coreType(tpar)
}

View File

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

@ -56,7 +56,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)
@ -73,6 +73,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
@ -141,6 +150,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 *ast.InterfaceType, def *Named) {
addEmbedded := func(pos token.Pos, typ Type) {
ityp.embeddeds = append(ityp.embeddeds, typ)
@ -210,16 +224,10 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
sortMethods(ityp.methods)
// (don't sort embeddeds: they must correspond to *embedPos entries)
// Compute type set with a non-nil *Checker as soon as possible
// to report any errors. Subsequent uses of type sets will use
// this computed type set and won't need to pass in a *Checker.
//
// Pin the checker to the interface type in the interim, in case the type set
// must be used before delayed funcs are processed (see issue #48234).
// TODO(rfindley): clean up use of *Checker with computeInterfaceTypeSet
ityp.check = check
// Compute type set as soon as possible to report any errors.
// Subsequent uses of type sets will use this computed type
// set and won't need to pass in a *Checker.
check.later(func() {
computeInterfaceTypeSet(check, iface.Pos(), ityp)
ityp.check = nil
}).describef(iface, "compute type set for %s", ityp)
}

View File

@ -72,11 +72,31 @@ 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.
func (t *Named) Obj() *TypeName {
@ -362,11 +382,11 @@ func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParam
// 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

@ -104,11 +104,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
}
@ -126,7 +127,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)
}
@ -135,7 +136,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)
}
@ -143,7 +144,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

@ -112,7 +112,8 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
// - the receiver specification acts as local declaration for its type parameters, which may be blank
_, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true)
if len(rparams) > 0 {
sig.rparams = bindTParams(check.declareTypeParams(nil, rparams))
tparams := check.declareTypeParams(nil, rparams)
sig.rparams = bindTParams(tparams)
// Blank identifiers don't get declared, so naive type-checking of the
// receiver type expression would fail in Checker.collectParams below,
// when Checker.ident cannot resolve the _ to a type.
@ -122,11 +123,10 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
// lookup in the scope.
for i, p := range rparams {
if p.Name == "_" {
tpar := sig.rparams.At(i)
if check.recvTParamMap == nil {
check.recvTParamMap = make(map[*ast.Ident]*TypeParam)
}
check.recvTParamMap[p] = tpar
check.recvTParamMap[p] = tparams[i]
}
}
// determine receiver type to get its type parameters
@ -142,22 +142,23 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
}
}
// 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, _BadRecv, "got %s, but receiver base type declares %d", got, len(recvTParams))
}
}
}
@ -192,66 +193,77 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
switch len(recvList) {
case 0:
// error reported by resolver
recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
recv = NewParam(token.NoPos, nil, "", Typ[Invalid]) // ignore recv below
default:
// more than one receiver
check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver")
check.error(recvList[len(recvList)-1], _InvalidRecv, "method must have exactly one receiver")
fallthrough // continue with first receiver
case 1:
recv = recvList[0]
}
sig.recv = recv
// TODO(gri) We should delay rtyp expansion to when we actually need the
// receiver; thus all checks here should be delayed to later.
rtyp, _ := deref(recv.typ)
// Delay validation of receiver type as it may cause premature expansion
// of types the receiver type is dependent on (see issues #51232, #51233).
check.later(func() {
rtyp, _ := deref(recv.typ)
// spec: "The receiver type must be of the form T or *T where T is a type name."
// (ignore invalid types - error was reported before)
if rtyp != Typ[Invalid] {
var err string
switch T := rtyp.(type) {
case *Named:
T.resolve(check.bestContext(nil))
// The receiver type may be an instantiated type referred to
// by an alias (which cannot have receiver parameters for now).
if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
check.errorf(atPos(recv.pos), _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
break
}
// spec: "The type denoted by T is called the receiver base type; it must not
// be a pointer or interface type and it must be declared in the same package
// as the method."
if T.obj.pkg != check.pkg {
err = "type not defined in this package"
} else {
// The underlying type of a receiver base type can be a type parameter;
// e.g. for methods with a generic receiver T[P] with type T[P any] P.
underIs(T, func(u Type) bool {
switch u := u.(type) {
case *Basic:
// unsafe.Pointer is treated like a regular pointer
if u.kind == UnsafePointer {
err = "unsafe.Pointer"
// spec: "The receiver type must be of the form T or *T where T is a type name."
// (ignore invalid types - error was reported before)
if rtyp != Typ[Invalid] {
var err string
switch T := rtyp.(type) {
case *Named:
T.resolve(check.bestContext(nil))
// The receiver type may be an instantiated type referred to
// by an alias (which cannot have receiver parameters for now).
if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
check.errorf(recv, _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
break
}
// spec: "The type denoted by T is called the receiver base type; it must not
// be a pointer or interface type and it must be declared in the same package
// as the method."
if T.obj.pkg != check.pkg {
err = "type not defined in this package"
if compilerErrorMessages {
check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
err = ""
}
} else {
// The underlying type of a receiver base type can be a type parameter;
// e.g. for methods with a generic receiver T[P] with type T[P any] P.
// TODO(gri) Such declarations are currently disallowed.
// Revisit the need for underIs.
underIs(T, func(u Type) bool {
switch u := u.(type) {
case *Basic:
// unsafe.Pointer is treated like a regular pointer
if u.kind == UnsafePointer {
err = "unsafe.Pointer"
return false
}
case *Pointer, *Interface:
err = "pointer or interface type"
return false
}
case *Pointer, *Interface:
err = "pointer or interface type"
return false
}
return true
})
return true
})
}
case *Basic:
err = "basic or unnamed type"
if compilerErrorMessages {
check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
err = ""
}
default:
check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
}
if err != "" {
check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
}
case *Basic:
err = "basic or unnamed type"
default:
check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
}
if err != "" {
check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
// ok to continue
}
}
sig.recv = recv
}).describef(recv, "validate receiver %s", recv)
}
sig.params = NewTuple(params...)

View File

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

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

@ -0,0 +1,29 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type RC[RG any] interface {
~[]RG
}
type Fn[RCT RC[RG], RG any] func(RCT)
type F[RCT RC[RG], RG any] interface {
Fn() Fn[RCT]
}
type concreteF[RCT RC[RG], RG any] struct {
makeFn func() Fn[RCT]
}
func (c *concreteF[RCT, RG]) Fn() Fn[RCT] {
return c.makeFn()
}
func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] {
return &concreteF[RCT]{
makeFn: nil,
}
}

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.
package p
type RC[RG any] interface {
~[]RG
}
type Fn[RCT RC[RG], RG any] func(RCT)
type FFn[RCT RC[RG], RG any] func() Fn[RCT]
type F[RCT RC[RG], RG any] interface {
Fn() Fn[RCT]
}
type concreteF[RCT RC[RG], RG any] struct {
makeFn FFn[RCT]
}
func (c *concreteF[RCT, RG]) Fn() Fn[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,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.
// 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() {}
func (/* ERROR got 1 type parameter, but receiver base type declares 2 */ T[_]) 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.Println /* ERROR cannot select on len */
len.Println /* ERROR cannot select on len */ ()
_ = len.Println /* ERROR cannot select on len */
_ = len /* ERROR cannot index len */ [0]
_ = *len /* ERROR cannot indirect len */
}

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

@ -7,9 +7,7 @@ package types
// 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.

View File

@ -35,6 +35,7 @@ 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()
@ -49,9 +50,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()
}
@ -95,9 +94,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
@ -138,16 +140,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).

View File

@ -37,7 +37,7 @@ func (s *_TypeSet) IsComparable(seen map[Type]bool) bool {
return s.comparable
}
return s.is(func(t *term) bool {
return t != nil && comparable(t.typ, seen, nil)
return t != nil && comparable(t.typ, false, seen, nil)
})
}
@ -101,9 +101,6 @@ func (s *_TypeSet) String() string {
// hasTerms reports whether the type set has specific type terms.
func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
// singleType returns the single type in s if there is exactly one; otherwise the result is nil.
func (s *_TypeSet) singleType() Type { return s.terms.singleType() }
// subsetOf reports whether s1 ⊆ s2.
func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }

View File

@ -323,7 +323,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
return typ
case *ast.InterfaceType:
typ := new(Interface)
typ := check.newInterface()
def.setUnderlying(typ)
if def != nil {
typ.obj = def.obj

View File

@ -79,7 +79,7 @@ func (check *Checker) validType0(typ Type, env *tparamEnv, path []Object) typeIn
// would have reported a type cycle and couldn't have been
// imported in the first place.
assert(t.obj.pkg == check.pkg)
t.underlying = Typ[Invalid] // t is in the current package (no race possibilty)
t.underlying = Typ[Invalid] // t is in the current package (no race possibility)
// Find the starting point of the cycle and report it.
for i, tn := range path {
if tn == t.obj {

View File

@ -703,6 +703,12 @@ var (
_ io.Reader = (*Buffers)(nil)
)
// WriteTo writes contents of the buffers to w.
//
// WriteTo implements io.WriterTo for Buffers.
//
// WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v),
// but does not modify v[i][j] for any i, j.
func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
if wv, ok := w.(buffersWriter); ok {
return wv.writeBuffers(v)
@ -719,6 +725,12 @@ func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
return n, nil
}
// Read from the buffers.
//
// Read implements io.Reader for Buffers.
//
// Read modifies the slice v as well as v[i] for 0 <= i < len(v),
// but does not modify v[i][j] for any i, j.
func (v *Buffers) Read(p []byte) (n int, err error) {
for len(p) > 0 && len(*v) > 0 {
n0 := copy(p, (*v)[0])

View File

@ -33,9 +33,14 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$432
ADD $LOCAL_REGARGS, RSP, R20
CALL runtime·spillArgs(SB)
MOVD R26, 32(RSP) // outside of moveMakeFuncArgPtrs's arg area
#ifdef GOEXPERIMENT_regabiargs
MOVD R26, R0
MOVD R20, R1
#else
MOVD R26, 8(RSP)
MOVD R20, 16(RSP)
CALL ·moveMakeFuncArgPtrs(SB)
#endif
CALL ·moveMakeFuncArgPtrs<ABIInternal>(SB)
MOVD 32(RSP), R26
MOVD R26, 8(RSP)
MOVD $argframe+0(FP), R3
@ -61,9 +66,14 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$432
ADD $LOCAL_REGARGS, RSP, R20
CALL runtime·spillArgs(SB)
MOVD R26, 32(RSP) // outside of moveMakeFuncArgPtrs's arg area
#ifdef GOEXPERIMENT_regabiargs
MOVD R26, R0
MOVD R20, R1
#else
MOVD R26, 8(RSP)
MOVD R20, 16(RSP)
CALL ·moveMakeFuncArgPtrs(SB)
#endif
CALL ·moveMakeFuncArgPtrs<ABIInternal>(SB)
MOVD 32(RSP), R26
MOVD R26, 8(RSP)
MOVD $argframe+0(FP), R3

View File

@ -229,16 +229,22 @@ store64loop:
// functions tail-call into the appropriate implementation, which
// means they must not open a frame. Hence, when they go down the
// panic path, at that point they push the LR to create a real frame
// (they don't need to pop it because panic won't return).
// (they don't need to pop it because panic won't return; however, we
// do need to set the SP delta back).
// Check if R1 is 8-byte aligned, panic if not.
// Clobbers R2.
#define CHECK_ALIGN \
AND.S $7, R1, R2 \
BEQ 4(PC) \
MOVW.W R14, -4(R13) /* prepare a real frame */ \
BL ·panicUnaligned(SB) \
ADD $4, R13 /* compensate SP delta */
TEXT ·Cas64(SB),NOSPLIT,$-4-21
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
// make unaligned atomic access panic
AND.S $7, R1, R2
BEQ 3(PC)
MOVW.W R14, -4(R13) // prepare a real frame
BL ·panicUnaligned(SB)
CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
@ -249,11 +255,7 @@ TEXT ·Cas64(SB),NOSPLIT,$-4-21
TEXT ·Xadd64(SB),NOSPLIT,$-4-20
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
// make unaligned atomic access panic
AND.S $7, R1, R2
BEQ 3(PC)
MOVW.W R14, -4(R13) // prepare a real frame
BL ·panicUnaligned(SB)
CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
@ -264,11 +266,7 @@ TEXT ·Xadd64(SB),NOSPLIT,$-4-20
TEXT ·Xchg64(SB),NOSPLIT,$-4-20
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
// make unaligned atomic access panic
AND.S $7, R1, R2
BEQ 3(PC)
MOVW.W R14, -4(R13) // prepare a real frame
BL ·panicUnaligned(SB)
CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
@ -279,11 +277,7 @@ TEXT ·Xchg64(SB),NOSPLIT,$-4-20
TEXT ·Load64(SB),NOSPLIT,$-4-12
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
// make unaligned atomic access panic
AND.S $7, R1, R2
BEQ 3(PC)
MOVW.W R14, -4(R13) // prepare a real frame
BL ·panicUnaligned(SB)
CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11
@ -294,11 +288,7 @@ TEXT ·Load64(SB),NOSPLIT,$-4-12
TEXT ·Store64(SB),NOSPLIT,$-4-12
NO_LOCAL_POINTERS
MOVW addr+0(FP), R1
// make unaligned atomic access panic
AND.S $7, R1, R2
BEQ 3(PC)
MOVW.W R14, -4(R13) // prepare a real frame
BL ·panicUnaligned(SB)
CHECK_ALIGN
MOVB runtime·goarm(SB), R11
CMP $7, R11

View File

@ -188,8 +188,12 @@ ret:
// func runtime·racefuncenter(pc uintptr)
// Called from instrumented code.
TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8
TEXT runtime·racefuncenter<ABIInternal>(SB), NOSPLIT, $0-8
#ifdef GOEXPERIMENT_regabiargs
MOVD R0, R9 // callpc
#else
MOVD callpc+0(FP), R9
#endif
JMP racefuncenter<>(SB)
// Common code for racefuncenter
@ -205,7 +209,7 @@ TEXT racefuncenter<>(SB), NOSPLIT, $0-0
// func runtime·racefuncexit()
// Called from instrumented code.
TEXT runtime·racefuncexit(SB), NOSPLIT, $0-0
TEXT runtime·racefuncexit<ABIInternal>(SB), NOSPLIT, $0-0
load_g
MOVD g_racectx(g), R0 // race context
// void __tsan_func_exit(ThreadState *thr);
@ -392,12 +396,12 @@ racecallatomic_ignore:
// Addr is outside the good range.
// Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
// An attempt to synchronize on the address would cause crash.
MOVD R9, R20 // remember the original function
MOVD R9, R21 // remember the original function
MOVD $__tsan_go_ignore_sync_begin(SB), R9
load_g
MOVD g_racectx(g), R0 // goroutine context
BL racecall<>(SB)
MOVD R20, R9 // restore the original function
MOVD R21, R9 // restore the original function
// Call the atomic function.
// racecall will call LLVM race code which might clobber R28 (g)
load_g
@ -424,10 +428,12 @@ TEXT runtime·racecall(SB), NOSPLIT, $0-0
JMP racecall<>(SB)
// Switches SP to g0 stack and calls (R9). Arguments already set.
TEXT racecall<>(SB), NOSPLIT, $0-0
// Clobbers R19, R20.
TEXT racecall<>(SB), NOSPLIT|NOFRAME, $0-0
MOVD g_m(g), R10
// Switch to g0 stack.
MOVD RSP, R19 // callee-saved, preserved across the CALL
MOVD R30, R20 // callee-saved, preserved across the CALL
MOVD m_g0(R10), R11
CMP R11, g
BEQ call // already on g0
@ -436,7 +442,7 @@ TEXT racecall<>(SB), NOSPLIT, $0-0
call:
BL R9
MOVD R19, RSP
RET
JMP (R20)
// C->Go callback thunk that allows to call runtime·racesymbolize from C code.
// Direct Go->C race call has only switched SP, finish g->g0 switch by setting correct g.

View File

@ -17,87 +17,91 @@ import (
//go:linkname syscall_syscall syscall.syscall
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscall()
//go:linkname syscall_syscallX syscall.syscallX
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscallX()
//go:linkname syscall_syscall6 syscall.syscall6
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscall6()
//go:linkname syscall_syscall6X syscall.syscall6X
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscall6X()
//go:linkname syscall_syscallPtr syscall.syscallPtr
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscallPtr()
//go:linkname syscall_rawSyscall syscall.rawSyscall
//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn))
return
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
return args.r1, args.r2, args.err
}
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn))
return
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
return args.r1, args.r2, args.err
}
// syscallNoErr is used in crypto/x509 to call into Security.framework and CF.
//go:linkname crypto_x509_syscall crypto/x509/internal/macos.syscall
//go:nosplit
//go:cgo_unsafe_args
func crypto_x509_syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1 uintptr) {
func crypto_x509_syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) (r1 uintptr) {
args := struct {
fn, a1, a2, a3, a4, a5 uintptr
f1 float64
r1 uintptr
}{fn, a1, a2, a3, a4, a5, f1, r1}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallNoErr)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_x509)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1
}
func syscallNoErr()
func syscall_x509()
// The *_trampoline functions convert from the Go calling convention to the C calling convention
// and then call the underlying libc function. They are defined in sys_darwin_$ARCH.s.

View File

@ -831,9 +831,10 @@ ok:
POPQ BP
RET
// syscallNoErr is like syscall6 but does not check for errors, and
// only returns one value, for use with standard C ABI library functions.
TEXT runtime·syscallNoErr(SB),NOSPLIT,$0
// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
// takes 5 uintptrs and 1 float64, and only returns one value,
// for use with standard C ABI functions.
TEXT runtime·syscall_x509(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
SUBQ $16, SP
@ -842,7 +843,7 @@ TEXT runtime·syscallNoErr(SB),NOSPLIT,$0
MOVQ (3*8)(DI), DX // a3
MOVQ (4*8)(DI), CX // a4
MOVQ (5*8)(DI), R8 // a5
MOVQ (6*8)(DI), R9 // a6
MOVQ (6*8)(DI), X0 // f1
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"

View File

@ -736,9 +736,10 @@ TEXT runtime·syscall6X(SB),NOSPLIT,$0
ok:
RET
// syscallNoErr is like syscall6 but does not check for errors, and
// only returns one value, for use with standard C ABI library functions.
TEXT runtime·syscallNoErr(SB),NOSPLIT,$0
// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
// takes 5 uintptrs and 1 float64, and only returns one value,
// for use with standard C ABI functions.
TEXT runtime·syscall_x509(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
MOVD R0, (RSP)
@ -747,7 +748,7 @@ TEXT runtime·syscallNoErr(SB),NOSPLIT,$0
MOVD 24(R0), R2 // a3
MOVD 32(R0), R3 // a4
MOVD 40(R0), R4 // a5
MOVD 48(R0), R5 // a6
FMOVD 48(R0), F0 // f1
MOVD 8(R0), R0 // a1
BL (R12)

View File

@ -10,7 +10,7 @@ package main
// This is a regression test for issue 14599, where profiling fails when the
// function is the first C function. Exported functions are the first C
// functions, so we use an exported function. Exported functions are created in
// lexigraphical order of source files, so this file is named aprof.go to
// lexicographical order of source files, so this file is named aprof.go to
// ensure its function is first.
// extern void CallGoNop();

View File

@ -17,10 +17,9 @@ type Builder struct {
buf []byte
}
// noescape hides a pointer from escape analysis. noescape is
// the identity function but escape analysis doesn't think the
// output depends on the input. noescape is inlined and currently
// compiles down to zero instructions.
// noescape hides a pointer from escape analysis. It is the identity function
// but escape analysis doesn't think the output depends on the input.
// noescape is inlined and currently compiles down to zero instructions.
// USE CAREFULLY!
// This was copied from the runtime; see issues 23382 and 7921.
//go:nosplit

View File

@ -0,0 +1,20 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
// Type I is the first basic test for the issue, which relates to a type that is recursive
// via a type constraint. (In this test, I -> IConstraint -> MyStruct -> I.)
type JsonRaw []byte
type MyStruct struct {
x *I[JsonRaw]
}
type IConstraint interface {
JsonRaw | MyStruct
}
type I[T IConstraint] struct {
}

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 main
import (
"a"
"fmt"
)
func main() {
var x a.I[a.JsonRaw]
fmt.Printf("%v\n", x)
}

View File

@ -0,0 +1,7 @@
// rundir -G=3
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,37 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
type Interaction[DataT InteractionDataConstraint] struct {
}
type InteractionDataConstraint interface {
[]byte |
UserCommandInteractionData
}
type UserCommandInteractionData struct {
resolvedInteractionWithOptions
}
type resolvedInteractionWithOptions struct {
Resolved Resolved `json:"resolved,omitempty"`
}
type Resolved struct {
Users ResolvedData[User] `json:"users,omitempty"`
}
type ResolvedData[T ResolvedDataConstraint] map[uint64]T
type ResolvedDataConstraint interface {
User | Message
}
type User struct{}
type Message struct {
Interaction *Interaction[[]byte] `json:"interaction,omitempty"`
}

View File

@ -0,0 +1,14 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package b
import (
"./a"
)
// InteractionRequest is an incoming request Interaction
type InteractionRequest[T a.InteractionDataConstraint] struct {
a.Interaction[T]
}

View File

@ -0,0 +1,14 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
import (
"./b"
)
// ResponseWriterMock mocks corde's ResponseWriter interface
type ResponseWriterMock struct {
x b.InteractionRequest[[]byte]
}

View File

@ -0,0 +1,7 @@
// compiledir -G=3
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored

View File

@ -0,0 +1,31 @@
// compile -G=3
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type RC[RG any] interface {
~[]RG
}
type Fn[RCT RC[RG], RG any] func(RCT)
type F[RCT RC[RG], RG any] interface {
Fn() Fn[RCT]
}
type concreteF[RCT RC[RG], RG any] struct {
makeFn func() Fn[RCT]
}
func (c *concreteF[RCT, RG]) Fn() Fn[RCT] {
return c.makeFn()
}
func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] {
return &concreteF[RCT]{
makeFn: nil,
}
}

View File

@ -0,0 +1,22 @@
// compile -G=3
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type RC[RG any] interface {
~[]RG
}
type Fn[RCT RC[RG], RG any] func(RCT)
type FFn[RCT RC[RG], RG any] func() Fn[RCT]
type F[RCT RC[RG], RG any] interface {
Fn() Fn[RCT]
}
type concreteF[RCT RC[RG], RG any] struct {
makeFn FFn[RCT]
}
func (c *concreteF[RCT, RG]) Fn() Fn[RCT] {
return c.makeFn()
}

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