diff options
330 files changed, 5520 insertions, 2670 deletions
diff --git a/.mailmap b/.mailmap index d72e6ebcb65..30c3212810c 100644 --- a/.mailmap +++ b/.mailmap @@ -7,51 +7,98 @@ Aaron Todd <github@opprobrio.us> Abhishek Chanda <abhishek.becs@gmail.com> Abhishek Chanda <abhishek@cloudscaling.com> +Abhijeet Bhagat <abhijeet.bhagat@gmx.com> +Abroskin Alexander <arkweid@evilmartians.com> Adolfo Ochagavía <aochagavia92@gmail.com> +Adrian Heine né Lang <mail@adrianheine.de> Adrien Tétar <adri-from-59@hotmail.fr> Ahmed Charles <ahmedcharles@gmail.com> <acharles@outlook.com> +Alan Egerton <eggyal@gmail.com> +Alan Stoate <alan.stoate@gmail.com> +Alessandro Decina <alessandro.d@gmail.com> Alex Burka <durka42+github@gmail.com> Alex Burka <aburka@seas.upenn.edu> +Alex Hansen <ahansen2@trinity.edu> Alex Lyon <arcterus@mail.com> <Arcterus@mail.com> Alex Newman <posix4e@gmail.com> Alex HotShot Newman <posix4e@gmail.com> Alex Rønne Petersen <alex@lycus.org> +Alex Vlasov <alex.m.vlasov@gmail.com> +Alex von Gluck IV <kallisti5@unixzen.com> Alexander Light <allight@cs.brown.edu> Alexander Light <scialexlight@gmail.com> +Alexander Ronald Altman <alexanderaltman@me.com> +Alexandre Martin <martin.alex32@hotmail.fr> Alexis Beingessner <a.beingessner@gmail.com> Alfie John <alfie@alfie.wtf> Alfie John <alfiej@fastmail.fm> +Amos Onn <amosonn@gmail.com> +Ana-Maria Mihalache <mihalacheana.maria@yahoo.com> Anatoly Ikorsky <aikorsky@gmail.com> Andre Bogus <bogusandre@gmail.com> +Andrea Ciliberti <meziu210@icloud.com> Andreas Gal <gal@mozilla.com> <andreas.gal@gmail.com> +Andreas Jonson <andjo403@users.noreply.github.com> +Andrew Gauger <andygauge@gmail.com> Andrew Kuchev <0coming.soon@gmail.com> Andrew <0coming.soon@gmail.com> +Andrew Lamb <andrew@nerdnetworks.org> Andrew Poelstra <asp11@sfu.ca> <apoelstra@wpsoftware.net> +Anhad Singh <andypythonappdeveloper@gmail.com> +Antoine Plaskowski <antoine.plaskowski@epitech.eu> Anton Löfgren <anton.lofgren@gmail.com> <alofgren@op5.com> +Araam Borhanian <avborhanian@gmail.com> +Araam Borhanian <avborhanian@gmail.com> <dobbybabee@gmail.com> Areski Belaid <areski@gmail.com> areski <areski@gmail.com> Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> Ariel Ben-Yehuda <ariel.byd@gmail.com> Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> arielb1 <arielb1@mail.tau.ac.il> +Artem Chernyak <artemchernyak@gmail.com> +Arthur Cohen <arthur.cohen@epita.fr> +Arthur Silva <arthurprs@gmail.com> +Arthur Woimbée <arthur.woimbee@gmail.com> +Artyom Pavlov <newpavlov@gmail.com> Austin Seipp <mad.one@gmail.com> <as@hacks.yi.org> +Ayaz Hafiz <ayaz.hafiz.1@gmail.com> Aydin Kim <ladinjin@hanmail.net> aydin.kim <aydin.kim@samsung.com> +Ayush Mishra <ayushmishra2005@gmail.com> +asrar <aszenz@gmail.com> +BaoshanPang <pangbw@gmail.com> Barosl Lee <vcs@barosl.com> Barosl LEE <github@barosl.com> +Bastian Kersting <bastian@cmbt.de> +Bastien Orivel <eijebong@bananium.fr> Ben Alpert <ben@benalpert.com> <spicyjalapeno@gmail.com> -Ben Sago <ogham@users.noreply.github.com> Ben S <ogham@bsago.me> -Ben Sago <ogham@users.noreply.github.com> Ben S <ogham@users.noreply.github.com> +Ben Lewis <benlewisj@gmail.com> +Ben Sago <ogham@users.noreply.github.com> +Ben Sago <ogham@users.noreply.github.com> <ogham@bsago.me> +Ben Striegel <ben.striegel@gmail.com> Benjamin Jackman <ben@jackman.biz> +Benoît Cortier <benoit.cortier@fried-world.eu> Bheesham Persaud <bheesham123@hotmail.com> Bheesham Persaud <bheesham.persaud@live.ca> Björn Steinbrink <bsteinbr@gmail.com> <B.Steinbrink@gmx.de> blake2-ppc <ulrik.sverdrup@gmail.com> <blake2-ppc> +boolean_coercion <booleancoercion@gmail.com> Boris Egorov <jightuse@gmail.com> <egorov@linux.com> +Braden Nelson <moonheart08@users.noreply.github.com> Brandon Sanderson <singingboyo@gmail.com> Brandon Sanderson <singingboyo@hotmail.com> Brett Cannon <brett@python.org> Brett Cannon <brettcannon@users.noreply.github.com> Brian Anderson <banderson@mozilla.com> <andersrb@gmail.com> Brian Anderson <banderson@mozilla.com> <banderson@mozilla.org> +Brian Bowman <seeker14491@gmail.com> +Brian Cain <brian.cain@gmail.com> Brian Dawn <brian.t.dawn@gmail.com> Brian Leibig <brian@brianleibig.com> Brian Leibig <brian.leibig@gmail.com> +Caleb Cartwright <caleb.cartwright@outlook.com> +Caleb Jones <code@calebjones.net> Noah Lev <camelidcamel@gmail.com> Noah Lev <camelidcamel@gmail.com> <37223377+camelid@users.noreply.github.com> +cameron1024 <cameron.studdstreet@gmail.com> +Camille Gillot <gillot.camille@gmail.com> Carl-Anton Ingmarsson <mail@carlanton.se> <ca.ingmarsson@gmail.com> +Carlo Teubner <carlo.teubner@gmail.com> Carol (Nichols || Goulding) <carol.nichols@gmail.com> <193874+carols10cents@users.noreply.github.com> Carol (Nichols || Goulding) <carol.nichols@gmail.com> <carol.nichols@gmail.com> Carol (Nichols || Goulding) <carol.nichols@gmail.com> <cnichols@thinkthroughmath.com> Carol Willing <carolcode@willingconsulting.com> +Chandler Deng <chandde@microsoft.com> Charles Lew <crlf0710@gmail.com> CrLF0710 <crlf0710@gmail.com> Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com> +Chris Gregory <czipperz@gmail.com> +Chris Pardy <chrispardy36@gmail.com> Chris Pressey <cpressey@gmail.com> Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com> Chris Vittal <christopher.vittal@gmail.com> Christopher Vittal <christopher.vittal@gmail.com> @@ -62,29 +109,53 @@ Christian Poveda <git@christianpoveda.xyz> <christianpoveda@protonmail.com> Christian Poveda <git@christianpoveda.xyz> <cn.poveda.ruiz@gmail.com> Christian Poveda <git@christianpoveda.xyz> <z1mvader@protonmail.com> Christian Poveda <git@christianpoveda.xyz> <cpovedar@fnal.gov> +Christian Vallentin <vallentinsource@gmail.com> +Christoffer Buchholz <chris@chrisbuchholz.me> +Christopher Durham <cad97@cad97.com> Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com> +Clement Miao <clementmiao@gmail.com> +Clément Renault <renault.cle@gmail.com> +Cliff Dyer <jcd@sdf.org> Clinton Ryan <clint.ryan3@gmail.com> Corey Richardson <corey@octayn.net> Elaine "See More" Nemo <corey@octayn.net> +Crazycolorz5 <Crazycolorz5@gmail.com> +csmoe <35686186+csmoe@users.noreply.github.com> Cyryl Płotnicki <cyplo@cyplo.net> Damien Schoof <damien.schoof@gmail.com> +Dan Robertson <danlrobertson89@gmail.com> +Daniel Campoverde <alx741@riseup.net> Daniel J Rollins <drollins@financialforce.com> +Daniel Mueller <deso@posteo.net> Daniel Ramos <dan@daramos.com> +Daniele D'Orazio <d.dorazio96@gmail.com> +Dante Broggi <34220985+Dante-Broggi@users.noreply.github.com> +David Carlier <devnexen@gmail.com> David Klein <david.klein@baesystemsdetica.com> David Manescu <david.manescu@gmail.com> <dman2626@uni.sydney.edu.au> David Ross <daboross@daboross.net> David Wood <david@davidtw.co> <david.wood@huawei.com> +Deadbeef <ent3rm4n@gmail.com> Deadbeef <ent3rm4n@gmail.com> <fee1-dead-beef@protonmail.com> Derek Chiang <derekchiang93@gmail.com> Derek Chiang (Enchi Jiang) <derekchiang93@gmail.com> +DeveloperC <DeveloperC@protonmail.com> +Devin Ragotzy <devin.ragotzy@gmail.com> +Dharma Saputra Wijaya <dswijj@gmail.com> Diggory Hardy <diggory.hardy@gmail.com> Diggory Hardy <github@dhardy.name> +Dileep Bapat <dileepbapat@gmail.com> Donough Liu <ldm2993593805@163.com> <donoughliu@gmail.com> Donough Liu <ldm2993593805@163.com> DingMing Liu <liudingming@bupt.edu.cn> Dustin Bensing <dustin.bensing@googlemail.com> +DutchGhost <kasper199914@gmail.com> Dylan Braithwaite <dylanbraithwaite1@gmail.com> <mail@dylanb.me> +Dylan DPC <dylan.dpc@gmail.com> +Dylan MacKenzie <ecstaticmorse@gmail.com> Dzmitry Malyshau <kvarkus@gmail.com> E. Dunham <edunham@mozilla.com> edunham <edunham@mozilla.com> +Ed Barnard <eabarnard@gmail.com> Eduard-Mihai Burtescu <edy.burt@gmail.com> Eduardo Bautista <me@eduardobautista.com> <=> Eduardo Bautista <me@eduardobautista.com> <mail@eduardobautista.com> +Eduardo Broto <ebroto@tutanota.com> Elliott Slaughter <elliottslaughter@gmail.com> <eslaughter@mozilla.com> Elly Fong-Jones <elly@leptoquark.net> Eric Holk <eric.holk@gmail.com> <eholk@cs.indiana.edu> @@ -92,46 +163,82 @@ Eric Holk <eric.holk@gmail.com> <eholk@mozilla.com> Eric Holmes <eric@ejholmes.net> Eric Reed <ecreed@cs.washington.edu> <ereed@mozilla.com> Erick Tryzelaar <erick.tryzelaar@gmail.com> <etryzelaar@iqt.org> +Erik Desjardins <erikdesjardins@users.noreply.github.com> +Erik Jensen <erikjensen@rkjnsn.net> +Erin Power <xampprocky@gmail.com> Erin Power <xampprocky@gmail.com> <theaaronepower@gmail.com> Erin Power <xampprocky@gmail.com> <Aaronepower@users.noreply.github.com> +Esteban Küber <esteban@kuber.com.ar> Esteban Küber <esteban@kuber.com.ar> <esteban@commure.com> Esteban Küber <esteban@kuber.com.ar> <estebank@users.noreply.github.com> Esteban Küber <esteban@kuber.com.ar> <github@kuber.com.ar> +Ethan Dagner <napen123@gmail.com> Evgeny Sologubov +F001 <changchun.fan@qq.com> +Fabian Kössel <fkjogu@users.noreply.github.com> Falco Hirschenberger <falco.hirschenberger@gmail.com> <hirschen@itwm.fhg.de> Felix S. Klock II <pnkfelix@pnkfx.org> Felix S Klock II <pnkfelix@pnkfx.org> +Félix Saparelli <felix@passcod.name> Flaper Fesp <flaper87@gmail.com> +Florian Berger <fbergr@gmail.com> Florian Wilkens <mrfloya_github@outlook.com> Florian Wilkens <floya@live.de> +François Mockers <mockersf@gmail.com> Frank Steffahn <fdsteffahn@gmail.com> <frank.steffahn@stu.uni-kiel.de> +Fridtjof Stoldt <xFrednet@gmail.com> +fukatani <nannyakannya@gmail.com> +Fuqiao Xue <xfq.free@gmail.com> Gareth Daniel Smith <garethdanielsmith@gmail.com> gareth <gareth@gareth-N56VM.(none)> Gareth Daniel Smith <garethdanielsmith@gmail.com> Gareth Smith <garethdanielsmith@gmail.com> +Gauri Kholkar <f2013002@goa.bits-pilani.ac.in> Georges Dubus <georges.dubus@gmail.com> <georges.dubus@compiletoi.net> +Giles Cope <gilescope@gmail.com> +Glen De Cauwsemaecker <decauwsemaecker.glen@gmail.com> Graham Fawcett <graham.fawcett@gmail.com> Graham Fawcett <fawcett@uwindsor.ca> Graydon Hoare <graydon@pobox.com> Graydon Hoare <graydon@mozilla.com> +Greg V <greg@unrelenting.technology> +Gregor Peach <gregorpeach@gmail.com> +Grzegorz Bartoszek <grzegorz.bartoszek@thaumatec.com> +Guanqun Lu <guanqun.lu@gmail.com> Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume1.gomez@gmail.com> ggomez <ggomez@ggo.ifr.lan> Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <ggomez@ggo.ifr.lan> Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume.gomez@huawei.com> +hamidreza kalbasi <hamidrezakalbasi@protonmail.com> Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com> Heather <heather@cynede.net> <Cynede@Gentoo.org> Heather <heather@cynede.net> <Heather@cynede.net> Herman J. Radtke III <herman@hermanradtke.com> Herman J. Radtke III <hermanradtke@gmail.com> Hirochika Matsumoto <git@hkmatsumoto.com> <matsujika@gmail.com> +Hrvoje Nikšić <hniksic@gmail.com> +Hsiang-Cheng Yang <rick68@users.noreply.github.com> Ian Jackson <ijackson@chiark.greenend.org.uk> <ian.jackson@citrix.com> Ian Jackson <ijackson@chiark.greenend.org.uk> <ijackson+github@slimy.greenend.org.uk> Ian Jackson <ijackson@chiark.greenend.org.uk> <iwj@xenproject.org> +Ibraheem Ahmed <ibrah1440@gmail.com> Ilyong Cho <ilyoan@gmail.com> inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> +Irina Popa <irinagpopa@gmail.com> Ivan Ivaschenko <defuz.net@gmail.com> +ivan tkachenko <me@ratijas.tk> J. J. Weber <jjweber@gmail.com> +Jack Huey <jack.huey@umassmed.edu> +Jacob <jacob.macritchie@gmail.com> +Jacob Greenfield <xales@naveria.com> Jacob Pratt <jacob@jhpratt.dev> <the.z.cuber@gmail.com> +Jake Vossen <jake@vossen.dev> +Jakob Degen <jakob@degen.com> +Jakob Lautrup Nysom <jako3047@gmail.com> +Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub.bukaj@yahoo.com> Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub@jakub.cc> Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakubw@jakubw.net> +James [Undefined] <tpzker@thepuzzlemaker.info> James Deng <cnjamesdeng@gmail.com> <cnJamesDeng@gmail.com> James Hinshelwood <jameshinshelwood1@gmail.com> <james.hinshelwood@bigpayme.com> James Miller <bladeon@gmail.com> <james@aatch.net> James Perry <james.austin.perry@gmail.com> +James Sanderson <zofrex@gmail.com> +Jaro Fietz <jaro.fietz@gmx.de> Jason Fager <jfager@gmail.com> Jason Liquorish <jason@liquori.sh> <Bassetts@users.noreply.github.com> Jason Orendorff <jorendorff@mozilla.com> <jason.orendorff@gmail.com> @@ -140,33 +247,60 @@ Jason Toffaletti <toffaletti@gmail.com> Jason Toffaletti <jason@topsy.com> Jauhien Piatlicki <jauhien@gentoo.org> Jauhien Piatlicki <jpiatlicki@zertisa.com> Jay True <glacjay@gmail.com> Jeremy Letang <letang.jeremy@gmail.com> +Jeremy Sorensen <jeremy.a.sorensen@gmail.com> Jeremy Stucki <dev@jeremystucki.ch> <stucki.jeremy@gmail.com> Jeremy Stucki <dev@jeremystucki.ch> <jeremy@myelin.ch> Jeremy Stucki <dev@jeremystucki.ch> +Jerry Hardee <hardeejj9@gmail.com> +Jesús Rubio <jesusprubio@gmail.com> Jethro Beekman <github@jbeekman.nl> +Jian Zeng <knight42@mail.ustc.edu.cn> Jihyun Yu <j.yu@navercorp.com> <yjh0502@gmail.com> Jihyun Yu <j.yu@navercorp.com> jihyun <jihyun@nablecomm.com> Jihyun Yu <j.yu@navercorp.com> Jihyun Yu <jihyun@nclab.kaist.ac.kr> João Oliveira <hello@jxs.pt> joaoxsouls <joaoxsouls@gmail.com> +joboet <jonasboettiger@icloud.com> Johann Hofmann <git@johann-hofmann.com> Johann <git@johann-hofmann.com> John Clements <clements@racket-lang.org> <clements@brinckerhoff.org> John Hodge <acessdev@gmail.com> John Hodge <tpg@mutabah.net> +John Hörnvall <trolledwoods@gmail.com> John Kåre Alsaker <john.kare.alsaker@gmail.com> John Talling <inrustwetrust@users.noreply.github.com> +John Van Enk <vanenkj@gmail.com> +Jonas Tepe <jonasprogrammer@gmail.com> Jonathan Bailey <jbailey@mozilla.com> <jbailey@jbailey-20809.local> +Jonathan Chan Kwan Yin <sofe2038@gmail.com> +Jonathan L <Xmasreturns@users.noreply.github.com> Jonathan S <gereeter@gmail.com> Jonathan S <gereeter+code@gmail.com> +Jonathan Sieber <mail@strfry.org> Jonathan Turner <probata@hotmail.com> Jorge Aparicio <japaric@linux.com> <japaricious@gmail.com> +Josef Reinhard Brandl <mail@josefbrandl.de> +Joseph Dunne <jd@lambda.tech> Joseph Martin <pythoner6@gmail.com> +Joseph Richey <joerichey@google.com> +Joseph T. Lyons <JosephTLyons@gmail.com> Joseph T. Lyons <JosephTLyons@gmail.com> <josephtlyons@gmail.com> Joseph T. Lyons <JosephTLyons@gmail.com> <JosephTLyons@users.noreply.github.com> +Josh Cotton <jcotton42@outlook.com> +Josh Driver <keeperofdakeys@gmail.com> +Josh Holmer <jholmer.in@gmail.com> Joshua Nelson <jyn514@gmail.com> <joshua@yottadb.com> +Julian Knodt <julianknodt@gmail.com> jumbatm <jumbatm@gmail.com> <30644300+jumbatm@users.noreply.github.com> Junyoung Cho <june0.cho@samsung.com> Jyun-Yan You <jyyou.tw@gmail.com> <jyyou@cs.nctu.edu.tw> +Kalita Alexey <kalita.alexey@outlook.com> +Kampfkarren <boynedmaster@gmail.com> Kang Seonghoon <kang.seonghoon@mearie.org> <public+git@mearie.org> +Karim Snj <karim.snj@gmail.com> +Katze <binary@benary.org> Keegan McAllister <mcallister.keegan@gmail.com> <kmcallister@mozilla.com> +Kerem Kat <keremkat@gmail.com> Kevin Butler <haqkrs@gmail.com> +Kevin Jiang <kwj2104@columbia.edu> +Kornel Lesiński <kornel@geekhood.net> +Krishna Sai Veera Reddy <veerareddy@email.arizona.edu> Kyeongwoon Lee <kyeongwoon.lee@samsung.com> Kyle J Strand <batmanaod@gmail.com> <BatmanAoD@users.noreply.github.com> Kyle J Strand <batmanaod@gmail.com> <kyle.j.strand@gmail.com> @@ -176,57 +310,102 @@ Laurențiu Nicola <lnicola@dend.ro> lcnr <rust@lcnr.de> <bastian_kauschke@hotmail.de> Lee Jeffery <leejeffery@gmail.com> Lee Jeffery <lee@leejeffery.co.uk> Lee Wondong <wdlee91@gmail.com> +lengyijun <sjtu5140809011@gmail.com> Lennart Kudling <github@kudling.de> Léo Lanteri Thauvin <leseulartichaut@gmail.com> Léo Lanteri Thauvin <leseulartichaut@gmail.com> <38361244+LeSeulArtichaut@users.noreply.github.com> Léo Testard <leo.testard@gmail.com> +Leonardo Yvens <leoyvens@gmail.com> +Liigo Zhuang <liigo@qq.com> Lily Ballard <lily@ballards.net> <kevin@sb.org> Lindsey Kuper <lindsey@composition.al> <lindsey@rockstargirl.org> Lindsey Kuper <lindsey@composition.al> <lkuper@mozilla.com> +Liu Dingming <liudingming@bytedance.com> +Loo Maclin <loo.maclin@protonmail.com> +Loïc BRANSTETT <lolo.branstett@numericable.fr> +Lucy <luxx4x@protonmail.com> +Lukas H. <lukaramu@users.noreply.github.com> +Lukas Lueg <lukas.lueg@gmail.com> Luke Metz <luke.metz@students.olin.edu> Luqman Aden <me@luqman.ca> <laden@csclub.uwaterloo.ca> Luqman Aden <me@luqman.ca> <laden@mozilla.com> +Lzu Tao <taolzu@gmail.com> +Maik Klein <maikklein@googlemail.com> +Malo Jaffré <jaffre.malo@gmail.com> Manish Goregaokar <manishsmail@gmail.com> +Mara Bos <m-ou.se@m-ou.se> Marcell Pardavi <marcell.pardavi@gmail.com> +Marcus Klaas de Vries <mail@marcusklaas.nl> Margaret Meyerhofer <mmeyerho@andrew.cmu.edu> <mmeyerho@andrew> +Mark Mansi <markm@cs.wisc.edu> Mark Rousskov <mark.simulacrum@gmail.com> Mark Sinclair <mark.edward.x@gmail.com> Mark Sinclair <mark.edward.x@gmail.com> =Mark Sinclair <=125axel125@gmail.com> +Markus Legner <markus@legner.ch> Markus Westerlind <marwes91@gmail.com> Markus <marwes91@gmail.com> +Martin Carton <cartonmartin+git@gmail.com> +Martin Habovštiak <martin.habovstiak@gmail.com> Martin Hafskjold Thoresen <martinhath@gmail.com> Matej Lach <matej.lach@gmail.com> Matej Ľach <matej.lach@gmail.com> +Mateusz Mikuła <mati865@gmail.com> Mateusz Mikuła <mati865@gmail.com> <mati865@users.noreply.github.com> Mateusz Mikuła <mati865@gmail.com> <matti@marinelayer.io> Matt Brubeck <mbrubeck@limpet.net> <mbrubeck@cs.hmc.edu> Matthew Auld <matthew.auld@intel.com> +Matthew Jasper <mjjasper1@gmail.com> Matthew Kraai <kraai@ftbfs.org> Matthew Kraai <kraai@ftbfs.org> <matt.kraai@abbott.com> Matthew Kraai <kraai@ftbfs.org> <mkraai@its.jnj.com> Matthew McPherrin <matthew@mcpherrin.ca> <matt@mcpherrin.ca> +Matthew Tran <0e4ef622@gmail.com> Matthijs Hofstra <thiezz@gmail.com> +Max Sharnoff <github@max.sharnoff.org> +Max Wase <max.vvase@gmail.com> +Mazdak Farrokhzad <twingoow@gmail.com> +Meade Kincke <thedarkula2049@gmail.com> Melody Horn <melody@boringcactus.com> <mathphreak@gmail.com> +Mendes <pedro.mendes.26@gmail.com> +mental <m3nta1@yahoo.com> +mibac138 <5672750+mibac138@users.noreply.github.com> Michael Williams <m.t.williams@live.com> Michael Woerister <michaelwoerister@posteo> <michaelwoerister@gmail> Michael Woerister <michaelwoerister@posteo> <michaelwoerister@users.noreply.github.com> Michael Woerister <michaelwoerister@posteo> <michaelwoerister@posteo.net> +Michael Zhang <hmperson1@gmail.com> +Michał Krasnoborski <mkrdln@gmail.com> +Michiel De Muynck <michieldemuynck@gmail.com> Mickaël Raybaud-Roig <raybaudroigm@gmail.com> m-r-r <raybaudroigm@gmail.com> +Mikhail Babenko <misha-babenko@yandex.ru> +Milan Landaverde <milanlandaverde@gmail.com> +mjptree <michael.prantl@hotmail.de> Ms2ger <ms2ger@gmail.com> <Ms2ger@gmail.com> +msizanoen1 <qtmlabs@protonmail.com> Mukilan Thiagarajan <mukilanthiagarajan@gmail.com> +Nadrieril Feneanar <Nadrieril@users.noreply.github.com> NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm@gmail.com> NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm+github@gmail.com> +Nathan Ringo <remexre@gmail.com> Nathan West <Lucretiel@gmail.com> <lucretiel@gmail.com> +Nathan Whitaker <nathan.whitaker01@gmail.com> Nathan Wilson <wilnathan@gmail.com> +Nathaniel Hamovitz <18648574+nhamovitz@users.noreply.github.com> Nathaniel Herman <nherman@post.harvard.edu> Nathaniel Herman <nherman@college.harvard.edu> Neil Pankey <npankey@gmail.com> <neil@wire.im> +Ngo Iok Ui (Wu Yu Wei) <wusyong9104@gmail.com> +Nicholas Baron <nicholas.baron.ten@gmail.com> Nick Platt <platt.nicholas@gmail.com> +Niclas Schwarzlose <15schnic@gmail.com> +Nicolas Abram <abramlujan@gmail.com> Nicole Mazzuca <npmazzuca@gmail.com> Nif Ward <nif.ward@gmail.com> Nika Layzell <nika@thelayzells.com> <michael@thelayzells.com> +Nixon Enraght-Moony <nixon.emoony@gmail.com> +NODA Kai <nodakai@gmail.com> +oliver <16816606+o752d@users.noreply.github.com> Oliver Middleton <olliemail27@gmail.com> <ollie27@users.noreply.github.com> Oliver Scherer <oliver.schneider@kit.edu> <git-spam-no-reply9815368754983@oli-obk.de> Oliver Scherer <oliver.schneider@kit.edu> <git-spam9815368754983@oli-obk.de> Oliver Scherer <oliver.schneider@kit.edu> <github333195615777966@oli-obk.de> -Oliver Scherer <oliver.schneider@kit.edu> <github6541940@oli-obk.de> Oliver Scherer <oliver.schneider@kit.edu> <rust19446194516@oli-obk.de> Oliver Scherer <oliver.schneider@kit.edu> <git-no-reply-9879165716479413131@oli-obk.de> Oliver Scherer <oliver.schneider@kit.edu> <git1984941651981@oli-obk.de> @@ -236,76 +415,139 @@ Oliver Scherer <oliver.schneider@kit.edu> <oli-obk@users.noreply.github.com> Oliver Scherer <oliver.schneider@kit.edu> <public.oliver.schneider@kit.edu> Oliver Scherer <oliver.schneider@kit.edu> <obk8176014uqher834@olio-obk.de> Oliver Scherer <oliver.schneider@kit.edu> +Ömer Sinan Ağacan <omeragacan@gmail.com> +Ophir LOJKINE <pere.jobs@gmail.com> Ožbolt Menegatti <ozbolt.menegatti@gmail.com> gareins <ozbolt.menegatti@gmail.com> +Pankaj Chaudhary <pankajchaudhary172@gmail.com> Paul Faria <paul_faria@ultimatesoftware.com> Paul Faria <Nashenas88@gmail.com> Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com> parir <peer.aramillo.irizar@gmail.com> Peter Elmers <peter.elmers@yahoo.com> <peter.elmers@rice.edu> Peter Liniker <peter.liniker+github@gmail.com> Phil Dawes <phil@phildawes.net> Phil Dawes <pdawes@drw.com> +Phil Hansch <dev@phansch.net> Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com> Philipp Brüschweiler <blei42@gmail.com> <bruphili@student.ethz.ch> -Philipp Krones <hello@philkrones.com> flip1995 <hello@philkrones.com> +Philipp Krones <hello@philkrones.com> +Philipp Krones <hello@philkrones.com> <9744647+flip1995@users.noreply.github.com> Philipp Krones <hello@philkrones.com> <philipp.krones@embecosm.com> +Philipp Krones <hello@philkrones.com> <uwdkn@student.kit.edu> Philipp Matthias Schäfer <philipp.matthias.schaefer@posteo.de> +phosphorus <steepout@qq.com> +Pierre Krieger <pierre.krieger1708@gmail.com> pierwill <pierwill@users.noreply.github.com> <19642016+pierwill@users.noreply.github.com> +Pradyumna Rahul <prkinformed@gmail.com> Przemysław Wesołek <jest@go.art.pl> Przemek Wesołek <jest@go.art.pl> +r00ster <r00ster91@protonmail.com> Rafael Ávila de Espíndola <respindola@mozilla.com> Rafael Avila de Espindola <espindola@dream.(none)> +rail <12975677+rail-rain@users.noreply.github.com> Ralph Giles <giles@thaumas.net> Ralph Giles <giles@mozilla.com> Ramkumar Ramachandra <r@artagnon.com> <artagnon@gmail.com> +Raphaël Huchet <rap2hpoutre@users.noreply.github.com> +rChaser53 <tayoshizawa29@gmail.com> +Rémy Rakic <remy.rakic@gmail.com> +Rémy Rakic <remy.rakic@gmail.com> <remy.rakic+github@gmail.com> Renato Riccieri Santos Zannon <renato@rrsz.com.br> Richard Diamond <wichard@vitalitystudios.com> <wichard@hahbee.co> +Ricky Hosfelt <ricky@hosfelt.io> +Ritiek Malhotra <ritiekmalhotra123@gmail.com> Rob Arnold <robarnold@cs.cmu.edu> Rob Arnold <robarnold@cs.cmu.edu> Rob Arnold <robarnold@68-26-94-7.pools.spcsdns.net> Robert Foss <dev@robertfoss.se> robertfoss <dev@robertfoss.se> Robert Gawdzik <rgawdzik@hotmail.com> Robert Gawdzik ☢ <rgawdzik@hotmail.com> +Robert Habermeier <rphmeier@gmail.com> Robert Millar <robert.millar@cantab.net> +Roc Yu <rocyu@protonmail.com> Rohit Joshi <rohitjoshi@users.noreply.github.com> Rohit Joshi <rohit.joshi@capitalone.com> +Roxane Fruytier <roxane.fruytier@hotmail.com> +Rui <xiongmao86dev@sina.com> Russell Johnston <rpjohnst@gmail.com> +Rustin-Liu <rustin.liu@gmail.com> +Rusty Blitzerr <rusty.blitzerr@gmail.com> +RustyYato <krishna.sd.2012@gmail.com> Ruud van Asseldonk <dev@veniogames.com> Ruud van Asseldonk <ruuda@google.com> +Ryan Leung <rleungx@gmail.com> Ryan Scheel <ryan.havvy@gmail.com> +Ryan Sullivant <rsulli55@gmail.com> +Ryan Wiedemann <Ryan1729@gmail.com> S Pradeep Kumar <gohanpra@gmail.com> +Sam Radhakrishnan <sk09idm@gmail.com> +Scott McMurray <scottmcm@users.noreply.github.com> Scott Olson <scott@solson.me> Scott Olson <scott@scott-olson.org> Sean Gillespie <sean.william.g@gmail.com> swgillespie <sean.william.g@gmail.com> +Seiichi Uchida <seuchida@gmail.com> Seonghyun Kim <sh8281.kim@samsung.com> +Shohei Wada <pc@wada314.jp> +Shotaro Yamada <sinkuu@sinkuu.xyz> +Shotaro Yamada <sinkuu@sinkuu.xyz> <sinkuu@users.noreply.github.com> Shyam Sundar B <shyambaskaran@outlook.com> Simon Barber-Dueck <sbarberdueck@gmail.com> Simon BD <simon@server> Simon Sapin <simon@exyr.org> <simon.sapin@exyr.org> Simonas Kazlauskas <git@kazlauskas.me> Simonas Kazlauskas <github@kazlauskas.me> +Siva Prasad <sivaauturic@gmail.com> +Smittyvb <me@smitop.com> +Srinivas Reddy Thatiparthy <thatiparthysreenivas@gmail.com> +Stanislav Tkach <stanislav.tkach@gmail.com> startling <tdixon51793@gmail.com> Stepan Koltsov <stepan.koltsov@gmail.com> Stepan Koltsov <nga@yandex-team.ru> Steve Klabnik <steve@steveklabnik.com> Steven Fackler <sfackler@gmail.com> <sfackler@palantir.com> +Steven Malis <smmalis37@gmail.com> Steven Stewart-Gallus <sstewartgallus00@langara.bc.ca> <sstewartgallus00@mylangara.bc.ca> Stuart Pernsteiner <stuart@pernsteiner.org> Stuart Pernsteiner <spernsteiner@mozilla.com> +Suyash458 <suyash.behera458@gmail.com> +Sébastien Marie <semarie@online.fr> +Takashi Idobe <idobetakashi@gmail.com> +Takayuki Maeda <takoyaki0316@gmail.com> Tamir Duberstein <tamird@gmail.com> Tamir Duberstein <tamird@squareup.com> +Tatsuyuki Ishi <ishitatsuyuki@gmail.com> Tero Hänninen <lgvz@users.noreply.github.com> Tero Hänninen <tejohann@kapsi.fi> +The8472 <git@infinite-source.de> Theo Belaire <theo.belaire@gmail.com> Theo Belaire <tyr.god.of.war.42@gmail.com> +Theodore Luo Wang <wangtheo662@gmail.com> Thiago Pontes <email@thiago.me> thiagopnts <thiagopnts@gmail.com> Thomas Bracht Laumann Jespersen <laumann.thomas@gmail.com> +Tibo Delor <delor.thibault@gmail.com> Ticki <Ticki@users.noreply.github.com> Ticki <@> Tim Brooks <brooks@cern.ch> Tim Brooks <tim.brooks@staples.com> Tim Chevalier <chevalier@alum.wellesley.edu> <catamorphism@gmail.com> +Tim Diekmann <t.diekmann.3dv@gmail.com> +Tim Hutt <tdhutt@gmail.com> Tim JIANG <p90eri@gmail.com> Tim Joseph Dumol <tim@timdumol.com> +Timothy Maloney <tmaloney@pdx.edu> +Tomas Koutsky <tomas@stepnivlk.net> +Torsten Weber <TorstenWeber12@gmail.com> Torsten Weber <TorstenWeber12@gmail.com> <torstenweber12@gmail.com> Trevor Spiteri <tspiteri@ieee.org> <trevor.spiteri@um.edu.mt> Ty Overby <ty@pre-alpha.com> Tyler Mandry <tmandry@gmail.com> <tmandry@google.com> +Tyler Ruckinger <t.ruckinger@gmail.com> Ulrik Sverdrup <bluss@users.noreply.github.com> bluss <bluss@users.noreply.github.com> Ulrik Sverdrup <bluss@users.noreply.github.com> bluss <bluss> Ulrik Sverdrup <bluss@users.noreply.github.com> Ulrik Sverdrup <root@localhost> Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Vadim Petrochenkov <vadim.petrochenkov@gmail.com> petrochenkov <vadim.petrochenkov@gmail.com> +Val Markovic <val@markovic.io> +Valerii Lashmanov <vflashm@gmail.com> Vitali Haravy <HumaneProgrammer@gmail.com> Vitali Haravy <humaneprogrammer@gmail.com> +Vitaly Shukela <vi0oss@gmail.com> +Waffle Maybe <waffle.lapkin@gmail.com> Wesley Wiser <wwiser@gmail.com> <wesleywiser@microsoft.com> whitequark <whitequark@whitequark.org> William Ting <io@williamting.com> <william.h.ting@gmail.com> +Wim Looman <wim@nemo157.com> +Without Boats <woboats@gmail.com> +Without Boats <woboats@gmail.com> <boats@mozilla.com> +Xinye Tao <xy.tao@outlook.com> Xuefeng Wu <benewu@gmail.com> Xuefeng Wu <xfwu@thoughtworks.com> Xuefeng Wu <benewu@gmail.com> XuefengWu <benewu@gmail.com> York Xiang <bombless@126.com> Youngsoo Son <ysson83@gmail.com> <ysoo.son@samsung.com> +Youngsuk Kim <joseph942010@gmail.com> +Yuki Okushi <jtitor@2k36.org> Yuki Okushi <jtitor@2k36.org> <huyuumi.dev@gmail.com> Yuki Okushi <jtitor@2k36.org> <yuki.okushi@huawei.com> +Yuning Zhang <codeworm96@outlook.com> Zach Pomerantz <zmp@umich.edu> Zack Corr <zack@z0w0.me> <zackcorr95@gmail.com> Zack Slayton <zack.slayton@gmail.com> diff --git a/Cargo.lock b/Cargo.lock index d8cb1133c73..c83763be3d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -613,9 +613,8 @@ dependencies = [ [[package]] name = "clippy" -version = "0.1.61" +version = "0.1.62" dependencies = [ - "cargo_metadata", "clippy_lints", "clippy_utils", "compiletest_rs", @@ -642,20 +641,18 @@ dependencies = [ name = "clippy_dev" version = "0.0.1" dependencies = [ - "bytecount", - "cargo_metadata", "clap 2.34.0", "indoc", "itertools", "opener", - "regex", "shell-escape", + "tempfile", "walkdir", ] [[package]] name = "clippy_lints" -version = "0.1.61" +version = "0.1.62" dependencies = [ "cargo_metadata", "clippy_utils", @@ -676,7 +673,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.61" +version = "0.1.62" dependencies = [ "arrayvec", "if_chain", @@ -2019,9 +2016,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.116" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" dependencies = [ "rustc-std-workspace-core", ] diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 550c66e3d3b..80caf37d709 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -439,7 +439,7 @@ impl MetaItem { } Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt { token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span), - token::Nonterminal::NtPath(ref path) => path.clone(), + token::Nonterminal::NtPath(ref path) => (**path).clone(), _ => return None, }, _ => return None, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 32621eb5f2f..15f7aceb83d 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -772,7 +772,9 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut token::NtBlock(block) => vis.visit_block(block), token::NtStmt(stmt) => visit_clobber(stmt, |stmt| { // See reasoning above. - vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item") + stmt.map(|stmt| { + vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item") + }) }), token::NtPat(pat) => vis.visit_pat(pat), token::NtExpr(expr) => vis.visit_expr(expr), diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 2132cdfc001..031c6cae793 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -668,7 +668,7 @@ impl PartialEq<TokenKind> for Token { pub enum Nonterminal { NtItem(P<ast::Item>), NtBlock(P<ast::Block>), - NtStmt(ast::Stmt), + NtStmt(P<ast::Stmt>), NtPat(P<ast::Pat>), NtExpr(P<ast::Expr>), NtTy(P<ast::Ty>), @@ -677,13 +677,13 @@ pub enum Nonterminal { NtLiteral(P<ast::Expr>), /// Stuff inside brackets for attributes NtMeta(P<ast::AttrItem>), - NtPath(ast::Path), - NtVis(ast::Visibility), + NtPath(P<ast::Path>), + NtVis(P<ast::Visibility>), } // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Nonterminal, 48); +rustc_data_structures::static_assert_size!(Nonterminal, 16); #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)] pub enum NonterminalKind { diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 9242c6aeb8b..927eb080b20 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -1,6 +1,7 @@ //! The entry point of the NLL borrow checker. use rustc_data_structures::vec_map::VecMap; +use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; @@ -8,7 +9,7 @@ use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, }; -use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid}; +use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid}; use rustc_span::symbol::sym; use std::env; use std::fmt::Debug; @@ -43,7 +44,7 @@ pub type PoloniusOutput = Output<RustcFacts>; /// closure requirements to propagate, and any generated errors. crate struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, - pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>, + pub opaque_type_values: VecMap<DefId, OpaqueHiddenType<'tcx>>, pub polonius_input: Option<Box<AllFacts>>, pub polonius_output: Option<Rc<PoloniusOutput>>, pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>, @@ -372,7 +373,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, - opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>, + opaque_type_values: &VecMap<DefId, OpaqueHiddenType<'tcx>>, errors: &mut crate::error::BorrowckErrors<'tcx>, ) { let tcx = infcx.tcx; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 0bb6559e654..fa07c4fa949 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,5 +1,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::vec_map::VecMap; +use rustc_hir::def_id::DefId; use rustc_hir::OpaqueTyOrigin; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::subst::GenericArgKind; @@ -54,8 +55,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, infcx: &InferCtxt<'_, 'tcx>, opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>, - ) -> VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> { - let mut result: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> = VecMap::new(); + ) -> VecMap<DefId, OpaqueHiddenType<'tcx>> { + let mut result: VecMap<DefId, OpaqueHiddenType<'tcx>> = VecMap::new(); for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls { let substs = opaque_type_key.substs; debug!(?concrete_type, ?substs); @@ -124,21 +125,24 @@ impl<'tcx> RegionInferenceContext<'tcx> { // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)` // and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that // once we convert the generic parameters to those of the opaque type. - if let Some(prev) = result.get_mut(&opaque_type_key) { + if let Some(prev) = result.get_mut(&opaque_type_key.def_id) { if prev.ty != ty { - let mut err = infcx.tcx.sess.struct_span_err( - concrete_type.span, - &format!("hidden type `{}` differed from previous `{}`", ty, prev.ty), - ); - err.span_note(prev.span, "previous hidden type bound here"); - err.emit(); + if !ty.references_error() { + prev.report_mismatch( + &OpaqueHiddenType { ty, span: concrete_type.span }, + infcx.tcx, + ); + } prev.ty = infcx.tcx.ty_error(); } // Pick a better span if there is one. // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. prev.span = prev.span.substitute_dummy(concrete_type.span); } else { - result.insert(opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span }); + result.insert( + opaque_type_key.def_id, + OpaqueHiddenType { ty, span: concrete_type.span }, + ); } } result diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index be628c9202c..ece250f61d5 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -141,7 +141,7 @@ pub fn expand_include<'cx>( fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> { let mut ret = SmallVec::new(); - while self.p.token != token::Eof { + loop { match self.p.parse_item(ForceCollect::No) { Err(mut err) => { err.emit(); @@ -149,9 +149,12 @@ pub fn expand_include<'cx>( } Ok(Some(item)) => ret.push(item), Ok(None) => { - let token = pprust::token_to_string(&self.p.token); - let msg = format!("expected item, found `{}`", token); - self.p.struct_span_err(self.p.token.span, &msg).emit(); + if self.p.token != token::Eof { + let token = pprust::token_to_string(&self.p.token); + let msg = format!("expected item, found `{}`", token); + self.p.struct_span_err(self.p.token.span, &msg).emit(); + } + break; } } diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index 2f4b3844430..86be0bd8775 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -144,7 +144,7 @@ impl<'a, K, V> IntoIterator for &'a VecMap<K, V> { } } -impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> { +impl<'a, K: 'a, V: 'a> IntoIterator for &'a mut VecMap<K, V> { type Item = (&'a K, &'a mut V); type IntoIter = impl Iterator<Item = Self::Item>; diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 06a90ab05ac..12b117d6fc9 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -118,7 +118,7 @@ impl Annotatable { Annotatable::ForeignItem(item) => { token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) } - Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), + Annotatable::Stmt(stmt) => token::NtStmt(stmt), Annotatable::Expr(expr) => token::NtExpr(expr), Annotatable::Arm(..) | Annotatable::ExprField(..) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index c3f7f4f27e5..9b224a73356 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -83,9 +83,7 @@ macro_rules! ast_fragments { } match self { $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| { - // We are repeating through arguments with `many`, to do that we have to - // mention some macro variable from those arguments even if it's not used. - macro _repeating($flat_map_ast_elt) {} + ${ignore(flat_map_ast_elt)} placeholder(AstFragmentKind::$Kind, *id, None).$make_ast() })),)?)* _ => panic!("unexpected AST fragment kind") diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index cd5bb93de65..21078f79f63 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(rustc::potential_query_instability)] #![feature(associated_type_bounds)] #![feature(associated_type_defaults)] #![feature(crate_visibility_modifier)] @@ -5,12 +6,12 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(let_else)] +#![feature(macro_metavar_expr)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_blocks)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index ffe8b10e687..604e25a14e6 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -315,7 +315,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize { /// only on the nesting depth of repetitions in the originating token tree it /// was derived from. /// -/// In layman's terms: `NamedMatch` will form a tree representing nested matches of a particular +/// In layperson's terms: `NamedMatch` will form a tree representing nested matches of a particular /// meta variable. For example, if we are matching the following macro against the following /// invocation... /// diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index b4bae8ce5fb..aec401a041c 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -90,7 +90,7 @@ impl MultiItemModifier for ProcMacroDerive { // A proc macro can't observe the fact that we're passing // them an `NtStmt` - it can only see the underlying tokens // of the wrapped item - token::NtStmt(stmt.into_inner()) + token::NtStmt(stmt) } _ => unreachable!(), }; diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 28466315c86..8340a0b360e 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -505,6 +505,8 @@ declare_features! ( (active, static_nobundle, "1.16.0", Some(37403), None), /// Allows attributes on expressions and non-item statements. (active, stmt_expr_attributes, "1.6.0", Some(15701), None), + /// Allows lints part of the strict provenance effort. + (active, strict_provenance, "1.61.0", Some(95228), None), /// Allows the use of `#[target_feature]` on safe functions. (active, target_feature_11, "1.45.0", Some(69098), None), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 5704c6ed3b2..89ce307d12c 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2649,6 +2649,96 @@ declare_lint! { } declare_lint! { + /// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer + /// and a pointer. + /// + /// ### Example + /// + /// ```rust + /// #![feature(strict_provenance)] + /// #![warn(fuzzy_provenance_casts)] + /// + /// fn main() { + /// let _dangling = 16_usize as *const u8; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// This lint is part of the strict provenance effort, see [issue #95228]. + /// Casting an integer to a pointer is considered bad style, as a pointer + /// contains, besides the *address* also a *provenance*, indicating what + /// memory the pointer is allowed to read/write. Casting an integer, which + /// doesn't have provenance, to a pointer requires the compiler to assign + /// (guess) provenance. The compiler assigns "all exposed valid" (see the + /// docs of [`ptr::from_exposed_addr`] for more information about this + /// "exposing"). This penalizes the optimiser and is not well suited for + /// dynamic analysis/dynamic program verification (e.g. Miri or CHERI + /// platforms). + /// + /// It is much better to use [`ptr::with_addr`] instead to specify the + /// provenance you want. If using this function is not possible because the + /// code relies on exposed provenance then there is as an escape hatch + /// [`ptr::from_exposed_addr`]. + /// + /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228 + /// [`ptr::with_addr`]: https://doc.rust-lang.org/core/ptr/fn.with_addr + /// [`ptr::from_exposed_addr`]: https://doc.rust-lang.org/core/ptr/fn.from_exposed_addr + pub FUZZY_PROVENANCE_CASTS, + Allow, + "a fuzzy integer to pointer cast is used", + @feature_gate = sym::strict_provenance; +} + +declare_lint! { + /// The `lossy_provenance_casts` lint detects an `as` cast between a pointer + /// and an integer. + /// + /// ### Example + /// + /// ```rust + /// #![feature(strict_provenance)] + /// #![warn(lossy_provenance_casts)] + /// + /// fn main() { + /// let x: u8 = 37; + /// let _addr: usize = &x as *const u8 as usize; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// This lint is part of the strict provenance effort, see [issue #95228]. + /// Casting a pointer to an integer is a lossy operation, because beyond + /// just an *address* a pointer may be associated with a particular + /// *provenance*. This information is used by the optimiser and for dynamic + /// analysis/dynamic program verification (e.g. Miri or CHERI platforms). + /// + /// Since this cast is lossy, it is considered good style to use the + /// [`ptr::addr`] method instead, which has a similar effect, but doesn't + /// "expose" the pointer provenance. This improves optimisation potential. + /// See the docs of [`ptr::addr`] and [`ptr::expose_addr`] for more information + /// about exposing pointer provenance. + /// + /// If your code can't comply with strict provenance and needs to expose + /// the provenance, then there is [`ptr::expose_addr`] as an escape hatch, + /// which preserves the behaviour of `as usize` casts while being explicit + /// about the semantics. + /// + /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228 + /// [`ptr::addr`]: https://doc.rust-lang.org/core/ptr/fn.addr + /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/ptr/fn.expose_addr + pub LOSSY_PROVENANCE_CASTS, + Allow, + "a lossy pointer to integer cast is used", + @feature_gate = sym::strict_provenance; +} + +declare_lint! { /// The `const_evaluatable_unchecked` lint detects a generic constant used /// in a type. /// @@ -3101,6 +3191,8 @@ declare_lint_pass! { UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, CENUM_IMPL_DROP_CAST, + FUZZY_PROVENANCE_CASTS, + LOSSY_PROVENANCE_CASTS, CONST_EVALUATABLE_UNCHECKED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, MUST_NOT_SUSPEND, diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 0324ac3641e..b63f81bffaa 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,5 +1,4 @@ #![feature(nll)] -#![cfg_attr(bootstrap, feature(native_link_modifiers))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] // NOTE: This crate only exists to allow linking on mingw targets. diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 046322a42d8..3402acccf3f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1169,14 +1169,18 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_associated_item_def_ids(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [DefId] { - if let Some(children) = self.root.tables.children.get(self, id) { - tcx.arena.alloc_from_iter( - children.decode((self, tcx.sess)).map(|child_index| self.local_def_id(child_index)), - ) - } else { - &[] - } + fn get_associated_item_def_ids( + self, + id: DefIndex, + sess: &'a Session, + ) -> impl Iterator<Item = DefId> + 'a { + self.root + .tables + .children + .get(self, id) + .unwrap_or_else(Lazy::empty) + .decode((self, sess)) + .map(move |child_index| self.local_def_id(child_index)) } fn get_associated_item(self, id: DefIndex) -> ty::AssocItem { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index cd3a1d72d41..63bf929fb86 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -160,7 +160,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, let _ = cdata; tcx.calculate_dtor(def_id, |_,_| Ok(())) } - associated_item_def_ids => { cdata.get_associated_item_def_ids(tcx, def_id.index) } + associated_item_def_ids => { + tcx.arena.alloc_from_iter(cdata.get_associated_item_def_ids(def_id.index, tcx.sess)) + } associated_item => { cdata.get_associated_item(def_id.index) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index fed6a608e57..63f2bc51aee 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -58,7 +58,7 @@ pub struct Allocation<Tag = AllocId, Extra = ()> { /// means that both the inner type (`Allocation`) and the outer type /// (`ConstAllocation`) are used quite a bit. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] -#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +#[rustc_pass_by_value] pub struct ConstAllocation<'tcx, Tag = AllocId, Extra = ()>( pub Interned<'tcx, Allocation<Tag, Extra>>, ); diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index cee510a4241..4d4eed179ca 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -9,7 +9,6 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::BitMatrix; use rustc_index::vec::IndexVec; -use rustc_middle::ty::OpaqueTypeKey; use rustc_span::Span; use rustc_target::abi::VariantIdx; use smallvec::SmallVec; @@ -242,7 +241,7 @@ pub struct BorrowCheckResult<'tcx> { /// All the opaque types that are restricted to concrete types /// by this function. Unlike the value in `TypeckResults`, this has /// unerased regions. - pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>, + pub concrete_opaque_types: VecMap<DefId, OpaqueHiddenType<'tcx>>, pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>, pub used_mut_upvars: SmallVec<[Field; 8]>, pub tainted_by_errors: Option<ErrorGuaranteed>, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index cb219c4c4e4..fc6710f07e3 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -161,7 +161,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for AdtDefData { } #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] -#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +#[rustc_pass_by_value] pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>); impl<'tcx> AdtDef<'tcx> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 45a215354d0..6e3dc92a233 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1112,6 +1112,26 @@ pub struct OpaqueHiddenType<'tcx> { pub ty: Ty<'tcx>, } +impl<'tcx> OpaqueHiddenType<'tcx> { + pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) { + // Found different concrete types for the opaque type. + let mut err = tcx.sess.struct_span_err( + other.span, + "concrete type differs from previous defining opaque type use", + ); + err.span_label(other.span, format!("expected `{}`, got `{}`", self.ty, other.ty)); + if self.span == other.span { + err.span_label( + self.span, + "this expression supplies two conflicting concrete types for the same opaque type", + ); + } else { + err.span_note(self.span, "previous use here"); + } + err.emit(); + } +} + rustc_index::newtype_index! { /// "Universes" are used during type- and trait-checking in the /// presence of `for<..>` binders to control what sets of names are diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 9865588cff4..1724bab5caa 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -13,7 +13,7 @@ use tracing::debug; #[derive(Debug)] pub enum InnerAttrPolicy<'a> { Permitted, - Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> }, + Forbidden { reason: &'a str, saw_doc_comment: bool, prev_outer_attr_sp: Option<Span> }, } const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ @@ -22,7 +22,7 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden { reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG, saw_doc_comment: false, - prev_attr_sp: None, + prev_outer_attr_sp: None, }; enum OuterAttributeType { @@ -34,14 +34,16 @@ enum OuterAttributeType { impl<'a> Parser<'a> { /// Parses attributes that appear before an item. pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { - let mut attrs: Vec<ast::Attribute> = Vec::new(); + let mut outer_attrs: Vec<ast::Attribute> = Vec::new(); let mut just_parsed_doc_comment = false; let start_pos = self.token_cursor.num_next_calls; loop { let attr = if self.check(&token::Pound) { + let prev_outer_attr_sp = outer_attrs.last().map(|attr| attr.span); + let inner_error_reason = if just_parsed_doc_comment { "an inner attribute is not permitted following an outer doc comment" - } else if !attrs.is_empty() { + } else if prev_outer_attr_sp.is_some() { "an inner attribute is not permitted following an outer attribute" } else { DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG @@ -49,7 +51,7 @@ impl<'a> Parser<'a> { let inner_parse_policy = InnerAttrPolicy::Forbidden { reason: inner_error_reason, saw_doc_comment: just_parsed_doc_comment, - prev_attr_sp: attrs.last().map(|a| a.span), + prev_outer_attr_sp, }; just_parsed_doc_comment = false; Some(self.parse_attribute(inner_parse_policy)?) @@ -97,12 +99,14 @@ impl<'a> Parser<'a> { }; if let Some(attr) = attr { - attrs.push(attr); + if attr.style == ast::AttrStyle::Outer { + outer_attrs.push(attr); + } } else { break; } } - Ok(AttrWrapper::new(attrs.into(), start_pos)) + Ok(AttrWrapper::new(outer_attrs.into(), start_pos)) } /// Matches `attribute = # ! [ meta_item ]`. @@ -215,15 +219,15 @@ impl<'a> Parser<'a> { } pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) { - if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy { - let prev_attr_note = + if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_outer_attr_sp } = policy { + let prev_outer_attr_note = if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" }; let mut diag = self.struct_span_err(attr_sp, reason); - if let Some(prev_attr_sp) = prev_attr_sp { + if let Some(prev_outer_attr_sp) = prev_outer_attr_sp { diag.span_label(attr_sp, "not permitted following an outer attribute") - .span_label(prev_attr_sp, prev_attr_note); + .span_label(prev_outer_attr_sp, prev_outer_attr_note); } diag.note( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7978a1a7f5f..7efc0ca2da2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -41,7 +41,7 @@ macro_rules! maybe_whole_expr { return Ok(e); } token::NtPath(path) => { - let path = path.clone(); + let path = (**path).clone(); $p.bump(); return Ok($p.mk_expr( $p.prev_token.span, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 792f9d9ccce..f1956fb695b 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1289,7 +1289,7 @@ impl<'a> Parser<'a> { /// so emit a proper diagnostic. // Public for rustfmt usage. pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { - maybe_whole!(self, NtVis, |x| x); + maybe_whole!(self, NtVis, |x| x.into_inner()); self.expected_tokens.push(TokenType::Keyword(kw::Crate)); if self.is_crate_vis() { diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index c105fbfaee0..b45bca3d2e0 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -118,7 +118,7 @@ impl<'a> Parser<'a> { token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) } NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { - Some(s) => token::NtStmt(s), + Some(s) => token::NtStmt(P(s)), None => { return Err(self.struct_span_err(self.token.span, "expected a statement")); } @@ -161,11 +161,11 @@ impl<'a> Parser<'a> { return Err(self.struct_span_err(self.token.span, msg)); } NonterminalKind::Path => token::NtPath( - self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?, + P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?), ), NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)), NonterminalKind::Vis => token::NtVis( - self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?, + P(self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?), ), NonterminalKind::Lifetime => { if self.check_lifetime() { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 93663a349f5..207ecd00e0c 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -165,7 +165,7 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPath, |path| { reject_generics_if_mod_style(self, &path); - path + path.into_inner() }); if let token::Interpolated(nt) = &self.token.kind { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index e3bcd945db7..5b7ae5f7a7b 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -54,7 +54,7 @@ impl<'a> Parser<'a> { stmt.visit_attrs(|stmt_attrs| { attrs.prepend_to_nt_inner(stmt_attrs); }); - return Ok(Some(stmt)); + return Ok(Some(stmt.into_inner())); } Ok(Some(if self.token.is_keyword(kw::Let) { @@ -535,7 +535,7 @@ impl<'a> Parser<'a> { recover: AttemptLocalParseRecovery, ) -> PResult<'a, Option<Stmt>> { // Skip looking for a trailing semicolon when we have an interpolated statement. - maybe_whole!(self, NtStmt, |x| Some(x)); + maybe_whole!(self, NtStmt, |x| Some(x.into_inner())); let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else { return Ok(None); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index b706547f7fc..07d261da813 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1248,7 +1248,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }; let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas); self.r.set_binding_parent_module(binding, parent_scope.module); - self.r.all_macros.insert(ident.name, res); + self.r.all_macro_rules.insert(ident.name, res); if is_macro_export { let module = self.r.graph_root; self.r.define(module, ident, MacroNS, (res, vis, span, expansion, IsMacroExport)); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 0c7d2f7b4e5..a09a225a2b5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1003,7 +1003,8 @@ pub struct Resolver<'a> { registered_attrs: FxHashSet<Ident>, registered_tools: RegisteredTools, macro_use_prelude: FxHashMap<Symbol, &'a NameBinding<'a>>, - all_macros: FxHashMap<Symbol, Res>, + /// FIXME: The only user of this is a doc link resolution hack for rustdoc. + all_macro_rules: FxHashMap<Symbol, Res>, macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>, dummy_ext_bang: Lrc<SyntaxExtension>, dummy_ext_derive: Lrc<SyntaxExtension>, @@ -1385,7 +1386,7 @@ impl<'a> Resolver<'a> { registered_attrs, registered_tools, macro_use_prelude: FxHashMap::default(), - all_macros: FxHashMap::default(), + all_macro_rules: Default::default(), macro_map: FxHashMap::default(), dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())), dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())), @@ -3311,8 +3312,8 @@ impl<'a> Resolver<'a> { } // For rustdoc. - pub fn all_macros(&self) -> &FxHashMap<Symbol, Res> { - &self.all_macros + pub fn take_all_macro_rules(&mut self) -> FxHashMap<Symbol, Res> { + mem::take(&mut self.all_macro_rules) } /// For rustdoc. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f5803aaa078..dc4d10f699c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1348,6 +1348,7 @@ symbols! { str_trim, str_trim_end, str_trim_start, + strict_provenance, stringify, stringify_macro, struct_field_attributes, diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index c46726b767b..169167f69bf 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1262,7 +1262,7 @@ impl<'a> fmt::Debug for LayoutS<'a> { } #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)] -#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +#[rustc_pass_by_value] pub struct Layout<'a>(pub Interned<'a, LayoutS<'a>>); impl<'a> fmt::Debug for Layout<'a> { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cf472813e9e..06f58240992 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -307,17 +307,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); } else if lang_items.unsize_trait() == Some(def_id) { self.assemble_candidates_for_unsizing(obligation, &mut candidates); - } else if lang_items.drop_trait() == Some(def_id) - && obligation.predicate.is_const_if_const() - { - // holds to make it easier to transition - // FIXME(fee1-dead): add a note for selection error of `~const Drop` - // when beta is bumped - // FIXME: remove this when beta is bumped - #[cfg(bootstrap)] - {} - - candidates.vec.push(SelectionCandidate::ConstDestructCandidate(None)) } else if lang_items.destruct_trait() == Some(def_id) { self.assemble_const_destruct_candidates(obligation, &mut candidates); } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 18a37759543..b97ab39d991 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1106,13 +1106,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None); - // FIXME: remove if statement below when beta is bumped - #[cfg(bootstrap)] - {} - - if obligation.predicate.skip_binder().def_id() == drop_trait { - return Ok(ImplSourceConstDestructData { nested: vec![] }); - } let tcx = self.tcx(); let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 7ce428ea124..6091b8fee00 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -807,11 +807,22 @@ impl<'a, 'tcx> CastCheck<'tcx> { // ptr -> * (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast - (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast - (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), - // * -> ptr - (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast + // ptr-addr-cast + (Ptr(m_expr), Int(t_c)) => { + self.lossy_provenance_ptr2int_lint(fcx, t_c); + self.check_ptr_addr_cast(fcx, m_expr) + } + (FnPtr, Int(_)) => { + // FIXME(#95489): there should eventually be a lint for these casts + Ok(CastKind::FnPtrAddrCast) + } + // addr-ptr-cast + (Int(_), Ptr(mt)) => { + self.fuzzy_provenance_int2ptr_lint(fcx); + self.check_addr_ptr_cast(fcx, mt) + } + // fn-ptr-cast (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), // prim -> prim @@ -973,6 +984,74 @@ impl<'a, 'tcx> CastCheck<'tcx> { } } } + + fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { + fcx.tcx.struct_span_lint_hir( + lint::builtin::LOSSY_PROVENANCE_CASTS, + self.expr.hir_id, + self.span, + |err| { + let mut err = err.build(&format!( + "under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`", + self.expr_ty, self.cast_ty + )); + + let msg = "use `.addr()` to obtain the address of a pointer"; + if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { + let scalar_cast = match t_c { + ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(), + _ => format!(" as {}", self.cast_ty), + }; + err.span_suggestion( + self.span, + msg, + format!("({}).addr(){}", snippet, scalar_cast), + Applicability::MaybeIncorrect + ); + } else { + err.help(msg); + } + err.help( + "if you can't comply with strict provenance and need to expose the pointer\ + provenance you can use `.expose_addr()` instead" + ); + + err.emit(); + }, + ); + } + + fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { + fcx.tcx.struct_span_lint_hir( + lint::builtin::FUZZY_PROVENANCE_CASTS, + self.expr.hir_id, + self.span, + |err| { + + let mut err = err.build(&format!( + "strict provenance disallows casting integer `{}` to pointer `{}`", + self.expr_ty, self.cast_ty + )); + let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address"; + if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { + err.span_suggestion( + self.span, + msg, + format!("(...).with_addr({})", snippet), + Applicability::HasPlaceholders, + ); + } else { + err.help(msg); + } + err.help( + "if you can't comply with strict provenance and don't have a pointer with \ + the correct provenance you can use `std::ptr::from_exposed_addr()` instead" + ); + + err.emit(); + }, + ); + } } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 9ebafc26f61..1841451580f 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -12,12 +12,13 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; +use rustc_infer::traits::Obligation; use rustc_middle::hir::nested_filter; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, ToPredicate, Ty, TyCtxt}; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; use rustc_span::{self, Span}; @@ -674,6 +675,13 @@ fn check_opaque_meets_bounds<'tcx>( } } + // Additionally require the hidden type to be well-formed with only the generics of the opaque type. + // Defining use functions may have more bounds than the opaque type, which is ok, as long as the + // hidden type is well formed even without those bounds. + let predicate = + ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into())).to_predicate(tcx); + inh.register_predicate(Obligation::new(misc_cause, param_env, predicate)); + // Check that all obligations are satisfied by the implementation's // version. let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 513e8576f2d..e18cb31acbd 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -171,8 +171,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Region checking during the WF phase for items. `wf_tys` are the /// types from which we should derive implied bounds, if any. + #[instrument(level = "debug", skip(self))] pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: FxHashSet<Ty<'tcx>>) { - debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys); let subject = self.tcx.hir().local_def_id(item_id); let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env); rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 9b1767c7835..b2be70e707d 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1657,7 +1657,7 @@ fn receiver_is_valid<'fcx, 'tcx>( } } else { debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty); - // If he receiver already has errors reported due to it, consider it valid to avoid + // If the receiver already has errors reported due to it, consider it valid to avoid // unnecessary errors (#58712). return receiver_ty.references_error(); } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 90b880adcd0..ec783a16ef7 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2700,7 +2700,7 @@ fn linkage_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Linkage { // Use the names from src/llvm/docs/LangRef.rst here. Most types are only // applicable to variable declarations and may not really make sense for // Rust code in the first place but allow them anyway and trust that the - // user knows what s/he's doing. Who knows, unanticipated use cases may pop + // user knows what they're doing. Who knows, unanticipated use cases may pop // up in the future. // // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index cb32e88588a..785538ab0df 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -356,7 +356,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let concrete_ty = tcx .mir_borrowck(owner) .concrete_opaque_types - .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) + .get(&def_id.to_def_id()) .copied() .map(|concrete| concrete.ty) .unwrap_or_else(|| { @@ -591,31 +591,17 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // Use borrowck to get the type with unerased regions. let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; debug!(?concrete_opaque_types); - for &(opaque_type_key, concrete_type) in concrete_opaque_types { - if opaque_type_key.def_id != self.def_id { + for &(def_id, concrete_type) in concrete_opaque_types { + if def_id != self.def_id { // Ignore constraints for other opaque types. continue; } - debug!(?concrete_type, ?opaque_type_key.substs, "found constraint"); + debug!(?concrete_type, "found constraint"); if let Some(prev) = self.found { if concrete_type.ty != prev.ty && !(concrete_type, prev).references_error() { - // Found different concrete types for the opaque type. - let mut err = self.tcx.sess.struct_span_err( - concrete_type.span, - "concrete type differs from previous defining opaque type use", - ); - err.span_label( - concrete_type.span, - format!("expected `{}`, got `{}`", prev.ty, concrete_type.ty), - ); - if prev.span == concrete_type.span { - err.span_label(prev.span, "this expression supplies two conflicting concrete types for the same opaque type"); - } else { - err.span_note(prev.span, "previous use here"); - } - err.emit(); + prev.report_mismatch(&concrete_type, self.tcx); } } else { self.found = Some(concrete_type); diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 44389ee47b0..39f8f1d5a0e 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -326,16 +326,12 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { #[cfg_attr(not(test), lang = "box_free")] #[inline] #[rustc_const_unstable(feature = "const_box", issue = "92521")] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping // This signature has to be the same as `Box`, otherwise an ICE will happen. // When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as // well. // For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`, // this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well. -pub(crate) const unsafe fn box_free< - T: ?Sized, - A: ~const Allocator + ~const Drop + ~const Destruct, ->( +pub(crate) const unsafe fn box_free<T: ?Sized, A: ~const Allocator + ~const Destruct>( ptr: Unique<T>, alloc: A, ) { diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 27e5af4f1be..8b13e36c4b3 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -331,7 +331,6 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_deref", issue = "88955")] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl<B: ?Sized + ToOwned> const Deref for Cow<'_, B> where B::Owned: ~const Borrow<B>, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index b5f4c9a237b..e6faf1df3a8 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -163,6 +163,11 @@ use crate::str::from_boxed_utf8_unchecked; #[cfg(not(no_global_oom_handling))] use crate::vec::Vec; +#[unstable(feature = "thin_box", issue = "92791")] +pub use thin::ThinBox; + +mod thin; + /// A pointer type for heap allocation. /// /// See the [module-level documentation](../../std/boxed/index.html) for more. @@ -349,10 +354,9 @@ impl<T, A: Allocator> Box<T, A> { #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_in(x: T, alloc: A) -> Self where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let mut boxed = Self::new_uninit_in(alloc); unsafe { @@ -379,11 +383,10 @@ impl<T, A: Allocator> Box<T, A> { #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> where - T: ~const Drop + ~const Destruct, - A: ~const Allocator + ~const Drop + ~const Destruct, + T: ~const Destruct, + A: ~const Allocator + ~const Destruct, { let mut boxed = Self::try_new_uninit_in(alloc)?; unsafe { @@ -417,10 +420,9 @@ impl<T, A: Allocator> Box<T, A> { #[cfg(not(no_global_oom_handling))] #[must_use] // #[unstable(feature = "new_uninit", issue = "63291")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let layout = Layout::new::<mem::MaybeUninit<T>>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -456,10 +458,9 @@ impl<T, A: Allocator> Box<T, A> { #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let layout = Layout::new::<mem::MaybeUninit<T>>(); let ptr = alloc.allocate(layout)?.cast(); @@ -491,10 +492,9 @@ impl<T, A: Allocator> Box<T, A> { #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] #[must_use] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let layout = Layout::new::<mem::MaybeUninit<T>>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -530,10 +530,9 @@ impl<T, A: Allocator> Box<T, A> { #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let layout = Layout::new::<mem::MaybeUninit<T>>(); let ptr = alloc.allocate_zeroed(layout)?.cast(); @@ -547,10 +546,9 @@ impl<T, A: Allocator> Box<T, A> { #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline(always)] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn pin_in(x: T, alloc: A) -> Pin<Self> where - A: 'static + ~const Allocator + ~const Drop + ~const Destruct, + A: 'static + ~const Allocator + ~const Destruct, { Self::into_pin(Self::new_in(x, alloc)) } @@ -579,10 +577,9 @@ impl<T, A: Allocator> Box<T, A> { #[unstable(feature = "box_into_inner", issue = "80437")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn into_inner(boxed: Self) -> T where - Self: ~const Drop + ~const Destruct, + Self: ~const Destruct, { *boxed } diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs new file mode 100644 index 00000000000..390030fa2b2 --- /dev/null +++ b/library/alloc/src/boxed/thin.rs @@ -0,0 +1,215 @@ +// Based on +// https://github.com/matthieu-m/rfc2580/blob/b58d1d3cba0d4b5e859d3617ea2d0943aaa31329/examples/thin.rs +// by matthieu-m +use crate::alloc::{self, Layout, LayoutError}; +use core::fmt::{self, Debug, Display, Formatter}; +use core::marker::{PhantomData, Unsize}; +use core::mem; +use core::ops::{Deref, DerefMut}; +use core::ptr::Pointee; +use core::ptr::{self, NonNull}; + +/// ThinBox. +/// +/// A thin pointer for heap allocation, regardless of T. +/// +/// # Examples +/// +/// ``` +/// #![feature(thin_box)] +/// use std::boxed::ThinBox; +/// +/// let five = ThinBox::new(5); +/// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]); +/// +/// use std::mem::{size_of, size_of_val}; +/// let size_of_ptr = size_of::<*const ()>(); +/// assert_eq!(size_of_ptr, size_of_val(&five)); +/// assert_eq!(size_of_ptr, size_of_val(&thin_slice)); +/// ``` +#[unstable(feature = "thin_box", issue = "92791")] +pub struct ThinBox<T: ?Sized> { + ptr: WithHeader<<T as Pointee>::Metadata>, + _marker: PhantomData<T>, +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl<T> ThinBox<T> { + /// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on + /// the stack. + /// + /// # Examples + /// + /// ``` + /// #![feature(thin_box)] + /// use std::boxed::ThinBox; + /// + /// let five = ThinBox::new(5); + /// ``` + #[cfg(not(no_global_oom_handling))] + pub fn new(value: T) -> Self { + let meta = ptr::metadata(&value); + let ptr = WithHeader::new(meta, value); + ThinBox { ptr, _marker: PhantomData } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl<Dyn: ?Sized> ThinBox<Dyn> { + /// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on + /// the stack. + /// + /// # Examples + /// + /// ``` + /// #![feature(thin_box)] + /// use std::boxed::ThinBox; + /// + /// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]); + /// ``` + #[cfg(not(no_global_oom_handling))] + pub fn new_unsize<T>(value: T) -> Self + where + T: Unsize<Dyn>, + { + let meta = ptr::metadata(&value as &Dyn); + let ptr = WithHeader::new(meta, value); + ThinBox { ptr, _marker: PhantomData } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl<T: ?Sized + Debug> Debug for ThinBox<T> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Debug::fmt(self.deref(), f) + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl<T: ?Sized + Display> Display for ThinBox<T> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(self.deref(), f) + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl<T: ?Sized> Deref for ThinBox<T> { + type Target = T; + + fn deref(&self) -> &T { + let value = self.data(); + let metadata = self.meta(); + let pointer = ptr::from_raw_parts(value as *const (), metadata); + unsafe { &*pointer } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl<T: ?Sized> DerefMut for ThinBox<T> { + fn deref_mut(&mut self) -> &mut T { + let value = self.data(); + let metadata = self.meta(); + let pointer = ptr::from_raw_parts_mut::<T>(value as *mut (), metadata); + unsafe { &mut *pointer } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl<T: ?Sized> Drop for ThinBox<T> { + fn drop(&mut self) { + unsafe { + let value = self.deref_mut(); + let value = value as *mut T; + self.ptr.drop::<T>(value); + } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl<T: ?Sized> ThinBox<T> { + fn meta(&self) -> <T as Pointee>::Metadata { + // Safety: + // - NonNull and valid. + unsafe { *self.ptr.header() } + } + + fn data(&self) -> *mut u8 { + self.ptr.value() + } +} + +/// A pointer to type-erased data, guaranteed to have a header `H` before the pointed-to location. +struct WithHeader<H>(NonNull<u8>, PhantomData<H>); + +impl<H> WithHeader<H> { + #[cfg(not(no_global_oom_handling))] + fn new<T>(header: H, value: T) -> WithHeader<H> { + let value_layout = Layout::new::<T>(); + let Ok((layout, value_offset)) = Self::alloc_layout(value_layout) else { + // We pass an empty layout here because we do not know which layout caused the + // arithmetic overflow in `Layout::extend` and `handle_alloc_error` takes `Layout` as + // its argument rather than `Result<Layout, LayoutError>`, also this function has been + // stable since 1.28 ._. + // + // On the other hand, look at this gorgeous turbofish! + alloc::handle_alloc_error(Layout::new::<()>()); + }; + + unsafe { + let ptr = alloc::alloc(layout); + + if ptr.is_null() { + alloc::handle_alloc_error(layout); + } + // Safety: + // - The size is at least `aligned_header_size`. + let ptr = ptr.add(value_offset) as *mut _; + + let ptr = NonNull::new_unchecked(ptr); + + let result = WithHeader(ptr, PhantomData); + ptr::write(result.header(), header); + ptr::write(result.value().cast(), value); + + result + } + } + + // Safety: + // - Assumes that `value` can be dereferenced. + unsafe fn drop<T: ?Sized>(&self, value: *mut T) { + unsafe { + // SAFETY: Layout must have been computable if we're in drop + let (layout, value_offset) = + Self::alloc_layout(Layout::for_value_raw(value)).unwrap_unchecked(); + + ptr::drop_in_place::<T>(value); + // We only drop the value because the Pointee trait requires that the metadata is copy + // aka trivially droppable + alloc::dealloc(self.0.as_ptr().sub(value_offset), layout); + } + } + + fn header(&self) -> *mut H { + // Safety: + // - At least `size_of::<H>()` bytes are allocated ahead of the pointer. + // - We know that H will be aligned because the middle pointer is aligned to the greater + // of the alignment of the header and the data and the header size includes the padding + // needed to align the header. Subtracting the header size from the aligned data pointer + // will always result in an aligned header pointer, it just may not point to the + // beginning of the allocation. + unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H } + } + + fn value(&self) -> *mut u8 { + self.0.as_ptr() + } + + const fn header_size() -> usize { + mem::size_of::<H>() + } + + fn alloc_layout(value_layout: Layout) -> Result<(Layout, usize), LayoutError> { + Layout::new::<H>().extend(value_layout) + } +} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 065d071a2e3..c54001dceea 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -120,6 +120,7 @@ #![feature(nonnull_slice_from_raw_parts)] #![feature(pattern)] #![feature(ptr_internals)] +#![feature(ptr_metadata)] #![feature(receiver_trait)] #![feature(set_ptr_value)] #![feature(slice_group_by)] @@ -131,6 +132,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] +#![feature(unchecked_math)] #![feature(unicode_internals)] #![feature(unsize)] // @@ -141,7 +143,6 @@ #![feature(box_syntax)] #![feature(cfg_sanitize)] #![feature(const_deref)] -#![cfg_attr(bootstrap, feature(const_fn_trait_bound))] #![feature(const_mut_refs)] #![feature(const_ptr_write)] #![feature(const_precise_live_drops)] @@ -152,6 +153,7 @@ #![feature(fundamental)] #![cfg_attr(not(test), feature(generator_trait))] #![feature(lang_items)] +#![feature(let_else)] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 89d85146963..31edbe0c5af 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -237,7 +237,6 @@ mod hack { } } -#[cfg_attr(bootstrap, lang = "slice_alloc")] #[cfg(not(test))] impl<T> [T] { /// Sorts the slice. @@ -267,7 +266,7 @@ impl<T> [T] { /// assert!(v == [-5, -3, 1, 2, 4]); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sort(&mut self) @@ -323,7 +322,7 @@ impl<T> [T] { /// assert!(v == [5, 4, 3, 2, 1]); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sort_by<F>(&mut self, mut compare: F) @@ -365,7 +364,7 @@ impl<T> [T] { /// assert!(v == [1, 2, -3, 4, -5]); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "slice_sort_by_key", since = "1.7.0")] #[inline] pub fn sort_by_key<K, F>(&mut self, mut f: F) @@ -412,7 +411,7 @@ impl<T> [T] { /// /// [pdqsort]: https://github.com/orlp/pdqsort #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")] #[inline] pub fn sort_by_cached_key<K, F>(&mut self, f: F) @@ -471,7 +470,7 @@ impl<T> [T] { /// // Here, `s` and `x` can be modified independently. /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[rustc_conversion_suggestion] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -496,7 +495,7 @@ impl<T> [T] { /// // Here, `s` and `x` can be modified independently. /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A> @@ -521,7 +520,7 @@ impl<T> [T] { /// /// assert_eq!(x, vec![10, 40, 30]); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> { @@ -549,7 +548,7 @@ impl<T> [T] { /// // this will panic at runtime /// b"0123456789abcdef".repeat(usize::MAX); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[cfg(not(no_global_oom_handling))] #[stable(feature = "repeat_generic_slice", since = "1.40.0")] pub fn repeat(&self, n: usize) -> Vec<T> @@ -618,7 +617,7 @@ impl<T> [T] { /// assert_eq!(["hello", "world"].concat(), "helloworld"); /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output where @@ -637,7 +636,7 @@ impl<T> [T] { /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]); /// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rename_connect_to_join", since = "1.3.0")] pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output where @@ -656,7 +655,7 @@ impl<T> [T] { /// assert_eq!(["hello", "world"].connect(" "), "hello world"); /// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output @@ -667,7 +666,6 @@ impl<T> [T] { } } -#[cfg_attr(bootstrap, lang = "slice_u8_alloc")] #[cfg(not(test))] impl [u8] { /// Returns a vector containing a copy of this slice where each byte @@ -680,7 +678,7 @@ impl [u8] { /// /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the uppercase bytes as a new Vec, \ without modifying the original"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] @@ -701,7 +699,7 @@ impl [u8] { /// /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the lowercase bytes as a new Vec, \ without modifying the original"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index a3c17612c3a..0eaa2639863 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -235,7 +235,6 @@ impl ToOwned for str { } /// Methods for string slices. -#[cfg_attr(bootstrap, lang = "str_alloc")] #[cfg(not(test))] impl str { /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating. @@ -250,7 +249,7 @@ impl str { /// let boxed_bytes = boxed_str.into_boxed_bytes(); /// assert_eq!(*boxed_bytes, *s.as_bytes()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "str_box_extras", since = "1.20.0")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] @@ -281,7 +280,7 @@ impl str { /// assert_eq!(s, s.replace("cookie monster", "little lamb")); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the replaced string as a new allocation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] @@ -322,7 +321,7 @@ impl str { /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the replaced string as a new allocation, \ without modifying the original"] #[stable(feature = "str_replacen", since = "1.16.0")] @@ -379,7 +378,7 @@ impl str { /// assert_eq!(new_year, new_year.to_lowercase()); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the lowercase string as a new String, \ without modifying the original"] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] @@ -462,7 +461,7 @@ impl str { /// assert_eq!("TSCHÜSS", s.to_uppercase()); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the uppercase string as a new String, \ without modifying the original"] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] @@ -498,7 +497,7 @@ impl str { /// assert_eq!(boxed_str.into_string(), string); /// ``` #[stable(feature = "box_str", since = "1.4.0")] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_string(self: Box<str>) -> String { @@ -527,7 +526,7 @@ impl str { /// let huge = "0123456789abcdef".repeat(usize::MAX); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use] #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { @@ -556,7 +555,7 @@ impl str { /// [`make_ascii_uppercase`]: str::make_ascii_uppercase /// [`to_uppercase`]: #method.to_uppercase #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] @@ -589,7 +588,7 @@ impl str { /// [`make_ascii_lowercase`]: str::make_ascii_lowercase /// [`to_lowercase`]: #method.to_lowercase #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f8b4d46ac10..a19999cd725 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -369,7 +369,7 @@ impl<T> Arc<T> { /// /// # Example /// ``` - /// #![allow(dead_code)] + /// # #![allow(dead_code)] /// use std::sync::{Arc, Weak}; /// /// struct Gadget { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 0b62622de81..74bcac2b541 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2274,6 +2274,51 @@ impl<T: Clone, A: Allocator> Vec<T, A> { } } +impl<T, A: Allocator, const N: usize> Vec<[T; N], A> { + /// Takes a `Vec<[T; N]>` and flattens it into a `Vec<T>`. + /// + /// # Panics + /// + /// Panics if the length of the resulting vector would overflow a `usize`. + /// + /// This is only possible when flattening a vector of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::<T>() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_flatten)] + /// + /// let mut vec = vec![[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + /// assert_eq!(vec.pop(), Some([7, 8, 9])); + /// + /// let mut flattened = vec.into_flattened(); + /// assert_eq!(flattened.pop(), Some(6)); + /// ``` + #[unstable(feature = "slice_flatten", issue = "95629")] + pub fn into_flattened(self) -> Vec<T, A> { + let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc(); + let (new_len, new_cap) = if mem::size_of::<T>() == 0 { + (len.checked_mul(N).expect("vec len overflow"), usize::MAX) + } else { + // SAFETY: + // - `cap * N` cannot overflow because the allocation is already in + // the address space. + // - Each `[T; N]` has `N` valid elements, so there are `len * N` + // valid elements in the allocation. + unsafe { (len.unchecked_mul(N), cap.unchecked_mul(N)) } + }; + // SAFETY: + // - `ptr` was allocated by `self` + // - `ptr` is well-aligned because `[T; N]` has the same alignment as `T`. + // - `new_cap` refers to the same sized allocation as `cap` because + // `new_cap * size_of::<T>()` == `cap * size_of::<[T; N]>()` + // - `len` <= `cap`, so `len * N` <= `cap * N`. + unsafe { Vec::<T, A>::from_raw_parts_in(ptr.cast(), new_len, new_cap, alloc) } + } +} + // This code generalizes `extend_with_{element,default}`. trait ExtendWith<T> { fn next(&mut self) -> T; diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index abce47e5afe..16d3b368595 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -38,6 +38,8 @@ #![feature(const_str_from_utf8)] #![feature(nonnull_slice_from_raw_parts)] #![feature(panic_update_hook)] +#![feature(slice_flatten)] +#![feature(thin_box)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; @@ -56,6 +58,7 @@ mod rc; mod slice; mod str; mod string; +mod thin_box; mod vec; mod vec_deque; diff --git a/library/alloc/tests/thin_box.rs b/library/alloc/tests/thin_box.rs new file mode 100644 index 00000000000..0fe6aaa4d00 --- /dev/null +++ b/library/alloc/tests/thin_box.rs @@ -0,0 +1,26 @@ +use alloc::boxed::ThinBox; +use core::mem::size_of; + +#[test] +fn want_niche_optimization() { + fn uses_niche<T: ?Sized>() -> bool { + size_of::<*const ()>() == size_of::<Option<ThinBox<T>>>() + } + + trait Tr {} + assert!(uses_niche::<dyn Tr>()); + assert!(uses_niche::<[i32]>()); + assert!(uses_niche::<i32>()); +} + +#[test] +fn want_thin() { + fn is_thin<T: ?Sized>() -> bool { + size_of::<*const ()>() == size_of::<ThinBox<T>>() + } + + trait Tr {} + assert!(is_thin::<dyn Tr>()); + assert!(is_thin::<[i32]>()); + assert!(is_thin::<i32>()); +} diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 19e39ebf910..bc1397146dd 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2408,3 +2408,10 @@ fn test_extend_from_within_panicing_clone() { assert_eq!(count.load(Ordering::SeqCst), 4); } + +#[test] +#[should_panic = "vec len overflow"] +fn test_into_flattened_size_overflow() { + let v = vec![[(); usize::MAX]; 2]; + let _ = v.into_flattened(); +} diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 9e42ab5923a..af661e485f5 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -395,7 +395,6 @@ macro_rules! array_impl_default { array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T} -#[cfg_attr(bootstrap, lang = "array")] impl<T, const N: usize> [T; N] { /// Returns an array of the same size as `self`, with function `f` applied to each element /// in order. diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 06aee3ccbaf..36000f8f389 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -2,7 +2,6 @@ use crate::marker::Destruct; -#[cfg_attr(bootstrap, lang = "bool")] impl bool { /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), /// or `None` otherwise. @@ -18,10 +17,9 @@ impl bool { #[unstable(feature = "bool_to_option", issue = "80967")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn then_some<T>(self, t: T) -> Option<T> where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { if self { Some(t) } else { None } } @@ -38,11 +36,10 @@ impl bool { #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn then<T, F>(self, f: F) -> Option<T> where F: ~const FnOnce() -> T, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { if self { Some(f()) } else { None } } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 3195205b1b6..5809ed1f33b 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -7,7 +7,6 @@ use crate::unicode::{self, conversions}; use super::*; -#[cfg_attr(bootstrap, lang = "char")] impl char { /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. /// @@ -804,6 +803,9 @@ impl char { /// ``` /// assert!(' '.is_whitespace()); /// + /// // line break + /// assert!('\n'.is_whitespace()); + /// /// // a non-breaking space /// assert!('\u{A0}'.is_whitespace()); /// diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index cfdc51c71ee..0444a9575d1 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -130,10 +130,9 @@ pub trait Clone: Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[default_method_body_is_const] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping fn clone_from(&mut self, source: &Self) where - Self: ~const Drop + ~const Destruct, + Self: ~const Destruct, { *self = source.clone() } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 27063952adb..8e02ca84317 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2358,7 +2358,6 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] #[lang = "const_eval_select"] #[rustc_do_not_const_check] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const unsafe fn const_eval_select<ARG, F, G, RET>( arg: ARG, _called_in_const: F, @@ -2366,7 +2365,7 @@ pub const unsafe fn const_eval_select<ARG, F, G, RET>( ) -> RET where F: ~const FnOnce<ARG, Output = RET>, - G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct, + G: FnOnce<ARG, Output = RET> + ~const Destruct, { called_at_rt.call_once(arg) } @@ -2378,7 +2377,6 @@ where )] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] #[lang = "const_eval_select_ct"] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>( arg: ARG, called_in_const: F, @@ -2386,7 +2384,7 @@ pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>( ) -> RET where F: ~const FnOnce<ARG, Output = RET>, - G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct, + G: FnOnce<ARG, Output = RET> + ~const Destruct, { called_in_const.call_once(arg) } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e13f50b0d7a..6546a5244fd 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -84,7 +84,7 @@ target_has_atomic_load_store = "ptr", ))] #![no_core] -#![cfg_attr(not(bootstrap), rustc_coherence_is_core)] +#![rustc_coherence_is_core] // // Lints: #![deny(rust_2021_incompatible_or_patterns)] @@ -163,15 +163,12 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(const_fn_floating_point_arithmetic)] -#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))] -#![cfg_attr(bootstrap, feature(const_fn_trait_bound))] -#![cfg_attr(bootstrap, feature(const_impl_trait))] #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_refs_to_cell)] #![feature(decl_macro)] #![feature(derive_default_enum)] -#![cfg_attr(not(bootstrap), feature(deprecated_suggestion))] +#![feature(deprecated_suggestion)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] #![feature(rustdoc_internals)] @@ -184,6 +181,7 @@ #![feature(intrinsics)] #![feature(lang_items)] #![feature(link_llvm_intrinsics)] +#![feature(macro_metavar_expr)] #![feature(min_specialization)] #![feature(mixed_integer_ops)] #![feature(must_not_suspend)] @@ -208,7 +206,6 @@ #![feature(asm_const)] // // Target features: -#![cfg_attr(bootstrap, feature(aarch64_target_feature))] #![feature(arm_target_feature)] #![feature(avx512_target_feature)] #![feature(cmpxchg16b_target_feature)] @@ -220,7 +217,6 @@ #![feature(sse4a_target_feature)] #![feature(tbm_target_feature)] #![feature(wasm_target_feature)] -#![cfg_attr(bootstrap, feature(adx_target_feature))] // allow using `core::` in intra-doc links #[allow(unused_extern_crates)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 74c94680e47..83f33ca007a 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -909,7 +909,10 @@ pub(crate) mod builtin { /// Inspects an environment variable at compile time. /// /// This macro will expand to the value of the named environment variable at - /// compile time, yielding an expression of type `&'static str`. + /// compile time, yielding an expression of type `&'static str`. Use + /// [`std::env::var`] instead if you want to read the value at runtime. + /// + /// [`std::env::var`]: ../std/env/fn.var.html /// /// If the environment variable is not defined, then a compilation error /// will be emitted. To not emit a compile error, use the [`option_env!`] @@ -950,7 +953,10 @@ pub(crate) mod builtin { /// expand into an expression of type `Option<&'static str>` whose value is /// `Some` of the value of the environment variable. If the environment /// variable is not present, then this will expand to `None`. See - /// [`Option<T>`][Option] for more information on this type. + /// [`Option<T>`][Option] for more information on this type. Use + /// [`std::env::var`] instead if you want to read the value at runtime. + /// + /// [`std::env::var`]: ../std/env/fn.var.html /// /// A compile time error is never emitted when using this macro regardless /// of whether the environment variable is present or not. diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 6b9d6253e42..4a90ef9545d 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -797,17 +797,10 @@ impl<T: ?Sized> Unpin for *mut T {} /// This should be used for `~const` bounds, /// as non-const bounds will always hold for every type. #[unstable(feature = "const_trait_impl", issue = "67792")] -#[cfg_attr(not(bootstrap), lang = "destruct")] -#[cfg_attr( - not(bootstrap), - rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg,) -)] +#[lang = "destruct"] +#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] pub trait Destruct {} -#[cfg(bootstrap)] -#[unstable(feature = "const_trait_impl", issue = "67792")] -impl<T: ?Sized> const Destruct for T {} - /// Implementations of `Copy` for primitive types. /// /// Implementations that cannot be described in Rust diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index e56e602a662..a983d0872bc 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -370,7 +370,6 @@ pub mod consts { pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32; } -#[cfg_attr(bootstrap, lang = "f32")] #[cfg(not(test))] impl f32 { /// The radix or base of the internal representation of `f32`. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 8304caf649c..05598e5fe7b 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -370,7 +370,6 @@ pub mod consts { pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64; } -#[cfg_attr(bootstrap, lang = "f64")] #[cfg(not(test))] impl f64 { /// The radix or base of the internal representation of `f64`. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 8cbece0417b..a30d2ff0ea6 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -193,26 +193,22 @@ macro_rules! widening_impl { }; } -#[cfg_attr(bootstrap, lang = "i8")] impl i8 { int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } } -#[cfg_attr(bootstrap, lang = "i16")] impl i16 { int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } -#[cfg_attr(bootstrap, lang = "i32")] impl i32 { int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } -#[cfg_attr(bootstrap, lang = "i64")] impl i64 { int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", @@ -220,7 +216,6 @@ impl i64 { "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } } -#[cfg_attr(bootstrap, lang = "i128")] impl i128 { int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728, 170141183460469231731687303715884105727, 16, @@ -233,7 +228,6 @@ impl i128 { } #[cfg(target_pointer_width = "16")] -#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", @@ -241,7 +235,6 @@ impl isize { } #[cfg(target_pointer_width = "32")] -#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", @@ -250,7 +243,6 @@ impl isize { } #[cfg(target_pointer_width = "64")] -#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", @@ -262,7 +254,6 @@ impl isize { /// If 6th bit set ascii is upper case. const ASCII_CASE_MASK: u8 = 0b0010_0000; -#[cfg_attr(bootstrap, lang = "u8")] impl u8 { uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } @@ -816,7 +807,6 @@ impl u8 { } } -#[cfg_attr(bootstrap, lang = "u16")] impl u16 { uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } @@ -848,14 +838,12 @@ impl u16 { } } -#[cfg_attr(bootstrap, lang = "u32")] impl u32 { uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } widening_impl! { u32, u64, 32, unsigned } } -#[cfg_attr(bootstrap, lang = "u64")] impl u64 { uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", @@ -865,7 +853,6 @@ impl u64 { widening_impl! { u64, u128, 64, unsigned } } -#[cfg_attr(bootstrap, lang = "u128")] impl u128 { uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", @@ -878,7 +865,6 @@ impl u128 { } #[cfg(target_pointer_width = "16")] -#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", @@ -886,7 +872,6 @@ impl usize { widening_impl! { usize, u32, 16, unsigned } } #[cfg(target_pointer_width = "32")] -#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", @@ -895,7 +880,6 @@ impl usize { } #[cfg(target_pointer_width = "64")] -#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", diff --git a/library/core/src/option.rs b/library/core/src/option.rs index b5ca9e35dce..91e4708f6a6 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -773,10 +773,9 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn unwrap_or(self, default: T) -> T where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { match self { Some(x) => x, @@ -796,11 +795,10 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn unwrap_or_else<F>(self, f: F) -> T where F: ~const FnOnce() -> T, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(x) => x, @@ -902,11 +900,10 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map<U, F>(self, f: F) -> Option<U> where F: ~const FnOnce(T) -> U, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(x) => Some(f(x)), @@ -932,11 +929,10 @@ impl<T> Option<T> { #[inline] #[unstable(feature = "result_option_inspect", issue = "91345")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn inspect<F>(self, f: F) -> Self where F: ~const FnOnce(&T), - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { if let Some(ref x) = self { f(x); @@ -966,12 +962,11 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map_or<U, F>(self, default: U, f: F) -> U where F: ~const FnOnce(T) -> U, - F: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, + F: ~const Destruct, + U: ~const Destruct, { match self { Some(t) => f(t), @@ -996,13 +991,12 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U where D: ~const FnOnce() -> U, - D: ~const Drop + ~const Destruct, + D: ~const Destruct, F: ~const FnOnce(T) -> U, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(t) => f(t), @@ -1034,10 +1028,9 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn ok_or<E>(self, err: E) -> Result<T, E> where - E: ~const Drop + ~const Destruct, + E: ~const Destruct, { match self { Some(v) => Ok(v), @@ -1064,11 +1057,10 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn ok_or_else<E, F>(self, err: F) -> Result<T, E> where F: ~const FnOnce() -> E, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(v) => Ok(v), @@ -1199,11 +1191,10 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn and<U>(self, optb: Option<U>) -> Option<U> where - T: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, + T: ~const Destruct, + U: ~const Destruct, { match self { Some(_) => optb, @@ -1242,11 +1233,10 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn and_then<U, F>(self, f: F) -> Option<U> where F: ~const FnOnce(T) -> Option<U>, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(x) => f(x), @@ -1281,12 +1271,11 @@ impl<T> Option<T> { #[inline] #[stable(feature = "option_filter", since = "1.27.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn filter<P>(self, predicate: P) -> Self where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, P: ~const FnOnce(&T) -> bool, - P: ~const Drop + ~const Destruct, + P: ~const Destruct, { if let Some(x) = self { if predicate(&x) { @@ -1326,10 +1315,9 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn or(self, optb: Option<T>) -> Option<T> where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { match self { Some(x) => Some(x), @@ -1353,11 +1341,10 @@ impl<T> Option<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn or_else<F>(self, f: F) -> Option<T> where F: ~const FnOnce() -> Option<T>, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(x) => Some(x), @@ -1389,10 +1376,9 @@ impl<T> Option<T> { #[inline] #[stable(feature = "option_xor", since = "1.37.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn xor(self, optb: Option<T>) -> Option<T> where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { match (self, optb) { (Some(a), None) => Some(a), @@ -1428,10 +1414,9 @@ impl<T> Option<T> { #[inline] #[stable(feature = "option_insert", since = "1.53.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn insert(&mut self, value: T) -> &mut T where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { *self = Some(value); @@ -1462,10 +1447,9 @@ impl<T> Option<T> { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn get_or_insert(&mut self, value: T) -> &mut T where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { if let None = *self { *self = Some(value); @@ -1530,11 +1514,10 @@ impl<T> Option<T> { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn get_or_insert_with<F>(&mut self, f: F) -> &mut T where F: ~const FnOnce() -> T, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { if let None = *self { // the compiler isn't smart enough to know that we are not dropping a `T` @@ -1645,11 +1628,10 @@ impl<T> Option<T> { /// ``` #[stable(feature = "option_zip_option", since = "1.46.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn zip<U>(self, other: Option<U>) -> Option<(T, U)> where - T: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, + T: ~const Destruct, + U: ~const Destruct, { match (self, other) { (Some(a), Some(b)) => Some((a, b)), @@ -1687,13 +1669,12 @@ impl<T> Option<T> { /// ``` #[unstable(feature = "option_zip", issue = "70086")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R> where F: ~const FnOnce(T, U) -> R, - F: ~const Drop + ~const Destruct, - T: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, + F: ~const Destruct, + T: ~const Destruct, + U: ~const Destruct, { match (self, other) { (Some(a), Some(b)) => Some(f(a, b)), @@ -1880,10 +1861,9 @@ const fn expect_failed(msg: &str) -> ! { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "91805")] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl<T> const Clone for Option<T> where - T: ~const Clone + ~const Drop + ~const Destruct, + T: ~const Clone + ~const Destruct, { #[inline] fn clone(&self) -> Self { diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index a018ad9eab3..714e9b73c78 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -83,7 +83,6 @@ impl<'a> Location<'a> { #[stable(feature = "track_caller", since = "1.46.0")] #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")] #[track_caller] - #[inline] pub const fn caller() -> &'static Location<'static> { crate::intrinsics::caller_location() } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index a908b1f3ba4..7a575a88e52 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -88,7 +88,6 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { // any extra arguments (including those synthesized by track_caller). #[cold] #[inline(never)] -#[cfg_attr(bootstrap, track_caller)] #[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function fn panic_no_unwind() -> ! { if cfg!(feature = "panic_immediate_abort") { diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index f862912432e..68f39dc4347 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -4,7 +4,6 @@ use crate::intrinsics; use crate::mem; use crate::slice::{self, SliceIndex}; -#[cfg_attr(bootstrap, lang = "const_ptr")] impl<T: ?Sized> *const T { /// Returns `true` if the pointer is null. /// @@ -1086,7 +1085,6 @@ impl<T: ?Sized> *const T { } } -#[cfg_attr(bootstrap, lang = "const_slice_ptr")] impl<T> *const [T] { /// Returns the length of a raw slice. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 5db9c3e941e..4c9b0f7cc0c 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -3,7 +3,6 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::intrinsics; use crate::slice::{self, SliceIndex}; -#[cfg_attr(bootstrap, lang = "mut_ptr")] impl<T: ?Sized> *mut T { /// Returns `true` if the pointer is null. /// @@ -1357,7 +1356,6 @@ impl<T: ?Sized> *mut T { } } -#[cfg_attr(bootstrap, lang = "mut_slice_ptr")] impl<T> *mut [T] { /// Returns the length of a raw slice. /// diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 641749be366..b2b132300a2 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -636,7 +636,7 @@ impl<T, E> Result<T, E> { #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] pub const fn ok(self) -> Option<T> where - E: ~const Drop + ~const Destruct, + E: ~const Destruct, { match self { Ok(x) => Some(x), @@ -667,7 +667,7 @@ impl<T, E> Result<T, E> { #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] pub const fn err(self) -> Option<E> where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { match self { // FIXME: ~const Drop doesn't quite work right yet @@ -1283,9 +1283,9 @@ impl<T, E> Result<T, E> { #[stable(feature = "rust1", since = "1.0.0")] pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E> where - T: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, - E: ~const Drop + ~const Destruct, + T: ~const Destruct, + U: ~const Destruct, + E: ~const Destruct, { match self { // FIXME: ~const Drop doesn't quite work right yet @@ -1368,9 +1368,9 @@ impl<T, E> Result<T, E> { #[stable(feature = "rust1", since = "1.0.0")] pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F> where - T: ~const Drop + ~const Destruct, - E: ~const Drop + ~const Destruct, - F: ~const Drop + ~const Destruct, + T: ~const Destruct, + E: ~const Destruct, + F: ~const Destruct, { match self { Ok(v) => Ok(v), @@ -1432,8 +1432,8 @@ impl<T, E> Result<T, E> { #[stable(feature = "rust1", since = "1.0.0")] pub const fn unwrap_or(self, default: T) -> T where - T: ~const Drop + ~const Destruct, - E: ~const Drop + ~const Destruct, + T: ~const Destruct, + E: ~const Destruct, { match self { Ok(t) => t, @@ -1803,11 +1803,10 @@ fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "91805")] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl<T, E> const Clone for Result<T, E> where - T: ~const Clone + ~const Drop + ~const Destruct, - E: ~const Clone + ~const Drop + ~const Destruct, + T: ~const Clone + ~const Destruct, + E: ~const Clone + ~const Destruct, { #[inline] fn clone(&self) -> Self { diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 7c002130040..9aa5c88a62c 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -6,7 +6,6 @@ use crate::iter; use crate::mem; use crate::ops; -#[cfg_attr(bootstrap, lang = "slice_u8")] #[cfg(not(test))] impl [u8] { /// Checks if all bytes in this slice are within the ASCII range. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 17f6373ecbf..2240c297a25 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -110,7 +110,6 @@ enum Direction { Back, } -#[cfg_attr(bootstrap, lang = "slice")] #[cfg(not(test))] impl<T> [T] { /// Returns the number of elements in the slice. @@ -814,7 +813,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> { - assert_ne!(chunk_size, 0); + assert_ne!(chunk_size, 0, "chunks cannot have a size of zero"); Chunks::new(self, chunk_size) } @@ -852,7 +851,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> { - assert_ne!(chunk_size, 0); + assert_ne!(chunk_size, 0, "chunks cannot have a size of zero"); ChunksMut::new(self, chunk_size) } @@ -3993,6 +3992,88 @@ impl<T> [T] { } } +#[cfg(not(bootstrap))] +impl<T, const N: usize> [[T; N]] { + /// Takes a `&[[T; N]]`, and flattens it to a `&[T]`. + /// + /// # Panics + /// + /// This panics if the length of the resulting slice would overflow a `usize`. + /// + /// This is only possible when flattening a slice of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::<T>() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_flatten)] + /// + /// assert_eq!([[1, 2, 3], [4, 5, 6]].flatten(), &[1, 2, 3, 4, 5, 6]); + /// + /// assert_eq!( + /// [[1, 2, 3], [4, 5, 6]].flatten(), + /// [[1, 2], [3, 4], [5, 6]].flatten(), + /// ); + /// + /// let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []]; + /// assert!(slice_of_empty_arrays.flatten().is_empty()); + /// + /// let empty_slice_of_arrays: &[[u32; 10]] = &[]; + /// assert!(empty_slice_of_arrays.flatten().is_empty()); + /// ``` + #[unstable(feature = "slice_flatten", issue = "95629")] + pub fn flatten(&self) -> &[T] { + let len = if crate::mem::size_of::<T>() == 0 { + self.len().checked_mul(N).expect("slice len overflow") + } else { + // SAFETY: `self.len() * N` cannot overflow because `self` is + // already in the address space. + unsafe { self.len().unchecked_mul(N) } + }; + // SAFETY: `[T]` is layout-identical to `[T; N]` + unsafe { from_raw_parts(self.as_ptr().cast(), len) } + } + + /// Takes a `&mut [[T; N]]`, and flattens it to a `&mut [T]`. + /// + /// # Panics + /// + /// This panics if the length of the resulting slice would overflow a `usize`. + /// + /// This is only possible when flattening a slice of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::<T>() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_flatten)] + /// + /// fn add_5_to_all(slice: &mut [i32]) { + /// for i in slice { + /// *i += 5; + /// } + /// } + /// + /// let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + /// add_5_to_all(array.flatten_mut()); + /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]); + /// ``` + #[unstable(feature = "slice_flatten", issue = "95629")] + pub fn flatten_mut(&mut self) -> &mut [T] { + let len = if crate::mem::size_of::<T>() == 0 { + self.len().checked_mul(N).expect("slice len overflow") + } else { + // SAFETY: `self.len() * N` cannot overflow because `self` is + // already in the address space. + unsafe { self.len().unchecked_mul(N) } + }; + // SAFETY: `[T]` is layout-identical to `[T; N]` + unsafe { from_raw_parts_mut(self.as_mut_ptr().cast(), len) } + } +} + trait CloneFromSpec<T> { fn spec_clone_from(&mut self, src: &[T]); } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 6bfa6a5e015..86e1afa2885 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -130,7 +130,6 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { ); } -#[cfg_attr(bootstrap, lang = "str")] #[cfg(not(test))] impl str { /// Returns the length of `self`. @@ -1832,14 +1831,14 @@ impl str { /// Returns a string slice with leading and trailing whitespace removed. /// /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. + /// Core Property `White_Space`, which includes newlines. /// /// # Examples /// /// Basic usage: /// /// ``` - /// let s = " Hello\tworld\t"; + /// let s = "\n Hello\tworld\t\n"; /// /// assert_eq!("Hello\tworld", s.trim()); /// ``` @@ -1855,7 +1854,7 @@ impl str { /// Returns a string slice with leading whitespace removed. /// /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. + /// Core Property `White_Space`, which includes newlines. /// /// # Text directionality /// @@ -1869,8 +1868,8 @@ impl str { /// Basic usage: /// /// ``` - /// let s = " Hello\tworld\t"; - /// assert_eq!("Hello\tworld\t", s.trim_start()); + /// let s = "\n Hello\tworld\t\n"; + /// assert_eq!("Hello\tworld\t\n", s.trim_start()); /// ``` /// /// Directionality: @@ -1894,7 +1893,7 @@ impl str { /// Returns a string slice with trailing whitespace removed. /// /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. + /// Core Property `White_Space`, which includes newlines. /// /// # Text directionality /// @@ -1908,8 +1907,8 @@ impl str { /// Basic usage: /// /// ``` - /// let s = " Hello\tworld\t"; - /// assert_eq!(" Hello\tworld", s.trim_end()); + /// let s = "\n Hello\tworld\t\n"; + /// assert_eq!("\n Hello\tworld", s.trim_end()); /// ``` /// /// Directionality: @@ -2407,7 +2406,7 @@ impl str { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn make_ascii_uppercase(&mut self) { - // SAFETY: safe because we transmute two types with the same layout. + // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; me.make_ascii_uppercase() } @@ -2434,7 +2433,7 @@ impl str { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn make_ascii_lowercase(&mut self) { - // SAFETY: safe because we transmute two types with the same layout. + // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; me.make_ascii_lowercase() } diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 9f8a3a1de42..fdf58c50e48 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -5,21 +5,17 @@ use crate::cmp::*; // macro for implementing n-ary tuple functions and operations macro_rules! tuple_impls { - ($( - $Tuple:ident { - $(($idx:tt) -> $T:ident)+ - } - )+) => { + ( $( $Tuple:ident( $( $T:ident )+ ) )+ ) => { $( #[stable(feature = "rust1", since = "1.0.0")] impl<$($T:PartialEq),+> PartialEq for ($($T,)+) where last_type!($($T,)+): ?Sized { #[inline] fn eq(&self, other: &($($T,)+)) -> bool { - $(self.$idx == other.$idx)&&+ + $( ${ignore(T)} self.${index()} == other.${index()} )&&+ } #[inline] fn ne(&self, other: &($($T,)+)) -> bool { - $(self.$idx != other.$idx)||+ + $( ${ignore(T)} self.${index()} != other.${index()} )||+ } } @@ -28,26 +24,28 @@ macro_rules! tuple_impls { #[stable(feature = "rust1", since = "1.0.0")] impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) - where last_type!($($T,)+): ?Sized { + where + last_type!($($T,)+): ?Sized + { #[inline] fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> { - lexical_partial_cmp!($(self.$idx, other.$idx),+) + lexical_partial_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+) } #[inline] fn lt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(lt, $(self.$idx, other.$idx),+) + lexical_ord!(lt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) } #[inline] fn le(&self, other: &($($T,)+)) -> bool { - lexical_ord!(le, $(self.$idx, other.$idx),+) + lexical_ord!(le, $( ${ignore(T)} self.${index()}, other.${index()} ),+) } #[inline] fn ge(&self, other: &($($T,)+)) -> bool { - lexical_ord!(ge, $(self.$idx, other.$idx),+) + lexical_ord!(ge, $( ${ignore(T)} self.${index()}, other.${index()} ),+) } #[inline] fn gt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(gt, $(self.$idx, other.$idx),+) + lexical_ord!(gt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) } } @@ -55,7 +53,7 @@ macro_rules! tuple_impls { impl<$($T:Ord),+> Ord for ($($T,)+) where last_type!($($T,)+): ?Sized { #[inline] fn cmp(&self, other: &($($T,)+)) -> Ordering { - lexical_cmp!($(self.$idx, other.$idx),+) + lexical_cmp!($( ${ignore(T)} self.${index()}, other.${index()} ),+) } } @@ -108,106 +106,16 @@ macro_rules! last_type { } tuple_impls! { - Tuple1 { - (0) -> A - } - Tuple2 { - (0) -> A - (1) -> B - } - Tuple3 { - (0) -> A - (1) -> B - (2) -> C - } - Tuple4 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - } - Tuple5 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - (4) -> E - } - Tuple6 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - (4) -> E - (5) -> F - } - Tuple7 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - (4) -> E - (5) -> F - (6) -> G - } - Tuple8 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - (4) -> E - (5) -> F - (6) -> G - (7) -> H - } - Tuple9 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - (4) -> E - (5) -> F - (6) -> G - (7) -> H - (8) -> I - } - Tuple10 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - (4) -> E - (5) -> F - (6) -> G - (7) -> H - (8) -> I - (9) -> J - } - Tuple11 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - (4) -> E - (5) -> F - (6) -> G - (7) -> H - (8) -> I - (9) -> J - (10) -> K - } - Tuple12 { - (0) -> A - (1) -> B - (2) -> C - (3) -> D - (4) -> E - (5) -> F - (6) -> G - (7) -> H - (8) -> I - (9) -> J - (10) -> K - (11) -> L - } + Tuple1(A) + Tuple2(A B) + Tuple3(A B C) + Tuple4(A B C D) + Tuple5(A B C D E) + Tuple6(A B C D E F) + Tuple7(A B C D E F G) + Tuple8(A B C D E F G H) + Tuple9(A B C D E F G H I) + Tuple10(A B C D E F G H I J) + Tuple11(A B C D E F G H I J K) + Tuple12(A B C D E F G H I J K L) } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 3af277a556b..09e2e04a1e5 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -93,6 +93,7 @@ #![feature(const_array_from_ref)] #![feature(const_slice_from_ref)] #![feature(waker_getters)] +#![feature(slice_flatten)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 798fcc3dfde..ada479147db 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2504,3 +2504,19 @@ fn test_slice_from_ptr_range() { assert_eq!(slice::from_ptr_range(range), &arr); } } + +#[test] +#[cfg(not(bootstrap))] +#[should_panic = "slice len overflow"] +fn test_flatten_size_overflow() { + let x = &[[(); usize::MAX]; 2][..]; + let _ = x.flatten(); +} + +#[test] +#[cfg(not(bootstrap))] +#[should_panic = "slice len overflow"] +fn test_flatten_mut_size_overflow() { + let x = &mut [[(); usize::MAX]; 2][..]; + let _ = x.flatten_mut(); +} diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 5338cd07757..4a020e59e9c 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -20,8 +20,6 @@ #![feature(rustc_allow_const_fn_unstable)] #![feature(nll)] #![feature(staged_api)] -#![cfg_attr(bootstrap, feature(const_fn_trait_bound))] -#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))] #![feature(allow_internal_unstable)] #![feature(decl_macro)] #![feature(extern_types)] diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index ae11964cb56..49b6cd4232c 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -315,14 +315,11 @@ pub fn take_alloc_error_hook() -> fn(Layout) { } fn default_alloc_error_hook(layout: Layout) { - #[cfg(not(bootstrap))] extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. static __rust_alloc_error_handler_should_panic: u8; } - #[cfg(bootstrap)] - let __rust_alloc_error_handler_should_panic = 0; #[allow(unused_unsafe)] if unsafe { __rust_alloc_error_handler_should_panic != 0 } { diff --git a/library/std/src/error.rs b/library/std/src/error.rs index c3cb71a5dee..4fb94908c80 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -516,6 +516,14 @@ impl<T: Error> Error for Box<T> { } } +#[unstable(feature = "thin_box", issue = "92791")] +impl<T: ?Sized + crate::error::Error> crate::error::Error for crate::boxed::ThinBox<T> { + fn source(&self) -> Option<&(dyn crate::error::Error + 'static)> { + use core::ops::Deref; + self.deref().source() + } +} + #[stable(feature = "error_by_ref", since = "1.51.0")] impl<'a, T: Error + ?Sized> Error for &'a T { #[allow(deprecated, deprecated_in_future)] diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 70b5941c7c7..ac288c599f3 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -28,7 +28,6 @@ pub use core::f32::{ }; #[cfg(not(test))] -#[cfg_attr(bootstrap, lang = "f32_runtime")] impl f32 { /// Returns the largest integer less than or equal to a number. /// @@ -43,7 +42,7 @@ impl f32 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -62,7 +61,7 @@ impl f32 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -82,7 +81,7 @@ impl f32 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -103,7 +102,7 @@ impl f32 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -124,7 +123,7 @@ impl f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -149,7 +148,7 @@ impl f32 { /// /// assert!(f32::NAN.abs().is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -173,7 +172,7 @@ impl f32 { /// /// assert!(f32::NAN.signum().is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -200,7 +199,7 @@ impl f32 { /// /// assert!(f32::NAN.copysign(1.0).is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "copysign", since = "1.35.0")] @@ -228,7 +227,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -253,7 +252,7 @@ impl f32 { /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -288,7 +287,7 @@ impl f32 { /// // limitation due to round-off error /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -309,7 +308,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -327,7 +326,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -352,7 +351,7 @@ impl f32 { /// assert!(negative.sqrt().is_nan()); /// assert!(negative_zero.sqrt() == negative_zero); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -374,7 +373,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -394,7 +393,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -416,7 +415,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -440,7 +439,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -460,7 +459,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -483,7 +482,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -508,7 +507,7 @@ impl f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -538,7 +537,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -560,7 +559,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -579,7 +578,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -598,7 +597,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -616,7 +615,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -638,7 +637,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -660,7 +659,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -681,7 +680,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -715,7 +714,7 @@ impl f32 { /// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -738,7 +737,7 @@ impl f32 { /// assert!(abs_difference_0 <= f32::EPSILON); /// assert!(abs_difference_1 <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin_cos(self) -> (f32, f32) { @@ -759,7 +758,7 @@ impl f32 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -781,7 +780,7 @@ impl f32 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -804,7 +803,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -827,7 +826,7 @@ impl f32 { /// // Same result /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -850,7 +849,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -870,7 +869,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -890,7 +889,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -910,7 +909,7 @@ impl f32 { /// /// assert!(abs_difference <= 1e-5); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index b90d068ec10..01279f01b05 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -28,7 +28,6 @@ pub use core::f64::{ }; #[cfg(not(test))] -#[cfg_attr(bootstrap, lang = "f64_runtime")] impl f64 { /// Returns the largest integer less than or equal to a number. /// @@ -43,7 +42,7 @@ impl f64 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -62,7 +61,7 @@ impl f64 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -82,7 +81,7 @@ impl f64 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -103,7 +102,7 @@ impl f64 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -124,7 +123,7 @@ impl f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -149,7 +148,7 @@ impl f64 { /// /// assert!(f64::NAN.abs().is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -173,7 +172,7 @@ impl f64 { /// /// assert!(f64::NAN.signum().is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -200,7 +199,7 @@ impl f64 { /// /// assert!(f64::NAN.copysign(1.0).is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] #[inline] @@ -228,7 +227,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -253,7 +252,7 @@ impl f64 { /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -288,7 +287,7 @@ impl f64 { /// // limitation due to round-off error /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -309,7 +308,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -327,7 +326,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -352,7 +351,7 @@ impl f64 { /// assert!(negative.sqrt().is_nan()); /// assert!(negative_zero.sqrt() == negative_zero); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -374,7 +373,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -394,7 +393,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -416,7 +415,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -440,7 +439,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -460,7 +459,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -485,7 +484,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -510,7 +509,7 @@ impl f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -540,7 +539,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -562,7 +561,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -581,7 +580,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -600,7 +599,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -618,7 +617,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-14); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -640,7 +639,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -662,7 +661,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -683,7 +682,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -717,7 +716,7 @@ impl f64 { /// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_2 < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -740,7 +739,7 @@ impl f64 { /// assert!(abs_difference_0 < 1e-10); /// assert!(abs_difference_1 < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin_cos(self) -> (f64, f64) { @@ -761,7 +760,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-20); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -783,7 +782,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-20); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -806,7 +805,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -829,7 +828,7 @@ impl f64 { /// // Same result /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -852,7 +851,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -872,7 +871,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -892,7 +891,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -912,7 +911,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -923,7 +922,7 @@ impl f64 { // Solaris/Illumos requires a wrapper around log, log2, and log10 functions // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 { if !cfg!(any(target_os = "solaris", target_os = "illumos")) { log_fn(self) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 3fa731c9529..e8d0132f4b9 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -644,9 +644,9 @@ fn recursive_rmdir_toctou() { // Test for time-of-check to time-of-use issues. // // Scenario: - // The attacker wants to get directory contents deleted, to which he does not have access. - // He has a way to get a privileged Rust binary call `std::fs::remove_dir_all()` on a - // directory he controls, e.g. in his home directory. + // The attacker wants to get directory contents deleted, to which they do not have access. + // They have a way to get a privileged Rust binary call `std::fs::remove_dir_all()` on a + // directory they control, e.g. in their home directory. // // The POC sets up the `attack_dest/attack_file` which the attacker wants to have deleted. // The attacker repeatedly creates a directory and replaces it with a symlink from diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index ac6d41e13b0..ae16015e35a 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -394,7 +394,6 @@ impl Stdin { /// # Examples /// /// ```no_run - /// #![feature(stdin_forwarders)] /// use std::io; /// /// let lines = io::stdin().lines(); @@ -403,7 +402,7 @@ impl Stdin { /// } /// ``` #[must_use = "`self` will be dropped if the result is not used"] - #[unstable(feature = "stdin_forwarders", issue = "87096")] + #[stable(feature = "stdin_forwarders", since = "1.62.0")] pub fn lines(self) -> Lines<StdinLock<'static>> { self.lock().lines() } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 1016fbc99d8..60e7c2af8e4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -228,12 +228,10 @@ #![feature(c_unwind)] #![feature(cfg_target_thread_local)] #![feature(concat_idents)] -#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))] -#![cfg_attr(bootstrap, feature(const_fn_trait_bound))] #![feature(const_mut_refs)] #![feature(const_trait_impl)] #![feature(decl_macro)] -#![cfg_attr(not(bootstrap), feature(deprecated_suggestion))] +#![feature(deprecated_suggestion)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_masked)] @@ -292,6 +290,7 @@ #![feature(get_mut_unchecked)] #![feature(map_try_insert)] #![feature(new_uninit)] +#![feature(thin_box)] #![feature(toowned_clone_into)] #![feature(try_reserve_kind)] #![feature(vec_into_raw_parts)] diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs index 1e8d1137ac8..75a5c0f9279 100644 --- a/library/std/src/sys/unix/stack_overflow.rs +++ b/library/std/src/sys/unix/stack_overflow.rs @@ -54,22 +54,6 @@ mod imp { use crate::sys::unix::os::page_size; use crate::sys_common::thread_info; - #[cfg(any(target_os = "linux", target_os = "android"))] - unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { - #[repr(C)] - struct siginfo_t { - a: [libc::c_int; 3], // si_signo, si_errno, si_code - si_addr: *mut libc::c_void, - } - - (*(info as *const siginfo_t)).si_addr as usize - } - - #[cfg(not(any(target_os = "linux", target_os = "android")))] - unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { - (*info).si_addr as usize - } - // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages // (unmapped pages) at the end of every thread's stack, so if a thread ends // up running into the guard page it'll trigger this handler. We want to @@ -97,7 +81,7 @@ mod imp { _data: *mut libc::c_void, ) { let guard = thread_info::stack_guard().unwrap_or(0..0); - let addr = siginfo_si_addr(info); + let addr = (*info).si_addr() as usize; // If the faulting address is within the guard page, then we print a // message saying so and abort. diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index bb4e4ee9aa7..d191e1fe7a6 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -122,7 +122,13 @@ impl Thread { // pthread wrapper only appeared in glibc 2.12, so we use syscall // directly. unsafe { - libc::prctl(PR_SET_NAME, name.as_ptr() as libc::c_ulong, 0, 0, 0); + libc::prctl( + PR_SET_NAME, + name.as_ptr(), + 0 as libc::c_ulong, + 0 as libc::c_ulong, + 0 as libc::c_ulong, + ); } } diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs index a914a3bcc12..c55df042003 100644 --- a/library/std/src/sys/windows/compat.rs +++ b/library/std/src/sys/windows/compat.rs @@ -77,6 +77,10 @@ macro_rules! compat_fn { static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init; unsafe extern "C" fn init() { + PTR = get_f(); + } + + unsafe extern "C" fn get_f() -> Option<F> { // There is no locking here. This code is executed before main() is entered, and // is guaranteed to be single-threaded. // @@ -88,13 +92,13 @@ macro_rules! compat_fn { let symbol_name: *const u8 = concat!(stringify!($symbol), "\0").as_ptr(); let module_handle = $crate::sys::c::GetModuleHandleA(module_name as *const i8); if !module_handle.is_null() { - match $crate::sys::c::GetProcAddress(module_handle, symbol_name as *const i8).addr() { - 0 => {} - n => { - PTR = Some(mem::transmute::<usize, F>(n)); - } + let ptr = $crate::sys::c::GetProcAddress(module_handle, symbol_name as *const i8); + if !ptr.is_null() { + // Transmute to the right function pointer type. + return Some(mem::transmute(ptr)); } } + return None; } #[allow(dead_code)] @@ -105,10 +109,15 @@ macro_rules! compat_fn { #[allow(dead_code)] pub unsafe fn call($($argname: $argtype),*) -> $rettype { if let Some(ptr) = PTR { - ptr($($argname),*) - } else { - $fallback_body + return ptr($($argname),*); + } + if cfg!(miri) { + // Miri does not run `init`, so we just call `get_f` each time. + if let Some(ptr) = get_f() { + return ptr($($argname),*); + } } + $fallback_body } } diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index df4f1b24eec..09d1dd55989 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -53,6 +53,9 @@ pub struct Pipes { /// with `OVERLAPPED` instances, but also works out ok if it's only ever used /// once at a time (which we do indeed guarantee). pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> { + // A 64kb pipe capacity is the same as a typical Linux default. + const PIPE_BUFFER_CAPACITY: u32 = 64 * 1024; + // Note that we specifically do *not* use `CreatePipe` here because // unfortunately the anonymous pipes returned do not support overlapped // operations. Instead, we create a "hopefully unique" name and create a @@ -91,8 +94,8 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res | c::PIPE_WAIT | reject_remote_clients_flag, 1, - 4096, - 4096, + PIPE_BUFFER_CAPACITY, + PIPE_BUFFER_CAPACITY, 0, ptr::null_mut(), ); diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index a41cb02a607..fc307c5666d 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -980,7 +980,7 @@ pub mod fast { unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { // SAFETY: See comment above (this function doc). if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } { - // SAFETY: See comment above (his function doc). + // SAFETY: See comment above (this function doc). Some(unsafe { self.inner.initialize(init) }) } else { None diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 56eef8314fb..dc0123cf432 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -103,12 +103,7 @@ impl ConsoleTestState { exec_time: Option<&TestExecTime>, ) -> io::Result<()> { self.write_log(|| { - let TestDesc { - name, - #[cfg(not(bootstrap))] - ignore_message, - .. - } = test; + let TestDesc { name, ignore_message, .. } = test; format!( "{} {}", match *result { @@ -116,14 +111,11 @@ impl ConsoleTestState { TestResult::TrFailed => "failed".to_owned(), TestResult::TrFailedMsg(ref msg) => format!("failed: {msg}"), TestResult::TrIgnored => { - #[cfg(not(bootstrap))] if let Some(msg) = ignore_message { format!("ignored: {msg}") } else { "ignored".to_owned() } - #[cfg(bootstrap)] - "ignored".to_owned() } TestResult::TrBench(ref bs) => fmt_bench_samples(bs), TestResult::TrTimedFail => "failed (time limit exceeded)".to_owned(), diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index 737921c1e10..c07fdafb167 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -120,22 +120,16 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> { Some(&*format!(r#""message": "{}""#, EscapedString(m))), ), - TestResult::TrIgnored => { - #[cfg(not(bootstrap))] - return self.write_event( - "test", - desc.name.as_slice(), - "ignored", - exec_time, - stdout, - desc.ignore_message - .map(|msg| format!(r#""message": "{}""#, EscapedString(msg))) - .as_deref(), - ); - - #[cfg(bootstrap)] - self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None) - } + TestResult::TrIgnored => self.write_event( + "test", + desc.name.as_slice(), + "ignored", + exec_time, + stdout, + desc.ignore_message + .map(|msg| format!(r#""message": "{}""#, EscapedString(msg))) + .as_deref(), + ), TestResult::TrBench(ref bs) => { let median = bs.ns_iter_summ.median as usize; diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 9b407df2190..69420222980 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -218,12 +218,7 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> { match *result { TestResult::TrOk => self.write_ok()?, TestResult::TrFailed | TestResult::TrFailedMsg(_) => self.write_failed()?, - TestResult::TrIgnored => { - #[cfg(not(bootstrap))] - self.write_ignored(desc.ignore_message)?; - #[cfg(bootstrap)] - self.write_ignored(None)?; - } + TestResult::TrIgnored => self.write_ignored(desc.ignore_message)?, TestResult::TrBench(ref bs) => { self.write_bench()?; self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?; diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index fb40f86b42e..5dace8baef7 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -11,8 +11,9 @@ use crate::{ types::TestDesc, }; -// insert a '\n' after 100 tests in quiet mode -const QUIET_MODE_MAX_COLUMN: usize = 100; +// We insert a '\n' when the output hits 100 columns in quiet mode. 88 test +// result chars leaves 12 chars for a progress count like " 11704/12853". +const QUIET_MODE_MAX_COLUMN: usize = 88; pub(crate) struct TerseFormatter<T> { out: OutputLocation<T>, @@ -65,7 +66,7 @@ impl<T: Write> TerseFormatter<T> { ) -> io::Result<()> { self.write_pretty(result, color)?; if self.test_count % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 { - // we insert a new line every 100 dots in order to flush the + // We insert a new line regularly in order to flush the // screen when dealing with line-buffered output (e.g., piping to // `stamp` in the rust CI). let out = format!(" {}/{}\n", self.test_count + 1, self.total_test_count); diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 8329e9735d4..0b81aff5907 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -61,7 +61,6 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { desc: TestDesc { name: StaticTestName("1"), ignore: true, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -74,7 +73,6 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { desc: TestDesc { name: StaticTestName("2"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -95,7 +93,6 @@ pub fn do_not_run_ignored_tests() { desc: TestDesc { name: StaticTestName("whatever"), ignore: true, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -117,7 +114,6 @@ pub fn ignored_tests_result_in_ignored() { desc: TestDesc { name: StaticTestName("whatever"), ignore: true, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -143,7 +139,6 @@ fn test_should_panic() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::Yes, compile_fail: false, @@ -169,7 +164,6 @@ fn test_should_panic_good_message() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::YesWithMessage("error message"), compile_fail: false, @@ -200,7 +194,6 @@ fn test_should_panic_bad_message() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::YesWithMessage(expected), compile_fail: false, @@ -235,7 +228,6 @@ fn test_should_panic_non_string_message_type() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::YesWithMessage(expected), compile_fail: false, @@ -262,7 +254,6 @@ fn test_should_panic_but_succeeds() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic, compile_fail: false, @@ -297,7 +288,6 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -333,7 +323,6 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -373,7 +362,6 @@ fn typed_test_desc(test_type: TestType) -> TestDesc { TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -486,7 +474,6 @@ pub fn exclude_should_panic_option() { desc: TestDesc { name: StaticTestName("3"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::Yes, compile_fail: false, @@ -511,7 +498,6 @@ pub fn exact_filter_match() { desc: TestDesc { name: StaticTestName(name), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -601,7 +587,6 @@ fn sample_tests() -> Vec<TestDescAndFn> { desc: TestDesc { name: DynTestName((*name).clone()), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -753,7 +738,6 @@ pub fn test_bench_no_iter() { let desc = TestDesc { name: StaticTestName("f"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -776,7 +760,6 @@ pub fn test_bench_iter() { let desc = TestDesc { name: StaticTestName("f"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -793,7 +776,6 @@ fn should_sort_failures_before_printing_them() { let test_a = TestDesc { name: StaticTestName("a"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -804,7 +786,6 @@ fn should_sort_failures_before_printing_them() { let test_b = TestDesc { name: StaticTestName("b"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 1084fb98389..ffb1efe18cc 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -117,7 +117,6 @@ pub struct TestId(pub usize); pub struct TestDesc { pub name: TestName, pub ignore: bool, - #[cfg(not(bootstrap))] pub ignore_message: Option<&'static str>, pub should_panic: options::ShouldPanic, pub compile_fail: bool, diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 82f1e63f4b5..a01b56004c4 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] #![feature(link_cfg)] -#![cfg_attr(bootstrap, feature(native_link_modifiers))] #![feature(native_link_modifiers_bundle)] #![feature(nll)] #![feature(staged_api)] diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e816f9b4c07..8c06a007013 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -835,6 +835,18 @@ impl<'a> Builder<'a> { } } + pub fn rustc_lib_paths(&self, compiler: Compiler) -> Vec<PathBuf> { + let mut dylib_dirs = vec![self.rustc_libdir(compiler)]; + + // Ensure that the downloaded LLVM libraries can be found. + if self.config.llvm_from_ci { + let ci_llvm_lib = self.out.join(&*compiler.host.triple).join("ci-llvm").join("lib"); + dylib_dirs.push(ci_llvm_lib); + } + + dylib_dirs + } + /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic /// library lookup path. pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { @@ -845,15 +857,7 @@ impl<'a> Builder<'a> { return; } - let mut dylib_dirs = vec![self.rustc_libdir(compiler)]; - - // Ensure that the downloaded LLVM libraries can be found. - if self.config.llvm_from_ci { - let ci_llvm_lib = self.out.join(&*compiler.host.triple).join("ci-llvm").join("lib"); - dylib_dirs.push(ci_llvm_lib); - } - - add_dylib_path(dylib_dirs, cmd); + add_dylib_path(self.rustc_lib_paths(compiler), cmd); } /// Gets a path to the compiler specified. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index be965971dbb..fdd1581d9cd 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -896,6 +896,7 @@ impl Step for PlainSourceTarball { cmd.arg("vendor") .arg("--sync") .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml")) + .arg("--sync") .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml")) .current_dir(&plain_dst_src); builder.run(&mut cmd); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index a9ca89bdea1..fc1c2f04fab 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -379,22 +379,14 @@ pub struct ErrorIndex { impl ErrorIndex { pub fn command(builder: &Builder<'_>) -> Command { - // This uses stage-1 to match the behavior of building rustdoc. - // Error-index-generator links with the rustdoc library, so we want to - // use the same librustdoc to avoid building rustdoc twice (and to - // avoid building the compiler an extra time). This uses - // saturating_sub to deal with building with stage 0. (Using stage 0 - // isn't recommended, since it will fail if any new error index tests - // use new syntax, but it should work otherwise.) - let compiler = builder.compiler(builder.top_stage.saturating_sub(1), builder.config.build); + // Error-index-generator links with the rustdoc library, so we need to add `rustc_lib_paths` + // for rustc_private and libLLVM.so, and `sysroot_lib` for libstd, etc. + let host = builder.config.build; + let compiler = builder.compiler_for(builder.top_stage, host, host); let mut cmd = Command::new(builder.ensure(ErrorIndex { compiler })); - add_dylib_path( - vec![ - PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host)), - builder.rustc_libdir(compiler), - ], - &mut cmd, - ); + let mut dylib_paths = builder.rustc_lib_paths(compiler); + dylib_paths.push(PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))); + add_dylib_path(dylib_paths, &mut cmd); cmd } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index defb1e4d83b..b78ca3712bd 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -63,7 +63,7 @@ pub fn libdir(target: TargetSelection) -> &'static str { } /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path. -/// If The dylib_path_par is already set for this cmd, the old value will be overwritten! +/// If the dylib_path_var is already set for this cmd, the old value will be overwritten! pub fn add_dylib_path(path: Vec<PathBuf>, cmd: &mut Command) { let mut list = dylib_path(); for path in path { diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index e363c4f79f9..a045666ca8a 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -111,6 +111,7 @@ ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi ENV TARGETS=$TARGETS,i686-unknown-freebsd +ENV TARGETS=$TARGETS,x86_64-unknown-none # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-8 (for gnux32) but not in the search path of the diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 8fc5a0d312b..32def67ed65 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -177,6 +177,7 @@ target | std | notes `x86_64-linux-android` | ✓ | 64-bit x86 Android `x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) +[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat `x86_64-unknown-redox` | ✓ | Redox OS [Fortanix ABI]: https://edp.fortanix.com/ @@ -291,7 +292,6 @@ target | std | host | notes `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku `x86_64-unknown-hermit` | ✓ | | HermitCore `x86_64-unknown-l4re-uclibc` | ? | | -[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | | Freestanding/bare-metal x86_64, softfloat `x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD `x86_64-unknown-uefi` | * | | 64-bit UEFI diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-none.md b/src/doc/rustc/src/platform-support/x86_64-unknown-none.md index afcc48003b9..bd5fd1d0502 100644 --- a/src/doc/rustc/src/platform-support/x86_64-unknown-none.md +++ b/src/doc/rustc/src/platform-support/x86_64-unknown-none.md @@ -1,6 +1,6 @@ # `x86_64-unknown-none` -**Tier: 3** +**Tier: 2** Freestanding/bare-metal x86-64 binaries in ELF format: firmware, kernels, etc. @@ -32,7 +32,7 @@ You can change this using the `-C code-model=` option to rustc. On `x86_64-unknown-none`, `extern "C"` uses the [standard System V calling convention](https://gitlab.com/x86-psABIs/x86-64-ABI), without red zones. -This target generated binaries in the ELF format. Any alternate formats or +This target generates binaries in the ELF format. Any alternate formats or special considerations for binary layout will require linker options or linker scripts. @@ -49,15 +49,19 @@ target = ["x86_64-unknown-none"] ## Building Rust programs -Rust does not yet ship pre-compiled artifacts for this target. To compile for -this target, you will either need to build Rust with the target enabled (see -"Building the target" above), or build your own copy of `core` by using -`build-std` or similar. +Starting with Rust 1.62, precompiled artifacts are provided via `rustup`: + +```text +# install cross-compile toolchain +rustup target add x86_64-unknown-none +# target flag may be used with any cargo or rustc command +cargo build --target x86_64-unknown-none +``` ## Testing As `x86_64-unknown-none` supports a variety of different environments and does -not support `std`, this target does not support running the Rust testsuite. +not support `std`, this target does not support running the Rust test suite. ## Cross-compilation toolchains and C code diff --git a/src/doc/unstable-book/src/language-features/strict-provenance.md b/src/doc/unstable-book/src/language-features/strict-provenance.md new file mode 100644 index 00000000000..dc60f3f375d --- /dev/null +++ b/src/doc/unstable-book/src/language-features/strict-provenance.md @@ -0,0 +1,22 @@ +# `strict_provenance` + +The tracking issue for this feature is: [#95228] + +[#95228]: https://github.com/rust-lang/rust/issues/95228 +----- + +The `strict_provenance` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints. +These lint on casts between integers and pointers, that are recommended against or invalid in the strict provenance model. +The same feature gate is also used for the experimental strict provenance API in `std` (actually `core`). + +## Example + +```rust +#![feature(strict_provenance)] +#![warn(fuzzy_provenance_casts)] + +fn main() { + let _dangling = 16_usize as *const u8; + //~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8` +} +``` diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 37c24738a2a..e6ef3c26e29 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -116,22 +116,14 @@ impl Clean<Option<GenericBound>> for hir::GenericBound<'_> { ) } hir::GenericBound::Trait(ref t, modifier) => { - // `T: ~const Drop` is not equivalent to `T: Drop`, and we don't currently document `~const` bounds - // because of its experimental status, so just don't show these. // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. if modifier == hir::TraitBoundModifier::MaybeConst - && [cx.tcx.lang_items().drop_trait(), cx.tcx.lang_items().destruct_trait()] - .iter() - .any(|tr| *tr == Some(t.trait_ref.trait_def_id().unwrap())) + && cx.tcx.lang_items().destruct_trait() + == Some(t.trait_ref.trait_def_id().unwrap()) { return None; } - #[cfg(bootstrap)] - { - // FIXME: remove `lang_items().drop_trait()` from above logic, - // as well as the comment about `~const Drop` because it was renamed to `Destruct`. - } GenericBound::TraitBound(t.clean(cx), modifier) } }) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a32b9caa30f..9d5ae68b3e4 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,3 +1,4 @@ +use rustc_ast::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::emitter::{Emitter, EmitterWriter}; @@ -17,7 +18,7 @@ use rustc_session::lint; use rustc_session::DiagnosticOutput; use rustc_session::Session; use rustc_span::symbol::sym; -use rustc_span::{source_map, Span}; +use rustc_span::{source_map, Span, Symbol}; use std::cell::RefCell; use std::lazy::SyncLazy; @@ -38,6 +39,7 @@ crate struct ResolverCaches { crate traits_in_scope: DefIdMap<Vec<TraitCandidate>>, crate all_traits: Option<Vec<DefId>>, crate all_trait_impls: Option<Vec<DefId>>, + crate all_macro_rules: FxHashMap<Symbol, Res<NodeId>>, } crate struct DocContext<'tcx> { diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 63b744133a2..50ae22b99cd 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1019,7 +1019,6 @@ impl Tester for Collector { Ignore::None => false, Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), }, - #[cfg(not(bootstrap))] ignore_message: None, // compiler failures are test failures should_panic: test::ShouldPanic::No, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index e223b306505..12da16527a0 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -597,11 +597,11 @@ fn document_item_info( ) { let item_infos = short_item_info(item, cx, parent); if !item_infos.is_empty() { - w.write_str("<div class=\"item-info\">"); + w.write_str("<span class=\"item-info\">"); for info in item_infos { w.write_str(&info); } - w.write_str("</div>"); + w.write_str("</span>"); } } @@ -1772,7 +1772,7 @@ pub(crate) fn render_impl_summary( let is_trait = i.inner_impl().trait_.is_some(); if is_trait { if let Some(portability) = portability(&i.impl_item, Some(parent)) { - write!(w, "<div class=\"item-info\">{}</div>", portability); + write!(w, "<span class=\"item-info\">{}</span>", portability); } } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index ee265b8c4b5..68c88b551ca 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -737,6 +737,10 @@ h2.location a { border: none; } +.item-info { + display: block; +} + .content .item-info code { font-size: 0.875rem; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 1d7a790bdb7..0fcfabba4c0 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -10,6 +10,7 @@ #![feature(control_flow_enum)] #![feature(box_syntax)] #![feature(drain_filter)] +#![feature(let_chains)] #![feature(let_else)] #![feature(nll)] #![feature(test)] diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index e19920cc2ce..c1b1139ad8c 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -2,13 +2,11 @@ //! //! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md +use pulldown_cmark::LinkType; use rustc_data_structures::{fx::FxHashMap, intern::Interned, stable_set::FxHashSet}; use rustc_errors::{Applicability, Diagnostic}; -use rustc_hir::def::{ - DefKind, - Namespace::{self, *}, - PerNS, -}; +use rustc_hir::def::Namespace::*; +use rustc_hir::def::{DefKind, Namespace, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::Mutability; use rustc_middle::ty::{DefIdTree, Ty, TyCtxt}; @@ -19,10 +17,7 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{BytePos, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; -use pulldown_cmark::LinkType; - use std::borrow::Cow; -use std::convert::{TryFrom, TryInto}; use std::fmt::Write; use std::mem; use std::ops::Range; @@ -487,25 +482,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { item_id: ItemId, module_id: DefId, ) -> Result<Res, ResolutionFailure<'a>> { - self.cx.enter_resolver(|resolver| { - // NOTE: this needs 2 separate lookups because `resolve_rustdoc_path` doesn't take - // lexical scope into account (it ignores all macros not defined at the mod-level) - debug!("resolving {} as a macro in the module {:?}", path_str, module_id); - if let Some(res) = resolver.resolve_rustdoc_path(path_str, MacroNS, module_id) { - // don't resolve builtins like `#[derive]` - if let Ok(res) = res.try_into() { - return Ok(res); - } - } - if let Some(&res) = resolver.all_macros().get(&Symbol::intern(path_str)) { - return Ok(res.try_into().unwrap()); - } - Err(ResolutionFailure::NotResolved { + self.resolve_path(path_str, MacroNS, item_id, module_id).ok_or_else(|| { + ResolutionFailure::NotResolved { item_id, module_id, partial_res: None, unresolved: path_str.into(), - }) + } }) } @@ -539,6 +522,21 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }) } + /// HACK: Try to search the macro name in the list of all `macro_rules` items in the crate. + /// Used when nothing else works, may often give an incorrect result. + fn resolve_macro_rules(&self, path_str: &str, ns: Namespace) -> Option<Res> { + if ns != MacroNS { + return None; + } + + self.cx + .resolver_caches + .all_macro_rules + .get(&Symbol::intern(path_str)) + .copied() + .and_then(|res| res.try_into().ok()) + } + /// Convenience wrapper around `resolve_rustdoc_path`. /// /// This also handles resolving `true` and `false` as booleans. @@ -560,7 +558,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .cx .enter_resolver(|resolver| resolver.resolve_rustdoc_path(path_str, ns, module_id)) .and_then(|res| res.try_into().ok()) - .or_else(|| resolve_primitive(path_str, ns)); + .or_else(|| resolve_primitive(path_str, ns)) + .or_else(|| self.resolve_macro_rules(path_str, ns)); debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns); result } diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index 44bf86b082a..dffceff045d 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -1,4 +1,4 @@ -use crate::clean; +use crate::clean::Attributes; use crate::core::ResolverCaches; use crate::html::markdown::markdown_links; use crate::passes::collect_intra_doc_links::preprocess_link; @@ -24,7 +24,7 @@ crate fn early_resolve_intra_doc_links( externs: Externs, document_private_items: bool, ) -> ResolverCaches { - let mut loader = IntraLinkCrateLoader { + let mut link_resolver = EarlyDocLinkResolver { resolver, current_mod: CRATE_DEF_ID, visited_mods: Default::default(), @@ -36,27 +36,28 @@ crate fn early_resolve_intra_doc_links( // Overridden `visit_item` below doesn't apply to the crate root, // so we have to visit its attributes and reexports separately. - loader.load_links_in_attrs(&krate.attrs); - loader.process_module_children_or_reexports(CRATE_DEF_ID.to_def_id()); - visit::walk_crate(&mut loader, krate); - loader.add_foreign_traits_in_scope(); + link_resolver.load_links_in_attrs(&krate.attrs); + link_resolver.process_module_children_or_reexports(CRATE_DEF_ID.to_def_id()); + visit::walk_crate(&mut link_resolver, krate); + link_resolver.process_extern_impls(); // FIXME: somehow rustdoc is still missing crates even though we loaded all // the known necessary crates. Load them all unconditionally until we find a way to fix this. // DO NOT REMOVE THIS without first testing on the reproducer in // https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb for (extern_name, _) in externs.iter().filter(|(_, entry)| entry.add_prelude) { - loader.resolver.resolve_rustdoc_path(extern_name, TypeNS, CRATE_DEF_ID.to_def_id()); + link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, CRATE_DEF_ID.to_def_id()); } ResolverCaches { - traits_in_scope: loader.traits_in_scope, - all_traits: Some(loader.all_traits), - all_trait_impls: Some(loader.all_trait_impls), + traits_in_scope: link_resolver.traits_in_scope, + all_traits: Some(link_resolver.all_traits), + all_trait_impls: Some(link_resolver.all_trait_impls), + all_macro_rules: link_resolver.resolver.take_all_macro_rules(), } } -struct IntraLinkCrateLoader<'r, 'ra> { +struct EarlyDocLinkResolver<'r, 'ra> { resolver: &'r mut Resolver<'ra>, current_mod: LocalDefId, visited_mods: DefIdSet, @@ -66,7 +67,7 @@ struct IntraLinkCrateLoader<'r, 'ra> { document_private_items: bool, } -impl IntraLinkCrateLoader<'_, '_> { +impl EarlyDocLinkResolver<'_, '_> { fn add_traits_in_scope(&mut self, def_id: DefId) { // Calls to `traits_in_scope` are expensive, so try to avoid them if only possible. // Keys in the `traits_in_scope` cache are always module IDs. @@ -101,64 +102,83 @@ impl IntraLinkCrateLoader<'_, '_> { /// That pass filters impls using type-based information, but we don't yet have such /// information here, so we just conservatively calculate traits in scope for *all* modules /// having impls in them. - fn add_foreign_traits_in_scope(&mut self) { - for cnum in Vec::from_iter(self.resolver.cstore().crates_untracked()) { - let all_traits = Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum)); - let all_trait_impls = - Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum)); - let all_inherent_impls = - Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum)); - let all_incoherent_impls = - Vec::from_iter(self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum)); - - // Querying traits in scope is expensive so we try to prune the impl and traits lists - // using privacy, private traits and impls from other crates are never documented in - // the current crate, and links in their doc comments are not resolved. - for &def_id in &all_traits { - if self.resolver.cstore().visibility_untracked(def_id) == Visibility::Public { - self.add_traits_in_parent_scope(def_id); + fn process_extern_impls(&mut self) { + // FIXME: Need to resolve doc links on all these impl and trait items below. + // Resolving links in already existing crates may trigger loading of new crates. + let mut start_cnum = 0; + loop { + let crates = Vec::from_iter(self.resolver.cstore().crates_untracked()); + for &cnum in &crates[start_cnum..] { + let all_traits = + Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum)); + let all_trait_impls = + Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum)); + let all_inherent_impls = + Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum)); + let all_incoherent_impls = Vec::from_iter( + self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum), + ); + + // Querying traits in scope is expensive so we try to prune the impl and traits lists + // using privacy, private traits and impls from other crates are never documented in + // the current crate, and links in their doc comments are not resolved. + for &def_id in &all_traits { + if self.resolver.cstore().visibility_untracked(def_id) == Visibility::Public { + self.add_traits_in_parent_scope(def_id); + } } - } - for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls { - if self.resolver.cstore().visibility_untracked(trait_def_id) == Visibility::Public - && simplified_self_ty.and_then(|ty| ty.def()).map_or(true, |ty_def_id| { - self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public - }) - { - self.add_traits_in_parent_scope(impl_def_id); + for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls { + if self.resolver.cstore().visibility_untracked(trait_def_id) + == Visibility::Public + && simplified_self_ty.and_then(|ty| ty.def()).map_or(true, |ty_def_id| { + self.resolver.cstore().visibility_untracked(ty_def_id) + == Visibility::Public + }) + { + self.add_traits_in_parent_scope(impl_def_id); + } } - } - for (ty_def_id, impl_def_id) in all_inherent_impls { - if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public { - self.add_traits_in_parent_scope(impl_def_id); + for (ty_def_id, impl_def_id) in all_inherent_impls { + if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public + { + self.add_traits_in_parent_scope(impl_def_id); + } } - } - for def_id in all_incoherent_impls { - self.add_traits_in_parent_scope(def_id); + for def_id in all_incoherent_impls { + self.add_traits_in_parent_scope(def_id); + } + + self.all_traits.extend(all_traits); + self.all_trait_impls + .extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id)); } - self.all_traits.extend(all_traits); - self.all_trait_impls.extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id)); + if crates.len() > start_cnum { + start_cnum = crates.len(); + } else { + break; + } } } fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute]) { - // FIXME: this needs to consider reexport inlining. - let attrs = clean::Attributes::from_ast(attrs, None); - for (parent_module, doc) in attrs.collapsed_doc_value_by_module_level() { - let module_id = parent_module.unwrap_or(self.current_mod.to_def_id()); - - self.add_traits_in_scope(module_id); - + let module_id = self.current_mod.to_def_id(); + let mut need_traits_in_scope = false; + for (doc_module, doc) in + Attributes::from_ast(attrs, None).collapsed_doc_value_by_module_level() + { + assert_eq!(doc_module, None); for link in markdown_links(&doc.as_str()) { - let path_str = if let Some(Ok(x)) = preprocess_link(&link) { - x.path_str - } else { - continue; - }; - self.resolver.resolve_rustdoc_path(&path_str, TypeNS, module_id); + if let Some(Ok(pinfo)) = preprocess_link(&link) { + self.resolver.resolve_rustdoc_path(&pinfo.path_str, TypeNS, module_id); + need_traits_in_scope = true; + } } } + + if need_traits_in_scope { + self.add_traits_in_scope(module_id); + } } /// When reexports are inlined, they are replaced with item which they refer to, those items @@ -170,32 +190,41 @@ impl IntraLinkCrateLoader<'_, '_> { } for child in self.resolver.module_children_or_reexports(module_id) { - if child.vis == Visibility::Public || self.document_private_items { - if let Some(def_id) = child.res.opt_def_id() { - self.add_traits_in_parent_scope(def_id); - } - if let Res::Def(DefKind::Mod, module_id) = child.res { - self.process_module_children_or_reexports(module_id); + // This condition should give a superset of `denied` from `fn clean_use_statement`. + if child.vis == Visibility::Public + || self.document_private_items + && child.vis != Visibility::Restricted(module_id) + && module_id.is_local() + { + if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() { + // FIXME: Need to resolve doc links on all these extern items + // reached through reexports. + let scope_id = match child.res { + Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id).unwrap(), + _ => def_id, + }; + self.add_traits_in_parent_scope(scope_id); // Outer attribute scope + if let Res::Def(DefKind::Mod, ..) = child.res { + self.add_traits_in_scope(def_id); // Inner attribute scope + } + // Traits are processed in `add_extern_traits_in_scope`. + if let Res::Def(DefKind::Mod | DefKind::Enum, ..) = child.res { + self.process_module_children_or_reexports(def_id); + } } } } } } -impl Visitor<'_> for IntraLinkCrateLoader<'_, '_> { +impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> { fn visit_item(&mut self, item: &ast::Item) { + self.load_links_in_attrs(&item.attrs); // Outer attribute scope if let ItemKind::Mod(..) = item.kind { let old_mod = mem::replace(&mut self.current_mod, self.resolver.local_def_id(item.id)); - - // A module written with a outline doc comments will resolve traits relative - // to the parent module. Make sure the parent module's traits-in-scope are - // loaded, even if the module itself has no doc comments. - self.add_traits_in_parent_scope(self.current_mod.to_def_id()); - - self.load_links_in_attrs(&item.attrs); + self.load_links_in_attrs(&item.attrs); // Inner attribute scope self.process_module_children_or_reexports(self.current_mod.to_def_id()); visit::walk_item(self, item); - self.current_mod = old_mod; } else { match item.kind { @@ -207,7 +236,6 @@ impl Visitor<'_> for IntraLinkCrateLoader<'_, '_> { } _ => {} } - self.load_links_in_attrs(&item.attrs); visit::walk_item(self, item); } } diff --git a/src/stage0.json b/src/stage0.json index 5990ab44359..952fc7817d4 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -2,347 +2,347 @@ "__comment": "Generated by `./x.py run src/tools/bump-stage0`. Run that command again to update the bootstrap compiler.", "dist_server": "https://static.rust-lang.org", "compiler": { - "date": "2022-02-22", + "date": "2022-04-05", "version": "beta" }, "rustfmt": { - "date": "2022-02-23", + "date": "2022-04-05", "version": "nightly" }, "checksums_sha256": { - "dist/2022-02-22/cargo-beta-aarch64-apple-darwin.tar.gz": "5b23653987a4157a80be39e7c3560f79b1b40ecdb30ae156170e02f659020e78", - "dist/2022-02-22/cargo-beta-aarch64-apple-darwin.tar.xz": "f2e8b34a2b57d9aa876b60d081689371aa2802e4e6ea38329785f2cba3c40dec", - "dist/2022-02-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "57d51d004175a2c05892b4edb347300c42cf5764d52f6aabc905e8cd8cb60330", - "dist/2022-02-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "5c0c7698b31394e531dc005b48b6ab78dbf74914cf7daef8e7cc41791adaa061", - "dist/2022-02-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "1257e6ba753b1328a22730b53da7db3064797d4bda5e02ee79566bec31cf60c3", - "dist/2022-02-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "12289ddd9564f7bd25eadfb182d67fbff275244faeb281d918998ba578f5923a", - "dist/2022-02-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "8d4d767930996e35c66b2208056b3c57da7cce642650ff3e12ca3e7f8c612d9d", - "dist/2022-02-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "a0e0ceeb786273d33d79e939e6aeb015d1e960c88675bd582815ff31312c0948", - "dist/2022-02-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "bd92f426ee10d84d162a78955e29d4da7c4c76808d17a81ad599777e76dc8869", - "dist/2022-02-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "844c40ed33b03d1cd7a0a82995ef02e33a450155cf1bab36e7b5cddf61ce7ebf", - "dist/2022-02-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "0a8e1a8ca38be1356aadf8f6e2f51d2b83ec27c87f3c63c0dc85dba5337b3139", - "dist/2022-02-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "de54fbd0cdd17e74e576fc1ad2147542fb82a845ac336c7efb284c6ffaab21c9", - "dist/2022-02-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "561b7566dd155b6ea6ae2dd1f6de6ae49b3104df7f6ad5bba59e2505e4a2386b", - "dist/2022-02-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "eff55c73491c83b109c2cd4e67f8e82314ddd9abcdbfcc358fb8c2423b31aa8c", - "dist/2022-02-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "3766d773de8332b0b6bbff26bdbeb090eaddf12badc37c91280cf26825400796", - "dist/2022-02-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "55e3553aacaab2139e15d231cb7c328f3abedf6c7014be64fab98b657b12dff3", - "dist/2022-02-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "b59118825ceee16f18a73de57da9de3db35715d9c53fe50c9dd3eaaaac0cf234", - "dist/2022-02-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "f530b478e8de8a1e23f73d0a7f9467835c02f5d5c29cabcaf6b7c8191753d23d", - "dist/2022-02-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "40354386ce0a62ae2851ed9cd82e86ff7da8fbce0a0232ba63b71b1ea583af8f", - "dist/2022-02-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "d480890b820adf734e4c952e7fc78636b679684ed9bcceb73c4596fb1d45c8e3", - "dist/2022-02-22/cargo-beta-mips-unknown-linux-gnu.tar.gz": "36575bdbde3af9f33467608d123b145a35a708c6814e8e66be3736cf38fcf4b8", - "dist/2022-02-22/cargo-beta-mips-unknown-linux-gnu.tar.xz": "977da6dd9a6865b125222d0a2067d95de6dc1042533df14bb8598e3160cd26f8", - "dist/2022-02-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "bac180c4c4d26acb42916f489abdc9bcc98683de2f9437ef56b00b624338db74", - "dist/2022-02-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "48640b94de8f38bc1c285c6c7a3f973c461d7336acfbec1b2f1eab09294929bf", - "dist/2022-02-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "870e51831fdb84e927b4556d3f6e1882bd8d3a542d36fd9c59a52333b7671e9d", - "dist/2022-02-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "898ea5ba25d4503092cdbeda226947c4465515e684945dbd16b9009881f1c2c0", - "dist/2022-02-22/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "b5177d9199b585710cf0f9cf65b9d5e9e3372e869a6a1445119566878737358c", - "dist/2022-02-22/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "9aa14abb02c8ccd4f9b684c02a544776e0936919f8f7e46698f85a69b7dbcd2d", - "dist/2022-02-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "9d6bd864f629a957172c7fbd20c7549d88248a42f259e6be9f779b4bbb4b09bd", - "dist/2022-02-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "988929cb1e75d053c1b081a8a672310447e630195175fd1e54dc5d0ec35783df", - "dist/2022-02-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "1b32b43d0ec4989d048223ffdc914656c693ea978e38543b45b1d0c78a6f2c2e", - "dist/2022-02-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "cd52c1191291ad23dee3a5eea11cb30d2b39e5be56cfbeba72d63add0c1f8689", - "dist/2022-02-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "54126eee55aadba389058e4114e57898604398a3638cec33cb06f0b08f19c293", - "dist/2022-02-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "04c0333e2ed44f0c6c24583f8dd08041bff444024407b5b15ca4679830d00748", - "dist/2022-02-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "d06c620327fbfbff716ac80c569fa3f93d21a137653226c3417a32978d7c21fa", - "dist/2022-02-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "dc9c6058c0612b9e75f17785571f334e3ab07d7d41e7e6892a9f176a032efbfb", - "dist/2022-02-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "41740c9043a17a6f94ccc9b1ce3e651bd5c1d40082573c2603fc467e3e7211d6", - "dist/2022-02-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "9f35c90f54fd109dc89101dc4f400c1e2274c73dd830ea47032f6669f17d2281", - "dist/2022-02-22/cargo-beta-x86_64-apple-darwin.tar.gz": "bb2df47156ed411068df28b2f3da9cbd1a43e87da92b79b08f49c9ec1b7acf9a", - "dist/2022-02-22/cargo-beta-x86_64-apple-darwin.tar.xz": "1e28f97bba0788d8666ea99dc6794f14246248d2215ca954523a022f32f0032a", - "dist/2022-02-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "ec819340d489948ca3376011e504163b2b8aa4a795757b76c680d7827a894d51", - "dist/2022-02-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "74e39561dec9a133d98e85f05659353fe5123b813e2042a6e1d1aeff44f8f018", - "dist/2022-02-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "43c4071dde2a487211ccb8b70738dd9f2bff6d629c10c676387bcf3dd1bbdbe5", - "dist/2022-02-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "14aa403752daef201d9c62efaf342fa9070f1acd15417a212840dec9b04e0bf6", - "dist/2022-02-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "dd186508224dddd5fd701741913bfabfc0a11ac4ec3268e4089ff20a9e6db851", - "dist/2022-02-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "051a08c9a74150e706f683c96ed1a89531d75622a379e738f27c838317f1aa0e", - "dist/2022-02-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "ed980715be8e3e8354656e09b0b8fd265a1009c7af3c77a0da7ee297c746d465", - "dist/2022-02-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "119943b8a0c62839de252a372960c93124b99de1b918122d2798dadac8658918", - "dist/2022-02-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "1738f1416773c85571414162ba894a753db03fcac9770012358f64db341fedd3", - "dist/2022-02-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "eac6a6deb3a7cf0d9d6c0d474cf3af2c3fb6a27f047c59e39549af219a04e487", - "dist/2022-02-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "20d7ee9d7234395840b2478681ce4d79bf71045ae218d61f6b54ab9476dc39a1", - "dist/2022-02-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "3eaf0ea2187a5483738aef57c1a72e90fd7d2f1f43d161b4312a88a2afb5fb36", - "dist/2022-02-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "7359595da468c6a22e42c8cc1918034e1efada2458281354d378c6921fd839bb", - "dist/2022-02-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "901fced3b888c3d117b7ce5dae9f670b5a3251572d6e2dc2b143c734e38ac683", - "dist/2022-02-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "dca112bb73d3db03df91770cda1a90f130fa19e80657bae8c70c9737a1739f0b", - "dist/2022-02-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "5d86a54ac7a3da08eee4401cbdca416b88f47e3f873bf77aa09f9d8259bde015", - "dist/2022-02-22/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "7496f9dc8cab45f14ff01c3ceb7938dd2532b802903aade5775f1311e29a2191", - "dist/2022-02-22/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "fb0704f0b2dd9cbee2a7b887963c15fd5c3391425632362161d59e94c81b608e", - "dist/2022-02-22/rust-std-beta-aarch64-apple-ios.tar.gz": "b63c47df8f9ee3a498248898d465dd24c2de842d3a61e2a7850fc10348c65080", - "dist/2022-02-22/rust-std-beta-aarch64-apple-ios.tar.xz": "d25ee7959831231a1661f95ca11bd3fbd5cb177ae8cd82bb3fb33889e8a081df", - "dist/2022-02-22/rust-std-beta-aarch64-fuchsia.tar.gz": "06fa5e122904ff03b1e0e9218a58b7c492c3cbb57e2d26e255171f6c7734f5b7", - "dist/2022-02-22/rust-std-beta-aarch64-fuchsia.tar.xz": "8b4a60e54a255c5eb45545c78c4b43d78527777f874a8a9b215999b414c3dbec", - "dist/2022-02-22/rust-std-beta-aarch64-linux-android.tar.gz": "7209d2f4fb41fe00afee1d49246228fecd955930abac317f7ae608a4eb27f834", - "dist/2022-02-22/rust-std-beta-aarch64-linux-android.tar.xz": "ad8aac4d753c357fb39408c01567a95710f95c73b5589d37304f6d8eedf43ea9", - "dist/2022-02-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "0e25c7a39e32cd3dff61a2972df5e5a08f743d505d0a1e99a26768b3d0abc44a", - "dist/2022-02-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "63f7d6967c920135bfdc45e4867579ffe5858d1608777bae0c64e3bb74180bc9", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "e1688baa8a9681e8975885def8ef160da31f79d4b767fdfffda0eb4a281c4a20", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "07acb0382de4c967421ad62367c4585e567ac16f82b2c6d2bac4218999ea217e", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "9abe9e57210890632319ae175e4ff10d4c05d505820e6e6d4b694a84e57b3e53", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "cf9edb113ce62b71b7e6d535c2d0c153fb0041a86ccf22393c7fa1bde99ff589", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "1d378a8eff18de4487f6edda01f9c9f991b0f3dc575be062d5faa04f0489dff1", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "84c23145e5ce8fe37088d413e3bc4072cbe662feb0400895e91e924515c4d8ac", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-none.tar.gz": "04a154058d8014608bbde9e70a85bb1943c58053ac64119ea84be70a1a085c35", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-none.tar.xz": "6edde8a372c29756b54fccf54232fee7899625eb6c5529658024028ae4f8a471", - "dist/2022-02-22/rust-std-beta-arm-linux-androideabi.tar.gz": "b1670696b4aa52daa390a5c9ce26056507a11ff883d98ed6e84a7f04b38ee7a2", - "dist/2022-02-22/rust-std-beta-arm-linux-androideabi.tar.xz": "2cb4a03fb3b8d8556c359c4d4f1823dbef3a22f0483e43f41ee154333a202ec8", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "46f7ba3b96a9088f242a0ad191ca320529d9798d8842d41accd14622fb7b6750", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "091190cccf966aeb6d387fb6542ad43f7f38b6843a13309f92df2f759a4045dd", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "4d1740f7d33566e2642d1618d9c6cd0c0650d39af5d428dfd993a4f65e27e3c6", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "4d4c2f1fb3319030b978d1343b80a34c22b3c4df58ef1dbce9eddc42a0e9ac41", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "d7ad7df20a41f7df39fd0973f37740d0c732468de6e099febc13db7f871860b4", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "598c5ab98d3a3ffeb4f3aaf5535d8947e6ae6d45aa0071438f9490dd63acf7b5", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "46d2276ab614e5f4d1f990824fd2b67c9398c669a01698c8a4b157bd45e3eedb", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "f404d2c3d89ae820112a324a3c5bf127efb6fb31813138c0fde99948eea7d76f", - "dist/2022-02-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "8c8c547387db74673c1954b8ac1cdeff5b726d432581649bc60f988acb0352e2", - "dist/2022-02-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "2942966353af6f1a29c3266e1f35e3f1bf49a7d555a6034dda72c31b7e83b89d", - "dist/2022-02-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "3b80afad86c655b5be24ddb8348c3d5781006053c14932ab2855be525c35108b", - "dist/2022-02-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "3b55016a3f27aa0381eb502e2d732aa9397aac117e98d4fb4721587b62ac7842", - "dist/2022-02-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "2c17d2a504c4f7aa581731bbfa9eecc1638b9bdc8800d136da1a6d248ec70e76", - "dist/2022-02-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "78dcb72afa5187b7ae91a1ccc2e7978b30cab8eaaa46cb09a62266868c866ad3", - "dist/2022-02-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "d42741e9ea6f23fc88dada5e9339cf7fb3015d3713335b77543afeaafdfcbb53", - "dist/2022-02-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "ecd0e30fbd08fc8dbf478ddfb7a48b619b84b04c687bdcd56259b64f9ccedea1", - "dist/2022-02-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "b4fedc281f748c443232bf061fde9dccbf415eec62053103a270613689c4cf1a", - "dist/2022-02-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "bae884d552a8d234efa795b5b56524cb834f06c77000e926bc0bd1446387174d", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "116c08ac9ca36e0d3d0bb86d0d25db8f19b508d851b93c6a738711400e1faf93", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "d15b7e02a7fdf7d45d0269b4c739a96dda4f22ef70d7a3a2b098527b34f81b76", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "86390d1528d0382109ae094005b35d84ccb5e6bc670a490d2c8e27010efafb13", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "fb23bfcadc53baf72793718b051710a6bfa6575f8fb7104925157681b1efdc3f", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "f34cce7af6d123b9c509f28d63f10397ebbea74b6181b819d022f700521dec7d", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "2777e62cbd8ddd5dce730f4a6671dffac132ecf194a8840178d178296264879e", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "4e6f11b82e57c60ab5e4329bcb0c5384f9bc2044ee8f194c3022949855389ab8", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "a45eaf577ddf69ebd8eb7b112bf2b79ffa7a3360ef959f6bfb5f0a5e634ede48", - "dist/2022-02-22/rust-std-beta-armv7a-none-eabi.tar.gz": "66fc6787cf5060b8d279d325ef745dc37206335a9e279bb7f3687b6564f3bdab", - "dist/2022-02-22/rust-std-beta-armv7a-none-eabi.tar.xz": "3996d7a5e7721262fed35af65949523510544eb3942c97dbcd231f84770edb7a", - "dist/2022-02-22/rust-std-beta-armv7r-none-eabi.tar.gz": "be50c97fd48c7209b2b452f3f9c00cca1fd26f8482b4c5bec46b9a32dbbf9cf1", - "dist/2022-02-22/rust-std-beta-armv7r-none-eabi.tar.xz": "4f74859110079c69ff3a84a4c4110ec4df7d4ce7bf4886a9115defc11174f41e", - "dist/2022-02-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "1d29241da65cedfd665917fdc0ae8d66eaf847280c57ebfa630d6e4993232642", - "dist/2022-02-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "a3898ab71f6fb6f0a0b85f706d74fc75330eaded7e4fde7e9903ad375b2c4c9e", - "dist/2022-02-22/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "6c895e95c55cb55a40a24cbe381a5ce6ed5d50a6ce97781c33429fb846449a9d", - "dist/2022-02-22/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "524b781dc177afef5fa70b13a80961d26ecfae25c331dc967127ed9964c29f98", - "dist/2022-02-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "43fae07717c4b20690c6d0843f43e10581e656346fcc1363cbb2f90efcbab93c", - "dist/2022-02-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "20c2d659ed82a128cb31d4fed737d79245edf84101b1ad58e4b694784c181aa1", - "dist/2022-02-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "240c51132bb92b3e5d0b3abd281c1d317aae0cdc23ac5d06b465fd6a3a783913", - "dist/2022-02-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "b8aafd530bc9f888b2d73d2ddb232501e481999faed06026994bfbc479adc892", - "dist/2022-02-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "0f36dd856386e03f34288c0fb720b86cb31969b1db5c90f6ab6329319b344b40", - "dist/2022-02-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "5bc340d21f80eb420ceafe5d7eb40651dc00dbbbb8ccde59ff88d6843ac93cda", - "dist/2022-02-22/rust-std-beta-i686-linux-android.tar.gz": "9eed175b238e5b7f2d7600233cda65efe570050f501680be8e08d98a54028123", - "dist/2022-02-22/rust-std-beta-i686-linux-android.tar.xz": "d6b106f23ac95537191b460847ce38b7e7f6ebb120561cb2b4497ec40d53217d", - "dist/2022-02-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "51b91d661906c4c6e54bfd34c16aa874447da706f15413c9f6caa7943e49b165", - "dist/2022-02-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "1d8b8c856e3eb75578a187a483074b2d78ea6c6047018a8110d685a9b6f59812", - "dist/2022-02-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "be373ef9dbc40c44be1cce66d6a37379670d8c6073d2e3ee0c010e08b8d0290e", - "dist/2022-02-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "97a8cabc18f4745c856e8a51deeb3b2cfaad15aa854dd8bf50d742c498375802", - "dist/2022-02-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "4dfdaa7fa0d282dfcc8a919fbc077fb5a987820ea920a3f443ad286c3f16e134", - "dist/2022-02-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "e9fef55eaf2302ae80b411bef7d3c52b9a2f8e5e80b1e629541722508aea629c", - "dist/2022-02-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "05b2bdc3bdcc5853d4b44423031e82452d040c74d5b3832e03910c25c752e70f", - "dist/2022-02-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "1038a6415b9f68c63cecb98b0ad860a0f424d7053e4fc6cc52c3054cdd9b3c56", - "dist/2022-02-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "588b13f016e2fd49c4261a230dde062f68de10d8b128e1b801071f6fb04e42b4", - "dist/2022-02-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "91dd6f3c85b28dc1aa0636bcfda1156c97fbb1322156c2a600bc66e2bac22627", - "dist/2022-02-22/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "140af043ae006d47e7b19badfede6aa684c455b18df6d7da4a7c2437a9d303e8", - "dist/2022-02-22/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "0ec24313945e2fe853c1139e729fa40e5ffec406070bd52468a23b96efd08c5d", - "dist/2022-02-22/rust-std-beta-mips-unknown-linux-musl.tar.gz": "3b4c2aa34c84d5cf6460f8fe46ba0e0596fe83403f38f0f53d8b14ecab3d7de3", - "dist/2022-02-22/rust-std-beta-mips-unknown-linux-musl.tar.xz": "53c3476fb78702570ba096d2f6becaef2b402bf8c5afa58b8d559ddbe7a379c5", - "dist/2022-02-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "e2963c7aaa7ae70a341a67d93d52ac2911309cb1977639e85750b0dd8061bb21", - "dist/2022-02-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "76444714fb5cdc40797c0d217536b4328484c12f2ad0f47e3635d88fc31aa958", - "dist/2022-02-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "0eeef057018f809ef008d23df65ede61b1d1695d2d5ffb6cf322e73939f789fb", - "dist/2022-02-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "efb4db958a03894289570b0383eedf47e3d3723793eab95a1336a8e4fac0a909", - "dist/2022-02-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "59a15a0870013712d2d5162d180bfae71388eefb63d0ff0ee3dd30471c4feaf0", - "dist/2022-02-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "46d9a7e326d582ec0d9cc674b4f2976da877b16197b0aec2ac783b3cbca8d0e2", - "dist/2022-02-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "c6f88389945fc1802fbd271bcdfe77172d60b27b6416a6a899c29854748f93b0", - "dist/2022-02-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "16ac29879c3fadb76ebc8ae1234dc4c2aed1809f329a95c67e5e54aa2730e9a7", - "dist/2022-02-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "6c93eab95575a3327ec019c45f57564bf8c2bf92df1c9cc895de6f6b6514c695", - "dist/2022-02-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "81e560c30f477cee45c866c6653fcf2b7942287547321f939ab68a849d1c680e", - "dist/2022-02-22/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "612d4169406b20abaa38362dad969008d5d3eea1b7c5a376f5ff33870879e70b", - "dist/2022-02-22/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "d39459a64250838ac6b46352de106fbd199e4e586f066123a1ffe78f52291d1d", - "dist/2022-02-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "ef9ada210252cf9f66e7ff6aa43855318ac6030b6a963f4f25ef227c3b50a51d", - "dist/2022-02-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "7ba46c4171c4776770d8a5e590e8b3e12fc85d519fe85c5db166569d353fa371", - "dist/2022-02-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "11e163b7e4884078185ac92fdba62a77468b70ffe0e4f22a6c420ff8441d12cd", - "dist/2022-02-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "3f88f0163078a219730898a77f3bf8db3df3967100931a4685bcd9d43f2b4668", - "dist/2022-02-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "68742e04b7fa9f398945363b41e8988040f53c46de6fb7b481647052d54f23ad", - "dist/2022-02-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "f978bff9ae78b26c439a3817648a63cd9e9e149bf08cf2124ef2372b5863c52e", - "dist/2022-02-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "715d0512df81db8266b1264721704ef069a78ae5ec615c772e876c119723df80", - "dist/2022-02-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "65739553817038796c9364f8e92f7b492872cc46cab9ea3535b74ce55a1b6474", - "dist/2022-02-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "65815e6f296c5651f4185820c2bfe9a6929d3a4aba555b453b1e21791e98586e", - "dist/2022-02-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "51f1a45d7fea68806220a31877c4ae2aa0be171aa594fab847ee295682afe9d2", - "dist/2022-02-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "25199052e5e2f39611c60cfb6c071337c3621eef7203090a1f1abba9959a05e5", - "dist/2022-02-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "ac272237e72fc06a2c940f643df7d614267182acdaaa883cdc2ed86baa83e955", - "dist/2022-02-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "8b6b8235a671d0ca3b0548b64197ec320975d9866f13435c069b279f95e8d8d9", - "dist/2022-02-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "f0136a97c8338e72e05bf4390ac0a828f52559b73727a9a075c137dbaa249637", - "dist/2022-02-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "7be9a45ddbdf281496520d76372a004f16b927fc6bade0ae97ad8b92d34d3d7c", - "dist/2022-02-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "47f3a3d69b0819dc681e37437618a2130f4c5aa199cad3bbbbee8bd442374ac6", - "dist/2022-02-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "8a7d37d7e022c4513877f428361312963d555f35e78978efc27f4eac2e411b6a", - "dist/2022-02-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "d530edb2ceadba90b840a691b61f267388b9022003318f489fd46c84560459b9", - "dist/2022-02-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "012398447b0236c20a3ceab1e4f6126bac120c361875f15d304e9ecb7c6781a3", - "dist/2022-02-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "c092dc1d8ee387e1ac8496b3bb412175a03efe4cf923b82ac4ec47c880986e72", - "dist/2022-02-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "acaeda013557588d8c9643fd0aa7ad0da5cc7c64f7aca0fc383b00f7b4a174ac", - "dist/2022-02-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "99c1a499bb9cfa343bf03da8abfa8f18595fedc3fb354e893fa62f67d067bd89", - "dist/2022-02-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "e07bcd62f79c9f764b6c6ea8d3744506beb8e1ee1ddb202276f116e9ee44ecc5", - "dist/2022-02-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "2283784176fc003b8ce29899b747dbdbe848fc226f963ec36a95d79b1afb0c0e", - "dist/2022-02-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "80c1613f9598db047a95be40494870942a5a4ef54c7e4a72c9fa3df9b23f64b1", - "dist/2022-02-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "9b33ce8b938978caa4164af52bbb982183fa2fa86e5f079805fb6f479c8c9aae", - "dist/2022-02-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "794c9b2cbe3e76e2dbab31d89817a7c21bdc19a59022ee652862aac025db6914", - "dist/2022-02-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "0a7afdedd20874df94e9604669926b1ce82b68774db7756312d43bbbea3e9334", - "dist/2022-02-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "19821e7291f4363f37b5ef2a1b505163cdf02e38d5b47aa980892e794e918c73", - "dist/2022-02-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "a4e0b594b756316bbaa05ebd4d0559edc9a733d5ffe84797c6e096882969ad36", - "dist/2022-02-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "222e15bb1db6e80459616a001ca8fcad8aba9921b1161e8b9ce9e38fd9fb2d10", - "dist/2022-02-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "72ae8a9dba6c2913ba3eaea2e96d7e744985f6c5badf170daa678c00b89e93e8", - "dist/2022-02-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "74b4d65d13262964ef180fd7a63a3d2f62c529aa3b99883e3e83815338129631", - "dist/2022-02-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "7dfacadec18736016520db4a07a677f74771db955418f4b1df6c09d871e159e9", - "dist/2022-02-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "6bf0482aecbe5d1dba551319cffa074e0a72e6ce8c2e636ead98733429bdf09c", - "dist/2022-02-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "81e9ff4577785f9d11cfbf92ee18dc6a1202147500ffa474f4a0ab099af0f7e4", - "dist/2022-02-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "bf073994172580e7b9e5a0a618ae5f58759801a8e949d2137f69191d05b146eb", - "dist/2022-02-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "8c21d837cd9e1c98db78b4c37dc03f07373184e2354880a1dd9501fc62f8b6f7", - "dist/2022-02-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "167f9fc5aa4d3dd68044110a346d5888d9bacc5c8d3fb1140d2687f312ddb057", - "dist/2022-02-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "c64177f1aab599a25d97497124c5d4e9449ecffaf96caefecc8b0a2552aacb4d", - "dist/2022-02-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "95de6b1fbd95287258f9caac1f805492afc9657adfada82295736d85b1b20c3c", - "dist/2022-02-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "d3f8c5ed80c59b1bd2c538aab63be8b39db78db3c2f49d7447092a8b97e2963c", - "dist/2022-02-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "aa0ec6f6b0d652ebde2694a8153252928cc1f41c565912da8bee5b0d225b786b", - "dist/2022-02-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "1f23bcb96112bdec4a1f45c41afef3faa95cddc5be2f693ee3e1f4f3e584c49f", - "dist/2022-02-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "49d6ea925560f3eed75da2c7d9cefe404525702504ce0cc4cbfb3fe638814566", - "dist/2022-02-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "13b93becc017bb6bb60212ba30d6717a1be6af139b965b15000264b48e163991", - "dist/2022-02-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "27f3dffa92ccdc8d2b3342e737b5f80b7b2dbc53a994249bf318810f4d8b4643", - "dist/2022-02-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "2236cab6b48c9c564731913dc652a2e0cc6af0d6b9a64b66cf39a6b943c410da", - "dist/2022-02-22/rust-std-beta-wasm32-wasi.tar.gz": "35ca9a19558512fc1758e9c7482246bf6a518e48d4a93a8748c07ebdb4be9d6c", - "dist/2022-02-22/rust-std-beta-wasm32-wasi.tar.xz": "3bbae2bf8423e3323155f3f336435fbd53b58cfa16107f9fa567ea77923e5ff4", - "dist/2022-02-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "9a6c1808797c92da862f706f08a6482a4412e52dc9a492d06645f03c8b1c0fc6", - "dist/2022-02-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "2a658172c220c047542e992a8b1440d887d809f301f3a0e23a811d586ff43dc2", - "dist/2022-02-22/rust-std-beta-x86_64-apple-ios.tar.gz": "2da9affdcc01bc9369192b40feb0797349d2084fb6ddff55e61d7b0a831272cc", - "dist/2022-02-22/rust-std-beta-x86_64-apple-ios.tar.xz": "dcf403a1d670bdb0e29d61161d268a2be9a6d31ea4055dff562e06cb72ba1c78", - "dist/2022-02-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "506ad99d890f0c1ff525a8c9f28aa4f7aec349afd78279b21d7486a88f548ef0", - "dist/2022-02-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "4f20a7b59e32266fc01c67d36ec27f68e9a44105819e1c5a1dc8823367c4914a", - "dist/2022-02-22/rust-std-beta-x86_64-fuchsia.tar.gz": "0705d9ad7e640a8a4b48c88d1997ffa57f849d1fa4cf3ae4185afd2122ed6b60", - "dist/2022-02-22/rust-std-beta-x86_64-fuchsia.tar.xz": "2b5382417346f07f105704eac3fdd4a8bfa0285804715a64d1e314a0c9ce4ef6", - "dist/2022-02-22/rust-std-beta-x86_64-linux-android.tar.gz": "03404906af39d9111316c624835a09a4326f6172f52a405b82f831c3b408ea9f", - "dist/2022-02-22/rust-std-beta-x86_64-linux-android.tar.xz": "5ff2b24d8fc552a791b609de6373afc57a8661d2769e89f4e19c5cf85be864b4", - "dist/2022-02-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "a90e13d0e45a71843caa1dd960a7b032120034aa0caa4148f825e3493d65640e", - "dist/2022-02-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "d176219f6fb41aa0bbb59b11801f45af29edeb24423325b162686d3fc3d3ff93", - "dist/2022-02-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "dd8da303ff2740b3b9ea565ed9a335f62de8c1357884660abbc4e7a9ccef7a74", - "dist/2022-02-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "d807829b1328527f49d318ce942dea5fd8e71a8fa16cbfe2d7444fb5a962e158", - "dist/2022-02-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "7ba1551ce159030125ce74ae7321e0365fb2d33758fd2a578693dec8ff817c66", - "dist/2022-02-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "55ab2bcc5469ff433e15c06f490af3721abd6dc468eed68ce3fb2842dacaf28e", - "dist/2022-02-22/rust-std-beta-x86_64-sun-solaris.tar.gz": "1e1b97a4840415f7efada876ddbeebf336ea4c6a0d0fab4238ce1f490e6450a3", - "dist/2022-02-22/rust-std-beta-x86_64-sun-solaris.tar.xz": "20377a3a7eb39727c3c4202a35569c52362f486fdc3ea451a0d9cc5ccc95ae4f", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "5c3116945faee33a8a45f911d270c19ad979f3c3f11af2dc769173b6b8f93564", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "852b0fa691ce59a509cf8c414407a8ea1bed362cf52007ceaa0d240533a3b6d1", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "66081135debd54f351c3117428aae95ca160895effd7c8c5d3c9eacdcc18dafd", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "80bd080495367c9cad59a356e410aa200aee03690ad38d817ff9020e2c46b7eb", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "42b513b8d24d66f582c4cab8d61414012c34a25d7f65679985ab68e2cdfc0fed", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "18c5bdfc09da2789c79d4b7ec8e0703699acbd2528efc13a249043517e415031", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "f12be56fd501f1305be77f31e7021c79749e60286d27f68c4c6fbaf9326b6b18", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "f9445ebb056c31cce13267e7ca1416aa01c482e6d0968044c1c90193a4ab7ecf", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "46724764c0c9ef57ca9e74ebcfefbfc4053d0aec9827219e3a8f70d7661d4f00", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "9ec841afae859c5d2f386a0ba333cb7f1055718645de6a46cc429e1ab6388a8d", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "224c80a3babc99ed5ab0f2c2376a730606a49adf99b26ac1039b98e96972bb49", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "a6011d4c075ac5f7c8fb64dca3388e659c18fb95b104ff5ba661e614015607e4", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "ca11ca60fc78827a87e202060f6892b2513c4e7ee7af637c9f5ffc73512258b5", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "a2df3333acdda56303a8607151538d4e3f0ccbb5e7ad0ce538c2daa16927a2aa", - "dist/2022-02-22/rustc-beta-aarch64-apple-darwin.tar.gz": "14e52bfeaaa4e1040c9ac2a1ef5ce55c6f862187d789ff07bfc10397d5302b2d", - "dist/2022-02-22/rustc-beta-aarch64-apple-darwin.tar.xz": "43e8d608a04b8c1037e3d6fae9c90aad0317b109176a9016b8327bca34346e4d", - "dist/2022-02-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "507d7533e80f022031e27698664bedd4c0e02334b008fa1276e0b4094c616a11", - "dist/2022-02-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "798d75848e5fe551d70feeaab10cd77709e218c34d65fefc8392667942e5da93", - "dist/2022-02-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "ce50f8abc2070654681d073db6d36ca0e36806a9af0e23d7273771713756b3c9", - "dist/2022-02-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "4654ae2341a8a62d7bc2facf85bcba483f3bb083d51e7127c8b3c18a63a31180", - "dist/2022-02-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "e66559d3acd1fd17c0fed9f106e51865e5de85438ff2eb2add4032a29ee4947b", - "dist/2022-02-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "648ca772d54e95a6066115dedc6b04b9874875bb0950f1cabef99d91c16083d2", - "dist/2022-02-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "737c865a96af5ea78492bccb1341025b25dcd6449229cbf085524296bcd232d9", - "dist/2022-02-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "484ecf1f2f940e4d46596dbf6697ff6d94edd90739769f63985415a360e65703", - "dist/2022-02-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "503e5827abbe658d4caa91432506121e3f3ed5d3d1896a7fe1f6b4dd38c5ba1a", - "dist/2022-02-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "c0001b8f07436a1765569b857b7f1c0ed81dfb87de8ada1e534c2cde1ce866e8", - "dist/2022-02-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "e39e0f013d02d2a340c62abfa58b37095fb0df828e5678c94f6611e3b03e3670", - "dist/2022-02-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "9aa60dba618f60f3099c0b2b14ca55a15187fc6858c45bde482bc40d324acefa", - "dist/2022-02-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "4ee632be637fea478c42f2c77a24f8146b6b982bb0c9c9a19d5e83a6cf0d49ca", - "dist/2022-02-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "ba4d659c22647102ed0ce4fa1b7121df788479838b6de08058a7ccd14923293c", - "dist/2022-02-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "9d37026d3efcd15c18eae8a35d5c91089b0094ca3fa2a09c07a9022a246ab5bf", - "dist/2022-02-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "2edb8490cc2a02821f1c088f0bb9576e8c6a511654209da940de0aec42210dca", - "dist/2022-02-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "3cd3297af97a6343bdd92457837aaa80f775f2efe64417856a51f6540b703151", - "dist/2022-02-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "c3497504066a953efbcc28840b6b7f1bf2799ec7aaa987d806cd56b874a9304a", - "dist/2022-02-22/rustc-beta-mips-unknown-linux-gnu.tar.gz": "a15c0cc57cee5ba21dcfba2c9e6ebc940e4aab635832d487e5db3adaf9749325", - "dist/2022-02-22/rustc-beta-mips-unknown-linux-gnu.tar.xz": "95d249a9c96253771e197adc86175acde4fa866f84aac84dc299df7bfee4985c", - "dist/2022-02-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "7c0b48e2e3af9807a5b460cc453534f821850522b43ca66e918f42312f634a16", - "dist/2022-02-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "aeb58f5b1dc9c96813f421763fa75b19219cdfa24100faa5ff833f70b56b8087", - "dist/2022-02-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "1ad4c58f78cf006b1243bdb3e4261ffc9d21c6eaa7ac2adad588173fa6bcba73", - "dist/2022-02-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "c119c341da94a30f569fbc1edeaf7d6e0083f6e16ef7aa219d3c499aae351ba5", - "dist/2022-02-22/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "b61616e8eeac33c979ee37f5938dd6ee5c308f58a6c2beb8a1f50c7e3506820f", - "dist/2022-02-22/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "bc5a46ef0c7e761f619e8cffb8dd1818a32551ca14be88649b2e2582f905bdec", - "dist/2022-02-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "6331d582c1130652d939f22eda45ce1b321b577d34affefc0cc0d54050460d28", - "dist/2022-02-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "bc5cb07aef32ef637b25850e443e737725c4cac7f513207d79f9520bd41888d7", - "dist/2022-02-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "a00742e6898e49363ee8478ec4f3d2cbfc778c540233d308b7ce88bdc7bc5dc0", - "dist/2022-02-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "ad3a5f983ce1ff07948c962f885bf7adf182543e8cb04630a3feaafe43b8a56a", - "dist/2022-02-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "4b620d1c6e97436100dd2135ea4e380c5c7f5a480a9dc615601343dfbe30bab6", - "dist/2022-02-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "92ef427c03064dbb5e5f3cdd00fa86a754a6b67961534c37256d8dbe127a097e", - "dist/2022-02-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "4e050159e2a61217dcf3b622f5fab7bc18a1110ab2e87f161879545b7da52fe4", - "dist/2022-02-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "bea23024681fb2bac5f1531969d494a421e48d19148a77b7be797298c6e162d0", - "dist/2022-02-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "efc8e427beffd618501b1c14562c9b1a78958831737eb849507c00ebf0ad6e90", - "dist/2022-02-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "c361166049cfdc1de3a3fa8f11061ea770d76f38623db0ede269366bb7f82d99", - "dist/2022-02-22/rustc-beta-x86_64-apple-darwin.tar.gz": "4c2c12f423036eadae0b328381426e7e43d7cb7a83e4fe06a4c88576e164d010", - "dist/2022-02-22/rustc-beta-x86_64-apple-darwin.tar.xz": "628d767591c8e5ece33de3e23e262fc55d6294513bbb537efbdb4b81f29f40a1", - "dist/2022-02-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "06a2f1e96caf3737c5bfed4bdfb219a4f8b3484339d42651005dbc03eea634ed", - "dist/2022-02-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "1892a79bb57dc0498db1ea467ea70455ec6bf4f55b5d014bd53170be81abb9d0", - "dist/2022-02-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "1d55ec78eb3be79cffe3cd3dbaf300f9fec74f2f0d7559098c7a04002da75788", - "dist/2022-02-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "6bf18b2583840dddebdd2f71b65e6986afb2c5ce03d9641a112afcdb443e3850", - "dist/2022-02-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "047906362381a6ea3c575e508fb80d12c269b104866c9a2b816c0702b67753f0", - "dist/2022-02-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "b186691e919123365da36a4368ed5d1b78b81e46583b9c282a909004998a396c", - "dist/2022-02-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "c8c60d2aa4645a18578eba0a637b4f9ebfabeec0992cf75515013be87fb34a00", - "dist/2022-02-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "a126ae90761c130a1e9afd69b547b2c37486472a6fdc5c21f07f4298a2b92f65", - "dist/2022-02-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "ebea0afac2fab2a014c11ed97d6beb75578cc0ec985e5f8f8bc09b1c01615307", - "dist/2022-02-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "c40d047cda71b01faf5048b8cebc3ac7315da6f8bd47e080183e154c3f4eb651", - "dist/2022-02-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "6f017936f0bcb0b98ff733887383a8ae8902eba9014b6fe674a7aa379d681ade", - "dist/2022-02-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "e89205f8583ea948ed82d7ff576c102bd18dd77bb9234835b3cd7c814951d69f", - "dist/2022-02-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "f6fa66459dc4b58a1b4c19c7b0590293c7ebe2685021ba0ac382b541072965d7", - "dist/2022-02-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "a65546bf3b63618ee16316c1ce552edf24f6d3d2d60dff63515ca61e69ee45a7", - "dist/2022-02-23/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "8f4bc35d8e2b03db96a5d9faedb5e25155082d96621c26b90734219468904c62", - "dist/2022-02-23/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "c83c48eae807ab73ebeb6324778faa1430b7efe0da6e32acb013cad9e2bb505c", - "dist/2022-02-23/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "00b0beac51b53a7469a6b6ef9d99309baa4b9da3e6ef08d9e5a84dcd4697ba2c", - "dist/2022-02-23/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "2d6dc8a6a02327d7d1fa3ab08f5a0a1cfb567a78ef6564a91050028d5f7e1eb0", - "dist/2022-02-23/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "88691ff2cefa6880cb4bbe2d717b5419cd0440ee0d000ff8a70f9d86d714b866", - "dist/2022-02-23/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "c075a7fe36931eff39f1880fce0dbb2d6d691bd4eee6f8db88b49f123e0117d0", - "dist/2022-02-23/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "394ee236b37b687963a0c42e40b3c6863460c302429ad00ca37c7931ea896233", - "dist/2022-02-23/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "74b68d4c1a7d36cca7fd1dab686bd43b04af1be5a9a07f7c42c52b0d5ebe35e4", - "dist/2022-02-23/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "d53edb376291a80362d4b51c8bf889f5cd3221e3e92c8db149f1d869024d4834", - "dist/2022-02-23/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "f26b9f9f97fce1c2de87b9d2168df0e4c3c995572dc6dcb5ac08ebb9185e8e77", - "dist/2022-02-23/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "2771d7d805b9fe3604d47640f969ebab005944f8b77e4d30b2b48adeec62a1f8", - "dist/2022-02-23/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "78f7160f9ad76a3dd6c5ac6021b9fb60ed758cbd90ae34ed2e16f3fd0a646add", - "dist/2022-02-23/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "f46da2d33597142d7b6d344b03cb17c5f6d9345421781b071aa84d52c3c13488", - "dist/2022-02-23/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "f95d077c5a5f713b26330aec15f14430731c53f4d297853d23e8a0158cb7818a", - "dist/2022-02-23/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "fd2db83f3a984d3834b8ecb1450846fd514e4ed1941095fe89d8e4217abd8c81", - "dist/2022-02-23/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "9a031255581634341287da672c7a0d7e893927faefdc9bafee50f5af53633bcc", - "dist/2022-02-23/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "13efc17049a0c032165eb8de8931069548acb2a282248f0a9a29656e8a97a5a8", - "dist/2022-02-23/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "7c684d51fd30c54203220b1505db629b37e2730686d0906d87e2b435093b52e7", - "dist/2022-02-23/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "8d6ca92b75866a8c238a401476f3cbf4314e8cafa098d9bbc45769926b77e534", - "dist/2022-02-23/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "c0609adb3c8cb75dd8e7351243fc6bf8f70701222097964262be0be3d8b6407d", - "dist/2022-02-23/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "66eb9b3684e1f96765001989b6e8eaf03be016b9aa903ebc428f604a468ebf94", - "dist/2022-02-23/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "7300327d6ffc0950943c480e9831e63a23af477816a9f971278e8bbc6c0e3514", - "dist/2022-02-23/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "670c81aed32cbe72b12b5c5b9de8ca65446ae201a3e547a7039bce015884acf8", - "dist/2022-02-23/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "9e86bddbbb0b755a7ad43fb2e20ff4cda4bd2e36d864112c75d69d142509e779", - "dist/2022-02-23/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "53f068e73ed65ad2a3903e7bbf80095d7dbc671e41d80780f52ffd1e1b101804", - "dist/2022-02-23/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "519a29e54063cbee1dca22a17624e1508d1b1a3f1d27cfdac08226c4a7d76092", - "dist/2022-02-23/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "56180120aa97452fff9016b87d8e97d15e35080e65a6dde9892059d20e09cb80", - "dist/2022-02-23/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "20604ae6826adfae2fbd67815a770a46d51f6aea7d5da73a54c66118645e76a3", - "dist/2022-02-23/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "3f0c4fa31ff93aab3b586def6202a9a2b63c7ce2509e707992f941b7bbd43ecb", - "dist/2022-02-23/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "d4eb5cb900b51018d83a0e1f0f50b12bd61f19cb7afc69f614c2fdeff446d323", - "dist/2022-02-23/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "3991a0259b758588ad2166ba5b7b10c79e777941a87f27bcbad4ee7422a240e0", - "dist/2022-02-23/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "2f507613d2cf82288f318bcd70c2d750dd06228699486ba7233ffb08f27baa03", - "dist/2022-02-23/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "811a37b83c293cf05780f62befaeecc69d5e847c407df3f355c27a69fffacd9c", - "dist/2022-02-23/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "99d5577c5766c6ddbba567306ba798ce62fbf92f9a6a227e46cb8c78ba04dda0", - "dist/2022-02-23/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "bac95ae187e4bae372de1ae20fe87eac02a45956bd4dcca71870cf2431b5abb5", - "dist/2022-02-23/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "a2501c6790552f2472891bd3298b0c9038e6dc3e826d060772ed396b2ca45f53", - "dist/2022-02-23/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "1e7a476248c2dc64ac2f65cfa74c0949f170c418674cb692ccf1c1cdccfdabd6", - "dist/2022-02-23/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "85fbac21530f0007da71dc979056f69cf267b2ed870e1d9deb71538a0f46b4c2", - "dist/2022-02-23/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "6e7ba1d83b61ce690c857bc197f3c0a1cf0cb2afd3c4c7f16fdb4079f460ce6f", - "dist/2022-02-23/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "6611703fcd9ec8ba9fa1837be5736c2b2833532cdcc152c5e3429d1994ac624a", - "dist/2022-02-23/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "e1350f9b420888776ab85bf2bc3e762c04a0ca8fe72e82d2d21215d4601f67ee", - "dist/2022-02-23/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "0cd5343e4e2db2f68026a2d55ae5e91cff2402dd1657bc03d9bf131264d9a75f", - "dist/2022-02-23/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "e1a81be6159fb9e28cb1f35ac4508a09a0be86edf6ab39db08988a5bbefa9e76", - "dist/2022-02-23/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "d5073cb4c148ef6e664c1fe17b02900e5f6ee0cf39710cad55887ebd919e797d", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "63a0018ed3b7bf94dca3db30be7a1d6940a7559cdd0ca408c366551e2f5e6863", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "85924719f0bfa06024496e550edfb6556a7b90e42d7d2d810b52f5bcef4401b0", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "ddd2d19ef69ecebb3d654769b06cba5da5c366f01167298ee581f7cd934c637e", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "9178284a64238c7778b521c5a105034efbbb85039b619e3ebb1247b83334bd7d", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "7ab236ced294c39de4bb563e9ebaed04c906a4ccfd1932138d37d6d03f75cae7", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "f392f5b890506e63407204998c3b9b9529dea8a7bdff2319bc202da6fa07c3b9", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "647da2183d93846ac5225b99117846a07a90975bdf1b5075e86601dcf97d1ecf", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "9c3be22743d1d9120d16ae47d035f788ba809207bdddeb8746828ea914dd90e4", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "4c396836a92122b0594568a288fedaca9f5bdd58a7a2013882a1afd17ef69de2", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "0ae2188987be65bfad882878e7a1365310c2cc28504f7ad8400fd759dbc40684" + "dist/2022-04-05/cargo-beta-aarch64-apple-darwin.tar.gz": "d522845ac8c2644378575b25a742fa1e77030a0ef3e45703fa40b3fc96e2fb28", + "dist/2022-04-05/cargo-beta-aarch64-apple-darwin.tar.xz": "9ebed4b378565e9218f4d415d84b36fc78c92ff8f2a0b5360d5199353dbb2402", + "dist/2022-04-05/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "88e973cd6c4fd1307ed614b7480984ef9b0101b06571f6d241082904acfc4b6b", + "dist/2022-04-05/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "dd13d493e02853f7399d886a8a74bfa621c5b2552ae2f50b6000c1dcbb76bd82", + "dist/2022-04-05/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "d1d46f8492b1ebd9c3e1845e14d83d49bd03490c6f11f7be9f046c16d8040602", + "dist/2022-04-05/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "95d521fb4530f9fed33ad82227cf0ab517d6ea160549fda8ebefaf66d44e400d", + "dist/2022-04-05/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "28f126c940bdf7fbbe27b64e7057f13a5fe03364b38c9898df2aaac9f682a60f", + "dist/2022-04-05/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "ad107be697369008d1fade995cc20c044f9ee53713835a3641f91b2b93dd9e2c", + "dist/2022-04-05/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "7fd5000abc9afe72cab7117f64dcdd737003a57302b7289c3113cf1a14d8e454", + "dist/2022-04-05/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "5b7576d67dacc763d4d9be0e3be53aa7a1753cb71cd52d82cde79a142afe3541", + "dist/2022-04-05/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "6ec9fbbc71d5e98535673e1e568cd5440c241ce466e1fc9eddf1cac99af7f86d", + "dist/2022-04-05/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "4e534c1960382f6084a0250060a048254470c1f498bbc28064878c1029232271", + "dist/2022-04-05/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b59bf7b126c91ac4bda9daefa2403bdc25f7240d72e7bd651d1e9f8e53041d61", + "dist/2022-04-05/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "e71597532634725eba7dcd85faf0fcb9bdf2fcf372c0a03e9d507ab1420b5576", + "dist/2022-04-05/cargo-beta-i686-pc-windows-gnu.tar.gz": "38b0ec02eb2acc51c7088542d3642b2c55c0e042f6d8c1ab3de84652c587411f", + "dist/2022-04-05/cargo-beta-i686-pc-windows-gnu.tar.xz": "a194fe60bee39f765e4478107c4a5cc23ccb0d25042b0fa9dd1d5a758e7ae5cf", + "dist/2022-04-05/cargo-beta-i686-pc-windows-msvc.tar.gz": "4467065f716670ef5c305d70b68e5375bf542514fdf6645dc92b43759e76213a", + "dist/2022-04-05/cargo-beta-i686-pc-windows-msvc.tar.xz": "78829f8a16ca9e5c389141b050c7b120115420f966a37888320fdc76886ead1d", + "dist/2022-04-05/cargo-beta-i686-unknown-linux-gnu.tar.gz": "26c423f1667bb0bbede80069be29272877e9ce8f75345f7391f5d1260ec900c1", + "dist/2022-04-05/cargo-beta-i686-unknown-linux-gnu.tar.xz": "b9753f612d59e7d30c3775bcfcaad76df7d0607ad5bdb81041cd40b5690b6239", + "dist/2022-04-05/cargo-beta-mips-unknown-linux-gnu.tar.gz": "5e200db1460c1f0bf43fce499debc9602b09c518f13570f6f6f8c86f83ee0f11", + "dist/2022-04-05/cargo-beta-mips-unknown-linux-gnu.tar.xz": "8c60fa42bf03826c4cd1eea5d96b57e1772381713d780ea3810cbff62ec23041", + "dist/2022-04-05/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "9fcdd60c22211be46e50103a315e0f905d225c61aa42c468760fcd7894dce62d", + "dist/2022-04-05/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "ba188f3ab64897109d2039756c01b43b30008479687a76aa236f50ffc99b9b2d", + "dist/2022-04-05/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "18717f3f965fe3b2182f5791451caa938eb8f0ca5e8c1c6ee0eb32b735c50392", + "dist/2022-04-05/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "ba6d2dc52ce330745d8b543906cd0c81114c2f7e22900f6565d1bede93667d59", + "dist/2022-04-05/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "47e74be39cf947641e37a8f2d41c49b63aba4467b86c89219edee5933b6c92d1", + "dist/2022-04-05/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "dea6a2f11dd8fa9f93f8e1781d3c7faa04d29dded20f4938cbee60b15e523feb", + "dist/2022-04-05/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "f559462b323bf183e8f1f20fb509309e4e88b593f872becd42214f771e860973", + "dist/2022-04-05/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "bd5e9774ddec783e085c9837204de7122eb0469098f93d0768e30ebe3ee165f1", + "dist/2022-04-05/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "78cba227c038364f02c7ed5d01c5e26ac1bf069f7f0a97e54b9911dde8114c3a", + "dist/2022-04-05/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "63514e4afb11b57b58304f246a603ad336b6e95ce6d288cd9d4b834b8e531eab", + "dist/2022-04-05/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "5495f5a77fd354c2d8ed9de86052a1c6528092afdc8af66be532859dddafcd5d", + "dist/2022-04-05/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "4ab4e7674bb927919dc7e4a3a6037978c260ff97966a18409c4b9ae4e1802c4a", + "dist/2022-04-05/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "9baf8bceb40d728eb1ed47ea572d1b890fd36762ad7b119c9de6f7378682fe7b", + "dist/2022-04-05/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "0ef8e9ed9e401a688af6aab9f928ff6b860ddd5449f0becb2216d2206f45ec45", + "dist/2022-04-05/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "d442fb0a4b8f56f7c008d53b15ba2a34d6e08701e0a69b2204e9c64ef32eb4c9", + "dist/2022-04-05/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "5a4d757fbdbd0581e26ce997e33663789630d20620cd3fefc70ab866849c3850", + "dist/2022-04-05/cargo-beta-x86_64-apple-darwin.tar.gz": "03d0ec29bdffbe606e70a96614e44e0e65eaba38ecae4a9aca2e202a8891eb56", + "dist/2022-04-05/cargo-beta-x86_64-apple-darwin.tar.xz": "76149cbf429502b9c1fc71a6bff9d38b24f575bc43caf26143552e2658bde544", + "dist/2022-04-05/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "ef7bbf4aaf758aa8c3ef74e68f8a39a6b1b2bad0ecfc90a0a49ceee41f5aef80", + "dist/2022-04-05/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "23d15d39aacfbb1cc382cf2e88d9d688827c867e1b4778ab24d66579e766bd22", + "dist/2022-04-05/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "20b0427583732b542b1274837d61b4f25a72c3810433d91bd31013daebfca54d", + "dist/2022-04-05/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "827699b4f5ad3a810d2cbae8fb0c0e3b2724b054d7b7505cebd1af5efbeb592c", + "dist/2022-04-05/cargo-beta-x86_64-unknown-freebsd.tar.gz": "bcbd4379d77d42bdb665a8583daae4bf101b0f3f6588c148c80d72f1c60c5267", + "dist/2022-04-05/cargo-beta-x86_64-unknown-freebsd.tar.xz": "832c90d532ffcba10039f1244bf06c7121ddd3b7fd7c0d913b62fd0ad82e1dce", + "dist/2022-04-05/cargo-beta-x86_64-unknown-illumos.tar.gz": "7af1097744bfaa50b7d019025fc8b940363f9f5665f5247edf8374115ce074cd", + "dist/2022-04-05/cargo-beta-x86_64-unknown-illumos.tar.xz": "f6d2a741b41e26877a3c5f0a8337ebd563370b839c69091acf9535a1c2d6046c", + "dist/2022-04-05/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "477b6914f38919af61ecb2889032ffc2b12fee6ef85967a28bab6baf71df4baf", + "dist/2022-04-05/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "e91b851cd4a2cac68264bb47431943556e6b8c30df74d8a755e655df171acb47", + "dist/2022-04-05/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "3218da520fd9fa9f70f78b1fbf2d69b74842d1cfd3e578eb5b4233b0632d2525", + "dist/2022-04-05/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "5e492a006cef711748772bf3b6e25fdf400316d1392a8391fc005a88d6d8cf0f", + "dist/2022-04-05/cargo-beta-x86_64-unknown-netbsd.tar.gz": "b5164be552ff72bb0f19076c8ae3d0057ef6cf219df032d34130f98abfa07feb", + "dist/2022-04-05/cargo-beta-x86_64-unknown-netbsd.tar.xz": "d641e7e17c4720f961f52353a0a5214683b019a3acf1c1939d9f9710053496cb", + "dist/2022-04-05/rust-std-beta-aarch64-apple-darwin.tar.gz": "d81a9d0e3e6fe59849977a77acb3b3aebbf76465176a03a45cde34982488dc80", + "dist/2022-04-05/rust-std-beta-aarch64-apple-darwin.tar.xz": "001be52129c7e9d08cad4c337eee8515dbe71c17bf06dccbb4b17b6deb59eaed", + "dist/2022-04-05/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "ebf3720b48a89422c473aa40645f8b4e02164b2e57a66e477c320836dfda8589", + "dist/2022-04-05/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "dcaea0924b93a34f8ed5a3043fc752a7fdd74e93747584b4852582601ad4e0c7", + "dist/2022-04-05/rust-std-beta-aarch64-apple-ios.tar.gz": "713438516e54c2451327d15b62ec02439fb1734897e5193dbef4c74a72c3b3d9", + "dist/2022-04-05/rust-std-beta-aarch64-apple-ios.tar.xz": "6ddc798abdeb7b10389fbd1d4870df7c64983a1f2a2aaddebe3ec3a10c7124b9", + "dist/2022-04-05/rust-std-beta-aarch64-fuchsia.tar.gz": "7d74750469755e6171e5ee467eb82f9da6fc659f54eb0713656bcdd0effb1770", + "dist/2022-04-05/rust-std-beta-aarch64-fuchsia.tar.xz": "c1023c97eb2be40c80f83e7fe5b20367cffb3e52515f5e0ecf45201835088d78", + "dist/2022-04-05/rust-std-beta-aarch64-linux-android.tar.gz": "7819b5e29f097b32408fead0fc281ac8fa477cec0141688e0a82233cf37789ab", + "dist/2022-04-05/rust-std-beta-aarch64-linux-android.tar.xz": "51ff2b862d2d6bbc2610041011ed0ef3fae0647d422dbda1613cfc9d900652e9", + "dist/2022-04-05/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "ab90419c8552c7bd7e5381ae6d15788d7b4f8f903395ec2b5b7ef1d561453805", + "dist/2022-04-05/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "6b293b6df7f7b22ddd0dc1dada083176ae60df3624ee29430106c04f0ee4f262", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "104c2f1c3b84024fb03e13da89a0a416d67659a8dc8b582e28c7697fe3f43224", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "35d7787bc6c2d123e6b5e8ccb0ea0070a674050ff3dab80283e4c193b8617f37", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "00fd161285c90a65134a31152dcab92dafd82ca41f94bde84b6beb94dd98e934", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "c3bf923b7025fd3ddb70f79b36ac540f1a3a0d065eefe0e650ce8a3cdadb7a7f", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "05788212f632c0b83c7aa83ceace41efaba1b90066dccdb40e2ba8e5ebc1b405", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "3095a6a9d5ed80cece5ea0dade7bc00790055ac789866c0c51c6e05134f4b26f", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-none.tar.gz": "9cc86be630b5ec83447fb1595a0afecb22a05d9ce89d73af39fb4edc43c37a8c", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-none.tar.xz": "43437ce5b50c45e757957d2d7df354ca6e244b77081d03bde8e519cac2d03fa1", + "dist/2022-04-05/rust-std-beta-arm-linux-androideabi.tar.gz": "1f30c740549ab4ee2641ab08f7339798a69a13edf4ee928462d7fe5c3d49e1c2", + "dist/2022-04-05/rust-std-beta-arm-linux-androideabi.tar.xz": "64032f816c38fb0ea0db6be3c69de702ba6301800cb7c437f547257c3c88ad72", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "54de198103c4a8c2463261e7e4fbbf0104294e5a56e663fc75b4f6606d7e5609", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "50e690bb090230e61a70d34d4191a3a8aedc7e2079ceeb70bc780ae718fa5719", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "56040245d9707a90f62ce33ed45c75110b1f5de50c98b4276d3b0303ca457ca0", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "ea33048f8bd7057b80db565ead072ba3830ac54e9cd9120514d86c0a71398138", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "627ff5136cb18eeaae03303cb265f5492a57f53fb329fe0d362084697d4de4d5", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "d996b8ee3452f5d4dfd758b5ac835dd77ee9f050496d1745fa553901812b843f", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "86303fe3be5da53633630de44f58ee11475624d4ef4bce4f8a91d48f80bc03da", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "14dc9ed9584f7c55967831c97862cfd3cc7ae5e6cbc65936e4ecd0bd9d75fb30", + "dist/2022-04-05/rust-std-beta-armebv7r-none-eabi.tar.gz": "be874fc36bf175eed366db71d0905974153a3339bc84f8abda83c482197a4235", + "dist/2022-04-05/rust-std-beta-armebv7r-none-eabi.tar.xz": "c10c6cf39bf5f5360eddc1a6caedb79ba04ab227336e718b3a45f4a2f3c357c6", + "dist/2022-04-05/rust-std-beta-armebv7r-none-eabihf.tar.gz": "6b429165fe0d52c6dfa74beef81d6b136f7fc35cd60ba2637af64f5195c7a018", + "dist/2022-04-05/rust-std-beta-armebv7r-none-eabihf.tar.xz": "c4913f09cc858f0f2b9870f12714de055e1658b4b708ec78a1cc14428e72912c", + "dist/2022-04-05/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "64ab028aa4d304c7a4a09bcaadb45f094f3c76fd17eb72afb29cc57d127ef743", + "dist/2022-04-05/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "4e2de3902e62ced0910bcc63d425a06e46c003ebc7111d0308637385817582f2", + "dist/2022-04-05/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "8847d73f6da535f4cb700c5da8e9f330710663cd8486bb014c0c67dfe238237e", + "dist/2022-04-05/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "85568b12784c98a331ccf6e2719a6d56261356d87a1142e4a72b9f7438a82380", + "dist/2022-04-05/rust-std-beta-armv7-linux-androideabi.tar.gz": "825fb7e878534ac9e3c05240ba52110bf253602cb39aba8aef31f54695d06cc5", + "dist/2022-04-05/rust-std-beta-armv7-linux-androideabi.tar.xz": "8ec0897de57b4e920a2419aa5af36fe421276306e61e6e0263f056f6769ff0b0", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "6664d7becfe4bcfda1e86eccf3f20cd549d9b7f3d3fc72f70f53da36a91016b8", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "13da845aab759efa0e690731beee1a51d662083aac6bb03451501bd21332397e", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "fe311715bee972d5b5ef669c93fa9d5d39a6ff5309d9f82150c0f3be72222d3b", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "e2937e4c67a6e5af57e79149d8595a24a6114bc877cd13dd568e719dce28162e", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "24209ff3a9431b58f0f7846a8f673c81488429efe6947049ac9c19523d071d83", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "ed1cde412c615ffa422f27cf347b8276c68281528cdd6d2642f290ccfbdf2ba5", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "b028af36212e244ce2eaf213bcc68c52783425a982465d422202fe2d1ad806ab", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "5b4fe3ec165f16cb29d7660b762ad8de84d9c56d9cac90b11d521de3162485d4", + "dist/2022-04-05/rust-std-beta-armv7a-none-eabi.tar.gz": "2cfab91a43151c6680932212732f4bb689dd93a7252e08b291ec56a02ea7642f", + "dist/2022-04-05/rust-std-beta-armv7a-none-eabi.tar.xz": "503cb200deab12a4cbe8f907823d1e3b63bf2729d1a878e7b7a3d495415f4036", + "dist/2022-04-05/rust-std-beta-armv7r-none-eabi.tar.gz": "b4b756f4c8100a377211cc74d5040fd23bb0231b45841fc8929067f8435a3871", + "dist/2022-04-05/rust-std-beta-armv7r-none-eabi.tar.xz": "44de1090cf49659dd983c081af9c675c9d24721e7510c2748f50befd92810c6e", + "dist/2022-04-05/rust-std-beta-armv7r-none-eabihf.tar.gz": "d6bca5dbb5f985b4c3a4b917311e3ceeefc3ba43fd6b4416b1d07136f405e47c", + "dist/2022-04-05/rust-std-beta-armv7r-none-eabihf.tar.xz": "4f9acc7d81e54d6a725d69bbfaaadb10a0bf4481495548513ff0b96fb3b4f85a", + "dist/2022-04-05/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "01b157479a25a19f8ff499d3993521c3d1b7920880b247599279c428146d9de7", + "dist/2022-04-05/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "b1393e5f200af7d3bcebfbcffb95a9edbb66005cf9413283884e520cd0105eaa", + "dist/2022-04-05/rust-std-beta-i586-pc-windows-msvc.tar.gz": "4086ce54630c7444d886900877bcfb3af0a33fa9c5770f42172a6963c20207f4", + "dist/2022-04-05/rust-std-beta-i586-pc-windows-msvc.tar.xz": "ada0ff31c61640d247f709964322001ef187ef96864618d225ce66af76868b85", + "dist/2022-04-05/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "137d56c7afa91f9a53191cf213e5f457604a1ee4d13e9132bf730bb5045eedc8", + "dist/2022-04-05/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "985d7efef52c800a839d8cf7bceeaa1ed44863e83596516507c617619ce744cd", + "dist/2022-04-05/rust-std-beta-i586-unknown-linux-musl.tar.gz": "73d9aab23a0674c9816a987ca24c584a75a934ced077e04787161208c8ccc92c", + "dist/2022-04-05/rust-std-beta-i586-unknown-linux-musl.tar.xz": "6c6e1bdc49286fe1dbad8a597902e8ea73c0562057e43d78fec9024cd31fc255", + "dist/2022-04-05/rust-std-beta-i686-linux-android.tar.gz": "6cebb5c0ab887358d2d948d072d3c436e9f987cf482423d9d55364e9416d492d", + "dist/2022-04-05/rust-std-beta-i686-linux-android.tar.xz": "a04b26ae9b558489dcc7abc5e632c0382ebe248803152407b0ca8702ead246ef", + "dist/2022-04-05/rust-std-beta-i686-pc-windows-gnu.tar.gz": "78dad5e34af6dd72549d04e59bf059bb28ada4bc6a2d2396b07b9d6eddc5b1d0", + "dist/2022-04-05/rust-std-beta-i686-pc-windows-gnu.tar.xz": "03cfd3a7b6ac10338cd6219811cd2b9e67e5e40adcfef6c725e14c571c9c00ef", + "dist/2022-04-05/rust-std-beta-i686-pc-windows-msvc.tar.gz": "61df958b515e51e2e44e2130f19a1e2a41e246af99e2ebe73b08fd2203b38268", + "dist/2022-04-05/rust-std-beta-i686-pc-windows-msvc.tar.xz": "aec3ba484f261d9feb4f81525b56b656dac1ad9af584b946dd85b643ee201202", + "dist/2022-04-05/rust-std-beta-i686-unknown-freebsd.tar.gz": "62669de085e1cdd6bebfc0a6ed74ece54807104c67256c75753e3d2269b450ad", + "dist/2022-04-05/rust-std-beta-i686-unknown-freebsd.tar.xz": "7bb82ba3e26bb4ae4558719d474322012cb09b1fdcab570d1d7dc7c3562023a6", + "dist/2022-04-05/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "22324f33d7be09df91263375535ca93d92372b8dfb320df0ba909f333a900458", + "dist/2022-04-05/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "8911af3a77bf067dd9ef4ee556ab2e13feafee33b0bb1c63b3cc1ae80042a30f", + "dist/2022-04-05/rust-std-beta-i686-unknown-linux-musl.tar.gz": "34b7b615bb5ff1bc7910683ae6f6fa7750119a6e0512df945979969b695a5fd0", + "dist/2022-04-05/rust-std-beta-i686-unknown-linux-musl.tar.xz": "d8614a9116f07ca652e15d7809d79ac50228dbf553ed1d7123a3e9d74a297f1f", + "dist/2022-04-05/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "803aec35491c632565c178100ea8803bb90f841cab99453ee726b846b887f7db", + "dist/2022-04-05/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "a85292e8eeef5a2eee4a16d0188f432602893a6bca6d971daebb1bbaa3d7cf4b", + "dist/2022-04-05/rust-std-beta-mips-unknown-linux-musl.tar.gz": "faaf96182517e399d73b7242ad1ba8798cb49da0bed66fdc31aa04eb916bfcea", + "dist/2022-04-05/rust-std-beta-mips-unknown-linux-musl.tar.xz": "6ceb46cb6495a76960e08f041b5595f954a2ffa41b786b951d58fefa6753dc51", + "dist/2022-04-05/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "0be7806f821b84cf53001964f1985c3a7a5c2df22575ba81e1f925fbf06b6e5f", + "dist/2022-04-05/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "b71f46228685f926bdb6bf675fb6c0b2a32e28a5b095b7375c5fed2c9067b423", + "dist/2022-04-05/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "55662bfa7ae485b1a2d655179588ec2b5936aae4f9998533559330d382f5731e", + "dist/2022-04-05/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "e58994d0a1b3624c36ba0c547ff621ca3ec331ac0bd3d58222919ddab0beb3ce", + "dist/2022-04-05/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "e0c0bb542516fa0159285e3770a469833ac95ec5fc663d39c3e01906f467b094", + "dist/2022-04-05/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "21ef3db32ea221d631c0a81f5034fb63e8bf76f7f39c1957c5d16929bd64bf17", + "dist/2022-04-05/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "ad3da919ca0fcbffdb84ea8f415bed2a2fb2f61e816aaaf28e8854a9850103f6", + "dist/2022-04-05/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "cb02f50e74534bbd805094b1e83c35d0a2e00dcbd75dd85f3517774f42e8fe1c", + "dist/2022-04-05/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "64350c36afa85b35b02dc1255fcc09abf2592e08a05aa0ea67794ef13442dcd8", + "dist/2022-04-05/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "894e0337a31935a13d26d2710a70b4526e1caa26aa0c9cd37981d2569b8ada31", + "dist/2022-04-05/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "cd5e15813a24234812e4a281fccb76f6aa2110c87a0043d4b5c60fdf3b272701", + "dist/2022-04-05/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "dea915cd8f79c3d78b063bebd86a9c6e88749f6a436ac16c6dee463bc9504f0a", + "dist/2022-04-05/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "af860ff78396796a125c9d3029f85e898ac0c0fb738956d5a9fb9432efd61770", + "dist/2022-04-05/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "a6470fa586262bf78b91bb4b59e6f15c6df9028f4b3aace8589ddeb12dbf7ea6", + "dist/2022-04-05/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "9b147bfd00a0f2cd7aeefb67b03cb08b7d2eb2661410dbc3afee30dcb1c7931c", + "dist/2022-04-05/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "4791c88990892a0aa3e41bd5e0d3c70a3e08714e0d46c00e58a14944f4be3d6a", + "dist/2022-04-05/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "d5ddb7a2ada5c0f10a1cfaa18ed9f454ba044bcc20070be35e104e33eca2a954", + "dist/2022-04-05/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "8eaa648476c02b86662d0eb20255d63f49295853733082aa7200e1d22565aa5c", + "dist/2022-04-05/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "fecc0c637feeaf867ed63d198169948373dd6b00cecb7c5deb00e2719a70f403", + "dist/2022-04-05/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "77932b3620e2a9642b91e7526f0c08f6fc7d96eb1506aae9382b9ceba5098ab8", + "dist/2022-04-05/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "37b5042d8d1dfc8f0edbd02766b0e47dd90f68a7465cc3f8a2ffb09ef605b11d", + "dist/2022-04-05/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "73b317b51e033076205f7c7c7c28877fa61e837cadfc97bd1899211c22ab1160", + "dist/2022-04-05/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "8f82803e3fd1304c8fc03d49cf9e41e8f7b605f84c94739706e0c7606c448e6e", + "dist/2022-04-05/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "1e6b7f7d5732446bfe865ee16183efc30fedfdb9dae45131c8cb59bf683348bf", + "dist/2022-04-05/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "beef2e14c29146435c9a3bdfad2a98298294b916672a73131202c72cc697df6c", + "dist/2022-04-05/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "f9aab3ca9bb4072a5e2e4682ab23fb5b4a071da7cc8b8e3844a4407e8e33fe6b", + "dist/2022-04-05/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "eda983cd1775f24b96b660ef3536f06df30385c40bfec46d8cfb8d35c27763d9", + "dist/2022-04-05/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "3168538fc3a537c15c0c994f3ccd46548b14727b46f95f8244e9068e68bb64e5", + "dist/2022-04-05/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "6e8681fc5c2b6258b669780438f3d10544a9236f288ae6a173bdd293ab710544", + "dist/2022-04-05/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "5abe0a935eaca18193ede75b59780b33c98dcfef2d38e96ea3dda10c30d192f6", + "dist/2022-04-05/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "94c55ad771f08611bebbb9395357cbd6001e0c3fe575c9dde2ad683015743cdf", + "dist/2022-04-05/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "77fc488d1ac4e4c6418980ec33a82aa0fd1f8c4a58cf14b681037d170bcd597f", + "dist/2022-04-05/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "5f909d74e47c38cdcdbfe784e78e2aafdfbca5d5cd385c8d0b466628030e5433", + "dist/2022-04-05/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "cb11de42adff210b131519581a11287ec67740bab4478f16bc1cfd56f7dcfc9f", + "dist/2022-04-05/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "68dc6686aa0b27e569d50c5ca0d607d4efe4c9d8990ba87ad8a2aa328dec8616", + "dist/2022-04-05/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "b2bf5ba8a83a15dfcc41598f794e3d3c83dbf915215b4f919e07a9047b1ffdb9", + "dist/2022-04-05/rust-std-beta-sparcv9-sun-solaris.tar.gz": "86a21737572edd36cb91e45941923c672252630d195f58fb94d7d8d49b8617c9", + "dist/2022-04-05/rust-std-beta-sparcv9-sun-solaris.tar.xz": "7aec356bec19a94d15b117e774cb42a8eb3564308ca02f60d79b65f43bd36af6", + "dist/2022-04-05/rust-std-beta-thumbv6m-none-eabi.tar.gz": "d755a31f9facef7dbc1476fb803f1bb912a4eabf70facbceaa2c23b5d38a482b", + "dist/2022-04-05/rust-std-beta-thumbv6m-none-eabi.tar.xz": "d62dadcb8bbfc1018937daaaacb28118e63fd7fc539ef62e88cf6e1efe7be0b8", + "dist/2022-04-05/rust-std-beta-thumbv7em-none-eabi.tar.gz": "df0f49f983f0c9d110bdf170643f08d0206e7979cc654bdddd70eac717334efc", + "dist/2022-04-05/rust-std-beta-thumbv7em-none-eabi.tar.xz": "6fe836a2ea7df03c1a88d823cb0557af888b0020c2389bf5027735c9dbccbcd0", + "dist/2022-04-05/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "facb752255f0f86ef7a03d8013cf77221263423658d0dce9b75b94e518947de3", + "dist/2022-04-05/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "8d63d9acd7af3e43bafdbef1953c111f4c13088af4c962802f12b38ae38073b8", + "dist/2022-04-05/rust-std-beta-thumbv7m-none-eabi.tar.gz": "e5e1eb0bd5fc3a5af561dd9bcf0839c53e36672a11c4dec55ade5a2f59804508", + "dist/2022-04-05/rust-std-beta-thumbv7m-none-eabi.tar.xz": "3ee0776ff315bcc48d62ace2aa8f8e520fee1a5c27a75abdb89a5093cbd70212", + "dist/2022-04-05/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "83150b0bd0827db25739e21afdc28a571cab9cf528eb7bde39d6457ab26fd28b", + "dist/2022-04-05/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "1d24ee3b0e3b34f88c54e76bff867a77a35ce74c055311d82f3bde23cae0988b", + "dist/2022-04-05/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "87411b8d0954c450b83dc1b805c94af4cc7907ccfc346e129e5d6909e716cebc", + "dist/2022-04-05/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "de9ab4a162f426eba6eb5a355ca0d2d12ba1286599cdc1adc8f4a779e507052e", + "dist/2022-04-05/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "24ca6e156c3eda6c8c790eb5d7c99e39c4394deb9224b495c90641bc828639b4", + "dist/2022-04-05/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "00bc42ff2b31965cce526f46ed43301966da1b57b694e4c4e5089928ecd13f31", + "dist/2022-04-05/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "3ea54fc5075d6f99db9e2d31a92fd000108500017d80cae6e6349e2ea43a7708", + "dist/2022-04-05/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "8809512122417753d6e72b2ae90637e8b339a3f72a51bd4ad53b3a152a992b16", + "dist/2022-04-05/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "bcff8f5e765b8bbfdc3a5c6cb08cb796c90f3435986587b0744d40c226e8f551", + "dist/2022-04-05/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "925605849a16cc8e9a0d5ae5b523a321fd7e80ebb8fced627d7ac90845e20261", + "dist/2022-04-05/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "64ef3fc95b97e5dc6a4e70bf383ffaab836a227f86427c8eadb01c1ed1d85a08", + "dist/2022-04-05/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "377aa739f9c9aec814031b260def0629b87d932f06bedbc6cff9c997911c7263", + "dist/2022-04-05/rust-std-beta-wasm32-unknown-unknown.tar.gz": "2f8d832b5cbcf8072e5ebccd5d569b351a3265aab0ac60f580fe326def9f40a4", + "dist/2022-04-05/rust-std-beta-wasm32-unknown-unknown.tar.xz": "4b6582d922280377297412496e443becae006a0c7b170dec0b75885322615876", + "dist/2022-04-05/rust-std-beta-wasm32-wasi.tar.gz": "31487c5f709ac9bb89bc20215cb806b5c83cc604f6fbf858939c7f1be9759a3c", + "dist/2022-04-05/rust-std-beta-wasm32-wasi.tar.xz": "712f2663bfcc2e67a797390a872e2d440f24474c92644818667b2bf741f938e6", + "dist/2022-04-05/rust-std-beta-x86_64-apple-darwin.tar.gz": "120f9ce8080d7fb25d50f0a055e708a14570c6ec98543008580c72d0037fb1db", + "dist/2022-04-05/rust-std-beta-x86_64-apple-darwin.tar.xz": "969c54f4aa028ad51087a41b556d6692b02ae240b805cc0a6d52cf0f4a5ae2b9", + "dist/2022-04-05/rust-std-beta-x86_64-apple-ios.tar.gz": "6a6b2485d5e012e53345a777b112c94563e0c8ce28845a8c68aa04b09196b59e", + "dist/2022-04-05/rust-std-beta-x86_64-apple-ios.tar.xz": "58a8643415ba08bda6cff638012de2b2d3d3d8c953808006dda74f65efae8210", + "dist/2022-04-05/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "c757c0e207d77edac9305714e056984affe6e97d6fb59a7b70dfe62de39458a1", + "dist/2022-04-05/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "561bb7ddb8eb5cdf33e4608f772c2a021504d0a9eb73536c66b30095545da05d", + "dist/2022-04-05/rust-std-beta-x86_64-fuchsia.tar.gz": "d8fa9b75e173766ecafe150aa8162860dcf93f2340a5dad5fa2529619a5ae05a", + "dist/2022-04-05/rust-std-beta-x86_64-fuchsia.tar.xz": "182c4809af23b0a0f6a0d3ef5f9f7f4cbd846ecc62d459f5aef840871f9fe7d5", + "dist/2022-04-05/rust-std-beta-x86_64-linux-android.tar.gz": "44f09c699a1543581bfcbea834b654dbd165826d80476d6bf4fa3cbf4e90dff9", + "dist/2022-04-05/rust-std-beta-x86_64-linux-android.tar.xz": "6c019c7ecaf340f27b42a87885e4918b736f9a8ef139773092a33bc42d8f27cf", + "dist/2022-04-05/rust-std-beta-x86_64-pc-solaris.tar.gz": "fff1f8b4192be1bd4f701b356094c0a5ce3fc8da4878d29cbf6dfb7476c371f2", + "dist/2022-04-05/rust-std-beta-x86_64-pc-solaris.tar.xz": "b8991973df37f86ccb4c09082caff85f7ddae365d2fa554db6ba26795b263051", + "dist/2022-04-05/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "fdab2938d8f835dc6244b8aae81989de11c46adb413a9feeca11986453dc5f2c", + "dist/2022-04-05/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "4d860de3ff0b5327736d23296365bb65761b4c14dbbc683201286d9fee2fd58e", + "dist/2022-04-05/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "b0e1942912bed10275f65bd525971a7c5fbf03c92bb3a3d2934b35004ca9f109", + "dist/2022-04-05/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "40ba2150b24081cb1a1268c196fc27a15d771cda3136fbb838d6cfa8535758bd", + "dist/2022-04-05/rust-std-beta-x86_64-sun-solaris.tar.gz": "4d4a43484120e6c0cd46ad66f2c3b9bb46532d8cedb3d899e11aa575638bee2e", + "dist/2022-04-05/rust-std-beta-x86_64-sun-solaris.tar.xz": "546cfcbc48405ea55f702866e7ab2581dcf99abf3d38d97a8736db5ebad72eda", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "dc84510940fd620db639ebfb127e398adbbb13639979cc8855d4a8485363da52", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "d457f1c09dd446e30e94e4bcb1e3b5fde9cc54080cbe5e0a329ee810ab07d312", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-illumos.tar.gz": "1e6b9a255ece3599af1614f47a086422632082ab2e4dd8382f4a23c48865bc84", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-illumos.tar.xz": "7420f5442c1835830c93340ed4cec54c58a104978b54fccb80c4015b9614b9bd", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "b3e69ff8e1725c8a0b61c79be8d2f2d396cda1dd13d2a3d1f87667ca426253ed", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "beaff8b113d35826c062d7c7f76b773e45d0e878e059c42de5411406906368a6", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "bc27fd39c6e67451235aa8f14bd6f4a1018379cf52131ab3924134d6294ea54f", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "4b2ada52b6bd53e786cd5494b6bbbcbc8d7ec6812359b4d1a1a5a25c64e190f6", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "7f1464a804086c7709d5198abde76f6470fd1c36fdebca664e41ebaeeff8b1a0", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "6c570824abd6478c104a55147d6d54e6b785222ea15ffd00c59caee373a78bfe", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "17c6e9204cfdf32fb8db4a7ade73dda300a35c515fc017804593d76590f537d9", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "738f9f96914b20a9e97195d75bc806563fbe4554dc30e02fda58dece420a2790", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-redox.tar.gz": "f0846eed5e5692deb83d01ea36792691232b2449f430c0433375e13efa014142", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-redox.tar.xz": "2ea808655537de27b207fb61b2245048d124cff21edd52ac388838fcbd1d13c1", + "dist/2022-04-05/rustc-beta-aarch64-apple-darwin.tar.gz": "ee587d1e4f90b0662ca8fd845b5b945b5bdeaf09ef51a48c082ccd5ad5582060", + "dist/2022-04-05/rustc-beta-aarch64-apple-darwin.tar.xz": "4d7f7800088d21ec7450a7b7cfe1a00d10ef832919895b7eadd948cc60c2ea51", + "dist/2022-04-05/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "2e96658cea6c5dd9a05490a2a03062e9faa8a19dc359e0751e36834fe0ef8d37", + "dist/2022-04-05/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "401257ac9451f86f2a8306805dffcc77b2d02d2957c2509e7397d640c650a971", + "dist/2022-04-05/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "8ed21a78a71fcad7ef9c37d5da5f6bfc728947b036996ce280f49076526d41a4", + "dist/2022-04-05/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "cf81292f92477f22220feaf07d4c151ef59a6f3fc73770a52ed02064cca3eb65", + "dist/2022-04-05/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "8d64fa488a87a8bb8a7ac4bdf4cd5bf258e5231b98b84361199ff414833ba354", + "dist/2022-04-05/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "4e1ccc5114bbc888a382db706dea497e9a5cfe95de221fc5ddb07942de804964", + "dist/2022-04-05/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "bead69bf19b04a5dfba77da2831e034224cf87d91867c4f14abdd4c0efdf862c", + "dist/2022-04-05/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "cf5f6849862fe528ffa3f7620d04150b3ac034ee985bbd0a45d6139e14b1314e", + "dist/2022-04-05/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "21d2f05ec33cf2c11359e785a74ee2997076f8aa11777e241855266f6d7b68a6", + "dist/2022-04-05/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "299a57e0d25333e1de955a12c69f1cd97da6163ebea681aba4a52601b08d7b26", + "dist/2022-04-05/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "f7460821d2f4289e72f4be807a72c16ac61496bf5732b3c846f6b6e8a43fd669", + "dist/2022-04-05/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "da22ccbaafafd05b18587c1c33ea8c12c083129d4accdfe728c32a9c341d8b12", + "dist/2022-04-05/rustc-beta-i686-pc-windows-gnu.tar.gz": "7be21e73f6d48e0765c102f2dc5b2e3ce57f00e5f9dae6cdcc354b7444acf6bc", + "dist/2022-04-05/rustc-beta-i686-pc-windows-gnu.tar.xz": "b964692919697ec8d5d8d4d4b41579d9fa805ce93c5efb56c3106e5c223f86bd", + "dist/2022-04-05/rustc-beta-i686-pc-windows-msvc.tar.gz": "629942cacf1ab50e5273de51bb786c4258f4efe83748180c27caecbedae6e2c8", + "dist/2022-04-05/rustc-beta-i686-pc-windows-msvc.tar.xz": "7a3b57b8f34c5ea10bee2142edd625b70bd8765761593da9fb0ffb76f30e0e7b", + "dist/2022-04-05/rustc-beta-i686-unknown-linux-gnu.tar.gz": "7cae7e0c0690f302064b768ef7daffe500a7b8767c1ea985d5f9706f41137f5e", + "dist/2022-04-05/rustc-beta-i686-unknown-linux-gnu.tar.xz": "74395a6013a4589b5d39af2d5780c8bf6420256d7159030f248f584bfec018b4", + "dist/2022-04-05/rustc-beta-mips-unknown-linux-gnu.tar.gz": "cfd2fe4c26207346f04d6c4e2e8dee1c9a42fef6663b6eff1029f30c06492efc", + "dist/2022-04-05/rustc-beta-mips-unknown-linux-gnu.tar.xz": "aafea47e80244a136f87640e0b482898362d73a8b4f80ebcf6a539a268713350", + "dist/2022-04-05/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "0d23c8b6e50d1788b46b45c7df4720076829cfe45a926edece8b99223ec02f35", + "dist/2022-04-05/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "89a452f3820732daa166adc30b232261b86019ded316efdb42266b0bbaa09957", + "dist/2022-04-05/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "30ba547c1e6b802b99d01ebbab93e7209a9abc701174079fd8f4651146926545", + "dist/2022-04-05/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "172dcf58d1b68b56ad28dc00571a31457da8e9cd9a02be0a0eb816924ef5617d", + "dist/2022-04-05/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "829459c4f165c80a8009c75860122c93dfbe7984b0ec4517a605973a82f86e42", + "dist/2022-04-05/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "46c50f7d1e84abcd31160de933be9a4557da5e141ee60e84dfb8bff5fc99efd5", + "dist/2022-04-05/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "313bf23cfa02982a59a2fed4301af0abc787969a493e437124a7bde76e73559c", + "dist/2022-04-05/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "c5599b35c68a06c16d7a467b4a7fbf4584b4e4ec2ef6ce8504e6d2cc57ea78c0", + "dist/2022-04-05/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "29d148d3b71f344d63d4fc8ca3809ea11dd4de58afaa0eac11047ee7772f7690", + "dist/2022-04-05/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "c5614d7fe9c4a388d7e5902ee37aaaada479ff3ba0eebb63f5539fd83b5200ae", + "dist/2022-04-05/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "29ce9644866ee2bbcf60668efb389255081b9c905ab1ccb34781c4b4258b5964", + "dist/2022-04-05/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "98eb0d3a369a39ba71b10c140986305c29fe56f79cdb3144e5a6d1eb9cfa6a82", + "dist/2022-04-05/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "0a510b176d2583b52873ca444122e8aff5b17183d87eb984cc3042b70125f685", + "dist/2022-04-05/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "85231536c338281263cf9f4f9fc4c4148f0ad87e436b368a13e45bf75dab382a", + "dist/2022-04-05/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "c998a37c27666f5eab87133df5b2b5f6c636df0375321a2dba149f8375bb2adc", + "dist/2022-04-05/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "50551f01002b91c14bf6e9232555764594e041fb3953b2d4c64ed48e904dc8f2", + "dist/2022-04-05/rustc-beta-x86_64-apple-darwin.tar.gz": "9dc62cef50cc1af0e5b790aefb475ab002a3e6e9abfe449bbd35c33c0e2694b0", + "dist/2022-04-05/rustc-beta-x86_64-apple-darwin.tar.xz": "088b67dcdc7bd2b79b438666fc1013d7fea31d603d50548dceddbdb6149f1c69", + "dist/2022-04-05/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "95ecf36825fd88d6f7b1717248a8dd1863c8e249af69d66594912964c4b9d06a", + "dist/2022-04-05/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "3ea5b4bc1e4e07e45a01df5519bd905c99726a0962e984059ad500243061f3e2", + "dist/2022-04-05/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "31f9226104cc55f67ea01db73a76e631937dee4e8b7e9561cb199cbbb02b33db", + "dist/2022-04-05/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "b054a6eadbfeebf1d8ccdbad8f323e65f32830095aaf512df80e65ec63900480", + "dist/2022-04-05/rustc-beta-x86_64-unknown-freebsd.tar.gz": "17774e9e0678f1825b92fee1e9bed6fe56c8baf76ee43c9608b13985359f2911", + "dist/2022-04-05/rustc-beta-x86_64-unknown-freebsd.tar.xz": "5b461322da60b08554f2557deb69485d3991abf13b75750a307c004d6547a42f", + "dist/2022-04-05/rustc-beta-x86_64-unknown-illumos.tar.gz": "404e9bc04cc7330989d34cb8597814ee576ceee31fccbb932576171cd0dc2fca", + "dist/2022-04-05/rustc-beta-x86_64-unknown-illumos.tar.xz": "5fa0cde302fb7abe148315116f5a499a76971d7bd7353043f1a4361510030a4d", + "dist/2022-04-05/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "a38030a213dc78b5030c03e40f1e6d533518e89fb88eed4632526c9297c7bd45", + "dist/2022-04-05/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "8595bf3845f559a9f7ddf63807ac535739592f4b61a62b028b63dd3db812fd6c", + "dist/2022-04-05/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "c8184f26eed43d4d059f0d39eb58da781ac8cd1546ae26be55d5e4aaf617bfc7", + "dist/2022-04-05/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "2cdf12d740ec570ae6999cb1334b84c24b5a5e4c0a97863b6085423c814caa93", + "dist/2022-04-05/rustc-beta-x86_64-unknown-netbsd.tar.gz": "24bf12c22c765678cf4ea6860b3caaaccfd2762f473db40a6617a377df11b098", + "dist/2022-04-05/rustc-beta-x86_64-unknown-netbsd.tar.xz": "64e3a7fd4027e3c93a147196b9ba1e0a2d43f1263d053c71e179fd2529c66a95", + "dist/2022-04-05/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "63a0c7abc8a755a6946a7f17dcf04ee925f138d1c50d2ccce9ae8af53526d95f", + "dist/2022-04-05/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "a1ecb5efe8f1232336f9f8c0d3b7ed87d6de64ec8ec11f1aca0cc08ed46fef42", + "dist/2022-04-05/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "fdee076495e8314a4b24de97736da154eb5db6dcecfe629153a05dcd903e9b45", + "dist/2022-04-05/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "5d845c73478bc38ab42fb16dd138b82c8a44fab6b0787b5635140eb418516b79", + "dist/2022-04-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "dec1f8535a8edee8aaade80c87dacad690c0a158c4775ee0c9d9e580e1ea47bd", + "dist/2022-04-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "2b91b40a7b2af113210b386991c966758da6defab7e6c5c610574496513ab5ed", + "dist/2022-04-05/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "85da42f4c758c88418f952dfe919b8eeba654ee75c72d87f2d56257fb2248efd", + "dist/2022-04-05/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "0c4aade052166886439598db875872efa8fa5b2aa49e27271f57cec68e6a464a", + "dist/2022-04-05/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "44312f3a088159f78f6cb5e6518aea2727d61681b8a37d71bc414fd1310d1160", + "dist/2022-04-05/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "1cf420d4c8e8af78d5bd5aa95e662182c7a90a24e549cbf23f59e7444b0e45da", + "dist/2022-04-05/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "019fa75361e72cfd813c4ba9be8d48774a4a0cff1870b0e343278527dc62dedb", + "dist/2022-04-05/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "1be1e449ef8c299ef269baeba36c612746afdb16d59d9af8575ef67d5a4a4a3a", + "dist/2022-04-05/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "8a03f3f1126fe7312c3e86fd0162ae7ce82111f477c00f7884b47e74776e4192", + "dist/2022-04-05/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "05345ba340c9eff4dc2893438a1bdeb047269a54f66cb2fcfd6f05f5a6706b07", + "dist/2022-04-05/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "9e5cc2cae5e40b9a964f4f52c20f9566d1d401b696a3eeeb322f34c907eb1d45", + "dist/2022-04-05/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "db8991874c2f3a1e1ab92c2160cda4c9b1b567fd7b73a610f071e3a59682f585", + "dist/2022-04-05/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "4729ed2d654cc84e4afc4cdbad7a2609783c2e01ff1442aa2b7209cc1793eeeb", + "dist/2022-04-05/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "1c92a4124af30627a44690177dfb9a47aae9794bb2a6f22dd0171c4d0740ce7d", + "dist/2022-04-05/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "4efb1ceabe3387eb9cb6663718ebef3cdcfc401ebd57557a1f71075c82db5443", + "dist/2022-04-05/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "1485487c0fe779ea52c387a41776418f82649bf11dff56c65eebc9836c447741", + "dist/2022-04-05/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "83af3e32a9e04e89fc0db69c96ee4de144464fc63daa9c15b5339b2b98dc29b3", + "dist/2022-04-05/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "6cd906bfac78de1ec92a53ddee54fbaa437280c413411aae678fd87db9df11c6", + "dist/2022-04-05/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "00bd1e70d9cf308fe4b48cae7188272068d8f98e782e40c74d6e1af20dad3984", + "dist/2022-04-05/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "51b3192cfa8a9ad4e6981a6fc7a57fd50059d3182e67425a1c036db37b67c1c7", + "dist/2022-04-05/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "b81e01d392d4d498be39b99ba4cbf24324248647d15eb470526421954596f2bf", + "dist/2022-04-05/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "e8c6a23e762c4f81030e8c7449e0d49fb60c058893e4ca2110012db8d4a9be43", + "dist/2022-04-05/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "64e38687c204feb1dcfd19aec7af93cea724548d5c1e74b38a69a29017c6d721", + "dist/2022-04-05/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "0bc3ac22801cdd0fd6e71d172f61cc3249c6e61b6333e748eb47624d4ef60748", + "dist/2022-04-05/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "9d03b1724dbacf126f626abc9c71c4461f75f6b1c71c5132c1ab1b4ae39363ee", + "dist/2022-04-05/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "3fda672627eaa0f69d7492f55cae4d769bd421c671a74960d77bfd5021dc71c7", + "dist/2022-04-05/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "265c0238b9878c454d65c361968d63b6d55b69f82adbf27fc626d333d093c212", + "dist/2022-04-05/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "c50dc03c50d8e0222c959867f621772e7cac5df72d4487f6f6082898ed1fd1b0", + "dist/2022-04-05/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "3b28fb9c8b8050fc3a06a4591bd90c7c2a42859aa61177572f60f1fed0bbd46a", + "dist/2022-04-05/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "2153976482c3bb6babf8602d7751a4bfa99ee96397d42efb91c38652e652bde9", + "dist/2022-04-05/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "7c2fdd326f5ebfcb7ad3c732954c2ca34191d40422eb7b318331219d282f34b7", + "dist/2022-04-05/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "38fe0ede661a71ca4010359c9e6d8c4656c2da4e13dbc9c7cd0b98481406bcd4", + "dist/2022-04-05/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "4b682444c300d130087d77ab595fe829d1cfd4d08bc22aeda4042ad818b0402d", + "dist/2022-04-05/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "c9d39631dae71e15702b194b7f4dd3dced040fa731dd2f8aeb892368f3637cbc", + "dist/2022-04-05/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "ee7c5a878da4b33761eb2991792833da41673d5bd5916ad8aefec83350e9cf3d", + "dist/2022-04-05/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "54147e40db10a73e22d6aa20b40d5cd64c79b0b1afa57758cbd6809bd7ba62a0", + "dist/2022-04-05/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "e019b5a55a66755794f03eeadd927cfc839a2745c5865c5a53230bd5a961a296", + "dist/2022-04-05/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "a7c0a92a4e34e2bb3d58166525bf10a400b643a0791b352b29ff25d8eee9a842", + "dist/2022-04-05/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "4a9f16df3b8bbd38d43a1a585c29ba5b95dd7d60e4ee6df3063fdd36d1b64acb", + "dist/2022-04-05/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "4af11a257914be44e8aff5e6d0e586282b12b52f326ecc95d2c58a921154606c", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "06cb18eb062ac90f1d77f2b0f09d0220a265790e0b80c3549360eef72af14dee", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "37b671df4350aa5320174965eac84e05063a35dc0549f1aec035724fff143f0d", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "4949b3846cb5dfd7e52abd081631397d7614c16782b8f4eec90aefdac927dfad", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "35a92e775b602d21d23bae702c5ac0de2c9eeba1da6e009084a95b448af8a689", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "f595603b8c255486801e62716133fa8460b63130e94a5c935dd48ec1189b1074", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "dc67ea19eb872659763784b716b8d264e654db5897d2a6766810623605af94b0", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "3e969a8904fe06c1299534d5bb334dea7b9b45321a155d189f2ab6c0781299a2", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "b7a8f67c8da8c148bf1c33df7bffc76c8c3ca430d4e0ab8c4b261a2aaa98dc67", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "7b0e15340585812b597a68c5e6ab778346db3de5d6af7c41fa0cb710e6bf130b", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "9fdb4e1e5afb2c3b110a605383ae2da844e1a5d87285a2475af4bf8d8dde5291" } } diff --git a/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs b/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs new file mode 100644 index 00000000000..b4ce3443ccd --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs @@ -0,0 +1,19 @@ +// Traits in scope are collected for doc links in both outer and inner module attributes. + +// check-pass +// aux-build: assoc-mod-inner-outer-dep.rs + +extern crate assoc_mod_inner_outer_dep; +pub use assoc_mod_inner_outer_dep::*; + +#[derive(Clone)] +pub struct Struct; + +pub mod outer1 { + /// [crate::Struct::clone] + pub mod inner {} +} + +pub mod outer2 { + //! [crate::Struct::clone] +} diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs new file mode 100644 index 00000000000..7a11a165723 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs @@ -0,0 +1,11 @@ +#[derive(Clone)] +pub struct Struct; + +pub mod dep_outer1 { + /// [crate::Struct::clone] + pub mod inner {} +} + +pub mod dep_outer2 { + //! [crate::Struct::clone] +} diff --git a/src/test/rustdoc/rfc-2632-const-trait-impl.rs b/src/test/rustdoc/rfc-2632-const-trait-impl.rs index 2adf69f6514..c5353c4d5b5 100644 --- a/src/test/rustdoc/rfc-2632-const-trait-impl.rs +++ b/src/test/rustdoc/rfc-2632-const-trait-impl.rs @@ -11,50 +11,40 @@ pub struct S<T>(T); // @!has foo/trait.Tr.html '//pre[@class="rust trait"]/code/a[@class="trait"]' '~const' -// @!has - '//pre[@class="rust trait"]/code/a[@class="trait"]' 'Drop' // @has - '//pre[@class="rust trait"]/code/a[@class="trait"]' 'Clone' // @!has - '//pre[@class="rust trait"]/code/span[@class="where"]' '~const' -// @!has - '//pre[@class="rust trait"]/code/span[@class="where"]' 'Drop' // @has - '//pre[@class="rust trait"]/code/span[@class="where"]' ': Clone' pub trait Tr<T> { // @!has - '//div[@id="method.a"]/h4[@class="code-header"]' '~const' - // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Drop' // @has - '//div[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone' // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const' - // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' 'Drop' // @has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone' #[default_method_body_is_const] - fn a<A: ~const Drop + ~const Clone>() where Option<A>: ~const Drop + ~const Clone {} + fn a<A: ~const Clone>() where Option<A>: ~const Clone {} } // @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]' '~const' -// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Drop' // @has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Clone' // @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where"]' '~const' -// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' 'Drop' // @has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' ': Clone' -impl<T: ~const Drop + ~const Clone> const Tr<T> for T where Option<T>: ~const Drop + ~const Clone { - fn a<A: ~const Drop + ~const Clone>() where Option<A>: ~const Drop + ~const Clone {} +impl<T: ~const Clone> const Tr<T> for T where Option<T>: ~const Clone { + fn a<A: ~const Clone>() where Option<A>: ~const Clone {} } // @!has foo/fn.foo.html '//pre[@class="rust fn"]/code/a[@class="trait"]' '~const' -// @!has - '//pre[@class="rust fn"]/code/a[@class="trait"]' 'Drop' // @has - '//pre[@class="rust fn"]/code/a[@class="trait"]' 'Clone' // @!has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' '~const' -// @!has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' 'Drop' // @has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' ': Clone' -pub const fn foo<F: ~const Drop + ~const Clone>() where Option<F>: ~const Drop + ~const Clone { +pub const fn foo<F: ~const Clone>() where Option<F>: ~const Clone { F::a() } impl<T> S<T> { // @!has foo/struct.S.html '//section[@id="method.foo"]/h4[@class="code-header"]' '~const' - // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Drop' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone' // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const' - // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' 'Drop' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone' - pub const fn foo<B: ~const Drop + ~const Clone>() where B: ~const Drop + ~const Clone { + pub const fn foo<B: ~const Clone>() where B: ~const Clone { B::a() } } diff --git a/src/test/rustdoc/stability.rs b/src/test/rustdoc/stability.rs index 4ff06d9c995..90be2050d92 100644 --- a/src/test/rustdoc/stability.rs +++ b/src/test/rustdoc/stability.rs @@ -4,7 +4,7 @@ pub struct Unstable { // @has stability/struct.Unstable.html \ - // '//div[@class="item-info"]//div[@class="stab unstable"]' \ + // '//span[@class="item-info"]//div[@class="stab unstable"]' \ // 'This is a nightly-only experimental API' // @count stability/struct.Unstable.html '//span[@class="stab unstable"]' 0 pub foo: u32, diff --git a/src/test/ui/box/thin_align.rs b/src/test/ui/box/thin_align.rs new file mode 100644 index 00000000000..3c61d0090e4 --- /dev/null +++ b/src/test/ui/box/thin_align.rs @@ -0,0 +1,26 @@ +#![feature(thin_box)] +// run-pass +use std::boxed::ThinBox; +use std::error::Error; +use std::ops::Deref; +use std::fmt; + +fn main() { + let expected = "Foo error!"; + let a: ThinBox<dyn Error> = ThinBox::new_unsize(Foo(expected)); + let a = a.deref(); + let msg = a.to_string(); + assert_eq!(expected, msg); +} + +#[derive(Debug)] +#[repr(align(1024))] +struct Foo(&'static str); + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Error for Foo {} diff --git a/src/test/ui/box/thin_drop.rs b/src/test/ui/box/thin_drop.rs new file mode 100644 index 00000000000..965613c114e --- /dev/null +++ b/src/test/ui/box/thin_drop.rs @@ -0,0 +1,37 @@ +#![feature(thin_box)] +// run-pass +use std::boxed::ThinBox; +use std::error::Error; +use std::ops::Deref; +use std::fmt; + +fn main() { + let expected = "Foo error!"; + let mut dropped = false; + { + let foo = Foo(expected, &mut dropped); + let a: ThinBox<dyn Error> = ThinBox::new_unsize(foo); + let a = a.deref(); + let msg = a.to_string(); + assert_eq!(expected, msg); + } + assert!(dropped); +} + +#[derive(Debug)] +#[repr(align(1024))] +struct Foo<'a>(&'static str, &'a mut bool); + +impl Drop for Foo<'_> { + fn drop(&mut self) { + *self.1 = true; + } +} + +impl fmt::Display for Foo<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Error for Foo<'_> {} diff --git a/src/test/ui/box/thin_new.rs b/src/test/ui/box/thin_new.rs new file mode 100644 index 00000000000..53f46478be4 --- /dev/null +++ b/src/test/ui/box/thin_new.rs @@ -0,0 +1,30 @@ +#![feature(thin_box)] +// run-pass +use std::boxed::ThinBox; +use std::error::Error; +use std::{fmt, mem}; + +fn main() { + let thin_error: ThinBox<dyn Error> = ThinBox::new_unsize(Foo); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_error)); + println!("{:?}", thin_error); + + let thin = ThinBox::new(42i32); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin)); + println!("{:?}", thin); + + let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_slice)); + println!("{:?}", thin_slice); +} + +#[derive(Debug)] +struct Foo; + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "boooo!") + } +} + +impl Error for Foo {} diff --git a/src/test/ui/box/thin_zst.rs b/src/test/ui/box/thin_zst.rs new file mode 100644 index 00000000000..77c400d17bb --- /dev/null +++ b/src/test/ui/box/thin_zst.rs @@ -0,0 +1,34 @@ +#![feature(thin_box)] +// run-pass +use std::boxed::ThinBox; +use std::error::Error; +use std::{fmt, mem}; +use std::ops::DerefMut; + +const EXPECTED: &str = "boooo!"; + +fn main() { + let thin_error: ThinBox<dyn Error> = ThinBox::new_unsize(Foo); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_error)); + let msg = thin_error.to_string(); + assert_eq!(EXPECTED, msg); + + let mut thin_concrete_error: ThinBox<Foo> = ThinBox::new(Foo); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_concrete_error)); + let msg = thin_concrete_error.to_string(); + assert_eq!(EXPECTED, msg); + let inner = thin_concrete_error.deref_mut(); + let msg = inner.to_string(); + assert_eq!(EXPECTED, msg); +} + +#[derive(Debug)] +struct Foo; + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", EXPECTED) + } +} + +impl Error for Foo {} diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr index a4b10a4c339..1b1ce67cb0c 100644 --- a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -13,7 +13,7 @@ LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x BorrowError BorrowMutError Box<T> - and 42 others + and 43 others = note: required for the cast to the object type `dyn std::error::Error` error[E0277]: the trait bound `(): std::error::Error` is not satisfied @@ -31,7 +31,7 @@ LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) BorrowError BorrowMutError Box<T> - and 42 others + and 43 others = note: required for the cast to the object type `(dyn std::error::Error + 'static)` error: aborting due to 2 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-strict_provenance.rs b/src/test/ui/feature-gates/feature-gate-strict_provenance.rs new file mode 100644 index 00000000000..75d0ee5700d --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-strict_provenance.rs @@ -0,0 +1,19 @@ +// check-pass + +#![deny(fuzzy_provenance_casts)] +//~^ WARNING unknown lint: `fuzzy_provenance_casts` +//~| WARNING unknown lint: `fuzzy_provenance_casts` +//~| WARNING unknown lint: `fuzzy_provenance_casts` +#![deny(lossy_provenance_casts)] +//~^ WARNING unknown lint: `lossy_provenance_casts` +//~| WARNING unknown lint: `lossy_provenance_casts` +//~| WARNING unknown lint: `lossy_provenance_casts` + +fn main() { + // no warnings emitted since the lints are not activated + + let _dangling = 16_usize as *const u8; + + let x: u8 = 37; + let _addr: usize = &x as *const u8 as usize; +} diff --git a/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr b/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr new file mode 100644 index 00000000000..34bd240c304 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr @@ -0,0 +1,63 @@ +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_lints)]` on by default + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: 6 warnings emitted + diff --git a/src/test/ui/hrtb/issue-94034.rs b/src/test/ui/hrtb/issue-94034.rs new file mode 100644 index 00000000000..5239e5db11c --- /dev/null +++ b/src/test/ui/hrtb/issue-94034.rs @@ -0,0 +1,96 @@ +// known-bug +// failure-status: 101 +// compile-flags: --edition=2021 --crate-type=lib +// rustc-env:RUST_BACKTRACE=0 + +// normalize-stderr-test "thread 'rustc' panicked.*" -> "thread 'rustc' panicked" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" +// normalize-stderr-test "query stack during panic:\n" -> "" +// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> "" +// normalize-stderr-test "end of query stack\n" -> "" +// normalize-stderr-test "#.*\n" -> "" + +// This should not ICE. + +use std::{ + future::Future, + marker::PhantomData, + pin::Pin, + task::{Context, Poll}, +}; + +mod object { + use super::*; + + pub trait Object<'a> { + type Error; + type Future: Future<Output = Self>; + fn create() -> Self::Future; + } + + impl<'a> Object<'a> for u8 { + type Error = (); + type Future = Pin<Box<dyn Future<Output = Self>>>; + fn create() -> Self::Future { + unimplemented!() + } + } + + impl<'a, E, A: Object<'a, Error = E>> Object<'a> for (A,) { + type Error = (); + type Future = CustomFut<'a, E, A>; + fn create() -> Self::Future { + unimplemented!() + } + } + + pub struct CustomFut<'f, E, A: Object<'f, Error = E>> { + ph: PhantomData<(A::Future,)>, + } + + impl<'f, E, A: Object<'f, Error = E>> Future for CustomFut<'f, E, A> { + type Output = (A,); + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { + unimplemented!() + } + } +} + +mod async_fn { + use super::*; + + pub trait AsyncFn { + type Future: Future<Output = ()>; + fn call(&self) -> Self::Future; + } + + impl<F, Fut> AsyncFn for F + where + F: Fn() -> Fut, + Fut: Future<Output = ()>, + { + type Future = Fut; + fn call(&self) -> Self::Future { + (self)() + } + } +} + +pub async fn test() { + use self::{async_fn::AsyncFn, object::Object}; + + async fn create<T: Object<'static>>() { + T::create().await; + } + + async fn call_async_fn(inner: impl AsyncFn) { + inner.call().await; + } + + call_async_fn(create::<(u8,)>).await; +} diff --git a/src/test/ui/hrtb/issue-94034.stderr b/src/test/ui/hrtb/issue-94034.stderr new file mode 100644 index 00000000000..1d8329142fc --- /dev/null +++ b/src/test/ui/hrtb/issue-94034.stderr @@ -0,0 +1 @@ +thread 'rustc' panicked diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index c03688d03b6..79f6a5850b5 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -48,7 +48,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF); note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL | -LL | G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct, +LL | G: FnOnce<ARG, Output = RET> + ~const Destruct, | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32` @@ -60,7 +60,7 @@ LL | const_eval_select((1,), foo, bar); note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL | -LL | G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct, +LL | G: FnOnce<ARG, Output = RET> + ~const Destruct, | ^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0631]: type mismatch in function arguments diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index a1cfee944c8..98fd13553c0 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -104,6 +104,32 @@ fn main() { "attempted to instantiate uninhabited type `Bar`" ); + test_panic_msg( + || mem::uninitialized::<[Foo; 2]>(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + test_panic_msg( + || mem::zeroed::<[Foo; 2]>(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + test_panic_msg( + || MaybeUninit::<[Foo; 2]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + + test_panic_msg( + || mem::uninitialized::<[Bar; 2]>(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + test_panic_msg( + || mem::zeroed::<[Bar; 2]>(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + test_panic_msg( + || MaybeUninit::<[Bar; 2]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + // Types that do not like zero-initialziation test_panic_msg( || mem::uninitialized::<fn()>(), @@ -199,7 +225,9 @@ fn main() { let _val = mem::zeroed::<OneVariant>(); let _val = mem::zeroed::<Option<&'static i32>>(); let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>(); + let _val = mem::zeroed::<[!; 0]>(); let _val = mem::uninitialized::<MaybeUninit<bool>>(); + let _val = mem::uninitialized::<[!; 0]>(); // These are UB because they have not been officially blessed, but we await the resolution // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.rs b/src/test/ui/lang-items/lang-item-generic-requirements.rs index c0b958f2bf2..fbb56e528c0 100644 --- a/src/test/ui/lang-items/lang-item-generic-requirements.rs +++ b/src/test/ui/lang-items/lang-item-generic-requirements.rs @@ -1,5 +1,5 @@ -// Checks that declaring a lang item with the wrong number -// of generic arguments errors rather than crashing (issue #83893, #87573, part of #9307, #79559). +// Checks that declaring a lang item with the wrong number of generic arguments errors rather than +// crashing (issue #83474, #83893, #87573, part of #9307, #79559). #![feature(lang_items, no_core)] #![no_core] @@ -25,6 +25,10 @@ struct MyPhantomData<T, U>; //~^ ERROR parameter `T` is never used //~| ERROR parameter `U` is never used +#[lang = "owned_box"] +//~^ ERROR `owned_box` language item must be applied to a struct with at least 1 generic argument +struct Foo; + // When the `start` lang item is missing generics very odd things can happen, especially when // it comes to cross-crate monomorphization #[lang = "start"] @@ -48,6 +52,9 @@ fn ice() { // Use phantomdata let _ = MyPhantomData::<(), i32>; + + // Use Foo + let _: () = Foo; } // use `start` diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.stderr b/src/test/ui/lang-items/lang-item-generic-requirements.stderr index df5a77850f1..326f5b0d595 100644 --- a/src/test/ui/lang-items/lang-item-generic-requirements.stderr +++ b/src/test/ui/lang-items/lang-item-generic-requirements.stderr @@ -32,8 +32,17 @@ LL | LL | struct MyPhantomData<T, U>; | ------ this struct has 2 generic arguments +error[E0718]: `owned_box` language item must be applied to a struct with at least 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:28:1 + | +LL | #[lang = "owned_box"] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Foo; + | - this struct has 0 generic arguments + error[E0718]: `start` language item must be applied to a function with 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:30:1 + --> $DIR/lang-item-generic-requirements.rs:34:1 | LL | #[lang = "start"] | ^^^^^^^^^^^^^^^^^ @@ -59,7 +68,7 @@ LL | struct MyPhantomData<T, U>; = help: consider removing `U` or referring to it in a field = help: if you intended `U` to be a const parameter, use `const U: usize` instead -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0392, E0718. For more information about an error, try `rustc --explain E0392`. diff --git a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs new file mode 100644 index 00000000000..d2d72a68f13 --- /dev/null +++ b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs @@ -0,0 +1,7 @@ +#![feature(strict_provenance)] +#![deny(fuzzy_provenance_casts)] + +fn main() { + let dangling = 16_usize as *const u8; + //~^ ERROR strict provenance disallows casting integer `usize` to pointer `*const u8` +} diff --git a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr new file mode 100644 index 00000000000..e50d243b6ad --- /dev/null +++ b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr @@ -0,0 +1,19 @@ +error: strict provenance disallows casting integer `usize` to pointer `*const u8` + --> $DIR/lint-strict-provenance-fuzzy-casts.rs:5:20 + | +LL | let dangling = 16_usize as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-strict-provenance-fuzzy-casts.rs:2:9 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^ + = help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead +help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address + | +LL | let dangling = (...).with_addr(16_usize); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs b/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs new file mode 100644 index 00000000000..3690fbc904d --- /dev/null +++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs @@ -0,0 +1,11 @@ +#![feature(strict_provenance)] +#![deny(lossy_provenance_casts)] + +fn main() { + let x: u8 = 37; + let addr: usize = &x as *const u8 as usize; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + + let addr_32bit = &x as *const u8 as u32; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` +} diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr new file mode 100644 index 00000000000..489cb03ddd3 --- /dev/null +++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr @@ -0,0 +1,23 @@ +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + --> $DIR/lint-strict-provenance-lossy-casts.rs:6:23 + | +LL | let addr: usize = &x as *const u8 as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()` + | +note: the lint level is defined here + --> $DIR/lint-strict-provenance-lossy-casts.rs:2:9 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^ + = help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead + +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` + --> $DIR/lint-strict-provenance-lossy-casts.rs:9:22 + | +LL | let addr_32bit = &x as *const u8 as u32; + | ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32` + | + = help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/match/issue-82866.rs b/src/test/ui/match/issue-82866.rs new file mode 100644 index 00000000000..95cd62261f1 --- /dev/null +++ b/src/test/ui/match/issue-82866.rs @@ -0,0 +1,7 @@ +fn main() { + match x { + //~^ ERROR cannot find value `x` in this scope + Some::<v>(v) => (), + //~^ ERROR cannot find type `v` in this scope + } +} diff --git a/src/test/ui/match/issue-82866.stderr b/src/test/ui/match/issue-82866.stderr new file mode 100644 index 00000000000..f9e3360a525 --- /dev/null +++ b/src/test/ui/match/issue-82866.stderr @@ -0,0 +1,16 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-82866.rs:2:11 + | +LL | match x { + | ^ not found in this scope + +error[E0412]: cannot find type `v` in this scope + --> $DIR/issue-82866.rs:4:16 + | +LL | Some::<v>(v) => (), + | ^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/parser/attr.rs b/src/test/ui/parser/attr.rs index 91a4abbd038..42b2dfde855 100644 --- a/src/test/ui/parser/attr.rs +++ b/src/test/ui/parser/attr.rs @@ -3,5 +3,4 @@ fn main() {} #![lang = "foo"] //~ ERROR an inner attribute is not permitted in this context - //~| ERROR definition of an unknown language item: `foo` fn foo() {} diff --git a/src/test/ui/parser/attr.stderr b/src/test/ui/parser/attr.stderr index 3cec61fe41e..3527274bd0f 100644 --- a/src/test/ui/parser/attr.stderr +++ b/src/test/ui/parser/attr.stderr @@ -3,7 +3,6 @@ error: an inner attribute is not permitted in this context | LL | #![lang = "foo"] | ^^^^^^^^^^^^^^^^ -LL | LL | fn foo() {} | ----------- the inner attribute doesn't annotate this function | @@ -14,12 +13,5 @@ LL - #![lang = "foo"] LL + #[lang = "foo"] | -error[E0522]: definition of an unknown language item: `foo` - --> $DIR/attr.rs:5:1 - | -LL | #![lang = "foo"] - | ^^^^^^^^^^^^^^^^ definition of unknown language item `foo` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0522`. diff --git a/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs b/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs new file mode 100644 index 00000000000..9429e514339 --- /dev/null +++ b/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs @@ -0,0 +1,3 @@ +// include file for issue-94340.rs +#![deny(rust_2018_idioms)] +#![deny(unused_must_use)] diff --git a/src/test/ui/parser/issues/issue-94340.rs b/src/test/ui/parser/issues/issue-94340.rs new file mode 100644 index 00000000000..d0fb84a689a --- /dev/null +++ b/src/test/ui/parser/issues/issue-94340.rs @@ -0,0 +1,8 @@ +// Make sure that unexpected inner attributes are not labeled as outer ones in diagnostics when +// trying to parse an item and that they are subsequently ignored not triggering confusing extra +// diagnostics like "expected item after attributes" which is not true for `include!` which can +// include empty files. + +include!("auxiliary/issue-94340-inc.rs"); + +fn main() {} diff --git a/src/test/ui/parser/issues/issue-94340.stderr b/src/test/ui/parser/issues/issue-94340.stderr new file mode 100644 index 00000000000..9fd7c38a80b --- /dev/null +++ b/src/test/ui/parser/issues/issue-94340.stderr @@ -0,0 +1,20 @@ +error: an inner attribute is not permitted in this context + --> $DIR/auxiliary/issue-94340-inc.rs:2:1 + | +LL | #![deny(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/auxiliary/issue-94340-inc.rs:3:1 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/target-feature/tied-features.rs b/src/test/ui/target-feature/tied-features.rs index 048777cb3ba..15f01505eba 100644 --- a/src/test/ui/target-feature/tied-features.rs +++ b/src/test/ui/target-feature/tied-features.rs @@ -1,7 +1,6 @@ // build-fail // compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu // needs-llvm-components: aarch64 -#![cfg_attr(bootstrap, feature(aarch64_target_feature))] #![feature(no_core, lang_items)] #![no_core] diff --git a/src/test/ui/target-feature/tied-features.stderr b/src/test/ui/target-feature/tied-features.stderr index 6362c7ae60b..525c9084330 100644 --- a/src/test/ui/target-feature/tied-features.stderr +++ b/src/test/ui/target-feature/tied-features.stderr @@ -1,5 +1,5 @@ error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:13:5 + --> $DIR/tied-features.rs:12:5 | LL | #[target_feature(enable = "pacg")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[target_feature(enable = "pacg")] = help: add the missing features in a `target_feature` attribute error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:25:1 + --> $DIR/tied-features.rs:24:1 | LL | #[target_feature(enable = "paca")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_generic.rs b/src/test/ui/type-alias-impl-trait/underconstrained_generic.rs new file mode 100644 index 00000000000..22264670f37 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/underconstrained_generic.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + +trait Trait { + fn foo<T, U>(t: T) -> U; +} + +trait ProofForConversion<X> { + fn convert<T, U>(_: PhantomData<Self>, r: T) -> U; +} + +impl<X: Trait> ProofForConversion<X> for () { + fn convert<T, U>(_: PhantomData<Self>, r: T) -> U { + X::foo(r) + } +} + +type Converter<T> = impl ProofForConversion<T>; +//~^ ERROR the trait bound `T: Trait` is not satisfied + +fn _defining_use<T: Trait>() -> Converter<T> { + () +} + + +fn main() { +} diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr b/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr new file mode 100644 index 00000000000..1c305abcfeb --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/underconstrained_generic.rs:19:21 + | +LL | type Converter<T> = impl ProofForConversion<T>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `ProofForConversion<T>` for `()` + --> $DIR/underconstrained_generic.rs:13:16 + | +LL | impl<X: Trait> ProofForConversion<X> for () { + | ^^^^^^^^^^^^^^^^^^^^^ ^^ +help: consider restricting type parameter `T` + | +LL | type Converter<T: Trait> = impl ProofForConversion<T>; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs new file mode 100644 index 00000000000..c5b2e8a1c5e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.rs @@ -0,0 +1,34 @@ +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + +trait ProofForConversion<'a, 'b> { + fn convert<T: ?Sized>(_: PhantomData<Self>, r: &'a T) -> &'b T; +} + +impl<'a, 'b> ProofForConversion<'a, 'b> for &'b &'a () { + fn convert<T: ?Sized>(_: PhantomData<Self>, r: &'a T) -> &'b T { + r + } +} + +type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; +//~^ ERROR reference has a longer lifetime than the data it references + +// Even _defining_use with an explicit `'a: 'b` compiles fine, too. +fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> { + x +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + Converter::<'a, 'b>::convert(PhantomData, x) +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = extend_lifetime(&x); + } + println!("{}", d); +} diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr new file mode 100644 index 00000000000..12d85a49d01 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/underconstrained_lifetime.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/underconstrained_lifetime.rs:15:26 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined here + --> $DIR/underconstrained_lifetime.rs:15:20 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/underconstrained_lifetime.rs:15:16 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index c682879e323..a1dfbef0601 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -152,6 +152,7 @@ static TARGETS: &[&str] = &[ "x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", + "x86_64-unknown-none", "x86_64-unknown-redox", "x86_64-unknown-hermit", ]; diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 88f71931d92..b4097ea86a5 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,143 @@ document. ## Unreleased / In Rust Nightly -[0eff589...master](https://github.com/rust-lang/rust-clippy/compare/0eff589...master) +[57b3c4b...master](https://github.com/rust-lang/rust-clippy/compare/57b3c4b...master) -## Rust 1.59 (beta) +## Rust 1.60 -Current beta, release 2022-02-24 +Current stable, released 2022-04-07 + +[0eff589...57b3c4b](https://github.com/rust-lang/rust-clippy/compare/0eff589...57b3c4b) + +### New Lints + +* [`single_char_lifetime_names`] + [#8236](https://github.com/rust-lang/rust-clippy/pull/8236) +* [`iter_overeager_cloned`] + [#8203](https://github.com/rust-lang/rust-clippy/pull/8203) +* [`transmute_undefined_repr`] + [#8398](https://github.com/rust-lang/rust-clippy/pull/8398) +* [`default_union_representation`] + [#8289](https://github.com/rust-lang/rust-clippy/pull/8289) +* [`manual_bits`] + [#8213](https://github.com/rust-lang/rust-clippy/pull/8213) +* [`borrow_as_ptr`] + [#8210](https://github.com/rust-lang/rust-clippy/pull/8210) + +### Moves and Deprecations + +* Moved [`disallowed_methods`] and [`disallowed_types`] to `style` (now warn-by-default) + [#8261](https://github.com/rust-lang/rust-clippy/pull/8261) +* Rename `ref_in_deref` to [`needless_borrow`] + [#8217](https://github.com/rust-lang/rust-clippy/pull/8217) +* Moved [`mutex_atomic`] to `nursery` (now allow-by-default) + [#8260](https://github.com/rust-lang/rust-clippy/pull/8260) + +### Enhancements + +* [`ptr_arg`]: Now takes the argument usage into account and lints for mutable references + [#8271](https://github.com/rust-lang/rust-clippy/pull/8271) +* [`unused_io_amount`]: Now supports async read and write traits + [#8179](https://github.com/rust-lang/rust-clippy/pull/8179) +* [`while_let_on_iterator`]: Improved detection to catch more cases + [#8221](https://github.com/rust-lang/rust-clippy/pull/8221) +* [`trait_duplication_in_bounds`]: Now covers trait functions with `Self` bounds + [#8252](https://github.com/rust-lang/rust-clippy/pull/8252) +* [`unwrap_used`]: Now works for `.get(i).unwrap()` and `.get_mut(i).unwrap()` + [#8372](https://github.com/rust-lang/rust-clippy/pull/8372) +* [`map_clone`]: The suggestion takes `msrv` into account + [#8280](https://github.com/rust-lang/rust-clippy/pull/8280) +* [`manual_bits`] and [`borrow_as_ptr`]: Now track the `clippy::msrv` attribute + [#8280](https://github.com/rust-lang/rust-clippy/pull/8280) +* [`disallowed_methods`]: Now works for methods on primitive types + [#8112](https://github.com/rust-lang/rust-clippy/pull/8112) +* [`not_unsafe_ptr_arg_deref`]: Now works for type aliases + [#8273](https://github.com/rust-lang/rust-clippy/pull/8273) +* [`needless_question_mark`]: Now works for async functions + [#8311](https://github.com/rust-lang/rust-clippy/pull/8311) +* [`iter_not_returning_iterator`]: Now handles type projections + [#8228](https://github.com/rust-lang/rust-clippy/pull/8228) +* [`wrong_self_convention`]: Now detects wrong `self` references in more cases + [#8208](https://github.com/rust-lang/rust-clippy/pull/8208) +* [`single_match`]: Now works for `match` statements with tuples + [#8322](https://github.com/rust-lang/rust-clippy/pull/8322) + +### False Positive Fixes + +* [`erasing_op`]: No longer triggers if the output type changes + [#8204](https://github.com/rust-lang/rust-clippy/pull/8204) +* [`if_same_then_else`]: No longer triggers for `if let` statements + [#8297](https://github.com/rust-lang/rust-clippy/pull/8297) +* [`manual_memcpy`]: No longer lints on `VecDeque` + [#8226](https://github.com/rust-lang/rust-clippy/pull/8226) +* [`trait_duplication_in_bounds`]: Now takes path segments into account + [#8315](https://github.com/rust-lang/rust-clippy/pull/8315) +* [`deref_addrof`]: No longer lints when the dereference or borrow occurs in different a context + [#8268](https://github.com/rust-lang/rust-clippy/pull/8268) +* [`type_repetition_in_bounds`]: Now checks for full equality to prevent false positives + [#8224](https://github.com/rust-lang/rust-clippy/pull/8224) +* [`ptr_arg`]: No longer lint for mutable references in traits + [#8369](https://github.com/rust-lang/rust-clippy/pull/8369) +* [`implicit_clone`]: No longer lints for double references + [#8231](https://github.com/rust-lang/rust-clippy/pull/8231) +* [`needless_lifetimes`]: No longer lints lifetimes for explicit `self` types + [#8278](https://github.com/rust-lang/rust-clippy/pull/8278) +* [`op_ref`]: No longer lints in `BinOp` impl if that can cause recursion + [#8298](https://github.com/rust-lang/rust-clippy/pull/8298) +* [`enum_variant_names`]: No longer triggers for empty variant names + [#8329](https://github.com/rust-lang/rust-clippy/pull/8329) +* [`redundant_closure`]: No longer lints for `Arc<T>` or `Rc<T>` + [#8193](https://github.com/rust-lang/rust-clippy/pull/8193) +* [`iter_not_returning_iterator`]: No longer lints on trait implementations but therefore on trait definitions + [#8228](https://github.com/rust-lang/rust-clippy/pull/8228) +* [`single_match`]: No longer lints on exhaustive enum patterns without a wildcard + [#8322](https://github.com/rust-lang/rust-clippy/pull/8322) +* [`manual_swap`]: No longer lints on cases that involve automatic dereferences + [#8220](https://github.com/rust-lang/rust-clippy/pull/8220) +* [`useless_format`]: Now works for implicit named arguments + [#8295](https://github.com/rust-lang/rust-clippy/pull/8295) + +### Suggestion Fixes/Improvements + +* [`needless_borrow`]: Prevent mutable borrows being moved and suggest removing the borrow on method calls + [#8217](https://github.com/rust-lang/rust-clippy/pull/8217) +* [`chars_next_cmp`]: Correctly excapes the suggestion + [#8376](https://github.com/rust-lang/rust-clippy/pull/8376) +* [`explicit_write`]: Add suggestions for `write!`s with format arguments + [#8365](https://github.com/rust-lang/rust-clippy/pull/8365) +* [`manual_memcpy`]: Suggests `copy_from_slice` when applicable + [#8226](https://github.com/rust-lang/rust-clippy/pull/8226) +* [`or_fun_call`]: Improved suggestion display for long arguments + [#8292](https://github.com/rust-lang/rust-clippy/pull/8292) +* [`unnecessary_cast`]: Now correctly includes the sign + [#8350](https://github.com/rust-lang/rust-clippy/pull/8350) +* [`cmp_owned`]: No longer flips the comparison order + [#8299](https://github.com/rust-lang/rust-clippy/pull/8299) +* [`explicit_counter_loop`]: Now correctly suggests `iter()` on references + [#8382](https://github.com/rust-lang/rust-clippy/pull/8382) + +### ICE Fixes + +* [`manual_split_once`] + [#8250](https://github.com/rust-lang/rust-clippy/pull/8250) + +### Documentation Improvements + +* [`map_flatten`]: Add documentation for the `Option` type + [#8354](https://github.com/rust-lang/rust-clippy/pull/8354) +* Document that Clippy's driver might use a different code generation than rustc + [#8037](https://github.com/rust-lang/rust-clippy/pull/8037) +* Clippy's lint list will now automatically focus the search box + [#8343](https://github.com/rust-lang/rust-clippy/pull/8343) + +### Others + +* Clippy now warns if we find multiple Clippy config files exist + [#8326](https://github.com/rust-lang/rust-clippy/pull/8326) + +## Rust 1.59 + +Released 2022-02-24 [e181011...0eff589](https://github.com/rust-lang/rust-clippy/compare/e181011...0eff589) @@ -174,7 +306,7 @@ Current beta, release 2022-02-24 ## Rust 1.58 -Current stable, released 2022-01-13 +Released 2022-01-13 [00e31fa...e181011](https://github.com/rust-lang/rust-clippy/compare/00e31fa...e181011) @@ -3069,6 +3201,7 @@ Released 2018-09-13 [`bytes_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#bytes_nth [`cargo_common_metadata`]: https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata [`case_sensitive_file_extension_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#case_sensitive_file_extension_comparisons +[`cast_abs_to_unsigned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned [`cast_enum_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_constructor [`cast_enum_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_truncation [`cast_lossless`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_lossless @@ -3097,6 +3230,7 @@ Released 2018-09-13 [`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain [`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator +[`crate_in_macro_def`]: https://rust-lang.github.io/rust-clippy/master/index.html#crate_in_macro_def [`create_dir`]: https://rust-lang.github.io/rust-clippy/master/index.html#create_dir [`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute [`dbg_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro @@ -3123,6 +3257,7 @@ Released 2018-09-13 [`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg [`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens [`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy +[`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_non_drop [`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref [`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec @@ -3130,12 +3265,14 @@ Released 2018-09-13 [`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum [`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr [`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop +[`empty_structs_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_structs_with_brackets [`enum_clike_unportable_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_clike_unportable_variant [`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_glob_use [`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names [`eq_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#eq_op [`equatable_if_let`]: https://rust-lang.github.io/rust-clippy/master/index.html#equatable_if_let [`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op +[`err_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#err_expect [`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence [`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision [`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums @@ -3174,6 +3311,7 @@ Released 2018-09-13 [`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map [`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy +[`forget_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_non_drop [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref [`format_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_in_format_args [`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 123af23881b..dd6518d5241 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.61" +version = "0.1.62" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -21,13 +21,12 @@ name = "clippy-driver" path = "src/driver.rs" [dependencies] -clippy_lints = { version = "0.1", path = "clippy_lints" } +clippy_lints = { path = "clippy_lints" } semver = "1.0" -rustc_tools_util = { version = "0.2", path = "rustc_tools_util" } +rustc_tools_util = { path = "rustc_tools_util" } tempfile = { version = "3.2", optional = true } [dev-dependencies] -cargo_metadata = "0.14" compiletest_rs = { version = "0.7.1", features = ["tmp"] } tester = "0.9" regex = "1.5" @@ -45,7 +44,7 @@ derive-new = "0.5" if_chain = "1.0" itertools = "0.10.1" quote = "1.0" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.125", features = ["derive"] } syn = { version = "1.0", features = ["full"] } futures = "0.3" parking_lot = "0.11.2" diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index d133e8cddab..81faa5fe5e1 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -4,15 +4,17 @@ version = "0.0.1" edition = "2021" [dependencies] -bytecount = "0.6" clap = "2.33" indoc = "1.0" itertools = "0.10.1" opener = "0.5" -regex = "1.5" shell-escape = "0.1" +tempfile = "3.2" walkdir = "2.3" -cargo_metadata = "0.14" [features] deny-warnings = [] + +[package.metadata.rust-analyzer] +# This package uses #[feature(rustc_private)] +rustc_private = true diff --git a/src/tools/clippy/clippy_dev/src/bless.rs b/src/tools/clippy/clippy_dev/src/bless.rs index b0fb39e8169..8e5c739afe0 100644 --- a/src/tools/clippy/clippy_dev/src/bless.rs +++ b/src/tools/clippy/clippy_dev/src/bless.rs @@ -1,22 +1,15 @@ //! `bless` updates the reference files in the repo with changed output files //! from the last test run. +use crate::cargo_clippy_path; use std::ffi::OsStr; use std::fs; use std::lazy::SyncLazy; use std::path::{Path, PathBuf}; use walkdir::{DirEntry, WalkDir}; -#[cfg(not(windows))] -static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; -#[cfg(windows)] -static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; - -static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> = SyncLazy::new(|| { - let mut path = std::env::current_exe().unwrap(); - path.set_file_name(CARGO_CLIPPY_EXE); - fs::metadata(path).ok()?.modified().ok() -}); +static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> = + SyncLazy::new(|| cargo_clippy_path().metadata().ok()?.modified().ok()); /// # Panics /// diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index 59fde447547..9c6d754b400 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -1,8 +1,12 @@ +#![feature(let_else)] #![feature(once_cell)] +#![feature(rustc_private)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] +extern crate rustc_lexer; + use std::path::PathBuf; pub mod bless; @@ -13,6 +17,19 @@ pub mod serve; pub mod setup; pub mod update_lints; +#[cfg(not(windows))] +static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; +#[cfg(windows)] +static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; + +/// Returns the path to the `cargo-clippy` binary +#[must_use] +pub fn cargo_clippy_path() -> PathBuf { + let mut path = std::env::current_exe().expect("failed to get current executable name"); + path.set_file_name(CARGO_CLIPPY_EXE); + path +} + /// Returns the path to the Clippy project directory /// /// # Panics diff --git a/src/tools/clippy/clippy_dev/src/lint.rs b/src/tools/clippy/clippy_dev/src/lint.rs index b8287980a4b..1bc1a39542d 100644 --- a/src/tools/clippy/clippy_dev/src/lint.rs +++ b/src/tools/clippy/clippy_dev/src/lint.rs @@ -1,19 +1,52 @@ -use std::process::{self, Command}; +use crate::cargo_clippy_path; +use std::process::{self, Command, ExitStatus}; +use std::{fs, io}; -pub fn run(filename: &str) { - let code = Command::new("cargo") - .args(["run", "--bin", "clippy-driver", "--"]) - .args(["-L", "./target/debug"]) - .args(["-Z", "no-codegen"]) - .args(["--edition", "2021"]) - .arg(filename) - .status() - .expect("failed to run cargo") - .code(); - - if code.is_none() { - eprintln!("Killed by signal"); +fn exit_if_err(status: io::Result<ExitStatus>) { + match status.expect("failed to run command").code() { + Some(0) => {}, + Some(n) => process::exit(n), + None => { + eprintln!("Killed by signal"); + process::exit(1); + }, } +} + +pub fn run(path: &str) { + let is_file = match fs::metadata(path) { + Ok(metadata) => metadata.is_file(), + Err(e) => { + eprintln!("Failed to read {path}: {e:?}"); + process::exit(1); + }, + }; + + if is_file { + exit_if_err( + Command::new("cargo") + .args(["run", "--bin", "clippy-driver", "--"]) + .args(["-L", "./target/debug"]) + .args(["-Z", "no-codegen"]) + .args(["--edition", "2021"]) + .arg(path) + .status(), + ); + } else { + exit_if_err(Command::new("cargo").arg("build").status()); - process::exit(code.unwrap_or(1)); + // Run in a tempdir as changes to clippy do not retrigger linting + let target = tempfile::Builder::new() + .prefix("clippy") + .tempdir() + .expect("failed to create tempdir"); + + let status = Command::new(cargo_clippy_path()) + .current_dir(path) + .env("CARGO_TARGET_DIR", target.as_ref()) + .status(); + + target.close().expect("failed to remove tempdir"); + exit_if_err(status); + } } diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index 30a241c8ba1..b1fe35a0243 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -4,6 +4,7 @@ use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; use clippy_dev::{bless, fmt, lint, new_lint, serve, setup, update_lints}; +use indoc::indoc; fn main() { let matches = get_clap_config(); @@ -56,8 +57,8 @@ fn main() { serve::run(port, lint); }, ("lint", Some(matches)) => { - let filename = matches.value_of("filename").unwrap(); - lint::run(filename); + let path = matches.value_of("path").unwrap(); + lint::run(path); }, _ => {}, } @@ -225,11 +226,20 @@ fn get_clap_config<'a>() -> ArgMatches<'a> { ) .subcommand( SubCommand::with_name("lint") - .about("Manually run clippy on a file") + .about("Manually run clippy on a file or package") + .after_help(indoc! {" + EXAMPLES + Lint a single file: + cargo dev lint tests/ui/attrs.rs + + Lint a package directory: + cargo dev lint tests/ui-cargo/wildcard_dependencies/fail + cargo dev lint ~/my-project + "}) .arg( - Arg::with_name("filename") + Arg::with_name("path") .required(true) - .help("The path to a file to lint"), + .help("The path to a file or package directory to lint"), ), ) .get_matches() diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index 59658b42c79..7a3fd131761 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -133,15 +133,23 @@ fn to_camel_case(name: &str) -> String { } fn get_stabilisation_version() -> String { - let mut command = cargo_metadata::MetadataCommand::new(); - command.no_deps(); - if let Ok(metadata) = command.exec() { - if let Some(pkg) = metadata.packages.iter().find(|pkg| pkg.name == "clippy") { - return format!("{}.{}.0", pkg.version.minor, pkg.version.patch); - } + fn parse_manifest(contents: &str) -> Option<String> { + let version = contents + .lines() + .filter_map(|l| l.split_once('=')) + .find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?; + let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else { + return None; + }; + let (minor, patch) = version.split_once('.')?; + Some(format!( + "{}.{}.0", + minor.parse::<u32>().ok()?, + patch.parse::<u32>().ok()? + )) } - - String::from("<TODO set version(see doc/adding_lints.md)>") + let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`"); + parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`") } fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String { diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index d368ef1f46a..59db51fbfac 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -1,9 +1,9 @@ +use core::fmt::Write; use itertools::Itertools; -use regex::Regex; +use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind}; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; -use std::lazy::SyncLazy; use std::path::Path; use walkdir::WalkDir; @@ -13,35 +13,7 @@ const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev u // Use that command to update this file and do not edit by hand.\n\ // Manual edits will be overwritten.\n\n"; -static DEC_CLIPPY_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| { - Regex::new( - r#"(?x) - declare_clippy_lint!\s*[\{(] - (?:\s+///.*)* - (?:\s*\#\[clippy::version\s*=\s*"[^"]*"\])? - \s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s* - (?P<cat>[a-z_]+)\s*,\s* - "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] -"#, - ) - .unwrap() -}); - -static DEC_DEPRECATED_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| { - Regex::new( - r#"(?x) - declare_deprecated_lint!\s*[{(]\s* - (?:\s+///.*)* - (?:\s*\#\[clippy::version\s*=\s*"[^"]*"\])? - \s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s* - "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] -"#, - ) - .unwrap() -}); -static NL_ESCAPE_RE: SyncLazy<Regex> = SyncLazy::new(|| Regex::new(r#"\\\n\s*"#).unwrap()); - -static DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; +const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; #[derive(Clone, Copy, PartialEq)] pub enum UpdateMode { @@ -60,60 +32,52 @@ pub enum UpdateMode { /// Panics if a file path could not read from or then written to #[allow(clippy::too_many_lines)] pub fn run(update_mode: UpdateMode) { - let lint_list: Vec<Lint> = gather_all().collect(); + let (lints, deprecated_lints) = gather_all(); - let internal_lints = Lint::internal_lints(&lint_list); - let deprecated_lints = Lint::deprecated_lints(&lint_list); - let usable_lints = Lint::usable_lints(&lint_list); + let internal_lints = Lint::internal_lints(&lints); + let usable_lints = Lint::usable_lints(&lints); let mut sorted_usable_lints = usable_lints.clone(); sorted_usable_lints.sort_by_key(|lint| lint.name.clone()); - let usable_lint_count = round_to_fifty(usable_lints.len()); - - let mut file_change = false; - - file_change |= replace_region_in_file( + replace_region_in_file( + update_mode, Path::new("README.md"), - &format!( - r#"\[There are over \d+ lints included in this crate!\]\({}\)"#, - DOCS_LINK - ), - "", - true, - update_mode == UpdateMode::Change, - || { - vec", - usable_lint_count, DOCS_LINK - )] + "[There are over ", + " lints included in this crate!]", + |res| { + write!(res, "{}", round_to_fifty(usable_lints.len())).unwrap(); }, - ) - .changed; + ); - file_change |= replace_region_in_file( + replace_region_in_file( + update_mode, Path::new("CHANGELOG.md"), - "<!-- begin autogenerated links to lint list -->", + "<!-- begin autogenerated links to lint list -->\n", "<!-- end autogenerated links to lint list -->", - false, - update_mode == UpdateMode::Change, - || gen_changelog_lint_list(usable_lints.iter().chain(deprecated_lints.iter())), - ) - .changed; + |res| { + for lint in usable_lints + .iter() + .map(|l| &l.name) + .chain(deprecated_lints.iter().map(|l| &l.name)) + .sorted() + { + writeln!(res, "[`{}`]: {}#{}", lint, DOCS_LINK, lint).unwrap(); + } + }, + ); // This has to be in lib.rs, otherwise rustfmt doesn't work - file_change |= replace_region_in_file( + replace_region_in_file( + update_mode, Path::new("clippy_lints/src/lib.rs"), - "begin lints modules", - "end lints modules", - false, - update_mode == UpdateMode::Change, - || gen_modules_list(usable_lints.iter()), - ) - .changed; - - if file_change && update_mode == UpdateMode::Check { - exit_with_failure(); - } + "// begin lints modules, do not remove this comment, it’s used in `update_lints`\n", + "// end lints modules, do not remove this comment, it’s used in `update_lints`", + |res| { + for lint_mod in usable_lints.iter().map(|l| &l.module).unique().sorted() { + writeln!(res, "mod {};", lint_mod).unwrap(); + } + }, + ); process_file( "clippy_lints/src/lib.register_lints.rs", @@ -123,7 +87,7 @@ pub fn run(update_mode: UpdateMode) { process_file( "clippy_lints/src/lib.deprecated.rs", update_mode, - &gen_deprecated(deprecated_lints.iter()), + &gen_deprecated(&deprecated_lints), ); let all_group_lints = usable_lints.iter().filter(|l| { @@ -146,15 +110,12 @@ pub fn run(update_mode: UpdateMode) { } pub fn print_lints() { - let lint_list: Vec<Lint> = gather_all().collect(); + let (lint_list, _) = gather_all(); let usable_lints = Lint::usable_lints(&lint_list); let usable_lint_count = usable_lints.len(); let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter()); for (lint_group, mut lints) in grouped_by_lint_group { - if lint_group == "Deprecated" { - continue; - } println!("\n## {}", lint_group); lints.sort_by_key(|l| l.name.clone()); @@ -198,19 +159,17 @@ struct Lint { name: String, group: String, desc: String, - deprecation: Option<String>, module: String, } impl Lint { #[must_use] - fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Self { + fn new(name: &str, group: &str, desc: &str, module: &str) -> Self { Self { name: name.to_lowercase(), - group: group.to_string(), - desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(), - deprecation: deprecation.map(ToString::to_string), - module: module.to_string(), + group: group.into(), + desc: remove_line_splices(desc), + module: module.into(), } } @@ -219,7 +178,7 @@ impl Lint { fn usable_lints(lints: &[Self]) -> Vec<Self> { lints .iter() - .filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal")) + .filter(|l| !l.group.starts_with("internal")) .cloned() .collect() } @@ -230,12 +189,6 @@ impl Lint { lints.iter().filter(|l| l.group == "internal").cloned().collect() } - /// Returns all deprecated lints - #[must_use] - fn deprecated_lints(lints: &[Self]) -> Vec<Self> { - lints.iter().filter(|l| l.deprecation.is_some()).cloned().collect() - } - /// Returns the lints in a `HashMap`, grouped by the different lint groups #[must_use] fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>> { @@ -243,6 +196,20 @@ impl Lint { } } +#[derive(Clone, PartialEq, Debug)] +struct DeprecatedLint { + name: String, + reason: String, +} +impl DeprecatedLint { + fn new(name: &str, reason: &str) -> Self { + Self { + name: name.to_lowercase(), + reason: remove_line_splices(reason), + } + } +} + /// Generates the code for registering a group fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator<Item = &'a Lint>) -> String { let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase())).collect(); @@ -262,32 +229,12 @@ fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator<Item = &'a Lin output } -/// Generates the module declarations for `lints` -#[must_use] -fn gen_modules_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> { - lints - .map(|l| &l.module) - .unique() - .map(|module| format!("mod {};", module)) - .sorted() - .collect::<Vec<String>>() -} - -/// Generates the list of lint links at the bottom of the CHANGELOG -#[must_use] -fn gen_changelog_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> { - lints - .sorted_by_key(|l| &l.name) - .map(|l| format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name)) - .collect() -} - /// Generates the `register_removed` code #[must_use] -fn gen_deprecated<'a>(lints: impl Iterator<Item = &'a Lint>) -> String { +fn gen_deprecated(lints: &[DeprecatedLint]) -> String { let mut output = GENERATED_FILE_COMMENT.to_string(); output.push_str("{\n"); - for Lint { name, deprecation, .. } in lints { + for lint in lints { output.push_str(&format!( concat!( " store.register_removed(\n", @@ -295,8 +242,7 @@ fn gen_deprecated<'a>(lints: impl Iterator<Item = &'a Lint>) -> String { " \"{}\",\n", " );\n" ), - name, - deprecation.as_ref().expect("`lints` are deprecated") + lint.name, lint.reason, )); } output.push_str("}\n"); @@ -330,61 +276,136 @@ fn gen_register_lint_list<'a>( output } -/// Gathers all files in `src/clippy_lints` and gathers all lints inside -fn gather_all() -> impl Iterator<Item = Lint> { - lint_files().flat_map(|f| gather_from_file(&f)) -} +/// Gathers all lints defined in `clippy_lints/src` +fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>) { + let mut lints = Vec::with_capacity(1000); + let mut deprecated_lints = Vec::with_capacity(50); + let root_path = clippy_project_root().join("clippy_lints/src"); -fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator<Item = Lint> { - let content = fs::read_to_string(dir_entry.path()).unwrap(); - let path = dir_entry.path(); - let filename = path.file_stem().unwrap(); - let path_buf = path.with_file_name(filename); - let mut rel_path = path_buf - .strip_prefix(clippy_project_root().join("clippy_lints/src")) - .expect("only files in `clippy_lints/src` should be looked at"); - // If the lints are stored in mod.rs, we get the module name from - // the containing directory: - if filename == "mod" { - rel_path = rel_path.parent().unwrap(); - } + for (rel_path, file) in WalkDir::new(&root_path) + .into_iter() + .map(Result::unwrap) + .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) + .map(|f| (f.path().strip_prefix(&root_path).unwrap().to_path_buf(), f)) + { + let path = file.path(); + let contents = + fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e)); + let module = rel_path + .components() + .map(|c| c.as_os_str().to_str().unwrap()) + .collect::<Vec<_>>() + .join("::"); + + // If the lints are stored in mod.rs, we get the module name from + // the containing directory: + let module = if let Some(module) = module.strip_suffix("::mod.rs") { + module + } else { + module.strip_suffix(".rs").unwrap_or(&module) + }; - let module = rel_path - .components() - .map(|c| c.as_os_str().to_str().unwrap()) - .collect::<Vec<_>>() - .join("::"); + if module == "deprecated_lints" { + parse_deprecated_contents(&contents, &mut deprecated_lints); + } else { + parse_contents(&contents, module, &mut lints); + } + } + (lints, deprecated_lints) +} - parse_contents(&content, &module) +macro_rules! match_tokens { + ($iter:ident, $($token:ident $({$($fields:tt)*})? $(($capture:ident))?)*) => { + { + $($(let $capture =)? if let Some((TokenKind::$token $({$($fields)*})?, _x)) = $iter.next() { + _x + } else { + continue; + };)* + #[allow(clippy::unused_unit)] + { ($($($capture,)?)*) } + } + } } -fn parse_contents(content: &str, module: &str) -> impl Iterator<Item = Lint> { - let lints = DEC_CLIPPY_LINT_RE - .captures_iter(content) - .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, module)); - let deprecated = DEC_DEPRECATED_LINT_RE - .captures_iter(content) - .map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), module)); - // Removing the `.collect::<Vec<Lint>>().into_iter()` causes some lifetime issues due to the map - lints.chain(deprecated).collect::<Vec<Lint>>().into_iter() +/// Parse a source file looking for `declare_clippy_lint` macro invocations. +fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) { + let mut offset = 0usize; + let mut iter = tokenize(contents).map(|t| { + let range = offset..offset + t.len; + offset = range.end; + (t.kind, &contents[range]) + }); + + while iter.any(|(kind, s)| kind == TokenKind::Ident && s == "declare_clippy_lint") { + let mut iter = iter + .by_ref() + .filter(|&(kind, _)| !matches!(kind, TokenKind::Whitespace | TokenKind::LineComment { .. })); + // matches `!{` + match_tokens!(iter, Bang OpenBrace); + match iter.next() { + // #[clippy::version = "version"] pub + Some((TokenKind::Pound, _)) => { + match_tokens!(iter, OpenBracket Ident Colon Colon Ident Eq Literal{..} CloseBracket Ident); + }, + // pub + Some((TokenKind::Ident, _)) => (), + _ => continue, + } + let (name, group, desc) = match_tokens!( + iter, + // LINT_NAME + Ident(name) Comma + // group, + Ident(group) Comma + // "description" } + Literal{..}(desc) CloseBrace + ); + lints.push(Lint::new(name, group, desc, module)); + } } -/// Collects all .rs files in the `clippy_lints/src` directory -fn lint_files() -> impl Iterator<Item = walkdir::DirEntry> { - // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories. - // Otherwise we would not collect all the lints, for example in `clippy_lints/src/methods/`. - let path = clippy_project_root().join("clippy_lints/src"); - WalkDir::new(path) - .into_iter() - .filter_map(Result::ok) - .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) +/// Parse a source file looking for `declare_deprecated_lint` macro invocations. +fn parse_deprecated_contents(contents: &str, lints: &mut Vec<DeprecatedLint>) { + let mut offset = 0usize; + let mut iter = tokenize(contents).map(|t| { + let range = offset..offset + t.len; + offset = range.end; + (t.kind, &contents[range]) + }); + while iter.any(|(kind, s)| kind == TokenKind::Ident && s == "declare_deprecated_lint") { + let mut iter = iter + .by_ref() + .filter(|&(kind, _)| !matches!(kind, TokenKind::Whitespace | TokenKind::LineComment { .. })); + let (name, reason) = match_tokens!( + iter, + // !{ + Bang OpenBrace + // #[clippy::version = "version"] + Pound OpenBracket Ident Colon Colon Ident Eq Literal{..} CloseBracket + // pub LINT_NAME, + Ident Ident(name) Comma + // "description" + Literal{kind: LiteralKind::Str{..},..}(reason) + // } + CloseBrace + ); + lints.push(DeprecatedLint::new(name, reason)); + } } -/// Whether a file has had its text changed or not -#[derive(PartialEq, Debug)] -struct FileChange { - changed: bool, - new_lines: String, +/// Removes the line splices and surrounding quotes from a string literal +fn remove_line_splices(s: &str) -> String { + let s = s + .strip_prefix('r') + .unwrap_or(s) + .trim_matches('#') + .strip_prefix('"') + .and_then(|s| s.strip_suffix('"')) + .unwrap_or_else(|| panic!("expected quoted string, found `{}`", s)); + let mut res = String::with_capacity(s.len()); + unescape::unescape_literal(s, unescape::Mode::Str, &mut |range, _| res.push_str(&s[range])); + res } /// Replaces a region in a file delimited by two lines matching regexes. @@ -396,144 +417,49 @@ struct FileChange { /// # Panics /// /// Panics if the path could not read or then written -fn replace_region_in_file<F>( +fn replace_region_in_file( + update_mode: UpdateMode, path: &Path, start: &str, end: &str, - replace_start: bool, - write_back: bool, - replacements: F, -) -> FileChange -where - F: FnOnce() -> Vec<String>, -{ - let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.display(), e)); - let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements); - - if write_back { - if let Err(e) = fs::write(path, file_change.new_lines.as_bytes()) { - panic!("Cannot write to {}: {}", path.display(), e); - } - } - file_change -} - -/// Replaces a region in a text delimited by two lines matching regexes. -/// -/// * `text` is the input text on which you want to perform the replacement -/// * `start` is a `&str` that describes the delimiter line before the region you want to replace. -/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. -/// * `end` is a `&str` that describes the delimiter line until where the replacement should happen. -/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. -/// * If `replace_start` is true, the `start` delimiter line is replaced as well. The `end` -/// delimiter line is never replaced. -/// * `replacements` is a closure that has to return a `Vec<String>` which contains the new text. -/// -/// If you want to perform the replacement on files instead of already parsed text, -/// use `replace_region_in_file`. -/// -/// # Example -/// -/// ```ignore -/// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end"; -/// let result = -/// replace_region_in_text(the_text, "replace_start", "replace_end", false, || { -/// vec!["a different".to_string(), "text".to_string()] -/// }) -/// .new_lines; -/// assert_eq!("replace_start\na different\ntext\nreplace_end", result); -/// ``` -/// -/// # Panics -/// -/// Panics if start or end is not valid regex -fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange -where - F: FnOnce() -> Vec<String>, -{ - let replace_it = replacements(); - let mut in_old_region = false; - let mut found = false; - let mut new_lines = vec![]; - let start = Regex::new(start).unwrap(); - let end = Regex::new(end).unwrap(); - - for line in text.lines() { - if in_old_region { - if end.is_match(line) { - in_old_region = false; - new_lines.extend(replace_it.clone()); - new_lines.push(line.to_string()); - } - } else if start.is_match(line) { - if !replace_start { - new_lines.push(line.to_string()); + write_replacement: impl FnMut(&mut String), +) { + let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e)); + let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) { + Ok(x) => x, + Err(delim) => panic!("Couldn't find `{}` in file `{}`", delim, path.display()), + }; + + match update_mode { + UpdateMode::Check if contents != new_contents => exit_with_failure(), + UpdateMode::Check => (), + UpdateMode::Change => { + if let Err(e) = fs::write(path, new_contents.as_bytes()) { + panic!("Cannot write to `{}`: {}", path.display(), e); } - in_old_region = true; - found = true; - } else { - new_lines.push(line.to_string()); - } - } - - if !found { - // This happens if the provided regex in `clippy_dev/src/main.rs` does not match in the - // given text or file. Most likely this is an error on the programmer's side and the Regex - // is incorrect. - eprintln!("error: regex \n{:?}\ndoesn't match. You may have to update it.", start); - std::process::exit(1); - } - - let mut new_lines = new_lines.join("\n"); - if text.ends_with('\n') { - new_lines.push('\n'); + }, } - let changed = new_lines != text; - FileChange { changed, new_lines } -} - -#[test] -fn test_parse_contents() { - let result: Vec<Lint> = parse_contents( - r#" -declare_clippy_lint! { - #[clippy::version = "Hello Clippy!"] - pub PTR_ARG, - style, - "really long \ - text" } -declare_clippy_lint!{ - #[clippy::version = "Test version"] - pub DOC_MARKDOWN, - pedantic, - "single line" -} - -/// some doc comment -declare_deprecated_lint! { - #[clippy::version = "I'm a version"] - pub SHOULD_ASSERT_EQ, - "`assert!()` will be more flexible with RFC 2011" -} - "#, - "module_name", - ) - .collect(); - - let expected = vec![ - Lint::new("ptr_arg", "style", "really long text", None, "module_name"), - Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"), - Lint::new( - "should_assert_eq", - "Deprecated", - "`assert!()` will be more flexible with RFC 2011", - Some("`assert!()` will be more flexible with RFC 2011"), - "module_name", - ), - ]; - assert_eq!(expected, result); +/// Replaces a region in a text delimited by two strings. Returns the new text if both delimiters +/// were found, or the missing delimiter if not. +fn replace_region_in_text<'a>( + text: &str, + start: &'a str, + end: &'a str, + mut write_replacement: impl FnMut(&mut String), +) -> Result<String, &'a str> { + let (text_start, rest) = text.split_once(start).ok_or(start)?; + let (_, text_end) = rest.split_once(end).ok_or(end)?; + + let mut res = String::with_capacity(text.len() + 4096); + res.push_str(text_start); + res.push_str(start); + write_replacement(&mut res); + res.push_str(end); + res.push_str(text_end); + + Ok(res) } #[cfg(test)] @@ -541,55 +467,65 @@ mod tests { use super::*; #[test] - fn test_replace_region() { - let text = "\nabc\n123\n789\ndef\nghi"; - let expected = FileChange { - changed: true, - new_lines: "\nabc\nhello world\ndef\nghi".to_string(), - }; - let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || { - vec!["hello world".to_string()] - }); - assert_eq!(expected, result); - } + fn test_parse_contents() { + static CONTENTS: &str = r#" + declare_clippy_lint! { + #[clippy::version = "Hello Clippy!"] + pub PTR_ARG, + style, + "really long \ + text" + } - #[test] - fn test_replace_region_with_start() { - let text = "\nabc\n123\n789\ndef\nghi"; - let expected = FileChange { - changed: true, - new_lines: "\nhello world\ndef\nghi".to_string(), - }; - let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || { - vec!["hello world".to_string()] - }); + declare_clippy_lint!{ + #[clippy::version = "Test version"] + pub DOC_MARKDOWN, + pedantic, + "single line" + } + "#; + let mut result = Vec::new(); + parse_contents(CONTENTS, "module_name", &mut result); + + let expected = vec![ + Lint::new("ptr_arg", "style", "\"really long text\"", "module_name"), + Lint::new("doc_markdown", "pedantic", "\"single line\"", "module_name"), + ]; assert_eq!(expected, result); } #[test] - fn test_replace_region_no_changes() { - let text = "123\n456\n789"; - let expected = FileChange { - changed: false, - new_lines: "123\n456\n789".to_string(), - }; - let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, Vec::new); + fn test_parse_deprecated_contents() { + static DEPRECATED_CONTENTS: &str = r#" + /// some doc comment + declare_deprecated_lint! { + #[clippy::version = "I'm a version"] + pub SHOULD_ASSERT_EQ, + "`assert!()` will be more flexible with RFC 2011" + } + "#; + + let mut result = Vec::new(); + parse_deprecated_contents(DEPRECATED_CONTENTS, &mut result); + + let expected = vec![DeprecatedLint::new( + "should_assert_eq", + "\"`assert!()` will be more flexible with RFC 2011\"", + )]; assert_eq!(expected, result); } #[test] fn test_usable_lints() { let lints = vec![ - Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"), - Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "internal", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "Not Deprecated", "\"abc\"", "module_name"), + Lint::new("should_assert_eq2", "internal", "\"abc\"", "module_name"), + Lint::new("should_assert_eq2", "internal_style", "\"abc\"", "module_name"), ]; let expected = vec![Lint::new( "should_assert_eq2", "Not Deprecated", - "abc", - None, + "\"abc\"", "module_name", )]; assert_eq!(expected, Lint::usable_lints(&lints)); @@ -598,55 +534,30 @@ mod tests { #[test] fn test_by_lint_group() { let lints = vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), - Lint::new("incorrect_match", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name"), + Lint::new("should_assert_eq2", "group2", "\"abc\"", "module_name"), + Lint::new("incorrect_match", "group1", "\"abc\"", "module_name"), ]; let mut expected: HashMap<String, Vec<Lint>> = HashMap::new(); expected.insert( "group1".to_string(), vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("incorrect_match", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name"), + Lint::new("incorrect_match", "group1", "\"abc\"", "module_name"), ], ); expected.insert( "group2".to_string(), - vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")], + vec![Lint::new("should_assert_eq2", "group2", "\"abc\"", "module_name")], ); assert_eq!(expected, Lint::by_lint_group(lints.into_iter())); } #[test] - fn test_gen_changelog_lint_list() { - let lints = vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), - ]; - let expected = vec![ - format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK), - format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK), - ]; - assert_eq!(expected, gen_changelog_lint_list(lints.iter())); - } - - #[test] fn test_gen_deprecated() { let lints = vec![ - Lint::new( - "should_assert_eq", - "group1", - "abc", - Some("has been superseded by should_assert_eq2"), - "module_name", - ), - Lint::new( - "another_deprecated", - "group2", - "abc", - Some("will be removed"), - "module_name", - ), + DeprecatedLint::new("should_assert_eq", "\"has been superseded by should_assert_eq2\""), + DeprecatedLint::new("another_deprecated", "\"will be removed\""), ]; let expected = GENERATED_FILE_COMMENT.to_string() @@ -665,32 +576,15 @@ mod tests { .join("\n") + "\n"; - assert_eq!(expected, gen_deprecated(lints.iter())); - } - - #[test] - #[should_panic] - fn test_gen_deprecated_fail() { - let lints = vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")]; - let _deprecated_lints = gen_deprecated(lints.iter()); - } - - #[test] - fn test_gen_modules_list() { - let lints = vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"), - ]; - let expected = vec!["mod another_module;".to_string(), "mod module_name;".to_string()]; - assert_eq!(expected, gen_modules_list(lints.iter())); + assert_eq!(expected, gen_deprecated(&lints)); } #[test] fn test_gen_lint_group_list() { let lints = vec![ - Lint::new("abc", "group1", "abc", None, "module_name"), - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("internal", "internal_style", "abc", None, "module_name"), + Lint::new("abc", "group1", "\"abc\"", "module_name"), + Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name"), + Lint::new("internal", "internal_style", "\"abc\"", "module_name"), ]; let expected = GENERATED_FILE_COMMENT.to_string() + &[ diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 66e61660d31..aebf9a87cab 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.61" +version = "0.1.62" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs new file mode 100644 index 00000000000..e9b0f1f672d --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -0,0 +1,42 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{meets_msrv, msrvs}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; +use rustc_semver::RustcVersion; + +use super::CAST_ABS_TO_UNSIGNED; + +pub(super) fn check( + cx: &LateContext<'_>, + expr: &Expr<'_>, + cast_expr: &Expr<'_>, + cast_from: Ty<'_>, + cast_to: Ty<'_>, + msrv: &Option<RustcVersion>, +) { + if_chain! { + if meets_msrv(msrv.as_ref(), &msrvs::UNSIGNED_ABS); + if cast_from.is_integral(); + if cast_to.is_integral(); + if cast_from.is_signed(); + if !cast_to.is_signed(); + if let ExprKind::MethodCall(method_path, args, _) = cast_expr.kind; + if let method_name = method_path.ident.name.as_str(); + if method_name == "abs"; + then { + span_lint_and_sugg( + cx, + CAST_ABS_TO_UNSIGNED, + expr.span, + &format!("casting the result of `{}::{}()` to {}", cast_from, method_name, cast_to), + "replace with", + format!("{}.unsigned_abs()", Sugg::hir(cx, &args[0], "..")), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs index a4ef1344ab9..d476a1a7646 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::is_hir_ty_cfg_dependant; use clippy_utils::ty::is_c_void; -use if_chain::if_chain; +use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, match_any_def_paths, paths}; use rustc_hir::{Expr, ExprKind, GenericArg}; use rustc_lint::LateContext; use rustc_middle::ty::layout::LayoutOf; @@ -20,45 +19,78 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { ); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); } else if let ExprKind::MethodCall(method_path, [self_arg, ..], _) = &expr.kind { - if_chain! { - if method_path.ident.name == sym!(cast); - if let Some(generic_args) = method_path.args; - if let [GenericArg::Type(cast_to)] = generic_args.args; + if method_path.ident.name == sym!(cast) + && let Some(generic_args) = method_path.args + && let [GenericArg::Type(cast_to)] = generic_args.args // There probably is no obvious reason to do this, just to be consistent with `as` cases. - if !is_hir_ty_cfg_dependant(cx, cast_to); - then { - let (cast_from, cast_to) = - (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr)); - lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); - } + && !is_hir_ty_cfg_dependant(cx, cast_to) + { + let (cast_from, cast_to) = + (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr)); + lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); } } } fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>) { - if_chain! { - if let ty::RawPtr(from_ptr_ty) = &cast_from.kind(); - if let ty::RawPtr(to_ptr_ty) = &cast_to.kind(); - if let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty); - if let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty); - if from_layout.align.abi < to_layout.align.abi; + if let ty::RawPtr(from_ptr_ty) = &cast_from.kind() + && let ty::RawPtr(to_ptr_ty) = &cast_to.kind() + && let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty) + && let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty) + && from_layout.align.abi < to_layout.align.abi // with c_void, we inherently need to trust the user - if !is_c_void(cx, from_ptr_ty.ty); + && !is_c_void(cx, from_ptr_ty.ty) // when casting from a ZST, we don't know enough to properly lint - if !from_layout.is_zst(); - then { - span_lint( - cx, - CAST_PTR_ALIGNMENT, - expr.span, - &format!( - "casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)", - cast_from, - cast_to, - from_layout.align.abi.bytes(), - to_layout.align.abi.bytes(), - ), - ); - } + && !from_layout.is_zst() + && !is_used_as_unaligned(cx, expr) + { + span_lint( + cx, + CAST_PTR_ALIGNMENT, + expr.span, + &format!( + "casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)", + cast_from, + cast_to, + from_layout.align.abi.bytes(), + to_layout.align.abi.bytes(), + ), + ); + } +} + +fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { + let Some(parent) = get_parent_expr(cx, e) else { + return false; + }; + match parent.kind { + ExprKind::MethodCall(name, [self_arg, ..], _) if self_arg.hir_id == e.hir_id => { + if matches!(name.ident.as_str(), "read_unaligned" | "write_unaligned") + && let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id) + && let Some(def_id) = cx.tcx.impl_of_method(def_id) + && cx.tcx.type_of(def_id).is_unsafe_ptr() + { + true + } else { + false + } + }, + ExprKind::Call(func, [arg, ..]) if arg.hir_id == e.hir_id => { + static PATHS: &[&[&str]] = &[ + paths::PTR_READ_UNALIGNED.as_slice(), + paths::PTR_WRITE_UNALIGNED.as_slice(), + paths::PTR_UNALIGNED_VOLATILE_LOAD.as_slice(), + paths::PTR_UNALIGNED_VOLATILE_STORE.as_slice(), + ]; + if let ExprKind::Path(path) = &func.kind + && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id() + && match_any_def_paths(cx, def_id, PATHS).is_some() + { + true + } else { + false + } + }, + _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index be59145afa0..55c1f085657 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -1,3 +1,4 @@ +mod cast_abs_to_unsigned; mod cast_enum_constructor; mod cast_lossless; mod cast_possible_truncation; @@ -473,6 +474,28 @@ declare_clippy_lint! { "casts from an enum tuple constructor to an integer" } +declare_clippy_lint! { + /// ### What it does + /// Checks for uses of the `abs()` method that cast the result to unsigned. + /// + /// ### Why is this bad? + /// The `unsigned_abs()` method avoids panic when called on the MIN value. + /// + /// ### Example + /// ```rust + /// let x: i32 = -42; + /// let y: u32 = x.abs() as u32; + /// ``` + /// Use instead: + /// let x: i32 = -42; + /// let y: u32 = x.unsigned_abs(); + /// ``` + #[clippy::version = "1.61.0"] + pub CAST_ABS_TO_UNSIGNED, + suspicious, + "casting the result of `abs()` to an unsigned integer can panic" +} + pub struct Casts { msrv: Option<RustcVersion>, } @@ -500,7 +523,8 @@ impl_lint_pass!(Casts => [ CHAR_LIT_AS_U8, PTR_AS_PTR, CAST_ENUM_TRUNCATION, - CAST_ENUM_CONSTRUCTOR + CAST_ENUM_CONSTRUCTOR, + CAST_ABS_TO_UNSIGNED ]); impl<'tcx> LateLintPass<'tcx> for Casts { @@ -536,6 +560,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { cast_possible_wrap::check(cx, expr, cast_from, cast_to); cast_precision_loss::check(cx, expr, cast_from, cast_to); cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to); + cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); } cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); cast_enum_constructor::check(cx, expr, cast_expr, cast_from); diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index 470c8c7ea26..af56ec11ef8 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -4,7 +4,8 @@ use clippy_utils::source::snippet_opt; use if_chain::if_chain; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Lit, UnOp}; +use rustc_hir::def::Res; +use rustc_hir::{Expr, ExprKind, Lit, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, InferTy, Ty}; @@ -18,6 +19,17 @@ pub(super) fn check( cast_from: Ty<'_>, cast_to: Ty<'_>, ) -> bool { + // skip non-primitive type cast + if_chain! { + if let ExprKind::Cast(_, cast_to) = expr.kind; + if let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind; + if let Res::PrimTy(_) = path.res; + then {} + else { + return false + } + } + if let Some(lit) = get_numeric_literal(cast_expr) { let literal_str = snippet_opt(cx, cast_expr.span).unwrap_or_default(); diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs new file mode 100644 index 00000000000..fc141b4a6e3 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs @@ -0,0 +1,125 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::ast::{AttrKind, Attribute, Item, ItemKind}; +use rustc_ast::token::{Token, TokenKind}; +use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{symbol::sym, Span}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for use of `crate` as opposed to `$crate` in a macro definition. + /// + /// ### Why is this bad? + /// `crate` refers to the macro call's crate, whereas `$crate` refers to the macro definition's + /// crate. Rarely is the former intended. See: + /// https://doc.rust-lang.org/reference/macros-by-example.html#hygiene + /// + /// ### Example + /// ```rust + /// #[macro_export] + /// macro_rules! print_message { + /// () => { + /// println!("{}", crate::MESSAGE); + /// }; + /// } + /// pub const MESSAGE: &str = "Hello!"; + /// ``` + /// Use instead: + /// ```rust + /// #[macro_export] + /// macro_rules! print_message { + /// () => { + /// println!("{}", $crate::MESSAGE); + /// }; + /// } + /// pub const MESSAGE: &str = "Hello!"; + /// ``` + /// + /// Note that if the use of `crate` is intentional, an `allow` attribute can be applied to the + /// macro definition, e.g.: + /// ```rust,ignore + /// #[allow(clippy::crate_in_macro_def)] + /// macro_rules! ok { ... crate::foo ... } + /// ``` + #[clippy::version = "1.61.0"] + pub CRATE_IN_MACRO_DEF, + suspicious, + "using `crate` in a macro definition" +} +declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]); + +impl EarlyLintPass for CrateInMacroDef { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if_chain! { + if item.attrs.iter().any(is_macro_export); + if let ItemKind::MacroDef(macro_def) = &item.kind; + let tts = macro_def.body.inner_tokens(); + if let Some(span) = contains_unhygienic_crate_reference(&tts); + then { + span_lint_and_sugg( + cx, + CRATE_IN_MACRO_DEF, + span, + "`crate` references the macro call's crate", + "to reference the macro definition's crate, use", + String::from("$crate"), + Applicability::MachineApplicable, + ); + } + } + } +} + +fn is_macro_export(attr: &Attribute) -> bool { + if_chain! { + if let AttrKind::Normal(attr_item, _) = &attr.kind; + if let [segment] = attr_item.path.segments.as_slice(); + then { + segment.ident.name == sym::macro_export + } else { + false + } + } +} + +fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option<Span> { + let mut prev_is_dollar = false; + let mut cursor = tts.trees(); + while let Some(curr) = cursor.next() { + if_chain! { + if !prev_is_dollar; + if let Some(span) = is_crate_keyword(&curr); + if let Some(next) = cursor.look_ahead(0); + if is_token(next, &TokenKind::ModSep); + then { + return Some(span); + } + } + if let TokenTree::Delimited(_, _, tts) = &curr { + let span = contains_unhygienic_crate_reference(tts); + if span.is_some() { + return span; + } + } + prev_is_dollar = is_token(&curr, &TokenKind::Dollar); + } + None +} + +fn is_crate_keyword(tt: &TokenTree) -> Option<Span> { + if_chain! { + if let TokenTree::Token(Token { kind: TokenKind::Ident(symbol, _), span }) = tt; + if symbol.as_str() == "crate"; + then { Some(*span) } else { None } + } +} + +fn is_token(tt: &TokenTree, kind: &TokenKind) -> bool { + if let TokenTree::Token(Token { kind: other, .. }) = tt { + kind == other + } else { + false + } +} diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index 92cf82bcd6a..28d0c75fde6 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -621,8 +621,8 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) { let filename = FileName::anon_source_code(&code); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let fallback_bundle = rustc_errors::fallback_fluent_bundle(false) - .expect("failed to load fallback fluent bundle"); + let fallback_bundle = + rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle"); let emitter = EmitterWriter::new( Box::new(io::sink()), None, diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs index 5c4b35fd4b9..88c54828da8 100644 --- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs +++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs @@ -1,9 +1,8 @@ -use clippy_utils::diagnostics::span_lint_and_note; -use clippy_utils::ty::is_copy; -use if_chain::if_chain; -use rustc_hir::{Expr, ExprKind}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note}; +use clippy_utils::is_must_use_func_call; +use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item}; +use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -103,6 +102,75 @@ declare_clippy_lint! { "calls to `std::mem::forget` with a value that implements Copy" } +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to `std::mem::drop` with a value that does not implement `Drop`. + /// + /// ### Why is this bad? + /// Calling `std::mem::drop` is no different than dropping such a type. A different value may + /// have been intended. + /// + /// ### Example + /// ```rust + /// struct Foo; + /// let x = Foo; + /// std::mem::drop(x); + /// ``` + #[clippy::version = "1.61.0"] + pub DROP_NON_DROP, + suspicious, + "call to `std::mem::drop` with a value which does not implement `Drop`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to `std::mem::forget` with a value that does not implement `Drop`. + /// + /// ### Why is this bad? + /// Calling `std::mem::forget` is no different than dropping such a type. A different value may + /// have been intended. + /// + /// ### Example + /// ```rust + /// struct Foo; + /// let x = Foo; + /// std::mem::forget(x); + /// ``` + #[clippy::version = "1.61.0"] + pub FORGET_NON_DROP, + suspicious, + "call to `std::mem::forget` with a value which does not implement `Drop`" +} + +declare_clippy_lint! { + /// ### What it does + /// Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`. + /// + /// ### Why is this bad? + /// The safe `drop` function does not drop the inner value of a `ManuallyDrop`. + /// + /// ### Known problems + /// Does not catch cases if the user binds `std::mem::drop` + /// to a different name and calls it that way. + /// + /// ### Example + /// ```rust + /// struct S; + /// drop(std::mem::ManuallyDrop::new(S)); + /// ``` + /// Use instead: + /// ```rust + /// struct S; + /// unsafe { + /// std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S)); + /// } + /// ``` + #[clippy::version = "1.49.0"] + pub UNDROPPED_MANUALLY_DROPS, + correctness, + "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value" +} + const DROP_REF_SUMMARY: &str = "calls to `std::mem::drop` with a reference instead of an owned value. \ Dropping a reference does nothing"; const FORGET_REF_SUMMARY: &str = "calls to `std::mem::forget` with a reference instead of an owned value. \ @@ -111,60 +179,65 @@ const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that imp Dropping a copy leaves the original intact"; const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements `Copy`. \ Forgetting a copy leaves the original intact"; +const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \ + Dropping such a type only extends it's contained lifetimes"; +const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \ + Forgetting such a type is the same as dropping it"; -declare_lint_pass!(DropForgetRef => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY]); +declare_lint_pass!(DropForgetRef => [ + DROP_REF, + FORGET_REF, + DROP_COPY, + FORGET_COPY, + DROP_NON_DROP, + FORGET_NON_DROP, + UNDROPPED_MANUALLY_DROPS +]); impl<'tcx> LateLintPass<'tcx> for DropForgetRef { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(path, args) = expr.kind; - if let ExprKind::Path(ref qpath) = path.kind; - if args.len() == 1; - if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); - then { - let lint; - let msg; - let arg = &args[0]; - let arg_ty = cx.typeck_results().expr_ty(arg); - - if let ty::Ref(..) = arg_ty.kind() { - match cx.tcx.get_diagnostic_name(def_id) { - Some(sym::mem_drop) => { - lint = DROP_REF; - msg = DROP_REF_SUMMARY.to_string(); - }, - Some(sym::mem_forget) => { - lint = FORGET_REF; - msg = FORGET_REF_SUMMARY.to_string(); - }, - _ => return, - } - span_lint_and_note(cx, - lint, - expr.span, - &msg, - Some(arg.span), - &format!("argument has type `{}`", arg_ty)); - } else if is_copy(cx, arg_ty) { - match cx.tcx.get_diagnostic_name(def_id) { - Some(sym::mem_drop) => { - lint = DROP_COPY; - msg = DROP_COPY_SUMMARY.to_string(); - }, - Some(sym::mem_forget) => { - lint = FORGET_COPY; - msg = FORGET_COPY_SUMMARY.to_string(); - }, - _ => return, - } - span_lint_and_note(cx, - lint, - expr.span, - &msg, - Some(arg.span), - &format!("argument has type {}", arg_ty)); + if let ExprKind::Call(path, [arg]) = expr.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id) + { + let arg_ty = cx.typeck_results().expr_ty(arg); + let (lint, msg) = match fn_name { + sym::mem_drop if arg_ty.is_ref() => (DROP_REF, DROP_REF_SUMMARY), + sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY), + sym::mem_drop if is_copy(cx, arg_ty) => (DROP_COPY, DROP_COPY_SUMMARY), + sym::mem_forget if is_copy(cx, arg_ty) => (FORGET_COPY, FORGET_COPY_SUMMARY), + sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => { + span_lint_and_help( + cx, + UNDROPPED_MANUALLY_DROPS, + expr.span, + "the inner value of this ManuallyDrop will not be dropped", + None, + "to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop", + ); + return; } - } + sym::mem_drop + if !(arg_ty.needs_drop(cx.tcx, cx.param_env) + || is_must_use_func_call(cx, arg) + || is_must_use_ty(cx, arg_ty)) => + { + (DROP_NON_DROP, DROP_NON_DROP_SUMMARY) + }, + sym::mem_forget if !arg_ty.needs_drop(cx.tcx, cx.param_env) => { + (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY) + }, + _ => return, + }; + span_lint_and_note( + cx, + lint, + expr.span, + msg, + Some(arg.span), + &format!("argument has type `{}`", arg_ty), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs new file mode 100644 index 00000000000..fdeac8d8255 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs @@ -0,0 +1,99 @@ +use clippy_utils::{diagnostics::span_lint_and_then, source::snippet_opt}; +use rustc_ast::ast::{Item, ItemKind, VariantData}; +use rustc_errors::Applicability; +use rustc_lexer::TokenKind; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Finds structs without fields (a so-called "empty struct") that are declared with brackets. + /// + /// ### Why is this bad? + /// Empty brackets after a struct declaration can be omitted. + /// + /// ### Example + /// ```rust + /// struct Cookie {} + /// ``` + /// Use instead: + /// ```rust + /// struct Cookie; + /// ``` + #[clippy::version = "1.62.0"] + pub EMPTY_STRUCTS_WITH_BRACKETS, + restriction, + "finds struct declarations with empty brackets" +} +declare_lint_pass!(EmptyStructsWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS]); + +impl EarlyLintPass for EmptyStructsWithBrackets { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + let span_after_ident = item.span.with_lo(item.ident.span.hi()); + + if let ItemKind::Struct(var_data, _) = &item.kind + && has_brackets(var_data) + && has_no_fields(cx, var_data, span_after_ident) { + span_lint_and_then( + cx, + EMPTY_STRUCTS_WITH_BRACKETS, + span_after_ident, + "found empty brackets on struct declaration", + |diagnostic| { + diagnostic.span_suggestion_hidden( + span_after_ident, + "remove the brackets", + ";".to_string(), + Applicability::MachineApplicable); + }, + ); + } + } +} + +fn has_no_ident_token(braces_span_str: &str) -> bool { + !rustc_lexer::tokenize(braces_span_str).any(|t| t.kind == TokenKind::Ident) +} + +fn has_brackets(var_data: &VariantData) -> bool { + !matches!(var_data, VariantData::Unit(_)) +} + +fn has_no_fields(cx: &EarlyContext<'_>, var_data: &VariantData, braces_span: Span) -> bool { + if !var_data.fields().is_empty() { + return false; + } + + // there might still be field declarations hidden from the AST + // (conditionaly compiled code using #[cfg(..)]) + + let Some(braces_span_str) = snippet_opt(cx, braces_span) else { + return false; + }; + + has_no_ident_token(braces_span_str.as_ref()) +} + +#[cfg(test)] +mod unit_test { + use super::*; + + #[test] + fn test_has_no_ident_token() { + let input = "{ field: u8 }"; + assert!(!has_no_ident_token(input)); + + let input = "(u8, String);"; + assert!(!has_no_ident_token(input)); + + let input = " { + // test = 5 + } + "; + assert!(has_no_ident_token(input)); + + let input = " ();"; + assert!(has_no_ident_token(input)); + } +} diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/identity_op.rs index f824f20ca40..4d6bef89bea 100644 --- a/src/tools/clippy/clippy_lints/src/identity_op.rs +++ b/src/tools/clippy/clippy_lints/src/identity_op.rs @@ -5,7 +5,7 @@ use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::consts::{constant_full_int, constant_simple, Constant, FullInt}; use clippy_utils::diagnostics::span_lint; use clippy_utils::{clip, unsext}; @@ -54,6 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for IdentityOp { check(cx, left, -1, e.span, right.span); check(cx, right, -1, e.span, left.span); }, + BinOpKind::Rem => check_remainder(cx, left, right, e.span, left.span), _ => (), } } @@ -70,6 +71,18 @@ fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_ && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1))) } +fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span: Span, arg: Span) { + let lhs_const = constant_full_int(cx, cx.typeck_results(), left); + let rhs_const = constant_full_int(cx, cx.typeck_results(), right); + if match (lhs_const, rhs_const) { + (Some(FullInt::S(lv)), Some(FullInt::S(rv))) => lv.abs() < rv.abs(), + (Some(FullInt::U(lv)), Some(FullInt::U(rv))) => lv < rv, + _ => return, + } { + span_ineffective_operation(cx, span, arg); + } +} + fn check(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) { let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() { @@ -83,15 +96,19 @@ fn check(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span) { 1 => v == 1, _ => unreachable!(), } { - span_lint( - cx, - IDENTITY_OP, - span, - &format!( - "the operation is ineffective. Consider reducing it to `{}`", - snippet(cx, arg, "..") - ), - ); + span_ineffective_operation(cx, span, arg); } } } + +fn span_ineffective_operation(cx: &LateContext<'_>, span: Span, arg: Span) { + span_lint( + cx, + IDENTITY_OP, + span, + &format!( + "the operation is ineffective. Consider reducing it to `{}`", + snippet(cx, arg, "..") + ), + ); +} diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index 9ead4bb27a5..4ba7477add8 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -96,6 +96,10 @@ declare_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING] impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if cx.tcx.hir().is_inside_const_context(expr.hir_id) { + return; + } + if let ExprKind::Index(array, index) = &expr.kind { let ty = cx.typeck_results().expr_ty(array).peel_refs(); if let Some(range) = higher::Range::hir(index) { @@ -151,6 +155,10 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { } else { // Catchall non-range index, i.e., [n] or [n << m] if let ty::Array(..) = ty.kind() { + // Index is a const block. + if let ExprKind::ConstBlock(..) = index.kind { + return; + } // Index is a constant uint. if let Some(..) = constant(cx, cx.typeck_results(), index) { // Let rustc's `const_err` lint handle constant `usize` indexing on arrays. diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs index 132a4662676..14ca93b5f3c 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs @@ -23,6 +23,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), LintId::of(booleans::LOGIC_BUG), LintId::of(booleans::NONMINIMAL_BOOL), + LintId::of(casts::CAST_ABS_TO_UNSIGNED), LintId::of(casts::CAST_ENUM_CONSTRUCTOR), LintId::of(casts::CAST_ENUM_TRUNCATION), LintId::of(casts::CAST_REF_TO_MUT), @@ -37,6 +38,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(comparison_chain::COMPARISON_CHAIN), LintId::of(copies::IFS_SAME_COND), LintId::of(copies::IF_SAME_THEN_ELSE), + LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF), LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), LintId::of(dereference::NEEDLESS_BORROW), LintId::of(derivable_impls::DERIVABLE_IMPLS), @@ -49,9 +51,12 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(double_comparison::DOUBLE_COMPARISONS), LintId::of(double_parens::DOUBLE_PARENS), LintId::of(drop_forget_ref::DROP_COPY), + LintId::of(drop_forget_ref::DROP_NON_DROP), LintId::of(drop_forget_ref::DROP_REF), LintId::of(drop_forget_ref::FORGET_COPY), + LintId::of(drop_forget_ref::FORGET_NON_DROP), LintId::of(drop_forget_ref::FORGET_REF), + LintId::of(drop_forget_ref::UNDROPPED_MANUALLY_DROPS), LintId::of(duration_subsec::DURATION_SUBSEC), LintId::of(entry::MAP_ENTRY), LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), @@ -152,6 +157,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(methods::CHARS_NEXT_CMP), LintId::of(methods::CLONE_DOUBLE_REF), LintId::of(methods::CLONE_ON_COPY), + LintId::of(methods::ERR_EXPECT), LintId::of(methods::EXPECT_FUN_CALL), LintId::of(methods::EXTEND_WITH_DRAIN), LintId::of(methods::FILTER_MAP_IDENTITY), @@ -175,6 +181,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(methods::MAP_COLLECT_RESULT_UNIT), LintId::of(methods::MAP_FLATTEN), LintId::of(methods::MAP_IDENTITY), + LintId::of(methods::NEEDLESS_OPTION_AS_DEREF), LintId::of(methods::NEEDLESS_SPLITN), LintId::of(methods::NEW_RET_NO_SELF), LintId::of(methods::OK_EXPECT), @@ -224,7 +231,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(needless_bool::NEEDLESS_BOOL), LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), LintId::of(needless_late_init::NEEDLESS_LATE_INIT), - LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF), LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), LintId::of(needless_update::NEEDLESS_UPDATE), LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), @@ -296,7 +302,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(types::REDUNDANT_ALLOCATION), LintId::of(types::TYPE_COMPLEXITY), LintId::of(types::VEC_BOX), - LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), LintId::of(unicode::INVISIBLE_CHARACTERS), LintId::of(uninit_vec::UNINIT_VEC), LintId::of(unit_hash::UNIT_HASH), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs index a2ce69065f9..10369a855ae 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs @@ -44,6 +44,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec! LintId::of(methods::MANUAL_SPLIT_ONCE), LintId::of(methods::MAP_FLATTEN), LintId::of(methods::MAP_IDENTITY), + LintId::of(methods::NEEDLESS_OPTION_AS_DEREF), LintId::of(methods::NEEDLESS_SPLITN), LintId::of(methods::OPTION_AS_REF_DEREF), LintId::of(methods::OPTION_FILTER_MAP), @@ -60,7 +61,6 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec! LintId::of(needless_bool::BOOL_COMPARISON), LintId::of(needless_bool::NEEDLESS_BOOL), LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), - LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF), LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), LintId::of(needless_update::NEEDLESS_UPDATE), LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs index df63f84463d..6bf2c4bbaed 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs @@ -22,6 +22,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(drop_forget_ref::DROP_REF), LintId::of(drop_forget_ref::FORGET_COPY), LintId::of(drop_forget_ref::FORGET_REF), + LintId::of(drop_forget_ref::UNDROPPED_MANUALLY_DROPS), LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), LintId::of(eq_op::EQ_OP), LintId::of(erasing_op::ERASING_OP), @@ -62,7 +63,6 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(transmute::WRONG_TRANSMUTE), LintId::of(transmuting_null::TRANSMUTING_NULL), - LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), LintId::of(unicode::INVISIBLE_CHARACTERS), LintId::of(uninit_vec::UNINIT_VEC), LintId::of(unit_hash::UNIT_HASH), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs index 21f1ef562b5..532590aaa5a 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs @@ -70,6 +70,7 @@ store.register_lints(&[ cargo::REDUNDANT_FEATURE_NAMES, cargo::WILDCARD_DEPENDENCIES, case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, + casts::CAST_ABS_TO_UNSIGNED, casts::CAST_ENUM_CONSTRUCTOR, casts::CAST_ENUM_TRUNCATION, casts::CAST_LOSSLESS, @@ -97,6 +98,7 @@ store.register_lints(&[ copies::IF_SAME_THEN_ELSE, copies::SAME_FUNCTIONS_IN_IF_CONDITION, copy_iterator::COPY_ITERATOR, + crate_in_macro_def::CRATE_IN_MACRO_DEF, create_dir::CREATE_DIR, dbg_macro::DBG_MACRO, default::DEFAULT_TRAIT_ACCESS, @@ -122,12 +124,16 @@ store.register_lints(&[ double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, drop_forget_ref::DROP_COPY, + drop_forget_ref::DROP_NON_DROP, drop_forget_ref::DROP_REF, drop_forget_ref::FORGET_COPY, + drop_forget_ref::FORGET_NON_DROP, drop_forget_ref::FORGET_REF, + drop_forget_ref::UNDROPPED_MANUALLY_DROPS, duration_subsec::DURATION_SUBSEC, else_if_without_else::ELSE_IF_WITHOUT_ELSE, empty_enum::EMPTY_ENUM, + empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS, entry::MAP_ENTRY, enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, enum_variants::ENUM_VARIANT_NAMES, @@ -280,6 +286,7 @@ store.register_lints(&[ methods::CLONE_DOUBLE_REF, methods::CLONE_ON_COPY, methods::CLONE_ON_REF_PTR, + methods::ERR_EXPECT, methods::EXPECT_FUN_CALL, methods::EXPECT_USED, methods::EXTEND_WITH_DRAIN, @@ -313,6 +320,7 @@ store.register_lints(&[ methods::MAP_FLATTEN, methods::MAP_IDENTITY, methods::MAP_UNWRAP_OR, + methods::NEEDLESS_OPTION_AS_DEREF, methods::NEEDLESS_SPLITN, methods::NEW_RET_NO_SELF, methods::OK_EXPECT, @@ -384,7 +392,6 @@ store.register_lints(&[ needless_continue::NEEDLESS_CONTINUE, needless_for_each::NEEDLESS_FOR_EACH, needless_late_init::NEEDLESS_LATE_INIT, - needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF, needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, needless_question_mark::NEEDLESS_QUESTION_MARK, needless_update::NEEDLESS_UPDATE, @@ -505,7 +512,6 @@ store.register_lints(&[ types::TYPE_COMPLEXITY, types::VEC_BOX, undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS, - undropped_manually_drops::UNDROPPED_MANUALLY_DROPS, unicode::INVISIBLE_CHARACTERS, unicode::NON_ASCII_LITERAL, unicode::UNICODE_NOT_NFC, diff --git a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs index 6ab139b2fb6..4802dd877e9 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs @@ -16,6 +16,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve LintId::of(default_union_representation::DEFAULT_UNION_REPRESENTATION), LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS), LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE), + LintId::of(empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS), LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS), LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS), LintId::of(exit::EXIT), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs index dcf399cf956..3114afac886 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_style.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_style.rs @@ -59,6 +59,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(methods::BYTES_NTH), LintId::of(methods::CHARS_LAST_CMP), LintId::of(methods::CHARS_NEXT_CMP), + LintId::of(methods::ERR_EXPECT), LintId::of(methods::INTO_ITER_ON_REF), LintId::of(methods::ITER_CLONED_COLLECT), LintId::of(methods::ITER_NEXT_SLICE), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs index fa3a88e1368..82f45b5fd58 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs @@ -7,8 +7,12 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec! LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK), LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF), + LintId::of(casts::CAST_ABS_TO_UNSIGNED), LintId::of(casts::CAST_ENUM_CONSTRUCTOR), LintId::of(casts::CAST_ENUM_TRUNCATION), + LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF), + LintId::of(drop_forget_ref::DROP_NON_DROP), + LintId::of(drop_forget_ref::FORGET_NON_DROP), LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE), LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), LintId::of(format_impl::PRINT_IN_FORMAT_IMPL), diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index f2a07999144..c9b836f9580 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -1,5 +1,6 @@ // error-pattern:cargo-clippy +#![feature(array_windows)] #![feature(binary_heap_into_iter_sorted)] #![feature(box_patterns)] #![feature(control_flow_enum)] @@ -190,6 +191,7 @@ mod collapsible_match; mod comparison_chain; mod copies; mod copy_iterator; +mod crate_in_macro_def; mod create_dir; mod dbg_macro; mod default; @@ -208,6 +210,7 @@ mod drop_forget_ref; mod duration_subsec; mod else_if_without_else; mod empty_enum; +mod empty_structs_with_brackets; mod entry; mod enum_clike; mod enum_variants; @@ -305,7 +308,6 @@ mod needless_borrowed_ref; mod needless_continue; mod needless_for_each; mod needless_late_init; -mod needless_option_as_deref; mod needless_pass_by_value; mod needless_question_mark; mod needless_update; @@ -375,7 +377,6 @@ mod transmuting_null; mod try_err; mod types; mod undocumented_unsafe_blocks; -mod undropped_manually_drops; mod unicode; mod uninit_vec; mod unit_hash; @@ -533,7 +534,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(ptr::Ptr)); store.register_late_pass(|| Box::new(ptr_eq::PtrEq)); store.register_late_pass(|| Box::new(needless_bool::NeedlessBool)); - store.register_late_pass(|| Box::new(needless_option_as_deref::OptionNeedlessDeref)); store.register_late_pass(|| Box::new(needless_bool::BoolComparison)); store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach)); store.register_late_pass(|| Box::new(misc::MiscLints)); @@ -812,7 +812,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone()))); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax)); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax)); - store.register_late_pass(|| Box::new(undropped_manually_drops::UndroppedManuallyDrops)); store.register_late_pass(|| Box::new(strings::StrToString)); store.register_late_pass(|| Box::new(strings::StringToString)); store.register_late_pass(|| Box::new(zero_sized_map_values::ZeroSizedMapValues)); @@ -847,7 +846,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: enable_raw_pointer_heuristic_for_send, )) }); - store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::default())); + store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks)); store.register_late_pass(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch)); store.register_late_pass(move || Box::new(format_args::FormatArgs)); store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray)); @@ -867,6 +866,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ignore_publish: cargo_ignore_publish, }) }); + store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef)); + store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs index 36ecd83f7d6..a0bd7ad0ac6 100644 --- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs @@ -2,9 +2,12 @@ use super::SINGLE_ELEMENT_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, snippet_with_applicability}; use if_chain::if_chain; +use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::Mutability; use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind, Pat}; +use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat}; use rustc_lint::LateContext; +use rustc_span::edition::Edition; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, @@ -13,31 +16,84 @@ pub(super) fn check<'tcx>( body: &'tcx Expr<'_>, expr: &'tcx Expr<'_>, ) { - let arg_expr = match arg.kind { - ExprKind::AddrOf(BorrowKind::Ref, _, ref_arg) => ref_arg, - ExprKind::MethodCall(method, [arg], _) if method.ident.name == rustc_span::sym::iter => arg, + let (arg_expression, prefix) = match arg.kind { + ExprKind::AddrOf( + BorrowKind::Ref, + Mutability::Not, + Expr { + kind: ExprKind::Array([arg]), + .. + }, + ) => (arg, "&"), + ExprKind::AddrOf( + BorrowKind::Ref, + Mutability::Mut, + Expr { + kind: ExprKind::Array([arg]), + .. + }, + ) => (arg, "&mut "), + ExprKind::MethodCall( + method, + [ + Expr { + kind: ExprKind::Array([arg]), + .. + }, + ], + _, + ) if method.ident.name == rustc_span::sym::iter => (arg, "&"), + ExprKind::MethodCall( + method, + [ + Expr { + kind: ExprKind::Array([arg]), + .. + }, + ], + _, + ) if method.ident.name.as_str() == "iter_mut" => (arg, "&mut "), + ExprKind::MethodCall( + method, + [ + Expr { + kind: ExprKind::Array([arg]), + .. + }, + ], + _, + ) if method.ident.name == rustc_span::sym::into_iter => (arg, ""), + // Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise. + ExprKind::Array([arg]) if cx.tcx.sess.edition() >= Edition::Edition2021 => (arg, ""), _ => return, }; if_chain! { - if let ExprKind::Array([arg_expression]) = arg_expr.kind; if let ExprKind::Block(block, _) = body.kind; if !block.stmts.is_empty(); then { let mut applicability = Applicability::MachineApplicable; let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability); - let arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability); + let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability); let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned(); block_str.remove(0); block_str.pop(); let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0)); + // Reference iterator from `&(mut) []` or `[].iter(_mut)()`. + if !prefix.is_empty() && ( + // Precedence of internal expression is less than or equal to precedence of `&expr`. + arg_expression.precedence().order() <= PREC_PREFIX || is_range_literal(arg_expression) + ) { + arg_snip = format!("({arg_snip})").into(); + } + span_lint_and_sugg( cx, SINGLE_ELEMENT_LOOP, expr.span, "for loop over a single element", "try", - format!("{{\n{}let {} = &{};{}}}", indent, pat_snip, arg_snip, block_str), + format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"), applicability, ) } diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index 0f6ac478432..f552d5c1afa 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet; +use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{iter_input_pats, method_chain_args}; use if_chain::if_chain; @@ -217,36 +217,33 @@ fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr let fn_arg = &map_args[1]; if is_unit_function(cx, fn_arg) { + let mut applicability = Applicability::MachineApplicable; let msg = suggestion_msg("function", map_type); let suggestion = format!( "if let {0}({binding}) = {1} {{ {2}({binding}) }}", variant, - snippet(cx, var_arg.span, "_"), - snippet(cx, fn_arg.span, "_"), + snippet_with_applicability(cx, var_arg.span, "_", &mut applicability), + snippet_with_applicability(cx, fn_arg.span, "_", &mut applicability), binding = let_binding_name(cx, var_arg) ); span_lint_and_then(cx, lint, expr.span, &msg, |diag| { - diag.span_suggestion(stmt.span, "try this", suggestion, Applicability::MachineApplicable); + diag.span_suggestion(stmt.span, "try this", suggestion, applicability); }); } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) { let msg = suggestion_msg("closure", map_type); span_lint_and_then(cx, lint, expr.span, &msg, |diag| { if let Some(reduced_expr_span) = reduce_unit_expression(cx, closure_expr) { + let mut applicability = Applicability::MachineApplicable; let suggestion = format!( "if let {0}({1}) = {2} {{ {3} }}", variant, - snippet(cx, binding.pat.span, "_"), - snippet(cx, var_arg.span, "_"), - snippet(cx, reduced_expr_span, "_") - ); - diag.span_suggestion( - stmt.span, - "try this", - suggestion, - Applicability::MachineApplicable, // snippet + snippet_with_applicability(cx, binding.pat.span, "_", &mut applicability), + snippet_with_applicability(cx, var_arg.span, "_", &mut applicability), + snippet_with_context(cx, reduced_expr_span, var_arg.span.ctxt(), "_", &mut applicability).0, ); + diag.span_suggestion(stmt.span, "try this", suggestion, applicability); } else { let suggestion = format!( "if let {0}({1}) = {2} {{ ... }}", diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index ff85623acf4..e93b494653f 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -667,7 +667,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { overlapping_arms::check(cx, ex, arms); match_wild_enum::check(cx, ex, arms); match_as_ref::check(cx, ex, arms, expr); - needless_match::check_match(cx, ex, arms); + needless_match::check_match(cx, ex, arms, expr); if self.infallible_destructuring_match_linted { self.infallible_destructuring_match_linted = false; diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs index 76131d307d7..2105a03e03a 100644 --- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs @@ -1,37 +1,25 @@ use super::NEEDLESS_MATCH; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::{eq_expr_value, get_parent_expr, higher, is_else_clause, is_lang_ctor, peel_blocks_with_stmt}; +use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts}; +use clippy_utils::{ + eq_expr_value, get_parent_expr_for_hir, get_parent_node, higher, is_else_clause, is_lang_ctor, over, + peel_blocks_with_stmt, +}; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; -use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, Pat, PatKind, Path, PathSegment, QPath, UnOp}; +use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, FnRetTy, Node, Pat, PatKind, Path, QPath}; use rustc_lint::LateContext; use rustc_span::sym; +use rustc_typeck::hir_ty_to_ty; -pub(crate) fn check_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { - // This is for avoiding collision with `match_single_binding`. - if arms.len() < 2 { - return; - } - - for arm in arms { - if let PatKind::Wild = arm.pat.kind { - let ret_expr = strip_return(arm.body); - if !eq_expr_value(cx, ex, ret_expr) { - return; - } - } else if !pat_same_as_expr(arm.pat, arm.body) { - return; - } - } - - if let Some(match_expr) = get_parent_expr(cx, ex) { +pub(crate) fn check_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { + if arms.len() > 1 && expr_ty_matches_p_ty(cx, ex, expr) && check_all_arms(cx, ex, arms) { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, NEEDLESS_MATCH, - match_expr.span, + expr.span, "this match expression is unnecessary", "replace it with", snippet_with_applicability(cx, ex.span, "..", &mut applicability).to_string(), @@ -60,11 +48,8 @@ pub(crate) fn check_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) /// } /// ``` pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>) { - if_chain! { - if let Some(ref if_let) = higher::IfLet::hir(cx, ex); - if !is_else_clause(cx.tcx, ex); - if check_if_let(cx, if_let); - then { + if let Some(ref if_let) = higher::IfLet::hir(cx, ex) { + if !is_else_clause(cx.tcx, ex) && expr_ty_matches_p_ty(cx, if_let.let_expr, ex) && check_if_let(cx, if_let) { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, @@ -79,6 +64,19 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>) { } } +fn check_all_arms(cx: &LateContext<'_>, match_expr: &Expr<'_>, arms: &[Arm<'_>]) -> bool { + for arm in arms { + let arm_expr = peel_blocks_with_stmt(arm.body); + if let PatKind::Wild = arm.pat.kind { + return eq_expr_value(cx, match_expr, strip_return(arm_expr)); + } else if !pat_same_as_expr(arm.pat, arm_expr) { + return false; + } + } + + true +} + fn check_if_let(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool { if let Some(if_else) = if_let.if_else { if !pat_same_as_expr(if_let.let_pat, peel_blocks_with_stmt(if_let.if_then)) { @@ -92,18 +90,21 @@ fn check_if_let(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool { if matches!(if_else.kind, ExprKind::Block(..)) { let else_expr = peel_blocks_with_stmt(if_else); + if matches!(else_expr.kind, ExprKind::Block(..)) { + return false; + } let ret = strip_return(else_expr); let let_expr_ty = cx.typeck_results().expr_ty(if_let.let_expr); if is_type_diagnostic_item(cx, let_expr_ty, sym::Option) { if let ExprKind::Path(ref qpath) = ret.kind { return is_lang_ctor(cx, qpath, OptionNone) || eq_expr_value(cx, if_let.let_expr, ret); } - } else { - return eq_expr_value(cx, if_let.let_expr, ret); + return true; } - return true; + return eq_expr_value(cx, if_let.let_expr, ret); } } + false } @@ -116,48 +117,70 @@ fn strip_return<'hir>(expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> { } } +/// Manually check for coercion casting by checking if the type of the match operand or let expr +/// differs with the assigned local variable or the funtion return type. +fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_>) -> bool { + if let Some(p_node) = get_parent_node(cx.tcx, p_expr.hir_id) { + match p_node { + // Compare match_expr ty with local in `let local = match match_expr {..}` + Node::Local(local) => { + let results = cx.typeck_results(); + return same_type_and_consts(results.node_type(local.hir_id), results.expr_ty(expr)); + }, + // compare match_expr ty with RetTy in `fn foo() -> RetTy` + Node::Item(..) => { + if let Some(fn_decl) = p_node.fn_decl() { + if let FnRetTy::Return(ret_ty) = fn_decl.output { + return same_type_and_consts(hir_ty_to_ty(cx.tcx, ret_ty), cx.typeck_results().expr_ty(expr)); + } + } + }, + // check the parent expr for this whole block `{ match match_expr {..} }` + Node::Block(block) => { + if let Some(block_parent_expr) = get_parent_expr_for_hir(cx, block.hir_id) { + return expr_ty_matches_p_ty(cx, expr, block_parent_expr); + } + }, + // recursively call on `if xxx {..}` etc. + Node::Expr(p_expr) => { + return expr_ty_matches_p_ty(cx, expr, p_expr); + }, + _ => {}, + } + } + false +} + fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool { let expr = strip_return(expr); match (&pat.kind, &expr.kind) { // Example: `Some(val) => Some(val)` - ( - PatKind::TupleStruct(QPath::Resolved(_, path), [first_pat, ..], _), - ExprKind::Call(call_expr, [first_param, ..]), - ) => { + (PatKind::TupleStruct(QPath::Resolved(_, path), tuple_params, _), ExprKind::Call(call_expr, call_params)) => { if let ExprKind::Path(QPath::Resolved(_, call_path)) = call_expr.kind { - if has_identical_segments(path.segments, call_path.segments) - && has_same_non_ref_symbol(first_pat, first_param) - { - return true; - } + return over(path.segments, call_path.segments, |pat_seg, call_seg| { + pat_seg.ident.name == call_seg.ident.name + }) && same_non_ref_symbols(tuple_params, call_params); } }, - // Example: `val => val`, or `ref val => *val` - (PatKind::Binding(annot, _, pat_ident, _), _) => { - let new_expr = if let ( - BindingAnnotation::Ref | BindingAnnotation::RefMut, - ExprKind::Unary(UnOp::Deref, operand_expr), - ) = (annot, &expr.kind) - { - operand_expr - } else { - expr - }; - - if let ExprKind::Path(QPath::Resolved( + // Example: `val => val` + ( + PatKind::Binding(annot, _, pat_ident, _), + ExprKind::Path(QPath::Resolved( _, Path { segments: [first_seg, ..], .. }, - )) = new_expr.kind - { - return pat_ident.name == first_seg.ident.name; - } + )), + ) => { + return !matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut) + && pat_ident.name == first_seg.ident.name; }, // Example: `Custom::TypeA => Custom::TypeB`, or `None => None` (PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => { - return has_identical_segments(p_path.segments, e_path.segments); + return over(p_path.segments, e_path.segments, |p_seg, e_seg| { + p_seg.ident.name == e_seg.ident.name + }); }, // Example: `5 => 5` (PatKind::Lit(pat_lit_expr), ExprKind::Lit(expr_spanned)) => { @@ -171,27 +194,16 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool { false } -fn has_identical_segments(left_segs: &[PathSegment<'_>], right_segs: &[PathSegment<'_>]) -> bool { - if left_segs.len() != right_segs.len() { +fn same_non_ref_symbols(pats: &[Pat<'_>], exprs: &[Expr<'_>]) -> bool { + if pats.len() != exprs.len() { return false; } - for i in 0..left_segs.len() { - if left_segs[i].ident.name != right_segs[i].ident.name { - return false; - } - } - true -} -fn has_same_non_ref_symbol(pat: &Pat<'_>, expr: &Expr<'_>) -> bool { - if_chain! { - if let PatKind::Binding(annot, _, pat_ident, _) = pat.kind; - if !matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut); - if let ExprKind::Path(QPath::Resolved(_, Path {segments: [first_seg, ..], .. })) = expr.kind; - then { - return pat_ident.name == first_seg.ident.name; + for i in 0..pats.len() { + if !pat_same_as_expr(&pats[i], &exprs[i]) { + return false; } } - false + true } diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs index 76eaedea8a0..44857d61fef 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs @@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E cx, BYTES_NTH, expr.span, - &format!("called `.byte().nth()` on a `{}`", caller_type), + &format!("called `.bytes().nth()` on a `{}`", caller_type), "try", format!( "{}.as_bytes().get({})", diff --git a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs new file mode 100644 index 00000000000..be9d4ad94fb --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs @@ -0,0 +1,60 @@ +use super::ERR_EXPECT; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::implements_trait; +use clippy_utils::{meets_msrv, msrvs, ty::is_type_diagnostic_item}; +use rustc_errors::Applicability; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_middle::ty::Ty; +use rustc_semver::RustcVersion; +use rustc_span::{sym, Span}; + +pub(super) fn check( + cx: &LateContext<'_>, + _expr: &rustc_hir::Expr<'_>, + recv: &rustc_hir::Expr<'_>, + msrv: Option<&RustcVersion>, + expect_span: Span, + err_span: Span, +) { + if_chain! { + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); + // Test the version to make sure the lint can be showed (expect_err has been + // introduced in rust 1.17.0 : https://github.com/rust-lang/rust/pull/38982) + if meets_msrv(msrv, &msrvs::EXPECT_ERR); + + // Grabs the `Result<T, E>` type + let result_type = cx.typeck_results().expr_ty(recv); + // Tests if the T type in a `Result<T, E>` is not None + if let Some(data_type) = get_data_type(cx, result_type); + // Tests if the T type in a `Result<T, E>` implements debug + if has_debug_impl(data_type, cx); + + then { + span_lint_and_sugg( + cx, + ERR_EXPECT, + err_span.to(expect_span), + "called `.err().expect()` on a `Result` value", + "try", + "expect_err".to_string(), + Applicability::MachineApplicable + ); + } + }; +} + +/// Given a `Result<T, E>` type, return its data (`T`). +fn get_data_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> { + match ty.kind() { + ty::Adt(_, substs) if is_type_diagnostic_item(cx, ty, sym::Result) => substs.types().next(), + _ => None, + } +} + +/// Given a type, very if the Debug trait has been impl'd +fn has_debug_impl<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { + cx.tcx + .get_diagnostic_item(sym::Debug) + .map_or(false, |debug| implements_trait(cx, ty, debug, &[])) +} diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs index c98cdfbca43..9651a52be4e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs @@ -48,13 +48,11 @@ pub fn is_clone_like(cx: &LateContext<'_>, method_name: &str, method_def_id: hir "to_os_string" => is_diag_item_method(cx, method_def_id, sym::OsStr), "to_owned" => is_diag_trait_item(cx, method_def_id, sym::ToOwned), "to_path_buf" => is_diag_item_method(cx, method_def_id, sym::Path), - "to_vec" => { - cx.tcx.impl_of_method(method_def_id) - .filter(|&impl_did| { - cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none() - }) - .is_some() - }, + "to_vec" => cx + .tcx + .impl_of_method(method_def_id) + .filter(|&impl_did| cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none()) + .is_some(), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs index b93f1399eae..54c9ca435a4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -1,11 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use clippy_utils::ty::{get_iterator_item_ty, is_copy}; +use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy}; use itertools::Itertools; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; +use rustc_span::sym; use std::ops::Not; use super::ITER_OVEREAGER_CLONED; @@ -20,9 +21,16 @@ pub(super) fn check<'tcx>( map_arg: &[hir::Expr<'_>], ) { // Check if it's iterator and get type associated with `Item`. - let inner_ty = match get_iterator_item_ty(cx, cx.typeck_results().expr_ty_adjusted(recv)) { - Some(ty) => ty, - _ => return, + let inner_ty = if_chain! { + if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + let recv_ty = cx.typeck_results().expr_ty(recv); + if implements_trait(cx, recv_ty, iterator_trait_id, &[]); + if let Some(inner_ty) = get_iterator_item_ty(cx, cx.typeck_results().expr_ty_adjusted(recv)); + then { + inner_ty + } else { + return; + } }; match inner_ty.kind() { diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs index f112b500d3d..862a9578e6f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs @@ -13,6 +13,7 @@ pub(super) fn check( expr: &hir::Expr<'_>, caller: &hir::Expr<'_>, map_arg: &hir::Expr<'_>, + name: &str, _map_span: Span, ) { let caller_ty = cx.typeck_results().expr_ty(caller); @@ -29,7 +30,7 @@ pub(super) fn check( MAP_IDENTITY, sugg_span, "unnecessary map of the identity function", - "remove the call to `map`", + &format!("remove the call to `{}`", name), String::new(), Applicability::MachineApplicable, ) diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 9d4e1fa3994..70d021a1668 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -9,6 +9,7 @@ mod chars_next_cmp_with_unwrap; mod clone_on_copy; mod clone_on_ref_ptr; mod cloned_instead_of_copied; +mod err_expect; mod expect_fun_call; mod expect_used; mod extend_with_drain; @@ -40,6 +41,7 @@ mod map_collect_result_unit; mod map_flatten; mod map_identity; mod map_unwrap_or; +mod needless_option_as_deref; mod ok_expect; mod option_as_ref_deref; mod option_map_or_none; @@ -364,6 +366,29 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does + /// Checks for `.err().expect()` calls on the `Result` type. + /// + /// ### Why is this bad? + /// `.expect_err()` can be called directly to avoid the extra type conversion from `err()`. + /// + /// ### Example + /// ```should_panic + /// let x: Result<u32, &str> = Ok(10); + /// x.err().expect("Testing err().expect()"); + /// ``` + /// Use instead: + /// ```should_panic + /// let x: Result<u32, &str> = Ok(10); + /// x.expect_err("Testing expect_err"); + /// ``` + #[clippy::version = "1.61.0"] + pub ERR_EXPECT, + style, + r#"using `.err().expect("")` when `.expect_err("")` can be used"# +} + +declare_clippy_lint! { + /// ### What it does /// Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and /// `Result` values. /// @@ -2055,7 +2080,7 @@ declare_clippy_lint! { /// Checks for use of `.collect::<Vec<String>>().join("")` on iterators. /// /// ### Why is this bad? - /// `.collect::<String>()` is more concise and usually more performant + /// `.collect::<String>()` is more concise and might be more performant /// /// ### Example /// ```rust @@ -2070,15 +2095,42 @@ declare_clippy_lint! { /// println!("{}", output); /// ``` /// ### Known problems - /// While `.collect::<String>()` is more performant in most cases, there are cases where + /// While `.collect::<String>()` is sometimes more performant, there are cases where /// using `.collect::<String>()` over `.collect::<Vec<String>>().join("")` /// will prevent loop unrolling and will result in a negative performance impact. + /// + /// Additionlly, differences have been observed between aarch64 and x86_64 assembly output, + /// with aarch64 tending to producing faster assembly in more cases when using `.collect::<String>()` #[clippy::version = "1.61.0"] pub UNNECESSARY_JOIN, pedantic, "using `.collect::<Vec<String>>().join(\"\")` on an iterator" } +declare_clippy_lint! { + /// ### What it does + /// Checks for no-op uses of `Option::{as_deref, as_deref_mut}`, + /// for example, `Option<&T>::as_deref()` returns the same type. + /// + /// ### Why is this bad? + /// Redundant code and improving readability. + /// + /// ### Example + /// ```rust + /// let a = Some(&1); + /// let b = a.as_deref(); // goes from Option<&i32> to Option<&i32> + /// ``` + /// Could be written as: + /// ```rust + /// let a = Some(&1); + /// let b = a; + /// ``` + #[clippy::version = "1.57.0"] + pub NEEDLESS_OPTION_AS_DEREF, + complexity, + "no-op use of `deref` or `deref_mut` method to `Option`." +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Option<RustcVersion>, @@ -2165,6 +2217,8 @@ impl_lint_pass!(Methods => [ NEEDLESS_SPLITN, UNNECESSARY_TO_OWNED, UNNECESSARY_JOIN, + ERR_EXPECT, + NEEDLESS_OPTION_AS_DEREF, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -2397,6 +2451,9 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio unnecessary_lazy_eval::check(cx, expr, recv, arg, "and"); } }, + ("as_deref" | "as_deref_mut", []) => { + needless_option_as_deref::check(cx, expr, recv, name); + }, ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv), ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv), ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv), @@ -2428,6 +2485,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio }, ("expect", [_]) => match method_call(recv) { Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv), + Some(("err", [recv], err_span)) => err_expect::check(cx, expr, recv, msrv, span, err_span), _ => expect_used::check(cx, expr, recv), }, ("extend", [arg]) => { @@ -2472,7 +2530,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio } } }, - ("map", [m_arg]) => { + (name @ ("map" | "map_err"), [m_arg]) => { if let Some((name, [recv2, args @ ..], span2)) = method_call(recv) { match (name, args) { ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, msrv), @@ -2484,7 +2542,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio _ => {}, } } - map_identity::check(cx, expr, recv, m_arg, span); + map_identity::check(cx, expr, recv, m_arg, name, span); }, ("map_or", [def, map]) => option_map_or_none::check(cx, expr, recv, def, map), (name @ "next", args @ []) => { diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs b/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs new file mode 100644 index 00000000000..7030baf19ff --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs @@ -0,0 +1,37 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::path_res; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::usage::local_used_after_expr; +use rustc_errors::Applicability; +use rustc_hir::def::Res; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_span::sym; + +use super::NEEDLESS_OPTION_AS_DEREF; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name: &str) { + let typeck = cx.typeck_results(); + let outer_ty = typeck.expr_ty(expr); + + if is_type_diagnostic_item(cx, outer_ty, sym::Option) && outer_ty == typeck.expr_ty(recv) { + if name == "as_deref_mut" && recv.is_syntactic_place_expr() { + let Res::Local(binding_id) = path_res(cx, recv) else { return }; + + if local_used_after_expr(cx, binding_id, recv) { + return; + } + } + + span_lint_and_sugg( + cx, + NEEDLESS_OPTION_AS_DEREF, + expr.span, + "derefed type is same as origin", + "try this", + snippet_opt(cx, recv.span).unwrap(), + Applicability::MachineApplicable, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs index b8dfe996880..0a393657267 100644 --- a/src/tools/clippy/clippy_lints/src/module_style.rs +++ b/src/tools/clippy/clippy_lints/src/module_style.rs @@ -1,17 +1,14 @@ -use std::{ - ffi::OsString, - path::{Component, Path}, -}; - use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{FileName, RealFileName, SourceFile, Span, SyntaxContext}; +use std::ffi::OsStr; +use std::path::{Component, Path}; declare_clippy_lint! { /// ### What it does - /// Checks that module layout uses only self named module files, bans mod.rs files. + /// Checks that module layout uses only self named module files, bans `mod.rs` files. /// /// ### Why is this bad? /// Having multiple module layout styles in a project can be confusing. @@ -40,7 +37,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks that module layout uses only mod.rs files. + /// Checks that module layout uses only `mod.rs` files. /// /// ### Why is this bad? /// Having multiple module layout styles in a project can be confusing. @@ -82,11 +79,7 @@ impl EarlyLintPass for ModStyle { let files = cx.sess().source_map().files(); - let trim_to_src = if let RealFileName::LocalPath(p) = &cx.sess().opts.working_dir { - p.to_string_lossy() - } else { - return; - }; + let RealFileName::LocalPath(trim_to_src) = &cx.sess().opts.working_dir else { return }; // `folder_segments` is all unique folder path segments `path/to/foo.rs` gives // `[path, to]` but not foo @@ -97,26 +90,27 @@ impl EarlyLintPass for ModStyle { // `{ foo => path/to/foo.rs, .. } let mut file_map = FxHashMap::default(); for file in files.iter() { - match &file.name { - FileName::Real(RealFileName::LocalPath(lp)) - if lp.to_string_lossy().starts_with(trim_to_src.as_ref()) => - { - let p = lp.to_string_lossy(); - let path = Path::new(p.trim_start_matches(trim_to_src.as_ref())); - if let Some(stem) = path.file_stem() { - file_map.insert(stem.to_os_string(), (file, path.to_owned())); - } - process_paths_for_mod_files(path, &mut folder_segments, &mut mod_folders); - check_self_named_mod_exists(cx, path, file); - }, - _ => {}, + if let FileName::Real(RealFileName::LocalPath(lp)) = &file.name { + let path = if lp.is_relative() { + lp + } else if let Ok(relative) = lp.strip_prefix(trim_to_src) { + relative + } else { + continue; + }; + + if let Some(stem) = path.file_stem() { + file_map.insert(stem, (file, path)); + } + process_paths_for_mod_files(path, &mut folder_segments, &mut mod_folders); + check_self_named_mod_exists(cx, path, file); } } for folder in &folder_segments { if !mod_folders.contains(folder) { if let Some((file, path)) = file_map.get(folder) { - let mut correct = path.clone(); + let mut correct = path.to_path_buf(); correct.pop(); correct.push(folder); correct.push("mod.rs"); @@ -138,25 +132,17 @@ impl EarlyLintPass for ModStyle { /// For each `path` we add each folder component to `folder_segments` and if the file name /// is `mod.rs` we add it's parent folder to `mod_folders`. -fn process_paths_for_mod_files( - path: &Path, - folder_segments: &mut FxHashSet<OsString>, - mod_folders: &mut FxHashSet<OsString>, +fn process_paths_for_mod_files<'a>( + path: &'a Path, + folder_segments: &mut FxHashSet<&'a OsStr>, + mod_folders: &mut FxHashSet<&'a OsStr>, ) { let mut comp = path.components().rev().peekable(); let _ = comp.next(); if path.ends_with("mod.rs") { - mod_folders.insert(comp.peek().map(|c| c.as_os_str().to_owned()).unwrap_or_default()); + mod_folders.insert(comp.peek().map(|c| c.as_os_str()).unwrap_or_default()); } - let folders = comp - .filter_map(|c| { - if let Component::Normal(s) = c { - Some(s.to_os_string()) - } else { - None - } - }) - .collect::<Vec<_>>(); + let folders = comp.filter_map(|c| if let Component::Normal(s) = c { Some(s) } else { None }); folder_segments.extend(folders); } diff --git a/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs b/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs deleted file mode 100644 index 9d3d7d1f24c..00000000000 --- a/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs +++ /dev/null @@ -1,65 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; -use clippy_utils::ty::is_type_diagnostic_item; -use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::symbol::sym; - -declare_clippy_lint! { - /// ### What it does - /// Checks for no-op uses of Option::{as_deref,as_deref_mut}, - /// for example, `Option<&T>::as_deref()` returns the same type. - /// - /// ### Why is this bad? - /// Redundant code and improving readability. - /// - /// ### Example - /// ```rust - /// let a = Some(&1); - /// let b = a.as_deref(); // goes from Option<&i32> to Option<&i32> - /// ``` - /// Could be written as: - /// ```rust - /// let a = Some(&1); - /// let b = a; - /// ``` - #[clippy::version = "1.57.0"] - pub NEEDLESS_OPTION_AS_DEREF, - complexity, - "no-op use of `deref` or `deref_mut` method to `Option`." -} - -declare_lint_pass!(OptionNeedlessDeref=> [ - NEEDLESS_OPTION_AS_DEREF, -]); - -impl<'tcx> LateLintPass<'tcx> for OptionNeedlessDeref { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if expr.span.from_expansion() { - return; - } - let typeck = cx.typeck_results(); - let outer_ty = typeck.expr_ty(expr); - - if_chain! { - if is_type_diagnostic_item(cx,outer_ty,sym::Option); - if let ExprKind::MethodCall(path, [sub_expr], _) = expr.kind; - let symbol = path.ident.as_str(); - if symbol == "as_deref" || symbol == "as_deref_mut"; - if outer_ty == typeck.expr_ty(sub_expr); - then{ - span_lint_and_sugg( - cx, - NEEDLESS_OPTION_AS_DEREF, - expr.span, - "derefed type is same as origin", - "try this", - snippet_opt(cx,sub_expr.span).unwrap(), - Applicability::MachineApplicable - ); - } - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs index 6ef6b9a20aa..2f3007658ea 100644 --- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs +++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs @@ -78,6 +78,10 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return }; if is_panic(cx, macro_call.def_id) { + if cx.tcx.hir().is_inside_const_context(expr.hir_id) { + return; + } + span_lint( cx, PANIC, diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 5f453dc1655..48a2666a2e0 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -601,9 +601,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: }, // If the types match check for methods which exist on both types. e.g. `Vec::len` and // `slice::len` - ty::Adt(def, _) - if def.did() == args.ty_did => - { + ty::Adt(def, _) if def.did() == args.ty_did => { set_skip_flag(); }, _ => (), diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 02569bd3a47..342f23f030c 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -410,9 +410,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if cx.tcx.is_diagnostic_item(sym::transmute, def_id); then { - // Avoid suggesting from/to bits and dereferencing raw pointers in const contexts. - // See https://github.com/rust-lang/rust/issues/73736 for progress on making them `const fn`. - // And see https://github.com/rust-lang/rust/issues/51911 for dereferencing raw pointers. + // Avoid suggesting non-const operations in const contexts: + // - from/to bits (https://github.com/rust-lang/rust/issues/73736) + // - dereferencing raw pointers (https://github.com/rust-lang/rust/issues/51911) + // - char conversions (https://github.com/rust-lang/rust/issues/89259) let const_context = in_constant(cx, e.hir_id); let from_ty = cx.typeck_results().expr_ty_adjusted(arg); @@ -427,7 +428,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let linted = wrong_transmute::check(cx, e, from_ty, to_ty) | crosspointer_transmute::check(cx, e, from_ty, to_ty) | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, qpath) - | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg) + | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg) | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs index 3eb07b68992..9e1823c373b 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs @@ -15,9 +15,10 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, + const_context: bool, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::Int(ty::IntTy::I32) | ty::Uint(ty::UintTy::U32), &ty::Char) => { + (ty::Int(ty::IntTy::I32) | ty::Uint(ty::UintTy::U32), &ty::Char) if !const_context => { span_lint_and_then( cx, TRANSMUTE_INT_TO_CHAR, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 7570bc2a7a8..786e7bfc56f 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -32,18 +32,20 @@ pub(super) fn check<'tcx>( "" }; + let snippet = snippet(cx, arg.span, ".."); + span_lint_and_sugg( cx, TRANSMUTE_BYTES_TO_STR, e.span, &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), "consider using", - format!( - "std::str::from_utf8{}({}).unwrap()", - postfix, - snippet(cx, arg.span, ".."), - ), - Applicability::Unspecified, + if const_context { + format!("std::str::from_utf8_unchecked{postfix}({snippet})") + } else { + format!("std::str::from_utf8{postfix}({snippet}).unwrap()") + }, + Applicability::MaybeIncorrect, ); triggered = true; } else { diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index e42c6c63ede..c8912a18f18 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -1,16 +1,13 @@ -use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_lint_allowed; -use clippy_utils::source::{indent_of, reindent_multiline, snippet}; -use rustc_errors::Applicability; -use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, HirId, Local, UnsafeSource}; -use rustc_lexer::TokenKind; -use rustc_lint::{LateContext, LateLintPass}; +use clippy_utils::source::walk_span_to_context; +use rustc_data_structures::sync::Lrc; +use rustc_hir::{Block, BlockCheckMode, UnsafeSource}; +use rustc_lexer::{tokenize, TokenKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::TyCtxt; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{BytePos, Span}; -use std::borrow::Cow; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{BytePos, Pos, SyntaxContext}; declare_clippy_lint! { /// ### What it does @@ -18,6 +15,24 @@ declare_clippy_lint! { /// explaining why the unsafe operations performed inside /// the block are safe. /// + /// Note the comment must appear on the line(s) preceding the unsafe block + /// with nothing appearing in between. The following is ok: + /// ```ignore + /// foo( + /// // SAFETY: + /// // This is a valid safety comment + /// unsafe { *x } + /// ) + /// ``` + /// But neither of these are: + /// ```ignore + /// // SAFETY: + /// // This is not a valid safety comment + /// foo( + /// /* SAFETY: Neither is this */ unsafe { *x }, + /// ); + /// ``` + /// /// ### Why is this bad? /// Undocumented unsafe blocks can make it difficult to /// read and maintain code, as well as uncover unsoundness @@ -44,179 +59,139 @@ declare_clippy_lint! { "creating an unsafe block without explaining why it is safe" } -impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS]); - -#[derive(Default)] -pub struct UndocumentedUnsafeBlocks { - pub local_level: u32, - pub local_span: Option<Span>, - // The local was already checked for an overall safety comment - // There is no need to continue checking the blocks in the local - pub local_checked: bool, - // Since we can only check the blocks from expanded macros - // We have to omit the suggestion due to the actual definition - // Not being available to us - pub macro_expansion: bool, -} +declare_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS]); impl LateLintPass<'_> for UndocumentedUnsafeBlocks { fn check_block(&mut self, cx: &LateContext<'_>, block: &'_ Block<'_>) { - if_chain! { - if !self.local_checked; - if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id); - if !in_external_macro(cx.tcx.sess, block.span); - if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules; - if let Some(enclosing_scope_hir_id) = cx.tcx.hir().get_enclosing_scope(block.hir_id); - if self.block_has_safety_comment(cx.tcx, enclosing_scope_hir_id, block.span) == Some(false); - then { - let mut span = block.span; - - if let Some(local_span) = self.local_span { - span = local_span; - - let result = self.block_has_safety_comment(cx.tcx, enclosing_scope_hir_id, span); + if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) + && !in_external_macro(cx.tcx.sess, block.span) + && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id) + && !is_unsafe_from_proc_macro(cx, block) + && !block_has_safety_comment(cx, block) + { + let source_map = cx.tcx.sess.source_map(); + let span = if source_map.is_multiline(block.span) { + source_map.span_until_char(block.span, '\n') + } else { + block.span + }; - if result.unwrap_or(true) { - self.local_checked = true; - return; - } - } - - self.lint(cx, span); - } - } - } - - fn check_local(&mut self, cx: &LateContext<'_>, local: &'_ Local<'_>) { - if_chain! { - if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, local.hir_id); - if !in_external_macro(cx.tcx.sess, local.span); - if let Some(init) = local.init; - then { - self.visit_expr(init); - - if self.local_level > 0 { - self.local_span = Some(local.span); - } - } + span_lint_and_help( + cx, + UNDOCUMENTED_UNSAFE_BLOCKS, + span, + "unsafe block missing a safety comment", + None, + "consider adding a safety comment on the preceding line", + ); } } +} - fn check_block_post(&mut self, _: &LateContext<'_>, _: &'_ Block<'_>) { - self.local_level = self.local_level.saturating_sub(1); - - if self.local_level == 0 { - self.local_checked = false; - self.local_span = None; - } - } +fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, block: &Block<'_>) -> bool { + let source_map = cx.sess().source_map(); + let file_pos = source_map.lookup_byte_offset(block.span.lo()); + file_pos + .sf + .src + .as_deref() + .and_then(|src| src.get(file_pos.pos.to_usize()..)) + .map_or(true, |src| !src.starts_with("unsafe")) } -impl<'v> Visitor<'v> for UndocumentedUnsafeBlocks { - fn visit_expr(&mut self, ex: &'v Expr<'v>) { - match ex.kind { - ExprKind::Block(_, _) => self.local_level = self.local_level.saturating_add(1), - _ => walk_expr(self, ex), +/// Checks if the lines immediately preceding the block contain a safety comment. +fn block_has_safety_comment(cx: &LateContext<'_>, block: &Block<'_>) -> bool { + // This intentionally ignores text before the start of a function so something like: + // ``` + // // SAFETY: reason + // fn foo() { unsafe { .. } } + // ``` + // won't work. This is to avoid dealing with where such a comment should be place relative to + // attributes and doc comments. + + let source_map = cx.sess().source_map(); + let ctxt = block.span.ctxt(); + if ctxt != SyntaxContext::root() { + // From a macro expansion. Get the text from the start of the macro declaration to start of the unsafe block. + // macro_rules! foo { () => { stuff }; (x) => { unsafe { stuff } }; } + // ^--------------------------------------------^ + if let Ok(unsafe_line) = source_map.lookup_line(block.span.lo()) + && let Ok(macro_line) = source_map.lookup_line(ctxt.outer_expn_data().def_site.lo()) + && Lrc::ptr_eq(&unsafe_line.sf, ¯o_line.sf) + && let Some(src) = unsafe_line.sf.src.as_deref() + { + macro_line.line < unsafe_line.line && text_has_safety_comment( + src, + &unsafe_line.sf.lines[macro_line.line + 1..=unsafe_line.line], + unsafe_line.sf.start_pos.to_usize(), + ) + } else { + // Problem getting source text. Pretend a comment was found. + true } + } else if let Ok(unsafe_line) = source_map.lookup_line(block.span.lo()) + && let Some(body) = cx.enclosing_body + && let Some(body_span) = walk_span_to_context(cx.tcx.hir().body(body).value.span, SyntaxContext::root()) + && let Ok(body_line) = source_map.lookup_line(body_span.lo()) + && Lrc::ptr_eq(&unsafe_line.sf, &body_line.sf) + && let Some(src) = unsafe_line.sf.src.as_deref() + { + // Get the text from the start of function body to the unsafe block. + // fn foo() { some_stuff; unsafe { stuff }; other_stuff; } + // ^-------------^ + body_line.line < unsafe_line.line && text_has_safety_comment( + src, + &unsafe_line.sf.lines[body_line.line + 1..=unsafe_line.line], + unsafe_line.sf.start_pos.to_usize(), + ) + } else { + // Problem getting source text. Pretend a comment was found. + true } } -impl UndocumentedUnsafeBlocks { - fn block_has_safety_comment(&mut self, tcx: TyCtxt<'_>, enclosing_hir_id: HirId, block_span: Span) -> Option<bool> { - let map = tcx.hir(); - let source_map = tcx.sess.source_map(); - - let enclosing_scope_span = map.opt_span(enclosing_hir_id)?; - - let between_span = if block_span.from_expansion() { - self.macro_expansion = true; - enclosing_scope_span.with_hi(block_span.hi()).source_callsite() - } else { - self.macro_expansion = false; - enclosing_scope_span.to(block_span).source_callsite() - }; - - let file_name = source_map.span_to_filename(between_span); - let source_file = source_map.get_source_file(&file_name)?; - - let lex_start = (between_span.lo().0 - source_file.start_pos.0 + 1) as usize; - let lex_end = (between_span.hi().0 - source_file.start_pos.0) as usize; - let src_str = source_file.src.as_ref()?[lex_start..lex_end].to_string(); - - let source_start_pos = source_file.start_pos.0 as usize + lex_start; - - let mut pos = 0; - let mut comment = false; - - for token in rustc_lexer::tokenize(&src_str) { - match token.kind { - TokenKind::LineComment { doc_style: None } - | TokenKind::BlockComment { - doc_style: None, - terminated: true, - } => { - let comment_str = src_str[pos + 2..pos + token.len].to_ascii_uppercase(); - - if comment_str.contains("SAFETY:") { - comment = true; - } - }, - // We need to add all whitespace to `pos` before checking the comment's line number - TokenKind::Whitespace => {}, - _ => { - if comment { - // Get the line number of the "comment" (really wherever the trailing whitespace ended) - let comment_line_num = source_file - .lookup_file_pos(BytePos((source_start_pos + pos).try_into().unwrap())) - .0; - // Find the block/local's line number - let block_line_num = tcx.sess.source_map().lookup_char_pos(block_span.lo()).line; - - // Check the comment is immediately followed by the block/local - if block_line_num == comment_line_num + 1 || block_line_num == comment_line_num { - return Some(true); - } - - comment = false; - } - }, +/// Checks if the given text has a safety comment for the immediately proceeding line. +fn text_has_safety_comment(src: &str, line_starts: &[BytePos], offset: usize) -> bool { + let mut lines = line_starts + .array_windows::<2>() + .rev() + .map_while(|[start, end]| { + src.get(start.to_usize() - offset..end.to_usize() - offset) + .map(|text| (start.to_usize(), text.trim_start())) + }) + .filter(|(_, text)| !text.is_empty()); + + let Some((line_start, line)) = lines.next() else { + return false; + }; + // Check for a sequence of line comments. + if line.starts_with("//") { + let mut line = line; + loop { + if line.to_ascii_uppercase().contains("SAFETY:") { + return true; + } + match lines.next() { + Some((_, x)) if x.starts_with("//") => line = x, + _ => return false, } - - pos += token.len; } - - Some(false) } - - fn lint(&self, cx: &LateContext<'_>, mut span: Span) { - let source_map = cx.tcx.sess.source_map(); - - if source_map.is_multiline(span) { - span = source_map.span_until_char(span, '\n'); + // No line comments; look for the start of a block comment. + // This will only find them if they are at the start of a line. + let (mut line_start, mut line) = (line_start, line); + loop { + if line.starts_with("/*") { + let src = src[line_start..line_starts.last().unwrap().to_usize()].trim_start(); + let mut tokens = tokenize(src); + return src[..tokens.next().unwrap().len] + .to_ascii_uppercase() + .contains("SAFETY:") + && tokens.all(|t| t.kind == TokenKind::Whitespace); } - - if self.macro_expansion { - span_lint_and_help( - cx, - UNDOCUMENTED_UNSAFE_BLOCKS, - span, - "unsafe block in macro expansion missing a safety comment", - None, - "consider adding a safety comment in the macro definition", - ); - } else { - let block_indent = indent_of(cx, span); - let suggestion = format!("// SAFETY: ...\n{}", snippet(cx, span, "..")); - - span_lint_and_sugg( - cx, - UNDOCUMENTED_UNSAFE_BLOCKS, - span, - "unsafe block missing a safety comment", - "consider adding a safety comment", - reindent_multiline(Cow::Borrowed(&suggestion), true, block_indent).to_string(), - Applicability::HasPlaceholders, - ); + match lines.next() { + Some(x) => (line_start, line) = x, + None => return false, } } } diff --git a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs deleted file mode 100644 index db652766705..00000000000 --- a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs +++ /dev/null @@ -1,59 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::path_res; -use clippy_utils::ty::is_type_lang_item; -use rustc_hir::{lang_items, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; - -declare_clippy_lint! { - /// ### What it does - /// Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`. - /// - /// ### Why is this bad? - /// The safe `drop` function does not drop the inner value of a `ManuallyDrop`. - /// - /// ### Known problems - /// Does not catch cases if the user binds `std::mem::drop` - /// to a different name and calls it that way. - /// - /// ### Example - /// ```rust - /// struct S; - /// drop(std::mem::ManuallyDrop::new(S)); - /// ``` - /// Use instead: - /// ```rust - /// struct S; - /// unsafe { - /// std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S)); - /// } - /// ``` - #[clippy::version = "1.49.0"] - pub UNDROPPED_MANUALLY_DROPS, - correctness, - "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value" -} - -declare_lint_pass!(UndroppedManuallyDrops => [UNDROPPED_MANUALLY_DROPS]); - -impl<'tcx> LateLintPass<'tcx> for UndroppedManuallyDrops { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(fun, [arg_0, ..]) = expr.kind; - if path_res(cx, fun).opt_def_id() == cx.tcx.get_diagnostic_item(sym::mem_drop); - let ty = cx.typeck_results().expr_ty(arg_0); - if is_type_lang_item(cx, ty, lang_items::LangItem::ManuallyDrop); - then { - span_lint_and_help( - cx, - UNDROPPED_MANUALLY_DROPS, - expr.span, - "the inner value of this ManuallyDrop will not be dropped", - None, - "to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop", - ); - } - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 09d671e1118..f8e1021af0e 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -34,7 +34,7 @@ declare_clippy_lint! { /// /// ### Example /// ```rust - /// struct Foo {} + /// struct Foo; /// impl Foo { /// fn new() -> Foo { /// Foo {} @@ -43,7 +43,7 @@ declare_clippy_lint! { /// ``` /// could be /// ```rust - /// struct Foo {} + /// struct Foo; /// impl Foo { /// fn new() -> Self { /// Self {} diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index 680b2eb1da7..271c3a3dd18 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -156,7 +156,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED. /// /// The minimum rust version that the project supports (msrv: Option<String> = None), diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index b3b241392fe..25d74b8c499 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -25,7 +25,7 @@ use rustc_hir::{ use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; use rustc_middle::mir::interpret::ConstValue; -use rustc_middle::ty::{self, subst::GenericArgKind}; +use rustc_middle::ty::{self, fast_reject::SimplifiedTypeGen, subst::GenericArgKind, FloatTy}; use rustc_semver::RustcVersion; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Spanned; @@ -889,7 +889,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve } } }, - Res::Def(DefKind::Const | DefKind::Static, def_id) => { + Res::Def(DefKind::Const | DefKind::Static(..), def_id) => { if let Some(Node::Item(item)) = cx.tcx.hir().get_if_local(def_id) { if let ItemKind::Const(.., body_id) | ItemKind::Static(.., body_id) = item.kind { let body = cx.tcx.hir().body(body_id); @@ -934,7 +934,16 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool { // implementations of native types. Check lang items. let path_syms: Vec<_> = path.iter().map(|p| Symbol::intern(p)).collect(); let lang_items = cx.tcx.lang_items(); - for item_def_id in lang_items.items().iter().flatten() { + // This list isn't complete, but good enough for our current list of paths. + let incoherent_impls = [ + SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F32), + SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F64), + SimplifiedTypeGen::SliceSimplifiedType, + SimplifiedTypeGen::StrSimplifiedType, + ] + .iter() + .flat_map(|&ty| cx.tcx.incoherent_impls(ty)); + for item_def_id in lang_items.items().iter().flatten().chain(incoherent_impls) { let lang_item_path = cx.get_def_path(*item_def_id); if path_syms.starts_with(&lang_item_path) { if let [item] = &path_syms[lang_item_path.len()..] { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index b3fad6ce7b6..ca03b8010dd 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -756,7 +756,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> { let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); if match_type(self.cx, expr_ty, &paths::LINT); then { - if let hir::def::Res::Def(DefKind::Static, _) = path.res { + if let hir::def::Res::Def(DefKind::Static(..), _) = path.res { let lint_name = last_path_segment(qpath).ident.name; self.lints.push(sym_to_string(lint_name).to_ascii_lowercase()); } else if let Some(local) = get_parent_local(self.cx, expr) { diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index d3ed8da4499..0b1fd95c345 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.61" +version = "0.1.62" edition = "2021" publish = false diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 62e14439801..a275bac4ce6 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -77,19 +77,22 @@ use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; use rustc_hir::{ - def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, - ExprKind, FnDecl, ForeignItem, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, - MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, - TraitItem, TraitItemKind, TraitRef, TyKind, UnOp, + def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, FnDecl, + ForeignItem, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, + Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, + TraitRef, TyKind, UnOp, }; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; use rustc_middle::ty as rustc_ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::binding::BindingMode; -use rustc_middle::ty::{IntTy, UintTy, FloatTy}; -use rustc_middle::ty::fast_reject::SimplifiedTypeGen::*; +use rustc_middle::ty::fast_reject::SimplifiedTypeGen::{ + ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType, + PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType, +}; use rustc_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeFoldable, UpvarCapture}; +use rustc_middle::ty::{FloatTy, IntTy, UintTy}; use rustc_semver::RustcVersion; use rustc_session::Session; use rustc_span::hygiene::{ExpnKind, MacroKind}; @@ -522,7 +525,7 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res { let tcx = cx.tcx; let starts = find_primitive(tcx, base) .chain(find_crate(tcx, base)) - .flat_map(|id| item_child_by_name(tcx, id, first)); + .filter_map(|id| item_child_by_name(tcx, id, first)); for first in starts { let last = path diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index fce93153d96..0424e067202 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -14,7 +14,7 @@ macro_rules! msrv_aliases { msrv_aliases! { 1,53,0 { OR_PATTERNS, MANUAL_BITS } 1,52,0 { STR_SPLIT_ONCE } - 1,51,0 { BORROW_AS_PTR } + 1,51,0 { BORROW_AS_PTR, UNSIGNED_ABS } 1,50,0 { BOOL_THEN } 1,47,0 { TAU } 1,46,0 { CONST_IF_MATCH } @@ -30,6 +30,6 @@ msrv_aliases! { 1,34,0 { TRY_FROM } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,28,0 { FROM_BOOL } - 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST } + 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR } 1,16,0 { STR_REPEAT } } diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index 6f56f8d5136..79e6e92dc0a 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -105,6 +105,8 @@ pub const PTR_READ_UNALIGNED: [&str; 3] = ["core", "ptr", "read_unaligned"]; pub const PTR_READ_VOLATILE: [&str; 3] = ["core", "ptr", "read_volatile"]; pub const PTR_REPLACE: [&str; 3] = ["core", "ptr", "replace"]; pub const PTR_SWAP: [&str; 3] = ["core", "ptr", "swap"]; +pub const PTR_UNALIGNED_VOLATILE_LOAD: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_load"]; +pub const PTR_UNALIGNED_VOLATILE_STORE: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_store"]; pub const PTR_WRITE: [&str; 3] = ["core", "ptr", "write"]; pub const PTR_WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"]; pub const PTR_WRITE_UNALIGNED: [&str; 3] = ["core", "ptr", "write_unaligned"]; diff --git a/src/tools/clippy/doc/release.md b/src/tools/clippy/doc/release.md index afe3033c288..c4f8f989384 100644 --- a/src/tools/clippy/doc/release.md +++ b/src/tools/clippy/doc/release.md @@ -121,4 +121,25 @@ happened a stable backport, make sure to re-merge those changes just as with the For this see the document on [how to update the changelog]. +If you don't have time to do a complete changelog update right away, just update +the following parts: + +- Remove the `(beta)` from the new stable version: + + ```markdown + ## Rust 1.XX (beta) -> ## Rust 1.XX + ``` + +- Update the release date line of the new stable version: + + ```markdown + Current beta, release 20YY-MM-DD -> Current stable, released 20YY-MM-DD + ``` + +- Update the release date line of the previous stable version: + + ```markdown + Current stable, released 20YY-MM-DD -> Released 20YY-MM-DD + ``` + [how to update the changelog]: https://github.com/rust-lang/rust-clippy/blob/master/doc/changelog_update.md diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 5befb856a02..bb29c71e9f4 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-03-24" +channel = "nightly-2022-04-07" components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index bc1b0d74575..00dc916b217 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -165,8 +165,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { // Separate the output with an empty line eprintln!(); - let fallback_bundle = rustc_errors::fallback_fluent_bundle(false) - .expect("failed to load fallback fluent bundle"); + let fallback_bundle = rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle"); let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( rustc_errors::ColorConfig::Auto, None, diff --git a/src/tools/clippy/tests/fmt.rs b/src/tools/clippy/tests/check-fmt.rs index 0defd45b68b..0defd45b68b 100644 --- a/src/tools/clippy/tests/fmt.rs +++ b/src/tools/clippy/tests/check-fmt.rs diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr index af4c298b310..e2010e99813 100644 --- a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr +++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr @@ -1,19 +1,19 @@ -error: `mod.rs` files are required, found `/bad/inner.rs` +error: `mod.rs` files are required, found `bad/inner.rs` --> $DIR/bad/inner.rs:1:1 | LL | pub mod stuff; | ^ | = note: `-D clippy::self-named-module-files` implied by `-D warnings` - = help: move `/bad/inner.rs` to `/bad/inner/mod.rs` + = help: move `bad/inner.rs` to `bad/inner/mod.rs` -error: `mod.rs` files are required, found `/bad/inner/stuff.rs` +error: `mod.rs` files are required, found `bad/inner/stuff.rs` --> $DIR/bad/inner/stuff.rs:1:1 | LL | pub mod most; | ^ | - = help: move `/bad/inner/stuff.rs` to `/bad/inner/stuff/mod.rs` + = help: move `bad/inner/stuff.rs` to `bad/inner/stuff/mod.rs` error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr index 11e15db7fb9..f9194020938 100644 --- a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr +++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr @@ -1,11 +1,11 @@ -error: `mod.rs` files are not allowed, found `/bad/mod.rs` +error: `mod.rs` files are not allowed, found `bad/mod.rs` --> $DIR/bad/mod.rs:1:1 | LL | pub struct Thing; | ^ | = note: `-D clippy::mod-module-files` implied by `-D warnings` - = help: move `/bad/mod.rs` to `/bad.rs` + = help: move `bad/mod.rs` to `bad.rs` error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr index 9302e02ccb9..67e1a07b7f5 100644 --- a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr +++ b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr @@ -46,11 +46,6 @@ LL | | report_in_external_macro: true LL | | } | |_^ | -note: the lint level is defined here - --> $DIR/check_clippy_version_attribute.rs:1:9 - | -LL | #![deny(clippy::internal)] - | ^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::missing_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]` = help: please use a `clippy::version` attribute, see `doc/adding_lints.md` = note: this error originates in the macro `$crate::declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.rs b/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.rs index 242984680e1..32dd80246fa 100644 --- a/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.rs +++ b/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.rs @@ -4,6 +4,6 @@ struct S { a: bool, } -struct Foo {} +struct Foo; fn main() {} diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs new file mode 100644 index 00000000000..3c40f77469b --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs @@ -0,0 +1,18 @@ +// compile-flags: --emit=link +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree}; + +#[proc_macro] +pub fn unsafe_block(input: TokenStream) -> TokenStream { + let span = input.into_iter().next().unwrap().span(); + TokenStream::from_iter([TokenTree::Ident(Ident::new("unsafe", span)), { + let mut group = Group::new(Delimiter::Brace, TokenStream::new()); + group.set_span(span); + TokenTree::Group(group) + }]) +} diff --git a/src/tools/clippy/tests/ui/bytes_nth.stderr b/src/tools/clippy/tests/ui/bytes_nth.stderr index 8a7afa93450..9851d4791d8 100644 --- a/src/tools/clippy/tests/ui/bytes_nth.stderr +++ b/src/tools/clippy/tests/ui/bytes_nth.stderr @@ -1,4 +1,4 @@ -error: called `.byte().nth()` on a `String` +error: called `.bytes().nth()` on a `String` --> $DIR/bytes_nth.rs:8:13 | LL | let _ = s.bytes().nth(3); @@ -6,13 +6,13 @@ LL | let _ = s.bytes().nth(3); | = note: `-D clippy::bytes-nth` implied by `-D warnings` -error: called `.byte().nth()` on a `String` +error: called `.bytes().nth()` on a `String` --> $DIR/bytes_nth.rs:9:14 | LL | let _ = &s.bytes().nth(3); | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)` -error: called `.byte().nth()` on a `str` +error: called `.bytes().nth()` on a `str` --> $DIR/bytes_nth.rs:10:13 | LL | let _ = s[..].bytes().nth(3); diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs index 68719c2bc6d..0d65071af15 100644 --- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs +++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs @@ -2,7 +2,7 @@ use std::string::String; -struct TestStruct {} +struct TestStruct; impl TestStruct { fn ends_with(self, arg: &str) {} diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs index 2e31ad3172e..cf85a5ca931 100644 --- a/src/tools/clippy/tests/ui/cast.rs +++ b/src/tools/clippy/tests/ui/cast.rs @@ -7,7 +7,7 @@ clippy::cast_sign_loss, clippy::cast_possible_wrap )] -#[allow(clippy::no_effect, clippy::unnecessary_operation)] +#[allow(clippy::cast_abs_to_unsigned, clippy::no_effect, clippy::unnecessary_operation)] fn main() { // Test clippy::cast_precision_loss let x0 = 1i32; diff --git a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed new file mode 100644 index 00000000000..4ec2465be06 --- /dev/null +++ b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed @@ -0,0 +1,8 @@ +// run-rustfix +#![warn(clippy::cast_abs_to_unsigned)] + +fn main() { + let x: i32 = -42; + let y: u32 = x.unsigned_abs(); + println!("The absolute value of {} is {}", x, y); +} diff --git a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs new file mode 100644 index 00000000000..59b9c8c3678 --- /dev/null +++ b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs @@ -0,0 +1,8 @@ +// run-rustfix +#![warn(clippy::cast_abs_to_unsigned)] + +fn main() { + let x: i32 = -42; + let y: u32 = x.abs() as u32; + println!("The absolute value of {} is {}", x, y); +} diff --git a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.stderr b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.stderr new file mode 100644 index 00000000000..eb12857357a --- /dev/null +++ b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.stderr @@ -0,0 +1,10 @@ +error: casting the result of `i32::abs()` to u32 + --> $DIR/cast_abs_to_unsigned.rs:6:18 + | +LL | let y: u32 = x.abs() as u32; + | ^^^^^^^^^^^^^^ help: replace with: `x.unsigned_abs()` + | + = note: `-D clippy::cast-abs-to-unsigned` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/cast_alignment.rs b/src/tools/clippy/tests/ui/cast_alignment.rs index 659591fffbe..e4e7290a30e 100644 --- a/src/tools/clippy/tests/ui/cast_alignment.rs +++ b/src/tools/clippy/tests/ui/cast_alignment.rs @@ -1,6 +1,7 @@ //! Test casts for alignment issues #![feature(rustc_private)] +#![feature(core_intrinsics)] extern crate libc; #[warn(clippy::cast_ptr_alignment)] @@ -34,4 +35,17 @@ fn main() { (&1u32 as *const u32 as *const libc::c_void) as *const u32; // For ZST, we should trust the user. See #4256 (&1u32 as *const u32 as *const ()) as *const u32; + + // Issue #2881 + let mut data = [0u8, 0u8]; + unsafe { + let ptr = &data as *const [u8; 2] as *const u8; + let _ = (ptr as *const u16).read_unaligned(); + let _ = core::ptr::read_unaligned(ptr as *const u16); + let _ = core::intrinsics::unaligned_volatile_load(ptr as *const u16); + let ptr = &mut data as *mut [u8; 2] as *mut u8; + let _ = (ptr as *mut u16).write_unaligned(0); + let _ = core::ptr::write_unaligned(ptr as *mut u16, 0); + let _ = core::intrinsics::unaligned_volatile_store(ptr as *mut u16, 0); + } } diff --git a/src/tools/clippy/tests/ui/cast_alignment.stderr b/src/tools/clippy/tests/ui/cast_alignment.stderr index aedd3684455..5df2b5b1094 100644 --- a/src/tools/clippy/tests/ui/cast_alignment.stderr +++ b/src/tools/clippy/tests/ui/cast_alignment.stderr @@ -1,5 +1,5 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes) - --> $DIR/cast_alignment.rs:18:5 + --> $DIR/cast_alignment.rs:19:5 | LL | (&1u8 as *const u8) as *const u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | (&1u8 as *const u8) as *const u16; = note: `-D clippy::cast-ptr-alignment` implied by `-D warnings` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes) - --> $DIR/cast_alignment.rs:19:5 + --> $DIR/cast_alignment.rs:20:5 | LL | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes) - --> $DIR/cast_alignment.rs:22:5 + --> $DIR/cast_alignment.rs:23:5 | LL | (&1u8 as *const u8).cast::<u16>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes) - --> $DIR/cast_alignment.rs:23:5 + --> $DIR/cast_alignment.rs:24:5 | LL | (&mut 1u8 as *mut u8).cast::<u16>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/crashes/ice-2774.rs b/src/tools/clippy/tests/ui/crashes/ice-2774.rs index d44b0fae820..88cfa1f923c 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-2774.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-2774.rs @@ -8,7 +8,7 @@ pub struct Bar { } #[derive(Eq, PartialEq, Debug, Hash)] -pub struct Foo {} +pub struct Foo; #[allow(clippy::implicit_hasher)] // This should not cause a "cannot relate bound region" ICE. diff --git a/src/tools/clippy/tests/ui/crashes/ice-6179.rs b/src/tools/clippy/tests/ui/crashes/ice-6179.rs index 8d9a1af8ff1..4fe92d356c4 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6179.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-6179.rs @@ -4,7 +4,7 @@ #![warn(clippy::use_self)] #![allow(dead_code)] -struct Foo {} +struct Foo; impl Foo { fn new() -> Self { diff --git a/src/tools/clippy/tests/ui/crashes/ice-6792.rs b/src/tools/clippy/tests/ui/crashes/ice-6792.rs index 0e2ab1a39b8..9cbafc716b5 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6792.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-6792.rs @@ -7,7 +7,7 @@ trait Trait { fn broken() -> Self::Ty; } -struct Foo {} +struct Foo; impl Trait for Foo { type Ty = Foo; diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr index 111350a6280..1a33e647588 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr @@ -5,11 +5,7 @@ LL | unsafe { 0 }; | ^^^^^^^^^^^^ | = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL ~ unsafe { 0 }; - | + = help: consider adding a safety comment on the preceding line error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.rs b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.rs index 676564b2445..376ff97ba60 100644 --- a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.rs +++ b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.rs @@ -3,7 +3,7 @@ trait Foo {} -struct Bar {} +struct Bar; struct Baz<'a> { bar: &'a Bar, diff --git a/src/tools/clippy/tests/ui/crashes/regressions.rs b/src/tools/clippy/tests/ui/crashes/regressions.rs index a41bcb33b44..6f9d98bbfe7 100644 --- a/src/tools/clippy/tests/ui/crashes/regressions.rs +++ b/src/tools/clippy/tests/ui/crashes/regressions.rs @@ -6,6 +6,6 @@ pub fn foo(bar: *const u8) { // Regression test for https://github.com/rust-lang/rust-clippy/issues/4917 /// <foo -struct A {} +struct A; fn main() {} diff --git a/src/tools/clippy/tests/ui/crate_in_macro_def.fixed b/src/tools/clippy/tests/ui/crate_in_macro_def.fixed new file mode 100644 index 00000000000..9fc594be311 --- /dev/null +++ b/src/tools/clippy/tests/ui/crate_in_macro_def.fixed @@ -0,0 +1,56 @@ +// run-rustfix +#![warn(clippy::crate_in_macro_def)] + +mod hygienic { + #[macro_export] + macro_rules! print_message_hygienic { + () => { + println!("{}", $crate::hygienic::MESSAGE); + }; + } + + pub const MESSAGE: &str = "Hello!"; +} + +mod unhygienic { + #[macro_export] + macro_rules! print_message_unhygienic { + () => { + println!("{}", $crate::unhygienic::MESSAGE); + }; + } + + pub const MESSAGE: &str = "Hello!"; +} + +mod unhygienic_intentionally { + // For cases where the use of `crate` is intentional, applying `allow` to the macro definition + // should suppress the lint. + #[allow(clippy::crate_in_macro_def)] + #[macro_export] + macro_rules! print_message_unhygienic_intentionally { + () => { + println!("{}", crate::CALLER_PROVIDED_MESSAGE); + }; + } +} + +#[macro_use] +mod not_exported { + macro_rules! print_message_not_exported { + () => { + println!("{}", crate::not_exported::MESSAGE); + }; + } + + pub const MESSAGE: &str = "Hello!"; +} + +fn main() { + print_message_hygienic!(); + print_message_unhygienic!(); + print_message_unhygienic_intentionally!(); + print_message_not_exported!(); +} + +pub const CALLER_PROVIDED_MESSAGE: &str = "Hello!"; diff --git a/src/tools/clippy/tests/ui/crate_in_macro_def.rs b/src/tools/clippy/tests/ui/crate_in_macro_def.rs new file mode 100644 index 00000000000..ac456108e4a --- /dev/null +++ b/src/tools/clippy/tests/ui/crate_in_macro_def.rs @@ -0,0 +1,56 @@ +// run-rustfix +#![warn(clippy::crate_in_macro_def)] + +mod hygienic { + #[macro_export] + macro_rules! print_message_hygienic { + () => { + println!("{}", $crate::hygienic::MESSAGE); + }; + } + + pub const MESSAGE: &str = "Hello!"; +} + +mod unhygienic { + #[macro_export] + macro_rules! print_message_unhygienic { + () => { + println!("{}", crate::unhygienic::MESSAGE); + }; + } + + pub const MESSAGE: &str = "Hello!"; +} + +mod unhygienic_intentionally { + // For cases where the use of `crate` is intentional, applying `allow` to the macro definition + // should suppress the lint. + #[allow(clippy::crate_in_macro_def)] + #[macro_export] + macro_rules! print_message_unhygienic_intentionally { + () => { + println!("{}", crate::CALLER_PROVIDED_MESSAGE); + }; + } +} + +#[macro_use] +mod not_exported { + macro_rules! print_message_not_exported { + () => { + println!("{}", crate::not_exported::MESSAGE); + }; + } + + pub const MESSAGE: &str = "Hello!"; +} + +fn main() { + print_message_hygienic!(); + print_message_unhygienic!(); + print_message_unhygienic_intentionally!(); + print_message_not_exported!(); +} + +pub const CALLER_PROVIDED_MESSAGE: &str = "Hello!"; diff --git a/src/tools/clippy/tests/ui/crate_in_macro_def.stderr b/src/tools/clippy/tests/ui/crate_in_macro_def.stderr new file mode 100644 index 00000000000..9ac5937dcc0 --- /dev/null +++ b/src/tools/clippy/tests/ui/crate_in_macro_def.stderr @@ -0,0 +1,10 @@ +error: `crate` references the macro call's crate + --> $DIR/crate_in_macro_def.rs:19:28 + | +LL | println!("{}", crate::unhygienic::MESSAGE); + | ^^^^^ help: to reference the macro definition's crate, use: `$crate` + | + = note: `-D clippy::crate-in-macro-def` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed index 1b0e7544e79..e0b4a2f6942 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed +++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed @@ -134,7 +134,7 @@ mod enum_ctor { } mod method_calls { - struct StructForMethodCallTest {} + struct StructForMethodCallTest; impl StructForMethodCallTest { fn concrete_arg(&self, f: f64) {} diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs index e9687777bbd..50bbb6eec6c 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs +++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs @@ -134,7 +134,7 @@ mod enum_ctor { } mod method_calls { - struct StructForMethodCallTest {} + struct StructForMethodCallTest; impl StructForMethodCallTest { fn concrete_arg(&self, f: f64) {} diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed index 55c082fcb19..bded9e2c0e8 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed +++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed @@ -133,7 +133,7 @@ mod enum_ctor { } mod method_calls { - struct StructForMethodCallTest {} + struct StructForMethodCallTest; impl StructForMethodCallTest { fn concrete_arg(&self, x: i32) {} diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs index e0a4828ce9f..3fceefa551c 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs +++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs @@ -133,7 +133,7 @@ mod enum_ctor { } mod method_calls { - struct StructForMethodCallTest {} + struct StructForMethodCallTest; impl StructForMethodCallTest { fn concrete_arg(&self, x: i32) {} diff --git a/src/tools/clippy/tests/ui/drop_forget_copy.rs b/src/tools/clippy/tests/ui/drop_forget_copy.rs index 9ddd6d64701..7c7a9ecff67 100644 --- a/src/tools/clippy/tests/ui/drop_forget_copy.rs +++ b/src/tools/clippy/tests/ui/drop_forget_copy.rs @@ -5,7 +5,7 @@ use std::mem::{drop, forget}; use std::vec::Vec; #[derive(Copy, Clone)] -struct SomeStruct {} +struct SomeStruct; struct AnotherStruct { x: u8, diff --git a/src/tools/clippy/tests/ui/drop_forget_copy.stderr b/src/tools/clippy/tests/ui/drop_forget_copy.stderr index 01de0be7cae..88228afae89 100644 --- a/src/tools/clippy/tests/ui/drop_forget_copy.stderr +++ b/src/tools/clippy/tests/ui/drop_forget_copy.stderr @@ -5,7 +5,7 @@ LL | drop(s1); | ^^^^^^^^ | = note: `-D clippy::drop-copy` implied by `-D warnings` -note: argument has type SomeStruct +note: argument has type `SomeStruct` --> $DIR/drop_forget_copy.rs:33:10 | LL | drop(s1); @@ -17,7 +17,7 @@ error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a LL | drop(s2); | ^^^^^^^^ | -note: argument has type SomeStruct +note: argument has type `SomeStruct` --> $DIR/drop_forget_copy.rs:34:10 | LL | drop(s2); @@ -29,7 +29,7 @@ error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a LL | drop(s4); | ^^^^^^^^ | -note: argument has type SomeStruct +note: argument has type `SomeStruct` --> $DIR/drop_forget_copy.rs:36:10 | LL | drop(s4); @@ -42,7 +42,7 @@ LL | forget(s1); | ^^^^^^^^^^ | = note: `-D clippy::forget-copy` implied by `-D warnings` -note: argument has type SomeStruct +note: argument has type `SomeStruct` --> $DIR/drop_forget_copy.rs:39:12 | LL | forget(s1); @@ -54,7 +54,7 @@ error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetti LL | forget(s2); | ^^^^^^^^^^ | -note: argument has type SomeStruct +note: argument has type `SomeStruct` --> $DIR/drop_forget_copy.rs:40:12 | LL | forget(s2); @@ -66,7 +66,7 @@ error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetti LL | forget(s4); | ^^^^^^^^^^ | -note: argument has type SomeStruct +note: argument has type `SomeStruct` --> $DIR/drop_forget_copy.rs:42:12 | LL | forget(s4); diff --git a/src/tools/clippy/tests/ui/drop_non_drop.rs b/src/tools/clippy/tests/ui/drop_non_drop.rs new file mode 100644 index 00000000000..5a0ebde82c5 --- /dev/null +++ b/src/tools/clippy/tests/ui/drop_non_drop.rs @@ -0,0 +1,40 @@ +#![warn(clippy::drop_non_drop)] + +use core::mem::drop; + +fn make_result<T>(t: T) -> Result<T, ()> { + Ok(t) +} + +#[must_use] +fn must_use<T>(t: T) -> T { + t +} + +fn drop_generic<T>(t: T) { + // Don't lint + drop(t) +} + +fn main() { + struct Foo; + // Lint + drop(Foo); + // Don't lint + drop(make_result(Foo)); + // Don't lint + drop(must_use(Foo)); + + struct Bar; + impl Drop for Bar { + fn drop(&mut self) {} + } + // Don't lint + drop(Bar); + + struct Baz<T>(T); + // Lint + drop(Baz(Foo)); + // Don't lint + drop(Baz(Bar)); +} diff --git a/src/tools/clippy/tests/ui/drop_non_drop.stderr b/src/tools/clippy/tests/ui/drop_non_drop.stderr new file mode 100644 index 00000000000..f73068901c5 --- /dev/null +++ b/src/tools/clippy/tests/ui/drop_non_drop.stderr @@ -0,0 +1,27 @@ +error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends it's contained lifetimes + --> $DIR/drop_non_drop.rs:22:5 + | +LL | drop(Foo); + | ^^^^^^^^^ + | + = note: `-D clippy::drop-non-drop` implied by `-D warnings` +note: argument has type `main::Foo` + --> $DIR/drop_non_drop.rs:22:10 + | +LL | drop(Foo); + | ^^^ + +error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends it's contained lifetimes + --> $DIR/drop_non_drop.rs:37:5 + | +LL | drop(Baz(Foo)); + | ^^^^^^^^^^^^^^ + | +note: argument has type `main::Baz<main::Foo>` + --> $DIR/drop_non_drop.rs:37:10 + | +LL | drop(Baz(Foo)); + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/drop_ref.rs b/src/tools/clippy/tests/ui/drop_ref.rs index e1a15c609fd..7de0b0bbdf9 100644 --- a/src/tools/clippy/tests/ui/drop_ref.rs +++ b/src/tools/clippy/tests/ui/drop_ref.rs @@ -1,7 +1,7 @@ #![warn(clippy::drop_ref)] #![allow(clippy::toplevel_ref_arg)] #![allow(clippy::map_err_ignore)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::unnecessary_wraps, clippy::drop_non_drop)] use std::mem::drop; diff --git a/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed b/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed new file mode 100644 index 00000000000..80f07603b8d --- /dev/null +++ b/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed @@ -0,0 +1,25 @@ +// run-rustfix +#![warn(clippy::empty_structs_with_brackets)] +#![allow(dead_code)] + +pub struct MyEmptyStruct; // should trigger lint +struct MyEmptyTupleStruct; // should trigger lint + +// should not trigger lint +struct MyCfgStruct { + #[cfg(feature = "thisisneverenabled")] + field: u8, +} + +// should not trigger lint +struct MyCfgTupleStruct(#[cfg(feature = "thisisneverenabled")] u8); + +// should not trigger lint +struct MyStruct { + field: u8, +} +struct MyTupleStruct(usize, String); // should not trigger lint +struct MySingleTupleStruct(usize); // should not trigger lint +struct MyUnitLikeStruct; // should not trigger lint + +fn main() {} diff --git a/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs b/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs new file mode 100644 index 00000000000..1d1ed4c7690 --- /dev/null +++ b/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs @@ -0,0 +1,25 @@ +// run-rustfix +#![warn(clippy::empty_structs_with_brackets)] +#![allow(dead_code)] + +pub struct MyEmptyStruct {} // should trigger lint +struct MyEmptyTupleStruct(); // should trigger lint + +// should not trigger lint +struct MyCfgStruct { + #[cfg(feature = "thisisneverenabled")] + field: u8, +} + +// should not trigger lint +struct MyCfgTupleStruct(#[cfg(feature = "thisisneverenabled")] u8); + +// should not trigger lint +struct MyStruct { + field: u8, +} +struct MyTupleStruct(usize, String); // should not trigger lint +struct MySingleTupleStruct(usize); // should not trigger lint +struct MyUnitLikeStruct; // should not trigger lint + +fn main() {} diff --git a/src/tools/clippy/tests/ui/empty_structs_with_brackets.stderr b/src/tools/clippy/tests/ui/empty_structs_with_brackets.stderr new file mode 100644 index 00000000000..0308cb5571a --- /dev/null +++ b/src/tools/clippy/tests/ui/empty_structs_with_brackets.stderr @@ -0,0 +1,19 @@ +error: found empty brackets on struct declaration + --> $DIR/empty_structs_with_brackets.rs:5:25 + | +LL | pub struct MyEmptyStruct {} // should trigger lint + | ^^^ + | + = note: `-D clippy::empty-structs-with-brackets` implied by `-D warnings` + = help: remove the brackets + +error: found empty brackets on struct declaration + --> $DIR/empty_structs_with_brackets.rs:6:26 + | +LL | struct MyEmptyTupleStruct(); // should trigger lint + | ^^^ + | + = help: remove the brackets + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/err_expect.fixed b/src/tools/clippy/tests/ui/err_expect.fixed new file mode 100644 index 00000000000..7e18d70bae4 --- /dev/null +++ b/src/tools/clippy/tests/ui/err_expect.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +struct MyTypeNonDebug; + +#[derive(Debug)] +struct MyTypeDebug; + +fn main() { + let test_debug: Result<MyTypeDebug, u32> = Ok(MyTypeDebug); + test_debug.expect_err("Testing debug type"); + + let test_non_debug: Result<MyTypeNonDebug, u32> = Ok(MyTypeNonDebug); + test_non_debug.err().expect("Testing non debug type"); +} diff --git a/src/tools/clippy/tests/ui/err_expect.rs b/src/tools/clippy/tests/ui/err_expect.rs new file mode 100644 index 00000000000..bf8c3c9fb8c --- /dev/null +++ b/src/tools/clippy/tests/ui/err_expect.rs @@ -0,0 +1,14 @@ +// run-rustfix + +struct MyTypeNonDebug; + +#[derive(Debug)] +struct MyTypeDebug; + +fn main() { + let test_debug: Result<MyTypeDebug, u32> = Ok(MyTypeDebug); + test_debug.err().expect("Testing debug type"); + + let test_non_debug: Result<MyTypeNonDebug, u32> = Ok(MyTypeNonDebug); + test_non_debug.err().expect("Testing non debug type"); +} diff --git a/src/tools/clippy/tests/ui/err_expect.stderr b/src/tools/clippy/tests/ui/err_expect.stderr new file mode 100644 index 00000000000..ffd97e00a5c --- /dev/null +++ b/src/tools/clippy/tests/ui/err_expect.stderr @@ -0,0 +1,10 @@ +error: called `.err().expect()` on a `Result` value + --> $DIR/err_expect.rs:10:16 + | +LL | test_debug.err().expect("Testing debug type"); + | ^^^^^^^^^^^^ help: try: `expect_err` + | + = note: `-D clippy::err-expect` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs b/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs index 1442ee08e75..f805bcc9ba8 100644 --- a/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs +++ b/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs @@ -20,7 +20,7 @@ fn h(_: bool, _: bool, _: bool) {} fn e(_: S, _: S, _: Box<S>, _: Vec<u32>) {} fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {} -struct S {} +struct S; trait Trait { fn f(_: bool, _: bool, _: bool, _: bool); fn g(_: bool, _: bool, _: bool, _: Vec<u32>); diff --git a/src/tools/clippy/tests/ui/forget_non_drop.rs b/src/tools/clippy/tests/ui/forget_non_drop.rs new file mode 100644 index 00000000000..7580cf95ebf --- /dev/null +++ b/src/tools/clippy/tests/ui/forget_non_drop.rs @@ -0,0 +1,27 @@ +#![warn(clippy::forget_non_drop)] + +use core::mem::forget; + +fn forget_generic<T>(t: T) { + // Don't lint + forget(t) +} + +fn main() { + struct Foo; + // Lint + forget(Foo); + + struct Bar; + impl Drop for Bar { + fn drop(&mut self) {} + } + // Don't lint + forget(Bar); + + struct Baz<T>(T); + // Lint + forget(Baz(Foo)); + // Don't lint + forget(Baz(Bar)); +} diff --git a/src/tools/clippy/tests/ui/forget_non_drop.stderr b/src/tools/clippy/tests/ui/forget_non_drop.stderr new file mode 100644 index 00000000000..03fb00960a4 --- /dev/null +++ b/src/tools/clippy/tests/ui/forget_non_drop.stderr @@ -0,0 +1,27 @@ +error: call to `std::mem::forget` with a value that does not implement `Drop`. Forgetting such a type is the same as dropping it + --> $DIR/forget_non_drop.rs:13:5 + | +LL | forget(Foo); + | ^^^^^^^^^^^ + | + = note: `-D clippy::forget-non-drop` implied by `-D warnings` +note: argument has type `main::Foo` + --> $DIR/forget_non_drop.rs:13:12 + | +LL | forget(Foo); + | ^^^ + +error: call to `std::mem::forget` with a value that does not implement `Drop`. Forgetting such a type is the same as dropping it + --> $DIR/forget_non_drop.rs:24:5 + | +LL | forget(Baz(Foo)); + | ^^^^^^^^^^^^^^^^ + | +note: argument has type `main::Baz<main::Foo>` + --> $DIR/forget_non_drop.rs:24:12 + | +LL | forget(Baz(Foo)); + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/forget_ref.rs b/src/tools/clippy/tests/ui/forget_ref.rs index c49e6756a6c..6c8c4c9c0ed 100644 --- a/src/tools/clippy/tests/ui/forget_ref.rs +++ b/src/tools/clippy/tests/ui/forget_ref.rs @@ -1,6 +1,6 @@ #![warn(clippy::forget_ref)] #![allow(clippy::toplevel_ref_arg)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::unnecessary_wraps, clippy::forget_non_drop)] use std::mem::forget; diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs index 12bbda71f43..edc3fe1aec1 100644 --- a/src/tools/clippy/tests/ui/identity_op.rs +++ b/src/tools/clippy/tests/ui/identity_op.rs @@ -66,4 +66,13 @@ fn main() { let b = a << 0; // no error: non-integer 1 * Meter; // no error: non-integer + + 2 % 3; + -2 % 3; + 2 % -3 + x; + -2 % -3 + x; + x + 1 % 3; + (x + 1) % 3; // no error + 4 % 3; // no error + 4 % -3; // no error } diff --git a/src/tools/clippy/tests/ui/identity_op.stderr b/src/tools/clippy/tests/ui/identity_op.stderr index 0103cf5457e..706f01a3dd6 100644 --- a/src/tools/clippy/tests/ui/identity_op.stderr +++ b/src/tools/clippy/tests/ui/identity_op.stderr @@ -78,5 +78,35 @@ error: the operation is ineffective. Consider reducing it to `x` LL | x >> &0; | ^^^^^^^ -error: aborting due to 13 previous errors +error: the operation is ineffective. Consider reducing it to `2` + --> $DIR/identity_op.rs:70:5 + | +LL | 2 % 3; + | ^^^^^ + +error: the operation is ineffective. Consider reducing it to `-2` + --> $DIR/identity_op.rs:71:5 + | +LL | -2 % 3; + | ^^^^^^ + +error: the operation is ineffective. Consider reducing it to `2` + --> $DIR/identity_op.rs:72:5 + | +LL | 2 % -3 + x; + | ^^^^^^ + +error: the operation is ineffective. Consider reducing it to `-2` + --> $DIR/identity_op.rs:73:5 + | +LL | -2 % -3 + x; + | ^^^^^^^ + +error: the operation is ineffective. Consider reducing it to `1` + --> $DIR/identity_op.rs:74:9 + | +LL | x + 1 % 3; + | ^^^^^ + +error: aborting due to 18 previous errors diff --git a/src/tools/clippy/tests/ui/implicit_clone.rs b/src/tools/clippy/tests/ui/implicit_clone.rs index 639fecb8927..2549c9f32f9 100644 --- a/src/tools/clippy/tests/ui/implicit_clone.rs +++ b/src/tools/clippy/tests/ui/implicit_clone.rs @@ -30,7 +30,7 @@ where } #[derive(Copy, Clone)] -struct Kitten {} +struct Kitten; impl Kitten { // badly named method fn to_vec(self) -> Kitten { @@ -44,7 +44,7 @@ impl Borrow<BorrowedKitten> for Kitten { } } -struct BorrowedKitten {} +struct BorrowedKitten; impl ToOwned for BorrowedKitten { type Owned = Kitten; fn to_owned(&self) -> Kitten { diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs index ca8ca53c80c..45a430edcb5 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs @@ -1,18 +1,34 @@ +#![feature(inline_const)] #![warn(clippy::indexing_slicing)] // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] -#![allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(const_err, clippy::no_effect, clippy::unnecessary_operation)] + +const ARR: [i32; 2] = [1, 2]; +const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr. +const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. + +const fn idx() -> usize { + 1 +} +const fn idx4() -> usize { + 4 +} fn main() { let x = [1, 2, 3, 4]; let index: usize = 1; x[index]; - x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. - x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + x[4]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. + x[1 << 3]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. x[0]; // Ok, should not produce stderr. x[3]; // Ok, should not produce stderr. + x[const { idx() }]; // Ok, should not produce stderr. + x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. + const { &ARR[idx()] }; // Ok, should not produce stderr. + const { &ARR[idx4()] }; // Ok, let rustc handle const contexts. let y = &x; y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021 @@ -25,7 +41,7 @@ fn main() { const N: usize = 15; // Out of bounds const M: usize = 3; // In bounds - x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + x[N]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. x[M]; // Ok, should not produce stderr. v[N]; v[M]; diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr index 76ecec33484..83a36f407d5 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr @@ -1,5 +1,17 @@ +error[E0080]: evaluation of `main::{constant#3}::<&i32>` failed + --> $DIR/indexing_slicing_index.rs:31:14 + | +LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts. + | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 + +error[E0080]: erroneous constant used + --> $DIR/indexing_slicing_index.rs:31:5 + | +LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts. + | ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors + error: indexing may panic - --> $DIR/indexing_slicing_index.rs:10:5 + --> $DIR/indexing_slicing_index.rs:22:5 | LL | x[index]; | ^^^^^^^^ @@ -8,7 +20,7 @@ LL | x[index]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:22:5 + --> $DIR/indexing_slicing_index.rs:38:5 | LL | v[0]; | ^^^^ @@ -16,7 +28,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:23:5 + --> $DIR/indexing_slicing_index.rs:39:5 | LL | v[10]; | ^^^^^ @@ -24,7 +36,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:24:5 + --> $DIR/indexing_slicing_index.rs:40:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -32,7 +44,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:30:5 + --> $DIR/indexing_slicing_index.rs:46:5 | LL | v[N]; | ^^^^ @@ -40,12 +52,13 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:31:5 + --> $DIR/indexing_slicing_index.rs:47:5 | LL | v[M]; | ^^^^ | = help: consider using `.get(n)` or `.get_mut(n)` instead -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0080`. diff --git a/src/tools/clippy/tests/ui/iter_nth_zero.fixed b/src/tools/clippy/tests/ui/iter_nth_zero.fixed index b54147c94d1..f23671c26e4 100644 --- a/src/tools/clippy/tests/ui/iter_nth_zero.fixed +++ b/src/tools/clippy/tests/ui/iter_nth_zero.fixed @@ -3,7 +3,7 @@ #![warn(clippy::iter_nth_zero)] use std::collections::HashSet; -struct Foo {} +struct Foo; impl Foo { fn nth(&self, index: usize) -> usize { diff --git a/src/tools/clippy/tests/ui/iter_nth_zero.rs b/src/tools/clippy/tests/ui/iter_nth_zero.rs index b92c7d18adb..7c968d49845 100644 --- a/src/tools/clippy/tests/ui/iter_nth_zero.rs +++ b/src/tools/clippy/tests/ui/iter_nth_zero.rs @@ -3,7 +3,7 @@ #![warn(clippy::iter_nth_zero)] use std::collections::HashSet; -struct Foo {} +struct Foo; impl Foo { fn nth(&self, index: usize) -> usize { diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed b/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed index a9041671101..56761ebbcb8 100644 --- a/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed +++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed @@ -1,5 +1,6 @@ // run-rustfix #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)] +#![allow(dead_code)] fn main() { let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()]; @@ -43,3 +44,8 @@ fn main() { // Should probably stay as it is. let _ = [0, 1, 2, 3, 4].iter().cloned().take(10); } + +// #8527 +fn cloned_flatten(x: Option<&Option<String>>) -> Option<String> { + x.cloned().flatten() +} diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.rs b/src/tools/clippy/tests/ui/iter_overeager_cloned.rs index dd04e33a4b3..98321d889b5 100644 --- a/src/tools/clippy/tests/ui/iter_overeager_cloned.rs +++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.rs @@ -1,5 +1,6 @@ // run-rustfix #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)] +#![allow(dead_code)] fn main() { let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()]; @@ -45,3 +46,8 @@ fn main() { // Should probably stay as it is. let _ = [0, 1, 2, 3, 4].iter().cloned().take(10); } + +// #8527 +fn cloned_flatten(x: Option<&Option<String>>) -> Option<String> { + x.cloned().flatten() +} diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.stderr b/src/tools/clippy/tests/ui/iter_overeager_cloned.stderr index e36b0e36fbd..0582700fd16 100644 --- a/src/tools/clippy/tests/ui/iter_overeager_cloned.stderr +++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.stderr @@ -1,5 +1,5 @@ error: called `cloned().last()` on an `Iterator`. It may be more efficient to call `last().cloned()` instead - --> $DIR/iter_overeager_cloned.rs:7:29 + --> $DIR/iter_overeager_cloned.rs:8:29 | LL | let _: Option<String> = vec.iter().cloned().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().last().cloned()` @@ -7,13 +7,13 @@ LL | let _: Option<String> = vec.iter().cloned().last(); = note: `-D clippy::iter-overeager-cloned` implied by `-D warnings` error: called `cloned().next()` on an `Iterator`. It may be more efficient to call `next().cloned()` instead - --> $DIR/iter_overeager_cloned.rs:9:29 + --> $DIR/iter_overeager_cloned.rs:10:29 | LL | let _: Option<String> = vec.iter().chain(vec.iter()).cloned().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().chain(vec.iter()).next().cloned()` error: called `cloned().count()` on an `Iterator`. It may be more efficient to call `count()` instead - --> $DIR/iter_overeager_cloned.rs:11:20 + --> $DIR/iter_overeager_cloned.rs:12:20 | LL | let _: usize = vec.iter().filter(|x| x == &"2").cloned().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().filter(|x| x == &"2").count()` @@ -21,25 +21,25 @@ LL | let _: usize = vec.iter().filter(|x| x == &"2").cloned().count(); = note: `-D clippy::redundant-clone` implied by `-D warnings` error: called `cloned().take(...)` on an `Iterator`. It may be more efficient to call `take(...).cloned()` instead - --> $DIR/iter_overeager_cloned.rs:13:21 + --> $DIR/iter_overeager_cloned.rs:14:21 | LL | let _: Vec<_> = vec.iter().cloned().take(2).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().take(2).cloned()` error: called `cloned().skip(...)` on an `Iterator`. It may be more efficient to call `skip(...).cloned()` instead - --> $DIR/iter_overeager_cloned.rs:15:21 + --> $DIR/iter_overeager_cloned.rs:16:21 | LL | let _: Vec<_> = vec.iter().cloned().skip(2).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().skip(2).cloned()` error: called `cloned().nth(...)` on an `Iterator`. It may be more efficient to call `nth(...).cloned()` instead - --> $DIR/iter_overeager_cloned.rs:17:13 + --> $DIR/iter_overeager_cloned.rs:18:13 | LL | let _ = vec.iter().filter(|x| x == &"2").cloned().nth(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().filter(|x| x == &"2").nth(2).cloned()` error: called `cloned().flatten()` on an `Iterator`. It may be more efficient to call `flatten().cloned()` instead - --> $DIR/iter_overeager_cloned.rs:19:13 + --> $DIR/iter_overeager_cloned.rs:20:13 | LL | let _ = [Some(Some("str".to_string())), Some(Some("str".to_string()))] | _____________^ diff --git a/src/tools/clippy/tests/ui/large_types_passed_by_value.rs b/src/tools/clippy/tests/ui/large_types_passed_by_value.rs index e4a2e9df4d7..7601b5c66fa 100644 --- a/src/tools/clippy/tests/ui/large_types_passed_by_value.rs +++ b/src/tools/clippy/tests/ui/large_types_passed_by_value.rs @@ -37,7 +37,7 @@ pub trait PubLargeTypeDevourer { fn devoure_array_in_public(&self, array: [u8; 6666]); } -struct S {} +struct S; impl LargeTypeDevourer for S { fn devoure_array(&self, array: [u8; 6666]) { todo!(); diff --git a/src/tools/clippy/tests/ui/let_and_return.rs b/src/tools/clippy/tests/ui/let_and_return.rs index e3561863c1e..bb162adc9ad 100644 --- a/src/tools/clippy/tests/ui/let_and_return.rs +++ b/src/tools/clippy/tests/ui/let_and_return.rs @@ -88,7 +88,7 @@ mod no_lint_if_stmt_borrows { ret } - struct Bar {} + struct Bar; impl Bar { fn new() -> Self { diff --git a/src/tools/clippy/tests/ui/let_underscore_must_use.rs b/src/tools/clippy/tests/ui/let_underscore_must_use.rs index a842e872a37..1edb77c748b 100644 --- a/src/tools/clippy/tests/ui/let_underscore_must_use.rs +++ b/src/tools/clippy/tests/ui/let_underscore_must_use.rs @@ -26,7 +26,7 @@ fn h() -> u32 { 0 } -struct S {} +struct S; impl S { #[must_use] diff --git a/src/tools/clippy/tests/ui/manual_async_fn.fixed b/src/tools/clippy/tests/ui/manual_async_fn.fixed index 136cc96be70..b7e46a4a8cc 100644 --- a/src/tools/clippy/tests/ui/manual_async_fn.fixed +++ b/src/tools/clippy/tests/ui/manual_async_fn.fixed @@ -38,7 +38,7 @@ async fn already_async() -> impl Future<Output = i32> { async { 42 } } -struct S {} +struct S; impl S { async fn inh_fut() -> i32 { // NOTE: this code is here just to check that the indentation is correct in the suggested fix diff --git a/src/tools/clippy/tests/ui/manual_async_fn.rs b/src/tools/clippy/tests/ui/manual_async_fn.rs index ddc453ffdb7..b05429da662 100644 --- a/src/tools/clippy/tests/ui/manual_async_fn.rs +++ b/src/tools/clippy/tests/ui/manual_async_fn.rs @@ -52,7 +52,7 @@ async fn already_async() -> impl Future<Output = i32> { async { 42 } } -struct S {} +struct S; impl S { fn inh_fut() -> impl Future<Output = i32> { async { diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed index 05d6c56f2ac..7d68978216c 100644 --- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed +++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed @@ -78,7 +78,7 @@ fn result_unwrap_or() { (Ok(1) as Result<i32, &str>).unwrap_or(42); // method call case, suggestion must not surround Result expr `s.method()` with parentheses - struct S {} + struct S; impl S { fn method(self) -> Option<i32> { Some(42) diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs index 09f62c69b71..b937fe6f977 100644 --- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs +++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs @@ -102,7 +102,7 @@ fn result_unwrap_or() { }; // method call case, suggestion must not surround Result expr `s.method()` with parentheses - struct S {} + struct S; impl S { fn method(self) -> Option<i32> { Some(42) diff --git a/src/tools/clippy/tests/ui/map_identity.fixed b/src/tools/clippy/tests/ui/map_identity.fixed index 4a1452b25f3..2256e51f2d0 100644 --- a/src/tools/clippy/tests/ui/map_identity.fixed +++ b/src/tools/clippy/tests/ui/map_identity.fixed @@ -16,6 +16,8 @@ fn main() { let _: Result<i8, f32> = Err(2.3).map(|x: i8| { return x + 3; }); + let _: Result<u32, u32> = Ok(1); + let _: Result<u32, u32> = Ok(1).map_err(|a: u32| a * 42); } fn not_identity(x: &u16) -> u16 { diff --git a/src/tools/clippy/tests/ui/map_identity.rs b/src/tools/clippy/tests/ui/map_identity.rs index 65c7e6e1ea5..ccfdc9ea76d 100644 --- a/src/tools/clippy/tests/ui/map_identity.rs +++ b/src/tools/clippy/tests/ui/map_identity.rs @@ -18,6 +18,8 @@ fn main() { let _: Result<i8, f32> = Err(2.3).map(|x: i8| { return x + 3; }); + let _: Result<u32, u32> = Ok(1).map_err(|a| a); + let _: Result<u32, u32> = Ok(1).map_err(|a: u32| a * 42); } fn not_identity(x: &u16) -> u16 { diff --git a/src/tools/clippy/tests/ui/map_identity.stderr b/src/tools/clippy/tests/ui/map_identity.stderr index e4a0320cbda..b6a77281f6d 100644 --- a/src/tools/clippy/tests/ui/map_identity.stderr +++ b/src/tools/clippy/tests/ui/map_identity.stderr @@ -33,5 +33,11 @@ LL | | return x; LL | | }); | |______^ help: remove the call to `map` -error: aborting due to 5 previous errors +error: unnecessary map of the identity function + --> $DIR/map_identity.rs:21:36 + | +LL | let _: Result<u32, u32> = Ok(1).map_err(|a| a); + | ^^^^^^^^^^^^^^^ help: remove the call to `map_err` + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/map_unit_fn.rs b/src/tools/clippy/tests/ui/map_unit_fn.rs index 9a74da4e3b8..e7f07b50f3a 100644 --- a/src/tools/clippy/tests/ui/map_unit_fn.rs +++ b/src/tools/clippy/tests/ui/map_unit_fn.rs @@ -1,5 +1,5 @@ #![allow(unused)] -struct Mappable {} +struct Mappable; impl Mappable { pub fn map(&self) {} diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs index c5f221220ec..f83c3e0e281 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_attr.rs +++ b/src/tools/clippy/tests/ui/min_rust_version_attr.rs @@ -99,7 +99,7 @@ pub fn manual_range_contains() { } pub fn use_self() { - struct Foo {} + struct Foo; impl Foo { fn new() -> Foo { @@ -145,6 +145,16 @@ fn int_from_bool() -> u8 { true as u8 } +fn err_expect() { + let x: Result<u32, &str> = Ok(10); + x.err().expect("Testing expect_err"); +} + +fn cast_abs_to_unsigned() { + let x: i32 = 10; + assert_eq!(10u32, x.abs() as u32); +} + fn main() { filter_map_next(); checked_conversion(); @@ -162,6 +172,8 @@ fn main() { missing_const_for_fn(); unnest_or_patterns(); int_from_bool(); + err_expect(); + cast_abs_to_unsigned(); } mod just_under_msrv { diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr index 6b3fdb0844b..de225eb740d 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr +++ b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr @@ -1,12 +1,12 @@ error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:186:24 + --> $DIR/min_rust_version_attr.rs:198:24 | LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); | ^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::manual-strip` implied by `-D warnings` note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:185:9 + --> $DIR/min_rust_version_attr.rs:197:9 | LL | if s.starts_with("hello, ") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,13 +17,13 @@ LL ~ assert_eq!(<stripped>.to_uppercase(), "WORLD!"); | error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:198:24 + --> $DIR/min_rust_version_attr.rs:210:24 | LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); | ^^^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:197:9 + --> $DIR/min_rust_version_attr.rs:209:9 | LL | if s.starts_with("hello, ") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/missing_inline.rs b/src/tools/clippy/tests/ui/missing_inline.rs index b73b24b8e0a..07f8e3888c9 100644 --- a/src/tools/clippy/tests/ui/missing_inline.rs +++ b/src/tools/clippy/tests/ui/missing_inline.rs @@ -7,8 +7,8 @@ type Typedef = String; pub type PubTypedef = String; -struct Foo {} // ok -pub struct PubFoo {} // ok +struct Foo; // ok +pub struct PubFoo; // ok enum FooE {} // ok pub enum PubFooE {} // ok @@ -63,4 +63,4 @@ impl PubFoo { // do not lint this since users cannot control the external code #[derive(Debug)] -pub struct S {} +pub struct S; diff --git a/src/tools/clippy/tests/ui/module_name_repetitions.rs b/src/tools/clippy/tests/ui/module_name_repetitions.rs index f5908cb5701..ebaa77cc283 100644 --- a/src/tools/clippy/tests/ui/module_name_repetitions.rs +++ b/src/tools/clippy/tests/ui/module_name_repetitions.rs @@ -7,7 +7,7 @@ mod foo { pub fn foo() {} pub fn foo_bar() {} pub fn bar_foo() {} - pub struct FooCake {} + pub struct FooCake; pub enum CakeFoo {} pub struct Foo7Bar; diff --git a/src/tools/clippy/tests/ui/module_name_repetitions.stderr b/src/tools/clippy/tests/ui/module_name_repetitions.stderr index bdd217a969c..3f343a3e430 100644 --- a/src/tools/clippy/tests/ui/module_name_repetitions.stderr +++ b/src/tools/clippy/tests/ui/module_name_repetitions.stderr @@ -15,8 +15,8 @@ LL | pub fn bar_foo() {} error: item name starts with its containing module's name --> $DIR/module_name_repetitions.rs:10:5 | -LL | pub struct FooCake {} - | ^^^^^^^^^^^^^^^^^^^^^ +LL | pub struct FooCake; + | ^^^^^^^^^^^^^^^^^^^ error: item name ends with its containing module's name --> $DIR/module_name_repetitions.rs:11:5 diff --git a/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.rs b/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.rs index 047a29fa1e3..3ebe46bc5be 100644 --- a/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.rs +++ b/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.rs @@ -1,5 +1,10 @@ #![warn(clippy::modulo_arithmetic)] -#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::modulo_one)] +#![allow( + clippy::no_effect, + clippy::unnecessary_operation, + clippy::modulo_one, + clippy::identity_op +)] fn main() { // Lint when both sides are const and of the opposite sign diff --git a/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr b/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr index 64335f35f0f..11b5f77461b 100644 --- a/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr +++ b/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr @@ -1,5 +1,5 @@ error: you are using modulo operator on constants with different signs: `-1 % 2` - --> $DIR/modulo_arithmetic_integral_const.rs:6:5 + --> $DIR/modulo_arithmetic_integral_const.rs:11:5 | LL | -1 % 2; | ^^^^^^ @@ -9,7 +9,7 @@ LL | -1 % 2; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> $DIR/modulo_arithmetic_integral_const.rs:7:5 + --> $DIR/modulo_arithmetic_integral_const.rs:12:5 | LL | 1 % -2; | ^^^^^^ @@ -18,7 +18,7 @@ LL | 1 % -2; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 3` - --> $DIR/modulo_arithmetic_integral_const.rs:8:5 + --> $DIR/modulo_arithmetic_integral_const.rs:13:5 | LL | (1 - 2) % (1 + 2); | ^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | (1 - 2) % (1 + 2); = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `3 % -1` - --> $DIR/modulo_arithmetic_integral_const.rs:9:5 + --> $DIR/modulo_arithmetic_integral_const.rs:14:5 | LL | (1 + 2) % (1 - 2); | ^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | (1 + 2) % (1 - 2); = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-35 % 300000` - --> $DIR/modulo_arithmetic_integral_const.rs:10:5 + --> $DIR/modulo_arithmetic_integral_const.rs:15:5 | LL | 35 * (7 - 4 * 2) % (-500 * -600); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | 35 * (7 - 4 * 2) % (-500 * -600); = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> $DIR/modulo_arithmetic_integral_const.rs:12:5 + --> $DIR/modulo_arithmetic_integral_const.rs:17:5 | LL | -1i8 % 2i8; | ^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | -1i8 % 2i8; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> $DIR/modulo_arithmetic_integral_const.rs:13:5 + --> $DIR/modulo_arithmetic_integral_const.rs:18:5 | LL | 1i8 % -2i8; | ^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | 1i8 % -2i8; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> $DIR/modulo_arithmetic_integral_const.rs:14:5 + --> $DIR/modulo_arithmetic_integral_const.rs:19:5 | LL | -1i16 % 2i16; | ^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | -1i16 % 2i16; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> $DIR/modulo_arithmetic_integral_const.rs:15:5 + --> $DIR/modulo_arithmetic_integral_const.rs:20:5 | LL | 1i16 % -2i16; | ^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | 1i16 % -2i16; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> $DIR/modulo_arithmetic_integral_const.rs:16:5 + --> $DIR/modulo_arithmetic_integral_const.rs:21:5 | LL | -1i32 % 2i32; | ^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | -1i32 % 2i32; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> $DIR/modulo_arithmetic_integral_const.rs:17:5 + --> $DIR/modulo_arithmetic_integral_const.rs:22:5 | LL | 1i32 % -2i32; | ^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | 1i32 % -2i32; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> $DIR/modulo_arithmetic_integral_const.rs:18:5 + --> $DIR/modulo_arithmetic_integral_const.rs:23:5 | LL | -1i64 % 2i64; | ^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | -1i64 % 2i64; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> $DIR/modulo_arithmetic_integral_const.rs:19:5 + --> $DIR/modulo_arithmetic_integral_const.rs:24:5 | LL | 1i64 % -2i64; | ^^^^^^^^^^^^ @@ -117,7 +117,7 @@ LL | 1i64 % -2i64; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> $DIR/modulo_arithmetic_integral_const.rs:20:5 + --> $DIR/modulo_arithmetic_integral_const.rs:25:5 | LL | -1i128 % 2i128; | ^^^^^^^^^^^^^^ @@ -126,7 +126,7 @@ LL | -1i128 % 2i128; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> $DIR/modulo_arithmetic_integral_const.rs:21:5 + --> $DIR/modulo_arithmetic_integral_const.rs:26:5 | LL | 1i128 % -2i128; | ^^^^^^^^^^^^^^ @@ -135,7 +135,7 @@ LL | 1i128 % -2i128; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> $DIR/modulo_arithmetic_integral_const.rs:22:5 + --> $DIR/modulo_arithmetic_integral_const.rs:27:5 | LL | -1isize % 2isize; | ^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | -1isize % 2isize; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> $DIR/modulo_arithmetic_integral_const.rs:23:5 + --> $DIR/modulo_arithmetic_integral_const.rs:28:5 | LL | 1isize % -2isize; | ^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs index ad0d694a217..02b43cce2bd 100644 --- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs +++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs @@ -14,7 +14,7 @@ mod issue_6089 { fn test(self: &Self); } - struct S1 {} + struct S1; impl T1 for S1 { fn test(self: &Self) {} @@ -32,7 +32,7 @@ mod issue_6089 { fn call_with_mut_self(&mut self); } - struct S2 {} + struct S2; // The method's signature will be expanded to: // fn call_with_mut_self<'life0>(self: &'life0 mut Self) {} diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs index f3eafe8e927..1456204ca86 100644 --- a/src/tools/clippy/tests/ui/needless_lifetimes.rs +++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs @@ -268,7 +268,7 @@ mod issue4291 { mod issue2944 { trait Foo {} - struct Bar {} + struct Bar; struct Baz<'a> { bar: &'a Bar, } diff --git a/src/tools/clippy/tests/ui/needless_match.fixed b/src/tools/clippy/tests/ui/needless_match.fixed index ece18ad737f..9ccccaa1725 100644 --- a/src/tools/clippy/tests/ui/needless_match.fixed +++ b/src/tools/clippy/tests/ui/needless_match.fixed @@ -4,38 +4,35 @@ #![allow(dead_code)] #[derive(Clone, Copy)] -enum Choice { +enum Simple { A, B, C, D, } -#[allow(unused_mut)] fn useless_match() { - let mut i = 10; + let i = 10; let _: i32 = i; - let _: i32 = i; - let mut _i_mut = i; - let s = "test"; let _: &str = s; } -fn custom_type_match(se: Choice) { - let _: Choice = se; +fn custom_type_match() { + let se = Simple::A; + let _: Simple = se; // Don't trigger - let _: Choice = match se { - Choice::A => Choice::A, - Choice::B => Choice::B, - _ => Choice::C, + let _: Simple = match se { + Simple::A => Simple::A, + Simple::B => Simple::B, + _ => Simple::C, }; // Mingled, don't trigger - let _: Choice = match se { - Choice::A => Choice::B, - Choice::B => Choice::C, - Choice::C => Choice::D, - Choice::D => Choice::A, + let _: Simple = match se { + Simple::A => Simple::B, + Simple::B => Simple::C, + Simple::C => Simple::D, + Simple::D => Simple::A, }; } @@ -55,29 +52,146 @@ fn func_ret_err<T>(err: T) -> Result<i32, T> { fn result_match() { let _: Result<i32, i32> = Ok(1); let _: Result<i32, i32> = func_ret_err(0_i32); + // as ref, don't trigger + let res = &func_ret_err(0_i32); + let _: Result<&i32, &i32> = match *res { + Ok(ref x) => Ok(x), + Err(ref x) => Err(x), + }; } -fn if_let_option() -> Option<i32> { - Some(1) +fn if_let_option() { + let _ = Some(1); + + fn do_something() {} + + // Don't trigger + let _ = if let Some(a) = Some(1) { + Some(a) + } else { + do_something(); + None + }; + + // Don't trigger + let _ = if let Some(a) = Some(1) { + do_something(); + Some(a) + } else { + None + }; } -fn if_let_result(x: Result<(), i32>) { - let _: Result<(), i32> = x; - let _: Result<(), i32> = x; +fn if_let_result() { + let x: Result<i32, i32> = Ok(1); + let _: Result<i32, i32> = x; + let _: Result<i32, i32> = x; // Input type mismatch, don't trigger - let _: Result<(), i32> = if let Err(e) = Ok(1) { Err(e) } else { x }; + let _: Result<i32, i32> = if let Err(e) = Ok(1) { Err(e) } else { x }; } -fn if_let_custom_enum(x: Choice) { - let _: Choice = x; +fn if_let_custom_enum(x: Simple) { + let _: Simple = x; + // Don't trigger - let _: Choice = if let Choice::A = x { - Choice::A + let _: Simple = if let Simple::A = x { + Simple::A } else if true { - Choice::B + Simple::B } else { x }; } +mod issue8542 { + #[derive(Clone, Copy)] + enum E { + VariantA(u8, u8), + VariantB(u8, bool), + } + + enum Complex { + A(u8), + B(u8, bool), + C(u8, i32, f64), + D(E, bool), + } + + fn match_test() { + let ce = Complex::B(8, false); + let aa = 0_u8; + let bb = false; + + let _: Complex = ce; + + // Don't trigger + let _: Complex = match ce { + Complex::A(_) => Complex::A(aa), + Complex::B(_, b) => Complex::B(aa, b), + Complex::C(_, b, _) => Complex::C(aa, b, 64_f64), + Complex::D(e, b) => Complex::D(e, b), + }; + + // Don't trigger + let _: Complex = match ce { + Complex::A(a) => Complex::A(a), + Complex::B(a, _) => Complex::B(a, bb), + Complex::C(a, _, _) => Complex::C(a, 32_i32, 64_f64), + _ => ce, + }; + } +} + +/// Lint triggered when type coercions happen. +/// Do NOT trigger on any of these. +mod issue8551 { + trait Trait {} + struct Struct; + impl Trait for Struct {} + + fn optmap(s: Option<&Struct>) -> Option<&dyn Trait> { + match s { + Some(s) => Some(s), + None => None, + } + } + + fn lint_tests() { + let option: Option<&Struct> = None; + let _: Option<&dyn Trait> = match option { + Some(s) => Some(s), + None => None, + }; + + let _: Option<&dyn Trait> = if true { + match option { + Some(s) => Some(s), + None => None, + } + } else { + None + }; + + let result: Result<&Struct, i32> = Err(0); + let _: Result<&dyn Trait, i32> = match result { + Ok(s) => Ok(s), + Err(e) => Err(e), + }; + + let _: Option<&dyn Trait> = if let Some(s) = option { Some(s) } else { None }; + } +} + +trait Tr { + fn as_mut(&mut self) -> Result<&mut i32, &mut i32>; +} +impl Tr for Result<i32, i32> { + fn as_mut(&mut self) -> Result<&mut i32, &mut i32> { + match self { + Ok(x) => Ok(x), + Err(e) => Err(e), + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_match.rs b/src/tools/clippy/tests/ui/needless_match.rs index 36649de35a6..d210ecff7f1 100644 --- a/src/tools/clippy/tests/ui/needless_match.rs +++ b/src/tools/clippy/tests/ui/needless_match.rs @@ -4,33 +4,21 @@ #![allow(dead_code)] #[derive(Clone, Copy)] -enum Choice { +enum Simple { A, B, C, D, } -#[allow(unused_mut)] fn useless_match() { - let mut i = 10; + let i = 10; let _: i32 = match i { 0 => 0, 1 => 1, 2 => 2, _ => i, }; - let _: i32 = match i { - 0 => 0, - 1 => 1, - ref i => *i, - }; - let mut _i_mut = match i { - 0 => 0, - 1 => 1, - ref mut i => *i, - }; - let s = "test"; let _: &str = match s { "a" => "a", @@ -39,25 +27,26 @@ fn useless_match() { }; } -fn custom_type_match(se: Choice) { - let _: Choice = match se { - Choice::A => Choice::A, - Choice::B => Choice::B, - Choice::C => Choice::C, - Choice::D => Choice::D, +fn custom_type_match() { + let se = Simple::A; + let _: Simple = match se { + Simple::A => Simple::A, + Simple::B => Simple::B, + Simple::C => Simple::C, + Simple::D => Simple::D, }; // Don't trigger - let _: Choice = match se { - Choice::A => Choice::A, - Choice::B => Choice::B, - _ => Choice::C, + let _: Simple = match se { + Simple::A => Simple::A, + Simple::B => Simple::B, + _ => Simple::C, }; // Mingled, don't trigger - let _: Choice = match se { - Choice::A => Choice::B, - Choice::B => Choice::C, - Choice::C => Choice::D, - Choice::D => Choice::A, + let _: Simple = match se { + Simple::A => Simple::B, + Simple::B => Simple::C, + Simple::C => Simple::D, + Simple::D => Simple::A, }; } @@ -86,37 +75,160 @@ fn result_match() { Err(err) => Err(err), Ok(a) => Ok(a), }; + // as ref, don't trigger + let res = &func_ret_err(0_i32); + let _: Result<&i32, &i32> = match *res { + Ok(ref x) => Ok(x), + Err(ref x) => Err(x), + }; } -fn if_let_option() -> Option<i32> { - if let Some(a) = Some(1) { Some(a) } else { None } +fn if_let_option() { + let _ = if let Some(a) = Some(1) { Some(a) } else { None }; + + fn do_something() {} + + // Don't trigger + let _ = if let Some(a) = Some(1) { + Some(a) + } else { + do_something(); + None + }; + + // Don't trigger + let _ = if let Some(a) = Some(1) { + do_something(); + Some(a) + } else { + None + }; } -fn if_let_result(x: Result<(), i32>) { - let _: Result<(), i32> = if let Err(e) = x { Err(e) } else { x }; - let _: Result<(), i32> = if let Ok(val) = x { Ok(val) } else { x }; +fn if_let_result() { + let x: Result<i32, i32> = Ok(1); + let _: Result<i32, i32> = if let Err(e) = x { Err(e) } else { x }; + let _: Result<i32, i32> = if let Ok(val) = x { Ok(val) } else { x }; // Input type mismatch, don't trigger - let _: Result<(), i32> = if let Err(e) = Ok(1) { Err(e) } else { x }; + let _: Result<i32, i32> = if let Err(e) = Ok(1) { Err(e) } else { x }; } -fn if_let_custom_enum(x: Choice) { - let _: Choice = if let Choice::A = x { - Choice::A - } else if let Choice::B = x { - Choice::B - } else if let Choice::C = x { - Choice::C +fn if_let_custom_enum(x: Simple) { + let _: Simple = if let Simple::A = x { + Simple::A + } else if let Simple::B = x { + Simple::B + } else if let Simple::C = x { + Simple::C } else { x }; + // Don't trigger - let _: Choice = if let Choice::A = x { - Choice::A + let _: Simple = if let Simple::A = x { + Simple::A } else if true { - Choice::B + Simple::B } else { x }; } +mod issue8542 { + #[derive(Clone, Copy)] + enum E { + VariantA(u8, u8), + VariantB(u8, bool), + } + + enum Complex { + A(u8), + B(u8, bool), + C(u8, i32, f64), + D(E, bool), + } + + fn match_test() { + let ce = Complex::B(8, false); + let aa = 0_u8; + let bb = false; + + let _: Complex = match ce { + Complex::A(a) => Complex::A(a), + Complex::B(a, b) => Complex::B(a, b), + Complex::C(a, b, c) => Complex::C(a, b, c), + Complex::D(E::VariantA(ea, eb), b) => Complex::D(E::VariantA(ea, eb), b), + Complex::D(E::VariantB(ea, eb), b) => Complex::D(E::VariantB(ea, eb), b), + }; + + // Don't trigger + let _: Complex = match ce { + Complex::A(_) => Complex::A(aa), + Complex::B(_, b) => Complex::B(aa, b), + Complex::C(_, b, _) => Complex::C(aa, b, 64_f64), + Complex::D(e, b) => Complex::D(e, b), + }; + + // Don't trigger + let _: Complex = match ce { + Complex::A(a) => Complex::A(a), + Complex::B(a, _) => Complex::B(a, bb), + Complex::C(a, _, _) => Complex::C(a, 32_i32, 64_f64), + _ => ce, + }; + } +} + +/// Lint triggered when type coercions happen. +/// Do NOT trigger on any of these. +mod issue8551 { + trait Trait {} + struct Struct; + impl Trait for Struct {} + + fn optmap(s: Option<&Struct>) -> Option<&dyn Trait> { + match s { + Some(s) => Some(s), + None => None, + } + } + + fn lint_tests() { + let option: Option<&Struct> = None; + let _: Option<&dyn Trait> = match option { + Some(s) => Some(s), + None => None, + }; + + let _: Option<&dyn Trait> = if true { + match option { + Some(s) => Some(s), + None => None, + } + } else { + None + }; + + let result: Result<&Struct, i32> = Err(0); + let _: Result<&dyn Trait, i32> = match result { + Ok(s) => Ok(s), + Err(e) => Err(e), + }; + + let _: Option<&dyn Trait> = if let Some(s) = option { Some(s) } else { None }; + } +} + +trait Tr { + fn as_mut(&mut self) -> Result<&mut i32, &mut i32>; +} +impl Tr for Result<i32, i32> { + fn as_mut(&mut self) -> Result<&mut i32, &mut i32> { + match self { + Ok(x) => Ok(x), + Err(e) => Err(e), + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_match.stderr b/src/tools/clippy/tests/ui/needless_match.stderr index ad1525406ad..34c5226f060 100644 --- a/src/tools/clippy/tests/ui/needless_match.stderr +++ b/src/tools/clippy/tests/ui/needless_match.stderr @@ -1,5 +1,5 @@ error: this match expression is unnecessary - --> $DIR/needless_match.rs:17:18 + --> $DIR/needless_match.rs:16:18 | LL | let _: i32 = match i { | __________________^ @@ -13,29 +13,7 @@ LL | | }; = note: `-D clippy::needless-match` implied by `-D warnings` error: this match expression is unnecessary - --> $DIR/needless_match.rs:23:18 - | -LL | let _: i32 = match i { - | __________________^ -LL | | 0 => 0, -LL | | 1 => 1, -LL | | ref i => *i, -LL | | }; - | |_____^ help: replace it with: `i` - -error: this match expression is unnecessary - --> $DIR/needless_match.rs:28:22 - | -LL | let mut _i_mut = match i { - | ______________________^ -LL | | 0 => 0, -LL | | 1 => 1, -LL | | ref mut i => *i, -LL | | }; - | |_____^ help: replace it with: `i` - -error: this match expression is unnecessary - --> $DIR/needless_match.rs:35:19 + --> $DIR/needless_match.rs:23:19 | LL | let _: &str = match s { | ___________________^ @@ -46,19 +24,19 @@ LL | | }; | |_____^ help: replace it with: `s` error: this match expression is unnecessary - --> $DIR/needless_match.rs:43:21 + --> $DIR/needless_match.rs:32:21 | -LL | let _: Choice = match se { +LL | let _: Simple = match se { | _____________________^ -LL | | Choice::A => Choice::A, -LL | | Choice::B => Choice::B, -LL | | Choice::C => Choice::C, -LL | | Choice::D => Choice::D, +LL | | Simple::A => Simple::A, +LL | | Simple::B => Simple::B, +LL | | Simple::C => Simple::C, +LL | | Simple::D => Simple::D, LL | | }; | |_____^ help: replace it with: `se` error: this match expression is unnecessary - --> $DIR/needless_match.rs:65:26 + --> $DIR/needless_match.rs:54:26 | LL | let _: Option<i32> = match x { | __________________________^ @@ -68,7 +46,7 @@ LL | | }; | |_____^ help: replace it with: `x` error: this match expression is unnecessary - --> $DIR/needless_match.rs:81:31 + --> $DIR/needless_match.rs:70:31 | LL | let _: Result<i32, i32> = match Ok(1) { | _______________________________^ @@ -78,7 +56,7 @@ LL | | }; | |_____^ help: replace it with: `Ok(1)` error: this match expression is unnecessary - --> $DIR/needless_match.rs:85:31 + --> $DIR/needless_match.rs:74:31 | LL | let _: Result<i32, i32> = match func_ret_err(0_i32) { | _______________________________^ @@ -88,35 +66,48 @@ LL | | }; | |_____^ help: replace it with: `func_ret_err(0_i32)` error: this if-let expression is unnecessary - --> $DIR/needless_match.rs:92:5 + --> $DIR/needless_match.rs:87:13 | -LL | if let Some(a) = Some(1) { Some(a) } else { None } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `Some(1)` +LL | let _ = if let Some(a) = Some(1) { Some(a) } else { None }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `Some(1)` error: this if-let expression is unnecessary - --> $DIR/needless_match.rs:96:30 + --> $DIR/needless_match.rs:110:31 | -LL | let _: Result<(), i32> = if let Err(e) = x { Err(e) } else { x }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x` +LL | let _: Result<i32, i32> = if let Err(e) = x { Err(e) } else { x }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x` error: this if-let expression is unnecessary - --> $DIR/needless_match.rs:97:30 + --> $DIR/needless_match.rs:111:31 | -LL | let _: Result<(), i32> = if let Ok(val) = x { Ok(val) } else { x }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x` +LL | let _: Result<i32, i32> = if let Ok(val) = x { Ok(val) } else { x }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x` error: this if-let expression is unnecessary - --> $DIR/needless_match.rs:103:21 + --> $DIR/needless_match.rs:117:21 | -LL | let _: Choice = if let Choice::A = x { +LL | let _: Simple = if let Simple::A = x { | _____________________^ -LL | | Choice::A -LL | | } else if let Choice::B = x { -LL | | Choice::B +LL | | Simple::A +LL | | } else if let Simple::B = x { +LL | | Simple::B ... | LL | | x LL | | }; | |_____^ help: replace it with: `x` -error: aborting due to 12 previous errors +error: this match expression is unnecessary + --> $DIR/needless_match.rs:156:26 + | +LL | let _: Complex = match ce { + | __________________________^ +LL | | Complex::A(a) => Complex::A(a), +LL | | Complex::B(a, b) => Complex::B(a, b), +LL | | Complex::C(a, b, c) => Complex::C(a, b, c), +LL | | Complex::D(E::VariantA(ea, eb), b) => Complex::D(E::VariantA(ea, eb), b), +LL | | Complex::D(E::VariantB(ea, eb), b) => Complex::D(E::VariantB(ea, eb), b), +LL | | }; + | |_________^ help: replace it with: `ce` + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed index d721452ae88..c09b07db3dc 100644 --- a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed +++ b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed @@ -1,13 +1,41 @@ // run-rustfix -#[warn(clippy::needless_option_as_deref)] +#![allow(unused)] +#![warn(clippy::needless_option_as_deref)] fn main() { // should lint let _: Option<&usize> = Some(&1); let _: Option<&mut usize> = Some(&mut 1); + let mut y = 0; + let mut x = Some(&mut y); + let _ = x; + // should not lint let _ = Some(Box::new(1)).as_deref(); let _ = Some(Box::new(1)).as_deref_mut(); + + // #7846 + let mut i = 0; + let mut opt_vec = vec![Some(&mut i)]; + opt_vec[0].as_deref_mut().unwrap(); + + let mut i = 0; + let x = &mut Some(&mut i); + (*x).as_deref_mut(); + + // #8047 + let mut y = 0; + let mut x = Some(&mut y); + x.as_deref_mut(); + dbg!(x); +} + +struct S<'a> { + opt: Option<&'a mut usize>, +} + +fn from_field<'a>(s: &'a mut S<'a>) -> Option<&'a mut usize> { + s.opt.as_deref_mut() } diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.rs b/src/tools/clippy/tests/ui/needless_option_as_deref.rs index bb15512adf6..c3ba27ecccf 100644 --- a/src/tools/clippy/tests/ui/needless_option_as_deref.rs +++ b/src/tools/clippy/tests/ui/needless_option_as_deref.rs @@ -1,13 +1,41 @@ // run-rustfix -#[warn(clippy::needless_option_as_deref)] +#![allow(unused)] +#![warn(clippy::needless_option_as_deref)] fn main() { // should lint let _: Option<&usize> = Some(&1).as_deref(); let _: Option<&mut usize> = Some(&mut 1).as_deref_mut(); + let mut y = 0; + let mut x = Some(&mut y); + let _ = x.as_deref_mut(); + // should not lint let _ = Some(Box::new(1)).as_deref(); let _ = Some(Box::new(1)).as_deref_mut(); + + // #7846 + let mut i = 0; + let mut opt_vec = vec![Some(&mut i)]; + opt_vec[0].as_deref_mut().unwrap(); + + let mut i = 0; + let x = &mut Some(&mut i); + (*x).as_deref_mut(); + + // #8047 + let mut y = 0; + let mut x = Some(&mut y); + x.as_deref_mut(); + dbg!(x); +} + +struct S<'a> { + opt: Option<&'a mut usize>, +} + +fn from_field<'a>(s: &'a mut S<'a>) -> Option<&'a mut usize> { + s.opt.as_deref_mut() } diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.stderr b/src/tools/clippy/tests/ui/needless_option_as_deref.stderr index 5dd507b4a71..bc07db5b38e 100644 --- a/src/tools/clippy/tests/ui/needless_option_as_deref.stderr +++ b/src/tools/clippy/tests/ui/needless_option_as_deref.stderr @@ -1,5 +1,5 @@ error: derefed type is same as origin - --> $DIR/needless_option_as_deref.rs:7:29 + --> $DIR/needless_option_as_deref.rs:8:29 | LL | let _: Option<&usize> = Some(&1).as_deref(); | ^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&1)` @@ -7,10 +7,16 @@ LL | let _: Option<&usize> = Some(&1).as_deref(); = note: `-D clippy::needless-option-as-deref` implied by `-D warnings` error: derefed type is same as origin - --> $DIR/needless_option_as_deref.rs:8:33 + --> $DIR/needless_option_as_deref.rs:9:33 | LL | let _: Option<&mut usize> = Some(&mut 1).as_deref_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&mut 1)` -error: aborting due to 2 previous errors +error: derefed type is same as origin + --> $DIR/needless_option_as_deref.rs:13:13 + | +LL | let _ = x.as_deref_mut(); + | ^^^^^^^^^^^^^^^^ help: try this: `x` + +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs index 5427c88faf3..7ece66a1ccb 100644 --- a/src/tools/clippy/tests/ui/no_effect.rs +++ b/src/tools/clippy/tests/ui/no_effect.rs @@ -78,7 +78,7 @@ impl FnOnce<(&str,)> for GreetStruct2 { } } -struct GreetStruct3 {} +struct GreetStruct3; impl FnOnce<(&str,)> for GreetStruct3 { type Output = (); diff --git a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed index 7d29445e66c..1290bd8efeb 100644 --- a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed +++ b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed @@ -80,6 +80,9 @@ fn option_map_unit_fn() { if let Some(ref value) = x.field { do_nothing(value + captured) } - if let Some(a) = option() { do_nothing(a) }} + if let Some(a) = option() { do_nothing(a) } + + if let Some(value) = option() { println!("{:?}", value) } +} fn main() {} diff --git a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs index b6f834f686f..f3e5b62c65b 100644 --- a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs +++ b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs @@ -80,6 +80,9 @@ fn option_map_unit_fn() { x.field.map(|ref value| { do_nothing(value + captured) }); - option().map(do_nothing);} + option().map(do_nothing); + + option().map(|value| println!("{:?}", value)); +} fn main() {} diff --git a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr index 8abdbcafb6e..ab2a294a060 100644 --- a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr +++ b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr @@ -139,10 +139,18 @@ LL | x.field.map(|ref value| { do_nothing(value + captured) }); error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()` --> $DIR/option_map_unit_fn_fixable.rs:83:5 | -LL | option().map(do_nothing);} +LL | option().map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(a) = option() { do_nothing(a) }` -error: aborting due to 18 previous errors +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` + --> $DIR/option_map_unit_fn_fixable.rs:85:5 + | +LL | option().map(|value| println!("{:?}", value)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(value) = option() { println!("{:?}", value) }` + +error: aborting due to 19 previous errors diff --git a/src/tools/clippy/tests/ui/or_then_unwrap.fixed b/src/tools/clippy/tests/ui/or_then_unwrap.fixed index 27d4b795a5e..6e0d5a87f68 100644 --- a/src/tools/clippy/tests/ui/or_then_unwrap.fixed +++ b/src/tools/clippy/tests/ui/or_then_unwrap.fixed @@ -3,7 +3,7 @@ #![warn(clippy::or_then_unwrap)] #![allow(clippy::map_identity)] -struct SomeStruct {} +struct SomeStruct; impl SomeStruct { fn or(self, _: Option<Self>) -> Self { self @@ -11,7 +11,7 @@ impl SomeStruct { fn unwrap(&self) {} } -struct SomeOtherStruct {} +struct SomeOtherStruct; impl SomeOtherStruct { fn or(self) -> Self { self diff --git a/src/tools/clippy/tests/ui/or_then_unwrap.rs b/src/tools/clippy/tests/ui/or_then_unwrap.rs index 0dab5ae2f1c..e406a71d46d 100644 --- a/src/tools/clippy/tests/ui/or_then_unwrap.rs +++ b/src/tools/clippy/tests/ui/or_then_unwrap.rs @@ -3,7 +3,7 @@ #![warn(clippy::or_then_unwrap)] #![allow(clippy::map_identity)] -struct SomeStruct {} +struct SomeStruct; impl SomeStruct { fn or(self, _: Option<Self>) -> Self { self @@ -11,7 +11,7 @@ impl SomeStruct { fn unwrap(&self) {} } -struct SomeOtherStruct {} +struct SomeOtherStruct; impl SomeOtherStruct { fn or(self) -> Self { self diff --git a/src/tools/clippy/tests/ui/panicking_macros.rs b/src/tools/clippy/tests/ui/panicking_macros.rs index 73380646462..12a0c776ae2 100644 --- a/src/tools/clippy/tests/ui/panicking_macros.rs +++ b/src/tools/clippy/tests/ui/panicking_macros.rs @@ -1,8 +1,23 @@ -#![warn(clippy::unimplemented, clippy::unreachable, clippy::todo, clippy::panic)] #![allow(clippy::assertions_on_constants, clippy::eq_op)] +#![feature(inline_const)] +#![warn(clippy::unimplemented, clippy::unreachable, clippy::todo, clippy::panic)] extern crate core; +const _: () = { + if 1 == 0 { + panic!("A balanced diet means a cupcake in each hand"); + } +}; + +fn inline_const() { + let _ = const { + if 1 == 0 { + panic!("When nothing goes right, go left") + } + }; +} + fn panic() { let a = 2; panic!(); diff --git a/src/tools/clippy/tests/ui/panicking_macros.stderr b/src/tools/clippy/tests/ui/panicking_macros.stderr index bfd1c7a3801..4ceb6d1440f 100644 --- a/src/tools/clippy/tests/ui/panicking_macros.stderr +++ b/src/tools/clippy/tests/ui/panicking_macros.stderr @@ -1,5 +1,5 @@ error: `panic` should not be present in production code - --> $DIR/panicking_macros.rs:8:5 + --> $DIR/panicking_macros.rs:23:5 | LL | panic!(); | ^^^^^^^^ @@ -7,19 +7,19 @@ LL | panic!(); = note: `-D clippy::panic` implied by `-D warnings` error: `panic` should not be present in production code - --> $DIR/panicking_macros.rs:9:5 + --> $DIR/panicking_macros.rs:24:5 | LL | panic!("message"); | ^^^^^^^^^^^^^^^^^ error: `panic` should not be present in production code - --> $DIR/panicking_macros.rs:10:5 + --> $DIR/panicking_macros.rs:25:5 | LL | panic!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `todo` should not be present in production code - --> $DIR/panicking_macros.rs:16:5 + --> $DIR/panicking_macros.rs:31:5 | LL | todo!(); | ^^^^^^^ @@ -27,19 +27,19 @@ LL | todo!(); = note: `-D clippy::todo` implied by `-D warnings` error: `todo` should not be present in production code - --> $DIR/panicking_macros.rs:17:5 + --> $DIR/panicking_macros.rs:32:5 | LL | todo!("message"); | ^^^^^^^^^^^^^^^^ error: `todo` should not be present in production code - --> $DIR/panicking_macros.rs:18:5 + --> $DIR/panicking_macros.rs:33:5 | LL | todo!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panicking_macros.rs:24:5 + --> $DIR/panicking_macros.rs:39:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^ @@ -47,19 +47,19 @@ LL | unimplemented!(); = note: `-D clippy::unimplemented` implied by `-D warnings` error: `unimplemented` should not be present in production code - --> $DIR/panicking_macros.rs:25:5 + --> $DIR/panicking_macros.rs:40:5 | LL | unimplemented!("message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panicking_macros.rs:26:5 + --> $DIR/panicking_macros.rs:41:5 | LL | unimplemented!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> $DIR/panicking_macros.rs:32:5 + --> $DIR/panicking_macros.rs:47:5 | LL | unreachable!(); | ^^^^^^^^^^^^^^ @@ -67,37 +67,37 @@ LL | unreachable!(); = note: `-D clippy::unreachable` implied by `-D warnings` error: usage of the `unreachable!` macro - --> $DIR/panicking_macros.rs:33:5 + --> $DIR/panicking_macros.rs:48:5 | LL | unreachable!("message"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> $DIR/panicking_macros.rs:34:5 + --> $DIR/panicking_macros.rs:49:5 | LL | unreachable!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `panic` should not be present in production code - --> $DIR/panicking_macros.rs:40:5 + --> $DIR/panicking_macros.rs:55:5 | LL | panic!(); | ^^^^^^^^ error: `todo` should not be present in production code - --> $DIR/panicking_macros.rs:41:5 + --> $DIR/panicking_macros.rs:56:5 | LL | todo!(); | ^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panicking_macros.rs:42:5 + --> $DIR/panicking_macros.rs:57:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> $DIR/panicking_macros.rs:43:5 + --> $DIR/panicking_macros.rs:58:5 | LL | unreachable!(); | ^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs index 03dd938a233..814bbc7af71 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.rs +++ b/src/tools/clippy/tests/ui/ptr_arg.rs @@ -112,7 +112,7 @@ mod issue_5644 { ) { } - struct S {} + struct S; impl S { fn allowed( #[allow(clippy::ptr_arg)] _v: &Vec<u32>, diff --git a/src/tools/clippy/tests/ui/recursive_format_impl.rs b/src/tools/clippy/tests/ui/recursive_format_impl.rs index 9241bf7ed74..f72fc77ab99 100644 --- a/src/tools/clippy/tests/ui/recursive_format_impl.rs +++ b/src/tools/clippy/tests/ui/recursive_format_impl.rs @@ -66,7 +66,7 @@ impl std::fmt::Display for D { // Check for use of self as Display, in Display impl // Triggers on direct use of self -struct G {} +struct G; impl std::fmt::Display for G { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -75,7 +75,7 @@ impl std::fmt::Display for G { } // Triggers on reference to self -struct H {} +struct H; impl std::fmt::Display for H { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -90,7 +90,7 @@ impl std::fmt::Debug for H { } // Triggers on multiple reference to self -struct H2 {} +struct H2; impl std::fmt::Display for H2 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -99,7 +99,7 @@ impl std::fmt::Display for H2 { } // Doesn't trigger on correct deref -struct I {} +struct I; impl std::ops::Deref for I { type Target = str; @@ -122,7 +122,7 @@ impl std::fmt::Debug for I { } // Doesn't trigger on multiple correct deref -struct I2 {} +struct I2; impl std::ops::Deref for I2 { type Target = str; @@ -139,7 +139,7 @@ impl std::fmt::Display for I2 { } // Doesn't trigger on multiple correct deref -struct I3 {} +struct I3; impl std::ops::Deref for I3 { type Target = str; @@ -156,7 +156,7 @@ impl std::fmt::Display for I3 { } // Does trigger when deref resolves to self -struct J {} +struct J; impl std::ops::Deref for J { type Target = str; @@ -178,7 +178,7 @@ impl std::fmt::Debug for J { } } -struct J2 {} +struct J2; impl std::ops::Deref for J2 { type Target = str; @@ -194,7 +194,7 @@ impl std::fmt::Display for J2 { } } -struct J3 {} +struct J3; impl std::ops::Deref for J3 { type Target = str; @@ -210,7 +210,7 @@ impl std::fmt::Display for J3 { } } -struct J4 {} +struct J4; impl std::ops::Deref for J4 { type Target = str; @@ -227,7 +227,7 @@ impl std::fmt::Display for J4 { } // Doesn't trigger on Debug from Display -struct K {} +struct K; impl std::fmt::Debug for K { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -242,7 +242,7 @@ impl std::fmt::Display for K { } // Doesn't trigger on Display from Debug -struct K2 {} +struct K2; impl std::fmt::Debug for K2 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { diff --git a/src/tools/clippy/tests/ui/redundant_allocation.rs b/src/tools/clippy/tests/ui/redundant_allocation.rs index 52fbc91e325..80f94e5f3cb 100644 --- a/src/tools/clippy/tests/ui/redundant_allocation.rs +++ b/src/tools/clippy/tests/ui/redundant_allocation.rs @@ -3,7 +3,7 @@ #![allow(clippy::blacklisted_name, unused_variables, dead_code)] #![allow(unused_imports)] -pub struct MyStruct {} +pub struct MyStruct; pub struct SubT<T> { foo: T, diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed b/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed index ef089b25f47..e7ed84731c0 100644 --- a/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed +++ b/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed @@ -4,7 +4,7 @@ #![allow(clippy::blacklisted_name, unused_variables, dead_code)] #![allow(unused_imports)] -pub struct MyStruct {} +pub struct MyStruct; pub struct SubT<T> { foo: T, diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs b/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs index fefa87721d7..de763f98b5c 100644 --- a/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs +++ b/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs @@ -4,7 +4,7 @@ #![allow(clippy::blacklisted_name, unused_variables, dead_code)] #![allow(unused_imports)] -pub struct MyStruct {} +pub struct MyStruct; pub struct SubT<T> { foo: T, diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed index 16b40dcd902..1525f6a93df 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.fixed +++ b/src/tools/clippy/tests/ui/redundant_clone.fixed @@ -1,7 +1,7 @@ // run-rustfix // rustfix-only-machine-applicable -#![allow(clippy::implicit_clone)] +#![allow(clippy::implicit_clone, clippy::drop_non_drop)] use std::ffi::OsString; use std::path::Path; diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs index bd3d7365229..2f82aefd928 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.rs +++ b/src/tools/clippy/tests/ui/redundant_clone.rs @@ -1,7 +1,7 @@ // run-rustfix // rustfix-only-machine-applicable -#![allow(clippy::implicit_clone)] +#![allow(clippy::implicit_clone, clippy::drop_non_drop)] use std::ffi::OsString; use std::path::Path; diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed index 921249606ad..acc8f1e25b6 100644 --- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed +++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed @@ -3,7 +3,7 @@ #![allow(unused)] #[derive(Debug)] -struct Foo {} +struct Foo; const VAR_ONE: &str = "Test constant #1"; // ERROR Consider removing 'static. diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs index 4d4b249d076..f2f0f78659c 100644 --- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs +++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs @@ -3,7 +3,7 @@ #![allow(unused)] #[derive(Debug)] -struct Foo {} +struct Foo; const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed index 631042c616b..14c331f67e7 100644 --- a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed +++ b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed @@ -75,6 +75,8 @@ fn result_map_unit_fn() { if let Ok(ref value) = x.field { do_nothing(value + captured) } + + if let Ok(value) = x.field { println!("{:?}", value) } } fn main() {} diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs index 679eb232626..8b0fca9ece1 100644 --- a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs +++ b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs @@ -75,6 +75,8 @@ fn result_map_unit_fn() { x.field.map(|ref value| { do_nothing(value + captured) }); + + x.field.map(|value| println!("{:?}", value)); } fn main() {} diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.stderr b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.stderr index 4f3a8c6b792..782febd5264 100644 --- a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.stderr +++ b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.stderr @@ -136,5 +136,13 @@ LL | x.field.map(|ref value| { do_nothing(value + captured) }); | | | help: try this: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` -error: aborting due to 17 previous errors +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` + --> $DIR/result_map_unit_fn_fixable.rs:79:5 + | +LL | x.field.map(|value| println!("{:?}", value)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { println!("{:?}", value) }` + +error: aborting due to 18 previous errors diff --git a/src/tools/clippy/tests/ui/same_item_push.rs b/src/tools/clippy/tests/ui/same_item_push.rs index 9d420ec672a..99964f0de07 100644 --- a/src/tools/clippy/tests/ui/same_item_push.rs +++ b/src/tools/clippy/tests/ui/same_item_push.rs @@ -120,7 +120,7 @@ fn main() { } // Fix #5979 #[derive(Clone)] - struct S {} + struct S; trait T {} impl T for S {} diff --git a/src/tools/clippy/tests/ui/single_element_loop.fixed b/src/tools/clippy/tests/ui/single_element_loop.fixed index c307afffcb8..63d31ff83f9 100644 --- a/src/tools/clippy/tests/ui/single_element_loop.fixed +++ b/src/tools/clippy/tests/ui/single_element_loop.fixed @@ -6,11 +6,31 @@ fn main() { let item1 = 2; { let item = &item1; - println!("{}", item); + dbg!(item); } { let item = &item1; - println!("{:?}", item); + dbg!(item); + } + + { + let item = &(0..5); + dbg!(item); + } + + { + let item = &mut (0..5); + dbg!(item); + } + + { + let item = 0..5; + dbg!(item); + } + + { + let item = 0..5; + dbg!(item); } } diff --git a/src/tools/clippy/tests/ui/single_element_loop.rs b/src/tools/clippy/tests/ui/single_element_loop.rs index 2c0c03b7211..2cda5a329d2 100644 --- a/src/tools/clippy/tests/ui/single_element_loop.rs +++ b/src/tools/clippy/tests/ui/single_element_loop.rs @@ -5,10 +5,26 @@ fn main() { let item1 = 2; for item in &[item1] { - println!("{}", item); + dbg!(item); } for item in [item1].iter() { - println!("{:?}", item); + dbg!(item); + } + + for item in &[0..5] { + dbg!(item); + } + + for item in [0..5].iter_mut() { + dbg!(item); + } + + for item in [0..5] { + dbg!(item); + } + + for item in [0..5].into_iter() { + dbg!(item); } } diff --git a/src/tools/clippy/tests/ui/single_element_loop.stderr b/src/tools/clippy/tests/ui/single_element_loop.stderr index f52ca8c5a9b..0aeb8da1a2e 100644 --- a/src/tools/clippy/tests/ui/single_element_loop.stderr +++ b/src/tools/clippy/tests/ui/single_element_loop.stderr @@ -2,7 +2,7 @@ error: for loop over a single element --> $DIR/single_element_loop.rs:7:5 | LL | / for item in &[item1] { -LL | | println!("{}", item); +LL | | dbg!(item); LL | | } | |_____^ | @@ -11,7 +11,7 @@ help: try | LL ~ { LL + let item = &item1; -LL + println!("{}", item); +LL + dbg!(item); LL + } | @@ -19,7 +19,7 @@ error: for loop over a single element --> $DIR/single_element_loop.rs:11:5 | LL | / for item in [item1].iter() { -LL | | println!("{:?}", item); +LL | | dbg!(item); LL | | } | |_____^ | @@ -27,9 +27,73 @@ help: try | LL ~ { LL + let item = &item1; -LL + println!("{:?}", item); +LL + dbg!(item); LL + } | -error: aborting due to 2 previous errors +error: for loop over a single element + --> $DIR/single_element_loop.rs:15:5 + | +LL | / for item in &[0..5] { +LL | | dbg!(item); +LL | | } + | |_____^ + | +help: try + | +LL ~ { +LL + let item = &(0..5); +LL + dbg!(item); +LL + } + | + +error: for loop over a single element + --> $DIR/single_element_loop.rs:19:5 + | +LL | / for item in [0..5].iter_mut() { +LL | | dbg!(item); +LL | | } + | |_____^ + | +help: try + | +LL ~ { +LL + let item = &mut (0..5); +LL + dbg!(item); +LL + } + | + +error: for loop over a single element + --> $DIR/single_element_loop.rs:23:5 + | +LL | / for item in [0..5] { +LL | | dbg!(item); +LL | | } + | |_____^ + | +help: try + | +LL ~ { +LL + let item = 0..5; +LL + dbg!(item); +LL + } + | + +error: for loop over a single element + --> $DIR/single_element_loop.rs:27:5 + | +LL | / for item in [0..5].into_iter() { +LL | | dbg!(item); +LL | | } + | |_____^ + | +help: try + | +LL ~ { +LL + let item = 0..5; +LL + dbg!(item); +LL + } + | + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs index 21de19a2601..f5ca91143af 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs @@ -62,7 +62,7 @@ trait BadTrait: Default + Clone { } #[derive(Default, Clone)] -struct Life {} +struct Life; impl T for Life { // this should not warn @@ -85,7 +85,7 @@ trait Iter: Iterator { } } -struct Foo {} +struct Foo; trait FooIter: Iterator<Item = Foo> { fn bar() diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs index 9b681a79aae..5b688ce4d64 100644 --- a/src/tools/clippy/tests/ui/transmute.rs +++ b/src/tools/clippy/tests/ui/transmute.rs @@ -73,6 +73,10 @@ fn crosspointer() { fn int_to_char() { let _: char = unsafe { std::mem::transmute(0_u32) }; let _: char = unsafe { std::mem::transmute(0_i32) }; + + // These shouldn't warn + const _: char = unsafe { std::mem::transmute(0_u32) }; + const _: char = unsafe { std::mem::transmute(0_i32) }; } #[warn(clippy::transmute_int_to_bool)] @@ -130,9 +134,12 @@ mod num_to_bytes { } } -fn bytes_to_str(b: &[u8], mb: &mut [u8]) { - let _: &str = unsafe { std::mem::transmute(b) }; +fn bytes_to_str(mb: &mut [u8]) { + const B: &[u8] = b""; + + let _: &str = unsafe { std::mem::transmute(B) }; let _: &mut str = unsafe { std::mem::transmute(mb) }; + const _: &str = unsafe { std::mem::transmute(B) }; } fn main() {} diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr index 86537153e32..72a386e8fa6 100644 --- a/src/tools/clippy/tests/ui/transmute.stderr +++ b/src/tools/clippy/tests/ui/transmute.stderr @@ -107,7 +107,7 @@ LL | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:80:28 + --> $DIR/transmute.rs:84:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -115,7 +115,7 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:86:31 + --> $DIR/transmute.rs:90:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` @@ -123,25 +123,25 @@ LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:87:31 + --> $DIR/transmute.rs:91:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `u64` to a `f64` - --> $DIR/transmute.rs:88:31 + --> $DIR/transmute.rs:92:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)` error: transmute from a `i64` to a `f64` - --> $DIR/transmute.rs:89:31 + --> $DIR/transmute.rs:93:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` error: transmute from a `u8` to a `[u8; 1]` - --> $DIR/transmute.rs:109:30 + --> $DIR/transmute.rs:113:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` @@ -149,96 +149,102 @@ LL | let _: [u8; 1] = std::mem::transmute(0u8); = note: `-D clippy::transmute-num-to-bytes` implied by `-D warnings` error: transmute from a `u32` to a `[u8; 4]` - --> $DIR/transmute.rs:110:30 + --> $DIR/transmute.rs:114:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> $DIR/transmute.rs:111:31 + --> $DIR/transmute.rs:115:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> $DIR/transmute.rs:112:30 + --> $DIR/transmute.rs:116:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> $DIR/transmute.rs:113:30 + --> $DIR/transmute.rs:117:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> $DIR/transmute.rs:114:31 + --> $DIR/transmute.rs:118:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `f32` to a `[u8; 4]` - --> $DIR/transmute.rs:115:30 + --> $DIR/transmute.rs:119:30 | LL | let _: [u8; 4] = std::mem::transmute(0.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` error: transmute from a `f64` to a `[u8; 8]` - --> $DIR/transmute.rs:116:30 + --> $DIR/transmute.rs:120:30 | LL | let _: [u8; 8] = std::mem::transmute(0.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` error: transmute from a `u8` to a `[u8; 1]` - --> $DIR/transmute.rs:121:30 + --> $DIR/transmute.rs:125:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` error: transmute from a `u32` to a `[u8; 4]` - --> $DIR/transmute.rs:122:30 + --> $DIR/transmute.rs:126:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> $DIR/transmute.rs:123:31 + --> $DIR/transmute.rs:127:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> $DIR/transmute.rs:124:30 + --> $DIR/transmute.rs:128:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> $DIR/transmute.rs:125:30 + --> $DIR/transmute.rs:129:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> $DIR/transmute.rs:126:31 + --> $DIR/transmute.rs:130:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:134:28 + --> $DIR/transmute.rs:140:28 | -LL | let _: &str = unsafe { std::mem::transmute(b) }; - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` +LL | let _: &str = unsafe { std::mem::transmute(B) }; + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()` | = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:135:32 + --> $DIR/transmute.rs:141:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` -error: aborting due to 38 previous errors +error: transmute from a `&[u8]` to a `&str` + --> $DIR/transmute.rs:142:30 + | +LL | const _: &str = unsafe { std::mem::transmute(B) }; + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)` + +error: aborting due to 39 previous errors diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs index 380303d8152..afa337c45f4 100644 --- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs @@ -1,5 +1,9 @@ +// aux-build:proc_macro_unsafe.rs + #![warn(clippy::undocumented_unsafe_blocks)] +extern crate proc_macro_unsafe; + // Valid comments fn nested_local() { @@ -89,11 +93,6 @@ fn block_comment_newlines() { unsafe {} } -#[rustfmt::skip] -fn inline_block_comment() { - /* Safety: */unsafe {} -} - fn block_comment_with_extras() { /* This is a description * SAFETY: @@ -209,8 +208,54 @@ fn local_nest() { let _ = [(42, unsafe {}, unsafe {}), (52, unsafe {}, unsafe {})]; } +fn in_fn_call(x: *const u32) { + fn f(x: u32) {} + + // Safety: reason + f(unsafe { *x }); +} + +fn multi_in_fn_call(x: *const u32) { + fn f(x: u32, y: u32) {} + + // Safety: reason + f(unsafe { *x }, unsafe { *x }); +} + +fn in_multiline_fn_call(x: *const u32) { + fn f(x: u32, y: u32) {} + + f( + // Safety: reason + unsafe { *x }, + 0, + ); +} + +fn in_macro_call(x: *const u32) { + // Safety: reason + println!("{}", unsafe { *x }); +} + +fn in_multiline_macro_call(x: *const u32) { + println!( + "{}", + // Safety: reason + unsafe { *x }, + ); +} + +fn from_proc_macro() { + proc_macro_unsafe::unsafe_block!(token); +} + // Invalid comments +#[rustfmt::skip] +fn inline_block_comment() { + /* Safety: */ unsafe {} +} + fn no_comment() { unsafe {} } diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr index f69d0da54e0..856a07fd316 100644 --- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr +++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr @@ -1,114 +1,110 @@ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:215:5 + --> $DIR/undocumented_unsafe_blocks.rs:256:19 + | +LL | /* Safety: */ unsafe {} + | ^^^^^^^^^ + | + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:260:5 | LL | unsafe {} | ^^^^^^^^^ | - = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` -help: consider adding a safety comment + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:264:14 | -LL ~ // SAFETY: ... -LL + unsafe {} +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^ | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:219:5 + --> $DIR/undocumented_unsafe_blocks.rs:264:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | -help: consider adding a safety comment + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:264:48 | -LL ~ // SAFETY: ... -LL + let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^ | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:223:5 + --> $DIR/undocumented_unsafe_blocks.rs:268:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | -help: consider adding a safety comment + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:268:37 | -LL ~ // SAFETY: ... -LL + let _ = (42, unsafe {}, "test", unsafe {}); +LL | let _ = (42, unsafe {}, "test", unsafe {}); + | ^^^^^^^^^ | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:227:5 + --> $DIR/undocumented_unsafe_blocks.rs:272:14 | LL | let _ = *unsafe { &42 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL + let _ = *unsafe { &42 }; + | ^^^^^^^^^^^^^^ | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:232:5 + --> $DIR/undocumented_unsafe_blocks.rs:277:19 | LL | let _ = match unsafe {} { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL + let _ = match unsafe {} { + | ^^^^^^^^^ | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:238:5 + --> $DIR/undocumented_unsafe_blocks.rs:283:14 | LL | let _ = &unsafe {}; - | ^^^^^^^^^^^^^^^^^^^ - | -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL + let _ = &unsafe {}; + | ^^^^^^^^^ | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:242:5 + --> $DIR/undocumented_unsafe_blocks.rs:287:14 | LL | let _ = [unsafe {}; 5]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL + let _ = [unsafe {}; 5]; + | ^^^^^^^^^ | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:246:5 + --> $DIR/undocumented_unsafe_blocks.rs:291:13 | LL | let _ = unsafe {}; - | ^^^^^^^^^^^^^^^^^^ - | -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL + let _ = unsafe {}; + | ^^^^^^^^^ | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:256:8 + --> $DIR/undocumented_unsafe_blocks.rs:301:8 | LL | t!(unsafe {}); | ^^^^^^^^^ | -help: consider adding a safety comment - | -LL ~ t!(// SAFETY: ... -LL ~ unsafe {}); - | + = help: consider adding a safety comment on the preceding line -error: unsafe block in macro expansion missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:262:13 +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:307:13 | LL | unsafe {} | ^^^^^^^^^ @@ -116,56 +112,40 @@ LL | unsafe {} LL | t!(); | ---- in this macro invocation | - = help: consider adding a safety comment in the macro definition + = help: consider adding a safety comment on the preceding line = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:270:5 + --> $DIR/undocumented_unsafe_blocks.rs:315:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ | -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL ~ unsafe {} // SAFETY: - | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:274:5 + --> $DIR/undocumented_unsafe_blocks.rs:319:5 | LL | unsafe { | ^^^^^^^^ | -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL + unsafe { - | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:284:5 + --> $DIR/undocumented_unsafe_blocks.rs:329:5 | LL | unsafe {}; | ^^^^^^^^^ | -help: consider adding a safety comment - | -LL ~ // SAFETY: ... -LL ~ unsafe {}; - | + = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:288:20 + --> $DIR/undocumented_unsafe_blocks.rs:333:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: consider adding a safety comment - | -LL ~ println!("{}", // SAFETY: ... -LL ~ unsafe { String::from_utf8_unchecked(vec![]) }); - | + = help: consider adding a safety comment on the preceding line -error: aborting due to 14 previous errors +error: aborting due to 18 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs index b77c19f2ba5..62c3e963686 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs @@ -30,4 +30,10 @@ fn main() { // do not lint cast to cfg-dependant type 1 as std::os::raw::c_char; + + // do not lint cast to alias type + 1 as I32Alias; + &1 as &I32Alias; } + +type I32Alias = i32; diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed index 3332f49c80c..36800c5340d 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed @@ -42,4 +42,9 @@ fn main() { let _ = -1_i32; let _ = -1.0_f32; + + let _ = 1 as I32Alias; + let _ = &1 as &I32Alias; } + +type I32Alias = i32; diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs index ec01e938779..d4b6bb952ab 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs @@ -42,4 +42,9 @@ fn main() { let _ = -1 as i32; let _ = -1.0 as f32; + + let _ = 1 as I32Alias; + let _ = &1 as &I32Alias; } + +type I32Alias = i32; diff --git a/src/tools/clippy/tests/ui/unsafe_derive_deserialize.rs b/src/tools/clippy/tests/ui/unsafe_derive_deserialize.rs index 690d705573d..bafca91917a 100644 --- a/src/tools/clippy/tests/ui/unsafe_derive_deserialize.rs +++ b/src/tools/clippy/tests/ui/unsafe_derive_deserialize.rs @@ -6,7 +6,7 @@ extern crate serde; use serde::Deserialize; #[derive(Deserialize)] -pub struct A {} +pub struct A; impl A { pub unsafe fn new(_a: i32, _b: i32) -> Self { Self {} @@ -14,13 +14,13 @@ impl A { } #[derive(Deserialize)] -pub struct B {} +pub struct B; impl B { pub unsafe fn unsafe_method(&self) {} } #[derive(Deserialize)] -pub struct C {} +pub struct C; impl C { pub fn unsafe_block(&self) { unsafe {} @@ -28,7 +28,7 @@ impl C { } #[derive(Deserialize)] -pub struct D {} +pub struct D; impl D { pub fn inner_unsafe_fn(&self) { unsafe fn inner() {} @@ -36,7 +36,7 @@ impl D { } // Does not derive `Deserialize`, should be ignored -pub struct E {} +pub struct E; impl E { pub unsafe fn new(_a: i32, _b: i32) -> Self { Self {} @@ -55,12 +55,12 @@ impl E { // Does not have methods using `unsafe`, should be ignored #[derive(Deserialize)] -pub struct F {} +pub struct F; // Check that we honor the `allow` attribute on the ADT #[allow(clippy::unsafe_derive_deserialize)] #[derive(Deserialize)] -pub struct G {} +pub struct G; impl G { pub fn unsafe_block(&self) { unsafe {} diff --git a/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs b/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs index a1f616733bd..cde4e96d668 100644 --- a/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs +++ b/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs @@ -14,8 +14,8 @@ use std::cell::UnsafeCell as Dangerunsafe; use std::cell::UnsafeCell as Bombsawayunsafe; mod mod_with_some_unsafe_things { - pub struct Safe {} - pub struct Unsafe {} + pub struct Safe; + pub struct Unsafe; } use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; diff --git a/src/tools/clippy/tests/ui/unused_self.rs b/src/tools/clippy/tests/ui/unused_self.rs index 7a4bbdda1ab..08bf58fec7c 100644 --- a/src/tools/clippy/tests/ui/unused_self.rs +++ b/src/tools/clippy/tests/ui/unused_self.rs @@ -5,7 +5,7 @@ mod unused_self { use std::pin::Pin; use std::sync::{Arc, Mutex}; - struct A {} + struct A; impl A { fn unused_self_move(self) {} @@ -27,7 +27,7 @@ mod unused_self { } mod unused_self_allow { - struct A {} + struct A; impl A { // shouldn't trigger @@ -35,7 +35,7 @@ mod unused_self_allow { fn unused_self_move(self) {} } - struct B {} + struct B; // shouldn't trigger #[allow(clippy::unused_self)] @@ -43,7 +43,7 @@ mod unused_self_allow { fn unused_self_move(self) {} } - struct C {} + struct C; #[allow(clippy::unused_self)] impl C { @@ -120,7 +120,7 @@ mod used_self { mod not_applicable { use std::fmt; - struct A {} + struct A; impl fmt::Debug for A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed index 9d216f56ae6..3e62ffe74fe 100644 --- a/src/tools/clippy/tests/ui/use_self.fixed +++ b/src/tools/clippy/tests/ui/use_self.fixed @@ -16,7 +16,7 @@ extern crate proc_macro_derive; fn main() {} mod use_self { - struct Foo {} + struct Foo; impl Foo { fn new() -> Self { @@ -35,7 +35,7 @@ mod use_self { } mod better { - struct Foo {} + struct Foo; impl Foo { fn new() -> Self { @@ -123,7 +123,7 @@ mod macros { }; } - struct Foo {} + struct Foo; impl Foo { use_self_expand!(); // Should not lint in local macros @@ -134,7 +134,7 @@ mod macros { } mod nesting { - struct Foo {} + struct Foo; impl Foo { fn foo() { #[allow(unused_imports)] @@ -209,7 +209,7 @@ mod issue3410 { #[allow(clippy::no_effect, path_statements)] mod rustfix { mod nested { - pub struct A {} + pub struct A; } impl nested::A { @@ -227,7 +227,7 @@ mod rustfix { } mod issue3567 { - struct TestStruct {} + struct TestStruct; impl TestStruct { fn from_something() -> Self { Self {} @@ -248,7 +248,7 @@ mod issue3567 { mod paths_created_by_lowering { use std::ops::Range; - struct S {} + struct S; impl S { const A: usize = 0; @@ -382,7 +382,7 @@ mod issue4305 { } mod lint_at_item_level { - struct Foo {} + struct Foo; #[allow(clippy::use_self)] impl Foo { @@ -400,7 +400,7 @@ mod lint_at_item_level { } mod lint_at_impl_item_level { - struct Foo {} + struct Foo; impl Foo { #[allow(clippy::use_self)] @@ -433,8 +433,8 @@ mod issue4734 { mod nested_paths { use std::convert::Into; mod submod { - pub struct B {} - pub struct C {} + pub struct B; + pub struct C; impl Into<C> for B { fn into(self) -> C { diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs index 5f604fe25e4..da2faddee12 100644 --- a/src/tools/clippy/tests/ui/use_self.rs +++ b/src/tools/clippy/tests/ui/use_self.rs @@ -16,7 +16,7 @@ extern crate proc_macro_derive; fn main() {} mod use_self { - struct Foo {} + struct Foo; impl Foo { fn new() -> Foo { @@ -35,7 +35,7 @@ mod use_self { } mod better { - struct Foo {} + struct Foo; impl Foo { fn new() -> Self { @@ -123,7 +123,7 @@ mod macros { }; } - struct Foo {} + struct Foo; impl Foo { use_self_expand!(); // Should not lint in local macros @@ -134,7 +134,7 @@ mod macros { } mod nesting { - struct Foo {} + struct Foo; impl Foo { fn foo() { #[allow(unused_imports)] @@ -209,7 +209,7 @@ mod issue3410 { #[allow(clippy::no_effect, path_statements)] mod rustfix { mod nested { - pub struct A {} + pub struct A; } impl nested::A { @@ -227,7 +227,7 @@ mod rustfix { } mod issue3567 { - struct TestStruct {} + struct TestStruct; impl TestStruct { fn from_something() -> Self { Self {} @@ -248,7 +248,7 @@ mod issue3567 { mod paths_created_by_lowering { use std::ops::Range; - struct S {} + struct S; impl S { const A: usize = 0; @@ -382,7 +382,7 @@ mod issue4305 { } mod lint_at_item_level { - struct Foo {} + struct Foo; #[allow(clippy::use_self)] impl Foo { @@ -400,7 +400,7 @@ mod lint_at_item_level { } mod lint_at_impl_item_level { - struct Foo {} + struct Foo; impl Foo { #[allow(clippy::use_self)] @@ -433,8 +433,8 @@ mod issue4734 { mod nested_paths { use std::convert::Into; mod submod { - pub struct B {} - pub struct C {} + pub struct B; + pub struct C; impl Into<C> for B { fn into(self) -> C { diff --git a/src/tools/clippy/tests/ui/useless_attribute.fixed b/src/tools/clippy/tests/ui/useless_attribute.fixed index a5fcde768f1..ce58a80347b 100644 --- a/src/tools/clippy/tests/ui/useless_attribute.fixed +++ b/src/tools/clippy/tests/ui/useless_attribute.fixed @@ -42,7 +42,7 @@ mod a { mod b { #[allow(dead_code)] #[allow(unreachable_pub)] - pub struct C {} + pub struct C; } #[allow(unreachable_pub)] diff --git a/src/tools/clippy/tests/ui/useless_attribute.rs b/src/tools/clippy/tests/ui/useless_attribute.rs index 0396d39e3d5..c82bb9ba07f 100644 --- a/src/tools/clippy/tests/ui/useless_attribute.rs +++ b/src/tools/clippy/tests/ui/useless_attribute.rs @@ -42,7 +42,7 @@ mod a { mod b { #[allow(dead_code)] #[allow(unreachable_pub)] - pub struct C {} + pub struct C; } #[allow(unreachable_pub)] diff --git a/src/tools/clippy/tests/versioncheck.rs b/src/tools/clippy/tests/versioncheck.rs index 77102b8cac0..38498ebdcf2 100644 --- a/src/tools/clippy/tests/versioncheck.rs +++ b/src/tools/clippy/tests/versioncheck.rs @@ -3,34 +3,32 @@ #![allow(clippy::single_match_else)] use rustc_tools_util::VersionInfo; +use std::fs; #[test] fn check_that_clippy_lints_and_clippy_utils_have_the_same_version_as_clippy() { + fn read_version(path: &str) -> String { + let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("error reading `{}`: {:?}", path, e)); + contents + .lines() + .filter_map(|l| l.split_once('=')) + .find_map(|(k, v)| (k.trim() == "version").then(|| v.trim())) + .unwrap_or_else(|| panic!("error finding version in `{}`", path)) + .to_string() + } + // do not run this test inside the upstream rustc repo: // https://github.com/rust-lang/rust-clippy/issues/6683 if option_env!("RUSTC_TEST_SUITE").is_some() { return; } - let clippy_meta = cargo_metadata::MetadataCommand::new() - .no_deps() - .exec() - .expect("could not obtain cargo metadata"); + let clippy_version = read_version("Cargo.toml"); + let clippy_lints_version = read_version("clippy_lints/Cargo.toml"); + let clippy_utils_version = read_version("clippy_utils/Cargo.toml"); - for krate in &["clippy_lints", "clippy_utils"] { - let krate_meta = cargo_metadata::MetadataCommand::new() - .current_dir(std::env::current_dir().unwrap().join(krate)) - .no_deps() - .exec() - .expect("could not obtain cargo metadata"); - assert_eq!(krate_meta.packages[0].version, clippy_meta.packages[0].version); - for package in &clippy_meta.packages[0].dependencies { - if package.name == *krate { - assert!(package.req.matches(&krate_meta.packages[0].version)); - break; - } - } - } + assert_eq!(clippy_version, clippy_lints_version); + assert_eq!(clippy_version, clippy_utils_version); } #[test] diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 1bdea33dffa..8a72b44e2b5 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -806,8 +806,7 @@ pub fn make_test_description<R: Read>( cfg: Option<&str>, ) -> test::TestDesc { let mut ignore = false; - #[cfg(not(bootstrap))] - let ignore_message: Option<String> = None; + let ignore_message = None; let mut should_fail = false; let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some(); @@ -879,7 +878,6 @@ pub fn make_test_description<R: Read>( test::TestDesc { name, ignore, - #[cfg(not(bootstrap))] ignore_message, should_panic, compile_fail: false, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 503b624114a..8c1f28f1407 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -744,12 +744,10 @@ fn make_test_name( testpaths: &TestPaths, revision: Option<&String>, ) -> test::TestName { - // Convert a complete path to something like - // - // ui/foo/bar/baz.rs - let path = PathBuf::from(config.src_base.file_name().unwrap()) - .join(&testpaths.relative_dir) - .join(&testpaths.file.file_name().unwrap()); + // Print the name of the file, relative to the repository root. + // `src_base` looks like `/path/to/rust/src/test/ui` + let root_directory = config.src_base.parent().unwrap().parent().unwrap().parent().unwrap(); + let path = testpaths.file.strip_prefix(root_directory).unwrap(); let debugger = match config.debugger { Some(d) => format!("-{}", d), None => String::new(), diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs index caae8c61178..70b00b36cf1 100644 --- a/src/tools/error_index_generator/build.rs +++ b/src/tools/error_index_generator/build.rs @@ -7,7 +7,6 @@ fn main() { // Note that we could skip one of the .. but this ensures we at least loosely find the right // directory. let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - let dest = out_dir.join("error_codes.rs"); let error_codes_path = "../../../compiler/rustc_error_codes/src/error_codes.rs"; @@ -29,35 +28,4 @@ fn main() { let md_content = fs::read_to_string(entry.path()).unwrap(); fs::write(&out_dir.join(entry.file_name()), &md_content).unwrap(); } - - let mut all = String::new(); - all.push_str( - r###" -fn register_all() -> Vec<(&'static str, Option<&'static str>)> { - let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new(); - macro_rules! register_diagnostics { - ($($ecode:ident: $message:expr,)*) => ( - register_diagnostics!{$($ecode:$message,)* ;} - ); - - ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( - $( - {long_codes.extend([ - (stringify!($ecode), Some($message)), - ].iter());} - )* - $( - {long_codes.extend([ - stringify!($code), - ].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());} - )* - ) - } -"###, - ); - all.push_str(r#"include!(concat!(env!("OUT_DIR"), "/all_error_codes.rs"));"#); - all.push_str("\nlong_codes\n"); - all.push_str("}\n"); - - fs::write(&dest, all).unwrap(); } diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 39498c99e64..51ed1b5a61c 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -277,4 +277,26 @@ fn main() { } } -include!(concat!(env!("OUT_DIR"), "/error_codes.rs")); +fn register_all() -> Vec<(&'static str, Option<&'static str>)> { + let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new(); + macro_rules! register_diagnostics { + ($($ecode:ident: $message:expr,)*) => ( + register_diagnostics!{$($ecode:$message,)* ;} + ); + + ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( + $( + {long_codes.extend([ + (stringify!($ecode), Some($message)), + ].iter());} + )* + $( + {long_codes.extend([ + stringify!($code), + ].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());} + )* + ) + } + include!(concat!(env!("OUT_DIR"), "/all_error_codes.rs")); + long_codes +} diff --git a/src/tools/miri b/src/tools/miri -Subproject 732461b4cd2c4bfd8b229ad43fbc32c193b4049 +Subproject be72564a643758afcc1de152ead2359d489149c |
